From ff5439d00ba53d3e4b82d79f78ce65524f3684fd Mon Sep 17 00:00:00 2001
From: Norbert Preining <norbert@preining.info>
Date: Sat, 15 May 2021 03:01:02 +0000
Subject: CTAN sync 202105150301

---
 .../contrib/pdfmanagement-testphase/l3pdffield.dtx | 1921 +++++++++++++-------
 1 file changed, 1298 insertions(+), 623 deletions(-)

(limited to 'macros/latex/contrib/pdfmanagement-testphase/l3pdffield.dtx')

diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3pdffield.dtx b/macros/latex/contrib/pdfmanagement-testphase/l3pdffield.dtx
index dc3fcc3df6..e1e5f8bae1 100644
--- a/macros/latex/contrib/pdfmanagement-testphase/l3pdffield.dtx
+++ b/macros/latex/contrib/pdfmanagement-testphase/l3pdffield.dtx
@@ -1,6 +1,6 @@
 % \iffalse meta-comment
 %
-%% File: l3pdfpdffield-checkbox.dtx
+%% File: l3pdffield.dtx
 %
 % Copyright (C) 2021 The LaTeX Project
 %
@@ -28,9 +28,9 @@
 \makeatletter
 \declare@file@substitution{doc.sty}{doc-v3beta.sty}
 \makeatother
-\documentclass[full]{l3doc}
-\usepackage{array,booktabs}
-\usepackage{l3pdffield-testphase,bearwear}
+\documentclass{l3doc}
+\usepackage{array,booktabs,caption}
+\usepackage{l3pdffield-testphase,tikz}
 \hypersetup{pdfauthor=The LaTeX Project,
  pdftitle=l3pdffield (LaTeX PDF management testphase bundle)}
 \begin{document}
@@ -43,17 +43,22 @@
 %   idxtype = {checkbox key},
 %   printtype= \textit{checkbox key}
 %    ]{Checkboxkey}{checkboxkey}
