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