%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{jobreferences.enhance("#1","#2")}}} \def\dofinishtextreference#1#2{\normalexpanded{\ctxlatelua{jobreferences.enhance("#1","#2",{})}}} \let\dofinishpagereference\dofinishfullreference \let\dofinishuserreference\dofinishfullreference \def\dodosetreference#1#2#3#4% kind labels userdata text -> todo: userdata {\ifreferencing \edef\currentreferencekind{#1}% \edef\currentreferencelabels{#2}% \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 jobreferences.set writes a % \setnextinternalreference \ctxlua{jobreferences.setandgetattribute("\currentreferencekind", "\referenceprefix","\currentreferencelabels", { references = { % internal = \nextinternalreference, % no need for an internal as we have an explicit block = "\currentstructureblock", section = structure.sections.currentid(), }, metadata = { kind = "#1", catcodes = \the\catcodetable, xmlroot = \ifx\currentreferencecoding\s!xml "\xmldocument" \else nil \fi, % only useful when text }, \ifx\currentreferencedata\empty\else entries = { text = \!!bs\currentreferencedata\!!es }, \fi userdata = structure.helpers.touserdata(\!!bs\detokenize{#3}\!!es) },"\@@iafocus") }% \xdef\currentdestinationattribute{\number\lastdestinationattribute}% \begingroup\attribute\destinationattribute\currentdestinationattribute\hbox{}\endgroup % todo \fi \fi} \def\defaultreferencepage#1{[[[#1]]]} \def\defaultreferencetext#1{[[[#1]]]} %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!systems{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{jobreferences.define("\referenceprefix","#1",\!!bs\detokenize{#2}\!!es)}} \def\resetreference[#1]% {\ctxlua{jobreferences.reset("\referenceprefix","#1")}} \def\setpagereference#1#2% name, specification {\ctxlua{jobreferences.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{jobreferences.expandcurrent()}\fi} \def\doifreferencefoundelse#1#2#3% {\ctxlua{jobreferences.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{jobreferences.analyse()}} %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\reportreferenceerror#1#2% only once (keep track in lua) {\ifinpagebody \else \doifconcepttracing{\doifsomething{#2}{\inleft{\infofont\doboundtext{#2}{\dimexpr\leftmarginwidth-2em\relax}{..}->}}}% \fi \showmessage\m!references{#1}{[\referenceprefix][#2]}} \def\unknownreference{\reportreferenceerror1} \def\illegalreference{\reportreferenceerror4} %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{jobreferences.setnextinternal("#1","#2")}} \def\getinternalorderreference#1#2% {\ctxlua{jobreferences.currentorder("#1","#2")}} \def\thisissomeinternal#1#2% tag reference (only for old time sake) {\begingroup\attribute\destinationattribute\ctxlua{jobreferences.mark("#1:#2")}\hbox{}\endgroup} \def\gotosomeinternal#1#2#3#4% {\ifinternalnamedreferences \directgoto{#4}[#1:#2]% \else \directgoto{#4}[page(#3)]% \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. \chardef\autocrossfilereferences=0 \unexpanded\def\setupreferencing {\dosingleargument\dosetupreferencing} \def\dosetupreferencing[#1]% {\getparameters [\??rf] [\c!prefix=\s!unknown,#1]% \processaction [\@@rfstate] [ \v!stop=>\referencingfalse, \v!start=>\referencingtrue]% \processaction [\@@rfinteraction] [ \v!all=>\let\dowantedreference\docompletereference, \v!label=>\let\dowantedreference\dolabelonlyreference, \v!text=>\let\dowantedreference\dotextonlyreference, \v!symbol=>\let\dowantedreference\dosymbolreference]% \chardef\autocrossfilereferences\zerocount \processaction [\@@rfautofile] [ \v!yes=>\chardef\autocrossfilereferences\plusone, \v!page=>\chardef\autocrossfilereferences\plustwo]% \chardef\referencefilecase\zerocount \processaction[\@@rfconvertfile] [ \v!yes=>\chardef\referencefilecase\plusone, \v!big=>\chardef\referencefilecase\plusone, \v!small=>\chardef\referencefilecase\plustwo]% \setupreferenceprefix[\@@rfprefix]% \doifelse\@@rfglobal\v!yes {\settrue \autoglobalfilereferences} {\setfalse\autoglobalfilereferences}} % \appendtoks\ctxlua{jobreferences.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{jobreferences.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} {\unknownreference{#2}\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{jobreferences.filter("number")}} \def\currentreferencepage {\ctxlua{jobreferences.filter("page")}} \def\currentreferencetitle {\ctxlua{jobreferences.filter("title")}} \def\currentreferencetext {\ctxlua{jobreferences.filter("text")}} \def\currentreferencedefault {\ctxlua{jobreferences.filter("default")}} \def\currentreferencerealpage{\ctxlua{jobreferences.realpage()}} \def\getreferenceentry#1{\ctxlua{jobreferences.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 analyses {\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 analyses {\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[\@@iasymbolset]% \symbol [\ifcase\referencepagestate \v!somewhere \or % same \v!nowhere \or % before \v!previous \or % after \v!next% \fi]}}} % \def\dosymbolreference#1#2[#3]% % {\removeunwantedspaces % \goto{\setupsymbolset[\@@iasymbolset]\high{\symbol % [\ifcase\referencepagestate % \v!somewhere % \or % same % \v!nowhere % \or % before % \v!previous % \or % after % \v!next% % \fi]}}[#3]} \def\dosymbolreference#1#2[#3]% {\removeunwantedspaces \goto{\referencesymbol}[#3]} \def\symbolreference[#1]% {\removeunwantedspaces \goto{\referencesymbol}[#1]} %D The other alternatives just conform their names: only the %D label, only the text, or the label and the text. \def\dounknownreference#1#2[#3]% {\unknownreference{#3}\dotextprefix{#2}\dummyreference}% \def\docompletereference#1#2[#3]% {\goto{\dotextprefix{#2}#1}[#3]} % \def\dolabelonlyreference#1#2[#3]% % {\doifsomespaceelse{#2}% space? % {\doifsomething{#2}{\goto{#2}[#3]}} % {\goto{\dotextprefix{#2}}[#3]}} \def\dolabelonlyreference#1#2[#3]% {\goto{\dotextprefix{#2}}[#3]} \def\dotextonlyreference#1#2[#3]% {\dotextprefix{#2}\goto{#1}[#3]} \let\dowantedreference\docompletereference %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 [more documentation will be added] %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}. % todo: inherit; probably not yet mkiv okay \unexpanded\def\definereferenceformat {\dodoubleargument\dodefinereferenceformat} \def\dodefinereferenceformat[#1][#2]% {\iffirstargument \getparameters[\??rf#1] [\c!left=, % of the number \c!right=, % of the number \c!text=, % before the number \c!label=, % can be {left}{right} \c!command=\in, #2]% \setuvalue{#1}% {\dontleavehmode\doexecutereferenceformat{#1}}% \fi} \def\noexecutelabelreferenceformat#1% {\doifvaluesomething{\??rf#1\c!text}{\gdef\textofreference{\csname\??rf#1\c!text\endcsname}}% \csname\??rf#1\c!command\endcsname} \def\doexecutelabelreferenceformat#1% {\csname\??rf#1\c!command\endcsname {\leftlabeltext {\csname\??rf#1\c!label\endcsname}}% {\rightlabeltext{\csname\??rf#1\c!label\endcsname}}} \def\doexecutereferenceformat#1% {\gdef\leftofreference {\csname\??rf#1\c!left \endcsname}% \gdef\rightofreference{\csname\??rf#1\c!right\endcsname}% \global\let\textofreference\empty % otherwise ~ added \doifelsevaluenothing{\??rf#1\c!label}\noexecutelabelreferenceformat\doexecutelabelreferenceformat{#1}} \let\leftofreference \relax \let\rightofreference\relax \let\textofreference \relax % fails on metafun {\leftofreference#1\ignorespaces#3\removeunwantedspaces\rightofreference}{#2}[#4]% % % \def\dodododoinatreference#1#2#3[#4]% no \removeunwantedspaces (fails on metafun) % {\ifx\next\bgroup % \dododododoinatreference{\leftofreference#1\ignorespaces#3\rightofreference}{#2}[#4]% % \else % \dododododoinatreference{\leftofreference#1\rightofreference}{#2#3}[#4]% % \fi} % % \def\dododododoinatreference#1#2[#3]% % {\dontleavehmode % replaces \leaveoutervmode % \begingroup % \postponenotes % \doifreferencefoundelse{#3} % {\doifelsenothing{#1}\dosymbolreference\dowantedreference{#1}{#2}[#3]}% % {\dounknownreference{#1}{#2}[#3]}% % \endgroup} % \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 \unexpanded\def\dospecialin{\let\currentreferencecontent\currentreferencedefault\doinatreference} \unexpanded\def\dospecialat{\let\currentreferencecontent\currentreferencepage \doinatreference} \newtoks\leftreferencetoks \newtoks\rightreferencetoks \def\doinatreference {\futurelet\next\doinatreferenceone} \def\doinatreferenceone {\ifx\next\bgroup \afterassignment\doinatreferenceonetwo \expandafter\leftreferencetoks \else \leftreferencetoks\emptytoks \expandafter\dodoinatreferencenone \fi} \def\doinatreferenceonetwo {\futurelet\next\doinatreferencetwo} \def\doinatreferencetwo {\ifx\next\bgroup \afterassignment\dodoinatreferenceboth \expandafter\rightreferencetoks \else \rightreferencetoks\emptytoks \expandafter\dodoinatreferenceleft \fi} \def\dodoinatreferencenone {\dodoinatreferenceindeed {\leftofreference\currentreferencecontent\rightofreference} {}} \def\dodoinatreferenceleft {\dodoinatreferenceindeed {\leftofreference\currentreferencecontent\rightofreference} {\the\leftreferencetoks}} \def\dodoinatreferenceboth {\dodoinatreferenceindeed {\leftofreference\currentreferencecontent\the\rightreferencetoks\rightofreference} {\the\leftreferencetoks}} \def\dodoinatreferenceindeed#1#2#3[#4]% #3 gobbles space {\dontleavehmode % replaces \leaveoutervmode \begingroup \postponenotes \doifreferencefoundelse{#4} {\doifelsenothing{#1}\dosymbolreference\dowantedreference{#1}{#2}[#4]}% {\dounknownreference{#1}{#2}[#4]}% \endgroup} \let\dosymbolreference\dowantedreference %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. \newbox\referencebox \def\dodirectgoto#1[#2]% no test for valid references {\dontleavehmode \begingroup \attribute\referenceattribute\attributeunsetvalue \iflocation \ctxlua{jobreferences.inject("\referenceprefix","#2",\number\ht\strutbox,\number\dp\strutbox,\extrareferencearguments)}% \setlocationattributes\??ia \setstrut % can be option \attribute\referenceattribute\lastreferenceattribute \fi #1% \endgroup} \def\dodirectgotohtdp#1[#2]% no test for valid references {\dontleavehmode \begingroup \attribute\referenceattribute\attributeunsetvalue \iflocation \ctxlua{jobreferences.inject("\referenceprefix","#2",\number\dimexpr\@@iaheight\relax,\number\dimexpr\@@iadepth\relax,\extrareferencearguments)}% \setlocationattributes\??ia \attribute\referenceattribute\lastreferenceattribute \fi #1% \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 \attribute\referenceattribute\attributeunsetvalue \iflocation \ctxlua{jobreferences.doifelse("\referenceprefix","#3",\extrareferencearguments)}% {\expandtexincurrentreference \ctxlua{jobreferences.injectcurrentset(\number\ht\strutbox,\number\dp\strutbox)}% \setlocationattributes\??ia \setstrut % can be option \attribute\referenceattribute\lastreferenceattribute}% {\unknownreference{#3}}% \fi #1% %\egroup\unhbox\referencebox} \endgroup} \def\dogotohtdp#1#2[#3]% #2 gobbles spaces after #1 so that \goto{xx} [yy] works ok {\dontleavehmode \begingroup \attribute\referenceattribute\attributeunsetvalue \iflocation \ctxlua{jobreferences.doifelse("\referenceprefix","#3",\extrareferencearguments)}% {\expandtexincurrentreference \ctxlua{jobreferences.injectcurrentset(\number\dimexpr\@@iaheight\relax,\number\dimexpr\@@iadepth\relax)}% \setlocationattributes\??ia \attribute\referenceattribute\lastreferenceattribute}% {\unknownreference{#3}}% \fi #1% \endgroup} \unexpanded\def\directgotobox#1[#2]% no test for valid references {\dontleavehmode \begingroup \attribute\referenceattribute\attributeunsetvalue \iflocation \ctxlua{jobreferences.inject("\referenceprefix","#2",nil,nil,\extrareferencearguments)}% \setlocationattributes\??ia \hbox attr \referenceattribute \lastreferenceattribute {#1}% \else #1% \fi \endgroup} \unexpanded\def\directgotospecbox#1#2[#3]% no test for valid references {\dontleavehmode \begingroup \attribute\referenceattribute\attributeunsetvalue \iflocation \ctxlua{jobreferences.inject("\referenceprefix","#3",nil,nil,\extrareferencearguments)}% \setlocationcolorspec{#1}% no consequence for strut \hbox attr \referenceattribute \lastreferenceattribute {#2}% \else #2% \fi \endgroup} \unexpanded\def\directgotodumbbox#1[#2]% no test for valid references {\dontleavehmode \begingroup \attribute\referenceattribute\attributeunsetvalue \iflocation \ctxlua{jobreferences.inject("\referenceprefix","#2",nil,nil,\extrareferencearguments)}% \hbox attr \referenceattribute \lastreferenceattribute {#1}% \else #1% \fi \endgroup} \unexpanded\def\gotobox#1[#2]% no test for valid references {\dontleavehmode \begingroup \attribute\referenceattribute\attributeunsetvalue \iflocation \ctxlua{jobreferences.doifelse("\referenceprefix","#2",\extrareferencearguments)}% {\expandtexincurrentreference \ctxlua{jobreferences.injectcurrentset(nil,nil)}% \setlocationattributes\??ia \hbox attr \referenceattribute \lastreferenceattribute {#1}}% {\unknownreference{#2}}% \else #1% \fi \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{jobreferences.urls.define("#1",\!!bs\detokenize{#2}\!!es,\!!bs\detokenize{#3}\!!es,\!!bs\detokenize{#4}\!!es)}} \def\dousefile[#1][#2][#3]% {\ctxlua{jobreferences.files.define("#1",\!!bs\detokenize{#2}\!!es,\!!bs\detokenize{#3}\!!es)}} \def\doifurldefinedelse #1{\ctxlua{commands.doifurldefinedelse ("#1")}} \def\doiffiledefinedelse#1{\ctxlua{commands.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{jobreferences.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{jobreferences.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{jobreferences.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{jobreferences.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. \newif\ifautocrossdocument \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 Buttons are just what their names says: things that can be %D clicked (pushed) on. They are similar to \type{\goto}, %D except that the text argument is not interpreted. %D Furthermore one can apply anything to them that can be done %D with \type{\framed}. %D %D \startbuffer %D \button[width=3cm,height=1.5cm]{Exit}[ExitViewer] %D \stopbuffer %D %D \typebuffer %D %D gives %D %D \getbuffer %D %D This command is formally specified as: %D %D \showsetup{button} %D %D The characteristics can be set with: %D %D \showsetup{setupbuttons} \unexpanded\def\setupbuttons {\dodoubleargument\getparameters[\??bt]} \definecomplexorsimpleempty\button \def\complexbutton {\docomplexbutton\??bt} \presetlocalframed[\??bt] \long\def\docomplexbutton#1[#2]#3#4% get rid of possible space before [#4] {\dodocomplexbutton#1[#2]{#3}#4} % #4 == [ \def\buttonframed{\dodoubleempty\localframed[\??bt]} % goodie \long\def\dodocomplexbutton#1[#2]#3[#4]% #3 can contain [] -> {#3} later {\begingroup \doifvalue{#1\c!state}\v!stop\locationfalse \iflocation \ConvertConstantAfter\doifelse{#3}\v!none\hphantom\hbox {\doifelsenothing{#4} {\setlocationboxnop#1[#2]{#3}[#4]} {\doifreferencefoundelse{#4} % INEFFICIENT {\setlocationboxyes#1[#2]{#3}[#4]} {\unknownreference{#4}% \setlocationboxnop#1[#2]{#3}[#4]}}}% \fi \endgroup} \setupbuttons [\c!state=\v!start] %D Interaction buttons, in fact a row of tiny buttons, are %D typically only used for navigational purposed. The next %D macro builds such a row based on a specification list. %D %D \startbuffer %D \interactionbuttons %D [width=\hsize][page,PreviousJump,ExitViewer] %D \stopbuffer %D %D \typebuffer %D %D gives %D %D \getbuffer %D %D Apart from individual entries, one can use \type{page} and %D \type {subpage} as shortcuts to their four associated buttons. %D The symbols are derived from the symbols linked to the %D entries. % does not work well with for instance SomeRef{whatever} \def\interactionbuttons {\dodoubleempty\dointeractionbuttons} \def\dointeractionbuttons[#1][#2]% er is een verdeel macro \horizontalfractions {\iflocation % BUG: fails when frame=off; best is to rewrite this macro \bgroup \doif\@@ibstate\v!stop\locationfalse \iflocation \ifsecondargument \setupinteractionbar[#1]% \checkinteractionbar{1.5em}\v!broad\!!zeropoint % brrrrr \setbox2\hbox{\localframed[\??ib][\c!background=]{\symbol[\@@iasymbolset][\v!previouspage]}}% \!!heighta\ht2 % needed because we default to nothing \setupinteractionbar[\c!strut=\v!no]% \setinteractionparameter\c!width\!!zeropoint \!!counta\zerocount % new, was 1 \processallactionsinset [#2] [ \v!page=>\advance\!!counta 4, \v!subpage=>\advance\!!counta 4, \s!unknown=>\advance\!!counta 1]% \ifdim\@@ibwidth=\zeropoint \!!widtha2em \advance\!!widtha \@@ibdistance % new \!!widthb\!!counta\!!widtha \advance\!!widthb -\@@ibdistance % new \else \!!widtha\@@ibwidth \!!widthb\@@ibdistance % new \multiply\!!widthb \!!counta % new \advance\!!widthb -\@@ibdistance % new \advance\!!widtha -\!!widthb % new \divide\!!widtha \!!counta \!!widthb\@@ibwidth \fi \def\xgoto##1% clash ? {\setnostrut \edef\localreference{##1}% \normalexpanded{\noexpand\dodocomplexbutton\??ib[\c!height=\the\!!heighta,\c!width=\the\!!widtha]}% {\dontleavehmode\symbol[\@@iasymbolset][\localreference]}% [\localreference]% \hss}% \hbox to \!!widthb {\processallactionsinset [#2] [ \v!page=>\xgoto\v!firstpage \xgoto\v!nextpage \xgoto\v!previouspage \xgoto\v!lastpage, \v!subpage=>\xgoto\v!firstsubpage \xgoto\v!nextsubpage \xgoto\v!previoussubpage \xgoto\v!lastsubpage, \s!unknown=>\xgoto\commalistelement]% \unskip}% \else \interactionbuttons[][#1]% \fi \fi \egroup \fi} %D \macros %D {overlaybutton} %D %D For converience we provide: %D %D \starttyping %D \overlaybutton[reference] %D \stoptyping %D %D This command can be used to define overlays an/or can be %D used in the whatevertext areas, like: %D %D \starttyping %D \defineoverlay[PrevPage][\overlaybutton{PrevPage}] %D \setupbackgrounds[page][background=PrevPage] %D \setuptexttexts[\overlaybutton{NextPage}] %D \stoptyping %D %D For practical reasons, this macro accepts square brackets %D as well as braces. \definecomplexorsimple\overlaybutton \def\simpleoverlaybutton#1% {\complexoverlaybutton[#1]} \def\complexoverlaybutton[#1]% {\iflocation \gotobox{\overlayfakebox}[#1]% \fi} \def\overlayfakebox {\hbox {\setbox\scratchbox\null \wd\scratchbox\overlaywidth \ht\scratchbox\overlayheight \box\scratchbox}} %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!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!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{jobreferences.get_current_metadata("kind")}} % {\ctxlua{jobreferences.get_current_metadata("name")}} % {#1}} % \def\currentreferencedefault % {\ctxlua{jobreferences.filter("default",\getreferencestructureprefixspec\v!default)}} % % this is shortcut for: \def\currentreferencedefault {\ctxlua{jobreferences.filter("default",\ctxlua{jobreferences.get_current_prefixspec("\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