msb@sq.com (Mark Brader) (03/20/89)
[Sorry if you get this twice - transient local problem.] About a week ago I posted an article about "troff and eof" in which I explained how troff handles end-of-input, and why, and how to work around the default termination if you don't want it. I said, among other things, that if you wanted the effect of a 'bp in your end-macro with a guarantee against troff terminating on the page transition, then you should precede the 'bp with a line consisting only of a \c escape sequence. I did not, however, discuss what you should do if you want the effect of a .bp in your end-macro. You might think that since .bp is equivalent to .br followed by 'bp, that all you need to say is .br \c 'bp But in fact this only works some of the time. The problem is that the .br will often cause an output line to be produced. If that action causes your bottom-of-page trap to be sprung, then you've reached the end of the page before the \c happened, and your buffers are empty (because of the .br), and so troff shuts down. The following trick will sometimes avoid that problem. Replace the ZZ with the name of an available number register, of course. .pl +1 .mk ZZ .sp |\n(ZZu .pl -1 \c 'bp The assumption here is that the bottom-of-page trap has had its position set relative to the bottom of the page, e.g. ".wh -1i BT" rather than ".wh 10i BT" which would be relative to the top of the page. If this assumption is true (as it is in -ms, for instance) then the .pl +1 will drag the trap position down, along with the bottom of the page, and the .pl -1 will move them back up to where they were. If there are no other traps in the vicinity, the production of one line of output while the page length is extended therefore cannot possibly spring a trap. And therefore we now really could do .br in safety. However, we don't want to cause unnecessary baseline motion, and in particular, we want to restore the page length (.pl -1) before falling off the page. So instead of .br we do a .sp (which, remember, causes the equivalent of .br as a side-effect) that will return the baseline to where it was before it started. The .mk-.sp pair looks like a no-op at first glance, but it isn't; the trick is that the argument of .sp is evaluated only after any output line forced out by its break-causing effect has appeared. So in this case, if an output line is produced, the .sp is equivalent to a .sp -1. (If no output line is produced, it's equivalent to .sp 0, so the .mk-.sp combination really is a no-op then.) So the above sequence is a replacement for .bp in the end-macro, if (a) your macros set their traps in the way I described, and (b) your page transition macros do not switch environments. If your page transition macros switch environments, then the \c has to be used within them. This trap-avoiding trick is useful elsewhere than in end-macros. I will discuss in a separate message its use in connection with the "aligning with the right margin" problem discussed lately in this newsgroup. In our version of troff, sqtroff, you don't have to assume anything about the macro package. This is because we have added a request .vpt, which disables and re-enables traps set by .ch, .wh, or .dt. (vpt = Vertical Position Traps). So in sqtroff, the above code becomes: .vpt off .mk ZZ .sp |\n(ZZu .vpt on \c 'bp And this will work regardless of what traps are set. Mark Brader, SoftQuad Inc., Toronto, 416-963-8337, from US 800-387-2777 { uunet!attcan | linus | decvax | watmath | pyramid } !utzoo!sq!msb msb@sq.com decwrl!utcsri!sq!msb