diff options
author | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
commit | e0c6872cf40896c7be36b11dcc744620f10adf1d (patch) | |
tree | 60335e10d2f4354b0674ec22d7b53f0f8abee672 /macros/lamstex/doc/wiz6.tex |
Initial commit
Diffstat (limited to 'macros/lamstex/doc/wiz6.tex')
-rw-r--r-- | macros/lamstex/doc/wiz6.tex | 3196 |
1 files changed, 3196 insertions, 0 deletions
diff --git a/macros/lamstex/doc/wiz6.tex b/macros/lamstex/doc/wiz6.tex new file mode 100644 index 0000000000..f15dd1becf --- /dev/null +++ b/macros/lamstex/doc/wiz6.tex @@ -0,0 +1,3196 @@ +\part Front and\\ Back Matter\label{FBM}\endpart + + +\chapter Front Matter\\(Table of Contents, List of Figures, Tables, etc.) +\label{FRONTMATTER}\endchapter +\runningchapter{Front Matter} + +Now that we've covered all the formatting of the paper proper, we only have +to worry about the formatting of the *.toc* and *.tic* files for the front +matter, and the *.ndx* file for the index. + +As we've seen in section~\Sref{STYF}, the +*\predocstyle* and *\postdocstyle* commands simply *\input* files with +the extension *.stf* and *.stb*, respectively. In the default style, +we say +** +\predocstyle{lamstex} +** +to *\input lamstex.stf*, and +** +\postdostyle{lamstex} +** +to *\input lamstex.stb*. In this chapter we consider the file *lamstex.stf*, +while the next chapter considers *lamstex.stb*. + +As in section~\Sref{GENDEFS}, we will be using double horizontal lines +for code from these subsidiary files. + +\section{{\tt lamstex.stf} preliminaries} The file +*lamstex.stf*, although it is only a +particular example of a front matter style file, nevertheless illustrates all +the main points we have to consider. + +As usual, we begin with +\CC** +\catcode`\@=11 +** +Since we are going to be introducing some *\newdimen*'s, we first +\CC** +\let\alloc@=\alloc@@ +** +(compare page~\ref{NEWALLOC}). + + +\medskip + + In the default style, we will be setting entries like +\bigskip +\line{\qquad\bf +Chapter 1. Introduction\leaders\hbox to10pt{\rm\hfil.\hfil}\hfil + \kern10pt\hbox{\rm3}\qquad} +\bigskip +\noindent +using dot leaders. This, of course, is merely a style decision, and some +modern style designers eschew dot leaders, on the grounds that blank space +will work just as well. I suspect, however, that many such supposedly +aesthetic decisions were really influenced by the difficulty of handling dot +leaders correctly. In any case, the default style uses dot leaders, giving us +the opportunity to address the question of long entries, where we will need +to use something like +\bigskip +\line{\qquad\bf Chapter 1. This chapter has such a long title that it will + be \hfil} +\line{\qquad\bf\setbox0\hbox{Chapter 1.}\hskip10pt\hskip\wd0 + necessary to split it into two parts\leaders\hbox +to10pt{\rm\hfil.\hfil}\hfil\kern10pt \rm3\qquad} +\bigskip + +For the moment, we simply define our leaders, +\CC** +\def\dotleaders{\leaders\hbox to10pt{\rm\hfil.\hfil}\hfil} +** +We also want to define the formatting for page numbers. +The *.toc* and *.tic* files contain lines like +** +\Page {3}{\arabic }{}{} +** +to handle the page number, the numbering style, and possible pre- and +post-page material. The routine *\Page@#1#2#3#4* tells how these will +be combined when typeset: +\CC** +\def\Page@#1#2#3#4{\kern10pt\hbox{\rm#3#2{#1}#4}} +** +Thus, for example, +** +\Page {3}{\roman }{A-}{} +** +will be printed as `A-iii', with at least 10~points of space between the +leaders and the number. + +\section{Setting an entry\label{SETENTRY}} +We begin with a test +** +\widerthanhsize@#1#2#3#4 +** +to determine + whether +the material for an entry is longer than *\hsize*. +In the example given above, *#1* will be the `\hbox{\bf Chapter 1. }' part of +the heading, + *#2* will be the title `{\bf This chapter \dots into two parts}', *#3* will +be the *\dotleaders*, and *#4* will be the suitable `*\Page@...*'. + + Displayed formulas and other +such nonsense aren't allowed in heading levels, but captions, at any rate, +could have more than one paragraph of text; moreover, in the *.toc* file + we might well want +to use *\newline* to force a short line when our entry is so long +that only one or +two of the dot leaders appear. +So we will use a test similar to +the *\widerthanisland@* test of section~\Sref{FMTC}: +\CC** +\long\def\widerthanhsize@#1#2#3#4{% + \test@true + \setbox0=\vbox{\hsize=\maxdimen + \rm\noindent@#1#2#3#4\par\setbox0=\lastbox}% + \ifdim\wd0=0pt + \setbox0=\hbox{\rm#1#2#3#4}% + \ifdim\wd0 > \hsize\else\test@false\fi + \fi} +** +We use *\noindent@* instead of the more complicated *\noindent@@* here +because we will be setting *\everypar{}* while the table of contents is +being made. (Actually, even the *\noindent@* is unnecessary, since we will +also be setting *\parindent=0pt*.) +Instead of *\rm*, other style files +might need to insert something like *\tenpoint* (just +in case the user has, for example, added + *\eightpoint* material at the beginning of the *.toc* file). + + +Then we define the routine *\setentry@#1#2#3#4*, + which sets the entry with parts *#1*, \dots, *#4* properly; when the +entry will have to be set on more than one line, we call the routine +*\longentry@*: +\CC** +\long\def\setentry@#1#2#3#4{% + \widerthanhsize@{#1}{#2}{#3}{#4}% + \iftest@ + \longentry@{#1}{#2}{#3}{#4}% + \else + \hbox to\hsize{\rm\strut#1#2#3#4\strut}% + \fi} +** +Notice that we added the *\strut*'s after the *\rm*; other styles +might have to specify something like *\tenpoint* instead of the *\rm*. + +Because our lines have *\strut*'s, which already make the baselines *12pt* +apart, +it is essential that we have +** +\lineskiplimit=0pt "8USELIMITPROB"8 +** +while we are setting the table of contents, +so that additional *\lineskip* glue isn't inserted between lines +(compare page~\ref{LIMITPROB}). However, instead of making this assignment +now, we will make it later, within the definition of *\maketoc*. + + +For entries that are longer than one line, +the default style uses hanging indentation, so that + lines after the first are indented by 10~points more than +the width of argument *#1*. We will declare a \<dimen\> register +*\thehang@* +for the necessary amount of hanging indentation, which will be determined by +** +\setbox0=\hbox{#1} +\thehang@=\wd0 \advance\thehang@ by 10pt +** + + All lines before the last will be made shorter +than *\hsize*, so that they don't overlap the width of the page number. +The default style leaves an extra 20~points leeway, which we arrange with +** +\setbox0=\hbox{#4} +\advance\hsize by -\wd0 \advance\hsize by -20pt + \hangafter 1 \hangindent=\thehang@ +** +Now the idea is to set a *\vbox* that looks like +\medskip +\line{\qquad\bf Chapter 1. This chapter has such a long title that it will + be necessary\hfil} +\line{\qquad\bf\setbox0\hbox{Chapter 1.}\hskip10pt\hskip\wd0 + to split it into two parts\hfil} +\medskip +\noindent +and then use *\lastbox* to extract the last line, to which we will finally +add the dot leaders and the page number: +** +\long\def\longentry@#1#2#3#4{% + \setbox0=\hbox{#1} \thehang@=\wd0 \advance\thehang@ by 10pt + \setbox0=\hbox{#4} + \setbox0=\vbox{\advance\hsize by -\wd0 + \advance\hsize by -20pt + \hangafter 1 \hangindent=\thehang@ + \rm\noindent@\strut\hbox{#1}#2\vphantom{#3#4}\strut} + . . . +** +We put *#1* inside an *\hbox* so that any glue within it will have only +its natural width, without any + stretch or shrink; this is necessary in order to insure that our hanging +indentation will truly be the width of *#1* plus 10~points. +The *\vphantom{#3#4}* is added so that the height and depth of the +last line of *\box0* won't +change when we add the dot leaders (*#3*) and the page number (*#4*). +As mentioned before, other styles might have to specify something like +*\tenpoint* rather than *\rm*; the *\strut* should come after that, +{\it and also after the\/} *\noindent@* (so that it doesn't start +a paragraph prematurely). + +As with footnotes (section~\Sref{VF}), we will actually want to replace +the first *\strut* with +** +\vbox to\ht\strutbox{} +** +and the last *\strut* with +** +\lower\dp\strutbox\vbox to\dp\strutbox{} +** +The latter combination will appear + more than once, so we adopt an abbreviation: +\CC** +\def\endstrut@{\lower\dp\strutbox\vbox to\dp\strutbox{}} +** + +Although we will have *\lineskiplimit=0pt* when *\longentry@* is +being used, +within our *\vbox* we want to declare +** +\normalbaselines +** +so that the standard value of *\lineskiplimit* is used there. (In the default +style *\normallineskiplimit* happens to be ~*0pt*, so that this is actually +superfluous, but in other styles that is not necessarily the case.) + +Now we start to make a new box, in which we *\unvbox0*: +** +\setbox0=\vbox{\unvbox0 + \setbox0=\lastbox + . . . +** +This makes the inner *\box0* the last line of the +paragraph, a ``short'' line that ends with *\parfillskip* glue, +and then yet another glue, namely *\rightskip*. So we need +** +\unhbox0 \unskip\unskip +** +to get rid of this extra glue, before we + add *#3* and *#4*. + In addition, +the hanging indentation does not insert glue or a kern at the beginning of +this box---instead, it merely shifts it to the right in the vertical list. +So we use +** +\setbox0=\vbox{\unvbox0 + \setbox0=\lastbox + \hbox to\hsize{\kern\thehang@ + \unhbox0 \unskip\unskip#3#4\endstrut@} + } +** + to create the desired final line. +And then we +simply *\unvbox0*: +\CC** +\newdimen\thehang@ +"slip +\long\def\longentry@#1#2#3#4{\setbox0=\hbox{#1}% + \thehang@=\wd0 \advance\thehang@ by 10pt +"2 + \setbox0=\hbox{#4}% +"2 + \setbox0=\vbox{\advance\hsize by -\wd0 + \advance\hsize by -20pt + \normalbaselines + \hangafter1 \hangindent=\thehang@ +"2 + \vskip-\parskip + \rm\noindent@\vbox to\ht\strutbox{}% + \hbox{#1}#2\vphantom{#3#4}\endstrut@}% +"2 + \setbox0=\vbox{\unvbox0 + \setbox0=\lastbox + \hbox to\hsize{\kern\thehang@ + \unhbox0 \unskip\unskip #3#4\endstrut@}% + }% + \unvbox0 } +** +Note that in the last *\setbox0=\vbox* there is no extra glue between the +*\unvbox0* and the *\hbox to\hsize* (compare the footnote on page~\ref{NEXG}); +that is why it is important to have the *\vphantom{#3#4}*, to insure +that the *\hbox to\hsize* has the same height as the *\lastbox* that it is +replacing. + + +\section{Further preliminaries for the table of contents} +The *\maketoc* command is going to *\input* the appropriate *.toc* file, +which will have entries like +\setbox0\hbox{and} +\setbox1\hbox{\<word\>} +\setbox2\hbox{\<formatted heading number\>} +** +\HL {1}{"copy1}{"box2} "8HLILLUS"8 + . . . +\Page ... +** +and/or entries like +\setbox0\hbox{and} +\setbox1\hbox{\<word\>} +\setbox2\hbox{\<formatted heading number\>} +** +\chapter {"copy1}{"box2} + . . . +\Page ... +** +(in which case an extra line like +** +\NameHL 1\chapter +** +should appear at the beginning), and similarly for *\hl*. + +We will therefore be redefining *\HL* and *\hl* so that such lines +print proper lines for the table of contents. +But +a few preliminaries are needed to deal with the + possibility that something like *""B""*, or even +*""\style B""* occurs instead of a \<formatted heading number\>. +First, we want a flag +\CC** +\newif\ifemptynumber@ +** +which will be set true precisely in the case where we have *""""* (in the +paper proper, this happens when *\thelabel@@* is *\empty*). When it comes +time to properly print the argument `*...*' +of *\HL* that represents the heading +number, we will use +** +\Style@...\Style@ +** +so that *\Style@* can use a *\futurelet* to see if `*...*' begins with +a *""* (we use *\Style@* because *\style@* is already used, as part of the +definition of *\style*). +We begin with +\CC** +\def\Style@{\emptynumber@false\futurelet\next\Style@@} +\def\Style@@{\ifx\next""\expandafter\Style@@@ + \else\expandafter\Style@@@@\fi} +** +For *\Style@@@*, when no *""* occurs, we might expect to use +** +\def\Style@@@#1\Style@{#1} +** +Instead, however, we will use +\CC** +\def\Style@@@@#1\Style@{\style{#1}} +** +so that each heading level can temporarily define `*\style*' to produce +whatever sort of formatting for the number that we want. +On the other hand, *\Style@@@* is defined by +\CC** +\def\Style@@@""#1""\Style@{% + \def\next@{#1}\ifx\next@\emtpy + \emptynumber@true\else#1\fi} +** +Thus, in the special case that our original argument is *""""*, +we simply set *\emptynumber@true*; otherwise we + print the argument *#1*. Notice that if this argument happens +to be something like *""\style B""*, the `*B*' will be formatted according +to the manner in which this heading level has temporarily defined +*\style* to operate. + +For setting *\hl1* entries, +we will also declare a new dimension *\digits*, +\CC** +\newdimen\digits "8DIGITS"8 +\setbox0\hbox{0.00} +\digits=\wd0 +** +so that *\digits* is the width of a double-digit number like `1.12' (the +user could reset *\digits* if necessary to accommodate even more digits). + +We also want to define +\CC** +\def\maketoc@W{CONTENTS} +** +so that *\newword\maketoc* can be used to choose a different word. + +\section{Starting the \CS{maketoc} command} +The *\maketoc* command first uses *\checkmainfile@* (page~\ref{CHECKMF}) +to issue an error message if no *\mainfile* command has appeared in the front +matter file, since it will have to *\input \mainfile@.toc*, where +*\mainfile@* has been defined by *\mainfile*. +Then it + starts a new page, +in case something like a Preface precedes it (the default front +matter style file *lamstex.stf* +doesn't have special constructions for Prefaces, etc., but +the *book* style, for example, does). +\footnote{We don't simply put *\checkmainfile@* at the beginning of +our file, since a user might omit the *\mainfile* line when +simply checking that something like a Preface looks right.} +Then we produce a centered bold heading `{\bf CONTENTS}', followed by +some space. + +Now we want to +*\input* the appropriate *.toc* file, which +is when everything interesting will happen. Certain subsidiary definitions +will be needed, so + we will start with +*\begingroup* and add an *\endgroup* after the *\input*, to keep these all +local. + +Any + *\label* or *\pagelabel* in a heading level or a +caption will have been written + to the *.toc* or *.tic* file (there's no practical +way to eliminate them), but they play no further role, and +we simply want to ignore them. The same is true of any *\Reset* or +*\Offset*. So after the *\begingroup* we want to add +** +\noset@ \unlabel@ +** +(section~\Sref{relax} and ~\Sref{relax2}). +Any *\nopunct* or *\nospace* or *\overlong* in the main file +will also show up in the *.tic* file. Some styles might want to make +use of these (presumably having them set certain flags), but in the default +front matter style *lamstex.stf*, we simply want to +** +\let\nopunct=\relax \let\nospace=\relax +\let\overlong=\relax +** +We also add +** +\everypar={}\parindent=0pt +** +for good measure. + +Furthermore, as mentioned previously (page~\ref{USELIMITPROB}), it is +essential that we + set +*\lineskiplimit=0pt*. +So our definition of *\maketoc* will start +** +\def\maketoc{\checkmainfile@ + \par\vfill\break + \noset@ \unlabel@ + \let\nopunct=\relax \let\nospace=\relax + \let\overlong=\relax + \everypar={}\parindent=0pt + \lineskiplimit=0pt +** + + +\section{Redefining \CS{HL} and \CS{hl}} +Next we have to redefine *\HL* and *\hl* so that *\HL* and *\hl* entries +will be properly set for the table of contents. + +To redefine *\HL*, recall (page~\ref{HLILLUS}) +that it will occur in a combination like +\setbox0\hbox{\<heading level\>} +\setbox1\hbox{\<formatted heading number\>} +\setbox3\hbox{\<heading word\>} +\setbox2\hbox{\<The heading\>} +** +\HL {"box0}{"box3}{"box1} + "box2 +\Page{...}{...}{...}{...} +** +so that we need a definition like +** +\def\HL#1#2#3#4\Page#5#6#7#8{ . . . "87ARGS"8 +** +(except that *#1* will be *##1*, etc., since this entire definition will be +made within the definition of *\maketoc*). + +The definition should always begin +** +\def\HL#1#2#3#4\Page#5#6#7#8{\def\HLlevel@{#1} + . . . +** +so that subsequent constructions can know which heading level is being +considered. For the default front matter style we will be using +** +\def\HL#1#2#3#4\Page#5#6#7#8{\def\HLlevel@{#1} + \ifnum\HLlevel@ = 1 + . . . + . . . + \else + \Err@{\string\HL#1 not defined in this style}% + \fi} +** +so that an error message will be given if *\HL {*\<number\>*}* occurs +for any \<number\>${}\ne{}$*1*. (Theoretically this shouldn't happen, since +the *.toc* file is generated by the main file, which only recognizes +*\HL1*; but we might as well add this precaution in case the *.toc* file +has been edited.) + +When *\HLlevel@* is~*1*, we want to use *\setentry@* with +the appropriate data, +\setbox1\hbox{\<arg$_{\text1}$\>} +\setbox2\hbox{\<arg$_{\text2}$\>} +\setbox3\hbox{\<arg$_{\text3}$\>} +\setbox4\hbox{\<arg$_{\text4}$\>} +** +\setentry@{"box1}{"box2}{"box3}{"box4} +** +In terms of the original arguments *#1*, *#2*, *#3*, \dots, *#8* + of *\HL* (see~ \recentpageref{7ARGS}{above}{the previous page}{}), +\<arg$_{\text2}$\> will be +** +\bf\ignorespaces#4\unskip +** +\<arg$_{\text3}$\> will be *\dotleaders*, and +\<arg$_{\text4}$\> will be +** +\Page@{#5}{#6}{#7}{#8} +** + +As for +\<arg$_{\text1}$\>, it will essentially be +\setbox0\hbox{\<word\>} +** +\bf #2 #3 +** +More precisely, it will be +** +\bf \def\next@{#2}\ifx\next@\empty\else#2\space\fi + \let\style=\HL@@S \Style@#3\Style@ + \ifemptynumber@\else\space\fi +** +So the \<word\> *#2* is followed by a space, if it is non-empty. Moreover, + when *\Style@...\Style@* uses *\style* to +produce the formatting of the number, this *\style* + will be *\HL@@S* (i.e., +`*\HL@S1*', since *\Hllevel@* was defined to be~*1*). And we also +add a space after this number, + except in the case of an empty number. Naturally, other +style files might do things differently. Note, moreover, that although +`*\HL@S1*' has been defined in *lamstex.tex*, if *\newstyle\HL1* appears +in the main file, it will also have to be added to the *.toc* file to +produce the same effect. (In practice, of course, only style file designers +will use *\newstyle\HL*, except perhaps for transient effects.) + +A multi-level *\HL1* heading will have *\\* in it. Although that should +probably be edited out, we can at least give *\\* a provisional definition as +\linebreak +`*\unskip\space\ignorespaces*'. + The only other thing to worry about is the spacing around the heading: +** +\def\HL#1#2#3#4\Page#5#6#7#8{\def\HLlevel@{#1}% + \ifnum\HLlevel@ = 1 +"2 + \bigbreak +"2 + \begingroup + \def\\{\unskip\space\ignorespaces}% +"2 + \setentry@ + {\bf\def\next@{##2}\ifx\next@\empty\else##2\space\fi + \let\style=\HL@@S \Style@#3\Style@ + \ifemptynumber@\else\space\fi}% + {\bf\ignorespaces#4\unskip}% + \dotleaders + {\Page@{#5}{#6}{#7}{#8}} +"2 + \endgroup + \nobreak\smallskip +"2 + \else + \Err@{\string\HL#1 not defined in this style}% + \fi} +** + +\newdimen\digits +\setbox0\hbox{0.00} +\digits=\wd0 + +The default style for *\hl1* headers is +\medskip +\line{\quad\qquad\hbox to\wd0{1.12}\enspace A short section + \leaders\hbox to10pt{\rm\hfil.\hfil}\hfil\kern10pt79\qquad} +\medskip +\noindent +where we indent a *\quad* from the left margin, and + leave room for a double-digit number like `*1.12*', followed by +an *\enspace*, before the section title. + +We have already introduced *\digits* (page~\ref{DIGITS}), +and the definition of *\hl* introduces nothing especially new: +** +\def\hl#1#2#3#4\Page#5#6#7#8{\def\hllevel@{#1}% + \ifnum\hllevel@ = 1 +"2 + \setentry@ + {\rm\quad \let\style=\hl@@S + \hbox to\digits{\Style@#3\Style@\hfil}\enspace}% + {\rm\ignorespaces#4\unskip}% + \dotleaders + {\Page@{#5}{#6}{#7}{#8}}% +"2 + \else + \Err@{\string\hl#1 not defined in this style}% + \fi} +** +In the default style, not only is `*\hl@W1*' empty, but *\hl1* doesn't +print this \<word\>, even if it has been changed by *\newword*; so +we also don't bother about printing it in the table of contents. + + +\section{\CS{NameHL} and \CS{Namehl}} +Finally, *\maketoc* has to deal with alternate names like *\chapter* and +*\section*. If the main file has +** +\NameHL 1 \chapter +\Namehl 1 \section +** +then these lines should also appear in the *.toc* file (before the use +of *\chapter* or *\section*, respectively). + + +First of all, we have to redefine *\NameHL* so that, for example, +\setbox0\hbox{\<word\>} +** +\chapter {"box0}{2} + . . . +\Page... +** +will typeset the same thing as +\setbox0\hbox{\<word\>} +** +\HL {1}{"box0}{2} + . . . +\Page... +** +In other words, we want to +** +"hskip-20pt\def\chapter#1#2#3\Page{\HL{1}{#1}{#2}#3\Page} +** +(we don't need braces around the second *#3*, since it is delimited by +*\Page*). So in general we want *\NameHL#1#2* to mean +** +\def#2##1##2##3\Page{\HL{#1}{##1}{##2}##3\Page} +** +and, similarly, we want +*\Namehl#1#2* to mean +** +\def#2##1##2##3\Page{\hl{#1}{##1}{##2}##3\Page}} +** + +\section{\CS{maketoc}}Putting all this together, our definition of +*\maketoc* is: +\CC** +\def\maketoc{\checkmainfile@ "8STFMAKETOC"8 + \par\vfill\break +"2 + \begingroup + \noset@ \unlabel@ +"2 + \let\nopunct=\relax \let\nospace= \relax +"2 + \let\overlong=\relax +"2 + \everypar{}\parindent=0pt + \lineskiplimit=0pt +"2 + \def\HL##1##2##3##4\Page##5##6##7##8{% + \def\HLlevel@{##1}% +"2 + \ifnum\HLlevel@=1 + \bigbreak +"2 + \begingroup + \def\\{\unskip\space\ignorespaces}% +"2 + \setentry@{\bf\def\next@{##2}\ifx\next@\empty + \else##2\space\fi + \let\style=\HL@@S \Style@##3\Style@ + \ifemptynumber@\else\space\fi}% + {\bf\ignorespaces##4\unskip}\dotleaders + {\Page@{##5}{##6}{##7}{##8}}% +"2 + \endgroup +"2 + \nobreak\smallskip +"2 + \else + \Err@{\string\HL##1 not defined in this style}% + \fi}% +"2 + \def\hl##1##2##3##4\Page##5##6##7##8{% + \def\hllevel@{##1}% +"2 + \ifnum\hllevel@=1 +"2 + \setentry@{\rm\quad\let\style=\hl@@S + \hbox to\digits{\Style@##3\Style@\hfil}\enspace}% + {\rm\ignorespaces##4\unskip}\dotleaders + {\Page@{##5}{##6}{##7}{##8}}% +"2 + \else + \Err@{\string\hl##1 not defined in this style}% + \fi}% +"2 + \def\NameHL##1##2{\def##2####1####2####3\Page + {\HL{##1}{####1}{####2}####3\Page}}% +"2 + \def\Namehl##1##2{\def##2####1####2####3\Page + {\hl{##1}{####1}{####2}####3\Page}}% +"2 + \centerline{\bf\maketoc@W}% + \vskip30pt plus10pt minus10pt + \input\mainfile@.toc + \endgroup} +** + +\nopunct\section{Lists of Figures, Tables, etc.} +The commands +** +\makelistFigures +\makelistTables +** +are defined directly in terms of the more general *\makelist* command, +\CC** +\def\makelistFigures{\makelist\c{F}List of + Figures\endmakelist} +\def\makelistTables{\makelist\c{T}List of + Tables\endmakelist} +** +The syntax has been changed from that of the \lamstex~Manual, page~92, +to conform with the general \amstex\ and \lamstex\ syntax for constructions +that allow *\\* to be used to indicate line breaks. + +*\makelist\c#1#2\endmakelist*, + like *\maketoc*, first uses the test\linebreak *\checkmainfile@*, and then +ends the previous page. After this we want to add +** +\noset@ \unlabel@ +\let\nopunct=\relax \let\nospace=\relax +\let\overlong=\relax +\everypar={}\parindent=0pt +\lineskiplimit=0pt +** +just as in *\maketoc*. +Then +*\makelist* will +** +\def\listclass@{#1} +** +so that, when we *\input* the *.tic* file we will know which of the +*\island*'s to process. + +Next *\makelist* must redefine *\island*. +In the case of *\HL#1...*, +once we had defined *\HLlevel@* as *#1*, +the style control sequence *\HL@@S* was defined, so that we could +*\let\style=\HL@@S* in our definition of *\HL*. A construction + introduced with *\NameHL1* is basically just a synonym for *\HL1*, +so we did not need to consider *\HL@@@S*, defined in terms of *\HLtype@*. +But the situation is different for *\island*'s, where we have only +*\island@@@S*, defined in terms of *\islandtype@*, which is *\island* for +an explicitly typed *\island*, but *\Figure* for a *\Figure*, etc. + +To deal with this situation, +\setbox0\hbox{\<Figure number\>} +\setbox1\hbox{\<caption\>} +** +\Figure {"box0} + "copy1 +\Page ... +** + in the *.tic* file will translate +to +\setbox0\hbox{\<Figure number\>} +\setbox1\hbox{\<caption\>} +\Litbox2=** +\island \at@\Figure \c{F}{Figure}{"copy0} + "copy1 +\Page ... +** +$$\vcenter{\box2}\tag"\style{\bf A}"$$ +---here *\at@* is simply an arbitrarily chosen \lamstex\ control sequence +that the user can't insert---% +while an explicitly typed *\island*, like +\setbox0\hbox{\<map number\>} +** +\island \c{M}{Map}{"box0} +** +will be regarded as +\setbox0\hbox{\<map number\>} +** +\island \at@\island \c{M}{Map}{"box0} +** +so that eventually everything reduces to a common case. + +We begin by redefining *\island* in terms of a *\futurelet*, to see whether +*\at@* follows: +** +\def\island{\futurelet\next\island@} +\def\island@{\ifx\next\at@\expandafter\island@@\else + \expandafter\island@@@\fi} +** + +*\island@@*, where *\at@* follows, has 9 arguments: +** +\long\def\island@@\at@#1\c#2#3#4#5\Page#6#7#8#9 +** +For example, in ({\bf A}), *#1* is `*\Figure*', *#2* is `*F*', *#3* is +`*Figure*', *#4* is the \<Figure number\>, and *#5* is the \<caption\>. + +The definition of *\island@@* +is similar to +the definition of *\HL* except that: +\list\item we use argument *#1* to define +*\islandtype@*, rather than *\HLlevel@*; +\item we print *#3* rather than the \<word\> before the \<Figure number\>; +\item +we process only those *\island*'s whose class *#2* is the *\listclass@* for +the list we are printing.\endlist +** +\long\def\island@@\at@#1\c#2#3#4#5\Page#6#7#8#9{% + \def\islandtype@{#1}% +"2 + \def\next@{#2}% +"2 + \ifx\next@\listclass@ +"2 + \setentry@ + {\rm#3" \let\style=\island@@@S \Style@#4\Style@ + \ifemptynumber@\else\space\fi}% + {\rm\ignorespaces#5\unskip}% + \dotleaders + {\Page@{#6}{#7}{#8}{#9}}% + \fi} +** + +The definition of *\island@@@*, when no *\at@* follows, is reduced to +the case where *\at@\island* follows: +** +\long\def\island@@@\c#1#2#3#4\Page#5#6#7#8{% + \island@@\at@\island + \c{#1}{#2}{#3}#4\Page{#5}{#6}{#7}{#8}} +** + +\bigskip + +When something like +** +\newisland\map\c{M}{Map} +** +appears, an occurrence of +\setbox0\hbox{\<map number\>} +\setbox1\hbox{\<caption\>} +** +\map {"box0} + "box1 +\Page ... +** +should translate to +\setbox0\hbox{\<map number\>} +\setbox1\hbox{\<caption\>} +** +\island \at@\map \c{M}{Map}{"box0} + "box1 +\Page ... +** +In other words, we should +** +\long\def\map#1#2\Page#3#4#5#6{\island \at@\map + \c{M}{Map}{#1}#2\Page{#3}{#4}{#5}{#6}} +** + +So in general, we want to +** +\def\newisland#1\c#2#3{% + \long\def#1##1##2\Page##3##4##5##6{% + \island\at@#1\c{#2}{#3}{##1}##2% + \Page{##3}{##4}{##5}{##6}}} +** + +Since *\Figure* and *\Table* are *\island* classes that are assumed to +be present in all styles, we should also add +** +\newisland\Figure\c{F}{Figure} +\newisland\Table\c{T}{Table} +** + +Putting this all together, we have +\CC** +\def\makelist\c#1#2\endmakelist{\checkmainfile@ + \par\vfill\break +"2 + \begingroup +"2 + \noset@ \unlabel@ +"2 + \let\nopunct=\relax \let\nospace=\relax + \let\overlong=\relax +"2 + \everypar{}\parindent=0pt + \lineskiplimit=0pt +"2 + \def\listclass@{#1}% + \def\island{\futurelet\next@\island@}% +"2 + \def\island@{\ifx\next\at@\expandafter\island@@\else + \expandafter\island@@@\fi}% +"2 + \long\def\island@@\at@##1\c##2##3##4##5\Page##6##7##8##9{% + \def\islandtype@{##1}% + \def\next@{##2}% +"2 + \ifx\next@\listclass@ +"2 + \setentry@{\rm##3 + \let\style=\island@@@S \Style@##4\Style@ + \ifemptynumber@\else\space\fi}% + {\rm\ignorespaces##5\unskip}\dotleaders + {\Page@{##6}{##7}{##8}{##9}}% +"2 + \fi}% +"2 + \long\def\island@@@\c##1##2##3##4\Page##5##6##7##8{% + \island@@\at@\island\c{##1}{##2}{##3}##4\Page + {##5}{##6}{##7}{##8}}% +"2 + \def\newisland##1\c##2##3{\long\def##1####1####2\Page + ####3####4####5####6{% + \island\at@##1\c{##2}{##3}{####1}####2\Page + {####3}{####4}{####5}{####6}}}% +"2 + \newisland\Figure\c{F}{Figure}% + \newisland\Table\c{T}{Table}% +"2 + \vbox{\Let@\tabskip\centering@\halign to\hsize + {\bf\hfil\ignorespaces##\unskip\hfil\cr#2\crcr}}% + \vskip30pt plus10pt minus10pt + \input\mainfile@.tic + \endgroup} +** + +\section{Fini}Then, as in section~\Sref{DONE}, +we finish with +\CC** +\def\alloc@#1#2#3#4#5{\global\advance\count1#1by\@ne + \ch@ck#1#4#2\allocationnumber=\count1#1 + \global#3#5=\allocationnumber + \wlog{\string#5=\string#2\the\allocationnumber}} +\catcode`\@=\active +** + + + + +\chapter Back matter\\The index\endchapter +\runningchapter{Back matter; the index} +Although the ``back matter'' may include the bibliography, and other matter, +the default style file *lamstex.stb* is used only for the index. As explained +in Chapter~13 of the \lamstex~Manual, the *\makeindex* command is going to +read in an *.xdx* ``expanded index file'', which is produced by the *index* +program from the *.ndx* file that \lamstex\ writes. The *index* program is +discussed in the next chapter. In this chapter, we are only concerned with +typesetting the *.xdx* file. In the default style, we will be using a +two-column format, with balanced columns at the end. + +Page 114 of The \lamstex~Manual +gives +a sample piece from an +*.xdx* file that illustrates almost all the features that we have to +consider; + the only additional feature is *\PageSpan*, mentioned on page~117. + + +\section{Preliminaries\label{BMPRE}}As with *lamstex.stf*, we begin with +\CC** +\catcode`\@=11 +\let\alloc@=\alloc@@ +** +Since *"1* has a special role of indicating options in + index entries, if an index entry actually had a \ast\ in it that symbol +will appear as *\asterisk*. So we will need to state +\dotC** +\let\asterisk="1 +** +so that *\asterisk* will print out a \ast\,. We've printed dotted lines +around this definition, since it will +actually + only be made within the definition +of *\makeindex*---for any +material inserted before or after *\makeindex*, the control sequence +*\asterisk* will simply be +undefined. + +As with the bibliography (section~\Sref{SBMACS}), + we will be redefining *\lkerns@* and + *\nkerns@* +for properly placing punctuation before line-breaking penalties, +\dotC** +\def\lkerns@{\null\kern-1sp\kern1sp} +\def\nkerns@{\null\kern-2sp\kern2sp} +** +(we don't really need the *\null*'s that occurred previously, since we're not +setting *\vbox*'s, but for simplicity we might as well stick to the old +definitions). +Once again, we use dotted lines, +since the redefinitions will only be made later, +by *\makeindex*, so that line +breaking commands won't change their meaning until we are actually setting +the index. +On the other hand, we can give + a definition of *\adjustpunct@* +(section~\Sref{BIBMACS}) right now; it differs from the previous definition +only in the omission of + *\closequotes@*: +\CC** +\def\adjustpunct@#1{\count@\lastkern + \ifnum\count@=0 #1\else + \ifnum\count@>2 #1\else + \ifnum\count@<-2 #1\else + \unkern\unkern\setbox0=\lastbox + \skip@=\lastskip \unskip + \count@@=\lastpenalty \unpenalty + \ifnum\count@ = 2 \unskip \setbox0=\lastbox\fi + \ifdim\skip@ = 0pt \else \hskip\skip@ \fi + #1% + \ifnum\count@=2 \null\hfill\fi + \penalty\count@@ + \fi\fi\fi} +** +(Since *\adjustpunct@* is stated within *lamstex.tex* itself, +we could simply state +*\let\closequotes@=\relax*, but restating the definition is preferable +in case *\purge{bib}* has been used.) + +In all the commands appearing in the *.xdx* file, +\setbox0\hbox{etc.,} +** +\Entry 10{acetyl-CoA}{}{}{}{} +\Page {34} +"box0 +** +we are going to want to ignore the space after the last *}*. +In addition, since blank lines might be introduced during editing, +or by ``error messages'', +we will want to skip over any such blank lines---we can't afford to +introduce a *\par* until we know that there are no more page numbers left to +be printed. +\footnote{In version~*1* of \lamstex@, + the *index* program was careful not to introduce +any blank lines, inserting a~ *%* before an otherwise blank line if +necessary, and users were warned not to introduce blank lines. However, +it seems preferable to have the macros +skip the blank lines, since they can make the +*.xdx* file look so much nicer.} + So we will use *\FNSS@* to get the first non-space token, and then +use a +*\futurelet\next* to see if the next token is +*\par*, which should also be discarded: +\CC** +\def\ignorepars@{\FNSS@\ignorepars@@} +\def\ignorepars@@{\ifx\next\par + \def\next@\par{\futurelet\next\ignorepars@@}\else + \let\next@=\relax\fi\next@} +** + +One of the main tasks of the *lamstex.stb* macros is to provide suitable +*\mark*'s so that appropriate ``continuation'' lines may be written at the +top of a page +when a page +break has occurred within an index entry, or subentry, etc. And because of +this, +column-breaking penalties will require more care. + + +The +*\columnbreak* command was not mentioned in the Manual, but + was added for the +*paper* style, and mentioned in the Installation~Manual. In version~*2* +we are also supplying *\nocolumnbreak* and *\newcolumn* (for a short +column), although *\columnbreak* is really the only important one. +Although these commands +essentially insert penalties in vertical mode, we have to make sure +that the penalties occur at the proper time with respect to the +*\mark*'s that are emitted by the *\LETTER* and *\Entry* construction. + +The column-breaking macros work quite differently from the line-breaking +macros because a penalty cannot be removed once it has been placed on the +main vertical list: +they +will not insert any penalties directly, but +will simply set the value of a counter, for later use. We declare the counter +now, +\CC** +\newcount\ctype@ +** +but the definitions +\dotC** +\def\nocolumnbreak{\ctype@=1 } +\def\columnbreak{\ctype@=2 } +\def\newcolumn{\ctype@=3 } +** +will only be given within the definition of *\makeindex*. +We also need to +declare a new counter to store the value of *\ctype@*, for use by the +*\output* routine, after other constructions have returned *\ctype@* to~*0*: +\CC** +\newcount\Ctype@ +** + +It also turns out that column breaks have to be treated quite differently +depending on whether they are inserted in the left column or the right +column, and we will need a flag +\CC** +\newif\ifleftcolbreak@ +** + +Now we define a routine *\cbreak@#1#2* that uses the value of *\ctype@*, +before resetting it to ~*0*. +The definition begins +** +\def\cbreak@#1#2{\ifcase\ctype@#1\or\nobreak#2\else + . . . +** +Thus, if *\ctype@* is *0* (the usual situation, when no column-breaking +command has recently been given), we simply insert *#1*, which will normally +be penalty and glue. If *\ctype@* is~*1* (because a *\nocolumnbreak* +command has recently been given), we instead insert *\nobreak* and then +*#2* (which would normally be *#1* +without the penalty). If *\ctype@* is *2* or *3* (because a *\columnbreak* +or *\newcolumn* command has recently been given), we simply insert a +*\break*. Then we reset *\ctype@* to~*0*. Before doing that last step, +however, we store *\ctype@* in *\Ctype@*. Moreover, we set +*\ifleftcolbreak@* to be false if $\hbox{*\pagetotal*}>\hbox{*\pageheight*}$ +(i.e., we already have enough on the page for the first column), but +true otherwise: +\CC** +\def\cbreak@#1#2{% + \ifcase\ctype@#1\or +"2 + \nobreak#2\else +"2 + \global\leftcolbreak@true + \ifdim\pagetotal > \pageheight@ + \global\leftcolbreak@false + \fi +"2 + \global\Ctype@=\ctype@ + \break + \fi + \ctype@=0 } +** +The value of *\Ctype@* will be used by the *\output* routine, which will +then globally reset *\Ctype@* to ~*0*. + + +We have another flag +\CC** +\newif\ifshortlastcolumn@ +** +for a final index feature not mentioned in the \lamstex~Manual, +\dotC** +\def\shortlastcolumn{\shortlastcolumn@true} +** +if we want the right +column on the last page of the index +to end short, instead of being spread out to match +the height of the left column. + +\section{\CS{LETTER} and \CS{Entry}} +The first *\Entry* after a *\LETTER* will be treated somewhat specially, so +we will need a flag +\CC** +\newif\ifletter@ +** +to tell when a *\LETTER* line has just been set. + + *\LETTER* will +end the previous paragraph (in which the various page numbers for a previous +entry are being set) and +emit a *\mark{}* to clear the marks. + Then we want +** +\penalty-200 +\bigskip +** +to encourage a page break (which really means a column break, since we will +be setting in double columns). +More precisely, we will use +** +\cbreak@{\penalty-200 \bigskip}\bigskip +** +Thus, when a *\nocolumnbreak* command has just appeared, we insert only the +*\bigskip*, and when a *\columnbreak* or *\newcolumnbreak* command +has just appeared, we just insert a *\break*. +Then we set *\ifletter@* to be true, +center the letter in bold face in its column, and finally +add a\linebreak *\nobreak\medskip*: +\dotC** +\def\LETTER#1{\par + \mark{}% + \cbreak@{\penalty-200 \bigskip}\bigskip + \letter@true + \centerline{\bf#1}% + \nobreak\medskip} +** +As usual, the dotted lines indicate that +this is a definition that will actually be included within the +definition of *\makeindex*. + + +To deal with the necessary *\mark*'s to be provided by +*\Entry*, it will be convenient to have five token lists: +\CC** +\newtoks\marktoks@i +\newtoks\marktoks@ii +\newtoks\marktoks@iii +\newtoks\marktoks@iv +\newtoks\marktoks@v +** +Moreover, we will use a flag +\CC** +\newif\ifentry@ +** +which *\Entry* will set true, and each *\Page* will set false. + + +\def\di{{\it d}$_{\text1}$} +\def\dii{{\it d}$_{\text2}$} + +Some aspects of our *\Entry* macro are particular to the default style, +namely the particular manner in which entries and subentries are typeset. +But the really + interesting aspect of *\Entry* is the way that +it uses the first +two arguments (\di, \dii, in the notation of +page~115 of the \lamstex~Manual), to determine which *\mark*'s should be +emitted; these *\mark*'s can be used by any style to define ``continuation +lines'' of any desired sort. To deal with all possibilities, we will need a +new counter +\CC** +\newcount\dii@ +** +which will hold the value of \dii\ for the {\it previous\/} +*\Entry*. + +The definition begins +** +\def\Entry#1#2#3#4#5#6#7{\par\entry@true + \marktoks@i={#3}\marktoks@ii={#4}\marktoks@iii={#5}% + \marktoks@iv={#6}\marktoks@v={#7}% + \ifcase#1% + \or + . . . +** +Thus, since the + case $\hbox{*#1*}=\hbox{\di}=\hbox{0}$ +is not supposed to occur, we consider first +the case $\hbox{*#1*}=\hbox{\di}=\hbox{1}$, + which means that we have a first order entry, i.e., + *#4*, \dots, *#7* are empty; + in this case $\hbox{*#2*}=\hbox{\dii}$ + should be 0, since this new first order +entry can't have any number of groups agreeing with the previous entry. + +We begin with +** +\ifletter@\else\mark{}\fi +\cbreak@\relax\relax +\noindent@ +\mark{10{\the\marktoks@i}}% +\hangafter 1 \hangindent=.5em{#3}% +** +Thus: +\list\item + We issue a *\mark{}* to clear the marks, unless the *\Entry* comes +right after a *\LETTER*, which has already done this. +\item If a *\nocolumnbreak* appeared right before the *\Entry* we +add a *\nobreak*; and if a *\columnbreak* or *\newcolumn* appeared, +we add a *\break*, and also set *\ifleftcolbreak@* to the appropriate value +and store *\ctype@* in *\Ctype@* before restoring *\ctype@* to~ *0*. +\item +Then we start an unindented paragraph, which begins +with a *\mark*, +** +\mark{10{\the\marktoks@i}}% +** +containing *#1#2*, and then a single group containing +*#3* (without any expansion). +The +** +\hangafter1 \hangindent=.5em{#3}% +** +means +that after the entry *#3* is printed we are set up for printing the +various page numbers, with hanging indentation if there are so many that they +won't fit on a line. We enclose *#3* in a group, in case it involves a font +change command, and are careful not to allow a space after *{#3}*, since +punctuation still has to be added. +\endlist + +When the paragraph with this entry is completed, +the *\mark{10{...}}*\linebreak will migrate out so that it occurs right after +the first line (before any\linebreak *\baselineskip* glue); consequently, +there will be no legal breakpoint between the *\mark* and this first line, +containing the typeset *{#3}*. +If a page break occurs after this entry, but + before another entry, which contributes a new *\mark*, +then after the +page has been *\output* the value of +*\botmark* +will be +** +10{#3} +** +When a style file has to add continuation lines at the beginning of the next +page, the *10* will tell it that the style broke at a main entry, which will +be contained in the next group. + (Actually, we will be using *\splitbotmark* rather than +*\botmark* when we do two-column setting.) + + +In summary, our definition begins: +** +\def\Entry#1#2#3#4#5#6#7{\par\entry@true + \marktoks@i={#3}\marktoks@ii={#4}\marktoks@iii={#5}% + \marktoks@iv={#6}\marktoks@v={#7}% + \ifcase#1% + \or + \ifletter@\else\mark{}\fi + \cbreak@\relax\relax + \noindent@ + \mark{10\the\marktoks@i}% + \hangafter1 \hangindent=.5em{#3}% + \or +** + +Now let's consider the next case, $\hbox{\di}=\hbox{*#1*}=\hbox{2}$, +so that we have a first order +subentry. In this case $\hbox{\dii}=\hbox{*#2*}$ + may be either ~0 or~1. When $\hbox{*#2*}=\hbox{0}$, we +have a subentry that does {\it not\/} have the same main entry as the +previous line, like the situation +** +\Entry 10{abracadabra}{}{}{}{} +\Page {5} +\Entry 20{acetyl-CoA}{action of}{}{}{} +\page {32} +** +As mentioned on page~116 of the \lamstex~Manual, in some styles this might +be printed as + {\bigskip\eightpoint\leftskip=30pt \noindent + abracadabra, 5\newline + acetyl-CoA, action of, 32 +\bigskip} +\noindent +In the default style, we will still print + {\bigskip\eightpoint\leftskip=30pt \noindent + abracadabra, 5\newline + acetyl-CoA\newline + \null\hskip5pt action of, 32 +\bigskip} +\noindent +but we still have to treat the *\mark*'s differently for the +cases $\hbox{\dii}=\hbox{*#2*}=\hbox{0}$ and $\hbox{\dii}=\hbox{*#2*}= +\hbox{1}$. + +For the case $\hbox{*#2*}=\hbox{0}$ we want +** +\ifletter@\else\mark{}\fi +\cbreak@\relax\relax +\noindent +\mark{20{\the\marktoks@i}{\the\marktoks@ii}}% +\hangafter1 \hangindent=.5em{#3}\par\nobreak +\noindent\hangafter1 \hangindent=1.5em\quad{#4}% +** +Thus: +\list\item +We clear the previous mark (the one for *abracadabra*). +\item We emit the mark +\setbox0\hbox + {$\bigl[$*20{acetyl-CoA}{action of}*, in the above example$\bigr]$} +** +20{#3}{#4} "box0 +** + and then set up the proper format for printing things. +If the page breaks in the middle of this entry, then *\botmark* will have +the value +** +20{#3}{#4} +** +and the *\output* routine will be clued in as to +what sort of continuation lines to +add. +\endlist + +The other case, when $\hbox{*#2*}=\hbox{1}$, +corresponds to the more common situation +where we have something like +** +\Entry 10{acetyl-CoA}{}{}{}{} +\Page {32} +\Entry 21{acetyl-Coa}{action of}{}{}{} +\Page {45} +** +Here we will use +** +\mark{10{\the\marktoks@i}}% +\cbreak@\relax\relax +\noindent@ +\mark{21{\the\marktoks@i}{\the\marktoks@ii}}% +\hangafter 1 \hangindent=1.5em\quad{#4} +** + +Even when the *\cbreak@* contributes nothing (the usual situation), there +is a legal break point between the first *\mark* and the *\noindent@*'ed +paragraph that follows, because of the *\parskip* glue (possibly *0pt*) +before this paragraph. +If the page breaks at this point, then *\botmark* will be this first +** +\mark{10{acetyl-CoA}} +** +which is precisely right: we have broken in the middle of a first level +entry. If the page breaks after the sub-entry begins, but before a new +*\Entry*, which contributes a new *\mark*, then *\botmark* will be +** +21{acetyl-CoA}{action of} +** +again giving the *\output* routine all the information it needs to decide +what sort of continuation lines to insert. + +\small +Although we are using *\cbreak@\relax\relax* in all clauses of our +*\Entry* definition, other styles might give more detailed choices. For +example, it might be considered + better to break right before an entry than right before +a subentry. We might use something like +** +\cbreak@{\ifletter@\else\penalty-20 \fi}\relax +** +for the case $\hbox{*#1*}=1$, thereby slightly encouraging a column break +before main entries, except those immediately following a *\LETTER*. +\endsmall + + +The case $\hbox{\di}=\hbox{*#1*}=\hbox{3}$ + begins similarly: When $\hbox{*#2*}=\hbox{0}$ we use +** +\ifletter@\else\mark{}\fi +\cbreak@\relax\relax +\noindent +\mark{30{\the\marktoks@i}{\the\marktoks@ii}{\the\marktoks@iii}}% +\hangafter1 \hangindent=.5em{#3}\par\nobreak +\noindent@\hangafter1 \hangindent=1.5em\quad{#4}\par\nobreak +\noindent@\hangafter1 \hangindent=2.5em\qquad{#5}% +** +and when $\hbox{*#2*}=\hbox{1}$ we use +** +\mark{10{\the\marktoks@i}}% +\cbreak@\relax\relax +\noindent@ +\mark{31{\the\marktoks@i}{\the\marktoks@ii}{\the\marktok@iii}}% +\hangafter1 \hangindent=1.5em\quad{#4}\par\nobreak +\noindent@\hangafter1 \hangindent=2.5em\qquad{#5}% +** + +But the case $\hbox{*#2*}=\hbox{2}$ + is a little different, because the previous entry +might have been an *\Entry 20* or an *\Entry 21*, and to provide the style +with all possible information, we want to supply the correct result. So we +use +** +\mark{2"9\number\dii@"9{\the\marktoks@i}{\the\marktoks@ii}}% +\cbreak@\relax\relax +\noindent@ +\mark{32{\the\marktoks@i}{\the\marktoks@ii}{\the\marktoks@iii}}% +\hangafter1 \hangindent=2.5em\qquad{#5}% +** +where *\dii@* will have the proper value, because, at the very end of +this long *\ifcase* (with sub *\ifcase*'s) +we finish off the whole definition of *\Entry* with +** +\dii@=#2\relax +\letter@false\ignorepars@} +** + +We won't bother writing out the whole definition, since these parts explain +everything interesting that is going on (moreover, the whole definition +appears only within the definition of *\makeindex*). + +\nopunct\section{\CS{Page}, etc.\label{IPAGE}} +Using *\adjustpunct@* (section~\Sref{BMPRE}), we will define +*\Page* for the index setting by +\dotC** +\def\Page#1{\ifentry@\adjustpunct@,\enspace\else + \adjustpunct@, \fi\entry@false{#1}\ignorepars@} +** +In other words, the first *\Page* after an *\Entry*, when *\ifentry@* is +still true, + will add a comma after +the entry, and then an *\enspace*, while successive *\Page*'s, for which +*\ifentry@* will be false, + will simply +add a comma after that page number and then an ordinary space +(with suitable juggling of line-breaking penalties). +We put *#1* in a group in case it involves a font change. + +The *\Pagespan*, *\Topage* combination requires a bit more + manipulation, because +the *index* program may have produced something like +** +\Pagespan {123} +\Topage {123} +** +which should be printed simply as `123', rather than as `123@--123'. + +We begin with +\dotC** +\def\Pagespan#1{\ifentry@\adjustpunct@,\enspace\else + \adjustpunct@, \fi + \entry@false\def\frompage@{#1}{#1}\ignorepars@} +** +Thus, we supply punctuation just as with *\Page*, and before printing +*#1* we also + store +*#1* in *\frompage@*, for use with *\Topage*, defined by +\dotC** +\def\Topage#1{\def\next@{#1}\ifx\next@\frompage@ + \else\hbox{--}{#1}\fi\ignorepars@} +** +The *\hbox{--}* gives an en-dash at which a line break can't occur + (it is what the +\lamstex\ construction *@--* produces). + +The variant *\PageSpan#1#2*, which has a control sequence as +its first argument, puts in punctuation in the same manner as + *\Pagespan*, and also + stores the page argument, *#2*, in *\frompage@*, as well as the +control sequence, *#1*, in *\pagecs@*. Then it begins a group in which +the definition of *\Topage* will be changed, so that the *\Topage* following +*\PageSpan* can act differently than when it follows *\Pagespan*: +\dotC** +\def\PageSpan#1#2{\ifentry@\adjustpunct@,\enspace + \else\adjustpunct@, \fi\entry@false + \def\pagecs@{#1}\def\frompage@{#2}% + \bgroup\let\Topage=\Topage@\ignorepars@} +** +Then *\Topage@* will apply *\pagecs@* to the pages spanned (or to +a single page if the two numbers are the same), and supply the *\egroup* to +match the *\bgroup*: +\CC** +\def\Topage@#1#2{\def\next@{#2}\ifx\next@\frompage@ + \pagecs@{\frompage@}\else + \pagecs@{\frompage@\hbox{--}#2}\fi + \egroup\ignorepars@} +** +We use *\pagecs@{...}* +in case *\pagecs@* is a control sequence with +an argument; the *\bgroup* and *\egroup* provide the necessary extra level of +grouping in case *\pagecs@* is a font change instruction. We might as +well give the definition of *\Topage@* now, rather than within the +definition of *\makeindex*, since *\Topage@* can't be typed by the user +anyway. + + +\nopunct\section{\CS{Xref}, etc.} +The description of the *"1x* option +on page~108 of the \lamstex~Manual, and the output it supposedly produces in +the *.xdx* file, as described on page~115 of the Manual, is incorrect. +\footnote{As mentioned on pages~8--9 of the \lamstex\ +Installation Manual.} +There are actually {\it two\/} options, *"1x* and *"1X*. The *"1x* option +is to be used +when only a cross-reference is desired, and not a reference to the page on +which the entry is marked, while the *"1X* option indicates a reference to +the page on which the entry is marked, together with a cross reference. + +If an entry is always marked with the *"1x* option, then the pages on which +it is marked are completely irrelevant, and it will give rise to an +*\Entryxref* line in the *.xdx* file (possibly followed by various +*\Morexref* lines). Otherwise, it will give rise to something like +\Litbox0=** +\Entry ... +\Xref ... +\Morexref ... + . . . +\Page ... +\Page ... +\Xref ... +\Morexref ... + . . . +** +$$\vcenter{\box0}\tag"\style{\bf A}"$$ +with *\Xref...* material occurring both before and after the *\Page*'s because +some styles might want to print the `{\it see also\/}' before the page +numbers instead of after them. + +In any case, as the Manual shows on page~115, each *\Xref*, *\Morexref*, +and *\Entryxref* will contain *\See*, which can be defined as needed. + +In the default style we will be ignoring the *\Xref* and *\Morexref*'s in +({\bf A}) that come before the first *\Page*; +this means that we want + *\Xref* and *\Morexref* to operate only when *\ifentry@* is false. + + +*\Xref*, which will occur after some *\Page*, will add a semi-colon after +the page, and then print `{\it see also\/} ' before its argument. +As with the bibliography macros, we use *\semicolon@* instead of~ *;* for +the benefit of French styles (section~\Sref{SEMICOL}), and we add *\/* before +it, +\dotC** +\def\Xref#1{\ifentry@\else + \def\See##1{\/\adjustpunct@\semicolon@\space + {\it see~also\/}~##1}{#1}\fi\ignorepars@} +** +while *\Morexref* will simply add a comma after the previous +cross-reference page, and then a space: +\dotC** +\def\Morexref#1{\ifentry@\else + \def\See##1{\adjustpunct@, ##1}{#1}\fi\ignorepars@} +** + +An *\Entryxref* is basically just an *\Entry*, after which we +add the final argument rather than succeeding *\Page*'s. +\dotC** +\def\Entryxref#1#2#3#4#5#6#7#8{% + \Entry{#1}{#2}{#3}{#4}{#5}{#6}{#7}% + \def\See##1{\adjustpunct@, {\it see\/}~##1}% + {#8}\ignorepars@} +** +(The *\adjustpunct@* is added in case the user adds a line-breaking +command, like +** +\Entryxref 10{adrenalin}{}{}{}{}{\linebreak\See {epinephrine}} +** +by hand.) + + +\small +Suppose that we want to print the `{\it see also }' +before the page numbers instead of after them, which means that +we need to +use the *\Xref*'s and *\Morexref*'s that +appear before the first *\Page*, +ignoring *\Xref*'s and *\Morexref*'s +following a *\Page*. + +For this we would introduce a new flag +** +\newif\ifxref@ +** +which *\Xref* would set true and *\Entry* would set false, and then +we could use definitions like +** +\def\Xref#1{\ifentry@ + \def\See##1{ {\it see also\/} ##1}{#1}\fi\ignorepars@} +\def\Morexref#1{\ifentry@ + \def\See##1{\adjustpunct@, ##1}{#1}\fi\ignorepars@} +\def\Page#1{\ifxref@\newline\else + \ifentry@\adjustpunct@,\enspace\else + \adjustpucnt@, \fi\fi\entry@false{#1}\ignorepars@} +** +Then entries without cross-references would appear as before, while +entries with cross-references would appear as +{\bigskip\eightpoint\leftskip30pt + acetyl-CoA {\it see also\/} derivative, pyruvate + \hskip5pt 30, 56, 78 +\bigskip} +\noindent Instead of the *\newline* we might prefer `*. *' or +perhaps *\Xref* would add `*({\it see also\/} *' while +*\Page* would add `*) *' instead of *\newline*. + +\andsmall +Similarly, +any punctuation after the last page number would have to be added by +the next *\Entry* (the definition +of *\makeindex* would also have to take care of the last *\Entry* specially). + But +no one ever adds this punctuation, so why worry about it. +\endsmall + + + +\section{Preliminaries for double columns} +We first declare +a \<dimen\> register to store *\vsize*, +\CC** +\newdimen\pageheight@ +\pageheight@=\vsize +** +since *\vsize* will be changed when +we are storing material for double columns, +and a dimension *\doublepageheight@*, which is a little more than twice +*\pageheight@*, +\CC** +\newdimen\doublepageheight@ +\doublepageheight@=2\pageheight@ +\advance\doublepageheight@ by 1 pc +** + +We also declare a \<dimen\> register + to store the original *\hsize*, +\CC** +\newdimen\pagewidth@ +\pagewidth@=\hsize +** + +The *\makeindex* routine will be setting columns 3~inches wide, so we will be +changing *\hsize*. Consequently, we must redefine *\makeheadline* and +*\makefootline* from *plain* \tex@, so that *\line* ($=${}*\hbox to\hsize*) +is replaced by *\hbox to\pagewidth@*: +\CC** +\def\makeheadline{\vbox to 0pt{\vskip-22.5pt + \hbox to\pagewidth@{\vbox to 8.5pt{}\the\headline}\vss}% + \nointerlineskip}% +\def\makefootline{\baselineskip=24pt + \hbox to\pagewidth@{\the\footline}}% +** +(The definition of *\makeheadline* isn't really needed for the default style, + since we are going to keep *\headline={}*, but we might as well take care of +the general mechanism.) + +As in Appendix E of {\it The \tex book}, page~417, +we will be setting ``pages'' +of +length *\doublepageheight@*, so that we can +automatically balance the columns on the last page. +We need another flag +\CC** +\newif\iffirstindexpage@ +** +since the first page of the index is special, having a header `{\bf INDEX}' +that extends across both columns. + +\section{\CS{makeindex}} +The *\makeindex* routine begins +\setbox0\hbox{\<all previous definitions enclosed in dotted lines} +\setbox1\hbox{\qquad(including the definition of *\Entry*)\>} +** +\def\makeindex{\checkmainfile@\par\vfill\break + \begingroup + "box0 + "box1 + \hsize=3in +** +Of course all *#*'s in any of those \<previous definitions\> are changed to +*##*'s. + +Next we set +** +\global\vsize=\doublepageheight@ +** +so that we will have +accumulated slightly more than we need to fill both columns of the page +before the *\output* routine is called (we use *\global* here because +it will be required later, when we set *\vsize* within the *\ouput* routine). +And +we set +** +\maxdepth=\maxdimen +** + so that the depth of +*\box255* will always be the actual depth of its last line; this is +needed at one point later (compare {\it The \tex book}, page~262@--263). + +Then we set +** +\global\firstindexpage@true +\global\advance\vsize by -60pt +** +The +60~points is need to leave room for a 30~point heading above both columns. + +Next, + we +set +** +\everypar={}\parindent=0pt +** +just as a precaution, and then +** +\rightskip=0pt plus3em \spaceskip=.3333em \xspaceskip=.5em +** +for ragged +right setting (we allow even more ``raggedness'' than the definition of +*\raggedright* in *plain* \tex)@. + +And then we want to change the *\output* routine to one called +** +\doublecolumns@ +** +before reading in the appropriate *.xdx* file; after this file has been +read we will issue an empty *\mark{}*, +change the *\ouput* routine to one called +*\balancecolumns@*, for the final page of the index, and then supply +the *\endgroup* that matches the *\begingroup* at the beginning of the +definition. For anything that follows the *\makeindex*, we will once +again have *\output="allowbreak{\plainoutput}*. However, *\vsize* has +been globally changed, so we must reset it to *\pageheight@*. +\setbox0\hbox{\<definitions from before\>} +\CC** +\def\makeindex{\checkmainfile@ + \par\vfill\break + \begingroup + "box0 + \hsize=3in +"2 + \global\vsize=\doublepageheight@ +"2 + \maxdepth=\maxdimen +"2 + \global\firstindexpage@true +"2 + \global\advance\vsize by -60pt +"2 + \everypar={}\parindent=0pt +"2 + \rightskip=0pt plus3em \spaceskip=.3333em \xspaceskip=.5em +"2 + \output={\doublecolumns@}% + \input\mainfile@.xdx + \mark{}% + \output={\balancecolumns@}% + \vfil\break + \endgroup + \global\vsize=\pageheight@} +** + + +\section{\CS{combinecols\@}} +Both *\doublecolumns@* and *\balancecolumns@* will store the two columns +in *\box0* and *\box2* and then + use the routine +*\combinecolumns@*, which prints these boxes +side by side, together with the proper headline and footline. +** +\def\makeindex@W{Index} +"slip +\def\combinecolumns@{% +"2 + \setbox\outbox@=\vbox{\makeheadline +"2 + \vbox to\pageheight@{\boxmaxdepth=\maxdepth +"2 + \iffirstindexpage@ +"2 + \vbox to30pt{\vskip10pt + \hbox to\pagewidth@{\hfil\bf + \uppercase\expandafter{\makeindex@W}\hfil}\vfil} +"2 + \nointerlineskip + \fi +"2 + \wd0=\hsize \wd2=\hsize + \setbox0=\hbox to\pagewidth@{\box0 \kern.5in\box2} + \dimen@=\dp0 \box0 \kern-\dimen@\vfill} + \makefootline} + {\noexpands@ \let\style=\relax + \shipout@\box\outbox@ + } + . . . +** + +This is like the *\shipout@* occurring in our definition of +*\plainoutput* (page~\ref{DEFPLOUT}), +except that the *\pagebody* must be replaced by +a *\vbox to*\linebreak*\pageheight@*, + containing the two boxes with a separation +of *.5in*. There are also two minor adjustments to be made: +\list +\item +We must explicitly declare the widths of *\box0* and *\box2* +to be *\hsize* (*\hsize* is simply the width of paragraphs within +these boxes; an inserted *\box* in vertical mode could be any width---compare +the footnote on page~\ref{MAXD}). +\item +Our *\vbox to\pageheight@* ends with the +** +\hbox to\pagewidth@{\box0 \kern.5in\box2} +** +followed by +*\vfill* (preceded by a *\kern*). + That is because on the last page, where we balance +columns, this *\hbox* will generally be smaller than *\pageheight@*. +Most of the time, of course, the *\vfill* will be irrelevant, except that +we have to be sure to insert the *\kern* before the *\vfill*, so that +the depth of the *\hbox* will not cause an *Overfull* box (compare +page~\ref{KMPR}).\pagelabel{USEKMPR} +\endlist + +In addition, on the first page of the +index, our two columns, *\box0* and *\box2* +will have been made 30~points smaller +than *\pageheight@*, in order to accommodate the +** +\vbox to30pt{\vskip10pt + \hbox to\pagewidth@{\hfil\bf + \uppercase\expandafter{\makeindex@W}\hfil}\vfil}% + \nointerlineskip +** +that we insert. We use *\makeindex@W*, so that *\newword* can be used +to determine the heading that will be printed. + + Notice that we have the *\noexpands@...\shipout@* in a +group, so that the *\noexpands@* won't interfere with +font change instructions in +``continuation'' lines contributed later + (see page~\ref{CONLINES}) by the *\output* routine. (Compare +page~\ref{SHIPOUTGROUP}.) + +After all this, we simply declare *\iffirstindexpage@* to be false, +set *\vsize* to *\doublepageheight@*, its proper value for all index pages +after the first, and *\advancepageno*: +\CC** +\def\makeindex@W{Index} +"slip +\def\combinecolumns@{% +"2 + \setbox\outbox@=\vbox{\makeheadline +"2 + \vbox to\pageheight@{\boxmaxdepth=\maxdepth +"2 + \iffirstindexpage@ +"2 + \vbox to30pt{\vskip10pt + \hbox to\pagewidth@{\hfil\bf + \uppercase\expandafter{\makeindex@W}\hfil}% + \vfil}% +"2 + \nointerlineskip +"2 + \fi +"2 + \wd0=\hsize \wd2=\hsize + \setbox0=\hbox to\pagewidth@{\box0 \kern.5in\box2}% +"2 + \dimen@=\dp0 \box0 \kern-\dimen@\vfill}% + \makefootline}% + {\noexpands@ \let\style=\relax + \shipout@\box\outbox@ + }% + \global\vsize=\doublepageheight@ + \global\firstindexpage@false + \advancepageno} +** + + +\section{\CS{doublecolumns\@}} +For the + *\doublecolumns@* routine, used for all but the last page, we will need +a new \<dimen\> register +\CC** +\newdimen\prevcoldepth@ +** +The routine +begins +with +** +\dimen@=\pageheight@ +\iffirstindexpage@ \advance\dimen@ by -30pt \fi +** +so that *\dimen@* is the height of the columns we want for the page. + +Now we have to consider the possibility that a *\columnbreak* or a\linebreak +*\newcolumn* +command caused the *\output* routine to be invoked. More precisely, we +want to insert the code +** +\ifleftcolbreak@ + \global\leftcolbreak@false + . . . +\else + _ _ _ +\fi +** +The flag *\ifleftcolbreak@* is set true (by *\cbreak@*) when +a *\columnbreak* or *\newcolumn* command has been issued +when we are setting the left column, +\footnote{I.e., when *\pagetotal* is + $\le\hbox{*\pageheight@*}$.} +and it is used only in the current +test; since we immediately reset it to be false, this means that +*\ifleftcolbreak@* is true precisely when we have forced a break in the left +column. We will simply let `\hbox{*. . .*}' for this case be +** +\vbox to\dimen@{\dimen@=\dp255 \unvbox255 + \ifnum\Ctype@=3 \kern-\dimen@\vfill\fi} +\allowbreak +** +In other words, when our *\output* routine has been forced while we +still have only enough material for the first column, we do not do any +*\shipout*, but simply put material back on the main vertical list. +What we put back is a *\vbox to\dimen@* (remember that *\dimen@* is +the desired height of columns for this page), containing all the material +in *\box255*, either stretched out, when we had a *\columnbreak* (so that +*\Ctype@* is~*2*), or filled with empty space at the bottom, when we had +a *\newcolumn* (so that *\Ctype@* is~*3*). As before (page~\ref{USEKMPR}), + we need to add a +*\kern* before the *\vfill*. + + + The next time the *\output* +routine is called, *\doublecolumns@* will use the rest of the routine, still +to be defined, which splits the full *\box255* into two boxes of height +*\dimen@*; the first part will then have to be this *\vbox to\dimen@* that +we have just added to the main vertical list. +\footnote{The only problem here is that the *\output* routine could +conceivably be *\balancecolumns* the next time it is called---see +the discussion on page~\ref{CBBAL}~ff.} + +Having gotten that consideration out of the way, let's consider the +other situation, where we haven't forced a break in a left-hand column. +Now we want to *\vsplit* *\box255* into two boxes of height *\dimen@*. +During the process we will set *\splittopskip=\topskip* and +*\splitmaxdepth=\maxdepth* (this assignment will be local, since the +*\output* routine, *\doublecolumns*, is implicitly enclosed in a group). +Splitting off the first column requires no special work, +** +\splittopskip=\topskip \splitmaxdepth=\maxdepth +\setbox0=\vsplit255 to\dimen@ +** +But for the second column, we can't simply +** +\setbox2=\vsplit255 to\dimen@ +** +This works when *\Ctype@* is~*0* or ~*1* (no column-breaking commands, +except perhaps a *\nocolumnbreak*, +were given). But when *\Ctype@* is~ +*2* or~ *3* +(a *\columnbreak* or *\newcolumn* +command was given) the *\vsplit*'ing is irrelevant---we +should simply let *\box2* be *\box255*. +And when *\Ctype@* is~*3* +(the *\newcolumn* case), we need to add *\vfill* at the +bottom of the box. +For a later step, we also want to store the depth of the last line +of the second column in *\prevcoldepth@*. + +Since the cases when *\Ctype@* is *0* and *1* are treated the same, +we consolidate the cases by first stating +** +\ifnum\Ctype@=0 \global\Ctype@=1 \fi +** +Then we can use +** +\ifcase\Ctype@ \or % case 1 (originally 0 or 1) + \setbox2=\vsplit255 to\dimen@ + \global\prevcoldepth@=\dp2 + \or % cases 2 and 3 + \global\prevcoldepth@=\dp255 % store the depth first + \setbox2=\vbox to\dimen@{\unvbox255 + \ifnum\Ctype@=3 \vfill\kern-\prevcoldepth@\vfill\fi} + \fi +** + +Once we've determined the columns, *\box0* and *\box2*, in this way, +we use +** +\combinecolumns@ +** +to *\shipout* the desired page. + +Now we have reached the point where we want the *\output* routine to +add ``continuation'' lines\pagelabel{CONLINES} + (these lines, inserted by the *\output* routine, +will go before anything remaining in *\box255*, since we will add these +lines before we *\unvbox255*; and both go before anything else that happens +to remain on the main vertical list when the page break was chosen). + +The default routine adds continuation lines at the beginning of the left +column on +a new page +to reflect the *\mark*'s at the end of the right column on the previous page. +This means that we will want to use *\splitbotmark* when *\box2* was +obtained as a *\vsplit255 to\dimen@*, but *\botmark* otherwise. +The specific continuation lines to be constructed from these marks will +be contributed by a routine, to be defined shortly, +\setbox0\hbox{\<the *\mark*'s\>} +** +\continue@ "box0 \continue@ +** +It will be convenient to consider *\continue@* to be followed by at least +~7 (possibly empty) arguments, + and we will use +** +\ifcase\Ctype@ \or % case 1, where \vsplit was used +\expandafter\continue@\splitbotmark{}\relax\relax\relax + \relax\relax\relax\continue@ +\else % cases 2 and 3 +\epxandafter\continue@\botmark{}\relax\relax\relax + \relax\relax\relax\continue@ +\fi +** +As we will see in a minute, *\continue@* will also attend to an important +detail about spacing. + +After these continuation lines, we simply use +** +\ifvoid255 \else \unvbox255 \penalty\outputpenalty\fi +** +to finish the *\else* clause of our definition. And, finally, after the +entire *\if...\else...\fi* has been done, we reset *\Ctype@* to be~*0*: +\CC** +\def\doublecolumns@{% + \dimen@=\pageheight@ + \iffirstindexpage@ \advance\dimen@ by -30pt \fi +"2 + \ifleftcolbreak@ + \global\leftcolbreak@false + \vbox to\dimen@{\dimen@=\dp255 + \unvbox255 \ifnum\Ctype@=3 \kern-\dimen@\vfill\fi}% + \allowbreak +"2 + \else + \splittopskip=\topskip \splitmaxdepth=\maxdepth + \setbox0=\vsplit255 to\dimen@ +"2 + \ifnum\Ctype@=0 \global\Ctype@=1 \fi +"2 + \ifcase\Ctype@ \or + \setbox2=\vsplit255 to\dimen@ + \global\prevcoldepth@=\dp2 +"2 + \else + \global\prevcoldepth@=\dp255 + \setbox2=\vbox to\dimen@{\unvbox255 + \ifnum\Ctype@=3 \kern-\prevcoldepth@\vfill\fi}% + \fi +"2 + \combinecolumns@ +"2 + \ifcase\Ctype@ \or \expandafter + \continue@\splitbotmark{}\relax\relax\relax + \relax\relax\relax\continue@ + \else + \expandafter\continue@\botmark{}\relax\relax\relax + \relax\relax\relax\continue@ + \fi +"2 + \ifvoid255 \else \unvbox255 \penalty\outputpenalty \fi + \fi + \global\Ctype@=0 } +** + +\medskip +The *\continue@* routine is followed by at least~7 (possibly empty) arguments, +** +\def\continue@#1#2#3#4#5#6#7#8\continue@ +** +Since *\continue@* is used in a combination +\setbox0\hbox{\<value of *\splitbotmark* or *\botmark*\>} +** +\continue@"box0{}\relax\relax\relax + \relax\relax\relax\continue@ +** +the test +** +\def\next@{#1}\ifx\next@\empty +** +isolates the case where the *\mark* is empty (in all other cases the +mark will begin with a digit). + When this is not the case, +we want +** +\noindent@#3 ({\it continued\/})\par +** +as the first continuation line. The default style also introduces +slightly differently formatted continuation lines for any sub-entries, where +the number of levels of sub-entries is known from the value of *#1*, +** +\ifnum#1>1 \noindent@\enspace(#4 {\it continued\/})\par\fi + . . . +\ifnum#1>4 \noindent@\enspace(#7 {\it continued\/})\par\fi +** + + +After these continuation lines are added, we have to attend to the detail +mentioned on page~263 of {\it The \tex book}, except that +now we have to consider two different cases: + +{\bf (1)} Suppose first that all of *\box255* has been used up, and that the +first box waiting to be placed +on the new current page +has height {\it h}. +This box + will be preceded by interline glue {\it g}, since the page break +that created it broke right before the glue. If +that box +were the first thing to be placed on the new page, + the glue {\it g\/} would be irrelevant, +since \tex\ discards glue when the current page does not contain any +boxes ({\it The \tex book}, page~112); instead of this glue, \tex\ would +simply insert the glue determined by *\topskip*. + But this glue will {\it not\/} + be discarded if +continuation lines have already been added. + + We have stored the depth of the line +preceding this first box in\linebreak + *\prevcoldepth@*; thus, the glue {\it +g\/} +satisfies +\Math\hbox{*\prevcoldepth@*}+\hbox{\it g}+\hbox{\it h} + =\hbox{*\baselineskip*}\endMath +But now we need new glue {\it g}$'$ such that +\Math +\hbox{*\prevdepth*}+\hbox{\it g}'+\hbox{\it h}=\hbox{*\baselineskip*}\endMath +So we need to add $\hbox{*\prevcoldepth@*}- + \hbox{*\prevdepth*}$ glue; thus, when continuation lines are added, +we need to +** +\global\advance\prevcoldepth@ by -\prevdepth \kern\prevcoldepth@ +** +(We can change *\prevcoldepth@* like this, instead of using the more +complicated code +** +"hskip-20pt\dimen@=\prevcoldepth@ \advance\dimen@ by -\prevdepth \kern\dimen@ +** +because *\prevcoldepth@* won't be used any more.) + +{\bf(2)} When *\box255* has not been used up, however, the situation is quite +different, since this *\box255* is what remains from a *\vsplit*, +so that the glue {\it g\/} is simply enough to make +\Math +\hbox{\it g}+\hbox{\it h}=\hbox{*\topskip*} +\endMath +We want glue {\it g}$'$ such that +\Math +\hbox{\it g}'+\hbox{\it h}+\hbox{*\prevdepth*}=\hbox{*\baselineskip*} +\endMath +so we need to add +\Math\hbox{*\baselineskip*}-\hbox{*\prevdepth*}-\hbox{*\topskip*} +\endMath +extra glue. + +Actually, in both cases {\bf(1)} and {\bf(2)}, *\baselineskip* should really +be\linebreak +$\hbox{*\baselineskip*}+\hbox{*\parskip*}$, though this +doesn't make any difference in the final result for {\bf(1)}. + +The whole definition is thus +\CC** +\def\continue@#1#2#3#4#5#6#7#8\continue@{% + \def\next@{#1}\ifx\next@\empty +"2 + \else + \noindent@#3 ({\it continued\/})\par +"2 + \ifnum#1>1 \noindent@\enspace(#4 {\it continued\/})\par\fi +"2 + \ifnum#1>2 \noindent@\enspace(#5 {\it continued\/})\par\fi +"2 + \ifnum#1>3 \noindent@\enspace(#6 {\it continued\/})\par\fi +"2 + \ifnum#1>4 \noindent@\enspace(#7 {\it continued\/})\par\fi + \ifvoid 255 + \global\advance\prevcoldepth@ by -\prevdepth \kern\prevcoldepth@ + \else + \skip@=\baselineskip \advance\skip@ by \parskip + \advance\skip@ by -\prevdepth + \advance\skip@ by -\topskip + \vskip\skip@ + \fi + \fi} +** + +\small If we had also +wanted continuation lines at the top of right hand columns, + *\doublecolumns@* would have to be more complicated: +\setbox0\hbox{\<the *\else* part of old *\doublecolumns@* routine\>} +\setbox1\hbox{\<set *\dimen@* as before\>} +\setbox2\hbox{\<corresponding part of old *\doublecolumns@* routine\>} +\setbox3\hbox{\<add continuation lines,} +\setbox4\hbox{\ \ \ adjusting space using *\leftcoldepth@*\>} +\setbox5\hbox{\ \ \ adjusting space using *\prevcoldepth@*\>} +** +\newif\ifleftcol@ +\newdimen\leftcoldepth@ +"slip +\def\doublecolumns@{"box1 + \ifleftcol@ + \global\leftcolfalse@ + \ifleftcolbreak@ + \global\leftcoldepth@=\dp255 + "box2 + "copy3 + "box4 +"2 + \else + {\splittopskip=\topskip \splitmaxdepth=\maxdepth + \global\setbox1=\vsplit255 to\dimen@ + \global\prevcoldepth@=\dp1 } + \box1 \allowbreak + "copy3 + "box5 + \fi +"2 + \else + \global\leftcol@true + "box0 + \fi + \global\Ctype@=0 } +** + Thus, *\doublecolumns@* would +end up +being + called twice for each page, even if there was no column break in the left +column. +\endsmall + + + + +\section{\CS{balancecolumns\@}} +The *\balancecolumns@* routine basically +follows that of page~417 of {\it The \tex +book}, except that we have to be a little more careful about the final +glue (the routine in {\it The \tex\ book\/} was used for setting +{\it The \tex book}, where the balanced columns are then followed by +more material), and we also have to allow for a short last column. + +We begin with +** +\setbox0=\vbox{\unvbox255 \unskip} +\dimen@=\ht0 +** +using *\unskip* to completely eliminate *\vfill* that may have been +added by the *\bye* (this *\vfill* might not be there if the page break +actually occurs before the final line); this prevents the depth of *\box255* +from being counted in the height of *\box0*. + +Now we basically want to divide *\dimen@* by 2, and split *\box0* into +two pieces of that height. But we make a slight adjustment: +When we split *\box0* into two pieces, the top line of the second piece, +which currently has *\baselineskip* glue before it, should only get +*\topskip* glue. So we use +** +\advance\dimen@ by \topskip +\advance\dimen@ by -\baselineskip +\divide\dimen@ by 2 +** +---now *\dimen@* is the ideal height for the two pieces into which we +hope to split *\box0*. + +Then we set +** +\splittopskip=\topskip +** +and use a *\loop* for splitting. This *\loop* will operate inside a group +with *\vbadness=10000*, so that *Underfull \vbox*'es won't be reported +unless the columns are actually bad after the balancing act: +** +{\vbadness=10000 + \loop + \global\setbox3=\copy 0 + \global\setbox1=\vsplit3 to\dimen@ + \ifdim\ht3 > \dimen@ \global\advance\dimen@ by 1pt + \repeat} +** +Briefly, we try splitting to the ideal *\dimen@*, but if we can't get +two columns of the same height we want the left column to be the bigger; +so, if the right column turns out to be bigger, we keep increasing *\dimen@* +by 1~point until we get a split where the left column is at least as big as +the right column. +We always *\split* a copy of *\box0* rather than *\box0* itself, so that +*\box0* is always available for the next iteration of the *\loop*. + +We used *\global\advance* here because we need to know the final value of +*\dimen@*. But to keep assignments of *\dimen@* local, we will modify this +code to +** +\global\dimen@i=\dimen@ +{\vbadness=10000 + \loop + \global\setbox3=\copy 0 + \global\setbox1=\vsplit3 to\dimen@i + \ifdim\ht3 > \dimen@ \global\advance\dimen@i by 1pt + \repeat} +** +so that *\dimen@i* is the final dimension we are interested in. + + +Now we have to set each of +*\box0* and *\box2*, which will be used by\linebreak *\combinecolumns@*, +to a *\vbox to\dimen@i* (at this point we may get an *Underfull \vbox* +message): +** +\setbox0=\vbox to\dimen@i{\unvbox1} +\setbox2=\vbox to\dimen@i{\dimen@=\dp3 \unvbox3 + \ifshortlastcolumn@ \kern-\dimen@ \vfill\fi} +** +The second column, *\box2* is supplied with *\vfill* when we want +it to be short; as usual (compare page~\ref{KMPR} and~\ref{USEKMPR}), + a + *\kern* is required before the *\vfill* to prevent the depth of +the box from being counted as part of the height, possibly producing +a spurious *Overfull* box. + +The complete code is: +\CC** +\def\balancecolumns@{% + \setbox0=\vbox{\unvbox255 \unskip}% +"2 + \dimen@=\ht0 \advance\dimen@ by \topskip + \advance\dimen@ by -\baselineskip + \divide\dimen@ by 2 +"2 + \splittopskip=\topskip + \global\dimen@i=\dimen@ +"2 + {\vbadness=10000 + \loop +"2 + \global\setbox3=\copy 0 + \global\setbox1=\vsplit 3 to\dimen@i + \ifdim\ht3 > \dimen@i \global\advance\dimen@i by 1pt + \repeat}% +"2 + \setbox0=\vbox to\dimen@i{\unvbox1}% + \setbox2=\vbox to\dimen@i{\dimen@=\dp3 \unvbox3 + \ifshortlastcolumn@ \kern-\dimen@ \vfill\fi}% + \combinecolumns@} +** + +That completes all the routines from *lamstex.stb*, so we end, as in +*lamstex.tex* itself, with +\CC** +\def\alloc@#1#2#3#4#5{\global\advance\count1#1by\@ne + \ch@ck#1#4#2\allocationnumber\count1#1 + \global#3#5\allocationnumber + \wlog{\string#5\string#2\the\allocationnumber}} +\catcode`\@=\active +** + +\small +Balancing an index can be problematical because of final letters with only a +few entries. \pagelabel{CBBAL} + For example, an index might end +\bigskip +\setbox0\vbox{\hsize10pc + \centerline{\bf Z} +\vskip6pt +\leftline{zap,\enspace 13--18} +\leftline{$z$-axis,\enspace 12, 256, 300} +\leftline{zebra,\enspace 121} +\leftline{zed,\enspace 103, 105} +\leftline{Zen,\enspace iii, vi, 122} +\leftline{zenith,\enspace 97,103} +\leftline{zero,\enspace 11, 14, 56, 79} +\leftline{zero-sum,\enspace 118} +\leftline{zeta ($\zeta$),\enspace 133} +\leftline{zilch, {\it see\/} zero} +\leftline{zone,\enspace 204, 208} +\leftline{Zorn's lemma\enspace 112, 145} +} +\setbox1=\vbox to\ht0{\hsize10pc \advance\baselineskip 0pt plus2pt +\leftline{yak ({\it continued\/})} +\leftline{\quad habitat of,\enspace 124} +\leftline{yam,\enspace 124} +\leftline{yang,\enspace 187} +\leftline{$y$-axis,\enspace 89, 345} +\leftline{yclept,\enspace 102} +\leftline{yellow,\enspace 103} +\leftline{yellow fever,\enspace108} +\leftline{Yellow Pages,\enspace223} +\leftline{yeti,\enspace301} +\leftline{yin,\enspace186} +\leftline{yodel,\enspace224} +} +\line{\hfil\box1 \kern1pc\box0 \hfil} +\bigskip +\noindent with the first column *Underfull*. +This is the best *\vsplit*, for +if the left column were any +bigger it would have +to include the {\bf Z} and the space after it, and at +least one more line (not to mention all the extra space that would normally +go {\it before\/} the {\bf Z}). + + If we added a *\newcolumn* right before the *zebra* *\Entry* +in the *.xdx* file (and also specified *\shortlastcolumn*), +the output would look acceptable, +\bigskip +\setbox2\vtop{\hsize10pc +\leftline{zebra,\enspace 121} +\leftline{zed,\enspace 103, 105} +\leftline{Zen,\enspace iii, vi, 122} +\leftline{zenith,\enspace 97,103} +\leftline{zero,\enspace 11, 14, 56, 79} +\leftline{zero-sum,\enspace 118} +\leftline{zeta ($\zeta$),\enspace 133} +\leftline{zilch, {\it see\/} zero} +\leftline{zone,\enspace 204, 208} +\leftline{Zorn's lemma\enspace 112, 145} +} +\setbox3=\vtop{\hsize=10pc +\leftline{yak ({\it continued\/})} +\leftline{\quad habitat of,\enspace 124} +\leftline{yam,\enspace 124} +\leftline{yang,\enspace 187} +\leftline{$y$-axis,\enspace 89, 345} +\leftline{yclept,\enspace 102} +\leftline{yellow,\enspace 103} +\leftline{yellow fever,\enspace108} +\leftline{Yellow Pages,\enspace223} +\leftline{yeti,\enspace301} +\leftline{yin,\enspace186} +\leftline{yodel,\enspace224} +\vskip12pt +\centerline{\bf Z} +\vskip6pt +\leftline{zap,\enspace13--18} +\leftline{$z$-axis,\enspace 12, 256, 300} +} +\line{\hfil\box3 \kern1pc\box2 \hfil} +\bigskip +\noindent +although we would get *Overfull \vbox* messages +(the *\newcolumn* causes the *\output* routine to be invoked +while we still have *\output={\doublecolumns}*, so the left column +will be made into a *\vbox to\pageheight@*). + +If we added the *\newcolumn* before the +*\LETTER Z* +(and also had specified\linebreak *\shortlastcolumn*), we would get +\bigskip +\setbox0\vtop{\hsize10pc + \centerline{\bf Z} +\vskip6pt +\leftline{zap,\enspace13--18} +\leftline{$z$-axis,\enspace 12, 256, 300} +\leftline{zebra,\enspace 121} +\leftline{zed,\enspace 103, 105} +\leftline{Zen,\enspace iii, vi, 122} +\leftline{zenith,\enspace 97,103} +\leftline{zero,\enspace 11, 14, 56, 79} +\leftline{zero-sum,\enspace 118} +\leftline{zeta ($\zeta$),\enspace 133} +\leftline{zilch, {\it see\/} zero} +\leftline{zone,\enspace 204, 208} +\leftline{Zorn's lemma\enspace 112, 145} +} +\setbox1=\vtop{\hsize=10pc +\leftline{yak ({\it continued\/})} +\leftline{\quad habitat of,\enspace 124} +\leftline{yam,\enspace 124} +\leftline{yang,\enspace 187} +\leftline{$y$-axis,\enspace 89, 345} +\leftline{yclept,\enspace 102} +\leftline{yellow,\enspace 103} +\leftline{yellow fever,\enspace108} +\leftline{Yellow Pages,\enspace223} +\leftline{yeti,\enspace301} +\leftline{yin,\enspace186} +\leftline{yodel,\enspace224} +} +\line{\hfil\box1 \kern1pc\box0 \hfil} +\bigskip +\noindent (again with *Overfull \vbox* messages). + + +Of course, the most reasonable thing would probably be to add a +*\columnbreak* a little before the *yak* entry, so that the left column +on the final page would be a little longer. + +\endsmall + +\chapter The {\tt index} program\label{IPROG}\endchapter + +The *index* program takes the raw data in an *.ndx* file and creates +an *.xdx* file. Specifically, it is invoked as +\setbox0\hbox{\<filename\>} +** +index "box0 +** +to operate on \<filename\>*.ndx*, producing \<filename\>*.xdx*. +Among its many tasks, the *index* file essentially sorts entries +alphabetically. As indicated below, the *"1a{*\<string\>*}* + option is used to indicate +that for purposes of alphabetizing, the entry should be treated as if it were + \<string\>. + + +The *index* program +was originally written in Microsoft~C, for MS-DOS machines. Porting to other +machines will presumably be done by modifying this code. However, this +chapter presents the complete specifications for the *index* program, in case +any one wants to write it from scratch. + + +It should be pointed out that currently +the alphabetizing part of the program is essentially set up for +English spelling, with the presumption that ``foreign'' +words (e.g., those with accented letters) + will be given an *"1a{*\<string\>*}* option. There should obviously +be versions (or perhaps switches) +for other languages that will provide +transparent alphabetizing for words in those languages, so that the *"1a* +option will only be needed for words that are ``foreign'' to those languages. + +It might also +be mentioned that the current version of the program specifically +assumes that the final line ends with a \<carriage-return\>, which should be +true of the *.ndx* files that \tex\ writes. Some systems might want to +modify this assumption. + +\def\controlseq{\hbox{\rm\<control sequence\>}} + +\section{The {\tt.ndx} file} +The *.ndx* file may contain certain lines +** +\define"controlseq . . . +** +that come from *\idefine*'s in the main file, as well as certain lines +** +\abbrev"1"controlseq{...} +** +that come from *\iabbrev*'s in the main file. Moreover, as explained on +page~113 of the \lamstex~Manual, a sequence of commands of the form +\setbox0\hbox{\<pre page material\>} +\setbox1\hbox{\<post page material\>} +\setbox2\hbox{\<order\>} +** +"hskip-40pt\pageorder"controlseq{"box0}{"box1}{"box2} +** +may have been inserted +at the very beginning of the +*.ndx* file (after the *.ndx* file was automatically made by \tex); +here each \controlseq\ is some + numbering style command, and the \<order\>'s are +*1*, *2*, *3*, \dots, in that sequence. + + +Aside from this, the *.ndx* file +should consist of pairs of lines +\setbox0\hbox{\<entry\>} +\setbox1\hbox{\<options\>} +\setbox2\hbox{\<number\>} +\setbox3\hbox{*\controlseq*} +\setbox4\hbox{\<prefix\>} +\setbox5\hbox{\<postfix\>} +** +"""box0"box1"" +{"box2}{"controlseq}{"box4}{"box5} +** +where \<number\> is a decimal number, \controlseq\ is some numbering +style +control sequence + (followed by a space, because \tex\ will always add the +space when it writes to the *.ndx* file), + and \<prefix\> and \<postfix\> are arbitrary, possibly +empty, strings. The \controlseq\ is normally `*\arabic" *'. + +Actually, the *index* program as currently written does not assume +that *""* is the delimiter +appearing at the beginning and end of the \<entry\> lines. It is +perfectly legitimate (compare section~\Sref{OTHERD}) +to have something like +\setbox0\hbox{\<entry\>} +\setbox1\hbox{\<options\>} +\setbox2\hbox{\<number\>} +\setbox3\hbox{*\controlseq*} +\setbox4\hbox{\<prefix\>} +\setbox5\hbox{\<postfix\>} +** +<"box0"box1> +{"box2}{"controlseq}{"box4}{"box5} +** +Any left delimiter other than *{* or *\* may be used; +the *index* program takes the \<entry\>\<option\> +combination to be everything between the first +symbol and the last non-space symbol on the line. + + +Each \<entry\> has one of the forms +\setbox1\hbox{\<entry\>$_{\text1}$} +\setbox2\hbox{\<entry\>$_{\text2}$} +\setbox3\hbox{\<entry\>$_{\text3}$} +\setbox4\hbox{\<entry\>$_{\text4}$} +\setbox5\hbox{\<entry\>$_{\text5}$} +** +"copy1 +"copy1, "copy2 +"copy1, "copy2, "copy3 +"copy1, "copy2, "copy3, "copy4 +"copy1, "copy2, "copy3, "copy4, "copy5 +** + +The \<options\> are a possibly empty sequence of + the following types of entries, where \<n\> +stands for *2*, *3*, *4* or *5*. Actually, *1* is also allowed, but simply +treated as if the *1* weren't there. +There are optional spaces between such +entries, including an optional space at the beginning and end of the +\<options\>: +\Math +\vcenter{\halign{#\hfil&\qquad#\hfil\cr + *"1a{*\<string\>*}*&(alphabetize as)\cr + *"1*\<*n*\>*a{*\<string\>*}*&(same for subentry at level \<*n*\>)\cr + *"1-{*\<string\>*}*&(print before entry)\cr + *"1*\<*n*\>*-{*\<string\>*}*&(same for subentry at level \<*n*\>)\cr + *"1+{*\<string\>*}*&(print after entry)\cr + *"1*\<*n*\>*+{*\<string\>*}*&(same for subentry at level \<*n*\>)\cr + *"1e*\<control sequence\>&(apply control sequence to entry)\cr + *"1*\<*n*\>*e*\<control sequence\>&(same for subentry at level \<*n*\>)\cr + *"1p*\<control sequence\>&(apply control sequence to page number)\cr + *"1f*&(begin page span)\cr + *"1F*&(begin page span, variant form)\cr + *"1t*&(end page span)\cr + *"1x{*\<string\>*}*&(cross reference as)\cr + *"1X{*\<string\>*}*&(list and cross reference as)\cr}} +\endMath + +In each +** +\abbrev"1"controlseq{...} +** +line, the `*...*' string should also be a sequence of these possible options, +and error messages should be given if it is not, or if *\abbrev* is otherwise +used incorrectly. + +The *"1x* and *"1X* options are meant to be mutually exclusive, so an error +message should be given if both occur in the same \<options\> list. + + + +\section{The {\tt index} program} +Here now are the steps taken by the *index* program. + +\medskip + +\noindent({\bf I}) {\bf Preprocessing:} + +\smallskip + +(1) The *index* program first uses any *\pageorder* lines at the beginning, +\setbox1\hbox{$_{\text1}$} +\setbox2\hbox{$_{\text2}$} +\setbox3\hbox{pre\copy1} +\setbox4\hbox{post\copy1} +\setbox5\hbox{pre\copy2} +\setbox6\hbox{post\copy2} +** +\pageorder"controlseq"copy1{"copy3}{"copy4}1 +\pageorder"controlseq"copy2{"copy5}{"copy6}2 + . . . +** +to +set up an ordering for arrays of the form +\setbox2\hbox{\<number\>} +\setbox3\hbox{\<controlseq\>} +\setbox4\hbox{\<prefix\>} +\setbox5\hbox{\<postfix\>} +** +{"box2} {"controlseq} {"box4} {"box5} +** +Namely, all arrays +\setbox1\hbox{$_{\text1}$} +\setbox2\hbox{$_{\text2}$} +\setbox3\hbox{pre\copy1} +\setbox4\hbox{post\copy1} +\setbox5\hbox{pre\copy2} +\setbox6\hbox{post\copy2} +\setbox7\hbox{\<number\>} +** +{"copy7}{"controlseq"copy1}{"copy3}{"copy4} +** +come first, with the ordering then determined by the \<number\>'s, +all arrays +** +{"copy7} {"controlseq"copy2} {"copy5} {"copy6} +** +come next, \dots. All other arrays come after these, and are simply ordered +first by the order of the \<number\>, and then purely alphabetically by +the remaining fields. + +Error messages presumably +ought to be given if any *\pageorder* line has the wrong +form, if the \<order\>'s don't occur in the proper order, or if two different +\<order\>'s are assigned to identical material. + +(2) Next we consider all lines +** +\abbrev"1"controlseq{...} +** +(which may appear anywhere in the *.ndx* file). + +In each case, any +occurrence of *"1"controlseq* in any entry line is replaced by +`*...*'; then the *\abbrev* lines are eliminated. + + +(3) All *\define* lines anywhere in the *.ndx* file are stored +in a safe place, before being removed; they will be written at the beginning +of the *.xdx* file. + +\medskip + +\noindent({\bf II}) {\bf Sorting:} + +\medskip + +\def\1{$_{\text1}$}\def\5{$_{\text2}$} +\def\3{$_{\text3}$}\def\4{$_{\text4}$}\def\5{$_{\text5}$} +\def\n{$_{\text\it n}$} + +\def\entrybar{$\overline{\hbox{\rm entry}}$} + + +(1) For each +\setbox0\hbox{\<entry\>} +\setbox1\hbox{\<options\>} +** +"""box0"box1"" +** +line, +if *"1a{*\<string\>*}* appears, replace \<entry\1\> by \<string\>, +and define \<\entrybar\1\> to be the old \<entry\1\>. + Otherwise define +\<\entrybar\1\> to be empty. + +Similarly, if +*"1*\<*n*\>*a{*\<string\>*}* appears, replace \<entry\n\> by \<string\>, +and define \<\entrybar\n\> to be the old + \<entry\n\>. Otherwise define \<\entrybar\n\> +to be empty. + + + +\setbox0\hbox{\<entry\>} +\setbox1\hbox{\<options\>} +\setbox2\hbox{\<number\>} +\setbox3\hbox{*\nstyle*} +\setbox4\hbox{\<prefix\>} +\setbox5\hbox{\<postfix\>} + +\smallskip + +(2) Each pair of lines +** +"""box0"box1"" +{"box2}{"controlseq}{"box4}{"box5} +** +now gives rise to a collection $\Cal F$ of fields: + +*E1* is \<entry\1\> followed by one space. + +*E1+* is empty unless *"1-{*\<string\>*}* appears, in which case it is +\<string\> followed by one space (note that +\<string\> may already have one space at +the end). + +*E1-* is empty unless *"1+{*\<string\>*}* appears, in which case it is +\<string\> followed by one space. + +*E2* is \<entry\5\> followed by one space (hence just a space if +\<entry\5\> is empty). + +*E2-* is empty unless *"12-{*\<string\>*}* appears, in which case it is +\<string\> followed by one space. + +*E2+* is empty unless *"12+{*\<string\>*}* appears, in which case it is +\<string\> followed by one space. + +*E3*, *E3+*, *E3-*, \dots, *E5*, *E5+*, *E5-* are similar. + +*P#* is \<number\>. + +*Pn* is \controlseq\ (usually `*\arabic" *'). + +*P-* is the \<prefix\>. + +*P+* is the \<postfix\>. + +\def\EE{$\overline{\hbox{\tt E}}$} + +*"EE1*, \dots, *"EE5* are \<\entrybar\1\>, \dots, \<\entrybar\5\>. + +*E1c* is empty unless *"1e*\<control sequence\> appears, in which case it +is \<control sequence\>, followed by one space. + +*E2c* is empty unless *"12e*\<control sequence\> appears, in which case it +is \<control sequence\>, followed by one space. + +*E3c*, *E4c*, *E5c* are similar, using *"13e*, *"14e* and *"15e*. + +*Pc* is empty unless *"1p*\<control sequence\> appears, in which case it +is \<control sequence\>, followed by one space. + +*PT* (page type) is *f* if *"1f* appeared, *F* if *"1F* appeared, *t* +if *"1t* appeared, and *s* (for single page) otherwise. + +*x* is empty unless *"1x{*\<string\>*}* appears, in which case it is +\<string\>, followed by one space. + +*X* is empty unless *"1X{*\<string\>*}* appears, in which case it is +\<string\>, followed by one space. + + +\medskip +(3) +We first sort these collections $\Cal F$ +alphabetically on *E1*, then among those with +identical *E1* on *E1-*, then on *E1+*, then on *E2*, \dots, *E5+*. +If we ignore the *-* and *+* fields for the moment, +this just alphabetizes the entries and subentries. + The spaces that were added after each +\<entry\n\> are meant to ensure that these entries are really sorted +alphabetically; for example, it produces the order +** +Time +Time table +Time tables +Times +Times tables +** +which will eventually appear in the index as +\bigskip\begingroup\parindent0pt\parskip0pt +\hskip30pt Time\par\nobreak +\hskip30pt \hskip10pt table\par\nobreak +\hskip30pt \hskip10pt tables\par\nobreak +\hskip30pt Times\par\nobreak +\hskip30pt \hskip10pt tables\par\nobreak +\endgroup\bigskip + + +The other fields, *E1-*, *E1+*, \dots, allow entries with +additional elements to appear in the proper order. For example, for the entry +** +""Time "1-{``} "1+{''}"" +** +*E1* is *Time* and *E1-* is *``*. This +will come after the entry line +** +""Time"" +** +where *E1* is also *Time* but *E1-* is empty, + so that we will obtain the order +\bigskip\begingroup\parindent0pt\parskip0pt +\hskip30pt Time\par\nobreak +\hskip30pt ``Time''\par +\endgroup\bigskip +\noindent in the index. + + +After using these fields for sorting, we next use the fields +** +P# Pn P- P+ +** +where + the sorting order for these arrays +is just that described in step (1) of ({\bf I}). + +There may be certain collections $\Cal F$ that are distinct, but agree for +all the fields so far. They can be left in any order, say the order in which +they appear in the *.ndx* file, or further sorted purely alphabetically +according to the remaining fields *"EE1*, \dots, *"EE5*, *E1c*, \dots, +*E5c* and *Pc*. + +The *PT*, *x* and *X* + fields are important for further processing, but need not be +considered in the sorting. + +After the sorting is completed, the additional spaces added to various fields +are no longer needed, and they are deleted in the next step. + +\medskip + + +\noindent ({\bf III}) {\bf Writing the *.xdx* file:} +\medskip + +(1) First, as indicated in step (3) of part ({\bf I}), all *\define* lines +originally in the *.ndx* file are written to the *.xdx* file. + +(2) The remaining material in the *.xdx* file will be in sections, each +preceded by a blank line, then a line +** +\LETTER ... +** +and then another blank line. +The line +** +\LETTER A +** +will normally be the first of these, and will precede all entries that begin +with *a* or *A*; +** +\LETTER B +** +will precede all entries that begin with *b* or *B*; etc. No such line +appears for a letter if there are no entries beginning with this +letter. Things like \hbox{*\LETTER !*} can appear if entries begin with +~ *!* (though normally one would expect the *"1a* option to be used for such +entries). + + + +(2) In most cases, +each collection $\Cal F$ gives rise to a pair of lines in the *.xdx* +file: +\def\di{{\it d}$_{\text1}$} +\def\dii{{\it d}$_{\text2}$} +** +\Entry "di"dii{...}{...}{...}{...}{...} +\Page {...} +** +except that if several collections have the exact same *\Entry* line, then +the corresponding *\Page* lines are listed under it in order, with +modifications to be mentioned in a minute, involving +the *PT*, *x* and *X* fields. + +For the first *{...}* in the *\Entry* line, `*...*' is +\def\F#1.{\hbox{\rm\<field #1\>}} +** +{E1-}{E1c{E1}}{E1+} +** +except that *E1* is replaced by *"EE1* +if this is non-empty. + +Note that there are braces around *E1* (or *"EE1*) +so that it will be the +argument of the control sequence *E1c*. However, these braces are +omitted if *E1c* is empty. Moreover, +all other unnecessary +braces are omitted: the first set of braces is omitted if *E1-* is +empty, the third set is omitted if *E1+* is empty, and the middle set is +also omitted if both are empty. + (Remember that this entire sequence, with +extraneous braces removed, is enclosed in the first set of braces in the +*\Entry* line.) + +The second *{...}* in the *\Entry* line is similar, using fields +*E2-*, *E2c*, *E2* and *E2+*. And similarly for the other groups. + + +\di\ is the number of *{...}* that are non-empty, i.e., not of the form +*{}*. + +\dii\ is the number of *{...}* {\it that agree with the most recent *\Entry* +line}. + +\medskip + + +Normally, +the *\Page* lines have the form +\def\FF{$\overline{\hbox{\rm\<field 17\>}}$} +** +\Page {Pc{{P-}{Pn{P#}}{P+}}} +** +But *Pn* is omitted when it is `*\arabic" *' (the usual case). + Moreover, superfluous braces are removed, as before, when +fields are empty. + +Duplicate *\Page* lines for the same entry are eliminated. But if +duplicates actually come from lines for which *Pc* is different, then +each *\Page* line after the first is printed as +{\advance\litindent-60pt +** +%% //////////////////////////////////////////////////////////////////////// +% +% \Page {Pc}{...}} +% Duplicate page number formatted differently +% +%% \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ +** +where *Pc* is the control sequence for that line. For readability, +there should be +a blank line before and after this ``error message'' +(the current version of the *index* +program actually prints things slightly differently).} + + +When *PT* is *f*, however, *\Page* is replaced by *\Pagespan*. And +if *PT* is *F*, then *\Page* is replaced by *\PageSpan*; moreover, the +line is then written in the form +** +\PageSpan {Pc}{{P-}{Pn{P#}}{P+}} +** +with the *Pc* as a separate argument. + Extraneous braces are removed, as usual. + +When *PT* is *t*, *\Page* is replaced by *\Topage*. However, if it was +preceded by a line for which *PT* is *F*, then once again we write +** +\Topage {Pc}{{P-}{Pn{P#}}{P+}} +** +with the *Pc* as a separate argument. + +When a *\Page* line for which *PT* is *s* is encountered between lines +for which *PT* is *f* or *F* and the corresponding line for which *PT* is +*t*, it is ignored, {\it unless it has\/} a different *Pc*. In this case +the new *\Page* line is printed as the error message +{\advance\litindent-60pt +\setbox0\hbox{new} +\setbox1\hbox{old} +** +%% //////////////////////////////////////////////////////////////////////// +% +% \Page {"copy0 Pc{...}} +% Page {"copy0 Pc{...}} within span starting at "copy1 Pc{...} +% +%% \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ +** + +Other such error} messages that should be issued +are indicated on pages 118@--119 of the \lamstex~ Manual. + + +\bigskip +This description is complete only +for entries that do not have an *"1x* or *"1X* option. For entries that do +have these options, the processing is somewhat different. +Recall that +*"1x* indicates a cross-reference without a reference to the page on +which the entry is marked, while *"1X* indicates a cross-reference together +with a reference to the page. + +The situation where at least one occurrence of \<entry\> has an *"1x* or +*"1X* option can happen in different ways: + +\medskip + +\noindent Case 1: Every occurrence of the \<entry\> involves *"1x* (and thus + not + *"1X*): +\setbox0\hbox{\<entry\>} +\setbox1\hbox{\<string\1\>} +\setbox2\hbox{\<string\5\>} +\setbox3\hbox{\<string\3\>} +** +"copy0 ... "1x{"copy1} +"copy0 ... "1x{"copy2} +"copy0 ... "1x{"copy3} +** +In this case the *.xdx* file +should contain +** +\Entryxref "di"dii{...}{...}{...}{...}{...}{\See {"copy1}} +\Morexref {\See {"copy2}} + . . . +** + +\medskip + +\noindent Case 2: The opposite case, in which at least one of the following +occurs: + +(1) \<entry\> occurs at least once with the *"1X* option, so that the +corresponding page number should appear. Other occurrences of \<entry\> + may or may not have +*"1x* options. + +(2) \<entry\> occurs at least once with {\it neither\/} *"1x* nor *"1X*, and +thus there is at least one page number that should appear because no +cross-referencing is involved at all. Other occurrences of \<entry\> may have +either *"1x* or *"1X* options. + +\smallskip +In these cases, +let \<string\1\>, \<string\5\>, \dots, be all the \<string\>'s, in +alphabetical order, that +occur in either *"1x* or *"1X* options, and +let +** +\Page {...} +\Page {...} + . . . +\Page {...} +** +be the lines that would be written considering all instances that do not +involve the *"1x* option (but possibly the *"1X* option). These lines +may actually involve *\Pagespan*, *\PageSpan* and *\Topage*. + + +Then the *.xdx* file should contain +\setbox1\hbox{\<string\1\>} +\setbox2\hbox{\<string\5\>} + +** +\Entry "di"dii{...}{...}{...}{...}{...} +\Xref {\See {"copy1}} +\Morexref {\See {"copy2}} + . . . +\Page {...} +\Page {...} + . . . +\Page {...} +\Xref {\See {"copy1}} +\Morexref {\See {"copy2}} + . . . +** + + + + |