summaryrefslogtreecommitdiff
path: root/tex/context/base/strc-ref.mkvi
diff options
context:
space:
mode:
authorMarius <mariausol@gmail.com>2011-10-01 12:00:13 +0300
committerMarius <mariausol@gmail.com>2011-10-01 12:00:13 +0300
commite4bd8545244428bdf7ffb5feba6680683aa8f68f (patch)
tree11b84c6ff3910b3c8ce2764a9e49a92ccee5839c /tex/context/base/strc-ref.mkvi
parent0526f4b53574cd916c133899b611422d487c6047 (diff)
downloadcontext-e4bd8545244428bdf7ffb5feba6680683aa8f68f.tar.gz
beta 2011.10.01 10:48
Diffstat (limited to 'tex/context/base/strc-ref.mkvi')
-rw-r--r--tex/context/base/strc-ref.mkvi1732
1 files changed, 1732 insertions, 0 deletions
diff --git a/tex/context/base/strc-ref.mkvi b/tex/context/base/strc-ref.mkvi
new file mode 100644
index 000000000..40f03a6d6
--- /dev/null
+++ b/tex/context/base/strc-ref.mkvi
@@ -0,0 +1,1732 @@
+%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
+%
+% \definestructureconversionset[default][Character,number,Romannumerals,Character][number]
+% \definestructureseparatorset [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
+
+\def\s!full{full}
+\def\s!user{user}
+\def\s!text{text}
+\def\s!page{page}
+
+% 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
+%D is one of the core features, although at a first glance
+%D probably nobody will notice. This is good, because
+%D referencing should be as hidden as possible.
+%D
+%D In paper documents, referencing comes down to cross
+%D referencing, but in their interactive counterparts, is also
+%D involves navigation. Many features implemented here are
+%D therefore closely related to navigation.
+%D
+%D Many \CONTEXT\ commands can optionally be fed with a
+%D reference. Such a reference, when called upon, returns the
+%D number of a figure, table, chapter etc, a piece of text, or
+%D 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\do_text_reference}
+\unexpanded\def\pagereference {\dosingleargument\do_page_reference}
+\unexpanded\def\reference {\dosingleargument\do_full_reference}
+\unexpanded\def\setreference {\dodoubleargument\do_set_reference }
+
+%D These are implemented in a low level form as:
+
+\def\do_text_reference [#labels]{\do_do_set_reference\s!text{#labels}{}}
+\def\do_page_reference [#labels]{\do_do_set_reference\s!page{#labels}{}{}}
+\def\do_full_reference [#labels]{\do_do_set_reference\s!full{#labels}{}}
+\def\do_set_reference[#labels][#settings]{\do_do_set_reference\s!user{#labels}{#settings}{}}
+
+%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\dofinishfullreference#prefix#label{\normalexpanded{\ctxlatelua{structures.references.enhance("#prefix","#label")}}}
+\def\dofinishtextreference#prefix#label{\normalexpanded{\ctxlatelua{structures.references.enhance("#prefix","#label",{})}}}
+
+\let\dofinishpagereference\dofinishfullreference
+\let\dofinishuserreference\dofinishfullreference
+
+\def\dofinishsomereference#kind{\executeifdefined{dofinish#{kind}reference}\gobbletwoarguments}
+
+\def\do_do_set_reference
+ {\ifreferencing
+ \expandafter\do_do_do_set_reference
+ \else
+ \expandafter\gobblefourarguments
+ \fi}
+
+\def\do_do_do_set_reference#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{\@@rfexpansion}% {\referenceparameter\c!expansion}
+ \ifx\currentreferencelabels\empty \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
+ \ctxlua{structures.references.setandgetattribute("\currentreferencekind", "\referenceprefix","\currentreferencelabels",
+ {
+ references = {
+ % internal = \nextinternalreference, % no need for an internal as we have an explicit
+ block = "\currentsectionblock",
+ section = structures.sections.currentid(),
+ },
+ metadata = { % we could assume page to have no metadata
+ kind = "#kind",
+ \ifx\currentreferencekind\s!page\else
+ catcodes = \the\catcodetable,
+ xmlroot = \ifx\currentreferencecoding\s!xml "\xmldocument"\else nil\fi, % only useful when text
+ \fi
+ },
+ \ifx\currentreferencedata\empty\else
+ entries = {
+ text = \!!bs\currentreferencedata\!!es
+ },
+ \fi
+ \ifx\currentreferenceuserdata\empty\else
+ userdata = structures.helpers.touserdata(\!!bs\detokenize{#userdata}\!!es)
+ \fi
+ },"\interactionparameter\c!focus")
+ }%
+ % todo: optional
+ \xdef\currentdestinationattribute{\number\lastdestinationattribute}%
+ \begingroup\attribute\destinationattribute\currentdestinationattribute\emptyhbox\endgroup % todo
+ \fi
+ \fi}
+
+\def\defaultreferencepage#text{[[[#text]]]}
+\def\defaultreferencetext#text{[[[#text]]]}
+
+%D For internal usage:
+
+\def\dosetsimplepagereference#label%
+ {\iflocation
+ \ctxlua{structures.references.setandgetattribute("\s!page", "\referenceprefix","#label",
+ {
+ references = {
+ % block = "\currentsectionblock",
+ % section = structures.sections.currentid(),
+ },
+ metadata = { % we could assume page to have no metadata
+ kind = "\s!page",
+ },
+ },"\interactionparameter\c!focus")
+ }%
+ \xdef\currentdestinationattribute{\number\lastdestinationattribute}%
+ \else
+ \xdef\currentdestinationattribute{\number\attributeunsetvalue}%
+ \fi}
+
+\def\dogetsimplepagereference#label%
+ {\iflocation
+ \ctxlua{structures.references.inject("\referenceprefix","#label",\number\ht\strutbox,\number\dp\strutbox,\extrareferencearguments)}%
+ \xdef\currentreferenceattribute{\number\lastreferenceattribute}%
+ \else
+ \xdef\currentreferenceattribute{\number\attributeunsetvalue}%
+ \fi}
+
+%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
+
+\def\referencepagestate{\ctxcommand{referencepagestate()}}
+\def\referencerealpage {\ctxcommand{referencerealpage ()}}
+
+% 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\do_define_reference}
+
+\def\do_define_reference[#name][#specification]%
+ {\ctxlua{structures.references.define("\referenceprefix","#name",\!!bs\detokenize{#specification}\!!es)}}
+
+\unexpanded\def\resetreference[#name]%
+ {\ctxlua{structures.references.reset("\referenceprefix","#name")}}
+
+\def\setpagereference#name#specification% hm,. low level ?
+ {\ctxlua{structures.references.define("","#name",\!!bs\v!page(\luaescapestring{#specification})\!!es)}}
+
+%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\ctxlua{structures.references.expandcurrent()}\fi}
+
+\def\expandreferenceoperation#tag#content{\ctxcommand{setreferenceoperation(#tag,\!!bs#content\!!es)}}
+\def\expandreferencearguments#tag#content{\ctxcommand{setreferencearguments(#tag,\!!bs#content\!!es)}}
+
+\def\doifreferencefoundelse#labels#yes#nop%
+ {\ctxlua{structures.references.doifelse("\referenceprefix","#labels",\luaconditional\highlighthyperlinks,\luaconditional\gotonewwindow)}%
+ {\expandtexincurrentreference
+ #yes}%
+ {#nop}}
+
+%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 ??}}
+
+%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.
+
+\ifx\buttonheight\undefined \newdimen\buttonheight \fi
+\ifx\buttonwidth \undefined \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
+ {\ctxlua{structures.references.setnextinternal("#kind","#name")}}
+
+\def\getinternalorderreference#kind#name%
+ {\ctxlua{structures.references.currentorder("#kind","#name")}}
+
+\def\thisissomeinternal#kind#name% only for old time sake
+ {\begingroup
+ \ctxlua{structures.references.setinternalreference("","#kind:#name")}%
+ \hbox attr \destinationattribute\lastdestinationattribute{}%
+ \endgroup}
+
+\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
+
+\newif\ifreferencing \referencingtrue
+
+%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
+
+%D These settings are accomplished by:
+%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.
+
+\newtoks \everysetupreferencing
+
+\unexpanded\def\setupreferencing
+ {\dosingleargument\do_setup_referencing}
+
+\def\do_setup_referencing[#settings]%
+ {\getparameters[\??rf][\c!prefix=\s!unknown,#settings]%
+ \the\everysetupreferencing}
+
+\appendtoks
+ \processaction
+ [\@@rfstate]
+ [ \v!stop=>\referencingfalse,
+ \v!start=>\referencingtrue]%
+\to \everysetupreferencing
+
+\newconditional\autocrossfilereferences
+
+\appendtoks
+ \doifelse\@@rfautofile\v!yes\settrue\setfalse\autocrossfilereferences
+\to \everysetupreferencing
+
+\def\exportreferences
+ {\doif\@@rfexport\v!yes{\ctxlua{structures.references.export()}}}
+
+\appendtoks
+ \exportreferences
+\to \everygoodbye
+
+\def\incrementreferenceprefix{+}
+\def\decrementreferenceprefix{-}
+
+\unexpanded\def\setupreferenceprefix[#prefix]%
+ {\edef\@@rfprefix{#prefix}%
+ \ifx\@@rfprefix\empty
+ \let\referenceprefix\empty
+ \else\ifx\@@rfprefix\incrementreferenceprefix
+ \advance\prefixcounter \plusone % should be global
+ \edef\referenceprefix{\the\prefixcounter}%
+ \let\@@rfprefix\s!unknown
+ \else\ifx\@@rfprefix\decrementreferenceprefix
+ \let\referenceprefix\empty
+ \let\@@rfprefix\s!unknown
+ \else\ifx\@@rfprefix\s!unknown
+ % forget about it
+ \else
+ \edef\referenceprefix{\@@rfprefix}% expanded !
+ \fi\fi\fi\fi}
+
+\unexpanded\def\setupglobalreferenceprefix[#prefix]%
+ {\xdef\referenceprefix{#prefix}}
+
+\unexpanded\def\pushreferenceprefix#prefix%
+ {\pushmacro\referenceprefix
+ \xdef\referenceprefix{#prefix}}
+
+\unexpanded\def\popreferenceprefix
+ {\popmacro\referenceprefix}
+
+%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 \reference_in}
+% \unexpanded\def\at {\mathortext\donormalmathat \reference_at}
+% \unexpanded\def\about{\mathortext\donormalmathabout\reference_about}
+% \unexpanded\def\from {\mathortext\donormalmathfrom \reference_from}
+% \unexpanded\def\over {\mathortext\donormalmathover \reference_about}
+
+% \definecommand in {\reference_in}
+% \definecommand at {\reference_at}
+% \definecommand about {\reference_about}
+% \definecommand from {\reference_from}
+% \definecommand over {\reference_about} % needed here, else math problems
+
+\appendtoks
+ \ifdefined\in \let\normalmathin \in \unexpanded\def\in {\mathortext\normalmathin \reference_in } \else \let\in \reference_in \fi
+ \ifdefined\at \let\normalmathat \at \unexpanded\def\at {\mathortext\normalmathat \reference_at } \else \let\at \reference_at \fi
+ \ifdefined\about \let\normalmathabout\about \unexpanded\def\about{\mathortext\normalmathabout\reference_about} \else \let\about\reference_about \fi
+ \ifdefined\from \let\normalmathfrom \from \unexpanded\def\from {\mathortext\normalmathfrom \reference_from } \else \let\from \reference_from \fi
+ \ifdefined\over \let\normalmathover \over \unexpanded\def\over {\mathortext\normalmathover \reference_about} \else \let\over \reference_about \fi
+\to \everydump
+
+ \def\filterreference #key{\ctxcommand{filterreference("#key")}} % no checking, expanded
+\unexpanded\def\getreferenceentry#key{\ctxcommand{filterreference("#key")}} % no checking, unexpanded
+
+\def\currentreferencenumber {\filterreference{number}}
+\def\currentreferencepage {\filterreference{page}}
+\def\currentreferencetitle {\filterreference{title}}
+\def\currentreferencetext {\filterreference{text}}
+\def\currentreferencedefault {\filterreference{default}}
+\def\currentreferencerealpage{\filterreference{realpage}}
+
+%D The most straightforward way of retrieving references is
+%D using \type{\ref}.
+
+\unexpanded\def\getreference % checking, unexpanded
+ {\dodoubleargument\do_get_reference}
+
+\def\do_get_reference[#key][#label]% #key = number page title text default realpage ...
+ {\ifsecondargument
+ \doifreferencefoundelse{#label}{\ctxcommand{filterreference("#key")}}\dummyreference
+ \else
+ \dummyreference
+ \fi}
+
+\let\ref\getreference
+
+%D Special cases:
+
+\unexpanded\def\reference_about[#label]%
+ {\dontleavehmode
+ \begingroup
+ \let\crlf\space
+ \let\\\space
+ \postponenotes
+ \@@rfleft
+ \doifreferencefoundelse{#label}
+ {\goto{\limitatetext\currentreferencetitle\@@rfwidth\unknown}[#label]}% not so efficient (dup lookup)
+ {}% todo
+ \@@rfright
+ \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.
+
+% 0 = unknown
+% 1 = same
+% 2 = before
+% 3 = after
+
+\def\do_by_reference_page_state#unknown#before#current#after%
+ {\ifcase\referencepagestate\relax#unknown\or#current\or#before\or#after\fi}
+
+\unexpanded\def\somewhere#backward#foreward#dummy[#label]% #dummy gobbles space around #foreward
+ {\doifreferencefoundelse{#label}% usage needs checking (useless)
+ {\goto{\do_by_reference_page_state{#label}{#backward}{}{#foreward}}[#label]}
+ {[#label]}}
+
+\unexpanded\def\atpage[#label]% todo
+ {\doifreferencefoundelse{#label}% kind of inefficient as \goto also analyzes
+ {\goto
+ {\do_by_reference_page_state
+ {\labeltexts\v!page\dummyreference}%
+ {\labeltext\v!hencefore}%
+ {\labeltexts\v!atpage\currentreferencepage}%
+ {\labeltext\v!hereafter}}%
+ [#label]}
+ {[#label]}}
+
+\unexpanded\def\referencesymbol
+ {\hbox{\strut\high
+ {\setupsymbolset[\interactionparameter\c!symbolset]%
+ \symbol[\do_by_reference_page_state\v!somewhere\v!nowhere\v!previous\v!next]}}}
+
+%D The other alternatives just conform their names: only the
+%D label, only the text, or the 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
+
+\setvalue{\??rf\c!interaction\v!all}%
+ {\the\leftreferencetoks
+ \doifsometokselse\leftreferencetoks \leftofreferencecontent \donothing
+ \leftofreference
+ \currentreferencecontent
+ \rightofreference
+ \doifsometokselse\rightreferencetoks\rightofreferencecontent\donothing
+ \the\rightreferencetoks}
+
+\setvalue{\??rf\c!interaction\v!label}%
+ {\leftofreference
+ \the\leftreferencetoks
+ \the\rightreferencetoks
+ \rightofreference}
+
+\setvalue{\??rf\c!interaction\v!text}%
+ {\leftofreference
+ \currentreferencecontent
+ \rightofreference}
+
+\setvalue{\??rf\c!interaction\v!symbol}%
+ {\referencesymbol}
+
+\def\referencesequence
+ {\csname \??rf\c!interaction
+ \ifcsname\??rf\c!interaction\@@rfinteraction\endcsname
+ \@@rfinteraction
+ \else
+ \v!all
+ \fi
+ \endcsname}
+
+\newtoks\everyresetinatreference
+
+\appendtoks
+ \glet\leftofreference \relax
+ \glet\rightofreference\relax
+\to \everyresetinatreference
+
+\def\start_goto_reference
+ {\dontleavehmode
+ \begingroup}
+
+\def\stop_goto_reference
+ {\the\everyresetinatreference
+ \endgroup}
+
+\def\pickup_goto_reference
+ {\dodoublegroupempty\do_pickup_goto_reference}
+
+\def\do_pickup_goto_reference#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
+ \doifreferencefoundelse{#label} % we need to resolve the text
+ {\goto{\referencesequence}[#label]}
+ {\let\currentreferencecontent\dummyreference
+ \goto{\referencesequence}[#label]}%
+ \stop_goto_reference}
+
+\unexpanded\def\reference_in{\start_goto_reference\let\currentreferencecontent\currentreferencedefault\pickup_goto_reference}
+\unexpanded\def\reference_at{\start_goto_reference\let\currentreferencecontent\currentreferencepage \pickup_goto_reference}
+
+%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
+
+\installcommandhandler \??re {referenceformat} \??re
+
+\appendtoks
+ \setuevalue\currentreferenceformat{\execute_reference_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\execute_reference_format#name%
+ {\start_goto_reference
+ \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}%
+ \dosetreferenceformatattributes \c!style \c!color
+ \ifx\fontattributehash\empty \else
+ \resetinteractionparameter\c!style
+ \fi
+ \ifx\colorattributehash\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
+ \pickup_goto_reference}
+
+\def\autoreferencelabeltextflag{*} % a proper key like 'auto' or 'name' can clash with a label key
+
+\unexpanded\def\autoreferencelabeltext
+ {\ctxlua{structures.references.getcurrentmetadata("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
+ {\luaconditional\highlighthyperlinks,\luaconditional\gotonewwindow,"\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
+ \ctxlua{structures.references.inject("\referenceprefix","#label",\number\ht\strutbox,\number\dp\strutbox,\extrareferencearguments)}%
+ \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
+ \ctxlua{structures.references.inject("\referenceprefix","#label",\number\dimexpr\interactionparameter\c!height\relax,\number\dimexpr\interactionparameter\c!depth\relax,\extrareferencearguments)}%
+ \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
+ \ctxlua{structures.references.doifelse("\referenceprefix","#label",\extrareferencearguments)}%
+ {\expandtexincurrentreference
+ \ctxlua{structures.references.injectcurrentset(\number\ht\strutbox,\number\dp\strutbox)}%
+ \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}
+
+\def\dogotohtdp#content#dummy[#label]% dummy gobbles spaces
+ {\dontleavehmode
+ \begingroup
+ \global\lastsavedreferenceattribute\attributeunsetvalue
+ \attribute\referenceattribute\attributeunsetvalue
+ \iflocation
+ \ctxlua{structures.references.doifelse("\referenceprefix","#label",\extrareferencearguments)}%
+ {\expandtexincurrentreference
+ \ctxlua{structures.references.injectcurrentset(\number\dimexpr\interactionparameter\c!height\relax,\number\dimexpr\interactionparameter\c!depth\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
+ \ctxlua{structures.references.inject("\referenceprefix","#label",nil,nil,\extrareferencearguments)}%
+ \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
+ \ctxlua{structures.references.inject("\referenceprefix","#label",nil,nil,\extrareferencearguments)}%
+ \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
+ \ctxlua{structures.references.inject("\referenceprefix","#label",nil,nil,\extrareferencearguments)}%
+ \global\lastsavedreferenceattribute\lastreferenceattribute
+ \dostarttagged\t!link\empty
+ \hbox attr \referenceattribute \lastreferenceattribute {#content}%
+ \dostoptagged
+ \else
+ #content%
+ \fi
+ \endgroup}
+
+\unexpanded\def\gotobox#content[#label]% no test for valid references
+ {\dontleavehmode
+ \begingroup
+ \global\lastsavedreferenceattribute\attributeunsetvalue
+ \attribute\referenceattribute\attributeunsetvalue
+ \iflocation
+ \ctxlua{structures.references.doifelse("\referenceprefix","#label",\extrareferencearguments)}%
+ {\expandtexincurrentreference
+ \ctxlua{structures.references.injectcurrentset(nil,nil)}%
+ \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
+ \ctxlua{structures.references.doifelse("\referenceprefix","#label",\extrareferencearguments)}%
+ {\ctxlua{structures.references.injectcurrentset(nil,nil)}%
+ \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\do_use_url } % so that they can be used in expanded arguments
+\unexpanded\def\usefile{\dotripleargument\do_use_file} % so that they can be used in expanded arguments
+
+\let\useURL \useurl
+\let\useexternaldocument\usefile
+
+\def\do_use_url[#label][#url][#file][#description]%
+ {\ctxlua{structures.references.urls.define("#label",\!!bs\detokenize{#url}\!!es,\!!bs\detokenize{#file}\!!es,\!!bs\detokenize{#description}\!!es)}}
+
+\def\do_use_file[#label][#file][#description]%
+ {\ctxlua{structures.references.files.define("#label",\!!bs\detokenize{#file}\!!es,\!!bs\detokenize{#description}\!!es)}}
+
+\def\doifurldefinedelse #label{\ctxcommand{doifurldefinedelse ("#label")}}
+\def\doiffiledefinedelse#label{\ctxcommand{doiffiledefinedelse("#label")}}
+
+%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}
+
+\unexpanded\def\setupurl
+ {\dodoubleargument\getparameters[\??ur]}
+
+\unexpanded\def\url[#label]% move \hyphenatedurl to lua end (is already lua)
+ {\dontleavehmode
+ \begingroup
+ \dosetfontattribute\??ur\c!style
+ \dosetcolorattribute\??ur\c!color
+ \hyphenatedurl{\ctxlua{structures.references.urls.get("#label","\@@uralternative","\@@urspace")}}%
+ \endgroup}
+
+% # fails
+
+%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
+%D \startlinecorrection
+%D \hbox to \hsize
+%D {\hss\en
+%D \setupreferencing[urlalternative=both]%
+%D \vbox{\hsize.25cm\hbox{\bf both}\prewordbreak\url[test]}%
+%D \hss
+%D \setupreferencing[urlalternative=before]%
+%D \vbox{\hsize.25cm\hbox{\bf before}\prewordbreak\url[test]}%
+%D \hss
+%D \setupreferencing[urlalternative=after]%
+%D \vbox{\hsize.25cm\hbox{\bf after}\prewordbreak\url[test]}%
+%D \hss}
+%D \stoplinecorrection
+%D
+%D By setting \type{urlspace=yes} one can get slightly better
+%D spacing when using very long \URL's.
+%D
+%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 We keep this for compatibility reasons, hence the hackery.
+
+\unexpanded\def\reference_from
+ {\dosingleempty\do_do_special_from}
+
+\def\do_do_special_from[#label]%
+ {\dontleavehmode
+ \goto{\ctxlua{structures.references.from("#label")}}[fileorurl(#label)]}
+
+\def\dofromurldescription#content% called at the lua end
+ {#content}
+
+\def\dofromurlliteral#content% called at the lua end
+ {\dosetfontattribute \??ur\c!style
+ \dosetcolorattribute\??ur\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
+
+\unexpanded\def\setupprograms
+ {\dodoubleargument\getparameters[\??pr]}
+
+\unexpanded\def\defineprogram
+ {\dotripleargument\do_define_program}
+
+\def\do_define_program[#name][#program][#description]%
+ {\ctxlua{structures.references.programs.define("#name","#program","#description")}}
+
+\def\program[#name]% incompatible, more consistent, hardy used anyway
+ {\dontleavehmode
+ \begingroup
+ \dosetfontattribute\??pr\c!style
+ \dosetcolorattribute\??pr\c!color
+ \ctxlua{structures.references.programs.get("#name","\@@pralternative","\@@prspace")}%
+ \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\do_define_page}
+
+\def\do_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 A still very rudimentary|/|experimental forward|/|backward
+%D reference mechanism is provided by the macro \type{\atpage}:
+%D
+%D \starttyping
+%D ... \somewhere{backward text}{forward text}[someref] ...
+%D ... \atpage[someref] ...
+%D \stoptyping
+%D
+%D In future versions there will be more sophisticated
+
+% 0 = no page reference
+% 1 = same page
+% 2 = preceding page
+% 3 = following page
+% 4 = backward, same page (todo)
+% 5 = forward, same page (todo)
+
+%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\do_couple_document}
+
+\def\do_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.
+
+\def\dotextprefix#text%
+ {\begingroup
+ \setbox\scratchbox\hbox{#text}% to be solved some day
+ \ifdim\wd\scratchbox>\zeropoint
+ \unhbox\scratchbox
+ \doifsomething\@@rfseparator{\removeunwantedspaces\@@rfseparator}% remove is new
+ \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]
+
+\setupurl
+ [\c!alternative=\v!both,
+ \c!space=\v!no,
+ \c!style=\v!type,
+ \c!color=]
+
+\setupprograms
+ [\c!directory=,
+ \c!alternative=\v!both,
+ \c!space=\v!no,
+ \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
+
+\def\getreferencestructureprefix#kind#name#category%
+ {{
+ 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",
+ set = "\referencestructureprefixparameter{#kind}{#name}{#category}\c!prefixset",
+ segments = "\referencestructureprefixparameter{#kind}{#name}{#category}\c!prefixsegments",
+ connector = \!!bs\referencestructureprefixparameter{#kind}{#name}{#category}\c!prefixconnector\!!es,
+ }}
+
+\unexpanded\def\setupreferencestructureprefix
+ {\dotripleempty\do_setup_reference_structure_prefix}
+
+\def\do_setup_reference_structure_prefix[#kind][#category][#settings]%
+ {\ifthirdargument
+ \getparameters[\??rf:\c!prefix:#kind:#category][#settings]%
+ \else\ifsecondargument
+ \getparameters[\??rf:\c!prefix::#kind][#category]%
+ \fi\fi}
+
+\def\referencestructureprefixparameter#kind#name#category#parameter%
+ {\ifcsname\??rf:\c!prefix:#name:#category#parameter\endcsname
+ \csname\??rf:\c!prefix:#name:#category#parameter\endcsname
+ \else\ifcsname\??rf:\c!prefix:#kind:#category#parameter\endcsname
+ \csname \??rf:\c!prefix:#kind:#category#parameter\endcsname
+ \else\ifcsname\??rf:\c!prefix::#category#parameter\endcsname
+ \csname \??rf:\c!prefix::#category#parameter\endcsname
+ \fi\fi\fi}
+
+\def\currentreferencedefault
+ {\ctxlua{structures.references.filter("default",\ctxlua{structures.references.getcurrentprefixspec("\v!default")})}}
+
+%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
+
+\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