+%  \NewDocElement[
+%   idxgroup=field keys,
+%   idxtype = {field key},
+%   printtype= \textit{field key}
+%    ]{Fieldkey}{fieldkey}
+%  \NewDocElement[
+%   idxgroup=setup keys,
+%   idxtype = {setup key},
+%   printtype= \textit{setup key}
+%    ]{Fieldsetupkey}{fieldsetupkey}
+%  \NewDocElement[
+%   idxgroup=annot keys,
+%   idxtype = {annot key},
+%   printtype= \textit{annot key}
+%    ]{Annotkey}{annotkey}%
 % \providecommand\hook[1]{\texttt{#1}}
-% \ExplSyntaxOn
-% \pdffield_store_appearance:nn {bear/Yes}
-%  {
-%    \tikz\bear\bearwear[shirt=red,body~deco={\node[font=\tiny\bfseries,white]~at~(beartummy){Yes};}];
-%  }
-% \pdffield_store_appearance:nn {bear/Off}
-%  {
-%   \tikz\bear\bearwear[body~deco={\node[font=\tiny\bfseries,white]~at~(beartummy){Off};}];
-%  }
-% \ExplSyntaxOff
 % \title{^^A
 %   The \pkg{l3pdffield} module\\ Commands to create form fields   ^^A
 %   \\ \LaTeX{} PDF management testphase bundle
@@ -68,36 +73,50 @@
 %    }^^A
 % }
 %
-% \date{Version 0.95c, released 2021-03-17}
+% \date{Version 0.95d, released 2021-05-14}
 %
 % \maketitle
 % \begin{documentation}
 % \section{\pkg{l3pdffield} Introduction}
-% The implementation of form fields in hyperref has some bugs, see for example
-% \url{https://github.com/latex3/hyperref/issues/94}. This package is a first step
+% The implementation of form fields in hyperref has some bugs\footnote{see for example
+% \url{https://github.com/latex3/hyperref/issues/94}}. This package is a first step
 % towards the goal to review and improve the code of form fields.
 %
 % Like the \pkg{pdfmanagement-testphase} package itself it is a temporary package:
-% the definite home of the code is not yet decided.
+% the definite home of the code is not yet decided, and during the development
+% changes in the interfaces are possible.
 %
-% It handles for now \emph{only} checkboxes, other form fields like pushbutton,
-% radio buttons or text fields will follow later. As currently no fonts are used,
-% it doesn't relies on the hyperref code
-% to initialize the form, but it can be used with hyperref.
+% The package itself is currently loaded with
+% \begin{verbatim}
+% \usepackage{l3pdffield-testphase}
+% \end{verbatim}
 %
-% The code requires the new PDF management. The code makes use of
-% \pkg{l3pdfxform} to create the Xobjects. This code doesn't support yet the
-% the dvips backend.
+% The code is splitted into various submodules. \texttt{l3pdffield}
+% contains the basic commands to create a form field. The code related to field types
+% like checkboxes are in \texttt{l3pdffield-\emph{type}}, for example
+% \texttt{l3pdffield-checkbox}. Currently only checkboxes have been implemented,
+% other form fields like pushbutton,
+% radio buttons or text fields will follow later.
+% The code doesn't rely on to initialize the form,
+% but it can be used with hyperref.
 %
+% The code requires the new PDF management. The code makes use of
+% \pkg{l3pdfxform} to create the form Xobjects of the appearances.
+% This code doesn't support yet the the dvips backend.
 %
+% The code targets PDF~2.0. This doesn't mean that it won't work in older
+% PDF versions, but it tries to implement requirements needed or recommended
+% for 2.0; most importantly appearances are used by default everywhere and it
+% deprecates |/NeedAppearances|.
 %
 % Please keep in mind
 % \begin{itemize}
-% \item Not every PDF viewer supports checkboxes.
+% \item Not every PDF viewer supports form fields or all types and features.
 % \item The handling can depend on settings in the PDF viewer. In adobe reader for
 % example I had to disable an option to avoid that it tries to create an appearance
-% itself
-% \item Standards like pdf/A disable form fields too (as you typically can't change the PDF).
+% itself.
+% \item Standards like pdf/A disable some features of form fields like javascript actions
+%  (as you typically can't change the PDF).
 % \end{itemize}
 %
 % If \pkg{hyperref} is loaded before
@@ -115,258 +134,636 @@
 % \begin{document}
 % \Form
 % \end{verbatim}
-% \section{Step 1: Checkboxes}
-% Click me:
-% \ExplSyntaxOn\pdffield_checkbox:n{name=bear,appearance=bear,width=23pt,height=30pt,depth=10pt}\ExplSyntaxOff
 %
-% \bigskip
-% \subsection{Commands}
-% \begin{function}{\pdffield_checkbox:n}
+% \section{Some background}
+%
+% A document can contain a arbitrary number of fields which can be organized in trees.
+% The leaf fields in such a tree, the \emph{terminal fields}, typically have
+% widget annotations as kids which are then the actual, visual instances of the field,
+% and allow to interact with the field. I will call such a
+% tree a \emph{fieldset}, nodes \emph{fields} and the widget annotation
+% \emph{field annotations}.
+%
+% If a field has only one child annotation the content of the field dictionary and the
+% widget annotation dictionary can be merged---some examples in the PDF reference
+% show such merged dictionaries---but the code here keeps them separate, at the end
+% this is clearer.
+%
+% A simple example would look like this
+%
+%  \begin{tikzpicture}[level 2/.style={level distance=7mm},
+%  level 1/.style={sibling distance=25mm},
+%  level 2/.style={sibling distance=15mm}]
+%   \node[draw] {week}
+%   child {node[draw] {mon}
+%           child {node[draw,dashed] {annot}}
+%         }
+%   child {node[draw] {tue}
+%          child {node[draw,dashed] {annot}}
+%         }
+%   child {node[draw] {wen}
+%           child {node[draw,dashed] {annot}}
+%           child {node[draw,dashed] {annot}}
+%         }
+%   ;
+%   \end{tikzpicture}
+%
+% In many cases a fieldset consists of only one field along with its field annotation(s),
+% but larger sets can be needed to build more complex interactions with javascript code.
+% For example a datepicker can be built as a fieldset with various fields to represent
+% the month and year choice and to select days.
+%
+% Fields in a fieldset should have a name, for example |wen| or |week| in the example
+% above. This name is the \emph{partial name} of the field, the \emph{full name}
+% is than built from it by adding the names of the parents separated by periods.
+% In the example above the partial name is \texttt{mon} and the full name
+% \texttt{week.mon}.
+% Partial names shouldn't contain periods. If two fields have the same name they will
+% work in unison: if you enter text in one field, the text appears also in the other, such
+% fields must have the same type and the same value and default value entry.
+% If a field has no name it is considered to be a simple widget annotation and so
+% only another representation of its parent.
+%
+%
+% All terminal fields should also have a type, e.g. \texttt{Btn} for a button field,
+% or \texttt{Tx} for a textfield. The type can be set for the parent and then inherited.
+% The fields in a fieldset can have different types.
+%
+% \subsection{The look of a field: Appearances and other settings}
+%
+% The look of widget annotation of a field can be set with various keys. The keys developed over
+% time and some of them superseed older ones. There is for example the simple
+% |/Border|, the more sophisticated |/BS| (\enquote{border style dictionary}),
+% the \enquote{dynamic appearance dictionary} |MK|, with lots of keys,
+% and the appearance dictionary |/AP| which
+% may define as many as three separate appearances:
+% the normal appearance (required), the rollover appearance and the down appearance.
+% Such an appearance can be a simple form XObjects%
+%   \footnote{Such form XObjects are small pictures stored in the PDF which
+%       can be referenced in various part of the PDF. They can be
+%       created with the commands of the \pkg{l3pdfxform} package.}%
+% , but in some cases the annotation can have different \emph{appearance states}:
+% a checkbox
+% for example can be checked or unchecked, in this case the appearances
+% are dictionaries which
+% maps state names like |/Yes| and |/Off| to form XObjects.
+%
+% The annotations cover a rectangular area on
+% the page and form XObjects appearances are squeezed into this rectangle.
+% So for the best result
+% both should have the same ratio of width and height. Simple plain backgrounds can
+% also be created in large size and reused for various annotations.
+% Form XObjects used as appearances can not be rotated, if needed one has to
+% create a new appearance.
+%
+%
+% In PDF 2.0 widget annotations must have at least a normal |/AP| appearance
+% (unless the size  of the annotation is zero) and the keys \enquote{\itshape C, IC, Border,
+% BS, BE, BM, CA, ca, H, DA, Q,
+% DS, LE, LL, LLE, and Sy shall be ignored}. But it is quite unclear if
+% PDF Viewer honor this, and if this make sense e.g. for text fields which require
+% a DA entry. It is also not clear how appearances and the entries of the MK dictionary
+% are related in a form field.  Tests with some PDF viewers
+% are needed here.
+%
+%
+% \section{Commands}
+% \begin{function}{\pdffield_field:nn,\pdffield_field:Vn}
 % \begin{syntax}
-%  \cs{pdffield_checkbox:n}\Arg{key val list}
+%  \cs{pdffield_field:nn}\Arg{key val list}\Arg{field ID}
 % \end{syntax}
-% This creates a checkbox to check and uncheck. The list of allowed keys is described below.
-% Typically the \meta{key val list} should at least set the name. Checkboxes with the same
-% name belong to the same field and are checked and unchecked together. The default appearance
-% is a quadratic frame with a \cs{texttimes} in it for the checked case.
+% This creates a new field. \meta{field ID} will be used to create and
+% reference the needed objects but it is not the direct object name, so
+% |pdf_object_ref:n| can not be used to access (and there will not
+% clash with object names). It is recommended to start
+% the name with a module prefix to avoid name clashes, so e.g. |mymodule/field/1| or
+% |mymodule/field/week|.
+%
+% The list of handled keys is described below.
+% Typically the \meta{key val list} should at least set the name |T|, fields that
+% are kids in a fieldset must set the |parent| key, this should point to a field
+% declared before.
+%
+% The command is meant as a basic command to build more complex variants like
+% checkbox or textfields. For this reason it doesn't check if
+% the combination of values and flags are sensible, and it uses as key names the
+% names from the PDF reference.
+% If you create a button field (Btn) and set MaxLen (which is only known for text
+% fields), it will not complain.
+%
+% Root fields (fields without parent) are added automatically to the
+% Catalog/AcroForm dictionary with
+%
+%
+% \begin{verbatim}
+% \pdfmanagement_add:nnx{Catalog/AcroForm}{Fields}{<obj ref>}
+% \end{verbatim}
+%
 % \end{function}
 %
-%\begin{function}{\pdffield_setup:nn}
+% \begin{function}{\pdffield_annot:n,\pdffield_annot:V}
 % \begin{syntax}
-%  \cs{pdffield_setup:nn}\Arg{field type}\Arg{key val list}
+%  \cs{pdffield_field:nn}\Arg{key val list}
 % \end{syntax}
-% This allows to setup up values for following fields. \Arg{field type}
-% should be a field, currently the only allowed value is |checkbox|.
+% This creates a new field annotation.
+% It is a widget annotation box created with \cs{pdfannot_widget_box:nnn}, and
+% it is possible to add values to its dictionary
+% by using |\pdfannot_dict_put:nnn {widget}...|.
+% But to correctly setup the parent/kid relationship some additional wrapper code is needed.
+% The command also setup dictionaries to fill the |AP|, |MK| and |AA| dictionaries.
 % \end{function}
 %
-%\begin{function}{\pdffield_store_appearance:nn}
+% \begin{function}{\pdffield_appearance:nn}
 % \begin{syntax}
-%  \cs{pdffield_store_appearance:nn}\Arg{name/state}\Arg{content}
+%  \cs{pdffield_appearance:nn}\Arg{name}\Arg{content}
 % \end{syntax}
-% This is a small wrapper around \cs{pdfxform_new:nn} and store appearances for the fields.
-% \meta{state} should be for checkboxes either |Yes| or |Off| (and typically
-% you should define both). \meta{name} is the name
-% that is used in the |appearance| key, |checkbox/default| is predefined and so can't be used.
-% \meta{content} is arbitrary content. The dimensions should fit to the planed size of the
-% checkbox.%
+% This is a small wrapper around \cs{pdfxform_new:nnn} (which could be used too)
+% to create an appearance. To avoid name clashes \meta{name} should start with
+% a module part, e.g. |mymodule/appearance/cross|.
 % \end{function}
-% \subsection{Keys}
 %
-% The new checkbox commands accepts following keys:
+% \begin{function}{\pdffield_setup:n}
+% \begin{syntax}
+%  \cs{pdffield_setup:n}\Arg{key-val}
+% \end{syntax}
+% This command allows to preset some field settings.
+% \end{function}
+% It knows currently two keys:
 %
-% \DescribeCheckboxkey{name} This sets the (internal) name of the field. It shouldn't contain
-% a period, be not empty and sensibly consist of simple chars. Checkboxes instances
-% with the same name belong to the same field and are checked and unchecked together.
+% \begin{function}{create-style}
+% \begin{syntax}
+%  |create-style| = \Arg{name}\Arg{key-val}
+% \end{syntax}
+% This defines a style which can then be used with the |style| key.
+% \Arg{key-val} can be an arbitrary collection of the  keys of the module.
+% \end{function}
 %
-% \DescribeCheckboxkey{altname} This sets an alternative name for user interaction.
-% This name can only be set at the first checkbox instance, when the field is initialized.
-% \DescribeCheckboxkey{mappingname} This sets an alternative name for export.
-% This name can only be set at the first checkbox instance, when the field is initialized.
+% \begin{function}{preset-checkbox}
+% \begin{syntax}
+% |preset-checkbox|=\Arg{key-val}
+% \end{syntax}
+% This allows to set default keys for a checkbox.
+% \end{function}
+
+% \section{Field Keys}
+%
+% Table~\ref{tab:fieldkeys} summarize the keys which can be used.
+% A number of keys have two names, the second is normally the name used by hyperref.
+% Where is makes sense an empty value \enquote{unsets} a key.
+%
+% \begin{table}
+% \caption{Keys for fields}\label{tab:fieldkeys}
+% \centering
+% \begin{tabular}{>{\ttfamily}lllll}
+% \toprule
+% key      & value      & required & inheritable &remark\\\midrule
+% parent   & field ID & for non-root fields &     \\
+% style    & style name &                   & defined with |create-style| \\
+% T, name        & string   & mostly   &             \\
+% TU, altname       & string   &          &             \\
+% TM, mappingname       & string   &          &             \\
+% FT       & name     & terminal fields & yes  \\
+% setFf,    & list of flags &     & yes\\
+% setfieldflags\\
+% unsetFf,  & list of flags &    & yes \\
+% unsetfieldflags \\
+% V        & various   &        & yes \\
+% DV       & various   &        & yes \\
+% MaxLen   & integer   & with Comb   & yes             & only textfields\\
+% Lock     & object name &         &                  & signature field\\
+% SV       & object name &         &                  & signature field\\
+% Opt      & object name &         &                  & buttons and choice fields\\
+% TI       & integer    &          &                  & list fields\\
+% I        & object name&          &                  & list fields\\
+% AA/K, keystroke     & javascript \\
+% AA/F, format     & javascript\\
+% AA/V, validate     & javascript\\
+% AA/C, calculate     & javascript\\
+% DA        & string    & yes   &   yes    & variable text \\
+% Q       & 0, 1 or 2   &          & yes   &variable text  \\
+% DS       &    &          &         & (ignored) \\
+% RV       &  &  &        & (ignored) \\\bottomrule
+% \end{tabular}
+% \end{table}
+%
+% \begin{function}{parent}
+%  \begin{syntax}
+%   |parent| = \meta{field ID}\\
+%  \end{syntax}
+% This declares the parent of the field. It is required if
+% the field is not the root of the fieldset. The value is the field ID
+% of the parent, the parent should have been already declared.
+% It will add the reference to the parent field to the |/Parent| key, and also
+% add reference of the kid as |/Kid| in the parent field.
+% \end{function}
 %
-% \DescribeCheckboxkey{width}
-% \DescribeCheckboxkey{height}
-% \DescribeCheckboxkey{depth} These keys allow to set the dimensions of checkbox instance.
-% The value should be a command that expands to a dimension expression. By default
-% |width| and |height| use \cs{normalbaselineskip}, the |depth| is zero.
-%
-% \DescribeCheckboxkey{appearance} This key sets the normal appearance. It takes as value a
-% \meta{name} and expects that the two appearances \meta{name}|/Yes| and \meta{name}|/Off|
-% has been created with the command described below. The initial value is |checkbox/default|
-% and shows a \cs{texttimes}.
-%
-% \DescribeCheckboxkey{rollover-appearance} This key sets the rollover appearance (when the
-% mouse hovers over the checkbox). It takes as value a
-% \meta{name} and expects that the two appearances \meta{name}|/Yes| and \meta{name}|/Off|
-% has been created with the command described below. Initially this is not set.
-% An empty value removes the entry.
-%
-% \DescribeCheckboxkey{down-appearance} This key sets the down appearance (when the
-% mouse clicks). It takes as value a
-% \meta{name} and expects that the two appearances \meta{name}|/Yes| and \meta{name}|/Off|
-% has been created with the command described below. Initially this is not set.
-% An empty value removes the entry.
-%
-% \DescribeCheckboxkey{checked} This is a boolean key which allows to set if the
-% checkbox should be initially checked or not. It sets the |/V| and |/DV| key of the field
-% and the |/AS| key of the annotation instance. It is possible to use different
-% values for different instances, if one wants to confuse the user.
-%
-% \DescribeCheckboxkey{setfieldflags}
-% \DescribeCheckboxkey{unsetfieldflags}
-% These keys allow to set or unset the field flags.  They expect a comma lists of
-% flag names. Allowed names |ReadOnly|, |Required|,
+% \begin{function}{name,T}
+%  \begin{syntax}
+%   |name| = \meta{partial name}\\
+%   |T| = \meta{partial name}
+%  \end{syntax}
+% This sets the partial name of the field. It shouldn't contain
+% a period, be not empty and sensibly consist of simple ascii chars.
+% It is normally required, see above. The value is passed through \cs{pdf_string_from_unicode:nnN}.
+% \end{function}
+%
+% \begin{function}{altname,TU}
+%  \begin{syntax}
+%   |altname| = \meta{string}\\
+%   |TU| = \meta{string}\\
+%  \end{syntax}
+% This sets an alternative name for user interaction.
+% Unlike the name field it can use unicode or periods.
+% The value is passed through \cs{pdf_string_from_unicode:nnN}
+% \end{function}
+%
+% \begin{function}{mappingname,TM}
+%  \begin{syntax}
+%   |mappingname| = \meta{string}\\
+%   |TM| = \meta{string}\\
+%  \end{syntax}
+% This sets an alternative name for the export.
+% The value is passed through \cs{pdf_string_from_unicode:nnN}
+% \end{function}
+%
+% \begin{function}{mappingname,TM}
+%  \begin{syntax}
+%   |FT| = |Btn|\verb"|"|Tx|\verb"|"|Ch|\verb"|"|Sig|
+%  \end{syntax}
+% This sets the type of the field, the value should be one of
+% \texttt{Btn} (button), \texttt{Tx} (text), \texttt{Ch} (choice),  \texttt{Sig} (signature).
+% The value is of relevance only for terminal fields, but it can be set in a parent
+% and then inherited.
+% \end{function}
+%
+% \begin{function}{setfieldflags,setFf,unsetfieldflags,unsetFf}
+%  \begin{syntax}
+%   |setfieldflags| = \meta{comma list of flags}\\
+%   |setFf| = \meta{comma list of flags}\\
+%   |unsetfieldflags| = |all| \verb"|" \meta{comma list of flags}\\
+%   |unsetFf| = |all| \verb"|" \meta{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{/Ff} key. Depending
+% on the field type some flags must be set or unset, other are optional or are ignored.
+% The flag name can be given in PDF spelling (\texttt{RadiosInUnison}),
+% in lowercase (\texttt{radiosinunison}), and as number. |unsetFf| and its
+% alias |unsetfieldflags|  know the special value |all| which clears all the fields.
+%
+% The list of flags are:
+% |ReadOnly|, |Required|,
 % |NoExport|, |Multiline|, |Password|,    |NoToggleToOff|, |Radio|, |Pushbotton|,
 % |Combo|, |Edit|,   |Sort|, |FileSelect|,  |MultiSelect|, |DoNotSpellCheck|,
 % |DoNotScroll|, |Comb|,  |RadiosInUnison|, |RichText|, |CommitOnSelChange|.
 %
-% From these |Radio|, |Pushbotton| are set automatically automatically by the code
-% as this is required for a checkbox. Not every one from the rest makes sense for
-% checkboxes but the same key will be used for other fields too.
-% Check the PDF reference to decide which one to set or unset.
-%
-% \begin{checkboxkey}{keystroke,format,validate,calculate}
-% These keys add the |/K, |/F, |/V|, |/C| key to the |/AA| dictionary of the field object.
-% Their value should be javascript code. The |/AA| dictionary is suppressed
-% if a pdf/A standard is set. These keys are probably not of much used with a checkbox.
-% \end{checkboxkey}
-%
-% \vspace{2\baselineskip}
-% \begin{checkboxkey}{onfocus,onblur,onmousedown,onmouseup,onenter,onexit}
-% These keys adds the |/F, |/Bl, |/D|, |/U|, |E| and |X| key to the |/AA| dictionary
-% of the widget  annotation (the checkbox instance) object.
-% Their value should be javascript code. The |/AA| dictionary
-% is suppressed if a pdf/A standard is set.
+% \end{function}
 %
-% For example
-% \begin{verbatim}
-%    onenter={app.alert('Hello');}
-% \end{verbatim}
-% \end{checkboxkey}
+% \begin{function}{V}
+%  \begin{syntax}
+%   |V| = \meta{various}
+%  \end{syntax}
+% This sets the value of the field. Its
+% format varies depending on the field type, so typically
+% commands for the various type will have to preprocess and sanitize it.
+% The value given here is x-expanded and then added to the dictionary!
+% See the descriptions of individual field types for further information.
+% (Pushbuttons for example don't have a value).
+% \end{function}
 %
-% \subsection{Using with hyperref}
-% The \cs{CheckBox} command from hyperref also prints a label, something that the
-% command here don't do. A redefinition like the following should allow to \cs{CheckBox}
-% to use the commands of this module. Be aware that the behaviour will not be identical!
-% Not every setting and key from \pkg{hyperref} has been copied.
+% \begin{function}{DV}
+%  \begin{syntax}
+%   |DV| = \meta{various}
+%  \end{syntax}
+% The default value, to which the field reverts
+% when a reset-form action is executed. The format of this value is the
+% same as that of \texttt{DV}.
+% \end{function}
 %
-% \begin{verbatim}
-% \ExplSyntaxOn\makeatletter
-% \def\@CheckBox[#1]#2{\LayoutCheckField{#2}{\pdffield_checkbox:n {name=#2,#1}}}
-% \ExplSyntaxOff\makeatother
-% \end{verbatim}
+% \begin{function}{MaxLen}
+%  \begin{syntax}
+%   |MaxLen| = \meta{integer}
+%  \end{syntax}
+% Only relevant for textfields.
+% The value is an integer and describes the maximum length of the field’s text in characters.
+% Required if the |Comb| flag is used.
+% \end{function}
 %
-% \subsection{Some background}
-% Form fields consist of a field object and number of instances of the field:
-% A checkbox can appear on more than one page or location and if one instance
-% is checked all other instances follows and are checked too.
-%
-% All instances are in this case widget annotations and are referenced in the Kid array of the field
-% object\footnote{Fields can actually build a tree: between the root field and
-% widget annotations there can be more fields. The last one before the widget is
-% the \emph{terminal} field, but unless a sensible
-% use case comes up, I will assume that the widget annotations are direct children of
-% the root and that the root field is the terminal field.}.
-% This means that the code has to collect all the children and write
-% out the field object at the end of the document.
-%
-% If a field has only one children the content of the field dictionary and the
-% widget annotation dictionary can be merged---some examples in the PDF reference
-% show such merged dictionaries---but the code here keeps them separate, at the end
-% this is clearer.
+% \begin{function}{Lock}
+%  \begin{syntax}
+%   |MaxLen| = \meta{object name}
+%  \end{syntax}
+% Only relevant for signature fields. The value is an object name
+% which should point to a dictionary that specifies a set of form fields
+% that shall be locked when this signature field is signed. The exact format of
+% the dictionary is described in the PDF reference.
+% \end{function}
 %
-% All the root field objects must be referenced in the AcroForm dictionary in the
-% Fields entry. This can be done with
+% \begin{function}{SV}
+%  \begin{syntax}
+%   |SV| = \meta{object name}
+%  \end{syntax}
+% Only relevant for signature fields. The value is an object name
+% which should point to a seed value dictionary. The exact format of
+% the dictionary is described in the PDF reference.
+% \end{function}
 %
-% \begin{verbatim}
-% \pdfmanagement_add:nnx{Catalog/AcroForm}{Fields}{<obj ref>}
-% \end{verbatim}
+% \begin{function}{Opt}
+%  \begin{syntax}
+%   |Opt| = \meta{object name}
+%  \end{syntax}
+% Only relevant for checkboxes, radiobuttons and choice fields.
+% The value is an object name
+% which should point to a array. The exact format of
+% the array is described in the PDF reference.
+% \end{function}
 %
-% A checkbox has two different looks: checked and unchecked. The current hyperref
-% implementation uses symbolic names for the two states and and adds some
-% values with the /MK key and lets the PDF viewer
-% create a look from them. But this doesn't work reliably. Also newer PDF versions
-% deprecate the /NeedAppearances setting and require that such a look,
-% an \enquote{appearance}, is given as form XObjects:
-% such form XObjects are like small pictures stored in the PDF and can be referenced
-% in various part of the PDF. They can be created with the commands of
-% the \pkg{l3pdfxform} package.
-%
-% The checkbox instances---the widget annotations---cover a rectangular area on
-% the page, the XObjects are squeezed into this rectangle. So for the best result
-% both should have the same ratio of width and height.
-% XObjects used as appearances can not be rotated, if needed one has to
-% create a new appearance.
+% \begin{function}{TI}
+%  \begin{syntax}
+%   |TI| = \meta{integer}
+%  \end{syntax}
+% Only relevant for scrollable list boxes.
+% The value is an integer, the top index (the index in the Opt array
+% of the first option visible in the list). Default value: 0
+% \end{function}
 %
-% \subsubsection{The field dictionary}
+% \begin{function}{I}
+%  \begin{syntax}
+%   |I| = \meta{object name}
+%  \end{syntax}
+% For choice fields that allow
+% multiple selection (MultiSelect flag set). The value is an object name
+% which should point to a array. The exact format of
+% the array is described in the PDF reference
+% (I have no idea what exactly should be added there, perhaps some future test will make
+% it more understandable.)
+% \end{function}
 %
-% The field dictionary shall or can have the following entries
+% The following four keys are used to add javascript (\enquote{ECMAScript}) code.
+% The values are currently only passed through \cs{pdf_string_from_unicode:nnN},
+% but this perhaps will have to change. The keys will be ignored if a pdfstandard
+% is used that prohibits such actions.
+%
+% \begin{function}{AA/K,keystroke}
+%  \begin{syntax}
+%   |AA/K| = \meta{string (ECMAScript)}\\
+%   |keystroke| = \meta{string (ECMAScript)}
+%  \end{syntax}
+% This adds a keystroke action to the
+% additional action dictionary. The value is passed through
+% \cs{pdf_string_from_unicode:nnN}. The action is meant for text and choice fields.
+%  It is quite unclear if such an action
+%  make sense for non-terminal fields.
+%  \end{function}
+%
+% \begin{function}{AA/F,format}
+%  \begin{syntax}
+%   |AA/F| = \meta{string (ECMAScript)}\\
+%   |format| = \meta{string (ECMAScript)}
+%  \end{syntax}
+% This adds a format action to the
+% additional action dictionary. The value is passed through
+% \cs{pdf_string_from_unicode:nnN}. The action is meant for text and choice fields.
+% It is quite unclear if such an action
+%  make sense for non-terminal fields.
+% \end{function}
 %
-% \begin{description}
-% \item[FT] required for terminal fields (here for the root field),
-%  the value is always \texttt{Btn}, so this entry is set by the code.
-% \item[Parents] currently irrelevant as we don't have a field hierarchy.
-% \item[Kids] an array. Contains references to the children, in our case to
-% the widget annotations. The array is build by the code.
+% \begin{function}{AA/V,validate}
+%  \begin{syntax}
+%   |AA/V| = \meta{string (ECMAScript)}\\
+%   |validate| = \meta{string (ECMAScript)}
+%  \end{syntax}
+% This adds a validate action to the
+% additional action dictionary. The value is passed through
+% \cs{pdf_string_from_unicode:nnN}. It is quite unclear if such an action
+%  make sense for non-terminal fields.
+%  \end{function}
+%
+% \begin{function}{AA/C,calculate}
+%  \begin{syntax}
+%   |AA/C| = \meta{string (ECMAScript)}\\
+%   |calculate| = \meta{string (ECMAScript)}
+%  \end{syntax}
+% This adds a calculate action to the
+% additional action dictionary. The value is passed through
+% \cs{pdf_string_from_unicode:nnN}. It is quite unclear if such an action
+%  make sense for non-terminal fields.
+% \end{function}
 %
-% \item[T] required, the name, a (unique) text string without a period.
-% This field is a mandatory argument which must be given by the user.
-% The value should be passed through a suitable string conversion and checked
-% if it contains a period (which is not allowed).
+% \begin{function}{DA}
+%  \begin{syntax}
+%   |DA| = \meta{string}
+%  \end{syntax}
+% This contains instructions for the text in text fields.
+% It is stored expanded and parentheses are added around the value.
+% \end{function}
 %
-% \item[TU,TM] optional, alternative names for user messages (TU) and export (TM).
-% As these fields are optional they should be set by some key-val option.
+% \begin{function}{Q,align}
+%  \begin{syntax}
+%   |Q| = |left|\verb"|"|center|\verb"|"|right|\\
+%   |align| = |left|\verb"|"|center|\verb"|"|right|
+%  \end{syntax}
+% The justification of the text.
+% \end{function}
 %
-% \item[Ff] A bitset, two flags must be unset for a checkbox (Radio and Pushbotton),
-% for the rest we need a keyval interface.
+% \begin{function}{DS,RV}
+% These two keys are currently not implemented
+% as it is unclear if there are of any use.
+% \end{function}
 %
-% \item[V] describes the initial value, for checkboxes is should be either |/Yes|
-%   or |/Off|. The initial value will be |/Yes|, keys are need to set both the local
-%   and the default value.
+% \section{Annot keys}
+%
+% Table~\ref{tab:annotkeys} summarize the keys which can be used.
+% A number of keys have alias names which are mentioned in the descriptions.
+%
+% \begin{table}
+% \caption{Keys for field annotations}\label{tab:annotkeys}
+% \centering
+% \begin{tabular}{>{\ttfamily}lllll}
+% \toprule
+% key      & value      & required &remark\\\midrule
+% parent   & field ID & yes             \\
+% width    & dim expression & (yes)  & default is 0pt \\
+% height   & dim expression & (yes)  & default is 0pt \\
+% depth   & dim expression & (yes)  & default is 0pt \\
+% AP/N    & appearance name  & yes  (in PDF 2.0) \\
+% AP/R    & appearance name  & yes  (in PDF 2.0) \\
+% AP/D    & appearance name  & yes  (in PDF 2.0) \\
+% AS      & name  & yes  (in PDF 2.0) \\
+% setF    & list of flags \\
+% unsetF  & list of flags \\
+% AA/*    & javascript   & *= F, Bl, D, U, E, \\
+%         &              &    X, PO, PC,PV, PI\\
+% MK/*    & various      & *= R, BC, BG, CA, RC, \\
+%         &              &   AC, I, RI, IX, IF, TP\\ \bottomrule
+%
+% \end{tabular}
+% \end{table}
+%
+% \begin{function}{width,height,depth}
+% \begin{syntax}
+% |width| = \meta{dim expression}\\
+% |height| = \meta{dim expression}\\
+% |depth| = \meta{dim expression}
+% \end{syntax}
+% These keys allow to set the dimensions of the annotation.
+% The value should be a command that expands to a dimension expression. By default
+% all values are zero.
+% \end{function}
+%
+% \begin{function}{parent}
+%  \begin{syntax}
+%   |parent| = \meta{field ID}\\
+%  \end{syntax}
+% This sets the parent. The value should be field ID of
+% an already declared field.
+% \end{function}
+%
+% \begin{function}{AP/N,AP/R,AP/D}
+%  \begin{syntax}
+%   |AP/N| = \meta{appearance name}\\
+%   |AP/R| = \meta{appearance name}\\
+%   |AP/D| = \meta{appearance name}
+%  \end{syntax}
+% This keys set the normal, rollover and down appearance. Alias names are
+% |appearance|, |rollover-appearance| and |down-appearance|.
+% The value is by default a simple name of an appearance/form Xobject but
+% modules like \pkg{l3pdffield-checkbox} change this to allow to add appearances for
+% various states.
+% \end{function}
 %
-% \item[DV] optional, the default value after a reset. Should  like |V| be either
-% |/Yes| or |/Off|.
+% \begin{function}{AS}
+%  \begin{syntax}
+%   |AS| = \meta{appearance state name}
+%  \end{syntax}
+% This key sets the default appearance state.
+% The value is a name without the starting slash
+% (it is passed through |\pdf_name_from_unicode_e:n|),
+% for checkbox for example |Yes|. If used it should typically have the same value
+% as the V and DV key of the field.
+% \end{function}
 %
-% \item[AA] An action dictionary. For this we need a special command to setup such
-% dictionaries, so that they then can be used in various places.
+%\begin{function}{setannotflags,setF,unsetannotflags,unsetF}
+%  \begin{syntax}
+%   |setannotflags| = \meta{comma list of flags}\\
+%   |setF| = \meta{comma list of flags}\\
+%   |unsetannotflags| = |all| \verb"|" \meta{comma list of flags}\\
+%   |unsetF| = |all| \verb"|" \meta{comma list of flags}
+%  \end{syntax}
+% These keys allow to set or unset the annot flags.  They expect a comma lists of
+% flag names. Allowed names |Invisible|, |Hidden|,
+%  |Print|, |NoZoom|,|NoRotate|, |NoView|, |ReadOnly|, |Locked|, |ToggleNoView|,
+%  |LockedContents|, or the lowercase variants or numbers.
+% \end{function}
 %
-% \end{description}
+% \begin{function}{AA/*}
+%  \begin{syntax}
+%  |AA/*| = \meta{string (ECMAScript)}
+%  \end{syntax}
+% * should be one of |F|, |Bl|, |D|, |U|, |E|, |X|, |PO|, |PC|, |PV|, |PI|.
+% Alias names for the first six keys are
+% |onfocus|, |onblur|, |onmousedown|, |onmouseup|, |onenter|,  |onexit|.
+% These keys adds then the respective key to the |/AA| dictionary
+% of the field annotation object.
+% Their value should be javascript code. The |/AA| dictionary
+% is suppressed if a pdf/A standard is set.
+%
+% For example
+% \begin{verbatim}
+%    onenter={app.alert('Hello');}
+% \end{verbatim}
+% \end{function}
 %
-% \subsubsection{The widget annotation dictionary}
+% The following keys add values to the  \emph{dynamic appearance dictionary}
+% |MK| directory. This is only relevant for
+% annotations with dynamic content, like e.g. textfields.
+% The settings can also affect checkboxes and radio buttons if the (deprecated)
+% |NeedAppearances| is set to true.
+%
+% The |MK| dictionary can also be added by using |\pdfannot_dict_put:nnn{Widget}{MK}{...}|
+% but the two methods should not be mixed.
+%
+%  \begin{function}{MK/R,rotate}
+%  \begin{syntax}
+%  |MK/R| = |0| \verb"|" |90| \verb"|" |180| \verb"|" |270|\\
+%  |rotate| = |0| \verb"|" |90| \verb"|" |180| \verb"|" |270|
+%  \end{syntax}
+% These rotates the content of the annotation.
+% \end{function}
 %
-% \begin{description}
-% \item[Type] Value: |/Annot|, set automatically
-% \item[Subtype] Value: |/Widget| this is added automatically.
-%  We use an internal dictionary which is locally copied over the one from l3pdfannot.
-%  It can be filled with keyval options.
-% \item[Parent] The reference to the field, automatically added.
-% \item[Rect] the size, calculated from the box size
-% \item[Contents] a text string, not really needed but an optional key should allow to
-% set it,
-% \item[AP] the appearance dictionary. It should look like this
-%  |/AP <</N <</Yes 17 0 R/Off 15 0 R>>>>|. I need to test if it makes sense here to
-%  have a |/R| and |/D| entry too. The objects refer to suitable xforms.
-% \item[AS] should be either |/Yes| or |/Off|, and sensibly by default be
-%  the same as the V entry in the field dictionary. If they differ the AS entry wins.
+% \begin{function}{MK/BC,bordercolor}
+%  \begin{syntax}
+%  |MK/BC| = \meta{color expression} \verb"|" [\meta{model}]\Arg{values}\\
+%  |bordercolor| = \meta{color expression} \verb"|" [\meta{model}]\Arg{values}
+%  \end{syntax}
+% These colors the border. Internally currently RGB is used.
+% The colors used in
+% \meta{color expression} must be known to the \pkg{l3color} commands.
+% \end{function}
 %
-% \item[A] Action, this must be checked.
-% \item[AA] additional actions. This must be checked too.
+% \begin{function}{MK/BG,backgroundcolor}
+%  \begin{syntax}
+%  |MK/BG| = \meta{color expression} \verb"|" [\meta{model}]\Arg{values}\\
+%  |backgroundcolor| = \meta{color expression} \verb"|" [\meta{model}]\Arg{values}
+%  \end{syntax}
+% These colors the background. Internally currently RGB is used.
+% The colors used in
+% \meta{color expression} must be known to the \pkg{l3color} commands.
+% \end{function}
 %
-% \item[Border, C, OC, AF, BM, Lang, P, NM, M, F, BS, H]: These are not specifically
-% needed for checkbox. An interface to add something to the used annot dictionary
-% is needed (or already there), but probably no special key-val support for now.
+% \begin{function}{MK/CA,caption}
+%  \begin{syntax}
+%  |MK/CA| = \meta{string}\\
+%  |caption| = \meta{string}
+%  \end{syntax}
+% This sets a text for the caption. \meta{string} is passed through \cs{pdf_string_from_unicode:nnN}
+% and parentheses are added automatically. The font used seems to depend on
+% the whims of the PDF reader: At least for checkboxes adobe reader quite insists to
+% always use a symbol font and not a text font. It also shows always
+% only one symbol, regardless how much one put in the string.
+% hyperref uses the key names |checkboxsymbol| and
+% |radiosymbol| for this setting.
+% \end{function}
 %
-% \item[MK] this is what hyperref uses to set the appearance, but I
-%  explicitly leave it out and use |AP|.
+% The remaining key are useful for buttons only, currently no special syntax support
+% is implemented. They will be handled when the code for push buttons is developed and
+% tested.
+% \begin{function}{MK/*}
+%  \begin{syntax}
+%  |MK/*| = \meta{various}
+%  \end{syntax}
+% These keys adds the various entries in the \emph{dynamic appearance dictionary}.
+% * should be one of  |RC|, |AC|, |I|, |RI|, |IX|, |IF|, |TP|.
+% The |MK| dictionary can also be added by using |\pdfannot_dict_put:nnn{Widget}{MK}{...}|
+% but the two methods should not be mixed.
+% \end{function}
 %
-% \item[Q] (alignment), used by hyperref but not relevant as we don't have variable
-% text here.
-% \end{description}
 % \end{documentation}
 %
 % \begin{implementation}
-% \section{\pkg{l3pdffield-checkbox} Implementation}
+% \section{\pkg{l3pdffield} Implementation}
 %    \begin{macrocode}
 %<*package>
 %<@@=pdffield>
 \NeedsTeXFormat{LaTeX2e}
-\ProvidesExplPackage{l3pdffield-testphase}{2021-03-17}{0.95c}%
-  {form field checkboxes}
+\ProvidesExplPackage{l3pdffield-testphase}{2021-05-14}{0.95d}%
+  {form fields}
 %    \end{macrocode}
 % \subsection{hyperref specific command}
 % hyperref sets NeedAppearances by default. As this is deprecated we disable this.
 %    \begin{macrocode}
 \csname HyField@NeedAppearancesfalse\endcsname % suppress NeedAppearances
-% values from hyperref:
-%\def\DefaultOptionsofCheckBox{print}
-%\def\DefaultHeightofCheckBox{\normalbaselineskip}
-%\def\DefaultWidthofCheckBox{\normalbaselineskip}
 %    \end{macrocode}
+%
 % \subsection{local variables}
+%
 %    \begin{macrocode}
-\str_new:N \l_@@_field_name_str
 \str_new:N \l_@@_tmpa_str
-\str_new:N \l_@@_name_tmpa_str
-\tl_new:N \l_@@_keys_tmpa_tl
+\tl_new:N  \l_@@_tmpa_tl
+\tl_new:N  \l_@@_tmpa_keys_tl
+\cs_new_protected:Npn \@@_tmpa:n #1 {}
+\cs_new_protected:Npn \@@_tmpa:nn #1 #2 {}
+\tl_new:N \l_@@_currentparent_tl
+\tl_new:N \l_@@_fieldID_tl
 %    \end{macrocode}
 %
 % \subsection{messages}
@@ -383,15 +780,40 @@
   }
 \msg_new:nnn {pdffield}{appearance-missing}
   {
-    The~appearance~`#1`~is~missing~for~the~#2~appearance.
+    The~appearance~definition~`#1`~is~missing~for~the~#2~appearance.
+  }
+\msg_new:nnn {pdffield}{not-implemented}
+  {
+    Support~for~'/#1'~is~not~implemented\\
+    The~key~is~ignored.
+  }
+\msg_new:nnn {pdffield}{key-disabled}
+  {
+    key~`#2`~is~disabled~and~ignored~in~the~`#1`~command.\\
+    Use~key~`#3`~instead.
   }
-\msg_new:nnn {pdffield}{field-keys-ignored}
+\msg_new:nnn {pdffield}{parent-field-missing}
   {
-    The~field~`#1`~is~already~initialized\\
-    The~field~keys~`#2`~are~ignored.
+    The~parent~field~'#1'~doesn't~exist\\
+    Create~it~with~\tl_to_str:n{\pdffield_field:nn}
   }
 %    \end{macrocode}
 
+% An auxiliary command to disable some keys
+% \begin{macro}{\@@_key_disable:nnn}
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_key_disable:nnn #1#2#3
+ {
+   \keys_define:nn {pdffield}
+    {
+      #2 .code:n =
+       {
+         \msg_warning:nnnnn {pdffield}{key-disabled}{#1}{#2}{#3}
+       }
+    }
+ }
+%    \end{macrocode}
+% \end{macro}
 % \subsection{bitsets}
 % A bitset for the field flag Ff
 % and an internal copy of the annot bitset.
@@ -417,7 +839,27 @@
     Comb              = 25,%Tx, requires MaxLen in dict
     RadiosInUnison    = 26,%Btn Radio
     RichText          = 26,%Tx
-    CommitOnSelChange = 27
+    CommitOnSelChange = 27,
+    readonly          = 1,
+    required          = 2,
+    noexport          = 3,
+    multiline         = 13,%Tx
+    password          = 14,
+    notoggletooff     = 15,%Btn, radio button
+    radio             = 16,%Btn: Radio:    15=1, 16=0
+    pushbutton        = 17,%Btn: Checkbox: 15=0, 16=0
+                           %Btn: Pushbutton: 16=1
+    combo             = 18,%Ch: Combo=1 List=0
+    edit              = 19,%Ch, Combo=1 -> + edit field
+    sort              = 20,%Ch, not relevant for view...
+    fileselect        = 21,%Tx
+    multiselect       = 22,%Ch
+    donotspellcheck   = 23,%Tx, Ch (if Combo + Edit set)
+    donotscroll       = 24,%Tx
+    comb              = 25,%Tx, requires MaxLen in dict
+    radiosinunison    = 26,%Btn Radio
+    richtext          = 26,%Tx
+    commitonselchange = 27
   }
 
 \bitset_new:Nn \l_@@_F_bitset
@@ -431,102 +873,107 @@
     ReadOnly       = 7,
     Locked         = 8,
     ToggleNoView   = 9,
-    LockedContents = 10
+    LockedContents = 10,
+    invisible      = 1,
+    hidden         = 2,
+    print          = 3,
+    nozoom         = 4,
+    norotate       = 5,
+    noview         = 6,
+    readonly       = 7,
+    locked         = 8,
+    togglenoview   = 9,
+    lockedcontents = 10
   }
 %    \end{macrocode}
 % \subsection{The field dictionary}
-% The field dictionary is the main object. It references the
-% actual widget annotations as kids. It is created at the first
-% checkbox with a specific name.
+% The field dictionary is the main object.
 % To be able to set values from the outside it will use a
 % dictionary which can be filled by key-val.
 %    \begin{macrocode}
-\pdfdict_new:n   {l_@@/checkbox/field}
-\pdfdict_put:nnn {l_@@/checkbox/field}{FT}{/Btn}
+\pdfdict_new:n   {l_@@/field}
+\pdfdict_new:n   {l_@@/field/AA}
+\bool_new:N \l_@@_root_field_bool
 %    \end{macrocode}
-% We need to check if the name contains a dot. But we will do this in an external command
-% to avoid to have it twice. Here we assume that the name is already converted and safe.
-%
-% We also assume that values that can be changed by the user are set outside
-% in the dictionary.
-% If the field object already exists nothing is done.
-% \begin{macro}{\@@_checkbox_field_add:n}
+% \begin{macro}{\@@_field:n}
 % \begin{syntax}
-% \cs{@@_checkbox_field_add:n}\Arg{name}
+% \cs{@@_field:n}\Arg{field ID}
 % \end{syntax}
-% \meta{name} should be a PDF text string without period. It identifies the
-% field.
 %    \begin{macrocode}
-\cs_new_protected:Npn \@@_checkbox_field_new:n #1
+\cs_new_protected:Npn \@@_field:n #1
   {
-      \group_begin:
-      \pdf_object_new:nn {@@_checkbox/field/#1}      {dict}
-      \pdf_object_new:nn {@@_checkbox/field/#1/Kids} {array}
-      \seq_new:c {g_@@_checkbox/field/#1/Kids_seq}
-      \hook_gput_code:nnn {shipout/lastpage}{pdffield} %xetex needs this ...
-        {
-          \pdf_object_write:nx {@@_checkbox/field/#1/Kids}
-            {
-              \seq_use:cn{g_@@_checkbox/field/#1/Kids_seq}{~}
-            }
-        }
-      \pdfdict_put:nnn {l_@@/checkbox/field}{T}{(#1)}
-     % V,DV are names describing the appearance. With checkboxes
-     % the values /Yes and /Off are used.
-     % this values are taken from the outside
-      \pdfdict_put:nnx {l_@@/checkbox/field}
-         {Kids}
-         {
-           \pdf_object_ref:n {@@_checkbox/field/#1/Kids}
-         }
-      \bitset_set_false:Nn \l_@@_Ff_bitset  {Radio}
-      \bitset_set_false:Nn \l_@@_Ff_bitset  {Pushbutton}
-      \pdfdict_put:nnx {l_@@/checkbox/field}
-        {Ff}
-        {\bitset_to_arabic:N \l_@@_Ff_bitset }
-      \pdfdict_if_empty:nF{l_@@/checkbox/field/AA}
-        {
-          \pdfmeta_standard_verify:nT
-            {annot_widget_no_AA}
-            {
-              \pdfdict_put:nnx
-                {l_@@/checkbox/field}
-                {AA}
-                {<<\pdfdict_use:n {l_@@/checkbox/field/AA}>>}
-            }
-        }
-      \pdf_object_write:nx {@@_checkbox/field/#1} { \pdfdict_use:n {l_@@/checkbox/field} }
-      \pdfmanagement_add:nnx
-        { Catalog / AcroForm }
-        { Fields }
-        {\pdf_object_ref:n {@@_checkbox/field/#1} }
-      \group_end:
+    \pdf_object_new:nn {@@/field/#1}      {dict}
+    \pdf_object_new:nn {@@/field/Kids/#1} {array}
+    \tl_if_empty:NTF \l_@@_currentparent_tl
+      {
+        \pdfmanagement_add:nnx
+          { Catalog / AcroForm }
+          { Fields }
+          {\pdf_object_ref:n {@@/field/#1} }
+      }
+      {
+        \exp_args:Ne
+        \pdf_object_if_exist:nTF {@@/field/\l_@@_currentparent_tl}
+          {
+            \pdfdict_put:nnx { l_@@/field }{Parent}
+              {\exp_args:Ne \pdf_object_ref:n{@@/field/\l_@@_currentparent_tl}}
+            \seq_gput_right:cx {g_@@_field/Kids/\l_@@_currentparent_tl _seq}
+              { \exp_args:Ne \pdf_object_ref:n{@@/field/#1}}
+          }
+          {
+            \msg_error:nnx {pdffield}{parent-field-missing}{\l_@@_currentparent_tl}
+          }
+      }
+    \seq_new:c {g_@@_field/Kids/#1_seq}
+    \pdfdict_put:nnx {l_@@/field}
+      {Kids}
+      {
+        \pdf_object_ref:n {@@/field/Kids/#1}
+      }
+    \pdfdict_put:nnx {l_@@/field}
+      {Ff}
+      {\bitset_to_arabic:N \l_@@_Ff_bitset }
+    \pdfdict_if_empty:nF{l_@@/field/AA}
+      {
+        \pdfmeta_standard_verify:nT
+          {annot_widget_no_AA}
+          {
+            \pdf_object_unnamed_write:nx {dict}{\pdfdict_use:n {l_@@/field/AA}}
+            \pdfdict_put:nnx
+              {l_@@/field}
+              {AA}
+              {\pdf_object_ref_last:}
+          }
+      }
+    \hook_gput_code:nnn {shipout/lastpage}{pdffield} %xetex needs this ...
+      {
+        \pdf_object_write:nx {@@/field/Kids/#1}
+          {
+            \seq_use:cn{g_@@_field/Kids/#1_seq}{~}
+          }
+      }
+    \pdf_object_write:nx {@@/field/#1} { \pdfdict_use:n {l_@@/field} }
+  }
+\cs_new_protected:Npn \pdffield_field:nn #1 #2
+  {
+    \group_begin:
+    \keys_set:nn { pdffield } {#1}
+    \@@_field:n {#2}
+    \group_end:
   }
-
 %    \end{macrocode}
 % \end{macro}
+%
 % \subsection{The annot dictionary}
 % We assume that the annotation should really occupy space on the page and
 % leave vertical mode.
-% We also assume that keys like AP, AS are added before through keys to
-% the dictionary.
-% We use a local dictionary which is copied into |l__pdfannot/widget| in the code.
-%    \begin{macrocode}
-\pdfdict_new:n   {l_@@/checkbox/annot}
-\pdfdict_put:nnn {l_@@/checkbox/annot}{Subtype}{/Widget}
-%    \end{macrocode}
 %
-% \begin{macro}{\@@_checkbox_annot_add:nnnn}
+% \begin{macro}{\@@_annot:}
+% The command doesn't add grouping, so should only be used inside a group.
+%
 %    \begin{macrocode}
-\cs_new_protected:Npn \@@_checkbox_annot_add:nnnn #1 #2 #3 #4 %name, wd, ht, dp,
+\cs_new_protected:Npn \@@_annot:
   {
-    \group_begin:
-%    \end{macrocode}
-% Copy the internal dictionary to the pdfannot dictionary. This
-% perhaps need a function in l3pdfannot,
-% as it actually uses an internal name of another module.
-%    \begin{macrocode}
-    \pdfdict_put:nnx {l_@@/checkbox/annot}{AP}{<<\pdfdict_use:n{l_@@/checkbox/annot/AP}>>}
     \pdfmeta_standard_verify:nF
       {annot_flags}
       {
@@ -535,428 +982,656 @@
         \bitset_set_false:Nn \l_@@_F_bitset {Invisible}
         \bitset_set_false:Nn \l_@@_F_bitset {NoView}
       }
-    \pdfdict_if_empty:nF{l_@@/checkbox/annot/AA}
+    \pdfannot_dict_put:nnx {widget}{F}{ \bitset_to_arabic:N \l_@@_F_bitset }
+    \tl_if_empty:NF \l_@@_currentparent_tl
       {
-        \pdfmeta_standard_verify:nT
-         {annot_widget_no_AA}
-         {
-            \pdfdict_put:nnx
-              {l_@@/checkbox/annot}
-              {AA}
-              {<<\pdfdict_use:n {l_@@/checkbox/annot/AA}>>}
-         }
-      }
-    \pdfdict_put:nnx {l_@@/checkbox/annot}{F}{ \bitset_to_arabic:N \l_@@_F_bitset }
-    \pdfdict_set_eq:nn {l__pdfannot/widget}{l_@@/checkbox/annot}
-    \pdfannot_dict_put:nnx {widget}{Parent}{\pdf_object_ref:n{@@_checkbox/field/#1}}
+         \exp_args:Ne
+         \pdf_object_if_exist:nTF { @@/field/\l_@@_currentparent_tl }
+           {
+             \pdfannot_dict_put:nnx {widget}{Parent}
+               {
+                 \exp_args:Ne
+                   \pdf_object_ref:n{@@/field/\l_@@_currentparent_tl}
+               }
+           }
+           {
+               \msg_error:nnx { pdffield }{parent-field-missing}{\l_@@_currentparent_tl}
+           }
+       }
     \mode_leave_vertical:
     \hbox_to_wd:nn
-      { #2  }
+      { \l_@@_annot_wd_dim  }
       {
-        \rule [-#4]{0pt}{\dim_eval:n{#3+#4} }
+        \rule [-\l_@@_annot_dp_dim]{0pt}{\dim_eval:n{\l_@@_annot_ht_dim+\l_@@_annot_dp_dim} }
         \pdfannot_widget_box:nnn
-           { #2 }
-           { #3 }
-           { #4 }
+           { \l_@@_annot_wd_dim }
+           { \l_@@_annot_ht_dim }
+           { \l_@@_annot_dp_dim }
          \hfill
       }
-    \seq_gput_right:cx {g_@@_checkbox/field/#1/Kids_seq}{ \pdfannot_box_ref_last:}
-    \group_end:
-  }
-
-%    \end{macrocode}
-% \end{macro}
-% \subsection{Appearances}
-% We don't try to force a size or content here.
-% The default appearances are a cross (\cs{texttimes}),
-% Every appearance should have two versions and follow the naming
-% checkbox/\meta{name}/Yes and checkbox/\meta{name}/Off.
-% TODO check if one delay the creation to a sensible place
-% (and don't forget that the appearance key sets an initial
-% value)
-%  \begin{macro}{\pdffield_store_appearance:nn,\@@_store_default_appearances:}
-%    \begin{macrocode}
-\cs_new_protected:Npn \pdffield_store_appearance:nn #1 #2
-  {
-     \pdfxform_new:nnn {@@_#1}{}{#2}
+    \tl_if_empty:NF \l_@@_currentparent_tl
+      {
+        \seq_if_exist:cTF {g_@@_field/Kids/\l_@@_currentparent_tl _seq}
+         {
+           \seq_gput_right:cx
+             {g_@@_field/Kids/\l_@@_currentparent_tl _seq}
+             { \pdfannot_box_ref_last:}
+         }
+         {
+           \msg_error:nnx { pdffield}{parent-field-missing}{\l_@@_currentparent_tl}
+         }
+      }
   }
-
-\cs_new_protected:Nn \@@_store_default_appearances:
-  {
-     \pdffield_store_appearance:nn {checkbox/default/Yes}
-       {
-         \normalsize
-         \fboxsep 0pt
-         \framebox
-           [ \dim_eval:n { \box_ht:N\strutbox+\box_dp:N\strutbox } ]
-           { \texttimes \strut }
-       }
-     \pdffield_store_appearance:nn {checkbox/default/Off}
-       {
-         \normalsize
-         \fboxsep 0pt
-         \framebox
-           [ \dim_eval:n { \box_ht:N\strutbox+\box_dp:N\strutbox } ]
-           { \phantom{\texttimes} \strut }
-       }
-  }
-
-\@@_store_default_appearances:
-%    \end{macrocode}
-% \end{macro}
-% We define a dictionary for the AP content, so that we can add R and D too
-%    \begin{macrocode}
-\pdfdict_new:n   {l_@@/checkbox/annot/AP}
-%    \end{macrocode}
-%
-% \subsection{Assembling the checkbox}
-% \begin{macro}{\@@_checkbox_add:n}
-%    \begin{macrocode}
-
-\cs_new_protected:Npn \@@_checkbox_add:n #1
+\cs_new_protected:Npn \pdffield_annot:n #1
   {
     \group_begin:
-    \keys_set_filter:nnnN {pdffield / checkbox }{field}{#1}\l_@@_keys_tmpa_tl
-    \str_if_empty:NT \l_@@_field_name_str
-      {
-        \msg_error:nn {pdffield}{empty-name}
-      }
-    \exp_args:Nx
-      \pdf_object_if_exist:nTF {@@_checkbox/field/\l_@@_field_name_str}
-       {
-          \tl_if_empty:NF \l_@@_keys_tmpa_tl
-           {
-             \msg_warning:nnxx
-               {pdffield}
-               {field-keys-ignored}
-               {\l_@@_field_name_str}
-               {\l_@@_keys_tmpa_tl}
-           }
-       }
-       {
-         \keys_set:nV { pdffield/checkbox } \l_@@_keys_tmpa_tl
-         \exp_args:No
-         \@@_checkbox_field_new:n {\l_@@_field_name_str}
-       }
-    \exp_args:No
-      \@@_checkbox_annot_add:nnnn
-        {\l_@@_field_name_str}
-        {\l_@@_annot_wd_tl }
-        {\l_@@_annot_ht_tl }
-        {\l_@@_annot_dp_tl }
+    \keys_set:nn { pdffield } {#1}
+    \@@_annot:
     \group_end:
   }
 %    \end{macrocode}
 % \end{macro}
-% \subsection{Keys}
-% The size of the checkbox
 %
+% \subsection{auxiliary command for color keys}
 %    \begin{macrocode}
-\tl_new:N \l_@@_annot_ht_tl
-\tl_new:N \l_@@_annot_wd_tl
-\tl_new:N \l_@@_annot_dp_tl
+\cs_new_protected:Npn \@@_color_set:nn #1 #2
+ {
+   \tl_if_head_eq_charcode:nNTF {#2}[ %]
+    {
+      \@@_color_set_aux:nwn  { #1 } #2
+    }
+    {
+      \color_set:nn {#1} {#2}
+    }
+ }
 
-\keys_define:nn { pdffield / checkbox }
+\cs_new_protected:Npn \@@_color_set_aux:nwn #1 [#2] #3
   {
-    ,width  .tl_set:N = \l_@@_annot_wd_tl
-    ,height .tl_set:N = \l_@@_annot_ht_tl
-    ,depth  .tl_set:N = \l_@@_annot_dp_tl
-    ,width  .initial:n = \normalbaselineskip
-    ,height .initial:n = \normalbaselineskip
-    ,depth  .initial:n = 0pt
+     \color_set:nnn {#1}{#2}{#3}
   }
+
 %    \end{macrocode}
+% \subsection{Field keys}
 % The names. The main name should not be empty, it is added to the dictionary
 % when the field is created. A new name means a new field.
 % The other names can only be set when the field is created,
 % so we put them in the field group.
 %    \begin{macrocode}
-\keys_define:nn { pdffield / checkbox }
+\cs_new_protected:Npn \@@_value_handler:nN #1#2
+  {
+    \tl_set:Nn #2 {#1}
+  }
+\keys_define:nn { pdffield  }
   {
-    ,name .code:n =
+    ,parent .tl_set:N = \l_@@_currentparent_tl
+    ,parent .groups:n = {field,annot}
+    ,T .code:n =
       {
-        \pdf_string_from_unicode:nnN {utf8/string-raw}{#1}\l_@@_field_name_str
-        \str_if_in:NnT \l_@@_field_name_str {.}
+        \pdf_string_from_unicode:nnN {utf8/string-raw}{#1}\l_@@_tmpa_str
+        \str_if_in:NnT \l_@@_tmpa_str {.}
           {
-            \msg_error:nnx {pdffield}{no-period}{\l_@@_field_name_str}
+            \msg_error:nnx {pdffield}{no-period}{\l_@@_tmpa_str}
           }
-        \str_if_empty:NT\l_@@_field_name_str
+        \str_if_empty:NTF\l_@@_tmpa_str
           {
-            \msg_error:nn {pdffield}{empty-name}
+            \msg_warning:nn {pdffield}{empty-name}
+            \pdfdict_remove:nn { l_@@/field }{T}
+          }
+          {
+            \pdfdict_put:nnx { l_@@/field }{T}{(\l_@@_tmpa_str)}
           }
       }
+    ,T .value_required:n = true
+    ,T .groups:n = {field}
+    ,name .meta:n          = {T={#1}}
     ,name .value_required:n = true
-    ,name .initial:n = checkbox
-    ,altname .code:n =
+    ,name .groups:n = {field}
+    ,TU .groups:n = {field}
+    ,TU .code:n =
       {
-        \pdf_string_from_unicode:nnN {utf8/string}{#1}\l_@@_name_tmpa_str
-        \pdfdict_put:nnx { l_@@/checkbox/field }{TU}{\l_@@_name_tmpa_str}
+        \tl_if_empty:nTF {#1}
+          {
+            \pdfdict_remove:nn { l_@@/field }{TU}
+          }
+          {
+            \pdf_string_from_unicode:nnN {utf8/string}{#1}\l_@@_tmpa_str
+            \pdfdict_put:nnx { l_@@/field }{TU}{\l_@@_tmpa_str}
+          }
       }
+    ,TU .groups:n = {field}
+    ,altname .meta:n      = {TU={#1}}
     ,altname .groups:n = {field}
-    ,mappingname .code:n =
+    ,TM .code:n =
       {
-        \pdf_string_from_unicode:nnN {utf8/string}{#1}\l_@@_name_tmpa_str
-        \pdfdict_put:nnx { l_@@/checkbox/field }{TM}{\l_@@_name_tmpa_str}
+        \tl_if_empty:nTF {#1}
+          {
+            \pdfdict_remove:nn { l_@@/field }{TM}
+          }
+          {
+            \pdf_string_from_unicode:nnN {utf8/string}{#1}\l_@@_tmpa_str
+            \pdfdict_put:nnx { l_@@/field }{TM}{\l_@@_tmpa_str}
+          }
       }
+    ,TM .groups:n = {field}
+    ,mappingname .meta:n   = {TM={#1}}
     ,mappingname .groups:n = {field}
-  }
-%    \end{macrocode}
-
-% A key to decide if the Box is initially checked or not
-%    \begin{macrocode}
-\keys_define:nn { pdffield / checkbox }
- {
-   ,checked .choice:
-   ,checked / false .code:n =
+    ,FT .choices:nn =
+      { Btn, Tx, Ch, Sig }
+      {
+        \pdfdict_put:nnn { l_@@/field }{FT}{ /#1 }
+      }
+    ,FT .groups:n = {field}
+    ,V .code:n =
      {
-       \pdfdict_put:nnn {l_@@/checkbox/field}{V}{/Off}
-       \pdfdict_put:nnn {l_@@/checkbox/annot}{AS}{/Off}
-       \pdfdict_put:nnn {l_@@/checkbox/field}{DV}{/Off}
+       \tl_if_empty:nTF {#1}
+         {
+           \pdfdict_remove:nn { l_@@/field }{V}
+         }
+         {
+           \@@_value_handler:nN{#1}\l_@@_tmpa_str
+           \pdfdict_put:nnx { l_@@/field }{V}{ \l_@@_tmpa_str }
+         }
      }
-   ,checked / true .code:n =
+    ,V .groups:n = {field}
+    ,DV .code:n =
      {
-       \pdfdict_put:nnn {l_@@/checkbox/field}{V}{/Yes}
-       \pdfdict_put:nnn {l_@@/checkbox/annot}{AS}{/Yes}
-       \pdfdict_put:nnn {l_@@/checkbox/field}{DV}{/Yes}
+       \tl_if_empty:nTF {#1}
+         {
+           \pdfdict_remove:nn { l_@@/field }{DV}
+         }
+         {
+           \@@_value_handler:nN{#1}\l_@@_tmpa_str
+           \pdfdict_put:nnx { l_@@/field }{DV}{ \l_@@_tmpa_str }
+         }
      }
-   ,checked .default:n = {true}
-   ,checked .initial:n = {false}
- }
+    ,DV .groups:n = {field}
+    ,MaxLen .code:n =
+     {
+       \tl_if_empty:nTF {#1}
+         {
+           \pdfdict_remove:nn { l_@@/field }{MaxLen}
+         }
+         {
+           \pdfdict_put:nnx { l_@@/field }{MaxLen}{ #1 }
+         }
+      }
+    ,MaxLen .groups:n = {field}
+    ,Lock .code:n =
+      {
+        \tl_if_empty:nTF {#1}
+          {
+            \pdfdict_remove:nn { l_@@/field }{Lock}
+          }
+          {
+            \pdfdict_put:nnx { l_@@/field }{Lock}{ \pdf_object_ref:n{#1} }
+          }
+      }
+    ,Lock .groups:n = {field}
+    ,SV .code:n =
+      {
+        \tl_if_empty:nTF {#1}
+          {
+            \pdfdict_remove:nn { l_@@/field }{SV}
+          }
+          {
+            \pdfdict_put:nnx { l_@@/field }{SV}{ \pdf_object_ref:n{#1} }
+          }
+      }
+    ,SV .groups:n = {field}
+    ,Opt .code:n =
+      {
+        \tl_if_empty:nTF {#1}
+          {
+            \pdfdict_remove:nn { l_@@/field }{Opt}
+          }
+          {
+            \pdfdict_put:nnx { l_@@/field }{Opt}{ \pdf_object_ref:n{#1} }
+          }
+      }
+    ,Opt .groups:n = {field}
+    ,TI .code:n =
+      {
+        \tl_if_empty:nTF {#1}
+          {
+            \pdfdict_remove:nn { l_@@/field }{TI}
+          }
+          {
+            \pdfdict_put:nnx { l_@@/field }{TI}{ #1 }
+          }
+       }
+    ,TI .groups:n = {field}
+    ,I .code:n =
+      {
+        \tl_if_empty:nTF {#1}
+          {
+            \pdfdict_remove:nn { l_@@/field }{I}
+          }
+          {
+            \pdfdict_put:nnx { l_@@/field }{I}{ \pdf_object_ref:n{#1} }
+          }
+      }
+    ,I .groups:n = {field}
+  }
 %    \end{macrocode}
-% Flags. We don't add lots of individual keys but mapped the key names directly
+
+% Flags. We don't add lots of individual keys but map the key names directly
 %    \begin{macrocode}
-\keys_define:nn { pdffield / checkbox }
+\keys_define:nn { pdffield }
   {
-    ,setfieldflags .code:n =
+    ,setFf .code:n =
       {
           \clist_map_inline:nn {#1}
            {
              \bitset_set_true:Nn \l_@@_Ff_bitset {##1}
            }
       }
+    ,setFf .groups:n = {field}
+    ,setfieldflags .meta:n =
+      {setFf={#1}}
     ,setfieldflags .groups:n = {field}
-    ,unsetfieldflags .code:n =
+    ,unsetFf .multichoice:
+    ,unsetFf / all .code:n = { \bitset_clear:N \l_@@_Ff_bitset}
+    ,unsetFf / unknown .code:n =
       {
-          \clist_map_inline:nn {#1}
-           {
-             \bitset_set_false:Nn \l_@@_Ff_bitset {##1}
-           }
+        \bitset_set_false:Nn \l_@@_Ff_bitset {#1}
       }
+    ,unsetFf .groups:n = {field}
+    ,unsetfieldflags .meta:n = {unsetFf={#1}}
     ,unsetfieldflags .groups:n = {field}
-    ,setannotflags .code:n =
+  }
+
+%    \end{macrocode}
+%
+%  Keys for the AA dictionary. They all trigger a javascript option.
+%  K=keystroke, F=format, V=validate, C=calculate
+%    \begin{macrocode}
+\cs_set_protected:Npn \@@_tmpa:n #1  %
+  {
+    \keys_define:nn { pdffield  }
       {
-          \clist_map_inline:nn {#1}
+         AA/#1 .code:n =
            {
-             \bitset_set_true:Nn \l_@@_F_bitset {##1}
-           }
+             \pdf_string_from_unicode:nnN {utf8/string-raw}{##1}\l_@@_tmpa_str
+             \str_if_empty:NTF \l_@@_tmpa_str
+               {
+                 \pdfdict_remove:nn {l_@@/field/AA}{#1}
+               }
+               {
+                 \pdfdict_put:nnx {l_@@/field/AA}
+                  {#1}
+                  {<</S/JavaScript/JS(\l_@@_tmpa_str)>>}
+               }
+           },
+        AA/#1 .groups:n  = {field}
       }
-    ,unsetannotflags .code:n =
+  }
+
+\clist_map_inline:nn {K,F,V,C}{\@@_tmpa:n{#1}}
+
+\cs_set_protected:Npn \@@_tmpa:nn #1 #2
+  {
+    \keys_define:nn { pdffield  }
       {
-          \clist_map_inline:nn {#1}
-           {
-             \bitset_set_false:Nn \l_@@_F_bitset {##1}
-           }
+         #1 .meta:nn =
+           { pdffield }{AA/#2={##1}},
+        #1 .groups:n  = {field}
       }
   }
+\@@_tmpa:nn {keystroke}{K}
+\@@_tmpa:nn {format}   {F}
+\@@_tmpa:nn {validate} {V}
+\@@_tmpa:nn {calculate}{C}
+
+
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+\keys_define:nn { pdffield }
+  {
+    DA .code:n =
+     {
+       \tl_if_empty:nTF {#1}
+         {
+           \pdfdict_remove:nn { l_@@/field }{DA}
+         }
+         {
+           \pdfdict_put:nnx { l_@@/field }{DA}{ (#1) }
+         }
+      }
+    ,DA .groups:n = {field}
+    ,Q .choices:nn = {left,center,right}
+     {
+       \pdfdict_put:nnx { l_@@/field }{Q}{ \int_eval:n{\l_keys_choice_int-1} }
+     }
+    ,Q / .code:n = { \pdfdict_remove:nn { l_@@/field }{Q} }
+    ,Q .groups:n = {field}
+    ,align .meta:n={Q=#1}
+    ,DS .code:n =
+     {
+       \msg_warning:nnn {pdffield}{not-implemented}{DS}
+     }
+    ,DS .groups:n = {field}
+    ,RV .code:n =
+     {
+       \msg_warning:nnn {pdffield}{not-implemented}{RV}
+     }
+    ,RV .groups:n = {field}
+  }
+%    \end{macrocode}
+%
+% \subsection{Annotation keys}
+% The size of the field annotation
+%
+%    \begin{macrocode}
+\dim_new:N \l_@@_annot_ht_dim
+\dim_new:N \l_@@_annot_wd_dim
+\dim_new:N \l_@@_annot_dp_dim
 
-\keys_define:nn { pdffield / checkbox }
+\keys_define:nn { pdffield }
   {
-    appearance .code:n = %value is a name of an appearance
+    ,width  .dim_set:N = \l_@@_annot_wd_dim
+    ,height .dim_set:N = \l_@@_annot_ht_dim
+    ,depth  .dim_set:N = \l_@@_annot_dp_dim
+    ,width  .initial:n = 0pt
+    ,height .initial:n = 0pt
+    ,depth  .initial:n = 0pt
+  }
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+\keys_define:nn { pdffield }
+ {
+   %parent is defined in field
+  ,AS .code:n =
+    {
+      \tl_if_empty:nTF {#1}
+        {
+          \pdfannot_dict_remove:nn { widget }{AS}
+        }
+        {
+          \pdfannot_dict_put:nnx {widget}{AS}{\pdf_name_from_unicode_e:n{#1}}
+        }
+    }
+  ,AS .groups:n = annot
+ }
+\cs_new_protected:Npn \@@_appearance_handler:nnn #1#2#3
+ {
+   \pdfxform_if_exist:nTF {  #1 }
+     {
+       \pdfannot_dict_put:nnx {widget/AP}{#2}
+         {
+           \pdfxform_ref:n {#1}
+         }
+     }
+     {
+       \msg_error:nnnn{pdffield}{appearance-missing}{#1}{#3}
+     }
+ }
+\keys_define:nn { pdffield }
+  {
+    AP/N .code:n =
       {
-        \pdfxform_if_exist:nTF {  @@_#1/Yes }
+        \tl_if_empty:nTF {#1}
           {
-            \pdfdict_put:nnn {l_@@/checkbox/annot/AP}
-              {N}
-              {
-                 <<
-                    /Yes ~ \pdfxform_ref:n { @@_#1/Yes}
-                    /Off ~ \pdfxform_ref:n { @@_#1/Off}
-                 >>
-              }
+            \pdfannot_dict_remove:nn { widget/AP }{N}
           }
           {
-            \msg_error:nnnn{pdffield}{appearance-missing}{#1}{normal}
+            \@@_appearance_handler:nnn {#1}{N}{normal}
           }
-      },
-    appearance .initial:n = checkbox/default,
+        }
+   ,AP/N .groups:n = annot
+   ,appearance .meta:n = {AP/N={#1}}
   }
-
-\keys_define:nn { pdffield / checkbox }
+\keys_define:nn { pdffield }
   {
-    rollover-appearance .code:n = %value is a name of an appearance
+    AP/R .code:n =
       {
+        \tl_if_empty:nTF {#1}
+          {
+            \pdfannot_dict_remove:nn { widget/AP }{R}
+          }
+          {
+             \@@_appearance_handler:nnn {#1}{R}{rollover}
+          }
+        }
+   ,AP/R .groups:n = annot
+   ,rollover-appearance .meta:n = {AP/R={#1}}
+  }
+\keys_define:nn { pdffield }
+  {
+    AP/D .code:n =
+      {
+        \tl_if_empty:nTF {#1}
+          {
+            \pdfannot_dict_remove:nn { widget/AP }{D}
+          }
+          {
+             \@@_appearance_handler:nnn {#1}{D}{rollover}
+          }
+        }
+   ,AP/D .groups:n = annot
+   ,down-appearance .meta:n = {AP/D={#1}}
+  }
+
+\keys_define:nn { pdffield  }
+  {
+    MK/R .choices:nn = {0,90,180,270}
+     {
+       \pdfannot_dict_put:nnx {widget/MK}{R}{#1}
+     }
+   ,MK/R / .code:n =
+     {
+        \pdfannot_dict_remove:nn { widget/MK }{R}
+     }
+   ,MK/R .groups:n = annot
+   ,rotate .meta:n = {MK/R=#1}
+  }
+
+\keys_define:nn { pdffield  }
+  {
+    MK/BC .code:n =
+     {
        \tl_if_empty:nTF {#1}
-         {
-           \pdfdict_remove:nn {l_@@/checkbox/annot/AP} {R}
-         }
-         {
-           \pdfxform_if_exist:nTF {  @@_#1/Yes }
-             {
-               \pdfdict_put:nnn {l_@@/checkbox/annot/AP}
-                 {R}
-                 {
-                    <<
-                       /Yes ~ \pdfxform_ref:n { @@_#1/Yes}
-                       /Off ~ \pdfxform_ref:n { @@_#1/Off}
-                    >>
-                 }
-              }
-              {
-                \msg_warning:nnnn{pdffield}{appearance-missing}{#1}{rollover}
-              }
+        {
+          \pdfannot_dict_remove:nn { widget/MK }{BC}
+        }
+        {
+          \@@_color_set:nn {@@/tmp}{#1}
+          \color_export:nnN{@@/tmp}{space-sep-rgb}\l_@@_tmpa_tl
+          \pdfannot_dict_put:nnx {widget/MK}{BC}{[\l_@@_tmpa_tl]}
+        }
+     }
+    ,MK/BC .groups:n = annot
+   ,bordercolor .meta:n = {MK/BC=#1}
+  }
 
-         }
-      },
+\keys_define:nn { pdffield  }
+  {
+    MK/BG .code:n =
+     {
+       \tl_if_empty:nTF {#1}
+        {
+          \pdfannot_dict_remove:nn { widget/MK }{BG}
+        }
+        {
+          \@@_color_set:nn {@@/tmp}{#1}
+          \color_export:nnN{@@/tmp}{space-sep-rgb}\l_@@_tmpa_tl
+          \pdfannot_dict_put:nnx {widget/MK}{BG}{[\l_@@_tmpa_tl]}
+        }
+     }
+    ,MK/BG .groups:n = annot
+   ,bordercolor .meta:n = {MK/BG=#1}
   }
 
-\keys_define:nn { pdffield / checkbox }
+
+\keys_define:nn { pdffield  }
   {
-    down-appearance .code:n = %value is a name of an appearance
-      {
+    MK/CA .code:n =
+     {
        \tl_if_empty:nTF {#1}
-         {
-           \pdfdict_remove:nn {l_@@/checkbox/annot/AP} {D}
-         }
-         {
-           \pdfxform_if_exist:nTF {  @@_#1/Yes }
+        {
+          \pdfannot_dict_remove:nn { widget/MK }{CA}
+        }
+        {
+          \pdf_string_from_unicode:nnN {utf8/string}{#1}\l_@@_tmpa_str
+          \pdfannot_dict_put:nnx {widget/MK}{CA}{\l_@@_tmpa_str}
+        }
+     }
+    ,MK/CA .groups:n = annot
+   ,caption .meta:n = {MK/CA=#1}
+  }
+
+\cs_set_protected:Npn \@@_tmpa:n #1
+ {
+   \keys_define:nn { pdffield  }
+     {
+       MK/#1 .code:n =
+        {
+          \tl_if_empty:nTF {##1}
             {
-              \pdfdict_put:nnn {l_@@/checkbox/annot/AP}
-                {D}
-                {
-                   <<
-                      /Yes ~ \pdfxform_ref:n { @@_#1/Yes}
-                      /Off ~ \pdfxform_ref:n { @@_#1/Off}
-                   >>
-                }
+              \pdfannot_dict_remove:nn { widget/AP }{#1}
             }
             {
-              \msg_warning:nnnn{pdffield}{appearance-missing}{#1}{down}
+              \pdfannot_dict_put:nnx {widget/MK}{#1}{##1}
             }
-         }
-      },
+        }
+      ,MK/#1 .groups:n = annot
+     }
+ }
+
+\clist_map_inline:nn {RC,AC,I,RI,IX,IF,TP}
+  { \@@_tmpa:n {#1} }
+%    \end{macrocode}
+% Flags.
+%    \begin{macrocode}
+\keys_define:nn { pdffield  }
+  {
+    ,setF .code:n =
+      {
+          \clist_map_inline:nn {#1}
+           {
+             \bitset_set_true:Nn \l_@@_F_bitset {##1}
+           }
+      }
+    ,setF .groups:n = annot
+    ,setannotflags .meta:nn =
+      { pdffield }{setF={#1}}
+    ,setannotflags .groups:n = annot
+    ,unsetF .multichoice:
+    ,unsetF / all .code:n = { \bitset_clear:N \l_@@_F_bitset}
+    ,unsetF / unknown .code:n =
+      {
+        \bitset_set_false:Nn \l_@@_F_bitset {#1}
+      }
+    ,unsetF .groups:n = annot
+    ,unsetannotflags .meta:nn =
+      { pdffield }{unsetF= {#1} }
+    ,unsetannotflags .groups:n = annot
   }
+
 %    \end{macrocode}
 %
-%  Keys for the AA dictionary. They all trigger javascript option.
-%  \begin{macro}{\@@_define_AAaction_key:nnn}
+% Keys for the AA dictionary. They all trigger a javascript option.
+% Fo = onfocus, Bl = onblur, D = onmousedown, U = onmouseup,
+% E = onenter, X = onexit, PO = pageopen, PC = pageclose,
+% PV = pagevisible, PI = pageinvisible
 %    \begin{macrocode}
-\pdfdict_new:n {l_@@/checkbox/annot/AA}
-\pdfdict_new:n {l_@@/checkbox/field/AA}
-
-\cs_new_protected:Npn \@@_define_AAaction_key:nnn #1 #2 #3 %#1 key, #2 pdf, #3 dict
+\cs_set_protected:Npn \@@_tmpa:n #1  %
   {
-    \keys_define:nn { pdffield / checkbox }
+    \keys_define:nn { pdffield }
       {
-         #1 .code:n =
+         AA/#1 .code:n =
            {
-             \pdf_string_from_unicode:nnN {utf8/string}{##1}\l_@@_tmpa_str
+             \pdf_string_from_unicode:nnN {utf8/string-raw}{##1}\l_@@_tmpa_str
              \str_if_empty:NTF \l_@@_tmpa_str
                {
-                 \pdfdict_remove:nn {l_@@/checkbox/#3/AA}{#2}
+                 \pdfannot_dict_remove:nn {widget/AA}{#1}
                }
                {
-                 \pdfdict_put:nnx {l_@@/checkbox/#3/AA}
-                  {#2}
-                  {<</S/JavaScript/JS\l_@@_tmpa_str>>}
+                 \pdfannot_dict_put:nnx {widget/AA}
+                  {#1}
+                  {<</S/JavaScript/JS(\l_@@_tmpa_str)>>}
                }
            },
-        #1 .groups:n = {#3}
+         ,AA/#1 .groups:n = annot
+      }
+  }
+
+\clist_map_inline:nn {Fo,Bl,D,U,E,X,PO,PC,PV,PI}{\@@_tmpa:n{#1}}
+
+\cs_set_protected:Npn \@@_tmpa:nn #1 #2
+  {
+    \keys_define:nn { pdffield }
+      {
+         #1 .meta:nn =
+           { pdffield }{AA/#2={##1}},
+         #1 .groups:n = {annot}
       }
   }
-\@@_define_AAaction_key:nnn {keystroke}{K}{field}
-\@@_define_AAaction_key:nnn {format}   {F}{field}
-\@@_define_AAaction_key:nnn {validate} {V}{field}
-\@@_define_AAaction_key:nnn {calculate}{C}{field}
-\@@_define_AAaction_key:nnn {onfocus}  {Fo}{annot}
-\@@_define_AAaction_key:nnn {onblur}   {Bl}{annot}
-\@@_define_AAaction_key:nnn {onmousedown}{D}{annot}
-\@@_define_AAaction_key:nnn {onmouseup}{U}{annot}
-\@@_define_AAaction_key:nnn {onenter}  {E}{annot}
-\@@_define_AAaction_key:nnn {onexit}   {X}{annot}
+\@@_tmpa:nn {onfocus}  {Fo}
+\@@_tmpa:nn {onblur}   {Bl}
+\@@_tmpa:nn {onmousedown}{D}
+\@@_tmpa:nn {onmouseup}{U}
+\@@_tmpa:nn {onenter}  {E}
+\@@_tmpa:nn {onexit}   {X}
+%    \end{macrocode}
+% \subsection{Appearances}
+% \begin{macro}{\pdffield_appearance:nn}
+%    \begin{macrocode}
+\cs_new_protected:Npn \pdffield_appearance:nn #1 #2
+  {
+     \pdfxform_new:nnn {#1}{}{#2}
+  }
+
+\cs_set_eq:NN \pdffield_store_appearance:nn\pdffield_appearance:nn
 %    \end{macrocode}
 % \end{macro}
-% \subsection{user commands}
-% \begin{macro}{\pdffield_checkbox:n,\pdffield_setup:nn}
+% \subsection{Setup command}
+%
 %    \begin{macrocode}
-\cs_set_eq:NN \pdffield_checkbox:n \@@_checkbox_add:n
+\keys_define:nn { pdffield / setup }
+  {
+    ,create-style .code:n  = { \@@_style_create:nn #1 }
+    ,preset-checkbox .code:n =
+      {
+        \keys_define:nn { pdffield }
+         {
+           @@/preset/checkbox .meta:n = {#1},
+         }
+      }
+   ,preset-textfield .code:n =
+      {
+        \keys_define:nn { pdffield }
+         {
+           @@/preset/textfield .meta:n = {#1},
+         }
+      }
+  }
+\keys_set:nn{ pdffield / setup }{preset-checkbox={}}
+\keys_set:nn{ pdffield / setup }{preset-textfield={}}
 
-\cs_new_protected:Npn \pdffield_setup:nn #1 #2
- {
-   \keys_set:nn {pdffield / #1 } {#2}
- }
+\cs_new_protected:Npn \@@_style_create:nn #1#2
+  {
+    \keys_define:nn { pdffield }
+      {
+        @@/style/#1 .meta:n = {#2},
+      }
+  }
+
+
+\cs_new_protected:Npn \pdffield_setup:n #1
+  {
+     \keys_set:nn{ pdffield / setup }{#1}
+  }
+
+\keys_define:nn { pdffield }
+  {
+    style .code:n = {\keys_set:nn {pdffield}{@@/style/#1={#1}}}
+  }
+%    \end{macrocode}
+%    \begin{macrocode}
 %</package>
 %    \end{macrocode}
-% \end{macro}
 %\end{implementation}
-
-\endinput%
-%%%%
-%
-%Field dict
-%Ft     : /Btn /Tx /Ch /Sig
-%Parent : OR
-%Kids: array, other fields or annot/widget
-%T: partial fieldname (test string)
-%TU: alternate description (test string)
-%TM: mapping name
-%Q integer (variable text field)
-%Ff: flags ->pdffield/checkbox/field
-%V: value            % not pushbutton
-%DV: default value   % not pushbutton
-%AA: Action dict ... -> see below
-%Opt: array of strings, connected to kids
-%     or for choices, choices
-%TI integer (lists)
-%I array Ch (complicated ...)
-%
-%/DA ( 0 0 1 rg /Ti 12 Tf ) %text field
-%/MaxLen                    %text field
-%
-%Lock dict (Sig)
-%SV dict (Sig)
-%
-%
-%
-%
-%Connected widget:
-%/AS default appearance from AP ( here/Yes or /Off)
-%% Appearance
-%%checkbox
-%/AP <</N <</Yes 2 0 R /Off 3 0 R>>>>
-%/C / Border /BS
-%
-%/OC ?
-%/Structparens?
-%/F flags
-%
-%
-%AA: Submit:
-%  /S   /SubmitForm
-%  /F   file /URI (/F ( ftp : / / www . beatles . com / Movies / AbbeyRoad . mov )
-%  /Fields array
-%
-%  /S /ImportData
-%  /F file
-%
-%  /S /ResetData
-%  /Fields array
-%
-%  /S /JavaScript
-%  /JS text string or stream
-%  %\pdf_flag_new:nn {annot/field/submit} %name is wrong ...
-%  {
-%    Include/Exclude       = 0,
-%    IncludeNoValueFields  = 1,
-%    ExportFormat          = 2,
-%    GetMethod             = 3, % if ExportFormat=0 -> =0 to
-%    SubmitCoordinates     = 4, % if ExportFormat=0 -> =0 to
-%    XFDF                  = 5,
-%    IncludeAppendSaves    = 6,
-%    IncludeAnnotations    = 7,
-%    SubmitPDF             = 8,
-%    CanonicalFormat       = 9,
-%    ExclNonUserAnnots     = 10,
-%    ExclFKey              = 11,
-%    EmbedForm             = 12
-%  }
-% source: %adapted from https://chat.stackexchange.com/transcript/message/54421537#54421537
+%
+% \PrintIndex
-- 
cgit v1.2.3

