.ig s.tmac Copyright (C) 1989-2021 Free Software Foundation, Inc. Written by James Clark (jjc@jclark.com) This file is part of groff. groff is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. groff is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . .. .if !\n(.g \ . ab groff ms macros require groff extensions; aborting . .if \n(.C \ . ab groff ms macros do not work in compatibility mode; aborting . .\" See if already loaded. .if r GS .nx .nr GS 1 . .mso devtag.tmac .nr s@devtag-needs-end-of-heading 0 .nr s@devtag-needs-end-of-title 0 . .\" Define a string for use in diagnostic messages. .ds @s s.tmac\" . .de @diag . ds *file \" empty . ds *line \" empty . if !'\\n[.F]'' .ds *file \\n[.F]:\" . if !'\\n[.c]'0' .ds *line \\n[.c]:\" . tm \*[@s]:\\*[*file]\\*[*line] \\$* . rm *file . rm *line .. . .de @error . @diag error: \\$* .. . .de @warning . @diag warning: \\$* .. . .de @nop .. . .de @not-implemented .@error sorry, .\\$0 not implemented .als \\$0 @nop .. . .\" documented Unix Version 7 ms macros that we don't implement .als EG @not-implemented \" engineer's notes .als IM @not-implemented \" internal memorandum .als MF @not-implemented \" memorandum for file .als MR @not-implemented \" memorandum for record .als TM @not-implemented \" technical memorandum .als TR @not-implemented \" technical report .als AT @not-implemented \" attachments .als CS @not-implemented \" cover sheet info for `TM` documents .als CT @not-implemented \" copies to .als OK @not-implemented \" "other keywords" for `TM` documents .als SG @not-implemented \" signatures for `TM` documents .als HO @not-implemented \" Holmdel .als IH @not-implemented \" Naperville (Indian Hill) .als MH @not-implemented \" Murray Hill .als PY @not-implemented \" Piscataway .als WH @not-implemented \" Whippany .als UX @not-implemented \" Unix w/ footnote trademark . .\" 4.2BSD ms macros documented by Tuthill 1983 that we don't implement .\"als TM @not-implemented \" thesis mode (already handled) .\"als CT @not-implemented \" chapter title for thesis (already handled) . .\" Wrap the .di request to save the name of the file being processed .\" when a diversion is started. This aids diagnostics when diversions .\" are still open after input has been processed and \n[.F] is empty. .als @divert di .de di . if \\n[.$] .ds @last-file-seen \\n[.F]\" . @divert \\$* .. . .de @init .if !rPO .nr PO \\n(.o .\" a non-empty environment .ev ne \c .ev .ev nf 'nf .ev .. .ds REFERENCES References .ds ABSTRACT ABSTRACT .ds TOC Table of Contents .ds MONTH1 January .ds MONTH2 February .ds MONTH3 March .ds MONTH4 April .ds MONTH5 May .ds MONTH6 June .ds MONTH7 July .ds MONTH8 August .ds MONTH9 September .ds MONTH10 October .ds MONTH11 November .ds MONTH12 December .ds MO \E*[MONTH\n[mo]] .ds DY \n[dy] \*[MO] \n[year] .de ND .if \\n[.$] .ds DY "\\$* .. .de DA .if \\n[.$] .ds DY "\\$* .ds CF \\*[DY] .. .\" print an error message and then try to recover .de @error-recover .@error \\$@ (recovering) .nr *pop-count 0 .while !'\\n(.z'' \{\ . \"@warning automatically terminating diversion \\n(.z . ie d @div-end!\\n(.z .@div-end!\\n(.z . el .*div-end-default . nr *pop-count +1 . \" ensure that we don't loop forever . if \\n[*pop-count]>20 .ab \*[@s]: fatal error: recovery failed .\} .while !'\\n[.ev]'0' .ev .par@reset-env .par@reset .. .de *div-end-default .ds *last-div \\n(.z .br .di .ev nf .\\*[*last-div] .ev .. .\" **************************** .\" ******** module cov ******** .\" **************************** .\" Cover sheet and first page. .de cov*err-not-after-first-page .@error .\\$0 is not allowed after the first page has started .. .de cov*err-not-before-tl .@error .\\$0 is not allowed before .TL .. .de cov*err-not-again .@error .\\$0 is not allowed more than once .. .de cov*err-not-after-ab .@error .\\$0 is not allowed after first .AB, .LP, .PP, .IP, .SH or .NH .. .als AU cov*err-not-before-tl .als AI cov*err-not-before-tl .als AB cov*err-not-before-tl .de cov*first-page-init .\" Invoked by '.wh 0' trap on first page. .\" We should not come here again, but at short page length, .\" recursion may occur; remove trap and macro to avoid it. .ch cov*first-page-init .rm cov*first-page-init .if !'\\n[.ev]'0' \{\ . ds cov*msg must be in top-level environment, not '\\n[.ev]',\" . as cov*msg " when first page is started\" . @error \\*[cov*msg] . rm cov*msg .\} .par@init .als RP cov*err-not-after-first-page .@init .ie \\n[cov*use-rp-format] \{\ . pg@cs-top . als FS cov*FS . als FE cov*FE .\} .el \{\ . pg@top . als FS @FS . als FE @FE .\} .wh 0 pg@top .CHECK-FOOTER-AND-KEEP .. .wh 0 cov*first-page-init .\" This handles the case where FS occurs before TL or LP. .de FS .br \\*[FS]\\ .. .nr cov*use-rp-format 0 .\" If we add more cover page formats, these behaviors and names could .\" be generalized. .nr cov*rp-no-repeat-info 0 .nr cov*rp-no-renumber 0 .\" report (AT&T: "released paper") document type .de RP .nr cov*use-rp-format 1 .while \\n[.$] \{\ . if '\\$1'no' .nr cov*rp-no-repeat-info 1 . if '\\$1'no-repeat-info' .nr cov*rp-no-repeat-info 1 . if '\\$1'no-renumber' .nr cov*rp-no-renumber 1 . shift .\} .if rPO .po \\n(POu .. .de TL .br .als TL cov*err-not-again .rn @AB AB .rn @AU AU .rn @AI AI .di cov*tl-div .par@reset .ft B .ps +2 .vs +3p .ll (u;\\n[LL]*5/6) .nr cov*n-au 0 .DEVTAG-TL .. .de @AU .par@reset .if !'\\n(.z'' \{\ . br . di .\} .nr cov*n-au +1 .di cov*au-div!\\n[cov*n-au] .nf .ft I .ie (\\n[PS] >= 1000) \ . ps (\\n[PS]z / 1000u) .el \ . ps \\n[PS] .. .de @AI .par@reset .if !'\\n(.z'' \{\ . br . di .\} .ie !\\n[cov*n-au] .@error .AI before .AU .el \{\ . di cov*ai-div!\\n[cov*n-au] . nf . ft R . ie (\\n[PS] >= 1000) \ . ps (\\n[PS]z / 1000u) . el \ . ps \\n[PS] .\} .. . .de LP .if !'\\n[.z]'' \{\ . br . di .\} .br .cov*ab-init .cov*print .nop \\*[\\$0]\\ .. . .als IP LP .als PP LP .als XP LP .als QP LP .als RS LP .als NH LP .als SH LP .als MC LP .als RT LP .als XS LP . .de cov*ab-init .als cov*ab-init @nop .als LP @LP .als IP @IP .als PP @PP .als XP @XP .als RT @RT .als XS @XS .als SH @SH .als NH @NH .als QP @QP .als RS @RS .als RE @RE .als QS @QS .als QE @QE .als MC @MC .als EQ @EQ .als EN @EN .als PS @PS .als TS @TS .als AB cov*err-not-after-ab .als AU par@AU .als AI par@AI .als TL par@TL .. . .de @AB .if !'\\n(.z'' \{\ . br . di .\} .cov*ab-init .ie '\*(.T'html' \{\ . cov*tl-au-print . als cov*tl-au-print @nop .\} .el .di cov*ab-div .par@ab-indent .par@reset .if !'\\$1'no' \{\ . if '\*(.T'html' \{\ . nf . sp . \} . ft I . ce 1 \\*[ABSTRACT] . sp . ft R .\} .ns .@PP .if '\*(.T'html' \{\ . cov*tl-au-print . als cov*tl-au-print @nop . par@reset-env . par@reset . cov*print .\} .. .de AE .ie '\*(.T'html' \{\ . als AE cov*err-not-again .\} .el \{\ . ie '\\n(.z'cov*ab-div' \{\ . als AE cov*err-not-again . br . di .\" nr cov*ab-height \\n[dn] . par@reset-env . par@reset . cov*print . \} . el .@error .AE without .AB .\} .. .de @div-end!cov*ab-div .AE .. .de cov*break-page .ie \\n[cov*rp-no-renumber] .bp .el .bp 1 .. .de cov*print .als cov*print @nop .ie d cov*tl-div \{\ . ie \\n[cov*use-rp-format] .cov*rp-print . el .cov*draft-print .\} .el \{\ . if \\n[cov*use-rp-format] \{\ . @warning .RP format but no .TL . .cov*break-page . als FS @FS . als FE @FE . CHECK-FOOTER-AND-KEEP . \} . br .\} .. .de cov*rp-print .nr cov*page-length \\n[.p] .pl 1000i .cov*tl-au-print .sp 3 .if d cov*ab-div \{\ . if !'\*(.T'html' .nf . cov*ab-div .\} .sp 3 .par@reset \\*[DY] .br .if \\n[cov*fn-height] \{\ . sp |(u;\\n[cov*page-length]-\\n[FM]\ -\\n[cov*fn-height]-\\n[fn@sep-dist]>?\\n[nl]) . fn@print-sep . ev nf . cov*fn-div . ev . ie \\n[cov*rp-no-repeat-info] .rm cov*fn-div . el \{\ . rn cov*fn-div fn@overflow-div . nr fn@have-overflow 1 . \} .\} .als FS @FS .als FE @FE .CHECK-FOOTER-AND-KEEP .\" If anything was printed below where the footer line is normally .\" printed, then that's an overflow. .if -\\n[FM]/2+1v+\\n[cov*page-length]<\\n[nl] \ . @error cover sheet overflow .pl \\n[cov*page-length]u .cov*break-page .if !\\n[cov*rp-no-repeat-info] .cov*tl-au-print .rs .sp 1 .. .de cov*draft-print .cov*tl-au-print .if d cov*ab-div \{\ . nf . sp 2 . cov*ab-div .\} .sp 1 .. .de cov*tl-au-print .par@reset .nf .rs .sp 3 .ce 9999 .if d cov*tl-div \{\ . cov*tl-div . DEVTAG-EO-TL .\} .nr cov*i 1 .nr cov*sp 1v .while \\n[cov*i]<=\\n[cov*n-au] \{\ . ie '\*(.T'html' .br . el .sp \\n[cov*sp]u . cov*au-div!\\n[cov*i] . ie d cov*ai-div!\\n[cov*i] \{\ . sp .5v . cov*ai-div!\\n[cov*i] . nr cov*sp 1v . \} . el .nr cov*sp .5v . nr cov*i +1 .\} .ce 0 .. .nr cov*fn-height 0 .nr cov*in-fn 0 .\" start of footnote on cover .de cov*FS .if \\n[cov*in-fn] \{\ . @error nested .FS . FE .\} .nr cov*in-fn 1 .ev fn .par@reset-env .da cov*fn-div .if !\\n[cov*fn-height] .ns .ie \\n[.$] .FP "\\$1" no .el .@LP .. .de @div-end!cov*fn-div .cov*FE .. .\" end of footnote on cover .de cov*FE .ie '\\n(.z'cov*fn-div' \{\ . br . ev . di . nr cov*in-fn 0 . nr cov*fn-height +\\n[dn] .\} .el .@error .FE without matching .FS .. .\" *************************** .\" ******** module pg ******** .\" *************************** .\" Page-level formatting. .\" > 0 if we have a footnote on the current page .nr pg@fn-flag 0 .nr pg@colw 0 .nr pg@fn-colw 0 .nr HM 1i .nr FM 1i .ds LF .ds CF .ds RF .ds LH .ds CH -\En[%]-\" .ds RH .ds pg*OH '\E*[LH]'\E*[CH]'\E*[RH]' .ds pg*EH '\E*[LH]'\E*[CH]'\E*[RH]' .ds pg*OF '\E*[LF]'\E*[CF]'\E*[RF]' .ds pg*EF '\E*[LF]'\E*[CF]'\E*[RF]' .de OH .ds pg*\\$0 "\\$* .. .als EH OH .als OF OH .als EF OH .aln PN % \" Lesk 1978 documents PN. .de PT .\" To compare the page number to 1, we need it in Arabic format. .ds pg*saved-page-number-format \\g%\" .af % 0 .nr pg*page-number-in-decimal \\n% .af % \\*[pg*saved-page-number-format] .fam \\*[pg@titles-font-family] .ie \\n[pg*page-number-in-decimal]=1 .if \\n[pg*P1] .tl \\*[pg*OH] .el \{\ . ie o .tl \\*[pg*OH] . el .tl \\*[pg*EH] .\} .rm pg*saved-page-number-format .. .de BT .fam \\*[pg@titles-font-family] .ie o .tl \\*[pg*OF] .el .tl \\*[pg*EF] .. .nr pg*P1 0 .de P1 .nr pg*P1 1 .. .wh -\n[FM]u pg@bottom .wh -\n[FM]u/2u pg*footer .nr MINGW 2n .nr pg@ncols 1 .de @MC .if !'\\n(.z'' .@error-recover .MC while diversion open .br .ie \\n[pg@ncols]>1 .pg@super-eject .el \{\ . \" flush out any floating keeps . while \\n[kp@tail]>\\n[kp@head] \{\ . rs . bp . \} .\} .ie !\\n(.$ \{\ . nr pg*gutw \\n[MINGW] . nr pg@colw \\n[LL]-\\n[pg*gutw]/2u . nr pg@ncols 2 .\} .el \{\ . nr pg@colw (n;\\$1)1 \ . nr pg*gutw \\n[LL]-(\\n[pg@ncols]*\\n[pg@colw])/(\\n[pg@ncols]-1) . el .nr pg*gutw 0 .\} .DEVTAG ".mc \\n[pg@ncols] \\n[pg@colw] \\n[pg*gutw]" .nr pg*col-num 0 .nr pg@fn-colw \\n[pg@colw]*\\*[FR] .par@reset .ns .mk pg*col-top .. .de 2C .MC .. .de 1C .MC \\n[LL]u .. .de pg@top .\" invoked by '.wh 0' trap at the top of every page .\" .\" At short page lengths, footers may get truncated or recursion may .\" occur; ensure that the page length suffices to avoid these problems. .if (u;\\n[HM]+\\n[FM]+\n[.V]>=\\n[.p]) \{\ . @error insufficient page length; aborting\" . pl \\n[nl]u . ab .\} .ch pg*footer -\\n[FM]u/2u .nr pg*col-num 0 .nr pg@fn-bottom-margin 0 .po \\n[PO]u .ev h .par@reset .sp (u;\\n[HM]/2) .PT .sp |\\n[HM]u .if d HD .HD .mk pg@header-bottom .ev .mk pg*col-top .pg*start-col .. .de pg*start-col .\" Handle footnote overflow before floating keeps, because the keep .\" might contain an embedded footnote. .fn@top-hook .kp@top-hook .tbl@top-hook .ns .. .de pg@cs-top .sp \\n[HM]u .\" move pg@bottom and pg*footer out of the way .ch pg@bottom \\n[.p]u*2u .ch pg*footer \\n[.p]u*2u .ns .. .de pg@bottom .tbl@bottom-hook .if \\n[pg@fn-flag] .fn@bottom-hook .nr pg*col-num +1 .ie \\n[pg*col-num]<\\n[pg@ncols] .pg*end-col .el .pg*end-page .. .de pg*end-col 'sp |\\n[pg*col-top]u .po (u;\\n[PO]+(\\n[pg@colw]+\\n[pg*gutw]*\\n[pg*col-num])) .\"po +(u;\\n[pg@colw]+\\n[pg*gutw]) .pg*start-col .. .de pg*end-page .po \\n[PO]u .\" Make sure we don't exit if there are still floats or footnotes .\" left-over. .ie \\n[kp@head]<\\n[kp@tail]:\\n[fn@have-overflow] \{\ . \" Switching environments ensures that we don't get an unnecessary . \" blank line at the top of the page. . ev ne ' bp . ev .\} .el \{\ . \" If the text has ended and there are no more footnotes or . \" keeps, exit. . if \\n[pg@text-ended] .ex . if r pg*next-number \{\ . pn \\n[pg*next-number] . rr pg*next-number . if d pg*next-format \{\ . af % \\*[pg*next-format] . rm pg*next-format . \} . \} ' bp .\} .. .\" pg@begin number format .de pg@begin .ie \\n[.$]>0 \{\ . nr pg*next-number (;\\$1) . ie \\n[.$]>1 .ds pg*next-format \\$2 . el .rm pg*next-format .\} .el .rr pg*next-number .pg@super-eject .. .\" print the footer line .de pg*footer .ev h .par@reset .BT .ev .. .\" flush out any keeps or footnotes .de pg@super-eject .br .if !'\\n(.z'' \{\ . ds @msg diversion open while ejecting page\" . as @msg " (last file seen: \\*[@last-file-seen])\" . @error-recover \\*[@msg] . rm @msg .\} .\" Make sure we stay in the end macro while there is still footnote .\" overflow left, or floating keeps. .while \\n[kp@tail]>\\n[kp@head]:\\n[pg@fn-flag] \{\ . rs . bp .\} .bp .. .nr pg@text-ended 0 .de pg@end-text .br .nr pg@text-ended 1 .pg@super-eject .. .em pg@end-text .\" *************************** .\" ******** module fn ******** .\" *************************** .\" Footnotes. .nr fn@sep-dist 8p .ev fn .\" Round it vertically .vs \n[fn@sep-dist]u .nr fn@sep-dist \n[.v] .ev .nr fn*text-num 0 1 .nr fn*note-num 0 1 .nr fn*open 0 .\" Handle initialition tasks deferred until par module is set up. .de fn@init .ie t .als fn@mark-start par@sup-start .el .ds fn@mark-start [ .ie t .als fn@mark-end par@sup-end .el .ds fn@mark-end ] .ds * \E*[fn@mark-start]\En+[fn*text-num]\E*[fn@mark-end] .. .\" normal FS .\" FS-MARK is a user definable hook, which may be used to perform .\" any set-up actions, (e.g. planting an HREF link as the footnote .\" mark, in the document text); passed the same arguments as have .\" been passed to FS itself, unless redefined, it is a no-op. .de @FS .FS-MARK \\$@ .ie \\n[.$] .fn*do-FS "\\$1" no .el \{\ . ie \\n[fn*text-num]>\\n[fn*note-num] .fn*do-FS \\n+[fn*note-num] . el .fn*do-FS .\} .. .\" Default no-op fallback for FS-MARK .de FS-MARK .. .\" Second argument of 'no' means don't embellish the first argument. .de fn*do-FS .if \\n[fn*open] .@error-recover nested .FS .nr fn*open 1 .if \\n[.u] \{\ . \" Ensure that the first line of the footnote is on the same page . \" as the reference. I think this is minimal. . ev fn . nr fn*need 1v . ev . ie \\n[pg@fn-flag] .nr fn*need +\\n[fn:PD] . el .nr fn*need +\\n[fn@sep-dist] . ne \\n[fn*need]u+\\n[.V]u>?0 .\} .ev fn .par@reset-env .fn*start-div .par@reset .fam \\*[fn@font-family] .ie \\n[.$] .FP \\$@ .el .@LP .. .de @FE .ie !\\n[fn*open] .@error .FE without .FS .el \{\ . nr fn*open 0 . br . ev . fn*end-div .\} .. .nr fn@have-overflow 0 .\" called at the top of each column .de fn@top-hook .nr fn*max-width 0 .nr fn*page-bottom-pos 0-\\n[FM]-\\n[pg@fn-bottom-margin] .ch pg@bottom \\n[fn*page-bottom-pos]u .if \\n[fn@have-overflow] \{\ . nr fn@have-overflow 0 . fn*start-div . ev nf . fn@overflow-div . ev . fn*end-div .\} .. .\" This is called at the bottom of the column if pg@fn-flag is set. .de fn@bottom-hook .nr pg@fn-flag 0 .nr fn@have-overflow 0 .nr fn@bottom-pos \\n[.p]-\\n[FM]-\\n[pg@fn-bottom-margin]+\\n[.v] .ev fn .nr fn@bottom-pos -\\n[.v] .ev .ie \\n[nl]+\\n[fn@sep-dist]+\n[.V]>\\n[fn@bottom-pos] \{\ . rn fn@div fn@overflow-div . nr fn@have-overflow 1 .\} .el \{\ . if \\n[pg@ncols]>1 \ . if \\n[fn*max-width]>\\n[pg@fn-colw] \ . nr pg@fn-bottom-margin \\n[.p]-\\n[FM]-\\n[nl]+1v . wh \\n[fn@bottom-pos]u fn*catch-overflow . fn@print-sep . ev nf . fn@div . rm fn@div . ev . if '\\n(.z'fn@overflow-div' \{\ . di . nr fn@have-overflow \\n[dn]>0 . \} . ch fn*catch-overflow .\} .. .de fn*catch-overflow .di fn@overflow-div .. .nr fn*embed-count 0 .de @div-end!fn@div .br .if '\\n[.ev]'fn' .ev .fn*end-div .nr fn*open 0 .. .als @div-end!fn*embed-div @div-end!fn@div .de fn*start-div .ie '\\n(.z'' \{\ . da fn@div . if !\\n[pg@fn-flag] .ns .\} .el .di fn*embed-div .. .de fn*end-div .ie '\\n(.z'fn@div' \{\ . di . nr fn*page-bottom-pos -\\n[dn] . nr fn*max-width \\n[fn*max-width]>?\\n[dl] . if !\\n[pg@fn-flag] .nr fn*page-bottom-pos -\\n[fn@sep-dist] . nr pg@fn-flag 1 . nr fn*page-bottom-pos \\n[nl]-\\n[.p]+\n[.V]>?\\n[fn*page-bottom-pos] . ch pg@bottom \\n[fn*page-bottom-pos]u .\} .el \{\ . ie '\\n(.z'fn*embed-div' \{\ . di . rn fn*embed-div fn*embed-div!\\n[fn*embed-count] \!. fn*embed-start \\n[fn*embed-count] . rs ' sp (u;\\n[dn]+\\n[fn@sep-dist]+\\n[.V]) \!. fn*embed-end . nr fn*embed-count +1 . \} . el \{\ . ev fn . @error-recover unclosed diversion within footnote . \} .\} .. .de fn*embed-start .ie '\\n(.z'' \{\ . fn*start-div . ev nf . fn*embed-div!\\$1 . rm fn*embed-div!\\$1 . ev . fn*end-div . di fn*null .\} .el \{\ \!. fn*embed-start \\$1 . rs .\} .. .de fn*embed-end .ie '\\n(.z'fn*null' \{\ . di . rm fn*null .\} .el \!.fn*embed-end .. .\" It's important that fn@print-sep use up exactly fn@sep-dist vertical .\" space. .de fn@print-sep .ev fn .in 0 .vs \\n[fn@sep-dist]u \D'l 1i 0' .br .ev .. .\" *************************** .\" ******** module kp ******** .\" *************************** .\" Keeps. .de KS .br .di kp@div .. .de KF .if !'\\n(.z'' .@error-recover .KF while diversion open .di kp@fdiv .ev k .par@reset-env .par@reset .. .de KE .ie '\\n(.z'kp@div' .kp*end .el \{\ . ie '\\n(.z'kp@fdiv' .kp*fend . el .@error .KE without .KS or .KF .\} .. .de @div-end!kp@div .kp*end .. .de @div-end!kp@fdiv .kp*fend .. .de kp*need .ie '\\n(.z'' .ds@need \\$1 .el \!.kp*need \\$1 .. .\" end non-floating keep .de kp*end .br .di .kp*need \\n[dn] .ev nf .kp@div .ev .rm kp@div .. .\" Floating keeps. .nr kp@head 0 .nr kp@tail 0 .\" end floating keep .de kp*fend .br .ev .di .ie \\n[.t]-(\\n[.k]>0*1v)>\\n[dn] \{\ . br . ev nf . kp@fdiv . rm kp@fdiv . ev .\} .el \{\ . rn kp@fdiv kp@div!\\n[kp@tail] . nr kp*ht!\\n[kp@tail] 0\\n[dn] . nr kp@tail +1 .\} .. .\" top of page processing for KF .nr kp*doing-top 0 .de kp@top-hook .if !\\n[kp*doing-top] \{\ . nr kp*doing-top 1 . kp*do-top . nr kp*doing-top 0 .\} .. .de kp*do-top .\" If the first keep won't fit, only force it out if we haven't had a .\" footnote and we're at the top of the page. .nr kp*force \\n[pg@fn-flag]=0&(\\n[nl]<=\\n[pg@header-bottom]) .nr kp*fits 1 .while \\n[kp@tail]>\\n[kp@head]&\\n[kp*fits] \{\ . ie \\n[.t]>\\n[kp*ht!\\n[kp@head]]:\\n[kp*force] \{\ . nr kp*force 0 . \" It's important to advance kp@head before bringing . \" back the keep, so that if the last line of the . \" last keep springs the bottom of page trap, a new . \" page will not be started unnecessarily. . rn kp@div!\\n[kp@head] kp*temp . nr kp@head +1 . ev nf . kp*temp . ev . rm kp*temp . \} . el .nr kp*fits 0 .\} .. .\" *************************** .\" ******** module ds ******** .\" *************************** .\" Displays and non-floating keeps. .de DE .ds*end!\\n[\\n[.ev]:ds-type] .nr \\n[.ev]:ds-type 0 .ns .. .de ds@auto-end .if \\n[\\n[.ev]:ds-type] \{\ . @error automatically terminating display . DE .\} .. .de @div-end!ds*div .ie \\n[\\n[.ev]:ds-type] .DE .el .ds*end!2 .. .de ds*end!0 .@error .DE without .DS, .ID, .CD, .LD, .RD, or .BD .. .de LD .br .nr \\n[.ev]:ds-type 1 .par@reset .nf .sp \\n[DD]u .. .de ID .LD .ie \\n[.$] .in +(n;\\$1) .el .in +\\n[DI]u .. .de CD .LD .ce 9999 .. .de RD .LD .rj 9999 .. .de ds*common-end .par@reset .sp \\n[DD]u .. .als ds*end!1 ds*common-end .de BD .LD .nr \\n[.ev]:ds-type 2 .di ds*div .. .de ds*end!2 .br .ie '\\n(.z'ds*div' \{\ . di . nf . in (u;\\n[.l]-\\n[dl]/2>?0) . ds*div . rm ds*div . ds*common-end .\} .el .@error-recover mismatched .DE .. .de DS .if '\\n(.z'ds*div' .@error-recover cannot begin display within display .nr ds*badarg 0 .di ds*div .ie '\\$1'B' \{\ . LD . nr \\n[.ev]:ds-type 4 .\} .el \{\ . ie '\\$1'L' .LD . el \{\ . ie '\\$1'C' .CD . el \{\ . ie '\\$1'R' .RD . el \{\ . ie '\\$1'I' .ID \\$2 . el \{\ . ie '\\$1'' .ID . el .nr ds*badarg 1 . \} . \} . \} . \} . ie \\n[ds*badarg] \{\ . ds ds*msg unrecognized argument '\\$1' to .\\$0;\" . as ds*msg " did you mean '.\\$0 I \\$1'?\" . @error \\*[ds*msg] . rm ds*msg . di . \} . el .nr \\n[.ev]:ds-type 3 .\} .rr ds*badarg .. .de ds@need .if '\\n(.z'' \{\ . while \\n[.t]<=(\\$1)&(\\n[nl]>\\n[pg@header-bottom]) \{\ . rs ' sp \\n[.t]u . \} .\} .. .de ds*end!3 .br .ie '\\n(.z'ds*div' \{\ . di . ds@need \\n[dn] . ev nf . ds*div . ev . rm ds*div . ds*common-end .\} .el .@error-recover mismatched .DE .. .de ds*end!4 .ie '\\n(.z'ds*div' \{\ . br . di . nf . in (u;\\n[.l]-\\n[dl]/2>?0) . ds@need \\n[dn] . ds*div . rm ds*div . ds*common-end .\} .el .@error-recover mismatched .DE .. .\" **************************** .\" ******** module par ******** .\" **************************** .\" Paragraph-level formatting. .\" Load time initialization. .de par@load-init .\" PS and VS might have been set on the command line .if !rPS .nr PS 10 .if !rLL .nr LL 6.5i .ll \\n[LL]u .\" don't set LT so that it can be defaulted from LL .ie rLT .lt \\n[LT]u .el .lt \\n[LL]u .ie (\\n[PS] >= 1000) \ . ps (\\n[PS]z / 1000u) .el \ . ps \\n[PS] .\" don't set VS so that it can be defaulted from PS .ie rVS \{\ . ie (\\n[VS] >= 1000) \ . par*vs "(\\n[VS]p / 1000u)" . el \ . par*vs \\n[VS] .\} .el \{\ . ie (\\n[PS] >= 1000) \ . par*vs "((\\n[PS]p / 1000u) + 2p)" . el \ . par*vs "(\\n[PS] + 2)" .\} .if dFAM .fam \\*[FAM] .if !rHY .nr HY 6 .hy \\n[HY] .TA .CHECK-FOOTER-AND-KEEP .. .de par*vs .\" If it's too big to be in points, treat it as units. .ie (p;\\$1)>=40p .vs (u;\\$1) .el .vs (p;\\$1) .. .de par@ab-indent .nr 0:li (u;\\n[LL]/12) .nr 0:ri \\n[0:li] .. .de par*env-init .aln \\n[.ev]:PS PS .aln \\n[.ev]:VS VS .aln \\n[.ev]:LL LL .aln \\n[.ev]:MCLL LL .aln \\n[.ev]:LT LT .aln \\n[.ev]:MCLT LT .aln \\n[.ev]:PI PI .aln \\n[.ev]:PD PD .ad \\n[par*adj] .par@reset-env .. .\" happens when the first page begins .de par@init .if !rLT .nr LT \\n[LL] .if !rFL .nr FL \\n[LL]*\\*[FR] .if !rVS \{\ . ie (\\n[PS] >= 1000) \ . nr VS (\\n[PS] + 2000) . el \ . nr VS (\\n[PS] + 2) .\} .if !rDI .nr DI .5i .if !rFPS \{\ . ie (\\n[PS] >= 1000) \ . nr FPS (\\n[PS] - 2000) . el \ . nr FPS (\\n[PS] - 2) .\} .if !rFVS \{\ . ie (\\n[FPS] >= 1000) \ . nr FVS (\\n[FPS] + 2000) . el \ . nr FVS (\\n[FPS] + 2) .\} .\" don't change environment 0 .ev h .ie (\\n[PS] >= 1000) \ . ps (\\n[PS]z / 1000u) .el \ . ps \\n[PS] .if !rQI .nr QI 5n .if !rPI .nr PI 5n .ie (\\n[VS] >= 1000) \ . par*vs "(\\n[VS]p / 1000u)" .el \ . par*vs \\n[VS] .if !rPD .nr PD .3v>?\n(.V .if !rDD .nr DD .5v>?\n(.V .if !rFI .nr FI 2n .if !rFPD .nr FPD \\n[PD]/2 .ev .if !dFAM .ds FAM \\n[.fam] .ds pg@titles-font-family \\*[FAM] .ds fn@font-family \\*[FAM] .nr par*adj \\n[.j] .par*env-init .ev h .par*env-init .ev .ev fn .par*env-init .ev .ev k .par*env-init .ev .aln 0:MCLL pg@colw .aln 0:MCLT pg@colw .aln k:MCLL pg@colw .aln k:MCLT pg@colw .aln fn:PS FPS .aln fn:VS FVS .aln fn:LL FL .aln fn:LT FL .aln fn:PI FI .aln fn:PD FPD .aln fn:MCLL pg@fn-colw .aln fn:MCLT pg@fn-colw .. .de par@reset-env .nr \\n[.ev]:il 0 .nr \\n[.ev]:li 0 .nr \\n[.ev]:ri 0 .nr \\n[.ev]:ai \\n[\\n[.ev]:PI] .nr \\n[.ev]:pli 0 .nr \\n[.ev]:pri 0 .nr \\n[.ev]:ds-type 0 .. .\" par@reset .de par@reset .br .if \\n[s@devtag-needs-end-of-title] .DEVTAG-EO-TL .nr s@devtag-needs-end-of-title 0 .if \\n[s@devtag-needs-end-of-heading] .DEVTAG-EO-H .nr s@devtag-needs-end-of-heading 0 .ce 0 .rj 0 .ul 0 .fi .ft 1 .ie '\\n[.ev]'fn' .fam \\*[fn@font-family] .el .fam \\*[FAM] .ie (\\n[\\n[.ev]:PS] >= 1000) \ . ps (\\n[\\n[.ev]:PS]z / 1000u) .el \ . ps \\n[\\n[.ev]:PS] .ie (\\n[\\n[.ev]:VS] >= 1000) \ . par*vs "(\\n[\\n[.ev]:VS]p / 1000u)" .el \ . par*vs \\n[\\n[.ev]:VS] .ls 1 .if !'\\$1'' .nr \\n[.ev]:pli (n;\\$1) .if !'\\$2'' .nr \\n[.ev]:pri (n;\\$2) .ie \\n[pg@ncols]>1 \{\ . ll (u;\\n[\\n[.ev]:MCLL]-\\n[\\n[.ev]:ri]-\\n[\\n[.ev]:pri]) . lt \\n[\\n[.ev]:MCLT]u .\} .el \{\ . ll (u;\\n[\\n[.ev]:LL]-\\n[\\n[.ev]:ri]-\\n[\\n[.ev]:pri]) . lt \\n[\\n[.ev]:LT]u .\} .in (u;\\n[\\n[.ev]:li]+\\n[\\n[.ev]:pli]) .TA .hy \\n[HY] .. .\" This can be redefined by the user. .de TA .ta T 5n .. .\" \n[PORPHANS] sets number of initial lines of any paragraph, .\" which must be kept together, without any included page break. .\" Initialise to reproduce original behaviour; user may adjust it. .if !rPORPHANS .nr PORPHANS 1 . .de par*start .ds@auto-end .par@reset \\$1 \\$2 .sp \\n[\\n[.ev]:PD]u .ne \\n[PORPHANS]v+\\n(.Vu .. .de par@finish .nr \\n[.ev]:ai \\n[\\n[.ev]:PI] .nr \\n[.ev]:pli 0 .nr \\n[.ev]:pri 0 .par@reset 0 0 .. .als @RT par@finish .\" normal LP .de @LP .par*start 0 0 .nr \\n[.ev]:ai \\n[\\n[.ev]:PI] .. .de @PP .par*start 0 0 .nr \\n[.ev]:ai \\n[\\n[.ev]:PI] .if !'\*(.T'html' .ti +\\n[\\n[.ev]:ai]u .. .de @QP .nr \\n[.ev]:ai \\n[\\n[.ev]:PI] .par*start \\n[QI]u \\n[QI]u .. .de @XP .par*start \\n[\\n[.ev]:PI]u 0 .ti -\\n[\\n[.ev]:PI]u .. .de @IP .ie \\n[.$]>1 \{\ .par*start \\$2 0 .nr \\n[.ev]:ai \\n[\\n[.ev]:pli] .\} .el .par*start \\n[\\n[.ev]:ai]u 0 .if !'\\$1'' \{\ . \" Divert the label so as to freeze any spaces. . di par*label . par*push-tag-env \&\\$1 . par*pop-tag-env . di . chop par*label . ti -\\n[\\n[.ev]:ai]u . ie \\n[dl]+1n<=\\n[\\n[.ev]:ai] \{\ . DEVTAG-COL 1 \\*[par*label]\h'|\\n[\\n[.ev]:ai]u'\c . DEVTAG-COL 2 . \} . el \{\ . DEVTAG-COL 1 \\*[par*label] . DEVTAG-COL-NEXT 2 . br . \} . rm par*label .\} .. .\" We don't want margin characters to be attached when we divert .\" the tag. Since there's no way to save and restore the current .\" margin character, we have to switch to a new environment, taking .\" what we need of the old environment with us. .de par*push-tag-env .nr par*saved-font \\n[.f] .nr par*saved-size \\n[.s]z .nr par*saved-ss \\n[.ss] .nr par*saved-sss \\n[.sss] .ds par*saved-fam \\n[.fam] .ev par .nf .TA .ft \\n[par*saved-font] .ps \\n[par*saved-size]u .ss \\n[par*saved-ss] \\n[par*saved-sss] .fam \\*[par*saved-fam] .. .de par*pop-tag-env .ev .. .de @RS .br .nr \\n[.ev]:li!\\n[\\n[.ev]:il] \\n[\\n[.ev]:li] .nr \\n[.ev]:ri!\\n[\\n[.ev]:il] \\n[\\n[.ev]:ri] .nr \\n[.ev]:ai!\\n[\\n[.ev]:il] \\n[\\n[.ev]:ai] .nr \\n[.ev]:pli!\\n[\\n[.ev]:il] \\n[\\n[.ev]:pli] .nr \\n[.ev]:pri!\\n[\\n[.ev]:il] \\n[\\n[.ev]:pri] .nr \\n[.ev]:il +1 .nr \\n[.ev]:li +\\n[\\n[.ev]:ai] .nr \\n[.ev]:ai \\n[\\n[.ev]:PI] .par@reset .. .de @RE .br .ie \\n[\\n[.ev]:il] \{\ . nr \\n[.ev]:il -1 . nr \\n[.ev]:ai \\n[\\n[.ev]:ai!\\n[\\n[.ev]:il]] . nr \\n[.ev]:li \\n[\\n[.ev]:li!\\n[\\n[.ev]:il]] . nr \\n[.ev]:ri \\n[\\n[.ev]:ri!\\n[\\n[.ev]:il]] . nr \\n[.ev]:pli \\n[\\n[.ev]:pli!\\n[\\n[.ev]:il]] . nr \\n[.ev]:pri \\n[\\n[.ev]:pri!\\n[\\n[.ev]:il]] .\} .el .@error unbalanced .\\$0 .ie '\\$0'QE' .par*start 0 0 .el .par@reset .. .de @QS .br .nr \\n[.ev]:li!\\n[\\n[.ev]:il] \\n[\\n[.ev]:li] .nr \\n[.ev]:ri!\\n[\\n[.ev]:il] \\n[\\n[.ev]:ri] .nr \\n[.ev]:ai!\\n[\\n[.ev]:il] \\n[\\n[.ev]:ai] .nr \\n[.ev]:pli!\\n[\\n[.ev]:il] \\n[\\n[.ev]:pli] .nr \\n[.ev]:pri!\\n[\\n[.ev]:il] \\n[\\n[.ev]:pri] .nr \\n[.ev]:il +1 .nr \\n[.ev]:li +\\n[QI] .nr \\n[.ev]:ri +\\n[QI] .nr \\n[.ev]:ai \\n[\\n[.ev]:PI] .par*start 0 0 .. .als @QE @RE .\" start boxed text .de B1 .br .HTML-IMAGE .di par*box-div .nr \\n[.ev]:li +1n .nr \\n[.ev]:ri +1n .nr par*box-in \\n[.in] .\" remember what 1n is, just in case the point size changes .nr par*box-n 1n .in +1n .ll -1n .lt -1n .ti \\n[par*box-in]u+1n .. .de @div-end!par*box-div .B2 .. .\" end boxed text .\" Postpone the drawing of the box until we're in the top-level .\" diversion, in case there's a footnote inside the box. .de B2 .ie '\\n(.z'par*box-div' \{\ . br . if \n[.V]>.25m .sp . di . if \n[.V]>.25m .sp . ds@need \\n[dn] . par*box-mark-top . ev nf . par*box-div . ev . nr \\n[.ev]:ri -\\n[par*box-n] . nr \\n[.ev]:li -\\n[par*box-n] . in -\\n[par*box-n]u . ll +\\n[par*box-n]u . lt +\\n[par*box-n]u . par*box-draw \\n[.i]u \\n[.l]u-(\\n[.H]u==1n*1n) .\} .el .@error .B2 without .B1 .HTML-IMAGE-END .. .de par*box-mark-top .ie '\\n[.z]'' \{\ . rs . mk par*box-top .\} .el \!.par*box-mark-top .. .de par*box-draw .ie '\\n[.z]'' \{\ . nr par*box-in \\n[.i] . nr par*box-ll \\n[.l] . nr par*box-vpt \\n[.vpt] . nr par*box-ad \\n[.j] . ad l . vpt 0 . in \\$1 . ll \\$2 \v'-1v+.25m'\ \D'l (u;\\n[.l]-\\n[.i]) 0'\ \D'l 0 |\\n[par*box-top]u'\ \D'l -(u;\\n[.l]-\\n[.i]) 0'\ \D'l 0 -|\\n[par*box-top]u' . br . sp -1 . in \\n[par*box-in]u . ll \\n[par*box-ll]u . vpt \\n[par*box-vpt] . ad \\n[par*box-ad] .\} .el \!.par*box-draw \\$1 \\$2 .. .\" \n[HORPHANS] sets how many lines of the following paragraph must be .\" kept together, with a preceding section header. Initialise it, .\" to reproduce original behaviour; user may change it. .if !rHORPHANS .nr HORPHANS 1 . .\" \n[GROWPS] and \n[PSINCR] cause auto-increment of header point size. .\" Initialise them, so they have no effect, unless explicitly set by .\" the user. .if !rGROWPS .nr GROWPS 0 .if !rPSINCR .nr PSINCR 1p . .de SH-NO-TAG .par@finish .\" Keep the heading and the first few lines of the next paragraph .\" together. (\n[HORPHANS] defines "first few" -- default = 1; user .\" may redefine it). .nr sh*minvs \\n[HORPHANS]v .if \\n[sh*psincr]<0 .nr sh*psincr 0 .ie \\n(VS<1000 .par*vs \\n(VSp+\\n[sh*psincr]u .el .par*vs \\n(VSp/1000u+\\n[sh*psincr]u .ne 2v+\\n[sh*minvs]u+\\n[\\n[.ev]:PD]u+\\n(.Vu .\" Adjust point size for heading text, as specified by \n[GROWPS] and .\" \n[PSINCR]. .ie \\n(PS<1000 .ps \\n(PS+\\n[sh*psincr]u .el .ps \\n(PSz/1000u+\\n[sh*psincr]u .sp 1 .ft B .. .de @SH .\" Standard ms implementation does not expect an argument, .\" but allow ".SH n" to make heading point size match ".NH n", .\" for same "n", when \n[GROWPS] and \n[PSINCR] are set. . nr sh*psincr 0 . if 0\\$1>0 .nr sh*psincr (\\n[GROWPS]-0\\$1)*\\n[PSINCR] . SH-NO-TAG . DEVTAG-SH 1 . if '\*(.T'html' .nr s@devtag-needs-end-of-heading 1 .. .\" TL, AU, and AI are aliased to these in cov*ab-init. .de par@TL .par@finish .sp 1 .ft B .ps +2 .vs +3p .ce 9999 .DEVTAG-TL .nr s@devtag-needs-end-of-title 1 .. .de par@AU .par@finish .sp 1 .ft I .ce 9999 .. .de par@AI .par@finish .sp .5 .ce 9999 .. .\" In paragraph macros. .de NL .if \En[.$] .@warning arguments to .NL ignored .ie (\\n[\\n[.ev]:PS] >= 1000) \ . ps (\\n[\\n[.ev]:PS]z / 1000u) .el \ . ps \\n[\\n[.ev]:PS] .. .de SM .if \En[.$] .@warning arguments to .SM ignored .ps -2 .. .de LG .if \En[.$] .@warning arguments to .LG ignored .ps +2 .. .\" par*define-font-macro macro font apply-italic-corrections .de par*define-font-macro .de \\$1 .ds par*lic \" empty .ds par*ic \" empty .if \\n[.$]>2 \{\ . as par*lic \,\" . as par*ic \/\" .\} .if \En[.$]>3 .@warning excess arguments to .\\$1 ignored .ie \En[.$] \{\ . nr par*prev-font \En[.f] \&\E$3\E*[par*lic]\f[\\$2]\E$1\f[\En[par*prev-font]]\E*[par*ic]\E$2 .\} .el .ft \\$2 \\.. .. .par*define-font-macro R R .par*define-font-macro B B .par*define-font-macro I I yes .par*define-font-macro BI BI yes .ie n .par*define-font-macro CW R .el .par*define-font-macro CW CR .\" underline a word .de UL .if \En[.$]>2 .@warning excess arguments to .UL ignored . ie t .do nop \Z'\\$1'\v'.25m'\D'l \w'\\$1'u 0'\v'-.25m'\\$2 . el \(ul\\$1\(ul\\$2 .. .\" box a word .de BX .if \En[.$]>1 .@warning excess arguments to .BX ignored .nr par*bxw \w'\\$1' .ie t \{\ .nr par*bxw +.4m \Z'\v'.25m'\ \D'l 0 -1m'\D'l \\n[par*bxw]u 0'\D'l 0 1m'\D'l -\\n[par*bxw]u 0''\ \Z'\h'.2m'\\$1'\h'\\n[par*bxw]u' .\} .el \m[black]\M[white]\Z'\\$1'\h'\\n[par*bxw]u'\m[]\M[] .. .\" superscript .ds par@sup-start \v'-.9m\s'\En[.s]*7u/10u'+.7m' .als { par@sup-start .ds par@sup-end \v'-.7m\s0+.9m' .als } par@sup-end .\" subscript .ds par@sub-start \v'+.3m\s'\En[.s]*7u/10u'-.1m' .als < par@sub-start .ds par@sub-end \v'+.1m\s0-.3m' .als > par@sub-end .\" footnote paragraphs .fn@init .\" FR is the ratio of footnote (horizontal) length to the line length .ds FR 11/12 .\" FF is the footnote format .nr FF 0 .\" This can be redefined. It gets a second argument of 'no' if the .\" first argument was supplied by the user, rather than automatically. .de FP .br .if !d par*fp!\\n[FF] \{\ . @error unknown footnote format '\\n[FF]' . nr FF 0 .\} .ie '\\$2'no' .par*fp!\\n[FF]-no "\\$1" .el .par*fp!\\n[FF] "\\$1" .. .de par*fp!0 .@PP \&\\*[fn@mark-start]\\$1\\*[fn@mark-end]\ \c .. .de par*fp!0-no .@PP \&\\$1\ \c .. .de par*fp!1 .@PP \&\\$1.\ \c .. .de par*fp!1-no .@PP \&\\$1\ \c .. .de par*fp!2 .@LP \&\\$1.\ \c .. .de par*fp!2-no .@LP \&\\$1\ \c .. .de par*fp!3 .@IP "\\$1." (u;\\n[\\n[.ev]:PI]*2) .. .de par*fp!3-no .@IP "\\$1" (u;\\n[\\n[.ev]:PI]*2) .. .\" *************************** .\" ******** module nh ******** .\" *************************** .\" Numbered headings. .\" nh*hl is the level of the last heading .nr nh*hl 0 .\" SN-DOT and SN-NO-DOT represent the section number of .\" the current heading, with and without a terminating dot. .ds SN-DOT .ds SN-NO-DOT .\" SN-STYLE sets the statement numbering style used in headings .\" (either SN-DOT or SN-NO-DOT); for backward compatibility with .\" earlier ms versions, the default is SN-DOT .als SN-STYLE SN-DOT .\" Also for backward compatibility, let SN represent SN-DOT. .als SN SN-DOT .\" numbered heading .de @NH .ie '\\$1'S' \{\ . shift . nr nh*hl 0 . while \\n[.$] \{\ . nr nh*hl +1 . nr H\\n[nh*hl] 0\\$1 . shift . \} . if !\\n[nh*hl] \{\ . nr H1 1 . nr nh*hl 1 . @error missing arguments to .NH S . \} .\} .el \{\ . nr nh*ohl \\n[nh*hl] . ie \\n[.$] \{\ . nr nh*hl 0\\$1 . ie \\n[nh*hl]<=0 \{\ . nr nh*ohl 0 . nr nh*hl 1 . \} . el \{\ . if \\n[nh*hl]-\\n[nh*ohl]>1 \{\ . ds nh*msg .NH \\n[nh*ohl] followed by\" . as nh*msg " .NH \\n[nh*hl]\" . @warning \\*[nh*msg] . rm nh*msg . \} . \} . \} . el .nr nh*hl 1 . while \\n[nh*hl]>\\n[nh*ohl] \{\ . nr nh*ohl +1 . nr H\\n[nh*ohl] 0 . \} . nr H\\n[nh*hl] +1 .\} .ds SN-NO-DOT \\n(H1 .nr nh*i 1 .while \\n[nh*i]<\\n[nh*hl] \{\ . nr nh*i +1 . as SN-NO-DOT .\\n[H\\n[nh*i]] .\} .ds SN-DOT \\*[SN-NO-DOT]. .nr sh*psincr (\\n[GROWPS]-\\n[nh*hl])*\\n[PSINCR] .SH-NO-TAG .DEVTAG-NH "\\$1" .if '\*(.T'html' .nr s@devtag-needs-end-of-heading 1 \\*[SN-STYLE] .. .\" **************************** .\" ******** module toc ******** .\" **************************** .\" Table of contents generation. .de @XS .da toc*div .ev h .ie \\n[.$] .XA "\\$1" .el .XA .. .de @div-end!toc*div .XE .. .de XA .ie '\\n(.z'toc*div' \{\ . if d toc*num .toc*end-entry . ie \\n[.$] \{\ . ie '\\$1'no' .ds toc*num \" empty . el .ds toc*num "\\$1 . \} . el .ds toc*num \\n[%]\" . br . par@reset . na . in (n;0\\$2) .\} .el .@error .XA without .XS .. .de XE .ie '\\n(.z'toc*div' \{\ . if d toc*num .toc*end-entry . ev . di .\} .el .@error .XE without .XS .. .\" Rudimentary integration of TOC generation with SH and NH; .\" (called by XH and XN respectively, to capture heading text .\" for reuse as TOC entry); may be redefined, to achieve more .\" sophisticated TOC layout effects. .\" .\" No-op initializers are called by XH and XN respectively, .\" before XH-UPDATE-TOC is called; if XH-UPDATE-TOC has been .\" redefined, then it may also be necessary to redefine either, .\" or both of these, to perform any initialization specific .\" to use after SH and NH respectively. .de XH-INIT de .de XN-INIT .. .de XH-UPDATE-TOC .\" .XH-UPDATE-TOC .XS .in (\\$1u - 1u * 2n) .shift \&\\$* .XE .. .\" Rudimentary integration hook, to be called (nominally) .\" after SH, but acceptable in any body-text context .de XH de .\" .XH .rn XH-REPLACEMENT XH .XH \\$@ .de XH-REPLACEMENT .XH-INIT .XH-UPDATE-TOC \\$@ .shift \&\\$* .. .\" Rudimentary integration hook, to be called after NH .de XN de .\" .XN .ie \\n[nh*hl] .toc*xn-init \\$@ .el \{\ . @error .XN is not allowed before .NH . nop \&\\$* .\} .de toc*xn-init de .rn XN-REPLACEMENT XN .XN \\$@ .rm \\$0 .de XN-REPLACEMENT .XN-INIT .XH-UPDATE-TOC \\n[nh*hl] \\$@ \&\\$* .. .de toc*end-entry .if !'\\*[toc*num]'' \\a\\t\\*[toc*num] .br .rm toc*num .. .de PX .1C .if !'\\$1'no' \{\ . ce 1 . ie (\\n[PS] >= 1000) \ . ps ((\\n[PS]z / 1000u) + 2z) . el \ . ps \\n[PS]+2 . ft B \\*[TOC] . ft . ps .\} .nf .if !r TC-MARGIN .nr TC-MARGIN \w'000' .if !c \[TC-LEADER] .char \[TC-LEADER] .\h'1m' .ta (u;\\n[.l]-\\n[.i]-\\n[TC-MARGIN]) (u;\\n[.l]-\\n[.i])R .lc \[TC-LEADER] .sp 2 .toc*div .par@reset .. .\" print the table of contents on page i .de TC .P1 .pg@begin 1 i .PX \\$1 .. .\" **************************** .\" ******** module eqn ******** .\" **************************** .\" Eqn support. .de EQ .. .de EN .. .de @EQ .if \\n[tbl@within-table] \ . @error .EQ is not allowed within a .TS/.TE table .br .ds eqn*num "\\$2 .ie '\\$1'L' .nr eqn*type 0 .el \{\ . ie '\\$1'I' .nr eqn*type 1 . el \{\ . nr eqn*type 2 . if !'\\$1'C' .ds eqn*num "\\$1 . \} .\} .di eqn*div .in 0 .if '\*(.T'html' \{\ . nr eqn*ll \\n[.l] . ll 1000n .\} .if \\n[eqn*type]=0 .EQN-HTML-IMAGE-LEFT .if \\n[eqn*type]=1 \{\ . if '\*(.T'html' .RS .EQN-HTML-IMAGE-INLINE .\} .if \\n[eqn*type]=2 .EQN-HTML-IMAGE .nf .. .de @div-end!eqn*div .@EN .. .\" Note that geqn mark and lineup work correctly in centered equations. .de @EN .ie !'\\n(.z'eqn*div' .@error-recover mismatched .EN .el \{\ . br . di . nr eqn*have-num 0 . if !'\\*[eqn*num]'' .nr eqn*have-num 1 . ie \\n[dl]:\\n[eqn*have-num] \{\ . sp \\n[DD]u . ns . par@reset . ds eqn*tabs \\n[.tabs] . nf . ie \\n[dl] \{\ .\" XXX: This really should not be necessary and .\" indicates that there is extra space creeping .\" into an equation when ps4html is enabled. . ie r ps4html .ds@need \\n[dn]u-1v+\n[.V]u+1i . el .ds@need \\n[dn]u-1v+\n[.V]u . chop eqn*div . ie \\n[eqn*type]=0 \{\ . ta (u;\\n[.l]-\\n[.i])R \\*[eqn*div]\t\\*[eqn*num] . \} . el \{\ . ie \\n[eqn*type]=1 .ta \\n[DI]u \ (u;\\n[.l]-\\n[.i])R . el .ta (u;\\n[.l]-\\n[.i]/2)C \ (u;\\n[.l]-\\n[.i])R \t\\*[eqn*div]\t\\*[eqn*num] . \} . \} . el \{\ . ta (u;\\n[.l]-\\n[.i])R \t\\*[eqn*num] . \} .\". if !'\*(.T'html' .sp \\n[DD]u . sp \\n[DD]u . ns . ta \\*[eqn*tabs] . \} . el \{\ .\" must terminate empty equations in html and ps4html as they contain .\" the EQN-HTML-IMAGE-END suppression nodes . if \\n[dl] .chop eqn*div . if '\*(.T'html' \\*[eqn*div] . if r ps4html \\*[eqn*div] . \} . if !'\*(.T'html' .fi . if \\n[eqn*type]=0 .EQN-HTML-IMAGE-END . if \\n[eqn*type]=1 \{\ . EQN-HTML-IMAGE-END . if '\*(.T'html' .RE . \} . if \\n[eqn*type]=2 .EQN-HTML-IMAGE-END . if '\*(.T'html' \ . ll \\n[eqn*ll]u .\} .. . .\" **************************** .\" ******** module tbl ******** .\" **************************** .\" Tbl support. .nr tbl@within-table 0 .nr tbl*have-header 0 .\" This gets called if TS occurs before the first paragraph. .de TS .LP .\" cov*ab-init, called by LP, aliases TS to @TS. \\*[TS]\\ .. .de @TS .nr tbl@within-table 1 .sp \\n[DD]u .if '\\$1'H' \{\ . ds tbl*stem .TS H table inside\" . ie '\\n[.z]'kp@div' .@warning \\*[tbl*stem] .KS/.KE keep . el .if '\\n[.z]'kp@fdiv' \ . @warning \\*[tbl*stem] .KF/.KE floating keep . rm tbl*stem . di tbl*header-div .\} .if '\*(.T'html' \{\ . nr tbl*ll \\n[.l] . ll 1000n .\} .HTML-IMAGE .. .de tbl@top-hook .if \\n[tbl*have-header] \{\ . ie \\n[.t]-\\n[tbl*header-ht]-1v .tbl*print-header . el .sp \\n[.t]u .\} .. .de tbl*print-header .ev nf .tbl*header-div .ev .mk #T .. .de TH .ie '\\n[.z]'tbl*header-div' \{\ . nr T. 0 . T# . br . di . \" A table with repeating headings requires enough room for them . \" and then at least one more vee for a row of data. . ie \\n[dn]+1v>=(\\n[.p]-\\n[FM]-\\n[HM]) \{\ . ds tbl*err .TH repeating table heading(s) do not fit in . as tbl*err " page area; formatting only once . @error \\*[tbl*err] . rm tbl*err . ds@need \\n[dn] . tbl*print-header . \} . el \{\ . nr tbl*header-ht \\n[dn] . ds@need \\n[dn]u+1v . tbl*print-header . nr tbl*have-header 1 . \} .\} .el .@error-recover .TH without .TS H .. .de @div-end!tbl*header-div .TH .TE .. .de TE .ie '\\n(.z'tbl*header-div' .@error-recover .TS H but no .TH before .TE .el \{\ . nr tbl*have-header 0 . if !'\*(.T'html' \{\ . sp \\n[DD]u . ns . \} .\} .HTML-IMAGE-END .if '\*(.T'html' \ . ll \\n[tbl*ll]u .\" reset tabs .TA .nr tbl@within-table 0 .. .de tbl@bottom-hook .if \\n[tbl*have-header] \{\ . nr T. 1 . T# .\} .. .de T& .. .\" **************************** .\" ******** module pic ******** .\" **************************** .\" Pic support. .\" This gets called if PS occurs before the first paragraph. .de PS .LP .\" cov*ab-init, called by LP, aliases PS to @PS. \\*[PS]\\ .. .\" @PS height width .de @PS .br .sp \\n[DD]u .ie !\\n[.$]=2 \{\ . ds pic*msg .PS: expected 2 arguments, got \\n[.$]\" . as pic*msg ; not preprocessed with pic?\" . @error \\*[pic*msg] . rm pic*msg .\} .el \{\ . ds@need (u;\\$1)+1v . in +(u;\\n[.l]-\\n[.i]-\\$2/2>?0) .\} .HTML-IMAGE .. .de PF .HTML-IMAGE-END .par@reset .. .de PE .PF .sp \\n[DD]u+.5m .. .\" **************************** .\" ******** module ref ******** .\" **************************** .\" Refer support. .mso refer-ms.tmac .\" **************************** .\" ******** module acc ******** .\" **************************** .\" Accents and special characters. .ds Q \(lq .ds U \(rq .ds - \(em .\" Characters .\" Accents .de acc*over-def .ds \\$1 \Z'\v'(u;\w'x'*0+\En[rst]-\En[.cht])'\ \h'(u;-\En[skw]+(-\En[.w]-\w'\\$2'/2)+\En[.csk])'\\$2' .. .de acc*under-def .ds \\$1 \Z'\v'\En[.cdp]u'\h'(u;-\En[.w]-\w'\\$2'/2)'\\$2' .. .de acc*slash-def .ds \\$1 \Z'\h'(u;-\En[.w]-\w'\\$2'/2)'\ \v'(u;\En[.cdp]-\En[.cht]+\En[rst]+\En[rsb]/2)'\\$2' .. .de acc*prefix-def .ds \\$1 \Z'\h'(u;\w'x'-\w'\\$2'/2)'\\$2' .. .acc*prefix-def ' \' .acc*prefix-def ` \` .acc*prefix-def ^ ^ .acc*prefix-def , \(ac .acc*prefix-def : \(ad .acc*prefix-def ~ ~ .\" improved accent marks .de AM .acc*over-def ' \' .acc*over-def ` \` .acc*over-def ^ ^ .acc*over-def ~ ~ .acc*over-def : \(ad .acc*over-def v \(ah .acc*over-def _ \(a- .acc*over-def o \(ao .acc*under-def , \(ac .acc*under-def . \s[\En[.s]*8u/10u]\v'.2m'.\v'-.2m'\s0 .acc*under-def hook \(ho .acc*slash-def / / .char \[hooko] o\E*[hook] .ds q \[hooko] .\" The idea of this definition is for the top of the 3 to be at the .\" x-height. .if !c\[yogh] .char \[yogh] \Z'\v'\w'x'*0-\En[rst]u'\s[\En[.s]*8u/10u]\ \v'\w'3'*0+\En[rst]u'3\s0'\h'\w'\s[\En[.s]*8u/10u]3'u' .ds 3 \[yogh] .ds D- \(-D\" Icelandic uppercase eth .ds d- \(Sd\" Icelandic lowercase eth .ds Th \(TP\" Icelandic uppercase thorn .ds th \(Tp\" Icelandic lowercase thorn .ds 8 \(ss\" German double s .ds Ae \(AE\" AE ligature .ds ae \(ae\" ae ligature .ds Oe \(OE\" OE ligature .ds oe \(oe\" oe ligature .ds ? \(r?\" upside down ? .ds ! \(r!\" upside down ! .. .de CHECK-FOOTER-AND-KEEP .if '\*(.T'html' \{\ . rm KF . als KF KS . . rm FS . de FS . sp . HTML-NS \\.. . rm FE . de FE . HTML-NS . sp \\.. .\} .. .par@load-init .\" Local Variables: .\" mode: nroff .\" fill-column: 72 .\" End: .\" vim: set filetype=groff textwidth=72: