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

\usepackage{array,booktabs}
\hypersetup{pdfauthor=The LaTeX Project,
 pdftitle=l3pdfannot (LaTeX PDF management bundle)}
\begin{document}
  \DocInput{\jobname.dtx}
\end{document}
%</driver>
% \fi
% \providecommand\hook[1]{\texttt{#1}}
% \title{^^A
%   The \pkg{l3pdfannot} module\\ Commands for PDF annotations   ^^A
%   \\ \LaTeX{} PDF management bundle
% }
%
% \author{^^A
%  The \LaTeX{} Project\thanks
%    {^^A
%      E-mail:
%        \href{mailto:latex-team@latex-project.org}
%          {latex-team@latex-project.org}^^A
%    }^^A
% }
%
% \date{Version 0.96y, released 2026-01-23}
%
% \maketitle
% \begin{documentation}
%
% \section{\pkg{l3pdfannot} documentation}
% This module contains a number of commands to create PDF annotations.
% The commands are \emph{not} always simple wrappers around primitive commands.
% To allow external packages to configure links and other annotations,
% some of the commands have hooks and use shared attribute dictionaries.
% For these commands the hooks and dictionaries are selected depending on the \meta{type}
% of the annotation. Currently the module only supports some general commands
% and link annotations. Commands for other annotations like widgets will be added
% later.
%
% \subsection{dvips specialities}
% With most engines and backend the content of arguments like \Arg{annot spec}
% are dictionaries with keys and values which looks like the PDF.
% With dvips this is different. As it write at first a postscript file which is
% then interpreted along the rule of the pdfmark reference (and the rules of the postscript
% language) the handling is in some parts so different that it is difficult to hide
% this in abstraction like the one of this module.
% And there is the additional complication that the
% two postscript processor ghostscript (ps2pdf) and distiller handles some code differently too.
%
% For now the following differences have been spotted, it is yet not quite clear
% how to resolve them
% \begin{itemize}
% \item distiller doesn't like it if the action is provided by directly
% providing the |/A| key with some values.
% Instead it expects a keyword \texttt{/Action}, which it will
% then translate to |/A|. For |GoTo| links this has been resolved at the backend level,
% but for other link types this problem is open.
% \item ghostscript doesn't like object references as values in some places.
% The work around here (which is e.g. used by hyperref for GoToR link) is to
% write the whole dictionary first as an object and to use its reference, but this
% is something distiller doesn't like, sigh.
% \item How to escaping text and create unicode can be different.
% \end{itemize}
%
%
%
% \subsection{General annotation commands}
%
% \begin{function}[added = 2019-09-05, updated = 2020-04-14]
%   { \pdfannot_box:nnnn,\pdfannot_box:nnne }
%   \begin{syntax}
%     \cs{pdfannot_box:nnnn} \Arg{width} \Arg{height} \Arg{depth} \Arg{annot spec}
%   \end{syntax}
%   This creates an \texttt{/Type/Annot} object with the given dimensions.
%   It doesn't use hooks or dictionaries. The annotation doesn't occupy space but
%   as it is a whatsit it can affect spacing.
% \end{function}
%
% \begin{function}[added = 2019-09-05]
%   { \pdfannot_box_ref_last: }
%   \begin{syntax}
%     \cs{pdfannot_box_ref_last:}
%   \end{syntax}
%   This retrieves the object reference of the last box annotation created.
% \end{function}
% \subsection{Dictionary for the annotation spec}
%
% \meta{annot spec} in the above command can be given in two ways. One way is
% to enter the needed dictionary keys and values directly:
% \begin{verbatim}
%  \pdfannot_box:nnnn{1cm}{1cm}{0cm}{/Subtype/Link /Border[0~0~1]}
% \end{verbatim}
%
% A second method is to make use of the dictionary commands provided by \pkg{l3pdfdict}:
%
% \begin{verbatim}
% \pdfdict_new:n  {l_my_annot}
% \pdfdict_put:nnn{l_my_annot}{Subtype}{/Link}
% \pdfdict_put:nnn{l_my_annot}{Border}{[0~0~1]}
% \pdfannot_box:nnne{1cm}{1cm}{0cm}{\pdfdict_use:n{l_my_annot}}
% \end{verbatim}
%
% The second method is clearly slower and more to type. But it has the advantage
% that using such a dictionary makes it easy to add, remove and change entries.
% It also avoids the potential problem that a key is added twice with different
% values. This allows to create user interfaces to change settings and
% also makes it easy to extend the interfaces in case some new setting
% should be included. For these reasons both the PDF management itself,
% but also the specific annotation commands in the following sections
% all make use of such dictionaries.
%
% \subsection{Link annotations}
% Link annotations are special cases of annotations. In the PDF they are identified
% by an |/Subtype/Link| entry in the dictionary.
% Link annotations are quite important as many documents contain links,
% both internal and external. They need a set of special commands for two reasons:
%
% At first the content of links are not only boxes. Links can contain line
% and page breaks (this is normally implemented by the primitive command by
% creating a set of annotations).
%
% At second link annotations are objects that need some
% \enquote{management} as more than one
% package wants to configure their look and behaviour.
% For example \pkg{hyperref}, \pkg{ocgx2} and the code for tagged PDF (currently
% in \pkg{tagpdf}) all want to add keys and values to the dictionaries of
% link annotation and code around links.
% So commands to create link annotations should offer suitable hooks.
% There are three standard places in a link where such hooks are needed:
% At the begin (for example for a structure command or color),
% in the \emph{attr spec} dictionary of the link (for example for the border), and
% at the end of the link (to close a structure or the color group).
% For the begin and end hooks of the LaTeX hook management are predefined and used.
% To add and remove values from the \emph{attr spec} dictionary special
% commands described below are provided. The link commands switch to horizontal mode
% as the commands of pdftex and luatex can't be used in vertical mode.
%
% \begin{variable}{\c_pdfannot_link_types_seq}
% There are currently five link types, \texttt{URI}, \texttt{GoToR},
%  \texttt{Launch}, \texttt{GoTo} or \texttt{Named}, and there are stored in this
%  constant.
% \end{variable}
% \begin{variable}
%  {
%   pdfannot/link/TYPE/before,
%   pdfannot/link/TYPE/begin,
%   pdfannot/link/TYPE/end,
%   pdfannot/link/TYPE/after
%  }
%  These are the hooks used by the following commands. TYPE can be one of
%  \texttt{URI}, \texttt{GoToR},
%  \texttt{Launch}, \texttt{GoTo} or \texttt{Named}
% \end{variable}
% \begin{variable}
%  {
%    link/TYPE
%  }
%  These is the name of the dictionary used by the following commands. TYPE can be one of
%  \texttt{URI}, \texttt{GoToR},
%  \texttt{Launch}, \texttt{GoTo} or \texttt{Named}. The dictionary can be changed
%  by the commands \cs{pdfannot_dict_put:nnn} and friends described below.
% \end{variable}
% \begin{function}[added = 2020-03-12, updated = 2020-12-06]
%    { \pdfannot_link:nnn,\pdfannot_link:nen }
%   \begin{syntax}
%     \cs{pdfannot_link:nnn} \Arg{type} \Arg{user action spec} \Arg{link text}
%   \end{syntax}
%  This creates a link around the \meta{link text}.
%  \texttt{/Subtype/Link} is added automatically through the dictionary.
%  \meta{user action spec}\footnote{The wording follows the pdftex documentation}.
%  is provided as a fast method to add dictionary contents,
%  but it should be noted that no provision is taken to avoid clashes with
%  values added through the dictionary. If needed clashing entries should be
%  removed from the dictionary first. Normally the argument is not needed, all
%  entries can be added through the dictionary too.
%  \meta{type} should be one of \texttt{URI}, \texttt{GoToR},
%  \texttt{Launch}, \texttt{GoTo} or \texttt{Named}. The |GoTo| variant does
%  \emph{not} complain if the destination name is not known like
%  \cs{pdfannot_link_goto_begin:nw}.
%  The attributes stored in the local dictionary
%  \texttt{link/}\meta{type} are inserted as
%  \emph{attr spec} before \meta{user action spec}.
%  The code in the begin and end hook
%  \texttt{pdfannot/link/\meta{type}/before}
%  and \texttt{pdfannot/link/\meta{type}/after}
%  is executed  before and after the link (outside the link command)
%  while \texttt{pdfannot/link/\meta{type}/begin}
%  and \texttt{pdfannot/link/\meta{type}/end} are directly around the link
%  text. None of the hooks introduce a group.
%  \meta{type} should normally be identical to the value of the |/S| key
%  in the action dictionary.
%  As example either with a direct action
%  \begin{verbatim}
%  \pdfannot_link:nnn { URI }
%     {
%       /A<<
%         /Type/Action
%         /S/URI
%         /URI(https://www.latex-project.org)
%       >>
%     }
%    { link text}
%  \end{verbatim}
%  Or through  a dictionary:
%  \begin{verbatim}
%    \pdfdict_new:n   {l_my_action_dict}
%    \pdfdict_put:nnn {l_my_action_dict}{Type}{/Action}
%    \pdfdict_put:nnn {l_my_action_dict}{S}{/URI}
%    \pdfdict_put:nnn {l_my_action_dict}{URI}{(https://www.latex-project.org)}
%
%    \pdfannot_dict_put:nnn
%      {link/URI} { C } {[1~0~0]} %red border
%
%    \pdfannot_link:nen { URI }
%     {
%       /A <<\pdfdict_use:n{l_my_action_dict}>>
%     }
%     { link text }
%    \end{verbatim}
%
% Or if you want to exclude the possibility of a duplicated /A entry
% (if the action is already in the link/GoTo dictionary e.g. if you can expect
% other packages to add a dictionary). An alternative is to ensure that
% no /A is there by removing it explicitly.
%
%  \begin{verbatim}
%    \pdfdict_new:n   {l_my_action_dict}
%    \pdfdict_put:nnn {l_my_action_dict}{Type}{/Action}
%    \pdfdict_put:nnn {l_my_action_dict}{S}{/URI}
%    \pdfdict_put:nnn {l_my_action_dict}{URI}{(https://www.latex-project.org)}
%
%
%    \pdfannot_dict_put:nnn
%      {link/URI} { C } {[1~0~0]} %red border
%
%    \group_begin:
%    \pdfannot_dict_put:nne {link/GoTo}{A}{<<\pdfdict_use:n{l_my_action_dict}>>}
%    \pdfannot_link:nnn { URI }{}{ link text }
%    \group_end:
%    \end{verbatim}
%
%
% \end{function}
% \begin{function}[updated = 2020-12-06]{ \pdfannot_link_begin:nnw, \pdfannot_link_end:n }
%   \begin{syntax}
%     \cs{pdfannot_link_begin:nnw} \Arg{type} \Arg{user action spec} \meta{content}
%     \cs{pdfannot_link_end:n} \Arg{type}
%   \end{syntax}
%  This creates a link like the previous command.
%  \texttt{/Subtype/Link} is added automatically through the dictionary.
%  \meta{user action spec}\footnote{The wording follows the pdftex documentation}.
%  is provided as a fast method to add dictionary contents,
%  but it should be noted that no provision is taken to avoid clashes with
%  values added through the dictionary. If needed clashing entries should be
%  removed from the dictionary first. Normally the argument is not needed, all
%  entries can be added through the dictionary too.
%  \texttt{/Subtype/Link} is added automatically.
%  In contrast to \cs{pdfannot_link:nnn} this function
%  does not absorb the argument when finding the \meta{content}, and so can
%  be used in circumstances where the \meta{content} may not be a simple
%  argument. But beside this, it works similar and use the same hooks.
%  As example
%  \begin{verbatim}
%    \pdfannot_link_begin:nnw { URI }
%     {
%       /A<<
%         /Type/Action
%         /S/URI
%         /URI(https://www.latex-project.org)
%       >>
%     }
%     link text
%    \pdfannot_link_end:n { URI }
%    \end{verbatim}
% \end{function}
% \begin{function}[updated = 2020-12-06]{ \pdfannot_link_goto_begin:nw, \pdfannot_link_goto_end: }
%   \begin{syntax}
%     \cs{pdfannot_link_goto_begin:nw} \Arg{destination} \meta{content}
%     \cs{pdfannot_link_goto_end:}
%   \end{syntax}
% This is a special, shorter version for links to internal destinations. It always
% uses the hooks and dictionary of the |GoTo| link type. \meta{destination} is a
% destination name. In difference to |\pdfannot_link:nnn { GoTo }| it will complain if
% \meta{destination} is an unknown destination and give the message
%
% |name{ZZZZ} has been referenced but does not exist, replaced by a fixed one|
%
% \end{function}
% \begin{function}[added = 2021-02-14]{  \pdfannot_link_ref_last: }
%   This retrieves the object reference a link created previously with the commands
%   above. This doesn't work currently with xelatex but a feature request has
%   been made. see https://tug.org/pipermail/dvipdfmx/2020-December/000134.html
% \end{function}
% \begin{function}[added = 2021-02-14]{  \pdfannot_ref_last: }
%   This retrieves the object reference a previously annotation
%   created either with a link or a general box command. When the last was a link
%   it won't work with xelatex.
%   see https://tug.org/pipermail/dvipdfmx/2020-December/000134.html
% \end{function}
% \begin{NOTE}{UF}
% only annot link or also annot?
% \end{NOTE}
% \begin{function}[added = 2020-03-12]{  \pdfannot_link_margin:n }
%  \begin{syntax}
%    \cs{pdfannot_link_margin:n} \Arg{dimen}
%  \end{syntax}
%   This sets the dimension of the link margin.
% \end{function}
%
% \begin{function}[added=2021-08-19]{\pdfannot_link_off:,\pdfannot_link_on:}
% In most engines links can broken over lines and pages. The backends then create
% intermediate link objects to catch all the content between the start and end of
% the links, mostly based on some heuristics using the boxlevel. This can
% lead to the unpleasant result that header and footer are part of the link too.
% Since texlive 2021 pdflatex and lualatex has commands similar to a special already
% included in dvipdfmx which allows to interrupt a link. The commands must be used
% with care: typically they must be outside a box that would be caught by link to
% have the wanted effect.
%
% \end{function}
% \begin{function}[added = 2020-12-04]{ \pdfannot_dict_put:nnn }
%  \begin{syntax}
%    \cs{pdfannot_dict_put:nnn} \Arg{dictionary name} \Arg{key} \Arg{value}
%  \end{syntax}
%   This adds (locally) a key-value to the internal annot dictionaries used
%   by the link commands above.
%   \meta{dictionary name} should be currently one of \texttt{link/URI},
%   \texttt{link/URI},\texttt{link/GoToR}, \texttt{link/Launch},
%   \texttt{link/GoTo}, \texttt{link/Named}.
% \end{function}
% \begin{function}[added = 2020-12-04]{ \pdfannot_dict_remove:nn }
%  \begin{syntax}
%    \cs{pdfannot_dict_remove:nn} \Arg{dictionary name} \Arg{key}
%  \end{syntax}
%   This removes a key-value from the internal annot dictionary
%   \meta{dictionary name} should be currently one of
%   \texttt{link/URI}, \texttt{link/GoToR}, \texttt{link/Launch},
%   \texttt{link/GoTo}, \texttt{link/Named}.
% \end{function}
% \begin{function}[added = 2020-12-04]{ \pdfannot_dict_show:n }
%  \begin{syntax}
%    \cs{pdfannot_dict_show:n} \Arg{dictionary name}
%  \end{syntax}
%   This shows the content of the internal annot dictionary.
%  \meta{dictionary name} should be currently one of \texttt{link/URI},
%   \texttt{link/URI}, \texttt{link/GoToR}, \texttt{link/Launch},
%   \texttt{link/GoTo}, \texttt{link/Named}.
% \end{function}
%
% \begin{function}[EXP,added = 2021-03-03]
%   { \pdfannot_dict_use:n  }
%   \begin{syntax}
%     \cs{pdfannot_dict_use:n} \Arg{dictionary name}
%   \end{syntax}
%   This outputs the property list of the dictionary as a list of
%   |/key value| pairs.
%   This can be used e.g. when writing a dictionary object with
%   \cs{pdf_object_write:nne}
% \end{function}
%
% \begin{variable}[added = 2020-12-28]{\l_pdfannot_F_bitset}
%  This is a bitset variable, with the named index names suitable for the
%  /F flag in an annotation.
%  It can be used for example like this:
%  \begin{verbatim}
%  \bitset_set_true:Nn \l_pdfannot_F_bitset {Print}
%  \pdfannot_dict_put:nne {link/URI} {F}
%     { \bitset_to_arabic:N \l_pdfannot_F_bitset }
%  \end{verbatim}
%  The known keys for the bitset are |Invisible|, |Hidden|,
%  |Print|, |NoZoom|, |NoRotate|, |NoView|, |ReadOnly|, |Locked|,  |ToggleNoView|,
%  |LockedContents| which correspond to the names used in the PDF references.
% \end{variable}
% \subsection{Widget annotations}
% Widget annotations are quite important for form fields, as they are used
% to build the actually instance of such fields.
%
% As they can contain meaningful content hooks are probably needed to allow tagging
% and other manipulations, so like with link special commands are provided.
% Widget are normally in a box and line and page breaks are not relevant, so
% the command is offered as box command.
%
% \begin{function}[added = 2021-03-02]
%   { \pdfannot_widget_box:nnn }
%   \begin{syntax}
%     \cs{pdfannot_widget_box:nnn} \Arg{width} \Arg{height} \Arg{depth}
%   \end{syntax}
%   This creates an \texttt{/Type/Annot} object with the given dimensions.
%   The annotation doesn't occupy space.
%   It will insert the attribute dictionary of the widget type (which
%   is prefilled with  \texttt{/Subtype/Widget}).
%   The hooks \texttt{pdfannot/widget/before} and \texttt{pdfannot/widget/after}
%   are executed before and after the widget.
%   The widget has four subdirectories, |widget/AA|, |widget/AP|, |widget/MK| and
%   |widget/BS|
%   which can be filled with \cs{pdfannot_dict_put:nnn} and will be used if not
%   empty.
%
% \end{function}
% \end{documentation}
%
% \begin{implementation}
%
% \section{\pkg{l3pdfannot} implementation}
%
%    \begin{macrocode}
%<@@=pdfannot>
%<*header>
\ProvidesExplPackage{l3pdfannot}{2026-01-23}{0.96y}
  {PDF-annotations}
\RequirePackage{l3pdfdict}
%</header>
%    \end{macrocode}
% Annotations have a /F flag, we provide a public
% bitset for it.
%    \begin{macrocode}
%<*package>
\cs_if_exist:NF \bitset_new:Nn
  { \RequirePackage { l3bitset } }
\bitset_new:Nn \l_pdfannot_F_bitset
  {
    Invisible      = 1,
    Hidden         = 2,
    Print          = 3,
    NoZoom         = 4,
    NoRotate       = 5,
    NoView         = 6,
    ReadOnly       = 7,
    Locked         = 8,
    ToggleNoView   = 9,
    LockedContents = 10
  }
%    \end{macrocode}
% \begin{NOTE}{UF}
% The code/naming tries to unify general annotations and the special type of
% link under a common name.
% regarding naming and relation of annotation commands see
% https://github.com/FrankMittelbach/AccessiblePDF/issues/73
% \subsection{Annotations / backend}
% The backend commands are in l3backend:
% \cs{__pdf_backend_annotation:nnnn} and \cs{__pdf_backend_annotation_last:}
% \cs{__pdfannot_backend_link_begin_user:nnw}, etc
% \end{NOTE}
%
% \subsection{ General Annotations }
% \begin{variable}
%  { \g_@@_use_lastlink_bool }
% The pdf engines have two different primitive commands to refer to the last created
% annotation: one for links, one for boxed annotation. We use a boolean to decide
% which one should be used, so that only one user command is needed.
%    \begin{macrocode}
\bool_new:N \g_@@_use_lastlink_bool
%    \end{macrocode}
% \end{variable}
% \begin{NOTE}{UF}
%  type or not type? Syntax for type?
%  should there be a version without type?
% \end{NOTE}
% \begin{macro}{\pdfannot_box:nnnn,\pdfannot_box:nnne,\pdfannot_box_ref_last:}
%    \begin{macrocode}
\cs_new_protected:Npn \pdfannot_box:nnnn #1 #2 #3 #4
  {
    \__pdf_backend_annotation:nnnn {#1}{#2}{#3}{#4}
    \bool_gset_false:N\g_@@_use_lastlink_bool
  }
\cs_generate_variant:Nn \pdfannot_box:nnnn {nnne,nnnx}
\cs_new:Npn \pdfannot_box_ref_last:
  {
    \__pdf_backend_annotation_last:
  }

%    \end{macrocode}
% \end{macro}
% \subsection{Annotations, subtype Widget}\label{pdf:annot:widget}
% Widgets are typically boxes, so we provide a box command.
% A local dictionary \texttt{l_@@/Widget} is used.
% It contains like the other dictionaries
% the subtype setting (the /Type is added by the backend).
%    \begin{macrocode}
 \pdfdict_new:n   { l_@@/widget }
 \pdfdict_new:n   { l_@@/widget/AA }
 \pdfdict_new:n   { l_@@/widget/AP }
 \pdfdict_new:n   { l_@@/widget/MK }
 \pdfdict_new:n   { l_@@/widget/BS }
 \pdfdict_put:nnn { l_@@/widget }{ Subtype }{ /Widget }
 \hook_new_pair:nn
   {pdfannot/widget/before}
   {pdfannot/widget/after}
\cs_new_protected:Npn \pdfannot_widget_box:nnn #1 #2 #3
  {
    \hook_use:n { pdfannot/widget/before }
    \group_begin:
    \pdfmeta_standard_verify:nT
      {annot_widget_no_AA}
      {
        \pdfdict_if_empty:nF { l_@@/widget/AA }
          {
            \pdf_object_unnamed_write:ne {dict}{\pdfdict_use:n{l_@@/widget/AA}}
            \pdfdict_put:nne { l_@@/widget }
              {AA}
              {\pdf_object_ref_last:}
          }
      }
    \pdfdict_if_empty:nF { l_@@/widget/AP }
      {
        \pdf_object_unnamed_write:ne {dict}{\pdfdict_use:n{l_@@/widget/AP}}
        \pdfdict_put:nne { l_@@/widget }
             {AP}
             {\pdf_object_ref_last:}
      }
    \pdfdict_if_empty:nF { l_@@/widget/MK }
      {
        \pdf_object_unnamed_write:ne {dict}{\pdfdict_use:n{l_@@/widget/MK}}
        \pdfdict_put:nne { l_@@/widget }
             {MK}
             {\pdf_object_ref_last:}
      }
    \pdfdict_if_empty:nF { l_@@/widget/BS }
      {
        \pdf_object_unnamed_write:ne {dict}{\pdfdict_use:n{l_@@/widget/BS}}
        \pdfdict_put:nne { l_@@/widget }
             {BS}
             {\pdf_object_ref_last:}
      }
    \pdfannot_box:nnne {#1}{#2}{#3}
      {
        \pdfdict_use:n { l_@@/widget}
      }
    \hook_use:n { pdfannot/widget/end }
    \group_end:
    \bool_gset_false:N\g_@@_use_lastlink_bool
  }
%    \end{macrocode}
%
% \subsection{Annotations, subtype Link}\label{sec:links}
% The code assumes that there will be different link types
% (currently URI, GoToR, Launch, GoTo, Named, hyperref uses the names
% url,file,run,link,menu) and that links of the same type share
% the \emph{attr spec} and also the same begin/end
% code. The list of link types need to stay restricted and well documented so that
% all packages know which types they have to handle. It is stored in a constant
% seq.
% \begin{NOTE}{UF}
% Perhaps a |cite| type will be useful at some time. -- Thinking more about it,
% a |cite| type is not sensible. hyperref supports it, but it doesn't fit in.
% Commands like cite, gls, acro, footnote and so on should locally change
% linkcolor and linkbordercolor.
% Probably we will need some commands to add an attribute to all link types
% at once.
% hyperref commands for the various type:
% url  |\hyper@linkurl|,
% file |\hyper@linkfile|,
% run  |\@hyper@launch run|,
% link |\hyper@link|, |\find@pdflink|
% menu |\Acrobatmenu|
% \end{NOTE}
% \begin{variable}[added = 2020-03-12]{ \c_pdfannot_link_types_seq }
% This constant sequence contains the list of currently supported link types
% for which hooks and dictionaries exist.
% \end{variable}
%
% \begin{variable}
%   {
%     link/TYPE,
%     pdfannot/link/TYPE/before,
%     pdfannot/link/TYPE/begin,
%     pdfannot/link/TYPE/end,
%     pdfannot/link/TYPE/after
%   }
% These setup the dictionary and the hook pairs.
%    \begin{macrocode}
\seq_const_from_clist:Nn \c_pdfannot_link_types_seq { URI , GoToR , Launch , GoTo, Named }
\seq_map_inline:Nn \c_pdfannot_link_types_seq
  {
    \pdfdict_new:n { l_@@/link/#1 }
    \pdfdict_put:nnn { l_@@/link/#1 }{ Subtype }{ /Link }
    \hook_new_pair:nn
      {pdfannot/link/#1/before}
      {pdfannot/link/#1/after}
    \hook_new_pair:nn
      {pdfannot/link/#1/begin}
      {pdfannot/link/#1/end}
   }
%    \end{macrocode}
% \end{variable}
%
% \subsection{Interruption of links}
%    \begin{macrocode}
\cs_if_free:NT \pdfannot_link_off:
 {
  \cs_new_protected:Nn \pdfannot_link_off: { \__pdfannot_backend_link_off: }
  \cs_new_protected:Nn \pdfannot_link_on:  { \__pdfannot_backend_link_on: }
 } 
%    \end{macrocode}
%
%
% \subsubsection{Annotations, subtype Link /management}
%
% \begin{macro}{\pdfannot_link:nnn,\pdfannot_link:nen}
%    \begin{macrocode}
\cs_new_protected:Nn \pdfannot_link:nnn %#1 type (URI, GoTo etc),
                                        %#2 action spec, #3 link text
  {
    \hook_use:n { pdfannot/link/#1/before}
    \mode_leave_vertical:
    \exp_args:Nee %xetex needs expansion
    \__pdfannot_backend_link_begin_user:nnw
      {
         \pdfdict_if_exist:nT { l_@@/link/#1 }
          {
            \pdfdict_use:n { l_@@/link/#1}
          }
      }
      {
        #2 %exp_not?
      }
    \bool_gset_true:N \g_@@_use_lastlink_bool
    \hook_use:n { pdfannot/link/#1/begin}
    #3
    \hook_use:n { pdfannot/link/#1/end}
    \__pdfannot_backend_link_end:
    \bool_gset_true:N \g_@@_use_lastlink_bool
    \hook_use:n { pdfannot/link/#1/after}
  }
\cs_generate_variant:Nn \pdfannot_link:nnn {nen,nxn}
%    \end{macrocode}
% \end{macro}
% \begin{macro}{
%   \pdfannot_link_begin:nnw,
%   \pdfannot_link_begin:new,
%   \pdfannot_link_end:n }
%    \begin{macrocode}
\cs_new_protected:Npn \pdfannot_link_begin:nnw #1 #2 %#1 type, #2 action spec
  {
    \hook_use:n { pdfannot/link/#1/before}
    \mode_leave_vertical:
    \exp_args:Nee %xetex needs expansion
      \__pdfannot_backend_link_begin_user:nnw
        {
           \pdfdict_if_exist:nT { l_@@/link/#1 }
            {
              \pdfdict_use:n { l_@@/link/#1}
            }
        }
        { #2 }
      \bool_gset_true:N \g_@@_use_lastlink_bool
      \hook_use:n { pdfannot/link/#1/begin}
  }

\cs_new_protected:Nn \pdfannot_link_end:n %#1 type, e.g. url
  {
    \hook_use:n { pdfannot/link/#1/end}
    \__pdfannot_backend_link_end:
    \bool_gset_true:N \g_@@_use_lastlink_bool
    \hook_use:n { pdfannot/link/#1/after}
  }
\cs_generate_variant:Nn \pdfannot_link_begin:nnw {new,nxw}
%    \end{macrocode}
% \end{macro}
% \begin{macro}{\pdfannot_link_goto_begin:nw, \pdfannot_link_goto_end:}
%     \begin{macrocode}
\cs_new_protected:Npn \pdfannot_link_goto_begin:nw #1 %#1 destination
  {
    \pdfdict_remove:nn { l_@@/link/GoTo} {Subtype}
    \hook_use:n { pdfannot/link/GoTo/before} %the backend add it too
    \mode_leave_vertical:
    \exp_args:Nee %xetex needs expansion
    \__pdfannot_backend_link_begin_goto:nnw
      {
        \pdfdict_use:n { l_@@/link/GoTo}
      }
      { #1 }
     \bool_gset_true:N \g_@@_use_lastlink_bool
    \pdfdict_put:nnn { l_@@/link/GoTo} {Subtype}{GoTo}
     \hook_use:n { pdfannot/link/GoTo/begin}
  }

\cs_new_protected:Nn \pdfannot_link_goto_end:
  {
    \hook_use:n { pdfannot/link/GoTo/end}
    \__pdfannot_backend_link_end:
    \bool_gset_true:N \g_@@_use_lastlink_bool
     \hook_use:n { pdfannot/link/GoTo/after}
  }
%    \end{macrocode}
% \end{macro}
% \begin{macro}[EXP]{\pdfannot_link_ref_last:, \pdfannot_ref_last:}
%    \begin{macrocode}
\cs_new:Nn \pdfannot_link_ref_last: { \__pdfannot_backend_link_last: }
%    \end{macrocode}
%    \begin{macrocode}
\cs_new:Npn \pdfannot_ref_last:
  {
    \bool_if:NTF \g_@@_use_lastlink_bool
      {
        \__pdfannot_backend_link_last:
      }
      {
        \__pdf_backend_annotation_last:
      }
  }
%    \end{macrocode}
% \end{macro}
% \begin{macro}{ \pdfannot_link_margin:n}
%    \begin{macrocode}
\cs_new_protected:Npn \pdfannot_link_margin:n #1
  {
    \__pdfannot_backend_link_margin:n { #1 }
  }
%    \end{macrocode}
% \end{macro}
% \begin{macro}
%   {
%     \pdfannot_dict_put:nnn,
%     \pdfannot_dict_put:nne,
%     \pdfannot_dict_remove:nn,
%     \pdfannot_dict_show:n
%     \pdfannot_dict_use:n
%   }
%    \begin{macrocode}
\cs_new_protected:Npn \pdfannot_dict_put:nnn #1 #2 #3
  {
    \pdfdict_put:nnn { l_@@/#1 } { #2 }{ #3 }
  }
\cs_generate_variant:Nn \pdfannot_dict_put:nnn {nne,nnx}
%    \end{macrocode}
%    \begin{macrocode}
\cs_new_protected:Npn \pdfannot_dict_remove:nn #1 #2
  {
    \pdfdict_remove:nn { l_@@/#1 } { #2 }
  }
%    \end{macrocode}
%    \begin{macrocode}
\cs_new_protected:Npn \pdfannot_dict_show:n #1
  {
    \pdfdict_show:n { l_@@/#1 }
  }

\cs_new:Npn \pdfannot_dict_use:n #1
  {
    \pdfdict_use:n { l_@@/#1 }
  }
%</package>
%    \end{macrocode}
% \end{macro}
% \end{implementation}
%
% \PrintIndex
