% $Id: macros.tex,v 1.4 2020/01/01 23:22:22 karl Exp $
% This is part of the book TeX for the Impatient.
% Copyright (C) 2003-2020 Paul W. Abrahams, Kathryn A. Hargreaves, Karl Berry.
% See file fdl.tex for copying conditions.
%
% Macros for typesetting TeX for the Impatient.
%
% These macros are being distributed without any warranty whatsoever.
% The level of commentary is that which we, the authors, found necessary
% for our own purposes. 
%
% ==========================================================================
%
% The macros use the term `chapter' for what in the book is called
% a `section', `section' for the book's `subsection', etc.  For purposes of
% defining macros it's convenient to think of the book as divided into
% chapters, but because of the nonsequential nature of the book we don't
% want to tell the readers that they are reading chapters.


% An embedded file should end with \byebye.
% 
\begingroup
\ifx \macsin\relax
   % In frontm.tex, we do \input macros several times, and we still want
   % the \byebye at the end to end the job.
   % So we \input inside a group in frontm, and make the assignment to
   % \endinput local.
   \aftergroup\let\aftergroup\byebye\aftergroup\endinput
   \aftergroup\endinput   % Don't read this file again.
\else
   \global\let\byebye = \end
   \global\let\macsin = \relax
\fi
\endgroup

% This must come before config.tex.
\input eplain

% Define configuration switches and then read their values.
% 
\newif\ifcenterpage \centerpagetrue
\newif\ifcompletebook
\newif\iffinal % true for the 2000dpi copy
\newif\ifmsdos
\newif\ifedgetabs \edgetabstrue
\newif\ifdvi \dvitrue % true if we want a .dvi file

%\xrefwarningfalse

% The config file contains settings for flags, e.g.,
%   \completebookfalse
% It can be empty as long as it exists.
\input config
\ifcompletebook \else\rewritetocfilefalse \fi
\edef\tempfile{\ifmsdos g:temp \else x \fi}
\ifx\setmodes\undefined\else\setmodes\fi % modify from command line input

% Certain defaults are forced by certain others.
%
\iffinal \centerpagetrue \edgetabstrue\fi

% Initial definitions.  (These should come before \input fonts.)
% 
\catcode`\@ = \letter % For the macro file only.

% We don't want register allocation information in the log,
% so we redefine the relevant macro from plain.tex.

\def\alloc@#1#2#3#4#5{\global\advance\count1#1 by 1
   \ch@ck#1#4#2%
   \allocationnumber=\count1#1  \global#3#5=\allocationnumber
}

% The fonts.  This should come before defining the new character control
% sequences that follow.
% 
\input fonts

\hyphenation{script-script base-line-skip no-base-line-skip line-skip
   line-skip-limit max-dead-cycles output-penalty no-inter-line-skip
   show-box-depth show-box-breadth if-hmode if-vmode if-mmode
   back-spaces back-space par-indent tracing-on-line}

{
   \catcode`\| = 0
   \catcode`\\ = \other
   |global|let|bsc = \   % \bsc is a true backslash character.
}

\let\\ = \bsc

\def\bslash{$\backslash$} % backslash suitable for printing
\let\shriek = !
\let\vbar = |
{
   \catcode `\[ = 1 \catcode `\] = 2 
   \catcode `\{ = \other \catcode `\} = \other
   \global\let\lbracechar = {
   \global\let\rbracechar = }
]
\def\blbrace{{\bt \{}}
\def\brbrace{{\bt \}}}

{
   \catcode`\ =\other% Notice no spaces at beginning of next line.
\gdef\otherspace{ }
}

\let\mathlbrace = \{  \let\mathrbrace = \}
{
   \catcode `\[ = 1 \catcode `\] = 2
   \catcode `\{ = \other \catcode `\} = \other
   \gdef\{[\ifmmode\mathlbrace\else [\bt {]\fi]
   \gdef\}[\ifmmode\mathrbrace\else [\bt }]\fi]
]


% These are for debugging (less drastically than \tracingall or \loggingall).
% 
\def\tron{\tracingmacros=2 \tracingcommands=2 \tracingonline=1}
\def\troff{\tracingmacros=0 \tracingcommands=0}

% \pagebreak should always cause a break, even if the resulting
% page is empty.
% 
\def\pagebreak{\null\vfill\eject}

% \linebreak causes a line break in chapter headings, but outside of that
% context we don't want it to do anything.
%
\let\linebreak = \relax


% Parameters.
% 
\parskip = 0pt plus 0.3pt
\newdimen\codefuzz \codefuzz = 10pt % for \csdisplay, \example
\hbadness = 4000
\vbadness = 8000
\hfuzz = 0.1pt % as in plain TeX
\vfuzz = 0.1pt % as in plain TeX
\exhyphenpenalty = 0 % we don't mind these
\widowpenalty = 10000 % these are very bad
\clubpenalty = 10000 % these are very bad too

% Page margins.
%
% Note that the \newdimens can't be within an \if or a \def
% because \newdimen is an \outer macro (thanks to DEK).
% 
\newdimen\insidemargin \newdimen\outsidemargin
\newdimen\topmargin \newdimen\bottommargin
\newdimen\headmargin
\newdimen\totalwidth \newdimen\totalheight
\newdimen\oddoffset \newdimen\evenoffset
\newif\ifnoheadline

% \totalwidth and \totalheight are the actual trim size of the book.
% \insidemargin, \outsidemargin, \topmargin, and \bottommargin are margins
% with respect to the pages of the book, not the draft 8 1/2 x 11 pages.
%

% This makes it so that we only have to cut twice on a page.
% 8.5" = 51.19125pc exactly.
% \totalwidth should = \outsidemargin + \insidemargin + \hsize.
% 
\totalwidth = 7.375in % 44.4159375pc = 7 3/8".
\outsidemargin = 8pc
\insidemargin = 10pc
\hsize = \totalwidth
\advance \hsize by -\outsidemargin
\advance \hsize by -\insidemargin
% \hsize should now be 26.4159375pc

% Now that we know \hsize, we can set \parfillskip to eliminate (most)
% widows. 
%
\parfillskip = .75\hsize plus .06\hsize minus .75\hsize


% \oddoffset and \evenoffset are the \hoffset values needed to
% align the left edge of the virtual page with the left edge of the
% draft paper (not the left edge of the book pages).
%
% The -1in below comes from the default margin, which the DVI driver must
% set at 1in.  Odd pages are on the left, even on the right.
% 
% First, align the left edge of the virtual page with the left edge of the
% draft page.
%
\oddoffset = -1in
\advance\oddoffset by \insidemargin
%
\evenoffset = -1in
\advance\evenoffset by \outsidemargin

% For centered pages, move the virtual page right by half the trim width.
%
\ifcenterpage
   \dimen0 = 8.5in
   \advance\dimen0 by -\totalwidth
   \divide\dimen0 by 2
   \advance\oddoffset by \dimen0
   \advance\evenoffset by \dimen0 

% For uncentered even-numbered pages, align the right edge of the virtual
% page with the right edge of the draft paper so that we can remove the trim
% of two-sided pages with a single cut.
%
\else
   \advance\evenoffset by 8.5in
   \advance\evenoffset by -\totalwidth
\fi

\hoffset = \oddoffset   % First page is numbered one.

% Now for the vertical, which is simpler, since it doesn't vary from
% page to page.
% 11" = 66.2475pc exactly.
% \totalheight should = \topmargin + \bottommargin + \vsize.
% 
\totalheight = 9.25in % 9 1/4" = 55.708125pc
\topmargin = 6pc      % Distance from top of page to baseline of text line 1
\bottommargin = 6pc   % Distance from last line to bottom of page.
\topskip = 2pc        % Distance from top of \box255 to baseline of text line 1
% \vsize                Distance from top of \box255 to last line of text.
% \headmargin           Distance from top of \box255 to top of page
% We'll place the headline just above \box255

\headmargin = \topmargin \advance \headmargin by -\topskip

\vsize = \totalheight
\advance \vsize by -\headmargin
\advance \vsize by -\bottommargin
% \vsize should now be 46.708125pc

\voffset = -1in % align top of logical page with top of physical page
\advance \voffset by \headmargin
\ifcenterpage
   \dimen0 = 11in
   \advance\dimen0 by -\totalheight
   \divide\dimen0 by 2
   \advance\voffset by \dimen0
\fi

\topskip = 2pc        % Distance from headline to first line of text.


% Other formatting parameters.
% 
% The basic increments we'll use in the layout.
% 
\def\setskip#1 = #2 {%
   \dimen0 = #2\baselineskip
   \csname #1skipamount\endcsname =
      \dimen0 plus .33\dimen0 minus .25\dimen0
   \ignorespaces
}
\newskip\greaterskipamount
\newskip\greatskipamount
\newskip\biggerskipamount
\newskip\medbigskipamount
\newskip\medsmallskipamount
\newskip\tinyskipamount

\setskip greater = 2.5
\setskip great = 2.0
\setskip bigger = 1.5
\setskip big = 1.0
\setskip medbig = .75
\setskip med = .5
\setskip medsmall = .375
\setskip small = .25
\setskip tiny = .125

\parindent = 1em
\newdimen\normalindent \normalindent = \parindent

\footnotemarkseparation = .16666em

