% \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 4051 2023-04-26 16:01:28Z 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]% }{% % \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} % %<*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}}% }% % %<*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 % % \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}}% }% % % \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 % % \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}} % % \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 } % % \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}{} % % \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 } % % \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 } % % \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}} % % \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} % \changes{v3.39}{2022/11/11}{initial dot added automatically} % 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 } % % \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}} % % \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 } % % \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 } % % \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 }{% % % \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 }{% % % \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> }% % \endgroup % \end{macrocode} % \begin{description} % \item[ToDo:] Maybe something like: % \begin{macrocode} %<*neveruse> {\@defaultunits#3=#4pt\relax\@nnil\FamilyKeyStateProcessed} % % \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, % lengths, skips, dimens }% }% } % % \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 } % % \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 } % % \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 } % % \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 } % % \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}} % % \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}% } % % \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}% } % % \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}} % \changes{v3.99}{2022/11/16}{not with \KOMAScript~4} % 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&!v4> \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 } % % \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 } % % \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}} % \changes{v3.99}{2022/11/16}{not with \KOMAScript~4} % 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&!v4> \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}% } % % \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}% }% }% } % % % \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: