%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 / Hans Hagen] %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][.,.,--][.] % \setupstructurehead[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-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\dotextreference} \unexpanded\def\pagereference {\dosingleargument\dopagereference} \unexpanded\def\reference {\dosingleargument\doreference } \unexpanded\def\setreference {\dodoubleargument\dosetreference } %D These are implemented in a low level form as: \def\dotextreference [#1]{\dodosetreference\s!text{#1}{}} \def\dopagereference [#1]{\dodosetreference\s!page{#1}{}{}} \def\doreference [#1]{\dodosetreference\s!full{#1}{}} \def\dosetreference[#1][#2]{\dodosetreference\s!user{#1}{#2}{}} %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#1#2{\normalexpanded{\ctxlatelua{structures.references.enhance("#1","#2")}}} \def\dofinishtextreference#1#2{\normalexpanded{\ctxlatelua{structures.references.enhance("#1","#2",{})}}} \let\dofinishpagereference\dofinishfullreference \let\dofinishuserreference\dofinishfullreference \def\dofinishsomereference#1{\executeifdefined{dofinish#1reference}\gobbletwoarguments} \def\dodosetreference {\ifreferencing \expandafter\dododosetreference \else \expandafter\gobblefourarguments \fi} \def\dododosetreference#1#2#3#4% kind 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{#1}% \edef\currentreferencelabels{#2}% \edef\currentreferenceuserdata{#3}% \edef\currentreferenceexpansion{\@@rfexpansion}% {\referenceparameter\c!expansion} \ifx\currentreferencelabels\empty \else \ifx\currentreferenceexpansion\s!xml \xmlstartraw \xdef\currentreferencedata{#4}% data, no text else conflict \xmlstopraw \globallet\currentreferencecoding\s!xml \else \ifx\currentreferenceexpansion\v!yes \xdef\currentreferencedata{#4}% \else \xdef\currentreferencedata{\detokenize{#4}}% \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 = "\currentstructureblock", section = structures.sections.currentid(), }, metadata = { % we could assume page to have no metadata kind = "#1", \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{#3}\!!es) \fi },"\interactionparameter\c!focus") }% % todo: optional \xdef\currentdestinationattribute{\number\lastdestinationattribute}% \begingroup\attribute\destinationattribute\currentdestinationattribute\emptyhbox\endgroup % todo \fi \fi} \def\defaultreferencepage#1{[[[#1]]]} \def\defaultreferencetext#1{[[[#1]]]} %D For internal usage: \def\dosetsimplepagereference#1% label {\iflocation \ctxlua{structures.references.setandgetattribute("\s!page", "\referenceprefix","#1", { references = { % block = "\currentstructureblock", % 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#1% {\iflocation \ctxlua{structures.references.inject("\referenceprefix","#1",\number\ht\strutbox,\number\dp\strutbox,\extrareferencearguments)}% \xdef\currentreferenceattribute{\number\lastreferenceattribute}% \else \xdef\currentreferenceattribute{\number\attributeunsetvalue}% \fi} %D These macros depend on three other ones, %D \type {\makesectionformat}, that generated \type %D {\sectionformat}, \type {\pagenumber}. The not yet used %D argument \type{#1} is a tag that specifies the type of %D reference. %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 \def\usereferences[#1]% not yet {\writestatus\m!system{references from other files are handled automatically}} %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\referencepagestate % set in backend \newcount\referencehastexstate % set in backend % referencepagestate: % % 0 = no page ref, 1=same page, 2=before, 3=after %D Text references can contain more than one entry and %D therefore we check for %D %D \starttyping %D {entry} %D \stoptyping %D %D or %D %D \starttyping %D {{entry}{entry}{entry}} %D \stoptyping %D %D and split accordingly. %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 When we split off the components of such a reference, the %D results are available in: %D %D \starttyping %D \currentreferencespecial %D \currentreferenceoperation %D \currentreferencearguments %D \currentinnerreference %D \currentouterreference %D \currentfullreference %D \stoptyping \newif\ifreferencefound % \let\currentfullreference \empty % \let\currentreferencespecial \empty % \let\currentreferenceoperation\empty % \let\currentreferencearguments\empty % \let\currentouterreference \empty % \let\currentinnerreference \empty %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\dodefinereference} \def\dodefinereference[#1][#2]% {\ctxlua{structures.references.define("\referenceprefix","#1",\!!bs\detokenize{#2}\!!es)}} \def\resetreference[#1]% {\ctxlua{structures.references.reset("\referenceprefix","#1")}} \def\setpagereference#1#2% name, specification {\ctxlua{structures.references.define("","#1",\!!bs\v!page(\luaescapestring{#2})\!!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#1#2{\ctxcommand{setreferenceoperation(#1,\!!bs#2\!!es)}} \def\expandreferencearguments#1#2{\ctxcommand{setreferencearguments(#1,\!!bs#2\!!es)}} \def\doifreferencefoundelse#1#2#3% {\ctxlua{structures.references.doifelse("\referenceprefix","#1",\luaconditional\highlighthyperlinks,\luaconditional\gotonewwindow)}% {\expandtexincurrentreference#2}% {#3}} %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. \def\analyzecurrentreference {\ctxlua{structures.references.analyze()}} %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. % \def\unknownreference#1% % {\iftrialtypesetting \else % \ifinpagebody \else % \doifconcepttracing{\doifsomething{#1}{\inleft{\infofont\doboundtext{#1}{\dimexpr\leftmarginwidth-2em\relax}{..}->}}}% % \fi % \fi} \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#1#2% plural {\ctxlua{structures.references.setnextinternal("#1","#2")}} \def\getinternalorderreference#1#2% {\ctxlua{structures.references.currentorder("#1","#2")}} \def\thisissomeinternal#1#2% tag reference (only for old time sake) {\begingroup \ctxlua{structures.references.setinternalreference("","#1:#2")}% \hbox attr \destinationattribute\lastdestinationattribute{}% \endgroup} \newconditional\preferpagereferences \def\gotosomeinternal#1#2#3#4% {\ifconditional\preferpagereferences \directgoto{#4}[page(#3)]% \else \directgoto{#4}[#1:#2]% \fi} \def\gotonextinternal#1#2% {\directgoto{#1}[internal(#2)]} %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 % compatibility hack \def\setglobalsystemreference#1#2#3{\definereference[#2][\v!action(#3)]} \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. \newconstant\autocrossfilereferences % not yet supported in mkiv \newconstant\referencefilecaseswap % not yet supported in mkiv \newtoks \everysetupreferencing \unexpanded\def\setupreferencing {\dosingleargument\dosetupreferencing} \def\dosetupreferencing[#1]% {\getparameters[\??rf][\c!prefix=\s!unknown,#1]% \the\everysetupreferencing} \appendtoks \processaction [\@@rfstate] [ \v!stop=>\referencingfalse, \v!start=>\referencingtrue]% \to \everysetupreferencing % \newconstant \referencecontentmode % % \appendtoks % \processaction % [\@@rfinteraction] % [ \v!all=>\referencecontentmode\zerocount, % \v!label=>\referencecontentmode\plusone, % \v!text=>\referencecontentmode\plustwo, % \v!symbol=>\referencecontentmode\plusthree]% % \to \everysetupreferencing \appendtoks \autocrossfilereferences\zerocount \processaction [\@@rfautofile] % not yet in mkiv [ \v!yes=>\autocrossfilereferences\plusone, \v!page=>\autocrossfilereferences\plustwo]% \to \everysetupreferencing \appendtoks \referencefilecaseswap\zerocount \processaction[\@@rfconvertfile] % not yet in mkiv [ \v!yes=>\referencefilecaseswap\plusone, \v!big=>\referencefilecaseswap\plusone, \v!small=>\referencefilecaseswap\plustwo]% \to \everysetupreferencing \appendtoks \setupreferenceprefix[\@@rfprefix]% \doifelse\@@rfglobal\v!yes {\settrue \autoglobalfilereferences}% {\setfalse\autoglobalfilereferences}% \to \everysetupreferencing % \appendtoks\ctxlua{structures.references.export("whatever")}\to\everystoptext % \starttext % \chapter[test]{test} % test \in{IN}[more] and \in{IN}[test] or \at{AT}[more] and \at{AT}[test]\par % test \in{IN}[whatever::more] and \in{IN}[whatever::test] or \at{AT}[whatever::more] and \at{AT}[whatever::test] \page % reference\reference[more]{oeps} % \stoptext \def\exportreferences {\doif\@@rfexport\v!yes{\ctxlua{structures.references.export()}}} \appendtoks \exportreferences \to \everygoodbye \def\incrementreferenceprefix{+} \def\decrementreferenceprefix{-} \unexpanded\def\setupreferenceprefix[#1]% {\edef\@@rfprefix{#1}% \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:}% \fi\fi\fi\fi} %D The most straightforward way of retrieving references is %D using \type{\ref}. Consider the reference: %D %D \startbuffer %D \reference[my ref]{{Look}{Here}{I am}} %D \stopbuffer %D %D \typebuffer %D %D \getbuffer %D %D We can ask for upto five reference components: %D %D \startbuffer %D user page reference: \ref[p][my ref] %D text reference: \ref[t][my ref] %D real page reference: \ref[r][my ref] %D sub text reference: \ref[s][my ref] %D extra text reference: \ref[e][my ref] %D \stopbuffer %D %D \typebuffer %D %D And get back: %D %D \startlines %D \getbuffer %D \stoplines %D %D This is a cheap compatibility hack. Don't use this command %D as there will be more advanced access to user data. \def\ref{\dodoubleargument\doref} \def\reftypep{\currentreferencepage} \def\reftypet{\currentreferencetext} \def\reftyper{\currentreferencepage} \def\reftypes{\currentreferencetext} \def\reftypee{\currentreferencetext} \def\doref[#1][#2]% {\ifsecondargument \doifreferencefoundelse{#2} {\executeifdefined{reftype#1}\reftypep} {\dummyreference}% \else \dummyreference \fi} %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 \dospecialin} % \unexpanded\def\at {\mathortext\donormalmathat \dospecialat} % \unexpanded\def\about{\mathortext\donormalmathabout\dospecialabout} % \unexpanded\def\from {\mathortext\donormalmathfrom \dospecialfrom} % \unexpanded\def\over {\mathortext\donormalmathover \dospecialabout} % \definecommand in {\dospecialin} % \definecommand at {\dospecialat} % \definecommand about {\dospecialabout} % \definecommand from {\dospecialfrom} % \definecommand over {\dospecialabout} % needed here, else math problems \def\currentreferencenumber {\ctxlua{structures.references.filter("number")}} \def\currentreferencepage {\ctxlua{structures.references.filter("page")}} \def\currentreferencetitle {\ctxlua{structures.references.filter("title")}} \def\currentreferencetext {\ctxlua{structures.references.filter("text")}} \def\currentreferencedefault {\ctxlua{structures.references.filter("default")}} \def\currentreferencerealpage{\ctxlua{structures.references.realpage()}} \def\getreferenceentry#1{\ctxlua{structures.references.filter("#1")}} % user entry \unexpanded\def\dospecialabout[#1]% {\dontleavehmode \begingroup \let\crlf\space \let\\\space \postponenotes \@@rfleft \doifreferencefoundelse{#1} {\goto{\limitatetext\currentreferencetitle\@@rfwidth\unknown}[#1]}% 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. % 1 = whatever % 2 = forward, following page % 3 = backward, preceding page % 4 = forward, same page % 5 = backward, same page % Yet untested: \unexpanded\def\somewhere#1#2#3[#4]% #3 gobbles space around #2 % todo {\doifreferencefoundelse{#4}% kind of inefficient as \goto also analyzes {\goto{\analyzecurrentreference\ifcase\referencepagestate\relax#1/#2\or#2\or#1\or#2\fi}[#4]} {[#1/#2]}} \unexpanded\def\atpage[#1]% todo {\doifreferencefoundelse{#1}% kind of inefficient as \goto also analyzes {\goto{\analyzecurrentreference\ifcase\referencepagestate \labeltexts\v!page\dummyreference \or \labeltexts\v!atpage\currentreferencepage \or \labeltexts\v!atpage\currentreferencepage \or \labeltexts\v!atpage\currentreferencepage \or \labeltext\v!hereafter \or \labeltext\v!hencefore \fi}[#1]} {[?]}} \unexpanded\def\referencesymbol {\hbox{\strut\high {\setupsymbolset[\interactionparameter\c!symbolset]% \symbol [\ifcase\referencepagestate \v!somewhere \or % same \v!nowhere \or % before \v!previous \or % after \v!next% \fi]}}} %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[#1]% for old times sake {\goto{\referencesymbol}[#1]} % \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}% {\leftofreference \the\leftreferencetoks \doifsometokselse\leftreferencetoks \leftofreferencecontent \donothing \currentreferencecontent \doifsometokselse\rightreferencetoks\rightofreferencecontent\donothing \the\rightreferencetoks \rightofreference} \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\dostartgotoreference {\dontleavehmode \begingroup} \def\dostopgotoreference {\the\everyresetinatreference \endgroup} \def\dopickupgotoreference {\dodoublegroupempty\dodopickupgotoreference} \def\dodopickupgotoreference#1#2#3[#4]% #3 gobbles spaces (really needed) {\leftreferencetoks \iffirstargument {#1}% \else \defaultleftreferencetoks \let\leftofreferencecontent\empty \fi \rightreferencetoks \ifsecondargument {#2}% \else \defaultrightreferencetoks \let\rightofreferencecontent\empty \fi \doifreferencefoundelse{#4} % we need to resolve the text {\goto{\referencesequence}[#4]} {\let\currentreferencecontent\dummyreference \goto{\referencesequence}[#4]}% \dostopgotoreference} \unexpanded\def\dospecialin{\dostartgotoreference\let\currentreferencecontent\currentreferencedefault\dopickupgotoreference} \unexpanded\def\dospecialat{\dostartgotoreference\let\currentreferencecontent\currentreferencepage \dopickupgotoreference} %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 %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 % todo: inherit \let\currentreferenceformat\empty \def\referenceformatparameter#1% some day we will add inheritance {\ifcsname\??rf\currentreferenceformat#1\endcsname\csname\??rf\currentreferenceformat#1\expandafter\endcsname\fi} \unexpanded\def\definereferenceformat {\dodoubleargument\dodefinereferenceformat} % left right text label \def\dodefinereferenceformat[#1][#2]% {\iffirstargument \getparameters[\??rf#1][\c!left=,\c!right=,\c!text=,\c!label=,\c!autocase=v!no,#2]% \setuvalue{#1}{\doexecutereferenceformat{#1}}% \fi} \def\doexecutereferenceformat#1% quite slow due to all assignments but we will speed it up {\dostartgotoreference % once it's stable \edef\currentreferenceformat{#1}% \gdef\leftofreference {\referenceformatparameter\c!left }% \gdef\rightofreference{\referenceformatparameter\c!right}% % we can make a helper for this .. we will use the new parameter handler anyway % but at least aditya can play with it now \doifsomething{\referenceformatparameter\c!style} {\dosetfontattribute{\??rf\currentreferenceformat}\c!style \resetinteractionparameter\c!style}% \doifsomething{\referenceformatparameter\c!color} {\dosetcolorattribute{\??rf\currentreferenceformat}\c!color \resetinteractionparameter\c!contrastcolor \resetinteractionparameter\c!color}% % \edef\currentreferenceformatlabel{\referenceformatparameter\c!label}% \ifx\currentreferenceformatlabel\autoreferencelabeltextflag \edef\currentreferenceformatlabel{\autoreferencelabeltext}% \fi \doif{\referenceformatparameter\c!autocase}\v!yes {\setcharactercleaning[1]}% \ifx\currentreferenceformatlabel\empty \defaultleftreferencetoks {\referenceformatparameter\c!text}% \defaultrightreferencetoks\emptytoks \else \defaultleftreferencetoks {\leftlabeltext \currentreferenceformatlabel}% \defaultrightreferencetoks{\rightlabeltext\currentreferenceformatlabel}% \fi \doifelse{\referenceformatparameter\c!type}\v!page {\let\currentreferencecontent\currentreferencepage} {\let\currentreferencecontent\currentreferencedefault}% \let\leftofreferencecontent \empty \let\rightofreferencecontent\empty \dopickupgotoreference} \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 %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\directgotohtdp\fi} \unexpanded\def\goto {\ifconditional\uselocationstrut\expandafter\dogoto \else\expandafter\gotohtdp \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#1[#2]% no test for valid references {\dontleavehmode \begingroup \attribute\referenceattribute\attributeunsetvalue \global\lastsavedreferenceattribute\attributeunsetvalue \iflocation \ctxlua{structures.references.inject("\referenceprefix","#2",\number\ht\strutbox,\number\dp\strutbox,\extrareferencearguments)}% \setlocationattributes\??ia \setstrut % can be option \global\lastsavedreferenceattribute\lastreferenceattribute \attribute\referenceattribute\lastreferenceattribute \dostarttagged\t!link\empty % not here #1% \dostoptagged \else #1% \fi \endgroup} \def\dodirectgotohtdp#1[#2]% no test for valid references {\dontleavehmode \begingroup \global\lastsavedreferenceattribute\attributeunsetvalue \attribute\referenceattribute\attributeunsetvalue \iflocation \ctxlua{structures.references.inject("\referenceprefix","#2",\number\dimexpr\interactionparameter\c!height\relax,\number\dimexpr\interactionparameter\c!depth\relax,\extrareferencearguments)}% \setlocationattributes\??ia \attribute\referenceattribute\lastreferenceattribute \global\lastsavedreferenceattribute\lastreferenceattribute \dostarttagged\t!link\empty #1% \dostoptagged \else #1% \fi \endgroup} \def\dogoto#1#2[#3]% #2 gobbles spaces after #1 so that \goto{xx} [yy] works ok {\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","#3",\extrareferencearguments)}% {\expandtexincurrentreference \ctxlua{structures.references.injectcurrentset(\number\ht\strutbox,\number\dp\strutbox)}% \setlocationattributes\??ia \setstrut % can be option \global\lastsavedreferenceattribute\lastreferenceattribute \attribute\referenceattribute\lastreferenceattribute \dostarttagged\t!link\empty #1% \dostoptagged}% {#1}% \else #1% \fi %\egroup\unhbox\referencebox} \endgroup} \def\dogotohtdp#1#2[#3]% #2 gobbles spaces after #1 so that \goto{xx} [yy] works ok {\dontleavehmode \begingroup \global\lastsavedreferenceattribute\attributeunsetvalue \attribute\referenceattribute\attributeunsetvalue \iflocation \ctxlua{structures.references.doifelse("\referenceprefix","#3",\extrareferencearguments)}% {\expandtexincurrentreference \ctxlua{structures.references.injectcurrentset(\number\dimexpr\interactionparameter\c!height\relax,\number\dimexpr\interactionparameter\c!depth\relax)}% \setlocationattributes\??ia \global\lastsavedreferenceattribute\lastreferenceattribute \attribute\referenceattribute\lastreferenceattribute \dostarttagged\t!link\empty #1% \dostoptagged}% {#1}% \else #1% \fi \endgroup} \unexpanded\def\directgotobox#1[#2]% no test for valid references {\dontleavehmode \begingroup \global\lastsavedreferenceattribute\attributeunsetvalue \attribute\referenceattribute\attributeunsetvalue \iflocation \ctxlua{structures.references.inject("\referenceprefix","#2",nil,nil,\extrareferencearguments)}% \setlocationattributes\??ia \global\lastsavedreferenceattribute\lastreferenceattribute \dostarttagged\t!link\empty \hbox attr \referenceattribute \lastreferenceattribute {#1}% \dostoptagged \else #1% \fi \endgroup} \unexpanded\def\directgotospecbox#1#2[#3]% no test for valid references {\dontleavehmode \begingroup \global\lastsavedreferenceattribute\attributeunsetvalue \attribute\referenceattribute\attributeunsetvalue \iflocation \ctxlua{structures.references.inject("\referenceprefix","#3",nil,nil,\extrareferencearguments)}% \setlocationcolorspec{#1}% no consequence for strut \global\lastsavedreferenceattribute\lastreferenceattribute \dostarttagged\t!link\empty \hbox attr \referenceattribute \lastreferenceattribute {#2}% \dostoptagged \else #2% \fi \endgroup} \unexpanded\def\directgotodumbbox#1[#2]% no test for valid references {\dontleavehmode \begingroup \global\lastsavedreferenceattribute\attributeunsetvalue \attribute\referenceattribute\attributeunsetvalue \iflocation \ctxlua{structures.references.inject("\referenceprefix","#2",nil,nil,\extrareferencearguments)}% \global\lastsavedreferenceattribute\lastreferenceattribute \dostarttagged\t!link\empty \hbox attr \referenceattribute \lastreferenceattribute {#1}% \dostoptagged \else #1% \fi \endgroup} \unexpanded\def\gotobox#1[#2]% no test for valid references {\dontleavehmode \begingroup \global\lastsavedreferenceattribute\attributeunsetvalue \attribute\referenceattribute\attributeunsetvalue \iflocation \ctxlua{structures.references.doifelse("\referenceprefix","#2",\extrareferencearguments)}% {\expandtexincurrentreference \ctxlua{structures.references.injectcurrentset(nil,nil)}% \setlocationattributes\??ia \global\lastsavedreferenceattribute\lastreferenceattribute \dostarttagged\t!link\empty \hbox attr \referenceattribute \lastreferenceattribute {#1}% \dostoptagged}% {#1}% \else #1% \fi \endgroup} \unexpanded\def\gotowdhtbox#1#2[#3]% fast variant for overlays {\dontleavehmode \begingroup \setbox\scratchbox\emptyhbox\wd\scratchbox#1\ht\scratchbox#2% \global\lastsavedreferenceattribute\attributeunsetvalue \attribute\referenceattribute\attributeunsetvalue \ctxlua{structures.references.doifelse("\referenceprefix","#3",\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\usefile{\dotripleargument\dousefile} % so that they can be used in expanded arguments \unexpanded\def\useurl {\doquadrupleempty\douseurl } % so that they can be used in expanded arguments \let\useURL \useurl \let\useexternaldocument\usefile \def\douseurl[#1][#2][#3][#4]% {\ctxlua{structures.references.urls.define("#1",\!!bs\detokenize{#2}\!!es,\!!bs\detokenize{#3}\!!es,\!!bs\detokenize{#4}\!!es)}} \def\dousefile[#1][#2][#3]% {\ctxlua{structures.references.files.define("#1",\!!bs\detokenize{#2}\!!es,\!!bs\detokenize{#3}\!!es)}} \def\doifurldefinedelse #1{\ctxcommand{doifurldefinedelse ("#1")}} \def\doiffiledefinedelse#1{\ctxcommand{doiffiledefinedelse("#1")}} %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[#1]% {\dontleavehmode \begingroup \dosetfontattribute\??ur\c!style \dosetcolorattribute\??ur\c!color \hyphenatedurl{\ctxlua{structures.references.urls.get("#1","\@@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\dospecialfrom {\dosingleempty\dodospecialfrom} \def\dodospecialfrom[#1]% {\dontleavehmode \goto{\ctxlua{structures.references.from("#1")}}[fileorurl(#1)]} \def\dofromurldescription#1% {#1} \def\dofromurlliteral#1% {\dosetfontattribute \??ur\c!style \dosetcolorattribute\??ur\c!color \hyphenatedurl{#1}} \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\dodefineprogram} \def\dodefineprogram[#1][#2][#3]% {\ctxlua{structures.references.programs.define("#1","#2","#3")}} \def\program[#1]% incompatible, more consistent, hardy used anyway {\dontleavehmode \begingroup \dosetfontattribute\??pr\c!style \dosetcolorattribute\??pr\c!color \ctxlua{structures.references.programs.get("#1","\@@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\dodefinepage} \def\dodefinepage[#1][#2]% {\definereference[#1][page(#1)]} \def\gotopage#1[#2]% {\goto{#1}[\v!page(#2)]} %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\docoupledocument} \def\docoupledocument[#1][#2][#3][#4]% [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#1% {\begingroup \setbox\scratchbox\hbox{#1}% 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 \unexpanded\def\setupreferencestructureprefix {\dotripleargument\dosetupreferencestructureprefix} \def\getreferencestructureprefix#1#2#3% {{ prefix = "\referencestructureprefixparameter{#1}{#2}{#3}\c!prefix", separatorset = "\referencestructureprefixparameter{#1}{#2}{#3}\c!prefixseparatorset", conversion = "\referencestructureprefixparameter{#1}{#2}{#3}\c!prefixconversion", conversionset = "\referencestructureprefixparameter{#1}{#2}{#3}\c!prefixconversionset", set = "\referencestructureprefixparameter{#1}{#2}{#3}\c!prefixset", segments = "\referencestructureprefixparameter{#1}{#2}{#3}\c!prefixsegments", connector = \!!bs\referencestructureprefixparameter{#1}{#2}{#3}\c!prefixconnector\!!es, }} \unexpanded\def\setupreferencestructureprefix {\dotripleempty\dosetupreferencestructureprefix} \def\dosetupreferencestructureprefix[#1][#2][#3]% {\ifthirdargument \getparameters[\??rf:\c!prefix:#1:#2][#3]% \else\ifsecondargument \getparameters[\??rf:\c!prefix::#1][#2]% \fi\fi} \def\referencestructureprefixparameter#1#2#3#4% kind name category parameter {\ifcsname\??rf:\c!prefix:#2:#3#4\endcsname \csname\??rf:\c!prefix:#2:#3#4\endcsname \else\ifcsname\??rf:\c!prefix:#1:#3#4\endcsname \csname\??rf:\c!prefix:#1:#3#4\endcsname \else\ifcsname\??rf:\c!prefix::#3#4\endcsname \csname\??rf:\c!prefix::#3#4\endcsname \fi\fi\fi} % \def\getreferencestructureprefixspec#1% we can save one call by moving this to the lua end % {\getreferencestructureprefix % {\ctxlua{structures.references.getcurrentmetadata("kind")}} % {\ctxlua{structures.references.getcurrentmetadata("name")}} % {#1}} % \def\currentreferencedefault % {\ctxlua{structures.references.filter("default",\getreferencestructureprefixspec\v!default)}} % % this is shortcut for: \def\currentreferencedefault {\ctxlua{structures.references.filter("default",\ctxlua{structures.references.getcurrentprefixspec("\v!default")})}} \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