summaryrefslogtreecommitdiff
path: root/tex/context/base/scrn-fld.mkiv
diff options
context:
space:
mode:
Diffstat (limited to 'tex/context/base/scrn-fld.mkiv')
-rw-r--r--tex/context/base/scrn-fld.mkiv686
1 files changed, 686 insertions, 0 deletions
diff --git a/tex/context/base/scrn-fld.mkiv b/tex/context/base/scrn-fld.mkiv
new file mode 100644
index 000000000..f895089e8
--- /dev/null
+++ b/tex/context/base/scrn-fld.mkiv
@@ -0,0 +1,686 @@
+%D \module
+%D [ file=scrn-fld,
+%D version=1997.05.18,
+%D title=\CONTEXT\ Screen Macros,
+%D subtitle=Fields,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Screen Macros / Fields}
+
+\unprotect
+
+%D First we hook fields into the (viewer based) layering mechanism
+%D (implemented as properties).
+
+\appendtoks
+ \doif\@@iafieldlayer\v!auto{\def\@@iafieldlayer{\currentviewerlayer}}%
+\to \everysetupinteraction
+
+\setupinteraction
+ [\c!fieldlayer=\v!auto] % auto by default
+
+%D \starttyping
+%D \definefield [name] [type] [group] [values] [default]
+%D
+%D \definefield [WWWW] [text] [textsetup] [default text]
+%D \definefield [XXXX] [push] [pushsetup] [yes,no] [yes]
+%D \definefield [XXXX] [check] [checksetup] [yes,no] [yes]
+%D \definefield [YYYY] [combo] [combosetup] [a,b,c,d] [b]
+%D \definefield [ZZZZ] [radio] [radiosetup] [W,X,Y,Z] [Y]
+%D
+%D \definesubfield [W] [subsetup] [p,q]
+%D \definesubfield [X,Y] [subsetup] [p,r]
+%D \definesubfield [Z] [subsetup] [y,z]
+%D
+%D evt \definemainfield ... wanneer geplaatst voor subs gegeven
+%D
+%D \clonefield [XXXX] [XX,YY] [mysetup] [on,off]
+%D \clonefield [Z] [AA,BB] [somesetup] [true,false]
+%D \clonefield [Z] [CC,DD] [anothersetup]
+%D
+%D \copyfield [XXXX] [PP,QQ,RR]
+%D
+%D \field[XXXX]
+%D \fitfield[XXXX]
+%D \stoptyping
+
+%D Internal command, linked to \type{\definesymbol}.
+
+\def\dogetfieldsymbol#1%
+ {\getobject{SYM}{#1}}
+
+\def\dopresetfieldsymbol#1%
+ {\doifobjectfoundelse{SYM}{#1}
+ {}
+ {\settightobject{SYM}{#1}\hbox{\symbol[#1]}%
+ \flushatshipout
+ {\setbox0\hbox{\hskip-\maxdimen\getobject{SYM}{#1}}%
+ \smashbox0\box0}}}
+
+\def\presetfieldsymbols[#1]% slow
+ {\def\dopresetfieldsymbols##1{\processcommalist[##1]\dopresetfieldsymbol}%
+ \@EA\processcommalist\@EA[#1]\dopresetfieldsymbols}
+
+\unexpanded\def\definedefaultsymbols
+ {\definesymbol[defaultyes][\mathematics{\times}]%
+ \definesymbol[defaultno ][\mathematics{\cdot }]}
+
+\def\resetfieldsymbol[#1]% for experimental usage only
+ {\resetobject{SYM}{#1}}
+
+%D The interface to the specials. DEFAULT NOG ANDERS
+
+\def\typesetfield
+ {\bgroup
+ \dosetfontattribute\??fd\c!style
+ \ctxlua{backends.codeinjections.typesetfield("\currentfieldname", {
+ title = "\currentfieldname",
+ width = \number\dimexpr\@@fdwidth\relax,
+ height = \number\dimexpr\@@fdheight\relax,
+ align = "\@@fdalign",
+ length = tonumber("\@@fdn") or 0,
+ style = "\@@fdstyle",
+ fontstyle = "\fontstyle",
+ fontalternative = "\fontalternative",
+ fontsize = "\currentfontbodysize",
+ color = "\@@fdcolor",
+ backgroundcolor = "\@@fdfieldbackgroundcolor",
+ framecolor = "\@@fdfieldframecolor",
+ layer = "\@@fdfieldlayer",
+ options = "\@@fdoption",
+ align = "\@@fdalign",
+ clickin = "\@@fdclickin",
+ clickout = "\@@fdclickout",
+ regionin = "\@@fdregionin",
+ regionout = "\@@fdregionout",
+ afterkey = "\@@fdafterkey",
+ format = "\@@fdformat",
+ validate = "\@@fdvalidate",
+ calculate = "\@@fdcalculate",
+ focusin = "\@@fdfocusin",
+ focusout = "\@@fdfocusout",
+ }) }%
+ \egroup}
+
+\unexpanded\def\definefieldset {\dodoubleargument\dodefinefieldset}
+\unexpanded\def\definefield {\doquintupleempty\dodefinefield}
+\unexpanded\def\definemainfield{\doquintupleempty\dodefinefield} % redundant
+\unexpanded\def\definesubfield {\dotripleempty \dodefinesubfield}
+\unexpanded\def\clonefield {\doquadrupleempty\doclonefield}
+\unexpanded\def\copyfield {\dodoubleempty \docopyfield}
+\unexpanded\def\field {\dodoubleempty \donormalfield}
+\unexpanded\def\fitfield {\dodoubleempty \dofitfield}
+\unexpanded\def\setupfield {\doquintupleempty\dosetupfield}
+\unexpanded\def\setupfields {\doquadrupleempty\dosetupfields}
+
+% misc
+
+% \appendtoks\ctxlua{backends.codeinjections.finishfields()}\to\everylastshipout
+
+% testing
+
+\def\doiffieldelse #1{\ctxlua{backends.codeinjections.doiffieldelse("#1")}}
+\def\doiffieldgroupelse#1{\ctxlua{backends.codeinjections.doiffieldgroupelse("#1")}}
+
+% definition
+
+\def\dodefinefield[#1][#2][#3][#4][#5]% [name] [kind] [group] [values] [default] | [name] [kind] [group] [default]
+ {\ctxlua{backends.codeinjections.definefield{ variant="normal", name="#1", kind="#2", group="#3", values=\!!bs#4\!!es, default=\!!bs#5\!!es }}}
+
+\def\dodefinesubfield[#1][#2][#3]% [name] [group] [values]
+ {\ctxlua{backends.codeinjections.definefield{ variant="normal", name="#1", kind="sub", group="#2", values=\!!bs#3\!!es }}}
+
+\def\doclonefield[#1][#2][#3][#4]% [parent] [children] [group] [values]
+ {\ctxlua{backends.codeinjections.clonefield{ variant="clone", parent="#1", children="#2", group="#3", values=\!!bs#4\!!es }}}
+
+\def\docopyfield[#1][#2]% [parent] [children]
+ {\ctxlua{backends.codeinjections.clonefield{ variant="copy", parent="#1", children="#2" }}}
+
+\def\dodefinefieldset[#1][#2]%
+ {\ctxlua{backends.codeinjections.definefieldset("#1","#2")}}
+
+% usage
+%
+% \iftrialtypesetting
+%
+% just a default setup
+
+\def\loadfieldscripts{\useJSscripts[fld]\globallet\loadfieldscripts\relax}
+
+\def\donormalfield{\doprocessfield\dohandlefield}
+\def\dofitfield {\doprocessfield\dohandlefitfield}
+
+\def\dosetupfieldindeed#1#2[#3]% [#4][#5][#6][#7]%
+ {#1[#2]} % [#4][#5][#6][#7]}
+
+\def\doprocessfield#1[#2][#3]% \method [name] [label]
+ {\dontleavehmode
+ \begingroup
+ \loadfieldscripts
+ \edef\currentfieldname {#2}%
+ \edef\currentfieldlabel{#3}%
+ \edef\currentfieldgroup{\ctxlua{backends.codeinjections.getfieldgroup("#2")}}%
+ \ifx\currentfieldlabel\empty
+ \let\currentfieldlabel\currentfieldname
+ \fi
+ \ifx\currentfieldgroup\empty
+ #1[#2][\v!label,\v!frame,\v!horizontal][][][]%
+ \else
+ \def\dosetupfield{\dosetupfieldindeed{#1}{#2}}%
+ \getvalue{\??fd::\currentfieldgroup}%
+ \fi
+ \endgroup}
+
+% setups
+
+\def\dosetupfield[#1][#2][#3][#4][#5]%
+ {\iffifthargument
+ \def\docommand##1{\dodosetupfield[##1][#2][#3][#4][#5]}%
+ \processcommalist[#1]\docommand
+ \else\ifthirdargument
+ \def\docommand##1{\dodosetupfield[##1][#2][][][#3]}%
+ \processcommalist[#1]\docommand
+ \else\ifsecondargument
+ \doifelse{#2}\v!reset
+ {\def\docommand##1{\donosetupfield[#1][][][][]}}
+ {\def\docommand##1{\dodosetupfield[##1][][][][#2]}}%
+ \processcommalist[#1]\docommand
+ \else\iffirstargument
+ \def\docommand##1{\dodosetupfield[##1][][][][]}%
+ \processcommalist[#1]\docommand
+ \else
+ \writestatus\m!fields{provide either 1, 2, 3 or 5 arguments}%
+ \fi\fi\fi\fi}
+
+\def\normaldodosetupfield[#1][#2][#3][#4][#5]%
+ {\ifcsname\??fd::#1\endcsname
+ \pushmacro\dosetupfield
+ \def\dosetupfield[##1][##2][##3][##4][##5]{\setvalue{\??fd::#1}{\dosetupfield[#1][##2,#2][##3,#3][##4,#4][##5,#5]}}%
+ \getvalue{\??fd::#1}%
+ \popmacro\dosetupfield
+ \else
+ \setvalue{\??fd::#1}{\dosetupfield[#1][#2][#3][#4][#5]}%
+ \fi}
+
+\let\dodosetupfield\normaldodosetupfield
+
+\def\donosetupfield[#1][#2][#3][#4][#5]%
+ {\setvalue{\??fd::#1}{\dosetupfield[#1][#2][#3][#4][#5]}}
+
+\def\dosetupfields[#1][#2][#3][#4]%
+ {\ifsecondargument
+ \def\dodosetupfield[##1][##2][##3][##4][##5]%
+ {\ifcsname\??fd::##1\endcsname
+ \def\dosetupfield[####1][####2][####3][####4][####5]%
+ {\setvalue{\??fd::##1}{\dosetupfield[##1][#1,####2,##2][#2,####3,##3][#3,####4,##4][#4,####5,##5]}}%
+ \getvalue{\??fd::##1}%
+ \else
+ \setvalue{\??fd::##1}{\dosetupfield[##1][#1,##2][#2,##3][#3,##4][#4,##5]}%
+ \fi}%
+ \else\iffirstargument
+ \doifelse{#1}\v!reset
+ {\resetfields}
+ {\setupfields[][][][#1]}% checken
+ \else
+ \writestatus\m!fields{provide either 1 or 4 arguments}%
+ \fi\fi}
+
+\def\resetfields
+ {\let\dodosetupfield\normaldodosetupfield}
+
+% \setupfields[\v!reset]
+
+% opties: veld, label, kader, vertikaal/horizontaal
+
+\newif\ifShowFieldLabel
+\newif\ifShowFieldFrame
+\newif\ifVerticalField
+\newif\ifHorizontalField
+
+% way to slow/complicated, we need some simple alternative
+% as well
+
+\def\dohandlefield[#1][#2][#3][#4][#5]%
+ {\presetlocalframed[\??fd]%
+ \processallactionsinset
+ [#2]
+ [ \v!reset=>\ShowFieldLabelfalse\ShowFieldFramefalse\HorizontalFieldfalse\VerticalFieldfalse,
+ \v!label=>\ShowFieldLabeltrue,
+ \v!frame=>\ShowFieldFrametrue,
+ \v!horizontal=>\HorizontalFieldtrue,
+ \v!vertical=>\VerticalFieldtrue]%
+ \ifVerticalField
+ \getparameters[\??fd][\c!distance=\zeropoint,\c!inbetween=\vskip\@@localoffset,\c!align=\v!right,\c!width=20em]%
+ \else\ifHorizontalField
+ \getparameters[\??fd][\c!distance=\@@localoffset,\c!inbetween=,\c!align=\c!left,\c!height=10ex]%
+ \else
+ \getparameters[\??fd][\c!distance=\zeropoint,\c!inbetween=,\c!align=\c!left]%
+ \fi\fi
+ \getparameters[\??fd][\c!n=,\c!before=,\c!after=\vss,\c!style=,\c!color=,#3]%
+ \ifShowFieldFrame
+ \localframed[\??fd][\c!strut=\v!no,\c!align=]\bgroup
+ \else
+ \vbox\bgroup
+ \fi
+ \dontcomplain
+ \ifShowFieldLabel
+ \setbox0\hbox
+ {\reshapeframeboxtrue % else wrong dimensions
+ \framed
+ [\c!style=,\c!color=,\c!align=\c!right,#4]
+ {\currentfieldlabel}}%
+ \fi
+ \setbox2\hbox
+ {\reshapeframeboxtrue % else wrong dimensions
+ \ifVerticalField
+ \setupframed[\c!height=6ex,\c!width=\hsize]%
+ \else\ifHorizontalField
+ \setupframed[\c!height=\vsize,\c!width=20em]%
+ \else
+ \setupframed[\c!height=2cm,\c!width=2cm]%
+ \fi\fi
+ \framed
+ [\c!align=\v!right,\c!strut=\v!no,#5]
+ {\getparameters
+ [\??fd]
+ [\c!color=,\c!style=,\c!align=\v!right,\c!option=,
+ \c!clickin=,\c!clickout=,\c!regionin=,\c!regionout=,
+ \c!afterkey=,\c!format=,\c!validate=,\c!calculate=,
+ \c!focusin=,\c!focusout=,
+ \c!fieldoffset=-\framedoffset,\c!fieldbackgroundcolor=,
+ \c!fieldframecolor=,\c!fieldlayer=\@@iafieldlayer,#5]%
+ \scratchdimen\framedwidth \edef\@@fdwidth {\the\scratchdimen}%
+ \scratchdimen\framedheight\edef\@@fdheight{\the\scratchdimen}%
+ \vfill
+ \hbox{\lower\@@fdfieldoffset\hbox{\typesetfield}}
+ \vss}}%
+ \ifShowFieldLabel
+ \ifVerticalField
+ \vbox
+ {\copy0
+ \@@fdinbetween
+ \copy2}%
+ \else
+ \hbox
+ {\vbox \ifdim\ht2>\ht0 to \ht2 \fi
+ {\@@fdbefore
+ \copy0
+ \@@fdafter}%
+ \hskip\@@fddistance
+ \vbox \ifdim\ht0>\ht2 to \ht0 \fi
+ {\@@fdbefore
+ \box2
+ \@@fdafter}}%
+ \fi
+ \else
+ \box2
+ \fi
+ \egroup}
+
+\chardef\fitfieldmode\plusone % 3 = best
+
+\def\dohandlefitfield[#1][#2][#3][#4][#5]% alleen check
+ {\presetlocalframed[\??fd]%
+ \localframed
+ [\??fd]
+ [\c!n=1024, % beware: weblink plug in truncates
+ \c!strut=\v!no,\c!color=,\c!style=,\c!option=,
+ \c!clickin=,\c!clickout=,\c!regionin=,\c!regionout=,
+ \c!focusin=,\c!focusout=,
+ \c!afterkey=,\c!format=,\c!validate=,\c!calculate=,
+ \c!fieldoffset=\zeropoint,\c!fieldbackgroundcolor=,
+ \c!fieldframecolor=,\c!fieldlayer=\@@iafieldlayer,#5,\c!align=]
+ {\edef\defaultfield{\ctxlua{backends.codeinjections.getdefaultfieldvalue("#1")}}%
+ % \dopresetsymbol\defaultfield
+ \setbox\scratchbox\hbox{\symbol[\defaultfield]}%
+ \edef\@@fdwidth {\the\wd\scratchbox}%
+ \ifcase\fitfieldmode
+ \edef\@@fdheight{\the\ht\scratchbox}%
+ \typesetfield
+ \or % 1 = ignore depth (original, assumed no depth, actually a bug)
+ \edef\@@fdheight{\the\ht\scratchbox}%
+ \vbox to \ht\scratchbox{\vfill\hbox to \wd\scratchbox{\typesetfield\hfill}\vss}%
+ \or % 2 = add depth to height, but no depth in result
+ \edef\@@fdheight{\the\htdp\scratchbox}%
+ \vbox to \ht\scratchbox{\vfill\hbox to \wd\scratchbox{\typesetfield\hfill}\vss}%
+ \or % 3 = add depth to height, and apply depth to result
+ \edef\@@fdheight{\the\htdp\scratchbox}%
+ \hbox to \wd\scratchbox{\lower\dp\scratchbox\hbox{\typesetfield}\hfill}%
+ \fi}}
+
+%D Common stuff
+
+\newcount\nofsystemfields
+
+\def\nextsystemfield
+ {\global\advance\nofsystemfields\plusone
+ \def\currentsystemfield{sys::\number\nofsystemfields}}
+
+%D An example:
+
+\def\fillinfield
+ {\dosingleempty\dofillinfield}
+
+\def\dofillinfield[#1]#2%
+ {\dontleavehmode
+ \hbox
+ {\forgetall
+ \setupfields[\v!reset]%
+ \nextsystemfield
+ \useJSscripts[ans]%
+ \doifelsenothing{#1}
+ {\def\therightanswer{#2}}
+ {\def\therightanswer{#1}}%
+ \setbox0\hbox{#2}%
+ \setbox2\hbox{\therightanswer}%
+ \dimen0=\ifdim\wd0>\wd2 \wd0 \else \wd2 \fi
+ \advance\dimen0 .2em
+ \definefield
+ [\currentsystemfield][line][systemfield]%
+ \setupfield
+ [systemfield]
+ [\c!n=1024, % beware: weblink plugin truncates
+ \c!location=\v!low,\c!strut=\v!yes,\c!fieldoffset=\zeropoint,
+ \c!height=1.2\openlineheight,\c!width=\dimen0,\c!offset=\v!overlay,
+ \c!style=,\c!align=\v!middle,\c!frame=\v!off,
+ \c!color=red,\c!fieldbackgroundcolor=\s!white,\c!fieldframecolor=blue,
+ \c!validate=JS(Check_Answer{\currentsystemfield,\therightanswer})]%
+ \switchtobodyfont
+ [\c!small]%
+ \hbox to \wd0
+ {\copy0\hskip-\wd0\hss\field[\currentsystemfield]\hss}}}
+
+%D and another one:
+
+\def\tooltip
+ {\dosingleempty\dotooltip}
+
+\def\dotooltip[#1]#2#3%
+ {\dontleavehmode
+ \begingroup
+ \setupfields[\v!reset]%
+ \useJSscripts[fld]%
+ \setbox0\hbox
+ {\dontcomplain
+ \nextsystemfield
+ \setbox0\hbox{#2}%
+ \definesymbol
+ [\currentsystemfield:txt]
+ [{\inframed[\c!frame=\v!off,\c!background=\v!screen]{#3}}]%
+ \setbox2\hbox{\symbol[\currentsystemfield:txt]}%
+ \definefield
+ [\currentsystemfield:txt][check]
+ [dummy][\currentsystemfield:txt][\currentsystemfield:txt]%
+ \setupfield
+ [dummy]
+ [\c!frame=\v!off,
+ \c!regionout=JS(Hide_Field{\currentsystemfield:txt}),
+ \c!option=\v!hidden]%
+ \hbox to \zeropoint
+ {\dimen0\wd2\advance\dimen0 -\wd0
+ \doifelse{#1}\v!left
+ {\hskip-\dimen0}
+ {\doif{#1}\v!middle
+ {\hskip-.5\dimen0}}%
+ \lower\openlineheight\hbox to \zeropoint
+ {\fitfield[\currentsystemfield:txt]}}%
+ \dimen0=\ifdim\wd0=\zeropoint 3em\else\wd0\fi
+ \definesymbol
+ [\currentsystemfield:but]
+ [{\framed[\c!height=2ex,\c!width=\dimen0,\c!frame=\v!off]{}}]%
+ \definefield
+ [\currentsystemfield:but][push]
+ [dummy][\currentsystemfield:but][\currentsystemfield:but]%
+ \setupfield
+ [dummy]
+ [\c!frame=\v!off,
+ \c!option=,
+ \c!regionin=JS(Vide_Field{\currentsystemfield:txt}),
+ \c!regionout=JS(Hide_Field{\currentsystemfield:txt}),
+ \c!fieldlayer=\@@iafieldlayer]%
+ \lower2ex\hbox to \zeropoint
+ {\fitfield[\currentsystemfield:but]}%
+ #2}%
+ \ht0\strutht\dp0\strutdp\box0
+ \endgroup}
+
+%D And one more:
+
+\unexpanded\def\definefieldstack
+ {\dotripleargument\dodefinefieldstack}
+
+\def\dodefinefieldstack[#1][#2][#3]% name, symbols, settings
+ {\ifcsname fieldstack:#1\endcsname \else
+ \setgvalue{fieldstack:#1}{\dodofieldstack[#1][#2][#3]}%
+ \fi}
+
+\def\fieldstack
+ {\dotripleempty\dofieldstack}
+
+\def\dofieldstack[#1][#2][#3]%
+ {\ifsecondargument
+ \dodefinefieldstack[#1][#2][#3]\fieldstack[#1]%
+ \else
+ \getvalue {fieldstack:#1}%
+ \setgvalue{fieldstack:#1}{[#1]}%
+ \fi}
+
+\def\dodofieldstack[#1][#2][#3]% start=n, 0 == leeg
+ {\dontleavehmode
+ \begingroup
+ \getparameters[\??fd][\c!start=1,#3]%
+ \setupfields[\v!reset]%
+ % \definesymbol[\v!empty][]%
+ \useJSscripts[fld][FieldStack]%
+ \newcounter\stackedfieldnumber
+ \def\dododofieldstack##1%
+ {\increment\stackedfieldnumber
+ \ifnum\stackedfieldnumber=\@@fdstart\relax
+ \definefield[#1:\stackedfieldnumber][check][#1][##1,\empty][##1]% \v!empty fails
+ \else
+ \definefield[#1:\stackedfieldnumber][check][#1][##1,\empty][\empty]% \v!empty fails
+ \fi}%
+ \processcommalist[#2]\dododofieldstack
+ \setupfield[#1][\v!reset]% added
+ \setupfield[#1][\c!option=\v!readonly,#3]% #3 swapped
+ \newcounter\stackedfieldnumber
+ \def\dododofieldstack##1%
+ {\doglobal\increment\stackedfieldnumber
+ \fitfield[#1:\stackedfieldnumber]\egroup\bgroup}%
+ \startoverlay
+ \bgroup
+ \globalprocesscommalist[#2]\dododofieldstack
+ \egroup
+ \stopoverlay
+ \endgroup}
+
+%D When submitting a form, we need to tell the driver module
+%D that we want \FDF\ or \HTML.
+
+\newtoks\everysetupforms
+
+\unexpanded\def\setupforms{\dosingleempty\dosetupforms}
+
+\def\dosetupforms[#1]
+ {\getparameters[\??fr][#1]%
+ \the\everysetupforms}
+
+\appendtoks
+ \ctxlua{backends.codeinjections.setformsmethod("@@frmethod")}%
+\to \everysetupforms
+
+\setupforms
+ [\c!method=XML] % no need for everyjob initialization as this is the default
+
+%D Goodie: (unchecked in \MKIV)
+
+\unexpanded\def\definepushbutton % name optional setup
+ {\dodoubleempty\dodefinepushbutton}
+
+\def\dodefinepushbutton[#1][#2]% name setup
+ {\dododefinepushbutton{#1}{n}{push}%
+ \dododefinepushbutton{#1}{r}{\symbol[psym:#1:n]}%
+ \dododefinepushbutton{#1}{d}{\symbol[psym:#1:r]}%
+ \setvalue{pushbutton:#1}{\dohandlepushbutton{#1}{#2}}}
+
+\def\dododefinepushbutton#1#2#3%
+ {\doifsymboldefinedelse{psym:#1:#2}%
+ \donothing{\definesymbol[psym:#1:#2][{#3}]}}
+
+\unexpanded\def\definepushsymbol
+ {\dotripleargument\dodefinepushsymbol}
+
+\def\dodefinepushsymbol[#1][#2]% [#3]
+ {\definesymbol[psym:#1:#2]}
+
+\def\dopushbutton[#1][#2]%
+ {\executeifdefined{pushbutton:#1}\gobbleoneargument{#2}}
+
+\def\pushbutton
+ {\dodoubleargument\dopushbutton}
+
+\def\dohandlepushbutton#1#2#3% identifier setup script
+ {\bgroup
+ \nextsystemfield
+ \setupfield
+ [pushbutton]
+ [\c!frame=\v!overlay,
+ \c!offset=\v!overlay,
+ \c!clickout=#3,#2]%
+ \definefield
+ [\currentsystemfield]
+ [push]
+ [pushbutton]
+ [psym:#1:n,psym:#1:r,psym:#1:d]%
+ \fitfield
+ [\currentsystemfield]%
+ \egroup}
+
+% \def\menu@psh
+% {\dodoubleargument\domenu@psh}
+%
+% \def\domenu@psh[#1][#2]#3\\%
+% {\txt\pushbutton[#1][#2]\\}%
+%
+%\appendtoks \let\psh\do@@ampsh \to \everysetmenucommands
+
+\unexpanded\def\menu@psh{\txt\pushbutton}
+
+\appendtoks \let\psh\menu@psh \to \everysetmenucommands
+
+% \definepushbutton [reset]
+%
+% \definepushsymbol [reset] [n] [\uniqueMPgraphic{whatever}{color=green}]
+% \definepushsymbol [reset] [r] [\uniqueMPgraphic{whatever}{color=white}]
+%
+% \startinteractionmenu[bottom]
+% \psh [reset] [JS(reset_something)] \\
+% \stopinteractionmenu
+
+%D Another goodie: (unchecked in \MKIV)
+
+% \definecolor[rollover:n][red]
+% \definecolor[rollover:r][green]
+% \definecolor[rollover:d][blue]
+
+\definepalet
+ [rollover]
+ [n=red,
+ r=green,
+ d=blue]
+
+\newcounter\nofrollovers
+\newcounter\nofrollbuttons
+
+\def\dorollbutton[#1][#2]#3[#4]%
+ {\dontleavehmode
+ \bgroup
+ \doglobal\increment\nofrollovers
+ \doglobal\increment\nofrollbuttons
+ \unexpanded\def\dosetlocationbox[##1]##2[##3]%
+ {\getparameters[##1][##3]%
+ \definecolor[rollover][rollover:##2]%
+ \doifelse{##2}{n}{\doifelsevalue{##1\c!alternative}\v!hidden\phantom\hbox}\hbox
+ {\localframed[##1]
+ [\c!framecolor=rollover,\c!backgroundcolor=rollover,\c!color=rollover]%
+ {\dolocationattributes{##1}\c!style\c!color{#3}}}}%
+ \iffirstargument
+ \ifsecondargument
+ \def\setlocationbox##1{\dosetlocationbox[\??am#1]{##1}[#2]}%
+ \else
+ \doifassignmentelse{#1}
+ {\def\setlocationbox##1{\dosetlocationbox[\??bt]{##1}[#1]}}
+ {\def\setlocationbox##1{\dosetlocationbox[\??am#1]{##1}[]}}%
+ \fi
+ \else
+ \def\setlocationbox##1{\dosetlocationbox[\??bt]{##1}[]}%
+ \fi
+ % todo: share symbols, tricky since different dimensions
+ \definesymbol[rsym:\nofrollovers:n][\setlocationbox n]%
+ \definesymbol[rsym:\nofrollovers:r][\setlocationbox r]%
+ \definesymbol[rsym:\nofrollovers:d][\setlocationbox d]%
+ \setupfield
+ [rollbutton]
+ [\c!frame=\v!off,
+ \c!offset=\v!overlay,
+ \c!clickout={#4}]%
+ \definefield
+ [roll:\nofrollbuttons][push][rollbutton]
+ [rsym:\nofrollovers:n,%
+ rsym:\nofrollovers:r,%
+ rsym:\nofrollovers:d]%
+ \fitfield[roll:\nofrollbuttons]%
+ \egroup}
+
+\unexpanded\def\rollbutton
+ {\dodoubleempty\dorollbutton}
+
+\def\menu@rob[#1]#2\\%
+ {\txt\rollbutton[\currentmenu]{\ignorespaces#2\unskip}[#1]\\}%
+
+\appendtoks \let\rob\menu@rob \to \everysetmenucommands
+
+% calls:
+% {..} [JS..]
+% [left] {..} [JS..]
+% [a=b] {..} [JS..]
+% [left] [a=b] {..} [JS..]
+%
+% \setupbuttons[offset=0pt,frame=off] % alternative=hidden
+%
+% \rollbutton {Manuals} [JS(Goto_File{show-man.pdf})]
+% \rollbutton {Articles} [JS(Goto_File{show-art.pdf})]
+% \rollbutton {Papers} [JS(Goto_File{show-pap.pdf})]
+% \rollbutton {Presentations} [JS(Goto_File{show-pre.pdf})]
+% \rollbutton {Resources} [JS(Goto_File{show-res.pdf})]
+%
+% \rob [JS(...)] bla bla \\
+
+\unexpanded\def\overlayrollbutton
+ {\dodoubleargument\dooverlayrollbutton}
+
+\def\dooverlayrollbutton[#1][#2]%
+ {\bgroup
+ \nextsystemfield
+ \setupfield
+ [overlayrollbutton]
+ [\c!frame=\v!off,\c!offset=\v!overlay,\c!regionin={#1},\c!regionout={#2}]%
+ \definesymbol
+ [\currentsystemfield]
+ [{\framed[\c!frame=\v!off,\c!width=\overlaywidth,\c!height=\overlayheight]{}}]%
+ \definefield
+ [\currentsystemfield][push][overlayrollbutton][\currentsystemfield][\currentsystemfield]%
+ \fitfield[\currentsystemfield]%
+ \egroup}
+
+% \defineoverlay
+% [ShowMenu]
+% [{\overlayrollbutton[VideLayer{navigation}][HideLayer{navigation}]}]
+
+\protect \endinput