% 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
   example 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 record with 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 formatting 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
