% \iffalse meta-comment
%
%% File: tagpdf-user.dtx
%
% Copyright (C) 2019-2024 Ulrike Fischer
%
% 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
%
%    https://www.latex-project.org/lppl.txt
%
% This file is part of the "tagpdf 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/tagpdf
%
% for those people who are interested.
%<*driver>
\DocumentMetadata{}
\documentclass{l3doc}
\usepackage{array,booktabs,caption}
\hypersetup{pdfauthor=Ulrike Fischer,
 pdftitle=tagpdf-user module (tagpdf)}
\begin{document}
  \DocInput{\jobname.dtx}
\end{document}
%</driver>
% \fi
% \title{^^A
%   The \pkg{tagpdf-user} module\\ Code related to \LaTeX2e user commands and document commands   ^^A
%   \\ Part of the tagpdf package
% }
%
% \author{^^A
%  Ulrike Fischer\thanks
%    {^^A
%      E-mail:
%        \href{mailto:fischer@troubleshooting-tex.de}
%          {fischer@troubleshooting-tex.de}^^A
%    }^^A
% }
%
% \date{Version 0.98v, released 2024-02-04}
% \maketitle
% \begin{documentation}
% \section{Setup commands}
% \begin{function}{\tagpdfsetup}
% \begin{syntax}
% \cs{tagpdfsetup}\Arg{key val list}
% \end{syntax}
% This is the main setup command to adapt the behaviour of tagpdf.
% It can be used in the preamble and in the document (but not all keys make sense there).
% \end{function}
%
% \begin{function}{activate (setup-key)}
% And additional setup key which combine the other activate keys
% |activate-mc|, |activate-tree|, |activate-struct| and additionally
% add a document structure.
% \end{function}
%
% \begin{function}{\tag_tool:n,\tagtool}
% \begin{syntax}
% \cs{tag_tool:n}\Arg{key val}
% \end{syntax}
% The tagging of basic document elements will require a variety of small commands
% to configure and adapt the tagging. This command will collect them under a command
% interface. The argument is \emph{one} key-value like string. This is work in progress
% and both syntax, known arguments and implementation can change!
% \end{function}
%
% \section{Commands related to mc-chunks}
% \begin{function}{\tagmcbegin, \tagmcend,\tagmcuse}
% \begin{syntax}
% \cs{tagmcbegin} \Arg{key-val}\\
% \cs{tagmcend}\\
% \cs{tagmcuse}\Arg{label}
% \end{syntax}
% These are wrappers around |\tag_mc_begin:n|, |\tag_mc_end:| and |\tag_mc_use:n|.
% The commands and their argument are documentated in the \pkg{tagpdf-mc} module.
% In difference to the expl3 commands, \cs{tagmcbegin} issues also an \cs{ignorespaces},
% and \cs{tagmcend} will issue in horizontal mode an \cs{unskip}.
% \end{function}
%
% \begin{function}{\tagmcifinTF}
% \begin{syntax}
% \cs{tagmcifin} \Arg{true code}\Arg{false code}
% \end{syntax}
% This is a wrapper around |\tag_mc_if_in:TF|.
% and tests if an mc is open or not. It is mostly of
% importance for pdflatex as lualatex doesn't mind much if a mc tag is not
% correctly closed. Unlike the expl3 command it is not expandable.
%
% The command is probably not of much use and will perhaps disappear in future
% versions. It normally makes more sense to push/pop an mc-chunk.
% \end{function}
%
% \section{Commands related to structures}
% \begin{function}{\tagstructbegin, \tagstructend,\tagstructuse}
% \begin{syntax}
% \cs{tagstructbegin} \Arg{key-val}\\
% \cs{tagstructend}\\
% \cs{tagstructuse}\Arg{label}
% \end{syntax}
% These are direct wrappers around |\tag_struct_begin:n|,
% |\tag_struct_end:| and |\tag_struct_use:n|.
% The commands and their argument are documentated in the \pkg{tagpdf-struct} module.
% \end{function}



% \section{Debugging}
% \begin{function}{\ShowTagging}
%   \begin{syntax}
%   \cs{ShowTagging} \Arg{key-val}
%   \end{syntax}
% This is a generic function to output various debugging helps. It not
% necessarily stops the compilation. The keys and their function are described below.
% \end{function}
%
% \begin{function}{mc-data (show-key)}
%  \begin{syntax}
%    |mc-data| = \meta{number}
%  \end{syntax}
% This key is (currently?) relevant for lua mode only.
% It shows the data of all mc-chunks created so far.
% It is accurate only after shipout (and perhaps a second compilation),
% so typically should be issued after a
% newpage. The value is a positive integer and sets the first mc-shown. If no value
% is given, 1 is used and so all mc-chunks created so far are shown.
% \end{function}
% \begin{function}{mc-current (show-key)}
%  \begin{syntax}
%    |mc-current|
%  \end{syntax}
% This key shows the number and the tag of the currently open mc-chunk. If no
% chunk is open it shows only the state of the abs count. It works in all mode,
% but the output in luamode looks different.
% \end{function}
% \begin{function}{mc-marks (show-key)}
%  \begin{syntax}
%    |mc-marks| = |show|\verb+|+|use|
%  \end{syntax}
% This key helps to debug the page marks. It should only be used at shipout in
% header or footer.
% \end{function}
% \begin{function}{struct-stack (show-key)}
%  \begin{syntax}
%    |struct-stack| = |log|\verb+|+|show|
%  \end{syntax}
% This key shows the current structure stack. With |log| the info is only
% written to the log-file, |show| stops the compilation and shows on the terminal.
% If no value is used, then the default is |show|.
% \end{function}
%
% \begin{function}{debug/structures (show-key)}
%  \begin{syntax}
%    |debug/structures| = \meta{structure number}
%  \end{syntax}
%  This key is available only if the tagpdf-debug package is loaded
%  and shows all structures starting with the one with the number 
%  given by the key.
% \end{function}

