summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/pdfmanagement-testphase
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
parent269940e8e52b921a855083542b9e1109af49af09 (diff)
CTAN sync 202106150301
Diffstat (limited to 'macros/latex/contrib/pdfmanagement-testphase')
-rw-r--r--macros/latex/contrib/pdfmanagement-testphase/CHANGELOG.md35
-rw-r--r--macros/latex/contrib/pdfmanagement-testphase/README.md2
-rw-r--r--macros/latex/contrib/pdfmanagement-testphase/color-ltx.sty2
-rw-r--r--macros/latex/contrib/pdfmanagement-testphase/hyperref-generic.dtx27
-rw-r--r--macros/latex/contrib/pdfmanagement-testphase/hyperref-generic.pdfbin947436 -> 947285 bytes
-rw-r--r--macros/latex/contrib/pdfmanagement-testphase/hyperxmp-patches-tmp-ltx.sty2
-rw-r--r--macros/latex/contrib/pdfmanagement-testphase/l3backend-testphase.dtx14
-rw-r--r--macros/latex/contrib/pdfmanagement-testphase/l3backend-testphase.pdfbin588344 -> 588643 bytes
-rw-r--r--macros/latex/contrib/pdfmanagement-testphase/l3pdfannot.dtx4
-rw-r--r--macros/latex/contrib/pdfmanagement-testphase/l3pdfannot.pdfbin573518 -> 573830 bytes
-rw-r--r--macros/latex/contrib/pdfmanagement-testphase/l3pdfdict.dtx4
-rw-r--r--macros/latex/contrib/pdfmanagement-testphase/l3pdfdict.pdfbin526914 -> 527359 bytes
-rw-r--r--macros/latex/contrib/pdfmanagement-testphase/l3pdffield-action.dtx813
-rw-r--r--macros/latex/contrib/pdfmanagement-testphase/l3pdffield-action.pdfbin0 -> 547960 bytes
-rw-r--r--macros/latex/contrib/pdfmanagement-testphase/l3pdffield-checkbox.dtx187
-rw-r--r--macros/latex/contrib/pdfmanagement-testphase/l3pdffield-checkbox.pdfbin438103 -> 530998 bytes
-rw-r--r--macros/latex/contrib/pdfmanagement-testphase/l3pdffield-choice.dtx672
-rw-r--r--macros/latex/contrib/pdfmanagement-testphase/l3pdffield-choice.pdfbin0 -> 534214 bytes
-rw-r--r--macros/latex/contrib/pdfmanagement-testphase/l3pdffield-pushbutton.dtx765
-rw-r--r--macros/latex/contrib/pdfmanagement-testphase/l3pdffield-pushbutton.pdfbin0 -> 526289 bytes
-rw-r--r--macros/latex/contrib/pdfmanagement-testphase/l3pdffield-radiobutton.dtx835
-rw-r--r--macros/latex/contrib/pdfmanagement-testphase/l3pdffield-radiobutton.pdfbin296047 -> 576391 bytes
-rw-r--r--macros/latex/contrib/pdfmanagement-testphase/l3pdffield-textfield.dtx215
-rw-r--r--macros/latex/contrib/pdfmanagement-testphase/l3pdffield-textfield.pdfbin419934 -> 505625 bytes
-rw-r--r--macros/latex/contrib/pdfmanagement-testphase/l3pdffield.dtx722
-rw-r--r--macros/latex/contrib/pdfmanagement-testphase/l3pdffield.pdfbin619765 -> 739350 bytes
-rw-r--r--macros/latex/contrib/pdfmanagement-testphase/l3pdffile.dtx36
-rw-r--r--macros/latex/contrib/pdfmanagement-testphase/l3pdffile.pdfbin551626 -> 553291 bytes
-rw-r--r--macros/latex/contrib/pdfmanagement-testphase/l3pdfmanagement.dtx11
-rw-r--r--macros/latex/contrib/pdfmanagement-testphase/l3pdfmanagement.pdfbin658596 -> 659120 bytes
-rw-r--r--macros/latex/contrib/pdfmanagement-testphase/l3pdfmeta.dtx43
-rw-r--r--macros/latex/contrib/pdfmanagement-testphase/l3pdfmeta.pdfbin661637 -> 663941 bytes
-rw-r--r--macros/latex/contrib/pdfmanagement-testphase/l3pdftools.dtx5
-rw-r--r--macros/latex/contrib/pdfmanagement-testphase/l3pdftools.pdfbin517767 -> 518384 bytes
-rw-r--r--macros/latex/contrib/pdfmanagement-testphase/l3pdfxform.dtx4
-rw-r--r--macros/latex/contrib/pdfmanagement-testphase/l3pdfxform.pdfbin435558 -> 436061 bytes
-rw-r--r--macros/latex/contrib/pdfmanagement-testphase/ltdocinit.dtx17
-rw-r--r--macros/latex/contrib/pdfmanagement-testphase/ltdocinit.pdfbin552201 -> 553013 bytes
-rw-r--r--macros/latex/contrib/pdfmanagement-testphase/pdflscape-ltx.sty4
-rw-r--r--macros/latex/contrib/pdfmanagement-testphase/pdfmanagement-firstaid.dtx4
-rw-r--r--macros/latex/contrib/pdfmanagement-testphase/pdfmanagement-firstaid.pdfbin421911 -> 422418 bytes
-rw-r--r--macros/latex/contrib/pdfmanagement-testphase/pdfmanagement-testphase.dtx6
-rw-r--r--macros/latex/contrib/pdfmanagement-testphase/pdfmanagement-testphase.ins4
-rw-r--r--macros/latex/contrib/pdfmanagement-testphase/pdfmanagement-testphase.pdfbin446163 -> 446685 bytes
-rw-r--r--macros/latex/contrib/pdfmanagement-testphase/transparent-ltx.sty2
-rw-r--r--macros/latex/contrib/pdfmanagement-testphase/xcolor-patches-tmp-ltx.sty2
46 files changed, 4227 insertions, 210 deletions
diff --git a/macros/latex/contrib/pdfmanagement-testphase/CHANGELOG.md b/macros/latex/contrib/pdfmanagement-testphase/CHANGELOG.md
index d114f50eed..9d7e75843d 100644
--- a/macros/latex/contrib/pdfmanagement-testphase/CHANGELOG.md
+++ b/macros/latex/contrib/pdfmanagement-testphase/CHANGELOG.md
@@ -5,14 +5,41 @@ first release 0.95a, 2021-02-23 will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
this project uses date-based 'snapshot' version identifiers.
-## [2021-05-14
+## [2021-06-14]
+### Added
+ - l3pdffile: \pdffile_filespec:nnn to create a filespec dictionary
+ - l3pdffield: sortkey and code for calculate actions
+ - l3pdffield-radiobutton, a module for radiobuttons
+ - l3pdffield-pushbutton, a module for pushbuttons
+ - l3pdffield-choice, a module for choice fields
+ - l3pdffield-action, a module for reset/submit/import actions
+ - l3pdffield: \pdffield_annot_ref_last:, needed for tagging in OBJR object.
+ - \pdffile_filespec:nnn to create a filespec dictionary
+ - l3pdfmeta, ltdocinit: support for pdf A-2u and A-3u
+ - l3pdffield: tagging support for form fields
+
+### Fixed
+ - l3pdftools: utf8/URI didn't handle "?"
+ - l3pdffield: encoding of value in l3pdffield-textfield
+ - l3pdffield: encoding of value of TM and TU key
+ - utf8/URI in l3pdftools didn't handle ?
+ - option handling of pdflscape-ltx
+ - distiller failed due to empty /PAGES
+ - small bugs in the hyperref driver
+
+### Changed
+ - l3pdffield: handling of ECMAscript in /AA keys
+ - no longer force unicode in the generic hyperref driver as
+ it is the default where sensible anyway and clashes with platex.
+
+## [2021-05-14]
### Fixed
- xcolor patch for [ps] type used in pstricks
- value of citecolor wasn't expanded (errored with tcolorbox)
- \url, \href, \hrefurl, \hrefrun and \hrefpdf leaves now vmode
- - handling of pdfauthor, pdftitle and pdfsubject in hyperxmp patch
-
-### Changes
+ - handling of pdfauthor, pdftitle and pdfsubject in hyperxmp patch
+
+### Changed
- the module for formfield and checkboxes has been in part rewritten to
better fit to the new module for textfield.
Keys and documentation has been extended.
diff --git a/macros/latex/contrib/pdfmanagement-testphase/README.md b/macros/latex/contrib/pdfmanagement-testphase/README.md
index 49840245c6..8f1a3ff674 100644
--- a/macros/latex/contrib/pdfmanagement-testphase/README.md
+++ b/macros/latex/contrib/pdfmanagement-testphase/README.md
@@ -1,6 +1,6 @@
# LaTeX PDF management testphase bundle
-Version: 0.95d, 2021-05-14
+Version: 0.95e, 2021-06-14
This package is used during a test phase to load the new PDF management code
of LaTeX.
diff --git a/macros/latex/contrib/pdfmanagement-testphase/color-ltx.sty b/macros/latex/contrib/pdfmanagement-testphase/color-ltx.sty
index d8a6c9c408..e2a9e0059d 100644
--- a/macros/latex/contrib/pdfmanagement-testphase/color-ltx.sty
+++ b/macros/latex/contrib/pdfmanagement-testphase/color-ltx.sty
@@ -22,7 +22,7 @@
%% This file has the LPPL maintenance status "maintained".
%%
\NeedsTeXFormat{LaTeX2e}[1995/12/01]
-\ProvidesPackage{color-ltx}[2021-05-14 v0.95d
+\ProvidesPackage{color-ltx}[2021-06-14 v0.95e
Standard LaTeX Color (patched for l3color, part of pdfmanagement-testphase, original version 2021/03/07 v1.2e) (DPC)]
\edef\Gin@codes{%
\catcode`\noexpand\^^A\the\catcode`\^^A\relax
diff --git a/macros/latex/contrib/pdfmanagement-testphase/hyperref-generic.dtx b/macros/latex/contrib/pdfmanagement-testphase/hyperref-generic.dtx
index 30266d866c..c120f0060e 100644
--- a/macros/latex/contrib/pdfmanagement-testphase/hyperref-generic.dtx
+++ b/macros/latex/contrib/pdfmanagement-testphase/hyperref-generic.dtx
@@ -86,7 +86,7 @@
% }^^A
% }
%
-% \date{Version 0.95d, released 2021-05-14}
+% \date{Version 0.95e, released 2021-06-14}
%
% \maketitle
% \begin{documentation}
@@ -922,7 +922,7 @@
%<@@=hyp>
% \end{macrocode}
% \begin{macrocode}
-\ProvidesFile{hgeneric-testphase.def}[2021-05-14 v0.95d %
+\ProvidesFile{hgeneric-testphase.def}[2021-06-14 v0.95e %
generic Hyperref driver for the LaTeX PDF management testphase bundle]
\RequirePackage{etoolbox} %why?
@@ -1124,14 +1124,6 @@
\def\Hy@numberline#1{#1\c_space_tl} %needed by bookmark
% \end{macrocode}
%
-% We force unicode as option. As bookmarks are still using \cs{pdfstringdef}
-% we also need to load puenc.def.
-% \begin{macrocode}
-\HyPsd@LoadUnicode
-\Hy@unicodetrue
-\let\HyPsd@pdfencoding\HyPsd@pdfencoding@unicode
-\Hy@DisableOption{unicode}
-% \end{macrocode}
% The pdfversion should be set in \cs{DeclareDocumentMetadata} but we must
% copy it to the \pkg{hyperref} command:
% \begin{macrocode}
@@ -1214,7 +1206,7 @@
,run-parameter .tl_set:N = \l_@@_href_run_parameter_tl
,nextactionraw .code:n =
{ %perhaps some safety match later, see hyperref code
- \tl_if_empty:nTF
+ \tl_if_empty:nTF {#1}
{
\pdfdict_remove:nn{l_hyp/annot/A}{Next}
}
@@ -3335,7 +3327,7 @@
}
,pdfpagescrop .code:n =
{
- \tl_if_empty:nTF %or blank?
+ \tl_if_empty:nTF {#1} %or blank?
{
\pdfmanagement_remove:nn {Pages} { CropBox }
}
@@ -3962,6 +3954,16 @@
#1 .code:n= { \@@_store_metadata:nn {#1}{##1}}
}
}
+
+\str_if_eq:eeT {A}{\pdfmeta_standard_item:n{type}}
+ {
+ \exp_args:Nnx
+ \keys_set:nn {hyp / setup}
+ {
+ ,pdfapart = \pdfmeta_standard_item:n {level}
+ ,pdfaconformance = \pdfmeta_standard_item:n {conformance}
+ }
+ }
% \end{macrocode}
%
% \subsection{Transitions}
@@ -4219,6 +4221,7 @@
\seq_sort:Nn \l_@@_tmpa_seq
{
\int_compare:nNnTF { \pdf@strcmp{##1}{##2} } > { 0 }
+ %\str_compare:nNnTF {##1} > {##2}
{ \sort_return_swapped: }
{ \sort_return_same: }
}
diff --git a/macros/latex/contrib/pdfmanagement-testphase/hyperref-generic.pdf b/macros/latex/contrib/pdfmanagement-testphase/hyperref-generic.pdf
index fb13e4b8e6..f8f62974fe 100644
--- a/macros/latex/contrib/pdfmanagement-testphase/hyperref-generic.pdf
+++ b/macros/latex/contrib/pdfmanagement-testphase/hyperref-generic.pdf
Binary files differ
diff --git a/macros/latex/contrib/pdfmanagement-testphase/hyperxmp-patches-tmp-ltx.sty b/macros/latex/contrib/pdfmanagement-testphase/hyperxmp-patches-tmp-ltx.sty
index ab8723947e..b6c5de36a3 100644
--- a/macros/latex/contrib/pdfmanagement-testphase/hyperxmp-patches-tmp-ltx.sty
+++ b/macros/latex/contrib/pdfmanagement-testphase/hyperxmp-patches-tmp-ltx.sty
@@ -19,7 +19,7 @@
%
% for those people who are interested.
\NeedsTeXFormat{LaTeX2e}[2020/10/01]
-\ProvidesExplPackage{hyperxmp-patches-tmp-ltx}{2021-05-14}{0.95d}
+\ProvidesExplPackage{hyperxmp-patches-tmp-ltx}{2021-06-14}{0.95e}
{Store hyperref metadata in XMP format / temporay patches to test pdfresource management ... UF}
\cs_if_exist:NT \pdfmanagement_add:nnn
diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3backend-testphase.dtx b/macros/latex/contrib/pdfmanagement-testphase/l3backend-testphase.dtx
index 497491f3b7..4ef756feb4 100644
--- a/macros/latex/contrib/pdfmanagement-testphase/l3backend-testphase.dtx
+++ b/macros/latex/contrib/pdfmanagement-testphase/l3backend-testphase.dtx
@@ -45,7 +45,7 @@
% }^^A
% }
%
-% \date{Version 0.95d, released 2021-05-14}
+% \date{Version 0.95e, released 2021-06-14}
%
% \maketitle
%
@@ -56,27 +56,27 @@
% \begin{macrocode}
%<drivers>\ProvidesExplFile
%<*dvipdfmx>
- {l3backend-testphase-dvipdfmx.def}{2021-05-14}{}
+ {l3backend-testphase-dvipdfmx.def}{2021-06-14}{}
{LaTeX~PDF~management~testphase~bundle~backend~support: dvipdfmx}
%</dvipdfmx>
%<*dvips>
- {l3backend-testphase-dvips.def}{2021-05-14}{}
+ {l3backend-testphase-dvips.def}{2021-06-14}{}
{LaTeX~PDF~management~testphase~bundle~backend~support: dvips}
%</dvips>
%<*dvisvgm>
- {l3backend-testphase-dvisvgm.def}{2021-05-14}{}
+ {l3backend-testphase-dvisvgm.def}{2021-06-14}{}
{LaTeX~PDF~management~testphase~bundle~backend~support: dvisvgm}
%</dvisvgm>
%<*luatex>
- {l3backend-testphase-luatex.def}{2021-05-14}{}
+ {l3backend-testphase-luatex.def}{2021-06-14}{}
{LaTeX~PDF~management~testphase~bundle~backend~support: PDF output (LuaTeX)}
%</luatex>
%<*pdftex>
- {l3backend-testphase-pdftex.def}{2021-05-14}{}
+ {l3backend-testphase-pdftex.def}{2021-06-14}{}
{LaTeX~PDF~management~testphase~bundle~backend~support: PDF output (pdfTeX)}
%</pdftex>
%<*xdvipdfmx>
- {l3backend-testphase-xetex.def}{2021-05-14}{}
+ {l3backend-testphase-xetex.def}{2021-06-14}{}
{LaTeX~PDF~management~testphase~bundle~backend~support: XeTeX}
%</xdvipdfmx>
% \end{macrocode}
diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3backend-testphase.pdf b/macros/latex/contrib/pdfmanagement-testphase/l3backend-testphase.pdf
index 6e8a0d0155..b2d8378135 100644
--- a/macros/latex/contrib/pdfmanagement-testphase/l3backend-testphase.pdf
+++ b/macros/latex/contrib/pdfmanagement-testphase/l3backend-testphase.pdf
Binary files differ
diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3pdfannot.dtx b/macros/latex/contrib/pdfmanagement-testphase/l3pdfannot.dtx
index c8eddc0806..17cb4db002 100644
--- a/macros/latex/contrib/pdfmanagement-testphase/l3pdfannot.dtx
+++ b/macros/latex/contrib/pdfmanagement-testphase/l3pdfannot.dtx
@@ -52,7 +52,7 @@
% }^^A
% }
%
-% \date{Version 0.95d, released 2021-05-14}
+% \date{Version 0.95e, released 2021-06-14}
%
% \maketitle
% \begin{documentation}
@@ -397,7 +397,7 @@
% \begin{macrocode}
%<@@=pdfannot>
%<*header>
-\ProvidesExplPackage{l3pdfannot}{2021-05-14}{0.95d}
+\ProvidesExplPackage{l3pdfannot}{2021-06-14}{0.95e}
{PDF-annotations}
\RequirePackage{l3pdfdict}
%</header>
diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3pdfannot.pdf b/macros/latex/contrib/pdfmanagement-testphase/l3pdfannot.pdf
index 8025552014..ccd2853d25 100644
--- a/macros/latex/contrib/pdfmanagement-testphase/l3pdfannot.pdf
+++ b/macros/latex/contrib/pdfmanagement-testphase/l3pdfannot.pdf
Binary files differ
diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3pdfdict.dtx b/macros/latex/contrib/pdfmanagement-testphase/l3pdfdict.dtx
index b23ff4508f..2c30250932 100644
--- a/macros/latex/contrib/pdfmanagement-testphase/l3pdfdict.dtx
+++ b/macros/latex/contrib/pdfmanagement-testphase/l3pdfdict.dtx
@@ -53,7 +53,7 @@
% }^^A
% }
%
-% \date{Version 0.95d, released 2021-05-14}
+% \date{Version 0.95e, released 2021-06-14}
%
% \maketitle
% \begin{documentation}
@@ -212,7 +212,7 @@
% \begin{macrocode}
%<@@=pdfdict>
%<*header>
-\ProvidesExplPackage{l3pdfdict}{2021-05-14}{0.95d}
+\ProvidesExplPackage{l3pdfdict}{2021-06-14}{0.95e}
{Tools for PDF dictionaries (LaTeX PDF management testphase bundle)}
%</header>
% \end{macrocode}
diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3pdfdict.pdf b/macros/latex/contrib/pdfmanagement-testphase/l3pdfdict.pdf
index bb3eb95d68..d9633f9f28 100644
--- a/macros/latex/contrib/pdfmanagement-testphase/l3pdfdict.pdf
+++ b/macros/latex/contrib/pdfmanagement-testphase/l3pdfdict.pdf
Binary files differ
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
diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-action.pdf b/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-action.pdf
new file mode 100644
index 0000000000..b06750156a
--- /dev/null
+++ b/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-action.pdf
Binary files differ
diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-checkbox.dtx b/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-checkbox.dtx
index 681a8d7059..413b9ee317 100644
--- a/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-checkbox.dtx
+++ b/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-checkbox.dtx
@@ -68,7 +68,7 @@
% }^^A
% }
%
-% \date{Version 0.95d, released 2021-05-14}
+% \date{Version 0.95e, released 2021-06-14}
%
% \maketitle
% \begin{documentation}
@@ -116,14 +116,17 @@
% The |appearance| keys have a more checkbox specific
% behaviour, other keys have other defaults than with the basic commands.
% Additionally there
-% are a small number of keys specific to a checkbox.
+% are a small number of keys specific to a checkbox.
+% For convenience a number of important keys are documented here too, even if
+% they are already in the document from l3pdffield.
%
%
% Disabled keys are
% \begin{itemize}
% \item |V|, |DV|, |AS|: use |checked| instead.
% \item |FT| is overwritten.
-% \item For checkboxes only the field flags |ReadOnly|, |Required| and |NoExport| make sense.
+% \item For checkboxes only the field flags |ReadOnly|, |Required| and |NoExport|
+% make sense.
% |Radio|, |Pushbotton| are set automatically automatically by the code
% as this is required for a checkbox.
% \end{itemize}
@@ -140,7 +143,7 @@
% |name| = \meta{partial name}\\
% |T| = \meta{partial name}
% \end{syntax}
-% This sets like the |T| key for fields the partial name of the field. The value
+% This sets the partial name of the field. The value
% shouldn't contain a period, be not empty and sensibly consist of simple chars.
% Additionally the value is used to create the field ID.
% This means that checkboxes with the same partial name are annotations
@@ -157,7 +160,8 @@
% \end{syntax}
% \emph{For experts only!}
% This allows to give the checkbox field a specific ID. This is only useful
-% in the context of a larger fieldset or if you want to attach another annotation
+% in the context of a larger fieldset, if for example you want to use
+% the same partial name for more than one field, or if you want to attach another annotation
% to the field with \cs{pdffield_annot:n}. If used wrongly you can
% easily create invalid fieldset. It allows you to create to fields with the
% same partial name, but if you want to see both
@@ -219,8 +223,9 @@
% \meta{partial appearance name}|/Yes| and \meta{partial appearance name}|/Off|
% has been created. The initial value is |pdffield/checkbox/default|
% for the normal appearance and shows a \cs{texttimes}.
-% The other appearance are not set by default.
+% The other appearances are not set by default.
% \end{function}
+%
% \begin{function}{checked}
% \begin{syntax}
% |checked| = |true|\verb"|"|false|
@@ -231,6 +236,13 @@
% values for different instances, if one wants to confuse the user.
% \end{function}
%
+% \begin{function}{value,default}
+% \begin{syntax}
+% |value| = |Yes|\verb"|"|Off|\\
+% |default| = |Yes|\verb"|"|Off|\\
+% \end{syntax}
+% With checkboxes this two key are simply an alternative input for |checked|.
+% \end{function}
%
% \subsection{Using with hyperref}
% The \cs{CheckBox} command from hyperref also prints a label, something that the
@@ -265,26 +277,123 @@
% \end{documentation}
%
% \begin{implementation}
+% \DoNotIndex
+% {\\
+% ,\bitset_clear:N
+% ,\bitset_new:Nn
+% ,\bitset_set_false:Nn
+% ,\bitset_set_true:Nn
+% ,\bitset_to_arabic:N
+% ,\bool_new:N
+% ,\box_dp:N
+% ,\box_ht: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_set_protected:Npn
+% ,\cs_generate_variant:Nn
+% ,\cs_gset_eq:NN
+% ,\csname
+% ,\dim_eval:n
+% ,\dim_new:N
+% ,\endcsname
+% ,\exp_args:Ne
+% ,\fboxsep
+% ,\group_begin:
+% ,\group_end:
+% ,\hbox_to_wd:nn
+% ,\hfill
+% ,\hook_gput_code:nnn
+% ,\int_eval:n
+% ,\l_keys_choice_int
+% ,\keys_define:nn
+% ,\keys_set:nn
+% ,\mode_leave_vertical:
+% ,\msg_error:nnn
+% ,\msg_error:nnnn
+% ,\msg_new:nnn
+% ,\msg_warning:nn
+% ,\msg_warning:nnn
+% ,\msg_warning:nnnnn
+% ,\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_write:nn
+% ,\pdf_string_from_unicode:nnN
+% ,\pdfannot_box_ref_last:
+% ,\pdfannot_dict_put:nnn
+% ,\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
+% ,\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
+% ,\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_new:N
+% ,\tl_set:Nn
+% ,\tl_to_str:n
+% ,\use:c
+% }
% \section{\pkg{l3pdffield-checkbox} Implementation}
% \begin{macrocode}
%<*package>
%<@@=pdffield>
% \end{macrocode}
% \subsection{Variables}
-% \begin{macrocode}
-% \end{macrocode}
+% There are no specific variables.
% \subsection{Messages}
-% \begin{macrocode}
-% \end{macrocode}
+% There are no specific messages.
% \subsection{Appearances}
-% The default appearances are a cross (\cs{texttimes}),
-% Every appearance should have two versions and follow the naming
+% The default appearances are a quadratic frame with cross (\cs{texttimes}) if
+% checked.
+% User appearances should have two versions and follow the naming
% module/\meta{name}/Yes and module/\meta{name}/Off.
-% \begin{macro}{@@/checkbox/default_appearances:}
+% \begin{macro}
+% {
+% \@@_checkbox_default_appearances:,
+% pdffield/checkbox/default/Yes,
+% pdffield/checkbox/default/Off
+% }
% This defines the standard appearance. It is setup at the first
% use of a checkbox, and will adapt to the font family in use then.
% \begin{macrocode}
-\cs_new_protected:cn {@@/checkbox/default_appearances:}
+\cs_new_protected:Npn \@@_checkbox_default_appearances:
{
\pdffield_appearance:nn {pdffield/checkbox/default/Yes}
{
@@ -302,13 +411,14 @@
[ \dim_eval:n { \box_ht:N\strutbox+\box_dp:N\strutbox } ]
{ \phantom{\texttimes} \strut }
}
- \cs_gset_eq:cN {@@/checkbox/default_appearances:} \prg_do_nothing:
+ \cs_gset_eq:NN \@@_checkbox_default_appearances: \prg_do_nothing:
}
% \end{macrocode}
% \end{macro}
%
%\subsection{Creating the field}
% A field should be created if the name doesn't exist
+% \begin{macro}{ \@@_checkbox_field:n }
% \begin{macrocode}
\cs_new_protected:Npn \@@_checkbox_field:n #1 %name
{
@@ -320,15 +430,18 @@
}
\cs_generate_variant:Nn \@@_checkbox_field:n {V}
% \end{macrocode}
+% \end{macro}
% \subsection{Assembling the checkbox}
-
+%
% \begin{macro}{\@@_checkbox:n}
% \begin{macrocode}
\cs_new_protected:Npn \@@_checkbox:n #1
{
\group_begin:
- \use:c {@@/checkbox/default_appearances:}
+ \@@_checkbox_default_appearances:
\cs_set_eq:NN\@@_appearance_handler:nnn \@@_checkbox_appearance_handler:nnn
+ \cs_set_eq:NN\@@_value_handler:n \@@_checkbox_value_handler:n
+ \cs_set_eq:NN\@@_default_handler:n \@@_checkbox_default_handler:n
% \end{macrocode}
% Setting up the defaults.
% \begin{macrocode}
@@ -369,6 +482,8 @@
% Most keys are inherited simply the ones from the generic field and annot keys.
% A key to decide if the box is initially checked or not.
% We stay in the same family so that we can build a style.
+% \begin{macro}{checked}
+% This is a key specific for checkbox, it sets both field and annotation keys.
% \begin{macrocode}
\keys_define:nn { pdffield }
{
@@ -388,15 +503,41 @@
,checked .default:n = {true}
,checked .groups:n = {checkbox}
}
-% \end{macrocode}
-% And a key to set a dedicated field ID
-% \begin{macrocode}
-\keys_define:nn { pdffield }
+\keys_define:nn { pdffield }
{
- fieldID .tl_set:N = \l_@@_fieldID_tl
+ ,__value .choice:
+ ,__value / Off .code:n =
+ {
+ \pdfdict_put:nnx { l_@@/field }{V} { /Off }
+ \pdfdict_put:nnx { l_@@/field }{DV}{ /Off }
+ \pdfannot_dict_put:nnn {widget}{AS}{ /Off }
+ }
+ ,__value / Yes .code:n =
+ {
+ \pdfdict_put:nnx { l_@@/field }{V} { /Yes }
+ \pdfdict_put:nnx { l_@@/field }{DV}{ /Yes }
+ \pdfannot_dict_put:nnn {widget}{AS}{ /Yes }
+ }
}
% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\@@_checkbox_value_handler:n,\@@_checkbox_default_handler:n}
+% |value| and |default| do the same as checked.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_checkbox_value_handler:n #1
+ {
+ \keys_set:nn{pdffield}{__value={#1}}
+ }
+\cs_new_protected:Npn \@@_checkbox_default_handler:n #1
+ {
+ \keys_set:nn{pdffield}{__value={#1}}
+ }
+% \end{macrocode}
+% \end{macro}
% \begin{macro}{\@@_checkbox_appearance_handler:nnn}
+% Appearances must create a dictionary, so we define a special handler.
+% \Arg{name} is the xform name without the /Yes, /Off, \Arg{type} is N, R, or D,
+% \Arg{text} is a word for the error message.
% \begin{macrocode}
\cs_new_protected:Npn \@@_checkbox_appearance_handler:nnn #1 #2 #3 %name, type, text
{
@@ -431,3 +572,5 @@
% \end{macrocode}
% \end{macro}
%\end{implementation}
+
+% \PrintIndex
diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-checkbox.pdf b/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-checkbox.pdf
index e4b957a528..21354721c7 100644
--- a/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-checkbox.pdf
+++ b/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-checkbox.pdf
Binary files differ
diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-choice.dtx b/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-choice.dtx
new file mode 100644
index 0000000000..630552274a
--- /dev/null
+++ b/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-choice.dtx
@@ -0,0 +1,672 @@
+% \iffalse meta-comment
+%
+%% File: l3pdfpdffield-choice.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}
+\usepackage{l3pdffield-testphase}
+\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-choice} module\\ Commands to create choice 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-choice} Introduction}
+% This is the documentation for choice fields, for general information about form fields
+% check the documentation l3pdffield.
+%
+%
+% Please keep in mind
+% \begin{itemize}
+% \item Not every PDF viewer supports choice field.
+% \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 features of form fields too
+% (as you typically can't change the PDF).
+% \end{itemize}
+% \section{Choice fields}
+%
+% Choice fields are drop down menus or scrollable lists where
+% the user can select one or more entries. They can also contain a field where
+% users can insert a free text. The export value and the displayed value can differ.
+% Some values can be preselected.
+%
+% This means that various data will have to be set, and the sorting matters.
+% The module here will assume that the various values are stored in sequences:
+%
+% \ExplSyntaxOn
+% \seq_const_from_clist:Nn \c_my_values_seq {hippo,duck,bear}
+% \seq_const_from_clist:Nn \c_my_displayvalues_seq {Sieglinde,,Bär}
+% \seq_const_from_clist:Nn \c_my_defaultvalues_seq {duck,Bär} %check if export or altname ...
+% \ExplSyntaxOff
+%
+% Only the first sequence is required.
+% Empty values in the display sequence are possible, then the normal value is used.
+%
+% \subsection{Types}
+% Choice fields can be a drop down menu (called |Combo|), which can contain an editable
+% field.
+%
+% |setfieldflags={Combo,Edit}| or |setfieldflags={Combo}|
+%
+% If |Edit| is set, one can also set |DoNotSpellCheck|.
+%
+% Or they can be a list.
+%
+% |unsetfieldflags={Combo,Edit,DoNotSpellCheck}|
+%
+%
+% For both types it is possible to set or unset |MultiSelect| and |CommitOnSelChange|.
+%
+%
+% \subsection{Appearance}
+% hm ....
+%
+% \bigskip
+% \subsection{Commands}
+% \begin{function}{\pdffield_choice:n}
+% \begin{syntax}
+% \cs{pdffield_choice:n}\Arg{key val list}
+% \end{syntax}
+% This creates a choice field.
+% The list of allowed keys is described below.
+% The \meta{key val list} should at least set the name,
+% without it the default |choice| is used. Choice fields with the same
+% belong to the same field and if changed, the others are changed accordingly.
+% The default appearance ...
+%
+% The first choice field setups the field and so should setup values and field flags.
+% \end{function}
+%
+%
+% \subsection{Keys}
+%
+% The new choice command accept all field and annot keys from l3pdffield.
+% A few keys are disabled or are forced to specific values.
+% The |appearance| keys have a ...
+% behaviour, other keys have other defaults than with the basic commands.
+% Additionally there
+% are a small number of keys specific to a choice field.
+% |value| and |default| have a special meaning.
+%
+%
+% Disabled keys are
+% \begin{itemize}
+% \item |V|, |DV|, |AS|: they are set by the other keys.
+% \item |FT| is overwritten.
+% \item For fields only the field flags |ReadOnly|, |Required|, |NoExport|,
+% |Combo|, |Edit|, |MultiSelect|, |Sort|, |DoNotSpellCheck| and |CommitOnSelChange|
+% make sense. The code will force some values (e.g. disable |Edit| if |Combo| is false).
+% \end{itemize}
+%
+%
+% \begin{function}{preset-choice}
+% \begin{syntax}
+% |preset-choice| = \Arg{key-val-list}
+% \end{syntax}
+% This allows to set default keys for a choice field.
+% \end{function}
+%
+% \begin{function}{name,T}
+% \begin{syntax}
+% |name| = \meta{partial name}\\
+% |T| = \meta{partial name}
+% \end{syntax}
+% These keys set the partial name of the field. They both do the same
+% thing, use the one you are more comfortable with. The value
+% shouldn't contain a period, be not empty and sensibly consist of simple chars.
+% Additionally the value is used to create the field ID.
+% This means that choice field with the same partial name are annotations
+% with the same field as parent.
+% The field ID is then internal and can not be used to
+% attach another annotation.
+% For explicit control of the field ID use the |fieldID| key.
+% \end{function}
+%
+% \begin{function}{value,values}
+% \begin{syntax}
+% |value| = \Arg{comma separated list of values}
+% |values| = \Arg{comma separated list of values}
+% \end{syntax}
+% With these keys you set the export value names. \meta{comma separated list of values} should contain
+% the values in the order as wanted. The values are passed through |\pdf_string_from_unicode:nnN|
+% and can use unicode.
+% \end{function}
+%
+% \begin{function}{display-values}
+% \begin{syntax}
+% |display-values| = \Arg{comma separated list of values}
+% \end{syntax}
+% With this key you set the display value names if they should be
+% different from the export values. They should be given in the same order as the values.
+% The values are passed through |\pdf_string_from_unicode:nnN|
+% and can use unicode.
+% \end{function}
+%
+% \begin{function}{default,default-values}
+% \begin{syntax}
+% |default| = \Arg{comma separated list of values}
+% |default-values| = \Arg{comma separated list of values}
+% \end{syntax}
+% With this keys you set the values which are selected when the PDF is opened.
+% The use of this keys is a bit dubious. It seems to work okay for combo fields,
+% but not for list fields. According to the PDF reference the
+% values should be the display values, but it is not clear if the PDF viewer
+% really implement it that way or if the export value should be preferred.
+% Depending on the values it could be needed to
+% add also an |I| array to the field.
+% \end{function}
+
+% \begin{function}{top-index}
+% \begin{syntax}
+% |top-index| = \Arg{integer}
+% \end{syntax}
+% With this key you set for a scrollable list field the number of the
+% value shown at the top. The first value has number 1 (that is the default).
+% I'm not sure if viewers handle this correctly, so the setting should be used with
+% care.
+% \end{function}
+
+% \begin{function}{fieldID}
+% \begin{syntax}
+% |fieldID| = \meta{field ID}\\
+% \end{syntax}
+% \emph{For experts only!}
+% This allows to give the radio field a specific ID. This is only useful
+% in the context of a larger fieldset or if you want to attach another annotation
+% to the field with \cs{pdffield_annot:n}. If used wrongly you can
+% easily create invalid fieldset. It allows you to create to fields with the
+% same partial name, but if you want to see both
+% you need to ensure that their full names are
+% different---for example by adding some parent fields.
+% \end{function}
+%
+% \begin{function}{parent}
+% \begin{syntax}
+% |parent| = \meta{field ID}\\
+% \end{syntax}
+% This is only needed if the field should be part
+% of a larger fieldset. The value should be a field ID of a field created previously
+% with \cs{pdffield_field:nn}.
+% \end{function}
+%
+%
+% \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 choice field.
+% The value should be a dimension expression. By default
+% |width| and |height| and |depth| are ....
+% \end{function}
+%
+% \begin{function}{AP/N,appearance,AP/R,rollover-appearance,AP/D,down-appearance}
+% \begin{syntax}
+% |AP/N| = \meta{appearance name}\\
+% |appearance| = \meta{appearance name}\\
+% |AP/R| = \meta{appearance name}\\
+% |rollover-appearance| = \meta{appearance name}\\
+% |AP/D| = \meta{appearance name}\\
+% |down-appearance| = \meta{appearance name}
+% \end{syntax}
+% This adds appearances. \meta{appearance name} should be the name of an form Xobjects.
+% The default normal appearance is a simple gray background, the same as with
+% text fields.
+% \end{function}
+%
+% The font are handled in a similar way as in textfield. Most of the remarks made there
+% are true for choice fields too.
+%
+% \begin{function}{fontcolor}
+% \begin{syntax}
+% |fontcolor| = \meta{color expression} \verb"|" [\meta{model}]\Arg{values}\\
+% \end{syntax}
+% This is sets the color of font in the textfield. Internally currently RGB is used.
+% The colors used in
+% \meta{color expression} must be known to the \pkg{l3color} commands.
+% The initial color is black. It is a \emph{field} setting, that means instances
+% share the color.
+% \end{function}
+%
+% \begin{function}{fontsize}
+% \begin{syntax}
+% |fontsize| = \meta{dim expression}
+% \end{syntax}
+% This is sets the size of the font in the textfield.
+% The default value is the current font size (\cs{f@size} in pt).
+% It is a \emph{field} setting, that means instances
+% share the size.
+% \end{function}
+%
+% \begin{function}{font}
+% \begin{syntax}
+% |font| = \meta{symbolic font name}
+% \end{syntax}
+% This is sets the font in the textfield. See the discussion at the begin of
+% the documentation about some background. The default value is |Helv| and this
+% name is setup if you load hyperref and issue the \cs{Form} command.
+% The default value is the current font size (\cs{f@size} in pt).
+% It is a \emph{field} setting, that means instances
+% share the font.
+% \end{function}
+% \subsection{Using with hyperref}
+%
+% hyperref combines radio button and choice field in one command. This makes it
+% difficult to replicate the hyperref commands here.
+%
+% \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
+% ,\box_dp:N
+% ,\box_ht:N
+% ,\clist_map_inline:nn
+% ,\color_export:nnN
+% ,\color_set:nn
+% ,\color_set:nnn
+% ,\color_select:n
+% ,\cs_new_protected:Npn
+% ,\cs_new_protected:cpn
+% ,\cs_set_eq:NN
+% ,\cs_gset_eq:cN
+% ,\cs_set_protected:Npn
+% ,\cs_generate_variant:Nn
+% ,\cs_gset_eq:NN
+% ,\c_space_tl
+% ,\csname
+% ,\dim_eval:n
+% ,\dim_new:N
+% ,\dim_to_decimal_in_bp:n
+% ,\endcsname
+% ,\exp_args:Ne
+% ,\exp_args:Nc
+% ,\fboxsep
+% ,\fp_eval:n
+% ,\f@size
+% ,\group_begin:
+% ,\group_end:
+% ,\hbox_to_wd:nn
+% ,\hfill
+% ,\hook_gput_code:nnn
+% ,\int_eval:n
+% ,\int_compare:nNnT
+% ,\int_compare:nNnTF
+% ,\int_incr:N
+% ,\int_new:N
+% ,\int_use:N
+% ,\int_zero:N
+% ,\l_keys_choice_int
+% ,\keys_define:nn
+% ,\keys_set:nn
+% ,\mode_leave_vertical:
+% ,\msg_error:nnn
+% ,\msg_error:nnnn
+% ,\msg_new:nnn
+% ,\msg_warning:nn
+% ,\msg_warning:nnn
+% ,\msg_warning:nnnnn
+% ,\NeedsTeXFormat
+% ,\normalsize
+% ,\paperheight
+% ,\paperwidth
+% ,\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:nx
+% ,\pdf_object_write:nn
+% ,\pdf_string_from_unicode:nnN
+% ,\pdfannot_box_ref_last:
+% ,\pdfannot_dict_put:nnn
+% ,\pdfannot_dict_put:nnx
+% ,\pdfdict_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
+% ,\pdfmanagement_add:nnn
+% ,\pdfmeta_standard_verify:nTF
+% ,\pdfxform_if_exist:nTF
+% ,\pdfxform_new:nnn
+% ,\pdfxform_ref:n
+% ,\phantom
+% ,\prg_do_nothing:
+% ,\ProvidesExplPackage
+% ,\quark_if_no_value:NT
+% ,\raisebox
+% ,\RequirePackage
+% ,\rule
+% ,\seq_gput_right:Nn
+% ,\seq_gput_right:cV
+% ,\seq_gput_left:cV
+% ,\seq_if_in:cVF
+% ,\seq_map_break:
+% ,\seq_map_inline:Nn
+% ,\seq_new:c
+% ,\seq_use:cn
+% ,\seq_if_exist:NTF
+% ,\seq_new:N
+% ,\seq_use:Nn
+% ,\smash
+% ,\str_if_empty:NTF
+% ,\str_if_in:NnTF
+% ,\str_if_eq:nVTF
+% ,\str_new:N
+% ,\strut
+% ,\strutbox
+% ,\tl_put_right:Nn
+% ,\tl_if_empty:NTF
+% ,\tl_if_empty:NT
+% ,\tl_if_empty:NF
+% ,\tl_put_left:Nn
+% ,\tl_if_eq:NnF
+% ,\tl_if_empty:nTF
+% ,\tl_if_head_eq_charcode:nNTF
+% ,\tl_new:N
+% ,\tl_set:Nn
+% ,\tl_to_str:n
+% ,\use:c
+% }
+% \section{\pkg{l3pdffield-radiobutton} Implementation}
+% \begin{macrocode}
+%<*package>
+%<@@=pdffield>
+\RequirePackage{l3draw}
+% \end{macrocode}
+% \subsection{Variables}
+% \begin{variable}
+% {
+% \l_@@_choice_values_seq
+% ,\l_@@_choice_defaultvalues_seq
+% ,\l_@@_choice_displayvalues_seq
+% ,\l_@@_choice_opt_seq
+% }
+% variables to hold the value, the default value, and display variants. The opt
+% set will be used to build the content of opt
+% \begin{macrocode}
+\seq_new:N \l_@@_choice_values_seq
+\seq_new:N \l_@@_choice_defaultvalues_seq
+\seq_new:N \l_@@_choice_displayvalues_seq
+\seq_new:N \l_@@_choice_opt_seq
+% \end{macrocode}
+% \end{variable}
+%
+% \subsection{Appearances}
+% (probably take from textfield ...)
+%
+%\subsection{Creating the field}
+% A field should be created if the name doesn't exist yet
+% \begin{macro}{\@@_choice_field:n}
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_choice_field:n #1 %name
+ {
+ \pdf_object_if_exist:nF {@@/field/@@/choice/#1}
+ {
+% \end{macrocode}
+% We must at first build the Opt array.
+% \begin{macrocode}
+ \seq_clear:N \l_@@_choice_opt_seq
+ \seq_map_indexed_inline:Nn \l_@@_choice_values_seq
+ {
+ \pdf_string_from_unicode:nnN{utf16/hex}{##2}\l_@@_tmpa_str
+ \tl_set:Nx \l_@@_tmpa_tl {\seq_item:Nn \l_@@_choice_displayvalues_seq {##1} }
+ \tl_if_empty:NTF \l_@@_tmpa_tl
+ {
+ \seq_put_right:NV \l_@@_choice_opt_seq \l_@@_tmpa_str
+ }
+ {
+ \exp_args:NnV
+ \pdf_string_from_unicode:nnN{utf16/hex}\l_@@_tmpa_tl\l_@@_tmpb_str
+ \seq_put_right:Nx \l_@@_choice_opt_seq
+ { [ \l_@@_tmpa_str\c_space_tl\l_@@_tmpb_str] }
+ }
+ }
+ \pdf_object_unnamed_write:nx {array}{\seq_use:Nn\l_@@_choice_opt_seq {~}}
+ \pdfdict_put:nnx { l_@@/field }{Opt} { \pdf_object_ref_last: }
+% \end{macrocode}
+% Now we handle the V value. If MultiSelect is set, we use the full
+% displayvalues seq, if not only the first value.
+% \begin{macrocode}
+ \int_compare:nNnTF {\bitset_item:Nn \l_@@_Ff_bitset {MultiSelect}} = {1}
+ {
+ \tl_clear:N \l_@@_tmpa_tl
+ \seq_map_inline:Nn \l_@@_choice_defaultvalues_seq
+ {
+ \pdf_string_from_unicode:nnN{utf16/hex}{##1}\l_@@_tmpa_str
+ \tl_put_right:NV \l_@@_tmpa_tl \l_@@_tmpa_str
+ \pdfdict_put:nnx { l_@@/field }{V} { [ \l_@@_tmpa_tl ] }
+ }
+ }
+ {
+ \tl_set:Nx \l_@@_tmpa_tl {\seq_item:Nn \l_@@_choice_defaultvalues_seq {1} }
+ \exp_args:NnV
+ \pdf_string_from_unicode:nnN{utf16/hex}\l_@@_tmpa_tl\l_@@_tmpb_str
+ \pdfdict_put:nnx { l_@@/field }{V} { \l_@@_tmpb_str }
+ }
+% \end{macrocode}
+% now we create the field and set it as parent for the following annotation.
+% \begin{macrocode}
+ \@@_field:n { @@/choice/#1 }
+ }
+ \keys_set:nn {pdffield}{parent=@@/choice/#1}
+ }
+\cs_generate_variant:Nn \@@_choice_field:n {V}
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Assembling the choice field}
+%
+% \begin{macro}{\@@_choice:n}
+% The argument are key-val settings.
+% At first we map the handlers.
+% As default appearance we reuse the text appearance: a simple gray background.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_choice:n #1
+ {
+ \group_begin:
+ \cs_set_eq:NN\@@_value_handler:n \@@_choice_value_handler:n
+ \cs_set_eq:NN\@@_default_handler:n \@@_choice_default_handler:n
+ \@@_textfield_default_appearance:
+% \end{macrocode}
+% Setting up the defaults.
+% \begin{macrocode}
+ \keys_set:nn {pdffield}
+ {
+ fieldID=
+ ,name=choice
+ ,appearance = pdffield/textfield/default
+ ,width = 3cm
+ ,height = \normalbaselineskip
+ ,type=combo-edit
+ ,@@/preset/choice
+ ,#1
+ ,FT= Ch
+ }
+ \@@_choice_set_type:
+ \keys_set:nn {pdffield}
+ {
+ ,DA=
+ {
+ \pdf_name_from_unicode_e:n{\l_@@_DA_fontname_tl}
+ \c_space_tl
+ \dim_to_decimal_in_bp:n{\l_@@_DA_fontsize_dim}
+ \c_space_tl
+ Tf
+ \c_space_tl
+ \l_@@_DA_fontcolor_tl
+ \c_space_tl
+ %\l_@@_text_DAextra_tl
+ }
+ }
+% \end{macrocode}
+% If the fieldID has not been set explicitly, we use the name/T key
+% \begin{macrocode}
+ \tl_if_empty:NT\l_@@_fieldID_tl
+ {
+ \pdfdict_get:nnN {l_@@/field}{T}\l_@@_fieldID_tl
+ \tl_put_left:Nn \l_@@_fieldID_tl {@@/choice/}
+ }
+% \end{macrocode}
+% Now we build the field
+% \begin{macrocode}
+ \@@_choice_field:V\l_@@_fieldID_tl
+% \end{macrocode}
+% And add the annotation.
+% \begin{macrocode}
+ \@@_annot:
+ \group_end:
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Keys and handlers}
+% Most keys are inherited simply the ones from the generic field and annot keys.
+% We define a group key, as the name is better.
+% The value key sets the export value. default the button which is checked on.
+% At first the two handlers
+% \begin{macro}{\@@_choice_value_handler:n,\@@_choice_default_handler:n,display-values}
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_choice_value_handler:n #1
+ {
+ \seq_set_from_clist:Nn \l_@@_choice_values_seq {#1}
+ }
+\cs_new_protected:Npn \@@_choice_default_handler:n #1
+ {
+ \seq_set_from_clist:Nn \l_@@_choice_defaultvalues_seq {#1}
+ }
+\keys_define:nn{pdffield}
+ {
+ values .meta:n = {value={#1}}
+ ,default-values .meta:n = {default={#1}}
+ ,display-values .code:n =
+ {
+ \seq_set_from_clist:Nn \l_@@_choice_displayvalues_seq {#1}
+ }
+ ,top-index .code:n =
+ {
+ \pdfdict_put:nnx {l_@@/field}{TI}{\int_eval:n{#1-1}}
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{type}
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_choice_set_type: {}
+
+\keys_define:nn { pdffield }
+ {
+ type .choice:
+ ,type / combo .code:n =
+ {
+ \cs_set_protected:Npn\@@_choice_set_type:
+ {
+ \keys_set:nn{pdffield}{setFf={Combo},unsetFf={Edit,DoNotSpellCheck}}
+ }
+ }
+ ,type / combo-edit .code:n =
+ {
+ \cs_set_protected:Npn\@@_choice_set_type:
+ {
+ \keys_set:nn{pdffield}{setFf={Combo,Edit}}
+ }
+ }
+ ,type / list .code:n =
+ {
+ \cs_set_protected:Npn\@@_choice_set_type:
+ {
+ \keys_set:nn{pdffield}{unsetFf={Combo,Edit,},unsetFf={Edit,DoNotSpellCheck}}
+ }
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+% \begin{macro}{\@@_choice_appearance_handler:nnn}
+% The handler for the appearances stores only the code
+% as it must be executed rather late.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_choice_appearance_handler:nnn #1 #2 #3 %name, type, text
+ {
+ }
+
+% \end{macrocode}
+%
+% \end{macro}
+%
+% \subsection{User commands}
+% \begin{macro}{\pdffield_choice:n}
+% \begin{macrocode}
+\cs_set_eq:NN \pdffield_choice:n \@@_choice:n
+%</package>
+% \end{macrocode}
+% \end{macro}
+%\end{implementation}
+% \PrintIndex
diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-choice.pdf b/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-choice.pdf
new file mode 100644
index 0000000000..d881c1bedb
--- /dev/null
+++ b/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-choice.pdf
Binary files differ
diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-pushbutton.dtx b/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-pushbutton.dtx
new file mode 100644
index 0000000000..fe969d7ea9
--- /dev/null
+++ b/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-pushbutton.dtx
@@ -0,0 +1,765 @@
+% \iffalse meta-comment
+%
+%% File: l3pdfpdffield-pushbutton.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}}
+% \ExplSyntaxOn
+% \pdffield_appearance:nn {pdffield/bear}
+% {
+% \tikz\bear\bearwear[shirt=red,body~deco={\node[font=\tiny\bfseries,white]~at~(beartummy){Push};}];
+% }
+% \ExplSyntaxOff
+% \title{^^A
+% The \pkg{l3pdffield-pushbutton} module\\ Commands to create pushbutton 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-pushbutton} Introduction}
+% This is the documentation for pushbutton fields, for general information about form fields
+% check the documentation l3pdffield.
+%
+%
+%
+% Please keep in mind
+% \begin{itemize}
+% \item Not every PDF viewer supports pushbuttons.
+% \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 features of form fields too
+% (as you typically can't change the PDF).
+% \end{itemize}
+% \section{Pushbuttons}
+% Click me:
+% \ExplSyntaxOn
+% \group_begin:
+% \tl_set:Nn\l_tmpa_tl{app.alert('Hello!~I\'m~Bär!',3,0);}
+% \regex_replace_once:nnN{ä}{\x5Cu00E4}\l_tmpa_tl{}
+% \pdf_object_unnamed_write:nx{stream}{{}{\exp_not:o{\l_tmpa_tl}}}
+% \pdfannot_dict_put:nnx{widget}{A}{<</S/JavaScript /JS~\pdf_object_ref_last:>>}
+% \pdffield_pushbutton:n{name=bear,appearance=pdffield/bear,width=23pt,height=30pt,depth=10pt}
+% \group_end:
+% \ExplSyntaxOff
+%
+% \bigskip
+% \subsection{Commands}
+% \begin{function}{\pdffield_push:n}
+% \begin{syntax}
+% \cs{pdffield_push:n}\Arg{key val list}
+% \end{syntax}
+% This creates a pushbutton. Unlike radio buttons and checkboxes pushbuttons
+% don't change their state and they don't store or represent a value.
+% Instead their purpose is to trigger an \emph{action}. Important
+% actions are for example Submit and Reset.
+%
+% Interfaces for such actions will be setup in another module later.
+% For now actions should be added through the widget dictionary. The following
+% for example setups a named action.
+%
+% \begin{verbatim}
+% \group_begin:
+% \pdfannot_dict_put:nnn {widget}{A}{<</S/Named /N/LastPage>>}
+% \sffamily\bfseries
+% \pdffield_pushbutton:n
+% {name=my/go,
+% width=4cm,
+% caption=go~to~last~page,
+% rollover-caption=click~me!}
+% \group_end:
+% \end{verbatim}
+% \begin{center}
+% \ExplSyntaxOn
+% \group_begin:
+% \pdfannot_dict_put:nnn {widget}{A}{<</S/Named /N/LastPage>>}
+% \sffamily\bfseries\pdffield_pushbutton:n
+% {name=my/go,width=4cm,caption=GO~TO~LAST~PAGE,rollover-caption=click~me!}
+% \group_end:
+% \ExplSyntaxOff
+% \end{center}
+% The list of allowed keys is described below.
+% The \meta{key val list} should at least set the name, without it the default name
+% |pushbutton| is used.
+% \end{function}
+%
+% \subsection{The look of the button}
+% Pushbuttons have no value. PDF compensates this by giving much more options to setup
+% the appearance. Beside the standard |AP| key there are number of settings in the
+% dynamic appearance dictionary |MK|. Sadly it is quite unclear how all this settings
+% interact (or should interact), and PDF viewers don't honor all of them. I was for
+% example not able to get the down appearance to show off.
+%
+% By default the code will draw (with l3draw) a button and place the caption and
+% rollover-caption on it. The caption will honor the surrounding font, fontsize and
+% the color, and will be placed on the baseline as described by the height and depth
+% keys.
+%
+%
+%
+% \subsection{Keys}
+%
+% The new pushbutton command accept all field and annot keys from l3pdffield.
+% A few keys are disabled or are forced to specific values.
+% The |appearance| keys have a more pushbutton specific
+% behaviour, other keys have other defaults than with the basic commands.
+% Additionally there
+% are a small number of keys specific to a pushbutton.
+% For convenience a number of important keys are documented here too, even if
+% they are already in the document from l3pdffield.
+%
+% Disabled keys are
+% \begin{itemize}
+% \item |V|, |DV|. As a pushbutton has no permanent state,
+% the keys should not be used.
+% \item |FT| is overwritten.
+% \item For pushbuttons only the field flags |ReadOnly|, |Required| and |NoExport|
+% make sense.
+% |Pushbutton| is set automatically by the code
+% as this is required for a pushbutton.
+% \end{itemize}
+%
+% \begin{function}{preset-pushbutton}
+% \begin{syntax}
+% |preset-pushbutton| = \Arg{key-val-list}
+% \end{syntax}
+% This allows to set default keys for a pushbutton.
+% \end{function}
+%
+% \begin{function}{name,T}
+% \begin{syntax}
+% |name| = \meta{partial name}\\
+% |T| = \meta{partial name}
+% \end{syntax}
+% This sets the partial name of the field. The value
+% shouldn't contain a period, be not empty and sensibly consist of simple chars.
+% Additionally the value is used to create the field ID.
+% This means that pushbuttons with the same partial name are annotations
+% with the same field as parent.
+% The field ID is then internal and can not be used to
+% attach another annotation.
+% For explicit control of the field ID use the |fieldID| key.
+% \end{function}
+%
+% \begin{function}{fieldID}
+% \begin{syntax}
+% |fieldID| = \meta{field ID}\\
+% \end{syntax}
+% \emph{For experts only!}
+% This allows to give the pushbutton field a specific ID. This is only useful
+% in the context of a larger fieldset or if you want to attach another annotation
+% to the field with \cs{pdffield_annot:n}. If used wrongly you can
+% easily create invalid fieldset. It allows you to create to fields with the
+% same partial name, but if you want to see both
+% you need to ensure that their full names are
+% different---for example by adding some parent fields.
+% \end{function}
+%
+% \begin{function}{parent}
+% \begin{syntax}
+% |parent| = \meta{field ID}\\
+% \end{syntax}
+% This is only needed if the field should be part
+% of a larger fieldset. The value should be a field ID of a field created previously
+% with \cs{pdffield_field:nn}.
+% \end{function}
+%
+% \begin{function}{altname,TU}
+% \begin{syntax}
+% |altname| = \meta{string}\\
+% |TU| = \meta{string}\\
+% \end{syntax}
+% This is sets an alternative name for user interaction.
+% This name can only be set at the first pushbutton instance, when the field is initialized.
+% \end{function}
+%
+% \begin{function}{mappingname,TM}
+% \begin{syntax}
+% |mappingname| = \meta{string}\\
+% |TM| = \meta{string}\\
+% \end{syntax}
+% This is sets an alternative name for export.
+% This name can only be set at the first pushbutton instance, when the field is initialized.
+% \end{function}
+%
+% \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 pushbutton instance.
+% The value should be a dimension expression. By default
+% |width| is \qty{3}{\centi\meter}, |height| uses 1.05\cs{normalbaselineskip}, and
+% |depth| is 0.45\cs{normalbaselineskip}.
+% \end{function}
+%
+% \begin{function}{AP/N,appearance,AP/R,rollover-appearance,AP/D,down-appearance}
+% \begin{syntax}
+% |AP/N| = \meta{appearance name}\\
+% |appearance| = \meta{appearance name}\\
+% |AP/R| = \meta{appearance name}\\
+% |rollover-appearance| = \meta{appearance name}\\
+% |AP/D| = \meta{appearance name}\\
+% |down-appearance| = \meta{appearance name}
+% \end{syntax}
+% This keys sets the normal appearance, the rollover appearance (when the
+% mouse hovers over the pushbutton) and the down appearance (when the
+% mouse clicks). They take as value a
+% \meta{appearance name} and expects that one form Xobjects
+% with this name has been created before.
+% It depends on the PDF viewer if such appearances
+% are shown. adobe reader for example ignores the down appearance.
+% \end{function}
+%
+% \begin{function}{action}
+% \begin{syntax}
+% |action| = .....\\
+% \end{syntax}
+% This key doesn't exist yet. It will (probably) be added when a interface
+% for actions are added.
+% \end{function}
+%
+% \subsection{Using with hyperref}
+% The \cs{Pushbutton} command from hyperref also adds a label. Something like
+% this could more or less fake it. But be aware that the options are not
+% identical.
+%
+% \begin{verbatim}
+% \ExplSyntaxOn\makeatletter
+% \def\@PushButton[#1]#2{\LayoutPushButtonField{#2}{\pdffield_pushbutton:n {name=#2,#1}}}
+% \ExplSyntaxOff\makeatother
+% \end{verbatim}
+%
+%
+% \end{documentation}
+%
+% \begin{implementation}
+% \DoNotIndex
+% {\\
+% ,\bitset_clear:N
+% ,\bitset_new:Nn
+% ,\bitset_set_false:Nn
+% ,\bitset_set_true:Nn
+% ,\bitset_to_arabic:N
+% ,\bool_new:N
+% ,\box_dp:N
+% ,\box_ht:N
+% ,\l_tmpa_box
+% ,\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_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
+% ,\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_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
+% ,\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
+% ,\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
+% ,\use:c
+% }
+% \section{\pkg{l3pdffield-pushbutton} Implementation}
+% \begin{macrocode}
+%<*package>
+%<@@=pdffield>
+% \end{macrocode}
+% \subsection{Variables}
+% A variable to store the appearance code, and two dimensions
+% for the appearances. We can't use a single default
+% appearance, so we use a count.
+% \begin{variable}
+% {
+% ,\l_@@_pushbutton_appearance_code_tl
+% ,\l_@@_pushbutton_linewidth_dim
+% ,\l_@@_pushbutton_totalht_dim
+% ,\g_@@_pushbutton_cnt_int
+% }
+% A pushbutton can setup the appearance only after the texts are known,
+% so the code is stored and executed later.
+% \begin{macrocode}
+\tl_new:N \l_@@_pushbutton_appearance_code_tl
+\dim_new:N \l_@@_pushbutton_linewidth_dim
+\dim_new:N \l_@@_pushbutton_totalht_dim
+\int_new:N \g_@@_pushbutton_cnt_int
+% \end{macrocode}
+% \end{variable}
+% \subsection{Appearances}
+% The default appearances are a rectangular frame with some text.
+%
+% \begin{macro}
+% {
+% \@@_pushbutton_default_appearances:,
+% pdffield/pushbutton/default-n,
+% pdffield/pushbutton/defaultrollover-n,
+% pdffield/pushbutton/defaultdown-n,
+% }
+% This defines the standard appearances. They are setup at the first
+% use of a pushbutton, and will adapt to the font family in use then.
+% \begin{macrocode}
+\dim_set:Nn \l_@@_pushbutton_linewidth_dim {0.4pt}
+\color_set:nn {pdffield/push/text}{black}
+\color_set:nn {pdffield/push/border}{black!95!white}
+\color_set:nn {pdffield/push/bordertop}{yellow!5!white}
+\color_set:nn {pdffield/push/borderbot}{black!50!white}
+\color_set:nn {pdffield/push/fill}{black!20!white}
+
+\cs_new_protected:Npn \@@_pushbutton_default_appearances:
+ {
+ \int_gincr:N \g_@@_pushbutton_cnt_int
+ \exp_args:Nx
+ \pdffield_appearance:nn {pdffield/pushbutton/default-\int_use:N \g_@@_pushbutton_cnt_int}
+ {
+ \draw_begin:
+ \color_set:nn {pdffield/push/text}{.}
+ \dim_set:Nn \l_@@_pushbutton_totalht_dim
+ {\l_@@_annot_ht_dim + \l_@@_annot_dp_dim}
+ \draw_linewidth:n {\l_@@_pushbutton_linewidth_dim}
+ \draw_path_rectangle_corners:nn
+ {0.5\l_@@_pushbutton_linewidth_dim,0.5\l_@@_pushbutton_linewidth_dim}
+ {
+ \l_@@_annot_wd_dim-0.5\l_@@_pushbutton_linewidth_dim,
+ \l_@@_pushbutton_totalht_dim-0.5\l_@@_pushbutton_linewidth_dim
+ }
+ \color_fill:n {pdffield/push/border}
+ \draw_path_use_clear:n { fill }
+ \draw_path_rectangle_corners:nn
+ {2\l_@@_pushbutton_linewidth_dim,2\l_@@_pushbutton_linewidth_dim}
+ {
+ \l_@@_annot_wd_dim-2\l_@@_pushbutton_linewidth_dim,
+ \l_@@_pushbutton_totalht_dim-2\l_@@_pushbutton_linewidth_dim
+ }
+ \color_fill:n {pdffield/push/bordertop}
+ \draw_path_use_clear:n { fill }
+ \draw_path_moveto:n
+ {
+ 2\l_@@_pushbutton_linewidth_dim,
+ 2\l_@@_pushbutton_linewidth_dim
+ }
+ \draw_path_lineto:n
+ {5\l_@@_pushbutton_linewidth_dim,5\l_@@_pushbutton_linewidth_dim}
+ \draw_path_lineto:n
+ {
+ \l_@@_annot_wd_dim-5\l_@@_pushbutton_linewidth_dim,
+ \l_@@_pushbutton_totalht_dim-5\l_@@_pushbutton_linewidth_dim
+ }
+ \draw_path_lineto:n
+ {
+ \l_@@_annot_wd_dim-2\l_@@_pushbutton_linewidth_dim,
+ \l_@@_pushbutton_totalht_dim-2\l_@@_pushbutton_linewidth_dim
+ }
+ \draw_path_lineto:n
+ {
+ \l_@@_annot_wd_dim-2\l_@@_pushbutton_linewidth_dim,
+ 2\l_@@_pushbutton_linewidth_dim
+ }
+ \draw_path_close:
+ \color_fill:n {pdffield/push/borderbot}
+ \draw_path_use_clear:n { fill }
+ \draw_path_rectangle_corners:nn
+ {
+ 1.5\l_@@_pushbutton_linewidth_dim,
+ 1.5\l_@@_pushbutton_linewidth_dim
+ }
+ {
+ \l_@@_annot_wd_dim-1.5\l_@@_pushbutton_linewidth_dim,
+ \l_@@_pushbutton_totalht_dim-1.5\l_@@_pushbutton_linewidth_dim
+ }
+ \color_stroke:n {pdffield/push/border}
+ \draw_path_use_clear:n { stroke }
+ \draw_path_rectangle_corners:nn
+ {4\l_@@_pushbutton_linewidth_dim,4\l_@@_pushbutton_linewidth_dim}
+ {
+ \l_@@_annot_wd_dim-4\l_@@_pushbutton_linewidth_dim,
+ \l_@@_pushbutton_totalht_dim-4\l_@@_pushbutton_linewidth_dim
+ }
+ \color_fill:n {pdffield/push/fill}
+ \draw_path_use_clear:n { fill }
+ \color_fill:n {pdffield/push/text}
+ \draw_transform_shift:n
+ {0.5 \l_@@_annot_wd_dim, \l_@@_annot_dp_dim }
+ \hbox_set:Nn \l_tmpa_box { \makebox[0pt]{\l_@@_caption_tl} }
+ \draw_box_use:N \l_tmpa_box
+ \draw_end:
+ }
+ \exp_args:Nx
+ \pdffield_appearance:nn {pdffield/pushbutton/defaultrollover-\int_use:N \g_@@_pushbutton_cnt_int}
+ {
+ \draw_begin:
+ \dim_set:Nn \l_@@_pushbutton_totalht_dim
+ {\l_@@_annot_ht_dim + \l_@@_annot_dp_dim}
+ \draw_linewidth:n {\l_@@_pushbutton_linewidth_dim}
+ \draw_path_rectangle_corners:nn
+ {0.5\l_@@_pushbutton_linewidth_dim,0.5\l_@@_pushbutton_linewidth_dim}
+ {
+ \l_@@_annot_wd_dim-0.5\l_@@_pushbutton_linewidth_dim,
+ \l_@@_pushbutton_totalht_dim-0.5\l_@@_pushbutton_linewidth_dim
+ }
+ \color_fill:n {pdffield/push/border}
+ \draw_path_use_clear:n { fill }
+ \draw_path_rectangle_corners:nn
+ {2\l_@@_pushbutton_linewidth_dim,2\l_@@_pushbutton_linewidth_dim}
+ {
+ \l_@@_annot_wd_dim-2\l_@@_pushbutton_linewidth_dim,
+ \l_@@_pushbutton_totalht_dim-2\l_@@_pushbutton_linewidth_dim
+ }
+ \color_fill:n {pdffield/push/borderbot}
+ \draw_path_use_clear:n { fill }
+ \draw_path_moveto:n
+ {
+ 2\l_@@_pushbutton_linewidth_dim,
+ 2\l_@@_pushbutton_linewidth_dim
+ }
+ \draw_path_lineto:n
+ {5\l_@@_pushbutton_linewidth_dim,5\l_@@_pushbutton_linewidth_dim}
+ \draw_path_lineto:n
+ {
+ \l_@@_annot_wd_dim-5\l_@@_pushbutton_linewidth_dim,
+ \l_@@_pushbutton_totalht_dim-5\l_@@_pushbutton_linewidth_dim
+ }
+ \draw_path_lineto:n
+ {
+ \l_@@_annot_wd_dim-2\l_@@_pushbutton_linewidth_dim,
+ \l_@@_pushbutton_totalht_dim-2\l_@@_pushbutton_linewidth_dim
+ }
+ \draw_path_lineto:n
+ {
+ \l_@@_annot_wd_dim-2\l_@@_pushbutton_linewidth_dim,
+ 2\l_@@_pushbutton_linewidth_dim
+ }
+ \draw_path_close:
+ \color_fill:n {pdffield/push/bordertop}
+ \draw_path_use_clear:n { fill }
+ \draw_path_rectangle_corners:nn
+ {
+ 1.5\l_@@_pushbutton_linewidth_dim,
+ 1.5\l_@@_pushbutton_linewidth_dim
+ }
+ {
+ \l_@@_annot_wd_dim-1.5\l_@@_pushbutton_linewidth_dim,
+ \l_@@_pushbutton_totalht_dim-1.5\l_@@_pushbutton_linewidth_dim
+ }
+ \color_stroke:n {pdffield/push/border}
+ \draw_path_use_clear:n { stroke }
+ \draw_path_rectangle_corners:nn
+ {4\l_@@_pushbutton_linewidth_dim,4\l_@@_pushbutton_linewidth_dim}
+ {
+ \l_@@_annot_wd_dim-4\l_@@_pushbutton_linewidth_dim,
+ \l_@@_pushbutton_totalht_dim-4\l_@@_pushbutton_linewidth_dim
+ }
+ \color_fill:n {pdffield/push/fill}
+ \draw_path_use_clear:n { fill }
+ \color_fill:n {pdffield/push/text}
+ \draw_transform_shift:n
+ {0.5 \l_@@_annot_wd_dim, \l_@@_annot_dp_dim }
+ \hbox_set:Nn \l_tmpa_box { \makebox[0pt]{\l_@@_rollover_caption_tl} }
+ \draw_box_use:N \l_tmpa_box
+ \draw_end:
+ }
+ \exp_args:Nx
+ \pdffield_appearance:nn {pdffield/pushbutton/defaultdown-\int_use:N \g_@@_pushbutton_cnt_int}
+ {
+ \draw_begin:
+ \dim_set:Nn \l_@@_pushbutton_totalht_dim
+ {\l_@@_annot_ht_dim + \l_@@_annot_dp_dim}
+ \draw_linewidth:n {\l_@@_pushbutton_linewidth_dim}
+ \draw_path_rectangle_corners:nn
+ {0.5\l_@@_pushbutton_linewidth_dim,0.5\l_@@_pushbutton_linewidth_dim}
+ {
+ \l_@@_annot_wd_dim-0.5\l_@@_pushbutton_linewidth_dim,
+ \l_@@_pushbutton_totalht_dim-0.5\l_@@_pushbutton_linewidth_dim
+ }
+ \color_fill:n {pdffield/push/border}
+ \draw_path_use_clear:n { fill }
+ \draw_path_rectangle_corners:nn
+ {2\l_@@_pushbutton_linewidth_dim,2\l_@@_pushbutton_linewidth_dim}
+ {
+ \l_@@_annot_wd_dim-2\l_@@_pushbutton_linewidth_dim,
+ \l_@@_pushbutton_totalht_dim-2\l_@@_pushbutton_linewidth_dim
+ }
+ \color_fill:n {pdffield/push/borderbot}
+ \draw_path_use_clear:n { fill }
+ \draw_path_moveto:n
+ {
+ 2\l_@@_pushbutton_linewidth_dim,
+ 2\l_@@_pushbutton_linewidth_dim
+ }
+ \draw_path_lineto:n
+ {5\l_@@_pushbutton_linewidth_dim,5\l_@@_pushbutton_linewidth_dim}
+ \draw_path_lineto:n
+ {
+ \l_@@_annot_wd_dim-5\l_@@_pushbutton_linewidth_dim,
+ \l_@@_pushbutton_totalht_dim-5\l_@@_pushbutton_linewidth_dim
+ }
+ \draw_path_lineto:n
+ {
+ \l_@@_annot_wd_dim-2\l_@@_pushbutton_linewidth_dim,
+ \l_@@_pushbutton_totalht_dim-2\l_@@_pushbutton_linewidth_dim
+ }
+ \draw_path_lineto:n
+ {
+ \l_@@_annot_wd_dim-2\l_@@_pushbutton_linewidth_dim,
+ 2\l_@@_pushbutton_linewidth_dim
+ }
+ \draw_path_close:
+ \color_fill:n {pdffield/push/bordertop}
+ \draw_path_use_clear:n { fill }
+ \draw_path_rectangle_corners:nn
+ {
+ 1.5\l_@@_pushbutton_linewidth_dim,
+ 1.5\l_@@_pushbutton_linewidth_dim
+ }
+ {
+ \l_@@_annot_wd_dim-1.5\l_@@_pushbutton_linewidth_dim,
+ \l_@@_pushbutton_totalht_dim-1.5\l_@@_pushbutton_linewidth_dim
+ }
+ \color_stroke:n {pdffield/push/border}
+ \draw_path_use_clear:n { stroke }
+ \draw_path_rectangle_corners:nn
+ {4\l_@@_pushbutton_linewidth_dim,4\l_@@_pushbutton_linewidth_dim}
+ {
+ \l_@@_annot_wd_dim-4\l_@@_pushbutton_linewidth_dim,
+ \l_@@_pushbutton_totalht_dim-4\l_@@_pushbutton_linewidth_dim
+ }
+ \color_fill:n {pdffield/push/fill}
+ \draw_path_use_clear:n { fill }
+ \color_fill:n {pdffield/push/text}
+ \draw_transform_shift:n
+ {0.5 \l_@@_annot_wd_dim, \l_@@_annot_dp_dim }
+ \hbox_set:Nn \l_tmpa_box { \makebox[0pt]{\l_@@_down_caption_tl} }
+ \draw_box_use:N \l_tmpa_box
+ \draw_end:
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+%\subsection{Creating the field}
+% A field should be created if the name doesn't exist
+% \begin{macro}{ \@@_pushbutton_field:n }
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_pushbutton_field:n #1 %name
+ {
+ \pdf_object_if_exist:nF {@@/field/@@/pushbutton/#1}
+ {
+ \@@_field:n { @@/pushbutton/#1 }
+ }
+ \keys_set:nn {pdffield}{parent=@@/pushbutton/#1}
+ }
+\cs_generate_variant:Nn \@@_pushbutton_field:n {V}
+% \end{macrocode}
+% \end{macro}
+% \subsection{Assembling the Pushbutton}
+%
+% \begin{macro}{\@@_pushbutton:n}
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_pushbutton:n #1
+ {
+ \group_begin:
+ \tl_set:Nn\l_@@_pushbutton_appearance_code_tl{}
+ \cs_set_eq:NN\@@_appearance_handler:nnn \@@_pushbutton_appearance_handler:nnn
+% \end{macrocode}
+% Setting up the defaults.
+% \begin{macrocode}
+ \keys_set:nn {pdffield}
+ {
+ fieldID=,
+ name=pushbutton,
+ width = 3cm,
+ height = 1.05\normalbaselineskip,
+ depth = 0.45\normalbaselineskip,
+ }
+% \end{macrocode}
+% Value keys should be undefined.
+% \begin{macrocode}
+ \keys_set:nn { pdffield }{@@/preset/pushbutton,#1}
+ \keys_set:nn { pdffield }
+ {
+ ,V=
+ ,DV=
+ ,setFf={Pushbutton}
+ ,FT= Btn
+ }
+ \tl_if_empty:NT\l_@@_fieldID_tl
+ {
+ \pdfdict_get:nnN {l_@@/field}{T}\l_@@_fieldID_tl
+ \tl_put_left:Nn \l_@@_fieldID_tl {@@/pushbutton/}
+ }
+ \tl_if_empty:NT\l_@@_pushbutton_appearance_code_tl
+ {
+ \@@_pushbutton_default_appearances:
+ \exp_args:Nnx
+ \keys_set:nn {pdffield}
+ {
+ appearance = pdffield/pushbutton/default-\int_eval:n{ \g_@@_pushbutton_cnt_int},
+ down-appearance = pdffield/pushbutton/defaultdown-\int_eval:n{ \g_@@_pushbutton_cnt_int},
+ rollover-appearance = pdffield/pushbutton/defaultrollover-\int_eval:n{ \g_@@_pushbutton_cnt_int},
+ }
+ }
+ \l_@@_pushbutton_appearance_code_tl
+ \@@_pushbutton_field:V\l_@@_fieldID_tl
+ \@@_annot:
+ \group_end:
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Keys}
+% Most keys are inherited from the generic field and annot keys.
+% We only need to handle the appearance in a special way.
+%
+% \begin{macro}{\@@_pushbutton_appearance_handler:nnn}
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_pushbutton_appearance_handler:nnn #1 #2 #3 %name, type, text
+ {
+ \tl_put_right:Nn \l_@@_pushbutton_appearance_code_tl
+ {
+ \pdfxform_if_exist:nTF { #1 }
+ {
+ \pdfannot_dict_put:nnx {widget/AP}{#2}{\pdfxform_ref:n{#1}}
+ }
+ {
+ \msg_error:nnnn{pdffield}{appearance-missing}{#1}{#3}
+ }
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{user commands}
+% \begin{macro}{\pdffield_pushbutton:n}
+% \begin{macrocode}
+\cs_set_eq:NN \pdffield_pushbutton:n \@@_pushbutton:n
+%</package>
+% \end{macrocode}
+% \end{macro}
+%\end{implementation}
+
+% \PrintIndex
diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-pushbutton.pdf b/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-pushbutton.pdf
new file mode 100644
index 0000000000..3ec4937ec8
--- /dev/null
+++ b/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-pushbutton.pdf
Binary files differ
diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-radiobutton.dtx b/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-radiobutton.dtx
new file mode 100644
index 0000000000..69187ec765
--- /dev/null
+++ b/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-radiobutton.dtx
@@ -0,0 +1,835 @@
+% \iffalse meta-comment
+%
+%% File: l3pdfpdffield-radiobutton.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}
+\usepackage{l3pdffield-testphase,bearwear,tikzlings,tikzducks}
+\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}}
+% \ExplSyntaxOn
+% \box_new:N\l_pdffield_bear_box
+% \box_new:N\l_pdffield_hippo_box
+% \box_new:N\l_pdffield_duck_box
+% \hbox_set:Nn \l_pdffield_bear_box {\tikz\bear\bearwear[shirt=red,body~deco={\node[font=\tiny\bfseries,white]~at~(beartummy){Yes};}];}
+% \hbox_set:Nn \l_pdffield_hippo_box {\vphantom{\tikz\bear;}\tikz\hippo;}
+% \hbox_set:Nn \l_pdffield_duck_box {\vphantom{\tikz\bear;}\tikz\duck;}
+%
+%
+% \pdffield_appearance:nn {pdffield/bear/Yes}
+% {
+% \fbox{\box_use:N \l_pdffield_bear_box}
+% }
+% \pdffield_appearance:nn {pdffield/bear/Off}
+% {
+% \fbox{\phantom{\box_use:N \l_pdffield_bear_box}}
+% }
+% \pdffield_appearance:nn {pdffield/hippo/Yes}
+% {
+% \fbox{\box_use:N \l_pdffield_hippo_box}
+% }
+% \pdffield_appearance:nn {pdffield/hippo/Off}
+% {
+% \fbox{\phantom{\box_use:N \l_pdffield_hippo_box}}
+% }%
+% \pdffield_appearance:nn {pdffield/duck/Yes}
+% {
+% \fbox{\box_use:N \l_pdffield_duck_box}
+% }
+% \pdffield_appearance:nn {pdffield/duck/Off}
+% {
+% \fbox{\phantom{\box_use:N \l_pdffield_duck_box}}
+% }%
+% \ExplSyntaxOff
+% \title{^^A
+% The \pkg{l3pdffield-radiobutton} module\\ Commands to create radio 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-radiobutton} Introduction}
+% This is the documentation for radio buttons fields, for general information about form fields
+% check the documentation l3pdffield.
+%
+% \begin{center}
+% Choose your favorite
+%
+% \medskip
+% \ExplSyntaxOn
+% \begin{tabular}{ccc}
+% \pdffield_radio:n{name=A,value=Bär,default=B,appearance=pdffield/bear,width=\box_wd:N\l_pdffield_bear_box,height=\box_ht:N\l_pdffield_bear_box}&
+% \pdffield_radio:n{name=A,value=Sieglinde,appearance=pdffield/hippo,width=\box_wd:N\l_pdffield_hippo_box,height=\box_ht:N\l_pdffield_hippo_box}&
+% \pdffield_radio:n{name=A,value=Duck,appearance=pdffield/duck,width=\box_wd:N\l_pdffield_duck_box,height=\box_ht:N\l_pdffield_duck_box}\\[1ex]
+% \pdffield_radio:n{name=A,value=Bär}&
+% \pdffield_radio:n{name=A,value=Sieglinde}&
+% \pdffield_radio:n{name=A,value=Duck}
+% \end{tabular}
+% \ExplSyntaxOff
+% \end{center}
+%
+% Please keep in mind
+% \begin{itemize}
+% \item Not every PDF viewer supports radio buttons.
+% \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 features of form fields too
+% (as you typically can't change the PDF).
+% \end{itemize}
+% \section{Radio buttons}
+% Click me:
+% \ExplSyntaxOn
+% ^^A \pdffield_radio:n{name=bear,appearance=pdffield/bear,width=23pt,height=30pt,depth=10pt}
+% \ExplSyntaxOff
+%
+% Radio buttons are similar to checkboxes and
+% they have like checkboxes two \enquote{states}:
+% checked and unchecked.
+%
+% The difference is that multiple checkboxes are either \enquote{clones} of each other
+% which are checked and unchecked together,
+% or they are independent of each other.
+% Radio buttons on the other side build \emph{groups}
+% where checking one of the buttons unchecks all other buttons.
+% The elements of a such a radio button group are annotations of one field which
+% has a flag set which makes it into a radio button group.
+%
+% In a checkbox field the two states have the
+% fix names |/Yes| and |/Off|.
+%
+% \begin{center}
+% \begin{tikzpicture}[level 2/.style={level distance=7mm},
+% level 1/.style={sibling distance=25mm},
+% level 2/.style={sibling distance=15mm}]
+% \node[draw] {checkbox field}
+% child {node[draw,dashed,align=left,font=\ttfamily]
+% {\textrm{annotation}\\ /Yes\\
+% /Off
+% }}
+% child {node[draw,dashed,align=left,font=\ttfamily]
+% {\textrm{annotation}\\ /Yes\\
+% /Off
+% }}
+% ;
+% \end{tikzpicture}
+% \end{center}
+%
+% In radio buttons
+% the off state should still always have the name |/Off|\footnote{%
+% the PDF reference doesn't say anything about this, but various tests showed that
+% one better should stick to this name, with other names the buttons disappeared.}
+% but the on state should be a specific value for every button.
+% The field dictionary should then set
+% in the |/V| key as the value of one of the button.
+% This button is then set as selected and all the other are deselected when the
+% PDF is opened or reset.
+%
+% It is theoretically possible to control the start appearance state for every
+% button so e.g. all buttons could have the \enquote{selected} state when the PDF is opened.
+% But as soon as one button is clicked
+% you get one selected button and the other are unselected. You can't select or
+% deselect all buttons. The PDF reference mentions an flag |NoToggleToOff| but this
+% doesn't do anything, at least not in the PDF viewers I tried. For this
+% reason setting special start states is currently not supported: it complicates the code and the
+% input for no real gain.
+%
+%
+% The values of the individual buttons can be coded as annotation state names:
+%
+% \begin{center}
+% \begin{tikzpicture}[level 2/.style={level distance=7mm},
+% level 1/.style={sibling distance=25mm},
+% level 2/.style={sibling distance=15mm}]
+% \node[draw,align=left,font=\ttfamily] {\textrm{radio button field}\\/V /value1 }
+% child {node[draw,dashed,align=left,font=\ttfamily]
+% {\textrm{annotation}\\ /value0 \\
+% /Off
+% }}
+% child {node[draw,dashed,align=left,font=\ttfamily]
+% {\textrm{annotation}\\ /value1 \\
+% /Off
+% }}
+% child {node[draw,dashed,align=left,font=\ttfamily]
+% {\textrm{annotation}\\ /value2 \\
+% /Off
+% }}
+% ;
+% \end{tikzpicture}
+% \end{center}
+%
+% But it can be awkward to have to use the values also as names of appearances states, it
+% makes it for example difficult to use unicode for the value names, so there is another
+% option: One can set up an |/Opt| array which contains the values as strings,
+% and used \enquote{named numbers} as appearance state name: The numbers
+% |/0|, |/1| point then to the index position in the array.
+%
+% \begin{center}
+% \begin{tikzpicture}[level 2/.style={level distance=7mm},
+% level 1/.style={sibling distance=25mm},
+% level 2/.style={sibling distance=15mm}]
+% \node[draw,align=left,font=\ttfamily] {\textrm{radio button field}\\
+% /Opt [(value0) (value1) (value2)]
+% /V /0 }
+% child {node[draw,dashed,align=left,font=\ttfamily]
+% {\textrm{annotation}\\ /0 \\
+% /Off
+% }}
+% child {node[draw,dashed,align=left,font=\ttfamily]
+% {\textrm{annotation}\\ /1 \\
+% /Off
+% }}
+% child {node[draw,dashed,align=left,font=\ttfamily]
+% {\textrm{annotation}\\ /2 \\
+% /Off
+% }}
+% ;
+% \end{tikzpicture}
+% \end{center}
+%
+% This method is clearly more flexible, and so it is used in this module.
+%
+% As radio buttons build a group of buttons, there is more interaction going on,
+% and more values have to be set. Also the first command, which initializes the field,
+% has to set the default value of the group.
+%
+% This means a typical setup should do something like this
+%
+% \begin{verbatim}
+% \pdffield_radio:n
+% {
+% group = A, % required, can also be given as name=A or T=A
+% value = button1, % required, on-state of this button
+% default = button4 % default of the group,
+% % if not given choice (button1) is used
+% % should refer to an existing button!
+% % It will set the V and the DV key
+% % button4 will be checked
+% }
+% \pdffield_radio:n
+% {
+% group = A, % required, can also be given as name=A or T=A
+% value = button2 % required, export value of this button
+% }
+% \pdffield_radio:n
+% {
+% group = A, % required, can also be given as name=A or T=A
+% value = button3, % required, choice/export value of this button
+% }
+% \pdffield_radio:n
+% {
+% group = A, % required, can also be given as name=A or T=A
+% value = button4 % required, choice/export value of this button
+% }
+% \end{verbatim}
+%
+%
+% If two radio field annotations use the same |value| they are selected and
+% unselected together, like checkboxes with the same |/Yes| state. This can be used
+% to build radio groups which works \enquote{in unison}. The flag |RadiosInUnison|
+% is neither needed for this (but doesn't harm either) nor
+% does it change the behaviour, at least again not in the PDF viewers I tried.
+%
+%
+% \bigskip
+% \subsection{Commands}
+% \begin{function}{\pdffield_radio:n}
+% \begin{syntax}
+% \cs{pdffield_radio:n}\Arg{key val list}
+% \end{syntax}
+% This creates a radio button to check and uncheck.
+% The list of allowed keys is described below.
+% The \meta{key val list} should at least set the group name,
+% without it the default group
+% |radio| is used. Radiobuttons with the same
+% group name belong to the same field and if checked, the others are unchecked.
+% The default appearance
+% is a circle frame with a black bullet in it for the checked case.
+% The default appearance is setup at the first use. Its geometry is quadratic.
+%
+% The first radio button setups the field and should also set the button which
+% should be shown as selected when the PDF is opened.
+% \end{function}
+%
+%
+% \subsection{Keys}
+%
+% The new radio command accept all field and annot keys from l3pdffield.
+% A few keys are disabled or are forced to specific values.
+% The |appearance| keys have a more radio specific
+% behaviour, other keys have other defaults than with the basic commands.
+% Additionally there
+% are a small number of keys specific to a radio button.
+% |value| and |default| have a special meaning.
+%
+%
+% Disabled keys are
+% \begin{itemize}
+% \item |V|, |DV|, |AS|: they are set by the other keys.
+% \item |FT| is overwritten.
+% \item For radio buttons only the field flags |ReadOnly|, |Required|, |NoExport|,
+% |NoToggleToOff| and |RadiosInUnison| make sense. The last two are as mentioned
+% above probably useless.
+% |Radio| is set automatically automatically by the code
+% as this is required for a radio button set.
+% \end{itemize}
+%
+%
+% \begin{function}{preset-radiobutton}
+% \begin{syntax}
+% |preset-radiobutton| = \Arg{key-val-list}
+% \end{syntax}
+% This allows to set default keys for a radio button.
+% \end{function}
+%
+% \begin{function}{group,name,T}
+% \begin{syntax}
+% |group| = \meta{partial name}\\
+% |name| = \meta{partial name}\\
+% |T| = \meta{partial name}
+% \end{syntax}
+% These keys set the partial name of the field. They all do the same
+% thing, use the one you are more comfortable with. The value
+% shouldn't contain a period, be not empty and sensibly consist of simple chars.
+% Additionally the value is used to create the field ID.
+% This means that radio buttons with the same partial name are annotations
+% with the same field as parent and so build a radio button group.
+% The field ID is then internal and can not be used to
+% attach another annotation.
+% For explicit control of the field ID use the |fieldID| key.
+% \end{function}
+%
+% \begin{function}{value}
+% \begin{syntax}
+% |value| = \meta{string}
+% \end{syntax}
+% With this key you set the export value name for the individual buttons.
+% Every button should have a value.
+% buttons with the same value are checked in unison. The value can use unicode.
+% \end{function}
+%
+% \begin{function}{default}
+% \begin{syntax}
+% |default| = \meta{string}
+% \end{syntax}
+% With this key you set the button which is checked when the PDF is opened.
+% The key must be used in the command of the first button. If it is missing
+% the value of the first button is used as default.
+% \meta{string} should be identical to a |value| of one of the buttons of the group.
+% This is not checked, buttons can be created on various pages, so it would
+% require a label/ref system to keep track of the names.
+% \end{function}
+
+% \begin{function}{fieldID}
+% \begin{syntax}
+% |fieldID| = \meta{field ID}\\
+% \end{syntax}
+% \emph{For experts only!}
+% This allows to give the radio field a specific ID. This is only useful
+% in the context of a larger fieldset or if you want to attach another annotation
+% to the field with \cs{pdffield_annot:n}. If used wrongly you can
+% easily create invalid fieldset. It allows you to create to fields with the
+% same partial name, but if you want to see both
+% you need to ensure that their full names are
+% different---for example by adding some parent fields.
+% \end{function}
+%
+% \begin{function}{parent}
+% \begin{syntax}
+% |parent| = \meta{field ID}\\
+% \end{syntax}
+% This is only needed if the field should be part
+% of a larger fieldset. The value should be a field ID of a field created previously
+% with \cs{pdffield_field:nn}.
+% \end{function}
+%
+%
+% \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 radio button.
+% The value should be a dimension expression. By default
+% |width| and |height| use \cs{normalbaselineskip}, the |depth| is zero.
+% \end{function}
+%
+% \begin{function}{AP/N,appearance,AP/R,rollover-appearance,AP/D,down-appearance}
+% \begin{syntax}
+% |AP/N| = \meta{partial appearance name}\\
+% |appearance| = \meta{partial appearance name}\\
+% |AP/R| = \meta{partial appearance name}\\
+% |rollover-appearance| = \meta{partial appearance name}\\
+% |AP/D| = \meta{partial appearance name}\\
+% |down-appearance| = \meta{partial appearance name}
+% \end{syntax}
+% This keys sets the normal appearance, the rollover appearance (when the
+% mouse hovers over the checkbox) and the down appearance (when the
+% mouse clicks). They take as value a
+% \meta{partial appearance name} and expects that \emph{two} form Xobjects
+% \meta{partial appearance name}|/Yes| and \meta{partial appearance name}|/Off|
+% has been created. The initial value is |pdffield/radio/default|
+% for the normal appearance and shows a button.
+% The down appearance enlarges the middle button a bit to give a visual feed back.
+% \end{function}
+%
+% \subsection{Using with hyperref}
+% Radio buttons in hyperref are created with \cs{ChoiceMenu} command, and
+% they also print a label. choices are actually a different field type and
+% so created with different commands. It is not quite clear yet,
+% how this could be mapped.
+%
+%
+% \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
+% ,\box_dp:N
+% ,\box_ht:N
+% ,\clist_map_inline:nn
+% ,\color_export:nnN
+% ,\color_set:nn
+% ,\color_set:nnn
+% ,\color_select:n
+% ,\cs_new_protected:Npn
+% ,\cs_new_protected:cpn
+% ,\cs_set_eq:NN
+% ,\cs_gset_eq:cN
+% ,\cs_set_protected:Npn
+% ,\cs_generate_variant:Nn
+% ,\cs_gset_eq:NN
+% ,\c_space_tl
+% ,\csname
+% ,\dim_eval:n
+% ,\dim_new:N
+% ,\dim_to_decimal_in_bp:n
+% ,\endcsname
+% ,\exp_args:Ne
+% ,\exp_args:Nc
+% ,\fboxsep
+% ,\fp_eval:n
+% ,\f@size
+% ,\group_begin:
+% ,\group_end:
+% ,\hbox_to_wd:nn
+% ,\hfill
+% ,\hook_gput_code:nnn
+% ,\int_eval:n
+% ,\int_compare:nNnT
+% ,\int_compare:nNnTF
+% ,\int_incr:N
+% ,\int_new:N
+% ,\int_use:N
+% ,\int_zero:N
+% ,\l_keys_choice_int
+% ,\keys_define:nn
+% ,\keys_set:nn
+% ,\mode_leave_vertical:
+% ,\msg_error:nnn
+% ,\msg_error:nnnn
+% ,\msg_new:nnn
+% ,\msg_warning:nn
+% ,\msg_warning:nnn
+% ,\msg_warning:nnnnn
+% ,\NeedsTeXFormat
+% ,\normalsize
+% ,\paperheight
+% ,\paperwidth
+% ,\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:nx
+% ,\pdf_object_write:nn
+% ,\pdf_string_from_unicode:nnN
+% ,\pdfannot_box_ref_last:
+% ,\pdfannot_dict_put:nnn
+% ,\pdfannot_dict_put:nnx
+% ,\pdfdict_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
+% ,\pdfmanagement_add:nnn
+% ,\pdfmeta_standard_verify:nTF
+% ,\pdfxform_if_exist:nTF
+% ,\pdfxform_new:nnn
+% ,\pdfxform_ref:n
+% ,\phantom
+% ,\prg_do_nothing:
+% ,\ProvidesExplPackage
+% ,\quark_if_no_value:NT
+% ,\raisebox
+% ,\RequirePackage
+% ,\rule
+% ,\seq_gput_right:Nn
+% ,\seq_gput_right:cV
+% ,\seq_gput_left:cV
+% ,\seq_if_in:cVF
+% ,\seq_map_break:
+% ,\seq_map_inline:Nn
+% ,\seq_new:c
+% ,\seq_use:cn
+% ,\seq_if_exist:NTF
+% ,\seq_new:N
+% ,\seq_use:Nn
+% ,\smash
+% ,\str_if_empty:NTF
+% ,\str_if_in:NnTF
+% ,\str_if_eq:nVTF
+% ,\str_new:N
+% ,\strut
+% ,\strutbox
+% ,\tl_put_right:Nn
+% ,\tl_if_empty:NTF
+% ,\tl_if_empty:NT
+% ,\tl_if_empty:NF
+% ,\tl_put_left:Nn
+% ,\tl_if_eq:NnF
+% ,\tl_if_empty:nTF
+% ,\tl_if_head_eq_charcode:nNTF
+% ,\tl_new:N
+% ,\tl_set:Nn
+% ,\tl_to_str:n
+% ,\use:c
+% }
+% \section{\pkg{l3pdffield-radiobutton} Implementation}
+% \begin{macrocode}
+%<*package>
+%<@@=pdffield>
+\RequirePackage{l3draw}
+% \end{macrocode}
+% \subsection{Variables}
+% \begin{variable}
+% {
+% \l_@@_radio_value_tl
+% ,\l_@@_radio_default_tl
+% ,\l_@@_radio_value_num_int
+% ,\l_@@_radio_appearance_code_tl
+% }
+% variables to hold the value, its index numbers and the default value.
+% radio buttons can setup the appearance only after the value is known,
+% so the code is stored and executed later.
+% \begin{macrocode}
+\tl_new:N \l_@@_radio_value_tl
+\tl_new:N \l_@@_radio_default_tl
+\int_new:N \l_@@_radio_value_num_int
+\tl_new:N \l_@@_radio_appearance_code_tl
+% \end{macrocode}
+% \end{variable}
+%
+% \subsection{Appearances}
+% The default appearances are a circle with button in it.
+% Every appearance should have two versions and follow the naming
+% module/\meta{name}/Yes and module/\meta{name}/Off.
+%
+% \begin{macro}
+% {
+% \@@_radio_default_appearances:,
+% pdffield/radio/default/Yes,
+% pdffield/radio/default/Off,
+% pdffield/radio/defaultdown/Yes,
+% pdffield/radio/defaultdown/Off
+% }
+% This defines the standard appearances. They are setup at the first
+% use of a radiobutton.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_radio_default_appearances:
+ {
+ \pdffield_appearance:nn {pdffield/radio/default/Yes}
+ {
+ \normalsize
+ \draw_begin:
+ \draw_path_circle:nn {0pt,0pt}{0.5\normalbaselineskip}
+ \draw_path_use_clear:n { stroke }
+ \draw_path_circle:nn {0pt,0pt}{0.2\normalbaselineskip}
+ \draw_path_use_clear:n { fill }
+ \draw_end:
+ }
+ \pdffield_appearance:nn {pdffield/radio/default/Off}
+ {
+ \normalsize
+ \draw_begin:
+ \draw_path_circle:nn {0pt,0pt}{0.5\normalbaselineskip}
+ \draw_path_use_clear:n { stroke }
+ \draw_end:
+ }
+
+ \pdffield_appearance:nn {pdffield/radio/defaultdown/Yes}
+ {
+ \normalsize
+ \draw_begin:
+ \draw_path_circle:nn {0pt,0pt}{0.5\normalbaselineskip}
+ \draw_path_use_clear:n { stroke }
+ \draw_path_circle:nn {0pt,0pt}{0.25\normalbaselineskip}
+ \draw_path_use_clear:n { fill }
+ \draw_end:
+ }
+ \pdffield_appearance:nn {pdffield/radio/defaultdown/Off}
+ {
+ \normalsize
+ \draw_begin:
+ \draw_path_circle:nn {0pt,0pt}{0.5\normalbaselineskip}
+ \draw_path_use_clear:n { stroke }
+ \draw_path_circle:nn {0pt,0pt}{0.25\normalbaselineskip}
+ \draw_path_use_clear:n { fill }
+ \draw_end:
+ }
+ \cs_gset_eq:NN \@@_radio_default_appearances: \prg_do_nothing:
+ }
+% \end{macrocode}
+% \end{macro}
+%
+%\subsection{Creating the field}
+% A field should be created if the name doesn't exist yet
+% \begin{macro}{\@@_radio_field:n}
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_radio_field:n #1 %name
+ {
+ \pdf_object_if_exist:nF {@@/field/@@/radio/#1}
+ {
+% \end{macrocode}
+% We need an object and a seq for the Opt array.
+% The object is written at the end of the document.
+% \begin{macrocode}
+ \pdf_object_new:nn {@@/field/@@/radio-Opt/#1}{array}
+ \pdfdict_put:nnx { l_@@/field }{Opt} { \pdf_object_ref:n {@@/field/@@/radio-Opt/#1} }
+ \seq_new:c { g_@@_radio_opt_#1_seq }
+ \hook_gput_code:nnn {shipout/lastpage}{pdffield/radio}
+ {
+ \pdf_object_write:nx
+ {@@/field/@@/radio-Opt/#1}
+ {\seq_use:cn {g_@@_radio_opt_#1_seq}{~}}
+ }
+% \end{macrocode}
+% The default value is always the first in the array.
+% If a default has been set, it is added to the left
+% of the seq.
+% \begin{macrocode}
+ \tl_if_eq:NnF \l_@@_radio_default_tl{()}
+ {
+ \seq_gput_left:cV { g_@@_radio_opt_#1_seq }\l_@@_radio_default_tl
+ }
+ \pdfdict_put:nnx { l_@@/field }{V} { /0 }
+ \pdfdict_put:nnx { l_@@/field }{DV} { /0 }
+% \end{macrocode}
+% now we create the field and set it as parent for the following annotation.
+% \begin{macrocode}
+ \@@_field:n { @@/radio/#1 }
+ }
+ \keys_set:nn {pdffield}{parent=@@/radio/#1}
+ }
+\cs_generate_variant:Nn \@@_radio_field:n {V}
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Assembling the radio}
+%
+% \begin{macro}{\@@_radio:n}
+% The argument are key-val settings.
+% At first we map the handlers. To setup the appearance we need the
+% Opt array, so the appearance handler only stores the code.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_radio:n #1
+ {
+ \group_begin:
+ \cs_set_eq:NN\@@_appearance_handler:nnn \@@_radio_appearance_handler:nnn
+ \cs_set_eq:NN\@@_value_handler:n \@@_radio_value_handler:n
+ \cs_set_eq:NN\@@_default_handler:n \@@_radio_default_handler:n
+% \end{macrocode}
+% Setting up the defaults.
+% \begin{macrocode}
+ \tl_set:Nn\l_@@_radio_appearance_code_tl{}
+ \keys_set:nn {pdffield}
+ {
+ fieldID=
+ ,name=radio
+ ,width = \normalbaselineskip
+ ,height = \normalbaselineskip
+ ,@@/preset/radiobutton
+ ,#1
+ ,unsetFf={Pushbutton}
+ ,setFf={Radio}
+ ,FT= Btn
+ }
+% \end{macrocode}
+% If the fieldID has not been set explicitly, we use the name/T key
+% \begin{macrocode}
+ \tl_if_empty:NT\l_@@_fieldID_tl
+ {
+ \pdfdict_get:nnN {l_@@/field}{T}\l_@@_fieldID_tl
+ \tl_put_left:Nn \l_@@_fieldID_tl {@@/radio/}
+ }
+% \end{macrocode}
+% Now we build the field
+% \begin{macrocode}
+ \@@_radio_field:V\l_@@_fieldID_tl
+% \end{macrocode}
+% Retrieve the number for the label
+% \begin{macrocode}
+ \seq_if_in:cVF { g_@@_radio_opt_ \l_@@_fieldID_tl _seq }\l_@@_radio_value_tl
+ {
+ \seq_gput_right:cV { g_@@_radio_opt_ \l_@@_fieldID_tl _seq }\l_@@_radio_value_tl
+ }
+ \int_zero:N \l_@@_radio_value_num_int
+ \exp_args:Nc
+ \seq_map_inline:Nn { g_@@_radio_opt_ \l_@@_fieldID_tl _seq }
+ {
+ \str_if_eq:nVTF { ##1 } \l_@@_radio_value_tl
+ {
+ \seq_map_break:
+ }
+ {
+ \int_incr:N \l_@@_radio_value_num_int
+ }
+ }
+% \end{macrocode}
+% Annotations with the default value are set to on, the rest to off
+% \begin{macrocode}
+ \int_compare:nNnTF { \l_@@_radio_value_num_int } = 0
+ { \pdfannot_dict_put:nnx {widget}{AS}{/0} }
+ { \pdfannot_dict_put:nnx {widget}{AS}{/Off} }
+% \end{macrocode}
+% Now we set the appearances, if no key has been use we take the default.
+% \begin{macrocode}
+ \tl_if_empty:NT\l_@@_radio_appearance_code_tl
+ {
+ \@@_radio_default_appearances:
+ \keys_set:nn {pdffield}
+ {
+ appearance = pdffield/radio/default,
+ down-appearance = pdffield/radio/defaultdown,
+ }
+ }
+ \l_@@_radio_appearance_code_tl
+ \@@_annot:
+ \group_end:
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Keys and handlers}
+% Most keys are inherited simply the ones from the generic field and annot keys.
+% We define a group key, as the name is better.
+% The value key sets the export value. default the button which is checked on.
+% At first the two handlers
+% \begin{macro}{\@@_radio_value_handler:n,\@@_radio_default_handler:n}
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_radio_value_handler:n #1
+ {
+ \pdf_string_from_unicode:nnN {utf8/string}{#1}\l_@@_radio_value_tl
+ }
+\cs_new_protected:Npn \@@_radio_default_handler:n #1
+ {
+ \pdf_string_from_unicode:nnN {utf8/string}{#1}\l_@@_radio_default_tl
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{group}
+% \begin{macrocode}
+\keys_define:nn { pdffield }
+ {
+ group .meta:n = {T=#1}
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_radio_appearance_handler:nnn}
+% The handler for the appearances stores only the code
+% as it must be executed rather late.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_radio_appearance_handler:nnn #1 #2 #3 %name, type, text
+ {
+ \tl_put_right:Nn \l_@@_radio_appearance_code_tl
+ {
+ \pdfxform_if_exist:nTF { #1 / Yes }
+ {
+ \pdf_object_unnamed_write:nx
+ {dict}
+ {
+ /\int_use:N \l_@@_radio_value_num_int
+ \c_space_tl \pdfxform_ref:n { #1/Yes}
+ /Off ~ \pdfxform_ref:n { #1/Off}
+ }
+ \pdfannot_dict_put:nnx {widget/AP}{#2}{\pdf_object_ref_last:}
+ }
+ {
+ \msg_error:nnnn{pdffield}{appearance-missing}{#1}{#3}
+ }
+ }
+ }
+
+% \end{macrocode}
+%
+% \end{macro}
+%
+% \subsection{User commands}
+% \begin{macro}{\pdffield_radio:n}
+% \begin{macrocode}
+\cs_set_eq:NN \pdffield_radio:n \@@_radio:n
+%</package>
+% \end{macrocode}
+% \end{macro}
+%\end{implementation}
+% \PrintIndex
diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-radiobutton.pdf b/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-radiobutton.pdf
index 5328b6e77e..9f53b703c6 100644
--- a/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-radiobutton.pdf
+++ b/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-radiobutton.pdf
Binary files differ
diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-textfield.dtx b/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-textfield.dtx
index a8ea21042f..395955714f 100644
--- a/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-textfield.dtx
+++ b/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-textfield.dtx
@@ -53,7 +53,7 @@
% }^^A
% }
%
-% \date{Version 0.95c, released 2021-03-17}
+% \date{Version 0.95e, released 2021-06-14}
%
% \maketitle
% \begin{documentation}
@@ -187,6 +187,7 @@
% Disabled keys are
% \begin{itemize}
% \item |FT| is overwritten.
+% \item |AS| is cleared.
% \item |DA| is overwritten.
% Locally use |fontcolor|, |fontsize| and |font| instead.
% Globally you can set the |DA| key in the catalog with for example
@@ -200,6 +201,10 @@
% set to 10 if it hasn't been set previously.
% \end{itemize}
%
+% The keys |value| and |default| are mapped to |V| and |DV| for this field type, see
+% below.
+%
+%
% \begin{function}{preset-textfield}
% \begin{syntax}
% |preset-textfield| = \Arg{key-val-list}
@@ -246,6 +251,7 @@
% with \cs{pdffield_field:nn}.
% \end{function}
%
+%
% \begin{function}{altname,TU}
% \begin{syntax}
% |altname| = \meta{string}\\
@@ -291,6 +297,25 @@
% make sense for a textfield).
% \end{function}
%
+% \begin{function}{V,value}
+% \begin{syntax}
+% |V| = \meta{text}\\
+% |value| = \meta{text}
+% \end{syntax}
+% This sets the start text in the field. The keys have an effect only at the first
+% instance of the textfield, when the field is initialized.
+% \end{function}
+%
+% \begin{function}{DV,default}
+% \begin{syntax}
+% |DV| = \meta{text}\\
+% |default| = \meta{text}
+% \end{syntax}
+% This sets the text which is shown if the form is reset.
+% The keys have an effect only at the first
+% instance of the textfield, when the field is initialized.
+% \end{function}
+%
% \begin{function}{fontcolor}
% \begin{syntax}
% |fontcolor| = \meta{color expression} \verb"|" [\meta{model}]\Arg{values}\\
@@ -340,41 +365,151 @@
% \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
+% ,\box_dp:N
+% ,\box_ht:N
+% ,\clist_map_inline:nn
+% ,\color_export:nnN
+% ,\color_set:nn
+% ,\color_set:nnn
+% ,\color_select:n
+% ,\cs_new_protected:Npn
+% ,\cs_new_protected:cpn
+% ,\cs_set_eq:NN
+% ,\cs_gset_eq:cN
+% ,\cs_set_protected:Npn
+% ,\cs_generate_variant:Nn
+% ,\cs_gset_eq:NN
+% ,\c_space_tl
+% ,\csname
+% ,\dim_eval:n
+% ,\dim_new:N
+% ,\dim_to_decimal_in_bp:n
+% ,\endcsname
+% ,\exp_args:Ne
+% ,\fboxsep
+% ,\fp_eval:n
+% ,\f@size
+% ,\group_begin:
+% ,\group_end:
+% ,\hbox_to_wd:nn
+% ,\hfill
+% ,\hook_gput_code:nnn
+% ,\int_eval:n
+% ,\int_compare:nNnT
+% ,\l_keys_choice_int
+% ,\keys_define:nn
+% ,\keys_set:nn
+% ,\mode_leave_vertical:
+% ,\msg_error:nnn
+% ,\msg_error:nnnn
+% ,\msg_new:nnn
+% ,\msg_warning:nn
+% ,\msg_warning:nnn
+% ,\msg_warning:nnnnn
+% ,\NeedsTeXFormat
+% ,\normalsize
+% ,\paperheight
+% ,\paperwidth
+% ,\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_write:nn
+% ,\pdf_string_from_unicode:nnN
+% ,\pdfannot_box_ref_last:
+% ,\pdfannot_dict_put:nnn
+% ,\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
+% ,\pdfmanagement_add:nnn
+% ,\pdfmeta_standard_verify:nTF
+% ,\pdfxform_if_exist:nTF
+% ,\pdfxform_new:nnn
+% ,\pdfxform_ref:n
+% ,\phantom
+% ,\prg_do_nothing:
+% ,\ProvidesExplPackage
+% ,\quark_if_no_value:NT
+% ,\raisebox
+% ,\rule
+% ,\seq_gput_right:Nn
+% ,\seq_if_exist:NTF
+% ,\seq_new:N
+% ,\seq_use:Nn
+% ,\smash
+% ,\str_if_empty:NTF
+% ,\str_if_in:NnTF
+% ,\str_new:N
+% ,\strut
+% ,\strutbox
+% ,\tl_put_right:Nn
+% ,\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_new:N
+% ,\tl_set:Nn
+% ,\tl_to_str:n
+% ,\use:c
+% }
% \section{\pkg{l3pdffield-textfield} Implementation}
% \begin{macrocode}
%<*package>
%<@@=pdffield>
% \end{macrocode}
% \subsection{Variables}
+% \begin{variable}
+% {
+% \l_@@_DA_fontcolor_tl, \l_@@_DA_fontsize_dim, \l_@@_DA_fontname_tl
+% }
+% Variables for the font setup in the DA key.
% \begin{macrocode}
\tl_new:N \l_@@_DA_fontcolor_tl
\dim_new:N \l_@@_DA_fontsize_dim
\tl_new:N \l_@@_DA_fontname_tl
% \end{macrocode}
-% \subsection{Messages}
-% \begin{macrocode}
-% \end{macrocode}
+% \end{variable}
+%
% \subsection{Appearances}
-% The default appearances are a cross (\cs{texttimes}),
-% Every appearance should have two versions and follow the naming
-% module/\meta{name}/Yes and module/\meta{name}/Off.
-% \begin{macro}{@@/textfield/default_appearances:}
+% The default appearance is a light gray background.
+%
+% \begin{macro}{\@@_textfield_default_appearance:}
% This defines the standard appearance. It is setup at the first
% use of a textfield.
% \begin{macrocode}
-\cs_new_protected:cn {@@/textfield/default_appearance:}
+\cs_new_protected:Npn {\@@_textfield_default_appearance:}
{
\pdffield_appearance:nn {pdffield/textfield/default}
{
{ \color_select:n{black!5!white}\rule{\paperwidth}{\paperheight} }
}
- \cs_gset_eq:cN {@@/textfield/default_appearance:} \prg_do_nothing:
+ \cs_gset_eq:NN \@@_textfield_default_appearance: \prg_do_nothing:
}
% \end{macrocode}
% \end{macro}
%
%\subsection{Creating the field}
-% A field should be created if the name doesn't exist
+% \begin{macro}{\@@_textfield_field:n}
+% A field should be created only if the name doesn't exist
% \begin{macrocode}
\cs_new_protected:Npn \@@_textfield_field:n #1 %name
{
@@ -386,17 +521,22 @@
}
\cs_generate_variant:Nn \@@_textfield_field:n {V}
% \end{macrocode}
+% \end{macro}
+%
% \subsection{Assembling the textfield}
-
+%
% \begin{macro}{\@@_textfield:n}
+% At first we map the handler and setup the appearance.
% \begin{macrocode}
\cs_new_protected:Npn \@@_textfield:n #1
{
\group_begin:
- \cs_set_eq:NN\@@_value_handler:nN \@@_textfield_value_handler:nN
- \use:c {@@/textfield/default_appearance:}
+ \cs_set_eq:NN\@@_V_handler:nN \@@_textfield_V_handler:nN
+ \cs_set_eq:NN\@@_value_handler:n \@@_textfield_value_handler:n
+ \cs_set_eq:NN\@@_default_handler:n \@@_textfield_default_handler:n
+ \@@_textfield_default_appearance:
% \end{macrocode}
-% Setting up the defaults.
+% Setting up the defaults and processing the keys.
% \begin{macrocode}
\keys_set:nn {pdffield}
{
@@ -409,9 +549,10 @@
depth = \fp_eval:n {0.3*\f@size} pt,
% font defaults!!
}
-% \end{macrocode}
-% \begin{macrocode}
\keys_set:nn { pdffield }{@@/preset/textfield,#1}
+% \end{macrocode}
+% We need to check if Comb is used and setup some flags in this case.
+% \begin{macrocode}
\int_compare:nNnT {\bitset_item:Nn \l_@@_Ff_bitset {Comb}}={1}
{
% warning if set?
@@ -429,6 +570,9 @@
% warning
}
}
+% \end{macrocode}
+% Now the postprocessing.
+% \begin{macrocode}
\keys_set:nn { pdffield }
{
,FT= Tx
@@ -446,12 +590,14 @@
%\l_@@_text_DAextra_tl
}
}
+% \end{macrocode}
+% If no field ID exists, we get it from the T key.
+% \begin{macrocode}
\tl_if_empty:NT\l_@@_fieldID_tl
{
\pdfdict_get:nnN {l_@@/field}{T}\l_@@_fieldID_tl
\tl_put_left:Nn \l_@@_fieldID_tl {@@/textfield/}
}
-
\@@_textfield_field:V\l_@@_fieldID_tl
\@@_annot:
\group_end:
@@ -463,6 +609,7 @@
% Most keys are inherited simply the ones from the generic field and annot keys.
% A key to decide if the box is initially checked or not.
% We stay in the same family so that we can build a style.
+% \begin{macro}{fontcolor,fontsize,font}
% \begin{macrocode}
\keys_define:nn {pdffield}
{
@@ -482,23 +629,32 @@
,fontsize .groups:n = {textfield}
}
% \end{macrocode}
-% And a key to set a dedicated field ID
-% \begin{macrocode}
-\keys_define:nn { pdffield }
- {
- fieldID .tl_set:N = \l_@@_fieldID_tl
- }
-% \end{macrocode}
+% \end{macro}
%
% \subsection{Handler}
+% \begin{macro}{\@@_textfield_V_handler:nN}
+% The handler for V/DV, it creates a string.
% \begin{macrocode}
-\cs_new_protected:Npn \@@_textfield_value_handler:nN #1#2
+\cs_new_protected:Npn \@@_textfield_V_handler:nN #1#2
{
- \pdf_string_from_unicode:nnN {utf8/string}{#1}#2
+ \pdf_string_from_unicode:nnN {utf16/hex}{#1}#2
}
% \end{macrocode}
-%
-% \subsection{user commands}
+% \end{macro}
+% \begin{macro}{\@@_textfield_value_handler:n,\@@_textfield_default_handler:n}
+% The handler for value and default. They simply map to V,DV here.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_textfield_value_handler:n #1
+ {
+ \keys_set:nn{pdffield}{V={#1}}
+ }
+\cs_new_protected:Npn \@@_textfield_default_handler:n #1
+ {
+ \keys_set:nn{pdffield}{DV={#1}}
+ }
+% \end{macrocode}
+% \end{macro}
+% \subsection{User command}
% \begin{macro}{\pdffield_textfield:n}
% \begin{macrocode}
\cs_set_eq:NN \pdffield_textfield:n \@@_textfield:n
@@ -506,3 +662,4 @@
% \end{macrocode}
% \end{macro}
%\end{implementation}
+%\PrintIndex
diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-textfield.pdf b/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-textfield.pdf
index 69a2e13b7d..ddbf333f3a 100644
--- a/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-textfield.pdf
+++ b/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-textfield.pdf
Binary files differ
diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3pdffield.dtx b/macros/latex/contrib/pdfmanagement-testphase/l3pdffield.dtx
index e1e5f8bae1..8331ebc127 100644
--- a/macros/latex/contrib/pdfmanagement-testphase/l3pdffield.dtx
+++ b/macros/latex/contrib/pdfmanagement-testphase/l3pdffield.dtx
@@ -73,7 +73,7 @@
% }^^A
% }
%
-% \date{Version 0.95d, released 2021-05-14}
+% \date{Version 0.95e, released 2021-06-14}
%
% \maketitle
% \begin{documentation}
@@ -91,14 +91,26 @@
% \usepackage{l3pdffield-testphase}
% \end{verbatim}
%
-% 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 source code is splitted into various submodules. All code is combined in the
+% sty, but the documentation is in individual PDF.
+% \begin{description}
+% \item[\texttt{l3pdffield}] This contains the basic commands and keys
+% to create a form field.
+% \item[\texttt{l3pdffield-checkbox}] The code to created checkboxes.
+% \item[\texttt{l3pdffield-textfield}] The code to created text fields.
+% \item[\texttt{l3pdffield-radiobutton}] The code to create radio buttons.
+% \item[\texttt{l3pdffield-pushbutton}] The code to create push buttons.
+% \item[\texttt{l3pdffield-choice}] The code to create choice fields (lists and drop-down/combo
+% fields.
+% \item[\texttt{l3pdffield-action}]
+% Code related to actions, mostly submit and reset actions.
+% \item[\texttt{l3pdffield-signature}] (not done yet) Code for signature fields
+% \item[Form initialization] (not done yet) The |\Form| command/environment
+% of \pkg{hyperref} initialize a few things like fonts
+% for text fields which should be moved. It is not strictly necessary to
+% have this code, most examples works without it, but in case of problems it is
+% possible to do the initialization by using the \pkg{hyperref} command.
+% \end{description}
%
% The code requires the new PDF management. The code makes use of
% \pkg{l3pdfxform} to create the form Xobjects of the appearances.
@@ -226,6 +238,30 @@
% are related in a form field. Tests with some PDF viewers
% are needed here.
%
+% \subsection{Tagged PDF}
+%
+% Field annotations are (like link annotations) not part of the page stream. But
+% they are obviously nevertheless meaningful content and must be consider if
+% a PDF is \enquote{tagged}, that means if a structure is added.
+%
+% According to the PDF references fields should be tagged by adding a |Form| structure
+% element containing the object reference to a field annotations. Fields with more than
+% one annotation like radio buttons need a |Form| structure for every one.
+% Additional some cross references to structure relevant object like the parent tree
+% are needed, for more info check the documentation of the \pkg{tagpdf} package.
+%
+% The commands of this module already contain the needed support. So if
+% \pkg{tagpdf} is used and tagging activated the fields will be added as |Form| element
+% to the structure where they are created. It is possible to deactivate tagging for
+% a field annotation by setting the |tag| to false as described below.
+%
+% If lualatex is used tagging require either that \pkg{tagpdf} is used with the
+% option |global-mc|, or mc-chunks must be correctly closed manually, as the automatic
+% code can't escape the grouping.
+%
+% It is recommended to use the |TU|/|altname| key to give the field a readable
+% name.
+%
%
% \section{Commands}
% \begin{function}{\pdffield_field:nn,\pdffield_field:Vn}
@@ -263,7 +299,7 @@
%
% \begin{function}{\pdffield_annot:n,\pdffield_annot:V}
% \begin{syntax}
-% \cs{pdffield_field:nn}\Arg{key val list}
+% \cs{pdffield_annot:n}\Arg{key val list}
% \end{syntax}
% This creates a new field annotation.
% It is a widget annotation box created with \cs{pdfannot_widget_box:nnn}, and
@@ -273,6 +309,15 @@
% The command also setup dictionaries to fill the |AP|, |MK| and |AA| dictionaries.
% \end{function}
%
+% \begin{function}{\pdffield_annot_ref_last:}
+% \begin{syntax}
+% \cs{pdffield_annot_ref_last:}
+% \end{syntax}
+% If a tagged PDF should be created, the object
+% of the annotation of a field should be referenced in the Form structure element.
+% This command allows to retrieve the reference to this object.
+% \end{function}
+
% \begin{function}{\pdffield_appearance:nn}
% \begin{syntax}
% \cs{pdffield_appearance:nn}\Arg{name}\Arg{content}
@@ -295,7 +340,14 @@
% |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.
+% \Arg{key-val} can be an arbitrary collection of the keys of the module.
+% \end{function}
+%
+% \begin{function}{create-style}
+% \begin{syntax}
+% |style| = \Arg{style}
+% \end{syntax}
+% This uses a style define with the previous |create-style|.
% \end{function}
%
% \begin{function}{preset-checkbox}
@@ -304,7 +356,32 @@
% \end{syntax}
% This allows to set default keys for a checkbox.
% \end{function}
-
+%
+% \begin{function}{preset-radio}
+% \begin{syntax}
+% |preset-radio|=\Arg{key-val}
+% \end{syntax}
+% This allows to set default keys for a radio button.
+% \end{function}
+%
+% \begin{function}{preset-textfield}
+% \begin{syntax}
+% |preset-textfield|=\Arg{key-val}
+% \end{syntax}
+% This allows to set default keys for a text field.
+% \end{function}
+%
+% \section{Special keys}
+%
+% \begin{function}{value,default}
+% \begin{syntax}
+% |value| =\Arg{value}\\
+% |default|=\Arg{value}
+% \end{syntax}
+% These two keys pass the value to a handler which can be redefined.
+% Their exact behaviour depends on field type. Please check their documentation.
+% \end{function}
+%
% \section{Field Keys}
%
% Table~\ref{tab:fieldkeys} summarize the keys which can be used.
@@ -317,7 +394,7 @@
% \begin{tabular}{>{\ttfamily}lllll}
% \toprule
% key & value & required & inheritable &remark\\\midrule
-% parent & field ID & for non-root fields & \\
+% parent & field ID & for non-root fields & \\
% style & style name & & defined with |create-style| \\
% T, name & string & mostly & \\
% TU, altname & string & & \\
@@ -499,42 +576,41 @@
% \end{function}
%
% 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
+% The values are expanded. It is recommended to store
+% the javascript in a stream object and to pass the object reference, but passing
+% a string (including parentheses) is possible too.
+% 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)}
+% |AA/K| = \meta{ECMAScript}\\
+% |keystroke| = \meta{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
+% additional action dictionary. 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)}
+% |AA/F| = \meta{ECMAScript}\\
+% |format| = \meta{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.
+% additional action dictionary. 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/V,validate}
% \begin{syntax}
-% |AA/V| = \meta{string (ECMAScript)}\\
-% |validate| = \meta{string (ECMAScript)}
+% |AA/V| = \meta{ECMAScript}\\
+% |validate| = \meta{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
+% additional action dictionary. It is quite unclear if such an action
% make sense for non-terminal fields.
% \end{function}
%
@@ -544,9 +620,23 @@
% |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.
+% additional action dictionary. It is quite unclear if such an action
+% make sense for non-terminal fields.
+% If an calculate action is used, the field will be added to the
+% AcroForm/CO array to define the calculation order. The order can
+% be controlled through the following key |sortkey|.
+% \end{function}
+%
+% \begin{function}{sortkey}
+% \begin{syntax}
+% |sortkey| = \meta{string}
+% \end{syntax}
+% This sets a sortkey for fields with calculate action.
+% The sortkeys are sorted lexically with |\str_compare:nNnTF|.
+% fields without sortkey will get an empty sortkey and so be at the begin,
+% the order of fields with the same sortkey is not defined.
+% The module only sorts fields created with the commands of this module, the
+% sorting of fields created by \pkg{hyperref} is independant.
% \end{function}
%
% \begin{function}{DA}
@@ -570,6 +660,16 @@
% as it is unclear if there are of any use.
% \end{function}
%
+% \begin{function}{fieldID}
+% \begin{syntax}
+% |fieldID| = \meta{field ID}\\
+% \end{syntax}
+% \emph{For experts only!}
+% This stores \meta{field ID} in an internal variable.
+% The variable is not used by the basic commands,
+% but by the commands to create the various field types.
+% Check their documentation for use cases.
+% \end{function}
% \section{Annot keys}
%
% Table~\ref{tab:annotkeys} summarize the keys which can be used.
@@ -618,17 +718,21 @@
% an already declared field.
% \end{function}
%
-% \begin{function}{AP/N,AP/R,AP/D}
+% \begin{function}{AP/N,appearance,AP/R,rollover-appearance,AP/D,down-appearance}
% \begin{syntax}
% |AP/N| = \meta{appearance name}\\
-% |AP/R| = \meta{appearance name}\\
-% |AP/D| = \meta{appearance name}
+% |appearance| = \meta{appearance name}\\
+% |AP/R| = \meta{rollover appearance name}\\
+% |rollover-appearance| = \meta{rollover appearance name}\\
+% |AP/D| = \meta{down appearance name}\\
+% |down appearance| = \meta{down appearance name}\\
% \end{syntax}
-% This keys set the normal, rollover and down appearance. Alias names are
-% |appearance|, |rollover-appearance| and |down-appearance|.
+% This keys set the normal, rollover and down appearance. The names
+% |appearance|, |rollover-appearance| and |down-appearance| are aliases.
% 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.
+% various states. So check the documentation for the various field types for the
+% exact format of the value.
% \end{function}
%
% \begin{function}{AS}
@@ -636,7 +740,7 @@
% |AS| = \meta{appearance state name}
% \end{syntax}
% This key sets the default appearance state.
-% The value is a name without the starting slash
+% The value is a name \emph{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.
@@ -657,19 +761,22 @@
%
% \begin{function}{AA/*}
% \begin{syntax}
-% |AA/*| = \meta{string (ECMAScript)}
+% |AA/*| = \meta{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
+% Their value should be javascript code. The value is expanded but not escaped.
+% It is recommended to
+% store the code in a stream object and to use the object reference as value.
+% The |/AA| dictionary
% is suppressed if a pdf/A standard is set.
%
% For example
% \begin{verbatim}
-% onenter={app.alert('Hello');}
+% onenter={(app.alert('Hello');)}
% \end{verbatim}
% \end{function}
%
@@ -724,15 +831,39 @@
% |radiosymbol| for this setting.
% \end{function}
%
-% 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/RC,rollover-caption}
+% \begin{syntax}
+% |MK/RC| = \meta{string}\\
+% |rollover-caption| = \meta{string}
+% \end{syntax}
+% This sets a text for the rollover-caption. \meta{string} is passed through \cs{pdf_string_from_unicode:nnN}
+% and parentheses are added automatically. The key should be used only with
+% pushbuttons. It is unclear if is actually used by the PDF viewer, but the
+% pushbuttons modules uses the argument also to setup the appearance.
+% \end{function}
+%
+% \begin{function}{MK/AC,down-caption}
+% \begin{syntax}
+% |MK/AC| = \meta{string}\\
+% |down-caption| = \meta{string}
+% \end{syntax}
+% This sets a text for the down-caption.
+% \meta{string} is passed through \cs{pdf_string_from_unicode:nnN}
+% and parentheses are added automatically. The key should be used only with
+% pushbuttons. It is unclear if is actually used by the PDF viewer, but the
+% pushbuttons modules uses the argument also to setup the appearance.
+% \end{function}
+%
+% The remaining key are like the two above useful for pushbuttons only.
+% Currently no special syntax support
+% is implemented. They will be handled if needed 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|.
+% * should be one of |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}
@@ -740,12 +871,106 @@
% \end{documentation}
%
% \begin{implementation}
+% \DoNotIndex
+% {
+% \\
+% ,\bitset_clear:N
+% ,\bitset_new:Nn
+% ,\bitset_set_false:Nn
+% ,\bitset_set_true:Nn
+% ,\bitset_to_arabic:N
+% ,\bool_new:N
+% ,\clist_map_inline:nn
+% ,\color_export:nnN
+% ,\color_set:nn
+% ,\color_set:nnn
+% ,\cs_new_protected:Npn
+% ,\cs_set_eq:NN
+% ,\cs_set_protected:Npn
+% ,\cs_if_exist:NTF
+% ,\cs_if_exist:NT
+% ,\cs_new:Npn
+% ,\csname
+% ,\dim_eval:n
+% ,\dim_new:N
+% ,\endcsname
+% ,\exp_args:Ne
+% ,\exp_args:Nnx
+% ,\exp_args:NV
+% ,\group_begin:
+% ,\group_end:
+% ,\hbox_to_wd:nn
+% ,\hfill
+% ,\hook_gput_code:nnn
+% ,\int_eval:n
+% ,\l_keys_choice_int
+% ,\keys_define:nn
+% ,\keys_set:nn
+% ,\mode_leave_vertical:
+% ,\msg_error:nnnn
+% ,\msg_error:nnx
+% ,\msg_new:nnn
+% ,\msg_warning:nn
+% ,\msg_warning:nnn
+% ,\msg_info:nnn
+% ,\msg_warning:nnnnn
+% ,\NeedsTeXFormat
+% ,\pdf_name_from_unicode_e:n
+% ,\pdf_object_if_exist:nTF
+% ,\pdf_object_new:nn
+% ,\pdf_object_ref:n
+% ,\pdf_object_ref_last:
+% ,\pdf_object_unnamed_write:nx
+% ,\pdf_object_write:nx
+% ,\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_if_empty:nF
+% ,\pdfdict_new:n
+% ,\pdfdict_put:nnn
+% ,\pdfdict_put:nnx
+% ,\pdfdict_remove:nn
+% ,\pdfdict_use:n
+% ,\pdfmanagement_add:nnn
+% ,\pdfmanagement_add:nnx
+% ,\pdfmeta_standard_verify:nTF
+% ,\pdfmeta_standard_verify:nT
+% ,\pdfmeta_standard_verify:nF
+% ,\pdfxform_if_exist:nTF
+% ,\pdfxform_new:nnn
+% ,\pdfxform_ref:n
+% ,\ProvidesExplPackage
+% ,\rule
+% ,\seq_gput_right:Nn
+% ,\seq_gput_right:cx
+% ,\seq_if_exist:NTF
+% ,\seq_if_exist:cTF
+% ,\seq_new:N
+% ,\seq_new:c
+% ,\seq_use:Nn
+% ,\seq_use:cn
+% ,\str_if_empty:NTF
+% ,\str_if_in:NnTF
+% ,\str_if_in:NnT
+% ,\str_new:N
+% ,\tl_if_empty:NTF
+% ,\tl_if_empty:NF
+% ,\tl_if_empty:nTF
+% ,\tl_if_head_eq_charcode:nNTF
+% ,\tl_new:N
+% ,\tl_set:Nn
+% ,\tl_to_str:n
+% }
% \section{\pkg{l3pdffield} Implementation}
% \begin{macrocode}
%<*package>
%<@@=pdffield>
\NeedsTeXFormat{LaTeX2e}
-\ProvidesExplPackage{l3pdffield-testphase}{2021-05-14}{0.95d}%
+\ProvidesExplPackage{l3pdffield-testphase}{2021-06-14}{0.95e}%
{form fields}
% \end{macrocode}
% \subsection{hyperref specific command}
@@ -756,16 +981,48 @@
%
% \subsection{local variables}
%
+% \begin{variable}
+% {
+% \l_@@_tmpa_str
+% ,\l_@@_tmpb_str
+% ,\l_@@_tmpa_tl
+% ,\l_@@_tmpa_keys_tl
+% ,\l_@@_currentparent_tl
+% ,\l_@@_fieldID_tl
+% ,\l_@@_caption_tl
+% ,\l_@@_rollover_caption_tl
+% ,\l_@@_down_caption_tl
+% ,\g_@@_CO_sortkeys_prop
+% ,\l_@@_CO_sortkey_str
+% ,\g_@@_annot_ref_last_tl
+% ,\l_@@_tag_bool
+% }
+% Some tmp variables, and a variable for the current parent and the
+% current fieldID.
% \begin{macrocode}
\str_new:N \l_@@_tmpa_str
+\str_new:N \l_@@_tmpb_str
\tl_new:N \l_@@_tmpa_tl
\tl_new:N \l_@@_tmpa_keys_tl
+\tl_new:N \l_@@_currentparent_tl
+\tl_new:N \l_@@_fieldID_tl
+\tl_new:N \l_@@_caption_tl
+\tl_new:N \l_@@_rollover_caption_tl
+\tl_new:N \l_@@_down_caption_tl
+\prop_new:N \g_@@_CO_sortkeys_prop
+\seq_new:N \g_@@_CO_sortkeys_seq
+\str_new:N \l_@@_CO_sortkey_str
+\tl_new:N \g_@@_annot_ref_last_tl
+\bool_new:N \l_@@_tag_bool
+\bool_set_true:N \l_@@_tag_bool
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{macrocode}
\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}
% \begin{macrocode}
\msg_new:nnn {pdffield}{no-period}
@@ -797,6 +1054,10 @@
The~parent~field~'#1'~doesn't~exist\\
Create~it~with~\tl_to_str:n{\pdffield_field:nn}
}
+\msg_new:nnn {pdffield}{key-ignored}
+ {
+ key~`#1`~has~no~function~and~is~ignored
+ }
% \end{macrocode}
% An auxiliary command to disable some keys
@@ -815,8 +1076,8 @@
% \end{macrocode}
% \end{macro}
% \subsection{bitsets}
-% A bitset for the field flag Ff
-% and an internal copy of the annot bitset.
+% \begin{macro}{\l_@@_Ff_bitset,\l_@@_F_bitset}
+% The field and the annot bitset.
% \begin{macrocode}
\bitset_new:Nn \l_@@_Ff_bitset
{
@@ -886,6 +1147,7 @@
lockedcontents = 10
}
% \end{macrocode}
+% \end{macro}
% \subsection{The field dictionary}
% The field dictionary is the main object.
% To be able to set values from the outside it will use a
@@ -893,9 +1155,8 @@
% \begin{macrocode}
\pdfdict_new:n {l_@@/field}
\pdfdict_new:n {l_@@/field/AA}
-\bool_new:N \l_@@_root_field_bool
% \end{macrocode}
-% \begin{macro}{\@@_field:n}
+% \begin{macro}{\@@_field:n,\pdffield_field:nn}
% \begin{syntax}
% \cs{@@_field:n}\Arg{field ID}
% \end{syntax}
@@ -943,6 +1204,14 @@
{l_@@/field}
{AA}
{\pdf_object_ref_last:}
+ \pdfdict_get:nnN {l_@@/field/AA}{C}\l_@@_tmpa_tl
+ \quark_if_no_value:NF \l_@@_tmpa_tl
+ {
+ \prop_gput:Nxx\g_@@_CO_sortkeys_prop
+ { \pdf_object_ref:n {@@/field/#1} }{ \l_@@_CO_sortkey_str }
+ \seq_gput_right:Nx\g_@@_CO_sortkeys_seq
+ { \pdf_object_ref:n {@@/field/#1} }
+ }
}
}
\hook_gput_code:nnn {shipout/lastpage}{pdffield} %xetex needs this ...
@@ -954,6 +1223,27 @@
}
\pdf_object_write:nx {@@/field/#1} { \pdfdict_use:n {l_@@/field} }
}
+
+\hook_gput_code:nnn {shipout/lastpage}{pdffield}
+ {
+ \prop_if_empty:NF \g_@@_CO_sortkeys_prop
+ {
+ \seq_sort:Nn \g_@@_CO_sortkeys_seq
+ {
+ \str_compare:eNeTF
+ { \prop_item:Nn \g_@@_CO_sortkeys_prop {#1} }
+ >
+ { \prop_item:Nn \g_@@_CO_sortkeys_prop {#2} }
+ { \sort_return_swapped: }
+ { \sort_return_same: }
+ }
+ \pdfmanagement_add:nnx
+ { Catalog / AcroForm }
+ { CO }
+ { \seq_use:Nn \g_@@_CO_sortkeys_seq{~} }
+ }
+ }
+
\cs_new_protected:Npn \pdffield_field:nn #1 #2
{
\group_begin:
@@ -968,7 +1258,7 @@
% We assume that the annotation should really occupy space on the page and
% leave vertical mode.
%
-% \begin{macro}{\@@_annot:}
+% \begin{macro}{\@@_annot:,\pdffield_annot:n}
% The command doesn't add grouping, so should only be used inside a group.
%
% \begin{macrocode}
@@ -983,6 +1273,7 @@
\bitset_set_false:Nn \l_@@_F_bitset {NoView}
}
\pdfannot_dict_put:nnx {widget}{F}{ \bitset_to_arabic:N \l_@@_F_bitset }
+ \@@_tag_add_struct_parent:
\tl_if_empty:NF \l_@@_currentparent_tl
{
\exp_args:Ne
@@ -999,6 +1290,7 @@
}
}
\mode_leave_vertical:
+ \@@_tag_struct_begin:
\hbox_to_wd:nn
{ \l_@@_annot_wd_dim }
{
@@ -1009,13 +1301,16 @@
{ \l_@@_annot_dp_dim }
\hfill
}
+ \tl_gset:Nx \g_@@_annot_ref_last_tl { \pdfannot_box_ref_last: }
+ \exp_args:NV \@@_tag_add_objr:n \g_@@_annot_ref_last_tl
+ \@@_tag_struct_end:
\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:}
+ { \g_@@_annot_ref_last_tl }
}
{
\msg_error:nnx { pdffield}{parent-field-missing}{\l_@@_currentparent_tl}
@@ -1032,7 +1327,68 @@
% \end{macrocode}
% \end{macro}
%
+% \begin{macro}{\pdffield_annot_ref_last:}
+% \begin{macrocode}
+\cs_new:Npn \pdffield_annot_ref_last: { \g_@@_annot_ref_last_tl }
+% \end{macrocode}
+% \end{macro}
+% \subsection{Tagging}
+% \begin{macro}
+% {
+% \@@_tag_add_struct_parent:,
+% \@@_tag_add_objr:n,
+% \@@_tag_struct_begin:
+% \@@_tag_struct_end:
+% }
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_tag_add_struct_parent: {}
+\cs_new_protected:Npn \@@_tag_add_objr:n #1 {}
+\cs_new_protected:Npn \@@_tag_struct_begin: {}
+\cs_new_protected:Npn \@@_tag_struct_end: {}
+\hook_gput_code:nnn {begindocument} { l3pdffield }
+ {
+ \cs_if_exist:NT \tag_if_active:T
+ {
+ \tag_if_active:T
+ {
+ \cs_set_protected:Npn \@@_tag_add_struct_parent:
+ {
+ \bool_if:NT \l_@@_tag_bool
+ {
+ \pdfannot_dict_put:nnx {widget}{StructParent}{ \tag_struct_parent_int: }
+ }
+ }
+ \cs_set_protected:Npn \@@_tag_add_objr:n #1
+ {
+ \bool_if:NT \l_@@_tag_bool
+ {
+ \exp_args:Nnx
+ \tag_struct_insert_annot:nn {#1}{ \tag_struct_parent_int: }
+ }
+ }
+ \cs_set_protected:Npn \@@_tag_struct_begin:
+ {
+ \bool_if:NT \l_@@_tag_bool
+ {
+ \tag_mc_end_push:
+ \tag_struct_begin:n{tag=Form}
+ }
+ }
+ \cs_set_protected:Npn \@@_tag_struct_end:
+ {
+ \bool_if:NT \l_@@_tag_bool
+ {
+ \tag_struct_end:
+ \tag_mc_begin_pop:n{}
+ }
+ }
+ }
+ }
+ }
+% \end{macrocode}
+% \end{macro}
% \subsection{auxiliary command for color keys}
+% \begin{macro}{\@@_color_set:nn }
% \begin{macrocode}
\cs_new_protected:Npn \@@_color_set:nn #1 #2
{
@@ -1051,16 +1407,25 @@
}
% \end{macrocode}
+% \end{macro}
% \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{macro}{\@@_V_handler:nN}
+% Values (V and DV) need different handling in the various field types. So
+% it uses a handler which can be redefined locally. By default it simply stores
+% the value in a tl var.
% \begin{macrocode}
-\cs_new_protected:Npn \@@_value_handler:nN #1#2
+\cs_new_protected:Npn \@@_V_handler:nN #1#2
{
\tl_set:Nn #2 {#1}
}
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{parent,T,name,TU,altname,TM,mappingname}
+% \begin{macrocode}
\keys_define:nn { pdffield }
{
,parent .tl_set:N = \l_@@_currentparent_tl
@@ -1094,7 +1459,7 @@
\pdfdict_remove:nn { l_@@/field }{TU}
}
{
- \pdf_string_from_unicode:nnN {utf8/string}{#1}\l_@@_tmpa_str
+ \pdf_string_from_unicode:nnN {utf16/hex}{#1}\l_@@_tmpa_str
\pdfdict_put:nnx { l_@@/field }{TU}{\l_@@_tmpa_str}
}
}
@@ -1108,13 +1473,32 @@
\pdfdict_remove:nn { l_@@/field }{TM}
}
{
- \pdf_string_from_unicode:nnN {utf8/string}{#1}\l_@@_tmpa_str
+ \pdf_string_from_unicode:nnN {utf16/hex}{#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}
+% \end{macro}
+%
+% \begin{macro}{fieldID}
+% For some field types we need a fieldID.
+%
+% \begin{macrocode}
+\keys_define:nn { pdffield }
+ {
+ fieldID .tl_set:N = \l_@@_fieldID_tl
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{FT,V,DV,MaxLen,Lock,SV,Opt,TI,I}
+% \begin{macrocode}
+\keys_define:nn{pdffield}
+ {
,FT .choices:nn =
{ Btn, Tx, Ch, Sig }
{
@@ -1128,7 +1512,7 @@
\pdfdict_remove:nn { l_@@/field }{V}
}
{
- \@@_value_handler:nN{#1}\l_@@_tmpa_str
+ \@@_V_handler:nN{#1}\l_@@_tmpa_str
\pdfdict_put:nnx { l_@@/field }{V}{ \l_@@_tmpa_str }
}
}
@@ -1140,7 +1524,7 @@
\pdfdict_remove:nn { l_@@/field }{DV}
}
{
- \@@_value_handler:nN{#1}\l_@@_tmpa_str
+ \@@_V_handler:nN{#1}\l_@@_tmpa_str
\pdfdict_put:nnx { l_@@/field }{DV}{ \l_@@_tmpa_str }
}
}
@@ -1213,8 +1597,9 @@
,I .groups:n = {field}
}
% \end{macrocode}
-
+% \end{macro}
% Flags. We don't add lots of individual keys but map the key names directly
+% \begin{macro}{setFf,setfieldflags,unsetFf,unsetfieldflags}
% \begin{macrocode}
\keys_define:nn { pdffield }
{
@@ -1241,7 +1626,12 @@
}
% \end{macrocode}
-%
+% \end{macro}
+% \begin{macro}
+% {
+% AA/K,keystroke,AA/F,format,
+% AA/V,validate,AA/C,calculate
+% }
% Keys for the AA dictionary. They all trigger a javascript option.
% K=keystroke, F=format, V=validate, C=calculate
% \begin{macrocode}
@@ -1251,15 +1641,14 @@
{
AA/#1 .code:n =
{
- \pdf_string_from_unicode:nnN {utf8/string-raw}{##1}\l_@@_tmpa_str
- \str_if_empty:NTF \l_@@_tmpa_str
+ \tl_if_empty:nTF {#1}
{
\pdfdict_remove:nn {l_@@/field/AA}{#1}
}
{
\pdfdict_put:nnx {l_@@/field/AA}
{#1}
- {<</S/JavaScript/JS(\l_@@_tmpa_str)>>}
+ {<</S/JavaScript/JS\c_space_tl ##1>>}
}
},
AA/#1 .groups:n = {field}
@@ -1282,9 +1671,15 @@
\@@_tmpa:nn {validate} {V}
\@@_tmpa:nn {calculate}{C}
-
+\keys_define:nn {pdffield}
+ {
+ sortkey .code:n = {\str_set:Nx \l_@@_CO_sortkey_str {\tl_to_str:n{#1}}}
+ }
% \end{macrocode}
+% \end{macro}
%
+% \begin{macro}{DA,Q,align,DS,RV}
+% The following keys are related to textfield and their format.
% \begin{macrocode}
\keys_define:nn { pdffield }
{
@@ -1318,15 +1713,24 @@
,RV .groups:n = {field}
}
% \end{macrocode}
-%
+% \end{macro}
% \subsection{Annotation keys}
% The size of the field annotation
-%
+% \begin{variable}
+% {
+% \l_@@_annot_ht_dim,
+% \l_@@_annot_wd_dim,
+% \l_@@_annot_dp_dim
+% }
% \begin{macrocode}
\dim_new:N \l_@@_annot_ht_dim
\dim_new:N \l_@@_annot_wd_dim
\dim_new:N \l_@@_annot_dp_dim
-
+% \end{macrocode}
+% \end{variable}
+% \begin{macro}{width,height,depth}
+% The size of the field annotation.
+% \begin{macrocode}
\keys_define:nn { pdffield }
{
,width .dim_set:N = \l_@@_annot_wd_dim
@@ -1337,7 +1741,37 @@
,depth .initial:n = 0pt
}
% \end{macrocode}
-%
+% \end{macro}
+% \begin{macro}{tag}
+% to disable tagging locall
+% \begin{macrocode}
+\keys_define:nn { pdffield }
+ {
+ ,tag .bool_set:N = \l_@@_tag_bool
+ }
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\@@_appearance_handler:nnn}
+% Appearances have to be handled in various ways, so we use a handler, that
+% the field types can redefine if needed.
+% \begin{macrocode}
+\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}
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{AS,AP/N,appearance,AP/R,rollover-appearance,AP/D,down-appearance}
+% The key for the default appearance and the various types.
% \begin{macrocode}
\keys_define:nn { pdffield }
{
@@ -1354,19 +1788,6 @@
}
,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 =
@@ -1381,6 +1802,7 @@
}
,AP/N .groups:n = annot
,appearance .meta:n = {AP/N={#1}}
+ ,appearance .groups:n = annot
}
\keys_define:nn { pdffield }
{
@@ -1396,6 +1818,7 @@
}
,AP/R .groups:n = annot
,rollover-appearance .meta:n = {AP/R={#1}}
+ ,rollover-appearance .groups:n = annot
}
\keys_define:nn { pdffield }
{
@@ -1406,13 +1829,18 @@
\pdfannot_dict_remove:nn { widget/AP }{D}
}
{
- \@@_appearance_handler:nnn {#1}{D}{rollover}
+ \@@_appearance_handler:nnn {#1}{D}{down}
}
}
,AP/D .groups:n = annot
,down-appearance .meta:n = {AP/D={#1}}
+ ,down-appearance .groups:n = annot
}
-
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{MK/R,rotate,MK/BC,bordercolor,MK/BG,backgroundcolor,MK/CA,caption}
+% This are the keys for the dynamic appearance. A number are not handled yet fully.
+% \begin{macrocode}
\keys_define:nn { pdffield }
{
MK/R .choices:nn = {0,90,180,270}
@@ -1460,7 +1888,7 @@
}
}
,MK/BG .groups:n = annot
- ,bordercolor .meta:n = {MK/BG=#1}
+ ,backgroundcolor .meta:n = {MK/BG=#1}
}
@@ -1468,6 +1896,7 @@
{
MK/CA .code:n =
{
+ \tl_set:Nn \l_@@_caption_tl {#1}
\tl_if_empty:nTF {#1}
{
\pdfannot_dict_remove:nn { widget/MK }{CA}
@@ -1481,6 +1910,49 @@
,caption .meta:n = {MK/CA=#1}
}
+\keys_define:nn { pdffield }
+ {
+ MK/RC .code:n =
+ {
+ \tl_set:Nn \l_@@_rollover_caption_tl {#1}
+ \tl_if_empty:nTF {#1}
+ {
+ \pdfannot_dict_remove:nn { widget/MK }{RC}
+ }
+ {
+ \pdf_string_from_unicode:nnN {utf8/string}{#1}\l_@@_tmpa_str
+ \pdfannot_dict_put:nnx {widget/MK}{RC}{\l_@@_tmpa_str}
+ }
+ }
+ ,MK/RC .groups:n = annot
+ ,rollover-caption .meta:n = {MK/RC=#1}
+ }
+
+\keys_define:nn { pdffield }
+ {
+ MK/AC .code:n =
+ {
+ \tl_set:Nn \l_@@_down_caption_tl {#1}
+ \tl_if_empty:nTF {#1}
+ {
+ \pdfannot_dict_remove:nn { widget/MK }{AC}
+ }
+ {
+ \pdf_string_from_unicode:nnN {utf8/string}{#1}\l_@@_tmpa_str
+ \pdfannot_dict_put:nnx {widget/MK}{AC}{\l_@@_tmpa_str}
+ }
+ }
+ ,MK/AC .groups:n = annot
+ ,down-caption .meta:n = {MK/AC=#1}
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{MK/I,MK/RI,MK/IX,MK/IF,MK/TP}
+% The following keys are pushputtons only. Currently there is no special handling
+% involved as it is unclear if they are useful.
+% \begin{macrocode}
+
\cs_set_protected:Npn \@@_tmpa:n #1
{
\keys_define:nn { pdffield }
@@ -1489,7 +1961,7 @@
{
\tl_if_empty:nTF {##1}
{
- \pdfannot_dict_remove:nn { widget/AP }{#1}
+ \pdfannot_dict_remove:nn { widget/MK }{#1}
}
{
\pdfannot_dict_put:nnx {widget/MK}{#1}{##1}
@@ -1499,10 +1971,13 @@
}
}
-\clist_map_inline:nn {RC,AC,I,RI,IX,IF,TP}
+\clist_map_inline:nn {I,RI,IX,IF,TP}
{ \@@_tmpa:n {#1} }
% \end{macrocode}
+% \end{macro}
+%
% Flags.
+% \begin{macro}{setF,setannotflags,unsetF,unsetannotflags}
% \begin{macrocode}
\keys_define:nn { pdffield }
{
@@ -1530,11 +2005,17 @@
}
% \end{macrocode}
-%
+% \end{macro}
% 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{macro}
+% {
+% AA/Fo,onfocus, AA/Bl,onblur, AA/D,onmousedown, AA/U,onmouseup,
+% AA/E,onenter, AA/X,onexit, AA/PO,pageopen, AA/PC,pageclose,
+% AA/PV,pagevisible, AA/PI,pageinvisible
+% }
% \begin{macrocode}
\cs_set_protected:Npn \@@_tmpa:n #1 %
{
@@ -1542,15 +2023,14 @@
{
AA/#1 .code:n =
{
- \pdf_string_from_unicode:nnN {utf8/string-raw}{##1}\l_@@_tmpa_str
- \str_if_empty:NTF \l_@@_tmpa_str
+ \tl_if_empty:nTF {#1}
{
\pdfannot_dict_remove:nn {widget/AA}{#1}
}
{
\pdfannot_dict_put:nnx {widget/AA}
{#1}
- {<</S/JavaScript/JS(\l_@@_tmpa_str)>>}
+ {<</S/JavaScript/JS\c_space_tl##1>>}
}
},
,AA/#1 .groups:n = annot
@@ -1575,8 +2055,9 @@
\@@_tmpa:nn {onenter} {E}
\@@_tmpa:nn {onexit} {X}
% \end{macrocode}
+% \end{macro}
% \subsection{Appearances}
-% \begin{macro}{\pdffield_appearance:nn}
+% \begin{macro}{\pdffield_appearance:nn,\pdffield_store_appearance:nn}
% \begin{macrocode}
\cs_new_protected:Npn \pdffield_appearance:nn #1 #2
{
@@ -1587,7 +2068,7 @@
% \end{macrocode}
% \end{macro}
% \subsection{Setup command}
-%
+% \begin{macro}{create-style,preset-checkbox,preset-radio,preset-textfield}
% \begin{macrocode}
\keys_define:nn { pdffield / setup }
{
@@ -1599,6 +2080,13 @@
@@/preset/checkbox .meta:n = {#1},
}
}
+ ,preset-radiobutton .code:n =
+ {
+ \keys_define:nn { pdffield }
+ {
+ @@/preset/radiobutton .meta:n = {#1},
+ }
+ }
,preset-textfield .code:n =
{
\keys_define:nn { pdffield }
@@ -1606,10 +2094,30 @@
@@/preset/textfield .meta:n = {#1},
}
}
+ ,preset-pushbutton .code:n =
+ {
+ \keys_define:nn { pdffield }
+ {
+ @@/preset/pushbutton .meta:n = {#1},
+ }
+ }
+ ,preset-choice .code:n =
+ {
+ \keys_define:nn { pdffield }
+ {
+ @@/preset/choice .meta:n = {#1},
+ }
+ }
}
\keys_set:nn{ pdffield / setup }{preset-checkbox={}}
\keys_set:nn{ pdffield / setup }{preset-textfield={}}
-
+\keys_set:nn{ pdffield / setup }{preset-radiobutton={}}
+\keys_set:nn{ pdffield / setup }{preset-pushbutton={}}
+\keys_set:nn{ pdffield / setup }{preset-choice={}}
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\@@_style_create:nn}
+% \begin{macrocode}
\cs_new_protected:Npn \@@_style_create:nn #1#2
{
\keys_define:nn { pdffield }
@@ -1618,7 +2126,10 @@
}
}
-
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\pdffield_setup:n,style}
+% \begin{macrocode}
\cs_new_protected:Npn \pdffield_setup:n #1
{
\keys_set:nn{ pdffield / setup }{#1}
@@ -1629,6 +2140,25 @@
style .code:n = {\keys_set:nn {pdffield}{@@/style/#1={#1}}}
}
% \end{macrocode}
+% \end{macro}
+% \section{Value keys}
+% \begin{macro}{value,default,\@@_value_handler:n,\@@_default_handler:n}
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_value_handler:n #1
+ {
+ \msg_info:nnn {pdffield}{key-ignored}{value}
+ }
+\cs_new_protected:Npn \@@_default_handler:n #1
+ {
+ \msg_info:nnn {pdffield}{key-ignored}{default}
+ }
+\keys_define:nn {pdffield}
+ {
+ value .code:n = { \@@_value_handler:n {#1} }
+ ,default .code:n = { \@@_default_handler:n {#1}}
+ }
+% \end{macrocode}
+% \end{macro}
% \begin{macrocode}
%</package>
% \end{macrocode}
diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3pdffield.pdf b/macros/latex/contrib/pdfmanagement-testphase/l3pdffield.pdf
index 903cd42c0a..12fd435f3e 100644
--- a/macros/latex/contrib/pdfmanagement-testphase/l3pdffield.pdf
+++ b/macros/latex/contrib/pdfmanagement-testphase/l3pdffield.pdf
Binary files differ
diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3pdffile.dtx b/macros/latex/contrib/pdfmanagement-testphase/l3pdffile.dtx
index cf2176e439..81e2ef273e 100644
--- a/macros/latex/contrib/pdfmanagement-testphase/l3pdffile.dtx
+++ b/macros/latex/contrib/pdfmanagement-testphase/l3pdffile.dtx
@@ -31,7 +31,7 @@
\documentclass[full]{l3doc}
\usepackage{array,booktabs,hyperxmp}
\hypersetup{pdfauthor=The LaTeX Project,pdftitle=l3pdffile (LaTeX PDF management testphase bundle)}
-
+\usepackage{caption}
\providecommand\potentialclash{\noindent\llap{\dbend\ }}
\begin{document}
\DocInput{\jobname.dtx}
@@ -53,7 +53,7 @@
% }^^A
% }
%
-% \date{Version 0.95d, released 2021-05-14}
+% \date{Version 0.95e, released 2021-06-14}
%
% \maketitle
% \begin{documentation}
@@ -245,13 +245,14 @@
% \end{function}
% \begin{table}
% \caption{Preset values in the file dictionaries\label{tab:filedict}}
-% \begin{tabular}{lll}
+% \hspace*{-3cm}\begin{tabular}{lll}
% dictionary & key & value \\\hline
% l\_pdffile & Type & /EmbeddedFile\\
% l\_pdffile/Params& Size & |\file_size:n{\l_pdffile_source_name_str}|\\
% l\_pdffile/Params& ModDate & |(\file_timestamp:n {\l_pdffile_source_name_str})|\\
% l\_pdffile/Params& CheckSum & |(\file_mdfive_hash:n{\l_pdffile_source_name_str})|\\
-% l\_pdffile/streamParams& & a /ModDate entry with year/month/date (used with \cs{pdffile_embed_stream:nnn})\\
+% l\_pdffile/streamParams& & a /ModDate entry with year/month/date \\
+% & & (used with \cs{pdffile_embed_stream:nnn})\\
% l\_pdffile/Filespec & Type & /Filespec\\
% l\_pdffile/Filespec & AFRelationship &Unspecified
% \end{tabular}
@@ -324,6 +325,28 @@
% The stream should not be too long, at least PS imposes a size limit for strings.
% \end{function}
%
+% \begin{function}{\pdffile_filespec:nnn,\pdffile_filespec:nnx}
+% \begin{syntax}
+% \cs{ pdffile_filespec:nnn }\Arg{object name}\Arg{file name}{stream object reference}
+% \end{syntax}
+% The previous commands are fine if stream and filespec dictionary can be created together.
+% But there are cases where the |filespec| dictionary should be referenced when the
+% stream object doesn't exist yet. For example in the |AF| key of a structure at
+% the begin of an environment where the stream is created from the body.
+%
+% This command allows to write a filespec dictionary alone and reference a previously
+% created stream.
+%
+% \begin{verbatim}
+% \pdf_object_new:nn{module/filespec/A}{dict} % a new filespec object
+% \pdf_object_ref:n {module/filespec/A} % a reference
+% \pdf_object_unnamed_write:nn { stream }{ {...}{content} } %writing the stream
+% % filling and writing the filespec dictionary:
+% \pdffile_filespec:nnn {module/filespec/A}{A.xml}{\pdf_object_ref_last:}
+% \end{verbatim}
+%
+% \end{function}
+%
% \begin{variable}{\g_pdffile_mimetypes_prop}
% This property contains a list of extensions and their mimetypes.
% Values can be added or changed with the standard commands:
@@ -377,7 +400,7 @@
%
% \begin{macrocode}
%<*header>
-\ProvidesExplPackage{l3pdffile}{2021-05-14}{0.95d}
+\ProvidesExplPackage{l3pdffile}{2021-06-14}{0.95e}
{embedding and referencing files in PDF---LaTeX PDF management testphase bundle}
\RequirePackage{l3pdftools} %temporarly!!
%</header>
@@ -636,7 +659,8 @@
}
}
-
+\cs_set_eq:NN \pdffile_filespec:nnn \@@_filespec_write:nnn
+\cs_generate_variant:Nn \pdffile_filespec:nnn {nnx}
%#1 {source filename}
%#2 {target filename}
%#3 { filespec object name } (will internally get a prefix! ??)
diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3pdffile.pdf b/macros/latex/contrib/pdfmanagement-testphase/l3pdffile.pdf
index b9b9a92b26..d5163b066e 100644
--- a/macros/latex/contrib/pdfmanagement-testphase/l3pdffile.pdf
+++ b/macros/latex/contrib/pdfmanagement-testphase/l3pdffile.pdf
Binary files differ
diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3pdfmanagement.dtx b/macros/latex/contrib/pdfmanagement-testphase/l3pdfmanagement.dtx
index 9383c03290..567bbc58a0 100644
--- a/macros/latex/contrib/pdfmanagement-testphase/l3pdfmanagement.dtx
+++ b/macros/latex/contrib/pdfmanagement-testphase/l3pdfmanagement.dtx
@@ -61,7 +61,7 @@
% }^^A
% }
%
-% \date{Version 0.95d, released 2021-05-14}
+% \date{Version 0.95e, released 2021-06-14}
%
% \maketitle
% \begin{documentation}
@@ -557,7 +557,7 @@
%<@@=pdfmanagement>
%<*header>
%
-\ProvidesExplPackage{l3pdfmanagement}{2021-05-14}{0.95d}
+\ProvidesExplPackage{l3pdfmanagement}{2021-06-14}{0.95e}
{Management of core PDF dictionaries (LaTeX PDF management testphase bundle)}
%</header>
% \end{macrocode}
@@ -914,9 +914,12 @@
% push to the register command / issue the special
\cs_new_protected:Npn \@@_Pages_gpush:
{
- \exp_args:Nx \__pdf_backend_Pages_primitive:n
+ \pdfdict_if_empty:nF { g__pdf_Core/Pages}
{
- \pdfdict_use:n { g__pdf_Core/Pages}
+ \exp_args:Nx \__pdf_backend_Pages_primitive:n
+ {
+ \pdfdict_use:n { g__pdf_Core/Pages}
+ }
}
}
diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3pdfmanagement.pdf b/macros/latex/contrib/pdfmanagement-testphase/l3pdfmanagement.pdf
index b35c3a3a4d..f065b63c72 100644
--- a/macros/latex/contrib/pdfmanagement-testphase/l3pdfmanagement.pdf
+++ b/macros/latex/contrib/pdfmanagement-testphase/l3pdfmanagement.pdf
Binary files differ
diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3pdfmeta.dtx b/macros/latex/contrib/pdfmanagement-testphase/l3pdfmeta.dtx
index 44ea8a9191..f78fc98375 100644
--- a/macros/latex/contrib/pdfmanagement-testphase/l3pdfmeta.dtx
+++ b/macros/latex/contrib/pdfmanagement-testphase/l3pdfmeta.dtx
@@ -53,7 +53,7 @@
% }^^A
% }
%
-% \date{Version 0.95d, released 2021-05-14}
+% \date{Version 0.95e, released 2021-06-14}
%
% \maketitle
% \begin{documentation}
@@ -220,6 +220,9 @@
% this will e.g. be checked by the new hyperref driver.
% \item[|annot_widget_no_A_AA|] (rule 6.9-2) no A and AA dictionary in widget.
% \item[|form_no_AA|] (6.9-3) no /AA dictionary in form field
+% \item[|unicode|] that is set in the U-standards, A-2u and A-3u and means that
+% every text should be in unicode. This is not something that can be enforced or
+% tested from TeX, but in a current LaTeX normally ToUnicode are set for all fonts.
% \end{description}
%
% \subsubsection{Tests with values and special handlers}
@@ -340,7 +343,7 @@
% \begin{macrocode}
%<@@=pdfmeta>
%<*header>
-\ProvidesExplPackage{l3pdfmeta}{2021-05-14}{0.95d}
+\ProvidesExplPackage{l3pdfmeta}{2021-06-14}{0.95e}
{PDF-Standards---LaTeX PDF management testphase bundle}
%</header>
% \end{macrocode}
@@ -513,7 +516,9 @@
% \begin{variable}{
% \g_@@_standard_pdf/A-1B_prop ,
% \g_@@_standard_pdf/A-2B_prop ,
-% \g_@@_standard_pdf/A-3B_prop
+% \g_@@_standard_pdf/A-2U_prop ,
+% \g_@@_standard_pdf/A-3B_prop ,
+% \g_@@_standard_pdf/A-3U_prop ,
% }
% \begin{macrocode}
\prop_new:c { g_@@_standard_pdf/A-1B_prop }
@@ -521,6 +526,8 @@
{
,name = pdf/A-1B
,type = A
+ ,level = 1
+ ,conformance = B
,year = 2005
,min_pdf_version = 1.4 %minimum
,no_encryption =
@@ -580,11 +587,25 @@
{ g_@@_standard_pdf/A-2B_prop }{name}{pdf/A-2B}
\prop_gput:cnn
{ g_@@_standard_pdf/A-2B_prop }{year}{2011}
+\prop_gput:cnn
+ { g_@@_standard_pdf/A-2B_prop }{level}{2}
% embedding files is allowed (with restrictions)
\prop_gremove:cn
{ g_@@_standard_pdf/A-2B_prop }
{ embed_content}
+%A-2u ==============
+\prop_new:c { g_@@_standard_pdf/A-2U_prop }
+\prop_gset_eq:cc
+ { g_@@_standard_pdf/A-2U_prop }
+ { g_@@_standard_pdf/A-2B_prop }
+\prop_gput:cnn
+ { g_@@_standard_pdf/A-2U_prop }{name}{pdf/A-2U}
+\prop_gput:cnn
+ { g_@@_standard_pdf/A-2U_prop }{conformance}{U}
+\prop_gput:cnn
+ { g_@@_standard_pdf/A-2U_prop }{unicode}{}
+
%A-3b ==============
\prop_new:c { g_@@_standard_pdf/A-3B_prop }
\prop_gset_eq:cc
@@ -593,11 +614,25 @@
\prop_gput:cnn
{ g_@@_standard_pdf/A-3B_prop }{name}{pdf/A-3B}
\prop_gput:cnn
- { g_@@_standard_pdf/A-2B_prop }{year}{2012}
+ { g_@@_standard_pdf/A-3B_prop }{year}{2012}
+\prop_gput:cnn
+ { g_@@_standard_pdf/A-3B_prop }{level}{3}
% embedding files is allowed (with restrictions)
\prop_gremove:cn
{ g_@@_standard_pdf/A-3B_prop }
{ embed_content}
+
+%A-3u ==============
+\prop_new:c { g_@@_standard_pdf/A-3U_prop }
+\prop_gset_eq:cc
+ { g_@@_standard_pdf/A-3U_prop }
+ { g_@@_standard_pdf/A-3B_prop }
+\prop_gput:cnn
+ { g_@@_standard_pdf/A-3U_prop }{name}{pdf/A-3U}
+\prop_gput:cnn
+ { g_@@_standard_pdf/A-3U_prop }{conformance}{U}
+\prop_gput:cnn
+ { g_@@_standard_pdf/A-3U_prop }{unicode}{}
% \end{macrocode}
% \end{variable}
%
diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3pdfmeta.pdf b/macros/latex/contrib/pdfmanagement-testphase/l3pdfmeta.pdf
index 7b8fdcea93..c6d4c7107b 100644
--- a/macros/latex/contrib/pdfmanagement-testphase/l3pdfmeta.pdf
+++ b/macros/latex/contrib/pdfmanagement-testphase/l3pdfmeta.pdf
Binary files differ
diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3pdftools.dtx b/macros/latex/contrib/pdfmanagement-testphase/l3pdftools.dtx
index 76368fc475..edffcde521 100644
--- a/macros/latex/contrib/pdfmanagement-testphase/l3pdftools.dtx
+++ b/macros/latex/contrib/pdfmanagement-testphase/l3pdftools.dtx
@@ -53,7 +53,7 @@
% }^^A
% }
%
-% \date{Version 0.95d, released 2021-05-14}
+% \date{Version 0.95e, released 2021-06-14}
%
% \maketitle
% \begin{documentation}
@@ -215,7 +215,7 @@
%
% \begin{macrocode}
%<*header>
-\ProvidesExplPackage{l3pdftools}{2021-05-14}{0.95d}
+\ProvidesExplPackage{l3pdftools}{2021-06-14}{0.95e}
{candidate commands for l3pdf---LaTeX PDF management testphase bundle}
%</header>
% \end{macrocode}
@@ -346,6 +346,7 @@
\exp_not:N \str_replace_all:Nnn #2 {\c_percent_str 2C} {,}
\exp_not:N \str_replace_all:Nnn #2 {\c_percent_str 3B} {;}
\exp_not:N \str_replace_all:Nnn #2 {\c_percent_str 3D} {=}
+ \exp_not:N \str_replace_all:Nnn #2 {\c_percent_str 3F} {?}
\exp_not:N \str_replace_all:Nnn #2 {\c_percent_str 30} {0}
\exp_not:N \str_replace_all:Nnn #2 {\c_percent_str 31} {1}
\exp_not:N \str_replace_all:Nnn #2 {\c_percent_str 32} {2}
diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3pdftools.pdf b/macros/latex/contrib/pdfmanagement-testphase/l3pdftools.pdf
index 4df0731176..497b9f5a39 100644
--- a/macros/latex/contrib/pdfmanagement-testphase/l3pdftools.pdf
+++ b/macros/latex/contrib/pdfmanagement-testphase/l3pdftools.pdf
Binary files differ
diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3pdfxform.dtx b/macros/latex/contrib/pdfmanagement-testphase/l3pdfxform.dtx
index 25465bdcb0..3508e2b25b 100644
--- a/macros/latex/contrib/pdfmanagement-testphase/l3pdfxform.dtx
+++ b/macros/latex/contrib/pdfmanagement-testphase/l3pdfxform.dtx
@@ -52,7 +52,7 @@
% }^^A
% }
%
-% \date{Version 0.95d, released 2021-05-14}
+% \date{Version 0.95e, released 2021-06-14}
%
% \maketitle
% \begin{documentation}
@@ -133,7 +133,7 @@
% \begin{macrocode}
%<@@=pdf>
%<*header>
-\ProvidesExplPackage{l3pdfxform}{2021-05-14}{0.95d}
+\ProvidesExplPackage{l3pdfxform}{2021-06-14}{0.95e}
{command to create xforms (beta)---LaTeX PDF management testphase bundle}
%</header>
% \end{macrocode}
diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3pdfxform.pdf b/macros/latex/contrib/pdfmanagement-testphase/l3pdfxform.pdf
index 8ff3c6f2d5..4b6d7ee999 100644
--- a/macros/latex/contrib/pdfmanagement-testphase/l3pdfxform.pdf
+++ b/macros/latex/contrib/pdfmanagement-testphase/l3pdfxform.pdf
Binary files differ
diff --git a/macros/latex/contrib/pdfmanagement-testphase/ltdocinit.dtx b/macros/latex/contrib/pdfmanagement-testphase/ltdocinit.dtx
index 4d6974eefe..d8e85c5e4c 100644
--- a/macros/latex/contrib/pdfmanagement-testphase/ltdocinit.dtx
+++ b/macros/latex/contrib/pdfmanagement-testphase/ltdocinit.dtx
@@ -51,7 +51,7 @@
% }^^A
% }
%
-% \date{Version 0.95d, released 2021-05-14}
+% \date{Version 0.95e, released 2021-06-14}
%
% \maketitle
% \begin{documentation}
@@ -103,10 +103,13 @@
% \item[\texttt{lang}] to set the Lang entry in the Catalog.
% E.g. \texttt{lang=de-DE}. The initial value is |en-US|
% \item[\texttt{pdfstandard}] Choice key to set the pdf standard.
-% Currently |A-1b|, |A-2b| and |A-3b| are accepted as
-% values. The underlying code to ensure the requirements (as far as they
+% Currently |A-1b|, |A-2b|, |A-2u|, |A-3b| and |A-3u| are accepted as
+% values. The casing is irrelevant, |a-1b| works too.
+% The underlying code to ensure the requirements (as far as they
% can be ensured) is incomplete, but a color profile is included and the
-% /OutputIntent is set. More information can be found in the documentation
+% /OutputIntent is set. The |u| variants for example do not force unicode,
+% but they will pass the information to hyperref and hyperxmp.
+% More information can be found in the documentation
% of \pkg{l3pdfmeta}.
% \item[\texttt{colorprofiles}] This allows to load icc-colorprofiles. Details
% are described in the documentation of \pkg{l3pdfmeta}.
@@ -138,7 +141,7 @@
%
% \begin{function}{\GetDocumentProperties}
% \begin{syntax}
-% \cs{AddToDocumentProperties}\Arg{label/property}
+% \cs{GetDocumentProperties}\Arg{label/property}
% \end{syntax}
% Expands to the \meta{value} corresponding to \meta{label/property}
% in the container. If \meta{label/property} is missing,
@@ -164,7 +167,7 @@
% \begin{macrocode}
%<@@=pdfmanagement>
%<*header>
-\ProvidesExplPackage{ltdocinit}{2021-05-14}{0.95d}
+\ProvidesExplPackage{ltdocinit}{2021-06-14}{0.95e}
{Initialize document metadata}
%</header>
% \end{macrocode}
@@ -329,7 +332,7 @@
\keys_set:nn {document / metadata} {_pdfstandard=\str_uppercase:n{#1}}
}
,_pdfstandard .choices:nn =
- {A-1B,A-2B,A-3B}
+ {A-1B,A-2B,A-2U,A-3B,A-3U}
{
\prop_if_exist:cT { g__pdfmeta_standard_pdf/#1_prop }
{
diff --git a/macros/latex/contrib/pdfmanagement-testphase/ltdocinit.pdf b/macros/latex/contrib/pdfmanagement-testphase/ltdocinit.pdf
index a7138a39fc..15a76982d1 100644
--- a/macros/latex/contrib/pdfmanagement-testphase/ltdocinit.pdf
+++ b/macros/latex/contrib/pdfmanagement-testphase/ltdocinit.pdf
Binary files differ
diff --git a/macros/latex/contrib/pdfmanagement-testphase/pdflscape-ltx.sty b/macros/latex/contrib/pdfmanagement-testphase/pdflscape-ltx.sty
index 43ac3a7ce9..9fa7a39930 100644
--- a/macros/latex/contrib/pdfmanagement-testphase/pdflscape-ltx.sty
+++ b/macros/latex/contrib/pdfmanagement-testphase/pdflscape-ltx.sty
@@ -22,9 +22,11 @@
%% This work consists of the main source file pdflscape-ltx.sty
%%
\NeedsTeXFormat{LaTeX2e}
-\ProvidesExplPackage{pdflscape-ltx}{2021-05-14}{0.95d}
+\ProvidesExplPackage{pdflscape-ltx}{2021-06-14}{0.95e}
{Display of landscape pages in PDF - adaption of pdflscape to the PDFmanagement bundle (testphase)}
+\DeclareOption*{\PassOptionsToPackage\CurrentOption{graphics}}
+\ProcessOptions
\RequirePackage{lscape}
% this always turns in the same direction as pdflscape does too.
% left and right would need
diff --git a/macros/latex/contrib/pdfmanagement-testphase/pdfmanagement-firstaid.dtx b/macros/latex/contrib/pdfmanagement-testphase/pdfmanagement-firstaid.dtx
index 647fd55f93..f2cd31608a 100644
--- a/macros/latex/contrib/pdfmanagement-testphase/pdfmanagement-firstaid.dtx
+++ b/macros/latex/contrib/pdfmanagement-testphase/pdfmanagement-firstaid.dtx
@@ -51,7 +51,7 @@
% }^^A
% }
%
-% \date{Version 0.95d, released 2021-05-14}
+% \date{Version 0.95e, released 2021-06-14}
%
% \maketitle
% \begin{documentation}
@@ -67,7 +67,7 @@
% |firstaidoff={name1,name2,...}|.
% \begin{macrocode}
%<*package>
-\ProvidesExplPackage{pdfmanagement-firstaid}{2021-05-14}{0.95d}
+\ProvidesExplPackage{pdfmanagement-firstaid}{2021-06-14}{0.95e}
{LaTeX PDF management testphase bundle / firstaid-patches}
%<@@=pdfmanagement>
diff --git a/macros/latex/contrib/pdfmanagement-testphase/pdfmanagement-firstaid.pdf b/macros/latex/contrib/pdfmanagement-testphase/pdfmanagement-firstaid.pdf
index 41b232b735..f9ad37cc81 100644
--- a/macros/latex/contrib/pdfmanagement-testphase/pdfmanagement-firstaid.pdf
+++ b/macros/latex/contrib/pdfmanagement-testphase/pdfmanagement-firstaid.pdf
Binary files differ
diff --git a/macros/latex/contrib/pdfmanagement-testphase/pdfmanagement-testphase.dtx b/macros/latex/contrib/pdfmanagement-testphase/pdfmanagement-testphase.dtx
index 82dc047ada..01636edb1e 100644
--- a/macros/latex/contrib/pdfmanagement-testphase/pdfmanagement-testphase.dtx
+++ b/macros/latex/contrib/pdfmanagement-testphase/pdfmanagement-testphase.dtx
@@ -51,7 +51,7 @@
% }^^A
% }
%
-% \date{Version 0.95d, released 2021-05-14}
+% \date{Version 0.95e, released 2021-06-14}
%
% \maketitle
% \begin{documentation}
@@ -384,7 +384,7 @@
% \begin{macrocode}
%<@@=pdf>
%<*package>
-\ProvidesExplPackage{pdfmanagement-testphase}{2021-05-14}{0.95d}
+\ProvidesExplPackage{pdfmanagement-testphase}{2021-06-14}{0.95e}
{LaTeX PDF management testphase bundle}
\providecommand\IfFormatAtLeastTF{\@ifl@t@r\fmtversion}
\IfFormatAtLeastTF{2020-10-01}{}{
@@ -411,7 +411,7 @@
% to allow to set it in the document.
% \begin{macrocode}
%<*header>
-\ProvidesExplFile{pdfmanagement-testphase.ltx}{2021-05-14}{0.95d}
+\ProvidesExplFile{pdfmanagement-testphase.ltx}{2021-06-14}{0.95e}
{PDF~management~code~(testphase)}
%</header>
%<*package>
diff --git a/macros/latex/contrib/pdfmanagement-testphase/pdfmanagement-testphase.ins b/macros/latex/contrib/pdfmanagement-testphase/pdfmanagement-testphase.ins
index 97db2f066e..e6ab7caa43 100644
--- a/macros/latex/contrib/pdfmanagement-testphase/pdfmanagement-testphase.ins
+++ b/macros/latex/contrib/pdfmanagement-testphase/pdfmanagement-testphase.ins
@@ -129,7 +129,11 @@ and all files in that bundle must be distributed together.
{%
\from{l3pdffield.dtx}{package}
\from{l3pdffield-checkbox.dtx}{package}
+ \from{l3pdffield-radiobutton.dtx}{package}
\from{l3pdffield-textfield.dtx}{package}
+ \from{l3pdffield-pushbutton.dtx}{package}
+ \from{l3pdffield-choice.dtx}{package}
+ \from{l3pdffield-action.dtx}{package}
}%
}
diff --git a/macros/latex/contrib/pdfmanagement-testphase/pdfmanagement-testphase.pdf b/macros/latex/contrib/pdfmanagement-testphase/pdfmanagement-testphase.pdf
index 2d1700dd49..33a851a4cd 100644
--- a/macros/latex/contrib/pdfmanagement-testphase/pdfmanagement-testphase.pdf
+++ b/macros/latex/contrib/pdfmanagement-testphase/pdfmanagement-testphase.pdf
Binary files differ
diff --git a/macros/latex/contrib/pdfmanagement-testphase/transparent-ltx.sty b/macros/latex/contrib/pdfmanagement-testphase/transparent-ltx.sty
index 4b4030c4b2..be65dc7a52 100644
--- a/macros/latex/contrib/pdfmanagement-testphase/transparent-ltx.sty
+++ b/macros/latex/contrib/pdfmanagement-testphase/transparent-ltx.sty
@@ -3,7 +3,7 @@
%% a replacement for transparent sty from Heiko Oberdiek
%%
\NeedsTeXFormat{LaTeX2e}[2020/10/01]
-\ProvidesExplPackage{transparent-ltx}{2021-05-14}{0.95d}
+\ProvidesExplPackage{transparent-ltx}{2021-06-14}{0.95e}
{Transparency with color stacks (replacement for transparent.sty from Heiko Oberdiek)}%
\RequirePackage{l3opacity}
diff --git a/macros/latex/contrib/pdfmanagement-testphase/xcolor-patches-tmp-ltx.sty b/macros/latex/contrib/pdfmanagement-testphase/xcolor-patches-tmp-ltx.sty
index 76aee08fef..2070e1b15e 100644
--- a/macros/latex/contrib/pdfmanagement-testphase/xcolor-patches-tmp-ltx.sty
+++ b/macros/latex/contrib/pdfmanagement-testphase/xcolor-patches-tmp-ltx.sty
@@ -1,6 +1,6 @@
%% LaTeX2e file `xcolor-patches.sty'
%%
-\ProvidesPackage{xcolor-patches-tmp-ltx}[2021-05-14 v0.95d patch xcolor for l3color]
+\ProvidesPackage{xcolor-patches-tmp-ltx}[2021-06-14 v0.95e patch xcolor for l3color]
\@ifundefined{color_set:nn}{\RequirePackage{l3color}}{}
\ExplSyntaxOn