% \iffalse meta-comment
% ======================================================================
% scrkernel-basics.dtx
% Copyright (c) Markus Kohm, 2002-2020
%
% 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.txt.
% ----------------------------------------------------------------------
% scrkernel-basics.dtx
% Copyright (c) Markus Kohm, 2002-2020
%
% Dieses Werk darf nach den Bedingungen der LaTeX Project Public Lizenz,
% Version 1.3c, verteilt und/oder veraendert werden.
% Die neuste Version dieser Lizenz ist
%   http://www.latex-project.org/lppl.txt
% und Version 1.3c ist Teil aller Verteilungen von LaTeX
% Version 2005/12/01 oder spaeter und dieses Werks.
%
% Dieses Werk hat den LPPL-Verwaltungs-Status "author-maintained"
% (allein durch den Autor verwaltet).
%
% Der Aktuelle Verwalter und Autor dieses Werkes ist Markus Kohm.
% 
% Dieses Werk besteht aus den in manifest.txt aufgefuehrten Dateien.
% ======================================================================
%
%%% From File: $Id: scrkernel-basics.dtx 3527 2020-09-11 09:44:32Z kohm $
%<prepare>%%%            (run: prepare)
%<option>%%%            (run: option)
%<body>%%%            (run: body)
%<load>%%%            (run: load)
%<package&prepare>\NeedsTeXFormat{LaTeX2e}[1995/06/01]
%<*dtx>
\ifx\ProvidesFile\undefined\def\ProvidesFile#1[#2]{}\fi
\begingroup
  \def\filedate$#1: #2-#3-#4 #5${\def\filedate{#2/#3/#4}}
  \filedate$Date: 2020-09-11 11:44:32 +0200 (Fri, 11 Sep 2020) $
  \def\filerevision$#1: #2 ${\def\filerevision{r#2}}
  \filerevision$Revision: 1638 $
  \xdef\fileinfo{\filedate\space\filerevision\space}
  \edef\reserved@a{%
    \noexpand\endgroup
    \noexpand\ProvidesFile{scrkernel_basics.dtx}%
                          [\filedate\space\filerevision\space
  }
\reserved@a
%</dtx>
%<*dtx|(package&prepare)>
%<package>\ProvidesPackage{%
%<package&base>  scrbase%
%<package&koma>  scrkbase%
%<package>}[%
%!KOMAScriptVersion
  package 
%<*dtx>
  source
%</dtx>
  (%
%<base>    KOMA-Script-independent
%<koma>    KOMA-Script-dependent
  basics and keyval usage)]
%</dtx|(package&prepare)>
%<*dtx>
\ifx\documentclass\undefined
  \input scrdocstrip.tex
  \@@input scrkernel-version.dtx
  \@@input scrstrip.inc
  \KOMAdefVariable{COPYRIGHTFROM}{2002}
  \generate{\usepreamble\defaultpreamble
    \file{scrbase.sty}{%
      \from{scrkernel-version.dtx}{package,scrbase}%
      \from{scrkernel-basics.dtx}{package,prepare,base}%
      \from{scrkernel-basics.dtx}{package,option,base}%
      \from{scrkernel-language.dtx}{package,option,base}%
      \from{scrkernel-basics.dtx}{package,body,base}%
      \from{scrkernel-language.dtx}{package,body,base}%
      \from{scrlogo.dtx}{logo}%
    }%
  }
  \@@input scrstrop.inc
\else
  \let\endbatchfile\relax
\fi
\endbatchfile
\documentclass{scrdoc}
\usepackage[english,ngerman]{babel}
\CodelineIndex
\RecordChanges
\GetFileInfo{scrkernel-basics.dtx}
\title{\KOMAScript{} \partname\ \texttt{\filename}%
  \footnote{Dies ist Revision \fileversion\ von Datei
    \texttt{\filename}.}}
\date{\filedate}
\author{Markus Kohm}

\begin{document}
  \maketitle
  \tableofcontents
  \DocInput{\filename}
\end{document}
%</dtx>
% \fi
%
% \selectlanguage{ngerman}
%
% \changes{v1.0}{2002/07/06}{Beginn der ersten Version}
% \changes{v3.12}{203/03/05}{Verwendung von \cs{@tempa}, \cs{@tempb},
%   \cs{@tempc} eliminiert}
% \changes{v3.32}{2020/09/11}{\textsf{scrlfile} wird nicht mehr geladen}
%
% \section{Grundlegenden \KOMAScript-Erweiterungen}
%
% Neue Versionen von \KOMAScript{} machen zunehmend Gebrauch vom
% \textsf{keyval}-Paket. Das \textsf{keyval}-Paket ist Bestandteil des
% \textsf{graphics}-Pakets und muss als solches auf allen
% \TeX-Systemen mit \LaTeX{} enthalten sein. Es genügt jedoch in
% einigen Punkten nicht den Anforderungen von \KOMAScript{}. Deshalb
% werden hier Erweiterungen vorgenommen, die von \KOMAScript-Klassen
% und \KOMAScript-Paketen verwendet werden können.
%
% Darüber hinaus werden immer mehr Teile von \KOMAScript{} von mehr als einem
% Paket oder von Paketen und Klassen verwendet. Diese grundlegenden Dinge
% wurden daher in zwei Pakete, \textsf{scrbase} (für Dinge, die auch von
% anderen Klassen und Paketen genutzt werden können) und \textsf{scrkbase}
% (für Dinge, die \KOMAScript vorbehalten bleiben), ausgegliedert. Dadurch
% werden die Pakete und Klassen selbst kleiner und die können trotzdem
% unabhängig voneinander verwendet werden. Selbstverständlich kann man dieses
% Paket auch ohne den Rest von \KOMAScript{} zum Einsatz bringen.
%
% \StopEventually{\PrintIndex\PrintChanges}
%
% \iffalse
%<*load>
% \fi
%
% \subsection{Laden des Pakets}
% Wer das Paket lädt, tut das allerdings in der Regel sogar bereits
% vor der Definition der Optionen mit:
%    \begin{macrocode}
\RequirePackage{scrkbase}[\KOMAScriptVersion]
%    \end{macrocode}
%
% \iffalse
%</load>
%<*prepare>
% \fi
%
% \subsection{\eTeX-Test}
% \changes{v3.02c}{2009/02/19}{Fehlermeldung, wenn nicht \eTeX{} verwendet
%   wird}
%
%    \begin{macrocode}
%<*base>
\begingroup
  \def\reserved@b{}%
  \def\reserved@a#1{%
    \PackageError{scrbase}{seems you are not running e-TeX#1}{%
      Since 2004 the LaTeX team recommends to use e-TeX.\MessageBreak
      KOMA-Script since version 2.95 uses several e-TeX features.\MessageBreak
      At actual systems `latex' should already use e-TeX.\MessageBreak
      At deprecated systems it may be called `elatex'.\MessageBreak
      Use either unsupported KOMA-Script up to version 2.9u or\MessageBreak
      ask you administrator for LaTeX using e-TeX#1.\MessageBreak
      Not using e-TeX#1 is a fatal error!\MessageBreak
      Processing cannot be continued!}%
    \endgroup
    \batchmode \errmessage{}\csname @@end\endcsname\end\relax
    \csname endinput\endcsname
  }%
  \expandafter\ifx\csname eTeXversion\endcsname\relax\else
    \ifnum\eTeXversion <2
      \def\reserved@b{ V 2}%
    \else
      \let\reserved@a\endgroup
    \fi
  \fi
\expandafter\reserved@a\expandafter{\reserved@b}
%</base>
%    \end{macrocode}
%
%
% \subsection{Der abhängige Teil lädt den unabhängigen Teil}
%
%    \begin{macrocode}
%<koma>\RequirePackage{scrbase}[\KOMAScriptVersion]
%    \end{macrocode}
%
% \subsection{Laden von \textsf{scrlfile}}
%
% \textsf{scrlfile} wird benötigt, um auf das Laden anderer Pakete reagieren
% zu können. Dazu gehört beispielsweise \textsf{polyglossia} wegen dessen
% unzureichender Behandlung unterschiedlicher Sprachvarianten. Welche Version
% davon geladen wird, ist allerdings ziemlich egal.
%
%    \begin{macrocode}
%<base>\RequirePackage{scrlfile}
%    \end{macrocode}
%
% \subsection{Laden von \textsf{keyval}}
%
% Hier wird nicht nur das Paket geladen, was ruckzuck mit:
%    \begin{macrocode}
%<base>\RequirePackage{keyval}
%    \end{macrocode}
% erledigt ist.
%
% \subsection{Schutz vor Umdefinierung von 
%   \LaTeX-Kern-Anweisungen durch
%   andere Pakete}
% Einige Pakete wie \textsf{amsgen} definieren \LaTeX-Kern-Anweisungen so um,
% dass sie nicht mehr korrekt funktionieren. Ich muss dann leider dafür
% sorgen, dass \KOMAScript{} damit keine Probleme hat. Die Klassen sind dabei
% in der günstigen Situation, dass sie ggf. einfach die vorhandene Definition
% testen und übernehmen können. Die Pakete müssen hingegen dummer Weise selbst
% dafür sorgen, dass es irgendwie funktioniert.
%
% \begin{macro}{\kernel@ifstar}
% \changes{v3.20}{2016/04/12}{neu (intern)}
% Ich hoffe ja, dass der \LaTeX-Kern zukünftig diese Anweisung definiert und
% das dann auch funktioniert. Damit es aber auch mit älteren \LaTeX-Versionen
% geht, sorge ich hier vor.
%    \begin{macrocode}
%<base>\providecommand*\kernel@ifstar[1]{\kernel@ifnextchar*{\@firstoftwo{#1}}}
%    \end{macrocode}
% \end{macro}%^^A \kernel@ifstar
%
% \selectlanguage{english}
%
% \subsection{Improved \LaTeX{} kernel commands}
% The \LaTeX{} kernel already provides some useful commands, but some can be
% improved.
%
% \begin{macro}{\rloop}
% \changes{v3.30}{2020/03/07}{new}
% The \cs{loop} \dots \cs{repeat} of the \LaTeX{} kernel cannot be used inside
% a \cs{loop} \dots \cs{repeat} without extra code for preserving
% \cs{iterate}. So here is a re-entrant version that is also long. This
% version can be used even inside a \cs{loop} \dots \cs{repeat}. However you
% should not use \cs{loop} \dots \cs{repeat} inside \cs{rloop} \dots
% \cs{repeat}.
%    \begin{macrocode}
%<*base>
\newcommand{\rloop}[1]{}
\long\def\rloop#1\repeat{%
  \ifdefined\iterate
    \edef\iterate{\unexpanded{#1\relax\expandafter\iterate\fi\def\iterate}%
      {\unexpanded\expandafter{\iterate}}}%
  \else
    \def\iterate{#1\relax\expandafter\iterate\fi\let\iterate\relax}%
  \fi
  \iterate
}
%</base>
%    \end{macrocode}
% \end{macro}
% \selectlanguage{ngerman}
%
%
% \subsection{Test von Anweisungen}
%
% \begin{macro}{\scr@ifundefinedorrelax}
% \changes{v2.95c}{2006/08/12}{neu (intern)}%^^A
% \changes{v2.97b}{2007/03/08}{vermurkste Logik korrigiert}%^^A
% \changes{v2.97c}{2007/04/18}{vermurkste Funktion korrigiert}%^^A
% \changes{v2.97c}{2007/04/18}{von \cs{scr@ifundefined} umbenannt}
% \changes{v3.02c}{2009/02/19}{Sonderbehandlung für nicht \eTeX entfernt}%^^A
% Dieses Makro arbeitet wie \cs{@ifundefined}, definiert dabei aber
% ein undefiniertes Makro nicht als \cs{relax}. Es muss bereits hier definiert
% werden, weil es gleich verwendet wird.
%    \begin{macrocode}
%<*base>
\newcommand{\scr@ifundefinedorrelax}[1]{%
  \ifcsname #1\endcsname
    \expandafter\ifx\csname #1\endcsname\relax
      \expandafter\expandafter\expandafter\@firstoftwo
    \else
      \expandafter\expandafter\expandafter\@secondoftwo
    \fi
  \else
    \expandafter\@firstoftwo
  \fi
}
%</base>
%    \end{macrocode}
% \end{macro}%^^A \scr@ifundefinedorrelax
%
%
% \subsection{Erweiterung von Meldungen}
%
% \begin{macro}{\PackageErrorNoLine}
% \changes{v3.12}{2013/09/19}{neu}%^^A
% \changes{v3.28}{2019/11/23}{unsinnige Anweisung entfernt}%^^A
% Wie Falk richtig angemerkt hat, ist die Anweisung sinnlos, weil
% \cs{PackageError} gar keine Zeilennummer anhängt. Verwendet wurde die
% Anweisung nur in einem veralteten Paket.
% \end{macro}
%
%
% \subsection{Definition von KOMA-\textsf{keyval}-Schlüsseln (Basis)}
%
% Üblicherweise verwendet \KOMAScript{} für alle
% \textsf{keyval}-Schlüssel die gleiche Bereichskennung
% "`\texttt{KOMA}"'. Dadurch ist es möglich, dass Pakete die Schlüssel
% der Klassen umdefinieren und dass jeder Teil von \KOMAScript{} die
% Schlüssel jedes anderen Teils ausführen kann -- sobald sie definiert
% sind.
%
% \begin{macro}{\DefineFamily}
% \changes{v3.00}{2008/04/30}{Neue Anweisung}%^^A
% \changes{v3.20}{2016/04/12}{\cs{@ifnextchar} replaced by
%     \cs{kernel@ifnextchar}}%^^A
% \begin{macro}{\DefineFamilyMember}
% \changes{v3.00}{2008/04/30}{Neue Anweisung}%^^A
% \begin{macro}{\DefineFamilyKey}
% \changes{v3.00}{2008/04/30}{Neue Anweisung}%^^A
% \changes{v3.12}{2013/03/04}{Setzen von \cs{FamilyKeyState}}
% \begin{macro}{\scr@if@family}
% \changes{v3.00}{2008/04/30}{Neu (intern)}%^^A
% \begin{macro}{\scr@if@familymember}
% \changes{v3.00}{2008/04/30}{Neu (intern)}%^^A
% \changes{v3.27}{2019/07/19}{das leere Mitglied existiert immer}%^^A
% \begin{macro}{\scr@define@family@key}
% \changes{v3.00}{2008/04/30}{Neu (intern)}%^^A
% \begin{macro}{\scr@define@family@key@nodefault}
% \changes{v3.00}{2008/04/30}{Neu (intern)}%^^A
% \changes{v3.18a}{2015/07/03}{fehlendes \% ergänzt}%^^A
% Familie, Familienmitglied und \textsf{keyval}-Schlüssel für ein
% Familienmitglied definieren. Dabei wird als Familienmitglied per Default der
% (Datei-)Name des aktuellen Pakets bzw. der aktuellen Klasse verwendet.
%    \begin{macrocode}
%<*base>
\newcommand*{\DefineFamily}[1]{%
  \scr@ifundefinedorrelax{#1@key@familylist}{%
    \@namedef{#1@key@familylist}{}%
  }{}%
}
\newcommand*{\scr@if@family}[2]{%
  \scr@ifundefinedorrelax{#1@key@familylist}{%
    \PackageError{scrbase}{%
      unknown family `#1'%
    }{%
      You've tried to #2 for family `#1'.\MessageBreak
      This my be done only for previous defined families.\MessageBreak
      You should call `\string\DefineFamily{#1}' first.%
    }%
  }%
}
\newcommand*{\DefineFamilyMember}[2][.\@currname.\@currext]{%
  \scr@if@family{#2}{define a family member}{%
    \edef\reserved@a{%
      \noexpand\in@{#2#1,}{\csname #2@key@familylist\endcsname}}%
    \reserved@a
    \ifin@\else
      \expandafter\edef\csname #2@key@familylist\endcsname{%
        \@nameuse{#2@key@familylist}#2#1,}%
    \fi
  }%
}
\newcommand*{\scr@if@familymember}[3]{%
  \scr@if@family{#2}{#3}{%
    \IfArgIsEmpty{#1}{%
      \@firstofone
    }{%
      \edef\reserved@a{%
        \noexpand\in@{#2#1,}{\csname #2@key@familylist\endcsname}}%
      \reserved@a
      \ifin@
        \expandafter\@firstofone
      \else
        \PackageError{scrbase}{%
          unknown member `#1' at family `#2'%
        }{%
          You've tried to #3 for member `#1' of family `#2'.\MessageBreak
          This my be done only for previous defined family members.\MessageBreak
          You should call `\string\DefineFamilyMember[{#1}]{#2}' first.%
        }%
        \expandafter\@gobble
      \fi
    }%
  }%
}
\newcommand*{\DefineFamilyKey}[3][.\@currname.\@currext]{%
  \kernel@ifnextchar[%]
  {%
    \edef\reserved@a{#1}%
    \expandafter\scr@define@family@key
    \expandafter{\reserved@a}{#2}{#3}%
  }{%
    \edef\reserved@a{#1}%
    \expandafter\scr@define@family@key@nodefault
    \expandafter{\reserved@a}{#2}{#3}%
  }%
}
\newcommand{\scr@define@family@key}{}
\long\def\scr@define@family@key#1#2#3[#4]#5{%
  \scr@if@familymember{#1}{#2}{define a key}{%
    \define@key{#2#1}{#3}[{#4}]{%
      \def\FamilyOfKey{#2}\def\FamilyMemberOfKey{#1}%
      \FamilyKeyStateUnknown
      #5%
      \def\FamilyOfKey{#2}\def\FamilyMemberOfKey{#1}%
    }%
  }%
}
\newcommand{\scr@define@family@key@nodefault}[4]{%
  \scr@if@familymember{#1}{#2}{define a key}{%
    \define@key{#2#1}{#3}{%
      \def\FamilyOfKey{#2}\def\FamilyMemberOfKey{#1}%
      \FamilyKeyStateUnknown
      #4%
      \def\FamilyOfKey{#2}\def\FamilyMemberOfKey{#1}%
    }%
    \@namedef{KV@#2#1@#3@default}{%
      \def\FamilyOfKey{#2}\def\FamilyMemberOfKey{#1}%
      \FamilyKeyStateNeedValue
    }%
  }%
}
%</base>
%    \end{macrocode}
% \end{macro}%^^A \scr@define@family@key@nodefault
% \end{macro}%^^A \scr@define@family@key
% \end{macro}%^^A \scr@if@familymember
% \end{macro}%^^A \scr@if@family
% \end{macro}%^^A \DefineFamilyKey
% \end{macro}%^^A \DefineFamilyMember
% \end{macro}%^^A \DefineFamily
%
% \begin{macro}{\RelaxFamilyKey}
% \changes{v3.15}{2014/12/03}{neue Anweisung}%^^A
% Undefiniert einen Schlüssel. Irgendwelche Hilfsmakros werden dabei nicht
% angetastet. Stattdessen wird nur der Schlüssel selbst und ggf. ein
% Defaultwert als \cs{relax} definiert, so dass er nicht mehr verwendet werden
% kann.
%    \begin{macrocode}
%<*base>
\newcommand*{\RelaxFamilyKey}[3][.\@currname.\@currext]{%
  \scr@ifundefinedorrelax{KV@#2#1@#3}{}{%
    \expandafter\let\csname KV@#2#1@#3\endcsname\relax
  }%
  \scr@ifundefinedorrelax{KV@#2#1@#3@default}{}{%
    \expandafter\let\csname KV@#2#1@#3@default\endcsname\relax
  }%
}
%</base>
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\FamilyKeyState}
% \changes{v3.12}{2013/03/04}{Neue Anweisung}%^^A
% \begin{macro}{\FamilyKeyStateProcessed}
% \changes{v3.12}{2013/03/04}{Neue Anweisung}%^^A
% \begin{macro}{\FamilyKeyStateUnknown}
% \changes{v3.12}{2013/03/04}{Neue Anweisung}%
% \begin{macro}{\FamilyKeyStateUnknownValue}
% \changes{v3.12}{2013/03/04}{Neue Anweisung}%
% \begin{macro}{\FamilyKeyStateNeedValue}
% \changes{v3.12}{2013/03/04}{Neue Anweisung}%
% \cs{FamilyKeyState} gibt den Status der Verarbeitung eines Schlüssels
% an. In der Voreinstellung wird der Status beim Aufruf des Schlüssels auf
% \cs{FamilyKeyStateUnknown} gesetzt, was anzeigt, dass der Zustand
% unbekannnt ist, der Schlüssel aber möglicherweise verarbeitet
% wurde. Daneben gibt es den Zustand \cs{FamilyKeyStateProcessed}, der
% anzeigt, dass der Schlüssel komplett verarbeitet wurde. Alternativ kann
% das Makro einen Text enthalten, der ggf. Teil einer Fehlermeldung, einer
% Warnung oder einer Information über Probleme bei der Verarbeitung wird. Es
% ist zu beachten, dass \cs{FamilyKeyState} nur unmittelbar nach der
% Verarbeitung gültig ist.
%    \begin{macrocode}
%<*base>
\newcommand*{\FamilyKeyState}{}
\newcommand*{\FamilyKeyStateUnknown}{%
  \let\FamilyKeyState\FamilyKeyStateUnknown
}
\newcommand*{\FamilyKeyStateUnknownValue}{%
  \let\FamilyKeyState\FamilyKeyStateUnknownValue
}
\newcommand*{\FamilyKeyStateNeedValue}{%
  \let\FamilyKeyState\FamilyKeyStateNeedValue
}
\newcommand*{\FamilyKeyStateProcessed}{%
  \let\FamilyKeyState\FamilyKeyStateProcessed
}
\let\FamilyKeyState\FamilyKeyStateUnknown
%</base>
%    \end{macrocode}
% \end{macro}%^^A \FamilyKeyStateNeedValue
% \end{macro}%^^A \FamilyKeyStateUnknownValue
% \end{macro}%^^A \FamilyKeyStateUnknown
% \end{macro}%^^A \FamilyKeyStateProcessed
% \end{macro}%^^A \FamilyKeyState
%
% \begin{macro}{\FamilyOfKey}
% \changes{v3.12}{2013/03/04}{Neue Anweisung}%^^A
% \begin{macro}{\FamilyMemberOfKey}
% \changes{v3.12}{2013/03/04}{Neue Anweisung}%^^A
% Geben innerhalb der Verarbeitung eines Schlüssels dessen Familie bzw. das
% zugehörige Familienmitglied an.
%    \begin{macrocode}
%<*base>
\newcommand*{\FamilyOfKey}{}
\newcommand*{\FamilyMemberOfKey}{}
%</base>
%    \end{macrocode}
% \end{macro}%^^A \FamilyMemberOfKey
% \end{macro}%^^A \FamilyOfKey
%
% \begin{macro}{\KOMA@key}
% \changes{v2.97c}{2007/04/19}{neues optionales Argument}%^^A
% \changes{v3.17}{2015/02/24}{rudimentäre Funktionalität zur Speicherung von
%     Optionen}%^^A
% \begin{macro}{\KOMA@key@familylist}
% \textsf{keyval}-Schlüssel für \KOMAScript{} werden mit \cs{KOMAkey}
% definiert, damit auch die Familie korrekt gesetzt und ggf. der Liste der
% Familien (\cs{KOMA@key@familylist}) hinzugefügt wird.
%    \begin{macrocode}
%<*koma>
\newcommand*{\KOMA@key}[1][.\@currname.\@currext]{%
  \DefineFamilyMember[{#1}]{KOMA}%
  \@ifundefined{scr@kav@KOMA#1}{\@namedef{scr@kav@KOMA#1}{}}{}%
  \DefineFamilyKey[{#1}]{KOMA}%
}
%</koma>
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\KOMA@kav@add}
% \changes{v3.17}{2015/02/24}{neu (\KOMAScript intern)}%^^A
% Dieses Makro speichert ein \texttt{key=value}-Paar in der internen Liste.
% Es ist ausschließlich für den \KOMAScript-internen Gebrauch bestimmt.
%    \begin{macrocode}
%<*koma>
\newcommand*{\KOMA@kav@add}[3]{%
  \@ifundefined{scr@kav@KOMA#1}{%
    \KOMA@internal@error\KOMA@kav@add{#1}%
  }{%
    \expandafter\l@addto@macro\csname scr@kav@KOMA#1\endcsname{\do{{#2}{#3}}}%
  }%
}
%    \end{macrocode}
%</koma>
% \end{macro}
%
% \begin{macro}{\KOMA@kav@xadd}
% \changes{v3.17}{2015/02/24}{neu (\KOMAScript intern)}%^^A
% Dieses Makro speichert ein zuvor expandiertes \texttt{key=value}-Paar in der
% internen Liste.
% Es ist ausschließlich für den \KOMAScript-internen Gebrauch bestimmt.
%    \begin{macrocode}
%<*koma>
\newcommand*{\KOMA@kav@xadd}[3]{%
  \@ifundefined{scr@kav@KOMA#1}{%
    \KOMA@internal@error\KOMA@kav@xadd{#1}%
  }{%
    \protected@edef\reserved@a{{#2}{#3}}%
    \expandafter\l@addto@macro\csname scr@kav@KOMA#1\expandafter\endcsname
    \expandafter{\expandafter\do\expandafter{\reserved@a}}%
  }%
}
%    \end{macrocode}
%</koma>
% \end{macro}
%
% \begin{macro}{\KOMA@kav@remove}
% \changes{v3.17}{2015/02/24}{neu (\KOMAScript intern)}%^^A
% Dieses Makro entfernt ein ganz bestimmtes \texttt{key=value}-Paar aus der
% internen Liste.
% Es ist ausschließlich für den \KOMAScript-internen Gebrauch bestimmt.
%    \begin{macrocode}
%<*koma>
\newcommand*{\KOMA@kav@remove}[3]{%
  \@ifundefined{scr@kav@KOMA#1}{%
    \KOMA@internal@error\KOMA@kav@remove{#1}%
  }{%
    \begingroup
      \def\reserved@a{\endgroup\@namedef{scr@kav@KOMA#1}{}}%
      \edef\reserved@b{\detokenize{{#2}{#3}}}%
      \def\do##1{%
        \edef\reserved@c{\detokenize{##1}}%
        \ifx\reserved@b\reserved@c\else
          \l@addto@macro\reserved@a{%
            \expandafter\l@addto@macro\csname scr@kav@KOMA#1\endcsname{%
              \do{##1}%
            }%
          }%
        \fi
      }%
      \@nameuse{scr@kav@KOMA#1}%
    \reserved@a
  }%
}
%</koma>
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\KOMA@kav@removekey}
% \changes{v3.17}{2015/02/24}{neu (\KOMAScript intern)}%^^A
% Dieses Makro entfernt alle \texttt{key=value}-Paar mit einem gegebenen
% \texttt{key} aus der internen Liste.
% Es ist ausschließlich für den \KOMAScript-internen Gebrauch bestimmt.
%    \begin{macrocode}
%<*koma>
\newcommand*{\KOMA@kav@removekey}[2]{%
  \@ifundefined{scr@kav@KOMA#1}{%
    \KOMA@internal@error\KOMA@kav@removekey{#1}%
  }{%
    \begingroup
      \def\reserved@a{\endgroup\@namedef{scr@kav@KOMA#1}{}}%
      \edef\reserved@b{\detokenize{#2}}%
      \def\reserved@d##1##2{\edef\reserved@c{\detokenize{##1}}}%
      \def\do##1{%
        \reserved@d##1\relax
        \ifx\reserved@b\reserved@c\else
          \l@addto@macro\reserved@a{%
            \expandafter\l@addto@macro\csname scr@kav@KOMA#1\endcsname{%
              \do{##1}%
            }%
          }%
        \fi
      }%
      \@nameuse{scr@kav@KOMA#1}%
    \reserved@a
  }%
}
%</koma>
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\KOMA@kav@replacevalue}
% \begin{macro}{\KOMA@kav@xreplacevalue}
% \changes{v3.17}{2015/02/25}{neu (\KOMAScript intern)}%^^A
% Diese Makros dienen dazu, den Wert Schlüssels in der internen Liste
% auszutauschen. Das erste (optionale) Argument ist das Mitglied, das zweite
% ist der Name des Schlüssels, das dritte der neue Wert. Es setzt den Status
% \cs{FamilyKeyStateProcessed} voraus. Anderenfalls tut es nichts!
% Es ist ausschließlich für den \KOMAScript-internen Gebrauch bestimmt.
%    \begin{macrocode}
%<*koma>
\newcommand*{\KOMA@kav@replacevalue}[3]{%
  \ifx\FamilyKeyState\FamilyKeyStateProcessed
    \@ifundefined{scr@kav@KOMA#1}{%
      \KOMA@internal@error\KOMA@kav@replacevalue{#1}%
    }{%
      \KOMA@kav@removekey{#1}{#2}%
      \KOMA@kav@add{#1}{#2}{#3}%
    }%
  \fi
}
\newcommand*{\KOMA@kav@xreplacevalue}[3]{%
  \ifx\FamilyKeyState\FamilyKeyStateProcessed
    \@ifundefined{scr@kav@KOMA#1}{%
      \KOMA@internal@error\KOMA@kav@replacevalue{#1}%
    }{%
      \KOMA@kav@removekey{#1}{#2}%
      \KOMA@kav@xadd{#1}{#2}{#3}%
    }%
  \fi
}
%</koma>
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\KOMA@kav@replacebool}
% \changes{v3.17}{2015/02/24}{neu (\KOMAScript intern)}%^^A
% Dieses Makro dient dazu, den Wert eines if-Schlüssels in der internen Liste
% auszutauschen. Das erste (optionale) Argument ist das Mitglied, das zweite
% ist der Name des Schlüssels, das dritte der Name des Schalters. Es setzt den
% Status \cs{FamilyKeyStateProcessed} voraus. Anderenfalls tut es nichts!
% Es ist ausschließlich für den \KOMAScript-internen Gebrauch bestimmt.
%    \begin{macrocode}
%<*koma>
\newcommand*{\KOMA@kav@replacebool}[3]{%
  \ifx\FamilyKeyState\FamilyKeyStateProcessed
    \@ifundefined{scr@kav@KOMA#1}{%
      \KOMA@internal@error\KOMA@kav@replacebool{#1}%
    }{%
      \KOMA@kav@remove{#1}{#2}{false}%
      \KOMA@kav@remove{#1}{#2}{true}%
      \expandafter\ifx\csname if#3\expandafter\endcsname
                      \csname iftrue\endcsname
        \KOMA@kav@xadd{#1}{#2}{true}%
      \else
        \KOMA@kav@xadd{#1}{#2}{false}%
      \fi
    }%
  \fi
}
%</koma>
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\KOMA@kav@defall}
% \changes{v3.17}{2015/02/24}{neu (\KOMAScript intern)}%^^A
% Dieses Makro liefert eine \texttt{key=value}-Liste aller gespeicherten Paare.
% Das erste Argument ist die zu definierende Anweisung, das zweite ist das
% Mitglied.
% Es ist ausschließlich für den \KOMAScript-internen Gebrauch bestimmt.
%    \begin{macrocode}
%<*koma>
\newcommand*{\KOMA@kav@defall}[2]{%
  \@ifundefined{scr@kav@KOMA#2}{%
    \KOMA@internal@error\KOMA@kav@defall{#1}%
  }{%
    \begingroup
      \let\reserved@a\@empty
      \def\reserved@b##1##2{\l@addto@macro\reserved@a{,{##1=##2}}}%
      \def\do##1{\reserved@b##1}%
      \@nameuse{scr@kav@KOMA#2}%
      \ifx\reserved@a\@empty
        \def\reserved@b{\endgroup\let#1\@empty}%
      \else
        \edef\reserved@b{%
          \unexpanded{\endgroup\def#1}{%
            \unexpanded
            \expandafter\expandafter\expandafter{%
              \expandafter\@gobble\reserved@a}}}%
      \fi
    \reserved@b
  }%
}
%</koma>
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\KOMA@kav@defone}
% \changes{v3.17}{2015/02/25}{neu (\KOMAScript intern)}%^^A
% \changes{v3.28}{2019/11/18}{\cs{ifstrstart} umbenannt in \cs{Ifstrstart}}%^^A
% Dieses Makro liefert alle aktuellen Werte eine Schlüssels aus der
% \texttt{key=value}-Liste aller gespeicherten Paare. Falls es mehr als einen
% Wert gibt, so werden diese \cs{KOMAoption}-tauglich verknüpft. Das erste
% Argument ist die zu definierende Anweisung, das zweite ist das Mitglied
% und das dritte der Schlüssel.
% Es ist ausschließlich für den \KOMAScript-internen Gebrauch bestimmt.
%    \begin{macrocode}
%<*koma>
\newcommand*{\KOMA@kav@defone}[3]{%
  \@ifundefined{scr@kav@KOMA#2}{%
    \KOMA@internal@error\KOMA@kav@defall{#1}%
  }{%
    \begingroup
      \let\reserved@a\@empty
      \def\reserved@b##1##2{%
        \Ifstr{##1}{#3}{\l@addto@macro\reserved@a{,{##2}}}{}%
      }%
      \def\do##1{\reserved@b##1}%
      \@nameuse{scr@kav@KOMA#2}%
      \ifx\reserved@a\@empty
        \def\reserved@b{\endgroup\let#1\@empty}%
      \else
        \edef\reserved@b{%
          \unexpanded{\endgroup\def#1}{%
            \unexpanded
            \expandafter\expandafter\expandafter{%
              \expandafter\@gobble\reserved@a}}}%
      \fi
    \reserved@b
  }%
}
%</koma>
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\KOMA@internal@error}
% \changes{v3.17}{2015/02/24}{neu (\KOMAScript intern)}%^^A
% Einfach nur eine Meldung über einen internen Fehler mit der Bitte um einen
% entsprechenden Bug-Report.
%    \begin{macrocode}
%<*koma>
\newcommand*{\KOMA@internal@error}[2]{%
  \PackageError{scrkbase}{internal error using \string#1{#2}}{%
    You've found an internal error either in KOMA-Script or a third
    party\MessageBreak
    definition, that uses KOMA-Script internal macros.\MessageBreak
    Please send a bug report with a minimal but complete example,
    that\MessageBreak
    shows this error, to komascript at gmx dot info or report it
    at\MessageBreak 
    <http://www.komascript.de/forum/20> (you need an account to do so).%
  }%
}
%</koma>
%    \end{macrocode}
% \end{macro}
%
% \subsection{Optionen}
%
% Ab Version 2.97c sollen sowohl globale KOMA-Optionen als auch die
% KOMA-Optionen der jeweiligen Datei als auch die normalen Optionen in der
% Reihenfolge ausgeführt werden, in der sie angegeben wurden -- zuerst die
% globalen Optionen, dann die lokalen. Dabei werden nur die Optionen
% verwendet, die auch für das jeweilige Paket bzw. die jeweilige Klasse
% definiert wurden.
%
% \begin{macro}{\@globaloptionslist}
% \changes{v2.96}{2006/11/26}{new}%^^A
% \changes{v2.96}{2006/11/26}{Klassenoptionen durchsuchen}%^^A
% \changes{v3.20}{2016/02/06}{Entscheidung später treffen}%^^A
% Die Liste der globalen Optionen wird teilweise benötigt. Weil
% \textsl{xkeyval} dämlicherweise glaubt, es müsse alle Optionen mit
% Gleichheitszeichen aus der Liste der Klassenoptionen entfernen
% (seltsamerweise aber nicht die (x)keyval-Optionen, die ohne Wert aufgerufen
% werden, weil ihr Defaultwert verwendet werden soll), wird hier ein eigenes
% Makro definiert. Bis \KOMAScript{} 3.19a wurde auch genau hier die Zuweisung
% durchgeführt. Wenn aber \textsf{scrbase} noch vor \cs{documentclass} geladen
% wird, dann ist \cs{@classoptionslist} natürlich noch nicht gültig. Deshalb
% wird die Zuweisung, seit \KOMAScript{} 3.20 in \cs{FamilyProcessOptions}
% durchgeführt.
%    \begin{macrocode}
%<*base>
\newcommand*{\@globaloptionslist}{}
%</base>
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\FamilyProcessOptions}
% \changes{v3.00}{2008/04/30}{Neue Anweisung}%
% \changes{v3.11a}{2012/06/11}{Klassen melden falsche Werte nicht
%     selbst als Fehler, sondern informieren nur darüber}%^^A
% \changes{v3.12}{2013/03/04}{Fehlerbehandlung}%^^A
% Es ist zu beachten, dass falsche Werte für Optionen grundsätzlich nicht in
% der Verarbeitung der Optionen per Info, Warnung oder Fehler gemeldet werden
% sollten, sondern über setzen von \cs{FamilyKeyState}. Erst, wenn auch andere
% Familienmitglieder den Wert nicht verarbeiten können, ergibt sich daraus
% ggf. eine Meldung, die dann von der Verarbeitung hier erzeugt wird.
% Es wird darauf hingewiesen, dass diese Anweisung nicht reentrant ist. Das
% bedeutet, dass man es innerhalb der eigenen Ausführung nicht erneut aufrufen
% darf.
% \begin{macro}{\scr@removeunused}
% \changes{v3.10}{2011/09/12}{neu (intern)}%
% \changes{v3.12}{2013/03/04}{entfernt}%^^A
% \end{macro}%^^A \scr@removeunused
% \begin{macro}{\scr@optiontest}
% \changes{v2.97c}{2007/04/18}{neu (intern)}%
% \changes{v3.12}{2013/03/04}{entfernt}%
% \begin{macro}{\scr@pti@ntest}
% \changes{v2.97c}{2007/04/18}{neu (intern)}%
% \changes{v3.12}{2013/03/04}{entfernt}%
% \end{macro}%^^A \scr@pti@ntest
% \end{macro}%^^A \scr@optiontest
%    \begin{macrocode}
%<*base>
\newcommand*{\FamilyProcessOptions}[2][.\@currname.\@currext]{%
  \ifx\AtEndOfFamilyOptions\scr@AtEndOfFamilyOptions
    \PackageError{scrbase}{nested \string\FamilyProcessOptions\space
      detected\MessageBreak}{%
      \string\FamilyProcessOptions\space has been used while processing or
      setting options.\MessageBreak
      This is currently not allowed. You should contact the author of the
      causing\MessageBreak
      code.\MessageBreak
      This error is fatal. You should not continue.%
    }%
  \fi
%    \end{macrocode}
% \changes{v3.18}{2015/06/17}{new hooks before processing the options}%^^A
% Ab Version~3.18 werden hier außerdem zwei Haken ausgeführt. Der erste gilt
% dabei für alle Klassen und Pakete einer Familie und löscht sich nicht
% selbst. Der zweite dagegen gilt nur ein einziges Mal für dieses eine
% Mitglied.
%    \begin{macrocode}
  \scr@ifundefinedorrelax{scr@before@process@options@#2@hook}{}{%
    \@nameuse{scr@before@process@options@#2@hook}%
  }%
  \scr@ifundefinedorrelax{scr@before@process@options@#2#1@hook}{}{%
    \@nameuse{scr@before@process@options@#2#1@hook}%
    \expandafter\let\csname scr@before@process@options@#2#1@hook\endcsname
    \relax
  }%
%    \end{macrocode}
% \changes{v3.23}{2017/02/16}{Korrektur: Haken danach verwendet die Familie
%     statt des Mitglieds}%^^A
% Jetzt \cs{AtEndOfFamilyOptions} samt Haken initialisieren.
%    \begin{macrocode}
  \scr@ifundefinedorrelax{scr@after@options@#2@hook}{%
    \@namedef{scr@after@options@#2@hook}{%
%    \end{macrocode}
% Die erste Aktion im Haken wird sein, den Haken selbst zu löschen.
%    \begin{macrocode}
      \@namedef{scr@after@options@#2@hook}{}%
    }%
  }{%
    \expandafter\edef\csname scr@after@options@#2@hook\endcsname{%
%    \end{macrocode}
% Die erste Aktion im Haken wird sein, die jetzige Form des Hakens wieder
% herzustellen.
%    \begin{macrocode}
      \noexpand\@namedef{scr@after@options@#2@hook}{%
        \unexpanded\expandafter\expandafter\expandafter
        {\csname scr@after@options@#2@hook\endcsname}%
      }%
    }%
  }%
%    \end{macrocode}
% \changes{v3.23}{2017/02/16}{neuer Haken für \cs{AtEndOfFamilyOptions*}}%^^A
% Seit Version 3.23 wird hier auch der neuen Haken vor
% \cs{AtEndOfFamilyOptions*} initialisiert und ausgeführt. Erkannt wird die
% oberste Ebene hier einfach an der Definition von \cs{AtEndOfFamilyOptions},
% weil das schneller geht als die Erkennung über die Definition des Hakens
% selbst (wie sie in \cs{FamilyOptions} verwendet werden muss).
%    \begin{macrocode}
  \ifx\AtEndOfFamilyOptions\scr@AtEndOfFamilyOptions@immediate
    \@namedef{scr@after@options@#2@hook@topmost}{%
%    \end{macrocode}
% Auch dieser Haken wird so definiert, dass er sich bei seiner Ausführung als
% erstes selbst löscht. Das ist auch für rekursive Aufrufe wichtig, um tiefere
% Ebenen eindeutig von der höchsten Ebene unterscheiden zu können.
%    \begin{macrocode}
      \@namedef{scr@after@options@#2@hook@topmost}{}%
    }%
%    \end{macrocode}
% Der Top-Haken wird außerdem zusammen mit dem Zurücksetzen der Definition von
% \cs{AtEndOfFamilyOptions} in den Haken der (obersten) Ebene
% eingefügt.
%    \begin{macrocode}
    \expandafter\l@addto@macro\csname scr@after@options@#2@hook\endcsname{%
      \let\AtEndOfFamilyOptions\scr@AtEndOfFamilyOptions@immediate
      \@nameuse{scr@after@options@#2@hook@topmost}%
    }%
%    \end{macrocode}
% Natürlich darf nicht vergessen werden, den Befehl für das Befüllen der
% beiden Haken nun von der direkten Ausführung eben auf das Befüllen der Haken
% umzustellen.
%    \begin{macrocode}
    \let\AtEndOfFamilyOptions\scr@AtEndOfFamilyOptions
  \fi
%    \end{macrocode}
% Jetzt geht es weiter mit der Adaption des Codes aus \cs{ProcessOptions}.
%    \begin{macrocode}
  \let\ds@\@empty
  \edef\@curroptions{\@ptionlist{\@currname.\@currext}}%
  \ifx\@currext\@clsextension\else
%    \end{macrocode}
% Bei Klassen ist die aktuelle Optionenliste gleichzeitig die globale
% Optionenliste. Daher dürften Klassen nicht auch noch die globale Optionliste
% verarbeiten. Paket verarbeiten jedoch auch die globale Optionenliste, geben
% dazu jedoch keine Fehler oder Warnungen aus.
% \changes{v3.18}{2015/06/17}{Behandlung von undefiniertem
%     \cs{@globaloptionslist}}%^^A
% \changes{v3.20}{2016/02/06}{\cs{@globaloptionslist} immer neu zuweisen}%^^A
%    \begin{macrocode}
    \let\@globaloptionslist\@classoptionslist
    \scr@ifundefinedorrelax{XKV@classoptionslist}{%
%<trace>    \PackageInfo{scrbase}{Using \string\@classoptionslist}%
    }{%
      \ifx\XKV@classoptionslist\@empty
%<trace>        \PackageInfo{scrbase}{Using \string\@classoptionslist}%
      \else
%<trace>        \PackageInfo{scrbase}{Using \string\XKV@classoptionslist}%
        \let\@globaloptionslist\XKV@classoptionslist
      \fi
    }%
    \scr@ifundefinedorrelax{@globaloptionslist}{}{%
      \@for\CurrentOption:=\@globaloptionslist\do{%
%    \end{macrocode}
% Die Optionen werden in der Reihenfolge verarbeitet, in der sie als globale
% Optionen angegeben wurden. Dabei werden nur Optionen verarbeitet, die nicht
% leer sind und die im aktuellen Paket bekannt sind. Das sind also keine
% \textsf{keyval}-Optionen, sondern normale \LaTeX-Optionen.
%    \begin{macrocode}
        \ifx\CurrentOption\@empty\else
          \@expandtwoargs\in@{,\CurrentOption,}{,\@declaredoptions,}%
          \ifin@
            \@use@ption
            \expandafter\let\csname ds@\CurrentOption\endcsname\@empty
          \else
%    \end{macrocode}
% Wenn die Option keine \LaTeX-Option ist, kann sie noch immer eine
% \textsf{keyval}-Option sein. In diesem Fall wird geprüft, ob das
% Mitglied (\#1) eine Option in der Familie (\#2) hat. Wenn das der Fall ist,
% wird die Option unmittelbar ausgeführt und zwar einmal ohne Mitglied (also
% Optionen, die global der Familie gehören) und dann mit Mitglied. Im Fall
% einer unbekannnten Option oder eines unbekannten Wertes, geschieht hier gar
% nichts.
%    \begin{macrocode}
            \scr@ifprocess@curroption{#1}{#2}{%
              \@expandtwoargs\@removeelement\CurrentOption
              \@unusedoptionlist\@unusedoptionlist
            }{}%
          \fi
        \fi
      }%
    }%
  \fi
%    \end{macrocode}
% Sowohl für Klassen als auch für Pakete werden nun die aktuellen Optionen
% abgearbeitet. In diesem Fall ist zu beachten, dass nicht definierte Optionen
% oder unbekannte Werte für Optionen unmittelbar zu einem Fehler führen, wenn
% es sich um ein Paket handelt. Bei Klassen landet die Option hingegen in der
% Liste der nicht benutzten globalen Optionen.
%    \begin{macrocode}
  \@for\CurrentOption:=\@curroptions\do{%
%    \end{macrocode}
% \changes{v3.26}{2018/10/22}{Optionen werden für Tests etc. nicht mehr
%   vollständig expandiert}%^^A
% \changes{v3.26}{2018/10/22}{\cs{@use@ption} wird für key-value-Optionen
%   nicht mehr aufgerufen}%^^A
% Ab \KOMAScript~3.26 wird für den Test, ob eine Option als normale Option
% existiert, die Option nicht mehr komplett expandiert. Da die wirklich
% notwendige Expansion bereits erfolgt ist, verhindert das Fehler wegen
% angeblich fehlendem \cs{endcsname}. Gleichzeitig wird für key-value-Optionen
% \cs{@use@ption} nicht mehr aufgerufen, da das darin enthaltene
% |\csname ds@\CurrentOption\endcsname| dasselbe Problem hat. Stattdessen wird
% die Option nur noch aus der Liste der nicht verwendeten Optionen entfernt.
%    \begin{macrocode}
    \edef\reserved@a{\expandafter\detokenize\expandafter{\CurrentOption}}%
    \scr@ifundefinedorrelax{ds@\reserved@a}{%
      \@expandtwoargs\@removeelement\CurrentOption
      \@unusedoptionlist\@unusedoptionlist
      \scr@ifprocess@curroption{#1}{#2}{}\default@ds
    }\@use@ption
  }%
%    \end{macrocode}
% Fast zum Schluss wird wir im \LaTeX-Kern der Optionencode für alle
% deklarierten \LaTeX-Optionen gelöscht und dafür gesorgt, dass nach dem Paket
% keine unverarbeiteten Optionen mehr vorhanden sind.
%    \begin{macrocode}
  \@for\CurrentOption:=\@declaredoptions\do{%
    \expandafter\let\csname ds@\CurrentOption\endcsname\relax}%
  \let\CurrentOption\@empty
  \let\@fileswith@pti@ns\@@fileswith@pti@ns
  \AtEndOfPackage{\let\@unprocessedoptions\relax}%
%    \end{macrocode}
% Jetzt muss noch der Hook ausgeführt und wieder gelöscht werden.
% \changes{v3.23}{2017/02/16}{Korrektur: Haken danach verwendet die Familie
%     statt des Mitglieds}%^^A
%    \begin{macrocode}
  \@nameuse{scr@after@options@#2@hook}%
}
\@onlypreamble\FamilyProcessOptions
%    \end{macrocode}
% \begin{macro}{\BeforeFamilyProcessOptions}
% \changes{v3.18}{2015/06/17}{neu}
% Über diese Anweisung kann man Code unmittelbar vor Ausführung von
% \cs{FamilyProcessOptions} ausgeführt werden. Dabei muss zur Verwendung
% des Hakens weder das Mitglied noch die Familie existieren. Man kann dies
% also beispielsweise auch verwenden, um unmittelbar vor der Ausführung der
% Optionen eines Pakets oder einer Klasse einzugreifen noch bevor das Paket
% oder die Klasse geladen ist.
%    \begin{macrocode}
\newcommand*{\BeforeFamilyProcessOptions}[3][.\@currname.\@currext]{%
  \scr@ifundefinedorrelax{scr@before@process@options@#2#1@hook}{%
    \@namedef{scr@before@process@options@#2#1@hook}{#3}%
  }{%
    \expandafter\g@addto@macro
    \csname scr@before@process@options@#2#1@hook\endcsname{#3}%
  }%
}
%    \end{macrocode}
% \end{macro}%^^A \BeforeFamilyProcessOptions
% \begin{macro}{\AtEndOfFamilyOptions}
% \changes{v3.12}{2013/03/04}{Neue Anweisung}%^^A
% \changes{v3.23}{2017/02/16}{Sternvariante}%^^A
% Mit dieser Option kann innerhalb der Ausführung einer Option Material auf
% das Ende der aktuellen \cs{FamilyProcessOptions}, \cs{FamilyExecuteOptions},
% \cs{FamilyOptions} oder \cs{FamilyOption} verzögert werden. Als einziges
% Argument wird der zu verzögernde Code erwartet, der an \cs{l@addto@macro}
% delegiert wird. Die Normalvariante verzögert bei verschachtelten
% \cs{FamilyOptions} bis zum Ende der aktuellen Schachtet, die Sternvariante
% bis zum Ende der äußeren Schachtel.
% \begin{macro}{\scr@AtEndOfFamilyOptions}
% \changes{v3.12}{2013/05/29}{Neue Anweisung (intern)}%^^A
% \begin{macro}{\scr@@AtEndOfFamilyOptions}
% \changes{v3.23}{2017/02/16}{Neue Anweisung (intern)}%^^A
% \begin{macro}{\scr@AtEndOfFamilyOptions@immediate}
% \changes{v3.23}{2017/02/16}{Neue Anweisung (intern)}%^^A
%    \begin{macrocode}
\newcommand*{\scr@AtEndOfFamilyOptions}{%
  \kernel@ifstar {\scr@@AtEndOfFamilyOptions{@topmost}}%
                 {\scr@@AtEndOfFamilyOptions\@empty}%
}
\newcommand*{\scr@@AtEndOfFamilyOptions}[1]{%
  \expandafter
  \l@addto@macro\csname scr@after@options@\FamilyOfKey @hook#1\endcsname
}
\newcommand*{\scr@AtEndOfFamilyOptions@immediate}{%
  \kernel@ifstar {\@firstofone}{\@firstofone}%
}
\newcommand*{\AtEndOfFamilyOptions}{}
\let\AtEndOfFamilyOptions\scr@AtEndOfFamilyOptions@immediate
%    \end{macrocode}
% \end{macro}%^^A \scr@AtEndOfFamilyOptions@immediate
% \end{macro}%^^A \scr@@AtEndOfFamilyOptions
% \end{macro}%^^A \scr@AtEndOfFamilyOptions
% \end{macro}%^^A \AtEndOfFamilyOptions
% \begin{macro}{\scr@ifprocess@curroption}
% \changes{v3.13}{2014/01/04}{\cs{CurrentOption} innerhalb von \cs{setkeys}
%   in Klammern gesetzt}%^^A
% Dieses Makro führt eine aktuelle \textsf{keyval}-Option für das angegebene
% Mitglied (\#1) der angegebenen Familie (\#2) aus. Falls die Option keinen
% entsprechenden Wert hat, wird das vierte Argument ausgeführt, anderenfalls
% nicht. Es ist zu beachten, dass vor der Option des Mitglieds die
% Familien-Option auszuführen ist. Ggf. benötigt das Mitglied dann keine
% entsprechende Option.
%    \begin{macrocode}
\newcommand*\scr@ifprocess@curroption[2]{%
%    \end{macrocode}
% \changes{v3.26}{2018/10/22}{\cs{scr@sp@def} statt \cs{def} für das Abtrennen
%   des Schlüssels}%^^A
% Da am 21. Oktober 2018 eine Diskussion begann, die darauf hindeutet, dass
% das Entfernen der Leerzeichen in der Optionenliste sich jederzeit ändern
% könnte, wird hier (und an einer weiteren Stelle) nun \cs{scr@sp@def}
% verwendet, um den Schlüssel zu erhalten. Allerdings genügt dies nicht, falls
% irgendwann tatsächlich gar keine Leerzeichen mehr entfernt werden. Dann
% müsste nämlich der komplette Parser umgeschrieben werden. Ich bin alles
% andere als begeistert von der Tatsache, dass hier im \LaTeX-Kern Jahrzehnte
% altes Verhalten ohne Rücksicht auf Verluste zur Disposition gestellt wird.
%    \begin{macrocode}
  \def\reserved@a##1=##2\@nil{\scr@sp@def\reserved@a{##1}}%
  \expandafter\reserved@a\CurrentOption=\@nil
  \scr@ifundefinedorrelax{KV@#2@\reserved@a}{%
    \scr@ifundefinedorrelax{KV@#2#1@\reserved@a}{%
      \let\FamilyKeyState\OptionNotUsed
    }{%
      \protected@edef\reserved@b{\noexpand\setkeys{#2#1}{{\CurrentOption}}%
        \noexpand\def\noexpand\CurrentOption{\CurrentOption}}%
      \reserved@b
      \ifx\FamilyKeyState\FamilyKeyStateUnknown
        \PackageInfo{scrbase}{Unknown processing state.\MessageBreak
          Processing option `\CurrentOption'\MessageBreak
          of member `#1' of family\MessageBreak
          `#2' doesn't set\MessageBreak
          a valid state. This will be interpreted\MessageBreak
          as \string\FamilyKeyStateProcessed
        }%
        \FamilyKeyStateProcessed
      \fi
    }{%
      \let\FamilyKeyState\OptionNotUsed
    }%
  }{%
    \protected@edef\reserved@b{\noexpand\setkeys{#2}{{\CurrentOption}}%
      \noexpand\def\noexpand\CurrentOption{\CurrentOption}}%
    \reserved@b
    \ifx\FamilyKeyState\FamilyKeyStateUnknown
      \PackageInfo{scrbase}{Unknown processing state.\MessageBreak
        Processing option `\CurrentOption'\MessageBreak
        of family `#2'\MessageBreak
        doesn't set a valid state.\MessageBreak
        This will be interpreted\MessageBreak
        as \string\FamilyKeyStateProcessed
      }%
      \FamilyKeyStateProcessed
    \fi
    \def\reserved@a##1=##2\@nil{\scr@sp@def\reserved@a{##1}}%
    \expandafter\reserved@a\CurrentOption=\@nil
    \scr@ifundefinedorrelax{KV@#2#1@\reserved@a}{}{%
      \protected@edef\reserved@b{\noexpand\setkeys{#2#1}{{\CurrentOption}}%
        \noexpand\def\noexpand\CurrentOption{\CurrentOption}}%
      \ifx\FamilyKeyState\FamiliyKeyStateProcessed
        \reserved@b
        \FamilyKeyStateProcessed
      \else
        \reserved@b
        \ifx\FamilyKeyState\FamilyKeyStateUnknown
          \PackageInfo{scrbase}{Unknown processing state.\MessageBreak
            Processing option `\CurrentOption'\MessageBreak
            of member `#1' of family\MessageBreak
            `#2' doesn't set\MessageBreak
            a valid state. This will be interpreted\MessageBreak
            as \string\FamilyKeyStateProcessed
          }%
          \FamilyKeyStateProcessed
        \fi
      \fi
    }%
  }%
  \ifx\FamilyKeyState\FamilyKeyStateProcessed
    \expandafter\@firstoftwo
  \else
    \expandafter\@secondoftwo
  \fi
}
%    \end{macrocode}
% \begin{macro}{\scr@sp@def}
% \changes{v3.26}{2018/08/29}{von \texttt{tocbasic.dtx} nach
%   \texttt{scrkernel-basics.dtx} verschoben und umbenannt}%^^A
% \changes{v3.26b}{2019/01/17}{\cs{long}}%^^A
% \begin{macro}{\scr@sp@d}
% \changes{v3.26}{2018/08/29}{von \texttt{tocbasic.dtx} nach
%   \texttt{scrkernel-basics.dtx} verschoben und umbenannt}%^^A
% \begin{macro}{\scr@sp@b}
% \changes{v3.26}{2018/08/29}{von \texttt{tocbasic.dtx} nach
%   \texttt{scrkernel-basics.dtx} verschoben und umbenannt}%^^A
% \changes{v3.26b}{2019/01/17}{\cs{long}}%^^A
% \begin{macro}{\scr@sp@c}
% \changes{v3.26}{2018/08/29}{von \texttt{tocbasic.dtx} nach
%   \texttt{scrkernel-basics.dtx} verschoben und umbenannt}%^^A
% \changes{v3.26b}{2019/01/17}{\cs{long}}%^^A
% Die Hilfsanweisung \cs{scr@sp@def} definiert eine Anweisung (erstes
% Argument) mit einer Tokenliste (zweites Argument) und entfernt dabei
% führende und abschließende Leerzeichen. Die Anweisung stammt ursprünglich
% aus \textsf{keyval}. Der Rest sind Hilfsanweisungen für die Implementierung
% der Hilfsanweisung.
%    \begin{macrocode}
\def\@tempa#1{%
  \long\def\scr@sp@def##1##2{%
    \futurelet\scr@sp@tempa\scr@sp@d##2\@nil\@nil#1\@nil\relax##1}%
  \def\scr@sp@d{%
    \ifx\scr@sp@tempa\@sptoken
      \expandafter\scr@sp@b
    \else
      \expandafter\scr@sp@b\expandafter#1%
    \fi}%
  \long\def\scr@sp@b#1##1 \@nil{\scr@sp@c##1}%
}
\@tempa{ }
\long\def\scr@sp@c#1\@nil#2\relax#3{\@temptokena{#1}\edef#3{\the\@temptokena}}
%</base>
%    \end{macrocode}
% \end{macro}%^^A \scr@sp@c
% \end{macro}%^^A \scr@sp@b
% \end{macro}%^^A \scr@sp@d
% \end{macro}%^^A \scr@sp@def
% \end{macro}%^^A \scr@process@curroption
% \end{macro}%^^A \FamilyProcessOptions
%
% \begin{macro}{\KOMAProcessOptions}
% \changes{v2.97c}{2007/04/18}{neu}%
% \changes{v3.00}{2008/04/30}{kein optionales Argument mehr}%
% Diese Anweisung führt alle Optionen, sowohl normal deklarierte als auch
% keyval-Optionen eines Pakets bzw. einer Klasse in der Reihenfolge, in der
% sie verwendet wurden aus -- zuerst globale Optionen, dann lokale
% Optionen. Das entspricht der Verwendung von \cs{ProcessOptions*} mit dem
% Unterschied, dass eben auch die keyval-Optionen abgearbeitet
% werden. keyval-Optionen, die keiner einzelnen Klasse und keinem einzelnen
% Paket zugeordnet werden, werden dabei vor gleichnamigen eigenen
%  keyval-Optionen ausgeführt.
%    \begin{macrocode}
%<*koma>
\newcommand*{\KOMAProcessOptions}{\FamilyProcessOptions{KOMA}}
\@onlypreamble\KOMAProcessOptions
%</koma>
%    \end{macrocode}
% \end{macro}
%
% \iffalse
%</prepare>
%<*option>
% \fi
%
% \begin{option}{internalonly}
% \changes{v2.96}{2006/11/26}{neu}%^^A
% \changes{v2.97c}{2007/06/20}{geht auch ohne Argument}%^^A
% \changes{v3.27a}{2019/11/04}{\cs{FamilyKeyStateProcessed} ergänzt}%^^A
% \changes{v3.27a}{2019/11/04}{nur innerhalb des Pakets definiert}%^^A
% \changes{v3.27a}{2019/11/04}{temporär in den Klassen definiert}%^^A
% \changes{v3.28}{2019/11/18}{Option ist veraltet}%^^A
% \begin{macro}{\dont@let@as@internal@defined}
% \changes{v2.96}{2006/11/26}{neu (intern)}%^^A
% \changes{v3.28}{2019/11/18}{entfernt}%^^A
%    \begin{macrocode}
%<*base>
\DefineFamily{KOMA}
\DefineFamilyMember{KOMA}
\DefineFamilyKey{KOMA}{internalonly}[\relax]{%
  \PackageInfo{scrbase}{Ignoring deprecated option `internalonly'}%
  \FamilyKeyStateProcessed
}
\AtEndOfPackage{%
  \RelaxFamilyKey[.scrbase.sty]{KOMA}{internalonly}%
}
%</base>
%    \end{macrocode}
% Da \textsf{scrbase} von den Klassen bereits vor der Verarbeitung der
% Optionen geladen wird, wird die Option zwar verarbeitet aber dann trotzdem
% als unbekannt gemeldet. Das kann man notdürftig beheben, indem die Klasse
% vorrübergehend eine Dummy-Option erhält.
%    \begin{macrocode}
%</option>
%<*load&class&neveruse>
\KOMA@key{internalonly}[\relax]{%
  \FamilyKeyStateProcessed
}
\AtEndOfClass{\RelaxFamilyKey[.\KOMAClassFileName]{KOMA}{internalonly}}%
%</load&class&neveruse>
%<*option>
%    \end{macrocode}
% \end{macro}
% \end{option}
%
%
% \changes{v2.96}{2006/08/20}{Optionen werden abgearbeitet}%^^A
% \changes{v2.97c}{2007/04/18}{Optionen werden mit \cs{KOMAProcessOptions}%^^A
%   abgearbeitet}
%    \begin{macrocode}
%<koma>\KOMAProcessOptions\relax
%<base>\FamilyProcessOptions{KOMA}\relax
%    \end{macrocode}
%
% \iffalse
%</option>
%<*body>
% \fi
%
% \subsection{Ein wenig zusätzliche Mathematik für \eTeX}
%
% \begin{macro}{\XdivY}
% \changes{v3.05a}{2010/03/10}{Neu}%^^A
% Ergebnis ist erster Argument durch zweites abgerundet auf die nächst
% kleinere ganze Zahl.
%    \begin{macrocode}
%<*base>
\newcommand*{\XdivY}[2]{%
  \numexpr ( #1 + #2 / 2 ) / #2 - 1\relax
}
%</base>
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\XmodY}
% \changes{v3.05a}{2010/03/10}{Neu}%^^A
% Ergebnis ist erstes Argument modulo zweites Argument.
%    \begin{macrocode}
%<*base>
\newcommand*{\XmodY}[2]{%
  \numexpr #1 - #2 * \XdivY{#1}{#2}\relax
}
%</base>
%    \end{macrocode}
% \end{macro}
%
% \subsection{Häufig benötigte Befehle}
%
% \selectlanguage{english}%^^A
% \begin{macro}{\scr@ForEachTrimmedListElement}
% \changes{v3.27}{2019/04/16}{new (internal)}%^^A
% Executes \cs{\#2\{\meta{element}\}} for each \meta{element} of the comma
% separated list \#1. Spaces before for after \meta{element} are eliminated
% and empty elements are ignored.
%    \begin{macrocode}
%<*base>
\newcommand{\scr@ForEachTrimmedListElement}[2]{%
  \begingroup
    \def\reserved@a{\endgroup}%
    \@for \reserved@b:=#1 \do {%
      \scr@trim@spaces\reserved@b
      \ifx\reserved@b\@empty\else
        \edef\reserved@a{%
          \unexpanded\expandafter{\reserved@a#2}%
          {\unexpanded\expandafter{\reserved@b}}%
        }%
      \fi
    }%
  \reserved@a
}
%</base>
%    \end{macrocode}
% \end{macro}%^^A \scr@ForEachTrimmedListElement
% \selectlanguage{ngerman}%^^A
%
% \begin{macro}{\scr@trim@spaces}
% \changes{v3.12}{2013/11/06}{neu (intern)}%^^A
% \changes{v3.26}{2018/08/29}{von \texttt{scrkernel-language.dtx} nach
%   \texttt{scrkernel-basics.dtx} verschoben}%^^A
% Diese Hilfsanweisung entfernt führende und abschließende
% Leerzeichen. Argument ist die Anweisung, deren Inhalt von den Leerzeichen
% befreit werden soll. Gedacht ist das ganze für die Listenverarbeitung mit
% Hilfe von \cs{@for}. Als Argument wird ein Makro übergeben, in dessen
% Definition führende und abschließende space-Tokens entfernt werden sollen.
%    \begin{macrocode}
%<*base>
\newcommand\scr@trim@spaces[1]{%
  \expandafter\scr@sp@def\expandafter#1\expandafter{#1}%
}
%</base>
%    \end{macrocode}
% \end{macro}%^^A \scr@trim@space
%
% \begin{macro}{\if@atdocument}
% \changes{v2.95}{2002/12/05}{neuer Schalter}%^^A
% \begin{macro}{\@atdocumenttrue}
% \begin{macro}{\@atdocumentfalse}
% Dieser Schalter wird bei \cs{begin}\texttt{\{document\}} wahr. Er
% wird von \KOMAScript{} für Befehle verwendet, die sich
% unterschiedlich verhalten, je nachdem, ob sie in der Präambel oder
% danach aufgerufen werden.
%    \begin{macrocode}
%<*base>
\newif\if@atdocument
\AtBeginDocument{\@atdocumenttrue}
\@onlypreamble\@atdocumentrue
\@onlypreamble\@atdocumentfalse
%</base>
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\let@as@internal@defined}
% \changes{v2.95}{2002/08/19}{neu (intern)}%^^A
% \changes{v2.95c}{2006/08/12}{Warnung bei Umdefinierung}%^^A
% \changes{v2.96}{2006/11/26}{Herausreichen von internen Makros als
%   Benutzermakros kann verhindert werden}%^^A
% \changes{v2.97c}{2007/06/20}{Herausreichen von internen Makros kann
%   generell verhindert werden}%^^A
% \changes{v3.10}{2010/10/26}{\cs{ignorespaces} beim \cs{document}-Patch
%   ergänzt}
% \changes{v3.13a}{2014/08/13}{potentielle Leerzeichen durch Zeilenumbruch
%   beseitigt}%^^A
% \changes{v3.28}{2019/11/18}{entfernt}%^^A
% \end{macro}
%
% \begin{macro}{\ifundefinedorrelax}
% \changes{v2.95}{2002/08/21}{neu}%^^A
% \changes{v2.95c}{2006/08/12}{über interne Anweisung definiert}%^^A
% \changes{v2.97c}{2007/06/20}{umbenannt von \cs{ifundefined}}%^^A
% \changes{v3.28}{2019/11/18}{umbenannt in \cs{Ifundefinedorrelax}}%^^A
% \changes{v3.29}{2020/01/17}{fix of missing backslash}%^^A
% \begin{macro}{\Ifundefinedorrelax}%^^A
% Dieses Makro arbeitet wie \cs{@ifundefined}, definiert dabei aber
% ein undefiniertes Makro nicht als \cs{relax}.
%    \begin{macrocode}
%<*base>
\newcommand*{\Ifundefinedorrelax}{\scr@ifundefinedorrelax}%
%</base>
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\ifnotundefined}
% \changes{v2.95}{2002/08/21}{neu}%^^A
% \changes{v2.95c}{2006/08/12}{nutzt \eTeX{} wenn möglich}%^^A
% \changes{v3.02c}{2009/02/19}{\eTeX{} ist zwingend}%^^A
% \changes{v3.28}{2019/11/18}{umdefiniert in \cs{Ifnotundefined}}%^^A
% \begin{macro}{\Ifnotundefined}
% \changes{v3.28}{2019/11/18}{neu Umbenennung von \cs{ifnotundefinded}}%^^A
% Dieses Makro arbeitet genau umgekehrt zu \cs{ifundefined}. Manchmal
% ist es ganz nützlich, auch das zu haben. Dieses Makro heißt nicht
% \cs{ifdefined}, weil \eTeX\ bereits ein solches Primitiv bietet.
%    \begin{macrocode}
%<*base>
\providecommand*{\ifnotundefined}{%
  \PackageWarning{scrbase}{Usage of deprecated command
    `\string\ifnotundefined'.\MessageBreak
    The command has been renamed because of a\MessageBreak
    recommendation of The LaTeX Project Team.\MessageBreak
    Please replace `\string\ifnotundefined' by `\string\Ifnotundefined'%
  }%
  \Ifnotundefined
}
\newcommand{\Ifnotundefined}[1]{%
  \ifcsname #1\endcsname
    \expandafter\@firstoftwo
  \else
    \expandafter\@secondoftwo
  \fi
}
%</base>
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\ifstr}
% \changes{v2.95}{2004/07/20}{if- und then-Teil werden nicht gefressen}%^^A
% \changes{v3.04b}{2010/01/29}{\cs{edef} durch \cs{protected@edef}
%   ersetzt}%^^A
% \changes{v3.28}{2019/11/18}{umbenannt in \cs{IfStr}}%^^A
% \begin{macro}{\Ifstr}
% \changes{v3.28}{2019/11/18}{neu aus Umbenennung von \cs{ifstr}}%^^A
% Dieses Makro vergleicht zwei Tokenfolgen. Eigentlich müsste es also
% eher \cs{ifequal} oder ähnlich heißen.
%    \begin{macrocode}
%<*base>
\providecommand*{\ifstr}{%
  \PackageWarning{scrbase}{Usage of deprecated command
    `\string\ifstr'.\MessageBreak
    The command has been renamed because of a\MessageBreak
    recommendation of The LaTeX Project Team.\MessageBreak
    Please replace `\string\ifstr' by `\string\Ifstr'%
  }%
  \Ifstr
}
\newcommand\Ifstr[2]{%
  \begingroup\protected@edef\reserved@a{#1}\protected@edef\reserved@b{#2}%
  \ifx\reserved@a\reserved@b
    \endgroup\expandafter\@firstoftwo
  \else
    \endgroup\expandafter\@secondoftwo
  \fi
}
%</base>
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\Ifstrstart}
% \changes{v3.28}{2019/11/18}{neu aus Umbenennung von \cs{ifstrstart}}%^^A
% \begin{macro}{\ifstrstart}
% \changes{v3.12}{2013/11/05}{neu}%^^A
% \changes{v3.28}{2019/11/18}{\cs{ifstrstart} umbenannt in \cs{Ifstrstart}}%^^A
% Falls die Expansion des ersten Arguments mit der Expansion des zweiten
% Arguments beginnt, wird das dritte Argument ausgeführt, sonst das vierte.
%    \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}{neu (intern)}%^^A
% Hilfsmakro, damit die Argumente vollständig expandiert werden können.
%    \begin{macrocode}
\newcommand*{\@ifstrstart}[2]{%
  \def\reserved@a ##1#2##2\@nil{%
    \if\relax\detokenize{##1}\relax
      \expandafter\@firstoftwo
    \else
      \expandafter\@secondoftwo
    \fi
  }%
  \reserved@a#1#2\@nil
}
%</base>
%    \end{macrocode}
% \end{macro}%^^A \@ifstrstart
% \end{macro}%^^A \ifstrstart
% \end{macro}%^^A \Ifstrstart
%
% \begin{macro}{\IfArgIsEmpty}
% \changes{v3.19}{2015/08/29}{neu}%^^A
% \changes{v3.27}{2019/03/11}{\cs{long}}%^^A
% \changes{v3.27}{2019/07/19}{wird bereits vor den Optionen benötigt}%^^A
% Falls das erste Argument tatsächlich leer ist, wird das zweite Argument
% ausgeführt sonst das dritte.
%</body>
%<*prepare>
%<*base>
%    \begin{macrocode}
\newcommand{\IfArgIsEmpty}[1]{%
  \if\relax\detokenize{#1}\relax
    \expandafter\@firstoftwo
  \else
    \expandafter\@secondoftwo
  \fi
}
%    \end{macrocode}
%</base>
%</prepare>
%<*body>
% \end{macro}%^^A \IfArgIsEmpty
%
%
% \begin{macro}{\ifislengthprimitive}
% \changes{v3.20}{2015/10/19}{neu}%^^A
% Falls das erste Argument ggf. über mehrere Stufen hinweg zu einem Primitiv
% expandiert, das als Länge verwendet werden kann, wird das erste Argument
% ausgeführt, sonst das zweite.
%    \begin{macrocode}
%<*base>
\newcommand*{\ifislengthprimitive}[1]{%
  \IfArgIsEmpty{#1}{\@secondoftwo}{\scr@ifislengthprimitive#1\@nil}%
}
%    \end{macrocode}
% \begin{macro}{\scr@ifislengthprimitive}
% \changes{v3.20}{2015/10/19}{neu (intern)}%^^A
% \changes{v3.28}{2019/11/18}{\cs{ifstrstart} umbenannt in \cs{Ifstrstart}}%^^A
% \changes{v3.28}{2019/11/18}{\cs{ifstr} umbenannt in \cs{Ifstr}}%^^A
% Hilfsmacro, das ggf. rekusiv auf diverse Primitive prüft.
%    \begin{macrocode}
\newcommand*{\scr@ifislengthprimitive}[1]{%
  \begingroup
    \Ifstrstart{\meaning #1}{\detokenize{macro:}}{%
      \aftergroup\expandafter\aftergroup\scr@ifislengthprimitive
    }{%
      \def\reserved@c{\aftergroup\scr@secondoftwoAfterNil}%
      \@for\reserved@a:=\baselineskip,\dp,\hsize,\ht,\lineskip,%
                        \parindent,\parskip,\pdfpageheight,\pdfpagewidth,%
                        \wd,\vsize \do {%
        \expandafter\Ifstr\expandafter{\expandafter\string\reserved@a}{%
          \meaning #1%
        }{%
          \def\reserved@c{\aftergroup\scr@TestDimenAssignTillNil}%
        }%
      }%
      \reserved@c
    }%
  \endgroup
  #1%
}
%</base>
%    \end{macrocode}
% \end{macro}%^^A \scr@ifislengthprimitive
% \end{macro}%^^A \ifislengthprimitive
%
%
% \begin{macro}{\ifisdimen}
% \changes{v3.12}{2013/11/05}{neu}%^^A
% \changes{v3.20}{2015/10/19}{Reimplementierung}%^^A
% \changes{v3.28}{2019/11/19}{umdefiniert in \cs{Ifisdimen}}%^^A
% \begin{macro}{\Ifisdimen}
% \changes{v3.28}{2019/11/19}{neu aus Umdefinierung von \cs{ifisdimen}}%^^A
% Falls das erste Argument ggf. über mehrere Stufen hinweg zu einem
% \cs{dimen}-Register (und zu nichts weiterem!) expandiert, wird das erste
% Argument ausgeführt, sonst das zweite.
%    \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}{neu (intern)}%^^A
% \changes{v3.28}{2019/11/18}{\cs{ifstrstart} umbenannt in \cs{Ifstrstart}}%^^A
% Hilfsmacro, das ggf. rekusiv auf ein \cs{dimen}-Register prüft
%    \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}{neu (intern)}
% Das durch \cs{@nil} begrenzte Argument wird einer temporären Länge
% zugewiesen. Wird dabei das Argument komplett aufgebraucht, so wird das
% erste Argument nach \cs{@nil} ausgeführt, sonst das zweite. Das begrenzte
% Argument wird in jedem Fall komplett aufgebraucht.
%    \begin{macrocode}
\newcommand*\scr@TestDimenAssignTillNil{}
\def\scr@TestDimenAssignTillNil#1\@nil{%
  \begingroup
    \afterassignment\scr@AfterEndGroupIfArgIsRelaxTillNnil
    \@tempdima=#1\relax\@nnil
}
%    \end{macrocode}
% \begin{macro}{\scr@IfAfterEndgroupArgIsRelaxTillNnil}
% \changes{v3.20}{2015/10/19}{neu (intern)}
% \changes{v3.28}{2019/11/18}{\cs{ifstr} umbenannt in \cs{Ifstr}}%^^A
% \changes{v3.28}{2019/11/18}{\cs{ifstrstart} umbenannt in \cs{Ifstrstart}}%^^A
% \begin{macro}{\scr@IfArgIsRelaxAfterRelaxTillNnil}
% \changes{v3.20}{2015/10/19}{neu (intern)}
% \changes{v3.28}{2019/11/18}{\cs{ifstr} umbenannt in \cs{Ifstr}}%^^A
% \changes{v3.28}{2019/11/18}{\cs{ifstrstart} umbenannt in \cs{Ifstrstart}}%^^A
% 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@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@IfArgIsRelaxAfterRelaxTillNnil
% \end{macro}%^^A \scr@IfArgIsRelaxTillNnil
% \end{macro}%^^A \scr@TestSkipAssignTillNil
% \begin{macro}{\scr@secondoftwoAfterNil}
% \changes{v3.20}{2015/10/19}{neu (intern)}
% Das Hilfsmakro liest ein durch \cs{@nil} begrenztes Argument und führt dann
% das zweite Argument nach \cs{@nil} aus. Dabei wird auch Sorge dafür getrage,
% dass das Argument eventuell leer sein könnte, was normalerweise dazu führen
% würde, dass \cs{@nil} zum Argument selbst wird.
% \begin{macro}{\scr@@secondoftwoAfterNil}
% \changes{v3.20}{2015/10/19}{neu (intern)}
% Zu diesem Zweck wird ein zweites Hilfsmakro benötigt.
%    \begin{macrocode}
\newcommand*{\scr@secondoftwoAfterNil}{\scr@@secondoftwoAfterNil\@empty}
\newcommand*{\scr@@secondoftwoAfterNil}{}
\def\scr@@secondoftwoAfterNil#1\@nil{\@secondoftwo}
%</base>
%    \end{macrocode}
% \end{macro}%^^A \scr@@secondoftwoAfterNil
% \end{macro}%^^A \scr@secondoftwoAfterNil
% \end{macro}%^^A \Ifisdimen
% \end{macro}%^^A \ifisdimen
%
% \begin{macro}{\ifisskip}
% \changes{v3.12}{2013/11/05}{neu}%^^A
% \changes{v3.18a}{2015/07/07}{\cs{baselineskip} und \cs{parskip} werden als
%     skips akzeptiert}%^^A
% \changes{v3.20}{2015/10/19}{\cs{baselineskip} und \cs{parskip} sind keine
%     skips}%^^A
% \changes{v3.20}{2015/10/19}{Reimplementierung}%^^A
% \changes{v3.28}{2019/11/19}{umdefiniert in \cs{Ifisskip}}%^^A
% \begin{macro}{\Ifisskip}
% \changes{v3.28}{2019/11/19}{neu aus Umdefinierung von \cs{ifisskip}}%^^A
% Falls das erste Argument ggf. über mehrere Stufen hinweg zu einem
% \cs{skip}-Register (und zu nichts weiterem!) expandiert, wird das erste
% Argument ausgeführt, sonst das zweite.
%    \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}{neu (intern)}%^^A
% \changes{v3.28}{2019/11/18}{\cs{ifstrstart} umbenannt in \cs{Ifstrstart}}%^^A
% Hilfsmacro, das ggf. rekusiv auf ein \cs{skip}-Register prüft
%    \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}{neu (intern)}
% Das durch \cs{@nil} begrenzte Argument wird einer temporären Länge
% zugewiesen. Wird dabei das Argument komplett aufgebraucht, so wird das
% erste Argument nach \cs{@nil} ausgeführt, sonst das zweite. Das begrenzte
% Argument wird in jedem Fall komplett aufgebraucht.
%    \begin{macrocode}
\newcommand*\scr@TestSkipAssignTillNil{}
\def\scr@TestSkipAssignTillNil#1\@nil{%
  \begingroup
    \afterassignment\scr@AfterEndGroupIfArgIsRelaxTillNnil
    \@tempskipa=#1\relax\@nnil
}
%</base>
%    \end{macrocode}
% \end{macro}%^^A \scr@TestSkipAssignTillNil
% \end{macro}%^^A \Ifisskip
% \end{macro}%^^A \ifiskip
%
% \begin{macro}{\ifiscount}
% \changes{v3.12}{2013/11/05}{neu}%^^A
% \changes{v3.20}{2015/10/19}{Reimplementierung}%^^A
% \changes{v3.28}{2019/11/19}{umdefiniert in \cs{Ifiscount}}%^^A
% \begin{macro}{\Ifiscount}
% \changes{v3.28}{2019/11/19}{neu aus Umdefinierung von \cs{ifiscount}}%^^A
% Falls das erste Argument ggf. über mehrere Stufen hinweg zu einem
% \cs{count}-Register (und zu nichts weiterem!) expandiert, wird das erste
% Argument ausgeführt, sonst das zweite.
%    \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}{neu (intern)}%^^A
% \changes{v3.28}{2019/11/18}{\cs{ifstrstart} umbenannt in \cs{Ifstrstart}}%^^A
% Hilfsmacro, das ggf. rekusiv auf ein \cs{count}-Register prüft
%    \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}{neu (intern)}
% Das durch \cs{@nil} begrenzte Argument wird einer temporären Länge
% zugewiesen. Wird dabei das Argument komplett aufgebraucht, so wird das
% erste Argument nach \cs{@nil} ausgeführt, sonst das zweite. Das begrenzte
% Argument wird in jedem Fall komplett aufgebraucht.
%    \begin{macrocode}
\newcommand*\scr@TestCountAssignTillNil{}
\def\scr@TestCountAssignTillNil#1\@nil{%
  \begingroup
    \afterassignment\scr@AfterEndGroupIfArgIsRelaxTillNnil
    \@tempcnta=#1\relax\@nnil
}
%</base>
%    \end{macrocode}
% \end{macro}%^^A \scr@TestCountAssignTillNil
% \end{macro}%^^A \Ifiscount
% \end{macro}%^^A \ifiscount
%
%
% \begin{macro}{\ifisdimexpr}
% \changes{v3.12}{2013/11/05}{neu}%^^A
% \changes{v3.20}{2015/10/19}{Reimplementierung}%^^A
% \changes{v3.28}{2019/11/19}{umdefiniert in \cs{Ifisdimexpr}}%^^A
% \begin{macro}{\Ifisdimexpr}
% \changes{v3.28}{2019/11/19}{neu aus Umdefinierung von \cs{ifisdimexpr}}%^^A
% Falls das erste Argument ggf. über mehrere Stufen hinweg zu einer
% \cs{dimexpr} (und zu nichts weiterem!) expandiert, wird das erste
% Argument ausgeführt, sonst das zweite. Dies unterscheidet sich in einem
% wichtigen Punkt von \cs{ifisdimen}: Sollte das ganze zwar als \cs{dimexpr}
% beginnen, aber syntaktisch nicht korrekt sein, so wird dies nicht erkannt,
% sondern führt tatsächlich zu einer Fehlermeldung.
%    \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}{neu (intern)}%^^A
% \changes{v3.28}{2019/11/18}{\cs{ifstrstart} umbenannt in \cs{Ifstrstart}}%^^A
% Hilfsmacro, das ggf. rekusiv auf eine \cs{dimexpr} prüft
%    \begin{macrocode}
\newcommand*{\scr@ifisdimexpr}[1]{%
  \begingroup
    \Ifstrstart{\meaning #1}{\detokenize{macro:}}{%
      \aftergroup\expandafter\aftergroup\scr@ifisdimexpr
    }{%
      \Ifstrstart{\meaning #1}{\string\dimexpr}{%
        \aftergroup\scr@TestDimenAssignTillNil
      }{%
        \aftergroup\scr@secondoftwoAfterNil
      }%
    }%
  \endgroup
  #1%
}
%</base>
%    \end{macrocode}
% \end{macro}%^^A \scr@ifisdimexpr
% \end{macro}%^^A \Ifisdimexpr
% \end{macro}%^^A \ifisdimexpr
%
%
% \begin{macro}{\ifisglueexpr}
% \changes{v3.12}{2013/11/05}{neu}%^^A
% \changes{v3.20}{2015/10/19}{Reimplementierung}%^^A
% \changes{v3.28}{2019/11/19}{umdefiniert in \cs{Ifisglueexpr}}%^^A
% \begin{macro}{\Ifisglueexpr}
% \changes{v3.28}{2019/11/19}{neu aus Umdefinierung von \cs{ifisglueexpr}}%^^A
% Falls das erste Argument ggf. über mehrere Stufen hinweg zu einer
% \cs{glueexpr} (und zu nichts weiterem!) expandiert, wird das erste
% Argument ausgeführt, sonst das zweite. Dies unterscheidet sich in einem
% wichtigen Punkt von \cs{ifisskip}: Sollte das ganze zwar als \cs{glueexpr}
% beginnen, aber syntaktisch nicht korrekt sein, so wird dies nicht erkannt,
% sondern führt tatsächlich zu einer Fehlermeldung.
%    \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}{neu (intern)}%^^A
% \changes{v3.28}{2019/11/18}{\cs{ifstrstart} umbenannt in \cs{Ifstrstart}}%^^A
% Hilfsmacro, das ggf. rekusiv auf eine \cs{glueexpr} prüft
%    \begin{macrocode}
\newcommand*{\scr@ifisglueexpr}[1]{%
  \begingroup
    \Ifstrstart{\meaning #1}{\detokenize{macro:}}{%
      \aftergroup\expandafter\aftergroup\scr@ifisglueexpr
    }{%
      \Ifstrstart{\meaning #1}{\string\glueexpr}{%
        \aftergroup\scr@TestSkipAssignTillNil
      }{%
        \aftergroup\scr@secondoftwoAfterNil
      }%
    }%
  \endgroup
  #1%
}
%</base>
%    \end{macrocode}
% \end{macro}%^^A \scr@ifisglueexpr
% \end{macro}%^^A \Ifisglueexpr
% \end{macro}%^^A \ifisglueexpr
%
%
% \begin{macro}{\ifisnumexpr}
% \changes{v3.12}{2013/11/05}{neu}%^^A
% \changes{v3.20}{2015/10/19}{Reimplementierung}%^^A
% \changes{v3.28}{2019/11/19}{umdefiniert in \cs{Ifisnumexpr}}%^^A
% \begin{macro}{\Ifisnumexpr}
% \changes{v3.28}{2019/11/19}{neu aus Umdefinierung von \cs{ifisnumexpr}}%^^A
% Falls das erste Argument ggf. über mehrere Stufen hinweg zu einer
% \cs{numexpr} (und zu nichts weiterem!) expandiert, wird das erste
% Argument ausgeführt, sonst das zweite. Dies unterscheidet sich in einem
% wichtigen Punkt von \cs{Ifiscount}: Sollte das ganze zwar als \cs{numexpr}
% beginnen, aber syntaktisch nicht korrekt sein, so wird dies nicht erkannt,
% sondern führt tatsächlich zu einer Fehlermeldung.
%    \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}{neu (intern)}%^^A
% \changes{v3.28}{2019/11/18}{\cs{ifstrstart} umbenannt in \cs{Ifstrstart}}%^^A
% Hilfsmacro, das ggf. rekusiv auf eine \cs{numexpr} prüft
%    \begin{macrocode}
\newcommand*{\scr@ifisnumexpr}[1]{%
  \begingroup
    \Ifstrstart{\meaning #1}{\detokenize{macro:}}{%
      \aftergroup\expandafter\aftergroup\scr@ifisnumexpr
    }{%
      \Ifstrstart{\meaning #1}{\string\numexpr}{%
        \aftergroup\scr@TestCountAssignTillNil
      }{%
        \aftergroup\scr@secondoftwoAfterNil
      }%
    }%
  \endgroup
  #1%
}
%</base>
%    \end{macrocode}
% \end{macro}%^^A \scr@ifisnumexpr
% \end{macro}%^^A \Ifisnumexpr
% \end{macro}%^^A \ifisnumexpr
%
%
% \begin{macro}{\ifisdefchar}
% \changes{v3.20}{2015/10/19}{neu}%^^A
% Falls das erste Argument ggf. über mehrere Stufen hinweg zu einem mit
% \cs{chardef} definierten Wert (und zu nichts weiterem!) expandiert, wird das
% erste Argument ausgeführt, sonst das zweite. Dies unterscheidet sich in einem
% wichtigen Punkt von \cs{Ifiscount}: Sollte das ganze zwar wie ein \cs{char}
% beginnen, aber syntaktisch nicht korrekt sein, so wird dies nicht erkannt,
% sondern führt tatsächlich zu einer Fehlermeldung.
%    \begin{macrocode}
%<*base>
\newcommand*{\ifisdefchar}[1]{%
  \IfArgIsEmpty{#1}{\@secondoftwo}{\scr@ifisdefchar#1\@nil}%
}
%    \end{macrocode}
% \begin{macro}{\scr@ifisdefchar}
% \changes{v3.20}{2015/10/19}{neu (intern)}%^^A
% \changes{v3.28}{2019/11/18}{\cs{ifstrstart} umbenannt in \cs{Ifstrstart}}%^^A
% Hilfsmacro, das ggf. rekusiv auf eine \cs{char} prüft
%    \begin{macrocode}
\newcommand*{\scr@ifisdefchar}[1]{%
  \begingroup
    \Ifstrstart{\meaning #1}{\detokenize{macro:}}{%
      \aftergroup\expandafter\aftergroup\scr@ifisdefchar
    }{%
      \Ifstrstart{\meaning #1}{\string\char\string"}{%
        \aftergroup\scr@TestCountAssignTillNil
      }{%
        \aftergroup\scr@secondoftwoAfterNil
      }%
    }%
  \endgroup
  #1%
}
%</base>
%    \end{macrocode}
% \end{macro}%^^A \scr@ifisdefchar
% \end{macro}%^^A \ifisdefchar
%
%
% \begin{macro}{\ifiscounter}
% \changes{v3.12}{2013/11/05}{neu}%^^A
% \changes{v3.28}{2019/11/19}{umdefiniert in \cs{Ifiscounter}}%^^A
% \begin{macro}{\Ifiscounter}
% \changes{v3.28}{2019/11/19}{neu aus Umdefinierung von \cs{ifiscounter}}%^^A
% Falls die Expansion des ersten Arguments ein \LaTeX-Zähler ist, wird das
% zweite Argument ausgeführt, sonst das dritte.
%    \begin{macrocode}
%<*base>
\providecommand*{\ifiscounter}{%
  \PackageWarning{scrbase}{Usage of deprecated command
    `\string\ifiscounter'.\MessageBreak
    The command has been renamed because of a\MessageBreak
    recommendation of The LaTeX Project Team.\MessageBreak
    Please replace `\string\ifiscounter' by `\string\Ifiscounter'%
  }%
  \Ifiscounter
}
\newcommand*{\Ifiscounter}[1]{%
  \begingroup
    \scr@ifundefinedorrelax{c@#1}{%
      \aftergroup\@secondoftwo
    }{%
      \aftergroup\@firstoftwo
    }%
  \endgroup
}
%</base>
%    \end{macrocode}
% \end{macro}%^^A \Ifiscounter
% \end{macro}%^^A \ifiscounter
%
%
% \begin{macro}{\ifisinteger}
% \changes{v3.12}{2013/11/05}{neu}%^^A
% \changes{v3.12a}{2014/01/24}{Leerzeichenfehler korrigiert}%^^A
% \changes{v3.20}{2015/10/19}{Reimplementierung}%^^A
% \changes{v3.28}{2019/11/19}{umdefiniert in \cs{Ifisinteger}}%^^A
% \begin{macro}{\Ifisinteger}
% \changes{v3.28}{2019/11/19}{neu aus Umdefinierung von \cs{ifisinteger}}%^^A
% Falls die Expansion des ersten Arguments eine (positive oder negative) ganze
% Zahl ist, wird das zweite Argument ausgeführt, sonst das dritte.
%    \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}{neu (intern)}%^^A
% \changes{v3.28}{2019/11/18}{\cs{ifstrstart} umbenannt in \cs{Ifstrstart}}%^^A
% Hilfsmacro, das ggf. rekusiv auf ein Vorzeichen oder eine positive Zahl
% prüft.
%    \begin{macrocode}
\def\scr@ifisinteger#1{%
  \begingroup
    \Ifstrstart{\meaning #1}{\detokenize{macro:}}{%
      \aftergroup\expandafter\aftergroup\scr@ifisinteger\aftergroup#1%
    }{%
      \Ifstrstart{\meaning #1}{\detokenize{the character}}{%
        \if #1-\aftergroup\scr@ifisinteger
        \else
          \if #1+\aftergroup\scr@ifisinteger
          \else
            \ifnum 0=0\if #10\else\if #11\else\if #12\else\if #13\else
                      \if #14\else\if #15\else\if #16\else\if #17\else
                      \if #18\else\if #19\else 1\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi
                      \relax
              \aftergroup\scr@TestCountAssignTillNil
              \aftergroup#1%
            \else
              \aftergroup\scr@secondoftwoAfterNil
              \aftergroup#1%
            \fi
          \fi
        \fi
      }{%
        \Ifstrstart{\meaning #1}{\string\char\string"}{%
          \aftergroup\scr@TestCountAssignTillNil
        }{%
          \def\reserved@c{%
            \aftergroup\scr@secondoftwoAfterNil
          }%
          \@for\reserved@a:=\abovedisplayskip,\abovedisplayshortskip,%
                            \adjdemerits,%
                            \baselineskip,\belowdisplayskip,%
                            \belowdisplayshortskip,\binoppenalty,\boxmaxdepth,%
                            \brokenpenalty,%
                            \clubpenalty,\count,%
                            \dimen,\dimexpr,\doublehyphendemerits,\dp,%
                            \emergenystretch,\exhyphenpenalty,%
                            \finalhyphendemerits,%
                            \glueexpr,%
                            \hbadness,\hfuzz,\hsize,\ht,\hyphenpenalty,%
                            \lastskip,\lastpenalty,\linepenalty,%
                            \lineskip,\lineskiplimit,%
                            \maxdepth,\numexpr,%
                            \overfullrule,%
                            \parfillskip,\parindent,\parskip,%
                            \pdfpageheight,\pdfpagewidth,%
                            \predisplaypenalty,\pretolerance,%
                            \relpenalty,\widowpenalty,%
                            \skip,\splitmaxdepth,\splittopskip,%
                            \tolerance,\topskip,%
                            \wd,\vbadness,\vfuzz,\vsize 
          \do {%
            \expandafter\Ifstr\expandafter{\expandafter\string\reserved@a}{%
              \meaning #1%
            }{%
              \def\reserved@c{\aftergroup\scr@TestCountAssignTillNil}%
            }%
          }%
          \reserved@c
        }%
        \aftergroup#1%
      }%
    }%
  \endgroup
}
%</base>
%    \end{macrocode}
% \end{macro}%^^A \scr@ifisinteger
% \end{macro}%^^A \Ifisinteger
% \end{macro}%^^A \ifisinteger
%
%
% \begin{macro}{\scr@ifrelax@to@nnil}
% \changes{v3.12}{2013/11/05}{neu (intern)}%^^A
% Hilfsmakro, zur Verwendung beispielsweise nach Zuweissungen. Falls alles bis
% zum ersten \cs{@nnil} aus genau einem \cs{relax} besteht, wird das erste
% Argument ausgeführt, sonst das zweite.
%    \begin{macrocode}
%<*base>
\newcommand*{\scr@ifrelax@to@nnil}{}
\def\scr@ifrelax@to@nnil#1\@nnil{%
  \begingroup
    \def\reserved@a{#1}\def\reserved@b{\relax}%
    \ifx\reserved@a\reserved@b
      \aftergroup\@firstoftwo
    \else
      \aftergroup\@secondoftwo
    \fi
  \endgroup
}
%</base>
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\ifisdimension}
% \changes{v3.12}{2013/11/05}{neu}%^^A
% \changes{v3.12a}{2014/01/24}{Leerzeichenfehler korrigiert}%^^A
% \changes{v3.20}{2015/10/20}{Reimplementierung}%^^A
% \changes{v3.28}{2019/11/19}{umdefiniert in \cs{Ifisdimension}}%^^A
% \begin{macro}{\Ifisdimension}
% \changes{v3.28}{2019/11/19}{neu aus Umdefinierung von \cs{ifisdimension}}%^^A
% Falls die stufenweise Expansion des ersten Arguments eine (positive oder
% negative) Länge ist, wird das zweite Argument ausgeführt, sonst das
% dritte.
%    \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}{neu (intern)}
% \changes{v3.28}{2019/11/18}{\cs{ifstrstart} umbenannt in \cs{Ifstrstart}}%^^A
% \changes{v3.28}{2019/11/23}{Vorzeichenfall \texttt{+} korrigiert}%^^A
% Eigentlich wäre dieses Hilfsmakro extrem aufwändig, da eine Dimension recht
% komplex aufgebaut sein darf. Ich habe aber beschlossen, hier mit einer
% Heuristik zu Werke zu gehen: Wenn das Argument mit einer beliebigen Anzahl
% Vorzeichen, gefolgt von max. einem Punkt, Komma oder einer Ziffer oder
% gefolgt einem der für Längen zulässigen Primitiv beginnt, dann probieren wir
% eine Zuweisung. Ist diese syntaktisch nicht korrekt, kann ein Fehler die
% Folge sein. Das mag unschön sein, vereinfacht den Test aber erheblich!
%    \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}{neu (intern)}
% Das durch \cs{@nil} begrenzte Argument wird einer temporären Länge
% zugewiesen. Wird dabei das Argument komplett aufgebraucht, so wird das
% erste Argument nach \cs{@nil} ausgeführt, sonst das zweite. Das begrenzte
% Argument wird in jedem Fall komplett aufgebraucht.
%    \begin{macrocode}
\newcommand*\scr@TestDimensionAssignTillNil{}
\def\scr@TestDimensionAssignTillNil#1\@nil{%
  \begingroup
    \afterassignment\scr@AfterEndGroupIfArgIsRelaxTillptNnil
    \@tempdima=#1pt\@nnil
}
%    \end{macrocode}
% \begin{macro}{\scr@IfAfterEndgroupArgIsRelaxTillptNnil}
% \changes{v3.20}{2015/10/19}{neu (intern)}
% \changes{v3.28}{2019/11/18}{\cs{ifstr} umbenannt in \cs{Ifstr}}%^^A
% \changes{v3.28}{2019/11/18}{\cs{ifstrstart} umbenannt in \cs{Ifstrstart}}%^^A
% \begin{macro}{\scr@IfArgIsRelaxAfterRelaxTillptNnil}
% \changes{v3.20}{2015/10/19}{neu (intern)}
% \changes{v3.28}{2019/11/18}{\cs{ifstr} umbenannt in \cs{Ifstr}}%^^A
% \changes{v3.28}{2019/11/18}{\cs{ifstrstart} umbenannt in \cs{Ifstrstart}}%^^A
% Die Hilfsmakros lesen ein durch \cs{@nnil} begrenztes Argument. Falls dieses
% Argument nur aus einer Folge von \cs{relax} besteht, wird das erste Argument
% nach \cs{@nnil} ausgeführt, sonst das zweite.
%    \begin{macrocode}
\newcommand*\scr@AfterEndGroupIfArgIsRelaxTillptNnil{}
\def\scr@AfterEndGroupIfArgIsRelaxTillptNnil#1\@nnil{%
  \endgroup
  \Ifstr{\detokenize{#1}}{\detokenize{pt}}{\@firstoftwo}{%
    \Ifstrstart{\detokenize{#1}}{\detokenize{\relax}}{%
      \scr@IfArgIsRelaxAfterRelaxTillptNnil #1\@nnil
    }{\@secondoftwo}%
  }%
}
\newcommand*\scr@IfArgIsRelaxAfterRelaxTillptNnil{}
\def\scr@IfArgIsRelaxAfterRelaxTillptNnil \relax#1pt\@nnil{%
  \Ifstr{\detokenize{#1}}{\detokenize{pt}}{\@firstoftwo}{%
    \Ifstrstart{\detokenize{#1}}{\detokenize{\relax}}{%
      \scr@IfArgIsRelaxAfterRelaxTillptNnil #1\@nnil
    }{\@secondoftwo}%
  }%
}
%</base>
%    \end{macrocode}
% \end{macro}%^^A \scr@IfArgIsRelaxAfterRelaxTillptNnil
% \end{macro}%^^A \scr@IfArgIsRelaxTillptNnil
% \end{macro}%^^A \scr@DimensionSkipAssignTillNil
% \end{macro}%^^A \scr@ifisdimension
% \end{macro}%^^A \Ifisdimension
% \end{macro}%^^A \ifisdimension
%
%
% \begin{macro}{\ifisglue}
% \changes{v3.12}{2013/11/05}{neu}%^^A
% \changes{v3.12a}{2014/01/24}{Leerzeichenfehler korrigiert}%^^A
% \changes{v3.20}{2015/10/21}{Reimplementierung}%^^A
% \changes{v3.28}{2019/11/19}{umdefiniert in \cs{Ifisglue}}%^^A
% \begin{macro}{\Ifisglue}
% \changes{v3.28}{2019/11/19}{neu aus Umdefinierung von \cs{ifisglue}}%^^A
% Falls die stufenweise Expansion des ersten Arguments eine (positive oder
% negative) Länge mit Leim ist, wird das zweite Argument ausgeführt, sonst das
% dritte.
%    \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}{neu (intern)}
% \changes{v3.28}{2019/11/18}{\cs{ifstrstart} umbenannt in
%   \cs{Ifstrstart}}%^^A
% \changes{v3.28}{2019/11/23}{Vorzeichenfall \texttt{+} korrigiert}%^^A
% \changes{v3.28}{2019/11/23}{im Plusfall \cs{ifisdimension} durch
%   \cs{ifisglue} ersetzt}%^^A
% Eigentlich wäre dieses Hilfsmakro extrem aufwändig, da Leim recht
% komplex aufgebaut sein darf. Ich habe aber beschlossen, hier mit einer
% Heuristik zu Werke zu gehen: Wenn das Argument mit einer beliebigen Anzahl
% Vorzeichen, gefolgt von max. einem Punkt, Komma oder einer Ziffer oder
% gefolgt einem der für Leim zulässigen Primitiv beginnt, dann probieren wir
% eine Zuweisung. Ist diese syntaktisch nicht korrekt, kann ein Fehler die
% Folge sein. Das mag unschön sein, vereinfacht den Test aber erheblich!
%    \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}{neu (intern)}
% Das durch \cs{@nil} begrenzte Argument wird einer temporären Länge
% zugewiesen. Wird dabei das Argument komplett aufgebraucht, so wird das
% erste Argument nach \cs{@nil} ausgeführt, sonst das zweite. Das begrenzte
% Argument wird in jedem Fall komplett aufgebraucht.
%    \begin{macrocode}
\newcommand*\scr@TestGlueAssignTillNil{}
\def\scr@TestGlueAssignTillNil#1\@nil{%
  \begingroup
    \afterassignment\scr@AfterEndGroupIfArgIsRelaxTillptNnil
    \@tempskipa=#1pt\@nnil
}
%</base>
%    \end{macrocode}
% \end{macro}%^^A \scr@TestGlueAssignTillNil
% \end{macro}%^^A \scr@ifisglue
% \end{macro}%^^A \Ifisglue
% \end{macro}%^^A \ifisglue
%
%
% \begin{macro}{\ifnumber}
% \changes{v3.12}{2013/10/30}{using \cs{aftergroup} instead of
%   \cs{endgroup}\cs{expandafter}}%^^A
% \changes{v3.12a}{2014/01/24}{Leerzeichenfehler korrigiert}%^^A
% \changes{v3.27}{2019/08/26}{leere Argumente werden korrekt behandelt}%^^A
% \changes{v3.28}{2019/11/18}{\cs{ifnumber} umbenannt in \cs{Ifnumber}}%^^A
% \begin{macro}{\Ifnumber}
% \changes{v3.28}{2019/11/18}{Neu aus Umbenennung von \cs{ifnumber}}%^^A
% Dieses Makro testet, ob ein übergebener Parameter eine positive,
% ganze Zahl ist. Ist dies der Fall, wird der zweite Parameter
% ausgeführt, sonst der dritte.
%    \begin{macrocode}
%<*base>
\providecommand*{\ifnumber}{%
%    \end{macrocode}
% Die Warnung darf nicht ausgegeben werden, wenn \textsf{babelbib} geladen
% wurde, weil das Paket die Anweisung ebenfalls definiert, aber nur, wenn sie
% nicht bereits definiert war. Dabei werden übrigens teilweise Makronamen mit
% dem Präfix \cs{scr@} definiert, was ich gar nicht lustig finde. Überhaupt
% geht das böse in die Hose, wenn \textsf{babelbib} vor \texttt{scrbase}
% geladen wird, was ja durchaus passieren kann. Möglichweise werde ich daher
% die Sonderbehandlung an dieser Stelle auch wieder entfernen, sobald ich die
% Anleitung von \textsf{babelbib} auf \textsf{biblatex} umgestellt habe.
%    \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\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}
% Für den eigentlichen Test wird der erste Parameter Token für Token
% gescannt und beurteilt.
%    \begin{macrocode}
\newcommand*{\test@number}[1]{%
  \ifx \scr@next#1%
    \let\scr@next\relax
  \else
%    \end{macrocode}
% Dabei wird für einen schnelleren Vergleich die Tatsache genutzt, dass
% Ziffernzeichen immer im selben durchgängigen Bereich liegen
%    \begin{macrocode}
    \@tempcnta=\expandafter\expandafter\expandafter\number
    \expandafter`#1\relax
    \ifnum \@tempcnta>47
      \ifnum \@tempcnta<58
        \@tempswatrue
      \else\@tempswafalse\fi
    \else\@tempswafalse\fi
%    \end{macrocode}
% Das zeichenweise Scannen und Parsen kann natürlich nicht einfach
% abgebrochen werden. Stattdessen ist der Parameterrest noch zu
%  entfernen.
%    \begin{macrocode}
    \if@tempswa\else\let\scr@next\gobble@till@scr@next\fi
  \fi
  \scr@next
}
%    \end{macrocode}
% \begin{macro}{\gobble@tillscr@@next}
% Das geschieht mit einem einzigen "`Leermacro"'.
%    \begin{macrocode}
\newcommand*{\gobble@till@scr@next}{}
\def\gobble@till@scr@next#1\scr@next{}
%</base>
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\ifintnumber}
% \changes{v3.12}{2013/10/30}{neu}%^^A
% \changes{v3.28}{2019/11/18}{\cs{ifintnumber} umbenannt in
%   \cs{Ifintnumber}}%^^A
% \begin{macro}{\Ifintnumber}
% \changes{v3.28}{2019/11/18}{neu aus Umbenennung von \cs{ifintnumber}}
% Ist das erste Argument eine positive oder negative ganze Zahl, to wird das
% zweite Argument ausgeführt, sonst das dritte. Wie bei \TeX{} auch sind
% beliebig viele Vorzeichen erlaubt.
%    \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}{neu (intern)}%^^A
%    \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\test@number\scr@next #1}%
      \fi
    \fi
  \fi
  \scr@next
}       
%</base>
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\ifdimen}
% \changes{v3.28}{2019/11/18}{umbenannt in \cs{Ifdimen}}%^^A
% \begin{macro}{\Ifdimen}
% \changes{v3.28}{2019/11/18}{neu aus Umbenennung von \cs{ifdimen}}%^^A
% Dieses Makro testet, ob ein übergebener Parameter eine Dimension
% ist und führt in Abhängigkeit davon den zweiten oder dritten
% Parameter aus.
%    \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\test@posdimen
  \expandafter\test@dimen#1\scr@next
  \if@tempswa
    \endgroup\expandafter\@firstoftwo
  \else
    \endgroup\expandafter\@secondoftwo
  \fi
}
%    \end{macrocode}
% \begin{macro}{\test@dimen}
% Als erste muss ein Vorzeichen entfernt werden.
%    \begin{macrocode}
\newcommand*{\test@dimen}[1]{%
  \ifx -#1\else\ifx +#1\else
      \def\scr@next{\let\scr@next\test@posdimen\scr@next#1}\fi\fi
  \scr@next
}
%    \end{macrocode}
% \begin{macro}{\test@posdimen}
% Dann muss getestet werden, ob es sich beim Rest um eine Dimension
% handelt. Dabei werden der Einfachheit halber mehrere Dezimalkomma
% und -punkte erlaubt. Natürlich könnte man es auch wirklich richtig
% machen, aber das wäre nochmal etwas aufwendiger. Ist das wirklich
% notwendig? 
%    \begin{macrocode}
\newcommand*{\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{\test@dimunt#1}\fi
        \else\def\scr@next{\test@dimunt#1}\fi
    \fi\fi
  \fi
  \scr@next
}
%    \end{macrocode}
% \begin{macro}{\test@dimunt}
% \begin{macro}{\test@trueunt}
% Außer einer Gleitkomma- bzw. Gleitpunktzahl muss auch noch die Einheit
% behandelt werden. Dabei sind sowohl die neun Standardeinheiten als auch
% deren "`true"'-Variante zu berücksichtigen. Deshalb wird zuerst ein
% eventuelles "`\texttt{true}"' weggeworfen.
%    \begin{macrocode}
\newcommand*{\test@dimunt}{}
\def\test@dimunt#1\scr@next{%
  \expandafter\test@trueunt#1truetrue\test@trueunt
}
\newcommand*{\test@trueunt}{}
\def\test@trueunt#1true#2true#3\test@trueunt{%
  \edef\reserved@a{#1}%
  \ifx\reserved@a\@empty\test@@ifdimunt{#2}\else\test@@ifdimunt{#1}\fi
}
%    \end{macrocode}
% \begin{macro}{\test@@ifdimunt}
% \changes{v3.21}{2016/05/27}{elf bis zwölf Einheiten nicht neun}
% \changes{v3.28}{2019/11/18}{\cs{ifstr} umbenannt in \cs{Ifstr}}%^^A
% Anschließend wird dann getestet, ob es sich um eine der elf bis zwölf
% üblichen Einheiten handelt.
%    \begin{macrocode}
\newcommand*\test@@ifdimunt[1]{%
  \@tempswafalse
  \Ifstr{#1}{pt}{\@tempswatrue}{%
    \Ifstr{#1}{pc}{\@tempswatrue}{%
      \Ifstr{#1}{in}{\@tempswatrue}{%
        \Ifstr{#1}{bp}{\@tempswatrue}{%
          \Ifstr{#1}{cm}{\@tempswatrue}{%
            \Ifstr{#1}{mm}{\@tempswatrue}{%
              \Ifstr{#1}{dd}{\@tempswatrue}{%
                \Ifstr{#1}{cc}{\@tempswatrue}{%
                  \Ifstr{#1}{sp}{\@tempswatrue}{%
                    \Ifstr{#1}{ex}{\@tempswatrue}{%
                      \Ifstr{#1}{em}{\@tempswatrue}{%
                        \scr@ifpdfoutput{%
                          \Ifstr{#1}{px}{\@tempswatrue}{}%
                        }{}%
                      }%
                    }%
                  }%
                }%
              }%
            }%
          }%
        }%
      }%
    }%
  }%
}
%</base>
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
%
% \begin{macro}{\ifpdftex}
% \changes{v2.95}{2002/08/19}{neu}%^^A
% \changes{v3.28}{2019/11/18}{entfernt}%^^A
% \begin{macro}{\scr@ifpdftex}
% \changes{v2.95}{2002/08/19}{neu (intern)}%^^A
% \changes{v3.30}{2020/03/06}{veralteten Befehl \cs{ifnotundefined} durch
%   \cs{Ifnotundefined} ersetzt}%^^A
% If-then-else-Konstrukt, um zu testen, ob pdf\TeX{} verwendet wird.
%    \begin{macrocode}
%<*base>
\newcommand{\scr@ifpdftex}{\Ifnotundefined{pdftexversion}}
%</base>
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\scr@ifluatex}
% \changes{v3.21}{2016/05/27}{neu (intern)}%^^A
% \changes{v3.30}{2020/03/06}{veralteten Befehl \cs{ifnotundefined} durch
%   \cs{Ifnotundefined} ersetzt}%^^A
% If-the-else-Konstrukt, um zu testen, ob lua\TeX{} verwendet wird.
%    \begin{macrocode}
%<*base>
\newcommand{\scr@ifluatex}{\Ifnotundefined{luatexversion}}
%</base>
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\scr@ifpdforluatex}
% \changes{v3.21}{2016/05/27}{neu (intern)}%^^A
% If-then-else-Konstrukt, um zu testen, ob pdf\TeX{} oder lua\TeX{} verwendet
% wird.
%    \begin{macrocode}
%<*base>
\newcommand*{\scr@ifpdforluatex}{%
  \scr@ifpdftex{\@firstoftwo}{\scr@ifluatex{\@firstoftwo}{\@secondoftwo}}%
}
%</base>
%    \end{macrocode}
% \end{macro}
%  
% \begin{macro}{\ifVTeX}
% \changes{v2.95}{2002/08/19}{neu}%^^A
% \changes{v2.97c}{2007/06/20}{umdefiniert von \cs{ifvtex}}%^^A
% \changes{v3.28}{2019/11/18}{entfernt}%^^A
% \begin{macro}{\scr@ifVTeX}
% \changes{v2.95}{2002/08/19}{neu}%^^A
% \changes{v2.97c}{2007/06/20}{umdefiniert von \cs{scr@ifvtex}}
% \changes{v3.30}{2020/03/06}{veralteten Befehl \cs{ifnotundefined} durch
%   \cs{Ifnotundefined} ersetzt}%^^A
% If-then-else-Konstrukt, um zu testen, ob V\TeX{} verwendet wird.
%    \begin{macrocode}
%<*base>
\newcommand{\scr@ifVTeX}{\Ifnotundefined{VTeXversion}}
%</base>
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\ifpdfoutput}
% \changes{v2.7g}{2001/04/17}{neu}%^^A
% \changes{v2.8q}{2001/10/19}{\cs{pdfoutput} wird nicht mehr zu
%      \cs{relax}, wenn zuvor undefiniert}
% \changes{v2.8q}{2001/10/19}{darf bereits definiert sein}%^^A
% \changes{v2.8q}{2001/10/19}{Verwendung von \cs{scr@ifpdfoutput}}%^^A
% \changes{v3.28}{2019/11/18}{Umbenannt in \cs{Ifpdfoutput}}%^^A
% \begin{macro}{\Ifpdfoutput}
% \changes{v3.28}{2019/11/18}{Neu aus Umbenennung von \cs{ifpdfoutput}}%^^A
% \begin{macro}{\scr@ifpdfoutput}
% \changes{v2.8q}{2001/10/19}{neu (intern)}%^^A
% \changes{v2.8q}{2001/11/13}{funktioniert}%^^A
% \changes{v2.95}{2002/08/21}{berücksichtigt V\TeX}%^^A
% \changes{v2.95}{2004/07/20}{Expandierbarkeit verbessert}%^^A
% \changes{v3.21}{2016/05/27}{lua\TeX{} nach 0.85 berücksichtigt}%^^A
% If-then-else-Konstrukt, um abhängig davon, ob als \texttt{pdf}
% ausgegeben wird oder nicht, Befehle auszuführen. Dieses Makro wird
% für die Deklaration der Option \texttt{pagesize} benötigt.
%    \begin{macrocode}
%<*base>
\newcommand{\scr@ifpdfoutput}{%
  \scr@ifundefinedorrelax{pdfoutput}{%
    \scr@ifundefinedorrelax{outputmode}{%
      \scr@ifundefinedorrelax{OpMode}{%
        \expandafter\@secondoftwo%
      }{%
        \ifnum\OpMode=1
          \expandafter\@firstoftwo
        \else
          \expandafter\@secondoftwo
        \fi
      }%
    }{%
      \ifnum\outputmode>0
        \expandafter\@firstoftwo
      \else
        \expandafter\@secondoftwo
      \fi
    }%
  }{%
    \ifnum\pdfoutput>0 
      \expandafter\@firstoftwo
    \else
      \expandafter\@secondoftwo
    \fi
  }%
}%
\providecommand*{\ifpdfoutput}{%
  \PackageWarning{scrbase}{Usage of deprecated command
    `\string\ifpdfoutput'.\MessageBreak
    The command has been renamed because of a\MessageBreak
    recommendation of The LaTeX Project Team.\MessageBreak
    Please replace `\string\ifpdfoutput' by `\string\Ifpdfoutput'%
  }%
  \Ifpdfoutput
}
\newcommand*{\Ifpdfoutput}{\scr@ifpdfoutput}
%</base>
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\ifpsoutput}
% \changes{v2.95}{2002/08/21}{neu}%^^A
% \changes{v3.28}{2019/11/18}{umbenannt in \cs{Ifpsoutput}}%^^A
% \begin{macro}{\Ifpsoutput}
% \changes{v3.28}{2019/11/18}{neu aus Umbenennung von \cs{ifpsoutput}}%^^A
% \begin{macro}{\scr@ifpsoutput}
% \changes{v2.95}{2002/08/21}{neu (intern)}%^^A
% \changes{v2.95}{2004/07/20}{Expandierbarkeit verbessert}%^^A
% \changes{v3.30}{2020/03/06}{veralteten Befehl \cs{ifnotundefined} durch
%   \cs{Ifnotundefined} ersetzt}%^^A
% If-then-else-Konstrukt, um abhängig davon, ob früher oder später
% \texttt{ps} ausgegeben wird oder nicht, Befehle auszuführen.
%    \begin{macrocode}
%<*base>
\newcommand*{\scr@ifpsoutput}{%
  \Ifnotundefined{if@dvips}{%
    \if@dvips 
      \expandafter\@firstoftwo
    \else 
      \expandafter\@secondoftwo
    \fi
  }{%
    \Ifnotundefined{OpMode}{%
      \ifnum\OpMode=2
        \expandafter\@firstoftwo
      \else
        \expandafter\@secondoftwo
      \fi
    }{%
      \expandafter\@secondoftwo
    }%
  }%
}
\providecommand*{\ifpsoutput}{%
  \PackageWarning{scrbase}{Usage of deprecated command
    `\string\ifpsoutput'.\MessageBreak
    The command has been renamed because of a\MessageBreak
    recommendation of The LaTeX Project Team.\MessageBreak
    Please replace `\string\ifpsoutput' by `\string\Ifpsoutput'%
  }%
  \Ifpsoutput
}
\newcommand*{\Ifpsoutput}{\scr@ifpsoutput}
%</base>
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\ifdvioutput}
% \changes{v2.95}{2002/08/21}{neu}%^^A
% \changes{v3.28}{2019/11/18}{umbenannt in \cs{Ifdvioutput}}%^^A
% \begin{macro}{\Ifdvioutput}
% \changes{v3.28}{2019/11/18}{neu aus Umbenennung von \cs{ifdvioutput}}%^^A
% \begin{macro}{\scr@ifdvioutput}
% \changes{v2.95}{2002/08/21}{neu (intern)}%^^A
% \changes{v2.95}{2004/07/20}{Expandierbarkeit verbessert}%^^A
% \changes{v3.23}{2017/02/14}{lua\TeX{} nach 0.85 berücksichtigt}%^^A
% If-then-else-Konstrukt, um abhängig davon, ob \texttt{dvi}
% ausgegeben wird oder nicht, Befehle auszuführen.
%    \begin{macrocode}
%<*base>
\newcommand*{\scr@ifdvioutput}{%
  \scr@ifundefinedorrelax{pdfoutput}{%
    \scr@ifundefinedorrelax{outputmode}{%
      \scr@ifundefinedorrelax{OpMode}{%
        \expandafter\@firstoftwo
      }{%
        \ifnum\OpMode=0
          \expandafter\@firstoftwo
        \else
          \expandafter\@secondoftwo
        \fi
      }%
    }{%
      \ifnum\outputmode>0
        \expandafter\@secondoftwo
      \else
        \expandafter\@firstoftwo
      \fi
    }%
  }{%
    \ifnum\pdfoutput=0
      \expandafter\@firstoftwo
    \else
      \expandafter\@secondoftwo
    \fi
  }%
}
\providecommand*{\ifdvioutput}{%
  \PackageWarning{scrbase}{Usage of deprecated command
    `\string\ifdvioutput'.\MessageBreak
    The command has been renamed because of a\MessageBreak
    recommendation of The LaTeX Project Team.\MessageBreak
    Please replace `\string\ifdvioutput' by `\string\Ifdvioutput'%
  }%
  \Ifdvioutput
}
\newcommand*{\Ifdvioutput}{\scr@ifdvioutput}
%</base>
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\scr@smashdp}
% \changes{v2.97c}{2007/09/17}{neu (intern)}%^^A
% \changes{v3.02a}{2009/01/23}{\cs{smash} nicht direkt verwenden, weil
%     \textsf{amsmath} das inkompatibel umdefiniert}
% Gibt Material aus, erzeugt dabei aber nur Höhe und Breite, jedoch keine
% Tiefe.
%    \begin{macrocode}
%<*base>
\newcommand*{\scr@smashdp}[1]{%
  \begingroup
    \def\finsm@sh{\dp\z@\z@\box\z@}%
    \ifmmode
      \expandafter\mathpalette\expandafter\mathsm@sh
    \else
      \expandafter\makesm@sh
    \fi
    {#1}%
  \endgroup
}
%</base>
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\IfRTL}
% \changes{v3.24}{2017/05/04}{neu}
%   Die Anweisung testet, ob wir uns gerade im Von-Rechts-Nach-Links-Modus von
%   Paketen wie \textsf{bidi} befinden. Ist das der Fall, wird das erste
%   Argument ausgeführt, sonst das zweite.
%    \begin{macrocode}
%<*base>
\newcommand*{\IfRTL}{%
  \scr@ifundefinedorrelax{if@RTL}{\@secondoftwo}{%
    \expandafter\ifx\csname if@RTL\expandafter\endcsname
                    \csname iftrue\endcsname
      \expandafter\@firstoftwo
    \else
      \expandafter\@secondoftwo
    \fi
  }
}
%</base>
%    \end{macrocode}
% \end{macro}%^^A \IfRTL
% \begin{macro}{\IfLTR}
% \changes{v3.24}{2017/05/04}{neu}
%   Die Anweisung testet, ob wir uns gerade nicht im
%   Von-Rechts-Nach-Links-Modus von Paketen wie \textsf{bidi} befinden. Ist
%   das der Fall, wird das erste Argument ausgeführt, sonst das zweite.
%    \begin{macrocode}
%<*base>
\newcommand*{\IfLTR}{%
  \scr@ifundefinedorrelax{if@RTL}{\@firstoftwo}{%
    \expandafter\ifx\csname if@RTL\expandafter\endcsname
                    \csname iftrue\endcsname
      \expandafter\@secondoftwo
    \else
      \expandafter\@firstoftwo
    \fi
  }
}
%</base>
%    \end{macrocode}
% \end{macro}%^^A \IfLTR
%
% \begin{macro}{\PackageInfoNoLine}
% \changes{v2.97d}{2007/10/03}{neu}%^^A
% Arbeitet wie \cs{PackageInfo} aber ohne Ausgabe der Zeilennummer.
%    \begin{macrocode}
%<*base>
\providecommand*{\PackageInfoNoLine}[2]{%
  \PackageInfo{#1}{#2\@gobble}%
}
%</base>
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\ClassInfoNoLine}
% \changes{v2.98c}{2008/02/15}{neu}%^^A
% Arbeitet wie \cs{ClassInfo} aber ohne Ausgabe der Zeilennummer.
%    \begin{macrocode}
%<*base>
\providecommand*{\ClassInfoNoLine}[2]{%
  \ClassInfo{#1}{#2\@gobble}%
}
%</base>
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@removefromreset}
% \changes{v3.15}{2014/11/21}{neue Anweisung, kompatibel mit
%     \textsf{remreset} und \textsf{chngcntr}}%^^A
% Dieser alte Bekannte aus dem Paket \textsf{remreset} wird auch von
% \KOMAScript{} benötigt. Es ist einfacher, ihn selbst zu definieren, als sich
% auf andere Pakete zu verlassen. Ab \LaTeX~2018-04-01 ist das aber auch
% Bestandteil von \LaTeX. Deshalb ist es in jedem Fall sinnvoll die Definition
% nur vorzunehmen, wenn es nicht definiert ist.
%    \begin{macrocode}
%<*base>
\providecommand*\@removefromreset[2]{%
  {%
    \expandafter\let\csname c@#1\endcsname\@removefromreset
    \def\@elt##1{%
      \expandafter\ifx\csname c@##1\endcsname\@removefromreset
      \else\noexpand\@elt{##1}\fi
    }%
    \expandafter\xdef\csname cl@#2\endcsname{\csname cl@#2\endcsname}%
  }%
}
%</base>
%    \end{macrocode}
% \end{macro}
%
% \selectlanguage{english}%
% \begin{macro}{\IfActiveMkBoth}
% \changes{v3.26}{2018/09/03}{new}%^^A
% \begin{macro}{\if@scrActiveMkBoth}
% \changes{v3.26}{2018/09/03}{new}%^^A
% \changes{v3.27}{2019/07/26}{handling for \cs{marks}}%^^A
% This command test, whether or not \cs{@mkboth} does change a mark or not.
%    \begin{macrocode}
%<*base>
\newif\ifscr@ActiveMkBoth
\def\scr@ActiveMkBothfalse{\global\let\ifscr@ActiveMkBoth\iffalse}
\def\scr@ActiveMkBothtrue {\global\let\ifscr@ActiveMkBoth\iftrue}
\newcommand*{\IfActiveMkBoth}{%
  \begingroup
    \def\markboth##1##2{\scr@ActiveMkBothtrue}%
    \def\markright##1{\scr@ActiveMkBothtrue}%
    \def\markleft##1{\scr@ActiveMkBothtrue}%
    \def\markboth##1{\scr@ActiveMkBothtrue}%
    \def\markdouble##1{\scr@ActiveMkBothtrue}%
    \def\mark##1{\scr@ActiveMkBothtrue}%
    \def\marks##1##2{\scr@ActiveMkBothtrue}%
    \scr@ActiveMkBothfalse
    \setbox\@tempboxa\vbox{\@mkboth{}{}}%
  \endgroup
  \ifscr@ActiveMkBoth
    \expandafter\@firstoftwo
  \else
    \expandafter\@secondoftwo
  \fi
}
%</base>
%    \end{macrocode}
% \end{macro}%^^A\if@scrActiveMkBoth
% \end{macro}%^^A\IfActiveMkBoth
% \selectlanguage{ngerman}%
%
% \subsection{Definition von KOMA-\textsf{keyval}-Schlüsseln (Hauptteil)}
%
% \begin{macro}{\FamilyExecuteOptions}
% \changes{v3.00}{2008/04/30}{Neue Anweisung}%^^A
% \changes{v3.04b}{2010/01/29}{\cs{edef} durch \cs{protected@edef} ersetzt}%^^A
% \changes{v3.04b}{2010/02/02}{\cs{scr@key@atlist} und \cs{scr@key@name}%^^A
%   vor Überschreiben in \cs{setkeys} geschützt}%^^A
% \changes{v3.12}{2013/03/04}{neue Implementierung}%^^A
% \changes{v3.12}{2013/03/04}{darf auch noch nach der Präambel verwendet
%   werden}%^^A
% \changes{v3.14}{2014/10/17}{das dritte Argument wird \cs{long}%^^A
%   verarbeitet}%^^A
% \begin{macro}{\@FamilyExecuteOptions}
% \changes{v3.14}{2014/10/17}{Neue streng interne Anweisung}%^^A
% \changes{v3.23}{2017/02/16}{Korrektur: Haken danach verwendet die Familie
%   statt des Mitglieds}%^^A
% \changes{v3.27}{2019/10/02}{Fehlermeldungen verbessert}%^^A
% \changes{v3.28}{2019/11/18}{\cs{ifstr} umbenannt in \cs{Ifstr}}%^^A
% Entspriche \cs{ExecuteOptions} jedoch \textsf{keyval}-Optionen. Insbesondere
% ist die Anweisung reentrant! Es ist jedoch zu beachten, dass der hook lokal
% zum jeweiligen Aufruf ist.
%    \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}{Besondere Behandlung der
%     \texttt{@else@}-Option}%^^A
% Es existiert zwar weder eine Familienoption noch eine Mitgliedsoption, aber
% vielleicht existiert ja die Spezialoption \texttt{@else@}, die in einem
% solchen Fall die eigentliche Option als Wert erhält.
%    \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}
% Im Gegensatz zu anderen Optionen bedeuten bei der \texttt{@else@}-Option
% alle von \cs{FamilyKeyStateProcessed} abweichenden Ergebnisse, dass die
% Option nicht korrekt verarbeitet werden konnte und deshalb die ursprüngliche
% Option als Fehler zu melden ist.
%    \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}{Memberoptionstest nach Familyoptionsausführung
%     korrigiert}%^^A
% Auch wenn eine Familienoption ausgeführt wurde, muss eine existierende
% Mitgliederoption ggf. noch ausgeführt werden. Existiert sie nicht, wird
% ebenfalls eine existierende \texttt{@else@}-Option ausgeführt. Allerdings
% führen in diesem Fall von \cs{FamilyKeyStateProcessed} abweichende
% Ergebnisse nicht zu einer Fehlermeldung.
%    \begin{macrocode}
            \scr@ifundefinedorrelax{KV@#2#1@\scr@key@name}{%
              \scr@ifundefinedorrelax{KV@#2#1@@else@}{}{%
                \scr@execute@elseoption{#2#1}%
              }%
            }{%
              \ifx\FamilyKeyState\FamilyKeyStateProcessed
                \scr@execute@option{#2#1}%
                \FamilyKeyStateProcessed
              \else
                \scr@execute@option{#2#1}%
              \fi
            }%
          }%
        }%
        \scr@show@key@state@error
      \fi
    \fi
  }%
  \@nameuse{scr@after@options@#2@hook}%
}
%</base>
%    \end{macrocode}
% \begin{macro}{\scr@show@key@state@error}
% \changes{v3.12}{2013/03/04}{Neue Anweisung (intern)}%^^A
% \changes{v3.27}{2019/10/02}{Fehlermeldungen verbessert}%^^A
% Zeige abhängig von \cs{FamilyKeyState} eine Fehlermeldung. Alle
% Informationen zu dem Fehler müssen in \cs{FamilyMemberOfKey}
% (Familienmitglied oder \cs{@empty}), \cs{FamilyOfKey} (Familie oder
% \cs{@empty}), \cs{scr@key@atlist} (Option, wie sie in der Liste stand),
% \cs{scr@key@name} (Name der Option) und \cs{scr@key@value} (Wert der
% Option) stehen. Es ist zu beachten, dass \cs{scr@key@atlist} und
% \cs{scr@key@value} ebenfalls Macros enthalten können. Deshalb werden diese
% Werte ggf. über \cs{detokenize} ausgegeben.
%    \begin{macrocode}
%<*base>
\newcommand*{\scr@show@key@state@error}{%
  \ifx\FamilyKeyState\FamilyKeyStateProcessed\else
    \PackageError{scrbase}{%
      unknown option
      \ifx\FamilyKeyState\FamilyKeyStateUnknownValue
        value at
      \fi
      `\expandafter\detokenize\expandafter{\scr@key@atlist}'%
    }{%
      Option
      `\expandafter\detokenize\expandafter{\scr@key@name}'\MessageBreak
      \ifx\FamilyMemberOfKey\@empty\else
        of member `\FamilyMemberOfKey'\MessageBreak
      \fi
      \ifx\FamilyOfKey\@empty\else
        of family `\FamilyOfKey'\MessageBreak
      \fi
      \ifx\FamilyKeyState\FamilyKeyStateNeedValue
        expects a value, but has been used without any value.%
      \else
        cannot handle value\MessageBreak
        `\expandafter\detokenize\expandafter{\scr@key@value}',%
        \MessageBreak
        \ifx\FamilyKeyState\FamilyKeyStateUnknownValue
          because this is an unsupported value.%
        \else
          because \FamilyKeyState.
        \fi
      \fi
    }%
  \fi
}
%</base>
%    \end{macrocode}
% \end{macro}%^^A \scr@show@key@state@error
% \end{macro}%^^A \@FamilyExecuteOptions
% \end{macro}%^^A \FamilyExecuteOptions
%
% \begin{macro}{\KOMAExecuteOptions}
% \changes{v2.97c}{2007/04/19}{Neue Anweisung}%^^A
% \changes{v3.00}{2008/04/30}{Kein optionales Argument mehr}%^^A
% \changes{v3.12}{2013/03/04}{darf auch noch nach der Präambel verwendet
%     werden}%^^A
% Liste von Optionen für ein Mitglied der Familie \texttt{KOMA} ausführen.
%    \begin{macrocode}
%<*koma>
\newcommand*{\KOMAExecuteOptions}[1][.\@currname.\@currext]{%
  \FamilyExecuteOptions[#1]{KOMA}%
}
%</koma>
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\FamilyOptions}
% \changes{v3.00}{2008/04/30}{Neue Anweisung}%^^A
% \changes{v3.12}{2013/03/02}{Neue Implementierung}%^^A
% \changes{v3.12}{2013/03/02}{\cs{scr@after@options@\#1@hook}}%^^A
% \changes{v3.14}{2014/10/17}{zweites Argument wird \cs{long} behandelt}%^^A
% \begin{macro}{\@FamilyOptions}
% \changes{v3.14}[2014/10/17]{Neue streng interne Anweisung}%^^A
% \changes{v3.27}{2019/10/02}{Fehlermeldungen verbessert}%^^A
% \begin{macro}{\Family@Options}
% \changes{v3.00}{2008/04/30}{Neues Makro (intern)}%^^A
% \changes{v3.12}{2013/03/04}{entfernt}%^^A
% \end{macro}%^^A \FamilyOptions
% Es werden Schlüssel einer Familie verwendet. Existiert ein Schlüssel nicht,
% oder ist der Wert für alle Schlüssel unbekannt, so wird ein Fehler
% ausgegeben. Diese Anweisung selbst ist reentrant, das heißt sie kann auch
% innerhalb der Ausführung von Optionen aufgerufen werden. Es sei jedoch
% erwähnt, dass der hook dabei nur die jeweilige Anweisung umfasst.
%    \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}{neuer Haken für \cs{AtEndOfFamilyOptions*}}%^^A
% Seit Version 3.23 wird hier auch der neuen Haken vor
% \cs{AtEndOfFamilyOptions*} initialisiert. Zunächst findet eine Art
% Vorinitialisierung statt, bei der der Haken lediglich leer definiert wird,
% falls er noch nicht existiert. Falls er nämlich existiert, kann an einem
% leeren Haken die oberste Ebene erkannt werden.
%    \begin{macrocode}
  \scr@ifundefinedorrelax{scr@after@options@#1@hook@topmost}{%
    \@namedef{scr@after@options@#1@hook@topmost}{}%
  }{}%
%    \end{macrocode}
% Dann wird an einem leeren Haken die oberste Ausführungsebene erkennt. In
% diesem Fall wird zum einen die Ausführung des Hakens in den normalen
% Ebenen-Haken (das ist dann automatische der oberste Ebenen-Haken)
% eingehängt und zum anderen der Haken selbst so initialisiert, dass er sich
% bei seiner Ausführung als erstes selbst löscht. Gleichzeitig ist der Haken
% selbst dadurch nicht mehr leer, so dass sich tiefere Ebenen von der höchsten
% eindeutig unterscheiden.
%    \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[Anmerkung:] Es wird nicht auf \textsf{xkeyval} und den dortigen Befehl
%   \cs{setkeys+} gesetzt, weil dieser die Optionen nicht in der Reihenfolge
%   der Optionen, sondern in der Reihenfolge der Familien ausführt. Das passt
%   mir aber hier gar nicht.
% \end{description}
% In einer Schleife über alle Optionen werden die Optionen zunächst in Option
% und Wert aufgespaltet.
%    \begin{macrocode}
  \@for\scr@key@atlist:=#2\do{%
%    \end{macrocode}
% \changes{v3.08}{2010/11/05}{leere Argumente in der Optionenliste}%
% Auf vielfachen Wunsch und entgegen meiner Überzeugung, sind auch leere
% Argumente in der Optionenliste erlaubt. Die erste Form wäre, wenn zwei
% Kommas diret aufeinander folgen:
%    \begin{macrocode}
    \ifx\scr@key@atlist\@empty\else
%    \end{macrocode}
% Die zweite Möglichkeit wäre, dass noch Leerzeichen zwischen den Komma
% übrig bleiben:
%    \begin{macrocode}
      \ifx\scr@key@atlist\space\else
        \expandafter\scr@key@split@name@value\scr@key@atlist==\@nil
%    \end{macrocode}
% Die dritte Möglichkeit, dass auch noch ein Gleichheitszeichen übrig
% gelassen wurde, werde ich aber nicht abfangen. Irgendwann müssen die
% Anwender auch mal ihre Fehler einsehen und korrigieren!
%
% Wir haben jetzt also eine Option und diese aufgespaltet in Schlüssel und
% Wert.
% \changes{v3.12}{2013/03/04}{der Gesamtstatus wird gespeichert}%^^A
% Jetzt speichern wir den Gesamtstatus einfach, indem der Fehlerspeicher
% gelöscht wird. Bei \cs{relax} wird er nicht weiter benötigt und es liegt
% ebenso wie bei \cs{@empty} kein auszugebender Fehler vor. Bei anderen
% Werten, enthält er Fehler, die zu melden sind.
%    \begin{macrocode}
        \let\scr@key@run@errors\@empty
%    \end{macrocode}
% \changes{v3.04b}{2010/01/29}{\cs{edef} durch \cs{protected@edef} ersetzt}
% \changes{v3.09a}{2011/06/07}{weniger Expansion durch sinnvollen Gebrauch
%     von \cs{unexpanded}}
% Dann wird in einer Schleife über alle Familienmitglieder festgestellt, ob
% die Option bei einem Mitglied bekannt ist und ggf. ausgeführt. Hier ist
% wichtig, dass keines der internen Macros vom Aufruf verändert wird. Außerdem
% muss der Status und die daraus resultierenden Meldungen aufgesammelt
% werden. Hilfreich ist, dass \cs{\meta{Familie}@key@familylist} eine Liste
% aus Familie + Mitglied ist und nicht nur aus dem Namen der Mitglieder.
% \changes{v3.27}{2019/07/19}{Fix: Familienoptionen werden zuerst
%   ausgeführt}%^^A
%    \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}{Behandlung für \texttt{@else@}-Optionen}%^^A
% Wenn das Familiemitglied keine entsprechende Option besitzt, kann es noch
% immer eine \texttt{@else@}-Option besitzen. In diesem Fall wird selbige
% ausgeführt. Die Ausführung hat aber nur dann Einfluss auf den
% Fehlerspeicher, wenn sie erfolgreich war. In diesem Fall wird der
% Fehlerspeicher gelöscht. Ausnahme ist, wenn das aktuelle Mitglied die
% Familie selbst ist. In diesem Fall wird die \texttt{@else@}-Option nicht
% hier ausgeführt. Das erledigen wir später und nur in dem Fall, dass
% tatsächlich kein Mitglied eine solche Option oder eine
% \texttt{@else@}-Option hatte.
%    \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}
% Wurde hingegen eine Option für ein Familienmitglied gefunden, so wird sie
% ausgeführt und bei Bedarf der Fehlerspeicher angepasst.
%    \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}{Fehlermeldungen und Infos korrigiert}%^^A
% Jetzt muss gegebenenfalls noch eine \texttt{@else@} Option behandelt und
% abhängig davon entweder ein Fehler oder eine Info ausgegeben werden.
%    \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}{Neue Anweisung (intern)}%^^A
% \changes{v3.13}{2014/06/30}{fehlendes \cs{expandafter} in \cs{PackageInfo}
%     ergänzt}%^^A
% \changes{v3.13a}{2014/08/13}{Leerzeichen durch fehlendes Prozentzeichen
%     beseitigt}%^^A
% \changes{v3.23}{2017/02/16}{den \cs{AtEndOfFamilyOptions} Haken hier zu
%     sichern nützt nichts}%^^A
% Es wird die bereits gesplittete Option ausgeführt, ohne dass die dabei
% wesentlichen Macros (aber nicht \cs{reserved@a}!)  verändert werden. Das
% erste Argument ist bereits der Besitzer in \textsf{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}%^^A
% 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}
% \begin{macro}{\scr@key@run@errors}
% \changes{v3.12}{2013/03/04}{Neue Anweisung (intern)}%^^A
% Wird innerhalb von \cs{FamilyOptions} benötigt, um die Fehlermeldungen
% aufzusammeln, aber erst auszugeben, wenn tatsächlich kein Mitglied die
% Option verarbeiten konnte. Wir definieren das hier, damit oben die
% Wiederherstellung korrekt funktioniert.
%    \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}{neu (intern)}%^^A
% \changes{v3.25}{2017/11/16}{Gruppe eingefügt}%^^A
% \changes{v3.25}{2017/11/16}{\cs{scr@key@name@else} und
%   \cs{scr@key@value@else} neu}%^^A
% \changes{v3.27}{2019/03/10}{missing percent added to avoid spaces}%^^A
% Ist eine Spezialoption mit dem Namen \texttt{@else@} definiert, so wird
% diese von \cs{FamilyExecuteOptions} genau dann ausgeführt, wenn keine
% passende Option gefunden wurde. Dafür dient dieses Makro, dessen Argumente
% und Aufrufstatus genau \cs{scr@execute@option} entspricht. Es soll auch
% genau dasselbe tun, außer dass es nicht die Option selbst aufruft, sondern
% die Option als Wert an die \texttt{@else@}-Option übergibt. Es muss also
% temporär \cs{scr@key@atlist}, \cs{scr@key@name} und \cs{scr@key@value}
% geändert werden, bevor \cs{scr@execute@option} ausgeführt wird. Da
% allerdings die Originalwerte ggf. von der \texttt{@else@}-Option ausgewertet
% werden sollen, wird das originale \cs{scr@key@atlist} zum Wert der
% \texttt{@else@}-Option. Damit diese nicht erneut aufgespaltet werden muss,
% werden die originalen \cs{scr@key@name} und \cs{scr@key@value} zusätzlich in
% \cs{scr@key@name@else} und \cs{scr@key@value@else} gespeichert.
%    \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}{\ifscr@key@found@}
% \changes{v2.97c}{2007/04/19}{Neuer Schalter (intern)}%^^A
% \changes{v3.00}{2008/04/30}{umbenannt von \cs{ifKOMA@key@found}}%^^A
% \begin{macro}{\scr@key@atlist}
% \changes{v2.97c}{2007/04/19}{Neues Makro (intern)}%^^A
% \changes{v3.00}{2008/04/30}{umbenannt von \cs{KOMA@key@atlist}}%^^A
% \begin{macro}{\scr@key@name}
% \changes{v2.97c}{2007/04/19}{Neues Makro (intern)}%^^A
% \changes{v3.00}{2008/04/30}{umbenannt von \cs{KOMA@key@name}}%^^A
% \begin{macro}{\scr@key@value}
% \changes{v2.97c}{2007/04/19}{Neues Makro (intern)}%^^A
% \changes{v3.00}{2008/04/30}{umbenannt von \cs{KOMA@key@value}}%^^A
% \begin{macro}{\scr@key@split@name@value}
% \changes{v2.97c}{2007/04/19}{Neues Makro (intern)}%^^A
% \changes{v2.97e}{2007/11/10}{verwendet \cs{KV@@sp@def} zur Entsorgung von
%   Leerzeichen}%^^A
% \changes{v3.00}{2008/04/30}{umbenannt von \cs{KOMA@key@split@name@value}}%^^A
% \changes{v3.13}{2014/10/17}{\cs{long}}%^^A
% \changes{v3.26}{2018/08/29}{Verwendung von \cs{scr@sp@def} statt
%   \cs{KV@@sp@def}}%^^A
%    \begin{macrocode}
\newif\ifscr@key@found@
\newcommand*{\scr@key@atlist}{}
\newcommand*{\scr@key@name}{}
\newcommand*{\scr@key@value}{}
\newcommand*{\scr@key@split@name@value}{}
\long\def\scr@key@split@name@value#1=#2=#3\@nil{%
  \scr@sp@def\scr@key@name{#1}%
  \scr@sp@def\scr@key@value{#2}%
}
%</base>
%    \end{macrocode}
% \end{macro}%^^A \scr@key@split@name@value
% \end{macro}%^^A \scr@key@value
% \end{macro}%^^A \scr@key@name
% \end{macro}%^^A \scr@key@atlist
% \end{macro}%^^A \@FamilyOptions
% \end{macro}%^^A \FamilyOptions
%
% \begin{macro}{\FamilyOption}
% \changes{v3.00}{2008/04/30}{Neue Anweisung}%^^A
% \changes{v3.26b}{2019/01/09}{Tyischen Fehler abgefangen}%^^A
% \begin{macro}{\@FamilyOptions}
% \changes{v3.14}[2014/10/17]{Neue streng interne Anweisung}%^^A
% \changes{v3.26}{2018/08/29}{Verwendung von \cs{scr@sp@def} statt
%   \cs{KV@@sp@def}}%^^A
% \begin{macro}{\Family@Option}
% \changes{v3.00}{2008/04/30}{Neu (intern)}%^^A
% \changes{v3.12}{2013/03/04}{entfernt}%^^A
% \end{macro}
% \changes{v3.04b}{2010/01/29}{\cs{edef} durch \cs{protected@edef} ersetzt}
% Im Gegensatz zu \cs{FamilyOptions} kann man mit dieser Anweisung nur eine
% einzige Option setzen. Dafür kann man gleich mehrere durch Komma getrennte
% Argumente für diese Option setzen. Das erste obligatorische Argument ist
% wieder die Familie, das zweite obligatorische Argument ist die Option, das
% dritte, obligatorische Argument ist die Liste der Werte für diese Option.
%    \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}
% Der einfachste Weg ist nun schlicht, die Liste der Werte durchzugehen und so
% nach und nach eine Liste von Werten für \cs{FamilyOptions} zu erzeugen.
%    \begin{macrocode}
  \let\reserved@a\@empty
  \@for\reserved@b:=#3\do{%
%    \end{macrocode}
% \changes{v3.08}{2010/11/05}{leere Argumente in der Werteliste}%^^A
% Auf vielfachen Wunsch und entgegen meiner Überzeugung, sind auch leere
% Argumente in der Werteliste erlaubt, werden jedoch ignoriert:
%    \begin{macrocode}
    \ifx\reserved@b\@empty\else
%    \end{macrocode}
% \changes{v3.12}{2012/03/04}{auch Leerzeichenargumente werden ignoriert}%^^A
% Auch Argumente, die nur aus einem Leerzeichen bestehen, werden ignoriert:
%    \begin{macrocode}
      \ifx\reserved@b\space\else
        \edef\reserved@a{\unexpanded\expandafter{\reserved@a},%
          \scr@key@name=\unexpanded\expandafter{\reserved@b}}%
      \fi
    \fi
  }%
  \def\reserved@b{\FamilyOptions{#1}}%
  \expandafter\reserved@b\expandafter{\reserved@a}%
}
%</base>
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\KOMAoptions}
% \changes{v2.96}{2006/08/20}{Neuer Hook nach den Optionen}%^^A
% \changes{v2.97c}{2007/04/19}{Optionen aller KOMA-Familien abarbeiten}%^^A
% \changes{v3.12}{2013/03/04}{Hook-Mechanismus von \cs{FamilyOptions}%^^A
%     verwendent}
% Simple kleine Abkürzung.
%    \begin{macrocode}
%<*koma>
\newcommand*{\KOMAoptions}{\FamilyOptions{KOMA}}
%</koma>
%    \end{macrocode}
% \begin{macro}{\KOMA@options}
% \changes{v2.97c}{2007/04/19}{Neues Makro (intern)}%^^A
% \changes{v3.12}{2013/03/04}{entfernt}%^^A
% \end{macro}%^^A \KOMA@options
% \end{macro}%^^A \KOMAoptions
%
% \begin{macro}{\KOMAoptionsOf}
% \changes{v3.17}{2015/02/25}{neue Anweisung}%^^A
% Mit dieser Anweisung können die aktuell gesetzten \KOMAScript-Optionen
% eines Pakets oder einer Klasse abgefragt werden, sobald ein Paket oder eine
% Klasse das unterstützt. Das erste (optionale) Argument gibt dabei eine
% Anweisung an, die für die Optionenliste ausgeführt werden soll. Das zweite
% (nicht optionale Argument) ist der Name eines KOMA-Script-Pakets oder einer
% KOMA-Script-Klasse einschließlich Dateiendung.
%    \begin{macrocode}
%<*koma>
\newcommand*{\KOMAoptionsOf}[2][\@firstofone]{%
  \scr@ifundefinedorrelax{scr@kav@KOMA.#2}{%
    \PackageError{scrkbase}{\string\KOMAoptionsOf\space not supported}{%
      #2 is not the name of a KOMA-Script package or\MessageBreak
      KOMA-Script class, that supports \string\KOMAoptionsOf.}%
  }{%
    \begingroup
      \def\reserved@a{#1}%
      \KOMA@kav@defall\reserved@b{.#2}%
    \expandafter\expandafter\expandafter\endgroup
    \expandafter\reserved@a\expandafter{\reserved@b}%
  }%
}
%</koma>
%    \end{macrocode}
% \end{macro}%^^A \KOMAoptionsOf
%
% \begin{macro}{\KOMAoptionOf}
% \changes{v3.17}{2015/02/26}{neue Anweisung}%^^A
% Mit dieser Anweisung kann eine aktuell gesetzte \KOMAScript-Option
% eines Pakets oder einer Klasse abgefragt werden, sobald ein Paket oder eine
% Klasse das unterstützt. Das erste (optionale) Argument gibt dabei eine
% Anweisung an, die für die Optionenliste ausgeführt werden soll. Das zweite
% (nicht optionale Argument) ist der Name eines KOMA-Script-Pakets oder einer
% KOMA-Script-Klasse einschließlich Dateiendung, das dritte (nicht optionale
% Argument) ist der Name der Option, die abgefragt werden soll.
%    \begin{macrocode}
%<*koma>
\newcommand*{\KOMAoptionOf}[3][\@firstofone]{%
  \scr@ifundefinedorrelax{scr@kav@KOMA.#2}{%
    \PackageError{scrkbase}{\string\KOMAoptionOf\space not supported}{%
      #2 is not the name of a KOMA-Script package or\MessageBreak
      KOMA-Script class, that supports \string\KOMAoptionOf.}%
  }{%
    \begingroup
      \def\reserved@a{#1}%
      \KOMA@kav@defone\reserved@b{.#2}{#3}%
      \ifx\reserved@b\@empty
        \PackageWarning{scrkbase}{option `#3' for `#2' unset}%
        \endgroup
      \else
      \expandafter\expandafter\expandafter\endgroup
      \expandafter\reserved@a\expandafter{\reserved@b}%
    \fi
  }%
}
%</koma>
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\post@kopt@hook}
% \changes{v3.12}{2013/03/04}{entfernt}%^^A
% \end{macro}%^^A \post@kopt@hook
% \begin{macro}{\AfterKOMAoptions}
% \changes{v3.12}{2013/03/04}{Verwendung von \cs{AtEndOfFamilyOptions}}%^^A
% \changes{v3.23}{2017/02/16}{kein \cs{let}}%^^A
% Eine Option kann dafür sorgen, dass nach den Optionen noch etwas passiert.
%    \begin{macrocode}
%<*koma>
\newcommand*{\AfterKOMAoptions}{\AtEndOfFamilyOptions}
%</koma>
%    \end{macrocode}
% \end{macro}%^^A \AfterKOMAoptions
%
% \begin{macro}{\l@addto@macro}
% \changes{v2.8p}{2001/09/22}{neu (intern)} 
% Damit \cs{AfterKOMAoptions} lokal möglich ist, wird eine lokal arbeitende
% Variante von \cs{g@addto@macro} benötigt, wie sie hier vorgestellt wird.
% \changes{v2.95}{2006/06/02}{korrigiert, damit es sich bezüglich
%     Erweiterung um Makrodefinitonen mit Argumenten wie \cs{g@addto@macro}%^^A
%     verhält}
% \changes{v3.12}{2013/04/20}{veraltete \eTeX-freie Version entfernt}%^^A
% \changes{v3.12}{2013/04/20}{Warnung, falls eine inkompatible Definition
%     von \cs{l@addto@macro} entdeckt wird}
% \changes{v3.23}{2017/02/16}{in den Optionen-Teil verschoben}%^^A
%    \begin{macrocode}
%</body>
%<*base&prepare>
\@ifundefined{l@addto@macro}{}{%
  \begingroup
    \long\def\reserved@a#1#2{%
      \edef#1{\unexpanded\expandafter{#1#2}}%
    }%
    \ifx\reserved@a\l@addto@macro\else
      \PackageWarning{scrbase}{%
        Someone also uses macro name \string\l@addto@macro.\MessageBreak
        When KOMA-Script author decided to use macro name\MessageBreak
        \string\l@addto@macro\space first, there was no other
        free\MessageBreak
        LaTeX package using this macro name.\MessageBreak
        In the meantime other package authers decided to use\MessageBreak
        same macro name, but unfortunatly not all of those\MessageBreak
        are compatible with KOMA-Script's definition, e.g.,\MessageBreak
        while adding definitions with arguments to macros.\MessageBreak
        Because of such potentially incompatible definitions,\MessageBreak
        KOMA-Script will redefine the command now.\MessageBreak
        Please ask the author of the other package to\MessageBreak
        rename his macro, if a problem results in the\MessageBreak
        redefinition%
      }%
    \fi
  \endgroup
}
\long\def\l@addto@macro#1#2{%
  \edef#1{\unexpanded\expandafter{#1#2}}%
}%
%</base&prepare>
%<*body>
%    \end{macrocode}
% \end{macro}%^^A \l@addto@macro
%
% \begin{macro}{\l@addto@macro@a}
% \changes{v3.20}{2015/11/20}{neu (intern)}
% So eine ähnliche Anweisung benötige ich außerdem für den Fall, dass eine
% Anweisung erweitert werden soll, die genau ein obligatorisches Argument
% benötigt. Achtung! Diese Anweisung funktioniert deutlich weniger allgemein
% als \cs{l@addto@macro} und wird deshalb nie offiziell dokumentiert!
%    \begin{macrocode}
%<*base>
\begingroup
  \catcode`\^^A=\catcode`\#
  \@makeother\#
  \gdef\l@addto@macro@a^^A1{%
    \begingroup
      \@makeother\#
      \def\l@addto@macro@a@cmd{^^A1}%
      \l@addto@macro@a@
  }
  \gdef\l@addto@macro@a@^^A1{%
    \def\l@addto@macro@a@add{^^A1}%
    \l@addto@macro@a@@
  }
\endgroup
\begingroup
  \@makeother\#
  \gdef\l@addto@macro@a@@{%
    \@makeother\#
    \edef\reserved@a{%
      \detokenize{\endgroup\def}%
      \detokenize\expandafter{\l@addto@macro@a@cmd#1}%
      {%
        \expandafter\detokenize%
        \expandafter\expandafter\expandafter{\l@addto@macro@a@cmd{#1}}%
        \expandafter\detokenize\expandafter{\l@addto@macro@a@add}%
      }%
    }%
    \expandafter\scantokens\expandafter{\reserved@a}%
  }%
\endgroup
%</base>
%    \end{macrocode}
% \end{macro}%^^A \l@addto@macro@a
%
% \begin{macro}{\l@preto@macro}
% \changes{v3.20}{2015/11/25}{neu (intern)}%^^A
% In gewisser Weise das gleiche wie \cs{l@appto@macro}, allerdings wird vorn
% statt hinten angefügt.
%    \begin{macrocode}
%<*base>
\newcommand\l@preto@macro[2]{%
  \edef#1{\unexpanded{#2}\unexpanded\expandafter{#1}}%
}%
%</base>
%    \end{macrocode}
% \end{macro}%^^A \l@preto@macro
%
% \begin{macro}{\l@preto@macro@a}
% \changes{v3.20}{2015/11/25}{neu (intern)}
% So eine ähnliche Anweisung benötige ich außerdem für den Fall, dass eine
% Anweisung erweitert werden soll, die genau ein obligatorisches Argument
% benötigt. Achtung! Diese Anweisung funktioniert deutlich weniger allgemein
% als \cs{l@preto@macro} und wird deshalb nie offiziell dokumentiert!
%    \begin{macrocode}
%<*base>
\begingroup
  \catcode`\^^A=\catcode`\#
  \@makeother\#
  \gdef\l@preto@macro@a^^A1{%
    \begingroup
      \@makeother\#
      \def\l@preto@macro@a@cmd{^^A1}%
      \l@preto@macro@a@
  }
  \gdef\l@preto@macro@a@^^A1{%
    \def\l@preto@macro@a@add{^^A1}%
    \l@preto@macro@a@@
  }
\endgroup
\begingroup
  \@makeother\#
  \gdef\l@preto@macro@a@@{%
    \@makeother\#
    \edef\reserved@a{%
      \detokenize{\endgroup\def}%
      \detokenize\expandafter{\l@preto@macro@a@cmd#1}%
      {%
        \expandafter\detokenize\expandafter{\l@preto@macro@a@add}%
        \expandafter\detokenize%
        \expandafter\expandafter\expandafter{\l@preto@macro@a@cmd{#1}}%
      }%
    }%
    \expandafter\scantokens\expandafter{\reserved@a}%
  }%
\endgroup
%</base>
%    \end{macrocode}
% \end{macro}%^^A \l@preto@macro@a
%
% \begin{macro}{\KOMAoption}
% \changes{v2.98c}{2008/03/12}{Neue Anweisung}%^^A
% \changes{v3.12}{2013/03/04}{Einfacher Aufruf von \cs{FamilyOption}}
%    \begin{macrocode}
%<*koma>
\newcommand*{\KOMAoption}{\FamilyOption{KOMA}}
%</koma>
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\FamilyUnknownKeyValue}
% \changes{v3.10}{2011/09/12}{no error while processing global options}%^^A
% \changes{v3.11a}{2012/05/28}{prevent remove from list of unused global
%   options globally}%^^A
% \changes{v3.14}{2014/10/17}{\cs{long}}%^^A
% \changes{v3.30}{2020/02/25}{spurious space in warning message removed}%^^A
% Dieses Makro berichtet über Fehler wegen unbekannter Wertübergabe an einen
% Schlüssel. Das erste Argument ist die Familie, das zweite der Schlüssel,
% das dritte der Wert und das vierte die Liste der möglichen Werte.
%    \begin{macrocode}
%<*base>
\newcommand{\FamilyUnknownKeyValue}[4]{%
  \FamilyKeyStateUnknownValue
  \ifx\FamilyElseValues\@empty\else
    \PackageWarning{scrbase}{non empty \string\FamilyElseValue
      ignored.\MessageBreak
      Setting this command to a non empty\MessageBreak
      value for option `#2' of\MessageBreak
      family `#1' is deprecated,\MessageBreak
      but has been found%
    }%
  \fi
}
%</base>
%    \end{macrocode}
% \begin{macro}{\FamilyElseValues}
% \changes{v3.00}{2008/05/02}{Neue Anweisung}%^^A
% \changes{v3.12}{2013/03/04}{wird intern nicht mehr verwendet}%^^A
% Diese Anweisung konnte ursprünglich vor dem Setzen eines Wertes definiert
% werden, um bei einer etwaigen Fehlermeldung weitere Werte als erlaubt
% auszugeben. Am Ende von \cs{FamilySetBool} und \cs{FamilySetNumerical}
% wird die Anweisung automatisch zu \cs{@empty}. Seit Version~3.12 wird
% diese Anweisung jedoch nicht mehr ausgewertet.
%    \begin{macrocode}
%<*base>
\newcommand*{\FamilyElseValues}{}
%</base>
%    \end{macrocode}
% \end{macro}%^^A \FamilyUnknownKeyValue
% \end{macro}%^^A \FamilyElseValue
%
% \begin{macro}{\FamilyBoolKey}
% \changes{v3.00}{2008/04/30}{Neue Anweisung}%^^A
% Dieses Makro definiert einen Schlüssel für eine Familie. Dieser Schlüssel
% ist ein Schalter, der über diverse Werte geschaltet werden kann.
% Das erste, optionale Argument ist das Familienmitglied, das zweite,
% obligatorische Argument ist die Familie, das dritte der Name des Schlüssels,
% das vierte der Schalter.
%    \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{macro}{\FamilySetBool}
% \changes{v3.00}{2008/04/30}{Neue Anweisung}%^^A
% \changes{v3.11a}{2012/05/25}{Argument in Fehlermeldung korrigiert}%^^A
% \changes{v3.27}{2019/07/08}{Leeres Argument ist \texttt{true}}%^^A
% \changes{v3.28}{2019/11/18}{\cs{ifstr} umbenannt in \cs{Ifstr}}%^^A
% Über diese Anweisung wird der Wert dann gesetzt. Dabei ist das erste
% Argument die Familie, das zweite der Name des Schlüssels, das dritte der
% Schalter und das vierte schließlich der gewünschte Wert.
%    \begin{macrocode}
\newcommand*{\FamilySetBool}[4]{%
  \Ifstr{#4}{}{\@nameuse{#3true}\FamilyKeyStateProcessed}{%
    \Ifstr{#4}{true}{\@nameuse{#3true}\FamilyKeyStateProcessed}{%
      \Ifstr{#4}{on}{\@nameuse{#3true}\FamilyKeyStateProcessed}{%
        \Ifstr{#4}{yes}{\@nameuse{#3true}\FamilyKeyStateProcessed}{%
          \Ifstr{#4}{false}{\@nameuse{#3false}\FamilyKeyStateProcessed}{%
            \Ifstr{#4}{off}{\@nameuse{#3false}\FamilyKeyStateProcessed}{%
              \Ifstr{#4}{no}{\@nameuse{#3false}\FamilyKeyStateProcessed}{%
                \FamilyUnknownKeyValue{#1}{#2}{#4}{%
                  `true', `on', `yes', `false', `off', `no'%
                }%
              }%
            }%
          }%
        }%
      }%
    }%
  }%
  \let\FamilyElseValues\@empty
}
%</base>
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \selectlanguage{english}
% \begin{macro}{\FamilyInverseBoolKey}
% \changes{3.27}{2019/07/08}{new}
% \begin{macro}{\FamilySetInverseBool}
% \changes{3.27}{2019/07/08}{new}
% These are similar to \cs{FamilyBoolKey} and \cs{FamilySetBoolKey} but use
% inverse logic (true sets false and false sets true).
%    \begin{macrocode}
%<*base>
\newcommand*{\FamilyInverseBoolKey}[4][.\@currname.\@currext]{%
  \@ifundefined{if#4}{%
    \expandafter\newif\csname if#4\endcsname
    \@nameuse{#4true}%
  }{}%
  \DefineFamilyKey[{#1}]{#2}{#3}[true]{\FamilySetInverseBool{#2}{#3}{#4}{##1}}%
}
\newcommand*{\FamilySetInverseBool}[4]{%
  \FamilySetBool{#1}{#2}{#3}{#4}%
  \ifx\FamilyKeyState\FamilyKeyStateProcessed
    \expandafter\ifx\csname if#3\expandafter\endcsname\csname iftrue\endcsname
      \@nameuse{#3false}%
    \else
      \@nameuse{#3true}%
    \fi
  \fi
}
%</base>
%    \end{macrocode}
% \end{macro}%^^A \FamilySetInverseBool
% \end{macro}%^^A \FamilyInverseBoolKey
% \selectlanguage{ngerman}
%
% \begin{macro}{\KOMA@unknown@keyval}
% Dieses Makro berichtet über Fehler wegen unbekannter Wertübergabe an
% einen Schlüssel. Das erste Argument ist der Schlüssel, das zweite
% der Wert und das dritte die Liste der möglichen Werte.
%    \begin{macrocode}
%<*koma>
\newcommand*{\KOMA@unknown@keyval}{\FamilyUnknownKeyValue{KOMA}}
%</koma>
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\KOMA@ifkey}
% \changes{v3.02c}{2009/02/04}{definiert ebenfalls das Familienmitglied}%^^A
% \changes{v3.17}{2015/03/02}{ersetzt den gespeicherten Wert}%^^A
% Dieses Makro definiert einen Schlüssel, der einen Schalter an Hand des
% Wertes setzt. Als Werte sind "`\texttt{true}"', "`\texttt{false}"',
% "`\texttt{on}"', "`\texttt{off}"', "`\texttt{yes}"' und
% "`\texttt{no}"' erlaubt. Der Default-Wert für den Schalter ist
% grundsätzlich "`false"', so dass der Default-Wert für die Verwendung
% des Schküssels grundsätzlich "`true"' ist. Das erste Argument ist
% der Name des Schlüssels, der zweite ist der Name des Schalters. 
%    \begin{macrocode}
%<*koma>
\newcommand*{\KOMA@ifkey}[2][.\@currname.\@currext]{%
  \begingroup\edef\reserved@a{\noexpand\KOMA@@ifkey{#1}{#2}}%
  \expandafter\endgroup\reserved@a
}
\newcommand*{\KOMA@@ifkey}[3]{%
  \@ifundefined{if#3}{%
    \expandafter\newif\csname if#3\endcsname
  }{}%
  \KOMA@key[{#1}]{#2}[true]{%
    \KOMA@set@ifkey{#2}{#3}{##1}%
    \KOMA@kav@replacebool{#1}{#2}{#3}%
  }%
  \csname if#3\endcsname
    \KOMA@kav@xadd{#1}{#2}{true}%
  \else
    \KOMA@kav@xadd{#1}{#2}{false}%
  \fi
}
%</koma>
%    \end{macrocode}
% \begin{macro}{\KOMA@set@ifkey}
% Die eigentliche Arbeit bei der ganzen Sache wird von diesem internen
% Makro erledigt. Dabei wird der Name des Schlüssels zu Argument 1, der
% Name des Schalters zu Argument 2 und der Wert des Schlüssels wird
% Argument 3.
%    \begin{macrocode}
%<*koma>
\newcommand*{\KOMA@set@ifkey}{\FamilySetBool{KOMA}}
%</koma>
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\FamilyCounterKey}
% \changes{v3.12}{2013/11/05}{neu}%^^A
% \changes{v3.15}{2014/12/03}{er wird ein (optionaler) Säumniswert
%     unterstützt}%^^A
% \changes{v3.20}{2016/04/12}{\cs{@ifnextchar} replaced by
%     \cs{kernel@ifnextchar}}%^^A
% Dieses Makro definiert einen Schlüssel, der einen \LaTeX-Zähler an Hand
% des Wertes setzt. Das erste, optionale Argument ist das Familienmitglied,
% das zweite, obligatorische Argument ist die Familie, das dritte der Name
% des Schlüssels, das vierte, optionale ist der Säumniswert, das fünfte der
% Name des \LaTeX-Zählers. Erlaubt sind alle Integer-Werte.
% \begin{macro}{\Family@@Counter@@Key}
% \changes{v3.15}{2014/12/03}{neu (intern)}%^^A
% \begin{macro}{\Family@Counter@Key}
% \changes{v3.15}{2014/12/03}{neu (intern)}%^^A
%    \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}
% \begin{macro}{\FamilySetCounter}
% \changes{v3.12}{2013/11/05}{neu}%^^A
% \changes{v3.18a}{2015/07/06}{korrekte Verwendung von
%     \cs{FamilyKeyStateProcessed}}%^^A
% \changes{v3.23}{2017/02/23}{Leerzeichen durch \cs{relax} ersetzt}%^^A
% Über diese Anweisung wird der Wert dann gesetzt. Dabei ist das erste
% Argument die Familie, das zweite der Name des Schlüssels, das dritte der
% Name des \LaTeX-Zählers, das vierte schließlich der gewünschte Wert.
%    \begin{macrocode}
\newcommand*{\FamilySetCounter}[4]{%
  \begingroup
    \protected@edef\reserved@a{#4}%
    \def\reserved@b{\endgroup\value{#3}=#4\relax\FamilyKeyStateProcessed}%
    \expandafter\Ifiscount\expandafter{\reserved@a}{}{%
      \expandafter\Ifisdimen\expandafter{\reserved@a}{}{%
        \expandafter\Ifisskip\expandafter{\reserved@a}{}{%
          \expandafter\Ifisnumexpr\expandafter{\reserved@a}{}{%
            \expandafter\Ifisdimexpr\expandafter{\reserved@a}{}{%
              \expandafter\Ifisinteger\expandafter{\reserved@a}{}{%
                \expandafter\Ifiscounter\expandafter{\reserved@a}{%
                  \def\reserved@b{%
                    \endgroup\value{#3}=\value{#4}\FamilyKeyStateProcessed
                  }%
                }{%
                  \def\reserved@b{%
                    \endgroup
                    \FamilyUnknownKeyValue{#1}{#2}{#4}{%
                      integer numbers, counters, lengths, skips, dimens
                    }%
                  }%
                }%
              }%
            }%
          }%
        }%
      }%
    }%
  \reserved@b
}
%</base>
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \begin{macro}{\FamilyCounterMacroKey}
% \changes{v3.12}{2013/11/05}{neu}%^^A
% \changes{v3.15}{2014/12/03}{er wird ein (optionaler) Säumniswert
%     unterstützt}%^^A
% Diese Anweisung arbeitet fast wie \cs{FamilyCounterKey}, allerdings wird
% dabei nicht ein Zähler, sondern ein Marko auf einen Wert definiert. Dabei
% ist das erste (optionale) Argument das Mitglied, das zweite die Familie, das
% dritte der Schlüssel, das vierte (optionale) der Säumniswert, das fünfte das
% Makro.
% \begin{macro}{\FamilySetCounterMacro}
% \changes{v3.12}{2013/11/05}{neu}%^^A
% \changes{v3.15}{2014/12/17}{\cs{aftergroup} vor
%     \cs{FamilyKeyStateProcessed}}%^^A
% \changes{v3.18a}{2015/07/06}{korrekte Verwendung von
%     \cs{FamilyKeyStateProcessed}}%^^A
% \changes{v3.20}{2016/04/12}{\cs{@ifnextchar} replaced by
%     \cs{kernel@ifnextchar}}%^^A
% Diese Anweisung arbeitet fast wie \cs{FamilySetCounter}, allerdings wird
% nicht ein Zähler gesetzt, sondern ein Makro auf einen Wert definiert. Dabei
% ist das erste Argument die Familie, das zweite der Name des Schlüssels, das
% dritte das Makro, das vierte schließlich der gewünschte Wert.
% \begin{macro}{\Family@@Counter@@Macro@@Key}
% \changes{v3.15}{2014/12/03}{neu (intern)}%^^A
% \begin{macro}{\Family@Counter@Macro@Key}
% \changes{v3.15}{2014/12/03}{neu (intern)}%^^A
%    \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#4\else\let#4\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}}%
}
\newcommand*{\FamilySetCounterMacro}[4]{%
  \begingroup
%    \end{macrocode}
% An dieser Stelle wird nun der immer definierte Zähler page als lokaler
% Zähler verwendet. Das ist nur möglich, weil \cs{FamilySetCounter} nicht
% global mit \cs{setcounter} arbeitet, sondern lokal mit einer Zuweisung an
% \cs{value}.
%    \begin{macrocode}
    \FamilySetCounter{#1}{#2}{page}{#4}%
    \ifx\FamilyKeyState\FamilyKeyStateProcessed
      \edef\reserved@a{%
        \unexpanded{\endgroup\def#3}%
        {\the\value{page}}%
        \noexpand\FamilyKeyStateProcessed
      }%
    \else
      \def\reserved@a{%
        \endgroup
        \FamilyUnknownKeyValue{#1}{#2}{#4}{%
          integer numbers, counters, lengths, skips, dimens
        }%
      }%
    \fi
  \reserved@a
}    
%</base>
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\FamilyLengthKey}
% \changes{v3.12}{2013/11/05}{neu}%^^A
% \changes{v3.15}{2014/12/03}{er wird ein (optionaler) Säumniswert
%     unterstützt}%^^A
% \changes{v3.20}{2016/04/12}{\cs{@ifnextchar} replaced by
%     \cs{kernel@ifnextchar}}%^^A
% Dieses Makro definiert einen Schlüssel, der eine \LaTeX-Länge an Hand
% des Wertes setzt. Das erste, optionale Argument ist das Familienmitglied,
% das zweite, obligatorische Argument ist die Familie, das dritte der Name
% des Schlüssels, das vierte der name der \LaTeX-Länge.
% \begin{macro}{\Family@@Length@@Key}
% \changes{v3.15}{2014/12/03}{neu (intern)}%^^A
% \begin{macro}{\Family@Length@Key}
% \changes{v3.15}{2014/12/03}{neu (intern)}%^^A
%    \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{macro}{\FamilySetLength}
% \changes{v3.12}{2013/11/05}{neu}%^^A
% \changes{v3.15}{2015/01/02}{\cs{ifglueexpr} hinzugefügt}%^^A
% \changes{v3.18a}{2015/07/06}{korrekte Verwendung von
%     \cs{FamilyKeyStateProcessed}}%^^A
% \changes{v3.20}{2016/04/27}{Expansion vor dem Test}%^^A
% Über diese Anweisung wird der Wert dann gesetzt. Dabei ist das erste
% Argument die Familie, das zweite der Name des Schlüssels, das dritte der
% Name der \LaTeX-Länge, das vierte schließlich der gewünschte Wert.
%    \begin{macrocode}
\newcommand*{\FamilySetLength}[4]{%
  \begingroup
  \protected@edef\reserved@a{#4}%
%    \end{macrocode}
% Zusammen mit \cs{@defaultsunits} (siehe unten) wäre hier das sinnvoll:
%    \begin{macrocode}
%<*neveruse>
    \expandafter\Ifiscount\expandafter{\reserved@a}{%
      \aftergroup\@firstoftwo
    }{%
%</neveruse>
    \expandafter\Ifisdimen\expandafter{\reserved@a}{%
      \aftergroup\@firstoftwo
    }{%
      \expandafter\Ifisskip\expandafter{\reserved@a}{%
        \aftergroup\@firstoftwo
      }{%
%    \end{macrocode}
% Zusammen mit \cs{@defaultsunits} (siehe unten) wäre hier das sinnvoll:
%    \begin{macrocode}
%<*neveruse>
        \expandafter\Ifisnumexpr\expandafter{\reserved@a}{%
          \aftergroup\@firstoftwo
        }{%
%</neveruse>
          \expandafter\Ifisdimexpr\expandafter{\reserved@a}{%
            \aftergroup\@firstoftwo
          }{%
            \expandafter\Ifisglueexpr\expandafter{\reserved@a}{%
              \aftergroup\@firstoftwo
            }{%
              \expandafter\Ifisglue\expandafter{\reserved@a}{%
                \aftergroup\@firstoftwo
              }{%
                \aftergroup\@secondoftwo
              }%
            }%
          }%
%<*neveruse>
        }%
%</neveruse>
      }%
    }%
%<*neveruse>
  }%
%</neveruse>
  \endgroup
%    \end{macrocode}
% TODO: An der Stelle wäre etwas wie:
%    \begin{macrocode}
%<*neveruse>
  {\@defaultunits#3=#4pt\relax\@nnil\FamilyKeyStateProcessed}
%</neveruse>
% schön. Aber aus irgend einem Grund habe ich mich seinerzeit dafür
% entschieden, die einfacher Form zu wählen:
%    \begin{macrocode}
  {#3=#4\FamilyKeyStateProcessed}%
  {%
    \FamilyUnknownKeyValue{#1}{#2}{#4}{%
      length values,
%<*neveruse>
      counters,
%</neveruse>
      lengths, skips, dimens
    }%
  }%
}
%</base>
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \begin{macro}{\FamilyLengthMacroKey}
% \changes{v3.12}{2013/11/05}{neu}%^^A
% \changes{v3.15}{2014/12/03}{er wird ein (optionaler) Säumniswert
%     unterstützt}%^^A
% \begin{macro}{\FamilySetLengthMacro}
% \changes{v3.12}{2013/11/05}{neu}%^^A
% \changes{v3.14a}{2014/11/24}{fix: \cs{@tempskipa} statt \cs{@temskipa}}%^^A
% \changes{v3.15}{2014/12/17}{\cs{aftergroup} vor
%     \cs{FamilyKeyStateProcessed}}%^^A
% \changes{v3.15}{2015/01/02}{\cs{ifglueexpr} hinzugefügt}%^^A
% \changes{v3.18a}{2015/07/06}{korrekte Verwendung von
%     \cs{FamilyKeyStateProcessed}}%^^A
% \changes{v3.20}{2016/04/12}{\cs{@ifnextchar} ersetzt durch
%     \cs{kernel@ifnextchar}}%^^A
% \changes{v3.20}{2016/04/27}{interne Verwendung von \cs{FamilySetLength}}%^^A
% Diese Anweisungen arbeitet fast wie \cs{FamilyLengthKey} und
% \cs{FamilySetLengt}, allerdings wird nicht eine Länge gesetzt, sondern
% ein Makro auf einen Wert definiert. Dabei ist das erste Argument die
% Familie, das zweite der Name des Schlüssels, das dritte das Makro, das
% vierte schließlich der gewünschte Wert.
% \begin{macro}{\Family@@Length@@Macro@@Key}
% \changes{v3.15}{2014/12/03}{neu (intern)}%^^A
% \begin{macro}{\Family@Length@Macro@Key}
% \changes{v3.15}{2014/12/03}{neu (intern)}%^^A
%    \begin{macrocode}
%<*base>
\newcommand*{\FamilyLengthMacroKey}[3][.\@currname.\@currext]{%
  \kernel@ifnextchar [%]
    {\Family@@Length@@Macro@@Key{#1}{#2}{#3}}%
    {\Family@Length@Macro@Key{#1}{#2}{#3}}%
}
\newcommand*{\Family@@Length@@Macro@@Key}{}
\def\Family@@Length@@Macro@@Key#1#2#3[#4]#5{%
  \ifdefined#5\else\let#5\z@\fi
  \DefineFamilyKey[{#1}]{#2}{#3}[{#4}]{\FamilySetLengthMacro{#2}{#3}{#5}{##1}}%
}
\newcommand*{\Family@Length@Macro@Key}[4]{%
  \ifdefined#4\else\let#4\z@\fi
  \DefineFamilyKey[{#1}]{#2}{#3}{\FamilySetLengthMacro{#2}{#3}{#4}{##1}}%
}
\newcommand*{\FamilySetLengthMacro}[4]{%
  \begingroup
    \FamilySetLength{#1}{#2}{\@tempskipa}{#4}%
    \ifx\FamilyKeyState\FamilyKeyStateProcessed
      \edef\reserved@a{%
        \unexpanded{\endgroup\def#3}%
        {\the\@tempskipa}%
        \noexpand\FamilyKeyStateProcessed
      }%
    \else
      \def\reserved@a{%
        \endgroup
        \FamilyUnknownKeyValue{#1}{#2}{#4}{%
          length values, counters, lengths, skips, dimens
        }%
      }%
    \fi
  \reserved@a
}    
%</base>
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
%
% \begin{macro}{\FamilyUseLengthMacroKey}
% \changes{v3.20}{2016/04/27}{neu}%^^A
% \begin{macro}{\FamilySetUseLengthMacro}
% \changes{v3.20}{2016/04/27}{neu}%^^A
% Diese Anweisungen arbeitet fast wie \cs{FamilyLengthKey} und
% \cs{FamilySetLengt}, allerdings wird das Makro nicht als den Wert des Werts,
% sondern als den Wert selbst definiert. Eine Expansion des Werts findet nur
% für die Prüfung statt. Änderungen am Wert wirken sich also ggf. weiterhin
% aus. Dabei ist das erste Argument die Familie, das zweite der Name des
% Schlüssels, das dritte das Makro, das vierte schließlich der gewünschte
% Wert.
% \begin{macro}{\Family@@UseLength@@Macro@@Key}
% \changes{v3.20}{2016/04/27}{neu (intern)}%^^A
% \begin{macro}{\Family@USeLength@Macro@Key}
% \changes{v3.20}{2016/04/27}{neu (intern)}%^^A
%    \begin{macrocode}
%<*base>
\newcommand*{\FamilyUseLengthMacroKey}[3][.\@currname.\@currext]{%
  \kernel@ifnextchar [%]
    {\Family@@UseLength@@Macro@@Key{#1}{#2}{#3}}%
    {\Family@UseLength@Macro@Key{#1}{#2}{#3}}%
}
\newcommand*{\Family@@UseLength@@Macro@@Key}{}
\def\Family@@UseLength@@Macro@@Key#1#2#3[#4]#5{%
  \ifdefined#5\else\let#5\z@\fi
  \DefineFamilyKey[{#1}]{#2}{#3}[{#4}]{%
    \FamilySetUseLengthMacro{#2}{#3}{#5}{##1}%
  }%
}
\newcommand*{\Family@UseLength@Macro@Key}[4]{%
  \ifdefined#4\else\let#4\z@\fi
  \DefineFamilyKey[{#1}]{#2}{#3}{\FamilySetUseLengthMacro{#2}{#3}{#4}{##1}}%
}
\newcommand*{\FamilySetUseLengthMacro}[4]{%
  \begingroup
    \FamilySetLength{#1}{#2}{\@tempskipa}{#4}%
    \ifx\FamilyKeyState\FamilyKeyStateProcessed
      \def\reserved@a{%
        \endgroup\def#3{#4}%
        \FamilyKeyStateProcessed
      }%
    \else
      \def\reserved@a{%
        \endgroup
        \FamilyUnknownKeyValue{#1}{#2}{#4}{%
          length values, counters, lengths, skips, dimens
        }%
      }%
    \fi
  \reserved@a
}    
%</base>
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
%
% \begin{macro}{\FamilyNumericalKey}
% \changes{v3.00}{2008/04/30}{Neue Anweisung}%^^A
% \changes{v3.20}{2016/04/12}{\cs{@ifnextchar} replaced by
%     \cs{kernel@ifnextchar}}%^^A
% \begin{macro}{\Family@Numerical@Key}
% \changes{v3.00}{2008/05/28}{Neu (intern)}%^^A
% \changes{v3.08b}{2011/03/31}{fehlendes Argument bei \cs{ifundefined}}
% Ein ähnliches Makro definiert einen Schlüssel, der ein nummerisches Makro
% auf einen bestimmten Wert setzt. Dabei können auch verschiedene symbolische
% Werte auf denselben nummerischen Wert abgebildet werden. Das erste,
% optionale Argument ist das Familienmitglied, das zweite, obligatorische
% Argument ist die Familie, das dritte, obligatorische Argument ist der Name
% der Option, das vierte, optionale Artument ist der Defaultwert für den
% Schlüssel, das fünfte, obligatorische Argument ist der Name des Makros, das
% (in der Voreinstellung als 0) definiert werden soll, das sechste,
% obligatorische Argument ist die Liste der symbolischen und nummerischen
% Werte. Die Liste hat die Form:
% \{\emph{Symbol}\}\{\emph{Wert}\},\{\emph{Symbol}\}\{\emph{Wert}\}\dots
% Das interne Makro wird benötigt, um das vierte, optionale Argument zu
% ermöglichen. Dabei ist dann das erste Argument nicht mehr optional, sondern
% obligatorisch.
%    \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}
% \begin{macro}{\FamilySetNumerical}
% \changes{v3.11a}{2012/05/28}{call of \cs{FamilyUnknownKeyValue} outside of
%   local group}%^^A
% \changes{v3.25}{2017/12/04}{komplett leere Listenelemente werden
%   ignoriert}%^^A
% Die eigentliche Arbeit dabei wird von diesem Makro erledigt. Dabei
% wird die Familie zu Argument 1, der Name des Schlüssels zu Argument 2, der
% Name des Makros, das definiert werden soll zu Argument 3, die Liste zu
% Argument 4 und der Wert, auf den gesetzt werden soll, zu Argument 5.
%    \begin{macrocode}
\newcommand*{\FamilySetNumerical}[5]{%
  \begingroup
    \edef\@searched{#5}%
    \let\reserved@a=\@empty
    \let\reserved@b=\@empty
    \@tempswafalse
    \@for\@valuelist:=#4\do{%
      \ifx\@valuelist\@empty\else
        \if@tempswa\else
          \edef\reserved@c{\expandafter\@firstoftwo\@valuelist}%
          \edef\reserved@a{\reserved@a\reserved@b`\reserved@c'}%
          \edef\reserved@b{, }%
          \ifx\reserved@c\@searched
            \@tempswatrue
            \edef\reserved@a{\expandafter\@secondoftwo\@valuelist}%
          \fi
        \fi
      \fi
    }%
    \if@tempswa
      \edef\reserved@a{\endgroup
        \noexpand\@namedef{#3}{\reserved@a}%
        \noexpand\FamilyKeyStateProcessed
      }%
    \else
      \edef\reserved@a{\endgroup
        \noexpand\FamilyUnknownKeyValue{#1}{#2}{#5}{\reserved@a}%
      }%
    \fi
  \reserved@a
  \let\FamilyElseValues\@empty
}
%</base>
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\KOMA@ncmdkey}
% \changes{v3.02c}{2009/02/04}{definiert ebenfalls das Familienmitglied}%^^A
% \changes{v3.17}{2015/03/16}{neu implementiert mit Speicherung der
%     Werte und optionalem erstem Argument}%^^A
% \begin{macro}{\KOMA@@ncmdkey}
% \changes{v3.17}{2015/03/16}{neu (intern)}%^^A
% \begin{macro}{\KOMA@@@ncmdkey}
% \changes{v3.17}{2015/03/16}{neu (intern)}%^^A
% Wie \cs{FamilyNumericalKey} mit zwei entscheidenden Unterschieden:
% \begin{itemize}
% \item Die Familien ist immer \texttt{KOMA} und entfällt daher als zweites
%   Argument.
% \item Der gespeicherte Wert wird ausgetauscht. Daher kann es nicht nur für
%   Optionen verwendet werden, bei denen die Werte exklusiv sind.
% \end{itemize}
% Wichtig: Die Voreinstellung muss anschließend noch in jedem Fall mit
% \cs{KOMA@kav@add} gesetzt werden!
%    \begin{macrocode}
%<*koma>
\newcommand*{\KOMA@ncmdkey}[2][.\@currname.\@currext]{%
  \begingroup\edef\reserved@a{\noexpand\KOMA@@ncmdkey{#1}{#2}}%
  \expandafter\endgroup\reserved@a
}
\newcommand*{\KOMA@@ncmdkey}[2]{%
  \kernel@ifnextchar [%]
    {\KOMA@@@ncmdkey{#1}{#2}}{\KOMA@@@ncmdkey{#1}{#2}[]}
}
\newcommand*{\KOMA@@@ncmdkey}{}
\def\KOMA@@@ncmdkey#1#2[#3]#4#5{%
  \@ifundefined{#4}{\@namedef{#4}{0}}{}%
  \ifx\relax#3\relax
    \KOMA@key[{#1}]{#2}{%
      \KOMA@set@ncmdkey{#2}{#4}{#5}{##1}%
      \KOMA@kav@replacevalue{#1}{#2}{##1}%
    }%
  \else
    \KOMA@key[{#1}]{#2}[{#3}]{%
      \KOMA@set@ncmdkey{#2}{#4}{#5}{##1}%
      \KOMA@kav@replacevalue{#1}{#2}{##1}%
    }%
  \fi
}
%</koma>
%    \end{macrocode}
% \begin{macro}{\KOMA@set@ncmdkey}
% Die eigentliche Arbeit dabei wird wahlweise von diesem Makro erledigt. Dabei
% wird der Name des Schlüssels zu Argument 1, der Name des Makros,
% das definiert werden soll zu Argument 2, die Liste zu Argument 3 und
% der Wert, auf den gesetzt werden soll, zu Argument 4. Dabei wird allerdings
% kein gespeicherter Wert ersetzt!
%    \begin{macrocode}
%<*koma>
\newcommand*{\KOMA@set@ncmdkey}{\FamilySetNumerical{KOMA}}
%</koma>
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
%
% \begin{macro}{\FamilyStringKey}
% \changes{v3.08}{2010/11/05}{Neue Anweisung}%^^A
% \changes{v3.08b}{2011/03/31}{\cs{Family@String@Key} und
%   \cs{Family@@String@@Key} vertauscht}%^^A
% \changes{v3.20}{2016/04/12}{\cs{@ifnextchar} replaced by
%  \cs{kernel@ifnextchar}}%^^A
% \begin{macro}{\Family@String@Key}
% \changes{v3.08}{2010/11/05}{Neu (intern)}%^^A
% \begin{macro}{\Family@@String@@Key}
% \changes{v3.08}{2010/11/05}{Neu (intern)}%^^A
% Ein ähnliches Makro definiert einen Schlüssel, der ein Makro auf einen
% beliegigen Wert setzt. Das erste, optionale Argument ist das
% Familienmitglied, das zweite, obligatorische Argument ist die Familie, das
% dritte, obligatorische Argument ist der Name der Option, das vierte,
% optionale Artument ist der Defaultwert für den Schlüssel, das fünfte,
% obligatorische Argument ist das Makros, das (in der Voreinstellung
% als leer) definiert werden soll. Die internen Makro werden benötigt, um das
% vierte, optionale Argument zu ermöglichen. Dabei ist dann das erste Argument
% nicht mehr optional, sondern obligatorisch.
%    \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}}%
}
\newcommand{\Family@String@Key}[4]{%
  \DefineFamilyKey[{#1}]{#2}{#3}{\def#4{##1}\FamilyKeyStateProcessed}%
}
%</base>
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
%
% \begin{macro}{\FamilyCSKey}
% \changes{v3.25}{2017/12/08}{Neue Anweisung}%^^A
% \begin{macro}{\Family@CS@Key}
% \changes{v3.25}{2017/12/08}{Neu (intern)}%^^A
% \begin{macro}{\Family@@CS@@Key}
% \changes{v3.25}{2017/12/08}{Neu (intern)}%^^A
% \changes{v3.26}{2018/11/06}{Es wird wirklich diese Anweisung (statt erneut
%   \cs{Family@@String@@Key}) definiert}%^^A
% Ein ähnliches Makro definiert einen Schlüssel, der eine Befehlssequenz auf
% einen beliegigen Wert setzt. Das erste, optionale Argument ist das
% Familienmitglied, das zweite, obligatorische Argument ist die Familie, das
% dritte, obligatorische Argument ist der Name der Option, das vierte,
% optionale Artument ist der Defaultwert für den Schlüssel, das fünfte,
% obligatorische Argument ist der Name des Makros, das (in der Voreinstellung
% als leer) definiert werden soll. Die internen Makro werden benötigt, um das
% vierte, optionale Argument zu ermöglichen. Dabei ist dann das erste Argument
% nicht mehr optional, sondern obligatorisch.
%    \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}}%
}
\newcommand{\Family@CS@Key}[4]{%
  \DefineFamilyKey[{#1}]{#2}{#3}{\@namedef{#4}{##1}\FamilyKeyStateProcessed}%
}
%</base>
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
%
% \begin{macro}{\KOMA@DeclareDeprecatedOption}
% \changes{v3.01a}{2008/11/20}{neu (intern)}%^^A
% \changes{v3.20}{2016/04/12}{\cs{@ifnextchar} replaced by
%     \cs{kernel@ifnextchar}}%^^A
% \begin{macro}{\KOMA@@DeclareDeprecatedOption}
% \changes{v3.01a}{2008/11/20}{neu (intern)}%^^A
% \begin{macro}{\KOMA@@@DeclareDeprecatedOption}
% \changes{v3.01a}{2008/11/20}{neu (intern)}%^^A
% Mit Hilfe dieses Makros kann eine Option definiert werden, die
% eigentlich obsolete ist. Statt dieser Option wird dann ein Schlüssel
% verwendet. Das erste Argument ist optional und muss dann der Paketname
% sein. Ist es nicht gesetzt, so wird stattdessen die Klasse
% \cs{KOMAClassName} angenommen. Das zweite Argument ist der Name der
% Option. Das vierte Argument ist das Setzen des gewünschten Schlüssels.
%    \begin{macrocode}
%<*koma>
\newcommand*{\KOMA@DeclareDeprecatedOption}{%
  \kernel@ifnextchar [%]
  {\KOMA@@DeclareDeprecatedOption}%
  {\KOMA@@@DeclareDeprecatedOption{\ClassWarningNoLine{\KOMAClassName}}}%
}
\newcommand*{\KOMA@@DeclareDeprecatedOption}[1][]{%
  \KOMA@@@DeclareDeprecatedOption{\PackageWarningNoLine{#1}}%
}
\newcommand*{\KOMA@@@DeclareDeprecatedOption}[3]{%
  \DeclareOption{#2}{\KOMA@UseDeprecatedOption{#1}{#2}{#3}}%
}
%    \end{macrocode}
% \begin{macro}{\KOMA@UseDeprecatedOption}
% \changes{v3.01a}{2008/11/20}{neu (intern)}%^^A
% \changes{v3.12}{2013/03/04}{Test für \texttt{version!=first}}%^^A
% \changes{v3.12a}{2014/01/22}{vertauschte Logic für 
%     \texttt{version!=first} korrigiert}%^^A
% \changes{v3.22}{2016/07/29}{diverse \cs{detokenize} eingefügt}%^^A
% Die eigentliche Arbeit wird von diesem Makro erledigt. Die Argumente sind
% 1. Meldungsbefehl, 2. obsolete Option, 3. Setzen des Schlüssels.
%    \begin{macrocode}
\newcommand*{\KOMA@UseDeprecatedOption}[3]{%
  \begingroup
    \scr@ifundefinedorrelax{KV@KOMA.\@currname.\@currext @version}{%
      \edef\reserved@a{\noexpand\endgroup
        \noexpand#1{%
          You've used obsolete 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 obsolete option `\detokenize{#2}'.\noexpand\MessageBreak
          Usage of this option indicates an old document\noexpand\MessageBreak
          and changes compatibility level using\noexpand\MessageBreak
          `\detokenize{#3},version=first,\noexpand\MessageBreak
          enabledeprecatedfontcommands' that may result\noexpand\MessageBreak
          in further warnings.\noexpand\MessageBreak
          If you don't want this, you should simply\noexpand\MessageBreak
          replace option `\detokenize{#2}' by `\detokenize{#3}'%
        }%
        \noexpand\KOMAExecuteOptions{%
          #3,version=first}%
        \noexpand\ExecuteOptions{enabledeprecatedfontcommands}%
        \noexpand\def\noexpand\CurrentOption{\CurrentOption}%
      }%
    }%
  \reserved@a
}
%</koma>
%    \end{macrocode}
% \end{macro}%^^A \KOMA@UseDeprecatedOption
% \end{macro}%^^A \KOMA@@@DeclareDeprecatedOption
% \end{macro}%^^A \KOMA@@DeclareDeprecatedOption
% \end{macro}%^^A \KOMA@DeclareDeprecatedOption
%
%
% \begin{macro}{\KOMA@DeclareStandardOption}
% \changes{v3.01a}{2008/11/21}{neu (intern)}%^^A
% \changes{v3.20}{2016/04/12}{\cs{@ifnextchar} replaced by
%     \cs{kernel@ifnextchar}}%^^A
% \begin{macro}{\KOMA@@DeclareStandardOption}
% \changes{v3.01a}{2008/11/21}{neu (intern)}%^^A
% \begin{macro}{\KOMA@@@DeclareStandardOption}
% \changes{v3.01a}{2008/11/21}{neu (intern)}%^^A
% Mit Hilfe dieses Makros kann eine Option definiert werden, die
% eigentlich obsolete ist. Statt dieser Option wird dann ein Schlüssel
% verwendet. Das erste Argument ist optional und muss dann der Paketname
% sein. Ist es nicht gesetzt, so wird stattdessen die Klasse
% \cs{KOMAClassName} angenommen. Das zweite Argument ist der Name der
% Option. Das vierte Argument ist das Setzen des gewünschten Schlüssels.
%    \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}}%
}
%    \end{macrocode}
% \begin{macro}{\KOMA@UseStandardOption}
% \changes{v3.01a}{2008/11/21}{neu (intern)}%^^A
% Die eigentliche Arbeit wird von diesem Makro erledigt. Die Argumente sind
% 1. Meldungsbefehl, 2. obsolete Option, 3. Setzen des Schlüssels.
%    \begin{macrocode}
\newcommand*{\KOMA@UseStandardOption}[3]{%
  \begingroup
    \edef\reserved@a{\noexpand\endgroup
      \noexpand#1{%
        You've used standard option `#2'.\noexpand\MessageBreak
        This is correct!\noexpand\MessageBreak
        Internally I'm using `#3'.\noexpand\MessageBreak
        If you'd like to set the option with \string\KOMAoptions,%
        \noexpand\MessageBreak
        you'd have to use `#3' there\noexpand\MessageBreak
        instead of `#2', too%
      }%
      \noexpand\KOMAExecuteOptions{#3}%
      \noexpand\def\noexpand\CurrentOption{\CurrentOption}%
    }%
  \reserved@a
}
%</koma>
%    \end{macrocode}
% \begin{macro}{\scr@sr@co}
% \changes{v2.96}{2006/08/20}{neu (intern)}%^^A
% \changes{v3.12a}{2014/01/22}{beseitigt}%^^A
% \end{macro}%^^A \scr@sr@co
% \end{macro}%^^A \KOMA@UseStandardOption
% \end{macro}%^^A \KOMA@@@DeclareStandardOption
% \end{macro}%^^A \KOMA@@DeclareStandardOption
% \end{macro}%^^A \KOMA@DeclareStandardOption
%
%
% \begin{macro}{\KOMA@DeclareObsoleteOption}
% \changes{v2.96}{2006/08/20}{\cs{CurrentOption wir geschützt}}
% \changes{v3.12}{2013/03/04}{entfernt weil unbenutzt}%^^A
% \begin{macro}{\KOMA@@DeclareObsoleteOption}
% \changes{v2.98c}{2008/02/18}{neu (intern)}%^^A
% \changes{v3.12}{2013/03/04}{entfernt weil unbenutzt}%^^A
% \begin{macro}{\KOMA@@@DeclareObsoleteOption}
% \changes{v2.98c}{2008/02/18}{neu (intern)}%^^A
% \changes{v3.12}{2013/03/04}{entfernt weil unbenutzt}%^^A
% \begin{macro}{\KOMA@iv@DeclareObsoleteOption}
% \changes{v2.98c}{2008/02/18}{neu (intern)}%^^A
% \changes{v3.12}{2013/03/04}{entfernt weil unbenutzt}%^^A
% \begin{macro}{\KOMA@UseObsoleteOption}
% \changes{v2.97c}{2007/04/19}{neu (intern)}%^^A
% \changes{v3.12}{2013/03/04}{entfernt weil unbenutzt}%^^A
% \end{macro}%^^A \KOMA@UseObsoleteOption
% \end{macro}%^^A \KOMA@iv@DeclareObsoleteOption
% \end{macro}%^^A \KOMA@iii@DeclareObsoleteOption
% \end{macro}%^^A \KOMA@ii@DeclareObsoleteOption
% \end{macro}%^^A \KOMA@i@DeclareObsoleteOption
%
%
% \begin{macro}{\KOMA@newdeprecatedcommand}
% \changes{v3.12}{2013/03/04}{renamed \cs{KOMA@newobsoletecommand} into
%     \cs{KOMA@newdeprecatedcommand}}
% Mit Hilfe dieses Makros kann ein Makro definiert werden, das
% eigentlich obsolete ist. Das Makro verwendet dann schlicht einen
% Schlüssel. Das erste Argument ist optional und muss dann entweder
% \cs{PackageInfo}, \cs{PackageInfoNoLine}, \cs{PackageWarning} oder
% \cs{PackageWarningNoLine} sein. Das zweite Argument ist das Makro.
% Das dritte Argument ist das Setzen des gewünschten Schlüssels. Das
% definierte Makro selbst hat Schaltercharakter, ist also nicht
% \cs{long} und versteht auch keine Argumente.
%    \begin{macrocode}
%<*koma>
\newcommand*{\KOMA@newdeprecatedcommand}[3][\@gobbletwo]{%
  \newcommand*{#2}{\KOMA@UseDeprecatedCommand{#1}{\string#2}{#3}}%
}
%    \end{macrocode}
% \begin{macro}{\KOMA@UseDeprecatedCommand}
% \changes{v2.97c}{2007/04/19}{neu (intern)}%^^A
% \changes{v3.12}{2013/03/04}{renamed \cs{KOMA@UseObsoleteCommand} into
%     \cs{KOMA@UseDeprecatedCommand}}
% Die eigentliche Arbeit wird von diesem Makro erledigt. Die Argumente sind
% dieselben.
%    \begin{macrocode}
\newcommand*{\KOMA@UseDeprecatedCommand}[3]{%
  #1{%
    scrkbase%
  }{%
    You've used deprecated command `#2'.\MessageBreak
    \protect\KOMAoptions{#3} will be used instead.\MessageBreak
    You should also replace `#2' by `\protect\KOMAoptions{#3}'%
  }%
  \KOMAoptions{#3}%
}
%</koma>
%    \end{macrocode}
% \end{macro}%^^A \KOMA@UseDeprecatedCommand
% \end{macro}%^^A \KOMA@newdeprecatedcommand
%
%
% \selectlanguage{english}
% \subsection{Do Hook Mechanism}
% \label{sec:dohook}
%
% \changes{v3.27}{2019/02/02}{Do hook mechanism added}%^^A
% 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{macro}{\ForDoHook}
% \changes{v3.27}{2019/02/05}{New}%^^A
% \changes{v3.28}{2019/11/18}{\cs{ifstr} umbenannt in \cs{Ifstr}}%^^A
% \changes{v3.30}{2020/03/07}{\cs{loop}\dots\cs{repeat} inside group}%^^A
% \changes{v3.30}{2020/03/07}{using \cs{rloop} instead of \cs{loop}}%^^A
% 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{macro}{\SplitDoHook}
% \changes{v3.27}{2019/02/04}{New}%^^A
% \changes{v3.28}{2019/11/18}{\cs{ifstr} umbenannt in \cs{Ifstr}}%^^A
% 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}{New internal}%^^A
% 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}{New internal}%^^A
%    \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{macro}
% \end{macro}
%
% \begin{macro}{\ExecuteDoHook}
% \changes{v3.27}{2019/02/02}{New}%^^A
% 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{macro}
%
% \begin{macro}{\AddtoDoHook}
% \changes{v3.27}{2019/02/02}{New}%^^A
% 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{macro}
%
% \begin{macro}{\AddtoOneTimeDoHook}
% \changes{v3.27}{2019/02/02}{New}%^^A
% \changes{v3.28}{2019/11/18}{\cs{ifstr} umbenannt in \cs{Ifstr}}%^^A
% Arguments:
% \begin{description}
% \item[\meta{specificator}:]
%   \meta{string} or \meta{string}\texttt{/}\meta{specificator}
% \item[\meta{element}:]
%   a \LaTeX command, that expects exactly one argument.
% \end{description}
% This is almost the same as \cs{AddtoDoHook} but a hook added by this command
% is executed only once.
%    \begin{macrocode}
\newcommand*{\AddtoOneTimeDoHook}[2]{%
  \Ifstr{#1}{}{%
    \PackageError{scrbase}{empty hook specificator}{%
      As hook specificators can never be empty, the first argument\MessageBreak
      of \string\AddtoDoHook\space must expand to an not empty string.%
    }%
  }{%
    \scr@ifundefinedorrelax{scr@otdohook@#1}{\@namedef{scr@otdohook@#1}{}}{}%
    \expandafter\l@addto@macro\csname scr@otdohook@#1\endcsname{%
      \scr@hook@do{#2}%
    }%
  }%
}
%</base>
%    \end{macrocode}
% \end{macro}
%
% \selectlanguage{ngerman}
%
% \iffalse
%</body>
% \fi
%
% \Finale
%
\endinput
%
% end of file `scrkernel-basics.dtx'
%%% Local Variables:
%%% mode: doctex
%%% TeX-master: t
%%% End:
