summaryrefslogtreecommitdiff
path: root/macros
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2020-06-21 03:02:27 +0000
committerNorbert Preining <norbert@preining.info>2020-06-21 03:02:27 +0000
commit9f10616edfed3b801246055ec6d06631ff60f9b1 (patch)
treed143be5217ed52f0895aa56a068090d530966afb /macros
parenteb6236a4ba3566f36e4f6f8cf78f39ea56861520 (diff)
CTAN sync 202006210302
Diffstat (limited to 'macros')
-rw-r--r--macros/generic/namedef/DEPENDS.txt1
-rw-r--r--macros/generic/namedef/README.md73
-rw-r--r--macros/generic/namedef/namedef.dtx1425
-rw-r--r--macros/generic/namedef/namedef.ins90
-rw-r--r--macros/generic/namedef/namedef.pdfbin0 -> 633001 bytes
-rw-r--r--macros/latex/contrib/apa7/apa7.dtx36
-rw-r--r--macros/latex/contrib/apa7/apa7.pdfbin522083 -> 522679 bytes
-rw-r--r--macros/latex/contrib/apa7/samples/longsample.pdfbin196731 -> 196731 bytes
-rw-r--r--macros/latex/contrib/apa7/samples/shortsample.pdfbin64110 -> 64110 bytes
-rw-r--r--macros/latex/contrib/hyperxmp/hyperxmp.dtx491
-rw-r--r--macros/latex/contrib/hyperxmp/hyperxmp.pdfbin1326332 -> 1341156 bytes
-rw-r--r--macros/latex/contrib/pict2e/README.md3
-rw-r--r--macros/latex/contrib/pict2e/p2e-drivers.pdfbin216020 -> 216020 bytes
-rw-r--r--macros/latex/contrib/pict2e/pict2e.dtx83
-rw-r--r--macros/latex/contrib/pict2e/pict2e.pdfbin887097 -> 889454 bytes
15 files changed, 2004 insertions, 198 deletions
diff --git a/macros/generic/namedef/DEPENDS.txt b/macros/generic/namedef/DEPENDS.txt
new file mode 100644
index 0000000000..574e1c1ca4
--- /dev/null
+++ b/macros/generic/namedef/DEPENDS.txt
@@ -0,0 +1 @@
+hard l3kernel
diff --git a/macros/generic/namedef/README.md b/macros/generic/namedef/README.md
new file mode 100644
index 0000000000..5cf05c4abc
--- /dev/null
+++ b/macros/generic/namedef/README.md
@@ -0,0 +1,73 @@
+# namedef
+Named parameters in TeX definitions
+
+This package allows you to use names rather than numbers in TeX
+definitions. Usually a definition would look like:
+```tex
+\def\SayHello#1%
+ {Hello, #1!}
+```
+which is usually good enough. However sometimes when writing macros the
+programmer (I, at least) has a macro with several arguments, and then
+adding another argument before `#1` requires changing all the numbers
+in the definition:
+```tex
+\def\Say#1#2%
+ {#1, #2!}
+```
+which again, is usually fine most of the time. But sometimes the
+definition is rather long, and has a handful of arguments, so changing
+the order requires the programmer to change a lot of `#1` to `#2` in the
+code, which is tedious, at best.
+
+With `namedef` you can prefix your definition with `\named`, then every
+parameter should be given a name:
+```tex
+\named\def\SayHello#[subject]%
+ {Hello, #[subject]!}
+```
+then adding another argument before the existing ones is trivial:
+```tex
+\named\def\Say#[greeting]#[subject]%
+ {#[greeting], #[subject]!}
+```
+and to change the order of the arguments you just swap `#[greeting]` and
+`#[subject]` in the <code>&langle;parameter text&rangle;</code>. No
+other changes required!
+
+Note that this can be (ab)used for writing macros, but it should
+probably be removed for publishing the code.
+
+---
+
+This repository contains the source code `namedef.dtx` and the
+installation file `namedef.ins`. To create the package file
+`namedef.sty`, run:
+```
+tex namedef.ins
+```
+and to produce the documentation, run:
+```
+pdflatex namedef.ins
+```
+
+---
+
+Copyright (C) 2019--2020 Phelype Oleinik
+
+This work may be distributed and/or modified under the conditions of
+the LaTeX Project Public License, either version 1.3c of this license
+or (at your option) any later version. The latest version of this
+license is in
+
+ http://www.latex-project.org/lppl.txt
+
+and version 1.3c or later is part of all distributions of LaTeX
+version 2005/12/01 or later.
+
+This work is "maintained" (as per the LPPL maintenance status)
+by Phelype Oleinik.
+
+Please send bug reports or feature requests at the project repository:
+https://github.com/PhelypeOleinik/namedef
+or by e-mail (contact info in the source file).
diff --git a/macros/generic/namedef/namedef.dtx b/macros/generic/namedef/namedef.dtx
new file mode 100644
index 0000000000..01e2cb8aec
--- /dev/null
+++ b/macros/generic/namedef/namedef.dtx
@@ -0,0 +1,1425 @@
+% \iffalse meta-comment
+% Copyright (C) 2019--2020
+% by Phelype Oleinik <phelype.oleinik@latex-project.org>
+%
+% This work may be distributed and/or modified under the conditions of
+% the LaTeX Project Public License, either version 1.3c of this license
+% or (at your option) any later version. The latest version of this
+% license is in
+%
+% http://www.latex-project.org/lppl.txt
+%
+% and version 1.3c or later is part of all distributions of LaTeX
+% version 2005/12/01 or later.
+%
+% This work is "maintained" (as per the LPPL maintenance status)
+% by Phelype Oleinik.
+%
+%<*package>
+\def\namedefDate{2020-06-20}
+\def\namedefVersion{1.0}
+%</package>
+%<*driver>
+\documentclass[a4paper,full,inline]{l3doc}
+\usepackage[T1]{fontenc}
+\usepackage{microtype}
+\usepackage{namedef}
+\usepackage{bookmark}
+\usepackage{xcolor}
+
+\def\TODO#1#{\begingroup\afterassignment\TODODO\let\tmp = }
+\def\TODODO{\setbox0=\vbox\bgroup\aftergroup\ENDTODO}
+\def\ENDTODO{\endgroup\ignorespaces}
+
+\begingroup
+ \lccode`~=`\%
+ \lowercase{\endgroup
+ \def\VRBCodes{^^A
+ \catcode`~=13
+ \def~{\%\global\linenofalse}}
+}
+\makeatletter
+\define@key{FV}{labelformat}{%
+ \def\FV@LabelFormat{#1}%
+ \ifx\FV@LabelFormat\FV@None
+ \let\FV@LabelFormat\relax
+ \fi}
+\def\FV@Label@ii[#1]#2\@nil{%
+ \def\@tempa{#1}%
+ \ifx\@tempa\empty
+ \def\FV@LabelBegin{\FV@LabelFormat#2}%
+ \else
+ \def\FV@LabelBegin{\FV@LabelFormat#1}%
+ \def\FV@LabelPositionBottomLine{\@ne}%
+ \fi
+ \def\FV@LabelEnd{\FV@LabelFormat#2}}
+\makeatother
+\DefineVerbatimEnvironment%
+ {example}{Verbatim}
+ {
+ gobble=3,
+ frame=single,
+ commandchars=|<>,
+ codes={\VRBCodes},
+ numbers=left,
+ labelformat=\rmfamily\bfseries,
+ }
+\def\mshow#1{> \string#1=\meaning#1}
+\newif\iflineno\linenotrue%\fi
+\def\theFancyVerbLine{^^A
+ \rmfamily
+ \scriptsize
+ \color{gray}^^A
+ \iflineno
+ \arabic{FancyVerbLine}^^A
+ \else
+ \global\addtocounter{FancyVerbLine}{-1}^^A
+ \fi
+ \global\linenotrue
+}
+\pdfstringdefDisableCommands{\let\footnotemark\relax}
+
+% Substitute lmtt/it by lmtt/sl
+\DeclareFontShape{T1}{lmtt}{lc}{it}{<->ssub*lmtt/lc/sl}{}
+
+\begin{document}
+ \overfullrule=5pt
+ \DocInput{\jobname.dtx}
+\end{document}
+%</driver>
+% \fi
+%
+% \GetFileInfo{\jobname.sty}
+%
+% \title{^^A
+% The \pkg{namedef} package\\
+% Named parameters in \TeX{} definitions^^A
+% \thanks{This file has version number \namedefVersion,
+% last revised \namedefDate.}
+% }
+%
+% \author{^^A
+% Phelype H. Oleinik\thanks
+% {^^A
+% E-mail:
+% \href{mailto:phelype.oleinik@latex-project.org}
+% {phelype.oleinik\meta{at}latex-project.org}^^A
+% }^^A
+% }
+%
+% \date{Released \namedefDate}
+%
+% \maketitle
+%
+% \begin{documentation}
+%
+% \section{Introduction}
+%
+% This package provides a somewhat dubious, however useful way to make
+% \TeX{} definitions using \cs{def} and the like. The usual way to
+% define a ``hello world'' macro is |\def\hello#1{Hello #1!}|. Sure,
+% this is easy (for people using this package, at least), but sometimes
+% I stumbled upon the case where I had a macro defined with something
+% like |\def\macro#1#2#3#4#5#6{#6#1#4#3#5#2}| and then I had to, for
+% whatever reason, add another argument before |#1|. Oh, the pain. But
+% OK, occupational hazard. And then I change my mind and needed to
+% revert. This package provides a way to give a semantic meaning to the
+% arguments of a definition such that it becomes clearer in meaning and
+% easier to change when an argument's identifier defines what it means
+% rather than its position in a list.
+%
+% \subsection{Features}
+%
+% This package defines a macro, \cs{named}, which acts like a prefix for
+% \cs{def} (the same way as \cs{long} and the like), and allows one to
+% rewrite the \cs{hello} macro like this:
+% |\named\def\hello#[who]{Hello #[who]!}|. Sure, a macro with one
+% argument won't see much benefit from it, but as soon as that number
+% increases, a better description of the arguments comes in handy.
+%
+% The package also defines a macro \cs{NamedDelim} which allows the user
+% to change the delimiter of the named parameters to their liking. For
+% example, after |\NamedDelim //| the example above changes to:
+% |\named\def\hello#/who/{Hello #/who/!}|. The default is
+% |\NamedDelim []|.
+%
+% The only dependency of this package is the \LaTeX3 programming layer,
+% \pkg{expl3}, thus this package works in any format and engine
+% supported by \pkg{expl3}. In \LaTeXe, load it with
+% |\usepackage{namedef}|, and in other formats with
+% |\input namedef.sty|.
+%
+% \subsection{Feedback}
+%
+% Bugs, feature requests, or suggestions are most welcome. You can send
+% them by e-mail or to the source code repository at
+% \url{https://github.com/PhelypeOleinik/namedef}.
+%
+% \section{Usage}
+%
+% \begin{function}{\named}
+% \begin{syntax}
+% \cs{named}\meta{other~prefixes}\meta{\cs[no-index]{(e,g,x)def}}^^A
+%\meta{parameter text}\marg{replacement text}
+% \end{syntax}
+% The \cs{named} macro will grab the \meta{other~prefixes}, the
+% \cs{def} command, the \meta{parameter~text} and
+% \meta{replacement~text}, and will replace every ocurrence of
+% |#[|\meta{text}|]| by a suitable |#|\meta{number} for \TeX{} to
+% carry on with the definition.
+%
+% The \meta{other~prefixes} can be any combination of \cs{long},
+% \cs{outer}, \cs{global}, and \cs{protected}. As for \TeX, their
+% relative order doesn't matter, except that \cs{named} must appear
+% \emph{before} any \cs{global} prefix. Other prefixes are detected
+% whether placed before or after \cs{named}.
+%
+% The \cs{def} command can be anything. The package will not check the
+% validity of the command, it will simply drag the token along until
+% the point where the definition is made. This allows one to use any
+% of \TeX's primitive \cs{def} commands as well as, for instance,
+% \pkg{expl3}'s \cs{cs_new:Npn} or the like. However \cs{named} will
+% not work with \LaTeX's \cs{newcommand} or \pkg{xparse}'s
+% \cs{NewDocumentCommand} and the like because their syntax is
+% completely different.
+%
+% The \meta{parameter~text} is the same \meta{parameter~text} that
+% would be used if the \cs{named} prefix wasn't used with the
+% difference that all |#|\meta{number} must be replaced by a
+% |#[|\meta{name}|]|. The characters |[| and |]| are mandatory and the
+% character |]| cannot appear in \meta{name}, however |[| and |]| can
+% still appear in the \meta{parameter~text} without restriction; the
+% special meaning is only applied after a parameter token (|#|).
+% \meta{name} can be anything that when fully expanded returns a
+% string of characters (anything valid in |\csname|\dots|\endcsname|).
+% The \meta{parameter~text} cannot, however, contain numbered
+% parameters anymore (|#1|,~|#2|,~\dots).
+% \TODO{This is not enforced... What should be done in this case?}
+%
+% The \meta{replacement~text} is also the same \meta{replacement~text}
+% that would be used otherwise, with all |#|\meta{number} replaced by
+% |#[|\meta{name}|]|.
+% \end{function}
+%
+% \begin{function}{\NamedDelim,\globalNamedDelim}
+% \begin{syntax}
+% \cs{NamedDelim}\meta{begin-token}\meta{end-token}
+% \cs{globalNamedDelim}\meta{begin-token}\meta{end-token}
+% \end{syntax}
+% These macros change the delimiter of the named parameters from the
+% default |#[|\meta{name}|]| to
+% |#|\meta{begin-token}\meta{name}\meta{end-token}. Both delimiters
+% must be one single non-macro token. Valid delimiters are character
+% tokens with catcode $3$, $4$, $7$, $8$, $11$, $12$, or $13$
+% (see section~\ref{sec:delimiters}).
+%
+% \cs{globalNamedDelim} is the same as \cs{NamedDelim} except that the
+% effect of the former has global scope, while the latter is local to
+% a group. While you can use both, you should be careful not to
+% interleave them too much or you might exhaust \TeX's save stack.
+%
+% Delimiters are matched based on their character code (using \cs{if})
+% so changes in their category code doesn't matter as long as that
+% change doesn't prevent the character from becoming a token or the
+% category code isn't \enquote{too special} :-) \quad (see above).
+%
+% The choice of delimiter is mostly ``what you like better''. Neither
+% the delimter tokens nor the name of the parameter make it to the
+% macro itself. They are just code-level abstractions. Thus the
+% delimiter should be something that the person writing the code can
+% easily distinguish from the rest of the code. For example, the code
+% |\NamedDelim xz \named\def\test#xyz{xyz#xyzxyz}| works, but its
+% readability is questionable.
+% \end{function}
+%
+% \subsection{Limitations}
+%
+% As already stated the command does not work (and I don't intend to
+% make it work) with \LaTeXe's \cs{newcommand} and its family because
+% a) the argument specification is by the number of arguments, so you
+% can't ``declare'' them as with \cs{def}, and b) because it's supposed
+% to be used for user-level interfaces, which usually (and preferably)
+% have a low argument count, so numbering shouldn't be a problem.
+% That said, see section~\ref{sec:newcommand}.
+%
+% For \pkg{xparse}'s \cs{NewDocumentCommand} the situation is the same.
+% Other than these, \cs{named} should work for whatever type of
+% definition that uses \TeX's \cs{def} syntax.
+%
+% Another limitation that I'd like to change in a future release (but
+% still don't know the best way to make the interface) is to support
+% definition commands which go beyond the
+% \meta{parameter~text}|{|\meta{replacement~text}|}| syntax. For
+% instance, in \pkg{expl3} a conditional that checks whether its
+% argument is negative can be defined like this (for integers, of
+% course):
+% \begin{Verbatim}
+% \prg_new_conditional:Npnn \namedef_if_negative:n #1 { T, F, TF }
+% {
+% \if_int_compare:w #1 < 0
+% \prg_return_true:
+% \else:
+% \prg_return_false:
+% \fi:
+% }
+% \end{Verbatim}
+% And if one tried to use \cs{named} in that definition it would fail
+% because this command takes one extra argument before the
+% \meta{replacement~text}. Something could be done to allow one (or
+% more) extra argument before the \meta{replacement~text}.
+%
+% \medskip
+% One serious limitation is when used with definitions that expand their
+% argument, namely \cs{edef} and \cs{xdef}. This type of definition
+% expands tokens as it reads them, possibly changing their meaning
+% during the process. \cs{named}, however, first grabs the definition as
+% argument to process the named arguments before actually performing the
+% definition, so these ``unexpected'' changes of meaning might make the
+% code misbehave. While writing this manual I could think of two (and a
+% half) situations which will be problematic and how to work around them
+% (sorry, no solution for now; suggestions are welcome :).
+%
+%^^A \begingroup
+% \edef\hash{\string#}
+% \edef\¿{\csname @gobble\expandafter\endcsname\string\\}
+% \def\nedeft{\ttfamily\¿named\¿edef\¿test}
+%
+% \subsubsection{\nedeft\{\¿string\#[arg]\}}
+% \label{sec:edef wa1}
+%
+% The normal (no \cs{named}) counterpart of this one is a perfectly
+% valid definition: |\edef\test{\string#1}|. While expanding the
+% \meta{replacement~text}, \cs{string} turns the parameter token |#|$_6$
+% into a character |#|$_{12}$, thus defining |\test| to expand to the
+% two characters |#1|. When using \cs{named}, however, the replacement
+% routine doesn't know what \cs{string} does to the token next to it, so
+% it goes on and treats |#[arg]| as one named argument only to find out
+% that it was never defined in the \meta{parameter~text}, so it aborts
+% the definition with an error.
+%
+% This will occur in the specific case where the user wishes to have the
+% macro expand to the characters |#[arg]|, without replacement by a
+% parameter. In this case the work-around is to temporarily switch the
+% delimiter tokens of \cs{named}'s scanner:
+% \begin{Verbatim}
+% \NamedDelim||
+% \named\edef\test{\string#[arg]}
+% \NamedDelim[]
+% \end{Verbatim}
+% in which case the scanner will still see the |#| as a parameter token
+% but since it is no longer followed by a delimiter, it will be simply
+% passed on to the definition. Afterwards, at the time \TeX{} tries to
+% carry on with the definition, \cs{string} will do its thing to |#|
+% without further problems.
+%
+% \subsubsection{\nedeft\#[arg]\{\¿string\}\#[arg]\}}
+% \label{sec:edef wa2}
+%
+% This one, as the previous, works fine without \cs{named}:
+% |\edef\test#1{\string}#1}|. Again, when \TeX{} scans this definition,
+% it will expand \cs{string} which will turn the end group token |}|$_2$
+% into a character |}|$_{12}$, which will have \TeX{} end the definition
+% with the next~|}|$_2$, after the |#1|. This only works because \TeX{}
+% does not grab the whole thing as argument before expanding. Which is
+% precisely what \cs{named} does.
+%
+% When \cs{named} grabs the definition as argument the first |}|
+% ends the \meta{replacement~text}, so what \cs{named} effectively sees
+% is |\edef\test#[arg]{\string}|, which is then processed (|#[arg]| is
+% replaced by |#1|) and left back in the input stream for \TeX{} to do
+% its thing, however the replacement |#[arg]| is never replaced:
+% |\edef\test#1{\string}#[arg]}|, then when \TeX{} tries to do the
+% definition it will complain about an ``! Illegal parameter number in
+% definition of |\test|.''
+%
+% The work-around in this case is to do a dirty brace trick to lure
+% \cs{named} into grabbing the whole thing as argument, but which will
+% disappear at the time \TeX{} performs the expansion and definition.
+% One option is |\iffalse{\fi|:
+% \begin{Verbatim}
+% \named\edef\test#[arg]{%
+% \iffalse{\fi \string}#[arg]}
+% \end{Verbatim}
+% In this example \cs{named} will process everything, but at the time of
+% the definition the entire |\iffalse{\fi| thing expands to nothing and
+% the final definition becomes the same as the one without \cs{named}.
+% The |\iffalse{\fi| block can also be left in the definition
+% \emph{without} named and the result will be the same. One could argue
+% that using the brace hack is safer because it doesn't change the
+% definition, yet avoid problems when grabbing the definition as
+% argument in a general situation.
+%
+% \let\SVsubsec\thesubsubsection
+% \def\thesubsubsection{^^A
+% \thesubsection .\number\numexpr\value{subsubsection}-1,5}
+%
+% \subsubsection{\nedeft\#[arg]\{\¿string\{\#[arg]\}}
+% \label{sec:edef wa3}
+%
+% \let\thesubsubsection\SVsubsec
+%^^A \endgroup
+%
+% This is rather similar to the previous one, except that the brace
+% later-to-be-detokenized begins a group: |\edef\test#1{\string{#1}|.
+% Here \TeX{} also expands \cs{string} and makes |{|$_1$ a |{|$_{12}$
+% which does not count in the brace balancing. \cs{named}, however, will
+% count it when grabbing the definition as argument and will require one
+% more |}|$_2$. If the code is run as is \TeX{} will probably report a
+% ``File ended while scanning use of \dots'' error unless there happens
+% to be a matching |}|$_2$ somewhere else, in which case the definition
+% will just go wrong. The work-around here is the same as the one
+% before, with |}| instead:
+% \begin{Verbatim}
+% \named\edef\test#[arg]{%
+% \string{#[arg]\iffalse}\fi}
+% \end{Verbatim}
+% This will ensure that \cs{named} will see the |}| it needs to grab the
+% definition correctly and will disappear once the definition is done.
+%
+% \subsection{Invalid delimiters}
+% \label{sec:delimiters}
+%
+% The delimiters that can be used should be character tokens with
+% catcode $3$, $4$, $7$, $8$, $11$, $12$, or $13$. Characters with
+% catcode $0$, $5$, $9$, $14$, and $15$ don't produce tokens to start
+% with, so they can't possibly be used. The remaining category codes
+% are currently disallowed in the code because they make the input
+% ambiguous or because they make the implementation more complex with no
+% real advantage.
+%
+% Catcodes $1$ and $2$ (begin-/end-group) cannot be used because they
+% become indistinguishable from the braces that delimit the
+% \meta{parameter~text} of the definition, so the input is ambiguous.
+%
+% Catcode $6$ (macro parameter) cannot be used because it gets hard to
+% distinguish a named parameter from some text surrounded by parameter
+% tokens. For example in: |\named\edef\foo#name#{\string#then#name#}|,
+% \pkg{namedef} would raise an error on |#then#| (unknown parameter)
+% without knowing that the first |#|$_{6}$ becomes |#|$_{12}$ and the
+% actual parameter is |#name#|\dots Or is it? I'm not entirely convinced
+% of my own argument, so this might be implemented in the future.
+%
+% Catcode $10$ (blank space) is possible but it requires a hanful of
+% extra precautions to avoid losing the space when passing arguments
+% around. Since it makes for a strange-looking syntax (our eyes are
+% trained to ignore spaces), this is not supported.
+%
+% \section{Boring examples}
+%
+% The following examples show two definitions each, which are the same,
+% but the second uses \cs{named}. The third line in each example shows
+% the \cs{meaning} of the defined macro.
+%
+% First the basics, replacing a numbered parameter by a named one:
+% \named\def\hello#[who]{Hello #[who]!}
+% \begin{example}[label=Basics]
+% \def\hello#1{Hello #1!}
+% \named\def\hello#[who]{Hello #[who]!}
+% |mshow|hello
+% \end{example}
+% \smallskip
+%
+% Prefixes can be added at will after the \cs{named} prefix:
+% \named\protected\long\edef\hello#[who]{Hello #[who]!}
+% \begin{example}[label=Prefixes]
+% \protected\long\edef\hello#1{Hello #1!}
+% \named\protected\long\edef\hello#[who]{Hello #[who]!}
+% |mshow|hello
+% \end{example}
+% \smallskip
+%
+%^^A Whatever prefixes put before \cs{named} will be lost. Notice that
+%^^A even though \cs{protected} is used, the macro itself is not defined
+%^^A with \cs{protected}:
+%^^A \protected\named\long\edef\hello#[who]{Hello #[who]!}
+%^^A \begin{example}[label=Wrong Prefixes]
+%^^A \protected \long\edef\hello#1{Hello #1!}
+%^^A \protected\named\long\edef\hello#[who]{Hello #[who]!}
+%^^A |mshow|hello
+%^^A \end{example}
+%^^A \smallskip
+%
+% This example is just to show that the named argument delimiter doesn't
+% interfere with the text in the macro:
+% \named\def\hello[#[who]]{Hello #[who]!}
+% \begin{example}[label=Argument delimited by \texttt{[} and \texttt{]}]
+% \def\hello[#1]{Hello #1!}
+% \named\def\hello[#[who]]{Hello #[who]!}
+% |mshow|hello
+% \end{example}
+% \smallskip
+%
+% However, for readability, the delimiter can be changed to something
+% else:
+% \named\def\hello[#[who]]{Hello #[who]!}
+% \begin{example}[label=Argument delimited by \texttt{[} and \texttt{]},
+% commandchars=/<>,firstnumber=0]
+% \NamedDelim{|}{|}
+% \def\hello[#1]{Hello #1!}
+% \named\def\hello[#|who|]{Hello #|who|!}
+% /mshow/hello
+% \end{example}
+% \smallskip
+%
+% This example demonstrates multiple arguments and arbitrary
+% \meta{parameter~text}:
+% \named\def\cfbox #[color] to #[width]#[content]{%
+% \fbox{\hbox to #[width]{\color{#[color]}#[content]}}}
+% \begin{example}[label=More arguments]
+% \def\cfbox #1 to #2#3{\fbox{\hbox to #2{\color{#1}#3}}}
+% \named\def\cfbox #[color] to #[width]#[content]{%
+% \fbox{\hbox to #[width]{\color{#[color]}#[content]}}}
+% |mshow|cfbox
+% \end{example}
+% \smallskip
+%
+% \TeX's weird |#{| argument can be used as well:
+% \named\def\cbox #[color] to #[width]#{^^A
+% \hbox to #[width]\bgroup\color{#[color]}\let\next= }
+% \begin{example}[label=Weird arguments]
+% \def\cbox #1 to #2#{\hbox to #2\bgroup\color{#1}\let\next= }
+% \named\def\cbox #[color] to #[width]#{%
+% \hbox to #[width]\bgroup\color{#[color]}\let\next= }
+% |mshow|cbox
+% \end{example}
+% \smallskip
+%
+% {\NamedDelim XX
+% \named\xdef\test{\string#[arg]}}
+% \begin{example}[commandchars=/<>, label=
+% \texttt{\string\edef} workaround \ref{sec:edef wa1}]
+% \edef\test{\string#[arg]}
+% \NamedDelim || /global/linenofalse
+% \named\edef\test{\string#[arg]} /global/linenofalse
+% \NamedDelim []
+% /mshow/test
+% \end{example}
+% \smallskip
+%
+% \named\edef\test#[arg]{\iffalse{\fi\string}#[arg]}
+% \begin{example}[label=
+% \texttt{\string\edef} workaround \ref{sec:edef wa2}]
+% \edef\test#1{\string}#1}
+% \named\edef\test#[arg]{\iffalse{\fi\string}#[arg]}
+% |mshow|test
+% \end{example}
+% \smallskip
+%
+% \named\edef\test#[arg]{\string{#[arg]\iffalse}\fi}
+% \begin{example}[label=
+% \texttt{\string\edef} workaround \ref{sec:edef wa3}]
+% \edef\test#1{\string{#1}
+% \named\edef\test#[arg]{\string{#[arg]\iffalse}\fi}
+% |mshow|test
+% \end{example}
+% \smallskip
+%
+% \section{Interesting\protect\footnotemark\ examples}
+% \footnotetext{Terms and Conditions may apply.}
+%
+% These examples shows a few more elaborate ways to use \pkg{namedef}.
+%
+% \subsection{Extended \cs{newcommand}}
+% \label{sec:newcommand}
+%
+% Here's an implementation to allow the syntax of \pkg{namedef} in
+% \cs{newcommand}. It uses \pkg{xparse} to handle optional arguments,
+% and uses \cs{newcommand} itself to define (possibly) optional argument
+% handling, so the resulting command uses \LaTeXe's command parsing
+% machinery.
+%
+% The syntax of the defined command is:
+%
+% |\newnamedcommand|\meta{*}\cs[no-index]{\meta{cmd}}\oarg{arg-list}^^A
+% [\meta{opt}=\meta{default}]\marg{definition}
+%
+% \noindent where everything is the same as in regular \cs{newcommand},
+% except for the optional arguments \meta{arg-list} and
+% \meta{opt}=\meta{default}. \meta{arg-list} should be a
+% comma-separated list of named parameters as \cs{named} would expect,
+% and \meta{opt} is a named parameter, and \meta{default} is its default
+% value. The usage would be something like:
+%
+% |\newnamedcommand\foo[#[one],#[two]][#[opt]=default]%|\par
+% \quad|{#[one], #[two], and #[opt]}|
+%
+% \noindent which translates to:
+%
+% |\newcommand\foo[3][default]%|\par
+% \quad|{#2, #3, and #1}|
+%
+% First, load \pkg{xparse} and \pkg{namedef}, and define the top-level
+% commands to use a common |\NNC_newcommand:NnNnnn|.
+% |\NNC_newcommand:NnNnnn| will store the mandatory arguments in
+% a \texttt{seq} variable for easier access, then call
+% |\__NNC_newcommand:NnNn| to do the \cs{newcommand} part of the job,
+% and |\__NNC_named_def:nNnn| to \cs{named} part.
+% |\new...|, |\renew...|, and |\provide...| versions are defined, but
+% since a \cs{def} is used later with no checking, the behaviour is
+% not exactly the same as you'd get with \cs{newcommand} in this regard.
+%
+% \begin{example}
+% \usepackage{namedef}
+% \usepackage{xparse}
+% \ExplSyntaxOn
+% \seq_new:N \l__NNC_args_seq
+% \scan_new:N \s__NNC
+% \NewDocumentCommand \newnamedcommand { s m o o m }
+% { \NNC_newcommand:NnNnnn \newcommand {#1} #2 {#3} {#4} {#5} }
+% \NewDocumentCommand \renewnamedcommand { s m o o m }
+% { \NNC_newcommand:NnNnnn \renewcommand {#1} #2 {#3} {#4} {#5} }
+% \NewDocumentCommand \providenamedcommand { s m o o m }
+% { \NNC_newcommand:NnNnnn \providecommand {#1} #2 {#3} {#4} {#5} }
+% \named \cs_new_protected:Npn \NNC_newcommand:NnNnnn
+% #[newcmd] #[star] #[cmd] #[args] #[opt] #[defn]
+% {
+% \seq_clear:N \l__NNC_args_seq
+% \IfValueT {#[args]}
+% { \seq_set_from_clist:Nn \l__NNC_args_seq {#[args]} }
+% \__NNC_newcommand:NnNn #[newcmd] {#[star]} #[cmd] {#[opt]}
+% \__NNC_named_def:nNnn {#[star]} #[cmd] {#[opt]} {#[defn]}
+% }
+% \end{example}
+%
+% |\__NNC_newcommand:NnNn| does the \cs{newcommand} part of the job. It
+% takes the arguments read in by \pkg{xparse}, and translates them into
+% the \cs{newcommand} syntax. The number of items in the |#[args]|
+% parameter is counted and left within brackets, and the default value
+% of the optional argument is also left within another pair of brackets.
+% This step is executed with an empty definition because the named
+% parameters will cause havoc in \cs{newcommand}.
+%
+% \begin{example}[firstnumber=last]
+% \named \cs_new_protected:Npn \__NNC_newcommand:NnNn
+% #[newcmd] #[star] #[cmd] #[opt]
+% {
+% \use:x
+% {
+% \exp_not:N #[newcmd]
+% \IfBooleanT {#[star]} { * }
+% \exp_not:N #[cmd]
+% \seq_if_empty:NF \l__NNC_args_seq
+% { [ \seq_count:N \l__NNC_args_seq ] }
+% \IfValueT {#[opt]} { [ \__NNC_opt_value:w #[opt] \s__NNC ] }
+% { }
+% }
+% }
+% \cs_new:Npn \__NNC_opt_value:w #1 = #2 \s__NNC {#2}
+% \end{example}
+%
+% Now |\__NNC_named_def:nNnn| will do the \cs{named} part.
+% First the |#[star]| argument (if not present) becomes \cs{long}, and
+% then comes \cs{named} and \cs{def}. Then, if an optional argument was
+% given, the command we need to define is |\\foo| rather than |\foo|, so
+% use take care of that with \cs{token_to_str:N}, and then leave the
+% named parameter given for the optional argument within brackets.
+% If there's no optional argument, we just define |#[cmd]| (pretty
+% boring). Then we call \cs{seq_use:Nn} on the mandatory arguments to
+% lay them flat for \cs{named}, and then the parameter text (|#[defn]|),
+% unexpanded.
+%
+% \begin{example}[firstnumber=last]
+% \named \cs_new_protected:Npn \__NNC_named_def:nNnn
+% #[star] #[cmd] #[opt] #[defn]
+% {
+% \use:x
+% {
+% \IfBooleanF {#[star]} { \long }
+% \named \def
+% \IfValueTF {#[opt]}
+% {
+% \exp_not:c { \token_to_str:N #[cmd] }
+% [ \exp_not:o { \__NNC_opt_name:w #[opt] \s__NNC } ]
+% }
+% { \exp_not:N #[cmd] }
+% \seq_use:Nn \l__NNC_args_seq { }
+% { \exp_not:n {#[defn]} }
+% }
+% }
+% \cs_new:Npn \__NNC_opt_name:w #1 = #2 \s__NNC {#1}
+% \ExplSyntaxOff
+% \end{example}
+%
+% \end{documentation}
+%
+% \begin{implementation}
+%
+% \section{\pkg{namedef} Implementation}
+%
+% \begin{macrocode}
+%<*package>
+%<@@=namedef>
+% \end{macrocode}
+%
+% \subsection{Loading}
+%
+% \begin{macro}{\@@_end_package_hook:}
+% Load \pkg{expl3}, either through \cs{RequirePackage} or through
+% inputting the generic loader, depending on the format in use
+% (copied from Bruno Le Floch's \pkg{gtl}).
+% \begin{macrocode}
+\begingroup\expandafter\expandafter\expandafter\endgroup
+\expandafter\ifx\csname RequirePackage\endcsname\relax
+ \input expl3-generic.tex
+\else
+ \RequirePackage{expl3}[2018-05-15]
+\fi
+\ExplSyntaxOn
+\cs_if_exist:NTF \ProvidesExplPackage
+ {
+ \cs_new_eq:NN \@@_end_package_hook: \prg_do_nothing:
+ \ExplSyntaxOff
+ \ProvidesExplPackage
+ }
+ {
+ \cs_new_eq:NN \@@_end_package_hook: \ExplSyntaxOff
+ \group_begin:
+ \ExplSyntaxOff
+ \cs_set_protected:Npn \@@_tmp:w #1#2#3#4
+ {
+ \group_end:
+ \tl_gset:cx { ver @ #1 . sty } { #2 ~ v#3 ~ #4 }
+ \cs_if_exist_use:NF \wlog { \iow_log:x }
+ { Package: ~ #1 ~ #2 ~ v#3 ~ #4 }
+ }
+ \@@_tmp:w
+ }
+ {namedef} {\namedefDate} {\namedefVersion}
+ {Named parameters in TeX definitions (PHO)}
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Declarations}
+%
+% \begin{macro}{\flag @@_parm_count}
+% A flag (mis)used as a counter to keep track of the parameter number.
+% \begin{macrocode}
+\flag_new:n { @@_parm_count }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\c_@@_prefix_tl}
+% A prefix to use as name space for temporary macros.
+% \begin{macrocode}
+\tl_const:Nn \c_@@_prefix_tl { namedef~parm~-> }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\l_@@_macro_tl}
+% A token list to store the name of the macro meing defined for error
+% messages.
+% \begin{macrocode}
+\tl_new:N \l_@@_macro_tl
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\q_@@_mark,\q_@@_stop}
+% Quarks used throughout the package.
+% \begin{macrocode}
+\quark_new:N \q_@@_mark
+\quark_new:N \q_@@_stop
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\s_@@}
+% Scan mark used to skip code.
+% \begin{macrocode}
+\scan_new:N \s_@@
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_skip_to_scan_mark:w, \@@_skip_to_scan_mark:nw}
+% Consume everything up to \cs{s_@@}.
+% \begin{macrocode}
+\cs_new:Npn \@@_skip_to_scan_mark:w #1 \s_@@ { }
+\cs_new:Npn \@@_skip_to_scan_mark:nw #1 #2 \s_@@ {#1}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_tmp:w}
+% A scratch macro.
+% \begin{macrocode}
+\cs_new_eq:NN \@@_tmp:w ?
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{The top-level \cs{named} macro}
+%
+% \begin{macro}{\named}
+% \begin{macro}{\@@_grab_prefix:nN}
+% Starts scanning ahead for prefixes and the definition
+% command. Once finished the scanning of prefixes, call
+% \cs{@@_replace_named:nNnn} to do the heavy lifting.
+% \begin{macrocode}
+\cs_new_protected:Npn \named { \@@_grab_prefix:nN { } }
+\cs_new_protected:Npn \@@_grab_prefix:nN #1 #2
+ {
+ \@@_if_prefix:NTF #2
+ { \@@_grab_prefix:nN }
+ { \@@_detect_prefixes:Nn \@@_kill_outer:nN }
+ { #1#2 }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[pTF]{\@@_if_prefix:N}
+% Checks against a list of valid prefixes and returns |true| or
+% |false| accordingly.
+% \begin{macrocode}
+\prg_new_conditional:Npnn \@@_if_prefix:N #1 { TF }
+ {
+ \if_int_compare:w 0
+ \if_meaning:w \tex_protected:D #1 1 \fi:
+ \if_meaning:w \tex_global:D #1 1 \fi:
+ \if_meaning:w \tex_outer:D #1 1 \fi:
+ \if_meaning:w \tex_long:D #1 1 \fi:
+ \if_meaning:w \scan_stop: #1 1 \fi:
+ = 1 \exp_stop_f:
+ \prg_return_true:
+ \else:
+ \prg_return_false:
+ \fi:
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_detect_prefixes:Nn}
+% \begin{macro}[rEXP]{\@@_extract_prefixes:w}
+% \begin{macro}[rEXP]{
+% \@@_extract_protected:n, \@@_extract_protected_aux:w,
+% \@@_extract_long:n, \@@_extract_long_aux:w,
+% \@@_extract_outer:n, \@@_extract_outer_aux:w,
+% }
+% Defines a scratch macro \cs{@@_tmp:w} and queries its prefixes, then
+% forwards them to the the next macro to perform the parameter
+% replacement and definition.
+%
+% This code would be quite a lot simpler if \cs{outer} didn't exist.
+% First extract the meaning of \cs{@@_tmp:w}, and pass the prefixes
+% (before ``|macro:|'') to \cs{@@_extract_prefixes:w}, and then to
+% \cs{@@_extract_protected:n}, \cs{@@_extract_long:n}, and
+% \cs{@@_extract_outer:n} in turn to check if each of these prefixes
+% is there.
+%
+% \cs{global} can't be checked this way because it's different from
+% other prefixes in the sense that it affects the definition \emph{at
+% the time} of the definition, rather than at the time it is used.
+% I don't know if it's possible to detect a \cs{global} after it's
+% already consumed by \TeX.
+%
+% \TODO{\cs{afterassignment} tokens are lost. It would be nice if
+% it were possible to retrieve it and save until later.}
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_detect_prefixes:Nn #1 #2
+ {
+ \cs_set_nopar:Npn \@@_tmp:w { }
+ \use:x
+ {
+ \exp_not:N #1
+ {
+ \exp_after:wN \exp_after:wN
+ \exp_after:wN \@@_extract_prefixes:w
+ \exp_after:wN \token_to_meaning:N
+ \cs:w @@_tmp:w \cs_end: \s_@@
+ \exp_not:n {#2}
+ }
+ }
+ }
+\use:x
+ {
+ \cs_new:Npn \exp_not:N \@@_extract_prefixes:w ##1
+ \tl_to_str:n { macro: } ##2 \s_@@
+ {
+ \exp_not:N \@@_extract_protected:n {##1}
+ \exp_not:N \@@_extract_long:n {##1}
+ \exp_not:N \@@_extract_outer:n {##1}
+ }
+ }
+\cs_set_protected:Npn \@@_tmp:w #1 #2
+ {
+ \use:x
+ {
+ \cs_new:cpn { @@_extract_#1:n } ####1
+ {
+ \exp_not:c { @@_extract_#1_aux:w } ####1
+ \token_to_str:N #2 \scan_stop: \token_to_str:N #2 \s_@@
+ }
+ \cs_new:cpn { @@_extract_#1_aux:w } ####1
+ \token_to_str:N #2 ####2 \token_to_str:N #2 ####3 \s_@@
+ {
+ \exp_not:N \if_meaning:w \scan_stop: ####2
+ \exp_not:N \else:
+ \exp_not:c { tex_#1:D }
+ \exp_not:N \fi:
+ }
+ }
+ }
+\@@_tmp:w { protected } { \protected }
+\@@_tmp:w { long } { \long }
+\@@_tmp:w { outer } { \outer }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Main routine}
+%
+% \begin{macro}{\@@_kill_outer:nN}
+% \begin{macro}{\@@_start:nNp, \@@_replace_named:nNnn}
+% \begin{macro}{\@@_replace_parameter:Nn, \@@_parameter_output:nnw}
+% \begin{macro}{\@@_handle_parameter:nN}
+% \begin{macro}{\@@_define:nnnN}
+% Here we play dirty: abuse the fact that \cs{exp_not:N} temporarily
+% makes the \cs{noexpand}ed control sequence temporarily equal to
+% \cs{relax}. But rather than using it in an \cs{edef} or whatnot,
+% hit \cs{exp_not:N} with \cs{exp_after:wN}, and then quickly grab
+% it with \cs{@@_start:nNp}, so it's safe to grab it, even if it's
+% \cs{outer}. If that wasn't bad enough, do it once again to make
+% it equal to \cs{relax} in the scope of \cs{@@_replace_named:nNnn}
+% so that it doesn't blow up.
+%
+% \TODO{Currently |\named\def{\foo}{bar}| works, but perhaps it
+% shouldn't.}
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_kill_outer:nN #1
+ {
+ \cs_set:Npn \@@_tmp:w { \@@_start:nNp {#1} }
+ \exp_after:wN \@@_tmp:w \exp_not:N
+ }
+\cs_new_protected:Npn \@@_start:nNp #1 #2 #3 #
+ {
+ \group_begin:
+ \int_set:Nn \tex_escapechar:D { `\\ }
+ \exp_after:wN \cs_set_eq:NN \exp_not:N #2 \scan_stop:
+ \@@_replace_named:nNnn {#1} #2 {#3}
+ }
+% \end{macrocode}
+%
+% Here the actual replacement of named parameters by numbered ones
+% takes place. A group is started to revert the flag and all the
+% defined temporary macros.
+%
+% \cs{@@_replace_parameter:Nn} \cs{@@_in_parameter:nN} starts
+% replacing a dummy macro in the generic parameter replacement routine
+% by the macro which counts the parameters and aliases the named
+% parameters with numbered ones. Finally it starts
+% \cs{@@_replace_parm:Nn}, which scans the \meta{parameter~text} for
+% the named parameters and replaces them by numbered ones. The second
+% output argument of \cs{@@_replace_parm:Nn} is a list of definitions
+% which assign a number to each named parameter so that they can be
+% used in the next step.
+%
+% \cs{@@_replace_parameter:Nn} \cs{@@_in_replacement:nN} then starts
+% by replacing the same dummy macro by one which will replace the
+% named parameter by its number. Again \cs{@@_replace_parm:Nn} is
+% started, and its output is the already-processed part of the
+% \meta{replacement~text}.
+%
+% The output of both steps is inserted after \cs{@@_define:nnnN} (it's
+% missing two arguments in the definition of
+% \cs{@@_replace_named:nNnn}). After all that is done, all the named
+% parameters were replaced by numbered ones, so \cs{@@_define:nnnN}
+% can do its thing.
+%
+% A final quark is put in the input stream for recovery from errors.
+% In a successful run this quark is removed by \cs{@@_define:nnnN}.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_replace_named:nNnn #1 #2 #3 #4
+ {
+ \tl_set:Nx \l_@@_macro_tl { \token_to_str:N #2 }
+ \@@_replace_parameter:Nn \@@_in_parameter:nN {#3}
+ \@@_replace_parameter:Nn \@@_in_replacement:nN {#4}
+ \@@_define:nnnN {#1} #2
+ \s_@@
+ }
+\cs_new_protected:Npn \@@_define:nnnN #1 #2 #3 #4
+ {
+ \group_end:
+ #3#4#2{#1}
+ }
+\cs_new_protected:Npn \@@_replace_parameter:Nn #1 #2
+ {
+ \cs_set_eq:NN \@@_handle_parameter:nN #1
+ \@@_replace_parm:Nn \@@_parameter_output:nnw {#2}
+ }
+\cs_new_eq:NN \@@_handle_parameter:nN ?
+\cs_new_protected:Npn \@@_parameter_output:nnw #1 #2
+ #3 \@@_define:nnnN
+ { #2 #3 \@@_define:nnnN {#1} }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_in_parameter:nN, \@@_in_replacement:nN}
+% These two functions handle the named parameters when they are found
+% in the \meta{parameter~text} and \meta{replacement~text},
+% respectively.
+%
+% \cs{@@_in_parameter:nN} checks if the named parameter already exists
+% (with \cs{relax} being |true|) and, in such case, throws an error
+% and inserts the number already set for that named parameter.
+% Otherwise the parameter is \cs{let} to
+% \cs{relax} so that if it is found later an error is issued. Setting
+% a macro to \cs{relax} is an expandable way to define it (the same
+% approach as in \pkg{l3flag}). After that,
+% the \cs{flag @@_parm_count} is raised once and its height is used as
+% the parameter number. The current parameter tokens and the parameter
+% number are flushed to the first (left) output slot, and a definition
+% |\cs_set:cpn {|\cs{c_@@_prefix_tl}~\meta{name}|} {|\meta{number}|}|
+% is appended to the second (right) output slot so that the names can
+% be used in the \meta{replacement~text}.
+%
+% In case of a repeated parameter it is tricky to do anything
+% sensible. In a normal definition, when \TeX{} sees a repeated
+% parameter number (like in |\def\foo#1#1{}|) it just uses the wrong
+% number to a parameter number not yet taken, or ignores the parameter
+% if there's already nine before that. However here we can't guess
+% the name of the next parameter, so we can't do much. The easiest
+% way out is to just use the same parameter number as before and go
+% on with out job: at the end, \TeX{} will complain again about this.
+% \begin{macrocode}
+\cs_new:Npn \@@_in_parameter:nN #1
+ {
+ \if_cs_exist:w \c_@@_prefix_tl #1 \cs_end:
+ \exp_after:wN \use_i:nn
+ \else:
+ \exp_after:wN \use_ii:nn
+ \fi:
+ { \msg_expandable_error:nnn { namedef } { repeated-parm } {#1} }
+ {
+ \exp_after:wN \use_none:n \cs:w \c_@@_prefix_tl #1 \cs_end:
+ \flag_raise:n { @@_parm_count }
+ }
+ \exp_args:Nf \@@_append_output:nnNwnn
+ { \flag_height:n { @@_parm_count } }
+ {#1}
+ }
+% \end{macrocode}
+%
+% \cs{@@_in_replacement:nN} also checks if the named parameter exists,
+% however now it will be \emph{not} be \cs{relax}, but the number
+% defined earlier, so \cs{cs_if_exist:cTF} can be safely used. If the
+% parameter does not exist it was never declared in the
+% \meta{parameter~text} (somewhat like |\def#1{#2}|), then raise an
+% error and abort.
+% Otherwise just flush |#|\meta{number}.
+% \begin{macrocode}
+\cs_new:Npn \@@_in_replacement:nN #1 #2
+ {
+ \cs_if_exist:cTF { \c_@@_prefix_tl #1 }
+ {
+ \exp_args:Nf \@@_append_output:nnNwnn
+ { \use:c { \c_@@_prefix_tl #1 } }
+ { }
+ }
+ {
+ \msg_expandable_error:nnn { namedef } { unknown-parm } {#1}
+ \exp_args:Ne \@@_append_output:nnNwnn
+ { #2 \@@_begin_name_token: #1 \@@_end_name_token: }
+ { \cs_end: { } \use_none:nn }
+ }
+ #2
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Scanning routine}
+%
+% \begin{macro}[EXP]{\@@_replace_parm:Nn}
+% \begin{macro}[EXP]{\@@_replace_loop:w}
+% \begin{macro}[EXP]{\@@_replace_end:wnn, \@@_flush:nw}
+% \begin{macro}[EXP]{\@@_append_output:nnNwnn}
+% \begin{macro}[EXP]{\@@_abort_definition:w}
+% \cs{@@_replace_parm:Nn} uses the same looping principle as in
+% \pkg{l3tl}'s \cs{__tl_act:NNNnn}. It scans the input (here, the
+% \meta{parameter~text} and \meta{replacement~text}, separately) token
+% by token, differentiating spaces, braced tokens (groups), and
+% \enquote{normal} tokens.
+% \begin{macrocode}
+\cs_new:Npn \@@_replace_parm:Nn #1 #2
+ {
+ \exp_after:wN #1
+ \exp:w
+ \@@_replace_loop:w #2
+ \q_@@_mark \q_@@_stop { } { }
+ }
+\cs_new:Npn \@@_replace_loop:w #1 \q_@@_stop
+ {
+ \tl_if_head_is_N_type:nTF {#1}
+ { \@@_replace_normal:N }
+ {
+ \tl_if_head_is_group:nTF {#1}
+ { \@@_replace_group:n }
+ { \@@_replace_space:w }
+ }
+ #1 \q_@@_stop
+ }
+\cs_new:Npn \@@_replace_end:wnn \q_@@_stop #1 #2
+ { \exp_end: {#1} {#2} }
+\cs_new:Npn \@@_flush:nw #1
+ #2 \q_@@_stop #3 #4
+ { \@@_replace_loop:w #2 \q_@@_stop { #3 #1 } {#4} }
+% \end{macrocode}
+%
+% \cs{@@_append_output:nnNwnn} takes three arguments (a parameter
+% number, a parameter name, and a parameter token) and the two output
+% slots as |#5| and |#6|. It appends the parameter token and number
+% to the first output slot, and a definition
+% |\cs_set:cpn {|\cs{c_@@_prefix_tl}~\meta{name}|} {|\meta{number}|}|
+% to the second output slot.
+% \begin{macrocode}
+\cs_new:Npn \@@_append_output:nnNwnn #1 #2 #3
+ #4 \q_@@_stop #5 #6
+ {
+ \@@_replace_loop:w #4 \q_@@_stop
+ { #5 #3#1 }
+ { #6 \cs_set:cpn { \c_@@_prefix_tl #2 } {#1} }
+ }
+% \end{macrocode}
+%
+% This macro doesn't really abort the definition at the time it's
+% called because it's called from within an |f|-expansion context, so
+% an attempt to end that prematurely will hardly end well. Instead
+% it hijacks the process by inserting
+% \cs{@@_skip_to_scan_mark:w} in the second output slot, so that
+% the definition end as soon as the scanning ends.
+% \TODO{Can be simplified further.}
+% \begin{macrocode}
+\cs_new:Npn \@@_abort_definition:w
+ #1 \q_@@_stop #2 #3
+ {
+ \@@_replace_loop:w #1 \q_@@_stop
+ {#2} { #3 \group_end: \@@_skip_to_scan_mark:w }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[EXP]{\@@_replace_normal:N}
+% \begin{macro}[EXP]{\@@_replace_group:n, \@@_flush_group:nnw}
+% \begin{macro}[EXP]{\@@_replace_space:w}
+% Spaces are just passed through: they aren't parameter tokens nor
+% valid delimiters, so need no special treatment.
+%
+% Braced tokens are recursively scanned by \cs{@@_replace_parm:Nn},
+% and the output is flushed inside a pair of braces (explicit catcode
+% $1$ and $2$ tokens are normalised to |{|_$1$ and |}|_$2$,
+% respectively)
+% \TODO{Since \cs{__tl_act:NNNnn} isn't used anymore, this doesn't
+% have to be |f|-expandable, so this restriciton can probably be
+% lifted.}
+%
+% The remaining tokens are examined for their meaning. If the token
+% is the quark \cs{q_@@_mark}, the scanning stops; if the token is a
+% parameter token, what follows is examined with \cs{@@_grab_parm:Nw}
+% to check if a replacement should be done; otherwise it's fluhsed to
+% the output.
+% \begin{macrocode}
+\cs_new:Npn \@@_replace_normal:N #1
+ {
+ \token_if_eq_meaning:NNTF \q_@@_mark #1
+ { \@@_replace_end:wnn }
+ {
+ \token_if_parameter:NTF #1
+ { \@@_grab_parm:Nw }
+ { \@@_flush:nw }
+ {#1}
+ }
+ }
+\cs_new:Npn \@@_replace_group:n #1
+ { \@@_replace_parm:Nn \@@_flush_group:nnw {#1} }
+\cs_new:Npn \@@_flush_group:nnw #1 #2
+ { \@@_flush:nw { {#1} } }
+\exp_last_unbraced:NNo
+\cs_new:Npn \@@_replace_space:w \c_space_tl
+ { \@@_flush:nw { ~ } }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Parsing a parameter}
+%
+% \begin{macro}[EXP]{\@@_grab_parm:Nw}
+% \begin{macro}[EXP]{\@@_grab_parm_aux:NNw, \@@_grab_parm_noop:NNw}
+% \begin{macro}[EXP]{\@@_grab_parm_scan:NNw}
+% \begin{macro}[EXP]{\@@_grab_parm_loop:nw, \@@_grab_parm_end:nw}
+% \begin{macro}[EXP]{
+% \@@_parm_get_normal:nN,
+% \@@_parm_get_group:nn,
+% \@@_parm_get_space:nw
+% }
+% These macros are the final pieces of the parameter replacement
+% routine. \cs{@@_grab_parm:Nw} checks if the next token in the stream
+% is a valid |N|-type. If it is, then \cs{@@_grab_parm_aux:NNw} checks
+% if its character code is equal to \cs{@@_begin_name_token:}, and if
+% it is, then call \cs{@@_grab_parm_scan:NNw} to scan ahead for the
+% named parameter. In all other cases, the tokens grabbed are not
+% named parameters, so they are flushed to the output.
+% \begin{macrocode}
+\cs_new:Npn \@@_grab_parm:Nw #1 #2 \q_@@_stop
+ {
+ \tl_if_head_is_N_type:nTF {#2}
+ { \@@_grab_parm_aux:NNw }
+ { \@@_flush:nw }
+ #1 #2 \q_@@_stop
+ }
+\cs_new:Npn \@@_grab_parm_aux:NNw #1 #2
+ {
+ \exp_args:No \token_if_eq_charcode:NNTF
+ { \@@_begin_name_token: } #2
+ { \@@_grab_parm_scan:NNw }
+ { \@@_grab_parm_noop:NNw }
+ #1 #2
+ }
+% \end{macrocode}
+%
+% Here we have to take care not to flush \cs{q_@@_mark} to the output.
+% \begin{macrocode}
+\cs_new:Npn \@@_grab_parm_noop:NNw #1 #2
+ {
+ \token_if_eq_meaning:NNTF \q_@@_mark #2
+ { \@@_flush:nw { #1 } #2 }
+ { \@@_flush:nw { #1 #2 } }
+ }
+% \end{macrocode}
+%
+% Here's the actual scanning routine. It would be a lot faster to
+% just define a delimiter macro with the right tokens, however this
+% would have two consequences: first, missing delimiters would be
+% rather catastrophic, and second, the catcode of the |end| delimiter
+% would need to match. With a manual scanning, we can kill off those
+% two items at the cost of some performance.
+%
+% The scanning routine is pretty standard: a looping macro, an output
+% slot, the tokens to be scanned, \cs{q_@@_stop} to delimit the whole
+% thing (\cs{q_@@_mark} is redundant here: the one from the main
+% scanning rountine is already in place), and the parameter token
+% safely stored at the end:
+% \begin{macrocode}
+\cs_new:Npn \@@_grab_parm_scan:NNw #1 #2 #3 \q_@@_stop
+ { \@@_grab_parm_loop:nw { } #3 \q_@@_stop {#1} }
+\cs_new:Npn \@@_grab_parm_loop:nw #1 #2 \q_@@_stop
+ {
+ \tl_if_head_is_N_type:nTF {#2}
+ { \@@_parm_get_normal:nN }
+ {
+ \tl_if_head_is_group:nTF {#2}
+ { \@@_parm_get_group:nn }
+ { \@@_parm_get_space:nw }
+ }
+ {#1} #2 \q_@@_stop
+ }
+% \end{macrocode}
+%
+% If the end of the token list was reached (signalled by
+% \cs{q_@@_mark}), the |end| delimiter is missing. If so, raise an
+% error and recover as gracefully as possible. Otherwise, if the
+% current token is the same character as the \cs{@@_end_name_token:},
+% then the scaning is complete.
+% \begin{macrocode}
+\cs_new:Npn \@@_parm_get_normal:nN #1 #2
+ {
+ \token_if_eq_meaning:NNTF \q_@@_mark #2
+ {
+ \msg_expandable_error:nn { namedef } { missing-end }
+ \@@_grab_parm_end:nw {#1} #2
+ }
+ {
+ \exp_args:No \token_if_eq_charcode:NNTF
+ { \@@_end_name_token: } #2
+ { \@@_grab_parm_end:nw {#1} }
+ { \@@_grab_parm_loop:nw {#1#2} }
+ }
+ }
+\cs_new:Npn \@@_parm_get_group:nn #1 #2
+ { \@@_grab_parm_loop:nw { #1{#2} } }
+\cs_new:Npn \@@_parm_get_space:nw #1 ~
+ { \@@_grab_parm_loop:nw { #1~ } }
+\cs_new:Npn \@@_grab_parm_end:nw #1 #2 \q_@@_stop #3
+ { \@@_handle_parameter:nN {#1} #3 #2 \q_@@_stop }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Changing delimiters}
+%
+% \begin{macro}[EXP]{\@@_begin_name_token:, \@@_end_name_token:}
+% These two hold the delimiters for named parameters. They are
+% initialised here so that we can use \cs{named} (just to show off)
+% ahead, and they are redefined every time \cs{NamedDelim} is used.
+% \begin{macrocode}
+\cs_new:Npn \@@_begin_name_token: { [ }
+\cs_new:Npn \@@_end_name_token: { ] }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\NamedDelim, \globalNamedDelim}
+% \begin{macro}{\@@_named_delim_set:Nnn}
+% \begin{macro}{\@@_check_delimiter:n}
+% At this point everything for the \cs{named} macro is set up,
+% so we can start using it. Now just some syntactic sugar to
+% allow the modification of the named argument delimiters.
+%
+% Both \cs{NamedDelim} and \cs{globalNamedDelim} take two arguments,
+% an initial and final delimiters for the named argument. Both
+% delimters should be single non-control sequence tokens. Some of
+% these restrictions could be lifted, but it's not really necessary
+% because the choice of delimiter should not influence the working of
+% the code, only the readability. A code with |\NamedDelim[]| and
+% |\def\test#[1][#[2]]{[#[1]][#[2]]}| should work without problems;
+% the only restriction is that \cs{@@_end_name_token:} (\emph{i.e.,}
+% the second argument of \cs{NamedDelim}) cannot appear in the
+% parameter name.
+% \begin{macrocode}
+\cs_new_protected:Npn \NamedDelim
+ { \@@_named_delim_set:Nnn \cs_set:Npn }
+\cs_new_protected:Npn \globalNamedDelim
+ { \@@_named_delim_set:Nnn \cs_gset:Npn }
+\named \cs_new_protected:Npn \@@_named_delim_set:Nnn
+ #[def] #[begin] #[end]
+ {
+ \tl_trim_spaces_apply:nN {#[begin]} \@@_check_delimiter:n
+ \tl_trim_spaces_apply:nN {#[end]} \@@_check_delimiter:n
+ #[def] \@@_begin_name_token: {#[begin]}
+ #[def] \@@_end_name_token: {#[end]}
+ \s_@@
+ }
+% \end{macrocode}
+%
+% Here the \meta{token} is checked against a bunch of forbidden cases.
+% \begin{macrocode}
+\named \cs_new_protected:Npn \@@_check_delimiter:n #[token]
+ {
+% \end{macrocode}
+% It can't be empty (nor a space: they were trimmed above):
+% \begin{macrocode}
+ \tl_if_empty:nT {#[token]}
+ {
+ \msg_error:nn { namedef } { blank-delim }
+ \@@_skip_to_scan_mark:w
+ }
+% \end{macrocode}
+% It can't be multiple tokens:
+% \begin{macrocode}
+ \tl_if_single_token:nF {#[token]}
+ {
+ \msg_error:nnn { namedef } { multi-token-delim } {#[token]}
+ \@@_skip_to_scan_mark:w
+ }
+% \end{macrocode}
+% It can't be an implicit begin- or end-group token:
+% \begin{macrocode}
+ \bool_lazy_or:nnT
+ { \token_if_group_begin_p:N #[token] }
+ { \token_if_group_end_p:N #[token] }
+ {
+ \msg_error:nnx { namedef } { group-delim }
+ { \cs_to_str:N #[token] }
+ \@@_skip_to_scan_mark:w
+ }
+% \end{macrocode}
+% It can't be a parameter token:
+% \TODO{Maybe it can, but maybe it will be ambiguous. Must check.}
+% \begin{macrocode}
+ \token_if_parameter:NT #[token]
+ {
+ \msg_error:nnx { namedef } { param-delim }
+ { \cs_to_str:N #[token] }
+ \@@_skip_to_scan_mark:w
+ }
+% \end{macrocode}
+% It can't be a control sequence:
+% \TODO{It probably can, but I'm not sure I want to allow this.}
+% \begin{macrocode}
+ \token_if_cs:NT #[token]
+ {
+ \msg_error:nnx { namedef } { macro-delim }
+ { \c_backslash_str \cs_to_str:N #[token] }
+ \@@_skip_to_scan_mark:w
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Messages}
+%
+% Now we define the messages used throughout the package.
+%
+% \begin{macrocode}
+\msg_new:nnn { namedef } { repeated-parm }
+ {
+ Parameter~\iow_char:N\#[#1]~duplicated~in~
+ definition~of~\l_@@_macro_tl.
+ }
+\msg_new:nnn { namedef } { unknown-parm }
+ {
+ Unknown~parameter~\iow_char:N\#[#1]~in~
+ definition~of~\l_@@_macro_tl.
+ }
+\msg_new:nnn { namedef } { multi-token-delim }
+ {
+ Invalid~\iow_char:N\\named~parameter~delimiter~`#1'.~
+ Delimiters~for~named~parameters~must~be~single~tokens.
+ }
+\msg_new:nnn { namedef } { macro-delim }
+ {
+ Invalid~\iow_char:N\\named~parameter~delimiter~`#1'.~
+ Delimiters~for~named~parameters~can't~be~control~sequence~nor~
+ active~characters.
+ }
+\msg_new:nnn { namedef } { group-delim }
+ {
+ Invalid~\iow_char:N\\named~parameter~delimiter~`\iow_char:N\\#1'.~
+ Delimiters~for~named~parameters~can't~be~
+ begin-/end-group~character~tokens.
+ }
+\msg_new:nnn { namedef } { blank-delim }
+ {
+ Invalid~\iow_char:N\\named~parameter~delimiter.~
+ Delimiters~for~named~parameters~can't~be~empty~nor~space~tokens.
+ }
+\msg_new:nnn { namedef } { param-delim }
+ {
+ Invalid~\iow_char:N\\named~parameter~delimiter.~
+ Delimiters~for~named~parameters~can't~be~parameter~tokens.
+ }
+\msg_new:nnn { namedef } { missing-end }
+ {
+ Missing~\@@_end_name_token:\iow_char:N\ inserted~in~
+ definition~of~\l_@@_macro_tl.
+ }
+% \end{macrocode}
+%
+% Now execute the end package hook (in \LaTeX{} it is
+% \cs{prg_do_nothing:}, but in plain \TeX{} it does \cs{ExplSyntaxOff}).
+%
+% \begin{macrocode}
+\@@_end_package_hook:
+% \end{macrocode}
+%
+% \iffalse
+%</package>
+% \fi
+%
+% \end{implementation}
+%
+%^^A \par\CodedocExplainEXP
+%^^A \par\CodedocExplainREXP
+%^^A \par\CodedocExplainTF
+%
+% \PrintIndex
+%
+\endinput
diff --git a/macros/generic/namedef/namedef.ins b/macros/generic/namedef/namedef.ins
new file mode 100644
index 0000000000..50806470e1
--- /dev/null
+++ b/macros/generic/namedef/namedef.ins
@@ -0,0 +1,90 @@
+%%
+%% Copyright (C) 2019--2020
+%% by Phelype Oleinik <phelype.oleinik@latex-project.org>
+%%
+%% This work may be distributed and/or modified under the conditions of
+%% the LaTeX Project Public License, either version 1.3c of this license
+%% or (at your option) any later version. The latest version of this
+%% license is in
+%%
+%% http://www.latex-project.org/lppl.txt
+%%
+%% and version 1.3c or later is part of all distributions of LaTeX
+%% version 2005/12/01 or later.
+%%
+%% This work is "maintained" (as per the LPPL maintenance status)
+%% by Phelype Oleinik.
+%%
+\def\projectname{namedef}%
+\def\nameofplainTeX{plain}%
+\def\mainext{sty}
+\ifx\fmtname\nameofplainTeX
+\else
+ \expandafter\begingroup
+\fi
+\input l3docstrip.tex
+\keepsilent
+\askforoverwritefalse
+
+\preamble
+
+This is a generated file.
+
+Copyright 2019--2020 Phelype Oleinik /phelype.oleinik@latex-project.org/
+
+This work may be distributed and/or modified under the conditions of the
+LaTeX Project Public License, either version 1.3c of this license or (at
+your option) any later version. The latest version of this license is in
+
+ http://www.latex-project.org/lppl.txt
+
+and version 1.3c or later is part of all distributions of LaTeX version
+2005/12/01 or later.
+
+\endpreamble
+
+\postamble
+
+This work is "maintained" (as per the LPPL maintenance status)
+by Phelype Oleinik.
+
+This work consists of the files \projectname.dtx, and
+ \projectname.ins,
+and the derived files \projectname.\mainext,
+ \projectname.pdf,
+ README.md, and
+ README.txt.%
+
+\endpostamble
+
+\generate
+ {
+ \file{\projectname.\mainext}
+ {
+ \from{\projectname.dtx}{package}
+ }
+ }
+
+\Msg{*********************************************************}
+\Msg{*}
+\Msg{* To finish the installation you have to move the}
+\Msg{* following file into a directory searched by TeX:}
+\Msg{*}
+\Msg{* \space\space \projectname.\mainext}
+\Msg{*}
+\ifx\fmtname\nameofplainTeX
+ \Msg{* To produce the documentation run the file \projectname.dtx}
+ \Msg{* through LaTeX.}
+ \Msg{*}
+\fi
+\Msg{* Happy TeXing!}
+\Msg{*}
+\Msg{*********************************************************}
+
+\ifx\fmtname\nameofplainTeX
+ \expandafter\endbatchfile
+\else
+ \expandafter\endgroup
+\fi
+
+\input{\projectname.dtx}
diff --git a/macros/generic/namedef/namedef.pdf b/macros/generic/namedef/namedef.pdf
new file mode 100644
index 0000000000..ae32bff6ac
--- /dev/null
+++ b/macros/generic/namedef/namedef.pdf
Binary files differ
diff --git a/macros/latex/contrib/apa7/apa7.dtx b/macros/latex/contrib/apa7/apa7.dtx
index fcaeda30fb..2f816a3f8a 100644
--- a/macros/latex/contrib/apa7/apa7.dtx
+++ b/macros/latex/contrib/apa7/apa7.dtx
@@ -4,11 +4,11 @@
% %
% CHANGE THESE VALUES WITH EACH NEW RELEASE: %
% %
-%<class>\ProvidesClass{apa7}[2020/05/27 v1.08 APA formatting (7th edition)]
+%<class>\ProvidesClass{apa7}[2020/06/19 v1.09 APA formatting (7th edition)]
% %
%<*internal> %
-\def\apaSevenVersionDate{2020/05/27}
-\def\apaSevenVersionNumber{1.08}
+\def\apaSevenVersionDate{2020/06/19}
+\def\apaSevenVersionNumber{1.09}
% %
% %
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -245,6 +245,8 @@ and the derived files apa7.ins,
%
% \changes{v1.08}{2020/05/27}{Added support for optional running head (shorttitle) in stu mode.}
%
+% \changes{v1.09}{2020/06/19}{Fixed note command (will no longer print "Author Note" header).}
+%
% \begin{abstract}
% The \textit{Publication Manual} of the American Psychological
% Association is widely used in the social sciences. The most
@@ -441,7 +443,7 @@ and the derived files apa7.ins,
% \begin{itemize}
% \item \DescribeMacro{\note}|\note|\marg{note-text}: Notation of
% manuscript date or other information desired beneath the
-% affiliation line
+% affiliation line (not part of the APA 7th edition specification for title page)
% \item \DescribeMacro{\journal}|\journal|\marg{journal-name}: Journal
% name or other note; typeset in the top left header of page 1
% (|jou| and |doc| modes only); to change the starting page to a
@@ -2511,12 +2513,9 @@ and the derived files apa7.ins,
\@affilSix \vspace{0.25in} \\ }}}}}
%% --- thp 2006/01/05 end of six-author display
- \@ifundefined{@note}{}{
- \vfill
- \section{\normalfont\normalsize\textbf\acksname}
- \raggedright
- \setlength{\parindent}{0.5in}
- \indent\@note\par}
+ \@ifundefined{@note}
+ {\vspace*{\baselineskip} }
+ {\@note}
}{% mask author identity -- show nothing in the author or author note space
}
@@ -2542,12 +2541,9 @@ and the derived files apa7.ins,
\@professor \\
\@duedate \\
- \@ifundefined{@note}{}{
- \vfill
- \section{\normalfont\normalsize\textbf\acksname}
- \raggedright
- \setlength{\parindent}{0.5in}
- \indent\@note\par}
+ \@ifundefined{@note}
+ {\vspace*{\baselineskip} }
+ {\@note}
\end{center}
@@ -2555,12 +2551,10 @@ and the derived files apa7.ins,
{}
{%
\vfill%
- \begin{center}%
- \acksname%
- \end{center}%
- \protect\raggedright
+ \section{\normalfont\normalsize\textbf\acksname}
+ \raggedright
\setlength{\parindent}{0.5in}
- \indent\par\@acks%
+ \indent\@acks\par%
}
}
diff --git a/macros/latex/contrib/apa7/apa7.pdf b/macros/latex/contrib/apa7/apa7.pdf
index 50bbb1c9c6..68b928107e 100644
--- a/macros/latex/contrib/apa7/apa7.pdf
+++ b/macros/latex/contrib/apa7/apa7.pdf
Binary files differ
diff --git a/macros/latex/contrib/apa7/samples/longsample.pdf b/macros/latex/contrib/apa7/samples/longsample.pdf
index 204fa117cf..61af7536c3 100644
--- a/macros/latex/contrib/apa7/samples/longsample.pdf
+++ b/macros/latex/contrib/apa7/samples/longsample.pdf
Binary files differ
diff --git a/macros/latex/contrib/apa7/samples/shortsample.pdf b/macros/latex/contrib/apa7/samples/shortsample.pdf
index 8ceb61d7fb..aafd245226 100644
--- a/macros/latex/contrib/apa7/samples/shortsample.pdf
+++ b/macros/latex/contrib/apa7/samples/shortsample.pdf
Binary files differ
diff --git a/macros/latex/contrib/hyperxmp/hyperxmp.dtx b/macros/latex/contrib/hyperxmp/hyperxmp.dtx
index e4e4f52837..9861784479 100644
--- a/macros/latex/contrib/hyperxmp/hyperxmp.dtx
+++ b/macros/latex/contrib/hyperxmp/hyperxmp.dtx
@@ -22,7 +22,7 @@
%<package>\NeedsTeXFormat{LaTeX2e}[1999/12/01]
%<package>\ProvidesPackage{hyperxmp}
%<*package>
- [2020/06/13 v5.3 Store hyperref metadata in XMP format]
+ [2020/06/19 v5.4 Store hyperref metadata in XMP format]
%</package>
%
%<*driver>
@@ -112,7 +112,7 @@
%</driver>
% \fi
%
-% \CheckSum{2610}
+% \CheckSum{2671}
%
% \CharacterTable
% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
@@ -190,8 +190,16 @@
%
% ^^A Define a few logical styles.
% \DeclareRobustCommand{\term}[1]{#1\SortIndex{#1}{#1}}
-% \DeclareRobustCommand{\pkgname}[1]{\mbox{\textsf{#1}}\SortIndex{#1}{\textsf{#1}}}
-% \DeclareRobustCommand{\clsname}[1]{\mbox{\textsf{#1}}\SortIndex{#1}{\textsf{#1}}}
+% \DeclareRobustCommand{\pkgname}[1]{^^A
+% \mbox{\textsf{#1}}^^A
+% \SortIndex{#1}{\textsf{#1} (package)}^^A
+% \index{packages&#1=\textsf{#1}}^^A
+% }
+% \DeclareRobustCommand{\clsname}[1]{^^A
+% \mbox{\textsf{#1}}^^A
+% \SortIndex{#1}{\textsf{#1} (class)}^^A
+% \index{classes&#1=\textsf{#1}}^^A
+% }
% \makeatletter
% \DeclareRobustCommand{\xmpprop}[2][]{^^A XMP property
% \def\xmppropopt{#1}^^A
@@ -210,7 +218,11 @@
% }
% \makeatother
% \index{XMP=\acrostyle {XMP}&properties|see{properties, \acrostyle{XMP}}}
-% \DeclareRobustCommand{\pdfterm}[1]{\mbox{\textsf{#1}}\SortIndex{#1}{\textsf{#1}}}
+% \DeclareRobustCommand{\pdfterm}[1]{^^A
+% \mbox{\textsf{#1}}^^A
+% \SortIndex{#1}{\textsf{#1}}^^A
+% \index{PDF=\acrostyle{PDF}&#1=\textsf{#1}}^^A
+% }
% \DeclareRobustCommand{\cmdname}[1]{\mbox{\texttt{#1}}\SortIndex{#1}{\texttt{#1}}}
% \DeclareRobustCommand{\optname}[1]{^^A
% \mbox{\textsf{#1}}^^A
@@ -272,6 +284,15 @@
% \DeclareRobustCommand{\Lua}{^^A
% Lua\index{Lua}^^A
% }
+% \DeclareRobustCommand{\Koma}{^^A
+% Koma^^A
+% \SortIndex{Koma}{Koma (class)}^^A
+% \index{classes&Koma}^^A
+% }
+% \DeclareRobustCommand{\ACMclass}{^^A
+% \acro{ACM}^^A
+% \index{classes&ACM=\acrostyle{ACM}}^^A
+% }
%
% ^^A Define an environment just like macro but for Lua functions.
% \makeatletter
@@ -1143,15 +1164,16 @@
% \optname{pdfmetalang} defaults to the same value as \optname{pdflang}
% if non-empty, ``|x-default|'' otherwise. \pkgname{hyperxmp}
% recognizes some class-specific metadata as well, such as that provided
-% via the Koma letter classes (e.g.,~\clsname{scrlttr2}) and the
-% \acro{ACM} article class (\clsname{acmart}).
+% via the \Koma\ letter classes (e.g.,~\clsname{scrlttr2}) and the
+% \ACMclass\ article class (\clsname{acmart}).
%
-% If a document uses the \pkgname{polyglossia} package, it is
-% recommended that it \emph{not} explicitly set \optname{pdflang}.
-% \optname{pdflang} accepts only a single language name while
-% \pkgname{hyperxmp} can automatically query \pkgname{polyglossia} for a
-% list of all languages used in the document and include this list in an
-% \acro{XMP} \xmpterm{dc:language} element.
+% If a document uses either or \pkgname{babel} or \pkgname{polyglossia}
+% package, it is recommended that it \emph{not} explicitly set
+% \optname{pdflang}. \optname{pdflang} accepts only a single language
+% name while \pkgname{hyperxmp} can automatically query \pkgname{babel}
+% and \pkgname{polyglossia} for a list of all languages used in the
+% document and include this list in an \acro{XMP} \xmpprop{dc:language}
+% element.
%
% \usagenote{Multilingual metadata}
% \label{note:multilingual}
@@ -2212,6 +2234,7 @@
}{}%
}%
% \end{macrocode}
+% \Needspace{6\baselineskip}
% \begin{macro}{\KV@Hyp@pdfauthor}
% \begin{macro}{\xmpcomma}
% \begin{macro}{\xmpquote}
@@ -2337,6 +2360,26 @@
% \end{macro}
% \end{macro}
%
+% \begin{macro}{\hyxmp@concated@metadata}
+% Assume that if the document loaded either \pkgname{babel} or
+% \pkgname{polyglossia} it will eventually define one or more languages
+% that \pkgname{hyperxmp} can list within a \xmpprop{dc:language}
+% element.
+% \begin{macrocode}
+\edef\hyxmp@concated@metadata{}
+\AtEndPreamble{%
+ \@ifpackageloaded{babel}{%
+ \edef\hyxmp@concated@metadata{babel}%
+ }{%
+ \@ifpackageloaded{polyglossia}{%
+ \edef\hyxmp@concated@metadata{polyglossia}%
+ }{%
+ }%
+ }%
+}
+% \end{macrocode}
+% \end{macro}
+%
% \begin{macro}{\hyxmp@find@metadata}
% \begin{macro}{\hyxmp@concated@metadata}
% Issue a warning message if the author failed to specify any metadata
@@ -2348,6 +2391,7 @@
% \begin{macrocode}
\newcommand*{\hyxmp@find@metadata}{%
\edef\hyxmp@concated@metadata{%
+ \hyxmp@concated@metadata
\@baseurl
\@pdfauthor
\@pdfauthortitle
@@ -2452,11 +2496,151 @@
% \end{macro}
% \end{macro}
%
+% Rather than load \pkgname{hyperref} ourself we let the author do it
+% then verify he actually did. This approach gives the author the
+% flexibility to load \pkgname{hyperxmp} and \pkgname{hyperref} in
+% either order and to call |\hypersetup| anywhere in the document's
+% preamble, not just before \pkgname{hyperxmp} is loaded.
+% \begin{macrocode}
+\AtEndPreamble{%
+ \@ifpackageloaded{hyperref}{%
+% \end{macrocode}
+% If \cs{@pdflang} is not set, see if we can detect the document
+% language via either the \pkgname{babel} or \pkgname{polyglossia}
+% packages.
+% \begin{macrocode}
+ \@if@def@and@nonempty{@pdflang}{%
+ }{%
+ \hyxmp@detect@langs
+ }%
+% \end{macrocode}
+% Fill in any missing metadata we can using values provided by the author
+% via mechanisms other than the \cs{hypersetup} command.
+% \begin{macrocode}
+ \hyxmp@auto@assign@data
+% \end{macrocode}
+% Most \acro{PDF} standards dictate that if the same metadata appear in
+% both the \acro{XMP} packet and the \acro{PDF} \pdfterm{Info}
+% dictionary, the metadata must match. This requirement poses a problem
+% for a user-unspecified \optname{pdfcreationdate} in the context of
+% \XeLaTeX\@. In this case we explicitly define |\@pdfcreationdate| as
+% |\hyxmp@today@pdf| to prevent the \cmdname{xdvipdfmx} back-end
+% processor from detecting a missing \pdfterm{CreationDate} in the
+% \pdfterm{Info} dictionary and adding its own---typically a few seconds
+% after \pkgname{hyperxmp} has constructed an \xmpprop{xmp:CreateDate}
+% for the \acro{XMP} metadata and leading to a metadata mismatch.
+% \begin{macrocode}
+ \@ifundefined{XeTeXversion}{}{%
+ \@ifmtargexp{\@pdfcreationdate}{%
+ \let\@pdfcreationdate=\hyxmp@today@pdf
+ }%
+ {}%
+ }%
+% \end{macrocode}
+% If the document claims to comply with one or more \acro{PDF}
+% standards, check that all of the requisite metadata are present.
+% \begin{macrocode}
+ \hyxmp@check@standards
+% \end{macrocode}
+% Older versions of \pkgname{hyperref} write the \pdfterm{Info}
+% dictionary to the \acro{PDF} file at the end of the document. New
+% versions of \pkgname{hyperref} write the \pdfterm{Info} dictionary to
+% the \acro{PDF} file at the \emph{beginning} of the document. For
+% compatibility with both old and new \pkgname{hyperref} implementations
+% we suppress writing the \pdfterm{Info} dictionary here, at the
+% beginning of the document.
+% \changes{v4.1}{2019/04/02}{Invoke
+% \protect\cs{hyxmp@no@info@lists} at the beginning of the
+% document, for compatibility with both newer and older versions of
+% \protect\pkgname{hyperref}}
+% \begin{macrocode}
+ \hyxmp@no@info@lists
+% \end{macrocode}
+% We wait until the end of the document to construct the \acro{XMP}
+% packet and write it to the \acro{PDF} document catalog. This gives
+% the author ample opportunity to provide metadata to \pkgname{hyperref}
+% and thereby \pkgname{hyperxmp}.
+% \begin{macrocode}
+ \hyxmp@at@end{%
+ \hyxmp@find@metadata
+ \hyxmp@embed@packet
+ }%
+ }{%
+ \PackageWarningNoLine{hyperxmp}{%
+ \jobname.tex failed to include a\MessageBreak
+ \string\usepackage\string{hyperref\string}
+ in the preamble.\MessageBreak
+ Consequently, all hyperxmp functionality will be\MessageBreak
+ disabled}%
+ }%
+}
+% \end{macrocode}
+%
+% A number of classes either require or recommend that authors declare
+% various class-specific metadata \emph{after} the |\begin{document}|.
+% So where do we invoke \cs{hyxmp@auto@assign@data}? On one hand, we
+% want to invoke it before the |\begin{document}| because this may
+% obviate \pkgname{hyperxmp}'s ``\meta{job name} did not specify any
+% metadata'' warning message. On the other hand, we want to invoke it
+% after the |\begin{document}| so it picks up metadata not specified in
+% the preamble. Our solution is to invoke \cs{hyxmp@auto@assign@data}
+% twice: both before the |\begin{document}| and at the |\end{document}|.
+% We additionally identify here the natural language(s) in use because
+% these aren't known until the end of the document when provided by
+% \pkgname{babel} or \pkgname{polyglossia}. Also, \pkgname{hyperref}
+% forbids changes to \optname{pdflang} past the |\begin{document}|.
+% \changes{v1.3}{2011/04/25}{Introduced the \protect\optname{pdfmetalang}
+% package option, which enables an author to specify the language in which he
+% wrote the document's metadata}
+% \changes{v2.0}{2012/08/02}{New \cs{AtBeginDocument} code from Heiko
+% Oberdiek to properly encode \cs{@pdfmetalang}}
+% \changes{v3.3}{2017/07/21}{Don't overwrite an existing
+% \protect\optname{pdfmetalang} with \protect\optname{pdflang} or
+% \protect\texttt{x-default}. This addresses a bug report by Niklas
+% Beisert}
+% \changes{v5.4}{2020/06/18}{Moved the automatic assignment of
+% \protect\cs{@pdflang} and \protect\cs{@pdfmetalang} from
+% \protect\cs{hyxmp@auto@assign@data} to within a call to
+% \protect\cs{hyxmp@at@end}}
+% \begin{macrocode}
+\hyxmp@at@end{%
+ \hyxmp@set@dc@lang
+ \ifx\@pdfmetalang\@empty
+ \ifx\@pdflang\@empty
+ \let\@pdfmetalang=\hyxmp@x@default
+ \else
+ \edef\@pdfmetalang{\@pdflang}%
+ \fi
+ \fi
+ \hyxmp@xmlify\@pdfmetalang
+ \hyxmp@auto@assign@data
+}
+% \end{macrocode}
+%
+%
+% \subsection{Advanced metadata detection}
+%
+% \pkgname{hyperxmp} strives to be as convenient and user-friendly as
+% possible. To that end, we try to automatically detect as much
+% metadata as possible. The author can of course augment or override
+% autodetected metadata by explicitly providing values to
+% \cs{hypersetup}, but the hope is that we can save the author some
+% effort in many cases.
+%
+% In this section, we identify additional metadata we can use. Most of
+% the functionality is class- or package-specific. For example, we
+% check for phone numbers provided to the \Koma\ letter classes via
+% |\setkomavar{fromphone}{|\dots|}| and/or
+% |\setkomavar{frommobilephone}{|\dots|}|, street addresses provided to
+% the \ACMclass\ article class via \cs{affiliation}, and languages
+% the \pkgname{polyglossia} package is instructed to load via
+% \cs{setdefaultlanguage} and \cs{setotherlanguage}.
+%
% \begin{macro}{\hyxmp@set@koma@phones}
% \changes{v5.3}{2020/06/07}{Added this macro}
% \begin{macro}{\hyxmp@koma@phones}
% Define \cs{hyxmp@koma@phones} as a comma-separated list of the phone
-% numbers provided to a Koma letter class (mobile and landline).
+% numbers provided to a \Koma\ letter class (mobile and landline).
% \begin{macrocode}
\newcommand*{\hyxmp@set@koma@phones}{%
\@if@def@and@nonempty{scr@frommobilephone@var}{%
@@ -2525,30 +2709,6 @@
% \begin{macrocode}
\newcommand*{\hyxmp@auto@assign@data}{%
% \end{macrocode}
-% If the author explicitly specified the language to use for the
-% document's metadata, we use that. If not, we use the document
-% language, specified to \pkgname{hyperref} with the \protect\optname{pdflang}
-% option. If the author did not specify a language, we use |x-default|
-% as the metadata language.
-% \changes{v1.3}{2011/04/25}{Introduced the \protect\optname{pdfmetalang}
-% package option, which enables an author to specify the language in which he
-% wrote the document's metadata}
-% \changes{v2.0}{2012/08/02}{New \cs{AtBeginDocument} code from Heiko
-% Oberdiek to properly encode \cs{@pdfmetalang}}
-% \changes{v3.3}{2017/07/21}{Don't overwrite an existing
-% \protect\optname{pdfmetalang} with \protect\optname{pdflang} or
-% \protect\texttt{x-default}. This addresses a bug report by Niklas
-% Beisert}
-% \begin{macrocode}
- \ifx\@pdfmetalang\@empty
- \ifx\@pdflang\@empty
- \let\@pdfmetalang=\hyxmp@x@default
- \else
- \edef\@pdfmetalang{\@pdflang}%
- \fi
- \fi
- \hyxmp@xmlify\@pdfmetalang
-% \end{macrocode}
% If the author left \optname{pdftitle} blank but specified |\title|,
% use the title for \optname{pdftitle}. Do likewise for various other
% metadata: identify author-provided information that can be co-opted
@@ -2558,7 +2718,7 @@
% unspecified. Thanks to Maciej Radziejewski for the suggestion}
% \changes{v5.3}{2020/05/29}{Consider other author-provided sources of
% metadata. Thanks to Robin Schwab for proposing that
-% \protect\pkgname{hyperxmp} use the Koma letter classes's metadata}
+% \protect\pkgname{hyperxmp} use the \Koma\ letter classes's metadata}
% \begin{macrocode}
\hyxmp@use@first@valid{pdftitle}{\@pdftitle}{%
\scr@subject@var,%
@@ -2728,6 +2888,8 @@
% ``10.1145/nnnnnnn.nnnnnnn'', or the example \acro{DOI} specified in
% the \clsname{acmart} example document, ``10.1145/1122445.1122456''.
% We ignore both of those \acro{DOI}s.
+% \changes{v5.4}{2020/06/16}{Bug fix: Correct a missing ``else'' argument
+% in two invocations of \protect\cs{@if@def@and@nonempty}}
% \begin{macrocode}
\@if@def@and@nonempty{@acmDOI}{%
\IfSubStr{\@acmDOI}{10.1145/1122445.1122456}{}{%
@@ -2738,6 +2900,7 @@
}%
}%
}%
+ {}%
% \end{macrocode}
% \begin{macro}{\hyxmp@strip@isbn@date}
% \begin{macro}{\hyxmp@acm@isbn}
@@ -2761,6 +2924,7 @@
}%
}%
}%
+ {}%
% \end{macrocode}
% \end{macro}
% \end{macro}
@@ -2819,16 +2983,17 @@
% \begin{macro}{\hyxmp@dc@lang}
% \cs{@pdflang} is used in both the \acro{PDF} document catalog (the
% \pdfterm{Lang} key, written to the \acro{PDF} file by
-% \pkgname{hyperref}) and in the Dublin Core \xmpterm{dc:language} tag
+% \pkgname{hyperref}) and in the Dublin Core \xmpprop{dc:language} tag
% (Section~\ref{sec:dublin-core}). Normally, these are the same.
% However, \pdfterm{Lang} accepts only a single language while
-% \xmpterm{dc:language} accepts multiple languages. If the document
-% loads \pkgname{polyglossia} and does not specify \optname{pdflang} in
-% \cs{hypersetup}, \cs{hyxmp@set@dc@lang} is redefined below to set
-% \cs{hyxmp@dc@lang} to \pkgname{polyglossia}'s list of used languages
-% (once this is known). Otherwise, \cs{hyxmp@set@dc@lang} assigns the
-% language specified by \optname{pdflang} (if any) to
-% \cs{hyxmp@dc@lang}.
+% \xmpprop{dc:language} accepts multiple languages. If the document
+% loads either \pkgname{babel} or \pkgname{polyglossia} and does not
+% specify \optname{pdflang} in \cs{hypersetup}, \cs{hyxmp@set@dc@lang}
+% is redefined below (in \cs{hyxmp@detect@langs}) to set
+% \cs{hyxmp@dc@lang} to \pkgname{babel}\slash\pkgname{polyglossia}'s
+% list of used languages (once this is known). Otherwise,
+% \cs{hyxmp@set@dc@lang} assigns the language specified by
+% \optname{pdflang} (if any) to \cs{hyxmp@dc@lang}.
% \begin{macrocode}
\newcommand*{\hyxmp@set@dc@lang}{%
\let\hyxmp@dc@lang=\@pdflang
@@ -2837,119 +3002,139 @@
% \end{macro}
% \end{macro}
%
-% Rather than load \pkgname{hyperref} ourself we let the author do it
-% then verify he actually did. This approach gives the author the
-% flexibility to load \pkgname{hyperxmp} and \pkgname{hyperref} in
-% either order and to call |\hypersetup| anywhere in the document's
-% preamble, not just before \pkgname{hyperxmp} is loaded.
+% \begin{macro}{\hyxmp@detect@langs}
+% If \optname{pdflang} was not specified, try to determine the document
+% language(s) using either \pkgname{babel}'s or \pkgname{polyglossia}'s
+% definitions. If so, we redefine \cs{hyxmp@set@dc@lang} as a
+% comma-separate list of languages used in the document.
+% \changes{v5.3}{2020/06/08}{Acquire the default language from the
+% \protect\pkgname{polyglossia} package, if loaded. Thanks to
+% Robin Schwab for bringing that package to my attention}
+% \changes{v5.4}{2020/06/16}{Refactored language detection into a
+% separate command}
% \begin{macrocode}
-\AtEndPreamble{%
- \@ifpackageloaded{hyperref}{%
+\newcommand*{\hyxmp@detect@langs}{%
+ \@ifundefined{mainbcp47id}{%
+ \@ifundefined{LocaleForEach}{%
% \end{macrocode}
-% In older versions of \pkgname{hyperref}, \cs{@pdflang} is set to
+% The document doesn't appear to have loaded either \pkgname{babel} or
+% \pkgname{polyglossia}. In this case we have one small task to do. In
+% older versions of \pkgname{hyperref}, \cs{@pdflang} is set to
% \cs{@empty} if \optname{pdflang} is not specified. In newer versions
% of \pkgname{hyperref}, \cs{@pdflang} is set to \cs{relax} if
% \optname{pdflang} is not specified. The latter is a bit problematic
% for \pkgname{hyperxmp} because it makes \cs{@pdflang} non-expandable,
% which causes a literal ``\cs{@pdflang}'' to be written as \acro{XMP}
-% metadata. To avoid that situation we redefine \cs{@pdflang} as
-% \cs{@empty} if we see it set to \cs{relax}. Actually, we first check
-% if the \pkgname{polyglossia} package has specified the document's main
-% language in \cs{mainbcp47id}. If so, we use that instead of
-% \cs{@empty} and redefine \cs{hyxmp@set@dc@lang} to consider
-% \pkgname{polyglossia}'s list of used languages.
+% metadata. To avoid that situation we explicitly set \cs{@pdflang} to
+% \cs{@empty} to avoid problems with non-expandable symbols.
% \changes{v2.3a}{2013/04/16}{Bug fix: Redefine \cs{@pdflang} as
% \cs{@empty} when \protect\pkgname{hyperref} has set
% it to \cs{relax}}
-% \changes{v5.3}{2020/06/08}{Acquire the default language from the
-% \protect\pkgname{polyglossia} package, if loaded. Thanks to
-% Robin Schwab for bringing that package to my attention}
% \begin{macrocode}
- \ifx\@pdflang\relax
- \@ifundefined{mainbcp47id}{%
- \let\@pdflang=\@empty
- }{%
- \xdef\@pdflang{\csname mainbcp47id\endcsname}%
- \renewcommand*{\hyxmp@set@dc@lang}{%
- \edef\hyxmp@dc@lang{\xpg@bcp@loaded}%
+ \let\@pdflang=\@empty
+ }{%
+% \end{macrocode}
+% Use \pkgname{babel}'s \cs{LocaleForEach} and \cs{getlocaleproperty} to
+% construct a comma-separate list of all document languages. We also
+% set \cs{@pdflang} within \cs{hyxmp@set@dc@lang}.
+% (\cs{hyxmp@detect@langs} should only be called if \cs{@pdflang} is
+% empty.) Unlike \pkgname{polyglossia}, \pkgname{babel} does not
+% provide information about the main language until after the
+% |\begin{document}| so we have to wait until \cs{hyxmp@set@dc@lang} is
+% called to set it.
+% \changes{v5.4}{2020/06/17}{Added support for \protect\pkgname{babel}}
+% \begin{macrocode}
+ \BabelEnsureInfo
+ \renewcommand*{\hyxmp@set@dc@lang}{%
+ \getlocaleproperty\@pdflang{\bbl@main@language}{identification/tag.bcp47}%
+ \hyxmp@write@pdflang
+ \let\hyxmp@dc@lang=\relax
+ \LocaleForEach{%
+ \getlocaleproperty\hyxmp@lang@tag{####1}{identification/tag.bcp47}%
+ \ifx\hyxmp@dc@lang\relax
+ \edef\hyxmp@dc@lang{\hyxmp@lang@tag}%
+ \else
+ \edef\hyxmp@dc@lang{\hyxmp@dc@lang,\hyxmp@lang@tag}%
+ \fi
}%
}%
- \fi
-% \end{macrocode}
-% Fill in any missing metadata we can using values provided by the author
-% via mechanisms other than the \cs{hypersetup} command.
-% \begin{macrocode}
- \hyxmp@auto@assign@data
+ }%
+ }{%
% \end{macrocode}
-% Most \acro{PDF} standards dictate that if the same metadata appear in
-% both the \acro{XMP} packet and the \acro{PDF} \pdfterm{Info}
-% dictionary, the metadata must match. This requirement poses a problem
-% for a user-unspecified \optname{pdfcreationdate} in the context of
-% \XeLaTeX\@. In this case we explicitly define |\@pdfcreationdate| as
-% |\hyxmp@today@pdf| to prevent the \cmdname{xdvipdfmx} back-end
-% processor from detecting a missing \pdfterm{CreationDate} in the
-% \pdfterm{Info} dictionary and adding its own---typically a few seconds
-% after \pkgname{hyperxmp} has constructed an \xmpprop{xmp:CreateDate}
-% for the \acro{XMP} metadata and leading to a metadata mismatch.
+% Use \pkgname{polyglossia}'s \cs{mainbcp47id} as the document's main
+% language and its \cs{xpg@bcp@loaded} as a comma-separated list of all
+% document languages.
% \begin{macrocode}
- \@ifundefined{XeTeXversion}{}{%
- \@ifmtargexp{\@pdfcreationdate}{%
- \let\@pdfcreationdate=\hyxmp@today@pdf
- }%
- {}%
+ \xdef\@pdflang{\csname mainbcp47id\endcsname}%
+ \renewcommand*{\hyxmp@set@dc@lang}{%
+ \edef\hyxmp@dc@lang{\xpg@bcp@loaded}%
}%
+ }%
+}
% \end{macrocode}
-% If the document claims to comply with one or more \acro{PDF}
-% standards, check that all of the requisite metadata are present.
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@write@pdflang}
+% Here's a conundrum: \pkgname{babel} doesn't provide access to
+% information on the document's main language until after the
+% |\begin{document}|. However, \pkgname{hyperref} allows
+% \optname{pdflang} to be set only \emph{before} the |\begin{document}|.
+% So what do we do?
+%
+% Note that the underlying \cs{@pdflang} macro serves two purposes:
+% \pkgname{hyperref} uses it to set the \pdfterm{Lang} entry in the
+% \acro{PDF} document catalog, and \pkgname{hyperxmp} uses it as the
+% default metadata language. The latter is used in \xmpprop{dc:title}
+% and other \acro{XMP} properties that can include per-language
+% variants. We set \cs{@pdflang} once we have the main-language
+% information from \pkgname{babel}. As this is too late for
+% \pkgname{hyperref}, we bypass \pkgname{hyperref} and manually write
+% the \pdfterm{Lang} key into the document catalog. This is a bit
+% kludgy, but we do leverage as much of \pkgname{hyperref}'s
+% infrastructure as possible to increase \cs{hyxmp@write@pdflang}'s
+% robustness.
+% \changes{v5.4}{2020/06/19}{Added this macro}
+% \begin{macrocode}
+\newcommand*{\hyxmp@write@pdflang}{%
+ \@ifundefined{pdfmark}{%
+ \@ifundefined{@pdfm@mark}{%
+ \@ifundefined{pdfcatalog}{%
+% \end{macrocode}
+% We don't recognize the \tex\ engine or \acro{PDF} generator. (This is
+% unexpected.) We therefore issue a warning message and take no further
+% action.
+% \begin{macrocode}
+ \PackageWarning{hyperxmp}{Unknown PDF generator; not setting the language (\@pdflang) in the PDF catalog}%
+ }{%
+% \end{macrocode}
+% We're running either \pdfTeX\ or \LuaTeX\@. (\pkgname{hyperref}
+% defines \cs{pdfcatalog} in the latter case.)
% \begin{macrocode}
- \hyxmp@check@standards
+ \pdfcatalog{/Lang (\@pdflang)}%
+ }%
+ }{%
% \end{macrocode}
-% Older versions of \pkgname{hyperref} write the \pdfterm{Info}
-% dictionary to the \acro{PDF} file at the end of the document. New
-% versions of \pkgname{hyperref} write the \pdfterm{Info} dictionary to
-% the \acro{PDF} file at the \emph{beginning} of the document. For
-% compatibility with both old and new \pkgname{hyperref} implementations
-% we suppress writing the \pdfterm{Info} dictionary here, at the
-% beginning of the document.
-% \changes{v4.1}{2019/04/02}{Invoke
-% \protect\cs{hyxmp@no@info@lists} at the beginning of the
-% document, for compatibility with both newer and older versions of
-% \protect\pkgname{hyperref}}
+% We're running either \XeTeX\ or \tex~+
+% \texttt{dvipdfm}.\SortIndex{dvipdfm}{\texttt{dvipdfm}}.
% \begin{macrocode}
- \hyxmp@no@info@lists
+ \@pdfm@mark{docview << /Lang (\@pdflang) >>}%
+ }%
+}{%
% \end{macrocode}
-% We wait until the end of the document to construct the \acro{XMP}
-% packet and write it to the \acro{PDF} document catalog. This gives
-% the author ample opportunity to provide metadata to \pkgname{hyperref}
-% and thereby \pkgname{hyperxmp}.
+% We're running either \tex~+ \Dvips~+ Adobe Acrobat Distiller (or other
+% converter from PostScript to \acro{PDF}).
% \begin{macrocode}
- \hyxmp@at@end{%
- \hyxmp@find@metadata
- \hyxmp@embed@packet
+ \pdfmark{%
+ pdfmark=/PUT,Raw={%
+ \string{Catalog\string} <<
+ /Lang (\@pdflang)
+ >>
+ }%
}%
- }{%
- \PackageWarningNoLine{hyperxmp}{%
- \jobname.tex failed to include a\MessageBreak
- \string\usepackage\string{hyperref\string}
- in the preamble.\MessageBreak
- Consequently, all hyperxmp functionality will be\MessageBreak
- disabled}%
}%
}
% \end{macrocode}
-%
-% A number of classes either require or recommend that authors declare
-% various class-specific metadata \emph{after} the |\begin{document}|.
-% So where do we invoke \cs{hyxmp@auto@assign@data}? On one hand, we
-% want to invoke it before the |\begin{document}| because this may
-% obviate \pkgname{hyperxmp}'s ``\meta{job name} did not specify any
-% metadata'' warning message. On the other hand, we want to invoke it
-% after the |\begin{document}| so it picks up metadata not specified in
-% the preamble. Our solution is to invoke \cs{hyxmp@auto@assign@data}
-% twice: both before the |\begin{document}| at at the |\end{document}|.
-% \begin{macrocode}
-\hyxmp@at@end{\hyxmp@auto@assign@data}
-% \end{macrocode}
+% \end{macro}
%
%
% \subsection{Manipulating author-supplied data}
@@ -4628,7 +4813,7 @@ _______________________________________________________________^^J%
% Assign |\hyxmp@major@minor| to be the \acro{PDF} version targeted by
% the running \TeX\ engine.
% \changes{v5.2}{2020/05/10}{Added this macro. \string\pkgname{hyperxmp}
-% now correctly specifies \string\xmpterm{pdf:PDFVersion} when
+% now correctly specifies \string\xmpprop{pdf:PDFVersion} when
% generating \string\acro{PDF}~2.0+. Thanks to Ulrike Fischer for
% alerting me to \string\acro{PDF}~2.0's availability in the
% \string\TeX\ ecosystem and informing me how to activate it}
@@ -4852,11 +5037,11 @@ ______</dc:#2>^^J%
% \end{macro}
%
% \begin{macro}{\hyxmp@cond@dc@identifier}
-% Conditionally add a \xmpterm{dc:identifier} tag. Given a prefix
+% Conditionally add a \xmpprop{dc:identifier} tag. Given a prefix
% string~(|#1|) and a main string~(|#2|), wrap these in a
-% \xmpterm{dc:identifier} if the main string is nonempty and
+% \xmpprop{dc:identifier} if the main string is nonempty and
% |\hyxmp@xmlified| \emph{is} empty (implying the
-% \xmpterm{dc:identifier} has not yet been written).
+% \xmpprop{dc:identifier} has not yet been written).
% \changes{v5.2}{2020/04/29}{Added this macro}
% \begin{macrocode}
\newcommand*{\hyxmp@cond@dc@identifier}[2]{%
@@ -4883,14 +5068,19 @@ ______</dc:#2>^^J%
% the author specified \optname{pdftype}, and the
% \xmpprop{dc:identifier} if the author specified
% \optname{pdfidentifier} or if we can derive it from other options. We
-% also specify the \xmpprop{dc:date} property using the date the
-% document was run through \LaTeX\ and the \xmpprop{dc:source} property
-% using the base name of the source file with |.tex| appended.
+% also specify the \xmpprop{dc:source} property using the base name of
+% the source file with |.tex| appended and the \xmpprop{dc:date}
+% property using the date the document was run through \LaTeX---unless
+% the author specified \optname{pdfdate}, in which case we use that.
% \changes{v2.0}{2012/08/26}{Added support for \xmpprop{dc:language}
% and \xmpprop{dc:source}}
% \changes{v2.4}{2013/12/21}{Made \xmpprop{dc:language} a \xmpterm{Bag}
% instead of an individual item so as to conform to the latest
% \acro{XMP} specifications, a detail identified by Florian Breitwieser}
+% \changes{v5.3}{2020/06/13}{Include all languages used in the document
+% in \protect\xmpprop{dc:language}}
+% \changes{v5.4}{2020/06/18}{Bug fix: Use \protect\cs{hyxmp@today@xmp}
+% as the date only if \protect\cs{@pdfdatetime} is undefined}
% \begin{macrocode}
\newcommand*{\hyxmp@dc@schema}{%
\hyxmp@add@simple{dc:format}{application/pdf}%
@@ -4898,7 +5088,11 @@ ______</dc:#2>^^J%
\hyxmp@rdf@dc[\ifHy@pdfa]{description}{\@pdfsubject}%
\hyxmp@rdf@dc{rights}{\@pdfcopyright}%
\hyxmp@singleton@dc{publisher}{\@pdfpublisher}%
- \hyxmp@singleton@dc[Seq]{date}{\hyxmp@today@xmp}%
+ \@ifmtargexp{\@pdfdatetime}{%
+ \hyxmp@singleton@dc[Seq]{date}{\hyxmp@today@xmp}%
+ }{%
+ \hyxmp@singleton@dc[Seq]{date}{\@pdfdatetime}%
+ }%
\hyxmp@singleton@dc{type}{\@pdftype}%
\hyxmp@list@to@xml[\ifHy@pdfa]{creator}{Seq}{\hyxmp@pdfauthor}%
\hyxmp@list@to@xml{subject}{Bag}{\hyxmp@pdfkeywords}%
@@ -4906,18 +5100,7 @@ ______</dc:#2>^^J%
\else
\hyxmp@add@simple{dc:source}{\@pdfsource}%
\fi
-% \end{macrocode}
-% Set \cs{hyxmp@dc@lang} to either the single language \cs{@pdflang}
-% (which may be unspecified) or to a list of languages used in the
-% document via \pkgname{polyglossia}. See
-% Section~\ref{sec:hyperref-int} for the definition of
-% \cs{hyxmp@set@dc@lang}.
-% \changes{v5.3}{2020/06/13}{Include all languages used in the document
-% in \protect\xmpterm{dc:language}}
-% \begin{macrocode}
- \hyxmp@set@dc@lang
\hyxmp@list@to@xml{language}{Bag}{\hyxmp@dc@lang}%
-% \end{macrocode}
% If |\@pdfidentifier| is empty, try setting it to each of |\@pdfdoi|,
% |\@pdfeissn|, |\@pdfissn|, and |\@pdfisbn|, in turn, with proper
% syntactic adjustments.
@@ -6254,6 +6437,7 @@ __</rdf:RDF>^^J%
% file, which offers the benefit of live hyperlinks in almost all
% \acro{PDF} readers.
%
+%
% \subsection{Ensuring proper support}
%
% \begin{macro}{\next}
@@ -6298,6 +6482,7 @@ __</rdf:RDF>^^J%
\typeout{Generating PDF/A-1b compliant hyperxmp documentation.}
% \end{macrocode}
%
+%
% \subsection{Complying with the PDF/A-1b standard}
%
% We can't specify \PDFstd{A}{1}{b}{} compliance until after both
diff --git a/macros/latex/contrib/hyperxmp/hyperxmp.pdf b/macros/latex/contrib/hyperxmp/hyperxmp.pdf
index 28b08b0787..998059c14e 100644
--- a/macros/latex/contrib/hyperxmp/hyperxmp.pdf
+++ b/macros/latex/contrib/hyperxmp/hyperxmp.pdf
Binary files differ
diff --git a/macros/latex/contrib/pict2e/README.md b/macros/latex/contrib/pict2e/README.md
index cda901f5a1..0e38783414 100644
--- a/macros/latex/contrib/pict2e/README.md
+++ b/macros/latex/contrib/pict2e/README.md
@@ -36,8 +36,5 @@ Recommended TDS locations:
pict2e.cfg: tex/latex/[TEXDIST]/graphics.cfg
```
-For general installation advice, see
-http://www.tex.ac.uk/cgi-bin/texfaq2html?label=instpackages
-
For bug reports use the GitHub repository: https://github.com/rolfn/pict2e/issues
diff --git a/macros/latex/contrib/pict2e/p2e-drivers.pdf b/macros/latex/contrib/pict2e/p2e-drivers.pdf
index fe1a1c89af..12c0741fba 100644
--- a/macros/latex/contrib/pict2e/p2e-drivers.pdf
+++ b/macros/latex/contrib/pict2e/p2e-drivers.pdf
Binary files differ
diff --git a/macros/latex/contrib/pict2e/pict2e.dtx b/macros/latex/contrib/pict2e/pict2e.dtx
index 9c2b986cc2..cccd714da7 100644
--- a/macros/latex/contrib/pict2e/pict2e.dtx
+++ b/macros/latex/contrib/pict2e/pict2e.dtx
@@ -23,7 +23,7 @@
%
%<*package>
\NeedsTeXFormat{LaTeX2e}[1999/12/01]
-\ProvidesPackage{pict2e}[2020/06/13 v0.3d Improved picture commands (HjG,RN,JT)]
+\ProvidesPackage{pict2e}[2020/06/20 v0.3e Improved picture commands (HjG,RN,JT)]
%</package>
%
%<*driver>
@@ -63,9 +63,9 @@
% \fi
%
% \GetFileInfo{pict2e.sty}
-% \def\docdate{2020/06/13}
+% \def\docdate{2020/06/20}
%
-% \CheckSum{2157}
+% \CheckSum{2206}
%
% ^^A ========
%
@@ -188,6 +188,8 @@
% \changes{v0.2z}{2014/01/12}{Conflict wit epic, eepic solved. (JT)}
% \changes{v0.3a}{2016/01/09}{Local line types, documentation fixes. (JT)}
% \changes{v0.3d}{2020/06/13}{\cmd{\@sline} renamed \cmd{\pIIe@sline} (RN)}
+% \changes{v0.3e}{2020/06/20}{Added \cmd{\Vector}, \cmd{\polyvector}
+% suggested by FMi (RN)}
% \fi
%
% \changes{v0.1a}{2003/07/18}{First version. (RN)}
@@ -1284,26 +1286,32 @@
% An equivalent \cmd{\pIIearc} to \cmd{\arc} is defined to solve possible
% conflicts with other packages.
%
-% \subsubsection{Lines, polygons}
+% \subsubsection{Line, Vector, polyline, polyvector, and polygon}
% \label{sec:usage:lines+polygons}
%
% \DescribeMacro\Line
% \DescribeMacro\polyline
+% \DescribeMacro\Vector
+% \DescribeMacro\polyvector
% \DescribeMacro\polygon
% \DescribeMacro{\polygon*}
% |\Line|\parg{X1,Y1}\parg{X2,Y2}\\
% |\polyline|\parg{X1,Y1}\parg{X2,Y2}\dots\parg{Xn,Yn}\\
+% |\Vector|\parg{X1,Y1}\parg{X2,Y2}\\
+% |\polyvector|\parg{X1,Y1}\parg{X2,Y2}\dots\parg{Xn,Yn}\\
% |\polygon|\parg{X1,Y1}\parg{X2,Y2}\dots\parg{Xn,Yn}\\
% |\polygon*|\parg{X1,Y1}\parg{X2,Y2}\dots\parg{Xn,Yn}\\
% A natural way how to describe a line segment is to give the coordinates of
-% the endpoints. The syntax of the \cmd{\line} is different because
+% the endpoints. The syntax of the \cmd{\line}/\cmd{\vector} is different
+% because
% the lines in the standard \texttt{picture} environment are made from small
% line segments of a limited number of slopes given in a font. However, this
% package changes the \cmd{\line} command computing the coordinates of the
% endpoints and using an internal macro for drawing a line segment with given
% endpoints. Hence it would be crazy do not use this possibility directly.
-% This is done by the command \cmd{\Line}. The command \cmd{\polyline} draws a
-% stroken line connecting points with given coordinates. The command
+% This is done by the commands \cmd{\Line} and \cmd{\Vector}. The commands
+% \cmd{\polyline} and \cmd{\polyvector} draws a
+% stroken line/vector connecting points with given coordinates. The command
% \cmd{\polygon} draws a polygon with given vertices, the star variant gives
% filled polygon. At least two points should be given.
%
@@ -2203,7 +2211,7 @@
% \]
% and $t = x/s$ and $\tau = 2(t-1/2)$.
% \end{quote}
-% \changes{v0.2r}{2005/07/15}{Two wrong global assignment changed. (RN)}
+% \changes{v0.2r}{2005/07/15}{Two wrong global assignments changed. (RN)}
% \begin{macrocode}
\newcommand*\pIIe@pyth[3]{%
\begingroup
@@ -2499,11 +2507,13 @@
\pIIe@divide{\@tempdimb}\dimen@\@ydim
\pIIe@divide{\@tempdima}\dimen@\@xdim
% \end{macrocode}
-% Rotate the following vector\slash arrow outlines by angle $\theta$.
+% Rotate the following vector\slash arrow outlines by angle $\theta$:\par
+% \BigIndent
+% $\cos{\theta}$\quad$\sin{\theta}$\quad$-\sin{\theta}$\quad$\cos{\theta}$\quad $0\quad 0$
% \begin{macrocode}
\pIIe@concat\@xdim\@ydim{-\@ydim}\@xdim\z@\z@
% \end{macrocode}
-% Internal command to draw the outline of the vector\slash arrow.
+% Internal command to draw the outline of the vector\slash arrow.
% \begin{macrocode}
\pIIe@vector
\pIIe@fillGraph
@@ -3196,15 +3206,14 @@
% We abuse \cmd{\@setfpsbit} from the float processing modules of the
% kernel.
% ^^A (Should this go to section low-level?)
-% \begin{macrocode}
+% \begin{macrocode}
\newcommand*\pIIe@get@quadrants[1]{%
\@ovttrue \@ovbtrue \@ovltrue \@ovrtrue \@tempcnta\z@
\@tfor\reserved@a:=#1\do{\csname @ov\reserved@a false\endcsname}%
\if@ovr \if@ovb\@setfpsbit2\fi \if@ovt\@setfpsbit4\fi \fi
\if@ovl \if@ovb\@setfpsbit1\fi \if@ovt\@setfpsbit8\fi \fi}
-% \end{macrocode}
+% \end{macrocode}
% \end{macro}
-%
% \subsubsection{Quadratic Bezier Curve}
% \label{sec:implementation:bezier-curves}
%
@@ -3259,7 +3268,6 @@
\fi}
% \end{macrocode}
% \end{macro}
-%
% \begin{macro}{\pIIe@bezier@QtoC}
% \changes{v0.1u}{2003/11/21}{New ancillary macro (HjG)}
% Ancillary macro; saves us some tokens above.
@@ -3271,10 +3279,10 @@
% \noindent
% (Missing: Reference for mathematical formula. Or is this trivial?)
% \begin{macrocode}
- \newcommand*\pIIe@bezier@QtoC[3]{%
- \@tempdimc#1\relax \advance\@tempdimc-#2\relax
- \divide\@tempdimc\thr@@ \advance\@tempdimc #2\relax
- #3\@tempdimc}
+ \newcommand*\pIIe@bezier@QtoC[3]{%
+ \@tempdimc#1\relax \advance\@tempdimc-#2\relax
+ \divide\@tempdimc\thr@@ \advance\@tempdimc #2\relax
+ #3\@tempdimc}
% \end{macrocode}
% \end{macro}
%
@@ -3404,13 +3412,17 @@
% \end{macrocode}
% \end{macro}
%
-% \subsubsection{Lines and polygons}
-% \label{sec:implementation:lines-polygons}
+% \subsubsection{Line, Vector, polyline, polyvector, and polygon}
+% \label{sec:implementation:polyline-polyvector}
%
+% \changes{v0.3e}{2020/06/20}{Added \cmd{\Vector} and \cmd{\polyvector}
+% suggested by FMi. (RN)}
% \begin{macro}{\Line}
% \begin{macro}{\polyline}
+% \begin{macro}{\Vector}
+% \begin{macro}{\polyvector}
% \begin{macro}{\polygon}
-% We use recursive macros for \cmd{\polyline} and \cmd{\polygon}.
+% We use recursive macros for \cmd{\polyline}, \cmd{\polyvector}, and \cmd{\polygon}.
% \begin{macrocode}
\let\lp@r( \let\rp@r)
\def\Line(#1,#2)(#3,#4){\polyline(#1,#2)(#3,#4)}
@@ -3423,6 +3435,33 @@
\def\@polyline(#1,#2){%
\pIIe@lineto{#1\unitlength}{#2\unitlength}%
\@ifnextchar\lp@r{\@polyline}{\pIIe@strokeGraph\ignorespaces}}
+ \def\Vector(#1,#2)(#3,#4){\polyvector(#1,#2)(#3,#4)}
+ \def\polyvector(#1,#2){%
+ \@killglue
+ \@ifnextchar\lp@r{\begingroup\@polyvector(#1,#2)}{%
+ \PackageWarning{pict2e}%
+ {Polygonal vectors require at least two vertices!}\ignorespaces}}
+ \def\@polyvector(#1,#2)(#3,#4){%
+% \end{macrocode}
+% See the similar definition for \cmd{\vector} (\ref{sec:implementation:vector})
+% \begin{macrocode}
+ \@xdim#1\unitlength \@tempdima=#3\unitlength
+ \@ydim#2\unitlength \@tempdimb=#4\unitlength
+ \advance\@tempdima-\@xdim \advance\@tempdimb-\@ydim
+ \ifdim\@tempdima=\z@ \@linelen\@tempdimb \else
+ \ifdim\@tempdimb=\z@ \@linelen\@tempdima \else
+ \pIIe@pyth\@tempdima\@tempdimb\@linelen
+ \fi
+ \fi
+ \ifdim\@linelen<\z@ \@linelen-\@linelen\fi
+ \pIIe@divide{\@tempdima}\@linelen\@ovxx
+ \pIIe@divide{\@tempdimb}\@linelen\@ovyy
+% \end{macrocode}
+% Note the shift to the previous point in addition to the rotation.
+% \begin{macrocode}
+ \pIIe@concat\@ovxx\@ovyy{-\@ovyy}\@ovxx\@xdim\@ydim
+ \pIIe@vector \pIIe@fillGraph
+ \@ifnextchar\lp@r{\@polyvector(#3,#4)}{\endgroup\ignorespaces}}
\def\polygon{%
\@killglue
\@ifstar{\begingroup\@tempswatrue\@polygon}%
@@ -3441,6 +3480,8 @@
% \end{macro}
% \end{macro}
% \end{macro}
+% \end{macro}
+% \end{macro}
%
% \subsubsection{Path commands}
% \label{sec:implementation:path-commands}
diff --git a/macros/latex/contrib/pict2e/pict2e.pdf b/macros/latex/contrib/pict2e/pict2e.pdf
index bcc86e4850..bb634560b3 100644
--- a/macros/latex/contrib/pict2e/pict2e.pdf
+++ b/macros/latex/contrib/pict2e/pict2e.pdf
Binary files differ