texlive[59769] Master/texmf-dist: tagpdf (30jun21)

commits+karl at tug.org commits+karl at tug.org
Wed Jun 30 23:14:14 CEST 2021


Revision: 59769
          http://tug.org/svn/texlive?view=revision&revision=59769
Author:   karl
Date:     2021-06-30 23:14:14 +0200 (Wed, 30 Jun 2021)
Log Message:
-----------
tagpdf (30jun21)

Modified Paths:
--------------
    trunk/Master/texmf-dist/doc/latex/tagpdf/README.md
    trunk/Master/texmf-dist/doc/latex/tagpdf/tagpdf.pdf
    trunk/Master/texmf-dist/doc/latex/tagpdf/tagpdf.tex
    trunk/Master/texmf-dist/source/latex/tagpdf/tagpdf-backend.dtx
    trunk/Master/texmf-dist/source/latex/tagpdf/tagpdf-checks.dtx
    trunk/Master/texmf-dist/source/latex/tagpdf/tagpdf-roles.dtx
    trunk/Master/texmf-dist/source/latex/tagpdf/tagpdf-space.dtx
    trunk/Master/texmf-dist/source/latex/tagpdf/tagpdf-struct.dtx
    trunk/Master/texmf-dist/source/latex/tagpdf/tagpdf-tree.dtx
    trunk/Master/texmf-dist/source/latex/tagpdf/tagpdf.dtx
    trunk/Master/texmf-dist/source/latex/tagpdf/tagpdf.ins
    trunk/Master/texmf-dist/tex/latex/tagpdf/tagpdf-luatex.def
    trunk/Master/texmf-dist/tex/latex/tagpdf/tagpdf-mc-code-generic.sty
    trunk/Master/texmf-dist/tex/latex/tagpdf/tagpdf-mc-code-lua.sty
    trunk/Master/texmf-dist/tex/latex/tagpdf/tagpdf.lua
    trunk/Master/texmf-dist/tex/latex/tagpdf/tagpdf.sty
    trunk/Master/texmf-dist/tex/latex/tagpdf/tagpdfdocu-patches.sty

Added Paths:
-----------
    trunk/Master/texmf-dist/doc/latex/tagpdf/global-ex.png
    trunk/Master/texmf-dist/doc/latex/tagpdf/tagpdf-code.pdf
    trunk/Master/texmf-dist/doc/latex/tagpdf/tagpdf-code.tex
    trunk/Master/texmf-dist/source/latex/tagpdf/tagpdf-mc-generic.dtx
    trunk/Master/texmf-dist/source/latex/tagpdf/tagpdf-mc-luacode.dtx
    trunk/Master/texmf-dist/source/latex/tagpdf/tagpdf-mc-shared.dtx
    trunk/Master/texmf-dist/source/latex/tagpdf/tagpdf-user.dtx

Removed Paths:
-------------
    trunk/Master/texmf-dist/source/latex/tagpdf/tagpdf-mc.dtx
    trunk/Master/texmf-dist/tex/latex/tagpdf/tagpdf-attr-code.sty
    trunk/Master/texmf-dist/tex/latex/tagpdf/tagpdf-checks-code.sty
    trunk/Master/texmf-dist/tex/latex/tagpdf/tagpdf-deprecated.def
    trunk/Master/texmf-dist/tex/latex/tagpdf/tagpdf-mc-code-shared.sty
    trunk/Master/texmf-dist/tex/latex/tagpdf/tagpdf-pdftex.def
    trunk/Master/texmf-dist/tex/latex/tagpdf/tagpdf-roles-code.sty
    trunk/Master/texmf-dist/tex/latex/tagpdf/tagpdf-space-code.sty
    trunk/Master/texmf-dist/tex/latex/tagpdf/tagpdf-struct-code.sty
    trunk/Master/texmf-dist/tex/latex/tagpdf/tagpdf-tree-code.sty
    trunk/Master/texmf-dist/tex/latex/tagpdf/tagpdf-user.sty

Modified: trunk/Master/texmf-dist/doc/latex/tagpdf/README.md
===================================================================
--- trunk/Master/texmf-dist/doc/latex/tagpdf/README.md	2021-06-30 20:41:50 UTC (rev 59768)
+++ trunk/Master/texmf-dist/doc/latex/tagpdf/README.md	2021-06-30 21:14:14 UTC (rev 59769)
@@ -1,6 +1,6 @@
 #tagpdf — A package to create tagged pdf
-Packageversion: 0.82 
-Packagedate: 2021/06/14
+Packageversion: 0.9 
+Packagedate: 2021/06/29
 Author: Ulrike Fischer
 
 ## License

Added: trunk/Master/texmf-dist/doc/latex/tagpdf/global-ex.png
===================================================================
(Binary files differ)

Index: trunk/Master/texmf-dist/doc/latex/tagpdf/global-ex.png
===================================================================
--- trunk/Master/texmf-dist/doc/latex/tagpdf/global-ex.png	2021-06-30 20:41:50 UTC (rev 59768)
+++ trunk/Master/texmf-dist/doc/latex/tagpdf/global-ex.png	2021-06-30 21:14:14 UTC (rev 59769)

Property changes on: trunk/Master/texmf-dist/doc/latex/tagpdf/global-ex.png
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex/tagpdf/tagpdf-code.pdf
===================================================================
(Binary files differ)

Index: trunk/Master/texmf-dist/doc/latex/tagpdf/tagpdf-code.pdf
===================================================================
--- trunk/Master/texmf-dist/doc/latex/tagpdf/tagpdf-code.pdf	2021-06-30 20:41:50 UTC (rev 59768)
+++ trunk/Master/texmf-dist/doc/latex/tagpdf/tagpdf-code.pdf	2021-06-30 21:14:14 UTC (rev 59769)

Property changes on: trunk/Master/texmf-dist/doc/latex/tagpdf/tagpdf-code.pdf
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/pdf
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex/tagpdf/tagpdf-code.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/tagpdf/tagpdf-code.tex	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/latex/tagpdf/tagpdf-code.tex	2021-06-30 21:14:14 UTC (rev 59769)
@@ -0,0 +1,94 @@
+ \iffalse meta-comment
+
+% File: tagpdf.dtx
+
+ Copyright (C) 2019-2020 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/u-fischer/tagpdf
+
+ for those people who are interested.
+
+ \fi
+\RequirePackage{pdfmanagement-testphase}
+\DeclareDocumentMetadata{}
+\makeatletter
+\declare at file@substitution{doc.sty}{doc-v3beta.sty}
+\makeatother
+\documentclass{l3doc}
+
+% The next line is needed so that \GetFileInfo will be able to pick up
+% version data.
+\usepackage{longtable}
+\usepackage{tagpdf}
+
+
+\begin{document}
+
+\GetFileInfo{tagpdf.sty}
+
+\title{%
+  \pkg{tagpdf} -- A package to experiment with pdf tagging%
+  \thanks{This file describes \fileversion,
+    last revised \filedate.}%
+}
+
+\author{^^A
+ Ulrike Fischer\thanks
+   {^^A
+     E-mail:
+       \href{mailto:fischer at troubleshooting-tex.de}
+         {fischer at troubleshooting-tex.de}^^A
+   }^^A
+}
+
+\date{Released \filedate}
+
+\maketitle
+\tableofcontents
+
+\clearpage
+
+% Make the separate source files into a single whole, format-wise
+\makeatletter
+\RenewDocumentCommand\maketitle{}{%
+  \clearpage
+  \part{\@title}%
+}
+\makeatother
+\renewcommand*\partname{Part}
+\DeclareExpandableDocumentCommand\thanks{m}{}
+
+\let\DelayPrintIndex\PrintIndex
+\RenewDocumentCommand\PrintIndex{}{}
+
+% Load the source files in order
+\DocInput{tagpdf.dtx}
+\DocInput{tagpdf-checks.dtx}
+\DocInput{tagpdf-user.dtx}
+\DocInput{tagpdf-tree.dtx}
+\DocInput{tagpdf-mc-shared.dtx}
+\DocInput{tagpdf-mc-generic.dtx}
+\DocInput{tagpdf-mc-luacode.dtx}
+\DocInput{tagpdf-struct.dtx}
+\DocInput{tagpdf-backend.dtx}
+\DocInput{tagpdf-roles.dtx}
+\DocInput{tagpdf-space.dtx}
+\clearpage
+
+\DelayPrintIndex
+
+\end{document}


Property changes on: trunk/Master/texmf-dist/doc/latex/tagpdf/tagpdf-code.tex
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Modified: trunk/Master/texmf-dist/doc/latex/tagpdf/tagpdf.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/tagpdf/tagpdf.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/tagpdf/tagpdf.tex	2021-06-30 20:41:50 UTC (rev 59768)
+++ trunk/Master/texmf-dist/doc/latex/tagpdf/tagpdf.tex	2021-06-30 21:14:14 UTC (rev 59769)
@@ -4,8 +4,8 @@
 
 
 \makeatletter
-\def\UlrikeFischer at package@version{0.82}
-\def\UlrikeFischer at package@date{2021-06-14}
+\def\UlrikeFischer at package@version{0.9}
+\def\UlrikeFischer at package@date{2021-06-29}
 \makeatother
 
 \documentclass[DIV=12,parskip=half-,bibliography=totoc]{scrartcl}
@@ -53,7 +53,6 @@
  interwordspace=true,
  %log=v
  %show-spaces
- global-mc
  }
 
 \usepackage{hyperxmp}
@@ -79,13 +78,9 @@
 \usepackage{tagpdfdocu-patches}
 
 
+\cfoot*{\pagemark}
 
-%header and footer. This still needs some sorting, the first page does't work correctly
-\cfoot*{\leavevmode\tagmcbegin{artifact=pagination}\pagemark\tagmcend}
-\makeatletter
-\patchcmd\@oddfoot{\begingroup}{\begingroup\tagpdfparaOff}{}{}
-\patchcmd\@oddhead{\begingroup}{\begingroup\tagpdfparaOff}{}{}
-\makeatother
+%
 
 \newcommand\PDF{PDF}
 
@@ -154,10 +149,20 @@
 
 
 \tableofcontents
+\section{Preface to version 0.9}
 
+In this version lots of things have changed, but most of them are internal: the code has been reviewed and cleaned up,
+a number of errors corrected, the code has been properly documented (and the code documentation can now be compiled and
+printed).
+
+There are nevertheless also a number of changes for the public interface, including some breaking changes. Check the change section below for
+details.
+
+
+
 \section{Preface to version 0.8 and newer}
 
-Starting with version 0.8 one major step towards integration of the code into the \LaTeX{} has been done:
+Starting with version 0.8 one major step towards integration of the code into the \LaTeX{} kernel has been done:
 The code now relies on the new \LaTeX{} PDF management. This management, which is for a testphase provided
 as an external package, \texttt{pdfmanagement-testphase},
 prepares the ground for better support for tagged PDF in \LaTeX{}.
@@ -204,7 +209,9 @@
 
 While the generic mode is not bad and I spent quite some time to get it working I nevertheless think that the lua mode is the future and the only one that will be usable for larger documents. \PDF{} is a page orientated format and so the ability of luatex to manipulate pages and nodes after the \TeX-processing is really useful here. Also with luatex characters are normally already given as unicode.
 
+The package uses quite a lot labels (in generic mode more than with luamode). At the begin it relied on the \pkg{zref} package, but switched now to a new experimental implementation for labels. The drawback of the new method is that they don't give yet good rerun messages if they have changed. I advise to use the \pkg{rerunfilecheck} package as a intermediate work-around.
 
+
 \subsection{References and target PDF version}
 
 My main reference for the first versions of this package
@@ -214,7 +221,7 @@
 now target \PDF{} 2.0. This doesn't mean that 2.0 will be required, but that the code and the options will be extended to
 support \PDF{} 2.0. One example is the support for associated files, another the support for name spaces in version 0.82.
 
-The packages doesn't try to suppress all 2.0 features if an older \PDF{} version is produced. It normally doesn't harm if a \PDF{} contains keys unknown in its version and it makes the code faster and easier to maintain if there aren't too many tests and code pathes; so for example associated files will always be added. But tests could be added in case this leads to incompabilities.
+The package doesn't try to suppress all 2.0 features if an older \PDF{} version is produced. It normally doesn't harm if a \PDF{} contains keys unknown in its version and it makes the code faster and easier to maintain if there aren't too many tests and code pathes; so for example associated files will always be added. But tests could be added in case this leads to incompabilities.
 
 It should be noted that some tools don't like \PDF{}~2.0.  PAC3 for example simply crashes, and pdftk will create a \PDF{}~1.0 from it. This makes testing \PDF{}~2.0 files a bit of a challenge.
 
@@ -239,7 +246,7 @@
 Syntax validation and formal standard validation can be done with preflight of the (non-free) adobe acrobat.
 It can also be done also with the free \PDF{} Accessibility Checker (PAC~3) \parencite{pac3}.
 There is also the validator veraPDF \parencite{verapdf}.
-A rather new tool is \enquote{Next Generation PDF} \parencite{ngpdf}, a browser application which converts a tagged PDF to html, allows to inspect its structure and also to edit the structure.
+A rather new and quite useful tool is \enquote{Next Generation PDF} \parencite{ngpdf}, a browser application which converts a tagged PDF to html, allows to inspect its structure and also to edit the structure.
 
 Practical validation is naturally the more complicated part. It needs screen reader, users which actually knows how to handle them, can test documents and can report where a \PDF{} has real accessibility problems.
 
@@ -338,6 +345,48 @@
 
 PDF 2.0 namespace are now supported.
 
+\subsection{Changes in version 0.82}
+
+A command |\tag_if_active:TF| to test if tagging is active has been added. This allow external packages to write conditional code.
+
+The commands |\tag_struct_parent_int:| and |\tag_struct_insert_annot:nn| have been added. They allow to
+add annotations to the structure.
+
+
+\subsection{Changes in version 0.83}
+
+|\tag_finish_structure:| has been removed, it is no longer a public command.
+
+\subsection{Changes in version 0.9}
+
+\begin{itemize}
+\item Code has been cleaned up and better documented.
+
+\item \textbf{More engines supported} The generic mode of \pkg{tagpdf} now works
+(theoretically, it is not much tested) with all engines supported
+by the pdfmanagement. So compilations with Xe\LaTeX{} or with dvips should work. But it should be noted that
+these engines and backends don't support the |interspaceword| option. With Xe\LaTeX{} it is perhaps possible
+implement something with |\XeTeXinterchartoks|, but for the dvips route I don't see an option (apart from lots
+of manual macros everywhere).
+\item \textbf{MC-attributes are global again} In\sidenote{Breaking change!} version 0.6 the attributes used in
+luamode to mark the MC-chunks were no longer set globally. This avoided a number of problems with header and footer
+and background material, but further tests showed that it makes it difficult to correctly mark things like
+links which have to interrupt the current marking code---the attributes couldn't easily escape groups added by
+users. See section~\ref{sec:global-local} for more details.
+\item \textbf{key global-mc removed:} Due to the changes in the attribute keys this key is not longer needed.
+\item \textbf{key check-tags removed:} It doesn't fit. Checks are handled over the logging level.
+\item |\tagpdfget| has been removed, use the expl3 version if needed.
+\item The show commands |\showtagpdfmcdata|, |\showtagpdfattributes|, |\showtagstack| have been removed and replaced
+by a more flexible command |\ShowTagging|.
+\item The commands |\tagmcbegin| and |\tagmcend| no longer ignore following spaces or remove earlier one. While this
+is nice in some places, it also ate spaces in places where this wanted expected. From now on both commands behave exactly
+like the expl3 versions.
+\item The lua-code to add real space glyphs has been separated from the tagging code. This means that |interwordspace| now
+works also if tagging is not active.
+\item The key |activate| has been added, it open the first structure, see below.
+\end{itemize}
+
+
 \subsection{Proof of concept: the tagging of the documentation itself}
 
 Starting with version 0.6 the documentation itself has been tagged. The tagging wasn't (and isn't) in no way perfect. The validator from Adobe didn't complain, but PAX3 wanted alternative text for all links (no idea why) and so I put everywhere simple text like \enquote{link} and \enquote{ref}. The links to footnotes gave warnings, so I disabled them. I used types from the \PDF{} version 1.7, mostly as I have no idea what should be used for code in 2.0. Margin notes were simply wrong \ldots
@@ -370,6 +419,8 @@
 
 \begin{docCommand}{tag_if_active:TF}{}\end{docCommand}
 
+The check is true only if \emph{everything} is activated. In all other cases (also if tagging has been stopped locally) it will be false.
+
 \subsection{Modes and package options}
 
 
@@ -401,6 +452,9 @@
 \begin{description}
 \item[\PrintKeyName{activate-all}]
  Boolean, initially false. Activates everything, that's normally the sensible thing to do.
+\item [\PrintKeyName{activate}] Like |activate-all|, \emph{additionally} is opens at begin document
+a structure with |\tagstructbegin| and closes it at end document. The key accepts as value a tag name which is used as the tag of the structure.
+The default value is |Document|.
 \item[\PrintKeyName{activate-mc}]
  Boolean, initially false. Activates the code related to marked content.
 \item[\PrintKeyName{activate-struct}]
@@ -409,8 +463,6 @@
 Boolean, initially false. Activates the code related to trees. Should be used only if the two other keys has been used too.
 \item[\PrintKeyName{add-new-tag}]
  Allows to define new tag names, see section \ref{sec:new-tag} for a description.
-\item[\PrintKeyName{check-tags}]
- Boolean, initially true. Activates some safety checks (but doesn't do very much currently. It will perhaps be merged with the log-level key).
 \item[\PrintKeyName{interwordspace}]
  Choice key, possible values are \PrintKeyName{true}/""\PrintKeyName{on} and \PrintKeyName{false}/\PrintKeyName{off}. The key activates/deactivates the insertion of space glyphs, see section~\ref{sec:spacechars}. In the luamode it only works if at least \PrintKeyName{activate-mc} has been used.
 
@@ -438,10 +490,7 @@
 \item[\PrintKeyName{uncompress}]
  Sets both the \PDF{} compresslevel and the \PDF{} objcompresslevel to 0 and so allows to inspect the \PDF{}.
 
-\item[\PrintKeyName{global-mc}]
- Only relevant for luatex and luamode and can only be used in the preamble. If used the attributes used for the mc-tags are set globally. This key is temporary! It is there to allow to test if global or local setting is more sensible. See section~\ref{sec:global-local} for more info.
 
-
 \end{description}
 
 
@@ -653,8 +702,17 @@
   Often text in a document is created automatically or moved around: entries in the table of contents, index, bibliography and more. To mark these text chunks correctly one has to analyze the code creating such content to find suitable places to inject the literals.
 
   \item
-  The literals are inserted directly and not at shipout. This means that due to the asynchronous page breaking of \TeX\ the MCID-number can be wrong even if the counter is reset at every page (this package uses in generic mode a label-ref-system to get around this problem. This sadly means that three compilations are needed until everything has settled down).
+  The literals are inserted directly and not at shipout. This means that due to the asynchronous page breaking of \TeX\ the MCID-number can be wrong even if the counter is reset at every page. This package uses in generic mode a label-ref-system to get around this problem. This sadly means that often at least three compilations are needed until everything has settled down.
 
+  It can actually be worse: If the text is changed after the MCID-numbers have been assigned, and
+  a new mc-chunk is inserted in the middle of the page, then all the numbers have to be recalculated
+  and that requires again a number of compilations until it really settles down again.
+  Internal references are especially problematic here, as the first compilation
+  typically creates a non-link |??|, and only the second inserts the structure and the new mc.
+  When the reference system in LaTeX will be extended, care will be taken to ensure that already the dummy text builds a chunk.
+  Until then the advice is to first compile the document and resolve all cross-reference and to activate tagging only at the end.
+
+
   \item
   There exist environments which process their content more than once -- examples are \texttt{align} and \texttt{tabularx}.
        So one has to check for doublettes and holes in the counting system.
@@ -680,6 +738,7 @@
 
 
 
+
 \subsubsection{Commands to mark content and chunks}
 
 
@@ -690,7 +749,7 @@
 \begin{docCommand}{tag_mc_begin:n}{\marg{key-val-list}}\end{docCommand}
 
 
-These commands insert the begin of the marked content code in the \PDF{}. They don't start a paragraph. \emph{They don't start a group}. The user command additionally issues an \verb+\ignorespaces+ to suppress spaces after itself.
+These commands insert the begin of the marked content code in the \PDF{}. They don't start a paragraph. \emph{They don't start a group}.
 Such markers should not be nested. The command will warn you if this happens.
 
 The key-val list understands the following keys:
@@ -751,28 +810,28 @@
 \begin{docCommand}{tagmcend}{}\end{docCommand}
 \begin{docCommand}{tag_mc:end}{}\end{docCommand}
 
-These commands insert the end code of the marked content. They don't end a group and in generic mode it doesn't matter if they are in another group as the starting commands. The user command also issues in hmode at first an \verb+\unskip+. In generic mode both commands check if there has been a begin marker and issue a warning if not. In luamode it is often possible to omit the command, as the effect of the begin command ends with the current group or with a new \verb+\tagmcbegin+ anyway.
+These commands insert the end code of the marked content. They don't end a group and it doesn't matter if they are in another group as the starting commands. In generic mode both commands check if there has been a begin marker and issue a warning if not. In luamode it is often possible to omit the command, as the effect of the begin command ends  with a new \verb+\tagmcbegin+ anyway.
 
 
+% no longer relevant
+%\begin{tcolorbox}[before upper=\tagpdfparaOn]
+%\minisec{About nesting mc-commands}\label{mc-nesting}
+%
+%\textbf{Attention!}\sidenote{luamode} As mentioned above in luamode it is often possible to omit the \verb+\tagmcend+ command. This basically means that mc-chunks can be nested.  But be aware that this can have surprising side effects on the order in the structure.
+%
+%Consider a code like this:
+%
+%
+%\begin{lstlisting}
+%\tagmcbegin{tag=P} Block 1 {\tagmcbegin{tag=P} Block 2} Block 3 \tagmcend
+%\end{lstlisting}
+%
+%
+%Block 3 will here get the same id number as Block 1 and be stored in the structure \emph{before} Block 2. The \PDF{} will record the chunks in the order \texttt{Block 1 -- Block 3 -- Block 2}. See also section~\ref{sec:global-local}.
+%
+%\end{tcolorbox}
 
-\begin{tcolorbox}[before upper=\tagpdfparaOn]
-\minisec{About nesting mc-commands}\label{mc-nesting}
 
-\textbf{Attention!}\sidenote{luamode} As mentioned above in luamode it is often possible to omit the \verb+\tagmcend+ command. This basically means that mc-chunks can be nested.  But be aware that this can have surprising side effects on the order in the structure.
-
-Consider a code like this:
-
-
-\begin{lstlisting}
-\tagmcbegin{tag=P} Block 1 {\tagmcbegin{tag=P} Block 2} Block 3 \tagmcend
-\end{lstlisting}
-
-
-Block 3 will here get the same id number as Block 1 and be stored in the structure \emph{before} Block 2. The \PDF{} will record the chunks in the order \texttt{Block 1 -- Block 3 -- Block 2}. See also section~\ref{sec:global-local}.
-
-\end{tcolorbox}
-
-
 \begin{docCommand}{tagmcuse}{}\end{docCommand}
 \begin{docCommand}{tag_mc_use:n}{}\end{docCommand}
 
@@ -803,24 +862,24 @@
 In \emph{lua mode} it tests if the mc-attribute is currently unset. You can't test the nesting level with it!
 
 
-\begin{docCommand}{tagpdfget}{\marg{key word}}\end{docCommand}
 \begin{docCommand}{tag_get:n}{\marg{key word}}\end{docCommand}
 
+This command give back some variables. Currently the only working key words are \verb+mc\_tag+ and \verb+struct\_tag+.
 
-These commands give back some variables. Currently the only working key words are \verb+mc\_tag+ and \verb+struct\_tag+.
-
 \subsubsection{Luamode: global or not global -- that is the question}\label{sec:global-local}
 
-In\sidenote{Luamode mode only} luamode the mc-commands set and unset an attribute to mark the nodes. One can view such an attribute like a font change or a color: they affect all following chars and glue node until stopped.
+In\sidenote{Luamode mode only} luamode the mc-commands set and unset an attribute to mark the nodes. One can view such an attribute like a font change or a color: they affect all following chars and glue nodes until stopped.
 
-Currently the attributes are set locally. This has the advantage that the attributes don't spill over in area where they are not wanted like the header and footer or the background pictures.
-But it has the disadvantage that is difficult for an inner structure to correctly interrupt the outer
-mc-chunk if it can't control the group level. For example this would work fine:
+From version 0.6 to 0.82 the attributes were set locally.
+This had the advantage that the attributes didn't spill over in area where they are not wanted like the header and footer or the background pictures.
+But it had the disadvantage that it was difficult for an inner structure to correctly interrupt the outer
+mc-chunk if it can't control the group level. For example this didn't work due to the grouping inserted by the user:
 
 \begin{lstlisting}
 \tagstructbegin{tag=P}
 \tagmcbegin{tag=P}
   Start paragraph
+  {% user grouping
    \tag_mc_end_push:
    \tagstructbegin{tag=Em}
    \tagmcbegin{tag=Em}
@@ -828,37 +887,52 @@
    \tagmcend
    \tagstructend
    \tag_mc_begin_pop:n{}
+  }% user grouping
  Continuation of paragraph
 \tagmcend
 \tagstructend
 \end{lstlisting}
 
-But if the user adds a group like in the following listing, then the reading order will be wrong and the \emph{emphasized text} will move in the structure at the end as described in the box about nesting
-mc-chunks on page~\pageref{mc-nesting}.
+The reading order was then wrong, and the \emph{emphasized text} moved in the structure at the end.
 
+So starting with version 0.9 this has been reverted. The attribute is now global again.
+This solves the \enquote{interruption} problem, but has its price: Material inserted by the output routine
+must be properly guarded. For example
+
 \begin{lstlisting}
-\tagstructbegin{tag=P}
-\tagmcbegin{tag=P}
-  Start paragraph
-  { %group
-   \tag_mc_end_push:
-   \tagstructbegin{tag=Em}
-   \tagmcbegin{tag=Em}
-   \emph{with emphasized text}
-   \tagmcend
-   \tagstructend
-   \tag_mc_begin_pop:n{}
-  } %group
- Continuation of paragraph
-\tagmcend
+\RequirePackage{pdfmanagement-testphase}
+\DeclareDocumentMetadata{uncompress}
+\documentclass{article}
+\usepackage{tagpdf}
+\tagpdfsetup{activate,interwordspace=true}
+
+\pagestyle{headings}
+\begin{document}
+\tagstructbegin{tag=Document}
+\sectionmark{HEADER}
+\AddToHook{shipout/background}{\put(5cm,-5cm){BACKGROUND}}
+\tagmcbegin{tag=P}Page 1\newpage Page 2\tagmcend
 \tagstructend
+\end{document}
 \end{lstlisting}
 
-If the attribute is set globally this wouldn't be a problem. Currently the question is undecided.
-To allow to test with both versions it is possible to switch for a document with \texttt{global-mc} to global attributes.
+Here the header and the background code on the  \emph{first} page will be marked up as paragraph
+and added as chunk to the document structure. The header and the background code on
+the \emph{second} page will be marked as artifact. The following figure shows how the tags looks
+like.
 
+\tagpdfparaOff
+\tagstructbegin{tag=Figure,alttext=Show tags of examples,attribute=bbox}\tagmcbegin{tag=Figure}
+\includegraphics{global-ex}
+\tagmcend\tagstructend
+\tagpdfparaOn
 
+It is therefore from now on important to correctly markup such code. Header and footer typically should be
+artifacts. The LaTeX kernel hasn't yet suitable hooks around header and footer to allow to automate
+this, but they will be added. With packages like \pkg{fancyhdr}  or \pkg{scrlayer-scrpage} it is quite easy to add
+the needed code too.
 
+
 \subsubsection{Tips}
 
 \begin{itemize}
@@ -892,7 +966,7 @@
 \end{figure}
 
 
-\subsubsection{Links and other annotations}
+\subsubsection{Links and other annotations}\label{sec:link+annot}
 
 Annotations (like links or form field annotations) are objects associated with a geometric region of the page rather than with a particular object in its content stream. Any connection between a link or a form field and the text is based solely on visual appearance (the link text is in the same region, or there is empty space for the form field annotation) rather than on an explicitly specified association.
 
@@ -904,7 +978,7 @@
 
 \begin{docCommand}{tag_struct_parent_int:}{}\end{docCommand}
 
-This insert the current value of a global counter used to track such object. It can be used to add the \texttt{/StructParent} value to
+This insert the current value of a global counter used to track such objects. It can be used to add the \texttt{/StructParent} value to
 the annotation dictionary.
 
 \begin{docCommand}{tag_struct_insert_annot:nn}{\marg{object reference}\marg{struct parent number}}\end{docCommand}
@@ -911,7 +985,7 @@
 
 This will insert the annotation described by the object reference into the current structure by creating the OBJR object. It will
 also add the necessary entry to the parent tree and increase the global counter referred to by |\tag_struct_parent_int:|.
-It does nothing if (structure) tagging is not activated. 
+It does nothing if (structure) tagging is not activated.
 
 Attention! As the second command increases the global counter at the end it changes the value given back by the first.
 That means that if nesting is involved care must be taken that the correct numbers is used. This should be easy to fulfil for most annotations, as there are boxes.
@@ -949,9 +1023,7 @@
 \end{lstlisting}
 
 
-With luatex and local attributes (see section~\ref{sec:global-local}) commands like \cs{url} should not be grouped to allow them to reset the mc-attributes, or if groups are involved the mc-chunks should be closed and reopened manually to get the right reading order.
 
-
 \subsubsection{Math}
 
 
@@ -998,7 +1070,7 @@
 sit amet, lacus.\tagmcend
 \end{lstlisting}
 
-\subsubsection{Automatic tagging of paragraphs}
+\subsubsection{Automatic tagging of paragraphs}\label{sec:paratagging}
 
 \begin{docCommand}{tagpdfparaOn}{}\end{docCommand}
 \begin{docCommand}{tagpdfparaOff}{}\end{docCommand}
@@ -1005,8 +1077,13 @@
 
 Another feature that emerged from the \LaTeX{} tagged PDF project are hooks at the begin and end of paragraphs.
 \pkg{tagpdf} makes use of these hooks to tag paragraphs. This can be activated/deactivated (also locally) with
-options of \cs{tagpdfsetup} or with the two commands above. \emph{This is very experimental and it requires a new latex-dev!}
+options of \cs{tagpdfsetup} or with the two commands above. \emph{This is very experimental and it requires a new \LaTeX!}
 
+The automatic tagging require that for every begin of a paragraph with the begin hook code 
+there a corresponding end with the closing hook code. This can fail, e.g if a |vbox| doesn't correctly issue a |\par| at the end.
+If this happens the tagging structure can get every confused. It is therefore needed to check the structure carefully as currently
+no checks are implemented to check this automatically. 
+
 \subsection{Task 2: Marking the structure}
 
 
@@ -1136,7 +1213,7 @@
     See also section~\ref{sec:attributes}.
 
   \item[\PrintKeyName{attribute-class}]
-   This key takes as argument a comma list of attribute names (use braces to protect the commas from the external key-val parser) and allows to add one or more attribute classes to the structure object. As an example
+   This key takes as argument a comma list of attribute names (use braces to protect the commas from the external key-val parser) and allows to add them as attribute classes to the structure object. As an example
 
 
       \begin{lstlisting}
@@ -1271,19 +1348,12 @@
 
 \subsection{Task 3: tree Management}
 
+When all the document content has been correctly marked and the data for the trees has been collected they must be flushed to the \PDF{}. This is done automatically (if the package has been activated) with an internal command in an end document hook.
 
+\begin{docCommand}{__tag_finish_structure:}{}\end{docCommand}
 
-When all the document content has been correctly marked and the data for the trees has been collected they must be flushed to the \PDF{}. This is done automatically (if the package has been activated) with the following command in \verb+\AfterEndDocument+:
-
-\begin{docCommand}{tag_finish_structure:}{}\end{docCommand}
-
 This will hopefully write all the needed objects and values to the \PDF{}. (Beside the already mentioned  \texttt{StructTreeRoot} and \texttt{StructElem} objects, additionally a so-called \texttt{ParentTree} is needed which records the parents of all the marked contents bits, a \texttt{Rolemap}, perhaps a \texttt{ClassMap} and object for the attributes, and a few more values and dictionaries).
 
-I'm not quite sure if this shouldn't be a really internal command.
-
-
-
-
 \subsection{A fully marked up document body}
 
 
@@ -1476,7 +1546,8 @@
 
 With pdftex this will simply call the primitive \verb+\pdfinterwordspaceon+. pdftex will then insert at various places a char from a font called dummy-space. Attention! This means that at every space there are additional font switches in the \PDF{}: from the current font to the dummy-space font and back again. This will make the \PDF{} larger. As \verb+\pdfinterwordspaceon+ is a primitive function it can't be fine tuned or adapted. You can only turn it on and off and insert manually such a space glyph with \verb+\pdffakespace+.
 
-With luatex (in luamode) interwordspace is implemented with a lua-function which is inserted in two callbacks and marks up the places where it seems sensible to inter a space glyph. Later in the process (when also the mc-markers are inserted) the space glyphs are injected -- the code will take the glyph from the current font if this has a space glyph or switch to the default latin modern font. The current code works reasonable well in normal text.
+With luatex (in luamode) |interwordspace| is implemented with a lua-function which is inserted in two callbacks and marks up the places where it seems sensible to inter a space glyph. Later in the process the space glyphs are injected -- the code will take the glyph from the current font if this has a space glyph or switch to the default latin modern font. The current code works reasonable well in normal text.
+|interwordspace| can be used without actually tagging a document.
 
 The key \PrintKeyName{show-spaces} will show lines at the places where in lua mode spaces are inserted and so can help you to find problematic places. For listings -- which have a quite specific handling of spaces -- you can find a suggestion in the example \texttt{ex-space-glyph-listings}.
 
@@ -1516,22 +1587,32 @@
 \section{Debugging}
 
 While developing commands and tagging a document, it can be useful to get some info about the current structure. For this
-a number of commands are provided
+a show command is provided
 
-\begin{docCommand}{showtagstack}{}\end{docCommand}
+\begin{docCommand}{ShowTagging}{\marg{key-val}}\end{docCommand}
 
-This shows the tag names of the currently open structures. Typically it will contain at
-least |root| and |Document|.
+This command takes as argument a key-val list which implements a number of show options.
 
-\begin{docCommand}{showtagpdfmcdata}{\oarg{mc number}}\end{docCommand}
+\begin{description}
+  \item[\PrintKeyName{mc-data}] This key is relevant for luamode 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. 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.
 
-This\sidenote{luaonly} can only be used with lualatex and shows some info about the
-current mc-chunk. The optional argument allows to select a number.
+  \item[\PrintKeyName{mc-current}]  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 absolute counter. It works in all mode,
+  but the output in luamode looks different.
 
-\begin{docCommand}{showtagpdfattributes}{}\end{docCommand}
+  \item[\PrintKeyName{struct-stack}] This key shows the current
+  structure stack. Typically it will contain at
+  least |root| and |Document|.
+  With the value |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{description}
 
-This\sidenote{luaonly} can only be used with lualatex and shows some info about the
-current attributes.
 
 
 \section{To-do}
@@ -1541,9 +1622,11 @@
 \begin{itemize}
 \item Add commands and keys to enable/disable the checks.
 \item Check/extend the code for language tags.
-\item Think about math.
+\item Think about math (progress: examples using luamml, associated files exists).
 \item Think about Links/Annotations
+     (progress: mostly done, see section~\ref{sec:link+annot} and the code in \pkg{l3pdffield})
 \item Keys for alternative and actualtext. How to define the input encoding? Like in Accsupp?
+     (progress: keys are there, but encoding interface needs perhaps improving)
 \item Check twocolumn documents
 \item Examples
 \item Write more Tests
@@ -1551,14 +1634,14 @@
 \item Unicode
 \item Hyphenation char
 \item Think about included (tagged) \PDF{}. Can one handle them?
-\item Improve the documentation
+\item Improve the documentation (progress: it gets better)
 \item Tag as proof of concept the documentation (nearly done)
-\item Document the code better
-\item Create dtx
+\item Document the code better (progress: mostly done)
+\item Create dtx (progress: done)
 \item Find someone to check and improve the lua code
 \item Move more things to lua in the luamode
 \item Find someone to check and improve the rest of the code
-\item Check differences between \PDF{} versions 1.7 and 2.0.
+\item Check differences between \PDF{} versions 1.7 and 2.0. (progress: WIP, namespaces done)
 \item bidi?
 \end{itemize}
 

Modified: trunk/Master/texmf-dist/source/latex/tagpdf/tagpdf-backend.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/tagpdf/tagpdf-backend.dtx	2021-06-30 20:41:50 UTC (rev 59768)
+++ trunk/Master/texmf-dist/source/latex/tagpdf/tagpdf-backend.dtx	2021-06-30 21:14:14 UTC (rev 59769)
@@ -22,31 +22,57 @@
 %
 % for those people who are interested.
 %
+%<*driver>
+\RequirePackage{pdfmanagement-testphase}
+\DeclareDocumentMetadata{}
+\makeatletter
+\declare at file@substitution{doc.sty}{doc-v3beta.sty}
+\makeatother
+\documentclass{l3doc}
+\usepackage{array,booktabs,caption}
+\hypersetup{pdfauthor=Ulrike Fischer,
+ pdftitle=tagpdf-mc module (tagpdf)}
+\begin{document}
+  \DocInput{\jobname.dtx}
+\end{document}
+%</driver>
 % \fi
+% \title{^^A
+%   The \pkg{tagpdf-luatex.def} \\ Driver for luatex  ^^A
+%   \\ Part of the tagpdf package
+% }
 %
+% \author{^^A
+%  Ulrike Fischer\thanks
+%    {^^A
+%      E-mail:
+%        \href{mailto:fischer at troubleshooting-tex.de}
+%          {fischer at troubleshooting-tex.de}^^A
+%    }^^A
+% }
+%
+% \date{Version 0.9, released 2021-06-29}
+% \maketitle
+% \begin{implementation}
 %    \begin{macrocode}
 %<@@=tag>
 %<*luatex>
-\ProvidesExplFile {tagpdf-luatex.def} {2021-06-14} {0.82}
+\ProvidesExplFile {tagpdf-luatex.def} {2021-06-29} {0.9}
   {tagpdf~driver~for~luatex}
-
-\newattribute \l_@@_mc_type_attr     %the value represent the type
-\newattribute \l_@@_mc_cnt_attr      %will hold the \c at g_@@_MCID_abs_int value
-
-\newattribute \g_@@_interwordspace_attr
-\newattribute \g_@@_interwordfont_attr
-
-% The lua code
-% ensure that 10pt font has been loaded:
+%    \end{macrocode}
+% \section{Loading the lua}
+% The space code requires that the fall back font has been loaded and initialized,
+% so we force that first. But perhaps this could be done in the kernel.
+%
+%    \begin{macrocode}
 {
   \fontencoding{TU}\fontfamily{lmr}\fontseries{m}\fontshape{n}\fontsize{10pt}{10pt}\selectfont
 }
-\directlua { tagpdf=require('tagpdf.lua') }
-
-%%%% driver (lualatex) commands
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-
+\lua_now:e { tagpdf=require('tagpdf.lua') }
+%    \end{macrocode}
+%
+% The following defines wrappers around prop and seq commands to store the
+% data also in lua tables.
 % I probably want also lua tables
 % I put them in the ltx.@@.tables namespaces
 % The tables will be named like the variables but without backslash
@@ -54,94 +80,80 @@
 % ltx.@@.tables[string]
 % Old code, I'm not quite sure if this was a good idea. Now I have mix of table in
 % ltx.@@.tables and ltx.@@.mc/struct. And a lot is probably not needed.
-
-
-\cs_new_protected:Nn \@@_prop_new:N
+% TODO: this should be cleaned up, but at least roles are currently using
+% the table!
+%
+% \begin{macro}
+%   {
+%     \@@_prop_new:N,
+%     \@@_seq_new:N,
+%     \@@_prop_gput:Nnn,
+%     \@@_seq_gput_right:Nn,
+%     \@@_seq_item:cn,
+%     \@@_prop_item:cn,
+%     \@@_seq_show:N,
+%     \@@_prop_show:N
+%   }
+%    \begin{macrocode}
+\cs_set_protected:Npn \@@_prop_new:N #1
   {
     \prop_new:N #1
-    \directlua { ltx.@@.tables.\cs_to_str:N#1 = {} }
+    \lua_now:e { ltx.@@.tables.\cs_to_str:N#1 = {} }
   }
 
 
-\cs_new_protected:Nn \@@_seq_new:N
+\cs_set_protected:Npn \@@_seq_new:N #1
   {
     \seq_new:N #1
-    \directlua { ltx.@@.tables.\cs_to_str:N#1 = {} }
+    \lua_now:e { ltx.@@.tables.\cs_to_str:N#1 = {} }
   }
 
 
-\cs_new_protected:Nn \@@_prop_gput:Nnn
+\cs_set_protected:Npn \@@_prop_gput:Nnn #1 #2 #3
   {
     \prop_gput:Nnn #1 { #2 } { #3 }
-    \directlua { ltx.@@.tables.\cs_to_str:N#1 ["#2"] = "#3" }
+    \lua_now:e { ltx.@@.tables.\cs_to_str:N#1 ["#2"] = "#3" }
   }
 
 
-\cs_new_protected:Nn \@@_seq_gput_right:Nn
+\cs_set_protected:Npn \@@_seq_gput_right:Nn #1 #2
   {
     \seq_gput_right:Nn #1 { #2 }
-    \directlua { table.insert(ltx.@@.tables.\cs_to_str:N#1, "#2") }
+    \lua_now:e { table.insert(ltx.@@.tables.\cs_to_str:N#1, "#2") }
   }
 
 %Hm not quite sure about the naming
 
-\cs_new:Npn \@@_seq_item:cn #1 #2
+\cs_set:Npn \@@_seq_item:cn #1 #2
   {
-    \directlua { tex.print(ltx.@@.tables.#1[#2]) }
+    \lua_now:e { tex.print(ltx.@@.tables.#1[#2]) }
   }
 
-\cs_new:Npn \@@_prop_item:cn #1 #2
+\cs_set:Npn \@@_prop_item:cn #1 #2
   {
-    \directlua { tex.print(ltx.@@.tables.#1["#2"]) }
+    \lua_now:e { tex.print(ltx.@@.tables.#1["#2"]) }
   }
 
 %for debugging commands that show both the seq/prop and the lua tables
-\cs_new_protected:Nn \@@_seq_show:N
+\cs_set_protected:Npn \@@_seq_show:N #1
   {
     \seq_show:N #1
-    \directlua { ltx.@@.trace.log ("lua~sequence~array~\cs_to_str:N#1",1) }
-    \directlua { ltx.@@.trace.show_seq (ltx.@@.tables.\cs_to_str:N#1) }
+    \lua_now:e { ltx.@@.trace.log ("lua~sequence~array~\cs_to_str:N#1",1) }
+    \lua_now:e { ltx.@@.trace.show_seq (ltx.@@.tables.\cs_to_str:N#1) }
   }
 
-\cs_new_protected:Nn \@@_prop_show:N
+\cs_set_protected:Npn \@@_prop_show:N #1
   {
     \prop_show:N #1
-    \directlua {ltx.@@.trace.log  ("lua~property~table~\cs_to_str:N#1",1) }
-    \directlua {ltx.@@.trace.show_prop (ltx.@@.tables.\cs_to_str:N#1) }
+    \lua_now:e {ltx.@@.trace.log  ("lua~property~table~\cs_to_str:N#1",1) }
+    \lua_now:e {ltx.@@.trace.show_prop (ltx.@@.tables.\cs_to_str:N#1) }
  }
-%</luatex>
 %    \end{macrocode}
-%
+% \end{macro}
 %    \begin{macrocode}
-%<*pdftex>
-\ProvidesExplFile {tagpdf-pdftex.def} {2021-06-14} {0.82}
-  {tagpdf~driver~for~pdftex}
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%%% driver (pdflatex) commands
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-
-% These commands are only aliases for pdflatex but are defined differently with luatex
-% to get also lua tables.
-\cs_set_eq:NN \@@_prop_new:N     \prop_new:N
-
-\cs_set_eq:NN \@@_seq_new:N      \seq_new:N
-
-\cs_set_eq:NN \@@_prop_gput:Nnn  \prop_gput:Nnn
-
-\cs_set_eq:NN \@@_seq_gput_right:Nn \seq_gput_right:Nn
-
-\cs_set_eq:NN \@@_seq_item:cn    \seq_item:cn
-
-\cs_set_eq:NN \@@_prop_item:cn   \prop_item:cn
-
-\cs_set_eq:NN \@@_seq_show:N     \seq_show:N
-
-\cs_set_eq:NN \@@_prop_show:N    \prop_show:N
-
-%</pdftex>
+%</luatex>
 %    \end{macrocode}
+% The module declaration
 %    \begin{macrocode}
 %<*lua>
 -- tagpdf.lua
@@ -149,8 +161,8 @@
 
 local ProvidesLuaModule = {
     name          = "tagpdf",
-    version       = "0.82",       --TAGVERSION
-    date          = "2021-06-14", --TAGDATE
+    version       = "0.9",       --TAGVERSION
+    date          = "2021-06-29", --TAGDATE
     description   = "tagpdf lua code",
     license       = "The LATEX Project Public License 1.3c"
 }
@@ -168,8 +180,9 @@
  -
 --]]
 
-
-
+%    \end{macrocode}
+% Some comments about the lua structure.
+%    \begin{macrocode}
 --[[
 the main table is named ltx.@@. It contains the functions and also the data
 collected during the compilation.
@@ -199,9 +212,10 @@
  ltx.@@.func.mark_shipout (): a wrapper around the core function which inserts the last EMC
  ltx.@@.func.fill_parent_tree_line (page): outputs the entries of the parenttree for this page
  ltx.@@.func.output_parenttree(): outputs the content of the parenttree
+ ltx.@@.func.pdf_object_ref(name): outputs the object reference for the object name
  ltx.@@.func.markspaceon(), ltx.@@.func.markspaceoff(): (de)activates the marking of positions for space chars
- ltx.@@.trace.show_mc_data (num): shows ltx.@@.mc[num]
- ltx.@@.trace.show_all_mc_data (max): shows a maximum about mc's
+ ltx.@@.trace.show_mc_data (num,loglevel): shows ltx.@@.mc[num] is the current log level is >= loglevel
+ ltx.@@.trace.show_all_mc_data (max,loglevel): shows a maximum about mc's if the current log level is >= loglevel
  ltx.@@.trace.show_seq: shows a sequence (array)
  ltx.@@.trace.show_struct_data (num): shows data of structure num
  ltx.@@.trace.show_prop: shows a prop
@@ -209,19 +223,34 @@
  ltx.@@.trace.showspaces : boolean
 --]]
 
-local mctypeattributeid       = luatexbase.registernumber ("l_@@_mc_type_attr")
-local mccntattributeid        = luatexbase.registernumber ("l_@@_mc_cnt_attr")
-local iwspaceattributeid = luatexbase.registernumber ("g_@@_interwordspace_attr")
-local iwfontattributeid = luatexbase.registernumber ("g_@@_interwordfont_attr")
-
-
-local catlatex       = luatexbase.registernumber("catcodetable at latex")
+%    \end{macrocode}
+% This set-ups the main attribute registers.
+% The mc_type attribute stores the type (P, Span etc) encoded as a num,
+% The mc_cnt attribute stores the absolute number and allows so to see
+% if a node belongs to the same mc-chunk.
+%
+% The interwordspace attr is set by the function |@@_mark_spaces|, and marks
+% the place where spaces should be inserted.
+% The interwordfont attr is set by the function |@@_mark_spaces| too and
+% stores the font, so that we can decide which font
+% to use for the real space char.
+%    \begin{macrocode}
+local mctypeattributeid  = luatexbase.new_attribute ("g_@@_mc_type_attr")
+local mccntattributeid   = luatexbase.new_attribute ("g_@@_mc_cnt_attr")
+local iwspaceattributeid = luatexbase.new_attribute ("g_@@_interwordspace_attr")
+local iwfontattributeid  = luatexbase.new_attribute ("g_@@_interwordfont_attr")
+%    \end{macrocode}
+% with this token we can query the state of the boolean
+% and so detect if unmarked nodes should be marked as attributes
+%    \begin{macrocode}
 local tagunmarkedbool= token.create("g_@@_tagunmarked_bool")
 local truebool       = token.create("c_true_bool")
-
+%    \end{macrocode}
+% Now a number of local versions from global tables.
+% Not all is perhaps needed, most node variants were copied from lua-debug.
+%    \begin{macrocode}
+local catlatex       = luatexbase.registernumber("catcodetable at latex")
 local tableinsert    = table.insert
-
--- not all needed, copied from lua-visual-debug.
 local nodeid           = node.id
 local nodecopy         = node.copy
 local nodegetattribute = node.get_attribute
@@ -247,29 +276,29 @@
 local PENALTY        = node.id("penalty")
 local LOCAL_PAR      = node.id("local_par")
 local MATH           = node.id("math")
-
-local function @@_get_mathsubtype  (mathnode)
- if mathnode.subtype == 0 then
-  subtype = "beginmath"
- else
-  subtype = "endmath"
- end
- return subtype
-end
-
-
-
+%    \end{macrocode}
+% Now we setup the main table structure. ltx is used by other latex code too!
+%    \begin{macrocode}
 ltx             = ltx        or { }
 ltx.@@          = ltx.@@        or { }
-ltx.@@.mc             = ltx.@@.mc     or  { } -- mc data
-ltx.@@.struct         = ltx.@@.struct or  { } -- struct data
-ltx.@@.tables         = ltx.@@.tables or  { } -- tables created with new prop and new seq.
-                                            -- wasn't a so great idea ...
-ltx.@@.page           = ltx.@@.page   or  { } -- page data, currently only i->{0->mcnum,1->mcnum,...}
-ltx.@@.trace          = ltx.@@.trace  or  { } -- show commands
-ltx.@@.func           = ltx.@@.func   or  { } -- functions
-ltx.@@.conf           = ltx.@@.conf   or  { } -- configuration variables
-
+ltx.@@.mc       = ltx.@@.mc     or  { } -- mc data
+ltx.@@.struct   = ltx.@@.struct or  { } -- struct data
+ltx.@@.tables   = ltx.@@.tables or  { } -- tables created with new prop and new seq.
+                                        -- wasn't a so great idea ...
+                                        -- g_@@_role_tags_seq used by tag<-> is in this tables!
+ltx.@@.page     = ltx.@@.page   or  { } -- page data, currently only i->{0->mcnum,1->mcnum,...}
+ltx.@@.trace    = ltx.@@.trace  or  { } -- show commands
+ltx.@@.func     = ltx.@@.func   or  { } -- functions
+ltx.@@.conf     = ltx.@@.conf   or  { } -- configuration variables
+%    \end{macrocode}
+% \section{Logging functions}
+%
+% \begin{macro}{@@_log,ltx.@@.trace.log}
+% This rather simple log function takes as argument a
+% message (string) and a number and
+% will output the message to the log/terminal if the current loglevel
+% is greater or equal than num.
+%    \begin{macrocode}
 local @@_log =
  function (message,loglevel)
   if (loglevel or 3) <= tex.count["l_@@_loglevel_int"] then
@@ -278,8 +307,117 @@
  end
 
 ltx.@@.trace.log = @@_log
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{ltx.@@.trace.show_seq}
+% This shows the content of a seq as stored in the tables table.
+% It is used by the |\@@_seq_show:N| function. It is not used
+% in user commands, only for debugging, and so requires log level >0.
+%    \begin{macrocode}
+function ltx.@@.trace.show_seq (seq)
+ if (type(seq) == "table") then
+  for i,v in ipairs(seq) do
+   @@_log ("[" .. i .. "] => " .. tostring(v),1)
+  end
+  else
+   @@_log ("sequence " .. tostring(seq) .. " not found",1)
+  end
+end
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{ @@_pairs_prop,ltx.@@.trace.show_prop}
+% This shows the content of a prop as stored in the tables table.
+% It is used by the |\@@_prop_show:N| function.
+%    \begin{macrocode}
+local @@_pairs_prop =
+ function  (prop)
+      local a = {}
+      for n in pairs(prop) do tableinsert(a, n) end
+      table.sort(a)
+      local i = 0                -- iterator variable
+      local iter = function ()   -- iterator function
+        i = i + 1
+        if a[i] == nil then return nil
+        else return a[i], prop[a[i]]
+        end
+      end
+      return iter
+  end
 
 
+function ltx.@@.trace.show_prop (prop)
+ if (type(prop) == "table") then
+  for i,v in @@_pairs_prop (prop) do
+    @@_log ("[" .. i .. "] => " .. tostring(v),1)
+  end
+ else
+   @@_log ("prop " .. tostring(prop) .. " not found or not a table",1)
+ end
+ end
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{ltx.@@.trace.show_mc_data}
+% This shows some data for a mc given by |num|.
+% If something is shown depends on the log level.
+% The function is used by the following function and then in
+% |\ShowTagging|
+%    \begin{macrocode}
+function ltx.@@.trace.show_mc_data (num,loglevel)
+ if ltx.@@ and ltx.@@.mc and ltx.@@.mc[num] then
+  for k,v in pairs(ltx.@@.mc[num]) do
+   @@_log  ("mc"..num..": "..tostring(k).."=>"..tostring(v),loglevel)
+  end
+  if ltx.@@.mc[num]["kids"] then
+  @@_log ("mc" .. num .. " has " .. #ltx.@@.mc[num]["kids"] .. " kids",loglevel)
+   for k,v in ipairs(ltx.@@.mc[num]["kids"]) do
+    @@_log ("mc ".. num .. " kid "..k.." =>" .. v.kid.." on page " ..v.page,loglevel)
+   end
+  end
+ else
+  @@_log  ("mc"..num.." not found",loglevel)
+ end
+end
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{ltx.@@.trace.show_all_mc_data}
+% This shows data for the mc's between |min| and |max| (numbers).
+% It is used by the |\ShowTagging| function.
+%    \begin{macrocode}
+function ltx.@@.trace.show_all_mc_data (min,max,loglevel)
+ for i = min, max do
+  ltx.@@.trace.show_mc_data (i,loglevel)
+ end
+ texio.write_nl("")
+end
+%    \end{macrocode}
+% \end{macro}
+
+% \begin{macro}
+%   {
+%    ltx.@@.trace.show_struct_data
+%   }
+% This function shows some struct data.
+% Unused but kept for debugging.
+%    \begin{macrocode}
+function ltx.@@.trace.show_struct_data (num)
+ if ltx.@@ and ltx.@@.struct and ltx.@@.struct[num] then
+  for k,v in ipairs(ltx.@@.struct[num]) do
+   @@_log  ("struct "..num..": "..tostring(k).."=>"..tostring(v),1)
+  end
+ else
+  @@_log   ("struct "..num.." not found ",1)
+ end
+end
+%    \end{macrocode}
+% \end{macro}
+
+%
+% \section{Helper functions}
+% \subsection{Retrieve data functions}
+% \begin{macro}{@@_get_mc_cnt_type_tag}
+% This takes a node as argument and returns the mc-cnt, the mc-type and
+% and the tag (calculated from the mc-cnt.
+%    \begin{macrocode}
 local @@_get_mc_cnt_type_tag = function (n)
   local mccnt      =  nodegetattribute(n,mccntattributeid)  or -1
   local mctype     =  nodegetattribute(n,mctypeattributeid)  or -1
@@ -286,8 +424,150 @@
   local tag        =  ltx.@@.func.get_tag_from(mctype)
   return mccnt,mctype,tag
 end
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{@@_get_mathsubtype}
+% This function allows to detect if we are at the begin or the end of math.
+% It takes as argument a mathnode.
+%    \begin{macrocode}
+local function @@_get_mathsubtype  (mathnode)
+ if mathnode.subtype == 0 then
+  subtype = "beginmath"
+ else
+  subtype = "endmath"
+ end
+ return subtype
+end
+%    \end{macrocode}
+% \end{macro}
 
+% \begin{macro}
+%   {
+%    @@_get_num_from,
+%    ltx.@@.func.get_num_from,
+%    ltx.@@.func.output_num_from
+%   }
+% These functions take as argument a string |tag|, and return the number
+% under which is it recorded (and so the attribute value).
+% The first function outputs the number for lua, while the |output| function
+% outputs to tex.
+%    \begin{macrocode}
+local @@_get_num_from =
+ function (tag)
+  if ltx.@@.tables["g_@@_role_tags_prop"][tag] then
+    a= ltx.@@.tables["g_@@_role_tags_prop"][tag]
+  else
+    a= -1
+  end
+  return a
+ end
 
+ltx.@@.func.get_num_from = @@_get_num_from
+
+function ltx.@@.func.output_num_from (tag)
+  local num = @@_get_num_from (tag)
+  tex.sprint(catlatex,num)
+  if num == -1 then
+   @@_log ("Unknown tag "..tag.." used")
+  end
+end
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}
+%   {
+%    @@_get_tag_from ,
+%    ltx.@@.func.get_tag_from,
+%    ltx.@@.func.output_tag_from
+%   }
+% These functions are the opposites to the previous function:
+% they take as argument a number (the attribute value) and return the string |tag|.
+% The first function outputs the number for lua, while the |output| function
+% outputs to tex.
+%    \begin{macrocode}
+local @@_get_tag_from =
+ function  (num)
+  if ltx.@@.tables["g_@@_role_tags_seq"][num] then
+   a = ltx.@@.tables["g_@@_role_tags_seq"][num]
+  else
+   a= "UNKNOWN"
+  end
+ return a
+end
+
+ltx.@@.func.get_tag_from = @@_get_tag_from
+
+function ltx.@@.func.output_tag_from (num)
+  tex.sprint(catlatex,@@_get_tag_from (num))
+end
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}
+%   {
+%    ltx.@@.func.store_mc_data
+%   }
+% This function stores for |key|=|data| for mc-chunk |num|. It is used in the
+% tagpdf-mc code, to store for example the tag string, and the raw options.
+%    \begin{macrocode}
+function ltx.@@.func.store_mc_data (num,key,data)
+ ltx.@@.mc[num] = ltx.@@.mc[num] or { }
+ ltx.@@.mc[num][key] = data
+ @@_log  ("INFO TEX-STORE-MC-DATA: "..num.." => "..tostring(key).." => "..tostring(data),3)
+end
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}
+%   {
+%    ltx.@@.func.store_mc_label
+%   }
+% This function stores the |label|=|num| relationship in the |labels| subtable.
+% TODO: this is probably unused and can go.
+%    \begin{macrocode}
+function ltx.@@.func.store_mc_label (label,num)
+ ltx.@@.mc["labels"] = ltx.@@.mc["labels"] or { }
+ ltx.@@.mc.labels[label] = num
+end
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}
+%   {
+%    ltx.@@.func.store_mc_kid
+%   }
+% This function is used in the traversing code. It stores
+% a sub-chunk of a mc |mcnum| into the |kids| table.
+%    \begin{macrocode}
+function ltx.@@.func.store_mc_kid (mcnum,kid,page)
+ ltx.@@.trace.log("INFO TAG-STORE-MC-KID: "..mcnum.." => " .. kid.." on page " .. page,3)
+ ltx.@@.mc[mcnum]["kids"] = ltx.@@.mc[mcnum]["kids"] or { }
+ local kidtable = {kid=kid,page=page}
+ tableinsert(ltx.@@.mc[mcnum]["kids"], kidtable )
+end
+%    \end{macrocode}
+% \end{macro}
+
+% \begin{macro}
+%   {
+%    ltx.@@.func.mc_num_of_kids
+%   }
+% This function returns the number of kids a mc |mcnum| has. We need to account for
+% the case that a mc can have no kids.
+%    \begin{macrocode}
+function ltx.@@.func.mc_num_of_kids (mcnum)
+ local num = 0
+ if ltx.@@.mc[mcnum] and ltx.@@.mc[mcnum]["kids"] then
+   num = #ltx.@@.mc[mcnum]["kids"]
+ end
+ ltx.@@.trace.log ("INFO MC-KID-NUMBERS: " .. mcnum .. "has " .. num .. "KIDS",4)
+ return num
+end
+%    \end{macrocode}
+% \end{macro}
+% \subsection{Functions to insert the pdf literals}
+% \begin{macro}{@@_insert_emc_node}
+% This insert the emc node.
+%    \begin{macrocode}
 local function @@_insert_emc_node (head,current)
  local emcnode = nodenew("whatsit","pdf_literal")
        emcnode.data = "EMC"
@@ -295,8 +575,11 @@
        head = node.insert_before(head,current,emcnode)
  return head
 end
-
-
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{@@_insert_bmc_node}
+% This inserts a simple bmc node
+%    \begin{macrocode}
 local function @@_insert_bmc_node (head,current,tag)
  local bmcnode = nodenew("whatsit","pdf_literal")
        bmcnode.data = "/"..tag.." BMC"
@@ -304,7 +587,12 @@
        head = node.insert_before(head,current,bmcnode)
  return head
 end
-
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{@@_insert_bdc_node}
+%  This inserts a bcd node with a fix dict.
+%  TODO: check if this is still used, now that we create properties.
+%    \begin{macrocode}
 local function @@_insert_bdc_node (head,current,tag,dict)
  local bdcnode = nodenew("whatsit","pdf_literal")
        bdcnode.data = "/"..tag.."<<"..dict..">> BDC"
@@ -312,8 +600,28 @@
        head = node.insert_before(head,current,bdcnode)
  return head
 end
-
--- this is for debugging the space chars
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{@@_pdf_object_ref,ltx.@@.func.pdf_object_ref}
+% This allows to reference a pdf object reserved with the l3pdf command by name.
+% The return value is |n 0 R|, if the object doesn't exist, n is 0.
+% TODO: is uses internal l3pdf commands, this should be properly supported by l3pdf
+%    \begin{macrocode}
+local function @@_pdf_object_ref (name)
+   local tokenname = 'c__pdf_backend_object_'..name..'_int'
+   local object = token.create(tokenname).index..' 0 R'
+   return object
+end
+ltx.@@.func.pdf_object_ref=@@_pdf_object_ref
+%    \end{macrocode}
+% \end{macro}
+%
+% \section{Function for the real space chars}
+% \begin{macro}{@@_show_spacemark}
+% A debugging function, it is used to
+% inserts red color markers in the places where space chars can go, it can have
+% side effects so not always reliable, but ok.
+%    \begin{macrocode}
 local function @@_show_spacemark (head,current,color,height)
  local markcolor = color or "1 0 0"
  local markheight = height or 10
@@ -323,7 +631,24 @@
        head = node.insert_after(head,current,pdfstring)
  return head
 end
-
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{@@_fakespace,ltx.@@.func.fakespace}
+% This is used to define a lua version of |\pdffakespace|
+%    \begin{macrocode}
+local function @@_fakespace()
+   tex.setattribute(iwspaceattributeid,1)
+   tex.setattribute(iwfontattributeid,font.current())
+end
+ltx.@@.func.fakespace = @@_fakespace
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{@@_mark_spaces}
+% a function to mark up places where real space chars should be inserted.
+% It only sets attributes, these are then be used in a later traversing
+% which inserts the actual spaces.
+% When space handling is activated this function is inserted in some callbacks.
+%    \begin{macrocode}
 --[[ a function to mark up places where real space chars should be inserted
      it only sets an attribute.
 --]]
@@ -353,13 +678,15 @@
       end
      --  look also back
      if glyph.prev and (glyph.prev.id == GLUE)
-        and not inside_math  and (glyph.prev.width >0) and not nodehasattribute(glyph.prev,iwspaceattributeid)
+        and not inside_math
+        and (glyph.prev.width >0)
+        and not nodehasattribute(glyph.prev,iwspaceattributeid)
       then
         nodesetattribute(glyph.prev,iwspaceattributeid,1)
         nodesetattribute(glyph.prev,iwfontattributeid,glyph.font)
       -- for debugging
-       if ltx.__tag.trace.showspaces then
-        __tag_show_spacemark (head,glyph)
+       if ltx.@@.trace.showspaces then
+        @@_show_spacemark (head,glyph)
        end
       end
     elseif id == PENALTY then
@@ -381,7 +708,18 @@
   end
   return head
 end
-
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}
+%   {
+%    @@_activate_mark_space,
+%    ltx.@@.func.markspaceon,
+%    @@_activate_mark_space,
+%    ltx.@@.func.markspaceoff
+%    }
+% Theses functions add/remove the function which marks the spaces to the callbacks
+% |pre_linebreak_filter| and |hpack_filter|
+%    \begin{macrocode}
 local function @@_activate_mark_space ()
  if not luatexbase.in_callback ("pre_linebreak_filter","markspaces") then
   luatexbase.add_to_callback("pre_linebreak_filter",@@_mark_spaces,"markspaces")
@@ -397,23 +735,150 @@
  luatexbase.remove_from_callback("hpack_filter","markspaces")
  end
 end
---
+
 ltx.@@.func.markspaceoff=@@_deactivate_mark_space
-
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}
+%  {
+%   default_space_char,
+%   default_fontid,
+%  }
+% We need two local variable to setup a default space char.
+%    \begin{macrocode}
 local default_space_char = node.new(GLYPH)
 local default_fontid     = font.id("TU/lmr/m/n/10")
 default_space_char.char  = 32
 default_space_char.font  = default_fontid
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}
+%   {
+%    @@_space_chars_shipout,
+%    ltx.@@.func.space_chars_shipout,
+%    }
+% These is the main function to insert real space chars. It inserts a
+% glyph before every glue which has been marked previously. The attributes
+% are copied from the glue, so if the tagging is done later,
+% it will be tagged like it.
+%    \begin{macrocode}
+local function @@_space_chars_shipout (box)
+ local head = box.head
+  if head then
+    for n in node.traverse(head) do
+      local spaceattr = nodegetattribute(n,iwspaceattributeid)  or -1
+      if n.id == HLIST  then -- enter the hlist
+         @@_space_chars_shipout (n)
+      elseif n.id == VLIST then -- enter the vlist
+         @@_space_chars_shipout (n)
+      elseif n.id == GLUE then
+        if ltx.@@.trace.showspaces and spaceattr==1  then
+          @@_show_spacemark (head,n,"0 1 0")
+        end
+        if spaceattr==1  then
+          local space
+          local space_char = node.copy(default_space_char)
+          local curfont    = nodegetattribute(n,iwfontattributeid)
+          ltx.@@.trace.log ("INFO SPACE-FUNCTION-FONT: ".. tostring(curfont),3)
+          if curfont and luaotfload.aux.slot_of_name(curfont,"space") then
+            space_char.font=curfont
+          end
+          head, space = node.insert_before(head, n, space_char) --
+          n.width     = n.width - space.width
+          space.attr  = n.attr
+        end
+      end
+    end
+  end
+end
 
-local function @@_insert_space_char (head,n,fontid)
- if luaotfload.aux.slot_of_name(fontid,"space") then
-  local space
-  -- head, space = node.insert_before(head, n, ) -- Set the right font
-  -- n.width = n.width - space.width
-  -- space.attr = n.attr
- end
+function ltx.@@.func.space_chars_shipout (box)
+  @@_space_chars_shipout (box)
 end
+%    \end{macrocode}
+% \end{macro}
+%
+% \section{Function for the tagging}
+% \begin{macro}
+%   {
+%    ltx.@@.func.mc_insert_kids
+%   }
+% This is the main function to insert the
+% K entry into a StructElem object. It is used in tagpdf-mc-luacode module.
+% The |single| attribute allows to handle the case that a single
+% mc on the tex side can have more than one kid after the processing here,
+% and so we get the correct array/non array setup.
+%    \begin{macrocode}
+function ltx.@@.func.mc_insert_kids (mcnum,single)
+  if ltx.@@.mc[mcnum] then
+  ltx.@@.trace.log("INFO TEX-MC-INSERT-KID-TEST: " .. mcnum,4)
+   if ltx.@@.mc[mcnum]["kids"] then
+    if #ltx.@@.mc[mcnum]["kids"] > 1 and single==1 then
+     tex.sprint("[")
+    end
+    for i,kidstable in ipairs( ltx.@@.mc[mcnum]["kids"] ) do
+     local kidnum  = kidstable["kid"]
+     local kidpage = kidstable["page"]
+     local kidpageobjnum = pdfpageref(kidpage)
+     ltx.@@.trace.log("INFO TEX-MC-INSERT-KID: " .. mcnum ..
+                      " insert KID " ..i..
+                      " with num " .. kidnum ..
+                      " on page " .. kidpage.."/"..kidpageobjnum,3)
+     tex.sprint(catlatex,"<</Type /MCR /Pg "..kidpageobjnum .. " 0 R /MCID "..kidnum.. ">> " )
+    end
+    if #ltx.@@.mc[mcnum]["kids"] > 1 and single==1 then
+     tex.sprint("]")
+    end
+   else
+    -- this is typically not a problem, e.g. empty hbox in footer/header can
+    -- trigger this warning.
+    ltx.@@.trace.log("WARN TEX-MC-INSERT-NO-KIDS: "..mcnum.." has no kids",2)
+    if single==1 then
+      tex.sprint("null")
+    end
+   end
+  else
+   ltx.@@.trace.log("WARN TEX-MC-INSERT-MISSING: "..mcnum.." doesn't exist",0)
+  end
+end
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{ltx.@@.func.store_struct_mcabs}
+% This function is used in the tagpdf-mc-luacode. It store the absolute count
+% of the mc into the current structure. This must be done ordered.
+%    \begin{macrocode}
+function ltx.@@.func.store_struct_mcabs (structnum,mcnum)
+ ltx.@@.struct[structnum]=ltx.@@.struct[structnum] or { }
+ ltx.@@.struct[structnum]["mc"]=ltx.@@.struct[structnum]["mc"] or { }
+ -- a structure can contain more than on mc chunk, the content should be ordered
+ tableinsert(ltx.@@.struct[structnum]["mc"],mcnum)
+ ltx.@@.trace.log("INFO TEX-MC-INTO-STRUCT: "..
+                   mcnum.." inserted in struct "..structnum,3)
+ -- but every mc can only be in one structure
+ ltx.@@.mc[mcnum]= ltx.@@.mc[mcnum] or { }
+ ltx.@@.mc[mcnum]["parent"] = structnum
+end
 
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{ltx.@@.func.store_mc_in_page}
+% This is used in the traversing code and stores the relation between
+% abs count and page count.
+%    \begin{macrocode}
+-- pay attention: lua counts arrays from 1, tex pages from one
+-- mcid and arrays in pdf count from 0.
+function ltx.@@.func.store_mc_in_page (mcnum,mcpagecnt,page)
+ ltx.@@.page[page] = ltx.@@.page[page] or {}
+ ltx.@@.page[page][mcpagecnt] = mcnum
+ ltx.@@.trace.log("INFO TAG-MC-INTO-PAGE: page " .. page ..
+                   ": inserting MCID " .. mcpagecnt .. " => " .. mcnum,3)
+end
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{ltx.@@.func.mark_page_elements}
+% This is the main traversing function. See the lua comment for more details.
+%    \begin{macrocode}
 --[[
     Now follows the core function
     It wades through the shipout box and checks the attributes
@@ -433,22 +898,35 @@
 function ltx.@@.func.mark_page_elements (box,mcpagecnt,mccntprev,mcopen,name,mctypeprev)
   local name = name or ("SOMEBOX")
   local mctypeprev = mctypeprev or -1
-  local abspage = status.total_pages + 1  -- the real counter is increased inside the box so one off
-                                                                       -- if the callback is not used.
-  ltx.@@.trace.log ("PAGE " .. abspage,3)
-  ltx.@@.trace.log ("FUNC ARGS: pagecnt".. mcpagecnt.." prev "..mccntprev .. " type prev "..mctypeprev,4)
-  ltx.@@.trace.log ("TRAVERSING BOX ".. tostring(name).." TYPE ".. node.type(node.getid(box)),3)
+  local abspage = status.total_pages + 1  -- the real counter is increased
+                                          -- inside the box so one off
+                                          -- if the callback is not used. (???)
+  ltx.@@.trace.log ("INFO TAG-ABSPAGE: " .. abspage,3)
+  ltx.@@.trace.log ("INFO TAG-ARGS: pagecnt".. mcpagecnt..
+                    " prev "..mccntprev ..
+                    " type prev "..mctypeprev,4)
+  ltx.@@.trace.log ("INFO TAG-TRAVERSING-BOX: ".. tostring(name)..
+                    " TYPE ".. node.type(node.getid(box)),3)
   local head = box.head -- ShipoutBox is a vlist?
   if head then
     mccnthead, mctypehead,taghead = @@_get_mc_cnt_type_tag (head)
-    ltx.@@.trace.log ("HEAD " .. node.type(node.getid(head)).. " MC"..tostring(mccnthead).." => TAG "..tostring(mctypehead).." => "..tostring(taghead),3)
+    ltx.@@.trace.log ("INFO TAG-HEAD: " ..
+                      node.type(node.getid(head))..
+                      " MC"..tostring(mccnthead)..
+                      " => TAG " .. tostring(mctypehead)..
+                      " => ".. tostring(taghead),3)
   else
-    ltx.@@.trace.log ("HEAD is ".. tostring(head),3)
+    ltx.@@.trace.log ("INFO TAG-NO-HEAD: head is "..
+                       tostring(head),3)
   end
   for n in node.traverse(head) do
     local mccnt, mctype, tag = @@_get_mc_cnt_type_tag (n)
     local spaceattr = nodegetattribute(n,iwspaceattributeid)  or -1
-    ltx.@@.trace.log ("NODE ".. node.type(node.getid(n)).." MC"..tostring(mccnt).." => TAG "..tostring(mctype).." => " .. tostring(tag),3)
+    ltx.@@.trace.log ("INFO TAG-NODE: "..
+                       node.type(node.getid(n))..
+                      " MC".. tostring(mccnt)..
+                      " => TAG ".. tostring(mctype)..
+                      " => " ..  tostring(tag),3)
     if n.id == HLIST
     then -- enter the hlist
      mcopen,mcpagecnt,mccntprev,mctypeprev=
@@ -456,49 +934,42 @@
     elseif n.id == VLIST then -- enter the vlist
      mcopen,mcpagecnt,mccntprev,mctypeprev=
       ltx.@@.func.mark_page_elements (n,mcpagecnt,mccntprev,mcopen,"INTERNAL VLIST",mctypeprev)
-    elseif n.id == GLUE then       -- at glue real space chars are inserted, for the rest it is ignored
-     -- for debugging
-     if ltx.@@.trace.showspaces and spaceattr==1  then
-        @@_show_spacemark (head,n,"0 1 0")
-     end
-     if spaceattr==1  then
-        local space
-        local space_char = node.copy(default_space_char)
-        local curfont    = nodegetattribute(n,iwfontattributeid)
-        ltx.@@.trace.log ("FONT ".. tostring(curfont),3)
-        if curfont and luaotfload.aux.slot_of_name(curfont,"space") then
-          space_char.font=curfont
-        end
-        head, space = node.insert_before(head, n, space_char) --
-        n.width     = n.width - space.width
-        space.attr  = n.attr
-     end
+    elseif n.id == GLUE then       -- at glue real space chars are inserted, but this has
+                                   -- been done if the previous shipout wandering, so here it is ignored
     elseif n.id == LOCAL_PAR then  -- local_par is ignored
     elseif n.id == PENALTY then    -- penalty is ignored
     elseif n.id == KERN then       -- kern is ignored
-     ltx.@@.trace.log ("SUBTYPE KERN ".. n.subtype,3)
+     ltx.@@.trace.log ("INFO TAG-KERN-SUBTYPE: "..
+       node.type(node.getid(n)).." "..n.subtype,4)
     else
      -- math is currently only logged.
      -- we could mark the whole as math
      -- for inner processing the mlist_to_hlist callback is probably needed.
      if n.id == MATH then
-      ltx.@@.trace.log("NODE "..node.type(node.getid(n)).." "..@@_get_mathsubtype(n),3)
+      ltx.@@.trace.log("INFO TAG-MATH-SUBTYPE: "..
+        node.type(node.getid(n)).." "..@@_get_mathsubtype(n),4)
      end
      -- endmath
-     ltx.@@.trace.log("CURRENT "..mccnt.." PREV "..mccntprev,3)
+     ltx.@@.trace.log("INFO TAG-MC-COMPARE: current "..
+               mccnt.." prev "..mccntprev,4)
      if mccnt~=mccntprev then -- a new mc chunk
-      ltx.@@.trace.log ("NODE ".. node.type(node.getid(n)).." MC"..tostring(mccnt).." <=> PREVIOUS "..tostring(mccntprev),3)
+      ltx.@@.trace.log ("INFO TAG-NEW-MC-NODE: "..
+                         node.type(node.getid(n))..
+                        " MC"..tostring(mccnt)..
+                        " <=> PREVIOUS "..tostring(mccntprev),4)
       if mcopen~=0 then -- there is a chunk open, close it (hope there is only one ...
        box.list=@@_insert_emc_node (box.list,n)
        mcopen = mcopen - 1
-       ltx.@@.trace.log ("INSERT EMC " .. mcpagecnt .. " MCOPEN = " .. mcopen,2)
+       ltx.@@.trace.log ("INFO TAG-INSERT-EMC: " ..
+         mcpagecnt .. " MCOPEN = " .. mcopen,3)
        if mcopen ~=0 then
-        ltx.@@.trace.log ("!WARNING! open mc" .. " MCOPEN = " .. mcopen,1)
+        ltx.@@.trace.log ("WARN TAG-OPEN-MC: " .. mcopen,1)
        end
       end
       if ltx.@@.mc[mccnt] then
        if ltx.@@.mc[mccnt]["artifact"] then
-        ltx.@@.trace.log("THIS IS AN ARTIFACT of type "..tostring(ltx.@@.mc[mccnt]["artifact"]),3)
+        ltx.@@.trace.log("INFO TAG-INSERT-ARTIFACT: "..
+                          tostring(ltx.@@.mc[mccnt]["artifact"]),3)
         if ltx.@@.mc[mccnt]["artifact"] == "" then
          box.list = @@_insert_bmc_node (box.list,n,"Artifact")
         else
@@ -505,34 +976,39 @@
          box.list = @@_insert_bdc_node (box.list,n,"Artifact", "/Type /"..ltx.@@.mc[mccnt]["artifact"])
         end
        else
-        ltx.@@.trace.log("THIS IS A TAG "..tostring(tag),3)
+        ltx.@@.trace.log("INFO TAG-INSERT-TAG: "..
+                          tostring(tag),3)
         mcpagecnt = mcpagecnt +1
-        ltx.@@.trace.log ("INSERT BDC "..mcpagecnt,2)
+        ltx.@@.trace.log ("INFO TAG-INSERT-BDC: "..mcpagecnt,3)
         local dict= "/MCID "..mcpagecnt
         if ltx.@@.mc[mccnt]["raw"] then
-         ltx.@@.trace.log("RAW CONTENT"..tostring(ltx.@@.mc[mccnt]["raw"]),3)
+         ltx.@@.trace.log("INFO TAG-USE-RAW: "..
+           tostring(ltx.@@.mc[mccnt]["raw"]),3)
          dict= dict .. " " .. ltx.@@.mc[mccnt]["raw"]
         end
         if ltx.@@.mc[mccnt]["alt"] then
-         ltx.@@.trace.log("RAW CONTENT"..tostring(ltx.@@.mc[mccnt]["alt"]),3)
+         ltx.@@.trace.log("INFO TAG-USE-ALT: "..
+            tostring(ltx.@@.mc[mccnt]["alt"]),3)
          dict= dict .. " " .. ltx.@@.mc[mccnt]["alt"]
         end
         if ltx.@@.mc[mccnt]["actualtext"] then
-         ltx.@@.trace.log("RAW CONTENT"..tostring(ltx.@@.mc[mccnt]["actualtext"]),3)
+         ltx.@@.trace.log("INFO TAG-USE-ACTUALTEXT: "..
+           tostring(ltx.@@.mc[mccnt]["actualtext"]),3)
          dict= dict .. " " .. ltx.@@.mc[mccnt]["actualtext"]
         end
         box.list = @@_insert_bdc_node (box.list,n,tag, dict)
         ltx.@@.func.store_mc_kid (mccnt,mcpagecnt,abspage)
         ltx.@@.func.store_mc_in_page(mccnt,mcpagecnt,abspage)
-        ltx.@@.trace.show_mc_data (mccnt)
+        ltx.@@.trace.show_mc_data (mccnt,3)
        end
        mcopen = mcopen + 1
       else
-       ltx.@@.trace.log("THIS HAS NOT BEEN TAGGED",1)
-     -- perhaps code that tag a artifact can be added ...
        if tagunmarkedbool.mode == truebool.mode then
+        ltx.@@.trace.log("INFO TAG-NOT-TAGGED: this has not been tagged, using artifact",2)
         box.list = @@_insert_bmc_node (box.list,n,"Artifact")
         mcopen = mcopen + 1
+       else
+        ltx.@@.trace.log("WARN TAG-NOT-TAGGED: this has not been tagged",1)
        end
       end
       mccntprev = mccnt
@@ -541,18 +1017,29 @@
   end -- end for
   if head then
     mccnthead, mctypehead,taghead = @@_get_mc_cnt_type_tag (head)
-    ltx.@@.trace.log ("ENDHEAD " .. node.type(node.getid(head)).. " MC"..tostring(mccnthead).." => TAG "..tostring(mctypehead).." => "..tostring(taghead),3)
+    ltx.@@.trace.log ("INFO TAG-ENDHEAD: " ..
+                       node.type(node.getid(head))..
+                      " MC"..tostring(mccnthead)..
+                      " => TAG "..tostring(mctypehead)..
+                      " => "..tostring(taghead),4)
   else
-    ltx.@@.trace.log ("ENDHEAD is ".. tostring(head),3)
+    ltx.@@.trace.log ("INFO TAG-ENDHEAD: ".. tostring(head),4)
   end
-  ltx.@@.trace.log ("QUITTING TRAVERSING BOX ".. tostring(name).." TYPE ".. node.type(node.getid(box)),3)
+  ltx.@@.trace.log ("INFO TAG-QUITTING-BOX "..
+                     tostring(name)..
+                    " TYPE ".. node.type(node.getid(box)),4)
  return mcopen,mcpagecnt,mccntprev,mctypeprev
 end
 
-
-
-function ltx.__tag.func.mark_shipout (box)
- mcopen = ltx.__tag.func.mark_page_elements (box,-1,-100,0,"Shipout",-1)
+%    \end{macrocode}
+% \end{macro}
+%  \begin{macro}{ltx.@@.func.mark_shipout}
+%  This is the function used in the callback. Beside calling the traversing
+%  function it also checks if there is an open MC-chunk from a page
+%  break and insert the needed EMC literal.
+%    \begin{macrocode}
+function ltx.@@.func.mark_shipout (box)
+ mcopen = ltx.@@.func.mark_page_elements (box,-1,-100,0,"Shipout",-1)
  if mcopen~=0 then -- there is a chunk open, close it (hope there is only one ...
   local emcnode = nodenew("whatsit","pdf_literal")
   local list = box.list
@@ -561,199 +1048,28 @@
   if list then
      list = node.insert_after (list,node.tail(list),emcnode)
      mcopen = mcopen - 1
-     ltx.__tag.trace.log ("INSERT LAST EMC, MCOPEN = " .. mcopen,2)
+     ltx.@@.trace.log ("INFO SHIPOUT-INSERT-LAST-EMC: MCOPEN " .. mcopen,3)
   else
-     ltx.__tag.trace.log ("UPS ",1)
+     ltx.@@.trace.log ("WARN SHIPOUT-UPS: this shouldn't happen",0)
   end
   if mcopen ~=0 then
-     ltx.__tag.trace.log ("!WARNING! open mc" .. " MCOPEN = " .. mcopen,1)
+     ltx.@@.trace.log ("WARN SHIPOUT-MC-OPEN: " .. mcopen,1)
   end
  end
 end
+%    \end{macrocode}
+% \end{macro}
 
-
-function ltx.@@.trace.show_seq (seq)
- if (type(seq) == "table") then
-  for i,v in ipairs(seq) do
-   @@_log ("[" .. i .. "] => " .. tostring(v),1)
-  end
-  else
-   @@_log ("sequence " .. tostring(seq) .. " not found",1)
-  end
-end
-
-local @@_pairs_prop =
- function  (prop)
-      local a = {}
-      for n in pairs(prop) do tableinsert(a, n) end
-      table.sort(a)
-      local i = 0                -- iterator variable
-      local iter = function ()   -- iterator function
-        i = i + 1
-        if a[i] == nil then return nil
-        else return a[i], prop[a[i]]
-        end
-      end
-      return iter
-  end
-
-
-function ltx.@@.trace.show_prop (prop)
- if (type(prop) == "table") then
-  for i,v in @@_pairs_prop (prop) do
-    @@_log ("[" .. i .. "] => " .. tostring(v),1)
-  end
- else
-   @@_log ("prop " .. tostring(prop) .. " not found or not a table",1)
- end
- end
-
-
-local @@_get_num_from =
- function (tag)
-  if ltx.@@.tables["g_@@_role_tags_prop"][tag] then
-    a= ltx.@@.tables["g_@@_role_tags_prop"][tag]
-  else
-    a= -1
-  end
-  return a
- end
-
-ltx.@@.func.get_num_from = @@_get_num_from
-
-function ltx.@@.func.output_num_from (tag)
-  local num = @@_get_num_from (tag)
-  tex.sprint(catlatex,num)
-  if num == -1 then
-   @@_log ("Unknown tag "..tag.." used")
-  end
-end
-
-local @@_get_tag_from =
- function  (num)
-  if ltx.@@.tables["g_@@_role_tags_seq"][num] then
-   a = ltx.@@.tables["g_@@_role_tags_seq"][num]
-  else
-   a= "UNKNOWN"
-  end
- return a
-end
-
-ltx.@@.func.get_tag_from = @@_get_tag_from
-
-function ltx.@@.func.output_tag_from (num)
-  tex.sprint(catlatex,@@_get_tag_from (num))
-end
-
-function ltx.@@.func.store_mc_data (num,key,data)
- ltx.@@.mc[num] = ltx.@@.mc[num] or { }
- ltx.@@.mc[num][key] = data
- @@_log  ("storing mc"..num..": "..tostring(key).."=>"..tostring(data))
-end
-
-function ltx.@@.trace.show_mc_data (num)
- if ltx.@@ and ltx.@@.mc and ltx.@@.mc[num] then
-  for k,v in pairs(ltx.@@.mc[num]) do
-   @@_log  ("mc"..num..": "..tostring(k).."=>"..tostring(v),3)
-  end
-  if ltx.@@.mc[num]["kids"] then
-  @@_log ("mc" .. num .. " has " .. #ltx.@@.mc[num]["kids"] .. " kids",3)
-   for k,v in ipairs(ltx.@@.mc[num]["kids"]) do
-    @@_log ("mc ".. num .. " kid "..k.." =>" .. v.kid.." on page " ..v.page,3)
-   end
-  end
- else
-  @@_log  ("mc"..num.." not found",3)
- end
-end
-
-function ltx.@@.trace.show_all_mc_data (max)
- for i = 1, max do
-  ltx.@@.trace.show_mc_data (i)
- end
-end
-
-
-function ltx.@@.func.store_mc_label (label,num)
- ltx.@@.mc["labels"] = ltx.@@.mc["labels"] or { }
- ltx.@@.mc.labels[label] = num
-end
-
-function ltx.@@.func.store_mc_kid (mcnum,kid,page)
- ltx.@@.trace.log("MC"..mcnum.." STORING KID" .. kid.." on page " .. page,3)
- ltx.@@.mc[mcnum]["kids"] = ltx.@@.mc[mcnum]["kids"] or { }
- local kidtable = {kid=kid,page=page}
- tableinsert(ltx.@@.mc[mcnum]["kids"], kidtable )
-end
-
-
-function ltx.@@.func.mc_num_of_kids (mcnum)
- local num = 0
- if ltx.@@.mc[mcnum] and ltx.@@.mc[mcnum]["kids"] then
-   num = #ltx.@@.mc[mcnum]["kids"]
- end
- ltx.@@.trace.log ("MC" .. mcnum .. "has " .. num .. "KIDS",4)
- return num
-end
-
-function ltx.@@.func.mc_insert_kids (mcnum,single)
-  if ltx.@@.mc[mcnum] then
-  ltx.@@.trace.log("MC-KIDS test " .. mcnum,4)
-   if ltx.@@.mc[mcnum]["kids"] then
-    if #ltx.@@.mc[mcnum]["kids"] > 1 and single==1 then
-     tex.sprint("[")
-    end
-    for i,kidstable in ipairs( ltx.@@.mc[mcnum]["kids"] ) do
-     local kidnum  = kidstable["kid"]
-     local kidpage = kidstable["page"]
-     local kidpageobjnum = pdfpageref(kidpage)
-     ltx.@@.trace.log("MC" .. mcnum .. " insert KID " ..i.. " with num " .. kidnum .. " on page " .. kidpage.."/"..kidpageobjnum,3)
-     tex.sprint(catlatex,"<</Type /MCR /Pg "..kidpageobjnum .. " 0 R /MCID "..kidnum.. ">> " )
-    end
-    if #ltx.@@.mc[mcnum]["kids"] > 1 and single==1 then
-     tex.sprint("]")
-    end
-   else
-    ltx.@@.trace.log("WARN! MC"..mcnum.." has no kids",0)
-    if single==1 then
-      tex.sprint("null")
-    end
-   end
-  else
-   ltx.@@.trace.log("WARN! MC"..mcnum.." doesn't exist",0)
-  end
-end
-
-
-function ltx.@@.func.store_struct_mcabs (structnum,mcnum)
- ltx.@@.struct[structnum]=ltx.@@.struct[structnum] or { }
- ltx.@@.struct[structnum]["mc"]=ltx.@@.struct[structnum]["mc"] or { }
- -- a structure can contain more than on mc chunk, the content should be ordered
- tableinsert(ltx.@@.struct[structnum]["mc"],mcnum)
- ltx.@@.trace.log("MCNUM "..mcnum.." insert in struct "..structnum,3)
- -- but every mc can only be in one structure
- ltx.@@.mc[mcnum]= ltx.@@.mc[mcnum] or { }
- ltx.@@.mc[mcnum]["parent"] = structnum
-end
-
-function ltx.@@.trace.show_struct_data (num)
- if ltx.@@ and ltx.@@.struct and ltx.@@.struct[num] then
-  for k,v in ipairs(ltx.@@.struct[num]) do
-   @@_log  ("struct "..num..": "..tostring(k).."=>"..tostring(v))
-  end
- else
-  @@_log   ("struct "..num.." not found ")
- end
-end
-
--- pay attention: lua counts arrays from 1, tex pages from one
--- mcid and arrays in pdf count from 0.
-function ltx.@@.func.store_mc_in_page (mcnum,mcpagecnt,page)
- ltx.@@.page[page] = ltx.@@.page[page] or {}
- ltx.@@.page[page][mcpagecnt] = mcnum
- ltx.@@.trace.log("PAGE " .. page .. ": inserting MCID " .. mcpagecnt .. " => " .. mcnum,3)
-end
-
+% \section{Parenttree}
+% \begin{macro}
+%   {
+%    ltx.@@.func.fill_parent_tree_line,
+%    ltx.@@.func.output_parenttree
+%   }
+% These functions create the parent tree. The second, main function
+% is used in the tagpdf-tree code.
+% TODO check if the tree code can move into the backend code.
+%    \begin{macrocode}
 function ltx.@@.func.fill_parent_tree_line (page)
      -- we need to get page-> i=kid -> mcnum -> structnum
      -- pay attention: the kid numbers and the page number in the parent tree start with 0!
@@ -761,9 +1077,12 @@
     local pdfpage = page-1
     if ltx.@@.page[page] and ltx.@@.page[page][0] then
      mcchunks=#ltx.@@.page[page]
-     ltx.@@.trace.log("PAGETREE PAGE "..page.." has "..mcchunks.."+1 Elements ",3)
+     ltx.@@.trace.log("INFO PARENTTREE-NUM:  page "..
+                   page.." has "..mcchunks.."+1 Elements ",4)
      for i=0,mcchunks do
-      ltx.@@.trace.log("PAGETREE CHUNKS "..ltx.@@.page[page][i],3)
+     -- what does this log??
+      ltx.@@.trace.log("INFO PARENTTREE-CHUNKS:  "..
+        ltx.@@.page[page][i],4)
      end
      if mcchunks == 0 then
       -- only one chunk so no need for an array
@@ -770,10 +1089,13 @@
       local mcnum  = ltx.@@.page[page][0]
       local structnum = ltx.@@.mc[mcnum]["parent"]
       local propname  = "g_@@_struct_"..structnum.."_prop"
-      local objref   =  ltx.@@.tables[propname]["objref"] or "XXXX"
-      ltx.@@.trace.log("=====>"..tostring(objref),5)
+      --local objref   =  ltx.@@.tables[propname]["objref"] or "XXXX"
+      local objref = @@_pdf_object_ref('@@/struct/'..structnum)
+      ltx.@@.trace.log("INFO PARENTTREE-STRUCT-OBJREF:  =====>"..
+        tostring(objref),5)
       numsentry = pdfpage .. " [".. objref .. "]"
-      ltx.@@.trace.log("PAGETREE PAGE" .. page.. " NUM ENTRY = ".. numsentry,3)
+      ltx.@@.trace.log("INFO PARENTTREE-NUMENTRY: page " ..
+        page.. " num entry = ".. numsentry,3)
      else
       numsentry = pdfpage .. " ["
        for i=0,mcchunks do
@@ -780,14 +1102,16 @@
         local mcnum  = ltx.@@.page[page][i]
         local structnum = ltx.@@.mc[mcnum]["parent"] or 0
         local propname  = "g_@@_struct_"..structnum.."_prop"
-        local objref   =  ltx.@@.tables[propname]["objref"] or "XXXX"
+        --local objref   =  ltx.@@.tables[propname]["objref"] or "XXXX"
+        local objref = @@_pdf_object_ref('@@/struct/'..structnum)
         numsentry = numsentry .. " ".. objref
        end
       numsentry = numsentry .. "] "
-      ltx.@@.trace.log("PAGETREE PAGE" .. page.. " NUM ENTRY = ".. numsentry,3)
+      ltx.@@.trace.log("INFO PARENTTREE-NUMENTRY: page " ..
+        page.. " num entry = ".. numsentry,3)
      end
     else
-      ltx.@@.trace.log ("PAGETREE: NO DATA FOR PAGE "..page,3)
+      ltx.@@.trace.log ("INFO PARENTTREE-NO-DATA: page "..page,3)
     end
     return numsentry
 end
@@ -798,7 +1122,10 @@
   tex.sprint(catlatex,line)
  end
 end
-
-
+%    \end{macrocode}
+% \end{macro}
+%    \begin{macrocode}
 %</lua>
 %    \end{macrocode}
+% \end{implementation}
+% \PrintIndex

Modified: trunk/Master/texmf-dist/source/latex/tagpdf/tagpdf-checks.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/tagpdf/tagpdf-checks.dtx	2021-06-30 20:41:50 UTC (rev 59768)
+++ trunk/Master/texmf-dist/source/latex/tagpdf/tagpdf-checks.dtx	2021-06-30 21:14:14 UTC (rev 59769)
@@ -22,60 +22,443 @@
 %
 % for those people who are interested.
 %
+%
+%<*driver>
+\RequirePackage{pdfmanagement-testphase}
+\DeclareDocumentMetadata{}
+\makeatletter
+\declare at file@substitution{doc.sty}{doc-v3beta.sty}
+\makeatother
+\documentclass{l3doc}
+\usepackage{array,booktabs,caption}
+\hypersetup{pdfauthor=Ulrike Fischer,
+ pdftitle=tagpdf-checks module (tagpdf)}
+\begin{document}
+  \DocInput{\jobname.dtx}
+\end{document}
+%</driver>
 % \fi
+% \title{^^A
+%   The \pkg{tagpdf-checks} module\\ Messages and check code   ^^A
+%   \\ Part of the tagpdf package
+% }
 %
+% \author{^^A
+%  Ulrike Fischer\thanks
+%    {^^A
+%      E-mail:
+%        \href{mailto:fischer at troubleshooting-tex.de}
+%          {fischer at troubleshooting-tex.de}^^A
+%    }^^A
+% }
+%
+% \date{Version 0.9, released 2021-06-29}
+% \maketitle
+% \begin{documentation}
+% \section{Commands}
+% \begin{function}[pTF,EXP]{\tag_if_active:}
+% This command tests if tagging is active. It only gives true if all tagging has
+% been activated, \emph{and} if tagging hasn't been stopped locally.
+% \end{function}
+% \begin{function}[EXP]{\tag_get:n}
+%  \begin{syntax}
+%  \cs{tag_get:n}\Arg{keyword}
+%  \end{syntax}
+% This is a generic command to retrieve data. Currently
+% the only sensible values for the argument \meta{keyword}
+% are |mc_tag| and |struct_tag|.
+% \end{function}
+%
+% \section{Description of log messages}
+% \subsection{\cs{ShowTagging} command}
+%  \begin{tabular}{lll}
+%   Argument                          & type           & note\\
+%  \cs{ShowTagging}{mc-data = num}    & log+term       & lua-only\\
+%  \cs{ShowTagging}{mc-current} & log+term       & \\
+%  \cs{ShowTagging}{struck-stack= [log\verb+|+show]}  & log or term+stop \\
+%  \end{tabular}
+%
+% \subsection{Messages in checks and commands}
+% \scriptsize
+% \begin{tabular}{llll}
+%   command                & message  & action   & remark\\
+%   |\@@_check_structure_has_tag:n|
+% & |struct-missing-tag|
+% & error
+% \\
+%   |\@@_check_structure_tag:N|
+% & |role-unknown-tag|
+% & warning
+% \\
+%   |\@@_check_info_closing_struct:n|
+% & |struct-show-closing|
+% & info
+% & log-level>0
+% \\
+%   |\@@_check_no_open_struct:|
+% & struct-faulty-nesting
+% & error
+% & TODO: error only with 1?
+% \\
+%   |\@@_check_struct_used:n|
+% & |struct-used-twice|
+% & warning
+% \\
+%   |\@@_check_add_tag_role:nn|
+% & |role-missing|, |role-tag|, |role-unknown|
+% & warning, info (>0), warning
+% \\
+%   |\@@_check_mc_if_nested:|,
+% & |mc-nested|
+% & warning
+% \\
+%   |\@@_check_mc_if_open:|
+% & |mc-not-open|
+% & warning
+% & only generic (?)
+% \\
+%   |\@@_check_mc_pushed_popped:nn|
+% & |mc-pushed|, |mc-popped|
+% & info (2), info+|seq_log| (>2)
+% \\
+%   |\@@_check_mc_tag:N|
+% & |mc-tag-missing|, |role-unknown-tag|
+% & error (missing), warning (unknown).
+% \\
+%   |\@@_check_mc_used:n|
+% & |mc-used-twice|
+% & warning
+% & TODO: review the sense of this test!
+% \\
+%   |\@@_check_show_MCID_by_page:|
+% &
+% &
+% & currently unused
+% \\
+%   |\tag_mc_use:n|
+% & |mc-label-unknown|, |mc-used-twice|
+% & warning
+% & in mc-shared
+% \\
+%   |\role_add_tag:nn|
+% & |new-tag|
+% &  info (>0)
+% & in roles
+% \\
+% & |sys-no-interwordspace|
+% &  warning
+% & space module, only xetex/dvi
+% \\
+%   |\@@_struct_write_obj:n|
+% & |struct-no-objnum|
+% & error
+% & in struct module
+% \\
+%   |\tag_struct_begin:n|
+% & |struct-faulty-nesting|
+% & error
+% \\
+%   |\@@_struct_insert_annot:nn|
+% & |struct-faulty-nesting|
+% & error
+% \\
+%   |tag_struct_use:n|
+% & |struct-label-unknown|
+% &  warning
+% \\
+%   |attribute-class|, |attribute|
+% & |attr-unknown|
+% & error
+% \\
+%  |\@@_tree_fill_parenttree:|
+% & |tree-mcid-index-wrong|
+% & warning
+% TODO: should trigger a standard  rerun message.
+% \end{tabular}
+%
+% \normalsize
+% \subsection{Warning messages from the lua-code}
+% The messages are triggered if the log-level is at least equal to the number.
+%
+% \begin{tabular}[t]{>{\ttfamily}lll}
+% message & log-level & remark \\\hline
+% WARN TAG-NOT-TAGGED:       &1                   \\
+% WARN TAG-OPEN-MC:          &1                   \\
+% WARN SHIPOUT-MC-OPEN:      &1                    \\
+% WARN SHIPOUT-UPS:          &0 & shouldn't happen \\
+% WARN TEX-MC-INSERT-MISSING:&0 & shouldn't happen \\
+% WARN TEX-MC-INSERT-NO-KIDS:&2 & e.g. from empty hbox
+% \end{tabular}
+%
+% \subsection{Info messages from the lua-code}
+% The messages are triggered if the log-level is at least equal to the number.
+% |TAG| messages are from the traversing function, |TEX| from code used in the tagpdf-mc module.
+% |PARENTREE| is the code building the parenttree.
+%
+% \begin{longtable}{>{\ttfamily}lll}
+% message & log-level & remark \\\hline\endhead
+% INFO SHIPOUT-INSERT-LAST-EMC & 3 & finish of shipout code \\
+% INFO SPACE-FUNCTION-FONT     & 3 & interwordspace code \\
+% INFO TAG-ABSPAGE & 3  \\
+% INFO TAG-ARGS & 4     \\
+% INFO TAG-ENDHEAD & 4  \\
+% INFO TAG-ENDHEAD & 4  \\
+% INFO TAG-HEAD & 3     \\
+% INFO TAG-INSERT-ARTIFACT & 3  \\
+% INFO TAG-INSERT-BDC & 3  \\
+% INFO TAG-INSERT-EMC & 3  \\
+% INFO TAG-INSERT-TAG & 3  \\
+% INFO TAG-KERN-SUBTYPE & 4\\
+% INFO TAG-MATH-SUBTYPE & 4 \\
+% INFO TAG-MC-COMPARE & 4   \\
+% INFO TAG-MC-INTO-PAGE & 3 \\
+% INFO TAG-NEW-MC-NODE & 4  \\
+% INFO TAG-NODE & 3  \\
+% INFO TAG-NO-HEAD & 3 \\
+% INFO TAG-NOT-TAGGED & 2 & replaced by artifact\\
+% INFO TAG-QUITTING-BOX & 4 \\
+% INFO TAG-STORE-MC-KID & 4 \\
+% INFO TAG-TRAVERSING-BOX 3 \\
+% INFO TAG-USE-ACTUALTEXT & 3 \\
+% INFO TAG-USE-ALT & 3 \\
+% INFO TAG-USE-RAW & 3 \\
+% INFO TEX-MC-INSERT-KID & 3 \\
+% INFO TEX-MC-INSERT-KID-TEST & 4 \\
+% INFO TEX-MC-INTO-STRUCT & 3 \\
+% INFO TEX-STORE-MC-DATA & 3  \\
+% INFO TEX-STORE-MC-KID &  3  \\
+% INFO PARENTTREE-CHUNKS &  3 \\
+% INFO PARENTTREE-NO-DATA & 3\\
+% INFO PARENTTREE-NUM & 3 \\
+% INFO PARENTTREE-NUMENTRY & 3 \\
+% INFO PARENTTREE-STRUCT-OBJREF & 4
+% \end{longtable}
+
+% \end{documentation}
+% \begin{implementation}
 %    \begin{macrocode}
 %<@@=tag>
-%<*checks>
-\ProvidesExplPackage {tagpdf-checks-code} {2021-06-14} {0.82}
- {part of tagpdf - code related to checks and messages}
-
-
-%messages
-
-% mc
-\msg_new:nnn { tag } {mc-nested}        { nested~marked~content~found~-~mcid~#1 }
-\msg_new:nnn { tag } {mc-tag-missing}   { required~tag~missing~-~mcid~#1 }
-\msg_new:nnn { tag } {mc-label-unknown} { label~#1~unknown~-~rerun }
-\msg_new:nnn { tag } {mc-used-twice}    { mc~#1~has~been~already~used }
-\msg_new:nnn { tag } {mc-not-open}      { there~is~no~mc~to~end~at~#1 }
-\msg_new:nnn { tag } {mc-pushed}        { #1~has~been~pushed~to~the~mc~stack}
-\msg_new:nnn { tag } {mc-popped}        { #1~has~been~removed~from~the~mc~stack }
-
-% structures
-\msg_new:nnn { tag } {struct-no-objnum}      { objnum~missing~for~structure~#1 }
-\msg_new:nnn { tag } {struct-faulty-nesting} { there~is~no~open~structure~on~the~stack }
-\msg_new:nnn { tag } {struct-missing-tag}    { a~structure~must~have~a~tag! }
-\msg_new:nnn { tag } {struct-show-closing}   { closing~structure~#1~tagged~\prop_item:cn{g_@@_struct_#1_prop}{S} }
-\msg_new:nnn { tag } {struct-used-twice}     { structure~with~label~#1~has~already~been~used}
-\msg_new:nnn { tag } {struct-label-unknown}  { structure~with~label~#1~is~unknown~rerun}
-
-% attributes
+%<*header>
+\ProvidesExplPackage {tagpdf-checks-code} {2021-06-29} {0.9}
+ {part of tagpdf - code related to checks, conditionals, debugging and messages}
+%</header>
+%    \end{macrocode}
+% \section{Messages}
+% \subsection{Messages related to mc-chunks}
+% \begin{macro}{mc-nested}
+% This message is issue is a mc is opened before the previous has been closed.
+% This is not relevant for luamode, as the attributes don't care about this.
+% It is used in the |\@@_check_mc_if_nested:| test.
+%    \begin{macrocode}
+%<*package>
+\msg_new:nnn { tag } {mc-nested} { nested~marked~content~found~-~mcid~#1 }
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{mc-tag-missing}
+% If the tag is missing
+%    \begin{macrocode}
+\msg_new:nnn { tag } {mc-tag-missing} { required~tag~missing~-~mcid~#1 }
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{mc-label-unknown}
+% If the label of a mc that is used in another place is not known (yet)
+% or has been undefined as the mc was already used.
+%    \begin{macrocode}
+\msg_new:nnn { tag } {mc-label-unknown}
+  { label~#1~unknown~or~has~been~already~used.\\
+    Either~rerun~or~remove~one~of~the~uses. }
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{mc-used-twice}
+% An mc-chunk can be inserted only in one structure. This indicates wrong coding
+% and so should at least give a warning.
+%    \begin{macrocode}
+\msg_new:nnn { tag } {mc-used-twice} { mc~#1~has~been~already~used }
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{mc-not-open}
+% This is issued if a |\tag_mc_end:| is issued wrongly, wrong coding.
+%    \begin{macrocode}
+\msg_new:nnn { tag } {mc-not-open} { there~is~no~mc~to~end~at~#1 }
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{mc-pushed,mc-popped}
+% Informational messages about mc-pushing.
+%    \begin{macrocode}
+\msg_new:nnn { tag } {mc-pushed} { #1~has~been~pushed~to~the~mc~stack}
+\msg_new:nnn { tag } {mc-popped} { #1~has~been~removed~from~the~mc~stack }
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{mc-current}
+% Informational messages about current mc state.
+%    \begin{macrocode}
+\msg_new:nnn { tag } {mc-current}
+  { current~MC:~
+    \bool_if:NTF\g_@@_in_mc_bool
+      {abscnt=\@@_get_mc_abs_cnt:,~tag=\g_@@_mc_key_tag_tl}
+      {no~MC~open,~current~abscnt=\@@_get_mc_abs_cnt:"}
+  }
+%    \end{macrocode}
+% \end{macro}
+% \subsection{Messages related to mc-chunks}
+% \begin{macro}{struct-no-objnum}
+% Should not happen \ldots
+%    \begin{macrocode}
+\msg_new:nnn { tag } {struct-no-objnum} { objnum~missing~for~structure~#1 }
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{struct-faulty-nesting}
+% This indicates that there is somewhere one |\tag_struct_end:| too much.
+% This should be normally an error.
+%    \begin{macrocode}
+\msg_new:nnn { tag }
+  {struct-faulty-nesting}
+  { there~is~no~open~structure~on~the~stack }
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{struct-missing-tag}
+% A structure must have a tag.
+%    \begin{macrocode}
+\msg_new:nnn { tag } {struct-missing-tag} { a~structure~must~have~a~tag! }
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{struct-used-twice}
+%    \begin{macrocode}
+\msg_new:nnn { tag } {struct-used-twice}
+  { structure~with~label~#1~has~already~been~used}
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{struct-label-unknown}
+% label is unknown, typically needs a rerun.
+%    \begin{macrocode}
+\msg_new:nnn { tag } {struct-label-unknown}
+  { structure~with~label~#1~is~unknown~rerun}
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{struct-show-closing}
+% Informational message shown if log-mode is high enough
+%    \begin{macrocode}
+\msg_new:nnn { tag } {struct-show-closing}
+  { closing~structure~#1~tagged~\prop_item:cn{g_@@_struct_#1_prop}{S} }
+%    \end{macrocode}
+% \end{macro}
+%
+% \subsection{Attributes}
+% Not much yet, as attributes aren't used so much.
+% \begin{macro}{attr-unknown}
+%    \begin{macrocode}
 \msg_new:nnn { tag } {attr-unknown}  { attribute~#1~is~unknown}
-
-
-%Roles
+%    \end{macrocode}
+% \end{macro}
+%
+% \subsection{Roles}
+% \begin{macro}{role-missing,role-unknown,role-unknown-tag}
+% Warning message if either the tag or the role is missing
+%    \begin{macrocode}
 \msg_new:nnn { tag } {role-missing}     { tag~#1~has~no~role~assigned  }
 \msg_new:nnn { tag } {role-unknown}     { role~#1~is~not~known  }
 \msg_new:nnn { tag } {role-unknown-tag} { tag~#1~is~not~known  }
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{role-tag,new-tag}
+% Info messages.
+%    \begin{macrocode}
 \msg_new:nnn { tag } {role-tag}         { mapping~tag~#1~to~role~#2  }
 \msg_new:nnn { tag } {new-tag}          { adding~new~tag~#1 }
-
-
-% trees
-\msg_new:nnn { tag } {tree-mcid-index-wrong} {something~is~wrong~with~the~mcid}
-
-% obj
-\msg_new:nnn { tag } {obj-write-num} {write~obj~#1~to~pdf}
-
-% engine problem
-\msg_new:nnn { tag } {sys-no-interwordspace} {engine~#1~doesn't~support~the~interword~spaces}
-
-%checks
-%structures
-
-\cs_new:Nn \@@_check_structure_has_tag:n %#1 struct num %_protected?
+%    \end{macrocode}
+% \end{macro}
+%
+% \subsection{Miscellaneous}
+% \begin{macro}{tree-mcid-index-wrong}
+% Used in the tree code, typically indicates the document must be rerun.
+%    \begin{macrocode}
+\msg_new:nnn { tag } {tree-mcid-index-wrong}
+  {something~is~wrong~with~the~mcid--rerun}
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{sys-no-interwordspace}
+% Currently only pdflatex and lualatex have some support for real spaces.
+%    \begin{macrocode}
+\msg_new:nnn { tag } {sys-no-interwordspace}
+  {engine/output~mode~#1~doesn't~support~the~interword~spaces}
+%    \end{macrocode}
+% \end{macro}
+% \section{Retrieving data}
+% \begin{macro}[EXP]{\tag_get:n}
+% This retrieves some data.
+% This is a generic command to retrieve data. Currently
+% the only sensible values for the argument are |mc_tag| and |struct_tag|.
+%    \begin{macrocode}
+\cs_new:Npn \tag_get:n #1   { \use:c {@@_get_data_#1: } }
+%    \end{macrocode}
+% \end{macro}
+%
+% \section{User conditionals}
+% \begin{macro}[pTF]{\tag_if_active:}
+% This is a test it tagging is active. This allows packages
+% to add conditional code.
+% The test is true if all booleans, the global and the two local one are true.
+%
+%    \begin{macrocode}
+\prg_new_conditional:Npnn \tag_if_active: { p , T , TF, F }
   {
+     \bool_lazy_all:nTF
+       {
+         {\g_@@_active_struct_bool}
+         {\g_@@_active_mc_bool}
+         {\g_@@_active_tree_bool}
+         {\l_@@_active_struct_bool}
+         {\l_@@_active_mc_bool}
+       }
+       {
+         \prg_return_true:
+       }
+       {
+         \prg_return_false:
+       }
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \section{Internal checks}
+% These are checks used in various places in the code.
+%
+% \subsection{checks for active tagging}
+% \begin{macro}[TF]{\@@_check_if_active_mc:,\@@_check_if_active_struct:}
+% Structures must have a tag, so we check if the S entry is in the property.
+% It is an error if this is missing. The argument is a number.
+%    \begin{macrocode}
+\prg_new_conditional:Npnn \@@_check_if_active_mc: {T,F,TF}
+  {
+    \bool_lazy_and:nnTF { \g_@@_active_mc_bool } { \l_@@_active_mc_bool }
+      {
+         \prg_return_true:
+      }
+      {
+         \prg_return_false:
+      }
+  }
+\prg_new_conditional:Npnn \@@_check_if_active_struct: {T,F,TF}
+  {
+    \bool_lazy_and:nnTF { \g_@@_active_struct_bool } { \l_@@_active_struct_bool }
+      {
+         \prg_return_true:
+      }
+      {
+         \prg_return_false:
+      }
+  }
+%    \end{macrocode}
+% \end{macro}
+% \subsection{Checks related to stuctures}
+% \begin{macro}{\@@_check_structure_has_tag:n}
+% Structures must have a tag, so we check if the S entry is in the property.
+% It is an error if this is missing. The argument is a number.
+% The tests for existence and type is split in structures,
+% as the tags are stored differently to the mc case.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_check_structure_has_tag:n #1 %#1 struct num
+  {
     \prop_if_in:cnF { g_@@_struct_#1_prop }
       {S}
       {
@@ -82,8 +465,13 @@
         \msg_error:nn { tag } {struct-missing-tag}
       }
   }
-
-\cs_new:Nn \@@_check_structure_tag:N            %_protected?
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{\@@_check_structure_tag:N}
+% This checks if the name of the tag is known,
+% either because it is a standard type or has been rolemapped.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_check_structure_tag:N #1
   {
     \prop_if_in:NoF \g_@@_role_tags_prop {#1}
       {
@@ -90,29 +478,37 @@
         \msg_warning:nnx { tag } {role-unknown-tag} {#1}
       }
   }
-
-\cs_new:Nn \@@_check_structure_tag:NN            %_protected?
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{\@@_check_info_closing_struct:n}
+% This info message is issued at a closing structure, the use should be guarded by
+% log-level.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_check_info_closing_struct:n #1 %#1 struct num
   {
-    \exp_args:NNx
-    \prop_if_in:NnF \g_@@_role_tags_prop {#1/#2}
+    \int_compare:nNnT {\l_@@_loglevel_int} > { 0 }
       {
-        \msg_warning:nnx { tag } {role-unknown-tag} {#1}
+        \msg_info:nnn { tag } {struct-show-closing} {#1}
       }
   }
 
-\cs_new_protected:Nn \@@_check_info_closing_struct:n %#1 struct num
-  {
-    \msg_info:nnn { tag } {struct-show-closing} {#1}
-  }
-
 \cs_generate_variant:Nn \@@_check_info_closing_struct:n {o,x}
-
-\cs_new_protected:Nn \@@_check_no_open_struck:
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{\@@_check_no_open_struct:}
+% This checks if there is an open structure. It should be used when trying to
+% close a structure. It errors if false.%
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_check_no_open_struct:
   {
     \msg_error:nn { tag } {struct-faulty-nesting}
   }
-
-\cs_new_protected:Nn \@@_check_struct_used:n %#1 label
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{\@@_check_struct_used:n}
+% This checks if a stashed structure has already been used.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_check_struct_used:n #1 %#1 label
   {
     \prop_get:cnNT
       {g_@@_struct_\@@_ref_value:enn{tagpdfstruct-#1}{tagstruct}{unknown}_prop}
@@ -122,10 +518,14 @@
         \msg_warning:nnn { tag } {struct-used-twice} {#1}
       }
   }
-
-%roles
-
-\cs_new_protected:Nn \@@_check_add_tag_role:nn %#1 tag, #2 role
+%    \end{macrocode}
+% \end{macro}
+%
+% \subsection{Checks related to roles}
+% \begin{macro}{\@@_check_add_tag_role:nn}
+% This check is used when defining a new role mapping.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_check_add_tag_role:nn #1 #2 %#1 tag, #2 role
   {
     \tl_if_empty:nTF {#2}
       {
@@ -134,7 +534,10 @@
       {
         \prop_get:NnNTF \g_@@_role_tags_prop {#2} \l_tmpa_tl
           {
-            \msg_info:nnnn { tag } {role-tag} {#1} {#2}
+            \int_compare:nNnT {\l_@@_loglevel_int} > { 0 }
+              {
+                \msg_info:nnnn { tag } {role-tag} {#1} {#2}
+              }
           }
           {
             \msg_warning:nnn { tag } {role-unknown} {#2}
@@ -141,9 +544,16 @@
           }
       }
   }
-
-%mc
-\cs_new_protected:Nn \@@_check_mc_if_nested:
+%    \end{macrocode}
+% \end{macro}
+%
+% \subsection{Check related to mc-chunks}
+%
+% \begin{macro}{\@@_check_mc_if_nested:,\@@_check_mc_if_open:}
+% Two tests if a mc is currently open. One for the true (for begin
+% code),  one for the false part (for end code).
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_check_mc_if_nested:
   {
     \@@_mc_if_in:T
       {
@@ -151,7 +561,7 @@
       }
   }
 
-\cs_new_protected:Nn \@@_check_mc_if_open:
+\cs_new_protected:Npn \@@_check_mc_if_open:
   {
     \@@_mc_if_in:F
       {
@@ -158,8 +568,14 @@
         \msg_warning:nnx { tag } {mc-not-open} { \@@_get_mc_abs_cnt: }
       }
   }
-
-\cs_new_protected:Nn \@@_check_mc_pushed_popped:nn
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{\@@_check_mc_pushed_popped:nn}
+% This creates an information message if mc's are pushed or popped.
+% The first argument is a word (pushed or popped), the second the tag name.
+% With larger log-level the stack is shown too.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_check_mc_pushed_popped:nn #1 #2
   {
     \int_compare:nNnT
       { \l_@@_loglevel_int } ={ 2 }
@@ -167,13 +583,16 @@
     \int_compare:nNnT
       { \l_@@_loglevel_int } > { 2 }
       {
-       \msg_warning:nnx {tag}{mc-#1}{#2}
-       \seq_log:N \g_@@_mc_stack_seq
+        \msg_info:nnx {tag}{mc-#1}{#2}
+        \seq_log:N \g_@@_mc_stack_seq
       }
   }
-
-
-\cs_new:Nn \@@_check_mc_tag:N %protected??
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{\@@_check_mc_tag:N}
+% This checks if the mc has a (known) tag.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_check_mc_tag:N #1  %#1 is var with a tag name in it
   {
     \tl_if_empty:NT #1
       {
@@ -184,22 +603,56 @@
        \msg_warning:nnx { tag } {role-unknown-tag} {#1}
      }
   }
-
-\seq_new:N \g_@@_check_mc_used_seq
-\cs_new_protected:Nn \@@_check_mc_used:n
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{variable}{\g_@@_check_mc_used_intarray, \@@_check_init_mc_used:}
+% This variable holds the list of used mc numbers.
+% Everytime we store a mc-number we will add one the relevant array index
+% If everything is right at the end there should be only 1 until the max count
+% of the mcid. 2 indicates that one mcid was used twice, 0 that we lost one.
+% In engines other than luatex the total number of all intarray entries
+% are restricted so we use only  a rather small value of 65536, and we initialize
+% the array only at first used, guarded by the log-level.
+% This check is probably only needed for debugging.
+% TODO does this really make sense to check? When can it happen??
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_check_init_mc_used:
   {
-    \seq_if_in:NnTF \g_@@_check_mc_used_seq {#1}
+    \intarray_new:Nn \g_@@_check_mc_used_intarray { 65536 }
+    \cs_gset_eq:NN \@@_check_init_mc_used: \prg_do_nothing:
+  }
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{macro}{\@@_check_mc_used:n}
+% This checks if a mc is used twice.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_check_mc_used:n #1 %#1 mcid abscnt
+  {
+    \int_compare:nNnT {\l_@@_loglevel_int} > { 2 }
       {
-        \msg_warning:nnn { tag } {mc-used-twice} {#1}
+        \@@_check_init_mc_used:
+        \intarray_gset:Nnn \g_@@_check_mc_used_intarray
+          {#1}
+          { \intarray_item:Nn \g_@@_check_mc_used_intarray {#1} + 1 }
+        \int_compare:nNnT
+          {
+            \intarray_item:Nn \g_@@_check_mc_used_intarray {#1}
+          }
+          >
+          { 1 }
+          {
+            \msg_warning:nnn { tag } {mc-used-twice} {#1}
+          }
       }
-      {
-        \seq_gput_right:Nx \g_@@_check_mc_used_seq {#1}
-      }
   }
-
-
-
-\cs_new_protected:Nn \@@_check_show_MCID_by_page:
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{\@@_check_show_MCID_by_page:}
+% This allows to show the mc on a page. Currently unused.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_check_show_MCID_by_page:
   {
     \tl_set:Nx \l_@@_tmpa_tl
       {
@@ -245,14 +698,10 @@
           \seq_show:N \l_tmpa_seq
       }
   }
-
-\cs_new:Nn \@@_check_record_pdfobj_num:n %protected?
-  {
-    \int_compare:nT { \l_@@_loglevel_int >= 3 }
-      {
-        \msg_info:nnx { tag } {obj-write-num} {#1}
-      }
-  }
-
-%</checks>
 %    \end{macrocode}
+% \end{macro}
+%    \begin{macrocode}
+%</package>
+%    \end{macrocode}
+% \end{implementation}
+% \PrintIndex

Added: trunk/Master/texmf-dist/source/latex/tagpdf/tagpdf-mc-generic.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/tagpdf/tagpdf-mc-generic.dtx	                        (rev 0)
+++ trunk/Master/texmf-dist/source/latex/tagpdf/tagpdf-mc-generic.dtx	2021-06-30 21:14:14 UTC (rev 59769)
@@ -0,0 +1,389 @@
+% \iffalse meta-comment
+%
+%% File: tagpdf-mc.dtx
+%
+% Copyright (C) 2019-2021 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/u-fischer/tagpdf
+%
+% for those people who are interested.
+%<*driver>
+\RequirePackage{pdfmanagement-testphase}
+\DeclareDocumentMetadata{}
+\makeatletter
+\declare at file@substitution{doc.sty}{doc-v3beta.sty}
+\makeatother
+\documentclass{l3doc}
+\usepackage{array,booktabs,caption}
+\hypersetup{pdfauthor=Ulrike Fischer,
+ pdftitle=tagpdf-mc module (tagpdf)}
+\begin{document}
+  \DocInput{\jobname.dtx}
+\end{document}
+%</driver>
+% \fi
+% \title{^^A
+%   The \pkg{tagpdf-mc-generic} module\\ Code related to Marked Content (mc-chunks), generic mode  ^^A
+%   \\ Part of the tagpdf package
+% }
+%
+% \author{^^A
+%  Ulrike Fischer\thanks
+%    {^^A
+%      E-mail:
+%        \href{mailto:fischer at troubleshooting-tex.de}
+%          {fischer at troubleshooting-tex.de}^^A
+%    }^^A
+% }
+%
+% \date{Version 0.9, released 2021-06-29}
+% \maketitle
+% \begin{implementation}
+% \section{Marked content code -- generic mode}
+%    \begin{macrocode}
+%<@@=tag>
+%<*generic>
+\ProvidesExplPackage {tagpdf-mc-code-generic} {2021-06-29} {0.9}
+ {part of tagpdf - code related to marking chunks - generic mode}
+%</generic>
+%    \end{macrocode}
+% \subsection{Variables}
+% \begin{variable}{\g_@@_in_mc_bool}
+% This booleans records if a mc is open, to test nesting.
+%    \begin{macrocode}
+%<*generic>
+\bool_new:N \g_@@_in_mc_bool
+%    \end{macrocode}
+% \end{variable}
+
+% \begin{variable}{\g_@@_MCID_byabspage_prop}
+% This property will hold the current maximum on a page
+% it will contain key-value of type \meta{abspagenum}=\meta{max mcid}
+%
+%    \begin{macrocode}
+\@@_prop_new:N \g_@@_MCID_byabspage_prop
+%    \end{macrocode}
+% \end{variable}
+
+% \begin{variable}{\l_@@_mc_ref_abspage_tl}
+% We need a ref-label system to ensure that the MCID cnt
+% restarts at 0 on a new page
+% This will be used to store the tagabspage attribute retrieved from
+% a label.
+%    \begin{macrocode}
+\tl_new:N \l_@@_mc_ref_abspage_tl
+%    \end{macrocode}
+% \end{variable}
+
+% \begin{variable}{\l_@@_mc_tmpa_tl}
+% temporary variable
+%    \begin{macrocode}
+\tl_new:N \l_@@_mc_tmpa_tl
+%    \end{macrocode}
+% \end{variable}
+
+% \subsection{Functions}
+
+% \begin{macro}[pTF]{\@@_mc_if_in:,\tag_mc_if_in:}
+% This is a test if a mc is open or not. It depends simply on a global boolean:
+% mc-chunks are added linearly so nesting should not be relevant.
+%    \begin{macrocode}
+\prg_new_conditional:Nnn \@@_mc_if_in: {p,T,F,TF}
+  {
+    \bool_if:NTF \g_@@_in_mc_bool
+      { \prg_return_true:  }
+      { \prg_return_false: }
+  }
+
+\prg_new_eq_conditional:NNn \tag_mc_if_in: \@@_mc_if_in: {p,T,F,TF}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{ \@@_mc_bmc:n,\@@_mc_emc:,\@@_mc_bdc:nn,\@@_mc_bdc:nx}
+% These are the low-level commands. There are now equal to the
+% pdfmanagement commands generic mode, but we use an indirection
+% in case luamode need something else.
+% change 04.08.2018: the commands do not check the validity of the arguments or try
+% to escape them, this should be done before using them.
+%    \begin{macrocode}
+% #1 tag, #2 properties
+\cs_set_eq:NN \@@_mc_bmc:n  \pdf_bmc:n
+\cs_set_eq:NN \@@_mc_emc:   \pdf_emc:
+\cs_set_eq:NN \@@_mc_bdc:nn \pdf_bdc:nn
+\cs_generate_variant:Nn \@@_mc_bdc:nn {nx}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}
+%   {
+%     \@@_mc_bdc_mcid:nn,\@@_mc_bdc_mcid:n,
+%     \@@_mc_handle_mcid:nn,\@@_mc_handle_mcid:VV
+%   }
+%
+% This create a BDC mark with an |/MCID| key. Most of the work here is to get
+% the current number value for the MCID: they must be numbered by page
+% starting with 0 and then successively.
+% The first argument is the tag, e.g. |P| or |Span|, the second is used to pass
+% more properties.
+% We also define a wrapper around the low-level command as luamode will need
+% something different.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_mc_bdc_mcid:nn #1 #2
+  {
+    \int_gincr:N \c at g_@@_MCID_abs_int
+    \tl_set:Nx \l_@@_mc_ref_abspage_tl
+      {
+        \@@_ref_value:enn %3 args
+          {
+            mcid-\int_use:N \c at g_@@_MCID_abs_int
+          }
+          { tagabspage }
+          {-1}
+      }
+    \prop_get:NoNTF
+      \g_@@_MCID_byabspage_prop
+      {
+        \l_@@_mc_ref_abspage_tl
+      }
+      \l_@@_mc_tmpa_tl
+      {
+        %key already present, use value for MCID and add 1 for the next
+        \int_gset:Nn \g_@@_MCID_tmp_bypage_int { \l_@@_mc_tmpa_tl }
+        \@@_prop_gput:Nxx
+          \g_@@_MCID_byabspage_prop
+          { \l_@@_mc_ref_abspage_tl }
+          { \int_eval:n {\l_@@_mc_tmpa_tl +1} }
+      }
+      {
+        %key not present, set MCID to 0 and insert 1
+        \int_gzero:N \g_@@_MCID_tmp_bypage_int
+        \@@_prop_gput:Nxx
+          \g_@@_MCID_byabspage_prop
+          { \l_@@_mc_ref_abspage_tl }
+          {1}
+      }
+    \@@_ref_label:en
+      {
+        mcid-\int_use:N \c at g_@@_MCID_abs_int
+      }
+      { mc }
+     \@@_mc_bdc:nx
+       {#1}
+       { /MCID~\int_eval:n { \g_@@_MCID_tmp_bypage_int }~ \exp_not:n { #2 } }
+ }
+\cs_new_protected:Npn \@@_mc_bdc_mcid:n #1
+  {
+    \@@_mc_bdc_mcid:nn {#1} {}
+  }
+
+\cs_new_protected:Npn \@@_mc_handle_mcid:nn #1 #2 %#1 tag, #2 properties
+  {
+    \@@_mc_bdc_mcid:nn {#1} {#2}
+  }
+
+\cs_generate_variant:Nn \@@_mc_handle_mcid:nn {VV}
+%    \end{macrocode}
+% \end{macro}
+
+% \begin{macro}{\@@_mc_handle_stash:n,\@@_mc_handle_stash:x}
+% This is the handler which puts a mc into the
+% the current structure. The argument is the number of the mc.
+% Beside storing the mc into the structure, it also has to record the
+% structure for the parent tree.
+% The name is a bit confusing, it does \emph{not} handle mc with the stash key
+% \ldots.
+% TODO: why does luamode use it for begin + use, but generic mode only for begin?
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_mc_handle_stash:n #1 %1 mcidnum
+  {
+    \@@_check_mc_used:n {#1}
+    \@@_struct_kid_mc_gput_right:nn
+      { \g_@@_struct_stack_current_tl }
+      {#1}
+   \prop_gput:Nxx \g_@@_mc_parenttree_prop
+     {#1}
+     { \g_@@_struct_stack_current_tl }
+  }
+\cs_generate_variant:Nn \@@_mc_handle_stash:n { x }
+%    \end{macrocode}
+% \end{macro}
+
+% \begin{macro}
+%  {
+%    \@@_mc_bmc_artifact:,
+%    \@@_mc_bmc_artifact:n,
+%    \@@_mc_handle_artifact:N
+%   }
+% Two commands to create artifacts, one without type, and one with.
+% We define also a wrapper handler as luamode will need a different definition.
+% TODO: perhaps later: more properties for artifacts
+%    \begin{macrocode}
+\cs_new_protected:Npn  \@@_mc_bmc_artifact:
+  {
+    \@@_mc_bmc:n {Artifact}
+  }
+\cs_new_protected:Npn \@@_mc_bmc_artifact:n #1
+  {
+    \@@_mc_bdc:nn {Artifact}{/Type/#1}
+  }
+\cs_new_protected:Npn \@@_mc_handle_artifact:N #1
+   % #1 is a var containing the artifact type
+  {
+    \tl_if_empty:NTF #1
+      { \@@_mc_bmc_artifact: }
+      { \exp_args:NV\@@_mc_bmc_artifact:n #1 }
+  }
+%    \end{macrocode}
+% \end{macro}
+
+% \begin{macro}{ \@@_get_data_mc_tag: }
+% This allows to retrieve the active mc-tag.
+% It is use by the get command.
+%    \begin{macrocode}
+\cs_new:Nn \@@_get_data_mc_tag: { \g_@@_mc_key_tag_tl }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\tag_mc_begin:n,\tag_mc_end:}
+% These are the core public commands to open and close an mc.
+% They don't need to be in the same group or grouping level,
+% but the code expect that they are issued linearly. The tag and
+% the state is passed to the end command through a global var and
+% a global boolean.
+%    \begin{macrocode}
+\cs_new_protected:Npn \tag_mc_begin:n #1 %#1 keyval
+  {
+    \@@_check_if_active_mc:T
+      {
+        \group_begin: %hm
+        \@@_check_mc_if_nested:
+        \bool_gset_true:N \g_@@_in_mc_bool
+        \keys_set:nn { @@ / mc } {#1}
+        \bool_if:NTF \l_@@_mc_artifact_bool
+          { %handle artifact
+            \@@_mc_handle_artifact:N \l_@@_mc_artifact_type_tl
+          }
+          { %handle mcid type
+            \@@_check_mc_tag:N  \l_@@_mc_key_tag_tl
+            \@@_mc_handle_mcid:VV
+               \l_@@_mc_key_tag_tl
+               \l_@@_mc_key_properties_tl
+            \tl_if_empty:NF {\l_@@_mc_key_label_tl}
+              {
+                \exp_args:NV
+                \@@_mc_handle_mc_label:n \l_@@_mc_key_label_tl
+              }
+            \bool_if:NF \l_@@_mc_key_stash_bool
+              {
+                \@@_mc_handle_stash:x { \int_use:N \c at g_@@_MCID_abs_int }
+              }
+          }
+        \group_end:
+      }
+  }
+\cs_new_protected:Nn \tag_mc_end:
+  {
+    \@@_check_if_active_mc:T
+      {
+        \@@_check_mc_if_open:
+        \bool_gset_false:N \g_@@_in_mc_bool
+        \tl_gset:Nn  \g_@@_mc_key_tag_tl { }
+        \@@_mc_emc:
+      }
+  }
+%    \end{macrocode}
+% \end{macro}
+
+%
+% \subsection{Keys}
+% Definitions are different in luamode.
+% |tag| and |raw| are expanded as |\lua_now:e| in lua does it too and
+% we assume that their values are safe.
+% \begin{macro}
+%  {
+%   tag,raw,
+%   alttext,alttext-o,
+%   actualtext,actualtext-o,
+%   label,artifact
+%  }
+%    \begin{macrocode}
+\keys_define:nn { @@ / mc }
+  {
+    tag .code:n = % the name (H,P,Span) etc
+      {
+        \tl_set:Nx   \l_@@_mc_key_tag_tl { #1 }
+        \tl_gset:Nx  \g_@@_mc_key_tag_tl { #1 }
+      },
+    raw  .code:n =
+      {
+        \tl_put_right:Nx \l_@@_mc_key_properties_tl { #1 }
+      },
+    alttext .code:n = % Alt property
+      {
+        \str_set_convert:Nnon
+          \l_@@_tmpa_str
+          { #1 }
+          { default }
+          { utf16/hex }
+        \tl_put_right:Nn \l_@@_mc_key_properties_tl { /Alt~< }
+        \tl_put_right:No \l_@@_mc_key_properties_tl { \l_@@_tmpa_str>~ }
+      },
+    alttext-o .code:n      = % Alt property
+      {
+        \str_set_convert:Noon
+          \l_@@_tmpa_str
+          { #1 }
+          { default }
+          { utf16/hex }
+        \tl_put_right:Nn \l_@@_mc_key_properties_tl { /Alt~< }
+        \tl_put_right:No \l_@@_mc_key_properties_tl { \l_@@_tmpa_str>~ }
+      },
+    actualtext .code:n      = % ActualText property
+      {
+        \str_set_convert:Nnon
+          \l_@@_tmpa_str
+          { #1 }
+          { default }
+          { utf16/hex }
+        \tl_put_right:Nn \l_@@_mc_key_properties_tl { /ActualText~< }
+        \tl_put_right:No \l_@@_mc_key_properties_tl { \l_@@_tmpa_str>~ }
+      },
+    actualtext-o .code:n      = % ActualText property
+      {
+        \str_set_convert:Noon
+          \l_@@_tmpa_str
+          { #1 }
+          { default }
+          { utf16/hex }
+        \tl_put_right:Nn \l_@@_mc_key_properties_tl { /ActualText~< }
+        \tl_put_right:No \l_@@_mc_key_properties_tl { \l_@@_tmpa_str>~ }
+      },
+    label .tl_set:N        = \l_@@_mc_key_label_tl,
+    artifact .code:n       =
+      {
+        \exp_args:Nnx
+          \keys_set:nn
+            { @@ / mc }
+            { __artifact-bool, __artifact-type=#1 }
+      },
+    artifact .default:n    = {notype}
+  }
+%</generic>
+%    \end{macrocode}
+% \end{macro}
+% \end{implementation}
+% \PrintIndex


Property changes on: trunk/Master/texmf-dist/source/latex/tagpdf/tagpdf-mc-generic.dtx
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/source/latex/tagpdf/tagpdf-mc-luacode.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/tagpdf/tagpdf-mc-luacode.dtx	                        (rev 0)
+++ trunk/Master/texmf-dist/source/latex/tagpdf/tagpdf-mc-luacode.dtx	2021-06-30 21:14:14 UTC (rev 59769)
@@ -0,0 +1,490 @@
+% \iffalse meta-comment
+%
+%% File: tagpdf-mc.dtx
+%
+% Copyright (C) 2019-2021 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/u-fischer/tagpdf
+%
+% for those people who are interested.
+%<*driver>
+\RequirePackage{pdfmanagement-testphase}
+\DeclareDocumentMetadata{}
+\makeatletter
+\declare at file@substitution{doc.sty}{doc-v3beta.sty}
+\makeatother
+\documentclass{l3doc}
+\usepackage{array,booktabs,caption}
+\hypersetup{pdfauthor=Ulrike Fischer,
+ pdftitle=tagpdf-mc module (tagpdf)}
+\begin{document}
+  \DocInput{\jobname.dtx}
+\end{document}
+%</driver>
+% \fi
+% \title{^^A
+%   The \pkg{tagpdf-mc-luacode} module\\ Code related to Marked Content (mc-chunks), luamode-specific  ^^A
+%   \\ Part of the tagpdf package
+% }
+%
+% \author{^^A
+%  Ulrike Fischer\thanks
+%    {^^A
+%      E-mail:
+%        \href{mailto:fischer at troubleshooting-tex.de}
+%          {fischer at troubleshooting-tex.de}^^A
+%    }^^A
+% }
+%
+% \date{Version 0.9, released 2021-06-29}
+% \maketitle
+
+% \begin{implementation}
+% The code is splitted into three parts: code shared by all engines,
+% code specific to luamode and code not used by luamode.
+%
+% \section{Marked content code -- luamode code}
+% luamode uses attributes to mark mc-chunks. The two attributes used are
+% defined in the backend file. The backend also load the lua file, as it can contain
+% functions needed elsewhere.
+% The attributes for mc are global (between 0.6 and 0.81 they were local but this
+% was reverted). The attributes are setup only in lua, and one should use
+% the lua functions to set and get them.\\
+% |g_@@_mc_type_attr|:  the value represent the type\\
+% |g_@@_mc_cnt_attr|:   will hold the |\c at g_@@_MCID_abs_int value|
+%
+% Handling attribute needs a different system to number the page wise mcid's:
+% a |\tagmcbegin ... \tagmcend| pair no longer surrounds exactly one mc chunk:
+% it can be split at page breaks.
+% We know the included mcid(s) only after the ship out.
+% So for the |struct -> mcid| mapping we
+% need to record |struct -> mc-cnt| (in |\g_@@_mc_parenttree_prop| and/or a lua table
+% and at shipout |mc-cnt-> {mcid, mcid, ...}|
+% and when building the trees connect both.
+%
+% Key definitions are overwritten for luatex to store that data in lua-tables.
+% The data for the mc are in |ltx.@@.mc[absnum]|.
+% The fields of the table are:\\
+% tag : the type (a string)\\
+% raw : more properties (string)\\
+% label: a string. \\
+% artifact: the presence indicates an artifact, the value (string) is the type.\\
+% kids: a array of tables\\
+% |{1={kid=num2,page=pagenum1}, 2={kid=num2,page=pagenum2},...}|,\\
+% this describes the chunks the mc has been split to by the traversing code\\
+% parent: the number of the structure it is in. Needed to build the parent tree.
+%
+%    \begin{macrocode}
+%<@@=tag>
+%<*luamode>
+\ProvidesExplPackage {tagpdf-mc-code-lua} {2021-06-29} {0.9}
+  {tagpdf - mc code only for the luamode }
+%</luamode>
+%    \end{macrocode}
+% The main function which wanders through the shipout box to inject the literals.
+% if the new callback is there, it is used.
+%    \begin{macrocode}
+%<*luamode>
+\hook_gput_code:nnn{begindocument}{tagpdf/mc}
+  {
+    \bool_if:NT\g__tag_active_space_bool
+      {
+        \lua_now:e
+          {
+           if~luatexbase.callbacktypes.pre_shipout_filter~then~
+              luatexbase.add_to_callback("pre_shipout_filter", function(TAGBOX)~
+              ltx.@@.func.space_chars_shipout(TAGBOX)~return~true~
+              end, "tagpdf")~
+            end
+          }
+       \lua_now:e
+         {
+           if~luatexbase.callbacktypes.pre_shipout_filter~then~
+           token.get_next()~
+           end
+         }\@secondoftwo\@gobble
+           {
+             \hook_gput_code:nnn{shipout/before}{tagpdf/lua}
+               {
+                \lua_now:e
+                   { ltx.@@.func.space_chars_shipout (tex.box["ShipoutBox"]) }
+               }
+           }
+      }
+    \bool_if:NT\g__tag_active_mc_bool
+      {
+        \lua_now:e
+          {
+            if~luatexbase.callbacktypes.pre_shipout_filter~then~
+              luatexbase.add_to_callback("pre_shipout_filter", function(TAGBOX)~
+              ltx.@@.func.mark_shipout(TAGBOX)~return~true~
+              end, "tagpdf")~
+            end
+          }
+       \lua_now:e
+         {
+           if~luatexbase.callbacktypes.pre_shipout_filter~then~
+           token.get_next()~
+           end
+         }\@secondoftwo\@gobble
+           {
+             \hook_gput_code:nnn{shipout/before}{tagpdf/lua}
+               {
+                 \lua_now:e
+                   { ltx.@@.func.mark_shipout (tex.box["ShipoutBox"]) }
+               }
+           }
+      }
+  }
+%    \end{macrocode}
+% \subsection{Commands}
+% \begin{macro}{\@@_mc_if_in:,\tag_mc_if_in:}
+% This tests, if we are in an mc, for attributes
+% this means to check against a number.
+%    \begin{macrocode}
+\prg_new_conditional:Nnn \@@_mc_if_in: {p,T,F,TF}
+  {
+    \int_compare:nNnTF
+      { -2147483647 }
+      =
+      {\lua_now:e
+         {
+           tex.print(tex.getattribute(luatexbase.attributes.g__tag_mc_type_attr))
+         }
+      }
+      { \prg_return_false:  }
+      { \prg_return_true: }
+  }
+
+\prg_new_eq_conditional:NNn \tag_mc_if_in: \@@_mc_if_in: {p,T,F,TF}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}
+%  {
+%     \@@_mc_lua_set_mc_type_attr:n
+%    ,\@@_mc_lua_set_mc_type_attr:o
+%    ,\@@_mc_lua_unset_mc_type_attr:
+%  }
+% This takes a tag name, and sets the attributes to the related number.
+% It is not decided yet if this will be global or local, see the global-mc option.
+%    \begin{macrocode}
+\cs_new:Nn \@@_mc_lua_set_mc_type_attr:n % #1 is a tag name
+  {
+    %TODO ltx.@@.func.get_num_from("#1") seems not to return a suitable number??
+    \tl_set:Nx\l_@@_tmpa_tl{\lua_now:e{ltx.@@.func.output_num_from ("#1")} }
+    \lua_now:e
+      {
+        tex.setattribute
+         (
+          "global",
+          luatexbase.attributes.g_@@_mc_type_attr,
+          \l_@@_tmpa_tl
+         )
+      }
+    \lua_now:e
+      {
+        tex.setattribute
+         (
+           "global",
+           luatexbase.attributes.g_@@_mc_cnt_attr,
+           \@@_get_mc_abs_cnt:
+         )
+      }
+  }
+
+\cs_generate_variant:Nn\@@_mc_lua_set_mc_type_attr:n { o }
+
+\cs_new:Nn \@@_mc_lua_unset_mc_type_attr:
+  {
+    \lua_now:e
+      {
+        tex.setattribute
+          (
+            "global",
+            luatexbase.attributes.g_@@_mc_type_attr,
+            -2147483647
+          )
+      }
+     \lua_now:e
+      {
+        tex.setattribute
+          (
+            "global",
+            luatexbase.attributes.g_@@_mc_cnt_attr,
+            -2147483647
+          )
+      }
+  }
+
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}
+%  {
+%    \@@_mc_insert_mcid_kids:n
+%   ,\@@_mc_insert_mcid_single_kids:n
+%  }
+% These commands will in the finish code replace the dummy for a mc by the real mcid kids
+% we need a variant for the case that it is the only kid, to get the array right
+%    \begin{macrocode}
+\cs_new:Nn \@@_mc_insert_mcid_kids:n
+  {
+    \lua_now:e { ltx.@@.func.mc_insert_kids (#1,0) }
+  }
+
+\cs_new:Nn \@@_mc_insert_mcid_single_kids:n
+  {
+    \lua_now:e {ltx.@@.func.mc_insert_kids (#1,1) }
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+%\begin{macro}{\@@_mc_handle_stash:n,\@@_mc_handle_stash:x}
+% This is the lua variant for the command to
+% put an mcid absolute number in the current structure.
+%    \begin{macrocode}
+\cs_new:Nn \@@_mc_handle_stash:n %1 mcidnum
+  {
+    \@@_check_mc_used:n { #1 }
+    \seq_gput_right:cn % Don't fill a lua table due to the command in the item,
+                       % so use the kernel command
+      { g_@@_struct_kids_\g_@@_struct_stack_current_tl _seq }
+      {
+        \@@_mc_insert_mcid_kids:n {#1}%
+      }
+    \lua_now:e
+      {
+        ltx.@@.func.store_struct_mcabs
+          (
+            \g_@@_struct_stack_current_tl,#1
+          )
+      }
+    \prop_gput:Nxx
+      \g_@@_mc_parenttree_prop
+      { #1 }
+      { \g_@@_struct_stack_current_tl }
+  }
+
+\cs_generate_variant:Nn \@@_mc_handle_stash:n { x }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\tag_mc_begin:n}
+% This is the lua version of the user command.
+% We currently don't check if there is nesting as it doesn't matter so
+% much in lua.
+%    \begin{macrocode}
+\cs_new_protected:Nn \tag_mc_begin:n
+  {
+    \@@_check_if_active_mc:T
+      {
+        \group_begin:
+        %\@@_check_mc_if_nested:
+        \bool_gset_true:N \g_@@_in_mc_bool
+        \bool_set_false:N\l_@@_mc_artifact_bool
+        \tl_clear:N \l_@@_mc_key_properties_tl
+        \int_gincr:N \c at g_@@_MCID_abs_int
+        \keys_set:nn { @@ / mc }{ label={}, #1 }
+        %check that a tag or artifact has been used
+        \@@_check_mc_tag:N \l_@@_mc_key_tag_tl
+        %set the attributes:
+        \@@_mc_lua_set_mc_type_attr:o  { \l_@@_mc_key_tag_tl }
+        \bool_if:NF \l_@@_mc_artifact_bool
+          { % store the absolute num name in a label:
+            \tl_if_empty:NF {\l_@@_mc_key_label_tl}
+              {
+                \exp_args:NV
+                 \@@_mc_handle_mc_label:n  \l_@@_mc_key_label_tl
+              }
+           % if not stashed record the absolute number
+            \bool_if:NF \l_@@_mc_key_stash_bool
+              {
+                \@@_mc_handle_stash:x { \@@_get_mc_abs_cnt: }
+              }
+          }
+        \group_end:
+     }
+  }
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{\tag_mc_end:}
+%
+% TODO: check how the use command must be guarded.
+%    \begin{macrocode}
+\cs_new_protected:Nn \tag_mc_end:
+  {
+    \@@_check_if_active_mc:T
+      {
+        %\@@_check_mc_if_open:
+        \bool_gset_false:N \g_@@_in_mc_bool
+        \bool_set_false:N\l_@@_mc_artifact_bool
+        \@@_mc_lua_unset_mc_type_attr:
+        \tl_set:Nn  \l_@@_mc_key_tag_tl { }
+        \tl_gset:Nn \g_@@_mc_key_tag_tl { }
+      }
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{ \@@_get_data_mc_tag: }
+% The command to retrieve the current mc tag.
+% TODO: Perhaps this should use the attribute instead.
+%    \begin{macrocode}
+\cs_new:Npn \@@_get_data_mc_tag: { \g_@@_mc_key_tag_tl }
+%    \end{macrocode}
+% \end{macro}
+
+% \subsection{Key definitions}
+% \begin{macro}
+%   {
+%    tag,raw,
+%    alttext,alttext-o,
+%    actualtext,actualtext-o,
+%    label,artifact
+%   }
+%   TODO: check conversion, check if local/global setting is right.
+%    \begin{macrocode}
+\keys_define:nn { @@ / mc }
+  {
+    tag .code:n = %
+      {
+        \tl_set:Nx   \l_@@_mc_key_tag_tl { #1 }
+        \tl_gset:Nx  \g_@@_mc_key_tag_tl { #1 }
+        \lua_now:e
+          {
+            ltx.@@.func.store_mc_data(\@@_get_mc_abs_cnt:,"tag","#1")
+          }
+      },
+    raw .code:n =
+      {
+        \tl_put_right:Nx \l_@@_mc_key_properties_tl { #1 }
+        \lua_now:e
+          {
+            ltx.@@.func.store_mc_data(\@@_get_mc_abs_cnt:,"raw","#1")
+          }
+      },
+    alttext .code:n      = % Alt property
+      {
+        \str_set_convert:Nnon
+          \l_@@_tmpa_str
+          { #1 }
+          { default }
+          { utf16/hex }
+        \tl_put_right:Nn \l_@@_mc_key_properties_tl { /Alt~< }
+        \tl_put_right:No \l_@@_mc_key_properties_tl { \l_@@_tmpa_str>~ }
+        \lua_now:e
+          {
+            ltx.@@.func.store_mc_data
+              (
+                 \@@_get_mc_abs_cnt:,"alt","/Alt~<\str_use:N \l_@@_tmpa_str>"
+              )
+          }
+      },
+    alttext-o .code:n      = % Alt property
+      {
+        \str_set_convert:Noon
+          \l_@@_tmpa_str
+          { #1 }
+          { default }
+          { utf16/hex }
+        \tl_put_right:Nn \l_@@_mc_key_properties_tl { /Alt~< }
+        \tl_put_right:No \l_@@_mc_key_properties_tl { \l_@@_tmpa_str>~ }
+        \lua_now:e
+          {
+            ltx.@@.func.store_mc_data
+              (
+                \@@_get_mc_abs_cnt:,"alt","/Alt~<\str_use:N \l_@@_tmpa_str>"
+              )
+          }
+      },
+    actualtext .code:n      = % Alt property
+      {
+        \str_set_convert:Nnon
+          \l_@@_tmpa_str
+          { #1 }
+          { default }
+          { utf16/hex }
+        \tl_put_right:Nn \l_@@_mc_key_properties_tl { /Alt~< }
+        \tl_put_right:No \l_@@_mc_key_properties_tl { \l_@@_tmpa_str>~ }
+        \lua_now:e
+          {
+            ltx.@@.func.store_mc_data
+              (
+                \@@_get_mc_abs_cnt:,"actualtext","/ActualText~<\str_use:N \l_@@_tmpa_str>"
+              )
+         }
+      },
+    actualtext-o .code:n      = % Alt property
+      {
+        \str_set_convert:Noon
+          \l_@@_tmpa_str
+          { #1 }
+          { default }
+          { utf16/hex }
+        \tl_put_right:Nn \l_@@_mc_key_properties_tl { /Alt~< }
+        \tl_put_right:No \l_@@_mc_key_properties_tl { \l_@@_tmpa_str>~ }
+        \lua_now:e
+          {
+            ltx.@@.func.store_mc_data
+              (
+                \@@_get_mc_abs_cnt:,
+                "actualtext",
+                "/ActualText~<\str_use:N \l_@@_tmpa_str>"
+              )
+          }
+      },
+    label .code:n =
+      {
+        \tl_set:Nn\l_@@_mc_key_label_tl { #1 }
+        \lua_now:e
+          {
+            ltx.@@.func.store_mc_data
+              (
+                \@@_get_mc_abs_cnt:,"label","#1"
+              )
+          }
+      },
+    __artifact-store .code:n =
+      {
+        \lua_now:e
+          {
+            ltx.@@.func.store_mc_data
+              (
+                \@@_get_mc_abs_cnt:,"artifact","#1"
+              )
+          }
+      },
+    artifact .code:n       =
+      {
+        \exp_args:Nnx
+          \keys_set:nn
+            { @@ / mc}
+            { __artifact-bool, __artifact-type=#1, tag=Artifact }
+        \exp_args:Nnx
+          \keys_set:nn
+            { @@ / mc }
+            { __artifact-store=\l_@@_mc_artifact_type_tl }
+      },
+    artifact .default:n    = { notype }
+  }
+
+%</luamode>
+%    \end{macrocode}
+% \end{macro}
+%
+% \end{implementation}
+% \PrintIndex


Property changes on: trunk/Master/texmf-dist/source/latex/tagpdf/tagpdf-mc-luacode.dtx
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/source/latex/tagpdf/tagpdf-mc-shared.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/tagpdf/tagpdf-mc-shared.dtx	                        (rev 0)
+++ trunk/Master/texmf-dist/source/latex/tagpdf/tagpdf-mc-shared.dtx	2021-06-30 21:14:14 UTC (rev 59769)
@@ -0,0 +1,442 @@
+% \iffalse meta-comment
+%
+%% File: tagpdf-mc.dtx
+%
+% Copyright (C) 2019-2021 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/u-fischer/tagpdf
+%
+% for those people who are interested.
+%<*driver>
+\RequirePackage{pdfmanagement-testphase}
+\DeclareDocumentMetadata{}
+\makeatletter
+\declare at file@substitution{doc.sty}{doc-v3beta.sty}
+\makeatother
+\documentclass{l3doc}
+\usepackage{array,booktabs,caption}
+\hypersetup{pdfauthor=Ulrike Fischer,
+ pdftitle=tagpdf-mc module (tagpdf)}
+\begin{document}
+  \DocInput{\jobname.dtx}
+\end{document}
+%</driver>
+% \fi
+% \title{^^A
+%   The \pkg{tagpdf-mc-shared} module\\ Code related to Marked Content (mc-chunks), code shared by all modes  ^^A
+%   \\ Part of the tagpdf package
+% }
+%
+% \author{^^A
+%  Ulrike Fischer\thanks
+%    {^^A
+%      E-mail:
+%        \href{mailto:fischer at troubleshooting-tex.de}
+%          {fischer at troubleshooting-tex.de}^^A
+%    }^^A
+% }
+%
+% \date{Version 0.9, released 2021-06-29}
+% \maketitle
+% \begin{documentation}
+% \section{Public Commands}
+%  \begin{function}{\tag_mc_begin:n,\tag_mc_end:}
+%   \begin{syntax}
+%     \cs{tag_mc_begin:n}\Arg{key-values}\\
+%     \cs{tag_mc_end:}
+%   \end{syntax}
+% These commands insert the end code of the marked content.
+% They don't end a group and in generic mode it doesn't matter
+% if they are in another group as the starting commands.
+% In generic mode both commands check if they are correctly nested
+% and issue a warning if not.
+% \end{function}
+%
+%  \begin{function}{\tag_mc_use:n}
+%   \begin{syntax}
+%     \cs{tag_mc_use:n}\Arg{label}
+%   \end{syntax}
+% These command allow to record a marked content that was stashed away before
+% into the current structure. A marked content can be used only once --
+% the command will issue a warning if an mc is use a second time.
+% \end{function}
+%
+%  \begin{function}[added = 2019-11-20]
+%   {
+%     \tag_mc_artifact_group_begin:n, \tag_mc_artifact_group_end:
+%   }
+%   \begin{syntax}
+%     \cs{tag_mc_artifact_group_begin:n} \Arg{name}\\
+%     \cs{tag_mc_artifact_group_end:}
+%   \end{syntax}
+%   This command pair creates a group with an artifact marker at the begin
+%   and the end. Inside the group the tagging commands are disabled.
+%   It allows to mark a complete region as artifact without having to worry
+%   about user commands with tagging commands.
+%   \meta{name} should be a value allowed also for the |artifact| key.
+%   It pushes and pops mc-chunks at the begin and end.
+%   TODO: document is in tagpdf.tex
+%   \end{function}
+%
+%  \begin{function}[added = 2021-04-22]
+%   {
+%     \tag_mc_end_push:, \tag_mc_begin_pop:n
+%   }
+%   \begin{syntax}
+%     \cs{tag_mc_end_push:} \\
+%     \cs{tag_mc_begin_pop:n}\Arg{key-values}
+%   \end{syntax}
+% If there is an open mc chunk,
+% \cs{tag_mc_end_push:} ends it and pushes its tag of the (global) stack.
+% If there is no open chunk, it puts $-1$ on the stack (for debugging)
+% \cs{tag_mc_begin_pop:n} removes a value from the stack. If it is different from
+% $-1$ it opens a tag with it.
+% The reopened mc chunk looses info like the alttext for now.
+% \end{function}
+%
+% \begin{function}[pTF, EXP]{\tag_mc_if_in:}
+%   \begin{syntax}
+%     \cs{tag_mc_if_in:TF} \Arg{true code} \Arg{false code}
+%   \end{syntax}
+%   Determines if a mc-chunk is open.
+% \end{function}
+
+%
+% \section{Public keys}
+% The following keys can be used with |\tag_mc_begin:n|, |\tagmcbegin|,
+% |\tag_mc_begin_pop:n|,
+%
+% \begin{function}{tag}
+% This key is required, unless artifact is used.
+% The value is a tag like |P| or |H1| without a slash at the begin,
+% this is added by the code.
+% It is possible to setup new tags.
+% The value of the key is expanded, so it can be a command.
+% The expansion is passed unchanged to the PDF,
+% so it should with a starting slash give a valid PDF name
+% (some ascii with numbers like \texttt{H4} is fine).
+% \end{function}
+%
+% \begin{function}{artifact}
+%  This will setup the marked content as an artifact. The key should be used
+%  for content that should be ignored.
+%  The key can take one of the values |pagination|,
+%  |layout|,  |page|,  |background| and |notype|
+%  (this is the default).
+% \end{function}
+%
+% \begin{function}{raw}
+% This key allows  to add more entries to the properties dictionary.
+% The value must be correct, low-level PDF. E.g.
+% \verb+raw=/Alt (Hello)+ will insert an alternative Text.
+% \end{function}
+%
+% \begin{function}{alttext,alttext-o}
+%  This key inserts an \texttt{/Alt} value in the property dictionary of the BDC operator.
+%  The value is handled as verbatim string, commands are not expanded. With |alttext-o|
+%  the value is expanded once.
+% \end{function}
+%
+% \begin{function}{actualtext,actualtext-o}
+%  This key inserts an \texttt{/ActualText} value in the property dictionary
+%  of the BDC operator. The value is handled as verbatim string,
+%  commands are not expanded.With |actualtext-o|
+%  the value is expanded once.
+% \end{function}
+%
+% \begin{function}{label}
+%  This key sets a label by which one can call the marked content
+%  later in another structure
+%  (if it has been stashed with the |stash| key).
+%  Internally the label name will start with \texttt{tagpdf-}.
+% \end{function}
+%
+% \begin{function}{stash}
+% This \enquote{stashes} an mc-chunk: it is not inserted into the current structure.
+% It should be normally be used along with a label to be able to use the mc-chunk
+% in another place.
+% \end{function}
+% \end{documentation}
+% \begin{implementation}
+% The code is splitted into three parts: code shared by all engines,
+% code specific to luamode and code not used by luamode.
+% \section{Marked content code -- shared}
+%    \begin{macrocode}
+%<@@=tag>
+%<*header>
+\ProvidesExplPackage {tagpdf-mc-code-shared} {2021-06-29} {0.9}
+  {part of tagpdf - code related to marking chunks -
+   code shared by generic and luamode }
+%</header>
+%    \end{macrocode}
+%
+% \subsection{Variables and counters}
+% MC chunks must be counted.
+% I use a latex counter for the absolute count, so that it is added to
+% |\cl@@ckpt| and restored e.g. in tabulars and align.
+% |\int_new:N  \c at g_@@_MCID_int| and
+% |\tl_put_right:Nn\cl@@ckpt{\@elt{g_uf_test_int}}|
+% would work too, but as the name is not expl3 then too, why bother?
+% The absolute counter can be used to label and to check if the page
+% counter needs a reset.
+%
+% \begin{variable}{g_@@_MCID_abs_int}
+%    \begin{macrocode}
+%<*shared>
+\newcounter { g_@@_MCID_abs_int }
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{macro}{\_@@_get_mc_abs_cnt:}
+% A (expandable) function to get the current value of the cnt.
+%    \begin{macrocode}
+\cs_new:Npn \_@@_get_mc_abs_cnt: { \int_use:N \c at g_@@_MCID_abs_int }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{variable}{\g_@@_MCID_tmp_bypage_int}
+% The following hold the temporary by page number assigned to a mc.
+% It must be defined in the shared code to avoid problems with labels.
+%    \begin{macrocode}
+\int_new:N \g_@@_MCID_tmp_bypage_int
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\g_@@_mc_parenttree_prop}
+% For every chunk we need to know the structure it is in, to
+% record this in the parent tree. We store this in a property.\\
+% key:   absolute number of the mc (tagmcabs)\\
+% value: the structure number the mc is in
+%    \begin{macrocode}
+\@@_prop_new:N \g_@@_mc_parenttree_prop
+%    \end{macrocode}
+% \end{variable}
+%
+%\begin{variable}{\g_@@_mc_parenttree_prop}
+% Some commands (e.g. links) want to close a previous mc and reopen it after
+% they did their work. For this we create a stack:
+%    \begin{macrocode}
+\seq_new:N \g_@@_mc_stack_seq
+%    \end{macrocode}
+% \end{variable}
+%
+%\begin{variable}{\l_@@_mc_artifact_type_tl}
+% Artifacts can have various types like Pagination or Layout. This stored
+% in this variable.
+%    \begin{macrocode}
+\tl_new:N \l_@@_mc_artifact_type_tl
+%    \end{macrocode}
+% \end{variable}
+%
+%\begin{variable}{\l_@@_mc_key_stash_bool,\l_@@_mc_artifact_bool}
+%This booleans store the stash and artifact status of the mc-chunk.
+%    \begin{macrocode}
+\bool_new:N \l_@@_mc_key_stash_bool
+\bool_new:N \l_@@_mc_artifact_bool
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}
+%  {
+%   \l_@@_mc_key_tag_tl,
+%   \g_@@_mc_key_tag_tl,
+%   \l_@@_mc_key_label_tl,
+%   \l_@@_mc_key_properties_tl
+%  }
+% Variables used by the keys. |\l_@@_mc_key_properties_tl|
+% will collect a number of values. TODO: should this be a pdfdict now?
+%    \begin{macrocode}
+\tl_new:N \l_@@_mc_key_tag_tl
+\tl_new:N \g_@@_mc_key_tag_tl
+\tl_new:N \l_@@_mc_key_label_tl
+\tl_new:N \l_@@_mc_key_properties_tl
+%    \end{macrocode}
+% \end{variable}
+%
+% \subsection{Functions}
+% \begin{macro}{\_@@_mc_handle_mc_label:n}
+% The commands labels a mc-chunk. It is used if the user explicitly
+% labels the mc-chunk with the |label| key. The argument is the
+% value provided by the user. It stores the attributes\\
+% |tagabspage|: the absolute page, |\g_shipout_readonly_int|,\\
+% |tagmcabs|: the absolute mc-counter |\c at g_@@_MCID_abs_int|,\\
+% |tagmcid|: the ID of the chunk on the page |\g_@@_MCID_tmp_bypage_int|, this
+%  typically settles down after a second compilation.
+%  The reference command is defined in tagpdf.dtx and is based on l3ref.
+%    \begin{macrocode}
+\cs_new:Nn \_@@_mc_handle_mc_label:n
+  {
+    \@@_ref_label:en{tagpdf-#1}{mc}
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_mc_set_label_used:n}
+% Unlike with structures we can't check if a labeled mc has been used by
+% looking at the P key, so we use a dedicated csname for the test
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_mc_set_label_used:n #1 %#1 labelname
+  {
+    \tl_new:c { g_@@_mc_label_\tl_to_str:n{#1}_used_tl }
+  }
+%    \end{macrocode}
+%
+% \end{macro}
+% \begin{macro}{\tag_mc_use:n}
+% These command allow to record a marked content that was stashed away before
+% into the current structure. A marked content can be used only once --
+% the command will issue a warning if an mc is use a second time.
+% The argument is a label name set with the |label| key.
+%
+% TODO: is testing for struct the right test?
+%    \begin{macrocode}
+\cs_new_protected:Npn \tag_mc_use:n #1 %#1: label name
+  {
+    \@@_check_if_active_struct:T
+      {
+        \tl_set:Nx  \l_@@_tmpa_tl { \@@_ref_value:nnn{tagpdf-#1}{tagmcabs}{} }
+        \tl_if_empty:NTF\l_@@_tmpa_tl
+          {
+            \msg_warning:nnn {tag} {mc-label-unknown} {#1}
+          }
+          {
+            \cs_if_free:cTF { g_@@_mc_label_\tl_to_str:n{#1}_used_tl }
+              {
+                \@@_mc_handle_stash:x { \l_@@_tmpa_tl }
+                \@@_mc_set_label_used:n {#1}
+              }
+              {
+                 \msg_warning:nnn {tag}{mc-used-twice}{#1}
+              }
+          }
+       }
+  }
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}
+%   {
+%     \tag_mc_artifact_group_begin:n,
+%     \tag_mc_artifact_group_end:
+%   }
+% This opens an artifact of the type given in the argument,
+% and then stops all tagging. It creates a group.
+% It pushes and pops mc-chunks at the begin and end.
+%    \begin{macrocode}
+\cs_new_protected:Npn \tag_mc_artifact_group_begin:n #1
+ {
+  \tag_mc_end_push:
+  \tag_mc_begin:n {artifact=#1}
+  \tag_stop_group_begin:
+ }
+
+\cs_new_protected:Npn \tag_mc_artifact_group_end:
+ {
+  \tag_stop_group_end:
+  \tag_mc_end:
+  \tag_mc_begin_pop:n{}
+ }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\tag_mc_end_push:, \tag_mc_begin_pop:n}
+%
+%    \begin{macrocode}
+\cs_new_protected:Npn \tag_mc_end_push:
+  {
+    \@@_check_if_active_mc:T
+      {
+        \@@_mc_if_in:TF
+          {
+            \seq_gpush:Nx \g_@@_mc_stack_seq { \tag_get:n {mc_tag} }
+            \@@_check_mc_pushed_popped:nn
+              { pushed }
+              { \tag_get:n {mc_tag} }
+            \tag_mc_end:
+          }
+          {
+            \seq_gpush:Nn \g_@@_mc_stack_seq {-1}
+            \@@_check_mc_pushed_popped:nn { pushed }{-1}
+          }
+      }
+  }
+
+\cs_new_protected:Npn \tag_mc_begin_pop:n #1
+  {
+    \@@_check_if_active_mc:T
+      {
+        \seq_gpop:NNTF \g_@@_mc_stack_seq \l_@@_tmpa_tl
+          {
+            \tl_if_eq:NnTF \l_@@_tmpa_tl {-1}
+              {
+                \@@_check_mc_pushed_popped:nn {popped}{-1}
+              }
+              {
+                \@@_check_mc_pushed_popped:nn {popped}{\l_@@_tmpa_tl}
+                \tag_mc_begin:n {tag=\l_@@_tmpa_tl,#1}
+              }
+          }
+          {
+            \@@_check_mc_pushed_popped:nn {popped}{empty~stack,~nothing}
+          }
+      }
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \subsection{Keys}
+% This are the keys where the code can be shared between the modes.
+%
+% \begin{macro}{stash,__artifact-bool,__artifact-type}
+% the two internal artifact keys are use to define the public |artifact|.
+%    \begin{macrocode}
+\keys_define:nn { @@ / mc }
+  {
+    stash                    .bool_set:N    = \l_@@_mc_key_stash_bool,
+    __artifact-bool          .bool_set:N    = \l_@@_mc_artifact_bool,
+    __artifact-type          .choice:,
+    __artifact-type / pagination .code:n    =
+      {
+        \tl_set:Nn \l_@@_mc_artifact_type_tl { Pagination }
+      },
+    __artifact-type / layout     .code:n    =
+      {
+        \tl_set:Nn \l_@@_mc_artifact_type_tl { Layout }
+      },
+    __artifact-type / page       .code:n    =
+      {
+        \tl_set:Nn \l_@@_mc_artifact_type_tl { Page }
+      },
+    __artifact-type / background .code:n    =
+      {
+        \tl_set:Nn \l_@@_mc_artifact_type_tl { Background }
+      },
+    __artifact-type / notype     .code:n    =
+      {
+        \tl_set:Nn \l_@@_mc_artifact_type_tl {}
+      },
+    __artifact-type /      .code:n    =
+      {
+        \tl_set:Nn \l_@@_mc_artifact_type_tl {}
+      },
+  }
+%    \end{macrocode}
+% \end{macro}
+%    \begin{macrocode}
+%</shared>
+%    \end{macrocode}
+% \end{implementation}
+% \PrintIndex


Property changes on: trunk/Master/texmf-dist/source/latex/tagpdf/tagpdf-mc-shared.dtx
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Deleted: trunk/Master/texmf-dist/source/latex/tagpdf/tagpdf-mc.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/tagpdf/tagpdf-mc.dtx	2021-06-30 20:41:50 UTC (rev 59768)
+++ trunk/Master/texmf-dist/source/latex/tagpdf/tagpdf-mc.dtx	2021-06-30 21:14:14 UTC (rev 59769)
@@ -1,818 +0,0 @@
-% \iffalse meta-comment
-%
-%% File: tagpdf-mc.dtx
-%
-% Copyright (C) 2019-2020 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/u-fischer/tagpdf
-%
-% for those people who are interested.
-%
-% \fi
-%
-%    \begin{macrocode}
-%<@@=tag>
-%<*shared>
-\ProvidesExplPackage {tagpdf-mc-code-shared} {2021-06-14} {0.82}
-  {part of tagpdf - code related to marking chunks -
-   code shared by generic and luamode }
-% I use a latex counter for the absolute count, so that it is added to
-% \cl@@ckpt and restored e.g. in tabulars and align
-% \int_new:N  \c at g_@@_MCID_int and
-% \tl_put_right:Nn\cl@@ckpt{\@elt{g_uf_test_int}}
-% would work too, but as the name is not expl3 then too, why bother?
-% the absolute counter can be used to label and to check if the page
-% counter needs a reset.
-
-\newcounter { g_@@_MCID_abs_int }
-\cs_new:Nn \_@@_get_mc_abs_cnt: { \int_use:N \c at g_@@_MCID_abs_int }
-
-% tagmcabs is the label name of the absolute count which is used
-% to identify the chunk
-% the ref code is now in tagpdf.dtx
-
-%stores labels of mcid.
-\cs_new:Nn \_@@_mc_handle_mc_label:n
-  {
-    \@@_ref_label:en{tagpdf-#1}{mc}
-  }
-
-% will hold the structure numbers for the parenttree
-% key:   absolute number of the mc (tagmcabs)
-% value: the structure number the mc is in
-\_@@_prop_new:N \g_@@_mc_parenttree_prop
-
-% some commands (e.g. links) want to close a previous mc and reopen it after
-% there work. For this we create a stack:
-\seq_new:N \g_@@_mc_stack_seq
-% shared keys
-% the rest are in the splitted code
-\tl_new:N \l_@@_mc_artifact_type_tl
-
-\keys_define:nn { @@ / mc }
-  {
-    stash                  .bool_set:N    = \l_@@_mc_key_stash_bool,
-    artifact-bool          .bool_set:N    = \l_@@_mc_artifact_bool,
-    artifact-type          .choice:,
-    artifact-type / pagination .code:n    =
-      {
-        \tl_set:Nn \l_@@_mc_artifact_type_tl { Pagination }
-      },
-    artifact-type / layout     .code:n    =
-      {
-        \tl_set:Nn \l_@@_mc_artifact_type_tl { Layout }
-      },
-    artifact-type / page       .code:n    =
-      {
-        \tl_set:Nn \l_@@_mc_artifact_type_tl { Page }
-      },
-    artifact-type / background .code:n    =
-      {
-        \tl_set:Nn \l_@@_mc_artifact_type_tl { Background }
-      },
-    artifact-type / notype     .code:n    =
-      {
-        \tl_set:Nn \l_@@_mc_artifact_type_tl {}
-      },
-     artifact-type /      .code:n    =
-      {
-        \tl_set:Nn \l_@@_mc_artifact_type_tl {}
-      },
-  }
-%    \end{macrocode}
-%  \begin{function}[added = 2019-11-20]
-%   {
-%     \tag_mc_artifact_group_begin:n, \tag_mc_artifact_group_end:
-%   }
-%   \begin{syntax}
-%     \cs{tag_mc_artifact_group_begin:n} \Arg{name}
-%   \end{syntax}
-%   This command pair create a group with an artifact marker at the begin
-%   and the end. Inside the group the tagging commands are disabled.
-%   \end{function}
-%    \begin{macrocode}
-
-
-\cs_new_protected:Npn \tag_mc_artifact_group_begin:n #1
- {
-  \tag_mc_begin:n {artifact=#1}
-  \tag_stop_group_begin:
- }
-
-\cs_new_protected:Npn \tag_mc_artifact_group_end:
- {
-  \tag_stop_group_end:
-  \tag_mc_end:
- }
-
-% we need to define it for both modes to avoid a problem with the label
-\int_new:N \g_@@_MCID_tmp_bypage_int
-
-%    \end{macrocode}
-
-%  \begin{function}[added = 2021-04-22]
-%   {
-%     \tag_mc_end_push:, \tag_mc_begin_pop:n
-%   }
-%   \begin{syntax}
-%     \cs{tag_mc_end_push:} \\
-%     \cs{tag_mc_begin_pop:n}\Arg{key-values}
-%   \end{syntax}
-% If there is an open mc chunk,
-% \cs{tag_mc_end_push:} ends it and pushes its tag of the stack. If there is no
-% open chunk, it puts -1 on the stack (for debugging)
-% \cs{tag_mc_begin_pop:n} removes a value from the stack. If it is different from
-% -1 it opens a tag with it.
-% The reopened mc chunk looses info like the alttext for now.
-%
-%    \begin{macrocode}
-\cs_new_protected:Npn \tag_mc_end_push:
- {
-   \@@_mc_if_in:TF
-     {
-       \seq_gpush:Nx \g_@@_mc_stack_seq { \tag_get:n {mc_tag} }
-       \@@_check_mc_pushed_popped:nn {pushed}{\tag_get:n {mc_tag}}
-       \tag_mc_end:
-     }
-     {
-       \@@_check_mc_pushed_popped:nn {pushed}{-1}
-       \seq_gpush:Nn \g_@@_mc_stack_seq{ -1  }
-     }
- }
-\cs_new_protected:Npn \tag_mc_begin_pop:n #1
- {
-   \seq_gpop:NNTF \g_@@_mc_stack_seq \l_@@_tmpa_tl
-     {
-       \tl_if_eq:NnTF \l_@@_tmpa_tl {-1}
-         {
-           \@@_check_mc_pushed_popped:nn {popped}{-1}
-         }
-         {
-           \@@_check_mc_pushed_popped:nn {popped}{\l_@@_tmpa_tl}
-           \tag_mc_begin:n {tag=\l_@@_tmpa_tl,#1}
-         }
-     }
-     { \@@_check_mc_pushed_popped:nn {popped}{empty~stack,~nothing} } %message?
- }
-
-%</shared>
-%    \end{macrocode}
-%    \begin{macrocode}
-%<*generic>
-\ProvidesExplPackage {tagpdf-mc-code-generic} {2021-06-14} {0.82}
- {part of tagpdf - code related to marking chunks - generic mode}
-
-% for the label system
-% tagmcid is the id which should be also in the pdf
-% it will be (hopefully) reset by page
-
-% ref code is in tagpdf.dtx now
-%
-% will hold the current maximum on a page
-% it will contain key-value of type "abspagenum=max mcid on this page"
-\@@_prop_new:N \g_@@_MCID_byabspage_prop
-
-%to test nesting mc:
-\bool_new:N \g_@@_in_mc_bool
-
-\prg_new_conditional:Nnn \@@_mc_if_in: {p,T,F,TF}
-  {
-    \bool_if:NTF \g_@@_in_mc_bool
-      { \prg_return_true:  }
-      { \prg_return_false: }
-  }
-
-\prg_new_eq_conditional:NNn \tag_mc_if_in: \@@_mc_if_in: {p,T,F,TF}
-
-
-
-% this are the low level mc command.
-% they insert literals and so a are specific to generic mode
-% checking if the type is defined will done somewhere else
-% #1 is the type/tag
-% change 04.08.2018: I don't try to escape the name, but assume that it is valid.
-% Checks/conversions should perhaps be done on a higher level
-\cs_new_protected:Nn \@@_mc_bmc:n
-  {
-    \pdf_bmc:n {#1}
-%    \@@_pdfliteral_page:n
-%      {
-%        /#1\c_space_tl BMC
-%      }
-  }
-
-\cs_new_protected:Nn \@@_mc_emc:
-  {
-    \pdf_emc:
-    %\@@_pdfliteral_page:n
-%      {
-%        EMC
-%      }
-  }
-
-% #1 tag, #2 properties
-% change 04.08.2018: I don't escape the name. Also the dictionary content
-% must imho be done at a higher level
-\cs_new_protected:Nn \@@_mc_bdc:nn
-  {
-    \pdf_bdc:nn { #1 } { #2 }
-  }
-
-\cs_generate_variant:Nn \@@_mc_bdc:nn {nx}
-% bdc with /MCID + more properties
-% we need a ref-label system to ensure that the cnt restarts at 0 on a new page
-
-\tl_new:N \l_@@_mc_ref_abspage_tl %will store the abspage value of label
-\tl_new:N \l_@@_mc_tmp_tl
-
-\cs_new:Nn \@@_mc_bdc_mcid:nn
-  {
-    \int_gincr:N \c at g_@@_MCID_abs_int
-    \tl_set:Nx \l_@@_mc_ref_abspage_tl
-      {
-        \@@_ref_value:enn %3 args
-          {
-            mcid-\int_use:N \c at g_@@_MCID_abs_int
-          }
-          { tagabspage }
-          {-1}
-      }
-    \prop_get:NoNTF
-      \g_@@_MCID_byabspage_prop
-      {
-        \l_@@_mc_ref_abspage_tl
-      }
-      \l_@@_mc_tmp_tl
-      {
-        %key already present, use value for MCID and add 1 for the next
-        \int_gset:Nn \g_@@_MCID_tmp_bypage_int { \l_@@_mc_tmp_tl }
-        \@@_prop_gput:Nxx
-          \g_@@_MCID_byabspage_prop
-          { \l_@@_mc_ref_abspage_tl }
-          { \int_eval:n {\l_@@_mc_tmp_tl +1} }
-      }
-      {
-        %key not present, set MCID to 0 and insert 1
-        \int_gzero:N \g_@@_MCID_tmp_bypage_int
-        \@@_prop_gput:Nxx
-          \g_@@_MCID_byabspage_prop
-          { \l_@@_mc_ref_abspage_tl }
-          {1}
-      }
-    \@@_ref_label:en
-      {
-        mcid-\int_use:N \c at g_@@_MCID_abs_int
-      }
-      { mc }
-   %\exp_args:Nnx
-     \@@_mc_bdc:nx
-       {#1}
-       { /MCID~\int_eval:n { \g_@@_MCID_tmp_bypage_int }~ \exp_not:n { #2 } }
- }
-
-% only /MCID
-\cs_new:Nn \@@_mc_bdc_mcid:n
-  {
-    \@@_mc_bdc_mcid:nn {#1} {}
-  }
-
-%artifact without type
-\cs_new:Nn  \@@_mc_bmc_artifact:
-  {
-    \@@_mc_bmc:n {Artifact}
-  }
-
-%artifact with a type:
-\cs_new:Nn \@@_mc_bmc_artifact:n
-  {
-    \@@_mc_bdc:nn {Artifact}{/Type/#1}
-  }
-
-% perhaps later: more properties for artifacts
-
-
-% keyval definitions for the user commands:
-
-\tl_new:N \l_@@_mc_key_tag_tl
-\tl_new:N \g_@@_mc_key_tag_tl %for "outside" queries
-\tl_new:N \l_@@_mc_key_properties_tl
-
-% Attention! definitions are different in luamode.
-% tag and raw are expanded as \directlua in lua does it too.
-\keys_define:nn { @@ / mc }
-  {
-    tag .code:n = % the name (H,P,Spa) etc
-      {
-         %%????????? \pdfescapename??
-        \tl_set:Nx   \l_@@_mc_key_tag_tl { #1 }
-        \tl_gset:Nx  \g_@@_mc_key_tag_tl { #1 }
-      },
-    raw  .code:n =
-      {
-        \tl_put_right:Nx \l_@@_mc_key_properties_tl { #1 }
-      },
-    alttext .code:n = % Alt property
-      {
-        \str_set_convert:Nnon
-          \l_@@_tmpa_str
-          { #1 }
-          { default }
-          { utf16/hex }
-        \tl_put_right:Nn \l_@@_mc_key_properties_tl { /Alt~< }
-        \tl_put_right:No \l_@@_mc_key_properties_tl { \l_@@_tmpa_str>~ }
-      },
-    alttext-o .code:n      = % Alt property
-      {
-        \str_set_convert:Noon
-          \l_@@_tmpa_str
-          { #1 }
-          { default }
-          { utf16/hex }
-        \tl_put_right:Nn \l_@@_mc_key_properties_tl { /Alt~< }
-        \tl_put_right:No \l_@@_mc_key_properties_tl { \l_@@_tmpa_str>~ }
-      },
-    actualtext .code:n      = % ActualText property
-      {
-        \str_set_convert:Nnon
-          \l_@@_tmpa_str
-          { #1 }
-          { default }
-          { utf16/hex }
-        \tl_put_right:Nn \l_@@_mc_key_properties_tl { /ActualText~< }
-        \tl_put_right:No \l_@@_mc_key_properties_tl { \l_@@_tmpa_str>~ }
-      },
-    actualtext-o .code:n      = % ActualText property
-      {
-        \str_set_convert:Noon
-          \l_@@_tmpa_str
-          { #1 }
-          { default }
-          { utf16/hex }
-        \tl_put_right:Nn \l_@@_mc_key_properties_tl { /ActualText~< }
-        \tl_put_right:No \l_@@_mc_key_properties_tl { \l_@@_tmpa_str>~ }
-      },
-    label .tl_set:N        = \l_@@_mc_key_label_tl,
-    artifact .code:n       =
-      {
-        \exp_args:Nnx
-          \keys_set:nn
-            { @@ / mc }
-            { artifact-bool, artifact-type=#1 }
-      },
-    artifact .default:n    = {notype}
-  }
-
-\cs_new:Nn \@@_mc_handle_artifact:N %#1 contains the artifact type
-  {
-    \tl_if_empty:NTF #1
-      { \@@_mc_bmc_artifact: }
-      { \exp_args:No\@@_mc_bmc_artifact:n {#1} }
-  }
-
-\cs_new:Nn \@@_mc_handle_mcid:nn %#1 tag, #2 properties
-  {
-    \@@_mc_bdc_mcid:nn {#1} {#2}
-  }
-
-\cs_generate_variant:Nn \@@_mc_handle_mcid:nn {VV}
-
-% puts the absolute number of an mcid in the current structure
-\cs_new:Nn \@@_mc_handle_stash:n %1 mcidnum
-  {
-    \@@_check_mc_used:n {#1}
-    \@@_struct_kid_mc_gput_right:nn
-      { \g_@@_struct_stack_current_tl }
-      {#1}
-   \prop_gput:Nxx \g_@@_mc_parenttree_prop
-     {#1}
-     { \g_@@_struct_stack_current_tl }
-  }
-
-\cs_new_protected:Nn \tag_mc_begin:n
-  {
-    \group_begin: %hm
-    \@@_check_mc_if_nested:
-    \bool_gset_true:N \g_@@_in_mc_bool
-    \keys_set:nn { @@ / mc } {#1}
-    \bool_if:NTF \l_@@_mc_artifact_bool
-      { %handle artifact
-        \@@_mc_handle_artifact:N \l_@@_mc_artifact_type_tl
-      }
-      { %handle mcid type
-        \@@_check_mc_tag:N  \l_@@_mc_key_tag_tl
-        \@@_mc_handle_mcid:VV
-           \l_@@_mc_key_tag_tl
-           \l_@@_mc_key_properties_tl
-        \tl_if_empty:NF {\l_@@_mc_key_label_tl}
-          {
-            \@@_mc_handle_mc_label:n { \l_@@_mc_key_label_tl }
-          }
-        \bool_if:NF \l_@@_mc_key_stash_bool
-          {
-            \@@_mc_handle_stash:n { \int_use:N \c at g_@@_MCID_abs_int }
-          }
-      }
-    \group_end:
-  }
-
-
-\cs_new_protected:Nn \tag_mc_end:
-  {
-    \@@_check_mc_if_open:
-    \bool_gset_false:N \g_@@_in_mc_bool
-    \tl_gset:Nn  \g_@@_mc_key_tag_tl { }
-    \@@_mc_emc:
-  }
-
-
-
-\cs_new_protected:Nn \tag_mc_use:n %#1: label name
-  {
-    \tl_set:Nx  \l_tmpa_tl { \@@_ref_value:enn{tagpdf-#1}{tagmcabs}{} }
-    \tl_if_empty:NTF\l_tmpa_tl
-      {
-        \msg_warning:nnn {tag} {mc-label-unknown} {#1}
-      }
-      {
-        \prop_gput:Nxx
-          \g_@@_mc_parenttree_prop
-          {
-            \@@_ref_value:enn {tagpdf-#1} {tagmcabs} {}
-          }
-          {
-            \g_@@_struct_stack_current_tl
-          }
-        \@@_struct_kid_mc_gput_right:nn
-          {
-            \g_@@_struct_stack_current_tl
-          }
-          {
-            \@@_ref_value:enn {tagpdf-#1} {tagmcabs} {}
-          }
-       }
-  }
-
-
-\cs_new:Nn \@@_get_data_mc_tag: { \g_@@_mc_key_tag_tl }
-%</generic>
-%    \end{macrocode}
-%    \begin{macrocode}
-%<*luamode>
-\ProvidesExplPackage {tagpdf-mc-code-lua} {2021-06-14} {0.82}
-  {tagpdf - mc code only for the luamode }
-
-% the two attibutes are defined in the driver file.
-% it also load the lua (as it can also contain functions needed by generic mode.
-% (new) attributes for mc are local:
-% \newattribute \l_@@_mc_type_attr     %the value represent the type
-% \newattribute \l_@@_mc_cnt_attr      %will hold the \c at g_@@_MCID_abs_int value
-
-
-% An attribute for the current structure probably doesn't make sense as mc chunks can be used later.
-% \newattribute \g_@@_struct_type_attr %represent the current structure type. Not sure if needed
-% \newattribute \g_@@_struct_cnt_attr  %will hold \c at g_@@_struct_abs_int a cnt
-
-% handling attribute needs a different system to number the page wise mcid's:
-% a tagmcbegin ... tagmcend pair no longer surrounds exactly one mc chunk: it can be split
-% at page breaks. We know the included mcid(s) only after the ship out. So for the struct-> mcid mapping we
-% need to record struct -> mc-cnt (in \g_@@_mc_parenttree_prop and/or a lua table
-% and at shipout mc-cnt-> {mcid, mcid, ...} (in a table?)
-% and when building the trees connect both
-
-% key definitions are overwritten for luatex to store that data in tables
-% the data for the mc are in ltx.@@.mc[absnum]
-% the fields of the table are
-% tag : the type (a string)
-% raw : more properties (string)
-% label: a string. Do we need a way to retrieve the num from the label from lua??
-% artifact: the presence indicates an artifact, the value (string) is the type.
-% kids: a array of tables {1={kid=num2,page=pagenum1}, 2={kid=num2,page=pagenum2},...},
-% this describes the chunks the mc has been split to by the traversing code
-% parent: the number of the structure it is in. Needed to build the parent tree.
-
-% The main function which wanders through the shipout box to inject the literals.
-% if the new callback is there, it is used.
-\hook_gput_code:nnn{begindocument}{tagpdf/mc}
-  {
-    \bool_if:NT\g__tag_active_mc_bool
-      {
-        \directlua
-          {
-            if~luatexbase.callbacktypes.pre_shipout_filter~then~
-              luatexbase.add_to_callback("pre_shipout_filter", function(TAGBOX)~
-              ltx.__tag.func.mark_shipout(TAGBOX)~return~true~
-              end, "tagpdf")~
-            end
-          }
-       \directlua
-         {
-           if~luatexbase.callbacktypes.pre_shipout_filter~then~
-           token.get_next()~
-           end
-         }\@secondoftwo\@gobble
-           {
-             \hook_gput_code:nnn{shipout/before}{tagpdf/lua}
-               {
-                 \directlua
-                   { ltx.__tag.func.mark_shipout (tex.box["ShipoutBox"]) }
-               }
-           }
-      }
-  }
-
-\prg_new_conditional:Nnn \@@_mc_if_in: {p,T,F,TF}
-  {
-    \int_compare:nNnTF { -2147483647 }={ \l_@@_mc_type_attr }
-      { \prg_return_false:  }
-      { \prg_return_true: }
-  }
-
-\prg_new_eq_conditional:NNn \tag_mc_if_in: \@@_mc_if_in: {p,T,F,TF}
-
-
-% the keys
-\tl_new:N \l_@@_mc_key_tag_tl
-\tl_new:N \l_@@_mc_key_label_tl
-\tl_new:N \l_@@_mc_key_properties_tl
-
-\keys_define:nn { @@ / mc }
-  {
-    tag .code:n = %
-      {%%????????? \pdfescapename??
-        \tl_set:Nx  \l_@@_mc_key_tag_tl { #1 }
-        \directlua
-          {
-            ltx.@@.func.store_mc_data(\@@_get_mc_abs_cnt:,"tag","#1")
-          }
-      },
-    raw .code:n =
-      {
-        \tl_put_right:Nx \l_@@_mc_key_properties_tl { #1 }
-        \directlua
-          {
-            ltx.@@.func.store_mc_data(\@@_get_mc_abs_cnt:,"raw","#1")
-          }
-      },
-    alttext .code:n      = % Alt property
-      {
-        \str_set_convert:Nnon
-          \l_@@_tmpa_str
-          { #1 }
-          { default }
-          { utf16/hex }
-        \tl_put_right:Nn \l_@@_mc_key_properties_tl { /Alt~< }
-        \tl_put_right:No \l_@@_mc_key_properties_tl { \l_@@_tmpa_str>~ }
-        \directlua
-          {
-            ltx.@@.func.store_mc_data
-              (
-                 \@@_get_mc_abs_cnt:,"alt","/Alt~<\str_use:N \l_@@_tmpa_str>"
-              )
-          }
-      },
-    alttext-o .code:n      = % Alt property
-      {
-        \str_set_convert:Noon
-          \l_@@_tmpa_str
-          { #1 }
-          { default }
-          { utf16/hex }
-        \tl_put_right:Nn \l_@@_mc_key_properties_tl { /Alt~< }
-        \tl_put_right:No \l_@@_mc_key_properties_tl { \l_@@_tmpa_str>~ }
-        \directlua
-          {
-            ltx.@@.func.store_mc_data
-              (
-                \@@_get_mc_abs_cnt:,"alt","/Alt~<\str_use:N \l_@@_tmpa_str>"
-              )
-          }
-      },
-    actualtext .code:n      = % Alt property
-      {
-        \str_set_convert:Nnon
-          \l_@@_tmpa_str
-          { #1 }
-          { default }
-          { utf16/hex }
-        \tl_put_right:Nn \l_@@_mc_key_properties_tl { /Alt~< }
-        \tl_put_right:No \l_@@_mc_key_properties_tl { \l_@@_tmpa_str>~ }
-        \directlua
-          {
-            ltx.@@.func.store_mc_data
-              (
-                \@@_get_mc_abs_cnt:,"actualtext","/ActualText~<\str_use:N \l_@@_tmpa_str>"
-              )
-         }
-      },
-    actualtext-o .code:n      = % Alt property
-      {
-        \str_set_convert:Noon
-          \l_@@_tmpa_str
-          { #1 }
-          { default }
-          { utf16/hex }
-        \tl_put_right:Nn \l_@@_mc_key_properties_tl { /Alt~< }
-        \tl_put_right:No \l_@@_mc_key_properties_tl { \l_@@_tmpa_str>~ }
-        \directlua
-          {
-            ltx.@@.func.store_mc_data
-              (
-                \@@_get_mc_abs_cnt:,
-                "actualtext",
-                "/ActualText~<\str_use:N \l_@@_tmpa_str>"
-              )
-          }
-      },
-    label .code:n =
-      {
-        \tl_set:Nn\l_@@_mc_key_label_tl { #1 }
-        \directlua
-          {
-            ltx.@@.func.store_mc_data
-              (
-                \@@_get_mc_abs_cnt:,"label","#1"
-              )
-          }
-      },
-    __artifact-store .code:n =
-      {
-        \directlua
-          {
-            ltx.@@.func.store_mc_data
-              (
-                \@@_get_mc_abs_cnt:,"artifact","#1"
-              )
-          }
-      },
-    artifact .code:n       =
-      {
-        \exp_args:Nnx
-          \keys_set:nn
-            { @@ / mc}
-            { artifact-bool, artifact-type=#1, tag=Artifact }
-        \exp_args:Nnx
-          \keys_set:nn
-            { @@ / mc }
-            { __artifact-store=\l_@@_mc_artifact_type_tl }
-      },
-    artifact .default:n    = { notype }
-  }
-
-
-% attributes
-% set the mc from a tag name
-
-\cs_set_protected:Npn \@@_attribute_gset:Nn #1 #2
-  {
-    \tex_global:D \setattribute #1 #2
-  }
-
-\cs_set_protected:Npn \@@_attribute_set:Nn #1 #2
-  {
-    \setattribute #1 #2
-  }
-
-\cs_set_protected:Npn \@@_attribute_gunset:N #1
-  {
-    \tex_global:D \unsetattribute #1
-  }
-
-\cs_set_protected:Npn \@@_attribute_unset:N #1
-  {
-    \unsetattribute #1
-  }
-
-
-\cs_new:Nn \@@_mc_lua_set_mc_type_attr:n % #1 is a tag name
-  {
-    \@@_attribute_set:Nn \l_@@_mc_type_attr
-      {
-        \directlua { ltx.@@.func.output_num_from ("#1") }
-      }
-    \@@_attribute_set:Nn \l_@@_mc_cnt_attr  { \@@_get_mc_abs_cnt: }
-  }
-
-\cs_generate_variant:Nn\@@_mc_lua_set_mc_type_attr:n { o }
-
-\cs_new:Nn \@@_mc_lua_unset_mc_type_attr:
-  {
-    \@@_attribute_unset:N \l_@@_mc_type_attr
-    \@@_attribute_unset:N \l_@@_mc_cnt_attr
-  }
-
-
-
-%This command will in the finish code replace the dummy for a mc by the real mcid kids
-%we need a variant for the case that it is the only kid, to get the array right
-\cs_new:Nn \@@_mc_insert_mcid_kids:n
-  {
-    \directlua { ltx.@@.func.mc_insert_kids (#1,0) }
-  }
-
-\cs_new:Nn \@@_mc_insert_mcid_single_kids:n
-  {
-    \directlua {ltx.@@.func.mc_insert_kids (#1,1) }
-  }
-
-
-% we need to pass the info if the kids are alone or already in an array
-% so we add a second argument, which should == 1 if the kids are single
-
-
-% puts an mcid absolute number in the current structure
-\cs_new:Nn \@@_mc_handle_stash:n %1 mcidnum
-  {
-    \@@_check_mc_used:n { #1 }
-    \seq_gput_right:cn % Don't fill a lua table due to the command in the item,
-                       % so use the kernel command
-      { g_@@_struct_kids_\g_@@_struct_stack_current_tl _seq }
-      {
-        \@@_mc_insert_mcid_kids:n {#1}%
-      }
-    \directlua
-      {
-        ltx.@@.func.store_struct_mcabs
-          (
-            \g_@@_struct_stack_current_tl,#1
-          )
-      }
-    \prop_gput:Nxx
-      \g_@@_mc_parenttree_prop
-      { #1 }
-      { \g_@@_struct_stack_current_tl }
-  }
-
-\cs_generate_variant:Nn \@@_mc_handle_stash:n { o }
-
-\cs_new_protected:Nn \tag_mc_begin:n
-  {
-    %\group_begin:
-    %\@@_check_mc_if_nested:
-    %\bool_gset_true:N \g_@@_in_mc_bool
-    \bool_set_false:N\l_@@_mc_artifact_bool
-    \int_gincr:N \c at g_@@_MCID_abs_int
-    \tl_clear:N \l_@@_mc_key_properties_tl
-    \keys_set:nn { @@ / mc }{ label={}, #1 }
-    %check that a tag or artifact has been used
-    \@@_check_mc_tag:N \l_@@_mc_key_tag_tl
-    %set the attributes:
-    \@@_mc_lua_set_mc_type_attr:o  { \l_@@_mc_key_tag_tl }
-    \bool_if:NF \l_@@_mc_artifact_bool
-      { % store the absolute num name in a label:
-        \tl_if_empty:NF {\l_@@_mc_key_label_tl}
-          {
-            \@@_mc_handle_mc_label:n { \l_@@_mc_key_label_tl }
-          }
-       % if not stashed record the absolute number
-        \bool_if:NF \l_@@_mc_key_stash_bool
-          {
-            \exp_args:Nx \@@_mc_handle_stash:n { \@@_get_mc_abs_cnt: }
-          }
-      }
-    %\bool_set_false:N\l_@@_mc_artifact_bool
-    %\group_end:
-  }
-
-
-\cs_new_protected:Nn \tag_mc_end:
-  {
-    %\@@_check_mc_if_open:
-    %\bool_gset_false:N \g_@@_in_mc_bool
-    \bool_set_false:N\l_@@_mc_artifact_bool
-    \@@_mc_lua_unset_mc_type_attr:
-    \tl_set:Nn  \l_@@_mc_key_tag_tl { }
-  }
-
-
-
-\cs_new_protected:Nn \tag_mc_use:n %#1: label name
-  {
-    \tl_set:Nx  \l_tmpa_tl { \@@_ref_value:enn{tagpdf-#1}{tagmcabs}{} }
-    \tl_if_empty:NTF\l_tmpa_tl
-      {
-        \msg_warning:nnn {tag} {mc-label-unknown} { #1 }
-      }
-      {
-        \@@_mc_handle_stash:o { \l_tmpa_tl }
-      }
-  }
-
-
-
-\cs_new:Nn \@@_get_data_mc_tag: { \l_@@_mc_key_tag_tl }
-%</luamode>
-%    \end{macrocode}

Modified: trunk/Master/texmf-dist/source/latex/tagpdf/tagpdf-roles.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/tagpdf/tagpdf-roles.dtx	2021-06-30 20:41:50 UTC (rev 59768)
+++ trunk/Master/texmf-dist/source/latex/tagpdf/tagpdf-roles.dtx	2021-06-30 21:14:14 UTC (rev 59769)
@@ -21,28 +21,60 @@
 %    https://github.com/u-fischer/tagpdf
 %
 % for those people who are interested.
-%
+%<*driver>
+\RequirePackage{pdfmanagement-testphase}
+\DeclareDocumentMetadata{}
+\makeatletter
+\declare at file@substitution{doc.sty}{doc-v3beta.sty}
+\makeatother
+\documentclass{l3doc}
+\usepackage{array,booktabs,caption}
+\hypersetup{pdfauthor=Ulrike Fischer,
+ pdftitle=tagpdf-checks module (tagpdf)}
+\begin{document}
+  \DocInput{\jobname.dtx}
+\end{document}
+%</driver>
 % \fi
+% \title{^^A
+%   The \pkg{tagpdf-roles} module\\ Tags, roles and namesspace code   ^^A
+%   \\ Part of the tagpdf package
+% }
 %
+% \author{^^A
+%  Ulrike Fischer\thanks
+%    {^^A
+%      E-mail:
+%        \href{mailto:fischer at troubleshooting-tex.de}
+%          {fischer at troubleshooting-tex.de}^^A
+%    }^^A
+% }
+%
+% \date{Version 0.9, released 2021-06-29}
+% \maketitle
+% \begin{implementation}
 %    \begin{macrocode}
 %<@@=tag>
-%<*roles>
-\ProvidesExplPackage {tagpdf-roles-code} {2021-06-14} {0.82}
+%<*header>
+\ProvidesExplPackage {tagpdf-roles-code} {2021-06-29} {0.9}
  {part of tagpdf - code related to roles and structure names}
+%</header>
 %    \end{macrocode}
-% \section{Variables}
+% \section{Code related to roles and structure names}
+% \subsection{Variables}
 % Tags have both a name (a string) and a number (for the lua attribute).
 % Testing a name is easier with a prop, while accessing with a number is
 % better done with a seq. So both are used and must be kept in sync if a new
 % tag is added. The number is only relevant for the MC type, tags with the same
 % name from different names spaces can have the same number.
-% \begin{macro}{\g_@@_role_tags_seq,\g_@@_role_tags_prop}
+% \begin{variable}{\g_@@_role_tags_seq,\g_@@_role_tags_prop}
 %    \begin{macrocode}
+%<*package>
 \@@_seq_new:N  \g_@@_role_tags_seq  %to get names (type/NS) from numbers
 \@@_prop_new:N \g_@@_role_tags_prop %to get numbers  from names (type/NS)
 %    \end{macrocode}
-% \end{macro}
-% \begin{macro}{\g_@@_role_tags_NS_prop}
+% \end{variable}
+% \begin{variable}{\g_@@_role_tags_NS_prop}
 % in pdf 2.0 tags belong to a name space. For every tag we store a default
 % name space.
 % The keys are the tags, the value shorthands like pdf2, or mathml.
@@ -50,8 +82,8 @@
 %    \begin{macrocode}
 \prop_new:N    \g_@@_role_tags_NS_prop %to namespace info
 %    \end{macrocode}
-% \end{macro}
-% \begin{macro}{\g_@@_role_NS_prop}
+% \end{variable}
+% \begin{variable}{\g_@@_role_NS_prop}
 % The standard names spaces are the following. The keys are the name
 % tagpdf will use,  the urls are the identifier in the namespace object.
 % \begin{description}
@@ -68,13 +100,28 @@
 %    \begin{macrocode}
 \prop_new:N \g_@@_role_NS_prop % collect namespaces
 %    \end{macrocode}
-% \end{macro}
-% \section{Namesspaces}
+% \end{variable}
+%
+% We need also a bunch of temporary variables:
+% \begin{variable}
+%  {
+%     \l_@@_role_tag_tmpa_tl
+%     ,\l_@@_role_tag_namespace_tmpa_tl
+%     ,\l_@@_role_role_tmpa_tl
+%     ,\l_@@_role_role_namespace_tmpa_tl
+%  }
+%    \begin{macrocode}
+\tl_new:N \l_@@_role_tag_tmpa_tl
+\tl_new:N \l_@@_role_tag_namespace_tmpa_tl
+\tl_new:N \l_@@_role_role_tmpa_tl
+\tl_new:N \l_@@_role_role_namespace_tmpa_tl
+%    \end{macrocode}
+% \end{variable}
+% \subsection{Namesspaces}
 % The following commands setups a names space. Namespace dictionaries can
 % contain an optional |/Schema| and |/RoleMapNS| entry. We only reserve the
 % objects but delay the writing to the finish code, where we can test if the
 % keys and the name spaces are actually needed
-% \begin{macro}{\@@_role_NS_new:nn}
 % This commands setups objects for the name space and its rolemap. It also
 % initialize a prop to collect the rolemaps if needed.
 % \begin{function}{\@@_role_NS_new:nnn}
@@ -85,7 +132,7 @@
 % \begin{macro}{\@@_role_NS_new:nnn}
 %    \begin{macrocode}
 \cs_new_protected:Npn \@@_role_NS_new:nnn #1 #2 #3
-  { \msg_redirect_name:nnn { pdfdict } { empty-value } { none }
+  {
     \pdf_object_new:nn {tag/NS/#1}{dict}
     \pdfdict_new:n     {g_@@_role/Namespace_#1_dict}
     \pdf_object_new:nn {@@/RoleMapNS/#1}{dict}
@@ -95,15 +142,20 @@
       {Type}
       {/Namespace}
     \pdf_string_from_unicode:nnN{utf8/string}{#2}\l_tmpa_str
-    \pdfdict_gput:nnx
-      {g_@@_role/Namespace_#1_dict}
-      {NS}
-      {\l_tmpa_str}
+    \tl_if_empty:NF \l_tmpa_str
+      {
+        \pdfdict_gput:nnx
+          {g_@@_role/Namespace_#1_dict}
+          {NS}
+          {\l_tmpa_str}
+      }
     %RoleMapNS is added in tree
-    \pdfdict_gput:nnx{g_@@_role/Namespace_#1_dict}
-      {Schema}{#3}
+    \tl_if_empty:nF  {#3}
+     {
+       \pdfdict_gput:nnx{g_@@_role/Namespace_#1_dict}
+        {Schema}{#3}
+     }
     \prop_gput:Nnx \g_@@_role_NS_prop {#1}{\pdf_object_ref:n{tag/NS/#1}~}
-    \msg_redirect_name:nnn { pdfdict } { empty-value } { warning }
   }
 %    \end{macrocode}
 % \end{macro}
@@ -112,6 +164,7 @@
 % be fixed by setting a seed. We fake a sort of
 % GUID but not try to be really exact as it doesn't matter ...
 %
+% \begin{variable}{\c_@@_role_userNS_id_str}
 %    \begin{macrocode}
 \str_const:Nx \c_@@_role_userNS_id_str
   { data:,
@@ -128,6 +181,7 @@
     \int_to_Hex:n{\int_rand:n {16777215}}
   }
 %    \end{macrocode}
+% \end{variable}
 % Now we setup the standard names spaces. Currently only if we detect pdf2.0 but
 % this will perhaps have to change if the structure code gets to messy.
 %    \begin{macrocode}
@@ -141,7 +195,7 @@
   }
 %    \end{macrocode}
 %
-% \section{Data}
+% \subsection{Data}
 % In this section we setup the standard data.
 % At first the list of structure types. We split them in three lists,
 % the tags with which are both in the pdf and pdf2 namespace,
@@ -148,7 +202,7 @@
 % the one only in pdf and the one with the tags only in pdf2.
 % We also define a rolemap for the pdfII only type to pdf so that
 % they can always be used.
-% \begin{macro}
+% \begin{variable}
 %   {
 %     \c_@@_role_sttags_pdf_pdfII_clist,
 %     \c_@@_role_sttags_only_pdf_clist,
@@ -160,7 +214,8 @@
 %
 \clist_const:Nn \c_@@_role_sttags_pdf_pdfII_clist
   {
-    Document,   %A complete document. This is the root element of any structure tree containing
+    Document,   %A complete document. This is the root element
+                %of any structure tree containing
                 %multiple parts or multiple articles.
     Part,       %A large-scale division of a document.
     Sect,       %A container for grouping related content elements.
@@ -205,13 +260,16 @@
 
 \clist_const:Nn \c_@@_role_sttags_only_pdf_clist
  {
-   Art,%A relatively self-contained body of text constituting a single narrative or exposition
-   BlockQuote, %A portion of text consisting of one or more paragraphs attributed to someone other
-               %than the author of the  surrounding text.
-   TOC,        %A list made up of table of contents item entries (structure tag TOCI; see below)
-                %and/or other nested table of contents entries
-   TOCI,       %An individual member of a table of contents. This entry's children can be any of
-               %the following structure  tags:
+   Art,        %A relatively self-contained body of text
+               %constituting a single narrative or exposition
+   BlockQuote, %A portion of text consisting of one or more paragraphs
+               %attributed to someone other than the author of the
+               %surrounding text.
+   TOC,        %A list made up of table of contents item entries
+               %(structure tag TOCI; see below) and/or other
+               %nested table of contents entries
+   TOCI,       %An individual member of a table of contents.
+               %This entry's children can be any of the following structure  tags:
                %Lbl,Reference,NonStruct,P,TOC
    Index,
    Private,
@@ -448,7 +506,7 @@
     Strong= Span,
   }
 %    \end{macrocode}
-% \end{macro}
+% \end{variable}
 % We fill the structure tags in to the seq. We allow all pdf1.7 and pdf2.0,
 % and role map if needed the 2.0 tags.
 %    \begin{macrocode}
@@ -482,7 +540,6 @@
 % For luatex and the MC we need a name/number relation.
 % The name space is not relevant.
 %    \begin{macrocode}
-
 \int_step_inline:nnnn { 1 }{ 1 }{ \seq_count:N \g_@@_role_tags_seq }
   {
     \@@_prop_gput:Nxn \g_@@_role_tags_prop
@@ -493,24 +550,29 @@
   }
 %    \end{macrocode}
 %
-% \section{Adding new tags and rolemapping}
+% \subsection{Adding new tags and rolemapping}
 %
-% \subsection{pdf 1.7 and earlier}
+% \subsubsection{pdf 1.7 and earlier}
 % With this versions only RoleMap is filled.
 % At first the dictionary:
+% \begin{variable}{g_@@_role/RoleMap_dict}
 %    \begin{macrocode}
 \pdfdict_new:n {g_@@_role/RoleMap_dict}
 %    \end{macrocode}
+% \end{variable}
 % \begin{macro}{\@@_role_add_tag:nn}
 % The pdf 1.7 version has only two arguments: new and rolemap name.
 % To make pdf 2.0 types usable we directly define a rolemapping for them.
-% TODO: add checks
+%
 %    \begin{macrocode}
 \cs_new_protected:Nn \@@_role_add_tag:nn %(new) name, reference to old
   {
     \prop_if_in:NnF \g_@@_role_tags_prop {#1}
       {
-         \msg_info:nnn { tag }{new-tag}{#1}
+        \int_compare:nNnT {\l_@@_loglevel_int} > { 0 }
+          {
+            \msg_info:nnn { tag }{new-tag}{#1}
+          }
          \@@_seq_gput_right:Nn \g_@@_role_tags_seq { #1 }
          \@@_prop_gput:Nnx \g_@@_role_tags_prop    { #1 }
            {
@@ -518,7 +580,7 @@
            }
          \prop_gput:Nnn \g_@@_role_tags_NS_prop    { #1 }{ user }
       }
-    %\@@_check_add_tag_role:nn {#1}{#2} %%!TODO
+    \@@_check_add_tag_role:nn {#1}{#2}
     \tl_if_empty:nF { #2 }
       {
         \pdfdict_gput:nnx {g_@@_role/RoleMap_dict}
@@ -538,15 +600,17 @@
 
 %    \end{macrocode}
 % \end{macro}
-%
+% \subsubsection{The pdf 2.0 version}
 % \begin{macro}{\@@_role_add_tag:nnnn}
-% The pdf 2.0 version takes for arguments:
+% The pdf 2.0 version takes four arguments:
 % tag/namespace/role/namespace
-% TODO: add checks
 %    \begin{macrocode}
 \cs_new_protected:Nn \@@_role_add_tag:nnnn %tag/namespace/role/namespace
   {
-    \msg_info:nnn { tag }{new-tag}{#1}
+    \int_compare:nNnT {\l_@@_loglevel_int} > { 0 }
+      {
+        \msg_info:nnn { tag }{new-tag}{#1}
+      }
     \@@_seq_gput_right:Nn \g_@@_role_tags_seq { #1 }
     \@@_prop_gput:Nnx \g_@@_role_tags_prop    { #1 }
        {
@@ -553,7 +617,7 @@
          \seq_count:N \g_@@_role_tags_seq
        }
     \prop_gput:Nnn \g_@@_role_tags_NS_prop    { #1 }{ #2 }
-    %\@@_check_add_tag_role:nn {#1}{#3} %TODO
+    \@@_check_add_tag_role:nn {#1}{#3}
     \pdfdict_gput:nnx {g_@@_role/RoleMapNS_#2_dict}{#1}
        {
          [
@@ -566,15 +630,11 @@
 \cs_generate_variant:Nn \@@_role_add_tag:nnnn {VVVV}
 %    \end{macrocode}
 % \end{macro}
-%  The user interface use the key add-new-tag, which takes either a
+% \subsection{Key-val user interface}
+%  The user interface use the key |add-new-tag|, which takes either a
 %  keyval list as argument, or a tag/role.
+%  \begin{macro}{tag,tag-namespace,role,role-namespace,add-new-tag}
 %    \begin{macrocode}
-
-\tl_new:N \l_@@_role_tag_tmpa_tl
-\tl_new:N \l_@@_role_tag_namespace_tmpa_tl
-\tl_new:N \l_@@_role_role_tmpa_tl
-\tl_new:N \l_@@_role_role_namespace_tmpa_tl
-
 \keys_define:nn { @@ / tag-role }
   {
     ,tag .tl_set:N = \l_@@_role_tag_tmpa_tl
@@ -632,7 +692,8 @@
        }
     }
   }
-
-
-%</roles>
+%</package>
 %    \end{macrocode}
+% \end{macro}
+% \end{implementation}
+% \PrintIndex

Modified: trunk/Master/texmf-dist/source/latex/tagpdf/tagpdf-space.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/tagpdf/tagpdf-space.dtx	2021-06-30 20:41:50 UTC (rev 59768)
+++ trunk/Master/texmf-dist/source/latex/tagpdf/tagpdf-space.dtx	2021-06-30 21:14:14 UTC (rev 59769)
@@ -2,7 +2,7 @@
 %
 %% File: tagpdf-space.dtx
 %
-% Copyright (C) 2019 Ulrike Fischer
+% Copyright (C) 2019-2021 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
@@ -21,26 +21,75 @@
 %    https://github.com/u-fischer/tagpdf
 %
 % for those people who are interested.
-%
+%<*driver>
+\RequirePackage{pdfmanagement-testphase}
+\DeclareDocumentMetadata{}
+\makeatletter
+\declare at file@substitution{doc.sty}{doc-v3beta.sty}
+\makeatother
+\documentclass{l3doc}
+\usepackage{array,booktabs,caption}
+\hypersetup{pdfauthor=Ulrike Fischer,
+ pdftitle=tagpdf-space module (tagpdf)}
+\begin{document}
+  \DocInput{\jobname.dtx}
+\end{document}
+%</driver>
 % \fi
+% \title{^^A
+%   The \pkg{tagpdf-space} module\\ Code related to real space chars   ^^A
+%   \\ Part of the tagpdf package
+% }
 %
+% \author{^^A
+%  Ulrike Fischer\thanks
+%    {^^A
+%      E-mail:
+%        \href{mailto:fischer at troubleshooting-tex.de}
+%          {fischer at troubleshooting-tex.de}^^A
+%    }^^A
+% }
+%
+% \date{Version 0.9, released 2021-06-29}
+% \maketitle
+% \begin{implementation}
 %    \begin{macrocode}
 %<@@=tag>
-%<*space>
-\ProvidesExplPackage {tagpdf-space-code} {2021-06-14} {0.82}
+%<*header>
+\ProvidesExplPackage {tagpdf-space-code} {2021-06-29} {0.9}
  {part of tagpdf - code related to real space chars}
-% luatex uses an attribute (declared in the driver file) and some luacode in tagpdf.lua
-% perhaps I will split the code by engine in the future
-
+%</header>
+%    \end{macrocode}
+% \section{Code for interword spaces}
+% The code is engine/backend dependant. Basically only pdftex and luatex
+% support real space chars. Most of the code for luatex which uses attributes
+% is in the lua code, here are only the keys.
+%
+% \begin{macro}{interwordspace,show-spaces}
+%    \begin{macrocode}
+%<*package>
 \sys_if_engine_pdftex:T
   {
-    \pdfglyphtounicode{space}{0020}
-    \keys_define:nn { @@ / setup }
+    \sys_if_output_pdf:TF
       {
-        interwordspace .choices:nn = { true, on }  { \pdfinterwordspaceon },
-        interwordspace .choices:nn = { false, off }{ \pdfinterwordspaceon },
-        show-spaces .bool_set:N = \l_@@_showspaces_bool
+        \pdfglyphtounicode{space}{0020}
+        \keys_define:nn { @@ / setup }
+          {
+            interwordspace .choices:nn = { true, on }  { \pdfinterwordspaceon },
+            interwordspace .choices:nn = { false, off }{ \pdfinterwordspaceon },
+            interwordspace .default:n = true,
+            show-spaces .bool_set:N = \l_@@_showspaces_bool
+          }
       }
+      {
+        \keys_define:nn { @@ / setup }
+          {
+            interwordspace .choices:nn = { true, on, false, off }
+              { \msg_warning:nnn {tag}{sys-no-interwordspace}{dvi}  },
+            interwordspace .default:n = true,
+            show-spaces .bool_set:N = \l_@@_showspaces_bool
+          }
+      }
   }
 
 
@@ -50,29 +99,24 @@
       {
         interwordspace .choices:nn =
                                  { true, on }
-                                 { \directlua{ltx.@@.func.markspaceon()} },
+                                 {
+                                   \bool_gset_true:N \g_@@_active_space_bool
+                                   \lua_now:e{ltx.@@.func.markspaceon()}
+                                 },
         interwordspace .choices:nn =
                                  { false, off }
-                                 {\directlua{ltx.@@.func.markspaceoff()} },
+                                 {
+                                  \bool_gset_false:N \g_@@_active_space_bool
+                                  \lua_now:e{ltx.@@.func.markspaceoff()}
+                                 },
+        interwordspace .default:n = true,
         show-spaces      .choice:,
         show-spaces  / true  .code:n =
-                                 {\directlua{ltx.@@.trace.showspaces=true}},
+                                 {\lua_now:e{ltx.@@.trace.showspaces=true}},
         show-spaces  / false .code:n =
-                                 {\directlua{ltx.@@.trace.showspaces=nil}},
+                                 {\lua_now:e{ltx.@@.trace.showspaces=nil}},
         show-spaces .default:n = true
       }
-
-    \cs_new_protected:Nn \@@_fakespace:
-      {
-        \group_begin:
-        \setattribute\g_@@_interwordspace_attr{1}
-        \setattribute\g_@@_interwordfont_attr
-          {
-            \directlua{tex.print(\the\catcodetable at latex, font.current())}
-          }
-        \skip_horizontal:n{\c_zero_skip}
-        \group_end:
-      }
   }
 
 \sys_if_engine_xetex:T
@@ -79,11 +123,33 @@
   {
     \keys_define:nn { @@ / setup }
       {
-        interwordspace .choices:nn = { true, on }  { \msg_warning:nnn {tag}{sys-no-interwordspace}{xetex}  },
-        interwordspace .choices:nn = { false, off }{ \msg_warning:nnn {tag}{sys-no-interwordspace}{xetex}  },
+        interwordspace .choices:nn = { true, on }
+          { \msg_warning:nnn {tag}{sys-no-interwordspace}{xetex}  },
+        interwordspace .choices:nn = { false, off }
+          { \msg_warning:nnn {tag}{sys-no-interwordspace}{xetex}  },
+        interwordspace .default:n = true,
         show-spaces .bool_set:N = \l_@@_showspaces_bool
       }
   }
-
-%</space>
 %    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_fakespace:}
+% For luatex we need a command for the fake space as equivalent of the pdftex
+% primitive.
+%    \begin{macrocode}
+\sys_if_engine_luatex:T
+  {
+    \cs_new_protected:Nn \@@_fakespace:
+      {
+        \group_begin:
+        \lua_now:e{ltx.@@.func.fakespace()}
+        \skip_horizontal:n{\c_zero_skip}
+        \group_end:
+      }
+  }
+%</package>
+%    \end{macrocode}
+% \end{macro}
+% \end{implementation}
+% \PrintIndex

Modified: trunk/Master/texmf-dist/source/latex/tagpdf/tagpdf-struct.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/tagpdf/tagpdf-struct.dtx	2021-06-30 20:41:50 UTC (rev 59768)
+++ trunk/Master/texmf-dist/source/latex/tagpdf/tagpdf-struct.dtx	2021-06-30 21:14:14 UTC (rev 59769)
@@ -21,32 +21,234 @@
 %    https://github.com/u-fischer/tagpdf
 %
 % for those people who are interested.
-%
+%<*driver>
+\RequirePackage{pdfmanagement-testphase}
+\DeclareDocumentMetadata{}
+\makeatletter
+\declare at file@substitution{doc.sty}{doc-v3beta.sty}
+\makeatother
+\documentclass{l3doc}
+\usepackage{array,booktabs,caption}
+\hypersetup{pdfauthor=Ulrike Fischer,
+ pdftitle=tagpdf-tree module (tagpdf)}
+\begin{document}
+  \DocInput{\jobname.dtx}
+\end{document}
+%</driver>
 % \fi
+% \title{^^A
+%   The \pkg{tagpdf-struct} module\\ Commands to create the structure   ^^A
+%   \\ Part of the tagpdf package
+% }
 %
+% \author{^^A
+%  Ulrike Fischer\thanks
+%    {^^A
+%      E-mail:
+%        \href{mailto:fischer at troubleshooting-tex.de}
+%          {fischer at troubleshooting-tex.de}^^A
+%    }^^A
+% }
+%
+% \date{Version 0.9, released 2021-06-29}
+% \maketitle
+% \begin{documentation}
+% \section{Public Commands}
+% \begin{function}{\tag_struct_begin:n,\tag_struct_end:}
+%   \begin{syntax}
+%     \cs{tag_struct_begin:n}\Arg{key-values}\\
+%     \cs{tag_struct_end:}
+%   \end{syntax}
+%  These commands start and end a new structure.
+%  They don't start a group. They set all their values globally.
+% \end{function}
+%  \begin{function}{\tag_struct_use:n}
+%   \begin{syntax}
+%     \cs{tag_struct_use:n}\Arg{label}
+%   \end{syntax}
+% These commands insert a structure previously stashed away as kid
+% into the currently active structure.
+% A structure should be used only once,
+% if the structure already has a parent a warning is issued.
+% \end{function}
+% The following two functions are used to add annotations. They must be used
+% together and with care to get the same numbers. Perhaps some improvements are needed
+% here.
+%  \begin{function}{\tag_struct_insert_annot:nn}
+%   \begin{syntax}
+%     \cs{tag_struct_insert_annot:nn}\Arg{object reference}\Arg{struct parent number}
+%   \end{syntax}
+% This inserts an annotation in the structure. \meta{object reference}
+% is there reference to the annotation. \meta{struct parent number}
+% should be the same number as had been inserted with \cs{tag_struct_parent_int:}
+% as |StructParent| value to the dictionary of the annotion.
+% The command will increase the value of the counter
+% used by \cs{tag_struct_parent_int:}.
+% \end{function}
+% \begin{function}{\tag_struct_parent_int:}
+%   \begin{syntax}
+%     \cs{tag_struct_parent_int:}
+%   \end{syntax}
+% This gives back the next free /StructParent number (assuming that it is
+% together with \cs{tag_struct_insert_annot:nn} which will increase the number.
+% \end{function}
+% \section{Public keys}
+% \subsection{Keys for the structure commands}
+% \begin{function}{tag}
+% This is required. The value of the key is normally one of the
+% standard types listed in section \ref{sec:new-tag}.
+% It is possible to setup new tags/types.
+% The value can also be of the form |type/NS|, where |NS| is the
+% shorthand of a declared name space.
+% Currently the names spaces |pdf|, |pdf2|, |mathml| and |user| are defined.
+% This allows to use a different name space than
+% the one connected by default to the tag. But normally this should not be needed.
+% \end{function}
+% \begin{function}{stash}
+%  Normally a new structure inserts itself as a kid
+%  into the currently active structure. This key prohibits this.
+%  The structure is nevertheless from now on
+%  \enquote{the current active structure}
+%  and parent for following  marked content and structures.
+% \end{function}
+% \begin{function}{label}
+% This key sets a label by which
+% one can use the structure later in another structure.
+% Internally the label name will start with \texttt{tagpdfstruct-}.
+% \end{function}
+% \begin{function}{title,title-o}
+% This keys allows to set the dictionary entry
+% \texttt{/Title} in the structure object.
+% The value is handled as verbatim string and hex encoded.
+% Commands are not expanded. |title-o| will expand the value once.
+% \end{function}
+%
+% \begin{function}{alttext,alttext-o}
+% This key inserts an \texttt{/Alt} value in the dictionary of structure object.
+% The value is handled as verbatim string and hex encoded.
+% |alttext-o| will expand the value once.
+% \end{function}
+% \begin{function}{actualtext,actualtext-o}
+% This key inserts an \texttt{/ActualText} value in the dictionary of structure object.
+% The value is handled as verbatim string and hex encoded.
+% |actualtext-o| will expand the value once.
+% \end{function}
+% \begin{function}{lang}
+% This key allows to set the language for a structure element. The value should be a bcp-identifier,
+% e.g. |de-De|.
+% \end{function}
+% \begin{function}{ref}
+%  This key allows to add references to other structure elements,
+%  it adds the |/Ref| array to the structure.
+% The value should be a comma separated list of structure labels
+% set with the |label| key. e.g. |ref={label1,label2}|.
+% \end{function}
+% \begin{function}{E}
+%  This key sets the |/E| key, the expanded form of an
+%  abbreviation or an acronym
+%  (I couldn't think of a better name, so I sticked to E).
+% \end{function}
+% \begin{function}{AF,AFinline,AFinline-o}
+% \begin{syntax}
+% AF = \meta{object name}\\
+% AF-inline = \meta{text content}
+% \end{syntax}
+% These keys allows to reference an associated file in the structure element.
+% The value \meta{object name} should be the name of an object pointing
+% to the \texttt{/Filespec} dictionary as expected by
+% |\pdf_object_ref:n| from a current \texttt{l3kernel}.
+%
+% The value |AF-inline| is some text,
+% which is embedded in the PDF as a text file with mime type text/plain.
+% |AF-inline-o| is like |AF-inline| but expands the value once.
+%
+% Future versions will perhaps extend this to more mime types, but it is
+% still a research task to find out what is really needed.
+%
+% \end{function}
+%
+% \begin{function}{attribute}
+%  This key takes as argument a comma list of attribute names
+%  (use braces to protect the commas from the external key-val parser)
+%  and allows to add one or more attribute dictionary entries in
+%  the structure object. As an example
+%     \begin{verbatim}
+%      \tagstructbegin{tag=TH,attribute= TH-row}
+%      \end{verbatim}
+%  Attribute names and their content must be declared first in \cs{tagpdfsetup}.
+%
+%  \end{function}
+%
+% \begin{function}{attribute-class}
+%  This key takes as argument a comma list of attribute class names
+%  (use braces to protect the commas from the external key-val parser)
+%  and allows to add one or more attribute classes to the structure object.
+%
+%  Attribute class names and their content
+%  must be declared first in \cs{tagpdfsetup}.
+% \end{function}
+% \subsection{Setup keys}
+% \begin{function}{newattribute}
+% \begin{syntax}
+% newattribute = \Arg{name}\Arg{Content}
+% \end{syntax}
+% This key can be used in the setup command \cs{tagpdfsetup} and allow to declare a
+% new attribute, which can be used as attribute or attribute class.
+% The value are two brace groups, the first contains the name, the second the content.
+% \begin{verbatim}
+% \tagpdfsetup
+%  {
+%   newattribute =
+%    {TH-col}{/O /Table /Scope /Column},
+%   newattribute =
+%    {TH-row}{/O /Table /Scope /Row},
+%   }
+% \end{verbatim}
+%
+% \end{function}
+% \end{documentation}
+% \begin{implementation}
 %    \begin{macrocode}
 %<@@=tag>
-%<*struct>
-\ProvidesExplPackage {tagpdf-struct-code} {2021-06-14} {0.82}
+%<*header>
+\ProvidesExplPackage {tagpdf-struct-code} {2021-06-29} {0.9}
  {part of tagpdf - code related to storing structure}
+%</header>
 %    \end{macrocode}
+% \section{Variables}
+% \begin{variable}{\c at g_@@_struct_abs_int}
+% Every structure will have a unique, absolute number.
 % I will use a latex counter for the structure count
-% to have a chance to avoid double structures in align etc
+% to have a chance to avoid double structures in align etc.
+%
 %    \begin{macrocode}
+%<*package>
 \newcounter  { g_@@_struct_abs_int }
 \int_gzero:N \c at g_@@_struct_abs_int
 %    \end{macrocode}
-% a sequence to store structnum -> the obj numbers
-% to allow easy mapping over the structures
+% \end{variable}
+%
+% \begin{variable}{\g_@@_struct_objR_seq}
+% a sequence to store mapping between the
+% structure number and the object number.
+% We assume that structure numbers are assign
+% consecutively and so the index of the seq can be used.
+% A seq allows easy mapping over the structures.
 %    \begin{macrocode}
 \@@_seq_new:N  \g_@@_struct_objR_seq
 %    \end{macrocode}
-% a sequence for the structure stack.
+% \end{variable}
+%
+% \begin{variable}{\g_@@_struct_stack_seq}
+% A stack sequence for the structure stack.
 % When a sequence is opened it's number is put on the stack.
 %    \begin{macrocode}
 \seq_new:N    \g_@@_struct_stack_seq
 \seq_gpush:Nn \g_@@_struct_stack_seq {0}
 %    \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\g_@@_struct_tag_stack_seq}
 % We will perhaps also need the tags. While it is possible to get them from the
 % numbered stack, lets build a tag stack too.
 %    \begin{macrocode}
@@ -53,25 +255,44 @@
 \seq_new:N    \g_@@_struct_tag_stack_seq
 \seq_gpush:Nn \g_@@_struct_tag_stack_seq {Root}
 %    \end{macrocode}
-%this variables will hold the number of top entry and the parent on the stack
+% \end{variable}
+%
+% \begin{variable}{\g_@@_struct_stack_current_tl,\l_@@_struct_stack_parent_tmpa_tl}
+% The global variable will hold the current structure number.
+% The local temporary variable will hold the parent when we fetch it from the stack.
 %    \begin{macrocode}
-\tl_new:N     \l_@@_struct_stack_parent_tmp_tl
 \tl_new:N     \g_@@_struct_stack_current_tl
+\tl_new:N     \l_@@_struct_stack_parent_tmpa_tl
 %    \end{macrocode}
-% I need at least one structure: the StructTreeRoot
+% \end{variable}
+%
+% I will need at least one structure: the StructTreeRoot
 % normally it should have only one kid, e.g. the document element.
 
 % The data of the StructTreeRoot and the StructElem are in properties:
-% \g_@@_struct_0_prop for the root
-% \g_@@_struct_N_prop, N >=1
-% they have all the keys
-% objnum    - number,
-% Type      - StructTreeRoot or StructElem
-% num - number (identical to the num in the name, or 0 for the root)
+% |\g_@@_struct_0_prop| for the root and
+% |\g_@@_struct_N_prop|, $N \geq =1$ for the other.
+%
+% This creates quite a number of properties, so perhaps we will have to
+% do this more efficiently in the future.
+%
+% All properties have at least the keys
+% \begin{description}
+%    \item[Type] StructTreeRoot or StructElem
+%  \end{description}
 % and the keys from the two following lists
 % (the root has a special set of properties).
 % the values of the prop should be already escaped properly
 % when the entries are created (title,lange,alt,E,actualtext)
+% \begin{variable}
+%   {
+%     \c_@@_struct_StructTreeRoot_entries_seq,
+%     \c_@@_struct_StructElem_entries_seq
+%   }
+%  These seq contain the keys we support in the two object types.
+%  They are currently no longer used, but are provided as documentation and
+%  for potential future checks.
+%  They should be adapted if there are changes in the PDF format.
 %    \begin{macrocode}
 \seq_const_from_clist:Nn \c_@@_struct_StructTreeRoot_entries_seq
   {%p. 857/858
@@ -79,7 +300,7 @@
     K,                 % kid, dictionary or array of dictionaries
     IDTree,            % currently unused
     ParentTree,        % required,obj ref to the parent tree
-    ParentTreeNextKey, %optional
+    ParentTreeNextKey, % optional
     RoleMap,
     ClassMap,
     Namespaces
@@ -96,11 +317,13 @@
     K,                 %kids
     A,                 %attributes, probably unused
     C,                 %class ""
-    %R,
+    %R,                %attribute revision number, irrelevant for us as we
+                       % don't update/change existing PDF and (probably)
+                       % deprecated in PDF 2.0
     T,                 %title, value in () or <>
     Lang,              %language
     Alt,               % value in () or <>
-    E,                 %abreviation
+    E,                 % abreviation
     ActualText,
     AF,                 %pdf 2.0, array of dict, associated files
     NS,                 %pdf 2.0, dict, namespace
@@ -107,11 +330,42 @@
     PhoneticAlphabet,   %pdf 2.0
     Phoneme             %pdf 2.0
   }
-
-% I need an output handler for each prop, to get expandable output
-% see https://tex.stackexchange.com/questions/424208/expandable-version-of-a-expl3-command/424213#424213
-
-\cs_new:Nn \@@_struct_output_prop_aux:nn %#1 num, #2 key
+%    \end{macrocode}
+% \end{variable}
+%
+% \subsection{Variables used by the keys}
+% \begin{variable}{\g_@@_struct_tag_tl,\g_@@_struct_tag_NS_tl}
+% Use by the tag key to store the tag and the namespace.
+%    \begin{macrocode}
+\tl_new:N \g_@@_struct_tag_tl
+\tl_new:N \g_@@_struct_tag_NS_tl
+%    \end{macrocode}
+% \end{variable}
+% \begin{variable}{\l_@@_struct_key_label_tl}
+% This will hold the label value.
+%    \begin{macrocode}
+\tl_new:N \l_@@_struct_key_label_tl
+%    \end{macrocode}
+% \end{variable}
+% \begin{variable}{\l_@@_struct_elem_stash_bool}
+% This will keep track of the stash status
+%    \begin{macrocode}
+\bool_new:N \l_@@_struct_elem_stash_bool
+%    \end{macrocode}
+% \end{variable}
+% \section{Commands}
+%
+% The properties must be in some places handled expandably.
+% So I need an output handler for each prop, to get expandable output
+% see \url{https://tex.stackexchange.com/questions/424208}.
+% There is probably room here for a more efficient implementation.
+% TODO check if this can now be implemented with the pdfdict commands.
+% The property contains currently non pdf keys, but e.g. object numbers are
+% perhaps no longer needed as we have named object anyway.
+%
+% \begin{macro}{\@@_struct_output_prop_aux:nn,\@@_new_output_prop_handler:n}
+%    \begin{macrocode}
+\cs_new:Npn \@@_struct_output_prop_aux:nn #1 #2 %#1 num, #2 key
   {
     \prop_if_in:cnT
       { g_@@_struct_#1_prop }
@@ -121,7 +375,7 @@
       }
   }
 
-\cs_new:Nn \@@_new_output_prop_handler:n
+\cs_new_protected:Npn \@@_new_output_prop_handler:n #1
   {
     \cs_new:cn { @@_struct_output_prop_#1:n }
       {
@@ -128,67 +382,66 @@
         \@@_struct_output_prop_aux:nn {#1}{##1}
       }
   }
+%    \end{macrocode}
+% \end{macro}
+%
+% \subsection{Initialization of the StructTreeRoot}
+% The first structure element, the StructTreeRoot is special, so
+% created manually. The underlying object is |@@/struct/0| which is currently
+% created in the tree code (TODO move it here).
+% The |ParentTree| and |RoleMap| entries are added at begin document
+% in the tree code as they refer to object which are setup in other parts of the
+% code. This avoid timing issues.
+%
+%    \begin{macrocode}
+\tl_gset:Nn \g_@@_struct_stack_current_tl {0}
+%    \end{macrocode}
 
-
-% the first one, the StructTreeRoot is special, so
-% created manually:
+%
+% \begin{variable}{g_@@_struct_0_prop,g_@@_struct_kids_0_seq}
+%    \begin{macrocode}
 \@@_prop_new:c { g_@@_struct_0_prop }
 \@@_new_output_prop_handler:n {0}
-\tl_gset:Nn \g_@@_struct_stack_current_tl {0}
-
 \@@_seq_new:c  { g_@@_struct_kids_0_seq }
 
-% new
-\@@_prop_gput:cnx
-  { g_@@_struct_0_prop }
-  { objref}
-  { \pdf_object_ref:n { @@/struct/0 } }
-
 \@@_prop_gput:cnn
   { g_@@_struct_0_prop }
   { Type }
   { /StructTreeRoot }
 
-% the constants are defined in the tree code.
-\@@_prop_gput:cnx
-  { g_@@_struct_0_prop }
-  { ParentTree }
-  { \pdf_object_ref:n { @@/tree/parenttree } }
 
-\@@_prop_gput:cnx
-  { g_@@_struct_0_prop }
-  { RoleMap }
-  { \pdf_object_ref:n { @@/tree/rolemap } }
 
-\@@_prop_gput:cnn
-  { g_@@_struct_0_prop }
-  { entries }
-  { StructTreeRoot }
-
-\@@_prop_gput:cnn
-  { g_@@_struct_0_prop }
-  { num }
-  { 0 }
-
-%Namespaces are pdf 2.0 but it doesn't harm to have an empty entry
+%    \end{macrocode}
+% Namespaces are pdf 2.0 but it doesn't harm
+% to have an empty entry. We could add a test, but if the code moves into
+% the kernel, timing could get tricky.
+%    \begin{macrocode}
 \@@_prop_gput:cnx
   { g_@@_struct_0_prop }
   { Namespaces }
   { \pdf_object_ref:n { @@/tree/namespaces } }
-
-
-% commands to store the kids
-% I don't compare the page objects number yet, but always add the /Pg key, perhaps later
-
-\cs_new:Nn \@@_struct_kid_mc_gput_right:nn %#1 structure num, #2 MCID absnum%
+%    \end{macrocode}
+% \end{variable}
+% \subsection{Handlings kids}
+% Commands to store the kids. Kids in a structure can be a reference to a mc-chunk,
+% an object reference to another structure element, or a object reference to an
+% annotation (through an OBJR object).
+% \begin{macro}{\@@_struct_kid_mc_gput_right:nn}
+% The command to store an mc-chunk, this is a dictionary of type MCR.
+% It would be possible to write out the content directly as unnamed object
+% and to store only the object reference, but probably this would be slower,
+% and the PDF is more readable like this.
+% The code doesn't try to avoid the use of the /Pg key by checking page numbers.
+% That imho only slows down without much gain.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_struct_kid_mc_gput_right:nn #1 #2 %#1 structure num, #2 MCID absnum%
   {
-    %\@@_store_pdfpageref:Nn \l_tmpa_tl { \@@_ref_value:enn{mcid-#2}{tagabspage}{1} }
     \@@_seq_gput_right:cx
       { g_@@_struct_kids_#1_seq }
       {
         <<
         /Type \c_space_tl /MCR \c_space_tl
-        /Pg %\c_space_tl \l_tmpa_tl \c_space_tl 0 \c_space_tl R \c_space_tl
+        /Pg
           \c_space_tl
           \pdf_pageobject_ref:n { \@@_ref_value:enn{mcid-#2}{tagabspage}{1} }
         /MCID \c_space_tl \@@_ref_value:enn{mcid-#2}{tagmcid}{1}
@@ -195,25 +448,40 @@
         >>
       }
   }
-
-\cs_new:Nn\@@_struct_kid_struct_gput_right:nn %#1 num of parent struct, #2 kid struct
+%    \end{macrocode}
+% \end{macro}
+%  \begin{macro}
+%    {
+%      \@@_struct_kid_struct_gput_right:nn,\@@_struct_kid_struct_gput_right:xx
+%    }
+%  This commands adds a structure as kid. We only need to record the object
+%  reference in the sequence.
+%    \begin{macrocode}
+\cs_new_protected:Npn\@@_struct_kid_struct_gput_right:nn #1 #2 %#1 num of parent struct, #2 kid struct
   {
     \@@_seq_gput_right:cx
       { g_@@_struct_kids_#1_seq }
       {
-        \prop_item:cn
-          { g_@@_struct_#2_prop }
-          { objref }
+        \pdf_object_ref:n { @@/struct/#2 }
       }
  }
 
-\cs_new:Nn\@@_struct_kid_OBJR_gput_right:nn %#1 num of parent struct, #2 obj reference
+\cs_generate_variant:Nn \@@_struct_kid_struct_gput_right:nn {xx}
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}
+%  {\@@_struct_kid_OBJR_gput_right:nn,\@@_struct_kid_OBJR_gput_right:xx}
+% At last the command to add an OBJR object. This has to write an object first.
+% The first argument is the number of the parent structure, the second the
+% (expanded) object reference of the annotation.
+%    \begin{macrocode}
+\cs_new_protected:Npn\@@_struct_kid_OBJR_gput_right:nn #1 #2 %#1 num of parent struct,
+                                                             %#2 obj reference
   {
-    \pdf_object_unnamed_write:nx
+    \pdf_object_unnamed_write:nn
       { dict }
       {
-        /Type \c_space_tl /OBJR \c_space_tl
-        /Obj~#2
+        /Type/OBJR/Obj~#2
       }
     \@@_seq_gput_right:cx
       { g_@@_struct_kids_#1_seq }
@@ -222,27 +490,43 @@
       }
   }
 
-\cs_generate_variant:Nn\@@_struct_kid_OBJR_gput_right:nn { nx }
+\cs_generate_variant:Nn\@@_struct_kid_OBJR_gput_right:nn { xx }
 
-\cs_new:Nn\@@_struct_exchange_kid_command:N %N= seq
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}
+%   {\@@_struct_exchange_kid_command:N, \@@_struct_exchange_kid_command:c}
+%  In luamode it can happen that a single kid in a structure is split at a page
+%  break into two or more mcid. In this case the lua code has to convert
+%  put the dictionary of the kid into an array. See issue 13 at tagpdf repo.
+%  We exchange the dummy command for the kids to mark this case.
+%    \begin{macrocode}
+\cs_new_protected:Npn\@@_struct_exchange_kid_command:N #1 %#1 = seq var
   {
-    \seq_gpop_left:NN #1 \l_tmpa_tl
+    \seq_gpop_left:NN #1 \l_@@_tmpa_tl
     \regex_replace_once:nnN
       { \c{\@@_mc_insert_mcid_kids:n} }
       { \c{\@@_mc_insert_mcid_single_kids:n} }
-      \l_tmpa_tl
-   \seq_gput_left:NV #1 \l_tmpa_tl
+      \l_@@_tmpa_tl
+    \seq_gput_left:NV #1 \l_@@_tmpa_tl
   }
 
 \cs_generate_variant:Nn\@@_struct_exchange_kid_command:N { c }
-
-\cs_new:Nn \@@_struct_fill_kid_key:n %#1 is the struct num
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{ \@@_struct_fill_kid_key:n }
+% This command adds the kid info to the K entry. In lua mode the
+% content contains commands which are expanded later. The argument is the structure
+% number.
+%
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_struct_fill_kid_key:n #1 %#1 is the struct num
   {
     \int_case:nnF
       {
         \seq_count:c
           {
-            g_@@_struct_kids_\prop_item:cn{ g_@@_struct_#1_prop }{num}_seq
+            g_@@_struct_kids_#1_seq
           }
       }
       {
@@ -251,17 +535,17 @@
         { 1 } % 1 kid, insert
          {
            % in this case we need a special command in
-           %luamode to get the array right. See issue #13
+           % luamode to get the array right. See issue #13
            \bool_if:NT\g_@@_mode_lua_bool
              {
                \@@_struct_exchange_kid_command:c
-                 {g_@@_struct_kids_\prop_item:cn{ g_@@_struct_#1_prop }{num}_seq}
+                {g_@@_struct_kids_#1_seq}
              }
            \@@_prop_gput:cnx { g_@@_struct_#1_prop } {K}
              {
                \seq_item:cn
                  {
-                   g_@@_struct_kids_\prop_item:cn{ g_@@_struct_#1_prop }{num}_seq
+                   g_@@_struct_kids_#1_seq
                  }
                  {1}
              }
@@ -273,7 +557,7 @@
             [
               \seq_use:cn
                 {
-                  g_@@_struct_kids_\prop_item:cn{ g_@@_struct_#1_prop }{num}_seq
+                  g_@@_struct_kids_#1_seq
                 }
                 {
                   \c_space_tl
@@ -283,22 +567,25 @@
       }
   }
 
-% this command can be used for roots and structure elements
-% #1 is a num
-
-\tl_new:N \l_@@_struct_dict_content_tl
-
-\cs_new:Nn \@@_struct_get_dict_content:n
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{\@@_struct_get_dict_content:nN}
+% This maps the dictionary content of a structure into a tl-var.
+% Basically it does what |\pdfdict_use:n| does.
+% TODO!! this looks over-complicated. Check if it can be done with pdfdict now.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_struct_get_dict_content:nN #1 #2 %#1: stucture num
   {
-    %\tl_set:Nn \l_@@_struct_dict_content_tl {<<}
-    \tl_clear:N \l_@@_struct_dict_content_tl
+    \tl_clear:N #2
     \seq_map_inline:cn
       {
-        c_@@_struct_\prop_item:cn{ g_@@_struct_#1_prop }{entries}_entries_seq
+        c_@@_struct_
+         \int_compare:nNnTF{#1}={0}{StructTreeRoot}{StructElem}
+         _entries_seq
       }
       {
         \tl_put_right:Nx
-          \l_@@_struct_dict_content_tl
+          #2
           {
              \prop_if_in:cnT
                { g_@@_struct_#1_prop }
@@ -308,25 +595,25 @@
                }
           }
       }
-    %\tl_put_right:Nn \l_@@_struct_dict_content_tl { >> }
   }
-
-
-% #1 is the struct num
-\cs_new:Nn \@@_struct_write_obj:n
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{\@@_struct_write_obj:n}
+% This writes out the structure object.
+% This is done in the finish code, in the tree module and
+% guarded by the tree boolean.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_struct_write_obj:n #1 % #1 is the struct num
   {
-    \prop_if_in:cnTF
-      { g_@@_struct_#1_prop }
-      { objref }
+    \pdf_object_if_exist:nTF { @@/struct/#1 }
       {
         \@@_struct_fill_kid_key:n { #1 }
-        %\prop_show:c { g_@@_struct_#1_prop }
-        \@@_struct_get_dict_content:n { #1 }
+        \@@_struct_get_dict_content:nN { #1 } \l_@@_tmpa_tl
         \exp_args:Nx
           \pdf_object_write:nx
             { @@/struct/#1 }
             {
-              \l_@@_struct_dict_content_tl
+              \l_@@_tmpa_tl
             }
       }
       {
@@ -333,11 +620,75 @@
         \msg_error:nnn { tag } { struct-no-objnum } { #1}
       }
   }
-
-% this command allows to get the current structure tag. We will need to handle nesting
-% P
-\cs_new:Nn \@@_get_data_struct_tag:
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{\@@_struct_insert_annot:nn}
+% This is the command to insert an annotation into the structure.
+% It can probably be used for xform too.
+%
+% Annotations used as structure content must
+% \begin{enumerate}
+% \item add a StructParent integer to their dictionary
+% \item push the object reference as OBJR object in the structure
+% \item Add a Structparent/obj-nr reference to the parent tree.
+% \end{enumerate}
+% For a link this looks like this
+% \begin{verbatim}
+%         \tag_struct_begin:n { tag=Link }
+%         \tag_mc_begin:n { tag=Link }
+% (1)     \pdfannot_dict_put:nnx
+%           { link/URI }
+%           { StructParent }
+%           { \int_use:N\c at g_@@_parenttree_obj_int }
+%    <start link> link text <stop link>
+% (2+3)   \@@_struct_insert_annot:nn {obj ref}{parent num}
+%         \tag_mc_end:
+%         \tag_struct_end:
+% \end{verbatim}
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_struct_insert_annot:nn #1 #2 %#1 object reference to the annotation/xform
+                                                       %#2 structparent number
   {
+    \bool_if:NT \g_@@_active_struct_bool
+      {
+        %get the number of the parent structure:
+        \seq_get:NNF
+          \g_@@_struct_stack_seq
+          \l_@@_struct_stack_parent_tmpa_tl
+          {
+            \msg_error:nn { tag } { struct-faulty-nesting }
+          }
+        %put the obj number of the annot in the kid entry, this also creates
+        %the OBJR object
+        \@@_struct_kid_OBJR_gput_right:xx
+          {
+            \l_@@_struct_stack_parent_tmpa_tl
+          }
+          {
+            #1 %
+          }
+        % add the parent obj number to the parent tree:
+        \exp_args:Nnx
+        \@@_parenttree_add_objr:nn
+          {
+            #2
+          }
+          {
+            \pdf_object_ref:e { @@/struct/\l_@@_struct_stack_parent_tmpa_tl }
+          }
+        % increase the int:
+        \stepcounter{ g_@@_parenttree_obj_int }
+      }
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_get_data_struct_tag:}
+% this command allows \cs{tag_get:n} to get the current
+% structure tag with the keyword |struct_tag|. We will need to handle nesting
+%    \begin{macrocode}
+\cs_new:Npn \@@_get_data_struct_tag:
+  {
     \exp_args:Ne
     \tl_tail:n
      {
@@ -344,28 +695,33 @@
        \prop_item:cn {g_@@_struct_\g__tag_struct_stack_current_tl _prop}{S}
      }
   }
-
-% keys for the user commands
-% should I pass the values (e.g. the tag) through an escape command?
+%    \end{macrocode}
+% \end{macro}
+%
+% \section{Keys}
+% This are the keys for the user commands.
 % we store the tag in a variable. But we should be careful, it is only reliable
-% at the begin
-\tl_new:N \g_@@_struct_tag_tl
-\tl_new:N \g_@@_struct_tag_NS_tl
-\cs_generate_variant:Nn \seq_set_split:Nnn{Nne}
+% at the begin.
+% \begin{macro}
+%  {
+%    label,stash,tag,
+%    title,title-o,
+%    alttext,alttext-o,
+%    actualtext,actualtext-o
+%    lang,ref,E
+%  }
+%    \begin{macrocode}
 \keys_define:nn { @@ / struct }
   {
     label .tl_set:N      = \l_@@_struct_key_label_tl,
     stash .bool_set:N    = \l_@@_struct_elem_stash_bool,
     tag   .code:n        = % S property
-      {%%????????? \pdfescapename?? slash/not slash is here the question ...
-        \seq_set_split:Nne \l_tmpa_seq { / } {#1/\prop_item:Nn\g__tag_role_tags_NS_prop{#1}}
-        \tl_gset:Nx \g_@@_struct_tag_tl    { \seq_item:Nn\l_tmpa_seq {1} }
-        \tl_gset:Nx \g_@@_struct_tag_NS_tl { \seq_item:Nn\l_tmpa_seq {2} }
-        \bool_if:NT \g_@@_check_tags_bool
-          {
-            \@@_check_structure_tag:N \g_@@_struct_tag_tl
-          }
-       \@@_prop_gput:cnx
+      {
+        \seq_set_split:Nne \l_@@_tmpa_seq { / } {#1/\prop_item:Nn\g__tag_role_tags_NS_prop{#1}}
+        \tl_gset:Nx \g_@@_struct_tag_tl    { \seq_item:Nn\l_@@_tmpa_seq {1} }
+        \tl_gset:Nx \g_@@_struct_tag_NS_tl { \seq_item:Nn\l_@@_tmpa_seq {2} }
+        \@@_check_structure_tag:N \g_@@_struct_tag_tl
+        \@@_prop_gput:cnx
          { g_@@_struct_\int_eval:n {\c at g_@@_struct_abs_int}_prop }
          { S }
          { \pdf_name_from_unicode_e:n{ \g_@@_struct_tag_tl} } %
@@ -482,12 +838,17 @@
           { <\l_@@_tmpa_str> }
       },
   }
-
-% keys for AF keys, they rely on l3pdffile!
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{AF,AFinline,AFinline-o}
+% keys for the AF keys (associated files). They use commands from l3pdffile!
 % The stream variants use txt as extension to get the mimetype.
+% TODO: check if this should be configurable. For math we will perhaps need another
+% extension.
+%    \begin{macrocode}
 \keys_define:nn { @@ / struct }
  {
-    AF .code:n        = % T property
+    AF .code:n        = % AF property
       {
         \pdf_object_if_exist:nTF {#1}
           {
@@ -503,8 +864,7 @@
    ,AFinline .code:n =
      {
        \group_begin:
-       \exp_args:Ne
-       \pdf_object_if_exist:nF {@@/fileobj\int_use:N\c at g_@@_struct_abs_int}
+       \pdf_object_if_exist:eF {@@/fileobj\int_use:N\c at g_@@_struct_abs_int}
         {
           \pdffile_embed_stream:nxx
             {#1}
@@ -520,8 +880,7 @@
    ,AFinline-o .code:n =
      {
        \group_begin:
-       \exp_args:Ne
-       \pdf_object_if_exist:nF {@@/fileobj\int_use:N\c at g_@@_struct_abs_int}
+       \pdf_object_if_exist:eF {@@/fileobj\int_use:N\c at g_@@_struct_abs_int}
         {
           \pdffile_embed_stream:oxx
             {#1}
@@ -535,81 +894,70 @@
        \group_end:
      }
  }
-
-\cs_new_protected:Nn \tag_struct_begin:n
+%    \end{macrocode}
+% \end{macro}
+%
+% \section{User commands}
+%
+% \begin{macro}{\tag_struct_begin:n,\tag_struct_end:}
+%    \begin{macrocode}
+\cs_new_protected:Npn \tag_struct_begin:n #1 %#1 key-val
   {
-    \group_begin:
-    \int_gincr:N \c at g_@@_struct_abs_int
-    \@@_prop_new:c  { g_@@_struct_\int_eval:n { \c at g_@@_struct_abs_int }_prop }
-    \@@_new_output_prop_handler:n {\int_eval:n { \c at g_@@_struct_abs_int }}
-    \@@_seq_new:c  { g_@@_struct_kids_\int_eval:n { \c at g_@@_struct_abs_int }_seq}
-    %\@@_pdfreserveobjnum:N \l_tmpa_tl
-    \exp_args:Ne
-      \pdf_object_new:nn
-        { @@/struct/\int_eval:n { \c at g_@@_struct_abs_int } }
-        { dict }
-    \@@_prop_gput:cnx
-      { g_@@_struct_\int_eval:n { \c at g_@@_struct_abs_int }_prop }
-      { objref}
+    \@@_check_if_active_struct:T
       {
+        \group_begin:
+        \int_gincr:N \c at g_@@_struct_abs_int
+        \@@_prop_new:c  { g_@@_struct_\int_eval:n { \c at g_@@_struct_abs_int }_prop }
+        \@@_new_output_prop_handler:n {\int_eval:n { \c at g_@@_struct_abs_int }}
+        \@@_seq_new:c  { g_@@_struct_kids_\int_eval:n { \c at g_@@_struct_abs_int }_seq}
         \exp_args:Ne
-          \pdf_object_ref:n
-            {@@/struct/\int_eval:n { \c at g_@@_struct_abs_int }}
-      }
-%    \prop_show:c { g_@@_struct_\int_eval:n { \c at g_@@_struct_abs_int }_prop }
-    \@@_prop_gput:cnx
-      { g_@@_struct_\int_eval:n { \c at g_@@_struct_abs_int }_prop }
-      { num}
-      { \int_eval:n { \c at g_@@_struct_abs_int } }
-    \@@_prop_gput:cno
-      { g_@@_struct_\int_eval:n { \c at g_@@_struct_abs_int }_prop }
-      { Type }
-      { /StructElem }
-    \@@_prop_gput:cno
-      { g_@@_struct_\int_eval:n { \c at g_@@_struct_abs_int }_prop }
-      { entries }
-      { StructElem }
-    \keys_set:nn { @@ / struct} { #1 }
-    \@@_check_structure_has_tag:n { \int_eval:n {\c at g_@@_struct_abs_int} }
-    \tl_if_empty:NF
-      \l_@@_struct_key_label_tl
-      {
-        \@@_ref_label:en{tagpdfstruct-\l_@@_struct_key_label_tl}{struct}
-      }
-    %get the potential parent from the stack:
-    \seq_get:NNF
-      \g_@@_struct_stack_seq
-      \l_@@_struct_stack_parent_tmp_tl
-      {
-        \msg_error:nn { tag } { struct-faulty-nesting }
-      }
-    \seq_gpush:NV \g_@@_struct_stack_seq        \c at g_@@_struct_abs_int
-    \seq_gpush:NV \g_@@_struct_tag_stack_seq    \g_@@_struct_tag_tl
-    \tl_gset:NV   \g_@@_struct_stack_current_tl \c at g_@@_struct_abs_int
-    %\seq_show:N   \g_@@_struct_stack_seq
-    \bool_if:NF
-      \l_@@_struct_elem_stash_bool
-      {%set the  parent
-        \@@_prop_gput:cnx
-          { g_@@_struct_\int_eval:n {\c at g_@@_struct_abs_int}_prop }
-          { P }
+          \pdf_object_new:nn
+            { @@/struct/\int_eval:n { \c at g_@@_struct_abs_int } }
+            { dict }
+        \@@_prop_gput:cno
+          { g_@@_struct_\int_eval:n { \c at g_@@_struct_abs_int }_prop }
+          { Type }
+          { /StructElem }
+        \keys_set:nn { @@ / struct} { #1 }
+        \@@_check_structure_has_tag:n { \int_eval:n {\c at g_@@_struct_abs_int} }
+        \tl_if_empty:NF
+          \l_@@_struct_key_label_tl
           {
-            \prop_item:cn
-              { g_@@_struct_\l_@@_struct_stack_parent_tmp_tl _prop}
-              { objref }
+            \@@_ref_label:en{tagpdfstruct-\l_@@_struct_key_label_tl}{struct}
           }
-        %record this structure as kid:
-        %\tl_show:N \g_@@_struct_stack_current_tl
-        %\tl_show:N \l_@@_struct_stack_parent_tmp_tl
-        \@@_struct_kid_struct_gput_right:nn
-          { \l_@@_struct_stack_parent_tmp_tl }
-          { \g_@@_struct_stack_current_tl }
+        %get the potential parent from the stack:
+        \seq_get:NNF
+          \g_@@_struct_stack_seq
+          \l_@@_struct_stack_parent_tmpa_tl
+          {
+            \msg_error:nn { tag } { struct-faulty-nesting }
+          }
+        \seq_gpush:NV \g_@@_struct_stack_seq        \c at g_@@_struct_abs_int
+        \seq_gpush:NV \g_@@_struct_tag_stack_seq    \g_@@_struct_tag_tl
+        \tl_gset:NV   \g_@@_struct_stack_current_tl \c at g_@@_struct_abs_int
+        %\seq_show:N   \g_@@_struct_stack_seq
+        \bool_if:NF
+          \l_@@_struct_elem_stash_bool
+          {%set the  parent
+            \@@_prop_gput:cnx
+              { g_@@_struct_\int_eval:n {\c at g_@@_struct_abs_int}_prop }
+              { P }
+              {
+                \pdf_object_ref:e { @@/struct/\l_@@_struct_stack_parent_tmpa_tl }
+              }
+            %record this structure as kid:
+            %\tl_show:N \g_@@_struct_stack_current_tl
+            %\tl_show:N \l_@@_struct_stack_parent_tmpa_tl
+            \@@_struct_kid_struct_gput_right:xx
+               { \l_@@_struct_stack_parent_tmpa_tl }
+               { \g_@@_struct_stack_current_tl }
+            %\prop_show:c { g_@@_struct_\g_@@_struct_stack_current_tl _prop }
+            %\seq_show:c {g_@@_struct_kids_\l_@@_struct_stack_parent_tmpa_tl _seq}
+          }
         %\prop_show:c { g_@@_struct_\g_@@_struct_stack_current_tl _prop }
-        %\seq_show:c {g_@@_struct_kids_\l_@@_struct_stack_parent_tmp_tl _seq}
-      }
-    %\prop_show:c { g_@@_struct_\g_@@_struct_stack_current_tl _prop }
-    %\seq_show:c {g_@@_struct_kids_\l_@@_struct_stack_parent_tmp_tl _seq}
-    \group_end:
+        %\seq_show:c {g_@@_struct_kids_\l_@@_struct_stack_parent_tmpa_tl _seq}
+        \group_end:
+     }
   }
 
 
@@ -617,149 +965,145 @@
   { %take the current structure num from the stack:
     %the objects are written later, lua mode hasn't all needed info yet
     %\seq_show:N \g_@@_struct_stack_seq
-    \seq_gpop:NN \g_@@_struct_tag_stack_seq \l_tmpa_tl
-    \seq_gpop:NNTF \g_@@_struct_stack_seq \l_tmpa_tl
+    \@@_check_if_active_struct:T
       {
-        \int_compare:nNnT {\l_@@_loglevel_int} > { 0 }
+        \seq_gpop:NN   \g_@@_struct_tag_stack_seq \l_@@_tmpa_tl
+        \seq_gpop:NNTF \g_@@_struct_stack_seq \l_@@_tmpa_tl
           {
             \@@_check_info_closing_struct:o { \g_@@_struct_stack_current_tl }
           }
-      }
-      { \@@_check_no_open_struck: }
-    % get the previous one, shouldn't be empty as the root should be there
-    \seq_get:NNTF \g_@@_struct_stack_seq \l_tmpa_tl
-      {
-        \tl_gset:NV   \g_@@_struct_stack_current_tl \l_tmpa_tl
-      }
-      {
-        \@@_check_no_open_struck:
-      }
-   \seq_get:NNT \g_@@_struct_tag_stack_seq \l_tmpa_tl
-      {
-        \tl_gset:NV \g_@@_struct_tag_tl \l_tmpa_tl
-      }
-  }
-
-
-
-\cs_new_protected:Nn \tag_struct_use:n %#1 is the label
-  {
-    \prop_if_exist:cTF
-      { g_@@_struct_\@@_ref_value:enn{tagpdfstruct-#1}{tagstruct}{unknown}_prop } %??????????
-      {
-        \@@_check_struct_used:n {#1}
-        %add the label structure as kid to the current structure (can be the root)
-        \@@_struct_kid_struct_gput_right:nn
-          { \g_@@_struct_stack_current_tl }
-          { \@@_ref_value:enn{tagpdfstruct-#1}{tagstruct}{0} }
-        %add the current structure to the labeled one as parents
-        \@@_prop_gput:cnx
-          { g_@@_struct_\@@_ref_value:enn{tagpdfstruct-#1}{tagstruct}{0}_prop }
-          { P }
+          { \@@_check_no_open_struct: }
+        % get the previous one, shouldn't be empty as the root should be there
+        \seq_get:NNTF \g_@@_struct_stack_seq \l_@@_tmpa_tl
           {
-            \prop_item:cn
-              { g_@@_struct_\g_@@_struct_stack_current_tl _prop}
-              { objref }
+            \tl_gset:NV   \g_@@_struct_stack_current_tl \l_@@_tmpa_tl
           }
+          {
+            \@@_check_no_open_struct:
+          }
+       \seq_get:NNT \g_@@_struct_tag_stack_seq \l_@@_tmpa_tl
+          {
+            \tl_gset:NV \g_@@_struct_tag_tl \l_@@_tmpa_tl
+          }
       }
-      {
-        \msg_warning:nnn{ tag }{struct-label-unknown}{#1}
-      }
   }
-
-
-%%%% Code to tag annotations like links.
-% Annotations used as structure content must
-% (1) add a StructParent integer to their dictionary
-% (2) push the object reference as OBJR object in the structure
-% (3) Add a Stuctparent/obj-nr reference to the parent three.
-% For a link this looks like this
-%         \tag_struct_begin:n { tag=Link }
-%         \tag_mc_begin:n { tag=Link }
-% (1)     \pdfannot_dict_put:nnx
-%           { link/URI }
-%           { StructParent }
-%           { \int_use:N\c at g_@@_parenttree_obj_int }
-%    <start link> link text <stop link>
-% (2+3)   \@@_struct_insert_annot:nn {obj ref}{parent num}
-%         \tag_mc_end:
-%         \tag_struct_end:
-%
-%%%% this works for url, see exp-link.pdf.
-%%%% it must be checked for other links
-
-
-% this will probably be used for xform too, but then we can rename it.
-\cs_new_protected:Npn \@@_struct_insert_annot:nn #1 #2 %#1 object reference to the annotation/xform
-                                                       %#2 structparent number
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{\tag_struct_use:n}
+% This command allows to use a stashed structure in another place.
+% TODO: decide how it should be guarded. Probably by the struct-check.
+%    \begin{macrocode}
+\cs_new_protected:Nn \tag_struct_use:n %#1 is the label
   {
-    \bool_if:NT \g_@@_active_struct_bool
+    \@@_check_if_active_struct:T
       {
-        %get the number of the parent link structure:
-        \seq_get:NNF
-          \g_@@_struct_stack_seq
-          \l_@@_struct_stack_parent_tmp_tl
+        \prop_if_exist:cTF
+          { g_@@_struct_\@@_ref_value:enn{tagpdfstruct-#1}{tagstruct}{unknown}_prop } %
           {
-            \msg_error:nn { tag } { struct-faulty-nesting }
+            \@@_check_struct_used:n {#1}
+            %add the label structure as kid to the current structure (can be the root)
+            \@@_struct_kid_struct_gput_right:xx
+              { \g_@@_struct_stack_current_tl }
+              { \@@_ref_value:enn{tagpdfstruct-#1}{tagstruct}{0} }
+            %add the current structure to the labeled one as parents
+            \@@_prop_gput:cnx
+              { g_@@_struct_\@@_ref_value:enn{tagpdfstruct-#1}{tagstruct}{0}_prop }
+              { P }
+              {
+                \pdf_object_ref:e { @@/struct/\g_@@_struct_stack_current_tl }
+              }
           }
-        %put the obj number of link annot in the kid entry:
-        \@@_struct_kid_OBJR_gput_right:nx
           {
-            \l_@@_struct_stack_parent_tmp_tl
+            \msg_warning:nnn{ tag }{struct-label-unknown}{#1}
           }
-          {
-            #1 %
-          }
-        % add the parent obj number to the parent tree:
-        \exp_args:Nnx
-        \@@_parenttree_add_objr:nn
-          {
-            #2
-          }
-          {
-            \prop_item:cn
-              { g_@@_struct_\l_@@_struct_stack_parent_tmp_tl _prop }
-              { objref }
-          }
-        % increase the int:
-        \stepcounter{ g_@@_parenttree_obj_int }
       }
   }
-
-
-
-% Code to add an annot to the structure.
-% This is for example needed for widget annotations and form field
-% It reuses the command used by links
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}
+%   {
+%     \tag_struct_insert_annot:nn,
+%     \tag_struct_insert_annot:xx
+%   }
+% \begin{macro}[EXP]
+%   {
+%     \tag_struct_parent_int:
+%   }
+% This are the user command to insert annotations. They must be used
+% together to get the numbers right. They use a counter to the
+% |StructParent| and \cs{tag_struct_insert_annot:nn}  increases the
+% counter given back by \cs{tag_struct_parent_int:}.
+%
+% It must be used together with |\tag_struct_parent_int:| to insert an
+% annotation.
+% TODO: decide how it should be guarded if tagging is deactivated.
+%    \begin{macrocode}
 \cs_new_protected:Npn \tag_struct_insert_annot:nn #1 #2 %#1 should be an object reference
                                                         %#2 struct parent num
   {
-     \@@_struct_insert_annot:nn {#1}{#2}
+    \@@_check_if_active_struct:T
+      {
+        \@@_struct_insert_annot:nn {#1}{#2}
+      }
   }
 
 \cs_generate_variant:Nn \tag_struct_insert_annot:nn {xx}
 \cs_new:Npn \tag_struct_parent_int: {\int_use:c { c at g_@@_parenttree_obj_int }}
 
-%</struct>
+%</package>
 
 %    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \section{Attributes and attribute classes}
 %    \begin{macrocode}
-%<*attr>
-\ProvidesExplPackage {tagpdf-attr-code} {2021-06-14} {0.82}
+%<*header>
+\ProvidesExplPackage {tagpdf-attr-code} {2021-06-29} {0.9}
   {part of tagpdf - code related to attributes and attribute classes}
-
-% the obj is written in tagpdf-tree-code.
-
+%</header>
+%    \end{macrocode}
+% \subsection{Variables}
+%  \begin{variable}
+%   {
+%     ,\g_@@_attr_entries_prop
+%     ,\g_@@_attr_class_used_seq
+%     ,\g_@@_attr_objref_prop
+%     ,\l_@@_attr_value_tl
+%   }
+% |\g_@@_attr_entries_prop| will store attribute names and their dictionary content.\\
+% |\g_@@_attr_class_used_seq| will hold the attributes which have been used as
+% class name.
+% |\l_@@_attr_value_tl| is used to build the attribute array or key.
+% Everytime an attribute is used for the first time, and object is created
+% with its content, the name-object reference relation is stored in
+% |\g_@@_attr_objref_prop|
+%    \begin{macrocode}
+%<*package>
+\prop_new:N \g_@@_attr_entries_prop
 \seq_new:N  \g_@@_attr_class_used_seq
+\tl_new:N   \l_@@_attr_value_tl
 \prop_new:N \g_@@_attr_objref_prop %will contain obj num of used attributes
-
-\prop_new:N \g_@@_attr_entries_prop
-\tl_new:N   \g_@@_attr_class_content_tl
-\tl_new:N   \l_@@_attr_objtmp_tl
-\tl_new:N   \l_@@_attr_value_tl
-
-
-\cs_new_protected:Nn \@@_attr_new_entry:nn %#1:name, #2: content
+%    \end{macrocode}
+% \end{variable}
+% \subsection{Commands and keys}
+% \begin{macro}{\@@_attr_new_entry:nn,newattribute}
+% This allows to define attributes. Defined attributes
+% are stored in a global property. |newattribute| expects
+% two brace group, the name and the content. The content typically
+% needs an |/O| key for the owner. An example look like
+% this.
+% \begin{verbatim}
+%  \tagpdfsetup
+%   {
+%    newattribute =
+%     {TH-col}{/O /Table /Scope /Column},
+%    newattribute =
+%     {TH-row}{/O /Table /Scope /Row},
+%    }
+% \end{verbatim}
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_attr_new_entry:nn #1 #2 %#1:name, #2: content
   {
     \prop_gput:Nnn \g_@@_attr_entries_prop
       {#1}{#2}
@@ -772,16 +1116,19 @@
         \@@_attr_new_entry:nn #1
       }
   }
-
-
-% the key for the structure:
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{attribute-class}
+% attribute-class has to store the used attribute names so that
+% they can be added to the ClassMap later.
+%    \begin{macrocode}
 \keys_define:nn { @@ / struct }
   {
     attribute-class .code:n =
      {
-       \clist_set:No \l_tmpa_clist { #1 }
-       \seq_set_from_clist:NN \l_tmpa_seq \l_tmpa_clist
-       \seq_map_inline:Nn \l_tmpa_seq
+       \clist_set:No \l_@@_tmpa_clist { #1 }
+       \seq_set_from_clist:NN \l_@@_tmpa_seq \l_@@_tmpa_clist
+       \seq_map_inline:Nn \l_@@_tmpa_seq
          {
            \prop_if_in:NnF \g_@@_attr_entries_prop {##1}
              {
@@ -789,38 +1136,41 @@
              }
            \seq_gput_left:Nn\g_@@_attr_class_used_seq { ##1}
          }
-       \seq_set_map:NNn \l_tmpb_seq \l_tmpa_seq
+       \seq_set_map:NNn \l_@@_tmpb_seq \l_@@_tmpa_seq
          {
            /##1
          }
-       \tl_set:Nx \l_tmpa_tl
+       \tl_set:Nx \l_@@_tmpa_tl
          {
-           \int_compare:nT { \seq_count:N \l_tmpa_seq > 1 }{[}
-           \seq_use:Nn \l_tmpb_seq  { \c_space_tl  }
-           \int_compare:nT { \seq_count:N \l_tmpa_seq > 1 }{]}
+           \int_compare:nT { \seq_count:N \l_@@_tmpa_seq > 1 }{[}
+           \seq_use:Nn \l_@@_tmpb_seq  { \c_space_tl  }
+           \int_compare:nT { \seq_count:N \l_@@_tmpa_seq > 1 }{]}
          }
-       \int_compare:nT { \seq_count:N \l_tmpa_seq > 0 }
+       \int_compare:nT { \seq_count:N \l_@@_tmpa_seq > 0 }
          {
            \@@_prop_gput:cnx
              { g_@@_struct_\int_eval:n {\c at g_@@_struct_abs_int}_prop }
              { C }
-             { \l_tmpa_tl }
+             { \l_@@_tmpa_tl }
           %\prop_show:c  { g_@@_struct_\int_eval:n {\c at g_@@_struct_abs_int}_prop }
          }
-    }
+     }
   }
-
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{attribute}
+%    \begin{macrocode}
 \keys_define:nn { @@ / struct }
   {
     attribute .code:n  = % A property (attribute, value currently a dictionary)
       {
-        \clist_set:No          \l_tmpa_clist { #1 }
-        \seq_set_from_clist:NN \l_tmpa_seq \l_tmpa_clist
+        \clist_set:No          \l_@@_tmpa_clist { #1 }
+        \seq_set_from_clist:NN \l_@@_tmpa_seq \l_@@_tmpa_clist
         \tl_set:Nx \l_@@_attr_value_tl
           {
-            \int_compare:nT { \seq_count:N \l_tmpa_seq > 1 }{[}%]
+            \int_compare:nT { \seq_count:N \l_@@_tmpa_seq > 1 }{[}%]
           }
-        \seq_map_inline:Nn \l_tmpa_seq
+        \seq_map_inline:Nn \l_@@_tmpa_seq
           {
             \prop_if_in:NnF \g_@@_attr_entries_prop {##1}
               {
@@ -844,7 +1194,7 @@
           }
         \tl_put_right:Nx \l_@@_attr_value_tl
           { %[
-            \int_compare:nT { \seq_count:N \l_tmpa_seq > 1 }{]}%
+            \int_compare:nT { \seq_count:N \l_@@_tmpa_seq > 1 }{]}%
           }
  %     \tl_show:N \l_@@_attr_value_tl
         \@@_prop_gput:cnx
@@ -853,5 +1203,7 @@
           { \l_@@_attr_value_tl }
     },
   }
-%</attr>
+%</package>
 %    \end{macrocode}
+% \end{macro}
+% \end{implementation}

Modified: trunk/Master/texmf-dist/source/latex/tagpdf/tagpdf-tree.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/tagpdf/tagpdf-tree.dtx	2021-06-30 20:41:50 UTC (rev 59768)
+++ trunk/Master/texmf-dist/source/latex/tagpdf/tagpdf-tree.dtx	2021-06-30 21:14:14 UTC (rev 59769)
@@ -22,16 +22,55 @@
 %
 % for those people who are interested.
 %
+%<*driver>
+\RequirePackage{pdfmanagement-testphase}
+\DeclareDocumentMetadata{}
+\makeatletter
+\declare at file@substitution{doc.sty}{doc-v3beta.sty}
+\makeatother
+\documentclass{l3doc}
+\usepackage{array,booktabs,caption}
+\hypersetup{pdfauthor=Ulrike Fischer,
+ pdftitle=tagpdf-tree module (tagpdf)}
+\begin{document}
+  \DocInput{\jobname.dtx}
+\end{document}
+%</driver>
 % \fi
+% \title{^^A
+%   The \pkg{tagpdf-tree} module\\ Commands trees and main dictionaries   ^^A
+%   \\ Part of the tagpdf package
+% }
 %
+% \author{^^A
+%  Ulrike Fischer\thanks
+%    {^^A
+%      E-mail:
+%        \href{mailto:fischer at troubleshooting-tex.de}
+%          {fischer at troubleshooting-tex.de}^^A
+%    }^^A
+% }
+%
+% \date{Version 0.9, released 2021-06-29}
+% \maketitle
+% \begin{implementation}
 %    \begin{macrocode}
 %<@@=tag>
-%<*tree>
-\ProvidesExplPackage {tagpdf-tree-code} {2021-06-14} {0.82}
+%<*header>
+\ProvidesExplPackage {tagpdf-tree-code} {2021-06-29} {0.9}
  {part of tagpdf - code related to writing trees and dictionaries to the pdf}
-
-%this does the actual finishing:
-%Is \AddToHook{enddocument/end} the best places??
+%</header>
+%    \end{macrocode}
+% \section{Trees, pdfmanagement and finalization code}
+%
+% The code to finish the structure is in a hook.
+% This will perhaps at the end be a kernel hook.
+% TODO check right place for the code
+% The pdfmanagement code is the kernel hook after
+% shipout/lastpage so all code affecting it should be before.
+% Objects can be written later, at least in pdf mode.
+%    \begin{macrocode}
+%<*package>
 \hook_gput_code:nnn{begindocument}{tagpdf}
   {
     \bool_if:NT \g_@@_active_tree_bool
@@ -38,29 +77,29 @@
       {
         \sys_if_output_pdf:TF
           {
-            \AddToHook{enddocument/end} { \tag_finish_structure: }
+            \AddToHook{enddocument/end} { \@@_finish_structure: }
           }
           {
-            \AddToHook{shipout/lastpage} { \tag_finish_structure: }
+            \AddToHook{shipout/lastpage} { \@@_finish_structure: }
           }
       }
   }
-
-
-% the StructTreeRoot
-% we better get the object number in any case:
-% deprecated
-%\@@_pdfreserveobjnum:N \l_tmpa_tl
-%\tl_const:Nx \c_@@_tree_obj_structtreeroot_tl { \l_tmpa_tl }
-
-%new
+%    \end{macrocode}
+% \subsection{Catalog: MarkInfo and StructTreeRoot}
+% The StructTreeRoot and the MarkInfo entry must be added to the catalog.
+% We do it late so that we can win, but before the pdfmanagement hook.
+% \begin{macro}{@@/struct/0}
+% This is the object for the root object, the StructTreeRoot
+%    \begin{macrocode}
 \pdf_object_new:nn { @@/struct/0 }{ dict }
-
- %need to think about the best place ...
-\hook_gput_code:nnn{begindocument}{tagpdf}
+%    \end{macrocode}
+% \end{macro}
+%    \begin{macrocode}
+\hook_gput_code:nnn{shipout/lastpage}{tagpdf}
   {
-    \bool_if:NT \g_@@_active_struct_bool
+    \bool_if:NT \g_@@_active_tree_bool
       {
+        \pdfmanagement_add:nnn { Catalog / MarkInfo } { Marked } { true }
         \pdfmanagement_add:nnx
           { Catalog }
           { StructTreeRoot }
@@ -67,35 +106,60 @@
           { \pdf_object_ref:n { @@/struct/0 } }
       }
   }
-\cs_new_protected:Nn \@@_tree_write_structtreeroot:
+%    \end{macrocode}
+%
+% \subsection{Writing structure elements}
+% The following commands are needed to write out the structure.
+% \begin{macro}{\@@_tree_write_structtreeroot:}
+% This writes out the root object.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_tree_write_structtreeroot:
   {
-    \@@_struct_write_obj:n { 0 }
+     \@@_prop_gput:cnx
+       { g_@@_struct_0_prop }
+       { ParentTree }
+       { \pdf_object_ref:n { @@/tree/parenttree } }
+     \@@_prop_gput:cnx
+       { g_@@_struct_0_prop }
+       { RoleMap }
+       { \pdf_object_ref:n { @@/tree/rolemap } }
+     \@@_struct_write_obj:n { 0 }
   }
-
-\cs_new_protected:Nn \@@_tree_write_structelements:
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_tree_write_structelements:}
+% This writes out the other struct elems, the absolute number is in the counter
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_tree_write_structelements:
   {
     \int_step_inline:nnnn {1}{1}{\c at g_@@_struct_abs_int}
       {
-        %\prop_show:c {g_@@_struct_##1_prop}
-        \@@_struct_write_obj:n { ##1 } %write the object
+        \@@_struct_write_obj:n { ##1 }
       }
   }
-
-
-%the ParentTree
-% deprecated
-%\@@_pdfreserveobjnum:N \l_tmpa_tl
-%\tl_const:Nx \c_@@_tree_obj_parenttree_tl    { \l_tmpa_tl }
-
-%new
+%    \end{macrocode}
+% \end{macro}
+%
+% \subsection{ParentTree}
+% \begin{macro}{@@/tree/parenttree}
+% The object which will hold the parenttree
+%    \begin{macrocode}
 \pdf_object_new:nn { @@/tree/parenttree }{ dict }
-
-% we have two sets of entries in the parent tree:
-% page streams and real objects.
-% The numbers must be distinct and ordered
-% So we rely on abspage and put the real objects at the end
-% I use a counter to have a chance to get the correct number
-% if code is process twice.
+%    \end{macrocode}
+% \end{macro}
+% The ParentTree maps numbers to objects or (if the number represents a page)
+% to arrays of objects. The numbers refer to two dictinct types of entries:
+% page streams and real objects like annotations.
+% The numbers must be distinct and ordered.
+% So we rely on abspage for the pages and put the real objects at the end.
+% We use a counter to have a chance to get the correct number
+% if code is processed twice.
+%
+% \begin{macro}{\c at g_@@_parenttree_obj_int}
+%  This is a counter for the real objects. It starts at the absolute last page
+%  value. It relies on l3ref.
+%    \begin{macrocode}
 \newcounter  { g_@@_parenttree_obj_int }
 \hook_gput_code:nnn{begindocument}{tagpdf}
   {
@@ -103,12 +167,21 @@
       \c at g_@@_parenttree_obj_int
       { \@@_ref_value_lastpage:nn{abspage}{100}  }
   }
-
-% we need to record the obj references:
-
+%    \end{macrocode}
+% \end{macro}
+% We store the number/object references in a tl-var. If more structure is needed
+% one could switch to a seq.
+%  \begin{variable}{ \g_@@_parenttree_objr_tl }
+%    \begin{macrocode}
 \tl_new:N \g_@@_parenttree_objr_tl
-
-\cs_new_protected:Nn \@@_parenttree_add_objr:nn %#1 Structparent number, #2 objref
+%    \end{macrocode}
+% \end{variable}
+%
+%  \begin{macro}{ \@@_parenttree_add_objr:nn }
+%  This command stores a StructParent number and a objref into the tl var.
+%  This is only for objects like annotations, pages are handled elsewhere.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_parenttree_add_objr:nn #1 #2 %#1 StructParent number, #2 objref
   {
     \tl_gput_right:Nx \g_@@_parenttree_objr_tl
       {
@@ -115,27 +188,38 @@
         #1 \c_space_tl #2 ^^J
       }
   }
-
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{variable}{\l_@@_parenttree_content_tl}
+% A tl-var which will get the page related parenttree content.
+%    \begin{macrocode}
 \tl_new:N \l_@@_parenttree_content_tl
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{macro}{\@@_tree_fill_parenttree:}
+% This is the main command to assemble the page related entries of the parent tree.
+% It wanders through the pages and the mcid numbers and collects all mcid of one page.
+%    \begin{macrocode}
 
-\cs_new_protected:Nn \@@_tree_fill_parenttree:
+\cs_new_protected:Npn \@@_tree_fill_parenttree:
   {
     \int_step_inline:nnnn{1}{1}{\@@_ref_value_lastpage:nn{abspage}{-1}} %not quite clear if labels are needed. See lua code
-      { %page ##1\par
-        \prop_clear:N \l_tmpa_prop
+      { %page ##1
+        \prop_clear:N \l_@@_tmpa_prop
         \int_step_inline:nnnn{1}{1}{\@@_ref_value_lastpage:nn{tagmcabs}{-1}}
           {
             %mcid####1
-            \int_compare:nT%F
+            \int_compare:nT
               {\@@_ref_value:enn{mcid-####1}{tagabspage}{-1}=##1} %mcid is on current page
-              {% yes\par
+              {% yes
                 \prop_put:Nxx
-                  \l_tmpa_prop
+                  \l_@@_tmpa_prop
                   {\@@_ref_value:enn{mcid-####1}{tagmcid}{-1}}
                   {\prop_item:Nn \g_@@_mc_parenttree_prop {####1}}
               }
           }
-          %\prop_show:N \l_tmpa_prop
         \tl_put_right:Nx\l_@@_parenttree_content_tl
           {
             \int_eval:n {##1-1}\c_space_tl
@@ -144,16 +228,18 @@
         \int_step_inline:nnnn
           {0}
           {1}
-          { \prop_map_function:NN \l_tmpa_prop\@@_prop_count:nn -1 }
+          { \prop_count:N \l_@@_tmpa_prop -1 }
           {
-            \prop_get:NnNTF \l_tmpa_prop {####1} \l_tmpb_tl
-              {% page#1:mcid##1:\l_tmpb_tl :content
+            \prop_get:NnNTF \l_@@_tmpa_prop {####1} \l_@@_tmpa_tl
+              {% page#1:mcid##1:\l_@@_tmpa_tl :content
                 \tl_put_right:Nx \l_@@_parenttree_content_tl
                   {
-                    \prop_item:cn { g_@@_struct_\l_tmpb_tl _prop } {objref}
+                    \pdf_object_if_exist:eT { @@/struct/\l_@@_tmpa_tl }
+                     {
+                       \pdf_object_ref:e { @@/struct/\l_@@_tmpa_tl }
+                     }
                     \c_space_tl
                   }
-                %\tl_show:N \l_@@_parenttree_content_tl
               }
               {
                 \msg_warning:nn { tag } {tree-mcid-index-wrong}
@@ -166,13 +252,18 @@
           }
       }
   }
-
-%lua mode must/can do it differently
-\cs_new_protected:Nn \@@_tree_lua_fill_parenttree:
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_tree_lua_fill_parenttree:}
+% This is a special variant for luatex.
+% lua mode must/can do it differently.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_tree_lua_fill_parenttree:
   {
     \tl_set:Nn \l_@@_parenttree_content_tl
       {
-        \directlua
+        \lua_now:e
           {
             ltx.@@.func.output_parenttree
               (
@@ -181,10 +272,14 @@
           }
       }
   }
-
-
-
-\cs_new_protected:Nn \@@_tree_write_parenttree:
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_tree_write_parenttree:}
+% This combines the two parts and writes out the object.
+% TODO should the check for lua be moved into the backend code?
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_tree_write_parenttree:
   {
     \bool_if:NTF \g_@@_mode_lua_bool
       {
@@ -199,12 +294,25 @@
         /Nums\c_space_tl [\l_@@_parenttree_content_tl]
       }
   }
-
-%the Rolemap tree
-
+%    \end{macrocode}
+% \end{macro}
+%
+% \subsection{Rolemap dictionary}
+% The Rolemap dictionary describes relations between new tags and standard types.
+% The main part here is handled in the role module, here we only define the
+% command which writes it to the PDF.
+% \begin{variable}{@@/tree/rolemap}
+% At first we reserve again an object.
+%    \begin{macrocode}
 \pdf_object_new:nn { @@/tree/rolemap }{ dict }
-
-\cs_new_protected:Nn \@@_tree_write_rolemap:
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{macro}{\@@_tree_write_rolemap:}
+% This writes out the rolemap, basically it simply pushes out
+% the dictionary which has been filled in the role module.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_tree_write_rolemap:
   {
     \pdf_object_write:nx  { @@/tree/rolemap }
       {
@@ -211,14 +319,19 @@
         \pdfdict_use:n{g_@@_role/RoleMap_dict}
       }
   }
-
-%classmap, should only be written, if values has been used
-
-\cs_new_protected:Nn \@@_tree_write_classmap:
+%    \end{macrocode}
+% \end{macro}
+%
+% \subsection{Classmap dictionary}
+% Classmap and attributes are setup in the struct module, here is only the
+% code to write it out. It should only done if values have been used.
+% \begin{macro}{\@@_tree_write_classmap:}
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_tree_write_classmap:
   {
-    \tl_gclear:N \g_@@_attr_class_content_tl
+    \tl_clear:N \l_@@_tmpa_tl
     \seq_gremove_duplicates:N \g_@@_attr_class_used_seq
-    \seq_set_map:NNn \l_tmpa_seq \g_@@_attr_class_used_seq
+    \seq_set_map:NNn \l_@@_tmpa_seq \g_@@_attr_class_used_seq
       {
         /##1\c_space_tl
         <<
@@ -227,21 +340,19 @@
             {##1}
         >>
       }
-    \tl_gset:Nx \g_@@_attr_class_content_tl
+    \tl_set:Nx \l_@@_tmpa_tl
       {
         \seq_use:Nn
-          \l_tmpa_seq
+          \l_@@_tmpa_seq
           { \iow_newline: }
       }
     \tl_if_empty:NF
-      \g_@@_attr_class_content_tl
+      \l_@@_tmpa_tl
       {
         \pdf_object_new:nn { @@/tree/classmap }{ dict }
-     %   \@@_pdfreserveobjnum:N \l_tmpa_tl
-     %   \tl_const:Nx \c_@@_tree_obj_classmap_tl { \l_tmpa_tl }
         \pdf_object_write:nx
           { @@/tree/classmap }
-          { \g_@@_attr_class_content_tl }
+          { \l_@@_tmpa_tl }
         \@@_prop_gput:cnx
           { g_@@_struct_0_prop }
           { ClassMap }
@@ -248,9 +359,18 @@
           { \pdf_object_ref:n { @@/tree/classmap }  }
       }
   }
-
-% namespaces are only relevant for pdf2.0 but we don't care
+%    \end{macrocode}
+% \end{macro}
+% \subsection{Namespaces}
+% Namespaces are handle in the role module, here is the code to write them out.
+% Namespaces are only relevant for pdf2.0 but we don't care, it doesn't harm.
+% \begin{variable}{@@/tree/namespaces}
+%    \begin{macrocode}
 \pdf_object_new:nn{ @@/tree/namespaces }{array}
+%    \end{macrocode}
+% \end{variable}
+% \begin{macro}{\@@_tree_write_namespaces:}
+%    \begin{macrocode}
 \cs_new_protected:Npn \@@_tree_write_namespaces:
   {
     \prop_map_inline:Nn \g_@@_role_NS_prop
@@ -274,21 +394,33 @@
         \prop_map_tokens:Nn \g_@@_role_NS_prop{\use_ii:nn}
       }
   }
-
-
-\cs_new_protected:Nn \tag_finish_structure:
+%    \end{macrocode}
+% \end{macro}
+% \subsection{Finishing the structure}
+% This assembles the various parts.
+% TODO (when tabular are done or if someone requests it): IDTree
+%  \begin{macro}{ \@@_finish_structure: }
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_finish_structure:
   {
-    \@@_tree_write_parenttree:
-    \@@_tree_write_rolemap:
-    \@@_tree_write_classmap:
-    \@@_tree_write_namespaces:
-    \@@_tree_write_structelements: %this is rather slow!!
-    \@@_tree_write_structtreeroot:
+    \bool_if:NT\g_@@_active_tree_bool
+      {
+        \hook_use:n {tagpdf/finish/before}
+        \@@_tree_write_parenttree:
+        \@@_tree_write_rolemap:
+        \@@_tree_write_classmap:
+        \@@_tree_write_namespaces:
+        \@@_tree_write_structelements: %this is rather slow!!
+        \@@_tree_write_structtreeroot:
+      }
   }
-
-
-%StructParents !!! we need a better hook for \g__pdf_BACKEND_thispage_shipout_tl!!
-% No actually
+%    \end{macrocode}
+% \end{macro}
+%
+% \subsection{StructParents entry for Page}
+% We need to add to the Page resources the |StructParents| entry, this is simply the
+% absolute page number.
+%    \begin{macrocode}
 \hook_gput_code:nnn{begindocument}{tagpdf}
   {
     \bool_if:NT\g_@@_active_tree_bool
@@ -295,13 +427,14 @@
       {
        \hook_gput_code:nnn{shipout/before} { tagpdf/structparents }
          {
-             \pdfmanagement_add:nnx
-               { Page }
-               {StructParents}
-               {\int_eval:n { \g_shipout_readonly_int}}
+           \pdfmanagement_add:nnx
+             { Page }
+             { StructParents }
+             { \int_eval:n { \g_shipout_readonly_int} }
          }
       }
   }
-
-%</tree>
+%</package>
 %    \end{macrocode}
+% \end{implementation}
+% \PrintIndex

Added: trunk/Master/texmf-dist/source/latex/tagpdf/tagpdf-user.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/tagpdf/tagpdf-user.dtx	                        (rev 0)
+++ trunk/Master/texmf-dist/source/latex/tagpdf/tagpdf-user.dtx	2021-06-30 21:14:14 UTC (rev 59769)
@@ -0,0 +1,585 @@
+% \iffalse meta-comment
+%
+%% File: tagpdf-user.dtx
+%
+% Copyright (C) 2019-2021 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/u-fischer/tagpdf
+%
+% for those people who are interested.
+%<*driver>
+\RequirePackage{pdfmanagement-testphase}
+\DeclareDocumentMetadata{}
+\makeatletter
+\declare at file@substitution{doc.sty}{doc-v3beta.sty}
+\makeatother
+\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 at troubleshooting-tex.de}
+%          {fischer at troubleshooting-tex.de}^^A
+%    }^^A
+% }
+%
+% \date{Version 0.9, released 2021-06-29}
+% \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}
+%
+% \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}{\tagmcifin}
+% \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
+% necessarly stops the compilation. The keys and their function are described below.
+% \end{function}
+%
+% \begin{function}{mc-data}
+%  \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}
+%  \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}{struct-stack}
+%  \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}
+%
+% \section{Extension commands}
+% The following commands and code parts are not core command 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,paratagging-show}
+%  \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}
+%
+% \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}
+% \end{documentation}
+%
+% \begin{implementation}
+% \section{User commands and extensions of document commands}
+%    \begin{macrocode}
+%<@@=tag>
+%<*header>
+\ProvidesExplPackage {tagpdf-user} {2021-06-29} {0.9}
+  {tagpdf - user commands}
+%</header>
+%    \end{macrocode}
+% \section{Setup and preamble commands}
+% \begin{macro}{\tagpdfsetup}
+%    \begin{macrocode}
+%<*package>
+\NewDocumentCommand \tagpdfsetup { m }
+  {
+    \keys_set:nn { @@ / setup } { #1 }
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+
+% \section{Commands for the mc-chunks}
+% \begin{macro}{\tagmcbegin,\tagmcend,\tagmcuse  }
+%    \begin{macrocode}
+\NewDocumentCommand \tagmcbegin { m }
+  {
+    \tag_mc_begin:n {#1}%\ignorespaces
+  }
+
+
+\NewDocumentCommand \tagmcend {  }
+  {
+    %\if_mode_horizontal: \unskip \fi: %
+    \tag_mc_end:
+  }
+
+\NewDocumentCommand \tagmcuse { m }
+  {
+    \tag_mc_use:n {#1}
+  }
+
+%    \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}
+\NewDocumentCommand \tagmcifinTF { m m }
+  {
+    \tag_mc_if_in:TF { #1 } { #2 }
+  }
+%    \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}
+\NewDocumentCommand \tagstructbegin { m }
+  {
+    \tag_struct_begin:n {#1}
+  }
+
+\NewDocumentCommand \tagstructend {  }
+  {
+   \tag_struct_end:
+  }
+
+\NewDocumentCommand \tagstructuse { m }
+  {
+    \tag_struct_use:n {#1}
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}{\tagpdfifluatexTF,\tagpdfifluatexT,\tagpdfifpdftexTF}
+% I should deprecate them ...
+%    \begin{macrocode}
+\cs_set_eq:NN\tagpdfifluatexTF \sys_if_engine_luatex:TF
+\cs_set_eq:NN\tagpdfifluatexT  \sys_if_engine_luatex:T
+\cs_set_eq:NN\tagpdfifpdftexT  \sys_if_engine_pdftex:T
+%    \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}
+\NewDocumentCommand\ShowTagging { m }
+  {
+    \keys_set:nn { @@ / show }{ #1}
+
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{mc-data}
+% 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}
+% 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__tag_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}{struct-stack}
+%    \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
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \section{Commands to extend document commands}
+% The following commands and code parts are not core command of tagpdf.
+% The 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.
+% \subsection{Document structure}
+% \begin{macro}{\@@_add_document_structure:n,activate}
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_add_document_structure:n #1
+ {
+   \hook_gput_code:nnn{begindocument}{tagpdf}{\tagstructbegin{tag=#1}}
+   \hook_gput_code:nnn{tagpdf/finish/before}{tagpdf}{\tagstructend}
+ }
+\keys_define:nn { @@ / setup}
+ {
+   activate   .code:n =
+    {
+      \keys_set:nn { @@ / setup }
+        { activate-mc,activate-tree,activate-struct }
+      \@@_add_document_structure:n {#1}
+    },
+  activate .default:n = Document
+ }
+%    \end{macrocode}
+% \end{macro}
+% \subsection{Fake space}
+% \begin{macro}{\pdffakespace}
+% We need a luatex variant for |\pdffakespace|. This should probably go into
+% the kernel at some time.
+%    \begin{macrocode}
+\sys_if_engine_luatex:T
+  {
+    \NewDocumentCommand\pdffakespace { }
+     {
+       \@@_fakespace:
+     }
+  }
+%    \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_show_bool,\g_@@_para_int}
+%  At first some variables.
+%    \begin{macrocode}
+\bool_new:N \l_@@_para_bool
+\bool_new:N \l_@@_para_show_bool
+\int_new:N  \g_@@_para_int
+%    \end{macrocode}
+% \end{macro}
+%
+%
+%\begin{macro}
+% {
+%  paratagging,
+%  paratagging-show,
+%  }
+% 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.
+%    \begin{macrocode}
+\keys_define:nn { @@ / setup }
+  {
+    paratagging      .bool_set:N = \l_@@_para_bool,
+    paratagging-show .bool_set:N = \l_@@_para_show_bool,
+  }
+
+%    \end{macrocode}
+% \end{macro}
+% This fills the para hooks with the needed code.
+%    \begin{macrocode}
+\AddToHook{para/begin}
+  {
+   \int_gincr:N \g_@@_para_int
+   \bool_if:NT \l__tag_para_bool
+     {
+       \tag_struct_begin:n {tag=P}
+       \bool_if:NT \l_@@_para_show_bool
+        { \tag_mc_begin:n{artifact}
+          \llap{\color_select:n{red}\tiny\int_use:N\g_@@_para_int\ }
+          \tag_mc_end:
+        }
+       \tag_mc_begin:n {tag=P}
+     }
+  }
+\AddToHook{para/end}
+  {
+    \bool_if:NT \l__tag_para_bool
+      {
+        \tag_mc_end:
+        \bool_if:NT \l_@@_para_show_bool
+          { \tag_mc_begin:n{artifact}
+            \rlap{\color_select:n{red}\tiny\ \int_use:N\g_@@_para_int}
+            \tag_mc_end:
+          }
+        \tag_struct_end:
+      }
+  }
+%    \end{macrocode}
+% \begin{macro}
+%   {
+%    \tagpdfparaOn,
+%    \tagpdfparaOff
+%   }
+%  This two command switch para mode on and off. |\tagpdfsetup| could be used
+%  too but is longer.
+%    \begin{macrocode}
+\newcommand\tagpdfparaOn {\bool_set_true:N \l__tag_para_bool}
+\newcommand\tagpdfparaOff{\bool_set_false:N \l__tag_para_bool}
+%    \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:nnx
+      { link/URI }
+      { StructParent }
+      { \tag_struct_parent_int: }
+  }
+
+\hook_gput_code:nnn
+  {pdfannot/link/URI/after}
+  {tagpdf}
+  {
+     \tag_struct_insert_annot:xx {\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:nnx
+       { link/GoTo }
+       { StructParent }
+       { \tag_struct_parent_int: }
+  }
+
+\hook_gput_code:nnn
+  {pdfannot/link/GoTo/after}
+  {tagpdf}
+  {
+    \tag_struct_insert_annot:xx {\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


Property changes on: trunk/Master/texmf-dist/source/latex/tagpdf/tagpdf-user.dtx
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Modified: trunk/Master/texmf-dist/source/latex/tagpdf/tagpdf.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/tagpdf/tagpdf.dtx	2021-06-30 20:41:50 UTC (rev 59768)
+++ trunk/Master/texmf-dist/source/latex/tagpdf/tagpdf.dtx	2021-06-30 21:14:14 UTC (rev 59769)
@@ -2,7 +2,7 @@
 %
 %% File: tagpdf.dtx
 %
-% Copyright (C) 2019-2020 Ulrike Fischer
+% Copyright (C) 2019-2021 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
@@ -24,10 +24,12 @@
 %
 % \fi
 %
+% \begin{implementation}
+% \section{Initialization and test if pdfmanagement is active.}
 %    \begin{macrocode}
 %<@@=tag>
 %<*package>
-\ProvidesExplPackage {tagpdf} {2021-06-14} {0.82}
+\ProvidesExplPackage {tagpdf} {2021-06-29} {0.9}
   { A package to experiment with pdf tagging }
 
 \bool_if:nF
@@ -49,33 +51,36 @@
        before~\string\documentclass
      }
   }
-
-%\debug_on:n{check-declarations,check-expressions,deprecation}
-
-%map internal tag to package name
+%    \end{macrocode}
+% We map the internal module name \enquote{tag} to \enquote{tagpdf} in messages.
+%    \begin{macrocode}
 \prop_if_exist:NT \g_msg_module_name_prop
   {
     \prop_gput:Nnn \g_msg_module_name_prop { tag }{ tagpdf }
   }
-
-% storing internal names to my name space:
-\cs_set_eq:NN \@@_tex_global:D              \tex_global:D
-
-%%% package options
+%    \end{macrocode}
+%\section{Package options}
+% There are only two options to switch for luatex between generic and luamode,
+% TODO try to get rid of them.
+%    \begin{macrocode}
 \bool_new:N\g_@@_mode_lua_bool
-
 \DeclareOption {luamode}    { \sys_if_engine_luatex:T { \bool_gset_true:N \g_@@_mode_lua_bool } }
 \DeclareOption {genericmode}{ \bool_gset_false:N\g_@@_mode_lua_bool }
 \ExecuteOptions{luamode}
 \ProcessOptions
-
-%%% some packages
-%references use l3ref-tmp
+%    \end{macrocode}
+% \section{Packages}
+% We need the temporary version of l3ref until this is in the kernel.
+%    \begin{macrocode}
 \RequirePackage{l3ref-tmp}
- %================
- % temporary code
- % ===============
- % faking the LastPage label:
+%    \end{macrocode}
+%
+% \section{Temporary code}
+% This is code which will be removed when proper support exists in LaTeX
+% \subsection{a LastPage label}
+% See also issue \#2 in Accessible-xref
+% \begin{macro}{\@@_lastpagelabel:}
+%    \begin{macrocode}
  \cs_new_protected:Npn \@@_lastpagelabel:
    {
      \legacy_if:nT { @filesw }
@@ -94,8 +99,17 @@
 
  \AddToHook{enddocument/afterlastpage}
   {\@@_lastpagelabel:}
-
- % a command to override the general default. See issue in ref
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\ref_value:nnn}
+% This allows to locally set a default value if the label or the attribute
+% doesn't exist.
+% See issue \#4 in Accessible-xref.
+% \begin{syntax}
+% \cs{ref_value:nnn}\Arg{label}\Arg{attribute}\Arg{Fallback default}
+% \end{syntax}
+%    \begin{macrocode}
  \cs_if_exist:NF \ref_value:nnn
    {
      \cs_new:Npn \ref_value:nnn #1#2#3
@@ -109,37 +123,158 @@
          \tl_if_exist:cTF { g__ref_label_ #1 _ #2 _tl }
            { \tl_use:c { g__ref_label_ #1 _ #2 _tl } }
            {
-             % test if attribute exist at all?
              #3
            }
        }
    }
+%    \end{macrocode}
+% \end{macro}
 
- %=============
- % attributes
- %=============
-\ref_attribute_gset:nnnn {tagstruct}    {0}{now}    { \int_use:N \c at g_@@_struct_abs_int }
-\ref_attribute_gset:nnnn {tagstructobj} {}{now}
- {
-  \exp_args:Ne
-   \pdf_object_if_exist:nT {@@/struct/\int_use:N \c at g__tag_struct_abs_int}
-    {
-      \pdf_object_ref:e{@@/struct/\int_use:N \c at g_@@_struct_abs_int}
-    }
- }
- % replace by abspage??
-\ref_attribute_gset:nnnn {tagabspage}{0}{shipout}{ \int_use:N \g_shipout_readonly_int }
-\ref_attribute_gset:nnnn {tagmcabs } {0}{now}    { \int_use:N \c at g_@@_MCID_abs_int }
-\ref_attribute_gset:nnnn {tagmcid }  {0}{now}    { \int_use:N \g_@@_MCID_tmp_bypage_int }
-%============
-% lists
-%============
-\clist_const:Nn \c_@@_refmc_clist     {tagabspage,tagmcabs,tagmcid} %mc is new!!
+% \section{Variables}
+% \begin{variable}
+%  {
+%    \l_@@_tmpa_tl,
+%    \l_@@_tmpa_str,
+%    \l_@@_tmpa_prop,
+%    \l_@@_tmpa_seq,
+%    \l_@@_tmpb_seq,
+%    \l_@@_tmpa_clist,
+%    \l_@@_tmpa_int
+%  }
+% A few temporary variables
+%    \begin{macrocode}
+\tl_new:N    \l_@@_tmpa_tl
+\str_new:N   \l_@@_tmpa_str
+\prop_new:N  \l_@@_tmpa_prop
+\seq_new:N   \l_@@_tmpa_seq
+\seq_new:N   \l_@@_tmpb_seq
+\clist_new:N \l_@@_tmpa_clist
+\int_new:N   \l_@@_tmpa_int
+%    \end{macrocode}
+% \end{variable}
+% Attribute lists for the label command. We have a list for
+% mc-related labels, and one for structures.
+% \begin{macro}{\c_@@_refmc_clist,\c_@@_refstruct_clist}
+%    \begin{macrocode}
+\clist_const:Nn \c_@@_refmc_clist     {tagabspage,tagmcabs,tagmcid}
 \clist_const:Nn \c_@@_refstruct_clist {tagstruct,tagstructobj}
-%=================
-% command to set a label
-%================
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{variable}{\l_@@_loglevel_int}
+% This integer hold the log-level and so allows to
+% control the messages.
+% TODO: a list which log-level shows what is needed. The current behaviour
+% is quite ad-hoc.
+%    \begin{macrocode}
+\int_new:N  \l_@@_loglevel_int
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}
+%  {
+%    \g_@@_active_space_bool,
+%    \g_@@_active_mc_bool,
+%    \g_@@_active_tree_bool,
+%    \g_@@_active_struct_bool
+%  }
+% These booleans should help to control the global behaviour of tagpdf.
+% Ideally it should more or less do nothing if all are false.
+% The space-boolean controles the interword space code,
+% the mc-boolean activates \cs{tag_mc_begin:n},
+% the tree-boolean activates writing the finish code and the pdfmanagement related
+% commands, the struct-boolean activates the storing of the structure data.
+% In a normal document all should be active, the split is only there for
+% debugging purpose.
+% Also we assume currently that they are set only at begin document. But
+% if some control passing over groups are needed they could be perhaps
+% used in a document too.
+% TODO: check if they are used everywhere as needed and as wanted.
+%    \begin{macrocode}
+\bool_new:N \g_@@_active_space_bool
+\bool_new:N \g_@@_active_mc_bool
+\bool_new:N \g_@@_active_tree_bool
+\bool_new:N \g_@@_active_struct_bool
+%    \end{macrocode}
+% \end{variable}
+
+% \begin{variable}
+%  {
+%    \l_@@_active_mc_bool,
+%    \l_@@_active_struct_bool
+%  }
+% These booleans should help to control the \emph{local} behaviour of tagpdf.
+% In some cases it could e.g. be necessary to stop tagging completely.
+% As local booleans they respect groups.
+% TODO: check if they are used everywhere as needed and as wanted.
+%    \begin{macrocode}
+\bool_new:N \l_@@_active_mc_bool
+\bool_set_true:N \l_@@_active_mc_bool
+\bool_new:N \l_@@_active_struct_bool
+\bool_set_true:N \l_@@_active_struct_bool
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\g_@@_tagunmarked_bool}
+% This boolean controls if the code should try to automatically
+% tag parts not in mc-chunk. It is currently only used in luamode.
+% It would be possible to used it in generic mode, but this would create
+% quite a lot empty artifact mc-chunks.
+%    \begin{macrocode}
+\bool_new:N \g_@@_tagunmarked_bool
+%    \end{macrocode}
+% \end{variable}
+%
+% \section{Variants of l3 commands}
+%     \begin{macrocode}
+\prg_generate_conditional_variant:Nnn \pdf_object_if_exist:n {e}{T,F}
+\cs_generate_variant:Nn \pdf_object_ref:n {e}
+\cs_generate_variant:Nn \pdfannot_dict_put:nnn {nnx}
+\cs_generate_variant:Nn \pdffile_embed_stream:nnn {nxx,oxx}
+\cs_generate_variant:Nn \prop_gput:Nnn {Nxx}
+\cs_generate_variant:Nn \prop_put:Nnn  {Nxx}
 \cs_generate_variant:Nn \ref_label:nn { nv }
+\cs_generate_variant:Nn \seq_set_split:Nnn{Nne}
+\cs_generate_variant:Nn \str_set_convert:Nnnn {Nonn, Noon, Nnon }
+%    \end{macrocode}
+
+% \section{Setup label attributes}
+% \begin{macro}{tagstruct,tagstructobj,tagabspage,tagmcabs,tagmcid}
+% This are attributes used by the label/ref system.
+% With structures we store the structure number |tagstruct|
+% and the object reference |tagstructobj|.
+% The second is needed to be able to reference a structure which hasn't been
+% created yet. The alternative would be to create the object in such cases,
+% but then we would have to check the object existence all the time.
+%
+% With mc-chunks we store the absolute page number |tagabspage|,
+% the absolute id |tagmcabc|, and the id on the page |tagmcid|.
+%    \begin{macrocode}
+\ref_attribute_gset:nnnn { tagstruct } {0} { now }
+  { \int_use:N \c at g_@@_struct_abs_int }
+\ref_attribute_gset:nnnn { tagstructobj } {} { now }
+  {
+    \pdf_object_if_exist:eT {@@/struct/\int_use:N \c at g__tag_struct_abs_int}
+      {
+        \pdf_object_ref:e{@@/struct/\int_use:N \c at g_@@_struct_abs_int}
+      }
+  }
+\ref_attribute_gset:nnnn { tagabspage } {0} { shipout }
+  { \int_use:N \g_shipout_readonly_int }
+\ref_attribute_gset:nnnn { tagmcabs } {0} { now }
+  { \int_use:N \c at g_@@_MCID_abs_int }
+\ref_attribute_gset:nnnn {tagmcid }  {0} { now }
+  { \int_use:N \g_@@_MCID_tmp_bypage_int }
+%    \end{macrocode}
+% \end{macro}
+%
+% \section{Label commands}
+% \begin{macro}{\@@_ref_label:nn}
+% A version of |\ref_label:nn| to set a label
+% which takes a keyword |mc| or |struct| to
+% call the relevant lists.
+% TODO: check if |\@bsphack| and |\@esphack| make sense here.
+%    \begin{macrocode}
 \cs_new_protected:Npn \@@_ref_label:nn #1 #2 %#1 label, #2 name of list mc or struct
   {
     \@bsphack
@@ -146,146 +281,59 @@
     \ref_label:nv {#1}{c_@@_ref#2_clist}
     \@esphack
   }
-%==============
-% command to retrieve the value
-%===============
+\cs_generate_variant:Nn \@@_ref_label:nn {en}
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{\@@_ref_value:nnn}
+% A local version to retrieve the value. It is a direct wrapper,
+% but to keep naming consistent \ldots. It uses the variant defined temporarly
+% above.
+%    \begin{macrocode}
 \cs_new:Npn \@@_ref_value:nnn #1 #2 #3 %#1 label, #2 attribute, #3 default
   {
     \ref_value:nnn {#1}{#2}{#3}
   }
-%===============
-% the LastPage label has a different name, so we need a special command for now
-% =============
+\cs_generate_variant:Nn \@@_ref_value:nnn {enn}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_ref_value_lastpage:nn}
+% A command to retrieve the lastpage label, this will be adapted when there
+% is a proper, kernel lastpage label.
+%    \begin{macrocode}
 \cs_new:Npn \@@_ref_value_lastpage:nn #1 #2
   {
     \ref_value:nnn {@@_LastPage}{#1}{#2}
   }
+%    \end{macrocode}
+%\end{macro}
 
-% as ref doesn't expand label names we need variants:
-\cs_generate_variant:Nn \@@_ref_label:nn {en}
-\cs_generate_variant:Nn \@@_ref_value:nnn {enn}
 
-\RequirePackage{etoolbox}
-%\RequirePackage{l3pdf}
-%\RequirePackage{pdfescape} %check if needed
-%\RequirePackage{pdftexcmds}%check if needed (expandable commands!)
 
-%\RequirePackage{l3str-convert}
-\cs_generate_variant:Nn \str_set_convert:Nnnn {Nonn, Noon, Nnon }
+%\section{Commands to fill seq and prop}
+% With most engines these are simply copies of the expl3 commands,
+% but luatex will overwrite them, to store the data also in lua tables.
+% \begin{macro}
+%  {
+%    \@@_prop_new:N
+%    ,\@@_seq_new:N
+%    ,\@@_prop_gput:Nnn
+%    ,\@@_seq_gput_right:Nn
+%    ,\@@_seq_item:cn
+%    ,\@@_prop_item:cn
+%    ,\@@_seq_show:N
+%    ,\@@_prop_show:N
+%  }
+%    \begin{macrocode}
+\cs_set_eq:NN \@@_prop_new:N        \prop_new:N
+\cs_set_eq:NN \@@_seq_new:N         \seq_new:N
+\cs_set_eq:NN \@@_prop_gput:Nnn     \prop_gput:Nnn
+\cs_set_eq:NN \@@_seq_gput_right:Nn \seq_gput_right:Nn
+\cs_set_eq:NN \@@_seq_item:cn       \seq_item:cn
+\cs_set_eq:NN \@@_prop_item:cn      \prop_item:cn
+\cs_set_eq:NN \@@_seq_show:N        \seq_show:N
+\cs_set_eq:NN \@@_prop_show:N       \prop_show:N
 
-
-
-
-%%% tagpdfsetup,
-%%% TODO: checks need to be improved
-\int_new:N  \l_@@_loglevel_int
-\tl_new:N   \l_@@_tree_tabs_order_tl
-
-\keys_define:nn { @@ / setup }
-  {
-    activate-mc     .bool_gset:N = \g_@@_active_mc_bool,
-    activate-tree   .bool_gset:N = \g_@@_active_tree_bool,
-    activate-struct .bool_gset:N = \g_@@_active_struct_bool,
-    activate-all    .meta:n ={activate-mc,activate-tree,activate-struct},
-    check-tags      .bool_gset:N = \g_@@_check_tags_bool,
-    check-tags      .initial:n  = true,
-    log             .choice:,
-    log / none      .code:n = {\int_set:Nn \l_@@_loglevel_int { 0 }},
-    log / v         .code:n = {\int_set:Nn \l_@@_loglevel_int { 1 }},
-    log / vv        .code:n = {\int_set:Nn \l_@@_loglevel_int { 2 }},
-    log / vvv       .code:n = {\int_set:Nn \l_@@_loglevel_int { 3 }},
-    log / all       .code:n = {\int_set:Nn \l_@@_loglevel_int { 10 }},
-    tagunmarked     .bool_gset:N = \g_@@_tagunmarked_bool,
-    tagunmarked     .initial:n  = true,
-    tabsorder       .choice:,
-    tabsorder / row       .code:n = %{\tl_set:Nn \l_@@_tree_tabs_order_tl {/Tabs/R}},
-      \pdfmanagement_add:nnn { Page } {Tabs}{/R},
-    tabsorder / column    .code:n = %{\tl_set:Nn \l_@@_tree_tabs_order_tl {/Tabs/C}},
-      \pdfmanagement_add:nnn { Page } {Tabs}{/C},
-    tabsorder / structure .code:n = %{\tl_set:Nn \l_@@_tree_tabs_order_tl {/Tabs/S}},
-      \pdfmanagement_add:nnn { Page } {Tabs}{/S},
-    tabsorder / none      .code:n = %{\tl_set:Nn \l_@@_tree_tabs_order_tl {}},
-      \pdfmanagement_remove:nn {Page} {Tabs},
-    tabsorder       .initial:n = structure,
-    uncompress      .code:n = {\pdf_uncompress:  },
-    global-mc .code:n =
-      {
-        \cs_set_eq:NN\@@_attribute_set:Nn \@@_attribute_gset:Nn
-        \cs_set_eq:NN\@@_attribute_unset:N\@@_attribute_gunset:N
-      }
-  }
-%need to think about the right place ...
-%\AtBeginDocument
-\hook_gput_code:nnn{begindocument}{tagpdf}
-  {
-    \bool_if:NT \g_@@_active_struct_bool
-      {
-         \pdfmanagement_add:nnn { Catalog / MarkInfo } { Marked } { true }
-      }
-    \keys_define:nn { @@ / setup }
-     {
-       global-mc .code:n={}
-     }
-  }
-% escape commands are a bit engine specific so have been moved to the backend files.
-% commands to escape strings so that they can be safely used in pdf
-% currently not much used. But will be needed later, when alt and actualtext are added.
-% we probably need the equivalent \pdfescapestring, \pdfescapename \pdfescapehex
-% the commands of pdfescape adds an additional layout to allow for babel shorthands
-%\cs_set_eq:NN \@@_pdf_escape_string:Nn \EdefEscapeString
-%\cs_set_eq:NN \@@_pdf_escape_name:Nn   \EdefEscapeName
-%\cs_set_eq:NN \@@_pdf_escape_hex:Nn    \EdefEscapeHex
-
-%\cs_set_eq:NN \@@_pdf_escape_string:n \EdefEscapeString
-%\cs_set_eq:NN \@@_pdf_escape_name:Nn   \EdefEscapeName
-
-%escape command. They are backend specific as \pdf at escapehex would ignore most chars
-%outside the "pdflatex" range
-
-
-
-
-
-% a hook for later code and an absolute page counter
-% should be executed before counters are resetted.
-% is it used?
-\cs_new:Nn   \@@_finish_page_hook: { }
-
-%\AtBeginShipout
-
-\hook_gput_code:nnn
-  { shipout/before }
-  { tagpdf/cnt }
-  {
-    \@@_finish_page_hook:
-    %\int_gincr:N \g_@@_abspage_int
-  }
-
-
-%testing the engines and loading the backend files
-\sys_if_engine_xetex:T
-  { %lets try with xelatex ...
-    %\PackageError { tagpdf } { xelatex~is~not~supported~-~aborting } {}
-    %\tex_endinput:D
-    \file_input:n {tagpdf-pdftex.def}
-  }
-
-\sys_if_engine_luatex:T
-  {
-    \file_input:n {tagpdf-luatex.def}
-  }
-
-\sys_if_engine_pdftex:T
-  {
-    \file_input:n {tagpdf-pdftex.def}
-  }
-
-\sys_if_output_dvi:T
-  {
-    %\PackageError { tagpdf } { dvi~output~is~not~supported~-~aborting }{}
-    %\tex_endinput:D
-  }
-
 \cs_generate_variant:Nn \@@_prop_gput:Nnn      { Nxn , Nxx, Nnx , cnn, cxn, cnx, cno}
 \cs_generate_variant:Nn \@@_seq_gput_right:Nn  { Nx  , No, cn, cx }
 \cs_generate_variant:Nn \@@_prop_new:N   { c }
@@ -292,439 +340,110 @@
 \cs_generate_variant:Nn \@@_seq_new:N    { c }
 \cs_generate_variant:Nn \@@_seq_show:N   { c }
 \cs_generate_variant:Nn \@@_prop_show:N  { c }
-\cs_generate_variant:Nn \prop_gput:Nnn {Nxx}
-\cs_generate_variant:Nn \prop_put:Nnn  {Nxx}
-
-\cs_generate_variant:Nn \pdffile_embed_stream:nnn {nxx,oxx}
-\cs_generate_variant:Nn \pdf_object_ref:n {e}
-
-
-% few temp tl
-\tl_new:N \g_@@_tmpa_tl
-\tl_new:N \l_@@_tmpa_tl
-\tl_new:N \l_@@_tmpb_tl
-\tl_new:N \l_@@_tmpc_tl
-\tl_new:N \l_@@_tmpd_tl
-\tl_new:N \l_@@_tmpe_tl
-\str_new:N \l_@@_tmpa_str
-
-% helper function to get the propcount.
-% use as \prop_map_function:NN PROP { \@@_prop_count:nn -1 }
-\cs_new:Nn\@@_prop_count:nn { + 1 }
-
-%% Loading the tagpdf sub packages
-\RequirePackage { tagpdf-checks-code }
-\RequirePackage { tagpdf-user }
-\RequirePackage { tagpdf-tree-code }
-\RequirePackage { tagpdf-roles-code }
-\RequirePackage { tagpdf-attr-code }
-% mc-code is split:
-\RequirePackage { tagpdf-mc-code-shared }
-\bool_if:NTF \g_@@_mode_lua_bool
-  {
-   \RequirePackage {tagpdf-mc-code-lua}
-  }
-  {
-   \RequirePackage { tagpdf-mc-code-generic } %
-  }
-
-\RequirePackage { tagpdf-struct-code }
-\RequirePackage { tagpdf-space-code }
-%</package>
 %    \end{macrocode}
+% \end{macro}
 %
-%    \begin{macrocode}
-%<*user>
-\ProvidesExplPackage {tagpdf-user} {2021-06-14} {0.82}
-  {tagpdf - user commands}
-%    \end{macrocode}
+% \section{General tagging commands}
 
-% \begin{macro}{\tagpdfsetup}
-%    \begin{macrocode}
-\NewDocumentCommand \tagpdfsetup { m }
-  {
-    \keys_set:nn { @@ / setup } { #1 }
-  }
-
-\cs_set_eq:NN\tagpdfifluatexTF \sys_if_engine_luatex:TF
-\cs_set_eq:NN\tagpdfifluatexT  \sys_if_engine_luatex:T
-\cs_set_eq:NN\tagpdfifpdftexT  \sys_if_engine_pdftex:T
-%    \end{macrocode}
-% \end{macro}
-% \begin{macro}{\tag_if_active:}
-% This is a test it tagging is active. This allows packages
-% to add conditional code. We probably will need a better
-% test in the end, but for now it should be ok.
-%    \begin{macrocode}
-\prg_new_conditional:Npnn \tag_if_active: { p , T , TF, F }
-  {
-     \bool_if:NTF\g_@@_active_struct_bool
-       {
-         \prg_return_true:
-       }
-       {
-         \prg_return_false:
-       }
-  }     
-%    \end{macrocode}
-% \end{macro}
-%
+% \begin{macro}{ \tag_stop_group_begin:, \tag_stop_group_end: }
 % We need a command to stop tagging in some places.
-%
-% \begin{macro}{ \tag_stop_group_begin:, \tag_stop_group_end: }
+% This simply switches the two local booleans.
 %    \begin{macrocode}
-\bool_new:N \l_@@_stop_bool
-
-\prg_new_conditional:Nnn \@@_if_stop: {p,T,F,TF}
-  {
-    \bool_if:NTF \l_@@_stop_bool
-      { \prg_return_true:  }
-      { \prg_return_false: }
-  }
-
-\prg_new_eq_conditional:NNn \tag_if_stop: \@@_if_stop: {p,T,F,TF}
-
-\cs_new_protected:Npn \@@_stop:
-  {
-    \bool_set_true:N \l_@@_stop_bool
-    \cs_set_eq:NN \tag_mc_begin:n     \use_none:n
-    \cs_set_eq:NN \tag_mc_end:        \prg_do_nothing:
-    \cs_set_eq:NN \tag_mc_use:n       \use_none:n
-    \cs_set_eq:NN \tag_struct_begin:n \use_none:n
-    \cs_set_eq:NN \tag_struct_end:    \prg_do_nothing:
-    \cs_set_eq:NN \tag_struct_use:n   \use_none:n
-  }
-
 \cs_new_protected:Npn \tag_stop_group_begin:
   {
     \group_begin:
-    \@@_stop:
+    \bool_set_false:N \l_@@_active_struct_bool
+    \bool_set_false:N \l_@@_active_mc_bool
   }
-
 \cs_set_eq:NN \tag_stop_group_end: \group_end:
 %    \end{macrocode}
 % \end{macro}
-% We need a command to stop tagging in some places.
 %
-% \begin{macro}{ \tagpdfget, \tag_get:n  }
-% This is a generic command to retrieve data. Currently
-% the only sensible value for the argument is |mc_tag|
-%    \begin{macrocode}
-\cs_new:Npn \tagpdfget #1   { \use:c {@@_get_data_#1: } }
-\cs_new:Npn \tag_get:n #1   { \use:c {@@_get_data_#1: } }
+% \section{Keys for tagpdfsetup}
 
-%    \end{macrocode}
-% \end{macro}
+% TODO: the log-levels must be sorted
 %
-% \begin{macro}{\tagmcifinTF}
-% This is a test 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.
+% \begin{macro}
+%  {
+%    activate-space,
+%    activate-mc,
+%    activate-tree,
+%    activate-struct,
+%    activate-all,
+%  }
+%  Keys to (globally) activate tagging.
+%  |activate-space| activates the additional parsing needed for
+%  interword spaces. It is not documented, the parsing is currently
+%  implicitly activated by the known key |interwordspace|, as the code will
+%  perhaps move to some other place, now that it is better separated.
 %    \begin{macrocode}
-\NewDocumentCommand \tagmcifinTF { m m }
+\keys_define:nn { @@ / setup }
   {
-    \@@_mc_if_in:TF { #1 } { #2 }
-  }
-%    \end{macrocode}
+    activate-space  .bool_gset:N = \g_@@_active_space_bool,
+    activate-mc     .bool_gset:N = \g_@@_active_mc_bool,
+    activate-tree   .bool_gset:N = \g_@@_active_tree_bool,
+    activate-struct .bool_gset:N = \g_@@_active_struct_bool,
+    activate-all    .meta:n =
+      {activate-mc,activate-tree,activate-struct},
+ %    \end{macrocode}
 % \end{macro}
-%
-% \begin{macro}{tagmcartifact}
+% \begin{macro}{log}
+% The |log| takes currently the values |none|, |v|, |vv|, |vvv|, |all|.
+% The description of the log levels is in tagpdf-checks.
 %    \begin{macrocode}
-\NewDocumentEnvironment{tagmcartifact}{m}
- {
-  \tag_mc_artifact_group_begin:n { #1}\ignorespaces
- }
- {
-  \tag_mc_artifact_group_end:
- }
-
+    log             .choice:,
+    log / none      .code:n = {\int_set:Nn \l_@@_loglevel_int { 0 }},
+    log / v         .code:n = {\int_set:Nn \l_@@_loglevel_int { 1 }},
+    log / vv        .code:n = {\int_set:Nn \l_@@_loglevel_int { 2 }},
+    log / vvv       .code:n = {\int_set:Nn \l_@@_loglevel_int { 3 }},
+    log / all       .code:n = {\int_set:Nn \l_@@_loglevel_int { 10 }},
 %    \end{macrocode}
 % \end{macro}
-%
-% \begin{macro}{\tagmcbegin,\tagmcend,\tagmcuse  }
+% \begin{macro}{tagunmarked}
+% This key allows to set if (in luamode) unmarked text should be
+% marked up as artifact. The initial value is true.
 %    \begin{macrocode}
-\NewDocumentCommand \tagmcbegin { m }
-  {
-    \tag_mc_begin:n {#1}\ignorespaces
-  }
-
-
-\NewDocumentCommand \tagmcend {  }
-  {
-    \if_mode_horizontal: \unskip \fi: %
-    \tag_mc_end:
-  }
-
-\NewDocumentCommand \tagmcuse { m }
-  {
-    \tag_mc_use:n {#1}
-  }
-
+    tagunmarked     .bool_gset:N = \g_@@_tagunmarked_bool,
+    tagunmarked     .initial:n  = true,
 %    \end{macrocode}
 % \end{macro}
-%
-% \begin{macro}{\tagstructbegin,\tagstructend,\tagstructuse  }
-%
-% These are structure related user commands
+% \begin{macro}{tabsorder}
+% This sets the tabsorder one a page. The values are |row|, |column|, |structure| (default)
+% or |none|. Currently this is set more or less globally. More finer controll can be
+% added if needed.
 %    \begin{macrocode}
-\NewDocumentCommand \tagstructbegin { m }
-  {
-    \tag_struct_begin:n {#1}
+    tabsorder       .choice:,
+    tabsorder / row       .code:n =
+      \pdfmanagement_add:nnn { Page } {Tabs}{/R},
+    tabsorder / column    .code:n =
+      \pdfmanagement_add:nnn { Page } {Tabs}{/C},
+    tabsorder / structure .code:n =
+      \pdfmanagement_add:nnn { Page } {Tabs}{/S},
+    tabsorder / none      .code:n =
+      \pdfmanagement_remove:nn {Page} {Tabs},
+    tabsorder       .initial:n = structure,
+    uncompress      .code:n = { \pdf_uncompress:  },
   }
-
-\NewDocumentCommand \tagstructend {  }
-  {
-   \tag_struct_end:
-  }
-
-\NewDocumentCommand \tagstructuse { m }
-  {
-    \tag_struct_use:n {#1}
-  }
-
 %    \end{macrocode}
 % \end{macro}
-%
-% \section{Debugging}
-%
-% \begin{macro}{\showtagpdfmcdata,\showtagpdfattributes }
-% This commands are lua only
+% \section{loading of engine/more dependent code}
 %    \begin{macrocode}
-\NewDocumentCommand\showtagpdfmcdata { O {\@@_tag_get_mc_abs_cnt:} }
-  {
-    \bool_if:NT \g_@@_mode_lua_bool
-      {
-        \sys_if_engine_luatex:T
-          {
-            \directlua{ltx.@@.trace.show_all_mc_data(#1)}
-          }
-      }
-  }
-
-\NewDocumentCommand\showtagpdfattributes { }
-  {
-    \bool_if:NT \g_@@_mode_lua_bool
-      {
-        \sys_if_engine_luatex:T
-          {
-            \directlua
-              {
-                ltx.@@.trace.log
-                 (
-                   "showtagpdfattributes:
-                    MC=>abscnt=\@@_get_mc_abs_cnt:
-                    =>attr=\the\l_@@_mc_cnt_attr=>tag="
-                    ..
-                    tostring(ltx.@@.func.get_tag_from (\the\l_@@_mc_type_attr))
-                    ..
-                    "=\the\l_@@_mc_type_attr",0
-                 )
-             }
-            \ignorespaces
-          }
-      }
-   }
-
-\NewDocumentCommand\showtagstack {}
-  {
-    \seq_show:N \g_@@_struct_tag_stack_seq
-  }
-%    \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{  }
-%    \begin{macrocode}
 \sys_if_engine_luatex:T
   {
-    \NewDocumentCommand\pdffakespace { }
-      {
-        \@@_fakespace:
-      }
+    \file_input:n {tagpdf-luatex.def}
   }
+%</package>
 %    \end{macrocode}
-% \end{macro}
-% \section{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{macrocode}
-\bool_new:N \l_@@_para_bool
-\bool_new:N \l_@@_para_show_bool
-\int_new:N \g_@@_para_int
-
-\keys_define:nn { @@ / setup }
+%<*mcloading>
+\bool_if:NTF \g_@@_mode_lua_bool
   {
-    paratagging      .bool_set:N = \l_@@_para_bool,
-    paratagging-show .bool_set:N = \l_@@_para_show_bool,
+   \RequirePackage {tagpdf-mc-code-lua}
   }
-
-\AddToHook{para/begin}
   {
-   \int_gincr:N \g_@@_para_int
-   \bool_if:NT \l__tag_para_bool
-     {
-       \tag_struct_begin:n {tag=P}
-       \bool_if:NT \l_@@_para_show_bool
-        { \tag_mc_begin:n{artifact}
-          \llap{\color_select:n{red}\tiny\int_use:N\g_@@_para_int\ }
-          \tag_mc_end:
-        }
-       \tag_mc_begin:n {tag=P}
-     }
+   \RequirePackage {tagpdf-mc-code-generic} %
   }
-\AddToHook{para/end}
-  {
-    \bool_if:NT \l__tag_para_bool
-      {
-        \tag_mc_end:
-        \bool_if:NT \l_@@_para_show_bool
-          { \tag_mc_begin:n{artifact}
-            \rlap{\color_select:n{red}\tiny\ \int_use:N\g_@@_para_int}
-            \tag_mc_end:
-          }
-        \tag_struct_end:
-      }
-  }
-
-
-\newcommand\tagpdfparaOn {\bool_set_true:N \l__tag_para_bool}
-\newcommand\tagpdfparaOff{\bool_set_false:N \l__tag_para_bool}
-
+%</mcloading>
 %    \end{macrocode}
-% \section{Links}
-% We need to close and reopen mc-chunks around links.
-% With luatex the push/pop command must be outside groups,
-% so we add also code to the generic commands in the hyperref driver.
-%    \begin{macrocode}
-\cs_generate_variant:Nn \pdfannot_dict_put:nnn {nnx}
-\hook_gput_code:nnn
-  {pdfannot/link/URI/before}
-  {tagpdf}
-  {
-    \bool_if:NT \g_@@_active_struct_bool
-      {
-        \tag_mc_end_push:
-        \tag_struct_begin:n { tag=Link }
-        \tag_mc_begin:n { tag=Link }
-        \pdfannot_dict_put:nnx
-          { link/URI }
-          { StructParent }
-          { \tag_struct_parent_int: }
-       }
-  }
-
-\hook_gput_code:nnn
-  {pdfannot/link/URI/after}
-  {tagpdf}
-  {
-    \bool_if:NT \g_@@_active_struct_bool
-      {
-        \tag_struct_insert_annot:xx {\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}
-  {
-    \bool_if:NT \g_@@_active_struct_bool
-      {
-        \tag_mc_end_push:
-        \tag_struct_begin:n{tag=Link}
-        \tag_mc_begin:n{tag=Link}
-        \pdfannot_dict_put:nnx
-          { link/GoTo }
-          { StructParent }
-          { \tag_struct_parent_int: }
-       }
-  }
-
-\hook_gput_code:nnn
-  {pdfannot/link/GoTo/after}
-  {tagpdf}
-  {
-    \bool_if:NT \g_@@_active_struct_bool
-      {
-        \tag_struct_insert_annot:xx {\pdfannot_link_ref_last:}{\tag_struct_parent_int:}
-        \tag_mc_end:
-        \tag_struct_end:
-        \tag_mc_begin_pop:n{}
-      }
-  }
-
-\hook_gput_code:nnn
- {cmd/url/before}
- {tagpdf}
- {\tag_mc_end_push:}
-
-\hook_gput_code:nnn
- {cmd/url/after}
- {tagpdf}
- {\tag_mc_begin_pop:n{}}
-
-\hook_gput_code:nnn
- {cmd/href/before}
- {tagpdf}
- {\tag_mc_end_push:}
-
-\hook_gput_code:nnn
- {cmd/href/after}
- {tagpdf}
- {\tag_mc_begin_pop:n{}}
-
-\hook_gput_code:nnn
- {cmd/hrefurl/before}
- {tagpdf}
- {\tag_mc_end_push:}
-
-\hook_gput_code:nnn
- {cmd/hrefurl/after}
- {tagpdf}
- {\tag_mc_begin_pop:n{}}
-
-%this will go when references are improved
-\hook_gput_code:nnn
- {cmd/T at ref/before}
- {tagpdf}
- {\tag_mc_end_push:}
-
-\hook_gput_code:nnn
- {cmd/T at ref/after}
- {tagpdf}
- {\tag_mc_begin_pop:n{}}
-
-\hook_gput_code:nnn
- {cmd/T at pageref/before}
- {tagpdf}
- {\tag_mc_end_push:}
-
-\hook_gput_code:nnn
- {cmd/T at pageref/after}
- {tagpdf}
- {\tag_mc_begin_pop:n{}}
-
-\hook_gput_code:nnn
- {cmd/T at nameref/before}
- {tagpdf}
- {\tag_mc_end_push:}
-
-\hook_gput_code:nnn
- {cmd/T at nameref/after}
- {tagpdf}
- {\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}
-%</user>
-%
+% \end{implementation}
+% \PrintIndex

Modified: trunk/Master/texmf-dist/source/latex/tagpdf/tagpdf.ins
===================================================================
--- trunk/Master/texmf-dist/source/latex/tagpdf/tagpdf.ins	2021-06-30 20:41:50 UTC (rev 59768)
+++ trunk/Master/texmf-dist/source/latex/tagpdf/tagpdf.ins	2021-06-30 21:14:14 UTC (rev 59769)
@@ -2,7 +2,7 @@
 
 File: tagpdf.ins
 
-Copyright (C) 2019 Ulrike Fischer
+Copyright (C) 2019-2021 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
@@ -34,7 +34,7 @@
 \let\MetaPrefix\relax
 \preamble
 
-Copyright (C) 2019 Ulrike Fischer
+Copyright (C) 2019-2021 Ulrike Fischer
 
 It may be distributed and/or modified under the conditions of
 the LaTeX Project Public License (LPPL), either version 1.3c of
@@ -55,41 +55,28 @@
 \keepsilent
 
 \generate
-  {\file{tagpdf.sty}           {\from{tagpdf.dtx}{package}}}
-\generate
-  {\file{tagpdf-user.sty}      {\from{tagpdf.dtx}{user}}}
-\generate
-  {\file{tagpdf-deprecated.def}{\from{tagpdf.dtx}{deprecated}}}
+  {\file{tagpdf.sty}
+      {
+        \from{tagpdf.dtx}{package}
+        \from{tagpdf-checks.dtx}{package}
+        \from{tagpdf-user.dtx}{package}
+        \from{tagpdf-mc-shared.dtx}{shared}
+        \from{tagpdf.dtx}{mcloading}
+        \from{tagpdf-tree.dtx}{package}
+        \from{tagpdf-roles.dtx}{package}
+        \from{tagpdf-struct.dtx}{package}%contains also the attr code.
+        \from{tagpdf-space.dtx}{package}
+      }
+  }
 
 \generate
   {\file{tagpdf-luatex.def}{\from{tagpdf-backend.dtx}{luatex}}}
 \generate
-  {\file{tagpdf-pdftex.def}{\from{tagpdf-backend.dtx}{pdftex}}}
-
+  {\file{tagpdf-mc-code-generic.sty}{\from{tagpdf-mc-generic.dtx}{generic}}}
 \generate
-  {\file{tagpdf-mc-code-shared.sty}{\from{tagpdf-mc.dtx}{shared}}}
-\generate
-  {\file{tagpdf-mc-code-generic.sty}{\from{tagpdf-mc.dtx}{generic}}}
-\generate
-  {\file{tagpdf-mc-code-lua.sty}{\from{tagpdf-mc.dtx}{luamode}}}
+  {\file{tagpdf-mc-code-lua.sty}{\from{tagpdf-mc-luacode.dtx}{luamode}}}
 
-\generate
-  {\file{tagpdf-struct-code.sty}{\from{tagpdf-struct.dtx}{struct}}}
-\generate
-  {\file{tagpdf-attr-code.sty}{\from{tagpdf-struct.dtx}{attr}}}
 
-\generate
-  {\file{tagpdf-checks-code.sty}{\from{tagpdf-checks.dtx}{checks}}}
-
-\generate
-  {\file{tagpdf-roles-code.sty}{\from{tagpdf-roles.dtx}{roles}}}
-
-\generate
-  {\file{tagpdf-space-code.sty}{\from{tagpdf-space.dtx}{space}}}
-
-\generate
-  {\file{tagpdf-tree-code.sty}{\from{tagpdf-tree.dtx}{tree}}}
-  
 \def\MetaPrefix{-- }
 \def\defaultpostamble{%
   \MetaPrefix^^J%

Deleted: trunk/Master/texmf-dist/tex/latex/tagpdf/tagpdf-attr-code.sty
===================================================================
--- trunk/Master/texmf-dist/tex/latex/tagpdf/tagpdf-attr-code.sty	2021-06-30 20:41:50 UTC (rev 59768)
+++ trunk/Master/texmf-dist/tex/latex/tagpdf/tagpdf-attr-code.sty	2021-06-30 21:14:14 UTC (rev 59769)
@@ -1,129 +0,0 @@
-%%
-%% This is file `tagpdf-attr-code.sty',
-%% generated with the docstrip utility.
-%%
-%% The original source files were:
-%%
-%% tagpdf-struct.dtx  (with options: `attr')
-%% 
-%% Copyright (C) 2019 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.
-%% 
-%% File: tagpdf-struct.dtx
-
-\ProvidesExplPackage {tagpdf-attr-code} {2021-06-14} {0.82}
-  {part of tagpdf - code related to attributes and attribute classes}
-
-
-\seq_new:N  \g__tag_attr_class_used_seq
-\prop_new:N \g__tag_attr_objref_prop %will contain obj num of used attributes
-
-\prop_new:N \g__tag_attr_entries_prop
-\tl_new:N   \g__tag_attr_class_content_tl
-\tl_new:N   \l__tag_attr_objtmp_tl
-\tl_new:N   \l__tag_attr_value_tl
-
-\cs_new_protected:Nn \__tag_attr_new_entry:nn %#1:name, #2: content
-  {
-    \prop_gput:Nnn \g__tag_attr_entries_prop
-      {#1}{#2}
-  }
-
-\keys_define:nn { __tag / setup }
-  {
-    newattribute .code:n =
-      {
-        \__tag_attr_new_entry:nn #1
-      }
-  }
-
-\keys_define:nn { __tag / struct }
-  {
-    attribute-class .code:n =
-     {
-       \clist_set:No \l_tmpa_clist { #1 }
-       \seq_set_from_clist:NN \l_tmpa_seq \l_tmpa_clist
-       \seq_map_inline:Nn \l_tmpa_seq
-         {
-           \prop_if_in:NnF \g__tag_attr_entries_prop {##1}
-             {
-               \msg_error:nnn { tag } { attr-unknown } { ##1 }
-             }
-           \seq_gput_left:Nn\g__tag_attr_class_used_seq { ##1}
-         }
-       \seq_set_map:NNn \l_tmpb_seq \l_tmpa_seq
-         {
-           /##1
-         }
-       \tl_set:Nx \l_tmpa_tl
-         {
-           \int_compare:nT { \seq_count:N \l_tmpa_seq > 1 }{[}
-           \seq_use:Nn \l_tmpb_seq  { \c_space_tl  }
-           \int_compare:nT { \seq_count:N \l_tmpa_seq > 1 }{]}
-         }
-       \int_compare:nT { \seq_count:N \l_tmpa_seq > 0 }
-         {
-           \__tag_prop_gput:cnx
-             { g__tag_struct_\int_eval:n {\c at g__tag_struct_abs_int}_prop }
-             { C }
-             { \l_tmpa_tl }
-          %\prop_show:c  { g__tag_struct_\int_eval:n {\c at g__tag_struct_abs_int}_prop }
-         }
-    }
-  }
-
-\keys_define:nn { __tag / struct }
-  {
-    attribute .code:n  = % A property (attribute, value currently a dictionary)
-      {
-        \clist_set:No          \l_tmpa_clist { #1 }
-        \seq_set_from_clist:NN \l_tmpa_seq \l_tmpa_clist
-        \tl_set:Nx \l__tag_attr_value_tl
-          {
-            \int_compare:nT { \seq_count:N \l_tmpa_seq > 1 }{[}%]
-          }
-        \seq_map_inline:Nn \l_tmpa_seq
-          {
-            \prop_if_in:NnF \g__tag_attr_entries_prop {##1}
-              {
-                \msg_error:nnn { tag } { attr-unknown } { ##1 }
-              }
-            \prop_if_in:NnF \g__tag_attr_objref_prop {##1}
-              {%\prop_show:N \g__tag_attr_entries_prop
-                \pdf_object_unnamed_write:nx
-                  { dict }
-                  {
-                    \prop_item:Nn\g__tag_attr_entries_prop {##1}
-                  }
-                \prop_gput:Nnx \g__tag_attr_objref_prop {##1} {\pdf_object_ref_last:}
-              }
-            \tl_put_right:Nx \l__tag_attr_value_tl
-              {
-                \c_space_tl
-                \prop_item:Nn \g__tag_attr_objref_prop {##1}
-              }
- %     \tl_show:N \l__tag_attr_value_tl
-          }
-        \tl_put_right:Nx \l__tag_attr_value_tl
-          { %[
-            \int_compare:nT { \seq_count:N \l_tmpa_seq > 1 }{]}%
-          }
- %     \tl_show:N \l__tag_attr_value_tl
-        \__tag_prop_gput:cnx
-          { g__tag_struct_\int_eval:n {\c at g__tag_struct_abs_int}_prop }
-          { A }
-          { \l__tag_attr_value_tl }
-    },
-  }
-%% 
-%%
-%% End of file `tagpdf-attr-code.sty'.

Deleted: trunk/Master/texmf-dist/tex/latex/tagpdf/tagpdf-checks-code.sty
===================================================================
--- trunk/Master/texmf-dist/tex/latex/tagpdf/tagpdf-checks-code.sty	2021-06-30 20:41:50 UTC (rev 59768)
+++ trunk/Master/texmf-dist/tex/latex/tagpdf/tagpdf-checks-code.sty	2021-06-30 21:14:14 UTC (rev 59769)
@@ -1,233 +0,0 @@
-%%
-%% This is file `tagpdf-checks-code.sty',
-%% generated with the docstrip utility.
-%%
-%% The original source files were:
-%%
-%% tagpdf-checks.dtx  (with options: `checks')
-%% 
-%% Copyright (C) 2019 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.
-%% 
-%% File: tagpdf-checks.dtx
-\ProvidesExplPackage {tagpdf-checks-code} {2021-06-14} {0.82}
- {part of tagpdf - code related to checks and messages}
-
-
-\msg_new:nnn { tag } {mc-nested}        { nested~marked~content~found~-~mcid~#1 }
-\msg_new:nnn { tag } {mc-tag-missing}   { required~tag~missing~-~mcid~#1 }
-\msg_new:nnn { tag } {mc-label-unknown} { label~#1~unknown~-~rerun }
-\msg_new:nnn { tag } {mc-used-twice}    { mc~#1~has~been~already~used }
-\msg_new:nnn { tag } {mc-not-open}      { there~is~no~mc~to~end~at~#1 }
-\msg_new:nnn { tag } {mc-pushed}        { #1~has~been~pushed~to~the~mc~stack}
-\msg_new:nnn { tag } {mc-popped}        { #1~has~been~removed~from~the~mc~stack }
-
-\msg_new:nnn { tag } {struct-no-objnum}      { objnum~missing~for~structure~#1 }
-\msg_new:nnn { tag } {struct-faulty-nesting} { there~is~no~open~structure~on~the~stack }
-\msg_new:nnn { tag } {struct-missing-tag}    { a~structure~must~have~a~tag! }
-\msg_new:nnn { tag } {struct-show-closing}   { closing~structure~#1~tagged~\prop_item:cn{g__tag_struct_#1_prop}{S} }
-\msg_new:nnn { tag } {struct-used-twice}     { structure~with~label~#1~has~already~been~used}
-\msg_new:nnn { tag } {struct-label-unknown}  { structure~with~label~#1~is~unknown~rerun}
-
-\msg_new:nnn { tag } {attr-unknown}  { attribute~#1~is~unknown}
-
-\msg_new:nnn { tag } {role-missing}     { tag~#1~has~no~role~assigned  }
-\msg_new:nnn { tag } {role-unknown}     { role~#1~is~not~known  }
-\msg_new:nnn { tag } {role-unknown-tag} { tag~#1~is~not~known  }
-\msg_new:nnn { tag } {role-tag}         { mapping~tag~#1~to~role~#2  }
-\msg_new:nnn { tag } {new-tag}          { adding~new~tag~#1 }
-
-\msg_new:nnn { tag } {tree-mcid-index-wrong} {something~is~wrong~with~the~mcid}
-
-\msg_new:nnn { tag } {obj-write-num} {write~obj~#1~to~pdf}
-
-\msg_new:nnn { tag } {sys-no-interwordspace} {engine~#1~doesn't~support~the~interword~spaces}
-
-
-\cs_new:Nn \__tag_check_structure_has_tag:n %#1 struct num %_protected?
-  {
-    \prop_if_in:cnF { g__tag_struct_#1_prop }
-      {S}
-      {
-        \msg_error:nn { tag } {struct-missing-tag}
-      }
-  }
-
-\cs_new:Nn \__tag_check_structure_tag:N            %_protected?
-  {
-    \prop_if_in:NoF \g__tag_role_tags_prop {#1}
-      {
-        \msg_warning:nnx { tag } {role-unknown-tag} {#1}
-      }
-  }
-
-\cs_new:Nn \__tag_check_structure_tag:NN            %_protected?
-  {
-    \exp_args:NNx
-    \prop_if_in:NnF \g__tag_role_tags_prop {#1/#2}
-      {
-        \msg_warning:nnx { tag } {role-unknown-tag} {#1}
-      }
-  }
-
-\cs_new_protected:Nn \__tag_check_info_closing_struct:n %#1 struct num
-  {
-    \msg_info:nnn { tag } {struct-show-closing} {#1}
-  }
-
-\cs_generate_variant:Nn \__tag_check_info_closing_struct:n {o,x}
-
-\cs_new_protected:Nn \__tag_check_no_open_struck:
-  {
-    \msg_error:nn { tag } {struct-faulty-nesting}
-  }
-
-\cs_new_protected:Nn \__tag_check_struct_used:n %#1 label
-  {
-    \prop_get:cnNT
-      {g__tag_struct_\__tag_ref_value:enn{tagpdfstruct-#1}{tagstruct}{unknown}_prop}
-      {P}
-      \l_tmpa_tl
-      {
-        \msg_warning:nnn { tag } {struct-used-twice} {#1}
-      }
-  }
-
-
-\cs_new_protected:Nn \__tag_check_add_tag_role:nn %#1 tag, #2 role
-  {
-    \tl_if_empty:nTF {#2}
-      {
-        \msg_warning:nnn { tag } {role-missing} {#1}
-      }
-      {
-        \prop_get:NnNTF \g__tag_role_tags_prop {#2} \l_tmpa_tl
-          {
-            \msg_info:nnnn { tag } {role-tag} {#1} {#2}
-          }
-          {
-            \msg_warning:nnn { tag } {role-unknown} {#2}
-          }
-      }
-  }
-
-\cs_new_protected:Nn \__tag_check_mc_if_nested:
-  {
-    \__tag_mc_if_in:T
-      {
-        \msg_warning:nnx { tag } {mc-nested} { \__tag_get_mc_abs_cnt: }
-      }
-  }
-
-\cs_new_protected:Nn \__tag_check_mc_if_open:
-  {
-    \__tag_mc_if_in:F
-      {
-        \msg_warning:nnx { tag } {mc-not-open} { \__tag_get_mc_abs_cnt: }
-      }
-  }
-
-\cs_new_protected:Nn \__tag_check_mc_pushed_popped:nn
-  {
-    \int_compare:nNnT
-      { \l__tag_loglevel_int } ={ 2 }
-      { \msg_info:nnx {tag}{mc-#1}{#2} }
-    \int_compare:nNnT
-      { \l__tag_loglevel_int } > { 2 }
-      {
-       \msg_warning:nnx {tag}{mc-#1}{#2}
-       \seq_log:N \g__tag_mc_stack_seq
-      }
-  }
-
-\cs_new:Nn \__tag_check_mc_tag:N %protected??
-  {
-    \tl_if_empty:NT #1
-      {
-        \msg_error:nnx { tag } {mc-tag-missing} { \__tag_get_mc_abs_cnt: }
-      }
-   \prop_if_in:NoF \g__tag_role_tags_NS_prop {#1}
-     {
-       \msg_warning:nnx { tag } {role-unknown-tag} {#1}
-     }
-  }
-
-\seq_new:N \g__tag_check_mc_used_seq
-\cs_new_protected:Nn \__tag_check_mc_used:n
-  {
-    \seq_if_in:NnTF \g__tag_check_mc_used_seq {#1}
-      {
-        \msg_warning:nnn { tag } {mc-used-twice} {#1}
-      }
-      {
-        \seq_gput_right:Nx \g__tag_check_mc_used_seq {#1}
-      }
-  }
-
-\cs_new_protected:Nn \__tag_check_show_MCID_by_page:
-  {
-    \tl_set:Nx \l__tag_tmpa_tl
-      {
-        \__tag_ref_value_lastpage:nn
-          {abspage}
-          {-1}
-      }
-    \int_step_inline:nnnn {1}{1}
-      {
-        \l__tag_tmpa_tl
-      }
-      {
-        \seq_clear:N \l_tmpa_seq
-        \int_step_inline:nnnn
-          {1}
-          {1}
-          {
-            \__tag_ref_value_lastpage:nn
-              {tagmcabs}
-              {-1}
-          }
-          {
-            \int_compare:nT
-              {
-                \__tag_ref_value:enn
-                  {mcid-####1}
-                  {tagabspage}
-                  {-1}
-                =
-                ##1
-             }
-             {
-               \seq_gput_right:Nx \l_tmpa_seq
-                 {
-                   Page##1-####1-
-                   \__tag_ref_value:enn
-                     {mcid-####1}
-                     {tagmcid}
-                     {-1}
-                 }
-             }
-          }
-          \seq_show:N \l_tmpa_seq
-      }
-  }
-
-\cs_new:Nn \__tag_check_record_pdfobj_num:n %protected?
-  {
-    \int_compare:nT { \l__tag_loglevel_int >= 3 }
-      {
-        \msg_info:nnx { tag } {obj-write-num} {#1}
-      }
-  }
-
-%% 
-%%
-%% End of file `tagpdf-checks-code.sty'.

Deleted: trunk/Master/texmf-dist/tex/latex/tagpdf/tagpdf-deprecated.def
===================================================================
--- trunk/Master/texmf-dist/tex/latex/tagpdf/tagpdf-deprecated.def	2021-06-30 20:41:50 UTC (rev 59768)
+++ trunk/Master/texmf-dist/tex/latex/tagpdf/tagpdf-deprecated.def	2021-06-30 21:14:14 UTC (rev 59769)
@@ -1,24 +0,0 @@
-%%
-%% This is file `tagpdf-deprecated.def',
-%% generated with the docstrip utility.
-%%
-%% The original source files were:
-%%
-%% tagpdf.dtx  (with options: `deprecated')
-%% 
-%% Copyright (C) 2019 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.
-%% 
-%% File: tagpdf.dtx
-%% 
-%%
-%% End of file `tagpdf-deprecated.def'.

Modified: trunk/Master/texmf-dist/tex/latex/tagpdf/tagpdf-luatex.def
===================================================================
--- trunk/Master/texmf-dist/tex/latex/tagpdf/tagpdf-luatex.def	2021-06-30 20:41:50 UTC (rev 59768)
+++ trunk/Master/texmf-dist/tex/latex/tagpdf/tagpdf-luatex.def	2021-06-30 21:14:14 UTC (rev 59769)
@@ -6,7 +6,7 @@
 %%
 %% tagpdf-backend.dtx  (with options: `luatex')
 %% 
-%% Copyright (C) 2019 Ulrike Fischer
+%% Copyright (C) 2019-2021 Ulrike Fischer
 %% 
 %% It may be distributed and/or modified under the conditions of
 %% the LaTeX Project Public License (LPPL), either version 1.3c of
@@ -19,71 +19,59 @@
 %% and all files in that bundle must be distributed together.
 %% 
 %% File: tagpdf-backend.dtx
-\ProvidesExplFile {tagpdf-luatex.def} {2021-06-14} {0.82}
+\ProvidesExplFile {tagpdf-luatex.def} {2021-06-29} {0.9}
   {tagpdf~driver~for~luatex}
-
-\newattribute \l__tag_mc_type_attr     %the value represent the type
-\newattribute \l__tag_mc_cnt_attr      %will hold the \c at g__tag_MCID_abs_int value
-
-\newattribute \g__tag_interwordspace_attr
-\newattribute \g__tag_interwordfont_attr
-
 {
   \fontencoding{TU}\fontfamily{lmr}\fontseries{m}\fontshape{n}\fontsize{10pt}{10pt}\selectfont
 }
-\directlua { tagpdf=require('tagpdf.lua') }
-
-%%%% driver (lualatex) commands
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-
-\cs_new_protected:Nn \__tag_prop_new:N
+\lua_now:e { tagpdf=require('tagpdf.lua') }
+\cs_set_protected:Npn \__tag_prop_new:N #1
   {
     \prop_new:N #1
-    \directlua { ltx.__tag.tables.\cs_to_str:N#1 = {} }
+    \lua_now:e { ltx.__tag.tables.\cs_to_str:N#1 = {} }
   }
 
-\cs_new_protected:Nn \__tag_seq_new:N
+\cs_set_protected:Npn \__tag_seq_new:N #1
   {
     \seq_new:N #1
-    \directlua { ltx.__tag.tables.\cs_to_str:N#1 = {} }
+    \lua_now:e { ltx.__tag.tables.\cs_to_str:N#1 = {} }
   }
 
-\cs_new_protected:Nn \__tag_prop_gput:Nnn
+\cs_set_protected:Npn \__tag_prop_gput:Nnn #1 #2 #3
   {
     \prop_gput:Nnn #1 { #2 } { #3 }
-    \directlua { ltx.__tag.tables.\cs_to_str:N#1 ["#2"] = "#3" }
+    \lua_now:e { ltx.__tag.tables.\cs_to_str:N#1 ["#2"] = "#3" }
   }
 
-\cs_new_protected:Nn \__tag_seq_gput_right:Nn
+\cs_set_protected:Npn \__tag_seq_gput_right:Nn #1 #2
   {
     \seq_gput_right:Nn #1 { #2 }
-    \directlua { table.insert(ltx.__tag.tables.\cs_to_str:N#1, "#2") }
+    \lua_now:e { table.insert(ltx.__tag.tables.\cs_to_str:N#1, "#2") }
   }
 
 
-\cs_new:Npn \__tag_seq_item:cn #1 #2
+\cs_set:Npn \__tag_seq_item:cn #1 #2
   {
-    \directlua { tex.print(ltx.__tag.tables.#1[#2]) }
+    \lua_now:e { tex.print(ltx.__tag.tables.#1[#2]) }
   }
 
-\cs_new:Npn \__tag_prop_item:cn #1 #2
+\cs_set:Npn \__tag_prop_item:cn #1 #2
   {
-    \directlua { tex.print(ltx.__tag.tables.#1["#2"]) }
+    \lua_now:e { tex.print(ltx.__tag.tables.#1["#2"]) }
   }
 
-\cs_new_protected:Nn \__tag_seq_show:N
+\cs_set_protected:Npn \__tag_seq_show:N #1
   {
     \seq_show:N #1
-    \directlua { ltx.__tag.trace.log ("lua~sequence~array~\cs_to_str:N#1",1) }
-    \directlua { ltx.__tag.trace.show_seq (ltx.__tag.tables.\cs_to_str:N#1) }
+    \lua_now:e { ltx.__tag.trace.log ("lua~sequence~array~\cs_to_str:N#1",1) }
+    \lua_now:e { ltx.__tag.trace.show_seq (ltx.__tag.tables.\cs_to_str:N#1) }
   }
 
-\cs_new_protected:Nn \__tag_prop_show:N
+\cs_set_protected:Npn \__tag_prop_show:N #1
   {
     \prop_show:N #1
-    \directlua {ltx.__tag.trace.log  ("lua~property~table~\cs_to_str:N#1",1) }
-    \directlua {ltx.__tag.trace.show_prop (ltx.__tag.tables.\cs_to_str:N#1) }
+    \lua_now:e {ltx.__tag.trace.log  ("lua~property~table~\cs_to_str:N#1",1) }
+    \lua_now:e {ltx.__tag.trace.show_prop (ltx.__tag.tables.\cs_to_str:N#1) }
  }
 %% 
 %%

Modified: trunk/Master/texmf-dist/tex/latex/tagpdf/tagpdf-mc-code-generic.sty
===================================================================
--- trunk/Master/texmf-dist/tex/latex/tagpdf/tagpdf-mc-code-generic.sty	2021-06-30 20:41:50 UTC (rev 59768)
+++ trunk/Master/texmf-dist/tex/latex/tagpdf/tagpdf-mc-code-generic.sty	2021-06-30 21:14:14 UTC (rev 59769)
@@ -4,9 +4,9 @@
 %%
 %% The original source files were:
 %%
-%% tagpdf-mc.dtx  (with options: `generic')
+%% tagpdf-mc-generic.dtx  (with options: `generic')
 %% 
-%% Copyright (C) 2019 Ulrike Fischer
+%% Copyright (C) 2019-2021 Ulrike Fischer
 %% 
 %% It may be distributed and/or modified under the conditions of
 %% the LaTeX Project Public License (LPPL), either version 1.3c of
@@ -19,14 +19,17 @@
 %% and all files in that bundle must be distributed together.
 %% 
 %% File: tagpdf-mc.dtx
-\ProvidesExplPackage {tagpdf-mc-code-generic} {2021-06-14} {0.82}
+\ProvidesExplPackage {tagpdf-mc-code-generic} {2021-06-29} {0.9}
  {part of tagpdf - code related to marking chunks - generic mode}
+\bool_new:N \g__tag_in_mc_bool
 
-
 \__tag_prop_new:N \g__tag_MCID_byabspage_prop
 
-\bool_new:N \g__tag_in_mc_bool
+\tl_new:N \l__tag_mc_ref_abspage_tl
 
+\tl_new:N \l__tag_mc_tmpa_tl
+
+
 \prg_new_conditional:Nnn \__tag_mc_if_in: {p,T,F,TF}
   {
     \bool_if:NTF \g__tag_in_mc_bool
@@ -35,29 +38,11 @@
   }
 
 \prg_new_eq_conditional:NNn \tag_mc_if_in: \__tag_mc_if_in: {p,T,F,TF}
-
-\cs_new_protected:Nn \__tag_mc_bmc:n
-  {
-    \pdf_bmc:n {#1}
-  }
-
-\cs_new_protected:Nn \__tag_mc_emc:
-  {
-    \pdf_emc:
-    %\__tag_pdfliteral_page:n
-  }
-
-\cs_new_protected:Nn \__tag_mc_bdc:nn
-  {
-    \pdf_bdc:nn { #1 } { #2 }
-  }
-
+\cs_set_eq:NN \__tag_mc_bmc:n  \pdf_bmc:n
+\cs_set_eq:NN \__tag_mc_emc:   \pdf_emc:
+\cs_set_eq:NN \__tag_mc_bdc:nn \pdf_bdc:nn
 \cs_generate_variant:Nn \__tag_mc_bdc:nn {nx}
-
-\tl_new:N \l__tag_mc_ref_abspage_tl %will store the abspage value of label
-\tl_new:N \l__tag_mc_tmp_tl
-
-\cs_new:Nn \__tag_mc_bdc_mcid:nn
+\cs_new_protected:Npn \__tag_mc_bdc_mcid:nn #1 #2
   {
     \int_gincr:N \c at g__tag_MCID_abs_int
     \tl_set:Nx \l__tag_mc_ref_abspage_tl
@@ -74,14 +59,14 @@
       {
         \l__tag_mc_ref_abspage_tl
       }
-      \l__tag_mc_tmp_tl
+      \l__tag_mc_tmpa_tl
       {
         %key already present, use value for MCID and add 1 for the next
-        \int_gset:Nn \g__tag_MCID_tmp_bypage_int { \l__tag_mc_tmp_tl }
+        \int_gset:Nn \g__tag_MCID_tmp_bypage_int { \l__tag_mc_tmpa_tl }
         \__tag_prop_gput:Nxx
           \g__tag_MCID_byabspage_prop
           { \l__tag_mc_ref_abspage_tl }
-          { \int_eval:n {\l__tag_mc_tmp_tl +1} }
+          { \int_eval:n {\l__tag_mc_tmpa_tl +1} }
       }
       {
         %key not present, set MCID to 0 and insert 1
@@ -96,38 +81,96 @@
         mcid-\int_use:N \c at g__tag_MCID_abs_int
       }
       { mc }
-   %\exp_args:Nnx
      \__tag_mc_bdc:nx
        {#1}
        { /MCID~\int_eval:n { \g__tag_MCID_tmp_bypage_int }~ \exp_not:n { #2 } }
  }
-
-\cs_new:Nn \__tag_mc_bdc_mcid:n
+\cs_new_protected:Npn \__tag_mc_bdc_mcid:n #1
   {
     \__tag_mc_bdc_mcid:nn {#1} {}
   }
 
-\cs_new:Nn  \__tag_mc_bmc_artifact:
+\cs_new_protected:Npn \__tag_mc_handle_mcid:nn #1 #2 %#1 tag, #2 properties
   {
-    \__tag_mc_bmc:n {Artifact}
+    \__tag_mc_bdc_mcid:nn {#1} {#2}
   }
 
-\cs_new:Nn \__tag_mc_bmc_artifact:n
+\cs_generate_variant:Nn \__tag_mc_handle_mcid:nn {VV}
+
+\cs_new_protected:Npn \__tag_mc_handle_stash:n #1 %1 mcidnum
   {
+    \__tag_check_mc_used:n {#1}
+    \__tag_struct_kid_mc_gput_right:nn
+      { \g__tag_struct_stack_current_tl }
+      {#1}
+   \prop_gput:Nxx \g__tag_mc_parenttree_prop
+     {#1}
+     { \g__tag_struct_stack_current_tl }
+  }
+\cs_generate_variant:Nn \__tag_mc_handle_stash:n { x }
+
+\cs_new_protected:Npn  \__tag_mc_bmc_artifact:
+  {
+    \__tag_mc_bmc:n {Artifact}
+  }
+\cs_new_protected:Npn \__tag_mc_bmc_artifact:n #1
+  {
     \__tag_mc_bdc:nn {Artifact}{/Type/#1}
   }
+\cs_new_protected:Npn \__tag_mc_handle_artifact:N #1
+   % #1 is a var containing the artifact type
+  {
+    \tl_if_empty:NTF #1
+      { \__tag_mc_bmc_artifact: }
+      { \exp_args:NV\__tag_mc_bmc_artifact:n #1 }
+  }
 
+\cs_new:Nn \__tag_get_data_mc_tag: { \g__tag_mc_key_tag_tl }
+\cs_new_protected:Npn \tag_mc_begin:n #1 %#1 keyval
+  {
+    \__tag_check_if_active_mc:T
+      {
+        \group_begin: %hm
+        \__tag_check_mc_if_nested:
+        \bool_gset_true:N \g__tag_in_mc_bool
+        \keys_set:nn { __tag / mc } {#1}
+        \bool_if:NTF \l__tag_mc_artifact_bool
+          { %handle artifact
+            \__tag_mc_handle_artifact:N \l__tag_mc_artifact_type_tl
+          }
+          { %handle mcid type
+            \__tag_check_mc_tag:N  \l__tag_mc_key_tag_tl
+            \__tag_mc_handle_mcid:VV
+               \l__tag_mc_key_tag_tl
+               \l__tag_mc_key_properties_tl
+            \tl_if_empty:NF {\l__tag_mc_key_label_tl}
+              {
+                \exp_args:NV
+                \__tag_mc_handle_mc_label:n \l__tag_mc_key_label_tl
+              }
+            \bool_if:NF \l__tag_mc_key_stash_bool
+              {
+                \__tag_mc_handle_stash:x { \int_use:N \c at g__tag_MCID_abs_int }
+              }
+          }
+        \group_end:
+      }
+  }
+\cs_new_protected:Nn \tag_mc_end:
+  {
+    \__tag_check_if_active_mc:T
+      {
+        \__tag_check_mc_if_open:
+        \bool_gset_false:N \g__tag_in_mc_bool
+        \tl_gset:Nn  \g__tag_mc_key_tag_tl { }
+        \__tag_mc_emc:
+      }
+  }
 
-
-\tl_new:N \l__tag_mc_key_tag_tl
-\tl_new:N \g__tag_mc_key_tag_tl %for "outside" queries
-\tl_new:N \l__tag_mc_key_properties_tl
-
 \keys_define:nn { __tag / mc }
   {
-    tag .code:n = % the name (H,P,Spa) etc
+    tag .code:n = % the name (H,P,Span) etc
       {
-         %%????????? \pdfescapename??
         \tl_set:Nx   \l__tag_mc_key_tag_tl { #1 }
         \tl_gset:Nx  \g__tag_mc_key_tag_tl { #1 }
       },
@@ -181,98 +224,10 @@
         \exp_args:Nnx
           \keys_set:nn
             { __tag / mc }
-            { artifact-bool, artifact-type=#1 }
+            { __artifact-bool, __artifact-type=#1 }
       },
     artifact .default:n    = {notype}
   }
-
-\cs_new:Nn \__tag_mc_handle_artifact:N %#1 contains the artifact type
-  {
-    \tl_if_empty:NTF #1
-      { \__tag_mc_bmc_artifact: }
-      { \exp_args:No\__tag_mc_bmc_artifact:n {#1} }
-  }
-
-\cs_new:Nn \__tag_mc_handle_mcid:nn %#1 tag, #2 properties
-  {
-    \__tag_mc_bdc_mcid:nn {#1} {#2}
-  }
-
-\cs_generate_variant:Nn \__tag_mc_handle_mcid:nn {VV}
-
-\cs_new:Nn \__tag_mc_handle_stash:n %1 mcidnum
-  {
-    \__tag_check_mc_used:n {#1}
-    \__tag_struct_kid_mc_gput_right:nn
-      { \g__tag_struct_stack_current_tl }
-      {#1}
-   \prop_gput:Nxx \g__tag_mc_parenttree_prop
-     {#1}
-     { \g__tag_struct_stack_current_tl }
-  }
-
-\cs_new_protected:Nn \tag_mc_begin:n
-  {
-    \group_begin: %hm
-    \__tag_check_mc_if_nested:
-    \bool_gset_true:N \g__tag_in_mc_bool
-    \keys_set:nn { __tag / mc } {#1}
-    \bool_if:NTF \l__tag_mc_artifact_bool
-      { %handle artifact
-        \__tag_mc_handle_artifact:N \l__tag_mc_artifact_type_tl
-      }
-      { %handle mcid type
-        \__tag_check_mc_tag:N  \l__tag_mc_key_tag_tl
-        \__tag_mc_handle_mcid:VV
-           \l__tag_mc_key_tag_tl
-           \l__tag_mc_key_properties_tl
-        \tl_if_empty:NF {\l__tag_mc_key_label_tl}
-          {
-            \__tag_mc_handle_mc_label:n { \l__tag_mc_key_label_tl }
-          }
-        \bool_if:NF \l__tag_mc_key_stash_bool
-          {
-            \__tag_mc_handle_stash:n { \int_use:N \c at g__tag_MCID_abs_int }
-          }
-      }
-    \group_end:
-  }
-
-\cs_new_protected:Nn \tag_mc_end:
-  {
-    \__tag_check_mc_if_open:
-    \bool_gset_false:N \g__tag_in_mc_bool
-    \tl_gset:Nn  \g__tag_mc_key_tag_tl { }
-    \__tag_mc_emc:
-  }
-
-\cs_new_protected:Nn \tag_mc_use:n %#1: label name
-  {
-    \tl_set:Nx  \l_tmpa_tl { \__tag_ref_value:enn{tagpdf-#1}{tagmcabs}{} }
-    \tl_if_empty:NTF\l_tmpa_tl
-      {
-        \msg_warning:nnn {tag} {mc-label-unknown} {#1}
-      }
-      {
-        \prop_gput:Nxx
-          \g__tag_mc_parenttree_prop
-          {
-            \__tag_ref_value:enn {tagpdf-#1} {tagmcabs} {}
-          }
-          {
-            \g__tag_struct_stack_current_tl
-          }
-        \__tag_struct_kid_mc_gput_right:nn
-          {
-            \g__tag_struct_stack_current_tl
-          }
-          {
-            \__tag_ref_value:enn {tagpdf-#1} {tagmcabs} {}
-          }
-       }
-  }
-
-\cs_new:Nn \__tag_get_data_mc_tag: { \g__tag_mc_key_tag_tl }
 %% 
 %%
 %% End of file `tagpdf-mc-code-generic.sty'.

Modified: trunk/Master/texmf-dist/tex/latex/tagpdf/tagpdf-mc-code-lua.sty
===================================================================
--- trunk/Master/texmf-dist/tex/latex/tagpdf/tagpdf-mc-code-lua.sty	2021-06-30 20:41:50 UTC (rev 59768)
+++ trunk/Master/texmf-dist/tex/latex/tagpdf/tagpdf-mc-code-lua.sty	2021-06-30 21:14:14 UTC (rev 59769)
@@ -4,9 +4,9 @@
 %%
 %% The original source files were:
 %%
-%% tagpdf-mc.dtx  (with options: `luamode')
+%% tagpdf-mc-luacode.dtx  (with options: `luamode')
 %% 
-%% Copyright (C) 2019 Ulrike Fischer
+%% Copyright (C) 2019-2021 Ulrike Fischer
 %% 
 %% It may be distributed and/or modified under the conditions of
 %% the LaTeX Project Public License (LPPL), either version 1.3c of
@@ -19,18 +19,38 @@
 %% and all files in that bundle must be distributed together.
 %% 
 %% File: tagpdf-mc.dtx
-\ProvidesExplPackage {tagpdf-mc-code-lua} {2021-06-14} {0.82}
+
+\ProvidesExplPackage {tagpdf-mc-code-lua} {2021-06-29} {0.9}
   {tagpdf - mc code only for the luamode }
-
-
-
-
-
 \hook_gput_code:nnn{begindocument}{tagpdf/mc}
   {
+    \bool_if:NT\g__tag_active_space_bool
+      {
+        \lua_now:e
+          {
+           if~luatexbase.callbacktypes.pre_shipout_filter~then~
+              luatexbase.add_to_callback("pre_shipout_filter", function(TAGBOX)~
+              ltx.__tag.func.space_chars_shipout(TAGBOX)~return~true~
+              end, "tagpdf")~
+            end
+          }
+       \lua_now:e
+         {
+           if~luatexbase.callbacktypes.pre_shipout_filter~then~
+           token.get_next()~
+           end
+         }\@secondoftwo\@gobble
+           {
+             \hook_gput_code:nnn{shipout/before}{tagpdf/lua}
+               {
+                \lua_now:e
+                   { ltx.__tag.func.space_chars_shipout (tex.box["ShipoutBox"]) }
+               }
+           }
+      }
     \bool_if:NT\g__tag_active_mc_bool
       {
-        \directlua
+        \lua_now:e
           {
             if~luatexbase.callbacktypes.pre_shipout_filter~then~
               luatexbase.add_to_callback("pre_shipout_filter", function(TAGBOX)~
@@ -38,7 +58,7 @@
               end, "tagpdf")~
             end
           }
-       \directlua
+       \lua_now:e
          {
            if~luatexbase.callbacktypes.pre_shipout_filter~then~
            token.get_next()~
@@ -47,32 +67,159 @@
            {
              \hook_gput_code:nnn{shipout/before}{tagpdf/lua}
                {
-                 \directlua
+                 \lua_now:e
                    { ltx.__tag.func.mark_shipout (tex.box["ShipoutBox"]) }
                }
            }
       }
   }
-
 \prg_new_conditional:Nnn \__tag_mc_if_in: {p,T,F,TF}
   {
-    \int_compare:nNnTF { -2147483647 }={ \l__tag_mc_type_attr }
+    \int_compare:nNnTF
+      { -2147483647 }
+      =
+      {\lua_now:e
+         {
+           tex.print(tex.getattribute(luatexbase.attributes.g__tag_mc_type_attr))
+         }
+      }
       { \prg_return_false:  }
       { \prg_return_true: }
   }
 
 \prg_new_eq_conditional:NNn \tag_mc_if_in: \__tag_mc_if_in: {p,T,F,TF}
+\cs_new:Nn \__tag_mc_lua_set_mc_type_attr:n % #1 is a tag name
+  {
+    %TODO ltx.__tag.func.get_num_from("#1") seems not to return a suitable number??
+    \tl_set:Nx\l__tag_tmpa_tl{\lua_now:e{ltx.__tag.func.output_num_from ("#1")} }
+    \lua_now:e
+      {
+        tex.setattribute
+         (
+          "global",
+          luatexbase.attributes.g__tag_mc_type_attr,
+          \l__tag_tmpa_tl
+         )
+      }
+    \lua_now:e
+      {
+        tex.setattribute
+         (
+           "global",
+           luatexbase.attributes.g__tag_mc_cnt_attr,
+           \__tag_get_mc_abs_cnt:
+         )
+      }
+  }
 
-\tl_new:N \l__tag_mc_key_tag_tl
-\tl_new:N \l__tag_mc_key_label_tl
-\tl_new:N \l__tag_mc_key_properties_tl
+\cs_generate_variant:Nn\__tag_mc_lua_set_mc_type_attr:n { o }
 
+\cs_new:Nn \__tag_mc_lua_unset_mc_type_attr:
+  {
+    \lua_now:e
+      {
+        tex.setattribute
+          (
+            "global",
+            luatexbase.attributes.g__tag_mc_type_attr,
+            -2147483647
+          )
+      }
+     \lua_now:e
+      {
+        tex.setattribute
+          (
+            "global",
+            luatexbase.attributes.g__tag_mc_cnt_attr,
+            -2147483647
+          )
+      }
+  }
+
+\cs_new:Nn \__tag_mc_insert_mcid_kids:n
+  {
+    \lua_now:e { ltx.__tag.func.mc_insert_kids (#1,0) }
+  }
+
+\cs_new:Nn \__tag_mc_insert_mcid_single_kids:n
+  {
+    \lua_now:e {ltx.__tag.func.mc_insert_kids (#1,1) }
+  }
+\cs_new:Nn \__tag_mc_handle_stash:n %1 mcidnum
+  {
+    \__tag_check_mc_used:n { #1 }
+    \seq_gput_right:cn % Don't fill a lua table due to the command in the item,
+                       % so use the kernel command
+      { g__tag_struct_kids_\g__tag_struct_stack_current_tl _seq }
+      {
+        \__tag_mc_insert_mcid_kids:n {#1}%
+      }
+    \lua_now:e
+      {
+        ltx.__tag.func.store_struct_mcabs
+          (
+            \g__tag_struct_stack_current_tl,#1
+          )
+      }
+    \prop_gput:Nxx
+      \g__tag_mc_parenttree_prop
+      { #1 }
+      { \g__tag_struct_stack_current_tl }
+  }
+
+\cs_generate_variant:Nn \__tag_mc_handle_stash:n { x }
+\cs_new_protected:Nn \tag_mc_begin:n
+  {
+    \__tag_check_if_active_mc:T
+      {
+        \group_begin:
+        %\__tag_check_mc_if_nested:
+        \bool_gset_true:N \g__tag_in_mc_bool
+        \bool_set_false:N\l__tag_mc_artifact_bool
+        \tl_clear:N \l__tag_mc_key_properties_tl
+        \int_gincr:N \c at g__tag_MCID_abs_int
+        \keys_set:nn { __tag / mc }{ label={}, #1 }
+        %check that a tag or artifact has been used
+        \__tag_check_mc_tag:N \l__tag_mc_key_tag_tl
+        %set the attributes:
+        \__tag_mc_lua_set_mc_type_attr:o  { \l__tag_mc_key_tag_tl }
+        \bool_if:NF \l__tag_mc_artifact_bool
+          { % store the absolute num name in a label:
+            \tl_if_empty:NF {\l__tag_mc_key_label_tl}
+              {
+                \exp_args:NV
+                 \__tag_mc_handle_mc_label:n  \l__tag_mc_key_label_tl
+              }
+           % if not stashed record the absolute number
+            \bool_if:NF \l__tag_mc_key_stash_bool
+              {
+                \__tag_mc_handle_stash:x { \__tag_get_mc_abs_cnt: }
+              }
+          }
+        \group_end:
+     }
+  }
+\cs_new_protected:Nn \tag_mc_end:
+  {
+    \__tag_check_if_active_mc:T
+      {
+        %\__tag_check_mc_if_open:
+        \bool_gset_false:N \g__tag_in_mc_bool
+        \bool_set_false:N\l__tag_mc_artifact_bool
+        \__tag_mc_lua_unset_mc_type_attr:
+        \tl_set:Nn  \l__tag_mc_key_tag_tl { }
+        \tl_gset:Nn \g__tag_mc_key_tag_tl { }
+      }
+  }
+\cs_new:Npn \__tag_get_data_mc_tag: { \g__tag_mc_key_tag_tl }
+
 \keys_define:nn { __tag / mc }
   {
     tag .code:n = %
-      {%%????????? \pdfescapename??
-        \tl_set:Nx  \l__tag_mc_key_tag_tl { #1 }
-        \directlua
+      {
+        \tl_set:Nx   \l__tag_mc_key_tag_tl { #1 }
+        \tl_gset:Nx  \g__tag_mc_key_tag_tl { #1 }
+        \lua_now:e
           {
             ltx.__tag.func.store_mc_data(\__tag_get_mc_abs_cnt:,"tag","#1")
           }
@@ -80,7 +227,7 @@
     raw .code:n =
       {
         \tl_put_right:Nx \l__tag_mc_key_properties_tl { #1 }
-        \directlua
+        \lua_now:e
           {
             ltx.__tag.func.store_mc_data(\__tag_get_mc_abs_cnt:,"raw","#1")
           }
@@ -94,7 +241,7 @@
           { utf16/hex }
         \tl_put_right:Nn \l__tag_mc_key_properties_tl { /Alt~< }
         \tl_put_right:No \l__tag_mc_key_properties_tl { \l__tag_tmpa_str>~ }
-        \directlua
+        \lua_now:e
           {
             ltx.__tag.func.store_mc_data
               (
@@ -111,7 +258,7 @@
           { utf16/hex }
         \tl_put_right:Nn \l__tag_mc_key_properties_tl { /Alt~< }
         \tl_put_right:No \l__tag_mc_key_properties_tl { \l__tag_tmpa_str>~ }
-        \directlua
+        \lua_now:e
           {
             ltx.__tag.func.store_mc_data
               (
@@ -128,7 +275,7 @@
           { utf16/hex }
         \tl_put_right:Nn \l__tag_mc_key_properties_tl { /Alt~< }
         \tl_put_right:No \l__tag_mc_key_properties_tl { \l__tag_tmpa_str>~ }
-        \directlua
+        \lua_now:e
           {
             ltx.__tag.func.store_mc_data
               (
@@ -145,7 +292,7 @@
           { utf16/hex }
         \tl_put_right:Nn \l__tag_mc_key_properties_tl { /Alt~< }
         \tl_put_right:No \l__tag_mc_key_properties_tl { \l__tag_tmpa_str>~ }
-        \directlua
+        \lua_now:e
           {
             ltx.__tag.func.store_mc_data
               (
@@ -158,7 +305,7 @@
     label .code:n =
       {
         \tl_set:Nn\l__tag_mc_key_label_tl { #1 }
-        \directlua
+        \lua_now:e
           {
             ltx.__tag.func.store_mc_data
               (
@@ -168,7 +315,7 @@
       },
     __artifact-store .code:n =
       {
-        \directlua
+        \lua_now:e
           {
             ltx.__tag.func.store_mc_data
               (
@@ -181,7 +328,7 @@
         \exp_args:Nnx
           \keys_set:nn
             { __tag / mc}
-            { artifact-bool, artifact-type=#1, tag=Artifact }
+            { __artifact-bool, __artifact-type=#1, tag=Artifact }
         \exp_args:Nnx
           \keys_set:nn
             { __tag / mc }
@@ -190,130 +337,6 @@
     artifact .default:n    = { notype }
   }
 
-
-\cs_set_protected:Npn \__tag_attribute_gset:Nn #1 #2
-  {
-    \tex_global:D \setattribute #1 #2
-  }
-
-\cs_set_protected:Npn \__tag_attribute_set:Nn #1 #2
-  {
-    \setattribute #1 #2
-  }
-
-\cs_set_protected:Npn \__tag_attribute_gunset:N #1
-  {
-    \tex_global:D \unsetattribute #1
-  }
-
-\cs_set_protected:Npn \__tag_attribute_unset:N #1
-  {
-    \unsetattribute #1
-  }
-
-\cs_new:Nn \__tag_mc_lua_set_mc_type_attr:n % #1 is a tag name
-  {
-    \__tag_attribute_set:Nn \l__tag_mc_type_attr
-      {
-        \directlua { ltx.__tag.func.output_num_from ("#1") }
-      }
-    \__tag_attribute_set:Nn \l__tag_mc_cnt_attr  { \__tag_get_mc_abs_cnt: }
-  }
-
-\cs_generate_variant:Nn\__tag_mc_lua_set_mc_type_attr:n { o }
-
-\cs_new:Nn \__tag_mc_lua_unset_mc_type_attr:
-  {
-    \__tag_attribute_unset:N \l__tag_mc_type_attr
-    \__tag_attribute_unset:N \l__tag_mc_cnt_attr
-  }
-
-\cs_new:Nn \__tag_mc_insert_mcid_kids:n
-  {
-    \directlua { ltx.__tag.func.mc_insert_kids (#1,0) }
-  }
-
-\cs_new:Nn \__tag_mc_insert_mcid_single_kids:n
-  {
-    \directlua {ltx.__tag.func.mc_insert_kids (#1,1) }
-  }
-
-
-\cs_new:Nn \__tag_mc_handle_stash:n %1 mcidnum
-  {
-    \__tag_check_mc_used:n { #1 }
-    \seq_gput_right:cn % Don't fill a lua table due to the command in the item,
-                       % so use the kernel command
-      { g__tag_struct_kids_\g__tag_struct_stack_current_tl _seq }
-      {
-        \__tag_mc_insert_mcid_kids:n {#1}%
-      }
-    \directlua
-      {
-        ltx.__tag.func.store_struct_mcabs
-          (
-            \g__tag_struct_stack_current_tl,#1
-          )
-      }
-    \prop_gput:Nxx
-      \g__tag_mc_parenttree_prop
-      { #1 }
-      { \g__tag_struct_stack_current_tl }
-  }
-
-\cs_generate_variant:Nn \__tag_mc_handle_stash:n { o }
-
-\cs_new_protected:Nn \tag_mc_begin:n
-  {
-    %\group_begin:
-    %\__tag_check_mc_if_nested:
-    %\bool_gset_true:N \g__tag_in_mc_bool
-    \bool_set_false:N\l__tag_mc_artifact_bool
-    \int_gincr:N \c at g__tag_MCID_abs_int
-    \tl_clear:N \l__tag_mc_key_properties_tl
-    \keys_set:nn { __tag / mc }{ label={}, #1 }
-    %check that a tag or artifact has been used
-    \__tag_check_mc_tag:N \l__tag_mc_key_tag_tl
-    %set the attributes:
-    \__tag_mc_lua_set_mc_type_attr:o  { \l__tag_mc_key_tag_tl }
-    \bool_if:NF \l__tag_mc_artifact_bool
-      { % store the absolute num name in a label:
-        \tl_if_empty:NF {\l__tag_mc_key_label_tl}
-          {
-            \__tag_mc_handle_mc_label:n { \l__tag_mc_key_label_tl }
-          }
-       % if not stashed record the absolute number
-        \bool_if:NF \l__tag_mc_key_stash_bool
-          {
-            \exp_args:Nx \__tag_mc_handle_stash:n { \__tag_get_mc_abs_cnt: }
-          }
-      }
-    %\bool_set_false:N\l__tag_mc_artifact_bool
-    %\group_end:
-  }
-
-\cs_new_protected:Nn \tag_mc_end:
-  {
-    %\__tag_check_mc_if_open:
-    %\bool_gset_false:N \g__tag_in_mc_bool
-    \bool_set_false:N\l__tag_mc_artifact_bool
-    \__tag_mc_lua_unset_mc_type_attr:
-    \tl_set:Nn  \l__tag_mc_key_tag_tl { }
-  }
-
-\cs_new_protected:Nn \tag_mc_use:n %#1: label name
-  {
-    \tl_set:Nx  \l_tmpa_tl { \__tag_ref_value:enn{tagpdf-#1}{tagmcabs}{} }
-    \tl_if_empty:NTF\l_tmpa_tl
-      {
-        \msg_warning:nnn {tag} {mc-label-unknown} { #1 }
-      }
-      {
-        \__tag_mc_handle_stash:o { \l_tmpa_tl }
-      }
-  }
-
-\cs_new:Nn \__tag_get_data_mc_tag: { \l__tag_mc_key_tag_tl }
 %% 
 %%
 %% End of file `tagpdf-mc-code-lua.sty'.

Deleted: trunk/Master/texmf-dist/tex/latex/tagpdf/tagpdf-mc-code-shared.sty
===================================================================
--- trunk/Master/texmf-dist/tex/latex/tagpdf/tagpdf-mc-code-shared.sty	2021-06-30 20:41:50 UTC (rev 59768)
+++ trunk/Master/texmf-dist/tex/latex/tagpdf/tagpdf-mc-code-shared.sty	2021-06-30 21:14:14 UTC (rev 59769)
@@ -1,117 +0,0 @@
-%%
-%% This is file `tagpdf-mc-code-shared.sty',
-%% generated with the docstrip utility.
-%%
-%% The original source files were:
-%%
-%% tagpdf-mc.dtx  (with options: `shared')
-%% 
-%% Copyright (C) 2019 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.
-%% 
-%% File: tagpdf-mc.dtx
-\ProvidesExplPackage {tagpdf-mc-code-shared} {2021-06-14} {0.82}
-  {part of tagpdf - code related to marking chunks -
-   code shared by generic and luamode }
-
-\newcounter { g__tag_MCID_abs_int }
-\cs_new:Nn \__tag_get_mc_abs_cnt: { \int_use:N \c at g__tag_MCID_abs_int }
-
-
-\cs_new:Nn \__tag_mc_handle_mc_label:n
-  {
-    \__tag_ref_label:en{tagpdf-#1}{mc}
-  }
-
-\__tag_prop_new:N \g__tag_mc_parenttree_prop
-
-\seq_new:N \g__tag_mc_stack_seq
-\tl_new:N \l__tag_mc_artifact_type_tl
-
-\keys_define:nn { __tag / mc }
-  {
-    stash                  .bool_set:N    = \l__tag_mc_key_stash_bool,
-    artifact-bool          .bool_set:N    = \l__tag_mc_artifact_bool,
-    artifact-type          .choice:,
-    artifact-type / pagination .code:n    =
-      {
-        \tl_set:Nn \l__tag_mc_artifact_type_tl { Pagination }
-      },
-    artifact-type / layout     .code:n    =
-      {
-        \tl_set:Nn \l__tag_mc_artifact_type_tl { Layout }
-      },
-    artifact-type / page       .code:n    =
-      {
-        \tl_set:Nn \l__tag_mc_artifact_type_tl { Page }
-      },
-    artifact-type / background .code:n    =
-      {
-        \tl_set:Nn \l__tag_mc_artifact_type_tl { Background }
-      },
-    artifact-type / notype     .code:n    =
-      {
-        \tl_set:Nn \l__tag_mc_artifact_type_tl {}
-      },
-     artifact-type /      .code:n    =
-      {
-        \tl_set:Nn \l__tag_mc_artifact_type_tl {}
-      },
-  }
-
-\cs_new_protected:Npn \tag_mc_artifact_group_begin:n #1
- {
-  \tag_mc_begin:n {artifact=#1}
-  \tag_stop_group_begin:
- }
-
-\cs_new_protected:Npn \tag_mc_artifact_group_end:
- {
-  \tag_stop_group_end:
-  \tag_mc_end:
- }
-
-\int_new:N \g__tag_MCID_tmp_bypage_int
-
-
-\cs_new_protected:Npn \tag_mc_end_push:
- {
-   \__tag_mc_if_in:TF
-     {
-       \seq_gpush:Nx \g__tag_mc_stack_seq { \tag_get:n {mc_tag} }
-       \__tag_check_mc_pushed_popped:nn {pushed}{\tag_get:n {mc_tag}}
-       \tag_mc_end:
-     }
-     {
-       \__tag_check_mc_pushed_popped:nn {pushed}{-1}
-       \seq_gpush:Nn \g__tag_mc_stack_seq{ -1  }
-     }
- }
-\cs_new_protected:Npn \tag_mc_begin_pop:n #1
- {
-   \seq_gpop:NNTF \g__tag_mc_stack_seq \l__tag_tmpa_tl
-     {
-       \tl_if_eq:NnTF \l__tag_tmpa_tl {-1}
-         {
-           \__tag_check_mc_pushed_popped:nn {popped}{-1}
-         }
-         {
-           \__tag_check_mc_pushed_popped:nn {popped}{\l__tag_tmpa_tl}
-           \tag_mc_begin:n {tag=\l__tag_tmpa_tl,#1}
-         }
-     }
-     { \__tag_check_mc_pushed_popped:nn {popped}{empty~stack,~nothing} } %message?
- }
-
-%% 
-%%
-%% End of file `tagpdf-mc-code-shared.sty'.

Deleted: trunk/Master/texmf-dist/tex/latex/tagpdf/tagpdf-pdftex.def
===================================================================
--- trunk/Master/texmf-dist/tex/latex/tagpdf/tagpdf-pdftex.def	2021-06-30 20:41:50 UTC (rev 59768)
+++ trunk/Master/texmf-dist/tex/latex/tagpdf/tagpdf-pdftex.def	2021-06-30 21:14:14 UTC (rev 59769)
@@ -1,47 +0,0 @@
-%%
-%% This is file `tagpdf-pdftex.def',
-%% generated with the docstrip utility.
-%%
-%% The original source files were:
-%%
-%% tagpdf-backend.dtx  (with options: `pdftex')
-%% 
-%% Copyright (C) 2019 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.
-%% 
-%% File: tagpdf-backend.dtx
-\ProvidesExplFile {tagpdf-pdftex.def} {2021-06-14} {0.82}
-  {tagpdf~driver~for~pdftex}
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%%% driver (pdflatex) commands
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-\cs_set_eq:NN \__tag_prop_new:N     \prop_new:N
-
-\cs_set_eq:NN \__tag_seq_new:N      \seq_new:N
-
-\cs_set_eq:NN \__tag_prop_gput:Nnn  \prop_gput:Nnn
-
-\cs_set_eq:NN \__tag_seq_gput_right:Nn \seq_gput_right:Nn
-
-\cs_set_eq:NN \__tag_seq_item:cn    \seq_item:cn
-
-\cs_set_eq:NN \__tag_prop_item:cn   \prop_item:cn
-
-\cs_set_eq:NN \__tag_seq_show:N     \seq_show:N
-
-\cs_set_eq:NN \__tag_prop_show:N    \prop_show:N
-
-%% 
-%%
-%% End of file `tagpdf-pdftex.def'.

Deleted: trunk/Master/texmf-dist/tex/latex/tagpdf/tagpdf-roles-code.sty
===================================================================
--- trunk/Master/texmf-dist/tex/latex/tagpdf/tagpdf-roles-code.sty	2021-06-30 20:41:50 UTC (rev 59768)
+++ trunk/Master/texmf-dist/tex/latex/tagpdf/tagpdf-roles-code.sty	2021-06-30 21:14:14 UTC (rev 59769)
@@ -1,510 +0,0 @@
-%%
-%% This is file `tagpdf-roles-code.sty',
-%% generated with the docstrip utility.
-%%
-%% The original source files were:
-%%
-%% tagpdf-roles.dtx  (with options: `roles')
-%% 
-%% Copyright (C) 2019 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.
-%% 
-%% File: tagpdf-roles.dtx
-\ProvidesExplPackage {tagpdf-roles-code} {2021-06-14} {0.82}
- {part of tagpdf - code related to roles and structure names}
-\__tag_seq_new:N  \g__tag_role_tags_seq  %to get names (type/NS) from numbers
-\__tag_prop_new:N \g__tag_role_tags_prop %to get numbers  from names (type/NS)
-\prop_new:N    \g__tag_role_tags_NS_prop %to namespace info
-\prop_new:N \g__tag_role_NS_prop % collect namespaces
-\cs_new_protected:Npn \__tag_role_NS_new:nnn #1 #2 #3
-  { \msg_redirect_name:nnn { pdfdict } { empty-value } { none }
-    \pdf_object_new:nn {tag/NS/#1}{dict}
-    \pdfdict_new:n     {g__tag_role/Namespace_#1_dict}
-    \pdf_object_new:nn {__tag/RoleMapNS/#1}{dict}
-    \pdfdict_new:n     {g__tag_role/RoleMapNS_#1_dict}
-    \pdfdict_gput:nnn
-      {g__tag_role/Namespace_#1_dict}
-      {Type}
-      {/Namespace}
-    \pdf_string_from_unicode:nnN{utf8/string}{#2}\l_tmpa_str
-    \pdfdict_gput:nnx
-      {g__tag_role/Namespace_#1_dict}
-      {NS}
-      {\l_tmpa_str}
-    %RoleMapNS is added in tree
-    \pdfdict_gput:nnx{g__tag_role/Namespace_#1_dict}
-      {Schema}{#3}
-    \prop_gput:Nnx \g__tag_role_NS_prop {#1}{\pdf_object_ref:n{tag/NS/#1}~}
-    \msg_redirect_name:nnn { pdfdict } { empty-value } { warning }
-  }
-\str_const:Nx \c__tag_role_userNS_id_str
-  { data:,
-    \int_to_Hex:n{\int_rand:n {65535}}
-    \int_to_Hex:n{\int_rand:n {65535}}
-    -
-    \int_to_Hex:n{\int_rand:n {65535}}
-    -
-    \int_to_Hex:n{\int_rand:n {65535}}
-    -
-    \int_to_Hex:n{\int_rand:n {65535}}
-    -
-    \int_to_Hex:n{\int_rand:n {16777215}}
-    \int_to_Hex:n{\int_rand:n {16777215}}
-  }
-\pdf_version_compare:NnT > {1.9}
-  {
-    \__tag_role_NS_new:nnn {pdf}   {http://iso.org/pdf/ssn}{}
-    \__tag_role_NS_new:nnn {pdf2}  {http://iso.org/pdf2/ssn}{}
-    \__tag_role_NS_new:nnn {mathml}{http://www.w3.org/1998/Math/MathML}{}
-    \exp_args:Nnx
-    \__tag_role_NS_new:nnn {user}{\c__tag_role_userNS_id_str}{}
-  }
-\clist_const:Nn \c__tag_role_sttags_pdf_pdfII_clist
-  {
-    Document,   %A complete document. This is the root element of any structure tree containing
-                %multiple parts or multiple articles.
-    Part,       %A large-scale division of a document.
-    Sect,       %A container for grouping related content elements.
-    Div,        %A generic block-level element or group of elements
-    Caption,    %A brief portion of text describing a table or figure.
-    Index,
-    NonStruct,  %probably not needed
-    H,
-    H1,
-    H2,
-    H3,
-    H4,
-    H5,
-    H6,
-    P,
-    L,           %list
-    LI,          %list item (around label and list item body)
-    Lbl,         %list label
-    LBody,       %list item body
-    Table,
-    TR,          %table row
-    TH,          %table header cell
-    TD,          %table data cell
-    THead,       %table header (n rows)
-    TBody,       %table rows
-    TFoot,       %table footer
-    Span,        %generic inline marker
-    Link,        %
-    Annot,
-    Figure,
-    Formula,
-    Form,
-    % ruby warichu etc ..
-    Ruby,
-    RB,
-    RT,
-    Warichu,
-    WT,
-    WP,
-    Artifact % only MC-tag ?...
-  }
-
-\clist_const:Nn \c__tag_role_sttags_only_pdf_clist
- {
-   Art,%A relatively self-contained body of text constituting a single narrative or exposition
-   BlockQuote, %A portion of text consisting of one or more paragraphs attributed to someone other
-               %than the author of the  surrounding text.
-   TOC,        %A list made up of table of contents item entries (structure tag TOCI; see below)
-                %and/or other nested table of contents entries
-   TOCI,       %An individual member of a table of contents. This entry's children can be any of
-               %the following structure  tags:
-               %Lbl,Reference,NonStruct,P,TOC
-   Index,
-   Private,
-   Quote,       %inline quote
-   Note,        %footnote, endnote. Lbl can be child
-   Reference,   %A citation to content elsewhere in the document.
-   BibEntry,    %bibentry
-   Code
- }
-
-\clist_const:Nn \c__tag_role_sttags_only_pdfII_clist
- {
-   DocumentFragment
-   ,Aside
-   ,H7
-   ,H8
-   ,H9
-   ,H10
-   ,Title
-   ,FENote
-   ,Sub
-   ,Em
-   ,Strong
-   ,Artifact
- }
-
-\clist_const:Nn \c__tag_role_sttags_mathml_clist
- {
-   abs
-   ,and
-   ,annotation
-   ,apply
-   ,approx
-   ,arccos
-   ,arccosh
-   ,arccot
-   ,arccoth
-   ,arccsc
-   ,arccsch
-   ,arcsec
-   ,arcsech
-   ,arcsin
-   ,arcsinh
-   ,arctan
-   ,arctanh
-   ,arg
-   ,bind
-   ,bvar
-   ,card
-   ,cartesianproduct
-   ,cbytes
-   ,ceiling
-   ,cerror
-   ,ci
-   ,cn
-   ,codomain
-   ,complexes
-   ,compose
-   ,condition
-   ,conjugate
-   ,cos
-   ,cosh
-   ,cot
-   ,coth
-   ,cs
-   ,csc
-   ,csch
-   ,csymbol
-   ,curl
-   ,declare
-   ,degree
-   ,determinant
-   ,diff
-   ,divergence
-   ,divide
-   ,domain
-   ,domainofapplication
-   ,emptyset
-   ,eq
-   ,equivalent
-   ,eulergamma
-   ,exists
-   ,exp
-   ,exponentiale
-   ,factorial
-   ,factorof
-   ,false
-   ,floor
-   ,fn
-   ,forall
-   ,gcd
-   ,geq
-   ,grad
-   ,gt
-   ,ident
-   ,image
-   ,imaginary
-   ,imaginaryi
-   ,implies
-   ,in
-   ,infinity
-   ,int
-   ,integers
-   ,intersect
-   ,interval
-   ,inverse
-   ,lambda
-   ,laplacian
-   ,lcm
-   ,leq
-   ,limit
-   ,ln
-   ,log
-   ,logbase
-   ,lowlimit
-   ,lt
-   ,maction
-   ,maligngroup
-   ,malignmark
-   ,math
-   ,matrix
-   ,matrixrow
-   ,max
-   ,mean
-   ,median
-   ,menclose
-   ,merror
-   ,mfenced
-   ,mfrac
-   ,mglyph
-   ,mi
-   ,min
-   ,minus
-   ,mlabeledtr
-   ,mlongdiv
-   ,mmultiscripts
-   ,mn
-   ,mo
-   ,mode
-   ,moment
-   ,momentabout
-   ,mover
-   ,mpadded
-   ,mphantom
-   ,mprescripts
-   ,mroot
-   ,mrow
-   ,ms
-   ,mscarries
-   ,mscarry
-   ,msgroup
-   ,msline
-   ,mspace
-   ,msqrt
-   ,msrow
-   ,mstack
-   ,mstyle
-   ,msub
-   ,msubsup
-   ,msup
-   ,mtable
-   ,mtd
-   ,mtext
-   ,mtr
-   ,munder
-   ,munderover
-   ,naturalnumbers
-   ,neq
-   ,none
-   ,not
-   ,notanumber
-   ,notin
-   ,notprsubset
-   ,notsubset
-   ,or
-   ,otherwise
-   ,outerproduct
-   ,partialdiff
-   ,pi
-   ,piece
-   ,piecewise
-   ,plus
-   ,power
-   ,primes
-   ,product
-   ,prsubset
-   ,quotient
-   ,rationals
-   ,real
-   ,reals
-   ,reln
-   ,rem
-   ,root
-   ,scalarproduct
-   ,sdev
-   ,sec
-   ,sech
-   ,selector
-   ,semantics
-   ,sep
-   ,set
-   ,setdiff
-   ,share
-   ,sin
-   ,sinh
-   ,subset
-   ,sum
-   ,tan
-   ,tanh
-   ,tendsto
-   ,times
-   ,transpose
-   ,true
-   ,union
-   ,uplimit
-   ,variance
-   ,vector
-   ,vectorproduct
-   ,xor
- }
-
-\prop_const_from_keyval:Nn \c__tag_role_sttags_pdfII_to_pdf_prop
-  {
-    DocumentFragment = Art,
-    Aside = Note,
-    Title = H1,
-    Sub   = Span,
-    H7    = H6 ,
-    H8    = H6 ,
-    H9    = H6 ,
-    H10   = H6,
-    FENote= Note,
-    Em    = Span,
-    Strong= Span,
-  }
-
-\clist_map_inline:Nn \c__tag_role_sttags_pdf_pdfII_clist
-  {
-    \__tag_seq_gput_right:Nn \g__tag_role_tags_seq { #1 }
-    \prop_gput:Nnn \g__tag_role_tags_NS_prop    { #1 }{ pdf2 }
-  }
-\clist_map_inline:Nn \c__tag_role_sttags_only_pdf_clist
-  {
-    \__tag_seq_gput_right:Nn \g__tag_role_tags_seq { #1 }
-    \prop_gput:Nnn \g__tag_role_tags_NS_prop    { #1 }{ pdf }
-  }
-\clist_map_inline:Nn \c__tag_role_sttags_only_pdfII_clist
-  {
-    \__tag_seq_gput_right:Nn \g__tag_role_tags_seq { #1 }
-    \prop_gput:Nnn \g__tag_role_tags_NS_prop    { #1 }{ pdf2 }
-  }
-\pdf_version_compare:NnT > {1.9}
-  {
-     \clist_map_inline:Nn \c__tag_role_sttags_mathml_clist
-       {
-         \__tag_seq_gput_right:Nn \g__tag_role_tags_seq { #1 }
-         \prop_gput:Nnn \g__tag_role_tags_NS_prop    { #1 }{ mathml }
-       }
-  }
-
-\int_step_inline:nnnn { 1 }{ 1 }{ \seq_count:N \g__tag_role_tags_seq }
-  {
-    \__tag_prop_gput:Nxn \g__tag_role_tags_prop
-      {
-        \seq_item:Nn \g__tag_role_tags_seq  { #1 }
-      }
-      { #1 }
-  }
-\pdfdict_new:n {g__tag_role/RoleMap_dict}
-\cs_new_protected:Nn \__tag_role_add_tag:nn %(new) name, reference to old
-  {
-    \prop_if_in:NnF \g__tag_role_tags_prop {#1}
-      {
-         \msg_info:nnn { tag }{new-tag}{#1}
-         \__tag_seq_gput_right:Nn \g__tag_role_tags_seq { #1 }
-         \__tag_prop_gput:Nnx \g__tag_role_tags_prop    { #1 }
-           {
-             \seq_count:N \g__tag_role_tags_seq
-           }
-         \prop_gput:Nnn \g__tag_role_tags_NS_prop    { #1 }{ user }
-      }
-    %\__tag_check_add_tag_role:nn {#1}{#2} %%!TODO
-    \tl_if_empty:nF { #2 }
-      {
-        \pdfdict_gput:nnx {g__tag_role/RoleMap_dict}
-          {#1}
-          {\pdf_name_from_unicode_e:n{#2}}
-      }
-  }
-\cs_generate_variant:Nn \__tag_role_add_tag:nn {VV}
-
-\pdf_version_compare:NnT < {2.0}
-  {
-     \prop_map_inline:Nn \c__tag_role_sttags_pdfII_to_pdf_prop
-       {
-         \__tag_role_add_tag:nn {#1}{#2}
-       }
-  }
-
-\cs_new_protected:Nn \__tag_role_add_tag:nnnn %tag/namespace/role/namespace
-  {
-    \msg_info:nnn { tag }{new-tag}{#1}
-    \__tag_seq_gput_right:Nn \g__tag_role_tags_seq { #1 }
-    \__tag_prop_gput:Nnx \g__tag_role_tags_prop    { #1 }
-       {
-         \seq_count:N \g__tag_role_tags_seq
-       }
-    \prop_gput:Nnn \g__tag_role_tags_NS_prop    { #1 }{ #2 }
-    %\__tag_check_add_tag_role:nn {#1}{#3} %TODO
-    \pdfdict_gput:nnx {g__tag_role/RoleMapNS_#2_dict}{#1}
-       {
-         [
-           \pdf_name_from_unicode_e:n{#3}
-           \c_space_tl
-           \pdf_object_ref:n {tag/NS/#4}
-         ]
-       }
-   }
-\cs_generate_variant:Nn \__tag_role_add_tag:nnnn {VVVV}
-
-\tl_new:N \l__tag_role_tag_tmpa_tl
-\tl_new:N \l__tag_role_tag_namespace_tmpa_tl
-\tl_new:N \l__tag_role_role_tmpa_tl
-\tl_new:N \l__tag_role_role_namespace_tmpa_tl
-
-\keys_define:nn { __tag / tag-role }
-  {
-    ,tag .tl_set:N = \l__tag_role_tag_tmpa_tl
-    ,tag-namespace  .tl_set:N = \l__tag_role_tag_namespace_tmpa_tl
-    ,role .tl_set:N = \l__tag_role_role_tmpa_tl
-    ,role-namespace .tl_set:N = \l__tag_role_role_namespace_tmpa_tl
-  }
-
-\keys_define:nn { __tag / setup }
-  {
-    add-new-tag .code:n =
-     {
-       \keys_set_known:nnnN
-         {__tag/tag-role}
-         {
-           tag-namespace=user,
-           role-namespace=, %so that we can test for it.
-          #1
-         }{__tag/tag-role}\l_tmpa_tl
-       \tl_if_empty:NF \l_tmpa_tl
-         {
-           \exp_args:NNno \seq_set_split:Nnn \l_tmpa_seq { / } {\l_tmpa_tl/}
-           \tl_set:Nx \l__tag_role_tag_tmpa_tl  { \seq_item:Nn \l_tmpa_seq {1} }
-           \tl_set:Nx \l__tag_role_role_tmpa_tl { \seq_item:Nn \l_tmpa_seq {2} }
-         }
-      \tl_if_empty:NT \l__tag_role_role_namespace_tmpa_tl
-         {
-           \prop_get:NVNTF
-             \g__tag_role_tags_NS_prop
-             \l__tag_role_role_tmpa_tl
-             \l__tag_role_role_namespace_tmpa_tl
-             {
-                \prop_if_in:NVF\g__tag_role_NS_prop \l__tag_role_role_namespace_tmpa_tl
-                 {
-                   \tl_set:Nn \l__tag_role_role_namespace_tmpa_tl {user}
-                 }
-             }
-             {
-               \tl_set:Nn \l__tag_role_role_namespace_tmpa_tl {user}
-             }
-         }
-      \pdf_version_compare:NnTF < {2.0}
-       {
-        %TODO add check for emptyness?
-          \__tag_role_add_tag:VV
-              \l__tag_role_tag_tmpa_tl
-              \l__tag_role_role_tmpa_tl
-       }
-       {
-         \__tag_role_add_tag:VVVV
-           \l__tag_role_tag_tmpa_tl
-           \l__tag_role_tag_namespace_tmpa_tl
-           \l__tag_role_role_tmpa_tl
-           \l__tag_role_role_namespace_tmpa_tl
-       }
-    }
-  }
-
-%% 
-%%
-%% End of file `tagpdf-roles-code.sty'.

Deleted: trunk/Master/texmf-dist/tex/latex/tagpdf/tagpdf-space-code.sty
===================================================================
--- trunk/Master/texmf-dist/tex/latex/tagpdf/tagpdf-space-code.sty	2021-06-30 20:41:50 UTC (rev 59768)
+++ trunk/Master/texmf-dist/tex/latex/tagpdf/tagpdf-space-code.sty	2021-06-30 21:14:14 UTC (rev 59769)
@@ -1,79 +0,0 @@
-%%
-%% This is file `tagpdf-space-code.sty',
-%% generated with the docstrip utility.
-%%
-%% The original source files were:
-%%
-%% tagpdf-space.dtx  (with options: `space')
-%% 
-%% Copyright (C) 2019 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.
-%% 
-%% File: tagpdf-space.dtx
-\ProvidesExplPackage {tagpdf-space-code} {2021-06-14} {0.82}
- {part of tagpdf - code related to real space chars}
-
-\sys_if_engine_pdftex:T
-  {
-    \pdfglyphtounicode{space}{0020}
-    \keys_define:nn { __tag / setup }
-      {
-        interwordspace .choices:nn = { true, on }  { \pdfinterwordspaceon },
-        interwordspace .choices:nn = { false, off }{ \pdfinterwordspaceon },
-        show-spaces .bool_set:N = \l__tag_showspaces_bool
-      }
-  }
-
-\sys_if_engine_luatex:T
-  {
-    \keys_define:nn { __tag / setup }
-      {
-        interwordspace .choices:nn =
-                                 { true, on }
-                                 { \directlua{ltx.__tag.func.markspaceon()} },
-        interwordspace .choices:nn =
-                                 { false, off }
-                                 {\directlua{ltx.__tag.func.markspaceoff()} },
-        show-spaces      .choice:,
-        show-spaces  / true  .code:n =
-                                 {\directlua{ltx.__tag.trace.showspaces=true}},
-        show-spaces  / false .code:n =
-                                 {\directlua{ltx.__tag.trace.showspaces=nil}},
-        show-spaces .default:n = true
-      }
-
-    \cs_new_protected:Nn \__tag_fakespace:
-      {
-        \group_begin:
-        \setattribute\g__tag_interwordspace_attr{1}
-        \setattribute\g__tag_interwordfont_attr
-          {
-            \directlua{tex.print(\the\catcodetable at latex, font.current())}
-          }
-        \skip_horizontal:n{\c_zero_skip}
-        \group_end:
-      }
-  }
-
-\sys_if_engine_xetex:T
-  {
-    \keys_define:nn { __tag / setup }
-      {
-        interwordspace .choices:nn = { true, on }  { \msg_warning:nnn {tag}{sys-no-interwordspace}{xetex}  },
-        interwordspace .choices:nn = { false, off }{ \msg_warning:nnn {tag}{sys-no-interwordspace}{xetex}  },
-        show-spaces .bool_set:N = \l__tag_showspaces_bool
-      }
-  }
-
-%% 
-%%
-%% End of file `tagpdf-space-code.sty'.

Deleted: trunk/Master/texmf-dist/tex/latex/tagpdf/tagpdf-struct-code.sty
===================================================================
--- trunk/Master/texmf-dist/tex/latex/tagpdf/tagpdf-struct-code.sty	2021-06-30 20:41:50 UTC (rev 59768)
+++ trunk/Master/texmf-dist/tex/latex/tagpdf/tagpdf-struct-code.sty	2021-06-30 21:14:14 UTC (rev 59769)
@@ -1,653 +0,0 @@
-%%
-%% This is file `tagpdf-struct-code.sty',
-%% generated with the docstrip utility.
-%%
-%% The original source files were:
-%%
-%% tagpdf-struct.dtx  (with options: `struct')
-%% 
-%% Copyright (C) 2019 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.
-%% 
-%% File: tagpdf-struct.dtx
-\ProvidesExplPackage {tagpdf-struct-code} {2021-06-14} {0.82}
- {part of tagpdf - code related to storing structure}
-\newcounter  { g__tag_struct_abs_int }
-\int_gzero:N \c at g__tag_struct_abs_int
-\__tag_seq_new:N  \g__tag_struct_objR_seq
-\seq_new:N    \g__tag_struct_stack_seq
-\seq_gpush:Nn \g__tag_struct_stack_seq {0}
-\seq_new:N    \g__tag_struct_tag_stack_seq
-\seq_gpush:Nn \g__tag_struct_tag_stack_seq {Root}
-\tl_new:N     \l__tag_struct_stack_parent_tmp_tl
-\tl_new:N     \g__tag_struct_stack_current_tl
-
-\seq_const_from_clist:Nn \c__tag_struct_StructTreeRoot_entries_seq
-  {%p. 857/858
-    Type,              % always /StructTreeRoot
-    K,                 % kid, dictionary or array of dictionaries
-    IDTree,            % currently unused
-    ParentTree,        % required,obj ref to the parent tree
-    ParentTreeNextKey, %optional
-    RoleMap,
-    ClassMap,
-    Namespaces
-  }
-
-\seq_const_from_clist:Nn \c__tag_struct_StructElem_entries_seq
-  {%p 858 f
-    Type,              %always /StructElem
-    S,                 %tag/type
-    P,                 %parent
-    ID,                %optional
-    Ref,               %optional, pdf 2.0 Use?
-    Pg,                %obj num of starting page, optional
-    K,                 %kids
-    A,                 %attributes, probably unused
-    C,                 %class ""
-    %R,
-    T,                 %title, value in () or <>
-    Lang,              %language
-    Alt,               % value in () or <>
-    E,                 %abreviation
-    ActualText,
-    AF,                 %pdf 2.0, array of dict, associated files
-    NS,                 %pdf 2.0, dict, namespace
-    PhoneticAlphabet,   %pdf 2.0
-    Phoneme             %pdf 2.0
-  }
-
-
-\cs_new:Nn \__tag_struct_output_prop_aux:nn %#1 num, #2 key
-  {
-    \prop_if_in:cnT
-      { g__tag_struct_#1_prop }
-      { #2 }
-      {
-        \c_space_tl/#2~ \prop_item:cn{ g__tag_struct_#1_prop } { #2 }
-      }
-  }
-
-\cs_new:Nn \__tag_new_output_prop_handler:n
-  {
-    \cs_new:cn { __tag_struct_output_prop_#1:n }
-      {
-        \__tag_struct_output_prop_aux:nn {#1}{##1}
-      }
-  }
-
-\__tag_prop_new:c { g__tag_struct_0_prop }
-\__tag_new_output_prop_handler:n {0}
-\tl_gset:Nn \g__tag_struct_stack_current_tl {0}
-
-\__tag_seq_new:c  { g__tag_struct_kids_0_seq }
-
-\__tag_prop_gput:cnx
-  { g__tag_struct_0_prop }
-  { objref}
-  { \pdf_object_ref:n { __tag/struct/0 } }
-
-\__tag_prop_gput:cnn
-  { g__tag_struct_0_prop }
-  { Type }
-  { /StructTreeRoot }
-
-\__tag_prop_gput:cnx
-  { g__tag_struct_0_prop }
-  { ParentTree }
-  { \pdf_object_ref:n { __tag/tree/parenttree } }
-
-\__tag_prop_gput:cnx
-  { g__tag_struct_0_prop }
-  { RoleMap }
-  { \pdf_object_ref:n { __tag/tree/rolemap } }
-
-\__tag_prop_gput:cnn
-  { g__tag_struct_0_prop }
-  { entries }
-  { StructTreeRoot }
-
-\__tag_prop_gput:cnn
-  { g__tag_struct_0_prop }
-  { num }
-  { 0 }
-
-\__tag_prop_gput:cnx
-  { g__tag_struct_0_prop }
-  { Namespaces }
-  { \pdf_object_ref:n { __tag/tree/namespaces } }
-
-
-\cs_new:Nn \__tag_struct_kid_mc_gput_right:nn %#1 structure num, #2 MCID absnum%
-  {
-    %\__tag_store_pdfpageref:Nn \l_tmpa_tl { \__tag_ref_value:enn{mcid-#2}{tagabspage}{1} }
-    \__tag_seq_gput_right:cx
-      { g__tag_struct_kids_#1_seq }
-      {
-        <<
-        /Type \c_space_tl /MCR \c_space_tl
-        /Pg %\c_space_tl \l_tmpa_tl \c_space_tl 0 \c_space_tl R \c_space_tl
-          \c_space_tl
-          \pdf_pageobject_ref:n { \__tag_ref_value:enn{mcid-#2}{tagabspage}{1} }
-        /MCID \c_space_tl \__tag_ref_value:enn{mcid-#2}{tagmcid}{1}
-        >>
-      }
-  }
-
-\cs_new:Nn\__tag_struct_kid_struct_gput_right:nn %#1 num of parent struct, #2 kid struct
-  {
-    \__tag_seq_gput_right:cx
-      { g__tag_struct_kids_#1_seq }
-      {
-        \prop_item:cn
-          { g__tag_struct_#2_prop }
-          { objref }
-      }
- }
-
-\cs_new:Nn\__tag_struct_kid_OBJR_gput_right:nn %#1 num of parent struct, #2 obj reference
-  {
-    \pdf_object_unnamed_write:nx
-      { dict }
-      {
-        /Type \c_space_tl /OBJR \c_space_tl
-        /Obj~#2
-      }
-    \__tag_seq_gput_right:cx
-      { g__tag_struct_kids_#1_seq }
-      {
-        \pdf_object_ref_last:
-      }
-  }
-
-\cs_generate_variant:Nn\__tag_struct_kid_OBJR_gput_right:nn { nx }
-
-\cs_new:Nn\__tag_struct_exchange_kid_command:N %N= seq
-  {
-    \seq_gpop_left:NN #1 \l_tmpa_tl
-    \regex_replace_once:nnN
-      { \c{\__tag_mc_insert_mcid_kids:n} }
-      { \c{\__tag_mc_insert_mcid_single_kids:n} }
-      \l_tmpa_tl
-   \seq_gput_left:NV #1 \l_tmpa_tl
-  }
-
-\cs_generate_variant:Nn\__tag_struct_exchange_kid_command:N { c }
-
-\cs_new:Nn \__tag_struct_fill_kid_key:n %#1 is the struct num
-  {
-    \int_case:nnF
-      {
-        \seq_count:c
-          {
-            g__tag_struct_kids_\prop_item:cn{ g__tag_struct_#1_prop }{num}_seq
-          }
-      }
-      {
-        { 0 }
-         { } %no kids, do nothing
-        { 1 } % 1 kid, insert
-         {
-           % in this case we need a special command in
-           %luamode to get the array right. See issue #13
-           \bool_if:NT\g__tag_mode_lua_bool
-             {
-               \__tag_struct_exchange_kid_command:c
-                 {g__tag_struct_kids_\prop_item:cn{ g__tag_struct_#1_prop }{num}_seq}
-             }
-           \__tag_prop_gput:cnx { g__tag_struct_#1_prop } {K}
-             {
-               \seq_item:cn
-                 {
-                   g__tag_struct_kids_\prop_item:cn{ g__tag_struct_#1_prop }{num}_seq
-                 }
-                 {1}
-             }
-         } %
-      }
-      { %many kids, use an array
-        \__tag_prop_gput:cnx { g__tag_struct_#1_prop } {K}
-          {
-            [
-              \seq_use:cn
-                {
-                  g__tag_struct_kids_\prop_item:cn{ g__tag_struct_#1_prop }{num}_seq
-                }
-                {
-                  \c_space_tl
-                }
-            ]
-          }
-      }
-  }
-
-
-\tl_new:N \l__tag_struct_dict_content_tl
-
-\cs_new:Nn \__tag_struct_get_dict_content:n
-  {
-    %\tl_set:Nn \l__tag_struct_dict_content_tl {<<}
-    \tl_clear:N \l__tag_struct_dict_content_tl
-    \seq_map_inline:cn
-      {
-        c__tag_struct_\prop_item:cn{ g__tag_struct_#1_prop }{entries}_entries_seq
-      }
-      {
-        \tl_put_right:Nx
-          \l__tag_struct_dict_content_tl
-          {
-             \prop_if_in:cnT
-               { g__tag_struct_#1_prop }
-               { ##1 }
-               {
-                 \c_space_tl/##1~\prop_item:cn{ g__tag_struct_#1_prop } { ##1 }
-               }
-          }
-      }
-    %\tl_put_right:Nn \l__tag_struct_dict_content_tl { >> }
-  }
-
-\cs_new:Nn \__tag_struct_write_obj:n
-  {
-    \prop_if_in:cnTF
-      { g__tag_struct_#1_prop }
-      { objref }
-      {
-        \__tag_struct_fill_kid_key:n { #1 }
-        %\prop_show:c { g__tag_struct_#1_prop }
-        \__tag_struct_get_dict_content:n { #1 }
-        \exp_args:Nx
-          \pdf_object_write:nx
-            { __tag/struct/#1 }
-            {
-              \l__tag_struct_dict_content_tl
-            }
-      }
-      {
-        \msg_error:nnn { tag } { struct-no-objnum } { #1}
-      }
-  }
-
-\cs_new:Nn \__tag_get_data_struct_tag:
-  {
-    \exp_args:Ne
-    \tl_tail:n
-     {
-       \prop_item:cn {g__tag_struct_\g__tag_struct_stack_current_tl _prop}{S}
-     }
-  }
-
-\tl_new:N \g__tag_struct_tag_tl
-\tl_new:N \g__tag_struct_tag_NS_tl
-\cs_generate_variant:Nn \seq_set_split:Nnn{Nne}
-\keys_define:nn { __tag / struct }
-  {
-    label .tl_set:N      = \l__tag_struct_key_label_tl,
-    stash .bool_set:N    = \l__tag_struct_elem_stash_bool,
-    tag   .code:n        = % S property
-      {%%????????? \pdfescapename?? slash/not slash is here the question ...
-        \seq_set_split:Nne \l_tmpa_seq { / } {#1/\prop_item:Nn\g__tag_role_tags_NS_prop{#1}}
-        \tl_gset:Nx \g__tag_struct_tag_tl    { \seq_item:Nn\l_tmpa_seq {1} }
-        \tl_gset:Nx \g__tag_struct_tag_NS_tl { \seq_item:Nn\l_tmpa_seq {2} }
-        \bool_if:NT \g__tag_check_tags_bool
-          {
-            \__tag_check_structure_tag:N \g__tag_struct_tag_tl
-          }
-       \__tag_prop_gput:cnx
-         { g__tag_struct_\int_eval:n {\c at g__tag_struct_abs_int}_prop }
-         { S }
-         { \pdf_name_from_unicode_e:n{ \g__tag_struct_tag_tl} } %
-       \prop_get:NVNT \g__tag_role_NS_prop\g__tag_struct_tag_NS_tl\l__tag_tmpa_tl
-         {
-           \__tag_prop_gput:cnx
-            { g__tag_struct_\int_eval:n {\c at g__tag_struct_abs_int}_prop }
-            { NS }
-            { \l__tag_tmpa_tl } %
-         }
-      },
-    title .code:n        = % T property
-      {
-        \str_set_convert:Nnon
-          \l__tag_tmpa_str
-          { #1 }
-          { default }
-          { utf16/hex }
-        \__tag_prop_gput:cnx
-          { g__tag_struct_\int_eval:n {\c at g__tag_struct_abs_int}_prop }
-          { T }
-          { <\l__tag_tmpa_str> }
-      },
-    title-o .code:n        = % T property
-      {
-        \str_set_convert:Nnon
-          \l__tag_tmpa_str
-          { #1 }
-          { default }
-          { utf16/hex }
-        \__tag_prop_gput:cnx
-          { g__tag_struct_\int_eval:n {\c at g__tag_struct_abs_int}_prop }
-          { T }
-          { <\l__tag_tmpa_str> }
-      },
-    alttext .code:n      = % Alt property
-      {
-        \str_set_convert:Nnon
-          \l__tag_tmpa_str
-          { #1 }
-          { default }
-          { utf16/hex }
-        \__tag_prop_gput:cnx
-          { g__tag_struct_\int_eval:n {\c at g__tag_struct_abs_int}_prop }
-          { Alt }
-          { <\l__tag_tmpa_str> }
-      },
-    alttext-o .code:n      = % Alt property
-      {
-        \str_set_convert:Noon
-          \l__tag_tmpa_str
-          { #1 }
-          { default }
-          { utf16/hex }
-        \__tag_prop_gput:cnx
-          { g__tag_struct_\int_eval:n {\c at g__tag_struct_abs_int}_prop }
-          { Alt }
-          { <\l__tag_tmpa_str> }
-      },
-    actualtext .code:n  = % ActualText property
-      {
-        \str_set_convert:Nnon
-          \l__tag_tmpa_str
-          { #1 }
-          { default }
-          { utf16/hex }
-        \__tag_prop_gput:cnx
-          { g__tag_struct_\int_eval:n {\c at g__tag_struct_abs_int}_prop }
-          { ActualText }
-          { <\l__tag_tmpa_str>}
-      },
-    actualtext-o .code:n  = % ActualText property
-      {
-        \str_set_convert:Noon
-          \l__tag_tmpa_str
-          { #1 }
-          { default }
-          { utf16/hex }
-        \__tag_prop_gput:cnx
-          { g__tag_struct_\int_eval:n {\c at g__tag_struct_abs_int}_prop }
-          { ActualText }
-          { <\l__tag_tmpa_str>}
-      },
-    lang .code:n        = % Lang property
-      {
-        \__tag_prop_gput:cnx
-          { g__tag_struct_\int_eval:n {\c at g__tag_struct_abs_int}_prop }
-          { Lang }
-          { (#1) }
-      },
-    ref .code:n        = % Lang property
-      {
-        \tl_clear:N\l__tag_tmpa_tl
-        \clist_map_inline:nn {#1}
-          {
-            \tl_put_right:Nx \l__tag_tmpa_tl
-              {~\ref_value:nn{tagpdfstruct-##1}{tagstructobj} }
-          }
-        \__tag_prop_gput:cnx
-          { g__tag_struct_\int_eval:n {\c at g__tag_struct_abs_int}_prop }
-          { Ref }
-          { [\l__tag_tmpa_tl] }
-      },
-    E .code:n        = % E property
-      {
-        \str_set_convert:Nnon
-          \l__tag_tmpa_str
-          { #1 }
-          { default }
-          { utf16/hex }
-        \__tag_prop_gput:cnx
-          { g__tag_struct_\int_eval:n {\c at g__tag_struct_abs_int}_prop }
-          { E }
-          { <\l__tag_tmpa_str> }
-      },
-  }
-
-\keys_define:nn { __tag / struct }
- {
-    AF .code:n        = % T property
-      {
-        \pdf_object_if_exist:nTF {#1}
-          {
-            \__tag_prop_gput:cnx
-             { g__tag_struct_\int_eval:n {\c at g__tag_struct_abs_int}_prop }
-             { AF }
-             { \pdf_object_ref:n {#1} }
-          }
-          {
-
-          }
-      },
-   ,AFinline .code:n =
-     {
-       \group_begin:
-       \exp_args:Ne
-       \pdf_object_if_exist:nF {__tag/fileobj\int_use:N\c at g__tag_struct_abs_int}
-        {
-          \pdffile_embed_stream:nxx
-            {#1}
-            {tag-AFfile\int_use:N\c at g__tag_struct_abs_int.txt}
-            {__tag/fileobj\int_use:N\c at g__tag_struct_abs_int}
-        }
-       \__tag_prop_gput:cnx
-         { g__tag_struct_\int_use:N\c at g__tag_struct_abs_int _prop }
-         { AF }
-         { \pdf_object_ref:e {__tag/fileobj\int_use:N\c at g__tag_struct_abs_int } }
-       \group_end:
-     }
-   ,AFinline-o .code:n =
-     {
-       \group_begin:
-       \exp_args:Ne
-       \pdf_object_if_exist:nF {__tag/fileobj\int_use:N\c at g__tag_struct_abs_int}
-        {
-          \pdffile_embed_stream:oxx
-            {#1}
-            {tag-AFfile\int_use:N\c at g__tag_struct_abs_int.txt}
-            {__tag/fileobj\int_use:N\c at g__tag_struct_abs_int}
-        }
-       \__tag_prop_gput:cnx
-         { g__tag_struct_\int_use:N\c at g__tag_struct_abs_int _prop }
-         { AF }
-         { \pdf_object_ref:e {__tag/fileobj\int_use:N\c at g__tag_struct_abs_int } }
-       \group_end:
-     }
- }
-
-\cs_new_protected:Nn \tag_struct_begin:n
-  {
-    \group_begin:
-    \int_gincr:N \c at g__tag_struct_abs_int
-    \__tag_prop_new:c  { g__tag_struct_\int_eval:n { \c at g__tag_struct_abs_int }_prop }
-    \__tag_new_output_prop_handler:n {\int_eval:n { \c at g__tag_struct_abs_int }}
-    \__tag_seq_new:c  { g__tag_struct_kids_\int_eval:n { \c at g__tag_struct_abs_int }_seq}
-    %\__tag_pdfreserveobjnum:N \l_tmpa_tl
-    \exp_args:Ne
-      \pdf_object_new:nn
-        { __tag/struct/\int_eval:n { \c at g__tag_struct_abs_int } }
-        { dict }
-    \__tag_prop_gput:cnx
-      { g__tag_struct_\int_eval:n { \c at g__tag_struct_abs_int }_prop }
-      { objref}
-      {
-        \exp_args:Ne
-          \pdf_object_ref:n
-            {__tag/struct/\int_eval:n { \c at g__tag_struct_abs_int }}
-      }
-    \__tag_prop_gput:cnx
-      { g__tag_struct_\int_eval:n { \c at g__tag_struct_abs_int }_prop }
-      { num}
-      { \int_eval:n { \c at g__tag_struct_abs_int } }
-    \__tag_prop_gput:cno
-      { g__tag_struct_\int_eval:n { \c at g__tag_struct_abs_int }_prop }
-      { Type }
-      { /StructElem }
-    \__tag_prop_gput:cno
-      { g__tag_struct_\int_eval:n { \c at g__tag_struct_abs_int }_prop }
-      { entries }
-      { StructElem }
-    \keys_set:nn { __tag / struct} { #1 }
-    \__tag_check_structure_has_tag:n { \int_eval:n {\c at g__tag_struct_abs_int} }
-    \tl_if_empty:NF
-      \l__tag_struct_key_label_tl
-      {
-        \__tag_ref_label:en{tagpdfstruct-\l__tag_struct_key_label_tl}{struct}
-      }
-    %get the potential parent from the stack:
-    \seq_get:NNF
-      \g__tag_struct_stack_seq
-      \l__tag_struct_stack_parent_tmp_tl
-      {
-        \msg_error:nn { tag } { struct-faulty-nesting }
-      }
-    \seq_gpush:NV \g__tag_struct_stack_seq        \c at g__tag_struct_abs_int
-    \seq_gpush:NV \g__tag_struct_tag_stack_seq    \g__tag_struct_tag_tl
-    \tl_gset:NV   \g__tag_struct_stack_current_tl \c at g__tag_struct_abs_int
-    %\seq_show:N   \g__tag_struct_stack_seq
-    \bool_if:NF
-      \l__tag_struct_elem_stash_bool
-      {%set the  parent
-        \__tag_prop_gput:cnx
-          { g__tag_struct_\int_eval:n {\c at g__tag_struct_abs_int}_prop }
-          { P }
-          {
-            \prop_item:cn
-              { g__tag_struct_\l__tag_struct_stack_parent_tmp_tl _prop}
-              { objref }
-          }
-        %record this structure as kid:
-        %\tl_show:N \g__tag_struct_stack_current_tl
-        %\tl_show:N \l__tag_struct_stack_parent_tmp_tl
-        \__tag_struct_kid_struct_gput_right:nn
-          { \l__tag_struct_stack_parent_tmp_tl }
-          { \g__tag_struct_stack_current_tl }
-        %\prop_show:c { g__tag_struct_\g__tag_struct_stack_current_tl _prop }
-        %\seq_show:c {g__tag_struct_kids_\l__tag_struct_stack_parent_tmp_tl _seq}
-      }
-    %\prop_show:c { g__tag_struct_\g__tag_struct_stack_current_tl _prop }
-    %\seq_show:c {g__tag_struct_kids_\l__tag_struct_stack_parent_tmp_tl _seq}
-    \group_end:
-  }
-
-\cs_new_protected:Nn \tag_struct_end:
-  { %take the current structure num from the stack:
-    %the objects are written later, lua mode hasn't all needed info yet
-    %\seq_show:N \g__tag_struct_stack_seq
-    \seq_gpop:NN \g__tag_struct_tag_stack_seq \l_tmpa_tl
-    \seq_gpop:NNTF \g__tag_struct_stack_seq \l_tmpa_tl
-      {
-        \int_compare:nNnT {\l__tag_loglevel_int} > { 0 }
-          {
-            \__tag_check_info_closing_struct:o { \g__tag_struct_stack_current_tl }
-          }
-      }
-      { \__tag_check_no_open_struck: }
-    % get the previous one, shouldn't be empty as the root should be there
-    \seq_get:NNTF \g__tag_struct_stack_seq \l_tmpa_tl
-      {
-        \tl_gset:NV   \g__tag_struct_stack_current_tl \l_tmpa_tl
-      }
-      {
-        \__tag_check_no_open_struck:
-      }
-   \seq_get:NNT \g__tag_struct_tag_stack_seq \l_tmpa_tl
-      {
-        \tl_gset:NV \g__tag_struct_tag_tl \l_tmpa_tl
-      }
-  }
-
-\cs_new_protected:Nn \tag_struct_use:n %#1 is the label
-  {
-    \prop_if_exist:cTF
-      { g__tag_struct_\__tag_ref_value:enn{tagpdfstruct-#1}{tagstruct}{unknown}_prop } %??????????
-      {
-        \__tag_check_struct_used:n {#1}
-        %add the label structure as kid to the current structure (can be the root)
-        \__tag_struct_kid_struct_gput_right:nn
-          { \g__tag_struct_stack_current_tl }
-          { \__tag_ref_value:enn{tagpdfstruct-#1}{tagstruct}{0} }
-        %add the current structure to the labeled one as parents
-        \__tag_prop_gput:cnx
-          { g__tag_struct_\__tag_ref_value:enn{tagpdfstruct-#1}{tagstruct}{0}_prop }
-          { P }
-          {
-            \prop_item:cn
-              { g__tag_struct_\g__tag_struct_stack_current_tl _prop}
-              { objref }
-          }
-      }
-      {
-        \msg_warning:nnn{ tag }{struct-label-unknown}{#1}
-      }
-  }
-
-%%%% Code to tag annotations like links.
-%%%% this works for url, see exp-link.pdf.
-%%%% it must be checked for other links
-
-\cs_new_protected:Npn \__tag_struct_insert_annot:nn #1 #2 %#1 object reference to the annotation/xform
-                                                       %#2 structparent number
-  {
-    \bool_if:NT \g__tag_active_struct_bool
-      {
-        %get the number of the parent link structure:
-        \seq_get:NNF
-          \g__tag_struct_stack_seq
-          \l__tag_struct_stack_parent_tmp_tl
-          {
-            \msg_error:nn { tag } { struct-faulty-nesting }
-          }
-        %put the obj number of link annot in the kid entry:
-        \__tag_struct_kid_OBJR_gput_right:nx
-          {
-            \l__tag_struct_stack_parent_tmp_tl
-          }
-          {
-            #1 %
-          }
-        % add the parent obj number to the parent tree:
-        \exp_args:Nnx
-        \__tag_parenttree_add_objr:nn
-          {
-            #2
-          }
-          {
-            \prop_item:cn
-              { g__tag_struct_\l__tag_struct_stack_parent_tmp_tl _prop }
-              { objref }
-          }
-        % increase the int:
-        \stepcounter{ g__tag_parenttree_obj_int }
-      }
-  }
-
-\cs_new_protected:Npn \tag_struct_insert_annot:nn #1 #2 %#1 should be an object reference
-                                                        %#2 struct parent num
-  {
-     \__tag_struct_insert_annot:nn {#1}{#2}
-  }
-
-\cs_generate_variant:Nn \tag_struct_insert_annot:nn {xx}
-\cs_new:Npn \tag_struct_parent_int: {\int_use:c { c at g__tag_parenttree_obj_int }}
-
-
-%% 
-%%
-%% End of file `tagpdf-struct-code.sty'.

Deleted: trunk/Master/texmf-dist/tex/latex/tagpdf/tagpdf-tree-code.sty
===================================================================
--- trunk/Master/texmf-dist/tex/latex/tagpdf/tagpdf-tree-code.sty	2021-06-30 20:41:50 UTC (rev 59768)
+++ trunk/Master/texmf-dist/tex/latex/tagpdf/tagpdf-tree-code.sty	2021-06-30 21:14:14 UTC (rev 59769)
@@ -1,268 +0,0 @@
-%%
-%% This is file `tagpdf-tree-code.sty',
-%% generated with the docstrip utility.
-%%
-%% The original source files were:
-%%
-%% tagpdf-tree.dtx  (with options: `tree')
-%% 
-%% Copyright (C) 2019 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.
-%% 
-%% File: tagpdf-tree.dtx
-\ProvidesExplPackage {tagpdf-tree-code} {2021-06-14} {0.82}
- {part of tagpdf - code related to writing trees and dictionaries to the pdf}
-
-\hook_gput_code:nnn{begindocument}{tagpdf}
-  {
-    \bool_if:NT \g__tag_active_tree_bool
-      {
-        \sys_if_output_pdf:TF
-          {
-            \AddToHook{enddocument/end} { \tag_finish_structure: }
-          }
-          {
-            \AddToHook{shipout/lastpage} { \tag_finish_structure: }
-          }
-      }
-  }
-
-
-\pdf_object_new:nn { __tag/struct/0 }{ dict }
-
- %need to think about the best place ...
-\hook_gput_code:nnn{begindocument}{tagpdf}
-  {
-    \bool_if:NT \g__tag_active_struct_bool
-      {
-        \pdfmanagement_add:nnx
-          { Catalog }
-          { StructTreeRoot }
-          { \pdf_object_ref:n { __tag/struct/0 } }
-      }
-  }
-\cs_new_protected:Nn \__tag_tree_write_structtreeroot:
-  {
-    \__tag_struct_write_obj:n { 0 }
-  }
-
-\cs_new_protected:Nn \__tag_tree_write_structelements:
-  {
-    \int_step_inline:nnnn {1}{1}{\c at g__tag_struct_abs_int}
-      {
-        %\prop_show:c {g__tag_struct_##1_prop}
-        \__tag_struct_write_obj:n { ##1 } %write the object
-      }
-  }
-
-
-\pdf_object_new:nn { __tag/tree/parenttree }{ dict }
-
-\newcounter  { g__tag_parenttree_obj_int }
-\hook_gput_code:nnn{begindocument}{tagpdf}
-  {
-    \int_gset:Nn
-      \c at g__tag_parenttree_obj_int
-      { \__tag_ref_value_lastpage:nn{abspage}{100}  }
-  }
-
-
-\tl_new:N \g__tag_parenttree_objr_tl
-
-\cs_new_protected:Nn \__tag_parenttree_add_objr:nn %#1 Structparent number, #2 objref
-  {
-    \tl_gput_right:Nx \g__tag_parenttree_objr_tl
-      {
-        #1 \c_space_tl #2 ^^J
-      }
-  }
-
-\tl_new:N \l__tag_parenttree_content_tl
-
-\cs_new_protected:Nn \__tag_tree_fill_parenttree:
-  {
-    \int_step_inline:nnnn{1}{1}{\__tag_ref_value_lastpage:nn{abspage}{-1}} %not quite clear if labels are needed. See lua code
-      { %page ##1\par
-        \prop_clear:N \l_tmpa_prop
-        \int_step_inline:nnnn{1}{1}{\__tag_ref_value_lastpage:nn{tagmcabs}{-1}}
-          {
-            %mcid####1
-            \int_compare:nT%F
-              {\__tag_ref_value:enn{mcid-####1}{tagabspage}{-1}=##1} %mcid is on current page
-              {% yes\par
-                \prop_put:Nxx
-                  \l_tmpa_prop
-                  {\__tag_ref_value:enn{mcid-####1}{tagmcid}{-1}}
-                  {\prop_item:Nn \g__tag_mc_parenttree_prop {####1}}
-              }
-          }
-          %\prop_show:N \l_tmpa_prop
-        \tl_put_right:Nx\l__tag_parenttree_content_tl
-          {
-            \int_eval:n {##1-1}\c_space_tl
-            [\c_space_tl %]
-          }
-        \int_step_inline:nnnn
-          {0}
-          {1}
-          { \prop_map_function:NN \l_tmpa_prop\__tag_prop_count:nn -1 }
-          {
-            \prop_get:NnNTF \l_tmpa_prop {####1} \l_tmpb_tl
-              {% page#1:mcid##1:\l_tmpb_tl :content
-                \tl_put_right:Nx \l__tag_parenttree_content_tl
-                  {
-                    \prop_item:cn { g__tag_struct_\l_tmpb_tl _prop } {objref}
-                    \c_space_tl
-                  }
-                %\tl_show:N \l__tag_parenttree_content_tl
-              }
-              {
-                \msg_warning:nn { tag } {tree-mcid-index-wrong}
-              }
-          }
-        \tl_put_right:Nn
-          \l__tag_parenttree_content_tl
-          {%[
-            ]^^J
-          }
-      }
-  }
-
-\cs_new_protected:Nn \__tag_tree_lua_fill_parenttree:
-  {
-    \tl_set:Nn \l__tag_parenttree_content_tl
-      {
-        \directlua
-          {
-            ltx.__tag.func.output_parenttree
-              (
-                \int_use:N\g_shipout_readonly_int
-              )
-          }
-      }
-  }
-
-\cs_new_protected:Nn \__tag_tree_write_parenttree:
-  {
-    \bool_if:NTF \g__tag_mode_lua_bool
-      {
-        \__tag_tree_lua_fill_parenttree:
-      }
-      {
-        \__tag_tree_fill_parenttree:
-      }
-    \tl_put_right:NV \l__tag_parenttree_content_tl\g__tag_parenttree_objr_tl
-    \pdf_object_write:nx  { __tag/tree/parenttree }
-      {
-        /Nums\c_space_tl [\l__tag_parenttree_content_tl]
-      }
-  }
-
-
-\pdf_object_new:nn { __tag/tree/rolemap }{ dict }
-
-\cs_new_protected:Nn \__tag_tree_write_rolemap:
-  {
-    \pdf_object_write:nx  { __tag/tree/rolemap }
-      {
-        \pdfdict_use:n{g__tag_role/RoleMap_dict}
-      }
-  }
-
-
-\cs_new_protected:Nn \__tag_tree_write_classmap:
-  {
-    \tl_gclear:N \g__tag_attr_class_content_tl
-    \seq_gremove_duplicates:N \g__tag_attr_class_used_seq
-    \seq_set_map:NNn \l_tmpa_seq \g__tag_attr_class_used_seq
-      {
-        /##1\c_space_tl
-        <<
-          \prop_item:Nn
-            \g__tag_attr_entries_prop
-            {##1}
-        >>
-      }
-    \tl_gset:Nx \g__tag_attr_class_content_tl
-      {
-        \seq_use:Nn
-          \l_tmpa_seq
-          { \iow_newline: }
-      }
-    \tl_if_empty:NF
-      \g__tag_attr_class_content_tl
-      {
-        \pdf_object_new:nn { __tag/tree/classmap }{ dict }
-     %   \__tag_pdfreserveobjnum:N \l_tmpa_tl
-     %   \tl_const:Nx \c__tag_tree_obj_classmap_tl { \l_tmpa_tl }
-        \pdf_object_write:nx
-          { __tag/tree/classmap }
-          { \g__tag_attr_class_content_tl }
-        \__tag_prop_gput:cnx
-          { g__tag_struct_0_prop }
-          { ClassMap }
-          { \pdf_object_ref:n { __tag/tree/classmap }  }
-      }
-  }
-
-\pdf_object_new:nn{ __tag/tree/namespaces }{array}
-\cs_new_protected:Npn \__tag_tree_write_namespaces:
-  {
-    \prop_map_inline:Nn \g__tag_role_NS_prop
-      {
-        \pdfdict_if_empty:nF {g__tag_role/RoleMapNS_##1_dict}
-          {
-            \pdf_object_write:nx {__tag/RoleMapNS/##1}
-              {
-                \pdfdict_use:n {g__tag_role/RoleMapNS_##1_dict}
-              }
-            \pdfdict_gput:nnx{g__tag_role/Namespace_##1_dict}
-              {RoleMapNS}{\pdf_object_ref:n {__tag/RoleMapNS/##1}}
-          }
-        \pdf_object_write:nx{tag/NS/##1}
-          {
-             \pdfdict_use:n {g__tag_role/Namespace_##1_dict}
-          }
-      }
-    \pdf_object_write:nx {__tag/tree/namespaces}
-      {
-        \prop_map_tokens:Nn \g__tag_role_NS_prop{\use_ii:nn}
-      }
-  }
-
-\cs_new_protected:Nn \tag_finish_structure:
-  {
-    \__tag_tree_write_parenttree:
-    \__tag_tree_write_rolemap:
-    \__tag_tree_write_classmap:
-    \__tag_tree_write_namespaces:
-    \__tag_tree_write_structelements: %this is rather slow!!
-    \__tag_tree_write_structtreeroot:
-  }
-
-\hook_gput_code:nnn{begindocument}{tagpdf}
-  {
-    \bool_if:NT\g__tag_active_tree_bool
-      {
-       \hook_gput_code:nnn{shipout/before} { tagpdf/structparents }
-         {
-             \pdfmanagement_add:nnx
-               { Page }
-               {StructParents}
-               {\int_eval:n { \g_shipout_readonly_int}}
-         }
-      }
-  }
-
-%% 
-%%
-%% End of file `tagpdf-tree-code.sty'.

Deleted: trunk/Master/texmf-dist/tex/latex/tagpdf/tagpdf-user.sty
===================================================================
--- trunk/Master/texmf-dist/tex/latex/tagpdf/tagpdf-user.sty	2021-06-30 20:41:50 UTC (rev 59768)
+++ trunk/Master/texmf-dist/tex/latex/tagpdf/tagpdf-user.sty	2021-06-30 21:14:14 UTC (rev 59769)
@@ -1,335 +0,0 @@
-%%
-%% This is file `tagpdf-user.sty',
-%% generated with the docstrip utility.
-%%
-%% The original source files were:
-%%
-%% tagpdf.dtx  (with options: `user')
-%% 
-%% Copyright (C) 2019 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.
-%% 
-%% File: tagpdf.dtx
-\ProvidesExplPackage {tagpdf-user} {2021-06-14} {0.82}
-  {tagpdf - user commands}
-
-\NewDocumentCommand \tagpdfsetup { m }
-  {
-    \keys_set:nn { __tag / setup } { #1 }
-  }
-
-\cs_set_eq:NN\tagpdfifluatexTF \sys_if_engine_luatex:TF
-\cs_set_eq:NN\tagpdfifluatexT  \sys_if_engine_luatex:T
-\cs_set_eq:NN\tagpdfifpdftexT  \sys_if_engine_pdftex:T
-\prg_new_conditional:Npnn \tag_if_active: { p , T , TF, F }
-  {
-     \bool_if:NTF\g__tag_active_struct_bool
-       {
-         \prg_return_true:
-       }
-       {
-         \prg_return_false:
-       }
-  }
-\bool_new:N \l__tag_stop_bool
-
-\prg_new_conditional:Nnn \__tag_if_stop: {p,T,F,TF}
-  {
-    \bool_if:NTF \l__tag_stop_bool
-      { \prg_return_true:  }
-      { \prg_return_false: }
-  }
-
-\prg_new_eq_conditional:NNn \tag_if_stop: \__tag_if_stop: {p,T,F,TF}
-
-\cs_new_protected:Npn \__tag_stop:
-  {
-    \bool_set_true:N \l__tag_stop_bool
-    \cs_set_eq:NN \tag_mc_begin:n     \use_none:n
-    \cs_set_eq:NN \tag_mc_end:        \prg_do_nothing:
-    \cs_set_eq:NN \tag_mc_use:n       \use_none:n
-    \cs_set_eq:NN \tag_struct_begin:n \use_none:n
-    \cs_set_eq:NN \tag_struct_end:    \prg_do_nothing:
-    \cs_set_eq:NN \tag_struct_use:n   \use_none:n
-  }
-
-\cs_new_protected:Npn \tag_stop_group_begin:
-  {
-    \group_begin:
-    \__tag_stop:
-  }
-
-\cs_set_eq:NN \tag_stop_group_end: \group_end:
-\cs_new:Npn \tagpdfget #1   { \use:c {__tag_get_data_#1: } }
-\cs_new:Npn \tag_get:n #1   { \use:c {__tag_get_data_#1: } }
-
-\NewDocumentCommand \tagmcifinTF { m m }
-  {
-    \__tag_mc_if_in:TF { #1 } { #2 }
-  }
-\NewDocumentEnvironment{tagmcartifact}{m}
- {
-  \tag_mc_artifact_group_begin:n { #1}\ignorespaces
- }
- {
-  \tag_mc_artifact_group_end:
- }
-
-\NewDocumentCommand \tagmcbegin { m }
-  {
-    \tag_mc_begin:n {#1}\ignorespaces
-  }
-
-\NewDocumentCommand \tagmcend {  }
-  {
-    \if_mode_horizontal: \unskip \fi: %
-    \tag_mc_end:
-  }
-
-\NewDocumentCommand \tagmcuse { m }
-  {
-    \tag_mc_use:n {#1}
-  }
-
-\NewDocumentCommand \tagstructbegin { m }
-  {
-    \tag_struct_begin:n {#1}
-  }
-
-\NewDocumentCommand \tagstructend {  }
-  {
-   \tag_struct_end:
-  }
-
-\NewDocumentCommand \tagstructuse { m }
-  {
-    \tag_struct_use:n {#1}
-  }
-
-\NewDocumentCommand\showtagpdfmcdata { O {\__tag_tag_get_mc_abs_cnt:} }
-  {
-    \bool_if:NT \g__tag_mode_lua_bool
-      {
-        \sys_if_engine_luatex:T
-          {
-            \directlua{ltx.__tag.trace.show_all_mc_data(#1)}
-          }
-      }
-  }
-
-\NewDocumentCommand\showtagpdfattributes { }
-  {
-    \bool_if:NT \g__tag_mode_lua_bool
-      {
-        \sys_if_engine_luatex:T
-          {
-            \directlua
-              {
-                ltx.__tag.trace.log
-                 (
-                   "showtagpdfattributes:
-                    MC=>abscnt=\__tag_get_mc_abs_cnt:
-                    =>attr=\the\l__tag_mc_cnt_attr=>tag="
-                    ..
-                    tostring(ltx.__tag.func.get_tag_from (\the\l__tag_mc_type_attr))
-                    ..
-                    "=\the\l__tag_mc_type_attr",0
-                 )
-             }
-            \ignorespaces
-          }
-      }
-   }
-
-\NewDocumentCommand\showtagstack {}
-  {
-    \seq_show:N \g__tag_struct_tag_stack_seq
-  }
-\sys_if_engine_luatex:T
-  {
-    \NewDocumentCommand\pdffakespace { }
-      {
-        \__tag_fakespace:
-      }
-  }
-\bool_new:N \l__tag_para_bool
-\bool_new:N \l__tag_para_show_bool
-\int_new:N \g__tag_para_int
-
-\keys_define:nn { __tag / setup }
-  {
-    paratagging      .bool_set:N = \l__tag_para_bool,
-    paratagging-show .bool_set:N = \l__tag_para_show_bool,
-  }
-
-\AddToHook{para/begin}
-  {
-   \int_gincr:N \g__tag_para_int
-   \bool_if:NT \l__tag_para_bool
-     {
-       \tag_struct_begin:n {tag=P}
-       \bool_if:NT \l__tag_para_show_bool
-        { \tag_mc_begin:n{artifact}
-          \llap{\color_select:n{red}\tiny\int_use:N\g__tag_para_int\ }
-          \tag_mc_end:
-        }
-       \tag_mc_begin:n {tag=P}
-     }
-  }
-\AddToHook{para/end}
-  {
-    \bool_if:NT \l__tag_para_bool
-      {
-        \tag_mc_end:
-        \bool_if:NT \l__tag_para_show_bool
-          { \tag_mc_begin:n{artifact}
-            \rlap{\color_select:n{red}\tiny\ \int_use:N\g__tag_para_int}
-            \tag_mc_end:
-          }
-        \tag_struct_end:
-      }
-  }
-
-\newcommand\tagpdfparaOn {\bool_set_true:N \l__tag_para_bool}
-\newcommand\tagpdfparaOff{\bool_set_false:N \l__tag_para_bool}
-
-\cs_generate_variant:Nn \pdfannot_dict_put:nnn {nnx}
-\hook_gput_code:nnn
-  {pdfannot/link/URI/before}
-  {tagpdf}
-  {
-    \bool_if:NT \g__tag_active_struct_bool
-      {
-        \tag_mc_end_push:
-        \tag_struct_begin:n { tag=Link }
-        \tag_mc_begin:n { tag=Link }
-        \pdfannot_dict_put:nnx
-          { link/URI }
-          { StructParent }
-          { \tag_struct_parent_int: }
-       }
-  }
-
-\hook_gput_code:nnn
-  {pdfannot/link/URI/after}
-  {tagpdf}
-  {
-    \bool_if:NT \g__tag_active_struct_bool
-      {
-        \tag_struct_insert_annot:xx {\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}
-  {
-    \bool_if:NT \g__tag_active_struct_bool
-      {
-        \tag_mc_end_push:
-        \tag_struct_begin:n{tag=Link}
-        \tag_mc_begin:n{tag=Link}
-        \pdfannot_dict_put:nnx
-          { link/GoTo }
-          { StructParent }
-          { \tag_struct_parent_int: }
-       }
-  }
-
-\hook_gput_code:nnn
-  {pdfannot/link/GoTo/after}
-  {tagpdf}
-  {
-    \bool_if:NT \g__tag_active_struct_bool
-      {
-        \tag_struct_insert_annot:xx {\pdfannot_link_ref_last:}{\tag_struct_parent_int:}
-        \tag_mc_end:
-        \tag_struct_end:
-        \tag_mc_begin_pop:n{}
-      }
-  }
-
-\hook_gput_code:nnn
- {cmd/url/before}
- {tagpdf}
- {\tag_mc_end_push:}
-
-\hook_gput_code:nnn
- {cmd/url/after}
- {tagpdf}
- {\tag_mc_begin_pop:n{}}
-
-\hook_gput_code:nnn
- {cmd/href/before}
- {tagpdf}
- {\tag_mc_end_push:}
-
-\hook_gput_code:nnn
- {cmd/href/after}
- {tagpdf}
- {\tag_mc_begin_pop:n{}}
-
-\hook_gput_code:nnn
- {cmd/hrefurl/before}
- {tagpdf}
- {\tag_mc_end_push:}
-
-\hook_gput_code:nnn
- {cmd/hrefurl/after}
- {tagpdf}
- {\tag_mc_begin_pop:n{}}
-
-\hook_gput_code:nnn
- {cmd/T at ref/before}
- {tagpdf}
- {\tag_mc_end_push:}
-
-\hook_gput_code:nnn
- {cmd/T at ref/after}
- {tagpdf}
- {\tag_mc_begin_pop:n{}}
-
-\hook_gput_code:nnn
- {cmd/T at pageref/before}
- {tagpdf}
- {\tag_mc_end_push:}
-
-\hook_gput_code:nnn
- {cmd/T at pageref/after}
- {tagpdf}
- {\tag_mc_begin_pop:n{}}
-
-\hook_gput_code:nnn
- {cmd/T at nameref/before}
- {tagpdf}
- {\tag_mc_end_push:}
-
-\hook_gput_code:nnn
- {cmd/T at nameref/after}
- {tagpdf}
- {\tag_mc_begin_pop:n{}}
-\pdfannot_dict_put:nnn
- { link/URI }
- { Contents }
- { (url) }
-
-\pdfannot_dict_put:nnn
- { link/GoTo }
- { Contents }
- { (ref) }
-
-%% 
-%%
-%% End of file `tagpdf-user.sty'.

Modified: trunk/Master/texmf-dist/tex/latex/tagpdf/tagpdf.lua
===================================================================
--- trunk/Master/texmf-dist/tex/latex/tagpdf/tagpdf.lua	2021-06-30 20:41:50 UTC (rev 59768)
+++ trunk/Master/texmf-dist/tex/latex/tagpdf/tagpdf.lua	2021-06-30 21:14:14 UTC (rev 59769)
@@ -6,7 +6,7 @@
 -- 
 --  tagpdf-backend.dtx  (with options: `lua')
 --  
---  Copyright (C) 2019 Ulrike Fischer
+--  Copyright (C) 2019-2021 Ulrike Fischer
 --  
 --  It may be distributed and/or modified under the conditions of
 --  the LaTeX Project Public License (LPPL), either version 1.3c of
@@ -24,8 +24,8 @@
 
 local ProvidesLuaModule = {
     name          = "tagpdf",
-    version       = "0.82",       --TAGVERSION
-    date          = "2021-06-14", --TAGDATE
+    version       = "0.9",       --TAGVERSION
+    date          = "2021-06-29", --TAGDATE
     description   = "tagpdf lua code",
     license       = "The LATEX Project Public License 1.3c"
 }
@@ -72,9 +72,10 @@
  ltx.__tag.func.mark_shipout (): a wrapper around the core function which inserts the last EMC
  ltx.__tag.func.fill_parent_tree_line (page): outputs the entries of the parenttree for this page
  ltx.__tag.func.output_parenttree(): outputs the content of the parenttree
+ ltx.__tag.func.pdf_object_ref(name): outputs the object reference for the object name
  ltx.__tag.func.markspaceon(), ltx.__tag.func.markspaceoff(): (de)activates the marking of positions for space chars
- ltx.__tag.trace.show_mc_data (num): shows ltx.__tag.mc[num]
- ltx.__tag.trace.show_all_mc_data (max): shows a maximum about mc's
+ ltx.__tag.trace.show_mc_data (num,loglevel): shows ltx.__tag.mc[num] is the current log level is >= loglevel
+ ltx.__tag.trace.show_all_mc_data (max,loglevel): shows a maximum about mc's if the current log level is >= loglevel
  ltx.__tag.trace.show_seq: shows a sequence (array)
  ltx.__tag.trace.show_struct_data (num): shows data of structure num
  ltx.__tag.trace.show_prop: shows a prop
@@ -82,18 +83,14 @@
  ltx.__tag.trace.showspaces : boolean
 --]]
 
-local mctypeattributeid       = luatexbase.registernumber ("l__tag_mc_type_attr")
-local mccntattributeid        = luatexbase.registernumber ("l__tag_mc_cnt_attr")
-local iwspaceattributeid = luatexbase.registernumber ("g__tag_interwordspace_attr")
-local iwfontattributeid = luatexbase.registernumber ("g__tag_interwordfont_attr")
-
-local catlatex       = luatexbase.registernumber("catcodetable at latex")
+local mctypeattributeid  = luatexbase.new_attribute ("g__tag_mc_type_attr")
+local mccntattributeid   = luatexbase.new_attribute ("g__tag_mc_cnt_attr")
+local iwspaceattributeid = luatexbase.new_attribute ("g__tag_interwordspace_attr")
+local iwfontattributeid  = luatexbase.new_attribute ("g__tag_interwordfont_attr")
 local tagunmarkedbool= token.create("g__tag_tagunmarked_bool")
 local truebool       = token.create("c_true_bool")
-
+local catlatex       = luatexbase.registernumber("catcodetable at latex")
 local tableinsert    = table.insert
-
--- not all needed, copied from lua-visual-debug.
 local nodeid           = node.id
 local nodecopy         = node.copy
 local nodegetattribute = node.get_attribute
@@ -119,27 +116,17 @@
 local PENALTY        = node.id("penalty")
 local LOCAL_PAR      = node.id("local_par")
 local MATH           = node.id("math")
-
-local function __tag_get_mathsubtype  (mathnode)
- if mathnode.subtype == 0 then
-  subtype = "beginmath"
- else
-  subtype = "endmath"
- end
- return subtype
-end
-
 ltx             = ltx        or { }
 ltx.__tag          = ltx.__tag        or { }
-ltx.__tag.mc             = ltx.__tag.mc     or  { } -- mc data
-ltx.__tag.struct         = ltx.__tag.struct or  { } -- struct data
-ltx.__tag.tables         = ltx.__tag.tables or  { } -- tables created with new prop and new seq.
-                                            -- wasn't a so great idea ...
-ltx.__tag.page           = ltx.__tag.page   or  { } -- page data, currently only i->{0->mcnum,1->mcnum,...}
-ltx.__tag.trace          = ltx.__tag.trace  or  { } -- show commands
-ltx.__tag.func           = ltx.__tag.func   or  { } -- functions
-ltx.__tag.conf           = ltx.__tag.conf   or  { } -- configuration variables
-
+ltx.__tag.mc       = ltx.__tag.mc     or  { } -- mc data
+ltx.__tag.struct   = ltx.__tag.struct or  { } -- struct data
+ltx.__tag.tables   = ltx.__tag.tables or  { } -- tables created with new prop and new seq.
+                                        -- wasn't a so great idea ...
+                                        -- g__tag_role_tags_seq used by tag<-> is in this tables!
+ltx.__tag.page     = ltx.__tag.page   or  { } -- page data, currently only i->{0->mcnum,1->mcnum,...}
+ltx.__tag.trace    = ltx.__tag.trace  or  { } -- show commands
+ltx.__tag.func     = ltx.__tag.func   or  { } -- functions
+ltx.__tag.conf     = ltx.__tag.conf   or  { } -- configuration variables
 local __tag_log =
  function (message,loglevel)
   if (loglevel or 3) <= tex.count["l__tag_loglevel_int"] then
@@ -148,7 +135,71 @@
  end
 
 ltx.__tag.trace.log = __tag_log
+function ltx.__tag.trace.show_seq (seq)
+ if (type(seq) == "table") then
+  for i,v in ipairs(seq) do
+   __tag_log ("[" .. i .. "] => " .. tostring(v),1)
+  end
+  else
+   __tag_log ("sequence " .. tostring(seq) .. " not found",1)
+  end
+end
+local __tag_pairs_prop =
+ function  (prop)
+      local a = {}
+      for n in pairs(prop) do tableinsert(a, n) end
+      table.sort(a)
+      local i = 0                -- iterator variable
+      local iter = function ()   -- iterator function
+        i = i + 1
+        if a[i] == nil then return nil
+        else return a[i], prop[a[i]]
+        end
+      end
+      return iter
+  end
 
+function ltx.__tag.trace.show_prop (prop)
+ if (type(prop) == "table") then
+  for i,v in __tag_pairs_prop (prop) do
+    __tag_log ("[" .. i .. "] => " .. tostring(v),1)
+  end
+ else
+   __tag_log ("prop " .. tostring(prop) .. " not found or not a table",1)
+ end
+ end
+function ltx.__tag.trace.show_mc_data (num,loglevel)
+ if ltx.__tag and ltx.__tag.mc and ltx.__tag.mc[num] then
+  for k,v in pairs(ltx.__tag.mc[num]) do
+   __tag_log  ("mc"..num..": "..tostring(k).."=>"..tostring(v),loglevel)
+  end
+  if ltx.__tag.mc[num]["kids"] then
+  __tag_log ("mc" .. num .. " has " .. #ltx.__tag.mc[num]["kids"] .. " kids",loglevel)
+   for k,v in ipairs(ltx.__tag.mc[num]["kids"]) do
+    __tag_log ("mc ".. num .. " kid "..k.." =>" .. v.kid.." on page " ..v.page,loglevel)
+   end
+  end
+ else
+  __tag_log  ("mc"..num.." not found",loglevel)
+ end
+end
+function ltx.__tag.trace.show_all_mc_data (min,max,loglevel)
+ for i = min, max do
+  ltx.__tag.trace.show_mc_data (i,loglevel)
+ end
+ texio.write_nl("")
+end
+
+function ltx.__tag.trace.show_struct_data (num)
+ if ltx.__tag and ltx.__tag.struct and ltx.__tag.struct[num] then
+  for k,v in ipairs(ltx.__tag.struct[num]) do
+   __tag_log  ("struct "..num..": "..tostring(k).."=>"..tostring(v),1)
+  end
+ else
+  __tag_log   ("struct "..num.." not found ",1)
+ end
+end
+
 local __tag_get_mc_cnt_type_tag = function (n)
   local mccnt      =  nodegetattribute(n,mccntattributeid)  or -1
   local mctype     =  nodegetattribute(n,mctypeattributeid)  or -1
@@ -155,7 +206,73 @@
   local tag        =  ltx.__tag.func.get_tag_from(mctype)
   return mccnt,mctype,tag
 end
+local function __tag_get_mathsubtype  (mathnode)
+ if mathnode.subtype == 0 then
+  subtype = "beginmath"
+ else
+  subtype = "endmath"
+ end
+ return subtype
+end
 
+local __tag_get_num_from =
+ function (tag)
+  if ltx.__tag.tables["g__tag_role_tags_prop"][tag] then
+    a= ltx.__tag.tables["g__tag_role_tags_prop"][tag]
+  else
+    a= -1
+  end
+  return a
+ end
+
+ltx.__tag.func.get_num_from = __tag_get_num_from
+
+function ltx.__tag.func.output_num_from (tag)
+  local num = __tag_get_num_from (tag)
+  tex.sprint(catlatex,num)
+  if num == -1 then
+   __tag_log ("Unknown tag "..tag.." used")
+  end
+end
+local __tag_get_tag_from =
+ function  (num)
+  if ltx.__tag.tables["g__tag_role_tags_seq"][num] then
+   a = ltx.__tag.tables["g__tag_role_tags_seq"][num]
+  else
+   a= "UNKNOWN"
+  end
+ return a
+end
+
+ltx.__tag.func.get_tag_from = __tag_get_tag_from
+
+function ltx.__tag.func.output_tag_from (num)
+  tex.sprint(catlatex,__tag_get_tag_from (num))
+end
+function ltx.__tag.func.store_mc_data (num,key,data)
+ ltx.__tag.mc[num] = ltx.__tag.mc[num] or { }
+ ltx.__tag.mc[num][key] = data
+ __tag_log  ("INFO TEX-STORE-MC-DATA: "..num.." => "..tostring(key).." => "..tostring(data),3)
+end
+function ltx.__tag.func.store_mc_label (label,num)
+ ltx.__tag.mc["labels"] = ltx.__tag.mc["labels"] or { }
+ ltx.__tag.mc.labels[label] = num
+end
+function ltx.__tag.func.store_mc_kid (mcnum,kid,page)
+ ltx.__tag.trace.log("INFO TAG-STORE-MC-KID: "..mcnum.." => " .. kid.." on page " .. page,3)
+ ltx.__tag.mc[mcnum]["kids"] = ltx.__tag.mc[mcnum]["kids"] or { }
+ local kidtable = {kid=kid,page=page}
+ tableinsert(ltx.__tag.mc[mcnum]["kids"], kidtable )
+end
+
+function ltx.__tag.func.mc_num_of_kids (mcnum)
+ local num = 0
+ if ltx.__tag.mc[mcnum] and ltx.__tag.mc[mcnum]["kids"] then
+   num = #ltx.__tag.mc[mcnum]["kids"]
+ end
+ ltx.__tag.trace.log ("INFO MC-KID-NUMBERS: " .. mcnum .. "has " .. num .. "KIDS",4)
+ return num
+end
 local function __tag_insert_emc_node (head,current)
  local emcnode = nodenew("whatsit","pdf_literal")
        emcnode.data = "EMC"
@@ -163,7 +280,6 @@
        head = node.insert_before(head,current,emcnode)
  return head
 end
-
 local function __tag_insert_bmc_node (head,current,tag)
  local bmcnode = nodenew("whatsit","pdf_literal")
        bmcnode.data = "/"..tag.." BMC"
@@ -171,7 +287,6 @@
        head = node.insert_before(head,current,bmcnode)
  return head
 end
-
 local function __tag_insert_bdc_node (head,current,tag,dict)
  local bdcnode = nodenew("whatsit","pdf_literal")
        bdcnode.data = "/"..tag.."<<"..dict..">> BDC"
@@ -179,8 +294,12 @@
        head = node.insert_before(head,current,bdcnode)
  return head
 end
-
--- this is for debugging the space chars
+local function __tag_pdf_object_ref (name)
+   local tokenname = 'c__pdf_backend_object_'..name..'_int'
+   local object = token.create(tokenname).index..' 0 R'
+   return object
+end
+ltx.__tag.func.pdf_object_ref=__tag_pdf_object_ref
 local function __tag_show_spacemark (head,current,color,height)
  local markcolor = color or "1 0 0"
  local markheight = height or 10
@@ -190,7 +309,11 @@
        head = node.insert_after(head,current,pdfstring)
  return head
 end
-
+local function __tag_fakespace()
+   tex.setattribute(iwspaceattributeid,1)
+   tex.setattribute(iwfontattributeid,font.current())
+end
+ltx.__tag.func.fakespace = __tag_fakespace
 --[[ a function to mark up places where real space chars should be inserted
      it only sets an attribute.
 --]]
@@ -220,7 +343,9 @@
       end
      --  look also back
      if glyph.prev and (glyph.prev.id == GLUE)
-        and not inside_math  and (glyph.prev.width >0) and not nodehasattribute(glyph.prev,iwspaceattributeid)
+        and not inside_math
+        and (glyph.prev.width >0)
+        and not nodehasattribute(glyph.prev,iwspaceattributeid)
       then
         nodesetattribute(glyph.prev,iwspaceattributeid,1)
         nodesetattribute(glyph.prev,iwfontattributeid,glyph.font)
@@ -248,7 +373,6 @@
   end
   return head
 end
-
 local function __tag_activate_mark_space ()
  if not luatexbase.in_callback ("pre_linebreak_filter","markspaces") then
   luatexbase.add_to_callback("pre_linebreak_filter",__tag_mark_spaces,"markspaces")
@@ -264,23 +388,97 @@
  luatexbase.remove_from_callback("hpack_filter","markspaces")
  end
 end
---
+
 ltx.__tag.func.markspaceoff=__tag_deactivate_mark_space
-
 local default_space_char = node.new(GLYPH)
 local default_fontid     = font.id("TU/lmr/m/n/10")
 default_space_char.char  = 32
 default_space_char.font  = default_fontid
+local function __tag_space_chars_shipout (box)
+ local head = box.head
+  if head then
+    for n in node.traverse(head) do
+      local spaceattr = nodegetattribute(n,iwspaceattributeid)  or -1
+      if n.id == HLIST  then -- enter the hlist
+         __tag_space_chars_shipout (n)
+      elseif n.id == VLIST then -- enter the vlist
+         __tag_space_chars_shipout (n)
+      elseif n.id == GLUE then
+        if ltx.__tag.trace.showspaces and spaceattr==1  then
+          __tag_show_spacemark (head,n,"0 1 0")
+        end
+        if spaceattr==1  then
+          local space
+          local space_char = node.copy(default_space_char)
+          local curfont    = nodegetattribute(n,iwfontattributeid)
+          ltx.__tag.trace.log ("INFO SPACE-FUNCTION-FONT: ".. tostring(curfont),3)
+          if curfont and luaotfload.aux.slot_of_name(curfont,"space") then
+            space_char.font=curfont
+          end
+          head, space = node.insert_before(head, n, space_char) --
+          n.width     = n.width - space.width
+          space.attr  = n.attr
+        end
+      end
+    end
+  end
+end
 
-local function __tag_insert_space_char (head,n,fontid)
- if luaotfload.aux.slot_of_name(fontid,"space") then
-  local space
-  -- head, space = node.insert_before(head, n, ) -- Set the right font
-  -- n.width = n.width - space.width
-  -- space.attr = n.attr
- end
+function ltx.__tag.func.space_chars_shipout (box)
+  __tag_space_chars_shipout (box)
 end
+function ltx.__tag.func.mc_insert_kids (mcnum,single)
+  if ltx.__tag.mc[mcnum] then
+  ltx.__tag.trace.log("INFO TEX-MC-INSERT-KID-TEST: " .. mcnum,4)
+   if ltx.__tag.mc[mcnum]["kids"] then
+    if #ltx.__tag.mc[mcnum]["kids"] > 1 and single==1 then
+     tex.sprint("[")
+    end
+    for i,kidstable in ipairs( ltx.__tag.mc[mcnum]["kids"] ) do
+     local kidnum  = kidstable["kid"]
+     local kidpage = kidstable["page"]
+     local kidpageobjnum = pdfpageref(kidpage)
+     ltx.__tag.trace.log("INFO TEX-MC-INSERT-KID: " .. mcnum ..
+                      " insert KID " ..i..
+                      " with num " .. kidnum ..
+                      " on page " .. kidpage.."/"..kidpageobjnum,3)
+     tex.sprint(catlatex,"<</Type /MCR /Pg "..kidpageobjnum .. " 0 R /MCID "..kidnum.. ">> " )
+    end
+    if #ltx.__tag.mc[mcnum]["kids"] > 1 and single==1 then
+     tex.sprint("]")
+    end
+   else
+    -- this is typically not a problem, e.g. empty hbox in footer/header can
+    -- trigger this warning.
+    ltx.__tag.trace.log("WARN TEX-MC-INSERT-NO-KIDS: "..mcnum.." has no kids",2)
+    if single==1 then
+      tex.sprint("null")
+    end
+   end
+  else
+   ltx.__tag.trace.log("WARN TEX-MC-INSERT-MISSING: "..mcnum.." doesn't exist",0)
+  end
+end
+function ltx.__tag.func.store_struct_mcabs (structnum,mcnum)
+ ltx.__tag.struct[structnum]=ltx.__tag.struct[structnum] or { }
+ ltx.__tag.struct[structnum]["mc"]=ltx.__tag.struct[structnum]["mc"] or { }
+ -- a structure can contain more than on mc chunk, the content should be ordered
+ tableinsert(ltx.__tag.struct[structnum]["mc"],mcnum)
+ ltx.__tag.trace.log("INFO TEX-MC-INTO-STRUCT: "..
+                   mcnum.." inserted in struct "..structnum,3)
+ -- but every mc can only be in one structure
+ ltx.__tag.mc[mcnum]= ltx.__tag.mc[mcnum] or { }
+ ltx.__tag.mc[mcnum]["parent"] = structnum
+end
 
+-- pay attention: lua counts arrays from 1, tex pages from one
+-- mcid and arrays in pdf count from 0.
+function ltx.__tag.func.store_mc_in_page (mcnum,mcpagecnt,page)
+ ltx.__tag.page[page] = ltx.__tag.page[page] or {}
+ ltx.__tag.page[page][mcpagecnt] = mcnum
+ ltx.__tag.trace.log("INFO TAG-MC-INTO-PAGE: page " .. page ..
+                   ": inserting MCID " .. mcpagecnt .. " => " .. mcnum,3)
+end
 --[[
     Now follows the core function
     It wades through the shipout box and checks the attributes
@@ -300,22 +498,35 @@
 function ltx.__tag.func.mark_page_elements (box,mcpagecnt,mccntprev,mcopen,name,mctypeprev)
   local name = name or ("SOMEBOX")
   local mctypeprev = mctypeprev or -1
-  local abspage = status.total_pages + 1  -- the real counter is increased inside the box so one off
-                                                                       -- if the callback is not used.
-  ltx.__tag.trace.log ("PAGE " .. abspage,3)
-  ltx.__tag.trace.log ("FUNC ARGS: pagecnt".. mcpagecnt.." prev "..mccntprev .. " type prev "..mctypeprev,4)
-  ltx.__tag.trace.log ("TRAVERSING BOX ".. tostring(name).." TYPE ".. node.type(node.getid(box)),3)
+  local abspage = status.total_pages + 1  -- the real counter is increased
+                                          -- inside the box so one off
+                                          -- if the callback is not used. (???)
+  ltx.__tag.trace.log ("INFO TAG-ABSPAGE: " .. abspage,3)
+  ltx.__tag.trace.log ("INFO TAG-ARGS: pagecnt".. mcpagecnt..
+                    " prev "..mccntprev ..
+                    " type prev "..mctypeprev,4)
+  ltx.__tag.trace.log ("INFO TAG-TRAVERSING-BOX: ".. tostring(name)..
+                    " TYPE ".. node.type(node.getid(box)),3)
   local head = box.head -- ShipoutBox is a vlist?
   if head then
     mccnthead, mctypehead,taghead = __tag_get_mc_cnt_type_tag (head)
-    ltx.__tag.trace.log ("HEAD " .. node.type(node.getid(head)).. " MC"..tostring(mccnthead).." => TAG "..tostring(mctypehead).." => "..tostring(taghead),3)
+    ltx.__tag.trace.log ("INFO TAG-HEAD: " ..
+                      node.type(node.getid(head))..
+                      " MC"..tostring(mccnthead)..
+                      " => TAG " .. tostring(mctypehead)..
+                      " => ".. tostring(taghead),3)
   else
-    ltx.__tag.trace.log ("HEAD is ".. tostring(head),3)
+    ltx.__tag.trace.log ("INFO TAG-NO-HEAD: head is "..
+                       tostring(head),3)
   end
   for n in node.traverse(head) do
     local mccnt, mctype, tag = __tag_get_mc_cnt_type_tag (n)
     local spaceattr = nodegetattribute(n,iwspaceattributeid)  or -1
-    ltx.__tag.trace.log ("NODE ".. node.type(node.getid(n)).." MC"..tostring(mccnt).." => TAG "..tostring(mctype).." => " .. tostring(tag),3)
+    ltx.__tag.trace.log ("INFO TAG-NODE: "..
+                       node.type(node.getid(n))..
+                      " MC".. tostring(mccnt)..
+                      " => TAG ".. tostring(mctype)..
+                      " => " ..  tostring(tag),3)
     if n.id == HLIST
     then -- enter the hlist
      mcopen,mcpagecnt,mccntprev,mctypeprev=
@@ -323,49 +534,42 @@
     elseif n.id == VLIST then -- enter the vlist
      mcopen,mcpagecnt,mccntprev,mctypeprev=
       ltx.__tag.func.mark_page_elements (n,mcpagecnt,mccntprev,mcopen,"INTERNAL VLIST",mctypeprev)
-    elseif n.id == GLUE then       -- at glue real space chars are inserted, for the rest it is ignored
-     -- for debugging
-     if ltx.__tag.trace.showspaces and spaceattr==1  then
-        __tag_show_spacemark (head,n,"0 1 0")
-     end
-     if spaceattr==1  then
-        local space
-        local space_char = node.copy(default_space_char)
-        local curfont    = nodegetattribute(n,iwfontattributeid)
-        ltx.__tag.trace.log ("FONT ".. tostring(curfont),3)
-        if curfont and luaotfload.aux.slot_of_name(curfont,"space") then
-          space_char.font=curfont
-        end
-        head, space = node.insert_before(head, n, space_char) --
-        n.width     = n.width - space.width
-        space.attr  = n.attr
-     end
+    elseif n.id == GLUE then       -- at glue real space chars are inserted, but this has
+                                   -- been done if the previous shipout wandering, so here it is ignored
     elseif n.id == LOCAL_PAR then  -- local_par is ignored
     elseif n.id == PENALTY then    -- penalty is ignored
     elseif n.id == KERN then       -- kern is ignored
-     ltx.__tag.trace.log ("SUBTYPE KERN ".. n.subtype,3)
+     ltx.__tag.trace.log ("INFO TAG-KERN-SUBTYPE: "..
+       node.type(node.getid(n)).." "..n.subtype,4)
     else
      -- math is currently only logged.
      -- we could mark the whole as math
      -- for inner processing the mlist_to_hlist callback is probably needed.
      if n.id == MATH then
-      ltx.__tag.trace.log("NODE "..node.type(node.getid(n)).." "..__tag_get_mathsubtype(n),3)
+      ltx.__tag.trace.log("INFO TAG-MATH-SUBTYPE: "..
+        node.type(node.getid(n)).." "..__tag_get_mathsubtype(n),4)
      end
      -- endmath
-     ltx.__tag.trace.log("CURRENT "..mccnt.." PREV "..mccntprev,3)
+     ltx.__tag.trace.log("INFO TAG-MC-COMPARE: current "..
+               mccnt.." prev "..mccntprev,4)
      if mccnt~=mccntprev then -- a new mc chunk
-      ltx.__tag.trace.log ("NODE ".. node.type(node.getid(n)).." MC"..tostring(mccnt).." <=> PREVIOUS "..tostring(mccntprev),3)
+      ltx.__tag.trace.log ("INFO TAG-NEW-MC-NODE: "..
+                         node.type(node.getid(n))..
+                        " MC"..tostring(mccnt)..
+                        " <=> PREVIOUS "..tostring(mccntprev),4)
       if mcopen~=0 then -- there is a chunk open, close it (hope there is only one ...
        box.list=__tag_insert_emc_node (box.list,n)
        mcopen = mcopen - 1
-       ltx.__tag.trace.log ("INSERT EMC " .. mcpagecnt .. " MCOPEN = " .. mcopen,2)
+       ltx.__tag.trace.log ("INFO TAG-INSERT-EMC: " ..
+         mcpagecnt .. " MCOPEN = " .. mcopen,3)
        if mcopen ~=0 then
-        ltx.__tag.trace.log ("!WARNING! open mc" .. " MCOPEN = " .. mcopen,1)
+        ltx.__tag.trace.log ("WARN TAG-OPEN-MC: " .. mcopen,1)
        end
       end
       if ltx.__tag.mc[mccnt] then
        if ltx.__tag.mc[mccnt]["artifact"] then
-        ltx.__tag.trace.log("THIS IS AN ARTIFACT of type "..tostring(ltx.__tag.mc[mccnt]["artifact"]),3)
+        ltx.__tag.trace.log("INFO TAG-INSERT-ARTIFACT: "..
+                          tostring(ltx.__tag.mc[mccnt]["artifact"]),3)
         if ltx.__tag.mc[mccnt]["artifact"] == "" then
          box.list = __tag_insert_bmc_node (box.list,n,"Artifact")
         else
@@ -372,34 +576,39 @@
          box.list = __tag_insert_bdc_node (box.list,n,"Artifact", "/Type /"..ltx.__tag.mc[mccnt]["artifact"])
         end
        else
-        ltx.__tag.trace.log("THIS IS A TAG "..tostring(tag),3)
+        ltx.__tag.trace.log("INFO TAG-INSERT-TAG: "..
+                          tostring(tag),3)
         mcpagecnt = mcpagecnt +1
-        ltx.__tag.trace.log ("INSERT BDC "..mcpagecnt,2)
+        ltx.__tag.trace.log ("INFO TAG-INSERT-BDC: "..mcpagecnt,3)
         local dict= "/MCID "..mcpagecnt
         if ltx.__tag.mc[mccnt]["raw"] then
-         ltx.__tag.trace.log("RAW CONTENT"..tostring(ltx.__tag.mc[mccnt]["raw"]),3)
+         ltx.__tag.trace.log("INFO TAG-USE-RAW: "..
+           tostring(ltx.__tag.mc[mccnt]["raw"]),3)
          dict= dict .. " " .. ltx.__tag.mc[mccnt]["raw"]
         end
         if ltx.__tag.mc[mccnt]["alt"] then
-         ltx.__tag.trace.log("RAW CONTENT"..tostring(ltx.__tag.mc[mccnt]["alt"]),3)
+         ltx.__tag.trace.log("INFO TAG-USE-ALT: "..
+            tostring(ltx.__tag.mc[mccnt]["alt"]),3)
          dict= dict .. " " .. ltx.__tag.mc[mccnt]["alt"]
         end
         if ltx.__tag.mc[mccnt]["actualtext"] then
-         ltx.__tag.trace.log("RAW CONTENT"..tostring(ltx.__tag.mc[mccnt]["actualtext"]),3)
+         ltx.__tag.trace.log("INFO TAG-USE-ACTUALTEXT: "..
+           tostring(ltx.__tag.mc[mccnt]["actualtext"]),3)
          dict= dict .. " " .. ltx.__tag.mc[mccnt]["actualtext"]
         end
         box.list = __tag_insert_bdc_node (box.list,n,tag, dict)
         ltx.__tag.func.store_mc_kid (mccnt,mcpagecnt,abspage)
         ltx.__tag.func.store_mc_in_page(mccnt,mcpagecnt,abspage)
-        ltx.__tag.trace.show_mc_data (mccnt)
+        ltx.__tag.trace.show_mc_data (mccnt,3)
        end
        mcopen = mcopen + 1
       else
-       ltx.__tag.trace.log("THIS HAS NOT BEEN TAGGED",1)
-     -- perhaps code that tag a artifact can be added ...
        if tagunmarkedbool.mode == truebool.mode then
+        ltx.__tag.trace.log("INFO TAG-NOT-TAGGED: this has not been tagged, using artifact",2)
         box.list = __tag_insert_bmc_node (box.list,n,"Artifact")
         mcopen = mcopen + 1
+       else
+        ltx.__tag.trace.log("WARN TAG-NOT-TAGGED: this has not been tagged",1)
        end
       end
       mccntprev = mccnt
@@ -408,11 +617,17 @@
   end -- end for
   if head then
     mccnthead, mctypehead,taghead = __tag_get_mc_cnt_type_tag (head)
-    ltx.__tag.trace.log ("ENDHEAD " .. node.type(node.getid(head)).. " MC"..tostring(mccnthead).." => TAG "..tostring(mctypehead).." => "..tostring(taghead),3)
+    ltx.__tag.trace.log ("INFO TAG-ENDHEAD: " ..
+                       node.type(node.getid(head))..
+                      " MC"..tostring(mccnthead)..
+                      " => TAG "..tostring(mctypehead)..
+                      " => "..tostring(taghead),4)
   else
-    ltx.__tag.trace.log ("ENDHEAD is ".. tostring(head),3)
+    ltx.__tag.trace.log ("INFO TAG-ENDHEAD: ".. tostring(head),4)
   end
-  ltx.__tag.trace.log ("QUITTING TRAVERSING BOX ".. tostring(name).." TYPE ".. node.type(node.getid(box)),3)
+  ltx.__tag.trace.log ("INFO TAG-QUITTING-BOX "..
+                     tostring(name)..
+                    " TYPE ".. node.type(node.getid(box)),4)
  return mcopen,mcpagecnt,mccntprev,mctypeprev
 end
 
@@ -426,193 +641,16 @@
   if list then
      list = node.insert_after (list,node.tail(list),emcnode)
      mcopen = mcopen - 1
-     ltx.__tag.trace.log ("INSERT LAST EMC, MCOPEN = " .. mcopen,2)
+     ltx.__tag.trace.log ("INFO SHIPOUT-INSERT-LAST-EMC: MCOPEN " .. mcopen,3)
   else
-     ltx.__tag.trace.log ("UPS ",1)
+     ltx.__tag.trace.log ("WARN SHIPOUT-UPS: this shouldn't happen",0)
   end
   if mcopen ~=0 then
-     ltx.__tag.trace.log ("!WARNING! open mc" .. " MCOPEN = " .. mcopen,1)
+     ltx.__tag.trace.log ("WARN SHIPOUT-MC-OPEN: " .. mcopen,1)
   end
  end
 end
 
-function ltx.__tag.trace.show_seq (seq)
- if (type(seq) == "table") then
-  for i,v in ipairs(seq) do
-   __tag_log ("[" .. i .. "] => " .. tostring(v),1)
-  end
-  else
-   __tag_log ("sequence " .. tostring(seq) .. " not found",1)
-  end
-end
-
-local __tag_pairs_prop =
- function  (prop)
-      local a = {}
-      for n in pairs(prop) do tableinsert(a, n) end
-      table.sort(a)
-      local i = 0                -- iterator variable
-      local iter = function ()   -- iterator function
-        i = i + 1
-        if a[i] == nil then return nil
-        else return a[i], prop[a[i]]
-        end
-      end
-      return iter
-  end
-
-function ltx.__tag.trace.show_prop (prop)
- if (type(prop) == "table") then
-  for i,v in __tag_pairs_prop (prop) do
-    __tag_log ("[" .. i .. "] => " .. tostring(v),1)
-  end
- else
-   __tag_log ("prop " .. tostring(prop) .. " not found or not a table",1)
- end
- end
-
-local __tag_get_num_from =
- function (tag)
-  if ltx.__tag.tables["g__tag_role_tags_prop"][tag] then
-    a= ltx.__tag.tables["g__tag_role_tags_prop"][tag]
-  else
-    a= -1
-  end
-  return a
- end
-
-ltx.__tag.func.get_num_from = __tag_get_num_from
-
-function ltx.__tag.func.output_num_from (tag)
-  local num = __tag_get_num_from (tag)
-  tex.sprint(catlatex,num)
-  if num == -1 then
-   __tag_log ("Unknown tag "..tag.." used")
-  end
-end
-
-local __tag_get_tag_from =
- function  (num)
-  if ltx.__tag.tables["g__tag_role_tags_seq"][num] then
-   a = ltx.__tag.tables["g__tag_role_tags_seq"][num]
-  else
-   a= "UNKNOWN"
-  end
- return a
-end
-
-ltx.__tag.func.get_tag_from = __tag_get_tag_from
-
-function ltx.__tag.func.output_tag_from (num)
-  tex.sprint(catlatex,__tag_get_tag_from (num))
-end
-
-function ltx.__tag.func.store_mc_data (num,key,data)
- ltx.__tag.mc[num] = ltx.__tag.mc[num] or { }
- ltx.__tag.mc[num][key] = data
- __tag_log  ("storing mc"..num..": "..tostring(key).."=>"..tostring(data))
-end
-
-function ltx.__tag.trace.show_mc_data (num)
- if ltx.__tag and ltx.__tag.mc and ltx.__tag.mc[num] then
-  for k,v in pairs(ltx.__tag.mc[num]) do
-   __tag_log  ("mc"..num..": "..tostring(k).."=>"..tostring(v),3)
-  end
-  if ltx.__tag.mc[num]["kids"] then
-  __tag_log ("mc" .. num .. " has " .. #ltx.__tag.mc[num]["kids"] .. " kids",3)
-   for k,v in ipairs(ltx.__tag.mc[num]["kids"]) do
-    __tag_log ("mc ".. num .. " kid "..k.." =>" .. v.kid.." on page " ..v.page,3)
-   end
-  end
- else
-  __tag_log  ("mc"..num.." not found",3)
- end
-end
-
-function ltx.__tag.trace.show_all_mc_data (max)
- for i = 1, max do
-  ltx.__tag.trace.show_mc_data (i)
- end
-end
-
-function ltx.__tag.func.store_mc_label (label,num)
- ltx.__tag.mc["labels"] = ltx.__tag.mc["labels"] or { }
- ltx.__tag.mc.labels[label] = num
-end
-
-function ltx.__tag.func.store_mc_kid (mcnum,kid,page)
- ltx.__tag.trace.log("MC"..mcnum.." STORING KID" .. kid.." on page " .. page,3)
- ltx.__tag.mc[mcnum]["kids"] = ltx.__tag.mc[mcnum]["kids"] or { }
- local kidtable = {kid=kid,page=page}
- tableinsert(ltx.__tag.mc[mcnum]["kids"], kidtable )
-end
-
-function ltx.__tag.func.mc_num_of_kids (mcnum)
- local num = 0
- if ltx.__tag.mc[mcnum] and ltx.__tag.mc[mcnum]["kids"] then
-   num = #ltx.__tag.mc[mcnum]["kids"]
- end
- ltx.__tag.trace.log ("MC" .. mcnum .. "has " .. num .. "KIDS",4)
- return num
-end
-
-function ltx.__tag.func.mc_insert_kids (mcnum,single)
-  if ltx.__tag.mc[mcnum] then
-  ltx.__tag.trace.log("MC-KIDS test " .. mcnum,4)
-   if ltx.__tag.mc[mcnum]["kids"] then
-    if #ltx.__tag.mc[mcnum]["kids"] > 1 and single==1 then
-     tex.sprint("[")
-    end
-    for i,kidstable in ipairs( ltx.__tag.mc[mcnum]["kids"] ) do
-     local kidnum  = kidstable["kid"]
-     local kidpage = kidstable["page"]
-     local kidpageobjnum = pdfpageref(kidpage)
-     ltx.__tag.trace.log("MC" .. mcnum .. " insert KID " ..i.. " with num " .. kidnum .. " on page " .. kidpage.."/"..kidpageobjnum,3)
-     tex.sprint(catlatex,"<</Type /MCR /Pg "..kidpageobjnum .. " 0 R /MCID "..kidnum.. ">> " )
-    end
-    if #ltx.__tag.mc[mcnum]["kids"] > 1 and single==1 then
-     tex.sprint("]")
-    end
-   else
-    ltx.__tag.trace.log("WARN! MC"..mcnum.." has no kids",0)
-    if single==1 then
-      tex.sprint("null")
-    end
-   end
-  else
-   ltx.__tag.trace.log("WARN! MC"..mcnum.." doesn't exist",0)
-  end
-end
-
-function ltx.__tag.func.store_struct_mcabs (structnum,mcnum)
- ltx.__tag.struct[structnum]=ltx.__tag.struct[structnum] or { }
- ltx.__tag.struct[structnum]["mc"]=ltx.__tag.struct[structnum]["mc"] or { }
- -- a structure can contain more than on mc chunk, the content should be ordered
- tableinsert(ltx.__tag.struct[structnum]["mc"],mcnum)
- ltx.__tag.trace.log("MCNUM "..mcnum.." insert in struct "..structnum,3)
- -- but every mc can only be in one structure
- ltx.__tag.mc[mcnum]= ltx.__tag.mc[mcnum] or { }
- ltx.__tag.mc[mcnum]["parent"] = structnum
-end
-
-function ltx.__tag.trace.show_struct_data (num)
- if ltx.__tag and ltx.__tag.struct and ltx.__tag.struct[num] then
-  for k,v in ipairs(ltx.__tag.struct[num]) do
-   __tag_log  ("struct "..num..": "..tostring(k).."=>"..tostring(v))
-  end
- else
-  __tag_log   ("struct "..num.." not found ")
- end
-end
-
--- pay attention: lua counts arrays from 1, tex pages from one
--- mcid and arrays in pdf count from 0.
-function ltx.__tag.func.store_mc_in_page (mcnum,mcpagecnt,page)
- ltx.__tag.page[page] = ltx.__tag.page[page] or {}
- ltx.__tag.page[page][mcpagecnt] = mcnum
- ltx.__tag.trace.log("PAGE " .. page .. ": inserting MCID " .. mcpagecnt .. " => " .. mcnum,3)
-end
-
 function ltx.__tag.func.fill_parent_tree_line (page)
      -- we need to get page-> i=kid -> mcnum -> structnum
      -- pay attention: the kid numbers and the page number in the parent tree start with 0!
@@ -620,9 +658,12 @@
     local pdfpage = page-1
     if ltx.__tag.page[page] and ltx.__tag.page[page][0] then
      mcchunks=#ltx.__tag.page[page]
-     ltx.__tag.trace.log("PAGETREE PAGE "..page.." has "..mcchunks.."+1 Elements ",3)
+     ltx.__tag.trace.log("INFO PARENTTREE-NUM:  page "..
+                   page.." has "..mcchunks.."+1 Elements ",4)
      for i=0,mcchunks do
-      ltx.__tag.trace.log("PAGETREE CHUNKS "..ltx.__tag.page[page][i],3)
+     -- what does this log??
+      ltx.__tag.trace.log("INFO PARENTTREE-CHUNKS:  "..
+        ltx.__tag.page[page][i],4)
      end
      if mcchunks == 0 then
       -- only one chunk so no need for an array
@@ -629,10 +670,13 @@
       local mcnum  = ltx.__tag.page[page][0]
       local structnum = ltx.__tag.mc[mcnum]["parent"]
       local propname  = "g__tag_struct_"..structnum.."_prop"
-      local objref   =  ltx.__tag.tables[propname]["objref"] or "XXXX"
-      ltx.__tag.trace.log("=====>"..tostring(objref),5)
+      --local objref   =  ltx.__tag.tables[propname]["objref"] or "XXXX"
+      local objref = __tag_pdf_object_ref('__tag/struct/'..structnum)
+      ltx.__tag.trace.log("INFO PARENTTREE-STRUCT-OBJREF:  =====>"..
+        tostring(objref),5)
       numsentry = pdfpage .. " [".. objref .. "]"
-      ltx.__tag.trace.log("PAGETREE PAGE" .. page.. " NUM ENTRY = ".. numsentry,3)
+      ltx.__tag.trace.log("INFO PARENTTREE-NUMENTRY: page " ..
+        page.. " num entry = ".. numsentry,3)
      else
       numsentry = pdfpage .. " ["
        for i=0,mcchunks do
@@ -639,14 +683,16 @@
         local mcnum  = ltx.__tag.page[page][i]
         local structnum = ltx.__tag.mc[mcnum]["parent"] or 0
         local propname  = "g__tag_struct_"..structnum.."_prop"
-        local objref   =  ltx.__tag.tables[propname]["objref"] or "XXXX"
+        --local objref   =  ltx.__tag.tables[propname]["objref"] or "XXXX"
+        local objref = __tag_pdf_object_ref('__tag/struct/'..structnum)
         numsentry = numsentry .. " ".. objref
        end
       numsentry = numsentry .. "] "
-      ltx.__tag.trace.log("PAGETREE PAGE" .. page.. " NUM ENTRY = ".. numsentry,3)
+      ltx.__tag.trace.log("INFO PARENTTREE-NUMENTRY: page " ..
+        page.. " num entry = ".. numsentry,3)
      end
     else
-      ltx.__tag.trace.log ("PAGETREE: NO DATA FOR PAGE "..page,3)
+      ltx.__tag.trace.log ("INFO PARENTTREE-NO-DATA: page "..page,3)
     end
     return numsentry
 end
@@ -657,6 +703,5 @@
   tex.sprint(catlatex,line)
  end
 end
-
 -- 
 --  End of File `tagpdf.lua'.

Modified: trunk/Master/texmf-dist/tex/latex/tagpdf/tagpdf.sty
===================================================================
--- trunk/Master/texmf-dist/tex/latex/tagpdf/tagpdf.sty	2021-06-30 20:41:50 UTC (rev 59768)
+++ trunk/Master/texmf-dist/tex/latex/tagpdf/tagpdf.sty	2021-06-30 21:14:14 UTC (rev 59769)
@@ -5,8 +5,16 @@
 %% The original source files were:
 %%
 %% tagpdf.dtx  (with options: `package')
+%% tagpdf-checks.dtx  (with options: `package')
+%% tagpdf-user.dtx  (with options: `package')
+%% tagpdf-mc-shared.dtx  (with options: `shared')
+%% tagpdf.dtx  (with options: `mcloading')
+%% tagpdf-tree.dtx  (with options: `package')
+%% tagpdf-roles.dtx  (with options: `package')
+%% tagpdf-struct.dtx  (with options: `package')
+%% tagpdf-space.dtx  (with options: `package')
 %% 
-%% Copyright (C) 2019 Ulrike Fischer
+%% Copyright (C) 2019-2021 Ulrike Fischer
 %% 
 %% It may be distributed and/or modified under the conditions of
 %% the LaTeX Project Public License (LPPL), either version 1.3c of
@@ -19,7 +27,7 @@
 %% and all files in that bundle must be distributed together.
 %% 
 %% File: tagpdf.dtx
-\ProvidesExplPackage {tagpdf} {2021-06-14} {0.82}
+\ProvidesExplPackage {tagpdf} {2021-06-29} {0.9}
   { A package to experiment with pdf tagging }
 
 \bool_if:nF
@@ -41,29 +49,16 @@
        before~\string\documentclass
      }
   }
-
-
 \prop_if_exist:NT \g_msg_module_name_prop
   {
     \prop_gput:Nnn \g_msg_module_name_prop { tag }{ tagpdf }
   }
-
-\cs_set_eq:NN \__tag_tex_global:D              \tex_global:D
-
-%%% package options
 \bool_new:N\g__tag_mode_lua_bool
-
 \DeclareOption {luamode}    { \sys_if_engine_luatex:T { \bool_gset_true:N \g__tag_mode_lua_bool } }
 \DeclareOption {genericmode}{ \bool_gset_false:N\g__tag_mode_lua_bool }
 \ExecuteOptions{luamode}
 \ProcessOptions
-
-%%% some packages
 \RequirePackage{l3ref-tmp}
- %================
- % temporary code
- % ===============
- % faking the LastPage label:
  \cs_new_protected:Npn \__tag_lastpagelabel:
    {
      \legacy_if:nT { @filesw }
@@ -82,8 +77,6 @@
 
  \AddToHook{enddocument/afterlastpage}
   {\__tag_lastpagelabel:}
-
- % a command to override the general default. See issue in ref
  \cs_if_exist:NF \ref_value:nnn
    {
      \cs_new:Npn \ref_value:nnn #1#2#3
@@ -97,31 +90,56 @@
          \tl_if_exist:cTF { g__ref_label_ #1 _ #2 _tl }
            { \tl_use:c { g__ref_label_ #1 _ #2 _tl } }
            {
-             % test if attribute exist at all?
              #3
            }
        }
    }
 
- %=============
- % attributes
- %=============
-\ref_attribute_gset:nnnn {tagstruct}    {0}{now}    { \int_use:N \c at g__tag_struct_abs_int }
-\ref_attribute_gset:nnnn {tagstructobj} {}{now}
- {
-  \exp_args:Ne
-   \pdf_object_if_exist:nT {__tag/struct/\int_use:N \c at g__tag_struct_abs_int}
-    {
-      \pdf_object_ref:e{__tag/struct/\int_use:N \c at g__tag_struct_abs_int}
-    }
- }
- % replace by abspage??
-\ref_attribute_gset:nnnn {tagabspage}{0}{shipout}{ \int_use:N \g_shipout_readonly_int }
-\ref_attribute_gset:nnnn {tagmcabs } {0}{now}    { \int_use:N \c at g__tag_MCID_abs_int }
-\ref_attribute_gset:nnnn {tagmcid }  {0}{now}    { \int_use:N \g__tag_MCID_tmp_bypage_int }
-\clist_const:Nn \c__tag_refmc_clist     {tagabspage,tagmcabs,tagmcid} %mc is new!!
+\tl_new:N    \l__tag_tmpa_tl
+\str_new:N   \l__tag_tmpa_str
+\prop_new:N  \l__tag_tmpa_prop
+\seq_new:N   \l__tag_tmpa_seq
+\seq_new:N   \l__tag_tmpb_seq
+\clist_new:N \l__tag_tmpa_clist
+\int_new:N   \l__tag_tmpa_int
+\clist_const:Nn \c__tag_refmc_clist     {tagabspage,tagmcabs,tagmcid}
 \clist_const:Nn \c__tag_refstruct_clist {tagstruct,tagstructobj}
+\int_new:N  \l__tag_loglevel_int
+\bool_new:N \g__tag_active_space_bool
+\bool_new:N \g__tag_active_mc_bool
+\bool_new:N \g__tag_active_tree_bool
+\bool_new:N \g__tag_active_struct_bool
+
+\bool_new:N \l__tag_active_mc_bool
+\bool_set_true:N \l__tag_active_mc_bool
+\bool_new:N \l__tag_active_struct_bool
+\bool_set_true:N \l__tag_active_struct_bool
+\bool_new:N \g__tag_tagunmarked_bool
+\prg_generate_conditional_variant:Nnn \pdf_object_if_exist:n {e}{T,F}
+\cs_generate_variant:Nn \pdf_object_ref:n {e}
+\cs_generate_variant:Nn \pdfannot_dict_put:nnn {nnx}
+\cs_generate_variant:Nn \pdffile_embed_stream:nnn {nxx,oxx}
+\cs_generate_variant:Nn \prop_gput:Nnn {Nxx}
+\cs_generate_variant:Nn \prop_put:Nnn  {Nxx}
 \cs_generate_variant:Nn \ref_label:nn { nv }
+\cs_generate_variant:Nn \seq_set_split:Nnn{Nne}
+\cs_generate_variant:Nn \str_set_convert:Nnnn {Nonn, Noon, Nnon }
+
+\ref_attribute_gset:nnnn { tagstruct } {0} { now }
+  { \int_use:N \c at g__tag_struct_abs_int }
+\ref_attribute_gset:nnnn { tagstructobj } {} { now }
+  {
+    \pdf_object_if_exist:eT {__tag/struct/\int_use:N \c at g__tag_struct_abs_int}
+      {
+        \pdf_object_ref:e{__tag/struct/\int_use:N \c at g__tag_struct_abs_int}
+      }
+  }
+\ref_attribute_gset:nnnn { tagabspage } {0} { shipout }
+  { \int_use:N \g_shipout_readonly_int }
+\ref_attribute_gset:nnnn { tagmcabs } {0} { now }
+  { \int_use:N \c at g__tag_MCID_abs_int }
+\ref_attribute_gset:nnnn {tagmcid }  {0} { now }
+  { \int_use:N \g__tag_MCID_tmp_bypage_int }
 \cs_new_protected:Npn \__tag_ref_label:nn #1 #2 %#1 label, #2 name of list mc or struct
   {
     \@bsphack
@@ -128,35 +146,50 @@
     \ref_label:nv {#1}{c__tag_ref#2_clist}
     \@esphack
   }
+\cs_generate_variant:Nn \__tag_ref_label:nn {en}
 \cs_new:Npn \__tag_ref_value:nnn #1 #2 #3 %#1 label, #2 attribute, #3 default
   {
     \ref_value:nnn {#1}{#2}{#3}
   }
+\cs_generate_variant:Nn \__tag_ref_value:nnn {enn}
 \cs_new:Npn \__tag_ref_value_lastpage:nn #1 #2
   {
     \ref_value:nnn {__tag_LastPage}{#1}{#2}
   }
 
-\cs_generate_variant:Nn \__tag_ref_label:nn {en}
-\cs_generate_variant:Nn \__tag_ref_value:nnn {enn}
+\cs_set_eq:NN \__tag_prop_new:N        \prop_new:N
+\cs_set_eq:NN \__tag_seq_new:N         \seq_new:N
+\cs_set_eq:NN \__tag_prop_gput:Nnn     \prop_gput:Nnn
+\cs_set_eq:NN \__tag_seq_gput_right:Nn \seq_gput_right:Nn
+\cs_set_eq:NN \__tag_seq_item:cn       \seq_item:cn
+\cs_set_eq:NN \__tag_prop_item:cn      \prop_item:cn
+\cs_set_eq:NN \__tag_seq_show:N        \seq_show:N
+\cs_set_eq:NN \__tag_prop_show:N       \prop_show:N
 
-\RequirePackage{etoolbox}
+\cs_generate_variant:Nn \__tag_prop_gput:Nnn      { Nxn , Nxx, Nnx , cnn, cxn, cnx, cno}
+\cs_generate_variant:Nn \__tag_seq_gput_right:Nn  { Nx  , No, cn, cx }
+\cs_generate_variant:Nn \__tag_prop_new:N   { c }
+\cs_generate_variant:Nn \__tag_seq_new:N    { c }
+\cs_generate_variant:Nn \__tag_seq_show:N   { c }
+\cs_generate_variant:Nn \__tag_prop_show:N  { c }
 
-\cs_generate_variant:Nn \str_set_convert:Nnnn {Nonn, Noon, Nnon }
+\cs_new_protected:Npn \tag_stop_group_begin:
+  {
+    \group_begin:
+    \bool_set_false:N \l__tag_active_struct_bool
+    \bool_set_false:N \l__tag_active_mc_bool
+  }
+\cs_set_eq:NN \tag_stop_group_end: \group_end:
 
-%%% tagpdfsetup,
-%%% TODO: checks need to be improved
-\int_new:N  \l__tag_loglevel_int
-\tl_new:N   \l__tag_tree_tabs_order_tl
-
 \keys_define:nn { __tag / setup }
   {
+    activate-space  .bool_gset:N = \g__tag_active_space_bool,
     activate-mc     .bool_gset:N = \g__tag_active_mc_bool,
     activate-tree   .bool_gset:N = \g__tag_active_tree_bool,
     activate-struct .bool_gset:N = \g__tag_active_struct_bool,
-    activate-all    .meta:n ={activate-mc,activate-tree,activate-struct},
-    check-tags      .bool_gset:N = \g__tag_check_tags_bool,
-    check-tags      .initial:n  = true,
+    activate-all    .meta:n =
+      {activate-mc,activate-tree,activate-struct},
+ %    \end{macrocode}
     log             .choice:,
     log / none      .code:n = {\int_set:Nn \l__tag_loglevel_int { 0 }},
     log / v         .code:n = {\int_set:Nn \l__tag_loglevel_int { 1 }},
@@ -166,109 +199,2097 @@
     tagunmarked     .bool_gset:N = \g__tag_tagunmarked_bool,
     tagunmarked     .initial:n  = true,
     tabsorder       .choice:,
-    tabsorder / row       .code:n = %{\tl_set:Nn \l__tag_tree_tabs_order_tl {/Tabs/R}},
+    tabsorder / row       .code:n =
       \pdfmanagement_add:nnn { Page } {Tabs}{/R},
-    tabsorder / column    .code:n = %{\tl_set:Nn \l__tag_tree_tabs_order_tl {/Tabs/C}},
+    tabsorder / column    .code:n =
       \pdfmanagement_add:nnn { Page } {Tabs}{/C},
-    tabsorder / structure .code:n = %{\tl_set:Nn \l__tag_tree_tabs_order_tl {/Tabs/S}},
+    tabsorder / structure .code:n =
       \pdfmanagement_add:nnn { Page } {Tabs}{/S},
-    tabsorder / none      .code:n = %{\tl_set:Nn \l__tag_tree_tabs_order_tl {}},
+    tabsorder / none      .code:n =
       \pdfmanagement_remove:nn {Page} {Tabs},
     tabsorder       .initial:n = structure,
-    uncompress      .code:n = {\pdf_uncompress:  },
-    global-mc .code:n =
+    uncompress      .code:n = { \pdf_uncompress:  },
+  }
+\sys_if_engine_luatex:T
+  {
+    \file_input:n {tagpdf-luatex.def}
+  }
+%% File: tagpdf-checks.dtx
+
+\msg_new:nnn { tag } {mc-nested} { nested~marked~content~found~-~mcid~#1 }
+\msg_new:nnn { tag } {mc-tag-missing} { required~tag~missing~-~mcid~#1 }
+\msg_new:nnn { tag } {mc-label-unknown}
+  { label~#1~unknown~or~has~been~already~used.\\
+    Either~rerun~or~remove~one~of~the~uses. }
+\msg_new:nnn { tag } {mc-used-twice} { mc~#1~has~been~already~used }
+\msg_new:nnn { tag } {mc-not-open} { there~is~no~mc~to~end~at~#1 }
+\msg_new:nnn { tag } {mc-pushed} { #1~has~been~pushed~to~the~mc~stack}
+\msg_new:nnn { tag } {mc-popped} { #1~has~been~removed~from~the~mc~stack }
+\msg_new:nnn { tag } {mc-current}
+  { current~MC:~
+    \bool_if:NTF\g__tag_in_mc_bool
+      {abscnt=\__tag_get_mc_abs_cnt:,~tag=\g__tag_mc_key_tag_tl}
+      {no~MC~open,~current~abscnt=\__tag_get_mc_abs_cnt:"}
+  }
+\msg_new:nnn { tag } {struct-no-objnum} { objnum~missing~for~structure~#1 }
+\msg_new:nnn { tag }
+  {struct-faulty-nesting}
+  { there~is~no~open~structure~on~the~stack }
+\msg_new:nnn { tag } {struct-missing-tag} { a~structure~must~have~a~tag! }
+\msg_new:nnn { tag } {struct-used-twice}
+  { structure~with~label~#1~has~already~been~used}
+\msg_new:nnn { tag } {struct-label-unknown}
+  { structure~with~label~#1~is~unknown~rerun}
+\msg_new:nnn { tag } {struct-show-closing}
+  { closing~structure~#1~tagged~\prop_item:cn{g__tag_struct_#1_prop}{S} }
+\msg_new:nnn { tag } {attr-unknown}  { attribute~#1~is~unknown}
+\msg_new:nnn { tag } {role-missing}     { tag~#1~has~no~role~assigned  }
+\msg_new:nnn { tag } {role-unknown}     { role~#1~is~not~known  }
+\msg_new:nnn { tag } {role-unknown-tag} { tag~#1~is~not~known  }
+\msg_new:nnn { tag } {role-tag}         { mapping~tag~#1~to~role~#2  }
+\msg_new:nnn { tag } {new-tag}          { adding~new~tag~#1 }
+\msg_new:nnn { tag } {tree-mcid-index-wrong}
+  {something~is~wrong~with~the~mcid--rerun}
+\msg_new:nnn { tag } {sys-no-interwordspace}
+  {engine/output~mode~#1~doesn't~support~the~interword~spaces}
+\cs_new:Npn \tag_get:n #1   { \use:c {__tag_get_data_#1: } }
+\prg_new_conditional:Npnn \tag_if_active: { p , T , TF, F }
+  {
+     \bool_lazy_all:nTF
+       {
+         {\g__tag_active_struct_bool}
+         {\g__tag_active_mc_bool}
+         {\g__tag_active_tree_bool}
+         {\l__tag_active_struct_bool}
+         {\l__tag_active_mc_bool}
+       }
+       {
+         \prg_return_true:
+       }
+       {
+         \prg_return_false:
+       }
+  }
+\prg_new_conditional:Npnn \__tag_check_if_active_mc: {T,F,TF}
+  {
+    \bool_lazy_and:nnTF { \g__tag_active_mc_bool } { \l__tag_active_mc_bool }
       {
-        \cs_set_eq:NN\__tag_attribute_set:Nn \__tag_attribute_gset:Nn
-        \cs_set_eq:NN\__tag_attribute_unset:N\__tag_attribute_gunset:N
+         \prg_return_true:
       }
+      {
+         \prg_return_false:
+      }
   }
-\hook_gput_code:nnn{begindocument}{tagpdf}
+\prg_new_conditional:Npnn \__tag_check_if_active_struct: {T,F,TF}
   {
-    \bool_if:NT \g__tag_active_struct_bool
+    \bool_lazy_and:nnTF { \g__tag_active_struct_bool } { \l__tag_active_struct_bool }
       {
-         \pdfmanagement_add:nnn { Catalog / MarkInfo } { Marked } { true }
+         \prg_return_true:
       }
-    \keys_define:nn { __tag / setup }
+      {
+         \prg_return_false:
+      }
+  }
+\cs_new_protected:Npn \__tag_check_structure_has_tag:n #1 %#1 struct num
+  {
+    \prop_if_in:cnF { g__tag_struct_#1_prop }
+      {S}
+      {
+        \msg_error:nn { tag } {struct-missing-tag}
+      }
+  }
+\cs_new_protected:Npn \__tag_check_structure_tag:N #1
+  {
+    \prop_if_in:NoF \g__tag_role_tags_prop {#1}
+      {
+        \msg_warning:nnx { tag } {role-unknown-tag} {#1}
+      }
+  }
+\cs_new_protected:Npn \__tag_check_info_closing_struct:n #1 %#1 struct num
+  {
+    \int_compare:nNnT {\l__tag_loglevel_int} > { 0 }
+      {
+        \msg_info:nnn { tag } {struct-show-closing} {#1}
+      }
+  }
+
+\cs_generate_variant:Nn \__tag_check_info_closing_struct:n {o,x}
+\cs_new_protected:Npn \__tag_check_no_open_struct:
+  {
+    \msg_error:nn { tag } {struct-faulty-nesting}
+  }
+\cs_new_protected:Npn \__tag_check_struct_used:n #1 %#1 label
+  {
+    \prop_get:cnNT
+      {g__tag_struct_\__tag_ref_value:enn{tagpdfstruct-#1}{tagstruct}{unknown}_prop}
+      {P}
+      \l_tmpa_tl
+      {
+        \msg_warning:nnn { tag } {struct-used-twice} {#1}
+      }
+  }
+\cs_new_protected:Npn \__tag_check_add_tag_role:nn #1 #2 %#1 tag, #2 role
+  {
+    \tl_if_empty:nTF {#2}
+      {
+        \msg_warning:nnn { tag } {role-missing} {#1}
+      }
+      {
+        \prop_get:NnNTF \g__tag_role_tags_prop {#2} \l_tmpa_tl
+          {
+            \int_compare:nNnT {\l__tag_loglevel_int} > { 0 }
+              {
+                \msg_info:nnnn { tag } {role-tag} {#1} {#2}
+              }
+          }
+          {
+            \msg_warning:nnn { tag } {role-unknown} {#2}
+          }
+      }
+  }
+\cs_new_protected:Npn \__tag_check_mc_if_nested:
+  {
+    \__tag_mc_if_in:T
+      {
+        \msg_warning:nnx { tag } {mc-nested} { \__tag_get_mc_abs_cnt: }
+      }
+  }
+
+\cs_new_protected:Npn \__tag_check_mc_if_open:
+  {
+    \__tag_mc_if_in:F
+      {
+        \msg_warning:nnx { tag } {mc-not-open} { \__tag_get_mc_abs_cnt: }
+      }
+  }
+\cs_new_protected:Npn \__tag_check_mc_pushed_popped:nn #1 #2
+  {
+    \int_compare:nNnT
+      { \l__tag_loglevel_int } ={ 2 }
+      { \msg_info:nnx {tag}{mc-#1}{#2} }
+    \int_compare:nNnT
+      { \l__tag_loglevel_int } > { 2 }
+      {
+        \msg_info:nnx {tag}{mc-#1}{#2}
+        \seq_log:N \g__tag_mc_stack_seq
+      }
+  }
+\cs_new_protected:Npn \__tag_check_mc_tag:N #1  %#1 is var with a tag name in it
+  {
+    \tl_if_empty:NT #1
+      {
+        \msg_error:nnx { tag } {mc-tag-missing} { \__tag_get_mc_abs_cnt: }
+      }
+   \prop_if_in:NoF \g__tag_role_tags_NS_prop {#1}
      {
-       global-mc .code:n={}
+       \msg_warning:nnx { tag } {role-unknown-tag} {#1}
      }
   }
+\cs_new_protected:Npn \__tag_check_init_mc_used:
+  {
+    \intarray_new:Nn \g__tag_check_mc_used_intarray { 65536 }
+    \cs_gset_eq:NN \__tag_check_init_mc_used: \prg_do_nothing:
+  }
+\cs_new_protected:Npn \__tag_check_mc_used:n #1 %#1 mcid abscnt
+  {
+    \int_compare:nNnT {\l__tag_loglevel_int} > { 2 }
+      {
+        \__tag_check_init_mc_used:
+        \intarray_gset:Nnn \g__tag_check_mc_used_intarray
+          {#1}
+          { \intarray_item:Nn \g__tag_check_mc_used_intarray {#1} + 1 }
+        \int_compare:nNnT
+          {
+            \intarray_item:Nn \g__tag_check_mc_used_intarray {#1}
+          }
+          >
+          { 1 }
+          {
+            \msg_warning:nnn { tag } {mc-used-twice} {#1}
+          }
+      }
+  }
+\cs_new_protected:Npn \__tag_check_show_MCID_by_page:
+  {
+    \tl_set:Nx \l__tag_tmpa_tl
+      {
+        \__tag_ref_value_lastpage:nn
+          {abspage}
+          {-1}
+      }
+    \int_step_inline:nnnn {1}{1}
+      {
+        \l__tag_tmpa_tl
+      }
+      {
+        \seq_clear:N \l_tmpa_seq
+        \int_step_inline:nnnn
+          {1}
+          {1}
+          {
+            \__tag_ref_value_lastpage:nn
+              {tagmcabs}
+              {-1}
+          }
+          {
+            \int_compare:nT
+              {
+                \__tag_ref_value:enn
+                  {mcid-####1}
+                  {tagabspage}
+                  {-1}
+                =
+                ##1
+             }
+             {
+               \seq_gput_right:Nx \l_tmpa_seq
+                 {
+                   Page##1-####1-
+                   \__tag_ref_value:enn
+                     {mcid-####1}
+                     {tagmcid}
+                     {-1}
+                 }
+             }
+          }
+          \seq_show:N \l_tmpa_seq
+      }
+  }
+%% File: tagpdf-user.dtx
 
+\NewDocumentCommand \tagpdfsetup { m }
+  {
+    \keys_set:nn { __tag / setup } { #1 }
+  }
 
+\NewDocumentCommand \tagmcbegin { m }
+  {
+    \tag_mc_begin:n {#1}%\ignorespaces
+  }
 
-\cs_new:Nn   \__tag_finish_page_hook: { }
+\NewDocumentCommand \tagmcend {  }
+  {
+    %\if_mode_horizontal: \unskip \fi: %
+    \tag_mc_end:
+  }
 
+\NewDocumentCommand \tagmcuse { m }
+  {
+    \tag_mc_use:n {#1}
+  }
 
-\hook_gput_code:nnn
-  { shipout/before }
-  { tagpdf/cnt }
+
+\NewDocumentCommand \tagmcifinTF { m m }
   {
-    \__tag_finish_page_hook:
-    %\int_gincr:N \g__tag_abspage_int
+    \tag_mc_if_in:TF { #1 } { #2 }
   }
+\NewDocumentCommand \tagstructbegin { m }
+  {
+    \tag_struct_begin:n {#1}
+  }
 
-\sys_if_engine_xetex:T
-  { %lets try with xelatex ...
-    %\PackageError { tagpdf } { xelatex~is~not~supported~-~aborting } {}
-    %\tex_endinput:D
-    \file_input:n {tagpdf-pdftex.def}
+\NewDocumentCommand \tagstructend {  }
+  {
+   \tag_struct_end:
   }
 
+\NewDocumentCommand \tagstructuse { m }
+  {
+    \tag_struct_use:n {#1}
+  }
+\cs_set_eq:NN\tagpdfifluatexTF \sys_if_engine_luatex:TF
+\cs_set_eq:NN\tagpdfifluatexT  \sys_if_engine_luatex:T
+\cs_set_eq:NN\tagpdfifpdftexT  \sys_if_engine_pdftex:T
+\NewDocumentCommand\ShowTagging { m }
+  {
+    \keys_set:nn { __tag / show }{ #1}
+
+  }
+\keys_define:nn { __tag / show }
+  {
+    mc-data .code:n =
+      {
+        \sys_if_engine_luatex:T
+          {
+            \lua_now:e{ltx.__tag.trace.show_all_mc_data(#1,\__tag_get_mc_abs_cnt:,0)}
+          }
+      }
+    ,mc-data .default:n = 1
+  }
+
+\keys_define:nn { __tag / show }
+  { mc-current .code:n =
+     {
+       \bool_if:NTF \g__tag_mode_lua_bool
+         {
+           \sys_if_engine_luatex:T
+             {
+               \int_compare:nNnTF
+                 { -2147483647 }
+                  =
+                 {
+                   \lua_now:e
+                     {
+                        tex.print
+                         (tex.getattribute
+                           (luatexbase.attributes.g__tag_mc_cnt_attr))
+                     }
+                 }
+                 {
+                   \lua_now:e
+                     {
+                       ltx.__tag.trace.log
+                        (
+                          "mc-current:~no~MC~open,~current~abscnt
+                           =\__tag_get_mc_abs_cnt:"
+                          ,0
+                        )
+                       texio.write_nl("")
+                     }
+                 }
+                 {
+                   \lua_now:e
+                     {
+                       ltx.__tag.trace.log
+                        (
+                          "mc-current:~abscnt=\__tag_get_mc_abs_cnt:=="
+                           ..
+                           tex.getattribute(luatexbase.attributes.g__tag_mc_cnt_attr)
+                           ..
+                           "~=>tag="
+                           ..
+                           tostring
+                             (ltx.__tag.func.get_tag_from
+                               (tex.getattribute
+                                 (luatexbase.attributes.g__tag_mc_type_attr)))
+                           ..
+                           "="
+                           ..
+                           tex.getattribute
+                            (luatexbase.attributes.g__tag_mc_type_attr)
+                           ,0
+                        )
+                       texio.write_nl("")
+                     }
+                 }
+             }
+         }
+         {
+          \msg_note:nn{ tag }{ mc-current }
+         }
+     }
+  }
+\keys_define:nn { __tag / show }
+  {
+     struct-stack .choice:
+    ,struct-stack / log .code:n = \seq_log:N \g__tag_struct_tag_stack_seq
+    ,struct-stack / show .code:n = \seq_show:N \g__tag_struct_tag_stack_seq
+    ,struct-stack .default:n = show
+  }
+\cs_new_protected:Npn \__tag_add_document_structure:n #1
+ {
+   \hook_gput_code:nnn{begindocument}{tagpdf}{\tagstructbegin{tag=#1}}
+   \hook_gput_code:nnn{tagpdf/finish/before}{tagpdf}{\tagstructend}
+ }
+\keys_define:nn { __tag / setup}
+ {
+   activate   .code:n =
+    {
+      \keys_set:nn { __tag / setup }
+        { activate-mc,activate-tree,activate-struct }
+      \__tag_add_document_structure:n {#1}
+    },
+  activate .default:n = Document
+ }
 \sys_if_engine_luatex:T
   {
-    \file_input:n {tagpdf-luatex.def}
+    \NewDocumentCommand\pdffakespace { }
+     {
+       \__tag_fakespace:
+     }
   }
+\bool_new:N \l__tag_para_bool
+\bool_new:N \l__tag_para_show_bool
+\int_new:N  \g__tag_para_int
+\keys_define:nn { __tag / setup }
+  {
+    paratagging      .bool_set:N = \l__tag_para_bool,
+    paratagging-show .bool_set:N = \l__tag_para_show_bool,
+  }
 
-\sys_if_engine_pdftex:T
+\AddToHook{para/begin}
   {
-    \file_input:n {tagpdf-pdftex.def}
+   \int_gincr:N \g__tag_para_int
+   \bool_if:NT \l__tag_para_bool
+     {
+       \tag_struct_begin:n {tag=P}
+       \bool_if:NT \l__tag_para_show_bool
+        { \tag_mc_begin:n{artifact}
+          \llap{\color_select:n{red}\tiny\int_use:N\g__tag_para_int\ }
+          \tag_mc_end:
+        }
+       \tag_mc_begin:n {tag=P}
+     }
   }
+\AddToHook{para/end}
+  {
+    \bool_if:NT \l__tag_para_bool
+      {
+        \tag_mc_end:
+        \bool_if:NT \l__tag_para_show_bool
+          { \tag_mc_begin:n{artifact}
+            \rlap{\color_select:n{red}\tiny\ \int_use:N\g__tag_para_int}
+            \tag_mc_end:
+          }
+        \tag_struct_end:
+      }
+  }
+\newcommand\tagpdfparaOn {\bool_set_true:N \l__tag_para_bool}
+\newcommand\tagpdfparaOff{\bool_set_false:N \l__tag_para_bool}
+\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:nnx
+      { link/URI }
+      { StructParent }
+      { \tag_struct_parent_int: }
+  }
 
-\sys_if_output_dvi:T
+\hook_gput_code:nnn
+  {pdfannot/link/URI/after}
+  {tagpdf}
   {
-    %\PackageError { tagpdf } { dvi~output~is~not~supported~-~aborting }{}
-    %\tex_endinput:D
+     \tag_struct_insert_annot:xx {\pdfannot_link_ref_last:}{\tag_struct_parent_int:}
+     \tag_mc_end:
+     \tag_struct_end:
+     \tag_mc_begin_pop:n{}
   }
 
-\cs_generate_variant:Nn \__tag_prop_gput:Nnn      { Nxn , Nxx, Nnx , cnn, cxn, cnx, cno}
-\cs_generate_variant:Nn \__tag_seq_gput_right:Nn  { Nx  , No, cn, cx }
-\cs_generate_variant:Nn \__tag_prop_new:N   { c }
-\cs_generate_variant:Nn \__tag_seq_new:N    { c }
-\cs_generate_variant:Nn \__tag_seq_show:N   { c }
-\cs_generate_variant:Nn \__tag_prop_show:N  { c }
-\cs_generate_variant:Nn \prop_gput:Nnn {Nxx}
-\cs_generate_variant:Nn \prop_put:Nnn  {Nxx}
+\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:nnx
+       { link/GoTo }
+       { StructParent }
+       { \tag_struct_parent_int: }
+  }
 
-\cs_generate_variant:Nn \pdffile_embed_stream:nnn {nxx,oxx}
-\cs_generate_variant:Nn \pdf_object_ref:n {e}
+\hook_gput_code:nnn
+  {pdfannot/link/GoTo/after}
+  {tagpdf}
+  {
+    \tag_struct_insert_annot:xx {\pdfannot_link_ref_last:}{\tag_struct_parent_int:}
+    \tag_mc_end:
+    \tag_struct_end:
+    \tag_mc_begin_pop:n{}
 
-\tl_new:N \g__tag_tmpa_tl
-\tl_new:N \l__tag_tmpa_tl
-\tl_new:N \l__tag_tmpb_tl
-\tl_new:N \l__tag_tmpc_tl
-\tl_new:N \l__tag_tmpd_tl
-\tl_new:N \l__tag_tmpe_tl
-\str_new:N \l__tag_tmpa_str
+  }
 
-\cs_new:Nn\__tag_prop_count:nn { + 1 }
+\pdfannot_dict_put:nnn
+ { link/URI }
+ { Contents }
+ { (url) }
 
-%% Loading the tagpdf sub packages
-\RequirePackage { tagpdf-checks-code }
-\RequirePackage { tagpdf-user }
-\RequirePackage { tagpdf-tree-code }
-\RequirePackage { tagpdf-roles-code }
-\RequirePackage { tagpdf-attr-code }
-\RequirePackage { tagpdf-mc-code-shared }
+\pdfannot_dict_put:nnn
+ { link/GoTo }
+ { Contents }
+ { (ref) }
+
+%% File: tagpdf-mc.dtx
+
+\newcounter { g__tag_MCID_abs_int }
+\cs_new:Npn \__tag_get_mc_abs_cnt: { \int_use:N \c at g__tag_MCID_abs_int }
+\int_new:N \g__tag_MCID_tmp_bypage_int
+\__tag_prop_new:N \g__tag_mc_parenttree_prop
+\seq_new:N \g__tag_mc_stack_seq
+\tl_new:N \l__tag_mc_artifact_type_tl
+\bool_new:N \l__tag_mc_key_stash_bool
+\bool_new:N \l__tag_mc_artifact_bool
+\tl_new:N \l__tag_mc_key_tag_tl
+\tl_new:N \g__tag_mc_key_tag_tl
+\tl_new:N \l__tag_mc_key_label_tl
+\tl_new:N \l__tag_mc_key_properties_tl
+\cs_new:Nn \__tag_mc_handle_mc_label:n
+  {
+    \__tag_ref_label:en{tagpdf-#1}{mc}
+  }
+\cs_new_protected:Npn \__tag_mc_set_label_used:n #1 %#1 labelname
+  {
+    \tl_new:c { g__tag_mc_label_\tl_to_str:n{#1}_used_tl }
+  }
+\cs_new_protected:Npn \tag_mc_use:n #1 %#1: label name
+  {
+    \__tag_check_if_active_struct:T
+      {
+        \tl_set:Nx  \l__tag_tmpa_tl { \__tag_ref_value:nnn{tagpdf-#1}{tagmcabs}{} }
+        \tl_if_empty:NTF\l__tag_tmpa_tl
+          {
+            \msg_warning:nnn {tag} {mc-label-unknown} {#1}
+          }
+          {
+            \cs_if_free:cTF { g__tag_mc_label_\tl_to_str:n{#1}_used_tl }
+              {
+                \__tag_mc_handle_stash:x { \l__tag_tmpa_tl }
+                \__tag_mc_set_label_used:n {#1}
+              }
+              {
+                 \msg_warning:nnn {tag}{mc-used-twice}{#1}
+              }
+          }
+       }
+  }
+\cs_new_protected:Npn \tag_mc_artifact_group_begin:n #1
+ {
+  \tag_mc_end_push:
+  \tag_mc_begin:n {artifact=#1}
+  \tag_stop_group_begin:
+ }
+
+\cs_new_protected:Npn \tag_mc_artifact_group_end:
+ {
+  \tag_stop_group_end:
+  \tag_mc_end:
+  \tag_mc_begin_pop:n{}
+ }
+\cs_new_protected:Npn \tag_mc_end_push:
+  {
+    \__tag_check_if_active_mc:T
+      {
+        \__tag_mc_if_in:TF
+          {
+            \seq_gpush:Nx \g__tag_mc_stack_seq { \tag_get:n {mc_tag} }
+            \__tag_check_mc_pushed_popped:nn
+              { pushed }
+              { \tag_get:n {mc_tag} }
+            \tag_mc_end:
+          }
+          {
+            \seq_gpush:Nn \g__tag_mc_stack_seq {-1}
+            \__tag_check_mc_pushed_popped:nn { pushed }{-1}
+          }
+      }
+  }
+
+\cs_new_protected:Npn \tag_mc_begin_pop:n #1
+  {
+    \__tag_check_if_active_mc:T
+      {
+        \seq_gpop:NNTF \g__tag_mc_stack_seq \l__tag_tmpa_tl
+          {
+            \tl_if_eq:NnTF \l__tag_tmpa_tl {-1}
+              {
+                \__tag_check_mc_pushed_popped:nn {popped}{-1}
+              }
+              {
+                \__tag_check_mc_pushed_popped:nn {popped}{\l__tag_tmpa_tl}
+                \tag_mc_begin:n {tag=\l__tag_tmpa_tl,#1}
+              }
+          }
+          {
+            \__tag_check_mc_pushed_popped:nn {popped}{empty~stack,~nothing}
+          }
+      }
+  }
+\keys_define:nn { __tag / mc }
+  {
+    stash                    .bool_set:N    = \l__tag_mc_key_stash_bool,
+    __artifact-bool          .bool_set:N    = \l__tag_mc_artifact_bool,
+    __artifact-type          .choice:,
+    __artifact-type / pagination .code:n    =
+      {
+        \tl_set:Nn \l__tag_mc_artifact_type_tl { Pagination }
+      },
+    __artifact-type / layout     .code:n    =
+      {
+        \tl_set:Nn \l__tag_mc_artifact_type_tl { Layout }
+      },
+    __artifact-type / page       .code:n    =
+      {
+        \tl_set:Nn \l__tag_mc_artifact_type_tl { Page }
+      },
+    __artifact-type / background .code:n    =
+      {
+        \tl_set:Nn \l__tag_mc_artifact_type_tl { Background }
+      },
+    __artifact-type / notype     .code:n    =
+      {
+        \tl_set:Nn \l__tag_mc_artifact_type_tl {}
+      },
+    __artifact-type /      .code:n    =
+      {
+        \tl_set:Nn \l__tag_mc_artifact_type_tl {}
+      },
+  }
+%% File: tagpdf.dtx
 \bool_if:NTF \g__tag_mode_lua_bool
   {
    \RequirePackage {tagpdf-mc-code-lua}
   }
   {
-   \RequirePackage { tagpdf-mc-code-generic } %
+   \RequirePackage {tagpdf-mc-code-generic} %
   }
+%% File: tagpdf-tree.dtx
+\hook_gput_code:nnn{begindocument}{tagpdf}
+  {
+    \bool_if:NT \g__tag_active_tree_bool
+      {
+        \sys_if_output_pdf:TF
+          {
+            \AddToHook{enddocument/end} { \__tag_finish_structure: }
+          }
+          {
+            \AddToHook{shipout/lastpage} { \__tag_finish_structure: }
+          }
+      }
+  }
+\pdf_object_new:nn { __tag/struct/0 }{ dict }
+\hook_gput_code:nnn{shipout/lastpage}{tagpdf}
+  {
+    \bool_if:NT \g__tag_active_tree_bool
+      {
+        \pdfmanagement_add:nnn { Catalog / MarkInfo } { Marked } { true }
+        \pdfmanagement_add:nnx
+          { Catalog }
+          { StructTreeRoot }
+          { \pdf_object_ref:n { __tag/struct/0 } }
+      }
+  }
+\cs_new_protected:Npn \__tag_tree_write_structtreeroot:
+  {
+     \__tag_prop_gput:cnx
+       { g__tag_struct_0_prop }
+       { ParentTree }
+       { \pdf_object_ref:n { __tag/tree/parenttree } }
+     \__tag_prop_gput:cnx
+       { g__tag_struct_0_prop }
+       { RoleMap }
+       { \pdf_object_ref:n { __tag/tree/rolemap } }
+     \__tag_struct_write_obj:n { 0 }
+  }
+\cs_new_protected:Npn \__tag_tree_write_structelements:
+  {
+    \int_step_inline:nnnn {1}{1}{\c at g__tag_struct_abs_int}
+      {
+        \__tag_struct_write_obj:n { ##1 }
+      }
+  }
+\pdf_object_new:nn { __tag/tree/parenttree }{ dict }
+\newcounter  { g__tag_parenttree_obj_int }
+\hook_gput_code:nnn{begindocument}{tagpdf}
+  {
+    \int_gset:Nn
+      \c at g__tag_parenttree_obj_int
+      { \__tag_ref_value_lastpage:nn{abspage}{100}  }
+  }
+\tl_new:N \g__tag_parenttree_objr_tl
+\cs_new_protected:Npn \__tag_parenttree_add_objr:nn #1 #2 %#1 StructParent number, #2 objref
+  {
+    \tl_gput_right:Nx \g__tag_parenttree_objr_tl
+      {
+        #1 \c_space_tl #2 ^^J
+      }
+  }
+\tl_new:N \l__tag_parenttree_content_tl
 
-\RequirePackage { tagpdf-struct-code }
-\RequirePackage { tagpdf-space-code }
+\cs_new_protected:Npn \__tag_tree_fill_parenttree:
+  {
+    \int_step_inline:nnnn{1}{1}{\__tag_ref_value_lastpage:nn{abspage}{-1}} %not quite clear if labels are needed. See lua code
+      { %page ##1
+        \prop_clear:N \l__tag_tmpa_prop
+        \int_step_inline:nnnn{1}{1}{\__tag_ref_value_lastpage:nn{tagmcabs}{-1}}
+          {
+            %mcid####1
+            \int_compare:nT
+              {\__tag_ref_value:enn{mcid-####1}{tagabspage}{-1}=##1} %mcid is on current page
+              {% yes
+                \prop_put:Nxx
+                  \l__tag_tmpa_prop
+                  {\__tag_ref_value:enn{mcid-####1}{tagmcid}{-1}}
+                  {\prop_item:Nn \g__tag_mc_parenttree_prop {####1}}
+              }
+          }
+        \tl_put_right:Nx\l__tag_parenttree_content_tl
+          {
+            \int_eval:n {##1-1}\c_space_tl
+            [\c_space_tl %]
+          }
+        \int_step_inline:nnnn
+          {0}
+          {1}
+          { \prop_count:N \l__tag_tmpa_prop -1 }
+          {
+            \prop_get:NnNTF \l__tag_tmpa_prop {####1} \l__tag_tmpa_tl
+              {% page#1:mcid##1:\l__tag_tmpa_tl :content
+                \tl_put_right:Nx \l__tag_parenttree_content_tl
+                  {
+                    \pdf_object_if_exist:eT { __tag/struct/\l__tag_tmpa_tl }
+                     {
+                       \pdf_object_ref:e { __tag/struct/\l__tag_tmpa_tl }
+                     }
+                    \c_space_tl
+                  }
+              }
+              {
+                \msg_warning:nn { tag } {tree-mcid-index-wrong}
+              }
+          }
+        \tl_put_right:Nn
+          \l__tag_parenttree_content_tl
+          {%[
+            ]^^J
+          }
+      }
+  }
+\cs_new_protected:Npn \__tag_tree_lua_fill_parenttree:
+  {
+    \tl_set:Nn \l__tag_parenttree_content_tl
+      {
+        \lua_now:e
+          {
+            ltx.__tag.func.output_parenttree
+              (
+                \int_use:N\g_shipout_readonly_int
+              )
+          }
+      }
+  }
+\cs_new_protected:Npn \__tag_tree_write_parenttree:
+  {
+    \bool_if:NTF \g__tag_mode_lua_bool
+      {
+        \__tag_tree_lua_fill_parenttree:
+      }
+      {
+        \__tag_tree_fill_parenttree:
+      }
+    \tl_put_right:NV \l__tag_parenttree_content_tl\g__tag_parenttree_objr_tl
+    \pdf_object_write:nx  { __tag/tree/parenttree }
+      {
+        /Nums\c_space_tl [\l__tag_parenttree_content_tl]
+      }
+  }
+\pdf_object_new:nn { __tag/tree/rolemap }{ dict }
+\cs_new_protected:Npn \__tag_tree_write_rolemap:
+  {
+    \pdf_object_write:nx  { __tag/tree/rolemap }
+      {
+        \pdfdict_use:n{g__tag_role/RoleMap_dict}
+      }
+  }
+\cs_new_protected:Npn \__tag_tree_write_classmap:
+  {
+    \tl_clear:N \l__tag_tmpa_tl
+    \seq_gremove_duplicates:N \g__tag_attr_class_used_seq
+    \seq_set_map:NNn \l__tag_tmpa_seq \g__tag_attr_class_used_seq
+      {
+        /##1\c_space_tl
+        <<
+          \prop_item:Nn
+            \g__tag_attr_entries_prop
+            {##1}
+        >>
+      }
+    \tl_set:Nx \l__tag_tmpa_tl
+      {
+        \seq_use:Nn
+          \l__tag_tmpa_seq
+          { \iow_newline: }
+      }
+    \tl_if_empty:NF
+      \l__tag_tmpa_tl
+      {
+        \pdf_object_new:nn { __tag/tree/classmap }{ dict }
+        \pdf_object_write:nx
+          { __tag/tree/classmap }
+          { \l__tag_tmpa_tl }
+        \__tag_prop_gput:cnx
+          { g__tag_struct_0_prop }
+          { ClassMap }
+          { \pdf_object_ref:n { __tag/tree/classmap }  }
+      }
+  }
+\pdf_object_new:nn{ __tag/tree/namespaces }{array}
+\cs_new_protected:Npn \__tag_tree_write_namespaces:
+  {
+    \prop_map_inline:Nn \g__tag_role_NS_prop
+      {
+        \pdfdict_if_empty:nF {g__tag_role/RoleMapNS_##1_dict}
+          {
+            \pdf_object_write:nx {__tag/RoleMapNS/##1}
+              {
+                \pdfdict_use:n {g__tag_role/RoleMapNS_##1_dict}
+              }
+            \pdfdict_gput:nnx{g__tag_role/Namespace_##1_dict}
+              {RoleMapNS}{\pdf_object_ref:n {__tag/RoleMapNS/##1}}
+          }
+        \pdf_object_write:nx{tag/NS/##1}
+          {
+             \pdfdict_use:n {g__tag_role/Namespace_##1_dict}
+          }
+      }
+    \pdf_object_write:nx {__tag/tree/namespaces}
+      {
+        \prop_map_tokens:Nn \g__tag_role_NS_prop{\use_ii:nn}
+      }
+  }
+\cs_new_protected:Npn \__tag_finish_structure:
+  {
+    \bool_if:NT\g__tag_active_tree_bool
+      {
+        \hook_use:n {tagpdf/finish/before}
+        \__tag_tree_write_parenttree:
+        \__tag_tree_write_rolemap:
+        \__tag_tree_write_classmap:
+        \__tag_tree_write_namespaces:
+        \__tag_tree_write_structelements: %this is rather slow!!
+        \__tag_tree_write_structtreeroot:
+      }
+  }
+\hook_gput_code:nnn{begindocument}{tagpdf}
+  {
+    \bool_if:NT\g__tag_active_tree_bool
+      {
+       \hook_gput_code:nnn{shipout/before} { tagpdf/structparents }
+         {
+           \pdfmanagement_add:nnx
+             { Page }
+             { StructParents }
+             { \int_eval:n { \g_shipout_readonly_int} }
+         }
+      }
+  }
+%% File: tagpdf-roles.dtx
+\__tag_seq_new:N  \g__tag_role_tags_seq  %to get names (type/NS) from numbers
+\__tag_prop_new:N \g__tag_role_tags_prop %to get numbers  from names (type/NS)
+\prop_new:N    \g__tag_role_tags_NS_prop %to namespace info
+\prop_new:N \g__tag_role_NS_prop % collect namespaces
+\tl_new:N \l__tag_role_tag_tmpa_tl
+\tl_new:N \l__tag_role_tag_namespace_tmpa_tl
+\tl_new:N \l__tag_role_role_tmpa_tl
+\tl_new:N \l__tag_role_role_namespace_tmpa_tl
+\cs_new_protected:Npn \__tag_role_NS_new:nnn #1 #2 #3
+  {
+    \pdf_object_new:nn {tag/NS/#1}{dict}
+    \pdfdict_new:n     {g__tag_role/Namespace_#1_dict}
+    \pdf_object_new:nn {__tag/RoleMapNS/#1}{dict}
+    \pdfdict_new:n     {g__tag_role/RoleMapNS_#1_dict}
+    \pdfdict_gput:nnn
+      {g__tag_role/Namespace_#1_dict}
+      {Type}
+      {/Namespace}
+    \pdf_string_from_unicode:nnN{utf8/string}{#2}\l_tmpa_str
+    \tl_if_empty:NF \l_tmpa_str
+      {
+        \pdfdict_gput:nnx
+          {g__tag_role/Namespace_#1_dict}
+          {NS}
+          {\l_tmpa_str}
+      }
+    %RoleMapNS is added in tree
+    \tl_if_empty:nF  {#3}
+     {
+       \pdfdict_gput:nnx{g__tag_role/Namespace_#1_dict}
+        {Schema}{#3}
+     }
+    \prop_gput:Nnx \g__tag_role_NS_prop {#1}{\pdf_object_ref:n{tag/NS/#1}~}
+  }
+\str_const:Nx \c__tag_role_userNS_id_str
+  { data:,
+    \int_to_Hex:n{\int_rand:n {65535}}
+    \int_to_Hex:n{\int_rand:n {65535}}
+    -
+    \int_to_Hex:n{\int_rand:n {65535}}
+    -
+    \int_to_Hex:n{\int_rand:n {65535}}
+    -
+    \int_to_Hex:n{\int_rand:n {65535}}
+    -
+    \int_to_Hex:n{\int_rand:n {16777215}}
+    \int_to_Hex:n{\int_rand:n {16777215}}
+  }
+\pdf_version_compare:NnT > {1.9}
+  {
+    \__tag_role_NS_new:nnn {pdf}   {http://iso.org/pdf/ssn}{}
+    \__tag_role_NS_new:nnn {pdf2}  {http://iso.org/pdf2/ssn}{}
+    \__tag_role_NS_new:nnn {mathml}{http://www.w3.org/1998/Math/MathML}{}
+    \exp_args:Nnx
+    \__tag_role_NS_new:nnn {user}{\c__tag_role_userNS_id_str}{}
+  }
+\clist_const:Nn \c__tag_role_sttags_pdf_pdfII_clist
+  {
+    Document,   %A complete document. This is the root element
+                %of any structure tree containing
+                %multiple parts or multiple articles.
+    Part,       %A large-scale division of a document.
+    Sect,       %A container for grouping related content elements.
+    Div,        %A generic block-level element or group of elements
+    Caption,    %A brief portion of text describing a table or figure.
+    Index,
+    NonStruct,  %probably not needed
+    H,
+    H1,
+    H2,
+    H3,
+    H4,
+    H5,
+    H6,
+    P,
+    L,           %list
+    LI,          %list item (around label and list item body)
+    Lbl,         %list label
+    LBody,       %list item body
+    Table,
+    TR,          %table row
+    TH,          %table header cell
+    TD,          %table data cell
+    THead,       %table header (n rows)
+    TBody,       %table rows
+    TFoot,       %table footer
+    Span,        %generic inline marker
+    Link,        %
+    Annot,
+    Figure,
+    Formula,
+    Form,
+    % ruby warichu etc ..
+    Ruby,
+    RB,
+    RT,
+    Warichu,
+    WT,
+    WP,
+    Artifact % only MC-tag ?...
+  }
+
+\clist_const:Nn \c__tag_role_sttags_only_pdf_clist
+ {
+   Art,        %A relatively self-contained body of text
+               %constituting a single narrative or exposition
+   BlockQuote, %A portion of text consisting of one or more paragraphs
+               %attributed to someone other than the author of the
+               %surrounding text.
+   TOC,        %A list made up of table of contents item entries
+               %(structure tag TOCI; see below) and/or other
+               %nested table of contents entries
+   TOCI,       %An individual member of a table of contents.
+               %This entry's children can be any of the following structure  tags:
+               %Lbl,Reference,NonStruct,P,TOC
+   Index,
+   Private,
+   Quote,       %inline quote
+   Note,        %footnote, endnote. Lbl can be child
+   Reference,   %A citation to content elsewhere in the document.
+   BibEntry,    %bibentry
+   Code
+ }
+
+\clist_const:Nn \c__tag_role_sttags_only_pdfII_clist
+ {
+   DocumentFragment
+   ,Aside
+   ,H7
+   ,H8
+   ,H9
+   ,H10
+   ,Title
+   ,FENote
+   ,Sub
+   ,Em
+   ,Strong
+   ,Artifact
+ }
+
+\clist_const:Nn \c__tag_role_sttags_mathml_clist
+ {
+   abs
+   ,and
+   ,annotation
+   ,apply
+   ,approx
+   ,arccos
+   ,arccosh
+   ,arccot
+   ,arccoth
+   ,arccsc
+   ,arccsch
+   ,arcsec
+   ,arcsech
+   ,arcsin
+   ,arcsinh
+   ,arctan
+   ,arctanh
+   ,arg
+   ,bind
+   ,bvar
+   ,card
+   ,cartesianproduct
+   ,cbytes
+   ,ceiling
+   ,cerror
+   ,ci
+   ,cn
+   ,codomain
+   ,complexes
+   ,compose
+   ,condition
+   ,conjugate
+   ,cos
+   ,cosh
+   ,cot
+   ,coth
+   ,cs
+   ,csc
+   ,csch
+   ,csymbol
+   ,curl
+   ,declare
+   ,degree
+   ,determinant
+   ,diff
+   ,divergence
+   ,divide
+   ,domain
+   ,domainofapplication
+   ,emptyset
+   ,eq
+   ,equivalent
+   ,eulergamma
+   ,exists
+   ,exp
+   ,exponentiale
+   ,factorial
+   ,factorof
+   ,false
+   ,floor
+   ,fn
+   ,forall
+   ,gcd
+   ,geq
+   ,grad
+   ,gt
+   ,ident
+   ,image
+   ,imaginary
+   ,imaginaryi
+   ,implies
+   ,in
+   ,infinity
+   ,int
+   ,integers
+   ,intersect
+   ,interval
+   ,inverse
+   ,lambda
+   ,laplacian
+   ,lcm
+   ,leq
+   ,limit
+   ,ln
+   ,log
+   ,logbase
+   ,lowlimit
+   ,lt
+   ,maction
+   ,maligngroup
+   ,malignmark
+   ,math
+   ,matrix
+   ,matrixrow
+   ,max
+   ,mean
+   ,median
+   ,menclose
+   ,merror
+   ,mfenced
+   ,mfrac
+   ,mglyph
+   ,mi
+   ,min
+   ,minus
+   ,mlabeledtr
+   ,mlongdiv
+   ,mmultiscripts
+   ,mn
+   ,mo
+   ,mode
+   ,moment
+   ,momentabout
+   ,mover
+   ,mpadded
+   ,mphantom
+   ,mprescripts
+   ,mroot
+   ,mrow
+   ,ms
+   ,mscarries
+   ,mscarry
+   ,msgroup
+   ,msline
+   ,mspace
+   ,msqrt
+   ,msrow
+   ,mstack
+   ,mstyle
+   ,msub
+   ,msubsup
+   ,msup
+   ,mtable
+   ,mtd
+   ,mtext
+   ,mtr
+   ,munder
+   ,munderover
+   ,naturalnumbers
+   ,neq
+   ,none
+   ,not
+   ,notanumber
+   ,notin
+   ,notprsubset
+   ,notsubset
+   ,or
+   ,otherwise
+   ,outerproduct
+   ,partialdiff
+   ,pi
+   ,piece
+   ,piecewise
+   ,plus
+   ,power
+   ,primes
+   ,product
+   ,prsubset
+   ,quotient
+   ,rationals
+   ,real
+   ,reals
+   ,reln
+   ,rem
+   ,root
+   ,scalarproduct
+   ,sdev
+   ,sec
+   ,sech
+   ,selector
+   ,semantics
+   ,sep
+   ,set
+   ,setdiff
+   ,share
+   ,sin
+   ,sinh
+   ,subset
+   ,sum
+   ,tan
+   ,tanh
+   ,tendsto
+   ,times
+   ,transpose
+   ,true
+   ,union
+   ,uplimit
+   ,variance
+   ,vector
+   ,vectorproduct
+   ,xor
+ }
+
+\prop_const_from_keyval:Nn \c__tag_role_sttags_pdfII_to_pdf_prop
+  {
+    DocumentFragment = Art,
+    Aside = Note,
+    Title = H1,
+    Sub   = Span,
+    H7    = H6 ,
+    H8    = H6 ,
+    H9    = H6 ,
+    H10   = H6,
+    FENote= Note,
+    Em    = Span,
+    Strong= Span,
+  }
+
+\clist_map_inline:Nn \c__tag_role_sttags_pdf_pdfII_clist
+  {
+    \__tag_seq_gput_right:Nn \g__tag_role_tags_seq { #1 }
+    \prop_gput:Nnn \g__tag_role_tags_NS_prop    { #1 }{ pdf2 }
+  }
+\clist_map_inline:Nn \c__tag_role_sttags_only_pdf_clist
+  {
+    \__tag_seq_gput_right:Nn \g__tag_role_tags_seq { #1 }
+    \prop_gput:Nnn \g__tag_role_tags_NS_prop    { #1 }{ pdf }
+  }
+\clist_map_inline:Nn \c__tag_role_sttags_only_pdfII_clist
+  {
+    \__tag_seq_gput_right:Nn \g__tag_role_tags_seq { #1 }
+    \prop_gput:Nnn \g__tag_role_tags_NS_prop    { #1 }{ pdf2 }
+  }
+\pdf_version_compare:NnT > {1.9}
+  {
+     \clist_map_inline:Nn \c__tag_role_sttags_mathml_clist
+       {
+         \__tag_seq_gput_right:Nn \g__tag_role_tags_seq { #1 }
+         \prop_gput:Nnn \g__tag_role_tags_NS_prop    { #1 }{ mathml }
+       }
+  }
+\int_step_inline:nnnn { 1 }{ 1 }{ \seq_count:N \g__tag_role_tags_seq }
+  {
+    \__tag_prop_gput:Nxn \g__tag_role_tags_prop
+      {
+        \seq_item:Nn \g__tag_role_tags_seq  { #1 }
+      }
+      { #1 }
+  }
+\pdfdict_new:n {g__tag_role/RoleMap_dict}
+\cs_new_protected:Nn \__tag_role_add_tag:nn %(new) name, reference to old
+  {
+    \prop_if_in:NnF \g__tag_role_tags_prop {#1}
+      {
+        \int_compare:nNnT {\l__tag_loglevel_int} > { 0 }
+          {
+            \msg_info:nnn { tag }{new-tag}{#1}
+          }
+         \__tag_seq_gput_right:Nn \g__tag_role_tags_seq { #1 }
+         \__tag_prop_gput:Nnx \g__tag_role_tags_prop    { #1 }
+           {
+             \seq_count:N \g__tag_role_tags_seq
+           }
+         \prop_gput:Nnn \g__tag_role_tags_NS_prop    { #1 }{ user }
+      }
+    \__tag_check_add_tag_role:nn {#1}{#2}
+    \tl_if_empty:nF { #2 }
+      {
+        \pdfdict_gput:nnx {g__tag_role/RoleMap_dict}
+          {#1}
+          {\pdf_name_from_unicode_e:n{#2}}
+      }
+  }
+\cs_generate_variant:Nn \__tag_role_add_tag:nn {VV}
+
+\pdf_version_compare:NnT < {2.0}
+  {
+     \prop_map_inline:Nn \c__tag_role_sttags_pdfII_to_pdf_prop
+       {
+         \__tag_role_add_tag:nn {#1}{#2}
+       }
+  }
+
+\cs_new_protected:Nn \__tag_role_add_tag:nnnn %tag/namespace/role/namespace
+  {
+    \int_compare:nNnT {\l__tag_loglevel_int} > { 0 }
+      {
+        \msg_info:nnn { tag }{new-tag}{#1}
+      }
+    \__tag_seq_gput_right:Nn \g__tag_role_tags_seq { #1 }
+    \__tag_prop_gput:Nnx \g__tag_role_tags_prop    { #1 }
+       {
+         \seq_count:N \g__tag_role_tags_seq
+       }
+    \prop_gput:Nnn \g__tag_role_tags_NS_prop    { #1 }{ #2 }
+    \__tag_check_add_tag_role:nn {#1}{#3}
+    \pdfdict_gput:nnx {g__tag_role/RoleMapNS_#2_dict}{#1}
+       {
+         [
+           \pdf_name_from_unicode_e:n{#3}
+           \c_space_tl
+           \pdf_object_ref:n {tag/NS/#4}
+         ]
+       }
+   }
+\cs_generate_variant:Nn \__tag_role_add_tag:nnnn {VVVV}
+\keys_define:nn { __tag / tag-role }
+  {
+    ,tag .tl_set:N = \l__tag_role_tag_tmpa_tl
+    ,tag-namespace  .tl_set:N = \l__tag_role_tag_namespace_tmpa_tl
+    ,role .tl_set:N = \l__tag_role_role_tmpa_tl
+    ,role-namespace .tl_set:N = \l__tag_role_role_namespace_tmpa_tl
+  }
+
+\keys_define:nn { __tag / setup }
+  {
+    add-new-tag .code:n =
+     {
+       \keys_set_known:nnnN
+         {__tag/tag-role}
+         {
+           tag-namespace=user,
+           role-namespace=, %so that we can test for it.
+          #1
+         }{__tag/tag-role}\l_tmpa_tl
+       \tl_if_empty:NF \l_tmpa_tl
+         {
+           \exp_args:NNno \seq_set_split:Nnn \l_tmpa_seq { / } {\l_tmpa_tl/}
+           \tl_set:Nx \l__tag_role_tag_tmpa_tl  { \seq_item:Nn \l_tmpa_seq {1} }
+           \tl_set:Nx \l__tag_role_role_tmpa_tl { \seq_item:Nn \l_tmpa_seq {2} }
+         }
+      \tl_if_empty:NT \l__tag_role_role_namespace_tmpa_tl
+         {
+           \prop_get:NVNTF
+             \g__tag_role_tags_NS_prop
+             \l__tag_role_role_tmpa_tl
+             \l__tag_role_role_namespace_tmpa_tl
+             {
+                \prop_if_in:NVF\g__tag_role_NS_prop \l__tag_role_role_namespace_tmpa_tl
+                 {
+                   \tl_set:Nn \l__tag_role_role_namespace_tmpa_tl {user}
+                 }
+             }
+             {
+               \tl_set:Nn \l__tag_role_role_namespace_tmpa_tl {user}
+             }
+         }
+      \pdf_version_compare:NnTF < {2.0}
+       {
+        %TODO add check for emptyness?
+          \__tag_role_add_tag:VV
+              \l__tag_role_tag_tmpa_tl
+              \l__tag_role_role_tmpa_tl
+       }
+       {
+         \__tag_role_add_tag:VVVV
+           \l__tag_role_tag_tmpa_tl
+           \l__tag_role_tag_namespace_tmpa_tl
+           \l__tag_role_role_tmpa_tl
+           \l__tag_role_role_namespace_tmpa_tl
+       }
+    }
+  }
+%% File: tagpdf-struct.dtx
+\newcounter  { g__tag_struct_abs_int }
+\int_gzero:N \c at g__tag_struct_abs_int
+\__tag_seq_new:N  \g__tag_struct_objR_seq
+\seq_new:N    \g__tag_struct_stack_seq
+\seq_gpush:Nn \g__tag_struct_stack_seq {0}
+\seq_new:N    \g__tag_struct_tag_stack_seq
+\seq_gpush:Nn \g__tag_struct_tag_stack_seq {Root}
+\tl_new:N     \g__tag_struct_stack_current_tl
+\tl_new:N     \l__tag_struct_stack_parent_tmpa_tl
+
+\seq_const_from_clist:Nn \c__tag_struct_StructTreeRoot_entries_seq
+  {%p. 857/858
+    Type,              % always /StructTreeRoot
+    K,                 % kid, dictionary or array of dictionaries
+    IDTree,            % currently unused
+    ParentTree,        % required,obj ref to the parent tree
+    ParentTreeNextKey, % optional
+    RoleMap,
+    ClassMap,
+    Namespaces
+  }
+
+\seq_const_from_clist:Nn \c__tag_struct_StructElem_entries_seq
+  {%p 858 f
+    Type,              %always /StructElem
+    S,                 %tag/type
+    P,                 %parent
+    ID,                %optional
+    Ref,               %optional, pdf 2.0 Use?
+    Pg,                %obj num of starting page, optional
+    K,                 %kids
+    A,                 %attributes, probably unused
+    C,                 %class ""
+    %R,                %attribute revision number, irrelevant for us as we
+                       % don't update/change existing PDF and (probably)
+                       % deprecated in PDF 2.0
+    T,                 %title, value in () or <>
+    Lang,              %language
+    Alt,               % value in () or <>
+    E,                 % abreviation
+    ActualText,
+    AF,                 %pdf 2.0, array of dict, associated files
+    NS,                 %pdf 2.0, dict, namespace
+    PhoneticAlphabet,   %pdf 2.0
+    Phoneme             %pdf 2.0
+  }
+\tl_new:N \g__tag_struct_tag_tl
+\tl_new:N \g__tag_struct_tag_NS_tl
+\tl_new:N \l__tag_struct_key_label_tl
+\bool_new:N \l__tag_struct_elem_stash_bool
+\cs_new:Npn \__tag_struct_output_prop_aux:nn #1 #2 %#1 num, #2 key
+  {
+    \prop_if_in:cnT
+      { g__tag_struct_#1_prop }
+      { #2 }
+      {
+        \c_space_tl/#2~ \prop_item:cn{ g__tag_struct_#1_prop } { #2 }
+      }
+  }
+
+\cs_new_protected:Npn \__tag_new_output_prop_handler:n #1
+  {
+    \cs_new:cn { __tag_struct_output_prop_#1:n }
+      {
+        \__tag_struct_output_prop_aux:nn {#1}{##1}
+      }
+  }
+\tl_gset:Nn \g__tag_struct_stack_current_tl {0}
+
+\__tag_prop_new:c { g__tag_struct_0_prop }
+\__tag_new_output_prop_handler:n {0}
+\__tag_seq_new:c  { g__tag_struct_kids_0_seq }
+
+\__tag_prop_gput:cnn
+  { g__tag_struct_0_prop }
+  { Type }
+  { /StructTreeRoot }
+
+\__tag_prop_gput:cnx
+  { g__tag_struct_0_prop }
+  { Namespaces }
+  { \pdf_object_ref:n { __tag/tree/namespaces } }
+\cs_new_protected:Npn \__tag_struct_kid_mc_gput_right:nn #1 #2 %#1 structure num, #2 MCID absnum%
+  {
+    \__tag_seq_gput_right:cx
+      { g__tag_struct_kids_#1_seq }
+      {
+        <<
+        /Type \c_space_tl /MCR \c_space_tl
+        /Pg
+          \c_space_tl
+          \pdf_pageobject_ref:n { \__tag_ref_value:enn{mcid-#2}{tagabspage}{1} }
+        /MCID \c_space_tl \__tag_ref_value:enn{mcid-#2}{tagmcid}{1}
+        >>
+      }
+  }
+\cs_new_protected:Npn\__tag_struct_kid_struct_gput_right:nn #1 #2 %#1 num of parent struct, #2 kid struct
+  {
+    \__tag_seq_gput_right:cx
+      { g__tag_struct_kids_#1_seq }
+      {
+        \pdf_object_ref:n { __tag/struct/#2 }
+      }
+ }
+
+\cs_generate_variant:Nn \__tag_struct_kid_struct_gput_right:nn {xx}
+\cs_new_protected:Npn\__tag_struct_kid_OBJR_gput_right:nn #1 #2 %#1 num of parent struct,
+                                                             %#2 obj reference
+  {
+    \pdf_object_unnamed_write:nn
+      { dict }
+      {
+        /Type/OBJR/Obj~#2
+      }
+    \__tag_seq_gput_right:cx
+      { g__tag_struct_kids_#1_seq }
+      {
+        \pdf_object_ref_last:
+      }
+  }
+
+\cs_generate_variant:Nn\__tag_struct_kid_OBJR_gput_right:nn { xx }
+
+\cs_new_protected:Npn\__tag_struct_exchange_kid_command:N #1 %#1 = seq var
+  {
+    \seq_gpop_left:NN #1 \l__tag_tmpa_tl
+    \regex_replace_once:nnN
+      { \c{\__tag_mc_insert_mcid_kids:n} }
+      { \c{\__tag_mc_insert_mcid_single_kids:n} }
+      \l__tag_tmpa_tl
+    \seq_gput_left:NV #1 \l__tag_tmpa_tl
+  }
+
+\cs_generate_variant:Nn\__tag_struct_exchange_kid_command:N { c }
+\cs_new_protected:Npn \__tag_struct_fill_kid_key:n #1 %#1 is the struct num
+  {
+    \int_case:nnF
+      {
+        \seq_count:c
+          {
+            g__tag_struct_kids_#1_seq
+          }
+      }
+      {
+        { 0 }
+         { } %no kids, do nothing
+        { 1 } % 1 kid, insert
+         {
+           % in this case we need a special command in
+           % luamode to get the array right. See issue #13
+           \bool_if:NT\g__tag_mode_lua_bool
+             {
+               \__tag_struct_exchange_kid_command:c
+                {g__tag_struct_kids_#1_seq}
+             }
+           \__tag_prop_gput:cnx { g__tag_struct_#1_prop } {K}
+             {
+               \seq_item:cn
+                 {
+                   g__tag_struct_kids_#1_seq
+                 }
+                 {1}
+             }
+         } %
+      }
+      { %many kids, use an array
+        \__tag_prop_gput:cnx { g__tag_struct_#1_prop } {K}
+          {
+            [
+              \seq_use:cn
+                {
+                  g__tag_struct_kids_#1_seq
+                }
+                {
+                  \c_space_tl
+                }
+            ]
+          }
+      }
+  }
+
+\cs_new_protected:Npn \__tag_struct_get_dict_content:nN #1 #2 %#1: stucture num
+  {
+    \tl_clear:N #2
+    \seq_map_inline:cn
+      {
+        c__tag_struct_
+         \int_compare:nNnTF{#1}={0}{StructTreeRoot}{StructElem}
+         _entries_seq
+      }
+      {
+        \tl_put_right:Nx
+          #2
+          {
+             \prop_if_in:cnT
+               { g__tag_struct_#1_prop }
+               { ##1 }
+               {
+                 \c_space_tl/##1~\prop_item:cn{ g__tag_struct_#1_prop } { ##1 }
+               }
+          }
+      }
+  }
+\cs_new_protected:Npn \__tag_struct_write_obj:n #1 % #1 is the struct num
+  {
+    \pdf_object_if_exist:nTF { __tag/struct/#1 }
+      {
+        \__tag_struct_fill_kid_key:n { #1 }
+        \__tag_struct_get_dict_content:nN { #1 } \l__tag_tmpa_tl
+        \exp_args:Nx
+          \pdf_object_write:nx
+            { __tag/struct/#1 }
+            {
+              \l__tag_tmpa_tl
+            }
+      }
+      {
+        \msg_error:nnn { tag } { struct-no-objnum } { #1}
+      }
+  }
+\cs_new_protected:Npn \__tag_struct_insert_annot:nn #1 #2 %#1 object reference to the annotation/xform
+                                                       %#2 structparent number
+  {
+    \bool_if:NT \g__tag_active_struct_bool
+      {
+        %get the number of the parent structure:
+        \seq_get:NNF
+          \g__tag_struct_stack_seq
+          \l__tag_struct_stack_parent_tmpa_tl
+          {
+            \msg_error:nn { tag } { struct-faulty-nesting }
+          }
+        %put the obj number of the annot in the kid entry, this also creates
+        %the OBJR object
+        \__tag_struct_kid_OBJR_gput_right:xx
+          {
+            \l__tag_struct_stack_parent_tmpa_tl
+          }
+          {
+            #1 %
+          }
+        % add the parent obj number to the parent tree:
+        \exp_args:Nnx
+        \__tag_parenttree_add_objr:nn
+          {
+            #2
+          }
+          {
+            \pdf_object_ref:e { __tag/struct/\l__tag_struct_stack_parent_tmpa_tl }
+          }
+        % increase the int:
+        \stepcounter{ g__tag_parenttree_obj_int }
+      }
+  }
+\cs_new:Npn \__tag_get_data_struct_tag:
+  {
+    \exp_args:Ne
+    \tl_tail:n
+     {
+       \prop_item:cn {g__tag_struct_\g__tag_struct_stack_current_tl _prop}{S}
+     }
+  }
+\keys_define:nn { __tag / struct }
+  {
+    label .tl_set:N      = \l__tag_struct_key_label_tl,
+    stash .bool_set:N    = \l__tag_struct_elem_stash_bool,
+    tag   .code:n        = % S property
+      {
+        \seq_set_split:Nne \l__tag_tmpa_seq { / } {#1/\prop_item:Nn\g__tag_role_tags_NS_prop{#1}}
+        \tl_gset:Nx \g__tag_struct_tag_tl    { \seq_item:Nn\l__tag_tmpa_seq {1} }
+        \tl_gset:Nx \g__tag_struct_tag_NS_tl { \seq_item:Nn\l__tag_tmpa_seq {2} }
+        \__tag_check_structure_tag:N \g__tag_struct_tag_tl
+        \__tag_prop_gput:cnx
+         { g__tag_struct_\int_eval:n {\c at g__tag_struct_abs_int}_prop }
+         { S }
+         { \pdf_name_from_unicode_e:n{ \g__tag_struct_tag_tl} } %
+       \prop_get:NVNT \g__tag_role_NS_prop\g__tag_struct_tag_NS_tl\l__tag_tmpa_tl
+         {
+           \__tag_prop_gput:cnx
+            { g__tag_struct_\int_eval:n {\c at g__tag_struct_abs_int}_prop }
+            { NS }
+            { \l__tag_tmpa_tl } %
+         }
+      },
+    title .code:n        = % T property
+      {
+        \str_set_convert:Nnon
+          \l__tag_tmpa_str
+          { #1 }
+          { default }
+          { utf16/hex }
+        \__tag_prop_gput:cnx
+          { g__tag_struct_\int_eval:n {\c at g__tag_struct_abs_int}_prop }
+          { T }
+          { <\l__tag_tmpa_str> }
+      },
+    title-o .code:n        = % T property
+      {
+        \str_set_convert:Nnon
+          \l__tag_tmpa_str
+          { #1 }
+          { default }
+          { utf16/hex }
+        \__tag_prop_gput:cnx
+          { g__tag_struct_\int_eval:n {\c at g__tag_struct_abs_int}_prop }
+          { T }
+          { <\l__tag_tmpa_str> }
+      },
+    alttext .code:n      = % Alt property
+      {
+        \str_set_convert:Nnon
+          \l__tag_tmpa_str
+          { #1 }
+          { default }
+          { utf16/hex }
+        \__tag_prop_gput:cnx
+          { g__tag_struct_\int_eval:n {\c at g__tag_struct_abs_int}_prop }
+          { Alt }
+          { <\l__tag_tmpa_str> }
+      },
+    alttext-o .code:n      = % Alt property
+      {
+        \str_set_convert:Noon
+          \l__tag_tmpa_str
+          { #1 }
+          { default }
+          { utf16/hex }
+        \__tag_prop_gput:cnx
+          { g__tag_struct_\int_eval:n {\c at g__tag_struct_abs_int}_prop }
+          { Alt }
+          { <\l__tag_tmpa_str> }
+      },
+    actualtext .code:n  = % ActualText property
+      {
+        \str_set_convert:Nnon
+          \l__tag_tmpa_str
+          { #1 }
+          { default }
+          { utf16/hex }
+        \__tag_prop_gput:cnx
+          { g__tag_struct_\int_eval:n {\c at g__tag_struct_abs_int}_prop }
+          { ActualText }
+          { <\l__tag_tmpa_str>}
+      },
+    actualtext-o .code:n  = % ActualText property
+      {
+        \str_set_convert:Noon
+          \l__tag_tmpa_str
+          { #1 }
+          { default }
+          { utf16/hex }
+        \__tag_prop_gput:cnx
+          { g__tag_struct_\int_eval:n {\c at g__tag_struct_abs_int}_prop }
+          { ActualText }
+          { <\l__tag_tmpa_str>}
+      },
+    lang .code:n        = % Lang property
+      {
+        \__tag_prop_gput:cnx
+          { g__tag_struct_\int_eval:n {\c at g__tag_struct_abs_int}_prop }
+          { Lang }
+          { (#1) }
+      },
+    ref .code:n        = % Lang property
+      {
+        \tl_clear:N\l__tag_tmpa_tl
+        \clist_map_inline:nn {#1}
+          {
+            \tl_put_right:Nx \l__tag_tmpa_tl
+              {~\ref_value:nn{tagpdfstruct-##1}{tagstructobj} }
+          }
+        \__tag_prop_gput:cnx
+          { g__tag_struct_\int_eval:n {\c at g__tag_struct_abs_int}_prop }
+          { Ref }
+          { [\l__tag_tmpa_tl] }
+      },
+    E .code:n        = % E property
+      {
+        \str_set_convert:Nnon
+          \l__tag_tmpa_str
+          { #1 }
+          { default }
+          { utf16/hex }
+        \__tag_prop_gput:cnx
+          { g__tag_struct_\int_eval:n {\c at g__tag_struct_abs_int}_prop }
+          { E }
+          { <\l__tag_tmpa_str> }
+      },
+  }
+\keys_define:nn { __tag / struct }
+ {
+    AF .code:n        = % AF property
+      {
+        \pdf_object_if_exist:nTF {#1}
+          {
+            \__tag_prop_gput:cnx
+             { g__tag_struct_\int_eval:n {\c at g__tag_struct_abs_int}_prop }
+             { AF }
+             { \pdf_object_ref:n {#1} }
+          }
+          {
+
+          }
+      },
+   ,AFinline .code:n =
+     {
+       \group_begin:
+       \pdf_object_if_exist:eF {__tag/fileobj\int_use:N\c at g__tag_struct_abs_int}
+        {
+          \pdffile_embed_stream:nxx
+            {#1}
+            {tag-AFfile\int_use:N\c at g__tag_struct_abs_int.txt}
+            {__tag/fileobj\int_use:N\c at g__tag_struct_abs_int}
+        }
+       \__tag_prop_gput:cnx
+         { g__tag_struct_\int_use:N\c at g__tag_struct_abs_int _prop }
+         { AF }
+         { \pdf_object_ref:e {__tag/fileobj\int_use:N\c at g__tag_struct_abs_int } }
+       \group_end:
+     }
+   ,AFinline-o .code:n =
+     {
+       \group_begin:
+       \pdf_object_if_exist:eF {__tag/fileobj\int_use:N\c at g__tag_struct_abs_int}
+        {
+          \pdffile_embed_stream:oxx
+            {#1}
+            {tag-AFfile\int_use:N\c at g__tag_struct_abs_int.txt}
+            {__tag/fileobj\int_use:N\c at g__tag_struct_abs_int}
+        }
+       \__tag_prop_gput:cnx
+         { g__tag_struct_\int_use:N\c at g__tag_struct_abs_int _prop }
+         { AF }
+         { \pdf_object_ref:e {__tag/fileobj\int_use:N\c at g__tag_struct_abs_int } }
+       \group_end:
+     }
+ }
+\cs_new_protected:Npn \tag_struct_begin:n #1 %#1 key-val
+  {
+    \__tag_check_if_active_struct:T
+      {
+        \group_begin:
+        \int_gincr:N \c at g__tag_struct_abs_int
+        \__tag_prop_new:c  { g__tag_struct_\int_eval:n { \c at g__tag_struct_abs_int }_prop }
+        \__tag_new_output_prop_handler:n {\int_eval:n { \c at g__tag_struct_abs_int }}
+        \__tag_seq_new:c  { g__tag_struct_kids_\int_eval:n { \c at g__tag_struct_abs_int }_seq}
+        \exp_args:Ne
+          \pdf_object_new:nn
+            { __tag/struct/\int_eval:n { \c at g__tag_struct_abs_int } }
+            { dict }
+        \__tag_prop_gput:cno
+          { g__tag_struct_\int_eval:n { \c at g__tag_struct_abs_int }_prop }
+          { Type }
+          { /StructElem }
+        \keys_set:nn { __tag / struct} { #1 }
+        \__tag_check_structure_has_tag:n { \int_eval:n {\c at g__tag_struct_abs_int} }
+        \tl_if_empty:NF
+          \l__tag_struct_key_label_tl
+          {
+            \__tag_ref_label:en{tagpdfstruct-\l__tag_struct_key_label_tl}{struct}
+          }
+        %get the potential parent from the stack:
+        \seq_get:NNF
+          \g__tag_struct_stack_seq
+          \l__tag_struct_stack_parent_tmpa_tl
+          {
+            \msg_error:nn { tag } { struct-faulty-nesting }
+          }
+        \seq_gpush:NV \g__tag_struct_stack_seq        \c at g__tag_struct_abs_int
+        \seq_gpush:NV \g__tag_struct_tag_stack_seq    \g__tag_struct_tag_tl
+        \tl_gset:NV   \g__tag_struct_stack_current_tl \c at g__tag_struct_abs_int
+        %\seq_show:N   \g__tag_struct_stack_seq
+        \bool_if:NF
+          \l__tag_struct_elem_stash_bool
+          {%set the  parent
+            \__tag_prop_gput:cnx
+              { g__tag_struct_\int_eval:n {\c at g__tag_struct_abs_int}_prop }
+              { P }
+              {
+                \pdf_object_ref:e { __tag/struct/\l__tag_struct_stack_parent_tmpa_tl }
+              }
+            %record this structure as kid:
+            %\tl_show:N \g__tag_struct_stack_current_tl
+            %\tl_show:N \l__tag_struct_stack_parent_tmpa_tl
+            \__tag_struct_kid_struct_gput_right:xx
+               { \l__tag_struct_stack_parent_tmpa_tl }
+               { \g__tag_struct_stack_current_tl }
+            %\prop_show:c { g__tag_struct_\g__tag_struct_stack_current_tl _prop }
+            %\seq_show:c {g__tag_struct_kids_\l__tag_struct_stack_parent_tmpa_tl _seq}
+          }
+        %\prop_show:c { g__tag_struct_\g__tag_struct_stack_current_tl _prop }
+        %\seq_show:c {g__tag_struct_kids_\l__tag_struct_stack_parent_tmpa_tl _seq}
+        \group_end:
+     }
+  }
+
+\cs_new_protected:Nn \tag_struct_end:
+  { %take the current structure num from the stack:
+    %the objects are written later, lua mode hasn't all needed info yet
+    %\seq_show:N \g__tag_struct_stack_seq
+    \__tag_check_if_active_struct:T
+      {
+        \seq_gpop:NN   \g__tag_struct_tag_stack_seq \l__tag_tmpa_tl
+        \seq_gpop:NNTF \g__tag_struct_stack_seq \l__tag_tmpa_tl
+          {
+            \__tag_check_info_closing_struct:o { \g__tag_struct_stack_current_tl }
+          }
+          { \__tag_check_no_open_struct: }
+        % get the previous one, shouldn't be empty as the root should be there
+        \seq_get:NNTF \g__tag_struct_stack_seq \l__tag_tmpa_tl
+          {
+            \tl_gset:NV   \g__tag_struct_stack_current_tl \l__tag_tmpa_tl
+          }
+          {
+            \__tag_check_no_open_struct:
+          }
+       \seq_get:NNT \g__tag_struct_tag_stack_seq \l__tag_tmpa_tl
+          {
+            \tl_gset:NV \g__tag_struct_tag_tl \l__tag_tmpa_tl
+          }
+      }
+  }
+\cs_new_protected:Nn \tag_struct_use:n %#1 is the label
+  {
+    \__tag_check_if_active_struct:T
+      {
+        \prop_if_exist:cTF
+          { g__tag_struct_\__tag_ref_value:enn{tagpdfstruct-#1}{tagstruct}{unknown}_prop } %
+          {
+            \__tag_check_struct_used:n {#1}
+            %add the label structure as kid to the current structure (can be the root)
+            \__tag_struct_kid_struct_gput_right:xx
+              { \g__tag_struct_stack_current_tl }
+              { \__tag_ref_value:enn{tagpdfstruct-#1}{tagstruct}{0} }
+            %add the current structure to the labeled one as parents
+            \__tag_prop_gput:cnx
+              { g__tag_struct_\__tag_ref_value:enn{tagpdfstruct-#1}{tagstruct}{0}_prop }
+              { P }
+              {
+                \pdf_object_ref:e { __tag/struct/\g__tag_struct_stack_current_tl }
+              }
+          }
+          {
+            \msg_warning:nnn{ tag }{struct-label-unknown}{#1}
+          }
+      }
+  }
+\cs_new_protected:Npn \tag_struct_insert_annot:nn #1 #2 %#1 should be an object reference
+                                                        %#2 struct parent num
+  {
+    \__tag_check_if_active_struct:T
+      {
+        \__tag_struct_insert_annot:nn {#1}{#2}
+      }
+  }
+
+\cs_generate_variant:Nn \tag_struct_insert_annot:nn {xx}
+\cs_new:Npn \tag_struct_parent_int: {\int_use:c { c at g__tag_parenttree_obj_int }}
+
+
+\prop_new:N \g__tag_attr_entries_prop
+\seq_new:N  \g__tag_attr_class_used_seq
+\tl_new:N   \l__tag_attr_value_tl
+\prop_new:N \g__tag_attr_objref_prop %will contain obj num of used attributes
+\cs_new_protected:Npn \__tag_attr_new_entry:nn #1 #2 %#1:name, #2: content
+  {
+    \prop_gput:Nnn \g__tag_attr_entries_prop
+      {#1}{#2}
+  }
+
+\keys_define:nn { __tag / setup }
+  {
+    newattribute .code:n =
+      {
+        \__tag_attr_new_entry:nn #1
+      }
+  }
+\keys_define:nn { __tag / struct }
+  {
+    attribute-class .code:n =
+     {
+       \clist_set:No \l__tag_tmpa_clist { #1 }
+       \seq_set_from_clist:NN \l__tag_tmpa_seq \l__tag_tmpa_clist
+       \seq_map_inline:Nn \l__tag_tmpa_seq
+         {
+           \prop_if_in:NnF \g__tag_attr_entries_prop {##1}
+             {
+               \msg_error:nnn { tag } { attr-unknown } { ##1 }
+             }
+           \seq_gput_left:Nn\g__tag_attr_class_used_seq { ##1}
+         }
+       \seq_set_map:NNn \l__tag_tmpb_seq \l__tag_tmpa_seq
+         {
+           /##1
+         }
+       \tl_set:Nx \l__tag_tmpa_tl
+         {
+           \int_compare:nT { \seq_count:N \l__tag_tmpa_seq > 1 }{[}
+           \seq_use:Nn \l__tag_tmpb_seq  { \c_space_tl  }
+           \int_compare:nT { \seq_count:N \l__tag_tmpa_seq > 1 }{]}
+         }
+       \int_compare:nT { \seq_count:N \l__tag_tmpa_seq > 0 }
+         {
+           \__tag_prop_gput:cnx
+             { g__tag_struct_\int_eval:n {\c at g__tag_struct_abs_int}_prop }
+             { C }
+             { \l__tag_tmpa_tl }
+          %\prop_show:c  { g__tag_struct_\int_eval:n {\c at g__tag_struct_abs_int}_prop }
+         }
+     }
+  }
+\keys_define:nn { __tag / struct }
+  {
+    attribute .code:n  = % A property (attribute, value currently a dictionary)
+      {
+        \clist_set:No          \l__tag_tmpa_clist { #1 }
+        \seq_set_from_clist:NN \l__tag_tmpa_seq \l__tag_tmpa_clist
+        \tl_set:Nx \l__tag_attr_value_tl
+          {
+            \int_compare:nT { \seq_count:N \l__tag_tmpa_seq > 1 }{[}%]
+          }
+        \seq_map_inline:Nn \l__tag_tmpa_seq
+          {
+            \prop_if_in:NnF \g__tag_attr_entries_prop {##1}
+              {
+                \msg_error:nnn { tag } { attr-unknown } { ##1 }
+              }
+            \prop_if_in:NnF \g__tag_attr_objref_prop {##1}
+              {%\prop_show:N \g__tag_attr_entries_prop
+                \pdf_object_unnamed_write:nx
+                  { dict }
+                  {
+                    \prop_item:Nn\g__tag_attr_entries_prop {##1}
+                  }
+                \prop_gput:Nnx \g__tag_attr_objref_prop {##1} {\pdf_object_ref_last:}
+              }
+            \tl_put_right:Nx \l__tag_attr_value_tl
+              {
+                \c_space_tl
+                \prop_item:Nn \g__tag_attr_objref_prop {##1}
+              }
+ %     \tl_show:N \l__tag_attr_value_tl
+          }
+        \tl_put_right:Nx \l__tag_attr_value_tl
+          { %[
+            \int_compare:nT { \seq_count:N \l__tag_tmpa_seq > 1 }{]}%
+          }
+ %     \tl_show:N \l__tag_attr_value_tl
+        \__tag_prop_gput:cnx
+          { g__tag_struct_\int_eval:n {\c at g__tag_struct_abs_int}_prop }
+          { A }
+          { \l__tag_attr_value_tl }
+    },
+  }
+%% File: tagpdf-space.dtx
+\sys_if_engine_pdftex:T
+  {
+    \sys_if_output_pdf:TF
+      {
+        \pdfglyphtounicode{space}{0020}
+        \keys_define:nn { __tag / setup }
+          {
+            interwordspace .choices:nn = { true, on }  { \pdfinterwordspaceon },
+            interwordspace .choices:nn = { false, off }{ \pdfinterwordspaceon },
+            interwordspace .default:n = true,
+            show-spaces .bool_set:N = \l__tag_showspaces_bool
+          }
+      }
+      {
+        \keys_define:nn { __tag / setup }
+          {
+            interwordspace .choices:nn = { true, on, false, off }
+              { \msg_warning:nnn {tag}{sys-no-interwordspace}{dvi}  },
+            interwordspace .default:n = true,
+            show-spaces .bool_set:N = \l__tag_showspaces_bool
+          }
+      }
+  }
+
+\sys_if_engine_luatex:T
+  {
+    \keys_define:nn { __tag / setup }
+      {
+        interwordspace .choices:nn =
+                                 { true, on }
+                                 {
+                                   \bool_gset_true:N \g__tag_active_space_bool
+                                   \lua_now:e{ltx.__tag.func.markspaceon()}
+                                 },
+        interwordspace .choices:nn =
+                                 { false, off }
+                                 {
+                                  \bool_gset_false:N \g__tag_active_space_bool
+                                  \lua_now:e{ltx.__tag.func.markspaceoff()}
+                                 },
+        interwordspace .default:n = true,
+        show-spaces      .choice:,
+        show-spaces  / true  .code:n =
+                                 {\lua_now:e{ltx.__tag.trace.showspaces=true}},
+        show-spaces  / false .code:n =
+                                 {\lua_now:e{ltx.__tag.trace.showspaces=nil}},
+        show-spaces .default:n = true
+      }
+  }
+
+\sys_if_engine_xetex:T
+  {
+    \keys_define:nn { __tag / setup }
+      {
+        interwordspace .choices:nn = { true, on }
+          { \msg_warning:nnn {tag}{sys-no-interwordspace}{xetex}  },
+        interwordspace .choices:nn = { false, off }
+          { \msg_warning:nnn {tag}{sys-no-interwordspace}{xetex}  },
+        interwordspace .default:n = true,
+        show-spaces .bool_set:N = \l__tag_showspaces_bool
+      }
+  }
+\sys_if_engine_luatex:T
+  {
+    \cs_new_protected:Nn \__tag_fakespace:
+      {
+        \group_begin:
+        \lua_now:e{ltx.__tag.func.fakespace()}
+        \skip_horizontal:n{\c_zero_skip}
+        \group_end:
+      }
+  }
 %% 
 %%
 %% End of file `tagpdf.sty'.

Modified: trunk/Master/texmf-dist/tex/latex/tagpdf/tagpdfdocu-patches.sty
===================================================================
--- trunk/Master/texmf-dist/tex/latex/tagpdf/tagpdfdocu-patches.sty	2021-06-30 20:41:50 UTC (rev 59768)
+++ trunk/Master/texmf-dist/tex/latex/tagpdf/tagpdfdocu-patches.sty	2021-06-30 21:14:14 UTC (rev 59769)
@@ -1,6 +1,40 @@
 %\RequirePackage[enable-debug]{expl3}[2018/06/14]
-\ProvidesExplPackage {tagpdfdocu-patches} {2021-06-14} {0.82}
+\ProvidesExplPackage {tagpdfdocu-patches} {2021-06-29} {0.9}
  {patches/commands for the tagpdf documentation}
+\RequirePackage{etoolbox}
+%%%%
+% header and footer (now needed as attributes are global again)
+%%%%
+%% patching \@oddfoot/\@oddhead is nonsense, that is redefined all the time.
+%% Using the scrlayer interfaces would probably work
+%% but we will need a core latex solution anyway
+%% so let's test it here and patch \@outputpage
+%% we also disable paratagging, not for the tagging but to avoid that the small
+%% numbers gives overfull vbox messages ...
+\patchcmd\@outputpage
+ {\hb at xt@\textwidth{\@thehead}}
+ {
+  \hb at xt@\textwidth
+   {
+    \bool_set_false:N \l__tag_para_bool
+    \tag_mc_artifact_group_begin:n{pagination}
+    \@thehead
+    \tag_mc_artifact_group_end:
+   }
+ }
+ {}{\fail}
+\patchcmd\@outputpage
+ {\hb at xt@\textwidth{\@thefoot}}
+ {
+  \hb at xt@\textwidth
+   {
+    \bool_set_false:N \l__tag_para_bool
+    \tag_mc_artifact_group_begin:n{pagination}
+    \@thefoot
+    \tag_mc_artifact_group_end:
+   }
+ }
+ {}{\fail}
 
 %%%%%
 % tableofcontents
@@ -40,10 +74,10 @@
    pagenumberformat=\tagscrtocpagenumber]{tocline}{paragraph}
 
 
-
+% \IfStr{#3} doesnt like a \label ...
 \renewcommand{\addtocentrydefault}[3]{%
- \Ifstr{#3}{}{}
-   {%\
+% \Ifstr{#3}{}{}
+%   {%
    \Ifstr{#2}{}
     {%
      \addcontentsline{toc}{#1}
@@ -69,7 +103,8 @@
      \tagstructend
      }%
     }%
-   }}%
+  %}
+}%
 
 % the dots must be marked too
 
@@ -185,7 +220,10 @@
 % but currently unneeded as we marked them up as artifacts anyway as they don't contain
 % meaningful contents
 
-\NewDocumentCommand\sidenote{m}{\begin{tagmcartifact}{notype}\tagpdfparaOff\marginnote{#1}\end{tagmcartifact}}
+\NewDocumentCommand\sidenote{m}
+ {
+   \tag_mc_artifact_group_begin:n{notype}\tagpdfparaOff\marginnote{#1}\tag_mc_artifact_group_end:
+ }
 
 % ======== tikzpicture ==========
 % TODO this needs some investigation: it messes up the stack if one add paraOff



More information about the tex-live-commits mailing list.