\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 \ 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{\} \setbox2\hbox{\} ** \HL {1}{"copy1}{"box2} "8HLILLUS"8 . . . \Page ... ** and/or entries like \setbox0\hbox{and} \setbox1\hbox{\} \setbox2\hbox{\} ** \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 \. 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{\} \setbox1\hbox{\} \setbox3\hbox{\} \setbox2\hbox{\} ** \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 {*\*}* occurs for any \${}\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{\} \setbox2\hbox{\} \setbox3\hbox{\} \setbox4\hbox{\} ** \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}{}), \ will be ** \bf\ignorespaces#4\unskip ** \ will be *\dotleaders*, and \ will be ** \Page@{#5}{#6}{#7}{#8} ** As for \, it will essentially be \setbox0\hbox{\} ** \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 \ *#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 \, 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{\} ** \chapter {"box0}{2} . . . \Page... ** will typeset the same thing as \setbox0\hbox{\} ** \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{\
} \setbox1\hbox{\} ** \Figure {"box0} "copy1 \Page ... ** in the *.tic* file will translate to \setbox0\hbox{\
} \setbox1\hbox{\} \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{\} ** \island \c{M}{Map}{"box0} ** will be regarded as \setbox0\hbox{\} ** \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 \
, and *#5* is the \. 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 \ before the \
; \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{\} \setbox1\hbox{\} ** \map {"box0} "box1 \Page ... ** should translate to \setbox0\hbox{\} \setbox1\hbox{\} ** \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 \ 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 \ 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{\} ** \def\makeindex{\checkmainfile@\par\vfill\break \begingroup "box0 "box1 \hsize=3in ** Of course all *#*'s in any of those \ 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{\} \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 \ 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{\} ** \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{\} ** \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{\} \setbox1\hbox{\} \setbox2\hbox{\} \setbox3\hbox{\} \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{\} ** index "box0 ** to operate on \*.ndx*, producing \*.xdx*. Among its many tasks, the *index* file essentially sorts entries alphabetically. As indicated below, the *"1a{*\*}* option is used to indicate that for purposes of alphabetizing, the entry should be treated as if it were \. 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{*\*}* 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 \, which should be true of the *.ndx* files that \tex\ writes. Some systems might want to modify this assumption. \def\controlseq{\hbox{\rm\}} \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{\
}
\setbox1\hbox{\}
\setbox2\hbox{\}
**
"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 \'s are
*1*, *2*, *3*, \dots, in that sequence. 


Aside from this, the *.ndx* file
should consist of pairs of lines
\setbox0\hbox{\}
\setbox1\hbox{\}
\setbox2\hbox{\}
\setbox3\hbox{*\controlseq*}
\setbox4\hbox{\}
\setbox5\hbox{\}
**
"""box0"box1""
{"box2}{"controlseq}{"box4}{"box5}
**
where \ 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 \ and \ 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 \ lines.  It is
perfectly legitimate (compare section~\Sref{OTHERD})
to have something like
\setbox0\hbox{\}
\setbox1\hbox{\}
\setbox2\hbox{\}
\setbox3\hbox{*\controlseq*}
\setbox4\hbox{\}
\setbox5\hbox{\}
**
<"box0"box1>
{"box2}{"controlseq}{"box4}{"box5}
**
Any left delimiter other than *{* or *\* may be used;
the *index* program takes the \\
combination to be everything between the first
symbol and  the last non-space symbol on the line.


Each \ has one of the forms
\setbox1\hbox{\$_{\text1}$}
\setbox2\hbox{\$_{\text2}$}
\setbox3\hbox{\$_{\text3}$}
\setbox4\hbox{\$_{\text4}$}
\setbox5\hbox{\$_{\text5}$}
**
"copy1
"copy1, "copy2
"copy1, "copy2, "copy3
"copy1, "copy2, "copy3, "copy4
"copy1, "copy2, "copy3, "copy4, "copy5
**

The \ are a possibly empty sequence of
 the following types of entries, where \
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
\:
\Math
\vcenter{\halign{#\hfil&\qquad#\hfil\cr
 *"1a{*\*}*&(alphabetize as)\cr
 *"1*\<*n*\>*a{*\*}*&(same for subentry at level \<*n*\>)\cr
 *"1-{*\*}*&(print before entry)\cr
 *"1*\<*n*\>*-{*\*}*&(same for subentry at level \<*n*\>)\cr
 *"1+{*\*}*&(print after entry)\cr
 *"1*\<*n*\>*+{*\*}*&(same for subentry at level \<*n*\>)\cr
 *"1e*\&(apply control sequence to entry)\cr
 *"1*\<*n*\>*e*\&(same for subentry at level \<*n*\>)\cr
 *"1p*\&(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{*\*}*&(cross reference as)\cr
 *"1X{*\*}*&(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 \ 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{\}
\setbox3\hbox{\}
\setbox4\hbox{\}
\setbox5\hbox{\}
**
{"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{\}
**
{"copy7}{"controlseq"copy1}{"copy3}{"copy4}
**
come first, with the ordering then determined by the \'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 \, 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 \'s don't occur in the proper order, or if two different
\'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{\}
\setbox1\hbox{\}
**
"""box0"box1""
**
line,
if *"1a{*\*}* appears, replace \ by \,
and define \<\entrybar\1\> to be the old \.
 Otherwise define
\<\entrybar\1\> to be empty.

Similarly, if
*"1*\<*n*\>*a{*\*}* appears, replace \ by \,
and define \<\entrybar\n\> to be the old
 \. Otherwise define \<\entrybar\n\> 
to be empty.



\setbox0\hbox{\}
\setbox1\hbox{\}
\setbox2\hbox{\}
\setbox3\hbox{*\nstyle*}
\setbox4\hbox{\}
\setbox5\hbox{\}

\smallskip

(2) Each pair of lines
**
"""box0"box1""
{"box2}{"controlseq}{"box4}{"box5}
**
now gives rise to a collection $\Cal F$ of fields:

*E1* is \ followed by one space.

*E1+* is empty unless *"1-{*\*}* appears, in which case it is
\ followed by one space (note that
\ may already have one space at
the end).

*E1-* is empty unless *"1+{*\*}* appears, in which case it is
\ followed by one space.

*E2* is \ followed by one space (hence just a space if
\ is empty).

*E2-* is empty unless *"12-{*\*}* appears, in which case it is
\ followed by one space.

*E2+* is empty unless *"12+{*\*}* appears, in which case it is
\ followed by one space.

*E3*, *E3+*, *E3-*, \dots, *E5*, *E5+*, *E5-* are similar.

*P#* is \.

*Pn* is \controlseq\ (usually `*\arabic" *').

*P-* is the \.

*P+* is the \.

\def\EE{$\overline{\hbox{\tt E}}$}

*"EE1*, \dots, *"EE5* are  \<\entrybar\1\>, \dots, \<\entrybar\5\>.

*E1c* is empty unless *"1e*\ appears, in which case it
is \, followed by one space.

*E2c* is empty unless *"12e*\ appears, in which case it
is \, followed by one space.

*E3c*, *E4c*, *E5c* are similar, using *"13e*, *"14e* and *"15e*.

*Pc* is empty unless *"1p*\ appears, in which case it
is \, 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{*\*}* appears, in which case it is
\, followed by one space.

*X* is empty unless *"1X{*\*}* appears, in which case it is
\, 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
\ 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\}}
**
{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\}}$}
**
\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 \ has an *"1x* or
*"1X* option can happen in different ways:

\medskip

\noindent Case 1: Every occurrence of the \ involves *"1x* (and thus
 not
 *"1X*):
\setbox0\hbox{\}
\setbox1\hbox{\}
\setbox2\hbox{\}
\setbox3\hbox{\}
**
"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) \ occurs at least once with the *"1X* option, so that the
corresponding page number should appear.  Other occurrences of \
 may or may not have
*"1x* options.

(2) \ 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 \ may have
either  *"1x* or *"1X* options.

\smallskip
In these cases, 
let \, \, \dots, be all the \'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{\}
\setbox2\hbox{\}

**
\Entry "di"dii{...}{...}{...}{...}{...}
\Xref {\See {"copy1}}
\Morexref {\See {"copy2}}
 . . .
\Page {...}
\Page {...}
 . . . 
\Page {...}
\Xref {\See {"copy1}}
\Morexref {\See {"copy2}}
 . . .
**