\abovelistskip = \smallskipamount
\interitemskip = \tinyskipamount
\belowlistskip = \smallskipamount
\listleftindent = \parindent

% Displays involve text and math.  We don't want as much flexibility in
% the glue as plain.tex sets.
% 
\abovedisplayskip = \medsmallskipamount
\abovedisplayshortskip = 0pt plus 2pt
\belowdisplayskip = \medsmallskipamount
\belowdisplayshortskip = \belowdisplayskip

\newskip\intercapsuleskip   \intercapsuleskip = .75\tinyskipamount plus 0.4pt
\newdimen\capsulehangindent  \capsulehangindent = 2pc

\newskip\aboveconceptskip   \aboveconceptskip = \bigskipamount


\newskip\abovesectionskip    \abovesectionskip = \greaterskipamount
% No stretch or shrink below heads, according to A-W.
\newskip\belowsectionskip    \belowsectionskip = 1\biggerskipamount

\newskip\abovesubsectionskip   \abovesubsectionskip = \greatskipamount
\newskip\belowsubsectionskip   \belowsubsectionskip = 1\bigskipamount

\newskip\abovedescriptionskip   \abovedescriptionskip = \biggerskipamount
\newskip\belowdescriptionskip   \belowdescriptionskip = \medskipamount

\newskip\explainskip   \explainskip = \tinyskipamount
\newskip\exampleskip   \exampleskip = \smallskipamount

\def\interexampleskip{\vskip\medsmallskipamount}
\def\tinyskip{\vskip\tinyskipamount}

% Space in which a symbol is shown in a columnated list of commands.
\newdimen\symbolspace  \symbolspace = 14pt

% \colsindent is the indentation before material arranged in columns and
% displayed, as in the list of Greek letters.
\newskip\colsindent \colsindent = \parindent

% The indentation for page lists in the index that don't fit on one line.
\newdimen\indexpageindent   \indexpageindent = 1pc

% The indentation for subsidiary entries in the index. (Should be less
% than \indexpageindent.)
\newdimen\indexlevelindent   \indexlevelindent = .5pc 

\newskip\codebaselineskip   \codebaselineskip = \baselineskip

% Fill the previous page with blank space before a command.
%
\def\cmdbreak{\par\nobreak\vfil\penalty 1000\vfilneg\par}

% Penalties.
%
\newcount\conceptpenalty   \conceptpenalty = -1500
\newcount\intercmdnamepenalty   \intercmdnamepenalty = 300
\newcount\@intercmdnamepenalty  \@intercmdnamepenalty = \intercmdnamepenalty



% The output routine.
%
\output = {%
   \onepageout
   %
   % Odd pages are right-hand pages.
   % 
   % Note \pageno has been incremented when we get here -- it now refers
   % to the page number of the page about to be typeset, not the page
   % that we just shipped out.
   % 
   \ifodd\pageno   % \onepageout advances \pageno.
      \global\hoffset = \oddoffset
      \global\intercmdnamepenalty = 10000
   \else
      \global\hoffset = \evenoffset
      \global\intercmdnamepenalty = \@intercmdnamepenalty
   \fi
}

\ifdvi\else\output={%
   \setbox0=\box255\deadcycles=0
   \advancepageno
   \global\advance \truepage by 1
   \ifnum\outputpenalty>-20000\else \dosupereject \fi
   }
\fi

\def\onepageout{%
   \shipout\vbox{%
      \offinterlineskip % The page should have vertically abutting boxes.
      \ifodd\pageno
         \cropmargin = \insidemargin
      \else
         \cropmargin = \outsidemargin
      \fi
      \addcropmarks % Does not affect the position.
      \ifcenterpage \addtruepage \fi
      %
      \ifedgetabs \ifodd\pageno \ifnoheadline\else
         \edgetabs % Does not affect the position.
      \fi\fi\fi
      %
      \vbox to 0pt{\vskip-\headmargin \vskip-3.5pc
         \rightline{\sevenrm\timestamp}\vss}%
      %
      \smash{\line{\the\headline}}% Simplified \makeheadline.
      \pagebody
      \vskip 2\normalbaselineskip
      % The footline is needed on one page (for an example).
      \line{\the\footline}%
   }%
   % Now the rest from \plainoutput:
   \advancepageno
   \global\advance\truepage by 1
   \ifnum\outputpenalty>-20000\else \dosupereject \fi
} 

\footline = {\hfil}

% The headline always includes the name of the current chapter.  This
% goes on the inside.  If more information, such as the concept we're
% explaining, is included, it goes on the outside.
% 
\headline = {%
   % Produce the timestamp
   \ifnoheadline
      \hfil
      \global\noheadlinefalse
   \else
      \let\\ = \ignorespaces
      \ifodd \pageno  % Right-hand page.
         {\tenit \firstmark}\hfil {\tenbf \folio}%
      \else           % Left-hand page.
         {\tenbf \folio}%
         \hfil
         {\tenit
          \chaptername
          \ifnum\pageno>0\ifback\else
            \quad $\backslash$\quad\S\the\chapterno
          \fi\fi
         }%
      \fi
   \fi
}

% Sizes for cropmarks:
% 
\newdimen\cropthick  \cropthick = 0.4pt
\newdimen\crophsize  \crophsize = 1pc
\newdimen\cropvsize  \cropvsize = 1pc
\newdimen\cropoffset \cropoffset = .0625in

% Each of the following macros generates a quarter of a cropmark as
% a zero-size box at the center point of the cropmark.
% We want the cropmarks to be centered with respect to their thicknesses.

\def\vcropdown {\hbox to 0pt{%
   \kern -.5\cropthick
   \vbox to 0pt{%
      \vskip \cropoffset
      \hrule width\cropthick depth\cropvsize height0pt
      \vss}%
   \kern -.5\cropthick}%
}

\def\vcropup {\hbox to 0pt{%
   \kern -.5\cropthick
   \vbox to 0pt{%
      \vss
      \hrule width\cropthick depth\cropvsize height0pt
      \vskip \cropoffset}%
   \kern -.5\cropthick}%
}

\def\hcropright{\rlap{\kern\cropoffset\smash{%
   \vrule width\crophsize depth .5\cropthick height .5\cropthick}}}

\def\hcropleft{\llap{\smash{%
   \vrule width\crophsize depth .5\cropthick height .5\cropthick}%
   \kern\cropoffset}}

% \cropmargin will be set to the left margin on the current page.
% 
\newdimen\cropmargin
\def\cropline#1{\moveleft\cropmargin\hbox to \totalwidth{#1}}

% \addcropmarks adds the cropmarks to a page while leaving everything else
% alone.  It assumes we're positioned at the top of the page.

\def\addcropmarks{%
   \vbox to 0pt{%
      \offinterlineskip % contextually redundant but precautionary
      \vskip -\headmargin  % to get to logical top of page
      \ifcenterpage
         \cropline{\hcropleft\vcropup \hfil \vcropup\hcropright}
      \else
         \cropline{\hfil \vcropdown}%
      \fi
      \vskip\totalheight
      \ifcenterpage
         \cropline{\hcropleft\vcropdown \hfil \vcropdown\hcropright}%
      \else
         \cropline{\hcropright\hfil\hcropleft\vcropup\vcropdown\hcropright}%
      \fi
      \vss
}}

% \addtruepage adds a small page number near the upper right cropmark.
%
\newcount\truepage \truepage = 1
\def\addtruepage{%
   \vbox to 0pt{\vskip -\headmargin\vskip -2pc
      \moveleft\cropmargin\hbox to \totalwidth{%
         \twelvebf 
         \quad\TeX\ for the Impatient\hss
         N\raise 3.3pt\hbox{o} \the\truepage\quad}%
      \vss}%
}


% The mark information is output by \markinfo.
%
% We can use a different mark, e.g., a shorter heading, by calling
% \changemark.
% 
\newtoks\shortmark \shortmark = {}
\newif\ifchangemark

\def\markinfo#1{%
   \ifchangemark
      \mark{\the\shortmark}\changemarkfalse
   \else
      \mark{#1}%
   \fi
}

\def\changemark#1{\shortmark = {#1}\changemarktrue}


% ``Tabs'' down the side of the book.
% Say \nextedgetab to move the thing down to the next.
% Say \edgetabsfalse to turn them off.
% 
\newcount\numtabs  \numtabs = 7
\newdimen\edgetabjump  \edgetabjump = 0pt
\def\nextedgetab{%
   \advance\edgetabjump by \edgetabdepth
}

\def\settabdepth#1{%
   \edgetabdepth = #1
   \setbox\tabbox = \vbox to \edgetabdepth{%
      \leaders
      \vbox{\vskip \edgespacing
         \hrule width\edgetabwidth height0pt depth\edgethick}%
      \vfil}
}

\newskip\bigtab \newskip\smalltab
\newskip\edgetabdepth   
\newbox\tabbox

\bigtab = \totalheight    \divide\bigtab by \numtabs
\smalltab = .4\bigtab % five smalls make two bigs

\newdimen\edgetabin     \edgetabin = .25in
\newdimen\edgetabbleed  \edgetabbleed = .25in
\newdimen\edgetabwidth
   \edgetabwidth = \edgetabin
   \advance \edgetabwidth by \edgetabbleed
