%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Module: ZzTeX Indexing Facilities, version 1 % % Synopsis: This file contains the tools for producing an index. % % Author: Paul C. Anagnostopoulos % Created: 20 May 2006 % % Copyright 1989--2020 by Paul C. Anagnostopoulos % under The MIT License (opensource.org/licenses/MIT) % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Index Version % ----- ------- \def \indexversion #1{% \input zzindexv#1\relax} % Define Index Locator Types % ------ ----- ------- ----- % This list contains the definition of each locator. New ones must be % added to the end, and any program looking at the definitions must assume % that duplicates may exist, and that the last one prevails. \def \zixloclist {} %~ This command is deprecated in favor of |\definelocator|. \def \definelocatortype #1#2#3#4#5#6{% {name}{attributes}{precedence} % {beginning-punc}{templates} % {ending-punc} {\setflag \pg = \true \let \page = \relax \def \nopage {\setflag \pg = \false}% \setflag \txt = \false \def \text {\setflag \txt = \true}% \let \notext = \relax #2% \def \bpunc {#4}% \def \temp {#5}% \def \epunc {#6}% \edef \znext {% \noexpand\append{{#1}{\pg}{\txt}{#3}% {\expandafter\zdefof \meaning\bpunc\zmark}% {\expandafter\zdefof \meaning\temp\zmark}% {\expandafter\zdefof \meaning\epunc\zmark}}}% \znext{\zixloclist}% \if \txt \withname\gdef{\x#1}##1##2{\zixindex{#1}{##1}{S}{##2}}% \if \pg \withname\gdef{\x#1begin}##1##2{\zixindex{#1}{##1}{B}{##2}}% \withname\gdef{\x#1end}##1##2{\zixindex{#1}{##1}{E}{##2}}% \fi \else \withname\gdef{\x#1}##1{\zixindex{#1}{##1}{S}{}}% \if \pg \withname\gdef{\x#1begin}##1{\zixindex{#1}{##1}{B}{}}% \withname\gdef{\x#1end}##1{\zixindex{#1}{##1}{E}{}}% \fi \fi}} % This command is deprecated. \def \defineindexlocator #1#2#3#4#5#6{% {name}{attributes}{precedence} % {punctuation}{single-template} % {range-template} } % Builtin Locator Types % ------- ------- ----- % Precedences 0--1 and 6--9 are reserved for specific books. \definelocatortype{term}{\page\notext}{2.3} {, |}{\bold{~P}|\bold{~P--~Q}|, }{. |} \definelocatortype{biblio}{\page\notext}{2.5} {, |}{~P|~P--~Q|, }{. |} \definelocatortype{cite}{\page\notext}{2.5} {, |}{~P|~P--~Q|, }{. |} \definelocatortype{page}{\page\notext}{2.5} {, |}{~P|~P--~Q|, }{. |} \definelocatortype{figure}{\page\notext}{2.7} {, |}{~P\+\emph{f}|~P--~Q\+\emph{f}|, }{. |} \definelocatortype{glossary}{\page\notext}{2.7} {, |}{~P\+\emph{g}|~P--~Q\+\emph{g}|, }{. |} \definelocatortype{note}{\page\notext}{2.8} {, |}{~P\+\emph{n}|~P--~Q\+\emph{n}|, }{. |} \definelocatortype{sidebar}{\page\notext}{2.7} {, |}{~P\+\emph{s}|~P--~Q\+\emph{s}|, }{. |} \definelocatortype{table}{\page\notext}{2.7} {, |}{~P\+\emph{t}|~P--~Q\+\emph{t}|, }{. |} \definelocatortype{see}{\nopage\text}{3} {. |\See\ }{~T||; }{. |} \definelocatortype{seealso}{\nopage\text}{4} {. |\Seealso\ }{~T||; }{. |} \definelocatortype{consult}{\nopage\text}{5} {. |\Consult\ }{~T||; }{. |} % Index Preparation File % ----- ----------- ---- % The \produceindex command must appear before the \document command. \setflag \zindexing = \false \def \produceindex #1#2{% {type}{prep-file} {\processdesign{\index}{#1}% \immediate\openout \zwritea = #2.zzh\relax \immediate\write \zwritea {root \jobname}% \immediate\write \zwritea {type #1}% \immediate\write \zwritea {divisions {\the\divisions}}% \immediate\write \zwritea {locators {\the\locators}}% \immediate\write \zwritea {\the\indexparams}% \maplist{\immediate\write \zwritea {define-locator ##1}}{\zixloclist}% \immediate\closeout \zwritea}% \global\setflag \zindexing = \true} % Index File Handling % ----- ---- -------- \definewrite{\zixrootfile} \definewrite{\zixdivfile} \setflag \zixdivopen = \false \def \zindexinit {% \if \zindexing \immediate\openout \zixrootfile = \jobname.zzi\relax \immediate\write \zixrootfile {\zcomment Raw index entry file for book `\jobname'.}% \fi} \def \zindexfinal {% \if \zindexing \immediate\write \zixrootfile {\zcomment [end]}% \immediate\closeout \zixrootfile \fi} \def \zindexdivinit #1{% {division} \if \zindexing \immediate\openout \zixdivfile = #1.zzi\relax \immediate\write \zixdivfile {\zcomment Raw index entry file for book `\jobname', division `#1'.}% \global\setflag \zixdivopen = \true \fi} \def \zindexdivfinal {% \if \zixdivopen \immediate\write \zixdivfile {\zcomment [end]}% \immediate\closeout \zixdivfile \global\setflag \zixdivopen = \false \fi} % Generate Index Entry % -------- ----- ----- % This macro is called from the indexing macros generated by % \definelocatortype. \def \zixindex #1#2#3#4{% {locator}{level}{page-code}{text} \tcounta = #2\relax \if \notp{\rangep{\tcounta}{1}{3}}% \error{invindexlvl}{Invalid index level '#2' specified}% \tcounta = 1 \fi \name{\zixindex\romannumeral\tcounta}{#1}{#2}{#3}{#4}} \def \zixindexi #1#2#3#4#5{% \zixindexw{#1}{#2}{#3}{#4}{#5}{}{}{\noexpand\folio}} \def \zixindexii #1#2#3#4#5#6{% \zixindexw{#1}{#2}{#3}{#4}{#5}{#6}{}{\noexpand\folio}} \def \zixindexiii #1#2#3#4#5#6#7{% \zixindexw{#1}{#2}{#3}{#4}{#5}{#6}{#7}{\noexpand\folio}} \catcode"B8 = \catother \gdef \zixindexw #1#2#3#4#5#6#7#8{% {locator}{level}{page-code}{text} % {heading1}{heading2}{heading3}{page} \if \notp{\zindexing}% \warning{notindexing}{An indexing command was encountered, but no \string\produceindex}% \fi \zbeginhidewrite \def \zhdx {#5}% \def \zhdy {#6}% \def \zhdz {#7}% \def \ztxt {#4}% \edef \znext {#1^^b8% #2^^b8% \expandafter\zdefof \meaning\zhdx\zmark^^b8% \expandafter\zdefof \meaning\zhdy\zmark^^b8% \expandafter\zdefof \meaning\zhdz\zmark^^b8% #3^^b8% #8^^b8% \expandafter\zdefof \meaning\ztxt\zmark}% \write \if \zixdivopen \zixdivfile \else \zixrootfile \fi \expandafter{\znext}% \if \vmodep \repeatpenalty \fi % In case glue follows write. \zendhidewrite} \catcode"B8 = \catinvalid % Discussion of Index Formatting % ---------- -- ----- ---------- % An index is formatted inside an index block, which is more or less % like a text block. Within the index block are occurences of the % \indexentry macro, one for each entry. In addition, the % \alphabreak macro can be used to produce breaks preceding the `A' % entries, `B' entries, etc. % % In an index block, parts 4 and 5 of the mark are used to remember % index entries so they can be carried forward to subsequent columns % or pages. The mark is used as follows: % % Part Subpart Usage % 4 1 Boolean, true if in the midst of a first-level entry. % 4 2 The first-level entry text. % 5 1 Boolean, true if in the midst of a second-level entry. % 5 2 The second-level entry text. % Index Block % ----- ----- \defineblock{\index}{\endindex}{\false}{} %~block index Type % \def \alphaformat ##1{...} % Alpha break formatter. % \bodyfont = {\size\style} % Body font. % \clubpenalty = penalty % Club penalty is often different. % \columngutter = glue % Column gutter. % \divisions = {...} % Which divisions to include. % \leftindent = glue % Left indentation. % \locators = {...} % Which locators to include. % \indexparams = {...} % Parameters for index generator. % \parhang = glue % Paragraph hang. % \parindent = dimen % Paragraph indent. % \parrag = dimen % Paragraph raggedness. % \parskip = glue % Paragraph skip. % \position = {...} % Position and number of columns. % \rightindent = glue % Right indentation. %~end \definetoks{\locators} \definetoks{\indexparams} \definecount{\previndexlevel}{0} \definecount{\zixcols}{0} \def \index #1{% {type} \blockcantbein{\index}{\index}% \beginblockscope{index}% \global\increment \indexdepth \clubpenalty = \breakallowed %~default soft \parskip = 0pt %~default soft \processdesign{\index}{#1}% \global\increment \indexnumber \def \zixtype {#1}% \zixparsepos \indexformat} \def \indexformat {% \the\bodyfont \alterindentation{\leftindent}{\rightindent}% \setparrag{\parrag}% \setpagecolumns{\zixpageuse}{\the\zixcols}{\columngutter}% \everycolumn = {\zixcarryover}% \begingroup \let \zfullcolumnbreak = \fullcolumnbreak \let \fullcolumnbreak = \indexbreak \let \shortcolumnbreak = \indexbreak \global\previndexlevel = 0\relax} \def \endindex {% \endgraf % End last entry. \vbox{}% % Force start of column if not already. \endgroup \clearindexmarks \everycolumn = {}% \setpagecolumns{\usetextmeasure}{1}{0pt}% \global\decrement \indexdepth \endblockscope{index}} \def \zixparsepos {% \zixcols = 1 \let \oneup = \relax \def \twoup {\zixcols = 2}% \def \threeup {\zixcols = 3}% \def \zixpageuse {\usetextmeasure}% \let \textarea = \relax \def \typearea {\def \zixpageuse {\usetypewidth}}% \let \leftmargin = \typearea \the\position} % Index Entries % ----- ------- \setflag \zixbreak = \false \def \indexentry #1#2#3{% level{heading}{locators} \endgraf \ifcase #1% \or % Level 1 heading: \clearindexmarks \zixmaybebreak \hangindent = \parhang \hangafter = 1 {\name{\index\zixtype entryiformat}{#2\setmarkinfo{4}{\true}{#2}}{#3}}% %%% \setmarkinfo{4}{\true}{#2}% \or % Level 2 heading: \setmarkinfo{5}{\false}{}% \zixmaybebreak \hangindent = \parhang \hangafter = 1 {\name{\index\zixtype entryiiformat}{#2\setmarkinfo{5}{\true}{#2}}{#3}}% %%% \setmarkinfo{5}{\true}{#2}% \or % Level 3 heading: \zixmaybebreak \hangindent = \parhang \hangafter = 1 {\name{\index\zixtype entryiiiformat}{#2}{#3}}% \fi \global\previndexlevel = #1\relax} \def \alphabreak #1{% {text} \endgraf \clearindexmarks \zixmaybebreak \alphaformat{#1}% \endgraf} \def \indexbreak {% \setflag \zixbreak = \true} \def \clearindexmarks {% \setmarkinfo{4}{\false}{}% \setmarkinfo{5}{\false}{}} \def \zixmaybebreak {% \if \zixbreak \zfullcolumnbreak \setflag \zixbreak = \false \fi} % This macro is invoked at the beginning of each column to perform % any first- and second-level entry carryovers. It only includes % carryovers on the first column of versos. \def \zixcarryover {% \if \andp{\evenpagep}{\firstcolumnp}% {\setflag \znext = {\markinfo{\bottommark}{4}{1}}% \if \znext \hangindent = \parhang \hangafter = 1 \name{\index\zixtype carryiformat}{\markinfo{\bottommark}{4}{2}}% \setflag \znext = {\markinfo{\bottommark}{5}{1}}% \if \znext \hangindent = \parhang \hangafter = 1 \name{\index\zixtype carryiiformat}{\markinfo{\bottommark}{5}{2}}% \fi \endgraf \tdimena = \zoutputcoldepth % Compensate for depth of \advance \tdimena by -\prevdepth % previous column v. depth \kern \tdimena % of carryover line(s). \fi}% \fi}