summaryrefslogtreecommitdiffstats
path: root/contrib/sboxes
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/sboxes')
-rw-r--r--contrib/sboxes/ChangeLog202
-rw-r--r--contrib/sboxes/msboxes.ms.in272
-rw-r--r--contrib/sboxes/notquine.sed18
-rw-r--r--contrib/sboxes/sboxes.am74
-rw-r--r--contrib/sboxes/sboxes.tmac147
5 files changed, 713 insertions, 0 deletions
diff --git a/contrib/sboxes/ChangeLog b/contrib/sboxes/ChangeLog
new file mode 100644
index 0000000..4d56984
--- /dev/null
+++ b/contrib/sboxes/ChangeLog
@@ -0,0 +1,202 @@
+2023-02-18 G. Branden Robinson <g.branden.robinson@gmail.com>
+
+ * sboxes.am (uninstall_sboxes): Clean more fastidiously; try to
+ remove the configured `sboxespdfdocdir` in the event it is
+ empty, but do not fail if it isn't. (It can be a directory
+ shared with other groff components; we don't know in what order
+ the uninstall targets will serialize, but the last one run
+ should succeed.)
+
+2022-10-23 G. Branden Robinson <g.branden.robinson@gmail.com>
+
+ * sboxes.tmac: Escape newline after opening conditional block.
+
+2022-05-20 G. Branden Robinson <g.branden.robinson@gmail.com>
+
+ * sboxes.am: Rename `BUILD_PDFDOC` to `USE_GROPDF`.
+
+2022-05-01 G. Branden Robinson <g.branden.robinson@gmail.com>
+
+ * sboxes.am ($(sboxes_builddir)/msboxes.pdf): Depend on new name
+ for devpdf stamp file.
+
+2022-04-03 Ingo Schwarze <schwarze@openbsd.org>
+
+ * sboxes.am: msboxes.ms is documentation, not merely an example.
+ Consequently, install msboxes.ms unconditionally and msboxes.pdf
+ if BUILD_PDFDOC is enabled, both to the documentation directory
+ rather than to the examples directory.
+
+2022-04-02 Ingo Schwarze <schwarze@openbsd.org>
+
+ * sboxes.am: Stop installing msboxes.ms.in;
+ installing msboxes.ms and msboxes.pdf is enough.
+
+2022-03-29 G. Branden Robinson <g.branden.robinson@gmail.com>
+
+ * sboxes.am: Track rename of `DOC_GROFF_ONLY` to `DOC_GROFF`.
+
+2022-03-29 G. Branden Robinson <g.branden.robinson@gmail.com>
+
+ * msboxes.ms.in: Tweak sboxes documentation to imply ms
+ dependency.
+
+ Fixes <https://savannah.gnu.org/bugs/?62062>.
+
+2022-03-22 Ingo Schwarze <schwarze@openbsd.org>
+
+ * sboxes.am: fix non-portable syntax in the msboxes.pdf target
+ by using DOC_GROFF_ONLY rather than DOC_GROFF in order to not
+ use $< outside a suffix rule; DOC_GROFF functionality is not
+ needed here in the first place.
+
+2022-03-22 Ingo Schwarze <schwarze@openbsd.org>
+
+ * sboxes.am: make the build of msboxes.{ms,pdf} work with BSD
+ make by using $(sboxes_builddir) consistently to prevent
+ variations in target names.
+
+2022-02-06 G. Branden Robinson <g.branden.robinson@gmail.com>
+
+ * sboxes.tmac: Prefix early diagnostics with package file name
+ literally. (We don't yet know if we can use \*[] string
+ interpolation.) It is better to violate DRY a little here than
+ to obscure from the user what is emitting the diagnostic.
+
+2022-02-06 G. Branden Robinson <g.branden.robinson@gmail.com>
+
+ * sboxes.tmac: Skip macro package instead of aborting if there
+ are prerequisite problems. This is an auxiliary package; it is
+ not necessarily fatal to the user's purposes if it doesn't load.
+
+2022-02-06 G. Branden Robinson <g.branden.robinson@gmail.com>
+
+ * notquine.sed: Convert tilde to special character when inlining
+ document source (\~ is used).
+
+2021-11-01 G. Branden Robinson <g.branden.robinson@gmail.com>
+
+ * msboxes.ms.in: Retitle document to "Using PDF Boxes with
+ _groff and_ the ms macros" (emphasis added) to make it clearer
+ that this package does not _require_ ms.
+
+2021-10-27 G. Branden Robinson <g.branden.robinson@gmail.com>
+
+ * notquine.sed: Improve portability and tighten logic. Thanks
+ to Axel Kielhorn for the report and Andreas Kusalananda Kähäri
+ for the suggested improvements.
+
+2021-10-24 G. Branden Robinson <g.branden.robinson@gmail.com>
+
+ * sboxes.tmac: Rename strings and macro I introduced so that
+ they fit Deri's selection within the name space (prefix "bx").
+ Rename existing macros to use the groff ms(7) naming convention.
+ None of the macros in this "module" seem meant to be visible to
+ other modules, so suffix the module name with '*' instead of
+ '@'. Drop unused 7th argument in a `pdfbackground` call.
+
+2021-10-24 G. Branden Robinson <g.branden.robinson@gmail.com>
+
+ * sboxes.tmac: Define GSBOX register as 0, then redefine it as 1
+ only if the output device is `pdf`. (This way a document author
+ can easily and separately test the presence of the package and
+ whether the device-specific feature is likely to work.)
+ (pdfbackground): Only define (overriding `pdf.tmac`) if GSBOX is
+ false.
+ * msboxes.ms.in: Document this aspect of the package interface.
+
+2021-10-21 G. Branden Robinson <g.branden.robinson@gmail.com>
+
+ * sboxes.am (SBOXES_FLAGS): Drop variable since we only expand
+ it in one place.
+ ($(sboxes_builddir)/msboxes.pdf): Be more consistent with the
+ rest of our build, particularly documentation generated in the
+ groff `doc` directory. Use `GROFF_V` instead of `AM_V_GEN` to
+ control output (since it is in fact groff producing the target).
+ Use `DOC_GROFF` to produce the document rather than
+ `test-groff`. Use the former `SBOXES_FLAGS` here.
+
+2021-10-20 G. Branden Robinson <g.branden.robinson@gmail.com>
+
+ * sboxes.am ($(sboxes_builddir)/msboxes.ms,
+ $(sboxes_builddir)/msboxes.pdf): Be quieter by default; use
+ $(AM_V_at) and $(AM_V_GEN) more consistently with the rest of
+ the build.
+
+2021-10-17 G. Branden Robinson <g.branden.robinson@gmail.com>
+
+ * sboxes.tmac: Rename macros to get out of user name space. Our
+ ms package documentation says that externally visible names will
+ consist only of uppercase letters and digits.
+ (BoxStart): Rename to BOXSTART.
+ (BoxStop): Rename to BOXSTOP.
+ * msboxes.ms.in: Document and use new names.
+
+2021-10-17 G. Branden Robinson <g.branden.robinson@gmail.com>
+
+ * sboxes.tmac: Add more prerequisite checking. Check `GS`
+ register for groff ms macros specifically. Check installed
+ version of groff since the gropdf in earlier versions won't
+ implement the underlying feature. Add new string to introduce
+ diagnostic messages now that we have more than one (that we can
+ emit without limp-along AT&T compatibility mode).
+ (sboxes*error): Use new string in diagnostic message.
+
+2021-10-17 G. Branden Robinson <g.branden.robinson@gmail.com>
+
+ * sboxes.tmac (sboxes*error): Add new macro to produce
+ diagnostic message in a standard format.
+ (BoxStart): Use it.
+
+2021-10-17 G. Branden Robinson <g.branden.robinson@gmail.com>
+
+ Make msboxes.ms quote its own source through a
+ self-interpolation process (with help from sed and the build
+ system), avoiding the need to manually keep the source document
+ and its quoted form in sync.
+
+ * msboxes.ms: Rename to...
+ * msboxes.ms.in: ...this.
+ * notquine.sed: New file; this sed script performs quotation of
+ roff syntax characters (and hyphens), inserts the quoted form of
+ the document's source into itself, and reproduces Deri's
+ Schrödinger's footnote trick.
+ * sboxes.am: Introduce new variables `sboxes_builddir` and
+ `sboxesnotquine` for convenience. Update value of
+ $(SBOXES_EXAMPLEFILES) to point to the new .in source file. Add
+ the generated ms document to $(SBOXES_PROCESSEDEXAMPLEFILES) and
+ $(MOSTLYCLEANFILES). Add the `notquine` sed script to the
+ distribution archive via $(EXTRA_DIST).
+ ($(sboxes_builddir)/msboxes.ms): New rule produces the ms
+ document from msboxes.ms.in, constructing it with sed.
+ ($(sboxes_builddir)/msboxes.pdf): Update rule to add dependency
+ on source document, use new `sboxes_builddir` variable, and look
+ for source document in the build tree instead of the source.
+
+2021-10-17 G. Branden Robinson <g.branden.robinson@gmail.com>
+
+ * sboxes.am: Add this ChangeLog to `EXTRA_DIST`.
+
+2021-10-11 G. Branden Robinson <g.branden.robinson@gmail.com>
+
+ * sboxes.am (MOSTLYCLEANFILES): Add
+ `$(SBOXES_PROCESSEDEXAMPLEFILES)`; allows `distcheck` target to
+ succeed.
+
+________________________________________________________________________
+
+##### License
+
+Copyright 2021 Free Software Foundation, Inc.
+
+Copying and distribution of this file, with or without modification,
+are permitted in any medium without royalty provided the copyright
+notice and this notice are preserved.
+
+##### Editor settings
+Local Variables:
+fill-column: 72
+mode: change-log
+version-control: never
+End:
+vim:set autoindent textwidth=72:
diff --git a/contrib/sboxes/msboxes.ms.in b/contrib/sboxes/msboxes.ms.in
new file mode 100644
index 0000000..a1700df
--- /dev/null
+++ b/contrib/sboxes/msboxes.ms.in
@@ -0,0 +1,272 @@
+.\" groff -ms -msboxes -Tpdf
+.nr LL 17c
+.nr PO 2c
+.nr PS 11
+.nr VS 13
+.nr PI 3.5n
+.nr HM 2c
+.nr FM 2c
+.nr QI 7n
+.ss 12 0
+.ND March 2021
+.EH '%''March 2021'
+.EF ''''
+.OH 'Using PDF boxes with \f[I]groff\f[] and the \f[I]ms\f[] macros''%'
+.OF ''''
+.\" Define a quotation macro.
+.de Qq
+. nop \[lq]\\$1\[rq]\\$2
+..
+.\" Define a macro for code literals; use bold and disable hyphenation.
+.de Lt
+. ft B
+. nh
+. nop \&\\$1\c
+. hy \\n[HY]
+. ft
+. nop \&\\$2
+..
+.ds FAM H
+.TL
+Using PDF boxes with
+.BI groff
+and the
+.BI ms
+macros
+.AU
+Deri James
+.AI
+deri@chuzzlewit.myzen.co.uk
+.LP
+An extension in version 1.23.0 of
+.I gropdf ,
+the PDF output driver for the
+.I groff
+document formatting system,
+allows coloured rectangles to be placed beneath any output created by
+.I groff .
+The extension can be accessed via a device control escape sequence
+.Lt "\[rs]X\[aq]pdf: background" \~.\|.\|.\|\c
+.Lt \[aq]
+or a convenience macro
+.Lt pdfbackground
+supporting the same parameters.
+.QS
+.BOXSTART SHADED cornsilk OUTLINED brown INDENT 2n WEIGHT 1p
+\M[floralwhite]\c
+.pdfbackground pagefill
+\M[]\c
+.B
+\[rs]X\[aq]pdf: background
+.BI
+cmd left top right bottom weight\[aq]
+.br
+.Lt .pdfbackground
+.BI
+cmd left top right bottom weight
+.LP
+each produce a background rectangle on the page, where
+.IP \f[I]cmd 8n \" indent enough to fit "bottom" tag
+is the command, which can be any of
+.Qq page|fill|box
+in combination.
+Thus,
+.Qq pagefill
+would draw a rectangle which covers the whole current page size (in
+which case the rest of the parameters can be omitted because the box
+dimensions are taken from the current media size).
+.Qq boxfill ,
+on the other hand, requires the given dimensions to place the box.
+Including
+.Qq fill
+in the command will paint the rectangle with the current fill colour (as
+with
+.Lt \[rs]M[] )
+and including
+.Qq box
+will give the rectangle a border in the current stroke colour
+(as with
+.Lt \[rs]m[] ).
+.sp \n[PD]u
+.I cmd
+may also be
+.Qq off
+on its own, which will terminate drawing the current box.
+If you have specified a page colour with
+.Qq pagefill ,
+it is always the first box in the stack, and if you specify it again, it
+will replace the first entry.
+Be aware that the
+.Qq pagefill
+box renders the page opaque, so tools that
+.Qq watermark
+PDF pages are unlikely to be successful.
+To return the background to transparent, issue an
+.Qq off
+command with no other boxes open.
+.sp \n[PD]u
+Finally,
+.I cmd
+may be
+.Qq footnote
+followed by a new value for
+.I bottom ,
+which will be used for all open boxes on the current page.
+This is to allow room for footnote areas that grow while a page is
+processed (to accommodate multiple footnotes,
+for instance).\m[red]\**\m[]\" FOOTNOTE
+.FS
+If the value is negative, it is used as an offset from the bottom of the
+page.
+.FE
+.nr oldPD \n[PD]
+.nr PD 0
+.IP \f[I]left
+.IP \f[I]top
+.IP \f[I]right
+.IP \f[I]bottom
+.nr PD \n[oldPD]
+are the coordinates of the box.
+The
+.I top
+and
+.I bottom
+coordinates are the minimum and maximum for the box, since the actual
+start of the box is
+.I groff 's
+drawing position when you issue the command, and the bottom of the box
+is the point where you turn the box
+.Qq off .
+The top and bottom coordinates are used only if the box drawing extends
+onto the next page; ordinarily, they would be set to the header and
+footer margins.
+.IP \f[I]weight
+provides the line width for the border if
+.Qq box
+is included in the command.
+.BOXSTOP
+.QE
+For an even more convenient interface, include
+.Lt \-msboxes
+on the
+.I groff
+command line; the
+.I sboxes
+package defines the macros
+.Lt BOXSTART
+and
+.Lt BOXSTOP .
+.QS
+.BOXSTART SHADED cornsilk OUTLINED brown INDENT 2n WEIGHT 1p
+.BOXSTART SHADED cornsilk3 INDENT 2p
+.Lt .BOXSTART
+.Lt SHADED
+.I colour
+.Lt OUTLINED
+.I colour
+.Lt INDENT
+.I size
+.Lt WEIGHT
+.I size
+.BOXSTOP
+.LP
+begins a box,
+where the argument after
+.Lt SHADED
+gives the fill colour and that after
+.Lt OUTLINED
+the border colour.
+Omit the former to get a borderless filled box and the latter for a
+border with no fill.
+The specified
+.Lt WEIGHT
+is used if the box is
+.Lt OUTLINED .
+.LP
+.Lt INDENT
+precedes a value which leaves a gap between the border and the contents
+inside the box.
+.LP
+Each
+.I colour
+must be a defined
+.I groff
+colour name,
+and each
+.I size
+a valid
+.I groff
+numeric expression.
+The keyword/value pairs can be specified in any order.
+.BOXSTOP
+.QE
+Boxes can be stacked, so you can start a box within another box; usually
+the later boxes would be smaller than the containing box, but this is
+not enforced.
+When using
+.Lt BOXSTART ,
+the left position is the current indent minus the
+.Lt INDENT
+in the command,
+and the right position is the left position (calculated above) plus the
+current line length and twice the indent.
+The synopsis of
+.Lt BOXSTART
+above itself uses a
+.Lt BOXSTART
+call without borders and with a
+.Lt 2p
+(two point) indent.
+.QS
+.BOXSTART SHADED cornsilk OUTLINED brown INDENT 2n WEIGHT 1p
+.BOXSTART SHADED cornsilk3 INDENT 2p
+.Lt .BOXSTOP
+.BOXSTOP
+.LP
+takes no parameters.
+It closes the most recently started box at the current vertical position
+after adding its
+.Lt INDENT
+spacing.
+.BOXSTOP
+.QE
+Your
+.I groff
+documents can conditionally exercise the
+.I sboxes
+macros.
+The register
+.Lt GSBOX
+is defined if the package is loaded, and interpolates a true value if
+the
+.Lt pdf
+output device is in use.
+.LP
+.I sboxes
+furthermore hooks into the
+.I "groff ms"
+package to receive notifications when footnotes are growing, so that it
+can close boxes on a page before footnotes are printed.
+When that condition obtains,
+.I sboxes
+will close open boxes two points\**
+.FS
+This amount probably will not match the box's
+.Lt INDENT .
+.FE
+above the footnote separator and re-open them on the next page.
+.LP
+This document was produced using the following code.
+.ds FAM C
+.nr PS 11
+.nr VS 13
+.LP
+.BOXSTART SHADED white OUTLINED brown INDENT 2n WEIGHT 1p
+.nf
+\# REPLACEME
+.BOXSTOP
+.\" Local Variables:
+.\" mode: nroff
+.\" fill-column: 72
+.\" End:
+.\" vim: set filetype=groff textwidth=72:
diff --git a/contrib/sboxes/notquine.sed b/contrib/sboxes/notquine.sed
new file mode 100644
index 0000000..1a110ab
--- /dev/null
+++ b/contrib/sboxes/notquine.sed
@@ -0,0 +1,18 @@
+s/.*\\##.*/&\
+&/
+s/\\##//
+t
+s/\\" FOOTNOTE/@FOOTNOTE@/
+s/\\/\\[rs]/g
+s/-/\\&/g
+s/'/\\[aq]/g
+s/~/\\[ti]/g
+s/^\./\\\&&/
+/@FOOTNOTE@/a\
+.FS\
+This is a long footnote occupying multiple output lines.\
+Its only purpose is to verify that the bottom of the box on this page\
+has been adjusted upwards to accommodate it.\
+.FE
+s/@FOOTNOTE@/\\m[red]\\**\\m[]/
+s/REPLACEME/(replaced by source of this document)/
diff --git a/contrib/sboxes/sboxes.am b/contrib/sboxes/sboxes.am
new file mode 100644
index 0000000..7786337
--- /dev/null
+++ b/contrib/sboxes/sboxes.am
@@ -0,0 +1,74 @@
+# Copyright (C) 2021 Free Software Foundation, Inc.
+# Written by Bertrand Garrigues <bertrand.garrigues@laposte.net>
+#
+# 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 <http://www.gnu.org/licenses/>.
+
+sboxes_srcdir = $(top_srcdir)/contrib/sboxes
+sboxes_builddir = $(top_builddir)/contrib/sboxes
+sboxesnotquine = $(sboxes_srcdir)/notquine.sed
+
+sboxestmacdir = $(tmacdir)
+dist_sboxestmac_DATA = contrib/sboxes/sboxes.tmac
+
+EXTRA_DIST += \
+ contrib/sboxes/ChangeLog \
+ contrib/sboxes/msboxes.ms.in \
+ contrib/sboxes/notquine.sed
+
+SBOXES_EXAMPLEFILES = $(sboxes_srcdir)/msboxes.ms.in
+
+sboxesotherdocdir = $(docdir)
+nodist_sboxesotherdoc_DATA = $(sboxes_builddir)/msboxes.ms
+
+if USE_GROPDF
+sboxespdfdocdir = $(pdfdocdir)
+nodist_sboxespdfdoc_DATA = $(sboxes_builddir)/msboxes.pdf
+endif
+
+MOSTLYCLEANFILES += msboxes.ms \
+ $(nodist_sboxesotherdoc_DATA) \
+ $(nodist_sboxespdfdoc_DATA)
+
+# The ordering of the sed -e expressions is important.
+$(sboxes_builddir)/msboxes.ms: $(SBOXES_EXAMPLEFILES) $(sboxesnotquine)
+ $(AM_V_at)mkdir -p $(sboxes_builddir)
+ $(AM_V_at)$(SED) -n -e '1,/REPLACEME/p' \
+ $(SBOXES_EXAMPLEFILES) > $@.tmp
+ $(AM_V_at)$(SED) -f $(sboxesnotquine) \
+ $(SBOXES_EXAMPLEFILES) >> $@.tmp
+ $(AM_V_at)$(SED) -n -e '/REPLACEME/,$$p' \
+ $(SBOXES_EXAMPLEFILES) >> $@.tmp
+ $(AM_V_GEN)mv $@.tmp $@
+
+$(sboxes_builddir)/msboxes.pdf: $(sboxes_builddir)/msboxes.ms \
+ $(dist_sboxestmac_DATA) groff troff gropdf font/devpdf/stamp
+ $(GROFF_V)$(DOC_GROFF) -M$(sboxes_srcdir) -ms -msboxes -Tpdf \
+ $(sboxes_builddir)/msboxes.ms > $@
+
+uninstall_groffdirs: uninstall_sboxes
+uninstall_sboxes:
+ if test -d $(DESTDIR)$(exampledir)/sboxes; then \
+ rmdir $(DESTDIR)$(exampledir)/sboxes; \
+ fi
+if USE_GROPDF
+ -rmdir $(DESTDIR)$(sboxespdfdocdir)
+endif
+
+# Local Variables:
+# fill-column: 72
+# mode: makefile-automake
+# End:
+# vim: set autoindent filetype=automake textwidth=72:
diff --git a/contrib/sboxes/sboxes.tmac b/contrib/sboxes/sboxes.tmac
new file mode 100644
index 0000000..63c9263
--- /dev/null
+++ b/contrib/sboxes/sboxes.tmac
@@ -0,0 +1,147 @@
+.ig
+
+sboxes.tmac
+
+Copyright (C) 2021 Free Software Foundation, Inc.
+ Written by Deri James (deri@chuzzlewit.myzen.co.uk)
+
+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 <http://www.gnu.org/licenses/>.
+..
+.if !\n(.g \{\
+. tm sboxes.tmac: macros require groff extensions; not loading
+. nx
+.\}
+.
+.if \n(.C \{\
+. tm sboxes.tmac: macros do not work in compatibility mode; not loading
+. nx
+.\}
+.
+.\" Define a string for use in diagnostic messages.
+.ds bx*name sboxes.tmac\"
+.
+.if !r GS \
+. ab \*[bx*name]: ms macros must be loaded first; aborting
+.
+.if (\n[.x]\n[.y] < 123) \{\
+. ds bx*msg \*[bx*name]: groff 1.23 or later is required,\"
+. as bx*msg " but found groff \n[.x].\n[.y]; not loading\"
+. tm \*[bx*msg]
+. nx
+.\}
+.
+.\" See if already loaded.
+.if r GSBOX .nx
+.
+.\" GSBOX is defined if the package is loaded, and true if it will work.
+.nr GSBOX 0
+.if '\*[.T]'pdf' \
+. nr GSBOX 1
+.
+.nr bx*stack 0
+.
+.de bx*error
+. tm \*[bx*name]:\\n[.F]:\\n[.c]: error: \\$*
+..
+.
+.\" Define dummy macro if we're not formatting for the pdf device.
+.if !\n[GSBOX] \{\
+. de pdfbackground
+. .
+.\}
+.
+.\" Link into ms macros to trap footnote growth
+.am fn@print-sep
+. nr bx*pb \\n[nl]u-2p
+. nop \!x X pdf: background footnote \\n[bx*pb]z
+. rr bx*pb
+..
+.\" Has PD been actioned?
+.am par*start
+. nr bx*PD \\n[PD]
+..
+.
+.de BOXSTART
+. fl
+. nr bx*stack \\n[bx*stack]+1u
+. nr bx*shad 0
+. nr bx*outl 0
+. nr bx*ind 1P
+. ds bx*wt 0
+. ds bx*type "\"
+. while \\n[.$] \{\
+. ie 'SHADED'\\$1' \{\
+. nop \\M[\\$2]\c
+. nr bx*shad 1
+. as bx*type "fill\"
+. shift 2
+. \}
+. el \{\
+. ie 'OUTLINED'\\$1' \{\
+. nop \\m[\\$2]\c
+. nr bx*outl 1
+. as bx*type "box\"
+. shift 2
+. \}
+. el \{\
+. ie 'WEIGHT'\\$1' \{\
+. ds bx*wt \\$2
+. shift 2
+. \}
+. el \{\
+. ie 'INDENT'\\$1' \{\
+. nr bx*ind \\$2
+. shift 2
+. \}
+. el \{\
+. bx*error ignoring unrecognized BOXSTART parameter '\\$1'
+. shift
+. \}
+. \}
+. \}
+. \}
+. \}
+.
+. if '\\*[bx*type]'' .ds bx*type "fill"
+. nr bx*l \\n[\\n[.ev]:li]s+\\n[.o]s-\\n[bx*ind]u
+. nr bx*r \\n[bx*l]u+\\n[.l]-\\n[\\n[.ev]:li]+(\\n[bx*ind]u*2u)
+. nr bx*gap \\n[.v]-\\n[.ps]+\\*[bx*wt]
+. nr bx*bot \\n[.p]u-\\n[FM]u+\\n[bx*ind]u+\\n[.ps]u
+. nr bx*top \\n[HM]-\\n[bx*ind]u+\\n[bx*gap]u
+. ne \\n[bx*ind]u+2v+\\*[bx*wt]
+. sp -(2v-(\\n[bx*PD]u*2u))u
+. pdfbackground \\*[bx*type] \\n[bx*l]z \\n[bx*top]z \
+ \\n[bx*r]z \\n[bx*bot]z \
+ \\*[bx*wt]
+. sp (\\n[bx*ind]u-1v)u
+. if (\\n[bx*shad]=1) .nop \\M[]\c
+. if (\\n[bx*outl]=1) .nop \\m[]\c
+. ds bx*ind\\n[bx*stack] \\n[bx*ind]
+. rr bx*shad bx*outl bx*ind bx*bot bx*top bx*l bx*r
+. rm wt type
+. sp -(\\n[bx*gap]u)
+. nr bx*PD 0
+..
+.de BOXSTOP
+. sp \\*[bx*ind\\n[bx*stack]]u-\\n[.psr]u
+. pdfbackground off
+. nr bx*stack \\n[bx*stack]-1u
+..
+.\" Local Variables:
+.\" mode: nroff
+.\" fill-column: 72
+.\" End:
+.\" vim: set expandtab filetype=groff textwidth=72: