summaryrefslogtreecommitdiff
path: root/macros/optex/base/maketoc.opm
blob: cb4c318b130f1e5fbf30aa98b1f3e3ef18901f3d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
% This is part of the OpTeX project, see http://petr.olsak.net/optex

\_codedecl \maketoc {Macros for maketoc <2021-07-18>} % preloaded in format

   \_doc ------------------------------------
   \`\_Xtoc` `{<level>}{<type>}{<number>}{<o-title>}<title>` (in `.ref` file) reads
   given data and appends them to the \`\_toclist` as
   \^`\_tocline``{<level>}{<type>}{<number>}{<o-title>}{<title>}{<gpageno>}{<pageno>}`
   where:
   \begitems
   * `<level>`:   0 reserved, 1: chapter, 2: section, 3: subsection
   * `<type>`:    the type of the level, i.e. chap, sec, secc
   * `<number>`:  the number of the chapter/section/subsection in the format 1.2.3
   * `<o-title>`: outlines title, if differs from `<title>`.
   * `<title>`:   the title text
   * `<gpageno>`: the page number numbered from 1 independently of pagination
   * `<pageno>`:  the page number used in the pagination
   \enditems
   The last two parameters are restored from previous
   \^`\_Xpage``{<pageno>}{<gpageno>}`, data were saved in the \^`\_currpage` macro.

   We read the <title> parameter by \^`\scantoeol` from `.ref` file
   because the <title> can include something like \code{`\{`}.
   \_cod ------------------------------------

\_def\_toclist{}
\_newifi \_ifischap \_ischapfalse

\_def\_Xtoc#1#2#3#4{\_ifnum#1=0 \_ischaptrue\_fi
   \_addto\_toclist{\_tocline{#1}{#2}{#3}{#4}}\_scantoeol\_XtocA}
\_def\_XtocA#1{\_addto\_toclist{{#1}}\_ea\_addto\_ea\_toclist\_ea{\_currpage}}

   \_doc ------------------------------------
   \`\_tocline``{<level>}{<type>}{<number>}{<o-title>}{<title>}{<gpageno>}{<pageno>}`
   prints the record to the table of contents. It opens group, reduces `\_leftskip`,
   `\_rightskip`, runs the \^`\everytocline` (user can customise the design of TOC
   here) and runs `\_tocl:<level> {<number>}{<title>}{<pageno>}` macro.
   This macro starts with vertical mode,
   inserts one record with given `<level>` and it should end by \^`\_tocpar`
   which returns to horizontal mode. The `\_tocpar`
   appends `\_nobreak \_hskip-2\_iindent\_null \_par`. This causes
   that the last line of the record is shifted outside the margin given by
   `\_rightskip`. A typical record (with long `<title>`) looks like this:
   \begtt \catcode`\<=13
                  |                        |
   \llap{<number>} text text text text text
                   text text text text text
                   text text .................... <pageno>
   \endtt
   Margins given by `\leftskip` and `\rightskip` are denoted by `|` in the
   examle above.
   \nl
   \`\tocrefnum` is the global counter of all TOC records (used by hyperlinks).
   \_cod ------------------------------------

\_newcount \_tocrefnum
\_def\_tocline#1#2#3#4#5#6#7{%
   \_advance\_tocrefnum by1
   \_bgroup
      \_leftskip=\_iindent \_rightskip=2\_iindent
      \_ifischap \_advance\_leftskip by \_iindent \_fi
      \_def\_pgn##1{\_ilink[pg:#6]{\_numprint{##1}}}%
      \_the\_everytocline
      \_ifcsname _tocl:#1\_endcsname
         \_cs{_tocl:#1}{#3}{\_scantextokens{#5}}{#7}\_par
      \_fi
   \_egroup
}
\_public \tocrefnum ;

   \_doc -----------------------------------
   You can re-define default macros for each level of tocline if you want.\nl
   Parameters are `{<number>}{<title>}{<pageno>}`.
   \_cod -----------------------------------

\_sdef{_tocl:1}#1#2#3{\_nofirst\_bigskip
   \_bf\_llaptoclink{#1}{#2}\_nobreak\_hfill \_pgn{#3}\_tocpar}
\_sdef{_tocl:2}#1#2#3{\_llaptoclink{#1}{#2}\_tocdotfill \_pgn{#3}\_tocpar}
\_sdef{_tocl:3}#1#2#3{\_advance\_leftskip by\_iindent \_cs{_tocl:2}{#1}{#2}{#3}}

   \_doc -----------------------------------
   The auxiliary macros are:
   \begitems
   * \`\_llaptoclink``<text>` does `\_noindent\_llap{<linked text>}`.
   * \`\_tocdotfill` creates dots in the TOC.
   * \`\_nofirst``\macro` applies the `\macro` only if we don't print the first
     record of the TOC.
   * \`\_tocpar` finalizes one TOC recors whith rlapped `<pageno>`.
   * \`\_pgn``{<pageno>}` creates <pageno> as link to real `<gpage>` saved in `#6`
     of \^`\_tocline`. This is temporarily defined in the \^`\_tocline`.
   \enditems
   \_cod ----------------------------------

\_def\_llaptoclink#1{\_noindent
   \_llap{\_ilink[toc:\_the\_tocrefnum]{\_enspace\_numprint{#1}\_kern.4em}\_kern.1em}}
\_def\_tocdotfill{\_nobreak\_leaders\_hbox to.8em{\_hss.\_hss}\_hskip 1em plus1fill\_relax}
\_def\_nofirst #1{\_ifnum \_lastpenalty=11333 \_else #1\_fi}
\_def\_tocpar{\_nobreak \_hskip-2\_iindent\_null \_par}

   \_doc -----------------------------------
   If you want a special formating of TOC with adding more
   special lines (no generated as titles from `\chap`, `\sec`, `\secc`), you
   can define `\addtotoc{<level>}{<type>}{<number>}{<o-title>}{<title>}` macro:
   \begtt
   \def\addtotoc#1#2#3#4#5{%
      \incr\_tocrefnum
      \_dest[toc:\_the\_tocrefnum]%
      \_ewref\_Xtoc{{#1}{#2}{#3}{#4}#5}%
   }
   \endtt
   and you can declare special lines (or something else)
   as an unused level (10 in the following example):
   \begtt
      \sdef{_tocl:10}#1#2#3{\medskip\hbox{\Blue #2}\medskip}
   \endtt
   Now, users can add a blue line into TOC by
   \begtt \catcode`\<=13
      \addtotoc{10}{blue-line}{}{\relax}{<blue text to be added in the TOC>}
   \endtt
   anywhere in the document. Note that `\relax` in the fourth parameter
   means that outline will be not generated. And second parameter
   `blue-line` is only a comment (unused in macros).

   \`\maketoc` prints warning if TOC data is empty, else it creates TOC by
   running \^`\_toclist`
   \_cod ----------------------------------

\_def\_maketoc{\_par \_ifx\_toclist\_empty
      \_opwarning{\_noexpand\maketoc -- data unavailable, TeX me again}\_openref
      \_incr\_unresolvedrefs
   \_else \_begingroup
      \_tocrefnum=0 \_penalty11333
      \_the\_regtoc \_toclist
   \_endgroup \_fi
}

   \_doc -----------------------------------
   \`\regmacro` appends its parameters to \`\_regtoc`, \`\_regmark` and
   \`\_regoul`. These token lists are used in \^`\maketoc`, \^`\_begoutput` and
   \^`\pdfunidef`.
   \_cod \_fin -----------------------------

\_newtoks \_regtoc  \_newtoks \_regmark  \_newtoks \_regoul

\_def\_regmacro #1#2#3{%
   \_toksapp\_regtoc{#1}\_toksapp\_regmark{#2}\_toksapp\_regoul{#3}%
}
\_public \maketoc \regmacro ;

\_endcode

2021-07-18 _tocl:1, \nobreak added, bug fixed
2021-02-09 \thisoutline implemented
2020-04-23 \_tocpar introduced (incompatible change)
2020-04-22 \_pg -> \_pgn (incompatible change)
2020-03-12 introduced