% \iffalse meta-comment
%/GitFileInfo=tudscr-base.dtx
%
%  TUD-Script -- Corporate Design of Technische Universität Dresden
% ----------------------------------------------------------------------------
%
%  Copyright (C) Falk Hanisch <hanisch.latex@outlook.com>, 2012-2022
%
% ----------------------------------------------------------------------------
%
%  This work may be distributed and/or modified under the conditions of the
%  LaTeX Project Public License, either version 1.3c of this license or
%  any later version. The latest version of this license is in
%    http://www.latex-project.org/lppl.txt
%  and version 1.3c or later is part of all distributions of
%  LaTeX version 2008-05-04 or later.
%
%  This work has the LPPL maintenance status "maintained".
%
%  The current maintainer and author of this work is Falk Hanisch.
%
% ----------------------------------------------------------------------------
%
% \fi
%
% \iffalse ins:batch + dtx:driver
%<*ins>
\ifx\documentclass\undefined
  \input docstrip.tex
  \ifToplevel{\batchinput{tudscr.ins}}
\else
  \let\endbatchfile\relax
\fi
\endbatchfile
%</ins>
%<*dtx>
\ProvidesFile{tudscr-base.dtx}[2022/08/09]
\RequirePackage{tudscr-gitinfo}
\documentclass[english,ngerman,xindy]{tudscrdoc}
\iftutex
  \usepackage{fontspec}
\else
  \usepackage[T1]{fontenc}
  \usepackage[ngerman=ngerman-x-latest]{hyphsubst}
\fi
\usepackage{babel}
\usepackage{tudscrfonts}
\usepackage[babel]{microtype}

\GitHubBase{\TUDScriptRepository}
\begin{document}
  \author{Falk Hanisch\TUDScriptContactTitle}
  \maketitle
  \tableofcontents
  \DocInput{\filename}
