summaryrefslogtreecommitdiff
path: root/macros/plain
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2020-07-18 03:01:08 +0000
committerNorbert Preining <norbert@preining.info>2020-07-18 03:01:08 +0000
commit63c4f21a5716ebbed11926d0bfbb26d656a766ea (patch)
treec02159e6ceb2453208664129ccda8ff306147328 /macros/plain
parent4ea983e3d411ade406c09b30ece9139457516b6f (diff)
CTAN sync 202007180301
Diffstat (limited to 'macros/plain')
-rw-r--r--macros/plain/contrib/zztex/README17
-rw-r--r--macros/plain/contrib/zztex/doc/zzbuiltin.dat325
-rw-r--r--macros/plain/contrib/zztex/doc/zzdetails.dat1597
-rw-r--r--macros/plain/contrib/zztex/doc/zzphrase.dat3085
-rw-r--r--macros/plain/contrib/zztex/doc/zzplain.dat1315
-rw-r--r--macros/plain/contrib/zztex/tex/zzart.tex611
-rw-r--r--macros/plain/contrib/zztex/tex/zzbiblio.tex427
-rw-r--r--macros/plain/contrib/zztex/tex/zzbibtex.tex290
-rw-r--r--macros/plain/contrib/zztex/tex/zzblock.tex327
-rw-r--r--macros/plain/contrib/zztex/tex/zzcmmath.tex15
-rw-r--r--macros/plain/contrib/zztex/tex/zzcomenc.tex153
-rw-r--r--macros/plain/contrib/zztex/tex/zzdiv.tex128
-rw-r--r--macros/plain/contrib/zztex/tex/zzdoc.tex500
-rw-r--r--macros/plain/contrib/zztex/tex/zzerror.tex123
-rw-r--r--macros/plain/contrib/zztex/tex/zzfloat.tex1164
-rw-r--r--macros/plain/contrib/zztex/tex/zzfont.tex453
-rw-r--r--macros/plain/contrib/zztex/tex/zzfront.tex247
-rw-r--r--macros/plain/contrib/zztex/tex/zzhelp.tex359
-rw-r--r--macros/plain/contrib/zztex/tex/zzhmode.tex924
-rw-r--r--macros/plain/contrib/zztex/tex/zzhmodeb.tex239
-rw-r--r--macros/plain/contrib/zztex/tex/zzhyper.tex185
-rw-r--r--macros/plain/contrib/zztex/tex/zzhyph.tex128
-rw-r--r--macros/plain/contrib/zztex/tex/zzindexv1.tex379
-rw-r--r--macros/plain/contrib/zztex/tex/zzindexv2.tex448
-rw-r--r--macros/plain/contrib/zztex/tex/zzio.tex84
-rw-r--r--macros/plain/contrib/zztex/tex/zzlist.tex163
-rw-r--r--macros/plain/contrib/zztex/tex/zzltrspc.tex111
-rw-r--r--macros/plain/contrib/zztex/tex/zzlucida.tex140
-rw-r--r--macros/plain/contrib/zztex/tex/zzmath.tex1919
-rw-r--r--macros/plain/contrib/zztex/tex/zzmathv3.tex123
-rw-r--r--macros/plain/contrib/zztex/tex/zzmathv4.tex129
-rw-r--r--macros/plain/contrib/zztex/tex/zzmathv5.tex129
-rw-r--r--macros/plain/contrib/zztex/tex/zzmathv6.tex180
-rw-r--r--macros/plain/contrib/zztex/tex/zzmerge.tex70
-rw-r--r--macros/plain/contrib/zztex/tex/zzmisc.tex292
-rw-r--r--macros/plain/contrib/zztex/tex/zzmtime.tex89
-rw-r--r--macros/plain/contrib/zztex/tex/zznewmath.tex93
-rw-r--r--macros/plain/contrib/zztex/tex/zznote.tex522
-rw-r--r--macros/plain/contrib/zztex/tex/zzoverlay.tex100
-rw-r--r--macros/plain/contrib/zztex/tex/zzpage.tex908
-rw-r--r--macros/plain/contrib/zztex/tex/zzplain.tex71
-rw-r--r--macros/plain/contrib/zztex/tex/zzprog.tex228
-rw-r--r--macros/plain/contrib/zztex/tex/zzps.tex251
-rw-r--r--macros/plain/contrib/zztex/tex/zzreg.tex437
-rw-r--r--macros/plain/contrib/zztex/tex/zzrunner.tex98
-rw-r--r--macros/plain/contrib/zztex/tex/zzsect.tex806
-rw-r--r--macros/plain/contrib/zztex/tex/zztabbing.tex266
-rw-r--r--macros/plain/contrib/zztex/tex/zztabularv1.tex465
-rw-r--r--macros/plain/contrib/zztex/tex/zztabularv2.tex512
-rw-r--r--macros/plain/contrib/zztex/tex/zztabularv3.tex771
-rw-r--r--macros/plain/contrib/zztex/tex/zztag.tex269
-rw-r--r--macros/plain/contrib/zztex/tex/zztex.tex196
-rw-r--r--macros/plain/contrib/zztex/tex/zztext.tex935
-rw-r--r--macros/plain/contrib/zztex/tex/zzttladj.tex78
-rw-r--r--macros/plain/contrib/zztex/tex/zztures.tex24
-rw-r--r--macros/plain/contrib/zztex/tex/zzver.tex1
-rw-r--r--macros/plain/contrib/zztex/tex/zzvmode.tex380
-rw-r--r--macros/plain/contrib/zztex/tex/zzxref.tex245
58 files changed, 24524 insertions, 0 deletions
diff --git a/macros/plain/contrib/zztex/README b/macros/plain/contrib/zztex/README
new file mode 100644
index 0000000000..dedbd02896
--- /dev/null
+++ b/macros/plain/contrib/zztex/README
@@ -0,0 +1,17 @@
+ZzTeX Macro Package, version 17.7
+
+The ZzTeX macro package is a full-featured TeX macro package specially
+designed for producing books, journals, and manuals. Development of the
+package began in 1989. Since then, about 500 textbooks and journals have
+been produced with it for a variety of publishers. Numerous authors have
+used the package to produce subsequent editions of their books.
+
+I provide the TeX files for ZzTeX under The MIT License. You may use any or
+all of the code for whatever purpose you desire. ZzTeX runs under Plain TeX.
+The only documentation available for the package is contained in the zz*.dat
+files that accompany the TeX files.
+
+I hope you find some of the code useful for your TeX projects.
+
+Copyright 1989--2020 by Paul C. Anagnostopoulos
+under The MIT License (opensource.org/licenses/MIT)
diff --git a/macros/plain/contrib/zztex/doc/zzbuiltin.dat b/macros/plain/contrib/zztex/doc/zzbuiltin.dat
new file mode 100644
index 0000000000..09599a8a48
--- /dev/null
+++ b/macros/plain/contrib/zztex/doc/zzbuiltin.dat
@@ -0,0 +1,325 @@
+\@catcodes %~ Establish INITEX catcode defaults.
+\@markdef \botmark %~ Last mark on the current page.
+\@markdef \firstmark %~ First mark on the current page.
+\@markdef \splitbotmark %~ Last mark in material split off by |\vsplit.|
+\@markdef \splitfirstmark %~ First mark in material split off by |\vsplit.|
+\@markdef \topmark %~ Last mark from previous page.
+\@prefix \global %~ Establishes a global definition.
+\@prefix \immediate %~ Performs the I/O operation immediately.
+\@prefix \long %~ Allows command arguments to be multiple paragraphs.
+\@prefix \outer %~ Restricts command to appear at top level.
+\@suffix \displaylimits %~ Limits are set above/below in display style, as scripts otherwise.
+\@suffix \limits %~ Limits are set above and below symbols.
+\@suffix \nolimits %~ Limits are set next to symbol like scripts.
+\countdef \adjdemerits = 0 %~ Demerits for adjacent incompatible lines.
+\countdef \badness = 0
+\countdef \binoppenalty = 0 %~ Penalty for line break after binary operator.
+\countdef \brokenpenalty = 0
+\countdef \clubpenalty = 0
+\countdef \day = 0
+\countdef \deadcycles = 0
+\countdef \defaulthyphenchar = 0
+\countdef \defaultskewchar = 0
+\countdef \delimiterfactor = 0
+\countdef \displaywidowpenalty = 0
+\countdef \doublehyphendemerits = 0
+\countdef \endlinechar = 0
+\countdef \errorcontextlines = 0
+\countdef \escapechar = 0
+\countdef \exhyphenpenalty = 0
+\countdef \fam = 0
+\countdef \finalhyphendemerits = 0
+\countdef \floatingpenalty = 0
+\countdef \globaldefs = 0
+\countdef \hangafter = 0
+\countdef \hbadness = 0
+\countdef \holdinginserts = 0
+\countdef \hypenchar = 0
+\countdef \hyphenpenalty = 0
+\countdef \insertpenalties = 0
+\countdef \interlinepenalty = 0
+\countdef \language = 0
+\countdef \lastpenalty = 0
+\countdef \lefthyphenmin = 0
+\countdef \linepenalty = 0
+\countdef \looseness = 0
+\countdef \mag = 0
+\countdef \maxdeadcycles = 0
+\countdef \month = 0
+\countdef \newlinechar = 0
+\countdef \outputpenalty = 0
+\countdef \pausing = 0
+\countdef \postdisplaypenalty = 0
+\countdef \predisplaypenalty = 0
+\countdef \pretolerance = 0
+\countdef \pretolerand = 0
+\countdef \prevgraf = 0
+\countdef \relpenalty = 0
+\countdef \righthyphenmin = 0
+\countdef \showboxbreadth = 0
+\countdef \showboxdepth = 0
+\countdef \skewchar = 0
+\countdef \spacefactor = 0
+\countdef \time = 0
+\countdef \tolerance = 0
+\countdef \tracingcommands = 0
+\countdef \tracinglostchars = 0
+\countdef \tracinglostchars = 0
+\countdef \tracingmacros = 0
+\countdef \tracingonline = 0
+\countdef \tracingoutput = 0
+\countdef \tracingpages = 0
+\countdef \tracingparagraphs = 0
+\countdef \tracingrestores = 0
+\countdef \tracingstats = 0
+\countdef \uchyph = 0
+\countdef \vbadness = 0
+\countdef \widowpenalty = 0
+\countdef \year = 0
+\def \ { %~ Command space.
+\def \"{ % {char} %~ Umlaut accent %^accent
+\def \'{ % {char} %~ Accute accent %^accent
+\def \-{
+\def \.{ % {char} %~ Dot accent %^accent
+\def \/{
+\def \={ % {char} %~ Macron accent %^accent
+\def \AA { %~ Scandinavian A with circle
+\def \aa { %~ Scandinavian a with circle
+\def \above { % dimen
+\def \abovewithdelims { % delim delim dimen
+\def \accent { % nnn
+\def \advance { % \name by value
+\def \AE { %~ Scandinavian ligature OE
+\def \ae { %~ Scandinavian ligature oe
+\def \afterassignment { % token
+\def \aftergroup { % token
+\def \atop
+\def \atopwithdelims { % delim delim
+\def \batchmode
+\def \begingroup
+\def \bgroup
+\def \box { % nnn
+\def \b{ % {char} %~ Bar-under accent %^accent
+\def \catcode { % char = nn
+\def \char
+\def \chardef { % \name = nn
+\def \cleaders
+\def \closein { % nn
+\def \closeout { % nn
+\def \copy { % nnn
+\def \count { % nnn = integer
+\def \countdef { % \name
+\def \cr
+\def \crcr
+\def \c{ % {char} %~ Cedilla accent %^accent
+\def \dag { %~ Dagger
+\def \ddag { %~ Double dagger
+\def \def
+\def \delcode
+\def \delimiter
+\def \dimendef { % \name
+\def \diment { % nnn
+\def \discretionary{text}{text}{text}
+\def \displaystyle
+\def \divide { % \name by number
+\def \dp
+\def \dump
+\def \d{ % {char} %~ Dot-under accent %^accent
+\def \edef
+\def \egroup
+\def \end
+\def \endgroup
+\def \errmessage{text}
+\def \errorstopmode
+\def \font { % \name = file-name [at size]
+\def \fontdiment { % nn \font = dimen
+\def \futurelet { % \name token token
+\def \gdef
+\def \halign{material}
+\def \hbox { % [to dimen] {text}
+\def \hfil
+\def \hfill
+\def \hfilneg
+\def \hrule { % width dimen height dimen depth dimen
+\def \hskip { % skip
+\def \hss
+\def \ht
+\def \hyphenation{text}
+\def \hyphenchar { % \font = nn
+\def \H{ % {char} %~ Long Hungarian umlaut accent %^accent
+\def \ignorespaces
+\def \indent
+\def \insert { % nnn {text}
+\def \kern { % dimen
+\def \L { %~ Polish suppressed L
+\def \l { %~ Polish suppressed l
+\def \lastbox
+\def \lccode { % char = char
+\def \leaders
+\def \left { % delim math \right delim
+\def \let { % \name = token
+\def \lower { % dimen box
+\def \lowercase { % {text}
+\def \mark { % {text}
+\def \mathaccent { % nnnnn math
+\def \mathbin { % {expression} %~ Binary operator class (2) %^math_class
+\def \mathchar { % "cfnn
+\def \mathchardef { % \name = nnnnn
+\def \mathchoice{text}{text}{text}{text}
+\def \mathclose { % {expression} %~ Closing fence class (5) %^math_class
+\def \mathcode
+\def \mathinner { % {expression} %~ Inner subexpression
+\def \mathop { % {expression} %~Large operator class (1) %^math_class
+\def \mathopen { % {expression} %~ Opening fence class (4) %^math_class
+\def \mathord { % {expression} %~ Ordinary symbol class (0) %^math_class
+\def \mathpunct { % {expression} %~ Punctuation class (6) %^math_class
+\def \mathrel { % {expression} %~ Relation class (3) %^math_class
+\def \message { % {text}
+\def \moveleft { % dimen box
+\def \moveright { % dimen box
+\def \mukern { % mudimen
+\def \multiply { % \name by number
+\def \muskip { % nnn = mu-glue
+\def \muskipdef { % \name
+\def \noalign { % {text}
+\def \noboundary
+\def \noboundary
+\def \noindent
+\def \nonscript
+\def \nonstopmode
+\def \number { % {number} %~ This command formats an integer as Arabic numerals.
+\def \O { %~ Scandinavian O with slash
+\def \o { %~ Scandinavian o with slash
+\def \OE { %~ French ligature OE
+\def \oe { %~ French ligature oe
+\def \omit
+\def \openin { % nn = file-name
+\def \openout { % nn = file-name
+\def \over
+\def \overline{text}
+\def \overwithdelims { % delim delim
+\def \P { %~ Paragraph sign (pilcrow)
+\def \par
+\def \parshape { % = nn dimen ...
+\def \patterns{text}
+\def \penalty { % nnnnn
+\def \radical { % nnnnn math
+\def \raise { % dimen box
+\def \read { % n to \name
+\def \relax
+\def \romannumeral { % {number} %~ This command formats an integer as uppercase Roman numerals.
+\def \S { %~ Section sign
+\def \scriptfont
+\def \scriptscriptfont
+\def \scriptscriptstyle
+\def \scriptstyle
+\def \scrollmode
+\def \setbox { % nnn = box
+\def \setlanguage { % nnn
+\def \sfcode
+\def \shipout { % box
+\def \show { % token
+\def \showbox { % nnn
+\def \showlists
+\def \showthe { % internal-quantity
+\def \skewchar { % \font = nn
+\def \skip { % nnn = glue
+\def \skipdef { % \name
+\def \span
+\def \special { % {text}
+\def \ss { %~ German es-zet
+\def \t { % {char} %~ Tie-after accent %^accent
+\def \textfont
+\def \textstylestyle
+\def \toks { % nnn
+\def \toksdef { % \name
+\def \uccode { % char = char
+\def \underline{text}
+\def \unhbox { % nnn
+\def \unhcopy { % nnn
+\def \unkern
+\def \unpenalty
+\def \unskip
+\def \unvbox { % nnn
+\def \unvcopy { % nnn
+\def \uppercase { % {text}
+\def \u{ % {char} %~ Breve accent %^accent
+\def \vadjust{text}
+\def \valign{text}
+\def \vbox { % [to dimen] {text}
+\def \vcenter{text}
+\def \vfil
+\def \vfill
+\def \vfilneg
+\def \vrule { % width dimen height dimen depth dimen
+\def \vskip { % dimen
+\def \vsplit { % nnn to dimen
+\def \vss
+\def \vtop { % [to dimen] {text}
+\def \v{ % {char} %~ Hacek accent %^accent
+\def \wd
+\def \write { % nn {text}
+\def \xdef
+\def \xleaders
+\def \^{ % {char} %~ Circumflex accent %^accent
+\def \`{ % {char} %~ Grave accent %^accent
+\def \~{ % {char} %~ Tilde accent %^accent
+\dimendef \boxmaxdepth = 0
+\dimendef \delimitershortfall = 0
+\dimendef \displayindent = 0
+\dimendef \displaywidth = 0
+\dimendef \emergencystretch = 0
+\dimendef \hangindent = 0
+\dimendef \hfuzz = 0
+\dimendef \hoffset = 0
+\dimendef \hsize = 0
+\dimendef \lastkern = 0
+\dimendef \lineskiplimit = 0
+\dimendef \mathsurround = 0
+\dimendef \maxdepth = 0
+\dimendef \nulldelimiterspace = 0
+\dimendef \overfullrule = 0
+\dimendef \pagedepth = 0
+\dimendef \pagefilllstretch = 0
+\dimendef \pagefillstretch = 0
+\dimendef \pagefilstretch = 0
+\dimendef \pagegoal = 0
+\dimendef \pageshrink = 0
+\dimendef \pagestretch = 0
+\dimendef \pagetotal = 0
+\dimendef \parindent = 0
+\dimendef \predisplaysize = 0
+\dimendef \prevdepth = 0
+\dimendef \scriptspace = 0
+\dimendef \splitmaxdepth = 0
+\dimendef \vfuzz = 0
+\dimendef \voffset = 0
+\dimendef \vsize = 0
+\muskipdef \medmuskip = 0
+\muskipdef \thickmuskip = 0
+\muskipdef \thinmuskip = 0
+\skipdef \abovedisplayshortskip = 0
+\skipdef \abovedisplayskip = 0
+\skipdef \baselineskip = 0
+\skipdef \belowdisplayshortskip = 0
+\skipdef \belowdisplayskip = 0
+\skipdef \lastskip = 0
+\skipdef \leftskip = 0
+\skipdef \lineskip = 0
+\skipdef \parfillskip = 0
+\skipdef \parskip = 0
+\skipdef \rightskip = 0
+\skipdef \spaceskip = 0
+\skipdef \splittopskip = 0
+\skipdef \tabskip = 0
+\skipdef \topskip = 0
+\skipdef \xspaceskip = 0
+\toksdef \errhelp = 0
+\toksdef \everycr = 0
+\toksdef \everydisplay = 0
+\toksdef \everyhbox = 0
+\toksdef \everyjob = 0
+\toksdef \everymath = 0
+\toksdef \everypar = 0
+\toksdef \everyvbox = 0
+\toksdef \output = 0
diff --git a/macros/plain/contrib/zztex/doc/zzdetails.dat b/macros/plain/contrib/zztex/doc/zzdetails.dat
new file mode 100644
index 0000000000..c1ef6d0b8f
--- /dev/null
+++ b/macros/plain/contrib/zztex/doc/zzdetails.dat
@@ -0,0 +1,1597 @@
+//---------------------------------------------------------------------------
+//
+// Copyright (c) 2012--2018 by Paul C. Anagnostopoulos
+//
+// This software may be used on your own computer systems and may
+// be distributed freely to other people. It may not be sold or
+// incorporated into any commercial products.
+//
+// Paul C. Anagnostopoulos
+// Windfall Software
+// 978 371-2316
+// paul@windfall.com
+//
+//---------------------------------------------------------------------------
+//
+// ZzExplore: Describe built-in TeX, Plain TeX, ZzTeX, and design
+// file entities for compositors.
+//
+// This is the details phrase file.
+//
+// Created: 7 May 2016
+
+// \art Block
+// ---- -----
+
+.details art_details \art
+.template art_details
+== The |\art| Block
+
+This tutorial describes the ZzTeX |\art| block, which is used to place
+Encapsulated PostScript (EPS) files on the page. EPS files can be created
+with many different applications, the most common being Adobe Illustrator
+and PhotoShop.
+
+=== The |\art| Command
+
+The format of the |\art| command is:
+
+| \art{*type*}{*file*,*width*,*height*,*scale*[,*gutter*,*file*,*width*,*height*,*scale*,...]}
+
+The *type* argument specifies the type of the code block and thus its
+design. Common examples are |figure| for art in floating figures and
+|text| for art in text.
+
+A single piece of art is described by four values in the second argument:
+
+& *file*& The name of the EPS file. See below.
+& *width*& The width of the art, usually specified in picas.
+& *height*& The height of the art.
+& *scale*& The scale factor for the art. See below.
+&.
+
+You can place multiple pieces of art, or panels, side-by-side by including
+additional values in the second argument. The *gutter* specifies the
+horizontal distance between the adjacent panels. The next four arguments specify
+the second art file, in the same manner as the first. This sequence can be
+continued to place three or four panels side-by-side.
+
+=== File Name
+
+The file name specified in the |\art| command is the name of an EPS file to be
+placed on the page. There is no need to specify the extension |.eps|. The
+file is assumed to reside in the directory specifed by the |\setartroot|
+command in the book's root file. If the name is preceded by an exclamation
+point (|!|), then the file is located in the main project directory (this
+feature is used for design art).
+
+Occasionally, a piece of art will include spurious whitespace on the edges
+of the art, but within its bounding box. This whitespace is called *slop*,
+and will result in the art appearing out of position. ZzTeX can compensate
+for the slops if you specify them with the file name, as follows:
+
+ \art{figure}{{smi01f01,0pt,5pt,0pt,3pt},...}
+
+Note the extra set of braces around the file name and slops. All four slops
+must be specified, in this order: left side, right side, top, bottom. If all
+the slops are less than 1.5 points or so, there is no need to include them.
+We haven't used slops much in the past decade or so; we simply ask the
+illustrator to eliminate the whitespace.
+
+=== Width and Height
+
+If both the width and height are specified as zero (i.e., |0pc,0pc|), then the
+art will be dynamically sized when the file is processed. ZzTeX inspects the
+EPS file to determine the art size. If it cannot find the |%%BoundingBox|
+comment that specifies the size, an error results. We use this feature
+only for design art.
+
+The ZzSizeArt utility can automatically size the art in a chapter file.
+Try |~.facility; sizing art| for more details.
+
+=== Scale Factor
+
+The scale factor specifies the scale at which the piece of art should be
+placed, relative to its natural size. The scale factor must always be
+specified, even if it is 100. There are three ways to specify it:
+
+* *percentage*&_A number that specifes the percentage of scaling.
+The number may include decimal places.
+
+* |=|&_An equal sign specifies that the art should be scaled
+to fit in the prevailing width. The width is usually the
+text measure or the type area width.
+
+* |=*width*|&_An equal sign and a width specifies that the art should
+be scaled to the specified width.
+*.
+
+=== Aligning Side-by-Side Panels
+
+The |\art| command aligns side-by-side panels along their top edges. Sometimes
+you want them aligned differently. To shift a panel vertically, specify a
+top slop that is positive to shift the panel up or negative to shift the panel
+down.
+
+Note that the slops are scaled by the scale factor, so the exact slop
+required to shift the panel correctly may not be obvious.
+
+// Art Sizing
+// --- ------
+
+
+.phrase art_sizing art sizing : text
+.synonym sizing art
+.synonym zzsizeart
+.template
+= ZzSizeArt Art Sizing Utility
+
+The ZzSizeArt utility allows you to manipulate the art sizes specified in
+|\art| commands in ZzTeX source files. Its two primary capabilities are to set
+the sizes of art files by inspecting the Encapsulated PostScript (EPS) files
+and to replace existing EPS files with new versions.
+
+The ZzSizeArt facility relies on the following conventions for art files:
+
+* The bulk of the art files for a book are stored in the art/
+subdirectory under the primary project directory.
+
+* Replacement art files are loaded into the new/ subdirectory under
+the art/ directory before eventually being hoisted into the
+art/ directory.
+
+* Before an art file in an |\art| command is sized, its width and height are
+coded as |20pc,10pc|. This special combination signals that the art has not
+been sized.
+
+* ZzTeX supports dynamic sizing by setting the |\art| size
+to |0pc,0pc|. In this case, the size is determined by inspecting the
+EPS file every time the chapter is processed, rather than being set
+statically. Most ZzSizeArt commands ignore dynamically sized files.
+*.
+
+== zzsizeart Command
+
+The zzsizeart command has the following syntax:
+
+| zzsizeart *root* *command* *additional-items*
+
+The *root* parameter specifies the root name of the book. It is usually
+specified as a period (|.|), which causes ZzSizeArt to figure out the root
+name. The command parameter is a keyword that determines which function
+ZzSizeArt performs. Its functions are described in alphabetical order
+in the following paragraphs.
+
+* |zzsizeart *root* reset *source-file*|
+
+This command resets all the art sizes in the specified ZzTeX source file to
+|20pc,10pc|. Dynamically sized art files are ignored unless the |-all| option is
+included, in which case they are reset also.
+
+If the |-scale| option is specified, then ZzSizeArt also resets the scale of
+the art files to 100.
+
+* |zzsizeart *root* replace *optional-file-spec*|
+
+This command analyzes the replacement art files in the art/new/ subdirectory
+to determine whether they are the same size as the existing art files and
+can safely replace them. If a *file-spec* parameter is provided, only the
+replacement files that match the file spec are analyzed. The command
+generates a report about the replacement art files and displays it on the
+screen. This reports tells you whether the replacement art files are the
+same size or a different size.
+
+If the |-hoist| option is included, then any replacement art files that are the
+same size as the existing files are hoisted from the new/ subdirectory up to
+the art/ directory, replacing the old art files of the same names. The rest of
+the replacement art files are left in the new/ subdirectory. You can use the
+PrintEPS utility to generate a proof of the remaining art files, from which
+you can read the sizes of those files. Also see the |tell| command below.
+
+If the |-all| option is also specified, then all replacement art files are
+hoisted, including those that are a different size from the existing art
+files.
+
+The |-epsilon=*w*,*h*| option specifies the epsilon values for the width (*w*) and
+height (*h*). If the difference in size is within these epsilons, the
+replacement file is considered the same size as the existing file. The
+default width and heigh epsilons are both 1.5 points.
+
+* |zzsizeart *root* size *source-file*|
+
+This command sizes the |\art| commands in the specified ZzTeX source file by
+analyzing the EPS files named in those |\art| commands. Every art file must have
+the size |20pc,10pc|, except for dynamically-sized art files, which are
+ignored. Every named art file must exist in the art/ subdirectory. The
+source file is modified so that the art files have their actual sizes.
+
+If the |-ifexists| option is specified, then ZzSizeArt will size those art
+files that exist in the art/ subdirectory and ignore any other files named
+in |\art| commands. *All* art files must still have the size |20pc,10pc|, but any
+files that do not exist will not be set to their actual sizes.
+
+If the |-partial| option is specified, then ZzSizeArt will size those art
+files whose sizes are |20pc,10pc| and ignore any other art files named in |\art|
+commands. This allows you to size art files that were not sized previously
+for whatever reason, possibly due to a prior use of the |-ifexists| option.
+
+If both |-ifexists| and |-partial| are specified, then ZzTeX will size any
+art file who size is |20pc,10pc| and that exists in the art/ subdirectory.
+
+* |zzsizeart *root* tell *eps-file* ...|
+
+This command analyzes the specified EPS files and displays a report giving
+their sizes. This is useful when you need to know the sizes of a few EPS
+files in order to update their |\art| commands by hand.
+*.
+----
+For more details on the |\art| command, try |~.facility; \art|.
+
+// Cleanup Report
+// ------- ------
+
+
+.phrase cleanup_report cleanup report
+.synonym clean-up report
+.synonym clean up report
+.template
+= Cleanup Report for ~.project;
+
+This report describes the chapter cleanup activities for books
+in general and ~.project; in particular.
+
+Before reading this report, it's a good idea to read the design
+report for ~.project;. Try |~.facility; design report|.
+
+== General Cleanup
+
+=== Clean Up Headings
+
+The heads in sectioning commands (e.g., |\chapter|, |\section|) and
+tables, along with the titles in captions, must be formatted according
+to the design. This involves
+
+* Captitalizing them correctly
+
+* Adding or removing trailing punctuation
+
+* Ensuring that run-in heads have no blank lines after them
+
+* Adding |\noindent| commands where they might be missing
+
+* Once the chapter is processed, turning multi-line heads with
+|\titlenl;| or |\titletl;|
+*.
+
+Here are the styles of the various heads and titles.
+
+&= Command& Style
+----
+~foreach cmd, style_table;
+& ~.cmd;& ~.style_table[cmd];
+~end;
+&.
+
+=== Clean Up Floats
+
+The cleanup for floats involves
+
+* Making sure there is a blank line on either side
+
+* Determining whether the author embedded floats in the middle of
+paragraphs and merging the broken paragraph segments
+
+* Moving floats after the first paragraph of reference (this may be
+easier during page make-up)
+
+* Placing the correct file names in |\art| commands.
+
+* Checking captions to see if they need a |\legend| marker.
+*.
+
+// \code Block
+// ----- -----
+
+.details code_details \code
+.template code_details subclass_set command code
+== Code Facilities
+
+This tutorial describes the ZzTeX code facilities. These facilities are
+used to produce computer program code examples.
+
+=== The |\code| Block
+
+The |\code| command has the following syntax:
+
+| \code{*type*}
+| *line of code*
+| ...
+| *line of code*
+| \endcode
+
+The *type* argument specifies the type of the code block and thus its
+design. Each line of code is set more or less verbatim and line breaks
+are preserved as they are. Code blocks are almost always set in a monospaced
+font so that indentation can be accomplished with spaces at the beginnings
+of lines.
+
+=== Verbatim Lines
+
+The degree to which the code lines are taken verbatim is determined
+by certain block design parameters. To investigate the design
+parameters for a code block, try |~.facility; \code*type* details|.
+
+* |\allowTeXcommands|&_If this flag is on, ZzTeX commands can be
+included in the code, as long as they use only backslash and
+braces (|\|, |{|, |}|). This flag is on in most code blocks.
+To include those characters in the code itself, you must use:
+|\\|, |\{|, |\}|.
+
+* |\allowTeXmath|&_If this flag is on, math expressions can be
+included in the code, using dollar sign, underscore, and hat (|$|,
+|_|, |^|). This flag is off in most code blocks. To include those
+character in the code itself, you must use: |\$|, |\_|, |\hat|.
+(See |\codemath| for another way to include math in code.)
+
+* |\allowatsigncommands|&_If this flag is on, at-sign commands
+can be included in the code and would probably be provided by
+the code design. This flag is off in most code blocks. To include an
+at-sign in the code itself, you must use: |\@|.
+
+=== |\code| Tools
+
+The following list includes all the tools that can be used within a |\code|
+block. You can explore these various commands to learn what they do.
+
+~foreach name, name_set;
+* |~.name;|
+~end;
+*.
+
+// \enunciation Block
+// ------------ -----
+
+.details enunciation_details \enunciation
+.template enunciation_details
+== The |\enunciation| Block
+
+This tutorial describes the ZzTeX |\enunciation| block, which produces
+mathematical "enunciations" such as theorems, corollaries, and proofs.
+Using the |\enunciation| command is reasonably straightforward,
+but defining the various types of enunciations is a bit trickier.
+
+The format is the |\enunciation| command is:
+
+| \enunciation{*type*}{*optional-attribution*}
+
+The *type* argument specifies the type of the code block and thus its
+design. The *optional-attribution* argument can have one of three
+formats. Note that the second set of braces is required in *all* cases.
+
+# |{}|&_If empty, there is no attribution for the enunciation.
+& Theorem 1.1.&_There exist irrational numbers ...
+&.
+
+# |{Smith's Conjecture}|&_The specified text is the attribution for the
+enunciation.
+& Conjecture 1.2 (Smith's Conjecture).&_Let *K* be the *n*th cyclotomic field ...
+&.
+
+# |{\title Kleene's Theorem}|&_The text specified after the |\title| marker
+is the complete title for the enunciation.
+& Kleene's Theorem.&_Every language definable with a regular expression ...
+&.
+#.
+
+=== Defining an Enunciation Type
+
+Prior to ZzTeX v5.8, each enunciation type had to be defined by
+writing a complete design macro, as with other block types. There
+are some subtle issues that make this difficult. In v5.8, the
+|\definenunciation| command was added.
+
+| \defineenunciation{*type*}{*association*}{*design*}
+
+The first argument is the enunciation's type. The second argument
+can be empty or specify the type of another enunciation whose
+number counter is to be shared. Both types of enunciation will be
+numbered sequentially with the same counter.
+
+The third argument specifies a design macro for the base design
+that is to be used for this new enunciation type. Multiple enunciations
+can share the same base design. For example,
+
+ \defineenunciation{conjecture}{}{\enunciationtheoremlikedesign{Conjecture}}
+ \defineenunciation{corollary}{}{\enunciationtheoremlikedesign{Corollary}}
+ \defineenunciation{definition}{}{\enunciationtheoremlikedesign{Definition}}
+ \defineenunciation{lemma}{}{\enunciationtheoremlikedesign{Lemma}}
+ \defineenunciation{proof}{}{\enunciationprooflikedesign{Proof}}
+ \defineenunciation{proposition}{}{\enunciationtheoremlikedesign{Proposition}}
+
+There are two base designs for these enunciations: |\enunciationtheoremlikedesign|
+for enunciations formatted like theorems, and |\enunciationprooflikedesign|
+for enunciations formatted like proofs. Note that the two design macros expect
+an argument that is the word to appear in the title of the enunciation (e.g.,
+"Conjecture", "Proof").
+
+So defining a set of related enunciations boils down to writing one
+base design macro.
+
+=== Base Enunciation Design
+
+Most of the details about enunciation design macros are the same
+as other design macros. There are two interesting additions.
+
+ \def \enunciationtheoremlikedesign #1{%
+ \aboveskip = \standardskip
+ ...
+ \def \labelformat ##1{%
+ \noindent
+ \attributiontypecase
+ {\llap{\colortext{darkblue}{\enunnumbersize\dbf #1 \the\enunciationcomptext}%
+ \hspace{10pt}}}% no attribution
+ {\llap{\colortext{darkblue}{\enunnumbersize\dbf #1 \the\enunciationcomptext}%
+ \hspace{10pt}}##1.\quad}% normal attribution
+ {\llap{\colortext{darkblue}{\enunnumbersize\dbf ##1}%
+ \hspace{10pt}}}% title override
+ \ignorespaces}%
+
+The first addition is that the design macro accepts an argument that is
+the word to be set in the title. The |#1| in the first line represents
+that argument.
+
+The second addition is the |\attributiontypecase| command in the
+label formatter. It takes three arguments, each of which formats the
+title (label) of the enunciation. The three arguments correspond to the
+three title argument formats described above.
+
+# The attribution argument is empty.
+# The attribution argument specifies an attribution.
+# The attribution argument includes the |\title| marker.
+#.
+
+=== The |\defineeoedingbat| Command
+
+The |\enunciation| block includes a design parameter named |\autoqed|.
+This parameter can specify the name of an "end-of-enunciation dingbat"
+that should appear at the end of the enunciation.
+
+ \def \enunciationprooflikedesign #1{%
+ ...
+ \autoqed = {\qed}%
+
+The |\qed| command, which typesets a dingbat, is automatically performed
+at the end of enunciations based on the |\enunciationprooflikedesign|
+design. To override the position of the resulting dingbat, you can
+specify the |\qed| command explicitly in the text of the enunciation.
+
+An end-of-enunciation dingbat is defined with
+
+| \defineeoedingbat{*name*}{*text*}{*space*}
+
+The first argument is the name of the dingbat command. The second argument
+is the text of the dingbat. The third argument specifies how to
+separate the dingbat from the final word of the enunciation.
+
+* |{10pt}|&_The dingbat is set 10 points from the final word.
+
+* |{\flushright 8pt}|&_The dingbat is set flush right, but a minimum
+of 8 points must separate it from the final word.
+*.
+
+So the |\qed| dingbat used above could be defined with
+
+ \defineeoedingbat{\qed}{\colortext{darkblue}{\slug{5pt}{5pt}}}{\flushright 8pt}
+
+// Environments
+// ------------
+
+
+.phrase environments environments : text
+.synonym LaTeX environments
+.template
+= LaTeX Environments
+
+A LaTeX *environment* is the equivalent of a ZzTeX *block*.
+The term environment is not used in ZzTeX.
+
+// \eqno Marker
+// ----- ------
+
+.details eqno_details \eqno
+.template eqno_details
+== Equation Numbers
+
+This tutorial describes the ZzTeX facilities for setting equation numbers on
+math displays. An equation number is set with the |\eqno| marker, which can
+appear in three places:
+
+# At the end of a single-line math display, before the closing |$$|.
+
+# At the end of an aligned math display, *after* the close brace of the
+|\eqaligned| and before the closing |$$|. In this case, the number pertains
+to the entire display.
+
+# At the end of a row of an aligned display, just *before* the |\cr| or
+close brace of the |\eqaligned|. In this case, the number pertains to
+the row in which it appears.
+#.
+
+Almost all book designs call for one of two formats of equation number. In
+most cases, the number consists of the chapter composite text and a sequence
+number within the chapter, as in "3.17". In a few cases, only a sequence
+number is used, as in "17". In the descriptions below, *chap* stands for the
+chapter composite text, while *num* stands for the equation sequence number. The
+sequence number is derived from the math display counter, in the same manner
+as section numbers are derived from the section counter.
+
+You can code an equation number in one of four ways:
+
+| \eqno
+| \eqno \tag{*xyz*}
+| \eqno *override*
+| \eqno *override* \tag{*xyz*}
+
+The optional *override* text is used to override the normal numbering sequence.
+A space or line break can be placed before and/or after the |\tag| command to
+aid readability. The |\tag| command must appear immediately following its
+paired |\eqno| in order to associate the tag with the correct equation
+number.
+
+The following paragraphs present the various forms of the *override* text for
+overriding the numbering sequence. Each case includes two examples, the
+first where the equations are numbered in the common (*chap*.*num*) format, and
+the second where the equations are numbered with only a sequence number, as
+in (*num*). The examples assume that the chapter number is 2 and the
+math display counter is at 4 prior to the display
+and also show the counter *after* the equation number is typeset.
+
+* |\eqno|&_&_&_Next sequence number
+
+The math display counter is incremented and its arabic form is used as
+the *num* text. This is the common case.
+
+&= Result when& Result when
+&= (*chap*.*num*) style& (*num*) style& Counter After
+----
+& (2.5)& (5)& 5
+&.
+
+* |\eqno +a|&_&_&_Next sequence number; use with suffix
+
+The math display counter is incremented and its arabic form is joined
+with the suffix following the plus sign to make up the *num* text.
+
+&= Result when& Result when
+&= (*chap*.*num*) style& (*num*) style& Counter After
+----
+& (2.6a)& (6a)& 5
+&.
+
+* |\eqno ,b|&_&_&_Same sequence number with suffix
+
+The math display counter is *not* incremented. Its arabic form is joined
+with the suffix following the comma to make up the *num* text.
+
+&= Result when& Result when
+&= (*chap*.*num*) style& (*num*) style& Counter After
+----
+& (2.4b)& (4b)& 4
+&.
+
+* |\eqno ,$'$|&_&_&_Same sequence number with suffix
+
+This is another example of the preceding case, showing the common use
+of a prime after the *num* text.
+
+&= Result when& Result when
+&= (*chap*.*num*) style& (*num*) style& Counter After
+----
+& (2.4&prime;)& (4&prime;)& 4
+&.
+
+* |\eqno A1|&_&_&_Ignore sequence number; use specified *num*
+
+The math display counter is ignored. The specified text is used as the
+complete *num* text.
+
+&= Result when& Result when
+&= (*chap*.*num*) style& (*num*) style& Counter After
+----
+& (2.A1)& (A1)& 4
+&.
+
+* |\eqno :A1|&_&_&_Next sequence number; use specified *num*
+
+The math display counter is incremented *but then ignored*. The specified
+text is used as the complete *num* text.
+
+&= Result when& Result when
+&= (*chap*.*num*) style& (*num*) style& Counter After
+----
+& (2.A1)& (A1)& 5
+&.
+
+* |\eqno =12;a|&_&_&_Set sequence number; use with suffix
+
+The math display counter is set to 12 and its arabic form is joined
+with the suffix following the semicolon to make up the *num* text. Note that
+the suffix (|a| here) is optional but the semicolon is required.
+
+&= Result when& Result when
+&= (*chap*.*num*) style& (*num*) style& Counter After
+----
+& (2.12a)& (12a)& 12
+&.
+
+* |\eqno !2B.1|&_&_&_Use specified text for number
+
+The chapter composite text and math display counter are ignored. The text
+following the exclamation point is the complete equation number. This
+feature is useful when you need to set an out-of-sequence equation number
+in something like a sidebar or a chapter appendix.
+
+&= Result when& Result when
+&= (*chap*.*num*) style& (*num*) style& Counter After
+----
+& (2B.1)& (2B.1)& 4
+&.
+
+* |\eqno >{*tag*}|&_&_&_Use equation number associated with tag
+
+The chapter composite text and math display counter are ignored. The equation
+number associated with the tag is duplicated for the equation number
+of this display.
+*.
+
+If you ever need to reset the math display counter, the following command
+will do it:
+
+| \setmathdisplaynumber{*num*}
+
+// Indexing
+// --------
+
+.phrase indexing indexing : text
+.template
+= Indexing Facilities, version 2
+
+This tutorial describes the second generation ZzTeX indexing facilities.
+These facilities are used to index a document with embedded indexing commands and
+then generate one or more indexes for typesetting.
+
+First, some definitions.
+
+* Locator.&_An item followng a heading that refers the reader to related
+information in the book. This is usually a page number or range,
+but sometimes a "See" or "See also." The term *locator* is also used
+for the commands that are inserted in the text to create index entries.
+
+* Main heading.&_The heading of a top-level entry in an index.
+
+* Raw index entry.&_A locator command such as |\xpage| generates
+a raw index entry in the raw index entry files. The entry contains
+unformatted information about the locator.
+
+* Sort override.&_An alternate heading used in place of a regular heading
+to specify how it should be sorted, For example, the heading "3-D"
+might have a sort heading of "three D".
+
+* Subheading.&_The heading of a second- or third-level entry in an index,
+subordinate to a main heading.
+*.
+
+== Indexing Locators
+
+Indexing locators are commands that are inserted in the text to produce raw index
+entries that ultimately make up the index. This section describes typical
+indexing locators. For another overview of locators, try |~.facility;
+locators|.
+
+Most locator commands produce a raw index entry that identifies a page or range of
+pages relevant to the headings.
+
+ \xpage{Automobiles}
+ \xpage{Automobiles|muscle cars}
+
+Locator commands begin with an |x| and include a type word that identifies
+the type of locator produced. The argument specifies one to three
+headings, separated by vertical bars (|&||). The first heading is the main heading
+and any remaining headings are subheadings.
+
+If the locator allows a page range, then the commands |\x*type*begin| and
+|\x*type*end| identify the beginning and ending positions of the range.
+
+ \xpagebegin{Automobiles}
+ ...
+ \xpageend{Automobiles}
+
+Some locators require an additional argument called the "text." This provides
+more information about the locator.
+
+ \xsee{Cars}{Automobiles}
+ \xseealso{Automobiles|muscle cars}{Automobiles|pony cars}
+
+Such locator commands produce locators that do not include a page number
+but rather text that refers the reader to other entries. The additional
+text argument is always the first argument of the locator command.
+
+=== Sort Overrides
+
+(To be supplied.)
+
+== Design File
+
+This section describes the commands that appear in the design file to define
+locators and their formatting and specify the design of the indexes in the
+book. The commands are described in the order in which they must appear in
+the design file.
+
+ \indexversion{2}
+
+This command must appear at the beginning of the Index section of the design
+file. It specifies that version 2 of the indexing facility is being used.
+
+=== Generating Indexes
+
+Multiple indexes can be generated from the raw index entries of a book. Each
+index is assigned a name and declared using the following command.
+
+| \generateindex{*name*}
+
+Typical names are |subject|, |author|, and |symbol|. For each generated
+index, ZzTeX produces an "index parameter file" with the same name as the
+index and the extension |zzp|. A parameter file contains information about
+the defined locators and information taken from the design definition for
+the named index. This information is used by the index generator to build
+the final index file. (See below for a description of index parameter files.)
+
+=== Defining Locators
+
+| \definelocator{*type*}{*attributes*}{*optional-format*}
+
+This command defines an index locator and establishes the indexing commands
+used to include the locator in the index. The first argument is the type word that
+identifies the type of locator. Typical examples are |page|, |figure|, and
+|see|.
+
+The second argument gives the attributes of the locator. It is a series
+of keywords:
+
+* |\page|, |\nopage|&_Indicates whether the locator includes a page number.
+
+* |\range|, |\norange|&_Indicates whether the locator may be used to specify
+a range of pages in addition to a single page.
+
+* |\text|, |\notext|&_Indicates whether the locator includes additional text.
+*.
+
+Assume that the type is |thing|. In all cases, the following locator command
+is defined:
+
+| \xthing{*headings*}
+
+If a range is allowed, then two additional commands are defined:
+
+| \xthingbegin{*headings*}
+| \xthingend{*headings*}
+
+If the locator includes additional text, then all commands take a first
+argument specifying the text:
+
+| \xthing{*text*}{*headings*}
+| \xthingbegin{*text*}{*headings*}
+| \xthingend{*text*}{*headings*}
+
+The third argument to |\definelocator| is optional and specifies the format
+of the locator in the final index. If the braces are empty, then the
+separetely defined format with the same name as the locator is used. To
+provide the format, use three sets of braces to specify the second, third,
+and fourth arguments for the |\definelocatorformat| command (below). The new
+format will be given the same name as the locator.
+
+=== Defining Formats
+
+| \definelocatorformat{*name*}{*rank*.*order*}{*level-1-items*}{*level-2-items*}
+
+This command defines a locator format with the given name for the final index.
+The third and fourth arguments specify items that are needed to format
+the locator. The level-1-items are used for locators associated with main
+headings, while the level-2-items include overrides that pertain to
+subheadings (both second- and third-level).
+
+The second argument specifies the rank and order of this locator. The *rank*
+determines this locator's position in the overall sequence of locators for a
+heading. Typically, the page locators appear first, then the "see" locator,
+then any "see also" locators.
+
+The *order* determines the order of the locator within a series of locators
+all with the same page number. Typically, plain page numbers appear first,
+then pages with suffix 'f' for figure, then pages with suffix 't' for table,
+etc.
+
+& Mustang, 13, 44--49, 45*f*, 45*t*
+&.
+
+Each item list argument is in the following format:
+
+| {*item*:*text*&|*item*:*text*&|...}
+
+There is a sequence of items separated by bars (|&||). Each item consists of
+an item tag, a colon (|:|), and some text. The following item tags are
+available.
+
+* |prefix1|&_Text to precede all locators of this rank, when this is
+the first locator after the heading. Defaults to empty.
+
+* |prefix2|&_Text to precede all locators of this rank, when this is
+not the first locator after the heading. Defaults to |prefix1|.
+
+* |tmplt|&_Template for this locator when there is a single page
+or no page (only text). No default.
+
+* |rtmplt|&_Template for this locator when there is a range of pages.
+No default.
+
+* |sep|&_Separator between locators of this rank. Defaults to empty.
+
+* |suffix|&_Text to follow all locators of this rank. Defaults to empty.
+
+* |term|&_Text to terminate the entire sequence of locators. Defaults to empty.
+*.
+
+The templates |tmplt| and |rtmplt| may include the following substitutors.
+
+&= Substitutor& What is substituted
+----
+& |?P|& Single page or first page of range.
+& |?Q|& Second page of range.
+& |?T|& Text (e.g., for |see| or |seealso| locators).
+& |??|& Single question mark (|?|).
+&.
+
+The builtin locators can be found in the ZzTeX file zzindexv2.tex. They
+are good examples of how locator formats are defined.
+
+== Index Design
+
+Each index of a book is typeset inside an index block whose design is
+specified, as usual, with a design macro. The parameters of the design macro
+include many common ones, but also a few that are special for index designs.
+The following paragraphs describe the special parameters.
+
+* |\def \alphaformat ##1{*text*}|
+
+This parameter specifies how to format the break between letters produced by
+the |\alphbreak{...}| command. The macro is passed the argument text from the
+|\alphabreak|.
+
+* |\divisions = {*div1*,*div2*,...}|
+
+This parameter specifies the book divisions to be included in the index.
+The value can be |\all|; a list of division names; or |\allbut| followed by a
+list of division names.
+
+* |\locators = {*loc1*,*loc2*,...}|
+
+This parameter specifies the locators to be included in the index. The value
+can be |\all|; a list of locators; or |\allbut| followed by a list of locators.
+Each locator consists of the locator type followed by an optional colon and
+format name. If a format name is not included, then the locator is formatted
+according to the format with the same name as the locator.
+
+* |\indexparams = {...}|
+
+This parameter specifies index parameter statements to be included in the
+index parameter file. See below for a description of the parameter
+statements.
+
+* |\position = {*options*}|
+
+This parameter specifies the overall format of the index. It consists of a
+sequence of the following options:
+
+&= Option& Meaning
+----
+& |\oneup|& Run index in one column.
+& |\outline|& Format entries in outline style.
+& |\runin|& Format entries in run-in (paragraph) style.
+& |\threeup|& Run index in three columns.
+& |\twoup|& Run index in two columns.
+& |\usetextmeasure|& Use the text measure for the columns.
+& |\usetextwidth|& Synonym for |\usetextmeasure|.
+& |\usetypewidth|& Use the type area width for the columns.
+&.
+*.
+
+=== Entry Formatters
+
+(To be supplied.)
+
+== Raw Index Entry Files
+
+ZzTeX populates raw index entry files as it encounters indexing locator
+commands in the book files. Each indexing locator generates one raw entry
+record in the file whose name is the same as the division with an extension
+of |.zzi|. A raw entry record has the following format. The semicolon (|;|)
+represents the field separator character hex B8, chosen because it cannot
+appear in an index heading.
+
+| *type*;*code*;*folio*;*main-head*;*subhead*;*sub-subhead*;*text*
+
+The *code* is |S| for a single page entry, |B| for a begin page range entry,
+or |E| for an end range entry.
+
+== Index Parameter Files
+
+(This material is highly technical and incomplete.)
+
+An index parameter file contains a series of statements that specify
+parameters for the index generator (zzindex2.exe). Each time an index is
+generated, at least two parameter files are read:
+
+* *index-name*.zzp&_The parameter file generated by the |\generateindex|
+command for the specific index being generated.
+
+* zzindex2.zzp&_A generic parameter file included with ZzTeX.
+*.
+
+Each statement in a parameter file has the following format:
+
+| [*mode*] *keyword* *item* ... ;
+
+The optional mode is enclosed in brackets and specifies the mode to which
+the statement pertains. If the mode is not specified, the statement is used
+in all modes. The items are separated by spaces. The statement ends with a
+semicolon.
+
+A parameter file may also contain blank lines and comment lines beginning
+with |//|. Comment lines are ignored.
+
+Statements that specify actions for tokens in headings include the token for
+which the action is to be performed. A token can be one of the following:
+
+&= Token& Meaning
+----
+& |SP|& space
+& |\SP|& TeX \<space> command
+& |\*name*|& TeX |\*name*| command
+& |\*c*|& TeX |\*c*| character command
+& *x*& any other character
+&.
+
+The following statements can appear in an index parameter file.
+
+* |begin-group *token* ;|
+
+The token begins a group and is discarded. The mode stack is pushed with the
+current mode.
+
+* |define-format *format-text* ;|
+
+(To be supplied.)
+
+* |define-locator *definition-text* ;|
+
+(To be supplied.)
+
+* |[mode] discard *token* ;|
+
+The token is discarded and does not appear in the canonicalized heading.
+
+* |[mode] discard/u *token* ;|
+
+The token is removed from the heading but suffixed to the canonicalized
+heading.
+
+* |divisions *divisions-text* ;|
+
+This statement specifies the required divisions from the |\divisions| parameter
+of the index design.
+
+* |end-group *token* ;|
+
+The token ends a group and is discarded. The mode stack is popped.
+
+* |include-param *file* ;|
+
+This statement requests that the named index parameter file be loaded.
+
+* |include-raw *file* ;|
+
+This statement requests that the named raw index entry file be included in
+the set of raw index entry files.
+
+* |index "*name*" ;|
+
+This statement specifies the name of the index to be generated.
+
+* |[mode] invalid *token* ;|
+
+The token is invalid and an error message is produced.
+
+* |[mode] keep *token* ;|
+
+The token is preserved as is on the canonicalized heading.
+
+* |locators *locators-text* ;|
+
+This statement specifies the required locators from the |\locators| parameter
+of the index design.
+
+* |math/u *token* ;|
+
+The token begins or ends math mode. The mode stack is pushed or popped as
+appropriate. The token is suffixed to the canonicalized heading.
+
+* |noise/u "*word*" ;|
+
+If the word appears at the beginning of a subheading or sub-subheading, it
+is removed but suffixed to the canonicalized heading.
+
+* |[mode] replace *token* "*text*" ;|
+
+The token is discarded and replaced with the specified text, which is not
+rescanned.
+
+* |[mode] replace/u *token* "*text*" ;|
+
+The token is discarded and replaced with the specified text, which is not
+rescanned. The token is, however, suffixed to the canonicalized heading.
+
+* |root "*name*" ;|
+
+This statement specifies the name of the book's root file.
+
+* |sort *mode* ;|
+
+(To be supplied.)
+
+* |[mode] synonym *token* "*text*" ;|
+
+The token is discarded and replaced with the specified text, which is then
+rescanned.
+*.
+
+// Letterspacing
+// -------------
+
+.details letterspace_details \letterspace
+.template letterspace_details
+== Letterspacing
+
+This tutorial describes the letterspacing facility in ZzTeX. All letterspacing
+is accomplished with the \letterspace command, which comes in two flavors:
+
+| \letterspace{*amount*}{*text*}
+
+This command letterspaces the specified text. The amount of letterspace is
+specified by the first argument, usually in ems.
+
+| \letterspace{*amount*,*space*}{*text*}
+
+This command operates like the first variant, except that the width of a
+space is specified explicitly after the letterspace amount.
+
+Note that |\letterspace| commands are usually embedded in design macros in
+the design file. Rarely does one appear directly in book files. However, to
+code titles that will be letterspaced, the compositor needs to understand
+the behavior of the |\letterspace| command.
+
+=== What Happens Automatically
+
+What a title or other text is letterspaced, the |\letterspace| command does
+the following things automatically:
+
+* Inserts the letterspace amount between adjacent pairs of keyboarded
+characters (e.g, |AB|, |01|, |l.|). A "keyboarded character" is one that
+is typed on the keyboard, not coded like |\copyright| or |\alpha|.
+
+* Replaces explicit spaces and tie characters (|~~|) with the space width
+derived from the first argument to the |\letterspace| command.
+
+* Recognizes en dashes (|--|), em dashes (|---|), and double quotes (|``...''|)
+and does not break them apart with letterspace.
+
+* Does *not* letterspace before or after ZzTeX commands, open braces (|{|), or
+close braces (|}|). This means that there will be no letterspacing around
+|\copyright|, |\ellipsis|, |\alpha|, |\times|, etc.
+*.
+
+=== Explicit Control of Letterspacing
+
+The automatic rules take care of many letterspacing problems. However,
+sometimes you need explicit control over letterspacing, so the following
+commands can be used within a title that is letterspaced. If the same
+title is carried elsewhere (such as into a running head)
+but is not letterspaced there, these commands have no effect.
+
+& |\lsp|& Insert a letterspace amount here.
+& |\lspspace|& Insert a letterspaced space here.
+& |\lspoff|& Turn off letterspacing completely.
+& |\lspon|& Restore letterspacing.
+&.
+
+=== An Example
+
+The following diabolical example shows the power of the letterspacing
+facility. Here is a chapter title that is letterspaced:
+
+ \chapter{Text Access\titlenl; ``Methods''\titlenl;
+ \lspoff$a-b'\times c$\lspon\lsp---Why~~Isn't It?}
+
+This produces the following title, where the vertical bar represents a
+letterspace and the underscore represents a space:
+
+& T&|e&|x&|t_A&|c&|c&|e&|s&|s
+& "&|M&|e&|t&|h&|o&|d&|s&|"
+& *a*&thinsp;-&thinsp;*b*&prime;&thinsp;&times;&thinsp;*c*&|---&|W&|h&|y_I&|s&|n&|'&|t_I&|t&|?
+&.
+
+If this title is used in a running head or table of contents, the control
+commands |\lspoff|, |\lspon|, and |\lsp| are ignored (as well as |\titlenl|,
+of course). Note that the |\lsp| command is necessary to produce a
+letterspace before the em-dash, since letterspacing is automatically
+supressed after the |\lspon| command.
+
+// Runners
+// -------
+
+.phrase runners runners
+.synonym running heads
+.synonym running feet
+.template
+= Running Heads and Feet
+
+Running heads and feet are collectively called *runners*. A design file can
+make use of multiple styles of runners. One is built into ZzTeX:
+
+* |blind|&_A style with empty running heads and feet.
+*.
+
+ZzTeX assumes the existence of two styles that must be defined in the
+design file:
+
+* |normal|&_The style for normal body pages.
+* |chapter|&_the style for chapter opener pages.
+*.
+
+Specific designs may use additional styles defined in the design file,
+for example:
+
+* |part|&_The style for part opener pages.
+*.
+
+For each style (except |blind|), the design file contains two definitions,
+one for the running head and one for the foot. These macros are responsible
+for formatting the header and footer, often using mark information to
+obtain chapter numbers, section titles, etc., and using |\folio| to obtain
+the page number:
+
+ \def \headernormalformat {...}
+
+ \def \footernormalformat {...}
+
+ \def \headerchapterformat {...}
+
+ \def \footerchapterformat {...}
+
+== Runner Commands
+
+The following commands are used to establish the runner styles
+for subsequent pages in the book.
+
+~foreach cmd, command_set;
+* |~.cmd;|
+~end;
+*.
+
+Those commands are lovely but rarely used explicitly, except in
+the front matter. Instead, runners are established using the |\runners|
+parameter of certain blocks.
+
+== |\runners| Parameter
+
+The |\runners| parameter is a design parameter for certain blocks in ZzTeX.
+It is usually specified in the design macros for those blocks in the design
+file, but you can override the normal styles by using the |\with| modifier on
+such blocks.
+
+The following list specifies the blocks that use the |\runner| parameter to
+perform an implicit |\setrunners| command. Each entry shows the standard
+value of the parameter:
+
+& |\part|& | \runners={blind,normal}|
+& |\quasipart|& |\runners={blind,normal}|
+& |\chapter|& |\runners={chapter,normal}|
+& |\quasichapter|& |\runners={chapter,normal}|
+& |\appendix|& |\runners={chapter,normal}|
+& |\float|& |\runners={normal}|
+&.
+
+Imagine you had a quasichapter and you wanted to suppress the drop folio
+normally set by the chapter runners. You simply do the following:
+
+ \with{\runners={blind,normal}}
+ \quasichapter{Weird Back Matter}
+
+You must remember to specify a second style of |normal| for the remaining
+pages of the quasichapter or they will all have blind runners.
+
+You can accomplish the same goal as follows:
+
+ \quasichapter{Weird Back Matter}
+ \overriderunners{blind}
+
+The |\float| block uses the |\runner| parameter to perform an implicit
+|\overriderunners| command.
+The float mechanism arranges to perform an |\overriderunners| with the
+style specified by the |\runner| parameter when it is about set a page
+containing *only floats*. If you want to suppress the running head on such a
+page:
+
+ \with{\runners={blind}}
+ \float{figure}
+
+However, see the |\userharea| block modifier for the best way to
+accomplish this.
+
+== Some Examples
+
+A book with a two-page-spread chapter opener could use the |\runners|
+parameter in the chapter design to set the correct runners for both
+opener pages:
+
+ \def \chapterdesign {%
+ ...
+ \def \paging {\freshpage{\short\floats\even}}%
+ ...
+ \runners = {blind,chapter,normal}%
+ ...}
+
+Some books have part pages but Chapter 1 occurs before Part I. If the
+running heads include the part number and title, that will probably fail in
+Chapter 1 because no part has been established. If the design file provides
+a special runners style |normalnopart| for such "part-less" chapters, you
+can use it quite easily:
+
+ \with{\runners={chapter,normalnopart}}
+ \chapter{The First Chapter}
+
+// \tabbing Block
+// -------- -----
+
+.details tabbing_details \tabbing
+.template tabbing_details
+== Tabbing Facilities
+
+This tutorial describes the ZzTeX tabbing facilities. The primary
+tabbing feature is the |\tabbing| block, which replaced the tabbing
+capability of the |\text| block in ZzTeX v17.2.
+
+=== The |\tabbing| Block
+
+The |\tabbing| command has the following syntax:
+
+| \tabbing{*type*}
+| *line of text*\nl
+| *another line*
+| &_*of text*\nl
+| ...
+| *last line of text*\nl
+| \endtabbing
+
+The *type* argument specifies the type of the tabbing block and thus its
+design. A line in the typeset block can occupy multiple lines in the
+TeX file but must end with an |\nl| command. Line breaks in the file are
+not taken verbatim. The |\nl| after the final line is optional.
+
+=== Setting Tab Stops
+
+There are two ways to set tab stops for the lines in a tabbing block.
+The first is to set uniform tab stops across the line. The distance
+between tab stops is specified by the |\defaulttabwidth| design
+parameter. If this parameter is a positive dimension, say, |14pt|,
+then tab stops are set every 14 points across the line.
+
+The second method of setting tab stops is to include a *template line*
+at the beginning of the tabbing block. For example,
+
+ \tabbing{algorithm}
+ @Cxxxxx@.xxxxx@.xxxxx@.xxxxxxxxxxxxxxx@.@D
+
+The |@C| command clears any existing tab stops. Each |@.| command
+sets a tab stop at the current width of the line. In this example,
+there will be a tab stop at the width of 5 |x| letters, 10 letters,
+15 letters, and 30 letters. The |@D| command discards the line
+so it doesn't show up on the page. The line exists only for the
+purpose of setting the stops.
+
+=== Tabbing
+
+The |@>| command is used to tab from one tab stop to the next. In this
+example, assume that tab stops are set every 14 points.
+
+ \tabbing{algorithm}
+ $\mvar{scores} = \{\}$\qquad // score accumulator maps doc IDs to scores\nl
+ \For $w\in q$ \Do\nl
+ @>\For $d, \mvar{count}\in \mvar{Idx}.\mvar{fetch}\_\mvar{docs}(w)$ \Do\nl
+ @>@>$\mvar{scores}[d] = \mvar{scores}[d] + \mvar{score}\_\mvar{term}(\mvar{count})$
+ @>\EndFor\nl
+ \EndFor\nl
+ \Return top $k$ documents from $\mvar{scores}$\nl
+ \endtabbing
+
+The third line is indented 14 points, the fourth line is indented 28 points, etc.
+
+Note that each |@>| command tabs to the next tab stop in the sequence of stops,
+regardless of whether the width of the text is beyond that stop. If the width
+of the text is beyond the next stop, the text following that stop will overprint
+the preceding text.
+
+=== Vertical Adjustments
+
+The are two ways to make vertical adjustments between lines of text.
+The first is to code a blank line:
+
+ \tabbing{algorithm}
+ $\mvar{scores} = \{\}$\qquad // score accumulator maps doc IDs to scores\nl
+ \nl
+ \For $w\in q$ \Do\nl
+
+A blank line produces the amount of vertical space specified by the
+|\tabbinggapskip| design parameter. This vertical space is usually
+less than a full line.
+
+The second method of performaing a vertical adjustment is to use the
+|\adjusttabbing| command in between two lines. Try |~.facility; \adjusttabbing|
+for more information.
+
+=== Line Numbers
+
+[To be supplied.]
+
+// \tabular Block
+// -------- -----
+
+.details tabular_details \tabular
+.template tabular_details subclass_set command tabular
+== Tabular Facilities, version 3
+
+This tutorial describes the third generation of the ZzTeX tabular
+facilities. These facilities are used to produce tabular material in
+text or in a floating table.
+
+First, some definitions:
+
+* Cell.&_The intersection of each row and column is called a cell.
+The cell contains the text at that row/column intersection.
+
+* Column.&_Tabular material is organized into vertical columns.
+Each column has a particular format, specified in the template.
+
+* Gutter.&_The gutter is the horizontal space between columns. It is
+typically 1 pica and can stretch or shrink if tables are
+to be forced to a particular width. The gutter between two
+columns can be changed on a case-by-case basis.
+
+* Interrow space.&_An extra amount of vertical space that is placed between
+rows of tabular material.
+
+* Picture.&_A sequence of characters used to determine the alignment
+of decimal-aligned numeric columns.
+
+* Row.&_Tabular material is organized into horizontal rows, with
+
+* Ruled table.&_Tabular material that includes vertical rules.
+
+* Template.&_An argument to the \tabular command that specifies the
+number of columns and the format for each column.
+*.
+
+=== The |\tabular| Command
+
+The |\tabular| command has the following syntax:
+
+| \tabular{*type*}{*template*}
+| *row* ... \cr
+| *row* ... \cr
+| ...
+| *row* ... \cr
+| \endtabular
+
+The *type* argument specifies the type of the tabular block and thus its
+design. The *template* argument specifies the number of columns and their
+associated formats (see below).
+
+Each row consists of a series of cells and is terminated by the |\cr| command
+("carriage return" or "complete row"). The cells are specified as follows:
+
+| *cell-1*&& *cell-2*&&&& *cell-4*&& ...&& *cell-n*\cr
+
+There is one cell for each column and they are separated by ampersands
+(|&&|). It is important to eliminate any spaces *preceding* the ampersands,
+although spaces following them are fine. An empty cell is allowed, as with
+the third cell above.
+
+In a ruled table, every cell in a row must be specified, although some may
+be empty (the cells corresponding to rule columns usually are). In a table
+that is not ruled, rightmost cells that are empty need not be specified.
+
+=== How ZzTeX Formats Tabular Material
+
+ZzTeX goes through the following steps to format tabular material.
+
+# The template is analyzed to check it, count the columns, and prepare the
+individual column formats.
+
+# All rows are read and each cell is formatted in its own box.
+
+# The maximum width of the cells in each column is determined, and all the
+cell boxes in that column are set to the maximum width. (See |\hidewidth| for
+an exception.)
+
+# All the boxes in each row are set side by side, with the column gutter
+between them. The widths of the rows are forced to the specified overall
+table width, if required by the design. The extra space is placed in the
+gutters.
+
+# The rows are butted together vertically, with no extra space between
+them.
+#.
+
+There are some interesting implications of this scheme:
+
+* Because every cell box in a column, except the widest, will not be filled
+with text, the template for each column must include at least one |\hfil|
+command to take up the slack. These |\hfil| commands are included in the
+builtin templates described below.
+
+* Because there is no extra space between the rows, each row must occupy the
+full height and depth of the tabular body font, plus any interrow space.
+Otherwise the rows will not be spaced uniformly. It is this requirement that
+makes ruled tables tricky.
+*.
+
+=== The Template
+
+The template argument to the |\tabular| command is coded as a sequence of
+format specifications, one for each column, in the desired order.
+
+| \tabular{*type*}{@*x* @*y* ... @*z*}
+
+The available column formats are specified as follows. Spaces and line
+breaks may appear in the template for readability.
+
+* |@l|&_Single line; text flush left.
+
+* |@c|&_Single line; text centered.
+
+* |@r|&_Single line; text flush right.
+
+* |@L{*picture*}|&_Decimal-aligned number; text flush left. See below.
+
+* |@C{*picture*}|&_Decimal-aligned number; text centered.
+
+* |@R{*picture*}|&_Decimal-aligned number; text flush right.
+
+* |@p{*width*}|&_Text set in multiple lines as one or more
+paragraphs. The width of the line is specified.
+The raggedness, hang, and paragraph skip is
+determined by the design.
+
+* |@e{*width*}|&_Empty column of the specified width.
+
+* |@s{*sequence*}|&_Special custom column. See below.
+
+* |@&||&_Column contains a vertical rule whose color and
+width are determined by the design. This is a real
+column that must be included in each row, but is
+normally empty.
+
+* |@!{*color*}{*width*}|&_Column contains a vertical rule whose color and
+width are specified.
+
+* |@>{*width*}|&_This template may appear following any of the
+above templates. It specifies the exact width of
+the gutter between the current column and the next,
+in place of the standard gutter determined by the
+design. Rule columns are surrounded by gutters half
+as wide as the standard, unless overridden with |@>|.
+If the width is follow by an asterisk (|&*|), then
+the gutter can vary in width according to the
+|\columngutter| parameter of the design.
+*.
+
+=== Decimal-Aligned Columns
+
+Decimal-aligned column templates include a picture that determines how the
+cells are aligned. The picture is composed of the following characters:
+
+& |0|& Represents a digit.
+& |.|& Specifies the position of the decimal point.
+& |,|& Indicates a comma in the number.
+& |$-$|& Indicates that the number may be preceded by a negative sign.
+& |(...)|& Indicates that the number may be surrounded by parentheses.
+&.
+
+If there is no decimal point in the picture, the cells are aligned on the
+right. If there is a decimal point, they are aligned on the point. The
+difference between left-, center-, and right-aligned number columns is
+irrelevant unless a nonnumeric cell in the column is wider than the widest
+numeric cell. In this case the numeric cells are set flush left, center, or
+right on those wider cells. This happens when the column heads are wider
+than the numbers.
+
+Because ZzTeX splits decimal-aligned numbers at their decimal points, it is
+necessary that both halves of the picture and of all the cell numbers
+be balanced with respect to braces and dollar signs.
+
+=== Special Custom Columns
+
+A special custom column can be used to construct a complex column that
+contains boilerplate material. For example, imagine a left column in which
+all entries should be in italic and enclosed in parentheses. This column
+could be specified as follows:
+
+| \tabular{table}{... @s{\emph{(#)}\hfil} ...}
+| ...& special& ...\cr
+| ...& critical& ...\cr
+
+The two cells would appear in italic in this format:
+
+| ... *(special)* ...
+| ... *(critical)* ...
+
+Each cell is formatted by replacing the template sequence's sharp sign (|#|)
+with the text specified in the row cell, then using the resulting sequence as
+the final text of the cell. In the first row above, the final text would be
+|\emph{(special)}\hfil|. Note that the template includes an |\hfil| command to
+take up the slack and left-align the text. Don't forget the sharp sign and
+at least one |\hfil|.
+
+=== |\tabular| Tools
+
+The following list includes all the tools that can be used with a |\tabular|
+block. You can explore these various commands to learn what they do.
+
+~foreach name, name_set;
+* |~.name;|
+~end;
+*.
+
+// \todo Block
+// ----- -----
+
+.details todo_details \todo
+.template todo_details
+== To-Do Facility
+
+The to-do facility allows you to place a
+reminder in a book file and optionally to typeset '???' to represent text
+that is still to come.
+
+The \todo command has three forms. The first form is used most frequently.
+
+| \todo{This math display needs to be cleaned up later.}
+
+This command displays the message on your console and includes it in the log
+file. Processing continues without interruption. A summary of the number of
+to-do reminders is displayed at the end of the run.
+
+| \todo{!Cannot continue until this table is formatted correctly.}
+
+This variant includes the message in the log file, but then generates a
+warning message and halts execution. You can continue processing by
+pressing Enter. Use this variant to force a halt when the division is
+processed.
+
+| \todo{?cover image credit}
+
+This command is similar to the first variant, but also typesets a triple
+question mark (|???|) where the |\todo| appears. You can use this variant to set
+the standard triple question mark where text will be supplied later.
+
+To obtain a list of all the outstanding to-dos, try |~.facility; to-dos|.
+
+.end
diff --git a/macros/plain/contrib/zztex/doc/zzphrase.dat b/macros/plain/contrib/zztex/doc/zzphrase.dat
new file mode 100644
index 0000000000..5265a53372
--- /dev/null
+++ b/macros/plain/contrib/zztex/doc/zzphrase.dat
@@ -0,0 +1,3085 @@
+//---------------------------------------------------------------------------
+//
+// Copyright (c) 2012--2018 by Paul C. Anagnostopoulos
+//
+// This software may be used on your own computer systems and may
+// be distributed freely to other people. It may not be sold or
+// incorporated into any commercial products.
+//
+// Paul C. Anagnostopoulos
+// Windfall Software
+// 978 371-2316
+// paul@windfall.com
+//
+//---------------------------------------------------------------------------
+//
+// ZzExplore: Describe built-in TeX, Plain TeX, ZzTeX, and design
+// file entities for compositors.
+//
+// This is the main phrase file.
+//
+// Created: 3 March 2016
+
+
+// The following three templates are used to produce helpful explanations
+// for phrases that do not match.
+
+// No match to phrase
+
+.template no_match
+= No Match
+Your request: ~.phrase;
+
+There is no match for "~.word;".
+
+~if not empty? choice;
+Some possibilities are:
+~foreach ph, choice;
+* ~.ph;
+~end;
+*.
+~fi;
+----
+If you think your request is reasonable, please inform Paul.
+
+// Ambiguous match to phrase
+
+.template ambiguous_match
+= Ambiguous Match
+Your request: ~.phrase;
+
+The word "~.word;" is ambiguous.
+
+Some possibilities are:
+~foreach ph, choice;
+* ~.ph;
+~end;
+*.
+----
+If you think your request is unambiguous, please inform Paul.
+
+// Partial phrase
+
+.template partial_phrase
+= Partial Phrase
+Your request: ~.phrase;
+
+These words match the beginning of a phrase, but additional
+words are needed.
+
+~if not empty? choice;
+Some possibilities are:
+~foreach ph, choice;
+* ~.ph;
+~end;
+*.
+~fi;
+
+If you are looking for a concept instead of specific examples,
+it might help to try the plural of the word.
+----
+If you think your request is complete enough to produce
+a description, please inform Paul.
+
+// Help Text
+// ---- ----
+
+
+// Help
+
+.phrase help help : text
+.template
+= ~.facility; v~.version;
+
+~.facility; allows you to view descriptions of characters, commands,
+block designs, and other entities that are defined by built-in TeX,
+Plain TeX, ZzTeX, and book design files. It can also present more
+detailed reports on concepts such as tags and tabular material.
+
+Invoke ~.facility; as follows:
+
+| > ~.facility; *word* *word* ...
+
+The *word* parameters form a phrase that ~.facility; uses to determine
+which information you want to see. If you don't include any words, this
+help text is displayed. Do *not* include question words and verbs in your
+request (e.g., "what is").
+
+~include command_line_chars;
+
+Without any options, the description is displayed on your terminal. If you
+want to view a more stylish description in your browser, enter
+
+| > ~.facility; -browser *word* *word* ...
+
+The browser starts up in an independent window, allowing you to work and
+read the description at the same time. Remember that you can close the
+browser window with Alt+F4.
+
+It is recommended that you add the following
+alias to your 4NT/Take Command alias file:
+
+ exp*lore=~.facility; -browser %$
+
+For a list of interesting examples of ~.facility;, enter
+
+| > ~.facility; examples
+
+For a list of what's new in version ~.version; and earlier versions, enter
+
+| > ~.facility; what's new
+
+.phrase examples examples : text
+.template
+= Examples
+
+Here are some examples of things you can do with ~.facility;.
+
+* To see an overview of the current project:
+
+ ~.facility; overview
+
+* To learn about a particular command:
+
+ ~.facility; \overrideparlength
+
+* To find out whether a command is available for the current book:
+
+ ~.facility; \separatefloat
+
+* To get information about a particular math character:
+
+ ~.facility; \beta
+
+* To find out which types of enunciations or lists are available:
+
+ ~.facility; enunciations
+ ~.facility; lists
+
+* To see some details about a particular enunciation:
+
+ ~.facility; \enunciation theorem
+
+* To learn the names of the zzd design macros for enunciations:
+
+ ~.facility; enunciation designs
+
+* To see all the details about the design of a particular enunciation:
+
+ ~.facility; \enunciationtheoremdesign details
+
+* To learn what a count register is:
+
+ ~.facility; counts
+
+* To get a list of all count registers or learn about a particular one:
+
+ ~.facility; all counts
+ ~.facility; \sectionnumber
+
+* To see which type styles are available in the current book:
+
+ ~.facility; type styles
+
+* To find out which type relationship commands are available
+for a particular style:
+
+ ~.facility; \tt
+
+* To find out which styles are established for a particular type
+size and whether they can be used in math:
+
+ ~.facility; \footnotesize
+
+.phrase whats_new what's new : text
+.synonym what is new
+.template
+= What's New in ~.facility; v~.version;
+
+* Complete description of the |\enunciation| block.
+* Complete description of the indexing facility.
+* Report of all bibliography entries for the project.
+* Report of missing art files.
+* List of commands for bibliography citations.
+* Improved word matching for design elements that are not blocks.
+* Improved report on at-sign commands.
+* Complete documentation on the ZzSizeArt utility.
+* Complete documentation on the new |\tabbing| block.
+*.
+
+== What's New in ~.facility; v1.1
+
+* This "what's new" report.
+* Improved report on math classes.
+* Improved report on individual characters.
+* Improved report on Greek letter commands.
+* Report on the new |\immediatemathdisplay| modifier.
+* Improved report on the |\immediatesublist| modifier.
+* Reports on the new |\breakabove| and |\breakbelow| modifiers.
+* Improved reports on the |\bottomfloat| et al. modifiers.
+* New page make-up report.
+* Complete documentation on the |\tabular| block and related commands.
+* Lists of commands for horizontal spacing and vertical spacing.
+* Report on penalties.
+* Complete documentation on the |\todo| command.
+* Complete documentation on the title adjustment commands.
+* Report on block modifiers.
+* Complete documentation on the |\code| block and related commands.
+* Improved documentation on tags.
+* Complete documentation on the various forms of |\eqno|.
+* Complete documentation on the |\letterspace| command.
+* Complete documentation on the |\art| block.
+* Complete documentation on running heads and feet (runners).
+*.
+
+// ZzTeX et al Phrases
+// ----- -- -- -------
+
+
+// Accents
+
+.phrase accents accents
+.synonym text accents
+.template
+= Accent Commands
+
+An accent command produces an accent over a character.
+For example,
+
+ Ha\v{c}ek na\"{\i}vet\'e, anyone?
+
+produces
+
+& Ha&ccaron;ek na&iuml;vet&eacute;, anyone?
+&.
+
+Here is a list of all the accent commands.
+
+&= Command& Description
+----
+~foreach acc, accent_table;
+& |~.acc;|& ~.accent_table[acc];
+~end;
+&.
+----
+For information on a specific accent, try |~.facility; \*name*|.
+
+// (Assumes that the 'one_command' group will also be populated.)
+.phrase one_accent <name> accent
+.synonym accent <name>
+.synonym <name> text accent
+.synonym text accent <name>
+.template
+= |~.name;| Accent Command
+
+~include common_info;
+
+~.comment;
+
+An accent command produces an accent over a character.
+----
+For a list of all accents, try |~.facility; accents|.
+
+// Attributes
+
+.phrase attributes attributes : text
+.synonym command attributes
+.template
+= Attributes
+
+When ~.facility; reports information about commands, math characters, and
+other entities, it includes an item called *attributes*. An attribute
+specifies special behavior of the command or character. Here is a list
+of all the attributes.
+
+* internal: The command is internal to Plain TeX or ZzTeX and is never
+used directly in design or book files.
+* long: The argument to the command can include multiple paragraphs.
+* outer: The command can only be used directly in a book file; it cannot
+be used by another command.
+* limits: The large operator (e.g., |\sum|) sets its limits above and below.
+* no limits: The large operator sets its limit as sub- and
+superscripts.
+* display limits: The large operator set its limits above and below when
+used in a math display; as scripts when used in text.
+*.
+
+// Blocks
+
+.phrase blocks blocks : text
+.synonym elements
+.template
+= Blocks
+
+The block is the primary design element provided by ZzTeX design
+files. A block generally spans a large amount of text that must
+be formatted in a special way. Examples are lists, footnotes,
+and framed text.
+
+Most blocks are started and ended with specific commands:
+
+ \list{bullet}
+ \item ...
+ ...
+ \endlist
+
+A few blocks, however, are started and ended with the same command:
+
+ \footnote{This is a footnote that will appear at the bottom.}
+
+A footnote has only one design style, or *type*. However, there can be an
+arbitrary number of different types of lists, such as bullet, number,
+label, and dialog. If a block requires a type, the type name is the first
+argument to the block command, as with |\list{bullet}| above.
+
+Two blocks, |\text| and |\list|, can also be nested to produce, say,
+multi-level lists. ZzTeX maintains the level counter automatically.
+
+Each block type and level has its own design. The designs are
+embodied in design macros in the design file. For example,
+the name of the design macro for a second-level bullet list is
+|\listbulletiidesign|. A design macro is essentially a list of
+assignments to *parameters* that control the formatting of the
+block's text.
+
+There are two ways to modify the design of a specific block.
+The first is to use a variant modifier, which produces predetermined
+changes to the design. Try |~.facility; variants| for more information.
+The second method is the |\with| modifier, which alters specified
+design parameters for the block. Try |~.facility; \with| for
+more information.
+----
+For a list of all the available blocks, try |~.facility; all blocks|.&/
+For details on a specific block, try |~.facility; \*name*|.
+
+.phrase all_blocks all blocks
+.template
+= List of Blocks
+
+This is the list of all the block elements available in ZzTeX.
+
+&= & Multiple& Can be& Used in
+&= Block command& types?& nested?& ~.project; design?
+----
+~foreach blk, type_table;
+& |~.blk;|& ~.type_table[blk];& ~.nest_table[blk];& ~.used_table[blk];
+~end;
+&.
+----
+For more information, try |~.facility; blocks|&/
+For information on a particular block, try |~.facility; \*name*|
+
+// (Assumes that the 'one_command' group will also be populated.)
+.phrase one_block <name> block
+.synonym block <name>
+.synonym <name> element
+.synonym element <name>
+.synonym <name> types
+.synonym <nb-name>
+.synonym <nb-name> blocks
+.synonym <nb-name> elements
+.synonym <nb-name> types
+.synonym <nb-name-s>
+.template
+= |~.name;| Block
+
+~include common_info;
+
+~.comment;
+
+The ~.name; block is one of the primary elements supported
+by ZzTeX.
+
+~if not used?;
+This block is not used in the ~.project; book.
+~elsif empty? level_table;
+This block is used in the ~.project; book.
+A ~.name; does not have multiple design types. Its single
+design is defined in ~.design_where;.
+~else;
+This table presents all the different
+types of |~.name;| blocks available in the ~.project; design.
+
+&= Type& Levels& Defined
+----
+~foreach type, level_table;
+& |~.type;|& ~.level_table[type];& ~.where_table[type];
+~end;
+&.
+~fi;
+----
+To see a description of this block's design parameters,
+try |~.facility; ~.name; parameters|.&/
+~if used?;~
+To see some details about the |~.name;| design~* not empty? level_table; for the ~.project;
+book, try |~.facility; ~.name; design|.&/~
+~fi;
+For more information about blocks in general, try |~.facility; blocks|.&/
+For a list of all available blocks, try |~.facility; all blocks|.&/
+
+.phrase block_params <name> parameters
+.synonym <name>=\mathdisplay:$$ parameters
+.synonym <name> design parameters
+.synonym <name>=\mathdisplay:$$ design parameters
+.template
+= |~.name;| Block Design Parameters
+
+Here is a list of all the design parameters for the |~.name;|
+block.
+
+&= Parameter& Type& Description
+----
+~foreach param, type_table;
+& |~.param;|& ~.type_table[param];& ~.desc_table[param];
+~end;
+&.
+
+// Block variants
+
+.phrase block_variants block variants : text
+.synonym variants
+.synonym design variants
+.template
+= Block Variants
+
+A block variant is a modifier that can be applied to a block
+command to alter the design of the block. Variants may only
+be applied to block commands.
+
+For example, the |\widefigure| variant might be applicable
+to a |\float| command to select a wider style for the figure.
+
+ \widefigure \float{figure}
+
+Often there is a group of variants that all vary the design
+of a block is related ways. For example, in addition to
+|\widefigure| we might have
+
+* |\sidebysidefigure|
+* |\widefigure|
+* |\broadsidefigure|
+*.
+
+Each of these modifiers applies to a figure float and vary its
+design in specific ways. The three variants are mutually exclusive:
+only one may be specified on any given |\float| command.
+----
+For more information about a specific variant, try |~.facility; \*name*|.&/
+To see a list of variants for a specific block, try |~.facility; \*block*|.
+
+.phrase one_block_variant <name>
+.synonym <name> variant
+.synonym variant <name>
+.synonym <name> block variant
+.synonym block variant <name>
+.synonym <name> design variant
+.synonym design variant <name>
+.template
+= |~.name;| Block Variant
+
+~include common_info;
+
+~.comment;
+
+A block variant is a modifier that can be applied to a block
+command to alter the design of the block. This variant
+applies to the |~.block;| block. It is a member of a group
+of variants:
+
+~foreach i, variant_list;
+* |~.variant_list[i];|
+~end;
+*.
+
+----
+For more information on block variants, try |~.facility; variants|.
+
+// Block modifiers
+
+.phrase block_modifiers block modifiers
+.synonym modifiers
+.template
+= Block Modifiers
+
+A block modifier is a command that can be applied to a block
+to alter the design of the block. Modifiers may only
+be applied to block commands.
+
+For example, the |\bottomfloat| modifier can be applied to
+a |\float| command to place the float at the bottom of the page.
+
+ \bottomfloat \float{figure}
+
+Note that block variants are another type of block modifier.
+
+Here is a list of all the block modifiers provided by ZzTeX and
+the ~.project; design. It does not include block variants.
+
+&= Modifier& Where defined
+----
+~foreach mod, where_table;
+& |~.mod;|& ~.where_table[mod];
+~end;
+&.
+----
+For more information about a specific modifier, try |~.facility; \*name*|.&/
+For more information on block variants, a type of modifier,
+try |~.facility; variants|.
+
+.phrase one_block_modifier <name>
+.synonym <name> modifier
+.synonym modifier <name>
+.synonym <name> block modifier
+.synonym block modifier <name>
+.template
+= |~.name;| Block Modifier
+
+~include common_info;
+
+~.comment;
+
+A block modifier is a command that can be applied to a block
+to alter the design of the block.
+----
+For more information on block modifiers, try |~.facility; modifiers|.
+
+// Box registers
+
+.phrase boxes box registers : text
+.synonym boxes
+.template
+= Box Registers
+
+A box register contains a box that has horizontal or vertical material
+in it. A box can contain a paragraph, a vertical sequence of paragraphs,
+a short text fragment for measuring, etc.
+
+A box register is accessed and set as follows:
+
+| \box \*name*
+| \setbox \*name* = \hbox {*horizontal material*}
+| \setbox \*name* = \vbox {*vertical material*}
+| \setbox \*name* = \vtop {*vertical material*}
+
+Boxes are never used directly in book files.
+----
+For a list of all boxes, try |~.facility; all boxes|.&/
+For information on a particular box, try |~.facility; \*name*|
+
+.phrase all_boxes all box registers
+.synonym all boxes
+.template
+= List of Box Registers
+
+This is the list of all box registers available in ZzTeX.
+
+&= Register& Description
+----
+~foreach reg, reg_table;
+& |~.reg;|& ~.reg_table[reg];
+~end;
+&.
+~include internal_note;
+----
+For more information, try |~.facility; boxes|
+
+.phrase one_box <name>
+.synonym <name> box
+.synonym box <name>
+.synonym <name> register
+.synonym register <name>
+.synonym <name> box register
+.synonym box register <name>
+.template
+= |~.name;| Box Register
+
+~include common_info;
+
+~.comment;
+
+Default: |~.default;|
+
+A box register contains a box that has horizontal or vertical material
+in it. A box can contain a paragraph, a vertical sequence of paragraphs,
+a short text fragment for measuring, etc.
+----
+For more information, try |~.facility; boxes|
+
+// Catcodes
+
+.phrase catcodes catcodes
+.synonym category codes
+.synonym character categories
+.synonym character category codes
+.template
+= Catcodes (Category Codes)
+
+A category code is assigned to every character read by TeX as it
+processes files. A character's category code determines how TeX handles
+that character.
+
+Here is a list of all the category codes.
+
+&= Number& Name& Meaning (example)
+----
+~foreach i, name_table;
+& ~.i;& |~.name_table[i];|& ~.meaning_table[i];
+~end;
+&.
+
+.phrase one_catcode <name>
+.synonym <name> catcode
+.synonym catcode <name>
+.synonym <name> category code
+.synonym category code <name>
+.template
+= |~.name;| Category Code
+
+~include common_info;
+
+~.comment;
+
+Value: ~.value;
+
+A category code is assigned to every character read by TeX as it
+processes files. A character's category code determines how TeX handles
+that character.
+----
+For more information and list of all catcodes, try |~.facility; catcodes|
+
+// Characters
+
+.phrase characters characters
+
+.phrase one_character <name>
+.synonym <name>=`T:tab
+.synonym <name>=`F:formfeed
+.synonym <name>=`R:newline
+.synonym <name>=`_:space
+.synonym <name>=":quote
+.synonym <name>=%:percent
+.synonym <name>=&:ampersand
+.synonym <name>=':apostrophe
+.synonym <name>=(:lparen
+.synonym <name>=,:comma
+.synonym <name>=<:less
+.synonym <name>=>:greater
+.synonym <name>=^:hat
+.synonym <name>=`=:equal
+.synonym <name>=``:backquote
+.synonym <name>=|:bar
+.template
+= ~.name; Character
+
+~include common_info;
+
+~.comment;
+
+& Catcode:& |~.catcode;|
+& Font position:& |~.position;|
+& Math class:& |~.math_class;|
+& Math family:& |~.math_family;|
+&.
+----
+For information on catcodes, try |~.facility; catcodes|.&/
+For information on math classes, try |~.facility; classes|.&/
+For information on math families, try |~.facility; families|.
+
+// Citation commands
+
+.phrase citations citations
+.synonym citation commands
+.template
+= Citation Commands
+
+A citation command is a command that accepts a bibliography item tag and produces
+a citation (reference) to that item. For example
+
+ As \citenoun{smith16} describes, the widget ...
+
+might produce
+
+& As Smith [2016] describes, the widget ...
+&.
+
+The following table lists all the citation commands available
+for the ~.project; book. Be careful to read about the commands
+defined in the design file (~.project;.zzd) first; some of
+them might specify that certain other citation commands should
+not be used.
+
+&= Command& Defined
+----
+~foreach cmd, where_table;
+& |~.cmd;|& ~.where_table[cmd];
+~end;
+&.
+
+// Command line
+
+.phrase command_line command line : text
+.template
+= Command Line
+
+Some characters are difficult or impossible to specify on the
+4NT/Take Command command line. The following table shows how to
+specify such characters by themselves or as the second
+character of a character command.
+
+& & How to Specify& How to Specify
+& Character& Character& Character Command
+----
+& <newline>& |newline|& |\.newline|
+& <formfeed>& |formfeed|& |\.formfeed|
+& <space>& |space|& |\.space|
+& |"|& |quote|& |\.quote|
+& |%|& |percent|& |\.percent|
+& |&&|& |ampersand|& |\.ampersand|
+& |'|& |apostrophe|& |\.apostrophe|
+& |(|& |lparen|& |\.lparen|
+& |,|& |comma|& |\.comma|
+& |<|& |less|& |\.less|
+& |&=|& |equal|& |\.equal|
+& |>|& |greater|& |\.greater|
+& |^|& |hat|& |\.hat|
+& |`|& |backquote|& |\.backquote|
+& |&||& |bar|& |\.bar|
+&.
+
+// Commands
+
+.phrase commands commands
+.synonym macros
+.template
+= Commands
+
+Commands are the primary entity with which TeX files are coded
+to produce beautiful text. A command name consists of a backslash
+(|\|) followed by
+
+* A sequence of upper- and lowercase letters (e.g., |\sin|), or
+* A single non-letter character (e.g., |\,|)
+*.
+
+Command names are *case-sensitive;* that is, an uppercase letter
+is different from the same lowercase letter. So |\big| and |\Big|
+are two different commands.
+
+A command name can operate by itself or it can require *arguments,*
+which are pieces of text that the command uses to perform its
+function. Arguments are usually enclosing in braces (|{|...|}|).
+However, if there is a single argument composed of a single Roman
+or Greek letter, then no braces are necessary.
+
+ For example, you can set an acute accent on a character using
+ braces, as in \'{a}, but the braces aren't necessary: \'a.
+
+When scanning a command, TeX has one rule that can cause trouble.
+Spaces and a single line break following a letter command are ignored.
+So the text
+
+ Don't you love the text that \TeX can produce?
+
+will result in the following:
+
+& Don't you love the text that TeXcan produce?
+&.
+
+There are two solutions, the first of which is preferred.
+
+ Don't you love the text that \TeX\ can produce?
+ Don't you love the text that \TeX{} can produce?
+
+Command names containing an at-sign (|@|) or beginning with '|z|'
+are internal to TeX and ZzTeX.
+----
+For information on a specific command, try |~.facility; \*name*|.&/
+For information on the attributes item included with individual
+command descriptions, try |~.facility; attributes|.&/
+~include command_line_chars;
+
+== Command Counts
+
+For your edification, this table presents the number of commands
+defined by TeX and ZzTeX.
+
+&= Count& Origin of command
+----
+& ~.builtin_count;& Built-in TeX
+& ~.plain_count;& Plain TeX macro package (many superceded by ZzTeX)
+& ~.zztex_count;& ZzTeX macro package
+& ~.zzd_count;& Design file(s)
+&.
+
+.phrase one_command <name>
+.synonym <name>=\`R:\.newline
+.synonym <name>=\`_:\.space
+.synonym <name>=\":\.quote
+.synonym <name>=\':\.apostrophe
+.synonym <name>=\,:\.comma
+.synonym <name>=\^:\.hat
+.synonym <name>=\`=:\.equal
+.synonym <name>=\``:\.backquote
+.synonym <name>=\mathdisplay:$$
+.synonym <name> command
+.synonym <name>=\`R:\.newline command
+.synonym <name>=\`_:\.space command
+.synonym <name>=\":\.quote command
+.synonym <name>=\':\.apostrophe command
+.synonym <name>=\,:\.comma command
+.synonym <name>=\^:\.hat command
+.synonym <name>=\`=:\.equal command
+.synonym <name>=\``:\.backquote command
+.synonym command <name>
+.synonym <name> macro
+.synonym macro <name>
+.template
+= |~.name;| Command
+
+~include common_info;
+
+~.comment;
+----
+~include command_info;
+
+// Count registers
+
+.phrase counts count registers : text
+.synonym counts
+.template
+= Count Registers
+
+A count register contains an integer that can be used as a counter,
+to number elements, to hold an integer parameter value, etc.
+
+A count register is accessed and set as follows:
+
+| \*name*
+| \*name* = *integer*
+
+Counts are rarely used directly in book files.
+----
+For a list of all count registers, try |~.facility; all counts|.&/
+For information on a particular count register, try |~.facility; \*name*|.
+
+.phrase all_counts all count registers
+.synonym all counts
+.template
+= List of Count Registers
+
+This is the list of all count registers available in ZzTeX.
+
+&= Register& Description
+----
+~foreach reg, reg_table;
+& |~.reg;|& ~.reg_table[reg];
+~end;
+&.
+~include internal_note;
+----
+For more information, try |~.facility; count registers|
+
+.phrase one_count <name>
+.synonym <name> count
+.synonym count <name>
+.synonym <name> register
+.synonym register <name>
+.synonym <name> count register
+.synonym count register <name>
+.template
+= |~.name;| Count Register
+
+~include common_info;
+
+~.comment;
+
+Default: |~.default;|
+
+A count register contains an integer that can be used as a counter,
+to number elements, to hold an integer parameter value, etc.
+----
+For more information, try |~.facility; counts|
+
+// Declarations
+
+.phrase declarations declarations : text
+.template
+= Declarations
+
+A TeX declaration has a name like a command, but it does not
+take any arguments. Instead, it pertains to the following text in
+the current brace group.
+
+Example: |{\it *text*}|
+
+The *text* is set in italic style, but text following the close brace
+is not. The braces limit the scope of the declaration.
+
+Declarations are used in design files but rarely in book files.
+There is almost always a command that should be used instead.
+
+Example: |\emph{*text*}|
+----
+For information on commands, try |~.facility; commands|
+
+.phrase one_declaration <name>
+.synonym <name> declaration
+.synonym declaration <name>
+
+// Designs
+
+.phrase designs designs : text
+.synonym block designs
+.template
+= Block Designs
+
+A block design is embodied in a macro usually located in a
+book's design file. There are a few block designs built into
+ZzTeX. The block design macro contains a list of block
+parameter assignments that together specify the features
+and format of the block.
+
+The block design macro name comes in three flavors.
+
+& |\def \footnotedesign|& The block does not have multiple types
+& |\def \floatfiguredesign|& The block has multiple types
+& |\def \listbulletidesign|& The block has multiple types and levels
+&.
+
+Within the design macro definition is a sequence of parameter
+assignments and other TeX coding to establish the design for
+that particular block, block type, or block type/level. Each
+time ZzTeX encounters a block in a book file, it executes the
+design macro to establish the design, then processes the contents
+of the block.
+----
+To see details about a design, try things like:
+
+| ~.facility; \listbulletidesign
+| ~.facility; \float{figure}
+| ~.facility; list bullet i
+
+// The phrases for a block with no type; e.g., \footnotedesign.
+
+.phrase one_design_notype <name>
+.synonym <name> macro
+.synonym <block> design
+.synonym <block>=\mathdisplay:$$ design
+.synonym <block> design macro
+.synonym <nb-block> design
+.synonym <nb-block> design macro
+.template
+= |~.name;| Design Macro
+
+~include common_info;
+
+~include design_info;
+
+~.comment;
+----
+~include gory_details;
+
+// The phrases for a block with a type, but no type specified.
+
+.phrase-dups one_design_type_general <block> designs
+.synonym <block> design macros
+.synonym <nb-block> designs
+.synonym <nb-block> design macros
+.template
+= |~.block;| Design Macros
+
+The following table shows a list of all the design macros
+available in the ~.project; book for the various types of |~.block;|.
+
+&= Design Macro& Element
+----
+~foreach des, design_table;
+& |~.des;|& ~.design_table[des];
+~end;
+&.
+----
+For information on a specific type, try |~.facility; ~.block; *type*|.
+
+// The phrases for a block with a specified type.
+
+.phrase one_design_type_specific <name>
+.synonym <name> macro
+.synonym <block> <type>
+.synonym <block> <type> design
+.synonym <block> <type> design macro
+.synonym <nb-block> <type>
+.synonym <nb-block> <type> design
+.synonym <nb-block> <type> design macro
+.synonym <type> <nb-block-s>
+.synonym <type> <nb-block> designs
+.synonym <type> <nb-block> design macros
+.template
+= |~.name;| Design Macro
+
+~include common_info;
+
+~include design_info;
+
+~.comment;
+----
+~include gory_details;
+
+// The phrases for a block with a type and level, but no type or level specified.
+
+.phrase-dups one_design_level_general <block> designs
+.synonym <block> design macros
+.synonym <nb-block> designs
+.synonym <nb-block> design macros
+.synonym <block> <type> designs
+.synonym <block> <type> design macros
+.synonym <nb-block> <type> designs
+.synonym <nb-block> <type> design macros
+.synonym <type> <nb-block-s>
+.synonym <type> <nb-block> designs
+.synonym <type> <nb-block> design macros
+.template
+= |~.block;| Design Macros
+
+The following table shows a list of all the design macros
+available in the ~.project; book for the various types of |~.block;|.
+
+&= Design Macro& Element
+----
+~foreach des, design_table;
+& |~.des;|& ~.design_table[des];
+~end;
+&.
+----
+For information on a specific type and level,
+try |~.facility; ~.block; *type* *level*|.
+
+// The phrases for a block with a specified type and level.
+
+.phrase one_design_level_specific <name>
+.synonym <name> macro
+.synonym <block> <type> <level>
+.synonym <block> <type> <level> design
+.synonym <block> <type> <level> design macro
+.synonym <nb-block> <type> <level>
+.synonym <nb-block> <type> <level> design
+.synonym <nb-block> <type> <level> design macro
+.template
+= |~.name;| Design Macro
+
+~include common_info;
+
+~include design_info;
+
+~.comment;
+----
+~include gory_details;
+
+.phrase design_details <name> details
+.template
+= ~.name; Design Details
+
+~include common_info;
+
+~include design_info;
+
+~if not empty? inblock_set;
+The design is modified when the block appears inside these surrounding blocks:
+~foreach blk,inblock_set,iter;~,blk,iter /= 1;~end;
+~fi;
+
+Here is a table of all the parameter values set by this design macro.
+
+&= Parameter& Type& Value& Note
+----
+~foreach param, type_table;
+& |~.param;|& ~.type_table[param];& |~.value_table[param];|& ~.note_table[param];
+~end;
+&.
+
+~if affected?;
+(Some parameters may be missing due to design changes caused by variants
+or nesting inside outer blocks.)
+~fi;
+----
+For the complete story on this design, see ~.where;.
+
+// Dimen registers
+
+.phrase dimens dimension registers : text
+.synonym dimensions
+.template
+= Dimen(sion) Registers
+
+A dimen register contains a dimension that can be used as the width,
+height, or depth of a box, an indentation amount, a page dimension, etc.
+
+A dimen register is accessed and set as follows:
+
+| \*name*
+| \*name* = *dimension*
+
+Dimensions are rarely used directly in book files.
+----
+For a list of all dimen registers, try |~.facility; all dimens|.&/
+For information on a particular dimen register, try |~.facility; \*name*|.
+
+.phrase all_dimens all dimension registers
+.synonym all dimensions
+.template
+= List of Dimen(sion) Registers
+
+This is the list of all dimen registers available in ZzTeX.
+
+&= Register& Description
+----
+~foreach reg, reg_table;
+& |~.reg;|& ~.reg_table[reg];
+~end;
+&.
+~include internal_note;
+----
+For more information, try |~.facility; dimen registers|
+
+.phrase one_dimen <name>
+.synonym <name> dimension
+.synonym dimension <name>
+.synonym <name> register
+.synonym register <name>
+.synonym <name> dimension register
+.synonym dimension register <name>
+.template
+= |~.name;| Dimen(sion) Register
+
+~include common_info;
+
+~.comment;
+
+Default: |~.default;|
+
+A dimen(sion) register contains a dimension that can be used as the width,
+height, or depth of a box, an indentation amount, a page dimension, etc.
+----
+For more information, try |~.facility; dimens|
+
+// Encodings
+
+.phrase encodings style encodings
+.synonym encodings
+.synonym font encodings
+.template
+= Style Encodings
+
+A style encoding is an integer value that specifies the overall organization
+of the fonts associated with that style. For example:
+
+* \encoderoman is the encoding for typical Roman text fonts.
+* \encodeitalic is the encoding for typical italic text fonts.
+* \encodemathitalic is the encoding for math fonts containing
+italic letters for use as variables.
+*.
+
+The encoding for a type style is specified in the |\definetypestyle|
+command for that style.
+
+Here are all the style encodings supported by ZzTeX.
+
+&= Encoding& Value& Meaning
+----
+~foreach val, value_set;
+& ~.encoding_table[val];& ~.val;& ~.meaning_table[val];
+~end;
+&.
+----
+For a list of type styles and their encodings, try |~.facility; type styles|.
+
+.phrase one_encoding <name>
+.synonym <name> encoding
+.synonym encoding <name>
+.synonym <name> style encoding
+.synonym style encoding <name>
+.synonym <name> font encoding
+.synonym font encoding <name>
+.template
+= |~.name;| Style Encoding
+
+~include common_info;
+
+~.comment;
+
+Value: ~.value;
+
+A style encoding is an integer value that specifies the overall organization
+of the fonts associated with that style.
+----
+For more information and list of all encodings, try |~.facility; style encodings|
+
+// End-of-enunciation dingbats
+
+.phrase eoe_dingbats end-of-enunciation dingbats : text
+.synonym dingbats
+.synonym eoe dingbats
+.synonym enunciation dingbats
+.template
+= End-of-Enunciation Dingbats
+
+An end-of-enunciation dingbat (eoe dingbat) is an icon that is set
+at the end of an enunciation. A mathemtical proof, for example, almost
+always has a dingbat at the end. The command for the dingbat would be
+|\qed|.
+
+The dingbat is set automatically at the end of the enunciation, or you
+can specify it explicitly using its command name.
+----
+For information on a specific dingbat, try |~.facility; \*name*|
+
+// (Assumes that the 'one_command' group will also be populated.)
+.phrase one_eoe_dingbat <name> dingbat
+.synonym dingbat <name>
+.synonym <name> eoe dingbat
+.synonym eoe dingbat <name>
+.synonym <name> enunciation dingbat
+.synonym enunciation dingbat <name>
+.synonym <name> end-of-enunciation dingbat
+.synonym end-of-enunciation dingbat <name>
+.template
+= |~.name;| End-of-Enunciation Dingbat Command
+
+~include common_info;
+
+~.comment;
+
+& Text of dingbat:& |~.text;|
+& Position:& |~.position;|
+&.
+
+An end-of-enunciation dingbat (eoe dingbat) is an icon that is set
+at the end of an enunciation.
+----
+For information on dingbats in general, try |~.facility; dingbats|
+
+// Enumerated Names
+
+.phrase one_chardef_enum <name>
+.template
+= ~.name; Symbolic Number
+
+~include common_info;
+
+~.comment;
+
+Value: ~.value;
+
+A symbolic number is a name assigned to a number to make it easier
+to refer to the number without having to remember its value. A symbolic
+number is often referred to as an *enumerated value.*
+
+~include internal_note;
+
+// Flags
+
+.phrase flags flags : text
+.synonym booleans
+.template
+= Flags
+
+A flag is a true/false (boolean) value stored in a TeX macro
+(not a register). It can be used to specify a yes/no option,
+the state of some binary choice, the result of a test, etc.
+
+A flag is accessed and set as follows:
+
+| \*name*
+| \setflag \*name* = \true
+| \setflag \*name* = \false
+
+Flags are rarely used directly in book files.
+----
+For a list of all flags, try |~.facility; all flags|.&/
+For information on a particular flag, try |~.facility; \*name*|.
+
+.phrase all_flags all flags
+.synonym all booleans
+.template
+= List of Flags
+
+This is the list of all flags available in ZzTeX.
+
+&= Name& Description
+----
+~foreach flag, flag_table;
+& |~.flag;|& ~.flag_table[flag];
+~end;
+&.
+~include internal_note;
+----
+For more information, try |~.facility; flags|
+
+.phrase one_flag <name>
+.synonym <name> flag
+.synonym flag <name>
+.synonym <name> boolean
+.synonym boolean <name>
+.template
+= |~.name;| Flag
+
+~include common_info;
+
+~.comment;
+
+Default: |~.default;|
+
+A flag is a true/false (boolean) value stored in a TeX macro
+(not a register). It can be used to specify a yes/no option,
+the state of some binary choice, the result of a test, etc.
+----
+For more information, try |~.facility; flags|
+
+// Fonts
+
+.phrase fonts fonts : text
+.synonym type fonts
+.template
+= Font Declarations
+
+A font declaration establishes the type font for the current brace
+group. In TeX, a font is a specific type family and style set at a
+particular size. Some common examples:
+
+&= Font Declaration& Family, Style, Size
+----
+& |\tenhalfrm|& morg at 10.5pt& (|morg| is Minion-Regular)
+& |\tenhalfmit|& mtmiz at 10.5pt& (|mtmiz| is MathTime Math Italic)
+& |\tenhalfit|& moi at 10.5pt& (|moi| is Minion-Italic)
+& |\twelvedbf|& Flama-Bold at 12pt
+&.
+
+Font declarations are never used directly in design or book files, instead
+operating behind the scenes when font sizes and styles are selected.
+----
+For a list of all fonts in the ~.project; book, try |~.facility; all fonts|.&/
+For information about a particular font, try |~.facility; \*name*|.&/
+For information on type sizes or styles, try |~.facility; sizes| or
+|~.facility; styles|.
+
+.phrase all_fonts all fonts
+.template
+= List of Fonts
+
+This is the list of all the fonts used in the ~.project; book.
+
+&= Fonts& Family, style, size
+----
+~foreach font, font_table;
+& |~.font;|& ~.font_table[font];
+~end;
+&.
+----
+For more information, try |~.facility; fonts|.
+
+// (Assumes that the 'one_declaration' group will also be populated.)
+.phrase one_font <name> font
+.synonym font <name>
+.synonym <name> type font
+.synonym type font <name>
+.template
+= |~.name;| Font Declaration
+
+~include common_info;
+
+Font: ~.font_size;.
+
+A font declaration establishes the type font for the current brace group.
+Font declarations are never used directly in design or book files, instead
+operating behind the scenes when font sizes or styles are selected.
+----
+For more information on fonts, try |~.facility; fonts|.&/
+~include declaration_info;
+
+// Glyphs
+
+.phrase glyphs glyphs
+
+// (Assumes that the 'one_command' group will also be populated.)
+.phrase one_glyph <name> glyph
+.synonym glyph <name>
+.template
+= |~.name;| Glyph Command
+
+~include common_info;
+
+~.comment;
+
+Art spec: ~.art_spec;
+
+A glyph is a command that sets a small graphic used as an icon
+or attention indicator. The glyph scales with the surrounding font.
+
+// Ifs
+
+.phrase ifs ifs : text
+.synonym if flags
+.template
+= If Flags
+
+An if flag is similar to ZzTeX's flags but is only used by Plain
+TeX. Because all the if flags are internal to Plain TeX and
+never used in design or book files, no more information will
+be provided.
+
+// Inserts
+
+.phrase inserts inserts : text
+.template
+= Inserts
+
+An insert is one or more chunks of text that are to be inserted on
+the page at the top or bottom. Examples are floating figures,
+floating tables, and footnotes.
+
+ZzTeX defines an insert for floats at the top of the page,
+floats at the bottom, and footnotes. Each insert consist of
+three registers needed to manage the text: a count, a dimen,
+and a skip.
+
+Since the operation of inserts is entirely internal, there is no
+additional information about them.
+
+// Lets
+
+.phrase one_let <name>
+.synonym <name>=\%:\.percent
+.synonym <name>=\&:\.ampersand
+.synonym <name>=\<:\.less
+.synonym <name>=\>:\.greater
+.synonym <name> synonym
+.synonym <name>=\&:\.ampersand synonym
+.synonym <name>=\%:\.percent synonym
+.synonym <name>=\<:\.less synonym
+.synonym <name>=\>:\.greater synonym
+.synonym synonym <name>
+.template
+= |~.name;| Synonym
+
+~include common_info;
+
+Synonym for: |~.parent;|
+
+~.comment;
+
+A synonym is a name established with the |\let| command and is
+equivalent to its "parent" command. To see information on this name's
+parent command, try |~.facility; ~.parent;|.
+
+// Locators
+
+.phrase locators locators
+.synonym indexing commands
+.synonym indexing locators
+.template
+= Index Locators
+
+An index locator is a command that creates an entry in the
+book's index. It takes an argument with one, two, or three headings
+separated by bars:
+
+ \xpage{Main|subhead}
+
+Some locators can specify a page range, in which case there are
+two additional commands:
+
+ \xpagebegin{Main|subhead}
+ \xpageend{Main|subhead}
+
+If it is a command like |\xsee| and |\xseealso|, it takes an additional
+first argument with the heading to consult. In this example, the heading
+|Synonym| will refer to the heading |Primary|:
+
+ \xsee{Primary}{Synonym}
+
+The following locators are available for the ~.project; book:
+
+&= & Begin/end& See-like
+&= Command& commands?& reference?
+----
+~foreach i, command_list;
+& |~.command_list[i];|& ~.range_list[i];& ~.refers_list[i];
+~end;
+&.
+----
+~include indexing_info;
+
+// (Assumes that the 'one_command' group will also be populated.)
+.phrase one_locator <name> locator
+.synonym locator <name>
+.synonym <name> indexer
+.synonym indexer <name>
+.synonym <name> indexing command
+.synonym indexing command <name>
+.synonym <name> locator command
+.synonym locator command <name>
+.template
+= |~.name;| Index Locator Command
+
+~include common_info;
+
+~.comment;
+
+An index locator is a command that creates an entry in the book's index.
+The format of this locator command is shown above. There is one command
+if this kind of locator can only specify a single page. There are three
+commands if it can specify a single page or a page range. The commands for
+this locator are:
+
+~foreach cmd, command_list;
+* ~.command_list[cmd];
+~end;
+*.
+----
+For more information on locators, try |~.facility; locators|.
+
+// Marks
+
+.phrase marks marks
+.synonym page marks
+.template
+= Mark Pseudo-Commands
+
+A mark is a chunk of text inserted into the current page using the
+|\mark| command. The purpose of a mark is to hold information
+for running heads and feet. This information can be extracted from
+the page using pseudo-commands such as |\topmark| in the header
+and footer formatting macros.
+
+The |\mark| command and the extracting pseudo-commands are not used
+directly in ZzTeX design or book files. Instead, |\setmarkinfo| and
+|\markinfo| are used.
+
+Here is a list of all the mark pseudo-commands.
+
+&= Command& Description
+----
+~foreach mark, desc_table;
+& |~.mark;|& ~.desc_table[mark];
+~end;
+&.
+
+(Do not confuse marks with markers.)
+----
+For information on a specific mark, try |~.facility; \*name*|.
+
+.phrase one_mark <name>
+.synonym <name> mark
+.synonym mark <name>
+.synonym <name> page mark
+.synonym page mark <name>
+.template
+= |~.name;| Mark Pseudo-Command
+
+~include common_info;
+
+~.comment;
+
+A mark is a chunk of text inserted into the current page using the
+|\mark| command. The purpose of a mark is to hold information
+for running heads and feet.
+----
+For more information on marks, try |~.facility; marks|.
+
+// Markers
+
+.phrase markers markers
+.synonym argument markers
+.synonym command markers
+.template
+= Markers
+
+A marker indicates a point in a command argument where the following
+text is interpreted differently from the preceding text. For example,
+
+ $$
+ a = b \eqno
+ $$
+
+The |\eqno| marker indicates that the following text (empty in this
+example) should be interpreted as the equation number.
+
+Here is a list of all the markers provided by ZzTeX.
+
+&= Marker& Meaning
+----
+~foreach marker, comment_table;
+& |~.marker;|& ~.comment_table[marker];
+~end;
+&.
+
+(Do not confuse markers with marks.)
+----
+For information on a specific marker, try |~.facility; \*name*|.
+
+.phrase one_marker <name>
+.synonym <name> marker
+.synonym marker <name>
+.template
+= |~.name;| Marker
+
+~include common_info;
+
+~.comment;
+
+A marker indicates a point in a command argument where the following
+text is interpreted differently from the preceding text.
+----
+For more information on markers, try |~.facility; markers|.
+
+// Math accents
+
+.phrase math_accents math accents
+.template
+= Math Accent Commands
+
+A math accent command produces an accent over a math character.
+For example,
+
+ x = y \times \hat{a}
+
+produces
+
+& *x* = *y* &times; *&acirc;*
+&.
+
+Here is a list of all the math accent commands.
+
+&= Command& Description
+----
+~foreach acc, accent_table;
+& |~.acc;|& ~.accent_table[acc];
+~end;
+&.
+~include internal_note;
+----
+For information on a specific accent, try |~.facility; \*name*|.
+
+// (Assumes that the 'one_command' group will also be populated.)
+.phrase one_math_accent <name> accent
+.synonym accent <name>
+.synonym <name> math accent
+.synonym math accent <name>
+.template
+= |~.name;| Math Accent Command
+
+~include common_info;
+
+~.comment;
+
+A math accent command produces an accent over a math character.
+----
+For a list of all math accents, try |~.facility; math accents|.
+
+// Math characters
+
+// (Assumes that the 'one_command' group will also be populated.)
+.phrase one_math_char <name> character
+.synonym character <name>
+.synonym <name> symbol
+.synonym symbol <name>
+.synonym <name> math character
+.synonym math character <name>
+.synonym <name> math symbol
+.synonym math symbol <name>
+.template
+= |~.name;| Math Character
+
+~include common_info;
+
+~.comment;
+
+This command sets a math character or symbol with the following properties.
+
+& Math class:& |~.math_class;|
+& Math family:& |~.math_family;|
+& Font position:& ~.position;
+&.
+
+// Math character constants
+
+.phrase one_math_char_constant <name>
+
+// Math classes
+
+.phrase math_classes math classes
+.synonym classes
+.template
+= Math Classes
+
+Each math character and subexpression is assigned to one of the
+math classes shown below. The class determines how the character or
+subexpression is formatted. In particular, it determines the amount
+of space on each side of it. Each class is assigned a number, although
+you never need to worry about them.
+
+You can force a math expression into a particular class using the
+commands in the following table. Each takes an argument that is
+the expression to be classified. For example:
+
+ x \mathbin{.} y
+
+This forces the period to act like a binary operator, thus being set
+with a thin space on either side of it.
+
+&= Class& Number& Class Command& Description
+----
+~foreach i, class_list;
+& |~.class_list[i];|& ~.i;& |~.command_list[i];|& ~.desc_list[i];
+~end;
+&.
+
+.phrase one_chardef_math_class <name>
+.synonym <name> math class
+.synonym math class <name>
+.synonym <name> class
+.synonym class <name>
+.template
+= |~.name;| Math Class
+
+~include common_info;
+
+~.comment;
+
+Value: ~.value;
+
+Each math character and subexpression is assigned to a math class.
+The class determines how the character or subexpression is formatted.
+----
+For more information and list of all math classes, try |~.facility; math classes|.
+
+// (Assumes that the 'one_command' group will also be populated.)
+.phrase one_command_math_class <name> math class
+.synonym math class <name>
+.synonym <name> class
+.synonym class <name>
+.template
+= |~.name;| Math Class Command
+
+~include common_info;
+
+~.comment;
+
+A math class command forces its argument to be interpreted
+according to a particular math class (specified above) rather than its standard
+math class.
+----
+For more information on math classes, try |~.facility; math classes|.&/
+~include command_info;
+
+// Math families
+
+.phrase math_families math families : text
+.synonym family
+.synonym families
+.synonym type family
+.synonym type families
+.template
+= Math Families
+
+A math family is a number that is assigned to a type style so the
+style can be used in math expressions. Associated with the family
+are three fonts, one each for text size, script size, and scriptscript
+size. A type style cannot be used in math without a family number.
+This is occasionally a problem because there is a limit of 15 families.
+----
+For information about a particular family, try |~.facility; \*xx*fam|;
+for example, |~.facility; \rmfam|&/
+For a list of type styles and their associated families,
+try |~.facility; type styles|.
+
+.phrase one_math_family <name>
+.synonym family <name>
+.synonym <name> family
+.synonym <name> math family
+.synonym <name> type family
+.synonym math family <name>
+.synonym type family <name>
+.template
+= |~.name;| Math Family
+
+~include common_info;
+
+~.comment;
+
+& Type style:& |~.style;|
+& Family number:& ~.number;
+&.
+
+A math family is a number assigned to a type style so the style
+can be used in math expressions. Only families 0--14 are usable
+in math.
+----
+For more information on math families, try |~.facility; math families|
+
+// Math functions
+
+.phrase math_functions math functions : text
+.synonym functions
+.template
+= Math Functions
+
+Math functions are commands that set the names of mathematical functions
+such as sin and max. If the command is followed by a fence, the fence
+abuts the name. Otherwise a thin space follows the name. For example,
+
+ ... the $\sin x$ and the $\sin(x)$ are both ways of writing ...
+
+produces
+
+& ... the sin&thinsp;*x* and the sin(*x*) are both ways of writing ...
+&.
+----
+For information on a specific function, try |~.facility; \*name*|
+
+// (Assumes that the 'one_command' group will also be populated.)
+.phrase one_math_function <name> function
+.synonym function <name>
+.synonym <name> math function
+.synonym math function <name>
+.template
+= |~.name;| Math Function
+
+~include common_info;
+
+~.comment;
+
+& Sets:& ~.function;
+& Limits:& ~.limits;
+&.
+
+A math function is a command that sets a math function name,
+usually in roman.
+----
+For more information, try |~.facility; math functions|
+
+// Math joined symbols
+
+// (Assumes that the 'one_command' group will also be populated.)
+.phrase one_math_joined <name> joined math symbol
+.synonym joined math symbol <name>
+.synonym <name> joined symbol
+.synonym joined symbol <name>
+.synonym <name> math symbol
+.synonym math symbol <name>
+.template
+= |~.name;| Joined Math Symbol
+
+~include common_info;
+
+~.comment;
+
+A joined math symbol is constructed by adjoining one symbol
+with another. In this case, the symbol is built as:
+
+ ~.left; ~.right;
+----
+~include math_class_info;
+
+// Math stacked symbols
+
+// (Assumes that the 'one_command' group will also be populated.)
+.phrase one_math_stacked <name> stacked math symbol
+.synonym stacked math symbol <name>
+.synonym <name> stacked symbol
+.synonym stacked symbol <name>
+.synonym <name> math symbol
+.synonym math symbol <name>
+.template
+= |~.name;| Stacked Math Symbol
+
+~include common_info;
+
+~.comment;
+
+A stacked math symbol is constructed by stacking one symbol
+on top of another. In this case, the symbol is built as:
+
+ ~.above;
+ ~.below;
+----
+~include math_class_info;
+
+// Muskip registers
+
+.phrase muskips muskip registers : text
+.synonym muskips
+.template
+= Muskip Registers
+
+A muskip register contains a glue value (nominal, stretch, shrink)
+measured in math mu units (1/18 em). It can specify a horizontal space
+to be used in math. Muskip registers are only used in math.
+
+A muskip register is accessed and set as follows:
+
+| \*name*
+| \*name* = *mu-glue*
+
+Muskip registers are never used directly in book files.
+----
+For a list of all muskip registers, try |~.facility; all muskips|.&/
+For information on a particular muskip register, try |~.facility; \*name*|.
+
+.phrase all_muskips all muskip registers
+.synonym all muskips
+.template
+= List of Muskip Registers
+
+This is the list of all muskip registers available in ZzTeX.
+
+&= Register& Description
+----
+~foreach reg, reg_table;
+& |~.reg;|& ~.reg_table[reg];
+~end;
+&.
+~include internal_note;
+----
+For more information, try |~.facility; muskip registers|
+
+.phrase one_muskip <name>
+.synonym <name> muskip
+.synonym muskip <name>
+.synonym <name> register
+.synonym register <name>
+.synonym <name> muskip register
+.synonym muskip register <name>
+.template
+= |~.name;| Muskip Register
+
+~include common_info;
+
+~.comment;
+
+Default: |~.default;|
+
+A muskip register contains a glue value (nominal, stretch, shrink)
+measured in math mu units (1/18 em). It can specify a horizontal space
+to be used in math.
+----
+For more information, try |~.facility; muskips|
+
+// Math \text command
+
+.phrase math_text math \text : text
+.template
+= Math |\text| Command
+
+There is a |\text| command that can be used in math expressions
+to typeset its argument in text mode.
+
+Usage: |\text{*text*}|
+
+For example,
+
+ $$
+ x = 0.999\ldots = 1\quad \text{(see limits description)}
+ $$
+
+This math display would be set as follows.
+
+& *x*&thinsp;=&thinsp;0.999...&thinsp;=&thinsp;1&_(see limits description)
+&.
+
+Note that this |\text| command is only defined in math mode.
+
+// Named Characters
+
+.phrase one_named_char <name>
+.synonym <name>=\|:\.bar
+.synonym <name> character
+.synonym <name>=\|:\.bar character
+.synonym character <name>
+.template
+= ~.name; Named Character
+
+~include common_info;
+
+~.comment;
+
+Font position: |~.position;|
+
+A named character is a single character that is not on the keyboard but is
+assigned a name so that it can be easily typed. Some named characters also
+have a character command synonym (e.g., |\@| = |\atsign|).
+
+// Page make-up
+
+.phrase page_makeup page make-up
+.synonym page makeup
+.synonym paging
+.template
+= Page Make-Up
+
+Page make-up is the process of formatting the text on each
+page of a book. In particular, it involves deciding what
+text should appear on each page and on each spread.
+
+The following ZzTeX commands can help with page make-up.
+
+~foreach name, makeup_set;
+* |~.name;|
+~end;
+*.
+
+// Penalties
+
+.phrase penalties penalties
+.synonym penalty
+.template
+= Penalties
+
+A penalty is a number that specifies how much TeX should favor or
+disfavor a line break or page break. Positive penalties cause TeX
+to disfavor breaks, while negative penalties cause it to favor breaks.
+Penalties range from -10,000 (meaning always break) to +10,000 (meaning
+never break).
+
+Penalties are used in commands such as |\vpenalty|, |\linebreak|, and
+|\columnbreak|. These commands are rarely used in book files.
+
+Here is a table of all the available penalties.
+
+&= Penalty& Meaning
+----
+~foreach name, comment_table;
+& |~.name;|& ~.comment_table[name];
+~end;
+&.
+
+.phrase one_penalty <name>
+.synonym <name> penalty
+.synonym penalty <name>
+.template
+= |~.name;| Penalty
+
+~include common_info;
+
+~.comment;
+----
+For more information, try |~.facility; penalties|.
+
+// Prefixes
+
+.phrase prefixes prefixes
+.synonym command prefixes
+.template
+= Prefixes
+
+A prefix specifies an attribute of the name being defined
+using |\def| and related commands. It also specifies an
+attribute of I/O operations.
+
+Here is a list of all the prefixes.
+
+&= Prefix& Description
+----
+~foreach pre, prefix_table;
+& |~.pre;|& ~.prefix_table[pre];
+~end;
+&.
+
+.phrase one_prefix <name>
+.synonym <name> prefix
+.synonym prefix <name>
+.synonym <name> command prefix
+.synonym command prefix <name>
+.template
+= |~.name;| Prefix
+
+~include common_info;
+
+~.comment;
+
+A prefix specifies an attribute of the name being defined
+using |\def| and related commands. It also specifies an
+attribute of I/O operations.
+----
+For more information, try |~.facility; prefixes|.
+
+// Skip (Glue) registers
+
+.phrase skips skip registers : text
+.synonym skips
+.synonym glue registers
+.synonym glues
+.template
+= Skip Registers
+
+A skip register contains a glue value (nominal, stretch, shrink)
+that can specify a horizontal or vertical space, a left or right
+indentation, a gutter, etc.
+
+A skip register is accessed and set as follows:
+
+| \*name*
+| \*name* = *glue*
+
+Skip registers are never used directly in book files.
+----
+For a list of all skip registers, try |~.facility; all skips|.&/
+For information on a particular skip register, try |~.facility; \*name*|.
+
+.phrase all_skips all skip registers
+.synonym all skips
+.synonym all glue registers
+.template
+= List of Skip (Glue) Registers
+
+This is the list of all skip registers available in ZzTeX.
+
+&= Register& Description
+----
+~foreach reg, reg_table;
+& |~.reg;|& ~.reg_table[reg];
+~end;
+&.
+~include internal_note;
+----
+For more information, try |~.facility; skip registers|
+
+.phrase one_skip <name>
+.synonym <name> skip
+.synonym skip <name>
+.synonym <name> register
+.synonym register <name>
+.synonym <name> skip register
+.synonym skip register <name>
+
+.synonym <name> glue
+.synonym glue <name>
+.synonym <name> glue register
+.synonym glue register <name>
+.template
+= |~.name;| Skip (Glue) Register
+
+~include common_info;
+
+~.comment;
+
+Default: |~.default;|
+
+A skip register contains a glue value (nominal, stretch, shrink)
+that can specify a horizontal or vertical space, a left or right
+indentation, a gutter, etc.
+----
+For more information, try |~.facility; skips|
+
+// Spacing
+
+.phrase spacing spacing : text
+.template
+= Spacing Commands
+
+To see a list of commands for horizontal spacing,
+try |~.facility; horizontal spacing|.
+
+To see a list of commands for vertical spacing,
+try |~.facility; vertical spacing|.
+
+.phrase horizontal_spacing horizontal spacing
+.template
+= Horizontal Spacing
+
+This table presents a list of all the horizontal spacing commands
+available in ZzTeX.
+
+A command described as *breakable* allows a preceding line break, and the
+space is discarded. A command described as *unbreakable* does not allow a
+preceding line break.
+
+~foreach cmd, comment_table;
+& |~.cmd;|& ~.comment_table[cmd];
+~end;
+&.
+----
+For more information on any of these commands, try |~.facility; \*name*|.
+
+.phrase vertical_spacing vertical spacing
+.template
+= Vertical Spacing
+
+Here is a list of all the vertical spacing commands available in ZzTeX.
+
+~foreach name, name_set;
+* |~.name;|
+~end;
+*.
+----
+For more information on any of these commands, try |~.facility; \*name*|.
+
+// Suffixes
+
+.phrase suffixes suffixes
+.synonym command suffixes
+.template
+= Suffixes
+
+A suffix can be affixed to certain math commands to specify
+how limits are to be set.
+
+Here is a list of all the suffixes.
+
+&= Suffix& Description
+----
+~foreach suf, suffix_table;
+& |~.suf;|& ~.suffix_table[suf];
+~end;
+&.
+
+.phrase one_suffix <name>
+.synonym <name> suffix
+.synonym suffix <name>
+.synonym <name> command suffix
+.synonym command suffix <name>
+.template
+= |~.name;| Suffix
+
+~include common_info;
+
+~.comment;
+
+A suffix can be affixed to certain math commands to specify
+how limits are to be set.
+----
+For more information, try |~.facility; suffixes|.
+
+// Titles
+
+.phrase titles titles
+.synonym heads
+.synonym adjustments
+.synonym head adjustments
+.synonym title adjustments
+.template
+= Titles and Their Adjustment
+
+A *title* or *head* appears in various ZzTeX commands, including
+hierarchy commands such as |\chapter| and |\section|, captions,
+enunciations, etc. Each of these commands takes an argument that
+specifies the text of the title.
+
+| \chapter{*title-text*}
+
+The title text can appear in various places:
+
+* In the body of the text at the position of the |\chapter| command.
+* In the running heads or feet of multiple pages.
+* In the main table of contents or a "mini-ToC" such as might
+appear at the beginning of each chapter.
+*.
+
+Sometimes it is necessary to modify the title slightly when it appears in
+these various places. For example, if a title has a footnote, that footnote
+does not want to appear in the running head or table of contents. ZzTeX
+provides the following commands that can be used within the text of a title
+to make such adjustments.
+
+~foreach cmd, command_set;
+* |~.cmd;|
+~end;
+*.
+
+// Toks registers
+
+.phrase toks toks registers : text
+.synonym toks
+.synonym tokens
+.synonym token registers
+.template
+= Toks (Token) Registers
+
+A toks (token) register contains a sequence of TeX tokens (characters, commands,
+spaces, etc.) that can specify a text fragment, file name, tag, options
+list, etc.
+
+A toks register is accessed and set as follows:
+
+| \*name*
+| \*name* = {*tokens*}
+
+Toks registers are never used directly in book files.
+----
+For a list of all toks registers, try |~.facility; all toks|.&/
+For information on a particular toks register, try |~.facility; \*name*|.
+
+.phrase all_toks all toks registers
+.synonym all toks
+.synonym all token registers
+.synonym all tokens
+.template
+= List of Toks (Token) Registers
+
+This is the list of all toks registers available in ZzTeX.
+
+&= Register& Description
+----
+~foreach reg, reg_table;
+& |~.reg;|& ~.reg_table[reg];
+~end;
+&.
+~include internal_note;
+----
+For more information, try |~.facility; toks registers|
+
+.phrase one_toks <name>
+.synonym <name> toks
+.synonym toks <name>
+.synonym <name> register
+.synonym register <name>
+.synonym <name> toks register
+.synonym toks register <name>
+
+.synonym <name> token
+.synonym token <name>
+.synonym <name> token register
+.synonym token register <name>
+.template
+= |~.name;| Toks (Token) Register
+
+~include common_info;
+
+~.comment;
+
+Default: |~.default;|
+
+A toks register contains a sequence of TeX tokens (characters, commands,
+spaces, etc.) that can specify a text fragment, file name, tag, options
+list, etc.
+----
+For more information, try |~.facility; toks|
+
+// Style relations
+
+.phrase style_relations style relations
+.synonym relations
+.synonym font relations
+.synonym type relations
+.template
+= Style Relation Commands
+
+A style relation is a command that selects a new type style for
+its argument text based on the prevailing type style. The argument text
+is set in the new style and then the prevailing style continues.
+For example,
+
+| *...* a set of \emph{dependencies} on parent structures *...*
+
+might typeset the text as
+
+& *...* a set of *dependencies* on parent structures *...*
+&.
+
+Style relation commands are used instead of the underlying type
+style declarations (e.g., |\it|) for various reasons, the most
+important one being that the style change is restricted to the
+argument text.
+
+Here is a list of the relation commands available for the ~.project;
+book. For more details about a particular relation, try |~.facility;
+\*name*|.
+
+&= Relation& Where defined
+----
+~foreach rel, relation_table;
+& |~.rel;|& ~.relation_table[rel];
+~end;
+&.
+
+*Note:* The |\mono| command is used like a relation, but it is
+actually just a normal command.
+----
+~include command_info;
+
+// (Assumes that the 'one_command' group will also be populated.)
+.phrase one_style_relation relation <name>
+.synonym <name> relation
+.synonym <name> font relation
+.synonym <name> style relation
+.synonym <name> type relation
+.synonym font relation <name>
+.synonym style relation <name>
+.synonym type relation <name>
+.template
+= |~.name;| Style Relation Command
+
+~include common_info;
+
+~.comment;
+
+A style relation is a command that selects a new type style for
+its argument based on the prevailing type style. The argument text
+is set in the new style and then the prevailing style continues.
+
+Here is a table of all the relationships established by this command.
+
+&= Prevailing& & New
+&= style& & style
+----
+~foreach sty, style_map;
+& ~.sty;& &rArr;& ~.style_map[sty];
+~end;
+&.
+----
+For more information on style relations and a list of all available
+relations, try |~.facility; style relations|.&/
+~include command_info;
+
+// Tags
+
+.phrase tags tags : text
+.template
+= Tags
+
+A tag is a TeX name that is used to store information about a particular
+spot in a book. You can tag a spot using the |\tag| command.
+
+ \section{All About Tags}
+ \tag{S:about-tags}
+
+The following information is associated with the tag |S:about-tags|:
+
+* The page number on which the tag is defined.
+
+* The composite number text of the enclosing element (in the above example,
+the section number).
+
+* The title or caption of the enclosing element.
+*.
+
+The following cross-referencing commands can be used to typeset the
+information asociated with a tag:
+
+& |\ref{*tag*}|& Set the composite number text.
+& |\refpage{*tag*}|& Set the page number.
+& |\reftitle{*tag*}|& Set the title (rarely used).
+&.
+
+If the |\tag| command is used at a point in the text where there is
+no surrounding taggable element, an error message is produced. In this
+situation, if you only want to reference the page number, use the |\tagpageonly|
+command instead.
+
+== Tag Names
+
+If you need to add a tag to a book, please follow the naming conventions
+chosen by the author. If the author was haphazard, use the following
+prefixes on tags of various kinds:
+
+&= Prefix& Meaning
+----
+& |A:|& appendix
+& |C:|& chapter or quasichapter
+& |E:|& equation
+& |F:|& figure
+& |I:|& list item
+& |P:|& page number of arbitrary text (with |\tagpageonly|)
+& |S:|& section, subsection, etc.
+& |T:|& table
+& |X:|& exercise
+&.
+
+Tags names beginning with |z*X*:|, where *X* is a capital letter, are
+internal to ZzTeX. For a description of these internal tags,
+try |~.facility; internal tags|.
+----
+To obtain a list of all the tags in the ~.project; book, try
+|~.facility; all tags|.
+
+.phrase internal_tags internal tags : text
+.template
+= Internal Tags
+
+Here is a list of all the internal tags used by ZzTeX.
+
+&= Tag prefix& Usage
+----
+& |zB:|& Bibliographic entry information.
+& |zE:|& Page number of frame element.
+& |zF:|& Page number of float element.
+& |zH:|& Error message help text.
+& |zM:|& Page number of marginnote element.
+& |zP:|& Page number of proofnote element.
+& |zR:|& Page number of marginrule element.
+& |zS:|& Composite cross-reference snapshot information.
+&.
+----
+For a description of tags in general, try |~.facility; tags|.
+
+// Type styles
+
+.phrase type_styles type styles
+.synonym styles
+.synonym font styles
+.template
+= Type Styles
+
+A type style is a declaration that establishes the current style for
+text (e.g., roman, italic). As with all declarations, it pertains only
+to the following text in the current brace group.
+
+Type styles are rarely used directly in book files. Instead, the current
+style is established using a style relation command such as |\emph| or
+|\bold|. To see a list of all the relation commands, try |~.facility;
+type relations|. To see a list for a particular style, along with
+information about that style, try |~.facility; \*style*|.
+
+Here are all the type styles available for the ~.project; book.
+&= & & Family& Family& Usable
+&= Style& Encoding& number& name& in math?
+----
+~foreach fam, family_list;
+& |~.style_list[fam];|& |~.encoding_list[fam];|& ~.fam;& |~.family_list[fam];|&
+~.math_list[fam];
+~end;
+&.
+----
+For information on encodings, try |~.facility; encodings|.&/
+~include declaration_info;
+
+// (Assumes that the 'one_declaration' group will also be populated.)
+.phrase one_type_style type style <name>
+.synonym <name> style
+.synonym style <name>
+.synonym <name> font style
+.synonym font style <name>
+.template
+= |~.name;| Type Style Declaration
+
+~include common_info;
+
+~.comment;
+
+A type style is a declaration that establishes the current style for
+text (e.g., roman, italic). Instead of using the style declaration,
+you should use a style relation command. Here are the style relations
+pertinent to this style.
+
+&= Current style& Relation& New style
+----
+~foreach rel, new_style;
+& |~.name;|& |~.rel;|& |~.new_style[rel];|
+~end;
+&.
+----
+For more information on type styles, try |~.facility; type styles|&/
+For more information on type relations, try |~.facility; type relations|
+
+// Type sizes
+
+.phrase type_sizes type sizes : text
+.synonym sizes
+.synonym font sizes
+.template
+= Type Sizes
+
+A type size is a declaration that establishes the current size
+for text. As with all declarations, it pertains only
+to the following text in the current brace group.
+
+When a type size is established, there is no current style
+for the subsequent text. You must also establish a style
+after establishing a size.
+
+ {\footnotesize\it That '\it' command was necessary
+ to establish the style.}
+
+Type sizes are rarely used directly in book files. Instead, the
+surrounding element (typically a block) establishes the size
+for the text in that element. The main text size is always called
+|\textsize|.
+----
+To see a list of all the available type sizes, try |~.facility; all sizes|.&/
+To see the details of a particular size, try |~.facility; \*name*|.
+
+.phrase all_type_sizes all type sizes
+.synonym all sizes
+.synonym all font sizes
+.template
+= List of Type Sizes
+
+This is the list of all type sizes available in the ~.project; book.
+
+&= Size declaration& Available styles
+----
+~foreach size, style_table;
+& |~.size;|& |~.style_table[size];|
+~end;
+&.
+----
+For more information, try |~.facility; type sizes|.&/
+To see the details of a particular size, try |~.facility; \*name*|.
+
+// (Assumes that the 'one_declaration' group will also be populated.)
+.phrase one_type_size size <name>
+.synonym <name> size
+.synonym <name> type size
+.synonym type size <name>
+.synonym <name> font size
+.synonym font size <name>
+.template
+= |~.name;| Type Size Declaration
+
+~include common_info;
+
+~.comment;
+
+A type size is a declaration that establishes the current size
+for text. As with all declarations, it pertains only
+to the following text in the current brace group.
+
+Here is a list of all the type styles available in |~.name;|.
+
+&= & Can use& Can use
+&= Style& in math?& in scripts?& Family, style, size
+----
+~foreach i, style_list;
+& |~.style_list[i];|& ~.math_list[i];& ~.script_list[i];& ~.font_list[i];
+~end;
+&.
+----
+For more information on type sizes, try |~.facility; type sizes|.&/
+To see a list of all the available type sizes, try |~.facility; all sizes|.
+
+// Composite Cross-Reference Phrases
+// --------- --------------- -------
+
+
+.phrase all_art_files all art files
+.synonym art files
+.template
+= List of All Art Files for ~.project;
+
+This is a list of all the art files used in ~.project;, in order
+by file name.
+
+Count: ~.*div_table;
+
+&= Division& Page& File& Size at scale& Reused?
+----
+~foreach file, div_table;
+& ~.div_table[file];& ~.page_table[file];& ~.file;& ~.size_table[file];& ~.reused_table[file];
+~end;
+&.
+----
+For a list of just the missing art files, try |~.facility; missing art files|.
+
+.phrase all_biblio_entries all bibliography entries
+.synonym all bibliography tags
+.synonym bibliography entry list
+.synonym bibliography entries
+.template
+= List of All Bibliography Entries for ~.project;
+
+This is a list of all the bibliography entries in the ~.project;
+bibliography, in order by tag.
+
+Count: ~.*page_table;
+
+&= Page& Tag& Author& Year
+----
+~foreach tag, page_table;
+& ~.page_table[tag];& |~.tag;|& ~.author_table[tag];& ~.year_table[tag];
+~end;
+&.
+
+.phrase all_tags all tags
+.synonym tag list
+.template
+= List of All Tags for ~.project;
+
+This is a list of all the tags used in ~.project;,
+in order by tag name.
+(This list does not include bibliography entry tags.)
+
+Count: ~.*comp_table;
+
+&= Tag& Comp. Text& Division& Page
+----
+~foreach tag, comp_table;
+& |~.tag;|& ~.comp_table[tag];& ~.div_table[tag];& ~.page_table[tag];
+~end;
+&.
+
+Tags beginning with |\z*X*:| are internal to ZzTeX. For a description
+of those tags, try |~.facility; internal tags|.&/
+----
+For a list of all the bibliography entry tags, try |~.facility;
+all biblio tags|.
+
+.phrase book_info book information : text
+.template
+= Book Information
+
+~.facility; can show you all kinds of information about the
+~.project; project.
+
+& |~.facility;| command words& Report produced
+----
+& |overview|& Overview of the book and its design.
+& |all art files|& List of all art files.
+& |all biblio entries|& List of all bibliography entries.
+& |all tags|& List of all tags.
+& |cleanup report|& Report about cleanup of files.
+& |contents|& High-level table of contents.
+& |design report|& Report of elements with explanatory comments.
+& |duplicate tags|& List of duplicate tags.
+& |library|& List of documentation files in ZzTeX directory.
+& |missing art files|& List of missing art files.
+& |printer report|& Report to accompany final printer PDF.
+& |proofnote list|& List of outstanding proofnotes.
+& |to-do list|& List of outstanding to-dos.
+& |undefined tags|& List of undefined tags.
+&.
+
+.phrase contents contents
+.synonym table of contents
+.template
+= Table of Contents for ~.project;
+
+~foreach i, page_list;
+& ~.page_list[i];& ~.comp_list[i];& ~.title_list[i];
+~end;
+&.
+
+.phrase design_report design report
+.synonym compositor's design report
+.template
+= Design Report for ~.project;
+
+~include title_author_publisher_isbn;
+&.
+
+== Summary of Design
+
+~include design_summary;
+
+Every project starts with a cleanup of the text files.
+Try |~.facility; cleanup report| for a description of
+the cleanup of ~.project;.
+
+== Documented Elements
+
+The following sections present the book design elements that
+have specific documentation in the main design file ~.zzd_file;.
+It is a good idea to review these elements at the start of a project.
+
+~foreach i, head_list;
+~if not empty? head_list[i];
+=== ~.head_list[i];
+~fi;
+
+&starf;&_~.usage_list[i];
+
+~if value? style_list[i];
+& Style: ~.style_list[i];
+&.
+~fi;
+
+~.comment_list[i];
+~end;
+
+.phrase duplicate_tags duplicate tags
+.synonym duplicate tags list
+.template
+= List of Duplicate Tags for ~.project;
+
+This is a list of all the duplicate tags in the ~.project; book.
+
+Count: ~.*comp_table;
+
+&= Tag& Comp. Texts& Divisions& Pages
+----
+~foreach tag, comp_table;
+& |~.tag;|& ~.comp_table[tag];& ~.div_table[tag];& ~.page_table[tag];
+~end;
+&.
+----
+To see a list of all the tags, try |~.facility; all tags|.
+
+.phrase library library
+.synonym documentation
+.template
+= ZzTeX Documentation library
+
+The following text documents are available in the ZzTeX directory.
+They present details about various facilities in ZzTeX.
+
+&= Document& Topic
+----
+~foreach file, title_table;
+& ~.file;& ~.title_table[file];
+~end;
+&.
+
+.phrase missing_art_files missing art files
+.synonym missing art
+.template
+= List of Missing Art Files for ~.project;
+
+This is a list of the missing art files used in ~.project;, in order
+by file name. An art file is missing if there is an |\art| command
+for it but it does not exist in the art directory.
+
+Count: ~.*div_table;
+
+&= Division& Page& File& Size at scale& Reused?
+----
+~foreach file, div_table;
+& ~.div_table[file];& ~.page_table[file];& ~.file;& ~.size_table[file];& ~.reused_table[file];
+~end;
+&.
+----
+For a list of all the art files, try |~.facility; all art files|.
+
+.phrase printer_report printer report
+.template
+= Printer Report for ~.project;
+
+~include title_author_publisher_isbn;
+& &`
+& Trim:& ~.trimwidth; &times; ~.trimheight;
+& Head&`margin:& ~.headmargin;
+& Gutter:& ~.eveninnermargin;
+& &`
+& Fonts:& All embedded and subsetted at 100%
+& Art:& All embedded
+&.
+
+&`
+
+----
+Black: For 2-color books, please set Overprint Black as the default.
+----
+
+&`
+
+Paul C. Anagnostopoulos&/
+Windfall Software&/
+978 371-2316&/
+paul@windfall.com
+
+&`
+
+= Pagination
+
+~foreach i, page_list;
+& ~.page_list[i];& ~.comp_list[i];& ~.title_list[i];
+~end;
+&.
+
+.phrase-dups project_overview <project>
+.synonym book
+.synonym overview
+.synonym project
+.synonym book overview
+.synonym project overview
+.template
+= ~.project; Overview
+
+~include title_author_publisher_isbn;
+& &`
+& Processed:& ~.date; ~.time;
+& ZzTeX&`version:& v~.zztex_version;
+& &`
+& Art&`root:& ~.art_root;
+& Placing&`art?& ~.place_art;
+& PDF&`hyperlinks?& ~.hyperlinks;
+& &`
+& Proof&`ident:& ~.proof;
+& Compositor:& ~.compositor;
+& Company:& ~.company;
+&.
+
+== Summary of Design
+
+~include design_summary;
+----
+~.facility; can present all sorts of information about this project.
+Try |~.facility; book info|.
+
+.phrase proofnote_list proofnote list
+.synonym all proofnotes
+.template
+= List of All Proofnotes for ~.project;
+
+This is a list of all the outstanding proofnotes in the ~.project;
+files.
+
+Count: ~.*div_list;
+
+&= Division& Page& Note
+----
+~foreach i, div_list;
+& ~.div_list[i];& ~.page_list[i];& ~.note_list[i];
+~end;
+&.
+
+.phrase todo_list to-dos
+.synonym todos
+.synonym to-do list
+.synonym todo list
+.synonym all to-dos
+.synonym all todos
+.template
+= List of All To-Dos for ~.project;
+
+This is a list of all the outstanding to-do notes in the ~.project;
+files.
+
+Count: ~.*div_list;
+
+&= Division& Page& Note
+----
+~foreach i, div_list;
+& ~.div_list[i];& ~.page_list[i];& ~.note_list[i];
+~end;
+&.
+----
+
+.phrase undefined_tags undefined tags
+.synonym undefined tags list
+.template
+= List of Undefined Tags for ~.project;
+
+This is a list of all the undefined tags in the ~.project; files.
+
+Count: ~.*div_table;
+
+&= & First& First
+&= Tag& Division& Page& References
+----
+~foreach tag, div_table;
+& |~.tag;|& ~.div_table[tag];& ~.page_table[tag];& ~.refs_table[tag];
+~end;
+&.
+----
+To see a list of all the tags, try |~.facility; all tags|.
+
+// Footnotes
+// ---------
+
+
+.footnote defineenunciation_enunciation \defineenunciation one_command
+.footnote defineenunciation_enunciation \title one_marker
+.footnote defineenunciation_enunciation \attributiontypecase one_command
+.footnote defineenunciation_enunciation \defineeoedingbat one_command
+.template defineenunciation_enunciation
+For a complete description of this item, try |~.facility; \enunciation|.
+
+.footnote definelocator_locators \definelocator one_command
+.footnote definelocator_locators \definelocatorformat one_command
+.footnote definelocator_locators \generateindex one_command
+.footnote definelocator_locators \indexentry one_command
+.footnote definelocator_locators \alphabreak one_command
+.template definelocator_locators
+~include indexing_info;
+
+.footnote hat_zmhat \hat one_named_char
+.template hat_zmhat
+*Note:* When used in math mode, |\hat| is a synonym for |\zmhat|
+and produces a hat accent over its argument.
+
+.footnote space_spacing space one_character
+.template space_spacing
+If you are looking for information on spacing commands,
+try |~.facility; spacing|.
+
+.footnote proofnote_note_list \proofnote one_block
+.template proofnote_note_list
+If you are looking for a list of the outstanding proofnotes
+for the ~.project; project, try |~.facility; proofnote list|.
+
+.footnote text_math_text \text one_block
+.template text_math_text
+If you are looking for information on the \text command that
+is used in math, try |~.facility; math \text|.
+
+.footnote tilde_zmtilde \tilde one_named_char
+.template tilde_zmtilde
+*Note:* When used in math mode, |\tilde| is a synonym for |\zmtilde|
+and produces a tilde accent over its argument.
+
+.footnote toc_contents \toc one_block
+.template toc_contents
+If you are looking for a table of contents for ~.project;,
+try |~.facility; contents|.
+
+.footnote zmhat_hat \zmhat one_math_accent
+.template zmhat_hat
+*Note:* This is the internal accent command. Use |\hat| in book files.
+
+.footnote zmtilde_tilde \zmtilde one_math_accent
+.template zmtilde_tilde
+*Note:* This is the internal accent command. Use |\tilde| in book files.
+
+// Included Templates
+// -------- ---------
+
+
+.template command_line_chars
+Some characters are difficult or impossible to type on the 4NT/Take
+Command command line. For an explanation of how to enter them,
+try |~.facility; command line|.
+
+.template common_info
+& What it is:& ~.class;
+& Where it is:& ~.where;
+& Attributes:& ~.attributes;
+~if value? overridden;& Supercedes:& ~.overridden;~fi;
+&.
+
+~if value? usage;Usage: |~.usage;|~fi;
+
+.template command_info
+For information on commands in general, try |~.facility; commands|.
+
+.template declaration_info
+For information on declarations in general, try |~.facility; declarations|.
+
+.template design_info
+& Design macro for:& ~.design;
+~if value? derived;& Derived from:& |~.derived;|~fi;
+~if value? style;& Element style:& |~.style;|~fi;
+~if not empty? variant_list;& Affecting variants:& ~
+ |~foreach i,variant_list,iter;~,variant_list[i],iter /= 1;~end;|~fi;
+&.
+
+.template design_summary
+& Trim:& ~.trimwidth; &times; ~.trimheight;
+& Text measure:& ~.textmeasure;
+& Lines per page:& ~.linesperpage;
+& For make-up:& ~.linesshort; short, ~.lineslong; long
+& Even text margins:& left = ~.evenlefttextmargin;, right = ~.evenrighttextmargin;
+& Odd text margins:& left = ~.oddlefttextmargin;, right = ~.oddrighttextmargin;
+& Paragraph indent:& ~.parindent;
+&.
+
+.template gory_details
+To see more details about the design, try |~.facility; ~.name; details|.
+
+.template indexing_info
+For a complete description of the ZzTeX indexing facility,
+try |~.facility; indexing|.
+
+.template internal_note
+(Note that names containing at-signs or beginning with 'z' are internal.)
+
+.template math_class_info
+For more information on math classes, try |~.facility; math classes|.
+
+.template title_author_publisher_isbn
+& Title:& *~.title;*
+~foreach i,author,iter;
+& ~if iter = 1;Author:~fi;& ~.author[i];
+~end;
+& Publisher:& ~.publisher;
+& ISBN:& ~.isbn;
+
+.include zzdetails.dat
+.end
diff --git a/macros/plain/contrib/zztex/doc/zzplain.dat b/macros/plain/contrib/zztex/doc/zzplain.dat
new file mode 100644
index 0000000000..5aebd853cd
--- /dev/null
+++ b/macros/plain/contrib/zztex/doc/zzplain.dat
@@ -0,0 +1,1315 @@
+% This is the plain TeX format that's described in The TeXbook.
+% N.B.: A version number is defined at the very end of this file;
+% please change that number whenever the file is modified!
+% And don't modify the file under any circumstances.
+
+\catcode`\{=1 % left brace is begin-group character
+\catcode`\}=2 % right brace is end-group character
+\catcode`\$=3 % dollar sign is math shift
+\catcode`\&=4 % ampersand is alignment tab
+\catcode`\#=6 % hash mark is macro parameter character
+\catcode`\^=7
+\catcode`\^^K=7 % circumflex and uparrow are for superscripts
+\catcode`\_=8
+\catcode`\^^A=8 % underline and downarrow are for subscripts
+\catcode`\^^I=10 % ascii tab is a blank space
+\chardef\active=13
+\catcode`\~=\active % tilde is active
+\catcode`\^^L=\active
+\outer\def^^L{\par} % ASCII formfeed is |\outer\par|
+
+\message{Preloading the plain format: codes,}
+
+% We had to define the \catcodes right away, before the message line,
+% since \message uses the { and } characters.
+% When INITEX (the TeX initializer) starts up,
+% it has defined the following \catcode values:
+% \catcode`\^^@=9 % ascii null is ignored
+% \catcode`\^^M=5 % ascii return is end-line
+% \catcode`\\=0 % backslash is TeX escape character
+% \catcode`\%=14 % percent sign is comment character
+% \catcode`\ =10 % ascii space is blank space
+% \catcode`\^^?=15 % ascii delete is invalid
+% \catcode`\A=11 ... \catcode`\Z=11 % uppercase letters
+% \catcode`\a=11 ... \catcode`\z=11 % lowercase letters
+% all others are type 12 (other)
+
+% Here is a list of the characters that have been specially catcoded:
+\def\dospecials{\do\ \do\\\do\{\do\}\do\$\do\&%
+ \do\#\do\^\do\^^K\do\_\do\^^A\do\%\do\~}
+% (not counting ascii null, tab, linefeed, formfeed, return, delete)
+% Each symbol in the list is preceded by \do, which can be defined
+% if you want to do something to every item in the list.
+
+% We make @ signs act like letters, temporarily, to avoid conflict
+% between user names and internal control sequences of plain format.
+\catcode`@=11
+
+% INITEX sets up \mathcode x=x, for x=0..255, except that
+% \mathcode x=x+"7100, for x = `A to `Z and `a to `z;
+% \mathcode x=x+"7000, for x = `0 to `9.
+% The following changes define internal codes as recommended
+% in Appendix C of The TeXbook:
+\mathcode`\^^@="2201 % \cdot
+\mathcode`\^^A="3223 % \downarrow
+\mathcode`\^^B="010B % \alpha
+\mathcode`\^^C="010C % \beta
+\mathcode`\^^D="225E % \land
+\mathcode`\^^E="023A % \lnot
+\mathcode`\^^F="3232 % \in
+\mathcode`\^^G="0119 % \pi
+\mathcode`\^^H="0115 % \lambda
+\mathcode`\^^I="010D % \gamma
+\mathcode`\^^J="010E % \delta
+\mathcode`\^^K="3222 % \uparrow
+\mathcode`\^^L="2206 % \pm
+\mathcode`\^^M="2208 % \oplus
+\mathcode`\^^N="0231 % \infty
+\mathcode`\^^O="0140 % \partial
+\mathcode`\^^P="321A % \subset
+\mathcode`\^^Q="321B % \supset
+\mathcode`\^^R="225C % \cap
+\mathcode`\^^S="225B % \cup
+\mathcode`\^^T="0238 % \forall
+\mathcode`\^^U="0239 % \exists
+\mathcode`\^^V="220A % \otimes
+\mathcode`\^^W="3224 % \leftrightarrow
+\mathcode`\^^X="3220 % \leftarrow
+\mathcode`\^^Y="3221 % \rightarrow
+\mathcode`\^^Z="8000 % \ne
+\mathcode`\^^[="2205 % \diamond
+\mathcode`\^^\="3214 % \le
+\mathcode`\^^]="3215 % \ge
+\mathcode`\^^^="3211 % \equiv
+\mathcode`\^^_="225F % \lor
+\mathcode`\ ="8000 % \space
+\mathcode`\!="5021
+\mathcode`\'="8000 % ^\prime
+\mathcode`\(="4028
+\mathcode`\)="5029
+\mathcode`\*="2203 % \ast
+\mathcode`\+="202B
+\mathcode`\,="613B
+\mathcode`\-="2200
+\mathcode`\.="013A
+\mathcode`\/="013D
+\mathcode`\:="303A
+\mathcode`\;="603B
+\mathcode`\<="313C
+\mathcode`\=="303D
+\mathcode`\>="313E
+\mathcode`\?="503F
+\mathcode`\[="405B
+\mathcode`\\="026E % \backslash
+\mathcode`\]="505D
+\mathcode`\_="8000 % \_
+\mathcode`\{="4266
+\mathcode`\|="026A
+\mathcode`\}="5267
+\mathcode`\^^?="1273 % \smallint
+
+% INITEX sets \uccode`x=`X and \uccode `X=`X for all letters x,
+% and \lccode`x=`x, \lccode`X=`x; all other values are zero.
+% No changes to those tables are needed in plain TeX format.
+
+% INITEX sets \sfcode x=1000 for all x, except that \sfcode`X=999
+% for uppercase letters. The following changes are needed:
+\sfcode`\)=0
+\sfcode`\'=0
+\sfcode`\]=0
+% The \nonfrenchspacing macro will make further changes to \sfcode values.
+
+% Finally, INITEX sets all \delcode values to -1, except \delcode`.=0
+\delcode`\(="028300
+\delcode`\)="029301
+\delcode`\[="05B302
+\delcode`\]="05D303
+\delcode`\<="26830A
+\delcode`\>="26930B
+\delcode`\/="02F30E
+\delcode`\|="26A30C
+\delcode`\\="26E30F
+% N.B. { and } should NOT get delcodes; otherwise parameter grouping fails!
+
+% To make the plain macros more efficient in time and space,
+% several constant values are declared here as control sequences.
+% If they were changed, anything could happen; so they are private symbols.
+\chardef\@ne=1
+\chardef\tw@=2
+\chardef\thr@@=3
+\chardef\sixt@@n=16
+\chardef\@cclv=255
+\mathchardef\@cclvi=256
+\mathchardef\@m=1000
+\mathchardef\@M=10000
+\mathchardef\@MM=20000
+
+% Allocation of registers
+
+% Here are macros for the automatic allocation of \count, \box, \dimen,
+% \skip, \muskip, and \toks registers, as well as \read and \write
+% stream numbers, \fam codes, \language codes, and \insert numbers.
+
+\message{registers,}
+
+% When a register is used only temporarily, it need not be allocated;
+% grouping can be used, making the value previously in the register return
+% after the close of the group. The main use of these macros is for
+% registers that are defined by one macro and used by others, possibly at
+% different nesting levels. All such registers should be defined through
+% these macros; otherwise conflicts may occur, especially when two or more
+% macro packages are being used at once.
+
+% The following counters are reserved:
+% 0 to 9 page numbering
+% 10 count allocation
+% 11 dimen allocation
+% 12 skip allocation
+% 13 muskip allocation
+% 14 box allocation
+% 15 toks allocation
+% 16 read file allocation
+% 17 write file allocation
+% 18 math family allocation
+% 19 language allocation
+% 20 insert allocation
+% 21 the most recently allocated number
+% 22 constant -1
+% New counters are allocated starting with 23, 24, etc. Other registers are
+% allocated starting with 10. This leaves 0 through 9 for the user to play
+% with safely, except that counts 0 to 9 are considered to be the page and
+% subpage numbers (since they are displayed during output). In this scheme,
+% \count 10 always contains the number of the highest-numbered counter that
+% has been allocated, \count 14 the highest-numbered box, etc.
+% Inserts are given numbers 254, 253, etc., since they require a \count,
+% \dimen, \skip, and \box all with the same number; \count 20 contains the
+% lowest-numbered insert that has been allocated. Of course, \box255 is
+% reserved for \output; \count255, \dimen255, and \skip255 can be used freely.
+
+% It is recommended that macro designers always use
+% \global assignments with respect to registers numbered 1, 3, 5, 7, 9, and
+% always non-\global assignments with respect to registers 0, 2, 4, 6, 8, 255.
+% This will prevent ``save stack buildup'' that might otherwise occur.
+
+\count10=22 % allocates \count registers 23, 24, ...
+\count11=9 % allocates \dimen registers 10, 11, ...
+\count12=9 % allocates \skip registers 10, 11, ...
+\count13=9 % allocates \muskip registers 10, 11, ...
+\count14=9 % allocates \box registers 10, 11, ...
+\count15=9 % allocates \toks registers 10, 11, ...
+\count16=-1 % allocates input streams 0, 1, ...
+\count17=-1 % allocates output streams 0, 1, ...
+\count18=3 % allocates math families 4, 5, ...
+\count19=0 % allocates \language codes 1, 2, ...
+\count20=255 % allocates insertions 254, 253, ...
+\countdef\insc@unt=20 % the insertion counter
+\countdef\allocationnumber=21 % the most recent allocation
+\countdef\m@ne=22
+\m@ne=-1 % a handy constant
+\def\wlog{\immediate\write\m@ne} % write on log file (only)
+
+% Here are abbreviations for the names of scratch registers
+% that don't need to be allocated.
+
+\countdef\count@=255
+\dimendef\dimen@=0
+\dimendef\dimen@i=1 % global only
+\dimendef\dimen@ii=2
+\skipdef\skip@=0
+\toksdef\toks@=0
+
+% Now, we define \newcount, \newbox, etc. so that you can say \newcount\foo
+% and \foo will be defined (with \countdef) to be the next counter.
+% To find out which counter \foo is, you can look at \allocationnumber.
+% Since there's no \boxdef command, \chardef is used to define a \newbox,
+% \newinsert, \newfam, and so on.
+
+\outer\def\newcount{\alloc@0\count\countdef\insc@unt}
+\outer\def\newdimen{\alloc@1\dimen\dimendef\insc@unt}
+\outer\def\newskip{\alloc@2\skip\skipdef\insc@unt}
+\outer\def\newmuskip{\alloc@3\muskip\muskipdef\@cclvi}
+\outer\def\newbox{\alloc@4\box\chardef\insc@unt}
+\let\newtoks=\relax % we do this to allow plain.tex to be read in twice
+\outer\def\newhelp#1#2{\newtoks#1#1\expandafter{\csname#2\endcsname}}
+\outer\def\newtoks{\alloc@5\toks\toksdef\@cclvi}
+\outer\def\newread{\alloc@6\read\chardef\sixt@@n}
+\outer\def\newwrite{\alloc@7\write\chardef\sixt@@n}
+\outer\def\newfam{\alloc@8\fam\chardef\sixt@@n}
+\outer\def\newlanguage{\alloc@9\language\chardef\@cclvi}
+\def\alloc@#1#2#3#4#5{\global\advance\count1#1by\@ne
+ \ch@ck#1#4#2% make sure there's still room
+ \allocationnumber=\count1#1%
+ \global#3#5=\allocationnumber
+ \wlog{\string#5=\string#2\the\allocationnumber}}
+\outer\def\newinsert#1{\global\advance\insc@unt by\m@ne
+ \ch@ck0\insc@unt\count
+ \ch@ck1\insc@unt\dimen
+ \ch@ck2\insc@unt\skip
+ \ch@ck4\insc@unt\box
+ \allocationnumber=\insc@unt
+ \global\chardef#1=\allocationnumber
+ \wlog{\string#1=\string\insert\the\allocationnumber}}
+\def\ch@ck#1#2#3{\ifnum\count1#1<#2%
+ \else\errmessage{No room for a new #3}\fi}
+
+% Here are some examples of allocation.
+\newdimen\maxdimen
+\maxdimen=16383.99999pt % the largest legal <dimen>
+\newskip\hideskip
+\hideskip=-1000pt plus 1fill % negative but can grow
+\newskip\centering
+\centering=0pt plus 1000pt minus 1000pt
+\newdimen\p@
+\p@=1pt % this saves macro space and time
+\newdimen\z@
+\z@=0pt % can be used both for 0pt and 0
+\newskip\z@skip
+\z@skip=0pt plus0pt minus0pt
+\newbox\voidb@x % permanently void box register
+
+% And here's a different sort of allocation:
+% For example, \newif\iffoo creates \footrue, \foofalse to go with \iffoo.
+\outer\def\newif#1{\count@\escapechar \escapechar\m@ne
+ \expandafter\expandafter\expandafter
+ \def\@if#1{true}{\let#1=\iftrue}%
+ \expandafter\expandafter\expandafter
+ \def\@if#1{false}{\let#1=\iffalse}%
+ \@if#1{false}\escapechar\count@} % the condition starts out false
+\def\@if#1#2{\csname\expandafter\if@\string#1#2\endcsname}
+{\uccode`1=`i \uccode`2=`f \uppercase{\gdef\if@12{}}} % `if' is required
+
+% Assign initial values to TeX's parameters
+
+\message{parameters,}
+
+% All of TeX's numeric parameters are listed here,
+% but the code is commented out if no special value needs to be set.
+% INITEX makes all parameters zero except where noted.
+
+\pretolerance=100
+\tolerance=200 % INITEX sets this to 10000
+\hbadness=1000
+\vbadness=1000
+\linepenalty=10
+\hyphenpenalty=50
+\exhyphenpenalty=50
+\binoppenalty=700
+\relpenalty=500
+\clubpenalty=150
+\widowpenalty=150
+\displaywidowpenalty=50
+\brokenpenalty=100
+\predisplaypenalty=10000
+% \postdisplaypenalty=0
+% \interlinepenalty=0
+% \floatingpenalty=0, set during \insert
+% \outputpenalty=0, set before TeX enters \output
+\doublehyphendemerits=10000
+\finalhyphendemerits=5000
+\adjdemerits=10000
+% \looseness=0, cleared by TeX after each paragraph
+% \pausing=0
+% \holdinginserts=0
+% \tracingonline=0
+% \tracingmacros=0
+% \tracingstats=0
+% \tracingparagraphs=0
+% \tracingpages=0
+% \tracingoutput=0
+\tracinglostchars=1
+% \tracingcommands=0
+% \tracingrestores=0
+% \language=0
+\uchyph=1
+% \lefthyphenmin=2 \righthyphenmin=3 set below
+% \globaldefs=0
+% \maxdeadcycles=25 % INITEX does this
+% \hangafter=1 % INITEX does this, also TeX after each paragraph
+% \fam=0
+% \mag=1000 % INITEX does this
+% \escapechar=`\\ % INITEX does this
+\defaulthyphenchar=`\-
+\defaultskewchar=-1
+% \endlinechar=`\^^M % INITEX does this
+\newlinechar=-1
+\delimiterfactor=901
+% \time=now % TeX does this at beginning of job
+% \day=now % TeX does this at beginning of job
+% \month=now % TeX does this at beginning of job
+% \year=now % TeX does this at beginning of job
+\showboxbreadth=5
+\showboxdepth=3
+\errorcontextlines=5
+
+\hfuzz=0.1pt
+\vfuzz=0.1pt
+\overfullrule=5pt
+\hsize=6.5in
+\vsize=8.9in
+\maxdepth=4pt
+\splitmaxdepth=\maxdimen
+\boxmaxdepth=\maxdimen
+% \lineskiplimit=0pt, changed by \normalbaselines
+\delimitershortfall=5pt
+\nulldelimiterspace=1.2pt
+\scriptspace=0.5pt
+% \mathsurround=0pt
+% \predisplaysize=0pt, set before TeX enters $$
+% \displaywidth=0pt, set before TeX enters $$
+% \displayindent=0pt, set before TeX enters $$
+\parindent=20pt
+% \hangindent=0pt, zeroed by TeX after each paragraph
+% \hoffset=0pt
+% \voffset=0pt
+
+% \baselineskip=0pt, changed by \normalbaselines
+% \lineskip=0pt, changed by \normalbaselines
+\parskip=0pt plus 1pt
+\abovedisplayskip=12pt plus 3pt minus 9pt
+\abovedisplayshortskip=0pt plus 3pt
+\belowdisplayskip=12pt plus 3pt minus 9pt
+\belowdisplayshortskip=7pt plus 3pt minus 4pt
+% \leftskip=0pt
+% \rightskip=0pt
+\topskip=10pt
+\splittopskip=10pt
+% \tabskip=0pt
+% \spaceskip=0pt
+% \xspaceskip=0pt
+\parfillskip=0pt plus 1fil
+
+\thinmuskip=3mu
+\medmuskip=4mu plus 2mu minus 4mu
+\thickmuskip=5mu plus 5mu
+
+% We also define special registers that function like parameters:
+\newskip\smallskipamount
+\smallskipamount=3pt plus 1pt minus 1pt
+\newskip\medskipamount
+\medskipamount=6pt plus 2pt minus 2pt
+\newskip\bigskipamount
+\bigskipamount=12pt plus 4pt minus 4pt
+\newskip\normalbaselineskip
+\normalbaselineskip=12pt
+\newskip\normallineskip
+\normallineskip=1pt
+\newdimen\normallineskiplimit
+\normallineskiplimit=0pt
+\newdimen\jot
+\jot=3pt
+\newcount\interdisplaylinepenalty
+\interdisplaylinepenalty=100
+\newcount\interfootnotelinepenalty
+\interfootnotelinepenalty=100
+
+% Definitions for preloaded fonts
+
+\def\magstephalf{1095 }
+\def\magstep#1{\ifcase#1 \@m\or 1200\or 1440\or 1728\or 2074\or 2488\fi\relax}
+
+% Fonts assigned to \preloaded are not part of "plain TeX",
+% but they are preloaded so that other format packages can use them.
+% For example, if another set of macros says "\font\ninerm=cmr9",
+% TeX will not have to reload the font metric information for cmr9.
+
+\message{fonts,}
+
+\font\tenrm=cmr10 % roman text
+% \font\preloaded=cmr9
+% \font\preloaded=cmr8
+\font\sevenrm=cmr7
+% \font\preloaded=cmr6
+\font\fiverm=cmr5
+
+\font\teni=cmmi10 % math italic
+% \font\preloaded=cmmi9
+% \font\preloaded=cmmi8
+\font\seveni=cmmi7
+% \font\preloaded=cmmi6
+\font\fivei=cmmi5
+
+\font\tensy=cmsy10 % math symbols
+% \font\preloaded=cmsy9
+% \font\preloaded=cmsy8
+\font\sevensy=cmsy7
+% \font\preloaded=cmsy6
+\font\fivesy=cmsy5
+
+\font\tenex=cmex10 % math extension
+
+% \font\preloaded=cmss10 % sans serif
+% \font\preloaded=cmssq8
+
+% \font\preloaded=cmssi10 % sans serif italic
+% \font\preloaded=cmssqi8
+
+\font\tenbf=cmbx10 % boldface extended
+% \font\preloaded=cmbx9
+% \font\preloaded=cmbx8
+\font\sevenbf=cmbx7
+% \font\preloaded=cmbx6
+\font\fivebf=cmbx5
+
+\font\tentt=cmtt10 % typewriter
+% \font\preloaded=cmtt9
+% \font\preloaded=cmtt8
+
+% \font\preloaded=cmsltt10 % slanted typewriter
+
+\font\tensl=cmsl10 % slanted roman
+% \font\preloaded=cmsl9
+% \font\preloaded=cmsl8
+
+\font\tenit=cmti10 % text italic
+% \font\preloaded=cmti9
+% \font\preloaded=cmti8
+% \font\preloaded=cmti7
+
+\message{more fonts,}
+% \font\preloaded=cmu10 % unslanted text italic
+
+% \font\preloaded=cmmib10 % bold math italic
+% \font\preloaded=cmbsy10 % bold math symbols
+
+% \font\preloaded=cmcsc10 % caps and small caps
+
+% \font\preloaded=cmssbx10 % sans serif bold extended
+
+% \font\preloaded=cmdunh10 % Dunhill style
+
+% \font\preloaded=cmr7 scaled \magstep4 % for titles
+% \font\preloaded=cmtt10 scaled \magstep2
+% \font\preloaded=cmssbx10 scaled \magstep2
+
+% \font\preloaded=manfnt % METAFONT logo and dragon curve and special symbols
+
+% Additional \preloaded fonts can be specified here.
+% (And those that were \preloaded above can be eliminated.)
+
+\let\preloaded=\undefined % preloaded fonts must be declared anew later.
+
+\skewchar\teni='177
+\skewchar\seveni='177
+\skewchar\fivei='177
+\skewchar\tensy='60
+\skewchar\sevensy='60
+\skewchar\fivesy='60
+
+\textfont0=\tenrm
+\scriptfont0=\sevenrm
+\scriptscriptfont0=\fiverm
+\def\rm{\fam\z@\tenrm}
+\textfont1=\teni
+\scriptfont1=\seveni
+\scriptscriptfont1=\fivei
+\def\mit{\fam\@ne}
+\def\oldstyle{\fam\@ne\teni}
+\textfont2=\tensy
+\scriptfont2=\sevensy
+\scriptscriptfont2=\fivesy
+\def\cal{\fam\tw@}
+\textfont3=\tenex
+\scriptfont3=\tenex
+\scriptscriptfont3=\tenex
+\newfam\itfam
+\def\it{\fam\itfam\tenit} % \it is family 4
+\textfont\itfam=\tenit
+\newfam\slfam
+\def\sl{\fam\slfam\tensl} % \sl is family 5
+\textfont\slfam=\tensl
+\newfam\bffam
+\def\bf{\fam\bffam\tenbf} % \bf is family 6
+\textfont\bffam=\tenbf
+\scriptfont\bffam=\sevenbf
+\scriptscriptfont\bffam=\fivebf
+\newfam\ttfam
+\def\tt{\fam\ttfam\tentt} % \tt is family 7
+\textfont\ttfam=\tentt
+
+% Macros for setting ordinary text
+\message{macros,}
+
+\def\frenchspacing{\sfcode`\.\@m \sfcode`\?\@m \sfcode`\!\@m
+ \sfcode`\:\@m \sfcode`\;\@m \sfcode`\,\@m}
+\def\nonfrenchspacing{\sfcode`\.3000\sfcode`\?3000\sfcode`\!3000%
+ \sfcode`\:2000\sfcode`\;1500\sfcode`\,1250 }
+
+\def\normalbaselines{\lineskip\normallineskip
+ \baselineskip\normalbaselineskip \lineskiplimit\normallineskiplimit}
+
+\def\^^M{\ } % \<return> = \<space>
+\def\^^I{\ } % \<tab> = \<space>
+
+\def\lq{`}
+\def\rq{'}
+\def\lbrack{[}
+\def\rbrack{]}
+
+\let\endgraf=\par
+\let\endline=\cr
+
+\def\space{ }
+\def\empty{}
+\def\null{\hbox{}}
+
+\let\bgroup={
+\let\egroup=}
+
+% In \obeylines, we say `\let^^M=\par' instead of `\def^^M{\par}'
+% since this allows, for example, `\let\par=\cr \obeylines \halign{...'
+{\catcode`\^^M=\active % these lines must end with %
+\gdef\obeylines{\catcode`\^^M\active \let^^M\par}%
+\global\let^^M=\par} % this is in case ^^M appears in a \write
+\def\obeyspaces{\catcode`\ \active}
+{\obeyspaces\global\let =\space}
+
+\def\loop#1\repeat{\def\body{#1}\iterate}
+\def\iterate{\body \let\next\iterate \else\let\next\relax\fi \next}
+\let\repeat=\fi % this makes \loop...\if...\repeat skippable
+
+\def\thinspace{\kern .16667em }
+\def\negthinspace{\kern-.16667em }
+\def\enspace{\kern.5em }
+
+\def\enskip{\hskip.5em\relax}
+\def\quad{\hskip1em\relax}
+\def\qquad{\hskip2em\relax}
+
+\def\smallskip{\vskip\smallskipamount}
+\def\medskip{\vskip\medskipamount}
+\def\bigskip{\vskip\bigskipamount}
+
+\def\nointerlineskip{\prevdepth-1000\p@}
+\def\offinterlineskip{\baselineskip-1000\p@
+ \lineskip\z@ \lineskiplimit\maxdimen}
+
+\def\topglue{\nointerlineskip\vglue-\topskip\vglue} % for top of page
+\def\vglue{\afterassignment\vgl@\skip@=}
+\def\vgl@{\par \dimen@\prevdepth \hrule height\z@
+ \nobreak\vskip\skip@ \prevdepth\dimen@}
+\def\hglue{\afterassignment\hgl@\skip@=}
+\def\hgl@{\leavevmode \count@\spacefactor \vrule width\z@
+ \nobreak\hskip\skip@ \spacefactor\count@}
+
+\def~{\penalty\@M \ }
+\def\slash{/\penalty\exhyphenpenalty} % a `/' that acts like a `-'
+
+\def\break{\penalty-\@M}
+\def\nobreak{\penalty \@M}
+\def\allowbreak{\penalty \z@}
+
+\def\filbreak{\par\vfil\penalty-200\vfilneg}
+\def\goodbreak{\par\penalty-500 }
+\def\eject{\par\break}
+\def\supereject{\par\penalty-\@MM}
+
+\def\removelastskip{\ifdim\lastskip=\z@\else\vskip-\lastskip\fi}
+\def\smallbreak{\par\ifdim\lastskip<\smallskipamount
+ \removelastskip\penalty-50\smallskip\fi}
+\def\medbreak{\par\ifdim\lastskip<\medskipamount
+ \removelastskip\penalty-100\medskip\fi}
+\def\bigbreak{\par\ifdim\lastskip<\bigskipamount
+ \removelastskip\penalty-200\bigskip\fi}
+
+\def\line{\hbox to\hsize}
+\def\leftline#1{\line{#1\hss}}
+\def\rightline#1{\line{\hss#1}}
+\def\centerline#1{\line{\hss#1\hss}}
+
+\def\rlap#1{\hbox to\z@{#1\hss}}
+\def\llap#1{\hbox to\z@{\hss#1}}
+
+\def\m@th{\mathsurround\z@}
+\def\underbar#1{$\setbox\z@\hbox{#1}\dp\z@\z@
+ \m@th \underline{\box\z@}$}
+
+\newbox\strutbox
+\setbox\strutbox=\hbox{\vrule height8.5pt depth3.5pt width\z@}
+\def\strut{\relax\ifmmode\copy\strutbox\else\unhcopy\strutbox\fi}
+
+\def\hidewidth{\hskip\hideskip} % for alignment entries that can stick out
+\def\ialign{\everycr{}\tabskip\z@skip\halign} % initialized \halign
+\newcount\mscount
+\def\multispan#1{\omit \mscount#1\relax
+ \loop\ifnum\mscount>\@ne \sp@n\repeat}
+\def\sp@n{\span\omit\advance\mscount\m@ne}
+
+\newif\ifus@
+\newif\if@cr
+\newbox\tabs
+\newbox\tabsyet
+\newbox\tabsdone
+
+\def\cleartabs{\global\setbox\tabsyet\null \setbox\tabs\null}
+\def\settabs{\setbox\tabs\null \futurelet\next\sett@b}
+\let\+=\relax % in case this file is being read in twice
+\def\sett@b{\ifx\next\+\def\nxt{\afterassignment\s@tt@b\let\nxt}%
+ \else\let\nxt\s@tcols\fi \let\next\relax \nxt}
+\def\s@tt@b{\let\nxt\relax \us@false\m@ketabbox}
+\def\tabalign{\us@true\m@ketabbox} % non-\outer version of \+
+\outer\def\+{\tabalign}
+\def\s@tcols#1\columns{\count@#1\dimen@\hsize
+ \loop\ifnum\count@>\z@ \@nother \repeat}
+\def\@nother{\dimen@ii\dimen@ \divide\dimen@ii\count@
+ \setbox\tabs\hbox{\hbox to\dimen@ii{}\unhbox\tabs}%
+ \advance\dimen@-\dimen@ii \advance\count@\m@ne}
+
+\def\m@ketabbox{\begingroup
+ \global\setbox\tabsyet\copy\tabs
+ \global\setbox\tabsdone\null
+ \def\cr{\@crtrue\crcr\egroup\egroup
+ \ifus@\unvbox\z@\lastbox\fi\endgroup
+ \setbox\tabs\hbox{\unhbox\tabsyet\unhbox\tabsdone}}%
+ \setbox\z@\vbox\bgroup\@crfalse
+ \ialign\bgroup&\t@bbox##\t@bb@x\crcr}
+
+\def\t@bbox{\setbox\z@\hbox\bgroup}
+\def\t@bb@x{\if@cr\egroup % now \box\z@ holds the column
+ \else\hss\egroup \global\setbox\tabsyet\hbox{\unhbox\tabsyet
+ \global\setbox\@ne\lastbox}% now \box\@ne holds its size
+ \ifvoid\@ne\global\setbox\@ne\hbox to\wd\z@{}%
+ \else\setbox\z@\hbox to\wd\@ne{\unhbox\z@}\fi
+ \global\setbox\tabsdone\hbox{\box\@ne\unhbox\tabsdone}\fi
+ \box\z@}
+
+\def\hang{\hangindent\parindent}
+\def\textindent#1{\indent\llap{#1\enspace}\ignorespaces}
+\def\item{\par\hang\textindent}
+\def\itemitem{\par\indent \hangindent2\parindent \textindent}
+\def\narrower{\advance\leftskip\parindent
+ \advance\rightskip\parindent}
+
+\outer\def\beginsection#1\par{\vskip\z@ plus.3\vsize\penalty-250
+ \vskip\z@ plus-.3\vsize\bigskip\vskip\parskip
+ \message{#1}\leftline{\bf#1}\nobreak\smallskip\noindent}
+\outer\def\proclaim #1. #2\par{\medbreak
+ \noindent{\bf#1.\enspace}{\sl#2\par}%
+ \ifdim\lastskip<\medskipamount \removelastskip\penalty55\medskip\fi}
+
+\def\raggedright{\rightskip\z@ plus2em \spaceskip.3333em \xspaceskip.5em\relax}
+\def\ttraggedright{\tt\rightskip\z@ plus2em\relax} % for use with \tt only
+
+\chardef\%=`\%
+\chardef\&=`\&
+\chardef\#=`\#
+\chardef\$=`\$
+\chardef\ss="19
+\chardef\ae="1A
+\chardef\oe="1B
+\chardef\o="1C
+\chardef\AE="1D
+\chardef\OE="1E
+\chardef\O="1F
+\chardef\i="10 % dotless i
+\chardef\j="11 % dotless j
+\def\aa{\accent23a} %^accent
+\def\l{\char32l}
+\def\L{\leavevmode\setbox0\hbox{L}\hbox to\wd0{\hss\char32L}}
+
+\def\leavevmode{\unhbox\voidb@x} % begins a paragraph, if necessary
+\def\_{\leavevmode \kern.06em \vbox{\hrule width.3em}}
+\def\AA{\leavevmode\setbox0\hbox{!}\dimen@\ht0\advance\dimen@-1ex%
+ \rlap{\raise.67\dimen@\hbox{\char'27}}A}
+
+\def\mathhexbox#1#2#3{\leavevmode
+ \hbox{$\m@th \mathchar"#1#2#3$}}
+\def\dag{\mathhexbox279}
+\def\ddag{\mathhexbox27A}
+\def\S{\mathhexbox278}
+\def\P{\mathhexbox27B}
+\def\Orb{\mathhexbox20D}
+
+\def\oalign#1{\leavevmode\vtop{\baselineskip\z@skip \lineskip.25ex%
+ \ialign{##\crcr#1\crcr}}} \def\o@lign{\lineskiplimit\z@ \oalign}
+\def\ooalign{\lineskiplimit-\maxdimen \oalign} % chars over each other
+{\catcode`p=12 \catcode`t=12 \gdef\\#1pt{#1}} \let\getf@ctor=\\
+\def\sh@ft#1{\dimen@#1\kern\expandafter\getf@ctor\the\fontdimen1\font
+ \dimen@} % kern by #1 times the current slant
+\def\d#1{{\o@lign{\relax#1\crcr\hidewidth\sh@ft{-1ex}.\hidewidth}}}
+\def\b#1{{\o@lign{\relax#1\crcr\hidewidth\sh@ft{-3ex}%
+ \vbox to.2ex{\hbox{\char22}\vss}\hidewidth}}}
+\def\c#1{{\setbox\z@\hbox{#1}\ifdim\ht\z@=1ex\accent24 #1% %^accent
+ \else\ooalign{\unhbox\z@\crcr\hidewidth\char24\hidewidth}\fi}}
+\def\copyright{{\ooalign{\hfil\raise.07ex\hbox{c}\hfil\crcr\Orb}}}
+
+\def\dots{\relax\ifmmode\ldots\else$\m@th\ldots\,$\fi}
+\def\TeX{T\kern-.1667em\lower.5ex\hbox{E}\kern-.125emX}
+
+\def\`#1{{\accent18 #1}} %^accent
+\def\'#1{{\accent19 #1}} %^accent
+\def\v#1{{\accent20 #1}} %^accent
+\let\^^_=\v
+\def\u#1{{\accent21 #1}} %^accent
+\let\^^S=\u
+\def\=#1{{\accent22 #1}} %^accent
+\def\^#1{{\accent94 #1}} %^accent
+\let\^^D=\^
+\def\.#1{{\accent95 #1}} %^accent
+\def\H#1{{\accent"7D #1}} %^accent
+\def\~#1{{\accent"7E #1}} %^accent
+\def\"#1{{\accent"7F #1}} %^accent
+\def\t#1{{\edef\next{\the\font}\the\textfont1\accent"7F\next#1}} %^accent
+
+\def\hrulefill{\leaders\hrule\hfill}
+\def\dotfill{\cleaders\hbox{$\m@th \mkern1.5mu.\mkern1.5mu$}\hfill}
+\def\rightarrowfill{$\m@th\smash-\mkern-7mu%
+ \cleaders\hbox{$\mkern-2mu\smash-\mkern-2mu$}\hfill
+ \mkern-7mu\mathord\rightarrow$}
+\def\leftarrowfill{$\m@th\mathord\leftarrow\mkern-7mu%
+ \cleaders\hbox{$\mkern-2mu\smash-\mkern-2mu$}\hfill
+ \mkern-7mu\smash-$}
+\mathchardef\braceld="037A
+\mathchardef\bracerd="037B
+\mathchardef\bracelu="037C
+\mathchardef\braceru="037D
+\def\downbracefill{$\m@th \setbox\z@\hbox{$\braceld$}%
+ \braceld\leaders\vrule height\ht\z@ depth\z@\hfill\braceru
+ \bracelu\leaders\vrule height\ht\z@ depth\z@\hfill\bracerd$}
+\def\upbracefill{$\m@th \setbox\z@\hbox{$\braceld$}%
+ \bracelu\leaders\vrule height\ht\z@ depth\z@\hfill\bracerd
+ \braceld\leaders\vrule height\ht\z@ depth\z@\hfill\braceru$}
+
+\outer\def\bye{\par\vfill\supereject\end}
+
+% Macros for math setting
+\message{math definitions,}
+
+\let\sp=^
+\let\sb=_
+\def\,{\mskip\thinmuskip}
+\def\>{\mskip\medmuskip}
+\def\;{\mskip\thickmuskip}
+\def\!{\mskip-\thinmuskip}
+\def\*{\discretionary{\thinspace\the\textfont2\char2}{}{}}
+{\catcode`\'=\active \gdef'{^\bgroup\prim@s}}
+\def\prim@s{\prime\futurelet\next\pr@m@s}
+\def\pr@m@s{\ifx'\next\let\nxt\pr@@@s \else\ifx^\next\let\nxt\pr@@@t
+ \else\let\nxt\egroup\fi\fi \nxt}
+\def\pr@@@s#1{\prim@s}
+\def\pr@@@t#1#2{#2\egroup}
+{\catcode`\^^Z=\active \gdef^^Z{\not=}} % ^^Z is like \ne in math
+
+{\catcode`\_=\active \global\let_=\_} % _ in math is either subscript or \_
+
+\mathchardef\alpha="010B
+\mathchardef\beta="010C
+\mathchardef\gamma="010D
+\mathchardef\delta="010E
+\mathchardef\epsilon="010F
+\mathchardef\zeta="0110
+\mathchardef\eta="0111
+\mathchardef\theta="0112
+\mathchardef\iota="0113
+\mathchardef\kappa="0114
+\mathchardef\lambda="0115
+\mathchardef\mu="0116
+\mathchardef\nu="0117
+\mathchardef\xi="0118
+\mathchardef\pi="0119
+\mathchardef\rho="011A
+\mathchardef\sigma="011B
+\mathchardef\tau="011C
+\mathchardef\upsilon="011D
+\mathchardef\phi="011E
+\mathchardef\chi="011F
+\mathchardef\psi="0120
+\mathchardef\omega="0121
+\mathchardef\varepsilon="0122
+\mathchardef\vartheta="0123
+\mathchardef\varpi="0124
+\mathchardef\varrho="0125
+\mathchardef\varsigma="0126
+\mathchardef\varphi="0127
+\mathchardef\Gamma="7000
+\mathchardef\Delta="7001
+\mathchardef\Theta="7002
+\mathchardef\Lambda="7003
+\mathchardef\Xi="7004
+\mathchardef\Pi="7005
+\mathchardef\Sigma="7006
+\mathchardef\Upsilon="7007
+\mathchardef\Phi="7008
+\mathchardef\Psi="7009
+\mathchardef\Omega="700A
+
+\mathchardef\aleph="0240
+\def\hbar{{\mathchar'26\mkern-9muh}}
+\mathchardef\imath="017B
+\mathchardef\jmath="017C
+\mathchardef\ell="0160
+\mathchardef\wp="017D
+\mathchardef\Re="023C
+\mathchardef\Im="023D
+\mathchardef\partial="0140
+\mathchardef\infty="0231
+\mathchardef\prime="0230
+\mathchardef\emptyset="023B
+\mathchardef\nabla="0272
+\def\surd{{\mathchar"1270}}
+\mathchardef\top="023E
+\mathchardef\bot="023F
+\def\angle{{\vbox{\ialign{$\m@th\scriptstyle##$\crcr
+ \not\mathrel{\mkern14mu}\crcr
+ \noalign{\nointerlineskip}
+ \mkern2.5mu\leaders\hrule height.34pt\hfill\mkern2.5mu\crcr}}}}
+\mathchardef\triangle="0234
+\mathchardef\forall="0238
+\mathchardef\exists="0239
+\mathchardef\neg="023A
+\let\lnot=\neg
+\mathchardef\flat="015B
+\mathchardef\natural="015C
+\mathchardef\sharp="015D
+\mathchardef\clubsuit="027C
+\mathchardef\diamondsuit="027D
+\mathchardef\heartsuit="027E
+\mathchardef\spadesuit="027F
+
+\mathchardef\coprod="1360
+\mathchardef\bigvee="1357
+\mathchardef\bigwedge="1356
+\mathchardef\biguplus="1355
+\mathchardef\bigcap="1354
+\mathchardef\bigcup="1353
+\mathchardef\intop="1352
+\def\int{\intop\nolimits}
+\mathchardef\prod="1351
+\mathchardef\sum="1350
+\mathchardef\bigotimes="134E
+\mathchardef\bigoplus="134C
+\mathchardef\bigodot="134A
+\mathchardef\ointop="1348
+\def\oint{\ointop\nolimits}
+\mathchardef\bigsqcup="1346
+\mathchardef\smallint="1273
+
+\mathchardef\triangleleft="212F
+\mathchardef\triangleright="212E
+\mathchardef\bigtriangleup="2234
+\mathchardef\bigtriangledown="2235
+\mathchardef\wedge="225E
+\let\land=\wedge
+\mathchardef\vee="225F
+\let\lor=\vee
+\mathchardef\cap="225C
+\mathchardef\cup="225B
+\mathchardef\ddagger="227A
+\mathchardef\dagger="2279
+\mathchardef\sqcap="2275
+\mathchardef\sqcup="2274
+\mathchardef\uplus="225D
+\mathchardef\amalg="2271
+\mathchardef\diamond="2205
+\mathchardef\bullet="220F
+\mathchardef\wr="226F
+\mathchardef\div="2204
+\mathchardef\odot="220C
+\mathchardef\oslash="220B
+\mathchardef\otimes="220A
+\mathchardef\ominus="2209
+\mathchardef\oplus="2208
+\mathchardef\mp="2207
+\mathchardef\pm="2206
+\mathchardef\circ="220E
+\mathchardef\bigcirc="220D
+\mathchardef\setminus="226E % for set difference A\setminus B
+\mathchardef\cdot="2201
+\mathchardef\ast="2203
+\mathchardef\times="2202
+\mathchardef\star="213F
+
+\mathchardef\propto="322F
+\mathchardef\sqsubseteq="3276
+\mathchardef\sqsupseteq="3277
+\mathchardef\parallel="326B
+\mathchardef\mid="326A
+\mathchardef\dashv="3261
+\mathchardef\vdash="3260
+\mathchardef\nearrow="3225
+\mathchardef\searrow="3226
+\mathchardef\nwarrow="322D
+\mathchardef\swarrow="322E
+\mathchardef\Leftrightarrow="322C
+\mathchardef\Leftarrow="3228
+\mathchardef\Rightarrow="3229
+\def\neq{\not=}
+\let\ne=\neq
+\mathchardef\leq="3214
+\let\le=\leq
+\mathchardef\geq="3215
+\let\ge=\geq
+\mathchardef\succ="321F
+\mathchardef\prec="321E
+\mathchardef\approx="3219
+\mathchardef\succeq="3217
+\mathchardef\preceq="3216
+\mathchardef\supset="321B
+\mathchardef\subset="321A
+\mathchardef\supseteq="3213
+\mathchardef\subseteq="3212
+\mathchardef\in="3232
+\mathchardef\ni="3233
+\let\owns=\ni
+\mathchardef\gg="321D
+\mathchardef\ll="321C
+\mathchardef\not="3236
+\mathchardef\leftrightarrow="3224
+\mathchardef\leftarrow="3220
+\let\gets=\leftarrow
+\mathchardef\rightarrow="3221
+\let\to=\rightarrow
+\mathchardef\mapstochar="3237
+\def\mapsto{\mapstochar\rightarrow}
+\mathchardef\sim="3218
+\mathchardef\simeq="3227
+\mathchardef\perp="323F
+\mathchardef\equiv="3211
+\mathchardef\asymp="3210
+\mathchardef\smile="315E
+\mathchardef\frown="315F
+\mathchardef\leftharpoonup="3128
+\mathchardef\leftharpoondown="3129
+\mathchardef\rightharpoonup="312A
+\mathchardef\rightharpoondown="312B
+
+\def\joinrel{\mathrel{\mkern-3mu}}
+\def\relbar{\mathrel{\smash-}} % \smash, because - has the same height as +
+\def\Relbar{\mathrel=}
+\mathchardef\lhook="312C
+\def\hookrightarrow{\lhook\joinrel\rightarrow}
+\mathchardef\rhook="312D
+\def\hookleftarrow{\leftarrow\joinrel\rhook}
+\def\bowtie{\mathrel\triangleright\joinrel\mathrel\triangleleft}
+\def\models{\mathrel|\joinrel=}
+\def\Longrightarrow{\Relbar\joinrel\Rightarrow}
+\def\longrightarrow{\relbar\joinrel\rightarrow}
+\def\longleftarrow{\leftarrow\joinrel\relbar}
+\def\Longleftarrow{\Leftarrow\joinrel\Relbar}
+\def\longmapsto{\mapstochar\longrightarrow}
+\def\longleftrightarrow{\leftarrow\joinrel\rightarrow}
+\def\Longleftrightarrow{\Leftarrow\joinrel\Rightarrow}
+\def\iff{\;\Longleftrightarrow\;}
+
+\mathchardef\ldotp="613A % ldot as a punctuation mark
+\mathchardef\cdotp="6201 % cdot as a punctuation mark
+\mathchardef\colon="603A % colon as a punctuation mark
+\def\ldots{\mathinner{\ldotp\ldotp\ldotp}}
+\def\cdots{\mathinner{\cdotp\cdotp\cdotp}}
+\def\vdots{\vbox{\baselineskip4\p@ \lineskiplimit\z@
+ \kern6\p@\hbox{.}\hbox{.}\hbox{.}}}
+\def\ddots{\mathinner{\mkern1mu\raise7\p@\vbox{\kern7\p@\hbox{.}}\mkern2mu
+ \raise4\p@\hbox{.}\mkern2mu\raise\p@\hbox{.}\mkern1mu}}
+
+\def\acute{\mathaccent"7013 } %^math_accent
+\def\grave{\mathaccent"7012 } %^math_accent
+\def\ddot{\mathaccent"707F } %^math_accent
+\def\tilde{\mathaccent"707E } %^math_accent
+\def\bar{\mathaccent"7016 } %^math_accent
+\def\breve{\mathaccent"7015 } %^math_accent
+\def\check{\mathaccent"7014 } %^math_accent
+\def\hat{\mathaccent"705E } %^math_accent
+\def\vec{\mathaccent"017E } %^math_accent
+\def\dot{\mathaccent"705F } %^math_accent
+\def\widetilde{\mathaccent"0365 } %^math_accent
+\def\widehat{\mathaccent"0362 } %^math_accent
+\def\overrightarrow#1{\vbox{\m@th\ialign{##\crcr
+ \rightarrowfill\crcr\noalign{\kern-\p@\nointerlineskip}
+ $\hfil\displaystyle{#1}\hfil$\crcr}}}
+\def\overleftarrow#1{\vbox{\m@th\ialign{##\crcr
+ \leftarrowfill\crcr\noalign{\kern-\p@\nointerlineskip}
+ $\hfil\displaystyle{#1}\hfil$\crcr}}}
+\def\overbrace#1{\mathop{\vbox{\m@th\ialign{##\crcr\noalign{\kern3\p@}
+ \downbracefill\crcr\noalign{\kern3\p@\nointerlineskip}
+ $\hfil\displaystyle{#1}\hfil$\crcr}}}\limits}
+\def\underbrace#1{\mathop{\vtop{\m@th\ialign{##\crcr
+ $\hfil\displaystyle{#1}\hfil$\crcr\noalign{\kern3\p@\nointerlineskip}
+ \upbracefill\crcr\noalign{\kern3\p@}}}}\limits}
+\def\skew#1#2#3{{\muskip\z@#1mu\divide\muskip\z@\tw@ \mkern\muskip\z@
+ #2{\mkern-\muskip\z@{#3}\mkern\muskip\z@}\mkern-\muskip\z@}{}}
+
+\def\lmoustache{\delimiter"437A340 } % top from (, bottom from )
+\def\rmoustache{\delimiter"537B341 } % top from ), bottom from (
+\def\lgroup{\delimiter"462833A } % extensible ( with sharper tips
+\def\rgroup{\delimiter"562933B } % extensible ) with sharper tips
+\def\arrowvert{\delimiter"26A33C } % arrow without arrowheads
+\def\Arrowvert{\delimiter"26B33D } % double arrow without arrowheads
+\def\bracevert{\delimiter"77C33E } % the vertical bar that extends braces
+\def\Vert{\delimiter"26B30D }
+\let\|=\Vert
+\def\vert{\delimiter"26A30C }
+\def\uparrow{\delimiter"3222378 }
+\def\downarrow{\delimiter"3223379 }
+\def\updownarrow{\delimiter"326C33F }
+\def\Uparrow{\delimiter"322A37E }
+\def\Downarrow{\delimiter"322B37F }
+\def\Updownarrow{\delimiter"326D377 }
+\def\backslash{\delimiter"26E30F } % for double coset G\backslash H
+\def\rangle{\delimiter"526930B }
+\def\langle{\delimiter"426830A }
+\def\rbrace{\delimiter"5267309 }
+\let\}=\rbrace
+\def\lbrace{\delimiter"4266308 }
+\let\{=\lbrace
+\def\rceil{\delimiter"5265307 }
+\def\lceil{\delimiter"4264306 }
+\def\rfloor{\delimiter"5263305 }
+\def\lfloor{\delimiter"4262304 }
+
+\def\bigl{\mathopen\big}
+\def\bigm{\mathrel\big}
+\def\bigr{\mathclose\big}
+\def\Bigl{\mathopen\Big}
+\def\Bigm{\mathrel\Big}
+\def\Bigr{\mathclose\Big}
+\def\biggl{\mathopen\bigg}
+\def\biggm{\mathrel\bigg}
+\def\biggr{\mathclose\bigg}
+\def\Biggl{\mathopen\Bigg}
+\def\Biggm{\mathrel\Bigg}
+\def\Biggr{\mathclose\Bigg}
+\def\big#1{{\hbox{$\left#1\vbox to8.5\p@{}\right.\n@space$}}}
+\def\Big#1{{\hbox{$\left#1\vbox to11.5\p@{}\right.\n@space$}}}
+\def\bigg#1{{\hbox{$\left#1\vbox to14.5\p@{}\right.\n@space$}}}
+\def\Bigg#1{{\hbox{$\left#1\vbox to17.5\p@{}\right.\n@space$}}}
+\def\n@space{\nulldelimiterspace\z@ \m@th}
+
+\def\choose{\atopwithdelims()}
+\def\brack{\atopwithdelims[]}
+\def\brace{\atopwithdelims\{\}}
+
+\def\sqrt{\radical"270370 }
+
+\def\mathpalette#1#2{\mathchoice{#1\displaystyle{#2}}%
+ {#1\textstyle{#2}}{#1\scriptstyle{#2}}{#1\scriptscriptstyle{#2}}}
+\newbox\rootbox % Box to hold radicand for nth root commands.
+\def\root#1\of{\setbox\rootbox
+ \hbox{$\m@th\scriptscriptstyle{#1}$}\mathpalette\r@@t}
+\def\r@@t#1#2{\setbox\z@\hbox{$\m@th#1\sqrt{#2}$}\dimen@\ht\z@
+ \advance\dimen@-\dp\z@
+ \mkern5mu\raise.6\dimen@\copy\rootbox \mkern-10mu\box\z@}
+\newif\ifv@
+\newif\ifh@
+\def\vphantom{\v@true\h@false\ph@nt}
+\def\hphantom{\v@false\h@true\ph@nt}
+\def\phantom{\v@true\h@true\ph@nt}
+\def\ph@nt{\ifmmode\def\next{\mathpalette\mathph@nt}%
+ \else\let\next\makeph@nt\fi\next}
+\def\makeph@nt#1{\setbox\z@\hbox{#1}\finph@nt}
+\def\mathph@nt#1#2{\setbox\z@\hbox{$\m@th#1{#2}$}\finph@nt}
+\def\finph@nt{\setbox\tw@\null
+ \ifv@ \ht\tw@\ht\z@ \dp\tw@\dp\z@\fi
+ \ifh@ \wd\tw@\wd\z@\fi \box\tw@}
+\def\mathstrut{\vphantom(}
+\def\smash{\relax % \relax, in case this comes first in \halign
+ \ifmmode\def\next{\mathpalette\mathsm@sh}\else\let\next\makesm@sh
+ \fi\next}
+\def\makesm@sh#1{\setbox\z@\hbox{#1}\finsm@sh}
+\def\mathsm@sh#1#2{\setbox\z@\hbox{$\m@th#1{#2}$}\finsm@sh}
+\def\finsm@sh{\ht\z@\z@ \dp\z@\z@ \box\z@}
+
+\def\cong{\mathrel{\mathpalette\@vereq\sim}} % congruence sign
+\def\@vereq#1#2{\lower.5\p@\vbox{\lineskiplimit\maxdimen\lineskip-.5\p@
+ \ialign{$\m@th#1\hfil##\hfil$\crcr#2\crcr=\crcr}}}
+\def\notin{\mathrel{\mathpalette\c@ncel\in}}
+\def\c@ncel#1#2{\m@th\ooalign{$\hfil#1\mkern1mu/\hfil$\crcr$#1#2$}}
+\def\rightleftharpoons{\mathrel{\mathpalette\rlh@{}}}
+\def\rlh@#1{\vcenter{\m@th\hbox{\ooalign{\raise2pt
+ \hbox{$#1\rightharpoonup$}\crcr
+ $#1\leftharpoondown$}}}}
+\def\buildrel#1\over#2{\mathrel{\mathop{\kern\z@#2}\limits^{#1}}}
+\def\doteq{\buildrel\textstyle.\over=}
+
+\def\log{\mathop{\rm log}\nolimits}
+\def\lg{\mathop{\rm lg}\nolimits}
+\def\ln{\mathop{\rm ln}\nolimits}
+\def\lim{\mathop{\rm lim}}
+\def\limsup{\mathop{\rm lim\,sup}}
+\def\liminf{\mathop{\rm lim\,inf}}
+\def\sin{\mathop{\rm sin}\nolimits}
+\def\arcsin{\mathop{\rm arcsin}\nolimits}
+\def\sinh{\mathop{\rm sinh}\nolimits}
+\def\cos{\mathop{\rm cos}\nolimits}
+\def\arccos{\mathop{\rm arccos}\nolimits}
+\def\cosh{\mathop{\rm cosh}\nolimits}
+\def\tan{\mathop{\rm tan}\nolimits}
+\def\arctan{\mathop{\rm arctan}\nolimits}
+\def\tanh{\mathop{\rm tanh}\nolimits}
+\def\cot{\mathop{\rm cot}\nolimits}
+\def\coth{\mathop{\rm coth}\nolimits}
+\def\sec{\mathop{\rm sec}\nolimits}
+\def\csc{\mathop{\rm csc}\nolimits}
+\def\max{\mathop{\rm max}}
+\def\min{\mathop{\rm min}}
+\def\sup{\mathop{\rm sup}}
+\def\inf{\mathop{\rm inf}}
+\def\arg{\mathop{\rm arg}\nolimits}
+\def\ker{\mathop{\rm ker}\nolimits}
+\def\dim{\mathop{\rm dim}\nolimits}
+\def\hom{\mathop{\rm hom}\nolimits}
+\def\det{\mathop{\rm det}}
+\def\exp{\mathop{\rm exp}\nolimits}
+\def\Pr{\mathop{\rm Pr}}
+\def\gcd{\mathop{\rm gcd}}
+\def\deg{\mathop{\rm deg}\nolimits}
+
+\def\bmod{\nonscript\mskip-\medmuskip\mkern5mu
+ \mathbin{\rm mod}\penalty900\mkern5mu\nonscript\mskip-\medmuskip}
+\def\pmod#1{\allowbreak\mkern18mu({\rm mod}\,\,#1)}
+
+\def\cases#1{\left\{\,\vcenter{\normalbaselines\m@th
+ \ialign{$##\hfil$&\quad##\hfil\crcr#1\crcr}}\right.}
+\def\matrix#1{\null\,\vcenter{\normalbaselines\m@th
+ \ialign{\hfil$##$\hfil&&\quad\hfil$##$\hfil\crcr
+ \mathstrut\crcr\noalign{\kern-\baselineskip}
+ #1\crcr\mathstrut\crcr\noalign{\kern-\baselineskip}}}\,}
+\def\pmatrix#1{\left(\matrix{#1}\right)}
+\newdimen\p@renwd
+\setbox0=\hbox{\tenex B}
+\p@renwd=\wd0 % width of the big left (
+\def\bordermatrix#1{\begingroup \m@th
+ \setbox\z@\vbox{\def\cr{\crcr\noalign{\kern2\p@\global\let\cr\endline}}%
+ \ialign{$##$\hfil\kern2\p@\kern\p@renwd&\thinspace\hfil$##$\hfil
+ &&\quad\hfil$##$\hfil\crcr
+ \omit\strut\hfil\crcr\noalign{\kern-\baselineskip}%
+ #1\crcr\omit\strut\cr}}%
+ \setbox\tw@\vbox{\unvcopy\z@\global\setbox\@ne\lastbox}%
+ \setbox\tw@\hbox{\unhbox\@ne\unskip\global\setbox\@ne\lastbox}%
+ \setbox\tw@\hbox{$\kern\wd\@ne\kern-\p@renwd\left(\kern-\wd\@ne
+ \global\setbox\@ne\vbox{\box\@ne\kern2\p@}%
+ \vcenter{\kern-\ht\@ne\unvbox\z@\kern-\baselineskip}\,\right)$}%
+ \null\;\vbox{\kern\ht\@ne\box\tw@}\endgroup}
+
+\def\openup{\afterassignment\@penup\dimen@=}
+\def\@penup{\advance\lineskip\dimen@
+ \advance\baselineskip\dimen@
+ \advance\lineskiplimit\dimen@}
+\def\eqalign#1{\null\,\vcenter{\openup\jot\m@th
+ \ialign{\strut\hfil$\displaystyle{##}$&$\displaystyle{{}##}$\hfil
+ \crcr#1\crcr}}\,}
+\newif\ifdt@p
+\def\displ@y{\global\dt@ptrue\openup\jot\m@th
+ \everycr{\noalign{\ifdt@p \global\dt@pfalse \ifdim\prevdepth>-1000\p@
+ \vskip-\lineskiplimit \vskip\normallineskiplimit \fi
+ \else \penalty\interdisplaylinepenalty \fi}}}
+\def\@lign{\tabskip\z@skip\everycr{}} % restore inside \displ@y
+\def\displaylines#1{\displ@y \tabskip\z@skip
+ \halign{\hbox to\displaywidth{$\@lign\hfil\displaystyle##\hfil$}\crcr
+ #1\crcr}}
+\def\eqalignno#1{\displ@y \tabskip\centering
+ \halign to\displaywidth{\hfil$\@lign\displaystyle{##}$\tabskip\z@skip
+ &$\@lign\displaystyle{{}##}$\hfil\tabskip\centering
+ &\llap{$\@lign##$}\tabskip\z@skip\crcr
+ #1\crcr}}
+\def\leqalignno#1{\displ@y \tabskip\centering
+ \halign to\displaywidth{\hfil$\@lign\displaystyle{##}$\tabskip\z@skip
+ &$\@lign\displaystyle{{}##}$\hfil\tabskip\centering
+ &\kern-\displaywidth\rlap{$\@lign##$}\tabskip\displaywidth\crcr
+ #1\crcr}}
+
+% Definitions related to output
+
+\message{output routines,}
+
+\countdef\pageno=0
+\pageno=1 % first page is number 1
+\newtoks\headline
+\headline={\hfil} % headline is normally blank
+\newtoks\footline
+\footline={\hss\tenrm\folio\hss}
+ % footline is normally a centered page number in font \tenrm
+\newif\ifr@ggedbottom
+\def\raggedbottom{\topskip 10\p@ plus60\p@ \r@ggedbottomtrue}
+\def\normalbottom{\topskip 10\p@ \r@ggedbottomfalse} % undoes \raggedbottom
+\def\folio{\ifnum\pageno<\z@ \romannumeral-\pageno \else\number\pageno \fi}
+\def\nopagenumbers{\footline{\hfil}} % blank out the footline
+\def\advancepageno{\ifnum\pageno<\z@ \global\advance\pageno\m@ne
+ \else\global\advance\pageno\@ne \fi} % increase |pageno|
+
+\newinsert\footins
+\def\footnote#1{\let\@sf\empty % parameter #2 (the text) is read later
+ \ifhmode\edef\@sf{\spacefactor\the\spacefactor}\/\fi
+ #1\@sf\vfootnote{#1}}
+\def\vfootnote#1{\insert\footins\bgroup
+ \interlinepenalty\interfootnotelinepenalty
+ \splittopskip\ht\strutbox % top baseline for broken footnotes
+ \splitmaxdepth\dp\strutbox \floatingpenalty\@MM
+ \leftskip\z@skip \rightskip\z@skip \spaceskip\z@skip \xspaceskip\z@skip
+ \textindent{#1}\footstrut\futurelet\next\fo@t}
+\def\fo@t{\ifcat\bgroup\noexpand\next \let\next\f@@t
+ \else\let\next\f@t\fi \next}
+\def\f@@t{\bgroup\aftergroup\@foot\let\next}
+\def\f@t#1{#1\@foot}
+\def\@foot{\strut\egroup}
+\def\footstrut{\vbox to\splittopskip{}}
+\skip\footins=\bigskipamount % space added when footnote is present
+\count\footins=1000 % footnote magnification factor (1 to 1)
+\dimen\footins=8in % maximum footnotes per page
+
+\newinsert\topins
+\newif\ifp@ge
+\newif\if@mid
+\def\topinsert{\@midfalse\p@gefalse\@ins}
+\def\midinsert{\@midtrue\@ins}
+\def\pageinsert{\@midfalse\p@getrue\@ins}
+\skip\topins=\z@skip % no space added when a topinsert is present
+\count\topins=1000 % magnification factor (1 to 1)
+\dimen\topins=\maxdimen % no limit per page
+\def\@ins{\par\begingroup\setbox\z@\vbox\bgroup} % start a \vbox
+\def\endinsert{\egroup % finish the \vbox
+ \if@mid \dimen@\ht\z@ \advance\dimen@\dp\z@ \advance\dimen@12\p@
+ \advance\dimen@\pagetotal \advance\dimen@-\pageshrink
+ \ifdim\dimen@>\pagegoal\@midfalse\p@gefalse\fi\fi
+ \if@mid \bigskip\box\z@\bigbreak
+ \else\insert\topins{\penalty100 % floating insertion
+ \splittopskip\z@skip
+ \splitmaxdepth\maxdimen \floatingpenalty\z@
+ \ifp@ge \dimen@\dp\z@
+ \vbox to\vsize{\unvbox\z@\kern-\dimen@}% depth is zero
+ \else \box\z@\nobreak\bigskip\fi}\fi\endgroup}
+
+\output{\plainoutput}
+\def\plainoutput{\shipout\vbox{\makeheadline\pagebody\makefootline}%
+ \advancepageno
+ \ifnum\outputpenalty>-\@MM \else\dosupereject\fi}
+\def\pagebody{\vbox to\vsize{\boxmaxdepth\maxdepth \pagecontents}}
+\def\makeheadline{\vbox to\z@{\vskip-22.5\p@
+ \line{\vbox to8.5\p@{}\the\headline}\vss}\nointerlineskip}
+\def\makefootline{\baselineskip24\p@\lineskiplimit\z@\line{\the\footline}}
+\def\dosupereject{\ifnum\insertpenalties>\z@ % something is being held over
+ \line{}\kern-\topskip\nobreak\vfill\supereject\fi}
+
+\def\pagecontents{\ifvoid\topins\else\unvbox\topins\fi
+ \dimen@=\dp\@cclv \unvbox\@cclv % open up \box255
+ \ifvoid\footins\else % footnote info is present
+ \vskip\skip\footins
+ \footnoterule
+ \unvbox\footins\fi
+ \ifr@ggedbottom \kern-\dimen@ \vfil \fi}
+\def\footnoterule{\kern-3\p@
+ \hrule width 2truein \kern 2.6\p@} % the \hrule is .4pt high
+
+% Hyphenation, miscellaneous macros, and initial values for standard layout
+\message{hyphenation}
+
+\lefthyphenmin=2
+\righthyphenmin=3 % disallow x- or -xx breaks
+\input hyphen
+
+\def\magnification{\afterassignment\m@g\count@}
+\def\m@g{\mag\count@
+ \hsize6.5truein\vsize8.9truein\dimen\footins8truein}
+
+\def\tracingall{\tracingonline\@ne\tracingcommands\tw@\tracingstats\tw@
+ \tracingpages\@ne\tracingoutput\@ne\tracinglostchars\@ne
+ \tracingmacros\tw@\tracingparagraphs\@ne\tracingrestores\@ne
+ \showboxbreadth\maxdimen\showboxdepth\maxdimen\errorstopmode}
+
+\def\showhyphens#1{\setbox0\vbox{\parfillskip\z@skip\hsize\maxdimen\tenrm
+ \pretolerance\m@ne\tolerance\m@ne\hbadness0\showboxdepth0\ #1}}
+
+\normalbaselines\rm % select roman font
+\nonfrenchspacing % punctuation affects the spacing
+\catcode`@=12 % at signs are no longer letters
+
+\def\fmtname{plain}
+\def\fmtversion{3.1415926} % identifies the current format
diff --git a/macros/plain/contrib/zztex/tex/zzart.tex b/macros/plain/contrib/zztex/tex/zzart.tex
new file mode 100644
index 0000000000..52b4081426
--- /dev/null
+++ b/macros/plain/contrib/zztex/tex/zzart.tex
@@ -0,0 +1,611 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% Module: ZzTeX Art Facilities
+%
+% Synopsis: This module provides facilities to deal with external art.
+%
+% Author: Paul C. Anagnostopoulos
+% Created: 7 June 1991
+%
+% Copyright 1989--2020 by Paul C. Anagnostopoulos
+% under The MIT License (opensource.org/licenses/MIT)
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% Art File Root & Placing Control
+% --- ---- ---- - ------- -------
+
+
+\def \zartroot {}
+\setflag \zplaceart = \true
+
+
+\def \setartroot #1{% {root/}
+ \gdef \zartroot {#1}}
+
+\def \zprependartroot #1#2{% {\name}{filespec}
+ \edef #1{\zartroot#2}}
+
+\def \placeart #1{%
+ \setflag \zplaceart = #1}
+
+% Imported Art
+% -------- ---
+
+
+\defineblock{\art}{\endart}{\false}{}
+
+%~block art Type
+% \abovepenalty = integer % Penalty above block.
+% \aboveskip = glue % Space b/b above block.
+% \belowpenalty = integer % Penalty below block.
+% \belowskip = glue % Space b/b below block.
+% \setflag \cliptobb = flag % Clip art to its bounding box?
+% \hfuzz = dimen % Horizontal fuzz.
+% \hscale = dimen % Horizontal scale (in points).
+% \leftindent = glue % Left indentation.
+% \rightindent = glue % Right indentation.
+% \vscale = dimen % Vertical scale (in points).
+% \vshift = dimen % Vertical shift.
+%~end
+
+\definedimen{\artwidth}{0pt}
+\definedimen{\artheight}{0pt}
+\definedimen{\hscale}{0pt}
+\definedimen{\vscale}{0pt}
+
+
+%~ The format of the *file-info* argument is:
+%~ *file*,*width*,*height*,*scale*[,*gutter*,*file*,...]&/
+%~ The *file* is a file name preceded by |!| or |=|.
+
+\def \art #1#2{% {type}{file-info}
+ \beginblockscope{art}%
+ \global\increment \artdepth
+ \abovepenalty = \breakgood %~default hard
+ \belowpenalty = \breakgood %~default hard
+ \setflag \cliptobb = \false %~default soft
+ \hfuzz = 1pt %~default soft
+ \hscale = 1.0pt %~default hard
+ \vscale = 1.0pt %~default hard
+ \vshift = \mindimen %~default soft
+ \processdesign{\art}{#1}%
+ \global\increment \artnumber
+ \global\artwidth = 0pt
+ \global\artheight = 0pt
+ \artformat{#2}%
+ \endart}
+
+\def \endart {%
+ \global\decrement \artdepth
+ \endblockscope{art}}
+
+\def \artformat #1{% {info}
+ \endgraf
+ \bbskipabove{\abovepenalty}{\aboveskip}%
+ \alterindentation{\leftindent}{\rightindent}%
+ \noindent \zbldartline 0pt,#1,\zmark \endgraf
+ \prevdepth = 0pt % Nothing better to do.
+ \bbskipbelow{\belowpenalty}{\belowskip}}
+
+\def \zbldartline #1,#2,#3,#4,#5,#6\zmark{% gutter,file,width,height,scale,...,\zmark
+ \zbuildartlineb{#1}{#2}{#3}{#4}{#5}%
+ \zwriteartinfo{#2}{#3}{#4}{#5}%
+ \if \notp{\emptyargp{#6}}\zbldartline #6\zmark \fi}
+
+% Place Art File
+% ----- --- ----
+
+
+\definedimen{\zleftslop}{0pt}
+\definedimen{\zrightslop}{0pt}
+\definedimen{\ztopslop}{0pt}
+\definedimen{\zbottomslop}{0pt}
+\definedimen{\zartwidth}{0pt}
+\definedimen{\zartheight}{0pt}
+\definedimen{\zartscale}{0pt}
+
+
+\def \zbuildartlineb #1#2#3#4#5{% {gutter}{file}{width}{height}{scale}
+ \kern #1\relax
+ \zparseartfile #2,0pt,0pt,0pt,0pt,\zmark
+ \zchkartfile{\zgotart}%
+ \zcalcartdimens{#3}{#4}{#5}%
+ \zbuildartlinec{\zartfile}%
+ \gcalculate \artwidth = {\artwidth,+,#1,+,\zartwidth}%
+ \if \dimgtrp{\zartheight}{\artheight}\global\artheight = \zartheight \fi}
+
+\def \zparseartfile #1,#2,#3,#4,#5,#6\zmark{% spec,left,right,top,bottom\zmark
+ \zparseartspec #1.eps.\zmark
+ \zleftslop = #2%
+ \zrightslop = #3%
+ \ztopslop = #4%
+ \zbottomslop = #5\relax}
+
+\def \zcalcartdimens #1#2#3{% {width}{height}{scale}
+ \if \orp{\andp{\dimzerop{#1}}{\dimzerop{#2}}}
+ {\forceepsbb}%
+ \if \zgotart
+ \zreadepsbb{\zartwidth}{\zartheight}{\zartfile}%
+ \else
+ \zartwidth = 20pc \zartheight = 10pc
+ \fi
+ \else
+ \calculate \zartwidth = {#1,-,\zleftslop,-,\zrightslop}%
+ \calculate \zartheight = {#2,-,\ztopslop,-,\zbottomslop}%
+ \fi
+ \zcalcartscale #3\zmark
+ \calculate \zartwidth = {\zartwidth,S,\zartscale,S,\hscale}%
+ \calculate \zartheight = {\zartheight,S,\zartscale,S,\vscale}%
+ \calculate \zleftslop = {\zleftslop,S,\zartscale,S,\hscale}%
+ \calculate \zbottomslop = {\zbottomslop,S,\zartscale,S,\vscale}%
+ \if \forceepsbb
+ \advance \zleftslop by \zbbxorigin
+ \advance \zbottomslop by \zbbyorigin
+ \fi}
+
+\def \zcalcartscale #1#2\zmark{% scale\zmark
+ \if \codeeqlp{#1}{=}%
+ \if \emptyargp{#2}%
+ \calculate \zartscale = {\hsize,R,\zartwidth}%
+ \else
+ \calculate \zartscale = {#2,R,\zartwidth}%
+ \fi
+ \else
+ \calculate \zartscale = {#1#2pt,/,100}%
+ \fi}
+
+\def \zbuildartlinec #1{% {title}
+ \if \dimeqlp{\vshift}{\mindimen}%
+ \measureascenderheight{\vshift}%
+ \fi
+ \vtop {% % Place art in a vbox.
+ \offinterlineskip
+ \rule{height \vshift width 0pt}% % Force the height of the
+ \kern -\vshift % box to match ascenders.
+ \rule{height 0pt width \zartwidth}% % Force the width of the box.
+ \if \andp{\zplaceart}{\zgotart}%
+ \rule{height 0pt depth \zartheight width 0pt}% % Force its depth.
+ \zplaceartfile
+ \vss
+ \else
+ \vbox to \zartheight{% % Force its depth.
+ \topcornermarks{\zartwidth}{.5pc}{.25pt}%
+ \vss
+ \hbox to \zartwidth {\hss \zannofont #1\hss}%
+ \hbox to \zartwidth {\hss \zannofont
+ \if \notp{\zplaceart}[not placing]\fi
+ \if \notp{\zgotart}[to come]\fi
+ \hss}%
+ \vss
+ \bottomcornermarks{\zartwidth}{.5pc}{.25pt}}%
+ \fi}}
+
+\def \zplaceartfile {%
+ \kern \zbottomslop
+ \moveleft \zleftslop \vbox{%
+ \special{CTM: push}%
+ \special{CTM: scale \thefactor\hscale \space \thefactor\vscale}%
+ \specialplaceepsfile{\zartfile}{\zartscale}{\cliptobb}%
+ \special{CTM: pop}}%
+ \kern -\zbottomslop}
+
+% Duplicates and Missing Art
+% ---------- --- ------- ---
+
+
+% Write an art entry into the cross-reference file.
+
+\def \zwriteartinfo #1#2#3#4{% {file}{width}{height}{scale}
+ \zbeginhidewrite
+ \edef \znext {\noexpand\xref{art}{\noexpand\folio}%
+ {#1}%
+ {#2,#3}
+ {#4}}%
+ \znext
+ \zendhidewrite}
+
+% This macro is invoked by \xref. In copy mode, it checks to make sure
+% that no art file is used twice.
+
+\def \xrefart #1#2#3#4{% {page}{number}{title}{tag}
+ \ifnum \xrefmode=\xrefcopymode
+ \zxrefarta #2,\zmark
+ \fi}
+
+\def \zxrefarta #1#2,#3\zmark{%
+ \if \notp{\orp{\codeeqlp{#1}{!}}{\codeeqlp{#1}{=}}}%
+ \if \definedp{\zart:#1#2}%
+ \warning{dupart}{Art file `#1#2' is used more than once in the book}%
+ \fi
+ \withname\gdef{\zart:#1#2}{}%
+ \fi}
+
+% This macro is invoked at the end of the run.
+
+\def \zmissingartmsg {%
+ \if \posp{\zmissingart}%
+ \remark{Number of missing art files in this run: \number\zmissingart.}%
+ \fi}
+
+% Built-In Art Blocks
+% -------- --- ------
+
+\def \fullpagegraphic #1{% {art-spec}
+ \vsinkfromtrim{-\standardbleed}
+ \smashbox{%
+ \with{\hfuzz=99pc%
+ \leftindent=\if \evenpagep \evenbleedshift \else \oddbleedshift \fi}
+ \art{graphic}{#1}}}
+
+\def \artgraphicdesign {%
+ \aboveskip = \noskip
+ \belowskip = \noskip
+ \setflag \cliptobb = \false
+ \hfuzz = 1pt
+ \leftindent = 0pt
+ \rightindent = 0pt
+ \vshift = 0pt}
+
+% Glyph Definitions
+% ----- -----------
+
+
+% This macro allows the user to define a "glyph," which is an EPS file
+% that is treated like a fancy character. The bounding box must be
+% perfect.
+
+\def \defineglyph #1#2#3{% {\name}{spec,width,height,scale}{raise}
+ \gdef #1{\zglyph #2,#3\zmark}}
+
+\def \zglyph #1,#2,#3,#4,#5\zmark{% spec,width,height,scale,raise\zmark
+ {\zparseartspec #1.eps.\zmark
+ \zchkartfile{\zgotart}%
+ \zartwidth = #2%
+ \zartheight = #3%
+ \tdimena = #4\typesize % \tdimena = final scale in points.
+ \divide \tdimena by 10
+ \calculate \zartwidth = {\zartwidth,P,\thefactor\tdimena}%
+ \calculate \zartheight = {\zartheight,P,\thefactor\tdimena}%
+ \raise #5 \hbox to \zartwidth{%
+ \rule{height \zartheight depth 0pt width 0pt}%
+ \if \zgotart
+ \specialplaceglyph{\zartfile}{\tdimena}{\false}%
+ \fi
+ \hfil}}}
+
+\defineglyph{\acidfree}{!acidfree,2pc,2pc,35}{-1.5pt}
+
+% Panel Label Block
+% ----- ----- -----
+
+
+\defineblock{\panellabel}{\endpanellabel}{\false}{}
+
+%~block panellabel Type
+% \aboveskip = glue % Space b/b above block.
+% \belowskip = glue % Space b/b below block.
+% \bodyfont = {...} % Font for text.
+% \style = {...} % Label style.
+% \vshift = dimen % Vertical shift.
+%~end
+
+\def \panellabel #1#2{% {type}{label-list}
+ \beginblockscope{panellabel}%
+ \global\increment \panellabeldepth
+ \style = {letter in parens}% %~default soft
+ \vshift = 0pt %~default soft
+ \processdesign{\panellabel}{#1}%
+ \global\increment \panellabelnumber
+ \panellabelformat{#2}%
+ \endpanellabel}
+
+\def \endpanellabel {%
+ \global\decrement \panellabeldepth
+ \endblockscope{panellabel}}
+
+\def \panellabelformat #1{% {panel-list}
+ \endgraf
+ \bbskipabove{\breaknever}{\aboveskip}%
+ \the\bodyfont
+ \noindent
+ \zdolabel #1,\zmark
+ \endgraf
+ \bbskipbelow{\breakallowed}{\belowskip}}
+
+\def \zdolabel #1,#2,#3\zmark{% shift,label,...
+ \rlap{%
+ \hspace{#1}%
+ \smash{\lower \vshift \hbox{#2}}}%
+ \if \notp{\emptyargp{#3}}\zdolabel #3\zmark \fi}
+
+% Frames
+% ------
+
+
+\defineblock{\frame}{\endframe}{\false}{}
+
+%~block frame Type
+% \abovepenalty = integer % Penalty above block.
+% \aboveskip = glue % Space b/b above block.
+% \def \backgroundformat ##1{...} % Background formatter.
+% \belowpenalty = integer % Penalty below block.
+% \belowskip = glue % Space b/b below block.
+% \deferredparams = {...} % Deferred parameter calculations.
+% \framecolor = {color} % Color of frame.
+% \framewidths = {left,right,top,bot} % Widths of frame segments.
+% \framegaps = {left,right,top,bot} % Gaps between frame and material.
+% \leftindent = glue % Left indentation of enclosed material.
+% \screencolor = {color} % Background screen color.
+% \width = dimen % Width of enclosed material.
+%~end
+
+% Together, \leftindent and \width specify the position of the enclosed
+% text within the text box, not of the frame itself.
+
+
+\definetoks{\deferredparams}
+\definetoks{\framecolor}
+\definetoks{\framewidths}
+\definetoks{\framegaps}
+\definetoks{\screencolor}
+
+\definecount{\framepage}{0}
+
+\definecount{\zdivframecounter}{0}
+
+\def \frame #1{% {type}
+ \beginblockscope{frame}%
+ \global\increment \framedepth
+ \global\increment \zdivframecounter
+ \whichpage{\framepage}{zE:\the\divisionname-\the\zdivframecounter}%
+ \abovepenalty = \breakgood %~default hard
+ \def \backgroundformat ##1{}% %~default soft
+ \belowpenalty = \breakgood %~default hard
+ \deferredparams = {}% %~default soft
+ \framecolor = {black}% %~default soft
+ \leftindent = 0pt %~default soft
+ \screencolor = {}% %~default soft
+ \width = \naturalwidth %~default soft
+ \processdesign{\frame}{#1}%
+ \global\increment \framenumber
+ \setbox\zboxa = \vtop \bgroup
+ \zpushvcontext}
+
+\def \endframe {%
+ \endgraf
+ \unskip
+ \zpopvcontext
+ \egroup % \vtop
+ \the\deferredparams
+ \setbox\zboxb = \hbox to \width{%
+ \hspace{-\leftindent}\box\zboxa \hss}%
+ \edef \zcolorrule {\noexpand\colorrule{\the\framecolor}}%
+ \def \zarga ##1,##2,##3,##4\zmark{##1\relax}%
+ \def \zargb ##1,##2,##3,##4\zmark{##2\relax}%
+ \def \zargc ##1,##2,##3,##4\zmark{##3\relax}%
+ \def \zargd ##1,##2,##3,##4\zmark{##4\relax}%
+ \tdimenc = \expandafter\zargc\the\framegaps\zmark
+ \advance \tdimenc by \ht\zboxb
+ \advance \tdimenc by \dp\zboxb
+ \advance \tdimenc by \expandafter\zargd\the\framegaps\zmark
+ \setbox\zboxa = \vtop {%
+ \offinterlineskip
+ \measureascenderheight{\tdimena}% % Force the height of the
+ \rule{width 0pt height \tdimena}% % box to match ascenders.
+ \kern -\tdimena
+ \smashbox{\backgroundformat{\tdimenc}}%
+ \if \notp{\emptytoksp{\screencolor}}%
+ \tdimend = \expandafter\zarga\the\framegaps\zmark
+ \advance \tdimend by \wd\zboxb
+ \advance \tdimend by \expandafter\zargb\the\framegaps\zmark
+ \smashbox{%
+%%% \moveright \expandafter\zarga\the\framewidths\zmark \smashbox{%
+ \colorrule{\the\screencolor}{width \tdimend height \tdimenc}}%
+ \fi
+ \zcolorrule{height \expandafter\zargc\the\framewidths\zmark}%
+ \kern -\expandafter\zargc\the\framewidths\zmark
+ \hbox {%
+ \rlap{\zcolorrule{height \tdimenc
+ width \expandafter\zarga\the\framewidths\zmark}}%
+ \hskip \expandafter\zarga\the\framegaps\zmark
+ \vbox {%
+ \vskip \expandafter\zargc\the\framegaps\zmark
+ \box\zboxb
+ \vskip \expandafter\zargd\the\framegaps\zmark}%
+ \hskip \expandafter\zargb\the\framegaps\zmark
+ \llap{\zcolorrule{height \tdimenc
+ width \expandafter\zargb\the\framewidths\zmark}}}%
+ \kern -\expandafter\zargd\the\framewidths\zmark
+ \zcolorrule{height \expandafter\zargd\the\framewidths\zmark}%
+ \tagpageonly{\uniquetag{zE}{\the\zdivframecounter}}}%
+ \advance \leftindent by -\expandafter\zarga\the\framewidths\zmark
+ \advance \leftindent by -\expandafter\zarga\the\framegaps\zmark
+ \frameformat
+ \global\decrement \framedepth
+ \endblockscope{frame}}
+
+\def \frameformat {%
+ \bbskipabove{\abovepenalty}{\aboveskip}%
+ \hindent{\leftindent} \rlap{\box\zboxa}\par
+ \prevdepth = 0pt % Last thing in box is rule.
+ \bbskipbelow{\belowpenalty}{\belowskip}}
+
+% This macro is invoked at the beginning of each division.
+
+\def \zframedivinit {%
+ \global\zdivframecounter = 0\relax}
+
+% Margin Rules
+% ------ -----
+
+
+\defineblock{\marginrule}{\endmarginrule}{\false}{}
+
+%~block marginrule Type
+% \artspec = {...} % Art spec for graphic above rule.
+% \leftshift = dimen % Horizontal shift for rule in left margin.
+% \position = {...} % Position options.
+% \rightshift = dimen % Horizonal shift for rule in right margin.
+% \rulecolor = {...} % Color of rule.
+% \rulewidth = dimen % Width of rule.
+% \vshift = dimen % Vertical shift for note.
+%~end
+
+\definetoks{\artspec}
+\definedimen{\leftshift}{0pt}
+\definedimen{\rightshift}{0pt}
+
+\definecount{\marginrulepage}{0}
+
+\definecount{\zdivmrcounter}{0}
+\definedimen{\zmrshift}{0pt}
+\definedimen{\zmrprevdepth}{0pt}
+
+\def \marginrule #1#2{% {type}{height,depth}
+ \blockcantbein{\marginrule}{\marginrule}%
+ \beginblockscope{marginrule}%
+ \global\increment \marginruledepth
+ \global\increment \zdivmrcounter
+ \whichpage{\marginrulepage}{zR:\the\divisionname-\the\zdivmrcounter}%
+ \rulecolor = {black} %~default soft
+ \vshift = 0pt %~default soft
+ \processdesign{\marginrule}{#1}%
+ \zparsemrpos{\the\position}%
+ \marginruleformat{#2}%
+ \endmarginrule}
+
+\def \endmarginrule {%
+ \global\decrement \marginruledepth
+ \endblockscope{marginrule}}
+
+\def \marginruleformat #1{% {height,depth}
+ \if \vmodep
+ \zmrprevdepth = \prevdepth
+ \nointerlineskip
+ \else
+ \vadjust
+ \fi
+ \bgroup
+ \topskip = 0pt
+ \moveright \zmrshift \vtop to 0pt{%
+ \vskip \vshift
+ \zmrgraphic
+ \zmrrule #1\zmark
+ \vss
+ \tagpageonly{\uniquetag{zR}{\the\zdivmrcounter}}}%
+ \egroup
+ \if \vmodep \prevdepth = \zmrprevdepth \fi}
+
+% This macro sets up variables that specify the position of a margin rule
+% according to the \position design parameter:
+%
+% \ifevenpage Use next position only on even page.
+% \ifoddpage Use next position only on odd page.
+% \leftmargin Shift note to left margin.
+% \outsidemargin Shift note to outside margin.
+% \rightmargin Shift note to right margin.
+
+\definecount{\zmrhpos}{0}
+
+\def \zparsemrpos #1{% {options...}
+ \global\zmrhpos = 0
+ {\def \ifevenpage ##1{\if \evenp{\marginrulepage}##1\fi}%
+ \def \ifoddpage ##1{\if \oddp{\marginrulepage}##1\fi}%
+ \def \leftmargin {\global\zmrhpos=1\relax}%
+ \def \outsidemargin{\ifevenpage{\leftmargin}\ifoddpage{\rightmargin}}%
+ \def \rightmargin {\global\zmrhpos=2\relax}%
+ #1\relax}%
+ \ifcase \zmrhpos
+ \error{nomrpos}
+ {No horizontal position has been specified for a margin rule}%
+ \or
+ \if \negp{\leftshift}%
+ \zmrshift = \leftshift
+ \else
+ \if \evenp{\marginrulepage}%
+ \calculate \zmrshift = {-\evenlefttextmargin,+,\leftshift}%
+ \else
+ \calculate \zmrshift = {-\oddlefttextmargin,+,\leftshift}%
+ \fi
+ \fi
+ \or
+ \calculate \zmrshift = {\textmeasure,+,\rightshift}%
+ \fi}
+
+\def \zmrgraphic {%
+ \if \emptytoksp{\artspec}%
+ \artheight = 0pt
+ \else
+ \xdef \znext {\noexpand\art{zmarginrule}{\the\artspec}}%
+ \znext
+ \kern -1pt
+ \fi}
+
+\definedimen{\zmrdepth}{0pt}
+
+\def \zmrrule #1,#2\zmark{% height,depth\zmark
+ \calculate \zmrdepth = {#2,-,\artheight}%
+ \setbox \zboxa = \hbox{\vrule width 0pt height #1 depth \zmrdepth}%
+ \vskip -\ht\zboxa
+ \colorrule{\the\rulecolor}{width \rulewidth height #1 depth \zmrdepth}}
+
+\def \artzmarginruledesign {%
+ \aboveskip = \noskip
+ \belowskip = \noskip
+ \setflag \cliptobb = \false
+ \hfuzz = 999pc
+ \leftindent = 0pt
+ \rightindent = 0pt
+ \vshift = \mindimen}
+
+% This macro is invoked at the beginning of each division.
+
+\def \zmrdivinit {%
+ \global\zdivmrcounter = 0\relax}
+
+% Corner Marks
+% ------ -----
+
+
+\def \topcornermarks #1#2#3{% {box-width}{length}{thickness}
+ \hbox to #1{\vrule height #3 depth 0pt width #2 \hss
+ \vrule height #3 depth 0pt width #2}%
+ \nointerlineskip
+ \hbox to #1{\vrule height #2 depth 0pt width #3 \hss
+ \vrule height #2 depth 0pt width #3}}
+
+\def \bottomcornermarks #1#2#3{% {box-width}{length}{thickness}
+ \hbox to #1{\vrule height #2 depth 0pt width #3 \hss
+ \vrule height #2 depth 0pt width #3}%
+ \nointerlineskip
+ \hbox to #1{\vrule height #3 depth 0pt width #2 \hss
+ \vrule height #3 depth 0pt width #2}}
+
+% Utilities
+% ---------
+
+
+\definecount{\zmissingart}{0} % Count of missing art files.
+
+
+% Check that the art file exists and issue remark if not.
+
+\def \zchkartfile #1{% {\flag}
+ \setflag #1= \true
+ \checkfile{\znext}{\zartfile}%
+ \if \notp{\znext}%
+ \remark{Art file `\zartfile' is missing; ignored for now}%
+ \global\increment \zmissingart
+ \setflag #1= \false
+ \fi}
+
+\def \zparseartspec #1#2.#3.#4\zmark{% name.ext.\zmark
+ \def \zartfile {???}% % Why do this?
+ \if \codeeqlp{#1}{!}%
+ \def \zartfile{#2.#3}%
+ \else\if \codeeqlp{#1}{=}%
+ \zprependartroot{\zartfile}{#2.#3}%
+ \else
+ \zprependartroot{\zartfile}{#1#2.#3}%
+ \fi\fi}
diff --git a/macros/plain/contrib/zztex/tex/zzbiblio.tex b/macros/plain/contrib/zztex/tex/zzbiblio.tex
new file mode 100644
index 0000000000..cc834e4109
--- /dev/null
+++ b/macros/plain/contrib/zztex/tex/zzbiblio.tex
@@ -0,0 +1,427 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% Module: ZzTeX Bibliography Facility
+%
+% Synopsis: This module provides a new bibliography facility to replace
+% zzbibtex. It is more flexible so that it can handle numeric,
+% key, and author/year citations.
+%
+% Author: Paul C. Anagnostopoulos
+% Created: 1 December 2016
+%
+% Copyright 1989--2020 by Paul C. Anagnostopoulos
+% under The MIT License (opensource.org/licenses/MIT)
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% Initialization
+% --------------
+
+
+\def \zbiblioinit {%
+ \if \definedp{\bibliodesign}%
+ \begingroup
+ \bibliodesign
+ \globaldefs = 1
+ \citestyle = \citestyle
+ \endgroup
+ \fi}
+
+% Bibliography Cross-Reference
+% ------------ ---------------
+
+
+% When tags are loaded, define the name \=zB:tag to contain the
+% bibliographic info in this format:
+% folio\zmark key\zmark {author}{year}{full-author}
+
+\def \xrefbib #1#2#3#4{% {folio}{key}{{author}{year}{full-author}}{tag}
+ \ifnum \xrefmode=\xrefloadtagmode
+ \if \definedp{\=zB:#4}\zduptag{#4}\fi
+ \withname\gdef{\=zB:#4}{#1\zmark#2\zmark#3}%
+ \fi}
+
+% This macro loads the cite cross-reference entries and invokes the
+% specified macro for each one.
+
+\def \mapxrefcites #1{% {\macro}
+ {\let \zmapcitemacro = #1\relax
+ \zxloadcomp{\xrefloadcitemode}}}
+
+\def \xrefcite #1#2#3#4{% {page}{}{}{tag}
+ \ifnum \xrefmode=\xrefloadcitemode
+ \zmapcitemacro{#1}{#4}%
+ \fi}
+
+% Biblio Block
+% ------ -----
+
+
+\defineblock{\biblio}{\endbiblio}{\false}{}
+
+%~block biblio
+% \citestyle = integer % Citation style.
+% \setflag \indexcites = boolean % If true, index each cite (not implemented).
+% \setflag \citeself = boolean % If true, \bibitem cites itself (not implemented).
+%~end
+
+\definecount{\citestyle}{-1}
+
+\chardef \citebynumber = 0
+\chardef \citebykey = 1
+\chardef \citebyauthoryear = 2
+
+
+\def \biblio {%
+ \blockcantbein{\biblio}{\biblio}%
+ \blockmustbein{\biblio}{\list}%
+ \beginblockscope{biblio}%
+ \global\increment \bibliodepth
+ \setflag \citeself = \false %~default soft
+ \processdesign{\biblio}{}%
+ \global\increment \biblionumber}
+
+\def \endbiblio {%
+ \endgraf
+ \fakepar % In case biblio is empty.
+ \global\decrement \bibliodepth
+ \endblockscope{biblio}}
+
+% Bibliography Items
+% ------------ -----
+
+
+\definecount{\zbibitemnumber}{0}
+\definetoks{\zbibauthor}
+\definetoks{\zbibyear}
+\definetoks{\zbibfullauthor}
+\definetoks{\bibitemtag} % Tag of current \bibitem.
+
+
+%~ The |\bibitem| command is used in a |\biblio| block to start
+%~ each entry in the bibliography. It takes two arguments; the
+%~ format of the first argument depends on the citation style.
+%~ * Cited by number: |\bibitem{}{*tag*}|
+%~ * Cited by key: |\bibitem{*key*}{*tag*}|
+%~ * Cited by author/year: |\bibitem{*author*;*year*;*full-author*}{*tag*}|
+%~ *.
+%~ In the author/year format, the second semicolon and *full-author* are
+%~ optional.
+
+\def \bibitem #1#2{% {[info]}{tag}
+ \blockmustbein{\bibitem}{\biblio}%
+ \zbibitemnumber = \itemnumber
+ \increment \zbibitemnumber
+ \ifcase \citestyle
+ \edef \zbibkey {\the\zbibitemnumber}%
+ \zbibauthor = {}%
+ \zbibyear = {}%
+ \zbibfullauthor = {}%
+ \or
+ \def \zbibkey {#1}%
+ \zbibauthor = {}%
+ \zbibyear = {}%
+ \zbibfullauthor = {}%
+ \or
+ \def \zbibkey {}%
+ \zparseauthoryear #1;;;\zmark
+ \else
+ \error{invalidcitestyle}{The \string\citestyle parameter is invalid: \the\citestyle}%
+ \fi
+ \bibitemtag = {#2}%
+ \item{\zbibkey}%
+ \if \PDFhyperlinks \PDFmark{T:#2}\fi
+ \if \notp{\emptyargp{#2}}%
+ \edef \znext {%
+ \noexpand\xref{bib}{\noexpand\folio}
+ {\zbibkey}
+ {{\the\zbibauthor}{\the\zbibyear}{\the\zbibfullauthor}}
+ {#2}}%
+ \znext
+ \fi
+%%% \if \indexcites
+%%% \edef \znext {\noexpand\xbiblio1{\the\zbibauthor}}%
+%%% \znext
+%%% \fi
+ \ignorespaces}
+
+\def \zparseauthoryear #1;#2;#3;#4\zmark{%
+ \if \orp{\emptyargp{#1}}{\emptyargp{#2}}%
+ \error{nocitetags}{The author and/or year are missing}%
+ \fi
+ \zbibauthor = {#1}%
+ \zbibyear = {#2}%
+ \zbibfullauthor = {#3}}
+
+% Bibliography Citation Page List
+% ------------ -------- ---- ----
+
+
+\setflag \zcitexrefsloaded = \false
+
+
+%~ If this macro is specified as the |\endpartext| of a bibliography
+%~ |\list|, then each entry in the bibliography will include a list
+%~ of the pages citing that entry. The argument determines whether
+%~ each page is made into a hyperlinked PDF button.
+%~
+%~ In order for the citation information to be available, the
+%~ |\xrefcites| document parameter must be set to 1.
+
+\def \citepagelist #1{% {button?}
+ \if \notp{\zcitexrefsloaded}%
+ \mapxrefcites{\zbibcitelist}%
+ \global\setflag \zcitexrefsloaded = \true
+ \fi
+ \setflag \zbibfirstpage = \true
+ \def \zbibprevpage {}%
+ \withname\maplistlf {\=citetag:\the\bibitemtag}
+ {\zbibcitepage{##1}{#1}}}
+
+\def \zbibcitelist #1#2{% {page}{tag}
+ \if \withname\undefinedp {\=citetag:#2}%
+ \withname\setlist {\=citetag:#2}={}%
+ \fi
+ \withname\appendlf {\=citetag:#2}{#1}}
+
+\def \zbibcitepage #1#2{% {page}{button?}
+ \stringeql{\zsamepage}{#1}{\zbibprevpage}%
+ \if \notp{\zsamepage}%
+ \if \notp{\emptydefp{\zbibprevpage}},\space \fi
+ \if #2%
+ \pagebutton{#1}{#1}%
+ \else
+ #1%
+ \fi
+ \def \zbibprevpage {#1}%
+ \fi}
+
+% Low-Level Citation Commands
+% --------- -------- --------
+
+
+%~ This command produces the key of the bibliography entry specified
+%~ by the *tag*. The command makes sense only for the numbered or
+%~ keyed citation styles.
+
+\def \citekey #1{% {tag} %^citation
+ \if \eqlp{\citestyle}{\citebyauthoryear}%
+ \warning{badcitekey}{The \noexpand\citekey command doesn't make sense
+ when citing by author/year}%
+ \fi
+ \zcitetaginfo{#1}%
+ \zcitetext{#1}{\zcitekey}%
+ \zxrefcite{\true}{#1}}
+%%% \if \indexcites \zciteindex{\zcitekey}\fi}
+
+%~ This command produces the author of the bibliography entry specified
+%~ by the *tag*. The command makes sense only for the author/year
+%~ citation style.
+
+\def \citeauthor #1{% {tag} %^citation
+ \if \neqlp{\citestyle}{\citebyauthoryear}%
+ \warning{badciteauthor}{The \noexpand\citeauthor command only makes sense
+ when citing by author/year}%
+ \fi
+ \zcitetaginfo{#1}%
+ \zcitetext{#1}{\zciteauthor}%
+ \zxrefcite{\true}{#1}}
+
+%~ This command produces the year of the bibliography entry specified
+%~ by the *tag*. The command makes sense only for the author/year
+%~ citation style.
+
+\def \citeyear #1{% {tag} %^citation
+ \if \neqlp{\citestyle}{\citebyauthoryear}%
+ \warning{badciteyear}{The \noexpand\citeyear command only makes sense
+ when citing by author/year}%
+ \fi
+ \zcitetaginfo{#1}%
+ \zcitetext{#1}{\zciteyear}%
+ \zxrefcite{\true}{#1}}
+
+%~ This command produces the full author of the bibliography entry specified
+%~ by the *tag*. The command makes sense only for the author/year
+%~ citation style.
+
+\def \citefullauthor #1{% {tag} %^citation
+ \if \neqlp{\citestyle}{\citebyauthoryear}%
+ \warning{badcitefullauthor}{The \noexpand\citefullauthor command only makes sense
+ when citing by author/year}%
+ \fi
+ \zcitetaginfo{#1}%
+ \zcitetext{#1}{\zcitefullauthor}%
+ \zxrefcite{\true}{#1}}
+
+\def \zcitetaginfo #1{% {tag}
+ \zcitenoinfo
+ \if \definedp{\=zB:#1}%
+ \expandafterthrice\zcitetaginfoa \name{\=zB:#1}%
+ \else
+ \writelog{ZzTeX citation: undefined tag `#1'.}%
+ \zxwriteinfo{\false}{undef-tag}{#1}{}%
+ \global\increment \zuntagrefs
+ \fi}
+
+\def \zcitetaginfoa #1\zmark#2\zmark#3#4#5{% folio\zmark key\zmark
+ % {author}{year}{full-author}
+ \if \eqlp{\citestyle}{\citebyauthoryear}%
+ \def \zciteauthor {#3}%
+ \def \zciteyear {#4}%
+ \def \zcitefullauthor {#5}%
+ \else
+ \def \zcitekey {#2}%
+ \fi}
+
+\def \zcitenoinfo {%
+ \def \zcitekey {???}%
+ \def \zciteauthor {???author???}%
+ \def \zciteyear {???}%
+ \def \zcitefullauthor {???full-author???}}
+
+\def \zcitetext #1#2{% {tag}{text}
+ \if \DVIWindoinuse \colorspecial{ifview color push rgb .5 .22 .24}\fi
+ \if \PDFhyperlinks
+ \tagbutton{#1}{#2}%
+ \else
+ #2%
+ \fi
+ \if \DVIWindoinuse \colorspecial{ifview color pop}\fi}
+
+\def \zxrefcite #1#2{% {defined?}{tag}
+ \ifcase \xrefcites
+ \relax
+ \or
+ \xref{cite}{\folio}{}{}{#2}%
+ \else
+ \customcitexref{#1}{#2}% {boolean}{tag}
+ \fi}
+
+%%%\def \zciteindex #1{% {\zcitemacro}
+%%% \expandafter\xcite\expandafter1\expandafter{#1}}
+
+% High-Level Citation Commands
+% ---------- -------- --------
+
+
+%~ This high-level citation command produces the key or author/year
+%~ of the bibliography entry specified by the *tag*. The text
+%~ is formatted in the style appropriate for a noun in a sentence.
+%~ There are two formats for the command:
+%~ * |\citenoun{*tag*}| accepts a tag and produces the key or author/year.
+%~ * |\citenoun{*tag*;*info*}| accepts a tag and additional
+%~ information such as a page number or section reference.
+%~ *.
+%~ The format of the text produced is controlled by the |\citenounformat|,
+%~ |\citenouninfoformat|, and |\citepunct| macros in the design file.
+
+\def \citenoun #1{% {tag[;info]} %^citation
+ \expandafter\zsetcitepunc \citepunct
+ \zcitetagsinfo #1;;\zmark
+ \def \zcitenounsep {}%
+ \expandafter\zcitenoun \zcitetags,\zmark}
+
+\def \zcitenoun #1,#2\zmark {% tag,other-tags\zmark
+ \zcitenounsep
+ \edef \zcitenounsep {\zcitesep}%
+ \if \eqlp{\citestyle}{\citebyauthoryear}%
+ \if \emptydefp{\zciteinfo}%
+ \zciteonetag{\citenounformat}#1!!\zmark
+ \else
+ \citenouninfoformat{\citeauthor{#1}}{\citeyear{#1}}{\zciteinfo}%
+ \fi
+ \else
+ \if \emptydefp{\zciteinfo}%
+ \citenounformat{\citekey{#1}}%
+ \else
+ \citenouninfoformat{\citekey{#1}}{\zciteinfo}%
+ \fi
+ \fi
+ \if \notp{\emptyargp{#2}}\zcitenoun #2\zmark \fi}
+
+%~ This high-level citation command produces the key or author/year
+%~ of the bibliography entry specified by the *tag*. The text
+%~ is formatted in the style appropriate for a parenthetical
+%~ citation list. There are two formats for the command:
+%~ * |\citeparen{*tag-list*}| accepts one or more tags separated
+%~ by commas and produces a parenthetical list of keys or author/years.
+%~ * |\citeparen{*tag*;*info*}| accepts a tag and additional
+%~ information such as a page number or section reference.
+%~ *.
+%~ The format of the text produced is controlled by the |\citeparenformat|,
+%~ |\citepareninfoformat|, and |\citepunct| macros in the design file.
+
+\def \citeparen #1{% {tags[;info]} %^citation
+ \expandafter\zsetcitepunc \citepunct
+ \zcitetagsinfo #1;;\zmark
+ \expandafter\zciteparen \zcitetags,\zmark
+ \zcitecfence}
+
+\def \zciteparen #1,#2\zmark {% tag,other-tags\zmark
+ \zciteofence
+ \edef \zciteofence {\zcitesep}%
+ \if \eqlp{\citestyle}{\citebyauthoryear}%
+ \if \emptydefp{\zciteinfo}%
+ \zciteonetag{\citeparenformat}#1!!\zmark
+ \else
+ \citepareninfoformat{\citeauthor{#1}}{\citeyear{#1}}{\zciteinfo}%
+ \fi
+ \else
+ \if \emptydefp{\zciteinfo}%
+ \citeparenformat{\citekey{#1}}%
+ \else
+ \citepareninfoformat{\citekey{#1}}{\zciteinfo}%
+ \fi
+ \fi
+ \if \notp{\emptyargp{#2}}\zciteparen #2\zmark \fi}
+
+%~ This high-level citation command produces the key or author/year
+%~ of the bibliography entry specified by the *tag*. The text
+%~ is formatted in the style appropriate for a citation that is part
+%~ of a surrounding parenthetical sentence.
+%~ There are two formats for the command:
+%~ * |\citeplain{*tag*}| accepts a tag and produces the key or author/year.
+%~ * |\citeplain{*tag*;*info*}| accepts a tag and additional
+%~ information such as a page number or section reference.
+%~ *.
+%~ The format of the text produced is controlled by the |\citeplainformat|
+%~ and |\citeplaininfoformat| macros in the design file.
+
+\def \citeplain #1{% {tag[;info]} %^citation
+ \zcitetagsinfo #1;;\zmark
+ \expandafter\zciteplain \zcitetags,\zmark}
+
+\def \zciteplain #1,#2\zmark {% tag,other-tags\zmark
+ \if \eqlp{\citestyle}{\citebyauthoryear}%
+ \if \emptydefp{\zciteinfo}%
+ \zciteonetag{\citeparenformat}#1!!\zmark
+ \else
+ \citepareninfoformat{\citeauthor{#1}}{\citeyear{#1}}{\zciteinfo}%
+ \fi
+ \else
+ \if \emptydefp{\zciteinfo}%
+ \citeparenformat{\citekey{#1}}%
+ \else
+ \citepareninfoformat{\citekey{#1}}{\zciteinfo}%
+ \fi
+ \fi
+ \if \notp{\emptyargp{#2}}\zciteplain #2\zmark \fi}
+
+\def \zsetcitepunc #1#2#3{%
+ \def \zciteofence {#1}%
+ \def \zcitecfence {#2}%
+ \def \zcitesep {#3}}
+
+\def \zcitetagsinfo #1;#2;#3\zmark {% {tags[;info]}
+ \if \emptyargp{#1}%
+ \warning{nocitetags}{No bibliography entry tags were specified}%
+ \fi
+ \def \zcitetags {#1}%
+ \def \zciteinfo {#2}}
+
+\def \zciteonetag #1#2!#3!#4\zmark {%
+ \if \emptyargp{#2}%
+ \citeyear{#3}%
+ \else
+ #1{\citeauthor{#2}}{\citeyear{#2}}%
+ \fi} \ No newline at end of file
diff --git a/macros/plain/contrib/zztex/tex/zzbibtex.tex b/macros/plain/contrib/zztex/tex/zzbibtex.tex
new file mode 100644
index 0000000000..a6179133f8
--- /dev/null
+++ b/macros/plain/contrib/zztex/tex/zzbibtex.tex
@@ -0,0 +1,290 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% Module: ZzTeX Interface to BibTeX
+%
+% Synopsis: This module provides the definitions necessary for ZzTeX to
+% interface to BibTeX.
+%
+% Author: Paul C. Anagnostopoulos
+% Created: 21 July 1992
+%
+% Copyright 1989--2020 by Paul C. Anagnostopoulos
+% under The MIT License (opensource.org/licenses/MIT)
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% Bibliography Preparation
+% ------------ -----------
+
+
+\def \zbiblioinit {}
+
+\ignore
+\setflag \zbiblioing = \false
+
+\def \preparebiblio {%
+ \setflag \zbiblioing = \true}
+
+\def \zbibfinal {%
+ \if \zbiblioing
+ \remark{[Generating auxiliary file for BibTeX.}%
+ {\immediate\openout \zwritea = \jobname.aux\relax
+ \immediate\write \zwritea
+ {\zcomment BibTeX auxiliary file for book `\jobname'.}%
+ \processdesign{\biblio}{}%
+ \immediate\write \zwritea {\string\bibstyle{\the\bibliostyle}}%
+ \immediate\write \zwritea {\string\bibdata{\the\bibliofiles}}%
+ \let \zxmodesave = \xrefmode
+ \let \xrefmode = \xrefloadauxmode
+ \input \jobname.zzc\relax
+ \let \xrefmode = \zxmodesave
+ \immediate\write \zwritea {\zcomment [end]}%
+ \immediate\closeout \zwritea}
+ \remark{Auxiliary file complete.]}%
+ \fi}
+
+\endignore
+
+% Citations
+% ---------
+
+
+%~ This citation command produces the key associated with
+%~ the specified tag. The key is usually the bibliography
+%~ entry number or the author/year combination.&/
+%~ *Note:* Some books do not allow this command to be used.
+
+\def \cite #1{% {tag} %^citation
+ \ensurepar
+ \if \definedp{\=zB:#1}%
+ \zcitetext{#1}{\expandafterthrice\zbibdata \name{\=zB:#1}0}%
+ \else
+ \zuncite{#1}%
+ \fi
+ \zxrefcite{\true}{#1}}
+
+%~ This citation command produces the author associated with
+%~ the specified tag.
+
+\def \citeauthor #1{% {tag} %^citation
+ \ensurepar
+ \if \definedp{\=zB:#1}%
+ \zcitetext{#1}{\expandafterthrice\zbibdata \name{\=zB:#1}1}%
+ \else
+ \zuncite{#1}%
+ \fi
+ \zxrefcite{\true}{#1}}
+
+%~ This citation command produces the year associated with
+%~ the specified tag.
+
+\def \citeyear #1{% {tag} %^citation
+ \ensurepar
+ \if \definedp{\=zB:#1}%
+ \zcitetext{#1}{\expandafterthrice\zbibdata \name{\=zB:#1}2}%
+ \else
+ \zuncite{#1}%
+ \fi
+ \zxrefcite{\true}{#1}}
+
+\def \nocite #1{% {tag}
+ \zxrefcite{\false}{#1}}
+
+\def \zcitetext #1#2{% {tag}{text}
+ \if \PDFhyperlinks
+ \tagbutton{#1}{#2}%
+ \else
+ #2%
+ \fi}
+
+\def \zxrefcite #1#2{%
+ \ifcase \xrefcites
+ \relax
+ \or
+ \xref{cite}{\folio}{}{}{#2}%
+ \else
+ \customcitexref{#1}{#2}% {boolean}{tag}
+ \fi}
+
+\def \zbibdata #1\zmark#2\zmark#3#4#5#6{% folio\zmark xxx\zmark
+ % {label}{author}{year}n
+ \if \DVIWindoinuse \colorspecial{ifview color push rgb .75 .35 0}\fi
+ \ifcase #6 #3\or #4\or #5\fi
+ \if \DVIWindoinuse \colorspecial{ifview color pop}\fi
+ \if \indexcites \xcite1{#4}\fi}
+
+\def \zuncite #1{%
+ \writelog{ZzTeX citation: undefined tag `#1'.}%
+ \zxwriteinfo{\false}{undef-tag}{#1}{}%
+ \global\increment \zuntagrefs
+ \zbibdata -\zmark-\zmark{???}--0}
+
+% Bibliography Cross-Reference
+% ------------ ---------------
+
+
+% When tags are loaded, define the name \=zB:tag to contain the
+% bibliographic info.
+
+\def \xrefbib #1#2#3#4{% {page}{???}{{label}{author}{year}}{tag}
+ \ifnum \xrefmode=\xrefloadtagmode
+ \if \definedp{\=zB:#4}\zduptag{#4}\fi
+ \withname\gdef{\=zB:#4}{#1\zmark#2\zmark#3}%
+ \fi}
+
+% This macro loads the cite cross-reference entries and invokes the
+% specified macro for each one.
+
+\def \mapxrefcites #1{% {\macro}
+ {\let \zmapcitemacro = #1\relax
+ \zxloadcomp{\xrefloadcitemode}}}
+
+\def \xrefcite #1#2#3#4{% {page}{}{}{tag}
+ \ifnum \xrefmode=\xrefloadcitemode
+ \zmapcitemacro{#1}{#4}%
+ \fi}
+
+% Biblio Block
+% ------ -----
+
+
+\defineblock{\biblio}{\endbiblio}{\false}{}
+
+%~block biblio
+% \bibliofiles = {file,...} % List of biblio database files.
+% \bibliostyle = {name} % Name of biblio style.
+% \setflag \citeself = boolean % If true, \bibitem cites itself.
+%~end
+
+\definetoks{\bibliofiles}
+\definetoks{\bibliostyle}
+
+\definecount{\zbiblionum}{0}
+
+
+\def \biblio {%
+ \blockcantbein{\biblio}{\biblio}%
+ \blockmustbein{\biblio}{\list}%
+ \beginblockscope{biblio}%
+ \global\increment \bibliodepth
+ \setflag \citeself = \false %~default soft
+ \processdesign{\biblio}{}%
+ \global\increment \biblionumber
+ \def \begin ##1##2{}%
+ \def \end ##1{}%
+ \let \bibitem = \zbibitem
+ \let \newblock = \relax
+ \let \em = \it
+ \zbiblionum = 0\relax}
+
+\def \endbiblio {%
+ \endgraf
+ \fakepar % In case biblio is empty.
+ \global\decrement \bibliodepth
+ \endblockscope{biblio}}
+
+% Bibliography Item
+% ------------ ----
+
+
+\definetoks{\zbibtoksa}
+\definetoks{\zbibtoksb}
+\definetoks{\zbibtoksc}
+\definetoks{\bibitemtag} % Tag of current \bibitem.
+
+
+% This supports items of the form `\bibitem[label][author][year]{tag}'.
+
+\def \zbibitem {%
+ \futurelet\znext \zbibitema}
+
+\def \zbibitema {%
+ \ifx \znext[%
+ \let \znext = \zbibitemb
+ \else
+ \increment \zbiblionum
+ % Expand \number\zbiblionum by hand.
+ \edef \znext {\noexpand\zbibitemb[\number\zbiblionum]}%
+ \fi
+ \znext}
+
+\def \zbibitemb[#1]{% [label]
+ \zbibtoksa = {#1}%
+ \futurelet\znext \zbibitemc}
+
+\def \zbibitemc {%
+ \if \tokeqlp{\znext}{[}%
+ \let \znext = \zbibitemd
+ \else
+ \def \znext {\zbibitemd[???]}%
+ \fi
+ \znext}
+
+\def \zbibitemd[#1]{% [author]
+ \zbibtoksb = {#1}%
+ \futurelet\znext \zbibiteme}
+
+\def \zbibiteme {%
+ \if \tokeqlp{\znext}{[}%
+ \let \znext = \zbibitemf
+ \else
+ \def \znext {\zbibitemf[???]}%
+ \fi
+ \znext}
+
+\def \zbibitemf[#1]#2{% [year]{tag}
+ \zbibtoksc = {#1}%
+ \bibitemtag = {#2}%
+ \item{\the\zbibtoksa}%
+ \if \PDFhyperlinks \PDFmark{T:#2}\fi
+ \if \notp{\emptyargp{#2}}%
+ \edef \znext{\noexpand\xref{bib}{\noexpand\folio}
+ {???}
+ {{\the\zbibtoksa}{\the\zbibtoksb}{\the\zbibtoksc}}
+ {#2}}%
+ \znext
+ \if \citeself \nocite{#2}\fi
+ \fi
+ \if \indexcites
+ \edef \znext {\noexpand\xbiblio1{\the\zbibtoksb}}%
+ \znext
+ \fi
+ \ignorespaces}
+
+% Bibliography Citation Page List
+% ------------ -------- ---- ----
+
+
+\setflag \zcitexrefsloaded = \false
+
+
+% If this macro is specified as the \endpartext of a bibliography
+% list, it will append a list of the citation pages to each entry.
+
+\def \citepagelist #1{% {button?}
+ \if \notp{\zcitexrefsloaded}%
+ \mapxrefcites{\zbibcitelist}%
+ \global\setflag \zcitexrefsloaded = \true
+ \fi
+ \setflag \zbibfirstpage = \true
+ \def \zbibprevpage {}%
+ \withname\maplistlf {\=citetag:\the\bibitemtag}
+ {\zbibcitepage{##1}{#1}}}
+
+\def \zbibcitelist #1#2{% {page}{tag}
+ \if \withname\undefinedp {\=citetag:#2}%
+ \withname\setlist {\=citetag:#2}={}%
+ \fi
+ \withname\appendlf {\=citetag:#2}{#1}}
+
+\def \zbibcitepage #1#2{% {page}{button?}
+ \stringeql{\zsamepage}{#1}{\zbibprevpage}%
+ \if \notp{\zsamepage}%
+ \if \notp{\emptydefp{\zbibprevpage}},\space \fi
+ \if #2%
+ \pagebutton{#1}{#1}%
+ \else
+ #1%
+ \fi
+ \def \zbibprevpage {#1}%
+ \fi}
diff --git a/macros/plain/contrib/zztex/tex/zzblock.tex b/macros/plain/contrib/zztex/tex/zzblock.tex
new file mode 100644
index 0000000000..989bb4363b
--- /dev/null
+++ b/macros/plain/contrib/zztex/tex/zzblock.tex
@@ -0,0 +1,327 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% Module: ZzTeX Blocks
+%
+% Synopsis: This module provides facilities for defining and creating
+% element blocks.
+%
+% Author: Paul C. Anagnostopoulos
+% Created: 23 August 1989
+%
+% Copyright 1989--2020 by Paul C. Anagnostopoulos
+% under The MIT License (opensource.org/licenses/MIT)
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% Block Definition
+% ----- ----------
+
+
+\setlist \zblocklist = {}
+
+\def \defineblock #1#2#3#4{% {\name}{\endname}{snap?}{redefine}
+ \if \emptyargp{#4}%
+ \withname\definecount{#1depth}{0}%
+ \withname\definecount{#1number}{0}%
+ \withname\definetoks{#1comptext}%
+ \withname\gdef{#1varinit}{}%
+ \if #3\withname\declaresnapitem{#1number}\fi
+ \append{#1}{\zblocklist}%
+ \fi}
+
+\def \resetinvcontext #1{% {\name}
+ \zdeclareeveryvcontext{\zblockvcontext{#1}}}
+
+\def \zblockvcontext #1{% {\name}
+ \zsavevcontext{\name{#1depth}=\the\name{#1depth}%
+ \name{#1number}=\the\name{#1number}%
+ \name{#1comptext}={\the\name{#1comptext}}}%
+ \global\name{#1depth}= 0\relax
+ \global\name{#1number}= 0\relax}
+
+% Block Utilities
+% ----- ---------
+
+
+\defineskip{\enclosingbaselineskip}{0pt}
+\defineskip{\enclosingleftss}{0pt}
+\definedimen{\enclosingparindent}{0pt}
+\definedimen{\enclosingparrag}{0pt}
+\defineskip{\enclosingparskip}{0pt}
+\defineskip{\enclosingrightss}{0pt}
+
+
+\def \beginblockscope #1{%
+ \begingroup
+ \zpushblock{#1}%
+ \enclosingbaselineskip = \baselineskip
+ \enclosingleftss = \leftskip
+ \tdimena = \leftskip
+ \advance \enclosingleftss by -\tdimena
+ \enclosingparindent = \parindent
+ \enclosingparrag = \parrag
+ \enclosingparskip = \parskip
+ \enclosingrightss = \rightskip
+ \tdimena = \rightskip
+ \advance \enclosingrightss by -\tdimena}
+
+\def \endblockscope #1{%
+ \zpopblock{#1}%
+ \endgroup}
+
+\def \processdesign #1#2{% {\block}{type etc.}
+ \zprocessvariant{#1}%
+ \resetnumber = {}%
+ \if \definedp{#1#2design}%
+ \name{#1#2design}\relax % \relax terminates numbers and such.
+ \else
+ \error{nodesign}{No design has been defined for the `\string#1#2' block}%
+ \fi
+ \zprocesswith
+ {\globaldefs = 1 \the\resetnumber}}
+
+\def \inblockp #1{% {\block-name}
+ \if \posp{\name{#1depth}}\true \else \false \fi}
+
+\def \setcomptext #1{% {\xxxcomptext}
+ \edef \znext {\comptextformat}%
+ #1= \expandafter{\znext}}%
+
+\def \blockmustbein #1#2{% {\inner}{\outer}
+ \if \zerop{\name{#2depth}}%
+ \error{blkmustnest}{A `\string#1' must be nested in a `\string#2'}%
+ \fi}
+
+\def \blockcantbein #1#2{% {\inner}{\outer}
+ \if \posp{\name{#2depth}}%
+ \error{blkcantnest}
+ {A `\string#1' cannot be nested inside a `\string#2'}%
+ \fi}
+
+\def \closeifinblock #1#2{% {\block}{\endblock}
+ \if \inblockp{#1}#2\fi}
+
+% Block Stack
+% ----- -----
+
+
+\setlist \zblockstack = {}
+\setlist \zlinestack = {}
+
+\def \zpushblock #1{%
+ \push{#1}{\zblockstack}%
+ \edef \znext {\noexpand\push{\the\inputlineno}}%
+ \znext{\zlinestack}}
+
+\def \zpopblock #1{%
+ \pop{\zblk}{\zblockstack}%
+ \pop{\zline}{\zlinestack}%
+ \stringeql{\znext}{\zblk}{#1}%
+ \if \notp{\znext}%
+ \error{blkinvnest}{The `\string\end#1' command does not match the
+ `\zblk' block that was started on line \zline}%
+ \fi}
+
+\def \zemptyblockstackp {\emptylistp{\zblockstack}}
+
+% Block Variants
+% ----- --------
+
+
+\def \definevariant #1#2#3{% {\block}{\style}{\modifier0,\modifier1,...}
+ \if \emptyargp{#3}%
+ \error{varmod}{Between 1 and 8 modifier commands must be specified}%
+ \fi
+ \withname\definecount{#2variant}{0}%
+ \withname\xdef{#1varinit}{\name{#1varinit}\name{#2variant}=0}%
+ {\tcounta = 0
+ \zdefvarpre #2#3,\zmark
+ \if \gtrp{\tcounta}{8}%
+ \error{varmod}{Between 1 and 8 modifier commands must be specified}%
+ \fi
+ \ztoksa = \expandaftertwice{\name{\zvarcase\lcromannumeral\tcounta}}%
+ \edef \znext {\global\let \name{#2varcase}=\the\ztoksa}%
+ \znext}}
+
+\def \zdefvarpre #1#2,#3\zmark{% \style\modifier,\modifier,...,\zmark
+ \xdef #2{\noexpand\variant{\name{#1variant}=\the\tcounta}}%
+ \increment \tcounta
+ \if \notp{\emptyargp{#3}}\zdefvarpre #1#3\zmark \fi}
+
+\gdef \zvariant {} % Holds \stylevariant assignments.
+
+\def \variant #1{% {\stylevariant assignment}
+ {\ztoksa = \expandafter{\zvariant}%
+ \ztoksb = {#1}%
+ \xdef \zvariant {\the\ztoksa \the\ztoksb}}%
+ \ignorespaces}
+
+\def \zprocessvariant #1{% {\block}
+ \name{#1varinit}%
+ \zvariant \relax % \relax terminates numbers and such.
+ \gdef \zvariant {}}
+
+\def \varcase #1{% \style
+ \name{#1varcase}#1}
+
+\long\def \zvarcasei #1#2{% \style {var1 code}
+ \ifcase \name{#1variant}#2\else\zbadvar\fi\relax}
+\long\def \zvarcaseii #1#2#3{% \style {var1 code}{var2 code}
+ \ifcase \name{#1variant}#2\or#3\else\zbadvar\fi\relax}
+\long\def \zvarcaseiii #1#2#3#4{%
+ \ifcase \name{#1variant}#2\or#3\or#4\else\zbadvar\fi\relax}
+\long\def \zvarcaseiv #1#2#3#4#5{%
+ \ifcase \name{#1variant}#2\or#3\or#4\or#5\else\zbadvar\fi\relax}
+\long\def \zvarcasev #1#2#3#4#5#6{%
+ \ifcase \name{#1variant}#2\or#3\or#4\or#5\or#6\else\zbadvar\fi\relax}
+\long\def \zvarcasevi #1#2#3#4#5#6#7{%
+ \ifcase \name{#1variant}#2\or#3\or#4\or#5\or#6\or#7\else\zbadvar\fi\relax}
+\long\def \zvarcasevii #1#2#3#4#5#6#7#8{%
+ \ifcase \name{#1variant}#2\or#3\or#4\or#5\or#6\or#7\or#8\else\zbadvar\fi\relax}
+\long\def \zvarcaseviii #1#2#3#4#5#6#7#8#9{%
+ \ifcase\name{#1variant}#2\or#3\or#4\or#5\or#6\or#7\or#8\or#9\else\zbadvar\fi\relax}
+
+\def \setvariant #1{% \modifier
+ #1%
+ \zvariant \relax
+ \gdef \zvariant {}}
+
+\def \zbadvar {%
+ \zzerror{Invalid value for variant}}
+
+% Block Options
+% ----- -------
+
+
+\gdef \zwith {} % Holds \with parameters.
+
+
+%~ The |\with| modifier can be used to modify specific design
+%~ parameters for the following block. It only makes sense
+%~ preceding block commands. Sometimes it is used with parameters
+%~ that are specifically intended for |\with|:
+%~ \with{\itemnumber=4} \list{number}
+%~ Other times it is used with a parameter that needs to be
+%~ changed for one particular block.
+%~ \with{\advance\belowskip by -8pt} \float{figure}
+%~ Again, be careful to use |\with| only on block commands.
+
+\long\def \with #1{% {parameter-assignments} %^modifier
+ {\ztoksa = \expandafter{\zwith}%
+ \ztoksb = {#1}%
+ \xdef \zwith {\the\ztoksa \the\ztoksb}}%
+ \ignorespaces}
+
+\def \zprocesswith {%
+ \zwith \relax % \relax terminates numbers and such.
+ \gdef \zwith {}}
+
+%~ This block modifier forces a page break above the block.
+
+\def \breakabove {% %^modifier
+ \with{\abovepenalty=\breakalways}}
+
+%~ This block modifier forces a page break below the block.
+
+\def \breakbelow {% %^modifier
+ \with{\belowpenalty=\breakalways}}
+
+% Common Design Parameters
+% ------ ------ ----------
+
+
+% These design parameters are used by a variety of ZZTeX's blocks, so
+% they are defined here.
+
+% Integer parameters:
+
+\definecount{\abovepenalty}{0} % Penalty above block.
+\definecount{\authorlevel}{0} % Author ToC entry level.
+\definecount{\belowpenalty}{0} % Penalty below block.
+\definecount{\continue}{0} % Block is continued (bit 0) and/or continuation (bit 1).
+\definecount{\difficulty}{0} % Level of difficulty of the block.
+
+% Flag parameters:
+
+\setflag \allowbreaks = \false % Allow page breaks in block?
+\setflag \allowintoc = \false % Allow section in ToC?
+
+% Dimension parameters:
+
+\definedimen{\height}{0pt} % Height of text.
+\definedimen{\ruleshift}{0pt} % Horizontal shift for rule.
+\definedimen{\ruleheight}{0pt} % Height (thickness) of rule.
+\definedimen{\rulewidth}{0pt} % Width of rule.
+\definedimen{\topadjust}{\mindimen} % Adjustment for head at top of page.
+\definedimen{\vshift}{0pt} % Vertical shift.
+\definedimen{\width}{0pt} % Width of text.
+
+% Skip (glue) parameters:
+
+\defineskip{\aboveskip}{0pt} % Base/base skip above block.
+\defineskip{\belowskip}{0pt} % Base/base skip below block.
+\defineskip{\columngutter}{0pt} % Width of gutter between columns.
+\defineskip{\interrowskip}{0pt} % Extra space between rows.
+\defineskip{\leftindent}{0pt} % Left indentation glue.
+\defineskip{\numbersink}{0pt} % Sinkage to section number, or
+\defineskip{\numberskip}{0pt} % Space b/b to section number.
+\defineskip{\parhang}{0pt} % Hanging indent for paragraph.
+\defineskip{\rightindent}{0pt} % Right indentation glue.
+\defineskip{\ruleskip}{0pt} % Vskip for rule.
+\defineskip{\textsink}{0pt} % Vsink for text.
+\defineskip{\textskip}{0pt} % Base/base skip for text.
+\defineskip{\titlesink}{0pt} % Sinkage to section title, or
+\defineskip{\titleskip}{0pt} % Space b/b to section title.
+
+% Token list parameters:
+
+\definetoks{\authortext} % Part/chapter author text.
+\definetoks{\bodyfont} % Font for body of block.
+\definetoks{\divisions} % List of division names.
+\definetoks{\numberfont} % Font for block number.
+\definetoks{\numberwordfont} % Font for block word like "chapter".
+\definetoks{\openertext} % Part/chapter opener text.
+\definetoks{\position} % Position of the block.
+\definetoks{\resetnumber} % List of sequence numbers to reset.
+\definetoks{\rulecolor} % Color of a rule.
+\definetoks{\runners} % Running head/foot macros.
+\definetoks{\style} % Heading style.
+\definetoks{\textcolor} % Color of text.
+\definetoks{\titlefont} % Font for title.
+
+% Macro parameters:
+
+\def \numberformat #1{} % {code} %~ Formatter for block number.
+\def \paging {} % {code} %~ Page control commands.
+\def \providemark #1{} % {code} %~ Provide marks for the block.
+\def \titleformat {} % {code} %~ Formatter for title.
+
+% The \continue Parameter
+% --- --------- ---------
+
+
+% The \continue parameter is set as follows:
+% 0: neither continued nor continuation
+% 1: continued
+% 2: continuation
+% 3: both continuation and continued
+
+
+\def \continuedp {\oddp{\continue}}
+
+\def \continuationp {\gtrp{\continue}{1}}
+
+\def \zsetcontinue {%
+ \if \andp{\zerop{\continue}}{\continuation}%
+ \continue = 2\relax
+ \fi}
+
+% Break Element
+% ----- -------
+
+
+\long\def \breakelement #1{%
+ \global\setflag \zinpar = {\hmodep}%
+ \if \zinpar \flushendpar \fi
+ #1%
+ \if \zinpar \noindent \ignorespaces \fi} \ No newline at end of file
diff --git a/macros/plain/contrib/zztex/tex/zzcmmath.tex b/macros/plain/contrib/zztex/tex/zzcmmath.tex
new file mode 100644
index 0000000000..a7c3f9f24b
--- /dev/null
+++ b/macros/plain/contrib/zztex/tex/zzcmmath.tex
@@ -0,0 +1,15 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% Module: Computer Modern math font support
+%
+% Copyright 1989--2020 by Paul C. Anagnostopoulos
+% under The MIT License (opensource.org/licenses/MIT)
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+% Not really much to do.
+
+\setstyleskewchar{\mit}{"7F}
+\setstyleskewchar{\msy}{"30}
+
diff --git a/macros/plain/contrib/zztex/tex/zzcomenc.tex b/macros/plain/contrib/zztex/tex/zzcomenc.tex
new file mode 100644
index 0000000000..4fecdcdfeb
--- /dev/null
+++ b/macros/plain/contrib/zztex/tex/zzcomenc.tex
@@ -0,0 +1,153 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% Module: Redefinitions for Common Encoding
+%
+% Copyright 1989--2020 by Paul C. Anagnostopoulos
+% under The MIT License (opensource.org/licenses/MIT)
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+% Redefine accents.
+
+\def \"#1{{\accent 8 #1}} %~ Umlaut accent. %^accent
+
+\def \.#1{{\accent 11 #1}} %~ Dot accent. %^accent
+
+\def \H #1{{\accent 12 #1}} %~ Long Hungarian umlaut accent. %^accent
+
+\def \^#1{{\accent 7 #1}} %~ Circumflex accent. %^accent
+
+\def \g #1{% %~ Ogonek accent. %^accent
+ \setbox \zboxa = \hbox{#1}%
+ \if \dimeqlp{\ht\zboxa}{1ex}%
+ \accent 14 #1%
+ \else
+ {\ooalign{\hidewidth \char 14 \hidewidth \cr
+ \unhbox \zboxa}}%
+ \fi}
+
+\def \~#1{{\accent 15 #1}} %~ Tilde accent. %^accent
+
+
+% Redefine standard ASCII characters.
+
+\def \udquote {% %~ Undirected double quote. %^named_char
+ \ensurepar
+ \char "22\relax}
+
+\def \dollar {% %~ Dollar sign. %^named_char
+ \zprehyph{\dollarhyph}%
+ \char "24\relax
+ \zposthyph{\dollarhyph}}
+
+\let \$ = \dollar
+
+\def \less {% %~ Less-than sign. %^named_char
+ \ensurepar
+ \char "3C\relax}
+
+\let \< = \relax
+
+\def \greater {% %~ Greater-than sign. %^named_char
+ \ensurepar
+ \char "3E\relax}
+
+\let \> = \relax
+
+\def \backslash {% %~ Backslash. %^named_char
+ \ensurepar
+ \if \mathmodep
+ \zmbackslash
+ \else
+ \char "5C\relax
+ \fi}
+
+\let \\ = \backslash
+
+\def \underscore {% %~ Underscore. %^named_char
+ \ensurepar
+ \zprehyph{\underscorehyph}%
+ \char "5F\relax
+ \zposthyph{\underscorehyph}}
+
+\let \_ = \underscore
+
+\def \lbrace {% %~ Left brace. %^named_char
+ \relax
+ \if \mathmodep
+ \zmlbrace
+ \else
+ \char "7B\relax
+ \fi}
+
+\let \{ = \lbrace
+
+\def \verticalbar {% %~ Vertical bar. %^named_char
+ \ensurepar
+ \char "7C\relax}
+
+\def \rbrace {% %~ Right brace. %^named_char
+ \relax
+ \if \mathmodep
+ \zmrbrace
+ \else
+ \char "7D\relax
+ \fi}
+
+\let \} = \rbrace
+
+
+% Define additional special characters.
+
+\def \specialchar #1#2{% {text-char}{math-char}
+ \ensurepar
+ \if \mathmodep
+ \if \emptyargp{#2}%
+ \error{scinmath}{Cannot use that special character in math mode}%
+ \else
+ #2\relax
+ \fi
+ \else
+ #1\relax
+ \fi}
+
+% Decided not to make these two characters pseudo-ligatures.
+
+\def \exclamdown {\specialchar{\char 142}{}} %~ Upside-down exclamation.
+\def \questiondown {\specialchar{\char 143}{}} %~ Upside-down question mark.
+
+\def \bullet {\specialchar{\char 150}{\zmbullet}} %~ Bullet.
+\def \cent {\specialchar{\char 151}{}} %~ Cent sign.
+\let \cents = \cent
+\def \copyright {\specialchar{\char 152}{}} %~ Copyright symbol.
+\def \currency {\specialchar{\char 153}{}} %~ Currency symbol.
+\def \dagger {\specialchar{\char 154}{\zmdagger}} %~ Dagger.
+\def \ddagger {\specialchar{\char 155}{\zmddagger}}%~ Double dagger.
+\def \degree {\specialchar{\char 156}{^\circ}} %~ Degree sign.
+\let \degrees = \degree
+\def \Edh {\specialchar{\char 157}{}} %~ Uppercase Edh.
+\def \edh {\specialchar{\char 158}{}} %~ Lowercase edh.
+\def \euro {\specialchar{\char 159}{}} %~ Euro symbol.
+\def \florin {\specialchar{\char 160}{}} %~ Florin.
+\def \lguill {\specialchar{\char 161}{}} %~ Left guillemot.
+\def \rguill {\specialchar{\char 162}{}} %~ Right guillemot.
+\def \L {\specialchar{\char 163}{}} %~ Uppercase Polish L.
+\def \l {\specialchar{\char 164}{}} %~ Lowercase Polish l.
+\def \minus {\specialchar{\char 165}{}} %~ Minus sign.
+\def \P {\specialchar{\char 166}{}} %~ Paragraph symbol (pilcrow).
+\def \perthousand {\specialchar{\char 167}{}} %~ Per thousand symbol.
+\def \usquote {\specialchar{\char 168}{}} %~ Undirected single quote.
+\def \registered {\specialchar{$^\roman{\char 169}$}{}} %~ Registered symbol.
+\def \S {\specialchar{\char 170}{}} %~ Section sign.
+\def \SS {\specialchar{\char 170\kern -.1em\char 170}{}} %~ Double section sign.
+\def \sterling {\specialchar{\char 171}{}} %~ Pound sterling symbol.
+\def \Thorn {\specialchar{\char 172}{}} %~ Uppercase Thorn.
+\def \thorn {\specialchar{\char 173}{}} %~ Lowercase thorn.
+\def \trademark {\specialchar{$^\roman{\char 174}$}{}} %~ Trademark symbol.
+\def \yen {\specialchar{\char 175}{}} %~ Yen symbol.
+
+% Redefine a few math things.
+
+\definemathchar{\zmdagger}{\classbinop}{\rmfam}{9A}
+\definemathchar{\zmddagger}{\classbinop}{\rmfam}{9B}
diff --git a/macros/plain/contrib/zztex/tex/zzdiv.tex b/macros/plain/contrib/zztex/tex/zzdiv.tex
new file mode 100644
index 0000000000..509fd4910c
--- /dev/null
+++ b/macros/plain/contrib/zztex/tex/zzdiv.tex
@@ -0,0 +1,128 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% Module: ZzTeX Division Facilities
+%
+% Synopsis: This module contains the macros to support divisions, which
+% allow a book to be processed in pieces.
+%
+% Author: Paul C. Anagnostopoulos
+% Created: 24 September 1990
+%
+% Copyright 1989--2020 by Paul C. Anagnostopoulos
+% under The MIT License (opensource.org/licenses/MIT)
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% Divisions
+% ---------
+
+
+\def \zdivext {tex}
+
+\definetoks{\divisionname} % Name of current division.
+\definetoks{\zdivreq} % Divisions requested with \setdivisions.
+\zdivreq = {\all}
+\definetoks{\zdivset} % Divisions set.
+\setlist \zdivset = {}
+
+
+%~ This command is used in the book's root file to specify
+%~ the list of divisions that should be processed by ZzTeX.
+%~ All other divisions are not processed. If the command
+%~ does not appear in the root file, all divisions are processed.
+
+\def \setdivisions #1{% {division,...}
+ \if \emptyargp{#1}%
+ \warning{nodivs}{The \noexpand\setdivisions command does not specify any divisions}
+ \else
+ \global\zdivreq = {#1}%
+ \fi}
+
+%~ This command is used in the book's root file to specify the
+%~ name of a book division file (e.g., |chap01|, |appa|). The order
+%~ of these commands determines the order of the divisions.
+
+\def \division #1{% {division}
+ \global\divisionname = {#1}%
+ \edef \znext {\noexpand\inclusionlist\noexpand\zset{#1}{\the\zdivreq}}%
+ \znext
+ \if \zset
+ \remark{Starting division `\the\divisionname'.}%
+ \push{#1}{\zdivset}%
+ \freshpage{\short\floats\any}%
+ \setcolumnnumber{1}%
+ \zxdivinit{#1}{\true}%
+ \zindexdivinit{#1}%
+ \zmndivinit
+ \zpndivinit
+ \zframedivinit
+ \zmrdivinit
+ \zfltdivinit
+ \include{#1.\zdivext}%
+ \endgraf
+ \freshpage{\short\floats\any}%
+ \zortahdivfinal
+ \zindexdivfinal
+ \zxdivfinal{#1}%
+ \else
+ \zxdivinit{#1}{\false}%
+ {\globaldefs = 1 \name{\=zS:#1}}% % Invoke snapshot.
+ \fi
+ \global\divisionname = \expandafter{\jobname}}
+
+% This macro is invoked at the end of the document.
+
+\def \zdivmsg {%
+ \edef \znext {\the\zdivreq}%
+ \edef \znextfirst {\expandafter\zdivmsga \znext\zmark}%
+ \if \tokeqlp{\znext}{\zallname}%
+ \remark{The entire book was processed.}%
+ \else\if \tokeqlp{\znextfirst}{\zallbutname}%
+ \relax
+ \else
+ \commalist{\zreqlist}{\the\zdivreq}%
+ \maplist{\zdivmsgb{##1}}{\zreqlist}%
+ \fi\fi}
+
+\def \zdivmsga #1#2\zmark{#1}
+
+\def \zdivmsgb #1{%
+ \member{\zexists}{#1}{\zdivset}%
+ \if \notp{\zexists}%
+ \warning{divnotexist}{The requested division `#1' does not exist}%
+ \fi}
+
+% Division Snapshots
+% -------- ---------
+
+
+\setlist \zsnaplist = {} % List of registers to be snapshot.
+
+
+\def \declaresnapitem #1{% {\name}
+ \append{#1}{\zsnaplist}}
+
+
+\def \ztakesnap {%
+ \let \zmodesave = \xrefmode
+ \let \xrefmode = \xrefsnapmode
+ \def \znext {}%
+ \maplist{\zsnapone{##1}}{\zsnaplist}%
+ \ztoksa = \expandafter{\znext}%
+ \edef \znext {\noexpand\xref{snap}{\noexpand\folio}{}%
+ {\the\ztoksa}{\the\divisionname}}%
+ \znext
+ \let \xrefmode = \zmodesave}
+
+\def \zsnapone #1{% {\register}
+ \ztoksa = \expandafter{\znext}%
+ \edef \znext {\the\ztoksa \noexpand#1\the#1}}
+
+
+% Store division snapshot information in a special name in the tag namespace.
+
+\def \xrefsnap #1#2#3#4{% {}{}{code}{division}
+ \ifnum \xrefmode=\xrefloadtagmode
+ \if \undefinedp{\=zS:#4}\withname{\gdef}{\=zS:#4}{}\fi
+ \withname\xdef{\=zS:#4}{\name{\=zS:#4}#3}%
+ \fi} \ No newline at end of file
diff --git a/macros/plain/contrib/zztex/tex/zzdoc.tex b/macros/plain/contrib/zztex/tex/zzdoc.tex
new file mode 100644
index 0000000000..072436a43a
--- /dev/null
+++ b/macros/plain/contrib/zztex/tex/zzdoc.tex
@@ -0,0 +1,500 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% Module: ZzTeX Document Facilities
+%
+% Synopsis:
+%
+% Author: Paul C. Anagnostopoulos
+% Created: 9 September 1989
+%
+% Copyright 1989--2020 by Paul C. Anagnostopoulos
+% under The MIT License (opensource.org/licenses/MIT)
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% Loading Design Files
+% ------- ------ -----
+
+
+\def \bookauthor {}
+\def \booktitle {}
+\def \bookpublisher {}
+\def \bookISBN {}
+
+
+\def \loaddesign #1{% {file-list}
+ \zdtinit
+ \zloadinifile
+ \global\divisionname = \expandafter{\jobname}%
+ \setfoliostyle{\arabic}% % Initialize various options that
+ \setsentencespacing{\false}% $ might be set in the design file.
+ \setmathspaces{4mu plus .4mu minus .75mu}
+ {4mu plus .4mu minus .75mu}
+ {4mu plus .4mu minus .75mu}%
+ \protectcitecommands
+ \commalist{\zdeslist}{#1}%
+ \maplist{\zinputdes{##1}}{\zdeslist}%
+ \textsize\rm % In case \documentdesign resets
+ % \normallineskip[limit].
+ \if \DVIWindorules \setflag \DVIWindoinuse = \true \fi %%% Temporary.
+ \if \newbiblio \input zzbiblio \else \input zzbibtex \fi
+ \if \rangep{\newmath}{1}{2}\input zznewmath\relax \fi
+ \if \newrunners \input zzrunner\relax \fi
+ \if \zerop{\tabularversion}%
+ \tabularversion = \if \newtabular 2\else 1\fi\relax
+ \fi
+ \if \neqlp{\tabularversion}{3}\input zztabularv\the\tabularversion\relax \fi
+ \if \newtitleadjustment \input zzttladj\relax \fi}
+
+\def \zinputdes #1{% {design-file}
+ \checkfile{\znext}{#1.zzd}%
+ \if \znext
+ \input #1.zzd\relax
+ \else
+ \error{nodesfile}{The design file `#1.zzd' is missing}
+ \zend
+ \fi
+ \if \orp{\hmodep}{\posp{\pagetotal}}
+ \error{desjunk}
+ {The design file `#1.zzd' has some spurious junk in it}
+ \fi
+ \textsize\rm % So \documentdesign macro can use it.
+ \documentdesign}
+
+\def \announcedesign #1{% {title}
+ \remark{Loading design file `#1'._}}
+
+\def \bookdata #1#2#3#4{% {author}{title}{publisher}{ISBN}
+ \gdef \bookauthor {#1}%
+ \gdef \booktitle {#2}%
+ \gdef \bookpublisher {#3}%
+ \gdef \bookISBN {#4}}
+
+%~ Deprecated in favor of |\bookdata|.
+
+\def \bookinfo #1#2#3{% {author}{title}{publisher}
+ \gdef \bookauthor {#1}%
+ \gdef \booktitle {#2}%
+ \gdef \bookpublisher {#3}}
+
+\def \commonencoding {%
+ \input zzcomenc\relax
+ \global\setflag \zcommonencoding = \true}
+
+\def \protectcitecommands {%
+ \let \cite = \citeleterror
+ \let \citeauthr = \citeleterror
+ \let \citeyear = \citeleterror
+ \let \nocite = \citeleterror}
+
+\def \citeleterror {%
+ \error{citelet}{Cannot use \noexpand\let to define \noexpand\cite commands}}
+
+% Design Alternatives
+% ------ ------------
+
+
+% Design alternatives are deprecated.
+
+\def \designalternative #1#2{% {\name}{choice}
+ \withname\gdef{\=zA:\string#1}{#2}}
+
+\def \definedesignalternative #1#2#3{% {\name}{required?}{choice1,...}
+ \definecount{#1}{-1}%
+ \if \undefinedp{\=zA:\string#1}%
+ \if #2%
+ \error{altreq}{The design alternative `\string#1' must be specified}%
+ \else
+ \zdefalt{#1}#3,\zmark
+ \fi
+ \fi
+ \commalist{\zaltlist}{#3}%
+ \tcounta = -1\relax
+ \maplist{\zcompalt{#1}{##1}}{\zaltlist}%
+ \if \negp{#1}%
+ \error{altinv}{The design alternative `\string#1' is invalid}%
+ \fi}
+
+\def \zdefalt #1#2,#3\zmark{% {\name}choice1,...\zmark
+ \designalternative{#1}{#2}}
+
+\def \zcompalt #1#2{% {\name}{choice}
+ \increment \tcounta
+ \stringeql{\znext}{\name{\=zA:\string#1}}{#2}%
+ \if \znext \global#1 = \tcounta \fi \relax}
+
+\let \altcase = \ifcase
+
+% Document Parameters
+% -------- ----------
+
+
+% The following PDF document information options are available.
+
+\chardef \PDFinfodefault = 0
+\chardef \PDFinfofull = 1
+\chardef \PDFinfocomp = 2
+\chardef \PDFinfonone = 3
+
+
+% Integer parameters:
+
+\adjdemerits = 10000 % Adjacent incompatible lines.
+\binoppenalty = 700 % Line break after binary operator.
+%\brokenpenalty = 0 % See \even and \oddbrokenpenalty.
+\clubpenalty = 500 % Club line at bottom of page.
+\defaulthyphenchar = `\- % Default hyphen character.
+\defaultskewchar = -1 % Default skew character.
+\delimiterfactor = 941 % Math delimiter size factor.
+\displaywidowpenalty = 500 % Widow line above math display.
+\definecount{\dollarhyph}{0} % 0: no hyphenation after dollar signs;
+ % 1: hyphenate after, but nowhere else;
+ % 2: hyphenate after and other places.
+\doublehyphendemerits = 80000 % Consecutive hyphenated lines.
+\errorcontextlines = 8 % Maximum error context line pairs.
+\definecount{\evenbrokenpenalty}{3000} % Column breaks after hyphenated
+ % line, but on same spread.
+\exhyphenpenalty = 0 % Line break after explicit hyphen.
+\finalhyphendemerits = 10000 % Penultimate hyphenated line.
+\hbadness = 1000 % Above which bad hboxes are shown.
+\hyphenpenalty = 50 % Line break after discretionary hyphen.
+\interlinepenalty = 0 % Between lines of a paragraph.
+\language = 0 % Current set of hyphenation rules.
+\lefthyphenmin = 2 % Shortest fragment at beginning of
+ % hyphenated word.
+\linepenalty = 10 % Increment at each line break.
+\definecount{\lineslong}{0} % Number of lines page can go long.
+\definecount{\linesperpage}{0} % Number of lines per page.
+\definecount{\linesshort}{0} % Number of lines page can go short.
+\definecount{\maxbottomcolumnfloats}{1} % Floats at column bottom.
+\definecount{\maxbottompagefloats}{1} % Floats at page bottom.
+\definecount{\maxtopcolumnfloats}{1} % Floats at column top.
+\definecount{\maxtoppagefloats}{1} % Floats at page top.
+\definecount{\mintextpercent}{10} % Percent of page that must have text.
+\newlinechar = -1 % Newline character for \write.
+\definecount{\newmath}{0} % Revision level of math---DEPRECATED.
+\definecount{\oddbrokenpenalty}{10000} % Spread breaks after
+ % hyphenated line.
+\definecount{\PDFinfo}{\PDFinfodefault} % Include document info in final PDF file.
+\pretolerance = 400 % Badness tolerated before hyphenation.
+\relpenalty = 500 % Line break after relation operator.
+\righthyphenmin = 3 % Shortest fragment at end of hypenated word.
+\definecount{\shrinkpercent}{10} % Percentage shrink is of nominal.
+\definecount{\stretchpercent}{25} % Percentage of the maximum stretch.
+\definecount{\tabularversion}{0} % Version of tabular facility.
+\tolerance = \pretolerance % Badness tolerated after hyphenation.
+\tracinglostchars = 1 % Positive to trace lost characters.
+\definecount{\tracingpagemakeup}{0} % Positive to trace page makeup.
+\tracingstats = 1 % Positive to trace memory statistics.
+\uchyph = 1 % Positive to hyphenate Capitalized words.
+\definecount{\underscorehyph}{1} % See \dollarhyph.
+\vbadness = 2000 % Above which bad vboxes are shown.
+\widowpenalty = 10000 % Widow line at top of page.
+\definecount{\xrefcites}{0} % Cross-reference \cite's:
+ % 0: no
+ % 1: simple xref entry
+ % 2: custom xref entry
+
+% Flag Parameters:
+
+\setflag \allowcolor = \true % Allow color specials?
+\setflag \allowreftitle = \false % Allow use of \reftitle?
+\setflag \baselinetoprules = \true % Rules at page top sit on baseline?
+\setflag \DVIWindoinuse = \false % Generate DVIWindo-specific goodies?
+\setflag \DVIWindorules = \false % Display page makeup rules? [deprecated]
+\setflag \forceepsbb = \false % Force reading of EPS bounding box?
+\setflag \indexcites = \false % \cite generates indexing command?
+\setflag \newbiblio = \false % Use new biblio facility?
+\setflag \newdots = \false % Use new \xdots commands?
+\setflag \newrunners = \false % Use new runners scheme?
+\setflag \newtabular = \false % Use new tabular module? [deprecated]
+\setflag \newtitleadjustment = \false % Use new title adjustment scheme?
+\setflag \PDFhyperlinks = \false % Generate PDF hyperlinks?
+\setflag \raggedbottom = \false % Ragged-bottom pages?
+\setflag \risingbottomfloats = \false % Bottom floats rise up on page?
+\setflag \risingfootnotes = \false % Footnotes rise up on page?
+\setflag \topdeltaadjustment = \false % Use \topdelta?
+\setflag \zcommonencoding = \false % Set with \commonencoding command.
+
+% Dimension Parameters:
+
+\boxmaxdepth = \maxdimen % Maximum depth of explicit vboxes.
+\delimitershortfall = 4pt % Maximum math delimiter shortfall.
+\emergencystretch = 4pt % Emergency stretchability of each line.
+\definedimen{\evenbleedshift}{0pt} % Bleed shift for versos.
+\definedimen{\eveninnermargin}{0pt} % Inner margin (gutter) for versos.
+\definedimen{\evenlefttextmargin}{0pt} % Left text margin for versos.
+\definedimen{\evenoutermargin}{0pt} % Outer margin for versos.
+\definedimen{\evenrighttextmargin}{0pt} % Right text margin for versos.
+\definedimen{\footerheight}{0pt} % Height of footer box.
+\definedimen{\headerheight}{0pt} % Height of running head.
+\definedimen{\headmargin}{0in} % Head (top) margin.
+\hfuzz = 0.33pt % Overrun before overfull hbox messages.
+\hoffset = 0pt % Overall horizontal offset.
+\zremovePlaindef \jot
+\definedimen{\jot}{3pt} % Increment for opening up math displays.
+\lineskiplimit = 0pt % Threshold where \lineskip is used
+ % instead of \baselineskip.
+\let \linewidth = \hsize % Alternate name for \hsize.
+\maxdepth = 4pt % Maximum depth of boxes on main pages.
+\zremovePlaindef \normallineskiplimit
+\definedimen{\normallineskiplimit}{0pt} % Normal line skip limit.
+\nulldelimiterspace = 1.2pt % Width of a null delimiter.
+\definedimen{\oddbleedshift}{0pt} % Bleed shift for rectos.
+\definedimen{\oddinnermargin}{0pt} % Inner margin (gutter) for rectos.
+\definedimen{\oddlefttextmargin}{0pt} % Left text margin for rectos.
+\definedimen{\oddoutermargin}{0pt} % Outer margin for rectos.
+\definedimen{\oddrighttextmargin}{0pt} % Right text margin for rectos.
+\overfullrule = 6pt % Width of rule appended to overfull boxes.
+\parindent = 0pt % Width of paragraph indent.
+\definedimen{\parrag}{0pt} % Raggedness of paragraph lines.
+\scriptspace = .25pt % Extra space after a sub/superscript.
+\splitmaxdepth = \maxdimen % Maximum depth of boxes on split pages.
+\definedimen{\standardbleed}{.125in} % Standard bleed required by press.
+\definedimen{\standardindent}{0pt} % Standard indentation amount.
+\definedimen{\textareaheight}{\mindimen}% Height of text area.
+\definedimen{\textmeasure}{0pc} % Width of text area.
+\let \textareawidth = \textmeasure
+\definedimen{\topdelta}{0pt} % \topskip - height(first line).
+\definedimen{\trimheight}{0in} % Trimmed paper height.
+\definedimen{\trimwidth}{0in} % Trimmed paper width.
+\definedimen{\trimplusbleedheight}{0in} % Trim plus bleed top and bottom.
+\definedimen{\trimplusbleedwidth}{0in} % Trim plus bleed both sides.
+\definedimen{\typeareaheight}{\mindimen}% Height of type area.
+\definedimen{\typeareawidth}{0pt} % Width of type area.
+\vfuzz = 0.5pt % Overrun before overfull vbox messages.
+\voffset = 0pt % Overall vertical offset.
+
+% Skip (glue) Parameters:
+
+\leftskip = 0pt % At left end of paragraph lines.
+\lineskip = 0pt % When \baselineskip isn't possible.
+\zremovePlaindef \normalbaselineskip
+\defineskip{\normalbaselineskip}{0pt} % Normal baseline distance.
+\zremovePlaindef \normallineskip
+\defineskip{\normallineskip}{0pt} % Normal line skip limit.
+\parfillskip = 0pt plus 1fil % Additional \rightskip at paragraph end.
+\parskip = 0pt % Above paragraphs.
+\rightskip = 0pt % At right end of lines.
+\spaceskip = 0pt % Between words (if nonzero).
+\splittopskip = 10pt % At top of split pages.
+\defineskip{\standardskip}{0pt} % Standard skip above/below elements.
+\topskip = \mindimen % At top of main pages.
+\xspaceskip = 0pt % Between sentences (if nonzero).
+
+% Muskip (mu glue) Parameters:
+
+\definemuskip{\fracbarhang}{0mu} % Fraction bar overhang.
+\thinmuskip = 0mu % Math space after punctuation.
+\medmuskip = 0mu % Math space around binary operators.
+\thickmuskip = 0mu % Math space around relational operators.
+
+% Token list parameters:
+
+\definetoks{\annotationfont} % Font for annotations (e.g., proof identification).
+\annotationfont = {cmssi10 at 7pt}
+\definetoks{\baselinemultiplier}% Multiplier for baselines.
+\baselinemultiplier = {1}
+\definetoks{\decimalpoint} % Decimal point character.
+\decimalpoint = {.}
+\definetoks{\PDFbuttoncolor} % Color of hyperlinked text.
+\definetoks{\matrixspread} % Baseline multiplier for matrices.
+\matrixspread = {1.0}
+
+% The following parameters are fixed and hidden from the user.
+
+\mathsurround = 0pt % Space around a math formula in text.
+
+% Parameter Calculation
+% --------- -----------
+
+
+\def \calculatetextareaheight #1{% {lines}
+ \relax
+ \if \dimnegp{\topskip}%
+ \error{misstopskip}{The value of \string\topskip must be set}%
+ \fi
+ {\global\linesperpage = #1\relax
+ \tcounta = #1\relax
+ \decrement \tcounta
+ \textareaheight = \the\tcounta\baselineskip
+ \global\advance \textareaheight by \topskip
+ \measurecapheight{\topdelta}%
+ \measureascenderheight{\tdimena}%
+ \if \dimgtrp{\tdimena}{\topdelta}\topdelta = \tdimena \fi
+ \advance \topdelta by -\topskip
+ \global\negate \topdelta}}
+
+\def \calculatetypeareaheight #1#2{% {head-height}{head-b/b}
+ \relax
+ \if \dimnegp{\textareaheight}%
+ \error{misstah}{The value of \string\textareaheight must be set}%
+ \fi
+ {\typeareaheight = \textareaheight
+ \advance \typeareaheight by -\topskip
+ \advance \typeareaheight by #1\relax
+ \advance \typeareaheight by #2\relax
+ \global\advance \typeareaheight by \footerheight
+ \headerheight = #1\relax
+ \advance \headerheight by #2\relax
+ \global\advance \headerheight by -\topskip}}
+
+\def \calculateoffsets #1#2{% {sheet-width}{sheet-height}
+ \relax
+ \if \andp{\dimposp{\trimwidth}}{\dimposp{\trimheight}}%
+ \hoffset = #1\relax
+ \advance \hoffset by -\trimwidth
+ \divide \hoffset by 2
+ \advance \hoffset by -1in
+ \voffset = #2\relax
+ \advance \voffset by -\trimheight
+ \divide \voffset by 2
+ \advance \voffset by -1in\relax
+ \else
+ \error{misstrim}{The values of \string\trimwidth and
+ \string\trimheight must be set}%
+ \fi}
+
+\def \calculatepdfoffsets #1#2#3{% {virtual-width}{virtual-height}{bleeds?}
+ \relax
+ \if \andp{\dimposp{\trimwidth}}{\dimposp{\trimheight}}%
+ \hoffset = -1in
+ \if #3\advance \hoffset by \standardbleed \fi
+ \calculate \voffset = {#2,-,\trimheight,-,1in}%
+ \if #3\advance \voffset by -\standardbleed \fi
+ \else
+ \error{misstrim}{The values of \string\trimwidth and
+ \string\trimheight must be set}%
+ \fi}
+
+\def \setskip #1=#2#3#4{% \parameter = {nominal}{max-stretch}{[shrink]}
+ \tdimena = #2\relax
+ \calculate \tdimenb = {#3,P,\stretchpercent}%
+ \if \emptyargp{#4}%
+ \calculate \tdimenc = {\tdimena,P,\shrinkpercent}%
+ \else
+ \tdimenc = #4\relax
+ \fi
+ #1 = \the\tdimena plus \the\tdimenb minus \the\tdimenc\relax}
+
+\def \fromtrim #1{% \setskip or \register
+ \if \tokeqlp{#1}{\setskip}%
+ \let \znext = \zfromtrima
+ \else
+ \def \zfromtrimreg {#1}%
+ \let \znext = \zfromtrimb
+ \fi
+ \znext}
+
+\def \zfromtrima #1=#2#3#4{%
+ \setskip #1={#2}{#3}{#4}%
+ \advance #1 by -\headmargin}
+
+\def \zfromtrimb {%
+ \afterassignment\zfromtrimc \zfromtrimreg}
+
+\def \zfromtrimc {%
+ \advance \zfromtrimreg by -\headmargin}
+
+% Document Block
+% -------- -----
+
+
+\def \document {%
+ % There is no point to embedding the entire document in a group.
+ % \documentdesign was already invoked by \loaddesign.
+ \zpushblock{document}%
+ \xdef \znext {%
+ \noexpand\definefont \noexpand\zannofont{\the\annotationfont}}
+ \znext
+ \zfontsummary{\false}%
+ \zopentfmlist
+ \zwritePDFinfo
+ \zpageinit
+ \zpushvcontext
+ \setparrag{\parrag}%
+ \zxrefinit
+ \zbiblioinit
+ \zindexinit
+ \zfloatinit
+ \setpagecolumns{}{1}{0pt}%
+ \if \definedp{\documentprolog}\documentprolog \fi}
+
+\def \enddocument {%
+ \endgraf
+ \if \definedp{\documentepilog}\documentepilog \fi
+ \closeanychapter
+ \closeanysection
+ \zpopblock{document}%
+ \freshpage{\short\floats\any}%
+ \zindexfinal
+ \zxreffinal
+%%% \zbibfinal
+ \zmissingartmsg
+ \ztagsummary
+ \zpopvcontext
+ \zlayoutsummary
+ \zfontsummary{\true}%
+ \zwritetfmlist
+ \if \posp{\tracingstats}\zregstats \fi
+ \zfeaturewarns
+ \ztodomsg
+ \zdivmsg
+ \zproofidfile
+ \zend}
+
+\def \zfeaturewarns {%
+ \messagenl{_}%
+ \if \zoverlayset
+ \remark{Overlays are present on each page.}%
+ \fi
+ \zproofident}
+
+\def \zproofident {%
+ \zproofidentline
+ \if \emptytoksp{\zproofid}%
+ \messagenl{| No proof identification.}%
+ \else
+ \messagenl{| \the\zproofid\space\space
+ \number\year/\number\month/\number\day\space
+ \formattime\space\space\space
+ \inicompositor}%
+ \fi
+ \zproofidentline}
+
+\def \zproofidentline {%
+ \messagenl{+-----------------------------------------------------------------------------_}}
+
+% Write PDF Document Information
+% ----- --- -------- -----------
+
+
+\def \zwritePDFinfo {%
+ \ifcase \PDFinfo
+ \relax
+ \or
+ \special{PDF: Title \booktitle}%
+ \special{PDF: Author \bookauthor}%
+ \special{PDF: Subject}%
+ \special{PDF: Keywords Publisher: \bookpublisher,
+ Compositor: \inicompositor}%
+ \or
+ \special{PDF: Title}%
+ \special{PDF: Author}%
+ \special{PDF: Subject}%
+ \special{PDF: Keywords Compositor: \inicompositor}%
+ \or
+ \special{PDF: Title}%
+ \special{PDF: Author}%
+ \special{PDF: Subject}%
+ \special{PDF: Keywords}%
+ \fi}
+
+% Disable \end
+% ------- ----
+
+
+\let \zend = \end
+
+\def \end {%
+ \error{noend}{Do not use the TeX \string\end\space command}}
diff --git a/macros/plain/contrib/zztex/tex/zzerror.tex b/macros/plain/contrib/zztex/tex/zzerror.tex
new file mode 100644
index 0000000000..693451b2c3
--- /dev/null
+++ b/macros/plain/contrib/zztex/tex/zzerror.tex
@@ -0,0 +1,123 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% Module: ZzTeX Error Handling
+%
+% Synopsis:
+%
+% Author: Paul C. Anagnostopoulos
+% Created: 13 August 1989
+%
+% Copyright 1989--2020 by Paul C. Anagnostopoulos
+% under The MIT License (opensource.org/licenses/MIT)
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% Remarks & Errors
+% ------- - ------
+
+
+\def \remark #1{% {text}
+ \messagenl{_ZzTeX: #1_}}
+
+\def \warning #1#2{% {help-id}{text}
+ \zsethelp{#1}%
+ \zerrmsg{warning}{#2}}
+
+\def \error #1#2{% {help-id}{text}
+ \zsethelp{#1}%
+ \zerrmsg{error}{#2}%
+ \remark{Continuing from an error may cause unpredictable results.}}
+
+\def \zzerror #1{% {text}
+ \zerrmsg{internal error}{#1}%
+ \remark{Continuing from an internal error will cause erroneous results.}}
+
+\def \zerrmsg #1#2{% {prefix}{text}
+ {\newlinechar = `\_%
+ \errmessage{ZzTeX #1: #2}}}
+
+%%%\def \zerrcontext #1{%
+%%% \listtop{\znext}{\zblockstack}%
+%%% \writelog{ZzTeX context: #1 \znext\space \the\typesizename
+%%% \the\typestyle \the\typeencoding.}}
+%%%
+%%%\def \context {%
+%%% \zerrcontext{???}%
+%%% \zend}
+
+% To-Do Facility
+% ----- --------
+
+
+\definecount{\ztodocount}{0}
+
+
+%~ The |\todo| command accepts a note that is stored in the composite
+%~ cross-reference file as a reminder of something that needs to
+%~ be done later. ZzExplore can display a list of the outstanding
+%~ to-dos.
+
+\long\def \todo #1{% {note}
+ \zwritetodo{#1}%
+ \ztodo #1\zmark
+ \global\increment \ztodocount}
+
+\long\def \ztodo #1#2\zmark{% {char1}{rest of message}
+ \if \codeeqlp{#1}{!}%
+ {\errorcontextlines = 0
+ \def \znext {#2}%
+ \zerrmsg{to-do}{\expandafter\zdefof \meaning\znext\zmark\space
+ [\the\divisionname]}}%
+ \else\if \codeeqlp{#1}{.}%
+ \def \znext {#2}%
+ \writelog{ZzTeX to-do: \expandafter\zdefof \meaning\znext\zmark\space
+ [\the\divisionname]}%
+ \else\if \codeeqlp{#1}{?}%
+ \def \znext {#2}%
+ \messagenl{_ZzTeX to-do: To come: \expandafter\zdefof \meaning\znext\zmark\space
+ [\the\divisionname]_}%
+ \if \DVIWindoinuse \colorspecial{ifview color push rgb 1 0 0}\fi
+ ???%
+ \if \DVIWindoinuse \colorspecial{ifview color pop}\fi
+ \else
+ \def \znext {#1#2}%
+ \messagenl{_ZzTeX to-do: \expandafter\zdefof \meaning\znext\zmark\space
+ [\the\divisionname]_}%
+ \fi\fi\fi}
+
+% Write a todo entry into the cross-reference file.
+
+\long\def \zwritetodo #1{% {message}
+ \zbeginhidewrite
+ \def \znext {#1}%
+ \edef \znext {\noexpand\xref{todo}{\noexpand\folio}{}
+ {\expandafter\zdefof \meaning\znext\zmark}
+ {\the\divisionname}}%
+ \znext
+ \zendhidewrite}
+
+% There is nothing to do with each entry in the cross-reference file
+% when it is loaded.
+
+\long\def \xreftodo #1#2#3#4{}
+
+% This macro is invoked at the end of the run.
+
+\def \ztodomsg {%
+ \if \posp{\ztodocount}%
+ \remark{Number of to-do reminders encountered: \the\ztodocount}%
+ \fi}
+
+
+% Help Text
+% ---- ----
+
+
+\def \zsethelp #1{%
+ \if \definedp{\=zH:#1}%
+ \global\errhelp = \expandafterthrice{\name{\=zH:#1}}%
+ \else
+ \global\errhelp = {No additional help is available.}%
+ \fi}
+
+
diff --git a/macros/plain/contrib/zztex/tex/zzfloat.tex b/macros/plain/contrib/zztex/tex/zzfloat.tex
new file mode 100644
index 0000000000..b6e3e08246
--- /dev/null
+++ b/macros/plain/contrib/zztex/tex/zzfloat.tex
@@ -0,0 +1,1164 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% Module: ZzTeX Float Facilities
+%
+% Synopsis: This module contains the float and caption blocks, as well as
+% all the code required to support the scheduling of floats.
+%
+% Notes: The broadside capability was implemented by Richard A. Wells and
+% integrated into ZzTeX on 9/7/94.
+%
+% Author: Richard A. Wells & Paul C. Anagnostopoulos
+% Created: 7 March 1990
+%
+% Copyright 1989--2020 by Paul C. Anagnostopoulos
+% under The MIT License (opensource.org/licenses/MIT)
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% Data Structures
+% ---- ----------
+
+
+\definecount{\zfltcount}{0}
+\def \zfloatfreeq {}
+\def \zfloatpendq {}
+
+
+\def \zdeffloat #1#2{% {\float}{\float-box}
+ \definebox{#2}%
+ \zfreefloat{#1}{#2}%
+ \global\increment \zfltcount}
+
+\def \zgetfloat #1{% {\float}
+ \if \emptydefp{\zfloatfreeq}%
+ \error{toomanyflt}
+ {More than `\the\zfltcount' floats remain for page makeup}%
+ \else
+ \pop{#1}{\zfloatfreeq}%
+ \fi}
+
+\def \zfreefloat #1#2{% {\float}{\float-box}
+ \gdef #1{\def \zcurfloatbox {#2}}%
+ \append{#1}{\zfloatfreeq}}
+
+\zdeffloat{\zflta}{\zfltboxa}
+\zdeffloat{\zfltb}{\zfltboxb}
+\zdeffloat{\zfltc}{\zfltboxc}
+\zdeffloat{\zfltd}{\zfltboxd}
+\zdeffloat{\zflte}{\zfltboxe}
+\zdeffloat{\zfltf}{\zfltboxf}
+\zdeffloat{\zfltg}{\zfltboxg}
+\zdeffloat{\zflth}{\zfltboxh}
+\zdeffloat{\zflti}{\zfltboxi}
+\zdeffloat{\zfltj}{\zfltboxj}
+\zdeffloat{\zfltk}{\zfltboxk}
+\zdeffloat{\zfltl}{\zfltboxl}
+\zdeffloat{\zfltm}{\zfltboxm}
+\zdeffloat{\zfltn}{\zfltboxn}
+\zdeffloat{\zflto}{\zfltboxo}
+\zdeffloat{\zfltp}{\zfltboxp}
+\zdeffloat{\zfltq}{\zfltboxq}
+\zdeffloat{\zfltr}{\zfltboxr}
+\zdeffloat{\zflts}{\zfltboxs}
+\zdeffloat{\zfltt}{\zfltboxt}
+\zdeffloat{\zfltu}{\zfltboxu}
+\zdeffloat{\zfltv}{\zfltboxv}
+\zdeffloat{\zfltw}{\zfltboxw}
+\zdeffloat{\zfltx}{\zfltboxx}
+\zdeffloat{\zflty}{\zfltboxy}
+\zdeffloat{\zfltz}{\zfltboxz}
+
+% There is an insert class for each of the two places where floats
+% can go.
+
+\defineinsert{\ztopcolinsert} % Floats at top of column.
+\count\ztopcolinsert = 1000
+\dimen\ztopcolinsert = \maxdimen
+\skip\ztopcolinsert = 0pt
+\defineinsert{\zbotcolinsert} % Floats at bottom of column.
+\count\zbotcolinsert = 1000
+\dimen\zbotcolinsert = \maxdimen
+\skip\zbotcolinsert = 0pt
+
+
+% We need a dimension register to capture box depths.
+
+\definedimen{\zfloatdp}{0pt}
+
+% Float Types
+% ----- -----
+
+
+\setlist \zfloattypelist = {}
+
+
+\def \definefloattype #1#2#3{% {type}{toc-level}{association}
+ \if \emptyargp{#3}%
+ \withname\definecount{\float#1number}{0}%
+ \withname\declaresnapitem{\float#1number}%
+ \else
+ \edef \znext {%
+ \global\withname\let{\float#1number}=\name{\float#3number}}%
+ \znext
+ \fi
+ \withname\gdef{\zflt#1lvl}{#2}%
+ \append{#1}{\zfloattypelist}}
+
+
+\def \resetfloatnumbers {%
+ \maplist{\global\name{\float##1number}=0\relax}{\zfloattypelist}}
+
+
+% Predefined float types (don't forget an index locator for each one).
+
+\definefloattype{algorithm}{101}{}
+\definefloattype{figure}{102}{}
+\definefloattype{table}{103}{}
+\definefloattype{listing}{104}{}
+\definefloattype{sidebar}{105}{}
+
+% Float Block
+% ----- -----
+
+
+\defineblock{\float}{\endfloat}{\false}{}
+
+%~block float Type
+% \aboveskip = glue % Space b/b above float.
+% \def \beginformat {...} % Beginning of float formatter.
+% \belowskip = glue % Space b/b below float.
+% \def \comptextformat {...} % Composite number text formatter.
+% \continue = integer % Continued or continuation.
+% \def \endformat {...} % End of float formatter.
+% \leftindent = dimen % Horizontal fudge for all floats.
+% \pageplacement = {...} % Overriding page placement.
+% \position = {...} % Position (see below).
+% \runners = {style} % Runners for a page of floats.
+% \topfloatfudge = dimen % Vertical fudge for topmost float.
+% \width = dimen % Explicit width for float.
+%~end
+
+\definetoks{\pageplacement}
+\definedimen{\topfloatfudge}{0pt}
+
+% These derived parameters are needed here and by \caption. They may
+% also be useful to the user.
+
+\definecount{\floatpage}{0}
+\definedimen{\floatshift}{0pt}
+\definedimen{\floatwidth}{0pt}
+
+\definecount{\zdivfltcounter}{0} % Count floats in each division.
+\definebox{\zfltbroadbox}
+
+
+% Floats are packaged up in a vbox using \vtop, so that the float box
+% has the same height as the first thing inside. This improves the
+% chances that a float at the top of a page will be positioned correctly.
+
+\def \float #1{% {type}
+ \if \undefinedp{\float#1number}%
+ \error{undefflt}{Float type `#1' has not been defined}%
+ \fi
+ \endgraf
+ \blockcantbein{\float}{\float}%
+ \blockcantbein{\float}{\multicolumn}%
+ \beginblockscope{float}%
+ \global\increment \floatdepth
+ \global\increment \zdivfltcounter
+ \whichpage{\floatpage}{zF:\the\divisionname-\the\zdivfltcounter}%
+ \def \beginformat {}% %~default soft
+ \continue = 0 %~default with
+ \def \comptextformat {}% %~default soft
+ \setflag \continuation = \false % Deprecated
+ \def \endformat {}% %~default soft
+ \leftindent = 0pt %~default soft
+ \pageplacement = {}% %~default with
+ \runners = {normal}% %~default soft
+ \zoldrunners{\normalheader\normalfooter}%
+ \width = \naturalwidth %~default soft
+ \processdesign{\float}{#1}%
+ \zsetcontinue % Handle old \continuation.
+ \if \notp{\continuationp}\global\withname\increment{\float#1number}\fi
+ \global\withname\floatnumber{\float#1number}%
+ \setcomptext{\floatcomptext}%
+ \def \zcurflttype {#1}%
+ \edef \zcurfltlvl {\name{\zflt\zcurflttype lvl}}%
+ \parindent = 0pt
+ \parrag = 0pt
+ \parskip = 0pt
+ \zparsefltpos{\the\position}%
+ \if \notp{\emptytoksp{\pageplacement}}%
+ \zparsefltpagepos{\the\pageplacement}%
+ \fi
+ \if \zfltposhere
+ \penalty \breakallowed % Synchronize main list.
+ \zparsefltpos{\the\position}% % Recalculate global stuff.
+ \if \notp{\emptytoksp{\pageplacement}}
+ \zparsefltpagepos{\the\pageplacement}%
+ \fi
+ \fi
+ \zcalcfltparams
+ \zgetfloat{\zcurfloat}%
+ \zcurfloat
+ \global\setbox \zcurfloatbox = \vtop \bgroup
+ \zpushvcontext
+ \setindentation{0pt}{0pt}%
+ \settextwidth{\floatwidth}%
+ \settaginfo{\the\floatcomptext}{}% % Set tag info without title.
+ \setsubtagnumber{0}%
+ \beginformat}
+
+\def \endfloat {%
+ \endgraf
+ \endformat
+ \global\zfloatdp = \prevdepth
+ \tagpageonly{\uniquetag{zF}{\the\zdivfltcounter}}%
+ \zpopvcontext
+ \egroup % \vtop
+ \expandafter\xdef \zcurfloat {%
+ \def \noexpand\zcurfloatid {\zcurflttype\space \the\floatnumber}%
+ \def \noexpand\zcurfloatbox {\zcurfloatbox}%
+ \zfloatdp = \the\zfloatdp
+ \aboveskip = \the\aboveskip
+ \belowskip = \the\belowskip
+ \leftindent = \the\leftindent
+ \position = {\the\position}%
+ \pageplacement = {\the\pageplacement}%
+ \runners = {\the\runners}%
+ \floatshift = \the\floatshift
+ \topfloatfudge = \the\topfloatfudge}%
+ \expandafter\append \zcurfloat{\zfloatpendq}%
+ \zschedulefloats{\znext}{\false}{\false}%
+ \if \gtrp{\znext}{99}%
+ \zfltpage{\zpenfloatpage}%
+ \fi
+ \global\decrement \floatdepth
+ \endblockscope{float}}
+
+%~ This |\float| modifier forces an alone float.
+
+\def \alonefloat {% %^modifier
+ \with{\pageplacement={\alone}}}
+
+%~ This |\float| modifier forces a bottom float.
+
+\def \bottomfloat {% %^modifier
+ \with{\pageplacement={\bottom}}}
+
+%~ This |\float| modifier forces a broadside float.
+
+\def \broadsidefloat {% %^modifier
+ \with{\pageplacement={\broadside}}}
+
+%~ This |\float| modifier forces a here float.
+
+\def \herefloat {% %^modifier
+ \with{\pageplacement={\here}}}
+
+%~ This |\float| modifier forces a separate float.
+
+\def \separatefloat {% %^modifier
+ \with{\pageplacement={\separate}}}
+
+%~ This |\float| modifier allows the float to occupy the
+%~ running head area. Any running head is deleted.
+
+\def \userharea {% %^modifier
+ \with{\runners={blind}%
+ \advance \topfloatfudge by -\headerheight}}
+
+\def \adjusttopfloatfudge #1{%
+ \global\advance \topfloatfudge by #1\relax}
+
+\def \piggybackfloat {%
+ \edef \znext {\noexpand\global\noexpand\increment
+ \name{\float\zcurflttype number}}%
+ \znext
+ \edef \znext {\floatnumber = \name{\float\zcurflttype number}}%
+ \znext}
+
+% Controlling Floats
+% ----------- ------
+
+
+% This macro is invoked at the beginning of each division.
+
+\def \zfltdivinit {%
+ \global\zdivfltcounter = 0\relax}
+
+
+\setflag \zschedflts = \true
+
+\def \deferfloats #1{% {boolean}
+ \global\setflag \zschedflts = {\notp{#1}}}
+
+
+% Scheduling Tools
+% ---------- -----
+
+
+% These counters keep track of the number of floats scheduled for the
+% current page.
+
+\definecount{\ztopcolfloats}{0} % Number of top column floats.
+\definecount{\zbotcolfloats}{0} % Number of bottom column floats.
+\definecount{\zfloatsinserted}{0} % Total number of floats.
+\definetoks{\zfltrunners} % Runners for first float on page.
+
+% This macro initializes for handling floats on a new page.
+
+\def \zfloatinit {%
+ \global\setflag \zschedflts = \true
+ \global\ztopcolfloats = 0
+ \global\zbotcolfloats = 0
+ \zfltrunners = {}}
+
+% These macros simply hide some of the details to make the \zsched*
+% macros easier to read.
+
+\def \ztallytopfloat {%
+ \if \orp{\notp{\zfltposmargonly}}{\posp{\ztopcolfloats}}%
+ \global\increment \ztopcolfloats
+ \fi}
+
+\def \zforcenewpage{%
+ \global\zfloatsinserted = 101\relax}
+
+\let \zquitscheding = \exitmaplist
+
+\def \zsetfloattall{%
+ \zmakefloatalone
+ \setflag \zfloattall = \true
+ \tracepagemakeup{Float is too tall for column; positioning `alone'.}}
+
+\def \zmakefloatalone{%
+ \setflag \zfltposalone = \true
+ \setflag \zfltposbottom = \false
+ \setflag \zfltposhereonly = \false
+ \setflag \zfltposhere = \false
+ \setflag \zfltposseparate = \false
+ \setflag \zfltpostop = \false}
+
+\def \zmakefloattop{%
+ \setflag \zfltposalone = \false
+ \setflag \zfltposbottom = \false
+ \setflag \zfltposhereonly = \false
+ \setflag \zfltposhere = \false
+ \setflag \zfltposseparate = \false
+ \setflag \zfltpostop = \true}
+
+% Float Scheduler
+% ----- ---------
+
+
+% return-count is a counter passed in by the caller that we should
+% set at the end of \zschedulefloats to indicate how
+% many floats were emitted during this call. A value
+% greater than 99 indicates that a new page should be
+% FORCED (e.g. for alone floats) by the output routine.
+% during-output? is a flag indicating that the caller is
+% part of the output routine.
+% flushing? A flag indicating whether we are flushing floats.
+
+\def \zschedulefloats #1#2#3{% {return-count}{during-output?}{flushing?}
+ \tracepagemakeup{[Scheduling \if #2floats during output%
+ \else float when encountered\fi.}%
+ \tracepagemakeup{Page total: \the\pagetotal; goal: \the\pagegoal.}%
+ % Reset our counter
+ \global\zfloatsinserted = 0
+ \if \zschedflts
+ \if \emptydefp{\zfloatpendq}%
+ \tracepagemakeup{There are no floats to be scheduled.}%
+ \else
+ \endgraf
+ \zinitfloatfit{#2}%
+ {\setflag \zschedfirstseparate = \true
+ \setflag \zschedseparateloop = \false
+ \maplist{\zschedone{#2}{#3}{##1}}{\zfloatpendq}}%
+ \fi
+ \else
+ \tracepagemakeup{Floats are deferred now.}%
+ \fi
+ \tracepagemakeup{Float scheduling complete;
+ floats inserted: \the\zfloatsinserted.]}%
+ \xdef #1{\the\zfloatsinserted}}
+
+
+\def \zschedone #1#2#3{% {during-output?}{flushing?}{\float}
+ #3%
+ \zparsefltpos{\the\position}%
+ \if \notp{\emptytoksp{\pageplacement}}
+ \zparsefltpagepos{\the\pageplacement}%
+ \fi
+ \if #2% % If flushing floats, force float
+ \setflag \zfltposbottom = \false % to a `separate'.
+ \setflag \zfltpostop = \false
+ \setflag \zfltposseparate = \true
+ \fi
+ \tracepagemakeup{Trying to schedule \zcurfloatid;
+ size: \the\ht\zcurfloatbox+\the\dp\zcurfloatbox.}%
+ \if \orp{\andp{\zfltposeven}{\oddpagep}}%
+ {\andp{\zfltposodd}{\evenpagep}}%
+ \tracepagemakeup{Float is deferred until appropriate even/odd page.}%
+ \zquitscheding
+ \else
+ \setflag \zfloatunsched = \true
+ \setflag \zfloattall = \false
+ % The following macros attempt, in order of priority, to schedule
+ % the current float. Each macro may set up state that causes
+ % the subsequent macro(s) to do nothing.
+ \zschedhereonly{#1}%
+ \zschedhere{#1}%
+ \zschedalone{#1}%
+ \zschedbroadside{#1}%
+ \zschedseparate{#1}%
+ \zschedtop{#1}%
+ \zschedbottom{#1}%
+ \if \zfloattall % Schedule as `alone'.
+ \zschedalone{#1}%
+ \fi
+ \if \zfloatunsched
+ \tracepagemakeup{Float could not be scheduled.}%
+ % This exits a \maplist call to \zschedone.
+ \zquitscheding
+ \else
+ % Remove the current float from the queue...
+ \pop{\zcurfloat}{\zfloatpendq}%
+ % ...and free up the associated data structures.
+ \expandaftertwice\zfreefloat \expandafter\zcurfloat\zcurfloatbox
+ \fi
+ \fi}
+
+% Fitting a Float
+% ------- - -----
+
+
+% These registers are used in float fitting. They contain,
+% respectively, the amount of vertical space used up by floats for
+% the current page and the maximum space available for floats.
+
+\definedimen{\zfloatpageused}{0pt}
+\definedimen{\zfloatmaxavail}{0pt}
+
+
+% Macro to initialize the above parameters (called in \zschedulefloats).
+
+\def\zinitfloatfit #1{% {during-output?}
+ \if #1
+ \zfloatpageused = 0pt
+ % Effectively: zfloatmaxavail = (100-mintextpercent) * vsize
+ \calculate \tcounta = {100,-,\mintextpercent}%
+ \calculate \zfloatmaxavail = {\vsize,P,\tcounta}%
+ \else
+ % Effectively: zfloatpageused = max(pagetotal, vsize * mintextpercent)
+ \calculate \zfloatpageused = {\vsize,P,\mintextpercent,X,\pagetotal}%
+ \zfloatmaxavail = \pagegoal
+ \fi}
+
+
+% The spacing above and below a float is fairly complicated.
+% In this table, h is the height of the float, d is the depth.
+%
+% Position Sequence Above Below
+%
+% \alone only \topskip - h + none
+% \topfloatfudge
+% \bottom first \aboveskip - h none
+% rest min(\aboveskip, none
+% \belowskip) - h
+%
+% \separate first \topskip - h + none
+% \topfloatfudge
+% rest min(\aboveskip, none
+% \belowskip) - h
+% \top first \topskip - h + \belowskip - \topskip - d
+% \topfloatfudge
+% rest min(\aboveskip, \belowskip - \topskip - d
+% \belowskip) - h
+
+
+% Here and broadside floats are handled differently, below in \zfitfloathere
+% and \zfitfloatbroadside
+
+\def \zfitfloat #1#2#3#4#5{% {result-flag}{top?}{aboveskip-first}
+ % {aboveskip-rest}{belowskip}
+ {\if \zfltposmargonly
+ \tcounta = 0 % Margin float should act as first one.
+ \else
+ \tcounta = \if #2\ztopcolfloats \else \zbotcolfloats \fi
+ \fi
+ \zskipa = \if \zerop{\tcounta}#3\else #4\fi
+ \advance \zskipa by -\ht\zcurfloatbox
+ \if \andp{#2}{\zerop{\tcounta}}\advance \zskipa by \topfloatfudge \fi
+ \tdimena = \zskipa
+ \advance \tdimena by \ht\zcurfloatbox
+ \advance \tdimena by \dp\zcurfloatbox
+ \tdimenb = #5\advance \tdimena by \tdimenb
+ \tdimenc = \zfloatpageused
+ \if \notp{\zfltposmargonly}\advance \tdimenc by \tdimena \fi
+ \tracepagemakeup{Requires: \the\tdimena;
+ available: \the\zfloatmaxavail;
+ used: \the\zfloatpageused.}%
+ \if \dimlssp{\tdimenc}{\zfloatmaxavail}%
+ \if \andp{\notp{#2}}{\zfltposmargonly}%
+ \insert \zbotcolinsert {%
+ \vbox to 0pt{%
+ \vss
+ \moveright \floatshift \box\zcurfloatbox
+ \vskip -\dp\zcurfloatbox}}%
+ \else
+ \insert \if #2\ztopcolinsert \else \zbotcolinsert \fi {%
+ \vskip \zskipa
+ \moveright \floatshift \box\zcurfloatbox
+ \nobreak
+ \if \zfltposmargonly
+ \vskip \tdimenb
+ \nobreak
+ \vskip -\tdimena
+ \else
+ \vskip #5\relax
+ \fi}%
+ \fi
+ \if \emptytoksp{\zfltrunners}%
+ \global\zfltrunners = \expandafter{\the\runners}%
+ \fi
+ \global\increment \zfloatsinserted
+ \global\zfloatpageused = \tdimenc
+ \global\setflag #1= \true
+ \else
+ \global\setflag #1= \false
+ \fi}}
+
+\def \zfitfloathere #1#2#3{% {result-flag}{aboveskip}{belowskip}
+ {\tdimena = #2\relax
+ \advance \tdimena by \dp\zcurfloatbox
+ \advance \tdimena by #3\relax
+ \tracepagemakeup{Requires: \the\tdimena;
+ page total: \the\pagetotal;
+ page goal: \the\pagegoal.}%
+ \advance \tdimena by \pagetotal
+ \if \dimlssp{\tdimena}{\pagegoal}%
+ \bbskipabove{\breaknever}{#2}%
+ \fakepar
+ \moveright \floatshift \box\zcurfloatbox
+ \prevdepth = \zfloatdp
+ \bbskipbelow{\breakallowed}{#3}%
+ \global\increment \zfloatsinserted
+ \global\setflag #1= \true
+ \else
+ \global\setflag #1= \false
+ \fi}}
+
+\def \zfitfloatbroadside {%
+ {% We know there are no other floats on the the topcolumn when
+ % this is called (by \zschedbroadside only) and we don't have to
+ % worry about fixing up the vertical position at the end of the
+ % page.
+ %
+ % Compute the space required
+ % Start with the topskip
+ \tdimena = \topfloatfudge
+ % Add the *width* (since the box will be rotated)
+ \advance \tdimena by \wd\zcurfloatbox
+ \tracepagemakeup{Requires: \the\tdimena;
+ broadside floats always fit.}%
+ \insert \ztopcolinsert {%
+ % vskip the top float fudge
+ \vskip \topfloatfudge
+ % save the width for unskipping later
+ \tdimenb = \wd\zcurfloatbox
+ % vskip the *width* of the box to do the position translation
+ % that we can't do with PostScript
+ \vskip \tdimenb
+ % Put our hbox in a vbox, so we can "lower" it rather than move
+ % it right (since it will be rotated)
+ \global\setbox\zfltbroadbox = \vbox{%
+ \vskip\floatshift % replaces \moveright in other floats
+ \box\zcurfloatbox}%
+ \rotatebox{\zfltbroadbox}{90}%
+ % Undo vertical skip so that insert doesn't cause additional page
+ \vskip -\tdimenb}%
+ \if \emptytoksp{\zfltrunners}%
+ \global\zfltrunners = \expandafter{\the\runners}%
+ \fi
+ \global\increment \zfloatsinserted
+ \global\zfloatpageused = \tdimena}}
+
+% Individual Schedulers
+% ---------- ----------
+
+
+% This is a temporary register used in calls to \zfitfloat where the
+% fit needs to take into account more than one skip value (such as
+% both the \aboveskip and \belowskip). In that case this dimen is
+% used as a temp to hold the sum of the skip values.
+
+\defineskip{\zfloatabove}{0pt}
+\defineskip{\zfloatbelow}{0pt}
+\definedimen{\zfloatextraskip}{0pt}
+
+
+% This scheduler is called for floats with position `here' and no others.
+
+\def\zschedhereonly #1{% {during-output?}
+ \if \andp{\zfloatunsched}{\zfltposhereonly}%
+ \tracepagemakeup{Float is to be positioned `here' only.}%
+ \if \zschedseparateloop
+ \tracepagemakeup{Making up a page of separates; quit.}%
+ \zforcenewpage
+ \zquitscheding
+ \else
+ \if #1% during output:
+ \tracepagemakeup{Float moved to top of this page.}%
+ \zmakefloattop
+ \else % when encountered:
+ \if \posp{\zbotcolfloats}%
+ \error{hereonlybot}{Cannot position float `here'; already floats
+ at bottom.}%
+ \else\if \dimzerop{\pagetotal}%
+ \tracepagemakeup{Float at top of column: schedule as `top' float.}%
+ \zmakefloattop
+ \else
+ \zfitfloathere{\zfloatfits}{\aboveskip}{\belowskip}%
+ \if \zfloatfits
+ \tracepagemakeup{Float inserted here.}%
+ \setflag \zfloatunsched = \false
+ \else
+ \tracepagemakeup{Float does not fit here.}%
+ \zforcenewpage
+ \zquitscheding
+ \fi
+ \fi\fi
+ \fi
+ \fi
+ \fi}
+
+
+% This scheduler is called for floats with position `here' along with at
+% least one other page position.
+
+\def\zschedhere #1{% {during-output?}
+ \if \andp{\zfloatunsched}{\zfltposhere}%
+ \tracepagemakeup{Float can be positioned `here'.}%
+ \if \zschedseparateloop
+ \tracepagemakeup{Making up a page of separates; quit.}%
+ \zforcenewpage
+ \zquitscheding
+ \else
+ \if #1% during output:
+ \relax
+ \else % when encountered:
+ \if \posp{\zbotcolfloats}%
+ \tracepagemakeup{There are already floats positioned `bottom'.}%
+ \else\if \dimzerop{\pagetotal}%
+ \tracepagemakeup{Float at top of column: schedule as `top' float.}%
+ \zmakefloattop
+ \else
+ \zfitfloathere{\zfloatfits}{\aboveskip}{\belowskip}%
+ \if \zfloatfits
+ \tracepagemakeup{Float inserted here.}%
+ \setflag \zfloatunsched = \false
+ \else
+ \tracepagemakeup{Float does not fit here.}%
+ \fi
+ \fi\fi
+ \fi
+ \fi
+ \fi}
+
+
+\def \zschedalone #1{% {during-output?}
+ \if \andp{\zfloatunsched}{\zfltposalone}%
+ \tracepagemakeup{Float can be positioned `alone'.}%
+ \if \zschedseparateloop
+ \tracepagemakeup{Making up a page of separates; quit.}%
+ \zforcenewpage
+ \zquitscheding
+ \else
+ \if \orp{#1}{\dimzerop{\pagetotal}}%
+ \if \firstcolumnp % building new page
+ \if \zerop{\zfloatsinserted}% no floats on this page, yet
+ \dp\zcurfloatbox = 0pt % Make it fit.
+ \zfitfloat{\zfloatfits}{\true}{\topskip}{999pt}{0pt}%
+ \if \zfloatfits
+ \ztallytopfloat
+ \tracepagemakeup{Inserted on a page by itself.}%
+ \zforcenewpage
+ \setflag \zfloatunsched = \false
+ \zquitscheding
+ \fi
+ \else % wait for next time
+ \tracepagemakeup{Already floats in this column; quit.}%
+ \zquitscheding
+ \fi
+ \else% still in the middle of a page
+ \tracepagemakeup{Not in first column of page; quit.}%
+ \zquitscheding
+ \fi
+ \else % As encountered, and page not empty.
+ \tracepagemakeup{Must wait for new page; quit.}%
+ \zquitscheding
+ \fi
+ \fi
+ \fi}
+
+\def \zschedbroadside #1{% {during-output?}
+ \if \andp{\zfloatunsched}{\zfltposbroadside}%
+ \tracepagemakeup{Float can be positioned `broadside'.}%
+ \if \zschedseparateloop
+ \tracepagemakeup{Making up a page of separates; quit.}%
+ \zforcenewpage
+ \zquitscheding
+ \else
+ \if \orp{#1}{\dimzerop{\pagetotal}}%
+ \if \firstcolumnp % building new page
+ \if \zerop{\zfloatsinserted}% no floats on this page, yet
+ % Broadside floats "always" fit. The output will have to be
+ % inspected.
+ \zfitfloatbroadside
+ \ztallytopfloat
+ \tracepagemakeup{Inserted on a page by itself.}%
+ \zforcenewpage
+ \setflag \zfloatunsched = \false
+ \zquitscheding
+ \else % wait for next time
+ \tracepagemakeup{Already floats on this page; quit.}%
+ \zquitscheding
+ \fi
+ \else% still in the middle of a page
+ \tracepagemakeup{Not in first column of page; quit.}%
+ \zquitscheding
+ \fi
+ \else % As encountered, and page not empty.
+ \tracepagemakeup{Must wait for new page; quit.}%
+ \zquitscheding
+ \fi
+ \fi
+ \fi}
+
+
+\def\zschedseparate #1{% {during-output?}
+ \if \andp{\zfloatunsched}{\zfltposseparate}%
+ \tracepagemakeup{Float can be positioned `separate'.}%
+ % If a separate float is called when encountered, we don't do anything.
+ \if #1% during output
+ \if \firstcolumnp % building a new page
+ \if \zschedfirstseparate
+ \if \zerop{\zfloatsinserted}% no floats on this page, yet
+ \zfloatmaxavail = \vsize % Entire page is available now.
+ \zfitfloat{\zfloatfits}{\true}{\topskip}{999pt}{0pt}%
+ \if \zfloatfits
+ \ztallytopfloat
+ \setflag \zfloatunsched = \false
+ \zforcenewpage % This is a page of separates now.
+ \tracepagemakeup{Inserted at the top of a new page.}%
+ \setflag \zschedfirstseparate = \false
+ \setflag \zschedseparateloop = \true
+ \else
+ \zsetfloattall
+ \fi
+ \else % wait for next time
+ \tracepagemakeup{Page already has other floats on it.}%
+ \zquitscheding
+ \fi
+ \else % Subsequent separates.
+ \zfloatabove = \if \dimlssp{\aboveskip}{\belowskip}\aboveskip
+ \else \belowskip \fi
+ \zfitfloat{\zfloatfits}{\true}{999pt}{\zfloatabove}{0pt}%
+ \if \zfloatfits
+ \ztallytopfloat
+ \setflag \zfloatunsched = \false
+ \tracepagemakeup{Inserted on a page with other separates.}%
+ \else
+ \zquitscheding
+ \tracepagemakeup{Does not fit on this page; start new page.}%
+ \fi
+ \fi
+ \else% still in the middle of a page
+ \tracepagemakeup{Must wait for new page; quit;}%
+ \zquitscheding
+ \fi
+ \else% when encountered
+ \tracepagemakeup{Must wait for new page; quit.}%
+ \zquitscheding
+ \fi
+ \fi}
+
+
+\def\zschedtop#1{% {during-output?}
+ \if \andp{\andp{\zfloatunsched}{\zfltpostop}}
+ {\orp{\notp{\zfltposfollow}}{#1}}%
+ \tracepagemakeup{Float can be positioned `top'.}%
+ \if \zschedseparateloop
+ \tracepagemakeup{Making up a page of separates; quit.}%
+ \zforcenewpage
+ \zquitscheding
+ \else
+ \if \lssp{\ztopcolfloats}{\maxtopcolumnfloats}%
+ \zfloatabove = \if \dimlssp{\aboveskip}{\belowskip}\aboveskip
+ \else \belowskip \fi
+ \advance \zfloatabove by -\belowskip
+ \advance \zfloatabove by \topskip
+ \zfloatbelow = \belowskip
+ \tdimena = \topskip
+ \advance \zfloatbelow by -\tdimena
+ \advance \zfloatbelow by -\zfloatdp
+ \zfitfloat{\zfloatfits}{\true}{\topskip}{\zfloatabove}{\zfloatbelow}%
+ \if \zfloatfits
+ \ztallytopfloat
+ \tracepagemakeup{Inserted at top of column.}%
+ \setflag \zfloatunsched = \false
+ \else
+ \if \andp{#1}{\zerop{\zfloatsinserted}}\zsetfloattall \fi
+ \fi
+ \fi
+ \fi
+ \fi}
+
+\def \zschedbottom#1{% {during-output?}
+ \if \andp{\zfloatunsched}{\zfltposbottom}%
+ \tracepagemakeup{Float can be positioned `bottom'.}%
+ \if \zschedseparateloop
+ \tracepagemakeup{Making up a page of separates; quit.}%
+ \zforcenewpage
+ \zquitscheding
+ \else
+ \if \lssp{\zbotcolfloats}{\maxbottomcolumnfloats}%
+ \zfloatbelow = \if \dimlssp{\aboveskip}{\belowskip}\aboveskip
+ \else \belowskip \fi
+ \zfitfloat{\zfloatfits}{\false}{\aboveskip}{\zfloatbelow}{0pt}%
+ \if \zfloatfits
+ \if \notp{\zfltpostopafterbot}%
+ \global\ztopcolfloats = \maxtopcolumnfloats
+ \fi
+ \global\increment \zbotcolfloats
+ \tracepagemakeup{Inserted at bottom of column.}%
+ \setflag \zfloatunsched = \false
+ \else
+ \if \andp{#1}{\zerop{\zfloatsinserted}}\zsetfloattall \fi
+ \fi
+ \fi
+ \fi
+ \fi}
+
+% Captions
+% --------
+
+
+\defineblock{\caption}{\endcaption}{\false}{}
+
+%~block caption Type
+% \aboveskip = glue % Space b/b above caption.
+% \setflag \allowintoc = flag % Allow caption in ToC.
+% \belowskip = glue % Space b/b below caption.
+% \captionfudge = dimen % Fudge for \aboveskip.
+% \def \comptextformat {...} % (No longer used with captions.)
+% \difficulty = integer % Level of difficulty.
+% \leftindent = glue % Left indentation.
+% \legendfont = {...} % Font for optional legend.
+% \def \legendformat ##1{...} % Legend formatter.
+% \numberfont = {...} % Font for float number.
+% \parindent = dimen % Paragraph indent.
+% \parrag = dimen % Paragraph raggedness.
+% \parskip = glue % Paragraph skip.
+% \position = {...} % Position (see below).
+% \rightindent = glue % Right indentation.
+% \style = {...} % Heading style.
+% \titlefont = {...} % Font for caption title.
+% \def \titleformat ##1{...} % Title formatter.
+% \width = dimen % Width of caption text.
+%~end
+
+\definedimen{\captionfudge}{0pt}
+\definetoks{\legendfont}
+
+\definebox{\zcapbox}
+\definedimen{\zcapshift}{0pt}
+
+%~ This marker indicates that the following text is the legend or
+%~ credit for the caption.
+
+\definemarker{\legend}
+
+
+\def \caption #1{% {title with optional \legend}
+ \blockmustbein{\caption}{\float}%
+ \blockcantbein{\caption}{\caption}%
+ \beginblockscope{caption}%
+ \global\increment \captiondepth
+ \captionfudge = 0pt %~default with
+ \def \comptextformat {}% %~default hard
+ \style = {Initial cap/lowercase}% %~default soft
+ \difficulty = 0 %~default with
+ \processdesign{\caption}{\zcurflttype}%
+ \global\increment \captionnumber
+ \if \notp{\emptydefp{\comptextformat}}%
+ \error{capcomptext}{The \string\comptextformat\space parameter is no
+ longer used in captions}
+ \fi
+ \captionformat #1\legend\zmark
+ \if \andp{\allowintoc}{\notp{\continuationp}}\zcaptoc #1\legend\zmark \fi
+ \endcaption
+ \zcaptag #1\legend\zmark}% % Reset tag info with title.
+
+\def \endcaption {%
+ \global\decrement \captiondepth
+ \endblockscope{caption}}
+
+\def \captionformat #1\legend#2\zmark{%
+ \the\numberfont
+ \setbox\zcapbox = \vtop{%
+ \zpushvcontext
+ \setindentation{\leftindent}{\rightindent}%
+ \settextwidth{\width}%
+ \setparrag{\parrag}%
+ \if \emptyargp{#2}%
+ \titleformat{#1}%
+ \else
+ \let \legend = \relax % So it won't interfere with formatting.
+ \titleformat{#1\the\legendfont \legendformat{#2}}%
+ \fi
+ \endgraf
+ \global\zfloatdp = \prevdepth
+ \zpopvcontext}%
+ \zparsecappos{\the\position}%
+ \zcalccapitems
+ \bbskipabove{\breaknever}{\aboveskip}%
+ \noindent \kern \zcapshift \box\zcapbox \par
+ \prevdepth = \zfloatdp
+ \bbskipbelow{\breaknever}{\belowskip}}
+
+\def \zcaptoc #1\legend#2\zmark{%
+ \tocentry{\the\floatcomptext}{#1}{\zcurfltlvl}}
+
+\def \zcaptag #1\legend#2\zmark{%
+ \settaginfo{\the\floatcomptext}{#1}}
+
+% Position Handling
+% -------- --------
+
+
+% This macro sets up variables that specify the position of a float,
+% according to the \position design parameter:
+%
+% \alone Place float on a page by itself.
+% \anypage Place float on any page.
+% \any (synonym for \anypage)
+% \bottom Place float at the bottom of a page.
+% \broadside Place float broadside (alone, rotated 90 degrees).
+% \evenpage Place float on an even page.
+% \follow Float must follow its position in the text.
+% \here Place float exactly where it appears.
+% \ifevenpage Use next position only on even page.
+% \ifoddpage Use next position only on odd page.
+% \leftmargin Shift float to left margin.
+% \margin Same as \leftmargin.
+% \marginonly Float fits in the margin and does not occupy any
+% vertical space on the page.
+% \nofollow Float need not follow its position in the text.
+% \oddpage Place float on an odd page.
+% \outsidemargin Shift float to outside margin.
+% \rightmargin Shift float to right margin.
+% \separate Place float on a page with floats only.
+% \textarea Leave float at left edge of text area.
+% \text (synonym for \textarea)
+% \top Place float at the top of a page.
+% \topafterbottom Okay to schedule \top float after \bottom.
+
+
+\definecount{\zfltposshift}{0}
+
+
+\def \zparsefltpos #1{% {options...}
+ {\zclearfltpagepos
+ \global\setflag \zfltposmargonly = \false
+ \global\zfltposshift = 0\relax
+ \zsetupfltpageopts
+ \def \ifevenpage ##1{\if \evenp{\floatpage}##1\fi}%
+ \def \ifoddpage ##1{\if \oddp{\floatpage}##1\fi}%
+ \def \leftmargin {\global\zfltposshift=1\relax}%
+ \let \margin = \leftmargin
+ \def \marginonly {\global\setflag\zfltposmargonly=\true}%
+ \def \outsidemargin{\ifevenpage{\leftmargin}\ifoddpage{\rightmargin}}%
+ \def \rightmargin {\global\zfltposshift=2\relax}%
+ \def \textarea {\global\zfltposshift=0\relax}%
+ \let \text = \textarea
+ \global\floatpage = \floatpage
+ #1%
+ \global\setflag \zfltposhereonly = \zfltposhere
+ \global\setflag \zfltposok = \zfltposhere
+ \if \orp{\zfltposalone}
+ {\orp{\zfltposbottom}
+ {\orp{\zfltposbroadside}
+ {\orp{\zfltposseparate}
+ {\zfltpostop}}}}%
+ \global\setflag \zfltposhereonly = \false
+ \global\setflag \zfltposok = \true
+ \fi
+ \if \zfltposhereonly \setflag \zfltposhere = \false \fi
+ \if \notp{\zfltposok}%
+ \warning{nofloatpos}{No page position has been specified for a float}%
+ \global\setflag \zfltposalone = \true
+ \fi}}
+
+\def \zparsefltpagepos #1{% {options...}
+ {\zclearfltpagepos
+ \zsetupfltpageopts
+ #1%
+ \global\setflag \zfltposhereonly = \zfltposhere
+ \if \orp{\zfltposalone}
+ {\orp{\zfltposbottom}{\orp{\zfltposseparate}{\zfltpostop}}}%
+ \global\setflag \zfltposhereonly = \false
+ \fi
+ \if \zfltposhereonly \global\setflag \zfltposhere = \false \fi}}
+
+\def \zclearfltpagepos {%
+ \global\setflag \zfltposalone = \false
+ \global\setflag \zfltposbottom = \false
+ \global\setflag \zfltposbroadside = \false
+ \global\setflag \zfltposeven = \false
+ \global\setflag \zfltposfollow = \false
+ \global\setflag \zfltposhere = \false
+ \global\setflag \zfltposodd = \false
+ \global\setflag \zfltposseparate = \false
+ \global\setflag \zfltpostop = \false
+ \global\setflag \zfltpostopafterbot = \false}
+
+\def \zsetupfltpageopts {%
+ \def \alone {\global\setflag\zfltposalone=\true}%
+ \def \anypage {\global\setflag\zfltposeven=\false
+ \global\setflag\zfltposodd=\false}%
+ \let \any = \anypage
+ \def \bottom {\global\setflag\zfltposbottom=\true}%
+ \def \broadside {\global\setflag\zfltposbroadside=\true}%
+ \def \evenpage {\global\setflag\zfltposeven=\true}%
+ \def \follow {\global\setflag\zfltposfollow=\true}%
+ \def \here {\global\setflag\zfltposhere=\true}%
+ \def \nofollow {\global\setflag\zfltposfollow=\false}%
+ \def \oddpage {\global\setflag\zfltposodd=\true}%
+ \def \separate {\global\setflag\zfltposseparate=\true}%
+ \def \top {\global\setflag\zfltpostop=\true}%
+ \def \topafterbottom {\global\setflag\zfltpostopafterbot=\true}}
+
+\def \zcalcfltparams {%
+ \floatshift = 0pt\relax
+ % Set \floatshift
+ \ifcase \zfltposshift
+ \relax
+ \or
+ \floatshift = \if \evenp{\floatpage}-\evenlefttextmargin
+ \else -\oddlefttextmargin \fi \relax
+ \or
+ \floatshift = \textmeasure
+ \else
+ \zzerror{Invalid value for float `\string\zfltposshift'}%
+ \fi
+ \advance \floatshift by \leftindent
+
+ % Set \floatwidth. Default of \naturalwidth is handled differently
+ % for broadsides than for non-broadsides. If \width not default, use
+ % it without modification.
+
+ \if \dimeqlp{\width}{\naturalwidth}%
+ \if \zfltposbroadside
+ \floatwidth = \textareaheight \relax
+ \else
+ \floatwidth = \textmeasure \relax
+ \ifcase \zfltposshift
+ \relax
+ \or
+ \advance \floatwidth by -\floatshift
+ \or
+ \floatwidth = \if \evenp{\floatpage}\evenrighttextmargin
+ \else \oddrighttextmargin \fi \relax
+ \else
+ \zzerror{Invalid value for float `\string\zfltposshift'}%
+ \fi
+ \fi
+ \else
+ \floatwidth = \width \relax
+ \fi}
+
+
+% This macro sets up variables that specify the position of a caption,
+% according to the \position design parameter:
+%
+% \above Caption is placed above the figure.
+% \below Caption is placed below the figure.
+% \follow Caption follows left edge of float.
+% \ifevenpage Use next position only on even page.
+% \ifoddpage Use next position only on odd page.
+% \leftmargin Force caption in left margin.
+% \margin Same as \leftmargin
+% \outsidemargin Shift caption to outside margin.
+% \rightmargin Force caption in right margin.
+% \rise Caption rises up from bottom of figure.
+% \separate Caption is separate from figure.
+% \sink Caption sinks down from top of figure.
+% \textarea Force caption at left edge of text area.
+% \text (synonym for \textarea)
+% \textarearight Force caption at right edge of text area.
+% \textright (synonym for \textarearight)
+
+
+\definecount{\zcapposshift}{0}
+\definecount{\zcapposvflow}{0}
+
+\def \zparsecappos #1{% {options...}
+ {\global\setflag \zcapposabove = \true
+ \global\zcapposvflow = 0\relax
+ \global\zcapposshift = 0\relax
+ \def \above {\global\setflag\zcapposabove=\true}%
+ \def \below {\global\setflag\zcapposabove=\false}%
+ \def \follow {\global\zcapposshift=4\relax}%
+ \def \ifevenpage ##1{\if \evenp{\floatpage}##1\fi}%
+ \def \ifoddpage ##1{\if \oddp{\floatpage}##1\fi}%
+ \def \leftmargin {\global\zcapposshift=1\relax}%
+ \let \margin = \leftmargin
+ \def \outsidemargin {\ifevenpage{\leftmargin}\ifoddpage{\rightmargin}}%
+ \def \rightmargin {\global\zcapposshift=2\relax}%
+ \def \rise {\global\zcapposvflow=1\relax}%
+ \def \separate {\global\zcapposvflow=0\relax}%
+ \def \sink {\global\zcapposvflow=2\relax}%
+ \def \textarea {\global\zcapposshift=0\relax}%
+ \let \text = \textarea
+ \def \textarearight {\global\zcapposshift=3\relax}%
+ \let \textright = \textarearight
+ #1}}
+
+\def \zcalccapitems {%
+ \ifcase \zcapposshift
+ \zcapshift = 0pt
+ \or
+ \zcapshift = \if \evenp{\floatpage}-\evenlefttextmargin
+ \else -\oddlefttextmargin \fi \relax
+ \or
+ \zcapshift = \textmeasure
+ \or
+ \zcapshift = \textmeasure
+ \advance \zcapshift by -\wd\zcapbox
+ \or
+ \zcapshift = \floatshift
+ \else
+ \zzerror{Invalid value for caption `\string\zcapposshift'}%
+ \fi
+ \advance \zcapshift by -\floatshift
+ % Captions in broadsides *always* follow, i.e. \zcapshift is 0pt
+ \if \zfltposbroadside
+ \zcapshift = 0pt\relax
+ \fi
+ \ifcase \zcapposvflow
+ \relax
+ \or
+ \forcenextbbskip
+ \aboveskip = -\dp\zcapbox
+ \advance \aboveskip by \zfloatdp
+ \advance \aboveskip by \captionfudge
+ \or
+ \advance \belowskip by -\dp\zcapbox
+ \advance \belowskip by -\captionfudge
+ \else
+ \zzerror{Invalid value for caption `\string\zcapposvflow'}%
+ \fi}
diff --git a/macros/plain/contrib/zztex/tex/zzfont.tex b/macros/plain/contrib/zztex/tex/zzfont.tex
new file mode 100644
index 0000000000..f2b15f3775
--- /dev/null
+++ b/macros/plain/contrib/zztex/tex/zzfont.tex
@@ -0,0 +1,453 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% Module: ZzTeX Font Facilities
+%
+% Synopsis: This module contains all the macros necessary to define type
+% sizes, styles, and fonts.
+%
+% Author: Paul C. Anagnostopoulos
+% Created: 28 August 1989
+%
+% Copyright 1989--2020 by Paul C. Anagnostopoulos
+% under The MIT License (opensource.org/licenses/MIT)
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% Baselines & Struts
+% --------- - ------
+
+
+\zremovePlaindef \strutbox
+\definebox{\strutbox} % Strut for current type size.
+
+\def \strut {%
+ \relax
+ \if \mathmodep
+ \copy \strutbox
+ \else
+ \unhcopy \strutbox
+ \fi}
+
+\def \normalbaselines {%
+ \baselineskip = \the\baselinemultiplier\normalbaselineskip
+ \lineskiplimit = \normallineskiplimit
+ \lineskip = \normallineskip}
+
+% Type Style & Size Definition
+% ---- ----- - ---- ----------
+
+
+% The following character set encodings are available. Odd numbers
+% indicate italic; numbers > 20 indicate monospaced.
+
+\chardef \encoderoman = 0 % Roman. %^encoding
+\chardef \encodeitalic = 1 % Italic. %^encoding
+\chardef \encodemathitalic = 3 % Math italic. %^encoding
+\chardef \encodemathsymbol = 4 % Math symbols. %^encoding
+\chardef \encodemathextended = 6 % Math extended symbols. %^encoding
+\chardef \encodematharrow = 8 % Math arrows. %^encoding
+\chardef \encodeother = 10 % Generic. %^encoding
+\chardef \encodemono = 22 % Monospaced. %^encoding
+\chardef \encodemonoitalic = 23 % Monospaced italic. %^encoding
+
+\setlist \zfsizelist = {}
+\setlist \zfstylelist = {}
+
+
+\def \definetypestyle #1#2{% {\name}{\encoding}
+ \append{#1}{\zfstylelist}%
+ \zfwithfam{\zdeffam}{#1}%
+ \zfwithmat{\def}{#1}{\zfl}{}%
+ \zfwithmat{\xdef}{#1}{\zen}{#2}}
+
+\def \definetypesize #1#2{% {\name}{size/baseline}
+ \append{#1}{\zfsizelist}%
+ \zdefsize #1#2/%
+ \zdefstrut #1#2/%
+ \zfbldsize{#1}}
+
+\def \zdefsize #1#2/#3/{% \name size/baseline/
+ \zfwithmat{\xdef}{#1}{\zsz}{#2pt}}
+
+\def \zdefstrut #1#2/#3/{% \name size/baseline/
+ {\calculate \tdimena = {#3pt,P,70}%
+ \tdimenb = #3pt\relax
+ \advance \tdimenb by -\tdimena
+ \zfwithmat{\xdef}{#1}{\zst}{height \the\tdimena\space depth \the\tdimenb}}}
+
+
+% A few useful predicates.
+
+\def \typestylep #1{% {\style}
+ \xtokeqlp{\the\typestyle}{#1}}
+
+\def \italicencodingp {%
+ \oddp{\typeencoding}}
+
+\def \monoencodingp {%
+ \gtrp{\typeencoding}{20}}
+
+% Commands to set font parameters.
+
+\def \setstylefontparam #1#2#3{% {\style}{param}{value}
+ \zfwithmat\maplistlf {#1}{\zfl}{%
+ \zfsetfp{##1}{#2}{#3}}}
+
+\def \setstylehyphenchar #1#2{% {\style}{number}
+ \setstylefontparam{#1}{-2}{#2}}
+
+\def \setstyleskewchar #1#2{% {\style}{number}
+ \setstylefontparam{#1}{-1}{#2}}
+
+\def \zfsetfp #1#2#3{% {font}{param}{value}
+ \if \eqlp{#2}{-2}%
+ \hyphenchar #1=#3\relax
+ \else\if \eqlp{#2}{-1}%
+ \skewchar #1=#3\relax
+ \else
+ \fontdimen#2#1=#3\relax
+ \fi\fi}
+
+% Style Relations
+% ----- ---------
+
+
+\def \definestylerelation #1#2#3{% {\style}{\relation}{\style}
+ \zfwithmat{\gdef}{#1}{#2}{#3}%
+ \gdef #2{\bgroup \zfrelstyle{#2}%
+ \if \italicencodingp \aftergroup \/\fi
+ \let \znext}}
+
+\def \zfrelstyle #1{% {\relation}
+ \if \mathmodep
+ \ztoksa = \expandaftertwice{\zfmat\math#1}%
+ \expandafter\ifx \the\ztoksa\relax
+ \zfnorelstyle{math}{#1}%
+ \fi
+ \else
+ \ztoksa = \expandafterthrice{\expandafter\zfmat\the\typestyle#1}%
+ \expandafter\ifx \the\ztoksa\relax
+ \zfnorelstyle{\the\typestyle}{#1}%
+ \fi
+ \fi
+ \the\ztoksa}
+
+\def \zfnorelstyle #1#2{%
+ \error{norelstyle}
+ {The current `#1' style has no related style for `\string#2'}}
+
+% Font Definition
+% ---- ----------
+
+
+\setlist \ztfmlist = {}%
+
+
+\def \definefont #1#2{% {\name}{tfm at size}
+ \global\font #1 = #2\relax
+ \zregistertfm #2\zmark
+ \if \zcommonencoding
+ \if \andp{\dimposp{\fontdimen7#1}}{\dimlssp{\fontdimen7#1}{.1pt}}%
+ \fontdimen7#1 = \fontdimen2#1\relax % Unlock it.
+ \else\if \dimeqlp{\fontdimen7#1}{\fontdimen2#1}
+ \relax % Already unlocked.
+ \else
+ \error{lockedfont}{The TFM for font `#2' is locked}%
+ \fi\fi
+ \fi}
+
+\def \zregistertfm #1 #2\zmark{% tfm at size\zmark
+ \member{\ztfmreg}{#1}{\ztfmlist}%
+ \if \notp{\ztfmreg}\append{#1}{\ztfmlist}\fi}
+
+\def \fontinterwordspacing #1#2{% {font}{factor}
+ \fontdimen2#1= #2\fontdimen2#1%
+ \fontdimen3#1= #2\fontdimen3#1%
+ \fontdimen4#1= #2\fontdimen4#1%
+ \fontdimen7#1= #2\fontdimen7#1}
+
+% Font Selection
+% ---- ---------
+
+
+\definetoks{\typesizename} % Current type size name.
+\definedimen{\typesize}{0pt} % Current type size in points.
+\definetoks{\typestyle} % Current type style.
+\definecount{\typeencoding}{0} % Current type encoding.
+
+
+% Equal signs and by's have been omitted for the sake of efficiency.
+
+\def \setfont #1#2#3{% {\size}{\style}{\font}
+ \setfontmath{#1}{#2}{#3}{\nullfont}{\nullfont}}
+
+\def \setfontmath #1#2#3#4#5{% {\size}{\style}{\text}{\script}{\scriptscript}
+ \edef \zfam {\zffam{#2}}%
+ \zfwithmat{\xdef}{#1}{#2}{%
+ \textfont \zfam #3%
+ \scriptfont \zfam #4%
+ \scriptscriptfont \zfam #5%
+ \def \noexpand#2{%
+ \typestyle {\noexpand#2}%
+ \typeencoding \zfmat{#2}{\zen}%
+ #3%
+ \fam \zfam}}%
+ \zfbldsize{#1}%
+ \zfaddfont{#2}{#3}%
+ \zfaddfont{#2}{#4}%
+ \zfaddfont{#2}{#5}}
+
+\def \zfbldsize #1{% {\size}
+ {\gdef #1{}
+ \maplist{\zfaddstyle{#1}{##1}}{\zfstylelist}%
+ \ztoksa \expandafter{#1}%
+ \xdef #1{%
+ \typesizename {\noexpand#1}%
+ \typesize \zfmat{#1}{\zsz}%
+ \the\ztoksa
+ \setbox\strutbox \hbox{\vrule \zfmat{#1}{\zst} width 0pt}%
+ \normalbaselineskip \ht\strutbox
+ \advance \normalbaselineskip \dp\strutbox
+ \noexpand\normalbaselines
+ \typestyle {none}\nullfont \fam -1\relax}}}
+
+\def \zfaddstyle #1#2{% {\size}{\style}
+ \ztoksa \expandafter{#1}%
+ \ztoksb \expandaftertwice{\zfmat{#1}{#2}}%
+ \expandafter\ifx \the\ztoksb\relax
+ \xdef #1{\the\ztoksa
+ \noexpand\zclearfam{\zffam{#2}}%
+ \def \noexpand#2{\noexpand\zfundef{\noexpand#1}{\noexpand#2}}}%
+ \else
+ \xdef #1{\the\ztoksa \the\ztoksb}%
+ \fi}
+
+\def \zfaddfont #1#2{% {\style}{font}
+ \zfwithmat{\appendlf}{#1}{\zfl}{#2}}
+
+
+% This macro clears out a family so TeX can't set math in it.
+
+\def \zclearfam #1{% {family}
+ \textfont #1 \nullfont
+ \scriptfont #1 \nullfont
+ \scriptscriptfont #1 \nullfont}
+
+% This macro is called if the user selects a type style that has no font
+% in the current size.
+
+\def \zfundef #1#2{% {\size}{\style}
+ \error{nofontset}
+ {No font has been set for size `\string#1' style `\string#2'}}
+
+% Miscellaneous
+% -------------
+
+
+% The following definition allows the user to write:
+% \withfont{\bf Hi there}
+
+\let \withfont = \relax
+
+% This macro helps with defining math fonts.
+
+\def \definemathfonts #1#2#3#4#5#6{% {prefix}{rm-font}{mit}{msy}{mex}{size}
+ \edef \znext {%
+ \noexpand\definefont{\name{#1rm}}{#2 at #6}%
+ \noexpand\definefont{\name{#1mit}}{#3 at #6}%
+ \noexpand\definefont{\name{#1msy}}{#4 at #6}%
+ \noexpand\definefont{\name{#1mex}}{#5 at #6}}%
+ \znext}
+
+% This macro helps with setting math fonts.
+
+\def \setmathfonts #1#2#3#4{% {\size}{\text}{\script}{\scriptscript}
+ \edef \znext {%
+ \noexpand\setfontmath{\noexpand#1}{\noexpand\rm}%
+ {\name{#2rm}}{\name{#3rm}}{\name{#4rm}}%
+ \noexpand\setfontmath{\noexpand#1}{\noexpand\mit}%
+ {\name{#2mit}}{\name{#3mit}}{\name{#4mit}}%
+ \noexpand\setfontmath{\noexpand#1}{\noexpand\msy}%
+ {\name{#2msy}}{\name{#3msy}}{\name{#4msy}}%
+ \noexpand\setfontmath{\noexpand#1}{\noexpand\mex}%
+ {\name{#2mex}}{\name{#2mex}}{\name{#2mex}}}%
+ \znext}
+
+% Measuring Things
+% --------- ------
+
+
+\definebox{\zmeasbox}
+
+
+\def \measureascenderheight #1{% {\dimen}
+ \zsetmeasbox{bdfhijklt}%
+ #1 = \ht\zmeasbox}
+
+\def \measurecapheight #1{% {\dimen}
+ \zsetmeasbox{ABCDEFGHIJKLMNOPQRSTUVWXYZ}%
+ #1 = \ht\zmeasbox}
+
+\def \measuredescenderdepth #1{% {\dimen}
+ \zsetmeasbox{gjpqy}%
+ #1 = \dp\zmeasbox}
+
+\def \measuredigitheight #1{% {\dimen}
+ \zsetmeasbox{0123456789}%
+ #1 = \ht\zmeasbox}
+
+\def \measuredigitwidth #1{% {\dimen}
+ \zsetmeasbox{0}%
+ #1 = \wd\zmeasbox}
+
+\def \measureemwidth #1{% {\dimen}
+ #1 = 1em}
+
+\def \measurespacewidth #1{% {\dimen}
+ #1 = \fontdimen2\font}
+
+\def \measurexheight #1{% {\dimen}
+ #1 = 1ex}
+
+\def \measuretextwidth #1#2{% {\dimen}{text}
+ \zsetmeasbox{#2}%
+ #1 = \wd\zmeasbox}
+
+\def \measuretextheight #1#2{% {\dimen}{text}
+ \zsetmeasbox{#2}%
+ #1 = \ht\zmeasbox}
+
+\def \measuretextdepth #1#2{% {\dimen}{text}
+ \zsetmeasbox{#2}%
+ #1 = \dp\zmeasbox}
+
+\def \zsetmeasbox #1{\setbox\zmeasbox = \hbox{#1}}
+
+\def \definewidthdimen #1#2{% {\dimen}{text}
+ \definedimen{#1}{0pt}%
+ \measuretextwidth{#1}{#2}}
+
+% Utilities
+% ---------
+
+
+\def \zfmat #1#2{% {\size}{\style}
+ \csname zf\expandafter\discardtok \string#1%
+ \expandafter\discardtok \string#2\endcsname}
+
+\def \zfwithmat #1#2#3{% {\command}{\size}{\style}
+ \expandafter#1\csname zf\expandafter\discardtok \string#2%
+ \expandafter\discardtok \string#3\endcsname}
+
+
+\def \zffam #1{% {\style}
+ \csname \expandafter\discardtok \string#1fam\endcsname}
+
+\def \zfwithfam #1#2{% {\command}{\style}
+ \expandafter#1\csname \expandafter\discardtok \string#2fam\endcsname}
+
+% Built-in Styles
+% -------- ------
+
+
+\zremovePlaindef \itfam
+\zremovePlaindef \bffam
+\zremovePlaindef \ttfam
+
+ % Family Name
+\definetypestyle{\rm}{\encoderoman} % 0 RoMan
+\definetypestyle{\mit}{\encodemathitalic} % 1 Math ITalic
+\definetypestyle{\msy}{\encodemathsymbol} % 2 Math SYmbol
+\definetypestyle{\mex}{\encodemathextended} % 3 Math EXtended symbol
+\definetypestyle{\cal}{\encoderoman} % 4 CALigraphic letters
+\definetypestyle{\bbb}{\encoderoman} % 5 BlackBoard Bold
+\definetypestyle{\it}{\encodeitalic} % 6 ITalic
+\definetypestyle{\bf}{\encoderoman} % 7 Bold Face
+\definetypestyle{\bi}{\encodeitalic} % 8 Bold Italic
+\definetypestyle{\tt}{\encodemono} % 9 monospaced (TypewriTer)
+
+% Note: style \math is reserved for math mode.
+
+\definestylerelation{\math}{\bbbold}{\bbb}
+\definestylerelation{\math}{\bold}{\bf}
+\definestylerelation{\rm}{\bold}{\bf}
+\definestylerelation{\it}{\bold}{\bi}
+\definestylerelation{\math}{\callig}{\cal}
+\definestylerelation{\rm}{\callig}{\cal}
+\definestylerelation{\rm}{\emph}{\it}
+\definestylerelation{\it}{\emph}{\rm}
+\definestylerelation{\bf}{\emph}{\bi}
+\definestylerelation{\bi}{\emph}{\bf}
+\definestylerelation{\math}{\fraktur}{\frk}
+\definestylerelation{\tt}{\meta}{\it}
+\definestylerelation{\math}{\roman}{\rm}
+\definestylerelation{\rm}{\roman}{\rm}
+\definestylerelation{\it}{\roman}{\rm}
+\definestylerelation{\bf}{\roman}{\rm}
+\definestylerelation{\tt}{\roman}{\rm}
+\definestylerelation{\rm}{\smallcaps}{\sc}
+
+% We do not define any sizes or fonts. They just take up memory.
+
+% Doodad Font
+% ------ ----
+
+
+\def \zrequiredoodad #1#2{% {\name}{size}
+ \if \undefinedp{\zfdoodad#2}%
+ \withname\definefont {\zfdoodad#2}{zztexorn at #2}%
+ \fi
+ \edef \znext {\let \noexpand#1\name{\zfdoodad#2}}%
+ \znext}
+
+% Font Style Summary
+% ---- ----- -------
+
+
+{\catcode`\_ = \catactive
+
+\gdef \zfontsummary #1{% {font-list?}
+ {\def _{\space}%
+ \writelog{}%
+ \writelog{Type Styles:}%
+ \writelog{}%
+ \writelog{Name_____Math Family}%
+ \writelog{----_____-----------}%
+ \maplist{\zfsone{##1}}{\zfstylelist}%
+ \if #1%
+ \writelog{}%
+ \maplist{\writelog{ZzTeX: Font used: ##1}}{\ztfmlist}%
+ \fi
+ \writelog{}}}
+
+\gdef \zfsone #1{%
+ \tcounta = \name{#1fam}%
+ \writelog{\string #1______%
+ \if \lssp{\tcounta}{10}%
+ _\number\tcounta
+ \else\if \lssp{\tcounta}{15}%
+ \number\tcounta
+ \else
+ ---%
+ \fi\fi}}
+
+}% \catcode
+
+% TFM List File
+% --- ---- ----
+
+
+\definewrite{\ztfmlistfile}
+
+
+\def \zopentfmlist {%
+ \if \zcommonencoding
+ \immediate\openout \ztfmlistfile = tfmlist.zzz\relax
+ \immediate\write \ztfmlistfile {\jobname}%
+ \fi}
+
+\def \zwritetfmlist {%
+ \if \zcommonencoding
+ \maplist{\immediate\write \ztfmlistfile {##1}}{\ztfmlist}%
+ \immediate\closeout \ztfmlistfile
+ \fi}
diff --git a/macros/plain/contrib/zztex/tex/zzfront.tex b/macros/plain/contrib/zztex/tex/zzfront.tex
new file mode 100644
index 0000000000..f0f281a9fc
--- /dev/null
+++ b/macros/plain/contrib/zztex/tex/zzfront.tex
@@ -0,0 +1,247 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% Module: ZzTeX Front Matter Facilities
+%
+% Synopsis: This file provides facilities for typesetting the front
+% matter of a book.
+%
+% Author: Paul C. Anagnostopoulos
+% Created: 24 September 1989
+%
+% Copyright 1989--2020 by Paul C. Anagnostopoulos
+% under The MIT License (opensource.org/licenses/MIT)
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% Copyright Page
+% --------- ----
+
+
+\def \copyrightline #1#2{% {year}{publisher}
+ \noindent Copyright \copyright\ #1 by #2\par}
+
+\def \concisecopyrightline #1#2{% {year}{publisher}
+ \noindent \copyright\ #1 by #2\par}
+
+\def \superconcisecopyrightline #1#2{% {year}{publisher}
+ \noindent \copyright\ #1 #2\par}
+
+\def \copyrightnotice {%
+ All rights reserved. No part of this publication may be reproduced,
+ stored in a retrieval system, or transmitted, in any form or by any
+ means, electronic, mechanical, photocopying, recording, or otherwise,
+ without the prior written permission of the publisher.}
+
+
+% We provide a standard text design for the Library of Congress
+% Cataloging-in-Publication data.
+
+\def \textcipdataidesign {%
+ \aboveskip = \noskip
+ \belowskip = \noskip
+ \bodyfont = {}%
+ \setflag \enabletabbing = \false
+ \leftindent = 0pt
+ \parindent = \enclosingparindent
+ \parrag = \enclosingparrag
+ \parskip = 0pt
+ \rightindent = 0pt
+ \setflag \verbatimlines = \true
+ \width = \naturalwidth}
+
+\def \textcipdataiidesign {%
+ \textcipdataidesign}
+
+% Table of Contents Entries
+% ----- -- -------- -------
+
+
+% This macro is used to write a ToC entry in the cross-reference file.
+
+\def \ztocentry #1#2#3#4{% {number}{title}{level}{allow?}
+ {\ztoksa = {#2}%
+ \tcounta = #3\relax
+ \edef \znext {\noexpand\xref{toc}{\noexpand\folio}{#1}{\the\ztoksa}
+ {\the\divisionname,\the\tcounta,%
+ \the\difficulty,\if #41\else 0\fi}}%
+ \znext}}
+
+% This is the public command for writing ToC entries.
+
+\def \tocentry #1#2#3{% {number}{title}{level}
+ \ztocentry{#1}{#2}{#3}{\true}}
+
+% This macro allows the compositor to adjust pages in the ToC.
+
+\setlist \ztocadjlist = {}
+
+\long\def \tocadjustment #1#2#3{% {toc-type}{number}{commands}
+ \append{{#1}{#2}{#3}}{\ztocadjlist}}
+
+% Table of Contents Block
+% ----- -- -------- -----
+
+
+\defineblock{\toc}{\endtoc}{\false}{}
+
+%~block toc Type
+% \abovepenalty = integer % Penalty above text.
+% \aboveskip = glue % Space b/b above text.
+% \belowpenalty = integer % Penalty below text.
+% \belowskip = glue % Space b/b below text.
+% \bodyfont = {\size\style} % Default font for body.
+% \divisions = {...} % List of divisions to include.
+% \foliofont = {\size\style} % Default font for folio.
+% \leftindent = glue % Left indentation.
+% \levels = {...} % List of levels to include.
+% \setflag \minitoc = boolean % Is this a miniToC?
+% \parindent = dimen % Paragraph indentation.
+% \parrag = dimen % Paragraph raggedness.
+% \parskip = glue % Paragraph skip.
+% \rightindent = glue % Right indentation.
+% \tocwidtha = dimen % General width a.
+% \tocwidthb = dimen % General width b.
+% \tocwidthc = dimen % General width c.
+% \width = dimen % Line width
+% \xreffile = {...} % Name of composite xref file to use.
+%~end
+
+\definetoks{\foliofont}
+\definetoks{\levels}
+\definedimen{\tocwidtha}{0pt}
+\definedimen{\tocwidthb}{0pt}
+\definedimen{\tocwidthc}{0pt}
+\definetoks{\xreffile}
+
+\definecount{\prevtocprimarylevel}{-1} % Previous level >= 70.
+
+
+\def \toc #1{% {type}
+ \beginblockscope{toc}%
+ \def \ztoctype {#1}%
+ \global\increment \tocdepth
+ \abovepenalty = \breaknever %~default hard
+ \belowpenalty = \breakbest %~default hard
+ \bodyfont = {}% %~default soft
+ \divisions = {\all}% %~default soft
+ \setflag \minitoc = \false %~default soft
+ \tocwidtha = 0pt %~default soft
+ \tocwidthb = 0pt %~default soft
+ \tocwidthc = 0pt %~default soft
+ \xreffile = {}% %~default hard
+ \processdesign{\toc}{#1}%
+ \global\increment \tocnumber
+ \commalist{\zlevlist}{\the\levels}%
+ \the\bodyfont
+ \tocformat
+ \endtoc}
+
+\def \endtoc {%
+ \endgraf
+ \endtocformat
+ \global\decrement \tocdepth
+ \endblockscope{toc}}
+
+\def \tocformat {%
+ \endgraf
+ \bbskipabove{\abovepenalty}{\aboveskip}%
+ \alterindentation{\leftindent}{\rightindent}%
+ \settextwidth{\width}%
+ \setparrag{\parrag}%
+ \zadjtitle = \if \minitoc \zadjtitleminitoc \else \zadjtitletoc \fi
+ % \adjusttitle should adjust appropriate ToC.
+ \def \zadjloc {\toc}%
+ \if \emptytoksp{\xreffile}%
+ \zxloadcomp{\xrefloadtocmode}%
+ \else
+ \zxloadothercomp{\the\xreffile}{\xrefloadtocmode}%
+ \fi}
+
+\def \endtocformat {%
+ \fakepar % In case the ToC is empty.
+ \setlist \ztocadjlist = {}%
+ \bbskipbelowblock{\belowpenalty}{\belowskip}}
+
+
+% The following macro is called for each entry in the cross-reference file.
+% Each entry must NOT be in a group.
+
+\def \xreftoc #1#2#3#4{%
+ \ifnum \xrefmode=\xrefloadtocmode
+ \xreftocb{#1}{#2}{#3}{#4}%
+ \fi}
+
+\definecount{\ztoclevel}{0}
+
+\def \xreftocb #1#2#3#4{% {page}{number}{title}
+ % {division,level,difficulty,allow}
+ \def \znext ##1,##2,##3,##4,##5\zmark{%
+ \ztoksa={##1}\ztoclevel=##2\difficulty=##3\tcounta=##4\relax}%
+ \znext #4,1,\zmark%
+ \if \posp{\tcounta}%
+ \edef \znext {\noexpand\inclusionlist\noexpand\ztoctest
+ {\the\ztoksa}{\the\divisions}}%
+ \znext
+ \if \ztoctest
+ \ztesttoclev{\ztoclevel}%
+ \if \ztoctest
+ \zchktocadj{#2}{#3}%
+ \the\bodyfont
+ \name{\toc\ztoctype\romannumeral\ztoclevel format}{#1}{#2}{#3}%
+ \if \gtrp{\ztoclevel}{69}%
+ \prevtocprimarylevel = \ztoclevel % Save ToC level.
+ \global\authortext = {}% % Clear author text.
+ \fi
+ \fi
+ \fi
+ \fi}
+
+\def \ztesttoclev #1{% {level}
+ \setflag \ztoctest = \false
+ \maplist{\ztesttoca{#1}##1-\zmark}{\zlevlist}}
+
+\def \ztesttoca #1#2-#3\zmark{% {n}low-high\zmark
+ \if \emptyargp{#3}%
+ \setflag \ztoctest = {\eqlp{#1}{#2}}%
+ \else
+ \ztesttocb{#1}{#2}#3%
+ \fi
+ \if \ztoctest \exitmaplist \fi}
+
+\def \ztesttocb #1#2#3-{% {n}{low}high-
+ \setflag \ztoctest = {\andp{\notp{\lssp{#1}{#2}}}
+ {\notp{\gtrp{#1}{#3}}}}}
+
+\long\def \zchktocadj #1#2{% {number}{title}
+ \maplist{\zchktocadjb##1{#1}{#2}}{\ztocadjlist}}
+
+\long\def \zchktocadjb #1#2#3#4#5{% {type}{number}{commands}{number}{title}
+ {\stringeql{\znext}{#1}{\ztoctype}%
+ \if \znext
+ \stringeql{\znext}{#2}{#4}%
+ \if \znext
+ #3\relax
+ \else
+ \def \tempa {#2}% % Don't expand titles.
+ \def \tempb {#5}%
+ \if \tokeqlp{\tempa}{\tempb}%
+ #3\relax
+ \fi
+ \fi
+ \fi}}
+
+\def \bbskipabovetochead #1#2#3#4#5{% {level}{penalty}{skip}{penalty}{skip}
+ \if \eqlp{\prevtocprimarylevel}{#1}%
+ \bbskipabove{#2}{#3}%
+ \else
+ \bbskipabove{#4}{#5}%
+ \fi}
+
+\definetoks{\zdelaytoc}
+
+\def \delaytocformatter #1{%
+ \global\zdelaytoc = \expandafter{\the\zdelaytoc #1}}
+
+\def \dodelayedtocformatter {%
+ \the\zdelaytoc
+ \global\zdelaytoc = {}}
diff --git a/macros/plain/contrib/zztex/tex/zzhelp.tex b/macros/plain/contrib/zztex/tex/zzhelp.tex
new file mode 100644
index 0000000000..6d947fbf6b
--- /dev/null
+++ b/macros/plain/contrib/zztex/tex/zzhelp.tex
@@ -0,0 +1,359 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% Module: ZzTeX Help Text
+%
+% Synopsis: This file contains the help text for each error and
+% warning signaled by ZzTeX.
+%
+% Author: Paul C. Anagnostopoulos
+% Created: 3 July 1990
+%
+% Copyright 1989--2020 by Paul C. Anagnostopoulos
+% under The MIT License (opensource.org/licenses/MIT)
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+\long\def \definehelp #1#2{% {help-id}{text}
+ \withname\gdef{\=zH:#1}{#2}}
+
+
+\definehelp{adjheads}{
+ You must eliminate the inter-row space between two adjacent rows_
+ of column heads. This is done with the \closeuprows command.}
+
+\definehelp{altinv}{
+ The design alternative named above was specified with an_
+ invalid value in a \designalternative command.}
+
+\definehelp{altreq}{
+ The design alternative named above must be specifed with a_
+ \designalternative command preceding the \loaddesign in_
+ your root file. There is no default.}
+
+\definehelp{artpos}{
+ The \art command is in the wrong position relative to the_
+ \caption command.}
+
+\definehelp{blkcantnest}{
+ The file contains an occurence of the first block mentioned above_
+ nested inside the second block. This is not allowed.}
+
+\definehelp{blkinvnest}{
+ A command to end a block is not properly associated with the command_
+ to begin the block. For example, an \endtext is matched with a \list._
+ All blocks must be properly nested.}
+
+\definehelp{blkmustend}{
+ The file contains an occurence of the block ending command_
+ mentioned first, but it is not preceded by the block starting_
+ command mentioned second. Each block must have a starting command.}
+
+\definehelp{blkmustnest}{
+ The file contains an occurence of the first block mentioned above,_
+ but it is not nested inside the second block. The first block_
+ must be nested in the second.}
+
+\definehelp{cananchor}{
+ The object anchor specified mentioned above is invalid._
+ Valid anchors are 'a' -- 'h'.}
+
+\definehelp{celldecpt}{
+ The picutre for this decimal-aligned cell did not include a decimal_
+ point, but the number to be typeset does. You must include a_
+ decimal point in the template or remove it from the number.}
+
+\definehelp{citelet}{
+ It appears that you have used \let to define a \citexxx command_
+ in the design file. This done not work; use \def instead.}
+
+\definehelp{desjunk}{
+ The design file named above contains some paragraph (horizontal mode)_
+ text that should not be there.__
+ You probably left a percent sign off a comment.}
+
+\definehelp{divnotexist}{
+ The division specified in the message is not included with a_
+ \division command in the root file.}
+
+\definehelp{dupart}{
+ The art file named above is used more than once in the book.__
+ If a figure really is used more than once, you must copy it with
+ another name and change one of the \art commands.}
+
+\definehelp{dupreg}{
+ The register named above has already been defined with another_
+ \definexxx command.}
+
+\definehelp{divortah}{
+ The \overridetextareaheight command has been used to override the_
+ text area height, but the override crosses from one division to the next.__
+ If you continue from the warning, the override will be cancelled.}
+
+\definehelp{empshape}{
+ The \shapepar command must be specified with at least one pair of_
+ indent/width arguments. You have specified one with no arguments.}
+
+\definehelp{hereonlybot}{
+ ZzTeX cannot position the float `here' because there is already_
+ a float positioned at the bottom of the page. Floats must be_
+ positioned in order.}
+
+\definehelp{invindexlvl}{
+ The level specified in an indexing command must be 1, 2, or 3.}
+
+\definehelp{invoper}{
+ The operator shown above is not valid in the expression argument_
+ of the \calculate command.}
+
+\definehelp{invsubpart}{
+ The subpart argument to \markinfo(upcased) must be 1 or 2._
+ You have specified the invalid subpart number shown above.}
+
+\definehelp{locattr}{
+ The attributes of the index locator are not valid. You must specify_
+ at least one of \page or \text.}
+
+\definehelp{missbb}{
+ The specified art file does not have a bounding box comment, so_
+ ZzTeX cannot determine the size of the art.}
+
+\definehelp{misset}{
+ A tabular column template must begin with \set, so that the column
+ type will be correctly interpreted.}
+
+\definehelp{misstah}{
+ The value of \textareaheight must be established by the document_
+ design macro before \calculatetypeareaheight can be used.__
+ You can set it directly or calculate it with \calculatetextareaheight.}
+
+\definehelp{misstopskip}{
+ The value of \topskip must be established by the document design_
+ macro before \calculatetextareaheight can be used.}
+
+\definehelp{misstrim}{
+ The values of \trimwidth and \trimheight must be established by the_
+ document design macro before \calculateoffsets can be used}
+
+\definehelp{needheads}{
+ The \tabheadrule and \skipbelowcolhead commands require that the_
+ previous row is a row of heads.}
+
+\definehelp{negtabvsp}{
+ A negative \tabvspace will not work; it produces no spacing at all._
+ You must use \tabcloseup.}
+
+\definehelp{noartfile}{
+ You have requested the art file named above for an \art block,_
+ but the file does not exist.__
+ If you continue from this warning, the art space will be framed_
+ with corner marks and contain the name of the missing file.}
+
+\definehelp{nobblfile}{
+ You have requested a bibliography list with the \biblio command,_
+ but there is no bibliography item file.__
+ If you continue from this warning, the bibliography list will not_
+ be typeset. You must first run BibTeX to produce the item file.}
+
+\definehelp{nodesfile}{
+ The design file named above is required for this book, but it_
+ does not exist.__
+ You may have misspelled the name of the design file in the_
+ \loaddesign command. If not, the design file must be created.}
+
+\definehelp{nodesign}{
+ The file contains a use of the block named above, but the_
+ book's design file does not contain a design macro_
+ for the block.__
+ It's possible you have misspelled the name of the block_
+ or its type (if any). If not, a design macro must be_
+ added to the design file.}
+
+\definehelp{nodivs}{
+ The \setdivisions command must specify one or more divisions to set.}
+
+\definehelp{noend}{
+ Do not use the \end command in ZzTeX. The root file is terminated_
+ with the \enddocument command.__
+ If you are trying to end a block, such as a \list block, you must_
+ use the corresponding ending command, such as \endlist.}
+
+\definehelp{nofloatpos}{
+ The \position parameter for a float does not specify any_
+ page positions for the float. The page positions are \alone,_
+ \bottom, \here, \separate, and \top. Without a page_
+ position, the float cannot be placed on the page.__
+ This error could be due to a missing position in the design file._
+ Or, you may have specified the \position parameter in a \with_
+ command on the float block and forgotten to include any of the_
+ page positions.__
+ If you continue, the float will be placed alone on a page. This_
+ message may appear again for the same float.}
+
+\definehelp{nofontset}{
+ The file has requested a font of the size and style mentioned above._
+ No font has been set for this size/style in the book's design file.__
+ You may have misspelled the name of the size or style. If not,_
+ the appropriate font must be established in the design file.}
+
+\definehelp{noheadfoot}{
+ The design file does not contain a definition for the header_
+ or footer format specified in the message. These definitions_
+ must be included in the design file.}
+
+\definehelp{noinclfile}{
+ The file mentioned above has been requested with an \include or_
+ \division command, but it does not exist.__
+ You may have misspelled the name of the file. If not, you must_
+ create it before processing the book again.__
+ If you continue from this error, ZzTeX will prompt you for another_
+ file name.}
+
+\definehelp{nomarks}{
+ The \markinfo command is being used to format a running head_
+ or foot, but no mark information has been provided for the_
+ current page.__
+ This only happens at the beginning of a book, before the first_
+ chapter or quasichapter. You may have set running heads and_
+ feet with \setrunners before the first chapter or quasichapter.}
+
+\definehelp{nomnpos}{
+ The \position parameter for a margin note does not specify any_
+ horizontal position for the float. The positions are \leftmargin,_
+ \rightmargin, and \outsidemargin.}
+
+\definehelp{noreftitle}{
+ The use of the \reftitle command has been disabled in the_
+ design file with the \allowreftitle document parameter.__
+ If you did not intend to use the \reftitle command, you must_
+ remove it from the file. If you need to use it, then modify_
+ the design file appropriately.}
+
+\definehelp{noregsleft}{
+ All of the available registers of the type specified in the_
+ message have been allocated for use, but a request for another_
+ such register has been made.}
+
+\definehelp{norelstyle}{
+ You have requested a type style related to the current style,_
+ but no such relation has been established. For example, the_
+ current style is \tt and you want to emphasize text with the_
+ \emph command, but no style for emphasizing monospaced text_
+ has been established.__
+ Use the \definestylerelation command to establish the appropriate_
+ relationship.}
+
+\definehelp{notaginfo}{
+ A \tag command has been specified in the current block, but_
+ the composite number and title has not been established yet.}
+
+\definehelp{notindexing}{
+ ZzTeX has encountered an indexing command (e.g., \xpage), but_
+ you have not included a \produceindex command in the root file._
+ At least one \produceindex command is required if the files contain_
+ indexing commands.__
+ If you continue from the warning, the index entries will be written_
+ to the log file.}
+
+\definehelp{notps}{
+ The feature show above is only available when you are producing_
+ PostScript output. It requires PostScript capabilities.}
+
+\definehelp{nowith}{
+ The \with modifier is not allowed on the command specified in the_
+ message. You must remove the \with modifier.__
+ If you continue from this warning, the \with will be ignored._
+ If you used \with on an \item command, use it on the \list_
+ command instead (it will apply to the entire list).}
+
+\definehelp{obsolete}{
+ The command named above is obsolete in this version of ZzTeX.}
+
+\definehelp{openblock}{
+ One or more blocks are in progress at the end of a chapter,_
+ appendix, or quasichapter. The names of the blocks are listed_
+ in messages preceding this warning.__
+ The problem is caused by missing \endxxx commands. For example,_
+ you have coded a list but forgotten the \endlist command. You_
+ will probably see the message `(\end occurred inside a group at_
+ level 1)' at the end of the log.}
+
+\definehelp{overortah}{
+ The \overridetextareaheight command has been used to override the_
+ text area height, but a previous override is still in progress.__
+ If you continue from the warning, the first command will be cancelled_
+ and the second one will take effect. However, the height of the current_
+ page may be incorrect.}
+
+\definehelp{pagepar}{
+ A command has been used to request a page break in the middle of_
+ a paragraph.__
+ You must terminate the paragraph before using the command.}
+
+\definehelp{plaintex}{
+ The Plain TeX command shown below cannot be used in ZzTeX.}
+
+\definehelp{scinmath}{
+ You have tried to use a special character that is not available_
+ in math mode.__
+ If you need it, use it in a \text command.}
+
+\definehelp{setminus}{
+ When using the MathTime fonts, it is better to use \setdiff than_
+ \setminus. If you really want to use \setminus, you will need_
+ to define it in the design file.}
+
+\definehelp{spectah}{
+ The design spec's text area height, as specified by \spectextareaheight,_
+ differs from the calculated text area height by more than 3 points._
+ You should contact the designer about this.}
+
+\definehelp{skipab}{
+ A sequence of elements in the book has resulted in a request_
+ for a `skip below an element' followed immediately by a_
+ `skip above an element'. Such a sequence is invalid.__
+ There is probably an error in the design file.}
+
+\definehelp{toomanyflt}{
+ There are more than the specified number of floats pending for_
+ page makeup. A float is pending for makeup when it has been_
+ encountered in a file but not yet placed on a page of the book.__
+ You must reorganize the file so that the floats are more spread_
+ out in the text, this giving ZzTeX an opportunity to place the_
+ floats on pages as soon as they are encountered.}
+
+\definehelp{undefat}{
+ The atsign command sequence specified above has not been defined_
+ in this block. It must be defined before you can use it.__
+ Use the \defineatsigncommand command to define the command.}
+
+\definehelp{undefflt}{
+ The float type specified above has not been defined. It must be_
+ defined before you can use it.__
+ Use the \definefloattype command to define the float.}
+
+\definehelp{unimpl}{
+ The ZzTeX feature mentioned above is not yet implemented.__
+ Please contact Windfall Software if you need the feature.}
+
+\definehelp{lockedfont}{
+ The font specified above is locked, which means it was not correctly_
+ installed with ZzTFM.__
+ Please contact Windfall Software to determine a remedy.}
+
+\definehelp{varmod}{
+ A variant definition must include between 1 and 8 modifier commands.__
+ Modifier commands are specified as a comma-separated list in the third_
+ argument to \definevariant.}
+
+\definehelp{xtran}{
+ An error flag from the XTran H converter is still present in this_
+ file. The flag message is shown in the above error message.__
+ You should fix the error flagged by XTran and remove the flag_
+ message from the source file.}
+
+\definehelp{zztran}{
+ An error flag from the ZzTran converter is still present in this_
+ file. The flag message is shown in the above error message.__
+ You should fix the error flagged by ZzTran and remove the flag_
+ message from the source file.} \ No newline at end of file
diff --git a/macros/plain/contrib/zztex/tex/zzhmode.tex b/macros/plain/contrib/zztex/tex/zzhmode.tex
new file mode 100644
index 0000000000..8e9553e8ac
--- /dev/null
+++ b/macros/plain/contrib/zztex/tex/zzhmode.tex
@@ -0,0 +1,924 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% Module: ZzTeX Horizontal Mode Facilities
+%
+% Synopsis: This module provides various facilities that operate in
+% horizontal mode, within a paragraph. See also ZZHMODEB.
+%
+% Author: Paul C. Anagnostopoulos
+% Created: 21 September 1989
+%
+% Copyright 1989--2020 by Paul C. Anagnostopoulos
+% under The MIT License (opensource.org/licenses/MIT)
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% Starting Paragraphs
+% -------- ----------
+
+
+% The following token register is executed at the beginning of
+% every paragraph.
+
+\definetoks{\everyparagraph}
+\everyparagraph = {}
+
+% This is what we have to do at the beginning of every paragraph:
+
+\everypar = {\requiredeverypar \the\everyparagraph}
+
+% The following command ensures that we are in horizontal mode,
+% without doing anything if we already are.
+
+\def \ensurepar {\unhbox \voidbox}
+
+% The following command fakes up the start of a paragraph while
+% leaving us in vertical mode.
+
+\def \fakepar {%
+ \endgraf
+ \vspace{\parskip}%
+ \requiredeverypar}
+
+% Paragraph Penalties
+% --------- ---------
+
+
+\definecount{\zclubsv}{-100000} % Overridden \clubpenalty.
+\definecount{\zclubct}{1} % Overridden paragraph count.
+
+
+\def \overrideclubpenalty #1{% {penalty}
+ \if \eqlp{\zclubsv}{-100000}\global\zclubsv = \clubpenalty \fi
+ \global\clubpenalty = #1\relax
+ \global\zclubct = \if \vmodep -1\else 0\fi \relax}
+
+\declareeverypar{\zclubpar}
+
+\def \zclubpar {%
+ \ifnum \zclubct=0
+ \global\clubpenalty=\zclubsv
+ \global\zclubsv=-100000\relax
+ \fi
+ \global\advance \zclubct 1\relax}
+
+% Single-Character Commands
+% ---------------- --------
+
+
+% Name Description
+
+% \<space> Control space
+% \! Negative sixth space; negative thin space in math;
+% callout in code
+% \" Dieresis (umlaut) accent
+% \# Pound sign
+% \$ Dollar sign
+% \% Percent sign
+% \& Ampersand
+% \' Acute accent
+% \( (reserved
+% \) for user)
+% \* \discretionary{}{}{}
+% \+ Hair space
+% \, Sixth space; thin space in math
+% \- Discretionary hyphen
+% \. Dot accent
+% \/ Italic correction
+% \0 \phantom{0}
+% \1 -- \9 (reserved for user)
+% \: List element separator
+% \; Third space; thick space in math
+% \< (reserved for user)
+% \= Macron accent; prefix for tag namespace
+% \> (reserved for user)
+% \? (reserved for user)
+% \@ At-sign
+% \H Hungarian umlaut accent
+% \L Polish suppressed L
+% \O Scandinavian O slash
+% \P Paragraph sign (pilcrow)
+% \S Section sign
+% \[ (reserved for user)
+% \\ Backslash
+% \] (reserved for user)
+% \^ Circumflex accent
+% \_ Underscore
+% \` Grave accent
+% \b Bar-under accent
+% \c Cedilla accent
+% \d Dot-under accent
+% \g Ogonek accent
+% \h Small horizontal space
+% \i Dotless i
+% \j Dotless j
+% \l Polish suppressed l
+% \o Scandinavian o slash
+% \r ring accent
+% \t Tie-after accent
+% \u Breve accent
+% \v Hacek accent
+% \x \
+% \y } (reserved for user, for index command abbreviations)
+% \z /
+% \{ Left brace
+% \| Vertical bar; \Vert in math mode
+% \} Right brace
+% \~ Tilde accent
+
+% Characters
+% ----------
+
+
+% These definitions are in alphabetical order.
+
+\def \AA {% %~ Ring A (Angstrom). %^named_char
+ \ensurepar
+ \if \mathmodep
+ \mtext{\AA}%
+ \else
+ \r{A}%
+ \fi}
+
+\def \aa {% %~ Ring a. %^named_char
+ \ensurepar
+ \if \mathmodep
+ \mtext{\aa}%
+ \else
+ \r{a}%
+ \fi}
+
+\chardef \AE = "1D %~ Scandinavian AE.
+
+\chardef \ae = "1A %~ Scandinavian ae.
+
+\chardef \ampersand = `\& %~ Ampersand.
+
+\let \& = \ampersand
+
+\chardef \atsign = `\@ %~ At sign.
+
+\let \@ = \atsign
+
+\def \backslash {% %~ Backslash. %^named_char
+ \ensurepar
+ \if \mathmodep
+ \zmbackslash
+ \else \if \monoencodingp
+ \char "5C\relax
+ \else
+ \PSbackslash
+ \fi\fi}
+
+\let \\=\backslash
+
+\def \baselinebullet #1{% {size} %~ Bullet set on baseline.
+ \zrequiredoodad{\zdoodadfont}{#1}%
+ \hbox{\zdoodadfont .}}
+
+\def \bullet {% %~ Bullet. %^named_char
+ \ensurepar
+ \if \mathmodep
+ \zmbullet
+ \else
+ \PSbullet
+ \fi}
+
+\def \cent {% %~ Cent sign. %^named_char
+ \ensurepar
+ \PScent}
+
+\let \cents = \cent
+
+\def \copyright {% %~ Copyright symbol. %^named_char
+ \ensurepar
+ \PScopyright}
+
+\def \cdquote {''} %~ Close double quote. %^named_char
+
+\def \dagger {% %~ Dagger. %^named_char
+ \ensurepar
+ \if \mathmodep
+ \zmdagger
+ \else
+ \PSdagger
+ \fi}
+
+\def \ddagger {% %~ Double dagger. %^named_char
+ \ensurepar
+ \if \mathmodep
+ \zmddagger
+ \else
+ \PSddagger
+ \fi}
+
+\def \dollar {% %~ Dollar sign. %^named_char
+ \zprehyph{\dollarhyph}%
+ \if \monoencodingp
+ \char "24\relax
+ \else
+ \PSdollar
+ \fi
+ \zposthyph{\dollarhyph}}
+
+\let \$ = \dollar
+
+\def \ellipsis {% %~ Text ellipsis.
+ \if \mathmodep
+ \ldots
+ \else
+ \unbreakable\thickspace
+ .\unbreakable\thickspace
+ .\unbreakable\thickspace
+ .\thickspace
+ \ignorespaces
+ \fi}
+
+\def \emdash {---} %~ Em dash. %^named_char
+
+\def \endash {--} %~ En dash. %^named_char
+
+\def \greater {% %~ Greater-than sign %^named_char
+ \ensurepar
+ \if \monoencodingp
+ \char "3E\relax
+ \else
+ \PSgreater
+ \fi}
+
+\def \>{% %~ Greater-than sign. %^named_char
+ \relax
+ \if \mathmodep \plainerror \else \greater \fi}
+
+\chardef \hash = `\# %~ Pound sign, hash, octothorpe.
+
+\let \# = \hash
+
+\def \hat {% %~ Hat symbol. %^named_char
+ \ensurepar
+ \if \mathmodep
+ \zmhat
+ \else
+ \char "5E\relax
+ \fi}
+
+\chardef \i = "10 %~ Dotless i.
+
+\chardef \j = "11 %~ Dotless j.
+
+\def \L {\PSpolishL} %~ Uppercase Polish L. %^named_char
+
+\def \l {\PSpolishl} %~ Lowercase Polish l. %^named_char
+
+% \lbrace and \rbrace cannot start with \ensurepar, because that won't
+% work following a \left or \right command. However, the \relax is required.
+
+\def \lbrace {% %~ Left brace. %^named_char
+ \relax
+ \if \mathmodep
+ \zmlbrace
+ \else \if \monoencodingp
+ \char "7B\relax
+ \else
+ \PSbraceleft
+ \fi\fi}
+
+\let \{ = \lbrace
+
+\def \less {% %~ Less-than sign. %^named_char
+ \ensurepar
+ \if \monoencodingp
+ \char "3C\relax
+ \else
+ \PSless
+ \fi}
+
+\let \< = \less
+
+\chardef \O = "1F %~ Slashed O.
+
+\chardef \o = "1C %~ Slashed o.
+
+\chardef \OE = "1E %~ OE diphthong.
+
+\chardef \oe = "1B %~ oe diphthong.
+
+\def \odquote {``} %~ Open double quote. %^named_char
+
+\def \P {% %~ Paragraph symbol (pilcrow). %^named_char
+ \ensurepar
+ \PSparagraph}
+
+\chardef \percent = `\% %~ Percent sign.
+
+\let \% = \percent
+
+\def \perthousand {% %~ Per thousand symbol. %^named_char
+ \ensurepar
+ \PSperthousand}
+
+\def \prellipsis {% %~ Text ellipsis with no left space.
+ .\unbreakable\thickspace
+ .\unbreakable\thickspace
+ .\thickspace
+ \ignorespaces}
+
+\def \rbrace {% %~ Right brace. %^named_char
+ \relax
+ \if \mathmodep
+ \zmrbrace
+ \else \if \monoencodingp
+ \char "7D\relax
+ \else
+ \PSbraceright
+ \fi\fi}
+
+\let \} = \rbrace
+
+\def \registered {% %~ Registered symbol. %^named_char
+ \ensurepar
+ \PSregistered}
+
+\def \S {% %~ Section sign. %^named_char
+ \ensurepar
+ \PSsection}
+
+\def \SS {% %~ Double section sign. %^named_char
+ \ensurepar
+ \PSsection\PSsection}
+
+\chardef \ss = "19 %~ German eszett.
+
+\def \sterling {% %~ Pound sterling symbol. %^named_char
+ \ensurepar
+ \PSsterling}
+
+\def \tilde {% %~ Tilde. %^named_char
+ \ensurepar
+ \if \mathmodep
+ \zmtilde
+ \else
+ \char "7E\relax
+ \fi}
+
+\def \trademark {% %~ Trademark symbol. %^named_char
+ \ensurepar
+ \PStrademark}
+
+\def \underscore {% %~ Underscore. %^named_char
+ \ensurepar
+ \zprehyph{\underscorehyph}%
+ \if \monoencodingp
+ \char "5F\relax
+ \else
+ \PSunderscore
+ \fi
+ \zposthyph{\underscorehyph}}
+
+\let \_ = \underscore
+
+\def \udquote {% %~ Undirected double quote. %^named_char
+ \ensurepar
+ \if \monoencodingp
+ \char "22\relax
+ \else
+ \PSudquote
+ \fi}
+
+\def \usquote {% %~ Undirected single quote. %^named_char
+ \ensurepar
+ \if \monoencodingp
+ \char "0D\relax
+ \else
+ \PSusquote
+ \fi}
+
+\def \verticalbar {% %~ Vertical bar. %^named_char
+ \ensurepar
+ \if \monoencodingp
+ \char "7C\relax
+ \else
+ \PSbar
+ \fi}
+
+\def \|{% %~ Vertical bar. %^named_char
+ \relax
+ \if \mathmodep \Vert \else \verticalbar \fi}
+
+% Accents
+% -------
+
+
+\def \"#1{{\accent "7F #1}} %~ Umlaut accent. %^accent
+
+\def \'#1{{\accent 19 #1}} %~ Acute accent. %^accent
+
+\def \.#1{{\accent 95 #1}} %~ Dot accent. %^accent
+
+\def \=#1{{\accent 22 #1}} %~ Macron accent. %^accent
+
+\def \^#1{{\accent 94 #1}} %~ Circumflex accent. %^accent
+
+\def \`#1{{\accent 18 #1}} %~ Grave accent. %^accent
+
+\def \~#1{{\accent "7E #1}} %~ Tilde accent. %^accent
+
+\def \b #1{% %~ Bar-under accent. %^accent
+ \ozalign{\relax #1\cr
+ \hidewidth \vbox to .2ex {\hbox{\char 22}\vss}\hidewidth}}
+
+\def \c #1{% %~ Cedilla accent. %^accent
+ \setbox \zboxa = \hbox{#1}%
+ \if \dimeqlp{\ht\zboxa}{1ex}%
+ \accent 24 #1%
+ \else
+ {\ooalign{\hidewidth \char 24 \hidewidth \cr
+ \unhbox \zboxa}}%
+ \fi}
+
+\def \d #1{% %~ Dot-under accent. %^accent
+ \ozalign{\relax #1\cr
+ \hidewidth.\hidewidth}}
+
+\def \g #1{% %~ Ogonek accent. %^accent
+ \setbox \zboxa = \hbox{#1}%
+ \if \dimeqlp{\ht\zboxa}{1ex}%
+ \accent 154 #1%
+ \else
+ {\ooalign{\hidewidth \char 154 \hidewidth \cr
+ \unhbox \zboxa}}%
+ \fi}
+
+\def \H #1{{\accent "7D #1}} %~ Long Hungarian umlaut accent. %^accent
+
+\def \r #1{{\accent "17 #1}} %~ Ring accent. %^accent
+
+\def \t #1{% %~ Tie-after accent. %^accent
+ {\edef \znext {\the\font}\the\textfont1 \accent "7F \znext #1}}
+
+\def \u #1{{\accent 21 #1}} %~ Breve accent. %^accent
+
+\def \v #1{{\accent 20 #1}} %~ Hacek accent. %^accent
+
+% Spaces
+% ------
+
+
+% TeX space primitives include the following:
+%
+% <space> Produce a normal space, obeying \spacefactor.
+% \<space> Produce a normal space as if \spacefactor = 1000.
+
+% Here are a set of "space" commands that produce breakable space:
+
+%~ Specified amount of breakable horizontal space.
+
+\def \hspace #1{\ensurepar \hskip #1\relax}% {amount} %^hspace
+
+%~ Specified amount of unbreakable horizontal space
+%~ measured in tenths of a point.
+
+\def \h #1;{% tenths-points; %^hspace
+ {\tdimena = .1pt
+ \tdimena = #1\tdimena
+ \kern \tdimena}}
+
+\def \fiveemspace {\ensurepar \hskip 5em\relax} %~ Breakable 5 em space. %^hspace
+
+\def \fouremspace {\ensurepar \hskip 4em\relax} %~ Breakable 4 em space. %^hspace
+
+\def \threeemspace {\ensurepar \hskip 3em\relax} %~ Breakable 3 em space. %^hspace
+
+\def \twoemspace {\ensurepar \hskip 2em\relax} %~ Breakable 2 em space. %^hspace
+
+\def \emspace {\ensurepar \hskip 1em\relax} %~ Breakable 1 em space. %^hspace
+
+\def \enspace {\ensurepar \hskip .5em\relax} %~ Breakable 1 en space. %^hspace
+
+\def \digitspace {% %~ Breakable digit space. %^hspace
+ {\measuredigitwidth{\tdimena}%
+ \ensurepar \hskip \tdimena}}
+
+{\catcode`\| = \catactive
+\gdef \digitspacebar {%
+ \catcode`\| = \catactive
+ \def |{\digitspace}}
+}
+
+\def \thirdspace {\ensurepar \hskip .333em\relax} %~ Breakable 1/3 em space. %^hspace
+\let \thickspace = \thirdspace
+\def \negthickspace {\ensurepar \hskip -.333em\relax} %~ Breakable negative 1/3 em space. %^hspace
+
+\def \space { } %~ Normal space.
+\def \^^M{\ } %~ Normal space.
+
+\def \fontspace {\ensurepar \hskip \fontdimen2\font} %~ Breakable font space. %^hspace
+
+\def \visiblespace {% %~ Visible space. %^hspace
+ \ensurepar
+ \hbox {%
+ \measurespacewidth{\tdimena}%
+ \kern .16ex
+ \llap{\rule{width .08ex height .15ex depth .2ex}}%
+ \lower .2ex \hbox{\rule{width \tdimena height .08ex depth 0pt}}%
+ \rlap{\rule{width .08ex height .15ex depth .2ex}}%
+ \kern .16ex}}
+
+\def \fourthspace {\ensurepar \hskip .25em\relax} %~ Breakable 1/4 em space. %^hspace
+
+\def \fifthspace {\ensurepar \hskip .2em\relax} %~ Breakable 1/5 em space. %^hspace
+\let \thinspace = \fifthspace
+\def \negfifthspace {\ensurepar \hskip -.2em\relax} %~ Breakable negative 1/3 em space. %^hspace
+\let \negthinspace = \negfifthspace
+
+\def \sixthspace {\ensurepar \hskip .16667em\relax} %~ Breakable 1/6 em space. %^hspace
+\def \negsixthspace {\ensurepar \hskip -.16667em\relax} %~ Breakable negative 1/6 em space. %^hspace
+
+\def \seventhspace {\ensurepar \hskip .14286em\relax} %~ Breakable 1/7 em space. %^hspace
+\let \hairspace = \seventhspace
+\def \negseventhspace {\ensurepar \hskip -.14286em\relax} %~ Breakable negative 1/7 em space. %^hspace
+
+\def \qqqqquad {\unbreakable\fiveemspace} %~ Unbreakable 5 em space. %^hspace
+\def \qqqquad {\unbreakable\fouremspace} %~ Unbreakable 4 em space. %^hspace
+\def \qqquad {\unbreakable\threeemspace} %~ Unbreakable 3 em space. %^hspace
+\def \qquad {\unbreakable\twoemspace} %~ Unbreakable 2 em space. %^hspace
+\def \quad {\unbreakable\emspace} %~ Unbreakable 1 em space. %^hspace
+\def \nut {\unbreakable\enspace} %~ Unbreakable 1 en space. %^hspace
+
+%~ Unbreakable 1/3 em space.
+
+\def \;{\relax\if \mathmodep \mthickspace \else \unbreakable\thickspace \fi} %^hspace
+
+%~ Unbreakable 1/5 em space.
+
+\def \,{\relax\if \mathmodep \mthinspace \else \unbreakable\thinspace \fi} %^hspace
+
+%~ Unbreakable negative 1/5 em space.
+
+\def \!{\relax\if \mathmodep \mnegthinspace \else \unbreakable\negthinspace\fi} %^hspace
+
+\def \+{\unbreakable\hairspace} %~ Unbreakable 1/7 em space. %^hspace
+
+%~ Specified amount of unbreakable horizontal space
+%~ measured in hundredths of an em.
+
+\def \k #1;{% hundredths-em; %^hspace
+ {\tdimena = .01em
+ \tdimena = #1\tdimena
+ \kern \tdimena}}
+
+%~ This command retains horizontal space at the beginning of a line.
+%~ Such space is normally discarded.
+
+\def \retain {\vrule height 0pt depth 0pt width 0pt\relax} %^hspace
+
+%~ This declaration causes spaces to be "obeyed," so that every space
+%~ in the source is relevent.
+
+\def \obeyspaces {%
+ \catcode`\ =\catactive}
+
+{\obeyspaces
+\global\let =\ %
+}
+
+% Space Factors
+% ----- -------
+
+
+% IniTeX sets the space factor code of uppercase letters to 999 so
+% periods after them will not end sentences. That just gives people
+% one more rule to remember.
+
+ \sfcode`\A=1000 \sfcode`\B=1000 \sfcode`\C=1000 \sfcode`\D=1000
+ \sfcode`\E=1000 \sfcode`\F=1000 \sfcode`\G=1000 \sfcode`\H=1000
+ \sfcode`\I=1000 \sfcode`\J=1000 \sfcode`\K=1000 \sfcode`\L=1000
+ \sfcode`\M=1000 \sfcode`\N=1000 \sfcode`\O=1000 \sfcode`\P=1000
+ \sfcode`\Q=1000 \sfcode`\R=1000 \sfcode`\S=1000 \sfcode`\T=1000
+ \sfcode`\U=1000 \sfcode`\V=1000 \sfcode`\W=1000 \sfcode`\X=1000
+ \sfcode`\Y=1000 \sfcode`\Z=1000
+
+% A few characters should not affect the space factor.
+
+ \sfcode`\'=0
+ \sfcode`\)=0
+ \sfcode`\]=0
+
+
+\def \setsentencespacing #1{% {flag}
+ \if #1%
+ \sfcode`\. = 2250
+ \sfcode`\? = 2250
+ \sfcode`\! = 2250
+ \sfcode`\: = 2000
+ \else
+ \sfcode`\. = 1000
+ \sfcode`\? = 1000
+ \sfcode`\! = 1000
+ \sfcode`\: = 1000
+ \fi
+ \relax}
+
+% Numbers
+% -------
+
+
+\let \lcromannumeral = \romannumeral
+
+%~ This command formats an integer as uppercase Roman numerals.
+
+\def \ucromannumeral #1{% {number}
+ \uppercase\expandafter{\romannumeral#1}}
+
+%~ This command formats an integer as lowercase letters.
+
+\def \lcletter #1{% {number}
+ \ifcase #1%
+ 0\or a\or b\or c\or d\or e\or f\or g\or h\or i\or j\or k\or l\or m\or
+ n\or o\or p\or q\or r\or s\or t\or u\or v\or w\or x\or y\or z\else
+ \number#1\fi}
+
+%~ This command formats an integer as uppercase letters.
+
+\def \ucletter #1{% {number}
+ \ifcase #1%
+ 0\or A\or B\or C\or D\or E\or F\or G\or H\or I\or J\or K\or L\or M\or
+ N\or O\or P\or Q\or R\or S\or T\or U\or V\or W\or X\or Y\or Z\else
+ \number#1\fi}
+
+% Lines
+% -----
+
+
+\long\def \line #1{% {text}
+ \if \vmodep
+ {\parfillskip = 0pt
+ \noindent #1\retain \par}%
+ \else
+ \retain #1\tl
+ \fi}
+
+\long\def \leftline #1{\line{#1\hfil}}% {text}
+\long\def \rightline #1{\line{\hfil#1}}% {text}
+\long\def \centerline #1{\line{\hfil#1\hfil}}% {text}
+\long\def \spreadline #1#2{\line{{#1}\hfil{#2}}}% {text1}{text2}
+\long\def \centerspreadline #1#2#3{%
+ \line{\rlap{#1}\hfil #2\hfil \llap{#3}}}% {text1}{text2}{text3}
+
+
+% This declaration causes line breaks to be "obeyed," so that each
+% results in a paragraph end.
+
+{\catcode`\^^M = \catactive%
+\gdef \obeylines {\catcode`\^^M = \active \let ^^M = \par}%
+}
+
+% Line Breaks
+% ---- ------
+
+
+\def \linebreak #1{% {penalty}
+ \penalty #1\relax}
+
+\def \tl {\break}
+
+\def \nl {%
+ \gluevaries{\znlvar}{\leftskip}%
+ \if \znlvar \tl \else \hfil \break \fi}
+
+\def \blankline {\ensurepar \nl}
+
+
+% These commands are used to tie text on one line.
+
+\def ~{\nobreak \ } % Unbreakable space (tie).
+
+\def \tie {\ensurepar \hbox}
+
+% Indentation
+% -----------
+
+
+% Note that this macro just sets \leftskip and \rightskip, and so
+% blows away any \parrag.
+
+\def \setindentation #1#2{% {left}{right}
+ \leftskip = #1\relax
+ \rightskip = #2\relax}
+
+
+\def \alterindentation #1#2{% {left-delta}{right-delta}
+ \leftskip = 1\leftskip
+ \advance \leftskip by #1\relax
+ \rightskip = 1\rightskip
+ \advance \rightskip by #2\relax}
+
+% Text Width
+% ---- -----
+
+
+% This command must be used AFTER the indentation is established with
+% \setindentation or \alterindentation.
+
+\def \settextwidth #1{% {width}
+ \if \dimneqlp{#1}{\naturalwidth}%
+ \hsize = #1\relax
+ \advance \hsize by \leftskip
+ \advance \hsize by \rightskip
+ \fi}
+
+% Paragraph Raggedness
+% --------- ----------
+
+
+% This command must be used AFTER the indentation is established with
+% \setindentation or \alterindentation.
+
+\def \setparrag #1{% {rag-dimen}
+ \gluevaries{\zrsvar}{\rightskip}%
+ \if \notp{\zrsvar}%
+ \tdimena = #1\relax
+ \advance \rightskip by 0pt plus \tdimena\relax
+ \fi}
+
+\zdeclareeveryvcontext{\setindentation{0pt}{0pt}\setparrag{0pt}}
+
+% Paragraph Shapes
+% --------- ------
+
+
+\definecount{\zshparct}{0}
+\definecount{\zshparrep}{0}
+\definedimen{\zshpari}{0pt}
+\definedimen{\zshparw}{0pt}
+
+
+\def \nshapepar #1{% {[*repeat1,]indent1,width1,...}
+ \if \emptyargp{#1}%
+ \error{empshape}{The argument to \string\shapepar cannot be empty}%
+ \fi
+ \gdef \zshpartoks {}%
+ \global\zshparct = 0
+ {\zshapeparc #1,\zmark}%
+ \parshape = \zshparct\zshpartoks\relax}
+
+\def \zshapeparc #1#2,#3\zmark{% [*repeat],indent,...
+ \if \codeeqlp{#1}{*}%
+ \global\zshparrep = #2\relax
+ \def \znext {\zshapepare #3\zmark}%
+ \else
+ \global\zshparrep = 1
+ \def \znext {\zshapepare #1#2,#3\zmark}%
+ \fi
+ \znext}
+
+\def \zshapepare #1,#2,#3\zmark{% indent,width,...
+ \zshapepard #1,\false,\zshpari\zmark
+ \global\zshpari = \tdimena
+ \zshapepard #2,\true,\zshparw\zmark
+ \global\zshparw = \tdimena
+ \loop
+ \if \posp{\zshparrep}%
+ \xdef \zshpartoks {\zshpartoks \space \the\zshpari \space \the\zshparw}%
+ \global\increment \zshparct
+ \global\decrement \zshparrep
+ \repeat
+ \if \emptyargp{#3}%
+ \let \znext = \relax
+ \else
+ \def \znext {\zshapeparc #3\zmark}%
+ \fi
+ \znext}
+
+\def \zshapepard #1#2,#3,#4\zmark{% dimen1 dimen-rest,width?,prev
+ \if \codeeqlp{#1}{+}%
+ \calculate \tdimena = {#4,+,#2}%
+ \else\if \codeeqlp{#1}{-}%
+ \calculate \tdimena = {#4,-,#2}%
+ \else\if \andp{\codeeqlp{#1}{=}}{#3}%
+ \calculate \tdimena = {\hsize,-,\zshpari}%
+ \else
+ \tdimena = #1#2\relax
+ \if \dimeqlp{\tdimena}{\naturalwidth}%
+ \calculate \tdimena = {\hsize,-,\zshpari}%
+ \fi
+ \fi\fi\fi
+ \if #3%
+ %%% Do we want to adjust the width by \leftskip or \rightskip?
+ \fi}
+
+
+%%%\definecount{\zshparct}{0}
+\definedimen{\zshpard}{0pt}
+\definedimen{\zshpare}{0pt}
+
+
+\def \shapepar #1{% {indent1,width1,...}
+ \if \emptyargp{#1}%
+ \error{empshape}{The argument to \string\shapepar cannot be empty}%
+ \fi
+ \gdef \zshpartoks {}%
+ \global\zshparct = 0
+ {\zshapepara #1,\zmark}%
+ \parshape = \zshparct\zshpartoks\relax}
+
+\def \zshapepara #1,#2,#3\zmark{% indent,width,...\zmark
+ \zshpard = #1\relax
+ \xdef \zshpartoks {\zshpartoks \space \the\zshpard}%
+ \zshpare = #2\relax
+ \if \dimeqlp{\zshpare}{\naturalwidth}%
+ \zshpare = \hsize
+ \advance \zshpare by -\zshpard
+ \else
+ \advance \zshpare by \leftskip
+ \advance \zshpare by \rightskip
+ \fi
+ \xdef \zshpartoks {\zshpartoks \space \the\zshpare}%
+ \global\increment \zshparct
+ \if \emptyargp{#3}%
+ \let \znext = \relax
+ \else
+ \def \znext {\zshapepara #3\zmark}%
+ \fi
+ \znext}
+
+
+\def \hangalign #1#2#3{% {indent}{text1}{text2}
+ \endgraf
+ {\setbox \zboxa = \hbox{#2}%
+ \tdimena = \wd\zboxa
+ \advance \tdimena by #1\relax
+ \shapepar{#1,\naturalwidth,\tdimena,\naturalwidth}%
+ \noindent \box\zboxa #3\par}}
+
+\def \hindent #1{% {indent}
+ \noindent \hspace{#1}%
+ \ignorespaces}
+
+% Adjustments
+% -----------
+
+
+%~ This page overrides the number of lines in a paragraph. The argument
+%~ specifies the number of lines and should start with a plus or
+%~ minus sign. TeX does not guarantee the change.
+
+\def \overrideparlength #1{% {lines} %^page_makeup
+ \looseness = #1\relax}
+
+
+%~ This command is used in the middle of a paragraph, on a line by
+%~ itself, to make an adjustment
+%~ between two lines. A typical use is to force a page break:
+%~ \adjustpar{\fullpagebreak}
+%~ There is no need to put a percent sign (|%|) after the command.
+
+\long\def \adjustpar #1{% {command} %^page_makeup
+ \vadjust{#1}%
+ \ignorespaces}
+
+
+% This command is used to adjust the title of a chapter, section, etc.
+% The argument looks like `\loc{commands}\loc{commands}...'
+% where each \loc is:
+% \body To adjust the title in the body of the text.
+% \mark To adjust the title in the mark (running heads and feet).
+% \toc To adjust the title in the table of contents.
+
+\def \zadjloc {\body} % Normally, \adjusttitle should adjust body.
+
+\def \adjusttitle #1{% {\loc{commands}...}
+ {\def \body ##1{}%
+ \def \mark ##1{}%
+ \def \toc ##1{}%
+ \expandafter\let \zadjloc = \zadjtitleb
+ #1}}
+
+\def \zadjtitleb #1{%
+ #1%
+ \def \znext {#1}%
+ \if \tokeqlp{\znext}{\nl}%
+ \let \znext = \ignorespaces
+ \else
+ \let \znext = \relax
+ \fi
+ \znext}
+
+% These macros use \lspspace so they do the right thing while letterspacing.
+
+\def \titlenl {\adjusttitle{\body{\nl}}\lspspace}
+\def \titletl {\adjusttitle{\body{\tl}}\lspspace}
+\def \tocnl {\adjusttitle{\toc{\nl}}\lspspace}
+\def \toctl {\adjusttitle{\toc{\tl}}\lspspace}
+
+
+% These definitions are used by the new title adjustment scheme,
+% but need to be present even when it is not in use.
+
+\chardef \zadjtitlenone = 0
+\chardef \zadjtitlebody = 1
+\chardef \zadjtitlemark = 2
+\chardef \zadjtitletoc = 3
+\chardef \zadjtitleminitoc = 4
+
+\definecount{\zadjtitle}{\zadjtitlebody}
diff --git a/macros/plain/contrib/zztex/tex/zzhmodeb.tex b/macros/plain/contrib/zztex/tex/zzhmodeb.tex
new file mode 100644
index 0000000000..69c92d9c1e
--- /dev/null
+++ b/macros/plain/contrib/zztex/tex/zzhmodeb.tex
@@ -0,0 +1,239 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% Module: ZzTeX Horizontal Mode Facilities
+%
+% Synopsis: This module provides various facilities that operate in
+% horizontal mode, within a paragraph. See also ZZHMODE.
+%
+% Author: Paul C. Anagnostopoulos
+% Created: 11 January 1994
+%
+% Copyright 1989--2020 by Paul C. Anagnostopoulos
+% under The MIT License (opensource.org/licenses/MIT)
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% Basic Tools
+% ----- -----
+
+
+\def \llap #1{\hbox to 0pt{\hss #1}}% {text}
+\def \rlap #1{\hbox to 0pt{#1\hss}}% {text}
+\def \clap #1{\hbox to 0pt{\hss #1\hss}}% {text}
+
+\def \minhbox to #1#2#3#4{% to width{text}{space-in}{space-out}
+ \measuretextwidth{\tdimena}{#2\hspace{#3}}%
+ \if \dimgtrp{\tdimena}{#1}%
+ {#2}\hspace{#4}%
+ \else
+ \hbox to #1{#2\hfil}%
+ \fi}
+
+% Drop Capitals
+% ---- --------
+
+
+\def \dropcapital #1#2#3{% {height}{lines}{text}
+ \setbox \zboxa = \hbox{#3}%
+ \tdimena = \ht\zboxa
+ \advance \tdimena by -#1\relax
+ \setbox \zboxa = \hbox{\lower \tdimena \box\zboxa}%
+ \dp\zboxa = 0pt
+ \def \zdropshape {0pt,\naturalwidth}%
+ \tcounta = #2\relax
+ \loop
+ \decrement \tcounta
+ \if \posp{\tcounta}%
+ \edef \zdropshape {\zdropshape ,\the\wd\zboxa,\naturalwidth}%
+ \repeat
+ \expandafter\shapepar\expandafter{\zdropshape,0pt,\naturalwidth}%
+ \noindent \box\zboxa}
+
+% Enclosing Text
+% --------- ----
+
+
+\def \enclose #1#2#3{% {thickness}{separation}{text}
+ \ensurepar
+ \hbox{\vrule width #1%
+ \vtop{\vbox{\hrule height #1%
+ \kern #2%
+ \hbox{\kern #2#3\kern #2}}%
+ \kern #2%
+ \hrule height #1}%
+ \vrule width #1}}
+
+\def \colorenclose #1#2#3#4{% {color}{thickness}{separation}{text}
+ \ensurepar
+ \hbox{\color{#1}\vrule width #2 \endcolor
+ \vtop{\vbox{\color{#1}\hrule height #2 \endcolor
+ \kern #3%
+ \hbox{\kern #3#4\kern #3}}%
+ \kern #3%
+ \color{#1}\hrule height #2 \endcolor}%
+ \color{#1}\vrule width #2 \endcolor}}
+
+% Fractions
+% ---------
+
+
+% This macro is specifically designed to work in math mode, too.
+
+\def \piecefraction #1{%
+ \ztfrac #1/}
+
+\def \ztfrac #1/#2/{%
+ \ensurepar
+ {\measuretextwidth{\tdimena}{/}%
+ \raise .5ex \hbox{$\scriptstyle #1$}%
+ \kern -.2\tdimena \raise .3ex \hbox{$\scriptstyle /$}\kern -.2\tdimena%
+ \hbox{$\scriptstyle #2$}}}
+
+\let \textfraction = \piecefraction % For compatibility.
+
+% Leaders
+% -------
+
+
+\def \alignedleaders #1{% {box-or-rule}
+ \leaders #1\hfill}
+
+\def \dotleaders {%
+ \alignedleaders{\hbox to 1em{\hss.\hss}}}
+
+\def \ruleleaders #1{% {rule}
+ \alignedleaders{#1}}
+
+\def \centeredleaders #1{% {box-or-rule}
+ \cleaders #1\hfill}
+
+\def \spreadleaders #1{% {box-or-rule}
+ \xleaders #1\hfill}
+
+% Paragraph Dingbats
+% --------- --------
+
+
+\def \pardingbat #1#2{% {space}{dingbat}
+ {\unskip \unbreakable\hfil \allowbreak
+ \hspace{#1}\retain\unbreakable\hfill
+ #2%
+ \finalhyphendemerits = 0 \par}}
+
+% Rules
+% -----
+
+
+\def \rule #1{% {dimensions}
+ \if \vmodep
+ \hrule #1\relax
+ \else
+ \vrule #1\relax
+ \fi}
+
+\def \colorrule #1#2{% {color}{dimensions}
+ \if \vmodep
+ \color{#1}
+ \nobreak
+ \hrule #2\relax
+ \endcolor
+ \else
+ \color{#1}\vrule #2\relax\endcolor
+ \fi}
+
+\def \slug #1#2{% {width}{height}
+ \rule{height #2 depth 0pt width #1}}
+
+% Shapes
+% ------
+
+
+\def \rectangle #1#2#3#4{% {rise}{width}{height}{thickness}
+ {\tdimena = #2\relax
+ \advance \tdimena by -#4\relax
+ \advance \tdimena by -#4\relax
+ \raise #1 \hbox{%
+ \vrule height #3 depth 0pt width #4\relax
+ \vbox to #3{%
+ \hrule height #4 depth 0pt width \tdimena\relax
+ \vfil
+ \hrule height #4 depth 0pt width \tdimena\relax}%
+ \vrule height #3 depth 0pt width #4}}}
+
+% Underlining & Overstriking
+% ----------- - ------------
+
+
+\def \fakebold #1{% {text}
+ \hbox{\rlap{#1}%
+ \rlap{\lower .009em \hbox{\kern .009em #1}}%
+ \lower .018em \hbox{\kern .018em #1}}}
+
+\def \multiunderline #1#2#3#4#5{% {count}{drop1}{drop2}{thickness}{text}
+ \ensurepar
+ {\setbox\zboxa = \hbox{#5}%
+ \rlap{\lower #2 \hbox{\vrule height #4 depth 0pt width \the\wd\zboxa}}%
+ \tcounta = #1\relax
+ \tdimena = #2\relax
+ \loop
+ \decrement \tcounta
+ \if \posp{\tcounta}%
+ \advance \tdimena by #3\relax
+ \rlap{\lower \tdimena \hbox{\vrule height #4 depth 0pt
+ width \the\wd\zboxa}}%
+ \repeat
+ \box\zboxa}}
+
+\def \overstrike #1#2{% {text1}{text2}
+ \ensurepar
+ {\setbox\zboxa = \hbox{#1}%
+ \setbox\zboxb = \hbox{#2}%
+ \tdimena = \wd\zboxa
+ \advance \tdimena by -\wd\zboxb
+ \divide \tdimena by 2
+ \rlap{\kern \tdimena \box\zboxb}\box\zboxa}}
+
+\def \strikethrough #1{% {text}
+ \ensurepar
+ {\setbox\zboxa = \hbox{#1}%
+ \rlap{\raise .45ex \hbox{\vrule height .1ex depth 0pt
+ width \the\wd\zboxa}}%
+ \box\zboxa}}
+
+\let \zunline = \underline
+
+\def \underline #1{% {text}
+ \relax
+ \if \mathmodep
+ \zunline{#1}%
+ \else
+ \multiunderline{1}{.4ex}{0pt}{.1ex}{#1}%
+ \fi}
+
+% Vertical Centering
+% -------- ---------
+
+
+\def \centeroncapheight #1{% {text}
+ \ensurepar
+ {\setbox\zboxa = \hbox{#1}%
+ \measurecapheight{\tdimena}% % Calculate ht(CAP) - ht(text)
+ \advance \tdimena by -\ht\zboxa % ------------------
+ \divide \tdimena by 2 % 2
+ \raise \tdimena \box\zboxa}}
+
+\def \centerondigitheight #1{% {text}
+ \ensurepar
+ {\setbox\zboxa = \hbox{#1}%
+ \measuredigitheight{\tdimena}% % Calculate ht(123) - ht(text)
+ \advance \tdimena by -\ht\zboxa % ------------------
+ \divide \tdimena by 2 % 2
+ \raise \tdimena \box\zboxa}}
+
+\def \centeronxheight #1{% {text}
+ \ensurepar
+ {\setbox\zboxa = \hbox{#1}%
+ \tdimena = 1ex % Calculate 1ex - ht(text)
+ \advance \tdimena by -\ht\zboxa % --------------
+ \divide \tdimena by 2 % 2
+ \raise \tdimena \box\zboxa}}
diff --git a/macros/plain/contrib/zztex/tex/zzhyper.tex b/macros/plain/contrib/zztex/tex/zzhyper.tex
new file mode 100644
index 0000000000..cf20d36eb2
--- /dev/null
+++ b/macros/plain/contrib/zztex/tex/zzhyper.tex
@@ -0,0 +1,185 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% Module: PDF Hyperlink Facility
+%
+% Synopsis: This module provides facilities for creating PDF hyperlinks
+% in the document.
+%
+% Author: Paul C. Anagnostopoulos
+% Created: 12 March 2014
+%
+% Copyright 1989--2020 by Paul C. Anagnostopoulos
+% under The MIT License (opensource.org/licenses/MIT)
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% Control Hyperlinking
+% ------- ------------
+
+
+% If hyperlinking is turned off, then we also clear the button color.
+
+\def \setPDFhyperlinks #1{%
+ \global\setflag \PDFhyperlinks = #1\relax
+ \if \notp{#1}\PDFbuttoncolor = {}\fi}
+
+% Hyperlink Marks
+% --------- -----
+
+
+% This macro generates a hyperlink mark that can be used as the target
+% of a button.
+
+\def \PDFmark #1{%
+ \if \PDFhyperlinks
+ \special{mark: #1}%
+ \if \vmodep \repeatpenalty \fi % In case glue follows \special.
+ \fi}
+
+% Hyperlink Buttons
+% --------- -------
+
+
+\def \pagebutton #1#2{% {folio}{text}
+ \if \PDFhyperlinks
+ \ztextbutton{P:#1}{#2}%
+ \if \emptytoksp{\PDFbuttoncolor}%
+ #2%
+ \else
+ \colortext{\the\PDFbuttoncolor}{#2}%
+ \fi
+ \else
+ #2%
+ \fi}
+
+\def \tagbutton #1#2{% {tag}{text}
+ \if \PDFhyperlinks
+ \ztextbutton{T:#1}{#2}%
+ \if \emptytoksp{\PDFbuttoncolor}%
+ #2%
+ \else
+ \colortext{\the\PDFbuttoncolor}{#2}%
+ \fi
+ \else
+ #2%
+ \fi}
+
+\def \URLbutton #1#2{% {URL}{text}
+ \if \PDFhyperlinks
+ \ztextbutton{#1}{#2}%
+ \if \emptytoksp{\PDFbuttoncolor}%
+ #2%
+ \else
+ \colortext{\the\PDFbuttoncolor}{#2}%
+ \fi
+ \else
+ #2%
+ \fi}
+
+\def \colorbuttontext {%
+ \if \andp{\PDFhyperlinks}{\notp{\emptytoksp{\PDFbuttoncolor}}}%
+ \color{\the\PDFbuttoncolor}%
+ \fi}
+
+\def \endcolorbuttontext {%
+ \if \andp{\PDFhyperlinks}{\notp{\emptytoksp{\PDFbuttoncolor}}}%
+ \endcolor
+ \fi}
+
+% Low-Level Button Macros
+% --------- ------ ------
+
+
+% These low-level macros do not check \PDFhyperlinks.
+
+
+\def \ztextbutton #1#2{% {mark}{text}
+ \measuretextwidth{\tdimena}{#2}%
+ \zwidthbutton{#1}{\tdimena}}
+
+\def \zwidthbutton #1#2{% {mark}{width-expr}
+ \calculate \tdimena = {#2}%
+ \if \hmodep
+ \smash{\lower .5ex \hbox{%
+ \special{button: \number\tdimena\space
+ \number\normalbaselineskip\space #1}}}%
+ \else
+ \special{button: \number\tdimena\space
+ \number\normalbaselineskip\space #1}%
+ \fi}
+
+\def \zURLbutton #1#2{% {url}{text}
+ \measuretextwidth{\tdimena}{#2}%
+ \def \zurltext {#1}%
+ \smash{\lower .5ex \hbox{%
+ \special{button: \number\tdimena\space
+ \number\normalbaselineskip\space
+ \expandafter\zdefof \meaning\zurltext\zmark}}}}
+
+% Email Addresses and URLs
+% ----- --------- --- ----
+
+
+\def \zurlprefix {}
+
+
+\def \urltext #1#2{% {font}{break before .?}{url}
+ \bgroup
+ #1%
+ \setflag \zurldotbreak = #2%
+ \catcode `\& = \catactive
+ \catcode `\. = \catactive
+ \catcode `\/ = \catactive
+ \catcode `\@ = \catactive
+ \catcode `\_ = \catactive
+ \zurltexta}
+
+\def \zurltexta #1{% {url}
+ \zurltextb #1\-\-\zmark}
+
+\def \zurltextb #1\-#2\-#3\zmark{% part1\-part2\-part3\zmark
+ \expandafter\def \expandafter\zfullurl \expandafter{\zurlprefix #1#2}%
+ \zurltextc{#1}%
+ \if \notp{\emptyargp{#2}}%
+ \break
+ \zurltextc{#2#3}%
+ \fi
+ \egroup
+ \gdef \zurlprefix {}}
+
+{\catcode `\& = \catactive
+ \catcode `\. = \catactive
+ \catcode `\/ = \catactive
+ \catcode `\@ = \catactive
+ \catcode `\_ = \catactive
+
+\gdef \zurltextc #1{% {url-text}
+ \def &{\ampersand \discretionary{}{}{}}% % Break after &
+ \let \& = &%
+ \if \zurldotbreak
+ \def .{\discretionary{}{}{}\char"2E }% % Break before .
+ \else
+ \def .{\char"2E \discretionary{}{}{}}% % Break after .
+ \fi
+ \def /{\char"2F \discretionary{}{}{}}% % Break after /
+ \def @{\atsign \discretionary{}{}{}}% % Break after @
+ \let \@ = @%
+ \let _ = \underscore % Set _
+ \let ~ = \tilde % Set ~
+ \def \-{\discretionary{}{}{}}% % No hyphenation
+ \if \PDFhyperlinks
+ \expandafter\zURLbutton \expandafter{\zfullurl}{#1}%
+ \fi
+ \colorbuttontext
+ #1%
+ \endcolorbuttontext}
+
+} % \catcode
+
+% Digital Object Identifiers
+% ------- ------ -----------
+
+
+\def \DOI {% {number}
+ \def \zurlprefix {http://dx.doi.org/}%
+ \ensurepar \url}
diff --git a/macros/plain/contrib/zztex/tex/zzhyph.tex b/macros/plain/contrib/zztex/tex/zzhyph.tex
new file mode 100644
index 0000000000..1aea8d1cd8
--- /dev/null
+++ b/macros/plain/contrib/zztex/tex/zzhyph.tex
@@ -0,0 +1,128 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% Module: ZzTeX Hyphenation Facilities
+%
+% Synopsis: This module provides the extra facilities for dealing with
+% hyphenation and related matters.
+%
+% Author: Paul C. Anagnostopoulos
+% Created: 6 October 1990
+%
+% Copyright 1989--2020 by Paul C. Anagnostopoulos
+% under The MIT License (opensource.org/licenses/MIT)
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% Hyphenating Words
+% ----------- -----
+
+
+\def \*{%
+ \discretionary{}{}{}}
+
+\def \hyphen{%
+ \nobreak -\zposthyph{2}}
+
+\def \slash {/\zposthyph{1}}
+
+
+% These macros are used in ZZHMODE to allow special characters to hyphenate.
+
+\def \zprehyph #1{% {\parameter}
+ \ifcase #1%
+ \relax
+ \or
+ \relax
+ \else
+ \nobreak
+ \fi}
+
+\def \zposthyph #1{% {\parameter}
+ \ifcase #1%
+ \relax
+ \or
+ \discretionary{}{}{}%
+ \else
+ \penalty \exhyphenpenalty \hskip 0pt\relax
+ \fi}
+
+% Displaying Hyphens
+% ---------- -------
+
+
+\def \showhyphens #1{%
+ \setbox\zboxa = \vbox{%
+ \hsize = \maxdimen
+ \parfillskip = 0pt
+ \pretolerance = -1
+ \tolerance = -1
+ \hbadness = 0pt
+ \showboxdepth = 0
+ \ #1}}
+
+% Hyphenation Exceptions
+% ----------- ----------
+
+
+\hyphenation{%
+ acad-e-my a-mi-no anag-no-sto-pou-los
+ an-a-lyse an-a-lysed an-a-lys-es
+ an-a-lys-ing analy-ses analy-sis a-no-ny-mi-ty
+ ap-pen-dix apple ap-pli-ca-tion ar-chive ar-chiv-ing ar-chiv-ist
+ arity aspect assume asyn-chro-nous asyn-chro-nous-ly
+ au-to-mat-ic au-to-ma-tion au-ton-o-mous
+ back-gam-mon berth-ing bio-che-mist bio-che-mists bio-med-i-cine
+ bio-poly-mer bio-poly-mers bit-map book-reader brows-ers
+ buff-er buff-er-ed buff-er-ing
+ cat-a-stroph-ic chi-ca-go ci-gar cig-a-rette cig-a-rettes
+ co-in-cide co-in-cides
+ co-iso-tro-pic col-umns com-pen-dium cor-vette cor-vettes
+ cross-over crypto-sys-tem crypto-sys-tems cur-vi-linear cy-to-cha-la-sin
+ data-base data-bases data-set data-sets date-stamp de-mon-strate de-mon-strates
+ der-i-va-tion dijk-stra di-lem-ma dis-tinc-tive
+ dump-ling dump-lings
+ eco-nom-ic eco-nom-ics econ-o-mies e-con-o-mist e-con-o-mists ec-ua-dor
+ ei-gen-space ei-gen-spaces elec-tro-dif-fu-sion en-gland
+ en-tre-pre-neur en-tre-pre-neurs en-tre-pre-neur-ship
+ e-pis-te-mol-o-gy e-pis-te-mo-log-i-cal
+ fashion fi-bo-nac-ci frame-work
+ geo-graph-ic ge-om-e-try geo-stro-phic graph-ics
+ he-mo-glo-bin hexa-dec-i-mal horse-rad-ish
+ ide-ol-o-gy ide-ol-o-gies ide-ol-o-gize idiom im-ped-ance im-plic-it
+ keynes-ian
+ leaf-lets li-chen life-style light-weight li-quid-i-ty li-thog-ra-phy lon-gi-tu-di-nal
+ look-ahead
+ ma-caque
+ mac-ro-eco-nom-ic mac-ro-eco-nom-ics mac-ro-eco-nom-ist mac-ro-eco-nom-ists
+ mac-ro-mol-e-cule mac-ro-mol-e-cules
+ man-u-script man-u-scripts mar-gin-al mas-sa-chu-setts
+ me-chan-i-cal me-di-um me-di-ter-ra-ne-an meta-bolic me-tab-o-lism
+ meta-lin-guis-tic met-a-phor met-a-phors met-a-phor-ic met-a-phor-i-cal
+ meth-od-ol-o-gy
+ mic-ro-eco-nom-ic mic-ro-eco-nom-ics mic-ro-eco-nom-ist mic-ro-eco-nom-ists
+ mini-tab mne-mon-ic meth-od-o-log-i-cal mol-ecule mol-ecules
+ mono-chrome mono-pole mono-poles mo-nop-o-ly
+ mono-sac-cha-rides mul-ti-pli-ca-tion mul-ti-pli-ca-tive
+ name-space noisi-ness noisy none-the-less not-with-stand-ing
+ often ol-i-gop-o-ly ol-i-gop-o-list-ic olym-pi-ad olym-pi-ads
+ om-e-lette om-e-lettes
+ op-er-and op-er-ands oper-ator over-view
+ paper pa-rab-o-la par-a-digm para-mag-ne-tic pa-ram-e-trized
+ patho-gen patho-gen-ic patho-gens people pe-ri-od per-suad-ed per-suad-ing
+ phoe-nix pho-neme pho-to-graphs pho-to-mi-cro-graph phys-i-co-chem-i-cal
+ phys-ics piano pic-to-graph pic-to-graph pic-to-graph-ic poly-sac-cha-rides
+ Post-Script pov-er-ty pow-er prayer pre-dimmed pref-er-a-ble pref-er-a-bly
+ pri-meval pro-cess pro-ces-sor pro-cure-ment
+ pro-gram-ma-ble prop-o-si-tion py-thag-o-re-an
+ qua-drat-ic qua-lia
+ ra-tional real-ly rec-tan-gu-lar re-pack-age re-pack-aged rep-er-toire
+ re-start re-start-ed re-start-able
+ sa-li-ent sched-ul-ing sche-nec-ta-dy scoun-drel scoun-drels ser-geant ser-geants
+ sha-pir-o small-talk so-lo-ist spec-tros-co-py stag-horn ste-reo-spe-cif-ic
+ sto-chas-tic syn-chro-nous syn-chro-nous-ly
+ table tem-po-rar-ily theo-rem time-stamp time-stamps to-ma-to
+ un-pre-dict-able uti-li-za-tion
+ water wave-guide wave-guides weap-on weap-ons which-ever white-space wild-life
+ woman women woman-kind
+ xe-rog-ra-phy
+}
diff --git a/macros/plain/contrib/zztex/tex/zzindexv1.tex b/macros/plain/contrib/zztex/tex/zzindexv1.tex
new file mode 100644
index 0000000000..c809d20c9f
--- /dev/null
+++ b/macros/plain/contrib/zztex/tex/zzindexv1.tex
@@ -0,0 +1,379 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% Module: ZzTeX Indexing Facilities, version 1
+%
+% Synopsis: This file contains the tools for producing an index.
+%
+% Author: Paul C. Anagnostopoulos
+% Created: 20 May 2006
+%
+% Copyright 1989--2020 by Paul C. Anagnostopoulos
+% under The MIT License (opensource.org/licenses/MIT)
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% Index Version
+% ----- -------
+
+
+\def \indexversion #1{%
+ \input zzindexv#1\relax}
+
+% Define Index Locator Types
+% ------ ----- ------- -----
+
+
+% This list contains the definition of each locator. New ones must be
+% added to the end, and any program looking at the definitions must assume
+% that duplicates may exist, and that the last one prevails.
+
+\def \zixloclist {}
+
+
+%~ This command is deprecated in favor of |\definelocator|.
+
+\def \definelocatortype #1#2#3#4#5#6{% {name}{attributes}{precedence}
+ % {beginning-punc}{templates}
+ % {ending-punc}
+ {\setflag \pg = \true
+ \let \page = \relax
+ \def \nopage {\setflag \pg = \false}%
+ \setflag \txt = \false
+ \def \text {\setflag \txt = \true}%
+ \let \notext = \relax
+ #2%
+ \def \bpunc {#4}%
+ \def \temp {#5}%
+ \def \epunc {#6}%
+ \edef \znext {%
+ \noexpand\append{{#1}{\pg}{\txt}{#3}%
+ {\expandafter\zdefof \meaning\bpunc\zmark}%
+ {\expandafter\zdefof \meaning\temp\zmark}%
+ {\expandafter\zdefof \meaning\epunc\zmark}}}%
+ \znext{\zixloclist}%
+ \if \txt
+ \withname\gdef{\x#1}##1##2{\zixindex{#1}{##1}{S}{##2}}%
+ \if \pg
+ \withname\gdef{\x#1begin}##1##2{\zixindex{#1}{##1}{B}{##2}}%
+ \withname\gdef{\x#1end}##1##2{\zixindex{#1}{##1}{E}{##2}}%
+ \fi
+ \else
+ \withname\gdef{\x#1}##1{\zixindex{#1}{##1}{S}{}}%
+ \if \pg
+ \withname\gdef{\x#1begin}##1{\zixindex{#1}{##1}{B}{}}%
+ \withname\gdef{\x#1end}##1{\zixindex{#1}{##1}{E}{}}%
+ \fi
+ \fi}}
+
+
+% This command is deprecated.
+
+\def \defineindexlocator #1#2#3#4#5#6{% {name}{attributes}{precedence}
+ % {punctuation}{single-template}
+ % {range-template}
+}
+
+% Builtin Locator Types
+% ------- ------- -----
+
+
+% Precedences 0--1 and 6--9 are reserved for specific books.
+
+\definelocatortype{term}{\page\notext}{2.3}
+ {, |}{\bold{~P}|\bold{~P--~Q}|, }{. |}
+\definelocatortype{biblio}{\page\notext}{2.5}
+ {, |}{~P|~P--~Q|, }{. |}
+\definelocatortype{cite}{\page\notext}{2.5}
+ {, |}{~P|~P--~Q|, }{. |}
+\definelocatortype{page}{\page\notext}{2.5}
+ {, |}{~P|~P--~Q|, }{. |}
+\definelocatortype{figure}{\page\notext}{2.7}
+ {, |}{~P\+\emph{f}|~P--~Q\+\emph{f}|, }{. |}
+\definelocatortype{glossary}{\page\notext}{2.7}
+ {, |}{~P\+\emph{g}|~P--~Q\+\emph{g}|, }{. |}
+\definelocatortype{note}{\page\notext}{2.8}
+ {, |}{~P\+\emph{n}|~P--~Q\+\emph{n}|, }{. |}
+\definelocatortype{sidebar}{\page\notext}{2.7}
+ {, |}{~P\+\emph{s}|~P--~Q\+\emph{s}|, }{. |}
+\definelocatortype{table}{\page\notext}{2.7}
+ {, |}{~P\+\emph{t}|~P--~Q\+\emph{t}|, }{. |}
+\definelocatortype{see}{\nopage\text}{3}
+ {. |\See\ }{~T||; }{. |}
+\definelocatortype{seealso}{\nopage\text}{4}
+ {. |\Seealso\ }{~T||; }{. |}
+\definelocatortype{consult}{\nopage\text}{5}
+ {. |\Consult\ }{~T||; }{. |}
+
+% Index Preparation File
+% ----- ----------- ----
+
+
+% The \produceindex command must appear before the \document command.
+
+\setflag \zindexing = \false
+
+
+\def \produceindex #1#2{% {type}{prep-file}
+ {\processdesign{\index}{#1}%
+ \immediate\openout \zwritea = #2.zzh\relax
+ \immediate\write \zwritea {root \jobname}%
+ \immediate\write \zwritea {type #1}%
+ \immediate\write \zwritea {divisions {\the\divisions}}%
+ \immediate\write \zwritea {locators {\the\locators}}%
+ \immediate\write \zwritea {\the\indexparams}%
+ \maplist{\immediate\write \zwritea {define-locator ##1}}{\zixloclist}%
+ \immediate\closeout \zwritea}%
+ \global\setflag \zindexing = \true}
+
+% Index File Handling
+% ----- ---- --------
+
+\definewrite{\zixrootfile}
+\definewrite{\zixdivfile}
+\setflag \zixdivopen = \false
+
+
+\def \zindexinit {%
+ \if \zindexing
+ \immediate\openout \zixrootfile = \jobname.zzi\relax
+ \immediate\write \zixrootfile
+ {\zcomment Raw index entry file for book `\jobname'.}%
+ \fi}
+
+\def \zindexfinal {%
+ \if \zindexing
+ \immediate\write \zixrootfile {\zcomment [end]}%
+ \immediate\closeout \zixrootfile
+ \fi}
+
+\def \zindexdivinit #1{% {division}
+ \if \zindexing
+ \immediate\openout \zixdivfile = #1.zzi\relax
+ \immediate\write \zixdivfile
+ {\zcomment Raw index entry file for book `\jobname', division `#1'.}%
+ \global\setflag \zixdivopen = \true
+ \fi}
+
+\def \zindexdivfinal {%
+ \if \zixdivopen
+ \immediate\write \zixdivfile {\zcomment [end]}%
+ \immediate\closeout \zixdivfile
+ \global\setflag \zixdivopen = \false
+ \fi}
+
+% Generate Index Entry
+% -------- ----- -----
+
+
+% This macro is called from the indexing macros generated by
+% \definelocatortype.
+
+\def \zixindex #1#2#3#4{% {locator}{level}{page-code}{text}
+ \tcounta = #2\relax
+ \if \notp{\rangep{\tcounta}{1}{3}}%
+ \error{invindexlvl}{Invalid index level '#2' specified}%
+ \tcounta = 1
+ \fi
+ \name{\zixindex\romannumeral\tcounta}{#1}{#2}{#3}{#4}}
+
+\def \zixindexi #1#2#3#4#5{%
+ \zixindexw{#1}{#2}{#3}{#4}{#5}{}{}{\noexpand\folio}}
+\def \zixindexii #1#2#3#4#5#6{%
+ \zixindexw{#1}{#2}{#3}{#4}{#5}{#6}{}{\noexpand\folio}}
+\def \zixindexiii #1#2#3#4#5#6#7{%
+ \zixindexw{#1}{#2}{#3}{#4}{#5}{#6}{#7}{\noexpand\folio}}
+
+\catcode"B8 = \catother
+
+\gdef \zixindexw #1#2#3#4#5#6#7#8{% {locator}{level}{page-code}{text}
+ % {heading1}{heading2}{heading3}{page}
+ \if \notp{\zindexing}%
+ \warning{notindexing}{An indexing command was encountered,
+ but no \string\produceindex}%
+ \fi
+ \zbeginhidewrite
+ \def \zhdx {#5}%
+ \def \zhdy {#6}%
+ \def \zhdz {#7}%
+ \def \ztxt {#4}%
+ \edef \znext {#1^^b8%
+ #2^^b8%
+ \expandafter\zdefof \meaning\zhdx\zmark^^b8%
+ \expandafter\zdefof \meaning\zhdy\zmark^^b8%
+ \expandafter\zdefof \meaning\zhdz\zmark^^b8%
+ #3^^b8%
+ #8^^b8%
+ \expandafter\zdefof \meaning\ztxt\zmark}%
+ \write \if \zixdivopen \zixdivfile \else \zixrootfile \fi
+ \expandafter{\znext}%
+ \if \vmodep \repeatpenalty \fi % In case glue follows write.
+ \zendhidewrite}
+
+\catcode"B8 = \catinvalid
+
+% Discussion of Index Formatting
+% ---------- -- ----- ----------
+
+
+% An index is formatted inside an index block, which is more or less
+% like a text block. Within the index block are occurences of the
+% \indexentry macro, one for each entry. In addition, the
+% \alphabreak macro can be used to produce breaks preceding the `A'
+% entries, `B' entries, etc.
+%
+% In an index block, parts 4 and 5 of the mark are used to remember
+% index entries so they can be carried forward to subsequent columns
+% or pages. The mark is used as follows:
+%
+% Part Subpart Usage
+% 4 1 Boolean, true if in the midst of a first-level entry.
+% 4 2 The first-level entry text.
+% 5 1 Boolean, true if in the midst of a second-level entry.
+% 5 2 The second-level entry text.
+
+% Index Block
+% ----- -----
+
+
+\defineblock{\index}{\endindex}{\false}{}
+
+%~block index Type
+% \def \alphaformat ##1{...} % Alpha break formatter.
+% \bodyfont = {\size\style} % Body font.
+% \clubpenalty = penalty % Club penalty is often different.
+% \columngutter = glue % Column gutter.
+% \divisions = {...} % Which divisions to include.
+% \leftindent = glue % Left indentation.
+% \locators = {...} % Which locators to include.
+% \indexparams = {...} % Parameters for index generator.
+% \parhang = glue % Paragraph hang.
+% \parindent = dimen % Paragraph indent.
+% \parrag = dimen % Paragraph raggedness.
+% \parskip = glue % Paragraph skip.
+% \position = {...} % Position and number of columns.
+% \rightindent = glue % Right indentation.
+%~end
+
+\definetoks{\locators}
+\definetoks{\indexparams}
+
+\definecount{\previndexlevel}{0}
+\definecount{\zixcols}{0}
+
+
+\def \index #1{% {type}
+ \blockcantbein{\index}{\index}%
+ \beginblockscope{index}%
+ \global\increment \indexdepth
+ \clubpenalty = \breakallowed %~default soft
+ \parskip = 0pt %~default soft
+ \processdesign{\index}{#1}%
+ \global\increment \indexnumber
+ \def \zixtype {#1}%
+ \zixparsepos
+ \indexformat}
+
+\def \indexformat {%
+ \the\bodyfont
+ \alterindentation{\leftindent}{\rightindent}%
+ \setparrag{\parrag}%
+ \setpagecolumns{\zixpageuse}{\the\zixcols}{\columngutter}%
+ \everycolumn = {\zixcarryover}%
+ \begingroup
+ \let \zfullcolumnbreak = \fullcolumnbreak
+ \let \fullcolumnbreak = \indexbreak
+ \let \shortcolumnbreak = \indexbreak
+ \global\previndexlevel = 0\relax}
+
+\def \endindex {%
+ \endgraf % End last entry.
+ \vbox{}% % Force start of column if not already.
+ \endgroup
+ \clearindexmarks
+ \everycolumn = {}%
+ \setpagecolumns{\usetextmeasure}{1}{0pt}%
+ \global\decrement \indexdepth
+ \endblockscope{index}}
+
+\def \zixparsepos {%
+ \zixcols = 1
+ \let \oneup = \relax
+ \def \twoup {\zixcols = 2}%
+ \def \threeup {\zixcols = 3}%
+ \def \zixpageuse {\usetextmeasure}%
+ \let \textarea = \relax
+ \def \typearea {\def \zixpageuse {\usetypewidth}}%
+ \let \leftmargin = \typearea
+ \the\position}
+
+% Index Entries
+% ----- -------
+
+
+\setflag \zixbreak = \false
+
+
+\def \indexentry #1#2#3{% level{heading}{locators}
+ \endgraf
+ \ifcase #1%
+ \or % Level 1 heading:
+ \clearindexmarks
+ \zixmaybebreak
+ \hangindent = \parhang \hangafter = 1
+ {\name{\index\zixtype entryiformat}{#2\setmarkinfo{4}{\true}{#2}}{#3}}%
+%%% \setmarkinfo{4}{\true}{#2}%
+ \or % Level 2 heading:
+ \setmarkinfo{5}{\false}{}%
+ \zixmaybebreak
+ \hangindent = \parhang \hangafter = 1
+ {\name{\index\zixtype entryiiformat}{#2\setmarkinfo{5}{\true}{#2}}{#3}}%
+%%% \setmarkinfo{5}{\true}{#2}%
+ \or % Level 3 heading:
+ \zixmaybebreak
+ \hangindent = \parhang \hangafter = 1
+ {\name{\index\zixtype entryiiiformat}{#2}{#3}}%
+ \fi
+ \global\previndexlevel = #1\relax}
+
+\def \alphabreak #1{% {text}
+ \endgraf
+ \clearindexmarks
+ \zixmaybebreak
+ \alphaformat{#1}%
+ \endgraf}
+
+\def \indexbreak {%
+ \setflag \zixbreak = \true}
+
+\def \clearindexmarks {%
+ \setmarkinfo{4}{\false}{}%
+ \setmarkinfo{5}{\false}{}}
+
+\def \zixmaybebreak {%
+ \if \zixbreak
+ \zfullcolumnbreak
+ \setflag \zixbreak = \false
+ \fi}
+
+
+% This macro is invoked at the beginning of each column to perform
+% any first- and second-level entry carryovers. It only includes
+% carryovers on the first column of versos.
+
+\def \zixcarryover {%
+ \if \andp{\evenpagep}{\firstcolumnp}%
+ {\setflag \znext = {\markinfo{\bottommark}{4}{1}}%
+ \if \znext
+ \hangindent = \parhang \hangafter = 1
+ \name{\index\zixtype carryiformat}{\markinfo{\bottommark}{4}{2}}%
+ \setflag \znext = {\markinfo{\bottommark}{5}{1}}%
+ \if \znext
+ \hangindent = \parhang \hangafter = 1
+ \name{\index\zixtype carryiiformat}{\markinfo{\bottommark}{5}{2}}%
+ \fi
+ \endgraf
+ \tdimena = \zoutputcoldepth % Compensate for depth of
+ \advance \tdimena by -\prevdepth % previous column v. depth
+ \kern \tdimena % of carryover line(s).
+ \fi}%
+ \fi}
diff --git a/macros/plain/contrib/zztex/tex/zzindexv2.tex b/macros/plain/contrib/zztex/tex/zzindexv2.tex
new file mode 100644
index 0000000000..e17a73102e
--- /dev/null
+++ b/macros/plain/contrib/zztex/tex/zzindexv2.tex
@@ -0,0 +1,448 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% Module: ZzTeX Indexing Facilities, version 2
+%
+% Synopsis: This file contains the facilities for generating index
+% parameter files, raw entry files, and for setting the indexes.
+%
+% Author: Paul C. Anagnostopoulos
+% Created: 13 June 2013
+%
+% Copyright 1989--2020 by Paul C. Anagnostopoulos
+% under The MIT License (opensource.org/licenses/MIT)
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% Define Index Locators
+% ------ ----- --------
+
+
+% This list contains the definition of each locator. New ones must be
+% added to the end, and any program looking at the definitions must assume
+% that duplicates may exist and that the last one prevails.
+
+\def \zixloclist {}
+
+
+\def \definelocator #1#2#3{% {type}{attributes}{[format-args]}
+ {\setflag \pg = \false
+ \setflag \rng = \false
+ \setflag \txt = \false
+ \def \page {\setflag \pg = \true}%
+ \def \nopage {\setflag \pg = \false}%
+ \def \range {\setflag \pg = \true \setflag \rng = \true}%
+ \def \norange {\setflag \rng = \false}%
+ \def \text {\setflag \txt = \true}%
+ \def \notext {\setflag \txt = \false}%
+ #2%
+ {\def \attr {#2}%
+ \edef \znext {%
+ \noexpand\append{{#1}{\expandafter\zdefof \meaning\attr\zmark}}}%
+ \znext{\zixloclist}}%
+ \if \andp{\pg}{\notp{\txt}}%
+ \withname\gdef{\x#1}##1{\zixindex{#1}{S}{##1}{}}%
+ \if \rng
+ \withname\gdef{\x#1begin}##1{\zixindex{#1}{B}{##1}{}}%
+ \withname\gdef{\x#1end}##1{\zixindex{#1}{E}{##1}{}}%
+ \fi
+ \else\if \txt
+ \withname\gdef{\x#1}##1##2{\zixindex{#1}{S}{##1}{##2}}%
+ \if \rng
+ \withname\gdef{\x#1begin}##1##2{\zixindex{#1}{B}{##1}{##2}}%
+ \withname\gdef{\x#1end}##1##2{\zixindex{#1}{E}{##1}{##2}}%
+ \fi
+ \else
+ \error{locattr}{Invalid index locator attributes}%
+ \fi\fi
+ \if \notp{\emptyargp{#3}}%
+ \definelocatorformat{#1}#3\relax
+ \fi}}
+
+% Define Locator Formats
+% ------ ------- -------
+
+
+% This list contains the definition of each locator format. It works like
+% the locator list above.
+
+\def \zixformatlist {}
+
+\def \definelocatorformat #1#2#3#4{% {name}{rank.order}{level-1-items}{level-2-items}
+ {\def \lvli {#3}%
+ \def \lvlii {#4}%
+ \edef \znext {%
+ \noexpand\append{{#1}{#2}%
+ {\expandafter\zdefof \meaning\lvli\zmark}%
+ {\expandafter\zdefof \meaning\lvlii\zmark}}}%
+ \znext{\zixformatlist}}}
+
+% Builtin Locator Types
+% ------- ------- -----
+
+
+% These locators are built-in for ease of use. Ranks 0, 1, and 5 and higher
+% are reserved for the user. Ranks 10 and higher result in deferred
+% locators.
+
+\definelocator{page}{\page\range}
+ {{2.1}{prefix1:, |tmplt:?P|rtmplt:?P--?Q|sep:, }{}}
+
+\definelocator{figure}{\page\range}
+ {{2.3}{prefix1:, |tmplt:?P\emph{f}|rtmplt:?P--?Q\emph{f}|sep:, }{}}
+
+\definelocator{note}{\page}
+ {{2.5}{prefix1:, |tmplt:?P\emph{n}|sep:, }{}}
+
+\definelocator{table}{\page\range}
+ {{2.7}{prefix1:, |tmplt:?P\emph{t}|rtmplt:?P--?Q\emph{t}|sep:, }{}}
+
+\definelocator{see}{\nopage\text}
+ {{3}{prefix1:. \emph{See} |tmplt:?T|sep:; }{}}
+
+\definelocator{seealso}{\nopage\text}
+ {{4}{prefix1:. \emph{See also} |tmplt:?T|sep:; }{}}
+
+% Generate Indexes
+% -------- -------
+
+
+\def \zixnamelist {}
+\setflag \zindexing = \false
+
+
+\def \generateindex #1{% {name}
+ \append{#1}{\zixnamelist}%
+ \global\setflag \zindexing = \true}
+
+% Index File Handling
+% ----- ---- --------
+
+%\definewrite{\zixrootfile}
+%\definewrite{\zixdivfile}
+\setflag \zixdivopen = \false
+
+
+\def \zindexinit {%
+ \if \zindexing
+ \maplist{\zixwritezzp{##1}}{\zixnamelist}%
+ \immediate\openout \zixrootfile = \jobname.zzi\relax
+ \immediate\write \zixrootfile
+ {\zcomment Raw index entry file for book `\jobname' root.}%
+ \fi}
+
+\def \zindexfinal {%
+ \if \zindexing
+ \immediate\write \zixrootfile {\zcomment [end]}%
+ \immediate\closeout \zixrootfile
+ \fi}
+
+\def \zindexdivinit #1{% {division}
+ \if \zindexing
+ \immediate\openout \zixdivfile = #1.zzi\relax
+ \immediate\write \zixdivfile
+ {\zcomment Raw index entry file for book `\jobname', division `#1'.}%
+ \global\setflag \zixdivopen = \true
+ \fi}
+
+\def \zindexdivfinal {%
+ \if \zixdivopen
+ \immediate\write \zixdivfile {\zcomment [end]}%
+ \immediate\closeout \zixdivfile
+ \global\setflag \zixdivopen = \false
+ \fi}
+
+\def \zixwritezzp #1{% {name}
+ \begingroup
+ \processdesign{\index}{#1}%
+ \immediate\openout \zwritea = #1.zzp\relax
+ \immediate\write \zwritea {root \jobname;}%
+ \immediate\write \zwritea {index #1;}%
+ \immediate\write \zwritea {divisions \the\divisions;}%
+ \maplist{\immediate\write \zwritea {define-locator ##1;}}{\zixloclist}%
+ \maplist{\immediate\write \zwritea {define-format ##1;}}{\zixformatlist}%
+ \immediate\write \zwritea {locators \the\locators;}%
+ \immediate\write \zwritea {\the\indexparams}%
+ \immediate\closeout \zwritea
+ \endgroup}
+
+% Write Raw Index Entry
+% ----- --- ----- -----
+
+
+% This macro is called from the indexing macros defined by
+% \definelocator.
+
+\def \zixindex #1#2#3#4{% {locator}{page-code}{headings}{[text]}
+ \zixindexb {#1}{#2}{#4}#3|||\zmark}
+
+\catcode"B8 = \catother
+
+\def \zixindexb #1#2#3#4|#5|#6|#7\zmark{% {locator}{page-code}{text}
+ % head1|head2|head3|...\zmark
+ \if \zindexing
+ \zbeginhidewrite
+ \def \zhdx {#4}%
+ \def \zhdy {#5}%
+ \def \zhdz {#6}%
+ \def \ztxt {#3}%
+ \edef \znext {#1^^b8%
+ #2^^b8%
+ \noexpand\folio^^b8%
+ \expandafter\zdefof \meaning\zhdx\zmark^^b8%
+ \expandafter\zdefof \meaning\zhdy\zmark^^b8%
+ \expandafter\zdefof \meaning\zhdz\zmark^^b8%
+ \expandafter\zdefof \meaning\ztxt\zmark}%
+ \write \if \zixdivopen \zixdivfile \else \zixrootfile \fi
+ \expandafter{\znext}%
+ \if \vmodep \repeatpenalty \fi % In case glue follows write.
+ \zendhidewrite
+ \fi}
+
+\catcode"B8 = \catinvalid
+
+% Discussion of Index Formatting
+% ---------- -- ----- ----------
+
+
+% An index is formatted inside an index block, which is more or less
+% like a text block. Within the index block are occurences of the
+% \indexentry macro, one for each entry. In addition, the
+% \alphabreak macro can be used to produce breaks preceding the 'A'
+% entries, 'B' entries, etc.
+%
+% In an index block, parts 4 and 5 of the mark are used to remember
+% index headings so they can be carried forward to subsequent columns
+% or pages. The mark is used as follows:
+%
+% Part Subpart Usage
+% 4 1 Boolean, true if in the midst of a first-level entry.
+% 4 2 The first-level entry heading.
+% 5 1 Boolean, true if in the midst of a second-level entry.
+% 5 2 The second-level entry heading.
+
+% Index Block
+% ----- -----
+
+
+\defineblock{\index}{\endindex}{\false}{redefine}
+
+%~block index Type
+% \def \alphaformat ##1{...} % Alphabetic break formatter.
+% \bodyfont = {\size\style} % Body font.
+% \clubpenalty = penalty % Club penalty is often different.
+% \columngutter = glue % Column gutter.
+% \divisions = {...} % Which divisions to include.
+% \leftindent = glue % Left indentation.
+% \locators = {...} % Which locators to include.
+% \indexparams = {...} % Parameters for index generator.
+% \parhang = glue % Paragraph hang.
+% \parindent = dimen % Paragraph indent.
+% \parrag = dimen % Paragraph raggedness.
+% \parskip = glue % Paragraph skip.
+% \position = {...} % Position and number of columns.
+% \rightindent = glue % Right indentation.
+%~end
+
+%\definetoks{\locators}
+%\definetoks{\indexparams}
+
+%\definecount{\previndexlevel}{0}
+%\definecount{\zixcols}{0}
+
+
+\def \index #1{% {type}
+ \blockcantbein{\index}{\index}%
+ \beginblockscope{index}%
+ \global\increment \indexdepth
+ \clubpenalty = \breakallowed %~default soft
+ \parskip = 0pt %~default soft
+ \processdesign{\index}{#1}%
+ \global\increment \indexnumber
+ \def \zixname {#1}%
+ \zixparsepos
+ \indexformat}
+
+\def \indexformat {%
+ \the\bodyfont
+ \alterindentation{\leftindent}{\rightindent}%
+ \setparrag{\parrag}%
+ \setpagecolumns{\zixpageuse}{\the\zixcols}{\columngutter}%
+ \everycolumn = {\zixcarryover}%
+ \begingroup
+ \let \zfullcolumnbreak = \fullcolumnbreak
+ \let \fullcolumnbreak = \zixcolumnbreak
+ \let \shortcolumnbreak = \zixcolumnbreak
+ \global\previndexlevel = 0\relax}
+
+\def \endindex {%
+ \endgraf % End last entry.
+ \vbox{}% % Force start of column if not already.
+ \endgroup
+ \zclearindexmarks
+ \everycolumn = {}%
+ \setpagecolumns{\usetextmeasure}{1}{0pt}%
+ \global\decrement \indexdepth
+ \endblockscope{index}}
+
+\def \zixparsepos {%
+ \zixcols = 1
+ \def \zixpageuse {\usetextmeasure}%
+ \setflag \zixrunin = \false
+ \let \oneup = \relax
+ \let \outline = \relax
+ \def \runin {\setflag \zixrunin = \true}%
+ \def \threeup {\zixcols = 3}%
+ \def \twoup {\zixcols = 2}%
+ \let \usetextmeasure = \relax
+ \let \usetextwidth = \relax
+ \def \usetypewidth {\def \zixpageuse {\usetypewidth}}%
+ \the\position}
+
+% Format Index Entries
+% ------ ----- -------
+
+
+\setflag \zixbreak = \false
+
+
+% This macro formats the main portion of an index entry.
+
+\def \indexentry #1#2#3{% level{heading}{locators}
+ \ifcase #1%
+ \or % Level 1 heading:
+ \endgraf
+ \zclearindexmarks
+ \zixmaybeforcebreak
+ \hangindent = \parhang \hangafter = 1
+ {\name{\index\zixname entryiformat}{#2\setmarkinfo{4}{\true}{#2}}{#3}}%
+ \or % Level 2 heading:
+ \if \notp{\zixrunin}%
+ \endgraf
+ \if \eqlp{\previndexlevel}{1}\vpenalty{\breaknever}\fi
+ \fi
+ \setmarkinfo{5}{\false}{}%
+ \zixmaybeforcebreak
+ \hangindent = \parhang \hangafter = 1
+ {\name{\index\zixname entryiiformat}{#2\setmarkinfo{5}{\true}{#2}}{#3}}%
+ \or % Level 3 heading:
+ \if \notp{\zixrunin}\endgraf \fi
+ \zixmaybeforcebreak
+ \hangindent = \parhang \hangafter = 1
+ {\name{\index\zixname entryiiiformat}{#2}{#3}}%
+ \fi
+ \global\previndexlevel = #1\relax
+ \ignorespaces}
+
+% This macro format any deferred locators.
+
+\def \indexdeferred #1#2{% level{locators}
+ \ifcase #1%
+ \or % Level 1 deferred locators:
+ \if \notp{\zixrunin}\endgraf \fi
+ \setmarkinfo{5}{\false}{}%
+ \zixmaybeforcebreak
+ \hangindent = \parhang \hangafter = 1
+ {\name{\index\zixname deferrediformat}{#2}}%
+ \or % Level 2 deferred locators:
+ \if \notp{\zixrunin}\endgraf \fi
+ \zixmaybeforcebreak
+ \hangindent = \parhang \hangafter = 1
+ {\name{\index\zixname deferrediiformat}{#2}}%
+ \fi
+ \ignorespaces}
+
+\def \alphabreak #1{% {text}
+ \endgraf
+ \zclearindexmarks
+ \zixmaybeforcebreak
+ \alphaformat{#1}%
+ \endgraf}
+
+\def \zclearindexmarks {%
+ \setmarkinfo{4}{\false}{}%
+ \setmarkinfo{5}{\false}{}}
+
+\def \zixcolumnbreak {%
+ \setflag \zixbreak = \true}
+
+\def \zixmaybeforcebreak {%
+ \if \zixbreak
+ \zfullcolumnbreak
+ \setflag \zixbreak = \false
+ \fi}
+
+
+% This macro is invoked at the beginning of each column to perform
+% any first- and second-level entry carryovers. It only includes
+% carryovers on the first column of versos.
+
+\def \zixcarryover {%
+ \if \andp{\evenpagep}{\firstcolumnp}%
+ {\setflag \znext = {\markinfo{\bottommark}{4}{1}}%
+ \if \znext
+ \hangindent = \parhang \hangafter = 1
+ \name{\index\zixname carryoveriformat}{\markinfo{\bottommark}{4}{2}}%
+ \setflag \znext = {\markinfo{\bottommark}{5}{1}}%
+ \if \znext
+ \hangindent = \parhang \hangafter = 1
+ \name{\index\zixname carryoveriiformat}{\markinfo{\bottommark}{5}{2}}%
+ \fi
+ \endgraf
+ \tdimena = \zoutputcoldepth % Compensate for depth of
+ \advance \tdimena by -\prevdepth % previous column v. depth
+ \kern \tdimena % of carryover line(s).
+ \fi}%
+ \fi}
+
+% Built-in Entry Formats
+% -------- ----- -------
+
+
+% These entry formats and carryovers are for a typical outliine style index.
+
+\def \indexoutlineentryiformat #1#2{%
+ \noindent #1#2\par}
+
+\def \indexoutlineentryiiformat #1#2{%
+ \indent #1#2\par}
+
+\def \indexoutlineentryiiiformat #1#2{%
+ \indent\indent #1#2\par}
+
+\def \indexoutlinedeferrediformat #1{%
+ \indent #1\par}
+
+\def \indexoutlinedeferrediiformat #1{%
+ \indent\indent #1\par}
+
+\def \indexoutlinecarryoveriformat #1{%
+ \noindent #1 \tie{\emph{(continued)}}\par}
+
+\def \indexoutlinecarryoveriiformat #1{%
+ \indent #1 \tie{\emph{(continued)}}\par}
+
+% These entry formats and carryovers are for a typical run-in style index.
+
+\setflag \zixplain = \false
+
+\def \indexruninentryiformat #1#2{%
+ \noindent #1#2%
+ \global\setflag \zixplain = {\emptyargp{#2}}%
+ \if \zixplain :\space \fi}
+
+\def \indexruninentryiiformat #1#2{%
+ \if \notp{\zixplain};\space \fi
+ \global\setflag \zixplain = \false
+ #1#2}
+
+\def \indexruninentryiiiformat #1#2{%
+ \error{runiniii}{It makes no sense to have level-3 entries in a run-in index}}
+
+\def \indexrunindeferrediformat #1{%
+ . #1}
+
+\def \indexrunincarryoveriformat #1{%
+ \noindent #1 \tie{\emph{(continued)}}\par}
+
+\def \indexrunincarryoveriiformat #1{%
+ \relax}
diff --git a/macros/plain/contrib/zztex/tex/zzio.tex b/macros/plain/contrib/zztex/tex/zzio.tex
new file mode 100644
index 0000000000..04a3fbbfac
--- /dev/null
+++ b/macros/plain/contrib/zztex/tex/zzio.tex
@@ -0,0 +1,84 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% Module: ZzTeX I/O Facilities
+%
+% Synopsis:
+%
+% Author: Paul C. Anagnostopoulos
+% Created: 9 September 1989
+%
+% Copyright 1989--2020 by Paul C. Anagnostopoulos
+% under The MIT License (opensource.org/licenses/MIT)
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% Terminal & Log I/O
+% -------- - --- ---
+
+% \message writes to the terminal and the log file, without newlines.
+% This macro adds a newline feature:
+
+\def \messagenl #1{% {text}
+ {\newlinechar = `\_%
+ \message{#1}}}
+
+% This macro writes a line to the log file, with a newline at the end.
+
+\def \writelog {\immediate\write -1}
+
+% \ask combines a prompt using \messagenl with a read from the terminal.
+
+\def \ask #1#2{% {\result-macro}{question}
+ {\messagenl{_#2}%
+ \endlinechar = -1
+ \global\read 16 to #1}}
+
+% Including Files
+% --------- -----
+
+
+\def \include #1{% {file}
+ {\checkfile{\zifile}{#1}%
+ \if \zifile
+ \gdef \znext {\input #1\relax}%
+ \else
+ \warning{noinclfile}{File `#1' does not exist}%
+ \ask{\newfile}{Enter a new file name, or a period (.) to skip it.}%
+ \stringeql{\znext}{\newfile}{.}%
+ \if \znext
+ \xdef \znext {}%
+ \else
+ \xdef \znext {\noexpand\include{\newfile}}%
+ \fi
+ \fi}%
+ \znext
+ \endgraf}
+
+\def \zportionid {}
+
+\def \includeportion #1#2{% {file}{portion-id}
+ \gdef \zportionid {#2}%
+ \include{#1}%
+ \gdef \zportionid {}}
+
+\def \portion #1{% {portion-id}
+ \stringeql{\znext}{#1}{\zportionid}%
+ \if \znext}
+
+\let \endportion = \fi
+
+\def \includeifexists #1{% {file}
+ \checkfile{\zifile}{#1}%
+ \if \zifile
+ \input #1\relax
+ \endgraf
+ \fi}
+
+% Utilities
+% ---------
+
+
+\def \checkfile #1#2{% {\result-flag}{file}
+ \openin \zreada #2\relax
+ \setflag #1= {\notp{\eofp{\zreada}}}%
+ \closein \zreada}
diff --git a/macros/plain/contrib/zztex/tex/zzlist.tex b/macros/plain/contrib/zztex/tex/zzlist.tex
new file mode 100644
index 0000000000..197090d153
--- /dev/null
+++ b/macros/plain/contrib/zztex/tex/zzlist.tex
@@ -0,0 +1,163 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% Module: ZzTeX List Facilities
+%
+% Synopsis:
+%
+% Author: Paul C. Anagnostopoulos
+% Created: 12 September 1989
+%
+% Copyright 1989--2020 by Paul C. Anagnostopoulos
+% under The MIT License (opensource.org/licenses/MIT)
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% List Block
+% ---- -----
+
+
+\defineblock{\list}{\endlist}{\false}{}
+\resetinvcontext{\list}
+
+%~block list Type, Level
+% \abovepenalty = integer % Penalty above list.
+% \aboveskip = glue % Space b/b above list.
+% \setflag \allowitemtag = flag % Allow \tag command on item.
+% \belowpenalty = integer % Penalty below list.
+% \belowskip = glue % Space b/b below list.
+% \bodyfont = {...} % Font for text.
+% \def \endpartext {...} % Text at end of each paragraph.
+% \interitemskip = skip % Extra space between items.
+% \itemnumber = integer % Number of first item.
+% \def \labelformat ##1{...} % Item label formatter.
+% \labelshift = dimen % Horizontal shift of label.
+% \def \labeltext {...} % Label text or \arg if \item{...}.
+% \labelwidth = dimen % Width of label or \naturalwidth.
+% \leftindent = glue % Left indentation.
+% \parindent = glue % Paragraph indent.
+% \parrag = dimen % Paragraph raggedness.
+% \parskip = glue % Paragraph skip.
+% \rightindent = glue % Right indentation.
+% \def \tagcomptext {...} % Composite text for tag, if not label.
+% \width = dimen % Width of text.
+%~end
+
+\defineskip{\interitemskip}{0pt}
+\definedimen{\labelshift}{0pt}
+\definedimen{\labelwidth}{0pt}
+
+\definecount{\nextitemnumber}{0}
+
+
+\def \list #1{% {type}
+ \endgraf
+ \beginblockscope{list}%
+ \global\increment \listdepth
+ \abovepenalty = \breakgood %~default hard
+ \setflag \allowitemtag = \false %~default soft
+ \belowpenalty = \breakgood %~default hard
+ \def \endpartext {}% %~default hard
+ \itemnumber = 1 %~default with
+ \def \tagcomptext {}% %~default soft
+ \processdesign{\list}{#1\romannumeral\listdepth}%
+ \global\increment \listnumber
+ \decrement \itemnumber
+ \listformat
+ \def \par {\endpartext \endgraf}%
+ \settaginfo{}{}} % No tag info so far.
+
+\def \endlist {%
+ \par
+ \futurelet\nexttoken \zendlist}
+
+\def \zendlist {%
+ \closeifinblock{\item}{\enditem}%
+ \endlistformat
+ \if \onep{\listdepth}%
+ \global\nextitemnumber = \itemnumber
+ \global\increment \nextitemnumber
+ \fi
+ \global\decrement \listdepth
+ \endblockscope{list}%
+ \parnext}
+
+\def \listformat {%
+ \the\bodyfont
+ \bbskipabove{\abovepenalty}{\aboveskip}%
+ \alterindentation{\leftindent}{\rightindent}%
+ \settextwidth{\width}%
+ \setparrag{\parrag}%
+ \advance \interitemskip by \baselineskip}
+
+\def \endlistformat{%
+ \bbskipbelowblockpar{\nexttoken}{\belowpenalty}{\belowskip}}
+
+
+% This macro helps with a list design that involves measuring some text.
+
+\def \setmeasuredlabel #1#2#3{% {extra-indent}{template}{formatter}
+ \def \labelformat ##1{#3}%
+ \measuretextwidth{\labelwidth}{#2}%
+ \labelshift = -\labelwidth
+ \leftindent = \labelwidth
+ \advance \leftindent by #1\relax}
+
+\def \adjustinteritemskip #1{% {amount} %^modifier
+ \with{\advance\interitemskip by #1}}
+
+%~ This modifier on |\list| is used when a list immediately follows
+%~ an |\item| command; that is, when an item is a sublist.
+%~ It eliminates the vertical space above the sublist.
+
+\def \immediatesublist {% %^modifier
+ \with{\abovepenalty = \breaknever
+ \aboveskip = 0pt}}
+
+% Item Block
+% ---- -----
+
+% The \item block is subordinate to the \list block, and thus inherits all
+% of its design parameters from \list.
+
+
+\defineblock{\item}{\enditem}{\false}{}
+
+%~block item
+% \difficulty = integer % Level of difficulty.
+%~end
+
+\def \item {% [{label}]
+ \blockmustbein{\item}{\list}%
+ \closeifinblock{\item}{\enditem}%
+ % Don't bother with block scope.
+ \difficulty = 0 %~default with
+ \zprocesswith % Instead of \processdesign.
+ \increment \itemnumber
+ \bbskipabove{\breakgood}{\interitemskip}%
+ \def \zarg {\arg}%
+ \if \tokeqlp{\labeltext}{\zarg}%
+ \def \znext {\itemformat}%
+ \else
+ \def \znext {\itemformat{\labeltext}}%
+ \fi
+ \znext}
+
+\def \enditem {%
+ \par}
+
+\def \itemformat #1{% {label}
+ \noindent
+ \kern \labelshift
+ \if \dimeqlp{\labelwidth}{\naturalwidth}%
+ {\labelformat{#1}}%
+ \else
+ \hbox to \labelwidth{\labelformat{#1}}%
+ \fi
+ \if \allowitemtag
+ \if \emptydefp{\tagcomptext}%
+ \settaginfo{#1}{???}%
+ \else
+ \settaginfo{\tagcomptext}{???}%
+ \fi
+ \fi
+ \ignorespaces}
diff --git a/macros/plain/contrib/zztex/tex/zzltrspc.tex b/macros/plain/contrib/zztex/tex/zzltrspc.tex
new file mode 100644
index 0000000000..7fcd6e5d72
--- /dev/null
+++ b/macros/plain/contrib/zztex/tex/zzltrspc.tex
@@ -0,0 +1,111 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% Module: Letterspacing Facility
+%
+% Synopsis: This module provides a fairly comprehensive letterspacing
+% facility for ZzTeX.
+%
+% Author: Paul C. Anagnostopoulos
+% Created: 10 July 1997
+%
+% Copyright 1989--2020 by Paul C. Anagnostopoulos
+% under The MIT License (opensource.org/licenses/MIT)
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% Letterspacing Commands
+% ------------- --------
+
+
+\defineskip{\zlspamount}{0pt}
+\defineskip{\zlspace}{0pt}
+
+
+\def \letterspace #1#2{% {amount[,space]}{text}
+ {\zlspparse #1,,\zmark
+ \zletterspace{#2}}}
+
+\def \eletterspace #1#2{% {amount[,space]}{text}
+ \edef \znext {\noexpand\letterspace{#1}{#2}}%
+ \znext}
+
+\def \zlspparse #1,#2,#3\zmark{%
+ \zlspamount = #1\relax
+ \if \emptyargp{#2}%
+ \measurespacewidth{\zlspace}%
+ \advance \zlspace by \zlspamount
+ \else
+ \zlspace = #2\relax
+ \fi}
+
+% These commands can be used in letterspaced text, but must do nothing
+% when letterspacing is not in progress.
+
+\let \lsp = \relax
+\let \nolsp = \relax
+\def \lspspace {\space}%
+\def \zlspoff {\relax}%
+\def \lspoff {\zlspoff}%
+\def \zlspon {\relax}%
+\def \lspon {\zlspon}%
+
+% Letterspacing Engine
+% ------------- ------
+
+
+\def \zletterspace #1{% {text}
+ \def \lsp {\nobreak\hskip \zlspamount}%
+ \def \lspspace {\hskip \zlspace}%
+ \def \zzlspoff {\zlspoff}%
+ \def \zzlspon {\zlspon}%
+ \setflag \zlsping = \true
+ \let \zlspprev = \relax
+ \setflag \zlspprevchar = \false
+ \let \zmark = \relax
+ {\zlspa #1\zmark}}
+
+\def \zlspa {\futurelet\zlspcur \zlspb}
+
+\def \zlspb {%
+ \let \znext = \zlspc
+ \if \tokeqlp{\zlspcur}{\zmark}%
+ \let \znext = \relax
+ \else\if \cateqlp{\noexpand\zlspcur}{\zspacetoken}%
+ \if \zlsping \aftergroup\lspspace \else \aftergroup\space \fi
+ \else\if \cateqlp{\noexpand\zlspcur}{\bgroup}%
+ \aftergroup{%
+ \else\if \cateqlp{\noexpand\zlspcur}{\egroup}%
+ \aftergroup}%
+ \else\if \tokeqlp{\zlspcur}{\zzlspoff}%
+ \setflag \zlsping = \false
+ \else\if \tokeqlp{\zlspcur}{\zzlspon}%
+ \setflag \zlsping = \true
+ \else
+ \let \znext = \zlspd
+ \fi\fi\fi\fi\fi\fi
+ \znext}
+
+\def \zlspc {% Discard current token.
+ \let \zlspprev = \zlspcur
+ \setflag \zlspprevchar = \false
+ \afterassignment\zlspa \let\zlspcur = }
+
+\long\def \zlspd #1{% Process current token.
+ \let \zlspprev = \zlspcur
+ \if \cateqlp{\noexpand#1}{\relax}%
+ \setflag \zlspprevchar = \false
+ \aftergroup#1%
+ \else\if \cateqlp{\noexpand#1}{\noexpand~}%
+ \setflag \zlspprevchar = \false
+ \if \zlsping \aftergroup\lspspace \else \aftergroup\space \fi
+ \else\if \orp{\andp{\codeeqlp{\zlspprev}{-}}{\codeeqlp{\zlspcur}{-}}}
+ {\orp{\andp{\codeeqlp{\zlspprev}{`}}{\codeeqlp{\zlspcur}{`}}}
+ {\andp{\codeeqlp{\zlspprev}{'}}{\codeeqlp{\zlspcur}{'}}}}%
+ \setflag \zlspprevchar = \true
+ \aftergroup#1%
+ \else
+ \if \andp{\zlspprevchar}{\zlsping}\aftergroup\lsp \fi
+ \setflag \zlspprevchar = \true
+ \aftergroup#1%
+ \fi\fi\fi
+ \zlspa}
diff --git a/macros/plain/contrib/zztex/tex/zzlucida.tex b/macros/plain/contrib/zztex/tex/zzlucida.tex
new file mode 100644
index 0000000000..6bfc5e5554
--- /dev/null
+++ b/macros/plain/contrib/zztex/tex/zzlucida.tex
@@ -0,0 +1,140 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% Module: ZzTeX Lucida Math Font Support
+%
+% Synopsis: This module contains various definitions and redefinitions
+% necessary to use the Lucida math fonts.
+%
+% Note: This module assumes the user is generating PostScript output.
+%
+% Author: Paul C. Anagnostopoulos
+% Created: 27 June 1992
+%
+% Copyright 1989--2020 by Paul C. Anagnostopoulos
+% under The MIT License (opensource.org/licenses/MIT)
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% Type Styles
+% ---- ------
+
+\setstyleskewchar{\msy}{"7F}
+\setstyleskewchar{\msy}{"30}
+
+% Redefine Math Characters
+% -------- ---- ----------
+
+
+\zmchar \Gamma \classvarfam \mexfam {D0}
+\zmchar \Delta \classvarfam \mexfam {D1}
+\zmchar \Theta \classvarfam \mexfam {D2}
+\zmchar \Lambda \classvarfam \mexfam {D3}
+\zmchar \Xi \classvarfam \mexfam {D4}
+\zmchar \Pi \classvarfam \mexfam {D5}
+\zmchar \Sigma \classvarfam \mexfam {D6}
+\zmchar \Upsilon \classvarfam \mexfam {D7}
+\zmchar \Phi \classvarfam \mexfam {D8}
+\zmchar \Psi \classvarfam \mexfam {D9}
+\zmchar \Omega \classvarfam \mexfam {DA}
+
+\zmchar {`=} \classrel \msyfam {83}
+\zmchar {`+} \classbinop \msyfam {82}
+
+\definemathdelimiter {`/} \classord \mitfam {3D} \mexfam {0E}
+
+\zmchar {`(} \classopen \mitfam {84}
+\definemathdelimiter {`(} \classord \mitfam {84} \mexfam {00}
+\zmchar {`)} \classclose \mitfam {85}
+\definemathdelimiter {`)} \classord \mitfam {85} \mexfam {01}
+
+\zmchar {`[} \classopen \mitfam {86}
+\definemathdelimiter {`[} \classord \mitfam {86} \mexfam {02}
+\zmchar {`]} \classclose \mitfam {87}
+\definemathdelimiter {`]} \classord \mitfam {87} \mexfam {03}
+
+\zmchar \angle \classord \msyfam {8B}
+\zmchar \bowtie \classrel \mitfam {F6}
+\zmchar \cong \classrel \msyfam {9B}
+\zmchar \doteq \classrel \msyfam {C9}
+\zmchar \models \classrel \msyfam {EE}
+
+ \if \zusemar
+\zmchar \hbar \classord \mitfam {9D}
+\zmchar \hookleftarrow \classrel \marfam {3C}
+\zmchar \hookrightarrow \classrel \marfam {3E}
+\zmchar \leftrightharpoons \classrel \marfam {79}
+\zmchar \mapsto \classrel \marfam {2C}
+\zmchar \neq \classrel \marfam {94}
+\zmchar \rightleftharpoons \classrel \marfam {7A}
+ \fi
+
+% New Math Characters
+% --- ---- ----------
+
+
+ \if \zusemar
+\zmchar \notapprox \classrel \marfam {98}
+\zmchar \notasymp \classrel \marfam {F3}
+\zmchar \notcong \classrel \marfam {99}
+\zmchar \noteq \classrel \marfam {94}
+\zmchar \notequiv \classrel \marfam {95}
+\zmchar \notgeq \classrel \marfam {9D}
+\zmchar \notgreater \classrel \marfam {9B}
+\zmchar \notin \classrel \marfam {1D}
+\zmchar \notleq \classrel \marfam {9C}
+\zmchar \notless \classrel \marfam {9A}
+\zmchar \notmid \classrel \marfam {F6}
+\zmchar \notmodels \classrel \marfam {F9}
+\zmchar \notni \classrel \marfam {1F}
+\zmchar \notparallel \classrel \marfam {F7}
+\zmchar \notprec \classrel \marfam {E5}
+\zmchar \notpreceq \classrel \marfam {E7}
+\zmchar \notsim \classrel \marfam {96}
+\zmchar \notsimeq \classrel \marfam {97}
+\zmchar \notsqsubseteq \classrel \marfam {D4}
+\zmchar \notsqsupseteq \classrel \marfam {D5}
+\zmchar \notsubset \classrel \marfam {C6}
+\zmchar \notsubseteq \classrel \marfam {C8}
+\zmchar \notsucc \classrel \marfam {E6}
+\zmchar \notsucceq \classrel \marfam {E8}
+\zmchar \notsupset \classrel \marfam {C7}
+\zmchar \notsupseteq \classrel \marfam {C9}
+\zmchar \notvdash \classrel \marfam {F8}
+ \fi
+
+% Redefine General Tools
+% -------- ------- -----
+
+
+\def \big #1{{\hbox{$\left#1\vbox to 8.2pt{}\right.\zmnosp$}}}
+\def \Big #1{{\hbox{$\left#1\vbox to 10.8pt{}\right.\zmnosp$}}}
+\def \bigg #1{{\hbox{$\left#1\vbox to 13.42pt{}\right.\zmnosp$}}}
+\def \Bigg #1{{\hbox{$\left#1\vbox to 16.03pt{}\right.\zmnosp$}}}
+\def \biggg #1{{\hbox{$\left#1\vbox to 17.72pt{}\right.\zmnosp$}}}
+\def \Biggg #1{{\hbox{$\left#1\vbox to 21.25pt{}\right.\zmnosp$}}}
+
+\def \bigggl {\mathopen\biggg}
+\def \Bigggl {\mathopen\Biggg}
+\def \bigggr {\mathclose\biggg}
+\def \Bigggr {\mathclose\Biggg}
+
+\def \joinrel {\mathrel{\mkern -4mu}}
+
+\def \mathstrut {\vphantom{f}}
+
+\def \matrix #1{%
+ \null\nonscript\,%
+ \vcenter{\normalbaselines
+ \ialign{\hfil $##$\hfil&& \quad \hfil $##$\hfil \crcr
+ \mathstrut\crcr
+ \noalign{\kern -0.9\baselineskip}%
+ #1\crcr
+ \mathstrut\crcr
+ \noalign{\kern -0.9\baselineskip}}}%
+ \nonscript\,}
+
+\def \zroot #1#2{% {\style}{radicand}
+ \setbox\zboxa = \hbox{$#1\sqrt{#2}$}%
+ \tdimena = \ht\zboxa
+ \advance \tdimena by -\dp\zboxa
+ \mkern 5mu \raise .6\tdimena \copy\zrootbox \mkern -8mu \box\zboxa}
diff --git a/macros/plain/contrib/zztex/tex/zzmath.tex b/macros/plain/contrib/zztex/tex/zzmath.tex
new file mode 100644
index 0000000000..9a39dd2f0b
--- /dev/null
+++ b/macros/plain/contrib/zztex/tex/zzmath.tex
@@ -0,0 +1,1919 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% Module: ZzTeX Mathematics Facilities
+%
+% Synopsis: This file provides the mathematics facilities of
+% ZzTeX. All of the Plain TeX math stuff is included.
+%
+% Author: Paul C. Anagnostopoulos
+% Created: 14 November 1990
+%
+% Copyright 1989--2020 by Paul C. Anagnostopoulos
+% under The MIT License (opensource.org/licenses/MIT)
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% Math Version
+% ---- -------
+
+
+\definecount{\zmathver}{0}
+
+
+\def \mathversion #1{%
+ \global\zmathver = #1\relax
+ \input zzmathv#1\relax}
+
+% Alternate Math Fonts
+% --------- ---- -----
+
+
+\outer\def \ComputerModernmathfonts {%
+ \input zzcmmath\relax}
+
+\outer\def \Lucidamathfonts #1{% {arrows?}
+ \setflag \zusemar = #1\relax
+ \input zzlucida\relax}
+
+\outer\def \MathTimefonts {%
+ \input zzmtime\relax}
+
+% Spacing
+% -------
+
+
+% Note major uses of each kind of space:
+% thin: around large operators; after punctuation
+% medium: around binary operators
+% thick: around relational operators
+
+\def \setmathspaces #1#2#3{% {thin}{medium}{thick}
+ \global\thinmuskip = #1\relax
+ \global\medmuskip = #2\relax
+ \global\thickmuskip = #3\relax}
+
+\def \mthickspace {\mkern 2\thinmuskip}
+
+\def \mthinspace {\mkern \thinmuskip}
+\def \mnegthinspace {\mkern -\thinmuskip}
+
+\def \mspace #1{\mkern #1\relax}% {mu}
+
+% Math mode \, \; \! are in ZZHMODE.
+
+\def \setTeXmathspaces {%
+ \setmathspaces{3mu}{4mu plus 2mu minus 4mu}{5mu plus 5mu}}
+
+% Character Definition
+% --------- ----------
+
+
+% These are the math character classes:
+
+\chardef \classord = 0 % An ordinary symbol (\alpha). %^math_class
+\chardef \classlargeop = 1 % A large operator (\sum).. %^math_class
+\chardef \classbinop = 2 % A binary operator (+). %^math_class
+\chardef \classrel = 3 % A relation (=). %^math_class
+\chardef \classopen = 4 % An opening fence ([). %^math_class
+\chardef \classclose = 5 % A closing fence (]). %^math_class
+\chardef \classpunc = 6 % A punctuation character (,). %^math_class
+\chardef \classvarfam = 7 % A character that varies with \fam (\Gamma). %^math_class
+\chardef \classactive = 8 % An active character ('). %^math_class
+
+
+\def \definemathaccent #1#2#3#4{% {name}{class}{family}{hex-code}
+ {\zcalcmathcode{#2}{#3}{#4}%
+ \xdef #1{\mathaccent \the\tcounta\relax}}%
+ \ignorespaces}
+
+\def \definemathchar #1#2#3#4{% {name}{class}{family}{hex-code}
+ {\zcalcmathcode{#2}{#3}{#4}%
+ \zdefmathch#1\zmark
+ \if \znext
+ \global\mathcode #1= \tcounta
+ \else
+ \global\mathchardef #1= \tcounta
+ \fi}%
+ \ignorespaces}
+
+\def \definemathdelimiter #1#2#3#4#5#6{% {name}{class}{fam1}{hex1}{fam2}{hex2}
+ {\zcalcmathcode{#2}{#3}{#4}%
+ \multiply \tcounta by 16
+ \advance \tcounta by #5
+ \multiply \tcounta by 256
+ \advance \tcounta by "#6\relax
+ \zdefmathch#1\zmark
+ \if \znext
+ \global\delcode #1= \tcounta
+ \else
+ \xdef #1{\delimiter\the\tcounta\relax}%
+ \fi}%
+ \ignorespaces}
+
+\def \definemathjoinedsymbol #1#2#3#4#5{% {name}{atom}{char1}{char2}{sep}
+ \gdef #1{#2{{#3}\mspace{#5mu}{#4}}}}
+
+\def \definemathlabeledarrow #1#2#3#4{% {name}{atom}{label}{arrow}
+ \gdef #1{#2{\mathop{#4}\limits^{#3}}}}
+
+\def \definemathstackedsymbol #1#2#3#4#5{% {name}{atom}{char1}{char2}{sep}
+ \gdef #1{#2{\mathpalette\zstksym{{#3}{#4}{#5}}}}}
+
+
+\def \zcalcmathcode #1#2#3{% {class}{family}{hex-code}
+ \tcounta = #1
+ \multiply \tcounta by 16
+ \advance \tcounta by #2
+ \multiply \tcounta by 256
+ \advance \tcounta by "#3\relax}
+
+\def \zdefmathch #1#2\zmark{%
+ \setflag\znext = {\if `\noexpand#1\true \else \false \fi}}
+
+\definedimen{\muwidth}{0pt}
+
+\def \zstksym #1#2{% {style}{{char1}{char2}{sep}}
+ \zstksymb #1#2}
+
+\def \zstksymb #1#2#3#4{% {style}{char1}{char2}{sep}
+ \vcenter{\baselineskip = 0pt
+ \lineskiplimit = -\maxdimen
+ \setbox \zboxa = \hbox{$#1\mkern 1mu$}%
+ \muwidth = \wd\zboxa
+ \ialign{\hfil ##\hfil\cr
+ \raise #4\muwidth \hbox{$#1#2$}\cr
+ $#1#3$\cr}}}
+
+% Character Styles
+% --------- ------
+
+
+\definecount{\zmstyfam}{0}
+
+
+\def \setmathdigitstyle #1{% {style}
+ {\tcounta = "\the\classvarfam0
+ \advance \tcounta by \name{#1fam}%
+ \multiply \tcounta by 256
+ \advance \tcounta by `\0%
+ \tcountb = `0
+ \loop
+ \global\mathcode \tcountb = \tcounta
+ \increment \tcounta
+ \increment \tcountb
+ \if \lssp{\tcountb}{`\:}\repeat}}
+
+\def \setmathletterstyle #1{% {\style}
+ {\tcounta = "\the\classvarfam0
+ \advance \tcounta by \name{#1fam}%
+ \multiply \tcounta by 256
+ \advance \tcounta by `\A%
+ \tcountb = `A
+ \loop
+ \global\mathcode \tcountb = \tcounta
+ \increment \tcounta
+ \increment \tcountb
+ \if \lssp{\tcountb}{`\[}\repeat
+ \advance \tcounta by 6
+ \tcountb = `\a
+ \loop
+ \global\mathcode \tcountb = \tcounta
+ \increment \tcounta
+ \increment \tcountb
+ \if \lssp{\tcountb}{`\{}\repeat}%
+ \if \zcommonencoding
+ \def \znext {#1}%
+ \def \zit {\it}%
+ \if \tokeqlp{\znext}{\zit}\setstyleskewchar{#1}{7}\fi
+ \fi}
+
+\def \setmathucgreekstyle #1{% {style}
+ {\zmstyfam = \name{#1fam}%
+\definemathchar \Alpha \classvarfam \rmfam {41}
+\definemathchar \Beta \classvarfam \rmfam {42}
+\definemathchar \Gamma \classvarfam \zmstyfam {00}
+\definemathchar \Delta \classvarfam \zmstyfam {01}
+\definemathchar \Epsilon \classvarfam \rmfam {45}
+\definemathchar \Zeta \classvarfam \rmfam {5A}
+\definemathchar \Eta \classvarfam \rmfam {48}
+\definemathchar \Theta \classvarfam \zmstyfam {02}
+\definemathchar \Iota \classvarfam \rmfam {49}
+\definemathchar \Kappa \classvarfam \rmfam {4B}
+\definemathchar \Lambda \classvarfam \zmstyfam {03}
+\definemathchar \Mu \classvarfam \rmfam {4D}
+\definemathchar \Nu \classvarfam \rmfam {4E}
+\definemathchar \Xi \classvarfam \zmstyfam {04}
+\definemathchar \Omicron \classvarfam \rmfam {4F}
+\definemathchar \Pi \classvarfam \zmstyfam {05}
+\definemathchar \Rho \classvarfam \rmfam {50}
+\definemathchar \Sigma \classvarfam \zmstyfam {06}
+\definemathchar \Tau \classvarfam \rmfam {54}
+\definemathchar \Upsilon \classvarfam \zmstyfam {07}
+\definemathchar \Phi \classvarfam \zmstyfam {08}
+\definemathchar \Chi \classvarfam \rmfam {58}
+\definemathchar \Psi \classvarfam \zmstyfam {09}
+\definemathchar \Omega \classvarfam \zmstyfam {0A}}}
+
+\def \zmtextstyle {\rm}
+\def \zmtextfam {\rmfam}
+
+\def \setmathtextstyle #1{% {style}
+ \gdef \zmtextstyle {#1}%
+ \xdef \zmtextfam {\name{#1fam}}}
+
+\def \zmfunstyle {\rm}
+
+\def \setmathfunctionstyle #1{% {style}
+ \gdef \zmfunstyle {#1}}
+
+\def \zmvarstyle {\it}
+
+\def \setmathmvarstyle #1{% {style}
+ \gdef \zmvarstyle {#1}}
+
+\def \setmathpunctuationstyle #1{% {style}
+ {\zmstyfam = \name{#1fam}%
+ \definemathchar {`.} \classord \zmstyfam {2E}
+ \definemathchar {`,} \classpunc \zmstyfam {2C}
+ \definemathchar {`;} \classpunc \zmstyfam {3B}}}
+
+% Characters
+% ----------
+
+
+\let \zmchar = \definemathchar
+
+
+% Letters:
+
+% INITEX does the following for each letter:
+%
+% \definemathchar{letter}{\classvarfam}{\mit}{xx}
+%
+% This can be changed using the \setmathletterstyle command above.
+
+
+% Figures (digits):
+
+% INITEX does the following for each digit:
+%
+% \definemathchar{digit}{\classvarfam}{\rm}{xx}
+%
+% This can be changed using the \setmathdigitstyle command above.
+
+
+% Uppercase Greek letters:
+
+% This can be changed using the \setmathucgreekstyle command above.
+
+\setmathucgreekstyle{\rm}
+
+
+% Lowercase Greek letters:
+
+\zmchar \alpha \classord \mitfam {0B}
+\zmchar \beta \classord \mitfam {0C}
+\zmchar \gamma \classord \mitfam {0D}
+\zmchar \delta \classord \mitfam {0E}
+\zmchar \epsilon \classord \mitfam {0F}
+\zmchar \zeta \classord \mitfam {10}
+\zmchar \eta \classord \mitfam {11}
+\zmchar \theta \classord \mitfam {12}
+\zmchar \iota \classord \mitfam {13}
+\zmchar \kappa \classord \mitfam {14}
+\zmchar \lambda \classord \mitfam {15}
+\zmchar \mu \classord \mitfam {16}
+\zmchar \nu \classord \mitfam {17}
+\zmchar \xi \classord \mitfam {18}
+\zmchar \omicron \classord \mitfam {6F}
+\zmchar \pi \classord \mitfam {19}
+\zmchar \rho \classord \mitfam {1A}
+\zmchar \sigma \classord \mitfam {1B}
+\zmchar \tau \classord \mitfam {1C}
+\zmchar \upsilon \classord \mitfam {1D}
+\zmchar \phi \classord \mitfam {1E}
+\zmchar \chi \classord \mitfam {1F}
+\zmchar \psi \classord \mitfam {20}
+\zmchar \omega \classord \mitfam {21}
+
+\zmchar \varepsilon \classord \mitfam {22}
+\zmchar \vartheta \classord \mitfam {23}
+\zmchar \varpi \classord \mitfam {24}
+\zmchar \varrho \classord \mitfam {25}
+\zmchar \varsigma \classord \mitfam {26}
+\zmchar \varphi \classord \mitfam {27}
+
+
+% Ordinary symbols:
+
+\zmchar {`.} \classord \rmfam {2E}
+\zmchar {`/} \classord \mitfam {3D}
+\zmchar \zmbackslash \classord \msyfam {6E}
+\zmchar {`|} \classord \msyfam {6A}
+\zmchar \aleph \classord \msyfam {40}
+\zmchar \bot \classord \msyfam {3F}
+\zmchar \clubsuit \classord \msyfam {7C}
+\zmchar \diamondsuit \classord \msyfam {7D}
+\zmchar \ell \classord \mitfam {60}
+\zmchar \emptyset \classord \msyfam {3B}
+\zmchar \exists \classord \msyfam {39}
+\zmchar \flat \classord \mitfam {5B}
+\zmchar \forall \classord \msyfam {38}
+\zmchar \heartsuit \classord \msyfam {7E}
+\zmchar \Im \classord \msyfam {3D}
+\zmchar \imath \classord \mitfam {7B}
+\zmchar \infinity \classord \msyfam {31}
+\let \infty = \infinity
+\zmchar \jmath \classord \mitfam {7C}
+\zmchar \nabla \classord \msyfam {72}
+\zmchar \natural \classord \mitfam {5C}
+\zmchar \neg \classord \msyfam {3A}
+\let \lnot = \neg
+\zmchar \partial \classord \mitfam {40}
+\zmchar \prime \classord \msyfam {30}
+\zmchar \Re \classord \msyfam {3C}
+\zmchar \sharp \classord \mitfam {5D}
+\zmchar \spadesuit \classord \msyfam {7F}
+\zmchar \surd \classord \msyfam {70}
+\zmchar \top \classord \msyfam {3E}
+\zmchar \triangle \classord \msyfam {34}
+\zmchar \wp \classord \mitfam {7D}
+
+
+% Large operations:
+
+\zmchar \bigcap \classlargeop \mexfam {54}
+\zmchar \bigcup \classlargeop \mexfam {53}
+\zmchar \bigodot \classlargeop \mexfam {4A}
+\zmchar \bigoplus \classlargeop \mexfam {4C}
+\zmchar \bigotimes \classlargeop \mexfam {4E}
+\zmchar \bigsqcup \classlargeop \mexfam {46}
+\zmchar \biguplus \classlargeop \mexfam {55}
+\zmchar \bigvee \classlargeop \mexfam {57}
+\zmchar \bigwedge \classlargeop \mexfam {56}
+\zmchar \coprod \classlargeop \mexfam {60}
+\zmchar \intop \classlargeop \mexfam {52}
+\zmchar \ointop \classlargeop \mexfam {48}
+\zmchar \prod \classlargeop \mexfam {51}
+\zmchar \smallint \classlargeop \msyfam {73}
+\zmchar \sum \classlargeop \mexfam {50}
+
+
+% Binary operations:
+
+\zmchar {`*} \classbinop \msyfam {03}
+\zmchar {`+} \classbinop \rmfam {2B}
+\zmchar {`-} \classbinop \msyfam {00}
+\zmchar \amalg \classbinop \msyfam {71}
+\zmchar \ast \classbinop \msyfam {03}
+\zmchar \bigcirc \classbinop \msyfam {0D}
+\zmchar \bigtriangledown \classbinop \msyfam {35}
+\zmchar \bigtriangleup \classbinop \msyfam {34}
+\zmchar \zmbullet \classbinop \msyfam {0F}
+\zmchar \cap \classbinop \msyfam {5C}
+\zmchar \cdot \classbinop \msyfam {01}
+\zmchar \circ \classbinop \msyfam {0E}
+\let \compose = \circ
+\zmchar \cup \classbinop \msyfam {5B}
+\zmchar \zmdagger \classbinop \msyfam {79}
+\zmchar \zmddagger \classbinop \msyfam {7A}
+\zmchar \diamond \classbinop \msyfam {05}
+\zmchar \div \classbinop \msyfam {04}
+\zmchar \mp \classbinop \msyfam {07}
+\zmchar \odot \classbinop \msyfam {0C}
+\zmchar \ominus \classbinop \msyfam {09}
+\zmchar \oplus \classbinop \msyfam {08}
+\zmchar \oslash \classbinop \msyfam {0B}
+\zmchar \otimes \classbinop \msyfam {0A}
+\zmchar \pm \classbinop \msyfam {06}
+\zmchar \setminus \classbinop \msyfam {6E}
+\zmchar \sqcap \classbinop \msyfam {75}
+\zmchar \sqcup \classbinop \msyfam {74}
+\zmchar \star \classbinop \mitfam {3F}
+\zmchar \times \classbinop \msyfam {02}
+\let \cross = \times
+\zmchar \triangleleft \classbinop \mitfam {2F}
+\zmchar \triangleright \classbinop \mitfam {2E}
+\zmchar \uplus \classbinop \msyfam {5D}
+\zmchar \vee \classbinop \msyfam {5F}
+\let \lor = \vee
+\zmchar \wedge \classbinop \msyfam {5E}
+\let \land = \wedge
+\zmchar \wr \classbinop \msyfam {6F}
+
+
+% Relations:
+
+\zmchar {`:} \classrel \rmfam {3A}
+\zmchar {`<} \classrel \mitfam {3C}
+\zmchar {`=} \classrel \rmfam {3D}
+\zmchar {`>} \classrel \mitfam {3E}
+\zmchar \approx \classrel \msyfam {19}
+\zmchar \asymp \classrel \msyfam {10}
+\zmchar \dashv \classrel \msyfam {61}
+\zmchar \equiv \classrel \msyfam {11}
+\zmchar \frown \classrel \mitfam {5F}
+\zmchar \geq \classrel \msyfam {15}
+\let \ge = \geq
+\let \gets = \leftarrow
+\zmchar \gg \classrel \msyfam {1D}
+\zmchar \in \classrel \msyfam {32}
+\zmchar \Leftarrow \classrel \msyfam {28}
+\zmchar \leftarrow \classrel \msyfam {20}
+\zmchar \leftharpoondown \classrel \mitfam {29}
+\zmchar \leftharpoonup \classrel \mitfam {28}
+\zmchar \Leftrightarrow \classrel \msyfam {2C}
+\zmchar \leftrightarrow \classrel \msyfam {24}
+\zmchar \leq \classrel \msyfam {14}
+\let \le = \leq
+\zmchar \lhook \classrel \mitfam {2C}
+\zmchar \ll \classrel \msyfam {1C}
+\zmchar \mapstochar \classrel \msyfam {37}
+\zmchar \mid \classrel \msyfam {6A}
+\let \given = \mid
+\zmchar \nearrow \classrel \msyfam {25}
+\zmchar \ni \classrel \msyfam {33}
+\zmchar \not \classrel \msyfam {36}
+\zmchar \nwarrow \classrel \msyfam {2D}
+\let \owns = \ni
+\zmchar \parallel \classrel \msyfam {6B}
+\zmchar \perp \classrel \msyfam {3F}
+\zmchar \prec \classrel \msyfam {1E}
+\zmchar \preceq \classrel \msyfam {16}
+\zmchar \propto \classrel \msyfam {2F}
+\zmchar \rhook \classrel \mitfam {2D}
+\zmchar \Rightarrow \classrel \msyfam {29}
+\zmchar \rightarrow \classrel \msyfam {21}
+\zmchar \rightharpoondown \classrel \mitfam {2B}
+\zmchar \rightharpoonup \classrel \mitfam {2A}
+\zmchar \searrow \classrel \msyfam {26}
+\zmchar \sim \classrel \msyfam {18}
+\zmchar \simeq \classrel \msyfam {27}
+\zmchar \smile \classrel \mitfam {5E}
+\zmchar \subset \classrel \msyfam {1A}
+\zmchar \subseteq \classrel \msyfam {12}
+\zmchar \succ \classrel \msyfam {1F}
+\zmchar \succeq \classrel \msyfam {17}
+\zmchar \supset \classrel \msyfam {1B}
+\zmchar \supseteq \classrel \msyfam {13}
+\zmchar \swarrow \classrel \msyfam {2E}
+\zmchar \sqsubseteq \classrel \msyfam {76}
+\zmchar \sqsupseteq \classrel \msyfam {77}
+\let \to = \rightarrow
+\zmchar \vdash \classrel \msyfam {60}
+
+
+% Openers:
+
+\zmchar {`(} \classopen \rmfam {28}
+\zmchar {`[} \classopen \rmfam {5B}
+\zmchar {`\{} \classopen \msyfam {66}
+
+
+% Closers:
+
+\zmchar {`!} \classclose \rmfam {21}
+\zmchar {`)} \classclose \rmfam {29}
+\zmchar {`?} \classclose \rmfam {3F}
+\zmchar {`]} \classclose \rmfam {5D}
+\zmchar {`\}} \classclose \msyfam {67}
+
+
+% Punctuation:
+
+\zmchar {`,} \classpunc \rmfam {2C}
+\zmchar {`;} \classpunc \rmfam {3B}
+\zmchar \cdotp \classpunc \msyfam {01}
+\zmchar \maps \classpunc \rmfam {3A}
+\let \colon = \maps
+\zmchar \ldotp \classpunc \mitfam {3A}
+
+
+% Active characters:
+
+\zmchar {` } \classactive \rmfam {00}
+\zmchar {`'} \classactive \rmfam {00}
+
+{\catcode`\' = \catactive
+\gdef '{^\bgroup \zmprima}
+} % \catcode
+
+\def \zmprima {\prime \futurelet\znext \zmprimb}
+\def \zmprimb {%
+ \if \tokeqlp{\znext}{'}%
+ \let \znext = \zmprimc
+ \else \if \tokeqlp{\znext}{^}%
+ \let \znext = \zmprimd
+ \else
+ \let \znext = \egroup
+ \fi\fi
+ \znext}
+\def \zmprimc #1{\zmprima}
+\def \zmprimd #1#2{#2\egroup}
+
+% Delimiters
+% ----------
+
+% IniTeX does the following for each character:
+%
+% \delcode`x = -1
+
+\definemathdelimiter{`(}{\classord}{\rmfam}{28}{\mexfam}{00}
+\definemathdelimiter{`)}{\classord}{\rmfam}{29}{\mexfam}{01}
+\definemathdelimiter{`/}{\classord}{\rmfam}{2F}{\mexfam}{0E}
+\definemathdelimiter{`<}{\classord}{\msyfam}{68}{\mexfam}{0A}
+\definemathdelimiter{`>}{\classord}{\msyfam}{69}{\mexfam}{0B}
+\definemathdelimiter{`[}{\classord}{\rmfam}{5B}{\mexfam}{02}
+\definemathdelimiter{`]}{\classord}{\rmfam}{5D}{\mexfam}{03}
+\definemathdelimiter{`|}{\classord}{\msyfam}{6A}{\mexfam}{0C}
+
+\definemathdelimiter{\Arrowvert}{\classord}{\mexfam}{3D}{\rmfam}{00}
+\definemathdelimiter{\arrowvert}{\classord}{\mexfam}{3C}{\rmfam}{00}
+\definemathdelimiter{\bracevert}{\classord}{\mexfam}{3E}{\rmfam}{00}
+\definemathdelimiter{\Downarrow}{\classrel}{\msyfam}{2B}{\mexfam}{7F}
+\definemathdelimiter{\downarrow}{\classrel}{\msyfam}{23}{\mexfam}{79}
+\definemathdelimiter{\langle}{\classopen}{\msyfam}{68}{\mexfam}{0A}
+\definemathdelimiter{\lceil}{\classopen}{\msyfam}{64}{\mexfam}{06}
+\definemathdelimiter{\lfloor}{\classopen}{\msyfam}{62}{\mexfam}{04}
+\definemathdelimiter{\lgroup}{\classopen}{\rmfam}{00}{\mexfam}{3A}
+\definemathdelimiter{\lmoustache}{\classopen}{\rmfam}{00}{\mexfam}{40}
+\definemathdelimiter{\rangle}{\classclose}{\msyfam}{69}{\mexfam}{0B}
+\definemathdelimiter{\rceil}{\classclose}{\msyfam}{65}{\mexfam}{07}
+\definemathdelimiter{\rfloor}{\classclose}{\msyfam}{63}{\mexfam}{05}
+\definemathdelimiter{\rgroup}{\classclose}{\rmfam}{00}{\mexfam}{3B}
+\definemathdelimiter{\rmoustache}{\classclose}{\rmfam}{00}{\mexfam}{41}
+\definemathdelimiter{\Uparrow}{\classrel}{\msyfam}{2A}{\mexfam}{7E}
+\definemathdelimiter{\uparrow}{\classrel}{\msyfam}{22}{\mexfam}{78}
+\definemathdelimiter{\Updownarrow}{\classrel}{\msyfam}{6D}{\mexfam}{77}
+\definemathdelimiter{\updownarrow}{\classrel}{\msyfam}{6C}{\mexfam}{3F}
+\definemathdelimiter{\Vert}{\classord}{\msyfam}{6B}{\mexfam}{0D}
+\definemathdelimiter{\vert}{\classord}{\msyfam}{6A}{\mexfam}{0C}
+\definemathdelimiter{\zmbackslash}{\classord}{\msyfam}{6E}{\mexfam}{0F}
+\definemathdelimiter{\zmlbrace}{\classopen}{\msyfam}{66}{\mexfam}{08}
+\definemathdelimiter{\zmrbrace}{\classclose}{\msyfam}{67}{\mexfam}{09}
+
+% Accents
+% -------
+
+
+\definemathaccent{\acute}{\classvarfam}{\rmfam}{13}
+\definemathaccent{\bar}{\classvarfam}{\rmfam}{16}
+\definemathaccent{\breve}{\classvarfam}{\rmfam}{15}
+\definemathaccent{\check}{\classvarfam}{\rmfam}{14}
+\definemathaccent{\ddot}{\classvarfam}{\rmfam}{7F}
+\definemathaccent{\dot}{\classvarfam}{\rmfam}{5F}
+\definemathaccent{\grave}{\classvarfam}{\rmfam}{12}
+\definemathaccent{\zmhat}{\classvarfam}{\rmfam}{5E}
+\definemathaccent{\zmtilde}{\classvarfam}{\rmfam}{7E}
+\definemathaccent{\ring}{\classvarfam}{\rmfam}{17}
+\definemathaccent{\widetilde}{\classord}{\mexfam}{65}
+\definemathaccent{\widehat}{\classord}{\mexfam}{62}
+\definemathaccent{\vec}{\classord}{\mitfam}{7E}
+
+\def \widebar #1{% {math} %~ Wide bar accent. %^math_accent
+ \mathpalette\zwidebar{#1}}
+
+\def \zwidebar #1#2{% {style}{math}
+ \rlap{\measuretextwidth{\tdimena}{$#1#2$}%
+ \kern .2\tdimena
+ $\overline{\vphantom{#1#2}\kern .6\tdimena}$}%
+ #2}
+
+% Defined Characters
+% ------- ----------
+
+
+\def \angle {%
+ {\vbox{\ialign{$\scriptstyle##$\cr
+ \not \mathrel{\mkern 14mu}\cr
+ \noalign{\nointerlineskip}%
+ \mkern 2.5mu \leaders \hrule height .34pt \hfill
+ \mkern 2.5mu\cr}}}}
+
+\definemathjoinedsymbol{\bowtie}{\mathrel}{\triangleright}{\triangleleft}{-3}
+
+\definemathstackedsymbol{\cong}{\mathrel}{\sim}{=}{6}
+
+\def \degree {^\circ}
+
+\let \degrees = \degree
+
+\def \defeq{%
+ \mathrel{\mathop{=}\limits^{\mathscriptscriptstyle{\roman{def}}}}}
+
+\definemathstackedsymbol{\Deltaeq}{\mathrel}{\mathscriptscriptstyle{\Delta}}{=}{9}
+
+\definemathstackedsymbol{\doteq}{\mathrel}{.}{=}{9}
+
+\definemathstackedsymbol{\gel}{\mathrel}{\zge}{<}{11}
+
+\definemathstackedsymbol{\zge}{\mathrel}{>}{=}{7.5}
+
+\definemathstackedsymbol{\gl}{\mathrel}{>}{<}{5.5}
+
+\def \hbar {\mathord{h \llap{$\mathchar"16 \mkern 3.5mu$}}}
+
+\definemathjoinedsymbol{\hookleftarrow}{\mathrel}{\leftarrow}{\rhook}{-3}
+
+\definemathjoinedsymbol{\hookrightarrow}{\mathrel}{\lhook}{\rightarrow}{-3}
+
+\def \int {\intop\nolimits}
+
+\def \iint {\zint2}
+
+\def \iiint {\zint3}
+
+\def \iiiint {\zint4}
+
+\def \idotsint {\zint0}
+
+\def \zint #1{%
+ \mkern -9mu \mathchoice{\mkern -5mu}{}{}{}%
+ \mathop{%
+ \mkern 9mu \mathchoice{\mkern 5mu}{}{}{}%
+ \intop
+ \ifcase #1%
+ \mkern -4mu \cdots \mkern -4mu
+ \or \relax \or
+ \zintkern
+ \or
+ \zintkern \intop \zintkern
+ \or
+ \zintkern \intop \zintkern \intop \zintkern
+ \fi}%
+ \intop\nolimits}
+
+\def \zintkern {\mkern -8mu \mathchoice{\mkern -3mu}{}{}{}}
+
+\let \join = \bowtie
+
+\definemathstackedsymbol{\leftrightarrows}{\mathrel}{\leftarrow}{\rightarrow}{6}
+
+\definemathstackedsymbol{\leftrightharpoons}{\mathrel}{\leftharpoonup}{\rightharpoondown}{4}
+
+\definemathstackedsymbol{\ltgt}{\mathrel}{<}{>}{5.5}
+
+\definemathjoinedsymbol{\Longleftarrow}{\mathrel}{\Leftarrow}{\Relbar}{-3}
+
+\definemathjoinedsymbol{\longleftarrow}{\mathrel}{\leftarrow}{\relbar}{-3}
+
+\definemathjoinedsymbol{\Longleftrightarrow}{\mathrel}{\Leftarrow}{\Rightarrow}{-3}
+\let \iff = \Longleftrightarrow
+
+\definemathjoinedsymbol{\longleftrightarrow}{\mathrel}{\leftarrow}{\rightarrow}{-3}
+
+\def \longmapsto {\mapstochar \longrightarrow}
+
+\definemathjoinedsymbol{\Longrightarrow}{\mathrel}{\Relbar}{\Rightarrow}{-3}
+
+\definemathjoinedsymbol{\longrightarrow}{\mathrel}{\relbar}{\rightarrow}{-3}
+
+\definemathjoinedsymbol{\longrightleftarrow}{\mathrel}{\rightarrow}{\leftarrow}{-3}
+
+\def \oint {\ointop\nolimits}
+
+\def \mapsto {\mapstochar \rightarrow}
+
+\definemathjoinedsymbol{\models}{\mathrel}{|}{=}{-3}
+
+\def \neq {\not=}
+\let \ne = \neq
+
+\def \nexists {\mathord{\raise .2ex \hbox{$\not\mkern 1.5mu$}\exists}}
+
+\def \notin {\not\in}
+\let \nin = \notin
+
+\def \nparallel {\mathrel{\not\mkern 2mu\parallel}}
+
+\definemathstackedsymbol{\rightleftarrows}{\mathrel}{\rightarrow}{\leftarrow}{6}
+
+\definemathstackedsymbol{\rightleftharpoons}{\mathrel}{\rightharpoonup}{\leftharpoondown}{4}
+
+\definemathjoinedsymbol{\semijoin}{\mathrel}{\triangleright}{<}{-4}
+
+% Functions
+% ---------
+
+
+\def \definemathfunction #1#2#3{% {\name}{text}{limits}
+ \def #1{\mathop{\zmfunstyle #2}#3}}
+
+\definemathfunction{\ad}{ad}{\nolimits} % adjoint
+\definemathfunction{\Ai}{Ai}{\nolimits} % Airy function
+\definemathfunction{\arccos}{arccos}{\nolimits} % arc cosine
+\definemathfunction{\arccosh}{arccosh}{\nolimits} % hyperbolic arc cosine
+\definemathfunction{\arccot}{arccot}{\nolimits} % arc cotangent
+\definemathfunction{\arcsec}{arcsec}{\nolimits} % arc secant
+\definemathfunction{\arcsin}{arcsin}{\nolimits} % arc sine
+\definemathfunction{\arctan}{arctan}{\nolimits} % arc tangent
+\definemathfunction{\arg}{arg}{\nolimits} % argument
+\definemathfunction{\argmax}{arg\,max}{\displaylimits} % argument maximum
+\definemathfunction{\argmin}{arg\,min}{\displaylimits} % argument maximum
+\definemathfunction{\Bd}{Bd}{\nolimits} % Bound
+\definemathfunction{\cl}{cl}{\nolimits} % closure
+\definemathfunction{\codim}{codim}{\nolimits} % co-dimension
+\definemathfunction{\coker}{coker}{\nolimits} % cokernel
+\definemathfunction{\conj}{conj}{\nolimits} % conjugate
+\definemathfunction{\cos}{cos}{\nolimits} % cosine
+\definemathfunction{\cosec}{cos}{\nolimits} % cosecant
+\definemathfunction{\cosh}{cosh}{\nolimits} % hyperbolic cosine
+\definemathfunction{\cot}{cot}{\nolimits} % cotangent
+\definemathfunction{\coth}{coth}{\nolimits} % hyperbolic cotangent
+\definemathfunction{\csc}{csc}{\nolimits} % cosecant
+\definemathfunction{\csch}{csch}{\nolimits} % hyperbolic cosecant
+\definemathfunction{\curl}{curl}{\nolimits} % curl
+\definemathfunction{\deg}{deg}{\nolimits} % degree
+\definemathfunction{\det}{det}{\displaylimits} % determinant
+\definemathfunction{\diag}{diag}{\nolimits} % diagonal
+\definemathfunction{\dim}{dim}{\nolimits} % dimension
+\definemathfunction{\dist}{dist}{\nolimits} % distance
+\definemathfunction{\erf}{erf}{\nolimits} % error function
+\definemathfunction{\erfc}{erfc}{\nolimits} % error function comp.
+\definemathfunction{\exp}{exp}{\nolimits} % exponential
+\definemathfunction{\gcd}{gcd}{\displaylimits} % greatest common div.
+\definemathfunction{\GL}{GL}{\nolimits} % General Linear
+\definemathfunction{\glb}{glb}{\nolimits} % greatest lower bound
+\definemathfunction{\gr}{gr}{\nolimits} % group
+\definemathfunction{\grad}{grad}{\nolimits} % gradient
+\definemathfunction{\hom}{hom}{\nolimits} % homology
+\definemathfunction{\id}{id}{\nolimits} % identity
+\definemathfunction{\inf}{inf}{\displaylimits} % infinum
+\definemathfunction{\injlim}{inj\,lim}{\displaylimits} % injected limit
+\definemathfunction{\ker}{ker}{\nolimits} % kernel
+\definemathfunction{\lcm}{lcm}{\displaylimits} % least common mult.
+\definemathfunction{\length}{length}{\nolimits} % length
+\definemathfunction{\lg}{lg}{\nolimits} % natural logarithm
+\definemathfunction{\lim}{lim}{\displaylimits} % limit
+\definemathfunction{\liminf}{lim\,inf}{\displaylimits} % limit infinum
+\definemathfunction{\limsup}{lim\,sup}{\displaylimits} % limit supremum
+\definemathfunction{\ln}{ln}{\nolimits} % natural logarithm
+\definemathfunction{\Log}{Log}{\nolimits} % principal logarithm
+\definemathfunction{\log}{log}{\nolimits} % logarithm
+\definemathfunction{\lub}{lub}{\nolimits} % least upper bound
+\definemathfunction{\max}{max}{\displaylimits} % maximum
+\definemathfunction{\min}{min}{\displaylimits} % minimum
+\definemathfunction{\mod}{mod}{\nolimits} % modulus
+\definemathfunction{\Pr}{Pr}{\displaylimits} % Probability
+\definemathfunction{\Prob}{Prob}{\displaylimits} % Probability
+\definemathfunction{\projlim}{proj\,lim}{\displaylimits}% projected limit
+\definemathfunction{\rank}{rank}{\nolimits} % rank
+\definemathfunction{\sec}{sec}{\nolimits} % secant
+\definemathfunction{\sech}{sech}{\nolimits} % hyperbolic secant
+\definemathfunction{\sgn}{sgn}{\nolimits} % sign
+\definemathfunction{\sign}{sign}{\nolimits} % sign
+\definemathfunction{\sin}{sin}{\nolimits} % sine
+\definemathfunction{\sinc}{sinc}{\nolimits} % cardinal sine
+\definemathfunction{\sinh}{sinh}{\nolimits} % hyperbolic sine
+\definemathfunction{\SL}{SL}{\nolimits} % Special Linear
+\definemathfunction{\sup}{sup}{\displaylimits} % supremum
+\definemathfunction{\Szg}{Sz(g)}{\nolimits} % Suzuki group
+\definemathfunction{\tan}{tan}{\nolimits} % tangent
+\definemathfunction{\tanh}{tanh}{\nolimits} % hyperbolic tangent
+\definemathfunction{\tr}{tr}{\nolimits} % trace
+\definemathfunction{\trace}{trace}{\nolimits} % trace
+\definemathfunction{\wstar}{w*}{\nolimits} % weak star
+
+
+% For the occasional one-timer:
+
+\def \mathfunction #1{\mathop{\rm #1}\nolimits}
+
+\let \mfun = \mathfunction
+
+% Display/Text/Script Styles
+% ------------------- ------
+
+
+\def \mathdisplaystyle #1{{\displaystyle #1}}% {subequation}
+\def \mathtextstyle #1{{\textstyle #1}}
+\def \mathscriptstyle #1{{\scriptstyle #1}}
+\def \mathscriptscriptstyle #1{{\scriptscriptstyle #1}}
+
+\def \mathpalette #1#2{% {\macro}{text}
+ \mathchoice{#1\displaystyle{#2}}%
+ {#1\textstyle{#2}}%
+ {#1\scriptstyle{#2}}%
+ {#1\scriptscriptstyle{#2}}}
+
+\def \mtext #1{%
+ {\mathchoice{\hbox{\zmtextstyle #1}}
+ {\hbox{\zmtextstyle #1}}
+ {\hbox{\the\scriptfont\zmtextfam #1}}
+ {\hbox{\the\scriptscriptfont\zmtextfam #1}}}}
+
+\everymath = {\let\text=\mtext}%
+
+% This is specifically designed to work in math or in text.
+
+\def \mvar #1{{\zmvarstyle #1\if \textmodep \/\fi}}% {text}
+
+% General Tools
+% ------- -----
+
+
+\def \aboverule #1{\above #1\relax}% {rule-height}
+
+\def \abs #1{\left|#1\right|}% {expression}
+
+\def \big #1{{\hbox{$\left#1\vbox to 8.5pt{}\right.\zmnosp$}}}
+\def \Big #1{{\hbox{$\left#1\vbox to 11.5pt{}\right.\zmnosp$}}}
+\def \bigg #1{{\hbox{$\left#1\vbox to 14.5pt{}\right.\zmnosp$}}}
+\def \Bigg #1{{\hbox{$\left#1\vbox to 17.5pt{}\right.\zmnosp$}}}
+\def \zmnosp {\nulldelimiterspace = 0pt}
+
+\def \bigl {\mathopen\big}
+\def \Bigl {\mathopen\Big}
+\def \bigm {\mathrel\big}
+\def \Bigm {\mathrel\Big}
+\def \bigr {\mathclose\big}
+\def \Bigr {\mathclose\Big}
+\def \biggl {\mathopen\bigg}
+\def \Biggl {\mathopen\Bigg}
+\def \biggm {\mathrel\bigg}
+\def \Biggm {\mathrel\Bigg}
+\def \biggr {\mathclose\bigg}
+\def \Biggr {\mathclose\Bigg}
+
+\def \binomial #1#2{{{#1} \atopwithdelims() {#2}}}
+
+\let \binom = \binomial
+
+\def \bmod {\mathbin{\rm mod}}
+
+\def \bordermatrix #1{%
+ {\setbox \zboxa = \hbox{\mex B}%
+ \tdimena = \wd\zboxa
+ \setbox \zboxa = \vbox{%
+ \def \cr {\crcr \noalign{\kern 0pt \global\let \cr = \completerow}}%
+ \ialign{$##$\hfil \kern 2pt \kern \tdimena&
+ \thinspace \hfil $##$\hfil&&
+ \quad \hfil $##$\hfil \crcr
+ \omit \strut \hfil \crcr
+ \noalign{\kern -\baselineskip}%
+ #1\crcr
+ \omit \strut \cr}}%
+ \setbox \zboxc = \vbox{%
+ \unvcopy \zboxa \global\setbox \zboxb = \lastbox}%
+ \setbox \zboxc = \hbox{%
+ \unhbox \zboxb \unskip \global\setbox \zboxb = \lastbox}%
+ \setbox \zboxc = \hbox{%
+ $\kern \wd\zboxb \kern -\tdimena \left(\kern -\wd\zboxb
+ \global\setbox \zboxb = \vbox{\box\zboxb \kern 8pt}%
+ \vcenter{\kern -\ht\zboxb \unvbox\zboxa \kern -\baselineskip}\,%
+ \right)$}%
+ \null\;\vbox{\kern \ht\zboxb \box\zboxc}}}
+
+\def \brace {\atopwithdelims\{\}}
+
+\def \bracematrix #1{% {row...}
+ \left\{ \matrix{#1} \right\}}
+
+\def \brack {\atopwithdelims[]}
+
+\def \bracketmatrix #1{% {row...}
+ \left[ \matrix{#1} \right]}
+
+\def \bracketmatrixfl #1{% {row...}
+ \left[ \matrixfl{#1} \right]}
+
+\def \bracketmatrixfr #1{% {row...}
+ \left[ \matrixfr{#1} \right]}
+
+\def \cases #1{% {row...}
+ \left\{ \,%
+ \vcenter{\matrixbaselines
+ \ialign{$##$\hfil&
+ \quad {\rm ##}\hfil \crcr
+ #1\crcr}}%
+ \right.}
+
+% This version of \cases has math in both columns.
+
+\def \mcases #1{% {row...}
+ \left\{ \,%
+ \vcenter{\matrixbaselines
+ \ialign{$##$\hfil&
+ \quad $##$\hfil \crcr
+ #1\crcr}}%
+ \right.}
+
+\def \cdots {\mathinner{\cdotp\cdotp\cdotp}}
+
+\def \ddots {%
+ \if \newdots
+ \vbox{\baselineskip = 4pt \lineskiplimit = 0pt
+ \hbox{.}
+ \hbox{\kern .4em .}
+ \hbox{\kern .8em .}}%
+ \else
+ \mathinner{\mkern 1mu \raise 7pt \vbox{\kern 7pt \hbox{.}}%
+ \mkern 2mu \raise 4pt \hbox{.}%
+ \mkern 2mu \raise 1pt \hbox{.}%
+ \mkern 1mu}%
+ \fi}
+
+\def \detmatrix #1{% {row...}
+ \left| \matrix{#1} \right|}
+
+\def \displayfrac #1#2{% {numerator}{denominator}
+ {\displaystyle \frac{#1}{#2}}}
+
+\def \displaylines #1{% {row...}
+ \openup \jot
+ \global\setflag \zdtop = \true
+ \everycr = {\noalign{\if \zdtop
+ \vskip -\lineskiplimit
+ \vskip \normallineskiplimit
+ \global\setflag \zdtop = \false
+ \else
+ \penalty \interdisplaylinepenalty
+ \fi}}%
+ \halign{\hbox to \displaywidth{$\tabskip = 0pt \everycr = {}%
+ \hfil \displaystyle ##\hfil$}\cr
+ #1\crcr}}
+
+\def \eqalign #1{% {row...}
+ \vcenter{%
+ \ialign{&\mathstrut \hfil $\displaystyle ##{}$&
+ $\displaystyle {}##$\hfil\cr
+ #1\crcr}}}
+
+\def \equalfill {%
+ $\mathord =\mkern -6mu
+ \cleaders \hbox{$\mkern -2mu \mathord =\mkern -2mu$}\hfill
+ \mkern -6mu \mathord =$}
+
+% All other fraction macros should use \frac.
+
+\def \frac #1#2{% {numerator}{denominator}
+ {{\mskip\fracbarhang #1\mskip\fracbarhang} \over
+ {\mskip\fracbarhang #2\mskip\fracbarhang}}}
+
+\def \fromunder #1{% {math}
+ \mathrel{\mathop{\longleftarrow}\limits^{#1}}}
+
+\def \hphantom {%
+ \setflag \zhphant = \true
+ \setflag \zvphant = \false
+ \zphanta}
+
+\def \joinrel {\mathrel{\mkern -3mu}}
+
+\def \largefrac #1#2{% {numerator}{denominator}
+ {\mathchoice{\mathdisplaystyle{\frac{#1}{#2}}}
+ {\mathdisplaystyle{\frac{#1}{#2}}}
+ {\mathtextstyle{\frac{#1}{#2}}}
+ {\mathscriptstyle{\frac{#1}{#2}}}}}
+
+\def \ldots {\mathinner{\ldotp\ldotp\ldotp}}
+
+\def \leftarrowfill {\zleftarrowfill{\textstyle}}
+\def \leftrightarrowfill {\zleftrightarrowfill{\textstyle}}
+\def \rightarrowfill {\zrightarrowfill{\textstyle}}
+\def \Rightarrowfill {\zRightarrowfill{\textstyle}}
+
+\def \zleftarrowfill #1{% {style}
+ \setbox\zboxa = \hbox{$#1-$}%
+ \ht\zboxa = 0pt
+ $#1\mathord\leftarrow \mkern -6mu
+ \cleaders \hbox{$#1\mkern -2mu \copy\zboxa \mkern -2mu$}\hfill
+ \mkern -6mu \box\zboxa$}
+
+\def \zleftrightarrowfill #1{% {style}
+ \setbox\zboxa = \hbox{$#1-$}%
+ \ht\zboxa = 0pt
+ $#1\mathord\leftarrow \mkern -6mu
+ \cleaders \hbox{$#1\mkern -2mu \box\zboxa \mkern -2mu$}\hfill
+ \mkern -6mu \mathord\rightarrow$}
+
+\def \zRightarrowfill #1{% {style}
+ \setbox\zboxa = \hbox{$#1=$}%
+ \ht\zboxa = 0pt
+ $#1\copy\zboxa \mkern -6mu
+ \cleaders \hbox{$#1\mkern -2mu \box\zboxa \mkern -2mu$}\hfill
+ \mkern -6mu \mathord\Rightarrow$}
+
+\def \zrightarrowfill #1{% {style}
+ \setbox\zboxa = \hbox{$#1-$}%
+ \ht\zboxa = 0pt
+ $#1\copy\zboxa \mkern -6mu
+ \cleaders \hbox{$#1\mkern -2mu \box\zboxa \mkern -2mu$}\hfill
+ \mkern -6mu \mathord\rightarrow$}
+
+\let \leqalignno = \eqalignno
+
+\def \mathstrut {\vphantom(}
+
+\def \matrix #1{% {row...}
+ \null\nonscript\,%
+ \vcenter{\matrixbaselines
+ \ialign{\hfil $##$\hfil&& \quad \hfil $##$\hfil \crcr
+ \mathstrut\crcr
+ \noalign{\kern -\baselineskip}%
+ #1\crcr
+ \mathstrut\crcr
+ \noalign{\kern -\baselineskip}}}%
+ \nonscript\,}
+
+\let \adjustmatrix = \noalign
+
+\def \matrixfl #1{% {row...}
+ \null\nonscript\,%
+ \vcenter{\matrixbaselines
+ \ialign{$##$\hfil && \quad $##$\hfil \crcr
+ \mathstrut\crcr
+ \noalign{\kern -\baselineskip}%
+ #1\crcr
+ \mathstrut\crcr
+ \noalign{\kern -\baselineskip}}}%
+ \nonscript\,}
+
+\def \matrixfr #1{% {row...}
+ \null\nonscript\,%
+ \vcenter{\matrixbaselines
+ \ialign{\hfil $##$&& \quad \hfil $##$\crcr
+ \mathstrut\crcr
+ \noalign{\kern -\baselineskip}%
+ #1\crcr
+ \mathstrut\crcr
+ \noalign{\kern -\baselineskip}}}%
+ \nonscript\,}
+
+\def \matrixbaselines {%
+ \baselineskip = \the\matrixspread\normalbaselineskip
+ \lineskiplimit = \normallineskiplimit
+ \lineskip = \normallineskip}
+
+\def \ontopof #1#2{{{#1} \atop {#2}}}% {numerator}{denominator}
+
+\def \openup {\afterassignment\zopenup \tdimena=}
+
+\def \zopenup {%
+ \advance \baselineskip by \tdimena
+ \advance \lineskiplimit by \tdimena
+ \advance \lineskip by \tdimena}
+
+\def \overbrace #1{%
+ \mathop{%
+ \vbox{\ialign{##\cr
+ \noalign{\kern 3pt}%
+ \downbracefill\cr
+ \noalign{\kern 3pt \nointerlineskip}%
+ $\hfil \displaystyle{#1}\hfil$\cr}}}\limits}
+
+\def \overleftarrow {\mathpalette\zoverleftarrow}
+\def \overleftrightarrow {\mathpalette\zoverleftrightarrow}
+\def \overRightarrow {\mathpalette\zoverRightarrow}
+\def \overrightarrow {\mathpalette\zoverrightarrow}
+
+\def \zoverleftarrow #1#2{% {style}{math}
+ \vbox{\ialign{##\cr
+ \zleftarrowfill{\scriptscriptstyle}\cr
+ \noalign{\nointerlineskip}%
+ $\hfil #1#2\hfil$\crcr}}}
+
+\def \zoverleftrightarrow #1#2{% {style}{math}
+ \vbox{\ialign{##\cr
+ \zleftrightarrowfill{\scriptscriptstyle}\cr
+ \noalign{\nointerlineskip}%
+ $\hfil #1#2\hfil$\crcr}}}
+
+\def \zoverRightarrow #1#2{% {style}{math}
+ \vbox{\ialign{##\cr
+ \zRightarrowfill{\scriptscriptstyle}\cr
+ \noalign{\nointerlineskip}%
+ $\hfil #1#2\hfil$\crcr}}}
+
+\def \zoverrightarrow #1#2{% {style}{math}
+ \vbox{\ialign{##\cr
+ \zrightarrowfill{\scriptscriptstyle}\cr
+ \noalign{\nointerlineskip}%
+ $\hfil #1#2\hfil$\crcr}}}
+
+\def \overset #1#2{
+ \mathbin{\mathop{#2}\limits^{#1}}}
+
+\def \parenmatrix #1{% {row...}
+ \left( \matrix{#1} \right)}
+
+\let \pmatrix = \parenmatrix
+
+\def \parenmatrixfl #1{% {row...}
+ \left( \matrixfl{#1} \right)}
+
+\def \parenmatrixfr #1{% {row...}
+ \left( \matrixfr{#1} \right)}
+
+\def \phantom {%
+ \setflag \zhphant = \true
+ \setflag \zvphant = \true
+ \zphanta}
+
+\def \zphanta {%
+ \if \mathmodep
+ \def \znext {\mathpalette\zphantb}%
+ \else
+ \let \znext = \zphantc
+ \fi
+ \znext}
+\def \zphantb #1#2{%
+ \setbox \zboxa = \hbox{$#1{#2}$}%
+ \zphantd}
+\def \zphantc #1{%
+ \setbox \zboxa = \hbox{#1}%
+ \zphantd}
+\def \zphantd {%
+ \setbox \zboxb = \hbox{}%
+ \if \zhphant \wd\zboxb = \wd\zboxa \fi
+ \if \zvphant \ht\zboxb = \ht\zboxa \dp\zboxb = \dp\zboxa \fi
+ \box \zboxb}
+
+\def \plainTeXmathdisplay {%
+ \global\everydisplay = {}}
+
+\def \pmod #1{\allowbreak \,({\rm mod}\,#1)}
+
+\def \Relbar {\mathrel =}
+\def \relbar {\mathrel{\smash -}}
+
+\definebox{\zrootbox}
+
+\def \nthroot #1{% {n}
+ \setbox\zrootbox = \hbox{$\scriptscriptstyle{#1}$}%
+ \mathpalette\zroot}
+
+\def \zroot #1#2{% {\style}{radicand}
+ \setbox\zboxa = \hbox{$#1\sqrt{#2}$}%
+ \tdimena = \ht\zboxa
+ \advance \tdimena by -\dp\zboxa
+ \mkern 5mu \raise .6\tdimena \copy\zrootbox \mkern -10mu \box\zboxa}
+
+\def \skew #1#2#3{% {amount}{accent}{char}
+ {\zmuskipa = #1mu
+ \divide \zmuskipa by 2
+ \mkern \zmuskipa
+ #2{\mkern -\zmuskipa{#3}\mkern \zmuskipa}%
+ \mkern -\zmuskipa}{}}
+
+\def \smallfrac #1#2{% {numerator}{denominator}
+ {\mathchoice{\mathtextstyle{\frac{#1}{#2}}}
+ {\mathscriptstyle{\frac{#1}{#2}}}
+ {\mathscriptscriptstyle{\frac{#1}{#2}}}
+ {\mathscriptscriptstyle{\frac{#1}{#2}}}}}
+
+\def \smash {%
+ \relax
+ \if \mathmodep
+ \def \znext {\mathpalette\zsmasha}%
+ \else
+ \let \znext = \zsmashb
+ \fi
+ \znext}
+
+\def \zsmasha #1#2{%
+ \setbox \zboxa = \hbox{$#1{#2}$}%
+ \zsmashc}
+\def \zsmashb #1{%
+ \setbox \zboxa = \hbox{#1}%
+ \zsmashc}
+\def \zsmashc {%
+ \ht\zboxa = 0pt
+ \dp\zboxa = 0pt
+ \box \zboxa}
+
+\def \sqrt {\radical"270370 }
+
+\let \sub = _
+\let \super = ^
+
+\def \Tounder #1{% {math}
+ \mathrel{\mathop{\Longrightarrow}\limits^{#1}}}
+
+\def \tounder #1{% {math}
+ \mathrel{\mathop{\longrightarrow}\limits^{#1}}}
+
+\def \underbrace #1{% {text}
+ \mathop{%
+ \vtop{\ialign{##\cr
+ $\hfil \displaystyle{#1}\hfil$\cr
+ \noalign{\kern 3pt \nointerlineskip}%
+ \upbracefill\cr
+ \noalign{\kern 3pt}}}}\limits}
+
+\def \underset #1#2{
+ \mathbin{\mathop{#2}\limits_{#1}}}
+
+\def \unit #1{% {text}
+ \if \mathmodep
+ {\nonscript\,\mtext{#1}}%
+ \else
+ \,#1%
+ \fi}
+
+\def \vdots {%
+ \if \newdots
+ \vbox{\baselineskip = 4pt \lineskiplimit = 0pt
+ \hbox{.}
+ \hbox{.}
+ \hbox{.}}%
+ \else
+ \vbox{\baselineskip = 4pt \lineskiplimit = 0pt
+ \kern 6pt
+ \hbox{.}
+ \hbox{.}
+ \hbox{.}}%
+ \fi}
+
+\def \vphantom {%
+ \setflag \zhphant = \false
+ \setflag \zvphant = \true
+ \zphanta}
+
+% Block Matrices
+% ----- --------
+
+
+\def \blockmatrix #1{% {rows}
+ \zblockmatrix{\false}{#1}}
+
+\def \blockmatrixvr #1{% {rows}
+ \zblockmatrix{\true}{#1}}
+
+\def \zblockmatrix #1#2{% {verticals?}{rows}
+ \left[
+ \vcenter{%
+ \defineatsigncommand @R{\colrule}%
+ \defineatsigncommand @N{\nocolrule}%
+ \offinterlineskip
+ \tdimena = \ht\strutbox \advance \tdimena by .2ex
+ \tdimenb = \dp\strutbox \advance \tdimenb by .4ex
+ \setbox \strutbox \hbox{\vrule width 0pt height \tdimena depth \tdimenb}%
+ \ialign{\hfil \strut \thirdspace $##$\thirdspace \hfil&&
+ \hspace{.35em}%
+ \vrule \if #1\colrule \else \nocolrule \fi
+ ##\relax
+ \hspace{.35em}&
+ \hfil \strut \thirdspace $##$\thirdspace \hfil\crcr
+ #2\crcr}}%
+ \right]}
+
+\def \rowrule {%
+ \noalign{%
+ \vskip .5ex
+ \hrule height .1ex\relax
+ \vskip .7ex}}
+
+\def \colrule {%
+ width .1ex }
+
+% Math Displays
+% ---- --------
+
+
+\defineblock{\mathdisplay}{\endmathdisplay}{\true}{}
+
+%~block mathdisplay
+% \abovepenalty = integer % Penalty above display.
+% \aboveskip = glue % Visual space above display.
+% \belowpenalty = integer % Penalty below display.
+% \belowskip = glue % Visual space below display.
+% \bodyfont = {...} % Font for display.
+% \def \comptextformat {...} % Composite number text formatter.
+% \diagramdiagarrowstyle = {...} % Style for diagonal arrows in diagrams.
+% \diagramgutter = dimen % Gutter between diagram columns.
+% \diagraminterrowskip = glue % Interrowskip for diagrams.
+% \diagramminarrow = dimen % Minimum length of arrow in diagram.
+% \hfuzz = dimen % Overhang allowed at end of line.
+% \interrowskip = glue % Extra visual space between equations.
+% \leftindent = dimen % Left indentation for \alignleft.
+% \matrixspread = {decimal} % Spread factor for matrices.
+% \def \numberformat {...} % Equation number formatter.
+% \position = {...} % Positioning options.
+% \rightindent = dimen % Right indentation for \alignright.
+% \textcolor = {...} % Color of text.
+%~end
+
+\definetoks{\diagramdiagarrowstyle}
+\definedimen{\diagramgutter}{0pt}
+\defineskip{\diagraminterrowskip}{0pt}
+\definedimen{\diagramminarrow}{0pt}
+
+% Positioning options are:
+% \alignleft Left aligned, with \leftindent.
+% \alignright Right aligned, with \rightindent.
+% \center Centered.
+% \numberleft Equation number on left.
+% \numberright Equation number on right.
+
+% These parameters are calculated:
+
+\definetoks{\mathdisplayeqno} % Text following \eqno marker.
+\definecount{\mathdisplayprevgraf}{-1} % Previous display's ending \prevgraf.
+\definecount{\mathdisplayprevpenalty}{0}% Previous display's \belowpenalty.
+\defineskip{\mathdisplayprevskip}{0pt} % Previous display's \belowskip.
+
+\declareeverypar{\global\mathdisplayprevgraf=-1}
+\zdeclareeveryvcontext{\zsavevcontext{\mathdisplayprevgraf=-1}}
+
+%~ This marker specifies that the following text is the equation number
+%~ for the math display.
+
+\definemarker{\eqno}
+
+
+\everydisplay = {\mathdisplay}
+
+\def \mathdisplay #1$${% equation $$
+ \advance \displayindent by \leftskip
+ \advance \displaywidth by -\leftskip
+ \advance \displaywidth by -\rightskip
+ % \beginblockscope is unnecessary.
+ \global\increment \mathdisplaydepth
+ \abovepenalty = 5000 %~default hard
+ \belowpenalty = \breakallowed %~default hard
+ \hfuzz = 1pt %~default hard
+ \leftindent = 0pt %~default soft
+ \matrixspread = {1.0} %~default soft
+ \rightindent = 0pt %~default soft
+ \textcolor = {}% %~default soft
+ \processdesign{\mathdisplay}{}%
+ % \mathdisplaynumber is incremented by \eqno, if appropriate.
+ \if \eqlp{\prevgraf}{\mathdisplayprevgraf}%
+ \aboveskip = -\belowskip
+ \advance \aboveskip by \interrowskip
+ \fi
+ \let \text = \mtext
+ \zmdparams
+ \settaginfo{}{}% % No tag info so far.
+ \if \notp{\emptytoksp{\textcolor}}\color{\the\textcolor}\fi
+ \mathdisplayformat{#1}%
+ \endmathdisplay}
+
+\def \endmathdisplay {%
+ \global\mathdisplayprevgraf = \prevgraf
+ \global\advance \mathdisplayprevgraf by 3
+ \global\mathdisplayprevpenalty = \belowpenalty
+ \global\mathdisplayprevskip = \belowskip
+ \global\decrement \mathdisplaydepth
+ \if \notp{\emptytoksp{\textcolor}}\endcolor \fi%
+ % \endblockscope is unnecessary.
+ $$}
+
+\definecount{\zmdhpos}{0}
+
+\def \zmdparams {%
+ \abovedisplayskip = \aboveskip
+ \abovedisplayshortskip = \aboveskip
+ \belowdisplayskip = \belowskip
+ \belowdisplayshortskip = \belowskip
+ \predisplaypenalty = \abovepenalty
+ \postdisplaypenalty = \belowpenalty
+ \zmdhpos = 0
+ \let \center = \relax
+ \def \alignleft {\zmdhpos = 1}%
+ \def \alignright {\zmdhpos = 2}%
+ \setflag \zmdnumleft = \false
+ \def \numberleft {\setflag \zmdnumleft = \true}%
+ \let \numberright = \relax
+ \the\position}
+
+\def \mathdisplayformat #1{% {display}
+ \the\bodyfont
+ \zmdparse#1\eqno\eqno\zmark
+ {\lineskiplimit = \maxdimen % Force \interrowskip between
+ \lineskip = \interrowskip % each row of multi-line display.
+ \ifcase \zmdhpos
+ \if \zmdnumleft % Centered display.
+ \hbox to \displaywidth {%
+ \rlap{\hspace{-1\leftskip}\zmdeqno}%
+ \hfil $\displaystyle \zmdeq$\hfil}%
+ \else
+ \hbox to \displaywidth {%
+ \hfil $\displaystyle \zmdeq$\hfil
+ \llap{\zmdeqno\hspace{-1\rightskip}}}%
+ \fi
+ \or
+ \if \zmdnumleft % Left-aligned display.
+ \hbox to \displaywidth {%
+ \hbox to \leftindent{\hspace{-1\leftskip}\zmdeqno\hss}%
+ $\displaystyle \zmdeq$\hfil}%
+ \else
+ \hbox to \displaywidth{%
+ \kern \leftindent $\displaystyle \zmdeq$\hfil
+ \llap{\zmdeqno\hspace{-1\rightskip}}}%
+ \fi
+ \or
+ \if \zmdnumleft % Right-aligned display.
+ \hbox to \displaywidth {%
+ \rlap{\hspace{-1\leftskip}\zmdeqno}%
+ \hfil $\displaystyle \zmdeq$\kern \rightindent}%
+ \else
+ \hbox to \displaywidth{%
+ \hfil $\displaystyle \zmdeq$%
+ \hbox to \rightindent{\hss\zmdeqno\hspace{-1\rightskip}}}%
+ \fi
+ \fi}}
+
+\def \zmdparse #1\eqno#2\eqno#3\zmark{% equation\eqno number\eqno ???\zmark
+ \def \zmdeq {#1}%
+ \if \andp{\emptyargp{#2}}{\emptyargp{#3}}%
+ \let \zmdeqno = \relax
+ \else
+ \def \zmdeqno {\zmdformeqno#2\tag\tag\zmark}%
+ \fi}
+
+% This macro is invoked to format equation numbers in both positions:
+% at the end of the display and at the end of \eqaligned rows.
+
+\def \zmdformeqno #1\tag#2\tag#3\zmark{% number\tag{xxx}\tag ???\zmark
+ \if \emptyargp{#1}%
+ \global\increment \mathdisplaynumber
+ \mathdisplayeqno = \expandafter{\number\mathdisplaynumber}%
+ \setcomptext{\mathdisplaycomptext}%
+ \else
+ \zmdexpliciteqno #1 \zmark
+ \fi
+ \settaginfo{\the\mathdisplaycomptext}{???}%
+ \hbox{\numberformat}%
+ \if \notp{\emptyargp{#3}}\zmdtageqno#2\zmark \fi}
+
+\def \zmdexpliciteqno #1#2 #3\zmark{%
+ \if \codeeqlp{#1}{!}%
+ \mathdisplayeqno = {#2}%
+ \mathdisplaycomptext = {#2}%
+ \else\if \codeeqlp{#1}{+}%
+ \global\increment \mathdisplaynumber
+ \mathdisplayeqno = \expandafter{\number\mathdisplaynumber #2}%
+ \setcomptext{\mathdisplaycomptext}%
+ \else\if \codeeqlp{#1}{,}%
+ \mathdisplayeqno = \expandafter{\number\mathdisplaynumber #2}%
+ \setcomptext{\mathdisplaycomptext}%
+ \else\if \codeeqlp{#1}{:}%
+ \global\increment \mathdisplaynumber
+ \mathdisplayeqno = {#2}%
+ \setcomptext{\mathdisplaycomptext}%
+ \else\if \codeeqlp{#1}{=}%
+ \zmdseteqno #2\zmark
+ \setcomptext{\mathdisplaycomptext}%
+ \else\if \codeeqlp{#1}{>}%
+ \zmdrefeqno #2;;\zmark
+%%% \mathdisplayeqno = {\ref{#2}}%
+%%% \mathdisplaycomptext = {\ref{#2}}%
+ \else
+ \mathdisplayeqno = {#1#2}%
+ \setcomptext{\mathdisplaycomptext}%
+ \fi\fi\fi\fi\fi\fi}
+
+\def \zmdseteqno #1;#2\zmark{%
+ \global\mathdisplaynumber = #1\relax
+ \mathdisplayeqno = \expandafter{\number\mathdisplaynumber #2}}
+
+\def \zmdrefeqno #1;#2;#3\zmark{%
+ \if \emptyargp{#2}%
+ \mathdisplayeqno = {\ref{#1}}%
+ \mathdisplaycomptext = {\ref{#1}}%
+ \else
+ \mathdisplayeqno = {\ref{#1}\,#2}%
+ \mathdisplaycomptext = {\ref{#1}\,#2}%
+ \fi}
+
+\def \zmdtageqno #1#2\zmark{%
+ \def \znext { }%
+ \if \znext#2\tag{#1}\else \tag{#1#2}\fi}
+
+\def \setmathdisplaynumber #1{%
+ \global\mathdisplaynumber = #1\relax
+ \global\decrement \mathdisplaynumber}
+
+%~ This modifier for |$$| is used when the display is the first thing
+%~ after a head, the first thing in a list item, the first thing in
+%~ a float, etc. It eliminates the vertical space above the display.
+
+\def \immediatemathdisplay {% %^modifier
+ \with{\abovepenalty = \breaknever
+ \aboveskip = 0pt}}
+
+% Aligned Equations
+% ------- ---------
+
+
+% This tool can only be used inside a math display.
+
+
+\defineskip{\zeqaltabskip}{0pt}
+\definedimen{\zeqnoshift}{0pt}
+
+\def \eqaligned #1{% {rows...}
+ \vcenter{%
+ \zeqalinit
+ \halign to \tdimena {%
+ \hfil $\displaystyle ##{}$\tabskip = 0pt&
+ $\displaystyle {}##$\hfil \tabskip = \zeqaltabskip&
+ \relax \zeqaleqno ##\zmark% \relax prevents expansion of \zeqaleqno.
+ \tabskip = \if \zmdnumleft \displaywidth \else 0pt \fi \cr
+ #1\crcr}}}
+
+\def \eqalignedpairs #1{% {rows...}
+ \vcenter{%
+ \zeqalinit
+ \halign to \tdimena {%
+ \hfil $\displaystyle ##{}$\tabskip = 0pt&
+ $\displaystyle {}##$\hfil&
+ \hfil $\displaystyle ##{}$&
+ $\displaystyle {}##$\hfil \tabskip = \zeqaltabskip&
+ \relax \zeqaleqno ##\zmark% \relax prevents expansion of \zeqaleqno.
+ \tabskip = \if \zmdnumleft \displaywidth \else 0pt \fi \cr
+ #1\crcr}}}
+
+\def \eqalignedtriples #1{% {rows...}
+ \vcenter{%
+ \zeqalinit
+ \halign to \tdimena {%
+ \hfil $\displaystyle ##{}$\tabskip = 0pt&
+ $\displaystyle {}##$\hfil&
+ \hfil $\displaystyle ##{}$&
+ $\displaystyle {}##$\hfil&
+ \hfil $\displaystyle ##{}$&
+ $\displaystyle {}##$\hfil \tabskip = \zeqaltabskip&
+ \relax \zeqaleqno ##\zmark% \relax prevents expansion of \zeqaleqno.
+ \tabskip = \if \zmdnumleft \displaywidth \else 0pt \fi \cr
+ #1\crcr}}}
+
+\def \eqalignedquadruples #1{% {rows...}
+ \vcenter{%
+ \zeqalinit
+ \halign to \tdimena {%
+ \hfil $\displaystyle ##{}$\tabskip = 0pt&
+ $\displaystyle {}##$\hfil&
+ \hfil $\displaystyle ##{}$&
+ $\displaystyle {}##$\hfil&
+ \hfil $\displaystyle ##{}$&
+ $\displaystyle {}##$\hfil&
+ \hfil $\displaystyle ##{}$&
+ $\displaystyle {}##$\hfil \tabskip = \zeqaltabskip&
+ \relax \zeqaleqno ##\zmark% \relax prevents expansion of \zeqaleqno.
+ \tabskip = \if \zmdnumleft \displaywidth \else 0pt \fi \cr
+ #1\crcr}}}
+
+\def \zeqalinit {%
+ \def \eqno {&\relax}% \relax prevents expansion of stuff after \eqno.
+ \tdimena = \displaywidth
+ \advance \tdimena by -\leftindent
+ \advance \tdimena by -\rightindent
+ \zeqaltabskip = \if \eqlp{\zmdhpos}{2}0pt \else \centerindent \fi
+ \if \zmdnumleft
+ \zeqnoshift = \leftskip \advance \zeqnoshift by \leftindent
+ \else
+ \zeqnoshift = \rightskip \advance \zeqnoshift by \rightindent
+ \fi
+ \tabskip = \if \eqlp{\zmdhpos}{1}0pt \else \centerindent \fi}
+
+\def \zeqaleqno \relax#1\zmark{% \relax [\eqno [text]][\tag]\zmark
+ \if \zmdnumleft
+ \kern -\displaywidth
+ \rlap{\zmdformeqno#1\tag\tag\zmark}%
+ \else
+ \llap{\zmdformeqno#1\tag\tag\zmark \hspace{-\zeqnoshift}}%
+ \fi}
+
+\let \adjustmathdisplay = \noalign
+
+% Diagrams
+% --------
+
+
+% This tool can only be used inside a math display.
+
+
+\def \diagram #1{% {rows...}
+ \zdiagcmds
+ \null\,%
+ \vcenter{%
+ \lineskip = \diagraminterrowskip
+ \lineskiplimit = \lineskip
+ \tabskip = -\diagramgutter
+ \halign{%
+ &\kern \diagramgutter \hfil $\displaystyle ##$\hfil \tabskip = 0pt \cr
+ #1\crcr}}%
+ \,}
+
+\def \zdiagcmds {%
+ \defineatsigncommand @>##1>##2>{\zdiagra{##1}{##2}}%
+ \defineatsigncommand @<##1<##2<{\zdiagla{##1}{##2}}%
+ \defineatsigncommand @X##1X##2X{\zdiaglra{##1}{##2}}%
+ \defineatsigncommand @=##1=##2={\zdiaghb{##1}{##2}}%
+ \defineatsigncommand @V##1V##2V{%
+ \zdiagva{c}{}{\hbox}{\big\downarrow}{##1}{##2}}%
+ \defineatsigncommand @A##1A##2A{%
+ \zdiagva{c}{}{\hbox}{\big\uparrow}{##1}{##2}}%
+ \defineatsigncommand @|##1|##2|{%
+ \zdiagva{c}{}{\hbox}{\big|}{##1}{##2}}%
+ \defineatsigncommand @H##1|##2|{%
+ \zdiagva{c}{}{\hbox}{\big\Vert}{##1}{##2}}%
+ \defineatsigncommand @1##11##21##31{%
+ \zdiagva{##1}{l}{r}{\the\diagramdiagarrowstyle \mathchar "7025}{##2}{##3}}%
+ \defineatsigncommand @3##13##23##33{%
+ \zdiagva{##1}{l}{r}{\the\diagramdiagarrowstyle \mathchar "7026}{##2}{##3}}%
+ \defineatsigncommand @5##15##25##35{%
+ \zdiagva{##1}{r}{l}{\the\diagramdiagarrowstyle \mathchar "702E}{##2}{##3}}%
+ \defineatsigncommand @7##17##27##37{%
+ \zdiagva{##1}{r}{l}{\the\diagramdiagarrowstyle \mathchar "702D}{##2}{##3}}%
+ \defineatsigncommand @"##1"##2"{\zdiagwd{##1}{##2}}}
+
+\def \zdiagra #1#2{%
+ {\setbox \zboxa = \hbox{$\scriptstyle \;{#1}\;\;\;$}%
+ \setbox \zboxb = \hbox{$\scriptstyle \;{#2}\;\;\;$}%
+ \setbox \zboxc = \hbox{$#2$}%
+ \tdimena = \diagramminarrow
+ \if \dimgtrp{\wd\zboxa}{\tdimena}\tdimena = \wd\zboxa \fi
+ \if \dimgtrp{\wd\zboxb}{\tdimena}\tdimena = \wd\zboxb \fi
+ \mathrel{\mathop{\hbox to \tdimena {\rightarrowfill}}%
+ \limits^{#1}\if \dimposp{\wd\zboxc}_{#2}\fi}}}
+
+\def \zdiagla #1#2{%
+ {\setbox \zboxa = \hbox{$\scriptstyle \;\;\;{#1}\;$}%
+ \setbox \zboxb = \hbox{$\scriptstyle \;\;\;{#2}\;$}%
+ \setbox \zboxc = \hbox{$#2$}%
+ \tdimena = \diagramminarrow
+ \if \dimgtrp{\wd\zboxa}{\tdimena}\tdimena = \wd\zboxa \fi
+ \if \dimgtrp{\wd\zboxb}{\tdimena}\tdimena = \wd\zboxb \fi
+ \mathrel{\mathop{\hbox to \tdimena {\leftarrowfill}}%
+ \limits^{#1}\if \dimposp{\wd\zboxc}_{#2}\fi}}}
+
+\def \zdiaglra #1#2{%
+ {\setbox \zboxa = \hbox{$\scriptstyle \;\;\;{#1}\;\;\;$}%
+ \setbox \zboxb = \hbox{$\scriptstyle \;\;\;{#2}\;\;\;$}%
+ \setbox \zboxc = \hbox{$#2$}%
+ \tdimena = \diagramminarrow
+ \if \dimgtrp{\wd\zboxa}{\tdimena}\tdimena = \wd\zboxa \fi
+ \if \dimgtrp{\wd\zboxb}{\tdimena}\tdimena = \wd\zboxb \fi
+ \mathrel{\mathop{\hbox to \tdimena {\leftrightarrowfill}}%
+ \limits^{#1}\if \dimposp{\wd\zboxc}_{#2}\fi}}}
+
+\def \zdiaghb #1#2{%
+ {\setbox \zboxa = \hbox{$\scriptstyle \;{#1}\;$}%
+ \setbox \zboxb = \hbox{$\scriptstyle \;{#2}\;$}%
+ \setbox \zboxc = \hbox{$#2$}%
+ \tdimena = \diagramminarrow
+ \if \dimgtrp{\wd\zboxa}{\tdimena}\tdimena = \wd\zboxa \fi
+ \if \dimgtrp{\wd\zboxb}{\tdimena}\tdimena = \wd\zboxb \fi
+ \mathrel{\mathop{\hbox to \tdimena {\equalfill}}%
+ \limits^{#1}\if \dimposp{\wd\zboxc}_{#2}\fi}}}
+
+\def \zdiagva #1#2#3#4#5#6{% {centering}{h-overlap}{t-overlap}
+ % {arrow}{left-label}{right-label}
+ \if \codeeqlp{#1}{h}%
+ \if \codeeqlp{#2}{l}%
+ \llap{$\scriptstyle{#5}\mkern 2mu{#4}$}%
+ \rlap{$\mkern 2mu \scriptstyle #6$}%
+ \else
+ \llap{$\scriptstyle{#5}\mkern 2mu$}%
+ \rlap{${#4}\mkern 2mu \scriptstyle{#6}$}%
+ \fi
+ \else\if \codeeqlp{#1}{t}%
+ \if \codeeqlp{#3}{l}%
+ \llap{$\scriptstyle{#5}\mkern 2mu{#4}$}
+ \rlap{$\mkern 2mu \scriptstyle #6$}%
+ \else
+ \llap{$\scriptstyle{#5}\mkern 2mu$}
+ \rlap{${#4}\mkern 2mu \scriptstyle #6$}%
+ \fi
+ \else
+ \llap{$\scriptstyle{#5}\mkern 2mu$}{#4}%
+ \rlap{$\mkern 2mu \scriptstyle #6$}%
+ \fi\fi}
+
+\def \zdiagwd #1#2{%
+ \setbox \zboxa = \hbox{$\scriptstyle #2$}%
+ \hbox to \wd\zboxa {\hfil $\scriptstyle #1$\hfil}}
+
+% Enunciation Definition
+% ----------- ----------
+
+
+\setlist \zenuntypelist = {}
+
+
+\def \defineenunciationtype #1#2{% {type}{association}
+ \if \emptyargp{#2}%
+ \if \withname\undefinedp{\enunciation#1number}%
+ \withname\definecount{\enunciation#1number}{0}%
+ \withname\declaresnapitem{\enunciation#1number}%
+ \fi
+ \else
+ \defineenunciationtype{#2}{}%
+ \edef \znext {%
+ \global\withname\let{\enunciation#1number}=\name{\enunciation#2number}}%
+ \znext
+ \fi
+ \append{#1}{\zenuntypelist}}
+
+%~ Use this command to define a new type of enunciation.
+
+\def \defineenunciation #1#2#3{% {type}{association}{design}
+ \defineenunciationtype{#1}{#2}%
+ \withname\def {\enunciation#1design}{#3}}
+
+
+% This is deprecated in favor of \defineenunciation.
+
+\def \defineenunciationtypedesign #1#2#3{% {type}{assocation}{design}
+ \defineenunciationtype{#1}{#2}%
+ \withname\def {\enunciation#1design}{#3}}
+
+\def \resetenunciationnumbers {%
+ \maplist{\global\name{\enunciation##1number}=0\relax}{\zenuntypelist}}
+
+% Enunciation Block
+% ----------- -----
+
+
+\defineblock{\enunciation}{\endenunciation}{\false}{}
+
+%~block enunciation Type
+% \abovepenalty = integer % Penalty above block
+% \aboveskip = glue % Space b/b above block.
+% \setflag \allowclubline = flag % True if club allowed below.
+% \setflag \allownesting = flag % True if blocks can be nested.
+% \attribution = {...} % Attribution text (no longer used).
+% \setflag \attributionarg = flag % True if \enunciation takes attribution argument.
+% \autoqed = {,,,} % Automatic QED at end.
+% \belowpenalty = integer % Penalty below block.
+% \belowskip = glue % Space b/b below block.
+% \bodyfont = {...} % Font for text.
+% \def \comptextformat {...} % Composite number text formatter.
+% \continue = integer % Continued or continuation.
+% \difficulty = integer % Level of difficulty.
+% \def \endformat {...} % End of enunciation formatter.
+% \def \labelformat ##1{...} % Enunciation label formatter.
+% \leftindent = glue % Left indentation.
+% \parindent = dimen % Paragraph indent.
+% \parrag = dimen % Paragraph raggedness.
+% \parskip = glue % Paragraph skip.
+% \rightindent = glue % Right indentation.
+% \width = dimen % Width of text.
+%~end
+
+\definetoks{\attribution}
+\definecount{\attributiontype}{0} % 0: none; 1: attribution; 2: new title
+\definetoks{\autoqed}
+
+\setflag \zautoqeddone = \false
+
+
+\def \enunciation #1{% {type}{optional-attribution}
+ \beginblockscope{enunciation}%
+ \global\increment \enunciationdepth
+ \abovepenalty = \breakgood %~default hard
+ \setflag \allowclubline = \false %~default soft
+ \setflag \allownesting = \false %~default soft
+ \attribution = {}% %~default with
+ \setflag \attributionarg = \false %~default soft
+ \autoqed = {}% %~default soft
+ \belowpenalty = \breakgood %~default hard
+ \continue = 0 %~default with
+ \setflag \continuation = \false % Deprecated
+ \difficulty = 0 %~default with
+ \def \endformat {}% %~default soft
+ \processdesign{\enunciation}{#1}%
+ \zsetcontinue % Handle old \continuation.
+ \if \andp{\notp{\allownesting}}{\gtrp{\enunciationdepth}{1}}%
+ \error{blkcantnest}
+ {An enunciation cannot be nested inside itself}%
+ \fi
+ \if \attributionarg
+ \let \znext = \enunciationarg
+ \else
+ \let \znext = \enunciationb
+ \fi
+ \znext{#1}}
+
+\def \enunciationarg #1#2{% {type}{attribution}
+ \if \notp{\emptyargp{#2}}\attribution = {#2}\fi
+ \enunciationb{#1}}
+
+\def \enunciationb #1{% {type}
+ \attributiontype = 0\relax
+ \global\setflag \zautoqeddone = \false
+ \if \notp{\emptytoksp{\attribution}}%
+ \expandafter\zparseenunattr \the\attribution \zmark
+ \fi
+ \if \notp{\continuationp}%
+ \global\withname\increment{\enunciation#1number}%
+ \fi
+ \global\withname\enunciationnumber{\enunciation#1number}%
+ \setcomptext{\enunciationcomptext}%
+ \enunciationformat
+ \settaginfo{\the\enunciationcomptext}{???}%
+ \ignorespaces}
+
+\def \endenunciation {%
+ \futurelet\nexttoken \zendenunciation}
+
+\def \zendenunciation {%
+ \endenunciationformat
+ \global\decrement \enunciationdepth
+ \endblockscope{enunciation}%
+ \parnext}
+
+\def \enunciationformat {%
+ \endgraf
+ \the\bodyfont
+ \bbskipabove{\abovepenalty}{\aboveskip}%
+ \alterindentation{\leftindent}{\rightindent}%
+ \settextwidth{\width}%
+ \setparrag{\parrag}%
+ \expandafter\labelformat\expandafter{\the\attribution}%
+ \if \notp{\allowclubline}\overrideclubpenalty{\breaknever}\fi}
+
+\def \endenunciationformat{%
+ \if \notp{\zautoqeddone}\the\autoqed \fi
+ \endgraf
+ \endformat
+ \bbskipbelowblockpar{\nexttoken}{\belowpenalty}{\belowskip}}
+
+%~ This marker indicates that the enunciation title completely
+%~ replaces the default title.
+
+\definemarker{\title}
+
+\def \zparseenunattr #1#2\zmark{%
+ \def \znext {#1}%
+ \def \ztitle {\title}%
+ \if \tokeqlp{\znext}{\ztitle}%
+ \attribution = {#2}%
+ \attributiontype = 2\relax
+ \else
+ \attributiontype = 1\relax
+ \fi}
+
+%~ This command is used in enunciation design macros to select the
+%~ title format based on the |\enunciation| *attribution* argument.
+
+\long\def \attributiontypecase #1#2#3{% {format1}{format2}{format3}
+ \ifcase \attributiontype
+ #1% no attribution
+ \or
+ #2% normal attribution
+ \or
+ #3% title override
+ \fi}%
+
+% QED Definition
+% --- ----------
+
+
+%~ This command defines an end-of-enunciation dingbat for use
+%~ with enunciations.
+
+\def \defineeoedingbat #1#2#3{% {name}{text}{space}
+ \withname\gdef {#1dingbat}{#2}%
+ \gdef #1{\zformateoe{#2}#3\zmark}%
+ \withname\gdef {\no\expandafter\discardtok\string#1}{%
+ \global\setflag \zautoqeddone = \true}}
+
+\def \zformateoe #1#2#3\zmark{%
+ {\def \znext {#2}%
+ \def \zfr {\flushright}%
+ \if \tokeqlp{\znext}{\zfr}%
+ \if \vmodep
+ \rightline{#1}%
+ \else\if \mathmodep
+ \hskip #3{#1}%
+ \else
+ \hskip #3\retain \nobreak \hfill {#1}%
+ \fi\fi
+ \else
+ \if \vmodep
+ \rightline{#1}%
+ \else\if \mathmodep
+ \hskip #2#3{#1}%
+ \else
+ \unskip \hskip #2#3\hskip 0pt plus -1fill \retain \nobreak \hfill {#1}%
+ \fi\fi
+ \fi
+ \global\setflag \zautoqeddone = \true}}
+
+
+%~ This command is deprecated in favor of |\defineeoedingbat|.
+
+\def \defineqed #1#2#3#4{% {\name}{text}{space}{min-space}
+ \withname\gdef {#1dingbat}{#2}%
+ \gdef #1{\zformatqed{#2}{#3}{#4}}%
+ \withname\gdef{\no\expandafter\discardtok\string#1}{%
+ \global\setflag \zautoqeddone = \true}}
+
+\def \zformatqed #1#2#3{% {text}{space}{min-space}
+ {\def \znext {#2}%
+ \def \zfr {\flushright}%
+ \if \tokeqlp{\znext}{\zfr}%
+ \hspace{#3}\retain \nobreak \hfill {#1}%
+ \else
+ \if \vmodep
+ \noindent #1\par
+ \else
+ \hspace{#2}{#1}%
+ \fi
+ \fi
+ \global\setflag \zautoqeddone = \true}}
diff --git a/macros/plain/contrib/zztex/tex/zzmathv3.tex b/macros/plain/contrib/zztex/tex/zzmathv3.tex
new file mode 100644
index 0000000000..a30a797bc2
--- /dev/null
+++ b/macros/plain/contrib/zztex/tex/zzmathv3.tex
@@ -0,0 +1,123 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% Module: ZzTeX New Mathematics Facilities
+%
+% Synopsis: This file provides the mathematics facilities for "new math"
+% version 3, which supercedes version 2.
+%
+% Author: Paul C. Anagnostopoulos
+% Created: 7 June 2003
+%
+% Copyright 1989--2020 by Paul C. Anagnostopoulos
+% under The MIT License (opensource.org/licenses/MIT)
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% Math Spaces
+% ---- ------
+
+
+\setmathspaces{4mu plus .25mu minus .5mu}
+ {4mu plus .25mu minus .5mu}
+ {4mu plus .25mu minus .5mu}%
+
+% Math Font Selections
+% ---- ---- ----------
+
+
+\outer\def \ComputerModernmathfonts {%
+ \input zzcmmath\relax
+ \setmathpunctuationstyle{\mit}{\rm}}
+
+\outer\def \Lucidamathfonts #1{% {arrows?}
+ \setflag \zusemar = #1\relax
+ \input zzlucida\relax
+ \setmathpunctuationstyle{\mit}{\rm}}
+
+\outer\def \MathTimefonts #1{% {text face is Times?}
+ \input zzmtime\relax
+ \if #1%
+ \setmathpunctuationstyle{\mit}{\rm}%
+ \else
+ \setmathpunctuationstyle{\rm}{\rm}%
+ \fi}
+
+\outer\def \Stonemathfonts {%
+ \setmathpunctuationstyle{\rm}{\rm}}
+
+% Punctuation Style
+% ----------- -----
+
+
+% Here we deal with the style for comma, period, semicolon, and colon.
+% The default punctuation style for all four is \rm.
+
+
+% This macro defines the math characters \zmperiod, \zmcomma,
+% colon, and semicolon to use the specified style.
+% If the style is \mit, then it's different.
+
+\def \setmathpunctuationstyle #1#2{% {\style1}{\style2}
+ {\zmstyfam = \name{#1fam}%
+ \if \eqlp{\zmstyfam}{\mitfam}%
+ \definemathchar {`.} \classord \mitfam {3A}
+ \definemathchar {`,} \classpunc \mitfam {3B}
+ \else
+ \definemathchar {`.} \classactive \rmfam {00}
+ \definemathchar {`,} \classactive \rmfam {00}
+ \definemathchar {\zmperiod} \classord \zmstyfam {2E}
+ \definemathchar {\zmcomma} \classpunc \zmstyfam {2C}
+ \fi
+ \zmstyfam = \name{#2fam}%
+ \definemathchar {`;} \classpunc \zmstyfam {3B}
+ \definemathchar {`:} \classrel \zmstyfam {3A}}}
+
+% When period and comma are active in math, this is what they do.
+
+{
+\catcode `\. = \catactive
+\gdef .{\mathpalette\zmactperiod{}}
+
+\catcode `\, = \catactive
+\gdef ,{\mathpalette\zmactcomma{}}
+}
+
+\def \zmactperiod #1#2{%
+ \mathord{\hbox to .275em{\hfil $#1\zmperiod$\kern .06em\hfil}}}
+
+\def \zmactcomma #1#2{%
+ \mathpunct{\hbox to .331em{\kern .045em $#1\zmcomma$\hfil}}}
+
+% Dot-Related Commands
+% ----------- --------
+
+
+\def \cdotp {\mathpunct{\vcenter{\hbox{$.$}}}}
+
+\def \ldotp {\mathpunct{.}}
+
+\def \cdots {\mathinner{\cdotp\cdotp\cdotp}}
+
+\def \ddots {%
+ \vbox{\baselineskip = 4pt \lineskiplimit = 0pt
+ \hbox{.}%
+ \hbox{\kern .4em .}%
+ \hbox{\kern .8em .}%
+ \vskip -.25ex}}
+
+\def \ldots {\mathinner{\ldotp\ldotp\ldotp}}
+
+\def \vdots {%
+ \vbox{\baselineskip = 4pt \lineskiplimit = 0pt
+ \hbox{.}%
+ \hbox{.}%
+ \hbox{.}%
+ \vskip -.25ex}}
+
+% Colon Commands
+% ----- --------
+
+
+\def \maps {\mathpunct{:}}
+
+\let \colon = \maps
diff --git a/macros/plain/contrib/zztex/tex/zzmathv4.tex b/macros/plain/contrib/zztex/tex/zzmathv4.tex
new file mode 100644
index 0000000000..a5c5a0c411
--- /dev/null
+++ b/macros/plain/contrib/zztex/tex/zzmathv4.tex
@@ -0,0 +1,129 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% Module: ZzTeX New Mathematics Facilities
+%
+% Synopsis: This file provides the mathematics facilities for "new math"
+% version 4.
+%
+% Author: Paul C. Anagnostopoulos
+% Created: 24 September 2003
+%
+% Copyright 1989--2020 by Paul C. Anagnostopoulos
+% under The MIT License (opensource.org/licenses/MIT)
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% Document Parameters
+% -------- ----------
+
+
+\delimitershortfall = 2pt
+
+% Math Spaces
+% ---- ------
+
+
+\setmathspaces{4mu plus .25mu minus .5mu}
+ {4mu plus .25mu minus .5mu}
+ {4mu plus .25mu minus .5mu}%
+
+% Math Font Selections
+% ---- ---- ----------
+
+
+\outer\def \ComputerModernmathfonts {%
+ \input zzcmmath\relax
+ \setmathpunctuationstyle{\mit}{\rm}}
+
+\outer\def \Lucidamathfonts #1{% {arrows?}
+ \setflag \zusemar = #1\relax
+ \input zzlucida\relax
+ \setmathpunctuationstyle{\mit}{\rm}}
+
+\outer\def \MathTimefonts #1{% {text face is Times?}
+ \input zzmtime\relax
+ \if #1%
+ \setmathpunctuationstyle{\mit}{\rm}%
+ \else
+ \setmathpunctuationstyle{\rm}{\rm}%
+ \fi}
+
+\outer\def \Stonemathfonts {%
+ \setmathpunctuationstyle{\rm}{\rm}}
+
+% Punctuation Style
+% ----------- -----
+
+
+% Here we deal with the style for comma, period, semicolon, and colon.
+% The default punctuation style for all four is \rm.
+
+
+% This macro defines the math characters \zmperiod, \zmcomma,
+% colon, and semicolon to use the specified style.
+% If the style is \mit, then it's different.
+
+\def \setmathpunctuationstyle #1#2{% {\style1}{\style2}
+ {\zmstyfam = \name{#1fam}%
+ \if \eqlp{\zmstyfam}{\mitfam}%
+ \definemathchar {`.} \classord \mitfam {3A}
+ \definemathchar {`,} \classpunc \mitfam {3B}
+ \else
+ \definemathchar {`.} \classactive \rmfam {00}
+ \definemathchar {`,} \classactive \rmfam {00}
+ \definemathchar {\zmperiod} \classord \zmstyfam {2E}
+ \definemathchar {\zmcomma} \classpunc \zmstyfam {2C}
+ \fi
+ \zmstyfam = \name{#2fam}%
+ \definemathchar {`;} \classpunc \zmstyfam {3B}
+ \definemathchar {`:} \classrel \zmstyfam {3A}}}
+
+% When period and comma are active in math, this is what they do.
+
+{
+\catcode `\. = \catactive
+\gdef .{\mathpalette\zmactperiod{}}
+
+\catcode `\, = \catactive
+\gdef ,{\mathpalette\zmactcomma{}}
+}
+
+\def \zmactperiod #1#2{%
+ \mathord{\hbox to .275em{\hfil $#1\zmperiod$\kern .06em\hfil}}}
+
+\def \zmactcomma #1#2{%
+ \mathpunct{\hbox to .331em{\kern .045em $#1\zmcomma$\hfil}}}
+
+% Dot-Related Commands
+% ----------- --------
+
+
+\def \cdotp {\mathpunct{\vcenter{\hbox{$.$}}}}
+
+\def \ldotp {\mathpunct{.}}
+
+\def \cdots {\mathinner{\cdotp\cdotp\cdotp}}
+
+\def \ddots {%
+ \vbox{\baselineskip = 4pt \lineskiplimit = 0pt
+ \hbox{.}%
+ \hbox{\kern .4em .}%
+ \hbox{\kern .8em .}%
+ \vskip -.25ex}}
+
+\def \ldots {\mathinner{\ldotp\ldotp\ldotp}}
+
+\def \vdots {%
+ \vbox{\baselineskip = 4pt \lineskiplimit = 0pt
+ \hbox{.}%
+ \hbox{.}%
+ \hbox{.}%
+ \vskip -.25ex}}
+
+% Colon Commands
+% ----- --------
+
+
+\def \maps {\mathpunct{:}}
+
+\let \colon = \maps
diff --git a/macros/plain/contrib/zztex/tex/zzmathv5.tex b/macros/plain/contrib/zztex/tex/zzmathv5.tex
new file mode 100644
index 0000000000..e7a8f90b2d
--- /dev/null
+++ b/macros/plain/contrib/zztex/tex/zzmathv5.tex
@@ -0,0 +1,129 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% Module: ZzTeX New Mathematics Facilities
+%
+% Synopsis: This file provides the mathematics facilities for "new math"
+% version 5.
+%
+% Author: Paul C. Anagnostopoulos
+% Created: 24 September 2003
+%
+% Copyright 1989--2020 by Paul C. Anagnostopoulos
+% under The MIT License (opensource.org/licenses/MIT)
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% Document Parameters
+% -------- ----------
+
+
+\delimitershortfall = 2pt
+
+% Math Spaces
+% ---- ------
+
+
+\setmathspaces{4mu plus .25mu minus .5mu}
+ {4mu plus .25mu minus .5mu}
+ {4mu plus .25mu minus .5mu}%
+
+% Math Font Selections
+% ---- ---- ----------
+
+
+\outer\def \ComputerModernmathfonts {%
+ \input zzcmmath\relax
+ \setmathpunctuationstyle{\mit}{\rm}}
+
+\outer\def \Lucidamathfonts #1{% {arrows?}
+ \setflag \zusemar = #1\relax
+ \input zzlucida\relax
+ \setmathpunctuationstyle{\mit}{\rm}}
+
+\outer\def \MathTimefonts #1{% {text face is Times?}
+ \input zzmtime\relax
+ \if #1%
+ \setmathpunctuationstyle{\mit}{\rm}%
+ \else
+ \setmathpunctuationstyle{\rm}{\rm}%
+ \fi}
+
+\outer\def \Stonemathfonts {%
+ \setmathpunctuationstyle{\rm}{\rm}}
+
+% Punctuation Style
+% ----------- -----
+
+
+% Here we deal with the style for comma, period, semicolon, and colon.
+% The default punctuation style for all four is \rm.
+
+
+% This macro defines the math characters \zmperiod, \zmcomma,
+% colon, and semicolon to use the specified style.
+% If the style is \mit, then it's different.
+
+\def \setmathpunctuationstyle #1#2{% {\style1}{\style2}
+ {\zmstyfam = \name{#1fam}%
+ \if \eqlp{\zmstyfam}{\mitfam}%
+ \definemathchar {`.} \classord \mitfam {3A}
+ \definemathchar {`,} \classpunc \mitfam {3B}
+ \else
+ \definemathchar {`.} \classactive \rmfam {00}
+ \definemathchar {`,} \classactive \rmfam {00}
+ \definemathchar {\zmperiod} \classord \zmstyfam {2E}
+ \definemathchar {\zmcomma} \classpunc \zmstyfam {2C}
+ \fi
+ \zmstyfam = \name{#2fam}%
+ \definemathchar {`;} \classpunc \zmstyfam {3B}
+ \definemathchar {`:} \classrel \zmstyfam {3A}}}
+
+% When period and comma are active in math, this is what they do.
+
+{
+\catcode `\. = \catactive
+\gdef .{\mathpalette\zmactperiod{}}
+
+\catcode `\, = \catactive
+\gdef ,{\mathpalette\zmactcomma{}}
+}
+
+\def \zmactperiod #1#2{%
+ \mathord{\hbox to .275em{\hfil $#1\zmperiod$\hfil}}}
+
+\def \zmactcomma #1#2{%
+ \mathpunct{\hbox to .331em{\kern .045em $#1\zmcomma$\hfil}}}
+
+% Dot-Related Commands
+% ----------- --------
+
+
+\def \cdotp {\mathpunct{\vcenter{\hbox{$.$}}}}
+
+\def \ldotp {\mathpunct{.}}
+
+\def \cdots {\mathinner{\cdotp\cdotp\cdotp}}
+
+\def \ddots {%
+ \vbox{\baselineskip = 4pt \lineskiplimit = 0pt
+ \hbox{.}%
+ \hbox{\kern .4em .}%
+ \hbox{\kern .8em .}%
+ \vskip -.25ex}}
+
+\def \ldots {\mathinner{\ldotp\ldotp\ldotp}}
+
+\def \vdots {%
+ \vbox{\baselineskip = 4pt \lineskiplimit = 0pt
+ \hbox{.}%
+ \hbox{.}%
+ \hbox{.}%
+ \vskip -.25ex}}
+
+% Colon Commands
+% ----- --------
+
+
+\def \maps {\mathpunct{:}}
+
+\let \colon = \maps
diff --git a/macros/plain/contrib/zztex/tex/zzmathv6.tex b/macros/plain/contrib/zztex/tex/zzmathv6.tex
new file mode 100644
index 0000000000..c47f22ae2d
--- /dev/null
+++ b/macros/plain/contrib/zztex/tex/zzmathv6.tex
@@ -0,0 +1,180 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% Module: ZzTeX New Mathematics Facilities
+%
+% Synopsis: This file provides the mathematics facilities for "new math"
+% version 5.
+%
+% Author: Paul C. Anagnostopoulos
+% Created: 24 September 2003
+%
+% Copyright 1989--2020 by Paul C. Anagnostopoulos
+% under The MIT License (opensource.org/licenses/MIT)
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% Document Parameters
+% -------- ----------
+
+
+\delimitershortfall = 2pt
+
+% Math Spaces
+% ---- ------
+
+
+\setmathspaces{4mu plus .25mu minus .5mu}
+ {4mu plus .25mu minus .5mu}
+ {4mu plus .25mu minus .5mu}%
+
+% Math Font Selections
+% ---- ---- ----------
+
+
+\outer\def \ComputerModernmathfonts {%
+ \input zzcmmath\relax
+ \setmathpunctuationstyle{\mit}{\rm}}
+
+\outer\def \Lucidamathfonts #1{% {arrows?}
+ \setflag \zusemar = #1\relax
+ \input zzlucida\relax
+ \setmathpunctuationstyle{\mit}{\rm}}
+
+\outer\def \MathTimefonts #1{% {text face is Times?}
+ \input zzmtime\relax
+ \setmathucgreekstyles{\mit}{\boldgreekunavailable}%
+ \if #1%
+ \setmathpunctuationstyle{\mit}{\rm}%
+ \else
+ \setmathpunctuationstyle{\rm}{\rm}%
+ \fi}
+
+\outer\def \Stonemathfonts {%
+ \setmathpunctuationstyle{\rm}{\rm}}
+
+% Greek Letter Style
+% ----- ------ -----
+
+
+\def \zmucgreekstyler {}
+\def \zmucgreekstyleb {}
+
+
+% Note the "s" at the end of the name, versus \setmathucgreekstyle.
+
+\def \setmathucgreekstyles #1#2{% {regular-style}{bold-style}
+ \gdef \zmucgreekstyler {#1}%
+ \gdef \zmucgreekstyleb {#2}%
+\definemathchar \Alpha \classvarfam \rmfam {41}%
+\definemathchar \Beta \classvarfam \rmfam {42}%
+\zdefucgreekchar \Gamma {30}%
+\zdefucgreekchar \Delta {31}%
+\definemathchar \Epsilon \classvarfam \rmfam {45}%
+\definemathchar \Zeta \classvarfam \rmfam {5A}%
+\definemathchar \Eta \classvarfam \rmfam {48}%
+\zdefucgreekchar \Theta {32}%
+\definemathchar \Iota \classvarfam \rmfam {49}%
+\definemathchar \Kappa \classvarfam \rmfam {4B}%
+\zdefucgreekchar \Lambda {33}%
+\definemathchar \Mu \classvarfam \rmfam {4D}%
+\definemathchar \Nu \classvarfam \rmfam {4E}%
+\zdefucgreekchar \Xi {34}%
+\definemathchar \Omicron \classvarfam \rmfam {4F}%
+\zdefucgreekchar \Pi {35}%
+\definemathchar \Rho \classvarfam \rmfam {50}%
+\zdefucgreekchar \Sigma {36}%
+\definemathchar \Tau \classvarfam \rmfam {54}%
+\zdefucgreekchar \Upsilon {37}%
+\zdefucgreekchar \Phi {38}%
+\definemathchar \Chi \classvarfam \rmfam {58}%
+\zdefucgreekchar \Psi {39}%
+\zdefucgreekchar \Omega {7F}}
+
+\def \zdefucgreekchar #1#2{% {\name}{code}
+ \gdef #1{%
+ \if \eqlp{\fam}{-1}%
+ {\zmucgreekstyler \mathchar "70#2}%
+ \else\if \eqlp{\fam}{\bffam}%
+ {\zmucgreekstyleb \mathchar "70#2}%
+ \else
+ \error{invgrkstyle}{The current math family precludes using bold Greek}%
+ \fi\fi}}
+
+% Punctuation Style
+% ----------- -----
+
+
+% Here we deal with the style for comma, period, semicolon, and colon.
+% The default punctuation style for all four is \rm.
+
+
+% This macro defines the math characters \zmperiod, \zmcomma,
+% colon, and semicolon to use the specified style.
+% If the style is \mit, then it's different.
+
+\def \setmathpunctuationstyle #1#2{% {\style1}{\style2}
+ {\zmstyfam = \name{#1fam}%
+ \if \eqlp{\zmstyfam}{\mitfam}%
+ \definemathchar {`.} \classord \mitfam {3A}%
+ \definemathchar {`,} \classpunc \mitfam {3B}%
+ \else
+ \definemathchar {`.} \classactive \rmfam {00}%
+ \definemathchar {`,} \classactive \rmfam {00}%
+ \definemathchar {\zmperiod} \classord \zmstyfam {2E}%
+ \definemathchar {\zmcomma} \classpunc \zmstyfam {2C}%
+ \fi
+ \zmstyfam = \name{#2fam}%
+ \definemathchar {`;} \classpunc \zmstyfam {3B}%
+ \definemathchar {`:} \classrel \zmstyfam {3A}}}
+
+% When period and comma are active in math, this is what they do.
+
+{
+\catcode `\. = \catactive
+\gdef .{\mathpalette\zmactperiod{}}
+
+\catcode `\, = \catactive
+\gdef ,{\mathpalette\zmactcomma{}}
+}
+
+\def \zmactperiod #1#2{%
+ \mathord{\hbox to .275em{\hfil $#1\zmperiod$\hfil}}}
+
+\def \zmactcomma #1#2{%
+ \mathpunct{\hbox to .331em{\kern .045em $#1\zmcomma$\hfil}}}
+
+% Dot-Related Commands
+% ----------- --------
+
+
+\def \cdot {\mathbin{\vcenter{\hbox{$.$}}}}
+
+\def \cdotp {\mathpunct{\vcenter{\hbox{$.$}}}}
+
+\def \ldotp {\mathpunct{.}}
+
+\def \cdots {\mathinner{\cdotp\cdotp\cdotp}}
+
+\def \ddots {%
+ \vbox{\baselineskip = 4pt \lineskiplimit = 0pt
+ \hbox{.}%
+ \hbox{\kern .4em .}%
+ \hbox{\kern .8em .}%
+ \vskip -.25ex}}
+
+\def \ldots {\mathinner{\ldotp\ldotp\ldotp}}
+
+\def \vdots {%
+ \vbox{\baselineskip = 4pt \lineskiplimit = 0pt
+ \hbox{.}%
+ \hbox{.}%
+ \hbox{.}%
+ \vskip -.25ex}}
+
+% Colon Commands
+% ----- --------
+
+
+\def \maps {\mathpunct{:}}
+
+\let \colon = \maps
diff --git a/macros/plain/contrib/zztex/tex/zzmerge.tex b/macros/plain/contrib/zztex/tex/zzmerge.tex
new file mode 100644
index 0000000000..05ef863971
--- /dev/null
+++ b/macros/plain/contrib/zztex/tex/zzmerge.tex
@@ -0,0 +1,70 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% Module: ZzTeX Merge Print
+%
+% Synopsis: This module provides a simple merge print facility for ZzTeX.
+%
+% Author: Paul C. Anagnostopoulos
+% Created: 17 October 2000
+%
+% Copyright 1989--2020 by Paul C. Anagnostopoulos
+% under The MIT License (opensource.org/licenses/MIT)
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% Merge Fields
+% ----- ------
+
+
+\setlist \zmrgfields = {}
+\definecount{\zmrgcount}{0}
+
+\def \mergefields #1{%
+ \commalist{\zmrgfields}{#1}%
+ \zmrgcount = 0
+ \maplist{\increment \zmrgcount
+ \withname\edef {\zmrgfmap:##1}{\the\zmrgcount}}
+ {\zmrgfields}}
+
+% Merge Text
+% ----- ----
+
+
+\definetoks{\zmrgtoks}
+
+\long\def \mergetext #1\endmergetext{%
+ \zmrgtoks = {#1}}
+
+% Merge Print
+% ----- -----
+
+
+\definecount{\zmrgi}{0}
+
+
+\def \mergeprint {%
+ \zmrgi = 0
+ \zmrgprinta}
+
+\def \zmrgprinta #1{%
+ \if \lssp{\zmrgi}{\zmrgcount}%
+ \increment \zmrgi
+ \withname\def {\zmrgvmap:\the\zmrgi}{#1}%
+ \let \znext = \zmrgprinta
+ \else
+ \let \znext = \zmrgprintb
+ \fi
+ \znext}
+
+\def \zmrgprintb {%
+ \freshpage{\short\floats\any}%
+ \the\zmrgtoks}
+
+% Merge a Field
+% ----- - -----
+
+
+\def \merge #1{%
+ \edef \tcounta {\name{\zmrgfmap:#1}}%
+ \edef \znext {\name{\zmrgvmap:\the\tcounta}}%
+ \znext}
diff --git a/macros/plain/contrib/zztex/tex/zzmisc.tex b/macros/plain/contrib/zztex/tex/zzmisc.tex
new file mode 100644
index 0000000000..1813a3f572
--- /dev/null
+++ b/macros/plain/contrib/zztex/tex/zzmisc.tex
@@ -0,0 +1,292 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% Module: ZzTeX Miscellaneous Facilities
+%
+% Synopsis: This module contains miscellaneous facilities that do not
+% seem to belong in any other file.
+%
+% Author: Paul C. Anagnostopoulos
+% Created: 26 August 1989
+%
+% Copyright 1989--2020 by Paul C. Anagnostopoulos
+% under The MIT License (opensource.org/licenses/MIT)
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% Character Categories
+% --------- ----------
+
+
+% The following list contains characters with category codes other
+% than endofline, ignored, space, letter, other, and invalid:
+
+\setlist \zcatlist = {}
+
+
+\def \establishcatcode #1#2{% {`\c}{\catname}
+ \zdelcat{#1}%
+ \catcode #1 = #2%
+ {\setflag \znext = \true
+ \if \eqlp{#2}{\catendofline}\setflag \znext = \false \fi
+ \if \eqlp{#2}{\catignored}\setflag \znext = \false \fi
+ \if \eqlp{#2}{\catspace}\setflag \znext = \false \fi
+ \if \eqlp{#2}{\catletter}\setflag \znext = \false \fi
+ \if \eqlp{#2}{\catother}\setflag \znext = \false \fi
+ \if \eqlp{#2}{\catinvalid}\setflag \znext = \false \fi
+ \if \znext \append{#1}{\zcatlist}\fi}}
+
+\def \zdelcat #1{%
+ {\setlist \znewcatlist = {}%
+ \maplist{\def \zcata {##1}\def \zcatb{#1}%
+ \if \notp{\tokeqlp{\zcata}{\zcatb}}\append{##1}{\znewcatlist}\fi}%
+ {\zcatlist}%
+ \setlist \zcatlist = \znewcatlist}}
+
+% Initialize the character list:
+
+\establishcatcode{`\^^L}{\catactive}
+\establishcatcode{`\#}{\catparameter}
+\establishcatcode{`\$}{\catmath}
+\establishcatcode{`\&}{\catalign}
+\establishcatcode{`\%}{\catcomment}
+\establishcatcode{`\@}{\catactive}
+\establishcatcode{`\\}{\catescape}
+\establishcatcode{`\^}{\catsuperscript}
+\establishcatcode{`\_}{\catsubscript}
+\establishcatcode{`\{}{\catbegin}
+\establishcatcode{`\}}{\catend}
+\establishcatcode{`\~}{\catactive}
+
+\def \uncatcode #1#2#3{% {allow-commands}{allow-at-commands}{allow-math}
+ \maplist{\catcode##1=\catother}{\zcatlist}%
+ \if #1%
+ \catcode`\\ = \catescape
+ \catcode`\{ = \catbegin
+ \catcode`\} = \catend
+ \fi
+ \if #2%
+ \catcode`\@ = \catactive
+ \fi
+ \if #3%
+ \catcode`\$ = \catmath
+ \catcode`\^ = \catsuperscript
+ \catcode`\_ = \catsubscript
+ \fi}
+
+\def \catcodemath {%
+ \catcode `\ = \catspace
+ \catcode `\$ = \catmath
+ \catcode `\^ = \catsuperscript
+ \catcode `\_ = \catsubscript}
+
+\def \catcoderange #1#2#3{% {first}{last}{\catname}
+ \tcounta = #1\relax
+ \tcountb = #2\relax \increment \tcountb
+ \loop
+ \ifnum \tcounta < \tcountb
+ \catcode \tcounta = #3%
+ \increment \tcounta
+ \repeat}
+
+% Make the upper half of the ASCII characters invalid.
+
+\catcoderange{"80}{"FF}{\catinvalid}
+
+% Conditional Text
+% ----------- ----
+
+
+\let \setif = \if
+\let \endsetif = \fi
+
+\def \ignore {%
+ \if \notp{\zemptyblockstackp}\todo{$\ignore command.}\fi
+ \setif \false}
+
+\let \endignore = \endsetif
+
+% Date & Time
+% ---- - ----
+
+
+% \year, \month, and \day are TeX parameters.
+
+\definecount{\weekday}{0}
+
+% \time is a TeX parameter, the number of minutes since midnight.
+
+\definecount{\hour}{0}
+\definecount{\minute}{0}
+
+
+\def \zdtinit {%
+ \zwdinit
+ \hour = \time
+ \divide \hour by 60
+ \minute = \time
+ \divide \minute by 60
+ \multiply \minute by -60
+ \advance \minute by \time}
+
+\def \zwdinit {%
+ \tcounta = \year
+ \if \lssp{\month}{3}\advance \tcounta by -1 \fi
+ \tcountb = \tcounta
+ \divide \tcountb by 100
+ \tcountc = \tcountb
+ \multiply \tcountc by -100
+ \advance \tcountc by \tcounta
+ \tcounta = \month
+ \if \lssp{\month}{3}\advance \tcounta by 9 \else \advance \tcounta by -3 \fi
+ \multiply \tcountb by 146097
+ \divide \tcountb by 4
+ \multiply \tcountc by 1461
+ \divide \tcountc by 4
+ \advance \tcountb by \tcountc
+ \multiply \tcounta by 153
+ \advance \tcounta by 2
+ \divide \tcounta by 5
+ \advance \tcountb by \tcounta
+ \advance \tcountb by \day
+ \advance \tcountb by -693902
+ \weekday = \tcountb
+ \divide \weekday by 7
+ \multiply \weekday by -7
+ \advance \weekday by \tcountb}
+
+
+\def \formattime {%
+ \number\hour:%
+ \if \lssp{\minute}{10}0\fi
+ \number\minute}
+
+% Fancy Names
+% ----- -----
+
+
+\def \AMSTeX {AMS\TeX}
+
+\def \BibTeX {Bib\TeX}
+
+\def \LaTeX {L\kern-.3em \raise .4ex \hbox{a}\kern-.05em \TeX}
+
+% Hiding Writes
+% ------ ------
+
+
+% These macros help to hide the \write's that are performed by commands
+% like \tag and \xpage.
+
+\definedimen{\zhidewriteskip}{0pt}
+
+\def \zbeginhidewrite {%
+ \zhidewriteskip = \lastskip
+ \begingroup
+ \if \hmodep \edef \zsf {\spacefactor=\the\spacefactor}\fi}
+
+\def \zendhidewrite {%
+ \if \hmodep \zsf \fi
+ \endgroup
+ \if \andp{\hmodep}{\dimposp{\zhidewriteskip}}\ignorespaces \fi}
+
+% Initialization File
+% -------------- ----
+
+
+\def \zloadinifile {%
+ \gdef \inicompositor {???}%
+ \gdef \iniinitials {???}%
+ \gdef \ininame {???}
+ \gdef \iniorganization {(none)}%
+ \checkfile{\zini}{zztex.ini}%
+ \if \zini
+ \writelog{(loading ini file)}%
+ \zloadinifilea
+ \else
+ \writelog{(no ini file)}%
+ \fi}
+
+\def \zloadinifilea {%
+ \begingroup
+ \catcode \endlinechar = \catcomment
+ \catcode `\; = \catcomment
+ \openin \zreada zztex.ini\relax
+ \setflag \zinireg = \false
+ \loop
+ \read \zreada to \zline
+ \if \notp{\emptydefp{\zline}}\expandafter\zloadinifileb \zline\zmark \fi
+ \if \notp{\eofp{\zreada}}\repeat
+ \closein \zreada
+ \endgroup}
+
+\def \zloadinifileb #1#2\zmark {%
+ \if \codeeqlp{#1}{[}%
+ \zloadinifilec #2\zmark
+ \else\if \zinireg
+ \zloadinifiled #1#2\zmark
+ \fi\fi}
+
+\def \zloadinifilec #1]#2\zmark {%
+ \stringeql{\zinireg}{#1}{registration}}
+
+\def \zloadinifiled #1=#2\zmark {%
+ \withname\gdef {\ini#1}{#2}}
+
+% Penalties
+% ---------
+
+
+% The following symbolic penalties should be used everywhere so they
+% can be adjusted without any recoding. The trailing spaces are
+% like \relax but don't screw up \ifnum.
+
+\def \breaknever {10000 } %~ Never break here. %^penalty
+\def \breakworst {500 } %~ Worst place to break. %^penalty
+\def \breakworse {300 } %~ Worse place to break. %^penalty
+\def \breakbad {100 } %~ Bad place to break. %^penalty
+\def \breakallowed {0 } %~ Break allowed here. %^penalty
+\def \breakgood {-100 } %~ Good place to break. %^penalty
+\def \breakbetter {-300 } %~ Better place to break. %^penalty
+\def \breakbest {-500 } %~ Best place to break. %^penalty
+\def \breakalways {-10000 } %~ Always break here. %^penalty
+
+
+\def \allowbreak {\penalty \breakallowed} %~ Allow page break here.
+\def \break {\penalty \breakalways} %~ Force page break here.
+\def \nobreak {\penalty \breaknever} %~ Disallow page break here.
+\let \unbreakable = \nobreak
+
+% Versions
+% --------
+
+
+% I have no idea what my intention was here.
+
+
+\def \defineversion #1#2{% {\name}{status}
+ \if #2%
+ \let \znext = \zletiftrue
+ \else
+ \let \znext = \zletiffalse
+ \fi
+ \withname\let {\end \expandafter\discardtok\string#1} = \fi
+ \znext{#1}}
+
+\def \zletiftrue #1{%
+ \let #1 = \iftrue}
+
+\def \zletiffalse #1{%
+ \let #1 = \iffalse}
+
+
+\defineversion{\ignore}{\false}
+
+% Translator Flags
+% ---------- -----
+
+
+\def \XTran<#1>{%
+ \error{xtran}{XTran flag: #1}}
+
+\def \ZzTran[#1]{%
+ \error{zztran}{ZzTran flag: #1}}
diff --git a/macros/plain/contrib/zztex/tex/zzmtime.tex b/macros/plain/contrib/zztex/tex/zzmtime.tex
new file mode 100644
index 0000000000..fd19871257
--- /dev/null
+++ b/macros/plain/contrib/zztex/tex/zzmtime.tex
@@ -0,0 +1,89 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% Module: ZzTeX MathTime Font Support
+%
+% Synopsis: This module contains various definitions and redefinitions
+% necessary to use the MathTime fonts by The TeXplorators Corp.
+%
+% Author: Paul C. Anagnostopoulos
+% Created: 24 March 1993
+%
+% Copyright 1989--2020 by Paul C. Anagnostopoulos
+% under The MIT License (opensource.org/licenses/MIT)
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% Type Styles
+% ---- ------
+
+\setstyleskewchar{\mit}{"2D}
+
+% Redefine Text Accents
+% -------- ---- -------
+
+
+\def \t #1{% %~ Tie-after accent. %^accent
+ {\edef \znext {\the\font}\the\textfont2 \accent "41 \znext #1}}
+
+% Redefine Math Characters
+% -------- ---- ----------
+
+
+\zmchar \Gamma \classord \mitfam {30}
+\zmchar \Delta \classord \mitfam {31}
+\zmchar \Theta \classord \mitfam {32}
+\zmchar \Lambda \classord \mitfam {33}
+\zmchar \Xi \classord \mitfam {34}
+\zmchar \Pi \classord \mitfam {35}
+\zmchar \Sigma \classord \mitfam {36}
+\zmchar \Upsilon \classord \mitfam {37}
+\zmchar \Phi \classord \mitfam {38}
+\zmchar \Psi \classord \mitfam {39}
+\zmchar \Omega \classord \mitfam {7F}
+
+\zmchar \varkappa \classord \mitfam {7E}
+
+\zmchar {`+} \classbinop \msyfam {43}
+\zmchar \compose \classbinop \msyfam {42}
+\zmchar \capprod \classbinop \msyfam {5A}
+\zmchar \cupprod \classbinop \msyfam {59}
+% Do not define \zmdagger and \zmddagger.
+\zmchar \setdiff \classbinop \msyfam {58}
+
+\zmchar \triangleleft \classbinop \msyfam {47}
+\zmchar \triangleright \classbinop \msyfam {46}
+
+\zmchar {`=} \classrel \msyfam {44}
+
+\zmchar {`(} \classopen \mitfam {2E}
+\definemathdelimiter {`(} \classord \mitfam {2E} \mexfam {00}
+
+\zmchar {`)} \classclose \mitfam {2F}
+\definemathdelimiter {`)} \classord \mitfam {2F} \mexfam {01}
+
+\def \hbar {\mathord{h \llap{$\mathchar"024E \mkern 3.5mu$}}}
+
+\def \acute {\zmtaccent{024B}{7013}} %~ Acute accent. %^math_accent
+\def \bar {\zmtaccent{024E}{7016}} %~ Bar accent. %^math_accent
+\def \breve {\zmtaccent{024D}{7015}} %~ Breve accent. %^math_accent
+\def \check {\zmtaccent{024C}{7014}} %~ Check accent. %^math_accent
+\def \ddot {\zmtaccent{0252}{????}} %~ Double dot accent. %^math_accent
+\def \dot {\zmtaccent{0250}{700B}} %~ Dot accent. %^math_accent
+\def \grave {\zmtaccent{024A}{7012}} %~ Grave accent. %^math_accent
+\def \zmhat {\zmtaccent{024F}{7007}} %~ Hat accent. %^math_accent
+\def \zmtilde {\zmtaccent{0251}{700F}} %~ Tilde accent. %^math_accent
+\def \vec {\mathaccent "0245\relax} %~ Vector accent. %^math_accent
+\def \widebar {\mathaccent "0253\relax} %~ Wide bar accent. %^math_accent
+
+\def \zmtaccent #1#2{%
+ \if \eqlp{\fam}{-1}%
+ \mathaccent "#1\relax
+ \else
+ \mathaccent "#2\relax
+ \fi}
+
+% Redefine General Tools
+% -------- ------- -----
+
+
+\zmchar \Relbar \classrel \msyfam {48}
diff --git a/macros/plain/contrib/zztex/tex/zznewmath.tex b/macros/plain/contrib/zztex/tex/zznewmath.tex
new file mode 100644
index 0000000000..583bb3d63a
--- /dev/null
+++ b/macros/plain/contrib/zztex/tex/zznewmath.tex
@@ -0,0 +1,93 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% Module: ZzTeX New Mathematics Facilities
+%
+% Synopsis: This file provides the mathematics facilities for "new math"
+% modes 1 and 2. It is loaded after the design file.
+%
+% Author: Paul C. Anagnostopoulos
+% Created: 16 October 2002
+%
+% Copyright 1989--2020 by Paul C. Anagnostopoulos
+% under The MIT License (opensource.org/licenses/MIT)
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% Punctuation
+% -----------
+
+
+\if \eqlp{\newmath}{1}%
+
+\def \ldotp {\hbox to .42em{\hfil.\hfil}}
+
+\else\if \gtrp{\newmath}{1}%
+
+% This macro defines the math characters \zmperiod, \zmcomma,
+% colon, and semicolon to use the specified style.
+% If the style is \mit, then it's different.
+
+\def \setmathpunctuationstyle #1{% {style}
+ {\zmstyfam = \name{#1fam}%
+ \definemathchar {\zmperiod} \classord \zmstyfam {2E}
+ \definemathchar {\zmcomma} \classpunc \zmstyfam {2C}
+ \definemathchar {`;} \classpunc \zmstyfam {3B}
+ \definemathchar {`:} \classrel \zmstyfam {3A}}}
+
+% Now establish \rm as the default punctuation style.
+
+\setmathpunctuationstyle{\rm}
+
+% Period and comma must be active in math.
+
+\definemathchar {`.} \classactive \rmfam {00}
+
+\definemathchar {`,} \classactive \rmfam {00}
+
+% When period and comma are active in math, this is what they do.
+
+{
+\catcode `\. = \catactive
+\gdef .{\mathpalette\zmactperiod{}}
+
+\catcode `\, = \catactive
+\gdef ,{\mathpalette\zmactcomma{}}
+}
+
+\def \zmactperiod #1#2{%
+ \mathord{\hbox to .28em{\hfil $#1\zmperiod$\hfil}}}
+
+\def \zmactcomma #1#2{%
+ \mathpunct{\hbox to .33em{\hfil $#1\zmcomma$\kern .03em\hfil}}}
+
+% Now we can define all the dot-oriented math commands.
+
+\def \cdotp {\mathpunct{\vcenter{\hbox{$.$}}}}
+
+\def \ldotp {\mathpunct{.}}
+
+\def \cdots {\mathinner{\cdotp\cdotp\cdotp}}
+
+\def \ddots {%
+ \vbox{\baselineskip = 4pt \lineskiplimit = 0pt
+ \hbox{.}%
+ \hbox{\kern .4em .}%
+ \hbox{\kern .8em .}%
+ \vskip -.25ex}}
+
+\def \ldots {\mathinner{\ldotp\ldotp\ldotp}}
+
+\def \vdots {%
+ \vbox{\baselineskip = 4pt \lineskiplimit = 0pt
+ \hbox{.}%
+ \hbox{.}%
+ \hbox{.}%
+ \vskip -.25ex}}
+
+% Make \maps and \colon do the right thing.
+
+\def \maps {\mathpunct{:}}
+
+\let \colon = \maps
+
+\fi\fi
diff --git a/macros/plain/contrib/zztex/tex/zznote.tex b/macros/plain/contrib/zztex/tex/zznote.tex
new file mode 100644
index 0000000000..412d46c98a
--- /dev/null
+++ b/macros/plain/contrib/zztex/tex/zznote.tex
@@ -0,0 +1,522 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% Module: ZzTeX Notes Facilities
+%
+% Synopsis: This module defines various blocks that produce "notes", such
+% as footnotes.
+%
+% Author: Paul C. Anagnostopoulos
+% Created: 28 September 1989
+%
+% Copyright 1989--2020 by Paul C. Anagnostopoulos
+% under The MIT License (opensource.org/licenses/MIT)
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% Footnotes
+% ---------
+
+
+\defineblock{\footnote}{\endfootnote}{\true}{}
+
+% The footnote parameters are used at two different times: when the
+% \footnote macro appears, and when the page is output.
+
+% The \referencing parameter takes the following values:
+% 0: Produce neither a reference nor an intro number.
+% 1: Produce an intro number, but no reference.
+% 2: Produce both a reference and an intro number.
+
+%~block footnote
+% \aboveskip = glue % Space b/b above first footnote line.
+% \setflag \abutting = flag % True if note abutts previous one.
+% \bodyfont = {...} % Font for footnote text.
+% \def \comptextformat {...} % Composite number text formatter.
+% \internoteskip = glue % Extra space between footnotes.
+% \leftindent = glue % Left indentation.
+% \height = dimen % Maximum height on page.
+% \interlinepenalty = penalty % Penalty between footnote lines.
+% \def \noteintroformat {...} % Footnote intro formatter.
+% \def \noterefformat {...} % Footnote reference formatter.
+% \parindent = dimen % Paragraph indent.
+% \parrag = dimen % Paragraph raggedness.
+% \parskip = glue % Paragraph skip.
+% \referencing = integer % How the footnote is referenced.
+% \rightindent = glue % Right indentation.
+% \rulecolor = {...} % Color of rule.
+% \rulewidth = dimen % Width of rule.
+% \ruleheight = dimen % Height of rule.
+% \ruleshift = dimen % Horizontal shift of rule.
+% \ruleskip = dimen % Space b/b below rule.
+% \def \spilloverride {...} % Override parameters on spillover.
+% \textcolor = {...} % Color of text.
+%~end
+
+\defineskip{\internoteskip}{0pt}
+\definecount{\referencing}{0}
+
+\defineinsert{\zfninsert}
+
+
+\def \footnote {% {text}
+ \blockcantbein{\footnote}{\footnote}%
+ \beginblockscope{footnote}%
+ \global\increment \footnotedepth
+ \setflag \abutting = \false %~default with
+ \referencing = 2 %~default with
+ \interlinepenalty = \breakworse %~default hard
+ \rulecolor = {black}% %~default soft
+ \ruleshift = 0pt %~default soft
+ \def \spilloverride {}% %~default soft
+ \textcolor = {black}% %~default soft
+ \processdesign{\footnote}{}%
+ \if \posp{\referencing}%
+ \global\increment \footnotenumber
+ \setcomptext{\footnotecomptext}%
+ \else
+ \footnotecomptext = {???}%
+ \fi
+ \settaginfo{\the\footnotecomptext}{???}%
+ \if \andp{\hmodep}{\eqlp{\referencing}{2}}%
+ {\edef \zsf {\spacefactor=\the\spacefactor}%
+ \/%
+ \if \DVIWindoinuse \colorspecial{ifview color push rgb 1 0 1}\fi
+ \noterefformat
+ \if \DVIWindoinuse \colorspecial{ifview color pop}\fi
+ \zsf}%
+ \fi
+ \footnoteinsert}
+
+\def \footnoteinsert {%
+ \the\bodyfont
+ \global\count\zfninsert = 1000
+ \global\dimen\zfninsert = \height
+ \global\skip\zfninsert = \aboveskip
+ \global\advance \skip\zfninsert by -\internoteskip
+ \global\advance \skip\zfninsert by -\ht\strutbox % of footnote text.
+ \insert \zfninsert \bgroup
+ \zpushvcontext
+ \color{\the\textcolor}%
+ \setindentation{\leftindent}{\rightindent}%
+ \setparrag{\parrag}%
+ \parfillskip = \normalparfillskip
+ \spaceskip = 0pt \xspaceskip = 0pt
+ \splittopskip = \ht\strutbox
+ \advance \splittopskip by \internoteskip
+ \splitmaxdepth = \dp\strutbox
+ \floatingpenalty = 20000\relax % Reference on same page as note.
+ \if \posp{\referencing}%
+ \noteintroformat
+ \else
+ \indent
+ \fi
+ \vbox to \splittopskip{}% % Strut in first line.
+ \bgroup
+ \aftergroup\endfootnote
+ \let \znext} % Eat open brace of footnote text.
+ % Absorb footnote text.
+ % \bgroup matches close brace.
+
+\def \endfootnote {%
+ \if \hmodep \strut \fi % Strut in last line.
+ \endgraf
+ \unskip
+ \endcolor
+ \zpopvcontext
+ \egroup % \insert
+ \global\decrement \footnotedepth
+ \endblockscope{footnote}}
+
+% This macro is invoked by the output routine to format footnotes.
+
+\def \zfootnoteformat #1{% {body-depth}
+ \beginblockscope{footnote}%
+ \ruleshift = 0pt
+ \def \spilloverride {}%
+ % We used to do the \processdesign here, but that does a \processwith
+ % that can end up processing some other block's pending \with. Oops.
+ \footnotedesign \relax % \processdesign{\footnote}{}
+ \if \notp{\emptydefp{\spilloverride}}%
+ \setbox \zboxa = \vtop{\unvcopy \zfninsert}%
+ \if \dimzerop{\ht\zboxa}\spilloverride \fi
+ \fi
+ \vskip \skip\zfninsert
+ \vskip -#1\relax
+ \if \andp{\dimposp{\ruleheight}}{\dimposp{\rulewidth}}%
+ \the\bodyfont
+ \tdimena = \ruleskip
+ \advance \tdimena by -\ht\strutbox
+ \advance \tdimena by -\internoteskip
+ \vskip -\tdimena
+ \vskip -\ruleheight
+ \nointerlineskip
+ \noindent \hspace{\ruleshift}%
+ \color{\the\rulecolor}\rule{height \ruleheight depth 0pt width \rulewidth}%
+ \endcolor\par
+ \vskip \tdimena
+ \fi
+ \unvbox \zfninsert
+ \endblockscope{footnote}}
+
+% Endnote
+% -------
+
+
+\defineblock{\endnote}{\endendnote}{\true}{}
+
+% The endnote parameters are used at two different times: when the
+% \endnote command appears, and when the \endnotes command is used
+% to typeset the notes.
+
+%~block endnote
+% \setflag \abutting = flag % True if note abutts previous one.
+% \def \comptextformat {...} % Composite number text formatter.
+% \endnoteclass = integer % Class of endnote.
+% \def \noterefformat {...} % Footnote reference formatter.
+% \referencing = integer % How the endnote is referenced.
+%~end
+
+\definecount{\endnoteclass}{0}
+\definetoks{\zendtoks}
+
+
+\def \endnote {% {text}
+ \blockcantbein{\endnote}{\endnote}%
+ \beginblockscope{endnote}%
+ \global\increment \endnotedepth
+ \setflag \abutting = \false %~default with
+ \endnoteclass = 0 %~default with
+ \referencing = 2 %~default with
+ \processdesign{\endnote}{}%
+ \global\increment \endnotenumber
+ \setcomptext{\endnotecomptext}%
+ \if \andp{\hmodep}{\eqlp{\referencing}{2}}%
+ {\edef \zsf {\spacefactor = \the\spacefactor}%
+ \/%
+ \if \DVIWindoinuse \colorspecial{ifview color push rgb 1 0 1}\fi
+ \noterefformat
+ \if \DVIWindoinuse \colorspecial{ifview color pop}\fi
+ \zsf}%
+ \fi
+ \afterassignment \endendnote
+ \zendtoks =}
+
+\def \endendnote {%
+ \edef \zendtext {\the\zendtoks}%
+ \edef \znext {\noexpand\xref{end}{\noexpand\folio}{\the\endnotecomptext}
+ {\expandafter\zdefof \meaning\zendtext\zmark}
+ {\the\divisionname,\the\endnoteclass}}%
+ \znext
+ \global\decrement \endnotedepth
+ \endblockscope{endnote}}
+
+% Endnotes
+% --------
+
+
+\defineblock{\endnotes}{\endendnotes}{\false}{}
+
+%~block endnotes
+% \setflag \abutting = flag % True if note abutts previous one.
+% \def \comptextformat {...} % Composite number text formatter.
+% \endnoteclass = integer % Class of endnote.
+% \def \noterefformat {...} % Footnote reference formatter.
+% \referencing = integer % How the endnote is referenced.
+%~end
+
+\definecount{\endnotepage}{0}
+\definetoks{\zenddivlist}
+\definetoks{\zenddiv}
+\definecount{\zendclass}{0}
+
+\def \endnotes #1{% {division-list}
+ \blockcantbein{\endnotes}{\endnotes}%
+ \blockmustbein{\endnotes}{\list}%
+ \beginblockscope{endnotes}%
+ \global\increment \endnotesdepth
+ \endnoteclass = 0 %~default with
+ \processdesign{\endnote}{}% % Use endnote block's design.
+ \global\increment \endnotesnumber
+ \zenddivlist = {#1}%
+ \zxloadcomp{\xrefloadendmode}%
+ \endendnotes}
+
+\def \endendnotes {%
+ \endgraf
+ \fakepar
+ \setlist \zendadjlist = {}%
+ \global\decrement \endnotesdepth
+ \endblockscope{endnotes}}
+
+% This macro is called for each endnote entry in the cross-reference file.
+
+\long\def \xrefend #1#2#3#4{%
+ \ifnum \xrefmode=\xrefloadendmode
+ \xrefendb{#1}{#2}{#3}{#4}%
+ \fi}
+
+\long\def \xrefendb #1#2#3#4{% {page}{number}{text}{division,class}
+ \def \znext ##1,##2,##3\zmark{%
+ \zenddiv={##1}\zendclass=##2}%
+ \znext #4,0,\zmark \relax
+ \if \eqlp{\zendclass}{\endnoteclass}%
+ \edef \znext {\noexpand\inclusionlist\noexpand\zendtest
+ {\the\zenddiv}{\the\zenddivlist}}%
+ \znext
+ \if \zendtest
+ \setbox \zboxa = \hbox{\zendclass=0#1}%
+ \endnotepage = \if \dimzerop{\wd\zboxa}#1\else 0 \fi
+ \let \xrefmode = \xrefrunmode
+ \zchkendadj{#2}%
+ \item{#2}#3\par
+ \let \xrefmode = \xrefloadendmode
+ \fi
+ \fi}
+
+% This macro allows the compositor to noninvasively adjust pages between
+% endnotes.
+
+\setlist \zendadjlist = {}
+
+\long\def \endnotesadjustment #1#2{% {division.number}{commands}
+ \append{{#1}{#2}}{\zendadjlist}}
+
+\long\def \zchkendadj #1{% {number}
+ \maplist{\zchkendadjb{#1}##1}{\zendadjlist}}
+
+\long\def \zchkendadjb #1#2#3{% {number}{division.number}{commands}
+ \stringeql{\znext}{\the\zenddiv.#1}{#2}%
+ \if \znext #3\relax \fi}
+
+% Margin Notes
+% ------ -----
+
+
+\defineblock{\marginnote}{\endmarginnote}{\true}{}
+
+%~block marginnote Type
+% \def \beginformat {...} % Beginning of text formatter.
+% \bodyfont = {...} % Font for note text.
+% \def \comptextformat {...} % Composite number text formatter.
+% \def \endformat {...} % End of text formatter.
+% \leftindent = glue % Left indentation.
+% \margingutter = dimen % Gutter for note in right margin.
+% \def \noteintroformat {...} % Note intro formatter.
+% \def \noterefformat {...} % Note reference formatter.
+% \parindent = dimen % Paragraph indent.
+% \parrag = dimen % Paragraph raggedness.
+% \parskip = glue % Paragraph skip.
+% \position = {...} % Position (see below).
+% \referencing = integer % How the margin note is referenced.
+% \rightindent = glue % Right indentation.
+% \textcolor = {...} % Color of text.
+% \vshift = dimen % Vertical shift for note.
+% \width = dimen % Width of text in box.
+%~end
+
+\definedimen{\margingutter}{0pt}
+\definecount{\marginnotepage}{0}
+
+\definecount{\zdivmncounter}{0}
+\definedimen{\zmnshift}{0pt}
+\definetoks{\zmntoks}
+\definebox{\zmnbox}
+\definedimen{\zmnprevdepth}{0pt}
+
+
+\def \marginnote #1{% {type}
+ \blockcantbein{\marginnote}{\marginnote}%
+ \beginblockscope{marginnote}%
+ \global\increment \marginnotedepth
+ \global\increment \zdivmncounter
+ \whichpage{\marginnotepage}{zM:\the\divisionname-\the\zdivmncounter}%
+ \def \beginformat {}% %~default soft
+ \def \endformat {}% %~default soft
+ \leftindent = 0pt %~default soft
+ \referencing = 0 %~default soft
+ \rightindent = 0pt %~default soft
+ \textcolor = {black}% %~default soft
+ \vshift = 0pt %~default soft
+ \processdesign{\marginnote}{#1}%
+ \zparsemnpos{\the\position}%
+ \if \posp{\referencing}%
+ \global\increment \marginnotenumber
+ \setcomptext{\marginnotecomptext}%
+ \else
+ \marginnotecomptext = {???}%
+ \fi
+ \settaginfo{\the\marginnotecomptext}{???}%
+ \if \andp{\hmodep}{\eqlp{\referencing}{2}}%
+ {\edef \zsf {\spacefactor=\the\spacefactor}%
+ \/%
+ \if \DVIWindoinuse \colorspecial{ifview color push rgb 1 0 1}\fi
+ \noterefformat
+ \if \DVIWindoinuse \colorspecial{ifview color pop}\fi
+ \zsf}%
+ \fi
+ \afterassignment \endmarginnote
+ \zmntoks =}
+
+\def \endmarginnote {%
+ \setbox \zmnbox = \vtop{%
+ \zpushvcontext
+ \color{\the\textcolor}%
+ \the\bodyfont
+ \setindentation{\leftindent}{\rightindent}%
+ \settextwidth{\width}
+ \setparrag{\parrag}%
+ \beginformat
+ \if \posp{\referencing}\noteintroformat \fi
+ \the\zmntoks
+ \endgraf
+ \endformat
+ \endcolor
+ \zpopvcontext}%
+ \marginnoteformat
+ \global\decrement \marginnotedepth
+ \endblockscope{marginnote}}
+
+\def \marginnoteformat {%
+ \if \vmodep
+ \zmnprevdepth = \prevdepth
+ \nointerlineskip
+ \else
+ \vadjust
+ \fi
+ \bgroup
+ \moveright \zmnshift \vtop to 0pt{%
+ \vskip \vshift
+ \box \zmnbox
+ \vss
+ \tagpageonly{\uniquetag{zM}{\the\zdivmncounter}}}%
+ \egroup
+ \if \vmodep \prevdepth = \zmnprevdepth \fi}
+
+% This macro sets up variables that specify the position of a margin note
+% according to the \position design parameter:
+%
+% \ifevenpage Use next position only on even page.
+% \ifoddpage Use next position only on odd page.
+% \leftmargin Shift note to left margin.
+% \outsidemargin Shift note to outside margin.
+% \rightmargin Shift note to right margin.
+
+\definecount{\zmnhpos}{0}
+
+\def \zparsemnpos #1{% {options...}
+ \global\zmnhpos = 0
+ {\def \ifevenpage ##1{\if \evenp{\marginnotepage}##1\fi}%
+ \def \ifoddpage ##1{\if \oddp{\marginnotepage}##1\fi}%
+ \def \leftmargin {\global\zmnhpos=1\relax}%
+ \def \outsidemargin{\ifevenpage{\leftmargin}\ifoddpage{\rightmargin}}%
+ \def \rightmargin {\global\zmnhpos=2\relax}%
+ #1\relax}%
+ \ifcase \zmnhpos
+ \error{nomnpos}
+ {No horizontal position has been specified for a margin note}%
+ \or
+ \if \evenp{\marginnotepage}%
+ \zmnshift = -\evenlefttextmargin
+ \else
+ \zmnshift = -\oddlefttextmargin
+ \fi
+ \or
+ \calculate \zmnshift = {\textmeasure,+,\margingutter}%
+ \fi}
+
+% This macro is invoked at the beginning of each division.
+
+\def \zmndivinit {%
+ \global\zdivmncounter = 0\relax}
+
+% Proof Notes
+% ----- -----
+
+
+\defineblock{\proofnote}{\endproofnote}{\true}{}
+
+%~block proofnote
+% \bodyfont = {...} % Font for note text.
+% \evenshift = dimen % Horizontal shift for even pages.
+% \oddshift = dimen % Horizontal shift for odd pages.
+% \textcolor = {...} % Color of note.
+% \vshift = dimen % Vertical shift for note.
+% \width = dimen % Width of note.
+%~end
+
+\definedimen{\evenshift}{0pt}
+\definedimen{\oddshift}{0pt}
+
+\definecount{\zdivpncounter}{0}
+\definecount{\zpnpage}{0}
+
+
+\def \proofnote {% {text}
+ \blockcantbein{\proofnote}{\proofnote}%
+ \beginblockscope{proofnote}%
+ \global\increment \proofnotedepth
+ \global\increment \zdivpncounter
+ \whichpage{\zpnpage}{zP:\the\divisionname-\the\zdivpncounter}%
+ \parindent = 0pt
+ \parskip = 2pt
+ \textcolor = {black}% %~default soft
+ \vshift = 0pt %~default soft
+ \processdesign{\proofnote}{}%
+ \afterassignment \endproofnote
+ \zmntoks =}
+
+\def \endproofnote {%
+ \zcalcpnshift
+ \setbox \zmnbox = \vtop{%
+ \zpushvcontext
+ \color{\the\textcolor}%
+ \the\bodyfont
+ \settextwidth{\width}
+ \setparrag{.4\width}%
+ \def \endpartext {}% % Prevent end-of-paragraph text.
+ \the\zmntoks
+ \endgraf
+ \endcolor
+ \zpopvcontext}%
+ \proofnoteformat
+ \long\edef \znext {\noexpand\todo{.Proof note: \the\zmntoks}}%
+ \znext
+ \global\decrement \proofnotedepth
+ \endblockscope{proofnote}}
+
+\def \proofnoteformat {%
+ \if \vmodep
+ \zmnprevdepth = \prevdepth
+ \nointerlineskip
+ \else
+ \vadjust
+ \fi
+ \bgroup
+ \moveright \zmnshift \vtop to 0pt{%
+ \vskip -\parskip
+ \vskip \vshift
+ \box \zmnbox
+ \vss
+ \tagpageonly{\uniquetag{zP}{\the\zdivpncounter}}}%
+ \egroup
+ \if \vmodep \prevdepth = \zmnprevdepth \fi}
+
+\def \zcalcpnshift {%
+ \if \evenp{\zpnpage}%
+ \if \negp{\evenshift}%
+ \zmnshift = \evenshift
+ \else
+ \calculate \zmnshift = {\textmeasure,+,\evenshift}%
+ \fi
+ \else
+ \if \negp{\oddshift}%
+ \zmnshift = \oddshift
+ \else
+ \calculate \zmnshift = {\textmeasure,+,\oddshift}%
+ \fi
+ \fi}
+
+% This macro is invoked at the beginning of each division.
+
+\def \zpndivinit {%
+ \global\zdivpncounter = 0\relax}
diff --git a/macros/plain/contrib/zztex/tex/zzoverlay.tex b/macros/plain/contrib/zztex/tex/zzoverlay.tex
new file mode 100644
index 0000000000..e957ebd35e
--- /dev/null
+++ b/macros/plain/contrib/zztex/tex/zzoverlay.tex
@@ -0,0 +1,100 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% Module: ZzTeX Page Overlay Facilities
+%
+% Synopsis: This file provides the ability to overlay text and rules
+% on each page.
+%
+% Author: Paul C. Anagnostopoulos
+% Created: 29 March 2006
+%
+% Copyright 1989--2020 by Paul C. Anagnostopoulos
+% under The MIT License (opensource.org/licenses/MIT)
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% Overlay & Proof Identification
+% ------- - ----- --------------
+
+
+\setflag \zoverlayset = \false
+\definetoks{\zoverlay}
+\zoverlay = {blind}
+\definetoks{\zproofid}
+\zproofid = {}
+
+\def \setpageoverlay #1{% {name}
+ \global\setflag \zoverlayset = \true
+ \global\zoverlay = {#1}}
+
+\def \proofidentification #1{% {text}
+ \zproofid = {#1}}
+
+\def \zproofidfile {%
+ \immediate\openout \zwritea = \jobname.zzq\relax
+ \immediate\write \zwritea {\the\zproofid}%
+ \immediate\closeout \zwritea}
+
+% Builtin Overlays
+% ------- --------
+
+
+\definedimen{\zoverlaythickness}{.4pt}
+
+
+\def \pageoverlayblind {}
+
+\def \pageoverlaytrimbox {%
+ \smashbox{%
+ \vbox to \trimheight{%
+ \topcornermarks{\trimwidth}{.5\trimheight}{\zoverlaythickness}%
+ \vss
+ \bottomcornermarks{\trimwidth}{.5\trimheight}{\zoverlaythickness}}}%
+ \zpagelengthmarks
+ \zslugline}
+
+\def \pageoverlaytrimmarks {%
+ \smashbox{%
+ \vbox to \trimheight{%
+ \topcornermarks{\trimwidth}{.75pc}{\zoverlaythickness}%
+ \vss
+ \bottomcornermarks{\trimwidth}{.75pc}{\zoverlaythickness}}}%
+ \zpagelengthmarks
+ \zslugline}
+
+% Page Length Marks
+% ---- ------ -----
+
+
+\def \zpagelengthmarks {%
+ \smashbox{%
+ \calculate \tdimena = {\headmargin,+,\typeareaheight,-,\footerheight}%
+ \vskip \tdimena
+ \hbox to \trimwidth{%
+ \llap{\vrule height \zoverlaythickness width .75pc}\hfil
+ \rlap{\vrule height \zoverlaythickness width .75pc}}}}
+
+% Slug Line
+% ---- ----
+
+
+\definedimen{\zslugindent}{.25in}
+
+
+\def \zslugline {%
+ \if \notp{\emptytoksp{\zproofid}}%
+ \kern \trimheight
+ \if \dimgtrp{\trimheight}{10.75in}\kern -.25in \fi
+ \kern -8pt
+ \hbox to \trimwidth{%
+ \hspace{\zslugindent}%
+ \zannofont
+ \the\zproofid \quad
+ \number\year/\number\month/\number\day\space \formattime \quad
+ p. \folio \hspace{5pt}%
+ \if \notp{\emptytoksp{\divisionname}}(\the\divisionname)\fi
+ \hfill
+ \inicompositor, \iniinitials \quad
+ \ZzTeX\ \ZzTeXversion
+ \hspace{\zslugindent}}%
+ \fi}
diff --git a/macros/plain/contrib/zztex/tex/zzpage.tex b/macros/plain/contrib/zztex/tex/zzpage.tex
new file mode 100644
index 0000000000..a666c18094
--- /dev/null
+++ b/macros/plain/contrib/zztex/tex/zzpage.tex
@@ -0,0 +1,908 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% Module: ZzTeX Page Facilities
+%
+% Synopsis: This module contains all the user facilities for
+% specifying things about the page layout. It also
+% contains the output routines.
+%
+% Author: Paul C. Anagnostopoulos
+% Created: 7 March 1990
+%
+% Copyright 1989--2020 by Paul C. Anagnostopoulos
+% under The MIT License (opensource.org/licenses/MIT)
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% Tracing Page Makeup
+% ------- ---- ------
+
+
+\def \tracepagemakeup #1{%
+ \if \posp{\tracingpagemakeup}%
+ \writelog{ZzTeX page \the\pagenumber: #1}%
+ \fi}
+
+% Initialize Page Parameters
+% ---------- ---- ----------
+
+
+% Here we assume that the type area width is the same on both pages.
+
+\def \zpageinit {%
+ \gcalculate \trimplusbleedheight = {\standardbleed,+,\trimheight,+,%
+ \standardbleed}%
+ \gcalculate \trimplusbleedwidth = {\standardbleed,+,\trimwidth,+,%
+ \standardbleed}%
+ \gcalculate \typeareawidth = {\oddlefttextmargin,+,\textmeasure,+,%
+ \oddrighttextmargin}%
+ \gcalculate \evenoutermargin = {\trimwidth,-,\typeareawidth,-,%
+ \eveninnermargin}%
+ \gcalculate \evenbleedshift = {-\evenlefttextmargin,-,\evenoutermargin,-,%
+ \standardbleed}%
+ \gcalculate \oddoutermargin = {\trimwidth,-,\typeareawidth,-,%
+ \oddinnermargin}%
+ \gcalculate \oddbleedshift = {-\oddlefttextmargin,-,\oddinnermargin,-,%
+ \standardbleed}}
+
+% Page Number
+% ---- ------
+
+
+\countdef \pagenumber = 0
+
+\declaresnapitem{\pagenumber}
+
+\def \setpagenumber #1{% {number}
+ \global\pagenumber = #1\relax
+ \setcolumnnumber{1}}
+
+\def \evenpagep {\evenp{\pagenumber}}
+\def \oddpagep {\oddp{\pagenumber}}
+
+\def \folio {}
+
+\def \setfoliostyle #1{% {\style}
+ \ztoksa = \expandaftertwice{\name{#1folio}}%
+ \xdef \folio {\the\ztoksa}}
+
+\def \chapterpagefolio {\the\chaptercomptext-\number\pagenumber}
+\def \arabicfolio {\number\pagenumber}
+\let \decimalfolio = \arabicfolio
+\def \letterfolio {\ucletter\pagenumber}
+\def \partpagefolio {\the\partcomptext-\number\pagenumber}
+\def \romanfolio {\romannumeral\pagenumber}
+
+% Marks
+% -----
+
+
+% These macros hold the five parts of the current mark, each part having
+% three subparts. When a part is saved, the first subpart is expanded and
+% the second and third subparts are not.
+
+\definetoks{\zmarki} \zmarki = {{???}{???}{???}}
+\definetoks{\zmarkii} \zmarkii = {{???}{???}{???}}
+\definetoks{\zmarkiii} \zmarkiii = {{???}{???}{???}}
+\definetoks{\zmarkiv} \zmarkiv = {{???}{???}{???}}
+\definetoks{\zmarkv} \zmarkv = {{???}{???}{???}}
+
+
+\def \setmarkinfothree #1#2#3#4{% {part}{text1}{text2}{text3}
+ {\tcounta = #1\relax
+ \edef \znext {{#2}}%
+ \global\name{\zmark\romannumeral\tcounta} = \expandafter{\znext{#3}{#4}}%
+ \mark{\noexpand\or \the\zmarki \noexpand\or \the\zmarkii
+ \noexpand\or \the\zmarkiii \noexpand\or \the\zmarkiv
+ \noexpand\or \the\zmarkv}}%
+ \if \vmodep \repeatpenalty \fi} % In case glue follows the mark.
+
+\def \setmarkinfo #1#2#3{% {part}{text1}{text2}
+ \setmarkinfothree{#1}{#2}{#3}{???}}
+
+
+\let \firstnewmark = \firstmark
+\let \bottommark = \botmark
+
+\def \markinfo #1#2#3{% {mark}{part}{subpart}
+ \ifcase #3%
+ \relax
+ \or
+ \expandafter\zoneofthree
+ \ifcase #2\expandafter\relax #1\else {???}{???}{???}\fi
+ \or
+ \expandafter\ztwoofthree
+ \ifcase #2\expandafter\relax #1\else {???}{???}{???}\fi
+ \or
+ \expandafter\zthreeofthree
+ \ifcase #2\expandafter\relax #1\else {???}{???}{???}\fi
+ \else
+ \error{invsubpart}{The subpart `#3' is invalid}%
+ \fi}
+
+% Page Screen
+% ---- ------
+
+
+\def \fullpagescreen #1{% {color}
+ \if \inbackground
+ \vskip -\standardbleed
+ \moveleft \standardbleed \vbox{%
+ \colorrule{#1}{width \trimplusbleedwidth height \trimplusbleedheight}}%
+ \else
+ \hrule width 0pt
+ \vsinkfromtrim{-\standardbleed}
+ \smashbox{%
+ \colorparrule{#1}
+ {\if \evenp{\pagenumber}\evenbleedshift \else \oddbleedshift \fi}
+ {width \trimplusbleedwidth height 0pt depth \trimplusbleedheight}}%
+ \fi}
+
+% New Headers & Footers Scheme
+% --- ------- - ------- ------
+
+
+% Most of the definitions are in zzrunner.tex, but these need to be in
+% here so they can be used in design files.
+
+
+\def \headerblindformat {}
+
+\def \footerblindformat {}
+
+\def \headercornermarkformat {%
+ \line{\vrule height .5pt depth 0pt width 6pt \hfil
+ \vrule height .5pt depth 0pt width 6pt}%
+ \nointerlineskip
+ \line{\vrule height 6pt depth 0pt width .5pt \hfil
+ \vrule height 6pt depth 0pt width .5pt}%
+ \vfil}
+
+\def \footercornermarkformat {%
+ \vfil
+ \line{\vrule height 6pt depth 0pt width .5pt \hfil
+ \vrule height 6pt depth 0pt width .5pt}%
+ \nointerlineskip
+ \line{\vrule height .5pt width 6pt \hfil
+ \vrule height .5pt width 6pt}}
+
+% Old Headers & Footers Scheme
+% --- ------- - ------- ------
+
+
+\def \zcurheader{\normalheader}
+\def \zcurfooter{\normalfooter}
+
+\setflag \zoverrunners = \false
+\let \zsaveheader = \relax
+\let \zsavefooter = \relax
+
+
+\def \setrunners #1#2{% {header}{footer}
+ \if \zoverrunners
+ \gdef \zsaveheader {#1}%
+ \gdef \zsavefooter {#2}%
+ \else
+ \gdef \zcurheader {#1}%
+ \gdef \zcurfooter {#2}%
+ \fi}
+
+\def \overriderunners #1#2{% {header}{footer}
+ \if \notp{\zoverrunners}%
+ \global\let \zsaveheader = \zcurheader
+ \global\let \zsavefooter = \zcurfooter
+ \global\setflag \zoverrunners = \true
+ \fi
+ \gdef \zcurheader {#1}%
+ \gdef \zcurfooter {#2}}
+
+\def \blindrunners {%
+ \overriderunners{\blindheader}{\blindfooter}}
+
+\def \zsetrunnerstoks #1{% {tokens}
+ \expandafter\overriderunners \the#1}
+
+\def \zoverriderunnerstoks #1{% {tokens}
+ \expandafter\overriderunners \the#1}
+
+% The following macro is used to initialize the \runners parameter.
+
+\def \zoldrunners #1{%
+ \runners = {#1}}
+
+% The following macro is called from the output routine.
+
+\def \znextpagerunners {%
+ \if \zoverrunners
+ \global\let \zcurheader = \zsaveheader
+ \global\let \zcurfooter = \zsavefooter
+ \global\setflag \zoverrunners = \false
+ \fi}
+
+
+% The following macros provide some standard, simple header and footer
+% formats.
+
+\def \blindheader {}
+
+\def \blindfooter {}
+
+\def \cornermarkheader {\headercornermarkformat}
+
+\def \cornermarkfooter {\footercornermarkformat}
+
+% The following header and footer formats are provided by the design.
+% Just in case they are forgotten:
+
+\def \normalheader {%
+ \warning{noheadfoot}{No normal header format has been specified}}
+\def \normalfooter {%
+ \warning{noheadfoot}{No normal footer format has been specified}}
+\def \chapterheader {%
+ \warning{noheadfoot}{No chapter header format has been specified}}
+\def \chapterfooter {%
+ \warning{noheadfoot}{No chapter footer format has been specified}}
+
+% Multiple Columns
+% -------- -------
+
+
+% The following parameters are calculated by the \setpagecolumns command:
+
+\setflag \zdofullbreak = \false % True if doing a full break.
+\setflag \zusetypewidth = \false % True if using type area width.
+
+\definecount{\columncount}{0} % Number of columns on page.
+\definecount{\columnnumber}{0} % Current column number.
+% \hsize
+% \vsize
+
+
+% The \setpagecolumns command accepts the following options:
+%
+% \fullbreak
+% \shortbreak
+% \usetextmeasure
+% \usetextwidth
+% \usetypewidth
+
+\def \setpagecolumns #1#2#3{% {options}{columns}{gutter-width}
+ \endgraf
+ {\def \fullbreak {\global\setflag \zdofullbreak = \true}%
+ \def \shortbreak {\global\setflag \zdofullbreak = \false}%
+ \def \usetextmeasure {\global\setflag \zutw = \false}%
+ \def \usetextwidth {\global\setflag \zutw = \false}%
+ \def \usetypewidth {\global\setflag \zutw = \true}%
+ \global\setflag \zdofullbreak = \false
+ \global\setflag \zutw = \false
+ #1}%
+ \if \andp{\zusetypewidth}{\notp{\zutw}}%
+ \zejectcolpage
+ \else\if \onep{\columncount}%
+ \if \orp{\gtrp{#2}{1}}{\zutw}\penalty \zpenoneton \fi
+ \else\if \neqlp{#2}{\columncount}%
+ \zejectcolpage
+ \fi\fi\fi
+ \global\columncount = #2\relax
+ \global\setflag \zusetypewidth = \zutw
+ \tdimena = \if \zusetypewidth \typeareawidth \else \textmeasure \fi
+ \calculate \tdimenb = {-#3,*,\columncount,+,#3,+,\tdimena,/,\columncount}%
+ \settextwidth{\tdimenb}%
+ \global\hsize = \hsize % Make these two parameters global.
+ \global\parfillskip = \parfillskip
+ \setcolumnnumber{1}%
+ \tracepagemakeup{Columns: \the\columncount; width: \the\hsize; gutter: #3.}}
+
+\def \zejectcolpage {%
+ \if \zdofullbreak
+ \freshpage{\full\floats\any}%
+ \else
+ \freshpage{\short\floats\any}%
+ \fi
+ \global\vsize = \textareaheight} % Needed even if no page eject.
+
+
+\def \setcolumnnumber #1{% {number}
+ \global\columnnumber = #1\relax
+ \if \andp{\oddpagep}{\lastcolumnp}%
+ \global\brokenpenalty = \oddbrokenpenalty
+ \else
+ \global\brokenpenalty = \evenbrokenpenalty
+ \fi}
+
+\def \firstcolumnp {\eqlp{\columnnumber}{1}}
+\def \lastcolumnp {\eqlp{\columnnumber}{\columncount}}
+
+
+%-----------------------------------------------------------------------------
+%
+% This old command is deprecated, although it will work forever.
+
+
+\def \setcolumns #1#2#3{% {count}{gutter-width}{use-type-area}
+ \endgraf
+ \if \andp{\zusetypewidth}{\notp{#3}}%
+ \freshpage{\short\floats\any}%
+ \global\vsize = \textareaheight % Needed even if no page eject.
+ \else \if \eqlp{\columncount}{1}%
+ \if \orp{\gtrp{#1}{1}}{#3}%
+ \penalty \zpenoneton
+ \fi
+ \else \if \neqlp{#1}{\columncount}%
+ \freshpage{\short\floats\any}%
+ \global\vsize = \textareaheight % Needed even if no page eject.
+ \fi\fi\fi
+ \global\columncount = #1\relax
+ \global\setflag \zusetypewidth = #3\relax
+ {\zpageinit
+ \tdimena = #2\relax
+ \multiply \tdimena by \columncount
+ \advance \tdimena by -#2\relax
+ \if \zusetypewidth
+ \advance \tdimena by -\typeareawidth
+ \else
+ \advance \tdimena by -\textmeasure
+ \fi
+ \divide \tdimena by -\columncount
+ \settextwidth{\tdimena}%
+ \global\hsize = \hsize % Make these two parameters global.
+ \global\parfillskip = \parfillskip}%
+ \setcolumnnumber{1}%
+ \tracepagemakeup{Columns: \the\columncount; width: \the\hsize; gutter: #2.}}
+
+% Column Breaks
+% ------ ------
+
+
+\def \columnbreak #1{% {penalty}
+ \penalty #1\relax}
+
+\def \freshcolumn #1{% {options}
+ {\let \zfill = \relax
+ \let \full = \relax \def \short {\def \zfill {\vfill}}%
+ #1\relax%
+ \if \notp{\dimzerop{\lastskip}}\vskip -\lastskip \fi
+ \zfill
+ \penalty \zpenfreshcol}}
+
+\def \fullcolumnbreak {\freshcolumn{\full}}
+\def \shortcolumnbreak {\freshcolumn{\short}}
+
+\def \blankcolumn {%
+ \line{}%
+ \shortcolumnbreak}
+
+% Page Breaks
+% ---- ------
+
+
+%~ This command starts a new page. The options specify the
+%~ exact behavior:
+%~ & |\any|& Start an even or odd page.
+%~ & |\even|& Start an even page.
+%~ & |\floats|& Place all floats before new page.
+%~ & |\full|& Current page is bottomed out.
+%~ & |\nofloats|& No need to place all floats.
+%~ & |\odd|& Start an odd page.
+%~ & |\short|& Run current page short.
+%~ &.
+
+\def \freshpage #1{% {options} %^page_makeup
+ \if \vmodep
+ {\let \zfill = \vfill
+ \let \short = \relax \def \full {\let \zfill = \relax}%
+ \let \zflush = \zpenfreshpage
+ \let \nofloats = \relax \def \floats {\let \zflush = \zpenflushpage}%
+ \let \zpage = \relax
+ \let \any = \relax
+ \def \odd {\def \zpage {\if \evenpagep \blankpage \fi}}%
+ \def \even {\def \zpage {\if \oddpagep \blankpage \fi}}%
+ #1\relax%
+ \if \notp{\dimzerop{\lastskip}}\vskip -\lastskip \fi
+ \zfill
+ \if \notp{\lastcolumnp}%
+ \penalty \zpenfreshcol
+ \if \notp{\lastcolumnp}%
+ \loop
+ \blankcolumn
+ \if \notp{\lastcolumnp}\repeat
+ \fi
+ \line{}%
+ \vfill
+ \fi
+ \penalty \zflush
+ \zpage}%
+ \else
+ \error{pagepar}{Page break requested in the middle of a paragraph}%
+ \fi}
+
+%~ This command starts a new page, bottoming out the current page.
+
+\def \fullpagebreak {\freshpage{\full\nofloats\any}} %^page_makeup
+
+%~ This command starts a new page, leaving the current page short.
+%~ The argument specifies the number of lines short, or, if
+%~ specified as |\asap|, runs the page as short as possible.
+
+\def \shortpagebreak #1{% {lines} %^page_makeup
+ {\def \zarg {#1}\def \zasap {\asap}%
+ \if \tokeqlp{\zarg}{\zasap}%
+ \freshpage{\short\nofloats\any}%
+ \else
+ \kern -\dp\strutbox
+ \kern #1\baselineskip
+ \fullpagebreak
+ \fi}}
+
+\def \blankpage {%
+ \blindrunners
+ \pagehint{(blank)}%
+ \hrule width 0pt
+ \freshpage{\short\nofloats\any}}
+
+\def \blankleaf {%
+ \freshpage{\short\floats\odd}
+ \blankpage
+ \freshpage{\short\even}
+ \blankpage}
+
+% Overriding Text Area Height
+% ---------- ---- ---- ------
+
+
+\definedimen{\zortahsave}{0pt} % Saved normal text area height.
+\definecount{\zortahcount}{0} % Number of overridden pages.
+
+
+%~ This command changes the number of lines on the specified number
+%~ of pages, beginning with the current page. The nominal line count
+%~ is increased or decreased by the specified number of lines,
+%~ which should be coded with a plus or minus sign. A fractional
+%~ number of lines is allowed. It is best to change two pages (a spread)
+%~ with each command.
+
+\def \overridetextareaheight #1#2{% {pages}{lines} %^page_makeup
+ \if \posp{\zortahcount}%
+ \warning{overortah}{Text area height overridden during previous override}%
+ \zresetortah
+ \fi
+ {\global\zortahsave = \textareaheight
+ \global\zortahcount = #1\relax
+ \global\advance \textareaheight by #2\baselineskip
+ \global\vsize = \textareaheight
+ \if \dimneqlp{\pagegoal}{\maxdimen}%
+ \tdimena = \textareaheight
+ \advance \tdimena by -\zortahsave
+ \advance \tdimena by \pagegoal
+ \global\pagegoal = \tdimena
+ \fi}%
+ \tracepagemakeup{Overriding text area height: pages: #1, vsize: \the\vsize,
+ goal: \the\pagegoal.}}
+
+\def \zresetortah {%
+ \global\zortahcount = 0
+ \global\textareaheight = \zortahsave
+ \global\vsize = \textareaheight
+%%% \global\pagegoal = \vsize
+ \tracepagemakeup{Un-overriding text area height: vsize: \the\vsize.}}
+
+\def \zortahdivfinal {%
+ \if \posp{\zortahcount}%
+ \warning{divortah}{Text area height overridden across a division}%
+ \zresetortah
+ \fi}
+
+% Text Margins
+% ---- -------
+
+
+% The following two macros are really bogus, because TeX doesn't
+% always know what page it's on, except in the output routine.
+
+\def \thislefttextmargin {%
+ \if \evenpagep \evenlefttextmargin \else \oddlefttextmargin \fi}
+
+\def \thisrighttextmargin {%
+ \if \evenpagep \evenrighttextmargin \else \oddrighttextmargin \fi}
+
+\definedimen{\typeareashift}{0pt}
+\definecount{\ztaspage}{0}
+
+\def \determinetypeareashift #1{% {page}
+ \global\typeareashift = \if \evenp{#1}-\evenlefttextmargin \else
+ -\oddlefttextmargin \fi}
+
+% Layout Summary
+% ------ -------
+
+
+{\catcode`\_ = \catactive
+
+\gdef \zlayoutsummary {%
+ {\def _{\space}%
+ \writelog{}%
+ \writelog{Layout:}%
+ \writelog{}%
+ \tdimena = .013837\trimwidth
+ \tdimenb = .013837\trimheight
+ \writelog{Trim: \thefactor\tdimena"_x_\thefactor\tdimenb"}%
+ \tdimena = .013837\headmargin
+ \writelog{Head margin: \thefactor\tdimena"}%
+ \tdimena = .083333\typeareawidth
+ \tdimenb = .083333\typeareaheight
+ \writelog{Type area: \thefactor\tdimena pc_x_\thefactor\tdimenb pc}%
+ \tdimena = .013837\eveninnermargin
+ \tdimenb = .013837\oddinnermargin
+ \writelog{Inside margins: even \thefactor\tdimena", odd \thefactor\tdimenb"}%
+ \tdimena = .013837\evenoutermargin
+ \tdimenb = .013837\oddoutermargin
+ \writelog{Outside margins: even \thefactor\tdimena", odd \thefactor\tdimenb"}%
+ \tdimena = .083333\evenlefttextmargin
+ \tdimenb = .083333\oddlefttextmargin
+ \writelog{Left text margins: even \thefactor\tdimena pc,
+ odd \thefactor \tdimenb pc}%
+ \tdimena = .083333\evenrighttextmargin
+ \tdimenb = .083333\oddrighttextmargin
+ \writelog{Right text margins: even \thefactor\tdimena pc,
+ odd \thefactor\tdimenb pc}%
+ \tdimena = .083333\textmeasure
+ \tdimenb = .083333\textareaheight
+ \writelog{Text area: \thefactor\tdimena pc_x_\thefactor\tdimenb pc}%
+ \writelog{Top skip: \the\topskip, delta: \the\topdelta}%
+ \writelog{}}}
+
+}% \catcode
+
+% Debugging
+% ---------
+
+
+\def \zlogoutf {-1} % First page to log.
+\def \zlogoutl {-1} % Last page to log.
+
+
+\def \logoutput #1#2{% {first-page}{last-page}
+ \global\def \zlogoutf {#1}%
+ \global\def \zlogoutl {#2}}
+
+% Output Routine
+% ------ -------
+
+
+% The following definitions are for special penalties that control
+% page makeup:
+
+\def \zpennormal {-10000\relax} % Normal page break.
+\def \zpenoneton {-10001\relax} % Switch from 1 to n columns.
+\def \zpenfreshcol {-10002\relax} % Fresh column.
+\def \zpenfreshpage {-10003\relax} % Fresh page.
+\def \zpenflushpage {-10004\relax} % Fresh page, and flush floats.
+\def \zpenfloatpage {-10005\relax} % Page of floats scheduled.
+
+% We need to put the depth of box 255 in a convenient place.
+
+\definedimen{\zoutputcoldepth}{0pt}
+
+% We must save \mathdisplayprevgraf across the output routine.
+
+\definecount{\zsavemdpg}{0}
+
+% The following boxes hold parts of the page:
+
+\definebox{\zcolbox} % One column's worth.
+\definebox{\zbodybox} % The body, multiple columns' worth.
+\definebox{\zonetonbox} % Stuff preceding 1- to n-column switch.
+\setflag \zonetontype = \false % True if 1-to-n text uses type area width.
+
+% This toks register is invoked at the beginning of every column, so that
+% things like index carryovers can be performed.
+
+\definetoks{\everycolumn}
+\everycolumn = {\relax}
+
+
+\output = {\zoutput}
+
+\def \zoutput {%
+ \if \andp{\notp{\lssp{\pagenumber}{\zlogoutf}}}%
+ {\notp{\gtrp{\pagenumber}{\zlogoutl}}}%
+ \tracingoutput = 1
+ \showboxdepth = 1000 \showboxbreadth = 1000\relax
+ \fi
+ \tracepagemakeup{[Output routine invoked for column \the\columnnumber;
+ penalty: \the\outputpenalty.}%
+ \tracepagemakeup{Vsize: \the\vsize;
+ Box 255: \the\ht255+\the\dp255 \space x \the\wd255.}%
+ \zoutputcoldepth = \dp255\relax
+ \let \zsavewith = \zwith % Save these items across the
+ \let \zsavevariant = \zvariant % output routine in case they
+ \zsavemdpg = \mathdisplayprevgraf % are altered within it.
+ \normalbaselines
+ \let \par = \endgraf
+ \everyparagraph = {}%
+ \spaceskip = 0pt
+ \tcounta = \outputpenalty
+ \if \eqlp{\tcounta}{-'10000000000}\tcounta = \zpenflushpage \fi
+ \if \gtrp{\tcounta}{-10000}\tcounta = -10000\relax \fi
+ \negate \tcounta
+ \advance \tcounta by -10000\relax
+ \ifcase \tcounta
+ \zpagenormal \or
+ \zpageoneton \or
+ \zpagefreshcol \or
+ \zpagefreshpage \or
+ \zpageflushpage \or
+ \zpagefloatpage \else
+ \zzerror{Invalid page break penalty: \the\outputpenalty}%
+ \fi
+ \global\let \zvariant = \zsavevariant
+ \global\let \zwith = \zsavewith
+ \global\mathdisplayprevgraf = \zsavemdpg
+ \tracepagemakeup{Output routine complete.]}}
+
+\def \zpagenormal {%
+ \tracepagemakeup{Process normal column.}%
+ \zcolumnsave
+ \if \lastcolumnp
+ \zpagecontents
+ \setcolumnnumber{1}%
+ \else
+ \tcounta = \columnnumber \increment \tcounta
+ \setcolumnnumber{\tcounta}%
+ \fi
+ \zfloatinit
+ \zschedulefloats{\zfloatcount}{\true}{\false}%
+ \if \gtrp{\zfloatcount}{99}%
+ \zfltpage{\zpenfloatpage}%
+ \else
+ \zeverycol
+ \fi}
+
+\def \zpageoneton {%
+ \tracepagemakeup{Process 1- to n-column transition.}%
+ \zonetoncolumnbody
+ \global\setflag \zonetontype = \zusetypewidth
+ \global\advance \vsize by -\ht\zonetonbox
+ \global\advance \vsize by -\dp\zonetonbox
+ \tracepagemakeup{Space remaining on page: \the\vsize.}}
+
+\def \zpagefreshcol {%
+ \tracepagemakeup{Process `fresh column' request.}%
+ \zpagenormal}
+
+\def \zpagefreshpage {%
+ \tracepagemakeup{Process `fresh page' request.}%
+ \zpagenormal}
+
+\def \zpageflushpage {%
+ \tracepagemakeup{Process `fresh page, flush floats' request.}%
+ \zcolumnsave
+ \if \lastcolumnp
+ \zpagecontents
+ \setcolumnnumber{1}%
+ \else
+ \tcounta = \columnnumber \increment \tcounta
+ \setcolumnnumber{\tcounta}%
+ \fi
+ \zfloatinit
+ \zschedulefloats{\zfloatcount}{\true}{\true}%
+ \if \posp{\zfloatcount}%
+ \zfltpage{\zpenflushpage}%
+ \else
+ \zeverycol
+ \fi}
+
+\def \zpagefloatpage {%
+ \tracepagemakeup{Process page of floats.}%
+ \zcolumnsave
+ \if \lastcolumnp
+ \zpagecontents
+ \setcolumnnumber{1}%
+ \else
+ \tcounta = \columnnumber \increment \tcounta
+ \setcolumnnumber{\tcounta}%
+ \fi
+ \zfloatinit
+ \zschedulefloats{\zfloatcount}{\true}{\false}%
+ \if \gtrp{\zfloatcount}{99}%
+ \zfltpage{\zpenfloatpage}%
+ \fi}
+
+\def \zfltpage #1{% {penalty}
+ \if \notp{\emptytoksp{\zfltrunners}}%
+ \zoverriderunnerstoks{\zfltrunners}%
+ \fi
+ {\leftskip = 0pt \rightskip = 0pt
+ \line{}}%
+ \kern -\topskip % Why bother to do this?
+ \nobreak \vfill
+ \penalty #1}
+
+\def \zeverycol {%
+ {\zadjtitle = \zadjtitlemark % \adjusttitle should adjust mark.
+ \def \zadjloc {\mark}%
+ \the\everycolumn}}
+
+% Page Makeup: Column
+% ---- ------- ------
+
+
+\def \zcolumnsave {%
+ \zcolumnbody
+ \if \firstcolumnp
+ \global\setbox \zbodybox = \hbox to \zbodyboxwidth {\box\zcolbox \hss}%
+ \ztoksa = \expandafter{\topmark}%
+ \xdef \topmarki {\the\ztoksa}%
+ \ztoksa = \expandafter{\firstnewmark}%
+ \xdef \firstnewmarki {\the\ztoksa}%
+ \ztoksa = \expandafter{\bottommark}%
+ \xdef \bottommarki {\the\ztoksa}%
+ \else
+ \global\setbox \zbodybox = \hbox to \zbodyboxwidth {%
+ \unhbox\zbodybox \hfill \box\zcolbox}%
+ \fi}
+
+\def \zbodyboxwidth {%
+ \if \zusetypewidth \typeareawidth \else \textmeasure \fi}
+
+\def \zcolumnbody {%
+ \tracepagemakeup{Wrapping up the column; hsize: \the\hsize.}%
+ {\vbadness = 10000\relax
+ \global\setbox \zcolbox = \vbox to \vsize {%
+ \setindentation{0pt}{0pt}%
+ \boxmaxdepth = \maxdepth
+ \if \notp{\voidboxp{\ztopcolinsert}}\unvbox \ztopcolinsert \fi
+ \unvbox 255 % Page built by TeX.
+ \if \risingfootnotes
+ \if \notp{\voidboxp{\zfninsert}}\zfootnoteformat{\zoutputcoldepth}\fi
+ \fi
+ \if \risingbottomfloats
+ \if \notp{\voidboxp{\zbotcolinsert}}\unvbox \zbotcolinsert \fi
+ \fi
+ \if \raggedbottom
+ \kern -\zoutputcoldepth \vfill
+ \fi
+ \if \notp{\risingfootnotes}%
+ \if \notp{\voidboxp{\zfninsert}}\zfootnoteformat{\zoutputcoldepth}\fi
+ \fi
+ \if \notp{\risingbottomfloats}%
+ \if \notp{\voidboxp{\zbotcolinsert}}\unvbox \zbotcolinsert \fi
+ \fi}}}
+
+% This is a special version of \zcolumnbody for the 1- to n-column
+% transition.
+
+\def \zonetoncolumnbody {%
+ \global\setbox \zonetonbox = \vbox{%
+ \setindentation{0pt}{0pt}%
+ \boxmaxdepth = \maxdepth
+ \if \notp{\voidboxp{\ztopcolinsert}}\unvbox \ztopcolinsert \fi
+ \unvbox 255 % Page built by TeX.
+ \vskip \baselineskip
+ \vskip -\topskip
+ % Ignore footnotes.
+ % Ignore bottom style.
+ % Ignore bottom floats.
+ % Don't produce text area bottom rule.
+ }}
+
+% Page Makeup: Page
+% ---- ------- ----
+
+
+\def \zpagecontents {%
+ \tracepagemakeup{Shipping out the final page.}%
+ \shipout \vbox to \trimheight {%
+ \parskip = 0pt \parindent = 0pt
+ \setindentation{0pt}{0pt}%
+ \zpageheadmargin
+ \nointerlineskip
+ \zpagetypearea
+ \vfil
+ \nointerlineskip
+ \zpageoverlay}%
+ \if \posp{\zortahcount}% % If overriding text area height:
+ \global\decrement \zortahcount
+ \if \zerop{\zortahcount}\zresetortah \fi
+ \fi
+ \tcounta = \pagenumber \increment \tcounta
+ \setpagenumber{\tcounta}%
+ \global\vsize = \textareaheight % In case it was reset for this page.
+ \znextpagerunners}
+
+\def \zpagelengthmarks {%
+ \tdimena = \headmargin
+ \advance \tdimena by \typeareaheight
+ \advance \tdimena by -\footerheight
+ \vskip \tdimena
+ \vbox to 0pt{%
+ \hbox to \trimwidth{%
+ \llap{\vrule height .5pt width .75pc}\hfil
+ \rlap{\vrule height .5pt width .75pc}}%
+ \vss}
+ \vskip -\tdimena
+ \nointerlineskip}
+
+\setflag \inbackground = \false
+
+\def \zpageheadmargin {%
+ \vbox to \headmargin {%
+ \hrule height 0pt width \trimwidth
+ \nointerlineskip
+ \smashbox{%
+ \setflag \inbackground = \true
+ \zcurback}%
+ \nointerlineskip
+ \vfil
+ \zmakeuprule{\trimwidth}{.5pt}}}
+
+\def \zpagetypearea {%
+ \if \evenpagep
+ \negate \eveninnermargin
+ \advance \eveninnermargin by \trimwidth
+ \advance \eveninnermargin by -\evenlefttextmargin
+ \advance \eveninnermargin by -\textmeasure
+ \advance \eveninnermargin by -\evenrighttextmargin
+ \fi
+ \moveright \if \oddpagep \oddinnermargin \else \eveninnermargin \fi
+ \vbox to \typeareaheight {%
+ \zadjtitle = \zadjtitlemark % \adjusttitle should adjust mark.
+ \def \zadjloc {\mark}%
+ \zpageheader
+ \nointerlineskip
+ \ztextandmargins
+ \zmakeuprule{\typeareawidth}{.5pt}%
+ \vss % Allows text area height to vary.
+ \vbox to \footerheight{%
+ \vss
+ \zpagefooter}}}
+
+\def \zpageheader {%
+ \vbox to \headerheight {%
+ \hsize = \typeareawidth
+ \zoutputbeginblack
+ \zcurheader
+ \zoutputendblack
+ \vfil
+ \zmakeuprule{\typeareawidth}{.5pt}}}
+
+\def \ztextandmargins {%
+ \hbox to \typeareawidth {%
+ \if \notp{\zusetypewidth}%
+ \hbox to \thislefttextmargin{\hss}%
+ \fi
+ \vbox{%
+ \boxmaxdepth = \maxdepth
+ \if \andp{\zusetypewidth}{\notp{\zonetontype}}%
+ \moveright \thislefttextmargin
+ \fi
+ \box\zonetonbox
+ \nointerlineskip
+ \vbox{\box\zbodybox}}%
+ \hss}}
+
+\def \zpagefooter {%
+ \hsize = \typeareawidth
+ \zoutputbeginblack
+ \zcurfooter
+ \zoutputendblack
+ \if \PDFhyperlinks \PDFmark{P:\folio}\fi}
+
+% This macro invokes the page overlay after positioning to the
+% upper-left corner of the trim.
+
+\def \zpageoverlay {%
+ \vbox to 0pt{%
+ \offinterlineskip
+ \kern -\trimheight
+ \name{\pageoverlay\the\zoverlay}%
+ \vss}}
+
+\def \zmakeuprule #1#2{% {width}{height}
+ \if \DVIWindoinuse
+ \colorspecial{ifview color push rgb 0 1 0}%
+ \tdimena = #1\tcounta = \tdimena
+ \tdimena = #2\tcountb = \tdimena
+ \special{viewrule: \the\tcounta\space \the\tcountb}%
+ \colorspecial{ifview color pop}%
+ \fi}
diff --git a/macros/plain/contrib/zztex/tex/zzplain.tex b/macros/plain/contrib/zztex/tex/zzplain.tex
new file mode 100644
index 0000000000..a24aa80139
--- /dev/null
+++ b/macros/plain/contrib/zztex/tex/zzplain.tex
@@ -0,0 +1,71 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%
+% Module: ZzTeX Plain TeX Compatibility
+%
+% Synopsis: This module contains definitions necessary for
+% compatibility with Plain TeX. The only goal is to
+% allow ZzTeX to run on top of Plain TeX.
+%
+% Author: Paul C. Anagnostopoulos
+% Created: 24 July 1991
+%
+% Copyright 1989--2020 by Paul C. Anagnostopoulos
+% under The MIT License (opensource.org/licenses/MIT)
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\if \definedp{\dospecials}
+ \let \znext = \relax
+\else
+ \let \znext = \endinput
+\fi
+\znext
+
+\def \zplainerror {%
+ \error{plaintex}{Cannot use this Plain TeX feature in ZzTeX}}
+
+% Definitions
+% -----------
+
+
+\catcode`\@ = \catletter
+\zremovePlaindef \p@
+\definedimen{\p@}{1pt}
+\zremovePlaindef \z@
+\definedimen{\z@}{0pt}
+\zremovePlaindef \z@skip
+\defineskip{\z@skip}{0pt plus 0pt minus 0pt}
+\catcode`\@ = \catactive
+
+\let \beginsection = \zplainerror
+
+\let \bye = \zplainerror
+
+\let \eject = \zplainerror
+
+\let \leavevmode = \ensurepar
+
+\let \normalbottom = \zplainerror
+
+\let \raggedright = \zplainerror
+
+\let \supereject = \zplainerror
+
+\let \ttraggedright = \zplainerror
+
+% Eliminate Fonts
+% --------- -----
+
+ \tcounta = 0
+ \loop
+ \zclearfam{\tcounta}%
+ \increment \tcounta
+ \if \lssp{\tcounta}{16}\repeat
+
+ \let \rm = \relax
+ \let \mit = \relax
+ \let \it = \relax
+ \let \sl = \undefined \let \slfam = \undefined
+ \let \bf = \relax
+ \let \tt = \relax
diff --git a/macros/plain/contrib/zztex/tex/zzprog.tex b/macros/plain/contrib/zztex/tex/zzprog.tex
new file mode 100644
index 0000000000..10b655bf0c
--- /dev/null
+++ b/macros/plain/contrib/zztex/tex/zzprog.tex
@@ -0,0 +1,228 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% Module: ZZTeX Programming Constructs
+%
+% Synopsis: This module contains definitions for ZZTeX's programming
+% constructs. These constructs provide various extensions
+% to TeX's sometimes meager repertoire of programming
+% features.
+%
+% Author: Paul C. Anagnostopoulos
+% Created: 27 March 1989
+%
+% Copyright 1989--2020 by Paul C. Anagnostopoulos
+% under The MIT License (opensource.org/licenses/MIT)
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% Token Hackery
+% ----- -------
+
+
+% We need a name for a space token.
+
+\def \\{\let \zspacetoken = } \\ % Now \zspacetoken is a space token.
+
+% This macro discards the next token.
+
+\def \discardtok #1{}% token
+
+% This macro removes the `pt' following a dimension.
+
+{\catcode `\p = \catother \catcode `\t = \catother
+
+\gdef \zremovedu #1pt{#1}
+
+} % \catcode
+
+% Using that macro, we can define a macro that "converts" a dimen register
+% into a factor.
+
+\def \thefactor #1{\expandafter\zremovedu \the#1}
+
+% This macro extracts the contents of a macro and returns it as plain text.
+% Usage: \expandafter\zdefof \meaning\macro\zmark
+
+\def \zdefof #1:->#2\zmark{#2}
+
+% Control Sequence Names
+% ------- -------- -----
+
+
+\def \name #1{% {\tokens}
+ \csname \expandafter\discardtok \string#1\endcsname}
+
+\def \withname #1#2{% {\command}{\tokens}
+ \expandafter#1\csname \expandafter\discardtok \string#2\endcsname}
+
+% Macro Expansion
+% ----- ---------
+
+
+\def \expandaftertwice {\expandafter\expandafter\expandafter}
+\def \expandafterthrice {\expandafter\expandafter\expandafter\expandafter
+ \expandafter\expandafter\expandafter}
+
+\def \zoneoftwo #1#2{#1}% {first}{second}
+\def \ztwooftwo #1#2{#2}% {first}{second}
+
+\def \zoneofthree #1#2#3{#1}% {first}{second}{third}
+\def \ztwoofthree #1#2#3{#2}% {first}{second}{third}
+\def \zthreeofthree #1#2#3{#3}% {first}{second}{third}
+
+\def \zoneoffour #1#2#3#4{#1}% {first}{second}{third}{fourth}
+\def \ztwooffour #1#2#3#4{#2}% {first}{second}{third}{fourth}
+\def \zthreeoffour #1#2#3#4{#3}% {first}{second}{third}{fourth}
+\def \zfouroffour #1#2#3#4{#4}% {first}{second}{third}{fourth}
+
+% Flags (Booleans)
+% ----- ----------
+
+% The boolean literals \true and \false are appropriate for use with
+% the \if command, which tests the codes of the next two characters.
+
+\def \true {TT}
+\def \false {FL}
+
+\def \setflag #1=#2{\edef #1{#2}}% \flag = boolean
+
+% IF and Predicates
+% -- --- ----------
+
+% A "predicate" is a macro that returns \true or \false as its value.
+% Such values are suitable for use with the \if conditional. For example:
+%
+% \if \oddp{\x} <then-clause> \else <else-clause> \fi
+
+% A predicate can be used with \setflag as follows:
+%
+% \setflag \flag = {<predicate>}
+
+% Here are the predicates for TeX's repertoire of conditional
+% commands. These might be more appropriately interspersed with
+% other definitions in this module, but what the heck.
+% Some additional "obvious" predicates are defined.
+
+
+\def \eqlp #1#2{\ifnum #1 = #2\true \else \false \fi}
+\def \neqlp #1#2{\ifnum #1 = #2\false \else \true \fi}
+\def \lssp #1#2{\ifnum #1 < #2\true \else \false \fi}
+\def \gtrp #1#2{\ifnum #1 > #2\true \else \false \fi}
+\def \zerop #1{\ifnum #1 = 0\true \else \false \fi}
+\def \onep #1{\ifnum #1 = 1\true \else \false \fi}
+\def \posp #1{\ifnum #1 > 0\true \else \false \fi}
+\def \negp #1{\ifnum #1 < 0\true \else \false \fi}
+\def \oddp #1{\ifodd #1\true \else \false \fi}
+\def \evenp #1{\ifodd #1\false \else \true \fi}
+\def \rangep #1#2#3{\if \orp{\lssp{#1}{#2}}{\gtrp{#1}{#3}}\false \else
+ \true \fi}
+\def \tensp #1{\rangep{#1}{10}{19}}
+
+\def \dimeqlp #1#2{\ifdim #1 = #2\true \else \false \fi}
+\def \dimneqlp #1#2{\ifdim #1 = #2\false \else \true \fi}
+\def \dimlssp #1#2{\ifdim #1 < #2\true \else \false \fi}
+\def \dimgtrp #1#2{\ifdim #1 > #2\true \else \false \fi}
+\def \dimzerop #1{\ifdim #1 = 0pt\true \else \false \fi}
+\def \dimposp #1{\ifdim #1 > 0pt\true \else \false \fi}
+\def \dimnegp #1{\ifdim #1 < 0pt\true \else \false \fi}
+
+\def \vmodep {\ifvmode \true \else \false \fi}
+\def \hmodep {\ifhmode \true \else \false \fi}
+\def \mathmodep {\ifmmode \true \else \false \fi}
+\def \textmodep {\ifmmode \false \else \true \fi}
+\def \innermodep {\ifinner \true \else \false \fi}
+
+\long\def \codeeqlp #1#2{\if #1#2\true \else \false \fi}
+
+\long\def \cateqlp #1#2{\ifcat #1#2\true \else \false \fi}
+
+\long\def \tokeqlp #1#2{\ifx #1#2\true \else \false \fi}
+\long\def \xtokeqlp #1#2{\expandafter\ifx #1#2\true \else \false \fi}
+
+\long\def \definedp #1{%
+ \expandafter\ifx \csname \expandafter\discardtok \string#1\endcsname
+ \relax \false \else \true \fi}
+
+\long\def \undefinedp #1{%
+ \expandafter\ifx \csname \expandafter\discardtok \string#1\endcsname
+ \relax \true \else \false \fi}
+\def \zempty {}
+\def \emptydefp #1{\ifx #1\zempty \true \else \false \fi}% {\name}
+
+\let \emptylistp = \emptydefp
+
+\long\def \emptyargp #1{% {#n}
+ \zempargp #1\zempargq\zmark}
+\long\def \zempargp #1#2\zmark{%
+ \ifx #1\zempargq \true \else \false \fi}
+\def \zempargq {\zempargq}
+
+\def \emptytoksp #1{% {\tokenreg}
+ \expandafter\zemptoksp \the#1\zmark}
+
+\long\def \zemptoksp #1\zmark{\emptyargp{#1}}
+
+\def \voidboxp #1{\ifvoid #1\true \else \false \fi}
+\def \hboxp #1{\ifhbox #1\true \else \false \fi}
+\def \vboxp #1{\ifvbox #1\true \else \false \fi}
+
+\def \eofp #1{\ifeof #1\true \else \false \fi}
+
+
+% Flags can also be used as predicates, as in:
+%
+% \if \flaga <then-clause> \else <else-clause> \fi
+
+
+% Now here we have predicates for the common logical operators.
+
+\def \notp #1{\if #1\false \else \true \fi}
+
+\def \andp #1#2{\if #1#2\else \false \fi}% {boolean1}{boolean2}
+
+\def \orp #1#2{\if #1\true \else #2\fi}% {boolean1}{boolean2}
+
+% Pseudo-Predicates
+% -----------------
+
+
+\def \stringeql #1#2#3{% {\return-flag}{string1}{string2}
+ \edef \zstra {#2}%
+ \edef \zstrb {#3}%
+ \edef #1{\ifx \zstra\zstrb \true \else \false \fi}}
+
+
+\def \gluevaries #1#2{% {\return-flag}{glue}
+ \zskipa = #2\relax
+ \tdimena = \zskipa
+ \stringeql{#1}{\the\zskipa}{\the\tdimena}%
+ \edef #1{\if #1\false \else \true \fi}}
+
+% Arithmetic
+% ----------
+
+
+\def \negate #1{\multiply #1 by -1\relax}% {\register}
+
+\def \increment #1{\advance #1 by 1\relax}% {\count}
+
+\def \decrement #1{\advance #1 by -1\relax}% {\count}
+
+% Looping
+% -------
+
+
+\def \loop #1\repeat{% body [actions] \if condition [actions] \repeat
+ \def \zloopbody {#1}%
+ \zloop}
+
+\def \zloop {%
+ \zloopbody
+ %\if condition
+ \let \zloopnext = \zloop
+ \else
+ \let \zloopnext = \relax
+ \fi
+ \zloopnext}
+
+\let \repeat = \fi \ No newline at end of file
diff --git a/macros/plain/contrib/zztex/tex/zzps.tex b/macros/plain/contrib/zztex/tex/zzps.tex
new file mode 100644
index 0000000000..f90d6e7ab9
--- /dev/null
+++ b/macros/plain/contrib/zztex/tex/zzps.tex
@@ -0,0 +1,251 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% Module: ZzTeX PostScript Facilities
+%
+% Synopsis: This module contains any and all facilities that rely on
+% PostScript output.
+%
+% Author: Paul C. Anagnostopoulos
+% Created: 21 January 1994
+%
+% Copyright 1989--2020 by Paul C. Anagnostopoulos
+% under The MIT License (opensource.org/licenses/MIT)
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% Extra Encoded Characters
+% ----- ------- ----------
+
+
+\def \PSbackslash {\char 134\relax}
+\def \PSbar {\char 138\relax}
+\def \PSbullet {\char 142\relax}
+\def \PSbraceleft {\char 137\relax}
+\def \PSbraceright {\char 139\relax}
+\def \PScent {\char 148\relax}
+\def \PScopyright {\char 145\relax}
+\def \PScurrency {\char 149\relax}
+\def \PSdagger {\char 140\relax}
+\def \PSddagger {\char 141\relax}
+\def \PSdollar {\char 131\relax}
+\def \PSgreater {\char 133\relax}
+\def \PSless {\char 132\relax}
+\def \PSordfeminine {\char 155\relax}
+\def \PSordmasculine {\char 156\relax}
+\def \PSparagraph {\char 143\relax}
+\def \PSperthousand {\char 157\relax}
+\def \PSpolishL {\char "A1\relax}
+\def \PSpolishl {\char "A2\relax}
+\def \PSregistered {\char 146\relax}
+\def \PSsection {\char 144\relax}
+\def \PSsterling {\char 158\relax}
+\def \PStrademark {\char 147\relax}
+\def \PSunderscore {\char 136\relax}
+\def \PSudquote {\char 135\relax}
+\def \PSusquote {\char 160\relax}
+\def \PSyen {\char 159\relax}
+
+% Import EPS File
+% ------ --- ----
+
+
+% The illustration \special is compatible with DVIPSONE, and with TeXtures
+% if clip? is false.
+% The scale is interpreted as follows:
+% <= 33.333: normal scale, 1.0 = 100%
+% > 33.333: TeX scale factor, 1000 = 100%
+
+\def \specialimportartfile #1#2#3{% {name}{scale}{clip?}
+ \special{illustration #1 scaled #2
+ \if #3clip\fi}}
+
+% This macro is a better variant of the preceding one. The scale
+% argument is a true scale specified in points.
+
+\def \specialplaceepsfile #1#2#3{% {name}{scale}{clip?}
+ {\tdimena = #2%
+ \if \dimgtrp{\tdimena}{33.333pt}% % Compensate for bizarre
+ \multiply \tdimena by 1000\relax % design of scaled option.
+ \fi
+ \special{illustration #1 scaled \thefactor\tdimena
+ \if #3\space clip\fi}}}
+
+% This macro is used to import an EPS file for a glyph. The scale
+% is specified as a percentage IN POINTS.
+
+\def \specialplaceglyph #1#2#3{% {name}{percentage}{clip?}
+ {\tdimena = #2%
+ \divide \tdimena by 100
+ \special{illustration #1 scaled \thefactor\tdimena
+ \if #3\space clip\fi}}}
+
+% Read EPS Bounding Box
+% ---- --- -------- ---
+
+
+\definedimen{\zbbxorigin}{0pt}
+\definedimen{\zbbyorigin}{0pt}
+
+
+{\catcode`\%=\catother
+\gdef \zpercent {%}
+} % \catcode
+
+\edef \zboundingbox {\zpercent\zpercent BoundingBox}
+\def \zatend {atend}
+\definecount{\zbbstate}{0}
+
+
+\def \zreadepsbb #1#2#3{% {\width}{\height}{file}
+ \def \zbbinfo {}%
+ \begingroup
+ \zsetepscatcodes
+ \openin \zreada #3\relax
+ \zbbstate = 0
+ \loop
+ \read \zreada to \zline
+ \ifeof \zreada
+ \zbbstate = 2
+ \else
+ \expandafter\zcheckbb \zline:.\zmark
+ \fi
+ \ifnum \zbbstate < 2 \repeat
+ \closein \zreada
+ \endgroup
+ \zsetbbsizes{#1}{#2}{#3}}
+
+\def \zsetepscatcodes {%
+ \catcoderange{0}{"1F}{\catcomment}%
+ \catcode `\^^I = \catspace
+ \catcode \endlinechar = \catendofline
+ \uncatcode{\false}{\false}{\false}%
+ \catcode `\: = \catother
+ \catcoderange{"7E}{"FF}{\catcomment}}
+
+\long \def \zcheckbb #1:#2#3\zmark{%
+ \def \znext {#1}%
+ \ifx \znext \zboundingbox
+ \zcheckatend #2#3()\zmark
+ \fi}
+
+\long \def \zcheckatend #1(#2)#3\zmark{%
+ \def \znext {#2}%
+ \ifx \znext \zatend
+ \zbbstate = 1
+ \else
+ \gdef \zbbinfo {#1}%
+ \ifnum \zbbstate = 0 \zbbstate = 2\fi
+ \fi}
+
+\def \zsetbbsizes #1#2#3{%
+ \if \emptydefp{\zbbinfo}%
+ \warning{missbb}{Art file `#3' has no bounding box}%
+ #1 = 20pc #2 = 10pc
+ \else
+ \expandafter \zcalcbb \zbbinfo \zmark{#1}{#2}%
+ \fi}
+
+\def \zcalcbb #1 #2 #3 #4 #5\zmark#6#7{%
+ \calculate #6= {#3pt,-,#1pt,+,1pt}%
+ \calculate #7= {#4pt,-,#2pt,+,1pt}%
+ \global\zbbxorigin = #1pt
+ \global\zbbyorigin = #2pt\relax}
+
+% Rotate Boxes
+% ------ -----
+
+
+\def \rotatebox #1#2{% {\box}{degrees}
+ \special{CTM: push rotate #2}%
+ \box #1%
+ \special{CTM: pop}}
+
+\def \rotatetext #1#2{% {text}{degrees}
+ \setbox \zboxa = \hbox{#1}%
+ \rotatebox{\zboxa}{#2}}
+
+% Colors
+% ------
+
+
+\def \colorspecial #1{%
+ \if \allowcolor
+ \special{#1}%
+ \fi}
+
+% These commands are called in the output routine to make sure that
+% everything added in the output routine is black.
+
+\def \zoutputbeginblack {%
+ \colorspecial{color push gray 0}}
+
+\def \zoutputendblack {%
+ \colorspecial{color pop}}
+
+% Color Block
+% ---- ------
+
+
+\defineblock{\color}{\endcolor}{\false}{}
+
+%~block color Type
+% \colorspec = {...} % Color specifier.
+%~end
+
+\definetoks{\colorspec}
+
+
+\def \color #1{% {type}
+ \beginblockscope{color}%
+ \global\increment \colordepth
+ \processdesign{\color}{#1}%
+ \global\increment \colornumber
+ \colorspecial{color push}%
+ \the\colorspec\zmark
+ \if \vmodep \vpenalty{\breaknever}\fi}
+
+\def \endcolor {%
+ \global\decrement \colordepth
+ \endblockscope{color}%
+ \colorspecial{color pop}}
+
+
+\def \setcolor #1{%
+ \begingroup
+ \processdesign{\color}{#1}%
+ \the\colorspec\zmark
+ \endgroup}
+
+% Color specifiers:
+
+\def \cmykcolor #1 #2 #3 #4\zmark{% c m y k\zmark
+ \colorspecial{color cmyk #1 #2 #3 #4}}
+
+\def \graycolor #1\zmark{% gray\zmark
+ \colorspecial{color gray #1}}
+
+\def \rgbcolor #1 #2 #3\zmark{% r g b\zmark
+ \colorspecial{color rgb #1 #2 #3}}
+
+% Built-in colors:
+
+\def \colorblackdesign {%
+ \colorspec = {\graycolor 0}}
+
+\def \colorwhitedesign {%
+ \colorspec = {\graycolor 1}}
+
+\def \colorproofnotereddesign {%
+ \colorspec = {\rgbcolor .5 0 0}}
+
+% A useful shorthand:
+
+\def \colortext #1#2{% {color}{text}
+ \color{#1}#2\endcolor}
+
+% TeXtures
+% --------
+
+
+\def \TeXtures {%
+ \input zztures\relax}
diff --git a/macros/plain/contrib/zztex/tex/zzreg.tex b/macros/plain/contrib/zztex/tex/zzreg.tex
new file mode 100644
index 0000000000..c50f9e74d8
--- /dev/null
+++ b/macros/plain/contrib/zztex/tex/zzreg.tex
@@ -0,0 +1,437 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% Module: ZzTeX Register Facilities
+%
+% Synopsis: This module provides facilities for defining and manipulating
+% TeX registers.
+%
+% Author: Paul C. Anagnostopoulos
+% Created: 13 August 1989
+%
+% Copyright 1989--2020 by Paul C. Anagnostopoulos
+% under The MIT License (opensource.org/licenses/MIT)
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% Register Definition
+% -------- ----------
+
+
+% The following constant specifies the number of the first insert register
+% set. Such a set is composed of a count, dimen, skip, and box.
+
+\chardef \zfirstinsert = 245
+
+% Establish counters to keep track of the most recently allocated
+% registers. The registers are initialized to the first available
+% register.
+
+\count10 = 20 % Count registers.
+\count11 = 0 % Dimen registers.
+\count12 = 0 % Skip registers.
+\count13 = 0 % Muskip registers.
+\count14 = 1 % Box registers (Plain TeX uses box 0).
+\count15 = 0 % Toks registers.
+\count16 = 0 % Read streams.
+\count17 = 0 % Write streams.
+\count18 = 0 % Math families.
+\count19 = \zfirstinsert % Insertion register sets.
+
+
+% There is one macro for each type of register, used to allocate one.
+
+\def \definecount #1#2{% {\name}{initial}
+ \zalloc{\count}{10}{\zfirstinsert}{\countdef}{#1}%
+ #1 = #2}
+
+\def \definedimen #1#2{% {\name}{initial}
+ \zalloc{\dimen}{11}{\zfirstinsert}{\dimendef}{#1}%
+ #1 = #2}
+
+\def \defineskip #1#2{% {\name}{initial}
+ \zalloc{\skip}{12}{\zfirstinsert}{\skipdef}{#1}%
+ #1 = #2}
+
+\def \definemuskip #1#2{% {\name}{initial}
+ \zalloc{\muskip}{13}{255}{\muskipdef}{#1}% Muskip 255 is scratch.
+ #1 = #2}
+
+\def \definebox #1{% {\name}
+ \zalloc{\box}{14}{\zfirstinsert}{\chardef}{#1}}
+
+\def \definetoks #1{% {\name}
+ \zalloc{\toks}{15}{256}{\toksdef}{#1}%
+ #1 = {}}
+
+\def \defineread #1{% {\name}
+ \zalloc{\read}{16}{16}{\chardef}{#1}}
+
+\def \definewrite #1{% {\name}
+ \zalloc{\write}{17}{16}{\chardef}{#1}}
+
+% Families are not defined directly by the user, but via \definetypestyle.
+
+\def \zdeffam #1{% {\name}
+ \if \lssp{\count18}{15}%
+ \zalloc{\fam}{18}{16}{\chardef}{#1}%
+ \else
+ \global\chardef #1=\count18
+ \fi}
+
+\def \defineinsert #1{% {\name}
+ \zalloc{\insert}{19}{255}{\chardef}{#1}} % Registers 255 are scratch.
+
+
+\def \zalloc #1#2#3#4#5{% {type}{counter}{limit}{\def-er}{\name}
+ \if \eqlp{\count#2}{#3}%
+ \error{noregsleft}{All `\string#1' registers have been allocated}%
+ \fi
+ \if \definedp{#5}%
+ \error{dupreg}{The register `\string#5' is already defined}%
+ \fi
+ \global#4 #5=\count#2
+ \global\increment {\count#2}}
+
+% Register Statistics
+% -------- ----------
+
+
+{\catcode`\_ = \catactive
+
+\gdef \zregstats {%
+ {\def _{\space}%
+ \writelog{}%
+ \writelog{Register Statistics:}%
+ \writelog{}%
+ \writelog{Type_____Used / Total}%
+ \writelog{----_____------------}%
+ \zrsone{Count_}{10}{\zfirstinsert}{}%
+ \zrsone{Dimen_}{11}{\zfirstinsert}{}%
+ \zrsone{Skip__}{12}{\zfirstinsert}{}%
+ \zrsone{Muskip}{13}{255}{}%
+ \zrsone{Box___}{14}{\zfirstinsert}{}%
+ \zrsone{Toks__}{15}{256}{}%
+ \zrsone{Read__}{16}{16}{}%
+ \zrsone{Write_}{17}{16}{}%
+ \zrsone{Family}{18}{256}{(15 for math)}%
+ \zrsone{Insert}{19}{255}{(starts at \the\zfirstinsert)}%
+ \writelog{}}}
+
+\gdef \zrsone #1#2#3#4{% {name}{counter}{ex-limit}{comment}
+ \tcounta = #3
+ \advance \tcounta by -1
+ \writelog{#1___\the\count#2 _/_\the\tcounta_#4}}
+
+} % \catcode
+
+% Constant Registers
+% -------- ---------
+
+
+\definecount{\maxcount}{2147483647}
+\definecount{\mincount}{-\maxcount}
+\zremovePlaindef \maxdimen
+\definedimen{\maxdimen}{16383.99999pt}
+\definedimen{\mindimen}{-\maxdimen}
+\definedimen{\naturalwidth}{\mindimen}
+
+\defineskip{\centerindent}{0pt plus 10000pt}
+\let \centering = \centerindent
+
+\defineskip{\normalparfillskip}{0pt plus 1fil}
+
+\definebox{\voidbox} % Permanently void box register.
+
+% Temporary Internal Registers
+% --------- -------- ---------
+
+
+\definecount{\tcounta}{0}
+\definecount{\tcountb}{0}
+\definecount{\tcountc}{0}
+
+\definedimen{\tdimena}{0pt}
+\definedimen{\tdimenb}{0pt}
+\definedimen{\tdimenc}{0pt}
+\definedimen{\tdimend}{0pt}
+
+\defineskip{\zskipa}{0pt}
+\defineskip{\zskipb}{0pt}
+\defineskip{\zskipc}{0pt}
+
+\definemuskip{\zmuskipa}{0mu}
+\definemuskip{\zmuskipb}{0mu}
+\definemuskip{\zmuskipc}{0mu}
+
+\definebox{\zboxa}
+\definebox{\zboxb}
+\definebox{\zboxc}
+
+\definetoks{\ztoksa}
+\definetoks{\ztoksb}
+\definetoks{\ztoksc}
+
+\defineread{\zreada}
+
+\definewrite{\zwritea}
+
+% Manipulating Boxes
+% ------------ -----
+
+
+\def \shiftboxbaseline #1#2{% {\box}{amount}
+ {\tdimena = #2%
+ \tdimenb = \ht#1%
+ \advance \tdimenb by \tdimena
+ \ht#1= \tdimenb
+ \tdimenb = \dp#1%
+ \advance \tdimenb by -\tdimena
+ \dp#1= \tdimenb}}
+
+% Lists
+% -----
+
+
+% These macros support the manipulation of lists in the following format:
+%
+% \:{<element-0>}\:{<element-1>}\: ...
+%
+% All lists are global!
+
+% We need two toks registers, which will be used just for lists.
+
+\definetoks{\zlta}
+\definetoks{\zltb}
+
+
+\def \setlist #1=#2{% \listname = {value}
+ \zlta = \expandafter{#2}%
+ \xdef #1{\the\zlta}}
+
+\long\def \append #1#2{% {item}{\list-name}
+ {\zlta = {\:{#1}}%
+ \zltb = \expandafter{#2}%
+ \xdef #2{\the\zltb\the\zlta}}}
+
+\long\def \appendlf #1#2{% {\list-name}{item}
+ {\zlta = {\:{#2}}%
+ \zltb = \expandafter{#1}%
+ \xdef #1{\the\zltb\the\zlta}}}
+
+\long\def \prepend #1#2{% {item}{\list-name}
+ {\zlta = {\:{#1}}%
+ \zltb = \expandafter{#2}%
+ \xdef #2{\the\zlta\the\zltb}}}
+
+\let \push = \prepend
+
+\def \pop #1#2{% {\return-macro}{\list-name}
+ \expandafter\zpop #2\zmark#1#2}
+
+\long\def \zpop \:#1#2\zmark#3#4{%
+ \def #3{#1}%
+ \gdef #4{#2}}
+
+\def \listtop #1#2{% {\return-macro}{\list-name}
+ \expandafter\zlisttop #2\zmark#1}
+
+\long\def \zlisttop \:#1#2\zmark#3{%
+ \def #3{#1}}
+
+\definecount{\zmapldepth}{0}
+
+\def \maplist #1#2{% {body}{\listname}
+ \increment \zmapldepth
+ \withname\let{\zmapl\romannumeral\zmapldepth}=\:%
+ \long\def \:##1{#1}%
+ #2%
+ \expandafter\let
+ \expandafter\:\csname zmapl\romannumeral\zmapldepth\endcsname
+ \decrement \zmapldepth}
+
+\def \maplistlf #1#2{% {\listname}{body}
+ \increment \zmapldepth
+ \withname\let{\zmapl\romannumeral\zmapldepth}=\:%
+ \long\def \:##1{#2}%
+ #1%
+ \expandafter\let
+ \expandafter\:\csname zmapl\romannumeral\zmapldepth\endcsname
+ \decrement \zmapldepth}
+
+\def \exitmaplist {\def \:##1{}}
+
+\def \listlength #1#2{% {\result-count}{\list}
+ #1= 0
+ \maplist{\increment #1}{#2}}
+
+\def \member #1#2#3{% {\result-flag}{item}{\list}
+ \setflag #1= \false
+ \maplist{\stringeql{#1}{##1}{#2}\if #1\exitmaplist \fi}
+ {#3}}
+
+\def \commalist #1#2{% {\result-name}{comma-list}
+ \setlist #1={}%
+ \expandafter\zcomma #2,\zmark#1}
+
+\def \zcomma #1,#2\zmark#3{%
+ \if \notp{\emptyargp{#1}}\append{#1}{#3}\fi
+ \if \notp{\emptyargp{#2}}%
+ \def \znext {\zcomma #2\zmark#3}%
+ \else
+ \let \znext = \relax
+ \fi
+ \znext}
+
+\def \inclusionlist #1#2#3{% {\result}{item}{inclusion-list}
+ \zincla {#1}{#2}#3\zmark}
+
+\let \all = \relax
+\let \allbut = \relax
+\def \zallname {\all}
+\def \zallbutname {\allbut}
+
+\def \zincla #1#2#3#4\zmark{% {\result}{item}{token1}{tokens...}
+ \def \znext {#3}%
+ \if \tokeqlp{\znext}{\zallname}%
+ \setflag #1= \true
+ \else \if \tokeqlp{\znext}{\zallbutname}%
+ \commalist{\zincllist}{#4}%
+ \member{#1}{#2}{\zincllist}%
+ \setflag #1= {\notp{#1}}%
+ \else
+ \commalist{\zincllist}{#3#4}%
+ \member{#1}{#2}{\zincllist}%
+ \fi\fi}
+
+% New Expression Evaluation
+% --- ---------- ----------
+
+
+% These macros provide a rudimentary expression evaluation facility.
+% The accumulator can be a count, dimen, or skip register. The expression
+% is in the form {operand0,op1,operand1,op2,operand2,...}.
+%
+% WARNING: The \register cannot be used in the expression except possibly
+% as the first operand.
+
+
+\definedimen{\zcalct}{0pt}
+
+
+\def \calculate #1=#2{% \register = {expression}
+ \let \zaccum = #1%
+ \zcalca =,#2,;,,\zmark}
+
+\def \gcalculate #1=#2{% \register = {expression}
+ \let \zaccum = #1%
+ \zcalca =,#2,;,,\zmark
+ \global \zaccum = \zaccum}
+
+\def \zcalca #1,#2,#3\zmark{%
+ \def \znext{\zcalca #3\zmark}%
+ \if #1=\zaccum = #2% % Assignment
+ \else\if #1+\advance \zaccum #2% % Addition
+ \else\if #1-\advance \zaccum -#2% % Subtraction
+ \else\if #1*\multiply \zaccum #2% % Multiplication
+ \else\if #1/\divide \zaccum #2% % Division
+ \else\if #1N\if \dimlssp{#2}{\zaccum}\zaccum = #2\fi % Minimum
+ \else\if #1P\divide \zaccum 100 % Percentage
+ \expandafter\zaccum #2\zaccum
+ \else\if #1R\zcalct = #2% % Ratio
+ \divide \zcalct by 4096
+ \divide \zaccum by \zcalct
+ \multiply \zaccum by 16\relax
+ \else\if #1S\zaccum = \thefactor#2\zaccum % Scale
+ \else\if #1X\if \dimgtrp{#2}{\zaccum}\zaccum = #2\fi % Maximum
+ \else\if #1;\let \znext = \relax % Done
+ \else
+ \error{invoper}{Invalid operator `#1' in expression}%
+ \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi
+ \znext}
+
+% Calculating Values
+% ----------- ------
+
+%%%\defineskip{\zcaccum}{0pt}
+%%%\setflag \zexprpos = \true
+%%%
+%%%\def \calculate #1=#2{% {\reg} = {expression}
+%%% \commalist{\zexprlist}{#2}%
+%%% \zcaccum = 0pt
+%%% \def \zoper {+}%
+%%% \setflag \zexprpos = \true
+%%% \maplist{\zcalc{##1}}{\zexprlist}%
+%%% #1=\zcaccum}
+%%%
+%%%\def \gcalculate #1=#2{% {\reg} = {expression}
+%%% \commalist{\zexprlist}{#2}%
+%%% \zcaccum = 0pt
+%%% \def \zoper {+}%
+%%% \setflag \zexprpos = \true
+%%% \maplist{\zcalc{##1}}{\zexprlist}%
+%%% \global #1=\zcaccum}
+%%%
+%%%\def \zcalc #1{% {token}
+%%% \if \zexprpos
+%%% \zcalcb{#1}%
+%%% \setflag \zexprpos = \false
+%%% \else
+%%% \def \zoper {#1}%
+%%% \setflag \zexprpos = \true
+%%% \fi}
+%%%
+%%%\def \zcalcb #1{% {operand}
+%%% \if \codeeqlp{\zoper}{+}% % Add.
+%%% \advance \zcaccum by #1%
+%%% \else\if \codeeqlp{\zoper}{-}% % Subtract.
+%%% \advance \zcaccum by -#1%
+%%% \else\if \codeeqlp{\zoper}{*}% % Multiply.
+%%% \multiply \zcaccum by #1%
+%%% \else\if \codeeqlp{\zoper}{/}% % Divide.
+%%% \divide \zcaccum by #1%
+%%% \else\if \codeeqlp{\zoper}{P}%
+%%% \divide \zcaccum by 100
+%%% \expandafter \zcaccum #1\zcaccum
+%%% \else\if \codeeqlp{\zoper}{R}% % Compute ratio (in points).
+%%% \zcalct = #1%
+%%% \divide \zcalct by 4096
+%%% \divide \zcaccum by \zcalct
+%%% \multiply \zcaccum by 16\relax
+%%% \else\if \codeeqlp{\zoper}{S}% % Scale (in points).
+%%% \zcaccum = \thefactor#1\zcaccum
+%%% \else
+%%% \error{invoper}{Invalid operator `\zoper' in expression}%
+%%% \fi\fi\fi\fi\fi\fi\fi}
+
+% The Vertical Context
+% --- -------- -------
+
+
+% This is in here because we need registers. Otherwise it would be
+% in ZZTEX.TEX
+
+
+\definecount{\zvcontextdepth}{0}
+
+\definetoks{\zeveryvcontext}
+\global\zeveryvcontext = {}
+
+
+\def \zdeclareeveryvcontext #1{%
+ \global\zeveryvcontext = \expandafter{\the\zeveryvcontext #1}}
+
+\def \zpushvcontext {%
+ \global\increment \zvcontextdepth
+ \withname\gdef{\zvcontextstack\romannumeral\zvcontextdepth}{}%
+ \the\zeveryvcontext}
+
+\def \zpopvcontext {%
+ {\globaldefs = 1\relax
+ \name{\zvcontextstack\romannumeral\zvcontextdepth}}%
+ \global\decrement \zvcontextdepth}
+
+\def \zsavevcontext #1{%
+ {\ztoksa = \expandafterthrice{%
+ \name{\zvcontextstack\romannumeral\zvcontextdepth}}%
+ \withname\xdef{\zvcontextstack\romannumeral\zvcontextdepth}%
+ {\the\ztoksa #1}}}
diff --git a/macros/plain/contrib/zztex/tex/zzrunner.tex b/macros/plain/contrib/zztex/tex/zzrunner.tex
new file mode 100644
index 0000000000..c0427cbddc
--- /dev/null
+++ b/macros/plain/contrib/zztex/tex/zzrunner.tex
@@ -0,0 +1,98 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% Module: ZzTeX New Running Head/Foot Scheme
+%
+% Synopsis: The new running head/foot scheme is an improvement over the
+% original scheme.
+%
+% Author: Paul C. Anagnostopoulos
+% Created: 26 November 1997
+%
+% Copyright 1989--2020 by Paul C. Anagnostopoulos
+% under The MIT License (opensource.org/licenses/MIT)
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% Data Structures
+% ---- ----------
+
+
+\def \zdefrun {normal}
+
+\setlist \zrunlist = {}
+
+\setflag \zoverrun = \false
+
+\def \zcurback {%
+ \if \definedp \backgroundnormalformat \backgroundnormalformat \fi}
+\def \zcurheader {\headernormalformat}
+\def \zcurfooter {\footernormalformat}
+
+% Specify Runners
+% ------- -------
+
+
+%~ This command discards any current runner styles and sets up to use style
+%~ *style1* on the current page, *style2* on the next, *style3* on the one after
+%~ that, and so forth. The last style specified is used as the style for all
+%~ subsequent pages (it becomes the default style). No spaces are allowed in the
+%~ list.
+
+\def \setrunners #1{% {style1,style2,style3,...} %^runners
+ {\if \zoverrun \pop{\zoverstyle}{\zrunlist}\fi
+ \commalist{\zrunlist}{#1}%
+ \maplist{\gdef \zdefrun {##1}}{\zrunlist}%
+ \if \zoverrun \expandafter\overriderunners\expandafter{\zoverstyle}\fi
+ \zsetcurrun}}
+
+%~ This command overrides the style for the current page, using style *style*
+%~ instead. After the current page, runner styles revert to those established
+%~ by the last |\setrunners| command.
+
+\def \overriderunners #1{% {style} %^runners
+ \if \notp{\emptylistp{\zrunlist}}%
+ \pop{\znext}{\zrunlist}%
+ \fi
+ \push{#1}{\zrunlist}%
+ \global\setflag \zoverrun = \true
+ \zsetcurrun}
+
+%~ This command is simply a shorthand for |\overriderunners{blind}|.
+
+\def \blindrunners {% %^runners
+ \overriderunners{blind}}
+
+% Internal Common Macros
+% -------- ------ ------
+
+
+\def \zsetrunnerstoks #1{% {\token-reg}
+ \expandafter\setrunners\expandafter{\the#1}}
+
+\def \zoverriderunnerstoks #1{% {\token-reg}
+ \expandafter\overriderunners\expandafter{\the#1}}
+
+\def \zoldrunners #1{}
+
+% Output Routine Interface
+% ------ ------- ---------
+
+
+\def \zsetcurrun {%
+ \if \emptylistp{\zrunlist}%
+ \edef \znext {\zdefrun}%
+ \else
+ \listtop{\znext}{\zrunlist}%
+ \fi
+ \ztoksa = \expandaftertwice{\name{\background\znext format}}%
+ \xdef \zcurback {%
+ \noexpand\if \noexpand\definedp\the\ztoksa \the\ztoksa \noexpand\fi}%
+ \ztoksa = \expandaftertwice{\name{\header\znext format}}%
+ \xdef \zcurheader {\the\ztoksa}%
+ \ztoksa = \expandaftertwice{\name{\footer\znext format}}%
+ \xdef \zcurfooter {\the\ztoksa}}
+
+\def \znextpagerunners {%
+ \if \notp{\emptylistp{\zrunlist}}\pop{\znext}{\zrunlist}\fi
+ \zsetcurrun
+ \global\setflag \zoverrun = \false}
diff --git a/macros/plain/contrib/zztex/tex/zzsect.tex b/macros/plain/contrib/zztex/tex/zzsect.tex
new file mode 100644
index 0000000000..280d2ecc5b
--- /dev/null
+++ b/macros/plain/contrib/zztex/tex/zzsect.tex
@@ -0,0 +1,806 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% Module: ZzTeX Sectioning Facilities
+%
+% Synopsis:
+%
+% Author: Paul C. Anagnostopoulos
+% Created: 25 August 1989
+%
+% Copyright 1989--2020 by Paul C. Anagnostopoulos
+% under The MIT License (opensource.org/licenses/MIT)
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% Part and Chapter Texts
+% ---- --- ------- -----
+
+
+\long\def \setauthortext #1{% {text} %^modifier
+ \with{\authortext = {#1}}}
+
+\long\def \setopenertext #1{% {text} %^modifier
+ \with{\openertext = {#1}}}
+
+% Part
+% ----
+
+
+\defineblock{\part}{\endpart}{\true}{}
+
+%~block part
+% \setflag \allowintoc = flag % Allow in ToC?
+% \authortext = {...} % Author needed for opener.
+% \def \comptextformat {...} % Composite number text formatter.
+% \def \paging {...} % Paging before part opener.
+% \def \partformat ##1{...} % Part page formatter.
+% \openertext = {...} % Special text needed for opener.
+% \def \providemark ##1{...} % Mark provider.
+% \resetnumber = {...} % List of numbers to reset.
+% \runners = {style,...} % Running head/foot styles.
+% \style = {...} % Heading style.
+%~end
+
+\def \part #1{% {title}
+ \closeanychapter
+ \beginblockscope{part}%
+ \global\increment \partdepth
+ \authortext = {}% %~default hard
+ \openertext = {}% %~default hard
+ \runners = {blind,normal}% %~default soft
+ \zoldrunners{\blindheader\blindfooter}%
+ \style = {Caps/lowercase, \noindent} %~default soft
+ \processdesign{\part}{}%
+ \global\increment \partnumber
+ \setcomptext{\partcomptext}%
+ \paging
+ \remark{Starting PART \number\partnumber.}%
+ % Next three things are done first, in case opener is more than one page.
+ \providemark{#1}%
+ \zpartchaptoc{\the\partcomptext}{#1}{80}%
+ \settaginfo{\the\partcomptext}{#1}
+ \zsetrunnerstoks{\runners}%
+ {\partformat{#1}}%
+ \endgraf}
+
+\def \endpart {%
+ \global\decrement \partdepth
+ \endblockscope{part}}
+
+\def \setpartnumber #1{% {number}
+ \global\partnumber = #1\relax
+ \global\decrement \partnumber}
+
+% Quasi-Part
+% ----------
+
+
+\defineblock{\quasipart}{\endquasipart}{\true}{}
+
+%~block quasipart
+% \setflag \allowintoc = flag % Allow in ToC?
+% \openertext = {...} % Special text needed for opener.
+% \def \paging {...} % Paging before part opener.
+% \def \quasipartformat ##1{...} % Part page formatter.
+% \def \providemark ##1{...} % Mark provider.
+% \resetnumber = {...} % List of numbers to reset.
+% \runners = {style,...} % Running head/foot styles.
+% \style = {...} % Heading style.
+%~end
+
+\def \quasipart #1{% {title}
+ \closeanychapter
+ \beginblockscope{quasipart}%
+ \global\increment \quasipartdepth
+ \openertext = {}% %~default hard
+ \runners = {blind,normal}% %~default soft
+ \zoldrunners{\blindheader\blindfooter}%
+ \style = {Caps/lowercase, \noindent}% %~default soft
+ \processdesign{\quasipart}{}%
+ \global\increment \quasipartnumber
+ \paging
+ \def \znext {#1}%
+ \remark{Starting QUASIPART `\expandafter\zdefof \meaning\znext\zmark'.}%
+ % Next three things are done first, in case opener is more than one page.
+ \providemark{#1}%
+ \zpartchaptoc{}{#1}{85}%
+ \settaginfo{}{#1}%
+ \zsetrunnerstoks{\runners}%
+ {\quasipartformat{#1}}%
+ \endgraf}
+%%% \endquasipart}
+
+\def \endquasipart {%
+ \global\decrement \quasipartdepth
+ \endblockscope{quasipart}}
+
+% Chapter
+% -------
+
+\defineblock{\chapter}{\endchapter}{\true}{}
+
+%~block chapter
+% \setflag \allowintoc = boolean % Allow in ToC?
+% \authorlevel = integer % Author ToC entry level.
+% \authortext = {...} % Author text needed for opener.
+% \def \comptextformat {...} % Composite number text formatter.
+% \difficulty = integer % Level of difficulty.
+% \numberfont = {...} % Font for number.
+% \numberwordfont = {...} % Font for word like "chapter".
+% \def \numberformat {...} % Number format.
+% \numbersink = glue % Sinkage to number, or
+% \numberskip = glue % Space b/b to number.
+% \openertext = {...} % Special text needed for opener.
+% \def \paging {...} % Initial paging.
+% \def \providemark ##1{...} % Mark provider.
+% \resetnumber = {...} % List of numbers to reset.
+% \setflag \resetsection = boolean % Reset section number?
+% \runners = {style,...} % Running head/foot styles.
+% \style = {...} % Heading style.
+% \textsink = sinkage % Sinkage to text, or
+% \textskip = skip % Space b/b from rule to text.
+% \titlefont = {...} % Title font.
+% \def \titleformat ##1{...} % Title format.
+% \titlesink = glue % Sinkage to title, or
+% \titleskip = glue % Space b/b from number to title.
+%~end
+
+\def \chapter #1{% {title}
+ \closeanychapter
+ \beginblockscope{chapter}%
+ \global\increment \chapterdepth
+ \authorlevel = 0 %~default hard
+ \authortext = {}% %~default hard
+ \difficulty = 0 %~default with
+ \openertext = {}% %~default hard
+ \setflag \resetsection = \true %~default hard
+ \runners = {chapter,normal}% %~default soft
+ \zoldrunners{\chapterheader\chapterfooter}%
+ \style = {Caps/lowercase, \noindent}% %~default soft
+ \processdesign{\chapter}{}%
+ \if \resetsection
+ \global\sectionnumber = 0
+ \global\quasisectionnumber = 0
+ \global\chapterappendixnumber = 0
+ \fi
+ \global\simpleheadnumber = 0
+ \global\increment \chapternumber
+ \setcomptext{\chaptercomptext}%
+ \paging
+ \remark{Starting chapter \if \emptytoksp{\chaptercomptext}'#1'\else
+ \the\chaptercomptext \fi.}%
+ \zsetrunnerstoks{\runners}%
+ \chapterformat{#1}%
+ \deferfloats{\true}%
+ \settaginfo{\the\chaptercomptext}{#1}}
+
+\def \endchapter {%
+ \closeanysection
+ \global\decrement \chapterdepth
+ \endblockscope{chapter}}
+
+\def \chapterformat #1{%
+ {\the\numberfont
+ \zsinkskip{\numbersink}{\breakbest}{\numberskip}%
+ \numberformat\par}%
+ {\the\titlefont
+ \zsinkskip{\titlesink}{\breaknever}{\titleskip}%
+ \titleformat{#1}\par}%
+ \providemark{#1}%
+ \zpartchaptoc{\the\chaptercomptext}{#1}{70}%
+ \zsinkskip{\textsink}{\breaknever}{\textskip}}
+
+\def \setchapternumber #1{% {number}
+ \global\chapternumber = #1\relax
+ \global\decrement \chapternumber}
+
+\def \setappendixnumber #1{% {number}
+ \global\appendixnumber = #1\relax
+ \global\decrement \appendixnumber}
+
+\def \setsectionnumber #1{% {number}
+ \global\sectionnumber = #1\relax
+ \global\decrement \sectionnumber}
+
+% Quasi-Chapter
+% -------------
+
+
+\defineblock{\quasichapter}{\endquasichapter}{\true}{}
+
+%~block quasichapter
+% \setflag \allowintoc = boolean % Allow in ToC?
+% \authorlevel = integer % Author ToC entry level.
+% \authortext = {...} % Author text needed for opener.
+% \openertext = {...} % Special text needed for opener.
+% \def \paging {...} % Initial paging.
+% \def \providemark ##1{...} % Mark provider.
+% \resetnumber = {...} % List of numbers to reset.
+% \runners = {style,...} % Running head/foot styles.
+% \style = {...} % Heading style.
+% \textsink = sinkage % Sinkage to text, or
+% \textskip = skip % Skip from rule to text.
+% \titlefont = {...} % Title font.
+% \def \titleformat ##1{...} % Title format.
+% \titlesink = glue % Sinkage to title, or
+% \titleskip = glue % Space b/b to title.
+%~end
+
+\def \quasichapter #1{% {title}
+ \closeanychapter
+ \beginblockscope{quasichapter}%
+ \global\increment \quasichapterdepth
+ \authorlevel = 0 %~default hard
+ \authortext = {}% %~default hard
+ \openertext = {}% %~default hard
+ \runners = {chapter,normal}% %~default soft
+ \zoldrunners{\chapterheader\chapterfooter}%
+ \style = {Caps/lowercase, \noindent}% %~default soft
+ \processdesign{\quasichapter}{}%
+ \global\increment \quasichapternumber
+ \chaptercomptext = {}%
+ \paging
+ \def \znext {#1}%
+ \remark{Starting quasichapter `\expandafter\zdefof \meaning\znext\zmark'.}%
+ \zsetrunnerstoks{\runners}%
+ \quasichapterformat{#1}%
+ \deferfloats{\true}%
+ \settaginfo{}{#1}}
+
+\def \endquasichapter {%
+ \closeanysection
+ \global\decrement \quasichapterdepth
+ \endblockscope{quasichapter}}
+
+\def \quasichapterformat #1{%
+ {\the\titlefont
+ \zsinkskip{\titlesink}{\breaknever}{\titleskip}%
+ \titleformat{#1}\par}
+ \providemark{#1}%
+ \zpartchaptoc{}{#1}{75}%
+ \zsinkskip{\textsink}{\breaknever}{\textskip}}
+
+% Appendix
+% --------
+
+
+\defineblock{\appendix}{\endappendix}{\true}{}
+
+%~block appendix
+% \setflag \allowintoc = boolean % Allow in ToC?
+% \authortext = {...} % Author text needed for opener.
+% \def \comptextformat {...} % Composite number text formatter.
+% \numberfont = {...} % Font for number.
+% \numberwordfont = {...} % Font for word like "appendix".
+% \def \numberformat {...} % Number format.
+% \numbersink = glue % Sinkage to number, or
+% \numberskip = glue % Space b/b to number.
+% \openertext = {...} % Special text needed for opener.
+% \def \paging {...} % Initial paging.
+% \def \providemark ##1{...} % Mark provider.
+% \resetnumber = {...} % List of numbers to reset.
+% \setflag \resetsection = boolean % Reset section number?
+% \runners = {style,...} % Running head/foot styles.
+% \style = {...} % Heading style.
+% \textsink = sinkage % Sinkage to text, or
+% \textskip = skip % Space b/b from rule to text.
+% \titlefont = {...} % Title font.
+% \def \titleformat ##1{...} % Title format.
+% \titlesink = glue % Sinkage to title, or
+% \titleskip = glue % Space b/b from number to title.
+%~end
+
+\def \appendix #1{% {title}
+ \closeanychapter
+ \beginblockscope{appendix}%
+ \global\increment \appendixdepth
+ \authortext = {}% %~default hard
+ \openertext = {}% %~default hard
+ \setflag \resetsection = \true %~default hard
+ \runners = {chapter,normal}% %~default soft
+ \zoldrunners{\chapterheader\chapterfooter}%
+ \style = {Caps/lowercase, \noindent}% %~default soft
+ \processdesign{\appendix}{}%
+ \if \resetsection
+ \global\sectionnumber = 0
+ \global\quasisectionnumber = 0
+ \global\chapterappendixnumber = 0
+ \fi
+ \global\increment \appendixnumber
+ \setcomptext{\chaptercomptext}% % Not \appendixcomptext!
+ \paging
+ \remark{Starting appendix \the\chaptercomptext.}%
+ \zsetrunnerstoks{\runners}%
+ \appendixformat{#1}%
+ \deferfloats{\true}%
+ \settaginfo{\the\chaptercomptext}{#1}}
+
+\def \endappendix {%
+ \closeanysection
+ \global\decrement \appendixdepth
+ \endblockscope{appendix}}
+
+\def \appendixformat #1{%
+ {\the\numberfont
+ \zsinkskip{\numbersink}{\breakbest}{\numberskip}%
+ \numberformat\par}%
+ {\the\titlefont
+ \zsinkskip{\titlesink}{\breaknever}{\titleskip}%
+ \titleformat{#1}\par}%
+ \providemark{#1}%
+ \zpartchaptoc{\the\chaptercomptext}{#1}{71}%
+ \zsinkskip{\textsink}{\breaknever}{\textskip}}
+
+% Section
+% -------
+
+
+\defineblock{\section}{\endsection}{\true}{}
+
+%~block section
+% \aboveskip = glue % Space b/b above title.
+% \setflag \allowintoc = boolean % Allow in ToC?
+% \def \comptextformat {...} % Composite number text formatter.
+% \difficulty = integer % Level of difficulty.
+% \numberfont = {...} % Number font.
+% \def \providemark ##1{...} % Mark provider.
+% \resetnumber = {...} % List of numbers to reset.
+% \style = {...} % Heading style.
+% \textskip = skip % Skip from title to text.
+% \titlefont = {...} % Title font.
+% \def \titleformat ##1{...} % Title format.
+% \topadjust = dimen % Adjust if at top of page.
+%~end
+
+\def \section #1{% {title}
+ \closeanysection
+ \beginblockscope{section}%
+ \global\increment \sectiondepth
+ \difficulty = 0 %~default with
+ \style = {Caps/lowercase, \noindent}% %~default soft
+ \topadjust = \mindimen %~default hard
+ \processdesign{\section}{}%
+ \global\subsectionnumber = 0
+ \global\subsubsectionnumber = 0
+ \global\subsubsubsectionnumber = 0
+ \global\increment \sectionnumber
+ \setcomptext{\sectioncomptext}%
+ \sectionformat{#1}%
+ \settaginfo{\the\sectioncomptext}{#1}}
+
+\def \endsection {%
+ \closeanysubsection
+ \global\decrement \sectiondepth
+ \endblockscope{section}}
+
+\def \sectionformat #1{%
+ {\if \emptytoksp{\numberfont}\the\titlefont \else \the\numberfont \fi
+ \zskipabovehead{\breakbest}{\aboveskip}%
+ \titleformat{#1}\par}%
+ \providemark{#1}%
+ \ztocentry{\the\sectioncomptext}{#1}{60}{\allowintoc}%
+ \bbskipabove{\breaknever}{\textskip}%
+ \overrideclubpenalty{\breaknever}}
+
+% Quasi-Section
+% -------------
+
+
+\defineblock{\quasisection}{\endquasisection}{\true}{}
+
+%~block quasisection
+% \aboveskip = glue % Space b/b above title.
+% \setflag \allowintoc = boolean % Allow in ToC?
+% \difficulty = integer % Level of difficulty.
+% \def \providemark ##1{...} % Mark provider.
+% \resetnumber = {...} % List of numbers to reset.
+% \style = {...} % Heading style.
+% \textskip = skip % Skip from title to text.
+% \titlefont = {...} % Title font.
+% \def \titleformat ##1{...} % Title format.
+% \topadjust = dimen % Adjust if at top of page.
+%~end
+
+\def \quasisection #1{% {tile}
+ \closeanysection
+ \beginblockscope{quasisection}%
+ \global\increment \quasisectiondepth
+ \difficulty = 0 %~default with
+ \style = {Caps/lowercase, \noindent}% %~default soft
+ \topadjust = \mindimen %~default hard
+ \processdesign{\quasisection}{}%
+ \global\increment \quasisectionnumber % In case needed for \tagpageonly.
+ \quasisectionformat{#1}%
+ \settaginfo{}{#1}}
+
+\def \endquasisection {%
+ \closeanysubsection
+ \global\decrement \quasisectiondepth
+ \endblockscope{quasisection}}
+
+\def \quasisectionformat #1{%
+ {\the\titlefont
+ \zskipabovehead{\breakbest}{\aboveskip}%
+ \titleformat{#1}\par}
+ \providemark{#1}%
+ \ztocentry{}{#1}{65}{\allowintoc}%
+ \bbskipabove{\breaknever}{\textskip}%
+ \overrideclubpenalty{\breaknever}}
+
+% Chapter Appendix
+% ------- --------
+
+
+\defineblock{\chapterappendix}{\endchapterappendix}{\true}{}
+
+%~block chapterappendix
+% \aboveskip = glue % Space b/b above title.
+% \setflag \allowintoc = boolean % Allow in ToC?
+% \def \comptextformat {...} % Composite number text formatter.
+% \difficulty = integer % Level of difficulty.
+% \numberfont = {...} % Number font.
+% \def \providemark ##1{...} % Mark provider.
+% \resetnumber = {...} % List of numbers to reset.
+% \style = {...} % Heading style.
+% \textskip = skip % Skip from title to text.
+% \titlefont = {...} % Title font.
+% \def \titleformat ##1{...} % Title format.
+% \topadjust = dimen % Adjust if at top of page.
+%~end
+
+\def \chapterappendix #1{% {title}
+ \closeanysection
+ \beginblockscope{chapterappendix}%
+ \global\increment \chapterappendixdepth
+ \difficulty = 0 %~default with
+ \style = {Caps/lowercase, \noindent}% %~default soft
+ \topadjust = \mindimen %~default hard
+ \processdesign{\chapterappendix}{}%
+ \global\subsectionnumber = 0
+ \global\subsubsectionnumber = 0
+ \global\subsubsubsectionnumber = 0
+ \global\increment \chapterappendixnumber
+ \setcomptext{\sectioncomptext}% % Not \chapterappendixcomptext!
+ \chapterappendixformat{#1}%
+ \settaginfo{\the\sectioncomptext}{#1}}
+
+\def \endchapterappendix {%
+ \closeanysubsection
+ \global\decrement \chapterappendixdepth
+ \endblockscope{chapterappendix}}
+
+\def \chapterappendixformat #1{%
+ {\if \emptytoksp{\numberfont}\the\titlefont \else \the\numberfont \fi
+ \zskipabovehead{\breakbest}{\aboveskip}%
+ \titleformat{#1}\par}%
+ \providemark{#1}%
+ \ztocentry{\the\sectioncomptext}{#1}{61}{\allowintoc}%
+ \bbskipabove{\breaknever}{\textskip}%
+ \overrideclubpenalty{\breaknever}}
+
+% Subsection
+% ----------
+
+
+\defineblock{\subsection}{\endsubsection}{\false}{}
+
+%~block subsection
+% \aboveskip = glue % Space b/b above title.
+% \setflag \allowintoc = flag % Allow in ToC?
+% \def \comptextformat {...} % Composite number text formatter.
+% \difficulty = integer % Level of difficulty.
+% \numberfont = {...} % Font for number.
+% \def \providemark ##1{...} % Mark provider.
+% \style = {...} % Heading style.
+% \textskip = skip % Skip from title to text.
+% \titlefont = {...} % Title font.
+% \def \titleformat ##1{...} % Title format.
+% \topadjust = dimen % Adjust if at top of page.
+%~end
+
+\def \subsection #1{% {title}
+ \closeanysubsection
+ \beginblockscope{subsection}%
+ \global\increment \subsectiondepth
+ \difficulty = 0 %~default with
+ \style = {Caps/lowercase, \noindent}% %~default soft
+ \topadjust = \mindimen %~default hard
+ \processdesign{\subsection}{}%
+ \global\subsubsectionnumber = 0
+ \global\subsubsubsectionnumber = 0
+ \global\increment \subsectionnumber
+ \setcomptext{\subsectioncomptext}%
+ \subsectionformat{#1}%
+ \settaginfo{\the\subsectioncomptext}{#1}%
+ \ignorespaces}
+
+\def \endsubsection {%
+ \closeanysubsubsection
+ \global\decrement \subsectiondepth
+ \endblockscope{subsection}}
+
+\def \subsectionformat #1{%
+ {\if \emptytoksp{\numberfont}\the\titlefont \else \the\numberfont \fi
+ \zskipabovehead{\breakbetter}{\aboveskip}%
+ \titleformat{#1}}%
+ \providemark{#1}%
+ \ztocentry{\the\subsectioncomptext}{#1}{50}{\allowintoc}%
+ \if \dimposp{\textskip}%
+ \par
+ \bbskipabove{\breaknever}{\textskip}%
+ \fi
+ \overrideclubpenalty{\breaknever}}
+
+% Quasi-Subsection
+% ----------------
+
+
+\defineblock{\quasisubsection}{\endquasisubsection}{\false}{}
+
+%~block quasisubsection
+% \aboveskip = glue % Space b/b above title.
+% \setflag \allowintoc = boolean % Allow in ToC?
+% \difficulty = integer % Level of difficulty.
+% \def \providemark ##1{...} % Mark provider.
+% \style = {...} % Heading style.
+% \textskip = skip % Skip from title to text.
+% \titlefont = {...} % Title font.
+% \def \titleformat ##1{...} % Title format.
+% \topadjust = dimen % Adjust if at top of page.
+%~end
+
+\def \quasisubsection #1{% {title}
+ \closeanysubsection
+ \beginblockscope{quasisubsection}%
+ \global\increment \quasisubsectiondepth
+ \difficulty = 0 %~default with
+ \style = {Caps/lowercase, \noindent}% %~default soft
+ \topadjust = \mindimen %~default hard
+ \processdesign{\quasisubsection}{}%
+ \quasisubsectionformat{#1}%
+ \settaginfo{}{#1}%
+ \ignorespaces}
+
+\def \endquasisubsection {%
+ \closeanysubsubsection
+ \global\decrement \quasisubsectiondepth
+ \endblockscope{quasisubsection}}
+
+\def \quasisubsectionformat #1{%
+ {\the\titlefont
+ \zskipabovehead{\breakbetter}{\aboveskip}%
+ \titleformat{#1}}
+ \providemark{#1}%
+ \ztocentry{}{#1}{55}{\allowintoc}%
+ \if \dimposp{\textskip}%
+ \par
+ \bbskipabove{\breaknever}{\textskip}%
+ \fi
+ \overrideclubpenalty{\breaknever}}
+
+% Subsubsection
+% -------------
+
+
+\defineblock{\subsubsection}{\endsubsubsection}{\false}{}
+
+%~block subsubsection
+% \aboveskip = glue % Space b/b above title.
+% \setflag \allowintoc = flag % Allow in ToC?
+% \def \comptextformat {...} % Composite number text formatter.
+% \difficulty = integer % Level of difficulty.
+% \numberfont = {...} % Font for number.
+% \def \providemark ##1{...} % Mark provider.
+% \style = {...} % Heading style.
+% \textskip = skip % Skip from title to text.
+% \titlefont = {...} % Title font.
+% \def \titleformat ##1{...} % Title format.
+% \topadjust = dimen % Adjust if at top of page.
+%~end
+
+\def \subsubsection #1{% {title}
+ \closeanysubsubsection
+ \beginblockscope{subsubsection}%
+ \global\increment \subsubsectiondepth
+ \difficulty = 0 %~default with
+ \style = {Caps/lowercase, \noindent}% %~default soft
+ \topadjust = \mindimen %~default hard
+ \processdesign{\subsubsection}{}%
+ \global\subsubsubsectionnumber = 0
+ \global\increment \subsubsectionnumber
+ \setcomptext{\subsubsectioncomptext}%
+ \subsubsectionformat{#1}%
+ \settaginfo{\the\subsubsectioncomptext}{#1}%
+ \ignorespaces}
+
+\def \endsubsubsection {%
+ \closeanysubsubsubsection
+ \global\decrement \subsubsectiondepth
+ \endblockscope{subsubsection}}
+
+\def \subsubsectionformat #1{%
+ {\if \emptytoksp{\numberfont}\the\titlefont \else \the\numberfont \fi
+ \zskipabovehead{\breakgood}{\aboveskip}%
+ \titleformat{#1}}%
+ \providemark{#1}%
+ \ztocentry{\the\subsubsectioncomptext}{#1}{40}{\allowintoc}%
+ \if \dimposp{\textskip}%
+ \par
+ \bbskipabove{\breaknever}{\textskip}%
+ \fi
+ \overrideclubpenalty{\breaknever}}
+
+% Subsubsubsection
+% ----------------
+
+
+\defineblock{\subsubsubsection}{\endsubsubsubsection}{\false}{}
+
+%~block subsubsubsection
+% \aboveskip = glue % Space b/b above title.
+% \setflag \allowintoc = flag % Allow in ToC?
+% \def \comptextformat {...} % Composite number text formatter.
+% \difficulty = integer % Level of difficulty.
+% \numberfont = {...} % Font for number.
+% \def \providemark ##1{...} % Mark provider.
+% \style = {...} % Heading style.
+% \textskip = skip % Skip from title to text.
+% \titlefont = {...} % Title font.
+% \def \titleformat ##1{...} % Title format.
+% \topadjust = dimen % Adjust if at top of page.
+%~end
+
+\def \subsubsubsection #1{% {title}
+ \closeanysubsubsubsection
+ \beginblockscope{subsubsubsection}%
+ \global\increment \subsubsubsectiondepth
+ \difficulty = 0 %~default with
+ \style = {Caps/lowercase, \noindent}% %~default soft
+ \topadjust = \mindimen %~default hard
+ \processdesign{\subsubsubsection}{}%
+ \global\increment \subsubsubsectionnumber
+ \setcomptext{\subsubsubsectioncomptext}%
+ \subsubsubsectionformat{#1}%
+ \settaginfo{\the\subsubsubsectioncomptext}{#1}%
+ \ignorespaces}
+
+\def \endsubsubsubsection {%
+ \global\decrement \subsubsubsectiondepth
+ \endblockscope{subsubsubsection}}
+
+\def \subsubsubsectionformat #1{%
+ {\if \emptytoksp{\numberfont}\the\titlefont \else \the\numberfont \fi
+ \zskipabovehead{\breakgood}{\aboveskip}%
+ \titleformat{#1}}%
+ \providemark{#1}%
+ \ztocentry{\the\subsubsubsectioncomptext}{#1}{30}{\allowintoc}%
+ \if \dimposp{\textskip}%
+ \par
+ \bbskipabove{\breaknever}{\textskip}%
+ \fi
+ \overrideclubpenalty{\breaknever}}
+
+% Simple Head
+% ------ ----
+
+
+\defineblock{\simplehead}{\endsimplehead}{\false}{}
+
+%~block simplehead Type
+% \aboveskip = glue % Space b/b above title.
+% \setflag \allowclubline = flag % True if club allowed below.
+% \setflag \allowintoc = boolean % Allow in ToC?
+% \difficulty = integer % Level of difficulty.
+% \style = {...} % Heading style.
+% \textskip = skip % Skip from title to text.
+% \titlefont = {...} % Title font.
+% \def \titleformat ##1{...} % Title format.
+% \tocentrylevel = integer % ToC entry level number (optional).
+% \topadjust = dimen % Adjust if at top of page.
+%~end
+
+\definecount{\tocentrylevel}{0}
+
+
+\def \simplehead #1#2{% {type}{title}
+ \endgraf
+ \beginblockscope{simplehead}%
+ \global\increment \simpleheaddepth
+ \setflag \allowclubline = \false %~default soft
+ \setflag \allowintoc = \true %~default with
+ \difficulty = 0 %~default with
+ \style = {Caps/lowercase, \noindent}% %~default soft
+ \tocentrylevel = 0 %~default soft
+ \topadjust = \mindimen %~default hard
+ \processdesign{\simplehead}{#1}%
+ \global\increment \simpleheadnumber
+ \simpleheadformat{#2}%
+ \endsimplehead}
+
+\def \endsimplehead {%
+ \global\decrement \simpleheaddepth
+ \endblockscope{simplehead}%
+ \ignorespaces}
+
+\def \simpleheadformat #1{%
+ {\the\titlefont
+ \zskipabovehead{\breakgood}{\aboveskip}%
+ \titleformat{#1}}%
+ \if \dimzerop{\textskip}%
+ \nobreak
+ \else
+ \endgraf
+ \bbskipabove{\breaknever}{\textskip}%
+ \fi
+ \if \posp{\tocentrylevel}%
+ \ztocentry{}{#1}{\tocentrylevel}{\allowintoc}%
+ \fi
+ \if \notp{\allowclubline}\overrideclubpenalty{\breaknever}\fi}
+
+% Useful Utilities
+% ------ ---------
+
+
+\def \chapterorchapterappendixcomptext {%
+ \if \inblockp{\chapterappendix}%
+ \the\sectioncomptext
+ \else
+ \the\chaptercomptext
+ \fi}
+
+\def \textonlyhead {% %^modifier
+ \with{\setflag\allowintoc=\false
+ \def\providemark##1{}}}
+
+\def \closeanychapter {%
+ \closeifinblock{\part}{\endpart}%
+ \closeifinblock{\quasipart}{\endquasipart}%
+ \closeifinblock{\quasichapter}{\endquasichapter}%
+ \closeifinblock{\chapter}{\endchapter}%
+ \closeifinblock{\appendix}{\endappendix}}
+
+\def \closeanysection {%
+ \closeifinblock{\quasisection}{\endquasisection}%
+ \closeifinblock{\section}{\endsection}%
+ \closeifinblock{\chapterappendix}{\endchapterappendix}}
+
+\def \closeanysubsection {%
+ \closeifinblock{\quasisubsection}{\endquasisubsection}%
+ \closeifinblock{\subsection}{\endsubsection}}
+
+\def \closeanysubsubsection {%
+ \closeifinblock{\subsubsection}{\endsubsubsection}}
+
+\def \closeanysubsubsubsection {%
+ \closeifinblock{\subsubsubsection}{\endsubsubsubsection}}
+
+\def \zsinkskip #1#2#3{% {sink}{penalty}{skip}
+ \if \dimposp{#3}%
+ \bbskipabove{#2}{#3}%
+ \else
+ \vsinkfromtypearea{#1}%
+ \fi}
+
+\def \zskipabovehead #1#2{% {penalty}{skip}
+ \bbskipabove{#1}{#2}%
+ \if \dimneqlp{\topadjust}{\mindimen}%
+ \vskip -\topadjust
+ \tdimena = \prevdepth
+ \rule{height 0pt depth 0pt width 0pt}%
+ \prevdepth = \tdimena
+ \penalty \breaknever
+ \vskip \topadjust
+ \fi}
+
+% If the author level is negative, the ToC entry goes before the chapter's
+% entry. Otherwise it goes after the chapter's entry.
+
+\def \zpartchaptoc #1#2#3{%
+ \edef \znext {\noexpand\tocentry{}{\the\authortext}}%
+ \if \andp{\notp{\emptytoksp{\authortext}}}{\negp{\authorlevel}}%
+ \znext{-\authorlevel}%
+ \fi
+ \ztocentry{#1}{#2}{#3}{\allowintoc}%
+ \if \andp{\notp{\emptytoksp{\authortext}}}{\posp{\authorlevel}}%
+ \znext{\authorlevel}%
+ \fi}
diff --git a/macros/plain/contrib/zztex/tex/zztabbing.tex b/macros/plain/contrib/zztex/tex/zztabbing.tex
new file mode 100644
index 0000000000..08257a45f4
--- /dev/null
+++ b/macros/plain/contrib/zztex/tex/zztabbing.tex
@@ -0,0 +1,266 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% Module: ZzTeX Tabbing Facilities
+%
+% Synopsis: This module contains the definition of the block that is
+% used to format text with tab stops.
+%
+% Authors: Paul C. Anagnostopoulos
+% Created: 27 May 2016
+%
+% Copyright 1989--2020 by Paul C. Anagnostopoulos
+% under The MIT License (opensource.org/licenses/MIT)
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% Tabbing Block
+% ------- -----
+
+
+\defineblock{\tabbing}{\endtabbing}{\false}{}
+\resetinvcontext{\tabbing}
+
+%~block tabbing Type
+% \abovepenalty = integer % Penalty above text.
+% \aboveskip = glue % Space b/b above text.
+% \setflag \autocallout = boolean % Automatically number lines?
+% \def \beginformat {...} % Beginning of text formatter.
+% \belowpenalty = integer % Penalty below text.
+% \belowskip = glue % Space b/b below text.
+% \bodyfont = {font} % Body font.
+% \def \calloutformat ##1{...} % Callout formatter.
+% \calloutnumber = integer % Number of first callout.
+% \def \callouttext {...} % Callout text or \arg.
+% \defaulttabwidth = dimen % Default repeating tab width.
+% \def \endformat {...} % End of text formatter.
+% \leftindent = glue % Left indentation.
+% \rightindent = glue % Right indentation.
+% \tabbinggapskip = glue % Standard tabbing gap.
+% \textcolor = {...} % Color of text.
+% \width = dimen % Line width.
+%~end
+
+\defineskip{\tabbinggapskip}{0pt}
+
+\def \tabbing #1{% {type}
+ \blockcantbein{\tabbing}{\tabbing}%
+ \beginblockscope{tabbing}%
+ \global\increment \tabbingdepth
+ \abovepenalty = \breakgood %~default hard
+ \setflag \autocallout = \false %~default soft
+ \def \beginformat {}% %~default soft
+ \belowpenalty = \breakgood %~default hard
+ \calloutnumber = 1 %~default with
+ \def \callouttext {\number\calloutnumber}% %~default soft
+ \defaulttabwidth = \mindimen %~default soft
+ \def \endformat {}% %~default soft
+ \tabbinggapskip = \enclosingbaselineskip %~default soft
+ \textcolor = {}% %~default soft
+ \parindent = 0pt
+ \parrag = 0pt
+ \parskip = 0pt
+ \processdesign{\tabbing}{#1}%
+ \global\increment \tabbingnumber
+ \tabbingformat
+ \def \zarg {\arg}%
+ \if \tokeqlp{\callouttext}{\zarg}%
+ \defineatsigncommand @##{\ztbngatcallout}%
+ \else
+ \defineatsigncommand @##{\ztbngatcallout{\callouttext}}%
+ \fi
+ \if \emptytoksp{\textcolor}% % Must have a group around \ztbnginit.
+ \bgroup
+ \else
+ \color{\the\textcolor}%
+ \fi
+ \ztbnginit
+ \ztbngstartline}
+
+\def \endtabbing {%
+ \ztbngfinal
+ \if \emptytoksp{\textcolor}%
+ \egroup % \tabbing group
+ \else
+ \endcolor
+ \fi
+ \futurelet\nexttoken \zendtabbing}
+
+\def \zendtabbing {%
+ \endtabbingformat
+ \global\decrement \tabbingdepth
+ \endblockscope{tabbing}%
+ \parnext}
+
+\def \tabbingformat {%
+ \endgraf
+ \the\bodyfont
+ \bbskipabove{\abovepenalty}{\aboveskip}%
+ \alterindentation{\leftindent}{\rightindent}%
+ \settextwidth{\width}%
+ \beginformat}
+
+\def \endtabbingformat {%
+ \endformat
+ \bbskipbelowblockpar{\nexttoken}{\belowpenalty}{\belowskip}}
+
+%~ Use this command in between lines in a |\tabbing| block to
+%~ perform a vertical adjustment between those two lines. For example,
+%~
+%~ \adjusttabbing{\fullpagebreak}
+
+\long\def \adjusttabbing #1{% {commands}
+ \ztbngadjust{#1}}
+
+% Initialize and Finalize
+% ---------- --- --------
+
+
+\definecount{\ztbngstopcount}{0}
+\definecount{\ztbngstopindex}{0}
+
+\definebox{\ztbngline}
+\definebox{\ztbngfragment}
+
+
+\def \ztbnginit {%
+ \let \par = \ztbngshouldntbepar
+ \def \nl {\ztbngfinishline{\false}}%
+ \defineatsigncommand @.{\ztbngatsetstop}%
+ \defineatsigncommand @>{\ztbngattab}%
+ \defineatsigncommand @C{\ztbngatclear}%
+ \defineatsigncommand @D{\ztbngatdiscard}%
+ \ztbngsetdefaultstops{\defaulttabwidth}}
+
+\def \ztbngsetdefaultstops #1{% {width}
+ \global\ztbngstopcount = 0
+ \def \ztbngstop {0pt}%
+ \if \dimgtrp{#1}{0pt}%
+ \tdimena = 0pt
+ \loop
+ \global\increment \ztbngstopcount
+ \advance \tdimena by #1\relax
+ \withname\edef {\ztbngstop\romannumeral\ztbngstopcount}{\the\tdimena}%
+ \if \dimlssp{\tdimena}{\hsize}%
+ \repeat
+ \fi}
+
+\def \ztbngfinal {%
+ \ztbngfinishline{\true}}
+
+% Build Lines
+% ----- -----
+
+
+\def \ztbngstartline {%
+ \ztbngstopindex = 0
+ \setbox\ztbngline = \hbox{}%
+ \global\setflag \ztbngdiscardp = \false
+ \settaginfo{\number\calloutnumber}{???title???}%
+ \ztbngstartfragment}
+
+\def \ztbngstartfragment {%
+ \setbox \ztbngfragment = \hbox\bgroup
+ \ignorespaces}
+
+\def \ztbngfinishfragment {%
+ \egroup % \ztbngfragment box
+ \setbox\ztbngline = \hbox{%
+ \unhbox\ztbngline
+ \tdimena = \name{\ztbngstop\romannumeral\ztbngstopindex}%
+ \hskip \tdimena
+ \tdimenb = \hsize
+ \advance \tdimenb by -\tdimena
+ \hbox to \tdimenb{\copy\ztbngfragment \hfil}%
+ \hskip -\tdimenb
+ \hskip -\tdimena}}
+
+\def \ztbngfinishline #1{% {end-of-block?}
+ \ztbngfinishfragment
+ \if \notp{\ztbngdiscardp}%
+ \if \orp{\posp{\ztbngstopindex}}{\dimposp{\wd\ztbngfragment}}%
+ \noindent
+ \if \autocallout
+ \llap{\calloutformat{\the\calloutnumber}}%
+ \increment \calloutnumber
+ \fi
+ \box\ztbngline
+ \endgraf
+ \else\if \notp{#1}%
+ \vspace{\tabbinggapskip}%
+ \fi\fi
+ \fi
+ \if #1\let \znext = \relax \else \let \znext = \ztbngstartline \fi
+ \znext}
+
+% At-sign Commands
+% ------- --------
+
+
+% @#{callout}text...
+
+\def \ztbngatcallout #1{% {callout}
+ \ztbngfinishfragment
+ \if \andp{\zerop{\ztbngstopindex}}{\dimzerop{\wd\ztbngfragment}}
+ \setbox\ztbngfragment = \hbox\bgroup
+ \llap{\calloutformat{#1}}%
+ \ztbngfinishfragment
+ \else
+ \error{badtabcallout}{Callout command (\noexpand@##) must appear
+ at the beginning of the line}%
+ \fi
+ \increment \calloutnumber
+ \ztbngstartfragment}
+
+% text@.more text...
+
+\def \ztbngatsetstop {%
+ \ztbngfinishfragment
+ \tdimena = \name{\ztbngstop\romannumeral\ztbngstopindex}%
+ \advance \tdimena by \wd\ztbngfragment
+ \increment \ztbngstopindex
+ \if \gtrp{\ztbngstopindex}{\ztbngstopcount}%
+ \withname\edef {\ztbngstop\romannumeral\ztbngstopindex}{\the\tdimena}%
+ \increment \ztbngstopcount
+ \else
+ \error{badtabstop}{There is already a tab stop}%
+ \fi
+ \ztbngstartfragment}
+
+% text@>more text...
+
+\def \ztbngattab {%
+ \ztbngfinishfragment
+ \if \lssp{\ztbngstopindex}{\ztbngstopcount}%
+ \increment \ztbngstopindex
+ \else
+ \warning{toomanytabs}{Too many tabs on line; extra tabs ignored}%
+ \fi
+ \ztbngstartfragment}
+
+% @Ctext...\nl
+
+\def \ztbngatclear {%
+ \if \zerop{\ztbngstopindex}%
+ \global\ztbngstopcount = 0\relax
+ \else
+ \error{badtabclear}{Tabs must be cleared at the beginning of the line}%
+ \fi}
+
+% text@D\nl
+
+\def \ztbngatdiscard {%
+ \global\setflag \ztbngdiscardp = \true \relax}
+
+% Adjustment
+% ----------
+
+
+\long\def \ztbngadjust #1{% {commands}
+ \ztbngfinishfragment
+ \if \andp{\zerop{\ztbngstopindex}}{\dimzerop{\wd\ztbngfragment}}
+ #1%
+ \else
+ \error{badtabadjust}{The \noexpand\adjusttabbing command must appear
+ in between lines}%
+ \fi
+ \ztbngstartfragment}
diff --git a/macros/plain/contrib/zztex/tex/zztabularv1.tex b/macros/plain/contrib/zztex/tex/zztabularv1.tex
new file mode 100644
index 0000000000..13fb536ab8
--- /dev/null
+++ b/macros/plain/contrib/zztex/tex/zztabularv1.tex
@@ -0,0 +1,465 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% Module: ZzTeX Tabular Facilities
+%
+% Synopsis: This module contains all the facilities for producing
+% tabular material.
+%
+% Author: Paul C. Anagnostopoulos
+% Created: 1990
+%
+% Copyright 1989--2020 by Paul C. Anagnostopoulos
+% under The MIT License (opensource.org/licenses/MIT)
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% Tabular Block
+% ------- -----
+
+
+\let \tabularcomptext = \relax
+\let \tabulardepth = \relax
+\let \tabularnumber = \relax
+
+
+\defineblock{\tabular}{\endtabular}{\false}{}
+
+%~obsolete-block tabular Type
+% \abovepenalty = integer
+% \aboveskip = glue
+% \setflag \allowbreaks = boolean
+% \belowpenalty = integer
+% \belowskip = glue
+% \bodyfont = {...}
+% \colheadaboveskip = glue
+% \colheadbelowskip = glue
+% \colheadfont = {...}
+% \colsubheadfont = {...}
+% \columngutter = glue
+% \cutinheadaboveskip = glue
+% \cutinheadbelowskip = glue
+% \cutinheadfont = {...}
+% \interrowskip = glue
+% \leftindent = glue
+% \parhang = dimen
+% \parrag = dimen
+% \rightindent = glue
+% \rulecolwidth = dimen
+% \spannerheadfont = {...}
+% \spannerruleaboveskip = dimen
+% \spannerrulebelowskip = dimen
+% \spannerruleheight = dimen
+% \def \tabnoteformat ##1{...}
+% \tabrulecolor = {color}%
+% \tabruleheight = dimen
+% \width = dimen
+%~end
+
+\defineskip{\colheadaboveskip}{0pt}
+\let \headaboveskip = \colheadaboveskip
+\let \headbelowskip = \colheadbelowskip
+\definetoks{\colsubheadfont}
+\defineskip{\cutinheadaboveskip}{0pt}
+\defineskip{\cutinheadbelowskip}{0pt}
+\definetoks{\cutinheadfont}
+
+
+\definecount{\tabularcolcount}{0} % Number of columns in table.
+\definebox{\rowstrutbox} % Strut for table rows.
+
+
+\def \tabular #1#2{% {type}{template}
+ \endgraf
+ \beginblockscope{tabular}%
+ \global\increment \tabulardepth
+ \abovepenalty = \breakgood %~default hard
+ \belowpenalty = \breakbetter %~default hard
+ \tabrulecolor = {black}% %~default soft
+ \processdesign{\tabular}{#1}%
+ \global\increment \tabularnumber
+ \iffalse{\fi % Must be done with master
+ \tabularcolcount = 0 % counter > 0, to hide inner
+ \ztabcols #2&\zmark % \set and &.
+ \let \set = \span
+ \iffalse}\fi
+ \tabularformat
+ \fakepar
+ \nointerlineskip % We assume this below.
+ \if \notp{\allowbreaks}\vtop \fi \bgroup
+ \offinterlineskip
+ \everycr = {}%
+ \tabskip = \leftskip
+ \halign \if \dimneqlp{\width}{\naturalwidth}to \width \fi \bgroup
+ #2\tabskip = \rightskip \cr}
+
+\def \endtabular {%
+ \crcr
+ \egroup % \halign
+ \if \posp{\prevdepth}\kern -\interrowskip \fi % If last line has strut.
+ \egroup % \vtop
+ \prevdepth = \dp\strutbox % So row strut depth won't shine thru.
+ \futurelet\nexttoken \zendtabular}
+
+\def \zendtabular {%
+ \endtabularformat
+ \global\decrement \tabulardepth
+ \endblockscope{tabular}%
+ \parnext}
+
+\def \tabularformat {%
+ \endgraf
+ \the\bodyfont
+ \tdimena = \dp\strutbox
+ \advance \tdimena by \interrowskip
+ \setbox \rowstrutbox = \hbox{\vrule height \ht\strutbox depth \tdimena
+ width 0pt}%
+ \advance \aboveskip by \baselineskip % Compensate for absence
+ \advance \aboveskip by -\prevdepth % of interlineskip above
+ \advance \aboveskip by -\ht\rowstrutbox % first row of tabular.
+ \bbskipabove{\abovepenalty}{\aboveskip}%
+ \alterindentation{\leftindent}{\rightindent}}
+
+\def \endtabularformat{%
+ \bbskipbelowblockpar{\nexttoken}{\belowpenalty}{\belowskip}}
+
+\def \ztabcols #1&#2\zmark{%
+ \increment \tabularcolcount
+ \if \notp{\emptyargp{#2}}\ztabcols #2\zmark \fi}
+
+% Template Facilities
+% -------- ----------
+
+
+% The following macros are used to construct the tabular template.
+% They are all used with the \set macro.
+
+\def \centercol {%
+ \hfil ##\rowstrut \hfil \tabskip=\columngutter}
+
+\def \centernumbercol #1{% {template}
+ \hfil \znumcell{#1}{##}\rowstrut \hfil \tabskip=\columngutter}
+
+\let \colgutter = \tabskip
+
+\def \customcol #1#2{% {left}{right}
+ #1\relax##\rowstrut #2\relax \tabskip=\columngutter}
+
+\def \customrulecol #1{% {width}
+ \color{\the\tabrulecolor}%
+ \vrule width #1 ##%
+ \endcolor \tabskip=\columngutter}
+
+\def \emptycol #1{% {width}
+ ##\rowstrut \hspace{#1}\tabskip=\columngutter}
+
+\def \leftcol {%
+ ##\rowstrut \hfil \tabskip=\columngutter}
+
+\def \leftnumbercol #1{% {template}
+ \znumcell{#1}{##}\rowstrut \hfil \tabskip=\columngutter}
+
+\def \parcol #1{% {width}
+ \vtop{\zpushvcontext
+ \zinitparcell{#1}{\parhang}%
+ \strut ##%
+ \if \hmodep \rowstrut \par \fi
+ \zpopvcontext}%
+ \tabskip=\columngutter}
+
+\def \rightcol {%
+ \hfil ##\rowstrut \tabskip=\columngutter}
+
+\def \rightnumbercol #1{% {template}
+ \hfil \znumcell{#1}{##}\rowstrut \tabskip=\columngutter}
+
+\def \rulecol {%
+ \color{\the\tabrulecolor}%
+ \vrule width \rulecolwidth ##%
+ \endcolor \tabskip=\columngutter}
+
+% Cell Facilities
+% ---- ----------
+
+
+% The following macros help with tabular entries (cells).
+
+\def \0{\phantom{0}}
+
+\def \centercell #1{% {text}
+ \omit
+ \hfil #1\rowstrut \hfil}
+
+\def \centerhead #1{% {heading}
+ \centercell{\the\colheadfont #1}}
+
+\def \centernumbercell #1#2{% {template}{text}
+ \omit
+ \hfil \znumcell{#1}{#2}\rowstrut \hfil}
+
+\def \centersubhead #1{% {heading}
+ \centercell{\the\colsubheadfont #1}}
+
+\def \customspannerrule #1#2{% {columns}{height}
+ \multispan{#1}%
+ \rowstrut
+ \ruleleaders{\hrule height #2 depth 0pt}}
+
+\def \customspannerruleabut #1#2{% {columns}{height}
+ \multispan{#1}%
+ \ruleleaders{\hrule height #2 depth 0pt}}
+
+\def \cutinhead #1{% {heading}
+ \multispan{\tabularcolcount}%
+ \leftcell{\the\cutinheadfont #1}}
+
+\def \cutinpar #1#2{% {width}{text}
+ \multispan{\tabularcolcount}%
+ \parhang = 0pt \parcell{#1}{#2}}
+
+\zremovePlaindef \hideskip
+\defineskip{\hideskip}{-1000pt plus 1fill}
+
+\def \hidewidth {\hskip \hideskip}
+
+\def \leftcell #1{% {text}
+ \omit
+ #1\rowstrut \hfil}
+
+\def \lefthead #1{% {heading}
+ \leftcell{\the\colheadfont #1}}
+
+\def \leftnumbercell #1#2{% {template}{text}
+ \omit
+ \znumcell{#1}{#2}\rowstrut \hfil}
+
+\def \leftsubhead #1{% {heading}
+ \leftcell{\the\colsubheadfont #1}}
+
+\def \multispan #1{% {columns}
+ \omit
+ \tcounta =#1\relax
+ \loop \ifnum \tcounta > 1 \zspan \repeat
+ \let \omit = \relax % In case the next thing is a \leftcell or whatever.
+ \ignorespaces}
+
+\def \zspan{\span\omit \decrement \tcounta}
+
+\def \nocolrule {%
+ width 0pt }
+
+\def \parcell #1#2{% {width}{text}
+ \omit
+ \vtop{\zpushvcontext
+ \zinitparcell{#1}{\parhang}%
+ \strut #2%
+ \if \hmodep \rowstrut \par \fi
+ \zpopvcontext}}
+
+\def \rightcell #1{% {text}
+ \omit
+ \hfil #1\rowstrut}
+
+\def \righthead #1{% {heading}
+ \rightcell{\the\colheadfont #1}}
+
+\def \rightnumbercell #1#2{% {template}{text}
+ \omit
+ \hfil \znumcell{#1}{#2}\rowstrut}
+
+\def \rightsubhead #1{% {heading}
+ \rightcell{\the\colsubheadfont #1}}
+
+\def \rowstrut {\unhcopy \rowstrutbox}
+
+\def \spannerhead #1#2{% {columns}{heading}
+ \multispan{#1}%
+ \centercell{\the\spannerheadfont #2}}
+
+\def \spannerrule #1{% {columns}
+ \multispan{#1}%
+ \rowstrut
+ \ruleleaders{\hrule height \spannerruleheight depth 0pt}}
+
+\def \spannerruleabut #1{% {columns}
+ \multispan{#1}%
+ \ruleleaders{\hrule height \spannerruleheight depth 0pt}}
+
+\def \spannerruleabutbelow #1{% {columns}
+ \multispan{#1}%
+ \vrule height \ht\rowstrutbox depth 0pt width 0pt\relax
+ \ruleleaders{\hrule height \spannerruleheight depth 0pt}}
+
+\def \tabnote #1{% {note-mark}
+ {\tabnoteformat{#1}}}
+
+\def \znumcell #1#2{% {template}{text}
+ \if \emptyargp{#2}%
+ \relax
+ \else
+ \znumcella{#1}{#2}%
+ \fi}
+
+\def \znumcella #1#2{% {template}{text}
+ {\ztoksa = {}\ztoksb = {}%
+ \setflag \znumpt = \false
+ \znumcellb #1\zmark
+ \setbox\zboxa = \hbox{\the\ztoksa}%
+ \tdimena = \wd\zboxa
+ \setbox\zboxa = \hbox{\the\ztoksb}%
+ \tdimenb = \wd\zboxa
+ \setflag \ztempt = \znumpt
+ \ztoksa = {}\ztoksb = {}%
+ \setflag \znumpt = \false
+ \znumcellb #2\zmark
+ \if \ztempt % Template had a decimal point.
+ \if \znumpt
+ \hbox to \tdimena{\hss \the\ztoksa}%
+ \the\decimalpoint
+ \hbox to \tdimenb{\the\ztoksb \hss}%
+ \else
+ \setbox\zboxa = \hbox{\the\decimalpoint}%
+ \hbox to \tdimena{\hss \the\ztoksa}%
+ \kern \wd\zboxa \kern \tdimenb
+ \fi
+ \else % Template had no decimal point.
+ \if \znumpt
+ \error{celldecpt}{Tabular template did not specify a decimal point}%
+ \else
+ \hbox to \tdimena{\hss \the\ztoksa}%
+ \fi
+ \fi}}
+
+\def \znumcellb #1#2\zmark{% t1 trest \zmark
+ \if \codeeqlp{\noexpand#1}{\the\decimalpoint}%
+ \setflag \znumpt = \true
+ \else
+ \if \znumpt
+ \ztoksb = \expandafter{\the\ztoksb #1}%
+ \else
+ \ztoksa = \expandafter{\the\ztoksa #1}%
+ \fi
+ \fi
+ \if \emptyargp{#2}%
+ \let \znext = \relax
+ \else
+ \def \znext {\znumcellb #2\zmark}%
+ \fi
+ \znext}
+
+% Inter-Row Facilities
+% --------- ----------
+
+
+% The following macros perform various actions in between rows.
+
+\def \adjusttab #1{%
+ \if \notp{\vmodep}%
+ \error{badrowcmd}{The \string\adjusttab command cannot be used in a table row}%
+ \fi
+ \noalign{#1}}
+
+\def \customtabrule #1{% {height}
+ \multispan{\tabularcolcount}%
+ \rowstrut
+ \color{\the\tabrulecolor}%
+ \ruleleaders{\hrule height #1 depth 0pt}%
+ \endcolor
+ \cr}
+
+\def \customtabruleabut #1{%
+ \multispan{\tabularcolcount}%
+ \color{\the\tabrulecolor}%
+ \ruleleaders{\hrule height #1 depth 0pt}%
+ \endcolor
+ \cr}
+
+\def \customtabruleabutbelow #1{%
+ \multispan{\tabularcolcount}%
+ \vrule height \ht\rowstrutbox depth 0pt width 0pt\relax
+ \color{\the\tabrulecolor}%
+ \ruleleaders{\hrule height #1 depth 0pt}%
+ \endcolor
+ \cr}
+
+\def \nointerrowskip {\tabvspace{-\interrowskip}}
+
+\def \skipabovecolhead {%
+ \tabbbskip{\colheadaboveskip}}
+
+\def \skipbelowcolhead {%
+ \tabbbskip{\colheadbelowskip}}
+
+\def \skipabovespannerrule {%
+ \tabbbskip{\spannerruleaboveskip}}
+
+\def \skipbelowspannerrule {%
+ \tabbbskip{\spannerrulebelowskip}}
+
+\def \skipabovecutinhead {%
+ \tabbbskip{\cutinheadaboveskip}}
+
+\def \skipbelowcutinhead {%
+ \tabbbskip{\cutinheadbelowskip}}
+
+\def \tabbbskip #1{% {glue}
+ \adjusttab{\zskipa = #1\relax
+ \advance \zskipa by -\ht\rowstrutbox
+ \advance \zskipa by -\dp\rowstrutbox
+ \vskip \zskipa}}
+
+\def \tabrule {%
+ \multispan{\tabularcolcount}%
+ \rowstrut
+ \color{\the\tabrulecolor}%
+ \ruleleaders{\hrule height \tabruleheight depth 0pt}%
+ \endcolor
+ \cr}
+
+\def \tabruleabut {%
+ \multispan{\tabularcolcount}%
+ \color{\the\tabrulecolor}%
+ \ruleleaders{\hrule height \tabruleheight depth 0pt}%
+ \endcolor
+ \cr}
+
+\def \tabruleabutbelow {%
+ \multispan{\tabularcolcount}%
+ \vrule height \ht\rowstrutbox depth 0pt width 0pt\relax
+ \color{\the\tabrulecolor}%
+ \ruleleaders{\hrule height \tabruleheight depth 0pt}%
+ \endcolor
+ \cr}
+
+\def \tabvspace #1{\adjusttab{\vskip #1}}% {glue}
+
+% Alignment Utilities
+% --------- ---------
+
+
+\let \completerow = \cr
+
+\def \ialign {\everycr = {}\tabskip = 0pt \halign}
+
+\def \oalign #1{% {row...}
+ \ensurepar
+ \vtop{\baselineskip = 0pt
+ \lineskip = .25ex
+ \ialign{##\cr #1\crcr}}}
+
+\def \ooalign {%
+ \lineskiplimit = -\maxdimen
+ \oalign}
+
+\def \ozalign {%
+ \lineskiplimit = 0pt\relax
+ \oalign}
+
+\def \zinitparcell #1#2{% {width}{hang}
+ \baselineskip = \normalbaselineskip
+ \lineskiplimit = 0pt \lineskip = 0pt
+ \setindentation{0pt}{0pt}%
+ \settextwidth{#1}%
+ \setparrag{\parrag}%
+ \leftskip = #2
+ \parindent = -#2
+ \parfillskip = \normalparfillskip}
diff --git a/macros/plain/contrib/zztex/tex/zztabularv2.tex b/macros/plain/contrib/zztex/tex/zztabularv2.tex
new file mode 100644
index 0000000000..932a42f5d4
--- /dev/null
+++ b/macros/plain/contrib/zztex/tex/zztabularv2.tex
@@ -0,0 +1,512 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% Module: ZzTeX New Tabular Facilities
+%
+% Synopsis: This module contains all the facilities for producing
+% tabular material. This is the second major version.
+%
+% Author: Paul C. Anagnostopoulos
+% Created: 30 April 2001
+%
+% Copyright 1989--2020 by Paul C. Anagnostopoulos
+% under The MIT License (opensource.org/licenses/MIT)
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% Tabular Block
+% ------- -----
+
+
+\let \tabularcomptext = \relax
+\let \tabulardepth = \relax
+\let \tabularnumber = \relax
+
+
+\defineblock{\tabular}{\endtabular}{\false}{}
+
+%~obsolete-block tabular Type
+% \abovepenalty = integer
+% \aboveskip = glue
+% \belowpenalty = integer
+% \belowskip = glue
+% \bodyfont = {...}
+% \columngutter = glue
+% \colheadaboveskip = glue
+% \colheadbelowskip = glue
+% \colheadfont = {...}
+% \cutinheadfont = {...}
+% \setflag \hastoprule = \false
+% \interrowskip = glue
+% \leftindent = glue
+% \parhang = dimen
+% \parrag = dimen
+% \rightindent = glue
+% \rulecolwidth = dimen
+% \sectionheadaboveskip = glue
+% \sectionheadbelowskip = glue
+% \sideheadfont = {...}
+% \spannerheadfont = {...}
+% \spannerruleaboveskip = dimen
+% \spannerrulebelowskip = dimen
+% \spannerrulecolor = {color}
+% \spannerruleheight = dimen
+% \style = {...}
+% \tabbottomruleaboveskip = dimen
+% \tabheadrulebelowskip = dimen
+% \def \tabnoteformat ##1{...}
+% \tabrulecolor = {color}
+% \tabruleheight = dimen
+% \width = dimen
+%~end
+
+\defineskip{\colheadaboveskip}{0pt}
+%%%\defineskip{\colheadbelowskip}{0pt}
+%%%\definetoks{\colheadfont}
+\definetoks{\cutinheadfont}
+%%%\definedimen{\rulecolwidth}{0pt}
+\defineskip{\sectionheadaboveskip}{0pt}
+\defineskip{\sectionheadbelowskip}{0pt}
+%%%\definetoks{\sideheadfont}
+%%%\definetoks{\spannerheadfont}
+%%%\defineskip{\spannerruleaboveskip}{0pt}
+%%%\defineskip{\spannerrulebelowskip}{0pt}
+%%%\definetoks{\spannerrulecolor}
+%%%\definedimen{\spannerruleheight}{0pt}
+%%%\definedimen{\tabbottomruleaboveskip}{0pt}
+%%%\definedimen{\tabheadrulebelowskip}{0pt}
+%%%\definetoks{\tabrulecolor}
+%%%\definedimen{\tabruleheight}{0pt}
+
+
+%%%\definecount{\tabcolcount}{0} % Number of columns in table.
+
+\definetoks{\ztabspacetoks} % Special row for vertical spacing.
+%%%\definebox{\zrowstrut} % Strut for table rows.
+%%%\definebox{\zparcelltopstrut} % Strut for first line of par cell.
+%%%\definebox{\zparcellbotstrut} % Strut for last line of par cell.
+
+
+\def \tabular #1#2{% {type}{template}
+ \endgraf
+ \beginblockscope{tabular}%
+ \global\increment \tabulardepth
+ \abovepenalty = \breakgood %~default hard
+ \belowpenalty = \breakbetter %~default hard
+ \setflag \hastoprule = \false %~default soft
+ \parhang = 0pt %~default soft
+ \spannerrulecolor = {black}% %~default soft
+ \style = {top/head/bottom rules}% %~default soft
+ \tabrulecolor = {black}% %~default soft
+ \processdesign{\tabular}{#1}%
+ \global\increment \tabularnumber
+ \iffalse{\fi % Analyze the template with
+ \tabcolcount = 0 % master counter > 0 to hide
+ \ztabspacetoks = {}% % \set and &.
+ \zchecktabcols #2&\zmark
+ \let \set = \span
+ \iffalse}\fi
+ \tabularformat
+ \offinterlineskip
+ \everycr = {}%
+ \defineatsigncommand @A{\adjustcolrule}%
+ \defineatsigncommand @C{\nointerrowskip}%
+ \defineatsigncommand @N{\nocolrule}%
+ \defineatsigncommand @S{\skipabovespannerrule}%
+ \defineatsigncommand @T{\skipbelowspannerrule}%
+ \tabskip = \leftskip
+ \halign \if \dimneqlp{\width}{\naturalwidth}to \width \fi \bgroup
+ #2\tabskip = \rightskip\cr}
+
+\def \endtabular {%
+ \egroup % \halign
+ \if \posp{\prevdepth}% % Does the last line have a strut?
+ \kern -.5\interrowskip % To eliminate row strut depth.
+ \prevdepth = \dp\strutbox
+ \else
+ \prevdepth = \tabruleheight
+ \fi
+ \futurelet\nexttoken \zendtabular}
+
+\def \zendtabular {%
+ \endtabularformat
+ \global\decrement \tabulardepth
+ \endblockscope{tabular}%
+ \parnext}
+
+\def \tabularformat {%
+ \the\bodyfont
+ \calculate \tdimena = {\interrowskip,/,2,+,\ht\strutbox}%
+ \calculate \tdimenb = {\interrowskip,/,2,+,\dp\strutbox}%
+ \setbox \zrowstrut = \hbox{\vrule width 0pt
+ height \tdimena depth \tdimenb}%
+ \setbox \zparcelltopstrut = \hbox{\vrule width 0pt
+ height \tdimena depth 0pt}%
+ \setbox \zparcellbotstrut = \hbox{\vrule width 0pt
+ height 0pt depth \tdimenb}%
+ \bbskipabove{\abovepenalty}{\aboveskip}%
+ \fakepar % This fakes an empty paragraph
+ \hbox{}% % so the \bbskipabove works.
+ \nobreak
+ \vskip \if \hastoprule -\tabruleheight \else -\ht\zrowstrut \fi
+ \alterindentation{\leftindent}{\rightindent}}
+
+\def \endtabularformat{%
+ \bbskipbelowblockpar{\nexttoken}{\belowpenalty}{\belowskip}}
+
+\def \zchecktabcols #1#2#3&#4\zmark{%
+ \if \notp{\tokeqlp{#1}{\set}}%
+ \error{misset}{A tabular column template must begin with \string\set}%
+ \fi
+ \if \posp{\tabcolcount}%
+ \ztabspacetoks = \expandafter{\the\ztabspacetoks &}%
+ \fi
+ \if \notp{\tokeqlp{#2}{\rulecol}}%
+ \ztabspacetoks = \expandafter{\the\ztabspacetoks \omit \ztabspacestrut}%
+ \fi
+ \increment \tabcolcount
+ \if \notp{\emptyargp{#4}}\zchecktabcols #4\zmark \fi}
+
+% Template Facilities
+% -------- ----------
+
+
+% The following macros are used to construct the tabular template.
+% They are all used with the \set macro.
+
+\def \centercol {%
+ \hfil ##\rowstrut \hfil \tabskip=\columngutter}
+
+\def \centernumbercol #1{% {template}
+ \hfil \znumcell{#1}{##}\rowstrut \hfil \tabskip=\columngutter}
+
+\let \gutter = \tabskip
+
+\def \customcol #1{% {template}
+ #1\rowstrut \tabskip=\columngutter}
+
+\def \customrulecol #1#2{% {color}{width}
+ \color{#1}%
+ \vrule width #2 ##%
+ \endcolor \tabskip=\columngutter}
+
+\def \emptycol #1{% {width}
+ ##\rowstrut \hspace{#1}\tabskip=\columngutter}
+
+\def \leftcol {%
+ ##\rowstrut \hfil \tabskip=\columngutter}
+
+\def \leftnumbercol #1{% {template}
+ \znumcell{#1}{##}\rowstrut \hfil \tabskip=\columngutter}
+
+\def \parcol #1{% {width}
+ \vtop{\zpushvcontext
+ \zinitparcell{#1}{\parhang}%
+ \unhcopy \zparcelltopstrut ##%
+ \if \hmodep \unhcopy \zparcellbotstrut \par \fi
+ \zpopvcontext}%
+ \tabskip=\columngutter}
+
+\def \rightcol {%
+ \hfil ##\rowstrut \tabskip=\columngutter}
+
+\def \rightnumbercol #1{% {template}
+ \hfil \znumcell{#1}{##}\rowstrut \tabskip=\columngutter}
+
+\def \rulecol {%
+ \color{\the\tabrulecolor}%
+ \vrule width \rulecolwidth ##%
+ \endcolor \tabskip=\columngutter}
+
+% Cell Facilities
+% ---- ----------
+
+
+% The following macros help with tabular entries (cells).
+
+\def \0{\phantom{0}}
+
+\def \centercell #1{% {text}
+ \omit
+ \hfil #1\rowstrut \hfil}
+
+\def \centerhead #1{% {heading}
+ \centercell{\the\colheadfont #1}}
+
+\def \centernumbercell #1#2{% {template}{text}
+ \omit
+ \hfil \znumcell{#1}{#2}\rowstrut \hfil}
+
+\def \cutinhead #1{% {heading}
+ \skipabovetabsection
+ \multispan{\tabcolcount}%
+ \leftcell{\the\cutinheadfont #1}\cr
+ \skipbelowtabsection}
+
+\zremovePlaindef \hideskip
+\defineskip{\hideskip}{-1000pt plus 1fill}
+
+\def \hidewidth {\hskip \hideskip}
+
+\def \leftcell #1{% {text}
+ \omit
+ #1\rowstrut \hfil}
+
+\def \lefthead #1{% {heading}
+ \leftcell{\the\colheadfont #1}}
+
+\def \leftnumbercell #1#2{% {template}{text}
+ \omit
+ \znumcell{#1}{#2}\rowstrut \hfil}
+
+\def \multispan #1{% {columns}
+ \omit
+ \tcounta = #1%
+ \loop \ifnum \tcounta > 1 \zspan \repeat
+ \let \omit = \relax % In case the next thing is a \leftcell or whatever.
+ \ignorespaces}
+
+\def \zspan {\span\omit \decrement \tcounta}
+
+\def \parcell #1#2{% {width}{text}
+ \omit
+ \vtop{\zpushvcontext
+ \zinitparcell{#1}{\parhang}%
+ \unhcopy \zparcelltopstrut #2%
+ \if \hmodep \unhcopy \zparcellbotstrut \par \fi
+ \zpopvcontext}}
+
+\def \rightcell #1{% {text}
+ \omit
+ \hfil #1\rowstrut}
+
+\def \righthead #1{% {heading}
+ \rightcell{\the\colheadfont #1}}
+
+\def \rightnumbercell #1#2{% {template}{text}
+ \omit
+ \hfil \znumcell{#1}{#2}\rowstrut}
+
+\def \rowstrut {%
+ \unhcopy \zrowstrut}
+
+\def \sidehead #1{% {heading}
+ \leftcell{\the\sideheadfont #1}}
+
+\def \spannerhead #1#2{% {columns}{heading}
+ \multispan{#1}%
+ \centercell{\the\spannerheadfont #2}}
+
+\def \tabnote #1{% {note-mark}
+ {\tabnoteformat{#1}}}
+
+\def \znumcell #1#2{% {template}{text}
+ \if \emptyargp{#2}%
+ \relax
+ \else
+ \znumcella{#1}{#2}%
+ \fi}
+
+\def \znumcella #1#2{% {template}{text}
+ {\ztoksa = {}\ztoksb = {}%
+ \setflag \znumpt = \false
+ \znumcellb #1\zmark
+ \setbox\zboxa = \hbox{\the\ztoksa}%
+ \tdimena = \wd\zboxa
+ \setbox\zboxa = \hbox{\the\ztoksb}%
+ \tdimenb = \wd\zboxa
+ \setflag \ztempt = \znumpt
+ \ztoksa = {}\ztoksb = {}%
+ \setflag \znumpt = \false
+ \znumcellb #2\zmark
+ \if \ztempt % Template had a decimal point.
+ \if \znumpt
+ \hbox to \tdimena{\hss \the\ztoksa}%
+ \the\decimalpoint
+ \hbox to \tdimenb{\the\ztoksb \hss}%
+ \else
+ \setbox\zboxa = \hbox{\the\decimalpoint}%
+ \hbox to \tdimena{\hss \the\ztoksa}%
+ \kern \wd\zboxa \kern \tdimenb
+ \fi
+ \else % Template had no decimal point.
+ \if \znumpt
+ \error{celldecpt}{Tabular template did not specify a decimal point}%
+ \else
+ \hbox to \tdimena{\hss \the\ztoksa}%
+ \fi
+ \fi}}
+
+\def \znumcellb #1#2\zmark{% t1 trest \zmark
+ \if \codeeqlp{\noexpand#1}{\the\decimalpoint}%
+ \setflag \znumpt = \true
+ \else
+ \if \znumpt
+ \ztoksb = \expandafter{\the\ztoksb #1}%
+ \else
+ \ztoksa = \expandafter{\the\ztoksa #1}%
+ \fi
+ \fi
+ \if \emptyargp{#2}%
+ \let \znext = \relax
+ \else
+ \def \znext {\znumcellb #2\zmark}%
+ \fi
+ \znext}
+
+% Rule Facilities
+% ---- ----------
+
+
+\def \adjustcolrule #1,#2,#3;{% width,height,depth;
+ \if \notp{\emptyargp{#1}}width #1pt\fi
+ \if \notp{\emptyargp{#2}}height #2pt\fi
+ \if \notp{\emptyargp{#3}}depth #3pt\fi\relax}
+
+\def \custompartialtabrule #1#2#3{% {color}{thickness}{columns}
+ \multispan{#3}%
+ \color{#1}%
+ \ruleleaders{\hrule height #2 depth 0pt}%
+ \endcolor}
+
+\def \customspannerrule #1#2#3{% {color}{thickness}{columns}
+ \multispan{#3}%
+ \rowstrut
+ \color{#1}%
+ \ruleleaders{\hrule height #2 depth 0pt}%
+ \endcolor}
+
+\def \customtabrule #1#2{% {color}{thickness}
+ \multispan{\tabcolcount}%
+ \color{#1}%
+ \ruleleaders{\hrule height #2 depth 0pt}%
+ \endcolor\cr}
+
+\def \nocolrule {%
+ width 0pt }
+
+\def \partialtabrule #1{% {columns}
+ \custompartialtabrule{\the\tabrulecolor}{\tabruleheight}{#1}}
+
+\def \spannerrule #1{% {columns}
+ \customspannerrule{\the\spannerrulecolor}{\spannerruleheight}{#1}}
+
+\def \tabbottomrule {%
+ \tabbbskipaboverule{\tabbottomruleaboveskip}%
+ \tabrule}
+
+\def \tabheadrule {%
+ \tabbbskipaboverule{\colheadbelowskip}%
+ \tabrule
+ \tabbbskipbelowrule{\tabheadrulebelowskip}}
+
+\def \tabrule {%
+ \customtabrule{\the\tabrulecolor}{\tabruleheight}}
+
+\def \tabtoprule {%
+ \tabrule
+ \tabbbskipbelowrule{\colheadaboveskip}}
+
+% Spacing Facilities
+% ------- ----------
+
+
+\definedimen{\zskipamount}{0pt}
+
+
+\def \nointerrowskip {%
+ \tabvspace{-\interrowskip}}
+
+\def \skipabovecolhead {%
+ \tabbbskip{\colheadaboveskip}}
+
+\def \skipbelowcolhead {%
+ \tabbbskip{\colheadbelowskip}}
+
+\def \skipabovespannerrule {%
+ \tabbbskip{\spannerruleaboveskip}}
+
+\def \skipbelowspannerrule {%
+ \tabbbskip{\spannerrulebelowskip}}
+
+\def \skipabovetabsection {%
+ \tabbbskip{\sectionheadaboveskip}}
+
+\def \skipbelowtabsection {%
+ \tabbbskip{\sectionheadbelowskip}}
+
+\def \tabbbskip #1{%
+ \noalign{%
+ \calculate \zskipamount = {#1,-,\dp\zrowstrut,-,\ht\zrowstrut}%
+ \ztabvspace{\zskipamount}}%
+ \the\ztabspacetoks\cr}
+
+\def \tabbbskipaboverule #1{%
+ \noalign{%
+ \calculate \zskipamount = {#1,-,\dp\zrowstrut,-,\tabruleheight}%
+ \ztabvspace{\zskipamount}}%
+ \the\ztabspacetoks\cr}
+
+\def \tabbbskipbelowrule #1{%
+ \noalign{%
+ \calculate \zskipamount = {#1,-,\ht\zrowstrut,-,\tabruleheight}%
+ \ztabvspace{\zskipamount}}%
+ \the\ztabspacetoks\cr}
+
+\def \tabvspace #1{%
+ \noalign{\ztabvspace{#1}}%
+ \the\ztabspacetoks\cr}
+
+\def \ztabvspace #1{%
+ \if \dimnegp{#1}%
+ \vskip #1\relax
+ \global\zskipamount = 0pt
+ \else
+ \global\zskipamount = #1%
+ \fi}
+
+\def \ztabspacestrut {%
+ \vrule width 0pt height 0pt depth \zskipamount\relax}
+
+% Inter-Row Facilities
+% --------- ----------
+
+
+\def \adjusttab #1{%
+ \if \notp{\vmodep}%
+ \error{badrowcmd}{The \string\adjusttab command cannot be used
+ in a table row}%
+ \fi
+ \noalign{#1}}
+
+
+% Utilities
+% ---------
+
+
+\let \completerow = \cr
+
+\def \ialign {\everycr = {}\tabskip = 0pt \halign}
+
+\def \oalign #1{% {row...}
+ \ensurepar
+ \vtop{\baselineskip = 0pt
+ \lineskip = .25ex
+ \ialign{##\cr #1\crcr}}}
+
+\def \ooalign {%
+ \lineskiplimit = -\maxdimen
+ \oalign}
+
+\def \ozalign {%
+ \lineskiplimit = 0pt\relax
+ \oalign}
+
+\def \zinitparcell #1#2{% {width}{hang}
+ \baselineskip = \normalbaselineskip
+ \lineskiplimit = 0pt \lineskip = 0pt
+ \setindentation{0pt}{0pt}%
+ \settextwidth{#1}%
+ \setparrag{\parrag}%
+ \leftskip = #2
+ \parindent = -#2
+ \parfillskip = \normalparfillskip}
diff --git a/macros/plain/contrib/zztex/tex/zztabularv3.tex b/macros/plain/contrib/zztex/tex/zztabularv3.tex
new file mode 100644
index 0000000000..c7035daa73
--- /dev/null
+++ b/macros/plain/contrib/zztex/tex/zztabularv3.tex
@@ -0,0 +1,771 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% Module: ZzTeX Tabular Facilities, version 3
+%
+% Synopsis: This module contains all the facilities for producing
+% tabular material. This is the third major version.
+%
+% Author: Paul C. Anagnostopoulos
+% Created: 4 June 2004
+%
+% Copyright 1989--2020 by Paul C. Anagnostopoulos
+% under The MIT License (opensource.org/licenses/MIT)
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% Tabular Block
+% ------- -----
+
+
+\defineblock{\tabular}{\endtabular}{\false}{}
+
+%~block tabular Type
+% \abovepenalty = integer % Penalty above text.
+% \aboveskip = glue % Space b/b above text.
+% \belowpenalty = integer % Penalty below text.
+% \belowskip = glue % Space b/b below text.
+% \bodyfont = {font} % Body font.
+% \columngutter = glue % Width of column gutter.
+% \colheadbelowskip = dimen % Space b/b below column heads.
+% \colheadcolor = {color} % Color of Column heads.
+% \colheadfont = {font} % Column head font.
+% \interrowskip = dimen % Extra space between rows.
+% \leftindent = glue % Left indentation.
+% \parhang = dimen % Paragraph column hang.
+% \parrag = dimen % Paragraph raggedness.
+% \parskip = skip % Paragraph skip.
+% \rightindent = glue % Right indentation.
+% \rulecolcolor = {color} % Color of table rules.
+% \rulecolwidth = dimen % Width of column rules.
+% \sideheadaboveskip = dimen % Space b/b above side heads.
+% \sideheadbelowskip = dimen % Space b/b below side heads.
+% \sideheadcolor = {color} % Color of side heads.
+% \sideheadfont = {font} % Side head font.
+% \spannerheadcolor = {color} % Color of spanner heads.
+% \spannerheadfont = {font} % Spanner head font.
+% \spannerruleaboveskip = dimen % Space b/b above spanner rules.
+% \spannerrulebelowskip = dimen % Space b/b below spanner rules.
+% \spannerrulecolor = {color} % Color of spanner rules.
+% \spannerruleheight = dimen % Spanner rule thickness.
+% \style = {...} % Style description.
+% \tabbottomruleaboveskip = dimen % Space b/b above bottom rules.
+% \tabheadrulebelowskip = dimen % Space b/b below head rules.
+% \def \tabnoteformat ##1{...} % Format of table note references.
+% \tabrulecolor = {color} % Color of table rules.
+% \tabruleheight = dimen % Table rule thickness.
+% \tabtoprulebelowskip = dimen % Space b/b below top rules.
+% \width = dimen % Width of tabular material.
+%~end
+
+\defineskip{\colheadbelowskip}{0pt}
+\definetoks{\colheadcolor}
+\definetoks{\colheadfont}
+\definetoks{\rulecolcolor}
+\definedimen{\rulecolwidth}{0pt}
+\definedimen{\sideheadaboveskip}{0pt}
+\definedimen{\sideheadbelowskip}{0pt}
+\definetoks{\sideheadcolor}
+\definetoks{\sideheadfont}
+\definetoks{\spannerheadcolor}
+\definetoks{\spannerheadfont}
+\definedimen{\spannerruleaboveskip}{0pt}
+\definedimen{\spannerrulebelowskip}{0pt}
+\definetoks{\spannerrulecolor}
+\definedimen{\spannerruleheight}{0pt}
+\definedimen{\tabbottomruleaboveskip}{0pt}
+\definedimen{\tabheadrulebelowskip}{0pt}
+\definetoks{\tabrulecolor}
+\definedimen{\tabruleheight}{0pt}
+\definedimen{\tabtoprulebelowskip}{0pt}
+
+
+\def \tabular #1#2{% {type}{template}
+ \endgraf
+ \beginblockscope{tabular}%
+ \global\increment \tabulardepth
+ \abovepenalty = \breakgood %~default hard
+ \belowpenalty = \breakbetter %~default hard
+ \processdesign{\tabular}{#1}%
+ \global\increment \tabularnumber
+ \zsetuptabular{#2}%
+ \tabularformat
+ \defineatsigncommand @A{\adjustcolrule}%
+ \defineatsigncommand @C{\closeuprows}%
+ \defineatsigncommand @N{\nocolrule}%
+ \defineatsigncommand @S{\skipabovespannerrule}%
+ \defineatsigncommand @T{\skipbelowspannerrule}%
+ \offinterlineskip
+ \nobreak
+ \tabskip=\leftskip
+ \halign \if \dimneqlp{\width}{\naturalwidth}to \width \fi \bgroup
+ \span\the\zpreamble \tabskip=\rightskip \cr}
+
+\def \endtabular {%
+ \crcr
+ \egroup % \halign
+ \if \posp{\prevdepth}% % Does the last line have a strut?
+ \kern -.5\interrowskip % Yes, eliminate extra depth from
+ \prevdepth = \dp\strutbox % \interrowskip.
+ \else
+ \prevdepth = \tabruleheight % No, compensate for bottom rule.
+ \fi
+ \futurelet\nexttoken \zendtabular}
+
+\def \zendtabular {%
+ \endtabularformat
+ \global\decrement \tabulardepth
+ \endblockscope{tabular}%
+ \parnext}
+
+\def \tabularformat {%
+ \bbskipabove{\abovepenalty}{\aboveskip}%
+ \fakepar % This empty paragraph allows
+ \hbox{}% % the \bbskipabove to work.
+ \kern
+ \if \dimzerop{\tabtoprulebelowskip}-\ht\zrowstrut \else -\tabruleheight \fi
+ \alterindentation{\leftindent}{\rightindent}}
+
+\def \endtabularformat{%
+ \bbskipbelowblockpar{\nexttoken}{\belowpenalty}{\belowskip}}
+
+\def \adjustcolumngutter #1{% {amount} %^tabular
+ \with{\advance\columngutter by #1}}
+
+\def \adjustinterrowskip #1{% {amount} %^tabular
+ \with{\advance\interrowskip by #1}}
+
+% Set Up Tabular
+% --- -- -------
+
+
+\definecount{\tabcolcount}{0} % Number of columns in table.
+\definetoks{\zpreamble} % Preamble for \halign.
+\definetoks{\ztabspacerow} % Special row for vertical spacing.
+\definebox{\zrowstrut} % Strut for table rows.
+\definebox{\zparcelltopstrut} % Strut for first line of par cell.
+\definebox{\zparcellbotstrut} % Strut for last line of par cell.
+
+\def \zsetuptabular #1{% {template}
+ \zanaltemplate{#1}%
+ \the\bodyfont
+ \calculate \tdimena = {\interrowskip,/,2,+,\ht\strutbox}%
+ \calculate \tdimenb = {\interrowskip,/,2,+,\dp\strutbox}%
+ \setbox \zrowstrut = \hbox{\vrule width 0pt
+ height \tdimena depth \tdimenb}%
+ \setbox \zparcelltopstrut = \hbox{\vrule width 0pt
+ height \tdimena depth 0pt}%
+ \setbox \zparcellbotstrut = \hbox{\vrule width 0pt
+ height 0pt depth \tdimenb}%
+ \global\zprevrowclass = \zrcpream
+ \global\zcurrowclass = \zrcpream
+ \gdef \zcolrulegate {}%
+ \global\setflag \zcolrulesenabled = \false
+ \everycr = {\noalign{\ztabcr}}}
+
+% Analyze Template
+% ------- --------
+
+
+\defineskip{\zpendgutter}{0pt}
+
+
+\def \zanaltemplate #1{% {template}
+ \setbox\zboxa = \hbox{%
+ \defineatsigncommand @!{\zcustomrulecol}%
+ \defineatsigncommand @>{\zgutterspec}%
+ \defineatsigncommand @c{\zcentercol}%
+ \defineatsigncommand @C{\zcenternumbercol}%
+ \defineatsigncommand @e{\zemptycol}%
+ \defineatsigncommand @l{\zleftcol}%
+ \defineatsigncommand @L{\zleftnumbercol}%
+ \defineatsigncommand @p{\zparcol}%
+ \defineatsigncommand @r{\zrightcol}%
+ \defineatsigncommand @R{\zrightnumbercol}%
+ \defineatsigncommand @s{\zspecialcol}%
+ \defineatsigncommand @|{\zrulecol}%
+ \global\tabcolcount = 0
+ \global\zpreamble = {}%
+ \global\ztabspacerow = {}%
+ #1}%
+ \tabcolcount = \tabcolcount
+ \zpreamble = \zpreamble
+ \ztabspacerow = \ztabspacerow}
+
+\def \zcentercol {%
+ \zstartcol{\false}%
+ \zappendpreamble{\hfil ##\rowstrut \hfil}}
+
+\def \zcenternumbercol #1{%
+ \zstartcol{\false}%
+ \zmeasuredanumber #1..\zmark
+ \edef \znext {%
+ \noexpand\zappendpreamble{%
+ \hfil \noexpand\zsetnumbercell{\the\tdimena}{\the\tdimenb}{####}\hfil}}%
+ \znext}
+
+\def \zcustomrulecol #1#2{% {color}{width}
+ \if \dimeqlp{\zpendgutter}{\mindimen}\zpendgutter = .5\columngutter \fi
+ \zstartcol{\true}%
+ \zappendpreamble{\zsetcolrule{#1}{#2}{##}}%
+ \zpendgutter = .5\columngutter}
+
+\def \zemptycol #1{% {width}
+ \zstartcol{\false}%
+ \zappendpreamble{##\rowstrut \hspace{#1}}}
+
+\def \zgutterspec #1{% {width}
+ \zparsegutterspec #1*\zmark}
+
+\def \zparsegutterspec #1*#2\zmark{%
+ \zpendgutter = #1\relax
+ \if \notp{\emptyargp{#2}}%
+ \advance \zpendgutter by \columngutter
+ \advance \zpendgutter by -1\columngutter
+ \fi}
+
+\def \zleftcol {%
+ \zstartcol{\false}%
+ \zappendpreamble{##\rowstrut \hfil}}
+
+\def \zleftnumbercol #1{%
+ \zstartcol{\false}%
+ \zmeasuredanumber #1..\zmark
+ \edef \znext {%
+ \noexpand\zappendpreamble{%
+ \noexpand\zsetnumbercell{\the\tdimena}{\the\tdimenb}{####}\hfil}}%
+ \znext}
+
+\def \zparcol #1{% {width}
+ \zstartcol{\false}%
+ \zappendpreamble{\zsetparcol{#1}{##}}}
+
+\def \zrightcol {%
+ \zstartcol{\false}%
+ \zappendpreamble{\hfil ##\rowstrut}}
+
+\def \zrightnumbercol #1{%
+ \zstartcol{\false}%
+ \zmeasuredanumber #1..\zmark
+ \edef \znext {%
+ \noexpand\zappendpreamble{%
+ \hfil \noexpand\zsetnumbercell{\the\tdimena}{\the\tdimenb}{####}}}%
+ \znext}
+
+\def \zrulecol {%
+ \if \dimeqlp{\zpendgutter}{\mindimen}\zpendgutter = .5\columngutter\relax \fi
+ \zstartcol{\true}%
+ \zappendpreamble{\zsetcolrule{}{}{##}}%
+ \zpendgutter = .5\columngutter\relax}
+
+\def \zspecialcol #1{% {template}
+ \zstartcol{\false}%
+ \zappendpreamble{#1\rowstrut}}
+
+\def \zstartcol #1{% {rule-column?}
+ \if \posp{\tabcolcount}%
+ \if \dimeqlp{\zpendgutter}{\mindimen}\zpendgutter = \columngutter \fi
+ \edef \znext {\noexpand\zappendpreamble{\tabskip=\the\zpendgutter &}}%
+ \znext
+ \global\ztabspacerow = \expandafter{\the\ztabspacerow &}%
+ \fi
+ \global\increment \tabcolcount
+ \if \notp{#1}%
+ \global\ztabspacerow = \expandafter{\the\ztabspacerow
+ \omit \copy \ztabvspacebox}%
+ \fi
+ \zpendgutter = \mindimen}
+
+\def \zappendpreamble #1{% {preamble stuff}
+ \global\zpreamble = \expandafter{\the\zpreamble #1}}
+
+% Preamble Helpers
+% -------- -------
+
+
+\def \zmeasuredanumber #1.#2.#3\zmark{%
+ \measuretextwidth{\tdimena}{#1}%
+ \measuretextwidth{\tdimenb}{.#2}%
+ \if \andp{\emptyargp{#2}}{\emptyargp{#3}}\tdimenb = 0pt\fi}
+
+\def \zsetcolrule #1#2#3{% {color}{width}{adjustment}
+ \if \emptyargp{#1}\color{\the\tabrulecolor}\else \color{#1}\fi
+ \vrule width \if \emptyargp{#2}\rulecolwidth \else #2\fi
+ \zcolrulegate #3%
+ \endcolor}
+
+\def \zsetnumbercell #1#2#3{% {pre-width}{post-width}{text}
+ \gdef \zcellstyle {}%
+ \zsplitdanumber #3..\zmark
+ \if \dimzerop{#2}%
+ \if \emptytoksp{\ztoksb}%
+ \hbox to #1{\hfil \the\ztoksa}%
+ \else
+ \error{celldecpt}{Template picture did not include a decimal point}%
+ \fi
+ \else
+ \hbox to #1{\hfil \the\ztoksa}%
+ \hbox to #2{\zcellstyle \the\ztoksb \hfil}%
+ \fi
+ \rowstrut}
+
+\long\def \zsetparcol #1#2{% {width}{text}
+ \vtop{%
+ \zpushvcontext
+ \baselineskip = \normalbaselineskip
+ \lineskiplimit = 0pt \lineskip = 0pt
+%%% \setindentation{0pt}{0pt}%
+ \settextwidth{#1}%
+ \setparrag{\parrag}%
+ \leftskip = \parhang
+ \parindent = -\parhang
+ \parfillskip = \normalparfillskip
+ \unhcopy \zparcelltopstrut
+ #2%
+ \if \hmodep \unhcopy \zparcellbotstrut \par \fi
+ \zpopvcontext}}
+
+\def \zsplitdanumber #1.#2.#3\zmark{%
+ \ztoksa = {#1}%
+ \ztoksb = {.#2}%
+ \if \andp{\emptyargp{#2}}{\emptyargp{#3}}\ztoksb = {}\fi}
+
+% Row Class
+% --- -----
+
+
+\definecount{\zprevrowclass}{0}
+\definecount{\zcurrowclass}{0}
+
+\chardef \zrcpream = 0
+\chardef \zrcdata = 1
+\chardef \zrchead = 2
+\chardef \zrcrule = 3
+\chardef \zrcvspace = 4
+\chardef \zrcbbskip = 5
+
+\def \zsetrowclass #1{%
+ \if \gtrp{#1}{\zcurrowclass}\global\zcurrowclass = #1\relax \fi}
+
+\def \ztabcr {%
+ \global\zprevrowclass = \zcurrowclass
+ \global\zcurrowclass = \zrcdata
+ \global\setflag \zcolrulesenabled = \false}
+
+% Cell Facilities
+% ---- ----------
+
+
+%~ This command produces a phantom zero, which is useful for aligning
+%~ numbers when decimal-aligned columns are not being used.
+
+\def \0{\phantom{0}} %^tabular
+
+\zremovePlaindef \hideskip
+\defineskip{\hideskip}{-1000pt plus 1fill}
+
+%~ This command "hides" the width of the cell from the column width calculation
+%~ process. The cell does not participate in determining the widest cell of
+%~ the column. If the cell is wider than the calculated column width, it will
+%~ stick into the left or right column gutter, depending on the position of the
+%~ |\hidewidth| command.
+
+\def \hidewidth {\hskip \hideskip} %^tabular
+
+%~ This command discards the templates for the specified number of columns and
+%~ creates one cell that spans them all. The content of the cell is specified
+%~ immediately following the command. This spanning cell has no template, so
+%~ you must include all the required commands in the cell text. This is usually done
+%~ using one of the cell override commands such as |\leftcell|.
+
+\def \multispan #1{% {columns} %^tabular
+ \omit
+ \tcounta = #1%
+ \loop \ifnum \tcounta > 1 \zspan \repeat
+ \let \omit = \relax % In case the next thing is a \leftcell or whatever.
+ \ignorespaces}
+
+\def \zspan {\span\omit \decrement \tcounta}
+
+\def \rowstrut {%
+ \unhcopy \zrowstrut}
+
+\def \zcellstyle {}
+
+\def \setcellstyle #1{%
+ #1%
+ \gdef \zcellstyle {#1}%
+ \ignorespaces}
+
+%~ This command sets a table note reference, usually a lowercase
+%~ letter. The format of the reference is determined by the design.
+
+\def \tabnote #1{% {note-mark} %^tabular
+ {\tabnoteformat{#1}}}
+
+% Cell Overrides
+% ---- ---------
+
+
+%~ This command overrides the template for the column and sets
+%~ a centered cell. It must appear immediately after the
+%~ ampersand (|&&|) that begins the cell.
+
+\def \centercell #1{% {text} %^tabular
+ \omit
+ \hfil #1\rowstrut \hfil}
+
+%~ This command overrides the template for the column and sets
+%~ a flush left cell. It must appear immediately after the
+%~ ampersand (|&&|) that begins the cell.
+
+\def \leftcell #1{% {text} %^tabular
+ \omit
+ #1\rowstrut \hfil}
+
+%~ This command overrides the template for the column and sets
+%~ a paragraph cell. It must appear immediately after the
+%~ ampersand (|&&|) that begins the cell.
+
+\def \parcell #1#2{% {width}{text} %^tabular
+ \omit
+ \zsetparcol{#1}{#2}}
+
+%~ This command overrides the template for the column and sets
+%~ a flush right cell. It must appear immediately after the
+%~ ampersand (|&&|) that begins the cell.
+
+\def \rightcell #1{% {text} %^tabular
+ \omit
+ \hfil #1\rowstrut}
+
+% Column Heads
+% ------ -----
+
+
+%~ This column head command produces a centered head.
+
+\def \centerhead #1{% {heading} %^tabular
+ \centercell{%
+ \the\colheadfont \colortext{\the\colheadcolor}{#1}%
+ \zchkadjheads}}
+
+%~ This column head command produces a flush left head.
+
+\def \lefthead #1{% {heading} %^tabular
+ \leftcell{%
+ \the\colheadfont \colortext{\the\colheadcolor}{#1}%
+ \zchkadjheads}}
+
+%~ This column head command produces a flush right head.
+
+\def \righthead #1{% {heading} %^tabular
+ \rightcell{%
+ \the\colheadfont \colortext{\the\colheadcolor}{#1}%
+ \zchkadjheads}}
+
+%~ This command produces a spanner head that spans the specified
+%~ number of columns.
+
+\def \spannerhead #1#2{% {columns}{heading} %^tabular
+ \multispan{#1}%
+ \centercell{\the\spannerheadfont \colortext{\the\spannerheadcolor}{#2}}%
+ \zsetrowclass{\zrchead}}
+
+\def \zchkadjheads {%
+ \if \andp{\eqlp{\zprevrowclass}{\zrchead}}{\posp{\interrowskip}}%
+ \warning{adjheads}{Two adjacent rows of heads need to be closed up}%
+ \global\zprevrowclass = \zrcdata
+ \fi
+ \zsetrowclass{\zrchead}}
+
+% Side Heads
+% ---- -----
+
+%~ This command is a shorthand for producing a cut-in head that spans the
+%~ entire width of the table. It is equivalent to:
+%~
+%~ | \skipabovesidehead
+%~ | \sidehead{*all-columns*}{*heading*}\cr
+%~ | \skipbelowsidehead
+
+\def \cutinhead #1{% {heading} %^tabular
+ \skipabovesidehead
+ \sidehead{\tabcolcount}{#1}\cr
+ \skipbelowsidehead}
+
+%~ This command produces a side head that spans the specified number of
+%~ columns. It is similar to |\spannerhead|. It is almost always the case that a
+%~ |\sidehead| row should be preceded by a |\skipabovesidehead| and followed by a
+%~ |\skipbelowsidehead|.
+
+\def \sidehead #1#2{% {columns}{heading} %^tabular
+ \multispan{#1}%
+ \leftcell{\the\sideheadfont \colortext{\the\sideheadcolor}{#2}}}
+
+% Vertical Spacing
+% -------- -------
+
+
+%~ This command eliminates the inter-row space between two rows. It must be
+%~ used between two consective rows of table heads. Shorthand: |@C|.
+
+\def \closeuprows {% %^tabular
+ \tabvspace{-\interrowskip}}
+
+%~ This command adds extra space between column heads and the first data row.
+%~ It must be used in tables that do not have head rules.
+
+\def \skipbelowcolhead {% %^tabular
+ \zchkbelowhead
+ \tabbbskip{\colheadbelowskip}}
+
+%~ This command produces the appropriate vertical space above
+%~ a spanner rule. Shorthand: |@S|. See also |\skipbelowspannerrule|.
+
+\def \skipabovespannerrule {% %^tabular
+ \tabbbskip{\spannerruleaboveskip}}
+
+%~ This command produces the appropriate vertical space below
+%~ a spanner rule. Shorthand: |@T|. See also |\skipabovespannerrule|.
+
+\def \skipbelowspannerrule {% %^tabular
+ \tabbbskip{\spannerrulebelowskip}}
+
+%~ This command produces the appropriate vertical space above
+%~ a side head. See also |\skipbelowsidehead|.
+
+\def \skipabovesidehead {% %^tabular
+ \tabbbskip{\sideheadaboveskip}}
+
+%~ This command produces the appropriate vertical space below
+%~ a side head. See also |\skiabovewsidehead|.
+
+\def \skipbelowsidehead {% %^tabular
+ \tabbbskip{\sideheadbelowskip}}
+
+%~ This command produces extra vertical space so that the base-to-base space
+%~ between the preceding and following rows is as specified.
+
+\def \tabbbskip #1{% {amount} %^tabular
+ \ztabbbskip{#1,-,\dp\zrowstrut,-,\ht\zrowstrut}%
+ \the\ztabspacerow\cr}
+
+%~ This command produces extra vertical space between a row and a rule.
+%~ It must be used instead of |\tabbbskip| to obtain the desired results when
+%~ spacing above horizontal rules. See also |\tabbbskipbelowrule|.
+
+\def \tabbbskipaboverule #1{% {amount} %^tabular
+ \noalign{\nobreak}%
+ \ztabbbskip{#1,-,\dp\zrowstrut,-,\tabruleheight}%
+ \noalign{\if \zcolrulesenabled \zsuppresscolrules \fi}%
+ \the\ztabspacerow \if \zcolrulesenabled \zallowcolrules \fi\cr
+ \noalign{\nobreak}}
+
+%~ This command produces extra vertical space between a rule and a row.
+%~ It must be used instead of |\tabbbskip| to obtain the desired results when
+%~ spacing below horizontal rules. See also |\tabbbskipaboverule|.
+
+\def \tabbbskipbelowrule #1{% {amount} %^tabular
+ \ztabbbskip{#1,-,\ht\zrowstrut}%
+ \the\ztabspacerow\cr}
+
+%~ This command produces the specified amount of extra vertical space
+%~ between two rows of the table.
+
+\def \tabvspace #1{% {amount} %^tabular
+ \noalign{%
+ \zsetrowclass{\zrcvspace}%
+ \zsetvspacebox{#1}}%
+ \the\ztabspacerow\cr}
+
+\def \ztabbbskip #1{%
+ \noalign{%
+ \zsetrowclass{\zrcbbskip}%
+ \if \eqlp{\zprevrowclass}{\zrcbbskip}%
+ \tdimena = 0pt\relax
+ \else
+ \calculate \tdimena = {#1}%
+ \fi
+ \zsetvspacebox{\tdimena}}}
+
+\definebox{\ztabvspacebox}
+\setbox \ztabvspacebox = \hbox{}%
+
+\def \zsetvspacebox #1{%
+ \if \dimnegp{#1}%
+ \vskip #1\relax
+ \dp\ztabvspacebox = 0pt
+ \else
+ \dp\ztabvspacebox = #1\relax
+ \fi}
+
+\def \zchkbelowhead {%
+ \noalign{%
+ \if \neqlp{\zprevrowclass}{\zrchead}%
+ \warning{needheads}{The previous row should be a row of column heads}%
+ \fi}}
+
+% Horizontal Rules
+% ---------- -----
+
+
+%~ This command produces a custom version of the partial table rule
+%~ (|\partialtabrule|). The color and thickness of the rules is specified
+%~ explicitly.
+
+\def \custompartialtabrule #1#2#3{% {color}{thickness}{columns} %^tabular
+ \multispan{#3}%
+ \color{#1}%
+ \ruleleaders{\hrule height #2 depth 0pt}%
+ \endcolor}
+
+%~ This command produces a custom version of the table spanner rule
+%~ (|\spannerrule|). The color and thickness of the rules is specified
+%~ explicitly.
+
+\def \customspannerrule #1#2#3{% {color}{thickness}{columns} %^tabular
+ \multispan{#3}%
+ \rowstrut
+ \color{#1}%
+ \ruleleaders{\hrule height #2 depth 0pt}%
+ \endcolor}
+
+%~ This command produces a custom version of the table rule
+%~ (|\tabrule|). The color and thickness of the rules is specified
+%~ explicitly.
+
+\def \customtabrule #1#2{% {color}{thickness} %^tabular
+ \multispan{\tabcolcount}%
+ \color{#1}%
+ \ruleleaders{\hrule height #2 depth 0pt}%
+ \endcolor\cr}
+
+%~ This command produces a table rule across the specified number of columns.
+%~ It is similar to |\spannerrule| but sets a rule of the same thickness
+%~ as |\tabrule|.
+
+\def \partialtabrule #1{% {columns} %^tabular
+ \custompartialtabrule{\the\tabrulecolor}{\tabruleheight}{#1}}
+
+%~ This command produces a spanner rule across the specified number of columns.
+%~ The color and thickness of the rule are determined by the design. A row with
+%~ spanner rules is usually preceded and followed by |\skipabovespannerrule| and
+%~ |\skipbelowspannerrule|.
+
+\def \spannerrule #1{% {columns} %^tabular
+ \customspannerrule{\the\spannerrulecolor}{\spannerruleheight}{#1}}
+
+%~ This command produces the standard bottom rule in a table. Which rules are
+%~ required is specified in the |\style| parameter of the |\tabular| design.
+%~ This command is not followed by |\cr|.
+
+\def \tabbottomrule {% %^tabular
+ \tabbbskipaboverule{\tabbottomruleaboveskip}%
+ \tabrule}
+
+%~ This command produces the standard head rule in a table. Which rules are
+%~ required is specified in the |\style| parameter of the |\tabular| design.
+%~ This command is not followed by |\cr|.
+
+\def \tabheadrule {% %^tabular
+ \zchkbelowhead
+ \tabbbskipaboverule{\colheadbelowskip}%
+ \tabrule
+ \tabbbskipbelowrule{\tabheadrulebelowskip}}
+
+%~ This command produces a table rule across the entire width of the table. The
+%~ color and thickness of the rule are determined by the design. This command
+%~ is not followed by |\cr|.
+
+\def \tabrule {% %^tabular
+ \customtabrule{\the\tabrulecolor}{\tabruleheight}}
+
+%~ This command produces the standard top rule in a table. Which rules are
+%~ required is specified in the |\style| parameter of the |\tabular| design.
+%~ This command is not followed by |\cr|.
+
+\def \tabtoprule {% %^tabular
+ \tabrule
+ \noalign{\nobreak}%
+ \tabbbskipbelowrule{\tabtoprulebelowskip}}
+
+% Vertical Rules
+% -------- -----
+
+
+%~ This command is used in the normally empty cell corresponding to a vertical
+%~ rule column. It adjusts the width, height, and/or depth of the rule in that
+%~ cell. To adjust one of those dimensions, specify the new dimension in
+%~ points, without the usual |pt|, in the appropriate argument position.
+%~ Omitted dimensions will have their standard values. You must specify both
+%~ commas and the semicolon. Shorthand: |@A*width*,*height*,*depth*;|
+
+\def \adjustcolrule #1,#2,#3;{% width,height,depth; %^tabular
+ \if \notp{\emptyargp{#1}}width #1pt\fi
+ \if \notp{\emptyargp{#2}}height #2pt\fi
+ \if \notp{\emptyargp{#3}}depth #3pt\fi\relax}
+
+%~ This command can be used between rows of a table to allow all vertical
+%~ rules. This is typically done after the column head portion of a table. If
+%~ |\allowcolrules| appears just before |\tabheadrule|, it is deferred until
+%~ after the vertical space above the horizontal rule, so that the vertical
+%~ rules recommence precisely at the horizontal rule. See also
+%~ |\suppresscolrules|.
+
+\def \allowcolrules {% %^tabular
+ \noalign{%
+ \zallowcolrules
+ \global\setflag \zcolrulesenabled = \true}}
+
+\def \zallowcolrules {%
+ \gdef \zcolrulegate {}}
+
+%~ This command can be used between rows of a table to suppress all vertical
+%~ rules. This is typically done for the column head portion of a table.
+%~ See also |\allowcolrules|.
+
+\def \suppresscolrules {% %^tabular
+ \noalign{\zsuppresscolrules}}
+
+\def \zsuppresscolrules {%
+ \gdef \zcolrulegate {\nocolrule}}
+
+%~ This command is used in the normally empty cell corresponding to a vertical
+%~ rule column. It suppresses the vertical rule in that cell. Shorthand: |@N|.
+
+\def \nocolrule {% %^tabular
+ width 0pt }
+
+% Inter-Row Facilities
+% --------- ----------
+
+
+%~ This command can be used between rows of a table to insert vertical material
+%~ that is independent of the rows themselves. It is rarely needed.
+
+\def \adjusttabular #1{% {commands} %^tabular
+ \noalign{#1}}
+
+\let \adjusttab = \adjusttabular
+
+% Low-Level Alignment Facilities
+% --------- --------- ----------
+
+
+\let \completerow = \cr
+
+\def \ialign {\everycr = {}\tabskip=0pt \halign}
+
+\def \oalign #1{% {row...}
+ \ensurepar
+ \vtop{\baselineskip = 0pt
+ \lineskip = .25ex
+ \ialign{##\cr #1\crcr}}}
+
+\def \ooalign {%
+ \lineskiplimit = -\maxdimen
+ \oalign}
+
+\def \ozalign {%
+ \lineskiplimit = 0pt\relax
+ \oalign}
diff --git a/macros/plain/contrib/zztex/tex/zztag.tex b/macros/plain/contrib/zztex/tex/zztag.tex
new file mode 100644
index 0000000000..32154dd8c4
--- /dev/null
+++ b/macros/plain/contrib/zztex/tex/zztag.tex
@@ -0,0 +1,269 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% Module: ZzTeX Tag Facilities
+%
+% Synopsis: This module contains the definitions necessary to implement
+% tags and references to them.
+%
+% Note: Tag names beginning with `zX:' are reserved for ZzTeX:
+%
+% zA: design alternative choices (obsolete)
+% zB: bibliographic tags
+% zE: frame page numbers
+% zF: float page numbers
+% zH: help text
+% zM: margin note page numbers
+% zP: proof note page numbers
+% zR: margin rule page numbers
+% zS: snapshot information
+%
+% Author: Paul C. Anagnostopoulos
+% Created: 19 September 1989
+%
+% Copyright 1989--2020 by Paul C. Anagnostopoulos
+% under The MIT License (opensource.org/licenses/MIT)
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% Tag Definition
+% --- ----------
+
+
+\definetoks{\taginfonumber}
+\taginfonumber = {???}
+\definetoks{\taginfotitle}
+\taginfotitle = {???}
+\definecount{\zmistags}{0}
+
+
+% The number is fully expanded, while the title is not expanded.
+% Then we make sure they are never expanded again.
+
+\def \settaginfo #1#2{% {number}{title}
+ \edef \znext {\taginfonumber = {#1}}%
+ \znext
+ \taginfotitle = {#2}}
+
+\def \tag #1{% {name}
+ \if \emptytoksp{\taginfonumber}%
+ \warning{notaginfo}{ZzTeX reference: Misplaced tag '#1'}%
+ \global\increment \zmistags
+ \fi
+ \zbeginhidewrite
+ \edef \znext {\noexpand\xref{tag}{\noexpand\folio}%
+ {\the\taginfonumber}%
+ {\the\taginfotitle}
+ {#1}}%
+ \znext
+ \if \PDFhyperlinks \PDFmark{T:#1}\fi
+ \zendhidewrite}
+
+\def \tagwith #1#2{% {name}{reference-text}
+ \zbeginhidewrite
+ \edef \znext {\noexpand\xref{tag}{\noexpand\folio}%
+ {#2}%
+ {???notitle???}
+ {#1}}%
+ \znext
+ \if \PDFhyperlinks \PDFmark{T:#1}\fi
+ \zendhidewrite}
+
+% This is a special command when you just want to know the page number.
+
+\def \tagpageonly #1{% {name}
+ \zbeginhidewrite
+ \edef \znext {\noexpand\xref{tag}{\noexpand\folio}%
+ {???nonumber???}%
+ {???notitle???}
+ {#1}}%
+ \znext
+ \if \PDFhyperlinks \PDFmark{T:#1}\fi
+ \zendhidewrite}
+
+\def \uniquetag #1#2{% {prefix}{counter}
+ #1:\the\divisionname-#2}
+
+% Subtag Definition
+% ------ ----------
+
+
+\definecount{\subtagnumber}{0}
+
+
+\def \setsubtagnumber #1{% {integer}
+ \subtagnumber = #1\relax}
+
+\def \subtag #1#2{% {name}{subnumber}
+ \zparsesubnumber #2???\zmark
+ \tagwith{#1}{\zsubtagtext}}
+
+\def \zparsesubnumber #1?#2?#3?#4\zmark{%
+ \if \emptyargp{#2}%
+ \edef \zsubtagtext {\the\taginfonumber #1}%
+ \else
+ \increment \subtagnumber
+ \edef \zsubtagtext {\the\taginfonumber #1#2\subtagnumber#3}%
+ \fi}
+
+% Tag Reference
+% --- ---------
+
+
+% This counter keeps track of the number of undefined tag references.
+
+\definecount{\zuntagrefs}{0}
+
+
+\def \refnumber #1{% {tag-name}
+ \zbeginrefhilight
+ \if \definedp{\=#1}%
+ \zreftext{#1}{\expandafterthrice\ztagdata \name{\=#1}\zmark1}%
+ \else
+ \zuntag{#1}{???}%
+ \fi
+ \zendrefhilight}
+
+\let \ref = \refnumber % Because it's so common.
+
+\def \refpage #1{% {tag-name}
+ \zbeginrefhilight
+ \if \definedp{\=#1}%
+ \zreftext{#1}{\expandafterthrice\ztagdata \name{\=#1}\zmark0}%
+ \else
+ \zuntag{#1}{???}%
+ \fi
+ \zendrefhilight}
+
+\def \reftitle #1{% {tag-name}
+ \zbeginrefhilight
+ \if \notp{\allowreftitle}%
+ \warning{noreftitle}{Use of \string\reftitle is not allowed}%
+ ???not allowed???%
+ \else \if \definedp{\=#1}%
+ {\zadjtitle = \zadjtitlenone
+ \zreftext{#1}{\expandafterthrice\ztagdata \name{\=#1}\zmark2}}%
+ \else
+ \zuntag{#1}{???title???}%
+ \fi\fi
+ \zendrefhilight}
+
+\def \zbeginrefhilight {%
+ \if \DVIWindoinuse
+ \colorspecial{ifview color push rgb 1 0 .25}% % Color the reference.
+ \fi}
+
+\def \zendrefhilight {%
+ \if \DVIWindoinuse
+ \colorspecial{ifview color pop}% % Done with color.
+ \fi}
+
+\def \zreftext #1#2{% {tag}{text}
+ \if \PDFhyperlinks
+ \tagbutton{#1}{#2}%
+ \else
+ #2%
+ \fi}
+
+\def \ztagdata #1\zmark#2\zmark#3\zmark#4{%
+ \ifcase #4 #1\or #2\or #3\fi} % Space after #4 is critical!
+
+\def \zuntag #1#2{% {tag}{what-to-set}
+ \writelog{ZzTeX reference: Undefined tag `#1'.}%
+ \zxwriteinfo{\false}{undef-tag}{#1}{}%
+ \global\increment \zuntagrefs
+ #2}
+
+% Determining the Page
+% ----------- --- ----
+
+
+% This command allows us to use the tag facility to determine which page
+% a particular element is on, in case the design of the element depends
+% on whether it is on a recto or verso.
+
+\def \whichpage #1#2{% {\count-reg}{tag-name}
+ \def \zreg {#1}%
+ \if \definedp{\=#2}%
+ \edef \zpg {\expandafterthrice\ztagdata \name{\=#2}\zmark0}%
+ \expandafter\zwhichpagea \zpg--\zmark
+ \else
+ \zuntag{#2}{\relax}%
+ #1=\pagenumber
+ \fi\relax}
+
+\def \zwhichpagea #1-#2-#3\zmark{%
+ \if \emptyargp{#2}%
+ \zwhichpageb #1\zmark
+ \else
+ \zwhichpageb #2\zmark
+ \fi}
+
+\def \zwhichpageb #1\zmark{%
+ \setbox \zboxa=\hbox{\zreg=0#1}%
+ \if \dimzerop{\wd\zboxa}%
+ \zreg=#1%
+ \else
+ \zreg=\pagenumber
+ \fi}
+
+% Tag Cross-Reference
+% --- ---------------
+
+
+% These counters keep track of the number of duplicate tags, and the
+% number of tags that have changed since the previous run.
+
+\definecount{\zduptags}{0}
+\definecount{\zchangedtags}{0}
+
+
+% Define the macro \=tag to contain the page, number, and title.
+% However, use of the title is controlled by \allowreftitle.
+
+\def \xreftag #1#2#3#4{% {page}{number}{title}{tag}
+ \ifnum \xrefmode=\xrefloadtagmode
+ \if \definedp{\=#4}\zduptag{#4}\fi
+ \xreftagdef{#1}{#2}{#3}{\=#4}%
+ \else\ifnum \xrefmode=\xrefcopymode
+ \xreftagchk{#1}{#2}{#3}{\=#4}%
+ \fi\fi}
+
+\def \xreftagdef #1#2#3#4{% {page}{number}{title}{\name}
+ \if \allowreftitle
+ \withname\gdef{#4}{#1\zmark#2\zmark#3}%
+ \else
+ \withname\gdef{#4}{#1\zmark#2\zmark}%
+ \fi}
+
+\def \xreftagchk #1#2#3#4{% {page}{number}{title}{\name}
+ \xreftagdef{#1}{#2}{#3}{\zxrefchk}%
+ \expandaftertwice\ifx \name{#4}\zxrefchk
+ \else
+ \global\increment \zchangedtags
+ \fi}
+
+\def \zduptag #1{% {tag}
+ \writelog{ZzTeX reference: Duplicate tag `#1'.}%
+ \global\increment \zduptags}
+
+% Tag Cross-Reference Summary
+% --- --------------- -------
+
+
+\def \ztagsummary {%
+ \if \posp{\zuntagrefs}%
+ \remark{Number of undefined tags in this run: \number\zuntagrefs.}%
+ \fi
+ \if \posp{\zduptags}%
+ \remark{Number of duplicate tags in this run: \number\zduptags._%
+ \space\space\space\space\space\space\space Eliminate duplicates %
+ and reprocess the book twice.}%
+ \fi
+ \if \posp{\zmistags}%
+ \remark{Number of misplaced tags in this run: \number\zmistags.}%
+ \fi
+ \if \posp{\zchangedtags}%
+ \remark{Number of tags changed since previous run: \number\zchangedtags._%
+ \space\space\space\space\space\space\space Reprocess the book %
+ to obtain correct cross-references.}%
+ \fi}
diff --git a/macros/plain/contrib/zztex/tex/zztex.tex b/macros/plain/contrib/zztex/tex/zztex.tex
new file mode 100644
index 0000000000..203affbfac
--- /dev/null
+++ b/macros/plain/contrib/zztex/tex/zztex.tex
@@ -0,0 +1,196 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% Module: ZzTeX Main Module
+%
+% Synopsis: This is the main module of ZzTeX. It sets up character
+% categories and loads all the other modules.
+%
+% Note: ZzTeX assumes the use of DVIPSONE, the PostScript DVI program
+% from Y&Y.
+%
+% Author: Paul C. Anagnostopoulos
+% Created: 27 March 1989
+%
+% Copyright 1989--2020 by Paul C. Anagnostopoulos
+% under The MIT License (opensource.org/licenses/MIT)
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% If ZzTeX is already loaded, quit immediately.
+
+\ifx \ZzTeX\zzzundefinedzzz \else \message{... using format}\endinput \fi
+
+% Character Categories
+% --------- ----------
+
+
+% Character INITEX ZzTeX Notes
+%
+% NUL ignored invalid Ignored in Plain TeX.
+% TAB invalid Space in Plain TeX.
+% FORMFEED active: \par
+% RETURN end of line end of line
+% space space space
+% # parameter
+% $ math shift
+% & alignment tab
+% % comment comment
+% @ other active: command
+% letters letter letter
+% \ escape escape
+% ^ superscript
+% _ subscript
+% { begin group
+% } end group
+% ~ active: tie
+% DELETE invalid invalid
+% others other invalid
+
+
+\chardef \catescape = 0 % Escape character (\). %^catcode
+\chardef \catbegin = 1 % Begin group ({). %^catcode
+\chardef \catend = 2 % End group (}). %^catcode
+\chardef \catmath = 3 % Math mode ($). %^catcode
+\chardef \catalign = 4 % Alignment tab (&). %^catcode
+\chardef \catendofline = 5 % End of line. %^catcode
+\chardef \catparameter = 6 % Parameter (#). %^catcode
+\chardef \catsuperscript = 7 % Superscript (^). %^catcode
+\chardef \catsubscript = 8 % Subscript (_). %^catcode
+\chardef \catignored = 9 % Ignored character. %^catcode
+\chardef \catspace = 10 % Space. %^catcode
+\chardef \catletter = 11 % Letter. %^catcode
+\chardef \catother = 12 % Other. %^catcode
+\chardef \catactive = 13 % Active character (tilde). %^catcode
+\chardef \catcomment = 14 % Comment (percent). %^catcode
+\chardef \catinvalid = 15 % Invalid character. %^catcode
+\chardef \catcsname = 16
+
+\catcode`\^ = \catsuperscript
+\catcode`\^^@ = \catinvalid
+\catcode`\^^I = \catinvalid
+\catcode`\^^L = \catactive
+\catcode`\^^M = \catendofline
+\catcode`\ = \catspace
+\catcode`\# = \catparameter
+\catcode`\$ = \catmath
+\catcode`\& = \catalign
+\catcode`\% = \catcomment
+\catcode`\@ = \catactive
+\catcode`\\ = \catescape
+\catcode`\_ = \catsubscript
+\catcode`\{ = \catbegin
+\catcode`\} = \catend
+\catcode`\~ = \catactive
+\catcode`\^^? = \catinvalid
+
+% Characters "80--"FF are catcoded as invalid in zzmisc.
+
+\outer \def ^^L{\par}
+
+% Atsign Commands
+% ------ --------
+
+
+% At-sign commands are reserved for extended commands within blocks.
+% \defineatsigncommand makes a local definition!
+
+
+\def \defineatsigncommand @#1{% char args {body}
+ \withname\def{\zat#1}}
+
+\def @#1{% char
+ %%%\relax % Stops \omit search in an alignment cell.
+ \if \undefinedp{\zat#1}%
+ \error{undefat}{The atsign command `\string@#1' is not defined
+ in this block}%
+ \fi
+ \name{\zat#1}}
+
+% Markers
+% -------
+
+
+% This command does nothing, but it provides a name on which to
+% hang a comment for ZzExplore.
+
+\def \definemarker #1{% {marker-name}
+ }
+
+% Paragraph Programs
+% --------- --------
+
+
+% We maintain a list of little programs that must be executed
+% at the beginning of every paragraph. A program is declared
+% with `\declareeverypar'. The programs are executed with
+% `\requiredeverypar'.
+
+\def \everyparlist {}
+
+\def \declareeverypar #1{% {code}
+ \append{#1}{\everyparlist}}
+
+\def \requiredeverypar {%
+ \maplist{##1}{\everyparlist}}
+
+% Modules
+% -------
+
+
+\def \zremovePlaindef #1{%
+ \let #1= \relax}
+
+\input zzprog % Must be first.
+\input zzreg % Must be second.
+\input zzerror
+\input zzhelp
+\input zzio
+\input zzfont
+\input zzvmode
+\input zzhmode
+\input zzhmodeb
+\input zzhyph
+\input zzltrspc
+\input zzblock
+\input zzxref
+\input zzdoc
+\input zzdiv
+\input zzpage
+\input zzoverlay
+\input zzindexv1 % Must precede body files.
+\input zzsect
+\input zztext
+\input zztabbing
+\input zznote
+\input zzlist
+\input zztabularv3
+\input zzfloat
+\input zzart
+\input zztag
+\input zzmath
+\input zzfront
+\input zzps
+\input zzhyper
+\input zzmisc % Must be next to last.
+\input zzplain % Must be last.
+
+% Identification
+% --------------
+
+
+\def \TeX {T\kern-.1667em \lower .55ex \hbox{E}\kern-.1em X}
+\def \ZzTeX {Z\kern -.02em z\kern -.05em \TeX}
+
+\input zzver\relax
+
+\everyjob = {\messagenl{__Welcome to ZzTeX version \ZzTeXversion__}}
+
+\def \fmtname {ZzTeX}
+\edef \fmtversion {\ZzTeXversion}
+
+
+\messagenl{__Welcome to ZzTeX version \ZzTeXversion__}
+
+\if \orp{\hmodep}{\posp{\pagetotal}}
+ \zzerror{Spurious paragraph text appears in the ZzTeX files}%
+\fi
diff --git a/macros/plain/contrib/zztex/tex/zztext.tex b/macros/plain/contrib/zztex/tex/zztext.tex
new file mode 100644
index 0000000000..8e37133039
--- /dev/null
+++ b/macros/plain/contrib/zztex/tex/zztext.tex
@@ -0,0 +1,935 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% Module: ZzTeX General Text Facilities
+%
+% Synopsis: This module contains definitions for blocks that are used to
+% format text.
+%
+% Notes: The tabbing facility was implemented by Richard A. Wells and
+% integrated into ZzTeX on 8/16/94.
+%
+% Authors: Paul C. Anagnostopoulos and Richard A. Wells
+% Created: 14 March 1990
+%
+% Copyright 1989--2020 by Paul C. Anagnostopoulos
+% under The MIT License (opensource.org/licenses/MIT)
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% Text Block
+% ---- -----
+
+
+\defineblock{\text}{\endtext}{\false}{}
+\resetinvcontext{\text}
+
+%~block text Type, Level
+% \abovepenalty = integer % Penalty above text.
+% \aboveskip = glue % Space b/b above text.
+% \def \beginformat {...} % Beginning of text formatter.
+% \belowpenalty = integer % Penalty below text.
+% \belowskip = glue % Space b/b below text.
+% \bodyfont = {font} % Body font.
+% \def \calloutformat ##1{...} % Callout formatter.
+% \calloutnumber = integer % Number of first callout.
+% \def \callouttext {...} % Callout text or \arg.
+% \defaulttabwidth = dimen % Default repeating tab width.
+% \setflag \enabletabbing = flag % Enable tabbing commands.
+% \def \endformat {...} % End of text formatter.
+% \leftindent = glue % Left indentation.
+% \parindent = dimen % Paragraph indentation.
+% \parrag = dimen % Paragraph raggedness.
+% \parskip = glue % Paragraph skip.
+% \rightindent = glue % Right indentation.
+% \textcolor = {...} % Color of text.
+% \setflag \verbatimlines = flag % Treat line breaks verbatim.
+% \width = dimen % Line width.
+%~end
+
+\definecount{\calloutnumber}{0}
+\setflag \enabletabbing = \false
+\definedimen{\defaulttabwidth}{0pt}
+\setflag \verbatimlines = \false
+
+
+\def \text #1{% {type}
+ \beginblockscope{text}%
+ \global\increment \textdepth
+ \abovepenalty = \breakgood %~default hard
+ \def \beginformat {}% %~default soft
+ \belowpenalty = \breakgood %~default hard
+ \calloutnumber = 1 %~default with
+ \def \callouttext {\number\calloutnumber}% %~default soft
+ \defaulttabwidth = \mindimen %~default soft
+ \setflag \enabletabbing = \false %~default soft
+ \def \endformat {}% %~default soft
+ \textcolor = {}% %~default soft
+ \setflag \verbatimlines = \false %~default soft
+ \processdesign{\text}{#1\romannumeral\textdepth}%
+ \global\increment \textnumber
+ \textformat
+ \def \zarg {\arg}%
+ \if \tokeqlp{\callouttext}{\zarg}%
+ \defineatsigncommand @##{\ztextcoformat}%
+ \else
+ \defineatsigncommand @##{\ztextcoformat{\callouttext}}%
+ \fi
+ \if \emptytoksp{\textcolor}%
+ \bgroup
+ \else
+ \color{\the\textcolor}%
+ \fi
+ \if \enabletabbing \ztabinittabbing \fi
+ \if \verbatimlines \obeylines \fi
+ \if \enabletabbing \ztabstarttabbing \fi}
+
+\def \endtext {%
+ % Must really be \par, not \endgraf, because might be redefined
+ % for tabbing.
+ \if \notp{\verbatimlines}%
+ % In \verbatimlines the line preceding \endtext{...} will put
+ % out a final \par, but if not we have to do it here.
+ \par
+ \fi
+ \if \enabletabbing \ztabfinaltabbing \fi
+ \if \emptytoksp{\textcolor}%
+ \egroup
+ \else
+ \endcolor
+ \fi
+ \futurelet\nexttoken \zendtext}
+
+\def \zendtext {%
+ \endtextformat
+ \global\decrement \textdepth
+ \endblockscope{text}%
+ \parnext}
+
+\def \textformat {%
+ \endgraf
+ \the\bodyfont
+ \bbskipabove{\abovepenalty}{\aboveskip}%
+ \alterindentation{\leftindent}{\rightindent}%
+ \settextwidth{\width}%
+ \setparrag{\parrag}%
+ \beginformat}
+
+\def \endtextformat {%
+ \endformat
+ \bbskipbelowblockpar{\nexttoken}{\belowpenalty}{\belowskip}}
+
+\def \ztextcoformat #1{% {text}
+ \calloutformat{#1}%
+ \global\increment \calloutnumber}
+
+% Tabbing Commands
+% ------- --------
+
+% These commands are available in a text block if \enabletabbing is turned on.
+
+
+% \ztabinitalizetabbing
+% - Redefines \par
+% - Defines the @ commands for tabbing. (The real work is done in the
+% in the \ztabcmd* macros, defined below.)
+% - Initializes variables
+
+\def \ztabinittabbing {%
+ % Redefine \par to ship out the tabbed line, \endgraf it and start a
+ % new tabbed line
+ \let \par = \ztabpar
+ % Define tabbing commands
+ \def \adjusttabbing ##1{\ztabadjusttabbing{##1}}%
+ \defineatsigncommand @.{\ztabcmdset}%
+ \defineatsigncommand @>{\ztabcmdforwards}%
+ \defineatsigncommand @+{\ztabcmdindent}%
+ \defineatsigncommand @-{\ztabcmdoutdent}%
+ \defineatsigncommand @D{\ztabcmddiscard}%
+ \defineatsigncommand @C{\ztabcmdclear}%
+ \defineatsigncommand @E##1{\ztabcmdevery{##1}}%
+ % Initialize variables
+ \if \verbatimlines
+ % The line with \text{...} will put out the first \par, so we
+ % want to skip it.
+ \ztabdiscardtrue
+ \else
+ \ztabdiscardfalse
+ \fi
+ \global\ztabindentlevel=0\relax
+ % Clear all tab stops
+ \ztabcmdclear}
+
+\def \ztabparfinishpreviousline {%
+ % Set state checked by \ztabendtabcell
+ \ztabatnltrue
+ % End last tab cell with \ztabnltrue
+ \ztabendtabcell
+ \egroup% closes inner group started below in \ztabmaketabbedline
+ \egroup% closes outer group started below in \ztabmaketabbedline
+ % Unless discarding, deposit the line and remove the last box
+ \if \notp{\ztabdiscardp}%
+ \unvbox\zboxa\lastbox
+ \else
+ % Clear discarding flag
+ \ztabdiscardfalse
+ \fi
+ \endgroup% closes outermost group started by \ztabmaketabbedline
+ % We should be back in vertical mode now.
+ %
+ % Reset \ztabsbox. The new value is the set of tbd boxes
+ % followed by the done boxes. If not all of the tbd boxes were
+ % used this should result in the same set of boxes as the
+ % previous value of \ztabsbox. However, if the tbd boxes were used up
+ % then the done boxes may contain additional boxes built on the fly.
+ \setbox\ztabsbox\hbox{\unhbox\ztabstbdbox\unhbox\ztabsdonebox}}
+
+\def \ztabparstartnextline {%
+ \ztabmaketabbedline}
+
+\def \ztabpar {% macro used instead of \par in tabbing
+ \ztabparfinishpreviousline
+ \endgraf
+ \ztabparstartnextline}
+
+\def \ztabstarttabbing {%
+ \ztabparstartnextline}
+
+\def \ztabfinaltabbing {%
+ % Discard and finish last tabbed line started by last \ztabpar
+ \ztabdiscardtrue
+ \ztabparfinishpreviousline}
+
+
+
+% Variables shared by \ztab* macros
+
+% Counts and dimens for building tab boxes
+\definecount{\ztabindentlevel}{0}
+\definecount{\ztabindentcounter}{0}
+\definedimen{\ztabcolwidth}{0pt}
+\definedimen{\ztabtabpos}{0pt}
+\definedimen{\ztabdimenii}{0pt}
+
+% Conditionals
+% atnlp: are we at a \nl in tab processing?
+\def \ztabatnlfalse {\global\setflag \ztabatnlp=\false}%
+\def \ztabatnltrue {\global\setflag \ztabatnlp=\true}%
+% discardp: are we discarding this line's output?
+\def \ztabdiscardfalse {\global\setflag \ztabdiscardp=\false}%
+\def \ztabdiscardtrue {\global\setflag \ztabdiscardp=\true}%
+% settingp: are we setting?
+\def \ztabsettingfalse {\global\setflag \ztabsettingp=\false}%
+\def \ztabsettingtrue {\global\setflag \ztabsettingp=\true}%
+% tabbingp: are we tabbing?
+\def \ztabtabbingfalse {\global\setflag \ztabtabbingp=\false}%
+\def \ztabtabbingtrue {\global\setflag \ztabtabbingp=\true}%
+
+
+% Boxes to hold the tabs
+\definebox{\ztabsbox}% hbox of hboxes for each tab column
+\definebox{\ztabstbdbox}% hbox of hbox tab columns still "to be done"
+\definebox{\ztabsdonebox}% hbox of hbox tab columns already done
+\definebox{\ztabsindentbox}% hbox of indents
+
+
+% The macros that implement the tabbing commands. \ztabcmd* are the
+% top-level macros called by the @ commands. Other \ztab* macros are
+% helpers.
+
+\def \ztabcmdset {%
+ % Set state checked by \ztabendtabcell
+ \ztabsettingtrue
+ % End the current cell with \ztabsettingtrue
+ \ztabendtabcell
+ % Start the next cell
+ \ztabbegintabcell\noindent\ignorespaces}%
+
+\def \ztabcmdforwards {%
+ % Set state checked by \ztabendtabcell
+ \ztabtabbingtrue
+ % End the current cell with \ztabsettingtrue
+ \ztabendtabcell
+ % Start the next cell
+ \ztabbegintabcell\noindent\ignorespaces}%
+
+\def \ztabcmdindent {\global\increment \ztabindentlevel\relax}%
+
+
+\def \ztabcmdoutdent {%
+ \global\decrement \ztabindentlevel\relax
+ \if \negp{\ztabindentlevel}%
+ \zzerror{Attempt to tab dedent (with \string@-) to left of left margin}%
+ \fi}
+
+\def \ztabcmddiscard {%
+ \ztabdiscardtrue}%
+
+\def \ztabcmdclear {% {boolean: initialization}
+ % First clear all boxes
+ \ztabcleartabboxes
+ % Surprise! Clearing tabs might actually set them, if \defaulttabwidth
+ % has been set in the design
+ \if \neqlp{\defaulttabwidth}{\mindimen}%
+ \ztabcmdevery{\defaulttabwidth}%
+ \else
+ % Must clear indent level since we've cleared all tabs (note that
+ % we intentionally leave indent level alone if there is a
+ % \defaulttabwidth!)
+ \global\ztabindentlevel=0\relax
+ \fi\ignorespaces}%
+
+\def \ztabcmdevery #1{%
+ % First clear all tabs
+ \ztabcleartabboxes
+ % Set new tab columns of the specified width into \ztabsbox
+ \ztabsettabs{#1}%
+ % Re-init the boxes used by \ztabmaketabbedline
+ \ztabinittabboxes{\true}% Flag indicates this is a re-init
+ \ignorespaces}
+
+
+% Implementation of the above commands
+
+
+\def \ztabinittabboxes #1{% Init the tab boxes {boolean: re-init}
+ % First copy \ztabsbox into \ztabstbdbox and clear \ztabsdonebox
+ \global\setbox\ztabstbdbox\copy\ztabsbox
+ \global\setbox\ztabsdonebox\null
+ % Put all of the indent boxes that might be built into an hbox
+ % which we will emit later, but just before processing cells
+ \global\setbox\ztabsindentbox\hbox%
+ \bgroup%
+ % Initialize counter for loop
+ \ztabindentcounter=0\relax
+ % Iterate \ztabindentlevel times, moving tabboxes from \ztabstbdbox to
+ % \ztabsdone, maybe emitting hboxes per indent
+ \if \lssp{\ztabindentcounter}{\ztabindentlevel}%
+ \loop
+ \increment \ztabindentcounter\relax% increment loop counter
+ % Pull \lastbox off of \ztabstbdbox
+ \global\setbox\ztabstbdbox\hbox{%
+ \unhbox\ztabstbdbox
+ \global\setbox\zboxb\lastbox}%
+ \ifvoid\zboxb
+ % This is a problem. Not allowed to indent past set tabs.
+ \zzerror{Attempt to tab indent (with \string@+, [\the\ztabindentlevel]) past set tabs}%
+ \else
+ % Nothing wrong with the box: push it on \ztabsdonebox
+ % and maybe emit it
+ \global\setbox\ztabsdonebox\hbox{\copy\zboxb\unhbox\ztabsdonebox}%
+ \if \notp{#1}% Not re-initializing
+ \box\zboxb
+ \fi
+ \fi
+ % Loop test
+ \if \lssp{\ztabindentcounter}{\ztabindentlevel}\repeat
+ \fi
+ % End hbox
+ \egroup}
+
+\def \ztabcleartabboxes {% Clear the tab boxes and indent level
+ \setbox\ztabsbox\null
+ \global\setbox\ztabstbdbox\null
+ \global\setbox\ztabsdonebox\null}
+
+\def \ztabsettabs #1{% Deposit tab stops of a specified width in \ztabsbox
+ \ztabcolwidth=#1\relax
+ \ztabtabpos=0pt\relax
+ % Loop while \ztabtabpos is less than \hsize, setting another tab
+ \loop
+ \ztabsetanother
+ \if \dimlssp{\ztabtabpos}{\hsize}\repeat}
+
+\def \ztabsetanother {% Helper for \ztabsettabs, immediately preceding
+ % Advance the counter
+ \advance \ztabtabpos by \ztabcolwidth
+ % Set another tab by "pushing" another hbox into the \ztabsbox hbox
+ % followed by its old set of hboxes
+ \setbox\ztabsbox\hbox{\hbox to\ztabcolwidth{}\unhbox\ztabsbox}}
+
+\def \ztabmaketabbedline {% Build a line of tabbed text
+ % Start outermost group that redefines \nl
+ \begingroup
+ % Inittab boxes (this also builds \ztabsindentbox)
+ \ztabinittabboxes{\false}% Flag indicates NOT a re-init
+ % \nl is a synonym for modified \par
+ \let\nl=\par
+ % \zboxa will contain the entire tabbed line in a vbox.
+ % (It is unvboxed in \nl and may be discarded if a @D is encountered.)
+ \setbox\zboxa\vbox%
+ % start outer group closed by \nl that holds state of \ztabatnlp
+ \bgroup%
+ % don't want to indent a tabbed line
+ \noindent
+ % Init conditionals
+ \ztabatnlfalse
+ \ztabsettingfalse
+ \ztabtabbingfalse
+ % start inner group closed by \nl that surrounds set of tabboxes
+ % and uses \zboxc as an hbox for the current cell.
+ \bgroup%
+ % emit indentation box
+ \box\ztabsindentbox
+ % start the first cell
+ \ztabbegintabcell}
+ % material for a cell will follow here and be ended by
+ % either a @ command or \nl, all of which will deposit
+ % \ztabendtabcell. The @ commands will begin another tab cell and
+ % \nl will also finish all of the groups started by
+ % \ztabmaketabbedline and put out the line.
+
+\def \ztabbegintabcell {%
+ % \zboxc contains an hbox as the current cell of tabbed material.
+ % (It is deposited at the end of \ztabendtabcell.)
+ \setbox\zboxc\hbox%
+ \bgroup% opens group closed in \ztabendtabcell
+ \ignorespaces}
+
+\def \ztabendtabcell {%
+ \if \ztabatnlp
+ % Processing last cell in this row. Close group opened in
+ % \ztabbegintabcell w/o bothering to re-set tabboxes.
+ \egroup
+ \else
+ % Close this cell's group (opened in \ztabbegintabcell) with \hss,
+ % since this is not the last cell.
+ \hss\egroup
+ % "Pop" current tabbox from \ztabstbdbox, measure it, deposit tabbed
+ % material into properly sized box and then "push" tabbox onto \ztabsdonebox
+ % "Pop" from the end of \ztabstbdbox using \lastbox into \zboxb
+ \global\setbox\ztabstbdbox\hbox{%
+ \unhbox\ztabstbdbox
+ \global\setbox\zboxb\lastbox}%
+ % Process the current tabbox
+ \ifvoid\zboxb
+ \if \ztabtabbingp
+ \zzerror{Attempt to tab (with \string@>) past set tabs}%
+ \else
+ % The current tabbox is void, so we set it to a box that is the
+ % natural width of \zboxc (which contains the cell material).
+ \global\setbox\zboxb\hbox to\wd\zboxc{}%
+ \fi
+ \else
+ \if \ztabsettingp
+ % Re-set previously stored tabbox to natural width of the cell (\zboxc)
+ \global\setbox\zboxb\hbox to\wd\zboxc{}%
+ \fi
+ % Re-deposit the cell material into \zboxc using the width of the
+ % current tabbox.
+ \setbox\zboxc\hbox to\wd\zboxb{\unhbox\zboxc}%
+ \fi
+ % "Push" the current tabbox measure onto the \ztabsdonebox set of boxes.
+ % (Note that this might have come from \ztabstbdbox or been measured from
+ % \zboxc if there were no more tabboxes, so this is where an "on-the-fly"
+ % tab is added to \ztabsdone, which will later be copied back into
+ % \ztabsbox for the next line.)
+ \global\setbox\ztabsdonebox\hbox{\box\zboxb\unhbox\ztabsdonebox}%
+ \fi
+ % Clear conditional variables
+ \ztabsettingfalse
+ \ztabtabbingfalse
+ % emit box for this cell
+ \box\zboxc}
+
+\def \ztabadjusttabbing #1{% {vertical-mode material}
+ % Close and discard currently open tabbed line (empty, but started
+ % by end of previous line).
+ \ztabcmddiscard
+ \ztabparfinishpreviousline
+ % Insert vertical material
+ #1\relax
+ % If in verbatimlines must set this line to be discarded by
+ % the newline which ends the \adjusttabbing{...} line, which will also
+ % start the next line.
+ \if \verbatimlines
+ \ztabdiscardtrue
+ \fi
+ % Start next tabbed line
+ \ztabparstartnextline}
+
+% Builtin Text Blocks
+% ------- ---- ------
+
+% The following text block formats text in a completely normal fashion.
+% It can be used with \with to make small changes to the text format.
+
+\def \textnormalidesign {%
+ \calculate \aboveskip = {\enclosingbaselineskip,+,\enclosingparskip}%
+ \belowskip = \aboveskip
+ \bodyfont = {}%
+ \leftindent = \enclosingleftss
+ \parindent = \enclosingparindent
+ \parrag = \enclosingparrag
+ \parskip = \enclosingparskip
+ \rightindent = \enclosingrightss
+ \setflag \verbatimlines = \false
+ \width = \naturalwidth}
+
+\def \textnormaliidesign {%
+ \textnormalidesign}
+\def \textnormaliiidesign {%
+ \textnormalidesign}
+\def \textnormalivdesign {%
+ \textnormalidesign}
+
+\def \setflushingleft {%
+ \leftindent = 0pt
+ \parfillskip = \normalparfillskip
+ \parindent = 0pt
+ \rightindent = 0pt
+ \width = \naturalwidth}
+
+
+% This text block centers text relative to the current left and right
+% indentation.
+
+\def \textcenteridesign {%
+ \textnormalidesign
+ \setcentering}
+
+\def \textcenteriidesign {%
+ \textcenteridesign}
+\def \textcenteriiidesign {%
+ \textcenteridesign}
+\def \textcenterivdesign {%
+ \textcenteridesign}
+
+\def \setcentering {%
+ \leftindent = \centerindent
+ \parfillskip = 0pt
+ \parindent = 0pt
+ \rightindent = \centerindent
+ \width = \naturalwidth}
+
+
+% This text block positions text flush right.
+
+\def \textflushrightidesign {%
+ \textnormalidesign
+ \setflushingright}
+
+\def \textflushrightiidesign {%
+ \textflushrightidesign}
+\def \textflushrightiiidesign {%
+ \textflushrightidesign}
+\def \textflushrightivdesign {%
+ \textflushrightidesign}
+
+\def \setflushingright {%
+ \leftindent = \centerindent
+ \parfillskip = 0pt
+ \parindent = 0pt
+ \rightindent = 0pt
+ \width = \naturalwidth}
+
+% This text block squares off the last line of paragraphs.
+
+\def \textflushendidesign {%
+ \textnormalidesign
+ \parfillskip = 0pt}
+
+\def \textflushendiidesign {%
+ \textflushendidesign}
+\def \textflushendiiidesign {%
+ \textflushendidesign}
+\def \textflushendivdesign {%
+ \textflushendidesign}
+
+\def \flushendpar {%
+ \zskipa = \parfillskip
+ \parfillskip = 0pt
+ \par
+ \parfillskip = \zskipa}
+
+% This text block sets text in the full type width.
+
+\def \texttypeareaidesign {%
+ \textnormalidesign
+ \leftindent = -\oddlefttextmargin
+ \width = \typeareawidth}
+
+\def \texttypeareaiidesign {%
+ \texttypeareaidesign}
+
+% This command centers a single line or sets multiple lines in block format.
+
+\def \centerorblockpar #1#2{% {width}{text}
+ \measuretextwidth{\tdimena}{#2}%
+ \if \dimlssp{\tdimena}{#1}%
+ \centerline{#2}%
+ \else
+ \noindent #2\par
+ \fi}
+
+% Code Block
+% ---- -----
+
+
+\defineblock{\code}{\endcode}{\false}{}
+
+%~block code Type
+% \abovepenalty = integer % Penalty above code.
+% \aboveskip = glue % Space b/b above code.
+% \setflag \allowbreaks = boolean % Page breaks allowed?
+% \setflag \allowatsigncommands = boolean % Allow at-sign commands.
+% \setflag \allowcallouttag = boolean % Allow \tag for callout numbers.
+% \setflag \allowTeXcommands = boolean % Allow commands with \ { }
+% \setflag \allowTeXmath = boolean % Allow math with $ _ ^
+% \setflag \autocallout = boolean % Automatically number lines?
+% \def \beginformat {...} % Beginning of code formatter.
+% \belowpenalty = integer % Penalty below code.
+% \belowskip = glue % Space b/b below code.
+% \bodyfont = {...} % Font for text.
+% \def \calloutformat ##1{...} % Callout formatter.
+% \calloutnumber = integer % Number of first callout.
+% \def \callouttext {...} % Callout text or \arg.
+% \codegapskip = glue % Standard code gap (see \codegap).
+% \def \endformat {...} % End of code formatter.
+% \hfuzz = dimen % Amount text can exceed \hsize.
+% \indentcolumns = integer % Standard indentation amount.
+% \leftindent = glue % Left indentation.
+% \metafont = {font} % Font for metasyntactic names.
+% \rightindent = glue % Right indentation.
+% \textcolor = {...} % Color of text.
+% \setflag \verbatimchars = flag % Take all characters verbatim?
+% \setflag \verbatimspaces = flag % Take all spaces verbatim?
+% \width = dimen % Width of code.
+%~end
+
+\defineskip{\codegapskip}{0pt}
+\definecount{\indentcolumns}{0}
+\definetoks{\metafont}
+
+\definecount{\codelinenumber}{0}
+
+\definecount{\zcodehyph}{0} % To remember hyphen character.
+
+\def \code #1{% {type}
+ \blockcantbein{\code}{\code}%
+ \beginblockscope{code}%
+ \global\increment \codedepth
+ \abovepenalty = \breakgood %~default hard
+ \setflag \allowatsigncommands = \false %~default soft
+ \setflag \allowcallouttag = \false %~default soft
+ \setflag \allowTeXcommands = \true %~default soft
+ \setflag \allowTeXmath = \false %~default soft
+ \setflag \autocallout = \false %~default soft
+ \def \beginformat {}% %~default soft
+ \belowpenalty = \breakbetter %~default hard
+ \calloutnumber = 1 %~default with
+ \def \callouttext {\number\calloutnumber}% %~default soft
+ \codegapskip = \mindimen %~default soft
+ \def \endformat {}% %~default soft
+ \indentcolumns = 3 %~default soft
+ \textcolor = {}% %~default soft
+ \setflag \verbatimchars = \true %~default soft
+ \setflag \verbatimspaces = \true %~default soft
+ \codelinenumber = 1\relax
+ \processdesign{\code}{#1}%
+ \global\increment \codenumber
+ \codeformat
+ \let \par = \zcodepar
+ \obeylines
+ \if \verbatimspaces \obeyspaces \fi
+ \let \zrealincl = \include
+ \let \include = \zcodeincl
+ \let \zrealfn = \footnote
+ \let \footnote = \zcodefn
+ \def \zarg {\arg}%
+ \if \tokeqlp{\callouttext}{\zarg}%
+ \def \!{\zcodecoformat}%
+ \else
+ \def \!{\zcodecoformat{\callouttext}}%
+ \fi
+ \settaginfo{}{}% % No tag information so far.
+ \if \notp{\emptytoksp{\textcolor}}\color{\the\textcolor}\fi
+ \begingroup % So we can undo the following things.
+ \if \autocallout \everyparagraph = {\!}\fi
+ \if \verbatimchars
+ \uncatcode{\allowTeXcommands}{\allowatsigncommands}{\allowTeXmath}
+ \fi
+ \zcodeflushline}
+
+{\catcode`\^^M = \catactive
+\gdef \zcodeflushline #1^^M{}%
+
+\gdef \endcode^^M{%
+%%% \columnbreak{\breakallowed}% % Allow break after last line.
+ \endgroup % Undo the \uncatcode,
+ \if \notp{\emptytoksp{\textcolor}}\endcolor \fi%
+ \futurelet\nexttoken \zendcode}% % and grab onto the next character.
+} % \catcode
+
+\def \zendcode {%
+ \hyphenchar\font = \zcodehyph
+ \setlist \zcodeadjlist = {}%
+ \endformat
+ \forcenextpenalty
+ \bbskipbelowblockpar{\nexttoken}{\belowpenalty}{\belowskip}%
+ \global\decrement \codedepth
+ \endblockscope{code}%
+ \parnext}
+
+\def \codeformat {%
+ \endgraf
+ \alterindentation{\leftindent}{\rightindent}%
+ \settextwidth{\width}%
+ \setparrag{0pt}%
+ \the\bodyfont
+ \zcodehyph = \hyphenchar\font
+ \hyphenchar\font = -1
+ \parskip = 0pt \parindent = 0pt
+ \bbskipabove{\abovepenalty}{\aboveskip}
+ \beginformat}
+
+\def \zcodepar {%
+ \increment \codelinenumber
+ \if \hmodep
+ \endgraf
+ \if \notp{\allowbreaks}\nobreak \relax \fi
+ \zchkcodeadj
+ \else
+ \if \notp{\allowbreaks}\nobreak \relax \fi
+ \zchkcodeadj
+ \vskip \baselineskip
+ \fi}
+
+% This macro allows the compositor to noninvasively adjust pages between
+% lines of code.
+
+\setlist \zcodeadjlist = {}
+
+\long\def \codeadjustment #1#2{% {line-number}{commands}
+ \append{{#1}{#2}}{\zcodeadjlist}}
+
+\long\def \zchkcodeadj {%
+ \maplist{\zchkcodeadjb##1}{\zcodeadjlist}}
+
+\long\def \zchkcodeadjb #1#2{% {line-number}{commands}
+ \if \eqlp{#1}{\codelinenumber}%
+ #2\relax
+ \fi}
+
+\def \zcodecoformat #1{% {text}
+ \ensurepar
+ {\ztoksa = {}%
+ \zcodecocln #1\zmark
+ \calloutformat{\the\ztoksa}}%
+ \if \allowcallouttag \settaginfo{#1}{???}\fi
+ \global\increment \calloutnumber}
+
+\def \zcodecocln #1#2\zmark{%
+ \ifx #1\ \else \ztoksa = \expandafter{\the\ztoksa#1}\fi
+ \if \notp{\emptyargp{#2}}\zcodecocln #2\zmark \fi}
+
+% Code Tools
+% ---- -----
+
+
+%~ This command is used to place a math expression in a
+%~ code block that doesn't allow dollar signs.
+
+\def \codemath {% $math$ %^code
+ $%
+ \catcodemath
+ \let \znext = } % Discard opening $.
+
+%~ This command produces a vertical ellipsis in code,
+%~ with optional text explaining the omission.
+
+\def \codeellipsis #1{% {text} %^code
+ \ensurepar
+ {\lower .85\baselineskip \hbox{%
+ \vbox{\baselineskip = .5\baselineskip \lineskiplimit = 0pt
+ \kern \baselineskip \hbox{.}\hbox{.}\hbox{.}\kern \baselineskip}}%
+ \unbreakable\quad {\the\metafont #1}}}%
+
+{\catcode`\^^M = \catactive
+
+% The \include macro is redefined to use this version, which eats
+% the newline at the end of the line.
+
+\gdef \zcodeincl #1^^M{\zrealincl{#1}}%
+
+% The \footnote macro is redefined so that it turns off \obeylines.
+
+\gdef \zcodefn {%
+ \bgroup%
+ \let ^^M = \space%
+ \zcodefnb}%
+
+\gdef \zcodefnb #1{%
+ \zrealfn{#1}%
+ \egroup}%
+
+%~ This command allows a vertical adjustment between two lines
+%~ of code. A typical use would be
+%~ \adjustcode{\fullpagebreak}
+
+\gdef \adjustcode #1#2^^M{#1}% {command} %^code
+
+%~ Blank lines in code should be produced with this command.
+%~ A regular blank line produces too much space.
+
+\gdef \codegap #1^^M{% %^code
+ \if \dimnegp{\codegapskip}%
+ \vspace{\baselineskip}%
+ \else%
+ \vspace{\codegapskip}%
+ \fi}%
+
+} % \catcode
+
+% Code Fragment
+% ---- --------
+
+
+%~ A "code fragment" is a short sequence of program code in the running text.
+%~ Most books use |\mono|, which is defined in terms of this command.
+
+\def \codefragment #1#2#3#4{% {prefix}{suffix}{font}{text}
+ {#1%
+ \measurespacewidth{\tdimena}%
+ #3%
+ \if \monoencodingp \spaceskip = 1.2\tdimena \fi
+ \relax #4%
+ #2}}
+
+% Multicolumn Block
+% ----------- -----
+
+
+\defineblock{\multicolumn}{\endmulticolumn}{\false}{}
+
+%~block multicolumn Type
+% \abovepenalty = integer % Penalty above block.
+% \aboveskip = glue % Visual space above block.
+% \belowpenalty = integer % Penalty below block.
+% \belowskip = glue % Visual space below block.
+% \brokenpenalty = penalty % For hyphenation at bottom of column.
+% \columngutter = dimen % Width of column gutter.
+% \columnrulecolor = {color} % Color of rule separating columns.
+% \columnrulewidth = dimen % Width of rule.
+% \columns = integer % Number of columns.
+% \setflag \flushbottom = flag % Should bottoms be flush?
+% \leftindent = glue % Indentation for left edge.
+% \margins = {left,right,top,bottom} % Four margins.
+% \parrag = dimen % Paragraph raggedness.
+% \setflag \preservelistdepth = flag % Preserve list depth?
+% \siderulecolor = {color} % Color of rules on sides.
+% \siderulewidth = dimen % Width of rules.
+% \vshift = dimen % Vertical shift for entire element.
+% \width = dimen % Width of each column.
+%~end
+
+\definetoks{\columnrulecolor}
+\definedimen{\columnrulewidth}{0pt}
+\definecount{\columns}{0}
+\definetoks{\margins}
+\definetoks{\siderulecolor}
+\definedimen{\siderulewidth}{0pt}
+
+\definebox{\zmctext}
+\definecount{\zmccolumn}{0}
+\definecount{\zentrylistdepth}{0}
+\definebox{\zmccoli}
+\definebox{\zmccolii}
+\definebox{\zmccoliii}
+\definebox{\zmccoliv}
+\definebox{\zmccolv}
+\definebox{\zmccolvi}
+\definebox{\zmccolvii}
+\definebox{\zmccolviii}
+\definedimen{\zmcmaxht}{0pt}
+\definebox{\zmcbox}
+
+
+\def \multicolumn #1{% {type}
+ \beginblockscope{multicolumn}%
+ \global\increment \multicolumndepth
+ \abovepenalty = \breakgood %~default hard
+ \belowpenalty = \breakgood %~default hard
+ \brokenpenalty = \breaknever %~default soft
+ \setflag \preservelistdepth = \false %~default soft
+ \vshift = 0pt %~default soft
+ \processdesign{\multicolumn}{#1}%
+ \global\increment \multicolumnnumber
+ \expandafter\zmcparse \the\margins\zmark
+ \setbox \zmctext = \vtop\bgroup
+ \zentrylistdepth = \listdepth
+ \zpushvcontext
+ \if \preservelistdepth \global\listdepth = \zentrylistdepth \fi
+ \settextwidth{\width}%
+ \setparrag{\parrag}}
+
+\def \endmulticolumn {%
+ \endgraf
+ \zpopvcontext
+ \egroup % \vtop
+ \zbuildmc
+ \global\decrement \multicolumndepth
+ \endblockscope{multicolumn}}
+
+\def \zbuildmc {%
+ \splitmaxdepth = \dp\strutbox
+ \vbadness = 10000 % Do we want this?
+ \setbox \zmctext = \vbox{%
+ \vskip \splittopskip
+ \vskip -\ht\zmctext
+ \unvbox \zmctext
+ \unskip \unpenalty \unskip}%
+ \zbuildmca
+ \zbuildmcb
+ \bbskipabove{\abovepenalty}{\aboveskip}%
+ \hfuzz=999pc
+ \hindent{\leftindent} \lower \vshift \box\zmcbox \par
+ \prevdepth = 0pt % Nothing better to do.
+ \bbskipbelowblock{\belowpenalty}{\belowskip}}
+
+\def \zbuildmca {%
+ \zmccolumn = \columns
+ \zmcmaxht = 0pt
+ \loop
+ \calculate \tdimena =
+ {\ht\zmctext,-,\splittopskip,/,\zmccolumn,+,\splittopskip}%
+ \setbox \name{\zmccol\romannumeral\zmccolumn} =
+ \if \onep{\zmccolumn}\box\zmctext \else
+ \vsplit \zmctext to \tdimena \fi
+ \tdimena = \ht\name{\zmccol\romannumeral\zmccolumn}%
+ \if \dimgtrp{\tdimena}{\zmcmaxht}\zmcmaxht = \tdimena \fi
+ \decrement \zmccolumn
+ \if \posp{\zmccolumn}\repeat}
+
+\def \zbuildmcb {%
+ \setbox \zmcbox = \hbox{%
+ \vrule width \siderulewidth
+ \hskip -\siderulewidth
+ \hskip \zmcleft
+ \zmccolumn = \columns
+ \loop
+ \tdimena = \dp\name{\zmccol\romannumeral\zmccolumn}%
+ \setbox \zboxa = \vbox to \zmcmaxht {%
+ \unvbox \name{\zmccol\romannumeral\zmccolumn}%
+ \if \notp{\flushbottom}\vfil \fi
+ \vskip -\tdimena
+ \vskip \zmcbottom}%
+ \calculate \tdimena = {\ht\zboxa,-,\splittopskip}%
+ \lower \tdimena \hbox{\box\zboxa}%
+ \if \gtrp{\zmccolumn}{1}%
+ \hskip .5\columngutter
+ \hskip -.5\columnrulewidth
+ \vrule width \columnrulewidth
+ \hskip -.5\columnrulewidth
+ \hskip .5\columngutter
+ \fi
+ \decrement \zmccolumn
+ \if \posp{\zmccolumn}\repeat
+ \hskip \zmcright
+ \hskip -\siderulewidth
+ \vrule width \siderulewidth}}
+
+\def \zmcparse #1,#2,#3,#4\zmark{%
+ \def \zmcleft {#1\relax}%
+ \def \zmcright {#2\relax}%
+ \splittopskip = #3\relax
+ \def \zmcbottom {#4\relax}}
diff --git a/macros/plain/contrib/zztex/tex/zzttladj.tex b/macros/plain/contrib/zztex/tex/zzttladj.tex
new file mode 100644
index 0000000000..d23439bfe3
--- /dev/null
+++ b/macros/plain/contrib/zztex/tex/zzttladj.tex
@@ -0,0 +1,78 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% Module: ZzTeX New Title Adjustment Scheme
+%
+% Synopsis: The new title adjustment scheme is an improvement over the
+% original scheme provided by \adjusttitle.
+%
+% Author: Paul C. Anagnostopoulos
+% Created: 9 July 1997
+%
+% Copyright 1989--2020 by Paul C. Anagnostopoulos
+% under The MIT License (opensource.org/licenses/MIT)
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% Title Adjustment Commands
+% ----- ---------- --------
+
+
+%~ This command provides an adjustment to the enclosing title
+%~ when it appears in the body of the book. The argument text
+%~ is included only when the title appears in the body.
+
+\def \adjustbodytitle #1{% {text} %^title_adj
+ \if \eqlp{\zadjtitle}{\zadjtitlebody}#1\fi}
+
+%~ This command provides an adjustment to the enclosing title
+%~ when it appears in a running head or foot. The argument text
+%~ is included only when the title appears in a runner.
+
+\def \adjustmarktitle #1{% {text} %^title_adj
+ \if \eqlp{\zadjtitle}{\zadjtitlemark}#1\fi}
+
+%~ This command provides an adjustment to the enclosing title
+%~ when it appears in the table of contents. The argument text
+%~ is included only when the title appears in the ToC.
+
+\def \adjusttoctitle #1{% {text} %^title_adj
+ \if \eqlp{\zadjtitle}{\zadjtitletoc}#1\fi}
+
+%~ This command provides an adjustment to the enclosing title
+%~ when it appears in a mini-Toc. The argument text
+%~ is included only when the title appears in a mini-ToC.
+
+\def \adjustminitoctitle #1{% {text} %^title_adj
+ \if \eqlp{\zadjtitle}{\zadjtitleminitoc}#1\fi}
+
+\def \adjusttitle {%
+ \error{obsolete}{The \noexpand\adjusttitle command is obsolete}}
+
+% Common Adjustment Commands
+% ------ ---------- --------
+
+
+%~ This command is equivalent to |\adjustbodytitle{\nl}|.
+
+\def \titlenl;{\adjustbodytitle{\nl}} %^title_adj
+
+%~ This command is equivalent to |\adjustbodytitle{\tl}|.
+
+\def \titletl;{\adjustbodytitle{\tl}} %^title_adj
+
+%~ This command is equivalent to |\adjusttoctitle{\nl}|.
+
+\def \tocnl;{\adjusttoctitle{\nl}} %^title_adj
+
+%~ This command is equivalent to |\adjusttoctitle{\tl}|.
+
+\def \toctl;{\adjusttoctitle{\tl}} %^title_adj
+
+%~ This command is equivalent to |\adjustminitoctitle{\nl}|.
+
+\def \minitocnl;{\adjustminitoctitle{\nl}} %^title_adj
+
+%~ This command is equivalent to |\adjustminitoctitle{\tl}|.
+
+\def \minitoctl;{\adjustminitoctitle{\tl}} %^title_adj
+
diff --git a/macros/plain/contrib/zztex/tex/zztures.tex b/macros/plain/contrib/zztex/tex/zztures.tex
new file mode 100644
index 0000000000..60f86eb367
--- /dev/null
+++ b/macros/plain/contrib/zztex/tex/zztures.tex
@@ -0,0 +1,24 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% Module: ZzTeX TeXtures Interface
+%
+% Synopsis: This module provides replacement definitions for things
+% that are different in TeXtures.
+%
+% Author: Paul C. Anagnostopoulos
+% Created: 17 March 1994
+%
+% Copyright 1989--2020 by Paul C. Anagnostopoulos
+% under The MIT License (opensource.org/licenses/MIT)
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% Unencodable Characters
+% ----------- ----------
+
+
+\def \PSbackslash {$\backslash$}
+\def \PSbar {$\vert$}
+\def \PSbullet {$\bullet$}
+\def \PSdollar {\char "24}
+\def \PSunderscore {\kern .06em \vbox{\hrule width .3em}}
diff --git a/macros/plain/contrib/zztex/tex/zzver.tex b/macros/plain/contrib/zztex/tex/zzver.tex
new file mode 100644
index 0000000000..7b3fd2bfa2
--- /dev/null
+++ b/macros/plain/contrib/zztex/tex/zzver.tex
@@ -0,0 +1 @@
+\def \ZzTeXversion {17.7}
diff --git a/macros/plain/contrib/zztex/tex/zzvmode.tex b/macros/plain/contrib/zztex/tex/zzvmode.tex
new file mode 100644
index 0000000000..a81b33d2bd
--- /dev/null
+++ b/macros/plain/contrib/zztex/tex/zzvmode.tex
@@ -0,0 +1,380 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% Module: ZzTeX Vertical Mode Facilities
+%
+% Synopsis:
+%
+% Author: Paul C. Anagnostopoulos
+% Created: 21 September 1989
+%
+% Copyright 1989--2020 by Paul C. Anagnostopoulos
+% under The MIT License (opensource.org/licenses/MIT)
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% Interline Skip
+% --------- ----
+
+
+\def \nointerlineskip {%
+ \prevdepth = -1000pt}
+
+\def \offinterlineskip {%
+ \baselineskip = -1000pt
+ \lineskip = 0pt
+ \lineskiplimit = \maxdimen}
+
+% Vertical Skiping Environment
+% -------- ------- -----------
+
+
+% The following registers make up the vertical skiping environment.
+
+\definecount{\zvskenvtype}{0} % Previous vertical skip type.
+\definecount{\zvskenvpen}{0} % Previous columnbreak penalty.
+\defineskip{\zvskenvreq}{0pt} % Previous required base-to-base skip.
+\defineskip{\zvskenvskip}{0pt} % Previous actual skip amount.
+
+\chardef \zvskenvdiscard = 0 % Just initialized the environment.
+\chardef \zvskenvpar = 1 % Previous element was a paragraph.
+\chardef \zvskenvabove = 2 % Just finished an above skip.
+\chardef \zvskenvbelow = 3 % Just finished a below skip.
+\chardef \zvskenvmath = 4 % Previous element was a paragraph ending
+ % with a math display.
+
+\definecount{\zvskenvnopen}{20000\relax}
+
+\let \noskip = \mindimen
+
+
+% The vertical skiping environment is maintained in the vertical context.
+
+\zdeclareeveryvcontext{\zvskenvvcontext}
+
+\def \zvskenvvcontext {%
+ \zsavevcontext{\zvskenvtype=\the\zvskenvtype
+ \zvskenvpen=\the\zvskenvpen
+ \zvskenvreq=\the\zvskenvreq
+ \zvskenvskip=\the\zvskenvskip}%
+ \zvskpar
+ \global\zvskenvtype = \zvskenvdiscard}
+
+% Base-to-Base Skiping
+% ------------ -------
+
+
+\declareeverypar{\zvskpar}
+
+\def \zvskpar {%
+ \global\zvskenvtype = \zvskenvpar
+ \global\zvskenvpen = \zvskenvnopen
+ \global\zvskenvreq = \parskip \global\advance \zvskenvreq by \baselineskip
+ \global\zvskenvskip = 0pt}
+
+
+%~ This command produces vertical space so that the base-to-base
+%~ distance above the next element is equal to the *glue*. The
+%~ space is preceded by the specified *penalty*. If there is a font
+%~ change for the next element, it must be specified before this command.
+
+\def \bbskipabove #1#2{% {penalty}{glue} %^vspace
+ \if \neqlp{\zvskenvtype}{\zvskenvdiscard}%
+ {\zvskprevmath{\parskip}{\baselineskip}%
+ \zparseglue #2\zmark
+ \setflag \znosk = {\dimeqlp{\zskipa}{\noskip}}%
+ \vpenalty{#1}%
+ \ifcase \zvskenvtype
+ \relax
+ \or
+ \if \znosk \zskipa = \zvskenvreq \fi
+ \or
+ \zskipa = \zvskenvreq
+ \or
+ \if \dimlssp{\zskipa}{\zvskenvreq}\zskipa = \zvskenvreq \fi
+ \or
+ \if \dimlssp{\zskipa}{\zvskenvreq}\zskipa = \zvskenvreq \fi
+ \fi
+ \if \notp{\dimzerop{\zvskenvskip}}\vskip -\zvskenvskip \fi
+ \zskipb = \zskipa
+ \advance \zskipb by -\parskip
+ \advance \zskipb by -\baselineskip
+ \vskip \zskipb
+ \if \notp{\znosk}%
+ \global\zvskenvtype = \zvskenvabove
+ \global\zvskenvreq = \zskipa
+ \fi
+ \global\zvskenvskip = \zskipb}%
+ \fi}
+
+%~ This command produces vertical space so that the base-to-base
+%~ distance below the current element is equal to the *glue*. The
+%~ space is preceded by the specified *penalty*.
+
+\def \bbskipbelow #1#2{% {penalty}{glue} %^vspace
+ \zvskbelow{#1}{#2}{\parskip}{\baselineskip}}
+
+\def \bbskipbelowblock #1#2{% {penalty}{glue}
+ \zvskbelow{#1}{#2}{\enclosingparskip}{\enclosingbaselineskip}}
+
+% This macro "returns" a value in \parnext:
+% \noindent if next token does not start a new paragraph.
+% empty if next token starts a new paragraph.
+
+\def \bbskipbelowblockpar #1#2#3{% {token}{penalty}{glue}
+ {\setflag \znext = \false % Set \true if token starts new paragraph.
+ \ifcat \noexpand#1\relax \setflag \znext = \true \fi
+ \ifcat \noexpand#1\endgraf \setflag \znext = \true \fi
+ \ifcat \noexpand#1\egroup \setflag \znext = \true \fi
+ \ifcat \noexpand#1&\setflag \znext = \true \fi
+ \ifx #1\noindent \setflag \znext = \false \fi
+ \xdef \parnext {\if \znext \else \noindent \fi}%
+ \zskipa = #3\relax
+ \if \andp{\znext}{\dimneqlp{#3}{\noskip}}%
+ \tdimena = \zskipa
+ \advance \zskipa by -\tdimena
+ \advance \zskipa by \enclosingparskip
+ \advance \zskipa by \enclosingbaselineskip
+ \if \dimlssp{\zskipa}{#3}\zskipa = #3\fi
+ \fi
+ \zvskbelow{#2}{\zskipa}{\enclosingparskip}{\enclosingbaselineskip}}}
+
+\def \zvskbelow #1#2#3#4{% {penalty}{glue}{parskip}{baselineskip}
+ {\zvskprevmath{#3}{#4}%
+ \zparseglue #2\zmark
+ \setflag \znosk = {\dimeqlp{\zskipa}{\noskip}}%
+ \vpenalty{#1}%
+ \ifcase \zvskenvtype
+ \zzerror{Skiping type is discard}%
+ \or
+ \if \znosk \zskipa = #3 \advance \zskipa by #4\fi
+ \or
+ \error{skipab}{A `skip below' follows a `skip above'}%
+ \or
+ \if \znosk \zskipa = \zvskenvreq \fi
+ \or
+ \if \dimlssp{\zskipa}{\zvskenvreq}\zskipa = \zvskenvreq \fi
+ \fi
+ \if \notp{\dimzerop{\zvskenvskip}}\vskip -\zvskenvskip \fi
+ \zskipb = \zskipa
+ \advance \zskipb by -#3%
+ \advance \zskipb by -#4%
+ \vskip \zskipb
+ \if \notp{\znosk}%
+ \if \neqlp{\zvskenvtype}{\zvskenvmath}% % Stay as math type so
+ \global\zvskenvtype = \zvskenvbelow % subsequent below skip
+ \fi % won't override.
+ \global\zvskenvreq = \zskipa
+ \fi
+ \global\zvskenvskip = \zskipb}}
+
+\def \zvskprevmath #1#2{% {parskip}{baselineskip}
+ \if \eqlp{\mathdisplayprevgraf}{\prevgraf}%
+ \global\zvskenvtype = \zvskenvmath
+ \global\zvskenvpen = \mathdisplayprevpenalty
+ \global\zvskenvreq = \mathdisplayprevskip
+ \global\advance \zvskenvreq by #1
+ \global\advance \zvskenvreq by #2
+ \global\zvskenvskip = \mathdisplayprevskip
+ \global\mathdisplayprevgraf = -1\relax
+ \fi}
+
+%~ This command forces the next base-to-base skip command
+%~ regardless of the relationship between the previous element
+%~ and the next one.
+
+\def \forcenextbbskip {% %^vspace
+ \global\zvskenvtype = \zvskenvpar
+ \global\mathdisplayprevgraf = -1\relax}
+
+\definecount{\zvpen}{0}
+
+\def \vpenalty #1{% {penalty}
+ \zvpen = \if \emptyargp{#1}\breaknever \else #1\fi
+ \if \orp{\eqlp{\zvskenvpen}{\zvskenvnopen}}
+ {\eqlp{\zvpen}{\breaknever}}%
+ \columnbreak{\zvpen}%
+ \global\zvskenvpen = \zvpen\relax
+ \else \if \andp{\posp{\zvskenvpen}}{\gtrp{\zvpen}{\zvskenvpen}}%
+ \columnbreak{\zvpen}%
+ \global\zvskenvpen = \zvpen\relax
+ \fi\fi}
+
+\def \forcenextpenalty {%
+ \global\zvskenvpen = \zvskenvnopen}
+
+\def \repeatpenalty {%
+ \if \neqlp{\zvskenvpen}{\zvskenvnopen}%
+ \columnbreak{\zvskenvpen}%
+ \fi}
+
+%~ This command inserts the specified amount of extra vertical space
+%~ between the previous element and the next one.
+
+\def \vspace #1{% {glue} %^vspace
+ \if \neqlp{\zvskenvtype}{\zvskenvdiscard}%
+ \zparseglue #1\zmark
+ \vskip \zskipa
+ \fi}
+
+%~ This command inserts extra vertical space between the previous element
+%~ and the next one. The space is measured in lines; a fractional number
+%~ is allowed.
+
+\def \linespace #1{\vspace{#1\baselineskip}}% {lines} %^vspace
+
+\def \zparseglue #1#2\zmark{% {token}{tokens...}
+ \def \znext {#1}%
+ \def \zskip {\skip}%
+ \if \tokeqlp{\znext}{\zskip}%
+ \setskip \zskipa = #2\relax
+ \else
+ \zskipa = #1#2\relax
+ \fi}
+
+% Top to Text Skipping
+% --- -- ---- --------
+
+
+% These commands use \zskipb so as not to screw up \fakepar.
+
+\def \vsinkfromtypearea #1{% {sinkage}
+ \endgraf
+ \nobreak % So \fakepar can't break.
+ \fakepar % So \bbskipabove won't discard.
+ \vbox{}% % Force start of page if not already.
+ \kern -\pagetotal
+ \kern -\headerheight
+ \bbskipabove{\breaknever}{#1}}
+
+\let \vsink = \vsinkfromtypearea
+
+\def \vsinkfromtrim #1{% {sinkage}
+ \zskipb = #1\relax
+ \advance \zskipb by -\headmargin
+ \vsinkfromtypearea{\zskipb}}
+
+\def \vsinkfromtextarea #1{% {sinkage}
+ \zskipb = #1\relax
+ \advance \zskipb by \headerheight
+ \if \topdeltaadjustment
+ \advance \zskipb by \topdelta
+ \fi
+ \vsinkfromtypearea{\zskipb}}
+
+% Rules
+% -----
+
+
+\def \parrule #1#2{% {shift}{dimensions}
+ \endgraf
+ {\if \notp{\baselinetoprules}\zadjrule{#2}\fi
+ \hfuzz = 100pc
+ \noindent \hspace{#1}\vbox{\hrule height 0pt depth 0pt #2}\endgraf}}
+
+\def \colorparrule #1#2#3{% {color}{shift}{dimensions}
+ \endgraf
+ {\if \notp{\baselinetoprules}\zadjrule{#3}\fi
+ \hfuzz = 100pc
+ \noindent \hspace{#2}%
+ \color{#1}\vbox{\hrule height 0pt depth 0pt #3}\endcolor \endgraf}}
+
+\def \scotchrule #1#2#3{% {shift}{width}{height,gap,...}
+ \endgraf
+ {\hfuzz = 100pc
+ \commalist{\zscotchlist}{#3}%
+ \tcounta = 1\relax
+ \maplist{\zscotchb{#1}{#2}{##1}}{\zscotchlist}}}
+
+\def \zscotchb #1#2#3{% {shift}{width}{dimension}
+ \if \andp{\eqlp{\tcounta}{1}}{\notp{\baselinetoprules}}%
+ \zadjrule{height #3 depth 0pt}%
+ \fi
+ \if \oddp{\tcounta}
+ \noindent \hspace{#1}\vbox{\hrule height #3 depth 0pt width #2}\endgraf
+ \parskip = 0pt
+ \else
+ \nobreak
+ \vspace{#3}%
+ \nointerlineskip
+ \fi
+ \increment \tcounta}
+
+\def \zadjrule #1{% {dimensions}
+ \if \notp{\innermodep}%
+ \fakepar
+ \tdimena = \baselineskip
+ \advance \tdimena by -\prevdepth
+ \setbox \zboxa = \hbox{\vrule #1}%
+ \advance \tdimena by -\ht\zboxa
+ \vskip \tdimena
+ \vskip \topskip
+ \rule{height 0pt depth 0pt width 0pt}%
+ \penalty \breaknever
+ \vskip -\topskip
+ \parskip = 0pt \baselineskip = \ht\zboxa
+ \fi}
+
+% Vertical Alignment
+% -------- ---------
+
+
+\def \bottomout {%
+ \hrule width 0pt height 0pt % Make sure \vskip isn't discarded.
+ \vskip 0pt plus 1filll}
+
+% Counting Lines
+% -------- -----
+
+
+\definecount{\zlinect}{0}
+
+
+\def \countlines #1#2#3#4{% {\count}{width}{font}{text}
+ \setbox\zboxa = \vbox{%
+ \hsize = #2%
+ #3%
+ #4\par}%
+ \global\zlinect = 0
+ \setbox\zboxa = \vbox{\unvbox\zboxa \zscanvbox}%
+ #1=\zlinect}
+
+\def \zscanvbox {%
+ \loop
+ \setflag \zscanagain = \false
+ \setbox\zboxa = \lastbox
+ \if \hboxp{\zboxa}%
+ \global\increment \zlinect
+ \setflag \zscanagain = \true
+ \else\if \notp{\dimzerop{\lastskip}}%
+ \unskip
+ \setflag \zscanagain = \true
+ \else\if \notp{\dimzerop{\lastkern}}%
+ \unkern
+ \setflag \zscanagain = \true
+ \else\if \notp{\zerop{\lastpenalty}}%
+ \unpenalty
+ \setflag \zscanagain = \true
+ \fi\fi\fi\fi
+ \if \zscanagain \repeat}
+
+% Special Boxes
+% ------- -----
+
+
+\definedimen{\zibprevdepth}{0pt}
+
+
+\long\def \interjectbox #1#2{% {right-shift}{content}
+ {\zibprevdepth = \prevdepth
+ \penalty \breaknever
+ \nointerlineskip
+ \moveright #1 \vbox to 0pt{%
+ \zpushvcontext
+ #1\relax
+ \zpopvcontext}%
+ \prevdepth = \zibprevdepth}}
+
+\long\def \smashbox #1{%
+ \vbox to 0pt{%
+ #1\relax
+ \vss}} \ No newline at end of file
diff --git a/macros/plain/contrib/zztex/tex/zzxref.tex b/macros/plain/contrib/zztex/tex/zzxref.tex
new file mode 100644
index 0000000000..a0771f3910
--- /dev/null
+++ b/macros/plain/contrib/zztex/tex/zzxref.tex
@@ -0,0 +1,245 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% Module: ZzTeX Cross-Referencing Facilities
+%
+% Synopsis:
+%
+% Author: Paul C. Anagnostopoulos
+% Created: 19 September 1989
+%
+% Copyright 1989--2020 by Paul C. Anagnostopoulos
+% under The MIT License (opensource.org/licenses/MIT)
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% Data Structures
+% ---- ----------
+
+
+\definewrite{\zxrootfile}
+
+\definewrite{\zxdivfile}
+\setflag \zxdivopen = \false
+
+\definewrite{\zxcompfile}
+\setflag \zxcompavail = \false
+
+\chardef \xrefbadmode = 0 % Invalid mode.
+\chardef \xrefrunmode = 1 % Normal running environment.
+\chardef \xrefsnapmode = 2 % Taking a division snapshot.
+\chardef \xrefcopymode = 3 % Copying cross-reference files.
+\chardef \xrefloadmodes = 4 % Beginning of load modes:
+\chardef \xrefloadtagmode = 5 % Load tag definitions.
+\chardef \xrefloadtocmode = 6 % Load table of contents.
+\chardef \xrefloadauxmode = 7 % Create BibTeX auxiliary file.
+\chardef \xrefloadendmode = 8 % Load endnotes.
+\chardef \xrefloadcitemode = 9 % Load citation folios.
+
+\let \xrefmode = \xrefbadmode % Default mode.
+
+% Comment Lines
+% ------- -----
+
+
+{\catcode`\%=\catother
+\gdef \zcomment {%\space}
+} % \catcode
+
+
+\def \zxwritecomment #1#2#3{% {file}{keyword}{values}
+ \immediate\write #1 {\zcomment #2: #3}}
+
+% Initialization
+% --------------
+
+
+\def \zxrefinit {%
+ \zxcompinit
+ \zxopenroot
+ \let \xrefmode = \xrefrunmode}
+
+\def \zxcompinit {%
+ \checkfile{\zxcompavail}{\jobname.zzc}%
+ \if \zxcompavail
+ \zxloadcomp{\xrefloadtagmode}%
+ \else
+ \checkfile{\zxcompavail}{\jobname.zzx}%
+ \if \zxcompavail
+ \zxgencomp
+ \zxloadcomp{\xrefloadtagmode}%
+ \else
+ \remark{There is no cross-reference file available for this run.}%
+ \fi
+ \fi}
+
+\def \zxopenroot {%
+ \immediate\openout \zxrootfile = \jobname.zzx\relax
+ \zxwritecomment{\zxrootfile}{root}{\jobname}}
+
+% Division Handling
+% -------- --------
+
+
+\def \zxdivinit #1#2{% {division-name}{setting-it?}
+ \immediate\write \zxrootfile {\noexpand\zinputzzx{#1}}%
+ \if #2%
+ \immediate\openout \zxdivfile = #1.zzx\relax
+ \global\setflag \zxdivopen = \true
+ \zxwritecomment{\zxdivfile}{division}{#1}%
+ \immediate\write \zxdivfile
+ {\noexpand\xref{div}{}{}{}{\the\divisionname}\zcomment}%
+ \fi}
+
+% There is nothing to do with each entry in the cross-reference file.
+
+\def \xrefdiv #1#2#3#4{}
+
+
+\def \zxdivfinal #1{%
+ \if \zxdivopen
+ \ztakesnap
+ \zxwritecomment{\zxdivfile}{end}{#1}%
+ \immediate\closeout \zxdivfile
+ \global\setflag \zxdivopen = \false
+ \fi}
+
+% Finalization
+% ------------
+
+
+\def \zxreffinal {%
+ \zxwritecomment{\zxrootfile}{end}{\jobname}%
+ \immediate\closeout \zxrootfile
+ \zxgencomp}
+
+% Generate Composite File
+% -------- --------- ----
+
+
+\def \zxgencomp {%
+ \remark{Generating composite cross-reference file:}%
+ \immediate\openout \zxcompfile = \jobname.zzc\relax
+ \zxwriteinfo{\true}{jobname}{\jobname}{}%
+ \zxwriteinfo{\true}{time}{\number\year.\number\month.\number\day}{\formattime}%
+ \zxwriteinfo{\true}{version}{\ZzTeXversion}{}%
+ \zxwriteinfo{\true}{author}{\bookauthor}{}%
+ \zxwriteinfo{\true}{title}{\booktitle}{}%
+ \zxwriteinfo{\true}{publisher}{\bookpublisher}{}%
+ \zxwriteinfo{\true}{ISBN}{\bookISBN}{}%
+ \zxwriteinfo{\true}{art-root}{\zartroot}{}%
+ \zxwriteinfo{\true}{place-art}{\zplaceart}{}%
+ \zxwriteinfo{\true}{PDF-hyperlinks}{\PDFhyperlinks}{}%
+ \zxwriteinfo{\true}{proof}{\the\zproofid}{}%
+ \zxwriteinfo{\true}{compositor}{\ininame}{\iniorganization}%
+ \zxwriteinfo{\true}{trim}{\the\trimwidth}{\the\trimheight}%
+ \zxwriteinfo{\true}{head-margin}{\the\headmargin}{}%
+ \zxwriteinfo{\true}{inner-margin}{\the\eveninnermargin}{\the\oddinnermargin}%
+ \let \zxmodesave = \xrefmode
+ \let \xrefmode = \xrefcopymode
+ \input \jobname.zzx\relax
+ \let \xrefmode = \zxmodesave
+ \zxwritecomment{\zxcompfile}{end}{\jobname}%
+ \immediate\closeout \zxcompfile}
+
+% This macro writes an information entry in the composite cross-reference
+% file.
+
+\def \zxwriteinfo #1#2#3#4{% {composite?}{key}{value1}{value2}
+ \if #1%
+ \immediate\write \zxcompfile {\noexpand\xref{info}{}{#2}{#3}{#4}\zcomment}%
+ \else
+ \zbeginhidewrite
+ \edef \znext {\noexpand\xref{info}{\noexpand\folio}%
+ {#2}%
+ {#3}
+ {#4}}%
+ \znext
+ \zendhidewrite
+ \fi}
+
+%%% \immediate\write #1{\noexpand\xref{info}{#2}{#3}{#4}{\noexpand\folio}\zcomment}}
+
+% There is nothing to do when info entries are executed.
+
+\def \xrefinfo #1#2#3#4{}
+
+% This macro is used in the root cross-reference file to suck in the
+% division cross-reference files.
+
+\def \zinputzzx #1{%
+ \checkfile{\znext}{#1.zzx}%
+ \if \znext \input #1.zzx \fi}
+
+% Load Composite File
+% ---- --------- ----
+
+
+\def \zxloadcomp #1{% {xref-mode}
+ \if \zxcompavail
+ \let \zxmodesave = \xrefmode
+ \let \xrefmode =#1%
+ \input \jobname.zzc\relax
+ \let \xrefmode = \zxmodesave
+ \fi}
+
+\def \zxloadothercomp #1#2{% {file}{xref-mode}
+ \let \zxmodesave = \xrefmode
+ \let \xrefmode = #2%
+ \input #1\relax
+ \let \xrefmode = \zxmodesave}
+
+\def \loadrelatedxref #1{% {file}
+ \zxloadothercomp{#1}{\xrefloadtagmode}}
+
+% Cross-Reference Macro
+% --------------- -----
+
+
+% Here's how the arguments are treated in each of the modes:
+%
+% Mode type page arg3 title arg5
+%
+% load expanded --- passed to appropriate \xrefxxx macro ---
+% copy expanded expanded expanded unexpanded expanded
+% run expanded unexpanded expanded unexpanded expanded
+% snap expanded expanded expanded expanded expanded
+
+% This macro is written for speed.
+
+\long\def \xref #1#2#3#4#5{% {type}{page-number}{arg3}{title}{arg5}
+ \ifnum \xrefmode>\xrefloadmodes
+ \name{\xref#1}{#2}{#3}{#4}{#5}%
+ \else\ifnum \xrefmode=\xrefcopymode
+ {\def \zxtitle {#4}%
+ \immediate\write \zxcompfile {\noexpand\xref{#1}{#2}{#3}%
+ {\expandafter\zdefof \meaning\zxtitle\zmark}{#5}\zcomment}}%
+ \name{\xref#1}{#2}{#3}{#4}{#5}% In case they want to do something.
+ \else\ifnum \xrefmode=\xrefrunmode
+ {\def \zxtitle {#4}%
+ \edef \znext {\noexpand\noexpand\noexpand\xref
+ {#1}{\noexpand#2}{#3}%
+ {\expandafter\zdefof \meaning\zxtitle\zmark}{#5}}%
+ \expandafter\zxwrite\expandafter{\znext\zcomment}}%
+ \if \vmodep \repeatpenalty \fi % In case glue follows write.
+ \else\ifnum \xrefmode=\xrefsnapmode
+ \immediate\zxwrite{\noexpand\xref{#1}{#2}{#3}{#4}{#5}\zcomment}%
+ \else
+ \zxnomode
+ \fi\fi\fi\fi}
+
+\def \zxwrite {%
+ \if \zxdivopen \write \zxdivfile \else \write \zxrootfile \fi}
+
+\def \zxnomode {%
+ \zzerror{No cross-reference mode is set}}
+
+% Page Hints
+% ---- -----
+
+
+\def \pagehint #1{%
+ \xref{hint}{\noexpand\folio}{}{#1}{}}
+
+% There is nothing to do when hint entries are executed.
+
+\def \xrefhint #1#2#3#4{}