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