diff options
Diffstat (limited to 'macros/latex/contrib/pdfmanagement-testphase/l3pdffield.dtx')
-rw-r--r-- | macros/latex/contrib/pdfmanagement-testphase/l3pdffield.dtx | 722 |
1 files changed, 626 insertions, 96 deletions
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} |