% \section{Extension commands}
% The following commands and code parts are not core commands of tagpdf.
% They either provide work-arounds for missing functionality elsewhere,
% or do a first step to apply tagpdf commands to document commands.
%
% The commands and keys should be view as experimental!
%
% This part will be regularly revisited to check if the code should go to a
% better place or can be improved and so can change easily.
%
% \subsection{Fake space}
% \begin{function}{\pdffakespace}
% (lua-only) This provides a lua-version of the |\pdffakespace| primitive of
% pdftex.
% \end{function}
%
% \subsection{Paratagging}
%
% This is a first try to make use of the new paragraph hooks in a current LaTeX to
% automate the tagging of paragraph. It requires sane paragraph nesting,
% faulty code, e.g. a missing |\par| at the end of a low-level vbox can highly
% confuse the tagging. The tags should be carefully checked if this is used.
%
% \begin{function}{paratagging (setup-key),paratagging-show (setup-key)}
%  \begin{syntax}
%    |paratagging| = |true|\verb+|+|false|\\
%    |paratagging-show| = |true|\verb+|+|false|\\
%  \end{syntax}
% This keys can be used in |\tagpdfsetup| and enable/disable paratagging.
% |paratagging-show| puts small red numbers at the begin and end of a paragraph.
% This is meant as a debugging help. The number are boxes and have a (tiny) height,
% so they can affect typesetting.
% \end{function}
%
% \begin{function}{\tagpdfparaOn,\tagpdfparaOff}
% These commands allow to enable/disable para tagging too and are a bit
% faster then |\tagpdfsetup|. But I'm not sure if the names are good.
% \end{function}
%
% \begin{function}{\tagpdfsuppressmarks}
%  This command allows to suppress the creation of the marks. It takes an argument
%  which should normally be one of the mc-commands, puts a group around it and
%  suppress the marks creation in this group. This command should be used if
%  the begin and end command are at different boxing levels. E.g.
%  \begin{verbatim}
%  \@hangfrom
%   {
%    \tagstructbegin{tag=H1}%
%    \tagmcbegin    {tag=H1}%
%    #2
%   }
%   {#3\tagpdfsuppressmarks{\tagmcend}\tagstructend}%
%  \end{verbatim}
% \end{function}
%
% \subsection{Header and footer}
% Header and footer are automatically excluded from tagging. This can
% be disabled with the following key.
% If some real content is in the header and
% footer, tagging must be restarted there explicitly.
% The key accepts the values |true| which surrounds the header with an artifact
% mc-chunk, |false| which disables the automatic tagging, and |pagination| which
% additionally adds an artifact structure with an pagination attribute.
%
% \begin{function}{exclude-header-footer (setup-key)}
%  \begin{syntax}
%    |exclude-header-footer| = |true|\verb+|+|false|\verb+|+pagination
%  \end{syntax}%
% \end{function}

% \subsection{Link tagging}
% Links need a special structure and cross reference system.
% This is added through hooks of the l3pdfannot module and will work
% automatically if tagging is activated.
%
% Links should (probably) have an alternative text in the Contents
% key. It is unclear which text this should be and
% how to get it. Currently the code simply adds the fix texts |url| and |ref|.
% Another text can be added by changing the dictionary value:
% \begin{verbatim}
% \pdfannot_dict_put:nnn
% { link/GoTo }
% { Contents }
% { (ref) }
% \end{verbatim}
% 
% \section{Socket support}
% 
% \begin{function}{\tag_socket_use:n,\tag_socket_use:nn,\UseTaggingSocket}
% \begin{syntax}
%  \cs{tag_socket_use:n} \Arg{socket name}\\
%  \cs{tag_socket_use:nn} \Arg{socket name} \Arg{socket argument}\\
%  \cs{UseTaggingSocket} \Arg{socket name} \\
%  \cs{UseTaggingSocket} \Arg{socket name} \Arg{socket argument}\\
% \end{syntax}
% \end{function}

% The next \LaTeX{} will use special sockets for the tagging.
% 
% These sockets will use names starting
% with \texttt{tagsupport/}. Usually, these sockets have exactly two
% plugs defined: \texttt{noop} (when no tagging is requested or 
% tagging is not wanted for some reason) and 
% a second plug that enables the tagging. There
% may be more, e.g., tagging with special debugging, etc., but right
% now it is usually just on or off.
%
% Given that we sometimes have to suspend tagging, it would be fairly
% inefficient to put different plugs into these sockets whenever that
% happens. We therefore offer \cs{UseTaggingSocket} which is like
%  \cs{UseSocket} except that the socket name is specified without
%  \texttt{tagsupport/}, i.e.,
% \begin{quote}
%   \verb=\UseTaggingSocket{foo}=      $\to$
%   \verb=\UseSocket{tagsupport/foo}=
% \end{quote}
%  Beside being slightly shorter, the big advantage is that this way
%  we can change \cs{UseTaggingSocket} to do nothing by switching a boolean
%  instead of changing the plugs of the tagging support sockets back and forth.
%
%  It is possible to use the tagging support sockets with
%  \cs{UseSocket} directly, but in this case the socket remains active
%  if e.g. \cs{SuspendTagging} is in force. There may be reasons for doing
%  that but in general we expect to always use \cs{UseTaggingSocket}.
%
%  The L3 programming layer versions \cs{tag_socket_use:n} and
%  \cs{tag_socket_use:nn} are slightly more efficient than
%  \cs{UseTaggingSocket} because they do not have to determine how
%  many arguments the socket takes when disabling it.
% \end{documentation}
%
% \begin{implementation}
% \section{User commands and extensions of document commands}
%    \begin{macrocode}
%<@@=tag>
%<*header>
\ProvidesExplPackage {tagpdf-user} {2024-02-04} {0.98v}
  {tagpdf - user commands}
%</header>
%    \end{macrocode}
% \section{Setup and preamble commands}
% \begin{macro}{\tagpdfsetup}
%    \begin{macrocode}
%<base>\NewDocumentCommand \tagpdfsetup { m }{}
%<*package>
\RenewDocumentCommand \tagpdfsetup { m }
  {
    \keys_set:nn { @@ / setup } { #1 }
  }
%</package>
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\tag_tool:n,\tagtool}
% This is a first definition of the tool command.
% Currently it uses key-val, but this should be probably
% be flattened to speed it up.
%    \begin{macrocode}
%<base>\cs_new_protected:Npn\tag_tool:n #1 {}
%<base>\cs_set_eq:NN\tagtool\tag_tool:n
%<*package>
\cs_set_protected:Npn\tag_tool:n #1 
  {
    \tag_if_active:T { \keys_set:nn {tag / tool}{#1} }  
  }
\cs_set_eq:NN\tagtool\tag_tool:n  
%</package>
%    \end{macrocode}
% \end{macro}

% \section{Commands for the mc-chunks}
% \begin{macro}{\tagmcbegin,\tagmcend,\tagmcuse  }
%    \begin{macrocode}
%<*base>
\NewDocumentCommand \tagmcbegin { m }
  {
    \tag_mc_begin:n {#1}
  }


\NewDocumentCommand \tagmcend {  }
  {
    \tag_mc_end:
  }

\NewDocumentCommand \tagmcuse { m }
  {
    \tag_mc_use:n {#1}
  }
%</base>
%    \end{macrocode}
% \end{macro}

% \begin{macro}{\tagmcifinTF}
% This is a wrapper around |\tag_mc_if_in:| and tests if an mc is open or not. It is mostly of
% importance for pdflatex as lualatex doesn't mind much if a mc tag is not
% correctly closed. Unlike the expl3 command it is not expandable.
%    \begin{macrocode}
%<*package>
\NewDocumentCommand \tagmcifinTF { m m }
  {
    \tag_mc_if_in:TF { #1 } { #2 }
  }
%</package>
%    \end{macrocode}
% \end{macro}
%
% \section{Commands for the structure}
% \begin{macro}{\tagstructbegin,\tagstructend,\tagstructuse  }
%
% These are structure related user commands. There are direct wrapper around the
% expl3 variants.
%    \begin{macrocode}
%<*base>
\NewDocumentCommand \tagstructbegin { m }
  {
    \tag_struct_begin:n {#1}
  }

\NewDocumentCommand \tagstructend {  }
  {
   \tag_struct_end:
  }

\NewDocumentCommand \tagstructuse { m }
  {
    \tag_struct_use:n {#1}
  }
%</base>
%    \end{macrocode}
% \end{macro}
%
% \section{Socket support}
% Until we can be sure that the kernel defines the commands we provide them before
% redefining them:
%    \begin{macrocode}
%<*base>
\providecommand\tag_socket_use:n[1]{}
\providecommand\tag_socket_use:nn[2]{}
\providecommand\UseTaggingSocket[1]{}
%</base>
%    \end{macrocode}
%
% \begin{macro}{\tag_socket_use:n,\tag_socket_use:nn,\UseTaggingSocket}
%    \begin{macrocode}
%<*package>
\cs_set_protected:Npn \tag_socket_use:n #1 
  {
    \bool_if:NT \l_@@_active_socket_bool
      { \UseSocket {tagsupport/#1} }
  }
%    \end{macrocode}
%
%    \begin{macrocode}
\cs_set_protected:Npn \tag_socket_use:nn #1#2 
  {
    \bool_if:NT \l_@@_active_socket_bool
       { \UseSocket {tagsupport/#1} {#2} }
  }
%    \end{macrocode}
%
%    \begin{macrocode}
\cs_set_protected:Npn \UseTaggingSocket #1 
  {
    \bool_if:NTF \l_@@_active_socket_bool
      { \UseSocket{tagsupport/#1} }
      {
        \int_case:nnF
            { \int_use:c { c__socket_tagsupport/#1_args_int } }
            {
              0 \prg_do_nothing:
              1 \use_none:n
              2 \use_none:nn
%    \end{macrocode}
%    We do not expect tagging sockets with more than one or two
%    arguments, so for now we only provide those.
%    \begin{macrocode}
            }
            \ERRORusetaggingsocket
      }
  }
%</package>  
%    \end{macrocode}
% \end{macro}
%
% \section{Debugging}
% \begin{macro}{\ShowTagging}
% This is a generic command for various show commands.
% It takes a keyval list, the various keys are implemented below.
%    \begin{macrocode}
%<*package>
\NewDocumentCommand\ShowTagging { m }
  {
    \keys_set:nn { @@ / show }{ #1}

  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{mc-data (show-key)}
% This key is (currently?) relevant for lua mode only.
% It shows the data of all mc-chunks created so far.
% It is accurate only after shipout, so typically should be issued after a
% newpage. With the optional argument the minimal number can be set.
%    \begin{macrocode}
\keys_define:nn { @@ / show }
  {
    mc-data .code:n =
      {
        \sys_if_engine_luatex:T
          {
            \lua_now:e{ltx.@@.trace.show_all_mc_data(#1,\@@_get_mc_abs_cnt:,0)}
          }
      }
    ,mc-data .default:n = 1
  }

%    \end{macrocode}
% \end{macro}
% \begin{macro}{mc-current (show-key)}
% This shows some info about the current mc-chunk. It works in generic and lua-mode.
%    \begin{macrocode}
\keys_define:nn { @@ / show }
  { mc-current .code:n =
     {
       \bool_if:NTF \g_@@_mode_lua_bool
         {
           \sys_if_engine_luatex:T
             {
               \int_compare:nNnTF
                 { -2147483647 }
                  =
                 {
                   \lua_now:e
                     {
                        tex.print
                         (tex.getattribute
                           (luatexbase.attributes.g_@@_mc_cnt_attr))
                     }
                 }
                 {
                   \lua_now:e
                     {
                       ltx.@@.trace.log
                        (
                          "mc-current:~no~MC~open,~current~abscnt
                           =\@@_get_mc_abs_cnt:"
                          ,0
                        )
                       texio.write_nl("")
                     }
                 }
                 {
                   \lua_now:e
                     {
                       ltx.@@.trace.log
                        (
                          "mc-current:~abscnt=\@@_get_mc_abs_cnt:=="
                           ..
                           tex.getattribute(luatexbase.attributes.g_@@_mc_cnt_attr)
                           ..
                           "~=>tag="
                           ..
                           tostring
                             (ltx.@@.func.get_tag_from
                               (tex.getattribute
                                 (luatexbase.attributes.g_@@_mc_type_attr)))
                           ..
                           "="
                           ..
                           tex.getattribute
                            (luatexbase.attributes.g_@@_mc_type_attr)
                           ,0
                        )
                       texio.write_nl("")
                     }
                 }
             }
         }
         {
          \msg_note:nn{ tag }{ mc-current }
         }
     }
  }
%    \end{macrocode}
% \end{macro}
% \begin{macro}{mc-marks (show-key)}
% It maps the mc-marks into the sequences and then shows them.
% This allows to inspect the first and last mc-Mark on a page.
% It should only be used in the shipout (header/footer).
%    \begin{macrocode}
\keys_define:nn { @@ / show }
  {
    mc-marks .choice: ,
    mc-marks / show .code:n =
      {
        \@@_mc_get_marks:
        \@@_check_if_mc_in_galley:TF
         {
          \iow_term:n {Marks~from~this~page:~}
         }
         {
           \iow_term:n {Marks~from~a~previous~page:~}
         }
        \seq_show:N \l_@@_mc_firstmarks_seq
        \seq_show:N \l_@@_mc_botmarks_seq
        \@@_check_if_mc_tmb_missing:T
         {
           \iow_term:n {BDC~missing~on~this~page!}
         }
        \@@_check_if_mc_tme_missing:T
         {
           \iow_term:n {EMC~missing~on~this~page!}
         }
      },
    mc-marks / use .code:n =
      {
        \@@_mc_get_marks:
        \@@_check_if_mc_in_galley:TF
         { Marks~from~this~page:~}
         { Marks~from~a~previous~page:~}
        \seq_use:Nn \l_@@_mc_firstmarks_seq {,~}\quad
        \seq_use:Nn \l_@@_mc_botmarks_seq {,~}\quad
        \@@_check_if_mc_tmb_missing:T
         {
           BDC~missing~
         }
        \@@_check_if_mc_tme_missing:T
         {
           EMC~missing
         }
      },
   mc-marks .default:n = show
  }
%    \end{macrocode}
% \end{macro}
% \begin{macro}{struct-stack (show-key)}
%    \begin{macrocode}
\keys_define:nn { @@ / show }
  {
     struct-stack .choice:
    ,struct-stack / log .code:n = \seq_log:N \g_@@_struct_tag_stack_seq
    ,struct-stack / show .code:n = \seq_show:N \g_@@_struct_tag_stack_seq
    ,struct-stack .default:n = show
  }
%</package>  
%    \end{macrocode}
% \end{macro}
% \begin{macro}{debug/structures (show-key)}
%  The following key is available only if the tagpdf-debug package is loaded
%  and shows all structures starting with the one with the number 
%  given by the key.
%    \begin{macrocode}
%<*debug>
\keys_define:nn { @@ / show }
  {
    ,debug/structures .code:n = 
      {
        \int_step_inline:nnn{#1}{\c@g_@@_struct_abs_int}
           {
            \msg_term:nneeee 
                   { tag/debug } { show-struct }
                   { ##1 }
                   { 
                     \prop_map_function:cN 
                       {g_@@_struct_debug_##1_prop} 
                       \msg_show_item_unbraced:nn 
                   }
                   { } { }
            \msg_term:nneeee  
                   { tag/debug } { show-kids }
                   {  ##1 }
                   { 
                     \seq_map_function:cN 
                       {g_@@_struct_debug_kids_##1_seq} 
                       \msg_show_item_unbraced:n
                   }
                   { } { }       
          }
      }    
    ,debug/structures .default:n = 0
  }
%</debug>  
%    \end{macrocode}
% \end{macro}
%
% \section{Commands to extend document commands}
% The following commands and code parts are not core commands of tagpdf.
% They either provide work-arounds for missing functionality elsewhere,
% or do a first step to apply tagpdf commands to document commands.
% This part should be regularly revisited to check if the code should go to a
% better place or can be improved.
% 
%    \begin{macrocode}
%<*package>
%    \end{macrocode}
% \subsection{Document structure}
% \begin{macro}{\g_@@_root_default_tl,activate (setup-key),activate-socket (setup-key)}
%    \begin{macrocode}
\tl_new:N\g_@@_root_default_tl
\tl_gset:Nn\g_@@_root_default_tl {Document}

\hook_gput_code:nnn{begindocument}{tagpdf}{\tagstructbegin{tag=\g_@@_root_default_tl}}
\hook_gput_code:nnn{tagpdf/finish/before}{tagpdf}{\tagstructend}

\keys_define:nn { @@ / setup}
 {  
   activate-socket .bool_set:N  = \l_@@_active_socket_bool, 
   activate  .code:n =
    {
      \keys_set:nn { @@ / setup }
        { activate-mc,activate-tree,activate-struct,activate-socket }
      \tl_gset:Nn\g_@@_root_default_tl {#1}  
    },
   activate .default:n = Document
 }
 
%    \end{macrocode}
% \end{macro}
% 
% \subsection{Structure destinations}
% Since TeXlive 2022 pdftex and luatex offer support for structure destinations
% and the pdfmanagement has backend support for. We activate them if
% structures are actually created.
% Structure destinations are actually PDF 2.0  only but they don't harm in 
% older PDF and can improve html export. 
%    \begin{macrocode}
\AddToHook{begindocument/before}
  {
    \bool_lazy_and:nnT
      { \g_@@_active_struct_dest_bool }
      { \g_@@_active_struct_bool }
      {
        \tl_set:Nn \l_pdf_current_structure_destination_tl 
           { _@@/struct/\g_@@_struct_stack_current_tl }
        \pdf_activate_structure_destination:
      }
   }
%    \end{macrocode}

% \subsection{Fake space}
% \begin{macro}{\pdffakespace}
% We need a luatex variant for |\pdffakespace|. This should probably go into
% the kernel at some time. We also provide a no-op version for dvi mode
%    \begin{macrocode}
\sys_if_engine_luatex:T
  {
    \NewDocumentCommand\pdffakespace { }
     {
       \@@_fakespace:
     }
  }
\providecommand\pdffakespace{}  
%    \end{macrocode}
% \end{macro}
%
% \subsection{Paratagging}
%  The following are some simple commands to enable/disable paratagging.
%  Probably one should add some checks if we are already in a paragraph.
%
%
%  \begin{macro}{
%   \l_@@_para_bool,
%   \l_@@_para_flattened_bool,
%   \l_@@_para_show_bool,
%   \g_@@_para_begin_int,
%   \g_@@_para_end_int,
%   \g_@@_para_main_begin_int,
%   \g_@@_para_main_end_int,
%   \g_@@_para_main_struct_tl,
%   \l_@@_para_tag_default_tl,
%   \l_@@_para_tag_tl,
%   \l_@@_para_main_tag_tl,
%   \l_@@_para_attr_class_tl,
%   \l_@@_para_main_attr_class_tl,
%   }
%  At first some variables.
%    \begin{macrocode}
%</package>
%<base>\bool_new:N \l_@@_para_flattened_bool
%<base>\bool_new:N \l_@@_para_bool
%<*package>
\int_new:N  \g_@@_para_begin_int
\int_new:N  \g_@@_para_end_int
\int_new:N  \g_@@_para_main_begin_int
\int_new:N  \g_@@_para_main_end_int
%    \end{macrocode}
% this will hold the structure number of the current text-unit.
%    \begin{macrocode}
\tl_new:N   \g_@@_para_main_struct_tl
\tl_new:N   \l_@@_para_tag_default_tl
\tl_set:Nn  \l_@@_para_tag_default_tl { text }
\tl_new:N   \l_@@_para_tag_tl
\tl_set:Nn  \l_@@_para_tag_tl { \l_@@_para_tag_default_tl }
\tl_new:N   \l_@@_para_main_tag_tl
\tl_set:Nn  \l_@@_para_main_tag_tl {text-unit}
%    \end{macrocode}
% this is perhaps already defined by the block code
%    \begin{macrocode}
\tl_if_exist:NF \l_@@_para_attr_class_tl
 {\tl_new:N \l_@@_para_attr_class_tl }
\tl_new:N \l_@@_para_main_attr_class_tl 
%    \end{macrocode}
% \end{macro}

% \begin{macro}
%   {
%   \@@_gincr_para_main_begin_int:,
%   \@@_gincr_para_main_end_int:,
%   \@@_gincr_para_begin_int:,
%   \@@_gincr_para_end_int:
%   }
% The global para counter should be set through commands so
% that \cs{tag_stop:} can stop them.  
%    \begin{macrocode}
\cs_new_protected:Npn \@@_gincr_para_main_begin_int:
 {
   \int_gincr:N \g_@@_para_main_begin_int
 }
\cs_new_protected:Npn \@@_gincr_para_begin_int:
 {
   \int_gincr:N \g_@@_para_begin_int
 }
\cs_new_protected:Npn \@@_gincr_para_main_end_int:
 {
   \int_gincr:N \g_@@_para_main_end_int
 }
\cs_new_protected:Npn \@@_gincr_para_end_int:
 {
   \int_gincr:N \g_@@_para_end_int
 }
%    \end{macrocode}
% \end{macro}
% \begin{macro}{\@@_start_para_ints:,\@@_stop_para_ints:}
%    \begin{macrocode}
\cs_new_protected:Npn \@@_start_para_ints:
 {
   \cs_set_protected:Npn \@@_gincr_para_main_begin_int:
     {
       \int_gincr:N \g_@@_para_main_begin_int
     }
   \cs_set_protected:Npn \@@_gincr_para_begin_int:
    {
      \int_gincr:N \g_@@_para_begin_int
    }
   \cs_set_protected:Npn \@@_gincr_para_main_end_int:
    {
      \int_gincr:N \g_@@_para_main_end_int
    }
   \cs_set_protected:Npn \@@_gincr_para_end_int:
    {
      \int_gincr:N \g_@@_para_end_int
    }  
 }
\cs_new_protected:Npn \@@_stop_para_ints:
 {
   \cs_set_eq:NN \@@_gincr_para_main_begin_int:\prg_do_nothing:
   \cs_set_eq:NN \@@_gincr_para_begin_int: \prg_do_nothing:
   \cs_set_eq:NN \@@_gincr_para_main_end_int: \prg_do_nothing:
   \cs_set_eq:NN \@@_gincr_para_end_int: \prg_do_nothing:
 } 
%    \end{macrocode}
% \end{macro}
%
% We want to be able to inspect the current para main structure, so 
% we need a command to store its structure number
% \begin{macro}{\@@_para_main_store_struct:}
%    \begin{macrocode}
\cs_new:Npn \@@_para_main_store_struct: 
  {
    \tl_gset:Ne \g_@@_para_main_struct_tl {\int_use:N \c@g_@@_struct_abs_int } 
  }
%    \end{macrocode}
% \end{macro}
% TEMPORARLY FIX (2023-11-17). Until latex-lab is updated we must adapt a sec command:
%    \begin{macrocode}
\AddToHook{package/latex-lab-testphase-sec/after}
 {
   \cs_set_protected:Npn \@kernel@tag@hangfrom #1
    {
     \tagstructbegin{tag=\l_@@_para_tag_tl}
     \@@_gincr_para_begin_int:
     \tagstructbegin{tag=Lbl}
     \setbox\@tempboxa
       \hbox
         {
           \bool_lazy_and:nnT
            {\tag_if_active_p:}
            {\g_@@_mode_lua_bool}
            {\tagmcbegin{tag=Lbl}}
           {#1}
         }
   \tag_stop:n{hangfrom}
   \hangindent \wd\@tempboxa\noindent
   \tag_start:n{hangfrom}
   \tagmcbegin{}\box\@tempboxa\tagmcend\tagstructend\tagmcbegin{}
   }
 } 
%    \end{macrocode}
% and one temporary adaptions for the block module:
%    \begin{macrocode}
\AddToHook{package/latex-lab-testphase-block/after}
 {
   \tl_if_exist:NT \l_tag_para_attr_class_tl
    {
      \tl_set:Nn \l_@@_para_attr_class_tl { \l_tag_para_attr_class_tl }
    }
} 
  
%    \end{macrocode}
%\begin{macro}
% {
%  paratagging (setup-key),
%  paratagging-show (setup-key),
%  paratag (setup-key),
%  paratag (tool-key),
%  unittag (tool-key),
%  para-flattened (tool-key),
%  }
% These keys enable/disable locally paratagging, and the debug modus.
% It can affect the typesetting if |paratagging-show| is used. The small numbers
% are boxes and they have a (small) height. The |paratag| key sets the tag used by
% the next automatic paratagging, it can also be changed with |\tag_tool:n|
%    \begin{macrocode}
\keys_define:nn { @@ / setup }
  {
    paratagging      .bool_set:N = \l_@@_para_bool,
    paratagging-show .bool_set:N = \l_@@_para_show_bool,
    paratag          .tl_set:N   = \l_@@_para_tag_tl
  }
\keys_define:nn { tag / tool} 
  {
    paratag .tl_set:N = \l_@@_para_tag_tl,
    unittag .tl_set:N = \l_@@_para_main_tag_tl,
    para-flattened .bool_set:N = \l_@@_para_flattened_bool
  }
%    \end{macrocode}
% \end{macro}
% Helper command for debugging: 
%    \begin{macrocode}
\cs_new_protected:Npn \@@_check_para_begin_show:nn #1 #2 
 %#1 color, #2 prefix
  {
    \bool_if:NT \l_@@_para_show_bool
      { 
        \tag_mc_begin:n{artifact}
        \llap{\color_select:n{#1}\tiny#2\int_use:N\g_@@_para_begin_int\ }
        \tag_mc_end:
      }
  }

\cs_new_protected:Npn \@@_check_para_end_show:nn #1 #2
 %#1  color, #2 prefix
  {
    \bool_if:NT \l_@@_para_show_bool
      { 
        \tag_mc_begin:n{artifact}
        \rlap{\color_select:n{#1}\tiny\ #2\int_use:N\g_@@_para_end_int}
        \tag_mc_end:
      }
  }
%    \end{macrocode}
%
% The para/begin and para/end code.
% We have two variants here: a simpler one, which must be used
% if the block code is not used (and so probably will disappear
% at some time) and a more sophisticated one that must
% be used if the block code is used.
% It is possible that we will need more variants, so
% we setup a socket so that the code can be easily switched.  
%    \begin{macrocode}
\socket_new:nn      {tagsupport/para/begin}{0}
\socket_new:nn      {tagsupport/para/end}{0}

\socket_new_plug:nnn{tagsupport/para/begin}{plain}
 {
   \bool_if:NT \l_@@_para_bool
     {
       \bool_if:NF \l_@@_para_flattened_bool
          {
            \@@_gincr_para_main_begin_int:
            \tag_struct_begin:n
              {
                tag=\l_@@_para_main_tag_tl,
              }
            \@@_para_main_store_struct:   
          }
        \@@_gincr_para_begin_int:
        \tag_struct_begin:n {tag=\l_@@_para_tag_tl}
        \@@_check_para_begin_show:nn {green}{}
        \tag_mc_begin:n {}
     }   
 }
\socket_new_plug:nnn{tagsupport/para/begin}{block}
 {
   \bool_if:NT \l_@@_para_bool
     {
       \legacy_if:nF { @inlabel }
         {
           \@@_check_typeout_v:n
             {==>~ @endpe = \legacy_if:nTF { @endpe }{true}{false} \on@line }
           \legacy_if:nF { @endpe }
            {
              \bool_if:NF \l_@@_para_flattened_bool
                 {
                   \@@_gincr_para_main_begin_int:
                   \tag_struct_begin:n
                    {
                     tag=\l_@@_para_main_tag_tl,
                     attribute-class=\l_@@_para_main_attr_class_tl,
                    }
                   \@@_para_main_store_struct: 
                 }
             }
            \@@_gincr_para_begin_int:
            \@@_check_typeout_v:n {==>~increment~ P \on@line }
            \tag_struct_begin:n
              {
                tag=\l_@@_para_tag_tl
                ,attribute-class=\l_@@_para_attr_class_tl
              }
            \@@_check_para_begin_show:nn {green}{\PARALABEL}    
            \tag_mc_begin:n {}
      }
    }  
 }
%    \end{macrocode}
% there was no real difference between the original and
% in the block variant, only a debug message. We therefore
% define only a plain variant.
%    \begin{macrocode}
\socket_new_plug:nnn{tagsupport/para/end}{plain}
  {
    \bool_if:NT \l_@@_para_bool
      {
        \@@_gincr_para_end_int:
        \@@_check_typeout_v:n {==>~increment~ /P \on@line }
        \tag_mc_end:
        \@@_check_para_end_show:nn {red}{}
        \tag_struct_end:
        \bool_if:NF \l_@@_para_flattened_bool
         {
           \@@_gincr_para_main_end_int:
           \tag_struct_end:
         }
      }  
  }
%    \end{macrocode}
% By default we assign the plain plug:
%    \begin{macrocode}
\socket_assign_plug:nn { tagsupport/para/begin}{plain}
\socket_assign_plug:nn { tagsupport/para/end}{plain}
%    \end{macrocode}
% And use the sockets in the hooks. Once tagging sockets exist, this
% can be adapted.
%    \begin{macrocode}
\AddToHook{para/begin}{ \socket_use:n { tagsupport/para/begin }
  }
\AddToHook{para/end} { \socket_use:n { tagsupport/para/end } }
%    \end{macrocode}
%
% If the block code is loaded we must ensure that it doesn't overwrite
% the hook again. And we must reassign the para/begin plug.
% This can go once the block code no longer tries to adapt the hooks.
%    \begin{macrocode}
\AddToHook{package/latex-lab-testphase-block/after}
 {
   \RemoveFromHook{para/begin}[tagpdf]
   \RemoveFromHook{para/end}[latex-lab-testphase-block]
   \AddToHook{para/begin}[tagpdf]
    {
      \socket_use:n { tagsupport/para/begin }
    }
  \AddToHook{para/end}[tagpdf]
    {
      \socket_use:n { tagsupport/para/end }
    }
  \socket_assign_plug:nn { tagsupport/para/begin}{block}
 }

%    \end{macrocode}
%
% We check the para count at the end. If tagging is not active it is not a error,
% but we issue a warning as it perhaps indicates that the testphase code didn't guard
% everything correctly.
%    \begin{macrocode}
\AddToHook{enddocument/info}
  {
    \tag_if_active:F
      {
        \msg_redirect_name:nnn { tag } { para-hook-count-wrong } { warning }
      }  
    \int_compare:nNnF {\g_@@_para_main_begin_int}={\g_@@_para_main_end_int}
         {
           \msg_error:nneee
             {tag}
             {para-hook-count-wrong}
             {\int_use:N\g_@@_para_main_begin_int}
             {\int_use:N\g_@@_para_main_end_int}
             {text-unit}
         }
    \int_compare:nNnF {\g_@@_para_begin_int}={\g_@@_para_end_int}
         {
           \msg_error:nneee
             {tag}
             {para-hook-count-wrong}
             {\int_use:N\g_@@_para_begin_int}
             {\int_use:N\g_@@_para_end_int}
             {text}
         }  
  }
%    \end{macrocode}
% We need at least the new-or-1 code.
% In generic mode we also must insert the code to finish the MC-chunks 
%    \begin{macrocode}
\@ifpackageloaded{footmisc}
  {\PackageWarning{tagpdf}{tagpdf~has~been~loaded~too~late!}} %
  {\RequirePackage{latex-lab-testphase-new-or-1}}
 
\AddToHook{begindocument/before}
 {
   \providecommand\@kernel@tagsupport@@@@makecol{}
   \providecommand\@kernel@before@cclv{}
   \bool_if:NF \g_@@_mode_lua_bool
     {
        \cs_if_exist:NT \@kernel@before@footins
         {
           \tl_put_right:Nn \@kernel@before@footins
             { \@@_add_missing_mcs_to_stream:Nn \footins {footnote} }
           \tl_put_right:Nn \@kernel@before@cclv
             {
               \@@_check_typeout_v:n {====>~In~\token_to_str:N \@makecol\c_space_tl\the\c@page}
               \@@_add_missing_mcs_to_stream:Nn \@cclv {main}
             }
           \tl_put_right:Nn \@kernel@tagsupport@@@@makecol
             {
               \@@_check_typeout_v:n {====>~In~\token_to_str:N \@makecol\c_space_tl\the\c@page}
               \@@_add_missing_mcs_to_stream:Nn \@outputbox {main}
             }  
           \tl_put_right:Nn \@mult@ptagging@hook
             {
               \@@_check_typeout_v:n {====>~In~\string\page@sofar}
               \process@cols\mult@firstbox
                {
                  \@@_add_missing_mcs_to_stream:Nn \count@ {multicol}
                }
               \@@_add_missing_mcs_to_stream:Nn \mult@rightbox {multicol}
             }
         }
     }
  }
%</package>
%    \end{macrocode}
% \begin{macro}
%   {
%    \tagpdfparaOn,
%    \tagpdfparaOff
%   }
%  This two command switch para mode on and off. |\tagpdfsetup| could be used
%  too but is longer. An alternative is |\tag_tool:n{para=false}|
%    \begin{macrocode}
%<base>\newcommand\tagpdfparaOn {}
%<base>\newcommand\tagpdfparaOff{}
%<*package>
\renewcommand\tagpdfparaOn {\bool_set_true:N \l_@@_para_bool}
\renewcommand\tagpdfparaOff{\bool_set_false:N \l_@@_para_bool}
\keys_define:nn { tag / tool} 
  {
    para .bool_set:N = \l_@@_para_bool,
    para-flattened .bool_set:N = \l_@@_para_flattened_bool,
  }  
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}
%   {
%    \tagpdfsuppressmarks
%   }
%  This command allows to suppress the creation of the marks. It takes an argument
%  which should normally be one of the mc-commands, puts a group around it and
%  suppress the marks creation in this group. This command should be used if
%  the begin and end command are at different boxing levels. E.g.
%  \begin{verbatim}
%  \@hangfrom
%   {
%    \tagstructbegin{tag=H1}%
%    \tagmcbegin    {tag=H1}%
%    #2
%   }
%   {#3\tagpdfsuppressmarks{\tagmcend}\tagstructend}%
%  \end{verbatim}
%    \begin{macrocode}
\NewDocumentCommand\tagpdfsuppressmarks{m}
  {{\use:c{@@_mc_disable_marks:} #1}}
%    \end{macrocode}
% \end{macro}
% \subsection{Header and footer}
% Header and footer should normally be tagged as artifacts. The following code
% requires the new hooks.
% For now we allow to disable this function, but probably the code should always there at
% the end.
% TODO check if Pagination should be changeable.
%    \begin{macrocode}
\cs_new_protected:Npn\@@_hook_kernel_before_head:{}
\cs_new_protected:Npn\@@_hook_kernel_after_head:{}
\cs_new_protected:Npn\@@_hook_kernel_before_foot:{}
\cs_new_protected:Npn\@@_hook_kernel_after_foot:{}

\AddToHook{begindocument}
 {
  \cs_if_exist:NT \@kernel@before@head
   {
     \tl_put_right:Nn \@kernel@before@head {\@@_hook_kernel_before_head:}
     \tl_put_left:Nn  \@kernel@after@head  {\@@_hook_kernel_after_head:}
     \tl_put_right:Nn \@kernel@before@foot {\@@_hook_kernel_before_foot:}
     \tl_put_left:Nn  \@kernel@after@foot  {\@@_hook_kernel_after_foot:}
   }
 }

\bool_new:N \g_@@_saved_in_mc_bool
\cs_new_protected:Npn \@@_exclude_headfoot_begin:
 {
    \bool_set_false:N  \l_@@_para_bool
    \bool_if:NTF \g_@@_mode_lua_bool
     {
      \tag_mc_end_push:
     }
     {
       \bool_gset_eq:NN   \g_@@_saved_in_mc_bool \g_@@_in_mc_bool
       \bool_gset_false:N \g_@@_in_mc_bool
     }
    \tag_mc_begin:n {artifact}
    \tag_stop:n{headfoot}
 }
\cs_new_protected:Npn \@@_exclude_headfoot_end:
 {
    \tag_start:n{headfoot}
    \tag_mc_end:
    \bool_if:NTF \g_@@_mode_lua_bool
     {
      \tag_mc_begin_pop:n{}
     }
     {
       \bool_gset_eq:NN \g_@@_in_mc_bool\g_@@_saved_in_mc_bool
     }
 }
%    \end{macrocode}
% This version allows to use an Artifact structure
%    \begin{macrocode}
\@@_attr_new_entry:nn {@@/attr/pagination}{/O/Artifact/Type/Pagination}
\cs_new_protected:Npn \@@_exclude_struct_headfoot_begin:n #1
 {
    \bool_set_false:N  \l_@@_para_bool
    \bool_if:NTF \g_@@_mode_lua_bool
     {
      \tag_mc_end_push:
     }
     {
       \bool_gset_eq:NN   \g_@@_saved_in_mc_bool \g_@@_in_mc_bool
       \bool_gset_false:N \g_@@_in_mc_bool
     }
    \tag_struct_begin:n{tag=Artifact,attribute-class=@@/attr/#1}
    \tag_mc_begin:n {artifact=#1}
    \tag_stop:n{headfoot}
 }

\cs_new_protected:Npn \@@_exclude_struct_headfoot_end:
 {
    \tag_start:n{headfoot}
    \tag_mc_end:
    \tag_struct_end:
    \bool_if:NTF \g_@@_mode_lua_bool
     {
      \tag_mc_begin_pop:n{}
     }
     {
       \bool_gset_eq:NN \g_@@_in_mc_bool\g_@@_saved_in_mc_bool
     }
 }
%    \end{macrocode}
% And now the keys
% \begin{macro}{exclude-header-footer (setup-key)}
%    \begin{macrocode}
\keys_define:nn { @@ / setup }
  {
    exclude-header-footer .choice:,
    exclude-header-footer / true .code:n =
     {
       \cs_set_eq:NN \@@_hook_kernel_before_head: \@@_exclude_headfoot_begin:
       \cs_set_eq:NN \@@_hook_kernel_before_foot: \@@_exclude_headfoot_begin:
       \cs_set_eq:NN \@@_hook_kernel_after_head:  \@@_exclude_headfoot_end:
       \cs_set_eq:NN \@@_hook_kernel_after_foot:  \@@_exclude_headfoot_end:
     },
    exclude-header-footer / pagination .code:n =
     {
       \cs_set:Nn \@@_hook_kernel_before_head: { \@@_exclude_struct_headfoot_begin:n {pagination} }
       \cs_set:Nn \@@_hook_kernel_before_foot: { \@@_exclude_struct_headfoot_begin:n {pagination} }
       \cs_set_eq:NN \@@_hook_kernel_after_head:  \@@_exclude_struct_headfoot_end:
       \cs_set_eq:NN \@@_hook_kernel_after_foot:  \@@_exclude_struct_headfoot_end:
     },
    exclude-header-footer / false .code:n =
     {
       \cs_set_eq:NN \@@_hook_kernel_before_head: \prg_do_nothing:
       \cs_set_eq:NN \@@_hook_kernel_before_foot: \prg_do_nothing:
       \cs_set_eq:NN \@@_hook_kernel_after_head:  \prg_do_nothing:
       \cs_set_eq:NN \@@_hook_kernel_after_foot:  \prg_do_nothing:
     },
   exclude-header-footer .default:n = true,
   exclude-header-footer .initial:n = true
  }
%    \end{macrocode}
% \end{macro}
% \subsection{Links}
% We need to close and reopen mc-chunks around links.
% Currently we handle URI and GoTo (internal) links.
% Links should have an alternative text in the Contents
% key. It is unclear which text this should be and
% how to get it.
%    \begin{macrocode}
\hook_gput_code:nnn
  {pdfannot/link/URI/before}
  {tagpdf}
  {
    \tag_mc_end_push:
    \tag_struct_begin:n { tag=Link }
    \tag_mc_begin:n { tag=Link }
    \pdfannot_dict_put:nne
      { link/URI }
      { StructParent }
      { \tag_struct_parent_int: }
  }

\hook_gput_code:nnn
  {pdfannot/link/URI/after}
  {tagpdf}
  {
     \tag_struct_insert_annot:ee {\pdfannot_link_ref_last:}{\tag_struct_parent_int:}
     \tag_mc_end:
     \tag_struct_end:
     \tag_mc_begin_pop:n{}
  }

\hook_gput_code:nnn
  {pdfannot/link/GoTo/before}
  {tagpdf}
  {
     \tag_mc_end_push:
     \tag_struct_begin:n{tag=Link}
     \tag_mc_begin:n{tag=Link}
     \pdfannot_dict_put:nne
       { link/GoTo }
       { StructParent }
       { \tag_struct_parent_int: }
  }

\hook_gput_code:nnn
  {pdfannot/link/GoTo/after}
  {tagpdf}
  {
    \tag_struct_insert_annot:ee {\pdfannot_link_ref_last:}{\tag_struct_parent_int:}
    \tag_mc_end:
    \tag_struct_end:
    \tag_mc_begin_pop:n{}

  }

% "alternative descriptions " for PAX3. How to get better text here??
\pdfannot_dict_put:nnn
 { link/URI }
 { Contents }
 { (url) }

\pdfannot_dict_put:nnn
 { link/GoTo }
 { Contents }
 { (ref) }

%    \end{macrocode}
%</package>
% \end{implementation}
% \PrintIndex
