%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: <three ignore arguments>: {\bla}

\def\strc_lists_define_placement_yes#tag%
  {\unexpanded\expandafter\normaldef\csname\??listelementcommand#tag\endcsname##1##2##3}

% direct definition: <three arguments>{\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