\newdimen\edgethick   \edgethick = .3pt % line thickness
\newdimen\edgespacing \edgespacing = .9pt % line spacing


\def\edgetabs{\vbox to 0pt{%
   \vskip-\headmargin
   \vskip\edgetabjump
   \hbox{%
      \hskip \hsize
      \hskip\outsidemargin
      \hskip-\edgetabin
      \copy\tabbox
      }%
   \vss
}}


% We can simplify \pagecontents (which is called by \pagebody) somewhat,
% since we don't have \topinserts.
% 
\def\pagecontents{%
   \unvbox255   % The main page contents.
   %
   \ifvoid\footins\else   % Footnotes are present.
      \vskip\skip\footins
      \footnoterule
      \unvbox\footins
   \fi
}


% The command chapters had a mini-index at the bottom of right-hand
% pages.  These definitions are the way to put entries into it.
% 
% \minref generates a reference for the mini-index, and prints the
% reference on the page, also.
% 
\def\minref#1{%
   #1% Print it on the page.
   % That's it, now.
}

% Mini-index entry without printing the argument on the page.
% Just ignore the argument now.
% 
\def\minrefs#1{%
   \ignorespaces
}

% This is used for producing the concept mini-index.
% 
\def\minrefsdelim#1\endmark{\minrefs{#1}}

% One last insertion-oriented thing:
% we always want numbered footnotes, as defined in eplain.
% We'll do them in 8-point type.
% 
\let\@plainfootnote = \footnote
\let\footnote = \numberedfootnote
\everyfootnote = {\footnotefonts}


% The \margin macro produces a marginal note at the same level as its call.
% It should only be used in a paragraph or in the main vertical list.
% It is nullified when we're printing the final copy.
%
\def\margin#1{%
   \ifhmode
      \vadjust{\printmarginnote{#1}}%
   \else
      \dimen0 = \prevdepth
      \prevdepth = -1000pt
      \printmarginnote{#1}%
      \prevdepth = \dimen0
   \fi
   \ignorespaces 
}

\def\printmarginnote#1{%
   \hbox to 0pt{%
      \hskip 1.1\hsize
      \vbox to 0pt{%
    \everypar = {}% Don't inherit hanging indentation.
    \hsize = 1in \rightskip = 0pt plus 1fil \noindent \sevenrm
    \let\tt = \eighttt
    \parfillskip = 0pt plus 1fil
    \baselineskip = 8pt #1%
         \vss
      }%
      \hss
   }%
}

%\iffinal
\iftrue
   \def\margin#1{\ignorespaces}
\fi


% Stuff to preserve page breaks inserted for the 2nd printing.
% This macro takes one ``argument''.
% 
\def\secondprinting{\afterassignment\finishsecondprinting \toks0 = }
\def\finishsecondprinting{\the\toks0}



% Parts of the book.
%
% 
% Chapters.
% 
\let\chaptername = \empty
\newcount\chapterno

\def\chaprule{\vrule depth3\baselineskip height1.5pc width1pt}

% Chapter openings should not have headlines.
% The text of each chapter starts on a right-hand page in the final
% book.  The facing page has an illustration.  This means that if the
% previous chapter ended on a left-hand (i.e., even) page, we have to
% eject an extra blank page.
% 
\outer\def\chapter#1 \par{%
   \ifcompletebook % Don't do the blank pages for proof copies.
      \blankpage % the illustration page
      % The first real chapter starts on page 1.
      \ifnum\pageno < 0 \pageno = 1 \fi
   \fi
   %
   \def\chaptername{#1}%
   \advance\chapterno by 1
   %
   \setbox0 = \hbox{\chapternumeralfont
                    \kern1pt
                    \expandafter\kernchapno\the\chapterno\empty
                    \kern3pt}%
   \vglue 0pt % But we get a \topskip of 2pc now.
   \nointerlineskip
   \leftline{%
      \ifback\else
         \vtop{%
            \copy0
            \vskip6pt
            \hrule width\wd0 height2.2pc
         }%
         \kern 16pt
      \fi
      \chapterfonts % to get \baselineskip now
      \chaprule
      \kern 6pt
      \vtop{%
         \def\linebreak{\hfil\break}%
         \noindent \chaptername}%
   }%
   \vskip 6pc plus.5pc minus.5pc
   \noheadlinetrue
   \toks0=\expandafter{\chaptername}
   \edef\writechaptertoc{%
     \noexpand\writenumberedtocentry{chapter}{\the\toks0}{\the\chapterno}%
   }%
   \writechaptertoc
   %
   % Use chaptername as first A-head (or only one).
   \mark{\chaptername}%
   \footnotenumber = 0 % Number footnotes from 1 in each chapter.
   \beginit{CHAPTER}%
   \noindent
   \ignorespaces
}

\def\endchapter{%
   \mark{\chaptername}% Use chapter name on last blank recto page
   \vfil\eject  % be sure everything's out before testing for recto
   \ifodd\pageno
      \message{Chapter ends on a verso page.}%
      \blankpage
   \fi
   \endit{CHAPTER}%
}
%
% \blankpage creates a blank page with no headline.
% In the final book, it just advances the page number.
% For the web edition, the blank pages serve no purpose except to keep
% the indexing correct.  I didn't want to rerun the index.
% 
\def\blankpage{%
   \iffinal
      \advancepageno
      \global \advance \truepage by 1
   \else
      \noheadlinetrue\pagebreak
   \fi
}

% This hokey little macro kerns between the numerals in the chapter
% number.  We want to kern more between `11' then otherwise; also, we
% want to remove the extra space before the chapter number, and after
% `11'.
% 
\def\kernchapno#1#2{%
   \ifx\empty#2\else \kern-3pt \fi
   #1%
   \ifx\empty#2\else
      \if1#2%
         \kern-.1em
      \else
         \kern-.05em
      \fi
   \fi
   #2%
   \if 1#2\kern-.1em\fi
}

% Sections.
% 
\newif\ifheading   % Avoid breaking after a heading.

% get section numbers for the fdl only, since it has internal references.
\let\fdlkludge=\empty

