% \iffalse meta-comment
%
%% File: l3pdffield-action.dtx
%
% Copyright (C) 2021-2025 The LaTeX Project
%
% It may be distributed and/or modified under the conditions of the
% LaTeX Project Public License (LPPL), either version 1.3c of this
% license or (at your option) any later version.  The latest version
% of this license is in the file
%
%    http://www.latex-project.org/lppl.txt
%
% This file is part of the "LaTeX PDF management bundle" (The Work in LPPL)
% and all files in that bundle must be distributed together.
%
% -----------------------------------------------------------------------
%
% The development version of the bundle can be found at
%
%    https://github.com/latex3/pdfresources
%
% for those people who are interested.
%
%<*driver>
\DocumentMetadata{tagging=on} %no ua-2 currently, as labels/contents for widgets are missing
\documentclass[full]{l3doc}
\usepackage{latex-lab-testphase-l3doc}

\usepackage{array,booktabs,siunitx}
\usepackage{l3pdffield,bearwear}
\hypersetup{pdfauthor=The LaTeX Project,
 pdftitle=l3pdffield (LaTeX PDF management bundle)}
\begin{document}
  \DocInput{\jobname.dtx}
\end{document}
%</driver>
% \fi
% \providecommand\hook[1]{\texttt{#1}}
% \title{^^A
%   The \pkg{l3pdffield-action} module\\ Commands to handle actions of form fields   ^^A
%   \\ \LaTeX{} PDF management bundle
% }
%
% \author{^^A
%  The \LaTeX{} Project\thanks
%    {^^A
%      E-mail:
%        \href{mailto:latex-team@latex-project.org}
%          {latex-team@latex-project.org}^^A
%    }^^A
% }
%
% \date{Version 0.96x, released 2025-11-12}
%
% \maketitle
% \begin{documentation}
% \section{\pkg{l3pdffield-action} Introduction}
% This is the documentation for actions for formular fields, for general information about form fields
% check the documentation l3pdffield.
%
% \begin{center}
%  \ExplSyntaxOn
%  A:~ \pdffield_checkbox:n {name=A}\quad B:~\pdffield_checkbox:n {name=B}\par\bigskip
%  \pdffield_pushbutton:n{name=all,caption=Reset~All,reset}\quad
%  \pdffield_reset_new:nn{B}{fields=B}
%  \pdffield_pushbutton:n{name=all,caption=Reset~B,reset=B}\quad
%  \ExplSyntaxOff
% \end{center}
%
% Please keep in mind
% \begin{itemize}
% \item Not every PDF viewer supports form fields.
% \item Even if they support it, that doesn't mean that
%  they support actions like Submit.
% \item The handling can depend on settings in the PDF viewer.
% \item Standards like pdf/A disable features of form fields too
% (as you typically can't change the PDF).
% \end{itemize}
%
% \section{Actions}
%
% Actions must be handled in three places: In the action dictionary (|/A|)
% of the annotation(s), in the additional action dictionary of the field (|/AA|),
% and in the additional action dictionary (|/AA|) of the annotation(s). The distinction
% between the two |/AA| dictionaries is relevant as field actions can only be
% added when the field is initialized, so typically with the first field command
% for a specific name, while annotation actions can be added for example only to
% one specific instance of a checkbox or to pushbuttons belonging to the same field.
%
% \subsection{The additional action dictionaries (AA)}
% The actions in the |/AA| dictionaries are JavaScript (ECMAScript) actions.
% An example is the |calculate|/|AA/C| action, which is added with the |/C| key:
%
% \begin{verbatim}
% Netto~\pdffield_textfield:n{name=netto}~
% \pdf_object_unnamed_write:ne{stream}
%   {
%     {}
%     {
%      var~f_netto = this.getField("netto");
%      event.value = 1.19*f_netto.value;
%     }
%   }
% \tl_set:Ne\l_tmpa_tl{\pdf_object_ref_last:}
% Brutto~\pdffield_textfield:n{name=brutto,AA/C={\l_tmpa_tl}}
% \end{verbatim}
%
% The main problem with scripts is to get the escaping right. While it is possible
% to pass the script as string, it is less error prone to include it as (file) stream
% and to reference the object number as done in the example.
%
% \subsection{The action dictionary (A)}
%
% The action dictionary can contain much more action types. The PDF reference lists 20
% different types\footnote{Sound and Movie are deprecated in PDF~2.0}:
% GoTo, GoToR, GoToE, GoToDp, Launch, Thread, URI, Sound, Movie,
% Hide, Named, SubmitForm, ResetForm, ImportData, SetOCGState, Rendition,
% Trans, GoTo3DView, JavaScript, RichMediaExecute.
%
% And action dictionary typically looks like this:
% \begin{verbatim}
% /A << /Type /Action
%       /S    ... % type name, e.g. /URI
%       /Next ... % optional, next action
%       ...   ... % more keys
%    >>
% \end{verbatim}
%
% The |/Next| key allows to chain actions. The value can be a reference to a
% single action, or an array of actions.
%
% It depends on the action type which other keys should be used.
%
% While almost all actions are usable in the annotations of a field, the three
% actions |SubmitForm|, |ResetForm| and |ImportData| are specific to fields and need
% explicit support. This support is the main task of this module.
%
% \subsubsection{ResetForm}
% The |ResetForm| action resets the fields of a form. The action is typically
% attached to a pushbutton.
%
% In simple cases the action only need to contain the subtype entry and then resets
% everything (sadly with some side-effect on the appearance of the pushbutton, sigh).
%
% \begin{verbatim}
% \group_begin:
% \pdfannot_dict_put:nnn{widget}{A}{<</Type/Action/S/ResetForm>>}
% \pdffield_pushbutton:n{name=R,caption=Reset}
% \group_end:
% \end{verbatim}
%
% A |ResetForm| action knows two optional keys: |/Fields| allows to describe or restrict
% the fields which should be reset. Depending on the setting of the |/Flags| key
% the value of |/Fields| describes the fields to reset or the fields to leave unchanged.
%
% The commands of this module allow to store actions under a name which can then be
% used in the key-val list of a field annotation.
%
% A reset action can be defined and used like this
% \begin{verbatim}
% \pdffield_reset_new:nn
%   {myreset}
%   {
%     fields= {A,B,C},
%     exclude     % or include
%   }
% \pdffield_pushbutton:n{name=r,caption=Reset,reset=myreset}
% \end{verbatim}
%
% |myreset| is the name the action can be referred to with the |reset| key.
%
% It is possible to define and use a reset action before all fields it
% refers too have been created.
% The list of names can contain names that are actually not used by the form.
%
% The reset action |all| is predefined.
%
% \subsubsection{ImportData}
% The |ImportData| action allows to import field data from an external file, for example
% a |.fdf| created with the submit action.
% The action is typically attached to a pushbutton, its only value is a file name.
%
% \subsubsection{SubmitForm}
%
% |SubmitForm| is the most challenging action. There are more keys in the dictionary,
% 13 flags, and there are four export options, which require each some flag settings.
% And the main argument is an url, which can contain special chars like \# or \% and
% so need special handling.
%
% A submit action can be defined like this
% \begin{verbatim}
% \pdffield_submit_new:nnn
%   {mysubmit}
%   {
%     export = fdf,
%     fields= {A,B,C},
%     exclude,     % or include
%     setsubmitflags={...}
%     ...
%   }
%   {URL}
% \pdffield_pushbutton:n{name=s,caption={Submit~A,B,C},submit=mysubmit}
% \end{verbatim}
%
% The export options are |html|, |pdf|, |fdf| and |xfdf|. The |html| export uses
% my default the |POST| method, the |GET| method can be forced by setting the
% |GetMethod| flag---at least according to the reference, I wasn't able yet to test it.
%
%
% The following tabular describes the relation between these export options and the
% flags. |0| and |1| in the tabular means that the value is set by the code. |*|
% can be set by the user with the |setFlags| or |setsubmitflags| key.
%
% \begin{center}
% \begin{tabular}{lcccc}
%     Flag                 & html  & pdf & fdf   & xfdf \\\hline
%     Include/Exclude      & *     & 0   &  *    &  *   \\
%     IncludeNoValueFields & *     & 0   &  *    &  *   \\
%     ExportFormat         & 1     & 0   &  0    &  0   \\
%     GetMethod            & *     & 0   &  0    &  0   \\
%     SubmitCoordinates    & *     & 0   &  0    &  0   \\
%     XFDF                 & 0     & 0   &  0    &  1   \\
%     IncludeAppendSaves   & 0     & 0   &  *    &  0   \\
%     IncludeAnnotations   & 0     & 0   &  *    &  0   \\
%     SubmitPDF            & 0     & 1   &  0    &  0   \\
%     CanonicalFormat      & *     & 0   &  *    &  *   \\
%     ExclNonUserAnnots    & 0     & 0   &  *    &  0   \\
%     ExclFKey             & 0     & 0   &  *    &  0   \\
%     EmbedForm            & 0     & 0   &  *    &  0   \\%
% \end{tabular}
% \end{center}
%
% \bigskip
% \subsection{Commands}
% \begin{function}{\pdffield_reset_new:nn}
% \begin{syntax}
% \cs{pdffield_reset_new:nn}\Arg{name}\Arg{key val list}
% \end{syntax}
% This defines an new reset action with the name \meta{name}.
% The keys are described below.
% \end{function}
%
% \begin{function}{\pdffield_submit_new:nnn}
% \begin{syntax}
% \cs{pdffield_submit_new:nn}\Arg{name}\Arg{key val list}\Arg{URL}
% \end{syntax}
% This defines an submit action with the name \meta{name}.
% The keys are described below. \meta{URL} should be given verbatim.
% That means \#  and \% should not be escaped. The URL should be
% correctly percent encoded, or the |urlencode| key should
% be used then the code will create the percent encoding.
%
% \meta{URL} can be a mail address and should then start with |mailto:|.
% A subject can be attached with |?subject=...|.
% This normally works quite fine as it only needs a correctly working mail program.
% (But for some unknown reason my mail program don't like mail addresses with hyphens in them).
%
% Alternatively it should be an URL of a script, which should return the correct
% answer (which one this is, is rather unclear).
%
% \end{function}
%
% \subsection{Keys for the commands to create actions}
% \begin{function}{fields}
% \begin{syntax}
% |fields| = \Arg{comma list of fully qualified field names}
% \end{syntax}
% |fields| is a comma list of \emph{fully qualified} field names, typically this can
% be the short name set with |name| in a field declaration, but in complex fieldsets
% it is needed to include the parents in the name too, separated by periods.
% If |exclude| is set, this list describes the fields that should
% be excluded from the reset or the submission.
% The default is |include|: the list describes the fields
% to reset or submit. Descendant of fields are reset or submitted too!
%
% The key is relevant for reset and submit actions.
% \end{function}
%
% \begin{function}{include, exclude}
% \begin{syntax}
% |include| \\
% |exclude|
% \end{syntax}
% These keys are shorthands to unset/set the |Include/Exclude| flag and decide
% if the list of fields in the |fields| key are included or
% excluded. The default is |include|: the list describes the fields
% to reset or submit.
%
% The keys are relevant for reset and submit actions.
% \end{function}

% \begin{function}{urlencode}
% \begin{syntax}
% |urlencode| = |true|\verb+|+|false|
% \end{syntax}
% When this is true the code will percent encode the submission URL.
% This is needed if the URL contains for example non-ascii chars or spaces.
% \end{function}
%
% \begin{function}{setsubmitflags,setFlags,unsetsubmitflags,unsetFlags}
%  \begin{syntax}
%   |setsubmitflags| = \Arg{comma list of flags}\\
%   |setFlags| = \Arg{comma list of flags}\\
%   |unsetsubmitflags| = |all| \verb"|" \Arg{comma list of flags}\\
%   |unsetFlags| = |all| \verb"|" \Arg{comma list of flags}
%  \end{syntax}
% These keys accept a list of flag names and then sets or unsets them, the resulting value
% is then used with the \texttt{/Flags} key of a submit action. |Include/Exclude|
% is also used by a reset action andcan also be set with the |exclude| and |include|
% keys.  Depending on the export type of the submit action some flags are set by the code.
% See the tabular above for details.
% The flag name can be given in PDF spelling (\texttt{IncludeNoValueFields}),
% in lowercase (\texttt{includenovaluefields}), and as number. |unsetFlags| and its
% alias |unsetsubmitflags|  know the special value |all| which clears all the fields.
%
% The list of flags are:
% |Include/Exclude|, |IncludeNoValueFields|, |ExportFormat|, |GetMethod|,
% |SubmitCoordinates|, |XFDF|, |IncludeAppendSaves|, |IncludeAnnotations|,
% |SubmitPDF|, |CanonicalFormat|, |ExclNonUserAnnots|, |ExclFKey|, |EmbedForm|
% \end{function}
%
% \begin{function}{next}
% \begin{syntax}
% |next| = \meta{object reference}
% \end{syntax}
% This allows to add a follow up action to the |/Next| key. The value is expanded, so can
% be given as |\pdf_object_ref:n{name}| and point to a suitable object.
% \end{function}
%
% \subsection{Keys for fields}
% With the following keys actions can be attached to the annotation of a form field,
% for example a pushbutton.
%
% \begin{function}{reset,submit}
% \begin{syntax}
% |reset|  = \meta{name}\\
% |submit| = \meta{name}
% \end{syntax}
% This adds the reset or submit action \meta{name} as action to the annotation.
% The action should be
% been defined first. The actions are mutually exclusive, only one action can
% be added. If more actions are needed use the |next| key.
% For reset the default value |all| exists and it is used if the key is used
% without value.
% \end{function}
%
% \begin{function}{import}
% \begin{syntax}
% |import| = \meta{file name}
% \end{syntax}
% This adds an import action to the annotation. \meta{file name} should
% be for example the name of a |.fdf| file. If the name contains a path use a
% slash as separator. non-ascii chars should work, but ascii is safer.
% The action is mutually exclusive to submit and reset.
% \end{function}
% \end{documentation}
%
% \begin{implementation}
% \DoNotIndex
%  {\\
%  ,\%,\#
% ,\bitset_clear:N
% ,\bitset_new:Nn
% ,\bitset_set_false:Nn
% ,\bitset_set_true:Nn
% ,\bitset_to_arabic:N
% ,\bitset_item:Nn
% ,\bool_new:N
% ,\bool_if:NTF
% ,\box_dp:N
% ,\box_ht:N
% ,\l_tmpa_box
% ,\char_set_catcode_other:N
% ,\clist_map_inline:nn
% ,\color_export:nnN
% ,\color_set:nn
% ,\color_set:nnn
% ,\cs_new_protected:Npn
% ,\cs_new_protected:cpn
% ,\cs_set_eq:NN
% ,\cs_gset_eq:cN
% ,\cs_if_exist:cTF
% ,\cs_set_protected:Npn
% ,\cs_generate_variant:Nn
% ,\cs_gset_eq:NN
% ,\csname
% ,\dim_eval:n
% ,\dim_new:N
% ,\dim_set:N
% ,\endcsname
% ,\exp_args:Ne
% ,\exp_args:Nne
% ,\exp_args:Ne
% ,\fboxsep
% ,\group_begin:
% ,\group_end:
% ,\hbox_to_wd:nn
% ,\hbox_set:Nn
% ,\hfill
% ,\hook_gput_code:nnn
% ,\int_eval:n
% ,\int_gincr:N
% ,\int_new:N
% ,\int_use:N
% ,\l_keys_choice_int
% ,\keys_define:nn
% ,\keys_set:nn
% ,\mode_leave_vertical:
% ,\makebox
% ,\msg_error:nnn
% ,\msg_error:nnnn
% ,\msg_new:nnn
% ,\msg_warning:nn
% ,\msg_warning:nnn
% ,\msg_warning:nnnnn
% ,\msg_warning:nnnn
% ,\NeedsTeXFormat
% ,\normalsize
% ,\pdf_name_from_unicode_e:n
% ,\pdf_object_if_exist:nTF
% ,\pdf_object_if_exist:nF
% ,\pdf_object_new:n
% ,\pdf_object_ref:n
% ,\pdf_object_ref_last:
% ,\pdf_object_unnamed_write:nn
% ,\pdf_object_unnamed_write:ne
% ,\pdf_object_write:nnn
% ,\pdf_string_from_unicode:nnN
% ,\pdfannot_box_ref_last:
% ,\pdfannot_dict_put:nnn
% ,\pdfannot_dict_put:nne
% ,\pdfannot_dict_remove:nn
% ,\pdfannot_widget_box:nnn
% ,\pdfdict_if_empty:nTF
% ,\pdfdict_get:nnN
% ,\pdfdict_new:n
% ,\pdfdict_put:nnn
% ,\pdfdict_remove:nn
% ,\pdfdict_use:n
% ,\pdfdict_put:nne
% ,\pdfmanagement_add:nnn
% ,\pdfmeta_standard_verify:nTF
% ,\pdfxform_if_exist:nTF
% ,\pdfxform_new:nnn
% ,\pdfxform_ref:n
% ,\phantom
% ,\prg_do_nothing:
% ,\ProvidesExplPackage
% ,\rule
% ,\seq_gput_right:Nn
% ,\seq_if_exist:NTF
% ,\seq_new:N
% ,\seq_use:Nn
% ,\seq_clear:N
% ,\seq_put_right:NV
% ,\str_if_empty:NTF
% ,\str_if_in:NnTF
% ,\str_new:N
% ,\strut
% ,\strutbox
% ,\tl_if_empty:NTF
% ,\tl_if_empty:NT
% ,\tl_if_empty:NF
% ,\tl_put_left:Nn
% ,\tl_if_empty:nTF
% ,\tl_if_head_eq_charcode:nNTF
% ,\tl_put_right:Nn
% ,\tl_new:N
% ,\tl_set:Nn
% ,\tl_to_str:n
% ,\tl_const:cn
% ,\tl_use:c
% ,\use:c
%   }
% \section{\pkg{l3pdffield-action} Implementation}
%    \begin{macrocode}
%<*package>
%<@@=pdffield>
%    \end{macrocode}
% \subsection{Messages}
%    \begin{macrocode}
\msg_new:nnn {pdffield}{action-name-undefined}
  {
    The~'#1'~action~name~'#2'~is~not~defined~and~
    will~be~ignored.
  }

%    \end{macrocode}
% \subsection{Variables}
% \begin{variable}
%  {
%     ,\l_@@_action_export_tl
%     ,\l_@@_action_Fields_seq
%     ,\l_@@_action_next_tl
%  }
% We need to store the export, fields and next value into variables.
%    \begin{macrocode}
\tl_new:N  \l_@@_action_export_tl
\seq_new:N \l_@@_action_Fields_seq
\tl_new:N  \l_@@_action_next_tl
%    \end{macrocode}
% \end{variable}
% \subsection{dictionaries}
% \begin{macro}{l_@@/ResetForm,l_@@/SubmitForm}
%  We define two dictionaries to handle the reset and submit code.
%    \begin{macrocode}
\pdfdict_new:n   {l_@@/ResetForm}
\pdfdict_put:nnn {l_@@/ResetForm}{Type}{/Action}
\pdfdict_put:nnn {l_@@/ResetForm}{S}{/ResetForm}
\pdfdict_new:n   {l_@@/SubmitForm}
\pdfdict_put:nnn {l_@@/SubmitForm}{Type}{/Action}
\pdfdict_put:nnn {l_@@/SubmitForm}{S}{/SubmitForm}
%    \end{macrocode}
% \end{macro}
% \subsection{bitset for submit action}
% \begin{variable}{\l_@@_Flags_bitset}
% A bitset for the submit (and the one reset) flags:
%    \begin{macrocode}
\bitset_new:Nn \l_@@_Flags_bitset
  {
     Include/Exclude      = 1
    ,IncludeNoValueFields = 2
    ,ExportFormat         = 3
    ,GetMethod            = 4
    ,SubmitCoordinates    = 5
    ,XFDF                 = 6
    ,IncludeAppendSaves   = 7
    ,IncludeAnnotations   = 8
    ,SubmitPDF            = 9
    ,CanonicalFormat      = 10
    ,ExclNonUserAnnots    = 11
    ,ExclFKey             = 12
    ,EmbedForm            = 14
    ,include/exclude      = 1
    ,includenovaluefields = 2
    ,exportformat         = 3
    ,getmethod            = 4
    ,submitcoordinates    = 5
    ,xfdf                 = 6
    ,includeappendsaves   = 7
    ,includeannotations   = 8
    ,submitpdf            = 9
    ,canonicalformat      = 10
    ,exclnonuserannots    = 11
    ,exclfkey             = 12
    ,embedform            = 14
  }
%    \end{macrocode}
% \end{variable}
% \begin{macro}
%  {
%   \@@_action_flags_pdf:
%   ,\@@_action_flags_html:
%   ,\@@_action_flags_fdf:
%   ,\@@_action_flags_xfdf:
%  }
% The following commands sets the forced flags for the export options.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_action_flags_pdf:
  {
    \bitset_clear:N \l_@@_Flags_bitset
    \bitset_set_true:Nn \l_@@_Flags_bitset { SubmitPDF }
  }

\cs_new_protected:Npn \@@_action_flags_html:
  {
    \bitset_set_true:Nn \l_@@_Flags_bitset { ExportFormat }
    \bitset_set_false:Nn \l_@@_Flags_bitset { XFDF }
    \bitset_set_false:Nn \l_@@_Flags_bitset { IncludeAppendSaves }
    \bitset_set_false:Nn \l_@@_Flags_bitset { IncludeAnnotations }
    \bitset_set_false:Nn \l_@@_Flags_bitset { SubmitPDF }
    \bitset_set_false:Nn \l_@@_Flags_bitset { ExclNonUserAnnots }
    \bitset_set_false:Nn \l_@@_Flags_bitset { ExclFKey }
    \bitset_set_false:Nn \l_@@_Flags_bitset { EmbedForm }
  }

\cs_new_protected:Npn \@@_action_flags_fdf:
  {
    \bitset_set_false:Nn \l_@@_Flags_bitset { ExportFormat }
    \bitset_set_false:Nn \l_@@_Flags_bitset { GetMethod }
    \bitset_set_false:Nn \l_@@_Flags_bitset { SubmitCoordinates }
    \bitset_set_false:Nn \l_@@_Flags_bitset { XFDF }
    \bitset_set_false:Nn \l_@@_Flags_bitset { SubmitPDF }
  }

\cs_new_protected:Npn \@@_action_flags_xfdf:
  {
    \bitset_set_false:Nn \l_@@_Flags_bitset { ExportFormat }
    \bitset_set_false:Nn \l_@@_Flags_bitset { GetMethod }
    \bitset_set_false:Nn \l_@@_Flags_bitset { SubmitCoordinates }
    \bitset_set_true:Nn \l_@@_Flags_bitset { XFDF }
    \bitset_set_false:Nn \l_@@_Flags_bitset { IncludeAppendSaves }
    \bitset_set_false:Nn \l_@@_Flags_bitset { IncludeAnnotations }
    \bitset_set_false:Nn \l_@@_Flags_bitset { SubmitPDF }
    \bitset_set_false:Nn \l_@@_Flags_bitset { ExclNonUserAnnots }
    \bitset_set_false:Nn \l_@@_Flags_bitset { ExclFKey }
    \bitset_set_false:Nn \l_@@_Flags_bitset { EmbedForm }
  }
%    \end{macrocode}
% \end{macro}
% \subsection{Keys}
% \begin{macro}{reset,submit,import}
% These are the three additional keys for the field annotations
%    \begin{macrocode}
\keys_define:nn { pdffield }
  {
    reset .code:n =
      {
        \cs_if_exist:cTF { @@_action_reset_#1: }
          {
            \use:c { @@_action_reset_#1: }
            \pdfannot_dict_put:nne{widget}
             {A}
             {\tl_use:c { c_@@_action_reset_#1_tl } }
          }
          {
            \msg_warning:nnnn{pdffield}{action-name-undefined}{reset}{#1}
          }
      }
   ,reset .default:n = all
  }

\keys_define:nn { pdffield }
  {
    submit .code:n =
      {
        \cs_if_exist:cTF { @@_action_submit_#1: }
          {
            \use:c { @@_action_submit_#1: }
            \pdfannot_dict_put:nne{widget}
             {A}
             {\tl_use:c { c_@@_action_submit_#1_tl } }
          }
          {
            \msg_warning:nnnn{pdffield}{action-name-undefined}{submit}{#1}
          }
      }
  }

\keys_define:nn { pdffield }
  {
    import .code:n =
      {
        \pdf_string_from_unicode:nnN {utf8/string}{#1}\l_@@_tmpa_str
        \pdf_object_unnamed_write:ne {dict}{/Type/Action/S/ImportData/F\l_@@_tmpa_str}
        \pdfannot_dict_put:nne{widget}
          {A}
          {\pdf_object_ref_last: }
      }
  }

%    \end{macrocode}
% \end{macro}
% \begin{macro}{fields,exclude,include,export,charset,urlencode,next}
% These are keys used when defining the actions.
%    \begin{macrocode}
\keys_define:nn { pdffield / action }
  {
    fields .code:n  =
      {
        \clist_map_inline:nn {#1}
          {
            \pdf_string_from_unicode:nnN {utf8/string}{##1}\l_@@_tmpa_str
            \seq_put_right:NV\l_@@_action_Fields_seq \l_@@_tmpa_str
          }
      }
    ,exclude .code:n = { \bitset_set_true:Nn \l_@@_Flags_bitset {Include/Exclude }}
    ,include .code:n = { \bitset_set_false:Nn \l_@@_Flags_bitset {Include/Exclude }}
    ,export .choices:nn = {pdf,fdf,html,xfdf}
      {
        \tl_set:Nn \l_@@_action_export_tl {#1}
      }
    ,export .initial:n = {html}
    ,charset .choices:nn =
      {utf-8, utf-16, Shift-JIS, BigFive, GBK, UHC}
      { \pdfdict_put:nnn { l_@@/SubmitForm }{#1} }
    ,urlencode .bool_set:N = \l_@@_url_encode_bool
    ,next .tl_set:N = \l_@@_action_next_tl
 }
%    \end{macrocode}
% \end{macro}
% \begin{macro}{setFlags,setsubmitflags,unsetFlags,unsetsubmitflags}
%    \begin{macrocode}
\keys_define:nn { pdffield / action }
  {
    ,setFlags .code:n =
      {
        \clist_map_inline:nn {#1}
          {
            \bitset_set_true:Nn \l_@@_Flags_bitset {##1}
          }
      }
    ,setsubmitflags .meta:n = {setFlags={#1}}
    ,unsetFlags .multichoice:
    ,unsetFlags / all .code:n = { \bitset_clear:N \l_@@_Flags_bitset}
    ,unsetFlags / unknown .code:n =
      {
        \bitset_set_false:Nn \l_@@_Flags_bitset {#1}
      }
    ,unsetsubmitflags .meta:n = {unsetFlags={#1}}
  }
%    \end{macrocode}
% \end{macro}
%
% \subsection{New reset action}
%
% \begin{macro}{ \@@_action_reset_new:nn }
% The command defines a command which will setup the dictionary at first use,
% and then store the reference in a constant.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_action_reset_new:nn #1 #2 %#1 name, #2 keyval
  {
    \cs_new_protected:cpn {@@_action_reset_#1:}
      {
        \group_begin:
        \seq_clear:N \l_@@_action_Fields_seq
        \keys_set:nn { pdffield / action }{ #2 }
        \pdf_object_unnamed_write:ne
          { array }
          { \seq_use:Nn \l_@@_action_Fields_seq {~} }
        \tl_if_empty:NF \l_@@_action_next_tl
          {
            \pdfdict_put:nne {l_@@/ResetForm}{Next}{\l_@@_action_next_tl}
          }
        \pdfdict_put:nne
          { l_@@/ResetForm }
          { Fields }
          { \pdf_object_ref_last: }
        \pdfdict_put:nne
          { l_@@/ResetForm }
          { Flags }
          { \bitset_item:Nn\l_@@_Flags_bitset{Include/Exclude} }
        \pdf_object_unnamed_write:ne
          { dict }
          { \pdfdict_use:n{l_@@/ResetForm} }
        \tl_const:ce { c_@@_action_reset_#1_tl } { \pdf_object_ref_last: }
        \cs_gset_eq:cN {@@_action_reset_#1:} \prg_do_nothing:
        \group_end:
      }
  }

\@@_action_reset_new:nn  {all}{fields={},exclude}
%    \end{macrocode}
% \end{macro}
%
% \subsection{New submit action}
% \begin{macro}{\@@_action_submit_new:nn}
% Quite similar to the reset command, only that we have to use an auxiliary
% to grab the URL with suitable catcodes.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_action_submit_new:nn #1 #2 %#1 name, #2 keyval
  {
    \group_begin:
    \char_set_catcode_other:N \%
    \char_set_catcode_other:N \#
    \@@_action_submit_new:nnn {#1}{#2}
  }
\cs_new_protected:Npn \@@_action_submit_new:nnn #1 #2 #3 %#1 name, #2 keyval, #3 url
  {
    \group_end:
    \cs_new_protected:cpn {@@_action_submit_#1:}
      {
        \group_begin:
        \seq_clear:N    \l_@@_action_Fields_seq
        \bitset_clear:N \l_@@_Flags_bitset
        \keys_set:nn {pdffield/action}{#2}
        \use:c{ @@_action_flags_\l_@@_action_export_tl :}
        \pdfdict_put:nne
          { l_@@/SubmitForm }
          { Flags }
          { \bitset_to_arabic:N \l_@@_Flags_bitset }
        \tl_if_empty:NF \l_@@_action_next_tl
          {
            \pdfdict_put:nne {l_@@/SubmitForm}{Next}{\l_@@_action_next_tl}
          }
        \bool_if:NTF \l_@@_url_encode_bool
          { \pdf_string_from_unicode:nnN { utf8/URI }   {#3}\l_@@_tmpa_str }
          { \pdf_string_from_unicode:nnN { utf8/string }{#3}\l_@@_tmpa_str }
        \pdf_object_unnamed_write:ne {dict}
          {
            /FS/URL
            /F \l_@@_tmpa_str
          }
        \pdfdict_put:nne
          { l_@@/SubmitForm }
          { F }
          { \pdf_object_ref_last: }
        \pdf_object_unnamed_write:ne
          { dict }
          { \pdfdict_use:n{ l_@@/SubmitForm } }
        \tl_const:ce { c_@@_action_submit_#1_tl } { \pdf_object_ref_last: }
        \cs_gset_eq:cN { @@_action_submit_#1: } \prg_do_nothing:
        \group_end:
      }
  }

%    \end{macrocode}
% \end{macro}
%
% \subsection{User commands}
% \begin{macro}{\pdffield_reset_new:nn, \pdffield_submit_new:nnn}
%    \begin{macrocode}
\cs_set_eq:NN \pdffield_reset_new:nn   \@@_action_reset_new:nn
\cs_set_eq:NN \pdffield_submit_new:nnn \@@_action_submit_new:nn
%</package>
%    \end{macrocode}
% \end{macro}
%\end{implementation}

% \PrintIndex
