%D \module %D [ file=strc-lst, %D version=2008.10.20, %D title=\CONTEXT\ Structure Macros, %D subtitle=Lists, %D author=Hans Hagen, %D date=\currentdate, %D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] %C %C This module is part of the \CONTEXT\ macro||package and is %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. \writestatus{loading}{ConTeXt Structure Macros / Lists} \registerctxluafile{strc-lst}{} % clean up in progress ... % % also (long term) todo: % % autocrossdocument % auto refs to lists (chain) % % TODO: strut=yes|no % % \lists -> strc_lists \unprotect %D Lists are mostly used for tables of contents but are in fact a rather generic %D feature of \CONTEXT. We seperate between storage and rendering and the current %D implementation is a reworked version of all that was added in steps. As lists %D are used frequently compatibility is an important aspect. A couple of rendering %D alternatives are provided here but more are possible. \installcorenamespace{list} \installframedcommandhandler \??list {list} \??list \let\setuplists\setuplist % yes or no \setuplist [\c!height=\v!broad, \c!depth=\v!broad, \c!offset=.25\emwidth, \c!state=\v!start, \c!coupling=\v!off, \c!criterium=\v!local, \c!reference=,% was number which was sort of obsolete \c!width=3\emwidth, %\c!maxwidth=, \c!distance=\zeropoint, \c!margin=\zeropoint, \c!alternative=\c!b, \c!style=\v!normal, %\c!color=, \c!textstyle=\listparameter\c!style, % \currentliststyleparameter (but then we need to set it in every ...) \c!numberstyle=\listparameter\c!style, % \currentliststyleparameter \c!pagestyle=\listparameter\c!style, % \currentliststyleparameter \c!textcolor=\listparameter\c!color, % \currentlistcolorparameter (but then we need to set it in every ...) \c!numbercolor=\listparameter\c!color, % \currentlistcolorparameter \c!pagecolor=\listparameter\c!color, % \currentlistcolorparameter \c!numbercommand=\firstofoneargument, \c!textcommand=\firstofoneargument, \c!pagecommand=\firstofoneargument, \c!pagenumber=\v!yes, % better: 'first' \c!headnumber=\v!yes, % better: 'second' % \c!sectionnumber=\listparameter\c!headnumber, % use this instead \c!interaction=\v!all, % was \v!sectionnumber, % or make this headnumber (or accept both) \c!label=\v!no, %\c!extras=, %\c!aligntitle=, %\c!before=, %\c!after=, %\c!inbetween=, %\c!symbol=, %\c!expansion=, \c!limittext=\languageparameter\c!limittext] % not used currently %D Helpers: \unexpanded\def\usenestedliststyleandcolor#style#color% will change {\useliststyleandcolor#style#color% % how about style \ifx\currentcolorparameter\empty \else \resetinteractionparameter\c!color \resetinteractionparameter\c!contrastcolor \fi} \unexpanded\def\doifelselist#tag% can also move to \installcommandhandler {\ifcsname\namedlisthash{#tag}\s!parent\endcsname \expandafter\firstoftwoarguments \else \expandafter\secondoftwoarguments \fi} \let\doiflistelse\doifelselist %D Regular list entries are bound to a specific location in order to %D get the right pagenumber etc.\ associated. When pushing something %D inbetween (in mkiv) it ends up directtly in the list. This is the %D default because otherwise users will wonder why spacing might get %D messed up (due to an unseen but present node). It is possible to %D force a location by explicitly setting \type {location} to \type %D {here}. %D %D Another way to force a certain order is to set the \type {order} %D variable when placing a list. The \type {command} option only %D pushes commands into the right order, and \type {all} orders all %D entries (which might be too much). In this case no specific %D location is needed with the inbetween method. Maybe additional %D mechanisms show up some day. See \type {inbetween-001.tex} for an %D example. % command : location=none % userdata : location=none % simple : location=here \installcorenamespace {listlocations} \unexpanded\def\doifelseinlistentry#1% {\ifcsname\??listlocations#1\endcsname \ifnum\lastnamedcs=\structurelistlocation\relax \doubleexpandafter\firstoftwoarguments \else \doubleexpandafter\secondoftwoarguments \fi \else \expandafter\secondoftwoarguments \fi} \unexpanded\def\doifelseincurrentlistentry {\doifelseinlistentry\currentlist} \unexpanded\def\structurelistinject {\dotripleempty\strc_lists_inject} \def\strc_lists_inject[#tag]% {\begingroup \edef\currentlist{#tag}% \doifelse{\listparameter\c!state}\v!start\strc_lists_inject_yes\strc_lists_inject_nop} \def\strc_lists_inject_nop[#dummya][#dummyb]% {\endgroup} % \unexpanded \def\strc_lists_inject_enhance#listindex% {\expandafter\clf_deferredenhancelist\number#listindex\relax} \unexpanded\def\strc_lists_inject_yes[#settings][#userdata]% can be used directly {\setupcurrentlist[\c!type=userdata,\c!location=\v!none,#settings]% grouped (use \let... \edef\p_location{\listparameter\c!location}% \setnextinternalreference \scratchcounter\clf_addtolist references { internal \locationcount % block {\currentsectionblock} % section structures.sections.currentid() % location {\p_location} } metadata { kind {\listparameter\c!type} name {\currentlist} % level structures.sections.currentlevel() catcodes \catcodetable } userdata {\detokenize\expandafter{\normalexpanded{#userdata}}} \relax \edef\currentlistnumber{\the\scratchcounter}% \setxvalue{\??listlocations\currentlist}{\the\locationcount}% \ifx\p_location\v!here % this branch injects nodes ! \strc_lists_inject_enhance{\currentlistnumber}% \clf_setinternalreference internal \locationcount view {\interactionparameter\c!focus}% \relax % this will change \xdef\currentstructurelistattribute{\the\lastdestinationattribute}% \dontleavehmode\hpack attr \destinationattribute \lastdestinationattribute{}% todo \else % and this one doesn't \clf_enhancelist\currentlistnumber\relax \fi \endgroup} % todo: make like \strc_references_direct_full_user ... with {}{}{} \unexpanded\def\strc_lists_inject_direct[#tag]% [#settings][#userdata] {\begingroup \edef\currentlist{#tag}% \strc_lists_inject_yes} % [#settings][#userdata] \unexpanded\def\writebetweenlist{\dodoubleempty \strc_lists_write_between} \unexpanded\def\writedatatolist {\dotripleargument\strc_lists_write_data_to} \unexpanded\def\writetolist {\dodoubleempty \strc_lists_write_to} \def\strc_lists_write_between[#tag]% {\begingroup \edef\currentlist{#tag}% \doifelse{\namedlistparameter{#tag}\c!state}\v!start \strc_lists_write_between_yes \strc_lists_write_between_nop} \def\strc_lists_write_between_yes[#settings]#command% {\strc_lists_inject_yes[#settings,\c!type=\s!command][command={#command}]} \def\strc_lists_write_between_nop[#settings]#command% {\endgroup} \def\strc_lists_write_data_to[#tag]% {\begingroup \edef\currentlist{#tag}% \doifelse{\namedlistparameter{#tag}\c!state}\v!start \strc_lists_write_data_to_yes \strc_lists_write_data_to_nop} \def\strc_lists_write_data_to_yes[#settings][#userdata]% {\ifthirdargument % no need to have an extra step ... used seldom \strc_lists_inject_yes[#settings,\c!type=\s!userdata][#userdata]% \else \strc_lists_inject_yes[\c!type=\s!userdata][#settings]% \fi} \def\strc_lists_write_data_to_nop[#settings][#userdata]% {\endgroup} \def\strc_lists_write_to[#tag]% {\begingroup \edef\currentlist{#tag}% \doifelse{\namedlistparameter{#tag}\c!state}\v!start \strc_lists_write_to_yes \strc_lists_write_to_nop} \def\strc_lists_write_to_yes[#settings]#first#second% no \s!first because we don't expand user settings {\strc_lists_inject_yes[\c!location=\v!here,#settings,\c!type=\s!simple][first={#first},second={#second}]} \def\strc_lists_write_to_nop[#settings]#first#second% {\endgroup} % \strc_lists_inject_nop[][] %D When placing a list either one or a set can be giving. This makes %D it possible to flush for instance an nested (or merged) table of %D contents. Keep in mind that placing a list is what we do most (think %D of tables of contents, figures, etc.\ but other usage is also possible %D in which case low level commands have to be used. \newtoks\everystructurelist \unexpanded\def\placelist {\dodoubleempty\strc_lists_place} \unexpanded\def\placerawlist {\dodoubleempty\strc_lists_place_raw} \def\strc_lists_place[#taglist][#settings]% {\begingroup \startpacked[\v!blank]% \edef\m_list {#taglist}% \edef\m_first{\firststructureelementinlist{#taglist}}% \ifx\m_list\m_first % use settings of first \else % use settings of root \let\m_first\empty \fi \strc_lists_place_indeed\m_first\m_list{#settings}% \stoppacked \endgroup} \def\strc_lists_place_raw[#tag][#settings]% just one list {\strc_lists_place_indeed\empty{#tag}{#settings}} \def\strc_lists_place_indeed#tag#list#settings% {\begingroup \the\t_lists_every_renderingcleanup % \let\currentlistentrylocation\empty \edef\currentlist{#tag}% \setupcurrentlist[#settings]% \the\everystructurelist % \doif{\listparameter\c!coupling}\v!on{\startlistreferences{#tag}}% \strc_lists_place_current % maybe inline {#list}% {\listparameter\c!criterium}% {\listparameter\c!reference}% {\listparameter\c!extras}% {\listparameter\c!order}% % \stoplistreferences \par % todo: only when vertical list mode \endgroup \strc_lists_set_mode} \def\strc_lists_set_mode {\ifcase\structurelistsize\relax \resetsystemmode\v!list \else \setsystemmode \v!list \fi} %D Complete lists are just lists but with a title. They were %D originally introduced to minimize the number for commands in %D a document source but nowadays that is less an issue in the %D sense that the extra few lines are neglectable to the rest. \unexpanded\def\systemsuppliedchapter {\csname\v!chapter\endcsname} % obsolete \unexpanded\def\systemsuppliedtitle {\csname\v!title \endcsname} % obsolete \unexpanded\def\completelist {\dodoubleempty\strc_lists_complete} \def\strc_lists_complete[#tag][#settings]% {\strc_lists_complete_indeed[#tag][#tag][#settings]} \def\strc_lists_complete_indeed[#singular][#plural][#settings]% {\normalexpanded{\startnamedsection[\v!title][\c!title=\headtext{#plural},\c!reference=#singular]}% {} around ref ? \strc_lists_place[#singular][#settings]% \stopnamedsection} %D Combined list provide a nice level of abstraction. %D %D \starttyping %D \definecombinedlist[whatever][a,b,c][settings] %D \stoptyping \unexpanded\def\definecombinedlist {\dotripleempty\strc_lists_combined_define} \def\strc_lists_combined_define[#tag][#list][#settings]% {\definelist[#tag][\c!criterium=\v!local,\c!reference=,\c!alternative=,\c!list={#list},#settings]% inherits from root \setvalue{\e!setup #tag\e!endsetup}{\dodoubleempty\strc_lists_combined_setup [#tag]}% \setvalue{\e!place #tag}{\dodoubleempty\strc_lists_combined_place [#tag]}% \setvalue{\e!complete #tag}{\dodoubleempty\strc_lists_combined_complete[#tag]}} \unexpanded\def\setupcombinedlist {\dodoubleargument\strc_lists_combined_setup} \def\strc_lists_combined_setup[#tag][#settings]% {\ifsecondargument \setuplist[#tag][#settings]% we don't want to mess up the parent \fi} \unexpanded\def\placecombinedlist {\dodoubleempty\strc_lists_combined_place} \def\strc_lists_combined_place[#tag][#settings]% i.e. no list set in settings {\begingroup % \edef\currentlist{#tag}% \setupcurrentlist[#settings]% \edef\m_strc_list_alternative{\listparameter\c!alternative}% we only inherit alternative % \strc_lists_place_indeed{#tag}{\listparameter\c!list}{#settings}% \endgroup} \def\strc_lists_combined_complete[#tag][#settings]% {\normalexpanded{\startnamedsection[\v!title][\c!title={\headtext{#tag}},\c!reference=#tag]}% {} around ref ? \strc_lists_combined_place[#tag][#settings]% \stopnamedsection} %D Given that some variables are set, we can ask for some properties of %D an entry. \def\currentstructurelistnumber{0} % injection \def\currentlistmethod {entry} % typesetting \def\currentlistindex {0} % typesetting (maybe also a real counter) \unexpanded\def\savedlistnumber #1#2{\clf_savedlistnumber {#1}\numexpr#2\relax} \unexpanded\def\savedlisttitle #1#2{\clf_savedlisttitle {#1}\numexpr#2\relax} \unexpanded\def\savedlistprefixednumber#1#2{\clf_savedlistprefixednumber{#1}\numexpr#2\relax} \newconditional\c_lists_show_realpage \installcorenamespace {listpagenumber} \setvalue{\??listpagenumber\v!always }{\settrue\c_lists_show_page\settrue\c_lists_has_page} \setvalue{\??listpagenumber\v!yes }{\settrue\c_lists_show_page} \setvalue{\??listpagenumber\s!realpage}{\settrue\c_lists_show_page\settrue\c_lists_show_realpage} \def\strc_lists_process_pagenumber#1% {\begincsname\??listpagenumber#1\endcsname} \def\structurelistlocation {\clf_listlocation\numexpr\currentlistindex\relax} \def\structurelistrealpagenumber {\clf_listrealpage{\currentlist}\numexpr\currentlistindex\relax} \unexpanded\def\structurelistpagenumber {\dostarttagged\t!listpage\empty \ifconditional\c_lists_show_realpage \clf_listrealpage{\currentlist}\numexpr\currentlistindex\relax \else \clf_listprefixedpage {\currentlist}% \currentlistindex { separatorset {\listparameter\c!pageprefixseparatorset} conversionset {\listparameter\c!pageprefixconversionset} set {\listparameter\c!pageprefixset} segments {\listparameter\c!pageprefixsegments} connector {\listparameter\c!pageprefixconnector} }% { prefix {\listparameter\c!pageprefix} conversionset {\listparameter\c!pageconversionset} starter {\listparameter\c!pagestarter} stopper {\listparameter\c!pagestopper} }% \relax \fi \dostoptagged} \unexpanded\def\structurelistuservariable#name% {\dostarttagged\t!listdata{#name}% \clf_listuserdata{\currentlist}\currentlistindex{#name}% \dostoptagged} \def\rawstructurelistuservariable#name% {\clf_listuserdata{\currentlist}\currentlistindex{#name}} \unexpanded\def\structurelistfirst {\structurelistuservariable\s!first } % s! \unexpanded\def\structurelistsecond{\structurelistuservariable\s!second} % s! \def\rawstructurelistfirst {\rawstructurelistuservariable\s!first } % s! % was \unexpanded \def\rawstructurelistsecond{\rawstructurelistuservariable\s!second} % s! % was \unexpanded \unexpanded\def\doifelsestructurelisthaspage {\clf_doifelselisthaspage{\currentlist}\numexpr\currentlistindex\relax} \unexpanded\def\doifelsestructurelisthasnumber {\clf_doifelselisthasnumber{\currentlist}\numexpr\currentlistindex\relax} \let\doifstructurelisthaspageelse \doifelsestructurelisthaspage \let\doifstructurelisthasnumberelse\doifelsestructurelisthasnumber \unexpanded\def\structurelistgenerictitle {\dostarttagged\t!listcontent\empty \clf_listtitle{\currentlist}\currentlistindex\relax \dostoptagged} \unexpanded\def\structurelistgenericnumber % tricky, we need to delay tagging as we have nested lua calls {\dostarttagged\t!listtag\empty \clf_listprefixednumber {\currentlist}% \currentlistindex {% prefix {\listparameter\c!prefix}% separatorset {\listparameter\c!prefixseparatorset}% conversionset {\listparameter\c!prefixconversionset}% starter {\listparameter\c!prefixstarter}% stopper {\listparameter\c!prefixstopper}% set {\listparameter\c!prefixset}% segments {\listparameter\c!prefixsegments}% connector {\listparameter\c!prefixconnector}% }% {% separatorset {\listparameter\c!numberseparatorset}% conversionset {\listparameter\c!numberconversionset}% starter {\listparameter\c!numberstarter}% stopper {\listparameter\c!numberstopper}% segments {\listparameter\c!numbersegments}% }% \relax \dostoptagged} % TODO: pass extra tag name (contents, figures, bibliography ...) \unexpanded\def\strc_lists_place_current#list#criterium#reference#extras#order% beware, not a user command {\dostarttaggedchained\t!list\empty\??list \clf_processlist names {#list} criterium {#criterium} reference {#reference} extras {#extras} order {#order} \relax \dostoptagged} \unexpanded\def\strc_lists_analyze#list#criterium#reference% {\clf_analyzelist names {#list} criterium {#criterium} reference {#reference} \relax} \def\firststructureelementinlist#list% expandable {\firstinset{#list}} \def\structurelistsize {\clf_listsize} %D Depending on what kind of list we have (e.g.\ a section related one) %D processors can be defined. % push pop test: % % \starttext % \placelist[chapter] [after={\placelist[section][criterium=local]}] % \chapter{One} \section{Alpha} \section{Beta} % \chapter{Two} \section{First} \section{Second} % \stoptext \installcorenamespace{structurelistprocessor} % the topmost list handler \installcorenamespace{listextra} % control of that handler \installcommandhandler \??listextra {listextra} \??listextra \definelistextra % example [\v!page] [\c!before={\showmessage\m!system{14}{\currentlist/\currentlistindex}\page}] \unexpanded\def\installstructurelistprocessor#tag#meaning% {\expandafter\normaldef\csname\??structurelistprocessor#tag\endcsname{#meaning}} \def\usestructurelistprocessor#tag% {\csname\??structurelistprocessor#tag\endcsname} \let\dotaglistlocation\relax \def\strc_lists_entry_process_default {no list method} % \def\strc_lists_entry_process % assume things to be set up % {\listextraparameter\c!before % \dostarttagged\t!listitem\currentlist % \dotaglistlocation % \csname\??structurelistprocessor % \ifcsname\??structurelistprocessor\currentlist:\currentlistmethod\endcsname\currentlist:\currentlistmethod\else % \ifcsname\??structurelistprocessor\currentlistmethod \endcsname\currentlistmethod \else % \ifcsname\??structurelistprocessor\currentlist \endcsname\currentlist \else % \s!default \fi\fi\fi % \endcsname % \dostoptagged % \listextraparameter\c!after} \def\strc_lists_entry_process % assume things to be set up {\listextraparameter\c!before \dostarttagged\t!listitem\currentlist \dotaglistlocation \ifcsname\??structurelistprocessor\currentlist:\currentlistmethod\endcsname\lastnamedcs\else \ifcsname\??structurelistprocessor\currentlistmethod \endcsname\lastnamedcs\else \ifcsname\??structurelistprocessor\currentlist \endcsname\lastnamedcs\else \strc_lists_entry_process_default\fi\fi\fi \dostoptagged \listextraparameter\c!after} \unexpanded\def\strclistsentryprocess#tag#method#index#extra% This one is called at the lua end! {\clf_pushlist#index\relax %\let\currentlistentrylocation\empty \edef\currentlist {#tag}% \edef\currentlistmethod{#method}% \edef\currentlistindex {#index}% \edef\currentlistextra {#extra}% \strc_lists_entry_process \clf_poplist} % lists that have a number/title are kind of generic and can share code \installstructurelistprocessor\s!default {\strc_lists_entry_process_default} \installstructurelistprocessor\s!simple {\let\currentlistentrynumber \structurelistfirst \let\currentlistentrytitle \structurelistsecond \let\currentlistentrypagenumber\structurelistpagenumber \strc_lists_apply_renderingsetup} \installstructurelistprocessor\s!command {\clf_listuserdata{\currentlist}\currentlistindex{\s!command}} \installstructurelistprocessor{section} {\let\currentlistentrynumber \structurelistgenericnumber \let\currentlistentrytitle \structurelistgenerictitle \let\currentlistentrypagenumber\structurelistpagenumber \strc_lists_apply_renderingsetup} \installstructurelistprocessor{number+title} {\let\currentlistentrynumber \structurelistgenericnumber \let\currentlistentrytitle \structurelistgenerictitle \let\currentlistentrypagenumber\structurelistpagenumber \strc_lists_apply_renderingsetup} % example of usage elsewhere: % % \installstructcurelistprocessor{pubs:userdata} % {\clf_listuserdata{\currentlist}\currentlistindex{bibref}} %D List symbols are used in interactive documents where no numbers %D are used but nevertheless structure is present. Beware, the list %D symbol macro gets an argument passed, i.e. when this argument is %D not picked up, the symbol becomes a kind of prefix. It's not really %D a user command (and might even get protected). \unexpanded\def\listsymbol[#tag]#number% {\begingroup \edef\currentlist{#tag}% \def\currentlistentrynumber{#number}% no edef else tag problems \currentlistsymbol \endgroup} % For historical reasons we're stuck to symbols, so in order to generalize, % we have to hook it into the symbol handle. One way to deal with this is % to use a different key and as it makes sense to use setups instead of % def's we use a new key 'renderingsetup' which is the name of a setup. \def\strc_lists_assign_dimen#dimension#key#default% {\edef\m_strc_list_dimen{\listparameter#key}% \doifelseinset\m_strc_list_dimen{\v!fit,\v!broad}{#dimension#default}{#dimension\m_strc_list_dimen}\relax} \definesymbol[\v!list][\v!none ][\strc_lists_symbol_none] \definesymbol[\v!list][\v!one ][\strc_lists_symbol_one] \definesymbol[\v!list][\v!two ][\strc_lists_symbol_two] \definesymbol[\v!list][\v!three ][\strc_lists_symbol_three] \definesymbol[\v!list][\s!default][\strc_lists_symbol_default] \definesymbol[\v!list][\s!unknown][\strc_lists_symbol_unknown] \unexpanded\def\currentlistsymbol {\edef\p_symbol{\listparameter\c!symbol}% \doifelseinsymbolset\v!list\p_symbol {\directsymbol\v!list\p_symbol} {\directsymbol\v!list\s!default}} \unexpanded\def\strc_lists_symbol_none {\strc_lists_assign_dimen\scratchwidth\c!width{1.5\emwidth}% \hpack to \scratchwidth{}} \unexpanded\def\strc_lists_symbol_one {\strut\symbol[bullet]} \unexpanded\def\strc_lists_symbol_two {\vrule\s!width\emwidth\s!height\exheight\s!depth\zeropoint\relax} \unexpanded\def\strc_lists_symbol_three {\begingroup \strc_lists_assign_dimen\scratchwidth \c!width {1.5\emwidth}% \strc_lists_assign_dimen\scratchheight\c!height\exheight \strc_lists_assign_dimen\scratchdepth \c!depth \zeropoint \vrule\s!width\scratchwidth\s!height\scratchheight\s!depth\scratchdepth \endgroup} \unexpanded\def\strc_lists_symbol_unknown {\listparameter\c!symbol} \installcorenamespace{listsymbollabels} \def\strc_lists_symbol_label_unknown {\leftlabeltext\currentlistlabel \listparameter\c!starter \currentlistentrynumber \listparameter\c!stopper \rightlabeltext\currentlistlabel} \unexpanded\def\strc_lists_symbol_default {\dontleavehmode \strut \begingroup \edef\currentlistlabel{\listparameter\c!label}% can be used in label % \csname\??listsymbollabels % \ifcsname\??listsymbollabels\currentlistlabel\endcsname\currentlistlabel\else\s!unknown\fi % \endcsname \ifcsname\??listsymbollabels\currentlistlabel\endcsname \lastnamedcs \else \strc_lists_symbol_label_unknown \fi \endgroup} \letvalue{\??listsymbollabels\s!unknown}\strc_lists_symbol_default \setvalue{\??listsymbollabels}% default (empty) {\listparameter\c!starter \currentlistentrynumber \listparameter\c!stopper} \setvalue{\??listsymbollabels\v!no}% also default {\listparameter\c!starter \currentlistentrynumber \listparameter\c!stopper} \setvalue{\??listsymbollabels\v!none}% real minimal (as suggested by WS) {\currentlistentrynumber} \setvalue{\??listsymbollabels\v!yes}% auto (use value stored in tuc file) {\edef\currentlistlabel{\clf_listlabel\currentlistindex{\currentlistlabel}}% \leftlabeltext\currentlistlabel \listparameter\c!starter \currentlistentrynumber \listparameter\c!stopper \rightlabeltext\currentlistlabel} % a : nr - tit - pag % b : nr - tit - fill - pag % c : nr - tit - dots - pag % d : inline % e : interaction % f : interaction % g : interaction \installcorenamespace{listalternative} % specific ways of rendering a list \installcorenamespace{listrenderings} % a namespace for setups (rather local) \installcommandhandler \??listalternative {listalternative} \??listalternative % Commands are bound to specific list instances as often these are % quite special and don't apply to multiple. So, being strict saves % us resets. % \installcorenamespace{listfiller} % % \unexpanded\def\installlistfiller#1#2% % {\setuvalue{\??listfiller#1}{#2}} % % \unexpanded\def\listfiller#1% % {\begincsname\??listfiller#1\endcsname} % % \unexpanded\def\currentlistfiller % {\begingroup % \edef\p_filler{\listalternativeparameter\c!filler}% % \ifcsname\??listfiller\p_filler\endcsname % \lastnamedcs % \else % \p_filler % \fi % \endgroup} % % \installlistfiller\v!sym % original one % {\begingroup % \scratchdimen.5\emwidth % \hskip\scratchdimen % \gleaders % \hbox to \scratchdimen % {\hss % \uselistalternativestyleandcolor\c!symstyle\c!symcolor % \listalternativeparameter\c!symbol % \hss}% % \hfill % \hskip\scratchdimen % \endgroup} % % \installlistfiller\v!symbol % new one (make that default?) % {\begingroup % \scratchdimen.5\emwidth % \hskip\scratchdimen % \gleaders % \hbox spread .5\scratchdimen % {\hss % \uselistalternativestyleandcolor\c!symstyle\c!symcolor % \listalternativeparameter\c!symbol % \hss}% % \hfill % \hskip\scratchdimen % \endgroup} % % \installlistfiller\v!width % {\hfill} % % \installlistfiller\v!space % {\hskip.25\emwidth\relax} \setuplistalternative [\c!command=\directlistparameter\c!command, \c!symbol=.] \unexpanded\def\currentlistfiller {\checkedfiller{\listalternativeparameter\c!filler}} \definelistalternative [a] [\c!distance=0pt, \c!width=2em, \c!stretch=10em, \c!filler=\hskip.25em\relax, \c!renderingsetup=\??listrenderings:abc] \definelistalternative [b] [\c!distance=5em, \c!width=2em, \c!stretch=10em, \c!filler=\hfill, \c!renderingsetup=\??listrenderings:abc] \definelistalternative [c] [\c!distance=5em, \c!width=0pt, \c!stretch=10em, \c!filler=\hskip.5em\gleaders\hbox to .5em{\hss.\hss}\hfill\hskip.5em\relax, \c!renderingsetup=\??listrenderings:abc] \definelistalternative [d] [\c!renderingsetup=\??listrenderings:d] \definelistalternative [e] [\c!renderingsetup=\??listrenderings:e] \definelistalternative [f] [\c!renderingsetup=\??listrenderings:f] \definelistalternative [g] [\c!renderingsetup=\??listrenderings:g] \definelistalternative [\v!command] [\c!renderingsetup=\??listrenderings:command] \definelistalternative [\v!none] [\c!renderingsetup=\??listrenderings:none] \definelistalternative [\v!vertical] [\c!before=\ifvmode\nointerlineskip\fi, \c!after=\ifvmode\nointerlineskip\fi\endgraf\allowbreak, \c!renderingsetup=\??listrenderings:generic] \definelistalternative [\v!horizontal] [\c!before=\noindent, \c!after=, \c!renderingsetup=\??listrenderings:generic] % \setuplist % [section] % [alternative=MyListItem, % after=\blank, % before=\blank] % % \definelistplacement[MyListItem][command]#1#2#3{(#1) (#2) (#3)} % \definelistplacement[MyListItem][command]{\whatever} % % this is a compatibility command, best use the regular % defined with command= either set in the alternative or % in the list \installcorenamespace{listelementcommand} % the old plugin model \unexpanded\def\definelistplacement {\dodoubleempty\strc_lists_define_placement} \def\strc_lists_define_placement[#tag][#method]% {\edef\p_method{#method}% \ifx\p_method\empty \let\p_method\v!command \fi \normalexpanded{\definelistalternative[#tag][\p_method]}[\c!command=\strc_lists_placement_command]% \doifelsenextbgroup {\strc_lists_define_placement_yes{#tag}} {\strc_lists_define_placement_nop{#tag}}} % indirect definition: : {\bla} \def\strc_lists_define_placement_yes#tag% {\unexpanded\expandafter\normaldef\csname\??listelementcommand#tag\endcsname##1##2##3} % direct definition: {\bla} \def\strc_lists_define_placement_nop#tag% {\unexpanded\expandafter\normaldef\csname\??listelementcommand#tag\endcsname} \def\strc_lists_placement_command {\csname\??listelementcommand\currentlistalternative\endcsname} %D The rendering macros. \newbox \b_strc_lists_number \newbox \b_strc_lists_text \newbox \b_strc_lists_page \newtoks \t_lists_every_renderingsetup \newtoks \t_lists_every_renderingtext \newtoks \t_lists_every_renderingsynchronize \newtoks \t_lists_every_renderingcleanup \newconditional\c_lists_has_number \newconditional\c_lists_has_page \newconditional\c_lists_show_number \newconditional\c_lists_show_page \let\currentlistentrylocation \empty % watch the 'entry' in the name \let\currentlistentrynumber \empty % watch the 'entry' in the name \let\currentlistentrytitle \empty % watch the 'entry' in the name \let\currentlistentrypagenumber\empty % watch the 'entry' in the name \appendtoks \dontcomplain % \letinteractionparameter\c!width\zeropoint % a weird one \to \t_lists_every_renderingsetup \appendtoks % better is to use a special list entry but we keep this for compatibility \enforced\let\\\space % so expanding this token register has to come *after* the font switch \dontconvertfont % (**) this has to become an option (see publ) \to \t_lists_every_renderingtext \appendtoks % because we want to avoid redundant lua calls we expand the % location beforehand \ifx\currentlistentrylocation\empty \edef\currentlistentrylocation{\structurelistlocation}% needs attention \fi % because these tests happen often and because we're dealing with % rather complex composed data we have special conditionals; keep % in mind that testing for empty fails do to tagging being applied % \edef\p_pagenumber{\listparameter\c!pagenumber}% % \ifx\p_pagenumber\v!always % \settrue\c_lists_has_page % \settrue\c_lists_show_page % \else % \doifelsestructurelisthaspage\settrue\setfalse\c_lists_has_page % \ifx\p_pagenumber\v!yes % \settrue\c_lists_show_page % \else % \setfalse\c_lists_show_page % \fi % \fi \setfalse\c_lists_show_page % necessary? \processcommacommand[\listparameter\c!pagenumber]\strc_lists_process_pagenumber \ifconditional\c_lists_has_page \else \doifelsestructurelisthaspage\settrue\setfalse\c_lists_has_page \fi % always forces number placement (in bib we use a forced number) \edef\p_headnumber{\listparameter\c!headnumber}% \ifx\p_headnumber\v!always \settrue\c_lists_has_number \settrue\c_lists_show_number \else \doifelsestructurelisthasnumber\settrue\setfalse\c_lists_has_number \ifx\p_headnumber\v!yes \settrue\c_lists_show_number \else \setfalse\c_lists_show_number \fi \fi \strc_lists_interaction_check \to \t_lists_every_renderingsetup \appendtoks \strc_references_flush_destination_nodes \to \t_lists_every_renderingsynchronize \appendtoks % as we don't want any interference we clear some variables % afterwards \let\currentlistentrylocation \empty \let\currentlistentrynumber \empty \let\currentlistentrytitle \empty \let\currentlistentrypagenumber\empty \setfalse\c_lists_has_page \setfalse\c_lists_has_number \setfalse\c_lists_show_page \setfalse\c_lists_show_realpage \setfalse\c_lists_show_number \to \t_lists_every_renderingcleanup \let\m_strc_list_alternative\empty % combined \unexpanded\def\strc_lists_apply_renderingsetup {\the\t_lists_every_renderingsetup % now we group \begingroup \ifx\m_strc_list_alternative\empty \edef\currentlistalternative{\listparameter\c!alternative}% \else \let\currentlistalternative\m_strc_list_alternative \fi \directsetup{\listalternativeparameter\c!renderingsetup}\relax \endgroup % till here, where we reset locals \the\t_lists_every_renderingcleanup} % todo: provide packager via attributes \doinstallinjector\s!list \installcorenamespace{listalternativemethods} % the general wrapper of a rendering \startsetups[\??listrenderings:none] % nothing, nb we use the [] syntax here because we end with a \cs \stopsetups \unexpanded\def\currentlistentrytitlesynchronize {\the\t_lists_every_renderingsynchronize} \unexpanded\def\currentlistentrytitlerendered {\currentlistentrytitlesynchronize\currentlistentrytitle} \startsetups[\??listrenderings:command] \edef\p_command{\listalternativeparameter\c!command}% \ifx\p_command\empty [\currentlist: \currentlistentrynumber\space -- \currentlistentrytitle\space -- \currentlistentrypagenumber]% \else \p_command \currentlistentrynumber \currentlistentrytitlerendered % {\currentlistentrytitlesynchronize\currentlistentrytitle} \currentlistentrypagenumber \fi \stopsetups % \startsetups[\??listrenderings:\v!vertical] % \directsetup{\??listrenderings:generic} % \stopsetups % \startsetups[\??listrenderings:\v!horizontal] % \directsetup{\??listrenderings:generic} % \stopsetups \startsetups[\??listrenderings:generic] \typo_injectors_check_list \listparameter\c!before % can be \hskip \edef\p_command{\listalternativeparameter\c!command} \ifx\p_command\empty \listalternativeparameter\c!before \vbox { \forgetall \noindent % otherwise annotations are mirrored up \typo_injectors_mark_list \hbox \strc_lists_get_reference_attribute\v!all { \ifconditional\c_lists_show_number % \ifconditional\c_lists_has_page \hbox \strc_lists_get_reference_attribute\v!number { \strc_lists_set_style_color\c!numberstyle\c!numbercolor\v!number \listparameter\c!numbercommand\currentlistsymbol } % \fi \fi \hbox \strc_lists_get_reference_attribute\v!text { \strc_lists_set_style_color\c!textstyle\c!textcolor\v!text \the\t_lists_every_renderingtext \the\t_lists_every_renderingsynchronize \listparameter\c!textcommand\currentlistentrytitle } \ifconditional\c_lists_show_page \ifconditional\c_lists_has_page \hbox \strc_lists_get_reference_attribute\v!pagenumber { \strc_lists_set_style_color\c!pagestyle\c!pagecolor\v!pagenumber \listparameter\c!pagecommand\currentlistentrypagenumber } \fi \fi } } \listalternativeparameter\c!after \else \noindent % otherwise annotations are mirrored up \typo_injectors_mark_list \hbox \strc_lists_get_reference_attribute\v!all \strc_lists_get_destination_attribute { \p_command\currentlistentrynumber\currentlistentrytitle\currentlistentrypagenumber } \fi \listparameter\c!after \stopsetups % to be documented: align, hang \startsetups[\??listrenderings:abc] \endgraf % are we grouped? \typo_injectors_check_list % \advance % yes or no ... \rightskip is also honored \leftskip\listparameter\c!margin % after \endgraf ! \listparameter\c!before \endgraf \edef\p_width{\listparameter\c!width} \scratchdistance\listparameter\c!distance\relax \ifx\p_width\v!fit \scratchwidth\zeropoint \else\ifconditional\c_lists_has_number \scratchwidth\p_width \else \edef\p_aligntitle{\listparameter\c!aligntitle} \ifx\p_aligntitle\v!yes \scratchwidth\zeropoint \scratchdistance\zeropoint \else \scratchwidth\p_width \fi \fi\fi \noindent % otherwise annotations are mirrored up \typo_injectors_mark_list \hbox \strc_lists_get_reference_attribute\v!all \strc_lists_get_destination_attribute { \setlocalhsize \hsize\localhsize \hbox to \hsize { \forgetall \strc_lists_set_style_color\c!style\c!color\v!all \scratchhsize\hsize \ifconditional\c_lists_has_number \ifconditional\c_lists_show_number \setbox\b_strc_lists_number % \hbox % \strc_lists_get_reference_attribute\v!number % \ifdim\scratchwidth>\zeropoint to \scratchwidth \fi \simplealignedboxplus \scratchwidth {\listparameter\c!numberalign} {\strc_lists_get_reference_attribute\v!number} { \strc_lists_set_style_color\c!numberstyle\c!numbercolor\v!number \listparameter\c!numbercommand\currentlistsymbol % \hfill } \else \setbox\b_strc_lists_number\emptyhbox \fi \else \scratchwidth\zeropoint \scratchdistance\zeropoint \setbox\b_strc_lists_number\emptyhbox \fi \ifconditional\c_lists_has_page \ifconditional\c_lists_show_page \setbox\b_strc_lists_page\hpack { \scratchdimen\listalternativeparameter\c!width \hbox \strc_lists_get_reference_attribute\v!pagenumber \ifdim\scratchdimen>\zeropoint to \scratchdimen\fi { \hfill \strc_lists_set_style_color\c!pagestyle\c!pagecolor\v!pagenumber \strut \listparameter\c!pagecommand\currentlistentrypagenumber } } \else \setbox\b_strc_lists_page\emptyhbox \fi \else \setbox\b_strc_lists_page\emptyhbox \fi \vbox { \hsize\scratchhsize \usealignparameter\listparameter \ifdim\scratchwidth<\hsize % we have leftskip so we'd better just skip back instead of messing % with hang* \edef\p_hang{\listparameter\c!hang} \hangindent\dimexpr\wd\b_strc_lists_number+\scratchdistance\relax \hangafter\ifx\p_hang\v!no\zerocount\else\plusone\fi \scratchdimen\listalternativeparameter\c!distance\relax \ifzeropt\wd\b_strc_lists_page \else \ifdim\scratchdimen>\zeropoint\relax \rightskip\scratchdimen\s!plus\listalternativeparameter\c!stretch\relax \parfillskip-\rightskip \fi \fi \else \scratchdistance\zeropoint \fi \parindent\zeropoint \dontleavehmode % this nils hang: i need to figure out why % % topaligned % % \scratchdimen\wd\b_strc_lists_number % \setbox\b_strc_lists_number\hbox to \hsize{\box\b_strc_lists_number\hss\box\b_strc_lists_page}% % \wd\b_strc_lists_number\scratchdimen % \box\b_strc_lists_number \hskip\scratchdistance\relax \begingroup \strc_lists_set_reference_attribute\v!text \strc_lists_set_style_color\c!textstyle\c!textcolor\v!text \the\t_lists_every_renderingtext \the\t_lists_every_renderingsynchronize \setstrut % needs checking, new here \begstrut \strc_lists_limitated_text\currentlistentrytitle \endstrut \endgroup \ifzeropt\wd\b_strc_lists_page\else \nobreak \currentlistfiller \box\b_strc_lists_page \fi } \hss } }% new \endgraf % new, else problems with nointerlinespace and prevdepth \nointerlineskip % anders verkeerde spatiering bij multi-line \endgraf \allowbreak \listparameter\c!after \stopsetups % % example from the context list % % \setuphead [part] [page=right,placehead=yes] % \setuplist [chapter] [alternative=d,before=\blank,after=\blank] % \setuplist [part] [before=\blank,after=\blank] % % \starttext % \startnarrower[2*right] \placecontent \stopnarrower % \blank[4*big] % \startsetups chapter % \blank \startnarrower[3*middle] \placecontent[criterium=local] \stopnarrower % \stopsetups % \placelist[part][criterium=text,after=\setups{chapter}] % % \part{First part} \chapter{Chapter one} \chapter{Chapter two} % \chapter{Chapter three} \chapter{Chapter four} \chapter{Chapter five} % \part{Second part} \chapter{Chapter one} \chapter{Chapter two} % \chapter{Chapter three} \chapter{Chapter four} \chapter{Chapter five} % \part{Third part} \chapter{Chapter one} \chapter{Chapter two} % \chapter{Chapter three} \chapter{Chapter four} \chapter{Chapter five} % \stoptext \startsetups[\??listrenderings:d] \ifvmode \advance\leftskip\listparameter\c!margin \fi \begingroup \ifvmode \noindent \fi \begingroup \strc_lists_set_reference_attribute\v!all \strc_lists_set_style_color\c!style\c!color\v!all \strc_lists_get_destination_attribute \begingroup \ifconditional\c_lists_show_number \donetrue \ifconditional\c_lists_has_number \else \edef\p_symbol{\listparameter\c!symbol} \ifx\p_symbol\empty \donefalse \fi \fi \ifdone \begingroup \strc_lists_set_reference_attribute\v!number \strc_lists_set_style_color\c!numberstyle\c!numbercolor\v!number \listparameter\c!left \listparameter\c!numbercommand\currentlistsymbol \listparameter\c!right \endgroup \kern.5\emwidth\relax \nobreak \fi \fi \endgroup \begingroup \strc_lists_set_reference_attribute\v!text \strc_lists_set_style_color\c!textstyle\c!textcolor\v!text \the\t_lists_every_renderingtext \the\t_lists_every_renderingsynchronize \setstrut % needs checking, new here \begstrut \strc_lists_limitated_text\currentlistentrytitle \endstrut \endgroup \begingroup \ifconditional\c_lists_has_page \ifconditional\c_lists_show_page \nobreak \hskip.75\emwidth\relax \nobreak \strc_lists_set_reference_attribute\v!pagenumber \strc_lists_set_style_color\c!pagestyle\c!pagecolor\v!pagenumber \strut \listparameter\c!pagecommand\currentlistentrypagenumber \fi \fi \endgroup \scratchdistance\listparameter\c!distance\relax \ifdim\scratchdistance<\emwidth \hskip\emwidth\s!plus\emwidth\s!minus.25\emwidth\relax \else \hskip\scratchdistance\s!plus.5\scratchdistance\s!minus.25\scratchdistance\relax \fi \endgroup \endgroup \stopsetups \startsetups[\??listrenderings:e] \typo_injectors_check_list \noindent % otherwise annotations are mirrored up \typo_injectors_mark_list \hbox \strc_lists_get_reference_attribute\v!all \strc_lists_get_destination_attribute { \letlistparameter\c!depth\zeropoint \letlistparameter\c!color\empty \inheritedlistframed { \letinteractionparameter\c!strut\v!no % still needed? \strc_lists_set_style_color\c!style\c!color\v!all \the\t_lists_every_renderingtext \the\t_lists_every_renderingsynchronize \setstrut \begstrut \strc_lists_limitated_text\currentlistentrytitle \endstrut } } \par \listparameter\c!inbetween \stopsetups \startsetups[\??listrenderings:f] \typo_injectors_check_list \noindent % otherwise annotations are mirrored up \typo_injectors_mark_list \hbox \strc_lists_get_reference_attribute\v!all \strc_lists_get_destination_attribute { \dosetraggedhbox{\listparameter\c!align}% \raggedbox { \strc_lists_set_style_color\c!style\c!color\v!all \the\t_lists_every_renderingtext \the\t_lists_every_renderingsynchronize \setstrut \begstrut \strc_lists_limitated_text\currentlistentrytitle \endstrut } } \par \listparameter\c!inbetween \stopsetups \startsetups[\??listrenderings:g] \typo_injectors_check_list \noindent % otherwise annotations are mirrored up \typo_injectors_mark_list \hbox \strc_lists_get_reference_attribute\v!all \strc_lists_get_destination_attribute { \midaligned { \strc_lists_set_style_color\c!style\c!color\v!all \the\t_lists_every_renderingtext \the\t_lists_every_renderingsynchronize \setstrut \begstrut \strc_lists_limitated_text\currentlistentrytitle \endstrut } } \par \listparameter\c!inbetween \stopsetups %D This is a new one, similar to vertical and horizontal but better suited when %D no command is set (WS): \definelistalternative [\v!interactive] [\c!renderingsetup=\??listrenderings:interactive, \c!before=\endgraf, % new per 2014-11-08 \c!after=\endgraf] % new per 2014-11-08 \startsetups[\??listrenderings:interactive] \edef\p_command{\listalternativeparameter\c!command}% \typo_injectors_check_list \listparameter\c!before \noindent % otherwise annotations are mirrored up \typo_injectors_mark_list \hbox \strc_lists_get_reference_attribute\v!all \strc_lists_get_destination_attribute { \ifx\p_command\empty [ \currentlist:\space \currentlistentrynumber \space\emdash\space \currentlistentrytitle \space\emdash\space \currentlistentrypagenumber ] \else \p_command\currentlistentrynumber\currentlistentrytitle\currentlistentrypagenumber \fi } \listparameter\c!after \stopsetups %D One special for publications (as Alan loves to hangindent). No fonts and %D such (for now). No interaction either as that is dealt with elsewhere. %D %D \currentlistsymbol %D \currentlistentrynumber %D \currentlistentrytitle %D \currentlistentrypagenumber % not really used \definelistalternative [\v!paragraph] [\c!filler=\v!space, \c!renderingsetup=\??listrenderings:\v!paragraph] \startsetups[\??listrenderings:\v!paragraph] \endgraf % are we grouped? \typo_injectors_check_list % ? \listparameter\c!before \endgraf \begingroup \forgetall \noindent \parindent\zeropoint \edef\p_width{\listparameter\c!width}% \edef\p_distance{\listparameter\c!distance}% we are nice for bib users \edef\p_margin{\listparameter\c!margin}% we are nice for bib users \ifx\p_distance\v!none \scratchdistance\zeropoint \else \scratchdistance\p_distance \fi \ifx\p_margin\v!none \scratchoffset\zeropoint \else \scratchoffset\p_margin \fi \ifx\p_width\v!fit \scratchwidth\zeropoint \leftskip\scratchoffset \else \scratchwidth\p_width \ifzeropt\scratchoffset \leftskip\dimexpr\scratchwidth+\scratchdistance\relax \else \leftskip\scratchoffset \fi \fi \usealignparameter\listparameter \hskip-\leftskip \ifconditional\c_lists_has_number \ifconditional\c_lists_show_number \setbox\scratchbox \simplealignedbox\scratchwidth{\listparameter\c!numberalign} \bgroup \useliststyleandcolor\c!numberstyle\c!numbercolor \currentlistsymbol \egroup \ifdim\wd\scratchbox>\zeropoint \box\scratchbox \hskip\scratchdistance\relax \fi \fi \fi \begingroup \useliststyleandcolor\c!textstyle\c!textcolor \setstrut \begstrut \currentlistentrytitle \endstrut \endgroup \ifconditional\c_lists_has_page \ifconditional\c_lists_show_page \nobreak \currentlistfiller \begingroup \useliststyleandcolor\c!pagestyle\c!pagecolor \currentlistentrypagenumber \endgroup \fi \fi \endgraf \endgroup \allowbreak \listparameter\c!after \stopsetups %D List elements are packaged in such a way that we can click on them %D in an interactive document. Here are a few helpers. \newconstant\a_strc_lists_reference \newconstant\a_strc_lists_destination \installcorenamespace{listinteractions} \letvalue{\??listinteractions\v!number }\v!number \letvalue{\??listinteractions\v!sectionnumber}\v!number \letvalue{\??listinteractions\v!text }\v!text \letvalue{\??listinteractions\v!title }\v!text \letvalue{\??listinteractions\v!page }\v!pagenumber \letvalue{\??listinteractions\v!pagenumber }\v!pagenumber \letvalue{\??listinteractions\v!all }\v!all \letvalue{\??listinteractions\v!yes }\v!all \def\listboxproperties {\strc_lists_get_reference_attribute} \def\listrenderingsetup {\the\t_lists_every_renderingtext} \def\listrenderingsynchronize{\the\t_lists_every_renderingsynchronize} \unexpanded\def\strc_lists_interaction_check {\iflocation \strc_lists_interaction_check_yes \else \strc_lists_interaction_check_nop \fi} \def\strc_lists_interaction_check_yes_yes {\edef\p_interaction_forward{\listparameter\c!interaction}% \ifcsname\??listinteractions\p_interaction_forward\endcsname %\expandafter\let\expandafter\p_interaction_forward\csname\??listinteractions\p_interaction_forward\endcsname \expandafter\let\expandafter\p_interaction_forward\lastnamedcs \strc_references_get_simple_reference{internal(\currentlistentrylocation)}% \a_strc_lists_reference\currentreferenceattribute \else \a_strc_lists_reference\attributeunsetvalue \fi \ifnum\a_strc_lists_reference=\attributeunsetvalue \let\strc_lists_get_reference_attribute\gobbleoneargument \let\strc_lists_set_reference_attribute\gobbleoneargument \let\strc_lists_set_style_color \strc_lists_set_style_color_normal \else \let\strc_lists_get_reference_attribute\strc_lists_get_reference_attribute_indeed \let\strc_lists_set_reference_attribute\strc_lists_set_reference_attribute_indeed \let\strc_lists_set_style_color \strc_lists_set_style_color_special \fi \edef\p_interaction_backward{\namedheadparameter\currentlist\c!interaction}% \namedheadparameter ! \ifx\p_interaction_backward\v!list \strc_references_set_simple_reference{*\currentlistentrylocation}% \a_strc_lists_destination\currentdestinationattribute \else \a_strc_lists_destination\attributeunsetvalue \fi \ifnum\a_strc_lists_destination=\attributeunsetvalue \let\strc_lists_get_destination_attribute\empty \let\strc_lists_set_destination_attribute\empty \else \let\strc_lists_get_destination_attribute\strc_lists_get_destination_attribute_indeed \let\strc_lists_set_destination_attribute\strc_lists_set_destination_attribute_indeed \fi} \def\strc_lists_interaction_check_yes_nop {\a_strc_lists_reference \attributeunsetvalue \a_strc_lists_destination\attributeunsetvalue \let\strc_lists_get_reference_attribute\gobbleoneargument \let\strc_lists_set_reference_attribute\gobbleoneargument \let\strc_lists_get_destination_attribute\empty \let\strc_lists_set_destination_attribute\empty \let\strc_lists_set_style_color\strc_lists_set_style_color_normal} \def\strc_lists_interaction_check_yes {\ifx\currentlistentrylocation\empty \strc_lists_interaction_check_yes_nop \else\ifnum\currentlistentrylocation=\zerocount \strc_lists_interaction_check_yes_nop \else \strc_lists_interaction_check_yes_yes \fi\fi} \def\strc_lists_interaction_check_nop {\let\strc_lists_get_reference_attribute \gobbleoneargument \let\strc_lists_set_reference_attribute \gobbleoneargument \let\strc_lists_get_destination_attribute\empty \let\strc_lists_set_destination_attribute\empty \let\strc_lists_set_style_color \strc_lists_set_style_color_normal} \strc_lists_interaction_check_nop \def\strc_lists_get_reference_attribute_indeed#element% {\ifx#element\p_interaction_forward attr \referenceattribute\a_strc_lists_reference \fi} \def\strc_lists_set_reference_attribute_indeed#element% {\ifx#element\p_interaction_forward \c_attr_reference\a_strc_lists_reference \fi} \def\strc_lists_get_destination_attribute_indeed {attr \destinationattribute\number\a_strc_lists_destination} \def\strc_lists_set_destination_attribute_indeed {\c_attr_destination\a_strc_lists_destination} \unexpanded\def\strc_lists_set_style_color_normal#style#color#element% {\useliststyleandcolor#style#color} \unexpanded\def\strc_lists_set_style_color_special#style#color#element% {\useliststyleandcolor#style#color% \ifx\currentcolorparameter\empty \ifx#element\p_interaction_forward \setlocationcolor \fi % \else % \resetinteractionparameter\c!color % \resetinteractionparameter\c!contrastcolor \fi} \let\strc_lists_set_style_color\strc_lists_set_style_color_normal %D A helper: \def\strc_lists_limitated_text#text% {\edef\p_maxwidth{\listparameter\c!maxwidth}% \ifx\p_maxwidth\empty \listparameter\c!textcommand{#text}% \else \listparameter\c!textcommand{\limitatetext{#text}\p_maxwidth{\splitsymbol{\listparameter\c!limittext}}}% \fi} % public helpers \unexpanded\def\startcurrentlistentrywrapper {\hbox \strc_lists_get_reference_attribute\v!all \strc_lists_get_destination_attribute\bgroup} \let\stopcurrentlistentrywrapper\egroup \let\currentlistentryreferenceattribute \strc_lists_get_reference_attribute \let\currentlistentrydestinationattribute\strc_lists_get_destination_attribute \let\currentlistentrylimitedtext \strc_lists_limitated_text % todo: \def\utilitylistlength{\listlength} % old name ... uses in styles \let\listlength\!!zerocount % better use listmode \unexpanded\def\determinelistcharacteristics {\dodoubleempty\strc_lists_determine_characteristics} \def\strc_lists_determine_characteristics[#list][#settings]% {\begingroup \edef\currentlist{\firststructureelementinlist{#list}}% \ifx\currentlist\empty \endgroup \let\listlength\!!zerocount \else \setupcurrentlist[#settings]% \strc_lists_analyze{#list}{\listparameter\c!criterium}{\listparameter\c!reference}% \normalexpanded{\endgroup\noexpand\edef\noexpand\listlength{\structurelistsize}}% \fi \strc_lists_set_mode} \protect \endinput