% The heading flag is turned on by headings and turned off
% at the start of a description.
% 
\outer\def\section#1 \par{%
   \par % be sure we're in vertical mode
   \saveskip = \lastskip % will be 0 if no skip
   \cmdbreak
   \combineskips\abovesectionskip
		\dimen0 = 2.5\baselineskip \advance\dimen0 by -\topskip
		\vskip -\dimen0
		\vglue \dimen0
   %
   {\sectionfonts \leftline{\fdlkludge #1}}%
   %
   \markinfo{#1}%
   \writetocentry{section}{#1}%
   \nobreak
   % Don't go into horizontal mode within the command descriptions.
   % 
   \vskip\belowsectionskip
   \ifcommands \else \noindent \fi
   \headingtrue
   \everypar = {\headingfalse \global\everypar = {}}%
      % only gets executed for \par in horizontal mode
   \ignorespaces
}


% Subsections.  We don't want a break at the glue if we were preceded by
% a \nobreak.
% 
\def\subsection#1 \par{%
   \par % be sure we're in vertical mode
   \saveskip = \lastskip % will be 0 if no skip
   \ifheading  % Did we just have \section?
      \nobreak
	\fi
   \combineskips\abovesubsectionskip
	\dimen0 = 2.5\baselineskip \advance\dimen0 by -\topskip
	\vskip -\dimen0
	\vglue \dimen0
   %
   {\subsectionfonts
      \leftline{\vrule width.5em height1.2ex depth.2ex \enspace #1}}%
   \writetocentry{subsection}{#1}%
   \nobreak
   % Don't go into horizontal mode within the command descriptions.
   \vskip\belowsubsectionskip
   \ifcommands \else \noindent \fi
   \headingtrue 
   \everypar = {\headingfalse \global\everypar = {}}%
      % only gets executed for \par in horizontal mode
   \ignorespaces
}

% \combineskips combines the current skip (#1) with the previous skip
% (which must be in \saveskip), and effectively skips by the larger of
% the two.
%
\newskip\saveskip
\def\combineskips#1{\ifdim\saveskip<#1\vskip-\saveskip \vskip#1\fi}



% List macros.
% 

% We want to use different names than eplain.
% 
\let\ulist = \unorderedlist
\let\endulist = \endunorderedlist
%
\let\olist = \numberedlist
\let\endolist = \endnumberedlist

\let\compact = \listcompact

% The \noindent here keeps us from getting indentation on the first line.
% It also makes the display into a `short' display, FYI.
% The \belowdisplayskip and \abovedisplayskip glue are inserted by the
% display.
% 
\long\def\display#1{%
   \ifvmode \noindent \fi
   $$\vtop{\everypar = {}\hsize = \displaywidth
      \parfillskip = 0pt plus 1fil % don't worry about widows
      \noindent #1\par\global\savedepth = \prevdepth}$$%
   \endgraf
   \prevdepth = \savedepth
}

% \vdisplay is like \display, except it's for vertical mode material.  Use it
% to avoid an unwanted initial lineskip.
% 
\long\def\vdisplay#1{%
   \ifvmode \noindent \fi
   $$\vtop{\everypar = {}\hsize = \displaywidth
      \parfillskip = 0pt plus 1fil % don't worry about widows
      #1\par\global\savedepth = \prevdepth}$$%
   \endgraf
   \prevdepth = \savedepth
}



% Indexing.
% Derived from Knuth's manmac macros.
% 
\newwrite\index

\immediate\openout\index = \jobname.idx
\newif\ifsilent

% We need ^ to be active temporarily, while we define it.
% 
{  \catcode`\^ = \active
%
\gdef^{%
   \ifmmode
      \let \nextaction = \sp
   \else
      \let \nextaction = \beginindexref
      \begingroup
      \catcode `| = \other \catcode `^ = \other
   \fi
   \nextaction
}}

\def\beginindexref{\futurelet\next\checksilence}

{% And for here, we need ^ to be deactivated
\catcode `^ = \other

\gdef\checksilence{%
   \if ^\next
      \silenttrue \let\nextaction = \secondhat
   \else
      \silentfalse \let\nextaction = \checkbar
   \fi
   \nextaction
}

% Eat the `^' that we saw would be the next token.
% 
\gdef\secondhat^{\checkbar}

} % end scope where ^ is \other

\def\checkbar{\futurelet\next\iswitch}

% Here we start reading the text of the actual index entry;
% we've determined whether it's silent or not.
% 
% We handle the following cases:
%      ^{alpha} and ^^{alpha}
%      ^|alpha| and ^^|alpha|
%      ^|\alpha| and ^^|\alpha|
% 
% When this is called, \next is either `|' or `{'.
%
\def\iswitch{%
   \ifx |\next
      \let \nextaction = \checkbackslash
   \else
      \let \nextaction = \normalidx
   \fi
   \nextaction
}

\def\checkbackslash|{%
   % within |...| we allow anything (but another |)
   \deactivate \catcode `\  = \other
   \futurelet\next\litidx
}

% The thing after the ^ is a |.  We have further checking to do -- is
% the next character a \?
% 
{ % reverse \ and /
\catcode`\/ = 0
\catcode`\\ = \other
/gdef/litidx{%
   /if \/next
      /expandafter/litidxA
   /else
      /expandafter/litidxB
   /fi
}

% The thing being indexed starts with a \.
% 
/gdef/litidxA \#1|{%
   /ctsidxref{#1}%
   /litidxswitch{/\#1}%
}

% The thing being indexed is just a word.
% 
/gdef/litidxB #1|{%
   /ttidxref{#1}%
   /litidxswitch{#1}%
}
}% end reversal of \ and /

% The thing after the ^ is not a |.
% 
\def\normalidx#1{%
   \ifsilent
      \aftergroup\ignorespaces
   \else
      #1%
   \fi
   \idxref{#1}%
   \endgroup % group started by \iswitch.
}

\def\litidxswitch#1{%
   \ifsilent
      \aftergroup\ignorespaces
   \else
      {\tt #1}%
   \fi 
   \endgroup % group started by \iswitch.
}



% Indexing macros for external use.

% \idxref generates an index entry for #1. If #1 contains any control
% sequences, they are treated literally.
% 
\def\idxref#1{\indexwrite{#1}N\ignorespaces}


% For creating an index entry for control space.
{\catcode `\ =\other
\gdef\blankidxref{\ctsidxref{ }}
}

% I removed this macro from eplain because \csname works as well, but
% since the macros below are already written to use it ...
\def\@tokstostring#1{\@ttsA#1 \@ttsmarkA}%
\let\tokstostring=\@tokstostring
\def\@ttsA#1 #2\@ttsmarkA{%
   \@ifempty{#1}\else
      \@ttsB #1\@ttsmarkB
      \@ifempty{#2}\else
         \@spacesub\@ttsA#2\@ttsmarkA
      \fi
   \fi
}%
\def\@ttsB#1{%
   \ifx #1\@ttsmarkB\else
      \string #1%
      \expandafter\@ttsB
   \fi
}%
\def\@ttsmarkB{\@ttsmarkB}% should never be expanded
%
\def\@spacesub{+}%
\let\spacesub = \@spacesub
%
\def\@ifempty#1{\@@ifempty #1\@emptymarkA\@emptymarkB}%
\def\@@ifempty#1#2\@emptymarkB{\ifx #1\@emptymarkA}%
\def\@emptymarkA{\@emptymarkA}% Again, so \ifx won't complain.

% #1 is the index term, #2 is the reference as in 
% Diacritical mark, see accent.

\def\idxsee#1#2{%
   \begingroup
   \def\spacesub{\otherspace}%
   \edef\nextaction{\write\index{\tokstostring{#1}::N::*\tokstostring{#2}}}%
   \nextaction
   \ignorespaces
\endgroup}


% \ttidxref generates an index entry for #1 in the program font.
% If #1 contains any control sequences, they are treated literally.
% 
\def\ttidxref#1{\indexwrite{#1}T\ignorespaces}


% \ctsidxref generates an index entry for a control sequence.  #1
% should not have a preceding backslash, so that the proper call for
% indexing \alpha is \ctsidxref{alpha}.
% 
\def\ctsidxref #1{\indexwrite{#1}C\ignorespaces}

% \indexchar is needed to generate index entries for three especially
% difficult single characters: {, }, and \.  They are blank-delimited.
% 
\def\indexchar{\begingroup \deactivate \indexcharA}
\def\indexcharA#1 {\indexwrite{#1}T\endgroup}

% \pix indicates that the next index entry is a principal one.
% 
\newif\ifpix
\def\pix{\global\pixtrue}

% \bix and \eix indicate that the next index entry begins or ends a
% range of pages.
%
\newif\ifbix \def\bix{\bixtrue}
\newif\ifeix \def\eix{\eixtrue}

% #1 is the text of the entry, #2 is N (normal), T (typewriter) or
% C (control sequence) or `cs' for now.
%
\def\indexwrite#1#2{\begingroup
   \def\spacesub{\otherspace}%
   \edef\tts{\tokstostring{#1}}%
   \edef\nextaction{\write\index{\tts::#2::\noexpand\number\noexpand\pageno
      \ifpix P\fi\ifbix B\fi\ifeix E\fi}}%
   \nextaction
   \global\pixfalse \global\bixfalse \global\eixfalse
\endgroup}

{\catcode `\^ = \other \gdef\twocarets{^^}}


% For generating index entries with weird characters, we need to deactivate
% them: { } blank \  and substitute [ ] ! for { } \ .  \recat does this.
% It should be enclosed in a group (which must end in `]').
\def\recat{%
   \aftergroup\ignorespaces
   \catcode `\! = 0 \catcode `[ = 1 \catcode `] = 2
   \catcode `\  = \other \deactivate
}



% Macros for the front matter.
%
% Space at the top of the frontmatter pages.
% 
\def\sinkage{\vglue 7pc \relax}

% And at the top of the backmatter pages.
% 
\def\backsinkage{\vglue 2pc \relax}

% \frontchapter doesn't care if we're on an even page or an odd page.
%
\def\frontchapter#1 \par{%
   \def\chaptername{#1}%
   \leftline{%
      \chapterfonts
      \chaprule
      \kern 6pt
      \vtop{%
         \def\linebreak{\hfil\break}%
         \noindent \chaptername}%
   }%
   \vskip 4pc
   \noheadlinetrue
   % Use chaptername as first A-head (or only one)
   \mark{\chaptername}%
   \noheadlinetrue
   \noindent \ignorespaces
}


% We are called from inside a group, so we can redefine the \toc... macros.
% 
\def\shortcontents{{%
   \firsttoctrue
   \backfalse
   \shorttocfonts
   \let\tocchapterentry = \shorttocchapter
   \let\tocsectionentry = \gobblethree
   \let\tocsubsectionentry = \gobblethree
   \halign{\hfil\strut##&\strut ##\hfil\cr
      \readtocfile
   \crcr}}%
   \pagebreak
   \global\backfalse
}

% #1 is the chapter name, #2 the chapter number, #3 the page number.
% 
\def\shorttocchapter#1#2#3{%
   \ifback\else#2\quad $\backslash$\quad\fi&#1\qquad 
   \raise3pt\hbox{\vrule height2pt width4pt depth2pt}$\,\,$#3\cr
}

% Yes, we read the entire contents (several pages) as one alignment.
% 
\def\contents{{%
   \firsttoctrue
   \backfalse
   \tocfonts
   \interlinepenalty = 100
   \halign{\hfil\strut##&\strut ##\hfil\cr
      \readtocfile
   \crcr}}%
   \pagebreak
   % We want to end the contents on a recto page, even if it's blank
   \ifodd\pageno\pagebreak\fi % leaves us on an even page.
   \global\backfalse
}

\newif\iffirsttoc

\def\tocchapterentry#1#2#3{%
   \iffirsttoc
      \global\firsttocfalse
   \else
      \noalign{\penalty-1000 \bigskip\smallskip}%
   \fi
   %
   \ifback\else\bf#2\quad $\backslash$\quad\fi
   &\bf#1\qquad\raise3pt\hbox{\vrule height2pt width4pt depth2pt}%
          $\,\,$#3\cr
   \noalign{\nobreak\vskip2pt}%
}

\def\tocsectionentry#1#2#3{%
   \noalign{\penalty-500 \vskip\medsmallskipamount}%
   &\it #1\quad \openbox$\,\,$\rm #3\cr
}

\def\tocsubsectionentry#1#2#3{%
   &\qquad #1\quad $\cdot\,$#3\cr
}

\def\openbox{\ht0 = 1.75pt \dp0 = 1.75pt \wd0 = 3.5pt
   \raise 2.75pt \makeblankbox{.2pt}{.2pt}%
}

\newif\ifback
% \ifback is true when we're doing the table of contents and are about
% to do the back matter.  It is also true just before we do the back matter
% chapters (really, only the index).
% 
\def\backmatter{\write\tocfile{\noexpand\setback}\backtrue}
\def\setback{\noalign{\bigskip\global\backtrue}}



% Macros for the examples chapter.
%
% \doexamples is called with the name of the examples file
% Each example is ended by ::: (including the last one)
% A line starting with ~ is executed in the output (without the ~)
% but dropped from the input.
% 
% Within the input, ! is an escape character, but {} are not recognized.
% This provides a limited control sequence capability, which is sufficient
% for delimited macros and therefore for cross-references (see \xrefdelim).
% !! stands for !.
% 
\def\endmark{:::}

\newif\ifnotatend  \newif\ifnotatendfile \newif\iftildeline
\newread\exfileA  \newread\exfileB  \newwrite\exfileC
\newcount\examplenumber

\def\doexamples#1{%
   % Here we assume that two read-only openings of the same file are OK.
   \immediate\openin\exfileA = #1
   \immediate\openin\exfileB = #1
   \loop
      \advance\examplenumber by 1
      \reader
      \ifx\holder\empty \notatendfilefalse \else \notatendfiletrue \fi
   \ifnotatendfile
      \dooneexample
   \repeat
}


% We want control sequences to be executed as the input of each example
% is formatted, but we don't want to execute them for the output of each
% example until we generate that output with an \input command.
% Therefore, we treat ! differently for \holder, which produces example
% input, and \holderA, which produces example output.
%
% We can't say \global\immediate\read, but \immediate is implied with \read.
% 
\def\reader{{\deactivate
   \catcode`\! = \other   % To execute control sequences on \input.
   \catcode`\^^M = 9     \global\read\exfileA to \holder
   %
   \catcode`\! = 0        % To execute control sequences right away.
   \obeyspaces \global\read\exfileB to \holderA
   }%
}

\def\dooneexample{{%
   % We want to mention \! in one of the examples:
   \edef\examplenum{\numbername\examplenumber}%

   \immediate\openout\exfileC = \tempfile

   \catcode`\| = \other   % No literal code in these examples.
   \chardef\! = `\! % !! means a literal ! character.


   % Collect the input page, as it is to be printed, in a box
   % At the same time, write out each line to \exfileC
   % We make the box 0pt tall to avoid problems with overfull pages.
   \setbox\xmpinput = \vbox to 0pt{%
      %
      \baselineskip = \codebaselineskip
      \loop
         \ifx\endmark\holder \notatendfalse \else\notatendtrue \fi
         \ifnotatend
            \expandafter\tildecheck\holder \empty \marker
               \iftildeline\else
               \leftline{\tt\frenchspacing \holderA \thinspace}%
               \immediate\write\exfileC{\holder}%
            \fi
            \reader
         \repeat
      \vss % reduce height to 0pt
      }% end \vtop

   \immediate\closeout\exfileC

   {%
      \maxdepth = \maxdimen % allow long input
      \vfill\eject
      \catcode`\! = 0
      \restoreplainTeX
      {%
        \let\eject = \relax \input\tempfile
        % Every example ends with \bye, but \bye is disabled in the main text.
        \vfill\par\penalty-10000
        \global\footline = {\hfil}%
      }%
      \box\xmpinput
   }%
}}

{
   \catcode `\~ = \other % So the \ifx works.
   \gdef\tildecheck#1#2\marker{%
      \ifx #1~%
         \immediate\write\exfileC {#2}\tildelinetrue
      \else
         \tildelinefalse
      \fi
   }
}

% This definition is more or less repeated verbatim in the first example
% in xmptext.tex.
% 
\def\xmpheader #1/#2{%
   {\exampletitlefonts \leftline{Example #1:\quad \bi#2}}%
   \vglue .5\baselineskip
   \count255 = \pageno
   \xdef\examplepage{\number\count255}%
   \markinfo{Example #1: #2}
   \ifrewritetocfile
      \write\tocfile{\string\tocsectionentry{#2}{}{\examplepage}}%
   \fi
}
% Let's number examples automatically; it makes it easier to move them
% around and add new ones.

\def\xmpnum{\number\examplenumber}

\newbox\xmpinput


% \negthin lets us put `\!' in examples.

\def\negthin{\ifmmode \mskip-\thinmuskip \else \char`\\ \char`\! \fi}

\def\xmpheaddef{see \xref{xmphead}}

\def\restoreplainTeX{%
   % Restore plain TeX's parameters (except for \hsize and \hoffset).
   \parindent = 20pt
   \parskip = 0pt plus 1pt
   \parfillskip = 0pt plus 1fil
   \hfuzz = 0.1pt
   \hbadness = 1000
   \abovedisplayskip=12pt plus 3pt minus 9pt
   \abovedisplayshortskip=0pt plus 3pt
   \belowdisplayskip=12pt plus 3pt minus 9pt
   \belowdisplayshortskip=7pt plus 3pt minus 4pt
   \everymath = {}%
   \everydisplay = {}%
   \centereddisplays
   \let\vfootnote = \@plainvfootnote
   \let\footnote = \@plainfootnote
   \let\tenrm = \oldtenrm
   \textfont0 = \tenrm
   \rm
   \ignorespaces
}%



% Macros for the concepts chapter.
% 
% 
% Start off the chapter.
% 
\def\beginconcepts{\openout\conceptfile = \jobname.ccs }
\def\endconcepts{\closeout\conceptfile}

\newwrite\conceptfile

% \concept produces a concept heading and also generates a crossreference
% suitable for the mini-index.  It even works for concepts with several words
% or containing control sequences like `\ascii'.
%
\def\concept#1 \par{%
   \par
   %k \cmdbreak
   \penalty\conceptpenalty\vskip\aboveconceptskip
   %k \vskip 0pt plus 1pt % allow a little more stretch
   \noindent
   % generate the index entry
   \ifconceptindex \else \global\indextoks = {\idxref{#1}}\fi
   \conceptindexfalse
   \pix\bix\the\indextoks
   %
   {\bt \let\it=\bti \unskip\null #1.\hskip1em plus.2em minus.2em }%
   \markinfo{#1}%
   \xrdef{#1}%
   \write\conceptfile{\string\doconcept{#1}{\number\pageno}}%
   \beginit{CONCEPT}%
   \nobreak
   \ignorespaces
}

\def\endconcept{%
   \par % always go to vertical mode here
   \eix\the\indextoks
   \endit{CONCEPT}%
   \ignorespaces
}

\def\doconcept#1#2{\hbox{#1\quad #2}}

% Sometimes we want to index a concept under some other name than the
% concept name, e.g., indexing `delimiter' as `delimiters'.  The
% \conceptindex macro lets us do this.
%
\newif\ifconceptindex
\newtoks\indextoks
\def\conceptindex#1{%
   \conceptindextrue
   \global\indextoks = {\idxref{#1}}%
   \ignorespaces
}


% Commands for cross-referencing within the concepts chapter.
% Each refterm has the form {a} or {a:b}, where b is the term to
% actually reference (e.g., \refterm{\PlainTeX:\plainTeX}).
% 
\def\refterm#1{%
   \reftermA #1:\endmark  % Parse the stuff.
   \expandafter\minrefsdelim\termtoref\endmark
   \relax % Cancel the \ignorespaces.
}%
\def\reftermA#1:{\reftermfirst{#1}\futurelet\next\reftermB}
\def\reftermB#1\endmark{\ifx\endmark \next \else \reftermsecond#1\fi}

\def\reftermfirst#1{#1\def\termtoref{#1}}
\def\reftermsecond#1:{\def\termtoref{#1}}%

% The defining sentence for a concept.
%
\def\defterm#1{{\it #1\/}}


% This macro prints the single page that will go on the back cover.
% 
\def\printconceptpage{%
   % Make sure this is considered an odd page.
   \ifodd\pageno\else\blankpage\fi
   \noheadlinetrue
   \advance\hsize by 2pc
   \vglue2pc % Plus a \topskip of 2pc.
   {\sectionfonts \leftline{List of concepts}}%
   \vskip\belowsectionskip
   {\conceptpagefonts
      \parindent=0pt
      \makecolumns 94/3:
      \input \jobname.ccs
      \vfil
      % Put the `logo' at the bottom of the page.
      \rightline{\thisbook}%
   }%
   \eject
}



% Macros for the commands chapters.
%
% \ifcommands is true when we're within \begindescriptions ...

\newif\ifcommands


% \begindescriptions should be called to start the actual control sequences.
%
\outer\def\begindescriptions{\beginit{DESCRIPTIONS}%
   % The following definitions are local to this chapter.
   % 
   \let\example = \commandexample
   \let\endexample = \endcommandexample
   \interlinepenalty = 50
   %
   \commandstrue
   \ignorespaces
}

% The \endgroup that \enddescriptions does must come after the page
% break, so the last page of descriptions will get a mini-index.
% 
\def\enddescriptions{%
   \vskip -\lastskip % undo the skip created by \enddesc
   \endit{DESCRIPTIONS}%
   \ignorespaces
}


% Begin or end the description of a control sequence or group thereof.
%
\def\begindesc{%
   \par % force vertical mode
   \saveskip = \lastskip % will be 0 if no skip
   \ifheading  % Did we just have \section or \subsection?
      \nobreak
   \else
      \cmdbreak
   \fi
   \combineskips\abovedescriptionskip
   \headingfalse
   \beginit{DESCRIPTION}%
   \beginit{COMMANDS}%
   % Each command name is set as a paragraph (for reasons I don't
   % remember, \leftline doesn't work because of the way the manuscript
   % was typed), and so \clubpenalty will be the penalty at the
   % interline glue (see p.96).
   \clubpenalty = \intercmdnamepenalty
   \parfillskip = 0pt plus 1fil
   \ignorespaces
}

\def\enddesc{%
   \nobreak % if we need a break, we'll get it from the next group opener
   \vskip\belowdescriptionskip
   \endit{DESCRIPTION}%
   \ignorespaces
}

% Begin the explanation of a control sequence.  Don't break at the
% space above the explanation, or the interline glue before the first line.
%
\def\explain{%
   \par
   \endit{COMMANDS}%
   \nobreak \vskip\explainskip
   \interlinepenalty = 50
   \nobreak \noindent
   \ignorespaces
}

% Here is how \example looks in the text:
% \example
%   ...
% |
% \produces
%   ...
% \endexample
%
% repeated an indefinite number of times.
% 
% We want to set the code of an example in a box so as to prevent it from
% being broken across pages.  By using \vtop we assure that the code is the
% right distance from the `Example:' line.  In order to keep the `produces:'
% the right distance from the last code line, we save the depth of that code
% line and then fool TeX into thinking that the \vtop has that depth by
% assigning it to \prevdepth.  If we didn't do this, the last line of the code
% would be too close to the `produces:' (as indeed it was in earlier versions
% of the book.
%
\newdimen\savedepth

{\makeactive|
\gdef\commandexample{% a.k.a. \example, inside \begindescriptions.
   \cmdbreak\vskip\exampleskip
   \leftline{\it Example:}%
   \nobreak % At the interline glue.
   \beginit{EXAMPLE}%
   \parfillskip = 0pt plus 1fil
   \hbox\bgroup\hskip\parindent\vtop\bgroup
      \begincs
      \let | = \endcode
      \advance\hsize by -\parindent
      \parindent = 0pt
      \bgroup\obeywhitespace
}}%

\def\endcode{%
   \egroup % end \obeywhitespace group
   \par\global\savedepth=\prevdepth
   \egroup % end inner \vbox
   \egroup % end outer \hbox
   \prevdepth = \savedepth
   \ignorespaces
}

% \dproduces should be used when the following material is a math
% display.
% 
\newif\ifexampledisplay
\def\dproduces{\global\exampledisplaytrue \produces}

\newif\ifproduces

% \produces puts its material into a vbox so it won't be broken.
% The material starts in VERTICAL MODE!  It uses the plainTeX conventions
% except that \parindent is 0pt.

\def\produces{%
   \producestrue
   \ifodd\pageno \par \nobreak \else \cmdbreak\fi
   \vskip\tinyskipamount
   \noindent {\it produces\ifexamplelog\ in the log\examplelogfalse\fi :}%
   \vadjust{\nobreak}% At the interline glue.
   \ifexampledisplay
      \centereddisplays
   \else
      \par\nobreak
      \advance\hsize by -\parindent
      \savedepth = \prevdepth
      \nointerlineskip
      \hbox\bgroup\hskip\normalindent
         \vtop\bgroup \restoreplainTeX \parindent = 0pt
         \prevdepth = \savedepth
   \fi
}%

% we need another ``produces'' form for when a command puts things in
% the log. In this case, the produces text also ends with a |.
%
\newif\ifexamplelog
{\makeactive|
\gdef\logproduces{\examplelogtrue\produces
   \begincs
   \def |{\endcode\producesfalse}%
   % Every line is set as a paragraph, so we get one \parindent for free.
   % But we also did \advance\leftskip in \produces, so now we have two.
   % We only want one.
   \advance\leftskip by -\parindent
   \bgroup\obeywhitespace
}}%

\def\nextexample{\endexample\interexampleskip\example}

\def\endcommandexample{%
   \par % force vertical mode, set previous paragraph
   \ifproduces \ifexampledisplay \global\exampledisplayfalse \else
      \global\savedepth = \prevdepth
      \egroup % Matches the \vtop in either the \produces or the \example.
      \egroup % Matches the \hbox in \producesbox.
      \global\producesfalse
      \par
      \prevdepth = \savedepth
   \fi\fi
   \endit{EXAMPLE}%
   \ignorespaces
}

\def\see{%
   \ifodd\pageno\nobreak\fi % don't put at the top of a verso page
   \vskip -\lastskip % should be \belowdescriptionskip
   \bigskip
   \noindent
    {\tenbi \spaceskip = 3.33pt plus 2pt minus 1.1pt
     \parfillskip = 0pt plus 1fil
     See also: %k \hskip 1em plus .5em minus .25em
    }%
    \ignorespaces
}%


\newif\ifxref \xreftrue

% \aux acts as a prefix to a \cts command, specifying that a
% cross-reference should not be generated.
% 
\def\aux{\xreffalse}

% So does \easy, which prints a hand, pointing at the control sequence.
% (The hand font doesn't define an em.)
% 
\newif\ifeasy
\let\easy = \easytrue 
\def\testeasy{\ifeasy\llap{\hand\ \kern 6pt}\easyfalse\fi}

% \cts typesets the beginning of a control sequence description, and
% generates an index entry and cross-reference definition for it.  The
% control sequence name must be delimited by a blank, since there may be
% parameters that follow.  The control sequence name can contain special
% characters; they are deactivated.  The initial \ must be omitted.
% 
\def\cts{\begingroup \deactivate \ctsA}
\def\ctsA#1 {\endgroup \ctsB{#1}}
\def\ctsB#1#2{%
   \ctsbasic{\\#1}{#2}%
   \ifxref \ctsxrdef{#1}\else \xreftrue \fi
   \pix\ctsidxref{#1}%
}

% \ctsx is like \cts, but separates the control sequence name and the
% text by more space. (`x' for `extra')
% 
\def\ctsx{\begingroup \deactivate \ctsxA}
\def\ctsxA#1 {\endgroup \ctsxB{#1}}
\def\ctsxB#1#2{%
   \ctsbasic{\\#1}{\quad #2}%
   \ifxref \ctsxrdef{#1}\else \xreftrue \fi
   \pix\ctsidxref{#1}%
}


% \ctscol is like \cts, but doesn't start a new paragraph.  It's used in
% in columns of cs's and their explanations.
%
\def\ctscol#1 #2{%
   {\bt \\#1}\quad #2%
   \ifxref \ctsxrdef{#1}\else \xreftrue \fi
   \pix\ctsidxref{#1}%
}

% \ctsbasic does the actual printing of a cs name.  It's needed on its
% own for `\ '.  It does not generate any index or cross-reference
% entries.  #1 is the command name, #2 some (possibly empty) text to go
% next to it.
% 
\def\ctsbasic#1#2{%
   \par
   \nobreak % At the \parskip glue the \noindent will produce.
   \noindent\testeasy {{\bt #1}\space #2}%
}

% \ctsxrdef generates a control sequence cross-reference definition.
% For example, `\ctsxrdef{@star}' generates a cross-reference definition
% for `\@star'.
% 
\def\ctsxrdef#1{\expandafter\xrdef\csname#1\endcsname}

% \ctsact prints an active character #1 and generates an index entry
% for it.  #1 is blank-delimited.  \ctsact does not generate a
% cross-reference definition.
% 
\def\ctsact{\begingroup \deactivate \ctsactA}
\def\ctsactA#1 {\endgroup
   \ctsbasic{#1}{}%
   \pix\ttidxref{#1}}

% \ctspecial prints a control sequence #1 and generates an index
% entry for it.  #1 is blank-delimited.  \ctspecial does not
% automatically generate a cross-reference definition, and so it's used
% for things like \newbox and \%.
%
\def\ctspecial{\begingroup \deactivate \ctspecialA}
\def\ctspecialA#1 {\endgroup
   \ctsbasic{\\#1}{}%
   \pix\ctsidxref{#1}%
}

% \ctspecialx is like \ctspecial, but leaves more space after its
% argument.  We want ` and ' to come from cmtt, instead of Optima, so we
% call \mapquotes before reading the argument.  This only affects the \`
% and \' descriptions.
% 
\def\ctspecialx{\begingroup \deactivate \mapquotes \ctspecialxA}
\def\ctspecialxA#1 {\endgroup
   \ctsbasic{\\#1}{}\quad
   \pix\ctsidxref{#1}%
}

% \ctsdisplay has a blank-delimited argument consisting of a control
% sequence such as alpha.  It produces $\alpha$ followed by \alpha.
% 
\def\ctsdisplay#1 {\basicdisplay {$\csname #1\endcsname$}{\\#1}%
   \ifxref\ctsxrdef{#1}\else\xreftrue\fi   \pix\ctsidxref {#1}}

% \ctsdoubledisplay has a blank-delimited argument consisting of a
% control sequence such as bigvee.  It produces $\bigvee$ and
% $\big\bigvee$ followed by \bigvee.
% 
\def\ctsdoubledisplay#1 {
   {%
      \symbolspace = 42pt
      \basicdisplay{$\csname #1\endcsname\quad
                     \displaystyle\csname #1\endcsname$\ddstrut}%
                   {\\#1}%
   }%
   \ifxref\ctsxrdef{#1}\else\xreftrue\fi
   \pix\ctsidxref{#1}%
}
\def\ddstrut{\vrule width0pt height15pt depth11pt}

% \ctsydisplay displays a control symbol.  #1 is a single character,
% which may be active.  #2 is the cross-reference label,
% blank-delimited.
% 
\def\ctsydisplay{\begingroup \deactivate\catcode`\|=\other \ctsydisplayA}
\def\ctsydisplayA#1 #2 {\endgroup
   \basicdisplay{$\csname\string#1\endcsname$}{\\#1}%
   \ifxref \ctsxrdef{#2}\else \xreftrue \fi
   \pix\ctsidxref{#1}%
}

% \actdisplay displays an active character. #1 is the character, and
% #2 is the cross-reference label, blank-delimited.
% 
\def\actdisplay{\begingroup\catcode `\|=\other\actdisplayA}
\def\actdisplayA#1 #2 {\endgroup
   \basicdisplay{$#1$}{\string#1}%
   \ifxref \xrdef{#2}\else \xreftrue \fi
   \pix\ttidxref{#1}%
}

% \basicdisplay does the actual typesetting of a control sequence name.
% for inside displays.
% 
\def\basicdisplay#1#2{\testeasy\hbox to \symbolspace{#1\hfil}{\bt #2}}

% Printing parameter and table entry headings.
%
\def\param#1{\printparam{#1}{parameter}}
\def\tblentry#1{\printparam{#1}{table entry}}
\def\printparam#1#2{\hskip1.5em [\kern3pt \<#1> #2\kern2pt]}

% Required braces.
%
\def\rqbraces#1{\{\hskip2pt#1\hskip2pt\}}

% Printing rulers.
% 
\def\1{\vrule height 0pt depth 2pt}
\def\2{\vrule height 0pt depth 4pt}
\def\3{\vrule height 0pt depth 6pt}
\def\4{\vrule height 0pt depth 8pt}
\def\ruler#1#2#3{{$\vcenter{\hrule\hbox{\4#1}}\,\,\rm#2\,{#3}$}}
\def\doruler{\par \noindent\ruler}
\def\tick#1{\hbox to .125in{\hfil#1}}
\def\8{\tick\1\tick\2\tick\1\tick\3\tick\1\tick\2\tick\1\tick\4}

% Macros for the capsule summary chapter.
% 
\def\begincapsum{\beginit{CAPSULE SUMMARY}%
   \let\bt = \tentt
   \bigskip
}

\def\endcapsum{\endit{CAPSULE SUMMARY}}

\newbox\@primitivebox \setbox\@primitivebox = \hbox{\tt *}
\newif\ifcs

\def\capline{\begingroup \deactivate\catcode `\| = \other \caplineA}
\def\caplineA#1 {\endgroup
   \begingroup
      \catcode `@ = \letter % for constructing labels
      \caplineB{#1}%
}

% Parameters of \caplineB:
%   #1 name of control sequence
%   #2 description
%   #3 * or empty
%   #4 xref or xref1:xref2 or empty

\def\caplineB#1#2#3#4{%
   \ifempty {#4}\temptrue\else\tempfalse\fi
   % \iftemp needed to avoid \if ... \else ... \fi nesting problems
   \ifcs
      \toks0 = {\caplineout{\\#1}{#2}{#3}}%
      \iftemp
         \toks1 = \expandafter{\csname #1\endcsname}%
      \else
         \toks1 = {#4}%
      \fi
      \edef\nextaction{\the\toks0 {\the\toks1}}%
      \nextaction
      \ctsidxref {#1}%
   \else
      % The \space makes one-character entries line up nicely.
      \caplineout{\space #1}{#2}{#3}{#4}%
      \ttidxref {#1}%
   \fi
   \endgroup
}

\newif\iftemp


% In a few cases we have two cross-references for a single control
% sequence.
%
\newif\ifcstwo

\def\capac{\cstwofalse\csfalse\capline}
\def\capactwo{\cstwotrue\csfalse\capline}
\def\capcs{\cstwofalse\cstrue\capline}
\def\capcstwo{\cstwotrue\cstrue\capline}

% \caplineout produces an output line (or several lines) for the capsule
% summary.  #1 is the command text, #2 is the description, #3 is either * or
% empty, and #4 is the cross-reference label.
% 
\def\caplineout#1#2#3#4{%
   \setbox0 = \ifempty {#3}\box\voidb@x \else \copy\@primitivebox\fi
   \vskip\intercapsuleskip
   % If we use \vbox here, a multi-line summary at the top of a page
   % will cause \topskip to disappear.
   % 
   \vtop{\noindent \hangindent = \capsulehangindent
      \spaceskip = 3.33pt plus 2pt minus 1.5pt
      \rightskip = 0pt plus 4em % a little more stretch
      \parfillskip = 0pt plus 1fil
      \llap{\box0}{\bt #1}% Bold typewriter for the cs name.
         \quad \hskip 0pt plus 1pt minus 1pt
         #2\unskip\ 
         (\ifcstwo \tworefs #4:\else \xref{#4}\fi)%
   }%
   \par
}

\def\tworefs#1:#2:{\xref{#1}, \xref{#2}}



% Macros for printing the index.
% 
% Set up to print it.
% 
\def\beginindex{%
   \doublecolumns
   \beginit{THE INDEX}
      \markinfo{\chaptername}%
      \indexfonts
      \parindent = 0pt
      \def\pp##1{{\it ##1}} % Principal entry.
      \def\c{,\thinspace\allowbreak}%
      \def\ic{,\quad}
      \def\see##1{.\quad{\it See} ##1 }
      \def\seealso##1{\hfil\break{\it See also} ##1 }
      \let\r = \romannumeral
      
      \raggedright
}

\def\endindex{\endit{THE INDEX}\singlecolumn}


% #1 is the level of this index entry minus 1 (i.e., 0 for a main
% entry), #2 is the index term, #3 is the kind of term
% (T for ttfont, C for control sequence, N for normal), and
% #4 is the list of pages.  The page list can have \pp (principal
% entry)in it, and each page is separated by \c.
% 
\def\indexentry#1#2#3#4{%
   \beginit{INDEX ENTRY}%
      \leftskip = #1\indexpageindent
      \par
      \leavevmode
      \hangindent = \indexlevelindent
      \ifx #3T%
         {\tt #2}% Typewriter.
      \else \ifx #3C%
         {\tt \llap{\\}#2}% Control sequence.
      \else
      % in normal entries, \b and \e enclose a group. ({ and } don't work.)
         {\let \b = \bgroup \let \e = \egroup #2}%
      \fi\fi
      #4% The list of pages.
      \par
   \endit{INDEX ENTRY}%
}

% Nah, let's forget printing the initial.
% 
\def\indexgroup#1{%
  \bigskip
}



% Code formatting.
% 
% 
% Turn off normally special characters.
% 
\def\deactivate{%
   \catcode`\\ = \other   \catcode`\{ = \other   \catcode`\} = \other
   \catcode`\$ = \other   \catcode`\& = \other   \catcode`\# = \other
   \catcode`\% = \other   \catcode`\~ = \other   \catcode`\^ = \other
   \catcode`\_ = \other
}

% It is convenient to have |...| mean print the ... verbatim, except for !.
% (But | should just be a vertical bar in math mode.)  This should be
% used only for inline code; returns inside |...| become spaces.
% 
\catcode`\| = \active
\def|{%
   \ifmmode
      \vert
   \else
      \begingroup
         \obeyspaces
         \begincs
         \let| = \endgroup
   \fi
}

% \csdisplay is similar, but it inserts glue before and after.
% It also is ended by |, so we have to redefine that.
% 
\def\csdisplay{%
   \par
   \nobreak % don't break above displays
   \vskip\abovedisplayskip
   \begingroup
      \interlinepenalty = 10000
      \obeywhitespace
      \begincs
      \def|{\endgroup\vskip\belowdisplayskip \noindent\ignorespaces}%
}

% \begincs does the setup for verbatim printing.  It does not confine
% its effects to a group.
% 
\def\begincs{%
   \hfuzz = \codefuzz
   \parfillskip = 0pt plus 1fil
   \parskip = 0pt % don't stretch interparagraph space within code displays
   \catcode`\! = 0
   \let\! = \exclam
   \let\| = \verticalbar
   \let\$ = $%
   \let\. = \empty  % Use !. to end a control sequence to be executed.
   \def\-{\discretionary{-}{}{}}% but allow explicit discretionary hyphens
   \tt \deactivate
}


\chardef\exclam = `\!
\chardef\verticalbar = `\|

% In math mode we want vertical bars and exclamation points to be
% regular characters again.
% 
\everymath = {\setmathchars}
\everydisplay = {\setmathchars}
\leftdisplays

\def\setmathchars{%
   \catcode`\| = \other  \catcode`\! = \other
   \let\{ = \lbrace  \let\} = \rbrace
}




% Some miscellanous macros.
% 
\def\anatomy{anatomy of \TeX}
\def\ascii{{\ninerm ASCII}}
\def\asciichar#1{$\langle \rm #1\rangle$}
\def\bblfile{{\tt .bbl} file}
\def\bibfile{{\tt .bib} file}
\def\bstfile{{\tt .bst} file}
\def\didotpt{did\^ot point}
\def\dvifile{{\tt .dvi} file}
\def\em{\thinspace {\rm em}}
\def\emph#1{{\it #1}\itcorr}  % Emphasize.
\def\ftp{{\tt ftp}}
\def\gffile{{\tt .gf} file}
\def\hand{{\handfont \char"2B}}
\def\ifatest{{\tt \\if} test}
\chardef\inches = "7D
\def\knuth#1{#1 of \texbook}
\let\Metafont = \MF
\def\Mperiod.{$M$\kern-1.6pt.}
\def\Mprimecomma,{$M'$\kern-3.5pt,}
\def\Mprimeperiod.{$M'$\kern-2.5pt.}
\def\mud{\thinspace {\rm mu}} % can't use \mu; it'a a Greek letter!
\def\newTeX{new \TeX}
\def\p{p.\thinspace}
\def\pkfile{{\tt .pk} file}
\def\plainTeX{plain \TeX}
\def\PlainTeX{Plain \TeX}
\def\pp{p\p}
\def\pt{\thinspace {\rm pt}}
\def\pxlfile{{\tt .pxl} file}
\def\tequiv{\unskip $\>\equiv\>$} % equivalence in text
\def\texbook{{\sl The \TeX book}\itcorr}
\let\tex@ = \TeX
\def\TeX{\tex@\null}
\def\TeXMeX{\TeX\ M\kern-.11em\lower .5ex\hbox{E}\kern-.125em X\null}%
\def\tfmfile{{\tt .tfm} file}
\def\thisbook{{\sl \TeX\ for the Impatient\/}}
\let\ths = \thinspace
\def\tminus{\unskip\allowbreak $\>-\>$\allowbreak} % minus in text
\def\tplus{\unskip\allowbreak $\>+\>$\allowbreak} % plus in text
\def\TUG{\TeX{} Users Group}
\def\Vcomma,{$V$\kern-2pt,}
\def\visiblespace{{\tentt \char'040}}
\def\Vperiod.{$V$\kern-2pt.}
\let\vs=\visiblespace
\def\xrefpg#1{page~\xrefn{#1}}

% \tighten attempts to shorten the number of lines occupied by a paragraph.
\def\tighten{\looseness=-1
   \spaceskip = .9\fontdimen2\font plus \fontdimen3\font
      minus 1.1\fontdimen4\font
}

% \itcorr can be used at the end of a macro that puts its argument in
% italics in order to produce an italic correction just when it's needed.
% It won't look inside a following macro call, however.

\def\itcorr{\futurelet\next\itcorrA}
\def\itcorrA{\ifx.\next\else\ifx,\next\else\/\fi\fi}


% Arrange N items in three columns.
% A right brace is needed at the end of the list to match the \bgroup.
% 
\def\threecolumns{\nobreak\vskip\abovedisplayskip\dothreecolumns}

\def\dothreecolumns#1 {\bgroup
   \parindent = 0pt
   \makecolumns #1/3:
}

% We don't want to make < an active character because then it cannot be used
% in \ifnum tests.  So, \<foo> denotes a nonterminal `foo'.
% 
\def\<#1>{$\langle${\rm\it \kern-.2pt #1\kern.65pt}$\rangle$}

\let\beginit = \environment
\let\endit = \endenvironment

\def\eatpar#1\par{}

% \needspace breaks out the page if there's less than #1 left on it.

\def\needspace#1{%
   \saveskip = \lastskip
   \par % force vertical mode
   \vfil
   \penalty 1000
   \vskip #1
   \penalty9999
   \par % exercise the page builder
   \vskip -#1 plus -1fil
   \vskip -\saveskip \vskip \saveskip % to restore \lastskip
}
   



% Expanded cross-referencing for various parts of the books.
% 

% Sometimes it is clearer to refer to a cross-reference as a control
% sequence.
% 
\def\ctsref{\begingroup \catcode`\@ = \letter \@ctsref}
\def\@ctsref#1{(\xref{#1})\endgroup}

\def\xrefdelim[#1]{page~\xrefn{#1}} % this form doesn't need braces
\def\xrefndelim[#1]{\xrefn{#1}} % this form doesn't need braces

% This command comes at the beginning of chapters, after the \chapter
% command and before the text.  Hence the \par in the template
% and the \noindent
% 
\def\chapterdef#1#2\par{%
   \@writeaux{%
      \string\gdef\expandafter\string
         \csname#1_C\endcsname{\the\chapterno}}%
   \noindent
}

\def\chapternum#1{%
   \def\csn{#1_C}%
   \expandafter\ifx\csname\csn\endcsname \relax
      \expandafter\def\csname\csn\endcsname{`#1'}%
      \ifxrefwarning
         \message{Undefined chapter `#1'.}%
      \fi
   \fi
   \csname\csn\endcsname
}

\def\chapterref#1{Section~\chapternum{#1}}

\def\headcit#1#2{``{\rm #1}'' (\xref{#2})}

\def\conceptcit#1{\headcit{#1}{#1}}

\def\seeconcept#1{(see ``{\rm #1}'', \xref{#1})}




% Special types of pictures.
% 
% Glue pictures:
% 
\newdimen\glueboxwidth
\newdimen\boxdepth  \boxdepth = 3.5pc
\newskip\underlabel  \underlabel= .1\boxdepth % space under `width n'.
\def\squeezeglue{\glueboxwidth = .725\glueboxwidth}

\def\labelledbox#1 #2 #3{\vtop{%
   \hrule
   \hbox{%
      \vrule
      \hbox to #1{\hfil \vbox to #2{\vfil#3\vskip\underlabel}\hfil}%
      \vrule
   }%
   \hrule
}}%

% Make a picture of a box.
% 
\def\picbox#1 {%
   \glueboxwidth = #1pc \squeezeglue
   \vtop{%
      \hbox to \glueboxwidth{\strut \hfil {\it box}\hfil}%
      \labelledbox % Have to have spaces after the arguments.
         {\glueboxwidth}
         {\boxdepth}
         {\halign{\hfil##\hfil\cr width #1\cr}}%
    }%
}

% And of glue.
% 
\def\gluebox#1 #2 #3 #4 {\vtop{%
   \glueboxwidth = #4pc \squeezeglue
   \hbox to \glueboxwidth{\strut \hfil {\it glue}\hfil}%
   \nointerlineskip
   \kern2pt % to move the brace down a bit
   \hbox{$\overbrace{\hbox{\hskip\glueboxwidth}}$}%
   \kern-3pt % The \overbrace puts in 3pt below itself.
   \nointerlineskip
   \vbox to \boxdepth{%
      \hsize = \glueboxwidth
      \vskip 2pt
      \advance\baselineskip by -2pt
      \centerline{\strut size #1}%
      \centerline{stretch #2}%
      \centerline{shrink #3}%
      \centerline{width #4}%
      \vss
   }%
   \kern 1.5pt % I don't know why this is needed.
   \nointerlineskip
   \hbox{$\underbrace{\hbox{\hskip\glueboxwidth}}$}%
}}

\def\gluepicture#1 #2{{\ninerm
   \medskip 
   \vtop{%
      \setbox0 = \hbox{#2}% The glue and box pictures.
      \glueboxwidth = \wd0
      \leftline{\box0}%
      \kern 6pt
      \hbox to \glueboxwidth{\leftarrowfill{ width #1 }\rightarrowfill}%
   }%
   \medskip
}}

% Box pictures.
% 
% Set up a `reference point' and the macro for a labelled height, for use
% in forming pictures of boxes.
% 
\newbox\refpoint

\setbox\refpoint = \vbox to 0pt{%
   \kern-2.6pt
   \hbox to 0pt{\kern-2.2pt $\bullet$\hss}
   \vss
}%
   
\def\labelledheight#1#2{%
\vtop to #1{\offinterlineskip
   \setbox0=\hbox{#2}\skip0=\wd0
   \hbox to \skip0{\hss\tenex\char"78\hss}\kern-4pt
   {\cleaders\hbox to \skip0{\hss\tenex\char"3F\hss}\vfil}%
   \vskip1pt\box0\vskip1pt
   {\cleaders\hbox to \skip0{\hss\tenex\char"3F\hss}\vfil}%
   \kern -6pt\boxmaxdepth 0pt\hbox to \skip0{\hss\tenex\char"79\hss}}}



% Paul's updates -- no longer needed; we have converged.
% 
%\input paulmacs

% Read the cross-reference definitions.
% 
\readauxfile

\catcode`\@ = \other  % Make @ an `other' character again.
\catcode`\^ = \active % Make ^'s do indexing outside of math mode.
