summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/koma-script/scrkernel-basics.dtx
diff options
context:
space:
mode:
Diffstat (limited to 'macros/latex/contrib/koma-script/scrkernel-basics.dtx')
-rw-r--r--macros/latex/contrib/koma-script/scrkernel-basics.dtx5356
1 files changed, 5356 insertions, 0 deletions
diff --git a/macros/latex/contrib/koma-script/scrkernel-basics.dtx b/macros/latex/contrib/koma-script/scrkernel-basics.dtx
new file mode 100644
index 0000000000..44e82629b8
--- /dev/null
+++ b/macros/latex/contrib/koma-script/scrkernel-basics.dtx
@@ -0,0 +1,5356 @@
+% \iffalse meta-comment
+% ======================================================================
+% scrkernel-basics.dtx
+% Copyright (c) Markus Kohm, 2002-2022
+%
+% This file is part of the LaTeX2e KOMA-Script bundle.
+%
+% This work may be distributed and/or modified under the conditions of
+% the LaTeX Project Public License, version 1.3c of the license.
+% 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 and of this work.
+%
+% This work has the LPPL maintenance status "author-maintained".
+%
+% The Current Maintainer and author of this work is Markus Kohm.
+%
+% This work consists of all files listed in MANIFEST.md.
+% ======================================================================
+%%% From File: $Id: scrkernel-basics.dtx 3913 2022-06-28 07:45:49Z kohm $
+%<prepare>%%% (run: prepare)
+%<option>%%% (run: option)
+%<body>%%% (run: body)
+%<load>%%% (run: load)
+%<package&prepare>\NeedsTeXFormat{LaTeX2e}[1995/06/01]
+%<*dtx>
+\ifx\ProvidesFile\undefined\def\ProvidesFile#1[#2]{}\fi
+\begingroup
+ \def\filedate$#1: #2-#3-#4 #5${\def\filedate{#2/#3/#4}}
+ \filedate$Date: 2022-06-28 09:45:49 +0200 (Di, 28. Jun 2022) $
+ \def\filerevision$#1: #2 ${\def\filerevision{r#2}}
+ \filerevision$Revision: 3913 $
+ \edef\reserved@a{%
+ \noexpand\endgroup
+ \noexpand\ProvidesFile{scrkernel-basics.dtx}%
+ [\filedate\space\filerevision\space
+ KOMA-Script
+ }
+\reserved@a
+%</dtx>
+%<*dtx|(package&prepare)>
+%<package>\ProvidesPackage{%
+%<package&base> scrbase%
+%<package&koma> scrkbase%
+%<package>}[%
+%!KOMAScriptVersion
+ package
+%<*dtx>
+ source
+%</dtx>
+ (%
+%<base> KOMA-Script-independent
+%<koma> KOMA-Script-dependent
+ basics and keyval usage)]
+%</dtx|(package&prepare)>
+%<*dtx>
+\ifx\documentclass\undefined
+ \input scrdocstrip.tex
+ \@@input scrkernel-version.dtx
+ \@@input scrstrip.inc
+ \KOMAdefVariable{COPYRIGHTFROM}{2002}
+ \generate{\usepreamble\defaultpreamble
+ \file{scrbase.sty}{%
+ \from{scrkernel-version.dtx}{package,scrbase}%
+ \from{scrkernel-basics.dtx}{package,prepare,base}%
+ \from{scrkernel-basics.dtx}{package,option,base}%
+ \from{scrkernel-language.dtx}{package,option,base}%
+ \from{scrkernel-basics.dtx}{package,body,base}%
+ \from{scrkernel-language.dtx}{package,body,base}%
+ \from{scrlogo.dtx}{logo}%
+ }%
+ }
+ \@@input scrstrop.inc
+\else
+ \let\endbatchfile\relax
+\fi
+\endbatchfile
+\documentclass[USenglish]{koma-script-source-doc}
+\usepackage{babel}
+\usepackage{hvlogos}
+\setcounter{StandardModuleDepth}{2}
+\begin{document}
+\DocInput{scrkernel-basics.dtx}
+\end{document}
+%</dtx>
+% \fi^^A meta-comment
+%
+% \changes{v1.0}{2002/07/06}{starting implementation}
+% \changes{v3.12}{203/03/05}{usage of \cs{@tempa}, \cs{@tempb}, \cs{@tempc}
+% eliminated}
+% \changes{v3.36}{2022/02/16}{switch over from \cls*{scrdoc} to
+% \cls*{koma-script-source-doc}}
+% \changes{v3.36}{2022/02/21}{whole implementation documentation in English}
+%
+% \GetFileInfo{scrkernel-basics.dtx}
+% \title{Basic Funktionality Used by Almost all
+% \href{https://komascript.de}{\KOMAScript} Classes and Packages}
+% \author{\href{mailto:komascript@gmx.info}{Markus Kohm}}
+% \date{Revision \fileversion{} of \filedate}
+% \maketitle
+% \begin{abstract}
+% New versions of \KOMAScript{} make increasing use of the \pkg{keyval}
+% package. The \pkg{keyval} package is part of the \pkg{graphics} package
+% and as such must be included on all \TeX{} systems with \LaTeX{}. However,
+% it does not meet the requirements of \KOMAScript{} in some
+% respects. Therefore, extensions are made here which can be used by
+% \KOMAScript classes and \KOMAScript packages.
+%
+% In addition, more and more parts of \KOMAScript{} are used by more than
+% one package or by packages and classes. These basic things have therefore
+% been split into two packages, \pkg*{scrbase} (for things that can also be
+% used by other classes and packages) and \pkg*{scrkbase} (for things that
+% are reserved for \pkg*{scrkbase}). This makes the packages and classes
+% themselves smaller and they can still be used independently. Of course you
+% can also use this package without the rest of \KOMAScript{}.
+% \end{abstract}
+% \tableofcontents
+%
+% \section{User Manual}
+%
+% You can find the user documentation of package \pkg*{scrbase} and the
+% commands implemented in \file{scrkernel-basics.dtx} in the \KOMAScript{}
+% manual, either the German \file{scrguide} or the English \file{scrguien}.
+%
+%
+% \subsection{Functions not yet in the Manual}
+%
+% Some user commands are not documented in the \KOMAScript{} manuals, e.g.,
+% because they are not stable enough to be used by average users or more or
+% less for internal usage only. Some are only not documented in the
+% \KOMAScript{} manual, because nobody has done it yet.
+%
+% \DescribeCommand\IfLTXAtLeastTF
+% \marginpar{\raggedleft\tiny Added: 2021-01-31}%
+% This is the same like \cs{IfFormatAtLeast} of \LaTeX{} from 2020/10/01, but
+% works also with older \LaTeX{} kernels.
+%
+% \DescribeCommand\Ifislengthprimitive
+% \marginpar{\raggedleft\tiny Added: 2015/10/19\\Renamed: 2022/02/17}%
+% \cs{Ifislengthprimitive}\marg{macro}\marg{then code}\marg{else code}
+% expands the \meta{macro} and tests if the result can be used as a length
+% primitive. If this is the case the \meta{then code} is executed, otherwise
+% the \meta{else code}. Note, that this command can be false negative,
+% because, i.e., with \LuaLaTeX{} there can be primitives, that are like length,
+% but that are not known by \cs{Ifislengthprimitive}.
+%
+% \DescribeCommand\Ifisdefchar
+% \marginpar{\raggedleft\tiny Added: 2015/10/19\\Renamed: 2022/02/17}%
+% \cs{Ifislengthprimitive}\marg{macro}\marg{then code}\marg{else code}
+% expands the \meta{macro} and tests if the result is a \cs{char}. If this is
+% the case the \meta{then code} is executed, otherwise the \meta{else code}.
+% Note, that this command can be false positive, if the \cs{char} value is
+% incorrect.
+%
+%
+% \MaybeStop{\PrintIndex}
+%
+% \section{Implementation of \pkg*{scrbase} and \pkg*{scrkbase}}
+%
+% \subsection{Loading \pkg*{scrkbase}}
+% Who ever loads ths package, always wants the same version of the already
+% used \KOMAScript version.
+% \begin{macrocode}
+%<*load>
+\RequirePackage{scrkbase}[\KOMAScriptVersion]
+%</load>
+% \end{macrocode}
+%
+%
+% \subsection{\eTeX{} test}
+% \changes{v3.02c}{2009/02/19}{error message without \eTeX}
+%
+% \begin{macrocode}
+%<*prepare>
+%<*base>
+\begingroup
+ \def\reserved@b{}%
+ \def\reserved@a#1{%
+ \PackageError{scrbase}{seems you are not running e-TeX#1}{%
+ Since 2004 the LaTeX team recommends to use e-TeX.\MessageBreak
+ KOMA-Script since version 2.95 uses several e-TeX features.\MessageBreak
+ At actual systems `latex' should already use e-TeX.\MessageBreak
+ At deprecated systems it may be called `elatex'.\MessageBreak
+ Use either unsupported KOMA-Script up to version 2.9u or\MessageBreak
+ ask you administrator for LaTeX using e-TeX#1.\MessageBreak
+ Not using e-TeX#1 is a fatal error!\MessageBreak
+ Processing cannot be continued!}%
+ \endgroup
+ \batchmode \errmessage{}\csname @@end\endcsname\end\relax
+ \csname endinput\endcsname
+ }%
+ \expandafter\ifx\csname eTeXversion\endcsname\relax\else
+ \ifnum\eTeXversion <2
+ \def\reserved@b{ V 2}%
+ \else
+ \let\reserved@a\endgroup
+ \fi
+ \fi
+\expandafter\reserved@a\expandafter{\reserved@b}
+%</base>
+% \end{macrocode}
+%
+%
+% \subsection{The \KOMAScript-only package loads the universal package}
+%
+% Once again the same version is wanted.
+% \begin{macrocode}
+%<koma>\RequirePackage{scrbase}[\KOMAScriptVersion]
+% \end{macrocode}
+%
+% \subsection{Package \pkg*{scrlfile}}
+%
+% We need to react on the loading other packages like \pkg{polyglossia}. For
+% this we use \pkg*{scrlfile}. But we can use any version.
+%
+% \begin{macrocode}
+%<base>\RequirePackage{scrlfile}
+% \end{macrocode}
+%
+% \subsection{Package \pkg*{keyval}}
+%
+% The \KOMAScript{} key handling bases on package \pkg{keyval}.
+% \begin{macrocode}
+%<base>\RequirePackage{keyval}
+% \end{macrocode}
+%
+%
+% \subsection{Using protected kernel macros}
+% Some package like \pkg{amsgen} redefine internal \LaTeX{} kernel macros, but
+% break them for other purposes than the own. So I have to make them work
+% again. The \KOMAScript{} classes have less problems with this, because most
+% of these packages cannot be loaded before a class. So the classes can simply
+% copy the original macro, before it is redefined. But I do not know, when a
+% package is loaded. So I have to implement the whole macro again with another
+% name (and can only hope, that such packages do not damage them also).
+%
+% \begin{macro}{\kernel@ifstar}
+% \changes{v3.20}{2016/04/12}{added}
+% I hope, the \LaTeX{} kernel will define this in future and other packages do
+% not redefine like they do with \cs{@ifstar}. So I use \cs{providecommand} to
+% not redefine the kernel macro, if it does exist.
+% \begin{macrocode}
+%<base>\providecommand*\kernel@ifstar[1]{\kernel@ifnextchar*{\@firstoftwo{#1}}}
+% \end{macrocode}
+% \end{macro}^^A \kernel@ifstar
+%
+%
+% \subsection{Improved \LaTeX{} kernel commands}
+% The \LaTeX{} kernel already provides some useful commands, but some can be
+% improved.
+%
+% \begin{command}{\rloop}
+% \changes{v3.30}{2020/03/07}{added}
+% The \cs{loop} \dots \cs{repeat} of the \LaTeX{} kernel cannot be used inside
+% a \cs{loop} \dots \cs{repeat} without extra code for preserving
+% \cs{iterate}. So here is a re-entrant version that is also long. This
+% version can be used even inside a \cs{loop} \dots \cs{repeat}. However you
+% should not use \cs{loop} \dots \cs{repeat} inside \cs{rloop} \dots
+% \cs{repeat}.
+% \begin{macrocode}
+%<*base>
+\newcommand{\rloop}[1]{}
+\long\def\rloop#1\repeat{%
+ \ifdefined\iterate
+ \edef\iterate{\unexpanded{#1\relax\expandafter\iterate\fi\def\iterate}%
+ {\unexpanded\expandafter{\iterate}}}%
+ \else
+ \def\iterate{#1\relax\expandafter\iterate\fi\let\iterate\relax}%
+ \fi
+ \iterate
+}
+%</base>
+% \end{macrocode}
+% \end{command}
+%
+% \begin{command}{\IfLTXAtLeastTF}
+% \changes{v3.33}{2021/01/21}{new}
+% This is the same like \cs{IfFormatAtLeastTF} of the current \LaTeX{} kernel,
+% but does also work, if \cs{IfFormatAtLeastTF} is not defined because of
+% very old \LaTeX{} kernel.
+% \begin{macrocode}
+%<*base>
+\newcommand*{\IfLTXAtLeastTF}{\@ifl@t@r\fmtversion}
+\ifcsname IfFormatAtLeastTF\endcsname
+ \let\IfLTXAtLeastTF\IfFormatAtLeastTF
+\fi
+\@onlypreamble\IfLTXAtLeastTF
+%</base>
+% \end{macrocode}
+% \end{command}
+%
+%
+% \subsection{Testing macros}
+%
+% \begin{macro}{\scr@ifundefinedorrelax}
+% \changes{v2.95c}{2006/08/12}{added}
+% \changes{v2.97b}{2007/03/08}{broken logic fixed}
+% \changes{v2.97c}{2007/04/18}{broken functionality fixed}
+% \changes{v2.97c}{2007/04/18}{\cs{scr@ifundefined} renamed}
+% \changes{v3.02c}{2009/02/19}{special treatment of \eTeX{} removed}
+% This macro is like \cs{@ifundefined}, but does not define the test macro
+% \cs{relax} if it was undefined before. Note: With up-to-date \LaTeX{} this
+% is the same with the original \cs{@ifundefined}.
+% \begin{macrocode}
+%<*base>
+\newcommand{\scr@ifundefinedorrelax}[1]{%
+ \ifcsname #1\endcsname
+ \expandafter\ifx\csname #1\endcsname\relax
+ \expandafter\expandafter\expandafter\@firstoftwo
+ \else
+ \expandafter\expandafter\expandafter\@secondoftwo
+ \fi
+ \else
+ \expandafter\@firstoftwo
+ \fi
+}
+%</base>
+% \end{macrocode}
+% \end{macro}^^A \scr@ifundefinedorrelax
+%
+%
+% \subsection{Extending messages}
+%
+% \begin{command}{\PackageErrorNoLine}
+% \changes{v3.12}{2013/09/19}{added}
+% \changes{v3.28}{2019/11/23}{nonsense command removed}
+% Falk correctly stated, that \cs{PackageError} already does not show a line
+% number. So we do not need this command.
+% \end{command}
+%
+%
+% \subsection{Definition of the \KOMAScript{} \pkg*{keyval} basis}
+%
+% \KOMAScript{} could use \pkg{keyval} keys with the same set of keywords
+% ``\texttt{KOMA}'' to make it possible, that packages can redefine keys of
+% classes and other packages. However this would be dangerous and can easily
+% break. So we split the set of keywords in an family of keywords and family
+% member of keywords and define commands to process the keywords either of a
+% member or a whole family.
+%
+% \begin{command}{\DefineFamily,\DefineFamilyMember,\DefineFamilyKey}
+% \changes{v3.00}{2008/04/30}{added}
+% \changes{v3.20}{2016/04/12}{\cs{@ifnextchar} replaced by \cs{kernel@ifnextchar}}
+% \begin{macro}{\scr@if@family}
+% \changes{v3.00}{2008/04/30}{added}
+% \begin{macro}{\scr@if@familymember}
+% \changes{v3.00}{2008/04/30}{added}
+% \changes{v3.27}{2019/07/19}{the empty member exists by default}
+% \begin{macro}{\scr@define@family@key}
+% \changes{v3.00}{2008/04/30}{added}
+% \begin{macro}{\scr@define@family@key@nodefault}
+% \changes{v3.00}{2008/04/30}{added}
+% \changes{v3.18a}{2015/07/03}{missing \% added}
+% Family, member of a family and \pkg{keyval} key for a member of a
+% family. The default of the member of a family is always the file name of a
+% class or package (while reading the file).
+% \begin{macrocode}
+%<*base>
+\newcommand*{\DefineFamily}[1]{%
+ \scr@ifundefinedorrelax{#1@key@familylist}{%
+ \@namedef{#1@key@familylist}{}%
+ }{}%
+}
+\newcommand*{\scr@if@family}[2]{%
+ \scr@ifundefinedorrelax{#1@key@familylist}{%
+ \PackageError{scrbase}{%
+ unknown family `#1'%
+ }{%
+ You've tried to #2 for family `#1'.\MessageBreak
+ This my be done only for previous defined families.\MessageBreak
+ You should call `\string\DefineFamily{#1}' first.%
+ }%
+ }%
+}
+\newcommand*{\DefineFamilyMember}[2][.\@currname.\@currext]{%
+ \scr@if@family{#2}{define a family member}{%
+ \edef\reserved@a{%
+ \noexpand\in@{#2#1,}{\csname #2@key@familylist\endcsname}}%
+ \reserved@a
+ \ifin@\else
+ \expandafter\edef\csname #2@key@familylist\endcsname{%
+ \@nameuse{#2@key@familylist}#2#1,}%
+ \fi
+ }%
+}
+\newcommand*{\scr@if@familymember}[3]{%
+ \scr@if@family{#2}{#3}{%
+ \IfArgIsEmpty{#1}{%
+ \@firstofone
+ }{%
+ \edef\reserved@a{%
+ \noexpand\in@{#2#1,}{\csname #2@key@familylist\endcsname}}%
+ \reserved@a
+ \ifin@
+ \expandafter\@firstofone
+ \else
+ \PackageError{scrbase}{%
+ unknown member `#1' at family `#2'%
+ }{%
+ You've tried to #3 for member `#1' of family `#2'.\MessageBreak
+ This my be done only for previous defined family members.\MessageBreak
+ You should call `\string\DefineFamilyMember[{#1}]{#2}' first.%
+ }%
+ \expandafter\@gobble
+ \fi
+ }%
+ }%
+}
+\newcommand*{\DefineFamilyKey}[3][.\@currname.\@currext]{%
+ \kernel@ifnextchar[%]
+ {%
+ \edef\reserved@a{#1}%
+ \expandafter\scr@define@family@key
+ \expandafter{\reserved@a}{#2}{#3}%
+ }{%
+ \edef\reserved@a{#1}%
+ \expandafter\scr@define@family@key@nodefault
+ \expandafter{\reserved@a}{#2}{#3}%
+ }%
+}
+\newcommand{\scr@define@family@key}{}
+\long\def\scr@define@family@key#1#2#3[#4]#5{%
+ \scr@if@familymember{#1}{#2}{define a key}{%
+ \define@key{#2#1}{#3}[{#4}]{%
+ \def\FamilyOfKey{#2}\def\FamilyMemberOfKey{#1}%
+ \FamilyKeyStateUnknown
+ #5%
+ \def\FamilyOfKey{#2}\def\FamilyMemberOfKey{#1}%
+ }%
+ }%
+}
+\newcommand{\scr@define@family@key@nodefault}[4]{%
+ \scr@if@familymember{#1}{#2}{define a key}{%
+ \define@key{#2#1}{#3}{%
+ \def\FamilyOfKey{#2}\def\FamilyMemberOfKey{#1}%
+ \FamilyKeyStateUnknown
+ #4%
+ \def\FamilyOfKey{#2}\def\FamilyMemberOfKey{#1}%
+ }%
+ \@namedef{KV@#2#1@#3@default}{%
+ \def\FamilyOfKey{#2}\def\FamilyMemberOfKey{#1}%
+ \FamilyKeyStateNeedValue
+ }%
+ }%
+}
+%</base>
+% \end{macrocode}
+% \end{macro}^^A \scr@define@family@key@nodefault
+% \end{macro}^^A \scr@define@family@key
+% \end{macro}^^A \scr@if@familymember
+% \end{macro}^^A \scr@if@family
+% \end{command}^^A \DefineFamily,\DefineFamilyMember,\DefineFamilyKey
+%
+%
+% \begin{command}{\RelaxFamilyKey}
+% \changes{v3.15}{2014/12/03}{added}
+% Sometimes it is useful to be able to \emph{un-define} a key. This will not
+% un-define all helper macros but only the key and a default value will become
+% \cs{relax}.
+% \begin{macrocode}
+%<*base>
+\newcommand*{\RelaxFamilyKey}[3][.\@currname.\@currext]{%
+ \scr@ifundefinedorrelax{KV@#2#1@#3}{}{%
+ \expandafter\let\csname KV@#2#1@#3\endcsname\relax
+ }%
+ \scr@ifundefinedorrelax{KV@#2#1@#3@default}{}{%
+ \expandafter\let\csname KV@#2#1@#3@default\endcsname\relax
+ }%
+}
+%</base>
+% \end{macrocode}
+% \end{command}^^A \RelaxFamilyKey
+%
+% \begin{command}{\FamilyKeyState,\FamilyKeyStateProcessed,\FamilyKeyStateUnknown,
+% \FamilyKeyStateUnknownValue,\FamilyKeyStateNeedValue}
+% \changes{v3.12}{2013/03/04}{added}
+% \cs{FamilyKeyState} is the state of processing a key. The initial state is
+% \cs{FamilyKeyStateUnknown}, so the state is indeed unknown. If a key has
+% been processed by the definition code and everything is OK, you should run
+% \cs{FamilyKeyStateProcessed}. This will set \cs{FamilyKeyState} also to
+% \cs{FamilyKeyStateProcessed} to indicate, the key has been processed
+% successfully. If the value assigned to the key is unknown, you should run
+% \cs{FamilyKeyStateUnknownValue}. And if the value is needed but no value has
+% been assigned, \cs{FamilyKeyStateNeedValue} is the correct choice. Note:
+% \cs{FamilyKeyState} is valid only immediately after processing a key.
+% \begin{macrocode}
+%<*base>
+\newcommand*{\FamilyKeyState}{}
+\newcommand*{\FamilyKeyStateUnknown}{%
+ \let\FamilyKeyState\FamilyKeyStateUnknown
+}
+\newcommand*{\FamilyKeyStateUnknownValue}{%
+ \let\FamilyKeyState\FamilyKeyStateUnknownValue
+}
+\newcommand*{\FamilyKeyStateNeedValue}{%
+ \let\FamilyKeyState\FamilyKeyStateNeedValue
+}
+\newcommand*{\FamilyKeyStateProcessed}{%
+ \let\FamilyKeyState\FamilyKeyStateProcessed
+}
+\let\FamilyKeyState\FamilyKeyStateUnknown
+%</base>
+% \end{macrocode}
+% \end{command}^^A \FamilyKeyState … \FamilyKeyStateNeedValue
+%
+% \begin{command}{\FamilyOfKey,\FamilyMemberOfKey}
+% \changes{v3.12}{2013/03/04}{added}
+% While processing a key, this is the family and the member of family.
+% \begin{macrocode}
+%<*base>
+\newcommand*{\FamilyOfKey}{}
+\newcommand*{\FamilyMemberOfKey}{}
+%</base>
+% \end{macrocode}
+% \end{command}^^A \FamilyOfKey,\FamilyMemberOfKey
+%
+% \begin{macro}{\KOMA@key}
+% \changes{v2.97c}{2007/04/19}{optional argument added}
+% \changes{v3.17}{2015/02/24}{rudimentary value storage}
+% \pkg{keyval} keys of \KOMAScript{} are defined with \cs{KOMAkey} to setup
+% the family to ``\texttt{KOMA}'' automatically. Additionally the value
+% storage is initialized.
+% \begin{macrocode}
+%<*koma>
+\newcommand*{\KOMA@key}[1][.\@currname.\@currext]{%
+ \DefineFamilyMember[{#1}]{KOMA}%
+ \@ifundefined{scr@kav@KOMA#1}{\@namedef{scr@kav@KOMA#1}{}}{}%
+ \DefineFamilyKey[{#1}]{KOMA}%
+}
+%</koma>
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\KOMA@kav@add}
+% \changes{v3.17}{2015/02/24}{added}
+% This macro stores a \texttt{\meta{key}=\meta{value}} pair in a internal
+% list. The first argument is the family member, the second the \meta{key} and
+% the third the \meta{value}.
+% \begin{macrocode}
+%<*koma>
+\newcommand*{\KOMA@kav@add}[3]{%
+ \@ifundefined{scr@kav@KOMA#1}{%
+ \KOMA@internal@error\KOMA@kav@add{#1}%
+ }{%
+ \expandafter\l@addto@macro\csname scr@kav@KOMA#1\endcsname{\do{{#2}{#3}}}%
+ }%
+}
+%</koma>
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\KOMA@kav@xadd}
+% \changes{v3.17}{2015/02/24}{added}
+% This macro stores a \texttt{\meta{key}=\meta{value}} pair in a internal
+% list after expanding both, the \meta{key} and the \meta{value}. The first
+% argument is the family member, the second the \meta{key} and the third the
+% \meta{value}.
+% \begin{macrocode}
+%<*koma>
+\newcommand*{\KOMA@kav@xadd}[3]{%
+ \@ifundefined{scr@kav@KOMA#1}{%
+ \KOMA@internal@error\KOMA@kav@xadd{#1}%
+ }{%
+ \protected@edef\reserved@a{{#2}{#3}}%
+ \expandafter\l@addto@macro\csname scr@kav@KOMA#1\expandafter\endcsname
+ \expandafter{\expandafter\do\expandafter{\reserved@a}}%
+ }%
+}
+%</koma>
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\KOMA@kav@remove}
+% \changes{v3.17}{2015/02/24}{added}
+% This macro removes a \texttt{\meta{key}=\meta{value}} pair from the internal
+% list. The first argument is the family member, the second the \meta{key} and
+% the third the \meta{value}.
+% \begin{macrocode}
+%<*koma>
+\newcommand*{\KOMA@kav@remove}[3]{%
+ \@ifundefined{scr@kav@KOMA#1}{%
+ \KOMA@internal@error\KOMA@kav@remove{#1}%
+ }{%
+ \begingroup
+ \def\reserved@a{\endgroup\@namedef{scr@kav@KOMA#1}{}}%
+ \edef\reserved@b{\detokenize{{#2}{#3}}}%
+ \def\do##1{%
+ \edef\reserved@c{\detokenize{##1}}%
+ \ifx\reserved@b\reserved@c\else
+ \l@addto@macro\reserved@a{%
+ \expandafter\l@addto@macro\csname scr@kav@KOMA#1\endcsname{%
+ \do{##1}%
+ }%
+ }%
+ \fi
+ }%
+ \@nameuse{scr@kav@KOMA#1}%
+ \reserved@a
+ }%
+}
+%</koma>
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\KOMA@kav@removekey}
+% \changes{v3.17}{2015/02/24}{added}
+% This macro removes all \texttt{\meta{key}=\meta{value}} pairs of a given
+% \meta{key} from the internal list. The first argument is the family member,
+% the second the \meta{key}.
+% \begin{macrocode}
+%<*koma>
+\newcommand*{\KOMA@kav@removekey}[2]{%
+ \@ifundefined{scr@kav@KOMA#1}{%
+ \KOMA@internal@error\KOMA@kav@removekey{#1}%
+ }{%
+ \begingroup
+ \def\reserved@a{\endgroup\@namedef{scr@kav@KOMA#1}{}}%
+ \edef\reserved@b{\detokenize{#2}}%
+ \def\reserved@d##1##2{\edef\reserved@c{\detokenize{##1}}}%
+ \def\do##1{%
+ \reserved@d##1\relax
+ \ifx\reserved@b\reserved@c\else
+ \l@addto@macro\reserved@a{%
+ \expandafter\l@addto@macro\csname scr@kav@KOMA#1\endcsname{%
+ \do{##1}%
+ }%
+ }%
+ \fi
+ }%
+ \@nameuse{scr@kav@KOMA#1}%
+ \reserved@a
+ }%
+}
+%</koma>
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\KOMA@kav@replacevalue,\KOMA@kav@xreplacevalue}
+% \changes{v3.17}{2015/02/25}{added}
+% If \cs{FamilyKeyState} is \cs{FamilyKeyStateProcessed},
+% these macros replace a \texttt{\meta{key}=\meta{value}} pair in the internal list.
+% The first argument is the family member, the second the \meta{key} and the
+% third is the new \meta{value}. \cs{KOMA@kav@xreplacevalue} expands both, the
+% \meta{key} and the \meta{value}.
+% \begin{macrocode}
+%<*koma>
+\newcommand*{\KOMA@kav@replacevalue}[3]{%
+ \ifx\FamilyKeyState\FamilyKeyStateProcessed
+ \@ifundefined{scr@kav@KOMA#1}{%
+ \KOMA@internal@error\KOMA@kav@replacevalue{#1}%
+ }{%
+ \KOMA@kav@removekey{#1}{#2}%
+ \KOMA@kav@add{#1}{#2}{#3}%
+ }%
+ \fi
+}
+\newcommand*{\KOMA@kav@xreplacevalue}[3]{%
+ \ifx\FamilyKeyState\FamilyKeyStateProcessed
+ \@ifundefined{scr@kav@KOMA#1}{%
+ \KOMA@internal@error\KOMA@kav@replacevalue{#1}%
+ }{%
+ \KOMA@kav@removekey{#1}{#2}%
+ \KOMA@kav@xadd{#1}{#2}{#3}%
+ }%
+ \fi
+}
+%</koma>
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\KOMA@kav@replacebool}
+% \changes{v3.17}{2015/02/24}{added}
+% If \cs{FamilyKeyState} is \cs{FamilyKeyStateProcessed},
+% this macro replaces the value of a if key in the internal list.
+% The first argument is the family member, the second the \meta{key} and the
+% third is the boolean switch (\cs{if\dots} statement) representing the new value.
+% \begin{macrocode}
+%<*koma>
+\newcommand*{\KOMA@kav@replacebool}[3]{%
+ \ifx\FamilyKeyState\FamilyKeyStateProcessed
+ \@ifundefined{scr@kav@KOMA#1}{%
+ \KOMA@internal@error\KOMA@kav@replacebool{#1}%
+ }{%
+ \KOMA@kav@remove{#1}{#2}{false}%
+ \KOMA@kav@remove{#1}{#2}{true}%
+ \expandafter\ifx\csname if#3\expandafter\endcsname
+ \csname iftrue\endcsname
+ \KOMA@kav@xadd{#1}{#2}{true}%
+ \else
+ \KOMA@kav@xadd{#1}{#2}{false}%
+ \fi
+ }%
+ \fi
+}
+%</koma>
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\KOMA@kav@defall}
+% \changes{v3.17}{2015/02/24}{added}
+% This macro defines a macro/command with the \texttt{\meta{key}=\meta{value}}
+% list of all stored pairs. The first argument is the macro/command to be
+% defined with the list. The second is the family member.
+% \begin{macrocode}
+%<*koma>
+\newcommand*{\KOMA@kav@defall}[2]{%
+ \@ifundefined{scr@kav@KOMA#2}{%
+ \KOMA@internal@error\KOMA@kav@defall{#1}%
+ }{%
+ \begingroup
+ \let\reserved@a\@empty
+ \def\reserved@b##1##2{\l@addto@macro\reserved@a{,{##1=##2}}}%
+ \def\do##1{\reserved@b##1}%
+ \@nameuse{scr@kav@KOMA#2}%
+ \ifx\reserved@a\@empty
+ \def\reserved@b{\endgroup\let#1\@empty}%
+ \else
+ \edef\reserved@b{%
+ \unexpanded{\endgroup\def#1}{%
+ \unexpanded
+ \expandafter\expandafter\expandafter{%
+ \expandafter\@gobble\reserved@a}}}%
+ \fi
+ \reserved@b
+ }%
+}
+%</koma>
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\KOMA@kav@defone}
+% \changes{v3.17}{2015/02/25}{added}
+% \changes{v3.28}{2019/11/18}{\cs{ifstrstart} renamed to \cs{Ifstrstart}}
+% This macro defines a macro/command with all stored values of a \meta{key}
+% from the internal list of \texttt{\meta{key}=\meta{value}} pairs.
+% The first argument is the macro/command to be defined. The second is the
+% family member and the third is the \meta{key}.
+% \begin{macrocode}
+%<*koma>
+\newcommand*{\KOMA@kav@defone}[3]{%
+ \@ifundefined{scr@kav@KOMA#2}{%
+ \KOMA@internal@error\KOMA@kav@defall{#1}%
+ }{%
+ \begingroup
+ \let\reserved@a\@empty
+ \def\reserved@b##1##2{%
+ \Ifstr{##1}{#3}{\l@addto@macro\reserved@a{,{##2}}}{}%
+ }%
+ \def\do##1{\reserved@b##1}%
+ \@nameuse{scr@kav@KOMA#2}%
+ \ifx\reserved@a\@empty
+ \def\reserved@b{\endgroup\let#1\@empty}%
+ \else
+ \edef\reserved@b{%
+ \unexpanded{\endgroup\def#1}{%
+ \unexpanded
+ \expandafter\expandafter\expandafter{%
+ \expandafter\@gobble\reserved@a}}}%
+ \fi
+ \reserved@b
+ }%
+}
+%</koma>
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\KOMA@internal@error}
+% \changes{v3.17}{2015/02/24}{added}
+% General internal error message with the recommendation to report a bug.
+% \begin{macrocode}
+%<*koma>
+\newcommand*{\KOMA@internal@error}[2]{%
+ \PackageError{scrkbase}{internal error using \string#1{#2}}{%
+ You've found an internal error either in KOMA-Script or a third
+ party\MessageBreak
+ definition, that uses KOMA-Script internal macros.\MessageBreak
+ Please send a bug report with a minimal but complete example,
+ that\MessageBreak
+ shows this error, to komascript at gmx dot info or report it
+ at\MessageBreak
+ <http://www.komascript.de/forum/20> (you need an account to do so).%
+ }%
+}
+%</koma>
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Options}
+%
+% From version 2.97c \KOMAScript{} processes all options in the order they
+% have been set and no longer in the order they have been defined. This is
+% much more intuitive for users. Packages first process the global options
+% then the local options.
+%
+% \begin{macro}{\@globaloptionslist}
+% \changes{v2.96}{2006/11/26}{added}
+% \changes{v2.96}{2006/11/26}{process class options}
+% \changes{v3.20}{2016/02/06}{delay decisions}
+% The lost of global options is sometimes needed. But because \pkg{xkeyval}
+% has the opinion it should remove all options with equal char from the list
+% of class options, we define out own macro with a copy of the class
+% options. Until \KOMAScript{} 3.19a the copy has been done here. But if
+% \pkg*{scrbase} is loaded before \cs{documentclass} this is too early. From
+% \KOMAScript{} 3.20 the assignment has been moved to
+% \cs{FamilyProcessOptions}. And from \KOMAScript{} 3.33 the normal class
+% option list is only used if the raw option list is not available.
+% \begin{macrocode}
+%<*base>
+\newcommand*{\@globaloptionslist}{}
+%</base>
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\scr@removeunused,\scr@optiontest,\scr@pti@ntest}
+% \changes{v2.97c}{2007/04/18}{added}
+% \changes{v3.12}{2013/03/04}{removed}
+% \end{macro}^^A \scr@removeunused,\scr@optiontest,\scr@pti@ntest
+%
+% \begin{command}{\FamilyProcessOptions}
+% \changes{v3.00}{2008/04/30}{added}
+% \changes{v3.11a}{2012/06/11}{classes do not report errors for unknown values}
+% \changes{v3.12}{2013/03/04}{error handling}
+% \changes{v3.33}{2021/03/02}{new version using raw options lists of \LaTeX{}
+% 2021/05/01}
+% Note: Wrong values should not result in errors or warnings and only seldom
+% in information. The best is to signal all kind of errors via
+% \cs{FamilyKeyState}. Only values, that cannot be handled by any family
+% member have to be reported. This is done inside \cs{FamilyProcessOptions}
+% depending on \cs{FamilyKeyState} of each member.
+% Note also: This command is not re-entrant. So it cannot be used while
+% processing another option.
+% Note also: We use 2021/05/01 instead of the official \LaTeX{} release date,
+% to detect a \LaTeX{} kernel version with raw option lists, because there
+% were relevant earlier \LaTeX{} developer releases with that date.
+% \begin{macrocode}
+%<*base>
+\IncludeInRelease{2021/05/01}{\FamilyProcessOptions}%
+ {Usage of raw or classic option list}
+\newcommand*{\FamilyProcessOptions}[2][.\@currname.\@currext]{%
+% \end{macrocode}
+% Before processing of the options we have to execute an initialise several
+% hooks:
+% \begin{macrocode}
+ \ifx\AtEndOfFamilyOptions\scr@AtEndOfFamilyOptions
+ \PackageError{scrbase}{nested \string\FamilyProcessOptions\space
+ detected\MessageBreak}{%
+ \string\FamilyProcessOptions\space has been used while processing or
+ setting options.\MessageBreak
+ This is currently not allowed. You should contact the author of the
+ causing\MessageBreak
+ code.\MessageBreak
+ This error is fatal. You should not continue.%
+ }%
+ \fi
+ \scr@ifundefinedorrelax{scr@before@process@options@#2@hook}{}{%
+ \@nameuse{scr@before@process@options@#2@hook}%
+ }%
+ \scr@ifundefinedorrelax{scr@before@process@options@#2#1@hook}{}{%
+ \@nameuse{scr@before@process@options@#2#1@hook}%
+ \expandafter\let\csname scr@before@process@options@#2#1@hook\endcsname
+ \relax
+ }%
+ \scr@ifundefinedorrelax{scr@after@options@#2@hook}{%
+ \@namedef{scr@after@options@#2@hook}{%
+ \@namedef{scr@after@options@#2@hook}{}%
+ }%
+ }{%
+ \expandafter\edef\csname scr@after@options@#2@hook\endcsname{%
+ \noexpand\@namedef{scr@after@options@#2@hook}{%
+ \unexpanded\expandafter\expandafter\expandafter
+ {\csname scr@after@options@#2@hook\endcsname}%
+ }%
+ }%
+ }%
+ \ifx\AtEndOfFamilyOptions\scr@AtEndOfFamilyOptions@immediate
+ \@namedef{scr@after@options@#2@hook@topmost}{%
+ \@namedef{scr@after@options@#2@hook@topmost}{}%
+ }%
+ \expandafter\l@addto@macro\csname scr@after@options@#2@hook\endcsname{%
+ \let\AtEndOfFamilyOptions\scr@AtEndOfFamilyOptions@immediate
+ \@nameuse{scr@after@options@#2@hook@topmost}%
+ }%
+ \let\AtEndOfFamilyOptions\scr@AtEndOfFamilyOptions
+ \fi
+ \let\ds@\@empty
+% \end{macrocode}
+% Here we set up \cs{@curroptions} to the raw options of the current class or
+% package or empty if the options are not defined.
+% \begin{macrocode}
+ \@ifundefined{@raw@opt@\@currname.\@currext}{%
+ \let\@curroptions\@empty
+ }{%
+ \expandafter\let\expandafter\@curroptions
+ \csname @raw@opt@\@currname.\@currext\endcsname
+ }%
+% \end{macrocode}
+% If this is not a class, we first have to process all raw class options.
+% \changes{v3.33}{2021/03/12}{switched to fast test like \LaTeX{} 2021/06/01}
+% \changes{v3.34}{2021/05/30}{use \cs{@raw@classoptionslist} only, if defined}
+% Note, if \pkg*{scrbase} or a depending package is loaded before the class,
+% \cs{@raw@classoptionslist} should not be processed.
+% \begin{macrocode}
+ \ifx\@currext\@clsextension\else
+ \@ifundefined{@raw@classoptionslist}{}{%
+ \@for\CurrentOption:=\@raw@classoptionslist\do{%
+ \scr@trim@spaces\CurrentOption
+ \ifx\CurrentOption\@empty\else
+ \@ifundefined{ds@\CurrentOption}{%
+ \scr@ifprocess@curroption{#1}{#2}{%
+ \@expandtwoargs\@removeelement{%
+ \expandafter\@remove@eq@value\CurrentOption=\@nil}%
+ \@unusedoptionlist\@unusedoptionlist
+ }{}%
+ }{%
+ \@use@ption
+ \expandafter\let\csname ds@\CurrentOption\endcsname\@empty
+ }%
+ \fi
+ }%
+ }%
+ \fi
+% \end{macrocode}
+% \changes{v3.34}{2021/06/05}{extra test because of \LaTeX{} raw option issue}
+% Afterwards we have to process the current options. Unfortunately there is an
+% issue with the raw option list of the \LaTeX{} kernel, that could result in
+% \cs{CurrentOption} in the option list instead of the one step expansion of
+% \cs{CurrentOption} (see
+% \url{https://sourceforge.net/p/koma-script/tickets/10/}). This would result
+% in an infinite loop using the usual loop:
+% \begin{macrocode}
+%<*dontusethis>
+ \@for\CurrentOption:=\@curroptions\do{%
+ \scr@trim@spaces\CurrentOption
+ \@ifundefined{ds@\CurrentOption}{%
+ \@use@ption
+ \scr@ifprocess@curroption{#1}{#2}{}\default@ds
+ }\@use@ption
+ }%
+%</dontusethis>
+% \end{macrocode}
+% So for a little more rosbustnes we do an extra test.
+% \begin{macrocode}
+ \@for\reserved@a:=\@curroptions\do{%
+ \scr@trim@spaces\reserved@a
+ \def\reserved@b{\CurrentOption}%
+ \ifx\reserved@a\reserved@b
+ \PackageError{scrbase}{%
+ \string\CurrentOption\space loop detected\MessageBreak
+ Perhaps someone uses:\MessageBreak\space\space
+ \ifx\@currext\@clsextension
+ \string\PassOptionsToClass
+ \else
+ \string\PassOptionsToPackage
+ \fi
+ {\string\CurrentOption}{…}.\MessageBreak
+ With LaTeX 2020/10/01 or 2021/06/01 this results in
+ \string\CurrentOption\MessageBreak
+ in the raw option list and therefore is not allowed.\MessageBreak
+ Please ask the class or package author to use:\MessageBreak\space\space
+ \string\expandafter
+ \ifx\@currext\@clsextension
+ \string\PassOptionsToClass
+ \else
+ \string\PassOptionsToPackage
+ \fi
+ \MessageBreak\space\space\space
+ \string\expandafter{\string\CurrentOption}{…}\MessageBreak
+ instead or update LaTeX (if possible)%
+ }%
+ \let\CurrentOption\@empty
+ \else
+ \let\CurrentOption\reserved@a
+ \fi
+ \@ifundefined{ds@\CurrentOption}{%
+ \@use@ption
+ \scr@ifprocess@curroption{#1}{#2}{}\default@ds
+ }\@use@ption
+ }%
+% \end{macrocode}
+% Clear all the definitions for declared options and the current option. Then
+% reset the marker macro, initiate emptying the unprocessed options list of
+% the current file and execute the exit hook.
+% \begin{macrocode}
+ \@for\CurrentOption:=\@declaredoptions\do{%
+ \expandafter\let\csname ds@\CurrentOption\endcsname\relax}%
+ \let\CurrentOption\@empty
+ \let\@fileswith@pti@ns\@@fileswith@pti@ns
+ \AtEndOfPackage{\expandafter\let
+ \csname unprocessedoptions-\@currname.\@currext\endcsname
+ \relax}%
+ \@nameuse{scr@after@options@#2@hook}%
+}
+\EndIncludeInRelease
+% \end{macrocode}
+% And here the old version for old \LaTeX{} kernel version:
+% \begin{macrocode}
+\IncludeInRelease{0000/00/00}{\FamilyProcessOptions}%
+ {Usage of raw or classic option list}
+\newcommand*{\FamilyProcessOptions}[2][.\@currname.\@currext]{%
+ \ifx\AtEndOfFamilyOptions\scr@AtEndOfFamilyOptions
+ \PackageError{scrbase}{nested \string\FamilyProcessOptions\space
+ detected\MessageBreak}{%
+ \string\FamilyProcessOptions\space has been used while processing or
+ setting options.\MessageBreak
+ This is currently not allowed. You should contact the author of the
+ causing\MessageBreak
+ code.\MessageBreak
+ This error is fatal. You should not continue.%
+ }%
+ \fi
+% \end{macrocode}
+% \changes{v3.18}{2015/06/17}{new hooks before processing the options}
+% From version 3.18 we execute two hooks. The first one is valid for all
+% classes and packages of a family. This is multi-time hook, not deleting
+% itself. The second one is valid only one time for one member.
+% \begin{macrocode}
+ \scr@ifundefinedorrelax{scr@before@process@options@#2@hook}{}{%
+ \@nameuse{scr@before@process@options@#2@hook}%
+ }%
+ \scr@ifundefinedorrelax{scr@before@process@options@#2#1@hook}{}{%
+ \@nameuse{scr@before@process@options@#2#1@hook}%
+ \expandafter\let\csname scr@before@process@options@#2#1@hook\endcsname
+ \relax
+ }%
+% \end{macrocode}
+% \changes{v3.23}{2017/02/16}{fix: the after hook uses the family instead of
+% the member}
+% Initialization of \cs{AtEndOfFamilyOptions} inclusive hook.
+% \begin{macrocode}
+ \scr@ifundefinedorrelax{scr@after@options@#2@hook}{%
+ \@namedef{scr@after@options@#2@hook}{%
+% \end{macrocode}
+% The first hook action is to delete the hook.
+% \begin{macrocode}
+ \@namedef{scr@after@options@#2@hook}{}%
+ }%
+ }{%
+ \expandafter\edef\csname scr@after@options@#2@hook\endcsname{%
+% \end{macrocode}
+% The first action in the hook is to reactivate the current hook.
+% \begin{macrocode}
+ \noexpand\@namedef{scr@after@options@#2@hook}{%
+ \unexpanded\expandafter\expandafter\expandafter
+ {\csname scr@after@options@#2@hook\endcsname}%
+ }%
+ }%
+ }%
+% \end{macrocode}
+% \changes{v3.23}{2017/02/16}{new hook added for \cs{AtEndOfFamilyOptions*}}
+% From version 3.23 there is one more hook before \cs{AtEndOfFamilyOptions*}
+% to be initialized and executed. We can detect the topmost level comparing
+% the definition of \cs{AtEndOfFamilyOptions}. This is faster than by the
+% definition of the hook itself (we have to do so in \cs{FamilyOptions}).
+% \begin{macrocode}
+ \ifx\AtEndOfFamilyOptions\scr@AtEndOfFamilyOptions@immediate
+ \@namedef{scr@after@options@#2@hook@topmost}{%
+% \end{macrocode}
+% The hook definitions also contains the hook deletion. This is important for
+% recursive calls, to distinguish lower levels from the topmost level.
+% \begin{macrocode}
+ \@namedef{scr@after@options@#2@hook@topmost}{}%
+ }%
+% \end{macrocode}
+% The top hook is added to the hook of the (topmost) level, while resetting
+% the definition of \cs{AtEndOfFamilyOptions}.
+% \begin{macrocode}
+ \expandafter\l@addto@macro\csname scr@after@options@#2@hook\endcsname{%
+ \let\AtEndOfFamilyOptions\scr@AtEndOfFamilyOptions@immediate
+ \@nameuse{scr@after@options@#2@hook@topmost}%
+ }%
+% \end{macrocode}
+% Don't forget to change the command to fill one of the hooks from immediate
+% execution to adding code to the corresponding hook.
+% \begin{macrocode}
+ \let\AtEndOfFamilyOptions\scr@AtEndOfFamilyOptions
+ \fi
+% \end{macrocode}
+% Continue the adaption of code from \cs{ProcessOptions}.
+% \begin{macrocode}
+ \let\ds@\@empty
+ \edef\@curroptions{\@ptionlist{\@currname.\@currext}}%
+ \ifx\@currext\@clsextension\else
+% \end{macrocode}
+% Within classes the current option list is same like the global option
+% list. So classes are not allowed to process the global option list
+% additionally to the local one. But packages do process the global option
+% list, but do not report errors or warnings about these options.
+% \changes{v3.18}{2015/06/17}{handling of not defined \cs{@globaloptionslist}}
+% \changes{v3.20}{2016/02/06}{\cs{@globaloptionslist} assignment always}
+% \begin{macrocode}
+ \let\@globaloptionslist\@classoptionslist
+ \scr@ifundefinedorrelax{XKV@classoptionslist}{%
+%<trace> \PackageInfo{scrbase}{Using \string\@classoptionslist}%
+ }{%
+ \ifx\XKV@classoptionslist\@empty
+%<trace> \PackageInfo{scrbase}{Using \string\@classoptionslist}%
+ \else
+%<trace> \PackageInfo{scrbase}{Using \string\XKV@classoptionslist}%
+ \let\@globaloptionslist\XKV@classoptionslist
+ \fi
+ }%
+ \scr@ifundefinedorrelax{@globaloptionslist}{}{%
+ \@for\CurrentOption:=\@globaloptionslist\do{%
+% \end{macrocode}
+% The options are processed in the order they have been set into the global
+% option list. But only these options are processed, that are not empty and
+% that are known by the current package. So these are only classic options not
+% \pkg{keyval} options.
+% \begin{macrocode}
+ \ifx\CurrentOption\@empty\else
+ \@expandtwoargs\in@{,\CurrentOption,}{,\@declaredoptions,}%
+ \ifin@
+ \@use@ption
+ \expandafter\let\csname ds@\CurrentOption\endcsname\@empty
+ \else
+% \end{macrocode}
+% But if they are not classic options, they could be \pkg{keyval} options. In
+% this case we test, if member (\texttt{\#1}) of family (\texttt{\#2}) has
+% such an option. If this is the case, the options is executed once with
+% member and once again with member. In case of an unknown key or value
+% nothing else happens.
+% \begin{macrocode}
+ \scr@ifprocess@curroption{#1}{#2}{%
+ \@expandtwoargs\@removeelement\CurrentOption
+ \@unusedoptionlist\@unusedoptionlist
+ }{}%
+ \fi
+ \fi
+ }%
+ }%
+ \fi
+% \end{macrocode}
+% Now, processing local options of classes and packages follows. In this case
+% unknown options (keys) or values of packages immediately can result in error
+% messages. But in classes they are only added to the list of unused global
+% options.
+% \begin{macrocode}
+ \@for\CurrentOption:=\@curroptions\do{%
+% \end{macrocode}
+% \changes{v3.26}{2018/10/22}{options are not fully expanded for the tests}
+% \changes{v3.26}{2018/10/22}{\cs{@use@ption} is not used for
+% \texttt{\meta{key}\quotechar=\meta{value}} options}
+% From \KOMAScript~3.26 the options are not fully expanded to test, if it is a
+% classic option. The essential expansion already has been done. So removing
+% the full expansion avoids errors because of missing
+% \cs{endcsname}. Additionally using \cs{@use@option} hat been removed for all
+% \texttt{\meta{key}=\meta{value}} options, because this would result in the
+% same error because of the |\csname ds@\CurrentOption\endcsname|, that is
+% used inside \cs{@use@option}. Instead of \cs{@use@option} we just remove the
+% option from the list of unused options.
+% \begin{macrocode}
+ \edef\reserved@a{\expandafter\detokenize\expandafter{\CurrentOption}}%
+ \scr@ifundefinedorrelax{ds@\reserved@a}{%
+ \@expandtwoargs\@removeelement\CurrentOption
+ \@unusedoptionlist\@unusedoptionlist
+ \scr@ifprocess@curroption{#1}{#2}{}\default@ds
+ }\@use@ption
+ }%
+% \end{macrocode}
+% Almost at the end we delete the options code of all declared options. This
+% is the same as with the \LaTeX{} kernel command
+% \cs{ProcessOptions*}. Additionally at the end of the package (not
+% \pkg*{tocbasic} but the package, that is using the command) all unprocessed
+% options are processed.
+% \changes{v3.33}{2021/02/15}{prepared for \LaTeX{} 2020/10/01}
+% \begin{macrocode}
+ \@for\CurrentOption:=\@declaredoptions\do{%
+ \expandafter\let\csname ds@\CurrentOption\endcsname\relax}%
+ \let\CurrentOption\@empty
+ \let\@fileswith@pti@ns\@@fileswith@pti@ns
+ \IfLTXAtLeastTF{2020/10/01}{%
+ \AtEndOfPackage{\expandafter\let
+ \csname unprocessedoptions-\@currname.\@currext\endcsname
+ \relax}%
+ }{%
+ \AtEndOfPackage{\let\@unprocessedoptions\relax}%
+ }%
+% \end{macrocode}
+% Last but not least the hook has to be executed and (self-)deleted.
+% \changes{v3.23}{2017/02/16}{fix using family instead of member}
+% \begin{macrocode}
+ \@nameuse{scr@after@options@#2@hook}%
+}
+\EndIncludeInRelease
+\@onlypreamble\FamilyProcessOptions
+% \end{macrocode}
+% \begin{command}{\BeforeFamilyProcessOptions}
+% \changes{v3.18}{2015/06/17}{added}
+% Add code to the hook used immediately before executing the options via
+% \cs{FamilyProcessOptions}. Neither the family nor the member need to
+% exist. So you are able to already add code to the hook before the class or
+% package has been loaded.
+% \begin{macrocode}
+\newcommand*{\BeforeFamilyProcessOptions}[3][.\@currname.\@currext]{%
+ \scr@ifundefinedorrelax{scr@before@process@options@#2#1@hook}{%
+ \@namedef{scr@before@process@options@#2#1@hook}{#3}%
+ }{%
+ \expandafter\g@addto@macro
+ \csname scr@before@process@options@#2#1@hook\endcsname{#3}%
+ }%
+}
+% \end{macrocode}
+% \end{command}^^A \BeforeFamilyProcessOptions
+% \begin{command}{\AtEndOfFamilyOptions}
+% \changes{v3.12}{2013/03/04}{added}
+% \changes{v3.23}{2017/02/16}{star variant added}
+% Inside the code of an option you can delay execution of code till the end of
+% the current \cs{FamilyProcessOptions}, \cs{FamilyExecuteOptions},
+% \cs{FamilyOptions} or \cs{FamilyOption}. The only argument is the code. The
+% argument is delegated to \cs{l@addto@macro} (instead of reading it
+% directly). The non-star variant delays only till the end of the current
+% level. The star-variant delays till the end of all levels.
+% \begin{macro}{\scr@AtEndOfFamilyOptions}
+% \changes{v3.12}{2013/05/29}{added}
+% \begin{macro}{\scr@@AtEndOfFamilyOptions,\scr@AtEndOfFamilyOptions@immediate}
+% \changes{v3.23}{2017/02/16}{added}
+% \begin{macrocode}
+\newcommand*{\scr@AtEndOfFamilyOptions}{%
+ \kernel@ifstar {\scr@@AtEndOfFamilyOptions{@topmost}}%
+ {\scr@@AtEndOfFamilyOptions\@empty}%
+}
+\newcommand*{\scr@@AtEndOfFamilyOptions}[1]{%
+ \expandafter
+ \l@addto@macro\csname scr@after@options@\FamilyOfKey @hook#1\endcsname
+}
+\newcommand*{\scr@AtEndOfFamilyOptions@immediate}{%
+ \kernel@ifstar {\@firstofone}{\@firstofone}%
+}
+\newcommand*{\AtEndOfFamilyOptions}{}
+\let\AtEndOfFamilyOptions\scr@AtEndOfFamilyOptions@immediate
+% \end{macrocode}
+% \end{macro}^^A \scr@@AtEndOfFamilyOptions,\scr@AtEndOfFamilyOptions@immediate
+% \end{macro}^^A \scr@AtEndOfFamilyOptions
+% \end{command}^^A \AtEndOfFamilyOptions
+% \begin{macro}{\scr@ifprocess@curroption}
+% \changes{v3.13}{2014/01/04}{brackets around \cs{CurrentOption} inside \cs{setkeys}}
+% This macro executes the current \pkg{keyval} option for member
+% \texttt{\#1} of family \texttt{\#2}. If the option does not know the value,
+% the forth argument is used. Otherwise it is ignored. Note, before the member
+% option the family option is executed. If this is successful the member does
+% not need to know the option.
+% \begin{macrocode}
+\newcommand*\scr@ifprocess@curroption[2]{%
+% \end{macrocode}
+% \changes{v3.26}{2018/10/22}{using \cs{scr@sp@def} instead of \cs{def} for
+% splitting the key}
+% Because white spaces are not always and forever removed from the option
+% list, here \cs{scr@sp@def} is used to eliminate unwanted white spaces before
+% the key, before and after the equal sign and at the end of the value.
+% \begin{macrocode}
+ \def\reserved@a##1=##2\@nil{\scr@sp@def\reserved@a{##1}}%
+ \expandafter\reserved@a\CurrentOption=\@nil
+ \scr@ifundefinedorrelax{KV@#2@\reserved@a}{%
+ \scr@ifundefinedorrelax{KV@#2#1@\reserved@a}{%
+ \let\FamilyKeyState\OptionNotUsed
+ }{%
+ \protected@edef\reserved@b{\noexpand\setkeys{#2#1}{{\CurrentOption}}%
+ \noexpand\def\noexpand\CurrentOption{\CurrentOption}}%
+ \reserved@b
+ \ifx\FamilyKeyState\FamilyKeyStateUnknown
+ \PackageInfo{scrbase}{Unknown processing state.\MessageBreak
+ Processing option `\CurrentOption'\MessageBreak
+ of member `#1' of family\MessageBreak
+ `#2' doesn't set\MessageBreak
+ a valid state. This will be interpreted\MessageBreak
+ as \string\FamilyKeyStateProcessed
+ }%
+ \FamilyKeyStateProcessed
+ \fi
+ }{%
+ \let\FamilyKeyState\OptionNotUsed
+ }%
+ }{%
+ \protected@edef\reserved@b{\noexpand\setkeys{#2}{{\CurrentOption}}%
+ \noexpand\def\noexpand\CurrentOption{\CurrentOption}}%
+ \reserved@b
+ \ifx\FamilyKeyState\FamilyKeyStateUnknown
+ \PackageInfo{scrbase}{Unknown processing state.\MessageBreak
+ Processing option `\CurrentOption'\MessageBreak
+ of family `#2'\MessageBreak
+ doesn't set a valid state.\MessageBreak
+ This will be interpreted\MessageBreak
+ as \string\FamilyKeyStateProcessed
+ }%
+ \FamilyKeyStateProcessed
+ \fi
+ \def\reserved@a##1=##2\@nil{\scr@sp@def\reserved@a{##1}}%
+ \expandafter\reserved@a\CurrentOption=\@nil
+ \scr@ifundefinedorrelax{KV@#2#1@\reserved@a}{}{%
+ \protected@edef\reserved@b{\noexpand\setkeys{#2#1}{{\CurrentOption}}%
+ \noexpand\def\noexpand\CurrentOption{\CurrentOption}}%
+ \ifx\FamilyKeyState\FamiliyKeyStateProcessed
+ \reserved@b
+ \FamilyKeyStateProcessed
+ \else
+ \reserved@b
+ \ifx\FamilyKeyState\FamilyKeyStateUnknown
+ \PackageInfo{scrbase}{Unknown processing state.\MessageBreak
+ Processing option `\CurrentOption'\MessageBreak
+ of member `#1' of family\MessageBreak
+ `#2' doesn't set\MessageBreak
+ a valid state. This will be interpreted\MessageBreak
+ as \string\FamilyKeyStateProcessed
+ }%
+ \FamilyKeyStateProcessed
+ \fi
+ \fi
+ }%
+ }%
+ \ifx\FamilyKeyState\FamilyKeyStateProcessed
+ \expandafter\@firstoftwo
+ \else
+ \expandafter\@secondoftwo
+ \fi
+}
+% \end{macrocode}
+% \begin{macro}{\scr@sp@d,\scr@sp@b,\scr@sp@c,\scr@sp@def}
+% \changes{v3.26}{2018/08/29}{moved from \file{tocbasic.dtx} to
+% \file{scrkernel-basics.dtx} and renamed}
+% \changes{v3.26b}{2019/01/17}{\cs{long}}
+% The helper macro \cs{scr@sp@def} defines a macro (\texttt{\#1}) to contain a
+% token list (\texttt{\#2}) and removes tailing spaces at the beginning an the
+% end. The original definition was from \pkg{keyval}. The other macros are
+% helpers to realize \cs{scr@sp@def}.
+% \begin{macrocode}
+\def\@tempa#1{%
+ \long\def\scr@sp@def##1##2{%
+ \futurelet\scr@sp@tempa\scr@sp@d##2\@nil\@nil#1\@nil\relax##1}%
+ \def\scr@sp@d{%
+ \ifx\scr@sp@tempa\@sptoken
+ \expandafter\scr@sp@b
+ \else
+ \expandafter\scr@sp@b\expandafter#1%
+ \fi}%
+ \long\def\scr@sp@b#1##1 \@nil{\scr@sp@c##1}%
+}
+\@tempa{ }
+\long\def\scr@sp@c#1\@nil#2\relax#3{\@temptokena{#1}\edef#3{\the\@temptokena}}
+%</base>
+% \end{macrocode}
+% \end{macro}^^A \scr@sp@d,\scr@sp@b,\scr@sp@c,\scr@sp@def
+% \end{macro}^^A \scr@process@curroption
+% \end{command}^^A \FamilyProcessOptions
+%
+% \begin{command}{\KOMAProcessOptions}
+% \changes{v2.97c}{2007/04/18}{added}
+% \changes{v3.00}{2008/04/30}{no optional argument}
+% This command executes all options, not only classic declared by
+% \cs{DeclareOption} or \cs{DeclareOption*}, but also \pkg{keyval} options in
+% the order these options have been used (not declared). For packages first
+% the global options, than the local options. For classes global and local
+% options are the same and only local options are processed. This is similar
+% to the \LaTeX{} kernel command \cs{ProcessOptions*} (with the difference of
+% processing \pkg{keyval} options too). Family options are always executed
+% before member options.
+% \begin{macrocode}
+%<*koma>
+\newcommand*{\KOMAProcessOptions}{\FamilyProcessOptions{KOMA}}
+\@onlypreamble\KOMAProcessOptions
+%</koma>
+% \end{macrocode}
+% \end{command}
+%
+% \begin{macro}{\scr@trim@spaces}
+% \changes{v3.12}{2013/11/06}{added}
+% \changes{v3.26}{2018/08/29}{moved from \file{scrkernel-language.dtx} to
+% \file{scrkernel-basics.dtx}}
+% \changes{v3.33}{2021/03/02}{moved to preparation section}
+% Helper macro to remove white spaces from the beginning or the end. This is
+% useful for list processing with \cs{@for} to remove spaces before or after
+% commas. The argument is a macro with the string to be trimmed and the result
+% is stored again in this macro.
+% \begin{macrocode}
+%<*base>
+\newcommand\scr@trim@spaces[1]{%
+ \expandafter\scr@sp@def\expandafter#1\expandafter{#1}%
+}
+%</base>
+%</prepare>
+% \end{macrocode}
+% \end{macro}^^A \scr@trim@space
+%
+%
+% \begin{option}{internalonly}
+% \changes{v2.96}{2006/11/26}{added}
+% \changes{v2.97c}{2007/06/20}{no argument needed}
+% \changes{v3.27a}{2019/11/04}{\cs{FamilyKeyStateProcessed} added}
+% \changes{v3.27a}{2019/11/04}{defined only inside the package}
+% \changes{v3.27a}{2019/11/04}{defined temporary inside the classes}
+% \changes{v3.28}{2019/11/18}{deprecated}
+% \begin{macro}{\dont@let@as@internal@defined}
+% \changes{v2.96}{2006/11/26}{added}
+% \changes{v3.28}{2019/11/18}{removed}
+% \end{macro}
+% \begin{macrocode}
+%<*option>
+%<*base>
+\DefineFamily{KOMA}
+\DefineFamilyMember{KOMA}
+\DefineFamilyKey{KOMA}{internalonly}[\relax]{%
+ \PackageInfo{scrbase}{Ignoring deprecated option `internalonly'}%
+ \FamilyKeyStateProcessed
+}
+\AtEndOfPackage{%
+ \RelaxFamilyKey[.scrbase.sty]{KOMA}{internalonly}%
+}
+%</base>
+% \end{macrocode}
+% If \pkg*{scrbase} has been loaded before the class, the option will be
+% reported as unused, despite it already has been processed. We could solve
+% this using a dummy option inside the classes. However, because the option is
+% deprecated the following code should never been used.
+% \begin{macrocode}
+%</option>
+%<*load&class&neveruse>
+\KOMA@key{internalonly}[\relax]{%
+ \FamilyKeyStateProcessed
+}
+\AtEndOfClass{\RelaxFamilyKey[.\KOMAClassFileName]{KOMA}{internalonly}}%
+%</load&class&neveruse>
+%<*option>
+% \end{macrocode}
+% \end{option}
+%
+%
+% \changes{v2.96}{2006/08/20}{processing options}
+% \changes{v2.97c}{2007/04/18}{using \cs{KOMAProcessOptions} for processing options}
+% \begin{macrocode}
+%<koma>\KOMAProcessOptions\relax
+%<base>\FamilyProcessOptions{KOMA}\relax
+%</option>
+%<*body>
+% \end{macrocode}
+%
+%
+% \subsection{Some additional math missing from \eTeX}
+%
+% \begin{command}{\XdivY}
+% \changes{v3.05a}{2010/03/10}{added}
+% \meta{X} divided by \meta{Y} and rounded to the lower integer.
+% \begin{macrocode}
+%<*base>
+\newcommand*{\XdivY}[2]{%
+ \numexpr ( #1 + #2 / 2 ) / #2 - 1\relax
+}
+%</base>
+% \end{macrocode}
+% \end{command}
+%
+% \begin{command}{\XmodY}
+% \changes{v3.05a}{2010/03/10}{added}
+% \meta{X} modulo \meta{Y} (rest of integer division \meta{X} divided by \meta{Y}).
+% \begin{macrocode}
+%<*base>
+\newcommand*{\XmodY}[2]{%
+ \numexpr #1 - #2 * \XdivY{#1}{#2}\relax
+}
+%</base>
+% \end{macrocode}
+% \end{command}
+%
+% \subsection{Often needed commands and macros}
+%
+% \begin{macro}{\scr@ForEachTrimmedListElement}
+% \changes{v3.27}{2019/04/16}{new (internal)}
+% Executes \cs{\#2\{\meta{element}\}} for each \meta{element} of the comma
+% separated list \#1. Spaces before for after \meta{element} are eliminated
+% and empty elements are ignored.
+% \begin{macrocode}
+%<*base>
+\newcommand{\scr@ForEachTrimmedListElement}[2]{%
+ \begingroup
+ \def\reserved@a{\endgroup}%
+ \@for \reserved@b:=#1 \do {%
+ \scr@trim@spaces\reserved@b
+ \ifx\reserved@b\@empty\else
+ \edef\reserved@a{%
+ \unexpanded\expandafter{\reserved@a#2}%
+ {\unexpanded\expandafter{\reserved@b}}%
+ }%
+ \fi
+ }%
+ \reserved@a
+}
+%</base>
+% \end{macrocode}
+% \end{macro}^^A \scr@ForEachTrimmedListElement
+%
+% \begin{macro}{\@atdocumenttrue,\@atdocumentfalse,\if@atdocument}
+% \changes{v2.95}{2002/12/05}{added}
+% \changes{v3.37}{2022/05/06}{\cs{atdocumenttrue} moved with \LaTeX{}
+% 2020/10/01 or newer}
+% The boolean switch becomes true while |\begin{document}|. \KOMAScript{} uses
+% it for commands and macros, which are different in the document preamble and
+% the document body.
+% \begin{macrocode}
+%<*base>
+\newif\if@atdocument
+\IfLTXAtLeastTF{2020/10/01}{%
+ \AddToHook{begindocument/before}{\@atdocumenttrue}%
+}{%
+ \AtBeginDocument{\@atdocumenttrue}%
+}
+\@onlypreamble\@atdocumentrue
+\@onlypreamble\@atdocumentfalse
+%</base>
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\let@as@internal@defined}
+% \changes{v2.95}{2002/08/19}{added}
+% \changes{v2.95c}{2006/08/12}{warning while redefining}
+% \changes{v2.96}{2006/11/26}{making user commands from internal macros can
+% be banned for single macros}
+% \changes{v2.97c}{2007/06/20}{making user commands from internal macros can
+% generally banned}
+% \changes{v3.10}{2010/10/26}{\cs{ignorespaces} at \cs{document} patch added}
+% \changes{v3.13a}{2014/08/13}{unwanted white spaces removed}
+% \changes{v3.28}{2019/11/18}{removed}
+% \end{macro}
+%
+% \begin{command}{\ifundefined,\ifundefinedorrelax,\Ifundefinedorrelax}
+% \changes{v2.95}{2002/08/21}{added}
+% \changes{v2.95c}{2006/08/12}{using an internal macro to define it}
+% \changes{v2.97c}{2007/06/20}{\cs{ifundefinedorrelax} replaces \cs{ifundefined}}
+% \changes{v3.28}{2019/11/18}{\cs{ifundefinedorrelax} renamed to
+% \cs{Ifundefinedorrelax}}
+% \changes{v3.29}{2020/01/17}{fix of missing backslash}
+% Same as \cs{scr@ifundefinedorrelax} but at user level.
+% \begin{macrocode}
+%<*base>
+\newcommand*{\Ifundefinedorrelax}{\scr@ifundefinedorrelax}%
+%</base>
+% \end{macrocode}
+% \end{command}
+%
+% \begin{command}{\ifnotundefined,\Ifnotundefined}
+% \changes{v2.95}{2002/08/21}{added}
+% \changes{v2.95c}{2006/08/12}{using \eTeX{} if possible}
+% \changes{v3.02c}{2009/02/19}{\eTeX{} is mandatory}
+% \changes{v3.28}{2019/11/18}{\cs{ifnotundefined} renamed to \cs{Ifnotundefined}}
+% This is the opposite to \cs{Ifundefinedorrelax}. Sometimes it is useful.
+% \begin{macrocode}
+%<*base>
+\providecommand*{\ifnotundefined}{%
+ \PackageWarning{scrbase}{Usage of deprecated command
+ `\string\ifnotundefined'.\MessageBreak
+ The command has been renamed because of a\MessageBreak
+ recommendation of The LaTeX Project Team.\MessageBreak
+ Please replace `\string\ifnotundefined' by `\string\Ifnotundefined'%
+ }%
+ \Ifnotundefined
+}
+\newcommand{\Ifnotundefined}[1]{%
+ \ifcsname #1\endcsname
+ \expandafter\@firstoftwo
+ \else
+ \expandafter\@secondoftwo
+ \fi
+}
+%</base>
+% \end{macrocode}
+% \end{command}
+%
+% \begin{command}{\ifstr,\Ifstr}
+% \changes{v2.95}{2004/07/20}{\meta{if code} and \meta{then code} delegated
+% after the command execution}
+% \changes{v3.04b}{2010/01/29}{\cs{edef} replaced by \cs{protected@edef}}
+% \changes{v3.28}{2019/11/18}{\cs{ifstr} renamed to \cs{Ifstr} (but still
+% available as deprecated command)}
+% This command compares two fully expanded token lists. So an alternative name
+% would be \cs{Ifxequal}.
+% \begin{macrocode}
+%<*base>
+\providecommand*{\ifstr}{%
+ \PackageWarning{scrbase}{Usage of deprecated command
+ `\string\ifstr'.\MessageBreak
+ The command has been renamed because of a\MessageBreak
+ recommendation of The LaTeX Project Team.\MessageBreak
+ Please replace `\string\ifstr' by `\string\Ifstr'%
+ }%
+ \Ifstr
+}
+\newcommand\Ifstr[2]{%
+ \begingroup\protected@edef\reserved@a{#1}\protected@edef\reserved@b{#2}%
+ \ifx\reserved@a\reserved@b
+ \endgroup\expandafter\@firstoftwo
+ \else
+ \endgroup\expandafter\@secondoftwo
+ \fi
+}
+%</base>
+% \end{macrocode}
+% \end{command}
+%
+% \begin{command}{\ifstrstart,\Ifstrstart}
+% \changes{v3.12}{2013/11/05}{added}
+% \changes{v3.28}{2019/11/18}{\cs{ifstrstart} renamed to \cs{Ifstrstart} (but
+% still available as deprecated command)}
+% If the expansion of the first argument starts with expansion of the second
+% one use the third argument, otherwise the fourth.
+% \begin{macrocode}
+%<*base>
+\providecommand*{\ifstrstart}{%
+ \PackageWarning{scrbase}{Usage of deprecated command
+ `\string\ifstrstart'.\MessageBreak
+ The command has been renamed because of a\MessageBreak
+ recommendation of The LaTeX Project Team.\MessageBreak
+ Please replace `\string\ifstrstart' by `\string\Ifstrstart'%
+ }%
+ \Ifstrstart
+}
+\newcommand*{\Ifstrstart}[2]{%
+ \begingroup
+ \edef\reserved@a{\noexpand\@ifstrstart{#1}{#2}}%
+ \reserved@a{\aftergroup\@firstoftwo}{\aftergroup\@secondoftwo}%
+ \endgroup
+}
+% \end{macrocode}
+% \begin{macro}{\@ifstrstart}
+% \changes{v3.12}{2013/11/05}{added}
+% Helper.
+% \begin{macrocode}
+\newcommand*{\@ifstrstart}[2]{%
+ \def\reserved@a ##1#2##2\@nil{%
+ \if\relax\detokenize{##1}\relax
+ \expandafter\@firstoftwo
+ \else
+ \expandafter\@secondoftwo
+ \fi
+ }%
+ \reserved@a#1#2\@nil
+}
+%</base>
+% \end{macrocode}
+% \end{macro}^^A \@ifstrstart
+% \end{command}^^A \ifstrstart,\Ifstrstart
+%
+% \begin{command}{\IfArgIsEmpty}
+% \changes{v3.19}{2015/08/29}{added}
+% \changes{v3.27}{2019/03/11}{\cs{long}}
+% \changes{v3.27}{2019/07/19}{needed already to process options}
+% If the first argument is absolutely empty execute the second one, otherwise
+% the third one.
+%</body>
+%<*prepare>
+%<*base>
+% \begin{macrocode}
+\newcommand{\IfArgIsEmpty}[1]{%
+ \if\relax\detokenize{#1}\relax
+ \expandafter\@firstoftwo
+ \else
+ \expandafter\@secondoftwo
+ \fi
+}
+% \end{macrocode}
+%</base>
+%</prepare>
+%<*body>
+% \end{command}^^A \IfArgIsEmpty
+%
+%
+% \begin{command}{\ifislengthprimitive,\Ifislengthprimitive}
+% \changes{v3.20}{2015/10/19}{added}
+% \changes{v3.36}{2022/02/17}{\cs{ifislengthprimitive} renamed to
+% \cs{Ifislengthprimitive} (but still defined as deprecated)}
+% If the first argument expands to a primitive, that can be used as a length,
+% execute the second argument, otherwise the third one.
+% \begin{macrocode}
+%<*base>
+\providecommand*{\ifislengthprimitive}{%
+ \PackageWarning{scrbase}{Usage of deprecated command
+ `\string\ifislengthprimitive'.\MessageBreak
+ The command has been renamed because of a\MessageBreak
+ recommendation of The LaTeX Project Team.\MessageBreak
+ Please replace `\string\ifislengthprimitive' by `\string\Ifislengthprimitive'%
+ }%
+ \Ifislengthprimitive
+}
+\newcommand*{\Ifislengthprimitive}[1]{%
+ \IfArgIsEmpty{#1}{\@secondoftwo}{\scr@ifislengthprimitive#1\@nil}%
+}
+% \end{macrocode}
+% \begin{macro}{\scr@ifislengthprimitive}
+% \changes{v3.20}{2015/10/19}{added}
+% \changes{v3.28}{2019/11/18}{\cs{ifstrstart} renamed to \cs{Ifstrstart}}
+% \changes{v3.28}{2019/11/18}{\cs{ifstr} renamed to \cs{Ifstr}}
+% Helper macro to test against several length like \TeX{} primitives.
+% \begin{macrocode}
+\newcommand*{\scr@ifislengthprimitive}[1]{%
+ \begingroup
+ \Ifstrstart{\meaning #1}{\detokenize{macro:}}{%
+ \aftergroup\expandafter\aftergroup\scr@ifislengthprimitive
+ }{%
+ \def\reserved@c{\aftergroup\scr@secondoftwoAfterNil}%
+ \@for\reserved@a:=\baselineskip,\dp,\hsize,\ht,\lineskip,%
+ \parindent,\parskip,\pdfpageheight,\pdfpagewidth,%
+ \wd,\vsize \do {%
+ \expandafter\Ifstr\expandafter{\expandafter\string\reserved@a}{%
+ \meaning #1%
+ }{%
+ \def\reserved@c{\aftergroup\scr@TestDimenAssignTillNil}%
+ }%
+ }%
+ \reserved@c
+ }%
+ \endgroup
+ #1%
+}
+%</base>
+% \end{macrocode}
+% \end{macro}^^A \scr@ifislengthprimitive
+% \end{command}^^A \ifislengthprimitive,\Ifislengthprimitive
+%
+%
+% \begin{command}{\ifisdimen,\Ifisdimen}
+% \changes{v3.12}{2013/11/05}{added}
+% \changes{v3.20}{2015/10/19}{re-implemented}
+% \changes{v3.28}{2019/11/19}{\cs{ifisdimen} renamed to \cs{Ifisdimen} (but
+% still defined as deprecated command)}
+% If the first argument expands to a \cs{dimen} register (and nothing else),
+% execute the second argument, otherwise the third one.
+% \begin{macrocode}
+%<*base>
+\providecommand*{\ifisdimen}{%
+ \PackageWarning{scrbase}{Usage of deprecated command
+ `\string\ifisdimen'.\MessageBreak
+ The command has been renamed because of a\MessageBreak
+ recommendation of The LaTeX Project Team.\MessageBreak
+ Please replace `\string\ifisdimen' by `\string\Ifisdimen'%
+ }%
+ \Ifisdimen
+}
+\newcommand*{\Ifisdimen}[1]{%
+ \IfArgIsEmpty{#1}{\@secondoftwo}{\scr@ifisdimen#1\@nil}%
+}
+% \end{macrocode}
+% \begin{macro}{\scr@ifisdimen}
+% \changes{v3.20}{2015/10/19}{added}
+% \changes{v3.28}{2019/11/18}{\cs{ifstrstart} renamed to \cs{Ifstrstart}}
+% Helper macro, that tests a macro recursive to expand to a \cs{dimen} register.
+% \begin{macrocode}
+\newcommand*{\scr@ifisdimen}[1]{%
+ \begingroup
+ \Ifstrstart{\meaning #1}{\detokenize{macro:}}{%
+ \aftergroup\expandafter\aftergroup\scr@ifisdimen
+ }{%
+ \Ifstrstart{\meaning #1}{\string\dimen}{%
+ \aftergroup\scr@TestDimenAssignTillNil
+ }{%
+ \aftergroup\scr@secondoftwoAfterNil
+ }%
+ }%
+ \endgroup
+ #1%
+}
+% \end{macrocode}
+% \end{macro}^^A \scr@ifisdimen
+% \begin{macro}{\scr@TestDimenAssignTillNil}
+% \changes{v3.20}{2015/10/19}{added}
+% Argument \texttt{\#1} delimited by \cs{@nil} is assigned to a temporary
+% length. If this uses the argument completely, the argument \texttt{\#2} behind
+% \cs{@nil} will executed, otherwise argument \texttt{\#3}. In any case
+% \texttt{\#1} will removed from the input totally.
+% \begin{macrocode}
+\newcommand*\scr@TestDimenAssignTillNil{}
+\def\scr@TestDimenAssignTillNil#1\@nil{%
+ \begingroup
+ \afterassignment\scr@AfterEndGroupIfArgIsRelaxTillNnil
+ \@tempdima=#1\relax\@nnil
+}
+% \end{macrocode}
+% \begin{macro}{\scr@IfAfterEndgroupArgIsRelaxTillNnil,\scr@IfArgIsRelaxAfterRelaxTillNnil}
+% \changes{v3.20}{2015/10/19}{added}
+% \changes{v3.28}{2019/11/18}{\cs{ifstr} renamed to \cs{Ifstr}}
+% \changes{v3.28}{2019/11/18}{\cs{ifstrstart} renamed to \cs{Ifstrstart}}
+% The helper macros read an argument delimited by \cs{@nnil}. If this
+% arguments consists of a number of \cs{relax} only, the second argument (first
+% behind \cs{@nnil}) will be execute, otherwise the third (second behind \cs{@nnil}).
+% \begin{macrocode}
+\newcommand*\scr@AfterEndGroupIfArgIsRelaxTillNnil{}
+\def\scr@AfterEndGroupIfArgIsRelaxTillNnil#1\@nnil{%
+ \endgroup
+ \Ifstr{\detokenize{#1}}{\detokenize{\relax}}{\@firstoftwo}{%
+ \Ifstrstart{\detokenize{#1}}{\detokenize{\relax}}{%
+ \scr@IfArgIsRelaxAfterRelaxTillNnil #1\@nnil
+ }{\@secondoftwo}%
+ }%
+}
+\newcommand*\scr@IfArgIsRelaxAfterRelaxTillNnil{}
+\def\scr@IfArgIsRelaxAfterRelaxTillNnil \relax#1\@nnil{%
+ \Ifstr{\detokenize{#1}}{\detokenize{\relax}}{\@firstoftwo}{%
+ \Ifstrstart{\detokenize{#1}}{\detokenize{\relax}}{%
+ \scr@IfArgIsRelaxAfterRelaxTillNnil #1\@nnil
+ }{\@secondoftwo}%
+ }%
+}
+% \end{macrocode}
+% \end{macro}^^A \scr@IfArgIsRelaxTillNnil,\scr@IfArgIsRelaxAfterRelaxTillNnil
+% \end{macro}^^A \scr@TestSkipAssignTillNil
+% \begin{macro}{\scr@@secondoftwoAfterNil,\scr@secondoftwoAfterNil}
+% \changes{v3.20}{2015/10/19}{added}
+% The helper macros reads arguments \texttt{\#1} delimited by \cs{@nil} and
+% executes \texttt{\#3}. We have to take care for the case of an empty first
+% argument, which would make \cs{@nil} to be the argument. Because of this we
+% need two helpers.
+% \begin{macrocode}
+\newcommand*{\scr@secondoftwoAfterNil}{\scr@@secondoftwoAfterNil\@empty}
+\newcommand*{\scr@@secondoftwoAfterNil}{}
+\def\scr@@secondoftwoAfterNil#1\@nil{\@secondoftwo}
+%</base>
+% \end{macrocode}
+% \end{macro}^^A \scr@@secondoftwoAfterNil,\scr@secondoftwoAfterNil
+% \end{command}^^A \ifisdimen,\Ifisdimen
+%
+% \begin{command}{\ifisskip,\Ifisskip}
+% \changes{v3.12}{2013/11/05}{added}
+% \changes{v3.18a}{2015/07/07}{\cs{baselineskip} and \cs{parskip} are skips}
+% \changes{v3.20}{2015/10/19}{\cs{baselineskip} and \cs{parskip} are not skips}
+% \changes{v3.20}{2015/10/19}{re-implemented}
+% \changes{v3.28}{2019/11/19}{\cs{ifisskip} renamed to \cs{Ifisskip}}
+% If the first argument expands to a \cs{skip} register (and nothing else),
+% execute the second argument, otherwise the third one.
+% \begin{macrocode}
+%<*base>
+\providecommand*{\ifisskip}{%
+ \PackageWarning{scrbase}{Usage of deprecated command
+ `\string\ifisskip'.\MessageBreak
+ The command has been renamed because of a\MessageBreak
+ recommendation of The LaTeX Project Team.\MessageBreak
+ Please replace `\string\ifisskip' by `\string\Ifisskip'%
+ }%
+ \Ifisskip
+}
+\newcommand*{\Ifisskip}[1]{%
+ \IfArgIsEmpty{#1}{\@secondoftwo}{\scr@ifisskip#1\@nil}%
+}
+% \end{macrocode}
+% \begin{macro}{\scr@ifisskip}
+% \changes{v3.20}{2015/10/19}{added}
+% \changes{v3.28}{2019/11/18}{\cs{ifstrstart} renamed to \cs{Ifstrstart}}
+% Helper macro, that tests a macro recursive to expand to a \cs{skip} register.
+% \begin{macrocode}
+\newcommand*{\scr@ifisskip}[1]{%
+ \begingroup
+ \Ifstrstart{\meaning #1}{\detokenize{macro:}}{%
+ \aftergroup\expandafter\aftergroup\scr@ifisskip
+ }{%
+ \Ifstrstart{\meaning #1}{\string\skip}{%
+ \aftergroup\scr@TestSkipAssignTillNil
+ }{%
+ \aftergroup\scr@secondoftwoAfterNil
+ }%
+ }%
+ \endgroup
+ #1%
+}
+% \end{macrocode}
+% \end{macro}^^A \scr@ifisskip
+% \begin{macro}{\scr@TestSkipAssignTillNil}
+% \changes{v3.20}{2015/10/19}{added}
+% Argument \texttt{\#1} delimited by \cs{@nil} is assigned to a temporary
+% \cs{skip}. If this uses the argument completely, the argument \texttt{\#2} behind
+% \cs{@nil} will executed, otherwise argument \texttt{\#3}. In any case
+% \texttt{\#1} will removed from the input totally.
+% \begin{macrocode}
+\newcommand*\scr@TestSkipAssignTillNil{}
+\def\scr@TestSkipAssignTillNil#1\@nil{%
+ \begingroup
+ \afterassignment\scr@AfterEndGroupIfArgIsRelaxTillNnil
+ \@tempskipa=#1\relax\@nnil
+}
+%</base>
+% \end{macrocode}
+% \end{macro}^^A \scr@TestSkipAssignTillNil
+% \end{command}^^A \ifiskip,\Ifisskip
+%
+% \begin{command}{\ifiscount,\Ifiscount}
+% \changes{v3.12}{2013/11/05}{added}
+% \changes{v3.20}{2015/10/19}{re-implemented}
+% \changes{v3.28}{2019/11/19}{\cs{ifiscount} renamed to \cs{Ifiscount}}
+% If the first argument expands to a \cs{count} register (and nothing else),
+% execute the second argument, otherwise the third one.
+% \begin{macrocode}
+%<*base>
+\providecommand*{\ifiscount}{%
+ \PackageWarning{scrbase}{Usage of deprecated command
+ `\string\ifiscount'.\MessageBreak
+ The command has been renamed because of a\MessageBreak
+ recommendation of The LaTeX Project Team.\MessageBreak
+ Please replace `\string\ifiscount' by `\string\Ifiscount'%
+ }%
+ \Ifiscount
+}
+\newcommand*{\Ifiscount}[1]{%
+ \IfArgIsEmpty{#1}{\@secondoftwo}{\scr@ifiscount#1\@nil}%
+}
+% \end{macrocode}
+% \begin{macro}{\scr@ifiscount}
+% \changes{v3.20}{2015/10/19}{added}
+% \changes{v3.28}{2019/11/18}{\cs{ifstrstart} renamed to \cs{Ifstrstart}}
+% Helper macro, that tests a macro recursive to expand to a \cs{count} register.
+% \begin{macrocode}
+\newcommand*{\scr@ifiscount}[1]{%
+ \begingroup
+ \Ifstrstart{\meaning #1}{\detokenize{macro:}}{%
+ \aftergroup\expandafter\aftergroup\scr@ifiscount
+ }{%
+ \Ifstrstart{\meaning #1}{\string\count}{%
+ \aftergroup\scr@TestCountAssignTillNil
+ }{%
+ \aftergroup\scr@secondoftwoAfterNil
+ }%
+ }%
+ \endgroup
+ #1%
+}
+% \end{macrocode}
+% \end{macro}^^A \scr@ifiscount
+% \begin{macro}{\scr@TestSkipCountTillNil}
+% \changes{v3.20}{2015/10/19}{added}
+% Argument \texttt{\#1} delimited by \cs{@nil} is assigned to a temporary
+% counter. If this uses the argument completely, the argument \texttt{\#2} behind
+% \cs{@nil} will executed, otherwise argument \texttt{\#3}. In any case
+% \texttt{\#1} will removed from the input totally.
+% \begin{macrocode}
+\newcommand*\scr@TestCountAssignTillNil{}
+\def\scr@TestCountAssignTillNil#1\@nil{%
+ \begingroup
+ \afterassignment\scr@AfterEndGroupIfArgIsRelaxTillNnil
+ \@tempcnta=#1\relax\@nnil
+}
+%</base>
+% \end{macrocode}
+% \end{macro}^^A \scr@TestCountAssignTillNil
+% \end{command}^^A \ifiscount,\Ifiscount
+%
+%
+% \begin{command}{\ifisdimexpr,\Ifisdimexpr}
+% \changes{v3.12}{2013/11/05}{added}
+% \changes{v3.20}{2015/10/19}{re-implemented}
+% \changes{v3.28}{2019/11/19}{\cs{ifisdimexpr} renamed to \cs{Ifisdimexpr}}
+% If the first argument expands to a \cs{dimexpr},
+% execute the second argument, otherwise the third one. There is an important
+% difference to \cs{Ifisdimen}: If the argument begins with \cs{dimexpr} but
+% is not a valid \emph{dimension expression} \cs{Ifisdimexpr} detects a
+% \cs{dimexpr}, but using this expression later will result in an error.
+% \begin{macrocode}
+%<*base>
+\providecommand*{\ifisdimexpr}{%
+ \PackageWarning{scrbase}{Usage of deprecated command
+ `\string\ifisdimexpr'.\MessageBreak
+ The command has been renamed because of a\MessageBreak
+ recommendation of The LaTeX Project Team.\MessageBreak
+ Please replace `\string\ifisdimexpr' by `\string\Ifisdimexpr'%
+ }%
+ \Ifisdimexpr
+}
+\newcommand*{\Ifisdimexpr}[1]{%
+ \IfArgIsEmpty{#1}{\@secondoftwo}{\scr@ifisdimexpr#1\relax\@nil}%
+}
+% \end{macrocode}
+% \begin{macro}{\scr@ifisdimexpr}
+% \changes{v3.20}{2015/10/19}{added}
+% \changes{v3.28}{2019/11/18}{\cs{ifstrstart} renamed to \cs{Ifstrstart}}
+% Helper macro, that tests a macro recursive to expand to a \cs{dimexpr}.
+% \begin{macrocode}
+\newcommand*{\scr@ifisdimexpr}[1]{%
+ \begingroup
+ \Ifstrstart{\meaning #1}{\detokenize{macro:}}{%
+ \aftergroup\expandafter\aftergroup\scr@ifisdimexpr
+ }{%
+ \Ifstrstart{\meaning #1}{\string\dimexpr}{%
+ \aftergroup\scr@TestDimenAssignTillNil
+ }{%
+ \aftergroup\scr@secondoftwoAfterNil
+ }%
+ }%
+ \endgroup
+ #1%
+}
+%</base>
+% \end{macrocode}
+% \end{macro}^^A \scr@ifisdimexpr
+% \end{command}^^A \ifisdimexpr,\Ifisdimexpr
+%
+%
+% \begin{command}{\ifisglueexpr,\Ifisglueexpr}
+% \changes{v3.12}{2013/11/05}{added}
+% \changes{v3.20}{2015/10/19}{re-implemented}
+% \changes{v3.28}{2019/11/19}{\cs{ifisglueexpr} renamed to \cs{Ifisglueexpr}}
+% If the first argument expands to a \cs{glueexpr},
+% execute the second argument, otherwise the third one. There is an important
+% difference to \cs{Ifisskip}: If the argument begins with \cs{glueexpr} but
+% is not a valid \emph{glue expression} \cs{Ifisglueexpr} detects a
+% \cs{göueexpr}, but using this expression later will result in an error.
+% \begin{macrocode}
+%<*base>
+\providecommand*{\ifisglueexpr}{%
+ \PackageWarning{scrbase}{Usage of deprecated command
+ `\string\ifisglueexpr'.\MessageBreak
+ The command has been renamed because of a\MessageBreak
+ recommendation of The LaTeX Project Team.\MessageBreak
+ Please replace `\string\ifisglueexpr' by `\string\Ifisglueexpr'%
+ }%
+ \Ifisglueexpr
+}
+\newcommand*{\Ifisglueexpr}[1]{%
+ \IfArgIsEmpty{#1}{\@secondoftwo}{\scr@ifisglueexpr#1\relax\@nil}%
+}
+% \end{macrocode}
+% \begin{macro}{\scr@ifisglueexpr}
+% \changes{v3.20}{2015/10/19}{added}
+% \changes{v3.28}{2019/11/18}{\cs{ifstrstart} renamed to \cs{Ifstrstart}}
+% Helper macro, that tests a macro recursive to expand to a \cs{glueexpr}.
+% \begin{macrocode}
+\newcommand*{\scr@ifisglueexpr}[1]{%
+ \begingroup
+ \Ifstrstart{\meaning #1}{\detokenize{macro:}}{%
+ \aftergroup\expandafter\aftergroup\scr@ifisglueexpr
+ }{%
+ \Ifstrstart{\meaning #1}{\string\glueexpr}{%
+ \aftergroup\scr@TestSkipAssignTillNil
+ }{%
+ \aftergroup\scr@secondoftwoAfterNil
+ }%
+ }%
+ \endgroup
+ #1%
+}
+%</base>
+% \end{macrocode}
+% \end{macro}^^A \scr@ifisglueexpr
+% \end{command}^^A \ifisglueexpr,\Ifisglueexpr
+%
+%
+% \begin{command}{\ifisnumexpr,\Ifisnumexpr}
+% \changes{v3.12}{2013/11/05}{added}
+% \changes{v3.20}{2015/10/19}{re-implemented}
+% \changes{v3.28}{2019/11/19}{\cs{ifisnumexpr} renamed to \cs{Ifisnumexpr}}
+% If the first argument expands to a \cs{numexpr},
+% execute the second argument, otherwise the third one. There is an important
+% difference to \cs{Ifiscount}: If the argument begins with \cs{numexpr} but
+% is not a valid \emph{numerical expression} \cs{Ifisnumexpr} detects a
+% \cs{numexpr}, but using this expression later will result in an error.
+% \begin{macrocode}
+%<*base>
+\providecommand*{\ifisnumexpr}{%
+ \PackageWarning{scrbase}{Usage of deprecated command
+ `\string\ifisnumexpr'.\MessageBreak
+ The command has been renamed because of a\MessageBreak
+ recommendation of The LaTeX Project Team.\MessageBreak
+ Please replace `\string\ifisnumexpr' by `\string\Ifisnumexpr'%
+ }%
+ \Ifisnumexpr
+}
+\newcommand*{\Ifisnumexpr}[1]{%
+ \IfArgIsEmpty{#1}{\@secondoftwo}{\scr@ifisnumexpr#1\relax\@nil}%
+}
+% \end{macrocode}
+% \begin{macro}{\scr@ifisnumexpr}
+% \changes{v3.20}{2015/10/19}{added}
+% \changes{v3.28}{2019/11/18}{\cs{ifstrstart} renamed to \cs{Ifstrstart}}
+% Helper macro, that tests a macro recursive to expand to a \cs{numexpr}.
+% \begin{macrocode}
+\newcommand*{\scr@ifisnumexpr}[1]{%
+ \begingroup
+ \Ifstrstart{\meaning #1}{\detokenize{macro:}}{%
+ \aftergroup\expandafter\aftergroup\scr@ifisnumexpr
+ }{%
+ \Ifstrstart{\meaning #1}{\string\numexpr}{%
+ \aftergroup\scr@TestCountAssignTillNil
+ }{%
+ \aftergroup\scr@secondoftwoAfterNil
+ }%
+ }%
+ \endgroup
+ #1%
+}
+%</base>
+% \end{macrocode}
+% \end{macro}^^A \scr@ifisnumexpr
+% \end{command}^^A \ifisnumexpr,\Ifisnumexpr
+%
+%
+% \begin{command}{\ifisdefchar,\Ifisdefchar}
+% \changes{v3.20}{2015/10/19}{added}
+% \changes{v3.36}{2022/02/17}{\cs{ifisdefchar} renamed to \cs{Ifisdefchar}}
+% If the first argument expands to a value defined using \cs{chardef},
+% execute the second argument, otherwise the third one. Note: If the expanded
+% argument begins with \verb|\char"| but is not a valid \emph{character value}
+% \cs{Ifisdefchar} detects a valid value, but using this value later will
+% result in an error.
+% \begin{macrocode}
+%<*base>
+\providecommand*{\ifisdefchar}{%
+ \PackageWarning{scrbase}{Usage of deprecated command
+ `\string\ifisdefchar'.\MessageBreak
+ The command has been renamed because of a\MessageBreak
+ recommendation of The LaTeX Project Team.\MessageBreak
+ Please replace `\string\ifisdefchar' by `\string\Ifisdefchar'%
+ }%
+ \Ifisdefchar
+}
+\newcommand*{\Ifisdefchar}[1]{%
+ \IfArgIsEmpty{#1}{\@secondoftwo}{\scr@ifisdefchar#1\@nil}%
+}
+% \end{macrocode}
+% \begin{macro}{\scr@ifisdefchar}
+% \changes{v3.20}{2015/10/19}{added}
+% \changes{v3.28}{2019/11/18}{\cs{ifstrstart} renamed to \cs{Ifstrstart}}
+% Helper macro, that tests a macro recursive to expand to a \cs{char}.
+% \begin{macrocode}
+\newcommand*{\scr@ifisdefchar}[1]{%
+ \begingroup
+ \Ifstrstart{\meaning #1}{\detokenize{macro:}}{%
+ \aftergroup\expandafter\aftergroup\scr@ifisdefchar
+ }{%
+ \Ifstrstart{\meaning #1}{\string\char\string"}{%
+ \aftergroup\scr@TestCountAssignTillNil
+ }{%
+ \aftergroup\scr@secondoftwoAfterNil
+ }%
+ }%
+ \endgroup
+ #1%
+}
+%</base>
+% \end{macrocode}
+% \end{macro}^^A \scr@ifisdefchar
+% \end{command}^^A \ifisdefchar,\Ifisdefchar
+%
+%
+% \begin{command}{\ifiscounter,\Ifiscounter}
+% \changes{v3.12}{2013/11/05}{added}
+% \changes{v3.28}{2019/11/19}{\cs{ifiscounter} renamed to \cs{Ifiscounter}}
+% If the first argument expands to a \LaTeX{} counter, execute the second
+% argument, otherwise the third one.
+% \begin{macrocode}
+%<*base>
+\providecommand*{\ifiscounter}{%
+ \PackageWarning{scrbase}{Usage of deprecated command
+ `\string\ifiscounter'.\MessageBreak
+ The command has been renamed because of a\MessageBreak
+ recommendation of The LaTeX Project Team.\MessageBreak
+ Please replace `\string\ifiscounter' by `\string\Ifiscounter'%
+ }%
+ \Ifiscounter
+}
+\newcommand*{\Ifiscounter}[1]{%
+ \begingroup
+ \scr@ifundefinedorrelax{c@#1}{%
+ \aftergroup\@secondoftwo
+ }{%
+ \aftergroup\@firstoftwo
+ }%
+ \endgroup
+}
+%</base>
+% \end{macrocode}
+% \end{command}^^A \ifiscounter,\Ifiscounter
+%
+%
+% \begin{command}{\ifisinteger,\Ifisinteger}
+% \changes{v3.12}{2013/11/05}{added}
+% \changes{v3.12a}{2014/01/24}{white space removed}
+% \changes{v3.20}{2015/10/19}{re-implemented}
+% \changes{v3.28}{2019/11/19}{\cs{ifisinteger} renamed to \cs{Ifisinteger}}
+% If the first argument expands to a (positive or negative) integer, execute
+% the second argument, otherwise the third one.
+% \begin{macrocode}
+%<*base>
+\providecommand*{\ifisinteger}{%
+ \PackageWarning{scrbase}{Usage of deprecated command
+ `\string\ifisinteger'.\MessageBreak
+ The command has been renamed because of a\MessageBreak
+ recommendation of The LaTeX Project Team.\MessageBreak
+ Please replace `\string\ifisinteger' by `\string\Ifisinteger'%
+ }%
+ \Ifisinteger
+}
+\newcommand*{\Ifisinteger}[1]{%
+ \IfArgIsEmpty{#1}{\@secondoftwo}{\scr@ifisinteger#1\@nil}%
+}
+% \end{macrocode}
+% \begin{macro}{\scr@ifisinteger}
+% \changes{v3.20}{2015/10/19}{added}
+% \changes{v3.28}{2019/11/18}{\cs{ifstrstart} renamed to \cs{Ifstrstart}}
+% Helper macro to test recursive to a algebraic sign or a number without sign.
+% \begin{macrocode}
+\def\scr@ifisinteger#1{%
+ \begingroup
+ \Ifstrstart{\meaning #1}{\detokenize{macro:}}{%
+ \aftergroup\expandafter\aftergroup\scr@ifisinteger\aftergroup#1%
+ }{%
+ \Ifstrstart{\meaning #1}{\detokenize{the character}}{%
+ \if #1-\aftergroup\scr@ifisinteger
+ \else
+ \if #1+\aftergroup\scr@ifisinteger
+ \else
+ \ifnum 0=0\if #10\else\if #11\else\if #12\else\if #13\else
+ \if #14\else\if #15\else\if #16\else\if #17\else
+ \if #18\else\if #19\else 1\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi
+ \relax
+ \aftergroup\scr@TestCountAssignTillNil
+ \aftergroup#1%
+ \else
+ \aftergroup\scr@secondoftwoAfterNil
+ \aftergroup#1%
+ \fi
+ \fi
+ \fi
+ }{%
+ \Ifstrstart{\meaning #1}{\string\char\string"}{%
+ \aftergroup\scr@TestCountAssignTillNil
+ }{%
+ \def\reserved@c{%
+ \aftergroup\scr@secondoftwoAfterNil
+ }%
+ \@for\reserved@a:=\abovedisplayskip,\abovedisplayshortskip,%
+ \adjdemerits,%
+ \baselineskip,\belowdisplayskip,%
+ \belowdisplayshortskip,\binoppenalty,\boxmaxdepth,%
+ \brokenpenalty,%
+ \clubpenalty,\count,%
+ \dimen,\dimexpr,\doublehyphendemerits,\dp,%
+ \emergenystretch,\exhyphenpenalty,%
+ \finalhyphendemerits,%
+ \glueexpr,%
+ \hbadness,\hfuzz,\hsize,\ht,\hyphenpenalty,%
+ \lastskip,\lastpenalty,\linepenalty,%
+ \lineskip,\lineskiplimit,%
+ \maxdepth,\numexpr,%
+ \overfullrule,%
+ \parfillskip,\parindent,\parskip,%
+ \pdfpageheight,\pdfpagewidth,%
+ \predisplaypenalty,\pretolerance,%
+ \relpenalty,\widowpenalty,%
+ \skip,\splitmaxdepth,\splittopskip,%
+ \tolerance,\topskip,%
+ \wd,\vbadness,\vfuzz,\vsize
+ \do {%
+ \expandafter\Ifstr\expandafter{\expandafter\string\reserved@a}{%
+ \meaning #1%
+ }{%
+ \def\reserved@c{\aftergroup\scr@TestCountAssignTillNil}%
+ }%
+ }%
+ \reserved@c
+ }%
+ \aftergroup#1%
+ }%
+ }%
+ \endgroup
+}
+%</base>
+% \end{macrocode}
+% \end{macro}^^A \scr@ifisinteger
+% \end{command}^^A \ifisinteger,\Ifisinteger
+%
+%
+% \begin{macro}{\scr@ifrelax@to@nnil}
+% \changes{v3.12}{2013/11/05}{added}
+% Helper macro to be used after an assignment. If everything until the first
+% \cs{@nnil} is exactly one \cs{relax}, the second argument (first after the
+% \cs{@nnil}) will be executed, otherwise the third argument (second after the
+% \cs{@nnil}).
+% \begin{macrocode}
+%<*base>
+\newcommand*{\scr@ifrelax@to@nnil}{}
+\def\scr@ifrelax@to@nnil#1\@nnil{%
+ \begingroup
+ \def\reserved@a{#1}\def\reserved@b{\relax}%
+ \ifx\reserved@a\reserved@b
+ \aftergroup\@firstoftwo
+ \else
+ \aftergroup\@secondoftwo
+ \fi
+ \endgroup
+}
+%</base>
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{command}{\ifisdimension,\Ifisdimension}
+% \changes{v3.12}{2013/11/05}{added}
+% \changes{v3.12a}{2014/01/24}{white space removed}
+% \changes{v3.20}{2015/10/20}{re-implemented}
+% \changes{v3.28}{2019/11/19}{\cs{ifisdimension} renamed to \cs{Ifisdimension}}
+% If the step by step expansion of the first argument results in a (positive
+% or negative) length, the second argument will be executed, otherwise the
+% third one.
+% \begin{macrocode}
+%<*base>
+\providecommand*{\ifisdimension}{%
+ \PackageWarning{scrbase}{Usage of deprecated command
+ `\string\ifisdimension'.\MessageBreak
+ The command has been renamed because of a\MessageBreak
+ recommendation of The LaTeX Project Team.\MessageBreak
+ Please replace `\string\ifisdimension' by `\string\Ifisdimension'%
+ }%
+ \Ifisdimension
+}
+\newcommand*{\Ifisdimension}[1]{%
+ \IfArgIsEmpty{#1}{\@secondoftwo}{\scr@ifisdimension#1\@nil}%
+}
+% \end{macrocode}
+% \begin{macro}{\scr@ifisdimension}
+% \changes{v3.20}{2015/10/20}{added}
+% \changes{v3.28}{2019/11/18}{\cs{ifstrstart} renamed to \cs{Ifstrstart}}
+% \changes{v3.28}{2019/11/23}{arithmetic plus sign fixed}
+% To make this command absolutely correct without false positive and false
+% negative results, it would be very complicated. Instead we use a heuristic:
+% If the argument consists of a arbitrary number of arithmetic signs followed
+% by at most one dot, comma or digit or followed by something, that is a valid
+% lengths primitive, we try an assignment. Invalid assignments can result in
+% errors. This is not the best solution but makes things a lot easier.
+% \begin{macrocode}
+\newcommand*{\scr@ifisdimension}[1]{%
+ \begingroup
+ \Ifstrstart{\meaning #1}{\detokenize{macro:}}{%
+ \aftergroup\expandafter\aftergroup\scr@ifisdimension\aftergroup#1%
+ }{%
+ \Ifstrstart{\meaning #1}{\detokenize{the character}}{%
+ \if #1-\aftergroup\scr@ifisdimension
+ \else
+ \if #1+\aftergroup\scr@ifisdimension
+ \else
+ \if #1.%
+ \aftergroup\scr@TestDimensionAssignTillNil
+ \aftergroup#1%
+ \else
+ \if #1,%
+ \aftergroup\scr@TestDimensionAssignTillNil
+ \aftergroup#1%
+ \else
+ \ifnum 0=0\if #10\else\if #11\else\if #12\else\if #13\else
+ \if #14\else\if #15\else\if #16\else\if #17\else
+ \if #18\else\if #19\else 1\fi\fi
+ \fi\fi\fi\fi
+ \fi\fi\fi\fi
+ \relax
+ \aftergroup\scr@TestDimensionAssignTillNil
+ \aftergroup#1%
+ \else
+ \aftergroup\scr@secondoftwoAfterNil
+ \aftergroup#1%
+ \fi
+ \fi
+ \fi
+ \fi
+ \fi
+ }{%
+ \Ifstrstart{\meaning #1}{\string\char\string"}{%
+ \aftergroup\scr@TestDimensionAssignTillNil
+ }{%
+ \def\reserved@c{%
+ \aftergroup\scr@secondoftwoAfterNil
+ \aftergroup\@empty
+ }%
+ \@for\reserved@a:=\abovedisplayskip,\abovedisplayshortskip,%
+ \adjdemerits,%
+ \baselineskip,\belowdisplayskip,%
+ \belowdisplayshortskip,\binoppenalty,\boxmaxdepth,%
+ \brokenpenalty,%
+ \clubpenalty,\count,%
+ \dimen,\dimexpr,\doublehyphendemerits,\dp,%
+ \emergenystretch,\exhyphenpenalty,%
+ \finalhyphendemerits,%
+ \glueexpr,%
+ \hbadness,\hfuzz,\hsize,\ht,\hyphenpenalty,%
+ \lastskip,\lastpenalty,\linepenalty,%
+ \lineskip,\lineskiplimit,%
+ \maxdepth,\numexpr,%
+ \overfullrule,%
+ \parfillskip,\parindent,\parskip,%
+ \pdfpageheight,\pdfpagewidth,%
+ \predisplaypenalty,\pretolerance,%
+ \relpenalty,\widowpenalty,%
+ \skip,\splitmaxdepth,\splittopskip,%
+ \tolerance,\topskip,%
+ \wd,\vbadness,\vfuzz,\vsize
+ \do {%
+ \expandafter\Ifstr\expandafter{\expandafter\string\reserved@a}{%
+ \meaning #1%
+ }{%
+ \def\reserved@c{\aftergroup\scr@TestDimensionAssignTillNil}%
+ }%
+ }%
+ \reserved@c
+ }%
+ \aftergroup#1%
+ }%
+ }%
+ \endgroup
+}
+% \end{macrocode}
+% \begin{macro}{\scr@TestDimenionAssignTillNil}
+% \changes{v3.20}{2015/10/19}{added}
+% Argument \texttt{\#1} delimited by \cs{@nil} is assigned to a temporary
+% length. If this uses the argument completely, the argument \texttt{\#2} behind
+% \cs{@nil} will executed, otherwise argument \texttt{\#3}. In any case
+% \texttt{\#1} will removed from the input totally. The difference to
+% \cs{scr@TestDimenAssignTillNil} is the \texttt{pt} test.
+% \begin{macrocode}
+\newcommand*\scr@TestDimensionAssignTillNil{}
+\def\scr@TestDimensionAssignTillNil#1\@nil{%
+ \begingroup
+ \afterassignment\scr@AfterEndGroupIfArgIsRelaxTillptNnil
+ \@tempdima=#1pt\@nnil
+}
+% \end{macrocode}
+% \begin{macro}{\scr@IfArgIsRelaxAfterRelaxTillptNnil,\scr@IfAfterEndgroupArgIsRelaxTillptNnil}
+% \changes{v3.20}{2015/10/19}{added}
+% \changes{v3.28}{2019/11/18}{\cs{ifstr} renamed to \cs{Ifstr}}
+% \changes{v3.28}{2019/11/18}{\cs{ifstrstart} renamed to \cs{Ifstrstart}}
+% Die Hilfsmakros lesen ein durch \cs{@nnil} begrenztes Argument. Falls dieses
+% Argument nur aus einer Folge von \cs{relax} besteht, wird das erste Argument
+% nach \cs{@nnil} ausgeführt, sonst das zweite.
+% \begin{macrocode}
+\newcommand*\scr@AfterEndGroupIfArgIsRelaxTillptNnil{}
+\def\scr@AfterEndGroupIfArgIsRelaxTillptNnil#1\@nnil{%
+ \endgroup
+ \Ifstr{\detokenize{#1}}{\detokenize{pt}}{\@firstoftwo}{%
+ \Ifstrstart{\detokenize{#1}}{\detokenize{\relax}}{%
+ \scr@IfArgIsRelaxAfterRelaxTillptNnil #1\@nnil
+ }{\@secondoftwo}%
+ }%
+}
+\newcommand*\scr@IfArgIsRelaxAfterRelaxTillptNnil{}
+\def\scr@IfArgIsRelaxAfterRelaxTillptNnil \relax#1pt\@nnil{%
+ \Ifstr{\detokenize{#1}}{\detokenize{pt}}{\@firstoftwo}{%
+ \Ifstrstart{\detokenize{#1}}{\detokenize{\relax}}{%
+ \scr@IfArgIsRelaxAfterRelaxTillptNnil #1\@nnil
+ }{\@secondoftwo}%
+ }%
+}
+%</base>
+% \end{macrocode}
+% \end{macro}^^A \scr@IfArgIsRelaxAfterRelaxTillptNnil,\scr@IfAfterEndgroupArgIsRelaxTillptNnil
+% \end{macro}^^A \scr@DimensionSkipAssignTillNil
+% \end{macro}^^A \scr@ifisdimension
+% \end{command}^^A \ifisdimension,\Ifisdimension
+%
+%
+% \begin{command}{\ifisglue}
+% \changes{v3.12}{2013/11/05}{added}
+% \changes{v3.12a}{2014/01/24}{white space removed}
+% \changes{v3.20}{2015/10/21}{re-implemented}
+% \changes{v3.28}{2019/11/19}{\cs{ifisglue} renamed to \cs{Ifisglue}}
+% If the step-by-step expansion of the first argument results in a (positive
+% or negativ) length with glue, the second argument is executed, otherwise the
+% third one.
+% \begin{macrocode}
+%<*base>
+\providecommand*{\ifisglue}{%
+ \PackageWarning{scrbase}{Usage of deprecated command
+ `\string\ifisglue'.\MessageBreak
+ The command has been renamed because of a\MessageBreak
+ recommendation of The LaTeX Project Team.\MessageBreak
+ Please replace `\string\ifisglue' by `\string\Ifisglue'%
+ }%
+ \Ifisglue
+}
+\newcommand*{\Ifisglue}[1]{%
+ \IfArgIsEmpty{#1}{\@secondoftwo}{\scr@ifisglue#1\@nil}%
+}
+% \end{macrocode}
+% \begin{macro}{\scr@ifisglue}
+% \changes{v3.20}{2015/10/21}{added}
+% \changes{v3.28}{2019/11/18}{\cs{ifstrstart} renamed to \cs{Ifstrstart}}
+% \changes{v3.28}{2019/11/23}{arithmetic plus sign fixed}
+% \changes{v3.28}{2019/11/23}{in plus case \cs{ifisdimension} replaced by
+% \cs{ifisglue}}
+% To make this command absolutely correct without false positive and false
+% negative results, it would be very complicated. Instead we use a heuristic:
+% If the argument consists of a arbitrary number of arithmetic signs followed
+% by at most one dot, comma or digit or followed by something, that is a valid
+% primitive for skips, we try an assignment. Invalid assignments can result in
+% errors. This is not the best solution but makes things a lot easier.
+% \begin{macrocode}
+\newcommand*{\scr@ifisglue}[1]{%
+ \begingroup
+ \Ifstrstart{\meaning #1}{\detokenize{macro:}}{%
+ \aftergroup\expandafter\aftergroup\scr@ifisglue\aftergroup#1%
+ }{%
+ \Ifstrstart{\meaning #1}{\detokenize{the character}}{%
+ \if #1-\aftergroup\scr@ifisglue
+ \else
+ \if #1+\aftergroup\scr@ifisglue
+ \else
+ \if #1.%
+ \aftergroup\scr@TestGlueAssignTillNil
+ \aftergroup#1%
+ \else
+ \if #1,%
+ \aftergroup\scr@TestGlueAssignTillNil
+ \aftergroup#1%
+ \else
+ \ifnum 0=0\if #10\else\if #11\else\if #12\else\if #13\else
+ \if #14\else\if #15\else\if #16\else\if #17\else
+ \if #18\else\if #19\else 1\fi\fi
+ \fi\fi\fi\fi
+ \fi\fi\fi\fi
+ \relax
+ \aftergroup\scr@TestGlueAssignTillNil
+ \aftergroup#1%
+ \else
+ \aftergroup\scr@secondoftwoAfterNil
+ \aftergroup#1%
+ \fi
+ \fi
+ \fi
+ \fi
+ \fi
+ }{%
+ \Ifstrstart{\meaning #1}{\string\char\string"}{%
+ \aftergroup\scr@TestGlueAssignTillNil
+ }{%
+ \def\reserved@c{%
+ \aftergroup\scr@secondoftwoAfterNil
+ \aftergroup\@empty
+ }%
+ \@for\reserved@a:=\abovedisplayskip,\abovedisplayshortskip,%
+ \adjdemerits,%
+ \baselineskip,\belowdisplayskip,%
+ \belowdisplayshortskip,\binoppenalty,\boxmaxdepth,%
+ \brokenpenalty,%
+ \clubpenalty,\count,%
+ \dimen,\dimexpr,\doublehyphendemerits,\dp,%
+ \emergenystretch,\exhyphenpenalty,%
+ \finalhyphendemerits,%
+ \glueexpr,%
+ \hbadness,\hfuzz,\hsize,\ht,\hyphenpenalty,%
+ \lastskip,\lastpenalty,\linepenalty,%
+ \lineskip,\lineskiplimit,%
+ \maxdepth,\numexpr,%
+ \overfullrule,%
+ \parfillskip,\parindent,\parskip,%
+ \pdfpageheight,\pdfpagewidth,%
+ \predisplaypenalty,\pretolerance,%
+ \relpenalty,\widowpenalty,%
+ \skip,\splitmaxdepth,\splittopskip,%
+ \tolerance,\topskip,%
+ \wd,\vbadness,\vfuzz,\vsize
+ \do {%
+ \expandafter\Ifstr\expandafter{\expandafter\string\reserved@a}{%
+ \meaning #1%
+ }{%
+ \def\reserved@c{\aftergroup\scr@TestGlueAssignTillNil}%
+ }%
+ }%
+ \reserved@c
+ }%
+ \aftergroup#1%
+ }%
+ }%
+ \endgroup
+}
+% \end{macrocode}
+% \begin{macro}{\scr@TestGlueAssignTillNil}
+% \changes{v3.20}{2015/10/21}{added}
+% Argument \texttt{\#1} delimited by \cs{@nil} is assigned to a temporary
+% \cs{skip}. If this uses the argument completely, the argument \texttt{\#2} behind
+% \cs{@nil} will executed, otherwise argument \texttt{\#3}. In any case
+% \texttt{\#1} will removed from the input totally. The difference to
+% \cs{scr@TestSkipAssignTillNil} is the \texttt{pt} test.
+% \begin{macrocode}
+\newcommand*\scr@TestGlueAssignTillNil{}
+\def\scr@TestGlueAssignTillNil#1\@nil{%
+ \begingroup
+ \afterassignment\scr@AfterEndGroupIfArgIsRelaxTillptNnil
+ \@tempskipa=#1pt\@nnil
+}
+%</base>
+% \end{macrocode}
+% \end{macro}^^A \scr@TestGlueAssignTillNil
+% \end{macro}^^A \scr@ifisglue
+% \end{command}^^A \ifisglue,\Ifisglue
+%
+%
+% \begin{command}{\ifnumber,\Ifnumber}
+% \changes{v3.12}{2013/10/30}{using \cs{aftergroup} instead of
+% \cs{endgroup}\cs{expandafter}}
+% \changes{v3.12a}{2014/01/24}{white space removed}
+% \changes{v3.27}{2019/08/26}{empty arguments fixed}
+% \changes{v3.28}{2019/11/18}{\cs{ifnumber} renamed to \cs{Ifnumber}}
+% If the first argument is a positive integer, the second argument is
+% executed, otherwise the third.
+% \begin{macrocode}
+%<*base>
+\providecommand*{\ifnumber}{%
+% \end{macrocode}
+% Note: We must not output the warning if package \pkg{babelbib} has been
+% loaded, because the package defines the same command but only, if it has not
+% been defined already. Unfortunately and against all conventions, it even
+% defines internal macros of \pkg*{scrbase} with prefix \cs{scr@}. This is
+% very dangerous and would result in errors, if \pkg{babelbib} is loaded
+% before \pkg*{scrbase}. Maybe I will remove this special treatment of
+% \pkg{babelbib} after switching over to \pkg{biblatex} for the \KOMAScript{}
+% manuals.
+% \begin{macrocode}
+ \scr@ifundefinedorrelax{ver@babelbib.sty}{%
+ \PackageWarning{scrbase}{Usage of deprecated command
+ `\string\ifnumber'.\MessageBreak
+ The command has been renamed because of a\MessageBreak
+ recommendation of The LaTeX Project Team.\MessageBreak
+ Please replace `\string\ifnumber' by `\string\Ifnumber'%
+ }%
+ }{}%
+ \Ifnumber
+}
+\newcommand\Ifnumber[1]{%
+ \begingroup\@tempswafalse\let\scr@next\scr@test@number
+ \IfArgIsEmpty{#1}{}{\expandafter\scr@next#1\scr@next}%
+ \if@tempswa
+ \aftergroup\@firstoftwo
+ \else
+ \aftergroup\@secondoftwo
+ \fi
+ \endgroup
+}
+% \end{macrocode}
+% \begin{macro}{\test@number,\scr@test@number}
+% \changes{v3.36}{2022/02/17}{\cs{test@number} renamed to \cs{scr@test@number}}
+% For the real test scan the first argument token by token.
+% \begin{macrocode}
+\newcommand*{\scr@test@number}[1]{%
+ \ifx \scr@next#1%
+ \let\scr@next\relax
+ \else
+ \@tempcnta=\expandafter\expandafter\expandafter\number
+ \expandafter`#1\relax
+ \ifnum \@tempcnta>47
+ \ifnum \@tempcnta<58
+ \@tempswatrue
+ \else\@tempswafalse\fi
+ \else\@tempswafalse\fi
+% \end{macrocode}
+% Remove the rest, if a non-digit has been found.
+% \begin{macrocode}
+ \if@tempswa\else\let\scr@next\gobble@till@scr@next\fi
+ \fi
+ \scr@next
+}
+% \end{macrocode}
+% \begin{macro}{\gobble@tillscr@@next}
+% Use a delimited \emph{empty} macro.
+% \begin{macrocode}
+\newcommand*{\gobble@till@scr@next}{}
+\def\gobble@till@scr@next#1\scr@next{}
+%</base>
+% \end{macrocode}
+% \end{macro}^^A \gobble@tillscr@next
+% \end{macro}^^A \test@number, \scr@test@number
+% \end{command}^^A \ifnumber,\Ifnumber
+%
+% \begin{command}{\ifintnumber,\Ifintnumber}
+% \changes{v3.12}{2013/10/30}{added}
+% \changes{v3.28}{2019/11/18}{\cs{ifintnumber} renamed to
+% \cs{Ifintnumber}}
+% If the first argument is a positive or negative integer, execute the second
+% argument, otherwise the third one. There are multiple arithmetic signs allowed.
+% \begin{macrocode}
+%<*base>
+\providecommand*{\ifintnumber}{%
+ \PackageWarning{scrbase}{Usage of deprecated command
+ `\string\ifintnumber'.\MessageBreak
+ The command has been renamed because of a\MessageBreak
+ recommendation of The LaTeX Project Team.\MessageBreak
+ Please replace `\string\ifintnumber' by `\string\Ifintnumber'%
+ }%
+ \Ifintnumber
+}
+\newcommand\Ifintnumber[1]{%
+ \begingroup\@tempswafalse\let\scr@next\scr@test@sign
+ \expandafter\scr@next#1\scr@next
+ \if@tempswa
+ \aftergroup\@firstoftwo
+ \else
+ \aftergroup\@secondoftwo
+ \fi
+ \endgroup
+}
+% \end{macrocode}
+% \begin{macro}{\scr@test@sign}
+% \changes{v3.12}{2013/10/30}{added}
+% \begin{macrocode}
+\newcommand*{\scr@test@sign}[1]{%
+ \ifx \scr@next#1
+ \let\scr@next\relax
+ \else
+ \if #1-%
+ \else
+ \ifx #1+%
+ \else
+ \def\scr@next{\let\scr@next\scr@test@number\scr@next #1}%
+ \fi
+ \fi
+ \fi
+ \scr@next
+}
+%</base>
+% \end{macrocode}
+% \end{macro}^^A \scr@test@sign
+% \end{command}^^A \ifintnumber,\Ifintnumber
+%
+% \begin{command}{\ifdimen,\Ifdimen}
+% \changes{v3.28}{2019/11/18}{renamed to \cs{Ifdimen}}
+% If the first argument is a dimension number, the second argument will be
+% executed, otherwise the third.
+% \begin{macrocode}
+%<*base>
+\providecommand*{\ifdimen}{%
+ \PackageWarning{scrbase}{Usage of deprecated command
+ `\string\ifdimen'.\MessageBreak
+ The command has been renamed because of a\MessageBreak
+ recommendation of The LaTeX Project Team.\MessageBreak
+ Please replace `\string\ifdimen' by `\string\Ifdimen'%
+ }%
+ \Ifdimen
+}
+\newcommand{\Ifdimen}[1]{%
+ \begingroup\@tempswatrue\let\scr@next\scr@test@posdimen
+ \expandafter\scr@test@dimen#1\scr@next
+ \if@tempswa
+ \endgroup\expandafter\@firstoftwo
+ \else
+ \endgroup\expandafter\@secondoftwo
+ \fi
+}
+% \end{macrocode}
+% \begin{macro}{\test@dimen,\scr@test@dimen}
+% \changes{v3.36}{2022/02/17}{\cs{test@dimen} renamed to \cs{scr@test@dimen}}
+% We have to remove the arithmetic signs.
+% \begin{macrocode}
+\newcommand*{\scr@test@dimen}[1]{%
+ \ifx -#1\else\ifx +#1\else
+ \def\scr@next{\let\scr@next\scr@test@posdimen\scr@next#1}\fi\fi
+ \scr@next
+}
+% \end{macrocode}
+% \begin{macro}{\test@posdimen,\scr@test@posdimen}
+% \changes{v3.36}{2022/02/17}{\cs{test@posdimen} renamed to \cs{scr@test@posdimen}}
+% Is the rest a dimension. Despite this is not correct, we allow more than one
+% decimal point or decimal comma. Should this be changed?
+% \begin{macrocode}
+\newcommand*{\scr@test@posdimen}[1]{%
+ \ifx \scr@next#1%
+ \@tempswafalse\let\scr@next\relax
+ \else
+ \if .#1\else\if ,#1\else
+ \@tempcnta=%
+ \expandafter\expandafter\expandafter\number\expandafter`#1\relax
+ \ifnum \@tempcnta>47
+ \ifnum \@tempcnta<58
+ \else\def\scr@next{\scr@test@dimunt#1}\fi
+ \else\def\scr@next{\scr@test@dimunt#1}\fi
+ \fi\fi
+ \fi
+ \scr@next
+}
+% \end{macrocode}
+% \begin{macro}{\test@dimunt,\test@trueunt,\scr@test@dimunt,\scr@test@trueunt}
+% Last but not least the unit has to be tested. We have standard units and
+% true units. So we first cut of a ``\texttt{true}''.
+% \begin{macrocode}
+\newcommand*{\scr@test@dimunt}{}
+\def\scr@test@dimunt#1\scr@next{%
+ \expandafter\scr@test@trueunt#1truetrue\scr@test@trueunt
+}
+\newcommand*{\scr@test@trueunt}{}
+\def\scr@test@trueunt#1true#2true#3\scr@test@trueunt{%
+ \edef\reserved@a{#1}%
+ \ifx\reserved@a\@empty\scr@test@@dimunt{#2}\else\scr@test@@dimunt{#1}\fi
+}
+% \end{macrocode}
+% \begin{macro}{\test@@ifdimunt,\scr@test@@dimunt}
+% \changes{v3.28}{2019/11/18}{\cs{ifstr} renamed to \cs{Ifstr}}
+% Currently we know eleven or twelve units. Unit \texttt{px} is only valid
+% with PDF output.
+% \begin{macrocode}
+\newcommand*\scr@test@@dimunt[1]{%
+ \@tempswafalse
+ \Ifstr{#1}{pt}{\@tempswatrue}{%
+ \Ifstr{#1}{pc}{\@tempswatrue}{%
+ \Ifstr{#1}{in}{\@tempswatrue}{%
+ \Ifstr{#1}{bp}{\@tempswatrue}{%
+ \Ifstr{#1}{cm}{\@tempswatrue}{%
+ \Ifstr{#1}{mm}{\@tempswatrue}{%
+ \Ifstr{#1}{dd}{\@tempswatrue}{%
+ \Ifstr{#1}{cc}{\@tempswatrue}{%
+ \Ifstr{#1}{sp}{\@tempswatrue}{%
+ \Ifstr{#1}{ex}{\@tempswatrue}{%
+ \Ifstr{#1}{em}{\@tempswatrue}{%
+ \scr@ifpdfoutput{%
+ \Ifstr{#1}{px}{\@tempswatrue}{}%
+ }{}%
+ }%
+ }%
+ }%
+ }%
+ }%
+ }%
+ }%
+ }%
+ }%
+ }%
+ }%
+}
+%</base>
+% \end{macrocode}
+% \end{macro}^^A \test@@ifdimunt,\scr@test@@dimunt
+% \end{macro}^^A \test@dimunt,\test@trueunt,\scr@test@dimunt,\scr@test@trueunt
+% \end{macro}^^A \scr@test@posdimen
+% \end{macro}^^A \scr@test@dimen
+% \end{command}^^A \ifdimen,\Ifdimen
+%
+%
+% \begin{command}{\ifpdftex}
+% \changes{v2.95}{2002/08/19}{added}
+% \changes{v3.28}{2019/11/18}{removed}
+% \end{command}
+% \begin{macro}{\scr@ifpdftex}
+% \changes{v2.95}{2002/08/19}{added}
+% \changes{v3.30}{2020/03/06}{\cs{ifnotundefined} replaced by \cs{Ifnotundefined}}
+% If \pdfTeX{} is used, execute the first argument, otherwise the
+% second. Note, we do not read the arguments but delegate them to
+% \cs{Ifnotundefined}.
+% \begin{macrocode}
+%<*base>
+\newcommand{\scr@ifpdftex}{\Ifnotundefined{pdftexversion}}
+%</base>
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\scr@ifluatex}
+% \changes{v3.21}{2016/05/27}{added}
+% \changes{v3.30}{2020/03/06}{\cs{ifnotundefined} replaced by \cs{Ifnotundefined}}
+% If \LuaTeX{} is used, execute the first argument, otherwise the
+% second. Note, we do not read the arguments but delegate them to
+% \cs{Ifnotundefined}.
+% \begin{macrocode}
+%<*base>
+\newcommand{\scr@ifluatex}{\Ifnotundefined{luatexversion}}
+%</base>
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\scr@ifpdforluatex}
+% \changes{v3.21}{2016/05/27}{added}
+% If either \LuaTeX{} or \pdfTeX{} is used, execute the first argument,
+% otherwise the second. Note, we do not read the arguments but delegate them
+% to \cs{@firstoftwo} and \cs{@secondoftwo}.
+% \begin{macrocode}
+%<*base>
+\newcommand*{\scr@ifpdforluatex}{%
+ \scr@ifpdftex{\@firstoftwo}{\scr@ifluatex{\@firstoftwo}{\@secondoftwo}}%
+}
+%</base>
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{command}{\ifvtex,\ifVTeX}
+% \changes{v2.95}{2002/08/19}{added}
+% \changes{v2.97c}{2007/06/20}{\cs{ifvtex} renamed to \cs{ifVTeX}}
+% \changes{v3.28}{2019/11/18}{removed}
+% \end{command}
+% \begin{macro}{\scr@ifvtex,\scr@ifVTeX}
+% \changes{v2.95}{2002/08/19}{added}
+% \changes{v2.97c}{2007/06/20}{\cs{scr@ifvtex} renamed to \cs{scr@ifVTeX}}
+% \changes{v3.30}{2020/03/06}{\cs{ifnotundefined} replaced by \cs{Ifnotundefined}}
+% If \VTeX{} is used, execute the first argument, otherwise the
+% second. Note, we do not read the arguments but delegate them to
+% \cs{Ifnotundefined}.
+% \begin{macrocode}
+%<*base>
+\newcommand{\scr@ifVTeX}{\Ifnotundefined{VTeXversion}}
+%</base>
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{command}{\ifpdfoutput,\Ifpdfoutput}
+% \changes{v2.7g}{2001/04/17}{added}
+% \changes{v2.8q}{2001/10/19}{\cs{pdfoutput} does not become \cs{relax} if it
+% was undefined before}
+% \changes{v2.8q}{2001/10/19}{\cs{ifpdfoutput} is only defined if new}
+% \changes{v2.8q}{2001/10/19}{usage of \cs{scr@ifpdfoutput}}
+% \changes{v3.28}{2019/11/18}{\cs{ifpdfoutput} renamed to \cs{Ifpdfoutput}}
+% \begin{macro}{\scr@ifpdfoutput}
+% \changes{v2.8q}{2001/10/19}{added}
+% \changes{v2.8q}{2001/11/13}{full functional}
+% \changes{v2.95}{2002/08/21}{knowing \VTeX}
+% \changes{v2.95}{2004/07/20}{expandable}
+% \changes{v3.21}{2016/05/27}{works for \LuaTeX{} after version 0.85}
+% If the output (currently) produces a PDF, the first argument is executed,
+% otherwise the second one. This macro is used inside the implementation of
+% option \opt{pagesize}, so we cannot remove it or declare it as deprecated.
+% \begin{macrocode}
+%<*base>
+\newcommand{\scr@ifpdfoutput}{%
+ \scr@ifundefinedorrelax{pdfoutput}{%
+ \scr@ifundefinedorrelax{outputmode}{%
+ \scr@ifundefinedorrelax{OpMode}{%
+ \expandafter\@secondoftwo%
+ }{%
+ \ifnum\OpMode=1
+ \expandafter\@firstoftwo
+ \else
+ \expandafter\@secondoftwo
+ \fi
+ }%
+ }{%
+ \ifnum\outputmode>0
+ \expandafter\@firstoftwo
+ \else
+ \expandafter\@secondoftwo
+ \fi
+ }%
+ }{%
+ \ifnum\pdfoutput>0
+ \expandafter\@firstoftwo
+ \else
+ \expandafter\@secondoftwo
+ \fi
+ }%
+}%
+\providecommand*{\ifpdfoutput}{%
+ \PackageWarning{scrbase}{Usage of deprecated command
+ `\string\ifpdfoutput'.\MessageBreak
+ The command has been renamed because of a\MessageBreak
+ recommendation of The LaTeX Project Team.\MessageBreak
+ Please replace `\string\ifpdfoutput' by `\string\Ifpdfoutput'%
+ }%
+ \Ifpdfoutput
+}
+\newcommand*{\Ifpdfoutput}{\scr@ifpdfoutput}
+%</base>
+% \end{macrocode}
+% \end{macro}
+% \end{command}
+%
+% \begin{command}{\ifpsoutput,\Ifpsoutput}
+% \changes{v2.95}{2002/08/21}{added}
+% \changes{v3.28}{2019/11/18}{renamed to \cs{Ifpsoutput}}
+% \begin{macro}{\scr@ifpsoutput}
+% \changes{v2.95}{2002/08/21}{added}
+% \changes{v2.95}{2004/07/20}{expandable}
+% \changes{v3.30}{2020/03/06}{\cs{ifnotundefined} replaced by \cs{Ifnotundefined}}
+% If the output is (currently) expected to be PS some time, the first argument
+% is executed, otherwise the second one. This macro is used inside the
+% implementation of option \opt{pagesize}, so we cannot remove it or declare
+% it as deprecated.
+% \begin{macrocode}
+%<*base>
+\newcommand*{\scr@ifpsoutput}{%
+ \Ifnotundefined{if@dvips}{%
+ \if@dvips
+ \expandafter\@firstoftwo
+ \else
+ \expandafter\@secondoftwo
+ \fi
+ }{%
+ \Ifnotundefined{OpMode}{%
+ \ifnum\OpMode=2
+ \expandafter\@firstoftwo
+ \else
+ \expandafter\@secondoftwo
+ \fi
+ }{%
+ \expandafter\@secondoftwo
+ }%
+ }%
+}
+\providecommand*{\ifpsoutput}{%
+ \PackageWarning{scrbase}{Usage of deprecated command
+ `\string\ifpsoutput'.\MessageBreak
+ The command has been renamed because of a\MessageBreak
+ recommendation of The LaTeX Project Team.\MessageBreak
+ Please replace `\string\ifpsoutput' by `\string\Ifpsoutput'%
+ }%
+ \Ifpsoutput
+}
+\newcommand*{\Ifpsoutput}{\scr@ifpsoutput}
+%</base>
+% \end{macrocode}
+% \end{macro}
+% \end{command}
+%
+% \begin{command}{\ifdvioutput,\Ifdvioutput}
+% \changes{v2.95}{2002/08/21}{added}
+% \changes{v3.28}{2019/11/18}{\cs{ifdvioutput} renamed to \cs{Ifdvioutput}}
+% \begin{macro}{\scr@ifdvioutput}
+% \changes{v2.95}{2002/08/21}{added}
+% \changes{v2.95}{2004/07/20}{expandable}
+% \changes{v3.23}{2017/02/14}{works for \LuaTeX{} after version 0.85}
+% If the output (currently) produces a DVI, the first argument is executed,
+% otherwise the second one. This macro is used inside the implementation of
+% option \opt{pagesize}, so we cannot remove it or declare it as deprecated.
+% \begin{macrocode}
+%<*base>
+\newcommand*{\scr@ifdvioutput}{%
+ \scr@ifundefinedorrelax{pdfoutput}{%
+ \scr@ifundefinedorrelax{outputmode}{%
+ \scr@ifundefinedorrelax{OpMode}{%
+ \expandafter\@firstoftwo
+ }{%
+ \ifnum\OpMode=0
+ \expandafter\@firstoftwo
+ \else
+ \expandafter\@secondoftwo
+ \fi
+ }%
+ }{%
+ \ifnum\outputmode>0
+ \expandafter\@secondoftwo
+ \else
+ \expandafter\@firstoftwo
+ \fi
+ }%
+ }{%
+ \ifnum\pdfoutput=0
+ \expandafter\@firstoftwo
+ \else
+ \expandafter\@secondoftwo
+ \fi
+ }%
+}
+\providecommand*{\ifdvioutput}{%
+ \PackageWarning{scrbase}{Usage of deprecated command
+ `\string\ifdvioutput'.\MessageBreak
+ The command has been renamed because of a\MessageBreak
+ recommendation of The LaTeX Project Team.\MessageBreak
+ Please replace `\string\ifdvioutput' by `\string\Ifdvioutput'%
+ }%
+ \Ifdvioutput
+}
+\newcommand*{\Ifdvioutput}{\scr@ifdvioutput}
+%</base>
+% \end{macrocode}
+% \end{macro}
+% \end{command}
+%
+% \begin{macro}{\scr@smashdp}
+% \changes{v2.97c}{2007/09/17}{added}
+% \changes{v3.02a}{2009/01/23}{using own definition instead of \cs{smash}}
+% \changes{v3.36}{2022/02/18}{as robust as \cs{smash}}
+% Generate a box and output it with height and width but no depth. Note: Using
+% internal macros \cs{finsm@sh}, \cs{mathsm@sh} and \cs{makesm@ash} from the
+% \LaTeX{} kernel is a very ugly hack and dangerous. Using \cs{smash} itself
+% would be problematic, because \pkg{amsmath} redefines it and the new
+% definition is not fully compatible. But maybe a better definition could be
+% found depending on, whether \pkg{amsmath} has been loaded or not.
+% \begin{macrocode}
+%<*base>
+\DeclareRobustCommand{\scr@smashdp}[1]{%
+ \relax
+ \begingroup
+ \def\finsm@sh{\dp\z@\z@ \leavevmode\box\z@}%
+ \ifmmode
+ \expandafter\mathpalette\expandafter\mathsm@sh
+ \else
+ \expandafter\makesm@sh
+ \fi
+ {#1}%
+ \endgroup
+}
+%</base>
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{command}{\IfRTL}
+% \changes{v3.24}{2017/05/04}{added}
+% \changes{v3.36}{2022/02/18}{white space removed}
+% If we are in the right-to-left mode of a package like \pkg{bidi} the first
+% argument will be used otherwise the second one.
+% \begin{macrocode}
+%<*base>
+\newcommand*{\IfRTL}{%
+ \scr@ifundefinedorrelax{if@RTL}{\@secondoftwo}{%
+ \expandafter\ifx\csname if@RTL\expandafter\endcsname
+ \csname iftrue\endcsname
+ \expandafter\@firstoftwo
+ \else
+ \expandafter\@secondoftwo
+ \fi
+ }%
+}
+%</base>
+% \end{macrocode}
+% \end{command}^^A \IfRTL
+% \begin{command}{\IfLTR}
+% \changes{v3.24}{2017/05/04}{added}
+% \changes{v3.36}{2022/02/18}{white space removed}
+% If we are not in the right-to-left mode of a package like \pkg{bidi} any
+% kind of left-to-right mode is assumed and the first argument is used,
+% otherwise the second one.
+% \begin{macrocode}
+%<*base>
+\newcommand*{\IfLTR}{%
+ \scr@ifundefinedorrelax{if@RTL}{\@firstoftwo}{%
+ \expandafter\ifx\csname if@RTL\expandafter\endcsname
+ \csname iftrue\endcsname
+ \expandafter\@secondoftwo
+ \else
+ \expandafter\@firstoftwo
+ \fi
+ }%
+}
+%</base>
+% \end{macrocode}
+% \end{command}^^A \IfLTR
+%
+% \begin{command}{\PackageInfoNoLine}
+% \changes{v2.97d}{2007/10/03}{added}
+% Like \cs{PackageInfo} but without output of line number at the end.
+% \begin{macrocode}
+%<*base>
+\providecommand*{\PackageInfoNoLine}[2]{%
+ \PackageInfo{#1}{#2\@gobble}%
+}
+%</base>
+% \end{macrocode}
+% \end{command}
+%
+% \begin{command}{\ClassInfoNoLine}
+% \changes{v2.98c}{2008/02/15}{added}
+% Like \cs{ClassInfo} but without output of line number at the end.
+% \begin{macrocode}
+%<*base>
+\providecommand*{\ClassInfoNoLine}[2]{%
+ \ClassInfo{#1}{#2\@gobble}%
+}
+%</base>
+% \end{macrocode}
+% \end{command}
+%
+% \begin{macro}{\@removefromreset}
+% \changes{v3.15}{2014/11/21}{added}%
+% For \LaTeX{} releases before 2018/04/01 and without using a package like
+% \pkg{remreset} or \pkg{chngcntr} we still need \cs{@removefromreset}.
+% \begin{macrocode}
+%<*base>
+\providecommand*\@removefromreset[2]{%
+ {%
+ \expandafter\let\csname c@#1\endcsname\@removefromreset
+ \def\@elt##1{%
+ \expandafter\ifx\csname c@##1\endcsname\@removefromreset
+ \else\noexpand\@elt{##1}\fi
+ }%
+ \expandafter\xdef\csname cl@#2\endcsname{\csname cl@#2\endcsname}%
+ }%
+}
+%</base>
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{command}{\IfActiveMkBoth}
+% \changes{v3.26}{2018/09/03}{added}
+% \begin{macro}{\if@scrActiveMkBoth}
+% \changes{v3.26}{2018/09/03}{added}
+% \changes{v3.27}{2019/07/26}{handling for \cs{marks}}
+% This command test, whether or not \cs{@mkboth} does change a mark or not.
+% \begin{macrocode}
+%<*base>
+\newif\ifscr@ActiveMkBoth
+\def\scr@ActiveMkBothfalse{\global\let\ifscr@ActiveMkBoth\iffalse}
+\def\scr@ActiveMkBothtrue {\global\let\ifscr@ActiveMkBoth\iftrue}
+\newcommand*{\IfActiveMkBoth}{%
+ \begingroup
+ \def\markboth##1##2{\scr@ActiveMkBothtrue}%
+ \def\markright##1{\scr@ActiveMkBothtrue}%
+ \def\markleft##1{\scr@ActiveMkBothtrue}%
+ \def\markboth##1{\scr@ActiveMkBothtrue}%
+ \def\markdouble##1{\scr@ActiveMkBothtrue}%
+ \def\mark##1{\scr@ActiveMkBothtrue}%
+ \def\marks##1##2{\scr@ActiveMkBothtrue}%
+ \scr@ActiveMkBothfalse
+ \setbox\@tempboxa\vbox{\@mkboth{}{}}%
+ \endgroup
+ \ifscr@ActiveMkBoth
+ \expandafter\@firstoftwo
+ \else
+ \expandafter\@secondoftwo
+ \fi
+}
+%</base>
+% \end{macrocode}
+% \end{macro}^^A \if@scrActiveMkBoth
+% \end{command}^^A \IfActiveMkBoth
+%
+%
+% \subsection{Definition of the \KOMAScript{} \pkg*{keyval} main handling}
+%
+% \begin{command}{\FamilyExecuteOptions}
+% \changes{v3.00}{2008/04/30}{added}
+% \changes{v3.04b}{2010/01/29}{\cs{edef} replaced by \cs{protected@edef}}
+% \changes{v3.04b}{2010/02/02}{prevent overwriting of \cs{scr@key@atlist} and
+% \cs{scr@key@name} in \cs{setkeys}}
+% \changes{v3.12}{2013/03/04}{re-implemented}
+% \changes{v3.12}{2013/03/04}{can be used after document preamble}
+% \changes{v3.14}{2014/10/17}{third argument is \cs{long}}
+% \begin{macro}{\@FamilyExecuteOptions}
+% \changes{v3.14}{2014/10/17}{new}
+% \changes{v3.23}{2017/02/16}{fix: hook after uses family instead of member}
+% \changes{v3.27}{2019/10/02}{improved error message}
+% \changes{v3.28}{2019/11/18}{\cs{ifstr} renamed to \cs{Ifstr}}
+% Similar to \cs{ExecuteOptions} but with \pkg{keyval} options. The command
+% also is re-entrant. Note: The hooks are local to every usage.
+% \begin{macrocode}
+%<*base>
+\newcommand*{\FamilyExecuteOptions}[2][.\@currname.\@currext]{%
+ \@FamilyExecuteOptions[{#1}]{#2}%
+}
+\newcommand{\@FamilyExecuteOptions}[3][.\@currname.\@currext]{%
+ \scr@ifundefinedorrelax{scr@after@options@#2@hook}{%
+ \@namedef{scr@after@options@#2@hook}{%
+ \@namedef{scr@after@options@#2@hook}{}%
+ }%
+ }{%
+ \expandafter\edef\csname scr@after@options@#2@hook\endcsname{%
+ \noexpand\@namedef{scr@after@options@#2@hook}{%
+ \unexpanded\expandafter\expandafter\expandafter
+ {\csname scr@after@options@#2@hook\endcsname}%
+ }%
+ }%
+ }%
+ \@for\scr@key@atlist:=#3\do{%
+ \expandafter\scr@key@split@name@value\scr@key@atlist==\@nil
+ \ifx\scr@key@name\@empty\else
+ \ifx\scr@key@name\space\else
+ \scr@ifundefinedorrelax{KV@#2@\scr@key@name}{%
+ \scr@ifundefinedorrelax{KV@#2#1@\scr@key@name}{%
+% \end{macrocode}
+% \changes{v3.20}{2015/11/18}{special treatment of \opt{@else@} option}
+% Neither family nor member option found. But maybe special option
+% \opt{@else@} exists. In this case the current option is set as value of
+% \opt{@else@}.
+% \begin{macrocode}
+ \scr@ifundefinedorrelax{KV@#2#1@@else@}{%
+ \PackageError{scrbase}{%
+ unknown option
+ `\expandafter\detokenize\expandafter{\scr@key@atlist}'%
+ }{%
+ Member `#1' of family `#2'\MessageBreak
+ cannot handle option `\scr@key@name'.\MessageBreak
+ So it cannot be set%
+ \ifx\scr@key@value\@empty\else
+ \space to value
+ `\expandafter\detokenize\expandafter{\scr@key@value}'%
+ \fi.%
+ }%
+ }{%
+ \scr@execute@elseoption{#2#1}%
+% \end{macrocode}
+% In difference to other options, for \opt{@else@} all states different from
+% \cs{FamilyKeyStateProcessed} have to be reported as error of the
+% current/original option.
+% \begin{macrocode}
+ \ifx\FamilyKeyState\FamilyKeyStateProcessed\else
+ \PackageError{scrbase}{%
+ unknown option
+ \ifx\FamilyKeyState\FamilyKeyStateUnknownValue
+ value at
+ \fi
+ `\expandafter\detokenize\expandafter{\scr@key@atlist}'%
+ }{%
+ Member `#1' of family `#2'\MessageBreak
+ cannot handle option `\scr@key@name'.\MessageBreak
+ So it cannot be set%
+ \ifx\scr@key@value\@empty\else
+ \space to value
+ `\expandafter\detokenize\expandafter{\scr@key@value}'%
+ \fi.%
+ }%
+ \fi
+ }%
+ }{%
+ \scr@execute@option{#2#1}%
+ }%
+ }{%
+ \scr@execute@option{#2}%
+ \Ifstr{#1}{}{}{%
+% \end{macrocode}
+% \changes{v3.20}{2015/11/18}{member option test after execution of family
+% option fixed}
+% If a family option has been found and executed an existing member option
+% still has to be executed. If no member option exists, also an existing
+% \opt{@else@} option of the member has to been used. But in this case, the
+% states different from \cs{FamilyKeyStateProcessed} are not errors.
+% \begin{macrocode}
+ \scr@ifundefinedorrelax{KV@#2#1@\scr@key@name}{%
+ \scr@ifundefinedorrelax{KV@#2#1@@else@}{}{%
+ \scr@execute@elseoption{#2#1}%
+ }%
+ }{%
+ \ifx\FamilyKeyState\FamilyKeyStateProcessed
+ \scr@execute@option{#2#1}%
+ \FamilyKeyStateProcessed
+ \else
+ \scr@execute@option{#2#1}%
+ \fi
+ }%
+ }%
+ }%
+ \scr@show@key@state@error
+ \fi
+ \fi
+ }%
+ \@nameuse{scr@after@options@#2@hook}%
+}
+%</base>
+% \end{macrocode}
+% \begin{macro}{\scr@show@key@state@error}
+% \changes{v3.12}{2013/03/04}{added}
+% \changes{v3.27}{2019/10/02}{improved error message}
+% Show depending on \cs{FamilyKeyState} a error message. All information to
+% the error has to be set to \cs{FamilyMemberOfKey} (member or \cs{@empty}),
+% \cs{FamilyOfKey} (family or \cs{@empty}), \cs{scr@key@atlest} (option as it
+% was in the option list), \cs{scr@key@name} (\meta{key} of the option), and
+% \cs{scr@key@value} (\meta{value} of the option). Note: \cs{scr@key@atlist}
+% and \cs{scr@key@value} can contain macros and will be output using
+% \cs{detokenize}.
+% \begin{macrocode}
+%<*base>
+\newcommand*{\scr@show@key@state@error}{%
+ \ifx\FamilyKeyState\FamilyKeyStateProcessed\else
+ \PackageError{scrbase}{%
+ \ifx\FamilyKeyState\FamilyKeyStateNeedValue
+ missing option value at
+ \else
+ unknown option
+ \ifx\FamilyKeyState\FamilyKeyStateUnknownValue
+ value at
+ \fi
+ \fi
+ `\expandafter\detokenize\expandafter{\scr@key@atlist}'%
+ }{%
+ Option
+ `\expandafter\detokenize\expandafter{\scr@key@name}'\MessageBreak
+ \ifx\FamilyMemberOfKey\@empty\else
+ of member `\FamilyMemberOfKey'\MessageBreak
+ \fi
+ \ifx\FamilyOfKey\@empty\else
+ of family `\FamilyOfKey'\MessageBreak
+ \fi
+ \ifx\FamilyKeyState\FamilyKeyStateNeedValue
+ expects a value, but has been used without any value.%
+ \else
+ cannot handle value\MessageBreak
+ `\expandafter\detokenize\expandafter{\scr@key@value}',%
+ \MessageBreak
+ \ifx\FamilyKeyState\FamilyKeyStateUnknownValue
+ because this is an unsupported value.%
+ \else
+ because \FamilyKeyState.
+ \fi
+ \fi
+ }%
+ \fi
+}
+%</base>
+% \end{macrocode}
+% \end{macro}^^A \scr@show@key@state@error
+% \end{macro}^^A \@FamilyExecuteOptions
+% \end{command}^^A \FamilyExecuteOptions
+%
+% \begin{command}{\KOMAExecuteOptions}
+% \changes{v2.97c}{2007/04/19}{added}
+% \changes{v3.00}{2008/04/30}{no optional argument}
+% \changes{v3.12}{2013/03/04}{can be used after the document preamble}
+% Executes a \meta{list of options} (\texttt{\#3}) of a \meta{member} (optional
+% \texttt{\#1}) of a \meta{family} (\texttt{\#2}). The default for the
+% \meta{member} is \file{.\cs{@currname}.\cs{@currext}}. Note: If
+% \cs{KOMAExcuteOptions} is not used while loading a class or package, the
+% optional first argument is not optional, but has to be set correctly! And
+% because filenames can be changed, it is recommended to \emph{always} use the
+% optional argument to set a definite \meta{member}.
+% \begin{macrocode}
+%<*koma>
+\newcommand*{\KOMAExecuteOptions}[1][.\@currname.\@currext]{%
+ \FamilyExecuteOptions[#1]{KOMA}%
+}
+%</koma>
+% \end{macrocode}
+% \end{command}
+%
+% \begin{command}{\FamilyOptions}
+% \changes{v3.00}{2008/04/30}{added}
+% \changes{v3.12}{2013/03/02}{re-implemented}
+% \changes{v3.12}{2013/03/02}{\cs{scr@after@options@\#1@hook}}
+% \changes{v3.14}{2014/10/17}{second argument is \cs{long}}
+% \begin{macro}{\@FamilyOptions}
+% \changes{v3.14}[2014/10/17]{added}
+% \changes{v3.27}{2019/10/02}{improved error message}
+% \begin{macro}{\Family@Options}
+% \changes{v3.00}{2008/04/30}{added}
+% \changes{v3.12}{2013/03/04}{removed}
+% \end{macro}^^A \Family@Options
+% Used to set the options of a family. The first argument (\texttt{\#1}) is
+% the \meta{family} and the second (\texttt{\#2}) a \meta{list of options}. If
+% a \meta{key} or a \meta{value} to a \meta{key} in the \meta{list of options}
+% does not exist, an error is reported. The command itself is re-entrant, so
+% it can be used inside the definition of an option. But in this case the hook
+% is local to the local usage of the command.
+% \begin{macrocode}
+%<*base>
+\newcommand{\FamilyOptions}[1]{\@FamilyOptions{#1}}
+\newcommand{\@FamilyOptions}[2]{%
+ \scr@ifundefinedorrelax{scr@after@options@#1@hook}{%
+ \@namedef{scr@after@options@#1@hook}{%
+ \@namedef{scr@after@options@#1@hook}{}%
+ }%
+ }{%
+ \expandafter\edef\csname scr@after@options@#1@hook\endcsname{%
+ \noexpand\@namedef{scr@after@options@#1@hook}{%
+ \unexpanded\expandafter\expandafter\expandafter
+ {\csname scr@after@options@#1@hook\endcsname}%
+ }%
+ }%
+ }%
+% \end{macrocode}
+% \changes{v3.23}{2017/02/16}{\cs{AtEndOfFamilyOptions*} hook added}
+% From version 3.23 the new hook before \cs{AtEndOfFamilyOptions*} has to be
+% initialized. First step is a kind of pre-initialization: The hook is
+% defined empty, if it does not already exist. So if the hook exists empty we
+% can now recognize the top level of using \cs{FamilyOptions}.
+% \begin{macrocode}
+ \scr@ifundefinedorrelax{scr@after@options@#1@hook@topmost}{%
+ \@namedef{scr@after@options@#1@hook@topmost}{}%
+ }{}%
+% \end{macrocode}
+% Now, if we recognize the top level, because of an empty hook, the execution
+% of the hook to the normal level hook (which is the top level hook in this
+% case) is added. Additionally the self destruction code is added to the very
+% beginning of the hook. Because of the self destruction hook the hook itself
+% it no longer empty. So deeper levels distinguish from the top level. Because
+% the hook is not empty any longer.
+% \begin{macrocode}
+ \expandafter\ifx\csname scr@after@options@#1@hook@topmost\endcsname\@empty
+ \expandafter\l@addto@macro\csname scr@after@options@#1@hook\endcsname{%
+ \@nameuse{scr@after@options@#1@hook@topmost}%
+ }%
+ \@namedef{scr@after@options@#1@hook@topmost}{%
+ \@namedef{scr@after@options@#1@hook@topmost}{}%
+ }%
+ \fi
+% \end{macrocode}
+% \begin{description}
+% \item[Note:] We do not use \pkg{xkeyval} and its \cs{setkeys+}, because this
+% would not execute the options in the order of the options but in the order
+% of the families, which is not intuitive and therefore not what we want.
+% \end{description}
+% We use a loop over all \meta{option}s in the \meta{list of options} to
+% split each \meta{option} into \meta{key} and \meta{value}.
+% \begin{macrocode}
+ \@for\scr@key@atlist:=#2\do{%
+% \end{macrocode}
+% \changes{v3.08}{2010/11/05}{empty options in the list are ignored}
+% Despite they do not make any sense empty \emph{options} are allowed and
+% ignored. This would at first mean two consecutive commas.
+% \begin{macrocode}
+ \ifx\scr@key@atlist\@empty\else
+% \end{macrocode}
+% But there also can be white spaces between the commas.
+% \begin{macrocode}
+ \ifx\scr@key@atlist\space\else
+ \expandafter\scr@key@split@name@value\scr@key@atlist==\@nil
+% \end{macrocode}
+% The third possibility would be a single equal sign. But in my opinion this
+% would be a mistake and therefore an error. So now, we have an \opt{option}
+% splitted into a \meta{key} and a \meta{value} (which can be empty).
+% \changes{v3.12}{2013/03/04}{storing the overall state}
+% Now, we are storing the overall state by emptying the error storage. If the
+% error storage is \cs{relax} it is not needed any longer. Both, \cs{relax}
+% and \cs{@empty} means no error. All other cases the error storage contains
+% all the errors to be reported.
+% \begin{macrocode}
+ \let\scr@key@run@errors\@empty
+% \end{macrocode}
+% \changes{v3.04b}{2010/01/29}{\cs{edef} replaced by \cs{protected@edef}}
+% \changes{v3.09a}{2011/06/07}{less number of expansions by improved usage of
+% \cs{unexpanded}}
+% Next a loop over the members is used, to detect members, that have the
+% \meta{key}. In this case the member option is executed. Note: The execution
+% of an option must not change any of the internal macros with the \meta{key},
+% \meta{value}, \meta{option} or \meta{list of options}
+% information. Additionally the states and the resulting messages have to been
+% collected. Here it is useful to have \cs{\meta{family}@key@familylist}, a
+% list of family + member and not only of members.
+% \changes{v3.27}{2019/07/19}{family options are executed first}
+% \begin{macrocode}
+ \scr@key@found@false
+ \edef\reserved@a{#1,\csname #1@key@familylist\endcsname}%
+ \@for\reserved@a:=\reserved@a\do{%
+ \scr@ifundefinedorrelax{KV@\reserved@a @\scr@key@name}{%
+% \end{macrocode}
+% \changes{v3.27}{2019/07/19}{treatment of \opt{@else@} options}
+% If a family member does not have the current option, there still may be a
+% \opt{@else@} option. In this case the \opt{@else@} option gets the current
+% \meta{option} as value and is executed. But this changes the error storage
+% only, if it was successful. In this case, the error storage has to become
+% empty. But the \opt{@else@} must not be executed here, if the current member
+% is the empty one, which represents the family itself. This will be done
+% later and only, if no one of the members have had the option itself or a
+% \opt{@else@} option. So the family \opt{@else@} option is only used, if the
+% option has not been successfully processed by any member in any kind.
+% \begin{macrocode}
+ \Ifstr{\reserved@a}{#1}{}{%
+ \scr@ifundefinedorrelax{KV@\reserved@a @@else@}{}{%
+ \expandafter\scr@execute@elseoption\expandafter{\reserved@a}%
+ \ifx\FamilyKeyState\FamilyKeyStateProcessed
+ \scr@key@found@true
+ \let\scr@key@run@errors\relax
+ \fi
+ }%
+ }%
+ }{%
+% \end{macrocode}
+% If the option has been found for a member, it is executed and the error
+% storage is updated.
+% \begin{macrocode}
+ \expandafter\scr@execute@option\expandafter{\reserved@a}%
+ \scr@key@found@true
+ \ifx\scr@key@run@errors\relax\else
+ \ifx\FamilyKeyState\FamilyKeyStateProcessed
+ \let\scr@key@run@errors\relax
+ \else
+ \ifx\FamilyKeyState\FamilyKeyStateUnknownValue
+ \edef\scr@key@run@errors{%
+ \unexpanded\expandafter{\scr@key@run@errors}%
+ \noexpand\MessageBreak
+ \space\space- `\FamilyMemberOfKey': unkown value
+ `\expandafter\detokenize\expandafter{\scr@key@value}'%
+ }%
+ \else
+ \ifx\FamilyKeyState\FamilyKeyStateNeedValue
+ \edef\scr@key@run@errors{%
+ \unexpanded\expandafter{\scr@key@run@errors}%
+ \noexpand\MessageBreak
+ \space\space- `\FamilyMemberOfKey': value expected
+ }%
+ \else
+ \edef\scr@key@run@errors{%
+ \unexpanded\expandafter{\scr@key@run@errors}%
+ \noexpand\MessageBreak
+ \space\space- `\FamilyMemberOfKey': \FamilyKeyState
+ }%
+ \fi
+ \fi
+ \fi
+ \fi
+ }%
+ }%
+ \ifscr@key@found@
+ \ifx\scr@key@run@errors\relax\else
+ \ifx\scr@key@run@errors\@empty\else
+% \end{macrocode}
+% \changes{v3.28}{2019/11/23}{error messages and info fixed}
+% Now, an existing \opt{@else@} option has to be used and either an error or
+% info has to be shown.
+% \begin{macrocode}
+ \scr@ifundefinedorrelax{KV@#1@@else@}{%
+ \PackageError{scrbase}{%
+ unknown option
+ `\expandafter\detokenize\expandafter{\scr@key@atlist}'%
+ }{%
+ The members of family `#1' cannot set option
+ `\scr@key@name'
+ \ifx\scr@key@value\@empty\else
+ \MessageBreak
+ to value
+ `\expandafter\detokenize\expandafter{\scr@key@value}'%
+ \fi.\MessageBreak
+ Here's what each member says:
+ \scr@key@run@errors
+ }%
+ }{%
+ \scr@execute@elseoption{#1}%
+ \ifx\FamilyKeyState\FamilyKeyStateProcessed
+ \PackageInfo{scrbase}{%
+ option
+ `\expandafter\detokenize\expandafter{\scr@key@atlist}'%
+ \MessageBreak
+ processed by `@else@' option of family\MessageBreak
+ `#1', after the members said:
+ \scr@key@run@errors\MessageBreak
+ o\expandafter\@gobble
+ }%
+ \let\scr@key@run@errors\relax
+ \else
+ \PackageError{scrbase}{%
+ unknown option
+ \ifx\FamilyKeyState\FamilyKeyStateUnknownValue
+ value at
+ \fi
+ `\expandafter\detokenize\expandafter{\scr@key@atlist}'%
+ }{%
+ The members of family `#1' cannot set option
+ `\scr@key@name'
+ \ifx\scr@key@value\@empty\else
+ \MessageBreak
+ to value
+ `\expandafter\detokenize\expandafter{\scr@key@value}'%
+ \fi.\MessageBreak
+ Here's what each member says:
+ \scr@key@run@errors
+ }%
+ \fi
+ }%
+ \fi
+ \fi
+ \else
+ \scr@ifundefinedorrelax{KV@#1@@else@}{%
+ \PackageError{scrbase}{%
+ unknown option
+ `\expandafter\detokenize\expandafter{\scr@key@atlist}'%
+ }{%
+ No one of the members of family `#1'\MessageBreak
+ can handle option `\scr@key@name'.\MessageBreak
+ So it cannot be set%
+ \ifx\scr@key@value\@empty\else
+ \space to value
+ `\expandafter\detokenize\expandafter{\scr@key@value}'%
+ \fi.%
+ }%
+ }{%
+ \scr@execute@elseoption{#1}%
+ \ifx\FamilyKeyState\FamilyKeyStateProcessed
+ \else
+ \PackageError{scrbase}{%
+ unknown option
+ \ifx\FamilyKeyState\FamilyKeyStateUnknownValue
+ value at
+ \fi
+ `\expandafter\detokenize\expandafter{\scr@key@atlist}'%
+ }{%
+ No one of the members of family `#1'\MessageBreak
+ can handle option `\scr@key@name'.\MessageBreak
+ So it cannot be set%
+ \ifx\scr@key@value\@empty\else
+ \space to value
+ `\expandafter\detokenize\expandafter{\scr@key@value}'%
+ \fi.%
+ }%
+ \fi
+ }%
+ \fi
+ \fi
+ \fi
+ }%
+ \@nameuse{scr@after@options@#1@hook}%
+}
+% \end{macrocode}
+% \begin{macro}{\scr@execute@option}
+% \changes{v3.12}{2013/03/04}{added}
+% \changes{v3.13}{2014/06/30}{missing \cs{expandafter} in \cs{PackageInfo} added}
+% \changes{v3.13a}{2014/08/13}{white spaces removed}
+% \changes{v3.23}{2017/02/16}{it does not help to save the
+% \cs{AtEndOfFamilyOptions} hook}
+% A split \opt{option} is executed, without changing any relevant macros (but
+% \cs{reserved@a}). The first argument is the complete set in \pkg{keyval} syntax.
+% \begin{macrocode}
+\newcommand*{\scr@execute@option}[1]{%
+ \protected@edef\reserved@a{%
+ \noexpand\let\noexpand\KV@err\noexpand\scr@KV@err
+ \noexpand\setkeys{#1}{%
+ \unexpanded\expandafter{\scr@key@atlist}}%
+ \noexpand\def\noexpand\scr@key@atlist{%
+ \unexpanded\expandafter{\scr@key@atlist}}%
+ \noexpand\def\noexpand\scr@key@name{%
+ \unexpanded\expandafter{\scr@key@name}}%
+ \noexpand\def\noexpand\scr@key@value{%
+ \unexpanded\expandafter{\scr@key@value}}%
+ \ifx\scr@key@run@errors\relax
+ \noexpand\let\noexpand\scr@key@run@errors\relax
+ \else
+ \noexpand\def\noexpand\scr@key@run@errors{%
+ \unexpanded\expandafter{\scr@key@run@errors}}%
+ \fi
+ \ifx\AtEndOfFamilyOptions\scr@AtEndOfFamilyOptions@immediate
+ \noexpand\let\noexpand\AtEndOfFamilyOptions
+ \noexpand\scr@AtEndOfFamilyOptions@immediate
+ \fi
+ }%
+ \let\AtEndOfFamilyOptions\scr@AtEndOfFamilyOptions
+ \reserved@a
+ \ifx\FamilyKeyState\FamilyKeyStateUnknown
+ \PackageInfo{scrbase}{Unknown processing state.\MessageBreak
+ Processing option
+ `\expandafter\detokenize\expandafter{\scr@key@atlist}'\MessageBreak
+ \ifx\FamilyMemberOfKey\@empty\else
+ of member `\FamilyMemberOfKey'\MessageBreak
+ \fi
+ of family `\FamilyOfKey'\MessageBreak
+ doesn't set a valid state.\MessageBreak
+ This will be interpreted\MessageBreak
+ as \string\FamilyKeyStateProcessed
+ }%
+ \FamilyKeyStateProcessed
+ \fi
+}
+% \end{macrocode}
+% \begin{macro}{\scr@KV@err}
+% \changes{v3.12a}{2013/03/04}{missing internal command added}
+% We just have to signal, that the option needs a value, that is missing.
+% \begin{macrocode}
+\newcommand*{\scr@KV@err}[1]{%
+ \FamilyKeyStateNeedValue
+}
+% \end{macrocode}
+% \end{macro}^^A \scr@KV@err
+% \begin{macro}{\scr@key@run@errors}
+% \changes{v3.12}{2013/03/04}{added}
+% Needed by \cs{FamilyOptions} to collect the error messages, but report the
+% error only, if no member has successfully processed the option. We define it
+% here to make the re-definition in the previous code does work without error.
+% \begin{macrocode}
+\newcommand*{\scr@key@run@errors}{}
+% \end{macrocode}
+% \end{macro}^^A \scr@key@run@errors}
+% \end{macro}^^A \scr@execute@option
+% \begin{macro}{\scr@execute@elseoption}
+% \changes{v3.20}{2015/11/18}{added}
+% \changes{v3.25}{2017/11/16}{group added}
+% \changes{v3.25}{2017/11/16}{\cs{scr@key@name@else} and
+% \cs{scr@key@value@else} added}
+% \changes{v3.27}{2019/03/10}{missing percent added to avoid spaces}
+% If a special option \opt{@else@} has been defined, it is executed by
+% \cs{FamilyExecuteOptions} if and only if no other suitable option has been
+% found. This is done by \cs{scr@execute@elseoption}. The argument and
+% resulting state are exactly the same as with \cs{scr@execute@option}. It
+% also have to do the same, but it does not call the option, but the
+% \opt{@else@} option. The option itself is used as \meta{value} of the
+% \opt{@else@} option. So temporary \cs{scr@key@atlist}, \cs{scr@key@name} and
+% \cs{scr@key@value} have to be changed, before calling
+% \cs{scr@execute@option}. To avoid once again splitting the \meta{value} into
+% an internal \meta{key} and \meta{value} the original \cs{scr@key@name} and
+% \cs{scr@key@value} are copied to \cs{scr@key@name@else} and
+% \cs{scr@key@value@else}. These can be used inside the code of the
+% \opt{@else@} option.
+% \begin{macrocode}
+\newcommand*{\scr@execute@elseoption}[1]{%
+ \begingroup
+ \protected@edef\reserved@a{%
+ \unexpanded{%
+ \endgroup
+ \let\scr@key@name@else\scr@key@name
+ \let\scr@key@value@else\scr@key@value
+ \def\scr@key@name{@else@}%
+ }%
+ \noexpand\def\noexpand\scr@key@value{%
+ \unexpanded\expandafter{\scr@key@atlist}}%
+ \noexpand\def\noexpand\scr@key@atlist{%
+ @else@={\unexpanded\expandafter{\scr@key@atlist}}}%
+ \noexpand\scr@execute@option{#1}%
+ \noexpand\def\noexpand\scr@key@atlist{%
+ \unexpanded\expandafter{\scr@key@atlist}}%
+ \noexpand\def\noexpand\scr@key@name{%
+ \unexpanded\expandafter{\scr@key@name}}%
+ \noexpand\def\noexpand\scr@key@value{%
+ \unexpanded\expandafter{\scr@key@value}}%
+ \scr@ifundefinedorrelax{scr@key@name@else}{%
+ \unexpanded{\let\scr@key@name@else\relax}%
+ }{%
+ \noexpand\def\noexpand\scr@key@name@else{%
+ \unexpanded\expandafter{\scr@key@name@else}%
+ }%
+ }%
+ \scr@ifundefinedorrelax{scr@key@value@else}{%
+ \unexpanded{\let\scr@key@value@else\relax}%
+ }{%
+ \noexpand\def\noexpand\scr@key@value@else{%
+ \unexpanded\expandafter{\scr@key@value@else}%
+ }%
+ }%
+ }\reserved@a
+}
+% \end{macrocode}
+% \end{macro}^^A \scr@execute@elseoption
+% \begin{macro}{\KOMA@key@foundtrue,\KOMA@key@foundfalse,\ifKOMA@key@found,
+% \scr@key@found@true,\scr@key@found@false,\ifscr@key@found@}
+% \changes{v2.97c}{2007/04/19}{added}
+% \changes{v3.00}{2008/04/30}{\cs{ifKOMA@key@found} renamed to \cs{ifscr@key@found}}
+% \begin{macro}{\KOMA@key@at@list,\scr@key@atlist}
+% \changes{v2.97c}{2007/04/19}{added}
+% \changes{v3.00}{2008/04/30}{\cs{KOMA@key@atlist} renamed to \cs{scr@key@atlist}}
+% \begin{macro}{\KOMA@key@name,\scr@key@name}
+% \changes{v2.97c}{2007/04/19}{added}
+% \changes{v3.00}{2008/04/30}{\cs{KOMA@key@name} renamed to \cs{scr@key@name}}
+% \begin{macro}{\KOMA@key@value,\scr@key@value}
+% \changes{v2.97c}{2007/04/19}{added}
+% \changes{v3.00}{2008/04/30}{\cs{KOMA@key@value} renamed to \cs{scr@key@value}}
+% \begin{macro}{\KOMA@key@split@name@value,\scr@key@split@name@value}
+% \changes{v2.97c}{2007/04/19}{added}
+% \changes{v2.97e}{2007/11/10}{using \cs{KV@@sp@def} to remove white spaces}
+% \changes{v3.00}{2008/04/30}{\cs{KOMA@key@split@name@value} renamed to
+% \cs{scr@key@split@name@value}}
+% \changes{v3.13}{2014/10/17}{\cs{long}}
+% \changes{v3.26}{2018/08/29}{using \cs{scr@sp@def} instead of \cs{KV@@sp@def}}
+% \begin{macrocode}
+\newif\ifscr@key@found@
+\newcommand*{\scr@key@atlist}{}
+\newcommand*{\scr@key@name}{}
+\newcommand*{\scr@key@value}{}
+\newcommand*{\scr@key@split@name@value}{}
+\long\def\scr@key@split@name@value#1=#2=#3\@nil{%
+ \scr@sp@def\scr@key@name{#1}%
+ \scr@sp@def\scr@key@value{#2}%
+}
+%</base>
+% \end{macrocode}
+% \end{macro}^^A \scr@key@split@name@value
+% \end{macro}^^A \scr@key@value
+% \end{macro}^^A \scr@key@name
+% \end{macro}^^A \scr@key@atlist
+% \end{macro}^^A \@FamilyOptions
+% \end{macro}^^A \ifscr@key@found@
+% \end{command}^^A \FamilyOptions
+%
+% \begin{command}{\FamilyOption}
+% \changes{v3.00}{2008/04/30}{added}
+% \changes{v3.26b}{2019/01/09}{handling of typical user mistakes}
+% \begin{macro}{\@FamilyOptions}
+% \changes{v3.14}[2014/10/17]{added}
+% \changes{v3.26}{2018/08/29}{using \cs{scr@sp@def} instead of \cs{KV@@sp@def}}
+% \begin{macro}{\Family@Option}
+% \changes{v3.00}{2008/04/30}{added}
+% \changes{v3.12}{2013/03/04}{removed}
+% \end{macro}^^A \Family@Option
+% \changes{v3.04b}{2010/01/29}{\cs{edef} replaced by \cs{protected@edef}}
+% In opposite to \cs{FamilyOptions} this command sets only one \meta{option}
+% (\texttt{\#2}) of a \meta{family} (\texttt{\#1}). But you can set it to a
+% \meta{list of values} (\texttt{\#3}). The values are set in the order of the
+% \meta{list of values}.
+% \begin{macrocode}
+%<*base>
+\newcommand*{\FamilyOption}[2]{%
+ \begingroup
+ \def\reserved@a##1,##2\@nil{\IfArgIsEmpty{##2}{}{\@tempswatrue}}%
+ \@tempswafalse\expandafter\reserved@a#2,\@nil
+ \if@tempswa
+ \PackageError{scrbase}{%
+ syntax error in key `\detokenize{#2}'%
+ }{%
+ You've used `\string\...Option' to set the key
+ `\detokenize{#2}'\MessageBreak
+ to new value(s), but `,' is not allowed in the key of
+ an option\MessageBreak
+ (and `\string\...Option' does not use `,' to separate several
+ keys).\MessageBreak
+ Maybe you've meant \string\...Options\space instead of
+ \string\...Option.\MessageBreak
+ If you'll continue, I'll give it a try, but you should expect
+ further\MessageBreak
+ and even strange error messages.%
+ }%
+ \else
+ \def\reserved@a##1=##2\@nil{%
+ \IfArgIsEmpty{##2}{}{\@tempswatrue\def\reserved@a{=}}}%
+ \expandafter\reserved@a#2=\@nil
+ \if@tempswa
+ \PackageError{scrbase}{%
+ syntax error in key `\detokenize{#2}'%
+ }{%
+ You've used `\string\...Option' to set the key
+ `\detokenize{#2}'\MessageBreak
+ to new value(s), but `=' is not allowed in the key of
+ an option\MessageBreak
+ (and `\string\...Option' does not use `=' to separate key and
+ value).\MessageBreak
+ Maybe you've meant \string\...Options\space instead of
+ \string\...Option.\MessageBreak
+ If you'll continue, I'll give it a try, but you should expect
+ further\MessageBreak
+ and even strange error messages.%
+ }%
+ \fi
+ \fi
+ \endgroup
+ \@FamilyOption{#1}{#2}%
+}
+\newcommand{\@FamilyOption}[3]{%
+ \expandafter\scr@sp@def\expandafter\scr@key@name\expandafter{#2}%
+% \end{macrocode}
+% The most simply solution is to walk through the \meta{list of values} and
+% generate a \meta{list of options} for \cs{FamilyOptions}.
+% \begin{macrocode}
+ \let\reserved@a\@empty
+ \@for\reserved@b:=#3\do{%
+% \end{macrocode}
+% \changes{v3.08}{2010/11/05}{allow empty values}
+% Empty elements in the \meta{list of values} are ignored. Note: This is not
+% really the correct solution but several users expect it. So for a real empty
+% value you need to use |{}|.
+% \begin{macrocode}
+ \ifx\reserved@b\@empty\else
+% \end{macrocode}
+% \changes{v3.12}{2012/03/04}{ignore white space values}
+% The same for white space values.
+% \begin{macrocode}
+ \ifx\reserved@b\space\else
+ \edef\reserved@a{\unexpanded\expandafter{\reserved@a},%
+ \scr@key@name=\unexpanded\expandafter{\reserved@b}}%
+ \fi
+ \fi
+ }%
+ \def\reserved@b{\FamilyOptions{#1}}%
+ \expandafter\reserved@b\expandafter{\reserved@a}%
+}
+%</base>
+% \end{macrocode}
+% \end{macro}
+% \end{command}
+%
+% \begin{command}{\KOMAoptions}
+% \changes{v2.96}{2006/08/20}{hook after options added}
+% \changes{v2.97c}{2007/04/19}{process options of all members}
+% \changes{v3.12}{2013/03/04}{using hooks of \cs{FamilyOptions}}
+% Nice little shortcut.
+% \begin{macrocode}
+%<*koma>
+\newcommand*{\KOMAoptions}{\FamilyOptions{KOMA}}
+%</koma>
+% \end{macrocode}
+% \begin{macro}{\KOMA@options}
+% \changes{v2.97c}{2007/04/19}{added}
+% \changes{v3.12}{2013/03/04}{removed}
+% \end{macro}^^A \KOMA@options
+% \end{command}^^A \KOMAoptions
+%
+% \begin{command}{\KOMAoptionsOf}
+% \changes{v3.17}{2015/02/25}{added}
+% Ask for the currently set options of a supporting \KOMAScript{} class or
+% package. The optional first argument (\texttt{\#1}) is a command or macro,
+% that will be execute with the list of options as an argument. The second
+% argument (\texttt{\#2}) is the filename of a \KOMAScript{} class or package
+% (with extension). Without optional argument, the \meta{list of options} are
+% be printed.
+% \begin{macrocode}
+%<*koma>
+\newcommand*{\KOMAoptionsOf}[2][\@firstofone]{%
+ \scr@ifundefinedorrelax{scr@kav@KOMA.#2}{%
+ \PackageError{scrkbase}{\string\KOMAoptionsOf\space not supported}{%
+ #2 is not the name of a KOMA-Script package or\MessageBreak
+ KOMA-Script class, that supports \string\KOMAoptionsOf.}%
+ }{%
+ \begingroup
+ \def\reserved@a{#1}%
+ \KOMA@kav@defall\reserved@b{.#2}%
+ \expandafter\expandafter\expandafter\endgroup
+ \expandafter\reserved@a\expandafter{\reserved@b}%
+ }%
+}
+%</koma>
+% \end{macrocode}
+% \end{command}^^A \KOMAoptionsOf
+%
+% \begin{command}{\KOMAoptionOf}
+% \changes{v3.17}{2015/02/26}{added}
+% Ask for the current values of one option of a supporting \KOMAScript{} class
+% or package. Again the optional first argument (\texttt{\#1}) is a command or
+% macro, that will be execute with the list of values as an argument. The second
+% argument (\texttt{\#2}) is the filename of a \KOMAScript{} class or package
+% (with extension). The third argument (\texttt{\#3}) is the name of an
+% option of the class resp. package. Without optional argument, the \meta{list of
+% values} are be printed.
+% \begin{macrocode}
+%<*koma>
+\newcommand*{\KOMAoptionOf}[3][\@firstofone]{%
+ \scr@ifundefinedorrelax{scr@kav@KOMA.#2}{%
+ \PackageError{scrkbase}{\string\KOMAoptionOf\space not supported}{%
+ #2 is not the name of a KOMA-Script package or\MessageBreak
+ KOMA-Script class, that supports \string\KOMAoptionOf.}%
+ }{%
+ \begingroup
+ \def\reserved@a{#1}%
+ \KOMA@kav@defone\reserved@b{.#2}{#3}%
+ \ifx\reserved@b\@empty
+ \PackageWarning{scrkbase}{option `#3' for `#2' unset}%
+ \endgroup
+ \else
+ \expandafter\expandafter\expandafter\endgroup
+ \expandafter\reserved@a\expandafter{\reserved@b}%
+ \fi
+ }%
+}
+%</koma>
+% \end{macrocode}
+% \end{command}
+%
+% \begin{macro}{\post@kopt@hook}
+% \changes{v3.12}{2013/03/04}{removed}
+% \end{macro}^^A \post@kopt@hook
+% \begin{command}{\AfterKOMAoptions}
+% \changes{v3.12}{2013/03/04}{using \cs{AtEndOfFamilyOptions}}
+% \changes{v3.23}{2017/02/16}{\cs{newcommand} instead of \cs{let}}
+% An option can process code after executing all options of the current
+% \cs{KOMAoptions}.
+% \begin{macrocode}
+%<*koma>
+\newcommand*{\AfterKOMAoptions}{\AtEndOfFamilyOptions}
+%</koma>
+% \end{macrocode}
+% \end{command}^^A \AfterKOMAoptions
+%
+% \begin{macro}{\l@addto@macro}
+% \changes{v2.8p}{2001/09/22}{added}
+% \changes{v2.95}{2006/06/02}{changed to handle macros with arguments same
+% like \cs{g@addto@macro}}
+% \changes{v3.12}{2013/04/20}{removed non-\eTeX{} implementation}
+% \changes{v3.12}{2013/04/20}{warn, if \cs{l@addto@macro} is already defined
+% different from our definition}
+% \changes{v3.23}{2017/02/16}{moved to \texttt{prepare}}
+% We need a local variant of \cs{g@addto@macro}.
+% \begin{macrocode}
+%</body>
+%<*base&prepare>
+\@ifundefined{l@addto@macro}{}{%
+ \begingroup
+ \long\def\reserved@a#1#2{%
+ \edef#1{\unexpanded\expandafter{#1#2}}%
+ }%
+ \ifx\reserved@a\l@addto@macro\else
+ \PackageWarning{scrbase}{%
+ Someone also uses macro name \string\l@addto@macro.\MessageBreak
+ When KOMA-Script author decided to use macro name\MessageBreak
+ \string\l@addto@macro\space first, there was no other
+ free\MessageBreak
+ LaTeX package using this macro name.\MessageBreak
+ In the meantime other package authers decided to use\MessageBreak
+ same macro name, but unfortunatly not all of those\MessageBreak
+ are compatible with KOMA-Script's definition, e.g.,\MessageBreak
+ while adding definitions with arguments to macros.\MessageBreak
+ Because of such potentially incompatible definitions,\MessageBreak
+ KOMA-Script will redefine the command now.\MessageBreak
+ Please ask the author of the other package to\MessageBreak
+ rename his macro, if a problem results in the\MessageBreak
+ redefinition%
+ }%
+ \fi
+ \endgroup
+}
+\long\def\l@addto@macro#1#2{%
+ \edef#1{\unexpanded\expandafter{#1#2}}%
+}%
+%</base&prepare>
+%<*body>
+% \end{macrocode}
+% \end{macro}^^A \l@addto@macro
+%
+% \begin{macro}{\l@addto@macro@a}
+% \changes{v3.20}{2015/11/20}{added}
+% I also need a version for macros with exactly one argument. Note: This macro
+% is dangerous. Sometimes it does not work correctly, so there is not an will
+% not be an official documentation.
+% \begin{macrocode}
+%<*base>
+\begingroup
+ \catcode`\^^A=\catcode`\#
+ \@makeother\#
+ \gdef\l@addto@macro@a^^A1{%
+ \begingroup
+ \@makeother\#
+ \def\l@addto@macro@a@cmd{^^A1}%
+ \l@addto@macro@a@
+ }
+ \gdef\l@addto@macro@a@^^A1{%
+ \def\l@addto@macro@a@add{^^A1}%
+ \l@addto@macro@a@@
+ }
+\endgroup
+\begingroup
+ \@makeother\#
+ \gdef\l@addto@macro@a@@{%
+ \@makeother\#
+ \edef\reserved@a{%
+ \detokenize{\endgroup\def}%
+ \detokenize\expandafter{\l@addto@macro@a@cmd#1}%
+ {%
+ \expandafter\detokenize%
+ \expandafter\expandafter\expandafter{\l@addto@macro@a@cmd{#1}}%
+ \expandafter\detokenize\expandafter{\l@addto@macro@a@add}%
+ }%
+ }%
+ \expandafter\scantokens\expandafter{\reserved@a}%
+ }%
+\endgroup
+%</base>
+% \end{macrocode}
+% \end{macro}^^A \l@addto@macro@a
+%
+% \begin{macro}{\l@preto@macro}
+% \changes{v3.20}{2015/11/25}{added}
+% Similar to \cs{l@addto@macro} but adds code at the very beginning instead of
+% appending it a the end.
+% \begin{macrocode}
+%<*base>
+\newcommand\l@preto@macro[2]{%
+ \edef#1{\unexpanded{#2}\unexpanded\expandafter{#1}}%
+}%
+%</base>
+% \end{macrocode}
+% \end{macro}^^A \l@preto@macro
+%
+% \begin{macro}{\l@preto@macro@a}
+% \changes{v3.20}{2015/11/25}{added}
+% I also need a version for macros with exactly one argument. Note: This macro
+% is dangerous. Sometimes it does not work correctly, so there is not an will
+% not be an official documentation.
+% \begin{macrocode}
+%<*base>
+\begingroup
+ \catcode`\^^A=\catcode`\#
+ \@makeother\#
+ \gdef\l@preto@macro@a^^A1{%
+ \begingroup
+ \@makeother\#
+ \def\l@preto@macro@a@cmd{^^A1}%
+ \l@preto@macro@a@
+ }
+ \gdef\l@preto@macro@a@^^A1{%
+ \def\l@preto@macro@a@add{^^A1}%
+ \l@preto@macro@a@@
+ }
+\endgroup
+\begingroup
+ \@makeother\#
+ \gdef\l@preto@macro@a@@{%
+ \@makeother\#
+ \edef\reserved@a{%
+ \detokenize{\endgroup\def}%
+ \detokenize\expandafter{\l@preto@macro@a@cmd#1}%
+ {%
+ \expandafter\detokenize\expandafter{\l@preto@macro@a@add}%
+ \expandafter\detokenize%
+ \expandafter\expandafter\expandafter{\l@preto@macro@a@cmd{#1}}%
+ }%
+ }%
+ \expandafter\scantokens\expandafter{\reserved@a}%
+ }%
+\endgroup
+%</base>
+% \end{macrocode}
+% \end{macro}^^A \l@preto@macro@a
+%
+% \begin{command}{\KOMAoption}
+% \changes{v2.98c}{2008/03/12}{added}
+% \changes{v3.12}{2013/03/04}{using \cs{FamilyOption}}
+% Simple little shortcut.
+% \begin{macrocode}
+%<*koma>
+\newcommand*{\KOMAoption}{\FamilyOption{KOMA}}
+%</koma>
+% \end{macrocode}
+% \end{command}
+%
+% \begin{command}{\FamilyUnknownKeyValue}
+% \changes{v3.10}{2011/09/12}{no error while processing global options}
+% \changes{v3.11a}{2012/05/28}{prevent remove from list of unused global
+% options globally}
+% \changes{v3.14}{2014/10/17}{\cs{long}}
+% \changes{v3.30}{2020/02/25}{spurious space in warning message removed}
+% Used to report an error because of unknown values. Arguments are
+% \marg{family}\marg{key}\marg{valid values}.
+% \begin{macrocode}
+%<*base>
+\newcommand{\FamilyUnknownKeyValue}[4]{%
+ \FamilyKeyStateUnknownValue
+ \ifx\FamilyElseValues\@empty\else
+ \PackageWarning{scrbase}{non empty \string\FamilyElseValue
+ ignored.\MessageBreak
+ Setting this command to a non empty\MessageBreak
+ value for option `#2' of\MessageBreak
+ family `#1' is deprecated,\MessageBreak
+ but has been found%
+ }%
+ \fi
+}
+%</base>
+% \end{macrocode}
+% \begin{command}{\FamilyElseValues}
+% \changes{v3.00}{2008/05/02}{added}
+% \changes{v3.12}{2013/03/04}{deprecated and not used internally}
+% \begin{macrocode}
+%<*base>
+\newcommand*{\FamilyElseValues}{}
+%</base>
+% \end{macrocode}
+% \end{command}^^A \FamilyUnknownKeyValue
+% \end{command}^^A \FamilyElseValue
+%
+% \begin{command}{\FamilyBoolKey}
+% \changes{v3.00}{2008/04/30}{added}
+% Defining a new boolean key:
+% \begin{quote}
+% \cs{FamilyBoolKey}\oarg{member}\marg{family}\marg{key}\marg{switch}
+% \end{quote}
+% The default \meta{member} is (once again)
+% \file{.\cs{@currname}.\cs{@currext}} and it is recommended to always use it!
+% \cs{if\meta{switch}} is automatically defined, if it was undefined. In this
+% case the initial value is \opt{false}. The default for using the \meta{key}
+% without argument would be \opt{true}. For other allowed values see
+% \cs{FamilySetBool}.
+% \begin{macrocode}
+%<*base>
+\newcommand*{\FamilyBoolKey}[4][.\@currname.\@currext]{%
+ \@ifundefined{if#4}{%
+ \expandafter\newif\csname if#4\endcsname
+ }{}%
+ \DefineFamilyKey[{#1}]{#2}{#3}[true]{\FamilySetBool{#2}{#3}{#4}{##1}}%
+}
+% \end{macrocode}
+% \begin{command}{\FamilySetBool}
+% \changes{v3.00}{2008/04/30}{added}
+% \changes{v3.11a}{2012/05/25}{error message fixed}
+% \changes{v3.27}{2019/07/08}{empty argument is \texttt{true}}
+% \changes{v3.28}{2019/11/18}{\cs{ifstr} renamed to \cs{Ifstr}}
+% Setting a boolean key:
+% \begin{quote}
+% \cs{FamilySetBool}\marg{family}\marg{key}\marg{switch}\marg{value}
+% \end{quote}
+% The \meta{family} and the \meta{key} are used for reporting unknown values using
+% \cs{FamilyUnknownKeyValue}. The \meta{switch} is used to use either
+% \cs{\meta{switch}true} or \cs{\meta{switch}false}. It is ignored, if these
+% are not defined, so have to take care, that \cs{if\meta{switch}} already has
+% been defined, e.g., using \cs{FamilyBoolKey}. The \meta{value} can either be
+% \opt{true}, \opt{on} or \opt{yes} for \cs{\meta{switch}true} or
+% \opt{false}, \opt{off} or \opt{no} for \cs{\meta{switch}false}.
+% \begin{macrocode}
+\newcommand*{\FamilySetBool}[4]{%
+ \Ifstr{#4}{}{\@nameuse{#3true}\FamilyKeyStateProcessed}{%
+ \Ifstr{#4}{true}{\@nameuse{#3true}\FamilyKeyStateProcessed}{%
+ \Ifstr{#4}{on}{\@nameuse{#3true}\FamilyKeyStateProcessed}{%
+ \Ifstr{#4}{yes}{\@nameuse{#3true}\FamilyKeyStateProcessed}{%
+ \Ifstr{#4}{false}{\@nameuse{#3false}\FamilyKeyStateProcessed}{%
+ \Ifstr{#4}{off}{\@nameuse{#3false}\FamilyKeyStateProcessed}{%
+ \Ifstr{#4}{no}{\@nameuse{#3false}\FamilyKeyStateProcessed}{%
+ \FamilyUnknownKeyValue{#1}{#2}{#4}{%
+ `true', `on', `yes', `false', `off', `no'%
+ }%
+ }%
+ }%
+ }%
+ }%
+ }%
+ }%
+ }%
+ \let\FamilyElseValues\@empty
+}
+%</base>
+% \end{macrocode}
+% \end{command}
+% \end{command}
+% \begin{command}{\FamilyInverseBoolKey,\FamilySetInverseBool}
+% \changes{3.27}{2019/07/08}{added}
+% These are similar to \cs{FamilyBoolKey} and \cs{FamilySetBoolKey} but use
+% inverse logic (true sets false and false sets true).
+% \begin{macrocode}
+%<*base>
+\newcommand*{\FamilyInverseBoolKey}[4][.\@currname.\@currext]{%
+ \@ifundefined{if#4}{%
+ \expandafter\newif\csname if#4\endcsname
+ \@nameuse{#4true}%
+ }{}%
+ \DefineFamilyKey[{#1}]{#2}{#3}[true]{\FamilySetInverseBool{#2}{#3}{#4}{##1}}%
+}
+\newcommand*{\FamilySetInverseBool}[4]{%
+ \FamilySetBool{#1}{#2}{#3}{#4}%
+ \ifx\FamilyKeyState\FamilyKeyStateProcessed
+ \expandafter\ifx\csname if#3\expandafter\endcsname\csname iftrue\endcsname
+ \@nameuse{#3false}%
+ \else
+ \@nameuse{#3true}%
+ \fi
+ \fi
+}
+%</base>
+% \end{macrocode}
+% \end{command}^^A \FamilyInverseBoolKey,\FamilySetInverseBool
+%
+% \begin{macro}{\KOMA@unknown@keyval}
+% Version of \cs{FamilyUnknownKeyValue} with static family |KOMA|.
+% \begin{macrocode}
+%<*koma>
+\newcommand*{\KOMA@unknown@keyval}{\FamilyUnknownKeyValue{KOMA}}
+%</koma>
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\KOMA@ifkey}
+% \changes{v3.02c}{2009/02/04}{defines the member if needed}
+% \changes{v3.17}{2015/03/02}{replaces the value in the storage}
+% This is an extended version of \cs{FamilyBoolKey} with static family
+% |KOMA|. So the syntax is:
+% \begin{quote}
+% \cs{KOMA@ifkey}\oarg{member}\marg{key}\marg{switch}
+% \end{quote}
+% The default \meta{member} is (once again)
+% \file{.\cs{@currname}.\cs{@currext}} and it is recommended to always use it!
+% \cs{if\meta{switch}} is automatically defined, if it was undefined. The
+% default for using the \meta{key} without argument would be \opt{true}. Note:
+% \meta{member} and \meta{key} are always fully expanded. Depending on a
+% already existing \cs{if\meta{key}} either \opt{\meta{key}=true} or
+% \opt{\meta{key}=false} is added to the value storage. If \cs{if\meta{key}}
+% was not defined, the initialized value is \opt{false}.
+% \begin{macrocode}
+%<*koma>
+\newcommand*{\KOMA@ifkey}[2][.\@currname.\@currext]{%
+ \begingroup\edef\reserved@a{\noexpand\KOMA@@ifkey{#1}{#2}}%
+ \expandafter\endgroup\reserved@a
+}
+\newcommand*{\KOMA@@ifkey}[3]{%
+ \@ifundefined{if#3}{%
+ \expandafter\newif\csname if#3\endcsname
+ }{}%
+ \KOMA@key[{#1}]{#2}[true]{%
+ \KOMA@set@ifkey{#2}{#3}{##1}%
+ \KOMA@kav@replacebool{#1}{#2}{#3}%
+ }%
+ \csname if#3\endcsname
+ \KOMA@kav@xadd{#1}{#2}{true}%
+ \else
+ \KOMA@kav@xadd{#1}{#2}{false}%
+ \fi
+}
+%</koma>
+% \end{macrocode}
+% \begin{macro}{\KOMA@set@ifkey}
+% Simple a shortcut for |\FamilySetBool{KOMA}|. So the syntax is:
+% \begin{quote}
+% \cs{KOMA@set@ifkey}\marg{key}\marg{switch}\marg{value}
+% \end{quote}
+% But all arguments are delegated.
+% \begin{macrocode}
+%<*koma>
+\newcommand*{\KOMA@set@ifkey}{\FamilySetBool{KOMA}}
+%</koma>
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{command}{\FamilyCounterKey}
+% \changes{v3.12}{2013/11/05}{added}
+% \changes{v3.15}{2014/12/03}{optional default value}
+% \changes{v3.20}{2016/04/12}{\cs{@ifnextchar} replaced by
+% \cs{kernel@ifnextchar}}
+% Defining a \meta{key} that sets a \LaTeX{} counter to a \meta{value}.
+% \begin{quote}
+% \cs{FamilyCounterKey}\oarg{member}\marg{family}\marg{key}\oarg{default}\marg{\LaTeX{} counter}
+% \end{quote}
+% \meta{default} and the \meta{value} of the option has to be (almost) any
+% kind of value, that can be assigned to a \LaTeX{} counter. The
+% \meta{counter} is automatically defined, if it was undefined. In this case
+% the initial value is 0.
+% \begin{macro}{\Family@@Counter@@Key,\Family@Counter@Key}
+% \changes{v3.15}{2014/12/03}{added}
+% \begin{macrocode}
+%<*base>
+\newcommand*{\FamilyCounterKey}[3][.\@currname.\@currext]{%
+ \kernel@ifnextchar [%]
+ {\Family@@Counter@@Key{#1}{#2}{#3}}%
+ {\Family@Counter@Key{#1}{#2}{#3}}%
+}
+\newcommand*{\Family@@Counter@@Key}{}
+\def\Family@@Counter@@Key#1#2#3[#4]#5{%
+ \@ifundefined{c@#5}{\newcounter{#5}}{}%
+ \DefineFamilyKey[{#1}]{#2}{#3}[{#4}]{\FamilySetCounter{#2}{#3}{#5}{##1}}%
+}
+\newcommand*{\Family@Counter@Key}[4]{%
+ \@ifundefined{c@#4}{\newcounter{#4}}{}%
+ \DefineFamilyKey[{#1}]{#2}{#3}{\FamilySetCounter{#2}{#3}{#4}{##1}}%
+}
+% \end{macrocode}
+% \end{macro}
+% \begin{command}{\FamilySetCounter}
+% \changes{v3.12}{2013/11/05}{added}
+% \changes{v3.18a}{2015/07/06}{using \cs{FamilyKeyStateProcessed}}
+% \changes{v3.23}{2017/02/23}{white space replaced by \cs{relax}}
+% Set the value of a \meta{key} defined by \cs{FamilyCounterKey}:
+% \begin{quote}
+% \cs{FamilySetCounter}\marg{family}\marg{key}\marg{counter}\marg{value}
+% \end{quote}
+% Note: Before assigning the \meta{value} to the \meta{counter} tests are
+% done, if the \meta{value} can be used to be assigned to a \LaTeX{}
+% counter. If this fails a unknown value is reported.
+% \begin{macrocode}
+\newcommand*{\FamilySetCounter}[4]{%
+ \begingroup
+ \protected@edef\reserved@a{#4}%
+ \def\reserved@b{\endgroup\value{#3}=#4\relax\FamilyKeyStateProcessed}%
+ \expandafter\Ifiscount\expandafter{\reserved@a}{}{%
+ \expandafter\Ifisdimen\expandafter{\reserved@a}{}{%
+ \expandafter\Ifisskip\expandafter{\reserved@a}{}{%
+ \expandafter\Ifisnumexpr\expandafter{\reserved@a}{}{%
+ \expandafter\Ifisdimexpr\expandafter{\reserved@a}{}{%
+ \expandafter\Ifisinteger\expandafter{\reserved@a}{}{%
+ \expandafter\Ifiscounter\expandafter{\reserved@a}{%
+ \def\reserved@b{%
+ \endgroup\value{#3}=\value{#4}\FamilyKeyStateProcessed
+ }%
+ }{%
+ \def\reserved@b{%
+ \endgroup
+ \FamilyUnknownKeyValue{#1}{#2}{#4}{%
+ integer numbers, counters, lengths, skips, dimens
+ }%
+ }%
+ }%
+ }%
+ }%
+ }%
+ }%
+ }%
+ }%
+ \reserved@b
+}
+%</base>
+% \end{macrocode}
+% \end{command}
+% \end{command}
+%
+% \begin{command}{\FamilyCounterMacroKey}
+% \changes{v3.12}{2013/11/05}{added}
+% \changes{v3.15}{2014/12/03}{support for optional default}
+% Similar to \cs{FamilyCounterKey}, but it does not use a \LaTeX{} counter to
+% store the value but a macro (or command):
+% \begin{quote}
+% \cs{FamilyCounterMacroKey}\oarg{member}\marg{family}\marg{key}\oarg{default}\marg{macro}
+% \end{quote}
+% The \meta{value} will be assigned to a counter (\cnt{page}) locally and the
+% \meta{macro} is defined using the value of the counter. The \meta{macro}
+% is automatically set to \cs{z@} if it was not already defined. If it was
+% defined, the user is responsible for that it has to be a number.
+% \begin{macro}{\Family@@Counter@@Macro@@Key,\Family@Counter@Macro@Key}
+% \changes{v3.15}{2014/12/03}{added}
+% \changes{v3.37}{2022/06/28}{existence test fixed}
+% \begin{macrocode}
+%<*base>
+\newcommand*{\FamilyCounterMacroKey}[3][.\@currname.\@currext]{%
+ \kernel@ifnextchar [%]
+ {\Family@@Counter@@Macro@@Key{#1}{#2}{#3}}%
+ {\Family@Counter@Macro@Key{#1}{#2}{#3}}%
+}
+\newcommand*{\Family@@Counter@@Macro@@Key}{}
+\def\Family@@Counter@@Macro@@Key#1#2#3[#4]#5{%
+ \ifdefined#5\else\let#5\z@\fi
+ \DefineFamilyKey[{#1}]{#2}{#3}[{#4}]{\FamilySetCounterMacro{#2}{#3}{#5}{##1}}%
+}
+\newcommand*{\Family@Counter@Macro@Key}[4]{%
+ \ifdefined#4\else\let#4\z@\fi
+ \DefineFamilyKey[{#1}]{#2}{#3}{\FamilySetCounterMacro{#2}{#3}{#4}{##1}}%
+}
+% \end{macrocode}
+% \end{macro}^^A \Family@@Counter@@Macro@@Key,\Family@Counter@Macro@Key
+% \begin{command}{\FamilySetCounterMacro}
+% \changes{v3.12}{2013/11/05}{added}
+% \changes{v3.15}{2014/12/17}{\cs{aftergroup} before \cs{FamilyKeyStateProcessed}}
+% \changes{v3.18a}{2015/07/06}{fixed usage of \cs{FamilyKeyStateProcessed}}
+% \changes{v3.20}{2016/04/12}{\cs{@ifnextchar} replaced by
+% \cs{kernel@ifnextchar}}
+% Similar to \cs{FamilySetCounter} but using a macro (or command) instead of a
+% \LaTeX{} counter:
+% \begin{quote}
+% \cs{FamilySetCounterMacro}\marg{family}\marg{key}\marg{macro}\marg{value}
+% \end{quote}
+% Note, that the \meta{value} is locally assigned to a counter (\cnt{page})
+% before defining the \meta{macro} using the value of the counter.
+% \begin{macrocode}
+\newcommand*{\FamilySetCounterMacro}[4]{%
+ \begingroup
+ \FamilySetCounter{#1}{#2}{page}{#4}%
+ \ifx\FamilyKeyState\FamilyKeyStateProcessed
+ \edef\reserved@a{%
+ \unexpanded{\endgroup\def#3}%
+ {\the\value{page}}%
+ \noexpand\FamilyKeyStateProcessed
+ }%
+ \else
+ \def\reserved@a{%
+ \endgroup
+ \FamilyUnknownKeyValue{#1}{#2}{#4}{%
+ integer numbers, counters, lengths, skips, dimens
+ }%
+ }%
+ \fi
+ \reserved@a
+}
+%</base>
+% \end{macrocode}
+% \end{command}^^A \FamilySetCounterMacro
+% \end{command}^^A \FamilyCounterMacroKey
+%
+% \begin{command}{\FamilyLengthKey}
+% \changes{v3.12}{2013/11/05}{added}
+% \changes{v3.15}{2014/12/03}{optional default value}
+% \changes{v3.20}{2016/04/12}{\cs{@ifnextchar} replaced by
+% \cs{kernel@ifnextchar}}
+% Defining a \meta{key} that sets a \LaTeX{} length to a \meta{value}.
+% \begin{quote}
+% \cs{FamilyLengthKey}\oarg{member}\marg{family}\marg{key}\oarg{default}\marg{\LaTeX{} length}
+% \end{quote}
+% \meta{default} and the \meta{value} of the option has to be (almost) any
+% kind of value, that can be assigned to a \LaTeX{} length, a \TeX{} dimension
+% or a \TeX{} skip. The \meta{\LaTeX{} length} is automatically defined, if it
+% was undefined. In this case the initial value is 0.
+% \begin{macro}{\Family@@Length@@Key,\Family@Length@Key}
+% \changes{v3.15}{2014/12/03}{added}
+% \begin{macrocode}
+%<*base>
+\newcommand*{\FamilyLengthKey}[3][.\@currname.\@currext]{%
+ \kernel@ifnextchar [%]
+ {\Family@@Length@@Key{#1}{#2}{#3}}%
+ {\Family@Length@Key{#1}{#2}{#3}}%
+}
+\newcommand*{\Family@@Length@@Key}{}
+\def\Family@@Length@@Key#1#2#3[#4]#5{%
+ \ifdefined#5\else\newlength{#5}\fi
+ \DefineFamilyKey[{#1}]{#2}{#3}[{#4}]{\FamilySetLength{#2}{#3}{#5}{##1}}%
+}
+\newcommand*{\Family@Length@Key}[4]{%
+ \ifdefined#4\else\newlength{#4}\fi
+ \DefineFamilyKey[{#1}]{#2}{#3}{\FamilySetLength{#2}{#3}{#4}{##1}}%
+}
+% \end{macrocode}
+% \begin{command}{\FamilySetLength}
+% \changes{v3.12}{2013/11/05}{added}
+% \changes{v3.15}{2015/01/02}{\cs{ifglueexpr} added}
+% \changes{v3.18a}{2015/07/06}{usage of \cs{FamilyKeyStateProcessed} fixed}
+% \changes{v3.20}{2016/04/27}{expansion before testing}
+% Set the value of a \meta{key} defined by \cs{FamilyLengthKey}:
+% \begin{quote}
+% \cs{FamilySetLength}\marg{family}\marg{key}\marg{\LaTeX{} length}\marg{value}
+% \end{quote}
+% Note: Before assigning the \meta{value} to the \meta{\LaTeX{} length} it is
+% fully expanded and tests are done, if the \meta{value} can be used to be
+% assigned to a \LaTeX{} length. If this fails a unknown value is reported. If
+% the expansion or the assignment fails a \TeX{} error happens.
+% \begin{macrocode}
+\newcommand*{\FamilySetLength}[4]{%
+ \begingroup
+ \protected@edef\reserved@a{#4}%
+% \end{macrocode}
+% Together with \cs{@defaultsunits} (see below) following code, could be used:
+% \begin{macrocode}
+%<*neveruse>
+ \expandafter\Ifiscount\expandafter{\reserved@a}{%
+ \aftergroup\@firstoftwo
+ }{%
+%</neveruse>
+% \end{macrocode}
+% But currently we don't use it!
+% \begin{macrocode}
+ \expandafter\Ifisdimen\expandafter{\reserved@a}{%
+ \aftergroup\@firstoftwo
+ }{%
+ \expandafter\Ifisskip\expandafter{\reserved@a}{%
+ \aftergroup\@firstoftwo
+ }{%
+% \end{macrocode}
+% Together with \cs{@defaultsunits} (see below) following code, could be used:
+% \begin{macrocode}
+%<*neveruse>
+ \expandafter\Ifisnumexpr\expandafter{\reserved@a}{%
+ \aftergroup\@firstoftwo
+ }{%
+%</neveruse>
+% \end{macrocode}
+% But currently we don't use it!
+% \begin{macrocode}
+ \expandafter\Ifisdimexpr\expandafter{\reserved@a}{%
+ \aftergroup\@firstoftwo
+ }{%
+ \expandafter\Ifisglueexpr\expandafter{\reserved@a}{%
+ \aftergroup\@firstoftwo
+ }{%
+ \expandafter\Ifisglue\expandafter{\reserved@a}{%
+ \aftergroup\@firstoftwo
+ }{%
+ \aftergroup\@secondoftwo
+ }%
+ }%
+ }%
+%<*neveruse>
+ }%
+%</neveruse>
+ }%
+ }%
+%<*neveruse>
+ }%
+%</neveruse>
+ \endgroup
+% \end{macrocode}
+% \begin{description}
+% \item[ToDo:] Maybe something like:
+% \begin{macrocode}
+%<*neveruse>
+ {\@defaultunits#3=#4pt\relax\@nnil\FamilyKeyStateProcessed}
+%</neveruse>
+% \end{macrocode}
+% would be nice. But there are reasons I've decided not to use
+% this. Unfortunately I cannot remember the reason (and because of this I've
+% added the code as \texttt{neveruse}). So the simple assignment is used
+% instead:
+% \end{description}
+% \begin{macrocode}
+ {#3=#4\FamilyKeyStateProcessed}%
+ {%
+ \FamilyUnknownKeyValue{#1}{#2}{#4}{%
+ length values,
+%<*neveruse>
+ counters,
+%</neveruse>
+ lengths, skips, dimens
+ }%
+ }%
+}
+%</base>
+% \end{macrocode}
+% \end{command}^^A \FamilySetLength
+% \end{macro}^^A \Family@@Leng{\FamilyLengthKey}th@@Key,\Family@Length@Key
+% \end{command}^^A FamilyLengthKey
+%
+% \begin{command}{\FamilyLengthMacroKey}
+% \changes{v3.12}{2013/11/05}{added}
+% \changes{v3.15}{2014/12/03}{support for optional default}
+% \begin{command}{\FamilySetLengthMacro}
+% \changes{v3.12}{2013/11/05}{added}
+% \changes{v3.14a}{2014/11/24}{fix: \cs{@tempskipa} instead of \cs{@temskipa}}
+% \changes{v3.15}{2014/12/17}{\cs{aftergroup} before
+% \cs{FamilyKeyStateProcessed}}
+% \changes{v3.15}{2015/01/02}{\cs{ifglueexpr} added}
+% \changes{v3.18a}{2015/07/06}{usage of \cs{FamilyKeyStateProcessed} fixed}
+% \changes{v3.20}{2016/04/12}{\cs{@ifnextchar} replaced by
+% \cs{kernel@ifnextchar}}
+% \changes{v3.20}{2016/04/27}{using \cs{FamilySetLength}}
+% Similar to \cs{FamilyLengthKey}, but it does not use a \LaTeX{} counter to
+% store the value but a macro (or command):
+% \begin{quote}
+% \cs{FamilyLength MacroKey}\oarg{member}\marg{family}\marg{key}\oarg{default}\marg{macro}
+% \end{quote}
+% The \meta{value} will be assigned to a length (\len{@tempskipa}) locally and
+% the \meta{macro} is defined using the value of the length. The \meta{macro}
+% is automatically set to \cs{z@} if it was not already defined. If it was
+% defined, the user is responsible for that it has to be a valid length. Usage
+% of \cs{dimexpr} is recommended for such a definition.
+% \begin{macro}{\Family@@Length@@Macro@@Key,\Family@Length@Macro@Key}
+% \changes{v3.15}{2014/12/03}{added}
+% \begin{macrocode}
+%<*base>
+\newcommand*{\FamilyLengthMacroKey}[3][.\@currname.\@currext]{%
+ \kernel@ifnextchar [%]
+ {\Family@@Length@@Macro@@Key{#1}{#2}{#3}}%
+ {\Family@Length@Macro@Key{#1}{#2}{#3}}%
+}
+\newcommand*{\Family@@Length@@Macro@@Key}{}
+\def\Family@@Length@@Macro@@Key#1#2#3[#4]#5{%
+ \ifdefined#5\else\let#5\z@\fi
+ \DefineFamilyKey[{#1}]{#2}{#3}[{#4}]{\FamilySetLengthMacro{#2}{#3}{#5}{##1}}%
+}
+\newcommand*{\Family@Length@Macro@Key}[4]{%
+ \ifdefined#4\else\let#4\z@\fi
+ \DefineFamilyKey[{#1}]{#2}{#3}{\FamilySetLengthMacro{#2}{#3}{#4}{##1}}%
+}
+\newcommand*{\FamilySetLengthMacro}[4]{%
+ \begingroup
+ \FamilySetLength{#1}{#2}{\@tempskipa}{#4}%
+ \ifx\FamilyKeyState\FamilyKeyStateProcessed
+ \edef\reserved@a{%
+ \unexpanded{\endgroup\def#3}%
+ {\the\@tempskipa}%
+ \noexpand\FamilyKeyStateProcessed
+ }%
+ \else
+ \def\reserved@a{%
+ \endgroup
+ \FamilyUnknownKeyValue{#1}{#2}{#4}{%
+ length values, counters, lengths, skips, dimens
+ }%
+ }%
+ \fi
+ \reserved@a
+}
+%</base>
+% \end{macrocode}
+% \end{macro}^^A \Family@@Length@@Macro@@Key,\Family@Length@Macro@Key
+% \end{command}^^A \FamilySetLengthMacro
+% \end{command}^^A \FamilyLengthMacroKey
+%
+%
+% \begin{command}{\FamilyUseLengthMacroKey,\FamilySetUseLengthMacro}
+% \changes{v3.20}{2016/04/27}{added}
+% These are almost the same like \cs{FamilyLengthMacroKey} and
+% \cs{FamilySetLengthMacro}. But there is one important difference: Instead of
+% setting the \meta{macro} to the value of the temporary length, that has been
+% used for a test assignment, the \meta{macro} is defined as \meta{value}. So
+% later changes valid for the expansion and value of \meta{value} will indeed
+% change the value of \meta{macro}, when it is used.
+% \begin{macro}{\Family@@UseLength@@Macro@@Key,\Family@USeLength@Macro@Key}
+% \changes{v3.20}{2016/04/27}{added}
+% \begin{macrocode}
+%<*base>
+\newcommand*{\FamilyUseLengthMacroKey}[3][.\@currname.\@currext]{%
+ \kernel@ifnextchar [%]
+ {\Family@@UseLength@@Macro@@Key{#1}{#2}{#3}}%
+ {\Family@UseLength@Macro@Key{#1}{#2}{#3}}%
+}
+\newcommand*{\Family@@UseLength@@Macro@@Key}{}
+\def\Family@@UseLength@@Macro@@Key#1#2#3[#4]#5{%
+ \ifdefined#5\else\let#5\z@\fi
+ \DefineFamilyKey[{#1}]{#2}{#3}[{#4}]{%
+ \FamilySetUseLengthMacro{#2}{#3}{#5}{##1}%
+ }%
+}
+\newcommand*{\Family@UseLength@Macro@Key}[4]{%
+ \ifdefined#4\else\let#4\z@\fi
+ \DefineFamilyKey[{#1}]{#2}{#3}{\FamilySetUseLengthMacro{#2}{#3}{#4}{##1}}%
+}
+\newcommand*{\FamilySetUseLengthMacro}[4]{%
+ \begingroup
+ \FamilySetLength{#1}{#2}{\@tempskipa}{#4}%
+ \ifx\FamilyKeyState\FamilyKeyStateProcessed
+ \def\reserved@a{%
+ \endgroup\def#3{#4}%
+ \FamilyKeyStateProcessed
+ }%
+ \else
+ \def\reserved@a{%
+ \endgroup
+ \FamilyUnknownKeyValue{#1}{#2}{#4}{%
+ length values, counters, lengths, skips, dimens
+ }%
+ }%
+ \fi
+ \reserved@a
+}
+%</base>
+% \end{macrocode}
+% \end{macro}^^A \Family@@UseLength@@Macro@@Key,\Family@USeLength@Macro@Key
+% \end{command}^^A \FamilyUseLengthMacroKey,\FamilySetUseLengthMacro
+%
+%
+% \begin{command}{\FamilyNumericalKey}
+% \changes{v3.00}{2008/04/30}{added}
+% \changes{v3.20}{2016/04/12}{\cs{@ifnextchar} replaced by
+% \cs{kernel@ifnextchar}}
+% This is a mapping of symbolic values to numerical values:
+% \begin{quote}
+% \cs{FamilyNumericalKey}\oarg{member}\marg{family}\marg{key}\oarg{default}\marg{macro}\marg{mapping list}
+% \end{quote}
+% The \meta{mapping list} is:
+% \begin{quote}
+% \texttt{\marg{symbol$_1$}\marg{value$_1$},\marg{symbol$_2$}\marg{value$_2$}\dots}
+% \end{quote}
+% There is no need for \meta{value$_n$} and \meta{value$_m$} to be mutual
+% exclusive. So several symbols can be mapped to the same value.
+% \begin{macro}{\Family@Numerical@Key}
+% \changes{v3.00}{2008/05/28}{added}
+% \changes{v3.08b}{2011/03/31}{fixed: missing argument to \cs{ifundefined}}
+% The internal macro is used to handle the optional \meta{default} (because
+% currently we are not using \pkg{xparse}).
+% \begin{macrocode}
+%<*base>
+\newcommand*{\FamilyNumericalKey}[3][.\@currname.\@currext]{%
+ \kernel@ifnextchar [%]
+ {\Family@Numerical@Key{#1}{#2}{#3}}{\Family@Numerical@Key{#1}{#2}{#3}[]}%
+}
+\newcommand*{\Family@Numerical@Key}{}
+\def\Family@Numerical@Key#1#2#3[#4]#5#6{%
+ \@ifundefined{#5}{\@namedef{#5}{0}}{}%
+ \ifx\relax#4\relax
+ \DefineFamilyKey[{#1}]{#2}{#3}{\FamilySetNumerical{#2}{#3}{#5}{#6}{##1}}%
+ \else
+ \DefineFamilyKey[{#1}]{#2}{#3}[{#4}]{%
+ \FamilySetNumerical{#2}{#3}{#5}{#6}{##1}}%
+ \fi
+}
+% \end{macrocode}
+% \end{macro}
+% \begin{command}{\FamilySetNumerical}
+% \changes{v3.11a}{2012/05/28}{call of \cs{FamilyUnknownKeyValue} outside of
+% local group}
+% \changes{v3.25}{2017/12/04}{handling of completely empty list elements}
+% Set the value of \meta{key} defined by \cs{FamilyNumericalKey}:
+% \begin{quote}
+% \cs{FamilySetNumerical}\marg{family}\marg{key}\marg{macro}\marg{mapping list}\marg{value}
+% \end{quote}
+% \begin{macrocode}
+\newcommand*{\FamilySetNumerical}[5]{%
+ \begingroup
+ \edef\@searched{#5}%
+ \let\reserved@a=\@empty
+ \let\reserved@b=\@empty
+ \@tempswafalse
+ \@for\@valuelist:=#4\do{%
+ \ifx\@valuelist\@empty\else
+ \if@tempswa\else
+ \edef\reserved@c{\expandafter\@firstoftwo\@valuelist}%
+ \edef\reserved@a{\reserved@a\reserved@b`\reserved@c'}%
+ \edef\reserved@b{, }%
+ \ifx\reserved@c\@searched
+ \@tempswatrue
+ \edef\reserved@a{\expandafter\@secondoftwo\@valuelist}%
+ \fi
+ \fi
+ \fi
+ }%
+ \if@tempswa
+ \edef\reserved@a{\endgroup
+ \noexpand\@namedef{#3}{\reserved@a}%
+ \noexpand\FamilyKeyStateProcessed
+ }%
+ \else
+ \edef\reserved@a{\endgroup
+ \noexpand\FamilyUnknownKeyValue{#1}{#2}{#5}{\reserved@a}%
+ }%
+ \fi
+ \reserved@a
+ \let\FamilyElseValues\@empty
+}
+%</base>
+% \end{macrocode}
+% \end{command}^^A \FamilySetNumerical
+% \end{command}^^A \FamilyNumericalKey
+%
+% \begin{macro}{\KOMA@ncmdkey}
+% \changes{v3.02c}{2009/02/04}{defining the member (if needed)}
+% \changes{v3.17}{2015/03/16}{re-implemented with value storage and optional default}
+% \begin{macro}{\KOMA@@@ncmdkey,\KOMA@@ncmdkey}
+% \changes{v3.17}{2015/03/16}{added}
+% Like \cs{FamilyNumericalKey} with two important differences:
+% \begin{itemize}
+% \item The family is not an argument but always |KOMA|.
+% \item The values will in the internal value storage is replaced (on success).
+% \end{itemize}
+% Important: Don't forget to add the default to the internal value storage,
+% e.g., using \cs{KOMA@kav@add}.
+% \begin{macrocode}
+%<*koma>
+\newcommand*{\KOMA@ncmdkey}[2][.\@currname.\@currext]{%
+ \begingroup\edef\reserved@a{\noexpand\KOMA@@ncmdkey{#1}{#2}}%
+ \expandafter\endgroup\reserved@a
+}
+\newcommand*{\KOMA@@ncmdkey}[2]{%
+ \kernel@ifnextchar [%]
+ {\KOMA@@@ncmdkey{#1}{#2}}{\KOMA@@@ncmdkey{#1}{#2}[]}
+}
+\newcommand*{\KOMA@@@ncmdkey}{}
+\def\KOMA@@@ncmdkey#1#2[#3]#4#5{%
+ \@ifundefined{#4}{\@namedef{#4}{0}}{}%
+ \ifx\relax#3\relax
+ \KOMA@key[{#1}]{#2}{%
+ \KOMA@set@ncmdkey{#2}{#4}{#5}{##1}%
+ \KOMA@kav@replacevalue{#1}{#2}{##1}%
+ }%
+ \else
+ \KOMA@key[{#1}]{#2}[{#3}]{%
+ \KOMA@set@ncmdkey{#2}{#4}{#5}{##1}%
+ \KOMA@kav@replacevalue{#1}{#2}{##1}%
+ }%
+ \fi
+}
+%</koma>
+% \end{macrocode}
+% \begin{macro}{\KOMA@set@ncmdkey}
+% The corresponding set command similar to \cs{FamilySetNumerical} but again
+% the family is not an argument but always |KOMA|.
+% \begin{macrocode}
+%<*koma>
+\newcommand*{\KOMA@set@ncmdkey}{\FamilySetNumerical{KOMA}}
+%</koma>
+% \end{macrocode}
+% \end{macro}^^A \KOMA@set@ncmdkey
+% \end{macro}^^A \KOMA@@@ncmdkey,\KOMA@@ncmdkey
+% \end{macro}^^A \KOMA@ncmdkey
+%
+%
+% \begin{command}{\FamilyStringKey}
+% \changes{v3.08}{2010/11/05}{added}
+% \changes{v3.08b}{2011/03/31}{\cs{Family@String@Key} and
+% \cs{Family@@String@@Key} switched}
+% \changes{v3.20}{2016/04/12}{\cs{@ifnextchar} replaced by
+% \cs{kernel@ifnextchar}}
+% Defining a \meta{key} that defines a \meta{macro} to be a \meta{value}.
+% \begin{quote}
+% \cs{FamilyStringKey}\oarg{member}\marg{family}\marg{key}\oarg{default}\marg{macro}
+% \end{quote}
+% \meta{default} and the \meta{value} of the option should be a string (but
+% currently every value is accepted). The definition is done using
+% \cs{def}. So it doesn't matter whether the \meta{macro} is already defined.
+% \begin{macro}{\Family@String@Key,\Family@@String@@Key}
+% \changes{v3.08}{2010/11/05}{added}
+% \changes{v3.37}{2022/06/28}{state signaling fixed}
+% \begin{macrocode}
+%<*base>
+\newcommand*{\FamilyStringKey}[3][.\@currname.\@currext]{%
+ \kernel@ifnextchar [%]
+ {\Family@@String@@Key{#1}{#2}{#3}}{\Family@String@Key{#1}{#2}{#3}}%
+}
+\newcommand*{\Family@@String@@Key}{}
+\long\def\Family@@String@@Key#1#2#3[#4]#5{%
+ \DefineFamilyKey[{#1}]{#2}{#3}[{#4}]{\def#5{##1}\FamilyKeyStateProcessed}%
+}
+\newcommand{\Family@String@Key}[4]{%
+ \DefineFamilyKey[{#1}]{#2}{#3}{\def#4{##1}\FamilyKeyStateProcessed}%
+}
+%</base>
+% \end{macrocode}
+% \end{macro}^^A \Family@String@Key,\Family@@String@@Key
+% \end{command}^^A \FamilyStringKey
+%
+%
+% \begin{command}{\FamilyCSKey}
+% \changes{v3.25}{2017/12/08}{added}
+% This is similar to \cs{FamilyStringKey} but instead of a \meta{macro} a
+% \meta{command sequence} is used:
+% \begin{quote}
+% \cs{FamilyCSKey}\oarg{member}\marg{family}\marg{key}\oarg{default}\marg{command sequence}
+% \end{quote}
+% Because of this, \cs{@namedef} instead of \cs{def} is used to define the
+% corresponding \cs{\meta{command sequence}}.
+% \begin{macro}{\Family@CS@Key}
+% \changes{v3.25}{2017/12/08}{added}
+% \begin{macro}{\Family@@CS@@Key}
+% \changes{v3.25}{2017/12/08}{added}
+% \changes{v3.26}{2018/11/06}{fix: don't overwrite \cs{Family@@String@@Key}}
+% \changes{v3.37}{2022/06/28}{state signaling fixed}
+% \begin{macrocode}
+%<*base>
+\newcommand*{\FamilyCSKey}[3][.\@currname.\@currext]{%
+ \kernel@ifnextchar [%]
+ {\Family@@CS@@Key{#1}{#2}{#3}}{\Family@CS@Key{#1}{#2}{#3}}%
+}
+\newcommand*{\Family@@CS@@Key}{}
+\long\def\Family@@CS@@Key#1#2#3[#4]#5{%
+ \DefineFamilyKey[{#1}]{#2}{#3}[{#4}]{\@namedef{#5}{##1}\FamilyKeyStateProcessed}%
+}
+\newcommand{\Family@CS@Key}[4]{%
+ \DefineFamilyKey[{#1}]{#2}{#3}{\@namedef{#4}{##1}\FamilyKeyStateProcessed}%
+}
+%</base>
+% \end{macrocode}
+% \end{macro}^^A \Family@@CS@@Key
+% \end{macro}^^A \Family@CS@Key
+% \end{command}^^A \FamilyCSKey
+%
+%
+% \begin{macro}{\KOMA@DeclareDeprecatedOption}
+% \changes{v3.01a}{2008/11/20}{added}
+% \changes{v3.20}{2016/04/12}{\cs{@ifnextchar} replaced by
+% \cs{kernel@ifnextchar}}
+% Used to define a deprecated \meta{classic option} by an up-to-date
+% \meta{\pkg*{keyval} option}.
+% \begin{quote}
+% \cs{KOMA@DeclareDeprecatedOption}\oarg{package name}\marg{classic
+% option}\marg{\pkg*{keyval} option}
+% \end{quote}
+% If the \meta{package name} is omitted, \cs{KOMAClassName} is used to report
+% a class warning instead of a package warning.
+% \begin{macro}{\KOMA@@DeclareDeprecatedOption,\KOMA@@@DeclareDeprecatedOption}
+% \changes{v3.01a}{2008/11/20}{added}
+% \begin{macrocode}
+%<*koma>
+\newcommand*{\KOMA@DeclareDeprecatedOption}{%
+ \kernel@ifnextchar [%]
+ {\KOMA@@DeclareDeprecatedOption}%
+ {\KOMA@@@DeclareDeprecatedOption{\ClassWarningNoLine{\KOMAClassName}}}%
+}
+\newcommand*{\KOMA@@DeclareDeprecatedOption}[1][]{%
+ \KOMA@@@DeclareDeprecatedOption{\PackageWarningNoLine{#1}}%
+}
+\newcommand*{\KOMA@@@DeclareDeprecatedOption}[3]{%
+ \DeclareOption{#2}{\KOMA@UseDeprecatedOption{#1}{#2}{#3}}%
+}
+% \end{macrocode}
+% \begin{macro}{\KOMA@UseDeprecatedOption}
+% \changes{v3.01a}{2008/11/20}{added}
+% \changes{v3.12}{2013/03/04}{test to use \opt{version\quotechar=first}}
+% \changes{v3.12a}{2014/01/22}{test fixed}
+% \changes{v3.22}{2016/07/29}{added several \cs{detokenize}}
+% \changes{v3.37}{2022/06/21}{message text ``obsolete'' replaced by
+% ``deprecated''}
+% One more helper:
+% \begin{quote}
+% \cs{KOMA@UseDeprecatedOption}\marg{warning command}\marg{classic
+% option}\marg{\pkg*{keyval} option}
+% \end{quote}
+% Note: \meta{warning command} should either be
+% |\ClassWarningNoLine{\KOMAClassName}| or
+% \cs{PackageWarningNoLine}\marg{package name}. But you could also use
+% \cs{ClassInfoNoLine} or \cs{PackageInfoNoLine}.
+% \begin{macrocode}
+\newcommand*{\KOMA@UseDeprecatedOption}[3]{%
+ \begingroup
+ \scr@ifundefinedorrelax{KV@KOMA.\@currname.\@currext @version}{%
+ \edef\reserved@a{\noexpand\endgroup
+ \noexpand#1{%
+ You've used deprecated option `\detokenize{#2}'.\noexpand\MessageBreak
+ Usage of this option is deprecated.\noexpand\MessageBreak
+ You should simply replace `\detokenize{#2}'\noexpand\MessageBreak
+ by `\detokenize{#3}'%
+ }%
+ \noexpand\KOMAExecuteOptions{#3}%
+ \noexpand\def\noexpand\CurrentOption{\CurrentOption}%
+ }%
+ }{%
+ \edef\reserved@a{\noexpand\endgroup
+ \noexpand#1{%
+ You've used deprecated option `\detokenize{#2}'.\noexpand\MessageBreak
+ Usage of this option indicates an old document\noexpand\MessageBreak
+ and changes compatibility level using\noexpand\MessageBreak
+ `\detokenize{#3},version=first,\noexpand\MessageBreak
+ enabledeprecatedfontcommands' that may result\noexpand\MessageBreak
+ in further warnings.\noexpand\MessageBreak
+ If you don't want this, you should simply\noexpand\MessageBreak
+ replace option `\detokenize{#2}' by `\detokenize{#3}'%
+ }%
+ \noexpand\KOMAExecuteOptions{%
+ #3,version=first}%
+ \noexpand\ExecuteOptions{enabledeprecatedfontcommands}%
+ \noexpand\def\noexpand\CurrentOption{\CurrentOption}%
+ }%
+ }%
+ \reserved@a
+}
+%</koma>
+% \end{macrocode}
+% \end{macro}^^A \KOMA@UseDeprecatedOption
+% \end{macro}^^A \KOMA@@DeclareDeprecatedOption,\KOMA@@@DeclareDeprecatedOption
+% \end{macro}^^A \KOMA@DeclareDeprecatedOption
+%
+%
+% \begin{macro}{\KOMA@DeclareStandardOption}
+% \changes{v3.01a}{2008/11/21}{added}
+% \changes{v3.20}{2016/04/12}{\cs{@ifnextchar} replaced by
+% \cs{kernel@ifnextchar}}
+% This is similar to \cs{KOMA@DeclareDeprecatedOption} but is used for
+% standard options, which means options known by the standard classes.
+% \begin{quote}
+% \cs{KOMA@DeclareStandardOption}\oarg{package name}\marg{classic
+% option}\marg{\pkg*{keyval} option}
+% \end{quote}
+% For compatibility these options are not reported as deprecated, but an info
+% is added to the \file{log} file about the usage and how it could be replaced
+% by a \pkg*{keyval} option.
+% \begin{macro}{\KOMA@@DeclareStandardOption,\KOMA@@@DeclareStandardOption,
+% \KOMA@UseStandardOption}
+% \changes{v3.01a}{2008/11/21}{added}
+% \begin{macrocode}
+%<*koma>
+\newcommand*{\KOMA@DeclareStandardOption}{%
+ \kernel@ifnextchar [%]
+ {\KOMA@@DeclareStandardOption}%
+ {\KOMA@@@DeclareStandardOption{\ClassInfoNoLine{\KOMAClassName}}}%
+}
+\newcommand*{\KOMA@@DeclareStandardOption}[1][]{%
+ \KOMA@@@DeclareStandardOption{\PackageInfoNoLine{#1}}%
+}
+\newcommand*{\KOMA@@@DeclareStandardOption}[3]{%
+ \DeclareOption{#2}{\KOMA@UseStandardOption{#1}{#2}{#3}}%
+}
+\newcommand*{\KOMA@UseStandardOption}[3]{%
+ \begingroup
+ \edef\reserved@a{\noexpand\endgroup
+ \noexpand#1{%
+ You've used standard option `#2'.\noexpand\MessageBreak
+ This is correct!\noexpand\MessageBreak
+ Internally I'm using `#3'.\noexpand\MessageBreak
+ If you'd like to set the option with \string\KOMAoptions,%
+ \noexpand\MessageBreak
+ you'd have to use `#3' there\noexpand\MessageBreak
+ instead of `#2', too%
+ }%
+ \noexpand\KOMAExecuteOptions{#3}%
+ \noexpand\def\noexpand\CurrentOption{\CurrentOption}%
+ }%
+ \reserved@a
+}
+%</koma>
+% \end{macrocode}
+% \begin{macro}{\scr@sr@co}
+% \changes{v2.96}{2006/08/20}{added}
+% \changes{v3.12a}{2014/01/22}{removed}
+% \end{macro}^^A \scr@sr@co
+% \end{macro}^^A \KOMA@@@DeclareStandardOption … \KOMA@UseStandardOption
+% \end{macro}^^A \KOMA@DeclareStandardOption
+%
+%
+% \begin{macro}{\KOMA@DeclareObsoleteOption}
+% \changes{v2.96}{2006/08/20}{\cs{CurrentOption} protected}
+% \changes{v3.12}{2013/03/04}{removed}
+% \begin{macro}{\KOMA@@DeclareObsoleteOption,\KOMA@@@DeclareObsoleteOption,
+% \KOMA@iv@DeclareObsoleteOption,\KOMA@UseObsoleteOption}
+% \changes{v2.98c}{2008/02/18}{added}
+% \changes{v3.12}{2013/03/04}{removed}
+% \end{macro}^^A \KOMA@@DeclareObsoleteOption … \KOMA@UseObsoleteOption
+% \end{macro}^^A \KOMA@DeclareObsoleteOption
+%
+%
+% \begin{macro}{\KOMA@newobsoletecommand,\KOMA@newdeprecatedcommand}
+% \changes{v3.12}{2013/03/04}{\cs{KOMA@newobsoletecommand} renamed to
+% \cs{KOMA@newdeprecatedcommand}}
+% Defines a deprecated command or \meta{macro}, represented by a
+% \meta{\pkg*{keyval} option}:
+% \begin{quote}
+% \cs{KOMA@newdeprecatedcommand}\oarg{warning
+% command}\marg{macro}\marg{\pkg*{keyval} option}
+% \end{quote}
+% Note: This can be used only for macros and commands, that behave as a
+% selector. Macros or commands with arguments are not supported.
+% \begin{macro}{\KOMA@UseDeprecatedCommand,\KOMA@UseDeprecatedCommand}
+% \changes{v2.97c}{2007/04/19}{added}
+% \changes{v3.12}{2013/03/04}{\cs{KOMA@UseObsoleteCommand} renamed to
+% \cs{KOMA@UseDeprecatedCommand}}
+% \begin{macrocode}
+%<*koma>
+\newcommand*{\KOMA@newdeprecatedcommand}[3][\@gobbletwo]{%
+ \newcommand*{#2}{\KOMA@UseDeprecatedCommand{#1}{\string#2}{#3}}%
+}
+\newcommand*{\KOMA@UseDeprecatedCommand}[3]{%
+ #1{%
+ scrkbase%
+ }{%
+ You've used deprecated command `#2'.\MessageBreak
+ \protect\KOMAoptions{#3} will be used instead.\MessageBreak
+ You should also replace `#2' by `\protect\KOMAoptions{#3}'%
+ }%
+ \KOMAoptions{#3}%
+}
+%</koma>
+% \end{macrocode}
+% \end{macro}^^A \KOMA@UseDeprecatedCommand
+% \end{macro}^^A \KOMA@newdeprecatedcommand
+%
+%
+% \subsection{Do hook mechanism}
+% \label{sec:dohook}
+%
+% \changes{v3.27}{2019/02/02}{Do hook mechanism added}
+% From \KOMAScript~v3.27 there is a new general hook mechanism called ``do
+% hook mechanism''. This mechanism is mentioned to provide extended hooks for
+% package authors. All hooks newly implemented in \KOMAScript{} \emph{should}
+% use this new mechanism.
+%
+%
+% \begin{command}{\ForDoHook}
+% \changes{v3.27}{2019/02/05}{added}
+% \changes{v3.28}{2019/11/18}{\cs{ifstr} renamed to \cs{Ifstr}}
+% \changes{v3.30}{2020/03/07}{\cs{loop}\dots\cs{repeat} inside group}
+% \changes{v3.30}{2020/03/07}{using \cs{rloop} instead of \cs{loop}}
+% Arguments:
+% \begin{description}
+% \item[\meta{specificator}:]
+% \meta{string} or \meta{string}\texttt{/}\meta{specificator}
+% \item[\meta{code}:] \LaTeX{} code
+% \end{description}
+% Executes \meta{code} for earch level of a do-hook. This is a helper command
+% normally not interesting for users or package authors. However, I define it
+% in the user context to be consistent with the other do-hook commands. Note,
+% there will be two arguments appended to the \meta{code}. The first one is
+% the name of the hook, the second one the hook argument.
+% See \cs{ExecuteDoHook} as an example.
+% \begin{macrocode}
+%<*base>
+\newcommand*{\ForDoHook}[2]{%
+ \Ifstr{#1}{}{%
+ \PackageError{scrbase}{empty do-hook specificator}{%
+ You've tried to use an empty do-hook specificator,\MessageBreak
+ but do-hook specificators must not be empty.%
+ }%
+ }{%
+ \begingroup
+ \def\scr@hookrun{\endgroup}%
+ \let\scr@hookname\relax
+ \edef\scr@hookargument{#1}%
+ \rloop
+ \scr@hooksplit@specificator\scr@hookname\scr@hookargument
+ \scr@hookargument
+ \edef\scr@hookrun{%
+ \unexpanded\expandafter{\scr@hookrun}%
+ \unexpanded{#2}{\scr@hookname}{\scr@hookargument}%
+ }%
+ \ifx\scr@hookargument\@empty\else
+ \repeat
+ \scr@hookrun
+ }%
+}
+% \end{macrocode}
+% \begin{command}{\SplitDoHook}
+% \changes{v3.27}{2019/02/04}{added}
+% \changes{v3.28}{2019/11/18}{\cs{ifstr} renamed to \cs{Ifstr}}
+% Arguments:
+% \begin{description}
+% \item[\meta{specificator}:]
+% \meta{string} or \meta{string}\texttt{/}\meta{specificator}
+% \item[\meta{prefix command}:] \LaTeX{} macro
+% \item[\meta{postfix command}:] \LaTeX{} macro
+% \end{description}
+% Splits of the \emph{last} element of the \meta{specificator}. The
+% \meta{postfix command} is defined to be that last element, the \meta{prefix
+% command} is defined to be the rest.
+% \begin{macrocode}
+\newcommand*{\SplitDoHook}[3]{%
+ \Ifstr{#1}{}{%
+ \PackageWarning{scrbase}{empty do-hook specificator}%
+ \let#2\@empty\let#3\@empty
+ }{%
+ \let#2\relax
+ \edef\reserved@a{%
+ \unexpanded{\scr@hooksplit@specificator{#2}{#3}}{#1}%
+ }\reserved@a
+ }%
+}
+% \end{macrocode}
+% \begin{macro}{\scr@hooksplit@specificator}
+% \changes{v3.27}{2019/02/02}{added}
+% Split of the first string of the specificator argument, append it to
+% \cs{scr@hookname} and store the rest in \cs{scr@hookargument}. The argument
+% must not be empty!
+% \begin{macro}{\scr@@hooksplit@specificator}
+% \changes{v3.27}{2019/02/02}{added}
+% \begin{macrocode}
+\newcommand*{\scr@hooksplit@specificator}[3]{%
+ \expandafter\scr@@hooksplit@specificator\expandafter#1\expandafter#2#3/\@nil
+}
+\newcommand*{\scr@@hooksplit@specificator}{}
+\def\scr@@hooksplit@specificator#1#2#3/#4\@nil{%
+ \scr@ifundefinedorrelax{scr@hookname}{\def#1{#3}}{%
+ \edef#1{#1/#3}%
+ }%
+ \def#2{#4}%
+ \ifx#2\@empty\else \scr@@hookargument#2#4\@nil\fi
+}
+\newcommand*{\scr@@hookargument}{}
+\def\scr@@hookargument#1#2/\@nil{\def#1{#2}}%
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{command}
+% \end{command}
+%
+% \begin{command}{\ExecuteDoHook}
+% \changes{v3.27}{2019/02/02}{added}
+% Arguments:
+% \begin{description}
+% \item[\meta{specificator}:]
+% \meta{string} or \meta{string}\texttt{/}\meta{specificator}
+% \end{description}
+% Each string of the \meta{specificator} defines a hook subgroup. The
+% execution is done in a loop, first all hook elements of the first
+% \meta{string} of the \meta{specificator} are executed with the rest of the
+% \meta{specificator} as an argument. Then the hook elements of the
+% composition of the first and the second \meta{string} are executed again
+% with the rest of the \meta{specificator} as an agument and so on until the
+% hook elements of the whole \meta{specificator} has been executed with an
+% empty argument. So every hook element has to expect an argument that is
+% itself a \meta{specificator}. At each loop level the one-time hooks
+% are executed after the permanent hooks.
+% \begin{macrocode}
+\newcommand*{\ExecuteDoHook}[1]{%
+ \@ifundefined{scr@execute@dohook}{%
+ \def\scr@execute@dohook##1##2{%
+ \def\scr@hook@do####1{####1{##2}}%
+ \@nameuse{scr@dohook@##1}%
+ \@nameuse{scr@otdohook@##1}%
+ \expandafter\global\expandafter\let
+ \csname scr@otdohook@##1\endcsname\@empty
+ \let\scr@hook@do\relax
+ }%
+ \ForDoHook{#1}{\scr@execute@dohook}%
+ \let\scr@execute@dohook\relax
+ }{%
+ \PackageWarning{scrbase}{cascaded do-hook detected.\MessageBreak
+ It seems, that the do-hook `\detokenize{#1}'\MessageBreak
+ is be executed, while another do-hook is active.\MessageBreak
+ This is not allowed and therefore ignored%
+ }%
+ }%
+}
+% \end{macrocode}
+% \end{command}
+%
+% \begin{command}{\AddtoDoHook}
+% \changes{v3.27}{2019/02/02}{added}
+% Arguments:
+% \begin{description}
+% \item[\meta{specificator}:]
+% \meta{string} or \meta{string}\texttt{/}\meta{specificator}
+% \item[\meta{element}:]
+% a \LaTeX command, that expects exactly one argument.
+% \end{description}
+% For the \meta{specificator} see \cs{ExecuteDoHook}. Here you can add an
+% \meta{element} to a hook defined by the \meta{specificator}. Adding a hook
+% is local to the current group.
+% \begin{macrocode}
+\newcommand*{\AddtoDoHook}[2]{%
+ \Ifstr{#1}{}{%
+ \PackageError{scrbase}{empty hook specificator}{%
+ As hook specificators can never be empty, the first argument\MessageBreak
+ of \string\AddtoDoHook\space must expand to an not empty string.%
+ }%
+ }{%
+ \scr@ifundefinedorrelax{scr@dohook@#1}{\@namedef{scr@dohook@#1}{}}{}%
+ \expandafter\l@addto@macro\csname scr@dohook@#1\endcsname{%
+ \scr@hook@do{#2}%
+ }%
+ }%
+}
+% \end{macrocode}
+% \end{command}
+%
+% \begin{command}{\AddtoOneTimeDoHook}
+% \changes{v3.27}{2019/02/02}{added}
+% \changes{v3.28}{2019/11/18}{\cs{ifstr} renamed to \cs{Ifstr}}
+% Arguments:
+% \begin{description}
+% \item[\meta{specificator}:]
+% \meta{string} or \meta{string}\texttt{/}\meta{specificator}
+% \item[\meta{element}:]
+% a \LaTeX command, that expects exactly one argument.
+% \end{description}
+% This is almost the same as \cs{AddtoDoHook} but a hook added by this command
+% is executed only once.
+% \begin{macrocode}
+\newcommand*{\AddtoOneTimeDoHook}[2]{%
+ \Ifstr{#1}{}{%
+ \PackageError{scrbase}{empty hook specificator}{%
+ As hook specificators can never be empty, the first argument\MessageBreak
+ of \string\AddtoDoHook\space must expand to an not empty string.%
+ }%
+ }{%
+ \scr@ifundefinedorrelax{scr@otdohook@#1}{\@namedef{scr@otdohook@#1}{}}{}%
+ \expandafter\l@addto@macro\csname scr@otdohook@#1\endcsname{%
+ \scr@hook@do{#2}%
+ }%
+ }%
+}
+%</base>
+%</body>
+% \end{macrocode}
+% \end{command}
+%
+%
+% \Finale
+% \PrintChanges
+%
+\endinput
+% Local Variables:
+% mode: doctex
+% ispell-local-dictionary: "en_US"
+% eval: (flyspell-mode 1)
+% TeX-master: t
+% TeX-engine: luatex-dev
+% eval: (setcar (or (cl-member "Index" (setq-local TeX-command-list (copy-alist TeX-command-list)) :key #'car :test #'string-equal) (setq-local TeX-command-list (cons nil TeX-command-list))) '("Index" "mkindex %s" TeX-run-index nil t :help "makeindex for dtx"))
+% End: