summaryrefslogtreecommitdiff
path: root/tex/context/base/mkiv/strc-ref.mkvi
diff options
context:
space:
mode:
Diffstat (limited to 'tex/context/base/mkiv/strc-ref.mkvi')
-rw-r--r--tex/context/base/mkiv/strc-ref.mkvi2231
1 files changed, 2231 insertions, 0 deletions
diff --git a/tex/context/base/mkiv/strc-ref.mkvi b/tex/context/base/mkiv/strc-ref.mkvi
new file mode 100644
index 000000000..404bef62f
--- /dev/null
+++ b/tex/context/base/mkiv/strc-ref.mkvi
@@ -0,0 +1,2231 @@
+%D \module
+%D [ file=strc-ref,
+%D version=2008.10.20,
+%D title=\CONTEXT\ Structure Macros,
+%D subtitle=Cross Referencing,
+%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.
+
+% todo: (1) configure references, (2) rendering => with presets
+%
+% \defineconversionset[default][Character,number,Romannumerals,Character][number]
+% \defineseparatorset [default][.,.,--][.]
+% \setuphead[subsection][sectionstopper=),sectionsegments=4:4]
+% \setupreferencestructureprefix[default][prefixsegments=2:4]
+% \setupreferencestructureprefix[figure][default][prefixsegments=3:4]
+% \chapter {One}
+% \section {One}
+% \subsection[sec:test]{Two}
+% See \in[sec:test] and \in[fig:xx] and \in[fig:yy]
+% \placefigure[here][fig:xx]{}{}
+% \placefigure[here][fig:yy]{}{}
+
+\writestatus{loading}{ConTeXt Structure Macros / Cross Referencing}
+
+\registerctxluafile{strc-rsc}{1.001}
+\registerctxluafile{strc-ref}{1.001}
+\registerctxluafile{node-ref}{1.001}
+
+\unprotect
+
+%D This module is a (partial) rewrite of core-ref.tex for \MKIV. As
+%D such it will be a moving target for a while.
+
+%D Later we will do a further cleanup and move much of the code to
+%D \LUA\ (i.e.\ better backend integration).
+
+\let\mainreference\gobblefivearguments
+
+% this will go when we got rid of the tuo file
+
+\let\currentfolioreference \!!zerocount % only used in xml-fo
+\let\resetreferences \relax
+\let\setreferences \relax
+\let\showcurrentreference \relax
+\let\setexecutecommandcheck\gobbletwoarguments
+
+% todo : unknown/illegal reference no arg
+% todo : +n pages check on 'samepage' (contrastcolor)
+% todo : multiple text in reference
+
+% Makes more sense to build action data first, especially now
+% openaction etc are supported.
+%
+% \definespecial\doexecuteactionchain w h
+% \definespecial\dosetgotolocation
+% \definespecial\dosetexecuteJScode
+% ...
+
+%D This module deals with referencing. In \CONTEXT\ referencing is one of
+%D the core features, although at a first glance probably nobody will
+%D notice. This is good, because referencing should be as hidden as possible.
+%D
+%D Before we start implementing functionality we provide a way to set
+%D up this mechanism.
+%D
+%D \showsetup{setupreferencing}
+%D
+%D In interactive documents verbose references don't always
+%D make sense (what is a page number in an unnumbered
+%D document). By setting the \type{interaction} variable, one
+%D can influences the way interactive references are set.
+
+\let\referenceprefix\empty
+
+\installcorenamespace{referencing}
+
+\installdirectcommandhandler \??referencing {referencing} % \??referencing
+
+\newif\ifreferencing \referencingtrue
+
+\appendtoks
+ \edef\p_state{\referencingparameter\c!state}%
+ \ifx\p_state\v!start
+ \referencingtrue
+ \else
+ \referencingfalse
+ \fi
+\to \everysetupreferencing
+
+%D In paper documents, referencing comes down to cross referencing, but in
+%D their interactive counterparts, is also involves navigation. Many features
+%D implemented here are therefore closely related to navigation.
+%D
+%D Many \CONTEXT\ commands can optionally be fed with a reference. Such a
+%D reference, when called upon, returns the number of a figure, table, chapter
+%D etc, a piece of text, or a pagenumber.
+%D
+%D There are three ways of defining a reference:
+%D
+%D \starttyping
+%D \pagereference[here]
+%D \textreference[here]{some text}
+%D \stoptyping
+%D
+%D the third alternative combines them in:
+%D
+%D \starttyping
+%D \reference[here]{some text}
+%D \stoptyping
+
+\unexpanded\def\textreference {\dosingleargument\strc_references_text_reference} % no need for \dosingle
+\unexpanded\def\pagereference {\dosingleargument\strc_references_page_reference} % as they're mandate and
+\unexpanded\def\reference {\dosingleargument\strc_references_full_reference} % never forgotten
+\unexpanded\def\setreference {\dodoubleargument\strc_references_set_reference } %
+
+% maybe: \let\reference\textreference
+
+\unexpanded\def\showreferences
+ {\enabletrackers[nodes.references.show,nodes.destinations.show]}
+
+%D These are implemented in a low level form as:
+
+\unexpanded\def\strc_references_text_reference [#labels]{\strc_references_set_named_reference\s!text{#labels}{}}
+\unexpanded\def\strc_references_page_reference [#labels]{\strc_references_set_named_reference\s!page{#labels}{}{}}
+\unexpanded\def\strc_references_full_reference [#labels]{\strc_references_set_named_reference\s!full{#labels}{}}
+\unexpanded\def\strc_references_set_reference[#labels][#settings]{\strc_references_set_named_reference\s!user{#labels}{#settings}{}}
+
+\unexpanded\def\dosetdirectpagereference#1{\strc_references_set_named_reference\s!page{#1}{}{}} % low level, maybe use _
+
+\unexpanded\def\usereferenceparameter#1% faster local variant
+ {\edef\m_strc_references_asked{#1\c!reference}%
+ \ifx\m_strc_references_asked\empty\else
+ \dosetdirectpagereference\m_strc_references_asked
+ \fi}
+
+%D Actually there is not much difference between a text and a
+%D full reference, but it's the concept that counts. The low
+%D level implementation is:
+
+\newcount\lastreferenceattribute
+\newcount\lastdestinationattribute
+
+\def\strc_references_finish#prefix#reference#internal%
+ {\normalexpanded{\ctxlatecommand{enhancereference("#prefix","#reference")}}}
+
+\let\dofinishreference\strc_references_finish % used at lua end
+
+% This is somewhat tricky: we want to keep the reference with the following word but
+% that word should also hyphenate. We need to find a better way.
+
+% 0 = nothing
+% 1 = bind to following word
+
+\setnewconstant\c_strc_references_bind_state\plusone
+
+\def\strc_references_inject_before
+ {}
+
+\def\strc_references_inject_after
+ {\ifcase\c_strc_references_bind_state
+ % nothing
+ \or
+ \prewordbreak % to be tested: \removeunwantedspaces\permithyphenation
+ \fi}
+
+
+\unexpanded\def\strc_references_set_named_reference
+ {\ifreferencing
+ \expandafter\strc_references_set_named_reference_indeed
+ \else
+ \expandafter\gobblefourarguments
+ \fi}
+
+\newbox\b_strc_destination_nodes
+
+\unexpanded\def\strc_references_flush_destination_nodes
+ {\ifvoid\b_strc_destination_nodes \else
+ \unhbox\b_strc_destination_nodes
+ \fi}
+
+\unexpanded\def\strc_references_start_destination_nodes % messy but we need the delay
+ {\setbox\b_strc_destination_nodes\hbox\bgroup} % also sets lastdestinationattribute
+
+\unexpanded\def\strc_references_stop_destination_nodes
+ {\normalexpanded{\egroup\lastdestinationattribute\the\lastdestinationattribute\relax}}
+
+\unexpanded\def\strc_references_set_named_reference_indeed#kind#labels#userdata#text% labels userdata text -> todo: userdata
+ {\ifreferencing
+ % we could have a more efficient one for page references but for the moment
+ % we don't care too much
+ \edef\currentreferencekind {#kind}%
+ \edef\currentreferencelabels {#labels}%
+ \edef\currentreferenceuserdata {#userdata}%
+ \edef\currentreferenceexpansion{\referencingparameter\c!expansion}% {\referenceparameter\c!expansion}
+ \ifx\currentreferencelabels\empty
+ \lastdestinationattribute\attributeunsetvalue
+ \else
+ \ifx\currentreferenceexpansion\s!xml
+ \xmlstartraw
+ \xdef\currentreferencedata{#text}% data, no text else conflict
+ \xmlstopraw
+ \globallet\currentreferencecoding\s!xml
+ \else
+ \ifx\currentreferenceexpansion\v!yes
+ \xdef\currentreferencedata{#text}%
+ \else
+ \xdef\currentreferencedata{\detokenize{#text}}%
+ \fi
+ \globallet\currentreferencecoding\s!tex
+ \fi
+ % beware, the structures.references.set writes a
+ \setnextinternalreference
+ \strc_references_start_destination_nodes
+ \clf_setreferenceattribute
+ {%
+ references {%
+ internal \nextinternalreference
+ % block {\currentsectionblock}%
+ view {\interactionparameter\c!focus}%
+ prefix {\referenceprefix}%
+ reference {\currentreferencelabels}%
+ }%
+ metadata {%
+ kind {\currentreferencekind}%
+ \ifx\currentreferencekind\s!page\else
+ \ifx\currentreferencecoding\s!xml
+ xmlroot {\xmldocument}%
+ \fi
+ catcodes \catcodetable
+ \fi
+ }%
+ \ifx\currentreferencedata\empty\else
+ entries {%
+ text {\currentreferencedata}%
+ }%
+ \fi
+ \ifx\currentreferenceuserdata\empty\else
+ userdata {\detokenize{#userdata}}%
+ \fi
+ }%
+ \relax
+ \strc_references_stop_destination_nodes
+ \fi
+ \else
+ \setbox\b_strc_destination_nodes\emptyhbox
+ \lastdestinationattribute\attributeunsetvalue
+ \fi
+ % will become obsolete:
+ \xdef\currentdestinationattribute{\number\lastdestinationattribute}%
+ % will become an option:
+ \ifnum\lastdestinationattribute>\zerocount
+ \strc_references_inject_before % new
+ \dontleavehmode\hbox attr \destinationattribute\lastdestinationattribute\bgroup
+ \strc_references_flush_destination_nodes
+ \egroup
+ \strc_references_inject_after % new
+ \fi}
+
+\def\strc_references_set_page_only_destination_attribute#labels% could in fact be fully expandable
+ {\ifreferencing
+ \edef\currentreferencelabels{#labels}%
+ \ifx\currentreferencelabels\empty
+ \setbox\b_strc_destination_nodes\emptyhbox
+ \lastdestinationattribute\attributeunsetvalue
+ \else
+ \strc_references_start_destination_nodes
+ \setnextinternalreference
+ \clf_setreferenceattribute
+ {%
+ references {%
+ internal \nextinternalreference
+ % block {\currentsectionblock}%
+ view {\interactionparameter\c!focus}%
+ prefix {\referenceprefix}%
+ reference {\currentreferencelabels}%
+ }%
+ metadata {%
+ kind {page}%
+ }%
+ }%
+ \relax
+ \strc_references_stop_destination_nodes
+ \fi
+ \else
+ \setbox\b_strc_destination_nodes\emptyhbox
+ \lastdestinationattribute\attributeunsetvalue
+ \fi}
+
+\unexpanded\def\strc_references_direct_full_user#user#labels#text%
+ {\ifreferencing
+ \strc_references_start_destination_nodes
+ \setnextinternalreference
+ \edef\m_strc_references_user{#user}%
+ \edef\m_strc_references_text{#text}%
+ \clf_setreferenceattribute
+ {%
+ references {%
+ internal \nextinternalreference
+ % block {\currentsectionblock}%
+ view {\interactionparameter\c!focus}%
+ prefix {\referenceprefix}%
+ reference {#labels}%
+ }%
+ metadata {%
+ kind {\s!full}%
+ }%
+ \ifx\m_strc_references_text\empty \else
+ entries {%
+ text {\m_strc_references_text}%
+ }%
+ \fi
+ \ifx\m_strc_references_user\empty \else
+ userdata {\m_strc_references_user}% \detokenize\expandafter{\normalexpanded{...}}
+ \fi
+ }%
+ \relax
+ \strc_references_stop_destination_nodes
+ \else
+ \setbox\b_strc_destination_nodes\emptyhbox
+ \lastdestinationattribute\attributeunsetvalue
+ \fi
+ % will become obsolete:
+ \xdef\currentdestinationattribute{\number\lastdestinationattribute}%
+ % will become an option:
+ \ifnum\lastdestinationattribute>\zerocount
+ \strc_references_inject_before % new
+ \dontleavehmode\hbox attr \destinationattribute\lastdestinationattribute\bgroup
+ \strc_references_flush_destination_nodes
+ \egroup
+ \strc_references_inject_after % new
+ \fi}
+
+\unexpanded\def\strc_references_direct_full
+ {\strc_references_direct_full_user\empty}
+
+\let\dodirectfullreference\strc_references_direct_full % for at lua end (no longer)
+
+\def\strc_references_set_page_only_destination_box_attribute#cs#labels%
+ {\strc_references_set_page_only_destination_attribute{#labels}%
+ \ifnum\lastdestinationattribute>\zerocount
+ \edef#cs{attr \destinationattribute\number\lastdestinationattribute}%
+ \else
+ \let#cs\empty
+ \fi}
+
+%D It's about time to clean up references .. stable enough now.
+
+\unexpanded\def\boxreference[#1]%
+ {\begingroup
+ \dowithnextbox
+ {\strc_references_set_page_only_destination_attribute{#1}%
+ \hbox
+ \ifnum\lastdestinationattribute=\attributeunsetvalue\else attr \destinationattribute \lastdestinationattribute \fi
+ {\box\b_strc_destination_nodes\box\nextbox}%
+ \endgroup}}
+
+\unexpanded\def\hboxreference[#1]{\boxreference[#1]\hbox}
+\unexpanded\def\vboxreference[#1]{\boxreference[#1]\vbox}
+
+% \ifx\currentdestinationattribute\empty
+% \begingroup\attribute\destinationattribute\currentdestinationattribute\emptyhbox\endgroup % todo
+% \fi
+
+\def\defaultreferencepage#text{[[[#text]]]}
+\def\defaultreferencetext#text{[[[#text]]]}
+
+%D For internal usage:
+
+\def\strc_references_set_simple_page_reference#label%
+ {\iflocation
+ \strc_references_start_destination_nodes
+ \clf_setreferenceattribute
+ {%
+ references {%
+ % block {\currentsectionblock}%
+ view {\interactionparameter\c!focus}%
+ prefix {\referenceprefix}%
+ reference {#label}%
+ }%
+ metadata {%
+ kind {\s!page}%
+ }%
+ }%
+ \relax
+ \strc_references_stop_destination_nodes
+ \xdef\currentdestinationattribute{\number\lastdestinationattribute}%
+ \else
+ \setbox\b_strc_destination_nodes\emptyhbox
+ \xdef\currentdestinationattribute{\number\attributeunsetvalue}%
+ \fi}
+
+\def\strc_references_get_simple_page_reference#label%
+ {\iflocation
+ \clf_injectreference
+ {\referenceprefix}%
+ {#label}%
+ {%
+ height \ht\strutbox
+ depth \dp\strutbox
+ \extrareferencearguments
+ }%
+ \relax
+ \xdef\currentreferenceattribute{\number\lastreferenceattribute}%
+ \else
+ \xdef\currentreferenceattribute{\number\attributeunsetvalue}%
+ \fi}
+
+%D \macros
+%D {contentreference}
+%D
+%D \starttyping
+%D \setupinteraction
+%D [state=start,
+%D focus=standard]
+%D
+%D \setupheader
+%D [state=stop]
+%D
+%D See page \goto{page 2}[page2] \page
+%D
+%D \contentreference
+%D [page2]
+%D [offset=1cm,toffset=2cm,frame=on]
+%D {\externalfigure[cow.pdf][factor=fit]}
+%D
+%D \stoptyping
+
+\unexpanded\def\contentreference
+ {\hbox\bgroup
+ \dodoubleempty\strc_references_content_pickup}
+
+\def\strc_references_content_pickup
+ {\ifsecondargument
+ \expandafter\strc_references_content_pickup_yes
+ \else
+ \expandafter\strc_references_content_pickup_nop
+ \fi}
+
+\def\strc_references_content_pickup_yes[#1][#2]%
+ {\dowithnextbox{\strc_references_content_yes_finish{#1}{#2}}\hbox}
+
+\def\strc_references_content_pickup_nop[#1][#2]%
+ {\dowithnextbox{\strc_references_content_nop_finish{#1}{#2}}\hbox}
+
+\def\strc_references_content_yes_finish#1#2%
+ {\scratchwidth \wd\nextbox
+ \scratchheight\ht\nextbox
+ \scratchdepth \dp\nextbox
+ \setbox\nextbox\hbox
+ {\framed[\c!frame=\v!off,#2]{\box\nextbox}}%
+ \strc_references_set_simple_page_reference{#1}%
+ \setbox\nextbox\hbox attr \destinationattribute \currentdestinationattribute
+ {\strc_references_flush_destination_nodes
+ \box\nextbox}%
+ \setbox\nextbox\hbox{\box\nextbox}%
+ \wd\nextbox\scratchwidth
+ \ht\nextbox\scratchheight
+ \dp\nextbox\scratchdepth
+ \box\nextbox
+ \egroup}
+
+\def\strc_references_content_nop_finish#1#2%
+ {\strc_references_set_simple_page_reference{#1}%
+ \hbox attr \destinationattribute \currentdestinationattribute
+ {\strc_references_flush_destination_nodes
+ \box\nextbox}%
+ \egroup}
+
+%D \macros
+%D {everyreference}
+%D
+%D For rather tricky purposes, one can assign sanitizing
+%D macros to \type{\everyreference} (no longer that relevant).
+
+\newevery \everyreference \relax
+
+%D This is really needed, since for instance Polish has a
+%D different alphabet and needs accented entries in registers.
+
+\appendtoks
+ \cleanupfeatures
+\to \everyreference
+
+%D We did not yet discuss prefixing. Especially in interactive
+%D documents, it's not always easy to keep track of duplicate
+%D references. The prefix mechanism, which we will describe
+%D later on, solves this problem. By (automatically) adding a
+%D prefix one keeps references local, but the global ones in
+%D view. To enable this feature, we explictly split the prefix
+%D from the reference.
+
+\let\referenceprefix\empty
+
+%D For a long time the only way to access an external file was
+%D to use the file prefix (\type {somefile::}. However, when
+%D you split up a document, redefining the references may be
+%D such a pain, that another approach is feasible. By setting
+%D the \type {autofile} variable to \type {yes} or \type
+%D {page}, you can access the reference directly.
+%D
+%D \starttabulate[||||]
+%D \NC filename::tag \NC page(filename::pnum) \NC tag \NC\NR
+%D \NC $\star$ \NC \NC \NC\NR
+%D \NC $\star$ \NC $\star$ \NC $\star$ \NC\NR
+%D \NC \NC $\star$ \NC \NC\NR
+%D \stoptabulate
+
+\unexpanded\def\usereferences[#filename]{} % obsolete
+
+%D As mentioned we will also use the cross reference mechanism
+%D for navigational purposes. The main reason for this is that
+%D we want to treat both categories alike:
+%D
+%D \starttyping
+%D \goto{go back}[PreviousJump]
+%D \goto{colofon}[colofon page]
+%D \stoptyping
+%D
+%D Here \type{PreviousJump} is handled by the viewer, while the
+%D \type{colofon page} reference is, apart from hyperlinking, a
+%D rather normal reference.
+%D
+%D We already saw that cross refences are written to and read
+%D from a file. The pure navigational ones don't need to be
+%D written to file, but both for fast processing and
+%D transparant integration, they are saved internally as a sort
+%D of reference. We can easily distinguish such system
+%D references from real cross reference ones by their tag.
+%D
+%D We also use the odd/even characteristic to determine the
+%D page state.
+
+\let\currentrealreference \empty
+\let\currentpagereference \empty
+\let\currenttextreference \empty
+\let\currentreferenceorder \empty
+\let\currentsubtextreference \empty
+\let\currentsubsubtextreference\empty
+
+\newcount\referencehastexstate % set in backend
+
+% referencepagestate:
+%
+% 0 = no page ref, 1=same page, 2=before, 3=after
+
+%D Cross references appear as numbers (figure~1.1, chapter~2)
+%D or pagenumbers (page~2, page 3--2), and are called with
+%D \type{\in} and \type{\at}. In interactive documents we also
+%D have \type{\goto}, \type{\button} and alike. These are more
+%D versatile and look like:
+%D
+%D \starttyping
+%D \goto[reference]
+%D \goto[outer reference::]
+%D \goto[outer reference::inner reference]
+%D \goto[operation(argument)]
+%D \goto[operation(action{argument,argument})]
+%D \goto[action]
+%D \goto[action{argument}]
+%D \stoptyping
+%D
+%D The first one is a normal reference, the second and third
+%D are references to a file or \URL. The brace delimited
+%D references for instance refer to a \JAVASCRIPT. The last
+%D example shows that we can pass arguments to the actions.
+%D
+%D Now we've come to the testing step. As we can see below,
+%D this macro does bit more than testing: it also resolves
+%D the reference. This means that whenever we test for the
+%D existance of a reference at an outer level, we have all the
+%D relevant properties of that reference avaliable inside the
+%D true branche~(\type{#2}).
+%D
+%D The prefix has to do with localizing references. When a
+%D prefix is set, looking for a reference comes to looking for
+%D the prefixed one, and when not found, looking for the non
+%D prefixed one. Consider for instance the prefix set to
+%D \type{sidetrack}.
+%D
+%D \starttyping
+%D \pagereference[important]
+%D \pagereference[unimportant]
+%D \setupreferencing[prefix=sidetrack]
+%D \pagereference[important]
+%D \stoptyping
+%D
+%D results in saving (writing) the references
+%D
+%D \starttyping
+%D ...{}{important}
+%D ...{}{unimportant}
+%D ...{sidetrack}{important}...
+%D \stoptyping
+%D
+%D Now when we call for \type{unimportant}, we will indeed get
+%D the pagenumber associated to this reference. But when we
+%D call for \type{important}, while the prefix is still set, we
+%D will get the pagenumber bound to the prefixed one.
+%D
+%D {\em Some day, when processing time and memory are no longer
+%D performance factors, we will introduce multi||level
+%D prefixes.}
+%D
+%D Before we start analyzing, I introduce a general
+%D definition macro. Consider:
+%D
+%D \starttyping
+%D \goto{do}[JS(My_Script{"test",123}),titlepage]
+%D \stoptyping
+%D
+%D This can also be achieved by:
+%D
+%D \starttyping
+%D \definereference[startup][JS(My_Script{"test",123}),titlepage]
+%D \goto{do}[startup]
+%D \stoptyping
+%D
+%D Now is this is a handy feature or not?
+%D
+%D \showsetup{definereference}
+%D
+%D We can trace references by setting the next switch to
+%D true.
+
+\unexpanded\def\definereference
+ {\dodoubleempty\strc_references_define_reference}
+
+\def\strc_references_define_reference[#name][#specification]%
+ {\clf_definereference{\referenceprefix}{#name}{\detokenize{#specification}}}
+
+\unexpanded\def\resetreference[#name]%
+ {\clf_resetreference{\referenceprefix}{#name}}
+
+\def\setpagereference#name#specification% hm,. low level ?
+ {\clf_definereference{}{#name}{\v!page(\detokenize{#specification}}} % is detokenize needed here?
+
+%D Chained references are defined as:
+%D
+%D \starttyping
+%D \goto{somewhere}[JS(somescript),nextpage,JS(anotherscript)]
+%D \stoptyping
+%D
+%D Actually supporting chains is up to the special driver. Here
+%D we only provide the hooks.
+
+%D \macros
+%D {highlighthyperlinks}
+%D
+%D The next switch can be used to make user hyperlinks are
+%D not highlighted when clicked on.
+
+\newconditional\highlighthyperlinks \settrue\highlighthyperlinks
+
+%D \macros
+%D {gotonewwindow}
+%D
+%D To make the {\em goto previous jump} feature more
+%D convenient when using more than one file, it makes sense
+%D to force the viewer to open a new window for each file
+%D opened.
+
+\newconditional\gotonewwindow \setfalse\gotonewwindow
+
+\def\expandtexincurrentreference % will happen in lua some time
+ {\ifcase\referencehastexstate\else\clf_expandcurrentreference\fi}
+
+\def\expandreferenceoperation#tag#content{\clf_setreferenceoperation#tag{#content}}
+\def\expandreferencearguments#tag#content{\clf_setreferencearguments#tag{#content}}
+
+\def\doifelsereferencefound#label#yes#nop%
+ {\clf_doifelsereference{\referenceprefix}{#label}{\extrareferencearguments}%
+ {\expandtexincurrentreference
+ #yes}%
+ {#nop}}
+
+\let\doifreferencefoundelse \doifelsereferencefound
+
+%D The tester only splits the reference in components but does
+%D not look into them. The following macro does a preroll and
+%D determines for instance the current real reference pagenumber.
+%D The \type {\currentrealreference} macro does the same so unless
+%D one wants to use the pagestate the next macro seldom needs to
+%D be called.
+
+%D The inner case is simple. Only two cases have to be taken
+%D care of:
+%D
+%D \starttyping
+%D \goto{some text}[reference]
+%D \goto{some text}[prefix:reference]
+%D \stoptyping
+%D
+%D References to other files however are treated strict or
+%D tolerant, depending on their loading and availability:
+%D
+%D \starttyping
+%D \useexternaldocument[somefile][filename][a nice description]
+%D
+%D \goto{checked reference}[somefile::reference]
+%D \goto{unchecked reference}[somefile::]
+%D \goto{unchecked reference}[anotherfile::reference]
+%D \stoptyping
+%D
+%D An unknown reference is reported on the screen, in the log
+%D file and, when enabled, in the left margin of the text.
+
+\let\unknownreference\gobbleoneargument
+
+%D When a reference is not found, we typeset a placeholder
+%D (two glyphs are often enough to represent the reference
+%D text).
+
+\def\dummyreference{{\tttf ??}}
+\def\emptyreference{{\tttf !!}}
+
+%D To prevent repetitive messages concerning a reference
+%D being defined, we set such an unknown reference to an empty
+%D one after the first encounter.
+
+%D Apart from cross references supplied by the user, \CONTEXT\
+%D generates cross references itself. Most of them are not
+%D saved as a reference, but stored with their source, for
+%D instance a list or an index entry. Such automatically
+%D generated, for the user invisible, references are called
+%D {\em internal references}. The user supplied ones are
+%D labeled as {\em external references}.
+%D
+%D A second important characteristic is that when we want to
+%D support different backends (viewers), we need to support
+%D named destinations as well as page numbers. I invite readers
+%D to take a glance at the special driver modules to understand
+%D the fine points of this. As a result we will deal with {\em
+%D locations} as well as {\em real page numbers}. We explictly
+%D call this pagenumber a real one, because it is independant
+%D of the page numbering scheme used in the document.
+%D
+%D One of the reasons for \CONTEXT\ being the first \TEX\ base
+%D macropackage to support sophisticated interactive \PDF\
+%D files, lays in the mere fact that real page numbers are
+%D available in most two pass data, like references, list data
+%D and index entries.
+%D
+%D We will speak of \type{thisis...} when we are marking a
+%D location, and \type{goto...} when we point to such a
+%D location. The latter one can be seen as a hyperlink to the
+%D former one. In the next macros one we use constructs like:
+%D
+%D \starttyping
+%D \dostart...
+%D \dostop...
+%D \stoptyping
+%D
+%D Such macros are used to invoke the relevant specials from
+%D the special driver modules (see \type{spec-ini}). The flag
+%D \type{\iflocation} signals if we're in interactive mode.
+
+\ifdefined\buttonheight \else \newdimen\buttonheight \fi
+\ifdefined\buttonwidth \else \newdimen\buttonwidth \fi
+
+%D Internal references can best be set using the next few
+%D macros. Setting such references to unique values is
+%D completely up to the macros that call them.
+%D
+%D \starttyping
+%D \thisissomeinternal{tag}{identifier}
+%D \gotosomeinternal {tag}{identifier}{pagenumber}{text}
+%D \stoptyping
+
+%D We could do this in lua ...
+
+\newif \iflocation
+\newcount\locationcount
+\newcount\locationorder
+\newbox \locationbox
+
+\def\nextinternalreference {\the\locationcount}
+\def\nextinternalorderreference{\the\locationorder}
+
+\def\setnextinternalreference
+ {\global\advance\locationcount\plusone}
+
+\def\setnextinternalreferences#kind#name% plural
+ {\clf_setnextinternalreference{#kind}{#name}}
+
+\def\getinternalorderreference#kind#name%
+ {\clf_currentreferenceorder{#kind}{#name}}
+
+\def\thisissomeinternal#kind#name% only for old time sake
+ {\begingroup
+ \clf_setinternalreference reference {#kind:#name}\relax
+ \hbox attr \destinationattribute\lastdestinationattribute{}%
+ \endgroup}
+
+\installcorenamespace{savedinternalreference}
+
+\letvalue{\??savedinternalreference\s!default}\!!zerocount
+
+\unexpanded\def\storeinternalreference#1#2%
+ {\setxvalue{\??savedinternalreference\currentstructurename}{#2}}
+
+\newconditional\preferpagereferences
+
+\def\gotosomeinternal#kind#name#target#text%
+ {\ifconditional\preferpagereferences
+ \directgoto{#text}[page(#target)]%
+ \else
+ \directgoto{#text}[#kind:#name]%
+ \fi}
+
+\def\gotonextinternal#text#target%
+ {\directgoto{#text}[internal(#target)]}
+
+%D In this module we define three system references: one for
+%D handling navigational, viewer specific, commands, another
+%D for jumping to special pages, like the first or last one,
+%D and a third reference for linking tree like lists, like
+%D tables of contents. The latter two adapt themselves to the
+%D current state.
+%D
+%D An example of an action is:
+%D
+%D \starttyping
+%D \goto{some action}[PreviousJump]
+%D \stoptyping
+%D
+%D as well as:
+%D
+%D \starttyping
+%D \goto{some text}[\v!action(PreviousJump]
+%D \stoptyping
+
+%D One can also activate an automatic prefix mechanism. By
+%D setting the \type{\prefix} variable to \type{+}, the prefix
+%D is incremented, when set to \type{-} or empty, the prefix is
+%D reset. Other values become the prefix.
+
+\newcount\prefixcounter
+
+\newconditional\autocrossfilereferences
+
+\appendtoks
+ \edef\p_autofile{\referencingparameter\c!autofile}%
+ \ifx\p_autofile\v!yes
+ \settrue \autocrossfilereferences
+ \else
+ \setfalse\autocrossfilereferences
+ \fi
+\to \everysetupreferencing
+
+\appendtoks
+ \edef\p_export{\referencingparameter\c!export}%
+ \ifx\p_export\v!yes
+ \clf_exportreferences
+ \fi
+\to \everygoodbye
+
+\unexpanded\def\setupglobalreferenceprefix[#prefix]%
+ {\xdef\referenceprefix{#prefix}}
+
+% \unexpanded\def\pushreferenceprefix#prefix%
+% {\pushmacro\referenceprefix
+% \xdef\referenceprefix{#prefix}} % global
+
+% \unexpanded\def\popreferenceprefix
+% {\popmacro\referenceprefix}
+
+\unexpanded\def\globalpushreferenceprefix#prefix%
+ {\xdef\referenceprefix{\clf_pushreferenceprefix{#prefix}}}
+
+\unexpanded\def\globalpopreferenceprefix
+ {\xdef\referenceprefix{\clf_popreferenceprefix}}
+
+\unexpanded\def\pushreferenceprefix#prefix%
+ {\edef\referenceprefix{\clf_pushreferenceprefix{#prefix}}}
+
+\unexpanded\def\popreferenceprefix
+ {\edef\referenceprefix{\clf_popreferenceprefix}}
+
+\def\m_strc_references_prefix_yes{+}
+\def\m_strc_references_prefix_nop{-}
+
+\unexpanded\def\setupreferenceprefix[#prefix]%
+ {\edef\p_prefix{#prefix}%
+ \ifx\p_prefix\empty
+ \let\referenceprefix\empty
+ \else\ifx\p_prefix\m_strc_references_prefix_yes
+ \letreferencingparameter\c!prefix\s!unknown
+ \global\advance\prefixcounter\plusone
+ \edef\referenceprefix{\the\prefixcounter}%
+ \else\ifx\p_prefix\m_strc_references_prefix_nop
+ \letreferencingparameter\c!prefix\s!unknown
+ \let\referenceprefix\empty
+ \else\ifx\p_prefix\s!unknown
+ % forget about it
+ \else
+ \let\referenceprefix\p_prefix
+ \fi\fi\fi\fi}
+
+\appendtoks
+ \setupreferenceprefix[\referencingparameter\c!prefix]
+\to \everysetupreferencing
+
+%D We can typeset a reference using \type{\in}, \type{\at} and
+%D \type{\about} and goto specific locations using
+%D \type{\goto}. The last one does not make that much sense in
+%D a paper document. To complicate things, \PLAIN\ \TEX\ also
+%D implements an \type {\in} but fortunately that one only
+%D makes sense in math mode.
+%D
+%D Typesetting the reference is a bit more complicated than one
+%D would at first sight expect. This is due to the fact that we
+%D distinguish three (five) alternative calls:
+%D
+%D \placefigure
+%D [here][three calls]
+%D {Three alternatives reference calls.}
+%D {\startcombination[1*3]
+%D {\framed{\type{ \in }}} {a}
+%D {\framed{\type{ \at }}} {b}
+%D {\framed{\type{\goto}}} {c}
+%D \stopcombination}
+%D
+%D \startbuffer
+%D \in figure[fig:three calls]
+%D \in{figure}[fig:three calls]
+%D \in figure a[fig:three calls]
+%D \in{figure}{a}[fig:three calls]
+%D figure~\in[fig:three calls]
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D This turns up as:
+%D
+%D \startlines
+%D \getbuffer
+%D \stoplines
+%D
+%D The dual \type{{}} results in a split reference. In a
+%D document meant for paper, one is tempted to use the last
+%D (most straightforward) alternative. When a document is also
+%D meant voor electronic distribution, the former alternatives
+%D have preference, because everything between the \type{\in}
+%D and~\type{[} becomes active (and when asked for, typeset
+%D in a different color and typeface).
+
+% \unexpanded\def\in {\mathortext\donormalmathin \strc_references_in}
+% \unexpanded\def\at {\mathortext\donormalmathat \strc_references_at}
+% \unexpanded\def\about{\mathortext\donormalmathabout\strc_references_about}
+% \unexpanded\def\from {\mathortext\donormalmathfrom \strc_references_from}
+% \unexpanded\def\over {\mathortext\donormalmathover \strc_references_about}
+
+% \definecommand in {\strc_references_in}
+% \definecommand at {\strc_references_at}
+% \definecommand about {\strc_references_about}
+% \definecommand from {\strc_references_from}
+% \definecommand over {\strc_references_about} % needed here, else math problems
+
+\appendtoks
+ \ifdefined\in \let\normalmathin \in \unexpanded\def\in {\mathortext\normalmathin \strc_references_in } \else \let\in \strc_references_in \fi
+ \ifdefined\at \let\normalmathat \at \unexpanded\def\at {\mathortext\normalmathat \strc_references_at } \else \let\at \strc_references_at \fi
+ \ifdefined\about \let\normalmathabout\about \unexpanded\def\about{\mathortext\normalmathabout\strc_references_about} \else \let\about\strc_references_about \fi
+ \ifdefined\from \let\normalmathfrom \from \unexpanded\def\from {\mathortext\normalmathfrom \strc_references_from } \else \let\from \strc_references_from \fi
+ \ifdefined\over \let\normalmathover \over \unexpanded\def\over {\mathortext\normalmathover \strc_references_about} \else \let\over \strc_references_about \fi
+\to \everydump
+
+ \def\filterreference #key{\clf_filterreference{#key}} % no checking, expanded
+\unexpanded\def\getreferenceentry#key{\clf_filterreference{#key}} % no checking, unexpanded
+
+\def\currentreferencenumber {\clf_filterreference{number}}
+\def\currentreferencepage {\clf_filterreference{page}}
+\def\currentreferencetitle {\clf_filterreference{title}}
+\def\currentreferencetext {\clf_filterreference{text}}
+\def\currentreferencedefault {\clf_filterreference{default}}
+\def\currentreferencerealpage{\clf_filterreference{realpage}}
+
+%D The most straightforward way of retrieving references is
+%D using \type{\ref}.
+
+\unexpanded\def\getreference % checking, unexpanded
+ {\dodoubleargument\strc_references_get_reference}
+
+\def\strc_references_get_reference[#key][#label]% #key = number page title text default realpage ...
+ {\ifsecondargument
+ \doifelsereferencefound{#label}{\clf_filterreference{#key}}\dummyreference
+ \else
+ \dummyreference
+ \fi}
+
+\let\ref\getreference
+
+%D Special cases:
+
+\unexpanded\def\strc_references_about[#label]%
+ {\dontleavehmode
+ \begingroup
+ \let\crlf\space
+ \let\\\space
+ \postponenotes % might go
+ \referencingparameter\c!left
+ \doifelsereferencefound{#label}
+ {\goto{\limitatetext\currentreferencetitle{\referencingparameter\c!width}\unknown}[#label]}% not so efficient (dup lookup)
+ {}% todo
+ \flushnotes % might go
+ \referencingparameter\c!right
+ \endgroup}
+
+%D The previously discussed setup macro lets us specify the
+%D representation of references. A symbol reference does not
+%D show the specific data, like the number of a figure, but
+%D shows one of: \hbox {$^\goforwardcharacter$
+%D $^\gobackwardcharacter$ $^\gonowherecharacter$}, depending
+%D on the direction to go.
+%D
+%D \starttyping
+%D ... \somewhere{backward text}{forward text}[someref] ...
+%D ... \atpage[someref] ...
+%D \stoptyping
+
+% standard detail
+%
+% 0 = unknown unknown
+% 1 = same on same page
+% 2 = before preceding page
+% 3 = after following page
+%
+% 4 = above above on same page
+% 5 = below below on same page
+
+% todo: optimize for use in pagebody
+% todo: maybe make it optional
+
+% \setuppagenumbering[alternative=doublesided]
+% \setupreferencing [doublesided=no] % yes is default
+%
+% \somewhere{backward}{foreward}[label]
+% \someplace{preceding}{backward}{current}{foreward}{following}[label]
+% \atpage[#label]
+% \doifcheckedpagestate{label}{preceding}{backward}{current}{foreward}{following}{otherwise}
+%
+% \dorecurse {20} {
+% \placefigure[here][fig:#1]{}{\externalfigure[dummy]}
+% \dorecurse {20} {
+% ##1: \atpage[fig:##1] /
+% \doifcheckedpagestate
+% {fig:##1}
+% {preceding}{backward}{current}{foreward}{following}
+% {otherwise}
+% }
+% }
+
+\newcount \nofreferencestates
+\newconditional\pagestatespread
+
+\appendtoks
+ \doifelse{\referencingparameter\c!doublesided}\v!yes\settrue\setfalse\pagestatespread
+\to \everysetupreferencing
+
+\setupreferencing
+ [\c!doublesided=\v!yes]
+
+\def\referencepagestate
+ {\numexpr\clf_referencepagestate
+ {rst::\number\nofreferencestates}%
+ \relax}
+
+\def\referencepagedetail
+ {\numexpr\clf_referencepagestate
+ {rst::\number\nofreferencestates}%
+ true %
+ \ifconditional\pagestatespread false\ifdoublesided true\else false\fi\fi
+ \relax}
+
+\def\referencerealpage
+ {\clf_referencerealpage}
+
+\unexpanded\def\tracedpagestate
+ {{\blue\tttf(\ifcase\referencepagedetail unknown\or same\or previous\or next\or above\or below\else unknown\fi)}}
+
+\unexpanded\def\markreferencepage
+ {\dontleavehmode\begingroup
+ \iftrialtypesetting
+ % issue warning that not stable
+ \else
+ % needs checking ... but probably never in trialmode
+ \global\advance\nofreferencestates\plusone
+ \xypos{rst::\number\nofreferencestates}%
+ % \tracedpagestate
+ \fi
+ \endgroup}
+
+\unexpanded\def\doifcheckedpagestate#label% #preceding#backward#current#foreward#following#otherwise%
+ {\doifelsereferencefound{#label}\strc_references_handle_page_state_yes\strc_references_handle_page_state_nop}
+
+\let\strc_references_handle_page_state_nop\sixthofsixarguments
+
+\def\strc_references_handle_page_state_yes
+ {\markreferencepage
+ \ifcase\referencepagedetail
+ \expandafter\sixthofsixarguments \or
+ \expandafter\thirdofsixarguments \or
+ \expandafter\firstofsixarguments \or
+ \expandafter\fifthofsixarguments \or
+ \expandafter\secondofsixarguments\or
+ \expandafter\fourthofsixarguments\else
+ \expandafter\sixthofsixarguments \fi}
+
+\unexpanded\def\referencesymbol
+ {\hbox\bgroup
+ \strut
+ \markreferencepage
+ \high
+ {\setupsymbolset[\interactionparameter\c!symbolset]%
+ \symbol[\ifcase\referencepagedetail\v!somewhere\or\v!nowhere\or\v!previous\or\v!next\or\v!previous\or\v!next\else\v!somewhere\fi]}%
+ \egroup}
+
+%D Hereafter the \type {\ignorespaces} binds the state node to next character (more likely
+%D than a preceding one) and one can always add an explicit space.
+
+\unexpanded\def\somewhere#backward#foreward#dummy[#label]% #dummy gobbles space around #foreward
+ {\doifcheckedpagestate{#label}%
+ {\goto{#backward}[#label]}%
+ {\goto{#backward}[#label]}%
+ {\ignorespaces}%
+ {\goto{#foreward}[#label]}%
+ {\goto{#foreward}[#label]}%
+ {#label}}%
+
+\unexpanded\def\someplace#preceding#backward#current#foreward#following#dummy[#label]% #dummy gobbles space around #foreward
+ {\doifcheckedpagestate{#label}%
+ {\doifelsenothing{#preceding}{\goto{#preceding}[#label]}\ignorespaces}%
+ {\doifelsenothing {#backward}{\goto {#backward}[#label]}\ignorespaces}%
+ {\doifelsenothing {#current}{\goto {#current}[#label]}\ignorespaces}%
+ {\doifelsenothing {#foreward}{\goto {#foreward}[#label]}\ignorespaces}%
+ {\doifelsenothing{#following}{\goto{#following}[#label]}\ignorespaces}%
+ {#label}}
+
+\unexpanded\def\atpage[#label]% todo
+ {\doifcheckedpagestate{#label}%
+ {\goto{\labeltext \v!precedingpage }[#label]}%
+ {\goto{\labeltext \v!hencefore }[#label]}%
+ {\ignorespaces}%
+ {\goto{\labeltext \v!hereafter }[#label]}%
+ {\goto{\labeltext \v!followingpage }[#label]}%
+ {\goto{\labeltexts\v!page\dummyreference}[#label]}}
+
+% Someone requested this but in retrospect didn't need it so we keep it as example.
+% Beware: a node is injected which is why we add ignorespaces!
+%
+% \unexpanded\def\strc_references_conditional#action#text[#condition]#dummy[#label]%
+% {\doifcheckedpagestate{#label}%
+% {\doifelse{#condition}\v!precedingpage{#action{#text}[#label]}\ignorespaces}%
+% {\doifelse{#condition}\v!hencefore {#action{#text}[#label]}\ignorespaces}%
+% {\doifelse{#condition}\v!current {#action{#text}[#label]}\ignorespaces}%
+% {\doifelse{#condition}\v!hereafter {#action{#text}[#label]}\ignorespaces}%
+% {\doifelse{#condition}\v!followingpage{#action{#text}[#label]}\ignorespaces}%
+% {#label}}
+%
+% \unexpanded\def\conditionalat {\strc_references_conditional\at}
+% \unexpanded\def\conditionalin {\strc_references_conditional\in}
+% \unexpanded\def\conditionalabout{\strc_references_conditional\about}
+
+%D The other alternatives just conform their names: only the label, only the text, or the
+%D label and the text.
+
+% \dounknownreference -> \dummyreference
+
+\def\symbolreference[#label]% for old times sake
+ {\goto{\referencesymbol}[#label]}
+
+% \referencecontentmode 0=all 1=label 2=text 3=symbol
+
+\newtoks\leftreferencetoks
+\newtoks\rightreferencetoks
+\newtoks\defaultleftreferencetoks
+\newtoks\defaultrightreferencetoks
+
+\def\leftofreferencecontent {\nobreakspace} % we cannot do \definereferenceformat[at] .. so we need this
+\let\rightofreferencecontent \empty
+\let\leftofreference \empty
+\let\rightofreference \empty
+
+\installcorenamespace{referencinginteraction}
+
+\def\strc_references_interaction_all
+ {\the\leftreferencetoks
+ \doifelsesometoks\leftreferencetoks \leftofreferencecontent \donothing
+ \leftofreference
+ \currentreferencecontent
+ \rightofreference
+ \doifelsesometoks\rightreferencetoks\rightofreferencecontent\donothing
+ \the\rightreferencetoks}
+
+\letvalue{\??referencinginteraction\v!all}\strc_references_interaction_all
+
+\setvalue{\??referencinginteraction\v!label}%
+ {\leftofreference
+ \the\leftreferencetoks
+ \the\rightreferencetoks
+ \rightofreference}
+
+\setvalue{\??referencinginteraction\v!text}%
+ {\leftofreference
+ \currentreferencecontent
+ \rightofreference}
+
+\setvalue{\??referencinginteraction\v!symbol}%
+ {\referencesymbol}
+
+% \def\referencesequence
+% {\csname\??referencinginteraction
+% \ifcsname\??referencinginteraction\referencingparameter\c!interaction\endcsname
+% \referencingparameter\c!interaction
+% \else
+% \v!all
+% \fi
+% \endcsname}
+
+\def\referencesequence
+ {\ifcsname\??referencinginteraction\referencingparameter\c!interaction\endcsname
+ \expandafter\lastnamedcs
+ \else
+ \expandafter\strc_references_interaction_all
+ \fi}
+
+\newtoks\everyresetinatreference
+
+\appendtoks
+ \glet\leftofreference \relax
+ \glet\rightofreference\relax
+\to \everyresetinatreference
+
+\def\strc_references_start_goto
+ {\dontleavehmode
+ \begingroup}
+
+\def\strc_references_stop_goto
+ {\the\everyresetinatreference
+ \endgroup}
+
+\def\strc_references_pickup_goto
+ {\dodoublegroupempty\strc_references_pickup_goto_indeed}
+
+\def\strc_references_pickup_goto_indeed#left#right#dummy[#label]% #dummy gobbles spaces (really needed)
+ {\leftreferencetoks
+ \iffirstargument
+ {#left}%
+ \else
+ \defaultleftreferencetoks
+ \let\leftofreferencecontent\empty
+ \fi
+ \rightreferencetoks
+ \ifsecondargument
+ {#right}%
+ \else
+ \defaultrightreferencetoks
+ \let\rightofreferencecontent\empty
+ \fi
+ % inefficient: double resolve
+ \doifelsereferencefound{#label} % we need to resolve the text
+ {\goto{\referencesequence}[#label]}
+ {\let\currentreferencecontent\dummyreference
+ \goto{\referencesequence}[#label]}%
+ \strc_references_stop_goto}
+
+\unexpanded\def\strc_references_in
+ {\strc_references_start_goto
+ \let\currentreferencecontent\currentreferencedefault
+ \strc_references_pickup_goto}
+
+\unexpanded\def\strc_references_at
+ {\strc_references_start_goto
+ \let\currentreferencecontent\currentreferencepage
+ \strc_references_pickup_goto}
+
+%D \macros
+%D {definereferenceformat}
+%D
+%D The next few macros were made for for David Arnold and Taco
+%D Hoekwater. They can be used for predefining reference
+%D texts, and thereby stimulate efficiency.
+%D
+%D \starttyping
+%D \definereferenceformat[informula] [left=(,right=),text=formula]
+%D \definereferenceformat[informulas] [left=(,right=),text=formulas]
+%D \definereferenceformat[andformula] [left=(,right=),text=and]
+%D \definereferenceformat[andformulas][left=(,right=),text=and]
+%D
+%D \informula [b] and \informula [for:c]
+%D the \informula {formulas}[b] \informula {and} [for:c]
+%D the \informulas {formulas}[b] \informula {and} [for:c]
+%D the \informulas [b] \informula {en} [for:c]
+%D the \informulas [b] \andformula [for:c]
+%D \stoptyping
+%D
+%D Instead of a text, one can specify a label, which should
+%D be defined with \type {\setuplabeltext}.
+%D
+%D Watch out: the second argument is somewhat special and mostly
+%D meant for a suffix to a number:
+%D
+%D \startbuffer
+%D \definereferenceformat [intesta] [left=(,right=),text=Whatever~]
+%D \definereferenceformat [intestb] [left=(,right=),label=figure]
+%D
+%D \placeformula[x]\startformula a \stopformula
+%D
+%D \starttabulate[|||||]
+%D \NC \in [x] \NC \in {left}[x] \NC \in {}{right}[x] \NC \in {left}{right}[x] \NC \NR
+%D \NC \intesta[x] \NC \intesta{left}[x] \NC \intesta{}{right}[x] \NC \intesta{left}{right}[x] \NC \NR
+%D \NC \intestb[x] \NC \intestb{left}[x] \NC \intestb{}{right}[x] \NC \intestb{left}{right}[x] \NC \NR
+%D \stoptabulate
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+% to be done: interfaced
+
+\installcorenamespace{referenceformat}
+
+\installcommandhandler \??referenceformat {referenceformat} \??referenceformat
+
+\appendtoks
+ \setuevalue\currentreferenceformat{\strc_references_apply_format{\currentreferenceformat}}%
+\to \everydefinereferenceformat
+
+\setupreferenceformat
+ [\c!left=,
+ \c!right=,
+ \c!text=,
+ \c!label=,
+ \c!autocase=\v!no,
+ \c!style=,
+ \c!type=default, % to be done: interfaced
+ \c!setups=,
+ \c!color=]
+
+\unexpanded\def\strc_references_apply_format#name%
+ {\strc_references_start_goto
+ \edef\currentreferenceformat{#name}%
+ \gdef\leftofreference {\referenceformatparameter\c!left }%
+ \gdef\rightofreference {\referenceformatparameter\c!right }%
+ \edef\currentreferenceformatlabel {\referenceformatparameter\c!label }%
+ \edef\currentreferenceformattype {\referenceformatparameter\c!type }%
+ \edef\currentreferenceformatsetups {\referenceformatparameter\c!setups }%
+ \edef\currentreferenceformatautocase{\referenceformatparameter\c!autocase}%
+ \usereferenceformatstyleandcolor\c!style\c!color
+ \ifx\currentstyleparameter\empty \else
+ \resetinteractionparameter\c!style
+ \fi
+ \ifx\currentcolorparameter\empty \else
+ \resetinteractionparameter\c!contrastcolor
+ \resetinteractionparameter\c!color
+ \fi
+ \ifx\currentreferenceformatlabel\autoreferencelabeltextflag
+ \edef\currentreferenceformatlabel{\autoreferencelabeltext}%
+ \fi
+ \ifx\currentreferenceformatautocase\v!yes
+ \setcharactercleaning[1]%
+ \fi
+ \ifx\currentreferenceformatlabel\empty
+ \defaultleftreferencetoks {\referenceformatparameter\c!text}%
+ \defaultrightreferencetoks\emptytoks
+ \else
+ \defaultleftreferencetoks {\leftlabeltext \currentreferenceformatlabel}%
+ \defaultrightreferencetoks{\rightlabeltext\currentreferenceformatlabel}%
+ \fi
+ \ifx\currentreferenceformattype\empty
+ \def\currentreferenceformattype{default}%
+ \fi
+ %
+ \ifx\currentreferenceformatsetups\empty
+ \def\currentreferencecontent{\filterreference\currentreferenceformattype}%
+ \else
+ \def\currentreferencecontent{\directsetup\currentreferenceformatsetups}%
+ \fi
+ %
+ \let\leftofreferencecontent \empty
+ \let\rightofreferencecontent\empty
+ \strc_references_pickup_goto}
+
+\def\autoreferencelabeltextflag{*} % a proper key like 'auto' or 'name' can clash with a label key
+
+\unexpanded\def\autoreferencelabeltext
+ {\clf_getcurrentreferencemetadata{name}}
+
+% \starttext
+% \definereferenceformat[inxx] [left=(,right=),text=txt]
+% \setupinteraction[state=start]
+% \chapter[one]{xx}
+% [\goto{state}[file(mk-last-state)]]
+% [\goto{state} [file(mk-last-state)]]
+% [\at{page} [one]]
+% [\at{page}[one]]
+% [\at{page}{okay}[one]]
+% [\inxx{a}{b}[one]]
+% \stoptext
+
+% \startsetups referenceformat:numberplustext
+% \filterreference{number}, \filterreference{title}
+% \stopsetups
+%
+% \definereferenceformat[hellup][text=Hellup ,setups=referenceformat:numberplustext]
+
+%D In interactive documents going to a specific location is not
+%D bound to cross references. The \type{\goto} commands can be
+%D used to let users access another part of the document. In
+%D this respect, interactive tables of contents and registers
+%D can be considered goto's. Because in fact a \type{\goto} is
+%D just a reference without reference specific data, the
+%D previous macros are implemented using the goto
+%D functionality.
+%D
+%D \showsetup{goto}
+%D
+%D One important characteristic is that the first argument of
+%D \type{\goto} (and therefore \type{\at} and \type{\in} is
+%D split at spaces. This means that, although hyphenation is
+%D prevented, long references can cross line endings.
+
+% \starttext
+% \setupinteraction[state=start]
+% [\goto{state}[file(mk-last-state)]]
+% [\goto{state} [file(mk-last-state)]]
+% \stoptext
+
+\newconditional\uselocationstrut \settrue\uselocationstrut
+
+\def\extrareferencearguments
+ {highlight \luaconditional\highlighthyperlinks\space
+ newwindow \luaconditional\gotonewwindow\space
+ layer {\currentviewerlayer}}
+
+\unexpanded\def\directgoto
+ {\ifconditional\uselocationstrut
+ \expandafter\dodirectgoto
+ \else
+ \expandafter\dodirectgotohtdp
+ \fi}
+
+\unexpanded\def\goto
+ {\ifconditional\uselocationstrut
+ \expandafter\dogoto
+ \else
+ \expandafter\dogotohtdp
+ \fi}
+
+% The unbox trick is needed in order to permit \par inside a reference. Otherwise
+% the reference attribute migrates to the outer boxes.
+
+\newcount\lastsavedreferenceattribute
+
+\newbox\referencebox
+
+\def\revivesavedreferenceattribute % sometimes handy as no test etc needed
+ {\attribute\referenceattribute\lastsavedreferenceattribute}
+
+\def\dodirectgoto#content[#label]% no test for valid references
+ {\dontleavehmode
+ \begingroup
+ \attribute\referenceattribute\attributeunsetvalue
+ \global\lastsavedreferenceattribute\attributeunsetvalue
+ \iflocation
+ \clf_injectreference
+ {\referenceprefix}%
+ {#label}%
+ {%
+ height \ht\strutbox
+ depth \dp\strutbox
+ \extrareferencearguments
+ }%
+ \relax
+ \setlocationattributes
+ \setstrut % can be option
+ \global\lastsavedreferenceattribute\lastreferenceattribute
+ \attribute\referenceattribute\lastreferenceattribute
+ \dostarttagged\t!link\empty % not here
+ #content%
+ \dostoptagged
+ \else
+ #content%
+ \fi
+ \endgroup}
+
+\def\dodirectgotohtdp#content[#label]% no test for valid references
+ {\dontleavehmode
+ \begingroup
+ \global\lastsavedreferenceattribute\attributeunsetvalue
+ \attribute\referenceattribute\attributeunsetvalue
+ \iflocation
+ \clf_injectreference
+ {\referenceprefix}%
+ {#label}%
+ {%
+ height \dimexpr\interactionparameter\c!height\relax
+ depth \dimexpr\interactionparameter\c!depth \relax
+ \extrareferencearguments
+ }%
+ \relax
+ \setlocationattributes
+ \attribute\referenceattribute\lastreferenceattribute
+ \global\lastsavedreferenceattribute\lastreferenceattribute
+ \dostarttagged\t!link\empty
+ #content%
+ \dostoptagged
+ \else
+ #content%
+ \fi
+ \endgroup}
+
+\def\dogoto#content#dummy[#label]% #dummy gobbles spaces
+ {\dontleavehmode
+ \begingroup
+ %\setbox\referencebox\hbox\bgroup % experiment, might change again to non \par support
+ \global\lastsavedreferenceattribute\attributeunsetvalue
+ \attribute\referenceattribute\attributeunsetvalue
+ \iflocation
+ \clf_doifelsereference{\referenceprefix}{#label}{\extrareferencearguments}%
+ {\expandtexincurrentreference
+ \clf_injectcurrentreferencehtdp
+ \ht\strutbox
+ \dp\strutbox
+ \relax
+ \setlocationattributes
+ \setstrut % can be option
+ \global\lastsavedreferenceattribute\lastreferenceattribute
+ \attribute\referenceattribute\lastreferenceattribute
+ \dostarttagged\t!link\empty
+ #content%
+ \dostoptagged}%
+ {#content}%
+ \else
+ #content%
+ \fi
+ %\egroup\unhbox\referencebox}
+ \endgroup}
+
+\unexpanded\def\startgoto[#label]%
+ {\dontleavehmode
+ \begingroup
+ \iflocation
+ \clf_doifelsereference{\referenceprefix}{#label}{\extrareferencearguments}%
+ {\expandafter\startgoto_yes}%
+ {\expandafter\startgoto_nop}%
+ \else
+ \expandafter\startgoto_nop
+ \fi}
+
+\unexpanded\def\startgoto_nop
+ {\let\stopgoto\stopgoto_nop}
+
+\unexpanded\def\stopgoto_nop
+ {\endgroup}
+
+\unexpanded\def\startgoto_yes
+ {\expandtexincurrentreference
+ \clf_injectcurrentreferencehtdp
+ \ht\strutbox
+ \dp\strutbox
+ \relax
+ \setlocationattributes
+ \setstrut % can be option
+ \global\lastsavedreferenceattribute\lastreferenceattribute
+ \attribute\referenceattribute\lastreferenceattribute
+ \dostarttagged\t!link\empty
+ \let\stopgoto\stopgoto_yes}
+
+\unexpanded\def\stopgoto_yes
+ {\dostoptagged
+ \endgroup}
+
+\def\dogotohtdp#content#dummy[#label]% dummy gobbles spaces
+ {\dontleavehmode
+ \begingroup
+ \global\lastsavedreferenceattribute\attributeunsetvalue
+ \attribute\referenceattribute\attributeunsetvalue
+ \iflocation
+ \clf_doifelsereference{\referenceprefix}{#label}{\extrareferencearguments}%
+ {\expandtexincurrentreference
+ \clf_injectcurrentreferencehtdp
+ \dimexpr\interactionparameter\c!height\relax
+ \dimexpr\interactionparameter\c!depth \relax
+ \relax
+ \setlocationattributes
+ \global\lastsavedreferenceattribute\lastreferenceattribute
+ \attribute\referenceattribute\lastreferenceattribute
+ \dostarttagged\t!link\empty
+ #content%
+ \dostoptagged}%
+ {#content}%
+ \else
+ #content%
+ \fi
+ \endgroup}
+
+\unexpanded\def\directgotobox#content[#label]% no test for valid references
+ {\dontleavehmode
+ \begingroup
+ \global\lastsavedreferenceattribute\attributeunsetvalue
+ \attribute\referenceattribute\attributeunsetvalue
+ \iflocation
+ \clf_injectreference
+ {\referenceprefix}%
+ {#label}%
+ {\extrareferencearguments}%
+ \relax
+ \setlocationattributes
+ \global\lastsavedreferenceattribute\lastreferenceattribute
+ \dostarttagged\t!link\empty
+ \hbox attr \referenceattribute \lastreferenceattribute {#content}%
+ \dostoptagged
+ \else
+ #content%
+ \fi
+ \endgroup}
+
+\unexpanded\def\directgotospecbox#resolver#content[#label]% no test for valid references
+ {\dontleavehmode
+ \begingroup
+ \global\lastsavedreferenceattribute\attributeunsetvalue
+ \attribute\referenceattribute\attributeunsetvalue
+ \iflocation
+ \clf_injectreference
+ {\referenceprefix}%
+ {#label}%
+ {\extrareferencearguments}%
+ \relax
+ \setlocationcolorspec{#resolver}% no consequence for strut
+ \global\lastsavedreferenceattribute\lastreferenceattribute
+ \dostarttagged\t!link\empty
+ \hbox attr \referenceattribute \lastreferenceattribute {#content}%
+ \dostoptagged
+ \else
+ #content%
+ \fi
+ \endgroup}
+
+\unexpanded\def\directgotodumbbox#content[#label]% no test for valid references
+ {\dontleavehmode
+ \begingroup
+ \global\lastsavedreferenceattribute\attributeunsetvalue
+ \attribute\referenceattribute\attributeunsetvalue
+ \iflocation
+ \clf_injectreference
+ {\referenceprefix}%
+ {#label}%
+ {\extrareferencearguments}%
+ \relax
+ \global\lastsavedreferenceattribute\lastreferenceattribute
+ \dostarttagged\t!link\empty
+ \hbox attr \referenceattribute \lastreferenceattribute {#content}%
+ \dostoptagged
+ \else
+ #content%
+ \fi
+ \endgroup}
+
+\unexpanded\def\gotobox#content[#label]%
+ {\dontleavehmode
+ \begingroup
+ \global\lastsavedreferenceattribute\attributeunsetvalue
+ \attribute\referenceattribute\attributeunsetvalue
+ \iflocation
+ \clf_doifelsereference{\referenceprefix}{#label}{\extrareferencearguments}%
+ {\expandtexincurrentreference
+ \clf_injectcurrentreference
+ \setlocationattributes
+ \global\lastsavedreferenceattribute\lastreferenceattribute
+ \dostarttagged\t!link\empty
+ \hbox attr \referenceattribute \lastreferenceattribute {#content}%
+ \dostoptagged}%
+ {#content}%
+ \else
+ #content%
+ \fi
+ \endgroup}
+
+\unexpanded\def\gotowdhtbox#width#height[#label]% fast variant for overlays
+ {\dontleavehmode
+ \begingroup
+ \setbox\scratchbox\emptyhbox
+ \wd\scratchbox#width%
+ \ht\scratchbox#height%
+ \global\lastsavedreferenceattribute\attributeunsetvalue
+ \attribute\referenceattribute\attributeunsetvalue
+ \clf_doifelsereference{\referenceprefix}{#label}{\extrareferencearguments}%
+ {\clf_injectcurrentreference
+ \global\lastsavedreferenceattribute\lastreferenceattribute
+ \hbox attr \referenceattribute \lastreferenceattribute {\box\scratchbox}}
+ {\box\scratchbox}%
+ \endgroup}
+
+%D An reference to another document can be specified as a file
+%D or as an \URL. Both are handled by the same mechanism and
+%D can be issued by saying something like:
+%D
+%D \starttyping
+%D \goto[dictionary::the letter a]
+%D \stoptyping
+%D
+%D One can imagine that many references to such a dictionary
+%D are made, so in most cases such a document reference in an
+%D indirect one.
+%D
+%D \showsetup{useexternaldocument}
+%D
+%D For example:
+%D
+%D \starttyping
+%D \useexternaldocument
+%D [dictionary][engldict]
+%D [The Famous English Dictionary]
+%D \stoptyping
+%D
+%D The next macro implements these relations, and also take
+%D care of loading the document specific references.
+%D
+%D The \URL\ alternative takes four arguments:
+%D
+%D \showsetup{useURL}
+%D
+%D like:
+%D
+%D \starttyping
+%D \useURL
+%D [dictionary][http://www.publisher.com/public][engldict]
+%D [The Famous English Dictionary]
+%D \stoptyping
+%D
+%D Several specifications are possible:
+%D
+%D \starttyping
+%D \useURL [id] [url] [file] [description]
+%D \useURL [id] [url] [file]
+%D \useURL [id] [url]
+%D \stoptyping
+%D
+%D This time we don't load the references when no file is
+%D specified. This is logical when one keeps in mind that a
+%D valid \URL\ can also be a mail address.
+
+\unexpanded\def\useurl {\doquadrupleempty\strc_references_use_url } % so that they can be used in expanded arguments
+\unexpanded\def\usefile{\dotripleargument\strc_references_use_file} % so that they can be used in expanded arguments
+
+\let\useURL \useurl
+\let\useexternaldocument\usefile
+
+\def\strc_references_use_url[#label][#url][#file][#description]%
+ {\clf_useurl{#label}{\detokenize{#url}}{\detokenize{#file}}{\detokenize{#description}}}
+
+\def\strc_references_use_file[#label][#file][#description]%
+ {\clf_usefile{#label}{\detokenize{#file}}{\detokenize{#description}}}
+
+\def\doifelseurldefined #label{\clf_doifelseurldefined {#label}}
+\def\doifelsefiledefined#label{\clf_doifelsefiledefined{#label}}
+
+\let\doifurldefinedelse \doifelseurldefined
+\let\doiffiledefinedelse\doifelsefiledefined
+
+%D \macros
+%D {url,setupurl}
+%D
+%D We also have: \type{\url} for directly calling the
+%D description. So we can say:
+%D
+%D \starttyping
+%D \useURL [one] [http://www.test.nl]
+%D \useURL [two] [http://www.test.nl] [] [Some Site]
+%D
+%D \url[one] or \from[two] or \goto{Whatever Site}[URL(two)]
+%D \stoptyping
+%D
+%D An \URL\ can be set up with
+%D
+%D \showsetup{setupurl}
+
+\installcorenamespace{url}
+
+\installdirectcommandhandler \??url {url}
+
+\setupurl
+ [\c!style=\v!type,
+ \c!color=]
+
+\unexpanded\def\url[#label]% move \hyphenatedurl to lua end (is already lua)
+ {\dontleavehmode
+ \begingroup
+ \useurlstyleandcolor\c!style\c!color
+ \hyphenatedurl{\clf_geturl{#label}}%
+ \endgroup}
+
+%D This macro is hooked into a support macro, and thereby
+%D \URL's break ok, according to the setting of a switch,
+%D
+%D \startbuffer
+%D \useURL
+%D [test]
+%D [sentence_sentence~sentence//sentence:sentence.sentence]
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D Such an \URL\ is, depending on the settings, hyphenated as:
+%D
+%D \getbuffer
+
+%D When defining the external source of information, one can
+%D also specify a suitable name (the last argument). This name
+%D can be called upon with:
+%D
+%D \showsetup{from}
+%D
+%D We keep this for compatibility reasons, hence the hackery.
+
+\unexpanded\def\strc_references_from
+ {\dosingleempty\strc_references_do_special_from}
+
+\def\strc_references_do_special_from[#label]%
+ {\dontleavehmode
+ \goto{\clf_from{#label}}[fileorurl(#label)]}
+
+\def\dofromurldescription#content% called at the lua end
+ {#content}
+
+\def\dofromurlliteral#content% called at the lua end
+ {\useurlstyleandcolor\c!style\c!color
+ \hyphenatedurl{#content}}
+
+\let\dofromfiledescription\dofromurldescription
+\let\dofromfileliteral \dofromurlliteral % maybe some day setupfile that inherits from url
+
+%D We also support:
+%D
+%D \starttyping
+%D \goto{some text}[file(identifier{location}]
+%D \stoptyping
+%D
+%D which is completely equivalent with
+%D
+%D \starttyping
+%D \goto{some text}[identifier::location]
+%D \stoptyping
+
+%D A special case of references are those to programs. These,
+%D very system dependant references are implemented by abusing
+%D some of the previous macros.
+%D
+%D \showsetup{setupprograms}
+%D \showsetup{defineprogram}
+%D \showsetup{program} % changed functionality !
+%D
+%D The latter gives access to the description of the program,
+%D being the last argument to the definition command.
+
+% also lua, like urls and files
+
+\installcorenamespace{programs}
+
+\installdirectcommandhandler \??programs {programs}
+
+\unexpanded\def\defineprogram
+ {\dotripleargument\strc_references_define_program}
+
+\def\strc_references_define_program[#name][#program][#description]%
+ {\clf_defineprogram{#name}{#program}{#description}}
+
+\def\program[#name]% incompatible, more consistent, hardy used anyway
+ {\dontleavehmode
+ \begingroup
+ \useprogramsstyleandcolor\c!style\c!color
+ \clf_getprogram{#name}%
+ \endgroup}
+
+%D As we can see, we directly use the special reference
+%D mechanism, which means that
+%D
+%D \starttyping
+%D \goto{some text}[program(name{args})]
+%D \stoptyping
+%D
+%D is valid.
+
+%D The next macro provides access to the actual pagenumbers.
+%D When documenting and sanitizing the original reference
+%D macros, I decided to keep the present meaning as well as to
+%D make this meaning available as a special reference method.
+%D So now one can use:
+%D
+%D \starttyping
+%D \gotopage{some text}[location]
+%D \gotopage{some text}[number]
+%D \gotopage{some text}[file::number]
+%D \stoptyping
+%D
+%D as well as:
+%D
+%D \starttyping
+%D \goto{some text}[page(location)]
+%D \goto{some text}[page(number)]
+%D \goto{some text}[file::page(number)]
+%D \stoptyping
+%D
+%D Here location is a keyword like \type{nextpage}.
+%D
+%D \showsetup{gotopage}
+
+\unexpanded\def\definepage
+ {\dodoubleargument\strc_references_define_page}
+
+\def\strc_references_define_page[#name][#target]%
+ {\definereference[#name][page(#target)]}
+
+\def\gotopage#text[#target]%
+ {\goto{#text}[\v!page(#target)]}
+
+%D The previous definitions are somewhat obsolete so we don't
+%D use it here.
+
+%D We can cross link documents by using:
+%D
+%D \showsetup{coupledocument}
+%D
+%D like:
+%D
+%D \starttyping
+%D \coupledocument[print][somefile][chapter,section]
+%D \stoptyping
+%D
+%D After which when applicable, we have available the
+%D references:
+%D
+%D \starttyping
+%D \goto{print version}[print::chapter]
+%D \stoptyping
+%D
+%D and alike. The title placement definition macros have a
+%D key \type{file}, which is interpreted as the file to jump
+%D to, that is, when one clicks on the title.
+
+\def\coupledocument
+ {\doquadrupleempty\strc_references_couple_document}
+
+\def\strc_references_couple_document[#name][#file][#sections][#description]%
+ {\ifthirdargument
+ % this will be done differently (when it's needed)
+ \fi}
+
+%D \macros
+%D {dotextprefix}
+%D
+%D In previous macros we used \type {\dotextprefix} to
+%D generate a space between a label and a number.
+%D
+%D \starttyping
+%D \dotextprefix{text}
+%D \stoptyping
+%D
+%D Only when \type {text} is not empty, a space is inserted.
+
+\unexpanded\def\dotextprefix#text%
+ {\begingroup
+ \setbox\scratchbox\hbox{#text}% to be solved some day
+ \ifdim\wd\scratchbox>\zeropoint
+ \unhbox\scratchbox
+ \edef\p_separator{\referencingparameter\c!separator}%
+ \ifx\p_separator\empty \else
+ \removeunwantedspaces % remove is new
+ \p_separator
+ \fi
+ \else
+ \unhbox\scratchbox
+ \fi
+ \endgroup}
+
+%D In the next settings we see some variables that were not
+%D used here and that concern the way the pagenumbers refered
+%D to are typeset.
+
+\setupreferencing
+ [\c!state=\v!start,
+ \c!autofile=\v!no,
+ \v!part\c!number=\v!yes,
+ \v!chapter\c!number=\v!no,
+ \c!interaction=\v!all,
+ \c!convertfile=\v!no,
+ %\c!strut=\v!no, % some day an option
+ \c!prefix=,
+ \c!width=.75\makeupwidth,
+ \c!left=\quotation\bgroup,
+ \c!right=\egroup,
+ \c!global=\v!no,
+ \c!expansion=\v!no,
+ \c!separator=\nonbreakablespace,
+ \c!export=\v!no]
+
+\setupprograms
+ [\c!directory=,
+ \c!style=\v!type,
+ \c!color=]
+
+\definereference [\v!CloseDocument ] [action(close)]
+\definereference [\v!ExitViewer ] [action(exit)]
+\definereference [\v!FirstPage ] [action(first)]
+\definereference [\v!LastPage ] [action(last)]
+\definereference [\v!NextJump ] [action(forward)]
+\definereference [\v!NextPage ] [action(next)]
+\definereference [\v!PauseMovie ] [action(pausemovie)]
+\definereference [\v!PauseSound ] [action(pausesound)]
+\definereference [\v!PauseRendering ] [action(pauserendering)]
+\definereference [\v!PreviousJump ] [action(backward)]
+\definereference [\v!PreviousPage ] [action(previous)]
+\definereference [\v!PrintDocument ] [action(print)]
+\definereference [\v!SaveForm ] [action(exportform)]
+\definereference [\v!LoadForm ] [action(importform)]
+\definereference [\v!ResetForm ] [action(resetform)]
+\definereference [\v!ResumeMovie ] [action(resumemovie)]
+\definereference [\v!ResumeSound ] [action(resumesound)]
+\definereference [\v!ResumeRendering ] [action(resumerendering)]
+\definereference [\v!SaveDocument ] [action(save)]
+\definereference [\v!SaveNamedDocument] [action(savenamed)]
+\definereference [\v!OpenNamedDocument] [action(opennamed)]
+\definereference [\v!SearchDocument ] [action(search)]
+\definereference [\v!SearchAgain ] [action(searchagain)]
+\definereference [\v!StartMovie ] [action(startmovie)]
+\definereference [\v!StartSound ] [action(startsound)]
+\definereference [\v!StartRendering ] [action(startrendering)]
+\definereference [\v!StopMovie ] [action(stopmovie)]
+\definereference [\v!StopSound ] [action(stopsound)]
+\definereference [\v!StopRendering ] [action(stoprendering)]
+\definereference [\v!SubmitForm ] [action(submitform)]
+\definereference [\v!ToggleViewer ] [action(toggle)]
+\definereference [\v!ViewerHelp ] [action(help)]
+\definereference [\v!HideField ] [action(hide)]
+\definereference [\v!ShowField ] [action(show)]
+\definereference [\v!GotoPage ] [action(gotopage)]
+\definereference [\v!Query ] [action(query)]
+\definereference [\v!QueryAgain ] [action(queryagain)]
+\definereference [\v!FitWidth ] [action(fitwidth)]
+\definereference [\v!FitHeight ] [action(fitheight)]
+\definereference [\v!ShowThumbs ] [action(thumbnails)]
+\definereference [\v!ShowBookmarks ] [action(bookmarks)]
+
+\definereference [\v!HideLayer ] [action(hidelayer)]
+\definereference [\v!VideLayer ] [action(videlayer)]
+\definereference [\v!ToggleLayer ] [action(togglelayer)]
+
+\definereference [\v!firstpage] [page(firstpage)]
+\definereference [\v!previouspage] [page(previouspage)]
+\definereference [\v!nextpage] [page(nextpage)]
+\definereference [\v!lastpage] [page(lastpage)]
+\definereference [\v!forward] [page(forward)]
+\definereference [\v!backward] [page(backward)]
+\definereference [\v!firstsubpage] [page(firstsubpage)]
+\definereference [\v!previoussubpage] [page(previoussubpage)]
+\definereference [\v!nextsubpage] [page(nextsubpage)]
+\definereference [\v!lastsubpage] [page(lastsubpage)]
+
+% we can do this but only when later in resolve (else problems with \chapter[first]{...}
+%
+% \definereference [\v!first] [page(firstpage)]
+% \definereference [\v!previous] [page(prevpage)]
+% \definereference [\v!next] [page(nextpage)]
+% \definereference [\v!last] [page(lastpage)]
+% \definereference [\v!first\v!sub] [page(firstsubpage)]
+% \definereference [\v!previous\v!sub] [page(prevsubpage)]
+% \definereference [\v!next\v!sub] [page(nextsubpage)]
+% \definereference [\v!last\v!sub] [page(lastsubpage)]
+
+%D We cannot set up buttons (not yet, this one calls a menu macro):
+
+%D New (and experimental):
+
+% \starttext
+% \chapter{test}
+% \placefigure[here][xx:1]{}{\framed{one}} \placefigure[here][xx:2]{}{\framed{three}}
+% \placetable [here][xx:3]{}{\framed{two}} \placetable [here][xx:4]{}{\framed{four}}
+% \start
+% \in{fig}[xx:1] and \in{fig}[xx:2] \in{tab}[xx:3] and \in{tab}[xx:4]
+% \stop \blank \start
+% \setupreferencestructureprefix[default][prefix=no]
+% \in{fig}[xx:1] and \in{fig}[xx:2] \in{tab}[xx:3] and \in{tab}[xx:4]
+% \stop \blank \start
+% \setupreferencestructureprefix[float][default][prefix=no]
+% \in{fig}[xx:1] and \in{fig}[xx:2] \in{tab}[xx:3] and \in{tab}[xx:4]
+% \stop \blank \start
+% \setupreferencestructureprefix[figure][default][prefix=no]
+% \in{fig}[xx:1] and \in{fig}[xx:2] \in{tab}[xx:3] and \in{tab}[xx:4]
+% \stop \blank
+% \stoptext
+
+% todo: parameterhandler
+
+\installcorenamespace{referencingprefix}
+
+\def\getreferencestructureprefix#kind#name#category% name will change
+ {{%
+ prefix {\referencestructureprefixparameter{#kind}{#name}{#category}\c!prefix}%
+ separatorset {\referencestructureprefixparameter{#kind}{#name}{#category}\c!prefixseparatorset}%
+ conversion {\referencestructureprefixparameter{#kind}{#name}{#category}\c!prefixconversion}%
+ conversionset {\referencestructureprefixparameter{#kind}{#name}{#category}\c!prefixconversionset}%
+ starter {\referencestructureprefixparameter{#kind}{#name}{#category}\c!prefixstarter}%
+ stopper {\referencestructureprefixparameter{#kind}{#name}{#category}\c!prefixstopper}%
+ set {\referencestructureprefixparameter{#kind}{#name}{#category}\c!prefixset}%
+ segments {\referencestructureprefixparameter{#kind}{#name}{#category}\c!prefixsegments}%
+ connector {\referencestructureprefixparameter{#kind}{#name}{#category}\c!prefixconnector}%
+ }%
+ {%
+ separatorset {\referencestructureprefixparameter{#kind}{#name}{#category}\c!numberseparatorset}%
+ conversion {\referencestructureprefixparameter{#kind}{#name}{#category}\c!numberconversion}%
+ conversionset {\referencestructureprefixparameter{#kind}{#name}{#category}\c!numberconversionset}%
+ starter {\referencestructureprefixparameter{#kind}{#name}{#category}\c!numberstarter}%
+ stopper {\referencestructureprefixparameter{#kind}{#name}{#category}\c!numberstopper}%
+ segments {\referencestructureprefixparameter{#kind}{#name}{#category}\c!numbersegments}%
+ }}
+
+\unexpanded\def\setupreferencestructureprefix
+ {\dotripleempty\strc_references_setup_reference_structure_prefix}
+
+\def\strc_references_setup_reference_structure_prefix[#kind][#category][#settings]%
+ {\ifthirdargument
+ \getparameters[\??referencingprefix#kind:#category][#settings]%
+ \else\ifsecondargument
+ \getparameters[\??referencingprefix:#kind][#category]%
+ \fi\fi}
+
+\def\referencestructureprefixparameter#kind#name#category#parameter%
+ {\ifcsname\??referencingprefix#name:#category#parameter\endcsname
+ \lastnamedcs
+ \else\ifcsname\??referencingprefix#kind:#category#parameter\endcsname
+ \lastnamedcs
+ \else\ifcsname\??referencingprefix:#category#parameter\endcsname
+ \lastnamedcs
+ \fi\fi\fi}
+
+\def\currentreferencedefault % for some reason we need to explicitly expand
+ {\normalexpanded{\noexpand\clf_filterdefaultreference
+ {\s!default}%
+ \noexpand\getreferencestructureprefix\clf_getcurrentprefixspec{\s!default}% returns #kind#name#category
+ \relax}}
+
+%D Not all support is visible by looking at the \TEX\ code; here is one of those:^
+%D
+%D \starttyping
+%D \startinteractionmenu[right]
+%D \startbut [section(first {chapter})] first chapter \stopbut
+%D \startbut [section(previous{chapter})] previous chapter \stopbut
+%D \startbut [section(next {chapter})] next chapter \stopbut
+%D \startbut [section(last {chapter})] last chapter \stopbut
+%D \blank[2*big]
+%D \startbut [section(first {section})] first section \stopbut
+%D \startbut [section(previous{section})] previous section \stopbut
+%D \startbut [section(next {section})] next section \stopbut
+%D \startbut [section(last {section})] last section \stopbut
+%D \stopinteractionmenu
+%D \stoptyping
+
+%D Relatively new:
+%D
+%D \starttyping
+%D \chapter{The never ending story}
+%D
+%D \section{An ending story}
+%D
+%D \in{chapter}[match(complex bibliographies)]
+%D \in{chapter}[match(never ending)]
+%D \in{chapter}[match(ending)]
+%D \in{chapter}[match(chapter:never ending)]
+%D \in{chapter}[match(chapter:ending)]
+%D \in{section}[match(section:ending)]
+%D \in{figure}[match(float:mess)]
+%D \in{figure}[match(figure:mess)]
+%D \in{figure (not found)}[match(section:mess)]
+%D \in{figure (not found)}[match(section:xxxx)]
+%D \in{figure}[match(mess)]
+%D
+%D \placefigure{What a mess}{}
+%D
+%D \chapter{About complex bibliographies}
+%D
+%D \in{chapter}[match(complex bibliographies)]
+%D \in{chapter}[match(never ending)]
+%D \in{figure}[match(mess)]
+%D \stoptyping
+
+%D Tracing:
+
+\unexpanded\def\strc_references_tracer#1#2% \csleft csright
+ {\hbox to \zeropoint \bgroup
+ \hss
+ \infofont
+ \darkblue
+ \ifx#1\empty\else
+ \raise\strutht \hbox \s!to \zeropoint \bgroup
+ \hss#1\hskip.2\emwidth
+ \egroup
+ \fi
+ \vrule \s!height 1.5\strutht \s!depth \strutdp \s!width .1\emwidth
+ \ifx#2\empty\else
+ \raise\strutht \hbox \s!to \zeropoint \bgroup
+ \hskip.2\emwidth#2\hss
+ \egroup
+ \fi
+ \hss
+ \egroup}%
+
+\protect \endinput
+
+% tricky:
+%
+% \enabletrackers[nodes.references]
+% \setupinteraction[state=start]
+% \def\KnuthTest{\input knuth }
+% \def\KnuthTest{\input tufte }
+% \def\TufteTest{\input tufte }
+% \defineoverlay[xxx][\overlaybutton{page(3)}]
+% \setupbackgrounds[text][background=xxx]
+% \starttext
+% test {\red \KnuthTest} test \par
+% \button{test}[page(1)] \par
+% \goto{page 2 \TeX}[page(2)] \goto{page 2 \TeX}[page(2)] \goto{\TufteTest}[page(2)] test \page
+% test \goto{page 3}[page(3)] \goto{\TufteTest\space\par\TufteTest}[page(4)] test \page
+% \goto{page 1}[page(1)] \goto{\TufteTest\space test}[page(1)] \page
+% \goto{page 1}[page(1)] \goto{\KnuthTest\space test}[page(1)] \page
+% test \goto{page 1}[page(1)] {\goto{\KnuthTest\space test}[page(1)]} test
+% \goto{page 1}[page(1)] \goto{\TufteTest}[page(1)] test \page
+% \stoptext