%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 ADE \& \CONTEXT\ Development Team}]
%C
%C This module is part of the \CONTEXT\ macro||package and is
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.

%D There is still some leftover code from mkii, where we need to be sparse with hash
%D entries and so have a somewhat complex setup mechanism. It doesn't pay off to
%D waste time on improving this because one never knows what happens with widgets
%D in \PDF; it has a history of dropping features like this. Also, the implementation
%D of fields fluctuates with versions.

% interaction checking

\writestatus{loading}{ConTeXt Screen Macros / Fields}

\unprotect

\registerctxluafile{scrn-fld}{}

%D In \MKII\ we had to cheat a bit with setups in order not to run out of memory
%D with thousands of fields, which we happen to need at that time. In \MKIV\ we can
%D store some data at the \LUA\ end and use a somewhat slower but quite okay
%D inheritance mechanism. For this reason we now have split definitions, although
%D the old method is still somewhat supported. The clone and copy commands are
%D somewhat obsolete for several reasons: we can now use inheritance and autocloning
%D has been supported for a while. In most cases cloning (especially with check
%D boxes) the acrobat browser is not stable enough with respect to appearance
%D handling.
%D
%D A fieldcategory is nothing more than a collection of settings.
%D
%D \starttyping
%D \definefieldcategory
%D   [all-email]
%D   [height=1cm,
%D    width=14cm,
%D    style=sstf]
%D \stoptyping
%D
%D A definition can refer to this category:
%D
%D \starttyping
%D \definefieldbody [email] [type=line,category=all-email,default=pragma@xs4all.nl]
%D \stoptyping
%D
%D A copy of a field is made as follows:
%D
%D \starttyping
%D \definefieldbody [xmail] [email]
%D \stoptyping
%D
%D You can also be more specific:
%D
%D \starttyping
%D \definefieldbody[buttona][type=check,values={one,two}]
%D \definefieldbody[buttonb][type=check,values={three,four}]
%D \definefieldbody[buttonc][buttona][values={three,four}]
%D \stoptyping
%D
%D Actually typesetting a field happens this way:
%D
%D \starttyping
%D \fieldbody [Email]
%D \fieldbody [Email] [width=6cm]
%D \fieldbody [eMAIL]
%D \fieldbody [eMAIL] [width=7cm]
%D
%D \fieldbody [buttona]
%D \fieldbody [buttona]
%D \fieldbody [buttonb]
%D \fieldbody [buttonb]
%D \fieldbody [buttonc]
%D \fieldbody [buttonc]
%D \stoptyping
%D
%D So, you can call up a field many times and quite some parameters can be set.
%D
%D Because there are persistent problems with acrobat rendering associated
%D appearance streams (some messy /MK interferende) we also support native (built-in
%D dingbat) symbols: check, circle, cross, diamond, square and star.
%D
%D \starttyping
%D \definefield[test1][check]
%D \definefield[test2][check]
%D
%D \fieldbody[test1][width=1em,height=\strutht,depth=\strutdp,symbol=check]
%D \fieldbody[test1][width=1em,height=\strutht,depth=\strutdp,symbol=circle]
%D \fieldbody[test2][width=1em,height=\strutht,depth=\strutdp,symbol=square]
%D \stoptyping
%D
%D When submitting a form, we need to tell the driver module that we want \FDF\ or
%D \HTML.

\installcorenamespace {forms}

\installdirectcommandhandler \??forms {forms}

\appendtoks
    \clf_setformsmethod{\formsparameter\c!method}%
\to \everysetupforms

\setupforms
  [\c!method=XML] % no need for everyjob initialization as this is the default

\mutable\lettonothing\currentfieldbackgroundcolor
\mutable\lettonothing\currentfieldbackgroundcolorvalue
\mutable\lettonothing\currentfieldbodycategory
\mutable\lettonothing\currentfieldframecolor
\mutable\lettonothing\currentfieldframecolorvalue
\mutable\lettonothing\currentfieldlabel
\mutable\lettonothing\currentfieldstackname

\appendtoks
    \iflocation
      \clf_exportformdata{\formsparameter\c!export}%
    \fi
\to \everystoptext

%D We need to initialize symbols in a special way so that they can be used as
%D rendering for a widget.