\end{document}
%</dtx>
% \fi
%
% \selectlanguage{ngerman}
%
% \changes{v2.02}{2014/06/23}{Paket \pkg{titlepage} nicht weiter unterstützt}^^A
%
%
%
% \section{Das Paket \pkg{tudscrbase} -- Basisdefinitionen für \TUDScript}
%
% Für die Erstellung der \TUDScript-Klassen werden die dafür benötigten Pakete
% eingebunden und Steuerungsbefehle definiert. Die Klassen sowie einige Pakete
% benötigen das Paket und laden dieses auch.
%
%    \begin{macrocode}
%<*package&base>
\ProvidesPackage{tudscrbase}[%
%!TUD@Version
  package (basics for the bundle)%
]
%</package&base>
%    \end{macrocode}
%
% \ToDo{
%   Schnittstelle äquivalent zu \cs{KOMA@kav@...}? Dann hierfür 
%   \pkg{etoolbox}-Listen und \cs{listadd} sowie \cs{listremove} nutzen
% }[v2.08]
% \ToDo{
%   Teile im Quelltext suchen, die nur einmalig durchlaufen werden müssen 
%   (bspw. notwendige Pakete und Schriften) und über aux-Eintrag abkürzen?!
%   siehe \cs{TUD@CheckPackage}
% }[v2.07]
%^^A\BeforeClosingMainAux{%
%^^A  \if@tud@xxx\if@filesw%
%^^A    \immediate\write\@mainaux{%
%^^A      \string\global\string\let\string\tud@test@xxx\string\relax%
%^^A    }%
%^^A  \fi\fi%
%^^A}
%
%
%
%    \begin{macrocode}
%<*load>
\RequirePackage{tudscrbase}[%
%!TUD@Version
]
%</load>
%    \end{macrocode}
%
% \iffalse
%<*package&base>
% \fi
%
% \subsection{Notwendige Kompatibilitätseinstellung für \KOMAScript}
%
% Die installierte Version und die gewählte Kompatibilitätseinstellung von 
% \KOMAScript{} wird gerpüft.
%    \begin{macrocode}
\AtBeginDocument{%
  \ifcsundef{scr@v@first}{}{%
%    \end{macrocode}
% Es wird gerpüft, ob die mindestens benötigte \KOMAScript-Version
% (v\csuse{TUD@KOMAVersionNumber}) verfügbar ist. Sollte dies nicht der Fall
% sein, wird ein Fehler erzeugt.
%    \begin{macrocode}
    \ifcsundef{scr@v@\TUD@KOMAVersionNumber}{%
      \PackageError{tudscrbase}{%
        KOMA-Script v\TUD@KOMAVersionNumber\space is required%
      }{%
        \TUD@Version\space must be used at least with\MessageBreak%
        \TUD@KOMAVersion, but only\MessageBreak%
        \KOMAScriptVersion\space was found.%
      }%
    }{%
%    \end{macrocode}
% Ist die mindestens nötige Version von \KOMAScript{} installiert, wird 
% geprüft, ob die Kompatibilitätseinstellung akzeptabel ist.
%    \begin{macrocode}
      \expandafter\ifnum\scr@v@is@lt{3.12}\relax%
        \PackageError{tudscrbase}{%
          KOMA-Script compatibility level too low%
        }{%
          \TUD@Version\space must be used at least with\MessageBreak%
          `version=3.12' KOMA-Script compatibility option.%
        }%
      \fi%
    }%
  }%
}
%    \end{macrocode}
%
% \subsection{Notwendige Pakete für \TUDScript}
%
% \changes{v2.06f}{2020/01/14}{Anpassungen für \pkg{scrbase} \val{v3.28}}^^A
% Das Paket \pkg{scrbase} wird zur Optionsdefinition benötigt, \pkg{scrlfile} 
% für verschiedene Hooks vor sowie nach Klassen und Paketen.
%    \begin{macrocode}
\RequirePackage{scrbase}[%
%!TUD@KOMAVersion
]
%    \end{macrocode}
% Die folgenden Pakete werden für die Manipulation bereits definierter
% Makros, zur erweiterten Auswertung boolescher Ausdrücke und allgemein zur
% Ablaufsteuerung benötigt.
%    \begin{macrocode}
\RequirePackage{iftex}
\RequirePackage{etoolbox}
\RequirePackage{xpatch}
\RequirePackage{letltxmacro}
%    \end{macrocode}
% Das Paket \pkg{kvsetkeys} erweitert \pkg{keyval} um die Möglichkeit, das
% Verhalten bei der Angabe eines nicht definierten Schlüssels festzulegen.
% \ToDo{sollte auch mit KOMA-Option \val{@else@} gehen, besser raus}[v2.07]
%    \begin{macrocode}
\RequirePackage{kvsetkeys}
%    \end{macrocode}
% Mit dem Paket \pkg{trimspaces} können eventuell vorhandene Leerzeichen aus
% einem Argument entfernt. Dies wird beispielsweise beim Einlesen von Feldern 
% oder bei der expliziten Auswahl einer Schrift des \CD sgenutzt.
%    \begin{macrocode}
\RequirePackage{trimspaces}
%    \end{macrocode}
% Für \pkg{hyperref} werden \cs{TUDScript} und \cs{KOMAScript} deaktiviert.
%    \begin{macrocode}
\AfterPackage*{hyperref}{%
  \pdfstringdefDisableCommands{%
    \def\TUDScript{TUD-Script}%
    \def\KOMAScript{KOMA-Script}%
  }%
}
%    \end{macrocode}
%
% \subsection{Grundlegende Befehle für \TUDScript}
% \subsubsection{Erweiterte Definition von \TeX-Primitiven}
%
% Mit \LaTeX{} lassen sich einige Primitiven definieren, ohne zu Prüfen, ob 
% ggf. bereits eine Definition vorhanden ist. Dies wird hiermit umgangen.
% \begin{macro}{\tud@newif}
% \changes{v2.06o}{2022/07/27}{neu}^^A
% \begin{macro}{\tud@newcount}
% \changes{v2.06o}{2022/07/27}{neu}^^A
% \begin{macro}{\tud@newtoks}
% \changes{v2.06o}{2022/07/27}{neu}^^A
% \begin{macro}{\tud@newread}
% \changes{v2.06o}{2022/07/27}{neu}^^A
% \begin{macro}{\tud@newwrite}
% \changes{v2.06o}{2022/07/27}{neu}^^A
%    \begin{macrocode}
\newcommand*\tud@newif[1]{\@ifdefinable#1{\newif#1}}
\newcommand*\tud@newcount[1]{\@ifdefinable#1{\newcount#1}}
\newcommand*\tud@newtoks[1]{\@ifdefinable#1{\newtoks#1}}
\newcommand*\tud@newread[1]{\@ifdefinable#1{\newread#1}}
\newcommand*\tud@newwrite[1]{\@ifdefinable#1{\newwrite#1}}
%    \end{macrocode}
% \end{macro}^^A \tud@newwrite
% \end{macro}^^A \tud@newread
% \end{macro}^^A \tud@newtoks
% \end{macro}^^A \tud@newcount
% \end{macro}^^A \tud@newif
%
% \subsubsection{Definition von Längen-Registern}
%
% \begin{macro}{\tud@newglue}
% \changes{v2.06o}{2022/07/28}{neu}^^A
% \begin{macro}{\tud@newdim}
% \changes{v2.06o}{2022/07/28}{neu}^^A
% \begin{macro}{\tud@setglue}
% \changes{v2.06o}{2022/07/28}{neu}^^A
% \begin{macro}{\tud@setdim}
% \changes{v2.06o}{2022/07/28}{neu}^^A
% \begin{macro}{\tud@addtoglue}
% \changes{v2.06o}{2022/07/28}{neu}^^A
% \begin{macro}{\tud@addtodim}
% \changes{v2.06o}{2022/07/28}{neu}^^A
% Der \LaTeX"~Kernel stellt lediglich \cs{newlength} zur Verfügung, um bereits 
% bestehende Makros nicht zu überschreiben. Soll jedoch ein \cs{dimen}-Register 
% definiert werden, gibt es keinen entsprechenden Befehl. Auch die Zuweisung 
% von Längenwerte kann mit \cs{setlength} nicht sauber erfolgen, da nicht 
% geprüft wird, ob die Zuweisung an ein \cs{skip}"~ oder \cs{dimen}-Register 
% erfolgt. Deshalb werden hier für diese Aufgabe interne Befehle definiert.
% Siehe dazu auch \GitHubRepo(latex3/latex2e)<227>.
%    \begin{macrocode}
\newcommand*\tud@newglue[1]{\@ifdefinable#1{\newskip#1}}
\newcommand*\tud@newdim[1]{\@ifdefinable#1{\newdimen#1}}
\newrobustcmd*\tud@setglue[2]{%
  \ifdefdimen{#1}{%
    \PackageWarning{tudscrbase}{%
      You tried to assign dimen \string#1\MessageBreak%
      so \string\tud@setdim\space is used%
    }%
    \tud@setdim{#1}{#2}%
  }{%
    \setlength#1{\glueexpr#2\relax}%
  }%
}
\newrobustcmd*\tud@setdim[2]{%
  \begingroup%
    \@tud@res@swafalse%
    \setlength\@tempskipa{\glueexpr#2\relax}%
    \ifdim\gluestretch\@tempskipa=\z@\relax\else%
      \@tud@res@swatrue%
    \fi%
    \ifdim\glueshrink\glueexpr\@tempskipa\relax=\z@\relax\else%
      \@tud@res@swatrue%
    \fi%
    \if@tud@res@swa%
      \PackageWarning{tudscrbase}{%
        You tried to use \string\tud@setdim\string#1\MessageBreak%
        with glue \detokenize{#2} (\the\@tempskipa)\MessageBreak%
        but only the base value is used%
      }%
    \fi%
  \endgroup%
  \setlength#1{\dimexpr\glueexpr#2\relax\relax}%
}
\newrobustcmd*\tud@addtoglue[2]{%
  \tud@setglue#1{\glueexpr#1+#2\relax}%
}
\newrobustcmd*\tud@addtodim[2]{%
  \tud@setdim#1{\glueexpr#1+#2\relax}%
}
%    \end{macrocode}
% \end{macro}^^A \tud@addtodim
% \end{macro}^^A \tud@addtoglue
% \end{macro}^^A \tud@setdim
% \end{macro}^^A \tud@setglue
% \end{macro}^^A \tud@newdim
% \end{macro}^^A \tud@newglue
% \begin{macro}{\tud@res@glue}
% \changes{v2.06}{2019/06/21}{neu}^^A
% Und gleich noch eine temporäre Länge mit dazu.
%    \begin{macrocode}
\tud@newglue\tud@res@glue
%    \end{macrocode}
% \end{macro}^^A \tud@res@glue
% \begin{macro}{\tud@if@lengthregister}
% \changes{v2.06o}{2022/07/28}{neu}^^A
% Prüft, ob der übergebene Befehl ein \cs{skip}"~ oder \cs{dimen}-Register ist.
%    \begin{macrocode}
\newcommand*\tud@if@lengthregister[1]{%
  \begingroup%
    \@tud@res@swafalse%
    \ifdeflength{#1}{\@tud@res@swatrue}{}%
    \ifdefdimen{#1}{\@tud@res@swatrue}{}%
    \if@tud@res@swa%
      \aftergroup\@firstoftwo%
    \else%
      \aftergroup\@secondoftwo%
    \fi%
  \endgroup%
}
%    \end{macrocode}
% \end{macro}^^A \tud@if@lengthregister
% \begin{macro}{\tud@length@setabsolute}
% \changes{v2.06o}{2022/07/28}{neu}^^A
% Um Schlüssel für Längen definieren zu können, die zwingend positiv sind, kann 
% dieses Makro genutzt werden. Übergeben werden muss entweder eine Länge oder 
% ein Makro, welches einen Längenausdruck enthält.
%    \begin{macrocode}
\newcommand*\tud@length@setabsolute[1]{%
  \tud@if@lengthregister{#1}{%
    \ifdim#1<\z@%
      \setlength#1{-\glueexpr#1\relax}%
    \fi%
  }{%
    \protected@edef#1{%
      \noexpand\ifdim\noexpand\glueexpr\expandonce#1\relax<\z@-\noexpand\fi%
      \noexpand\glueexpr\expandonce#1\relax%
    }%
  }%
}
%    \end{macrocode}
% \end{macro}^^A \tud@length@setabsolute
%
% \subsubsection{Temporäre Makros zur internen Verwendung durch \TUDScript}
%
% Hier werden Makros definiert, die allein für die interne temporäre Nutzung 
% gedacht sind.
% \ToDo{sämtliche \cs{@temp...}-Makros auf \cs{tud@res@...} ändern}[v2.07]
% \ToDo{\cs{tud@reserved} in \cs{tud@res@...}, Achtung bei Dopplungen!}[v2.07]
% \ToDo{Schlüssel sollten weiterhin \cs{@temp...}-Makros verwenden}[v2.07]
% \ToDo{Makros mit \val{@num} in count ändern}[v2.07]
% \begin{macro}{\tud@reserved}
% \changes{v2.05}{2015/10/27}{neu}^^A
% \begin{macro}{\tud@res@a}
% \changes{v2.06}{2018/07/12}{neu}^^A
% \begin{macro}{\tud@res@b}
% \changes{v2.06}{2018/07/12}{neu}^^A
% \begin{macro}{\tud@res@c}
% \changes{v2.06}{2018/07/12}{neu}^^A
% \begin{macro}{\tud@res@d}
% \changes{v2.06}{2018/07/12}{neu}^^A
% \begin{macro}{\if@tud@res@swa}
% \changes{v2.06}{2018/07/12}{neu}^^A
% \begin{macro}{\tud@res@cnt}
% \changes{v2.06}{2019/06/13}{neu}^^A
% Makros zur temporären Verwendung.
%    \begin{macrocode}
\newcommand*\tud@reserved{}
\newcommand*\tud@res@a{}
\newcommand*\tud@res@b{}
\newcommand*\tud@res@c{}
\newcommand*\tud@res@d{}
\tud@newif\if@tud@res@swa
\tud@newcount\tud@res@cnt
%    \end{macrocode}
% \end{macro}^^A \tud@res@cnt
% \end{macro}^^A \if@tud@res@swa
% \end{macro}^^A \tud@res@d
% \end{macro}^^A \tud@res@c
% \end{macro}^^A \tud@res@b
% \end{macro}^^A \tud@res@a
% \end{macro}^^A \tud@reserved
% \begin{macro}{\tud@toks@}
% \changes{v2.05}{2015/11/01}{neu}^^A
% \begin{macro}{\addto@hook@expandafter}
% \changes{v2.05}{2015/11/01}{neu}^^A
% Es wird ein token-Regsiter reserviert, welches im weiteren Verlauf an allen
% möglichen Punkten verwendet wird. Mit \cs{addto@hook@expandafter} wird~-- in 
% Ergänzung zu \cs{addto@hook} aus dem \LaTeX"~Kernel~-- ein Makro zum Anfügen
% des expandierten Arguments an ein token-Register bereitgestellt.
%    \begin{macrocode}
\tud@newtoks\tud@toks@
\newcommand*\addto@hook@expandafter[2]{%
  \expandafter\addto@hook\expandafter#1\expandafter{#2}%
}
%    \end{macrocode}
% \end{macro}^^A \addto@hook@expandafter
% \end{macro}^^A \tud@toks@
%
% \subsubsection{Verzweigung für Präambel und Dokument}
%
% \begin{macro}{\tud@if@preamble}
% \changes{v2.05o}{2022/07/25}{als Ersatz für \cs{if@atdocument}}^^A
% Mit \KOMAScript~v3.37 wurde das Aktivieren des Schalters \cs{if@atdocument} 
% aufgrund des stark veränderten und damit leider nur bedingt deterministischen 
% \hrfn{https://sourceforge.net/p/koma-script/tickets/23/}{Hook-Managements} 
% des Kernels auf |begindocument/before| verschoben. Dieser Befehl wird als
% Gegenstück definiert und führt in Abhängigkeit von |begindocument/after| 
% Quelltext verzweigt aus.
%    \begin{macrocode}
\newcommand*\tud@if@preamble{}
\let\tud@if@preamble\@firstoftwo
\AfterEndPreamble{\let\tud@if@preamble\@secondoftwo}
%    \end{macrocode}
% \end{macro}^^A \tud@if@preamble
%
% \subsubsection{Strings}
% \minisec{Expandierte Tests}
%
% \begin{macro}{\tud@if@strequal}
% \changes{v2.06o}{2022/07/28}{neu}^^A
% \begin{macro}{\tud@if@strstart}
% \changes{v2.06o}{2022/07/28}{neu}^^A
% \begin{macro}{\tud@if@strempty}
% \changes{v2.06o}{2022/07/28}{neu}^^A
% \begin{macro}{\tud@if@strblank}
% \changes{v2.06o}{2022/07/28}{neu}^^A
% Hiermit wird geprüft, ob ein String gleich, leer oder blank (Leerzeichen)
% ist, wobei die gegebene Argumente expandiert werden. In ihrer Syntax sind 
% sie identisch zu den aus aus \pkg{etoolbox} stammenden und unterlagerten
% Befehlen \cs{ifstrequal}, \cs{ifstrempty} und \cs{ifblank}. Der Befehl 
% \cs{tud@if@strstart} nutzt \cs{Ifstrstart} von \KOMAScript.
%    \begin{macrocode}
\newcommand*\tud@if@strequal[2]{%
  \begingroup%
    \protected@edef\tud@res@a{%
      \endgroup%
      \noexpand\ifstrequal{#1}{#2}%
    }%
  \tud@res@a%
}
\newcommand*\tud@if@strstart[2]{%
  \begingroup%
    \protected@edef\tud@res@a{%
      \endgroup%
      \noexpand\Ifstrstart{\noexpand\detokenize{#1}}{\noexpand\detokenize{#2}}%
    }%
  \tud@res@a%
}
\newcommand*\tud@if@strempty{\tud@if@strequal{}}
\newcommand*\tud@if@strblank[1]{%
  \begingroup%
    \protected@edef\tud@res@a{%
      \endgroup%
      \noexpand\ifblank{#1}%
    }%
  \tud@res@a%
}
%    \end{macrocode}
% \end{macro}^^A \tud@if@strblank
% \end{macro}^^A \tud@if@strempty
% \end{macro}^^A \tud@if@strstart
% \end{macro}^^A \tud@if@strequal
%
% \minisec{Test auf booleschen Ausdruck in Form eines Strings}
%
% \begin{macro}{\tud@if@strbool}
% \changes{v2.03}{2015/01/09}{neu}^^A
% Dieser Befehl dient zum Testen, ob ein gegebener String als boolescher 
% Ausdruck interpretiert werden kann. Ist der String als \enquote{wahr} 
% interpretierbar, wird das zweite Argument ausgeführt. Kann der String als 
% \enquote{falsch} angesehen werden, dementsprechen das dritte. Ist der String 
% kein logischer Wert, kommt das letzte Argument zum Tragen. Die Syntax lautet:
% \newline
% \cs{tud@if@strbool}\marg{Argument}\marg{Wahr}\marg{Falsch}\marg{Andernfalls}
%    \begin{macrocode}
\newcommand*\tud@if@strbool[4]{%
  \TUD@set@ifkey{strbool}{@tempswa}{#1}%
  \ifx\FamilyKeyState\FamilyKeyStateProcessed%
    \if@tempswa#2\else#3\fi%
  \else%
    #4
  \fi%
}
%    \end{macrocode}
% \end{macro}^^A \tud@if@strbool
%
% \minisec{Erzwungene Kleinschreibung von Strings}
%
% \begin{macro}{\tud@strlowercase}
% Dieses Makro expandiert das zweite Argument, setzt es in Minuskeln und
% speichert das Ergebnis in den im ersten Argument angegebenen Befehl. Dies 
% wird zum Beispiel benötigt, um bestimmte Werte bei Schlüssel-Wert-Paaren,
% Schlüsselwörtern in einigen Feldern oder auch Einheiten bei Längenangaben
% sicher erkennen zu können. Die Syntax lautet:
% \newline
% \cs{tud@strlowercase}\marg{Zielmakro}\marg{String} benutzt.
%    \begin{macrocode}
\newcommand*\tud@strlowercase[2]{%
  \protected@edef#1{%
    \lowercase{\def\noexpand#1{#2}}%
  }#1%
}
%    \end{macrocode}
% \end{macro}^^A \tud@strlowercase
%
% \minisec{Ausgabe einer Länge als Strings}
%
% \begin{macro}{\tud@strlength}
% \changes{v2.06o}{2022/07/28}{neu}^^A
% Die direkte Verwendung von \cs{the} auf ein \cs{skip}-Register hat zur Folge, 
% dass die Einheit \val{pt} mit die Charactercodes \val{12} zurückgegeben 
% werden, was bei der Weiterverarbeitung unter Umständen Probleme bereitet. 
% Dieses Makro löst das Problem.
%    \begin{macrocode}
\newcommand*\tud@strlength[2]{%
  \begingroup%
    \def\tud@res@c{\glueexpr#2\relax}%
    \edef\tud@res@a{\strip@pt\dimexpr\tud@res@c\relax pt}%
    \edef\tud@res@b{\strip@pt\dimexpr\gluestretch\tud@res@c\relax}%
    \ifdim\tud@res@b\p@=\z@\relax\else%
      \eappto\tud@res@a{%
        \space\@plus\space\tud@res@b%
        \ifcase\gluestretchorder\tud@res@c pt\or fil\or fill\or filll\fi%
      }%
    \fi%
    \edef\tud@res@b{\strip@pt\dimexpr\glueshrink\tud@res@c\relax}%
    \ifdim\tud@res@b\p@=\z@\relax\else%
      \eappto\tud@res@a{%
        \space\@minus\space\tud@res@b%
        \ifcase\glueshrinkorder\tud@res@c pt\or fil\or fill\or filll\fi%
      }%
    \fi%
    \edef\tud@res@a{%
      \endgroup%
      \unexpanded{\def#1}{\tud@res@a}%
    }%
  \tud@res@a%
}
%    \end{macrocode}
% \end{macro}^^A \tud@strlength
%
% \minisec{Entfernen aller Leerzeichen in Strings}
%
% \begin{macro}{\tud@remove@spaces@within}
% Hiermit können in einem gegebenen String \emph{alle} Leerzeichen enthaltenen 
% entfernt werden. Dies wird verwendet, um für \cs{TUD@set@gluekey} sowie 
% \cs{TUD@set@dimkey} eine Warnung auszugeben, falls das übergebene Argument 
% fehlerhaft formatiert ist, wobei Unterschiede bei Leerzeichen ignoriert 
% werden sollen.
%    \begin{macrocode}
\newcommand*\tud@remove@spaces@within[1]{%
  \begingroup%
    \protected@edef\tud@res@a{\noexpand\zap@space#1\space\noexpand\@empty}%
    \protected@edef\tud@res@a{%
      \endgroup%
      \unexpanded{\def#1}{\tud@res@a}%
    }%
  \tud@res@a%
}
%    \end{macrocode}
% \end{macro}^^A \tud@remove@spaces@within
%
% \subsubsection{Test auf eine verwendbare Sprache}
%
% \begin{macro}{\iflanguageloaded}
% \changes{v2.05}{2015/11/23}{neu}^^A
% Hiermit kann getestet werden, ob das Argument als Sprache nutzbar ist.
%    \begin{macrocode}
\AtEndPreamble{%
  \providecommand*\iflanguageloaded[1]{%
    \PackageWarning{tudscrbase}{%
      `\string\iflanguageloaded' is not defined. Loading\MessageBreak%
      either package `babel' or package `polyglossia'\MessageBreak%
      is recommended%
    }%
    \def\iflanguageloaded##1{\expandafter\@secondoftwo}%
    \iflanguageloaded{#1}%
  }%
}
\AfterPackage*{babel}{%
  \providecommand*\iflanguageloaded[1]{%
    \@expandtwoargs\in@{,#1,}{,\bbl@loaded,}%
    \ifin@%
      \expandafter\@firstoftwo%
    \else%
      \expandafter\@secondoftwo%
    \fi%
  }%
}
%    \end{macrocode}
% \end{macro}^^A \iflanguageloaded
%
% \subsubsection{Expansion geschützter Makros}
%
% Im \LaTeX"~Kernel wird der Befehl \cs{@expandtwoargs} definiert, welcher zwei
% Argumente in ein angegebenes Makro vollständig expandiert. Dabei erfolgt die 
% Expansion der beiden Argumente aufgrund der standardmäßigen Verwendung von 
% \cs{edef} allerdings vollständig und ohne die Beachtung von \cs{protect}.
% \begin{macro}{\protected@expandtwoargs}
% \changes{v2.02}{2014/11/13}{neu}^^A
% Der Befehl \cs{protected@expandtwoargs} kann äquivalent genutzt werden, 
% lässt dabei aber mit \cs{protect} geschützte Makros unberührt.
%    \begin{macrocode}
\providecommand*\protected@expandtwoargs[3]{%
  \protected@edef\reserved@a{\noexpand#1{#2}{#3}}\reserved@a%
}
%    \end{macrocode}
% \end{macro}^^A \protected@expandtwoargs
%
% \subsubsection{Division für rationale Zahlen}
%
% Mit \LaTeX{} kann~-- ohne die Verwendung zusätzlicher Pakete~-- nicht ohne 
% Weiteres eine Division durchgeführt werden, die als Ergenis eine rationale 
% Zahl liefert. Dem wird hier Abhilfe geleistet.
% \begin{macro}{\tud@divide}
% \changes{v2.04}{2015/04/09}{neu}^^A
% Der Befehl erwartet im ersten Argument das Makro, in welches das Ergebnis 
% der Division expandiert werden soll, danach folgen Dividend und Divisor. Die 
% Berechnung erfolgt in einer Gruppe, damit die benötigten Längenregister nach 
% dieser erhalten bleiben.
%    \begin{macrocode}
\newcommand*\tud@divide[3]{%
  \begingroup%
%    \end{macrocode}
% Die Division wird über temporäre Längenregister durchgeführt. Die zu 
% teilenden Zahlen werden normiert, wodurch auch Längen mit unterschiedlichen 
% Einheiten geteilt werden können.
%    \begin{macrocode}
    \@defaultunits\@tempdima #2pt\relax\@nnil%
    \@defaultunits\@tempdimb #3pt\relax\@nnil%
%    \end{macrocode}
% Danach wird mit der größeren der beiden Zahlen der größtmögliche, durch
% \val{2} teilbare Faktor zur Berechnung ermittelt.
%    \begin{macrocode}
    \ifdim\@tempdima>\@tempdimb\relax%
      \@whiledim\@tempdimb>1pt\relax\do{%
        \setlength\@tempdima{\dimexpr\@tempdima/10\relax}%
        \setlength\@tempdimb{\dimexpr\@tempdimb/10\relax}%
      }%
      \setlength\@tempdimc{\@tempdima}%
    \else%
      \@whiledim\@tempdima>1pt\relax\do{%
        \setlength\@tempdima{\dimexpr\@tempdima/10\relax}%
        \setlength\@tempdimb{\dimexpr\@tempdimb/10\relax}%
      }%
      \setlength\@tempdimc{\@tempdimb}%
    \fi%
    \@tempcnta=1\relax%
    \@whiledim%
      \dimexpr\@tempcnta\@tempdimc\relax<\dimexpr\maxdimen/100\relax%
    \do{%
      \multiply\@tempcnta by 10\relax%
    }%
%    \end{macrocode}
% Mit dem im temporären Zählerregister \cs{@tempcnta} gespeicherten Faktor 
% wird der Dividend erweitert und der berechnete Quotient wieder gekürzt.
%    \begin{macrocode}
    \setlength\@tempdimc{\dimexpr(\@tempcnta\@tempdima/\@tempdimb*\p@)\relax}%
    \setlength\@tempdimc{\dimexpr\@tempdimc/\@tempcnta\relax}%
%    \end{macrocode}
% Das Ergebnis wird in das angegebene Makro expandiert.
%    \begin{macrocode}
    \edef\@tempa{\endgroup\def\noexpand#1{\strip@pt\@tempdimc}}%
  \@tempa%
}
%    \end{macrocode}
% \end{macro}^^A \tud@divide
%
% \subsubsection{Test auf vorhandene Dateien von Schriftdefinitionen}
%
% \begin{macro}{\tud@if@fdfileexists}
% \changes{v2.06b}{2019/07/17}{neu}^^A
% Der Befehl wird genutzt, um \file{\dots.fd}~Dateien zu suchen. Dabei muss 
% beachtet werden, dass \cs{IfFileExists} auf unixoiden Betriebssystemen 
% case-sensitiv ist.
%    \begin{macrocode}
\newcommand*\tud@if@fdfileexists[2]{%
  \begingroup%
%    \end{macrocode}
% Der Schalter \cs{if@tud@res@swa} wird \val{false} gesetzt, falls die Schrift 
% gefunden wurde. Der zu prüfenden Schriftname wird dabei in unterschiedlichen 
% Varianten getestet. Zunächst die Standardvariante in Kleinschreibung\dots
%    \begin{macrocode}
    \@tud@res@swatrue%
    \tud@strlowercase\tud@res@a{#1#2.fd}%
    \IfFileExists{\tud@res@a}{\@tud@res@swafalse}{}%
%    \end{macrocode}
% \dots gefolgt von der Variante mit Kleinschreibung der Kodierung und dem 
% Namen der Schrift wie angegeben\dots
%    \begin{macrocode}
    \if@tud@res@swa%
      \tud@strlowercase\tud@res@a{#1}%
      \edef\tud@res@a{\tud@res@a#2.fd}%
      \IfFileExists{\tud@res@a}{\@tud@res@swafalse}{}%
    \fi%
%    \end{macrocode}
% \dots abgeschlossen mit der Variante wie gegeben.
%    \begin{macrocode}
    \if@tud@res@swa%
      \edef\tud@res@a{#1#2.fd}%
      \IfFileExists{\tud@res@a}{\@tud@res@swafalse}{}%
    \fi%
%    \end{macrocode}
% Wurde die Schriftdatei gefunden, ist \cs{if@tud@res@swa}|=|\cs{iffalse}.
%    \begin{macrocode}
    \if@tud@res@swa%
      \aftergroup\@secondoftwo%
    \else%
      \aftergroup\@firstoftwo%
    \fi%
  \endgroup%
}
%    \end{macrocode}
% \end{macro}^^A \tud@if@fdfileexists
%
% \subsubsection{Sicherung und Wiederherstellung originaler Befehle und Längen}
%
% \begin{macro}{\tud@cs@letltx}
% \changes{v2.06}{2019/06/13}{\cs{LetLtxMacro} zum Sichern originärer Makros}^^A
% \begin{macro}{\tud@cs@store}
% \changes{v2.06}{2018/07/15}{mit \cs{DeclareRobustCommand} definierte Befehle
%   werden unterstüzt}^^A
% \begin{macro}{\tud@cs@restore}
% \changes{v2.06}{2018/07/15}{stellt originäre Makros auch wieder her, wenn
%   diese mit \cs{undef} zwischendurch \emph{undefiniert} gesetzt wurden}^^A
% \begin{macro}{\tud@cs@reset}
% \begin{macro}{\tud@cs@update}
% \changes{v2.04}{2015/03/03}{neu}^^A
% \begin{macro}{\tud@cs@use}
% \begin{macro}{\tud@cs@check}
% \changes{v2.03}{2015/01/09}{neu}^^A
% Mit diesen Befehlen wird es möglich, Originalbefehle sichern, nutzen und
% wiederherstellen zu können. Dies wird benötigt, um zwischen den einzelnen
% Layouts über Optionseinstellungen zu wechseln und dabei von einem definierten
% Anfangszustand auszugehen.
%
% Der Befehl \cs{tud@cs@letltx} nutzt intern \cs{LetLtxMacro} aus dem Paket 
% \pkg{letltxmacro}, um auch robust definierte Befehle korrekt zu sichern.
% \ToDo{Kernel stellt mittlerweiele \cs{NewCommandCopy} bereit}[v2.07]
%    \begin{macrocode}
\newcommand*\tud@cs@letltx[2]{%
  \expandafter\expandafter\expandafter\LetLtxMacro%
  \expandafter\csname #1\expandafter\endcsname\csname #2\endcsname%
}
%    \end{macrocode}
% Mit dem Aufruf \cs{tud@cs@store}\marg{Befehlsname} wird der im Argument 
% angegebene Befehl in einem neuem Makro |\@@tud@|\meta{Befehlsname}
% gespeichert. Dieser kann danach beliebig angepasst werden. Soll der Befehl zu
% einem späteren Zeitpunkt auf den Orginalzustand zurücksetzen, kann hierfür
% jederzeit der Befehl \cs{tud@cs@reset}\marg{Befehlsname} verwendet werden.
% Durch das Makro \cs{tud@cs@restore}\marg{Befehlsname} wird das mit
% \cs{tud@cs@store} erstellte Hilfsmakro zusätzlich noch gelöscht. Der
% ursprüngliche Befehl kann als solcher mit \cs{tud@cs@use}\marg{Befehlsname}
% weiterhin genutzt werden. Ein zuvor bereits gesicherter Befehl kann mit 
% \cs{tud@cs@update}\marg{Befehlsname} auf die momentane Definition 
% aktualisiert werden.
%    \begin{macrocode}
\newrobustcmd*\tud@cs@store[1]{%
  \tud@cs@check{#1}{%
    \ifcsdef{@@tud@#1}{}{%
      \tud@cs@letltx{@@tud@#1}{#1}%
    }%
  }%
}
\newrobustcmd*\tud@cs@restore[1]{%
%    \end{macrocode}
% Sollte ein zuvor gesichertes Makro mit \cs{undef} oder \cs{csundef} 
% zwischenzeitlich \emph{undefiniert} gesetzt worden sein, wird das originäre 
% Makro dennoch wiederhergestellt. Hierfür wird es zu \cs{relax} gesetzt, damit
% die Überprüfung mit \cs{tud@cs@check} keinen Fehler erzeugt.
%    \begin{macrocode}
  \ifcsdef{#1}{}{%
    \ifcsdef{@@tud@#1}{%
      \cslet{#1}{\relax}%
    }{}%
  }%
%    \end{macrocode}
% Die eigentliche Wiederherstellung.
%    \begin{macrocode}
  \tud@cs@check{#1}{%
    \ifcsdef{@@tud@#1}{%
      \tud@cs@letltx{#1}{@@tud@#1}%
      \csundef{@@tud@#1}%
    }{}%
  }%
}
\newrobustcmd*\tud@cs@reset[1]{%
  \tud@cs@check{#1}{%
    \ifcsdef{@@tud@#1}{%
      \tud@cs@letltx{#1}{@@tud@#1}%
    }{}%
  }%
}
\newrobustcmd*\tud@cs@update[1]{%
  \tud@cs@check{#1}{%
    \ifcsdef{@@tud@#1}{%
      \tud@cs@letltx{@@tud@#1}{#1}%
    }{}%
  }%
}
\newrobustcmd*\tud@cs@use[1]{%
  \tud@cs@check{#1}{%
    \ifcsdef{@@tud@#1}{%
      \csuse{@@tud@#1}%
    }{%
      \csuse{#1}%
    }%
  }%
}
%    \end{macrocode}
% Dieses Makro dient zum Überprüfen, ob der zu sichernde beziehungsweise 
% wiederherzustellende Befehl überhaupt definiert ist. Sollte das nicht der 
% Fall sein, wird ein Fehler ausgegeben.
%    \begin{macrocode}
\newrobustcmd*\tud@cs@check[1]{%
  \begingroup%
    \ifcsdef{#1}{\@tud@res@swatrue}{\@tud@res@swafalse}%
    \if@tud@res@swa%
      \ifcscounter{#1}{\@tud@res@swafalse}{}%
      \ifcslength{#1}{\@tud@res@swafalse}{}%
      \ifcsdimen{#1}{\@tud@res@swafalse}{}%
    \fi%
    \if@tud@res@swa%
      \aftergroup\@firstofone%
    \else%
      \PackageError{tudscrbase}{`\@backslashchar#1' is not a defined macro}{%
        The macro `\@backslashchar#1' was never defined. \MessageBreak%
        Please contact the TUD-Script maintainer\MessageBreak%
        via \TUDScriptContact. A bugfix is urgently required.%
      }%
      \aftergroup\@gobble%
    \fi%
  \endgroup%
}
%    \end{macrocode}
% \end{macro}^^A \tud@cs@check
% \end{macro}^^A \tud@cs@use
% \end{macro}^^A \tud@cs@update
% \end{macro}^^A \tud@cs@reset
% \end{macro}^^A \tud@cs@restore
% \end{macro}^^A \tud@cs@store
% \end{macro}^^A \tud@cs@letltx
% \begin{macro}{\tud@cslength@store}
% \changes{v2.04}{2015/03/02}{neu}^^A
% \changes{v2.05}{2016/07/13}{Verwendung von \cs{tud@cslength@check}}^^A
% \begin{macro}{\tud@cslength@restore}
% \changes{v2.04}{2015/03/02}{neu}^^A
% \changes{v2.05}{2016/07/13}{Verwendung von \cs{tud@cslength@check}}^^A
% \begin{macro}{\tud@cslength@reset}
% \changes{v2.05}{2016/07/13}{neu}^^A
% \begin{macro}{\tud@cslength@check}
% \changes{v2.05}{2016/07/13}{neu}^^A
% Hiermit können~-- äquivalent zum Sichern und Wiederherstellen von Befehlen~-- 
% Längenregister abgespeichert werden.
%    \begin{macrocode}
\newcommand*\tud@cslength@store[1]{%
  \tud@cslength@check{#1}{%
    \ifcsundef{@@tud@length@#1}{%
      \csedef{@@tud@length@#1}{\expandafter\the\csname #1\endcsname}%
    }{}%
  }%
}
\newcommand*\tud@cslength@restore[1]{%
  \tud@cslength@check{#1}{%
    \ifcsundef{@@tud@length@#1}{}{%
      \expandafter\setlength\csname #1\endcsname{%
        \csname @@tud@length@#1\endcsname%
      }%
      \csundef{@@tud@length@#1}%
    }%
  }%
}
\newcommand*\tud@cslength@reset[1]{%
  \tud@cslength@check{#1}{%
    \ifcsundef{@@tud@length@#1}{}{%
      \expandafter\setlength\csname #1\endcsname{%
        \csname @@tud@length@#1\endcsname%
      }%
    }%
  }%
}
\newcommand*\tud@cslength@check[1]{%
  \expandafter\tud@if@lengthregister\expandafter{\csname #1\endcsname}{%
    \expandafter\@firstofone%
  }{%
    \PackageError{tudscrbase}{`\@backslashchar#1' is not a defined length}{%
      The length `\@backslashchar#1' was never defined. \MessageBreak%
      Please contact the TUD-Script maintainer\MessageBreak%
      via \TUDScriptContact. A bugfix is urgently required.%
    }%
    \expandafter\@gobble%
  }%
}
%    \end{macrocode}
% \end{macro}^^A \tud@cslength@check
% \end{macro}^^A \tud@cslength@reset
% \end{macro}^^A \tud@cslength@restore
% \end{macro}^^A \tud@cslength@store
% \begin{macro}{\tud@patch@wrn}
% \TUDScript verwendet die Möglichkeiten von \pkg{etoolbox} und \pkg{xpatch}, 
% um mit den Makros  (\cs{[x]apptocmd}, \cs{[x]pretocmd}, \cs{[x]patchcmd}) 
% bereits definierte Befehle anzupassen. Falls dies nicht gelingt, wird eine 
% Warnung ausgegeben, die hier definiert wird.
% \ToDo{generelle Schnittstelle schaffen und failure hier behandeln}[v2.07]
%    \begin{macrocode}
\newcommand*\tud@patch@wrn[1]{%
  \PackageWarning{tudscrbase}{%
    It wasn't possible to patch `\@backslashchar#1'\MessageBreak%
    Please contact the TUD-Script maintainer\MessageBreak%
    via \TUDScriptContact. Without a bugfix an\MessageBreak%
    erroneous output may occur%
  }%
}
%    \end{macrocode}
% \end{macro}^^A \tud@patch@wrn
%
% \subsection{Schlüsseldefinitionen für \TUDScript}
%
% In Anlehnung an \KOMAScript{} werden hier Befehle zur Definition und
% Ausführung unterschiedlicher Klassenoptionen mithilfe der Funktionen aus
% dem \pkg{scrbase}-Paket erstellt. 
%
% \begin{macro}{\TUDProcessOptions}
% \begin{macro}{\TUDExecuteOptions}
% \begin{macro}{\TUDoptions}
% \begin{macro}{\TUDoption}
% Zuerst ein paar Makros zur einfacheren Verwendung.
%    \begin{macrocode}
\DefineFamily{TUD}
\newcommand*\TUDProcessOptions[1][.\@currname.\@currext]{%
  \FamilyProcessOptions[{#1}]{TUD}%
}
\newcommand*\TUDExecuteOptions[1][.\@currname.\@currext]{%
  \FamilyExecuteOptions[{#1}]{TUD}%
}
\newcommand*\TUDoptions{\FamilyOptions{TUD}}
\newcommand*\TUDoption{\FamilyOption{TUD}}
%    \end{macrocode}
% \end{macro}^^A \TUDoption
% \end{macro}^^A \TUDoptions
% \end{macro}^^A \TUDExecuteOptions
% \end{macro}^^A \TUDProcessOptions
%
% \subsubsection{Optionsdefinitionen}
%
% \begin{macro}{\TUD@key}
% \begin{macro}{\TUD@key@define}
% \changes{v2.06}{2018/07/19}{neu}^^A
% \begin{macro}{\TUD@key@@define}
% \changes{v2.06}{2018/07/19}{neu}^^A
% \begin{macro}{\TUD@key@preset}
% \changes{v2.06}{2018/07/19}{neu}^^A
% Dies ist der zentrale Befehl zur Definition von Optionen, welcher die von
% \KOMAScript{} Schnittstelle \cs{DefineFamilyKey} nutzt.
%
% Da sich die Klassenoptionen teilweise selbst gegenseitig beeinflussen oder
% aber in bestimmten Fällen eine Option in Abhängigkeit von einer anderen
% unterschiedliche Standardwerte annehmen soll, wird dafür eine Möglichkeit
% geschaffen. Hierfür wird für jede Option ein korrelierende Schalter 
% |\if@tud@key@|\meta{Schlüssel}|@set| definiert. Dieser wird auf \val{true} 
% gesetzt, sobald der Schlüssel explizit gesetzt wurde, womit ein Standardwert 
% einer Klassenoption überschrieben werden kann. Das Setzen der Standardwerte 
% erfolgt intern mit dem Befehl \cs{TUD@key@preset}.
%    \begin{macrocode}
\newcommand*\TUD@key[2][.\@currname.\@currext]{%
%    \end{macrocode}
% Basierend auf dem Namen des Schalters wird die notwendige, boolesche Variable
% erzeugt (|\if@tud@key@|\meta{Schlüssel}|@set|), welche im Falle des direkten
% Aufrufs des Schlüssels, ein Überschreiben mit einem Standardwert verhindert.
%    \begin{macrocode}
  \providebool{@tud@key@#2@set}%
  \DefineFamilyMember[{#1}]{TUD}%
  \kernel@ifnextchar[%]
    {\TUD@key@define{#1}{#2}}%
    {\TUD@key@@define{#1}{#2}}%
}
\newcommand*\TUD@key@define{}
\def\TUD@key@define#1#2[#3]#4{%
  \DefineFamilyKey[{#1}]{TUD}{#2}[{#3}]{%
    #4%
    \ifx\FamilyKeyState\FamilyKeyStateProcessed%
      \booltrue{@tud@key@#2@set}%
    \fi%
  }%
}
\newcommand*\TUD@key@@define{}
\def\TUD@key@@define#1#2#3{%
  \DefineFamilyKey[{#1}]{TUD}{#2}{%
    #3%
    \ifx\FamilyKeyState\FamilyKeyStateProcessed%
      \booltrue{@tud@key@#2@set}%
    \fi%
  }%
}
%    \end{macrocode}
% Es kann intern über |\if@tud@key@|\meta{Schlüssel}|@set| geprüft werden, ob
% einem Schlüssel ein explizites Wert zugewiesen wurde. Sollte dies nicht der
% Fall sein, kann dieser hiermit intern beliebig angepasst werden. Da es durch 
% das Setzen der Option mit \cs{TUDoption} zu einer Sperrung kommt, muss diese
% folgend wieder rückgängig gemacht werden.
%    \begin{macrocode}
\newcommand*\TUD@key@preset[2]{%
  \ifbool{@tud@key@#1@set}{}{%
    \TUDoption{#1}{#2}%
    \boolfalse{@tud@key@#1@set}%
  }%
}
%    \end{macrocode}
% \end{macro}^^A \TUD@key@preset
% \end{macro}^^A \TUD@key@@define
% \end{macro}^^A \TUD@key@define
% \end{macro}^^A \TUD@key
%
% Die folgenden Befehle dienen zum Verarbeiten der Optionen, wobei prinzipiell 
% auch eine freie Definition mit anschließender Abarbeitung ohne diese möglich 
% ist.
%
% \begin{macro}{\TUD@set@ifkey}
% \changes{v2.06}{2018/08/01}{forcierte Kleinschreibung Schlüsselwerte}^^A
% Hiermit wird der Option ein einfacher Schalterwert zugewiesen.
%    \begin{macrocode}
\newcommand*\TUD@set@ifkey[3]{%
  \begingroup%
    \tud@strlowercase\tud@res@a{#3}%
    \edef\tud@res@a{%
      \endgroup%
      \unexpanded{\FamilySetBool{TUD}{#1}{#2}}{\tud@res@a}%
    }%
  \tud@res@a%
}
%    \end{macrocode}
% \end{macro}^^A \TUD@set@ifkey
% \begin{macro}{\TUD@set@numkey}
% \changes{v2.02}{2014/11/05}{neu}^^A
% \changes{v2.06}{2018/08/01}{forcierte Kleinschreibung Schlüsselwerte}^^A
% \begin{macro}{\TUD@bool@numkey}
% \changes{v2.03}{2015/01/09}{neu}^^A
% Hiermit werden für eine Option mehrere mögliche Werte definiert. 
%    \begin{macrocode}
\newcommand*\TUD@set@numkey[4]{%
  \begingroup%
    \tud@strlowercase\tud@res@a{#4}%
    \edef\tud@res@a{%
      \endgroup%
      \unexpanded{\FamilySetNumerical{TUD}{#1}{#2}{#3}}{\tud@res@a}%
    }%
  \tud@res@a%
}
%    \end{macrocode}
% Um Dopplungen im Code zu vermeiden, werden für die numerische Schlüssel die 
% booleschen Standardwertzuweisungen in einem Makro gespeichert.
%    \begin{macrocode}
\newcommand*\TUD@bool@numkey{%
  {false}{0},{off}{0},{no}{0},{true}{1},{on}{1},{yes}{1}%
}
%    \end{macrocode}
% \end{macro}^^A \TUD@bool@numkey
% \end{macro}^^A \TUD@set@numkey
% \begin{macro}{\TUD@set@gluekey}
% \changes{v2.06o}{2022/08/01}{neu}^^A
% \begin{macro}{\tud@normalize@gluekey}
% \changes{v2.06o}{2022/08/01}{neu}^^A
% \begin{macro}{\tud@normalize@@gluekey}
% \changes{v2.06o}{2022/08/01}{neu}^^A
% \begin{macro}{\tud@validate@gluekey}
% \changes{v2.06o}{2022/08/01}{neu}^^A
% Mit \cs{TUD@set@gluekey} und \cs{TUD@set@dimkey} wird der übergebene Wert
% entweder als Skip (Länge mit Kleister) oder Dimension (Länge ohne Kleister)
% im spezifizierten Makro gespeichert, wobei auf eine gültige Eingabe geprüft 
% wird.
%
% Wurde ein Argument übergeben, dass in einen String expandiert, ist einiger
% Aufwand notwendig, da das zugrunde liegende \cs{FamilySetLength} einen Fehler
% wirft, wenn eine Längenangabe mit falscher Einheit übergeben wird. Das 
% optionale Argument gibt die gewünschte Längeneinheit an, falls diese im 
% Argument nicht spezifiert wurde.
%    \begin{macrocode}
\newcommand*\TUD@set@gluekey[4][pt]{%
  \begingroup%
    \tud@strlowercase\tud@res@a{#4}%
%    \end{macrocode}
% Es wird geprüft, ob das Argument zu einem String expandiert. Ist dies der
% Fall, wird die vermeintliche Längenangabe mit \cs{tud@normalize@gluekey} 
% normalisiert, wobei das Resultat in das Makro im ersten Argument des Befehls
% zurückgeschrieben wird. Sollte das Normalisieren nicht gelingen, wird ein
% leerer Wert zurückgegeben. 
%    \begin{macrocode}
    \edef\tud@res@b{\detokenize\expandafter{\tud@res@a}}%
    \edef\tud@res@c{\detokenize\expandafter{\@backslashchar}}%
    \@expandtwoargs\in@{\tud@res@c}{\tud@res@b}%
    \ifin@\else%
      \tud@normalize@gluekey\tud@res@a{#1}%
    \fi%
%    \end{macrocode}
% Konnte eine Längenangabe interpretiert werden, wird für ein falsch 
% formatiertes Argument mit \cs{tud@validate@gluekey} ggf. eine Warnung
% ausgegeben und anschließend der gültige Wert gesetzt.
%    \begin{macrocode}
    \protected@edef\tud@res@a{%
      \endgroup%
      \ifx\tud@res@a\@empty%
        \noexpand\FamilyKeyStateUnknownValue%
      \else%
        \unexpanded{\tud@validate@gluekey{#2}}{\tud@res@a}{#4}%
        \unexpanded{\FamilySetUseLengthMacro{TUD}{#2}{#3}}{\tud@res@a}%
      \fi%
    }%
  \tud@res@a%
}
%    \end{macrocode}
% Das Makro \cs{tud@normalize@gluekey} erhält im ersten Argument den zu
% interpretierenden String und im zweiten die ggf. zu setzende Einheit. Dieser
% String wird in den Basiswert und möglichen Kleister aufgetrennt, wobei
% hierbei auch eine vertauschte und eigentlich fehlerhafte Angabe von Kleister
% in der Form |... minus ... plus ...| verarbeitet wird.
%    \begin{macrocode}
\newcommand*\tud@normalize@gluekey[2]{%
  \begingroup%
    \edef\tud@res@c{#1}%
    \def\tud@res@a##1plus##2plus##3\@nil{%
      \let\tud@res@a\@empty%
      \tud@res@b##1minusminus\@nil%
      \tud@res@b##2minusminus\@nil%
    }%
%    \end{macrocode}
% Die vier Token \marg{Grundwert}\marg{negativ}\marg{positiv}\marg{negativ} 
% werden in \cs{tud@res@a} geschrieben, wobei der zweite Token mit negativem
% Kleister gesetzt ist, falls dieser \emph{vor} dem positiven angegeben wurde.
%    \begin{macrocode}
    \def\tud@res@b##1minus##2minus##3\@nil{%
      \eappto\tud@res@a{{\trim@spaces{##1}}{\trim@spaces{##2}}}%
    }%
    \expandafter\tud@res@a\tud@res@c plusplus\@nil%
%    \end{macrocode}
% Hier wird dementsprechend \cs{tud@res@a} auf drei Token reduziert und so
% definiert, dass auf den Grundwert erst der positive und danach der negative 
% Kleister folgt.
%    \begin{macrocode}
    \def\tud@res@b##1##2##3##4{%
      \IfArgIsEmpty{##2}{%
        \def\tud@res@a{{##1}{##3}{##4}}%
      }{%
        \def\tud@res@a{{##1}{##3}{##2}}%
      }%
    }%
    \expandafter\tud@res@b\tud@res@a%
%    \end{macrocode}
% Jeder der drei Token wird nun mit \cs{tud@normalize@@gluekey} geprüft, ob 
% es sich tatsächlich um eine Dimensionsangabe oder zumindest einen Zahlenwert 
% handelt. Für letzteren Fall wird die übergebene Einheit angehangen. Kann ein
% Token nicht als Dimensionsangabe interpretiert werden~-- das übergebene Makro 
% wird zu \cs{relax} gesetzt~-- wird der Prozess abgebrochen.
%    \begin{macrocode}
    \edef\tud@res@b{%
      \unexpanded{\@tfor\tud@res@b:=}\tud@res@a%
    }%
    \let\tud@res@c\@empty%
    \@tud@res@swatrue%
    \tud@res@b\do{%
      \tud@normalize@@gluekey\tud@res@a{\tud@res@b}{#2}%
      \ifx\tud@res@a\relax%
        \@tud@res@swafalse%
        \@break@tfor%
      \else%
        \eappto\tud@res@c{{\tud@res@a}}%
      \fi%
    }%
%    \end{macrocode}
% Nach dem Durchlauf enthält \cs{tud@res@c} alle drei zuvor extrahierten Token, 
% die ggf. um eine Einheit ergänzt wurden, falls diese gegeben waren. Der erste 
% Token erhält folgend eine Sonderbehandlung. Wenn dieser leer ist, wird er auf 
% alle Fälle gesetzt, da es sonst zu Problemen bei der Wertzuweisung an ein 
% Längenregister gibt.
%    \begin{macrocode}
    \let\tud@res@a\@empty%
    \if@tud@res@swa%
      \def\tud@res@b##1##2##3{%
        \IfArgIsEmpty{##1}{\def\tud@res@b{0#2}}{\def\tud@res@b{##1}}%
        \Ifdimen{\tud@res@b}{%
          \edef\tud@res@a{%
            \tud@res@b%
            \IfArgIsEmpty{##2}{}{\space\@plus\space##2}%
            \IfArgIsEmpty{##3}{}{\space\@minus\space##3}%
          }%
        }{}%
      }%
      \expandafter\tud@res@b\tud@res@c%
    \fi%
    \edef\tud@res@c{%
      \endgroup%
      \unexpanded{\def#1}{\tud@res@a}%
    }%
  \tud@res@c%
}
%    \end{macrocode}
% Diese Makro behandelt die einzelnen extrahierten Token. Dabei müssen zuerst 
% die Vorzeichen beachtet werden, welches erst in \cs{tud@res@b} gesichert und 
% anschließend von \cs{tud@res@a} entfernt wird.
%    \begin{macrocode}
\newcommand*\tud@normalize@@gluekey[3]{%
  \begingroup%
    \edef\tud@res@a{#2}%
    \@tud@res@swafalse%
    \expandafter\if\expandafter\@car\tud@res@a\relax\@nil+\@tud@res@swatrue\fi%
    \expandafter\if\expandafter\@car\tud@res@a\relax\@nil-\@tud@res@swatrue\fi%
    \if@tud@res@swa%
      \protected@edef\tud@res@b{\expandafter\@car\tud@res@a\relax\@nil}%
      \protected@edef\tud@res@a{\expandafter\@gobble\tud@res@a}%
    \else%
      \let\tud@res@b\@empty%
    \fi%
%    \end{macrocode}
% Danach wird mit \cs{Ifdimen} geprüft, ob die Angabe tatsächlich eine Länge
% ist. Hier kommt zum Tragen, das \cs{Ifdimen} auch wahr ist, wenn lediglich 
% eine gültige Einheit ohne Maßzahl (\cs{Ifdimen}|{pt}|) angegeben wird.
% Für Werte ohne Dimensionsangabe wird gegebenenfalls einfach das optionale
% Argument als intendierte angenommen. Sollte es sich bei dem Argument nicht um
% einen String sondern um eine \TeX"~Primitive oder ein geschütztes Makro
% handeln, wird kein \val{true}-Zweig durchlaufen.
%    \begin{macrocode}
    \@tud@res@swatrue%
    \Ifdimen{\tud@res@a}{}{%
      \Ifdimen{\tud@res@a#3}{%
        \appto\tud@res@a{#3}%
      }{%
        \@tud@res@swafalse%
      }%
    }%
%    \end{macrocode}
% Wertangaben ohne Betrag werden ignoriert.
%    \begin{macrocode}
    \if@tud@res@swa%
      \Ifisdimension{\tud@res@a}{}{%
        \let\tud@res@a\@empty%
        \let\tud@res@b\@empty%
      }%
    \else%
%    \end{macrocode}
% Sollte keine gültige Dimension angegeben worden sein, wird nun geprüft, ob es 
% sich um eine dehnbare Länge handelt. Diese \emph{muss} mit einer Maßzahl 
% genutzt werden. Fehlt diese, wird \val{1} angenommen. Außerdem ist zu 
% beachten, dass es insgesamt drei Abstufungen der dehnbaren Ausdrücke 
% existieren.
%    \begin{macrocode}
      \def\tud@res@c##1fil##2fil##3\@nil{%
        \IfArgIsEmpty{##1}{\def\tud@res@a{1}}{\def\tud@res@a{##1}}%
        \Ifdimen{\tud@res@a pt}{\@tud@res@swatrue}{\@tud@res@swafalse}%
        \if@tud@res@swa%
          \appto\tud@res@a{fil##2}%
          \tud@if@strequal{##2}{}{}{%
            \tud@if@strequal{##2}{l}{}{%
              \tud@if@strequal{##2}{ll}{}{\@tud@res@swafalse}%
            }%
          }%
        \fi%
      }%
      \expandafter\tud@res@c\tud@res@a filfil\@nil%
    \fi%
%    \end{macrocode}
% Das Vorzeichen nicht vergessen!
%    \begin{macrocode}
    \edef\tud@res@c{%
      \endgroup%
      \if@tud@res@swa%
        \unexpanded{\def#1}{\tud@res@b\tud@res@a}%
      \else%
        \unexpanded{\let#1\relax}%
      \fi%
    }%
  \tud@res@c%
}
%    \end{macrocode}
% Mit diesem Makro wird ganz am Ende des Interpretationsprozesses das Ergebnis 
% mit dem angegbenen Argument verglichen und eine Warnung erzeugt, falls die 
% Formatierung des Argumentes es notwendig machte, dieses zu interpretieren.
%    \begin{macrocode}
\newcommand*\tud@validate@gluekey[3]{%
  \begingroup%
%    \end{macrocode}
% Unterschiede bei Leerzeichen sollen keine Warnung erzeugen.
%    \begin{macrocode}
    \protected@edef\tud@res@a{#2}%
    \protected@edef\tud@res@b{#3}%
    \tud@remove@spaces@within\tud@res@a%
    \tud@remove@spaces@within\tud@res@b%
    \ifx\tud@res@a\tud@res@b%
      \aftergroup\@gobble%
    \else%
      \aftergroup\@firstofone%
    \fi%
  \endgroup{%
    \PackageWarning{tudscrbase}{%
      The length `#3'\MessageBreak%
      seems to be wrong formatted. Assuming, you meant\MessageBreak%
      `#1=#2'%
    }%
  }%
}
%    \end{macrocode}
% \end{macro}^^A \tud@validate@gluekey
% \end{macro}^^A \tud@normalize@@gluekey
% \end{macro}^^A \tud@normalize@gluekey
% \end{macro}^^A \TUD@set@gluekey
% \begin{macro}{\TUD@set@dimkey}
% \changes{v2.05}{2016/06/15}{neu}^^A
% \changes{v2.06}{2018/08/01}{forcierte Kleinschreibung Schlüsselwerte}^^A
% Zur Angabe von Dimensionen wird auf \cs{TUD@set@gluekey} zurückgegriffen 
% und anschließend geprüft, ob das Argument für \cs{dimen} genutzt werden kann.
%    \begin{macrocode}
\newcommand*\TUD@set@dimkey[4][pt]{%
  \begingroup%
    \TUD@set@gluekey[{#1}]{#2}{\tud@res@a}{#4}%
    \ifx\FamilyKeyState\FamilyKeyStateProcessed%
%    \end{macrocode}
% Das Ergebnis der Wertzuweisung an \cs{TUD@set@gluekey} wurde im Makro
% \cs{tud@res@a} gespeichert. Handelt es sich beim Argument um ein
% \cs{skip}"~Register oder eine \cs{glueexpr}, kann nicht sichergestellt 
% werden, dass diesem später doch noch Kleister hinzugefügt wird, weshalb diese
% nicht akzeptiert werden.
%    \begin{macrocode}
      \@tud@res@swafalse%
      \Ifisskip{\tud@res@a}{%
        \protected@edef\tud@res@a{\dimexpr\tud@res@a\relax}%
        \def\tud@res@b{a \string\skip\space register}%
        \@tud@res@swatrue%
      }{%
        \Ifisglueexpr{\tud@res@a}{%
          \protected@edef\tud@res@a{\dimexpr\tud@res@a\relax}%
          \def\tud@res@b{a glue expression}%
          \@tud@res@swatrue%
        }{%
%    \end{macrocode}
% Ebenso wird direkt angegebener Kleister entfernt. Nicht über das Konstrukt 
% mit \cs{@tempdima} und \cs{glueexpr} wundern. Ohne das Paket \pkg{calc} ist 
% die Zuweisung von Kleister als String an ein \cs{dimen}-Register nicht ohne 
% weiteres möglich. Die Verwendung \cs{glueexpr} dient quasi als Umschlag.
%    \begin{macrocode}
          \Ifisglue{\tud@res@a}{%
            \Ifisdimension{\tud@res@a}{}{%
              \setlength\@tempdima{\dimexpr\glueexpr\tud@res@a\relax\relax}%
              \tud@strlength\tud@res@a{\@tempdima}%
              \def\tud@res@b{something containing glue}%
              \@tud@res@swatrue%
            }%
          }{}%
        }%
      }%
%    \end{macrocode}
% Sollte einer der zuvor beschriebenen Fälle aufgetreten sein, wird eine 
% Warnung ausgegeben.
%    \begin{macrocode}
      \if@tud@res@swa%
        \PackageWarning{tudscrbase}{%
          Using option `#2' with\MessageBreak%
          \tud@res@b\space(#4)\MessageBreak%
          is not recommended. You should consider to use\MessageBreak%
          an expression for a dimen instead. Setting\MessageBreak%
          `#2=\tud@res@a'%
        }%
      \fi%
      \protected@edef\tud@res@a{%
        \endgroup%
        \unexpanded{\FamilySetUseLengthMacro{TUD}{#2}{#3}}{\tud@res@a}%
      }%
    \else%
      \def\tud@res@a{\endgroup\FamilyKeyStateUnknownValue}%
    \fi%
  \tud@res@a%
}
%    \end{macrocode}
% \end{macro}^^A \TUD@set@dimkey
% \begin{macro}{\TUD@unknown@keyval}
% Dieser Befehl wird lediglich pro forma definiert. An diesen kann eine Liste 
% möglicher Wertzuweisungen übergeben werden, welche durch \KOMAScript{} 
% derzeit jedoch nicht abgearbeitet und ausgegeben wird.
%    \begin{macrocode}
\newcommand*\TUD@unknown@keyval{\FamilyUnknownKeyValue{TUD}}
%    \end{macrocode}
% \end{macro}^^A \TUD@unknown@keyval
%
% \subsubsection{Voreinstellungen für abhängige Optionen}
%
% \begin{macro}{\tud@locked@newnum}
% \begin{macro}{\tud@locked@num@preset}
% \begin{macro}{\tud@locked@num@set}
% Mit \cs{tud@locked@newnum}\marg{Name}\marg{Definition} lässt sich ein Makro 
% definieren, für das mit \cs{tud@locked@num@preset}\marg{Name}\marg{Definition}
% eine Voreinstellung definiert werden kann, solange der Wert nicht mit
% \cs{tud@locked@num@set}\marg{Name}\marg{Definition} explizit überschrieben
% wurde. Damit ist es möglich, Voreinstellungen abhängig von anderen Optionen 
% zu realisieren.
%    \begin{macrocode}
\newcommand*\tud@locked@newnum[2]{%
  \expandafter\newcommand\expandafter*\csname #1\endcsname{#2}%
  \newbool{#1@locked}%
  \tud@num@set{#1}{#2}%
}
\newcommand*\tud@locked@num@preset[2]{%
  \ifbool{#1@locked}{}{%
    \tud@num@set{#1}{#2}%
    \boolfalse{#1@locked}%
  }%
}
\newcommand*\tud@locked@num@set[2]{%
  \tud@num@set{#1}{#2}%
  \booltrue{#1@locked}%
}
\newcommand*\tud@num@set[2]{%
  \ifcsundef{#1}{%
    \PackageError{tudscrbase}{%
      `\@backslashchar#1' was never defined%
    }{%
      You tried using the numerical expression `\@backslashchar#1'\MessageBreak%
      but you didn't define it with `\string\tud@locked@newnum'.%
    }%
  }{%
    \Ifnumber{#2}{%
      \csdef{#1}{#2}%
    }{%
      \PackageError{tudscrbase}{%
        `#2' is not a valid numerical expression%
      }{%
        You set the numerical expression `\@backslashchar#1'\MessageBreak%
        to value `#2', which isn't numerical.%
      }%
    }%
  }%
}
%    \end{macrocode}
% \end{macro}^^A \tud@locked@num@set
% \end{macro}^^A \tud@locked@num@preset
% \end{macro}^^A \tud@locked@newnum
% \begin{macro}{\tud@locked@newbool}
% \begin{macro}{\tud@locked@bool@preset}
% \begin{macro}{\tud@locked@bool@set}
% \begin{macro}{\tud@bool@set}
% \changes{v2.05}{2015/07/03}{neu}^^A
% Diese Makros dienen in Anlehnung an die vorherigen zum Definieren und Setzen
% von sperrbaren booleschen Schaltern. Dabei wird \cs{tud@bool@set} definiert, 
% um nicht nur \val{true} und \val{false} sondern auch alle anderen bekannten 
% booleschen Zuweisungen (\val{yes} und \val{on} sowie \val{no} und \val{off})
% mit diesen Befehlen verwenden zu können.
%    \begin{macrocode}
\newcommand*\tud@locked@newbool[2][false]{%
  \newbool{#2}%
  \newbool{#2@locked}%
  \tud@bool@set{#2}{#1}%
}
\newcommand*\tud@locked@bool@preset[2]{%
  \ifbool{#1@locked}{}{%
    \tud@bool@set{#1}{#2}%
    \boolfalse{#1@locked}%
  }%
}
\newcommand*\tud@locked@bool@set[2]{%
  \tud@bool@set{#1}{#2}%
  \booltrue{#1@locked}%
}
\newcommand*\tud@bool@set[2]{%
  \tud@if@strbool{#2}{\booltrue{#1}}{\boolfalse{#1}}{%
    \PackageError{tudscrbase}{%
      `#2' is not a valid boolean expression%
    }{%
      You tried to set the boolean switch `\@backslashchar if#1'\MessageBreak%
      to value `#2' but only `true' `on' and `yes' as well as \MessageBreak%
      `false' `no' and `off' are valid values.%
    }%
  }%
}
%    \end{macrocode}
% \end{macro}^^A \tud@bool@set
% \end{macro}^^A \tud@locked@bool@set
% \end{macro}^^A \tud@locked@bool@preset
% \end{macro}^^A \tud@locked@newbool
%
% \subsubsection{Parameterdefinitionen}
%
% \begin{macro}{\TUD@parameter@family}
% \begin{macro}{\TUD@parameter@@family}
% \begin{macro}{\TUD@parameter@checkfamily}
% Mit \cs{TUD@parameter@family}\marg{Familienname}\marg{Definitionen} können
% für die optionalen Argumente von Befehlen Schlüssel-Wert-Parameter definiert
% werden. Das erste Argument definiert den Familiennamen für den jeweiligen 
% Befehl, welcher eindeutig gewählt werden sollte. Dieser wird im Hilfsmakro
% \cs{TUD@parameter@@family} gesichert. Dies soll im Zusammenspiel mit dem 
% Makro \cs{TUD@parameter@checkfamily} dafür sorgen, dass die im Folgenden
% bereitgestellten Befehle \cs{TUD@parameter@def}, \cs{TUD@parameter@let} und
% \cs{TUD@parameter@handler@macro}~-- welche die eigentliche Definition der
% Parameter für den Benutzer bewerkstelligen~-- ohne die Angabe der Familie 
% nur innerhalb des zweiten Argumentes von \cs{TUD@parameter@family} verwendet
% werden können.
% \ToDo{
%   Eine Katastrophe, dringend überarbeiten; generelle Lösung mit \cs{toks@}? 
%   KOMA-Option \val{@else@} verwenden?
% }[v2.07]
%    \begin{macrocode}
\newcommand*\TUD@parameter@@family{}
\newcommand*\TUD@parameter@family[2]{%
  \xdef\TUD@parameter@@family{#1}%
  #2%
  \gdef\TUD@parameter@@family{}%
}
%    \end{macrocode}
% Dieser Befehl prüft, ob eine Familie für den Paramter definiert wurde.
%    \begin{macrocode}
\newcommand*\TUD@parameter@checkfamily[2]{%
  \tud@if@strblank{#1}{%
    \PackageError{tudscrbase}{%
      No family for \@backslashchar#2 defined%
    }{%
      You have to use \@backslashchar#2\space within the\MessageBreak%
      second argument of \string\TUD@parameter@family. The first\MessageBreak%
      argument of \string\TUD@parameter@family\space has to be\MessageBreak%
      a unique family name. Alternatively, you can specify\MessageBreak%
      the family name within the optional argument of\MessageBreak%
      \@backslashchar#2.%
    }%
  }{}%
}
%    \end{macrocode}
% \end{macro}^^A \TUD@parameter@checkfamily
% \end{macro}^^A \TUD@parameter@@family
% \end{macro}^^A \TUD@parameter@family
% \begin{macro}{\TUD@parameter@def}
% \begin{macro}{\TUD@parameter@let}
% \changes{v2.02}{2014/07/25}{Beachtung der gegebenen Standardwerte}^^A
% \cs{TUD@parameter@def}\marg{Name}\oarg{Säumniswert}\marg{Verarbeitung} nutzt
% \cs{define@key} aus dem \pkg{keyval}-Paket, um einen Schlüssel und dessen
% Verarbeitung zu definieren, wobei auf den zugewiesenen Wert innerhalb des
% zweiten obligatorischen Argumentes mit |#1| zugegriffen werden kann.
%    \begin{macrocode}
\newcommand*\TUD@parameter@def[1][\TUD@parameter@@family]{%
  \TUD@parameter@checkfamily{#1}{TUD@parameter@def}%
  \expandafter\define@key\expandafter{#1}%
}
%    \end{macrocode}
% Mit \cs{TUD@parameter@let}\marg{Name}\marg{Name} kann äquivalent zur
% \mbox{\TeX-Primitive \cs{let}} die Definition der Verarbeitung eines
% Parameters auf einen weiteren übertragen werden.
%    \begin{macrocode}
\newcommand*\TUD@parameter@let[3][\TUD@parameter@@family]{%
  \TUD@parameter@checkfamily{#1}{TUD@parameter@let}%
  \@expandtwoargs{\csletcs}{KV@#1@#2}{KV@#1@#3}%
  \@expandtwoargs{\csletcs}{KV@#1@#2@default}{KV@#1@#3@default}%
}
%    \end{macrocode}
% \end{macro}^^A \TUD@parameter@let
% \end{macro}^^A \TUD@parameter@def
% \begin{macro}{\TUD@parameter@set}
% \changes{v2.05}{2016/05/26}{robustere Verarbeitung von Default-Argumenten}^^A
% \begin{macro}{\TUD@parameter@nokey}
% \changes{v2.05}{2016/05/26}{neu}^^A
% Mit \cs{TUD@parameter@set}\marg{Familienname}\marg{Parameterliste} wird die
% Verarbeitung aller gegebenen Parameter veranlasst. Normalerweise wird dieser
% Befehl \emph{nicht} innerhalb des Argumentes von \cs{TUD@parameter@family}
% verwendet. In jedem Fall muss die zu verwendende Familie angegeben werden.
%    \begin{macrocode}
\newcommand*\TUD@parameter@nokey{@nokey@}
\newcommand*\TUD@parameter@set[2]{%
  \IfArgIsEmpty{#2}{}{%
%    \end{macrocode}
% Hierfür wird die angegebene Parameterliste sukzessive abgearbeitet. Elemente, 
% welche in Schlüssel-Wert-Syntax angegeben wurden, bleiben unverändert\dots
%    \begin{macrocode}
    \let\@tempb\@empty%
    \def\@tempa##1{%
      \@expandtwoargs\in@{=}{##1}%
      \ifin@%
        \appto\@tempb{##1,}%
      \else%
%    \end{macrocode}
% \dots ebenso wie Schlüssel ohne Wert, falls diese definiert wurden. Zu 
% beachten ist, dass es mit \cs{TUD@parameter@handler@value} respektive
% \cs{TUD@parameter@handler@default} auch möglich ist, für einen mit einem der 
% beiden Makros gewählten Schlüssel, lediglich den passenden Wert anzugeben.
% Dies wird genutzt, um optionale Argumente direkt für den Hauptparameter eines
% Makros oder einer Umgebung~-- wie beispielsweise für eine Überschrift~--
% nutzen zu können, aber zusätzlich die Möglichkeit zu bieten, auch eine
% Parameterliste zu verwenden. Hierfür werden Umlaute sowie das \enquote*{ß}
% unschädlich gemacht.
%    \begin{macrocode}
        \begingroup%
          \let\IeC\@firstofone%
          \def\"####1{####1e}%
          \def\ss{ss}%
          \def\SS{SS}%
          \protected@edef\tud@reserved{%
            \endgroup%
            \noexpand\protected@edef\noexpand\@tempc{KV@#1@##1}%
          }%
        \tud@reserved%
        \ifcsdef{\@tempc}{%
          \appto\@tempb{##1,}%
        }{%
          \protected@eappto\@tempb{\TUD@parameter@nokey=##1,}%
        }%
      \fi%
    }%
    \forcsvlist\@tempa{#2}%
    \@expandtwoargs\kvsetkeys{#1}{\@tempb}%
  }%
}
% Ursprünglich entwickelte sich dieser Ansatz aus der Situation, dass das Makro 
% \cs{maketitle} in seiner Standarddefinition ein optionales Argument für eine
% Seitenzahl bereithält, bei den \TUDScript-Klassen jedoch auch die Möglichkeit
% besteht, verschiedene zusätzliche Parameter für diesen Befehl zu verwenden. 
% Um allerdings für den Anwender das gewohnte Vorgehen beibehalten zu können,
% wurde diese Sonderbehandlung implementiert. 
%    \end{macrocode}
% \end{macro}^^A \TUD@parameter@nokey
% \end{macro}^^A \TUD@parameter@set
% \begin{macro}{\TUD@parameter@handler@macro}
% \changes{v2.05}{2016/05/26}{robustere Verarbeitung von Default-Argumenten}^^A
% Durch \cs{TUD@parameter@handler@macro} kann definiert werden, wie mit einem
% zuvor nicht mit \cs{TUD@parameter@def} definiertem Parameter beziehungsweise
% gewöhnlichem optionalen Argument umzugehen ist. Dabei wird unterschieden, ob 
% es sich bei dem unbekannten Parameter um ein normales optionales Argument 
% oder um eine Angabe in Schlüssel-Wert-Syntax handelt. Dabei wurden einfache 
% optionale Argumente zuvor durch \cs{TUD@parameter@set} dem Schlüssel 
% \cs{TUD@parameter@nokey} als Wert zugewiesen, um Umlaute etc. ohne Bedenken
% verwenden zu können.
%
% Das erste obligatorische Argument von \cs{TUD@parameter@handler@macro} wird 
% für die Verarbeitung unbekannter Schlüssel-Wert-Paare genutzt, das zweite für 
% einfache optionale Argumente.
% \ToDo{
%   Eine Katastrophe, dringend überarbeiten; generelle Lösung mit \cs{toks@}? 
%   KOMA-Option \val{@else@} verwenden?
% }[v2.07]
%    \begin{macrocode}
\newcommand*\TUD@parameter@handler@macro[3][\TUD@parameter@@family]{%
  \TUD@parameter@checkfamily{#1}{TUD@parameter@handler@macro}%
  \expandafter\kv@set@family@handler\expandafter{#1}{%
    \tud@if@strequal{\kv@key}{\TUD@parameter@nokey}{#3}{#2}%
  }%
}
%    \end{macrocode}
% \end{macro}^^A \TUD@parameter@handler@macro
% \begin{macro}{\TUD@parameter@handler@value}
% \changes{v2.05}{2016/05/26}{neu}^^A
% Mit diesem Makro wird einem optionalen Argument, welches ohne Schlüssel 
% angegeben wurde, ein expliziter Parameter zugewiesen, welcher damit gesetzt 
% wird. Unbekannte Schlüssel-Wert-Argumente werden durch \cs{kv@handled@false} 
% immer als Fehler zurückgemeldet.
%    \begin{macrocode}
\newcommand*\TUD@parameter@handler@value[2][\TUD@parameter@@family]{%
  \TUD@parameter@checkfamily{#1}{TUD@parameter@handler@value}%
  \protected@edef\@tempa{%
    \noexpand\TUD@parameter@set{#1}{#2=\noexpand\kv@value}%
  }%
  \def\@tempb{\TUD@parameter@handler@macro[{#1}]{\kv@handled@false}}%
  \expandafter\@tempb\expandafter{\@tempa}%
}
%    \end{macrocode}
% \end{macro}^^A \TUD@parameter@handler@value
% \begin{macro}{\TUD@parameter@handler@default}
% Hiermit kann sowohl die zu verwendende Sprache als auch die Anzahl der
% gewünschten Spalten für bestimmte Umgebungen ohne die explizite Angabe eines
% Schlüssels festgelegt werden. Momentan betrifft das die beiden Umgebungen
% \env{abstract} und \env{tudpage} sowie Befehle und Umgebungen, welche auf 
% letzterer basieren. Unbekannte Argumente in Schlüssel-Wert-Syntax werden
% nicht unterstützt.
%    \begin{macrocode}
\newcommand*\TUD@parameter@handler@default[2][\TUD@parameter@@family]{%
  \TUD@parameter@checkfamily{#1}{TUD@parameter@handler@default}%
  \tud@if@strblank{#2}{%
    \def\@tempa{\let\tud@reserved\relax}%
  }{%
    \def\@tempa{\def\tud@reserved{#2=\kv@value}}%
  }%
  \appto\@tempa{%
    \tud@if@strequal{\kv@value}{twocolumn}{\def\kv@value{2}}{}%
    \Ifnumber{\kv@value}{\def\tud@reserved{columns=\kv@value}}{}%
    \iflanguageloaded{\kv@value}{\def\tud@reserved{language=\kv@value}}{}%
    \ifx\tud@reserved\relax%
      \tud@if@strblank{\kv@value}{}{%
        \PackageError{tudscrbase}{%
          Unknown default value `\kv@value'%
        }{%
          If `\kv@value' is a language, you haven't loaded it. \MessageBreak%
          Otherwise, there's no handler for the given value. \MessageBreak%
          You should specify a certian key (<key>=\kv@value).%
        }%
      }%
    \fi%
  }%
  \protected@eappto\@tempa{%
    \noexpand\ifx\noexpand\tud@reserved\noexpand\relax\noexpand\else%
      \noexpand\TUD@parameter@set{#1}{\noexpand\tud@reserved}%
    \noexpand\fi%
  }%
  \def\@tempb{\TUD@parameter@handler@macro[{#1}]{\kv@handled@false}}%
  \expandafter\@tempb\expandafter{\@tempa}%
}
%    \end{macrocode}
% \end{macro}^^A \TUD@parameter@handler@default
% \begin{macro}{\TUD@parameter@err}
% Das Makro \cs{TUD@parameter@err}\marg{Parameter}\marg{Werteliste} gibt für
% den Fall einer ungültigen Wertzuweisung an einen bestimmten \meta{Parameter}
% einen Fehler mit einem entsprechenden Hinweis auf gültige Werte innerhalb von
% \meta{Werteliste} aus.
%    \begin{macrocode}
\newcommand*\TUD@parameter@err[2]{%
  \PackageError{tudscrbase}{Unsupported value for parameter `#1'}{%
    `#1' can only be used with values:\MessageBreak#2%
    \MessageBreak Please choose a valid one.%
  }%
}
%    \end{macrocode}
% \end{macro}^^A \TUD@parameter@err
%
% \subsection{Ausführung von paketspezifischem Quellcode}
%
% Ab und an ist es notwendig, bestimmten Quelltext gezielt in Abhängigkeit vom
% Ladezustand eines Paketes auszuführen.
% \begin{macro}{\TUD@UnwindPackage}
% \changes{v2.05}{2015/10/28}{neu}^^A
% \changes{v2.06o}{2022/08/02}{Sternversion}^^A
% Dieser Befehl dient zur Ausführung von Quelltext, falls ein Paket bis zum 
% Ende der Dokumentpräambel nicht geladen wurde. Im ersten obligatorischen
% Argument wird das Paket angegeben, im zweiten der Quellcode. Die Sternversion 
% führt den Quellcode auch nach dem Laden des Paketes aus.
%    \begin{macrocode}
\NewDocumentCommand\TUD@UnwindPackage{s m m}{%
  \IfBooleanT{#1}{\AfterPackage*{#2}{#3}}%
  \AtEndPreamble{\@ifpackageloaded{#2}{}{#3}}%
}
\@onlypreamble\TUD@UnwindPackage
%    \end{macrocode}
% \end{macro}^^A \TUD@UnwindPackage
% \begin{macro}{\TUD@CheckPackage}
% \changes{v2.06}{2019/06/21}{neu}^^A
% \begin{macro}{\tud@if@packagelater@exists}
% \changes{v2.06}{2019/06/21}{neu}^^A
% Mit \cs{TUD@CheckPackage} wird geprüft, ob ein Paket mindestens in der 
% angegebenen Version existiert. Sollte das Paket in einer früheren Version 
% existieren, wird eine Warnung ausgegeben. Dabei wird das Paket \emph{nicht} 
% geladen. Damit lässt sich sicherstellen, dass beispielsweise Schriftdateien 
% in einer bestimmten Version vorhanden sind, ohne diese durch das Paket selbst 
% zu laden. Ist das Paket gar nicht installiert, wird durch den Aufruf von 
% \cs{RequirePackage} ein Fehler erzeugt respektive MiKTeX zur automatischen 
% Nachinstallation animiert.
% \ToDo{.aux schreiben, wenn existent und so ggf. nur einmalig ausführen}[v2.07]
%    \begin{macrocode}
\newcommand*\TUD@CheckPackage[2]{%
  \tud@if@packagelater@exists{#1}{#2}{}{%
    \PackageWarningNoLine{tudscrbase}{%
      The version `#2' of package `#1'\MessageBreak%
      is urgently required. An erroneous output\MessageBreak%
      may occur. Please update your distribution%
    }%
    \IfFileExists{#1.sty}{}{\RequirePackage{#1}[#2]}%
  }%
}
\@onlypreamble\TUD@CheckPackage
%    \end{macrocode}
% Hiermit wird geprüft, ob ein installiertes Paket in einer bestimmten Version
% vorhanden ist, ohne dieses zu laden. Hierfür wird die Datei zeilenweise 
% gelesen, bis der Eintrag \cs{ProvidesPackage}\marg{Paketname}\oarg{Version} 
% gefunden wird.
% \ToDo{kann \cs{@ifl@t@r} ersetzt werden?}[v2.07]
% \ToDo{Name in \cs{IfPackageExistsAtLeastTF} ändern}[v2.07]
%    \begin{macrocode}
\newcommand*\tud@if@packagelater@exists[2]{%
  \begingroup%
    \let\tud@res@a\@empty%
    \def\tud@res@b[##1]{\def\tud@res@a{##1}}%
    \def\ProvidesPackage##1{%
      \kernel@ifnextchar[%]
        {\tud@res@b}%
        {\tud@res@b[]}%
    }%
    \IfFileExists{#1.sty}{%
      \openin\@inputcheck=#1.sty%
      \@tud@res@swatrue%
      \loop%
        \read\@inputcheck to\tud@res@c%
        \@expandtwoargs\in@{\string\ProvidesPackage}%
          {\expandafter\detokenize\expandafter{\tud@res@c}}%
        \ifin@%
          \@tud@res@swafalse%
          \tud@res@c%
        \fi%
        \ifeof\@inputcheck\@tud@res@swafalse\fi%
        \if@tud@res@swa%
      \repeat%
      \closein\@inputcheck%
    }{}%
    \edef\tud@res@a{\endgroup\noexpand\@ifl@t@r{\tud@res@a}{#2}}%
  \tud@res@a%
}
\@onlypreamble\tud@if@packagelater@exists
%    \end{macrocode}
% \end{macro}^^A \tud@if@packagelater@exists
% \end{macro}^^A \TUD@CheckPackage
% \begin{macro}{\TUD@RecommendPackage}
% \changes{v2.06}{2018/07/12}{neu}^^A
% \begin{macro}{\TUD@Recommend@Package}
% Bestimmte Pakete sind für die Funktionalität von \TUDScript empfohlen, aber 
% nicht zwingend erforderlich. Sind diese nicht vorhanden, wird eine Warnung 
% ausgegeben.
%    \begin{macrocode}
\newcommand*\TUD@RecommendPackage[1]{%
  \kernel@ifnextchar[%]
    {\TUD@Recommend@Package#1}%
    {\TUD@Recommend@Package#1[]}%
}
\@onlypreamble\TUD@RecommendPackage
\newcommand*\TUD@Recommend@Package{}
\def\TUD@Recommend@Package#1[#2]{%
  \IfFileExists{#1.sty}{%
    \RequirePackage{#1}[#2]%
  }{%
    \PackageWarning{tudscrbase}{%
      The usage of package `#1' (#2) is\MessageBreak%
      recommended but it isn't installed%
    }%
  }%
}
\@onlypreamble\TUD@Recommend@Package
%    \end{macrocode}
% \end{macro}^^A \TUD@Recommend@Package
% \end{macro}^^A \TUD@RecommendPackage
% \begin{macro}{\TUD@AfterPackage@set}
% \changes{v2.04}{2015/03/09}{neu}^^A
% \begin{macro}{\TUD@AfterPackage@do}
% \changes{v2.03}{2015/02/15}{neu}^^A
% Mit diesen beiden Befehlen wird die Ausführung von Quellcode erst nach dem 
% Laden des gewünschten Paketes oder~-- falls das Paket geladen wurde~--  
% direkt im Dokument ausgeführt. Im ersten Argument wird das Paket angegeben, 
% im zweiten der Quellcode.
%    \begin{macrocode}
\newcommand*\TUD@AfterPackage@set[1]{%
  \newbool{@tud@#1@loaded}%
  \AfterAtEndOfPackage*{#1}{\booltrue{@tud@#1@loaded}}%
}
\newcommand*\TUD@AfterPackage@do[2]{%
  \ifcsundef{if@tud@#1@loaded}{%
    \PackageError{tudscrbase}{\string\TUD@AfterPackage@set{#1} missing}{%
      You have to set \string\TUD@AfterPackage@set{#1} before\MessageBreak%
      using \string\TUD@AfterPackage@do{#1}{<code>}.%
    }%
  }{%
    \tud@if@preamble{%
      \AfterAtEndOfPackage*{#1}{#2}%
    }{%
      \ifbool{@tud@#1@loaded}{#2}{}%
    }%
  }%
}
%    \end{macrocode}
% \end{macro}^^A \TUD@AfterPackage@do
% \end{macro}^^A \TUD@AfterPackage@set
%
% \iffalse
%</package&base>
% \fi
%
% \subsection{Bedingt verzögerte Ausführung von \KOMAScript-Optionen}
%
% \begin{macro}{\TUD@KOMAoptions}
% \changes{v2.05}{2015/07/17}{neu}^^A
% Dieses Makro wird verwendet, um innerhalb der \TUDScript-Klassen zu 
% unterschieden, wie eine \KOMAScript-Option auszuführen ist. Wurde bereits 
% das Paket \pkg{scrextend} oder eine \KOMAScript-Klasse geladen, erfolgt die 
% Ausführung des Arguments direkt über \cs{KOMAoptions}. Andernfalls wird das 
% angegebene Argument an die zuladende Klasse durchgereicht.
%    \begin{macrocode}
%<*package&base>
\newcommand*\TUD@KOMAoptions[1]{}
\ifundef{\KOMAClassName}{%
  \renewcommand*\TUD@KOMAoptions[1]{%
    \PackageWarning{tudscrbase}{%
      You should load package `scrextend' right after\MessageBreak%
      the documentclass. The following option is gobbled:\MessageBreak%
      \string\KOMAoptions{`#1'}%
    }%
  }%
  \AfterPackage*{scrextend}{\def\TUD@KOMAoptions{\KOMAoptions}}%
}{%
  \def\TUD@KOMAoptions{\KOMAoptions}%
}
%</package&base>
%    \end{macrocode}
% Nach dem Laden einer \TUDScript-Klasse wird der Befehl so angepasst, dass 
% dieser vor dem Laden der dazugehörigen \KOMAScript-Elternklasse die Optionen 
% einfach durchreicht. Nach dem Laden der Klasse steht dann \cs{KOMAoptions} 
% zur Verfügung.
%    \begin{macrocode}
%<*load&class>
%<*!inherit>
\renewcommand*\TUD@KOMAoptions[1]{\PassOptionsToClass{#1}{\TUD@Class@KOMA}}
\AfterClass{\TUD@Class@KOMA}{\let\TUD@KOMAoptions\KOMAoptions}
%</!inherit>
%<*inherit>
\renewcommand*\TUD@KOMAoptions[1]{\PassOptionsToClass{#1}{\TUD@Class@Parent}}
\AfterClass{\TUD@Class@Parent}{\let\TUD@KOMAoptions\KOMAoptions}
%</inherit>
%</load&class>
%    \end{macrocode}
% \end{macro}^^A \TUD@KOMAoptions
%
% \iffalse
%<*class&option>
% \fi
%
% \section{Zusätzliches für die \TUDScript-Klassen}
% \subsection{Erweiterung von \KOMAScript-Schriftelementen}
%
% \begin{macro}{\tud@komafont@set}
% \begin{macro}{\tud@komafont@unset}
% \begin{macro}{\tud@komafont@reset}
% \changes{v2.02}{2014/08/24}{neu}^^A
% Es wird die Möglichkeit geschaffen, bestimmten Schriftelementen weitere
% Eigenschaften mitzugeben. Damit dies optionsabhängig geschehen kann und
% \cs{addtokomafont} nur einmalig verwendete werden muss, wird im Zweifelsfall
% einem Schriftelement ein Hilfsmakro |\tud@komafont@|\meta{Element} 
% zugewiesen, welches intern angepasst werden kann. Mit \cs{tud@komafont@set} 
% werden dem angegebenen Element die gewünschten Schriftattribute zugeteilt.
%    \begin{macrocode}
\newcommand*\tud@komafont@set[2]{%
  \ifcsdef{tud@komafont@#1}{}{\addtokomafont{#1}{\csuse{tud@komafont@#1}}}%
  \csdef{tud@komafont@#1}{#2\nobreak}%
}
%    \end{macrocode}
% Mit \cs{tud@komafont@unset} kann das angegebene Element wieder zurückgesetzt
% werden. Dabei wird das hinzugefügte Makro auf \cs{relax} gesetzt.
%    \begin{macrocode}
\newcommand*\tud@komafont@unset[1]{%
  \ifcsdef{tud@komafont@#1}{}{\addtokomafont{#1}{\csuse{tud@komafont@#1}}}%
  \csdef{tud@komafont@#1}{\relax}%
}
%    \end{macrocode}
% Werden \KOMAScript-Schriftelemente auf ihre Ausgangsdefinition zurückgesetzt, 
% so kann diesen mit \cs{tud@komafont@reset} kann das passende Hilfsmakro
% abermals zugewiesen werden.
%    \begin{macrocode}
\newcommand*\tud@komafont@reset[1]{%
  \ifcsdef{tud@komafont@#1}{\addtokomafont{#1}{\csuse{tud@komafont@#1}}}{}%
}
%    \end{macrocode}
% \end{macro}^^A \tud@komafont@unset
% \end{macro}^^A \tud@komafont@reset
% \end{macro}^^A \tud@komafont@set
%
% \iffalse
%</class&option>
%<*class&body>
% \fi
%
% \subsection{Externe Pakete für die \TUDScript-Klassen}
%
% \changes{v2.01}{2014/04/24}{Versionsanforderungen bei benötigten Paketen}^^A
% \changes{v2.02}{2014/07/08}{Warnung bei Verwendung von \pkg{graphics}}^^A
%
% Für die Verwendung der hier erstellten \KOMAScript-Wrapper-Klassen werden
% einige wenige Pakete eingebunden. Dabei wurde versucht, die Anzahl der
% Pakete möglichst gering zu halten und nur die wirklich notwendigen zu
% verwenden.
%
% \subsubsection{Erweiterte Umgebungsdefinition mit dem Paket \pkg{environ}}
%
% Die \env{abstract}-Umgebung wird im Vergleich zu den \KOMAScript-Klassen
% stark erweitert. Für diese sowie für die Umgebungen \env{declarations} und 
% \env{tudpage} wird das Paket \pkg{environ} für die Umgebungsdefinition
% benötigt.
%    \begin{macrocode}
\RequirePackage{environ}
%    \end{macrocode}
%
% Innerhalb dieser Umgebungen soll es außerdem möglich sein, ein mehrspaltiges 
% Layout~-- auch konträr zu den globalen Dokumenteinstellungen~-- zu verwenden.
% Mit diesen Befehlen lässt sich die Anzahl der Spalten über einen Parameter
% anpassen, falls das Paket \pkg{multicol} geladen wurde.
% \begin{macro}{\tud@x@multicol@num}
% \begin{macro}{\tud@x@multicol@check}
% Im Makro \cs{tud@x@multicol@num} wird die Anzahl der gewünschten Spalten in 
% einer Umgebung für die Verwendung des \pkg{multicol}-Paketes gespeichert.
%    \begin{macrocode}
\newcommand*\tud@x@multicol@num{1}
%    \end{macrocode}
% Der Befehl \cs{tud@x@multicol@check} prüft, ob das Paket \pkg{multicol} 
% geladen wurde. Falls dies nicht der Fall ist, wird eine Warnung ausgegeben 
% und die Änderung des Wertes über einen Parameter der Umgebungen \env{tudpage} 
% respektive \env{abstract} sowie \env{declarations} verhindert.
%    \begin{macrocode}
\newcommand*\tud@x@multicol@check{%
  \ifnum\tud@x@multicol@num>\@ne\relax%
    \ClassWarning{\TUD@Class@Name}{%
      The option `columns=\tud@x@multicol@num' is only\MessageBreak%
      supported, when package `multicol' is loaded%
    }%
    \renewcommand*\tud@x@multicol@num{1}%
  \fi%
}
\AfterPackage{multicol}{\let\tud@x@multicol@check\relax}
%    \end{macrocode}
% \end{macro}^^A \tud@x@multicol@check
% \end{macro}^^A \tud@x@multicol@num
%
% \subsubsection{Pakete für Grafiken und Farben}
%
% Es folgen die Pakete, welche bei Bedarf am Ende der Präambel geladen werden.
%    \begin{macrocode}
\AtEndPreamble{%
%    \end{macrocode}
% Mit \pkg{graphicx} werden die Logos der TU~Dresden sowie von Dresden Concept
% mit dem Befehl \cs{includegraphics} u.\,a. auf der Titelseite eingebunden.
% Sollte lediglich das \pkg{graphics}-Paket geladen worden sein, so wird der
% Nutzer mit einer Warnung informiert, dass zusätzlich das \pkg{graphicx}-Paket 
% geladen wird.
%    \begin{macrocode}
  \@ifpackageloaded{graphicx}{}{%
    \@ifpackageloaded{graphics}{%
      \ClassWarningNoLine{\TUD@Class@Name}{%
        Package `graphics' was superseded by `graphicx',\MessageBreak%
        which now will be loaded automatically%
      }%
    }{}%
    \RequirePackage{graphicx}
  }%
%    \end{macrocode}
% Mit dem Paket \pkg{tudscrcolor} werden die Befehle für die Auswahl der Farben
% des \CDs definiert, welches wiederum \pkg{xcolor} lädt.
%    \begin{macrocode}
  \RequirePackage{tudscrcolor}[%
%!TUD@Version
  ]%
}
%    \end{macrocode}
%
% \iffalse
%</class&body>
% \fi
%
% \PrintBackMatter
%
\endinput
