% xeplain.tex: macros for nonformatting. Written 1989--94 by (mostly)
% Karl Berry. These macros are in the public domain.
%
% This is the ``extended plain'' TeX format that's described in
% `eplain.texinfo', which you should have received with this file. We
% assume plain has been loaded.
%
% N.B.: A version number is defined at the beginning and end of this file;
% please change those numbers whenever the file is modified!
% And don't modify the file under any circumstances; rename it first.
%
% Some macros were written and/or suggested by Paul Abrahams.
% Other sources (e.g., The TeXbook) are cited at the appropriate places.
%
%% @texfile{
%% author = "Karl Berry",
%% version = "REPLACE-WITH-VERSION",
%% date = "REPLACE-WITH-DATE",
%% filename = "xeplain.tex",
%% email = "[email protected]",
%% address = "135 Center Hill Rd. // Plymouth, MA 02360"
%% checksum = "REPLACE-WITH-CHECKSUM",
%% codetable = "ISO/ASCII",
%% supported = "yes",
%% docstring = "This file defines macros that extend and expand on
%% plain TeX. eplain.tex is xeplain.tex and the other
%% source files with comments stripped; see the original
%% files for author credits, etc. And please base diffs
%% or other contributions on xeplain.tex, not the
%% stripped-down eplain.tex.",
%% }
%
%
% Category codes, etc.
%
\def\makeactive#1{\catcode`#1 = \active \ignorespaces}%
\chardef\letter = 11
\chardef\other = 12
%
%
% So we can have user-inaccessible control sequences.
%
\edef\leftdisplays{\the\catcode`@}%
\catcode`@ = \letter
\let\@eplainoldatcode = \leftdisplays
%
% Save miniscule amounts of memory and time by writing \toks@ii instead
% of \toks2.
\toksdef\toks@ii = 2
%
%
% This macro is defined in The TeXbook, but it never made it
% into plain TeX. \dospecials is defined there, though.
%
\def\uncatcodespecials{%
\def\do##1{\catcode`##1 = \other}%
\dospecials
}%
%
%
% Here is a way to do \let^^M = \cs, where the \let need not be global.
{%
\makeactive\^^M %
\long\gdef\letreturn#1{\let^^M = #1}%
}%
%
%
% Swallow parameters, etc.
%
\let\@eattoken = \relax % Define this, so \eattoken can be used in \edef.
\def\eattoken{\let\@eattoken = }%
\def\gobble#1{}%
\def\gobbletwo#1#2{}%
\def\gobblethree#1#2#3{}%
%
% We can't just use \empty as the identity function, since then outer
% braces which would supposedly delimit the argument would define a group.
\def\identity#1{#1}%
%
% True if #1 is the empty string, i.e., called like `\ifempty{}'.
\def\ifempty#1{\@@ifempty #1\@emptymarkA\@emptymarkB}%
\def\@@ifempty#1#2\@emptymarkB{\ifx #1\@emptymarkA}%
%
% Turn a definition into the characters that compose it. See
% ``Sanitizing control sequences under \write'', by Ron Whitney, TUGboat
% 11(4), p.620.
\def\@gobblemeaning#1:->{}%
\def\sanitize{\expandafter\@gobblemeaning\meaning}%
%
%
% From p.308 of the TeXbook. This cannot be used in places where TeX
% might be skipping tokens, e.g., in conditionals.
%
\def\ifundefined#1{\expandafter\ifx\csname#1\endcsname\relax}%
%
%
% \csname constructions come up an awful lot, so we save typing with the
% following. (But the extra macro expansion does take time, so we don't
% use these in frequently-executed code.)
%
\def\csn#1{\csname#1\endcsname}%
\def\ece#1#2{\expandafter#1\csname#2\endcsname}%
%
%
% \expandonce{TOKEN} abbreviates \expandafter\noexpand TOKEN.
%
\def\expandonce{\expandafter\noexpand}%
%
%
% Don't show our register allocations in the log.
%
\let\@plainwlog = \wlog
\let\wlog = \gobble
%
%
% Make it convenient to put newlines in error messages.
%
\newlinechar = `^^J
%
%
% Sometimes it is convenient to have everything in the transcript file
% and nothing on the terminal. We don't just call \tracingall here,
% since that produces some useless output on the terminal.
%
\def\gloggingall{\begingroup \globaldefs = 1 \loggingall \endgroup}%
\def\loggingall{\tracingcommands\tw@\tracingstats\tw@
\tracingpages\@ne\tracingoutput\@ne\tracinglostchars\@ne
\tracingmacros\tw@\tracingparagraphs\@ne\tracingrestores\@ne
\showboxbreadth\maxdimen\showboxdepth\maxdimen
}%
% Show the complete contents of boxes.
%
\def\tracingboxes{\showboxbreadth = \maxdimen \showboxdepth = \maxdimen}%
%
% Don't trace anything, except restore \showbox... to plain's values.
%
\def\gtracingoff{\begingroup \globaldefs = 1 \tracingoff \endgroup}%
\def\tracingoff{\tracingonline\z@\tracingcommands\z@\tracingstats\z@
\tracingpages\z@\tracingoutput\z@\tracinglostchars\z@
\tracingmacros\z@\tracingparagraphs\z@\tracingrestores\z@
\showboxbreadth5 \showboxdepth3
}%
%
%
% Definitions to produce actual `{' (et al.) characters in an output
% file via \write. We omit the line break after the first }, since we
% have no comment character at that point.
%
\begingroup
\catcode`\{ = 12 \catcode`\} = 12
\catcode`\[ = 1 \catcode`\] = 2
\gdef\lbracechar[{]%
\gdef\rbracechar[}]%
\catcode`\% = \other
\gdef\percentchar[%]\endgroup
%
%
% In order to do anything with ^^L inside a macro, it must
% be made non-\outer.
%
\def^^L{\par}%
%
%
% Leave horizontal mode (if we're in it), then insert a penalty.
% And conversely.
%
\def\vpenalty{\ifhmode\par\fi \penalty}%
\def\hpenalty{\ifvmode\leavevmode\fi \penalty}%
%
%
% Make \else usable in \loop. From Victor Eijkhout's TeX by Topic (page
% 104). See also Alois Kabelschacht, TUGboat 8(2), page 184.
%
\def\iterate{%
\let\next\relax
\body
\let\next\iterate
\fi
\next
}%
%
%
% Add #2 (which is expanded in an \edef) to the end of the definition of
% #1 (which must be a previously-defined control sequence). This is a
% way to construct simple lists.
%
\def\edefappend#1#2{%
\toks@ = \expandafter{#1}%
\edef#1{\the\toks@ #2}%
}%
%
%
%
% Hooks.
%
% \hookaction{HOOK}{TOKENS} adds TOKENS to the list of actions for
% HOOK. We avoid defining a \toks register for each hook, although
% maybe that isn't so important.
%
% \hookappend and \hookprepend add TOKENS specificially to the end or
% the beginning. When the argument is used, \toks@ will be the previous
% value of the hook, and \toks@ii the new tokens.
%
\long\def\hookprepend{\@hookassign{\the\toks@ii \the\toks@}}%
\long\def\hookappend{\@hookassign{\the\toks@ \the\toks@ii}}%
\let\hookaction = \hookappend % either one should be ok
%
%
% \@hookassign{LAST-DEF}{HOOK}{TOKENS} makes \toks@ the previous value
% of HOOK, and \toks@ii TOKENS, and then assigns the new value using
% LASTDEF. We store the hook in a control sequence \@HOOKhook.
%
\long\def\@hookassign#1#2#3{%
% Make \toks@ be the expansion (to one level) of \@HOOKhook, or empty.
\expandafter\ifx\csname @#2hook\endcsname \relax
% If \@HOOKhook was undefined, let it be empty.
\toks@ = {}%
\else
% Otherwise, expand it to one level. We can't just assign from
% \expandafter{\csname ...} since then the \toks register would
% contain the control sequence, not its definition.
\expandafter\let\expandafter\temp \csname @#2hook\endcsname
\toks@ = \expandafter{\temp}%
\fi
\toks2 = {#3}% Don't expand the argument all the way.
\ece\edef{@#2hook}{#1}%
}%
%
%
% \hookactiononce{HOOK}\CS adds `\global\let\CS=\relax' to the
% definition of \CS, then adds to HOOK. Thus, \CS is expanded the next
% time HOOK is called, but then it goes away. This only works if \CS is
% expandable, though.
%
\long\def\hookactiononce#1#2{%
\edefappend#2{\global\let\noexpand#2\relax}
\hookaction{#1}#2%
}%
%
%
% \hookrun{HOOKNAME} runs whatever actions have been defined for HOOK.
%
\def\hookrun#1{%
\expandafter\ifx\csname @#1hook\endcsname \relax \else
% Isn't this fun? We want to get rid of the \fi before expanding
% the actions, so that they can read what's coming up next.
\def\temp{\csname @#1hook\endcsname}%
\expandafter\temp
\fi
}%
%
%
%
% Properties a la Lisp.
%
% \setproperty{ATOM}{PROPNAME}{VALUE} defines the property PROPNAME on the
% ``atom'' ATOM to have VALUE.
%
\def\setproperty#1#2#3{\ece\edef{#1@p#2}{#3}}%
%
%
% \getproperty{ATOM}{PROPNAME} expands to the value of the property
% PROPNAME on ATOM, or to nothing (i.e., \empty), if the property isn't
% present.
%
\def\getproperty#1#2{%
\expandafter\ifx\csname#1@p#2\endcsname\relax
% then \empty
\else \csname#1@p#2\endcsname
\fi
}%
%
%
%
% Macros to support BibTeX are in a separate file, btxmac.tex.
%
% (They are maintained separately, too, by Oren Patashnik,
% [email protected].) btxmac.tex also defines other macros we
% want to use and make available.
%
% But not all people want to read the BibTeX macros, because of either
% space or time considerations. Therefore, we look for \nobibtex,
% which, if defined, causes btxmac.tex not to be read. But we still
% have to get \tokstostring et al. defined---so eplain.tex contains
% those definitions, automatically edited in from btxmac.tex. All the
% documentation has been removed, so you must read btxmac.tex if you
% want the comments.
%
%
% We want to give a slightly different message than btxmac if no .aux
% file exists (unless the person using us has already define some
% message, possibly empty.)
%
\ifx\@undefinedmessage\@undefined
\def\@undefinedmessage
{No .aux file; I won't warn you about undefined labels.}%
\fi
%
%
% We use a token register to define all the BibTeX definitions, to avoid
% problems with the \if... constructions when they are conditionally
% read.
%
%% [[[here is the first set of common definitions from btxmac]]]
\toks0 = {%
%% [[[here are the BibTeX-specific definitions from btxmac]]]
}%
\ifx\nobibtex\@undefined \the\toks0 \fi
%% [[[here is the second set of common definitions from btxmac]]]
%
% Here are the control sequences that btxmac.tex defines using an @,
% because btxmac.tex wants to absolutely minimize the chance of
% conflicts. But these control sequence implement documented features
% of eplain, so we want to allow people to use them without the @.
%
\let\auxfile = \@auxfile
\let\for = \@for
\let\futurenonspacelet = \@futurenonspacelet
\def\iffileexists{\if@fileexists}%
\let\innerdef = \@innerdef
\let\innernewcount = \@innernewcount
\let\innernewdimen = \@innernewdimen
\let\innernewif = \@innernewif
\let\innernewwrite = \@innernewwrite
\let\linenumber = \@linenumber
\let\readauxfile = \@readauxfile
\let\spacesub = \@spacesub
\let\testfileexistence = \@testfileexistence
\let\writeaux = \@writeaux
%
%
% btxmac.tex defines \innerdef. Let's use it to make an abbreviation
% for \innerdef\inner<name>{<name>}.
%
\def\innerinnerdef#1{\expandafter\innerdef\csname inner#1\endcsname{#1}}%
%
% Use that in turn to make non-outer versions of the rest of plain TeX's
% allocation macros. (btxmac.tex already did a few of them.)
%
\innerinnerdef{newbox}%
\innerinnerdef{newfam}%
\innerinnerdef{newhelp}%
\innerinnerdef{newinsert}%
\innerinnerdef{newlanguage}%
\innerinnerdef{newmuskip}%
\innerinnerdef{newread}%
\innerinnerdef{newskip}%
\innerinnerdef{newtoks}%
%
%
% Besides doing a \write to the aux file, we also need to do an
% \immediate\write.
%
\def\immediatewriteaux#1{%
\ifx\noauxfile\@undefined
\immediate\write\@auxfile{#1}%
\fi
}%
%
%
%
% Macros that produce output.
%
% \obeywhitespace makes both end-of-lines and spaces in the input be
% respected in the output. Even spaces at the beginning of lines turn
% into blank space the size of the natural space of the current font.
% The reason why plain TeX's \obeyspaces does not do this last is that
% it produces actual space characters, i.e., glue, and glue is discarded
% at a(n output) line break, and so if line breaks in the input are
% line breaks in the output...
%
% Tabs are not affected; they will still produce glue (a single space).
%
\begingroup
\makeactive\^^M \makeactive\ % No spaces or ^^M's from here on.
\gdef\obeywhitespace{%
\makeactive\^^M\def^^M{\par\futurelet\next\@finishobeyedreturn}%
\makeactive\ \let =\ %
%
% The group we use here is the one \obeywhitespace must be enclosed in.
% If we don't do this, then if the obeyed stuff ends in a newline, the
% indent produced by the definition of ^^M will make that line indented,
% even if it isn't the end of the paragraph.
\aftergroup\@removebox%
\futurelet\next\@finishobeywhitespace%
}%
%
% \@finishobeywhitespace eats any spaces and/or the end-of-line after
% the \obeywhitespace command itself. The group here is the one that it
% itself creates.
%
\gdef\@finishobeywhitespace{{%
\ifx\next %
\aftergroup\@obeywhitespaceloop%
\else\ifx\next^^M%
\aftergroup\gobble%
\fi\fi}}%
%
% \@finishobeyedreturn is invoked at the end of every input line. We
% check if the next thing is also a return, and, if so, insert extra
% space. Then we start the next line.
%
\gdef\@finishobeyedreturn{%
\ifx\next^^M\vskip\blanklineskipamount\fi%
\indent%
}%
\endgroup
%
% The argument here is the space that we are supposed to eat after the
% \obeywhitespace command.
%
\def\@obeywhitespaceloop#1{\futurelet\next\@finishobeywhitespace}%
%
%
% This removes the last box, if it was a empty box of width \parindent.
% We might have been called inside a \vbox, so we have to test if we are
% in horizontal mode before using \lastbox.
%
\def\@removebox{%
\ifhmode
\setbox0 = \lastbox
\ifdim\wd0=\parindent
\setbox2 = \hbox{\unhbox0}%
\ifdim\wd2=0pt
% Don't put it back: it was an indentation box.
% This \ignorespaces ignores spaces after the group.
\ignorespaces
\else
\box2 % Put it back: it wasn't empty.
\fi
\else
\box0 % Put it back: it wasn't the right width.
\fi
\fi
}%
%
% We allow for extra (possibly negative) space when we hit blank lines.
%
\newskip\blanklineskipamount
\blanklineskipamount = 0pt
%
%
% A good way to print fractions in text when you don't want
% to use \over (which should be most of the time), and yet
% just `1/2' doesn't look right. (From the TeXbook,
% the answer to exercise 11.6, p.311.)
%
\def\frac#1/#2{\leavevmode
\kern.1em \raise .5ex \hbox{\the\scriptfont0 #1}%
\kern-.1em $/$%
\kern-.15em \lower .25ex \hbox{\the\scriptfont0 #2}%
}%
%
%
% The `e' just means `Eplain', as in `Eplain's hrule'. The advantage
% to using these is that you can change the default thickness.
%
\newdimen\hruledefaultheight \hruledefaultheight = 0.4pt
\newdimen\hruledefaultdepth \hruledefaultdepth = 0.0pt
\newdimen\vruledefaultwidth \vruledefaultwidth = 0.4pt
%
\def\ehrule{\hrule height\hruledefaultheight depth\hruledefaultdepth}%
\def\evrule{\vrule width\vruledefaultwidth}%
%
%
% The texnames.sty and path.sty files included below were originally
% written by Nelson Beebe and Philip Taylor, respectively. See the
% complete source files (e.g., in this distribution) for comments.
%% [[[include texnames.sty]]]
%% [[[include path.sty]]]
%
%
% A square box, suitable for being a marker in lists.
%
\def\blackbox{\vrule height .8ex width .6ex depth -.2ex \relax}% square bullet
%
%
% From p.311 of the TeXbook.
%
% Make an unfilled rectangle with the dimensions of \box0. #1 is the
% height of the rules, #2 the depth (i.e., the thicknesses).
%
\def\makeblankbox#1#2{%
\ifvoid0
\errhelp = \@makeblankboxhelp
\errmessage{Box 0 is void}%
\fi
\hbox{\lower\dp0
\vbox{\hidehrule{#1}{#2}%
\kern -#1% overlap rules
\hbox to \wd0{\hidevrule{#1}{#2}%
\raise\ht0\vbox to #1{}% vrule height
\lower\dp0\vtop to #1{}% vrule depth
\hfil\hidevrule{#2}{#1}%
}%
\kern-#1\hidehrule{#2}{#1}%
}%
}%
}%
%
\newhelp\@makeblankboxhelp{Assigning to the dimensions of a void^^J%
box has no effect. Do `\string\setbox0=\string\null' before you^^J%
define its dimensions.}%
%
%
% Produce an hrule with height #1 and depth #2, and insert kerning so it
% doesn't change the current position.
%
\def\hidehrule#1#2{\kern-#1\hrule height#1 depth#2 \kern-#2}%
%
% Produce a vrule with width #1+#2, kerning so as not to change the
% current position.
%
\def\hidevrule#1#2{%
\kern-#1%
\dimen@=#1\advance\dimen@ by #2%
\vrule width\dimen@
\kern-#2%
}%
%
%
% The \boxit macro from the TeXbook, trivially generalized to allow
% something other than 3pt around the TeX box being boxed.
%
\newdimen\boxitspace \boxitspace = 3pt
%
\long\def\boxit#1{%
\vbox{%
\ehrule
\hbox{%
\evrule
\kern\boxitspace
\vbox{\kern\boxitspace \parindent = 0pt #1\kern\boxitspace}%
\kern\boxitspace
\evrule
}%
\ehrule
}%
}%
%
%
% Produce the written-out form of a number.
%
\def\numbername#1{\ifcase#1%
zero%
\or one%
\or two%
\or three%
\or four%
\or five%
\or six%
\or seven%
\or eight%
\or nine%
\or ten%
\or #1%
\fi
}%
%
% The following arrow macros were written by Steven Smith. See arrow.tex.
\let\@plainnewif = \newif
\let\@plainnewdimen = \newdimen
\let\newif = \innernewif
\let\newdimen = \innernewdimen
\edef\@eplainoldandcode{\the\catcode`& }%
\catcode`& = 11
\toks0 = {%
%% [[[include arrow1]]]
}%
\catcode`& = 4
\toks2 = {%
%% [[[include arrow2]]]
}%
\let\newif = \@plainnewif
\let\newdimen = \@plainnewdimen
\ifx\noarrow\@undefined \the\toks0 \the\toks2 \fi
\catcode`& = \@eplainoldandcode
%
%
%
% Environments.
%
% Define an ``environment'': arbitrary text, enclosed by \begingroup and
% \endgroup. But you get to label the group, so that if you forget an
% \environment or an \endenvironment, you will probably get an error
% message about it.
%
% Since the environment names appear in \errmessage arguments, it's best
% to keep them to `letter' and `other' characters. I suppose we could
% call \tokstostring to allow more general labels.
%
% These macros improve slightly on the answer to exercise 5.7 in
% The TeXbook, by making some checks on \begingroup and \endgroup, as
% well as just making sure \environment and \endenvironment's match.
%
%
\def\environment#1{%
\ifx\@groupname\@undefined\else
% This gets invoked if we have two \environments (and no matching
% \endenvironment to the first) with an \endgroup in between.
\errhelp = \@unnamedendgrouphelp
\errmessage{`\@groupname' was not closed by \string\endenvironment}%
\fi
% Use \edef in case we are passed a macro that contains the name,
% instead of the name.
\edef\@groupname{#1}%
\begingroup
\let\@groupname = \@undefined
}%
%
\def\endenvironment#1{%
\endgroup
\edef\@thearg{#1}%
\ifx\@groupname\@thearg
\else
\ifx\@groupname\@undefined
% Unfortunately, one gets an `extra \endgroup' message before
% seeing this. But we have to restore \@groupname, so I see no
% alternative.
\errhelp = \@isolatedendenvironmenthelp
\errmessage{Isolated \string\endenvironment\space for `#1'}%
\else
\errhelp = \@mismatchedenvironmenthelp
\errmessage{Environment `#1' ended, but `\@groupname' started}%
\endgroup % Probably a typo in the names.
\fi
\fi
\let\@groupname = \@undefined
}%
%
\newhelp\@unnamedendgrouphelp{Most likely, you just forgot an^^J%
\string\endenvironment. Maybe you should try inserting another^^J%
\string\endgroup to recover.}%
%
\newhelp\@isolatedendenvironmenthelp{You ended an environment X, but^^J%
no \string\environment{X} to start it is anywhere in sight.^^J%
You might also be at an \string\endenvironment\space that would match^^J%
a \string\begingroup, i.e., you forgot an \string\endgroup.}%
%
\newhelp\@mismatchedenvironmenthelp{You started an environment named X, but^^J%
you ended one named Y. Maybe you made a typo in one^^J%
or the other of the names?}%
%
%
% The above sort of environment allows nesting. But environments
% shouldn't always be allowed to nest (like the \flushright,
% \flushleft, and \center ones defined below). Here are some macros to
% help deal with that.
%
% \checkenvironmentnesting goes at the beginning of a macro that is
% going to define the environment.
%
\newif\ifenvironment
\def\checkenv{\ifenvironment \errhelp = \@interwovenenvhelp
\errmessage{Interwoven environments}%
\egroup \fi
}%
%
\newhelp\@interwovenenvhelp{Perhaps you forgot to end the previous^^J%
environment? I'm finishing off the current group,^^J%
hoping that will fix it.}%
%
%
%
% Mathematics displays.
%
% By default, TeX centers displayed material. To get left-justified
% displays, say \leftdisplays. To go back to centered displays, say
% \centereddisplays.
%
% This is based on an approach developed by Donald Arseneau,
% [email protected].
%
\newtoks\previouseverydisplay
\newdimen\leftdisplayindent
\newif\if@leftdisplays
%
\def\leftdisplays{%
% IF we've already been called, do nothing.
\if@leftdisplays\else
\previouseverydisplay = \everydisplay
\everydisplay = {\the\previouseverydisplay \leftdisplaysetup}%
%
% Since we don't want to start a group (the \leftdisplays might
% well continue to the end of the document), we have to explicitly
% save and restore everything we change.
\let\@save@maybedisableeqno = \@maybedisableeqno
\let\@saveeqno = \eqno
\let\@saveleqno = \leqno
\let\@saveeqalignno = \eqalignno
\let\@saveleqalignno = \leqalignno
\let\@maybedisableeqno = \relax
\def\eqno{\hfill\textstyle\enspace}%
\def\leqno{%
\hfill
\hbox to0pt\bgroup
\kern-\displaywidth
\kern-\displayindent
$\aftergroup\@leftleqnoend
}%
\@redefinealignmentdisplays
\@leftdisplaystrue
\fi
}%
%
\def\centereddisplays{%
% If \leftdisplays hasn't been called, don't try to restore all the
% stuff it changes.
%
\if@leftdisplays
\everydisplay = \previouseverydisplay
\let\@maybedisableeqno = \@save@maybedisableeqno
\let\eqno = \@saveeqno
\let\leqno = \@saveleqno
\let\eqalignno = \@saveeqalignno
\let\leqalignno = \@saveleqalignno
\@leftdisplaysfalse
\fi
}%
%
\def\leftdisplaysetup{%
\hbox to\displaywidth\bgroup
\strut
\dimen@ = \parindent
\advance\dimen@ by \leftdisplayindent
\advance\dimen@ by \leftskip
\hskip\dimen@
% We can't use \displayindent all along, because then we would
% \hskip by the above plus \hangindent or \parshape indentation.
% See p.188.
\advance\displayindent by \dimen@
\advance\displaywidth by -\parindent
\advance\displaywidth by -\leftdisplayindent
\advance\displaywidth by -\leftskip
$%
%
% If we do a \noalign inside an \eqalignno, we will be in horizontal
% mode, and the line will be as wide as \hsize. This will cause an
% overfull alignment, since we also have to fit the indentation in,
% before the alignment.
\advance\hsize by -\displayindent
%
\aftergroup\@lefteqend
\displaystyle
}%
%
\def\@lefteqend{\hfil\egroup$}% gets inserted between the ending $$
\def\@leftleqnoend{\hss \egroup$}%
%
% Since the equation is typeset in math mode and not display math mode,
% \halign is illegal. So we use \vcenter, a la \eqalign, to make the
% \halign legal. Also, we remove the \hfil from the left of the
% template, to make the display come out flush left.
%
\def\@redefinealignmentdisplays{%
\def\displaylines##1{\displ@y
\vcenter{%
% We add another \hfil outside math mode in this template to cure
% underfull hboxes that sometimes result (from big fractions as in
% exercise 19.19). I'm not sure why DEK does \halign{\hbox to...}
% instead of just \halign to... here.
\halign{\hbox to\displaywidth{$\@lign\displaystyle####\hfil$\hfil}\crcr
##1\crcr}}}%
%
\def\eqalignno##1{\displ@y
\let\noalign = \@lefteqalignonoalign
\vcenter{%
\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
% Don't use the \eqno in \eqdef.
\let\eqno = \relax
\vcenter{%
\halign to\displaywidth{%
\hfil$\@lign\displaystyle{####}$\tabskip\z@skip
&$\@lign\displaystyle{{}####}$\hfil\tabskip\centering
&\kern-\displaywidth
\rlap{\kern-\displayindent $\@lign####$}%
\tabskip\displaywidth\crcr
##1\crcr}}}%
}%
%
% \noalign is typically used to insert a few words (`and', for example)
% between two aligned equations. So I don't think the \noaligned
% material should be indented. Since \noalign takes <vertical mode
% material>, we would end up with double indentation, anyway: one
% because we're indenting the whole display, and one at the start of the
% <v.m.m.>. (If you want to change any of this, you can put something in
% \@everynoalign.) So, we use this definition for \noalign in a
% left-justified \eqalignno:
%
\let\@primitivenoalign = \noalign
\newtoks\@everynoalign
\def\@lefteqalignonoalign#1{%
\@primitivenoalign{%
% Is it right to set \leftskip=0pt first, thus perhaps making this
% work in lists and so forth? We just compensate for the other ways
% the display is indented here.
\advance\leftskip by -\parindent
\advance\leftskip by -\leftdisplayindent
\parskip = 0pt
%
% We use \parindent=0pt instead of \noindent because the latter
% starts unrestricted horizontal mode, which means the alignment
% we're inside will wind up being as wide as the page. When the arg
% is just vertical material, this is wrong. For example, using
% \matrix inside \eqalignno fails if \noindent is used.
\parindent = 0pt
\the\@everynoalign
#1%
}%
}%
%
%
%
% Time macros.
%
% TeX sets \time, \day, \month, and \year when it begins. (And does not
% update them as it runs!)
%
%
% \monthname produces the name of the month, abbreviated to three
% letters. The primitive \month should never be zero.
%
\def\monthname{%
\ifcase\month
\or Jan\or Feb\or Mar\or Apr\or May\or Jun%
\or Jul\or Aug\or Sep\or Oct\or Nov\or Dec%
\fi
}%
%
% \fullmonthname is like \monthname, except it doesn't abbreviate.
%
\def\fullmonthname{%
\ifcase\month
\or January\or February\or March\or April\or May\or June%
\or July\or August\or September\or October\or November\or December%
\fi
}%
%
% \timestring produces the current time, in a format like `1:14 p.m.'.
%
\def\timestring{\begingroup
\count0 = \time
\divide\count0 by 60
\count2 = \count0 % The hour, from zero to 23.
%
\count4 = \time
\multiply\count0 by 60
\advance\count4 by -\count0 % The minute, from zero to 59.
% But we need the minutes with a leading zero, if necessary.
\ifnum\count4<10
\toks1 = {0}%
\else
\toks1 = {}%
\fi
%
% Convert the hour into `a.m.' or `p.m.', and make it mod 12.
\ifnum\count2<12
\toks0 = {a.m.}%
\else
\toks0 = {p.m.}%
\advance\count2 by -12
\fi
%
% If it's midnight, call it `12', not `0'.
\ifnum\count2=0
\count2 = 12
\fi
%
% Produce the output.
\number\count2:\the\toks1 \number\count4 \thinspace \the\toks0
\endgroup}%
%
%
% \timestamp produces a text string for the whole thing like
% `23 Apr 1964 1:14 p.m.'.
%
\def\timestamp{\number\day\space\monthname\space\number\year\quad\timestring}%
%
%
% \today produces the current date, as in `23 April 1964'.
%
\def\today{\the\day\ \fullmonthname\ \the\year}%
%
%
%
% (Typographical) lists.
%
% These macros can produce numbered or unnumbered lists.
%
% You can change the spacing by assigning new values to these registers.
% They are used by both kinds of lists. \listleftindent is relative to
% the current paragraph indentation, while \listrightindent is an
% absolute value. I do this for two reasons: (1) it is more useful, if not
% more ``logical'', to make list indentation depend on the paragraph
% indentation; (2) footnotes do not work if \parindent is zero, and
% having a footnote in a list item is perfectly reasonable.
%
% If you change \baselineskip and want \abovelistskip and \belowlistskip
% to retain their meanings here, you will have to reassign to them. The
% \baselineskip here is the value at the time eplain.tex is read, i.e.,
% 12pt (most likely).
%
% If the items in your lists are very long, you might want to
% make \interitemskipamount nonzero.
%
\newskip\abovelistskipamount \abovelistskipamount = .5\baselineskip
\newcount\abovelistpenalty \abovelistpenalty = 10000
\def\abovelistskip{\vpenalty\abovelistpenalty \vskip\abovelistskipamount}%
\newskip\interitemskipamount \interitemskipamount = 0pt
\newcount\belowlistpenalty \belowlistpenalty = -50
\def\belowlistskip{\vpenalty\belowlistpenalty \vskip\belowlistskipamount}%
\newskip\belowlistskipamount \belowlistskipamount = .5\baselineskip
\newcount\interitempenalty \interitempenalty = 0
\def\interitemskip{\vpenalty\interitempenalty \vskip\interitemskipamount}%
\newdimen\listleftindent \listleftindent = 0pt
\newdimen\listrightindent \listrightindent = 0pt
\let\listmarkerspace = \enspace
%
% To do arbitrary things at the start of each list:
\newtoks\everylist
%
% If you want no space between items for a particular list
% (perhaps because the items in it are short), you can say,
% e.g., \numberedlist\listcompact.
%
\def\listcompact{\interitemskipamount = 0pt \relax}%
%
% This is called to set up the parameters by both sorts of lists.
% Because we set \rightskip, we finish off the current paragraph.
%
\newdimen\@listindent
%
\def\beginlist{%
% Insert the space above this list, before we change \leftskip
% (because the \vskip in here might be what ends the paragraph).
\abovelistskip
%
\@listindent = \parindent
\advance\@listindent by \listleftindent
%
% \leftskip shifts nested lists to the right on the page.
\advance\leftskip by \@listindent
\advance\rightskip by \listrightindent
%
% We always need \itemnumber, so we can know whether an item is the
% first one or not.
\itemnumber = 1
%
\the\everylist
}%
%
% A list item, for both kinds of lists.
%
\def\li{\@getoptionalarg\@finli}%
\def\@finli{%
\ifx\@optionalarg\empty \else
\expandafter\writeitemxref\expandafter{\@optionalarg}%
\fi
\ifnum\itemnumber=1 \else \interitemskip \fi
\printitem
\advance\itemnumber by 1
\advance\itemletter by 1
\advance\itemromannumeral by 1
%
% Just in case somebody creeps in with an argument or something.
\ignorespaces
}%
%
% \writeitemxref{LABEL} writes out a definition for LABEL to be \marker
% for the aux file.
%
\def\writeitemxref#1{\definexref{#1}\marker{item}}%
%
% \printitem is used to print items by both sorts of lists. A \par gets
% produced before every item -- even the first one. We also want to
% make paragraphs after the first appear to be indented -- i.e., they
% will have double indentation. It is usually bad exposition to have
% lists with multiparagraph items, but sometimes it is unavoidable.
%
\def\printitem{%
\par
\vskip-\parskip
\noindent
\printmarker\marker
}%
%
% Output the list marker.
%
\def\printmarker#1{\llap{\marker \enspace}}%
%
% Common ending.
%
\def\endlist{\belowlistskip}%
%
%
% \numberedlist produces items which are numbered sequentially, starting
% from one. You start items with \li (`list item'). End the list with
% \endnumberedlist.
%
% A nested \numberedlist produces items labelled `(a)', `(b)', etc. A
% doubly (and deeper) nested \numberedlist labels items with `*'.
%
% These registers keep track of where we are.
%
\newcount\numberedlistdepth
\newcount\itemnumber
\newcount\itemletter
\newcount\itemromannumeral
%
\def\numberedmarker{%
\ifcase\numberedlistdepth
(impossible)%
\or \printitemnumber
\or \printitemletter
\or \printitemromannumeral
\else *%
\fi
}%
%
% These produce the text of the labels. We use \the\itemletter so that
% the value will expand.
%
\def\printitemnumber{\number\itemnumber}%
\def\printitemletter{\char\the\itemletter}%
\def\printitemromannumeral{\romannumeral\itemromannumeral}%
\def\numberedprintmarker#1{\llap{#1) \listmarkerspace}}%
%
\def\numberedlist{\environment{@numbered-list}%
% This is set back to zero by getting to the end of the group.
\advance\numberedlistdepth by 1
\itemletter = `a
\itemromannumeral = 1
\beginlist
\let\marker = \numberedmarker
\let\printmarker = \numberedprintmarker
}%
%
\def\endnumberedlist{%
\par
\endenvironment{@numbered-list}%
\endlist
}%
%
% Allow synonyms for \numberedlist.
\let\orderedlist = \numberedlist
\let\endorderedlist = \endnumberedlist
%
%
%
% \unorderedlist produces items which are labelled with bullets. You
% start an item with \li, just as with numbered lists. You end the list
% with \endunorderedlist.
%
% A nested \unorderedlist produces items labelled with em-dashes. A
% doubly (and deeper) nested \unorderedlist uses `*'.
%
\newcount\unorderedlistdepth
%
\def\unorderedmarker{%
\ifcase\unorderedlistdepth
(impossible)%
\or \blackbox
\or ---%
\else *%
\fi
}%
\def\unorderedprintmarker#1{\llap{#1\listmarkerspace}}%
%
\def\unorderedlist{\environment{@unordered-list}%
\advance\unorderedlistdepth by 1
\beginlist
\let\marker = \unorderedmarker
\let\printmarker = \unorderedprintmarker
}%
%
\def\endunorderedlist{%
\par
\endenvironment{@unordered-list}%
\endlist
}%
%
%
%
% Verbatim listing.
%
% ... well, almost verbatim. We assume the font \tt has all the
% characters that will appear. Control characters, except for tabs and
% form feeds (and returns) won't produce anything useful. Tabs produce
% a fixed amount of space, and form feeds produce a page break.
%
% This is based on Knuth's ideas in Appendix D of the TeXbook, p. 380.
% The argument should be a filename.
%
% if you need to do something more for your particular fonts and/or
% environment before the file is input, give a definition to
% \setuplistinghook. If you want line numbers on the output, you can
% say \let\setuplistinghook = \linenumberedlisting.
%
\def\listing#1{%
\par \begingroup
\@setuplisting
\setuplistinghook
\input #1
\endgroup
}%
%
\let\setuplistinghook = \relax
%
\def\linenumberedlisting{%
\ifx\lineno\undefined \innernewcount\lineno \fi
\lineno = 0
\everypar = {\advance\lineno by 1 \printlistinglineno}%
}%
\def\printlistinglineno{\llap{[\the\lineno]\quad}}%
%
%
% \uncatcodespecials must come before \obeywhitespace, lest a space
% character in the input produce character 32 from the \tt font.
%
\def\listingfont{\tt}%
\def\@setuplisting{%
\uncatcodespecials
\obeywhitespace
\makeactive\`
\makeactive\^^I
\def^^L{\vfill\eject}%
\parskip = 0pt
\listingfont
}%
%
% Give definitions to the characters we want to be special.
%
% Do ` separately, so can use ` in the \catcode commands elsewhere.
%
{%
\makeactive\`
\gdef`{\relax\lq}% Defeat ligatures.
}%
{%
\makeactive\^^I
\gdef^^I{\hskip8\fontdimen2\font \relax}%
}%
%
%
% \verbatim ... |endverbatim typesets the ... in typewriter. To produce a |
% in the ..., use ||. This macro was contributed by [email protected].
% Generalized to characters other than | by [email protected].
%
\def\verbatimescapechar#1{%
\gdef\@makeverbatimescapechar{%
\@makeverbatimdoubleescape #1%
\catcode`#1 = 0
}%
}%
\def\@makeverbatimdoubleescape#1{%
\catcode`#1 = \other
\begingroup
\lccode`\* = `#1%
\lowercase{\endgroup \ece\def*{*}}%
}%
\verbatimescapechar\| % initially escapechar is |
%
\def\verbatim{\begingroup
\uncatcodespecials
\obeywhitespace
\makeactive\` % make space character a single space, not stretchable
\@makeverbatimescapechar
\tt}
\let\endverbatim = \endgroup
%
%
%
% Table of contents, list of figures, etc.
%
% Entries for the table of contents are recorded in \jobname.toc, which
% we open for writing at the first \writetocentry or when \readtocfile
% is invoked (after we read it, in the latter case). Actually, we use
% \tocfilebasename for the root of the filename to read; \jobname is
% the default.
%
\def\definecontentsfile#1{%
\ece\innernewwrite{#1file}%
\ece\innernewif{if@#1fileopened}%
\ece\let{#1filebasename} = \jobname
\ece\def{open#1file}{\opencontentsfile{#1}}%
\ece\def{write#1entry}{\writecontentsentry{#1}}%
\ece\def{writenumbered#1entry}{\writenumberedcontentsentry{#1}}%
\ece\innernewif{ifrewrite#1file} \csname rewrite#1filetrue\endcsname
\ece\def{read#1file}{\readcontentsfile{#1}}%
}%
%
% We provide \opentocfile, \readtocfile, etc., by default.
\definecontentsfile{toc}%
%
% And `toc' is just the argument to this macro.
\def\opencontentsfile#1{%
\csname if@#1fileopened\endcsname \else
\ece{\immediate\openout}{#1file} = \csname #1filebasename\endcsname.#1
\ece\global{@#1fileopenedtrue}%
\fi
}%
%
% \writetocentry#1#2 produces a line in the .toc file that
% looks like:
% \toc#1entry{#2}{page number}
% e.g.,
% \tocchapterentry{Introduction}{2}
% would be written by
% \writetocentry{chapter}{Introduction}
% if the chapter started on page two.
%
% Thus, #1 is intended to be something like `chapter' or `section', #2
% to be the text of the title.
%
% Of course, if you want, you can \write\tocfile yourself with whatever
% you like. In that case, you must also call \opentocfile.
%
% By the way, it would be wrong to put a \percentchar at the end of the
% output line. Then, when the .toc file is read, if each line is turned
% into a \leftline, say, there would be no legal breakpoint between the
% boxes, and one extremely long line would result.
%
% `toc' is the first argument to this; \writetocentry is defined by
% \definecontentsfile.
\def\writecontentsentry#1#2#3{\writenumberedcontentsentry{#1}{#2}{#3}{}}%
%
% Sometimes you want the control sequence to take another number (e.g.,
% a chapter number) as a parameter. (Although you can pass anything you
% want as the third parameter, naturally.) The third parameter is
% expanded at the point of the \writenumberedtocentry, not when the
% \write actually happens. This makes the usual case---the third
% parameter being \the\someregister---work.
%
% For example:
% \writenumberedtocentry{chapter}{The second chapter}{2}
% would produce:
% \tocchapterentry{The second chapter}{2}{14}
%
% if the second chapter started on page 14.
%
% `toc' is the first argument, as above.
\def\writenumberedcontentsentry#1#2#3#4{%
\csname ifrewrite#1file\endcsname
\csname open#1file\endcsname
\toks0 = {\expandafter\noexpand \csname #1#2entry\endcsname}%
\def\temp{#3}%
%
% Usually #4 is just `\the\register', which we want to expand. But
% if it's not a number at all -- e.g., if it's an author's name, we
% don't want to expand control sequences for accents and the like.
% So we play some games here.
\toks2 = \expandafter{#4}%
\edef\cs{\the\toks2}%
\edef\@wr{%
\write\csname #1file\endcsname{%
\the\toks0 % the \toc...entry control sequence
{\sanitize\temp}% the text
\ifx\empty\cs\else {\sanitize\cs}\fi % A secondary number, or nothing:
{\noexpand\folio}% the page number
}%
}%
\@wr
\fi
\ignorespaces
}%
%
% The entries are read in when the user invokes \readtocfile (which
% should be before the first \writetocentry). The .toc file is also
% opened for writing (i.e., emptied) here, unless \rewritetocfilefalse.
% You might want to set that if you're reading it in twice to make a
% short contents or some such.
\def\readcontentsfile#1{%
\edef\temp{%
\noexpand\testfileexistence[\csname #1filebasename\endcsname]{toc}%
}\temp
\if@fileexists
\input \csname #1filebasename\endcsname.#1\relax
\csname ifrewrite#1file\endcsname \csname open#1file\endcsname \endif
\fi
}%
\def\endif{\fi}%
%
% Here are some sample definitions of the \toc...entry macros. Perhaps
% you or your book designer can come up with a better way of handling
% contents than leaders. These definitions are just examples, not
% something you might want to actually use to print a document.
\def\tocchapterentry#1#2{\line{\bf #1 \dotfill\ #2}}%
\def\tocsectionentry#1#2{\line{\quad\sl #1 \dotfill\ \rm #2}}%
\def\tocsubsectionentry#1#2{\line{\qquad\rm #1 \dotfill\ #2}}%
%
%
%
% Cross-references.
%
% Definitions of references are recorded in \jobname.aux, called
% \auxfile in the macros, which btxmac.tex has opened.
%
% When a label isn't defined, we only want to complain if
% \xrefwarningtrue; btxmac uses \if@citewarning for this, so we have to
% reuse that name. We can't just say \let\ifxrefwarning =
% \if@citewarning, since then changes to the latter won't be reflected
% in the former. On the other hand, we have to have a true \if...
% command, so \if's and \fi's match properly. What a mess.
%
\let\ifxrefwarning = \iftrue
\def\xrefwarningtrue{\@citewarningtrue \let\ifxrefwarning = \iftrue}%
\def\xrefwarningfalse{\@citewarningfalse \let\ifxrefwarning = \iffalse}%
%
%
% \xref{foo} produces ``p.\thinspace <page#>''. \xrefn{foo} produces
% ``<page#>''. \xrdef{foo} produces nothing, but defines the label
% `foo' to be on the current page.
%
% As usual, it takes two passes to get the cross-references right. I
% would like to check for labels being defined twice, but I don't know
% how to do that. If the cross-reference file has been read in, many
% cross-references will be defined that I don't want to complain about.
% It is only if two \xrdef commands are given to the same string that I
% want to complain. I could define a new control sequence for each
% cross-reference, and check that, but that seems like too high of a
% price to pay.
%
%
% \xrlabel{LABEL} expands to a cross-reference internal name. We append
% an _ character to NAME, to help avoid conflicts. And we append an `x'
% so that we don't redefine \_ on an empty label.
%
\begingroup
% Mike Spivak's MathTime macros for Times Roman fonts changes the
% catcode of _ to be active. (From [email protected].)
\catcode`\_ = 8
\gdef\xrlabel#1{#1_x}%
\endgroup
%
%
% \xrdef{LABEL} defines LABEL to be the current page number. But we
% don't define the label here, because the page number might be off: if
% this is not the first time through, the label would already be
% defined, and we would redefine it with the wrong information.
%
\def\xrdef#1{\definexref{#1}{\noexpand\folio}{page}}%
%
% \definexref{LABEL}{DEFINITION}{CLASS} defines a cross-reference named
% LABEL of label class CLASS to be DEFINITION. (Or LABEL can be a
% control sequence; it's expanded to get the label text.) To get a
% possible page number right, we have to write the definition out to the
% auxiliary file, instead of only defining it directly.
%
\def\definexref#1#2#3{%
% Remember what we're given; it might be `\@optionalarg', which
% \readauxfile trashes. (No loss of generality here, since \csname
% will fully expand the label anyway.)
\edef\temp{#1}%
%
% Be sure we've read the aux file before we zap it:
\readauxfile
%
% When we read in the aux file next time, define the label:
\edef\@wr{\noexpand\writeaux{\string\@definelabel{\temp}{#2}{#3}}}%
\@wr
\ignorespaces
}%
%
% \@definelabel{LABEL}{DEFINITION}{CLASS} actually defines LABEL of
% label class CLASS to be DEFINITION.
%
\def\@definelabel#1#2#3{%
% Define the control sequence.
\expandafter\gdef\csname\xrlabel{#1}\endcsname{#2}%
%
% Remember what kind of label this is, so \ref will know what to do.
\global\setproperty{\xrlabel{#1}}{class}{#3}%
}%
%
%
% Typeset a reference to the label #1.
%
\def\xrefn#1{%
\readauxfile
%
\expandafter \ifx\csname\xrlabel{#1}\endcsname\relax
\if@citewarning
\message{\linenumber Undefined label `#1'.}%
\fi
%
% Give it a dummy definition, though, to stop multiple error messages.
\expandafter\def\csname\xrlabel{#1}\endcsname{%
`{\tt
\escapechar = -1
\expandafter\string\csname#1\endcsname
}'%
}%
\fi
\csname\xrlabel{#1}\endcsname % Always produce something.
}%
%
% \refn is just a synonym.
%
\let\refn = \xrefn
%
% One common case: print `p. ' before the page number.
%
\def\xref{p.\thinspace\xrefn}%
%
% \ref{LABEL} typesets \CLASSword for LABEL's class (if it's defined)
% and then does \refn on LABEL. But amstex also has a \ref, so tell the
% user if they try to use \ref and have loaded amsppt.sty.
%
% \refs is similar, but puts the letter `s' after the \...word, thus
% producing (for example) `Figures 1.2' (presumably to be followed by
% `and~\refn{fig-1.3}').
%
\def\@maybewarnref{%
\ifundefined{amsppt.sty}%
% No amsppt.sty, so just use ours.
\else
\message{Warning: amsppt.sty and Eplain both define \string\ref. See
the Eplain manual.}%
% Remember their definition.
\let\amsref = \ref
\fi
\let\ref = \eplainref
\ref
}
\let\ref = \@maybewarnref
%
\def\eplainref{\@generalref{}}%
\def\refs{\@generalref s}%
%
% #1 is the text to follow the \...word, and is supplied by the macros
% above. #2 comes from the document, and is the LABEL.
%
\def\@generalref#1#2{%
\readauxfile
%
\edef\temp{\getproperty{\xrlabel{#2}}{class}}%
%
% If the word for this class is not defined, don't complain.
\expandafter\ifx\csname \temp word\endcsname\relax \else
% Produce the word.
\csname \temp word\endcsname
% Add the suffix and then put in a tie before the \refn. Do not
% rely on `~' being defined as a tie.
#1\penalty\@M \
\fi
%
\refn{#2}%
}%
%
%
% References to equations are similar.
%
% \eqref{foo} produces ``(<text for equation label foo>)''.
% \eqdefn{foo} advances \eqnumber, resets \eqsubnumber, and defines
% `foo' to be the new number.
% \eqsubdefn{foo} advances \eqsubnumber and defines `foo'. \eqref works
% for both equations and subequations,
% \eqdef{foo} does \eqdefn, then inserts an \eqno and \eqref.
% \eqsubdef{foo} does \eqsubdefn, then what \eqdef does.
%
% The non-``sub'' macros also take an optional argument; if it's
% present, we use it as the text for the equation label, instead of the
% various counters.
%
% Because there are no page break issues with equations, we can
% immediately define the control sequence. But we also need to write
% the definition out, in case the user wants to forward reference an
% equation (bad style as that may be).
%
% The current equation number is in \eqnumber; we just advance it by one
% for each \eqdef. You can handle fancier equation numbers (e.g., ones
% that include a chapter number) by redefining \eqprint, below, and
% using your own counters. We do provide for one level of substructure,
% since that's more painful to implement than superstructures.
%
\newcount\eqnumber
\newcount\subeqnumber
%
%
% \eqdefn[TEXT]{LABEL} defines LABEL to be TEXT (if it's present),
% otherwise it advances \eqnumber and defines LABEL to be that. It
% doesn't produce anything.
%
\def\eqdefn{\@getoptionalarg\@fineqdefn}%
\def\@fineqdefn#1{%
\ifx\@optionalarg\empty
\global\advance\eqnumber by 1
% We call \eqconstruct here instead of in \@eqdefn because we don't
% want to expand it for \eqsubdefn -- \eqsubdefn already includes an
% \eqrefn which includes the text of the label which was \eqconstructed.
\def\temp{\eqconstruct{\number\eqnumber}}%
\else
\def\temp{\noexpand\@optionalarg}%
\fi
%
% Always reset the current subequation number:
\global\subeqnumber = 0
%
% Remember this label, so that we can define subequations:
\gdef\@currenteqlabel{#1}%
\toks0 = \expandafter{\@currenteqlabel}%
%
% Actually do the definition, taking precautions not to expand \eqrefn
% in what we output to the aux file. \eqrefn expands to many things,
% including \count@'s and \edef's and the expansion of \xrlabel, and
% it's just a real mess.
\begingroup
\def\eqrefn{\noexpand\eqrefn}%
\edef\temp{\noexpand\@eqdefn{\the\toks0}{\temp}}%
\temp
\endgroup
}%
%
%
% \eqsubdefn defines its argument as a ``subequation'' of the last \eqdef.
%
\def\eqsubdefn#1{%
\global\advance\subeqnumber by 1
\toks0 = {#1}%
%
% Get the text of the label;
\toks2 = \expandafter{\@currenteqlabel}%
%
% We must expand \@currenteqlabel. We have to not expand
% \eqsubreftext here, as well \eqrefn, since the first arg to
% \eqsubreftext could also include lots of complicated things.
\begingroup
\def\eqrefn{\noexpand\eqrefn}%
\def\eqsubreftext{\noexpand\eqsubreftext}%
\edef\temp{%
\noexpand\@eqdefn
{\the\toks0}%
{\eqsubreftext{\eqrefn{\the\toks2}}{\the\subeqnumber}}%
}%
\temp
\endgroup
}%
%
% \@eqdefn{LABEL}{REF-TEXT} actually handles the equation number
% definitions and writing to the aux file.
%
% In contrast to \xrdef, we define LABEL right away (as REF-TEXT). We
% can do this since we know right now what the right equation number is.
% This eliminates some unnecessary warning. It also lets the user put
% \eqdef{} on all equations and have it work, since then \eqref
% refers to the just-defined new value.
%
\def\@eqdefn#1#2{%
\definexref{#1}{#2}{eq}%
\@definelabel{#1}{#2}{eq}%
}%
%
% \eqdef{LABEL} defines LABEL, with \eqdefn, then prints it. We allow
% an optional argument to explicitly specify the text which we define
% the label as.
%
\def\eqdef{\@getoptionalarg\@fineqdef}%
\def\@fineqdef{%
\toks0 = \expandafter{\@optionalarg}%
\edef\temp{\noexpand\@eqdef{\noexpand\eqdefn[\the\toks0]}}%
\temp
}%
%
% \eqsubdef is to \eqdef as \eqsubdefn is to \eqdefn. No optional
% argument allowed here.
%
\def\eqsubdef{\@eqdef\eqsubdefn}%
%
% \@eqdef{DEFN-CMD}{LABEL} defines LABEL, using DEFN-CMD. Then it
% inserts an \eqno (unless it's called when an \eqno would be invalid).
% Then it prints the newly-defined value using \eqprint.
%
\def\@eqdef#1#2{%
#1{#2}% Define the label.
%
\@maybedisableeqno
\eqno \eqref{#2}% Print the text.
\@mayberestoreeqno
\ignorespaces
}%
%
%
% If we are in an alignment or some other inner place, \eqno won't work.
%
\let\@mayberestoreeqno = \relax
%
\def\@maybedisableeqno{%
\ifinner
\global\let\eqno = \relax
\global\let\@mayberestoreeqno = \@restoreeqno
\fi
}%
%
% This makes `\eqno' mean \eqno again.
%
\let\@primitiveeqno = \eqno
\def\@restoreeqno{%
\global\let\eqno = \@primitiveeqno
\global\let\@mayberestoreeqno = \empty
}%
%
%
% \eqrefn{LABEL} produces the text for the equation label LABEL, or
% something suitable if LABEL is undefined. (It possibly issues a
% warning in the latter case as well.)
%
\let\eqrefn = \xrefn
%
% \eqref{LABEL} is the usual way to refer to equation labels; it calls
% \eqprint on the text of LABEL.
%
\def\eqref#1{\eqprint{\eqrefn{#1}}}%
%
%
% \eqconstruct{EQ-TEXT} constructs an equation number, i.e., the text to
% be defined as the value of a label.
%
\let\eqconstruct = \identity
%
% \eqprint{EQ-TEXT} produces the typeset equation number EQ-TEXT.
%
\def\eqprint#1{(#1)}%
%
% \eqsubreftext{EQ-TEXT}{SUBEQ-TEXT} produces the text of a subequation
% reference. (\eqprint is later called on the result of this to produce
% output for subequations; I didn't define any \subeqprint.)
%
\def\eqsubreftext#1#2{#1.#2}%
%
%
%
% Indexing.
%
% \defineindex{PREFIX} defines an index with ``prefix'' PREFIX. The
% prefix is used to construct the output filename and the various
% commands. We just define all the index commands for this index to
% call the general commands with PREFIX.
%
\let\extraidxcmdsuffixes = \empty
%
\outer\def\defineindex#1{%
\def\@idxprefix{#1}%
%
% Define the indexing commands for this prefix.
\for\@idxcmd:=,marked,submarked,name%
\extraidxcmdsuffixes\do
{%
\@defineindexcmd\@idxcmd
}%
%
% Allocate a stream for the output.
\ece\innernewwrite{@#1indexfile}%
%
% And a conditional to test whether we've opened the file.
\ece\innernewif{if@#1indexfileopened}%
}%
%
%
% \@defineindexcmd{SUFFIX} defines both silent and non-silent index
% command for prefix \@idxprefix with suffix SUFFIX. That is, we define
% both `\@idxprefix dxSUFFIX' and `\s\@idxprefix dxSUFFIX' to call the
% corresponding generic command with \@idxprefix. \silentindexentry is
% used to decide whether we should ignore following spaces.
%
\newif\ifsilentindexentry
%
\def\@defineindexcmd#1{%
\@defineoneindexcmd{s}{#1}\silentindexentrytrue
\@defineoneindexcmd{}{#1}\silentindexentryfalse
}%
%
%
% \@defineoneindexcmd{PREFIX}{SUFFIX}{PRECALL} does just one silent or
% non-silent commands. We define the command `\@@PREFIXidxSUFFIX' to do
% PRECALL, then define \@idxprefix, then call \@idxgetrange with an
% argument of `\@@{,s}idxSUFFIX'. (So far every indexing command
% should allow a range. If not, you could redefine `\@@{,s}idxSUFFIX'
% after this macro is called.)
%
\def\@defineoneindexcmd#1#2#3{%
\toks@ = {#3}%
\edef\temp{%
\def
% We have to restrict expansion because the generic (\@@...)
% commands will be defined after the first call to \defineindex.
% Not expanding the user (\idx...) commands is unnecessary unless
% the user has defined some new commands, but may as well be cautious.
\expandonce\csname#1\@idxprefix dx#2\endcsname % e.g., \idx or \sidxname.
{\def\noexpand\@idxprefix{\@idxprefix}% define \@idxprefix
% call, e.g., \@@idx or \@@sidxname:
\expandonce\csname @@#1idx#2\endcsname
}%
\def
\expandonce\csname @@#1idx#2\endcsname{% e.g., \@@idx
% First do PRECALL.
\the\toks@
% Then call \@idxgetrange with, e.g., \@idx or \@sidxname as its arg.
\noexpand\@idxgetrange\expandonce\csname @#1idx#2\endcsname
}%
}%
\temp
}%
%
%
% \@idxwrite{TERM}{PAGENO} writes a general index entry for TERM on page
% PAGENO to the index file `\@idxprefix indexfile'. We open the stream
% as `\indexfilebasename.\@idxprefix dx' if it isn't already open.
%
\let\indexfilebasename = \jobname
%
\def\@idxwrite#1#2{%
% Be sure the file is opened.
\csname if@\@idxprefix indexfileopened\endcsname \else
\expandafter\immediate\openout\csname @\@idxprefix indexfile\endcsname =
\indexfilebasename.\@idxprefix dx
\expandafter\global\csname @\@idxprefix indexfileopenedtrue\endcsname
\fi
%
% Save the index term.
\def\temp{#1}%
%
% Write the index term and page number.
\edef\@wr{%
\expandafter\write\csname @\@idxprefix indexfile\endcsname{%
\string\indexentry
{\sanitize\temp}%
{\noexpand#2}%
}%
}%
\@wr
%
% Marginalize the index term, if desired.
\ifindexproofing \insert\@indexproof{\indexproofterm{#1}}\fi
%
% We just appended at least one non-discardable item (namely, the
% whatsit from the \write) to the current list. So in case glue comes
% next (not unlikely), be sure we don't inadvertently make that glue a
% valid breakpoint, if it wouldn't have been without us.
\hookrun{afterindexterm}%
%
% This is the end of the index entry processing. If this was a silent
% entry, ignore following spaces.
\ifsilentindexentry \expandafter\ignorespaces\fi
}%
%
%
% If this conditional is true, we output the index terms on the page
% where they occur.
\newif\ifindexproofing
%
% We need a new insertion class to collect the proofed terms.
\newinsert\@indexproof
\dimen\@indexproof = \maxdimen % No limit on number of terms.
\count\@indexproof = 0 \skip\@indexproof = 0pt % They take up no space.
%
% This actually typesets the proofed term. We don't go to any lengths
% to provide nice-looking output; since the term might have all kinds of
% weird characters in it, we just dump it in the smallest standard
% Computer Modern typewriter font.
%
% We put the term in an \hbox, even though that might make the output
% run off the page, since we don't really need to see all of it, and
% I think it's better to opt for simplicity -- one term per line.
\font\indexprooffont = cmtt8
\def\indexproofterm#1{\hbox{\strut \indexprooffont #1}}%
%
%
% If \output doesn't use \makeheadline, or redefines it, it's up to the
% new \output to call \indexproofunbox.
\let\@plainmakeheadline = \makeheadline
\def\makeheadline{%
\indexproofunbox
\@plainmakeheadline
}%
%
% We want to put the proof index terms in the margin, outside the
% printed area. So if \outsidemargin (for odd pages) and \insidemargin
% (for even pages) are undefined, we define them (both) to be the default
% TeX margin -- one inch + \hoffset.
\def\indexsetmargins{%
\ifx\undefined\outsidemargin
\dimen@ = 1in
\advance\dimen@ by \hoffset
\edef\outsidemargin{\the\dimen@}%
\let\insidemargin = \outsidemargin
\fi
}%
%
% We always put the terms in the right-hand margin, so long terms run
% off the page, instead of into the text.
\def\indexproofunbox{%
\ifvoid\@indexproof\else
\indexsetmargins
\rlap{%
\kern\hsize
\ifodd\pageno \kern\outsidemargin \else \kern\insidemargin \fi
\vbox to 0pt{\unvbox\@indexproof\vss}%
}%
\fi
}%
%
%
% \@idxgetrange\CS parses an optional argument which, if present, should
% be either `begin' or `end', marking the beginning or ending of a range
% for the index entry. If we find this, we set the appropriate one of
% \@idxrangestr. Then we call \CS.
%
% If the optional argument is `see' or `seealso' we read another
% argument, namely, the entry to see.
%
\def\idxrangebeginword{begin}%
\def\idxbeginrangemark{(}% the corresponding magic char to go in the idx file
%
\def\idxrangeendword{end}%
\def\idxendrangemark{)}%
%
\def\idxseecmdword{see}%
\def\idxseealsocmdword{seealso}%
\newif\if@idxsee
\let\@idxseenterm = \relax
%
\def\idxpagemarkupcmdword{pagemarkup}%
\let\@idxpagemarkup = \relax
%
\def\@idxgetrange#1{%
\let\@idxrangestr = \empty
\let\@afteridxgetrange = #1%
\@getoptionalarg\@finidxgetopt
}%
\def\@finidxgetopt{%
\for\@idxarg:=\@optionalarg\do{%
% These are ordered by my guess at frequency of use.
\expandafter\@idxcheckpagemarkup\@idxarg=,%
%
\ifx\@idxarg\idxrangebeginword
\def\@idxrangestr{\idxencapoperator\idxbeginrangemark}%
\else
\ifx\@idxarg\idxrangeendword
\def\@idxrangestr{\idxencapoperator\idxendrangemark}%
\else
\ifx\@idxarg\idxseecmdword
\def\@idxpagemarkup{indexsee}%
\@idxseetrue
\else
\ifx\@idxarg\idxseealsocmdword
\def\@idxpagemarkup{indexseealso}%
\@idxseetrue
\else
\ifx\@idxpagemarkup\relax
\errmessage{Unrecognized index option `\@idxarg'}%
\fi
\fi
\fi
\fi
\fi
}%
\@afteridxgetrange
}%
%
%
% Check for a command of the form `pagemarkup=\cmd', and if found, set
% \@idxpagemarkup to `cmd'.
%
\def\@idxcheckpagemarkup#1=#2,{%
\def\temp{#1}%
\ifx\temp\idxpagemarkupcmdword
\if ,#2, % If #2 is empty, complain.
\errmessage{Missing markup command to `pagemarkup'}%
\else
% Remove a trailing =.
\def\temp##1={##1}%
\edef\@idxpagemarkup{\temp\string#2}%
\fi
\fi
}%
%
%
% \@idxtokscollect uses \@idxmaintoks as the token list for the main
% part of an index entry and \@idxsubtoks for the subpart. Then it
% calls \@idxwrite.
%
\def\idxsubentryseparator{!}%
\def\idxencapoperator{|}%
\def\idxmaxpagenum{99999}%
%
\newtoks\@idxmaintoks
\newtoks\@idxsubtoks
%
\def\@idxtokscollect{%
% Remember the subentry.
\edef\temp{\the\@idxsubtoks}%
%
% We want to expand the conditions, but not the terms. The index
% entry starts simply with \@idxmaintoks and \@idxsubtoks.
\edef\@indexentry{%
\the\@idxmaintoks
\ifx\temp\empty\else \idxsubentryseparator\the\@idxsubtoks \fi
\@idxrangestr
}%
%
% If this is a `see' or `see also' entry, we need to read one more
% arg. We use a giant page number so the entry will be last (for the
% benefit of `see also's). MakeIndex rejects page numbers >=1000.
%
\if@idxsee
\@idxseefalse % Reset so the next term won't be a `see'.
\edef\temp{\noexpand\@finidxtokscollect{\idxmaxpagenum}}%
\else
\def\temp{\@finfinidxtokscollect\folio}%
\fi
\temp
}%
%
%
% \@finidxtokscollect{PAGENO}{REAL-TERM} reads the final term for
% see/see also entries. We do not check if the person has put both a
% range and a see in the same index term (which will confuse makeindex).
%
\def\@finidxtokscollect#1#2{%
\def\@idxseenterm{#2}%
\@finfinidxtokscollect{#1}%
}%
%
% \@finfinidxtokscollect{PAGENO} writes \@indexentry for page PAGENO.
% Besides \@indexentry, if \@idxpagemarkup is not \relax we output an
% index entry \@indexentry|\@idxpagemarkup{PAGENO}. And if
% \@idxseenterm is not \relax we output {\@idxseenterm} after the
% \@idxpagemarkup. (This will become an argument to the ``markup''
% command, which will be \indexsee or \indexseealso.)
%
\def\@finfinidxtokscollect#1{%
% If we've got a page markup command, append it.
\ifx\@idxpagemarkup\relax \else
\toks@ = \expandafter{\@indexentry}%
\edef\@indexentry{\the\toks@ \idxencapoperator \@idxpagemarkup}%
\let\@idxpagemarkup = \relax
\fi
%
% If we've got an argument to the ``page markup'' command, append it.
\ifx\@idxseenterm\relax \else
\toks@ = \expandafter{\@indexentry}%
\edef\@indexentry{\the\toks@{\sanitize\@idxseenterm}}%
\let\@idxseenterm = \relax
\fi
%
% Finally, write what we've constructed.
\expandafter\@idxwrite\expandafter{\@indexentry}{#1}%
}%
%
%
% \@idxcollect{MAIN}{SUB} sets up the token registers
% \@idx{main,sub}toks, then calls \@idxtokscollect. This is convenient
% for some of the macros below.
%
\def\@idxcollect#1#2{%
\@idxmaintoks = {#1}%
\@idxsubtoks = {#2}%
\@idxtokscollect
}%
%
%
% Following are the TeX macros that correspond to the commands
% that actually appear in the document.
%
% \@idx{TERM} produces TERM in the output and then makes the index entry
% for TERM as usual. We don't allow a [SUBTERM] here since then we
% would lose spaces after the command, which would be very inconvenient.
%
% As with all our index commands, we've already defined \@idxprefix (in
% \idx or whatever), to save passing it around, and we've looked for a
% range argument before TERM.
%
\def\@idx#1{%
#1% Produce TERM as output.
\@idxcollect{#1}{}%
}%
%
% \@sidx{TERM}[SUBTERM] produces an index entry TERM and no output. If
% SUBTERM is present, this is a subentry. (At the moment, I don't
% provide for subsubentries, since I've never needed that.)
%
\def\@sidx#1{\@idxmaintoks = {#1}\@getoptionalarg\@finsidx}%
\def\@finsidx{%
\@idxsubtoks = \expandafter{\@optionalarg}%
\@idxtokscollect
}%
%
%
% \@idxconstructmarked{TOKS-REG}\CS{TERM}
%
\def\idxsortkeysep{@}% This `@' is catcode 11, but it doesn't matter.
%
\def\@idxconstructmarked#1#2#3{%
\toks@ = {#2}% The control sequence.
\toks2 = {#3}% The term.
%
% Construct TERM@\CS{TERM} as the string to write.
\edef\temp{\the\toks2 \idxsortkeysep \the\toks@{\the\toks2}}%
%
% Save it in TOKS-REG.
#1 = \expandafter{\temp}%
}%
%
%
% \@idxmarked\CS{TERM} outputs \CS{TERM} and then calls the main part of
% \@sidxmarked.
%
\def\@idxmarked#1#2{%
#1{#2}% Produce \CS{TERM} as output.
\@idxconstructmarked\@idxmaintoks{#1}{#2}%
\@idxsubtoks = {}%
\@idxtokscollect
}%
%
% \@sidxmarked\CS{TERM}[SUBTERM] outputs an index entry sorted by TERM
% but producing \CS{TERM}.
%
\def\@sidxmarked#1#2{%
\@idxconstructmarked\toks@{#1}{#2}%
\edef\temp{{\the\toks@}}%
\expandafter\@sidx\temp
}%
%
%
% \@idxsubmarked{TERM}\CS{SUBTERM} is like \@idxmarked, except that it's
% SUBTERM that's marked instead of TERM.
%
\def\@idxsubmarked#1#2#3{%
#1 #2{#3}% produce `TERM \CS{SUBTERM} as output.
\@sidxsubmarked{#1}{#2}{#3}%
}%
%
% \@sidxsubmarked{TERM}\CS{SUBTERM} is to \@sidxmarked as \@idxsubmarked
% is to \@idxmarked.
%
\def\@sidxsubmarked#1#2#3{%
\@idxmaintoks = {#1}%
\@idxconstructmarked\@idxsubtoks{#2}{#3}%
\@idxtokscollect
}%
%
%
% \@idxcollectname{FIRST}{LAST} puts `LAST, FIRST' into \temp. (Well,
% we use \idxnameseparator instead of hardwiring `, '.) If FIRST is
% empty, don't include the separator.
%
\def\idxnameseparator{, }% as in `Tachikawa, Elizabeth'
%
\def\@idxcollectname#1#2{%
\def\temp{#1}%
\ifx\temp\empty
\toks@ = {}%
\else
\toks@ = {\idxnameseparator #1}%
\fi
\toks2 = {#2}%
%
\edef\temp{\the\toks2 \the\toks@}%
}%
%
%
% \@idxname{FIRST}{LAST} also produces `FIRST LAST' in the output and an
% index entry for `LAST, FIRST'.
%
\def\@idxname#1#2{%
#1 #2% Separate the names by a space in the output.
\@idxcollectname{#1}{#2}%
\expandafter\@idxcollect\expandafter{\temp}{}%
}%
%
% \@sidxname{FIRST}{LAST}[SUBTERM] is to \@sidx as \@idxname is to
% \@idx.
%
\def\@sidxname#1#2{%
\@idxcollectname{#1}{#2}%
\expandafter\@sidx\expandafter{\temp}%
}%
%
%
% Now we come to actually producing the index, i.e., implementing the
% formatting commands that MakeIndex outputs.
%
% \readindexfile is responsible for formatting and printing the index.
% It reads \indexfilebasename.ind. We implement the same commands that
% LaTeX does. I suppose we could allow for different indices having
% different basenames, but I can't imagine when that would be useful.
%
\let\indexfonts = \relax
%
\def\readindexfile#1{%
\edef\@idxprefix{#1}%
%
% Does the output file exist?
\testfileexistence[\indexfilebasename]{\@idxprefix nd}%
\iffileexists \begingroup
% If no \begin or \end, define them. The argument will be `{theindex}'.
\ifx\begin\undefined
\def\begin##1{\@beginindex}%
\let\end = \@gobble
\fi
%
% Read the file:
\input \indexfilebasename.\@idxprefix nd
%
% \doublecolumns isn't affected by groups.
\singlecolumn
\endgroup
\else
\message{No index file \indexfilebasename.\@idxprefix nd.}%
\fi
}%
%
% Here's the default for `\begin{theindex}', if \begin isn't defined.
\def\@beginindex{%
% Define the commands MakeIndex outputs.
\let\item = \@indexitem
\let\subitem = \@indexsubitem
\let\subsubitem = \@indexsubsubitem
%
% Set up the default formatting:
\indexfonts
\doublecolumns
\parindent = 0pt
%
% Let the user override the defaults.
\hookrun{beginindex}%
}%
%
% MakeIndex puts \indexspace between groups in the ind file.
\let\indexspace = \bigbreak
%
% You can make \afterindexterm appear after the term and before the
% first page with the following in the ist file:
% delim_0 "\\afterindexterm "
% delim_1 "\\afterindexterm "
% delim_2 "\\afterindexterm "
\let\afterindexterm = \quad
%
%
% Top-level index entries start with \item.
\newskip\aboveindexitemskipamount \aboveindexitemskipamount = 0pt plus2pt
\def\aboveindexitemskip{\vskip\aboveindexitemskipamount}%
%
\def\@indexitem{\begingroup
\@indexitemsetup
\leftskip = 0pt
\aboveindexitemskip
\penalty-100 % Encourage page breaks before items.
%
% But forbid page breaks after items, in case a subitem follows.
\def\par{\endgraf\endgroup\nobreak}%
}%
%
% Secondary index entries.
\def\@indexsubitem{%
\@indexitemsetup
\leftskip = 1em
}%
%
% And tertiary entries.
\def\@indexsubsubitem{%
\@indexitemsetup
\leftskip = 2em
}%
%
% Common setup for the formatting.
\def\@indexitemsetup{%
\par
\hangindent = 1em
\raggedright
\hyphenpenalty = 10000
\hookrun{indexitem}%
}%
%
%
% \indexsee{TERM}{PAGENO} ignores PAGENO, and says `See TERM'.
\def\seevariant{\it}%
\def\indexseeword{See}%
\def\indexsee#1#2{{\seevariant \indexseeword\ }#1}%
%
% \indexseealso{TERM}{PAGENO} is similar.
\def\indexseealsowords{see also}%
\def\indexseealso#1#2{{\seevariant \indexseealsowords\ }#1}%
%
%
% We provide one index by default; commands are \idx, \sidx, etc.
\defineindex{i}%
%
%
%
% Justification of multiple input lines.
%
% You use these by saying
% {\flushright
% <flush right text>
% }
%
% and similarly for \flushleft and \center. The command must be
% embedded in a group. The lines are set in paragraphs as usual, i.e.,
% blank lines start a new paragraph (by virtue of the
% \blanklineskipamount vertical glue being inserted).
%
% \environment ... \endenvironment isn't appropriate in this case, since
% these ``environments'' can't be nested.
%
\begingroup
\catcode `\^^M = \active %
\gdef\flushleft{%
\def\@endjustifycmd{\@endflushleft}%
\def\@eoljustifyaction{\null\hfil\break}%
\let\@firstlinejustifyaction = \relax
\@startjustify %
}%
\gdef\flushright{%
\def\@endjustifycmd{\@endflushright}%
\def\@eoljustifyaction{\break\null\hfil}%
\def\@firstlinejustifyaction{\hfil\null}%
\@startjustify %
}%
\gdef\center{%
\def\@endjustifycmd{\@endcenter}%
\def\@eoljustifyaction{\hfil\break\null\hfil}%
\def\@firstlinejustifyaction{\hfil\null}%
\@startjustify %
}%
%
% We do this before starting any of the justification commands.
\gdef\@startjustify{%
\parskip = 0pt
\catcode`\^^M = \active %
\def^^M{\futurelet\next\@finjustifyreturn}%
%
% \@eateol is called at the beginning of each justified paragraph.
\def\@eateol##1^^M{%
\def\temp{##1}%
\@firstlinejustifyaction %
\ifx\temp\empty\else \temp^^M\fi %
}%
\expandafter\aftergroup\@endjustifycmd %
\checkenv \environmenttrue %
\par\noindent %
\@eateol %
}%
%
% If the next thing is a ^^M, insert \blanklineskipamount glue. Then
% do \@eoljustifyaction (which each justification command defines).
\gdef\@finjustifyreturn{%
\@eoljustifyaction %
\ifx\next^^M%
% Insert extra glue when the \@end... command does the \par.
\def\par{\endgraf\vskip\blanklineskipamount \global\let\par = \endgraf}%
\@endjustifycmd %
% Get back into horizontal mode for the next line.
\noindent %
\@firstlinejustifyaction %
\fi %
}%
\endgroup
%
\def\@endflushleft{\unpenalty{\parfillskip = 0pt plus1fil\par}\ignorespaces}%
\def\@endflushright{% Remove the \hfil\null\break we just put on.
\unskip \setbox0=\lastbox \unpenalty
% We have fil glue at the left of the line; \parfillskip shouldn't
% affect that.
{\parfillskip = 0pt \par}\ignorespaces
}%
\def\@endcenter{% Remove the \hfil\null\break we just put on.
\unskip \setbox0=\lastbox \unpenalty
% We have fil glue at the left of the line; \parfillskip must balance it.
{\parfillskip = 0pt plus1fil \par}\ignorespaces
}%
%
%
%
% Automatically-columnated tables.
%
% \makecolumns N/K: organizes the entries on the following N lines into
% K columns. If N is too small, some text beyond the end of the table
% will be incorporated into the table, probably producing an error
% message. If N is too large, some of the entries will appear after the
% table, probably looking very out of place.
%
% You can adjust the position of the table on the page by changing
% \parindent (space to the left of the block) and \hsize (distance from
% the left margin to the right of the block). (No doubt inside a
% group.) And you can allow a page break above the valign by changing
% \abovecolumnspenalty.
%
\newcount\abovecolumnspenalty \abovecolumnspenalty = 10000
\newcount\@linestogo % Lines remaining to process.
\newcount\@linestogoincolumn % Lines remaining in column.
\newcount\@columndepth % Number of lines in a column.
\newdimen\@columnwidth % Width of each column.
\newtoks\crtok \crtok = {\cr}%
\newcount\currentcolumn
%
% The space matches an end-of-line that will probably be there.
%
\def\makecolumns#1/#2: {\par \begingroup
% Set \@columndepth to the number of items we will put in a column:
% (N - 1) / K.
\@columndepth = #1
\advance\@columndepth by #2
\advance\@columndepth by -1
\divide \@columndepth by #2
\@linestogoincolumn = \@columndepth
\@linestogo = #1
%
% We start in the first column.
\currentcolumn = 1
%
\def\@endcolumnactions{%
\ifnum \@linestogo<2
\the\crtok \egroup \endgroup \par % End \valign and \makecolumns.
\else
% We've done one more line out of the total.
\global\advance\@linestogo by -1
%
% How many left in the column?
%
\ifnum\@linestogoincolumn<2
% End this column, that was the last line.
\global\advance\currentcolumn by 1
\global\@linestogoincolumn = \@columndepth
\the\crtok
\else
% Still got more lines to go.
&\global\advance\@linestogoincolumn by -1
\fi
\fi
}%
%
% Set up to read the table.
%
\makeactive\^^M
\letreturn \@endcolumnactions
%
% Figure out how wide our columns are going to be; each column has
% exactly the same template, so we can use the feature described on
% p.241 of the TeXbook for repeating preambles.
%
\@columnwidth = \hsize
\advance\@columnwidth by -\parindent
\divide\@columnwidth by #2
\penalty\abovecolumnspenalty
\noindent % It's not a paragraph (usually).
\valign\bgroup
&\hbox to \@columnwidth{\strut \hsize = \@columnwidth ##\hfil}\cr
%
% The next end-of-line starts everything going.
}%
%
%
%
% \numberedfootnote is like plain TeX's \footnote, but automatically
% numbered. When you want to reset the footnote number, say
% \footnotenumber = 0.
%
% We also provide for more general formatting than \footnote:
% \footnotemarkseparation is the space between the reference mark and
% the footnote text;
% \interfootnoteskip is the space between footnotes;
% \everyfootnote is expanded just before we typeset the footnote.
%
% The dimensions of the footnote rule are controlled by
% \footnoterulewidth and \footnoteruleheight (the depth is always zero);
% the space after the rule is \belowfootnoterulespace.
%
\newcount\footnotenumber
\newdimen\footnotemarkseparation \footnotemarkseparation = .5em
\newskip\interfootnoteskip \interfootnoteskip = 0pt
\newtoks\everyfootnote
\newdimen\footnoterulewidth \footnoterulewidth = 2in
\newdimen\footnoteruleheight \footnoteruleheight = 0.4pt
\newdimen\belowfootnoterulespace \belowfootnoterulespace = 2.6pt
%
\let\@plainfootnote = \footnote
\let\@plainvfootnote = \vfootnote
%
\def\vfootnote#1{\insert\footins\bgroup
\interlinepenalty\interfootnotelinepenalty
\splittopskip\ht\strutbox % top baseline for broken footnotes
\advance\splittopskip by \interfootnoteskip
\splitmaxdepth\dp\strutbox
\floatingpenalty\@MM
\leftskip\z@skip \rightskip\z@skip \spaceskip\z@skip \xspaceskip\z@skip
\everypar = {}%
\parskip = 0pt % because of the vskip
% Even if typesetting in multicolumns, do footnotes in normal page width.
% (We don't have any provision in the output routine for having
% footnotes per column, anyway.)
\ifnum\@numcolumns > 1 \hsize = \@normalhsize \fi
\the\everyfootnote
\vskip\interfootnoteskip
\indent\llap{#1\kern\footnotemarkseparation}\footstrut\futurelet\next\fo@t
}%
%
\def\footnoterule{\dimen@ = \footnoteruleheight
\advance\dimen@ by \belowfootnoterulespace
\kern-\dimen@
\hrule width\footnoterulewidth height\footnoteruleheight depth0pt
\kern\belowfootnoterulespace
\vskip-\interfootnoteskip
}%
%
\def\numberedfootnote{%
\global\advance\footnotenumber by 1
\@plainfootnote{$^{\number\footnotenumber}$}%
}%
%
%
%
% Margins.
%
% TeX's primitives determine the type area. But some users prefer to
% think in terms of margins. These definitions allow one to say, for
% example, `\topmargin = 2in', instead of `\voffset=1in\advance\vsize by
% -1in'. Constructions like `\advance\topmargin by 1in' give an error
% message, though, since \topmargin is not a parameter. Instead, the
% macro \advancetopmargin has to be used.
%
%
\newdimen\paperheight \paperheight = 11in
%
\def\topmargin{\afterassignment\@finishtopmargin \dimen@}%
\def\@finishtopmargin{%
\dimen2 = \voffset % Remember the old \voffset.
\voffset = \dimen@ \advance\voffset by -1in
\advance\dimen2 by -\voffset % Compute the change in \voffset.
\advance\vsize by \dimen2 % Change type area accordingly.
}%
\def\advancetopmargin{%
\dimen@ = 0pt \afterassignment\@finishadvancetopmargin \advance\dimen@
}%
\def\@finishadvancetopmargin{%
\advance\voffset by \dimen@
\advance\vsize by -\dimen@
}%
%
%
\def\bottommargin{\afterassignment\@finishbottommargin \dimen@}%
\def\@finishbottommargin{%
\@computebottommargin % Result in \dimen2.
\advance\dimen2 by -\dimen@ % Compute the change in the bottom margin.
\advance\vsize by \dimen2 % Change the type area.
}%
\def\advancebottommargin{%
\dimen@ = 0pt \afterassignment\@finishadvancebottommargin \advance\dimen@
}%
\def\@finishadvancebottommargin{%
\advance\vsize by -\dimen@
}%
%
% Find the current bottom margin, putting the result in \dimen2.
%
\def\@computebottommargin{%
\dimen2 = \paperheight % The total paper size.
\advance\dimen2 by -\vsize % Less the text size.
\advance\dimen2 by -\voffset % Less the offset at the top.
\advance\dimen2 by -1in % Less the default offset.
}%
%
%
\newdimen\paperwidth \paperwidth = 8.5in
%
\def\leftmargin{\afterassignment\@finishleftmargin \dimen@}%
\def\@finishleftmargin{%
\dimen2 = \hoffset % Remember the old \hoffset.
\hoffset = \dimen@ \advance\hoffset by -1in
\advance\dimen2 by -\hoffset % Compute the change in \hoffset.
\advance\hsize by \dimen2 % Change type area accordingly.
}%
\def\advanceleftmargin{%
\dimen@ = 0pt \afterassignment\@finishadvanceleftmargin \advance\dimen@
}%
\def\@finishadvanceleftmargin{%
\advance\hoffset by \dimen@
\advance\hsize by -\dimen@
}%
%
%
\def\rightmargin{\afterassignment\@finishrightmargin \dimen@}%
\def\@finishrightmargin{%
\@computerightmargin % Result in \dimen2.
\advance\dimen2 by -\dimen@ % Compute the change in the right margin.
\advance\hsize by \dimen2 % Change the type area.
}%
\def\advancerightmargin{%
\dimen@ = 0pt \afterassignment\@finishadvancerightmargin \advance\dimen@
}%
\def\@finishadvancerightmargin{%
\advance\hsize by -\dimen@
}%
%
% Find the current right margin, putting the result in \dimen2.
%
\def\@computerightmargin{%
\dimen2 = \paperwidth % The total paper size.
\advance\dimen2 by -\hsize % Less the text size.
\advance\dimen2 by -\hoffset % Less the offset at the left.
\advance\dimen2 by -1in % Less the default offset.
}%
%
%
%
% Double column output.
%
% \doublecolumns begins double column output. It can be called
% in the midst of a page. \singlecolumn restores single column
% output. (It would be wrong to require \enddoublecolumns, because
% often one wants double column mode to continue to the end of
% the document.)
%
% The basic approach is that of Appendix E of the TeXbook, p.417.
% David Guichard made significant improvements to my original implementation.
%
% The glue here (the default is intended to be one linespace) is inserted
% before double columns start, and after they end.
%
\newskip\abovecolumnskip \abovecolumnskip = \bigskipamount
\newskip\belowcolumnskip \belowcolumnskip = \bigskipamount
%
% Space between the columns. It can be changed as desired.
\newdimen\gutter \gutter = 2pc
%
% These registers are needed for dealing with switching back and forth.
\newbox\@partialpage
\newdimen\@columnhsize
\newdimen\@normalhsize
\newdimen\@normalvsize
\newtoks\previousoutput
%
% Some synonymous ways to refer to multiple column modes.
\def\quadcolumns{\@columns4}%
\def\triplecolumns{\@columns3}%
\def\doublecolumns{\@columns2}%
\def\begincolumns#1{\ifcase#1\relax \or \singlecolumn \or \@columns2 \or
\@columns3 \or \@columns4 \else \relax \fi}%
\let\endcolumns = \singlecolumn
\let\@ndcolumns = \relax
%
% Set this by default so \vfootnote can unconditionally inspect it.
\chardef\@numcolumns = 1
%
% Start typesetting with #1 columns.
\def\@columns#1{%
\@ndcolumns
%
\let\@ndcolumns = \@endcolumns
\chardef\@numcolumns = #1
%
\par % Shouldn't start in horizontal mode.
\previousoutput = \expandafter{\the\output}%
%
% Figure out how wide the columns should be -- for n columns,
% decrement by n - 1 gutters.
\@columnhsize = \hsize
\count@ = \@numcolumns
\advance\count@ by -1
\advance\@columnhsize by -\count@\gutter
\divide\@columnhsize by \@numcolumns
%
% Set up to grab the page so far and save it in \@partialpage.
\output = {\global\setbox\@partialpage =
\vbox{\unvbox255\vskip\abovecolumnskip}%
}%
%
% \pagegoal is the size that TeX will make \box255. We want a box
% exactly the size of the current height of the page, i.e., \pagetotal.
\pagegoal = \pagetotal
%
% Expand the \output we just defined.
\eject
%
% Reset \output to prepare for the first real page break.
\output = {\@columnoutput}%
\@normalhsize = \hsize
\@normalvsize = \vsize
\hsize = \@columnhsize
%
% Compute \vsize based on what's already on the page
% and the number of columns. Also change the mag factor for insertions.
\advance\vsize by -\ht\@partialpage
%
\advance\vsize by -\ht\footins
\ifvoid\footins\else \advance\vsize by -\skip\footins \fi
\multiply\count\footins by \@numcolumns
%
\advance\vsize by -\ht\topins
\ifvoid\topins\else \advance\vsize by -\skip\topins \fi
\multiply\count\topins by \@numcolumns
%
\global\vsize = \@numcolumns\vsize
}%
%
% When this is invoked box 255 contains just the right amount of
% material, whether triggered by an output routine or a change in the
% number of columns. Because columns have to contain an integral number
% of lines of type, we take a bit of care with balancing the heights of
% the columns to prevent either losing material or having a very short
% last column.
%
% when a page ends due to \bye or \eject, box 255 will contain lots of
% white space, so the columns will not look balanced. To fix this use
% \singlecolumn before ending the page.
%
\def\@columnsplit{%
\splittopskip = \topskip
\splitmaxdepth = \baselineskip
%
% \dimen@ will be the height that the double-column material on this
% page should have, i.e., the height of the page (\singlecolumvsize)
% minus single-column material, which includes insertions. (If you
% want your insertions to respect the columns, you will have to
% change the output routine.) If you add more insertions, they
% should be taken into account both here and in \singlecolumn.
%
% Unfortunately, we lose on flexible glue because we must
% \vsplit to a <dimen>.
\dimen@ = \ht255
\divide\dimen@ by \@numcolumns
%
% Split the long scroll into columns.
\begingroup
% We do not want to see underfull \vbox messages unless the final
% page is underfull.
\vbadness = 10000
%
% The first (leftmost) column.
\global\setbox1 = \vsplit255 to \dimen@ \global\wd1 = \hsize
%
% The second column.
\global\setbox3 = \vsplit255 to \dimen@ \global\wd3 = \hsize
%
\ifnum\@numcolumns > 2
% The third column, if requested.
\global\setbox5 = \vsplit255 to \dimen@ \global\wd5 = \hsize
\fi
\ifnum\@numcolumns > 3
% The fourth column, likewise if requested.
\global\setbox7 = \vsplit255 to \dimen@ \global\wd7 = \hsize
\fi
\endgroup
%
% Preserve what's left over.
\setbox0 = \box255
%
% Set up \box255 with the real output page, as the previous output
% routine expects.
\global\setbox255 = \vbox{%
\unvbox\@partialpage
\ifcase\@numcolumns \relax\or\relax
\or \hbox to \@normalhsize{\box1\hfil\box3}%
\or \hbox to \@normalhsize{\box1\hfil\box3\hfil\box5}%
\or \hbox to \@normalhsize{\box1\hfil\box3\hfil\box5\hfil\box7}%
\fi
}%
%
% Save what's left over in a private register before calling their
% output routine.
\setbox\@partialpage = \box0
}%
%
% Our output routine splits the columns and then calls the previous one.
%
\def\@columnoutput{%
\@columnsplit
\hsize = \@normalhsize % Local to \output's group.
\vsize = \@normalvsize
\the\previousoutput
%
% Put back what didn't fit.
\unvbox\@partialpage
\penalty\outputpenalty
%
% The correct vsize is the original vsize times the
% number of columns.
\global\vsize = \@numcolumns\@normalvsize
}%
%
% Go back to single-column typesetting. Assume \doublecolumns has
% been called.
%
\def\singlecolumn{%
\@ndcolumns
\chardef\@numcolumns = 1
\vskip\belowcolumnskip
\nointerlineskip
}%
%
\def\@endcolumns{%
\global\let\@ndcolumns = \relax
\par % Shouldn't start in horizontal mode.
%
\global\output = {\global\setbox1 = \box255}%
\pagegoal = \pagetotal
\eject % Exercise the page builder, i.e., \output.
\global\setbox255 = \box1 % Retrieve what the fake \output set.
%
% \box255 now has the double-column material. On the page where we
% switch back to one column, the double-column material might not
% fill up the page. We want to split whatever is there.
\@columnsplit
%
\global\vsize = \@normalvsize
\global\hsize = \@normalhsize
\global\output = \expandafter{\the\previousoutput}%
%
\ifvoid\topins\else\topinsert\unvbox\topins\endinsert\fi
\unvbox255
}%
%
% We don't have any way to force a column eject, since the \output
% routine is only prepared to split up a full page of material. Instead,
% we provide the following as a guess at enough space to fill up the
% current column.
\def\columnfill{%
\dimen@ = \@normalvsize
\advance\dimen@ by -\pagetotal
\kern\dimen@
}
%
%
\let\wlog = \@plainwlog
\catcode`@ = \@eplainoldatcode
%
\def\fmtname{eplain}%
\def\eplain{t}%
{\edef\plainversion{\fmtversion}%
\xdef\fmtversion{REPLACE-WITH-VERSION: REPLACE-WITH-DAY-MONTH-YEAR (and plain \plainversion)}%
}%
%
%
%
%
% Local variables:
% page-delimiter: "^% \f"
% End:
|