diff options
Diffstat (limited to 'Master/texmf-dist/source/latex/latex-lab/latex-lab-footnotes.dtx')
-rw-r--r-- | Master/texmf-dist/source/latex/latex-lab/latex-lab-footnotes.dtx | 1418 |
1 files changed, 1073 insertions, 345 deletions
diff --git a/Master/texmf-dist/source/latex/latex-lab/latex-lab-footnotes.dtx b/Master/texmf-dist/source/latex/latex-lab/latex-lab-footnotes.dtx index 6fe7ff6955a..4c8c9b73a61 100644 --- a/Master/texmf-dist/source/latex/latex-lab/latex-lab-footnotes.dtx +++ b/Master/texmf-dist/source/latex/latex-lab/latex-lab-footnotes.dtx @@ -1,7 +1,7 @@ % \iffalse meta-comment % %% File: latex-lab-footnotes.dtx -% Copyright (C) 2022 The LaTeX Project +% Copyright (C) 2022-2023 The LaTeX Project % % It may be distributed and/or modified under the conditions of the % LaTeX Project Public License (LPPL), either version 1.3c of this @@ -53,19 +53,19 @@ % offering configurable methods for layout and functionality % adjustments that avoid overwriting each other when used in % classes as well as in packages (as far as possible --- obviously -% some adjustments are mutally exclusive). This is achieved by -% providing a a larger number of hooks (for areas where different +% some adjustments are mutually exclusive). This is achieved by +% providing a larger number of hooks (for areas where different % packages/classes can easily coexist with their adjustments) and a % number of configuration points to which only one class or package -% can write to successfully (in case of multiple changes the the +% can write to successfully (in case of multiple changes the % last one wins). The latter are for special functionality, e.g., % if footnote text is typeset as a single paragraph, it can't be configured % the same time to be typeset vertically with one footnote below % each other. % % The interfaces are set up to support tagged PDF, but in order -% for this to work, all packages altering the fontnote setup should -% use the inferfaces provided here and not do it through the +% for this to work, all packages altering the footnote setup should +% use the interfaces provided here and not do it through the % legacy methods (though there is some support for the latter as % well, but if will not work in a cases). % @@ -81,7 +81,7 @@ % that was used by most document classes, % but \cs{@makefntext} had to be defined in the class itself because % the format didn't provide a default. As a result you will find -% definitions for the latter in all document classes and defintions +% definitions for the latter in all document classes and definitions % for \cs{@makefnmark} only in very few. % % Furthermore, to enable special footnote layouts or provide @@ -114,7 +114,7 @@ % % In contrast the hooks are of interest to many classes to provide % their layout alterations in a way that it works smoothly with -% other packages handling aspects of foonote formatting. +% other packages handling aspects of footnote formatting. % % % \subsection{Formatting the mark in the main text} @@ -140,7 +140,7 @@ % % Executed at the very beginning of \cs{footnotemark}. Currently % there are two packages (\pkg{bibarts} and \pkg{chextras}) that -% prepend material at this point (not ncessarily correctly, e.g., +% prepend material at this point (not necessarily correctly, e.g., % they do not all check that they are in horizontal mode). % % This hook is paired with hook \hook{fnmark/after}. @@ -163,15 +163,15 @@ % \item[\hook{fnmark/begin}] % % This hook is executed directly in front of the typeset mark. -% This is the place where \pkg{hyperref} adds part of its code, -% i.e., after the \cs{nobreak} mentioned above. With a closer -% integration of \pkg{hyperref} this hook may not be necessary at -% all. +% This is the place where \pkg{hyperref} would have added +% part of its code, i.e., after the \cs{nobreak} mentioned above. +% With the integration of hyperlinks in the tagging code +% this hook may not be necessary at all. % % \item[\hook{fnmark/end}] % % This hook is executed directly after the typeset mark. It is -% used by \pkg{hyperref}, \pkg{memhfixc}, \pkg{scrlttr2}, and +% used by \pkg{memhfixc}, \pkg{scrlttr2}, and % \pkg{footmisc}. Used, for example, to implement support for % multiple marks in succession. % @@ -227,9 +227,9 @@ % \item[\cs{@footnotetext@cfgpointiii} (no argument)] % % By default this configuration point adds a strut to the -% footnote material. so that consecutive footnotes are properly +% footnote material so that consecutive footnotes are properly % spaced vertically. In some use cases this is not appropriate -% (e.g., when running all footnotes s a single paragraph) and so +% (e.g., when running all footnotes as a single paragraph) and so % this configuration point can cancel the action or do something % else instead. % @@ -261,17 +261,18 @@ % % If tagging is produced this configuration point is also % responsible for surrounding the mark with the appropriate tags -% marking the mark as an Lbl. It does this using the command \cs{tag@FELbl}. +% marking the mark as an Lbl. It does this using the command +% \cs{tag@FENoteLbl}. % % \item[\cs{@makefntext@cfgpointii} (1 argument)] % % This configuration point manages the formatting of the footnote -% text once the mark has been typeset. +% text once the mark has been typeset. % % If tagging is produced this configuration point is also % responsible for surrounding the mark with the appropriate tags % marking the mark as an MC of type FENote. It does this using -% the command \cs{tag@FENote}. +% the command \cs{tag@FENotetext}. % % \end{description} % @@ -335,7 +336,7 @@ % % At the very end of \cs{footnotetext} we execute the hook % \hook{fntext/after} which is a reversed hook paired with -% \hook{fntext/before}. Some packages, e.g., \pkg{linuex}, have +% \hook{fntext/before}. Some packages, e.g., \pkg{linguex}, have % code in that position. % % \end{description} @@ -346,7 +347,7 @@ % \subsubsection{Additional configuration possibilities} % % The formatting of the footnote mark in front of the footnote -% texts is influenced by the setting of the dimen parameter +% text is influenced by the setting of the dimen parameter % \cs{footnotemargin}. By default its value is 1.8em in the current % text font (or \texttt{-}\cs{maxdimen} when the para option is % chosen). The following rules apply: @@ -381,7 +382,247 @@ % \end{itemize} % % -% \section{Tagging support} +% \section{Tagging and hyperlinking support} +% +% Footnotes consist of a \emph{footnotemark} (short: mark) that is typically placed in the text +% as a superscript number like this\footnotemark[1], and a \emph{footnotetext} +% (short: note) that is placed at the bottom of the page. +% The \emph{footnotetext} normally repeats at the begin the mark as a visual clue. +% +% Tagging (and hyperlinking) has to connect the mark with the note. +% For the tagging code, we assume that every mark has exactly one associated note, +% and that every note is associated to at least one mark +% and can have more associated marks. +% +% The mark doesn't need to be visible, e.g. the typesetted +% mark\textsuperscript{1--3} denotes three marks, where the second is invisible. +% Tagging should produce here probably three \texttt{Lbl} structures +% (one without content), and an artifact for the range marker. +% If such a range is used, links can only point to the notes 1 and 3 and +% one has to suppress the linking for the second mark. +% This means that links and tagging are also related +% to the actual formatting of the footnote mark. +% In the following this problem is mostly ignored for now, but +% should not be forgotten and handled later. +% +% \subsection{Technical details for the tagging} +% +% The \emph{footnotemark} should create a \texttt{/Lbl} structure\footnote{to make it easier +% to identify the role we use \texttt{/footnotemark} which we rolemap to \texttt{/Lbl}} that should contain a \texttt{/Ref} entry pointing +% to the structure of the \emph{footnotetext}. +% +% The \emph{footnotetext} should create a \texttt{/FENote}\footnote{We tag it as \texttt{/footnote} and role map it.} +% structure with a \texttt{/Ref} +% entry pointing to the structures of \emph{all} marks related to the note. +% The mark at the begin of the +% note is in a \texttt{/Lbl}\footnote{We tag it as \texttt{/footnotelabel}.} +% structure but has to fulfil no special requirements. +% +% Structure objects and the underlying properties used by the tagging +% code are initialized when the structure is opened. This means that one can not +% directly add data to a future structure +% but as structure objects are written at the end of the document it is +% possible to update \texttt{/Ref} entries in an end document hook. +% +% +% So tagging has to solve two problems: +% \begin{itemize} +% \item the mark and the footnote text must be surrounded by the correct structure +% and marked content commands. This is not trivial +% as there are various layouts (bottom, marginpar, minipage) and the tagging +% from the automatic paratagging must be taken into account if one want to avoid +% faulty nesting. +% +% \item It must detect which marks are related to which notes +% so that it can setup the \texttt{/Ref} cross-references. +% \end{itemize} +% +% +% \subsection{Requirements for links} +% +% Links should go from the mark to the note. Sometimes it has been requested +% that links go back too, but as there +% can be more than one mark connected to a note it is not clear how to decide to which mark it should go. +% Using the keys from the PDF viewer to go back is normally better. +% +% Links are closely related to the references stored in the \texttt{/Ref} +% entry of a mark and so are handled in the code together with them. +% But there are subtle technical differences to take care of +% as links and destinations are whatsits and so must be created at the correct time. +% +% It should be possible to suppress the links both globally and locally.\footnote{ +% Currently hyperref only offers the option to suppress the +% footnote links globally +% with the option \texttt{hyperfootnotes=false}. To suppress them locally +% only the \texttt{NoHyper} environment is provided.} +% +% +% \subsection{The algorithmus to connect marks and notes} +% +% +% The connection is made by comparing the value of \cs{@thefnmark}. +% +% The standard mark commands (\cs{footnotemark} and \cs{footnote}) +% store the current value of \cs{@thefnmark} +% with their own structure number as a key in a property. +% +% A following \cs{footnotetext} compares its own \cs{@thefnmark} with the values in +% the prop. If there is a match it stores the structure numbers and removes the entries +% from the properties (so in a normal document the property will never contain more than +% a few entries). +% +% This works well as long as the \cs{footnotemark} commands are issued before the \cs{footnotetext} and +% as long as nothing unusual is done to \cs{@thefnmark}. +% It also works if a document uses more than one footnote series as long as they have distinct numbering +% systems, but in case a distinction is needed it is possible to define +% a new data structure and to switch locally to use this +% container. The following three commands are used for this. +% +% The default property uses the name \texttt{default} +% +% \begin{function}{\fnote_new:nn} +% \begin{syntax} +% \cs{fnote_new:nn}\Arg{name}\Arg{key/value option} +% \end{syntax} +% +% This commands set up the needed data structure. Currently this only +% consists of a property which is used to store and manage the mark values. +% There are no options yet. +% \end{function} +% +% \begin{function}{\fnote_mark_gput:nn,\fnote_mark_gput:no,\fnote_mark_gput:oo} +% \begin{syntax} +% \cs{fnote_mark_gput:nn}\Arg{mark}\Arg{footnote type name} +% \end{syntax} +% This command stores the current structure number as key and the \meta{mark} as +% value in the property associated with the \meta{footnote type name} +% \end{function} +% +% \begin{function}{\fnote_mark_gpop:nnN} +% \begin{syntax} +% \cs{fnote_mark_gpop:nnN}\Arg{mark}\Arg{footnote type name}\meta{sequence} +% \end{syntax} +% This command stores the keys/structure numbers whose value are \meta{mark} in the +% property associated with \meta{footnote type name} in the \meta{sequence} +% and then remove them from the property. The content of the sequence can then be +% used to create link targets and references. +% \end{function} +% +% +% \subsubsection{\cs{footref}} +% +% \cs{footref} use internally the same command to set the mark as \cs{footnotemark}, it only +% defines \cs{@thefnmark} differently. This \cs{@thefnmark} is not suitable for the method described +% above, as it contains a reference command it can't be used to match a note, also \cs{footref} can +% be used after the note has already been set. \cs{footref} disables therefore the automatic detection. +% +% Instead the \cs{label} command is (currently with the help of a hook from the \texttt{nameref} package) +% extended in the \cs{footnotetext} command to also store the structure number and \cs{footref} retrieves this +% number to setup the reference and the link. +% +% The structure related to the \cs{footref} is added to the end of the \texttt{/Ref} array of the note and so the +% \texttt{/Ref} array doesn't necessarly reflect the order of the marks in the document. It would probably +% be possible to change this, but it is not clear if it actually matters and so it worth the additional coding +% and processing. +% +% \subsubsection{\cs{footnotemark} after \cs{footnotetext}} +% +% The automatic detection doesn't work if a \cs{footnotemark} is issued after +% the \cs{footnotetext} it refers to. There will be no error, but neither the link nor +% the \texttt{/Ref} will connect both. +% +% The simple way to handle this is to use a label and \cs{footref}: +% +% \begin{verbatim} +% \footnotetext{\label{fn:a}text} ... \footref{fn:a} +% \end{verbatim} +% +% An alternative would be to extend the syntax of \cs{footnotemark} and +% \cs{footnotetext} to allow to add a label which can then be used. +% For example +% +% \begin{verbatim} +% \footnotetext[label=fn:a]{text} ... \footnotemark[label=fn:a] +% \end{verbatim} +% +% As both have already an optional argument, that requires the optional argument extension. +% +% +% \subsection{Links} +% +% The structure numbers detected for the \texttt{/Ref} are also used for links: +% even if tagging is not activated the tagging commands are defined through +% the \pkg{tagpdf-base} package +% and the structure commands increase the structure counter and this info can be used. +% +% A \cs{footnotetext} creates a bunch of destinations (in most cases this sums up to +% two destinations): one for every structure number in the \texttt{/Ref} (used as target +% by the mark commands) and one for the structure number of the footnotetest itself +% (used as target by \cs{footref}s commands). +% +% \subsection{Implementation details} +% +% \subsection{Handling the mark} +% +% The mark in the text is handled by redefining the kernel configuration point +% \cs{@kernel@process@makefnmark} to \cs{tag@FEMark}. +% It takes one argument, \cs{@makefnmark}, the command which formats the +% mark, and surrounds it by link and tagging commands. +% At the point where \cs{@kernel@process@makefnmark} is issued \cs{@thefnmark} has already been +% defined and can be used to setup the reference detections. +% +% +% \subsection{Handling the footnotetext} +% +% The main part is done by redefining \cs{@kernel@process@footnotetext}. This configuration point takes two arguments, \cs{@footnotetext@cfgpoint} (by default \verb+\insert\footins+) and as second argument lots of code related to typesetting the notemark and the footnote text with the actual content of the footnote text somewhere in the middle. +% +% The redefinition of \cs{@kernel@process@footnotetext} surrounds the content with the structure command +% and tries to detect to which mark the note is related. +% +% The actual typesetting of the note text is done +% by \cs{@makefntext}/\cs{fnote_makefntext:n}. In the new implementation this contains two configuration +% points, \cs{@makefntext@cfgpoint} and \cs{@makefntext@cfgpointii}. These are redefined to add the tagging commands around note mark and note text. +% +% \subsection{Footnotes in minipages} +% +% In minipages the \cs{footnote} command uses a special marker +% (small italic letters by default) and puts the +% footnote text at the bottom of the box. The \cs{footnotemark} +% command uses the standard footnote counter and marker (and so typically +% creates a superscript number). +% It is meant to be used with a \cs{footnotetext} \emph{outside} +% the minipage to create a footnote mark which refers to a footnote text +% at the bottom of the page. +% This means to repeat a footnote marker in a minipage you should use the \cs{footref} command. +% +% Tagging works quite similar to normal footnotes if the new definition is used +% and if the minipage code is changed to use the new configuration point. +% The main problem here is currently the tagging of the minipage itself. +% +% \section{TODOs} +% +% \begin{itemize} +% +% \item tagging destroys footnotes directly following the text with pdflatex. +% +% \item there is a dependency on nameref as it provides the hook in \cs{label} +% used by the \cs{footref} code. +% +% \item there is a dependency to etoolbox as we patch \cs{\@iiiminipage} +% +% \item Special formatting of footnote marks in the text, e.g. if ranges or commas are +% used require special care as they should normally mark up such text as artifacts and +% perhaps have to insert empty structures to represent an invisible mark. This must be coordinated +% with the relevant packages and classes. +% +% \item manyfoot doesn't work correctly and must be analyzed. +% +% \item Check if additional kernel configuration points are needed/possible +% to avoid the redefinitions of \cs{@makefntext@cfgpoint} and \cs{@makefntext@cfgpointii}. +% +% \item \pkg{memoir} is not supported at all and errors when the code tries to patch +% \cs{@makefntext}. +% \end{itemize} % % \emph{To be documented} % @@ -403,46 +644,171 @@ % \subsection{File declaration} % \begin{macrocode} \ProvidesFile{latex-lab-footnotes.ltx} - [2022-07-22 v0.6b changes to the footnote interfaces] + [2023-02-04 v0.7 changes to the footnote interfaces] % \end{macrocode} % +% \subsection{code not fully handled yet} % \begin{macrocode} - +% % latex.ltx +% not looked at yet +% \@mpfootnotetext is probably no longer needed, or only to support other +% classes and package. See below about the minipage code. +% +% \long\def\@mpfootnotetext#1{% +% \global\setbox\@mpfootins\vbox{% +% \unvbox\@mpfootins +% \reset@font\footnotesize +% \hsize\columnwidth +% \@parboxrestore +% \def\@currentcounter{mpfootnote}% +% \protected@edef\@currentlabel +% {\csname p@mpfootnote\endcsname\@thefnmark}% +% \color@begingroup +% \@makefntext{% +% \rule\z@\footnotesep\ignorespaces#1\@finalstrut\strutbox}% +% \par +% \color@endgroup}} +% ======== +% used by the minipage footnote code. +% +% \def\@mpfn{footnote} +% \def\thempfn{\thefootnote} +% ========= +% this perhaps need some configuration options. +% +%\def\@makefnmark{\hbox{\@textsuperscript{\normalfont\@thefnmark}}} +% +% ========= +%% alterations not covered: +% +% ./arabtex/afoot.sty --- too different (and probably too old) +% +% ===== +% alterations of footnotetext not covered: +% +% ./revtex4-1/revtex4-1.cls ./revtex/ltxutil.sty ./revtex/revtex4-2.cls ... (need analysis) +% ./bigfoot/bigfoot.sty +% +% memoir needs checking too +% +% ===== +% +% use of kerns to mark h-mode positions (unit sp) +% +% 1 = CJK +% 2 = CJK +% 3 = multiple footnotes (footmisc, koma, eledmac, tufte, memoir, +% parnotes, sidenotes) +% 3 = outer kern in letter spacing (letterspace) +% 3 = beginning of list (examdesign.cls) +% 4 = CJK pigin +% 5 = CJK ruby - % not looked at yet - -\long\def\@mpfootnotetext#1{% - \global\setbox\@mpfootins\vbox{% - \unvbox\@mpfootins - \reset@font\footnotesize - \hsize\columnwidth - \@parboxrestore - \def\@currentcounter{mpfootnote}% - \protected@edef\@currentlabel - {\csname p@mpfootnote\endcsname\@thefnmark}% - \color@begingroup - \@makefntext{% - \rule\z@\footnotesep\ignorespaces#1\@finalstrut\strutbox}% - \par - \color@endgroup}} - - -\def\@makefnmark{\hbox{\@textsuperscript{\normalfont\@thefnmark}}} - - - -\def\@mpfn{footnote} -\def\thempfn{\thefootnote} - - - +% 1-4 = polyglossia for korean +% +% \end{macrocode} %------------------------------------- - - +% \begin{macrocode} \ExplSyntaxOn +% \end{macrocode} +% \subsection{Temporary variables} +% \begin{macrocode} +\prop_new:N \l_@@_tmpa_prop +\tl_new:N \l_@@_tmpa_tl +% \end{macrocode} +% \subsection{Public variables} +% +% A footnote mark will store its structure number (key) and the +% expanded \cs{@thefnmark} in this prop so +% that a following note can retrieve this info +% if needed. It is possible to use more than one footnote series (type) +% if needed (if different footnotes/note use the same +% numbering system). +% If this command is changed an accompanying property must be created +% \begin{NOTE}{UF} +% TODO: interface to create the property.\\ +% TODO: check and decide about the name of the tl +% \end{NOTE} +% \begin{macro}{\l_fnote_type_tl} +% \begin{macrocode} +\tl_new:N \l_fnote_type_tl +\tl_set:Nn \l_fnote_type_tl {default} +% \end{macrocode} +% \end{macro} +% It must be possible to suppress the hyperlinking, both locally +% and globally. hyperref's hyperfootnotes option should set the boolean. +% \begin{macro}{\l_fnote_link_bool} +% \begin{macrocode} +\bool_new:N \l_fnote_link_bool +\bool_set_true:N \l_fnote_link_bool +% \end{macrocode} +% \end{macro} +% A hyperlink should have an changeable link type. This can +% be e.g. used to change the color or the border. +% \begin{macro}{\l_fnote_link_type_tl} +% \begin{macrocode} +\tl_new:N \l_fnote_link_type_tl +\tl_set:Nn \l_fnote_link_type_tl {link} +% \end{macrocode} +% \end{macro} +% +% \subsection{Internal variables} +% +% \begin{macro}{\l_@@_linktarget_tl} +% This command stores the name of a linktarget/destination +% when needed +% \begin{macrocode} +\tl_new:N \l_@@_linktarget_tl +% \end{macrocode} +% \end{macro} +% \begin{macro}{\l_@@_currentlabel_tl} +% This command is used to pass a label name around. +% \begin{macrocode} +\tl_new:N \l_@@_currentlabel_tl +% \end{macrocode} +% \end{macro} - +% \begin{macro}{\l_@@_currentrefs_seq} +% This sequence stores the list of reference of a note +% \begin{macrocode} +\seq_new:N \l_@@_currentrefs_seq +% \end{macrocode} +% \end{macro} +% +% The connection between the mark(s) in the text and the note +% is either deduced automatically or done through an label. +% The default is automatic, but we must be able to suppress it. For this we use a boolean. +% \begin{macro}{\l_@@_autodetect_bool} +% \begin{macrocode} +\bool_new:N \l_@@_autodetect_bool +\bool_set_true:N \l_@@_autodetect_bool +% \end{macrocode} +% \end{macro} +% This is used to pass the structure number of the note around, e.g. +% to a label inside the note. +% \begin{macrocode} +\tl_new:N \l_@@_currentstruct_tl +\tl_set:Nn \l_@@_currentstruct_tl {1} +% \end{macrocode} +% +% +% \subsection{Variants} +% +% \begin{macrocode} +\cs_generate_variant:Nn \ref_label:nn { Vn } +\cs_generate_variant:Nn \ref_value:nn { Vn } +\cs_generate_variant:Nn \prop_gput:Nnn {cxn} +\cs_generate_variant:Nn \hook_gput_code:nnn{nne} +\cs_generate_variant:Nn \tag_struct_use:n {e} +% \end{macrocode} +% +% \subsection{Updating \cs{@thefnmark}} +% \begin{macro}{\fnote_step_fnmark:nn} +% This command updates \cs{@thefnmark}. The first argument +% is an optional integer expression, the second a counter name. +% If the optional argument is not given it steps the counter. +% \begin{macrocode} \cs_new_protected:Npn \fnote_step_fnmark:nn #1#2 { \tl_if_novalue:nTF {#1} { @@ -463,7 +829,12 @@ \group_end: } } - +% \end{macrocode} +% \end{macro} +% \begin{macro}{\fnote_set_fnmark:nn} +% This is similar to the previous command, but it doesn't step the +% counter but use the current value. +% \begin{macrocode} \cs_new_protected:Npn \fnote_set_fnmark:nn #1#2 { \tl_if_novalue:nTF {#1} { @@ -476,25 +847,40 @@ \group_end: } } - -%------------------------------------- - -% the debugging code is just temp -\bool_new:N \g_fnote_debug_bool -\bool_gset_true:N \g_fnote_debug_bool % for now we have debugging turned on by default - -%------------------------------------- - - - +% \end{macrocode} +% \end{macro} +% +% \subsection{Hooks} +% +% Hooks in the footnotemark command. +% \begin{macrocode} \NewMirroredHookPair{fnmark/before}{fnmark/after} \NewHook{fnmark} \NewHook{fnmark/begin} \NewHook{fnmark/end} - - -\cs_new:Npn \@@_debug_footnotemark: { - \bool_if:NT \g_fnote_debug_bool +% \end{macrocode} +% Hooks in the footnotetext command +% \begin{macrocode} +\NewMirroredHookPair{fntext/before}{fntext/after} +\NewHook{fntext} +\NewHook{fntext/para} +\NewHook{fntext/begin} +\NewHook{fntext/end} +% \end{macrocode} +% +% \subsection{Debugging code} +% the debugging code is just temporary +% +% For now we have debugging turned on by default +% \begin{macrocode} +\bool_new:N \g_fnote_debug_bool +\bool_gset_true:N \g_fnote_debug_bool +% \end{macrocode} +% We log the hooks in the footnote mark command, but only once +% \begin{macrocode} +\cs_new_protected:Npn \@@_debug_footnotemark: + { + \bool_if:NT \g_fnote_debug_bool { \LogHook{fnmark/before} \LogHook{fnmark} @@ -503,9 +889,38 @@ \LogHook{fnmark/after} \cs_gset_eq:NN \@@_debug_footnotemark: \prg_do_nothing: } -} - - + } +% \end{macrocode} +% Similar for the footnotetext +% \begin{macrocode} +\cs_new_protected:Npn \@@_debug_footnotetext: + { + \bool_if:NT \g_fnote_debug_bool + { + \cs_log:N\@footnotetext@cfgpoint + \cs_log:N\@footnotetext@cfgpointii + \cs_log:N\@footnotetext@cfgpointiii + \cs_log:N\@footnotetext@cfgpointiv + \cs_log:N\@makefntext@cfgpoint + \cs_log:N\@makefntext@cfgpointii + \LogHook{fntext/before} + \LogHook{fntext} + \LogHook{fntext/para} + \LogHook{fntext/begin} + \LogHook{fntext/end} + \LogHook{fntext/after} +% \end{macrocode} +% Show the info only once (if at all). +% \begin{macrocode} + \cs_gset_eq:NN \@@_debug_footnotetext: \prg_do_nothing: + } + } +% \end{macrocode} +% +% \subsection{The new \cs{@footnotemark} command} +% \begin{macro}{\fnote_footnotemark:} +% This is the main command which will replace \cs{@footnotemark}. +% \begin{macrocode} \cs_new_protected:Npn \fnote_footnotemark: { \@@_debug_footnotemark: %------- @@ -535,17 +950,20 @@ % \end{macrocode} % If a footnote mark is placed by its own then it should finish by % executing \hook{fnmark/end}, resetting the space factor, and -% finishing with \hook{fnmark/after}. However, inf a complete +% finishing with \hook{fnmark/after}. However, in a complete % footnote these actions have to happen only after we have handled -% the footnote text (e.g., by placing it into an \cs{insert}. In +% the footnote text (e.g., by placing it into an \cs{insert}). In % such a situation \cs{_@@_footmark_finish:} below does nothing % and the action is carried out later. % \begin{macrocode} \@@_footnotemark_finish: } - - -\cs_new:Npn \@@_finish: { +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_finish:,\@@_footnotemark_finish:} +% \begin{macrocode} +\cs_new_protected:Npn \@@_finish: { % hyperref.sty % memhfixc.sty --- could move fnmark/after % scrlttr2.cls --- could vanish if footmisc uses a hook @@ -561,57 +979,30 @@ %------- } - \cs_new_eq:NN \@@_footnotemark_finish: \@@_finish: - - - +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@kernel@process@makefnmark} % Not a public config point but the kernel hook to add tagging +% \begin{macrocode} \def \@kernel@process@makefnmark { } - - -% alterations not covered: +% \end{macrocode} +% \end{macro} % -% ./arabtex/afoot.sty --- too different (and probably too old) - - -% Provide the name \LaTeXe{} is used to. - +% \begin{macro}{\@footnotemark} +% At last provide the name \LaTeXe{} is used to. +% \begin{macrocode} \cs_set_eq:NN \@footnotemark \fnote_footnotemark: - - - -%------------------------------------- - -\NewMirroredHookPair{fntext/before}{fntext/after} -\NewHook{fntext} -\NewHook{fntext/para} -\NewHook{fntext/begin} -\NewHook{fntext/end} - - -\cs_new:Npn \@@_debug_footnotetext: { - \bool_if:NT \g_fnote_debug_bool - { - \cs_log:N\@footnotetext@cfgpoint - \cs_log:N\@footnotetext@cfgpointii - \cs_log:N\@footnotetext@cfgpointiii - \cs_log:N\@footnotetext@cfgpointiv - \cs_log:N\@makefntext@cfgpoint - \cs_log:N\@makefntext@cfgpointii - \LogHook{fntext/before} - \LogHook{fntext} - \LogHook{fntext/para} - \LogHook{fntext/begin} - \LogHook{fntext/end} - \LogHook{fntext/after} % \end{macrocode} -% Show the info only once (if at all). +% \end{macro} +% +% +% \subsection{The new \cs{@footnotetext} command} +% +% +% \begin{macro}{\fnote_footnotetext:n} % \begin{macrocode} - \cs_gset_eq:NN \@@_debug_footnotetext: \prg_do_nothing: - } - } - \cs_new_protected:Npn \fnote_footnotetext:n #1 { \@@_debug_footnotetext: %------- @@ -690,55 +1081,75 @@ \UseHook{fntext/after} %------- } - +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@footnotetext@cfgpoint} % default for config point (1 arg) +% \begin{macrocode} \cs_new_protected:Npn \@footnotetext@cfgpoint { \insert\footins } - +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\@footnotetext@cfgpointii} % default for config point (1 arg) +% \begin{macrocode} \cs_new_protected:Npn \@footnotetext@cfgpointii { \@makefntext } - - +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@footnotetext@cfgpointiii} % default for config point (0 args) +% \begin{macrocode} \cs_new_protected:Npn \@footnotetext@cfgpointiii { \rule\z@\footnotesep } - +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@footnotetext@cfgpointiv} % default for config point (0 args) +% \begin{macrocode} \cs_new_protected:Npn \@footnotetext@cfgpointiv { \@finalstrut\strutbox } - - +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@kernel@process@footnotetext} % kernel hook for tagging (2 args) +% \begin{macrocode} \cs_new_protected:Npn \@kernel@process@footnotetext {} - +% \end{macrocode} +% \end{macro} +% % Provide the name \LaTeXe{} is used to and do this unconditionally % (no patching of class code if any). This means that if a class provides it own % definition that gets lost and if necessary needs to be handled -% with firstaid (or updating of the class. - -\AddToHook{begindocument}{ - \cs_set_eq:NN \@footnotetext \fnote_footnotetext:n -} - -% alterations not covered: +% with firstaid (or updating of the class). +% \begin{macrocode} +\AddToHook{begindocument} + { + \cs_set_eq:NN \@footnotetext \fnote_footnotetext:n + } +% \end{macrocode} % -% ./revtex4-1/revtex4-1.cls ./revtex/ltxutil.sty ./revtex/revtex4-2.cls ... (need analysis) -% ./bigfoot/bigfoot.sty - - - -% \footnotemargin is the logic implemented by footmisc. Perhaps we +% \subsection{The new \cs{@makefntext} command} +% +% \cs{footnotemargin} is the logic implemented by footmisc. Perhaps we % don't want to do this like that in the kernel but for now I have % used this interface unchanged. - - +% \begin{macrocode} \newdimen\footnotemargin \footnotemargin\maxdimen % no value given -\AtBeginDocument{ - \ifdim \footnotemargin=\maxdimen - \setlength\footnotemargin{1.8em} - \fi -} - +\AtBeginDocument + { + \ifdim \footnotemargin=\maxdimen + \setlength\footnotemargin{1.8em} + \fi + } +% \end{macrocode} +% \begin{macro}{\fnote_makefntext:n} +% \begin{macrocode} \cs_new_protected:Npn \fnote_makefntext:n #1 { % \end{macrocode} % Some classes in their redefinition for \cs{@makefntext} have @@ -765,36 +1176,45 @@ \@makefntext@cfgpointii { #1 } } - - - - +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@makefntext@cfgpoint} % default for config point (1 arg) +% \begin{macrocode} \cs_new_protected:Npn \@makefntext@cfgpoint { \noindent } - +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@makefntext@cfgpointii} % default for config point (1 arg) +% \begin{macrocode} \cs_new_protected:Npn \@makefntext@cfgpointii #1 { #1 } % \end{macrocode} +% \end{macro} % +% \subsubsection{Making documents use the new \cs{@makefntext}} % +% If the definition for \cs{@makefntext} is that of the standard +% classes then replace it with \cs{fnote_makefntext:n}, otherwise +% try to patch the definition. % -% If the definition for \cs{@makefntext} is that of the standard -% classes then replace it with \cs{fnote_makefntext:n}, otherwise -% try to patch the definition. +% Here is the definition the way it is in +% \texttt{classes.dtx}. Notice that (for saving space) there is no +% space after \texttt{em} to terminate the assignment. We need to +% mimic that, otherwise a test would return false even if the +% definition has not been modified. % -% Here is the the definition the way it is in -% \texttt{classes.dtx}. Notice that (for saving space) there is no -% space after \texttt{em} to terminate the assignment. We need to -% mimic that, otherwise a test would return false even if the -% definition has not been modified. % +% \begin{macro}{\old@std@class@makefntext} % \begin{macrocode} \newcommand\old@std@class@makefntext[1]{% \parindent 1em% \noindent \hb@xt@1.8em{\hss\@makefnmark}#1} - % \end{macrocode} +% \end{macro} +% % Here is the messy code for patching. Note that this is only there % to help classes along that aren't updated yet so it does some % minimal patching to hopefully add configuration points in the @@ -822,7 +1242,6 @@ % \cs{@makefnmark} without surrounding it in a box and if that % fails it gives up with an \cs{ERROR} (which needs to get a proper definition). % \begin{macrocode} - \tl_new:N \l_@@_patch_tl \cs_new_eq:NN \@@_tmp:w \ERROR @@ -853,6 +1272,7 @@ %\begin{verbatim} % AAA \@makefntext@processX { \hbox BBB } %\end{verbatim} +% % \begin{macrocode} \cs_new:Npn \@@_patch_hbox:w #1 \hbox #2 # { \exp_stop_f: #1 \@makefntext@processX { \hbox #2 } } @@ -869,25 +1289,27 @@ % different structure so this is a simple reshuffling. Would be % better if we can patch the right structure in directly, but I'm % not a patch person, so this is the simple way out for now: -% +% % \begin{macrocode} \cs_new:Npn \@makefntext@processX #1#2{\@makefntext@cfgpoint{#1{#2}}} % \end{macrocode} +% % At \verb=\begin{document}= check if the current definition is % that of the standard classes and if so replace it by % \cs{fnote_makefntext:n} otherwise try and patch the definition % using the approach above. % \begin{macrocode} -\AddToHook{begindocument}{ - \cs_if_eq:NNTF \@makefntext \old@std@class@makefntext - { - \cs_set_eq:NN \@makefntext \fnote_makefntext:n - } - { - \@@_patch: - } -} +\AddToHook{begindocument} + { + \cs_if_eq:NNTF \@makefntext \old@std@class@makefntext + { + \cs_set_eq:NN \@makefntext \fnote_makefntext:n + } + { + \@@_patch: + } + } % possibly add the following to check for multiple \hbox in @@ -898,63 +1320,112 @@ % % \end{macrocode} % +% \subsection{Document-level commands} % +% \begin{macro}{\footnotetext} +% \begin{macrocode} +\DeclareDocumentCommand\footnotetext {o+m} + { + \fnote_set_fnmark:nn {#1} \@mpfn + \@footnotetext {#2} + } +% \end{macrocode} +% \end{macro} % % -% \subsection{Document-level commands} -% -% \changes{v0.6b}{2022/07/22}{Make mandatory arguments of \cs{footnote} -% and \cs{footnotetext} long (gh863)} +% \begin{macro}{\footnote} % \begin{macrocode} +\DeclareDocumentCommand\footnote {o+m} + { + \fnote_step_fnmark:nn {#1} \@mpfn + \cs_set_eq:NN \@@_footnotemark_finish: \prg_do_nothing: + \@footnotemark + \cs_set_eq:NN \@@_footnotemark_finish: \@@_finish: + \@footnotetext {#2} + \@@_footnotemark_finish: + } +% \end{macrocode} +% \end{macro} +% -\DeclareDocumentCommand\footnotetext {o+m} { - \fnote_set_fnmark:nn {#1} \@mpfn - \@footnotetext {#2} -} - - -%------------------------------------- - - -\DeclareDocumentCommand\footnote {o+m} { - \fnote_step_fnmark:nn {#1} \@mpfn - \cs_set_eq:NN \@@_footnotemark_finish: \prg_do_nothing: - \@footnotemark - \cs_set_eq:NN \@@_footnotemark_finish: \@@_finish: - \@footnotetext {#2} - \@@_footnotemark_finish: -} - -%------------------------------------- - - -\DeclareDocumentCommand\footnotemark {o} { - \fnote_step_fnmark:nn {#1} { footnote } - \@footnotemark -} - - -%------------------------------------- - -\DeclareDocumentCommand\footref {m}{% - \begingroup - \unrestored@protected@xdef\@thefnmark{\ref{#1}}% - \endgroup - \@footnotemark -} - +% \begin{macro}{\footnotemark} +% \begin{macrocode} +\DeclareDocumentCommand\footnotemark {o} + { + \fnote_step_fnmark:nn {#1} { footnote } + \@footnotemark + } % \end{macrocode} -% +% \end{macro} + +% \begin{macro}{\footref} +% \cs{footref} used the starred \cs{ref} in \cs{@thefnmark} +% as the linking is handled by the tagging code inside +% the \cs{@footnotemark}. +% \cs{footref} should not try to link to its related related +% note automatically but should instead use the label. +% This is passed to \cs{@footnotemark} through +% \cs{l__fnote_currentlabel_tl}. +% % \begin{macrocode} -%<@@=> +\DeclareDocumentCommand\footref {m} + { + \begingroup + \unrestored@protected@xdef\@thefnmark{\ref*{#1}}% + \endgroup + \bool_set_false:N \l_@@_autodetect_bool + \tl_set:Nn \l_@@_currentlabel_tl {#1} + \@footnotemark + \bool_set_true:N \l_@@_autodetect_bool + } % \end{macrocode} +% \end{macro} % % +% \subsection{Firstaid for packages and classes} % +% \subsection{Kernel patches} +% Tagging of footnotes in minipages require a change in the minipage commands +% We define at first a local configuration command for minipage footnotes. % +% TODO remove the dependency to etoolbox, and need for the patch. +% \begin{macrocode} +\cs_new_protected:Npn \@mpfootnotetext@cfgpoint #1 + { + \global\setbox\@mpfootins\vbox{% + \unvbox\@mpfootins + #1 + } + } +% \end{macrocode} +% Then we patch \cs{@iiiminipage} +% \begin{macrocode} +\RequirePackage{etoolbox} +\ExplSyntaxOff +\patchcmd\@iiiminipage + {\let\@footnotetext\@mpfootnotetext} + {\let\@footnotetext@cfgpoint\@mpfootnotetext@cfgpoint} + {}{\ERROR} +\ExplSyntaxOn +% \end{macrocode} % +% \subsubsection{\pkg{memoir}} +% The \pkg{memoir} class redefines various internal commands to inject its +% hooks and addtional code. The following reinstates the kernel command and +% so probably breaks various options of \pkg{memoir}, but without the +% changes it errors anyway. The \pkg{footmisc} package should be used to change +% for example to para footnotes. % -% \subsection{Firstaid for packages and classes} +% \begin{macrocode} +\AddToHook{class/memoir/before} + { \let\new@std@class@makecol\@makecol } +\AddToHook{class/memoir/after} + { + \cs_set_eq:NN \@footnotemark \fnote_footnotemark: + \cs_set_eq:NN \@makefntext\old@std@class@makefntext + \cs_set_eq:NN \@makecol\new@std@class@makecol + } +% \end{macrocode} % % \subsubsection{\pkg{setspace}} % @@ -967,156 +1438,410 @@ % \end{macrocode} % % -% -% % \subsubsection{\pkg{hyperref}} % -% Prevent hyperref from redefining footnote stuff --- this is a -% temp solution. +% hyperref has a hook which allows to disable its footnote +% related patches. As we will handle links directly in the code +% this is used. +% % \begin{macrocode} -\AddToHook{package/hyperref/after}{ - \let\H@@footnotetext\fnote_footnotetext:n - \let\H@@footnotemark\fnote_footnotemark: - \let \@footnotetext \fnote_footnotetext:n - \let \@footnotemark \fnote_footnotemark: -} - - - +\def\hyper@nopatch@footnote{} % \end{macrocode} -% -% \subsection{Stuff that needs cleanup and documentation} -% +% We use the hyperref commands for now for links. To avoid +% to have to test for hyperref we provide dummies. +% TODO consider to use specials to get similar spacing. % \begin{macrocode} - - -%------------------------------------- - -% use of kerns to mark h-mode positions (unit sp) +\AtBeginDocument + { + \providecommand\hyper@linkstart{\@gobbletwo} + \providecommand\hyper@linkend{\@empty} + } +% \end{macrocode} % -% 1 = CJK -% 2 = CJK -% 3 = multiple footnotes (footmisc, koma, eledmac, tufte, memoir, -% parnotes, sidenotes) -% 3 = outer kern in letter spacing (letterspace) -% 3 = beginning of list (examdesign.cls) -% 4 = CJK pigin -% 5 = CJK ruby - -% 1-4 = polyglossia for korean - -%------------------------------------- - - - -%------------------------------------- -% Tagging -%------------------------------------- - -% hyperref support only when loaded (improve integration) - -\newcounter{absfootnote} -\AddToHook{fnmark/begin}{\stepcounter{absfootnote}} % too simple (fails with opt args) - - - -% this is rubbish and should be handled better: - -\cs_new_protected:Npn \tag_if_loaded:TF { \cs_if_exist:NTF \tag_struct_begin:n } - - - -\cs_new_protected:Npn \tag@FEMark #1 { - \tag_if_loaded:TF +% It must be possible to suppress the hyperlinking, both locally +% and globally. hyperref should set the boolean \cs{l_fnote_link_bool}. +% For now we test for the hyperref boolean (so it can be suppressed only globally). +% \begin{macrocode} +\AtBeginDocument + { + \@ifpackageloaded{hyperref} { - \tag_mc_end_push: - \exp_args:Nx - \tag_struct_begin:n{tag=Lbl,ref=fn.\the\c@absfootnote} - \tag_mc_begin:n{tag=Lbl} - \IfPackageLoadedTF{hyperref}{ \hyper@linkstart - {link}{fn.\the\c@absfootnote} }{} - #1 - \IfPackageLoadedTF{hyperref}{ \hyper@linkend }{} - \tag_mc_end: - \tag_struct_end: - \tag_mc_begin_pop:n{} + \legacy_if:nF{Hy@hyperfootnotes}{\bool_set_false:N \l_fnote_link_bool} } - { #1 } -} - -% to be done next round around: + { + \bool_set_false:N \l_fnote_link_bool + } + } +% \end{macrocode} % -% \the\c@absfootnote should be replaced directly by some command with default meaning -% \the\c@absfootnote so that the actual reference can be changed from the outside. +% \subsection{Tagging and hyperlink code} +% \subsubsection{Rolemap for structure tags} +% We use role-mapping to get more speaking names +% in the PDF and so ease debugging. These names are already +% provided by tagpdf directly. +% +% \subsubsection{Extending the label system} +% For \cs{footref} and (perhaps later for labeled footnotes) +% we must extend the label system. +% Beside the normal values we also need the structure number of the note. +% We use the \pkg{nameref} hook until latex provides a hook for its label. +% At first we define a suitable attribute, it uses as value the structure +% number of the note as stored in \cs{l__fnote_currentstruct_tl} +% \begin{macrocode} +\ref_attribute_gset:nnnn {fnote/struct}{1}{now}{\l_@@_currentstruct_tl} +% \end{macrocode} % -% there are several instances that are curently hardwired. - -\cs_set_eq:NN \@kernel@process@makefnmark \tag@FEMark - - - -% kernel hook for tagging (2 args) -\cs_set:Npn \@kernel@process@footnotetext #1#2 { - \tag_if_loaded:TF +% We add a hook to the \pkg{nameref} hook. By default it does nothing +% \begin{macro}{\@@_label_hook:} +% \begin{macrocode} +\cs_new_protected:Npn \@@_label_hook: {} +\AddToHook{begindocument/before} + { + \RequirePackage{nameref} + \g@addto@macro\label@hook + { + \@@_label_hook: + } + } +% \end{macrocode} +% \end{macro} +% Inside a footnotetext we change the hook to store the structure number too. +% nameref provides the name of label in \cs{label@name}. +% \begin{macrocode} +\AddToHook{fntext/begin} + { + \cs_set_protected:Npn \@@_label_hook: { - \tag_mc_end_push: - \tag_struct_begin:n { tag=FENote,label=fn.\the\c@absfootnote } - #1 {#2} - \tag_struct_end: - \tag_mc_begin_pop:n{} + \ref_label:Vn \label@name {fnote/struct} } - { #1 {#2} } -} - - + } +% \end{macrocode} +% +% \subsubsection{Storing and retrieving reference data} +% To establish the connection between a mark and a note +% the mark has to store its representation, and the +% note has to analyse the stored representations to get +% the structure numbers of its mark. This is done +% with the public function to allow similar systems (e.g. +% tabular notes, other footnote series) to make use of this. +% +% +% \begin{macro}{\fnote_new:nn} +% This sets up a new footnote type, the first argument +% is the name, the second is meant for options. Currently +% it does nothing at all. +% It is not necessary to setup every footnote like +% command as its own type! +% +% \begin{macrocode} +\cs_new_protected:Npn \fnote_new:nn #1 #2 % #1 name, #2 options + { + \prop_new:c { g_@@_currentmarks_ #1 _prop } + } -\cs_set:Npn \@makefntext@cfgpoint #1 { - \noindent - \cs_if_exist:NT \tag_struct_begin:n { \tag_mc_end_push: } - \tag@FELbl { #1 } -} +\fnote_new:nn {default}{} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\fnote_mark_gput:nn} +% This commands takes as argument the representation of the mark +% (e.g. \cs{@thefnmark} and the type (typically default should work) +% \begin{macrocode} +\cs_new_protected:Npn \fnote_mark_gput:nn #1 #2 % #1 the representation of the mark, #2 type + { + \prop_gput:cxn { g_@@_currentmarks_ #2 _prop } + { \tag_get:n{struct_num} } + { #1 } + } -\cs_set:Npn \@makefntext@cfgpointii #1 { - \tag@FENote { #1 } - \cs_if_exist:NT \tag_struct_begin:n { \tag_mc_begin_pop:n{} } -} +\cs_generate_variant:Nn \fnote_mark_gput:nn {no,oo} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\fnote_mark_gpop:nnN} +% This commands takes as argument the representation of the mark +% (e.g. the content of\cs{@thefnmark}), the series (typically default should work) +% and a sequence into which every structure number in the property +% is stored that has the same value as the mark +% \begin{macrocode} +\cs_new_protected:Npn \fnote_mark_gpop:nnN #1 #2 #3 + { + \seq_clear:N #3 + \prop_set_eq:Nc \l_@@_tmpa_prop { g_@@_currentmarks_ #2 _prop } + \prop_map_inline:Nn \l_@@_tmpa_prop + { + \tl_if_eq:nnT {#1} { ##2 } + { +% \end{macrocode} +% store the key (the structure number) in the seq +% \begin{macrocode} + \seq_put_right:Nn #3 { ##1 } +% \end{macrocode} +% remove entry as used from the global prop +% \begin{macrocode} + \prop_gremove:cn { g_@@_currentmarks_ #2 _prop } {##1} + } + } + } +\cs_generate_variant:Nn\fnote_mark_gpop:nnN {ooN} +% \end{macrocode} +% \end{macro} +% \subsubsection{Enabling tagging and links for the mark command} +% To handle the mark in the text, we define a special command +% which will surround \cs{@makefntext}. +% At this time \cs{@thefnmark} is already set. +% \begin{macrocode} +\cs_new_protected:Npn \tag@FEMark #1 %#1 content + { +% \end{macrocode} +% end an open mc and start the structure. +% \begin{macrocode} + \tag_mc_end_push: + \tag_struct_begin:n { tag=footnotemark } +% \end{macrocode} +% The associated note is either auto detected +% or given by the user. +% \begin{macrocode} + \bool_if:NTF \l_@@_autodetect_bool + { +% \end{macrocode} +% For the auto detecting we store the structure number +% and \cs{@thefnmark} inside a prop and set +% the target name of the link to the current structure number. +% TODO: this should be usable for other footnote types +% which means the name of the prop shouldn't be fix. +% \begin{macrocode} + \fnote_mark_gput:oo {\@thefnmark}{\l_fnote_type_tl} + \tl_set:Nx \l_@@_linktarget_tl {footnote*.\tag_get:n{struct_num}} + } +% \end{macrocode} +% If there is no autodetecting we need some id, +% currently it is called \cs{l__fnote_currentlabel_tl}. +% the Ref is set by looking at the label value. +% We must also add the current structure number to the \ref of the FEnote. +% Both must be delayed as we don't know if the objects of the FEnote and the mark +% have already been created. +% \begin{macrocode} + { + \hook_gput_code:nne {tagpdf/finish/before} {tagpdf/footnote} + { + \exp_not:N\fnote_gput_refs:ee + { \tag_get:n{struct_num} } + { \ref_value:Vn\l_@@_currentlabel_tl {fnote/struct} } + } +% \end{macrocode} +% in this case we set the name of the linktarget in the note +% to the structure number of the text mark. +% \begin{macrocode} + \tl_set:Nx \l_@@_linktarget_tl {footnote*.\ref_value:Vn\l_@@_currentlabel_tl {fnote/struct}} + } +% \end{macrocode} +% And now the actual content +% \begin{macrocode} + \tag_mc_begin:n{tag=Lbl} + % + \bool_if:NTF \l_fnote_link_bool + { + \exp_args:No + \hyper@linkstart + { \l_fnote_link_type_tl } + { \l_@@_linktarget_tl } + #1 + \hyper@linkend + } + { #1 } + \tag_mc_end: + \tag_struct_end: + \tag_mc_begin_pop:n{} + } +% \end{macrocode} +% At last set the kernel command to this one +% \begin{macrocode} +\cs_set_eq:NN \@kernel@process@makefnmark \tag@FEMark +% \end{macrocode} +% \subsubsection{The footnote text} -\cs_new_protected:Npn \tag@FELbl #1 { - \tag_if_loaded:TF - { - % target should perhaps be raised ... - \IfPackageLoadedTF{hyperref}{ \hypertarget{fn.\the\c@absfootnote}{} }{} - %\tag_struct_begin:n { tag=FENote,label=fn.\the\c@absfootnote } %alternativ location for structure - \tag_struct_begin:n { tag=Lbl } - \tag_mc_begin:n { tag=Lbl } - #1 - \tag_mc_end: - \tag_struct_end: - } - { #1 } -} +% We need a public command to append values to the Ref keys +% \begin{macro}{\@@_gput_ref:nn,\fnote_gput_refs:nn,\fnote_gput_refs:ee} +% \begin{macrocode} +\cs_new_protected:Npn \@@_gput_ref:nn #1 #2 %#1 the structure number receiving the ref #2 + { + \tag_if_active:T + { + \tag_struct_gput:nne {#1}{ref}{\tag_struct_object_ref:e { #2 }} + } + } +\cs_new_protected:Npn \fnote_gput_refs:nn #1 #2 % pair of numbers + { + \@@_gput_ref:nn {#1}{#2} + \@@_gput_ref:nn {#2}{#1} + } +\cs_generate_variant:Nn \fnote_gput_refs:nn {ee} +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +\tl_new:N \l_@@_dflt_struct_tl +\tl_set:Nn \l_@@_dflt_struct_tl {1} +% \end{macrocode} +% kernel hook for tagging (2 args) +% this sets the structure around the whole text +% +% \begin{macrocode} +\cs_new_protected:Npn \tag@FENote #1#2 % #1 config point, \insert\footins #2 content + { + \tag_mc_end_push: +% \end{macrocode} +% test if a footnote is allowed, if not move up to the document structure. +% \begin{macrocode} + \tag_check_child:nnTF {FENote}{pdf2} + { + \tag_struct_begin:n { tag=footnote } + } + { + \tag_struct_begin:n { tag=footnote,parent=\l_@@_dflt_struct_tl } + } +% \end{macrocode} +% Store the current structure number for labels. +% \begin{macrocode} + \tl_set:Nx \l_@@_currentstruct_tl { \tag_get:n{struct_num} } +% \end{macrocode} +% We want to move the label structure here. So we provide a container +% It number is |\l__fnote_currentstruct_tl| plus 1. +% \begin{macrocode} + \tag_struct_begin:n { tag=footnotelabel }\tag_struct_end: +% \end{macrocode} +% after we have opened the structure we can use the structure number to +% try to detect the connected marks. As with the marks we assume that sometimes +% no auto detection is done. +% \begin{macrocode} + \bool_if:NTF \l_@@_autodetect_bool + { +% \end{macrocode} +% find open marks with identical \cs{@thefnmark} +% \begin{macrocode} + \fnote_mark_gpop:ooN { \@thefnmark }{ \l_fnote_type_tl } \l_@@_currentrefs_seq +% \end{macrocode} +% Then we store the object numbers of the marks in the /Ref of the FENote structure: +% and the number of the FEnote into the marks structure: +% \begin{macrocode} + \seq_map_inline:Nn \l_@@_currentrefs_seq + { + \fnote_gput_refs:ee {##1}{ \l_@@_currentstruct_tl } + } + } +% \end{macrocode} +% If no auto detection is done +% \begin{NOTE}{UF} +% TODO: decide what to do here: some label in the optional argument? +% or refer to \cs{footref} +% \end{NOTE} +% \begin{macrocode} + {%no auto -\cs_new_protected:Npn \tag@FENote #1 { - \tag_if_loaded:TF - { - \tag_mc_begin:n{tag=FENote} - #1 + } +% \end{macrocode} +% This finish the setup of the tagging structure. +% Now we process the text. The destinations for the links are set with the label +% so that we can be sure that we are in hmode. +% \begin{macrocode} + #1 {#2} + \tag_struct_end: + \tag_mc_begin_pop:n{} + } +% \end{macrocode} +% At last set the kernel command to this one +% \begin{macrocode} +\cs_set_eq:NN \@kernel@process@footnotetext \tag@FENote +% \end{macrocode} +% +% \cs{@makefntext@cfgpoint} is the configuration point responsible for +% typesetting the mark in the note. We use it to surround +% the mark with the needed tagging commands. +% +% TODO check if this should/can be kernel configuration points +% or if an additional kernel configuration points are needed. +% If yes, what about the paragraph start and the paratagging?? +% +% \begin{macrocode} +\cs_set_protected:Npn \@makefntext@cfgpoint #1 %#1 code that typesets the mark. + { + \noindent + \tag_mc_end_push: + \tag@FENoteLbl { #1 } + \tag_mc_begin_pop:n{} + } +% \end{macrocode} +% \cs{tag@FENoteLbl} creates the label in the note on the bottom. +% It also adds link targets for the hyperlinking. +% +% \begin{macro}{\tag@FENoteLbl} +% \begin{macrocode} +\cs_new_protected:Npn \tag@FENoteLbl #1 + { +% \end{macrocode} +% We create a link target for every related mark. The name is footnote* + structure number +% of the mark. We also add a link target for the current structure (for footref) +% \begin{macrocode} + %\seq_show:N\l_@@_currentrefs_seq + \seq_map_inline:Nn\l_@@_currentrefs_seq {\MakeLinkTarget*{footnote*.##1}} + \MakeLinkTarget*{footnote*.\l_@@_currentstruct_tl} +% \end{macrocode} +% now we add the tagging commands. We move the structure of the label to +% to the container at the begin of the note. +% \begin{NOTE}{UF} +% check if the NonStruct is really needed. Perhaps we can simply move the mc. +% \end{NOTE} +% \begin{macrocode} + \tag_struct_begin:n { tag=NonStruct,parent=\l_@@_currentstruct_tl +1 } + \tag_mc_begin:n { tag=Lbl } + #1 \tag_mc_end: - %\tag_struct_end: %alternative location for structure end but ends inside a P - } - { #1 } -} - + \tag_struct_end: + } +% \end{macrocode} +% \end{macro} +% +% +% \cs{@makefntext@cfgpointii} is the +% configuration point around the actual note text. +% +% TODO check if this should/can be kernel configuration points +% \begin{macrocode} +\cs_set_protected:Npn \@makefntext@cfgpointii #1 + { + \tag_mc_end_push: + \tag@FENotetext { #1 } + \tag_mc_begin_pop:n{} + } +% \end{macrocode} +% \begin{macro}{\tag@FENotetext} +% +% This command currently only adds an MC chunk, +% +% TODO Should it set a mc or could it rely on the content? +% \begin{macrocode} +\cs_new_protected:Npn \tag@FENotetext #1 + { + \tag_mc_begin:n{} + #1 + \tag_mc_end: + } +% \end{macrocode} +% \end{macro} %------------------------------------- - +% \begin{macrocode} \ExplSyntaxOff %</kernel> % \end{macrocode} -% +% \begin{macrocode} +%<@@=> +% \end{macrocode} % % \section{Reimplementing the \pkg{footmisc} package} % @@ -1571,7 +2296,10 @@ \ifFN@multiplefootnote \providecommand*{\multiplefootnotemarker}{3sp} - \providecommand*{\multfootsep}{,} +% we tag the separator as artifact + \ExplSyntaxOn + \providecommand*{\multfootsep}{\tag_mc_end_push:\tag_mc_begin:n{artifact},\tag_mc_end:\tag_mc_begin_pop:n{}} + \ExplSyntaxOff \AddToHook{fnmark} {\FN@mf@check} \AddToHook{fnmark/end} {\FN@mf@prepare} % |