% \iffalse meta-comment
% ======================================================================
% scrkernel-basics.dtx
% Copyright (c) Markus Kohm, 2002-2023
%
% 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 4074 2023-07-14 15:56:59Z kohm $
%%%% (run: 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}%
}
%
% \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}
%
%<*load&class&neveruse>
\KOMA@key{internalonly}[\relax]{%
\FamilyKeyStateProcessed
}
\AtEndOfClass{\RelaxFamilyKey[.\KOMAClassFileName]{KOMA}{internalonly}}%
%
%<*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}
%\KOMAProcessOptions\relax
%\FamilyProcessOptions{KOMA}\relax
%
%<*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
}
%
% \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
}
%
% \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
}
%
% \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
%
% \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}%
%
% \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
}
%
% \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
}
%
% \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
}
%
% \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.
%
%<*prepare>
%<*base>
% \begin{macrocode}
\newcommand{\IfArgIsEmpty}[1]{%
\if\relax\detokenize{#1}\relax
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi
}
% \end{macrocode}
%
%
%<*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%
}
%
% \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}
%
% \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
}
%
% \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
}
%
% \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%
}
%
% \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%
}
%
% \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%
}
%
% \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%
}
%
% \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
}
%
% \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
}
%
% \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
}
%
% \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}%
}%
}
%
% \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
}
%
% \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{}
%
% \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
}
%
% \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}{}%
}{}%
}%
}%
}%
}%
}%
}%
}%
}%
}%
}%
}%
}
%
% \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}}
%
% \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}}
%
% \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}}%
}
%
% \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}}
%
% \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}
%
% \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}
%
% \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}
%
% \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
}
%
% \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
}%
}
%
% \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
}%
}
%
% \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}%
}
%
% \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}%
}
%
% \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}%
}%
}
%
% \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
}
%
% \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}%
}
%
% \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
}
%
% \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}
% \changes{v3.39}{2022/11/11}{initial dot added automatically}
% \changes{v3.99}{2022/11/16}{do not handle deprecated initial dot}
% 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]{%
%<*!v4>
\Ifstrstart{#1}{.}{%
\PackageWarning{scrkbase}{Deprecated initial dot of member
argument\MessageBreak
of \string\KOMAExecuteOptions\space detected%
}%
\expandafter\FamilyExecuteOptions[#1]%
}{%
%!v4>
\FamilyExecuteOptions[.#1]%
% }%
{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}%
}
%
% \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}%
}
%
% \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}}
%
% \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}
% \changes{v3.39}{2022/11/11}{initial dot removed from member argument of
% \cs{KOMA@kac@defall}}
% 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}%
}%
}
%
% \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
}%
}
%
% \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}
%
% \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}
%