summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-action.dtx
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2021-06-15 03:01:03 +0000
committerNorbert Preining <norbert@preining.info>2021-06-15 03:01:03 +0000
commit2faf2507ca4d1d6d153f4c2b4c4c78479d459f06 (patch)
treee0f2305625e9b7254276aac23ed0253b6a6c0f60 /macros/latex/contrib/pdfmanagement-testphase/l3pdffield-action.dtx
parent269940e8e52b921a855083542b9e1109af49af09 (diff)
CTAN sync 202106150301
Diffstat (limited to 'macros/latex/contrib/pdfmanagement-testphase/l3pdffield-action.dtx')
-rw-r--r--macros/latex/contrib/pdfmanagement-testphase/l3pdffield-action.dtx813
1 files changed, 813 insertions, 0 deletions
diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-action.dtx b/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-action.dtx
new file mode 100644
index 0000000000..74362cc9a8
--- /dev/null
+++ b/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-action.dtx
@@ -0,0 +1,813 @@
+% \iffalse meta-comment
+%
+%% File: l3pdfpdffield-action.dtx
+%
+% Copyright (C) 2021 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 testphase 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>
+\RequirePackage{pdfmanagement-testphase}
+\DeclareDocumentMetadata{}
+\makeatletter
+\declare@file@substitution{doc.sty}{doc-v3beta.sty}
+\makeatother
+\documentclass[full]{l3doc}
+\usepackage{array,booktabs,siunitx}
+\usepackage{l3pdffield-testphase,bearwear}
+\hypersetup{pdfauthor=The LaTeX Project,
+ pdftitle=l3pdffield (LaTeX PDF management testphase 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 testphase 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.95e, released 2021-06-14}
+%
+% \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:nx{stream}
+% {
+% {}
+% {
+% var~f_netto = this.getField("netto");
+% event.value = 1.19*f_netto.value;
+% }
+% }
+% \tl_set:Nx\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 programm.
+% (But for some unknown reason my mail program don't like mail addresses with hyphens in them).
+%
+% Alternativly 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:Nnx
+% ,\exp_args:Nx
+% ,\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:nn
+% ,\pdf_object_ref:n
+% ,\pdf_object_ref_last:
+% ,\pdf_object_unnamed_write:nn
+% ,\pdf_object_unnamed_write:nx
+% ,\pdf_object_write:nn
+% ,\pdf_string_from_unicode:nnN
+% ,\pdfannot_box_ref_last:
+% ,\pdfannot_dict_put:nnn
+% ,\pdfannot_dict_put:nnx
+% ,\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:nnx
+% ,\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:nnx{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:nnx{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:nx {dict}{/Type/Action/S/ImportData/F\l_@@_tmpa_str}
+ \pdfannot_dict_put:nnx{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:nx
+ { array }
+ { \seq_use:Nn \l_@@_action_Fields_seq {~} }
+ \tl_if_empty:NF \l_@@_action_next_tl
+ {
+ \pdfdict_put:nnx {l_@@/ResetForm}{Next}{\l_@@_action_next_tl}
+ }
+ \pdfdict_put:nnx
+ { l_@@/ResetForm }
+ { Fields }
+ { \pdf_object_ref_last: }
+ \pdfdict_put:nnx
+ { l_@@/ResetForm }
+ { Flags }
+ { \bitset_item:Nn\l_@@_Flags_bitset{Include/Exclude} }
+ \pdf_object_unnamed_write:nx
+ { dict }
+ { \pdfdict_use:n{l_@@/ResetForm} }
+ \tl_const:cx { 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:nnx
+ { l_@@/SubmitForm }
+ { Flags }
+ { \bitset_to_arabic:N \l_@@_Flags_bitset }
+ \tl_if_empty:NF \l_@@_action_next_tl
+ {
+ \pdfdict_put:nnx {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:nx {dict}
+ {
+ /FS/URL
+ /F \l_@@_tmpa_str
+ }
+ \pdfdict_put:nnx
+ { l_@@/SubmitForm }
+ { F }
+ { \pdf_object_ref_last: }
+ \pdf_object_unnamed_write:nx
+ { dict }
+ { \pdfdict_use:n{ l_@@/SubmitForm } }
+ \tl_const:cx { 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