\permanent\protected\def\presetfieldsymbols[#list]% slow
  {\processcommacommand[#list]\scrn_symbols_preset}

\def\scrn_symbols_preset#set%
  {\processcommalist[#set]\scrn_symbols_preset_indeed}%

\permanent\protected\def\scrn_symbols_preset_indeed#tag%
  {\doifelseobjectfound{SYM}{#tag}
     {}
     {\settightobject{SYM}{#tag}\hbox{\symbol[#tag]}%                        % todo: set this as immediate xform
      \page_otr_add_special_content{\hskip-\maxdimen\getobject{SYM}{#tag}}}} % and then force it into the file

\aliased\let\dosetfieldsymbol\scrn_symbols_preset_indeed

\permanent\def\dogetfieldsymbol#tag%
  {\getobject{SYM}{#tag}}

\permanent\protected\def\definedefaultsymbols % used ?
  {\definesymbol[defaultyes][\mathematics{\times}]%
   \definesymbol[defaultno] [\mathematics{\cdot }]}

%D Now comes the real code:

\installcorenamespace{fieldcategory}
\installcorenamespace{fieldbody}

\installcommandhandler \??fieldcategory {fieldcategory} \??fieldcategory
\installcommandhandler \??fieldbody     {fieldbody}     \??fieldbody

\newbox\b_scrn_field_body

\setupfieldcategory
  [\c!alternative=\v!normal, % normal clone copy
   \c!type=\v!line,          % line text ...
   \c!width=5em,
   \c!height=1em,
   \c!depth=\zeropoint,
   \c!align=\v!flushleft,
   \c!option=\v!printable, % maybe we need a globaloptions and marge them
   \c!n=1024]

\def\scrn_field_check_category
  {\edef\currentfieldbodycategory{\fieldbodyparameter\c!category}%
   \ifempty\currentfieldbodycategory
     \letfieldbodyparameter\s!parent\??fieldcategory
    %\setevalue{\currentfieldbodyhash\s!parent}{\namedfieldcategoryhash\empty}% to WS: not hash !
   \else
     \expanded{\setfieldbodyparameter{\s!parent}{\??fieldcategory\currentfieldbodycategory}}%
    %\setevalue{\currentfieldbodyhash\s!parent}{\namedfieldcategoryhash\currentfieldbodycategory}% to WS: not hash !
   \fi}

\appendtoks % we cannot use parent .. maybe s!parent has to change
    \ifempty\currentfieldbodyparent
        \scrn_field_check_category
        \clf_definefield
            name        {\currentfieldbody}%
            alternative {normal}%
            type        {\fieldbodyparameter\c!type}%
            category    {\fieldbodyparameter\c!category}%
            values      {\fieldbodyparameter\c!values}%
            default     {\fieldbodyparameter\c!default}%
        \relax
    \else
        \clf_clonefield
            children    {\currentfieldbody}%
            alternative {clone}%
            parent      {\currentfieldbodyparent}%
            category    {\fieldbodyparameter\c!category}%
            values      {\fieldbodyparameter\c!values}%
            default     {\fieldbodyparameter\c!default}%
        \relax
    \fi
\to \everydefinefieldbody

\permanent\tolerant\protected\def\fieldbody[#tag]#spacer[#S#settings]%
  {\iflocation
     \hbox\bgroup
       \edef\currentfieldbody{#tag}%
       \setupcurrentfieldbody[#settings]%
       \scrn_field_body_typeset
       \box\b_scrn_field_body
       \egroup
   \fi}

\def\scrn_field_body_typeset % todo: fieldsymbol (checkfields /MK mess)
  {\edef\currentfieldframecolor{\fieldbodyparameter\c!fieldframecolor}%
   \ifempty\currentfieldframecolor\else
     \getcolorattributevalue\currentfieldframecolor\currentfieldframecolorvalue
    % == \edef\currentfieldframecolorvalue{\thecolorattribute\currentfieldframecolor}%
   \fi
   \edef\currentfieldbackgroundcolor{\fieldbodyparameter\c!fieldbackgroundcolor}%
   \ifempty\currentfieldbackgroundcolor\else
     \getcolorattributevalue\currentfieldbackgroundcolor\currentfieldbackgroundcolorvalue
    % == \edef\currentfieldbackgroundcolorvalue{\thecolorattribute\currentfieldbackgroundcolor}%
   \fi
   \usefieldbodystyleandcolor\c!style\c!color
   \clf_insertfield
     {\currentfieldbody}%
     {%
       title                {\currentfieldbody}%
       width                {\fieldbodyparameter\c!width }%
       height               {\fieldbodyparameter\c!height}%
       depth                {\fieldbodyparameter\c!depth }%
       align                {\fieldbodyparameter\c!align}%
       length               {\fieldbodyparameter\c!n}%
       fontstyle            {\fontstyle}%
       fontalternative      {\fontalternative}%
       fontsize             {\fontbody}%
       fontsymbol           {\fieldbodyparameter\c!symbol}%
       color                {\fieldbodyparameter\c!color}%
       colorvalue           \c_attr_color
   \ifempty\currentfieldbackgroundcolor \else
       backgroundcolor      {\currentfieldbackgroundcolor}%
       backgroundcolorvalue {\currentfieldbackgroundcolorvalue}%
   \fi
   \ifempty\currentfieldframecolor \else
       framecolor           {\currentfieldframecolor}%
       framecolorvalue      {\currentfieldframecolorvalue}%
   \fi
       layer                {\fieldbodyparameter\c!fieldlayer}%
       option               {\fieldbodyparameter\c!option}%
       clickin              {\fieldbodyparameter\c!clickin}%
       clickout             {\fieldbodyparameter\c!clickout}%
       regionin             {\fieldbodyparameter\c!regionin}%
       regionout            {\fieldbodyparameter\c!regionout}%
       afterkey             {\fieldbodyparameter\c!afterkey}%
       format               {\fieldbodyparameter\c!format}%
       validate             {\fieldbodyparameter\c!validate}%
       calculate            {\fieldbodyparameter\c!calculate}%
       focusin              {\fieldbodyparameter\c!focusin}%
       focusout             {\fieldbodyparameter\c!focusout}%
       openpage             {\fieldbodyparameter\c!openpage}%
       closepage            {\fieldbodyparameter\c!closepage}%
      }%
    \relax}

%D The sets are used in grouped calculations.
%D
%D [name] [set]

\permanent\tolerant\protected\def\definefieldbodyset[#tag]#spacer[#list]%
  {\clf_definefieldset{#tag}{#list}}

\aliased\let\dodefinefieldset\definefieldbodyset % compatibility

%D A few testing macros (expandable for historic reasons):

\permanent\def\doifelsefieldbody    #tag{\clf_doifelsefieldset{#tag}}
\permanent\def\doifelsefieldcategory#tag{\clf_doifelsefieldcategory{#tag}}

\aliased\let\doiffieldbodyelse    \doifelsefieldbody
\aliased\let\doiffieldcategoryelse\doifelsefieldcategory

\aliased\let\doiffieldelse        \doifelsefieldbody % compatibility / will be dropped
\aliased\let\doifelsefield        \doifelsefieldbody % compatibility / will be dropped

%D We still support the traditional method of defining fields:
%D
%D \starttyping
%D \definefield [name] [type] [category] [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 \stoptyping
%D
%D Keep in mind that you can also use \type {\definefieldbody} to achieve the same.

\permanent\tolerant\protected\def\definefield[#tag]#spacer[#type]#spacer[#category]#spacer[#values]#spacer[#default]%
  {\definefieldbody[#tag][\c!type=#type,\c!category=#category,\c!values={#values},\c!default={#default}]}

\permanent\tolerant\protected\def\definesubfield[#tag]#spacer[#category]#spacer[#values]%
  {\definefieldbody[#tag][\c!type=sub,\c!category=#category,\c!values={#values}]}

\permanent\tolerant\protected\def\clonefield[#parent]#spacer[#tag]#spacer[#category]#spacer[#values]%
  {\definefieldbody[#tag][#parent][\c!category=#category,\c!values={#values}]}

\permanent\tolerant\protected\def\copyfield[#parent]#spacer[#tag]%
  {\definefieldbody[#tag][#parent]}

\aliased\let\definemainfield\definefield % obsolete !

%D We hook fields into the (viewer based) layering mechanism
%D (implemented as properties).

\appendtoks
    \lettonothing\currentfieldcategory
    \ifcstok{\interactionparameter\c!fieldlayer}\v!auto
        \setupcurrentfieldcategory[\c!fieldlayer=\currentviewerlayer]%
    \else
        \setupcurrentfieldcategory[\c!fieldlayer=]%
    \fi
\to \everysetupinteraction

\setupinteraction
  [\c!fieldlayer=\v!auto] % auto by default

%D The \type {\fieldbody} is the more bare one. One step further goes \type
%D {\fitfield}, in fact it (now) uses a dedicated instance of framed: \type
%D {fitfieldframed}.
%D
%D \starttyping
%D \ruledhbox{\fieldbody[Email][height=\strutht,depth=\strutdp,style=normal]}
%D \ruledhbox{\fitfield[Email][height=\strutht,depth=\strutdp,style=normal]}
%D \ruledhbox{\fitfield[buttona]}
%D \stoptyping

\newbox\b_scrn_field_fit_symbol

\defineframed
  [fitfieldframed]
  [\c!strut=\v!no,
   \c!frame=off,
   \c!offset=\v!overlay,
   \c!align=]

\permanent\tolerant\protected\def\fitfield[#tag]#spacer[#S#settings]%
  {\iflocation
     \begingroup
       \setbox\b_scrn_field_fit_symbol\hbox\bgroup
         \expanded{\symbol[\clf_getdefaultfieldvalue{#tag}]}%
       \egroup
       \fitfieldframed
         {\fieldbody[#tag]
            [\c!width=\wd\b_scrn_field_fit_symbol,
             \c!height=\ht\b_scrn_field_fit_symbol,
             \c!depth=\dp\b_scrn_field_fit_symbol,
             #settings]}%
     \endgroup
   \fi}

%D The traditional field command does some labeling and boxing:

\installcorenamespace{fieldlabel}
\installcorenamespace{fieldcontent}
\installcorenamespace{fieldtotal}

\installparameterhandler     \??fieldlabel   {fieldlabelframed}
\installparameterhandler     \??fieldcontent {fieldcontentframed}
\installparameterhandler     \??fieldtotal   {fieldtotalframed}

\installparametersethandler  \??fieldcontent {fieldcontentframed}

\installsetuphandler         \??fieldlabel   {fieldlabelframed}
\installsetuphandler         \??fieldcontent {fieldcontentframed}
\installsetuphandler         \??fieldtotal   {fieldtotalframed}

\installinheritedframed                      {fieldlabelframed}
\installinheritedframed                      {fieldcontentframed}
\installinheritedframed                      {fieldtotalframed}

\setupfieldcontentframed
  [\c!align=\v!flushleft,
   \c!strut=\v!no,
   \s!parent=\??regularframed] % needs checking

\setupfieldcontentframed % independent
  [\c!alternative=\v!normal,
   \c!type=\v!line,
   \c!width=5em,
   \c!height=\lineheight,
   \c!depth=\zeropoint,
   \c!align=\v!flushleft,
   \c!option=\v!printable,
   \c!n=1024]

\setupfieldlabelframed
  [\c!style=,
   \c!color=,
   \c!align=\v!flushleft,
   \s!parent=\??regularframed] % needs checking

\setupfieldtotalframed
  [%\c!alternative={\v!label,\v!frame,\v!horizontal},
   \c!strut=\v!no,
   \c!align=,
   \s!parent=\??regularframed] % needs checking

% \setupcurrent

\permanent\tolerant\protected\def\setupfield[#tag]#spacer[#variant]#spacer[#S#totalsettings]#spacer[#S#labelsettings]#spacer[#S#fieldsettings]%
  {\ifarguments\or\or
     \definefieldcategory[#tag][\s!parent=\??fieldcontent#tag,#variant]%
     \setupfieldtotalframed  [#tag][\s!parent=\??fieldtotal]%
     \setupfieldlabelframed  [#tag][\s!parent=\??fieldlabel]%
     \setupfieldcontentframed[#tag][\s!parent=\??fieldcontent,#variant]%
   \or
     \definefieldcategory[#tag][\s!parent=\??fieldcontent#tag,#totalsettings]%
     \setupfieldtotalframed  [#tag][\s!parent=\??fieldtotal,\c!alternative={#variant}]%
     \setupfieldlabelframed  [#tag][\s!parent=\??fieldlabel]%
     \setupfieldcontentframed[#tag][\s!parent=\??fieldcontent,#totalsettings]%
   \or
     \definefieldcategory[#tag][\s!parent=\??fieldcontent#tag,#labelsettings]%
     \setupfieldtotalframed  [#tag][\s!parent=\??fieldtotal,\c!alternative={#variant},#totalsettings]%
     \setupfieldlabelframed  [#tag][\s!parent=\??fieldlabel]%
     \setupfieldcontentframed[#tag][\s!parent=\??fieldcontent,#labelsettings]%
   \or
     \definefieldcategory[#tag][\s!parent=\??fieldcontent#tag,#fieldsettings]%
     \setupfieldtotalframed  [#tag][\s!parent=\??fieldtotal,\c!alternative={#variant},#totalsettings]%
     \setupfieldlabelframed  [#tag][\s!parent=\??fieldlabel,#labelsettings]%
     \setupfieldcontentframed[#tag][\s!parent=\??fieldcontent,#fieldsettings]%
   \fi}

\permanent\tolerant\protected\def\setupfields[#variant]#spacer[#S#totalsettings]#spacer[#S#labelsettings]#spacer[#S#fieldsettings]%
  {\ifarguments\or
     \setupfieldtotalframed  [#variant]%
   \or
     \setupfieldtotalframed  [#variant]%
     \setupfieldcontentframed[#totalsettings]%
   \or
     \setupfieldtotalframed  [#variant]%
     \setupfieldlabelframed  [#totalsettings]%
     \setupfieldcontentframed[#labelsettings]%
   \or
     \setupfieldtotalframed  [\c!alternative={#variant},#totalsettings]%
     \setupfieldlabelframed  [#labelsettings]%
     \setupfieldcontentframed[#fieldsettings]%
   \fi}

% just to get the chain right for no category:

\definefieldcategory    [][\s!parent=\??fieldcontent]
%setupfieldtotalframed  [][\s!parent=\??fieldtotal]
%setupfieldlabelframed  [][\s!parent=\??fieldlabel]
%setupfieldcontentframed[][\s!parent=\??fieldcontent]

% no longer supported:

% \let\resetfields\relax

\def\scrn_field_load_scripts{\useJSscripts[fld]\glet\scrn_field_load_scripts\relax}

\newconditional\fieldlabelshown
\newconditional\fieldframeshown
\newconditional\fieldisvertical
\newconditional\fieldishorizontal

\mutable\lettonothing\currentfieldtotalframed
\mutable\lettonothing\currentfieldlabelframed
\mutable\lettonothing\currentfieldcontentframed

\mutable\lettonothing\fieldtotalframedparameterhash   % weird that we have to flag this
\mutable\lettonothing\fieldlabelframedparameterhash   % idem
\mutable\lettonothing\fieldcontentframedparameterhash % idem

\permanent\tolerant\protected\def\field[#tag]#spacer[#label]% can be sped up with \setupcurrentfieldtotalframed etc
  {\iflocation
     \dontleavehmode
     \begingroup
     \scrn_field_load_scripts
     \edef\currentfieldbody    {#tag}%
     \edef\currentfieldlabel   {#label}%
     \edef\currentfieldcategory{\clf_getfieldcategory{#tag}}%
     \ifempty\currentfieldlabel
       \let\currentfieldlabel\currentfieldbody
     \fi
     \ifempty\currentfieldcategory
       \setupfieldtotalframed  [\currentfieldbody][\s!parent=\??fieldtotal]%
       \setupfieldlabelframed  [\currentfieldbody][\s!parent=\??fieldlabel]%
       \setupfieldcontentframed[\currentfieldbody][\s!parent=\??fieldcontent]%
       \definefieldcategory    [\currentfieldbody]%
       \setupfieldbody         [\currentfieldbody][\c!category=\currentfieldbody]%
       \let\currentfieldcategory\currentfieldbody
     \fi
     \let\currentfieldtotalframed  \currentfieldcategory
     \let\currentfieldlabelframed  \currentfieldcategory
     \let\currentfieldcontentframed\currentfieldcategory
     \scrn_field_analyze_setups
     \ifconditional\fieldframeshown
       \inheritedfieldtotalframedframed % lower framedoffset
       \bgroup
     \else
       \vbox
       \bgroup
     \fi
     \dontcomplain
     \ifconditional\fieldlabelshown
       \scrn_field_set_label_box
     \fi
     \scrn_field_set_content_box
     \ifconditional\fieldlabelshown
       \ifconditional\fieldisvertical
         \scrn_field_flush_vertical
       \else
         \scrn_field_flush_horizontal
       \fi
     \else
       \scrn_field_flush_content
     \fi
     \egroup
     \endgroup
   \fi}

% opties: veld, label, kader, vertikaal/horizontaal

\newbox\b_scrn_field_label
\newbox\b_scrn_field_content

% lower framedoffset

\def\scrn_field_set_label_box
  {\setbox\b_scrn_field_label\hbox
      {\reshapeframeboxtrue % else wrong dimensions % still needed?
       \inheritedfieldlabelframedframed{\currentfieldlabel}}}

% \c!fieldoffset=-\framedoffset,\c!fieldbackgroundcolor=,
% \hbox{\lower\@@fdfieldoffset\hbox{\typesetfield}}

\def\scrn_field_set_content_box
  {\setbox\b_scrn_field_content\hbox
     {\reshapeframeboxtrue % else wrong dimensions (to be checked)
      \ifempty{\fieldcontentframedparameter\c!height}%
        \ifconditional\fieldisvertical
          \setfieldcontentframedparameter\c!height{6ex}%
        \orelse\ifconditional\fieldishorizontal
          \setfieldcontentframedparameter\c!height{\vsize}%
        \else
          \setfieldcontentframedparameter\c!height{2cm}%
        \fi
      \fi
      \ifempty{\fieldcontentframedparameter\c!width}%
        \ifconditional\fieldisvertical
          \setfieldcontentframedparameter\c!width{\hsize}%
        \orelse\ifconditional\fieldishorizontal
          \setfieldcontentframedparameter\c!width{20em}%
        \else
          \setfieldcontentframedparameter\c!width{2cm}%
        \fi
      \fi
      \inheritedfieldcontentframedframed % lower framedoffset
        {\fieldbody
           [\currentfieldbody]
           [\c!width=\framedwidth,\c!height=\framedheight]}}}


\def\scrn_field_flush_vertical
  {\vbox
     {\copy\b_scrn_field_label
      \fieldtotalframedparameter\c!inbetween
      \copy\b_scrn_field_content}}

\def\scrn_field_flush_horizontal
   {\hbox
      {\vbox \ifdim\ht\b_scrn_field_content>\ht\b_scrn_field_label to \ht\b_scrn_field_content \fi
         {\fieldtotalframedparameter\c!before
          \copy\b_scrn_field_label
          \fieldtotalframedparameter\c!after}%
       \hskip{\fieldtotalframedparameter\c!distance}%
       \vbox \ifdim\ht\b_scrn_field_label>\ht\b_scrn_field_content to \ht\b_scrn_field_label \fi
         {\fieldtotalframedparameter\c!before
          \box\b_scrn_field_content
          \fieldtotalframedparameter\c!after}}}

\def\scrn_field_flush_content
  {\box\b_scrn_field_content}

%D todo: replace \processallactionsinset

\def\scrn_field_analyze_setups
  {\fieldlabelshown\conditionalfalse
   \fieldframeshown\conditionalfalse
   \fieldishorizontal\conditionalfalse
   \fieldisvertical\conditionalfalse
   \expanded{\processallactionsinset[\fieldtotalframedparameter\c!alternative]}
     [      \v!reset=>\fieldlabelshown\conditionalfalse
                      \fieldframeshown\conditionalfalse
                      \fieldishorizontal\conditionalfalse
                      \fieldisvertical\conditionalfalse,
            \v!label=>\fieldlabelshown\conditionaltrue,
            \v!frame=>\fieldframeshown\conditionaltrue,
       \v!horizontal=>\fieldishorizontal\conditionaltrue,
         \v!vertical=>\fieldisvertical\conditionaltrue]%
   \ifconditional\fieldisvertical
     \setupfieldtotalframed[\c!distance=\zeropoint,\c!inbetween=\vskip\d_framed_local_offset,\c!align=\v!right,\c!width=20em]%
   \orelse\ifconditional\fieldishorizontal
     \setupfieldtotalframed[\c!distance=\d_framed_local_offset,\c!inbetween=,\c!align=\c!left,\c!height=10ex]%
   \else
     \setupfieldtotalframed[\c!distance=\zeropoint,\c!inbetween=,\c!align=\c!left]%
   \fi
   \setupfieldtotalframed[\c!n=,\c!before=,\c!after=\vss,\c!style=,\c!color=]}

%D Common stuff (obsolete)

\newinteger\c_scrn_field_system_n

\permanent\def\currentsystemfield{sys::\the\c_scrn_field_system_n}

\permanent\protected\def\nextsystemfield
  {\global\advanceby\c_scrn_field_system_n\plusone}

%D \CONTEXT\ had tooltips right from the moment that it supported fields. Due to the
%D at that moment somewhat limited \PDF\ specification, they were implemented using
%D \JAVASCRIPT, but nowadays more kind of actions are supported, so we can do
%D without. The \MKIV\ version also supports definition of tooltips and
%D configuration.
%D
%D \starttyping
%D before \tooltip[right]{inbetween}{a very nice tip} after\par
%D before \tooltip[align=normal]{inbetween}{a very\\nice tip} after\par
%D before \tooltip[middle]{inbetween}{a very nice tip} after\par
%D before \tooltip[left]{inbetween}{a very nice tip} after\par
%D \stoptyping

\newbox    \b_scrn_tooltip_anchor
\newbox    \b_scrn_tooltip_text
\newinteger\c_scrn_tooltip_n

\installcorenamespace{tooltip}

\installframedcommandhandler \??tooltip {tooltip} \??tooltip

\setuptooltip
  [\c!location=\v!right,
   \c!frame=\v!off,
   \c!offset=.1ex,
   \c!background=\v!color,
   \c!backgroundcolor=gray]

\appendtoks
    \protected\frozen\instance\edefcsname\currenttooltip\endcsname{\scrn_tooltip_direct{\currenttooltip}}%
\to \everydefinetooltip

\protected\def\scrn_tooltip_direct#tag%
  {\cdef\currenttooltip{#tag}%
   \iflocation
     \expandafter\scrn_tooltip_indeed
   \else
     \expandafter\scrn_tooltip_ignore
   \fi}

\tolerant\def\scrn_tooltip_ignore[#S#settings]#:#anchortext#tiptext%
  {#anchortext}

\mutable\lettonothing\currenttooltipname

\tolerant\def\scrn_tooltip_indeed[#S#settings]#:#anchortext#tiptext% a more modern aproach (push buttons)
  {\dontleavehmode \hbox \bgroup
     \dontcomplain
     \global\advanceby\c_scrn_tooltip_n\plusone
     \edef\currenttooltipname{tooltip:\the\c_scrn_tooltip_n}%
     \setbox\b_scrn_tooltip_anchor\hbox
       {\strut#anchortext}%
     \doifelseassignment{#settings}
       {\setupcurrenttooltip[#settings]}%
       {\setupcurrenttooltip[\c!location=#settings]}%
     \setbox\b_scrn_tooltip_text\hbox
       {\resettooltipparameter\c!location
        \inheritedtooltipframed{#tiptext}}%
     \definesymbol
       [\currenttooltipname:txt]
       [\copy\b_scrn_tooltip_text]%
     \definefieldbody
       [\currenttooltipname:txt]
       [\c!type=push,
        \c!width=\wd\b_scrn_tooltip_text,
        \c!height=\ht\b_scrn_tooltip_text,
        \c!depth=\dp\b_scrn_tooltip_text,
        \c!option=\v!hidden,
        \c!values=\currenttooltipname:txt]%
     \setbox\b_scrn_tooltip_text\hbox
       {\fieldbody[\currenttooltipname:txt]}%
     \setbox\b_scrn_tooltip_text\hbox
       {\strut\lower{.25\exheight+\ht\b_scrn_tooltip_text}\box\b_scrn_tooltip_text}%
     \edef\p_location{\tooltipparameter\c!location}%
     \ifx\p_location\v!left
       \hsmashed{\hskip\wd\b_scrn_tooltip_anchor\llap{\box\b_scrn_tooltip_text}}%
     \orelse\ifx\p_location\v!middle
       \hsmashed to \wd\b_scrn_tooltip_anchor{\hss\box\b_scrn_tooltip_text\hss}%
     \else
       \hsmashed{\box\b_scrn_tooltip_text}%
     \fi
     \definesymbol
       [\currenttooltipname:but]
       [\hphantom{\copy\b_scrn_tooltip_anchor}]%
     \definefieldbody
       [\currenttooltipname:but]
       [\c!type=push,
        \c!regionin=action(show{\currenttooltipname:txt}),
        \c!regionout=action(hide{\currenttooltipname:txt}),
        \c!width=\wd\b_scrn_tooltip_anchor,
        \c!height=\ht\b_scrn_tooltip_anchor,
        \c!depth=\dp\b_scrn_tooltip_anchor]%
     \hsmashed{\fieldbody[\currenttooltipname:but]}%
   \egroup
   #anchortext}% when hyphenated the text wil stick out ... such are fields and we cannot use a link here

\definetooltip[tooltip]

%D From messages on the mailing list we can conclude that fieldstacks are used so we
%D keep them in the core:
%D
%D \starttyping
%D \definesymbol[one]  [one]
%D \definesymbol[two]  [two]
%D \definesymbol[three][three]
%D
%D \definefieldstack[mine][one,two,three]
%D \fieldstack[mine]
%D \fieldstack[mine]
%D
%D \goto{walk field}[Walk{mine}]
%D \stoptyping

% todo: expand #symbols

\installcorenamespace {fieldstack}

\permanent\tolerant\protected\def\definefieldstack[#tag]#spacer[#symbols]#spacer[#S#settings]%
  {\ifcsname\??fieldstack#tag\endcsname
     % already done
   \else
     %xdefcsname\??fieldstack#tag\endcsname{\scrn_fieldstack_construct[#tag][#symbols][#settings]}%
     \xdefcsname\??fieldstack#tag\endcsname{\scrn_fieldstack_construct[#tag][#symbols][\notexpanded{#settings}]}%
   \fi}

\permanent\tolerant\protected\def\fieldstack[#tag]#spacer[#symbols]#spacer[#S#settings]%
  {\ifparameter#symbols\or
     \definefieldstack[#tag][#symbols][#settings]%
   \fi
   \csname\??fieldstack#tag\endcsname}

\newbox\b_scrn_fieldstack_box

\definesymbol[\s!empty][]

\def\scrn_fieldstack_add#tag#settings#symbol%
  {\advanceby\scratchcounter\plusone
   \edef\currentfieldstackname{#tag:\the\scratchcounter}%
   \ifnum\scratchcounter=\fieldcategoryparameter\c!start\relax
     \definefieldbody[\currentfieldstackname][\c!type=check,\c!values={#symbol,\s!empty},\c!default={#symbol}]%
   \else
     \definefieldbody[\currentfieldstackname][\c!type=check,\c!values={#symbol,\s!empty},\c!default=\s!empty]%
   \fi
   \setbox\b_scrn_fieldstack_box\hbox{\symbol[#symbol]}%
   \setcollector
     [fieldstack]
     {\fieldbody
        [\currentfieldstackname]
        [\c!option={\v!readonly},
         \c!width=\wd\b_scrn_fieldstack_box,
         \c!height=\ht\b_scrn_fieldstack_box,
         \c!depth=\dp\b_scrn_fieldstack_box,
         #settings]}}

\protected\def\scrn_fieldstack_construct[#tag][#symbols][#S#settings]% start=n, 0 == leeg
  {\iflocation
     \dontleavehmode
     \begingroup
     \setupfieldcategory[\c!start=1,#settings]% was just \??fieldcategory
     \scrn_field_load_scripts
     \definecollector
       [fieldstack]%
       [\c!corner=\v!middle,
        \c!location=\v!middle]%
     \scratchcounter\zerocount
     \processcommalist[#symbols]{\scrn_fieldstack_add{#tag}{#settings}}%
     \flushcollector[fieldstack]%
     \endgroup
   \fi}

%D Another goodie. Two actions can be hookes into an overlay.
%D
%D \starttyping
%D \defineviewerlayer[test]
%D
%D \startviewerlayer[test]Hide Me\stopviewerlayer
%D
%D \defineoverlay
%D   [WithTest]
%D   [{\overlayrollbutton[HideLayer{test}][VideLayer{test}]}]
%D
%D \framed[background=WithTest]{toggle}
%D \stoptyping

\newinteger\c_scrn_rollbutton_n

\permanent\tolerant\protected\def\overlayrollbutton[#1]#*[#2]#;#=#=%
  {\iflocation
     \bgroup
     \global\advanceby\c_scrn_rollbutton_n_button\plusone
     \global\advanceby\c_scrn_rollbutton_n_symbol\plusone
     \definesymbol
       [rollsymbol:\the\c_scrn_rollbutton_n_symbol]
       [{\framed[\c!frame=\v!off,\c!width=\overlaywidth,\c!height=\overlayheight]{}}]%
   % \definefieldbody
   %   [rollbutton:\the\c_scrn_rollbutton_n_button]
   %   [\c!type=push,
   %    \c!values=rollsymbol:\the\c_scrn_rollbutton_n_symbol,
   %    \c!default=rollsymbol:\the\c_scrn_rollbutton_n_symbol]%
   % \fitfield
   %   [rollbutton:\the\c_scrn_rollbutton_n_button]%
   %   [\c!regionin={#regionin},
   %    \c!regionout={#regionout}]%
     %
     \definefield
       [rollbutton:\the\c_scrn_rollbutton_n_button][push][rollbutton]
       [rollsymbol:\the\c_scrn_rollbutton_n_symbol]%
     \fitfield
       [rollbutton:\the\c_scrn_rollbutton_n_button]%
       [\c!regionin={#1#3},\c!regionout={#2#4}]%
     %
     \egroup
   \fi}

% \protect \endinput % THE FOLLOWING CODE IS NOT CHECKED

%D I will redo these when I need them.

% \setupinteraction[state=start]
%
% \definepushbutton [reset]
%
% \startuniqueMPgraphic{whatever}{color}
%     fill fullcircle xysized (OverlayWidth,OverlayHeight) withcolor \MPvar{color} ;
% \stopuniqueMPgraphic
%
% \definepushsymbol [reset] [n] [\uniqueMPgraphic{whatever}{color=red}]
% \definepushsymbol [reset] [r] [\uniqueMPgraphic{whatever}{color=green}]
% \definepushsymbol [reset] [d] [\uniqueMPgraphic{whatever}{color=blue}]
%
% \starttext
%     \startTEXpage
%         \pushbutton [reset] [page(2)]
%     \stopTEXpage
%     \startTEXpage
%         \pushbutton [reset] [page(1)]
%     \stopTEXpage
% \stoptext

\newinteger\c_scrn_pushbutton_n

\permanent\tolerant\protected\def\definepushbutton[#tag]#spacer[#S#settings]%
  {\scrn_pushbutton_define_variant{#tag}{n}{push}%
   \scrn_pushbutton_define_variant{#tag}{r}{\symbol[pushsymbol:#tag:n]}%
   \scrn_pushbutton_define_variant{#tag}{d}{\symbol[pushsymbol:#tag:r]}%
   \setvalue{pushbutton:#tag}{\scrn_pushbutton_handle{#tag}{#settings}}}

\def\scrn_pushbutton_define_variant#tag#variant#content%
  {\doifelsesymboldefined{pushsymbol:#tag:#variant}
     \donothing
     {\definesymbol[pushsymbol:#tag:#variant][{#content}]}}

\def\scrn_pushbutton_handle#tag#settings#reference%
  {\bgroup
   \global\advanceby\c_scrn_pushbutton_n\plusone
   \setupfield
     [pushbutton]%
     [\c!frame=\v!overlay,%
      \c!offset=\v!overlay,%
      \c!clickout={#reference},%
      #settings]%
   \definefield
     [pushbutton:\the\c_scrn_pushbutton_n]%
     [push]%
     [pushbutton]%
     [pushsymbol:#tag:n,pushsymbol:#tag:r,pushsymbol:#tag:d]%
   \fitfield
     [pushbutton:\the\c_scrn_pushbutton_n]%
   \egroup}

\permanent\tolerant\protected\def\definepushsymbol[#tag]#spacer[#variant]% [#reference]
  {\definesymbol[pushsymbol:#tag:#variant]}

\permanent\tolerant\def\pushbutton[#tag]#spacer[#variant]%
  {\executeifdefined{pushbutton:#tag}\gobbleoneargument{#variant}}

%D We plug into the menu system

\permanent\permanent\protected\def\scrn_menu_psh_start[#reference]#text\stoppsh
  {\starttxt\pushbutton[\currentinteractionmenu][#reference]\stoptxt}

\permanent\permanent\protected\def\scrn_menu_psh_direct[#reference]#text\\
  {\scrn_menu_psh_start[#reference]\stoprob}

\aliased\let\startpsh\relax % maybe mutable
\aliased\let\stoppsh \relax % maybe mutable
\aliased\let\psh     \relax % maybe mutable

\appendtoks
    \enforced\let\startpsh\scrn_menu_psh_start
    \enforced\let\stoppsh \relax
    \enforced\let\psh     \scrn_menu_psh_direct
\to \everysetmenucommands

%D Another goodie: (unchecked in \MKIV)

% 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 \\

% \definecolor[rollover:n][red]
% \definecolor[rollover:r][green]
% \definecolor[rollover:d][blue]

\definepalet
  [rollover]
  [n=red,
   r=green,
   d=blue]

\newinteger\c_scrn_rollbutton_n_button
\newinteger\c_scrn_rollbutton_n_symbol

\permanent\def\lastrollbuttonindex{\the\c_scrn_rollbutton_n_button}

\setupfield
  [rollbutton]
  [\c!frame=\v!off,
   \c!offset=\v!overlay]

\let\scrn_rollbutton_symbol\relax

\def\scrn_rollbutton_symbol_m
  {\scrn_rollbutton_symbol_indeed
     \interactionmenuparameter
     \inheritedinteractionmenuframed
     \setinteractionmenuparameter
     \useinteractionmenustyleandcolor}

\def\scrn_rollbutton_symbol_b
  {\scrn_rollbutton_symbol_indeed
     \buttonparameter
     \inheritedbuttonframed
     \setbuttonparameter
     \usebuttonstyleandcolor}

\permanent\tolerant\protected\def\rollbutton[#tag]#spacer[#S#settings]#:#text[#reference]%
  {\dontleavehmode
   \bgroup
   \global\advanceby\c_scrn_rollbutton_n_button\plusone
   \global\advanceby\c_scrn_rollbutton_n_symbol\plusone
   \ifparameter#tag\or
     \ifparameter#settings\or
       \edef\currentinteractionmenu{#tag}%
       \setupcurrentinteractionmenu[#settings]%
       \let\scrn_rollbutton_symbol\scrn_rollbutton_symbol_m
     \orelse\ifhastok={#tag}%
       \lettonothing\currentbutton
       \setupcurrentbutton[#tag]%
       \let\scrn_rollbutton_symbol\scrn_rollbutton_symbol_b
     \else
       \edef\currentinteractionmenu{#tag}%
       \let\scrn_rollbutton_symbol\scrn_rollbutton_symbol_m
     \fi
   \else
     \let\scrn_rollbutton_symbol\scrn_rollbutton_symbol_b
   \fi
   % todo: share symbols, tricky since different dimensions (maybe \unique...)
   \definesymbol[rollsymbol:\the\c_scrn_rollbutton_n_symbol:n][\scrn_rollbutton_symbol{n}{#text}]%
   \definesymbol[rollsymbol:\the\c_scrn_rollbutton_n_symbol:r][\scrn_rollbutton_symbol{r}{#text}]%
   \definesymbol[rollsymbol:\the\c_scrn_rollbutton_n_symbol:d][\scrn_rollbutton_symbol{d}{#text}]%
   \definefield
     [rollbutton:\the\c_scrn_rollbutton_n_button][push][rollbutton]
     [rollsymbol:\the\c_scrn_rollbutton_n_symbol:n,%
      rollsymbol:\the\c_scrn_rollbutton_n_symbol:r,%
      rollsymbol:\the\c_scrn_rollbutton_n_symbol:d]%
   \fitfield
     [rollbutton:\the\c_scrn_rollbutton_n_button]%
     [\c!clickout={#reference}]%
   \egroup}

\protected\def\scrn_rollbutton_symbol_indeed#getparameter#inheritedframed#setparameter#usestyleandcolor#what#text%
  {\definecolor[rollover][rollover:#what]%
   \ifcstok{#getparameter\c!alternative}\v!hidden
     \expandafter\phantom
   \else
     \expandafter\hbox
   \fi
   \bgroup
     #setparameter\c!framecolor     {rollover}%
     #setparameter\c!backgroundcolor{rollover}%
     #setparameter\c!color          {rollover}%
     #inheritedframed{#usestyleandcolor\c!style\c!color{#text}}%
   \egroup}

%D We plug into the menu system

\permanent\protected\def\scrn_menu_rob_start[#reference]#text\stoprob
  {\starttxt\rollbutton[\currentinteractionmenu]{\ignorespaces#text\unskip}[#reference]\stoptxt}

\permanent\protected\def\scrn_menu_rob_direct[#reference]#text\\
  {\scrn_menu_rob_start[#reference]#text\stoprob}

\aliased\let\startrob\relax % maybe mutable
\aliased\let\stoprob \relax % maybe mutable
\aliased\let\rob     \relax % maybe mutable

\appendtoks
    \enforced\let\startrob\scrn_menu_rob_start
    \enforced\let\stoprob \relax
    \enforced\let\rob     \scrn_menu_rob_direct
\to \everysetmenucommands

%D Signing:
%D
%D \starttyping
%D \setupinteraction[state=start]
%D
%D \definefield[signature][signed]
%D
%D \starttext
%D
%D     \defineoverlay[signature][my signature]
%D
%D     \startTEXpage[offset=1ts]
%D         sign: \inframed
%D           [background=signature]
%D           {\fieldbody[signature][width=3cm,option=hidden]}
%D     \stopTEXpage
%D
%D \stoptext
%D \stoptyping
%D
%D after processing:
%D
%D \starttyping
%D mtxrun --script pdf --sign   --certificate=somesign.pem --password=test --uselibrary somefile
%D mtxrun --script pdf --verify --certificate=somesign.pem --password=test --uselibrary somefile
%D \stoptyping

\protect \endinput
