strc-lst.mklx /size: 58 Kb    last modification: 2023-12-21 09:44
1%D \module
2%D   [       file=strc-lst,
3%D        version=2008.10.20,
4%D          title=\CONTEXT\ Structure Macros,
5%D       subtitle=Lists,
6%D         author=Hans Hagen,
7%D           date=\currentdate,
8%D      copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
9%C
10%C This module is part of the \CONTEXT\ macro||package and is
11%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
12%C details.
13
14\writestatus{loading}{ConTeXt Structure Macros / Lists}
15
16\registerctxluafile{strc-lst}{autosuffix}
17
18% clean up in progress ...
19%
20% also (long term) todo:
21%
22% autocrossdocument
23% auto refs to lists (chain)
24%
25% TODO: strut=yes|no
26%
27% \lists -> strc_lists
28
29\unprotect
30
31%D Lists are mostly used for tables of contents but are in fact a rather generic
32%D feature of \CONTEXT. We seperate between storage and rendering and the current
33%D implementation is a reworked version of all that was added in steps. As lists
34%D are used frequently compatibility is an important aspect. A couple of rendering
35%D alternatives are provided here but more are possible.
36
37\installcorenamespace{list}
38
39\installframedcommandhandler \??list {list} \??list
40
41\aliased\let\setuplists\setuplist % yes or no
42
43\setuplist
44  [\c!height=\v!broad,
45   \c!depth=\v!broad,
46   \c!offset=.25\emwidth,
47   \c!state=\v!start,
48   \c!coupling=\v!off,
49   \c!criterium=\v!local,
50   \c!reference=,% was number which was sort of obsolete
51   \c!width=3\emwidth,
52  %\c!maxwidth=,
53   \c!distance=\zeropoint,
54   \c!margin=\zeropoint,
55   \c!alternative=\c!b,
56   \c!style=\v!normal,
57  %\c!color=,
58   \c!textstyle=\listparameter\c!style,   % \currentliststyleparameter (but then we need to set it in every ...)
59   \c!numberstyle=\listparameter\c!style, % \currentliststyleparameter
60   \c!pagestyle=\listparameter\c!style,   % \currentliststyleparameter
61   \c!textcolor=\listparameter\c!color,   % \currentlistcolorparameter (but then we need to set it in every ...)
62   \c!numbercolor=\listparameter\c!color, % \currentlistcolorparameter
63   \c!pagecolor=\listparameter\c!color,   % \currentlistcolorparameter
64   \c!numbercommand=\firstofoneargument,
65   \c!textcommand=\firstofoneargument,
66   \c!pagecommand=\firstofoneargument,
67   \c!pagenumber=\v!yes, % better: 'first'
68   \c!headnumber=\v!yes, % better: 'second'
69%  \c!sectionnumber=\listparameter\c!headnumber, % use this instead
70   \c!interaction=\v!all, % was \v!sectionnumber, % or make this headnumber (or accept both)
71   \c!label=\v!no,
72  %\c!extras=,
73  %\c!aligntitle=,
74  %\c!before=,
75  %\c!after=,
76  %\c!inbetween=,
77  %\c!symbol=,
78  %\c!expansion=,
79   \c!limittext=\languageparameter\c!limittext] % not used currently
80
81%D Kind of new:
82
83\permanent\protected\tolerant\def\uselist[#1]#*[#2]#*[#3]% tag file
84  {\doifelsefiledefined{#1}{}{\usefile[#1][#2]}%
85   \clf_uselist{#1}{#2}{#3}}
86
87%D Helpers:
88
89\permanent\protected\def\usenestedliststyleandcolor#style#color% will change
90  {\useliststyleandcolor#style#color%
91   % how about style
92   \ifempty\currentcolorparameter \else
93     \resetinteractionparameter\c!color
94     \resetinteractionparameter\c!contrastcolor
95   \fi}
96
97\permanent\protected\def\doifelselist#tag% can also move to \installcommandhandler
98  {\ifcsname\namedlisthash{#tag}\s!parent\endcsname
99     \expandafter\firstoftwoarguments
100   \else
101     \expandafter\secondoftwoarguments
102   \fi}
103
104\aliased\let\doiflistelse\doifelselist
105
106%D Regular list entries are bound to a specific location in order to get the right
107%D pagenumber etc.\ associated. When pushing something inbetween (in mkiv) it ends
108%D up directtly in the list. This is the default because otherwise users will wonder
109%D why spacing might get messed up (due to an unseen but present node). It is
110%D possible to force a location by explicitly setting \type {location} to \type
111%D {here}.
112%D
113%D Another way to force a certain order is to set the \type {order} variable when
114%D placing a list. The \type {command} option only pushes commands into the right
115%D order, and \type {all} orders all entries (which might be too much). In this case
116%D no specific location is needed with the inbetween method. Maybe additional
117%D mechanisms show up some day. See \type {inbetween-001.tex} for an example.
118
119% command  : location=none
120% userdata : location=none
121% simple   : location=here
122
123\installcorenamespace {listlocations}
124
125\permanent\protected\def\doifelseinlistentry#1%
126  {\unless\ifcsname\??listlocations#1\endcsname
127     \expandafter\secondoftwoarguments
128   \orelse\ifnum\lastnamedcs=\structurelistlocation\relax
129     \expandafter\firstoftwoarguments
130   \else
131     \expandafter\secondoftwoarguments
132   \fi}
133
134\permanent\protected\def\doifelseincurrentlistentry
135  {\doifelseinlistentry\currentlist}
136
137\permanent\protected\def\structurelistinject[#tag]%
138  {\begingroup
139   \cdef\currentlist{#tag}%
140   \ifcstok{\listparameter\c!state}\v!start
141     \expandafter\strc_lists_inject_yes
142   \else
143     \expandafter\strc_lists_inject_nop
144   \fi}
145
146\tolerant\protected\def\strc_lists_inject_nop[#S#settings]#spacer[#S#userdata]%
147  {\endgroup}
148
149\def\strc_lists_inject_enhance#listindex%
150  {\expandafter\clf_deferredenhancelist\number#listindex\relax}
151
152\tolerant\protected\def\strc_lists_inject_yes[#S#settings]#spacer[#S#userdata]% can be used directly
153  {\setupcurrentlist[\c!type=userdata,\c!location=\v!none,#settings]% grouped (use \let...
154   \edef\p_location{\listparameter\c!location}%
155   \setnextinternalreference
156   \scratchcounter\clf_addtolist
157        references {
158            internal \locationcount
159          % block    {\currentsectionblock} % needed for publications (can be get from section)
160          % section  structures.sections.currentid()
161          % location {\p_location}
162        }
163        metadata {
164            kind     {\listparameter\c!type}
165            name     {\currentlist}
166          % level    structures.sections.currentlevel()
167            catcodes \catcodetable
168        }
169        userdata {\detokenize\expandafter{\normalexpanded{#userdata}}}
170   \relax
171   \edef\currentlistnumber{\the\scratchcounter}%
172   \xdefcsname\??listlocations\currentlist\endcsname{\the\locationcount}%
173   \ifx\p_location\v!here
174     % this branch injects nodes !
175     \strc_lists_inject_enhance{\currentlistnumber}%
176     \clf_setinternalreference
177        internal \locationcount
178        view     {\interactionparameter\c!focus}%
179     \relax % this will change
180     \xdef\currentstructurelistattribute{\the\lastdestinationattribute}%
181     \dontleavehmode\hpack attr \destinationattribute \lastdestinationattribute{}% todo
182   \else
183     % and this one doesn't
184     \clf_enhancelist\currentlistnumber\relax
185   \fi
186   \endgroup}
187
188% todo: make like \strc_references_direct_full_user ... with {}{}{}
189
190\protected\def\strc_lists_inject_direct[#tag]% [#settings][#userdata]
191  {\begingroup
192   \cdef\currentlist{#tag}%
193   \strc_lists_inject_yes} % [#settings][#userdata]
194
195\permanent\protected\def\writebetweenlist[#tag]%
196  {\begingroup
197   \cdef\currentlist{#tag}%
198   \ifcstok{\namedlistparameter{#tag}\c!state}\v!start
199     \expandafter\strc_lists_write_between_yes
200   \else
201     \expandafter\strc_lists_write_between_nop
202   \fi}
203
204\tolerant\def\strc_lists_write_between_yes[#S#settings]#:#command%
205  {\strc_lists_inject_yes[#settings,\c!type=\s!command][command={#command}]}
206
207\tolerant\def\strc_lists_write_between_nop[#S#settings]#:#command%
208  {\endgroup}
209
210\permanent\protected\def\writedatatolist[#tag]%
211  {\begingroup
212   \cdef\currentlist{#tag}%
213   \ifcstok{\namedlistparameter{#tag}\c!state}\v!start
214     \expandafter\strc_lists_write_data_to_yes
215   \else
216     \expandafter\strc_lists_write_data_to_nop
217   \fi}
218
219\tolerant\def\strc_lists_write_data_to_yes[#S#settings]#spacer[#userdata]%
220  {\ifparameter#userdata\or % no need to have an extra step ... used seldom
221     \strc_lists_inject_yes[#settings,\c!type=\s!userdata][#userdata]%
222   \else
223     \strc_lists_inject_yes[\c!type=\s!userdata][#settings]%
224   \fi}
225
226\tolerant\def\strc_lists_write_data_to_nop[#S#settings]#spacer[#userdata]%
227  {\endgroup}
228
229\permanent\protected\def\writetolist[#tag]%
230  {\begingroup
231   \cdef\currentlist{#tag}%
232   \ifcstok{\namedlistparameter{#tag}\c!state}\v!start
233     \expandafter\strc_lists_write_to_yes
234   \else
235     \expandafter\strc_lists_write_to_nop
236   \fi}
237
238\tolerant\def\strc_lists_write_to_yes[#S#settings]#:#first#second% no \s!first because we don't expand user settings
239  {\strc_lists_inject_yes[\c!location=\v!here,#settings,\c!type=\s!simple][first={#first},second={#second}]}
240
241\tolerant\def\strc_lists_write_to_nop[#S#settings]#:#first#second%
242  {\endgroup} % \strc_lists_inject_nop[][]
243
244% \starttyping
245% \installstructurelistprocessor{chapter:userdata}
246%   {\startlinecorrection[blank]
247%    \hfill \inframed{you really need to look at \structurelistuservariable{pagenumber}}%
248%    \stoplinecorrection}
249%
250% \starttext
251%   \placelist[chapter]
252%   \chapter{one}
253%   \writebetweenlist[chapter][location=here]{\blank page 4\blank}
254%   \writedatatolist[chapter][location=here][pagenumber=4]
255%   \writetolist[chapter]{}{It's a test}
256%   \chapter{two}
257% \stoptext
258% \stoptyping
259
260%D When placing a list either one or a set can be giving. This makes it possible to
261%D flush for instance an nested (or merged) table of contents. Keep in mind that
262%D placing a list is what we do most (think of tables of contents, figures, etc.\
263%D but other usage is also possible in which case low level commands have to be
264%D used.
265
266\newtoks\everystructurelist
267
268\permanent\tolerant\protected\def\placelist[#taglist]#spacer[#S#settings]%
269  {\begingroup
270   \startpacked[\v!blank]%
271   \edef\m_list {#taglist}%
272   \edef\m_first{\firststructureelementinlist{#taglist}}%
273   \ifx\m_list\m_first
274      % use settings of first
275   \else
276      % use settings of root
277      \lettonothing\m_first
278   \fi
279   \strc_lists_place_indeed\m_first\m_list{#settings}%
280   \stoppacked
281   \endgroup}
282
283\permanent\tolerant\protected\def\placerawlist[#tag]#spacer[#S#settings]% just one list
284  {\strc_lists_place_indeed\empty{#tag}{#settings}}
285
286\aliased\let\strc_lists_place\placelist % used in strc-flt
287
288\def\strc_lists_place_indeed#tag#list#settings%
289  {\begingroup
290   \expand\t_lists_every_renderingcleanup % \lettonothing\currentlistentrylocation
291   \cdef\currentlist{#tag}%
292   \setupcurrentlist[#settings]%
293   \expand\everystructurelist
294 % \ifcstok{\listparameter\c!coupling}\v!on
295 %   \startlistreferences{#tag}%
296 % \fi
297   \strc_lists_place_current % maybe inline
298     {#list}%
299     {\listparameter\c!criterium}%
300     {\listparameter\c!reference}%
301     {\listparameter\c!extras}%
302     {\listparameter\c!order}%
303     {\listparameter\c!levels}%
304 % \stoplistreferences
305   \par % todo: only when vertical list mode
306   \endgroup
307   \strc_lists_set_mode}
308
309\def\strc_lists_set_mode
310  {\ifcase\structurelistsize\relax
311     \resetsystemmode\v!list
312   \else
313     \setsystemmode  \v!list
314   \fi}
315
316%D Complete lists are just lists but with a title. They were originally introduced
317%D to minimize the number for commands in a document source but nowadays that is
318%D less an issue in the sense that the extra few lines are neglectable to the rest.
319
320\ifdefined\startnamedsection \else \let\startnamedsection\relax \fi
321\ifdefined\stopnamedsection  \else \let\stopnamedsection \relax \fi
322\ifdefined\headtext          \else \let\headtext         \relax \fi
323
324\permanent\tolerant\protected\def\completelist[#tag]#spacer[#S#settings]%
325  {\normalexpanded{\startnamedsection[\v!title][\c!title=\headtext{#tag},\c!reference=#tag]}% {} around ref ?
326   \strc_lists_place[#tag][#settings]%
327   \stopnamedsection}
328
329\permanent\tolerant\protected\def\strc_lists_complete[#singular]#spacer[#plural]#spacer[#S#settings]% used in strc-flt
330  {\normalexpanded{\startnamedsection[\v!title][\c!title=\headtext{#plural},\c!reference=#singular]}% {} around ref ?
331   \strc_lists_place[#singular][#settings]%
332   \stopnamedsection}
333
334\permanent\tolerant\def\strc_lists_combined_complete[#tag]#spacer[#S#settings]%
335  {\normalexpanded{\startnamedsection[\v!title][\c!title={\headtext{#tag}},\c!reference=#tag]}%
336   \placecombinedlist[#tag][#settings]%
337   \stopnamedsection}
338
339%D Combined list provide a nice level of abstraction.
340%D
341%D \starttyping
342%D \definecombinedlist[whatever][a,b,c][settings]
343%D \stoptyping
344
345\permanent\tolerant\protected\def\definecombinedlist[#tag]#spacer[#list]#spacer[#S#settings]%
346  {\definelist[#tag][\c!criterium=\v!local,\c!reference=,\c!alternative=,\c!list={#list},#settings]% inherits from root
347   \frozen\instance\defcsname\e!setup#tag\e!endsetup\endcsname{\setupcombinedlist[#tag]}%
348   \frozen\instance\defcsname\e!place#tag\endcsname{\placecombinedlist[#tag]}%
349   \frozen\instance\defcsname\e!complete#tag\endcsname{\strc_lists_combined_complete[#tag]}}
350
351\permanent\tolerant\protected\def\setupcombinedlist[#tag]#spacer[#settings]%
352  {\ifarguments\or\or
353     \setuplist[#tag][#settings]% we don't want to mess up the parent
354   \fi}
355
356\permanent\tolerant\protected\def\placecombinedlist[#tag]#spacer[#S#settings]% i.e. no list set in settings
357  {\begingroup
358   \cdef\currentlist{#tag}%
359   \setupcurrentlist[#settings]%
360   \edef\m_strc_list_alternative{\listparameter\c!alternative}% we only inherit alternative
361   \strc_lists_place_indeed{#tag}{\listparameter\c!list}{#settings}%
362   \endgroup}
363
364%D Given that some variables are set, we can ask for some properties of
365%D an entry.
366
367\mutable\def\currentstructurelistnumber{0}     % injection
368\mutable\def\currentlistmethod         {entry} % typesetting
369\mutable\def\currentlistindex          {0}     % typesetting (maybe also a real counter)
370
371\permanent\protected\def\savedlistnumber        #1#2{\clf_savedlistnumber        {#1}\numexpr#2\relax}
372\permanent\protected\def\savedlisttitle         #1#2{\clf_savedlisttitle         {#1}\numexpr#2\relax}
373\permanent\protected\def\savedlistprefixednumber#1#2{\clf_savedlistprefixednumber{#1}\numexpr#2\relax}
374
375\newconditional\c_lists_show_realpage
376
377\installcorenamespace {listpagenumber}
378
379\defcsname\??listpagenumber\v!always  \endcsname{\c_lists_show_page\conditionaltrue\c_lists_has_page\conditionaltrue}
380\defcsname\??listpagenumber\v!yes     \endcsname{\c_lists_show_page\conditionaltrue}
381\defcsname\??listpagenumber\s!realpage\endcsname{\c_lists_show_page\conditionaltrue\c_lists_show_realpage\conditionaltrue}
382
383\def\strc_lists_process_pagenumber#1%
384  {\begincsname\??listpagenumber#1\endcsname}
385
386\permanent\def\structurelistexternal
387  {\clf_listexternal\numexpr\currentlistindex\relax}
388
389\permanent\def\structurelistlocation
390  {\clf_listlocation\numexpr\currentlistindex\relax}
391
392\permanent\def\structurelistrawnumber#1%
393  {\clf_rawlistnumber\numexpr\currentlistindex\relax{#1}}
394
395\permanent\def\structurelistrealpagenumber
396  {\clf_listrealpage{\currentlist}\numexpr\currentlistindex\relax}
397
398\permanent\protected\def\structurelistpagenumber
399  {\dostarttagged\t!listpage\empty
400   \ifconditional\c_lists_show_realpage
401     \clf_listrealpage{\currentlist}\numexpr\currentlistindex\relax
402   \else
403     \clf_listprefixedpage
404       {\currentlist}%
405       \currentlistindex
406       {%
407         separatorset  {\listparameter\c!pageprefixseparatorset}%
408         conversionset {\listparameter\c!pageprefixconversionset}%
409         set           {\listparameter\c!pageprefixset}%
410         segments      {\listparameter\c!pageprefixsegments}%
411         connector     {\listparameter\c!pageprefixconnector}%
412       }%
413       {%
414         prefix        {\listparameter\c!pageprefix}%
415         conversionset {\listparameter\c!pageconversionset}%
416         starter       {\listparameter\c!pagestarter}%
417         stopper       {\listparameter\c!pagestopper}%
418       }%
419     \relax
420   \fi
421   \dostoptagged}
422
423\permanent\protected\def\structurelistuservariable#name%
424  {\dostarttagged\t!listdata{#name}%
425   \clf_listuserdata{\currentlist}\currentlistindex{#name}%
426   \dostoptagged}
427
428\permanent\def\rawstructurelistuservariable#name%
429  {\clf_listuserdata{\currentlist}\currentlistindex{#name}}
430
431\permanent\protected\def\structurelistfirst {\structurelistuservariable\s!first } % s!
432\permanent\protected\def\structurelistsecond{\structurelistuservariable\s!second} % s!
433
434\permanent\def\rawstructurelistfirst {\rawstructurelistuservariable\s!first } % s! % was \protected
435\permanent\def\rawstructurelistsecond{\rawstructurelistuservariable\s!second} % s! % was \protected
436
437\permanent\protected\def\doifelsestructurelisthaspage
438  {\clf_doifelselisthaspage{\currentlist}\numexpr\currentlistindex\relax}
439
440\permanent\protected\def\doifelsestructurelisthasnumber
441  {\clf_doifelselisthasnumber{\currentlist}\numexpr\currentlistindex\relax}
442
443\aliased\let\doifstructurelisthaspageelse  \doifelsestructurelisthaspage
444\aliased\let\doifstructurelisthasnumberelse\doifelsestructurelisthasnumber
445
446\permanent\protected\def\structurelistgenerictitle
447  {\dostarttagged\t!listcontent\empty
448   \clf_listtitle{\currentlist}\currentlistindex\relax
449   \dostoptagged}
450
451\permanent\protected\def\structurelistgenericnumber % tricky, we need to delay tagging as we have nested lua calls
452  {\dostarttagged\t!listtag\empty
453   \clf_listprefixednumber
454     {\currentlist}%
455     \currentlistindex
456     {%
457         prefix        {\listparameter\c!prefix}%
458         separatorset  {\listparameter\c!prefixseparatorset}%
459         conversionset {\listparameter\c!prefixconversionset}%
460         starter       {\listparameter\c!prefixstarter}%
461         stopper       {\listparameter\c!prefixstopper}%
462         set           {\listparameter\c!prefixset}%
463         segments      {\listparameter\c!prefixsegments}%
464         connector     {\listparameter\c!prefixconnector}%
465     }%
466     {%
467         separatorset  {\listparameter\c!numberseparatorset}%
468         conversionset {\listparameter\c!numberconversionset}%
469         starter       {\listparameter\c!numberstarter}%
470         stopper       {\listparameter\c!numberstopper}%
471         segments      {\listparameter\c!numbersegments}%
472     }%
473   \relax
474   \dostoptagged}
475
476% TODO: pass extra tag name (contents, figures, bibliography ...)
477
478\protected\def\strc_lists_place_current#list#criterium#reference#extras#order#levels% beware, not a user command
479  {\dostarttaggedchained\t!list\empty\??list
480   \clf_processlist
481        names     {#list}
482        criterium {#criterium}
483        reference {#reference}
484        extras    {#extras}
485        order     {#order}
486        levels    {#levels}
487   \relax
488   \dostoptagged}
489
490\protected\def\strc_lists_analyze#list#criterium#reference%
491  {\clf_analyzelist
492        names     {#list}
493        criterium {#criterium}
494        reference {#reference}
495   \relax}
496
497\permanent\def\firststructureelementinlist#list% expandable
498  {\firstinset{#list}}
499
500\permanent\def\structurelistsize
501  {\clf_listsize}
502
503%D Depending on what kind of list we have (e.g.\ a section related one) processors
504%D can be defined.
505
506% push pop test:
507%
508% \starttext
509%   \placelist[chapter] [after={\placelist[section][criterium=local]}]
510%   \chapter{One} \section{Alpha} \section{Beta}
511%   \chapter{Two} \section{First} \section{Second}
512% \stoptext
513
514\installcorenamespace{structurelistprocessor} % the topmost list handler
515\installcorenamespace{listextra}              % control of that handler
516
517\installcommandhandler \??listextra {listextra} \??listextra
518
519\definelistextra % example
520  [\v!page]
521  [\c!before={\showmessage\m!system{14}{\currentlist/\currentlistindex}\page}]
522
523\permanent\protected\def\installstructurelistprocessor#tag#meaning%
524  {\expandafter\normaldef\csname\??structurelistprocessor#tag\endcsname{#meaning}}
525
526\permanent\def\usestructurelistprocessor#tag%
527  {\begincsname\??structurelistprocessor#tag\endcsname}
528
529\aliased\let\dotaglistlocation\relax
530
531\def\strc_lists_entry_process_default
532  {no list method}
533
534\def\strc_lists_entry_process % assume things to be set up
535  {\listextraparameter\c!before
536   \dostarttagged\t!listitem\currentlist
537   \dotaglistlocation
538   \ifcsname\??structurelistprocessor\currentlist:\currentlistmethod\endcsname\lastnamedcs\orelse
539   \ifcsname\??structurelistprocessor\currentlistmethod             \endcsname\lastnamedcs\orelse
540   \ifcsname\??structurelistprocessor\currentlist                   \endcsname\lastnamedcs\else
541                                                         \strc_lists_entry_process_default\fi
542   \dostoptagged
543   \listextraparameter\c!after}
544
545\permanent\protected\def\strclistsentryprocess#tag#method#index#extra% This one is called at the lua end!
546  {\clf_pushlist#index\relax
547  %\lettonothing\currentlistentrylocation
548   \cdef\currentlist      {#tag}%
549   \edef\currentlistmethod{#method}%
550   \edef\currentlistindex {#index}%
551   \edef\currentlistextra {#extra}%
552   \strc_lists_entry_process
553   \clf_poplist}
554
555% lists that have a number/title are kind of generic and can share code
556
557\installstructurelistprocessor\s!default
558  {\strc_lists_entry_process_default}
559
560\installstructurelistprocessor\s!simple
561  {\let\currentlistentrynumber    \structurelistfirst
562   \let\currentlistentrytitle     \structurelistsecond
563   \let\currentlistentrypagenumber\structurelistpagenumber
564   \strc_lists_apply_renderingsetup}
565
566\installstructurelistprocessor\s!command
567  {\clf_listuserdata{\currentlist}\currentlistindex{\s!command}}
568
569\installstructurelistprocessor{section}
570  {\let\currentlistentrynumber    \structurelistgenericnumber
571   \let\currentlistentrytitle     \structurelistgenerictitle
572   \let\currentlistentrypagenumber\structurelistpagenumber
573   \strc_lists_apply_renderingsetup}
574
575\installstructurelistprocessor{number+title}
576  {\let\currentlistentrynumber    \structurelistgenericnumber
577   \let\currentlistentrytitle     \structurelistgenerictitle
578   \let\currentlistentrypagenumber\structurelistpagenumber
579   \strc_lists_apply_renderingsetup}
580
581% example of usage elsewhere:
582%
583% \installstructurelistprocessor{pubs:userdata}
584%   {\clf_listuserdata{\currentlist}\currentlistindex{bibref}}
585
586%D List symbols are used in interactive documents where no numbers are used but
587%D nevertheless structure is present. Beware, the list symbol macro gets an argument
588%D passed, i.e. when this argument is not picked up, the symbol becomes a kind of
589%D prefix. It's not really a user command (and might even get protected).
590
591\permanent\protected\def\listsymbol[#tag]#number%
592  {\begingroup
593   \cdef\currentlist{#tag}%
594   \def\currentlistentrynumber{#number}% no edef else tag problems
595   \currentlistsymbol
596   \endgroup}
597
598%D For historical reasons we're stuck to symbols, so in order to generalize, we have
599%D to hook it into the symbol handle. One way to deal with this is to use a
600%D different key and as it makes sense to use setups instead of def's we use a new
601%D key \quote {renderingsetup} which is the name of a setup.
602
603\def\strc_lists_assign_dimen#dimension#key#default%
604  {\edef\m_strc_list_dimen{\listparameter#key}%
605   #dimension\ifinset{\m_strc_list_dimen}{\v!fit,\v!broad}#default\else\m_strc_list_dimen\fi\relax}
606
607\definesymbol[\v!list][\v!none   ][\strc_lists_symbol_none]
608\definesymbol[\v!list][\v!one    ][\strc_lists_symbol_one]
609\definesymbol[\v!list][\v!two    ][\strc_lists_symbol_two]
610\definesymbol[\v!list][\v!three  ][\strc_lists_symbol_three]
611\definesymbol[\v!list][\s!default][\strc_lists_symbol_default]
612\definesymbol[\v!list][\s!unknown][\strc_lists_symbol_unknown]
613
614\permanent\protected\def\currentlistsymbol
615  {\edef\p_symbol{\listparameter\c!symbol}%
616   \doifelseinsymbolset\v!list\p_symbol
617     {\directsymbol\v!list\p_symbol}
618     {\directsymbol\v!list\s!default}}
619
620\protected\def\strc_lists_symbol_none
621  {\strc_lists_assign_dimen\scratchwidth\c!width{1.5\emwidth}%
622   \hpack to \scratchwidth{}}
623
624\protected\def\strc_lists_symbol_one
625  {\strut\symbol[bullet]}
626
627\protected\def\strc_lists_symbol_two
628  {\vrule\s!width\emwidth\s!height\exheight\s!depth\zeropoint\relax}
629
630\protected\def\strc_lists_symbol_three
631  {\begingroup
632   \strc_lists_assign_dimen\scratchwidth \c!width {1.5\emwidth}%
633   \strc_lists_assign_dimen\scratchheight\c!height\exheight
634   \strc_lists_assign_dimen\scratchdepth \c!depth \zeropoint
635   \vrule\s!width\scratchwidth\s!height\scratchheight\s!depth\scratchdepth
636   \endgroup}
637
638\protected\def\strc_lists_symbol_unknown
639  {\listparameter\c!symbol}
640
641\installcorenamespace{listsymbollabels}
642
643\def\strc_lists_symbol_label_unknown
644  {\leftlabeltext\currentlistlabel
645   \listparameter\c!starter
646   \currentlistentrynumber
647   \listparameter\c!stopper
648   \rightlabeltext\currentlistlabel}
649
650\mutable\let\currentlistnumber\!!zerocount
651
652\mutable\lettonothing\currentlistlabel
653
654\protected\def\strc_lists_symbol_default
655  {\dontleavehmode
656   \strut
657   \begingroup
658   \edef\currentlistlabel{\listparameter\c!label}% can be used in label
659   \ifcsname\??listsymbollabels\currentlistlabel\endcsname
660      \lastnamedcs
661   \else
662     \strc_lists_symbol_label_unknown
663   \fi
664   \endgroup}
665
666\letcsname\??listsymbollabels\s!unknown\endcsname\strc_lists_symbol_default
667
668\defcsname\??listsymbollabels\endcsname % default (empty)
669  {\listparameter\c!starter
670   \currentlistentrynumber
671   \listparameter\c!stopper}
672
673\defcsname\??listsymbollabels\v!no\endcsname % also default
674  {\listparameter\c!starter
675   \currentlistentrynumber
676   \listparameter\c!stopper}
677
678\defcsname\??listsymbollabels\v!none\endcsname % real minimal (as suggested by WS)
679  {\currentlistentrynumber}
680
681\defcsname\??listsymbollabels\v!yes\endcsname % auto (use value stored in tuc file)
682  {\edef\currentlistlabel{\clf_listlabel\currentlistindex{\currentlistlabel}}%
683   \leftlabeltext\currentlistlabel
684   \listparameter\c!starter
685   \currentlistentrynumber
686   \listparameter\c!stopper
687   \rightlabeltext\currentlistlabel}
688
689% a : nr - tit - pag
690% b : nr - tit - fill - pag
691% c : nr - tit - dots - pag
692% d : inline
693% e : interaction
694% f : interaction
695% g : interaction
696
697\installcorenamespace{listalternative} % specific ways of rendering a list
698\installcorenamespace{listrenderings}  % a namespace for setups (rather local)
699
700\installcommandhandler \??listalternative {listalternative} \??listalternative
701
702% Commands are bound to specific list instances as often these are quite special
703% and don't apply to multiple. So, being strict saves us resets.
704
705% \installcorenamespace{listfiller}
706%
707% \protected\def\installlistfiller#1#2%
708%   {\protected\defcsname\??listfiller#1\endcsname{#2}}
709%
710% \protected\def\listfiller#1%
711%   {\begincsname\??listfiller#1\endcsname}
712%
713% \protected\def\currentlistfiller
714%   {\begingroup
715%    \edef\p_filler{\listalternativeparameter\c!filler}%
716%    \ifcsname\??listfiller\p_filler\endcsname
717%      \lastnamedcs
718%    \else
719%      \p_filler
720%    \fi
721%    \endgroup}
722%
723% \installlistfiller\v!sym % original one
724%   {\begingroup
725%    \scratchdimen.5\emwidth
726%    \hskip\scratchdimen
727%    \gleaders
728%      \hbox to \scratchdimen
729%        {\hss
730%         \uselistalternativestyleandcolor\c!symstyle\c!symcolor
731%         \listalternativeparameter\c!symbol
732%         \hss}%
733%      \hfill
734%    \hskip\scratchdimen
735%    \endgroup}
736%
737% \installlistfiller\v!symbol % new one (make that default?)
738%   {\begingroup
739%    \scratchdimen.5\emwidth
740%    \hskip\scratchdimen
741%    \gleaders
742%      \hbox spread .5\scratchdimen
743%        {\hss
744%         \uselistalternativestyleandcolor\c!symstyle\c!symcolor
745%         \listalternativeparameter\c!symbol
746%         \hss}%
747%      \hfill
748%    \hskip\scratchdimen
749%    \endgroup}
750%
751% \installlistfiller\v!width
752%   {\hfill}
753%
754% \installlistfiller\v!space
755%   {\hskip.25\emwidth\relax}
756
757\setuplistalternative
758  [\c!command=\directlistparameter\c!command,
759   \c!symbol=.]
760
761\permanent\protected\def\currentlistfiller
762  {\checkedfiller{\listalternativeparameter\c!filler}}
763
764\definelistalternative
765  [a]
766  [\c!distance=0pt,
767   \c!width=2em,
768   \c!stretch=10em,
769   \c!filler=\hskip.25em\relax,
770   \c!renderingsetup=\??listrenderings:abc]
771
772\definelistalternative
773  [b]
774  [\c!distance=5em,
775   \c!width=2em,
776   \c!stretch=10em,
777   \c!filler=\hfill,
778   \c!renderingsetup=\??listrenderings:abc]
779
780\definelistalternative
781  [c]
782  [\c!distance=5em,
783   \c!width=0pt,
784   \c!stretch=10em,
785   \c!filler=\hskip.5em\gleaders\hbox to .5\emwidth{\hss.\hss}\hfill\hskip.5em\relax,
786   \c!renderingsetup=\??listrenderings:abc]
787
788\definelistalternative
789  [d]
790  [\c!renderingsetup=\??listrenderings:d]
791
792\definelistalternative
793  [e]
794  [\c!renderingsetup=\??listrenderings:e]
795
796\definelistalternative
797  [f]
798  [\c!renderingsetup=\??listrenderings:f]
799
800\definelistalternative
801  [g]
802  [\c!renderingsetup=\??listrenderings:g]
803
804\definelistalternative
805  [\v!command]
806  [\c!renderingsetup=\??listrenderings:command]
807
808\definelistalternative
809  [\v!none]
810  [\c!renderingsetup=\??listrenderings:none]
811
812\definelistalternative
813  [\v!vertical]
814  [\c!before=\ifvmode\nointerlineskip\fi,
815   \c!after=\ifvmode\nointerlineskip\fi\endgraf\allowbreak,
816   \c!renderingsetup=\??listrenderings:generic]
817
818\definelistalternative
819  [\v!horizontal]
820  [\c!before=\noindent,
821   \c!after=,
822   \c!renderingsetup=\??listrenderings:generic]
823
824% \setuplist
825%   [section]
826%   [alternative=MyListItem,
827%    after=\blank,
828%    before=\blank]
829%
830% \definelistplacement[MyListItem][command]#1#2#3{(#1) (#2) (#3)}
831% \definelistplacement[MyListItem][command]{\whatever}
832%
833% this is a compatibility command, best use the regular defined with command=
834% either set in the alternative or in the list
835
836\installcorenamespace{listelementcommand} % the old plugin model
837
838\permanent\tolerant\protected\def\definelistplacement[#tag]#spacer[#method]%
839  {\edef\p_method{#method}%
840   \ifempty\p_method
841     \let\p_method\v!command
842   \fi
843   \normalexpanded{\definelistalternative[#tag][\p_method]}[\c!command=\strc_lists_placement_command]%
844   \doifelsenextbgroup
845     {\strc_lists_define_placement_yes{#tag}}
846     {\strc_lists_define_placement_nop{#tag}}}
847
848% indirect definition: <three ignore arguments>: {\bla}
849
850\def\strc_lists_define_placement_yes#tag%
851  {\protected\defcsname\??listelementcommand#tag\endcsname##1##2##3}
852
853% direct definition: <three arguments>{\bla}
854
855\def\strc_lists_define_placement_nop#tag%
856  {\protected\defcsname\??listelementcommand#tag\endcsname}
857
858\def\strc_lists_placement_command
859  {\csname\??listelementcommand\currentlistalternative\endcsname}
860
861%D The rendering macros.
862
863\newbox  \b_strc_lists_number
864\newbox  \b_strc_lists_text
865\newbox  \b_strc_lists_page
866
867\newtoks \t_lists_every_renderingsetup
868\newtoks \t_lists_every_renderingtext
869\newtoks \t_lists_every_renderingsynchronize
870\newtoks \t_lists_every_renderingcleanup
871
872\newconditional\c_lists_has_number
873\newconditional\c_lists_has_page
874\newconditional\c_lists_show_number
875\newconditional\c_lists_show_page
876
877\mutable\lettonothing\currentlistentrylocation   % watch the 'entry' in the name
878\mutable\lettonothing\currentlistentrynumber     % watch the 'entry' in the name
879\mutable\lettonothing\currentlistentrytitle      % watch the 'entry' in the name
880\mutable\lettonothing\currentlistentrypagenumber % watch the 'entry' in the name
881
882\appendtoks
883    \dontcomplain
884  % \letinteractionparameter\c!width\zeropoint % a weird one
885\to \t_lists_every_renderingsetup
886
887\appendtoks
888    % better is to use a special list entry but we keep this for compatibility
889    \enforced\let\\\space
890    % so expanding this token register has to come *after* the font switch
891    \dontconvertfont % (**) this has to become an option (see publ)
892\to \t_lists_every_renderingtext
893
894\appendtoks
895    % because we want to avoid redundant lua calls we expand the
896    % location beforehand
897    \ifempty\currentlistentrylocation
898        \enforced\edef\currentlistentrylocation{\structurelistlocation}% needs attention
899    \fi
900    % because these tests happen often and because we're dealing with
901    % rather complex composed data we have special conditionals; keep
902    % in mind that testing for empty fails do to tagging being applied
903%   \edef\p_pagenumber{\listparameter\c!pagenumber}%
904%   \ifx\p_pagenumber\v!always
905%     \c_lists_has_page\conditionaltrue
906%     \c_lists_show_page\conditionaltrue
907%   \else
908%     \doifelsestructurelisthaspage{\c_lists_has_page\conditionaltrue}{\c_lists_has_page\conditionalfalse}%
909%     \ifx\p_pagenumber\v!yes
910%       \c_lists_show_page\conditionaltrue
911%     \else
912%       \c_lists_show_page\conditionalfalse
913%     \fi
914%   \fi
915    \c_lists_show_page\conditionalfalse % necessary?
916    \processcommacommand[\listparameter\c!pagenumber]\strc_lists_process_pagenumber
917    \ifconditional\c_lists_has_page \else
918      \doifelsestructurelisthaspage
919        {\c_lists_has_page\conditionaltrue}%
920        {\c_lists_has_page\conditionalfalse}%
921    \fi
922    % always forces number placement (in bib we use a forced number)
923    \edef\p_headnumber{\listparameter\c!headnumber}%
924    \ifx\p_headnumber\v!always
925      \c_lists_has_number\conditionaltrue
926      \c_lists_show_number\conditionaltrue
927    \else
928      \doifelsestructurelisthasnumber
929        {\c_lists_has_number\conditionaltrue}%
930        {\c_lists_has_number\conditionalfalse}%
931      \ifx\p_headnumber\v!yes
932        \c_lists_show_number\conditionaltrue
933      \else
934        \c_lists_show_number\conditionalfalse
935      \fi
936    \fi
937    \strc_lists_interaction_check
938\to \t_lists_every_renderingsetup
939
940\appendtoks
941    \strc_references_flush_destination_nodes
942\to \t_lists_every_renderingsynchronize
943
944\appendtoks
945   % as we don't want any interference we clear some variables
946   % afterwards
947   \lettonothing\currentlistentrylocation
948   \lettonothing\currentlistentrynumber
949   \lettonothing\currentlistentrytitle
950   \lettonothing\currentlistentrypagenumber
951   \c_lists_has_page\conditionalfalse
952   \c_lists_has_number\conditionalfalse
953   \c_lists_show_page\conditionalfalse
954   \c_lists_show_realpage\conditionalfalse
955   \c_lists_show_number\conditionalfalse
956\to \t_lists_every_renderingcleanup
957
958\lettonothing\m_strc_list_alternative % combined
959
960\protected\def\strc_lists_apply_renderingsetup
961  {\expand\t_lists_every_renderingsetup
962   % now we group
963   \begingroup
964   \ifempty\m_strc_list_alternative
965     \edef\currentlistalternative{\listparameter\c!alternative}%
966   \else
967     \let\currentlistalternative\m_strc_list_alternative
968   \fi
969   \directsetup{\listalternativeparameter\c!renderingsetup}\relax
970   \endgroup
971   % till here, where we reset locals
972   \expand\t_lists_every_renderingcleanup}
973
974% todo: provide packager via attributes
975
976\doinstallinjector\s!list
977
978\installcorenamespace{listalternativemethods} % the general wrapper of a rendering
979
980\startsetups[\??listrenderings:none]
981    % nothing, nb we use the [] syntax here because we end with a \cs
982\stopsetups
983
984\permanent\protected\def\currentlistentrytitlesynchronize
985  {\expand\t_lists_every_renderingsynchronize}
986
987\permanent\protected\def\currentlistentrytitlerendered
988  {\currentlistentrytitlesynchronize\currentlistentrytitle}
989
990\startsetups[\??listrenderings:command]
991    \edef\p_command{\listalternativeparameter\c!command}%
992    \ifempty\p_command
993        [\currentlist: \currentlistentrynumber\space -- \currentlistentrytitle\space -- \currentlistentrypagenumber]%
994    \else
995        \p_command
996          \currentlistentrynumber
997          \currentlistentrytitlerendered % {\currentlistentrytitlesynchronize\currentlistentrytitle}
998          \currentlistentrypagenumber
999    \fi
1000\stopsetups
1001
1002% \startsetups[\??listrenderings:\v!vertical]
1003%     \directsetup{\??listrenderings:generic}
1004% \stopsetups
1005
1006% \startsetups[\??listrenderings:\v!horizontal]
1007%     \directsetup{\??listrenderings:generic}
1008% \stopsetups
1009
1010\startsetups[\??listrenderings:generic]
1011    \typo_injectors_check_list
1012    \listparameter\c!before % can be \hskip
1013    \edef\p_command{\listalternativeparameter\c!command}
1014    \ifempty\p_command
1015        \listalternativeparameter\c!before
1016        \vbox {
1017            \forgetall
1018            \noindent % otherwise annotations are mirrored up
1019            \typo_injectors_mark_list
1020            \hbox \strc_lists_get_reference_attribute\v!all {
1021                \ifconditional\c_lists_show_number
1022                  % \ifconditional\c_lists_has_page
1023                        \hbox \strc_lists_get_reference_attribute\v!number {
1024                            \strc_lists_set_style_color\c!numberstyle\c!numbercolor\v!number
1025                            \listparameter\c!numbercommand\currentlistsymbol
1026                        }
1027                  % \fi
1028                \fi
1029                \hbox \strc_lists_get_reference_attribute\v!text {
1030                    \strc_lists_set_style_color\c!textstyle\c!textcolor\v!text
1031                    \expand\t_lists_every_renderingtext
1032                    \expand\t_lists_every_renderingsynchronize
1033                    \listparameter\c!textcommand\currentlistentrytitle
1034                }
1035                \ifconditional\c_lists_show_page
1036                    \ifconditional\c_lists_has_page
1037                        \hbox \strc_lists_get_reference_attribute\v!pagenumber {
1038                            \strc_lists_set_style_color\c!pagestyle\c!pagecolor\v!pagenumber
1039                            \listparameter\c!pagecommand\currentlistentrypagenumber
1040                        }
1041                    \fi
1042                \fi
1043            }
1044        }
1045        \listalternativeparameter\c!after
1046   \else
1047        \noindent % otherwise annotations are mirrored up
1048        \typo_injectors_mark_list
1049        \hbox \strc_lists_get_reference_attribute\v!all \strc_lists_get_destination_attribute {
1050            \p_command\currentlistentrynumber\currentlistentrytitle\currentlistentrypagenumber
1051        }
1052   \fi
1053   \listparameter\c!after
1054\stopsetups
1055
1056% to be documented: align, hang
1057
1058\startsetups[\??listrenderings:abc]
1059    \endgraf % are we grouped?
1060    \typo_injectors_check_list
1061  % \advanceby % yes or no ... \rightskip is also honored
1062    \leftskip\listparameter\c!margin % after \endgraf !
1063    \listparameter\c!before
1064    \endgraf
1065    \edef\p_width{\listparameter\c!width}
1066    \scratchdistance\listparameter\c!distance\relax
1067    \ifx\p_width\v!fit
1068        \scratchwidth\zeropoint
1069    \orelse\ifconditional\c_lists_has_number
1070        \scratchwidth\p_width
1071    \else
1072        \edef\p_aligntitle{\listparameter\c!aligntitle}
1073        \ifx\p_aligntitle\v!yes
1074            \scratchwidth\zeropoint
1075            \scratchdistance\zeropoint
1076        \else
1077            \scratchwidth\p_width
1078        \fi
1079    \fi
1080    \noindent % otherwise annotations are mirrored up
1081    \typo_injectors_mark_list
1082    \hbox \strc_lists_get_reference_attribute\v!all \strc_lists_get_destination_attribute {
1083        \setlocalhsize
1084        \hsize\localhsize
1085        \hbox to \hsize {
1086            \forgetall
1087            \strc_lists_set_style_color\c!style\c!color\v!all
1088            \scratchhsize\hsize
1089            \ifconditional\c_lists_has_number
1090                \ifconditional\c_lists_show_number
1091                  \setbox\b_strc_lists_number
1092%                    \hbox
1093%                      \strc_lists_get_reference_attribute\v!number
1094%                      \ifdim\scratchwidth>\zeropoint to \scratchwidth \fi
1095                    \simplealignedboxplus
1096                        \scratchwidth
1097                        {\listparameter\c!numberalign}
1098                        {\strc_lists_get_reference_attribute\v!number}
1099                        {
1100                            \strc_lists_set_style_color\c!numberstyle\c!numbercolor\v!number
1101                            \listparameter\c!numbercommand\currentlistsymbol
1102%                             \hfill
1103                        }
1104                \else
1105                    \setbox\b_strc_lists_number\emptyhbox
1106                \fi
1107            \else
1108                \scratchwidth\zeropoint
1109                \scratchdistance\zeropoint
1110                \setbox\b_strc_lists_number\emptyhbox
1111            \fi
1112            \ifconditional\c_lists_has_page
1113                \ifconditional\c_lists_show_page
1114                    \setbox\b_strc_lists_page\hpack {
1115                        \scratchdimen\listalternativeparameter\c!width
1116                        \hbox \strc_lists_get_reference_attribute\v!pagenumber \ifdim\scratchdimen>\zeropoint to \scratchdimen\fi {
1117                            \hfill
1118                            \strc_lists_set_style_color\c!pagestyle\c!pagecolor\v!pagenumber
1119                            \strut
1120                            \listparameter\c!pagecommand\currentlistentrypagenumber
1121                        }
1122                    }
1123                \else
1124                    \setbox\b_strc_lists_page\emptyhbox
1125                \fi
1126            \else
1127                \setbox\b_strc_lists_page\emptyhbox
1128            \fi
1129            \vbox {
1130                \hsize\scratchhsize
1131                \usealignparameter\listparameter
1132                \ifdim\scratchwidth<\hsize
1133                    % we have leftskip so we'd better just skip back instead of messing
1134                    % with hang*
1135                    \edef\p_hang{\listparameter\c!hang}
1136                    \hangindent\dimexpr\wd\b_strc_lists_number+\scratchdistance\relax
1137                    \hangafter\ifx\p_hang\v!no\zerocount\else\plusone\fi
1138                    \scratchdimen\listalternativeparameter\c!distance\relax
1139                    \ifzeropt\wd\b_strc_lists_page\orelse\ifdim\scratchdimen>\zeropoint\relax
1140                        \rightskip\scratchdimen\s!plus\listalternativeparameter\c!stretch\relax
1141                        \parfillskip-\rightskip
1142                    \fi
1143                \else
1144                    \scratchdistance\zeropoint
1145                \fi
1146                \parindent\zeropoint
1147                \dontleavehmode % this nils hang: i need to figure out why
1148                % % topaligned
1149                %
1150                % \scratchdimen\wd\b_strc_lists_number
1151                % \setbox\b_strc_lists_number\hbox to \hsize{\box\b_strc_lists_number\hss\box\b_strc_lists_page}%
1152                % \wd\b_strc_lists_number\scratchdimen
1153                %
1154                \box\b_strc_lists_number
1155                \hskip\scratchdistance\relax
1156                \begingroup
1157                \strc_lists_set_reference_attribute\v!text
1158                \strc_lists_set_style_color\c!textstyle\c!textcolor\v!text
1159                \expand\t_lists_every_renderingtext
1160                \expand\t_lists_every_renderingsynchronize
1161                \setstrut % needs checking, new here
1162                \begstrut
1163                \strc_lists_limitated_text\currentlistentrytitle
1164                \endstrut
1165                \endgroup
1166                \ifzeropt\wd\b_strc_lists_page\else
1167                    \nobreak
1168                    \currentlistfiller
1169                    \box\b_strc_lists_page
1170                \fi
1171            }
1172            \hss
1173        }
1174    }% new
1175    \endgraf % new, else problems with nointerlinespace and prevdepth
1176    \nointerlineskip % anders verkeerde spatiering bij multi-line
1177    \endgraf
1178    \allowbreak
1179    \listparameter\c!after
1180\stopsetups
1181
1182% % example from the context list
1183%
1184% \setuphead [part]    [page=right,placehead=yes]
1185% \setuplist [chapter] [alternative=d,before=\blank,after=\blank]
1186% \setuplist [part]    [before=\blank,after=\blank]
1187%
1188% \starttext
1189%   \startnarrower[2*right] \placecontent \stopnarrower
1190%   \blank[4*big]
1191%   \startsetups chapter
1192%     \blank \startnarrower[3*middle] \placecontent[criterium=local] \stopnarrower
1193%   \stopsetups
1194%   \placelist[part][criterium=text,after=\setups{chapter}]
1195%
1196%   \part{First part}       \chapter{Chapter one}  \chapter{Chapter two}
1197%   \chapter{Chapter three} \chapter{Chapter four} \chapter{Chapter five}
1198%   \part{Second part}      \chapter{Chapter one}  \chapter{Chapter two}
1199%   \chapter{Chapter three} \chapter{Chapter four} \chapter{Chapter five}
1200%   \part{Third part}       \chapter{Chapter one}  \chapter{Chapter two}
1201%   \chapter{Chapter three} \chapter{Chapter four} \chapter{Chapter five}
1202% \stoptext
1203
1204\startsetups[\??listrenderings:d]
1205    \ifvmode
1206        \advanceby\leftskip\listparameter\c!margin
1207    \fi
1208    \begingroup
1209    \ifvmode
1210        \noindent
1211    \fi
1212    \begingroup
1213    \strc_lists_set_reference_attribute\v!all
1214    \strc_lists_set_style_color\c!style\c!color\v!all
1215    \strc_lists_get_destination_attribute
1216    \begingroup
1217    \ifconditional\c_lists_show_number
1218        \donetrue
1219        \ifconditional\c_lists_has_number \else
1220            \edef\p_symbol{\listparameter\c!symbol}
1221            \ifempty\p_symbol
1222                \donefalse
1223            \fi
1224        \fi
1225        \ifdone
1226            \begingroup
1227            \strc_lists_set_reference_attribute\v!number
1228            \strc_lists_set_style_color\c!numberstyle\c!numbercolor\v!number
1229            \listparameter\c!left
1230            \listparameter\c!numbercommand\currentlistsymbol
1231            \listparameter\c!right
1232            \endgroup
1233            \kern.5\emwidth\relax
1234            \nobreak
1235        \fi
1236    \fi
1237    \endgroup
1238    \begingroup
1239    \strc_lists_set_reference_attribute\v!text
1240    \strc_lists_set_style_color\c!textstyle\c!textcolor\v!text
1241    \expand\t_lists_every_renderingtext
1242    \expand\t_lists_every_renderingsynchronize
1243    \setstrut % needs checking, new here
1244    \begstrut
1245    \strc_lists_limitated_text\currentlistentrytitle
1246    \endstrut
1247    \endgroup
1248    \begingroup
1249    \ifconditional\c_lists_has_page
1250        \ifconditional\c_lists_show_page
1251            \nobreak
1252            \hskip.75\emwidth\relax
1253            \nobreak
1254            \strc_lists_set_reference_attribute\v!pagenumber
1255            \strc_lists_set_style_color\c!pagestyle\c!pagecolor\v!pagenumber
1256            \strut
1257            \listparameter\c!pagecommand\currentlistentrypagenumber
1258        \fi
1259    \fi
1260    \endgroup
1261    \scratchdistance\listparameter\c!distance\relax
1262    \ifdim\scratchdistance<\emwidth
1263        \hskip\emwidth\s!plus\emwidth\s!minus.25\emwidth\relax
1264    \else
1265        \hskip\scratchdistance\s!plus.5\scratchdistance\s!minus.25\scratchdistance\relax
1266    \fi
1267    \endgroup
1268    \endgroup
1269\stopsetups
1270
1271\startsetups[\??listrenderings:e]
1272    \typo_injectors_check_list
1273    \noindent % otherwise annotations are mirrored up
1274    \typo_injectors_mark_list
1275    \hbox \strc_lists_get_reference_attribute\v!all \strc_lists_get_destination_attribute {
1276        \letlistparameter  \c!depth\zeropoint
1277        \resetlistparameter\c!color
1278        \inheritedlistframed {
1279            \letinteractionparameter\c!strut\v!no % still needed?
1280            \strc_lists_set_style_color\c!style\c!color\v!all
1281            \expand\t_lists_every_renderingtext
1282            \expand\t_lists_every_renderingsynchronize
1283            \setstrut
1284            \begstrut
1285            \strc_lists_limitated_text\currentlistentrytitle
1286            \endstrut
1287        }
1288    }
1289    \par
1290    \listparameter\c!inbetween
1291\stopsetups
1292
1293\startsetups[\??listrenderings:f]
1294    \typo_injectors_check_list
1295    \noindent % otherwise annotations are mirrored up
1296    \typo_injectors_mark_list
1297    \hbox \strc_lists_get_reference_attribute\v!all \strc_lists_get_destination_attribute {
1298        \dosetraggedhbox{\listparameter\c!align}%
1299        \raggedbox {
1300            \strc_lists_set_style_color\c!style\c!color\v!all
1301            \expand\t_lists_every_renderingtext
1302            \expand\t_lists_every_renderingsynchronize
1303            \setstrut
1304            \begstrut
1305            \strc_lists_limitated_text\currentlistentrytitle
1306            \endstrut
1307        }
1308    }
1309    \par
1310    \listparameter\c!inbetween
1311\stopsetups
1312
1313\startsetups[\??listrenderings:g]
1314    \typo_injectors_check_list
1315    \noindent % otherwise annotations are mirrored up
1316    \typo_injectors_mark_list
1317    \hbox \strc_lists_get_reference_attribute\v!all \strc_lists_get_destination_attribute {
1318        \midaligned {
1319            \strc_lists_set_style_color\c!style\c!color\v!all
1320            \expand\t_lists_every_renderingtext
1321            \expand\t_lists_every_renderingsynchronize
1322            \setstrut
1323            \begstrut
1324            \strc_lists_limitated_text\currentlistentrytitle
1325            \endstrut
1326        }
1327    }
1328    \par
1329    \listparameter\c!inbetween
1330\stopsetups
1331
1332%D This is a new one, similar to vertical and horizontal but better suited when
1333%D no command is set (WS):
1334
1335\definelistalternative
1336  [\v!interactive]
1337  [\c!renderingsetup=\??listrenderings:interactive,
1338   \c!before=\endgraf, % new per 2014-11-08
1339   \c!after=\endgraf]  % new per 2014-11-08
1340
1341\startsetups[\??listrenderings:interactive]
1342    \edef\p_command{\listalternativeparameter\c!command}%
1343    \typo_injectors_check_list
1344    \listparameter\c!before
1345    \noindent % otherwise annotations are mirrored up
1346    \typo_injectors_mark_list
1347    \hbox \strc_lists_get_reference_attribute\v!all \strc_lists_get_destination_attribute {
1348        \ifempty\p_command
1349            [
1350                \currentlist:\space
1351                \currentlistentrynumber
1352                \space\emdash\space
1353                \currentlistentrytitle
1354                \space\emdash\space
1355                \currentlistentrypagenumber
1356            ]
1357        \else
1358            \p_command\currentlistentrynumber\currentlistentrytitle\currentlistentrypagenumber
1359        \fi
1360   }
1361   \listparameter\c!after
1362\stopsetups
1363
1364%D One special for publications (as Alan loves to hangindent). No fonts and such
1365%D (for now). No interaction either as that is dealt with elsewhere.
1366%D
1367%D \currentlistsymbol
1368%D \currentlistentrynumber
1369%D \currentlistentrytitle
1370%D \currentlistentrypagenumber % not really used
1371
1372\definelistalternative
1373  [\v!paragraph]
1374  [\c!filler=\v!space,
1375   \c!renderingsetup=\??listrenderings:\v!paragraph]
1376
1377\startsetups[\??listrenderings:\v!paragraph]
1378    \endgraf % are we grouped?
1379    \typo_injectors_check_list % ?
1380    \listparameter\c!before
1381    \endgraf
1382    \begingroup
1383    \forgetall
1384    \noindent
1385    \parindent\zeropoint
1386    \edef\p_width{\listparameter\c!width}%
1387    \edef\p_distance{\listparameter\c!distance}% we are nice for bib users
1388    \edef\p_margin{\listparameter\c!margin}% we are nice for bib users
1389    \ifx\p_distance\v!none
1390        \scratchdistance\zeropoint
1391    \else
1392        \scratchdistance\p_distance
1393    \fi
1394    \ifx\p_margin\v!none
1395        \scratchoffset\zeropoint
1396    \else
1397        \scratchoffset\p_margin
1398    \fi
1399    \ifx\p_width\v!fit
1400        \scratchwidth\zeropoint
1401        \leftskip\scratchoffset
1402    \else
1403        \scratchwidth\p_width
1404        \ifzeropt\scratchoffset
1405            \leftskip\dimexpr\scratchwidth+\scratchdistance\relax
1406        \else
1407            \leftskip\scratchoffset
1408        \fi
1409    \fi
1410    \usealignparameter\listparameter
1411    \hskip-\leftskip
1412    \ifconditional\c_lists_has_number
1413        \ifconditional\c_lists_show_number
1414            \setbox\scratchbox
1415                \simplealignedbox\scratchwidth{\listparameter\c!numberalign}
1416                \bgroup
1417                    \useliststyleandcolor\c!numberstyle\c!numbercolor
1418                    \currentlistsymbol
1419                \egroup
1420            \ifdim\wd\scratchbox>\zeropoint
1421                \box\scratchbox
1422                \hskip\scratchdistance\relax
1423            \fi
1424        \fi
1425    \fi
1426    \begingroup
1427        \useliststyleandcolor\c!textstyle\c!textcolor
1428        \setstrut
1429        \begstrut
1430        \currentlistentrytitle
1431        \endstrut
1432    \endgroup
1433    \ifconditional\c_lists_has_page
1434        \ifconditional\c_lists_show_page
1435            \nobreak
1436            \currentlistfiller
1437            \begingroup
1438                \useliststyleandcolor\c!pagestyle\c!pagecolor
1439                \currentlistentrypagenumber
1440            \endgroup
1441        \fi
1442    \fi
1443    \endgraf
1444    \endgroup
1445    \allowbreak
1446    \listparameter\c!after
1447\stopsetups
1448
1449%D List elements are packaged in such a way that we can click on them in an
1450%D interactive document. Here are a few helpers.
1451
1452\newconstant\a_strc_lists_reference
1453\newconstant\a_strc_lists_destination
1454
1455\installcorenamespace{listinteractions}
1456
1457\letcsname\??listinteractions\v!number       \endcsname\v!number
1458\letcsname\??listinteractions\v!sectionnumber\endcsname\v!number
1459\letcsname\??listinteractions\v!text         \endcsname\v!text
1460\letcsname\??listinteractions\v!title        \endcsname\v!text
1461\letcsname\??listinteractions\v!page         \endcsname\v!pagenumber
1462\letcsname\??listinteractions\v!pagenumber   \endcsname\v!pagenumber
1463\letcsname\??listinteractions\v!all          \endcsname\v!all
1464\letcsname\??listinteractions\v!yes          \endcsname\v!all
1465
1466\permanent\def\listboxproperties       {\strc_lists_get_reference_attribute}
1467\permanent\def\listrenderingsetup      {\expand\t_lists_every_renderingtext}
1468\permanent\def\listrenderingsynchronize{\expand\t_lists_every_renderingsynchronize}
1469
1470\protected\def\strc_lists_interaction_check
1471  {\iflocation
1472     \strc_lists_interaction_check_yes
1473   \else
1474     \strc_lists_interaction_check_nop
1475   \fi}
1476
1477% \def\strc_lists_interaction_check_yes_yes
1478%   {\edef\p_interaction_forward{\listparameter\c!interaction}%
1479%    \ifcsname\??listinteractions\p_interaction_forward\endcsname
1480%     %\expandafter\let\expandafter\p_interaction_forward\csname\??listinteractions\p_interaction_forward\endcsname
1481%      \expandafter\let\expandafter\p_interaction_forward\lastnamedcs
1482%      \strc_references_get_simple_reference{internal(\currentlistentrylocation)}%
1483%      \a_strc_lists_reference\currentreferenceattribute
1484%    \else
1485%      \a_strc_lists_reference\attributeunsetvalue
1486%    \fi
1487%    \ifnum\a_strc_lists_reference=\attributeunsetvalue
1488%      \let\strc_lists_get_reference_attribute\gobbleoneargument
1489%      \let\strc_lists_set_reference_attribute\gobbleoneargument
1490%      \let\strc_lists_set_style_color        \strc_lists_set_style_color_normal
1491%    \else
1492%      \let\strc_lists_get_reference_attribute\strc_lists_get_reference_attribute_indeed
1493%      \let\strc_lists_set_reference_attribute\strc_lists_set_reference_attribute_indeed
1494%      \let\strc_lists_set_style_color        \strc_lists_set_style_color_special
1495%    \fi
1496%    \edef\p_interaction_backward{\namedheadparameter\currentlist\c!interaction}% \namedheadparameter !
1497%    \ifx\p_interaction_backward\v!list
1498%      \strc_references_set_simple_reference{*\currentlistentrylocation}%
1499%      \a_strc_lists_destination\currentdestinationattribute
1500%    \else
1501%      \a_strc_lists_destination\attributeunsetvalue
1502%    \fi
1503%    \ifnum\a_strc_lists_destination=\attributeunsetvalue
1504%      \lettonothing\strc_lists_get_destination_attribute
1505%      \lettonothing\strc_lists_set_destination_attribute
1506%    \else
1507%      \let\strc_lists_get_destination_attribute\strc_lists_get_destination_attribute_indeed
1508%      \let\strc_lists_set_destination_attribute\strc_lists_set_destination_attribute_indeed
1509%    \fi}
1510
1511\def\strc_lists_interaction_check_yes_yes
1512  {\edef\p_interaction_forward {\listparameter\c!interaction}%
1513   \edef\p_interaction_backward{\namedheadparameter\currentlist\c!interaction}% \namedheadparameter !
1514   \ifcsname\??listinteractions\p_interaction_forward\endcsname
1515    %\expandafter\let\expandafter\p_interaction_forward\csname\??listinteractions\p_interaction_forward\endcsname
1516     \expandafter\let\expandafter\p_interaction_forward\lastnamedcs
1517     \ifempty{\structurelistexternal}% luacall
1518       \strc_references_get_simple_reference{internal(\currentlistentrylocation)}%
1519     \else
1520     % \writestatus{FAR OUT LIST}{\structurelistexternal::page(\number\structurelistrealpagenumber)}%
1521       \strc_references_get_simple_reference{\structurelistexternal::page(\number\structurelistrealpagenumber)}%
1522       \let\p_interaction_backward\empty
1523     \fi
1524     \a_strc_lists_reference\currentreferenceattribute
1525   \else
1526     \a_strc_lists_reference\attributeunsetvalue
1527   \fi
1528   \ifnum\a_strc_lists_reference=\attributeunsetvalue
1529     \let\strc_lists_get_reference_attribute\gobbleoneargument
1530     \let\strc_lists_set_reference_attribute\gobbleoneargument
1531     \let\strc_lists_set_style_color        \strc_lists_set_style_color_normal
1532   \else
1533     \let\strc_lists_get_reference_attribute\strc_lists_get_reference_attribute_indeed
1534     \let\strc_lists_set_reference_attribute\strc_lists_set_reference_attribute_indeed
1535     \let\strc_lists_set_style_color        \strc_lists_set_style_color_special
1536   \fi
1537   \ifx\p_interaction_backward\v!list
1538     \strc_references_set_simple_reference{*\currentlistentrylocation}%
1539     \a_strc_lists_destination\currentdestinationattribute
1540   \else
1541     \a_strc_lists_destination\attributeunsetvalue
1542   \fi
1543   \ifnum\a_strc_lists_destination=\attributeunsetvalue
1544     \lettonothing\strc_lists_get_destination_attribute
1545     \lettonothing\strc_lists_set_destination_attribute
1546   \else
1547     \let\strc_lists_get_destination_attribute\strc_lists_get_destination_attribute_indeed
1548     \let\strc_lists_set_destination_attribute\strc_lists_set_destination_attribute_indeed
1549   \fi}
1550
1551\def\strc_lists_interaction_check_yes_nop
1552  {\a_strc_lists_reference  \attributeunsetvalue
1553   \a_strc_lists_destination\attributeunsetvalue
1554   \let\strc_lists_get_reference_attribute\gobbleoneargument
1555   \let\strc_lists_set_reference_attribute\gobbleoneargument
1556   \lettonothing\strc_lists_get_destination_attribute
1557   \lettonothing\strc_lists_set_destination_attribute
1558   \let\strc_lists_set_style_color\strc_lists_set_style_color_normal}
1559
1560\def\strc_lists_interaction_check_yes
1561  {\ifempty\currentlistentrylocation
1562     \strc_lists_interaction_check_yes_nop
1563   \orelse\ifnum\currentlistentrylocation=\zerocount
1564     \strc_lists_interaction_check_yes_nop
1565   \else
1566     \strc_lists_interaction_check_yes_yes
1567   \fi}
1568
1569\def\strc_lists_interaction_check_nop
1570  {\let\strc_lists_get_reference_attribute  \gobbleoneargument
1571   \let\strc_lists_set_reference_attribute  \gobbleoneargument
1572   \lettonothing\strc_lists_get_destination_attribute
1573   \lettonothing\strc_lists_set_destination_attribute
1574   \let\strc_lists_set_style_color          \strc_lists_set_style_color_normal}
1575
1576\strc_lists_interaction_check_nop
1577
1578\def\strc_lists_get_reference_attribute_indeed#element%
1579  {\ifx#element\p_interaction_forward
1580     attr \referenceattribute\a_strc_lists_reference
1581   \fi}
1582
1583\def\strc_lists_set_reference_attribute_indeed#element%
1584  {\ifx#element\p_interaction_forward
1585     \c_attr_reference\a_strc_lists_reference
1586   \fi}
1587
1588\def\strc_lists_get_destination_attribute_indeed
1589  {attr \destinationattribute\number\a_strc_lists_destination}
1590
1591\def\strc_lists_set_destination_attribute_indeed
1592  {\c_attr_destination\a_strc_lists_destination}
1593
1594\protected\def\strc_lists_set_style_color_normal#style#color#element%
1595  {\useliststyleandcolor#style#color}
1596
1597\protected\def\strc_lists_set_style_color_special#style#color#element%
1598  {\useliststyleandcolor#style#color%
1599   \ifempty\currentcolorparameter
1600     \ifx#element\p_interaction_forward
1601       \setlocationcolor
1602     \fi
1603 % \else
1604 %   \resetinteractionparameter\c!color
1605 %   \resetinteractionparameter\c!contrastcolor
1606   \fi}
1607
1608\let\strc_lists_set_style_color\strc_lists_set_style_color_normal
1609
1610%D A helper:
1611
1612\protected\def\strc_lists_limitated_text#text%
1613  {\edef\p_maxwidth{\listparameter\c!maxwidth}%
1614   \ifempty\p_maxwidth
1615     \listparameter\c!textcommand{#text}%
1616   \else
1617     \listparameter\c!textcommand{\limitatetext{#text}\p_maxwidth{\splitsymbol{\listparameter\c!limittext}}}%
1618   \fi}
1619
1620% public helpers
1621
1622\permanent\protected\def\startcurrentlistentrywrapper
1623  {\hbox \strc_lists_get_reference_attribute\v!all \strc_lists_get_destination_attribute\bgroup}
1624
1625\aliased\let\stopcurrentlistentrywrapper\egroup
1626
1627\permanent\def\currentlistentryreferenceattribute  {\strc_lists_get_reference_attribute}   % this definition can change
1628\permanent\def\currentlistentrydestinationattribute{\strc_lists_get_destination_attribute} % this definition can change
1629\permanent\def\currentlistentrylimitedtext         {\strc_lists_limitated_text}            % this definition can change
1630
1631% todo:
1632
1633\permanent\def\utilitylistlength{\listlength} % also in strc-reg (downward compatible name)
1634
1635\mutable\let\listlength\!!zerocount           % also in strc-reg
1636
1637\permanent\tolerant\protected\def\determinelistcharacteristics[#list]#spacer[#S#settings]%
1638  {\begingroup
1639   \cdef\currentlist{\firststructureelementinlist{#list}}%
1640   \ifempty\currentlist
1641     \endgroup
1642     \let\listlength\!!zerocount
1643   \else
1644     \setupcurrentlist[#settings]%
1645     \strc_lists_analyze{#list}{\listparameter\c!criterium}{\listparameter\c!reference}%
1646     \normalexpanded{\endgroup\noexpand\edef\noexpand\listlength{\structurelistsize}}%
1647   \fi
1648   \strc_lists_set_mode}
1649
1650\protect \endinput
1651