summaryrefslogtreecommitdiff
path: root/macros/optex/base/outlines.opm
blob: 6230d8988b82c878c9e657c4c8e385e09fe7e1ef (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
%% This is part of the OpTeX project, see http://petr.olsak.net/optex

\_codedecl \outlines {PDF outlines <2021-02-09>} % preloaded in format

\_def\_outlines#1{\_pdfcatalog{/PageMode/UseOutlines}\_openref
   \_ifx\_toclist\_empty
     \_opwarning{\_noexpand\outlines -- data unavailable. TeX me again}%
     \_incr\_unresolvedrefs
   \_else
     \_ifx\_dest\_destactive \_else
        \_opwarning{\_noexpand\outlines doesn't work when \_noexpand\hyperlinks isn't declared}\_fi
     {\_let\_tocline=\_outlinesA
      \_count0=0 \_count1=0 \_count2=0 \_count3=0 \_toclist % calculate numbers o childs
      \_def\_outlinelevel{#1}\_let\_tocline=\_outlinesB
      \_tocrefnum=0 \_count0=0 \_count1=0 \_count2=0 \_count3=0
      \_toclist}% create outlines
   \_fi
}
\_def\_outlinesA#1#2#3#4#5#6#7{%
   \_isequal{\relax}{#4}\_iffalse
      \_advance\_count#1 by1
      \_ifcase#1\_or
         \_addoneol{_ol:\_the\_count0}\_or
         \_addoneol{_ol:\_the\_count0:\_the\_count1}\_or
         \_addoneol{_ol:\_the\_count0:\_the\_count1:\_the\_count2}\_or
         \_addoneol{_ol:\_the\_count0:\_the\_count1:\_the\_count2:\_the\_count3}\_fi
   \_fi
}
\_def\_addoneol#1{%
   \_ifcsname #1\_endcsname
           \_tmpnum=\_csname#1\_endcsname\_relax
           \_advance\_tmpnum by1 \_sxdef{#1}{\_the\_tmpnum}%
   \_else \_sxdef{#1}{1}%
   \_fi
}
\_def\_outlinesB#1#2#3#4#5#6#7{%
   \_advance\_tocrefnum by1
   \_isequal{\relax}{#4}\_iffalse
      \_advance\_count#1 by1
      \_ifcase#1%
         \_tmpnum=\_trycs{_ol:\_the\_count0}{0}\_or
         \_tmpnum=\_trycs{_ol:\_the\_count0:\_the\_count1}{0}\_relax\_or
         \_tmpnum=\_trycs{_ol:\_the\_count0:\_the\_count1:\_the\_count2}{0}\_relax\_or
         \_tmpnum=\_trycs{_ol:\_the\_count0:\_the\_count1:\_the\_count2:\_the\_count3}{0}\_relax\_or
         \_tmpnum = 0\_relax\_fi
      \_isempty{#4}\_iftrue \_pdfunidef\_tmp{#5}\_else \_pdfunidef\_tmp{#4}\_fi
      \_outlinesC{toc:\_the\_tocrefnum}{\_ifnum#1<\_outlinelevel\_space\_else-\_fi}{\_tmpnum}{\_tmp}%
   \_fi
}
\_def\_outlinesC#1#2#3#4{\_pdfoutline goto name{#1} count #2#3{#4}\_relax}

\_newcount\_oulnum
\_def\_insertoutline#1{\_incr\_oulnum
   \_pdfdest name{oul:\_the\_oulnum} xyz\_relax
   \_pdfunidef\_tmp{#1}%
   \_pdfoutline goto name{oul:\_the\_oulnum} count0 {\_tmp}\_relax
}
\_public \outlines \insertoutline ;

\_endcode % ----------------------------

The problem is that PDF format needs to know the number of direct
descendants of each outline if we need to create the tree of structured
outlines. But we know only the level of each outline. The required data
should be calculated from TOC data. We use two steps over TOC data saved in
the `\_toclist` where each record is represented by one `\_tocline`.

The first step, the \`\outlines` macro sets `\_tocline` to \`\_outlinesA` and
calculates the number of direct descendants of each record. The second step,
the `\outlines` macro sets `\_tocline` to \`\_outlinesB` and it uses prepared
data and creates outlines.

Each outline is mapped to the control sequence of the type
`\_ol:<num>` or `\_ol:<num>:<num>` or `\_ol:<num>:<num>:<num>` or etc.
The first one is reserved for level 0, the second one for level 1 (chapters), the third
one for level 2 (sections) etc. The number of direct descendants will be stored
in these macros after the first step is finished. Each new outline of a given level
increases the `<num>` at the given level. When the first step is processed then
(above that) the `\_ol:..` sequence of the parent increases its value too. The
`_ol:...` sequences are implemented by `\_ol:\_count0:\_count1:\count2` etc.
For example, when section (level 2) is processed in the first step then we do:

\begtt
   \advance \count2 by 1
                    % increases the mapping pointer of the type
                    % \_ol:\_count0:\_count1:\_count2 of this section
   \advance \_ol:\_count0:\_count1 by 1
                    % increases the number of descendants connected
                    % to the parent of this section.
\endtt

When the second step is processed, then we only read the stored data about the
number of descendants. And we use it in `count` parameter of `\_pdfoutline`
primitive.

For linking, we use the same links as in TOC, i.e. the `toc:\_the\_tocrefnum`
labels are used.

\`\insertoutline` `{<text>}` inserts one outline with zero direct descendants.
It creates a link destination of the type `oul:<num>` into the document
(where \^`\insertoutline` is used) and the link itself is created too in the
outline.

\endinput

2021-02-15 \_advance -> \_incr
2021-02-09 \thisoutline implemented
2020-03-12 released