summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/datatool/datatool.dtx
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /macros/latex/contrib/datatool/datatool.dtx
Initial commit
Diffstat (limited to 'macros/latex/contrib/datatool/datatool.dtx')
-rw-r--r--macros/latex/contrib/datatool/datatool.dtx29468
1 files changed, 29468 insertions, 0 deletions
diff --git a/macros/latex/contrib/datatool/datatool.dtx b/macros/latex/contrib/datatool/datatool.dtx
new file mode 100644
index 0000000000..9115c37a69
--- /dev/null
+++ b/macros/latex/contrib/datatool/datatool.dtx
@@ -0,0 +1,29468 @@
+%\iffalse
+% datatool.dtx generated using makedtx version 1.2 (c) Nicola Talbot
+% Command line args:
+% -macrocode "databib\.bst"
+% -codetitle ""
+% -setambles "databib\.bst=>\nopreamble\nopostamble"
+% -src "datatool-base.sty\Z=>datatool-base.sty"
+% -src "datatool-fp.sty\Z=>datatool-fp.sty"
+% -src "datatool-pgfmath.sty\Z=>datatool-pgfmath.sty"
+% -src "datatool.sty\Z=>datatool.sty"
+% -src "datagidx.sty\Z=>datagidx.sty"
+% -src "databib.sty\Z=>databib.sty"
+% -src "databar.sty\Z=>databar.sty"
+% -src "datapie.sty\Z=>datapie.sty"
+% -src "dataplot.sty\Z=>dataplot.sty"
+% -src "person.sty\Z=>person.sty"
+% -src "databib.bst\Z=>databib.bst"
+% -doc "datatool-manual.tex"
+% -author "Nicola Talbot"
+% -comment "databib\.bst"
+% datatool
+% Created on 2018/12/7 15:44
+%\fi
+%\iffalse
+%<*package>
+%% \CharacterTable
+%% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
+%% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
+%% Digits \0\1\2\3\4\5\6\7\8\9
+%% Exclamation \! Double quote \" Hash (number) \#
+%% Dollar \$ Percent \% Ampersand \&
+%% Acute accent \' Left paren \( Right paren \)
+%% Asterisk \* Plus \+ Comma \,
+%% Minus \- Point \. Solidus \/
+%% Colon \: Semicolon \; Less than \<
+%% Equals \= Greater than \> Question mark \?
+%% Commercial at \@ Left bracket \[ Backslash \\
+%% Right bracket \] Circumflex \^ Underscore \_
+%% Grave accent \` Left brace \{ Vertical bar \|
+%% Right brace \} Tilde \~}
+%</package>
+%\fi
+% \iffalse
+% Doc-Source file to use with LaTeX2e
+% Copyright (C) 2018 Nicola Talbot, all rights reserved.
+% \fi
+% \iffalse
+%<*driver>
+\documentclass[report,widecs]{nlctdoc}
+
+\iffalse
+datatool-manual.tex is a stub file used by makedtx to create
+datatool.dtx
+\fi
+
+\DeleteShortVerb{|}
+
+\usepackage{datatool}
+\usepackage[utf8]{inputenc}
+\usepackage[T1]{fontenc}
+\usepackage[colorlinks,
+ bookmarks,
+ hyperindex=false,
+ pdfauthor={Nicola L. C. Talbot},
+ pdftitle={datatool: Databases and data manipulation},
+ pdfkeywords={LaTeX,package,database,data,chart,plot}]{hyperref}
+
+\doxitem{Counter}{counter}{counters}
+\doxitem{Option}{option}{package options}
+
+\CheckSum{24081}
+
+\RecordChanges
+\PageIndex
+\setcounter{IndexColumns}{2}
+
+\begin{document}
+\DocInput{datatool.dtx}
+\end{document}
+%</driver>
+%\fi
+%\MakeShortVerb{"}
+%
+%\title{Documented Code for datatool v2.31}
+%\author{Nicola L. C. Talbot\\
+%\url{http://www.dickimaw-books.com/}}
+%
+%\date{2018-12-07}
+%\maketitle
+%
+%\pagenumbering{roman}
+%
+%This is the documented code for the \styfmt{datatool} bundle. See
+%\url{datatool-user.pdf} for the main user manual.
+%
+%\clearpage
+%\pdfbookmark[0]{Contents}{contents}
+%\tableofcontents
+%
+%\pagenumbering{arabic}
+%
+%\StopEventually{%
+% \clearpage\phantomsection
+% \addcontentsline{toc}{chapter}{Index}%
+% \PrintIndex
+% \clearpage\phantomsection
+% \addcontentsline{toc}{chapter}{History}\PrintChanges
+%}
+%
+%
+%
+%\iffalse
+% \begin{macrocode}
+%<*datatool-base.sty>
+% \end{macrocode}
+%\fi
+%\chapter{datatool-base.sty}
+%\label{sec:code:datatool-base}
+% This package provides all the basic commands needed by various
+% packages in the \styfmt{datatool} bundle.
+%
+% \begin{macrocode}
+\NeedsTeXFormat{LaTeX2e}
+\ProvidesPackage{datatool-base}[2018/12/07 v2.31 (NLCT)]
+% \end{macrocode}
+% Required packages:
+% \begin{macrocode}
+\RequirePackage{etoolbox}
+\RequirePackage{amsmath}
+\RequirePackage{xkeyval}
+\RequirePackage{xfor}
+\RequirePackage{ifthen}
+% \end{macrocode}
+% Version of \isty{substr} required that fixes
+% \cs{su@IfSubStringInString}
+% \begin{macrocode}
+\RequirePackage{substr}[2009/10/20]
+% \end{macrocode}
+%
+%\section{Package Options}
+%
+%\begin{option}{verbose}
+% Define key for package option \pkgopt{verbose}. (This also
+% switches the \sty{fp} messages on/off if \sty{datatool-fp} used.)
+% This boolean may already have been defined if \sty{datatool} has
+% been loaded.
+% \begin{macrocode}
+\ifundef{\ifdtlverbose}
+{
+ \define@boolkey{datatool-base.sty}[dtl]{verbose}[true]{}
+}%
+{}
+% \end{macrocode}
+%\end{option}
+%\begin{option}{math}
+% Determine whether to use \sty{fp} or \sty{pgfmath} for the
+% arithmetic commands. The default is to use \sty{fp}.
+% \begin{macrocode}
+\define@choicekey{datatool-base.sty}{math}[\val\nr]{fp,pgfmath}{%
+ \renewcommand*\@dtl@mathprocessor{#1}%
+}
+% \end{macrocode}
+%\end{option}
+%
+%\begin{option}{utf8}
+%\changes{2.24}{2016-01-12}{new}
+% Enable UTF-8 support in comparison handlers. This is still a bit
+% experimental, so it needs to be explicitly switched on.
+% \begin{macrocode}
+\define@boolkey{datatool-base.sty}[@dtl@]{utf8}[true]{}
+\ifdef\UTFviii@two@octets
+{\booltrue{@dtl@utf8}}%
+{\boolfalse{@dtl@utf8}}
+% \end{macrocode}
+%\end{option}
+%
+%\begin{macro}{\dtlenableUTFviii}
+%\changes{2.24}{2016-01-12}{new}
+% \begin{macrocode}
+\newcommand*{\dtlenableUTFviii}{\booltrue{@dtl@utf8}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtldisableUTFviii}
+%\changes{2.24}{2016-01-12}{new}
+% \begin{macrocode}
+\newcommand*{\dtldisableUTFviii}{\boolfalse{@dtl@utf8}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@mathprocessor}
+% \begin{macrocode}
+\providecommand*{\@dtl@mathprocessor}{fp}
+% \end{macrocode}
+%\end{macro}
+%
+% Process options:
+% \begin{macrocode}
+\ProcessOptionsX
+% \end{macrocode}
+%
+% Load package dealing with numerical processes:
+% \begin{macrocode}
+\RequirePackage{datatool-\@dtl@mathprocessor}
+% \end{macrocode}
+%
+%\section{Utilities}
+%
+%\begin{macro}{\dtl@message}
+%\begin{definition}
+%\cs{dtl@message}\marg{message string}
+%\end{definition}
+% Displays message only if the verbose option is set.
+% \begin{macrocode}
+\newcommand*{\dtl@message}[1]{%
+ \ifdtlverbose\typeout{#1}\fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@toks}
+% \begin{macrocode}
+\newtoks\@dtl@toks
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@tmpcount}
+% Define temporary count register
+% \begin{macrocode}
+\newcount\@dtl@tmpcount
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtl@tmplength}
+% Define temporary length register:
+% \begin{macrocode}
+\newlength\dtl@tmplength
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtl@ifsingle}
+%\begin{definition}
+%\cs{dtl@ifsingle}\marg{arg}\marg{true part}\marg{false part}
+%\end{definition}
+% If there is only one object in \meta{arg} (without expansion)
+% do \meta{true part}, otherwise do false part.
+% \begin{macrocode}
+\newcommand{\dtl@ifsingle}[3]{%
+ \def\@dtl@arg{#1}%
+ \ifdefempty{\@dtl@arg}%
+ {%
+ #3%
+ }%
+ {%
+ \@dtl@ifsingle#1\@nil{#2}{#3}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@dtl@ifsingle}
+% \begin{macrocode}
+\def\@dtl@ifsingle#1#2\@nil#3#4{%
+ \def\dtl@sg@arg{#2}%
+ \ifdefempty{\dtl@sg@arg}%
+ {%
+ #3%
+ }%
+ {%
+ #4%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@ifsingleorUTFviii}
+%\changes{2.24}{2016-01-12}{new}
+% As above but also checks for UTF8.
+% \begin{macrocode}
+\newcommand{\dtl@ifsingleorUTFviii}[3]{%
+ \ifbool{@dtl@utf8}
+ {%
+ \def\@dtl@arg{#1}%
+ \ifdefempty{\@dtl@arg}%
+ {%
+ #3%
+ }%
+ {%
+ \expandafter\dtl@if@two@octets#1\relax\relax\dtl@end@if@two@octets
+ {%
+ \dtl@getfirst@UTFviii#1\@nil\end@dtl@getfirst@UTFviii
+ \ifdefempty\dtl@rest{#2}{#3}%
+ }%
+ {%
+ \@dtl@ifsingle#1\@nil{#2}{#3}%
+ }%
+ }%
+ }%
+ {%
+ \dtl@ifsingle{#1}{#2}{#3}%
+ }%
+}%
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlifintopenbetween}
+%\begin{definition}
+%\cs{dtlifintopenbetween}\marg{num}\marg{min}\marg{max}\marg{true
+%part}\marg{false part}
+%\end{definition}
+% If we're dealing with integers it's more efficient to use \TeX's
+% \cs{ifnum}.
+% \begin{macrocode}
+\newcommand{\dtlifintopenbetween}[5]{%
+ \ifnum#1>#2\relax
+% \end{macrocode}
+% Greater than minimum value. Is it less than the maximum?
+% \begin{macrocode}
+ \ifnum#1<#3\relax
+ #4%
+ \else
+ #5%
+ \fi
+ \else
+ #5%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlifintclosedbetween}
+%\begin{definition}
+%\cs{dtlifintclosedbetween}\marg{num}\marg{min}\marg{max}\marg{true
+%part}\marg{false part}
+%\end{definition}
+% If we're dealing with integers it's more efficient to use \TeX's
+% \cs{ifnum}.
+% \begin{macrocode}
+\newcommand{\dtlifintclosedbetween}[5]{%
+ \dtlifintopenbetween{#1}{#2}{#3}{#4}%
+ {%
+% \end{macrocode}
+% Check end points.
+% \begin{macrocode}
+ \ifnum#1=#2\relax
+ #4%
+ \else
+ \ifnum#1=#3\relax
+ #4%
+ \else
+ #5%
+ \fi
+ \fi
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\long@collect@body}
+% Need long versions of \isty{amsmath}'s \cs{collect@body}. These macros are
+% adapted from the macros defined by \sty{amsmath}.
+% \begin{macrocode}
+\long\def\long@collect@body#1{%
+ \@envbody{\@xp#1\@xp{\the\@envbody}}%
+ \edef\process@envbody{\the\@envbody\@nx\end{\@currenvir}}%
+ \@envbody\@emptytoks \def\begin@stack{b}%
+ \begingroup
+ \@xp\let\csname\@currenvir\endcsname\long@collect@@body
+ \edef\process@envbody{\@xp\@nx\csname\@currenvir\endcsname}%
+ \process@envbody
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\long@addto@envbody}
+%\changes{2.10}{2012-07-18}{new}
+% Adapted from \isty{amsmath}'s \cs{addto@envbody}
+% \begin{macrocode}
+\long\def\long@addto@envbody#1{%
+ \toks@{#1}%
+ \edef\@dtl@tmp{\the\@envbody\the\toks@}%
+ \global\@envbody\@xp{\@dtl@tmp}%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\long@collect@@body}
+%\changes{2.10}{2012-07-18}{new}
+% Adapted from \isty{amsmath}'s \cs{collect@body}
+% \begin{macrocode}
+\long\def\long@collect@@body#1\end#2{%
+ \protected@edef\begin@stack{%
+ \long@push@begins#1\begin\end \@xp\@gobble\begin@stack
+ }%
+ \ifx\@empty\begin@stack
+ \endgroup
+ \@checkend{#2}%
+ \long@addto@envbody{#1}%
+ \else
+ \long@addto@envbody{#1\end{#2}}%
+ \fi
+ \process@envbody
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\long@push@begins}
+%\changes{2.10}{2012-07-18}{new}
+%Adapted from \isty{amsmath}'s \cs{push@begins}
+% \begin{macrocode}
+\long\def\long@push@begins#1\begin#2{%
+ \ifx\end#2\else b\@xp\long@push@begins\fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\subsection{General List Utilities}
+%
+%\begin{macro}{\DTLifinlist}
+%\begin{definition}
+%\cs{DTLifinlist}\marg{element}\marg{list}\marg{true part}\marg{false part}
+%\end{definition}
+% If \meta{element} is contained in the comma-separated list given
+% by \meta{list}, then do \meta{true part} otherwise do false
+% part. (Does a one level expansion on \meta{list}, but no
+% expansion on \meta{element}.)
+% \begin{macrocode}
+\newcommand*{\DTLifinlist}[4]{%
+ \def\@dtl@doifinlist##1,#1,##2\end@dtl@doifinlist{%
+ \def\@before{##1}%
+ \def\@after{##2}%
+ }%
+ \expandafter\@dtl@doifinlist\expandafter,#2,#1,\@nil
+ \end@dtl@doifinlist
+ \ifx\@after\@nnil
+% not found
+ #4%
+ \else
+% found
+ #3%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\ifDTLlistskipempty}
+%\changes{2.31}{2018-12-07}{new}
+%If true, skip empty elements in the list-related commands below.
+% \begin{macrocode}
+\newif\ifDTLlistskipempty
+\DTLlistskipemptytrue
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLlistelement}
+%\begin{definition}
+%\cs{DTLlistelement}\marg{list}\marg{idx}
+%\end{definition}
+%Does the \meta{idx}th element in the list. The index
+%should start from 1 for the first element.
+% \begin{macrocode}
+\newrobustcmd{\DTLlistelement}[2]{%
+% \end{macrocode}
+%The \cs{@for}-loop is scoped in case it's nested.
+% \begin{macrocode}
+ \begingroup
+ \@dtl@tmpcount=0\relax
+ \@for\@dtl@element:=#1\do{%
+ \ifDTLlistskipempty
+ \ifdefempty{\@dtl@element}%
+ {}%
+ {%
+ \advance\@dtl@tmpcount by 1\relax%
+ \ifnum\@dtl@tmpcount=#2 \@dtl@element\@endfortrue\fi
+ }%
+ \else
+ \advance\@dtl@tmpcount by 1\relax%
+ \ifnum\@dtl@tmpcount=#2 \@dtl@element\@endfortrue\fi
+ \fi
+ }%
+ \if@endfor \else\@dtl@listelement@outofrange{#2}\fi
+ \endgroup
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLfetchlistelement}
+%\begin{definition}
+%\cs{DTLfetchlistelement}\marg{list}\marg{idx}\marg{cs}
+%\end{definition}
+%Fetches the \meta{idx}th element in the list and stores in \meta{cs}. The index
+%should start from 1 for the first element.
+% \begin{macrocode}
+\newrobustcmd{\DTLfetchlistelement}[3]{%
+% \end{macrocode}
+%The \cs{@for}-loop is scoped in case it's nested.
+% \begin{macrocode}
+ \begingroup
+ \@dtl@tmpcount=0\relax
+ \@for\@dtl@element:=#1\do{%
+ \ifDTLlistskipempty
+ \ifdefempty{\@dtl@element}%
+ {}%
+ {%
+ \advance\@dtl@tmpcount by 1\relax%
+ \ifnum\@dtl@tmpcount=#2 \@endfortrue\fi
+ }%
+ \else
+ \advance\@dtl@tmpcount by 1\relax%
+ \ifnum\@dtl@tmpcount=#2 \@endfortrue\fi
+ \fi
+ }%
+ \if@endfor \else\def\@dtl@element{\@dtl@listelement@outofrange{#2}}\fi
+ \edef\x{%
+ \endgroup
+ \noexpand\def\noexpand#3{\expandonce\@dtl@element}%
+ }\x
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@listelement@outofrange}
+%\changes{2.31}{2018-12-07}{new}
+% \begin{macrocode}
+\newcommand{\@dtl@listelement@outofrange}[1]{%
+ \PackageWarning{datatool-base}{List index `\number#1' out of range}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLnumitemsinlist}
+%\begin{definition}
+%\cs{DTLnumitemsinlist}\marg{list}\marg{cmd}
+%\end{definition}
+% Counts number of non-empty elements in list and stores result in control
+% sequence \meta{cmd}.
+%\changes{2.31}{2018-12-07}{made robust}
+% \begin{macrocode}
+\newrobustcmd{\DTLnumitemsinlist}[2]{%
+ \@dtl@tmpcount=0\relax
+ \@for\@dtl@element:=#1\do{%
+ \ifDTLlistskipempty
+ \ifdefempty{\@dtl@element}%
+ {}%
+ {\advance\@dtl@tmpcount by 1\relax}%
+ \else
+ \advance\@dtl@tmpcount by 1\relax
+ \fi
+ }%
+ \edef#2{\number\@dtl@tmpcount}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@choplast}
+%\begin{definition}
+% \cs{dtl@choplast}\marg{list}\marg{rest}\marg{last}
+%\end{definition}
+% Chops the last element off a comma separated list, putting the
+% last element in the control sequence \meta{last} and putting
+% the rest in the control sequence \meta{rest}. The control
+% sequence \meta{list} is unchanged. If the list is empty, both
+% \meta{last} and \meta{rest} will be empty.
+% \begin{macrocode}
+\newcommand*{\dtl@choplast}[3]{%
+% \end{macrocode}
+% Set \meta{rest} to empty:
+% \begin{macrocode}
+ \let#2\@empty
+% \end{macrocode}
+% Set \meta{last} to empty:
+% \begin{macrocode}
+ \let#3\@empty
+% \end{macrocode}
+% Iterate through \meta{list}:
+% \begin{macrocode}
+ \@for\@dtl@element:=#1\do{%
+ \ifdefempty{#3}%
+ {%
+% \end{macrocode}
+% First iteration, don't set \meta{rest}.
+% \begin{macrocode}
+ }%
+ {%
+ \ifdefempty{#2}%
+ {%
+% \end{macrocode}
+% Second iteration, set \meta{rest} to \meta{last} (which is
+% currently set to the previous value:
+% \begin{macrocode}
+ \expandafter\toks@\expandafter{#3}%
+ \edef#2{{\the\toks@}}%
+ }%
+ {%
+% \end{macrocode}
+% Subsequent iterations, set \meta{rest} to \meta{rest},\meta{last}
+% (\meta{last} is currently set to the previous value):
+% \begin{macrocode}
+ \expandafter\toks@\expandafter{#3}%
+ \expandafter\@dtl@toks\expandafter{#2}%
+ \edef#2{\the\@dtl@toks,{\the\toks@}}%
+ }%
+ }%
+% \end{macrocode}
+% Now set \meta{last} to current element.
+% \begin{macrocode}
+ \let#3=\@dtl@element%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@chopfirst}
+%\begin{definition}
+% \cs{dtl@chopfirst}\marg{list}\marg{first}\marg{rest}
+%\end{definition}
+% Chops first element off \meta{list} and store in \meta{first}.
+% The remainder of the list is stored in \meta{rest}. (\meta{list}
+% remains unchanged.)
+% \begin{macrocode}
+\newcommand*{\dtl@chopfirst}[3]{%
+ \let#2=\@empty
+ \let#3=\@empty
+ \@for\@dtl@element:=#1\do{%
+ \let#2=\@dtl@element
+ \@endfortrue
+ }%
+ \if@endfor
+ \let#3=\@forremainder
+ \fi
+ \@endforfalse
+}
+% \end{macrocode}
+%\end{macro}
+%
+%I made a bit of a blunder here. \cs{dtl@sortlist} was supposed to
+%work with commands like \cs{dtlcompare}, but those commands require
+%three arguments, the first being the register in which to store the
+%result. This contradicts the requirements of \cs{dtl@sortlist}. The
+%\qt{bug fix} in v2.26 fixed it to work with commands like
+%\cs{dtlcompare}, but that broke the documented design (which breaks
+%the \sty{glossaries} package). The other problem is that
+%\cs{dtl@insertinto} actually sorts in the reverse order.
+%So v2.27 undoes the change from v2.26 to ensure backward
+%compatibility and provides an alternative user-level command
+%\cs{dltsortlist}, that's designed to work with the three-argument
+%handler commands like \cs{dtlcompare}.
+%
+%\begin{macro}{\dtl@sortlist}
+%\begin{definition}
+% \cs{dtl@sortlist}\marg{list}\marg{criteria cmd}
+%\end{definition}
+% Performs an insertion sort on \meta{list}, where \meta{criteria cmd}
+% is a macro which takes two arguments \meta{a} and \meta{b}.
+% \meta{criteria cmd} must set the count register \cs{dtl@sortresult}
+% to either $-1$ (\meta{b} less than \meta{a}), 0 (\meta{a} is
+% equal to \meta{b}) or 1 (\meta{b} is greater than \meta{a}.)
+% \begin{macrocode}
+\newcommand{\dtl@sortlist}[2]{%
+\def\@dtl@sortedlist{}%
+\@for\@dtl@currentrow:=#1\do{%
+\expandafter\dtl@insertinto\expandafter
+ {\@dtl@currentrow}{\@dtl@sortedlist}{#2}%
+\@endforfalse}%
+\let#1=\@dtl@sortedlist
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@insertinto}
+%\begin{definition}
+% \cs{dtl@insertinto}\marg{element}\marg{sorted-list}\marg{criteria cmd}
+%\end{definition}
+% Inserts \meta{element} into the sorted list \meta{sorted-list}
+% according to the criteria given by \meta{criteria cmd} (see above.)
+% \begin{macrocode}
+\newcommand{\dtl@insertinto}[3]{%
+ \def\@dtl@newsortedlist{}%
+ \@dtl@insertdonefalse
+ \@for\dtl@srtelement:=#2\do{%
+ \if@dtl@insertdone
+ \expandafter\toks@\expandafter{\dtl@srtelement}%
+ \edef\@dtl@newstuff{{\the\toks@}}%
+ \else
+% \end{macrocode}
+%\changes{2.26}{2016-07-20}{fixed bug (missing \cs{dtl@sortresult})}
+%\changes{2.27}{2016-07-28}{undone the incorrect change in v2.26}
+% \begin{macrocode}
+ \expandafter#3\expandafter{\dtl@srtelement}{#1}%
+% \end{macrocode}
+%\changes{2.26}{2016-07-20}{fixed bug (incorrect inequality sign)}
+%\changes{2.27}{2016-07-28}{undone the incorrect change in v2.26}
+% \begin{macrocode}
+ \ifnum\dtl@sortresult<0\relax
+ \expandafter\toks@\expandafter{\dtl@srtelement}%
+ \@dtl@toks{#1}%
+ \edef\@dtl@newstuff{{\the\@dtl@toks},{\the\toks@}}%
+ \@dtl@insertdonetrue
+ \else
+ \expandafter\toks@\expandafter{\dtl@srtelement}%
+ \edef\@dtl@newstuff{{\the\toks@}}%
+ \fi
+ \fi
+ \ifdefempty{\@dtl@newsortedlist}%
+ {%
+ \expandafter\toks@\expandafter{\@dtl@newstuff}%
+ \edef\@dtl@newsortedlist{\the\toks@}%
+ }%
+ {%
+ \expandafter\toks@\expandafter{\@dtl@newsortedlist}%
+ \expandafter\@dtl@toks\expandafter{\@dtl@newstuff}%
+ \edef\@dtl@newsortedlist{\the\toks@,\the\@dtl@toks}%
+ }%
+ \@endforfalse
+ }%
+ \ifdefempty{\@dtl@newsortedlist}%
+ {%
+ \@dtl@toks{#1}%
+ \edef\@dtl@newsortedlist{{\the\@dtl@toks}}%
+ }%
+ {%
+ \if@dtl@insertdone
+ \else
+ \expandafter\toks@\expandafter{\@dtl@newsortedlist}%
+ \@dtl@toks{#1}%
+ \edef\@dtl@newsortedlist{\the\toks@,{\the\@dtl@toks}}%
+ \fi
+ }%
+ \global\let#2=\@dtl@newsortedlist
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlsortlist}
+%\changes{2.27}{2016-07-28}{new}
+%\begin{definition}
+% \cs{dtlsortlist}\marg{list}\marg{criteria cmd}
+%\end{definition}
+% As \cs{dtl@sortlist} but the \meta{criteria} command must take
+% three arguments.
+% \begin{macrocode}
+\newcommand{\dtlsortlist}[2]{%
+\def\@dtl@sortedlist{}%
+\@for\@dtl@currentrow:=#1\do{%
+\expandafter\dtlinsertinto\expandafter
+ {\@dtl@currentrow}{\@dtl@sortedlist}{#2}%
+\@endforfalse}%
+\let#1=\@dtl@sortedlist
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlinsertinto}
+%\changes{2.27}{2016-07-28}{new}
+%\begin{definition}
+% \cs{dtlinsertinto}\marg{element}\marg{sorted-list}\marg{criteria cmd}
+%\end{definition}
+% Inserts \meta{element} into the sorted list \meta{sorted-list}
+% according to the criteria given by \meta{criteria cmd}, which
+% should be a command that takes three arguments
+% \marg{reg}\marg{A}\marg{B}, where \meta{reg} is a count register
+% in which to store the result, \meta{A} is the first element and
+% \meta{B} is the second element to compare.
+% \begin{macrocode}
+\newcommand{\dtlinsertinto}[3]{%
+ \def\@dtl@newsortedlist{}%
+ \@dtl@insertdonefalse
+ \@for\dtl@srtelement:=#2\do{%
+ \expandafter\DTLifSubString\expandafter{\dtl@srtelement}{,}
+ {%
+ \expandafter\toks@\expandafter{\dtl@srtelement}%
+ \edef\dtl@srtelement{{\the\toks@}}%
+ }%
+ {%
+ }
+ \if@dtl@insertdone
+ \let\@dtl@newstuff\dtl@srtelement
+ \else
+ \expandafter#3\expandafter\dtl@sortresult
+ \expandafter{\dtl@srtelement}{#1}%
+ \ifnum\dtl@sortresult>0\relax
+ \DTLifSubString{#1}{,}%
+ {%
+ \@dtl@toks{{#1}}%
+ }%
+ {%
+ \@dtl@toks{#1}%
+ }%
+ \expandafter\toks@\expandafter{\dtl@srtelement}%
+ \edef\@dtl@newstuff{\the\@dtl@toks,\the\toks@}%
+ \@dtl@insertdonetrue
+ \else
+ \expandafter\toks@\expandafter{\dtl@srtelement}%
+ \edef\@dtl@newstuff{{\the\toks@}}%
+ \let\@dtl@newstuff\dtl@srtelement
+ \fi
+ \fi
+ \ifdefempty{\@dtl@newsortedlist}%
+ {%
+ \expandafter\toks@\expandafter{\@dtl@newstuff}%
+ \edef\@dtl@newsortedlist{\the\toks@}%
+ }%
+ {%
+ \expandafter\toks@\expandafter{\@dtl@newsortedlist}%
+ \expandafter\@dtl@toks\expandafter{\@dtl@newstuff}%
+ \edef\@dtl@newsortedlist{\the\toks@,\the\@dtl@toks}%
+ }%
+ \@endforfalse
+ }%
+ \ifdefempty{\@dtl@newsortedlist}%
+ {%
+ \DTLifSubString{#1}{,}%
+ {%
+ \@dtl@toks{{#1}}%
+ }%
+ {%
+ \@dtl@toks{#1}%
+ }%
+ \edef\@dtl@newsortedlist{\the\@dtl@toks}%
+ }%
+ {%
+ \if@dtl@insertdone
+ \else
+ \DTLifSubString{#1}{,}%
+ {%
+ \@dtl@toks{{#1}}%
+ }%
+ {%
+ \@dtl@toks{#1}%
+ }%
+ \expandafter\toks@\expandafter{\@dtl@newsortedlist}%
+ \edef\@dtl@newsortedlist{\the\toks@,\the\@dtl@toks}%
+ \fi
+ }%
+ \global\let#2=\@dtl@newsortedlist
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\edtlinsertinto}
+%\changes{2.27}{2016-07-28}{new}
+%\begin{definition}
+% \cs{edtlinsertinto}\marg{element}\marg{sorted-list}\marg{criteria cmd}
+%\end{definition}
+%First expands \meta{element} before inserting into the list.
+% \begin{macrocode}
+\newcommand*{\edtlinsertinto}[3]{%
+ \protected@edef\dtl@srtelement{#1}%
+ \expandafter\dtlinsertinto\expandafter{\dtl@srtelement}{#2}{#3}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\if@dtl@insertdone}
+% Define conditional to indicate whether the new entry has
+% been inserted into the sorted list.
+% \begin{macrocode}
+\newif\if@dtl@insertdone
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtl@sortresult}
+% Define \cs{dtl@sortresult} to be set by comparison macro.
+% \begin{macrocode}
+\newcount\dtl@sortresult
+% \end{macrocode}
+%\end{macro}
+%
+%This next command is based on the list iteration exercise
+%given at
+%\url{http://www.dickimaw-books.com/latex/admin/html/foreachtips.shtml#oxfordcomma}
+%It's designed to format a comma-separated list using
+%\cs{DTLlistformatsep}
+%between each item except for the last. The separator for the
+%last pair is \cs{DTLlistformatlastsep} if the list only contains two
+%items or \cs{DTLlistformatoxford}\cs{DTLlistformatlastsep} if the list contains three or
+%more items. Each item is formatted according to
+%\cs{DTLlistformatitem}.
+%\begin{macro}{\DTLlistformatsep}
+%\changes{2.28}{2017-11-10}{new}
+% \begin{macrocode}
+\newcommand*{\DTLlistformatsep}{, }
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLlistformatoxford}
+%\changes{2.28}{2017-11-10}{new}
+% \begin{macrocode}
+\newcommand*{\DTLlistformatoxford}{}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLandname}
+%\changes{2.28}{2017-11-10}{new}
+% \begin{macrocode}
+\ifdef\andname
+{\newcommand*{\DTLandname}{\andname}}
+{\newcommand*{\DTLandname}{\&}}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLlistformatlastsep}
+%\changes{2.28}{2017-11-10}{new}
+% \begin{macrocode}
+\newcommand*{\DTLlistformatlastsep}{ \DTLandname\space}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLlistformatitem}
+%\changes{2.28}{2017-11-10}{new}
+% \begin{macrocode}
+\newcommand*{\DTLlistformatitem}[1]{#1}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@formatlist@handler}
+%\changes{2.28}{2017-11-10}{new}
+% \begin{macrocode}
+\newcommand*{\@dtl@formatlist@handler}[1]{%
+ \@dtl@formatlist@itemsep
+ \@dtl@formatlist@lastitem
+ \renewcommand{\@dtl@formatlist@lastitem}{%
+ \renewcommand{\@dtl@formatlist@itemsep}{%
+ \DTLlistformatsep
+ \renewcommand*{\@dtl@formatlist@prelastitemsep}{%
+ \DTLlistformatoxford}}%
+ \renewcommand{\@dtl@formatlist@prelastitem}{%
+ \@dtl@formatlist@prelastitemsep
+ \DTLlistformatlastsep}%
+ \DTLlistformatitem{#1}%
+ }%
+}%
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLformatlist}
+%\changes{2.28}{2017-11-10}{new}
+%Formats the comma-separated list supplied in its argument.
+%The unstarred version adds grouping.
+% \begin{macrocode}
+\newrobustcmd*{\DTLformatlist}{%
+ \@ifstar{\s@dtlformatlist}{\@dtlformatlist}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\s@dtlformatlist}
+%\changes{2.28}{2017-11-10}{new}
+%Starred version of \cs{DTLformatlist} doesn't add grouping.
+% \begin{macrocode}
+\newcommand*{\s@dtlformatlist}[1]{%
+ \def\@dtl@formatlist@itemsep{}%
+ \def\@dtl@formatlist@lastitem{}%
+ \def\@dtl@formatlist@prelastitem{}%
+ \def\@dtl@formatlist@prelastitemsep{}%
+ \@for\@dtl@formatlist@item:=#1\do{%
+ \ifDTLlistskipempty
+ \ifdefempty{\@dtl@formatlist@item}%
+ {}%
+ {\expandafter\@dtl@formatlist@handler\expandafter{\@dtl@formatlist@item}}%
+ \else
+ \expandafter\@dtl@formatlist@handler\expandafter{\@dtl@formatlist@item}%
+ \fi
+ }%
+ \@dtl@formatlist@prelastitem\@dtl@formatlist@lastitem
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtlformatlist}
+%\changes{2.28}{2017-11-10}{new}
+%Unstarred version of \cs{DTLformatlist} adds grouping.
+% \begin{macrocode}
+\newcommand*{\@dtlformatlist}[1]{{\s@dtlformatlist{#1}}}
+% \end{macrocode}
+%\end{macro}
+%
+% \subsection{General Token Utilities}
+%\changes{2.28}{2017-11-10}{renamed \cs{toks@g...} to
+%\cs{dtl@toks@g...}}
+%\begin{macro}{\@dtl@toks@gput@right@cx}
+%\begin{definition}
+%\cs{dtl@toks@gput@right@cx}\marg{toks name}\marg{stuff}
+%\end{definition}
+% Globally appends stuff to token register \cs{}\meta{toks name}
+% \begin{macrocode}
+\newcommand{\@dtl@toks@gput@right@cx}[2]{%
+ \def\@dtl@toks@name{#1}%
+ \edef\@dtl@stuff{#2}%
+ \global\csname\@dtl@toks@name\endcsname\expandafter
+ \expandafter\expandafter{\expandafter\the
+ \csname\expandafter\@dtl@toks@name\expandafter\endcsname\@dtl@stuff}%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@dtl@toks@gconcat@middle@cx}
+%\begin{definition}
+%\cs{dtl@toks@gconcat@middle@cx}\marg{toks name}\marg{before toks}\marg{stuff}\marg{after toks}
+%\end{definition}
+% Globally sets token register \cs{}\meta{toks name} to
+% the contents of \meta{before toks} concatenated with
+% \meta{stuff} (expanded) and the contents of \meta{after toks}
+% \begin{macrocode}
+\newcommand{\@dtl@toks@gconcat@middle@cx}[4]{%
+ \def\@dtl@toks@name{#1}%
+ \edef\@dtl@stuff{#3}%
+ \global\csname\@dtl@toks@name\endcsname\expandafter\expandafter
+ \expandafter\expandafter\expandafter
+ \expandafter\expandafter{\expandafter\expandafter\expandafter
+ \the\expandafter\expandafter\expandafter#2%
+ \expandafter\@dtl@stuff\the#4}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\section{Locale Dependent Information}
+%
+%\begin{macro}{\@dtl@numgrpsepcount}
+% Define count register to count the digits between the number
+% group separators.
+% \begin{macrocode}
+\newcount\@dtl@numgrpsepcount
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@decimal}
+% The current decimal character is stored in \cs{@dtl@decimal}.
+% \begin{macrocode}
+\newcommand*{\@dtl@decimal}{.}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@dtl@numbergroupchar}
+% The current number group character is stored in
+% \cs{@dtl@numbergroupchar}.
+% \begin{macrocode}
+\newcommand*{\@dtl@numbergroupchar}{,}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLsetnumberchars}
+%\begin{definition}
+%\cs{DTLsetnumberchars}\marg{number group char}\marg{decimal char}
+%\end{definition}
+% This sets the decimal character and number group
+% characters.
+% \begin{macrocode}
+\newcommand*{\DTLsetnumberchars}[2]{%
+ \renewcommand*{\@dtl@numbergroupchar}{#1}%
+ \renewcommand*{\@dtl@decimal}{#2}%
+ \@dtl@construct@getnums
+ \@dtl@construct@stripnumgrpchar{#1}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@construct@getintfrac}
+%\begin{definition}
+%\cs{@dtl@construct@getintfrac}\marg{char}
+%\end{definition}
+% This constructs the macros for extracting integer and
+% fractional parts from a real number using the decimal character
+% \meta{char}.
+%
+%\begin{definition}[\DescribeMacro{\DTLconverttodecimal}]
+% \cs{DTLconverttodecimal}\marg{num}\marg{cmd}
+%\end{definition}
+% \cs{DTLconverttodecimal} will convert locale dependent \meta{num}
+% a decimal number in a form that can be used in the
+% macros defined in the \sty{fp} package. The resulting
+% number is stored in \meta{cmd}. This command has to be redefined
+% whenever the decimal and number group characters are changed
+% as they form part of the command definitions.
+%\changes{2.12}{2012-11-30}{switched to \cs{ifdefempty}}
+% \begin{macrocode}
+\edef\@dtl@construct@getintfrac#1{%
+ \noexpand\def\noexpand\@dtl@getintfrac##1#1##2\noexpand\relax{%
+ \noexpand\@dtl@get@intpart{##1}%
+ \noexpand\def\noexpand\@dtl@fracpart{##2}%
+ \noexpand\ifdefempty{\noexpand\@dtl@fracpart}
+ {%
+ \noexpand\def\noexpand\@dtl@fracpart{0}%
+ }%
+ {%
+ \noexpand\@dtl@getfracpart##2\noexpand\relax
+ \noexpand\@dtl@choptrailingzeroes{\noexpand\@dtl@fracpart}%
+ }%
+ }%
+ \noexpand\def\noexpand\@dtl@getfracpart##1#1\noexpand\relax{%
+ \noexpand\def\noexpand\@dtl@fracpart{##1}%
+ }%
+ \noexpand\def\noexpand\DTLconverttodecimal##1##2{%
+ \noexpand\dtl@ifsingle{##1}%
+ {%
+ \noexpand\expandafter\noexpand\toks@\noexpand\expandafter{##1}%
+ \noexpand\edef\noexpand\@dtl@tmp{\noexpand\the\noexpand\toks@}%
+ }%
+ {%
+ \noexpand\def\noexpand\@dtl@tmp{##1}%
+ }%
+ \noexpand\@dtl@standardize@currency\noexpand\@dtl@tmp
+ \noexpand\ifdefempty{\noexpand\@dtl@org@currency}%
+ {%
+ }%
+ {%
+ \noexpand\let\noexpand\@dtl@currency\noexpand\@dtl@org@currency
+ }%
+ \noexpand\expandafter
+ \noexpand\@dtl@getintfrac\noexpand\@dtl@tmp#1\noexpand\relax
+ \noexpand\edef##2{\noexpand\@dtl@intpart.\noexpand\@dtl@fracpart}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@dtl@construct@getnums}
+% The following calls the above with the relevant
+% decimal character:
+% \begin{macrocode}
+\newcommand*{\@dtl@construct@getnums}{%
+ \expandafter\@dtl@construct@getintfrac\expandafter{\@dtl@decimal}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@get@intpart}
+% The following gets the integer part (adjusting for
+% repeating +/- signs if necessary.)
+% Sets \cs{@dtl@intpart}.
+% \begin{macrocode}
+\newcommand*{\@dtl@get@intpart}[1]{%
+ \@dtl@tmpcount=1\relax
+ \def\@dtl@intpart{#1}%
+ \ifx\@dtl@intpart\@empty
+ \def\@dtl@intpart{0}%
+ \else
+ \def\@dtl@intpart{}%
+ \@dtl@get@int@part#1.\relax%
+ \fi
+ \ifnum\@dtl@tmpcount<0\relax
+ \edef\@dtl@intpart{-\@dtl@intpart}%
+ \fi
+ \@dtl@strip@numgrpchar{\@dtl@intpart}%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@dtl@get@int@part}
+% \begin{macrocode}
+\def\@dtl@get@int@part#1#2\relax{%
+ \def\@dtl@argi{#1}%
+ \def\@dtl@argii{#2}%
+ \ifx\protect#1\relax%
+ \let\@dtl@get@nextintpart=\@dtl@get@int@part
+ \else
+ \expandafter\ifx\@dtl@argi\$%
+ \let\@dtl@get@nextintpart=\@dtl@get@int@part
+ \else
+ \ifx-#1%
+ \multiply\@dtl@tmpcount by -1\relax
+ \let\@dtl@get@nextintpart=\@dtl@get@int@part
+ \else
+ \if\@dtl@argi+%
+ \let\@dtl@get@nextintpart=\@dtl@get@int@part
+ \else
+ \def\@dtl@intpart{#1}%
+ \ifx.\@dtl@argii
+ \let\@dtl@get@nextintpart=\@gobble
+ \else
+ \let\@dtl@get@nextintpart=\@dtl@get@next@intpart
+ \fi
+ \fi
+ \fi
+ \fi
+ \fi
+ \@dtl@get@nextintpart#2\relax
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@dtl@get@next@intpart}
+% \begin{macrocode}
+\def\@dtl@get@next@intpart#1.\relax{%
+ \edef\@dtl@intpart{\@dtl@intpart#1}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@choptrailingzeroes}
+%\begin{definition}
+% \cs{@dtl@choptrailingzeroes}\marg{cmd}
+%\end{definition}
+% Chops trailing zeroes from number given by \meta{cmd}.
+% \begin{macrocode}
+\newcommand*{\@dtl@choptrailingzeroes}[1]{%
+ \def\@dtl@tmpcpz{}%
+ \expandafter\@dtl@chop@trailingzeroes#1\@nil%
+ \let#1=\@dtl@tmpcpz
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@chop@trailingzeroes}
+% Trailing zeroes are chopped using a recursive algorithm.
+% \cs{@dtl@tmpcpz} needs to be set before using this. (The chopped
+% number is put in this control sequence.)
+% \begin{macrocode}
+\def\@dtl@chop@trailingzeroes#1#2\@nil{%
+ \dtlifnumeq{#2}{0}%
+ {%
+ \edef\@dtl@tmpcpz{\@dtl@tmpcpz#1}%
+ \let\@dtl@chopzeroesnext=\@dtl@gobbletonil
+ }%
+ {%
+ \edef\@dtl@tmpcpz{\@dtl@tmpcpz#1}%
+ \let\@dtl@chopzeroesnext=\@dtl@chop@trailingzeroes
+ }%
+ \@dtl@chopzeroesnext#2\@nil
+}
+% \end{macrocode}
+%\end{macro}
+% No-op macro to end recursion:
+%\begin{macro}{\@dtl@gobbletonil}
+% \begin{macrocode}
+\def\@dtl@gobbletonil#1\@nil{}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@truncatedecimal}
+%\begin{definition}
+%\cs{dtl@truncatedecimal}\meta{cmd}
+%\end{definition}
+%Truncates decimal given by \meta{cmd} to an integer (assumes the
+% number is in decimal format with full stop as decimal point.)
+% \begin{macrocode}
+\newcommand*{\dtl@truncatedecimal}[1]{%
+ \expandafter\@dtl@truncatedecimal#1.\@nil#1%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@dtl@truncatedecimal}
+% \begin{macrocode}
+\def\@dtl@truncatedecimal#1.#2\@nil#3{%
+ \def#3{#1}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@strip@numgrpchar}
+%\begin{definition}
+% \cs{@dtl@strip@numgrpchar}\marg{cmd}
+%\end{definition}
+% Strip the number group character from the number given by
+% \meta{cmd}.
+% \begin{macrocode}
+\newcommand*{\@dtl@strip@numgrpchar}[1]{%
+ \def\@dtl@stripped{}%
+ \edef\@dtl@do@stripnumgrpchar{%
+ \noexpand\@@dtl@strip@numgrpchar#1\@dtl@numbergroupchar
+ \noexpand\relax
+ }%
+ \@dtl@do@stripnumgrpchar
+ \let#1=\@dtl@stripped
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@construct@stripnumgrpchar}
+% The following macro constructs \cs{@@dtl@strip@numgrpchar}.
+% \begin{macrocode}
+\edef\@dtl@construct@stripnumgrpchar#1{%
+ \noexpand\def\noexpand\@@dtl@strip@numgrpchar##1#1##2\noexpand\relax{%
+ \noexpand\expandafter\noexpand\toks@\noexpand\expandafter
+ {\noexpand\@dtl@stripped}%
+ \noexpand\edef\noexpand\@dtl@stripped{%
+ \noexpand\the\noexpand\toks@
+ ##1%
+ }%
+ \noexpand\def\noexpand\@dtl@tmp{##2}%
+ \noexpand\ifx\noexpand\@dtl@tmp\noexpand\@empty
+ \noexpand\let\noexpand\@dtl@next=\noexpand\relax
+ \noexpand\else
+ \noexpand\let\noexpand\@dtl@next=\noexpand\@@dtl@strip@numgrpchar
+ \noexpand\fi
+ \noexpand\@dtl@next##2\noexpand\relax
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLdecimaltolocale}
+%\begin{definition}
+% \cs{DTLdecimaltolocale}\marg{number}\marg{cmd}
+%\end{definition}
+% Define command to convert a decimal number into the locale
+% dependent format. Stores result in \meta{cmd} which must be
+% a control sequence.
+% \begin{macrocode}
+\newcommand*{\DTLdecimaltolocale}[2]{%
+ \edef\@dtl@tmpdtl{#1}%
+ \expandafter\@dtl@decimaltolocale\@dtl@tmpdtl.\relax
+ \dtlifnumeq{\@dtl@fracpart}{0}%
+ {%
+ \edef#2{\@dtl@intpart}%
+ }%
+ {%
+ \edef#2{\@dtl@intpart\@dtl@decimal\@dtl@fracpart}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@dtl@decimaltolocale}
+% Convert the integer part (store in \cs{@dtl@intpart})
+% \begin{macrocode}
+\def\@dtl@decimaltolocale#1.#2\relax{%
+ \@dtl@decimaltolocaleint{#1}%
+ \def\@dtl@fracpart{#2}%
+ \ifdefempty\@dtl@fracpart
+ {%
+ \def\@dtl@fracpart{0}%
+ }%
+ {%
+ \@dtl@decimaltolocalefrac#2\relax
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@dtl@decimaltolocaleint}
+% \begin{macrocode}
+\def\@dtl@decimaltolocaleint#1{%
+ \@dtl@tmpcount=0\relax
+ \@dtl@countdigits#1.\relax
+ \@dtl@numgrpsepcount=\@dtl@tmpcount\relax
+ \divide\@dtl@numgrpsepcount by 3\relax
+ \multiply\@dtl@numgrpsepcount by 3\relax
+ \advance\@dtl@numgrpsepcount by -\@dtl@tmpcount\relax
+ \ifnum\@dtl@numgrpsepcount<0\relax
+ \advance\@dtl@numgrpsepcount by 3\relax
+ \fi
+ \def\@dtl@intpart{}%
+ \@dtl@decimal@to@localeint#1.\relax
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@dtl@countdigits}
+% Counts the number of digits until "#2" is a full stop.
+% (increments \cs{@dtl@tmpcount}.)
+% \begin{macrocode}
+\def\@dtl@countdigits#1#2\relax{%
+ \advance\@dtl@tmpcount by 1\relax
+ \ifx.#2\relax
+ \let\@dtl@countnext=\@gobble
+ \else
+ \let\@dtl@countnext=\@dtl@countdigits
+ \fi
+ \@dtl@countnext#2\relax
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@dtl@decimal@to@localeint}
+% \begin{macrocode}
+\def\@dtl@decimal@to@localeint#1#2\relax{%
+ \advance\@dtl@numgrpsepcount by 1\relax
+ \ifx.#2\relax
+ \edef\@dtl@intpart{\@dtl@intpart#1}%
+ \let\@dtl@localeintnext=\@gobble
+ \else
+ \ifnum\@dtl@numgrpsepcount=3\relax
+ \edef\@dtl@intpart{\@dtl@intpart#1\@dtl@numbergroupchar}%
+ \@dtl@numgrpsepcount=0\relax
+ \else
+ \ifnum\@dtl@numgrpsepcount>3\relax
+ \@dtl@numgrpsepcount=0\relax
+ \fi
+ \edef\@dtl@intpart{\@dtl@intpart#1}%
+ \fi
+ \let\@dtl@localeintnext=\@dtl@decimal@to@localeint
+ \fi
+ \@dtl@localeintnext#2\relax
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@decimaltolocalefrac}
+% Convert the fractional part (store in \cs{@dtl@fracpart}).
+%\changes{2.22}{2014-06-10}{removed \cs{@dtl@choptrailingzeroes}
+% and added \cs{@dtl@chopexcessfrac}}%
+%\cs{@dtl@choptrailingzeroes} was originally used, but this
+%interfered with \cs{dtlround}. Removing
+%\cs{@dtl@choptrailingzeroes} caused a `Number too big' error,
+% so any fractional part over 2147483647 needs to be trimmed.
+% Unfortunately \verb|\ifnum#1>2147483647| also causes the
+% `Number too big' error, so count the digits, and if the digit
+% count exceeds 9, trim the excess.
+% \begin{macrocode}
+\def\@dtl@decimaltolocalefrac#1.\relax{%
+ \count@=0\relax
+ \@dtl@digitcount#1\relax
+ \ifnum\count@>9\relax
+ \@dtl@chopexcessfrac#1000000000\@nil
+ \else
+ \def\@dtl@fracpart{#1}%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@chopexcessfrac}
+% Chop fractional part to just 9 digits.
+%\changes{2.22}{2014-06-10}{new}
+% \begin{macrocode}
+\newcommand*{\@dtl@chopexcessfrac}[9]{%
+ \def\@dtl@fracpart{#1#2#3#4#5#6#7#8#9}%
+ \@dtl@gobbletonil
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@digitcount}
+% Counts the number of digits in \#1.
+%\changes{2.22}{2014-06-10}{new}
+% \begin{macrocode}
+\newcommand*{\@dtl@digitcount}[1]{%
+ \ifx\relax#1\relax
+ \let\@dtl@digitcountnext\relax
+ \else
+ \advance\count@ by \@ne
+ \let\@dtl@digitcountnext\@dtl@digitcount
+ \fi
+ \@dtl@digitcountnext
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLdecimaltocurrency}
+%\begin{definition}
+% \cs{DTLdecimaltocurrency}\marg{number}\marg{cmd}
+%\end{definition}
+% This converts a decimal number into the locale
+% dependent currency format. Stores result in \meta{cmd} which must be
+% a control sequence.
+% \begin{macrocode}
+\newcommand*{\DTLdecimaltocurrency}[2]{%
+ \edef\@dtl@tmpdtl{#1}%
+ \expandafter\@dtl@decimaltolocale\@dtl@tmpdtl.\relax
+ \dtl@truncatedecimal\@dtl@tmpdtl
+ \@dtl@tmpcount=\@dtl@tmpdtl\relax
+ \expandafter\@dtl@toks\expandafter{\@dtl@currency}%
+ \dtlifnumeq{\@dtl@fracpart}{0}%
+ {%
+ \ifnum\@dtl@tmpcount<0\relax
+ \@dtl@tmpcount = -\@dtl@tmpcount\relax
+ \edef#2{-\the\@dtl@toks\the\@dtl@tmpcount\@dtl@decimal00}%
+ \else
+ \edef#2{\the\@dtl@toks\@dtl@intpart\@dtl@decimal00}%
+ \fi
+ }%
+ {%
+ \ifnum\@dtl@tmpcount<0\relax
+ \@dtl@tmpcount = -\@dtl@tmpcount\relax
+ \ifnum\@dtl@fracpart<10\relax
+ \edef#2{%
+ -\the\@dtl@toks\number\@dtl@tmpcount
+ \@dtl@decimal\@dtl@fracpart0%
+ }%
+ \else
+ \edef#2{%
+ -\the\@dtl@toks\number\@dtl@tmpcount
+ \@dtl@decimal\@dtl@fracpart
+ }%
+ \fi
+ \else
+ \ifnum\@dtl@fracpart<10\relax
+ \edef#2{\the\@dtl@toks\@dtl@intpart\@dtl@decimal\@dtl@fracpart0}%
+ \else
+ \edef#2{\the\@dtl@toks\@dtl@intpart\@dtl@decimal\@dtl@fracpart}%
+ \fi
+ \fi
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+% Set the defaults:
+% \begin{macrocode}
+\@dtl@construct@getnums
+\expandafter\@dtl@construct@stripnumgrpchar\expandafter
+ {\@dtl@numbergroupchar}
+% \end{macrocode}
+%
+%\subsection{Currencies}
+%\begin{macro}{\@dtl@currencies}
+% \cs{@dtl@currencies} stores all known currencies.
+% \begin{macrocode}
+\newcommand*{\@dtl@currencies}{\$,\pounds}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLnewcurrencysymbol}
+%\begin{definition}
+% \cs{DTLaddcurrency}\marg{symbol}
+%\end{definition}
+% Adds \meta{symbol} to the list of known currencies
+% \begin{macrocode}
+\newcommand*{\DTLnewcurrencysymbol}[1]{%
+ \expandafter\toks@\expandafter{\@dtl@currencies}%
+ \@dtl@toks{#1}%
+ \edef\@dtl@currencies{\the\@dtl@toks,\the\toks@}%
+}
+% \end{macrocode}
+%\end{macro}
+% If any of the following currency commands have been defined,
+% add them to the list:
+% \begin{macrocode}
+\AtBeginDocument{%
+ \@ifundefined{texteuro}{}{\DTLnewcurrencysymbol{\texteuro}}%
+ \@ifundefined{textdollar}{}{\DTLnewcurrencysymbol{\textdollar}}%
+ \@ifundefined{textstirling}{}{\DTLnewcurrencysymbol{\textstirling}}%
+ \@ifundefined{textyen}{}{\DTLnewcurrencysymbol{\textyen}}%
+ \@ifundefined{textwon}{}{\DTLnewcurrencysymbol{\textwon}}%
+ \@ifundefined{textcurrency}{}{\DTLnewcurrencysymbol{\textcurrency}}%
+ \@ifundefined{euro}{}{\DTLnewcurrencysymbol{\euro}}%
+ \@ifundefined{yen}{}{\DTLnewcurrencysymbol{\yen}}%
+}
+% \end{macrocode}
+%\begin{macro}{\@dtl@standardize@currency}
+%\begin{definition}
+%\cs{@dtl@standardize@currency}\marg{cmd}
+%\end{definition}
+% Substitutes the first currency symbol found in \meta{cmd}
+% with "\$". This is used when testing text to determine
+% if it is currency. The original currency symbol is stored
+% in \cs{@dtl@org@currency}, so that it can be replaced later.
+% If no currency symbol is found, \cs{@dtl@org@currency} will
+% be empty.
+% \begin{macrocode}
+\newcommand{\@dtl@standardize@currency}[1]{%
+ \def\@dtl@org@currency{}%
+ \@for\@dtl@thiscurrency:=\@dtl@currencies\do{%
+ \expandafter\toks@\expandafter{\@dtl@thiscurrency}%
+ \edef\@dtl@dosubs{\noexpand\DTLsubstitute{\noexpand#1}%
+ {\the\toks@}{\noexpand\$}}%
+ \@dtl@dosubs
+ \ifdefempty{\@dtl@replaced}%
+ {%
+ }%
+ {%
+ \let\@dtl@org@currency=\@dtl@replaced
+ \@endfortrue
+ }%
+ }%
+ \@endforfalse
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@currency}
+%\cs{@dtl@currency} is set by \cs{DTLlocaltodecimal} and
+%\cs{@dtl@checknumerical}. It is used by \cs{DTLdecimaltocurrency}.
+% Set to "\$" by default.
+% \begin{macrocode}
+\newcommand*{\@dtl@currency}{\$}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLsetdefaultcurrency}
+%\cs{DTLsetdefaultcurrency}\marg{symbol} sets the default currency.
+% \begin{macrocode}
+\newcommand*{\DTLsetdefaultcurrency}[1]{%
+ \renewcommand*{\@dtl@currency}{#1}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+% \section{Floating Point Arithmetic}
+% The commands defined in this section all use the equivalent
+% commands provided by the \sty{fp} or \sty{pgfmath} packages, but
+% first convert the decimal number into the required format.
+%
+%\begin{macro}{\DTLadd}
+%\begin{definition}
+% \cs{DTLadd}\marg{cmd}\marg{num1}\marg{num2}
+%\end{definition}
+% Sets \meta{cmd} = \meta{num1} + \meta{num2}
+% \begin{macrocode}
+\newcommand*{\DTLadd}[3]{%
+ \DTLconverttodecimal{#2}{\@dtl@numi}%
+ \DTLconverttodecimal{#3}{\@dtl@numii}%
+ \dtladd{\@dtl@tmp}{\@dtl@numi}{\@dtl@numii}%
+ \ifdefempty{\@dtl@replaced}%
+ {%
+ \DTLdecimaltolocale{\@dtl@tmp}{#1}%
+ }%
+ {%
+ \DTLdecimaltocurrency{\@dtl@tmp}{#1}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLgadd}
+% Global version
+% \begin{macrocode}
+\newcommand*{\DTLgadd}[3]{%
+ \DTLadd{\@dtl@tmpii}{#2}{#3}%
+ \global\let#1=\@dtl@tmpii
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLaddall}
+%\begin{definition}
+%\cs{DTLaddall}\marg{cmd}\marg{num list}
+%\end{definition}
+% Sums all the values in \meta{num list} and stores in
+% \meta{cmd} which must be a control sequence.
+%\changes{1.01}{2007 Aug 17}{removed extraneous space}
+% \begin{macrocode}
+\newcommand*{\DTLaddall}[2]{%
+ \def\@dtl@sum{0}%
+ \@for\dtl@thisval:=#2\do{%
+ \expandafter\DTLconverttodecimal\expandafter{\dtl@thisval}{\@dtl@num}%
+ \dtladd{\@dtl@sum}{\@dtl@sum}{\@dtl@num}%
+ }%
+ \ifdefempty{\@dtl@replaced}%
+ {%
+ \DTLdecimaltolocale{\@dtl@sum}{#1}%
+ }%
+ {%
+ \DTLdecimaltocurrency{\@dtl@sum}{#1}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLgaddall}
+%\begin{definition}
+%\cs{DTLgaddall}\marg{cmd}\marg{num list}
+%\end{definition}
+% Global version
+% \begin{macrocode}
+\newcommand*{\DTLgaddall}[2]{%
+ \DTLaddall{\@dtl@tmpi}{#2}%
+ \global\let#1=\@dtl@tmpi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLsub}
+%\begin{definition}
+% \cs{DTLsub}\marg{cmd}\marg{num1}\marg{num2}
+%\end{definition}
+% Sets \meta{cmd} = \meta{num1} - \meta{num2}
+% \begin{macrocode}
+\newcommand*{\DTLsub}[3]{%
+ \DTLconverttodecimal{#2}{\@dtl@numi}%
+ \DTLconverttodecimal{#3}{\@dtl@numii}%
+ \dtlsub{\@dtl@tmp}{\@dtl@numi}{\@dtl@numii}%
+ \ifdefempty{\@dtl@replaced}%
+ {%
+ \DTLdecimaltolocale{\@dtl@tmp}{#1}%
+ }%
+ {%
+ \DTLdecimaltocurrency{\@dtl@tmp}{#1}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLgsub}
+% Global version
+% \begin{macrocode}
+\newcommand*{\DTLgsub}[3]{%
+ \DTLsub{\@dtl@tmpii}{#2}{#3}%
+ \global\let#1=\@dtl@tmpii
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLmul}
+%\begin{definition}
+% \cs{DTLmul}\marg{cmd}\marg{num1}\marg{num2}
+%\end{definition}
+% Sets \meta{cmd} = \meta{num1} $\times$ \meta{num2}
+% \begin{macrocode}
+\newcommand*{\DTLmul}[3]{%
+ \let\@dtl@thisreplaced=\@empty
+ \DTLconverttodecimal{#2}{\@dtl@numi}%
+ \ifdefempty{\@dtl@replaced}%
+ {%
+ }%
+ {%
+ \let\@dtl@thisreplaced=\@dtl@replaced
+ }%
+ \DTLconverttodecimal{#3}{\@dtl@numii}%
+ \ifdefempty{\@dtl@replaced}%
+ {%
+ }%
+ {%
+ \let\@dtl@thisreplaced=\@dtl@replaced
+ }%
+ \dtlmul{\@dtl@tmp}{\@dtl@numi}{\@dtl@numii}%
+ \ifdefempty{\@dtl@thisreplaced}%
+ {%
+ \DTLdecimaltolocale{\@dtl@tmp}{#1}%
+ }%
+ {%
+ \DTLdecimaltocurrency{\@dtl@tmp}{#1}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLgmul}
+% Global version
+% \begin{macrocode}
+\newcommand*{\DTLgmul}[3]{%
+ \DTLmul{\@dtl@tmpii}{#2}{#3}%
+ \global\let#1=\@dtl@tmpii
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLdiv}
+%\begin{definition}
+% \cs{DTLdiv}\marg{cmd}\marg{num1}\marg{num2}
+%\end{definition}
+% Sets \meta{cmd} = \meta{num1} / \meta{num2}
+% \begin{macrocode}
+\newcommand*{\DTLdiv}[3]{%
+ \let\@dtl@thisreplaced=\@empty
+ \DTLconverttodecimal{#2}{\@dtl@numi}%
+ \ifdefempty{\@dtl@replaced}%
+ {%
+ }%
+ {%
+ \let\@dtl@thisreplaced=\@dtl@replaced
+ }%
+ \DTLconverttodecimal{#3}{\@dtl@numii}%
+ \dtldiv{\@dtl@tmp}{\@dtl@numi}{\@dtl@numii}%
+ \ifdefempty{\@dtl@thisreplaced}%
+ {%
+ \DTLdecimaltolocale{\@dtl@tmp}{#1}%
+ }%
+ {%
+ \ifdefequal{\@dtl@thisreplaced}{\@dtl@replaced}%
+ {%
+ \DTLdecimaltolocale{\@dtl@tmp}{#1}%
+ }%
+ {%
+ \DTLdecimaltocurrency{\@dtl@tmp}{#1}%
+ }%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLgdiv}
+% Global version
+% \begin{macrocode}
+\newcommand*{\DTLgdiv}[3]{%
+ \DTLdiv{\@dtl@tmpii}{#2}{#3}%
+ \global\let#1=\@dtl@tmpii
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLabs}
+%\begin{definition}
+% \cs{DTLabs}\marg{cmd}\marg{num}
+%\end{definition}
+% Sets \meta{cmd} = abs(\meta{num})
+% \begin{macrocode}
+\newcommand*{\DTLabs}[2]{%
+ \DTLconverttodecimal{#2}{\@dtl@numi}%
+ \dtlabs{\@dtl@tmp}{\@dtl@numi}%
+ \ifdefempty{\@dtl@replaced}%
+ {%
+ \DTLdecimaltolocale{\@dtl@tmp}{#1}%
+ }%
+ {%
+ \DTLdecimaltocurrency{\@dtl@tmp}{#1}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLgabs}
+% Global version
+% \begin{macrocode}
+\newcommand*{\DTLgabs}[2]{%
+ \DTLabs{\@dtl@tmpii}{#2}%
+ \global\let#1=\@dtl@tmpii
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLneg}
+%\begin{definition}
+% \cs{DTLneg}\marg{cmd}\marg{num}
+%\end{definition}
+% Sets \meta{cmd} = -\meta{num}
+% \begin{macrocode}
+\newcommand*{\DTLneg}[2]{%
+ \DTLconverttodecimal{#2}{\@dtl@numi}%
+ \dtlneg{\@dtl@tmp}{\@dtl@numi}%
+ \ifdefempty{\@dtl@replaced}%
+ {%
+ \DTLdecimaltolocale{\@dtl@tmp}{#1}%
+ }%
+ {%
+ \DTLdecimaltocurrency{\@dtl@tmp}{#1}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLgneg}
+% Global version
+% \begin{macrocode}
+\newcommand*{\DTLgneg}[2]{%
+ \DTLneg{\@dtl@tmpii}{#2}%
+ \global\let#1=\@dtl@tmpii
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLsqrt}
+%\begin{definition}
+% \cs{DTLsqrt}\marg{cmd}\marg{num}
+%\end{definition}
+% Sets \meta{cmd} = sqrt(\meta{num})
+% \begin{macrocode}
+\newcommand*{\DTLsqrt}[2]{%
+ \DTLconverttodecimal{#2}{\@dtl@numi}%
+ \dtlroot{\@dtl@tmpi}{\@dtl@numi}{2}%
+ \ifdefempty{\@dtl@replaced}%
+ {%
+ \DTLdecimaltolocale{\@dtl@tmpi}{#1}%
+ }%
+ {%
+ \DTLdecimaltocurrency{\@dtl@tmpi}{#1}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLgsqrt}
+% Global version
+% \begin{macrocode}
+\newcommand*{\DTLgsqrt}[2]{%
+\DTLsqrt{\@dtl@tmpii}{#2}%
+\global\let#1=\@dtl@tmpii
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLmin}
+%\begin{definition}
+% \cs{DTLmin}\marg{cmd}\marg{num1}\marg{num2}
+%\end{definition}
+% Sets \meta{cmd} = min(\meta{num1}, \meta{num2})
+% \begin{macrocode}
+\newcommand*{\DTLmin}[3]{%
+ \DTLconverttodecimal{#2}{\@dtl@numi}%
+ \DTLconverttodecimal{#3}{\@dtl@numii}%
+ \dtlifnumlt{\@dtl@numi}{\@dtl@numii}%
+ {%
+ \dtl@ifsingle{#2}%
+ {\let#1=#2}%
+ {\def#1{#2}}%
+ }%
+ {%
+ \dtl@ifsingle{#3}%
+ {\let#1=#3}%
+ {\def#1{#3}}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLgmin}
+% Global version
+% \begin{macrocode}
+\newcommand*{\DTLgmin}[3]{%
+ \DTLmin{\@dtl@tmpii}{#2}{#3}%
+ \global\let#1=\@dtl@tmpii
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLminall}
+%\begin{definition}
+%\cs{DTLminall}\marg{cmd}\marg{num list}
+%\end{definition}
+% Finds the minimum value in \meta{num list} and stores in
+% \meta{cmd} which must be a control sequence.
+%\changes{1.01}{2007 Aug 17}{removed extraneous space}
+% \begin{macrocode}
+\newcommand*{\DTLminall}[2]{%
+ \let\@dtl@min=\@empty
+ \@for\dtl@thisval:=#2\do{%
+ \expandafter\DTLconverttodecimal\expandafter{\dtl@thisval}{\@dtl@num}%
+ \ifdefempty{\@dtl@min}%
+ {%
+ \let\@dtl@min=\@dtl@num
+ }%
+ {%
+ \dtlmin{\@dtl@min}{\@dtl@min}{\@dtl@num}%
+ }%
+ }%
+ \ifdefempty{\@dtl@replaced}%
+ {%
+ \DTLdecimaltolocale{\@dtl@min}{#1}%
+ }%
+ {%
+ \DTLdecimaltocurrency{\@dtl@min}{#1}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLgminall}
+%\begin{definition}
+%\cs{DTLgminall}\marg{cmd}\marg{num list}
+%\end{definition}
+% Global version
+% \begin{macrocode}
+\newcommand*{\DTLgminall}[2]{%
+ \DTLminall{\@dtl@tmpi}{#2}%
+ \global\let#1=\@dtl@tmpi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLmax}
+%\begin{definition}
+% \cs{DTLmax}\marg{cmd}\marg{num1}\marg{num2}
+%\end{definition}
+% Sets \meta{cmd} = max(\meta{num1}, \meta{num2})
+% \begin{macrocode}
+\newcommand*{\DTLmax}[3]{%
+ \DTLconverttodecimal{#2}{\@dtl@numi}%
+ \DTLconverttodecimal{#3}{\@dtl@numii}%
+ \dtlmax{\@dtl@tmp}{\@dtl@numi}{\@dtl@numii}%
+ \dtlifnumgt{\@dtl@numi}{\@dtl@numii}%
+ {%
+ \dtl@ifsingle{#2}%
+ {\let#1=#2}%
+ {\def#1{#2}}%
+ }%
+ {%
+ \dtl@ifsingle{#3}%
+ {\let#1=#3}%
+ {\def#1{#3}}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLgmax}
+% Global version
+% \begin{macrocode}
+\newcommand*{\DTLgmax}[3]{%
+ \DTLmax{\@dtl@tmpii}{#2}{#3}%
+ \global\let#1=\@dtl@tmpii
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLmaxall}
+%\begin{definition}
+%\cs{DTLmaxall}\marg{cmd}\marg{num list}
+%\end{definition}
+% Finds the maximum value in \meta{num list} and stores in
+% \meta{cmd} which must be a control sequence.
+%\changes{1.01}{2007 Aug 17}{removed extraneous space}
+% \begin{macrocode}
+\newcommand*{\DTLmaxall}[2]{%
+ \let\@dtl@max=\@empty
+ \@for\dtl@thisval:=#2\do{%
+ \expandafter\DTLconverttodecimal\expandafter{\dtl@thisval}{\@dtl@num}%
+ \ifdefempty{\@dtl@max}%
+ {%
+ \let\@dtl@max\@dtl@num
+ }%
+ {%
+ \dtlmax{\@dtl@max}{\@dtl@max}{\@dtl@num}%
+ }%
+ }%
+ \ifdefempty{\@dtl@replaced}%
+ {%
+ \DTLdecimaltolocale{\@dtl@max}{#1}%
+ }%
+ {%
+ \DTLdecimaltocurrency{\@dtl@max}{#1}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLgmaxall}
+%\begin{definition}
+%\cs{DTLgmaxall}\marg{cmd}\marg{num list}
+%\end{definition}
+% Global version
+% \begin{macrocode}
+\newcommand*{\DTLgmaxall}[2]{%
+\DTLmaxall{\@dtl@tmpi}{#2}%
+\global\let#1=\@dtl@tmpi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLmeanforall}
+%\begin{definition}
+%\cs{DTLmeanforall}\marg{cmd}\marg{num list}
+%\end{definition}
+% Computes the arithmetic mean of all the values in \meta{num list}
+% and stores in \meta{cmd} which must be a control sequence.
+%\changes{1.01}{2007 Aug 17}{removed extraneous space}
+% \begin{macrocode}
+\newcommand*{\DTLmeanforall}[2]{%
+ \def\@dtl@mean{0}%
+ \def\@dtl@n{0}%
+ \@for\dtl@thisval:=#2\do{%
+ \expandafter\DTLconverttodecimal\expandafter{\dtl@thisval}{\@dtl@num}%
+ \dtladd{\@dtl@mean}{\@dtl@mean}{\@dtl@num}%
+ \dtladd{\@dtl@n}{\@dtl@n}{1}%
+ }%
+ \dtldiv{\@dtl@mean}{\@dtl@mean}{\@dtl@n}%
+ \ifdefempty{\@dtl@replaced}%
+ {%
+ \DTLdecimaltolocale{\@dtl@mean}{#1}%
+ }%
+ {%
+ \DTLdecimaltocurrency{\@dtl@mean}{#1}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLgmeanforall}
+%\begin{definition}
+%\cs{DTLgmeanforall}\marg{cmd}\marg{num list}
+%\end{definition}
+% Global version
+% \begin{macrocode}
+\newcommand*{\DTLgmeanforall}[2]{%
+ \DTLmeanforall{\@dtl@tmpi}{#2}%
+ \global\let#1=\@dtl@tmpi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLvarianceforall}
+%\begin{definition}
+%\cs{DTLvarianceforall}\marg{cmd}\marg{num list}
+%\end{definition}
+% Computes the variance of all the values in \meta{num list}
+% and stores in \meta{cmd} which must be a control sequence.
+%\changes{1.01}{2007 Aug 17}{fixed bug}
+%\changes{1.01}{2007 Aug 17}{removed extraneous space}
+% \begin{macrocode}
+\newcommand*{\DTLvarianceforall}[2]{%
+ \def\@dtl@mean{0}%
+ \def\@dtl@n{0}%
+ \let\@dtl@decvals=\@empty
+ \@for\dtl@thisval:=#2\do{%
+ \expandafter\DTLconverttodecimal\expandafter{\dtl@thisval}{\@dtl@num}%
+ \ifdefempty{\@dtl@decvals}%
+ {%
+ \let\@dtl@decvals=\@dtl@num
+ }%
+ {%
+ \expandafter\toks@\expandafter{\@dtl@decvals}%
+ \edef\@dtl@decvals{\the\toks@,\@dtl@num}%
+ }%
+ \dtladd{\@dtl@mean}{\@dtl@mean}{\@dtl@num}%
+ \dtladd{\@dtl@n}{\@dtl@n}{1}%
+ }%
+ \dtldiv{\@dtl@mean}{\@dtl@mean}{\@dtl@n}%
+ \def\@dtl@var{0}%
+ \@for\@dtl@num:=\@dtl@decvals\do{%
+ \dtlsub{\@dtl@diff}{\@dtl@num}{\@dtl@mean}%
+ \dtlmul{\@dtl@diff}{\@dtl@diff}{\@dtl@diff}%
+ \dtladd{\@dtl@var}{\@dtl@var}{\@dtl@diff}%
+ }%
+ \dtldiv{\@dtl@var}{\@dtl@var}{\@dtl@n}%
+ \ifdefempty{\@dtl@replaced}%
+ {%
+ \DTLdecimaltolocale{\@dtl@var}{#1}%
+ }%
+ {%
+ \DTLdecimaltocurrency{\@dtl@var}{#1}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLgvarianceforall}
+%\begin{definition}
+%\cs{DTLgvarianceforall}\marg{cmd}\marg{num list}
+%\end{definition}
+% Global version
+% \begin{macrocode}
+\newcommand*{\DTLgvarianceforall}[2]{%
+ \DTLvarianceforall{\@dtl@tmpi}{#2}%
+ \global\let#1=\@dtl@tmpi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLsdforall}
+%\begin{definition}
+%\cs{DTLsdforall}\marg{cmd}\marg{num list}
+%\end{definition}
+% Computes the standard deviation of all the values in \meta{num list}
+% and stores in \meta{cmd} which must be a control sequence.
+%\changes{1.01}{2007 Aug 17}{fixed bug}
+%\changes{1.01}{2007 Aug 17}{removed extraneous space}
+% \begin{macrocode}
+\newcommand*{\DTLsdforall}[2]{%
+ \def\@dtl@mean{0}%
+ \def\@dtl@n{0}%
+ \let\@dtl@decvals=\@empty
+ \@for\dtl@thisval:=#2\do{%
+ \expandafter\DTLconverttodecimal\expandafter{\dtl@thisval}{\@dtl@num}%
+ \ifdefempty{\@dtl@decvals}%
+ {%
+ \let\@dtl@decvals=\@dtl@num
+ }%
+ {%
+ \expandafter\toks@\expandafter{\@dtl@decvals}%
+ \edef\@dtl@decvals{\the\toks@,\@dtl@num}%
+ }%
+ \dtladd{\@dtl@mean}{\@dtl@mean}{\@dtl@num}%
+ \dtladd{\@dtl@n}{\@dtl@n}{1}%
+ }%
+ \dtldiv{\@dtl@mean}{\@dtl@mean}{\@dtl@n}%
+ \def\@dtl@sd{0}%
+ \@for\@dtl@num:=\@dtl@decvals\do{%
+ \dtlsub{\@dtl@diff}{\@dtl@num}{\@dtl@mean}%
+ \dtlmul{\@dtl@diff}{\@dtl@diff}{\@dtl@diff}%
+ \dtladd{\@dtl@sd}{\@dtl@sd}{\@dtl@diff}%
+ }%
+ \dtldiv{\@dtl@sd}{\@dtl@sd}{\@dtl@n}%
+ \dtlroot{\@dtl@sd}{\@dtl@sd}{2}%
+ \ifdefempty{\@dtl@replaced}%
+ {%
+ \DTLdecimaltolocale{\@dtl@sd}{#1}%
+ }%
+ {%
+ \DTLdecimaltocurrency{\@dtl@sd}{#1}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLgsdforall}
+%\begin{definition}
+%\cs{DTLgsdforall}\marg{cmd}\marg{num list}
+%\end{definition}
+% Global version
+% \begin{macrocode}
+\newcommand*{\DTLgsdforall}[2]{%
+ \DTLsdforall{\@dtl@tmpi}{#2}%
+ \global\let#1=\@dtl@tmpi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLround}
+%\begin{definition}
+% \cs{DTLround}\marg{cmd}\marg{num}\marg{num digits}
+%\end{definition}
+% Sets \meta{cmd} to \meta{num} rounded to \meta{num digits}
+% digits after the decimal character.
+% \begin{macrocode}
+\newcommand*{\DTLround}[3]{%
+ \DTLconverttodecimal{#2}{\@dtl@numi}%
+ \dtlround{\@dtl@tmp}{\@dtl@numi}{#3}%
+ \ifdefempty{\@dtl@replaced}%
+ {%
+ \DTLdecimaltolocale{\@dtl@tmp}{#1}%
+ }%
+ {%
+ \DTLdecimaltocurrency{\@dtl@tmp}{#1}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLground}
+% Global version
+% \begin{macrocode}
+\newcommand*{\DTLground}[3]{%
+ \DTLround{\@dtl@tmpii}{#2}{#3}%
+ \global\let#1=\@dtl@tmpii
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLtrunc}
+%\begin{definition}
+% \cs{DTLtrunc}\marg{cmd}\marg{num}\marg{num digits}
+%\end{definition}
+% Sets \meta{cmd} to \meta{num} truncated to \meta{num digits}
+% digits after the decimal character.
+% \begin{macrocode}
+\newcommand*{\DTLtrunc}[3]{%
+ \DTLconverttodecimal{#2}{\@dtl@numi}%
+ \dtltrunc{\@dtl@tmp}{\@dtl@numi}{#3}%
+ \ifdefempty{\@dtl@replaced}%
+ {%
+ \DTLdecimaltolocale{\@dtl@tmp}{#1}%
+ }%
+ {%
+ \DTLdecimaltocurrency{\@dtl@tmp}{#1}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLgtrunc}
+% Global version
+% \begin{macrocode}
+\newcommand*{\DTLgtrunc}[3]{%
+ \DTLtrunc{\@dtl@tmpii}{#2}{#3}%
+ \global\let#1=\@dtl@tmpii
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLclip}
+%\begin{definition}
+% \cs{DTLclip}\marg{cmd}\marg{num}
+%\end{definition}
+% Sets \meta{cmd} to \meta{num} with all unnecessary 0's removed.
+% \begin{macrocode}
+\newcommand*{\DTLclip}[2]{%
+ \DTLconverttodecimal{#2}{\@dtl@numi}%
+ \dtlclip{\@dtl@tmp}{\@dtl@numi}%
+ \ifdefempty{\@dtl@replaced}%
+ {%
+ \DTLdecimaltolocale{\@dtl@tmp}{#1}%
+ }%
+ {%
+ \DTLdecimaltocurrency{\@dtl@tmp}{#1}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLgclip}
+% Global version
+% \begin{macrocode}
+\newcommand*{\DTLgclip}[3]{%
+ \DTLclip{\@dtl@tmpii}{#2}%
+ \global\let#1=\@dtl@tmpii
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\section{String Macros}
+%\begin{macro}{\DTLinitials}
+%\begin{definition}
+%\cs{DTLinitials}\marg{string}
+%\end{definition}
+% Convert a string into initials.
+% (Any "~" character found is first converted into a space.)
+%\changes{1.01}{2007 Aug 17}{now works with unbreakable space symbol}
+%\changes{1.01}{2007 Aug 17}{now uses \cs{DTLinitialhyphen}}
+% \begin{macrocode}
+\newcommand*\DTLinitials[1]{%
+ \def\dtl@initialscmd{}%
+ \dtl@subnobrsp{#1}{\dtl@string}%
+ \DTLsubstituteall{\dtl@string}{~}{ }%
+ \DTLsubstituteall{\dtl@string}{\ }{ }%
+ \DTLsubstituteall{\dtl@string}{\space}{ }%
+ \expandafter\dtl@initials\dtl@string{} \@nil%
+ \dtl@initialscmd
+}%
+% \end{macrocode}
+%\end{macro}
+% The following substitutes "\protect \nobreakspace {}" with
+% a space. (Note that in this case the space following
+% "\nobreakspace" forms part of the command.)
+% \begin{macrocode}
+\edef\dtl@construct@subnobrsp{%
+% \end{macrocode}
+% Define \ics{@dtl@subnobrsp}
+% \begin{macrocode}
+ \noexpand\def\noexpand\@dtl@subnobrsp##1\noexpand\protect
+ \expandafter\noexpand\csname nobreakspace \endcsname ##2{%
+ \noexpand\toks@{##1}%
+ \noexpand\expandafter\noexpand\@dtl@toks\noexpand\expandafter{%
+ \noexpand\@dtl@string}%
+ \noexpand\edef\noexpand\@dtl@string{\noexpand\the\noexpand\@dtl@toks
+ \noexpand\the\noexpand\toks@}%
+ \noexpand\def\noexpand\@dtl@tmp{##2}%
+ \noexpand\ifx\noexpand\@dtl@tmp\noexpand\@nnil
+ \noexpand\let\noexpand\@dtl@subnobrspnext=\noexpand\relax
+ \noexpand\else
+ \noexpand\toks@{ }%
+ \noexpand\expandafter\noexpand\@dtl@toks\noexpand\expandafter{%
+ \noexpand\@dtl@string}%
+ \noexpand\edef\noexpand\@dtl@string{\noexpand\the\noexpand\@dtl@toks
+ \noexpand\the\noexpand\toks@}%
+ \noexpand\let\noexpand\@dtl@subnobrspnext=\noexpand\@dtl@subnobrsp
+ \noexpand\fi
+ \noexpand\@dtl@subnobrspnext
+ }%
+% \end{macrocode}
+% Define \ics{dtl@subnobrsp}
+% \begin{macrocode}
+ \noexpand\def\noexpand\dtl@subnobrsp##1##2{%
+ \noexpand\def\noexpand\@dtl@string{}%
+ \noexpand\@dtl@subnobrsp ##1\noexpand\protect\expandafter\noexpand
+ \csname nobreakspace \endcsname \noexpand\@nil
+ \noexpand\let##2=\noexpand\@dtl@string
+ }%
+}
+\dtl@construct@subnobrsp
+% \end{macrocode}
+%
+%\begin{macro}{\DTLstoreinitials}
+%\begin{definition}
+%\cs{DTLstoreinitials}\marg{string}\marg{cmd}
+%\end{definition}
+% Convert a string into initials and store in \meta{cmd}.
+% (Any "~" character found is first converted into a space.)
+%\changes{1.01}{2007 Aug 17}{now works with unbreakable space symbol}
+%\changes{1.01}{2007 Aug 17}{now uses \cs{DTLinitialhyphen}}
+% \begin{macrocode}
+\newcommand*{\DTLstoreinitials}[2]{%
+ \def\dtl@initialscmd{}%
+ \dtl@subnobrsp{#1}{\dtl@string}%
+ \DTLsubstituteall{\dtl@string}{~}{ }%
+ \DTLsubstituteall{\dtl@string}{\ }{ }%
+ \DTLsubstituteall{\dtl@string}{\space}{ }%
+ \expandafter\dtl@initials\dtl@string{} \@nil
+ \let#2=\dtl@initialscmd
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtl@initials}
+% \begin{macrocode}
+\def\dtl@initials#1#2 #3{%
+ \dtl@ifsingle{#1}%
+ {%
+ \ifcat\noexpand#1\relax\relax
+ \def\@dtl@donextinitials{\@dtl@initials#2 {#3}}%
+ \else
+ \def\@dtl@donextinitials{\@dtl@initials#1#2 {#3}}%
+ \fi
+ }%
+ {%
+ \def\@dtl@donextinitials{\@dtl@initials{#1}#2 {#3}}%
+ }%
+ \@dtl@donextinitials
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@dtl@initials}
+% \begin{macrocode}
+\def\@dtl@initials#1#2 #3{%
+ \dtl@initialshyphen#2-{}\dtl@endhyp
+ \expandafter\@dtl@toks\expandafter{\dtl@initialscmd}%
+ \toks@{#1}%
+ \ifdefempty{\dtl@inithyphen}%
+ {%
+ }%
+ {%
+ \edef\dtl@initialscmd{\the\@dtl@toks\the\toks@}%
+ \expandafter\@dtl@toks\expandafter{\dtl@initialscmd}%
+ \expandafter\toks@\expandafter{\dtl@inithyphen}%
+ }%
+ \def\dtl@tmp{#3}%
+ \ifx\@nnil\dtl@tmp
+ \edef\dtl@initialscmd{\the\@dtl@toks\the\toks@\DTLafterinitials}%
+ \let\dtl@initialsnext=\@gobble
+ \else
+ \edef\dtl@initialscmd{\the\@dtl@toks\the\toks@\DTLbetweeninitials}%
+ \let\dtl@initialsnext=\dtl@initials
+ \fi
+ \dtl@initialsnext{#3}%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtl@initialshyphen}
+% \begin{macrocode}
+\def\dtl@initialshyphen#1-#2#3\dtl@endhyp{%
+ \def\dtl@inithyphen{#2}%
+ \ifdefempty{\dtl@inithyphen}%
+ {%
+ }%
+ {%
+ \edef\dtl@inithyphen{%
+ \DTLafterinitialbeforehyphen\DTLinitialhyphen#2}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLafterinitials}
+% Defines what to do after the final initial.
+% \begin{macrocode}
+\newcommand*{\DTLafterinitials}{.}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLbetweeninitials}
+% Defines what to do between initials.
+% \begin{macrocode}
+\newcommand*{\DTLbetweeninitials}{.}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLafterinitialbeforehyphen}
+% Defines what to do before a hyphen.
+% \begin{macrocode}
+\newcommand*{\DTLafterinitialbeforehyphen}{.}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLinitialhyphen}
+%Defines what to do at the hyphen
+%\changes{1.01}{2007 Aug 17}{new}
+% \begin{macrocode}
+\newcommand*{\DTLinitialhyphen}{-}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLifAllUpperCase}
+%\begin{definition}
+%\cs{DTLifAllUpperCase}\marg{string}\marg{true part}\marg{false part}
+%\end{definition}
+% If \meta{string} only contains uppercase characters do \meta{true
+%part}, otherwise do \meta{false part}.
+% \begin{macrocode}
+\newcommand*{\DTLifAllUpperCase}[3]{%
+ \protected@edef\dtl@tuc{#1}%
+ \expandafter\dtl@testifuppercase\dtl@tuc\@nil\relax
+ \if@dtl@condition#2\else#3\fi
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtl@testifalluppercase}
+% \begin{macrocode}
+\def\dtl@testifuppercase#1#2{%
+ \def\dtl@argi{#1}%
+ \def\dtl@argii{#2}%
+ \def\dtl@tc@rest{}%
+ \ifx\dtl@argi\@nnil
+ \let\dtl@testifuppernext=\@nnil
+ \else
+ \ifx#1\protect
+ \let\dtl@testifuppernext=\dtl@testifuppercase
+ \else
+ \ifx\uppercase#1\relax
+ \@dtl@conditiontrue
+ \def\dtl@tc@rest{}%
+ \let\dtl@testifuppernext=\relax
+ \else
+ \edef\dtl@tc@arg{\string#1}%
+ \expandafter\dtl@test@ifuppercase\dtl@tc@arg\end
+ \ifx\dtl@argii\@nnil
+ \let\dtl@testifuppernext=\@dtl@gobbletonil
+ \fi
+ \fi
+ \fi
+ \fi
+ \ifx\dtl@testifuppernext\relax
+ \edef\dtl@dotestifuppernext{%
+ \noexpand\dtl@testifuppercase}%
+ \else
+ \ifx\dtl@testifuppernext\@nnil
+ \edef\dtl@dotestifuppernext{#2}%
+ \else
+ \expandafter\toks@\expandafter{\dtl@tc@rest}%
+ \@dtl@toks{#2}%
+ \edef\dtl@dotestifuppernext{%
+ \noexpand\dtl@testifuppernext\the\toks@\the\@dtl@toks}%
+ \fi
+ \fi
+ \dtl@dotestifuppernext
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtl@test@ifalluppercase}
+% \begin{macrocode}
+\def\dtl@test@ifuppercase#1#2\end{%
+ \def\dtl@tc@rest{#2}%
+ \IfSubStringInString{\string\MakeUppercase}{#1#2}%
+ {%
+ \@dtl@conditiontrue
+ \def\dtl@tc@rest{}%
+ \let\dtl@testifuppernext=\relax
+ }%
+ {%
+ \IfSubStringInString{\string\MakeTextUppercase}{#1#2}%
+ {%
+ \@dtl@conditiontrue
+ \def\dtl@tc@rest{}%
+ \let\dtl@testifuppernext=\relax
+ }%
+ {%
+ \edef\dtl@uccode{\the\uccode`#1}%
+ \edef\dtl@code{\number`#1}%
+ \ifnum\dtl@code=\dtl@uccode\relax
+ \@dtl@conditiontrue
+ \let\dtl@testifuppernext=\dtl@testifuppercase
+ \else
+ \ifnum\dtl@uccode=0\relax
+ \@dtl@conditiontrue
+ \let\dtl@testifuppernext=\dtl@testifuppercase
+ \else
+ \@dtl@conditionfalse
+ \let\dtl@testifuppernext=\@dtl@gobbletonil
+ \fi
+ \fi
+ }%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLifAllLowerCase}
+%\begin{definition}
+%\cs{DTLifAllLowerCase}\marg{string}\marg{true part}\marg{false part}
+%\end{definition}
+% If \meta{string} only contains lowercase characters do \meta{true
+%part}, otherwise do \meta{false part}.
+% \begin{macrocode}
+\newcommand*{\DTLifAllLowerCase}[3]{%
+ \protected@edef\dtl@tlc{#1}%
+ \expandafter\dtl@testiflowercase\dtl@tlc\@nil\relax
+ \if@dtl@condition#2\else#3\fi
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtl@testifalllowercase}
+% \begin{macrocode}
+\def\dtl@testiflowercase#1#2{%
+ \def\dtl@argi{#1}%
+ \def\dtl@argii{#2}%
+ \ifx\dtl@argi\@nnil
+ \let\dtl@testiflowernext=\@nnil
+ \else
+ \ifx#1\protect
+ \let\dtl@testiflowernext=\dtl@testiflowercase
+ \else
+ \ifx\lowercase#1\relax
+ \@dtl@conditiontrue
+ \def\dtl@tc@rest{}%
+ \let\dtl@testiflowernext=\relax
+ \else
+ \edef\dtl@tc@arg{\string#1}%
+ \expandafter\dtl@test@iflowercase\dtl@tc@arg\end
+ \ifx\dtl@argii\@nnil
+ \let\dtl@testiflowernext=\@dtl@gobbletonil
+ \fi
+ \fi
+ \fi
+ \fi
+ \ifx\dtl@testiflowernext\relax
+ \edef\dtl@dotestiflowernext{%
+ \noexpand\dtl@testiflowercase}%
+ \else
+ \ifx\dtl@testiflowernext\@nnil
+ \edef\dtl@dotestiflowernext{#2}%
+ \else
+ \expandafter\toks@\expandafter{\dtl@tc@rest}%
+ \@dtl@toks{#2}%
+ \edef\dtl@dotestiflowernext{%
+ \noexpand\dtl@testiflowernext\the\toks@\the\@dtl@toks}%
+ \fi
+ \fi
+ \dtl@dotestiflowernext
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtl@test@ifalllowercase}
+% \begin{macrocode}
+\def\dtl@test@iflowercase#1#2\end{%
+ \def\dtl@tc@rest{#2}%
+ \IfSubStringInString{\string\MakeLowercase}{#1#2}%
+ {%
+ \@dtl@conditiontrue
+ \def\dtl@tc@rest{}%
+ \let\dtl@testiflowernext=\relax
+ }%
+ {%
+ \IfSubStringInString{\string\MakeTextLowercase}{#1#2}%
+ {%
+ \@dtl@conditiontrue
+ \def\dtl@tc@rest{}%
+ \let\dtl@testiflowernext=\relax
+ }%
+ {%
+ \edef\dtl@lccode{\the\lccode`#1}%
+ \edef\dtl@code{\number`#1}%
+ \ifnum\dtl@code=\dtl@lccode\relax
+ \@dtl@conditiontrue
+ \let\dtl@testiflowernext=\dtl@testiflowercase
+ \else
+ \ifnum\dtl@lccode=0\relax
+ \@dtl@conditiontrue
+ \let\dtl@testiflowernext=\dtl@testiflowercase
+ \else
+ \@dtl@conditionfalse
+ \let\dtl@testiflowernext=\@dtl@gobbletonil
+ \fi
+ \fi
+ }%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLsubstitute}
+%\begin{definition}
+%\cs{DTLsubstitute}\marg{cmd}\marg{original}\marg{replacement}
+%\end{definition}
+% Substitutes first occurrence of \meta{original} with
+% \marg{replacement} within the string given by \meta{cmd}
+% \begin{macrocode}
+\newcommand{\DTLsubstitute}[3]{%
+ \expandafter\DTLsplitstring\expandafter
+ {#1}{#2}{\@dtl@beforepart}{\@dtl@afterpart}%
+ \ifdefempty{\@dtl@replaced}%
+ {%
+ }%
+ {%
+ \def#1{}%
+ \expandafter\@dtl@toks\expandafter{\@dtl@beforepart}%
+ \expandafter\toks@\expandafter{#1}%
+ \protected@edef#1{\the\toks@\the\@dtl@toks#3}%
+ \expandafter\@dtl@toks\expandafter{\@dtl@afterpart}%
+ \expandafter\toks@\expandafter{#1}%
+ \edef#1{\the\toks@\the\@dtl@toks}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLsplitstring}
+%\begin{definition}
+%\cs{DTLsplitstring}\marg{string}\marg{split text}\marg{before
+%cmd}\marg{after cmd}
+%\end{definition}
+% Splits string at \meta{split text} stores the pre split text
+% in \meta{before cmd} and the post split text in \meta{after cmd}.
+%\changes{1.01}{2007 Aug 17}{new}
+% \begin{macrocode}
+\newcommand*{\DTLsplitstring}[4]{%
+ \def\dtl@splitstr##1#2##2\@nil{%
+ \def#3{##1}%
+ \def#4{##2}%
+ \ifdefempty{#4}%
+ {%
+ \let\@dtl@replaced=\@empty
+ }%
+ {%
+ \def\@dtl@replaced{#2}%
+ \dtl@split@str##2\@nil
+ }%
+ }%
+ \def\dtl@split@str##1#2\@nil{%
+ \def#4{##1}}%
+ \dtl@splitstr#1#2\@nil
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLsubstituteall}
+%\begin{definition}
+%\cs{DTLsubstituteall}\marg{cmd}\marg{original}\marg{replacement}
+%\end{definition}
+% Substitutes all occurrences of \meta{original} with
+% \marg{replacement} within the string given by \meta{cmd}
+%\changes{1.01}{2007 Aug 17}{fixed bug caused when certain commands
+% occur in the string}
+%\changes{2.10}{2012-07-18}{added \cs{long}}
+% \begin{macrocode}
+\newcommand{\DTLsubstituteall}[3]{%
+ \def\@dtl@splitsubstr{}%
+ \let\@dtl@afterpart=#1\relax
+ \@dtl@dosubstitute{#2}{#3}%
+ \expandafter\toks@\expandafter{\@dtl@splitsubstr}%
+ \expandafter\@dtl@toks\expandafter{\@dtl@afterpart}%
+ \long\edef#1{\the\toks@\the\@dtl@toks}%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@dtl@dosubstitute}
+% Recursive substitution macro.
+% \begin{macrocode}
+\def\@dtl@dosubstitute#1#2{%
+ \expandafter\DTLsplitstring\expandafter
+ {\@dtl@afterpart}{#1}{\@dtl@beforepart}{\@dtl@afterpart}%
+ \expandafter\toks@\expandafter{\@dtl@splitsubstr}%
+ \expandafter\@dtl@toks\expandafter{\@dtl@beforepart}%
+ \edef\@dtl@splitsubstr{\the\toks@\the\@dtl@toks}%
+ \ifdefempty{\@dtl@replaced}%
+ {%
+ \let\@dtl@dosubstnext=\@dtl@dosubstitutenoop
+ }%
+ {%
+ \expandafter\toks@\expandafter{\@dtl@splitsubstr}%
+ \@dtl@toks{#2}%
+ \edef\@dtl@splitsubstr{\the\toks@\the\@dtl@toks}%
+ \let\@dtl@dosubstnext=\@dtl@dosubstitute
+ }%
+ \@dtl@dosubstnext{#1}{#2}%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@dtl@dosubstitutenoop}
+% Terminates recursive substitution macro.
+% \begin{macrocode}
+\def\@dtl@dosubstitutenoop#1#2{}
+% \end{macrocode}
+%\end{macro}
+%
+%\section{Conditionals}
+%
+%\begin{macro}{\if@dtl@condition}
+% \begin{macrocode}
+\newif\if@dtl@condition
+% \end{macrocode}
+%\end{macro}
+%
+% \subsection{Determining Data Types}
+% The control sequence \cs{@dtl@checknumerical} checks the data
+% type of its argument, and sets \cs{@dtl@datatype} to 0 if
+% the argument is a string, 1 if the argument is an integer
+% or 2 if the argument is a real number. First define
+% \cs{@dtl@datatype}:
+%\begin{macro}{\@dtl@datatype}
+% \begin{macrocode}
+\newcount\@dtl@datatype
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@dtl@checknumerical}
+%\begin{definition}
+%\cs{@dtl@checknumerical}\marg{arg}
+%\end{definition}
+% Checks if \meta{arg} is numerical
+% (includes decimal numbers, but not scientific notation.)
+% Sets \cs{@dtl@datatype}, as described above.
+% \begin{macrocode}
+\newcommand{\@dtl@checknumerical}[1]{%
+ \@dtl@numgrpsepfalse
+ \dtl@ifsingle{#1}%
+ {%
+ \expandafter\toks@\expandafter{#1}%
+ \edef\@dtl@tmp{\the\toks@}%
+ }%
+ {%
+ \def\@dtl@tmp{#1}%
+ }%
+% \end{macrocode}
+%\changes{2.16}{2013-08-16}{Moved empty check}
+% \begin{macrocode}
+ \ifdefempty\@dtl@tmp
+ {%
+ \@dtl@datatype=0\relax
+ }%
+ {%
+ \@dtl@tmpcount=0\relax
+ \@dtl@datatype=0\relax
+ \@dtl@numgrpsepcount=2\relax
+ \@dtl@standardize@currency\@dtl@tmp
+ \ifdefempty{\@dtl@org@currency}%
+ {%
+ }%
+ {%
+ \let\@dtl@currency\@dtl@org@currency
+ }%
+ \expandafter\@dtl@checknumericalstart\@dtl@tmp\@nil\@nil
+ }%
+ \ifnum\@dtl@numgrpsepcount>-1\relax
+ \if@dtl@numgrpsep
+ \ifnum\@dtl@numgrpsepcount=3\relax
+ \else
+ \@dtl@datatype=0\relax
+ \fi
+ \fi
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@dtl@protect}
+%\changes{2.31}{2018-12-07}{new}
+% \begin{macrocode}
+\newcommand*{\@dtl@protect}{\protect}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@dtl@minus}
+%\changes{2.31}{2018-12-07}{new}
+% \begin{macrocode}
+\newcommand*{\@dtl@minus}{-}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@dtl@plus}
+%\changes{2.31}{2018-12-07}{new}
+% \begin{macrocode}
+\newcommand*{\@dtl@plus}{+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@dtl@dollar}
+%\changes{2.31}{2018-12-07}{new}
+% \begin{macrocode}
+\newcommand*{\@dtl@dollar}{\$}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@dtl@checknumericalstart}
+% Check first character for checknumerical process to see if
+% it's a plus or minus sign.
+% \begin{macrocode}
+\def\@dtl@checknumericalstart#1#2\@nil\@nil{%
+ \def\@dtl@tmp{#1}%
+ \ifx\@dtl@tmp\@dtl@protect
+ \@dtl@checknumericalstart#2\@nil\@nil\relax
+ \else
+ \ifx\@dtl@tmp\@dtl@minus
+ \def\@dtl@tmp{#2}%
+ \ifdefempty{\@dtl@tmp}%
+ {%
+ \@dtl@datatype=0\relax
+ }%
+ {%
+ \ifnum\@dtl@datatype=0\relax
+ \@dtl@datatype=1\relax
+ \fi
+ \@dtl@checknumericalstart#2\@nil\@nil\relax
+ }%
+ \else
+ \ifx\@dtl@tmp\@dtl@plus
+ \def\@dtl@tmp{#2}%
+ \ifdefempty{\@dtl@tmp}%
+ {%
+ \@dtl@datatype=0\relax
+ }%
+ {%
+ \ifnum\@dtl@datatype=0\relax
+ \@dtl@datatype=1\relax
+ \fi
+ \@dtl@checknumericalstart#2\@nil\@nil\relax
+ }%
+ \else
+ \def\@dtl@tmp{#1}%
+ \ifx\@dtl@tmp\@dtl@dollar
+ \def\@dtl@tmp{#2}%
+ \ifdefempty{\@dtl@tmp}%
+ {%
+ \@dtl@datatype=0\relax
+ }%
+ {%
+ \@dtl@datatype=3\relax
+ \@dtl@checknumericalstart#2\@nil\@nil\relax
+ }%
+ \else
+ \ifdefempty{\@dtl@tmp}%
+ {%
+ \@dtl@datatype=0\relax
+ }%
+ {%
+ \ifnum\@dtl@datatype=0\relax
+ \@dtl@datatype=1\relax
+ \fi
+ \@dtl@checknumericalloop#1#2\@nil\@nil\relax
+ }%
+ \fi
+ \fi
+ \fi
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\if@dtl@numgrpsep}
+% The conditional \cs{if@dtl@numgrpsep} is set the first time
+% \cs{@dtl@checknumericalloop} encounters the number group
+% separator.
+% \begin{macrocode}
+\newif\if@dtl@numgrpsep
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@dtl@ifDigitOrDecimalSep}
+% Check if argument is either a digit or the decimal separator.
+% Rewrite provided by Bruno Le Floch.
+%\changes{1.01}{2007 Aug 17}{new}
+%\changes{2.10}{2012-07-18}{Rewritten}
+% \begin{macrocode}
+\newcommand*{\@dtl@ifDigitOrDecimalSep}[3]{%
+ \ifnum 9<1\noexpand#1\relax
+ #2%
+ \else
+ \expandafter\ifx\@dtl@decimal#1\relax
+ #2%
+ \else
+ #3%
+ \fi
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@dtl@checknumericalloop}
+% Check numerical loop. This iterates through each character
+% until \cs{@nil} is reached, or invalid character found.
+% Increments \cs{@dtl@tmpcount} each time it encounters a
+% decimal character.\changes{1.01}{2007 Aug 17}{fixed bug caused
+% by commands occuring within text being tested}
+% \begin{macrocode}
+\def\@dtl@checknumericalloop#1#2\@nil{%
+\def\@dtl@tmp{#1}%
+\ifx\@nnil\@dtl@tmp\relax
+ \let\@dtl@chcknumnext=\@dtl@checknumericalnoop%
+\else
+ \@dtl@ifDigitOrDecimalSep{#1}{%
+ \let\@dtl@chcknumnext=\@dtl@checknumericalloop%
+ \expandafter\ifx\@dtl@decimal#1\relax
+ \if@dtl@numgrpsep
+ \ifnum\@dtl@numgrpsepcount=3\relax
+ \@dtl@numgrpsepcount=-1\relax
+ \else
+ \@dtl@datatype=0\relax
+ \let\@dtl@chcknumnext=\@dtl@checknumericalnoop
+ \fi
+ \else
+ \@dtl@numgrpsepcount=-1\relax
+ \fi
+ \else
+ \ifnum\@dtl@numgrpsepcount=-1\relax
+ \else
+ \advance\@dtl@numgrpsepcount by 1\relax
+ \fi
+ \fi
+}{%
+\ifx\@dtl@numbergroupchar\@dtl@tmp\relax
+ \@dtl@numgrpseptrue
+ \ifnum\@dtl@numgrpsepcount<3\relax
+ \@dtl@datatype=0\relax
+ \let\@dtl@chcknumnext=\@dtl@checknumericalnoop
+ \else
+ \@dtl@numgrpsepcount=0\relax
+ \fi
+\else
+ \@dtl@datatype=0\relax
+ \let\@dtl@chcknumnext=\@dtl@checknumericalnoop
+\fi
+}%
+ \ifx\@dtl@decimal\@dtl@tmp\relax
+ \ifnum\@dtl@datatype<3\relax
+ \@dtl@datatype=2\relax
+ \fi
+ \advance\@dtl@tmpcount by 1\relax
+ \ifnum\@dtl@tmpcount>1\relax
+ \@dtl@datatype=0\relax
+ \let\@dtl@chcknumnext=\@dtl@checknumericalnoop%
+ \fi
+ \fi
+\fi
+\@dtl@chcknumnext#2\@nil
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@dtl@checknumericalnoop}
+% End loop
+% \begin{macrocode}
+\def\@dtl@checknumericalnoop#1\@nil#2{}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLifnumerical}
+%\begin{definition}
+%\cs{DTLifnumerical}\marg{arg}\marg{true part}\marg{false part}
+%\end{definition}
+% Tests the first argument, if
+% its numerical do second argument, otherwise do third argument.
+% \begin{macrocode}
+\newcommand{\DTLifnumerical}[3]{%
+\@dtl@checknumerical{#1}%
+\ifnum\@dtl@datatype=0\relax#3\else#2\fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLifreal}
+%\begin{definition}
+%\cs{DTLifreal}\marg{arg}\marg{true part}\marg{false part}
+%\end{definition}
+% Tests the first argument, if
+% it's a real number (not an integer) do second argument,
+% otherwise do third argument.
+% \begin{macrocode}
+\newcommand{\DTLifreal}[3]{%
+ \@dtl@checknumerical{#1}%
+ \ifnum\@dtl@datatype=2\relax #2\else #3\fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLifint}
+%\begin{definition}
+%\cs{DTLifint}\marg{arg}\marg{true part}\marg{false part}
+%\end{definition}
+% Tests the first argument, if
+% it's an integer do second argument,
+% otherwise do third argument.
+% \begin{macrocode}
+\newcommand{\DTLifint}[3]{%
+ \@dtl@checknumerical{#1}%
+ \ifnum\@dtl@datatype=1\relax #2\else #3\fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLifstring}
+%\begin{definition}
+%\cs{DTLifstring}\marg{arg}\marg{true part}\marg{false part}
+%\end{definition}
+% Tests the first argument, if
+% it's a string do second argument,
+% otherwise do third argument.
+% \begin{macrocode}
+\newcommand{\DTLifstring}[3]{%
+ \@dtl@checknumerical{#1}%
+ \ifnum\@dtl@datatype=0\relax #2\else #3\fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLifcurrency}
+%\begin{definition}
+%\cs{DTLifcurrency}\marg{arg}\marg{true part}\marg{false part}
+%\end{definition}
+% Tests the first argument, if
+% it starts with the currency symbol do second argument,
+% otherwise do third argument.
+% \begin{macrocode}
+\newcommand{\DTLifcurrency}[3]{%
+ \@dtl@checknumerical{#1}%
+ \ifnum\@dtl@datatype=3\relax #2\else #3\fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLifcurrencyunit}
+%\begin{definition}
+%\cs{DTLifcurrencyunit}\marg{arg}\marg{symbol}\marg{true
+% part}\marg{false part}
+%\end{definition}
+% This tests if \meta{arg} is currency, and uses the currency unit
+% \meta{symbol}. If true do third argument, otherwise
+% do fourth argument.
+% \begin{macrocode}
+\newcommand*{\DTLifcurrencyunit}[4]{%
+ \@dtl@checknumerical{#1}%
+ \ifnum\@dtl@datatype=3\relax
+ \ifthenelse{\equal{\@dtl@org@currency}{#2}}{#3}{#4}%
+ \else
+ #4%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLifcasedatatype}
+%\begin{definition}
+%\cs{DTLifcasedatatype}\marg{arg}\marg{string case}\marg{int
+%case}\marg{real case}\marg{currency case}
+%\end{definition}
+% If \meta{arg} is a string, do \meta{string case}, if \meta{arg}
+% is an integer do \meta{int case}, if \meta{arg} is a real number,
+% do \meta{real case}, if \meta{arg} is currency, do \meta{curreny
+%case}.
+% \begin{macrocode}
+\newcommand{\DTLifcasedatatype}[5]{%
+ \@dtl@checknumerical{#1}%
+ \ifcase\@dtl@datatype
+ #2% string
+ \or
+ #3% integer
+ \or
+ #4% number
+ \or
+ #5% currency
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@testbothnumerical}
+%\begin{definition}
+%\cs{dtl@testbothnumerical}\marg{arg1}\marg{arg2}
+%\end{definition}
+% Tests if both arguments are numerical. This sets
+% the conditional \cs{if@dtl@condition}.
+% \begin{macrocode}
+\newcommand*{\dtl@testbothnumerical}[2]{%
+ \dtl@ifsingle{#1}{%
+ \edef\@dtl@tmp{#1}}{%
+ \def\@dtl@tmp{#1}}%
+ \expandafter\@dtl@checknumerical\expandafter{\@dtl@tmp}%
+ \edef\@dtl@firsttype{\number\@dtl@datatype}%
+ \dtl@ifsingle{#2}{%
+ \edef\@dtl@tmp{#2}}{%
+ \def\@dtl@tmp{#2}}%
+ \expandafter\@dtl@checknumerical\expandafter{\@dtl@tmp}%
+ \multiply\@dtl@datatype by \@dtl@firsttype\relax
+ \ifnum\@dtl@datatype>0\relax
+ \@dtl@conditiontrue
+ \else
+ \@dtl@conditionfalse
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLifnumlt}
+%\begin{definition}
+%\cs{DTLifnumlt}\marg{num1}\marg{num2}\marg{true part}\marg{false part}
+%\end{definition}
+% Determines if \marg{num1} $<$ \marg{num2}. Both numbers
+% need to have the decimal separator changed to a dot
+% to ensure that it works with \cs{dtlifnumlt}
+%\changes{2.10}{2012-07-18}{changed \cs{FPiflt} to \cs{dtlifnumlt}}
+% \begin{macrocode}
+\newcommand*{\DTLifnumlt}[4]{%
+ \DTLconverttodecimal{#1}{\@dtl@numi}%
+ \DTLconverttodecimal{#2}{\@dtl@numii}%
+ \dtlifnumlt{\@dtl@numi}{\@dtl@numii}%
+ {%
+ #3%
+ }%
+ {%
+ #4%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\label{src:dtlcompare}
+%\begin{macro}{\dtlcompare}
+%\begin{definition}
+%\cs{dtlcompare}\marg{count}\marg{string1}\marg{string2}
+%\end{definition}
+% Compares \meta{string1} and \meta{string2}, and stores the
+% result in the count register \meta{count}. The result may be
+% one of:
+%\par\vskip\baselineskip\noindent
+%\begin{tabular}{rl}
+%-1 & if \meta{string1} is considered to be less than
+%\meta{string2}\\
+%0 & if \meta{string1} is considered to be the same as
+%\meta{string2}\\
+%1 & if \meta{string1} is considered to be greater than
+%\meta{string2}
+%\end{tabular}
+%\par\vskip\baselineskip\noindent
+%Note that for the purposes of string comparisons, commands within
+%\meta{string1} and \meta{string2} are ignored, except for
+%\cs{space} and "~", which are both treated as a space (character
+%code 32.) The following
+%examples assume that the count register \cs{mycount} has been
+%defined as follows:
+%\begin{verbatim}
+%\newcount\mycount
+%\end{verbatim}
+%\newcount\mycount\par\noindent
+%\textbf{Examples:}
+%\begin{enumerate}
+%\item
+%\begin{verbatim}
+%\dtlcompare{\mycount}{Z\"oe}{Zoe}\number\mycount
+%\end{verbatim}
+%produces:
+%\dtlcompare{\mycount}{Z\"oe}{Zoe}\number\mycount, since the accent
+%command is ignored.
+%
+%\item
+%\begin{verbatim}
+%\dtlcompare{\mycount}{foo}{Foo}\number\mycount
+%\end{verbatim}
+%produces:
+%\dtlcompare{\mycount}{foo}{Foo}\number\mycount, since the comparison
+%is case sensitive, however, note the following example:
+%\item
+%\begin{verbatim}
+%\dtlcompare{\mycount}{foo}{\uppercase{f}oo}\number\mycount
+%\end{verbatim}
+%which produces:
+%\dtlcompare{\mycount}{foo}{\uppercase{f}oo}\number\mycount, since
+%the \cs{uppercase} command is ignored.
+%
+%\item You can ``trick'' \cs{dtlcompare} using a command which doesn't
+%output any text. Suppose you have defined the following command:
+%\begin{verbatim}
+%\newcommand*{\noopsort}[1]{}
+%\end{verbatim}
+%\providecommand*{\noopsort}[1]{}
+%then "\noopsort{a}foo" produces the text: \noopsort{a}foo, however
+%the following
+%\begin{verbatim}
+%\dtlcompare{\mycount}{\noopsort{a}foo}{bar}\number\mycount
+%\end{verbatim}
+%produces:
+%\dtlcompare{\mycount}{\noopsort{a}foo}{bar}\number\mycount,
+%since the command \cs{noopsort} is disregarded when the comparison
+%is made, so \cs{dtlcompare} just compares "{a}foo" with "bar", and
+%since "a" is less than "b", the first string is considered to be less
+%than the second string.
+%
+%\item Note that this also means that:
+%\begin{verbatim}
+%\def\mystr{abc}%
+%\dtlcompare{\mycount}{\mystr}{abc}\number\mycount
+%\end{verbatim}
+%produces:
+%\def\mystr{abc}\relax
+%\dtlcompare{\mycount}{\mystr}{abc}\number\mycount, since the command
+%\cs{mystr} is disregarded, which means that \cs{dtlcompare} is
+%comparing an empty string with the string "abc".
+%
+%\item Spaces count in the comparison:
+%\begin{verbatim}
+%\dtlcompare{\mycount}{ab cd}{abcd}\number\mycount
+%\end{verbatim}
+%produces:
+%\dtlcompare{\mycount}{ab cd}{abcd}\number\mycount,
+%but sequential spaces are treated as a single space:
+%\begin{verbatim}
+%\dtlcompare{\mycount}{ab cd}{ab cd}\number\mycount
+%\end{verbatim}
+%produces:
+%\dtlcompare{\mycount}{ab cd}{ab cd}\number\mycount.
+%
+%\item As usual, spaces following command names are ignored, so
+%\begin{verbatim}
+%\dtlcompare{\mycount}{ab\relax cd}{ab cd}\number\mycount
+%\end{verbatim}
+%produces:
+%\dtlcompare{\mycount}{ab\relax cd}{ab cd}\number\mycount.
+%
+%\item "~" and \cs{space} are considered to be the same as a
+% space:
+%\begin{verbatim}
+%\dtlcompare{\mycount}{ab cd}{ab~cd}\number\mycount
+%\end{verbatim}
+%produces:
+%\dtlcompare{\mycount}{ab cd}{ab~cd}\number\mycount.
+%\end{enumerate}
+%\changes{1.01}{2007 Aug 17}{replaces \cs{compare} (no
+% longer using compare.tex)}
+% \begin{macrocode}
+\newcommand*{\dtlcompare}[3]{%
+ \dtl@subnobrsp{#2}{\@dtl@argA}%
+ \dtl@subnobrsp{#3}{\@dtl@argB}%
+ \ifdefempty{\@dtl@argA}%
+ {%
+ \ifdefempty{\@dtl@argB}%
+ {%
+ #1=0\relax
+ }%
+ {%
+ #1=-1\relax
+ }%
+ }%
+ {%
+ \ifdefempty{\@dtl@argB}%
+ {%
+ #1=1\relax
+ }%
+ {%
+ \DTLsubstituteall{\@dtl@argA}{ }{\space }%
+ \DTLsubstituteall{\@dtl@argB}{ }{\space }%
+ \expandafter\dtl@getfirst\@dtl@argA\end@dtl@getfirst
+ \let\dtl@firstA=\dtl@first
+ \let\dtl@restA=\dtl@rest
+ \expandafter\dtl@getfirst\@dtl@argB\end@dtl@getfirst
+ \let\dtl@firstB=\dtl@first
+ \let\dtl@restB=\dtl@rest
+ \expandafter\dtl@ifsingleorUTFviii\expandafter{\dtl@firstA}{%
+ \expandafter\dtl@ifsingleorUTFviii\expandafter{\dtl@firstB}{%
+ \expandafter\dtl@setcharcode\expandafter{\dtl@firstA}{\dtl@codeA}%
+ \expandafter\dtl@setcharcode\expandafter{\dtl@firstB}{\dtl@codeB}%
+ \ifnum\dtl@codeA=-1\relax
+ \ifnum\dtl@codeB=-1\relax
+% \end{macrocode}
+%v2.25: added \cs{expandonce} to prevent non-ASCII characters from being
+%expanded.
+%\changes{2.25}{2016-01-18}{added \cs{expandonce}}
+% \begin{macrocode}
+ \edef\dtl@donext{%
+ \noexpand\dtlcompare
+ {\noexpand#1}{\expandonce\dtl@restA}{\expandonce\dtl@restB}}%
+ \dtl@donext
+ \else
+ \edef\dtl@donext{%
+ \noexpand\dtlcompare
+ {\noexpand#1}%
+ {\expandonce\dtl@restA}%
+ {\expandonce\dtl@firstB\expandonce\dtl@restB}}%
+ \dtl@donext
+ \fi
+ \else
+ \ifnum\dtl@codeB=-1\relax
+% \end{macrocode}
+%v2.25: added \cs{expandonce} to prevent non-ASCII characters from being
+%expanded.
+% \begin{macrocode}
+ \edef\dtl@donext{%
+ \noexpand\dtlcompare
+ {\noexpand#1}%
+ {\expandonce\dtl@firstA\expandonce\dtl@restA}%
+ {\expandonce\dtl@restB}}%
+ \dtl@donext
+ \else
+ \ifnum\dtl@codeA<\dtl@codeB
+ #1=-1\relax
+ \else
+ \ifnum\dtl@codeA>\dtl@codeB
+ #1=1\relax
+ \else
+ \ifdefempty{\dtl@restA}%
+ {%
+ \ifdefempty{\dtl@restB}%
+ {%
+ #1=0\relax
+ }%
+ {%
+ #1=-1\relax
+ }%
+ }%
+ {%
+ \ifdefempty{\restB}%
+ {%
+ #1=1\relax
+ }%
+ {%
+ \protected@edef\dtl@donext{%
+ \noexpand\dtlcompare
+ {\noexpand#1}{\dtl@restA}{\dtl@restB}}%
+ \dtl@donext
+ }%
+ }%
+ \fi
+ \fi
+ \fi
+ \fi
+ }{%
+% \end{macrocode}
+%v2.25: added \cs{expandonce} to prevent non-ASCII characters from being
+%expanded.
+% \begin{macrocode}
+ \edef\dtl@donext{%
+ \noexpand\dtlcompare
+ {\noexpand#1}%
+ {\expandonce\dtl@firstA\expandonce\dtl@restA}%
+ {\expandonce\dtl@firstB\expandonce\dtl@restB}}%
+ \dtl@donext
+ }}{%
+ \edef\dtl@donext{%
+ \noexpand\dtlcompare
+ {\noexpand#1}%
+ {\expandonce\dtl@firstA\expandonce\dtl@restA}%
+ {\expandonce\dtl@firstB\expandonce\dtl@restB}}%
+ \dtl@donext
+ }%
+ }%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@if@two@octets}
+%\changes{2.24}{2016-01-12}{new}
+%Check if argument starts with \cs{UTFviii@two@octets}
+% \begin{macrocode}
+\def\dtl@if@two@octets#1#2\dtl@end@if@two@octets#3#4{%
+ \ifbool{@dtl@utf8}
+ {%
+ \ifx\UTFviii@two@octets#1\relax
+ #3%
+ \else
+ #4%
+ \fi
+ }%
+ {%
+ #4%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@getfirst@UTFviii}
+%\changes{2.24}{2016-01-12}{new}
+% \begin{macrocode}
+\def\dtl@getfirst@UTFviii#1#2#3\end@dtl@getfirst@UTFviii{%
+ \def\dtl@first{#1#2}%
+ \ifx\@nil#3\relax
+ \def\dtl@rest{}%
+ \else
+ \expandafter\def\expandafter\dtl@rest\expandafter{\@dtl@firsttonil#3}%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@firsttonil}
+%\changes{2.24}{2016-01-12}{new}
+% \begin{macrocode}
+\def\@dtl@firsttonil#1\@nil{#1}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@getfirst}
+% Gets the first object, and stores in \cs{dtl@first}. The remainder
+% is stored in \cs{dtl@rest}.
+%\changes{2.23}{2015-07-11}{changed \cs{end} to \cs{end@dtl@getfirst}}
+% \begin{macrocode}
+\def\dtl@getfirst#1#2\end@dtl@getfirst{%
+ \def\dtl@first{#1}%
+ \ifdefempty{\dtl@first}%
+ {%
+ \def\dtl@rest{#2}%
+ }%
+ {%
+ \ifbool{@dtl@utf8}
+ {%
+ \expandafter\dtl@if@two@octets#1#2\relax\dtl@end@if@two@octets
+ {%
+ \dtl@getfirst@UTFviii#1#2\@nil\end@dtl@getfirst@UTFviii
+ }%
+ {%
+ \dtl@ifsingle{#1}{\def\dtl@rest{#2}}{\dtl@getfirst#1#2\end@dtl@getfirst}%
+ }%
+ }%
+ {%
+ \dtl@ifsingle{#1}{\def\dtl@rest{#2}}{\dtl@getfirst#1#2\end@dtl@getfirst}%
+ }%
+ }%
+}%
+% \end{macrocode}
+%\end{macro}
+% Count registers to store character codes:
+% \begin{macrocode}
+\newcount\dtl@codeA
+\newcount\dtl@codeB
+% \end{macrocode}
+%\begin{macro}{\dtl@setcharcode}
+%\begin{definition}
+%\cs{dtl@setcharcode}\marg{c}\marg{count register}
+%\end{definition}
+% Sets \meta{count register} to the character code of \meta{c}, or to
+% -1 if \meta{c} is a control sequence, unless \meta{c} is either
+% \cs{space} or |~| in which case it sets \meta{count register}
+% to the character code of the space character.
+% \begin{macrocode}
+\newcommand*{\dtl@setcharcode}[2]{%
+ \ifstrempty{#1}%
+ {%
+% \end{macrocode}
+% Empty argument. Set code to $-1$.
+% \begin{macrocode}
+ #2=-1\relax
+ }%
+ {%
+ \ifx\@dtl@wordbreak#1\relax
+% \end{macrocode}
+% Reached a word break. Set to character code of a space.
+%\changes{2.13}{2013-01-15}{change from check for space and tilde to check
+%for \cs{@dtl@wordbreak}}
+% \begin{macrocode}
+ #2=`\ \relax
+ \else
+ \ifcat\noexpand#1\relax
+% \end{macrocode}
+% Argument is a control sequence, so set to 0.
+% \begin{macrocode}
+ #2=0\relax
+ \else
+ \expandafter\dtl@if@two@octets#1\relax\relax\dtl@end@if@two@octets
+ {%
+% \end{macrocode}
+% Argument is a UTF8 character.
+% \begin{macrocode}
+ \dtlsetUTFviiicharcode{#1}{#2}%
+ }%
+ {%
+% \end{macrocode}
+% Argument is a character, so set to the character code.
+% \begin{macrocode}
+ \dtlsetcharcode{#1}{#2}%
+ }%
+ \fi
+ \fi
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlsetcharcode}
+%\changes{2.24}{2016-01-12}{new}
+% Set the code for the given character. May be redefined by user
+% for non-UTF8 encodings (e.g.\ Latin-1).
+% \begin{macrocode}
+\newcommand*{\dtlsetcharcode}[2]{#2=`#1\relax}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlsetlccharcode}
+%\changes{2.24}{2016-01-12}{new}
+% Set the lowercase code for the given character. May be redefined by user
+% for non-UTF8 encodings (e.g.\ Latin-1).
+% \begin{macrocode}
+\newcommand*{\dtlsetlccharcode}[2]{#2=\lccode`#1\relax}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlsetUTFviiicharcode}
+% Default behaviour is to set all UTF8 characters to code 64 (before
+% A). This will need to be redefined according to the relevant alphabet.
+%\changes{2.24}{2016-01-12}{new}
+% \begin{macrocode}
+\newcommand*\dtlsetUTFviiicharcode[2]{\dtlsetdefaultUTFviiicharcode{#1}{#2}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlsetUTFviiilccharcode}
+%\changes{2.24}{2016-01-12}{new}
+% Default behaviour is to set all UTF8 characters to code 96 (before
+% a). This will need to be redefined according to the relevant alphabet.
+% \begin{macrocode}
+\newcommand*\dtlsetUTFviiilccharcode[2]{\dtlsetdefaultUTFviiilccharcode{#1}{#2}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlsetdefaultUTFviiicharcode}
+%\changes{2.24}{2016-01-12}{new}
+% Default codes for some supplemental Latin characters.
+% \begin{macrocode}
+\newcommand*\dtlsetdefaultUTFviiicharcode[2]{%
+ \ifboolexpr
+ {
+ test {\ifstrequal{#1}{À}}
+ or test {\ifstrequal{#1}{Á}}
+ or test {\ifstrequal{#1}{Á}}
+ or test {\ifstrequal{#1}{Ã}}
+ or test {\ifstrequal{#1}{Ä}}
+ }%
+ {%
+ #2=`A\relax
+ }%
+ {%
+ \ifstrequal{#1}{Ç}%
+ {%
+ #2=`C\relax
+ }%
+ {%
+ \ifboolexpr
+ {
+ test {\ifstrequal{#1}{È}}
+ or test {\ifstrequal{#1}{É}}
+ or test {\ifstrequal{#1}{Ê}}
+ or test {\ifstrequal{#1}{Ë}}
+ }%
+ {%
+ #2=`E\relax
+ }%
+ {%
+ \ifboolexpr
+ {
+ test {\ifstrequal{#1}{Ì}}
+ or test {\ifstrequal{#1}{Í}}
+ or test {\ifstrequal{#1}{Î}}
+ or test {\ifstrequal{#1}{Ï}}
+ }%
+ {%
+ #2=`I\relax
+ }%
+ {%
+ \ifstrequal{#1}{Ñ}%
+ {%
+ #2=`N\relax
+ }%
+ {%
+ \ifboolexpr
+ {
+ test {\ifstrequal{#1}{Ò}}
+ or test {\ifstrequal{#1}{Ó}}
+ or test {\ifstrequal{#1}{Ô}}
+ or test {\ifstrequal{#1}{Õ}}
+ or test {\ifstrequal{#1}{Ö}}
+ }%
+ {%
+ #2=`O\relax
+ }%
+ {%
+ \ifboolexpr
+ {
+ test {\ifstrequal{#1}{Ù}}
+ or test {\ifstrequal{#1}{Ú}}
+ or test {\ifstrequal{#1}{Û}}
+ or test {\ifstrequal{#1}{Ü}}
+ }%
+ {%
+ #2=`U\relax
+ }%
+ {%
+ \ifstrequal{#1}{Ý}%
+ {%
+ #2=`Y\relax
+ }%
+ {%
+ \ifboolexpr
+ {
+ test {\ifstrequal{#1}{à}}
+ or test {\ifstrequal{#1}{á}}
+ or test {\ifstrequal{#1}{á}}
+ or test {\ifstrequal{#1}{ã}}
+ or test {\ifstrequal{#1}{ä}}
+ }%
+ {%
+ #2=`a\relax
+ }%
+ {%
+ \ifstrequal{#1}{ç}%
+ {%
+ #2=`c\relax
+ }%
+ {%
+ \ifboolexpr
+ {
+ test {\ifstrequal{#1}{è}}
+ or test {\ifstrequal{#1}{é}}
+ or test {\ifstrequal{#1}{ê}}
+ or test {\ifstrequal{#1}{ë}}
+ }%
+ {%
+ #2=`e\relax
+ }%
+ {%
+ \ifboolexpr
+ {
+ test {\ifstrequal{#1}{ì}}
+ or test {\ifstrequal{#1}{í}}
+ or test {\ifstrequal{#1}{î}}
+ or test {\ifstrequal{#1}{ï}}
+ }%
+ {%
+ #2=`i\relax
+ }%
+ {%
+ \ifstrequal{#1}{ñ}%
+ {%
+ #2=`n\relax
+ }%
+ {%
+ \ifboolexpr
+ {
+ test {\ifstrequal{#1}{ò}}
+ or test {\ifstrequal{#1}{ó}}
+ or test {\ifstrequal{#1}{ô}}
+ or test {\ifstrequal{#1}{õ}}
+ or test {\ifstrequal{#1}{ö}}
+ }%
+ {%
+ #2=`o\relax
+ }%
+ {%
+ \ifboolexpr
+ {
+ test {\ifstrequal{#1}{ù}}
+ or test {\ifstrequal{#1}{ú}}
+ or test {\ifstrequal{#1}{û}}
+ or test {\ifstrequal{#1}{ü}}
+ }%
+ {%
+ #2=`u\relax
+ }%
+ {%
+ \ifstrequal{#1}{ý}%
+ {%
+ #2=`y\relax
+ }%
+ {%
+ #2=64\relax
+ }%
+ }%
+ }%
+ }%
+ }%
+ }%
+ }%
+ }%
+ }%
+ }%
+ }%
+ }%
+ }%
+ }%
+ }%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlsetdefaultUTFviiilccharcode}
+%\changes{2.24}{2016-01-12}{new}
+% As above but for case-insensitive comparison.
+% \begin{macrocode}
+\newcommand*\dtlsetdefaultUTFviiilccharcode[2]{%
+ \ifboolexpr
+ {
+ test {\ifstrequal{#1}{à}}
+ or test {\ifstrequal{#1}{á}}
+ or test {\ifstrequal{#1}{á}}
+ or test {\ifstrequal{#1}{ã}}
+ or test {\ifstrequal{#1}{ä}}
+ or test {\ifstrequal{#1}{À}}
+ or test {\ifstrequal{#1}{Á}}
+ or test {\ifstrequal{#1}{Á}}
+ or test {\ifstrequal{#1}{Ã}}
+ or test {\ifstrequal{#1}{Ä}}
+ }%
+ {%
+ #2=`a\relax
+ }%
+ {%
+ \ifboolexpr
+ {
+ test {\ifstrequal{#1}{ç}}
+ or test {\ifstrequal{#1}{Ç}}
+ }
+ {%
+ #2=`c\relax
+ }%
+ {%
+ \ifboolexpr
+ {
+ test {\ifstrequal{#1}{è}}
+ or test {\ifstrequal{#1}{é}}
+ or test {\ifstrequal{#1}{ê}}
+ or test {\ifstrequal{#1}{ë}}
+ or test {\ifstrequal{#1}{È}}
+ or test {\ifstrequal{#1}{É}}
+ or test {\ifstrequal{#1}{Ê}}
+ or test {\ifstrequal{#1}{Ë}}
+ }%
+ {%
+ #2=`e\relax
+ }%
+ {%
+ \ifboolexpr
+ {
+ test {\ifstrequal{#1}{ì}}
+ or test {\ifstrequal{#1}{í}}
+ or test {\ifstrequal{#1}{î}}
+ or test {\ifstrequal{#1}{ï}}
+ or test {\ifstrequal{#1}{Ì}}
+ or test {\ifstrequal{#1}{Í}}
+ or test {\ifstrequal{#1}{Î}}
+ or test {\ifstrequal{#1}{Ï}}
+ }%
+ {%
+ #2=`i\relax
+ }%
+ {%
+ \ifboolexpr
+ {
+ test {\ifstrequal{#1}{ñ}}
+ or test {\ifstrequal{#1}{Ñ}}
+ }
+ {%
+ #2=`n\relax
+ }%
+ {%
+ \ifboolexpr
+ {
+ test {\ifstrequal{#1}{ò}}
+ or test {\ifstrequal{#1}{ó}}
+ or test {\ifstrequal{#1}{ô}}
+ or test {\ifstrequal{#1}{õ}}
+ or test {\ifstrequal{#1}{ö}}
+ or test {\ifstrequal{#1}{Ò}}
+ or test {\ifstrequal{#1}{Ó}}
+ or test {\ifstrequal{#1}{Ô}}
+ or test {\ifstrequal{#1}{Õ}}
+ or test {\ifstrequal{#1}{Ö}}
+ }%
+ {%
+ #2=`o\relax
+ }%
+ {%
+ \ifboolexpr
+ {
+ test {\ifstrequal{#1}{ù}}
+ or test {\ifstrequal{#1}{ú}}
+ or test {\ifstrequal{#1}{û}}
+ or test {\ifstrequal{#1}{ü}}
+ or test {\ifstrequal{#1}{Ù}}
+ or test {\ifstrequal{#1}{Ú}}
+ or test {\ifstrequal{#1}{Û}}
+ or test {\ifstrequal{#1}{Ü}}
+ }%
+ {%
+ #2=`u\relax
+ }%
+ {%
+ \ifboolexpr
+ {
+ test {\ifstrequal{#1}{ý}}
+ or test {\ifstrequal{#1}{Ý}}
+ }%
+ {%
+ #2=`y\relax
+ }%
+ {%
+ #2=96\relax
+ }%
+ }%
+ }%
+ }%
+ }%
+ }%
+ }%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@setlccharcode}
+%\begin{definition}
+%\cs{dtl@setlccharcode}\marg{c}\marg{count register}
+%\end{definition}
+% As \cs{dtl@setlccharcode} except it sets \meta{count register}
+% to the lower case character code of \meta{c}, unless \meta{c}
+% is a control sequence, in which case it does the same as
+% \cs{dtl@setcharcode}.
+% \begin{macrocode}
+\newcommand*{\dtl@setlccharcode}[2]{%
+ \ifstrempty{#1}%
+ {%
+% \end{macrocode}
+% String is empty so set to $-1$.
+% \begin{macrocode}
+ #2=-1\relax
+ }%
+ {%
+% \end{macrocode}
+% Do we have a word break?
+%\changes{2.13}{2013-01-15}{changed to test for \cs{@dtl@wordbreak} instead
+%of \cs{space} and tilde}
+% \begin{macrocode}
+ \ifx#1\@dtl@wordbreak\relax
+ #2=`\ \relax
+ \else
+ \ifcat\noexpand#1\relax%
+% \end{macrocode}
+% Argument is a control sequence, so set to 0.
+% \begin{macrocode}
+ #2=0\relax
+ \else
+ \expandafter\dtl@if@two@octets#1\relax\relax\dtl@end@if@two@octets
+ {%
+% \end{macrocode}
+% Argument is a UTF8 character.
+% \begin{macrocode}
+ \dtlsetUTFviiilccharcode{#1}{#2}%
+ }%
+ {%
+% \end{macrocode}
+% Argument is a character, so set to the lower case code.
+% \begin{macrocode}
+ \dtlsetlccharcode{#1}{#2}%
+ }%
+% \end{macrocode}
+% If the result is zero, which means the character doesn't have a lower case
+% equivalent. So set to the character code.
+%\changes{2.13}{2013-01-15}{fixed bug where characters without a lower case
+%equivalent were all considered equal}
+% \begin{macrocode}
+ \ifnum#2=0\relax
+ #2=`#1\relax
+ \fi
+ \fi
+ \fi
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtlicompare}
+%\begin{definition}
+%\cs{dtlicompare}\marg{count}\marg{string1}\marg{string2}
+%\end{definition}
+% As \cs{dtlcompare} but ignores case.
+%\changes{1.01}{2007 Aug 17}{new}
+% \begin{macrocode}
+\newcommand*{\dtlicompare}[3]{%
+ \dtl@subnobrsp{#2}{\@dtl@argA}%
+ \dtl@subnobrsp{#3}{\@dtl@argB}%
+ \ifdefempty{\@dtl@argA}%
+ {%
+ \ifdefempty{\@dtl@argB}%
+ {%
+% \end{macrocode}
+% Both are empty, so they are equal.
+% \begin{macrocode}
+ #1=0\relax
+ }%
+ {%
+% \end{macrocode}
+% The first string is empty, but the second isn't. Therefore the
+% first string is less than the second string.
+% \begin{macrocode}
+ #1=-1\relax
+ }%
+ }%
+ {%
+ \ifdefempty{\@dtl@argB}%
+ {%
+% \end{macrocode}
+% The second string is empty, but the first isn't. Therefore the
+% first string is greater than the second string.
+% \begin{macrocode}
+ #1=1\relax
+ }%
+ {%
+% \end{macrocode}
+% Identify all word breaks.
+%\changes{2.13}{2013-01-15}{now using \cs{dtl@setwordbreaksnohyphens} to
+%deal with spaces}
+% \begin{macrocode}
+ \dtl@setwordbreaksnohyphens{\@dtl@argA}{\@dtl@wordbreak}%
+ \let\@dtl@argA\dtl@string
+ \dtl@setwordbreaksnohyphens{\@dtl@argB}{\@dtl@wordbreak}%
+ \let\@dtl@argB\dtl@string
+% \end{macrocode}
+% Get the first object and the remaining text.
+% \begin{macrocode}
+ \expandafter\dtl@getfirst\@dtl@argA\end@dtl@getfirst
+ \let\dtl@firstA=\dtl@first
+ \let\dtl@restA=\dtl@rest
+ \expandafter\dtl@getfirst\@dtl@argB\end@dtl@getfirst
+ \let\dtl@firstB=\dtl@first
+ \let\dtl@restB=\dtl@rest
+% \end{macrocode}
+% Is the first object of \meta{string1} a single character or a group?
+% \begin{macrocode}
+ \expandafter\dtl@ifsingleorUTFviii\expandafter{\dtl@firstA}%
+ {%
+% \end{macrocode}
+% It's a single character. Is the first object of \meta{string2} a
+% single character or a group?
+% \begin{macrocode}
+ \expandafter\dtl@ifsingleorUTFviii\expandafter{\dtl@firstB}%
+ {%
+% \end{macrocode}
+% Both are a single character. Get the lower case character code.
+% \begin{macrocode}
+ \expandafter\dtl@setlccharcode\expandafter{\dtl@firstA}{\dtl@codeA}%
+ \expandafter\dtl@setlccharcode\expandafter{\dtl@firstB}{\dtl@codeB}%
+ \ifnum\dtl@codeA=-1\relax
+ \ifnum\dtl@codeB=-1\relax
+% \end{macrocode}
+%v2.25: added \cs{expandonce} to prevent non-ASCII characters from being
+%expanded.
+%\changes{2.25}{2016-01-18}{added \cs{expandonce}}
+% \begin{macrocode}
+ \edef\dtl@donext{%
+ \noexpand\dtlicompare{\noexpand#1}%
+ {\expandonce\dtl@restA}{\expandonce\dtl@restB}}%
+ \dtl@donext
+ \else
+ \edef\dtl@donext{%
+ \noexpand\dtlicompare
+ {\noexpand#1}%
+ {\expandonce\dtl@restA}%
+ {\expandonce\dtl@firstB\expandonce\dtl@restB}}%
+ \dtl@donext
+ \fi
+ \else
+ \ifnum\dtl@codeB=-1\relax
+% \end{macrocode}
+%v2.25: added \cs{expandonce} to prevent non-ASCII characters from being
+%expanded.
+% \begin{macrocode}
+ \edef\dtl@donext{%
+ \noexpand\dtlicompare
+ {\noexpand#1}%
+ {\expandonce\dtl@firstA\expandonce\dtl@restA}%
+ {\expandonce\dtl@restB}}%
+ \dtl@donext
+ \else
+ \ifnum\dtl@codeA<\dtl@codeB
+ #1=-1\relax
+ \else
+ \ifnum\dtl@codeA>\dtl@codeB
+ #1=1\relax
+ \else
+ \ifdefempty{\dtl@restA}%
+ {%
+ \ifdefempty{\dtl@restB}%
+ {%
+ #1=0\relax
+ }%
+ {%
+ #1=-1\relax
+ }%
+ }%
+ {%
+ \ifdefempty{\restB}%
+ {%
+ #1=1\relax
+ }%
+ {%
+% \end{macrocode}
+%v2.25: added \cs{expandonce} to prevent non-ASCII characters from being
+%expanded.
+% \begin{macrocode}
+ \edef\dtl@donext{%
+ \noexpand\dtlicompare
+ {\noexpand#1}%
+ {\expandonce\dtl@restA}%
+ {\expandonce\dtl@restB}}%
+ \dtl@donext
+ }%
+ }%
+ \fi
+ \fi
+ \fi
+ \fi
+ }%
+ {%
+% \end{macrocode}
+% The first object in \meta{string1} is a single character, but the
+% first object in \meta{string2} isn't a single character.
+%v2.25: added \cs{expandonce} to prevent non-ASCII characters from being
+%expanded.
+% \begin{macrocode}
+ \edef\dtl@donext{%
+ \noexpand\dtlicompare
+ {\noexpand#1}%
+ {\expandonce\dtl@firstA\expandonce\dtl@restA}%
+ {\expandonce\dtl@firstB\expandonce\dtl@restB}}%
+ \dtl@donext
+ }%
+ }%
+ {%
+% \end{macrocode}
+% Neither object is a single character.
+%v2.25: added \cs{expandonce} to prevent non-ASCII characters from being
+%expanded.
+% \begin{macrocode}
+ \edef\dtl@donext{%
+ \noexpand\dtlicompare
+ {\noexpand#1}%
+ {\expandonce\dtl@firstA\expandonce\dtl@restA}%
+ {\expandonce\dtl@firstB\expandonce\dtl@restB}}%
+ \dtl@donext
+ }%
+ }%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlwordindexcompare}
+% Word breaks come before all other letters of the alphabet.
+% \begin{macrocode}
+\newcommand*{\dtlwordindexcompare}[3]{%
+ \@dtldictcompare{#1}{#2}{#3}{\@dtl@wordbreak}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlletterindexcompare}
+% Word breaks are ignored.
+% \begin{macrocode}
+\newcommand*{\dtlletterindexcompare}[3]{%
+ \@dtldictcompare{#1}{#2}{#3}{}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtldictcompare}
+% Word or letter compare. Fourth argument should be
+% \cs{@dtl@wordbreak} for word compare or empty for letter compare.
+% \begin{macrocode}
+\newcommand*{\@dtldictcompare}[4]{%
+ \dtl@subnobrsp{#2}{\@dtl@argA}%
+ \dtl@subnobrsp{#3}{\@dtl@argB}%
+ \ifdefempty{\@dtl@argA}%
+ {%
+ \ifdefempty{\@dtl@argB}%
+ {%
+ #1=0\relax
+ }%
+ {%
+ #1=-1\relax
+ }%
+ }%
+ {%
+ \ifdefempty{\@dtl@argB}%
+ {%
+ #1=1\relax
+ }%
+ {%
+% \end{macrocode}
+% Alphabetizing continues until a comma indicates inverted order.
+% This assumes that an actual comma indicates that the comma forms part of
+% the text (e.g.\ in a title of a play). Inversion commas should be
+% indicated using commands such as \ics{datatoolpersoncomma}.
+% There are three types of
+% inverted order: people, places and subjects (concepts or objects).
+% We also need to treat parenthetical material in a similar way.
+% Find if the first string has an inverted order.
+% \begin{macrocode}
+ \expandafter\DTLsplitstring\expandafter
+ {\@dtl@argA}{\datatoolpersoncomma}{\@dtl@beforepart}{\@dtl@afterpart}%
+ \ifdefempty{\@dtl@replaced}%
+ {%
+ \expandafter\DTLsplitstring\expandafter
+ {\@dtl@argA}{\datatoolplacecomma}{\@dtl@beforepart}{\@dtl@afterpart}%
+ \ifdefempty{\@dtl@replaced}%
+ {%
+ \expandafter\DTLsplitstring\expandafter
+ {\@dtl@argA}{\datatoolsubjectcomma}{\@dtl@beforepart}{\@dtl@afterpart}%
+ \ifdefempty{\@dtl@replaced}%
+ {%
+ \expandafter\DTLsplitstring\expandafter
+ {\@dtl@argA}{\datatoolparenstart}{\@dtl@beforepart}{\@dtl@afterpart}%
+ \ifdefempty{\@dtl@replaced}%
+ {%
+ \def\@dtl@A@comma{0}%
+ \let\@dtl@A@before\@dtl@argA
+ \def\@dtl@A@after{}%
+ }%
+ {%
+ \let\@dtl@A@comma\@dtl@replaced
+ \let\@dtl@A@before\@dtl@beforepart
+ \let\@dtl@A@after\@dtl@afterpart
+ }%
+ }%
+ {%
+ \let\@dtl@A@comma\@dtl@replaced
+ \let\@dtl@A@before\@dtl@beforepart
+ \let\@dtl@A@after\@dtl@afterpart
+ }%
+ }%
+ {%
+ \let\@dtl@A@comma\@dtl@replaced
+ \let\@dtl@A@before\@dtl@beforepart
+ \let\@dtl@A@after\@dtl@afterpart
+ }%
+ }%
+ {%
+ \let\@dtl@A@comma\@dtl@replaced
+ \let\@dtl@A@before\@dtl@beforepart
+ \let\@dtl@A@after\@dtl@afterpart
+ }%
+% \end{macrocode}
+% Now find if the second string has an inverted order.
+% \begin{macrocode}
+ \expandafter\DTLsplitstring\expandafter
+ {\@dtl@argB}{\datatoolpersoncomma}{\@dtl@beforepart}{\@dtl@afterpart}%
+ \ifdefempty{\@dtl@replaced}%
+ {%
+ \expandafter\DTLsplitstring\expandafter
+ {\@dtl@argB}{\datatoolplacecomma}{\@dtl@beforepart}{\@dtl@afterpart}%
+ \ifdefempty{\@dtl@replaced}%
+ {%
+ \expandafter\DTLsplitstring\expandafter
+ {\@dtl@argB}{\datatoolsubjectcomma}{\@dtl@beforepart}{\@dtl@afterpart}%
+ \ifdefempty{\@dtl@replaced}%
+ {%
+ \expandafter\DTLsplitstring\expandafter
+ {\@dtl@argB}{\datatoolparenstart}{\@dtl@beforepart}{\@dtl@afterpart}%
+ \ifdefempty{\@dtl@replaced}%
+ {%
+ \def\@dtl@B@comma{0}%
+ \let\@dtl@B@before\@dtl@argB
+ \def\@dtl@B@after{}%
+ }%
+ {%
+ \let\@dtl@B@comma\@dtl@replaced
+ \let\@dtl@B@before\@dtl@beforepart
+ \let\@dtl@B@after\@dtl@afterpart
+ }%
+ }%
+ {%
+ \let\@dtl@B@comma\@dtl@replaced
+ \let\@dtl@B@before\@dtl@beforepart
+ \let\@dtl@B@after\@dtl@afterpart
+ }%
+ }%
+ {%
+ \let\@dtl@B@comma\@dtl@replaced
+ \let\@dtl@B@before\@dtl@beforepart
+ \let\@dtl@B@after\@dtl@afterpart
+ }%
+ }%
+ {%
+ \let\@dtl@B@comma\@dtl@replaced
+ \let\@dtl@B@before\@dtl@beforepart
+ \let\@dtl@B@after\@dtl@afterpart
+ }%
+% \end{macrocode}
+% Get the first letter and find out if it's a letter, digit or
+% symbol.
+% \begin{macrocode}
+ \expandafter\dtl@ifcasechargroup\@dtl@A@before\dtl@end@ifcasechargroup
+ {\def\@dtl@A@chargroup{2}}%
+ {\def\@dtl@A@chargroup{1}}%
+ {\def\@dtl@A@chargroup{0}}%
+ \expandafter\dtl@ifcasechargroup\@dtl@B@before\dtl@end@ifcasechargroup
+ {\def\@dtl@B@chargroup{2}}%
+ {\def\@dtl@B@chargroup{1}}%
+ {\def\@dtl@B@chargroup{0}}%
+% \end{macrocode}
+% Are they in the same group?
+% \begin{macrocode}
+ \ifnum\@dtl@A@chargroup<\@dtl@B@chargroup
+ #1=-1\relax
+ \else
+ \ifnum\@dtl@A@chargroup>\@dtl@B@chargroup
+ #1=1\relax
+ \else
+% \end{macrocode}
+% In the same group. Which group are they in?
+% \begin{macrocode}
+ \ifcase\@dtl@A@chargroup
+% \end{macrocode}
+% Symbol group
+%v2.25: added \cs{expandonce} to prevent non-ASCII characters from being
+%expanded.
+%\changes{2.25}{2016-01-18}{added \cs{expandonce}}
+% \begin{macrocode}
+ \edef\dtl@donext{%
+ \noexpand\dtlcompare
+ {\noexpand#1}%
+ {\expandonce\@dtl@A@before}%
+ {\expandonce\@dtl@B@before}}%
+ \dtl@donext
+% \end{macrocode}
+% Number.
+% \begin{macrocode}
+ \or
+ \ifnum\@dtl@A@before<\@dtl@B@before\relax
+ #1=-1\relax
+ \else
+ \ifnum\@dtl@A@before>\@dtl@B@before\relax
+ #1=1\relax
+ \else
+ #1=0\relax
+ \fi
+ \fi
+ \or
+% \end{macrocode}
+% Word or phrase.
+% \begin{macrocode}
+ \@dtlwordindexcompare{#1}{\@dtl@A@before}{\@dtl@B@before}
+ {\dtlicomparewords}{#4}%
+% \end{macrocode}
+% If they are equal, do we have an inverted order?
+% \begin{macrocode}
+ \ifnum#1=0\relax
+% \end{macrocode}
+% Temporarily redefine the inversion commas to numbers to make the
+% comparisons easier.
+% \begin{macrocode}
+ \let\@org@dtl@person@comma\datatoolpersoncomma
+ \let\@org@dtl@place@comma\datatoolplacecomma
+ \let\@org@dtl@subject@comma\datatoolsubjectcomma
+ \let\@org@dtl@paren@start\datatoolparenstart
+% \end{macrocode}
+% People first, then places, then subjects, then no inversion, then
+% parenthetical.
+% \begin{macrocode}
+ \def\datatoolpersoncomma{3}%
+ \def\datatoolplacecomma{2}%
+ \def\datatoolsubjectcomma{1}%
+ \def\datatoolparenstart{-1}%
+% \end{macrocode}
+% Now compare:
+% \begin{macrocode}
+ \ifnum\@dtl@A@comma>\@dtl@B@comma\relax
+ #1=-1\relax
+ \else
+ \ifnum\@dtl@A@comma<\@dtl@B@comma\relax
+ #1=1\relax
+ \else
+% \end{macrocode}
+% They are the same type. First do a reverse case sensitive comparison.
+% \begin{macrocode}
+ \@dtlwordindexcompare{#1}{\@dtl@B@before}{\@dtl@A@before}
+ {\dtlcomparewords}{#4}%
+% \end{macrocode}
+% Are they still equal?
+% \begin{macrocode}
+ \ifnum#1=0\relax
+% \end{macrocode}
+% So sort on inversion.
+% \begin{macrocode}
+ \@dtlwordindexcompare{#1}{\@dtl@A@after}{\@dtl@B@after}
+ {\dtlicomparewords}{#4}%
+ \fi
+ \fi
+ \fi
+% \end{macrocode}
+% Restore original definitions.
+% \begin{macrocode}
+ \let\datatoolpersoncomma\@org@dtl@person@comma
+ \let\datatoolplacecomma\@org@dtl@place@comma
+ \let\datatoolsubjectcomma\@org@dtl@subject@comma
+ \let\datatoolparenstart\@org@dtl@paren@start
+ \fi
+ \fi
+ \fi
+ \fi
+ }%
+ }%
+}%
+% \end{macrocode}
+%\end{macro}
+%
+% Need to indicate type of inversion.
+%\begin{macro}{\datatoolpersoncomma}
+% \begin{macrocode}
+\newcommand*{\datatoolpersoncomma}{,\space}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\datatoolplacecomma}
+% \begin{macrocode}
+\newcommand*{\datatoolplacecomma}{,\space}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\datatoolsubjectcomma}
+% \begin{macrocode}
+\newcommand*{\datatoolsubjectcomma}{,\space}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\datatoolparenstart}
+% \begin{macrocode}
+\newcommand*{\datatoolparenstart}{\space}
+% \end{macrocode}
+%\end{macro}
+%
+%
+%\begin{macro}{\@dtlwordindexcompare}
+%\begin{definition}
+%\cs{@dtlwordindexcompare}\marg{count}\marg{cs A}\marg{cs
+%B}\marg{word comparison handler}\marg{word break replacement}
+%\end{definition}
+% \begin{macrocode}
+\newcommand*{\@dtlwordindexcompare}[5]{%
+% \end{macrocode}
+% Word or phrase. Replace word breaks.
+% \begin{macrocode}
+ \dtl@setwordbreaks{#2}{#5}%
+ \let#2\dtl@string
+% \end{macrocode}
+% And again for the second string.
+% \begin{macrocode}
+ \dtl@setwordbreaks{#3}{}%
+ \let#3\dtl@string
+% \end{macrocode}
+% Now compare both strings.
+% \begin{macrocode}
+% \@dtl@dict@compare{#1}{#2}{#3}{#4}%
+ \edef\@dtl@do@compare{%
+ \noexpand#4{\noexpand#1}%
+ {\expandonce#2}{\expandonce#3}%
+ }%
+ \@dtl@do@compare
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@dict@compare}
+%\begin{definition}
+%\cs{@dtl@dict@compare}\marg{count}\marg{cs A}\marg{cs
+%B}\marg{word comparison handler}
+%\end{definition}
+% Now that all the word breaks have been identified with
+% \cs{@dtl@wordbreak} compare both strings.
+% \begin{macrocode}
+\newcommand*{\@dtl@dict@compare}[4]{%
+% \end{macrocode}
+% Are either empty?
+% \begin{macrocode}
+ \ifdefempty{#2}%
+ {%
+% \end{macrocode}
+% A is empty. Is B empty?
+% \begin{macrocode}
+ \ifdefempty{#3}%
+ {%
+% \end{macrocode}
+% Both are empty.
+% \begin{macrocode}
+ #1=0\relax
+ }%
+ {%
+% \end{macrocode}
+% A is empty but B isn't
+% \begin{macrocode}
+ #1=-1\relax
+ }%
+ }%
+ {%
+% \end{macrocode}
+% A isn't empty. Is B empty?
+% \begin{macrocode}
+ \ifdefempty{#3}%
+ {%
+% \end{macrocode}
+% B is empty but A isn't.
+% \begin{macrocode}
+ #1=1\relax
+ }%
+ {%
+% \end{macrocode}
+% Neither are empty. Grab first word from A.
+% \begin{macrocode}
+ \expandafter\dtl@grabword#2\@dtl@endgrabword\dtl@A@first\dtl@A@remain
+% \end{macrocode}
+% Grab first word from B.
+% \begin{macrocode}
+ \expandafter\dtl@grabword#3\@dtl@endgrabword\dtl@B@first\dtl@B@remain
+% \end{macrocode}
+% Compare A and B.
+% \begin{macrocode}
+ \edef\@dtl@do@compare{%
+ \noexpand#4{\noexpand#1}%
+ {\expandonce\dtl@A@first}{\expandonce\dtl@B@first}%
+ }%
+ \@dtl@do@compare
+% \end{macrocode}
+% Are they the same?
+% \begin{macrocode}
+ \ifnum#1=0\relax
+% \end{macrocode}
+% They are, so compare on the next word.
+% \begin{macrocode}
+ \@dtl@dict@compare{#1}{\dtl@A@remain}{\dtl@B@remain}{#4}%
+ \fi
+ }%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@grabword}
+% Grab first word from phrase.
+% \begin{macrocode}
+\def\dtl@grabword#1\@dtl@wordbreak#2\@dtl@endgrabword#3#4{%
+ \def#3{#1}%
+ \def#4{#2}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlicomparewords}
+%\begin{definition}
+%\cs{dtlicomparewords}\marg{count}\marg{word A}\marg{word B}
+%\end{definition}
+%This does a case insensitive comparison.
+% \begin{macrocode}
+\newcommand{\dtlicomparewords}[3]{%
+ \dtlicompare{#1}{#2}{#3}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlcomparewords}
+%\begin{definition}
+%\cs{dtlcomparewords}\marg{count}\marg{word A}\marg{word B}
+%\end{definition}
+%This does a case sensitive comparison.
+% \begin{macrocode}
+\newcommand{\dtlcomparewords}[3]{%
+ \dtlcompare{#1}{#2}{#3}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@setwordbreaks}
+% Replace word breaks (space, \cs{space}, \cs{\space}, \verb|~| and
+% hyphen \texttt{-}) with the second argument (either
+% \cs{@dtl@wordbreak} for letter sort or nothing for word sort). Result is stored in
+% \cs{dtl@string}.
+% \begin{macrocode}
+\newcommand*{\dtl@setwordbreaks}[2]{%
+ \expandafter\dtl@subnobrsp\expandafter{#1}{\dtl@string}%
+ \DTLsubstituteall{\dtl@string}{~}{#2}%
+ \DTLsubstituteall{\dtl@string}{\ }{#2}%
+ \DTLsubstituteall{\dtl@string}{\space}{#2}%
+ \DTLsubstituteall{\dtl@string}{-}{#2}%
+% \end{macrocode}
+% Now deal with actual spaces.
+% \begin{macrocode}
+ \toks@{#2}%
+ \edef\dtl@do@setwordbreaks{%
+ \noexpand\@dtl@setwordbreaks{\the\toks@}\expandonce\dtl@string\space\noexpand\@nil}%
+ \def\dtl@string{}%
+ \dtl@do@setwordbreaks
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@dtl@setwordbreaks}
+% \begin{macrocode}
+\def\@dtl@setwordbreaks#1#2 #3{%
+ \def\dtl@tmp{#3}%
+ \ifx\@nnil\dtl@tmp
+% \end{macrocode}
+% Reached end of loop.
+% \begin{macrocode}
+ \let\@dtl@setwordbreaks@next\@gobbletwo
+ \appto\dtl@string{#2}%
+ \else
+ \let\@dtl@setwordbreaks@next\@dtl@setwordbreaks
+ \appto\dtl@string{#2#1}%
+ \fi
+ \@dtl@setwordbreaks@next{#1}#3%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@dtl@setwordbreaksnohyphens}
+% As \cs{dtl@setwordbreaks} but excludes hyphens.
+% \begin{macrocode}
+\newcommand*{\dtl@setwordbreaksnohyphens}[2]{%
+ \expandafter\dtl@subnobrsp\expandafter{#1}{\dtl@string}%
+ \DTLsubstituteall{\dtl@string}{~}{#2}%
+ \DTLsubstituteall{\dtl@string}{\ }{#2}%
+ \DTLsubstituteall{\dtl@string}{\space}{#2}%
+% \end{macrocode}
+% Now deal with actual spaces.
+% \begin{macrocode}
+ \toks@{#2}%
+ \edef\dtl@do@setwordbreaks{%
+ \noexpand\@dtl@setwordbreaks{\the\toks@}\expandonce\dtl@string\space\noexpand\@nil}%
+ \def\dtl@string{}%
+ \dtl@do@setwordbreaks
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@wordbreak}
+% \begin{macrocode}
+\newcommand*{\@dtl@wordbreak}{ }
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@ifcasechargroup}
+% Determine if first character is a letter, a digit or a symbol.
+% \begin{macrocode}
+\def\dtl@ifcasechargroup#1#2\dtl@end@ifcasechargroup#3#4#5{%
+% \end{macrocode}
+% Does it start with a UTF8 character?
+% \begin{macrocode}
+ \expandafter\dtl@if@two@octets#1#2\relax\relax\dtl@end@if@two@octets
+ {%
+% \end{macrocode}
+% Get the lower case character code.
+%\changes{2.24}{2016-01-12}{added check for UTF8}
+% \begin{macrocode}
+ \dtl@getfirst@UTFviii#1#2\@nil\end@dtl@getfirst@UTFviii
+ \expandafter\dtlsetUTFviiilccharcode\expandafter{\dtl@first}{\count@}%
+ \ifnum\count@<`a\relax #5\else#3\fi
+ }%
+ {%
+ \dtlifcasechargroup{#1}%
+ {#3}%
+ {%
+% \end{macrocode}
+% Starts with a digit. Is the whole thing an integer?
+% \begin{macrocode}
+ \DTLifint{#1#2}
+ {%
+ #4%
+ }%
+ {%
+% \end{macrocode}
+% No, it isn't. Consider it a string.
+% \begin{macrocode}
+ #3%
+ }%
+ }%
+ {#5}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{macro}
+%\begin{definition}
+%\cs{dtlifcasechargroup}\marg{char}\marg{case letter}\marg{case
+%digit}\marg{case symbol}
+%\end{definition}
+% \begin{macrocode}
+\newcommand*{\dtlifcasechargroup}[4]{%
+ \count@=`#1\relax
+ \dtlifintclosedbetween{\number\count@}{48}{57}%
+ {%
+% \end{macrocode}
+% It's a digit.
+% \begin{macrocode}
+ #3%
+ }%
+ {%
+ \dtlifintclosedbetween{\number\count@}{97}{122}%
+ {%
+% \end{macrocode}
+% Lower case letter
+% \begin{macrocode}
+ #2%
+ }%
+ {%
+ \dtlifintclosedbetween{\number\count@}{65}{90}%
+ {%
+% \end{macrocode}
+% Upper case letter
+% \begin{macrocode}
+ #2%
+ }%
+ {%
+% \end{macrocode}
+% Other
+% \begin{macrocode}
+ #4%
+ }%
+ }%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlparsewords}
+%\changes{2.13}{2013-01-15}{new}
+%\begin{definition}
+%\cs{dtlparsewords}\marg{phrase}\marg{handler cs}
+%\end{definition}
+% Iterates through the given phrase. Hyphens are considered word
+% boundaries.
+% \begin{macrocode}
+\newcommand*{\dtlparsewords}[2]{%
+ \dtl@subnobrsp{#1}{\dtl@string}%
+ \DTLsubstituteall{\dtl@string}{~}{ }%
+ \DTLsubstituteall{\dtl@string}{\ }{ }%
+ \DTLsubstituteall{\dtl@string}{\space}{ }%
+ \DTLsubstituteall{\dtl@string}{-}{ }%
+ \let\dtl@parsewordshandler#2\relax
+ \edef\dtl@donext{%
+ \noexpand\@dtl@parse@words\expandonce\dtl@string\space\noexpand\@nil}%
+ \dtl@donext
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@parse@words}
+% \begin{macrocode}
+\def\@dtl@parse@words#1 #2{%
+ \def\dtl@tmp{#2}%
+ \ifx\@nnil\dtl@tmp
+ \let\parse@wordsnext=\@gobble
+ \else
+ \let\parse@wordsnext=\@dtl@parse@words
+ \fi
+ \dlt@parsewordshandler{#1}%
+ \parse@wordsnext#2%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLifstringlt}
+%\begin{definition}
+%\cs{DTLifstringlt}\marg{string1}\marg{string2}\marg{true part}\marg{false part}
+%\end{definition}
+% String comparison (Starred version ignores case)
+%\changes{1.01}{2007 Aug 17}{added starred version}
+% \begin{macrocode}
+\newcommand*{\DTLifstringlt}{\@ifstar\@sDTLifstringlt\@DTLifstringlt}
+% \end{macrocode}
+% Unstarred version
+% \begin{macrocode}
+\newcommand*{\@DTLifstringlt}[4]{%
+ \protected@edef\@dtl@tmpcmp{%
+ \noexpand\dtlcompare{\noexpand\@dtl@tmpcount}{#1}{#2}}%
+ \@dtl@tmpcmp
+ \ifnum\@dtl@tmpcount<0\relax
+ #3%
+ \else
+ #4%
+ \fi
+}
+% \end{macrocode}
+% Starred version
+% \begin{macrocode}
+\newcommand*{\@sDTLifstringlt}[4]{%
+ \protected@edef\@dtl@tmpcmp{%
+ \noexpand\dtlicompare{\noexpand\@dtl@tmpcount}{#1}{#2}}%
+ \@dtl@tmpcmp
+ \ifnum\@dtl@tmpcount<0\relax
+ #3%
+ \else
+ #4%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLiflt}
+%\begin{definition}
+%\cs{DTLiflt}\marg{arg1}\marg{arg2}\marg{true part}\marg{false part}
+%\end{definition}
+% Does \cs{DTLifnumlt} if both \meta{arg1} and \meta{arg2} are
+% numerical, otherwise do \cs{DTLifstringlt} (unstarred version)
+% or \cs{DTLifstringlt*} (starred version).
+%\changes{1.01}{2007 Aug 17}{added starred version}
+% \begin{macrocode}
+\newcommand*{\DTLiflt}{\@ifstar\@sDTLiflt\@DTLiflt}
+% \end{macrocode}
+% Unstarred version
+% \begin{macrocode}
+\newcommand*{\@DTLiflt}[4]{%
+ \dtl@testbothnumerical{#1}{#2}%
+ \if@dtl@condition
+ \DTLifnumlt{#1}{#2}{#3}{#4}%
+ \else
+ \@DTLifstringlt{#1}{#2}{#3}{#4}%
+ \fi
+}
+% \end{macrocode}
+% Starred version
+% \begin{macrocode}
+\newcommand*{\@sDTLiflt}[4]{%
+ \dtl@testbothnumerical{#1}{#2}%
+ \if@dtl@condition
+ \DTLifnumlt{#1}{#2}{#3}{#4}%
+ \else
+ \@sDTLifstringlt{#1}{#2}{#3}{#4}%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLifnumgt}
+%\begin{definition}
+%\cs{DTLifnumgt}\marg{num1}\marg{num2}\marg{true part}\marg{false part}
+%\end{definition}
+% Determines if \marg{num1} $>$ \marg{num2}. Both numbers
+% need to have the decimal separator changed to a dot
+% to ensure that it works with \cs{dtlifnumgt}
+%\changes{2.10}{2012-07-18}{changed \cs{FPifgt} to \cs{dtlifnumgt}}
+% \begin{macrocode}
+\newcommand*{\DTLifnumgt}[4]{%
+ \DTLconverttodecimal{#1}{\@dtl@numi}%
+ \DTLconverttodecimal{#2}{\@dtl@numii}%
+ \dtlifnumgt{\@dtl@numi}{\@dtl@numii}%
+ {%
+ #3%
+ }%
+ {%
+ #4%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLifstringgt}
+%\begin{definition}
+%\cs{DTLifstringgt}\marg{string1}\marg{string2}\marg{true part}\marg{false part}
+%\end{definition}
+% String comparison (starred version ignores case)
+%\changes{1.01}{2007 Aug 17}{added starred version}
+% \begin{macrocode}
+\newcommand*{\DTLifstringgt}{\@ifstar\@sDTLifstringgt\@DTLifstringgt}
+% \end{macrocode}
+% Unstarred version
+% \begin{macrocode}
+\newcommand*{\@DTLifstringgt}[4]{%
+ \protected@edef\@dtl@tmpcmp{%
+ \noexpand\dtlcompare{\noexpand\@dtl@tmpcount}{#1}{#2}}%
+ \@dtl@tmpcmp
+ \ifnum\@dtl@tmpcount>0\relax
+ #3%
+ \else
+ #4%
+ \fi
+}
+% \end{macrocode}
+% Starred version
+% \begin{macrocode}
+\newcommand*{\@sDTLifstringgt}[4]{%
+ \protected@edef\@dtl@tmpcmp{%
+ \noexpand\dtlicompare{\noexpand\@dtl@tmpcount}{#1}{#2}}%
+ \@dtl@tmpcmp
+ \ifnum\@dtl@tmpcount>0\relax
+ #3%
+ \else
+ #4%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLifgt}
+%\begin{definition}
+%\cs{DTLifgt}\marg{arg1}\marg{arg2}\marg{true part}\marg{false part}
+%\end{definition}
+% Does \cs{DTLifnumgt} if both \meta{arg1} and \meta{arg2} are
+% numerical, otherwise do \cs{DTLifstringgt} or \cs{DTLifstringgt*}.
+%\changes{1.01}{2007 Aug 17}{added starred version}
+% \begin{macrocode}
+\newcommand*{\DTLifgt}{\@ifstar\@sDTLifgt\@DTLifgt}
+% \end{macrocode}
+% Unstarred version
+% \begin{macrocode}
+\newcommand*{\@DTLifgt}[4]{%
+ \dtl@testbothnumerical{#1}{#2}%
+ \if@dtl@condition
+ \DTLifnumgt{#1}{#2}{#3}{#4}%
+ \else
+ \@DTLifstringgt{#1}{#2}{#3}{#4}%
+ \fi
+}
+% \end{macrocode}
+% Starred version
+% \begin{macrocode}
+\newcommand*{\@sDTLifgt}[4]{%
+ \dtl@testbothnumerical{#1}{#2}%
+ \if@dtl@condition
+ \DTLifnumgt{#1}{#2}{#3}{#4}%
+ \else
+ \@sDTLifstringgt{#1}{#2}{#3}{#4}%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLifnumeq}
+%\begin{definition}
+%\cs{DTLifnumeq}\marg{num1}\marg{num2}\marg{true part}\marg{false part}
+%\end{definition}
+% Determines if \marg{num1} = \marg{num2}. Both numbers
+% need to have the decimal separator changed to a dot
+% to ensure that it works with \cs{dtlifnumeq}
+%\changes{2.10}{2012-07-18}{changed \cs{FPifeq} to \cs{dtlifnumeq}}
+% \begin{macrocode}
+\newcommand*{\DTLifnumeq}[4]{%
+ \DTLconverttodecimal{#1}{\@dtl@numi}%
+ \DTLconverttodecimal{#2}{\@dtl@numii}%
+ \dtlifnumeq{\@dtl@numi}{\@dtl@numii}%
+ {%
+ #3%
+ }%
+ {%
+ #4%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLifstringeq}
+%\begin{definition}
+%\cs{DTLifstringeq}\marg{string1}\marg{string2}\marg{true part}\marg{false part}
+%\end{definition}
+% String comparison (starred version ignores case)
+%\changes{1.01}{2007 Aug 17}{added starred version}
+% \begin{macrocode}
+\newcommand*{\DTLifstringeq}{\@ifstar\@sDTLifstringeq\@DTLifstringeq}
+% \end{macrocode}
+% Unstarred version
+% \begin{macrocode}
+\newcommand*{\@DTLifstringeq}[4]{%
+ \protected@edef\@dtl@tmpcmp{%
+ \noexpand\dtlcompare{\noexpand\@dtl@tmpcount}{#1}{#2}}%
+ \@dtl@tmpcmp
+ \ifnum\@dtl@tmpcount=0\relax
+ #3%
+ \else
+ #4%
+ \fi
+}
+% \end{macrocode}
+% Starred version
+% \begin{macrocode}
+\newcommand*{\@sDTLifstringeq}[4]{%
+ \protected@edef\@dtl@tmpcmp{%
+ \noexpand\dtlicompare{\noexpand\@dtl@tmpcount}{#1}{#2}}%
+ \@dtl@tmpcmp
+ \ifnum\@dtl@tmpcount=0\relax
+ #3%
+ \else
+ #4%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLifeq}
+%\begin{definition}
+%\cs{DTLifeq}\marg{arg1}\marg{arg2}\marg{true part}\marg{false part}
+%\end{definition}
+% Does \cs{DTLifnumeq} if both \meta{arg1} and \meta{arg2} are
+% numerical, otherwise do \cs{DTLifstringeq} or \cs{DTLifstringeq*}.
+%\changes{1.01}{2007 Aug 17}{added starred version}
+% \begin{macrocode}
+\newcommand*{\DTLifeq}{\@ifstar\@sDTLifeq\@DTLifeq}
+% \end{macrocode}
+% Unstarred version
+% \begin{macrocode}
+\newcommand*{\@DTLifeq}[4]{%
+ \dtl@testbothnumerical{#1}{#2}%
+ \if@dtl@condition
+ \DTLifnumeq{#1}{#2}{#3}{#4}%
+ \else
+ \@DTLifstringeq{#1}{#2}{#3}{#4}%
+ \fi
+}
+% \end{macrocode}
+% Starred version
+% \begin{macrocode}
+\newcommand*{\@sDTLifeq}[4]{%
+ \dtl@testbothnumerical{#1}{#2}%
+ \if@dtl@condition
+ \DTLifnumeq{#1}{#2}{#3}{#4}%
+ \else
+ \@sDTLifstringeq{#1}{#2}{#3}{#4}%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLifSubString}
+%\begin{definition}
+%\cs{DTLifSubString}\marg{string}\marg{sub string}\marg{true
+%part}\marg{false part}
+%\end{definition}
+% If \meta{sub string} is contained in \meta{string} does
+%\meta{true part}, otherwise does \meta{false part}.
+%\changes{1.01}{2007 Aug 17}{new}
+% \begin{macrocode}
+\newcommand*{\DTLifSubString}[4]{%
+ \protected@edef\@dtl@dotestifsubstring{\noexpand\dtl@testifsubstring
+ {#1}{#2}}%
+ \@dtl@dotestifsubstring
+ \if@dtl@condition
+ #3%
+ \else
+ #4%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtl@testifsubstring}
+% \begin{macrocode}
+\newcommand*{\dtl@testifsubstring}[2]{%
+ \dtl@subnobrsp{#1}{\@dtl@argA}%
+ \dtl@subnobrsp{#2}{\@dtl@argB}%
+% \end{macrocode}
+% Identify all word breaks.
+%\changes{2.13}{2013-01-15}{now using \cs{dtl@setwordbreaksnohyphens} to
+%deal with spaces}
+% \begin{macrocode}
+ \dtl@setwordbreaksnohyphens{\@dtl@argA}{\@dtl@wordbreak}%
+ \let\@dtl@argA\dtl@string
+ \dtl@setwordbreaksnohyphens{\@dtl@argB}{\@dtl@wordbreak}%
+ \let\@dtl@argB\dtl@string
+ \edef\dtl@donext{%
+ \noexpand\@dtl@testifsubstring{\expandonce\@dtl@argA}{\expandonce\@dtl@argB}}%
+ \dtl@donext
+}
+\newcommand*{\@dtl@testifsubstring}[2]{%
+% \end{macrocode}
+%\changes{2.23}{2015-07-11}{bug fix: temp control sequences clash with
+%\cs{@dtl@teststartswith}}
+% \begin{macrocode}
+ \def\@dtl@subs@argA{#1}%
+ \def\@dtl@subs@argB{#2}%
+ \ifdefempty{\@dtl@subs@argB}%
+ {%
+ \@dtl@conditiontrue
+ }%
+ {%
+ \ifdefempty{\@dtl@subs@argA}%
+ {%
+ \@dtl@conditionfalse
+ }%
+ {%
+ \@dtl@teststartswith{#1}{#2}%
+ \if@dtl@condition
+ \else
+ \dtl@getfirst#1\end@dtl@getfirst
+ \expandafter\dtl@ifsingle\expandafter{\dtl@first}%
+ {%
+ \expandafter\@dtl@testifsubstring\expandafter{\dtl@rest}{#2}%
+ }%
+ {%
+ \protected@edef\@dtl@donext{\noexpand\@dtl@testifsubstring
+ {\expandonce\dtl@first\expandonce\dtl@rest}{\expandonce\@dtl@subs@argB}}%
+ \@dtl@donext
+ }%
+ \fi
+ }%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLifStartsWith}
+%\begin{definition}
+%\cs{DTLifStartsWith}\marg{string}\marg{substring}\marg{true
+%part}\marg{false part}
+%\end{definition}
+%If \meta{string} starts with \meta{substring}, this does
+%\meta{true part}, otherwise it does \meta{false part}.
+%\changes{1.01}{2007 Aug 17}{new}
+% \begin{macrocode}
+\newcommand*{\DTLifStartsWith}[4]{%
+ \@dtl@conditionfalse
+ \protected@edef\@dtl@tmp{\noexpand\dtl@teststartswith{#1}{#2}}%
+ \@dtl@tmp
+ \if@dtl@condition
+ #3%
+ \else
+ #4%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@teststartswith}
+%\begin{definition}
+%\cs{dtl@teststartswith}\marg{string}\marg{prefix}
+%\end{definition}
+% Tests if \meta{string} starts with \meta{prefix}. This sets
+% \cs{if@dtl@condition}. First substitute all word breaks with
+% \cs{dtl@setwordbreaksnohyphen}
+% \begin{macrocode}
+\newcommand*{\dtl@teststartswith}[2]{%
+ \dtl@subnobrsp{#1}{\@dtl@argA}%
+ \dtl@subnobrsp{#2}{\@dtl@argB}%
+% \end{macrocode}
+% Identify all word breaks.
+%\changes{2.13}{2013-01-15}{now using \cs{dtl@setwordbreaksnohyphens} to
+%deal with spaces}
+% \begin{macrocode}
+ \dtl@setwordbreaksnohyphens{\@dtl@argA}{\@dtl@wordbreak}%
+ \let\@dtl@argA\dtl@string
+ \dtl@setwordbreaksnohyphens{\@dtl@argB}{\@dtl@wordbreak}%
+ \let\@dtl@argB\dtl@string
+ \edef\dtl@donext{%
+ \noexpand\@dtl@teststartswith{\expandonce\@dtl@argA}{\expandonce\@dtl@argB}}%
+ \dtl@donext
+}
+
+\newcommand*{\@dtl@teststartswith}[2]{%
+ \def\@dtl@argA{#1}%
+ \def\@dtl@argB{#2}%
+ \ifdefempty{\@dtl@argA}%
+ {%
+ \ifdefempty{\@dtl@argB}%
+ {%
+ \@dtl@conditiontrue
+ }%
+ {%
+ \@dtl@conditionfalse
+ }%
+ }%
+ {%
+ \ifdefempty{\@dtl@argB}%
+ {%
+ \@dtl@conditiontrue
+ }%
+ {%
+ \expandafter\dtl@getfirst\@dtl@argA\end@dtl@getfirst
+% \end{macrocode}
+% Get the first object and the remaining text.
+% \begin{macrocode}
+ \let\dtl@firstA=\dtl@first
+ \let\dtl@restA=\dtl@rest
+ \expandafter\dtl@getfirst\@dtl@argB\end@dtl@getfirst
+ \let\dtl@firstB=\dtl@first
+ \let\dtl@restB=\dtl@rest
+% \end{macrocode}
+% Is the first object of \meta{string1} a single character or a group?
+% \begin{macrocode}
+ \expandafter\dtl@ifsingle\expandafter{\dtl@firstA}%
+ {%
+% \end{macrocode}
+% It's a single character. Is the first object of \meta{string2} a
+% single character or a group?
+% \begin{macrocode}
+ \expandafter\dtl@ifsingle\expandafter{\dtl@firstB}%
+ {%
+% \end{macrocode}
+% Both are a single character. Get the lower case character code.
+% \begin{macrocode}
+ \expandafter\dtl@setcharcode\expandafter{\dtl@firstA}{\dtl@codeA}%
+ \expandafter\dtl@setcharcode\expandafter{\dtl@firstB}{\dtl@codeB}%
+ \ifnum\dtl@codeA=-1\relax
+ \ifnum\dtl@codeB=-1\relax
+ \protected@edef\dtl@donext{%
+ \noexpand\@dtl@teststartswith{\expandonce\dtl@restA}{\expandonce\dtl@restB}}%
+ \dtl@donext
+ \else
+ \protected@edef\dtl@donext{%
+ \noexpand\@dtl@teststartswith
+ {\expandonce\dtl@restA}{\expandonce\dtl@firstB\expandonce\dtl@restB}}%
+ \dtl@donext
+ \fi
+ \else
+ \ifnum\dtl@codeB=-1\relax
+ \protected@edef\dtl@donext{%
+ \noexpand\@dtl@teststartswith
+ {\expandonce\dtl@firstA\expandonce\dtl@restA}{\expandonce\dtl@restB}}%
+ \dtl@donext
+ \else
+ \ifnum\dtl@codeA=\dtl@codeB
+ \protected@edef\dtl@donext{%
+ \noexpand\@dtl@teststartswith{\expandonce\dtl@restA}{\expandonce\dtl@restB}}%
+ \dtl@donext
+ \else
+ \@dtl@conditionfalse
+ \fi
+ \fi
+ \fi
+ }%
+ {%
+% \end{macrocode}
+% The first object in \meta{string1} is a single character, but the
+% first object in \meta{string2} isn't a single character.
+% \begin{macrocode}
+ \protected@edef\dtl@donext{%
+ \noexpand\@dtl@teststartswith
+ {\expandonce\dtl@firstA\expandonce\dtl@restA}%
+ {\expandonce\dtl@firstB\expandonce\dtl@restB}}%
+ \dtl@donext
+ }%
+ }%
+ {%
+% \end{macrocode}
+% Neither object is a single character.
+% \begin{macrocode}
+ \protected@edef\dtl@donext{%
+ \noexpand\@dtl@teststartswith
+ {\expandonce\dtl@firstA\expandonce\dtl@restA}%
+ {\expandonce\dtl@firstB\expandonce\dtl@restB}}%
+ }%
+ }%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLifnumclosedbetween}
+%\begin{definition}
+%\cs{DTLifnumclosedbetween}\marg{num}\marg{min}\marg{max}\marg{true part}\marg{false part}
+%\end{definition}
+% Determines if \meta{min} $\leq$ \meta{num} $\leq$ \meta{max}.
+% \begin{macrocode}
+\newcommand*{\DTLifnumclosedbetween}[5]{%
+ \DTLconverttodecimal{#1}{\@dtl@numi}%
+ \DTLconverttodecimal{#2}{\@dtl@numii}%
+ \DTLconverttodecimal{#3}{\@dtl@numiii}%
+ \DTLifFPclosedbetween{\@dtl@numi}{\@dtl@numii}{\@dtl@numiii}{#4}{#5}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLifstringclosedbetween}
+%\begin{definition}
+%\cs{DTLifstringclosedbetween}\marg{string}\marg{min}\marg{max}\marg{true part}\marg{false part}
+%\end{definition}
+% String comparison (starred version ignores case)
+%\changes{1.01}{2007 Aug 17}{added starred version}
+% \begin{macrocode}
+\newcommand*{\DTLifstringclosedbetween}{%
+ \@ifstar\@sDTLifstringclosedbetween\@DTLifstringclosedbetween
+}
+% \end{macrocode}
+% Unstarred version
+% \begin{macrocode}
+\newcommand*{\@DTLifstringclosedbetween}[5]{%
+ \protected@edef\@dtl@tmpcmp{%
+ \noexpand\dtlcompare{\noexpand\@dtl@tmpcount}{#1}{#2}}%
+ \@dtl@tmpcmp
+ \let\@dtl@dovalue\relax
+ \ifnum\@dtl@tmpcount<0\relax
+ \def\@dtl@dovalue{#5}%
+ \fi
+ \ifx\@dtl@dovalue\relax
+ \protected@edef\@dtl@tmpcmp{%
+ \noexpand\dtlcompare{\noexpand\@dtl@tmpcount}{#1}{#3}}%
+ \@dtl@tmpcmp
+ \ifnum\@dtl@tmpcount>0\relax
+ \def\@dtl@dovalue{#5}%
+ \else
+ \def\@dtl@dovalue{#4}%
+ \fi
+ \fi
+ \@dtl@dovalue
+}
+% \end{macrocode}
+% Starred version
+% \begin{macrocode}
+\newcommand*{\@sDTLifstringclosedbetween}[5]{%
+ \protected@edef\@dtl@tmpcmp{%
+ \noexpand\dtlicompare{\noexpand\@dtl@tmpcount}{#1}{#2}}%
+ \@dtl@tmpcmp
+ \let\@dtl@dovalue\relax
+ \ifnum\@dtl@tmpcount<0\relax
+ \def\@dtl@dovalue{#5}%
+ \fi
+ \ifx\@dtl@dovalue\relax
+ \protected@edef\@dtl@tmpcmp{%
+ \noexpand\dtlicompare{\noexpand\@dtl@tmpcount}{#1}{#3}}%
+ \@dtl@tmpcmp
+ \ifnum\@dtl@tmpcount>0\relax
+ \def\@dtl@dovalue{#5}%
+ \else
+ \def\@dtl@dovalue{#4}%
+ \fi
+ \fi
+ \@dtl@dovalue
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLifclosedbetween}
+%\begin{definition}
+%\cs{DTLifclosedbetween}\marg{arg}\marg{min}\marg{max}\marg{true part}\marg{false part}
+%\end{definition}
+% Does \cs{DTLifnumclosedbetween} if \marg{arg}, \meta{min} and \meta{max} are
+% numerical, otherwise do \cs{DTLifstringclosedbetween}
+% or \cs{DTLifstringclosedbetween*}.
+%\changes{1.01}{2007 Aug 17}{added starred version}
+% \begin{macrocode}
+\newcommand*{\DTLifclosedbetween}{%
+ \@ifstar\@sDTLifclosedbetween\@DTLifclosedbetween
+}
+% \end{macrocode}
+% Unstarred version
+% \begin{macrocode}
+\newcommand*{\@DTLifclosedbetween}[5]{%
+ \dtl@testbothnumerical{#2}{#3}%
+ \if@dtl@condition
+ \dtl@ifsingle{#1}{%
+ \edef\@dtl@tmp{#1}}{%
+ \def\@dtl@tmp{#1}}%
+ \expandafter\@dtl@checknumerical\expandafter{\@dtl@tmp}%
+ \ifnum\@dtl@datatype>0\relax
+ \DTLifnumclosedbetween{#1}{#2}{#3}{#4}{#5}%
+ \else
+ \@DTLifstringclosedbetween{#1}{#2}{#3}{#4}{#5}%
+ \fi
+ \else
+ \@DTLifstringclosedbetween{#1}{#2}{#3}{#4}{#5}%
+ \fi
+}
+% \end{macrocode}
+% Starred version
+% \begin{macrocode}
+\newcommand*{\@sDTLifclosedbetween}[5]{%
+ \dtl@testbothnumerical{#2}{#3}%
+ \if@dtl@condition
+ \dtl@ifsingle{#1}{%
+ \edef\@dtl@tmp{#1}}{%
+ \def\@dtl@tmp{#1}}%
+ \expandafter\@dtl@checknumerical\expandafter{\@dtl@tmp}%
+ \ifnum\@dtl@datatype>0\relax
+ \DTLifnumclosedbetween{#1}{#2}{#3}{#4}{#5}%
+ \else
+ \@sDTLifstringclosedbetween{#1}{#2}{#3}{#4}{#5}%
+ \fi
+ \else
+ \@sDTLifstringclosedbetween{#1}{#2}{#3}{#4}{#5}%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLifnumopenbetween}
+%\begin{definition}
+%\cs{DTLifnumopenbetween}\marg{num}\marg{min}\marg{max}\marg{true part}\marg{false part}
+%\end{definition}
+% Determines if \meta{min} $<$ \meta{num} $<$ \meta{max}.
+% \begin{macrocode}
+\newcommand*{\DTLifnumopenbetween}[5]{%
+ \DTLconverttodecimal{#1}{\@dtl@numi}%
+ \DTLconverttodecimal{#2}{\@dtl@numii}%
+ \DTLconverttodecimal{#3}{\@dtl@numiii}%
+ \DTLifFPopenbetween{\@dtl@numi}{\@dtl@numii}{\@dtl@numiii}{#4}{#5}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLifstringopenbetween}
+%\begin{definition}
+%\cs{DTLifstringopenbetween}\marg{string}\marg{min}\marg{max}\marg{true part}\marg{false part}
+%\end{definition}
+% String comparison (starred version ignores case)
+%\changes{1.01}{2007 Aug 17}{added starred version}
+% \begin{macrocode}
+\newcommand*{\DTLifstringopenbetween}{%
+ \@ifstar\@sDTLifstringopenbetween\@DTLifstringopenbetween
+}
+% \end{macrocode}
+% Unstarred version:
+% \begin{macrocode}
+\newcommand*{\@DTLifstringopenbetween}[5]{%
+ \protected@edef\@dtl@tmpcmp{%
+ \noexpand\dtlcompare{\noexpand\@dtl@tmpcount}{#1}{#2}}%
+ \@dtl@tmpcmp
+ \let\@dtl@dovalue\relax
+ \ifnum\@dtl@tmpcount>0\relax
+ \else
+ \def\@dtl@dovalue{#5}%
+ \fi
+ \ifx\@dtl@dovalue\relax
+ \protected@edef\@dtl@tmpcmp{%
+ \noexpand\dtlcompare{\noexpand\@dtl@tmpcount}{#1}{#3}}%
+ \@dtl@tmpcmp
+ \ifnum\@dtl@tmpcount<0\relax
+ \def\@dtl@dovalue{#4}%
+ \else
+ \def\@dtl@dovalue{#5}%
+ \fi
+ \fi
+ \@dtl@dovalue
+}
+% \end{macrocode}
+% Starred version
+% \begin{macrocode}
+\newcommand*{\@sDTLifstringopenbetween}[5]{%
+ \protected@edef\@dtl@tmpcmp{%
+ \noexpand\dtlicompare{\noexpand\@dtl@tmpcount}{#1}{#2}}%
+ \@dtl@tmpcmp
+ \let\@dtl@dovalue\relax
+ \ifnum\@dtl@tmpcount>0\relax
+ \else
+ \def\@dtl@dovalue{#5}%
+ \fi
+ \ifx\@dtl@dovalue\relax
+ \protected@edef\@dtl@tmpcmp{%
+ \noexpand\dtlicompare{\noexpand\@dtl@tmpcount}{#1}{#3}}%
+ \@dtl@tmpcmp
+ \ifnum\@dtl@tmpcount<0\relax
+ \def\@dtl@dovalue{#4}%
+ \else
+ \def\@dtl@dovalue{#5}%
+ \fi
+ \fi
+ \@dtl@dovalue
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLifopenbetween}
+%\begin{definition}
+%\cs{DTLifopenbetween}\marg{arg}\marg{min}\marg{max}\marg{true part}\marg{false part}
+%\end{definition}
+% Does \cs{DTLifnumopenbetween} if \marg{arg}, \meta{min} and \meta{max} are
+% numerical, otherwise do \cs{DTLifstringopenbetween}
+% or \cs{DTLifstringopenbetween*}.
+%\changes{1.01}{2007 Aug 17}{added starred version}
+% \begin{macrocode}
+\newcommand*{\DTLifopenbetween}{%
+ \@ifstar\@sDTLifopenbetween\@DTLifopenbetween
+}
+% \end{macrocode}
+% Unstarred version
+% \begin{macrocode}
+\newcommand*{\@DTLifopenbetween}[5]{%
+ \dtl@testbothnumerical{#2}{#3}%
+ \if@dtl@condition
+ \dtl@ifsingle{#1}{%
+ \edef\@dtl@tmp{#1}}{%
+ \def\@dtl@tmp{#1}}%
+ \expandafter\@dtl@checknumerical\expandafter{\@dtl@tmp}%
+ \ifnum\@dtl@datatype>0\relax
+ \DTLifnumopenbetween{#1}{#2}{#3}{#4}{#5}%
+ \else
+ \@DTLifstringopenbetween{#1}{#2}{#3}{#4}{#5}%
+ \fi
+ \else
+ \@DTLifstringopenbetween{#1}{#2}{#3}{#4}{#5}%
+ \fi
+}
+% \end{macrocode}
+% Starred version
+% \begin{macrocode}
+\newcommand*{\@sDTLifopenbetween}[5]{%
+ \dtl@testbothnumerical{#2}{#3}%
+ \if@dtl@condition
+ \dtl@ifsingle{#1}{%
+ \edef\@dtl@tmp{#1}}{%
+ \def\@dtl@tmp{#1}}%
+ \expandafter\@dtl@checknumerical\expandafter{\@dtl@tmp}%
+ \ifnum\@dtl@datatype>0\relax
+ \DTLifnumopenbetween{#1}{#2}{#3}{#4}{#5}%
+ \else
+ \@sDTLifstringopenbetween{#1}{#2}{#3}{#4}{#5}%
+ \fi
+ \else
+ \@sDTLifstringopenbetween{#1}{#2}{#3}{#4}{#5}%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLifFPopenbetween}
+%\begin{definition}
+%\cs{DTLifFPopenbetween}\marg{num}\marg{min}\marg{max}\marg{true part}\marg{false part}
+%\end{definition}
+% Determines if \meta{min} $<$ \meta{num} $<$ \meta{max} where
+% all arguments are in standard fixed point notation.
+% (Command name maintained for backward compatibility.)
+% \begin{macrocode}
+\let\DTLifFPopenbetween\dtlifnumopenbetween
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLifFPclosedbetween}
+%\begin{definition}
+%\cs{DTLifFPclosedbetween}\marg{num}\marg{min}\marg{max}\marg{true part}\marg{false part}
+%\end{definition}
+% Determines if \meta{min} $\leq$ \meta{num} $\leq$ \meta{max}.
+% (Command name maintained for backward compatibility.)
+% \begin{macrocode}
+\let\DTLifFPclosedbetween\dtlifnumclosedbetween
+% \end{macrocode}
+%\end{macro}
+%
+%
+%\subsection{ifthen Conditionals}
+% The following commands provide conditionals \cs{DTLis}\ldots\
+% which can be used in \cs{ifthenelse}.
+%
+%\begin{macro}{\dtl@testlt}
+% Command to test if first argument is less than second argument.
+% If either argument is a string, a case sensitive string comparison
+% is used instead.
+% This sets \cs{if@dtl@condition}.
+% \begin{macrocode}
+\newcommand*{\dtl@testlt}[2]{%
+ \DTLiflt{#1}{#2}{\@dtl@conditiontrue}{\@dtl@conditionfalse}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLislt}
+% Provide conditional command for use in \cs{ifthenelse}
+% \begin{macrocode}
+\newcommand*{\DTLislt}[2]{%
+ \TE@throw\noexpand\dtl@testlt{#1}{#2}\noexpand\if@dtl@condition
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@testiclt}
+% Command to test if first argument is less than second argument.
+% If either argument is a string, a case insensitive string comparison
+% is used instead.
+% This sets \cs{if@dtl@condition}.
+% \begin{macrocode}
+\newcommand*{\dtl@testiclt}[2]{%
+ \@sDTLiflt{#1}{#2}{\@dtl@conditiontrue}{\@dtl@conditionfalse}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLisilt}
+% Provide conditional command for use in \cs{ifthenelse}
+%\changes{1.01}{2007 Aug 17}{new}
+% \begin{macrocode}
+\newcommand*{\DTLisilt}[2]{%
+ \TE@throw\noexpand\dtl@testiclt{#1}{#2}\noexpand\if@dtl@condition
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@testgt}
+% Command to test if first argument is greater than second argument.
+% This sets \cs{if@dtl@condition}.
+% \begin{macrocode}
+\newcommand*{\dtl@testgt}[2]{%
+ \DTLifgt{#1}{#2}{\@dtl@conditiontrue}{\@dtl@conditionfalse}%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLisgt}
+% Provide conditional command for use in \cs{ifthenelse}
+% \begin{macrocode}
+\newcommand*{\DTLisgt}[2]{%
+ \TE@throw\noexpand\dtl@testgt{#1}{#2}\noexpand\if@dtl@condition
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@testicgt}
+% Command to test if first argument is greater than second argument
+% (ignores case).
+% This sets \cs{if@dtl@condition}.
+% \begin{macrocode}
+\newcommand*{\dtl@testicgt}[2]{%
+ \@sDTLifgt{#1}{#2}{\@dtl@conditiontrue}{\@dtl@conditionfalse}%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLisigt}
+% Provide conditional command for use in \cs{ifthenelse}
+%\changes{1.01}{2007 Aug 17}{new}
+% \begin{macrocode}
+\newcommand*{\DTLisigt}[2]{%
+ \TE@throw\noexpand\dtl@testicgt{#1}{#2}\noexpand\if@dtl@condition
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@testeq}
+% Command to test if first argument is equal to the second argument.
+% This sets \cs{if@dtl@condition}.
+% \begin{macrocode}
+\newcommand*{\dtl@testeq}[2]{%
+ \DTLifeq{#1}{#2}{\@dtl@conditiontrue}{\@dtl@conditionfalse}%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLiseq}
+% Provide conditional command for use in \cs{ifthenelse}
+% \begin{macrocode}
+\newcommand*{\DTLiseq}[2]{%
+ \TE@throw\noexpand\dtl@testeq{#1}{#2}\noexpand\if@dtl@condition
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@testiceq}
+% Command to test if first number is equal to the second number
+% (ignores case).
+% This sets \cs{if@dtl@condition}.
+% \begin{macrocode}
+\newcommand*{\dtl@testiceq}[2]{%
+ \@sDTLifeq{#1}{#2}{\@dtl@conditiontrue}{\@dtl@conditionfalse}%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLisieq}
+% Provide conditional command for use in \cs{ifthenelse}
+%\changes{1.01}{2007 Aug 17}{new}
+% \begin{macrocode}
+\newcommand*{\DTLisieq}[2]{%
+ \TE@throw\noexpand\dtl@testiceq{#1}{#2}\noexpand\if@dtl@condition
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLisSubString}
+% Tests if second argument is contained in first argument.
+%\changes{1.01}{2007 Aug 17}{new}
+% \begin{macrocode}
+\newcommand*{\DTLisSubString}[2]{%
+ \TE@throw\noexpand\dtl@testifsubstring{#1}{#2}%
+ \noexpand\if@dtl@condition
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLisPrefix}
+% Tests if first argument starts with second argument.
+%\changes{1.01}{2007 Aug 17}{new}
+% \begin{macrocode}
+\newcommand*{\DTLisPrefix}[2]{%
+ \TE@throw\noexpand\dtl@teststartswith{#1}{#2}%
+ \noexpand\if@dtl@condition
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLisinlist}
+% Tests if first argument starts with second argument.
+%\changes{2.23}{2015-07-11}{new}
+% \begin{macrocode}
+\newcommand*{\DTLisinlist}[2]{%
+ \TE@throw\noexpand\dtl@testinlist{#1}{#2}%
+ \noexpand\if@dtl@condition
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@testinlist}
+%\changes{2.23}{2015-07-11}{new}
+% \begin{macrocode}
+\newcommand*{\dtl@testinlist}[2]{%
+ \DTLifinlist{#1}{#2}{\@dtl@conditiontrue}{\@dtl@conditionfalse}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@testnumclosedbetween}
+% Command to test if first number lies between second and third
+% numbers. (End points included, all arguments are fixed point
+% numbers in standard format.) This sets \cs{if@dtl@condition}.
+% \begin{macrocode}
+\newcommand*{\dtl@testnumclosedbetween}[3]{%
+ \DTLifnumclosedbetween{#1}{#2}{#3}%
+ {\@dtl@conditiontrue}{\@dtl@conditionfalse}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+% Provide conditional command for use in \cs{ifthenelse}
+%\begin{macro}{\DTLisnumclosedbetween}
+% \begin{macrocode}
+\newcommand*{\DTLisnumclosedbetween}[3]{%
+ \TE@throw\noexpand\dtl@testnumclosedbetween{#1}{#2}{#3}%
+ \noexpand\if@dtl@condition
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@testnumopenbetween}
+% Command to test if first number lies between second and third
+% numbers. (End points excluded, all arguments are fixed point
+% numbers in standard format.) This sets \cs{if@dtl@condition}.
+% \begin{macrocode}
+\newcommand*{\dtl@testnumopenbetween}[3]{%
+ \DTLifnumopenbetween{#1}{#2}{#3}%
+ {\@dtl@conditiontrue}{\@dtl@conditionfalse}%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLisnumopenbetween}
+% Provide conditional command for use in \cs{ifthenelse}
+% \begin{macrocode}
+\newcommand*{\DTLisnumopenbetween}[3]{%
+ \TE@throw\noexpand\dtl@testnumopenbetween{#1}{#2}{#3}%
+ \noexpand\if@dtl@condition
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@testclosedbetween}
+% Command to test if first value lies between second and third
+% values. (End points included, case sensitive.)
+% This sets \cs{if@dtl@condition}.
+% \begin{macrocode}
+\newcommand*{\dtl@testclosedbetween}[3]{%
+ \DTLifclosedbetween{#1}{#2}{#3}%
+ {\@dtl@conditiontrue}{\@dtl@conditionfalse}%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLisclosedbetween}
+% Provide conditional command for use in \cs{ifthenelse}
+% \begin{macrocode}
+\newcommand*{\DTLisclosedbetween}[3]{%
+ \TE@throw\noexpand\dtl@testclosedbetween{#1}{#2}{#3}%
+ \noexpand\if@dtl@condition
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@testiclosedbetween}
+% Command to test if first value lies between second and third
+% values. (End points included, case ignored.)
+% This sets \cs{if@dtl@condition}.
+% \begin{macrocode}
+\newcommand*{\dtl@testiclosedbetween}[3]{%
+ \@sDTLifclosedbetween{#1}{#2}{#3}%
+ {\@dtl@conditiontrue}{\@dtl@conditionfalse}%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLisiclosedbetween}
+% Provide conditional command for use in \cs{ifthenelse}
+%\changes{1.01}{2007 Aug 17}{new}
+% \begin{macrocode}
+\newcommand*{\DTLisiclosedbetween}[3]{%
+ \TE@throw\noexpand\dtl@testiclosedbetween{#1}{#2}{#3}%
+ \noexpand\if@dtl@condition
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@testopenbetween}
+% Command to test if first value lies between second and third
+% values. (End points excluded, case sensitive.)
+% This sets \cs{if@dtl@condition}.
+% \begin{macrocode}
+\newcommand*{\dtl@testopenbetween}[3]{%
+ \DTLifopenbetween{#1}{#2}{#3}%
+ {\@dtl@conditiontrue}{\@dtl@conditionfalse}%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLisopenbetween}
+% Provide conditional command for use in \cs{ifthenelse}
+% \begin{macrocode}
+\newcommand*{\DTLisopenbetween}[3]{%
+ \TE@throw\noexpand\dtl@testopenbetween{#1}{#2}{#3}%
+ \noexpand\if@dtl@condition
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@testiopenbetween}
+% Command to test if first value lies between second and third
+% values. (End points excluded, case ignored.)
+% This sets \cs{if@dtl@condition}.
+% \begin{macrocode}
+\newcommand*{\dtl@testiopenbetween}[3]{%
+ \@sDTLifopenbetween{#1}{#2}{#3}%
+ {\@dtl@conditiontrue}{\@dtl@conditionfalse}%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLisiopenbetween}
+% Provide conditional command for use in \cs{ifthenelse}
+%\changes{1.01}{2007 Aug 17}{new}
+% \begin{macrocode}
+\newcommand*{\DTLisiopenbetween}[3]{%
+ \TE@throw\noexpand\dtl@testiopenbetween{#1}{#2}{#3}%
+ \noexpand\if@dtl@condition
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLisFPclosedbetween}
+% Keep old command name for backwards compatibility:
+% \begin{macrocode}
+\let\DTLisFPclosedbetween\DTLisnumclosedbetween
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@testopenbetween}
+% Command to test if first number lies between second and third
+% numbers. (End points excluded, all arguments are fixed point
+% numbers in standard format.) This sets \cs{if@dtl@condition}.
+% \begin{macrocode}
+\newcommand*{\dtl@testFPopenbetween}[3]{%
+ \DTLifFPopenbetween{#1}{#2}{#3}%
+ {\@dtl@conditiontrue}{\@dtl@conditionfalse}%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLisFPopenbetween}
+% Provide conditional command for use in \cs{ifthenelse}
+% \begin{macrocode}
+\newcommand*{\DTLisFPopenbetween}[3]{%
+ \TE@throw\noexpand\dtl@testFPopenbetween{#1}{#2}{#3}%
+ \noexpand\if@dtl@condition
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@testFPislt}
+% Command to test if first number is less than second
+% number where both numbers are in standard format.
+% This sets \cs{if@dtl@condition}.
+% \begin{macrocode}
+\newcommand*{\dtl@testFPislt}[2]{%
+ \dtlifnumlt{#1}{#2}%
+ {%
+ \@dtl@conditiontrue
+ }%
+ {%
+ \@dtl@conditionfalse
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLisFPlt}
+% Provide conditional command for use in \cs{ifthenelse}
+% \begin{macrocode}
+\newcommand*{\DTLisFPlt}[2]{%
+ \TE@throw\noexpand\dtl@testFPislt{#1}{#2}%
+ \noexpand\if@dtl@condition
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@testFPisgt}
+% Command to test if first number is greater than second
+% number where both numbers are in standard format.
+% This sets \cs{if@dtl@condition}.
+% \begin{macrocode}
+\newcommand*{\dtl@testFPisgt}[2]{%
+ \dtlifnumgt{#1}{#2}%
+ {%
+ \@dtl@conditiontrue
+ }%
+ {%
+ \@dtl@conditionfalse
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLisFPgt}
+% Provide conditional command for use in \cs{ifthenelse}
+% \begin{macrocode}
+\newcommand*{\DTLisFPgt}[2]{%
+ \TE@throw\noexpand\dtl@testFPisgt{#1}{#2}%
+ \noexpand\if@dtl@condition
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@testFPiseq}
+% Command to test if two numbers are equal, where both numbers
+% are in standard decimal format
+% \begin{macrocode}
+\newcommand*{\dtl@testFPiseq}[2]{%
+ \dtlifnumeq{#1}{#2}%
+ {%
+ \@dtl@conditiontrue
+ }%
+ {%
+ \@dtl@conditionfalse
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLisFPeq}
+% Provide conditional command for use in \cs{ifthenelse}
+% \begin{macrocode}
+\newcommand*{\DTLisFPeq}[2]{%
+ \TE@throw\noexpand\dtl@testFPiseq{#1}{#2}%
+ \noexpand\if@dtl@condition
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@testFPislteq}
+% Command to test if first number is less than or equal to second
+% number where both numbers are in standard format.
+% This sets \cs{if@dtl@condition}.
+% \begin{macrocode}
+\newcommand*{\dtl@testFPislteq}[2]{%
+ \dtlifnumlt{#1}{#2}%
+ {%
+ \@dtl@conditiontrue
+ }%
+ {%
+ \@dtl@conditionfalse
+ }%
+ \if@dtl@condition
+ \else
+ \dtl@testFPiseq{#1}{#2}%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLisFPlteq}
+% Provide conditional command for use in \cs{ifthenelse}
+% \begin{macrocode}
+\newcommand*{\DTLisFPlteq}[2]{%
+ \TE@throw\noexpand\dtl@testFPislteq{#1}{#2}%
+ \noexpand\if@dtl@condition
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@testFPisgteq}
+% Command to test if first number is greater than or equal to second
+% number where both numbers are in standard format.
+% This sets \cs{if@dtl@condition}.
+% \begin{macrocode}
+\newcommand*{\dtl@testFPisgteq}[2]{%
+ \dtlifnumgt{#1}{#2}%
+ {%
+ \@dtl@conditiontrue
+ }%
+ {%
+ \@dtl@conditionfalse
+ }%
+ \if@dtl@condition
+ \else
+ \dtl@testFPiseq{#1}{#2}%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLisFPgteq}
+% Provide conditional command for use in \cs{ifthenelse}
+% \begin{macrocode}
+\newcommand*{\DTLisFPgteq}[2]{%
+ \TE@throw\noexpand\dtl@testFPisgteq{#1}{#2}%
+ \noexpand\if@dtl@condition}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@teststring}
+% Command to test if argument is a string. This sets
+% \cs{if@dtl@condition}
+% \begin{macrocode}
+\newcommand*{\dtl@teststring}[1]{%
+ \DTLifstring{#1}{\@dtl@conditiontrue}{\@dtl@conditionfalse}}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLisstring}
+% Provide conditional command for use in \cs{ifthenelse}
+% \begin{macrocode}
+\newcommand*{\DTLisstring}[1]{%
+ \TE@throw\noexpand\dtl@teststring{#1}\noexpand\if@dtl@condition}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@testnumerical}
+% Command to test if argument is a numerical. This sets
+% \cs{if@dtl@condition}
+% \begin{macrocode}
+\newcommand*{\dtl@testnumerical}[1]{%
+ \DTLifnumerical{#1}{\@dtl@conditiontrue}{\@dtl@conditionfalse}%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLisnumerical}
+% Provide conditional command for use in \cs{ifthenelse}
+% \begin{macrocode}
+\newcommand*{\DTLisnumerical}[1]{%
+ \TE@throw\noexpand\dtl@testnumerical{#1}\noexpand\if@dtl@condition}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@testint}
+% Command to test if argument is an integer. This sets
+% \cs{if@dtl@condition}
+% \begin{macrocode}
+\newcommand*{\dtl@testint}[1]{%
+ \DTLifint{#1}{\@dtl@conditiontrue}{\@dtl@conditionfalse}}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLisint}
+% Provide conditional command for use in \cs{ifthenelse}
+% \begin{macrocode}
+\newcommand*{\DTLisint}[1]{%
+ \TE@throw\noexpand\dtl@testint{#1}\noexpand\if@dtl@condition}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@testreal}
+% Command to test if argument is a real. This sets
+% \cs{if@dtl@condition}
+% \begin{macrocode}
+\newcommand*{\dtl@testreal}[1]{%
+ \DTLifreal{#1}{\@dtl@conditiontrue}{\@dtl@conditionfalse}}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLisreal}
+% Provide conditional command for use in \cs{ifthenelse}
+% \begin{macrocode}
+\newcommand*{\DTLisreal}[1]{%
+ \TE@throw\noexpand\dtl@testreal{#1}\noexpand\if@dtl@condition}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@testcurrency}
+% Command to test if argument is a currency. This sets
+% \cs{if@dtl@condition}
+% \begin{macrocode}
+\newcommand*{\dtl@testcurrency}[1]{%
+ \DTLifcurrency{#1}{\@dtl@conditiontrue}{\@dtl@conditionfalse}}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLiscurrency}
+% Provide conditional command for use in \cs{ifthenelse}
+% \begin{macrocode}
+\newcommand*{\DTLiscurrency}[1]{%
+ \TE@throw\noexpand\dtl@testcurrency{#1}\noexpand\if@dtl@condition}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@testcurrencyunit}
+% Command to test if argument is a currency with given unit. This sets
+% \cs{if@dtl@condition}
+% \begin{macrocode}
+\newcommand*{\dtl@testcurrencyunit}[2]{%
+ \DTLifcurrencyunit{#1}{#2}{\@dtl@conditiontrue}{\@dtl@conditionfalse}}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLiscurrencyunit}
+% Provide conditional command for use in \cs{ifthenelse}
+% \begin{macrocode}
+\newcommand*{\DTLiscurrencyunit}[2]{%
+ \TE@throw\noexpand\dtl@testcurrencyunit{#1}{#2}%
+ \noexpand\if@dtl@condition
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\section{Loops}
+%\begin{macro}{\dtlbreak}
+% Break out of loop at the end of current iteration.
+% \begin{macrocode}
+\newcommand*{\dtlbreak}{%
+ \PackageError{datatool}{Can't break out of anything}{}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlforint}
+%\begin{definition}
+%\cs{dtlforint}\meta{ct}=\meta{start}\cs{to}\meta{end}\cs{step}%
+%\meta{inc}\cs{do}\marg{body}
+%\end{definition}
+% \meta{ct} is a count register, \meta{start}, \meta{end} and
+% \meta{inc} are integers.
+% Group if nested or use \cs{dtlgforint}.
+% An infinite loop may result if \meta{inc}$=0$ and
+% \meta{start} $\le$ \meta{end} and \cs{dtlbreak} isn't used.
+% \begin{macrocode}
+\long\def\dtlforint#1=#2\to#3\step#4\do#5{%
+% \end{macrocode}
+% Make a copy of old version of break function
+% \begin{macrocode}
+ \let\@dtl@orgbreak\dtlbreak
+ \def\@dtl@endloophook{}%
+% \end{macrocode}
+% Setup break function for the loop (sets \meta{ct} to \meta{end}
+% at the end of the current iteration).
+% \begin{macrocode}
+ \def\dtlbreak{\def\@dtl@endloophook{#1=#3}}%
+% \end{macrocode}
+% Initialise \meta{ct}
+% \begin{macrocode}
+ #1=#2\relax
+% \end{macrocode}
+% Check if the steps are positive or negative.
+% \begin{macrocode}
+ \ifnum#4<0\relax
+% \end{macrocode}
+% Counting down
+% \begin{macrocode}
+ \whiledo{\(#1>#3\)\TE@or\(#1=#3\)}%
+ {%
+ #5%
+ \@dtl@endloophook
+ \advance#1 by #4\relax
+ }%
+ \else
+% \end{macrocode}
+% Counting up
+% \begin{macrocode}
+ \whiledo{\(#1<#3\)\TE@or\(#1=#3\)}%
+ {%
+ #5%
+ \@dtl@endloophook
+ \advance#1 by #4\relax
+ }%
+ \fi
+% \end{macrocode}
+% Restore break function.
+% \begin{macrocode}
+ \let\dtlbreak\@dtl@orgbreak
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@foreach@level}
+% Count register to keep track of global nested loops.
+% \begin{macrocode}
+\newcount\@dtl@foreach@level
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlgforint}
+%\begin{definition}
+%\cs{dtlgforint}\meta{ct}=\meta{start}\cs{to}\meta{end}\cs{step}%
+%\meta{inc}\cs{do}\marg{body}
+%\end{definition}
+% \meta{ct} is a count register, \meta{start}, \meta{end} and
+% \meta{inc} are integers.
+% An infinite loop may result if \meta{inc}=0 and \meta{start} $\le$
+% \meta{end} and \cs{dtlbreak} isn't used.
+% \begin{macrocode}
+\long\def\dtlgforint#1=#2\to#3\step#4\do#5{%
+% \end{macrocode}
+% Initialise
+% \begin{macrocode}
+ \global#1=#2\relax
+% \end{macrocode}
+% Increment level counter to allow for nested loops
+% \begin{macrocode}
+ \global\advance\@dtl@foreach@level by 1\relax
+% \end{macrocode}
+% Set up end loop hook
+% \begin{macrocode}
+ \expandafter\global\expandafter
+ \let\csname @dtl@endhook@\the\@dtl@foreach@level\endcsname
+ \relax
+% \end{macrocode}
+% Set up the break function:
+% Copy current definition
+% \begin{macrocode}
+ \expandafter\global\expandafter
+ \let\csname @dtl@break@\the\@dtl@foreach@level\endcsname
+ \dtlbreak
+% \end{macrocode}
+% Set up definition for this level (sets <ct> to <end> at the end
+% of the current iteration).
+% \begin{macrocode}
+ \gdef\dtlbreak{\expandafter
+ \gdef\csname @dtl@endhook@\the\@dtl@foreach@level\endcsname{%
+ #1=#3}}%
+% \end{macrocode}
+% check the direction
+% \begin{macrocode}
+ \ifnum#4<0\relax
+% \end{macrocode}
+% Counting down
+% \begin{macrocode}
+ \whiledo{\(#1>#3\)\TE@or\(#1=#3\)}%
+ {%
+ #5%
+ \csname @dtl@endhook@\the\@dtl@foreach@level\endcsname
+ \global\advance#1 by #4\relax
+ }%
+ \else
+% \end{macrocode}
+% Counting up (or 0 increments)
+% \begin{macrocode}
+ \whiledo{\(#1<#3\)\TE@or\(#1=#3\)}%
+ {%
+ #5%
+ \csname @dtl@endhook@\the\@dtl@foreach@level\endcsname
+ \global\advance#1 by #4\relax
+ }%
+ \fi
+% \end{macrocode}
+% Restore break function
+% \begin{macrocode}
+ \expandafter\global\expandafter\let\expandafter\dtlbreak
+ \csname @dtl@break@\the\@dtl@foreach@level\endcsname
+% \end{macrocode}
+% Decrement level counter
+% \begin{macrocode}
+ \global\advance\@dtl@foreach@level by -1\relax
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{environment}{dtlenvgforint}
+% Environment form (contents are gathered, so verbatim can't be
+% used):
+% \begin{macrocode}
+\newenvironment{dtlenvgforint}[1]%
+{%
+ \def\@dtlenvgforint@arg{#1}%
+ \long@collect@body\@do@dtlenvgforint
+}%
+{}
+\newcommand{\@do@dtlenvgforint}[1]{%
+ \expandafter\dtlgforint\@dtlenvgforint@arg\do{#1}%
+}
+% \end{macrocode}
+%\end{environment}
+%\iffalse
+% \begin{macrocode}
+%</datatool-base.sty>
+% \end{macrocode}
+%\fi
+%\iffalse
+% \begin{macrocode}
+%<*datatool-fp.sty>
+% \end{macrocode}
+%\fi
+%\chapter{datatool-fp.sty}\label{sec:code:datatool-fp}
+% Definitions of fixed-point commands that use the \sty{fp} package.
+% \begin{macrocode}
+\NeedsTeXFormat{LaTeX2e}
+\ProvidesPackage{datatool-fp}[2018/12/07 v2.31 (NLCT)]
+% \end{macrocode}
+% Required packages:
+% \begin{macrocode}
+\RequirePackage{xkeyval}
+\RequirePackage{fp}
+\RequirePackage{datatool-base}
+% \end{macrocode}
+%\begin{option}{verbose}
+% Switch \sty{fp} messages on or off
+% \begin{macrocode}
+\define@choicekey{datatool-fp}{verbose}[\val\nr]{true,false}[true]{%
+ \ifcase\nr\relax
+ \FPmessagestrue
+ \or
+ \FPmessagesfalse
+ \fi
+}
+\let\ifFPmessages\ifdtlverbose
+% \end{macrocode}
+%\end{option}
+%
+% Process package options:
+% \begin{macrocode}
+\ProcessOptionsX
+% \end{macrocode}
+%
+% Define commands that are needed before loading
+% \sty{datatool-base}:
+% \begin{macrocode}
+\providecommand*{\@dtl@mathprocessor}{fp}
+% \end{macrocode}
+%\begin{macro}{\dtlifnumeq}
+%\begin{definition}
+%\cs{dtlifnumeq}\marg{num1}\marg{num2}\marg{true part}\marg{false
+%part}
+%\end{definition}
+% Does \meta{true part} if \meta{num1}=\meta{num2}, otherwise does
+% \meta{false part}. The numbers must use a full stop as the decimal
+% character and no number group separator.
+% \begin{macrocode}
+\newcommand*{\dtlifnumeq}[4]{%
+ \FPifeq{#1}{#2}%
+ #3%
+ \else
+ #4%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+% If \pkgopt{verbose} option set, switch on \pkgopt{verbose} for
+% \sty{datatool-base} as well:
+% \begin{macrocode}
+\let\ifdtlverbose\ifFPmessages
+% \end{macrocode}
+%
+%\section{Comparison Commands}
+%
+%\begin{macro}{\dtlifnumlt}
+%\begin{definition}
+%\cs{dtlifnumlt}\marg{num1}\marg{num2}\marg{true part}\marg{false
+%part}
+%\end{definition}
+% Does \meta{true part} if \meta{num1} \textless \meta{num2}, otherwise does
+% \meta{false part}. The numbers must use a full stop as the decimal
+% character and no number group separator.
+% \begin{macrocode}
+\newcommand*{\dtlifnumlt}[4]{%
+ \FPiflt{#1}{#2}%
+ #3%
+ \else
+ #4%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlifnumgt}
+%\begin{definition}
+%\cs{dtlifnumgt}\marg{num1}\marg{num2}\marg{true part}\marg{false
+%part}
+%\end{definition}
+% Does \meta{true part} if \meta{num1} \textgreater \meta{num2}, otherwise does
+% \meta{false part}. The numbers must use a full stop as the decimal
+% character and no number group separator.
+% \begin{macrocode}
+\newcommand*{\dtlifnumgt}[4]{%
+ \FPifgt{#1}{#2}%
+ #3%
+ \else
+ #4%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlifnumopenbetween}
+%\begin{definition}
+%\cs{dtlifnumopenbetween}\marg{num}\marg{min}\marg{max}\marg{true part}\marg{false part}
+%\end{definition}
+% Determines if \meta{min} $<$ \meta{num} $<$ \meta{max} where
+% all arguments are in standard fixed point notation.
+% \begin{macrocode}
+\newcommand*{\dtlifnumopenbetween}[5]{%
+ \let\@dtl@dovalue\relax
+ \dtlifnumgt{#1}{#2}%
+ {}%
+ {%
+ \def\@dtl@dovalue{#5}%
+ }%
+ \dtlifnumlt{#1}{#3}%
+ {%
+ \ifx\@dtl@dovalue\relax
+ \def\@dtl@dovalue{#4}%
+ \fi
+ }%
+ {%
+ \def\@dtl@dovalue{#5}%
+ }%
+ \@dtl@dovalue
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlifnumclosedbetween}
+%\begin{definition}
+%\cs{dtlifnumclosedbetween}\marg{num}\marg{min}\marg{max}\marg{true part}\marg{false part}
+%\end{definition}
+% Determines if \meta{min} $\leq$ \meta{num} $\leq$ \meta{max} where
+% all arguments are in standard fixed point notation.
+% \begin{macrocode}
+\newcommand*{\dtlifnumclosedbetween}[5]{%
+ \let\@dtl@dovalue\relax
+ \dtlifnumgt{#1}{#2}%
+ {}%
+ {%
+ \dtlifnumeq{#1}{#2}%
+ {%
+ \def\@dtl@dovalue{#4}%
+ }%
+ {%
+ \def\@dtl@dovalue{#5}%
+ }%
+ }%
+ \dtlifnumlt{#1}{#3}%
+ {%
+ \ifx\@dtl@dovalue\relax
+ \def\@dtl@dovalue{#4}%
+ \fi
+ }%
+ {%
+ \dtlifnumeq{#1}{#3}%
+ {%
+ \def\@dtl@dovalue{#4}%
+ }%
+ {%
+ \def\@dtl@dovalue{#5}%
+ }%
+ }%
+ \@dtl@dovalue
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\section{Functions}
+%
+%\begin{macro}{\dtladd}
+% Adds two numbers using fp.
+% \begin{macrocode}
+\newcommand*{\dtladd}[3]{%
+ \FPadd{#1}{#2}{#3}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlsub}
+% Subtracts two numbers using fp.
+% \begin{macrocode}
+\newcommand*{\dtlsub}[3]{%
+ \FPsub{#1}{#2}{#3}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlmul}
+% Multiplies two numbers using fp.
+% \begin{macrocode}
+\newcommand*{\dtlmul}[3]{%
+ \FPmul{#1}{#2}{#3}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtldiv}
+% Divides two numbers using fp.
+% \begin{macrocode}
+\newcommand*{\dtldiv}[3]{%
+ \FPdiv{#1}{#2}{#3}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlroot}
+% Square root using fp.
+% \begin{macrocode}
+\newcommand*{\dtlroot}[2]{%
+ \FProot{#1}{#2}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlround}
+% Rounds using fp.
+% \begin{macrocode}
+\newcommand*{\dtlround}[3]{%
+ \FPround{#1}{#2}{#3}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtltrunc}
+% Truncates using fp.
+% (Third argument is the number of digits.)
+% \begin{macrocode}
+\newcommand*{\dtltrunc}[3]{%
+ \FPtrunc{#1}{#2}{#3}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlclip}
+% \begin{macrocode}
+\newcommand*{\dtlclip}[2]{%
+ \FPclip{#1}{#2}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlmin}
+% Minimum of two numbers using fp.
+% \begin{macrocode}
+\newcommand*{\dtlmin}[3]{%
+ \FPmin{#1}{#2}{#3}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlmax}
+% Maximum of two numbers using fp.
+% \begin{macrocode}
+\newcommand*{\dtlmax}[3]{%
+ \FPmax{#1}{#2}{#3}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlabs}
+% Absolute value using fp.
+% \begin{macrocode}
+\newcommand*{\dtlabs}[2]{%
+ \FPabs{#1}{#2}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlneg}
+% Negative of a value using fp.
+% \begin{macrocode}
+\newcommand*{\dtlneg}[2]{%
+ \FPneg{#1}{#2}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\iffalse
+% \begin{macrocode}
+%</datatool-fp.sty>
+% \end{macrocode}
+%\fi
+%\iffalse
+% \begin{macrocode}
+%<*datatool-pgfmath.sty>
+% \end{macrocode}
+%\fi
+%\chapter{datatool-pgfmath.sty}\label{sec:code:datatool-pgfmath}
+% Definitions of fixed-point commands that use the \sty{pgfmath} package.
+% \begin{macrocode}
+\NeedsTeXFormat{LaTeX2e}
+\ProvidesPackage{datatool-pgfmath}[2018/12/07 v2.31 (NLCT)]
+% \end{macrocode}
+% Required packages:
+% \begin{macrocode}
+\RequirePackage{xkeyval}
+\RequirePackage{pgfrcs,pgfkeys,pgfmath}
+% \end{macrocode}
+%
+% Process package options:
+% \begin{macrocode}
+\ProcessOptionsX
+% \end{macrocode}
+%
+% Define commands that are needed before loading
+% \sty{datatool-base}:
+% \begin{macrocode}
+\providecommand*{\@dtl@mathprocessor}{pgfmath}
+% \end{macrocode}
+%\begin{macro}{\dtlifnumeq}
+%\begin{definition}
+%\cs{dtlifnumeq}\marg{num1}\marg{num2}\marg{true part}\marg{false
+%part}
+%\end{definition}
+% Does \meta{true part} if \meta{num1}=\meta{num2}, otherwise does
+% \meta{false part}. The numbers must use a full stop as the decimal
+% character and no number group separator. The \verb|\number0| part
+% allows an empty argument to be treated as zero. (\cs{number}
+% required to prevent a zero prefix indicating an octal number.)
+%\changes{2.12}{2012-11-30}{fixed bug causing premature expansion}
+%\changes{2.26}{2016-07-20}{added \cs{number}}
+% \begin{macrocode}
+\newcommand*{\dtlifnumeq}[4]{%
+ \def\@dtl@truepart{#3}%
+ \def\@dtl@falsepart{#4}%
+ \pgfmathifthenelse{\number0#1==\number0#2}%
+ {"\noexpand\@dtl@truepart"}{"\noexpand\@dtl@falsepart"}%
+ \pgfmathresult
+}
+% \end{macrocode}
+%\end{macro}
+%
+% Load base package:
+% \begin{macrocode}
+\RequirePackage{datatool-base}
+% \end{macrocode}
+%
+%\section{Comparison Commands}
+%\begin{macro}{\dtlifnumlt}
+%\begin{definition}
+%\cs{dtlifnumlt}\marg{num1}\marg{num2}\marg{true part}\marg{false
+%part}
+%\end{definition}
+% Does \meta{true part} if \meta{num1} \textless \meta{num2}, otherwise does
+% \meta{false part}. The numbers must use a full stop as the decimal
+% character and no number group separator.
+%\changes{2.12}{2012-11-30}{fixed bug causing premature expansion}
+%\changes{2.26}{2016-07-20}{added \cs{number}}
+% \begin{macrocode}
+\newcommand*{\dtlifnumlt}[4]{%
+ \def\@dtl@truepart{#3}%
+ \def\@dtl@falsepart{#4}%
+ \pgfmathifthenelse{\number0#1 < \number0#2}%
+ {"\noexpand\@dtl@truepart"}{"\noexpand\@dtl@falsepart"}%
+ \pgfmathresult
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlifnumgt}
+%\begin{definition}
+%\cs{dtlifnumgt}\marg{num1}\marg{num2}\marg{true part}\marg{false
+%part}
+%\end{definition}
+% Does \meta{true part} if \meta{num1} \textgreater \meta{num2}, otherwise does
+% \meta{false part}. The numbers must use a full stop as the decimal
+% character and no number group separator.
+%\changes{2.12}{2012-11-30}{fixed bug causing premature expansion}
+%\changes{2.26}{2016-07-20}{added \cs{number}}
+% \begin{macrocode}
+\newcommand*{\dtlifnumgt}[4]{%
+ \def\@dtl@truepart{#3}%
+ \def\@dtl@falsepart{#4}%
+ \pgfmathifthenelse{\number0#1 > \number0#2}%
+ {"\noexpand\@dtl@truepart"}{"\noexpand\@dtl@falsepart"}%
+ \pgfmathresult
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlifnumopenbetween}
+%\begin{definition}
+%\cs{dtlifnumopenbetween}\marg{num}\marg{min}\marg{max}\marg{true part}\marg{false part}
+%\end{definition}
+% Determines if \meta{min} $<$ \meta{num} $<$ \meta{max} where
+% all numerical arguments are in standard fixed point notation.
+%\changes{2.12}{2012-11-30}{fixed bug causing premature expansion}
+%\changes{2.26}{2016-07-20}{added \cs{number}}
+% \begin{macrocode}
+\newcommand*{\dtlifnumopenbetween}[5]{%
+ \def\@dtl@truepart{#4}%
+ \def\@dtl@falsepart{#5}%
+ \pgfmathifthenelse
+ {(\number0#2 < \number0#1) && (\number0#1 < \number0#3)}%
+ {"\noexpand\@dtl@truepart"}{"\noexpand\@dtl@falsepart"}%
+ \pgfmathresult
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlifnumclosedbetween}
+%\begin{definition}
+%\cs{dtlifnumclosedbetween}\marg{num}\marg{min}\marg{max}\marg{true part}\marg{false part}
+%\end{definition}
+% Determines if \meta{min} $\leq$ \meta{num} $\leq$ \meta{max} where
+% all numerical arguments are in standard fixed point notation.
+%\changes{2.12}{2012-11-30}{fixed bug causing premature expansion}
+%\changes{2.26}{2016-07-20}{added \cs{number}}
+% \begin{macrocode}
+\newcommand*{\dtlifnumclosedbetween}[5]{%
+ \def\@dtl@truepart{#4}%
+ \def\@dtl@falsepart{#5}%
+ \pgfmathifthenelse
+ {(\number0#2 <= \number0#1) && (\number0#1 <= \number0#3)}
+ {"\noexpand\@dtl@truepart"}{"\noexpand\@dtl@falsepart"}%
+ \pgfmathresult
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\section{Functions}
+%\begin{macro}{\dtladd}
+% Adds two numbers using PGF math engine.
+% \begin{macrocode}
+\newcommand*{\dtladd}[3]{%
+ \pgfmathadd{#2}{#3}%
+ \let#1\pgfmathresult
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlsub}
+% Subtracts two numbers using PGF math engine.
+% \begin{macrocode}
+\newcommand*{\dtlsub}[3]{%
+ \pgfmathsubtract{#2}{#3}%
+ \let#1\pgfmathresult
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlmul}
+% Multiplies two numbers using PGF math engine.
+% \begin{macrocode}
+\newcommand*{\dtlmul}[3]{%
+ \pgfmathmultiply{#2}{#3}%
+ \let#1\pgfmathresult
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtldiv}
+% Divides two numbers using PGF math engine.
+% \begin{macrocode}
+\newcommand*{\dtldiv}[3]{%
+ \pgfmathdivide{#2}{#3}%
+ \let#1\pgfmathresult
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlroot}
+% Square root using PGF math engine.
+% \begin{macrocode}
+\newcommand*{\dtlroot}[2]{%
+ \pgfmathsqrt{#2}%
+ \let#1\pgfmathresult
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlround}
+% Rounds using PGF math engine.
+%\changes{2.26}{2016-07-20}{fixed bug cause by rounding}
+% \begin{macrocode}
+\newcommand*{\dtlround}[3]{%
+ \ifnum#3=0\relax
+ \pgfmathparse{int(round(#2))}%
+ \let#1\pgfmathresult
+ \else
+ \pgfmathparse{int(10^#3)}%
+ \let\dtl@tmpshift\pgfmathresult
+% \end{macrocode}
+%Need to be careful not to trigger the dimension too large error,
+%so this is a bit convoluted.
+% \begin{macrocode}
+ \pgfmathparse{int(floor(#2))}%
+ \let\dtl@int@round\pgfmathresult
+ \pgfmathparse{int(round((#2-\dtl@int@round) * \dtl@tmpshift))}%
+% \end{macrocode}
+%\changes{2.26}{2016-07-20}{fixed bug caused by rounding errors}
+% This bit is awkward because simply dividing by multiples
+% of 10 in pgfmath can cause rounding errors, so need to
+% employ another method.
+% \begin{macrocode}
+ \@dtl@tmpcount=0\relax
+ \expandafter\@dtl@countdigits\pgfmathresult.\relax
+ \advance\@dtl@tmpcount by -#3\relax
+ \def\@dtl@intpart{}%
+ \def\@dtl@fracpart{}%
+ \expandafter\@dtl@gatherintfrac\pgfmathresult\relax
+ \edef\@dtl@intpart{\number\numexpr\dtl@int@round
+ +\number0\@dtl@intpart}%
+ \edef#1{\@dtl@intpart.\@dtl@fracpart}%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@gatherintfrac}
+%\changes{2.26}{2016-07-20}{new}
+% \begin{macrocode}
+\newcommand*{\@dtl@gatherintfrac}[1]{%
+ \ifx\relax#1\relax
+ \else
+ \advance\@dtl@tmpcount by -1\relax
+ \ifnum\@dtl@tmpcount<0\relax
+ \edef\@dtl@fracpart{\@dtl@fracpart#1}%
+ \else
+ \edef\@dtl@intpart{\@dtl@intpart#1}%
+ \fi
+ \expandafter\@dtl@gatherintfrac
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtltrunc}
+% Truncates using PGF math engine.
+% (Third argument is the number of digits.)
+%\changes{2.26}{2016-07-20}{new}
+%This suffers from the same problems as \cs{dtlround}. Can
+% cause dimension too large error or rounding errors.
+% \begin{macrocode}
+\newcommand*{\dtltrunc}[3]{%
+ \ifnum#3=0\relax
+ \pgfmathparse{int(floor(#2))}%
+ \let#1\pgfmathresult
+ \else
+ \pgfmathparse{int(10^#3)}%
+ \let\dtl@tmpshift\pgfmathresult
+% \end{macrocode}
+%Need to be careful not to trigger the dimension too large error,
+%so this is a bit convoluted.
+% \begin{macrocode}
+ \pgfmathparse{int(floor(#2))}%
+ \let\dtl@int@trunc\pgfmathresult
+ \pgfmathparse{int(floor((#2-\dtl@int@trunc) * \dtl@tmpshift))}%
+% \end{macrocode}
+%\changes{2.26}{2016-07-20}{fixed bug caused by rounding errors}
+% This bit is awkward because simply dividing by multiples
+% of 10 in pgfmath can cause rounding errors, so need to
+% employ another method.
+% \begin{macrocode}
+ \@dtl@tmpcount=0\relax
+ \expandafter\@dtl@countdigits\pgfmathresult.\relax
+ \advance\@dtl@tmpcount by -#3\relax
+ \def\@dtl@intpart{}%
+ \def\@dtl@fracpart{}%
+ \expandafter\@dtl@gatherintfrac\pgfmathresult\relax
+ \edef\@dtl@intpart{\number\numexpr\dtl@int@trunc
+ +\number0\@dtl@intpart}%
+ \edef#1{\@dtl@intpart.\@dtl@fracpart}%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlclip}
+% There isn't a clip in pgfmath as it seems to automatically clip.
+% \begin{macrocode}
+\newcommand*{\dtlclip}[2]{%
+ \edef#1{#2}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlmin}
+% Minimum of two numbers using PGF math engine.
+% \begin{macrocode}
+\newcommand*{\dtlmin}[3]{%
+ \pgfmathmin{#2}{#3}%
+ \let#1\pgfmathresult
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlmax}
+% Maximum of two numbers using PGF math engine.
+% \begin{macrocode}
+\newcommand*{\dtlmax}[3]{%
+ \pgfmathmax{#2}{#3}%
+ \let#1\pgfmathresult
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlabs}
+% Absolute value using PGF math engine.
+% \begin{macrocode}
+\newcommand*{\dtlabs}[2]{%
+ \pgfmathabs{#2}%
+ \let#1\pgfmathresult
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlneg}
+% Negative of a value using PGF math engine.
+% \begin{macrocode}
+\newcommand*{\dtlneg}[2]{%
+ \pgfmathmul{-1}{#2}%
+ \let#1\pgfmathresult
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\iffalse
+% \begin{macrocode}
+%</datatool-pgfmath.sty>
+% \end{macrocode}
+%\fi
+%\iffalse
+% \begin{macrocode}
+%<*datatool.sty>
+% \end{macrocode}
+%\fi
+%\chapter{datatool.sty}
+%\label{sec:code:datatool}
+%\section{Package Declaration}
+% \begin{macrocode}
+\NeedsTeXFormat{LaTeX2e}
+\ProvidesPackage{datatool}[2018/12/07 v2.31 (NLCT)]
+% \end{macrocode}
+% Load required packages:
+% \begin{macrocode}
+\RequirePackage{xkeyval}
+\RequirePackage{ifthen}
+\RequirePackage{xfor}
+\RequirePackage{substr}
+\RequirePackage{etoolbox}
+% \end{macrocode}
+%\changes{2.0}{2009 February 27}{added etex as a required package}
+%\changes{2.23}{2015-07-11}{removed etex as a required package}
+%
+%\section{Package Options}
+%\begin{macro}{\@dtl@separator}
+% The data separator character (comma by default) is stored in
+% \cs{@dtl@separator}.
+% This is the separator used in external data files, not in the
+% \LaTeX\ code, which always uses a comma separator.
+% \begin{macrocode}
+\newcommand*{\@dtl@separator}{,}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLsetseparator}
+%\begin{definition}
+%\cs{DTLsetseparator}\marg{char}
+%\end{definition}
+% The sets \cs{@dtl@separator}, and constructs the relevant macros
+% that require this character to be hardcoded into their definition.
+% \begin{macrocode}
+\newcommand*{\DTLsetseparator}[1]{%
+ \renewcommand*{\@dtl@separator}{#1}%
+ \@dtl@construct@lopoffs
+}
+% \end{macrocode}
+%\end{macro}
+\begingroup
+\catcode`\^^I12
+%\begin{macro}{\DTLsettabseparator}
+%\cs{DTLsettabseparator} makes it easier to set a tab separator.
+%\changes{2.10}{2012-07-18}{changed tab character to
+%\texttt{\textasciicircum\textasciicircum I}}
+% \begin{macrocode}
+\gdef\DTLsettabseparator{%
+ \catcode`\^^I12
+ \DTLsetseparator{^^I}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLmaketabspace}
+%\changes{2.23}{2015-07-11}{restores tab catcode to 10}
+% \begin{macrocode}
+\gdef\DTLmaketabspace{%
+ \catcode`\^^I10\relax
+}
+\endgroup
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@delimiter}
+% The data delimiter character (double quote by default) is stored
+% in \cs{@dtl@delimiter}. This is used in external data files, not
+% in the \LaTeX\ code.
+% \begin{macrocode}
+\begingroup
+\catcode`\"12\relax
+\gdef\@dtl@delimiter{"}
+\endgroup
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLsetdelimiter}
+%\begin{definition}
+%\cs{DTLsetdelimiter}\marg{char}
+%\end{definition}
+% This sets the delimiter.
+% \begin{macrocode}
+\newcommand*\DTLsetdelimiter[1]{%
+ \renewcommand*{\@dtl@delimiter}{#1}%
+ \@dtl@construct@lopoffs
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@construct@lopoff}
+%\begin{definition}
+%\cs{@dtl@construct@lopoff}\meta{separator char}\meta{delimiter char}
+%\end{definition}
+% This defines
+%\begin{definition}
+% \cs{@dtl@lopoff}\meta{first element}\meta{sep}\meta{rest of list}\cs{to}\meta{cmd1}\meta{cmd2}
+%\end{definition}
+%for the current separator and delimiter.
+%\changes{2.30}{2018-04-16}{removed spurious spaces}
+% \begin{macrocode}
+\edef\@dtl@construct@lopoff#1#2{%
+ \noexpand\long
+ \noexpand\def\noexpand\@dtl@lopoff#1##1##2\noexpand\to##3##4{%
+ \noexpand\ifx#2##1\noexpand\relax
+ \noexpand\ifstrempty{##1}%
+ {\noexpand\@dtl@qlopoff#1{}##2\noexpand\to##3##4\relax}%
+ {%
+ \noexpand\dtl@ifsingle{##1}%
+ {\noexpand\@dtl@qlopoff#1##1##2\noexpand\to##3##4\relax}%
+ {\noexpand\@dtl@qlopoff#1{##1}##2\noexpand\to##3##4\relax}%
+ }%
+ \noexpand\else
+ \noexpand\ifstrempty{##1}%
+ {\noexpand\@dtl@lop@ff#1{}##2\noexpand\to##3##4\relax}%
+ {%
+ \noexpand\dtl@ifsingle{##1}%
+ {\noexpand\@dtl@lop@ff#1##1##2\noexpand\to##3##4\relax}%
+ {\noexpand\@dtl@lop@ff#1{##1}##2\noexpand\to##3##4\relax}%
+ }%
+ \noexpand\fi
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@construct@qlopoff}
+%\begin{definition}
+% \cs{@dtl@construct@qlopoff}\meta{separator char}\meta{delimiter char}
+%\end{definition}
+% This constructs \cs{@dtl@qlopoff} to be used
+% when the entry is surrounded by the current delimiter value.
+% \begin{macrocode}
+\edef\@dtl@construct@qlopoff#1#2{%
+ \noexpand\long
+ \noexpand\def\noexpand\@dtl@qlopoff#1#2##1#2#1##2\noexpand\to##3##4{%
+ \noexpand\def##4{##1}%
+% \end{macrocode}
+% Replace any escaped delimiters
+%\changes{2.10}{2012-07-18}{Added code to replace escaped delimiters}
+% \begin{macrocode}
+ \noexpand\DTLsubstituteall{##4}{#2#2}{#2}%
+ \noexpand\edef\noexpand\@dtl@dosubs{%
+ \noexpand\noexpand\noexpand\DTLsubstituteall{\noexpand\noexpand##4}%
+ {\noexpand\expandafter\noexpand\noexpand\noexpand\csname#2\noexpand\endcsname#2}%
+ {\noexpand\expandafter\noexpand\noexpand\noexpand\csname#2\noexpand\endcsname}%
+ }%
+ \noexpand\@dtl@dosubs
+ \noexpand\def##3{#1##2}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@dtl@construct@lop@ff}
+%\begin{definition}
+% \cs{@dtl@construct@lop@ff}\meta{separator char}
+%\end{definition}
+% This constructs \cs{@dtl@lop@ff} to be used when
+% the entry isn't surrouded by the delimiter.
+% \begin{macrocode}
+\edef\@dtl@construct@lop@ff#1{%
+ \noexpand\long
+ \noexpand\def\noexpand\@dtl@lop@ff#1##1#1##2\noexpand\to##3##4{%
+ \noexpand\def##4{##1}%
+ \noexpand\def##3{#1##2}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@construct@lopoffs}
+%\begin{definition}
+%\cs{@dtl@construct@lopoffs}
+%\end{definition}
+% This constructs all the lopoff macros
+% using the given separator and delimiter characters.
+% \begin{macrocode}
+\newcommand{\@dtl@construct@lopoffs}{%
+ \edef\@dtl@chars{{\@dtl@separator}{\@dtl@delimiter}}%
+ \expandafter\@dtl@construct@lopoff\@dtl@chars
+ \expandafter\@dtl@construct@qlopoff\@dtl@chars
+ \expandafter\@dtl@construct@lop@ff\expandafter{\@dtl@separator}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{option}{separator}
+% Define separator used in external data files.
+% \begin{macrocode}
+\define@key{datatool.sty}{separator}{%
+ \DTLsetseparator{#1}%
+}
+% \end{macrocode}
+%\end{option}
+%
+%\begin{option}{delimiter}
+% Define delimiter used in external data files.
+% \begin{macrocode}
+\define@key{datatool.sty}{delimiter}{%
+ \DTLsetdelimiter{#1}%
+}
+% \end{macrocode}
+%\end{option}
+%
+%\begin{option}{verbose}
+% \begin{macrocode}
+\define@boolkey{datatool.sty}[dtl]{verbose}[true]{}
+% \end{macrocode}
+%\end{option}
+%
+%\begin{option}{math}
+% Determine whether to use \sty{fp} or \sty{pgfmath} for the
+% arithmetic commands. The default is to use \sty{fp}.
+%\changes{2.13}{2013-01-15}{changed \cs{newcommand} to
+%\cs{providecommand}}
+% \begin{macrocode}
+\define@choicekey{datatool.sty}{math}[\val\nr]{fp,pgfmath}{%
+ \renewcommand*\@dtl@mathprocessor{#1}%
+}
+\providecommand*{\@dtl@mathprocessor}{fp}
+% \end{macrocode}
+%\end{option}
+%
+%\begin{macro}{\@dtl@set@options}
+%\changes{2.28}{2017-11-10}{new}
+% \begin{macrocode}
+\newcommand*{\@dtl@set@options}{}
+% \end{macrocode}
+%\end{macro}
+%\begin{option}{utf8}
+%\changes{2.28}{2017-11-10}{new}
+%Pass to \sty{datatool-base}
+% \begin{macrocode}
+\define@choicekey{datatool.sty}{utf8}{true,false}[true]{%
+ \renewcommand*{\@dtl@set@options}{\setbool{@dtl@utf8}{#1}}%
+}
+% \end{macrocode}
+%\end{option}
+% Process package options:
+% \begin{macrocode}
+\ProcessOptionsX
+% \end{macrocode}
+%
+% Set the defaults:
+% \begin{macrocode}
+\@dtl@construct@lopoffs
+% \end{macrocode}
+%
+% Load base package:
+% \begin{macrocode}
+\RequirePackage{datatool-base}
+% \end{macrocode}
+%Set options that depend on \sty{datatool-base}:
+% \begin{macrocode}
+\@dtl@set@options
+% \end{macrocode}
+%
+%\begin{macro}{\DTLpar}
+% Many of the commands used by this package are short commands.
+% This means that you can't use \cs{par}
+% in the data. This command needs to be robust so it doesn't get
+% expanded when written to a file. We also can't just use a synonym
+% for \cs{@@par} because it may be used in a context where \cs{par}
+% has a different meaning to \cs{@@par}.
+%\changes{2.14}{2013-06-28}{changed to \cs{let}}
+%\changes{2.18}{2013-09-06}{changed back to a robust command}
+% \begin{macrocode}
+\DeclareRobustCommand{\DTLpar}{\par}
+% \end{macrocode}
+%\end{macro}
+%
+% \section{Defining New Databases}
+% As from v2.0, the internal structure of the database has changed
+% to make it more efficient.\footnote{Thanks to Morten H\o gholm
+% for the suggestion.} The database is now stored in a token
+% register instead of a macro. Each row is represented as:\par
+%\verb|\db@row@elt@w|%
+%\verb|\db@row@id@w| \meta{row idx}\verb|\db@row@id@end@|%
+%\meta{column data}%
+%\verb|\db@row@id@w| \meta{row idx}\verb|\db@row@id@end@|%
+%\verb|\db@row@elt@end@|\par
+% where \meta{row idx} is the row index and \meta{column data} is
+% the data for each column in the row. Each column for a given
+% row is stored as:\par
+%\verb|\db@col@id@w| \meta{column idx}\verb|\db@col@id@end@|%
+%\verb|\db@col@elt@w| \meta{value}\verb|\db@col@elt@end@|%
+%\verb|\db@col@id@w| \meta{column idx}\verb|\db@col@id@end@|\par
+% where \meta{column idx} is the column index and \meta{value}
+% is the entry for the given column and row.
+%
+% Each row only has an associated index, but columns have
+% a unique identifying key as well as an associated index. Columns
+% also have an associated data type which may be: 0 (column
+% contains strings), 1 (column contains integers), 2 (column
+% contains real numbers), 3 (column contains currency) or
+% \meta{empty} (column contains no data). Since the key sometimes
+% has to be expanded, a header is also available in the event
+% that the user wants to use \cs{DTLdisplaydb} or
+% \cs{DTLdisplaylongdb} and requires a column header that would
+% cause problems if used as a key. The general column
+% information is stored in a token register where each column
+% has information stored in the form:\par
+%\verb|\db@plist@elt@w|%
+%\verb|\db@col@id@w| \meta{index}\verb|\db@col@id@end@|%
+%\verb|\db@key@id@w| \meta{key}\verb|\db@key@id@end@|%
+%\verb|\db@type@id@w| \meta{type}\verb|\db@type@id@end@|%
+%\verb|\db@header@id@w| \meta{type}\verb|\db@header@id@end@|%
+%\verb|\db@col@id@w| \meta{index}\verb|\db@col@id@end@|%
+%\verb|\db@plist@elt@end@|
+%
+% The column name (\meta{key}) is mapped to the column index
+% using \cs{dtl@ci@}\meta{db}"@"\meta{key} where \meta{db} is
+% the database name.
+%
+%\begin{macro}{\DTLnewdb}
+%\begin{definition}
+% \cs{DTLnewdb}\marg{db name}
+%\end{definition}
+%\changes{2.0}{2009 February 27}{Changed way database is stored}
+% Initialises a database called \meta{name}.
+% \begin{macrocode}
+\newcommand*{\DTLnewdb}[1]{%
+% \end{macrocode}
+% Check if there is already a database with this name.
+% \begin{macrocode}
+ \DTLifdbexists{#1}%
+ {%
+ \PackageError{datatool}{Database `#1' already exists}{}%
+ }%
+ {%
+% \end{macrocode}
+% Define new database. Add information message if in verbose
+% mode.
+% \begin{macrocode}
+ \dtl@message{Creating database `#1'}%
+% \end{macrocode}
+% Define token register used to store the contents of the database.
+% \begin{macrocode}
+ \expandafter\newtoks\csname dtldb@#1\endcsname
+% \end{macrocode}
+% Define token register used to store the column header information.
+% \begin{macrocode}
+ \expandafter\newtoks\csname dtlkeys@#1\endcsname{}%
+% \end{macrocode}
+% Define count register used to store the row count.
+% \begin{macrocode}
+ \expandafter\newcount\csname dtlrows@#1\endcsname
+% \end{macrocode}
+% Define count register used to store the column count.
+% \begin{macrocode}
+ \expandafter\newcount\csname dtlcols@#1\endcsname
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLcleardb}
+%\begin{definition}
+% \cs{DTLcleardb}\marg{db name}
+%\end{definition}
+% Clears the database. (Makes it empty, but still defined.)
+%\changes{2.03}{2009 November 15}{new}
+% \begin{macrocode}
+\newcommand*{\DTLcleardb}[1]{%
+ \DTLifdbexists{#1}%
+ {%
+ \dtlforeachkey(\@dtl@key,\@dtl@col,\@dtl@type,\@dtl@head)\in{#1}\do
+ {%
+ \expandafter\let\csname dtl@ci@#1@\@dtl@key\endcsname\undefined
+ }%
+ \csname dtldb@#1\endcsname{}%
+ \csname dtlkeys@#1\endcsname{}%
+ \csname dtlrows@#1\endcsname=0\relax
+ \csname dtlcols@#1\endcsname=0\relax
+ }%
+ {%
+ \PackageError{Can't clear database `#1':
+ database doesn't exist}{}{}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLdeletedb}
+%\begin{definition}
+% \cs{DTLdeletedb}\marg{db name}
+%\end{definition}
+% Deletes a database.
+%\changes{2.03}{2009 November 15}{new}
+% \begin{macrocode}
+\newcommand*{\DTLdeletedb}[1]{%
+ \DTLifdbexists{#1}%
+ {%
+ \dtlforeachkey(\@dtl@key,\@dtl@col,\@dtl@type,\@dtl@head)\in{#1}\do
+ {%
+ \expandafter\let\csname dtl@ci@#1@\@dtl@key\endcsname\undefined
+ }%
+ \expandafter\let\csname dtldb@#1\endcsname\undefined
+ \expandafter\let\csname dtlkeys@#1\endcsname\undefined
+ \expandafter\let\csname dtlrows@#1\endcsname\undefined
+ \expandafter\let\csname dtlcols@#1\endcsname\undefined
+ }%
+ {%
+ \PackageError{Can't delete database `#1':
+ database doesn't exist}{}{}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLgnewdb}
+%\begin{definition}
+% \cs{DTLgnewdb}\marg{db name}
+%\end{definition}
+%\changes{2.13}{2013-01-15}{new}
+% Initialises a database called \meta{name}. (Global version.)
+% \begin{macrocode}
+\newcommand*{\DTLgnewdb}[1]{%
+% \end{macrocode}
+% Check if there is already a database with this name.
+% \begin{macrocode}
+ \DTLifdbexists{#1}%
+ {%
+ \PackageError{datatool}{Database `#1' already exists}{}%
+ }%
+ {%
+% \end{macrocode}
+% Define new database. Add information message if in verbose
+% mode.
+% \begin{macrocode}
+ \dtl@message{Creating database `#1'}%
+% \end{macrocode}
+% Define token register used to store the contents of the database.
+% \begin{macrocode}
+ \expandafter\global\expandafter\newtoks\csname dtldb@#1\endcsname
+% \end{macrocode}
+% Define token register used to store the column header information.
+% \begin{macrocode}
+ \expandafter\global\expandafter\newtoks\csname dtlkeys@#1\endcsname{}%
+% \end{macrocode}
+% Define count register used to store the row count.
+% \begin{macrocode}
+ \expandafter\global\expandafter\newcount\csname dtlrows@#1\endcsname
+% \end{macrocode}
+% Define count register used to store the column count.
+% \begin{macrocode}
+ \expandafter\global\expandafter\newcount\csname dtlcols@#1\endcsname
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLgdeletedb}
+%\begin{definition}
+% \cs{DTLgdeletedb}\marg{db name}
+%\end{definition}
+% Deletes a database. (Global version.)
+%\changes{2.13}{2013-01-15}{new}
+% \begin{macrocode}
+\newcommand*{\DTLgdeletedb}[1]{%
+ \DTLifdbexists{#1}%
+ {%
+ \dtlforeachkey(\@dtl@key,\@dtl@col,\@dtl@type,\@dtl@head)\in{#1}\do
+ {%
+ \expandafter\global\expandafter\let\csname dtl@ci@#1@\@dtl@key\endcsname\undefined
+ }%
+ \expandafter\global\expandafter\let\csname dtldb@#1\endcsname\undefined
+ \expandafter\global\expandafter\let\csname dtlkeys@#1\endcsname\undefined
+ \expandafter\global\expandafter\let\csname dtlrows@#1\endcsname\undefined
+ \expandafter\global\expandafter\let\csname dtlcols@#1\endcsname\undefined
+ }%
+ {%
+ \PackageError{Can't delete database `#1':
+ database doesn't exist}{}{}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLgcleardb}
+%\begin{definition}
+% \cs{DTLgcleardb}\marg{db name}
+%\end{definition}
+% Clears the database. (Global version.)
+%\changes{2.13}{2013-01-15}{new}
+% \begin{macrocode}
+\newcommand*{\DTLgcleardb}[1]{%
+ \DTLifdbexists{#1}%
+ {%
+ \dtlforeachkey(\@dtl@key,\@dtl@col,\@dtl@type,\@dtl@head)\in{#1}\do
+ {%
+ \expandafter\global\expandafter\let\csname dtl@ci@#1@\@dtl@key\endcsname\undefined
+ }%
+ \expandafter\global\csname dtldb@#1\endcsname{}%
+ \expandafter\global\csname dtlkeys@#1\endcsname{}%
+ \expandafter\global\csname dtlrows@#1\endcsname=0\relax
+ \expandafter\global\csname dtlcols@#1\endcsname=0\relax
+ }%
+ {%
+ \PackageError{Can't clear database `#1':
+ database doesn't exist}{}{}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%
+%\begin{macro}{\DTLrowcount}
+%\begin{definition}
+% \cs{DTLrowcount}\marg{db name}
+%\end{definition}
+% The number of rows in the database called \meta{db name}.
+% (Doesn't check if database exists.)
+% \begin{macrocode}
+\newcommand*{\DTLrowcount}[1]{%
+ \expandafter\number\csname dtlrows@#1\endcsname
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLcolumncount}
+%\begin{definition}
+% \cs{DTLcolumncount}\marg{db name}
+%\end{definition}
+% The number of columns in the database called \meta{db name}.
+% (Doesn't check if database exists.)
+%\changes{2.0}{2009 February 27}{new}%
+% \begin{macrocode}
+\newcommand*{\DTLcolumncount}[1]{%
+ \expandafter\number\csname dtlcols@#1\endcsname
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLifdbempty}
+%\begin{definition}
+% \cs{DTLifdbempty}\marg{name}\marg{true part}\marg{false part}
+%\end{definition}
+% Check if named database is empty (i.e.\ no rows have been added).
+% \begin{macrocode}
+\newcommand{\DTLifdbempty}[3]{%
+ \DTLifdbexists{#1}%
+ {\@DTLifdbempty{#1}{#2}{#3}}%
+ {\PackageError{Can't check if database `#1' is empty:
+ database doesn't exist}{}{}}%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@DTLifdbempty}
+%\begin{definition}
+% \cs{@sDTLifdbempty}\marg{name}\marg{true part}\marg{false part}
+%\end{definition}
+% Check if named existing database is empty. (No check performed
+% to determine if the database exists.)
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\newcommand{\@DTLifdbempty}[3]{%
+ \expandafter\ifnum\csname dtlrows@#1\endcsname=0\relax
+ #2%
+ \else
+ #3%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLnewrow}
+%\begin{definition}
+% \cs{DTLnewrow}\marg{db name}
+%\end{definition}
+% Add a new row to named database. The starred version doesn't
+% check for the existence of the database.
+% \begin{macrocode}
+\newcommand*{\DTLnewrow}{%
+ \@ifstar\@sDTLnewrow\@DTLnewrow
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@DTLnewrow}
+%\begin{definition}
+% \cs{@DTLnewrow}\marg{db name}
+%\end{definition}
+% Add a new row to named database. (Checks for the existence
+% of the database.)
+%\changes{2.13}{2013-01-15}{fixed typo in \cs{PackageError}}
+% \begin{macrocode}
+\newcommand*{\@DTLnewrow}[1]{%
+\DTLifdbexists{#1}%
+ {\@sDTLnewrow{#1}}%
+ {\PackageError{datatool}{Can't add new row to database `#1':
+ database doesn't exist}{}}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@sDTLnewrow}
+%\begin{definition}
+% \cs{@DTLnewrow}\marg{db name}
+%\end{definition}
+% Add a new row to named existing database. (No check performed
+% to determine if the database exists.)
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\newcommand*{\@sDTLnewrow}[1]{%
+% \end{macrocode}
+% Increment row count.
+% \begin{macrocode}
+ \global\advance\csname dtlrows@#1\endcsname by 1\relax
+% \end{macrocode}
+% Append an empty row to the database
+% \begin{macrocode}
+ \@dtl@toks@gput@right@cx{dtldb@#1}{%
+ \noexpand\db@row@elt@w%
+ \noexpand\db@row@id@w \number\csname dtlrows@#1\endcsname
+ \noexpand\db@row@id@end@%
+ \noexpand\db@row@id@w \number\csname dtlrows@#1\endcsname
+ \noexpand\db@row@id@end@%
+ \noexpand\db@row@elt@end@%
+ }%
+% \end{macrocode}
+% Display message on terminal and log file if in verbose mode.
+% \begin{macrocode}
+ \dtl@message{New row added to database `#1'}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlcolumnnum}
+% Count register to keep track of column index.
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\newcount\dtlcolumnnum
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtlrownum}
+% Count register to keep track of row index.
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\newcount\dtlrownum
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLifhaskey}
+%\begin{definition}
+%\cs{DTLifhaskey}\meta{db name}\meta{key}\meta{true part}\meta{false
+% part}
+%\end{definition}
+% Checks if the named database \meta{db name} has a column with label
+% \meta{key}. If column exists, do \meta{true part} otherwise
+% do \meta{false part}. The starred version doesn't check if
+% the named database exists.
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\newcommand*{\DTLifhaskey}{\@ifstar\@sDTLifhaskey\@DTLifhaskey}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@DTLifhaskey}
+% Unstarred version of \cs{DTLifhaskey}
+% \begin{macrocode}
+\newcommand{\@DTLifhaskey}[4]{%
+ \DTLifdbexists{#1}%
+ {%
+ \@sDTLifhaskey{#1}{#2}{#3}{#4}%
+ }%
+ {%
+ \PackageError{datatool}{Database `#1' doesn't exist}{}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@sDTLifhaskey}
+% Starred version of \cs{DTLifhaskey}
+% \begin{macrocode}
+\newcommand{\@sDTLifhaskey}[4]{%
+ \@ifundefined{dtl@ci@#1@#2}%
+ {%
+% \end{macrocode}
+% Key not defined
+% \begin{macrocode}
+ #4%
+ }%
+ {%
+% \end{macrocode}
+% Key defined
+% \begin{macrocode}
+ #3%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLgetcolumnindex}
+%\begin{definition}
+%\cs{DTLgetcolumnindex}\marg{cs}\marg{db}\marg{key}
+%\end{definition}
+% Gets index for column with label \meta{key} from database
+% \meta{db} and stores in \meta{cs} which must be a control
+% sequence.
+% Unstarred version checks if database and key exist, unstarred
+% version doesn't perform any checks.
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\newcommand*{\DTLgetcolumnindex}{%
+ \@ifstar\@sdtl@getcolumnindex\@dtl@getcolumnindex
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@getcolumnindex}
+% Unstarred version of \cs{DTLgetcolumnindex}
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\newcommand*{\@dtl@getcolumnindex}[3]{%
+% \end{macrocode}
+% Check if database exists.
+% \begin{macrocode}
+ \DTLifdbexists{#2}%
+ {%
+% \end{macrocode}
+% Database exists. Now check if key exists.
+% \begin{macrocode}
+ \@sDTLifhaskey{#2}{#3}%
+ {%
+% \end{macrocode}
+% Key exists so go ahead and get column index.
+% \begin{macrocode}
+ \@sdtl@getcolumnindex{#1}{#2}{#3}%
+ }%
+ {%
+% \end{macrocode}
+% Key doesn't exists in named database.
+% \begin{macrocode}
+ \PackageError{datatool}{Database `#2' doesn't contain
+ key `#3'}{}%
+ }%
+ }%
+ {%
+% \end{macrocode}
+% Named database doesn't exist.
+% \begin{macrocode}
+ \PackageError{datatool}{Database `#2' doesn't exist}{}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@getcolumnindex}
+% Starred version of \cs{DTLgetcolumnindex}.
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\newcommand*{\@sdtl@getcolumnindex}[3]{%
+ \expandafter\let\expandafter#1\csname dtl@ci@#2@#3\endcsname
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlcolumnindex}
+%\begin{definition}
+% \cs{dtlcolumnindex}\marg{db}\marg{key}
+%\end{definition}
+% Column index corresponding to \meta{key} in database \meta{db}.
+% (No check for existance of database or key.)
+%\changes{2.0}{2009 February 27}{new}
+%\changes{2.03}{2009 November 15}{renamed \cs{dtl@columnindex} to
+%\cs{dtlcolumnindex}}
+% \begin{macrocode}
+\newcommand*{\dtlcolumnindex}[2]{%
+ \csname dtl@ci@#1@#2\endcsname
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLgetkeyforcolumn}
+%\begin{definition}
+%\cs{DTLgetkeyforcolumn}\marg{key cs}\marg{db}\marg{column index}
+%\end{definition}
+% Gets the key associated with the given column index and stores
+% in \meta{key cs}. Unstarred version doesn't perform checks.
+% \begin{macrocode}
+\newcommand*{\DTLgetkeyforcolumn}{%
+ \@ifstar\@sdtlgetkeyforcolumn\@dtlgetkeyforcolumn}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtlgetkeyforcolumn}
+% \begin{macrocode}
+\newcommand*{\@dtlgetkeyforcolumn}[3]{%
+ \DTLifdbexists{#2}%
+ {%
+% \end{macrocode}
+% Check if index is in range.
+% \begin{macrocode}
+ \ifnum#3<1\relax
+ \PackageError{datatool}{Invalid column index \number#3}{%
+ Column indices start at 1}%
+ \else
+ \expandafter\ifnum\csname dtlcols@#2\endcsname<#3\relax
+ \PackageError{datatool}{Index \number#3\space out of
+ range for database `#2'}{Database `#2' only has
+ \expandafter\number\csname dtlcols@#2\endcsname\space
+ columns}%
+ \else
+ \@sdtlgetkeyforcolumn{#1}{#2}{#3}%
+ \fi
+ \fi
+ }%
+ {%
+ \PackageError{datatool}{Database `#2' doesn't exists}{}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@sdtlgetkeyforcolumn}
+%\begin{definition}
+%\cs{@sdtlgetkeyforcolumn}\marg{key cs}\marg{db}\marg{column index}
+%\end{definition}
+% Gets the key associated with the given column index and stores
+% in \meta{key cs}
+% \begin{macrocode}
+\newcommand*{\@sdtlgetkeyforcolumn}[3]{%
+ \edef\@dtl@dogetkeyforcolumn{\noexpand\@dtl@getkeyforcolumn
+ {\noexpand#1}{#2}{\number#3}}%
+ \@dtl@dogetkeyforcolumn
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@dtl@getkeyforcolumn}
+% Column index must be fully expanded before use.
+%\changes{2.10}{2012-07-18}{fixed bug}
+% \begin{macrocode}
+\newcommand*{\@dtl@getkeyforcolumn}[3]{%
+ \def\@dtl@get@keyforcolumn##1% before stuff
+ \db@plist@elt@w% start of block
+ \db@col@id@w #3\db@col@id@end@% index
+ \db@key@id@w ##2\db@key@id@end@% key
+ \db@type@id@w ##3\db@type@id@end@% data type
+ \db@header@id@w ##4\db@header@id@end@% header
+ \db@col@id@w #3\db@col@id@end@% index
+ \db@plist@elt@end@% end of block
+ ##5\q@nil{\def#1{##2}}%
+ \edef\@dtl@tmp{\expandafter\the\csname dtlkeys@#2\endcsname}%
+ \expandafter\@dtl@get@keyforcolumn\@dtl@tmp
+ \db@plist@elt@w% start of block
+ \db@col@id@w #3\db@col@id@end@ %index
+ \db@key@id@w \@nil\db@key@id@end@% key
+ \db@type@id@w \db@type@id@end@% data type
+ \db@header@id@w \db@header@id@end@% header
+ \db@col@id@w #3\db@col@id@end@% index
+ \db@plist@elt@end@% end of block
+ \q@nil
+}
+% \end{macrocode}
+%\end{macro}
+%
+% Define some commands to indicate the various data types a database
+% may contain.
+%\begin{macro}{\DTLunsettype}
+% Unknown data type. (All entries in the column are blank so the
+% type can't be determined.)
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\def\DTLunsettype{}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLstringtype}
+% Data type representing strings.
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\def\DTLstringtype{0}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLinttype}
+% Data type representing integers.
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\def\DTLinttype{1}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLrealtype}
+% Data type representing real numbers.
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\def\DTLrealtype{2}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLcurrencytype}
+% Data type representing currency.
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\def\DTLcurrencytype{3}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLgetdatatype}
+%\begin{definition}
+%\cs{DTLgetdatatype}\marg{cs}\marg{db}\marg{key}
+%\end{definition}
+% Gets data type associated with column labelled \meta{key} in
+% database \meta{db} and stores in \meta{cs}. Type may be:
+% \meta{empty} (unset), 0 (string), 1 (int),
+% 2 (real), 3 (currency). Unstarred version checks if the database
+% and key exist, starred version doesn't.
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\newcommand*{\DTLgetdatatype}{%
+ \@ifstar\@sdtlgetdatatype\@dtlgetdatatype
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtlgetdatatype}
+% Unstarred version of \cs{DTLgetdatatype}.
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\newcommand*{\@dtlgetdatatype}[3]{%
+% \end{macrocode}
+% Check if database exists.
+% \begin{macrocode}
+ \DTLifdbexists{#2}%
+ {%
+% \end{macrocode}
+% Check if key exists in this database.
+% \begin{macrocode}
+ \@sDTLifhaskey{#2}{#3}%
+ {%
+% \end{macrocode}
+% Get data type for this database and key.
+% \begin{macrocode}
+ \@sdtlgetdatatype{#1}{#2}{#3}%
+ }%
+ {%
+% \end{macrocode}
+% Key doesn't exist in this database.
+% \begin{macrocode}
+ \PackageError{datatool}{Key `#3' undefined in database `#2'}{}%
+ }%
+ }%
+ {%
+% \end{macrocode}
+% Database doesn't exist.
+% \begin{macrocode}
+ \PackageError{datatool}{Database `#2' doesn't exist}{}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@sdtlgetdatatype}
+% Starred version of \cs{DTLgetdatatype}. This ensures that
+% the key is fully expanded before begin passed to
+% \cs{@dtl@getdatatype}.
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\newcommand*{\@sdtlgetdatatype}[3]{%
+ \edef\@dtl@dogetdata{\noexpand\@dtl@getdatatype{\noexpand#1}%
+ {\expandafter\the\csname dtlkeys@#2\endcsname}%
+ {\dtlcolumnindex{#2}{#3}}}%
+ \@dtl@dogetdata
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@getdatatype}
+%\begin{definition}
+%\cs{@dtl@getdatatype}\marg{cs}\marg{data specs}\marg{column index}
+%\end{definition}
+% Column index must be expanded.
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\newcommand*{\@dtl@getdatatype}[3]{%
+ \def\@dtl@get@keydata##1% stuff before
+ \db@plist@elt@w% start of key block
+ \db@col@id@w #3\db@col@id@end@% column index
+ \db@key@id@w ##2\db@key@id@end@% key id
+ \db@type@id@w ##3\db@type@id@end@% data type
+ \db@header@id@w ##4\db@header@id@end@% header
+ \db@col@id@w #3\db@col@id@end@% column index
+ \db@plist@elt@end@% end of key block
+ ##5% stuff afterwards
+ \q@nil{\def#1{##3}}%
+ \@dtl@get@keydata#2\q@nil
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@getprops}
+%\begin{definition}
+%\cs{@dtl@getprops}\marg{key cs}\marg{type cs}\marg{header toks}\marg{before toks}\marg{after toks}\marg{data specs}\marg{column index}
+%\end{definition}
+% Column index must be expanded.
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\newcommand*{\@dtl@getprops}[7]{%
+ \def\@dtl@get@keydata##1% stuff before
+ \db@plist@elt@w% start of key block
+ \db@col@id@w #7\db@col@id@end@% column index
+ \db@key@id@w ##2\db@key@id@end@% key id
+ \db@type@id@w ##3\db@type@id@end@% data type
+ \db@header@id@w ##4\db@header@id@end@% header
+ \db@col@id@w #7\db@col@id@end@% column index
+ \db@plist@elt@end@% end of key block
+ ##5% stuff afterwards
+ \q@nil{%
+ \def#1{##2}% key
+ \def#2{##3}% data type
+ #3={##4}% header
+ #4={##1}% before stuff
+ #5={##5}% after stuff
+ }%
+ \@dtl@get@keydata#6\q@nil
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@before}
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\newtoks\@dtl@before
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@dtl@after}
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\newtoks\@dtl@after
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@dtl@colhead}
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\newtoks\@dtl@colhead
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLaddcolumn}
+%\begin{definition}
+%\cs{DTLaddcolumn}\marg{db}\marg{key}
+%\end{definition}
+% Adds a column with given key to given column. No data is added to
+% the column. The starred version doesn't check for the existence of
+% the database.
+%\changes{2.11}{2012-09-25}{new}
+% \begin{macrocode}
+\newcommand*{\DTLaddcolumn}{%
+ \@ifstar\@sDTLaddcolumn\@DTLaddcolumn
+}
+\newcommand{\@DTLaddcolumn}[2]{%
+ \DTLifdbexists{#1}%
+ {\@dtl@updatekeys{#1}{#2}{}}%
+ {\PackageError{datatool}{Can't add new column to database `#1':
+ database doesn't exist}{}}%
+}
+\newcommand{\s@DTLaddcolumn}[2]{%
+ \@dtl@updatekeys{#1}{#2}{}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@updatekeys}
+%\begin{definition}
+%\cs{@dtl@updatekeys}\marg{db}\marg{key}\marg{value}
+%\end{definition}
+% Adds key to database's key list if it doesn't exist.
+% The value is used to update the data type associated with that key.
+% Key must be fully expanded. Doesn't check if database exists.
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\newcommand*{\@dtl@updatekeys}[3]{%
+% \end{macrocode}
+% Check if key already exists
+% \begin{macrocode}
+ \@sDTLifhaskey{#1}{#2}%
+ {%
+% \end{macrocode}
+% Key exists, may need to update data type. First get the
+% column index.
+% \begin{macrocode}
+ \expandafter\dtlcolumnnum\expandafter
+ =\dtlcolumnindex{#1}{#2}\relax
+% \end{macrocode}
+% Get the properties for this column
+%\changes{2.11}{2012-09-25}{remove unwanted space}
+% \begin{macrocode}
+ \edef\@dtl@dogetprops{\noexpand\@dtl@getprops
+ {\noexpand\@dtl@key}{\noexpand\@dtl@type}%
+ {\noexpand\@dtl@colhead}{\noexpand\@dtl@before}%
+ {\noexpand\@dtl@after}{\the\csname dtlkeys@#1\endcsname}%
+ {\number\dtlcolumnnum}}%
+ \@dtl@dogetprops
+% \end{macrocode}
+% Is the value empty?
+%\changes{2.14}{2013-06-28}{expand value before testing if it's
+%empty}
+%\changes{2.16}{2013-08-16}{reverted to not expanding value (2.14 change
+%causes an error with fragile commands). Fix now in
+%\cs{@dtl@checknumerical}}
+% \begin{macrocode}
+ \ifstrempty{#3}%
+ {%
+% \end{macrocode}
+% Leave data type as it is
+% \begin{macrocode}
+ }%
+ {%
+% \end{macrocode}
+% Make a copy of current data type
+% \begin{macrocode}
+ \let\@dtl@oldtype\@dtl@type
+% \end{macrocode}
+% Check the data type for this entry (stored in \cs{@dtl@datatype})
+% \begin{macrocode}
+ \@dtl@checknumerical{#3}%
+% \end{macrocode}
+% If this column currently has no data type assigned to it
+% then use the new type.
+% \begin{macrocode}
+ \ifdefempty{\@dtl@type}%
+ {%
+ \edef\@dtl@type{\number\@dtl@datatype}%
+ }%
+ {%
+% \end{macrocode}
+% This column already has an associated data type but it may
+% need updating.
+% \begin{macrocode}
+ \ifcase\@dtl@datatype % string
+% \end{macrocode}
+% String overrides all other types
+% \begin{macrocode}
+ \def\@dtl@type{0}%
+ \or % int
+% \end{macrocode}
+% All other types override int, so leave it as it is
+% \begin{macrocode}
+ \or % real
+% \end{macrocode}
+% Real overrides int, but not currency or string
+% \begin{macrocode}
+ \ifnum\@dtl@type=1\relax
+ \def\@dtl@type{2}%
+ \fi
+ \or % currency
+% \end{macrocode}
+% Currency overrides int and real but not string
+% \begin{macrocode}
+ \ifnum\@dtl@type>0\relax
+ \def\@dtl@type{3}%
+ \fi
+ \fi
+ }%
+% \end{macrocode}
+% Has the data type been updated?
+% \begin{macrocode}
+ \ifx\@dtl@oldtype\@dtl@type
+% \end{macrocode}
+% No change needed
+% \begin{macrocode}
+ \else
+% \end{macrocode}
+% Update required
+% \begin{macrocode}
+ \@dtl@toks@gconcat@middle@cx{dtlkeys@#1}%
+ {\@dtl@before}%
+ {%
+ \noexpand\db@plist@elt@w% start of key block
+ \noexpand\db@col@id@w \the\dtlcolumnnum
+ \noexpand\db@col@id@end@% column index
+ \noexpand\db@key@id@w #2\noexpand\db@key@id@end@% key id
+ \noexpand\db@type@id@w \@dtl@type
+ \noexpand\db@type@id@end@% data type
+ \noexpand\db@header@id@w \the\@dtl@colhead
+ \noexpand\db@header@id@end@% header
+ \noexpand\db@col@id@w \the\dtlcolumnnum
+ \noexpand\db@col@id@end@% column index
+ \noexpand\db@plist@elt@end@% end of key block
+ }%
+ {\@dtl@after}%
+ \fi
+ }%
+ }%
+ {%
+% \end{macrocode}
+% Key doesn't exist. Increment column count.
+% \begin{macrocode}
+ \expandafter\global\expandafter\advance
+ \csname dtlcols@#1\endcsname by 1\relax
+ \dtlcolumnnum=\csname dtlcols@#1\endcsname\relax
+% \end{macrocode}
+% Set column index for this key.
+% \begin{macrocode}
+ \expandafter\xdef\csname dtl@ci@#1@#2\endcsname{%
+ \number\dtlcolumnnum}%
+% \end{macrocode}
+% Get data type for this entry (stored in \cs{@dtl@datatype})
+% \begin{macrocode}
+ \ifstrempty{#2}%
+ {%
+ \edef\@dtl@type{}% don't know data type yet
+ }%
+ {%
+ \@dtl@checknumerical{#3}%
+ \edef\@dtl@type{\number\@dtl@datatype}%
+ }%
+% \end{macrocode}
+% Append to property list
+% \begin{macrocode}
+ \@dtl@toks@gput@right@cx{dtlkeys@#1}%
+ {%
+ \noexpand\db@plist@elt@w
+ \noexpand\db@col@id@w \the\dtlcolumnnum
+ \noexpand\db@col@id@end@
+ \noexpand\db@key@id@w #2\noexpand\db@key@id@end@
+ \noexpand\db@type@id@w \@dtl@type
+ \noexpand\db@type@id@end@
+ \noexpand\db@header@id@w #2\noexpand\db@header@id@end@
+ \noexpand\db@col@id@w \the\dtlcolumnnum
+ \noexpand\db@col@id@end@
+ \noexpand\db@plist@elt@end@
+ }%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLsetheader}
+%\begin{definition}
+%\cs{DTLsetheader}\marg{db}\marg{key}\marg{header}
+%\end{definition}
+% Sets header for column given by \meta{key} in database \meta{db}.
+% Starred version doesn't check for existance of database or key.
+% \begin{macrocode}
+\newcommand*{\DTLsetheader}{\@ifstar\@sDTLsetheader\@DTLsetheader}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@DTLsetheader}
+% Unstarred version
+% \begin{macrocode}
+\newcommand*{\@DTLsetheader}[3]{%
+% \end{macrocode}
+% Check if database exists
+% \begin{macrocode}
+ \DTLifdbexists{#1}%
+ {%
+% \end{macrocode}
+% Check if key exists.
+% \begin{macrocode}
+ \@sDTLifhaskey{#1}{#2}%
+ {%
+ \@sDTLsetheader{#1}{#2}{#3}%
+ }%
+ {%
+ \PackageError{datatool}{Database `#1' doesn't contain key
+ `#2'}{}%
+ }%
+ }%
+ {%
+ \PackageError{datatool}{Database `#1' doesn't exist}{}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@sDTLsetheader}
+% Starred version
+% \begin{macrocode}
+\newcommand*{\@sDTLsetheader}[3]{%
+ \expandafter\dtlcolumnnum\expandafter
+ =\dtlcolumnindex{#1}{#2}\relax
+ \@dtl@setheaderforindex{#1}{\dtlcolumnnum}{#3}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@setheaderforindex}
+%\begin{definition}
+%\cs{@dtl@setheaderforindex}\marg{db}\marg{column index}\marg{header}
+%\end{definition}
+% Sets the header for column given by \meta{column index} in
+% database \meta{db}. The header must be expanded.
+% \begin{macrocode}
+\newcommand*{\@dtl@setheaderforindex}[3]{%
+% \end{macrocode}
+% Get the properties for this column
+%\changes{2.13}{2013-01-15}{removed spurious space}
+% \begin{macrocode}
+ \edef\@dtl@dogetprops{\noexpand\@dtl@getprops
+ {\noexpand\@dtl@key}{\noexpand\@dtl@type}%
+ {\noexpand\@dtl@colhead}{\noexpand\@dtl@before}%
+ {\noexpand\@dtl@after}{\the\csname dtlkeys@#1\endcsname}%
+ {\number#2}}%
+ \@dtl@dogetprops
+% \end{macrocode}
+% Store the header in \cs{@dtl@toks}
+% \begin{macrocode}
+ \@dtl@colhead={#3}%
+% \end{macrocode}
+% Reconstruct property list
+% \begin{macrocode}
+ \edef\@dtl@colnum{\number#2}\relax
+ \@dtl@toks@gconcat@middle@cx{dtlkeys@#1}%
+ {\@dtl@before}%
+ {%
+ \noexpand\db@plist@elt@w% start of block
+ \noexpand\db@col@id@w \@dtl@colnum
+ \noexpand\db@col@id@end@% index
+ \noexpand\db@key@id@w \@dtl@key\noexpand\db@key@id@end@% key
+ \noexpand\db@type@id@w \@dtl@type
+ \noexpand\db@type@id@end@% data type
+ \noexpand\db@header@id@w \the\@dtl@colhead
+ \noexpand\db@header@id@end@% header
+ \noexpand\db@col@id@w \@dtl@colnum
+ \noexpand\db@col@id@end@% index
+ \noexpand\db@plist@elt@end@% end of block
+ }%
+ {\@dtl@after}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlexpandnewvalue}
+% Expand new value before adding to database
+% \begin{macrocode}
+\newcommand*{\dtlexpandnewvalue}{%
+ \def\@dtl@setnewvalue##1{\protected@edef\@dtl@tmp{##1}%
+ \expandafter\@dtl@toks\expandafter{\@dtl@tmp}}%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtlnoexpandnewvalue}
+% Don't expand new value before adding to database
+% \begin{macrocode}
+\newcommand*{\dtlnoexpandnewvalue}{%
+ \def\@dtl@setnewvalue##1{\@dtl@toks{##1}}%
+}
+% \end{macrocode}
+% Do this by default:
+% \begin{macrocode}
+\dtlnoexpandnewvalue
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLnewdbentry}
+%\begin{definition}
+% \cs{DTLnewdbentry}\marg{db name}\marg{id}\marg{value}.
+%\end{definition}
+% Adds an entry to the last row (adds new row if database is empty)
+% and updates general column information if necessary. The
+% starred version doesn't check if the database exists.
+% \begin{macrocode}
+\newcommand{\DTLnewdbentry}{%
+ \@ifstar\@sDTLnewdbentry\@DTLnewdbentry
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@DTLnewdbentry}
+% Unstarred version of \cs{DTLnewdbentry}.
+% \begin{macrocode}
+\newcommand{\@DTLnewdbentry}[3]{%
+ \DTLifdbexists{#1}%
+ {\@sDTLnewdbentry{#1}{#2}{#3}}%
+ {\PackageError{datatool}{Can't add new entry to database `#1':
+ database doesn't exist}{}}%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@sDTLnewdbentry}
+% Starred version of \cs{DTLnewdbentry} (doesn't check if the database exists).
+% \begin{macrocode}
+\newcommand*{\@sDTLnewdbentry}[3]{%
+% \end{macrocode}
+% Update key list
+% \begin{macrocode}
+ \@dtl@updatekeys{#1}{#2}{#3}%
+% \end{macrocode}
+% Get the column index
+% \begin{macrocode}
+ \expandafter\dtlcolumnnum\expandafter
+ =\dtlcolumnindex{#1}{#2}\relax
+% \end{macrocode}
+% Get the current row:
+% \begin{macrocode}
+ \edef\dtl@dogetrow{\noexpand\dtlgetrow{#1}%
+ {\number\csname dtlrows@#1\endcsname}}%
+ \dtl@dogetrow
+% \end{macrocode}
+% Check if this row already has an entry for the given column.
+% \begin{macrocode}
+ \edef\dtl@dogetentry{\noexpand\dtlgetentryfromcurrentrow
+ {\noexpand\dtl@entry}{\number\dtlcolumnnum}%
+ }%
+ \dtl@dogetentry
+ \ifx\dtl@entry\dtlnovalue
+% \end{macrocode}
+% Store the value of this entry in \cs{@dtl@toks}
+%\changes{2.03}{2009 November 15}{value can be expanded before
+% adding to database}%
+% \begin{macrocode}
+ \@dtl@setnewvalue{#3}%
+% \end{macrocode}
+% There are no entries in this row for the given column.
+% Add this entry.
+% \begin{macrocode}
+ \@dtl@toks@gconcat@middle@cx{dtldb@#1}%
+ {\dtlbeforerow}%
+ {%
+% \end{macrocode}
+% Start of this row:
+% \begin{macrocode}
+ \noexpand\db@row@elt@w%
+% \end{macrocode}
+% Row ID:
+% \begin{macrocode}
+ \noexpand\db@row@id@w \number\csname dtlrows@#1\endcsname
+ \noexpand\db@row@id@end@%
+% \end{macrocode}
+% Current row so far
+% \begin{macrocode}
+ \the\dtlcurrentrow
+% \end{macrocode}
+% New column:
+% Column ID
+% \begin{macrocode}
+ \noexpand\db@col@id@w \number\dtlcolumnnum
+ \noexpand\db@col@id@end@%
+% \end{macrocode}
+% Value:
+% \begin{macrocode}
+ \noexpand\db@col@elt@w \the\@dtl@toks
+ \noexpand\db@col@elt@end@%
+% \end{macrocode}
+% Column ID:
+% \begin{macrocode}
+ \noexpand\db@col@id@w \number\dtlcolumnnum
+ \noexpand\db@col@id@end@%
+% \end{macrocode}
+% Row ID:
+% \begin{macrocode}
+ \noexpand\db@row@id@w \number\csname dtlrows@#1\endcsname
+ \noexpand\db@row@id@end@%
+% \end{macrocode}
+% End of this row
+% \begin{macrocode}
+ \noexpand\db@row@elt@end@%
+ }%
+% \end{macrocode}
+% Rest (this should be empty)
+% \begin{macrocode}
+ {\dtlafterrow}%
+% \end{macrocode}
+% Print information message if in verbose mode.
+% \begin{macrocode}
+ \dtl@message{Added #2\space -> #3\space to database `#1'}%
+ \else
+% \end{macrocode}
+% There's already an entry for the given column in this row
+% \begin{macrocode}
+ \PackageError{datatool}{Can't add entry with ID `#2' to
+ current row of database `#1'}{There is already an entry with
+ this ID in the current row}%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\changes{2.0}{2009 February 27}{removed \cs{@dtl@setidtype}}
+%\changes{2.0}{2009 February 27}{removed \cs{@dtl@setkeys}}
+%\changes{2.0}{2009 February 27}{removed \cs{@dtl@getidtype}}
+%
+%\begin{macro}{\DTLifdbexists}
+%\begin{definition}
+%\cs{DTLifdbexists}\marg{db name}\marg{true part}\marg{false part}
+%\end{definition}
+% Checks if a data base with the given name exists.
+% \begin{macrocode}
+\newcommand{\DTLifdbexists}[3]{%
+ \@ifundefined{dtldb@#1}{#3}{#2}}
+% \end{macrocode}
+%\end{macro}
+%
+%\changes{2.0}{2009 February 27}{removed \cs{@dtl@ifrowcontains}}
+%\changes{2.0}{2009 February 27}{removed \cs{dtl@getentryvalue}}
+%\changes{2.0}{2009 February 27}{removed \cs{dtl@getentryid}}
+%
+%\section{Accessing Data}
+%
+%\begin{macro}{\DTLassign}
+%\begin{definition}
+%\cs{DTLassign}\marg{db}\marg{row idx}\marg{assign list}
+%\end{definition}
+% Assigns values given in \meta{assign list} for row \meta{row idx} in database
+% \meta{db}. (Where \meta{assign list} is in the same form as in
+% \cs{DTLforeach})
+%\changes{2.10}{2012-07-18}{new}
+% \begin{macrocode}
+\newcommand*{\DTLassign}[3]{%
+ \DTLifdbexists{#1}
+ {%
+% \end{macrocode}
+% Grouped in the event that \cs{dtlcurrentrow} is already in use.
+% (Assignments in \cs{@dtl@assign} are global.)
+% \begin{macrocode}
+ {%
+ \dtlgetrow{#1}{#2}%
+ \@dtl@assign{#3}{#1}%
+ }%
+ }%
+ {%
+ \PackageError{datatool}{Database `#1' doesn't exist}{}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLassignfirstmatch}
+%\begin{definition}
+%\cs{DTLassignfirstmatch}\marg{db}\marg{col key}\marg{value}\marg{assign list}
+%\end{definition}
+% Applies the assignment list to the first row that has the given
+% value in the given column. (Value must be expanded.)
+%\changes{2.20}{2014-02-03}{new}
+% \begin{macrocode}
+\newcommand*{\DTLassignfirstmatch}[4]{%
+ \dtl@assignfirstmatch{#3}{#1}{#2}{#4}%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\xDTLassignfirstmatch}
+%\begin{definition}
+%\cs{xDTLassignfirstmatch}\marg{db}\marg{col key}\marg{value}\marg{assign list}
+%\end{definition}
+% Applies the assignment list to the first row that has the given
+% value in the given column. (Performs \emph{one level} expansion on
+% \meta{value}.)
+%\changes{2.20}{2014-02-03}{new}
+% \begin{macrocode}
+\newcommand*{\xDTLassignfirstmatch}[4]{%
+ \protected@edef\@dtl@asg@value{\expandonce{#3}}%
+ \expandafter\dtl@assignfirstmatch\expandafter
+ {\@dtl@asg@value}{#1}{#2}{#4}%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtl@assignfirstmatch}
+% Internal swaps the ordering around so the value is first. (This
+% just makes it easier for \cs{xDTLassignfirstmatch}
+% \begin{macrocode}
+\newcommand*{\dtl@assignfirstmatch}[4]{%
+ \DTLifdbexists{#2}%
+ {%
+% Grouped in the event that \cs{dtlcurrentrow} is already in use.
+% (Assignments in \cs{@dtl@assign} are global.)
+% \begin{macrocode}
+ {%
+% \end{macrocode}
+% Get row idx:
+% \begin{macrocode}
+ \dtlgetrowindex{\dtl@asg@rowidx}{#2}{\dtlcolumnindex{#2}{#3}}{#1}%
+ \ifx\dtl@asg@rowidx\dtlnovalue
+ \PackageError{datatool}{No match found for
+ \string\DTLassignfirstmatch{#2}{#3}{#1}{#4}}{}%
+ \else
+ \dtlgetrow{#2}{\dtl@asg@rowidx}%
+ \@dtl@assign{#4}{#2}%
+ \fi
+ }%
+ }%
+ {%
+ \PackageError{datatool}{Data base `#2' doesn't exist}{}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@assign}
+%\begin{definition}
+%\cs{@dtl@assign}\marg{list}\marg{db}
+%\end{definition}
+% Assigns commands according to the given keys.
+% The current row must be stored in \cs{dtlcurrentrow}.
+%\changes{2.0}{2009 February 27}{updated to use new database
+% structure}
+%\changes{2.20}{2014-02-03}{Added check for empty argument}%
+% \begin{macrocode}
+\newcommand*{\@dtl@assign}[2]{%
+ \ifstrempty{#1}{}%
+ {%
+ \@dtl@assigncmd#1,\@nil\@@{#2}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@assigncmd}
+%\begin{definition}
+% \cs{@dtl@assigncmd}\meta{cmd}=\meta{id}\cs{@nil}
+%\end{definition}
+%\changes{2.03}{2009 November 15}{modified to ignore spaces after
+% commas}
+% \begin{macrocode}
+\def\@dtl@assigncmd#1#2=#3,#4\@@#5{%
+% \end{macrocode}
+% Store database label. (This may already have been done so \cs{edef}
+% is used to prevent infinite recursion.)
+%\changes{2.20}{2014-02-03}{Stored db label in \cs{@dtl@dbname}}
+% \begin{macrocode}
+ \edef\@dtl@dbname{#5}%
+% \end{macrocode}
+% get entry for ID given by \#3 and store in \#2
+% \begin{macrocode}
+ \@sDTLifhaskey{#5}{#3}%
+ {%
+ \edef\@dtl@dogetentry{%
+ \noexpand\dtlgetentryfromcurrentrow
+ {\noexpand#1}{\dtlcolumnindex{#5}{#3}}}%
+ \@dtl@dogetentry
+% \end{macrocode}
+% Set to null if required
+% \begin{macrocode}
+ \ifdefequal{#1}{\dtlnovalue}%
+ {%
+ \@@dtl@setnull{#1}{#3}%
+ }%
+ {}%
+% \end{macrocode}
+% Make it global
+% \begin{macrocode}
+ \global\let#1=#1\relax
+ }%
+ {%
+ \PackageError{datatool}{Can't assign \string#1\space: there
+ is no key `#3' in data base `#5'}{}%
+% \end{macrocode}
+% Set to null
+% \begin{macrocode}
+ \global\let#1\DTLstringnull
+ }%
+% \end{macrocode}
+% Recurse?
+% \begin{macrocode}
+ \def\dtl@tmp{#4}%
+ \ifx\@nnil\dtl@tmp
+ \let\@dtl@next\@dtl@assigncmdnoop
+ \else
+ \let\@dtl@next\@dtl@assigncmd
+ \fi
+ \@dtl@next#4\@@{#5}%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@dtl@assigncmdnoop}
+% End loop
+% \begin{macrocode}
+\def\@dtl@assigncmdnoop#1\@@#2{}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@setnull}
+%\cs{@dtl@setnull}\marg{cmd}\marg{id} sets \meta{cmd} to either
+% \cs{@dtlstringnull} or \cs{@dtlnumbernull} depending on the data
+% type for \meta{id}. (Database
+% name should be stored in \cs{@dtl@dbname} prior to use.)
+%\changes{2.0}{2009 February 27}{modified to use new database
+% structure}
+% \begin{macrocode}
+\newcommand*{\@dtl@setnull}[2]{%
+% \end{macrocode}
+% Check if database given by \cs{@dtl@dbname} has the required key.
+% \begin{macrocode}
+ \@sDTLifhaskey{\@dtl@dbname}{#2}%
+ {%
+% \end{macrocode}
+% Set to null
+% \begin{macrocode}
+ \@@dtl@setnull{#1}{#2}%
+ }%
+ {%
+% \end{macrocode}
+% Key not defined in database \cs{@dtl@dbname}.
+% \begin{macrocode}
+ \global\let#1=\DTLstringnull
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@@dtl@setnull}
+% As above, but doesn't check if key exists
+% \begin{macrocode}
+\newcommand*{\@@dtl@setnull}[2]{%
+% \end{macrocode}
+% Get the data type associated with this key and store in
+% \cs{@dtl@type}.
+% \begin{macrocode}
+ \@sdtlgetdatatype{\@dtl@type}{\@dtl@dbname}{#2}%
+% \end{macrocode}
+% Check data type.
+% \begin{macrocode}
+ \ifnum0\@dtl@type=0\relax
+% \end{macrocode}
+% Data type is \meta{empty} or 0, so set to string null.
+% \begin{macrocode}
+ \global\let#1=\DTLstringnull
+ \else
+% \end{macrocode}
+% Data type is numerical, so set to number null.
+% \begin{macrocode}
+ \global\let#1=\DTLnumbernull
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLstringnull}
+% String null value:
+% \begin{macrocode}
+\newcommand*{\DTLstringnull}{\@dtlstringnull}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@dtlstringnull}
+%\changes{2.13}{2013-01-15}{new}
+% String null value:
+% \begin{macrocode}
+\newcommand*{\@dtlstringnull}{NULL}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLnumbernull}
+% Number null value:
+% \begin{macrocode}
+\newcommand*{\DTLnumbernull}{\@dtlnumbernull}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@dtlnumbernull}
+%\changes{2.13}{2013-01-15}{new}
+% Number null value:
+% \begin{macrocode}
+\newcommand*{\@dtlnumbernull}{0}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLifnull}
+%\begin{definition}
+%\cs{DTLifnull}\marg{command}\marg{true part}\marg{false part}
+%\end{definition}
+% Checks if \meta{command} is null (either \cs{DTLstringnull} or
+% \cs{DTLnumbernull}) if true, does \meta{true part} otherwise
+% does \meta{false part}.
+% \begin{macrocode}
+\newcommand*{\DTLifnull}[3]{%
+ \ifx#1\dtlnovalue
+ #2%
+ \else
+ \ifx#1\DTLstringnull
+ #2%
+ \else
+ \ifx#1\DTLnumbernull
+ #2%
+ \else
+ #3%
+ \fi
+ \fi
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLifnullorempty}
+%\begin{definition}
+%\cs{DTLifnullorempty}\marg{command}\marg{true part}\marg{false part}
+%\end{definition}
+%\changes{2.20}{2014-02-03}{new}
+% \begin{macrocode}
+\newcommand*{\DTLifnullorempty}[3]{%
+ \ifdefempty{#1}{#2}{\DTLifnull{#1}{#2}{#3}}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtlnovalue}
+% \begin{macrocode}
+\def\@dtlnovalue{Undefined Value}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtlnovalue}
+% \begin{macrocode}
+\def\dtlnovalue{\@dtlnovalue}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLgetkeydata}
+%\begin{definition}
+%\cs{DTLgetkeydata}\marg{key}\marg{db}\marg{col cs}\marg{type cs}\marg{header cs}
+%\end{definition}
+% Gets data for given key in database \meta{db}: the column index is
+% stored in \meta{col cs} and data type is stored in \meta{type cs}.
+% The unstarred version checks for the existance of the database
+% and key, the starred version doesn't.
+% \begin{macrocode}
+\newcommand*{\DTLgetkeydata}{%
+ \@ifstar\@sdtlgetkeydata\@dtlgetkeydata
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtlgetkeydata}
+% Unstarred version of \cs{DTLgetkeydata}
+% \begin{macrocode}
+\newcommand*{\@dtlgetkeydata}[5]{%
+% \end{macrocode}
+% Check if the database exists.
+% \begin{macrocode}
+ \DTLifdbexists{#2}%
+ {%
+% \end{macrocode}
+% Check if the given key exists in the database.
+% \begin{macrocode}
+ \@sDTLifhaskey{#2}{#1}%
+ {%
+% \end{macrocode}
+% Get the data.
+% \begin{macrocode}
+ \@sdtlgetkeydata{#1}{#2}{#3}{#4}{#5}%
+ }%
+ {%
+% \end{macrocode}
+% Key not defined in the given database.
+% \begin{macrocode}
+ \PackageError{datatool}{Key `#1' not defined in database
+ `#2'}{}%
+ }%
+ }%
+ {%
+% \end{macrocode}
+% Database not defined.
+% \begin{macrocode}
+ \PackageError{datatool}{Database `#2' doesn't exist}{}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@sdtlgetkeydata}
+%\cs{@sdtlgetkeydata}\marg{key}\marg{db}\marg{col cs}\marg{type cs}\marg{header cs}
+% Starred verison of \cs{DTLgetkeydata}.
+% \begin{macrocode}
+\newcommand*{\@sdtlgetkeydata}[5]{%
+ \@sdtl@getcolumnindex{#3}{#2}{#1}%
+ \edef\@dtl@dogetkeydata{\noexpand\@dtl@getprops
+ {\noexpand\@dtl@key}{\noexpand#4}{\noexpand\@dtl@colhead}%
+ {\noexpand\@dtl@before}{\noexpand\@dtl@after}%
+ {\expandafter\the\csname dtlkeys@#2\endcsname}%
+ {#3}}%
+ \@dtl@dogetkeydata
+ \edef#5{\the\@dtl@toks}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@gathervalues}
+%\begin{definition}
+%\cs{dtl@gathervalues}\oarg{label}\marg{db name}\marg{row toks}
+%\end{definition}
+% Stores each element of \meta{row} in \meta{db name} into
+% the command \cs{@dtl@}\meta{label}\texttt{@}\meta{key},
+% where \meta{key} is the
+% key for that element, and \meta{label} defaults to "key".
+%\changes{2.0}{2009 February 27}{updated to use new database structure}
+% \begin{macrocode}
+\newcommand{\dtl@gathervalues}[3][key]{%
+ \dtlforeachkey(\@dtl@key,\@dtl@col,\@dtl@type,\@dtl@head)\in{#2}\do
+ {%
+% \end{macrocode}
+%\changes{2.21}{2014-03-08}{fixed bug that ignore row tok argument}
+% \begin{macrocode}
+ \dtlgetentryfromrow{\@dtl@tmp}{\@dtl@col}{#3}%
+ \ifx\@dtl@tmp\dtlnovalue
+ \@dtl@setnull{\@dtl@tmp}{\@dtl@key}%
+ \fi
+ \expandafter\let\csname @dtl@#1@\@dtl@key\endcsname\@dtl@tmp
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@g@gathervalues}
+%\begin{definition}
+%\cs{dtl@g@gathervalues}\oarg{label}\marg{db name}\marg{row toks}
+%\end{definition}
+% As above but makes global assignments
+%\changes{2.21}{2014-03-08}{new}
+% \begin{macrocode}
+\newcommand{\dtl@g@gathervalues}[3][key]{%
+ \dtlforeachkey(\@dtl@key,\@dtl@col,\@dtl@type,\@dtl@head)\in{#2}\do
+ {%
+ \dtlgetentryfromrow{\@dtl@tmp}{\@dtl@col}{#3}%
+ \ifx\@dtl@tmp\dtlnovalue
+ \@dtl@setnull{\@dtl@tmp}{\@dtl@key}%
+ \fi
+ \expandafter\global
+ \expandafter\let\csname @dtl@#1@\@dtl@key\endcsname\@dtl@tmp
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlcurrentrow}
+% Define token register to store current row.
+% \begin{macrocode}
+\newtoks\dtlcurrentrow
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtlbeforerow}
+% Define token register to store everything before the current row.
+% \begin{macrocode}
+\newtoks\dtlbeforerow
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtlafterrow}
+% Define token register to store everything after the current row.
+% \begin{macrocode}
+\newtoks\dtlafterrow
+% \end{macrocode}
+%\end{macro}
+
+%\begin{macro}{\dtlgetrow}
+%\begin{definition}
+%\cs{dtlgetrow}\marg{db}\marg{row idx}
+%\end{definition}
+% Gets row with index \meta{row idx} from database named \meta{db}
+% and stores the row in \cs{dtlcurrentrow}, the preceding rows in
+% \cs{dtlbeforerow} and the following rows in \cs{dtlafterrow}.
+% The row index, \meta{row idx}, is stored in \cs{dtlrownum}
+% and the database name, \meta{db}, is stored in \cs{dtldbname}.
+% This assumes that the given row exists.
+% \begin{macrocode}
+\newcommand*{\dtlgetrow}[2]{%
+ \dtlrownum=#2\relax
+ \edef\dtldbname{#1}%
+ \expandafter\toks@\expandafter=\csname dtldb@#1\endcsname
+ \edef\@dtl@dogetrow{\noexpand\@dtlgetrow{\the\toks@}{\number#2}}%
+ \@dtl@dogetrow
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\edtlgetrowforvalue}
+%\changes{2.17}{2013-08-29}{new}
+%\begin{definition}
+%\cs{edtlgetrowforvalue}\marg{db}\marg{column idx}\marg{value}
+%\end{definition}
+% A version of \cs{dtlgetrowforvalue} that expands its arguments.
+% \begin{macrocode}
+\newcommand{\edtlgetrowforvalue}[3]{%
+ \protected@edef\@dtl@dogetrowforvalue{%
+ \noexpand\dtlgetrowforvalue{#1}{#2}{#3}}%
+ \@dtl@dogetrowforvalue
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLfetch}
+%\changes{2.17}{2013-08-29}{new}
+%\begin{definition}
+%\cs{DTLfetch}\marg{db name}\marg{column1 name}\marg{column1
+%value}\marg{column2 name}
+%\end{definition}
+% Fetches and displays the value for \meta{column2 name} in the
+% first row where the value of \meta{column1 name} is \meta{column1
+% value}. Note that all arguments are expanded.
+% \begin{macrocode}
+\newcommand{\DTLfetch}[4]{%
+ \edtlgetrowforvalue{#1}{\dtlcolumnindex{#1}{#2}}{#3}%
+ \dtlgetentryfromcurrentrow{\dtlcurrentvalue}{\dtlcolumnindex{#1}{#4}}%
+ \dtlcurrentvalue
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlgetrowforvalue}
+%\begin{definition}
+%\cs{dtlgetrowforvalue}\marg{db}\marg{column idx}\marg{value}
+%\end{definition}
+% Like \cs{dtlgetrow}, but gets the row where the entry in column
+% \meta{column index} matches \meta{value}. Produces an error if row
+% not found.
+%\changes{2.11}{2012-09-25}{new}
+% \begin{macrocode}
+\newcommand*{\dtlgetrowforvalue}[3]{%
+ \dtlgetrowindex{\dtl@rowidx}{#1}{#2}{#3}%
+ \ifx\dtl@rowidx\dtlnovalue
+ \PackageError{datatool}{No row found in database `#1' for
+ column `\number#2' matching `#3'}{}%
+ \else
+ \dtlrownum=\dtl@rowidx\relax
+ \edef\dtldbname{#1}%
+ \expandafter\toks@\expandafter=\csname dtldb@#1\endcsname
+ \edef\@dtl@dogetrow{\noexpand\@dtlgetrow{\the\toks@}{\dtl@rowidx}}%
+ \@dtl@dogetrow
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%
+%\begin{macro}{\@dtlgetrow}
+%\begin{definition}
+%\cs{@dtlgetrow}\marg{data specs}\marg{row idx}
+%\end{definition}
+% Gets the row specs from \meta{data specs} for row with index
+% \meta{row idx} which must be fully expanded.
+% \begin{macrocode}
+\newcommand*{\@dtlgetrow}[2]{%
+ \def\@dtl@getrow##1% before stuff
+ \db@row@elt@w% start of the row
+ \db@row@id@w #2\db@row@id@end@% row id
+ ##2%
+ \db@row@id@w #2\db@row@id@end@% row id
+ \db@row@elt@end@% end of the row
+ ##3% after stuff
+ \q@nil{\dtlbeforerow={##1}\dtlcurrentrow={##2}\dtlafterrow={##3}}%
+ \@dtl@getrow#1\q@nil
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlrecombine}
+%\begin{definition}
+%\cs{dtlrecombine}
+%\end{definition}
+% Recombines database contents from \cs{dtlbeforerow},
+% \cs{dtlcurrentrow} and \cs{dtlafterrow}
+% \begin{macrocode}
+\newcommand*{\dtlrecombine}{%
+ \@dtl@toks@gconcat@middle@cx{dtldb@\dtldbname}%
+ {\dtlbeforerow}%
+ {%
+% \end{macrocode}
+% Start of row tag
+% \begin{macrocode}
+ \noexpand\db@row@elt@w
+% \end{macrocode}
+% Row number
+% \begin{macrocode}
+ \noexpand\db@row@id@w
+ \number\dtlrownum
+ \noexpand\db@row@id@end@
+% \end{macrocode}
+% Current row specs:
+% \begin{macrocode}
+ \the\dtlcurrentrow
+% \end{macrocode}
+% Row number
+% \begin{macrocode}
+ \noexpand\db@row@id@w
+ \number\dtlrownum
+ \noexpand\db@row@id@end@
+% \end{macrocode}
+% End of row tag
+% \begin{macrocode}
+ \noexpand\db@row@elt@end@
+ }%
+ {\dtlafterrow}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlrecombineomitcurrent}
+%\begin{definition}
+%\cs{dtlrecombineomitcurrent}
+%\end{definition}
+%Like \cs{dtlrecombine} but omits \cs{dtlcurrentrow}
+%\changes{2.10}{2012-07-18}{new}
+% \begin{macrocode}
+\newcommand{\dtlrecombineomitcurrent}{%
+% \end{macrocode}
+% Decrement row indices in \cs{dtlafterrow}:
+% \begin{macrocode}
+ \dtl@decrementrows{\dtlafterrow}{\dtlrownum}
+% \end{macrocode}
+% Reconstruct database contents by concatenating
+% \cs{dtlbeforerow} and \cs{dtlafterrow}
+% \begin{macrocode}
+ \csname dtldb@\dtldbname\endcsname=\dtlbeforerow
+ \@dtl@toks@gput@right@cx{dtldb@\dtldbname}{\the\dtlafterrow}%
+ \dtl@message{Removed row \number\dtlrownum\space in database
+ `\dtldbname'}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlsplitrow}
+%\begin{definition}
+%\cs{dtlsplitrow}\marg{row specs}\marg{col num}\marg{before
+% cs}\marg{after cs}
+%\end{definition}
+% Splits the row around the entry given by \meta{col num}. The
+% entries before the split are stored in \meta{before cs} and the
+% entries after the split are stored in \meta{after cs}.
+% \meta{row specs} and \meta{col num} need to be expanded before use.
+% \begin{macrocode}
+\newcommand*{\dtlsplitrow}[4]{%
+ \def\@dtlsplitrow##1%before stuff
+ \db@col@id@w #2\db@col@id@end@% column id
+ ##2% unwanted stuff
+ \db@col@id@w #2\db@col@id@end@% column id
+ ##3% after stuff
+ \q@nil{\def#3{##1}\def#4{##3}}%
+ \@dtlsplitrow#1\q@nil
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlreplaceentryincurrentrow}
+%\begin{definition}
+%\cs{dtlreplaceentryincurrentrow}\marg{new value}\marg{col num}
+%\end{definition}
+% Replaces entry for column \meta{col num} in \cs{dtlcurrentrow}
+% with \meta{new value}
+%\changes{2.10}{2012-07-18}{new}
+% \begin{macrocode}
+\newcommand*{\dtlreplaceentryincurrentrow}[2]{%
+% \end{macrocode}
+% Split row
+% \begin{macrocode}
+ \edef\@dtl@do@splitrow{\noexpand\dtlsplitrow
+ {\the\dtlcurrentrow}%
+ {\number#2}%
+ {\noexpand\@dtl@before@cs}%
+ {\noexpand\@dtl@after@cs}}%
+ \@dtl@do@splitrow
+% \end{macrocode}
+% Recombine with new value
+% \begin{macrocode}
+ \toks@{#1}%
+ \edef\@dtl@stuff{%
+ \expandonce\@dtl@before@cs
+% \end{macrocode}
+% Begin column index specs:
+% \begin{macrocode}
+ \noexpand\db@col@id@w \number#2\noexpand
+ \noexpand\db@col@id@end@% column id
+% \end{macrocode}
+% New entry:
+% \begin{macrocode}
+ \noexpand\db@col@elt@w
+ \the\toks@
+ \noexpand\db@col@elt@end@
+% \end{macrocode}
+% End column index specs:
+% \begin{macrocode}
+ \noexpand\db@col@id@w \number#2\noexpand
+ \noexpand\db@col@id@end@% column id
+ \expandonce\@dtl@after@cs
+ }%
+% \end{macrocode}
+% Store in \cs{dtlcurrentrow}
+% \begin{macrocode}
+ \expandafter\dtlcurrentrow\expandafter{\@dtl@stuff}%
+% \end{macrocode}
+% Update column specs
+% \begin{macrocode}
+ \@sdtlgetkeyforcolumn{\@dtl@key}{\dtldbname}{#2}%
+ \@dtl@updatekeys{\dtldbname}{\@dtl@key}{#1}%
+ \dtl@message{Updated \@dtl@key\space -> #1\space in database
+ `\dtldbname'}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlremoveentryincurrentrow}
+%\begin{definition}
+%\cs{dtlremoveentryincurrentrow}\marg{col idx}
+%\end{definition}
+% Removes entry for column \meta{col idx} from \cs{dtlcurrentrow}.
+%\changes{2.10}{2012-07-18}{new}
+% \begin{macrocode}
+\newcommand*{\dtlremoveentryincurrentrow}[1]{%
+% \end{macrocode}
+% Split row
+% \begin{macrocode}
+ \edef\@dtl@do@splitrow{\noexpand\dtlsplitrow
+ {\the\dtlcurrentrow}%
+ {\number#1}%
+ {\noexpand\@dtl@before@cs}%
+ {\noexpand\@dtl@after@cs}}%
+ \@dtl@do@splitrow
+% \end{macrocode}
+% Combine row without given column:
+% \begin{macrocode}
+ \edef\@dtl@stuff{%
+ \expandonce\@dtl@before@cs
+ \expandonce\@dtl@after@cs
+ }%
+% \end{macrocode}
+% Store in \cs{dtlcurrentrow}
+% \begin{macrocode}
+ \expandafter\dtlcurrentrow\expandafter{\@dtl@stuff}%
+ \dtl@message{Removed entry from column \number#1\space\space in database
+ `\dtldbname'}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlswapentriesincurrentrow}
+%\begin{definition}
+%\cs{dtlswapentriesincurrentrow}\marg{col1
+%num}\marg{col2 num}
+%\end{definition}
+% Swaps columns \meta{col1 num} and \meta{col2 num} in \cs{dtlcurrentrow}
+%\changes{2.10}{2012-07-18}{new}
+% \begin{macrocode}
+\newcommand*{\dtlswapentriesincurrentrow}[2]{%
+ \dtlgetentryfromcurrentrow{\@dtl@entryI}{#1}%
+ \dtlgetentryfromcurrentrow{\@dtl@entryII}{#2}%
+ \expandafter\dtlreplaceentryincurrentrow\expandafter
+ {\@dtl@entryII}{#1}%
+ \expandafter\dtlreplaceentryincurrentrow\expandafter
+ {\@dtl@entryI}{#2}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlgetentryfromcurrentrow}
+%\begin{definition}
+%\cs{dtlgetentryfromcurrentrow}\marg{cs}\marg{col num}
+%\end{definition}
+% Gets value for column \meta{col num} from \cs{dtlcurrentrow}
+% and stores in \meta{cs}. If not found, \meta{cs} is set to
+% \cs{dtlnovalue}.
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\newcommand*{\dtlgetentryfromcurrentrow}[2]{%
+ \dtlgetentryfromrow{#1}{#2}{\dtlcurrentrow}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlgetentryfromrow}
+%\begin{definition}
+%\cs{dtlgetentryfromrow}\marg{cs}\marg{col num}\marg{row toks}
+%\end{definition}
+% \begin{macrocode}
+\newcommand*{\dtlgetentryfromrow}[3]{%
+ \edef\@dtl@do@getentry{\noexpand\dtl@getentryfromrow
+ {\noexpand#1}{\number#2}{\the#3}}%
+ \@dtl@do@getentry
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@getentryfromrow}
+%\begin{definition}
+%\cs{dtl@getentryfromrow}\marg{cs}\marg{col num}\marg{row specs}
+%\end{definition}
+% \begin{macrocode}
+\newcommand*{\dtl@getentryfromrow}[3]{%
+ \def\dtl@dogetentry##1% before stuff
+ \db@col@id@w #2\db@col@id@end@% Column id
+ \db@col@elt@w ##2\db@col@elt@end@% Value
+ \db@col@id@w #2\db@col@id@end@% Column id
+ ##3% Remaining stuff
+ \q@nil{\def#1{##2}}%
+ \dtl@dogetentry#3%
+ \db@col@id@w #2\db@col@id@end@%
+ \db@col@elt@w \@dtlnovalue\db@col@elt@end@%
+ \db@col@id@w #2\db@col@id@end@%
+ \q@nil
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlappendentrytocurrentrow}
+%\begin{definition}
+%\cs{dtlappendentrytocurrentrow}\marg{key}\marg{value}
+%\end{definition}
+% Appends entry to \cs{dtlcurrentrow}
+%\changes{2.10}{2012-07-18}{new}
+% \begin{macrocode}
+\newcommand*{\dtlappendentrytocurrentrow}[2]{%
+% \end{macrocode}
+% Update information about this column (adding new column if
+% necessary)
+% \begin{macrocode}
+ \@dtl@updatekeys{\dtldbname}{#1}{#2}%
+% \end{macrocode}
+% Get column index and store in \cs{dtlcolumnnum}
+% \begin{macrocode}
+ \expandafter\dtlcolumnnum\expandafter
+ =\dtlcolumnindex{\dtldbname}{#1}\relax
+% \end{macrocode}
+% Does this row already have an entry with this key?
+% \begin{macrocode}
+ \edef\dtl@dogetentry{\noexpand\dtlgetentryfromcurrentrow
+ {\noexpand\dtl@entry}{\number\dtlcolumnnum}%
+ }%
+ \dtl@dogetentry
+ \ifx\dtl@entry\dtlnovalue
+% \end{macrocode}
+% There are no entries in this row for the given key.
+% Expand entry value before storing.
+% \begin{macrocode}
+ \protected@edef\@dtl@tmp{#2}%
+ \expandafter\@dtl@toks\expandafter{\@dtl@tmp}%
+% \end{macrocode}
+% Append this entry to the current row.
+% \begin{macrocode}
+ \@dtl@toks@gput@right@cx{dtlcurrentrow}%
+ {%
+% \end{macrocode}
+% Begin column index specs:
+% \begin{macrocode}
+ \noexpand\db@col@id@w
+ \number\dtlcolumnnum
+ \noexpand\db@col@id@end@
+% \end{macrocode}
+% New entry:
+% \begin{macrocode}
+ \noexpand\db@col@elt@w
+ \the\@dtl@toks
+ \noexpand\db@col@elt@end@
+% \end{macrocode}
+% End column index specs:
+% \begin{macrocode}
+ \noexpand\db@col@id@w
+ \number\dtlcolumnnum
+ \noexpand\db@col@id@end@
+ }%
+% \end{macrocode}
+% Print information to terminal and log file if in verbose mode.
+% \begin{macrocode}
+ \dtl@message{Appended #1\space -> #2\space to database
+ `\dtldbname'}%
+ \else
+% \end{macrocode}
+% There is already an entry in this row for the given key
+% \begin{macrocode}
+ \PackageError{datatool}{Can't append entry to row:
+ there is already an entry for key `#1' in this row}{}%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlupdateentryincurrentrow}
+%\begin{definition}
+%\cs{dtlupdateentryincurrentrow}\marg{key}\marg{value}
+%\end{definition}
+% Appends entry to \cs{dtlcurrentrow} if column with given key
+% doesn't exist, otherwise updates the value.
+%\changes{2.11}{2012-09-25}{new}
+% \begin{macrocode}
+\newcommand*{\dtlupdateentryincurrentrow}[2]{%
+% \end{macrocode}
+% Update information about this column (adding new column if
+% necessary)
+% \begin{macrocode}
+ \@dtl@updatekeys{\dtldbname}{#1}{#2}%
+% \end{macrocode}
+% Get column index and store in \cs{dtlcolumnnum}
+% \begin{macrocode}
+ \expandafter\dtlcolumnnum\expandafter
+ =\dtlcolumnindex{\dtldbname}{#1}\relax
+% \end{macrocode}
+% Does this row already have an entry with this key?
+% \begin{macrocode}
+ \edef\dtl@dogetentry{\noexpand\dtlgetentryfromcurrentrow
+ {\noexpand\dtl@entry}{\number\dtlcolumnnum}%
+ }%
+ \dtl@dogetentry
+ \ifx\dtl@entry\dtlnovalue
+% \end{macrocode}
+% There are no entries in this row for the given key.
+% Expand entry value before storing.
+% \begin{macrocode}
+ \protected@edef\@dtl@tmp{#2}%
+ \expandafter\@dtl@toks\expandafter{\@dtl@tmp}%
+% \end{macrocode}
+% Append this entry to the current row.
+% \begin{macrocode}
+ \@dtl@toks@gput@right@cx{dtlcurrentrow}%
+ {%
+% \end{macrocode}
+% Begin column index specs:
+% \begin{macrocode}
+ \noexpand\db@col@id@w
+ \number\dtlcolumnnum
+ \noexpand\db@col@id@end@
+% \end{macrocode}
+% New entry:
+% \begin{macrocode}
+ \noexpand\db@col@elt@w
+ \the\@dtl@toks
+ \noexpand\db@col@elt@end@
+% \end{macrocode}
+% End column index specs:
+% \begin{macrocode}
+ \noexpand\db@col@id@w
+ \number\dtlcolumnnum
+ \noexpand\db@col@id@end@
+ }%
+% \end{macrocode}
+% Print information to terminal and log file if in verbose mode.
+% \begin{macrocode}
+ \dtl@message{Appended #1\space -> #2\space to database
+ `\dtldbname'}%
+ \else
+% \end{macrocode}
+% There is already an entry in this row for the given key
+% \begin{macrocode}
+ \toks@{#2}%
+ \edef\do@dtlreplaceincurrentrow{%
+ \noexpand\dtlreplaceentryincurrentrow{\the\toks@}{\number\dtlcolumnnum}%
+ }%
+ \do@dtlreplaceincurrentrow
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLgetvalue}
+%\begin{definition}
+%\cs{DTLgetvalue}\marg{cs}\marg{db}\marg{r}\marg{c}
+%\end{definition}
+% Gets the element in row \meta{r}, column \meta{c} from database
+% \meta{db} and stores in \meta{cs}.
+% \begin{macrocode}
+\newcommand*{\DTLgetvalue}[4]{%
+ \edef\dtl@dogetvalue{\noexpand\dtl@getvalue{\noexpand#1}{#2}%
+ {\number#3}{\number#4}}%
+ \dtl@dogetvalue
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@getvalue}
+% \begin{macrocode}
+\newcommand*{\dtl@getvalue}[4]{%
+ \def\@dtl@getvalue ##1% stuff before row <r>
+ \db@row@id@w #3\db@row@id@end@% row <r> id
+ ##2% stuff in row <r> before column <c>
+ \db@col@id@w #4\db@col@id@end@% column <c> id
+ \db@col@elt@w ##3\db@col@elt@end@% value
+ ##4% stuff after value
+ \q@nil{\def#1{##3}}%
+ \toks@=\csname dtldb@#2\endcsname
+ \expandafter\@dtl@getvalue\the\toks@% contents of data base
+ \db@row@id@w #3\db@row@id@end@%
+ \db@col@id@w #4\db@col@id@end@%
+ \db@col@elt@w \@dtlnovalue\db@col@elt@end@% undefined value
+ \q@nil
+ \ifx#1\dtlnovalue
+ \PackageError{datatool}{There is no element at (row=#3,\space
+ column=#4) in database `#2'}{}%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLgetlocation}
+%\begin{definition}
+%\cs{DTLgetlocation}\marg{row cs}\marg{column cs}\marg{database}%
+%\marg{value}
+%\end{definition}
+% Assigns \meta{row cs} and \meta{column cs} to the indices of the
+% first entry in \meta{database} that matches \meta{value}.
+% \begin{macrocode}
+\newcommand*{\DTLgetlocation}[4]{%
+ \def\@dtl@getlocation##1% stuff before value
+ \db@col@elt@w #4\db@col@elt@end@% value
+ \db@col@id@w ##2\db@col@id@end@% column id
+ ##3% stuff after this column
+ \db@row@id@w ##4\db@row@id@end@% row id
+ ##5% stuff after row
+ \q@nil{\def#1{##4}\def#2{##2}}%
+ \toks@=\csname dtldb@#3\endcsname
+ \expandafter\@dtl@getlocation\the\toks@% contents of data base
+ \db@col@elt@w #4\db@col@elt@end@% value
+ \db@col@id@w \@dtlnovalue\db@col@id@end@% undefined column id
+ \db@row@id@w \@dtlnovalue\db@row@id@end@% undefined row id
+ \q@nil
+ \ifx#1\dtlnovalue
+ \PackageError{datatool}{There is no element `#4' in database `#3'}{}%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLgetrowindex}
+%\begin{definition}
+%\cs{DTLgetrowindex}\marg{row cs}\marg{database}\marg{column index}%
+%\marg{value}
+%\end{definition}
+% Assigns \meta{row cs} to the row index of the
+% first entry in \meta{database} where the entry in \meta{column
+% index} matches \meta{value}.
+%\changes{2.11}{2012-09-25}{new}
+% \begin{macrocode}
+\newcommand*{\DTLgetrowindex}[4]{%
+ \toks@{#4}%
+ \edef\dtl@dogetrowindex{\noexpand\@dtlgetrowindex{\noexpand#1}{#2}{\number#3}{\the\toks@}}%
+ \dtl@dogetrowindex
+ \ifx#1\dtlnovalue
+ \PackageError{datatool}{There is no element `#4' for column
+ \number#3\space in database `#2'}{}%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlgetrowindex}
+%\begin{definition}
+%\cs{dtlgetrowindex}\marg{row cs}\marg{database}\marg{column index}%
+%\marg{value}
+%\end{definition}
+% As above but doesn't produce an error if not found.
+%\changes{2.11}{2012-09-25}{new}
+% \begin{macrocode}
+\newcommand*{\dtlgetrowindex}[4]{%
+ \toks@{#4}%
+ \edef\dtl@dogetrowindex{\noexpand\@dtlgetrowindex{\noexpand#1}{#2}{\number#3}{\the\toks@}}%
+ \dtl@dogetrowindex
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\xdtlgetrowindex}
+%\begin{definition}
+%\cs{xdtlgetrowindex}\marg{row cs}\marg{database}\marg{column index}%
+%\marg{value}
+%\end{definition}
+% As above but expands the value.
+%\changes{2.28}{2017-11-10}{new}
+% \begin{macrocode}
+\newcommand*{\xdtlgetrowindex}[4]{%
+ \protected@edef\dtl@dogetrowindex{\noexpand\@dtlgetrowindex{\noexpand#1}{#2}{\number#3}{#4}}%
+ \dtl@dogetrowindex
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtlgetrowindex}
+%\begin{definition}
+%\cs{@dtlgetrowindex}\marg{row cs}\marg{database}\marg{column index}%
+%\marg{value}
+%\end{definition}
+% Column index must be fully expanded.
+%\changes{2.11}{2012-09-25}{new}
+% \begin{macrocode}
+\newcommand*{\@dtlgetrowindex}[4]{%
+ \def\@dtl@getrowindex##1% stuff before value
+ \db@col@elt@w #4\db@col@elt@end@% value
+ \db@col@id@w #3\db@col@id@end@% column id
+ ##2% stuff after this column
+ \db@row@id@w ##3\db@row@id@end@% row id
+ ##4% stuff after row
+ \q@nil{\def#1{##3}}%
+ \toks@=\csname dtldb@#2\endcsname
+ \expandafter\@dtl@getrowindex\the\toks@% contents of data base
+ \db@col@elt@w #4\db@col@elt@end@% value
+ \db@col@id@w #3\db@col@id@end@% column id
+ \db@row@id@w \@dtlnovalue\db@row@id@end@% undefined row id
+ \q@nil
+}
+% \end{macrocode}
+%\end{macro}
+
+
+%\section{Iterating Through Databases}
+%\label{sec:code:loops}
+%
+%\begin{macro}{\@dtlforeachrow}
+%\begin{definition}
+%\cs{@dtlforeachrow}(\meta{idx cs},\meta{row cs})\cs{in}\marg{db}%
+%\cs{do}\marg{body}
+%\end{definition}
+% Iterates through each row in database. Assigns the current row
+% index to \meta{idx cs} and the row specs to \meta{row cs}
+% \begin{macrocode}
+\long\def\@dtlforeachrow(#1,#2)\in#3\do#4{%
+ \edef\dtl@tmp{\expandafter\the\csname dtldb@#3\endcsname}%
+ \expandafter\@dtl@foreachrow\dtl@tmp
+ \db@row@elt@w%
+ \db@row@id@w \@nil\db@row@id@end@%
+ \db@row@id@w \@nil\db@row@id@end@%
+ \db@row@elt@end@%
+ \@@{#1}{#2}{#4}\q@nil
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@foreachrow}
+% \begin{macrocode}
+\long\def\@dtl@foreachrow\db@row@elt@w%
+\db@row@id@w #1\db@row@id@end@%
+#2\db@row@id@w #3\db@row@id@end@%
+\db@row@elt@end@#4\@@#5#6#7\q@nil{%
+% \end{macrocode}
+% Define control sequence given by "#5"
+% \begin{macrocode}
+ \gdef#5{#1}%
+% \end{macrocode}
+% Hide the loop body in a macro
+% \begin{macrocode}
+ \gdef\@dtl@loopbody{#7}%
+% \end{macrocode}
+% Increment level counter to allow for nested loops
+% \begin{macrocode}
+ \global\advance\@dtl@foreach@level by 1\relax
+% \end{macrocode}
+% Check if we have reached the end of the loop
+% \begin{macrocode}
+ \ifx#5\@nnil
+ \expandafter\global\expandafter
+ \let\csname @dtl@foreachnext\the\@dtl@foreach@level\endcsname
+ =\@dtl@foreachnoop
+ \else
+ \gdef#6{#2}%
+% \end{macrocode}
+% Set up the break function:
+% Make a copy of current break function
+% \begin{macrocode}
+ \expandafter\let
+ \csname @dtl@break@\the\@dtl@foreach@level\endcsname
+ \dtlbreak
+% \end{macrocode}
+% Setup break function for this level
+% \begin{macrocode}
+ \gdef\dtlbreak{\expandafter\global\expandafter
+ \let\csname @dtl@foreachnext\the\@dtl@foreach@level\endcsname
+ =\@dtl@foreachnoop}%
+% \end{macrocode}
+% Initialise
+% \begin{macrocode}
+ \expandafter\global\expandafter
+ \let\csname @dtl@foreachnext\the\@dtl@foreach@level\endcsname
+ =\@dtl@foreachrow
+% \end{macrocode}
+% Do body of loop
+% \begin{macrocode}
+ \@dtl@loopbody
+% \end{macrocode}
+% Restore break function
+% \begin{macrocode}
+ \expandafter\let\expandafter\dtlbreak
+ \csname @dtl@break@\the\@dtl@foreach@level\endcsname
+ \fi
+% \end{macrocode}
+% Set up what to do next.
+% \begin{macrocode}
+ \expandafter\let\expandafter\@dtl@foreachnext
+ \csname @dtl@foreachnext\the\@dtl@foreach@level\endcsname
+% \end{macrocode}
+% Decrement level counter.
+% \begin{macrocode}
+ \global\advance\@dtl@foreach@level by -1\relax
+% \end{macrocode}
+% Repeat loop if necessary.
+% \begin{macrocode}
+ \@dtl@foreachnext#4\@@{#5}{#6}{#7}\q@nil
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@foreachnoop}
+% \begin{macrocode}
+\long\def\@dtl@foreachnoop#1\@@#2\q@nil{}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlforeachkey}
+%\begin{definition}
+%\cs{dtlforeachkey}(\meta{key cs},\meta{col cs},\meta{type cs},\meta{header cs})%
+%\cs{in}\marg{db}\cs{do}\marg{body}
+%\end{definition}
+% Iterates through all the keys in database \meta{db}. In each
+% iteration, \meta{key cs} stores the key, \meta{col cs} stores the
+% column index,\meta{type cs} stores the data type and \meta{header
+% cs} stores the header.
+% \begin{macrocode}
+\long\def\dtlforeachkey(#1,#2,#3,#4)\in#5\do#6{%
+ \gdef\@dtl@loopbody{#6}%
+ \edef\@dtl@keys{\expandafter\the\csname dtlkeys@#5\endcsname}%
+ \expandafter\@dtl@foreachkey\@dtl@keys
+ \db@plist@elt@w%
+ \db@col@id@w -1\db@col@id@end@%
+ \db@key@id@w \db@key@id@end@%
+ \db@type@id@w \db@type@id@end@%
+ \db@header@id@w \db@header@id@end@%
+ \db@col@id@w -1\db@col@id@end@%
+ \db@plist@elt@end@%
+ \@@{\@dtl@updatefkcs{#1}{#2}{#3}{#4}}\q@nil
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@updatefkcs}
+% \begin{macrocode}
+\newcommand*{\@dtl@updatefkcs}[8]{%
+ \gdef#1{#5}%
+ \gdef#2{#6}%
+ \gdef#3{#7}%
+ \gdef#4{#8}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@foreachkey}
+% Sets everything globally in case it occurs in a tabular environment
+% Loop body needs to be stored in \cs{@dtl@loopbody}.
+% "#7" indicates an update macro.
+% \begin{macrocode}
+\long\def\@dtl@foreachkey\db@plist@elt@w%
+\db@col@id@w #1\db@col@id@end@%
+\db@key@id@w #2\db@key@id@end@%
+\db@type@id@w #3\db@type@id@end@%
+\db@header@id@w #4\db@header@id@end@%
+\db@col@id@w #5\db@col@id@end@%
+\db@plist@elt@end@#6\@@#7\q@nil{%
+ \ifnum#1=-1\relax
+% \end{macrocode}
+% Terminate loop
+% \begin{macrocode}
+ \let\@dtl@foreachnext\@dtl@foreachnoop
+ \else
+% \end{macrocode}
+% Set up loop variables
+% \begin{macrocode}
+ #7{#2}{#1}{#3}{#4}%
+% \end{macrocode}
+% Increment level counter to allow for nested loops
+% \begin{macrocode}
+ \global\advance\@dtl@foreach@level by 1\relax
+% \end{macrocode}
+% Set up the break function
+% \begin{macrocode}
+ \expandafter\let
+ \csname @dtl@break@\the\@dtl@foreach@level\endcsname
+ \dtlbreak
+ \gdef\dtlbreak{\expandafter\global\expandafter
+ \let\csname @dtl@foreachnext\the\@dtl@foreach@level\endcsname
+ =\@dtl@foreachnoop}%
+% \end{macrocode}
+% Initialise
+% \begin{macrocode}
+ \expandafter\global\expandafter
+ \let\csname @dtl@foreachnext\the\@dtl@foreach@level\endcsname
+ =\@dtl@foreachkey
+% \end{macrocode}
+% Do body of loop
+% \begin{macrocode}
+ \@dtl@loopbody
+% \end{macrocode}
+% Set up what to do next
+% \begin{macrocode}
+ \expandafter\let\expandafter\@dtl@foreachnext
+ \csname @dtl@foreachnext\the\@dtl@foreach@level\endcsname
+% \end{macrocode}
+% Restore break function
+% \begin{macrocode}
+ \expandafter\let\expandafter\dtlbreak
+ \csname @dtl@break@\the\@dtl@foreach@level\endcsname
+% \end{macrocode}
+% Decrement level counter
+% \begin{macrocode}
+ \global\advance\@dtl@foreach@level by -1\relax
+ \fi
+% \end{macrocode}
+% Recurse if necessary
+% \begin{macrocode}
+ \@dtl@foreachnext#6\@@{#7}\q@nil
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlforcolumn}
+%\begin{definition}
+%\cs{dtlforcolumn}\marg{cs}\marg{db}\marg{key}\marg{body}
+%\end{definition}
+% Iterates through column given by \meta{key} in database \meta{db}.
+% \meta{cs} is assign to the element of the column in the
+% current iteration. Starred version doesn't check if data base
+% exists
+% \begin{macrocode}
+\newcommand*{\dtlforcolumn}{\@ifstar\@sdtlforcolumn\@dtlforcolumn}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtlforcolumn}
+% \begin{macrocode}
+\newcommand{\@dtlforcolumn}[4]{%
+% \end{macrocode}
+% Check if data base exists
+% \begin{macrocode}
+ \DTLifdbexists{#2}%
+ {%
+ \@DTLifhaskey{#2}{#3}%
+ {%
+ \@sdtlforcolumn{#1}{#2}{#3}{#4}%
+ }%
+% \end{macrocode}
+% key not in data base
+% \begin{macrocode}
+ {%
+ \PackageError{datatool}{Database `#2' doesn't contain
+ key `#3'}{}%
+ }%
+ }%
+%
+ {%
+ \PackageError{datatool}{Database `#2' doesn't exist}{}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@sdtlforcolumn}
+% \begin{macrocode}
+\newcommand{\@sdtlforcolumn}[4]{%
+ \toks@{#4}%
+ \edef\@dtl@doforcol{\noexpand\dtl@forcolumn{\noexpand#1}%
+ {\expandafter\the\csname dtldb@#2\endcsname}%
+ {\dtlcolumnindex{#2}{#3}}{\the\toks@}%
+ }%
+ \@dtl@doforcol%
+}
+% end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlforcolumnidx}
+%\begin{definition}
+%\cs{dtlforcolumnidx}\marg{cs}\marg{db}\marg{col num}\marg{body}
+%\end{definition}
+% Iterates through the column with index <col num> in database <db>.
+% Starred version doesn't check if database exists.
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\newcommand*{\dtlforcolumnidx}{%
+ \@ifstar\@sdtlforcolumnidx\@dtlforcolumnidx
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtlforcolumnidx}
+% \begin{macrocode}
+\newcommand{\@dtlforcolumnidx}[4]{%
+ \DTLifdbexists{#2}%
+ {%
+ \expandafter\ifnum\csname dtlcols@#2\endcsname<#3\relax
+ \PackageError{datatool}{Column index \number#3\space out of
+ bounds for database `#2'}{Database `#2' only has
+ \expandafter\number\csname dtlcols@#2\endcsname\space
+ columns}%
+ \else
+ \ifnum#3<1\relax
+ \PackageError{datatool}{Column index \number#3\space out of
+ bounds for database `#2'}{Indices start from 1}%
+ \else
+ \@sdtlforcolumnidx{#1}{#2}{#3}{#4}%
+ \fi
+ \fi
+ }%
+% \end{macrocode}
+% data base doesn't exist
+% \begin{macrocode}
+ {%
+ \PackageError{datatool}{Database `#2' doesn't exist}{}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@sdtlforcolumnidx}
+% \begin{macrocode}
+\newcommand{\@sdtlforcolumnidx}[4]{%
+ \toks@{#4}%
+ \edef\@dtl@doforcol{\noexpand\dtl@forcolumn{\noexpand#1}%
+ {\expandafter\the\csname dtldb@#2\endcsname}%
+ {\number#3}{\the\toks@}%
+ }%
+ \@dtl@doforcol
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@forcolumn}
+%\begin{definition}
+%\cs{dtl@forcolumn}\marg{cs}\marg{db specs}\marg{col num}\marg{body}
+%\end{definition}
+% \meta{col num} needs to be fully expanded
+% \begin{macrocode}
+\newcommand{\dtl@forcolumn}[4]{%
+% \end{macrocode}
+% make a copy of break function
+% \begin{macrocode}
+ \let\@dtl@oldbreak\dtlbreak
+% \end{macrocode}
+% set up break function
+% \begin{macrocode}
+ \def\dtlbreak{\let\@dtl@forcolnext=\@dtl@forcolnoop}%
+% \end{macrocode}
+% define loop macro for this column
+% \begin{macrocode}
+ \def\@dtl@forcolumn##1% before stuff
+ \db@col@id@w #3\db@col@id@end@% column index
+ \db@col@elt@w ##2\db@col@elt@end@% entry
+ \db@col@id@w #3\db@col@id@end@% column index
+ ##3% after stuff
+ \q@nil{%
+ \def#1{##2}% assign value to <cs>
+% \end{macrocode}
+% check if end of loop
+% \begin{macrocode}
+ \ifx#1\@nnil
+ \let\@dtl@forcolnext=\@dtl@forcolnoop
+ \else
+% \end{macrocode}
+% do body of loop
+% \begin{macrocode}
+ #4%
+ \let\@dtl@forcolnext=\@dtl@forcolumn
+ \fi
+% \end{macrocode}
+% repeat if necessary
+% \begin{macrocode}
+ \@dtl@forcolnext##3\q@nil
+ }%
+% \end{macrocode}
+% do loop
+% \begin{macrocode}
+ \@dtl@forcolumn#2%
+ \db@col@id@w #3\db@col@id@end@%
+ \db@col@elt@w \@nil\db@col@elt@end@%
+ \db@col@id@w #3\db@col@id@end@\q@nil
+% \end{macrocode}
+% restore break function
+% \begin{macrocode}
+ \let\dtlbreak\@dtl@oldbreak
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@dtl@forcolnoop}
+% \begin{macrocode}
+\def\@dtl@forcolnoop#1\q@nil{}
+% \end{macrocode}
+%\end{macro}
+
+%\begin{macro}{\dtlforeachlevel}
+%\cs{DTLforeach} can only be nested up to three levels.
+% \cs{dtlforeachlevel} keeps track of the current level.
+% \begin{macrocode}
+\newcount\dtlforeachlevel
+% \end{macrocode}
+%\end{macro}
+%
+% The counter DTLrow\meta{n} keeps track of each row of data during
+% the \meta{n} nested \cs{DTLforeach}. It is only incremented in the
+% conditions (given by the optional argument) are met.
+% \begin{macrocode}
+\newcounter{DTLrowi}
+\newcounter{DTLrowii}
+\newcounter{DTLrowiii}
+% \end{macrocode}
+% Keep \sty{hyperref} happy
+% \begin{macrocode}
+\newcounter{DTLrow}
+\def\theHDTLrow{\arabic{DTLrow}}
+\def\theHDTLrowi{\theHDTLrow.\arabic{DTLrowi}}
+\def\theHDTLrowii{\theHDTLrowi.\arabic{DTLrowii}}
+\def\theHDTLrowiii{\theHDTLrowii.\arabic{DTLrowiii}}
+% \end{macrocode}
+%
+% \begin{macrocode}
+\newcount\dtl@rowi
+\newcount\dtl@rowii
+\newcount\dtl@rowiii
+% \end{macrocode}
+%
+% \begin{macrocode}
+\newtoks\@dtl@curi
+\newtoks\@dtl@previ
+\newtoks\@dtl@nexti
+\newtoks\@dtl@curii
+\newtoks\@dtl@previi
+\newtoks\@dtl@nextii
+\newtoks\@dtl@curiii
+\newtoks\@dtl@previii
+\newtoks\@dtl@nextiii
+% \end{macrocode}
+%
+%\begin{macro}{\DTLsaverowcount}
+%\begin{definition}
+%\cs{DTLsavelastrowcount}\marg{cmd}
+%\end{definition}
+% Stores the maximum row count for the last \cs{DTLforeach}.
+% \begin{macrocode}
+\newcommand*{\DTLsavelastrowcount}[1]{%
+\ifnum\dtlforeachlevel>2\relax
+ \def#1{0}%
+\else
+ \ifnum\dtlforeachlevel<0\relax
+ \def#1{0}%
+ \else
+ \@dtl@tmpcount=\dtlforeachlevel
+ \advance\@dtl@tmpcount by 1\relax
+ \edef#1{\expandafter\number
+ \csname c@DTLrow\romannumeral\@dtl@tmpcount\endcsname}%
+ \fi
+\fi}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{environment}{DTLenvforeach}
+% Environment form of \cs{DTLforeach} (contents are gathered, so
+% verbatim can't be used).
+% \begin{macrocode}
+\newenvironment{DTLenvforeach}[3][\boolean{true}]%
+{%
+ \def\@dtlenvforeach@args{[#1]{#2}{#3}}%
+ \long@collect@body\@do@dtlenvforeach
+}%
+{}
+\newcommand{\@do@dtlenvforeach}[1]{%
+ \expandafter\@DTLforeach\@dtlenvforeach@args{#1}%
+}
+% \end{macrocode}
+%\end{environment}
+%
+%\begin{environment}{DTLenvforeach*}
+% Environment form of \cs{DTLforeach*} (contents are gathered, so
+% verbatim can't be used).
+% \begin{macrocode}
+\newenvironment{DTLenvforeach*}[3][\boolean{true}]%
+{%
+ \def\s@dtlenvforeach@args{[#1]{#2}{#3}}%
+ \long@collect@body\@do@sdtlenvforeach
+}%
+{}
+\newcommand{\@do@sdtlenvforeach}[1]{%
+ \expandafter\@sDTLforeach\s@dtlenvforeach@args{#1}%
+}
+% \end{macrocode}
+%\end{environment}
+%
+%\begin{macro}{\DTLforeach}
+%\begin{definition}
+% \cs{DTLforeach}\oarg{conditions}\marg{db name}\marg{values}\marg{text}
+%\end{definition}
+% For each row of data in the database given by \meta{db name},
+% do \meta{text}, if the specified conditions are satisfied.
+% The argument \marg{values} is a comma separated list of
+% \meta{cmd}\texttt{=}\meta{key} pairs. At the start of each row,
+% each of the commands in this list are set to the value of the
+% entry with the corresponding key \meta{key}.
+% (\cs{gdef} is used to ensure \cs{DTLforeach} works in a tabular
+% environment.) The database may be edited in the unstarred
+% version, in the starred version the database is read only.
+%\changes{1.01}{2007 Aug 17}{added starred version}
+% \begin{macrocode}
+\newcommand*{\DTLforeach}{\@ifstar\@sDTLforeach\@DTLforeach}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@DTLforeach}
+% \cs{@DTLforeach} is the unstarred version of \cs{DTLforeach}.
+% The database is reconstructed to allow for rows to be edited.
+% Use the starred version for faster access.
+%\changes{2.0}{2009 February 27}{updated to use new database structure}
+% \begin{macrocode}
+\newcommand{\@DTLforeach}[4][\boolean{true}]{%
+% \end{macrocode}
+% Check database exists
+% \begin{macrocode}
+ \DTLifdbexists{#2}%
+ {%
+% \end{macrocode}
+% Keep \sty{hyperref} happy
+% \begin{macrocode}
+ \refstepcounter{DTLrow}%
+% \end{macrocode}
+% Make it global (so that it works in tabular environment)
+% \begin{macrocode}
+ \global\c@DTLrow=\c@DTLrow\relax
+% \end{macrocode}
+% Store database name
+%\changes{2.20}{2014-02-03}{change \cs{gdef} to \cs{xdef}}
+% \begin{macrocode}
+ \xdef\@dtl@dbname{#2}%
+% \end{macrocode}
+% Increment level and check not exceeded 3
+% \begin{macrocode}
+ \global\advance\dtlforeachlevel by 1\relax
+ \ifnum\dtlforeachlevel>3\relax
+ \PackageError{datatool}{\string\DTLforeach\space nested too
+ deeply}{Only 3 levels are allowed}%
+ \else
+ \@DTLifdbempty{#2}%
+% \end{macrocode}
+% Do nothing if database is empty
+% \begin{macrocode}
+ {}%
+ {%
+% \end{macrocode}
+% Set level dependent information (needs to be global to ensure
+% it works in the \env{tabular} environment). Row counter:
+% \begin{macrocode}
+ \expandafter\global
+ \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname
+ = 0\relax
+% \end{macrocode}
+% Store previous value of \cs{DTLiffirstrow}
+% \begin{macrocode}
+ \expandafter\global\expandafter\let%
+ \csname @dtl@iffirstrow\the\dtlforeachlevel\endcsname
+ \DTLiffirstrow
+% \end{macrocode}
+% Define current \cs{DTLiffirstrow}
+% \begin{macrocode}
+ \gdef\DTLiffirstrow##1##2{%
+ \expandafter\ifnum
+ \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname
+ =1\relax
+ ##1%
+ \else
+ ##2%
+ \fi}%
+% \end{macrocode}
+% Store previous value of \cs{DTLiflastrow}
+% \begin{macrocode}
+ \expandafter\global\expandafter\let%
+ \csname @dtl@iflastrow\the\dtlforeachlevel\endcsname
+ \DTLiflastrow
+% \end{macrocode}
+% Define current \cs{DTLiflastrow}
+%\changes{2.12}{2012-11-30}{fixed bug in \cs{DTLiflastrow}}
+% \begin{macrocode}
+ \gdef\DTLiflastrow##1##2{%
+ \expandafter\ifnum
+ \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname
+ =\csname dtlrows@#2\endcsname\relax
+ ##1%
+ \else
+ ##2%
+ \fi}%
+% \end{macrocode}
+% Store previous value of \cs{DTLifoddrow}
+% \begin{macrocode}
+ \expandafter\global\expandafter\let%
+ \csname @dtl@ifoddrow\the\dtlforeachlevel\endcsname
+ \DTLifoddrow
+% \end{macrocode}
+% Define current \cs{DTLifoddrow}
+% \begin{macrocode}
+ \gdef\DTLifoddrow##1##2{%
+ \expandafter\ifodd
+ \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname
+ ##1%
+ \else
+ ##2%
+ \fi}%
+% \end{macrocode}
+% Store data base name for current level
+% \begin{macrocode}
+ \expandafter\global\expandafter\let
+ \csname @dtl@dbname@\romannumeral\dtlforeachlevel\endcsname
+ =\@dtl@dbname
+% \end{macrocode}
+% Mark it as not read only
+% \begin{macrocode}
+ \expandafter\global\expandafter\let
+ \csname @dtl@ro@\romannumeral\dtlforeachlevel\endcsname
+ = 0\relax
+% \end{macrocode}
+% Loop through each row.
+% Loop counter given by \cs{dtl@row}\meta{level}
+% \begin{macrocode}
+ \dtlgforint
+ \csname dtl@row\romannumeral\dtlforeachlevel\endcsname
+ =1\to\csname dtlrows@#2\endcsname\step1\do
+ {%
+% \end{macrocode}
+% Get current row from the data base
+% \begin{macrocode}
+ \@dtl@tmpcount=
+ \csname dtl@row\romannumeral\dtlforeachlevel\endcsname
+ \edef\dtl@dogetrow{\noexpand\dtlgetrow{#2}%
+ {\number\@dtl@tmpcount}}%
+ \dtl@dogetrow
+% \end{macrocode}
+% Store the current row for this level
+% \begin{macrocode}
+ \expandafter\global
+ \csname @dtl@cur\romannumeral\dtlforeachlevel\endcsname
+ = \dtlcurrentrow
+% \end{macrocode}
+% Store the previous rows for this level
+% \begin{macrocode}
+ \expandafter\global
+ \csname @dtl@prev\romannumeral\dtlforeachlevel\endcsname
+ = \dtlbeforerow
+% \end{macrocode}
+% Store the subsequent rows for this level
+% \begin{macrocode}
+ \expandafter\global
+ \csname @dtl@next\romannumeral\dtlforeachlevel\endcsname
+ = \dtlafterrow
+% \end{macrocode}
+% Assign commands to the required entries
+% \begin{macrocode}
+ \ifx\relax#3\relax
+ \else
+ \@dtl@assign{#3}{#2}%
+ \fi
+% \end{macrocode}
+% Do the main body of text if condition is satisfied
+% \begin{macrocode}
+ \ifthenelse{#1}%
+ {%
+% \end{macrocode}
+% Increment user row counter
+% \begin{macrocode}
+ \refstepcounter{DTLrow\romannumeral\dtlforeachlevel}%
+ \expandafter\edef\expandafter\DTLcurrentindex%
+ \expandafter{%
+ \arabic{DTLrow\romannumeral\dtlforeachlevel}}%
+ #4%
+% \end{macrocode}
+% Has this row been marked for deletion?
+% \begin{macrocode}
+ \edef\@dtl@tmp{\expandafter\the
+ \csname @dtl@cur\romannumeral
+ \dtlforeachlevel\endcsname}%
+ \ifx\@dtl@tmp\@nnil
+% \end{macrocode}
+% Row needs to be deleted
+% Decrement row indices for rows with a higher index than this one
+% \begin{macrocode}
+ \expandafter\dtl@decrementrows\expandafter
+ {\csname @dtl@prev\romannumeral
+ \dtlforeachlevel\endcsname
+ }{\csname dtl@row\romannumeral
+ \dtlforeachlevel\endcsname}%
+ \expandafter\dtl@decrementrows\expandafter
+ {\csname @dtl@next\romannumeral
+ \dtlforeachlevel\endcsname
+ }{\csname dtl@row\romannumeral
+ \dtlforeachlevel\endcsname}%
+% \end{macrocode}
+% Reconstruct data base without this row
+% \begin{macrocode}
+ \edef\@dtl@tmp{%
+ \expandafter\the
+ \csname @dtl@prev\romannumeral
+ \dtlforeachlevel\endcsname
+ \expandafter\the
+ \csname @dtl@next\romannumeral
+ \dtlforeachlevel\endcsname
+ }%
+ \expandafter\global\expandafter
+ \csname dtldb@#2\endcsname\expandafter{\@dtl@tmp}%
+% \end{macrocode}
+% Decrement the row count for this database:
+% \begin{macrocode}
+ \expandafter\global\expandafter
+ \advance\csname dtlrows@#2\endcsname by -1\relax
+% \end{macrocode}
+% Decrement the counter for this loop
+% \begin{macrocode}
+ \expandafter\global\expandafter
+ \advance\csname dtl@row\romannumeral
+ \dtlforeachlevel\endcsname by -1\relax
+ \else
+% \end{macrocode}
+% Reconstruct data base
+% \begin{macrocode}
+ \@dtl@before=\csname @dtl@prev\romannumeral
+ \dtlforeachlevel\endcsname
+ \@dtl@after=\csname @dtl@next\romannumeral
+ \dtlforeachlevel\endcsname
+ \@dtl@toks@gconcat@middle@cx{dtldb@#2}%
+ {\@dtl@before}%
+ {%
+% \end{macrocode}
+% This row
+% \begin{macrocode}
+ \noexpand\db@row@elt@w%
+ \noexpand\db@row@id@w \expandafter\number
+ \csname dtl@row\romannumeral
+ \dtlforeachlevel\endcsname
+ \noexpand\db@row@id@end@%
+ \expandafter\the
+ \csname @dtl@cur\romannumeral
+ \dtlforeachlevel\endcsname
+ \noexpand\db@row@id@w \expandafter\number
+ \csname dtl@row\romannumeral
+ \dtlforeachlevel\endcsname
+ \noexpand\db@row@id@end@%
+ \noexpand\db@row@elt@end@%
+ }%
+ {\@dtl@after}%
+ \fi
+ }%
+% \end{macrocode}
+% Condition not met so ignore
+% \begin{macrocode}
+ {}%
+ }%
+% \end{macrocode}
+% Restore previous value of \cs{DTLiffirstrow}
+% \begin{macrocode}
+ \expandafter\global\expandafter\let\expandafter\DTLiffirstrow
+ \csname @dtl@iffirstrow\the\dtlforeachlevel\endcsname
+% \end{macrocode}
+% Restore previous value of \cs{DTLiflastrow}
+% \begin{macrocode}
+ \expandafter\global\expandafter\let\expandafter\DTLiflastrow
+ \csname @dtl@iflastrow\the\dtlforeachlevel\endcsname
+% \end{macrocode}
+% Restore previous value of \cs{DTLifoddrow}
+% \begin{macrocode}
+ \expandafter\global\expandafter\let\expandafter\DTLifoddrow
+ \csname @dtl@ifoddrow\the\dtlforeachlevel\endcsname
+ }%
+ \fi
+% \end{macrocode}
+% Decrement level
+% \begin{macrocode}
+ \global\advance\dtlforeachlevel by -1\relax
+ }%
+% \end{macrocode}
+% else part (data base doesn't exist):
+% \begin{macrocode}
+ {%
+ \PackageError{datatool}{Database `#2' doesn't exist}{}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@sDTLforeach}
+% \cs{@sDTLforeach} is the starred version of \cs{DTLforeach}.
+% The database rows can't be edited.
+%\changes{2.0}{2009 February 27}{updated to use new database structure}
+% \begin{macrocode}
+\newcommand{\@sDTLforeach}[4][\boolean{true}]{%
+% \end{macrocode}
+% Check database exists
+% \begin{macrocode}
+ \DTLifdbexists{#2}%
+ {%
+% \end{macrocode}
+% Keep \sty{hyperref} happy
+% \begin{macrocode}
+ \refstepcounter{DTLrow}%
+% \end{macrocode}
+% Make it global (so that it works in tabular environment)
+% \begin{macrocode}
+ \global\c@DTLrow=\c@DTLrow
+% \end{macrocode}
+% Store database name.
+%\changes{2.20}{2014-02-03}{Added missing \cs{@dtl@dbname} assignment}
+% \begin{macrocode}
+ \xdef\@dtl@dbname{#2}%
+% \end{macrocode}
+% Increment level and check not exceeded 3
+% \begin{macrocode}
+ \global\advance\dtlforeachlevel by 1\relax
+ \ifnum\dtlforeachlevel>3\relax
+ \PackageError{datatool}{\string\DTLforeach\space nested too
+ deeply}{Only 3 levels are allowed}%
+ \else
+ \@DTLifdbempty{#2}%
+% \end{macrocode}
+% Do nothing if database is empty
+% \begin{macrocode}
+ {}%
+ {%
+% \end{macrocode}
+% Set level dependent information (needs to be global to ensure
+% it works in the \env{tabular} environment). Row counter:
+% \begin{macrocode}
+ \expandafter\global
+ \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname
+ = 0\relax
+% \end{macrocode}
+% Store previous value of \cs{DTLiffirstrow}
+% \begin{macrocode}
+ \expandafter\global\expandafter\let%
+ \csname @dtl@iffirstrow\the\dtlforeachlevel\endcsname
+ \DTLiffirstrow
+% \end{macrocode}
+% Define current \cs{DTLiffirstrow}
+% \begin{macrocode}
+ \gdef\DTLiffirstrow##1##2{%
+ \expandafter\ifnum
+ \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname
+ =1\relax
+ ##1%
+ \else
+ ##2%
+ \fi}%
+% \end{macrocode}
+% Store previous value of \cs{DTLiflastrow}
+% \begin{macrocode}
+ \expandafter\global\expandafter\let%
+ \csname @dtl@iflastrow\the\dtlforeachlevel\endcsname
+ \DTLiflastrow
+% \end{macrocode}
+% Define current \cs{DTLiflastrow}
+%\changes{2.12}{2012-11-30}{fixed bug in \cs{DTLiflastrow}}
+% \begin{macrocode}
+ \gdef\DTLiflastrow##1##2{%
+ \expandafter\ifnum
+ \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname
+ =\csname dtlrows@#2\endcsname\relax
+ ##1%
+ \else
+ ##2%
+ \fi}%
+% \end{macrocode}
+% Store previous value of \cs{DTLifoddrow}
+% \begin{macrocode}
+ \expandafter\global\expandafter\let%
+ \csname @dtl@ifoddrow\the\dtlforeachlevel\endcsname
+ \DTLifoddrow
+% \end{macrocode}
+% Define current \cs{DTLifoddrow}
+% \begin{macrocode}
+ \gdef\DTLifoddrow##1##2{%
+ \expandafter\ifodd
+ \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname
+ ##1%
+ \else
+ ##2%
+ \fi}%
+% \end{macrocode}
+% Store data base name for current level
+% \begin{macrocode}
+ \expandafter\gdef\csname @dtl@dbname@\romannumeral
+ \dtlforeachlevel\endcsname{#2}%
+% \end{macrocode}
+% Mark it as read only
+% \begin{macrocode}
+ \expandafter\global\expandafter\let
+ \csname @dtl@ro@\romannumeral\dtlforeachlevel\endcsname
+ = 1\relax
+% \end{macrocode}
+% Iterate through each row.
+% \begin{macrocode}
+ \@dtlforeachrow(\dtl@thisidx,\dtl@thisrow)\in{#2}\do%
+ {%
+% \end{macrocode}
+% Assign row number (not sure if this is needed here)
+% \begin{macrocode}
+ \csname dtl@row\romannumeral\dtlforeachlevel\endcsname
+ = \dtl@thisidx\relax
+% \end{macrocode}
+% Store the current row specs for this level
+% \begin{macrocode}
+ \expandafter\global
+ \csname @dtl@cur\romannumeral\dtlforeachlevel\endcsname
+ = \expandafter{\dtl@thisrow}%
+% \end{macrocode}
+% Assign commands to the required entries
+% \begin{macrocode}
+ \ifx\relax#3\relax
+ \else
+% \end{macrocode}
+% Need to set \cs{dtlcurrentrow} for \cs{@dtl@assign}
+% \begin{macrocode}
+ \dtlcurrentrow=\expandafter{\dtl@thisrow}%
+ \@dtl@assign{#3}{#2}%
+ \fi
+% \end{macrocode}
+% Do the main body of text if condition is satisfied
+% \begin{macrocode}
+ \ifthenelse{#1}%
+ {%
+% \end{macrocode}
+% Increment user row counter
+% \begin{macrocode}
+ \refstepcounter{DTLrow\romannumeral\dtlforeachlevel}%
+ \expandafter\edef\expandafter\DTLcurrentindex%
+ \expandafter{%
+ \arabic{DTLrow\romannumeral\dtlforeachlevel}}%
+ #4%
+ }%
+% \end{macrocode}
+% Condition not met so ignore
+% \begin{macrocode}
+ {}%
+ }%
+% \end{macrocode}
+% Restore previous value of \cs{DTLiffirstrow}
+% \begin{macrocode}
+ \expandafter\global\expandafter\let\expandafter\DTLiffirstrow
+ \csname @dtl@iffirstrow\the\dtlforeachlevel\endcsname
+% \end{macrocode}
+% Restore previous value of \cs{DTLiflastrow}
+% \begin{macrocode}
+ \expandafter\global\expandafter\let\expandafter\DTLiflastrow
+ \csname @dtl@iflastrow\the\dtlforeachlevel\endcsname
+% \end{macrocode}
+% Restore previous value of \cs{DTLifoddrow}
+% \begin{macrocode}
+ \expandafter\global\expandafter\let\expandafter\DTLifoddrow
+ \csname @dtl@ifoddrow\the\dtlforeachlevel\endcsname
+ }%
+ \fi
+% \end{macrocode}
+% Decrement level
+% \begin{macrocode}
+ \global\advance\dtlforeachlevel by -1\relax
+ }%
+% \end{macrocode}
+% else part (data base doesn't exist):
+% \begin{macrocode}
+ {%
+ \PackageError{datatool}{Database `#2' doesn't exist}{}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtlifreadonly}
+%\begin{definition}
+%\cs{@dtlifreadonly}\marg{true part}\marg{false part}
+%\end{definition}
+% Checks if current loop level is read only
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\newcommand*{\@dtlifreadonly}[2]{%
+ \expandafter\ifx
+ \csname @dtl@ro@\romannumeral\dtlforeachlevel\endcsname1\relax
+% \end{macrocode}
+% Read only
+% \begin{macrocode}
+ #1%
+ \else
+% \end{macrocode}
+% Not read only
+% \begin{macrocode}
+ #2%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLappendtorow}
+%\begin{definition}
+%\cs{DTLappendtorow}\marg{key}\marg{value}
+%\end{definition}
+% Appends entry to current row. (The current row is given by
+% \cs{@dtl@cur}\meta{n} where \meta{n} is roman
+% numeral value of \cs{dtlforeachlevel}.
+% One level expansion is applied to \meta{value}.
+%\changes{2.0}{2009 February 27}{updated to use new database structure}
+% \begin{macrocode}
+\newcommand*{\DTLappendtorow}[2]{%
+ \ifnum\dtlforeachlevel=0\relax
+ \PackageError{datatool}{\string\DTLappendrow\space can only be
+ used inside \string\DTLforeach}{}%
+ \else
+% \end{macrocode}
+% Set \cs{@dtl@thisdb} to the current database name:
+% \begin{macrocode}
+ \expandafter\let\expandafter\@dtl@thisdb
+ \csname @dtl@dbname@\romannumeral\dtlforeachlevel\endcsname
+% \end{macrocode}
+% Check this isn't in \cs{DTLforeach*}
+% \begin{macrocode}
+ \@dtlifreadonly
+ {%
+ \PackageError{datatool}{\string\DTLappendtorow\space can't
+ be used inside \DTLforeach*}{The starred version of
+ \string\DTLforeach\space is read only}%
+ }%
+ {%
+% \end{macrocode}
+% Store current row number in \cs{dtlrownum}
+% \begin{macrocode}
+ \dtlrownum=
+ \csname dtl@row\romannumeral\dtlforeachlevel\endcsname\relax
+% \end{macrocode}
+% Update information about this column (adding new column if
+% necessary)
+% \begin{macrocode}
+ \@dtl@updatekeys{\@dtl@thisdb}{#1}{#2}%
+% \end{macrocode}
+% Get column index and store in \cs{dtlcolumnnum}
+% \begin{macrocode}
+ \expandafter\dtlcolumnnum\expandafter
+ =\dtlcolumnindex{\@dtl@thisdb}{#1}\relax
+% \end{macrocode}
+% Set \cs{dtlcurrentrow} to the current row
+% \begin{macrocode}
+ \dtlcurrentrow =
+ \csname @dtl@cur\romannumeral\dtlforeachlevel\endcsname
+% \end{macrocode}
+% Does this row already have an entry with this key?
+% \begin{macrocode}
+ \edef\dtl@dogetentry{\noexpand\dtlgetentryfromcurrentrow
+ {\noexpand\dtl@entry}{\number\dtlcolumnnum}%
+ }%
+ \dtl@dogetentry
+ \ifx\dtl@entry\dtlnovalue
+% \end{macrocode}
+% There are no entries in this row for the given key.
+% Expand entry value before storing.
+%\changes{2.03}{2009 November 15}{value expanded before storing}
+% \begin{macrocode}
+ \protected@edef\@dtl@tmp{#2}%
+ \expandafter\@dtl@toks\expandafter{\@dtl@tmp}%
+% \end{macrocode}
+% Append this entry to the current row.
+% \begin{macrocode}
+ \@dtl@toks@gput@right@cx{@dtl@cur\romannumeral\dtlforeachlevel}%
+ {%
+ \noexpand\db@col@id@w \number\dtlcolumnnum
+ \noexpand\db@col@id@end@
+ \noexpand\db@col@elt@w \the\@dtl@toks
+ \noexpand\db@col@elt@end@
+ \noexpand\db@col@id@w \number\dtlcolumnnum
+ \noexpand\db@col@id@end@
+ }%
+% \end{macrocode}
+% Print information to terminal and log file if in verbose mode.
+% \begin{macrocode}
+ \dtl@message{Appended #1\space -> #2\space to database
+ `\@dtl@thisdb'}%
+ \else
+% \end{macrocode}
+% There is already an entry in this row for the given key
+% \begin{macrocode}
+ \PackageError{datatool}{Can't append entry to row:
+ there is already an entry for key `#1' in this row}{}%
+ \fi
+ }%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLremoveentryfromrow}
+%\begin{definition}
+%\cs{DTLremoveentryfromrow}\marg{key}
+%\end{definition}
+% Removes entry given by \meta{key} from current row.
+% (The current row is given by
+% \cs{@dtl@cur}\meta{n} where \meta{n} is roman
+% numeral value of \cs{dtlforeachlevel}.
+%\changes{2.0}{2009 February 27}{updated to use new database structure}
+% \begin{macrocode}
+\newcommand*{\DTLremoveentryfromrow}[1]{%
+ \ifnum\dtlforeachlevel=0\relax
+ \PackageError{datatool}{\string\DTLremoventryfromrow\space
+ can only be used inside \string\DTLforeach}{}%
+ \else
+% \end{macrocode}
+% Set \cs{@dtl@thisdb} to the current database name:
+% \begin{macrocode}
+ \expandafter\let\expandafter\@dtl@thisdb
+ \csname @dtl@dbname@\romannumeral\dtlforeachlevel\endcsname
+% \end{macrocode}
+% Check this isn't in \cs{DTLforeach*}
+% \begin{macrocode}
+ \@dtlifreadonly
+ {%
+ \PackageError{datatool}{\string\DTLremoveentryfromrow\space
+ can't be used inside \string\DTLforeach*}{The starred
+ version of \string\DTLforeach\space is read only}%
+ }%
+ {%
+% \end{macrocode}
+% Store current row number in \cs{dtlrownum}
+% \begin{macrocode}
+ \dtlrownum=
+ \csname dtl@row\romannumeral\dtlforeachlevel\endcsname\relax
+% \end{macrocode}
+% Is there a column corresponding to this key?
+% \begin{macrocode}
+ \@DTLifhaskey{\@dtl@thisdb}{#1}%
+ {%
+% \end{macrocode}
+% There exists a column for this key, so get the index:
+% \begin{macrocode}
+ \@dtl@getcolumnindex{\thiscol}{\@dtl@thisdb}{#1}\relax
+ \dtlcolumnnum=\thiscol\relax
+% \end{macrocode}
+% Set \cs{dtlcurrentrow} to the current row
+% \begin{macrocode}
+ \dtlcurrentrow =
+ \csname @dtl@cur\romannumeral\dtlforeachlevel\endcsname
+% \end{macrocode}
+% Does this row have an entry with this key?
+% \begin{macrocode}
+ \edef\dtl@dogetentry{\noexpand\dtlgetentryfromcurrentrow
+ {\noexpand\dtl@entry}{\number\dtlcolumnnum}%
+ }%
+ \dtl@dogetentry
+ \ifx\dtl@entry\dtlnovalue
+% \end{macrocode}
+% This row doesn't contain an entry with this key
+% \begin{macrocode}
+ \PackageError{datatool}{Can't remove entry given by `#1'
+ from current row in database `\@dtl@thisdb': no such
+ entry}{The current row doesn't contain an entry for
+ key `#1'}%
+ \else
+% \end{macrocode}
+% Split the current row around the unwanted entry
+% \begin{macrocode}
+ \edef\@dtl@dosplitrow{%
+ \noexpand\dtlsplitrow{\the\dtlcurrentrow}%
+ {\number\dtlcolumnnum}{\noexpand\dtl@pre}%
+ {\noexpand\dtl@post}%
+ }%
+ \@dtl@dosplitrow
+% \end{macrocode}
+% Reconstruct row without unwanted entry
+% \begin{macrocode}
+ \expandafter\@dtl@toks\expandafter{\dtl@pre}%
+ \expandafter\toks@\expandafter{\dtl@post}%
+ \edef\@dtl@tmp{\the\@dtl@toks \the\toks@}%
+ \dtlcurrentrow=\expandafter{\@dtl@tmp}%
+ \expandafter\global
+ \csname @dtl@cur\romannumeral\dtlforeachlevel\endcsname
+ = \dtlcurrentrow
+ \dtl@message{Removed entry given by #1\space from current
+ row of database `\@dtl@thisdb'}%
+ \fi
+ }%
+ {%
+ \PackageError{datatool}{Can't remove entry given by
+ `#1' - no such key exists}{}%
+ }%
+ }%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLreplaceentryforrow}
+%\begin{definition}
+%\cs{DTLreplaceentryforrow}\marg{key}\marg{value}
+%\end{definition}
+% Replaces entry given by \meta{key} in current row with
+% \meta{value}.
+% (The current row is given by the token register
+% \cs{@dtl@cur}\meta{n} where \meta{n} is roman
+% numeral value of \cs{dtlforeachlevel}.
+%\changes{2.0}{2009 February 27}{updated to use new database structure}
+% \begin{macrocode}
+\newcommand*{\DTLreplaceentryforrow}[2]{%
+ \ifnum\dtlforeachlevel=0\relax
+ \PackageError{datatool}{\string\DTLreplaceentryforrow\space
+ can only be used inside \string\DTLforeach}{}%
+ \else
+% \end{macrocode}
+% Set \cs{@dtl@thisdb} to the current database name:
+% \begin{macrocode}
+ \expandafter\let\expandafter\@dtl@thisdb
+ \csname @dtl@dbname@\romannumeral\dtlforeachlevel\endcsname
+% \end{macrocode}
+% Check this isn't in \cs{DTLforeach*}
+% \begin{macrocode}
+ \@dtlifreadonly
+ {%
+ \PackageError{datatool}{\string\DTLreplaceentryforrow\space
+ can't be used inside \string\DTLforeach*}{The starred version
+ of \string\DTLforeach\space is read only}%
+ }%
+ {%
+% \end{macrocode}
+% Store current row number in \cs{dtlrownum}
+% \begin{macrocode}
+ \dtlrownum=
+ \csname dtl@row\romannumeral\dtlforeachlevel\endcsname\relax
+% \end{macrocode}
+% Is there a column corresponding to this key?
+% \begin{macrocode}
+ \@DTLifhaskey{\@dtl@thisdb}{#1}%
+ {%
+% \end{macrocode}
+% There exists a column for this key, so get the index:
+% \begin{macrocode}
+ \@dtl@getcolumnindex{\thiscol}{\@dtl@thisdb}{#1}\relax
+ \dtlcolumnnum=\thiscol\relax
+% \end{macrocode}
+% Set \cs{dtlcurrentrow} to the current row
+% \begin{macrocode}
+ \dtlcurrentrow =
+ \csname @dtl@cur\romannumeral\dtlforeachlevel\endcsname
+% \end{macrocode}
+% Does this row have an entry with this key?
+% \begin{macrocode}
+ \edef\dtl@dogetentry{\noexpand\dtlgetentryfromcurrentrow
+ {\noexpand\dtl@entry}{\number\dtlcolumnnum}%
+ }%
+ \dtl@dogetentry
+ \ifx\dtl@entry\dtlnovalue
+% \end{macrocode}
+% This row doesn't contain an entry with this key
+% \begin{macrocode}
+ \PackageError{datatool}{Can't replace entry given by `#1'
+ from current row in database `\@dtl@thisdb': no such
+ entry}{The current row doesn't contain an entry for
+ key `#1'}%
+ \else
+% \end{macrocode}
+% Split the current row around the requested entry
+% \begin{macrocode}
+ \edef\@dtl@dosplitrow{%
+ \noexpand\dtlsplitrow{\the\dtlcurrentrow}%
+ {\number\dtlcolumnnum}{\noexpand\dtl@pre}%
+ {\noexpand\dtl@post}%
+ }%
+ \@dtl@dosplitrow
+% \end{macrocode}
+% Reconstruct row with new value (given by \verb|#2|).
+%\changes{2.03}{2009 November 15}{expand replacement entry}
+% \begin{macrocode}
+ \protected@edef\@dtl@tmp{#2}%
+ \expandafter\@dtl@toks\expandafter{\@dtl@tmp}% new value
+ \expandafter\@dtl@before\expandafter{\dtl@pre}%
+ \expandafter\@dtl@after\expandafter{\dtl@post}%
+ \@dtl@toks@gconcat@middle@cx
+ {@dtl@cur\romannumeral\dtlforeachlevel}%
+ {\@dtl@before}%
+ {%
+ \noexpand\db@col@id@w \number\dtlcolumnnum
+ \noexpand\db@col@id@end@%
+ \noexpand\db@col@elt@w \the\@dtl@toks
+ \noexpand\db@col@elt@end@%
+ \noexpand\db@col@id@w \number\dtlcolumnnum
+ \noexpand\db@col@id@end@%
+ }%
+ {\@dtl@after}%
+% \end{macrocode}
+% Print information to terminal and log file if in verbose mode.
+% \begin{macrocode}
+ \dtl@message{Updated #1\space -> #2\space in database
+ `\@dtl@thisdb'}%
+ \fi
+ }%
+ {%
+% \end{macrocode}
+% There doesn't exist a column for this key.
+% \begin{macrocode}
+ \PackageError{datatool}{Can't replace key `#1' - no such
+ key in database `\@dtl@thisdb'}{}%
+ }%
+ }%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLremovecurrentrow}
+%\begin{definition}
+%\cs{DTLremovecurrentrow}
+%\end{definition}
+% Removes current row. This just sets the current row to empty
+%\changes{1.01}{2007 Aug 17}{fix bug caused by missing \cs{fi}
+% and unrequired argument}
+%\changes{2.0}{2009 February 27}{updated to use new database structure}
+% \begin{macrocode}
+\newcommand*{\DTLremovecurrentrow}{%
+ \ifnum\dtlforeachlevel=0\relax
+ \PackageError{datatool}{\string\DTLremovecurrentrow\space can
+ only be used inside \string\DTLforeach}{}%
+ \else
+% \end{macrocode}
+% Set \cs{@dtl@thisdb} to the current database name:
+% \begin{macrocode}
+ \expandafter\let\expandafter\@dtl@thisdb
+ \csname @dtl@dbname@\romannumeral\dtlforeachlevel\endcsname
+% \end{macrocode}
+% Check this isn't in \cs{DTLforeach*}
+% \begin{macrocode}
+ \@dtlifreadonly
+ {%
+ \PackageError{datatool}{\string\DTLreplaceentryforrow\space
+ can't be used inside \string\DTLforeach*}{The starred version
+ of \string\DTLforeach\space is read only}%
+ }%
+ {%
+% \end{macrocode}
+% Set the current row to \cs{@nil} (\cs{DTLforeach} needs to check
+% for this)
+% \begin{macrocode}
+ \expandafter\global
+ \csname @dtl@cur\romannumeral\dtlforeachlevel\endcsname
+ ={\@nil}%
+ }%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLaddentryforrow}
+%\begin{definition}
+%\cs{DTLaddentryforrow}\marg{db name}\marg{assign list}\marg{condition}\marg{key}\marg{value}
+%\end{definition}
+% Adds the entry with key given by \meta{key} and value given by
+% \meta{value} to the first row in the database \meta{db name}
+% which satisfies the condition given by \meta{condition}. The
+% \meta{assign list} is the same as for \cs{DTLforeach} and may
+% be used to set the values which are to be tested in \meta{condition}.
+%\changes{2.0}{2009 February 27}{updated to use new database structure}
+% \begin{macrocode}
+\newcommand{\DTLaddentryforrow}[5]{%
+% \end{macrocode}
+% Iterate through the data base until condition is met
+%\changes{2.13}{2013-01-15}{removed spurious space}
+% \begin{macrocode}
+ \DTLifdbexists{#1}%
+ {%
+ \def\@dtl@notdone{\PackageError{datatool}{Unable to add entry
+ given by key `#4': condition not met for any row in database
+ `#1'}{}}%
+% \end{macrocode}
+% Iterate through each row
+% \begin{macrocode}
+ \DTLforeach[#3]{#1}{#2}%
+ {%
+% \end{macrocode}
+% add entry to this row
+% \begin{macrocode}
+ \DTLappendtorow{#4}{#5}%
+% \end{macrocode}
+% disable error message
+% \begin{macrocode}
+ \let\@dtl@notdone\relax
+% \end{macrocode}
+% break out of loop
+% \begin{macrocode}
+ \dtlbreak
+ }%
+ \@dtl@notdone
+ }%
+ {%
+ \PackageError{datatool}{Unable to add entry given by key `#4':
+ database `#1' doesn't exist}{}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLforeachkeyinrow}
+%\begin{definition}
+%\cs{DTLforeachkeyinrow}\marg{cmd}\marg{text}
+%\end{definition}
+% Iterates through each key in the current row of \cs{DTLforeach},
+% and does \meta{text}.
+%\changes{2.0}{2009 February 27}{updated to use new database structure}
+% \begin{macrocode}
+\newcommand*{\DTLforeachkeyinrow}[2]{%
+ \ifnum\dtlforeachlevel=0\relax
+ \PackageError{datatool}{\string\DTLforeachkeyinrow\space can only
+ be used inside \string\DTLforeach}{}%
+ \else
+% \end{macrocode}
+% Set \cs{@dtl@thisdb} to the current database name:
+% \begin{macrocode}
+ \expandafter\let\expandafter\@dtl@thisdb
+ \csname @dtl@dbname@\romannumeral\dtlforeachlevel\endcsname
+% \end{macrocode}
+% Iterate through key list
+% \begin{macrocode}
+ \dtlforeachkey(\dtlkey,\dtlcol,\dtltype,\dtlheader)\in
+ \@dtl@thisdb\do{%
+% \end{macrocode}
+% store row in \cs{dtlcurrentrow}
+% (This may get nested so need to do it here instead of
+% outside this loop in case
+% \meta{text} changes it.)
+% \begin{macrocode}
+ \dtlcurrentrow =
+ \csname @dtl@cur\romannumeral\dtlforeachlevel\endcsname
+% \end{macrocode}
+% Get the value for this key and store in "#1"
+% \begin{macrocode}
+ \edef\dtl@dogetentry{\noexpand\dtlgetentryfromcurrentrow
+ {\noexpand#1}{\dtlcol}}%
+ \dtl@dogetentry
+% \end{macrocode}
+% Check if null
+% \begin{macrocode}
+ \ifx#1\dtlnovalue
+ \ifnum0\dtltype=0\relax
+% \end{macrocode}
+%\changes{2.13}{2013-01-15}{changed to use \cs{@dtlstringnull} and
+%\cs{@dtlnumbernull}}%
+% Data type is \meta{empty} or 0, so set to string null.
+% \begin{macrocode}
+ \let#1=\@dtlstringnull
+ \else
+% \end{macrocode}
+% Data type is numerical, so set to number null.
+% \begin{macrocode}
+ \let#1=\@dtlnumbernull
+ \fi
+ \fi
+% \end{macrocode}
+% Make "#1" global in case this is in a tabular environment (or
+% something similar)
+% \begin{macrocode}
+ \global\let#1#1%
+% \end{macrocode}
+% Store loop body so that any scoping commands (such as "&") don't
+% cause a problem for \cs{ifx}
+% \begin{macrocode}
+ \def\@dtl@loop@body{#2}%
+ \@dtl@loop@body
+ }%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\section{DTLforeach Conditionals}
+% The following conditionals are only meant to be used within
+% \cs{DTLforeach} as they depend on the counter
+% \texttt{DTLrow}\meta{n}.
+%
+%\begin{macro}{\DTLiffirstrow}
+%\begin{definition}
+%\cs{DTLiffirstrow}\marg{true part}\marg{false part}
+%\end{definition}
+% Test if the current row is the first row. (This takes
+% \meta{condition}, the optional argument of \cs{DTLforeach},
+% into account, so it may not correspond to row~1 of the
+% database.) Can only be used in \cs{DTLforeachrow}.
+%\changes{2.0}{2009 February 27}{modified to have different
+% definition depending on location}
+% \begin{macrocode}
+\newcommand{\DTLiffirstrow}[2]{%
+ \PackageError{datatool}{\string\DTLiffirstrow\space can only
+ be used inside \string\DTLforeach}{}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLiflastrow}
+%\begin{definition}
+%\cs{DTLiflastrow}\marg{true part}\marg{false part}
+%\end{definition}
+% Checks if the current row is the last row of the database.
+% It doesn't take the condition (the optional argument of
+% \cs{DTLforeach}) into account, so its possible it may never
+% do \meta{true part}, as the last row of the database may not
+% meet the condition. It is therefore not very useful and is
+% confusing since it behaves differently to \cs{DTLiffirstrow}
+% which does take the condition into account, so I have removed
+% its description from the main part of the manual. If you need
+% to use the optional argument of \cs{DTLforeach}, you will first
+% have to iterate through the database to count up the number
+% of rows which meet the condition, and then do another pass,
+% checking if the current row has reached that number.
+%\changes{1.01}{2007 Aug 17}{fixed bug}
+%\changes{2.0}{2009 February 27}{modified to have different
+% definition depending on location}
+% \begin{macrocode}
+\newcommand{\DTLiflastrow}[2]{%
+ \PackageError{datatool}{\string\DTLiflastrow\space can only
+ be used inside \string\DTLforeach}{}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLifoddrow}
+%\begin{definition}
+%\cs{DTLifoddrow}\marg{true part}\marg{false part}
+%\end{definition}
+% Determines whether the current row is odd (takes the optional
+% argument of \cs{DTLforeach} into account.)
+%\changes{2.0}{2009 February 27}{modified to have different
+% definition depending on location}
+% \begin{macrocode}
+\newcommand{\DTLifoddrow}[2]{%
+ \PackageError{datatool}{\string\DTLifoddrow\space can only
+ be used inside \string\DTLforeach}{}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\section{Displaying Database}
+% This section defines commands to display the entire database
+% in a \env{tabular} or \env{longtable} environment.
+%
+%\begin{macro}{\dtlbetweencols}
+% This specifies what to put between the column alignment
+% specifiers.
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\newcommand*{\dtlbetweencols}{}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtlbeforecols}
+% This specifies what to put before the first column alignment
+% specifier.
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\newcommand*{\dtlbeforecols}{}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtlaftercols}
+% This specifies what to put after the last column alignment
+% specifier.
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\newcommand*{\dtlaftercols}{}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlstringalign}
+% Alignment character for columns containing strings
+% \begin{macrocode}
+\newcommand*{\dtlstringalign}{l}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtlintalign}
+% Alignment character for columns containing integers
+% \begin{macrocode}
+\newcommand*{\dtlintalign}{r}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtlrealalign}
+% Alignment character for columns containing real numbers
+% \begin{macrocode}
+\newcommand*{\dtlrealalign}{r}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtlcurrencyalign}
+% Alignment character for columns containing currency numbers
+% \begin{macrocode}
+\newcommand*{\dtlcurrencyalign}{r}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtladdalign}
+%\begin{definition}
+%\cs{dtladdalign}\marg{cs}\marg{type}\marg{col num}\marg{max cols}
+%\end{definition}
+% Adds tabular column alignment character to \meta{cs} for column
+% \meta{col num} which contains data type \meta{type}.
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\newcommand*{\dtladdalign}[4]{%
+ \ifnum#3=1\relax
+ \protected@edef#1{\dtlbeforecols}%
+ \else
+ \protected@edef#1{#1\dtlbetweencols}%
+ \fi
+ \ifstrempty{#2}%
+ {%
+ \protected@edef#1{#1c}%
+ }%
+ {%
+ \ifcase#2\relax
+% \end{macrocode}
+% string
+% \begin{macrocode}
+ \protected@edef#1{#1\dtlstringalign}%
+ \or
+% \end{macrocode}
+% integer
+% \begin{macrocode}
+ \protected@edef#1{#1\dtlintalign}%
+ \or
+% \end{macrocode}
+% real number
+% \begin{macrocode}
+ \protected@edef#1{#1\dtlrealalign}%
+ \or
+% \end{macrocode}
+% currency
+% \begin{macrocode}
+ \protected@edef#1{#1\dtlcurrencyalign}%
+ \else
+% \end{macrocode}
+% Unknown type
+% \begin{macrocode}
+ \protected@edef#1{#1c}%
+ \PackageError{datatool}{Unknown data type `#2'}{}%
+ \fi
+ }%
+ \ifnum#3=#4\relax
+ \protected@edef#1{#1\dtlaftercols}%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlheaderformat}
+%\begin{definition}
+%\cs{dtlheaderformat}\marg{text}
+%\end{definition}
+% Specifies how to format the column title.
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\newcommand*{\dtlheaderformat}[1]{\null\hfil\textbf{#1}\hfil\null}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlstringformat}
+%\begin{definition}
+%\cs{dtlstringformat}\marg{text}
+%\end{definition}
+% Specifies how to format entries in columns with string data type.
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\newcommand*{\dtlstringformat}[1]{#1}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtlintformat}
+%\begin{definition}
+%\cs{dtlintformat}\marg{text}
+%\end{definition}
+% Specifies how to format entries in columns with integer data type.
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\newcommand*{\dtlintformat}[1]{#1}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtlrealformat}
+%\begin{definition}
+%\cs{dtlrealformat}\marg{text}
+%\end{definition}
+% Specifies how to format entries in columns with real data type.
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\newcommand*{\dtlrealformat}[1]{#1}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtlcurrencyformat}
+%\begin{definition}
+%\cs{dtlcurrencyformat}\marg{text}
+%\end{definition}
+% Specifies how to format entries in columns with currency data type.
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\newcommand*{\dtlcurrencyformat}[1]{#1}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtldisplaystarttab}
+% Indicates what to do just after "\begin{tabular}"\marg{column specs}
+% (e.g.\ \cs{hline}).
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\newcommand*{\dtldisplaystarttab}{}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtldisplayendtab}
+% Indicates what to do just before "\end{tabular}".
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\newcommand*{\dtldisplayendtab}{}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtldisplayafterhead}
+% Indicates what to do after the header row, before the first row
+% of data.
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\newcommand*{\dtldisplayafterhead}{}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtldisplayvalign}
+%\changes{2.11}{2012-09-25}{new}
+% Stores the vertical alignment specifier for the tabular
+% environment used in \cs{DTLdisplaydb}
+% \begin{macrocode}
+\newcommand*{\dtldisplayvalign}{c}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtldisplaystartrow}
+% Indicates what to do at the start of each row (not including
+% the header row or the first row of data).
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\newcommand*{\dtldisplaystartrow}{}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtldisplaycr}
+%\changes{2.19}{2014-01-17}{new}
+% \begin{macrocode}
+\newcommand{\dtldisplaycr}{\tabularnewline}
+% \end{macrocode}
+%\end{macro}
+
+%\begin{macro}{\DTLdisplaydb}
+%\begin{definition}
+%\cs{DTLdisplaydb}\oarg{omit list}\marg{db}
+%\end{definition}
+% Displays the database \meta{db} in a tabular environment.
+%\changes{2.0}{2009 February 27}{new}
+%\changes{2.10}{2012-07-18}{added optional arg}
+% \begin{macrocode}
+\newcommand*{\DTLdisplaydb}[2][]{%
+% \end{macrocode}
+% Initialise:
+% only want "&" between columns
+%\changes{2.13}{2013-01-15}{removed spurious space}
+% \begin{macrocode}
+ \def\@dtl@doamp{\gdef\@dtl@doamp{&}}%
+ \def\@dtl@resetdoamp{\gdef\@dtl@doamp{\gdef\@dtl@doamp{&}}}%
+% \end{macrocode}
+% Store maximum number of columns
+% \begin{macrocode}
+ \edef\@dtl@maxcols{\expandafter\number
+ \csname dtlcols@#2\endcsname}%
+% \end{macrocode}
+% Subtract number of omitted columns
+% \begin{macrocode}
+ \DTLnumitemsinlist{#1}{\@dtl@tmp}%
+ \dtlsub{\@dtl@maxcols}{\@dtl@maxcols}{\@dtl@tmp}%
+ \dtlclip{\@dtl@maxcols}{\@dtl@maxcols}%
+% \end{macrocode}
+% Argument for tabular environment
+% \begin{macrocode}
+ \def\@dtl@tabargs{}%
+ \dtlforeachkey(\@dtl@key,\@dtl@idx,\@dtl@type,\@dtl@head)%
+ \in{#2}\do
+ {%
+ \expandafter\DTLifinlist\expandafter{\@dtl@key}{#1}%
+ {}%
+ {%
+ \dtladdalign\@dtl@tabargs\@dtl@type\@dtl@idx\@dtl@maxcols
+% \end{macrocode}
+%\changes{2.13}{2013-01-15}{removed spurious space}
+% \begin{macrocode}
+ }%
+ }%
+% \end{macrocode}
+% Begin tabular environment
+% \begin{macrocode}
+ \edef\@dtl@dobegintab{\noexpand\begin{tabular}[\dtldisplayvalign]{\@dtl@tabargs}}%
+ \@dtl@dobegintab
+% \end{macrocode}
+% Do start hook
+% \begin{macrocode}
+ \dtldisplaystarttab
+% \end{macrocode}
+% Reset \cs{@dtl@doamp} so it doesn't do an ampersand at the
+% start of the first column.
+% \begin{macrocode}
+ \@dtl@resetdoamp
+% \end{macrocode}
+% Do the header row.
+% \begin{macrocode}
+ \dtlforeachkey(\@dtl@key,\@dtl@idx,\@dtl@type,\@dtl@head)%
+ \in{#2}\do
+ {%
+ \expandafter\DTLifinlist\expandafter{\@dtl@key}{#1}%
+ {}%
+ {%
+ \@dtl@doamp
+ \dtlheaderformat{\@dtl@head}%
+ }%
+ }%
+ \\%
+% \end{macrocode}
+% Do the after header hook
+% \begin{macrocode}
+ \dtldisplayafterhead
+% \end{macrocode}
+% Reset \cs{@dtl@doamp} so it doesn't do an ampersand at the
+% start of the first column.
+% \begin{macrocode}
+ \@dtl@resetdoamp
+% \end{macrocode}
+% Iterate through each row of the database
+% \begin{macrocode}
+ \@sDTLforeach{#2}{}{%
+% \end{macrocode}
+% Do the start row hook if not the first row
+%\changes{2.19}{2014-01-17}{switched to \cs{dtldisplaycr}}
+% \begin{macrocode}
+ \DTLiffirstrow{}{\dtldisplaycr\dtldisplaystartrow}%
+% \end{macrocode}
+% Reset \cs{@dtl@doamp} so it doesn't do an ampersand at the
+% start of the first column.
+% \begin{macrocode}
+ \@dtl@resetdoamp
+% \end{macrocode}
+% Iterate through each column.
+% \begin{macrocode}
+ \DTLforeachkeyinrow{\@dtl@val}%
+ {%
+ \expandafter\DTLifinlist\expandafter{\dtlkey}{#1}%
+ {}%
+ {%
+% \end{macrocode}
+% Need to make value global as it needs to be used after the
+% ampersand.
+% \begin{macrocode}
+ \global\let\@dtl@val\@dtl@val
+ \@dtl@doamp
+% \end{macrocode}
+% \cs{DTLforeachkeyinrow} sets \cs{dtltype} to the data type
+% for the current key. This can be used to determine which
+% format to use for this entry.
+% \begin{macrocode}
+ \@dtl@datatype=0\dtltype\relax
+ \ifcase\@dtl@datatype
+ \dtlstringformat\@dtl@val
+ \or
+ \dtlintformat\@dtl@val
+ \or
+ \dtlrealformat\@dtl@val
+ \or
+ \dtlcurrencyformat\@dtl@val
+ \else
+ \@dtl@val
+ \fi
+ }%
+ }%
+ }%
+ \dtldisplayendtab
+ \end{tabular}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+% Define keys to use in the optional argument of
+% \cs{DTLdisplaylongdb}.
+%
+% The caption key sets the caption for the longtable.
+% \begin{macrocode}
+\define@key{displaylong}{caption}{\def\@dtl@cap{#1}}
+% \end{macrocode}
+% The contcaption key sets the continuation caption for the
+% longtable.
+% \begin{macrocode}
+\define@key{displaylong}{contcaption}{\def\@dtl@contcap{#1}}
+% \end{macrocode}
+% The shortcaption key sets the lof caption for the longtable.
+% \begin{macrocode}
+\define@key{displaylong}{shortcaption}{\def\@dtl@shortcap{#1}}
+% \end{macrocode}
+% The label key sets the label for the longtable.
+% \begin{macrocode}
+\define@key{displaylong}{label}{\def\@dtl@label{#1}}
+% \end{macrocode}
+% The foot key sets the longtable foot
+% \begin{macrocode}
+\define@key{displaylong}{foot}{\def\@dtl@foot{#1}}
+% \end{macrocode}
+% The lastfoot key sets the longtable last foot
+% \begin{macrocode}
+\define@key{displaylong}{lastfoot}{\def\@dtl@lastfoot{#1}}
+% \end{macrocode}
+% List of omitted columns
+% \begin{macrocode}
+\define@key{displaylong}{omit}{\def\@dtl@omitlist{#1}}
+% \end{macrocode}
+%
+%\begin{macro}{\@dtl@resetdostartrow}
+% Resets start row hook so that it skips the first row.
+%\changes{2.19}{2014-01-17}{switched to \cs{dtldisplaycr}}
+% \begin{macrocode}
+\newcommand*{\@dtl@resetdostartrow}{%
+ \gdef\@dtl@dostartrow{%
+ \gdef\@dtl@dostartrow{\dtldisplaycr\dtldisplaystartrow}}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLdisplaylongdb}
+%\begin{definition}
+%\cs{DTLdisplaylongdb}\oarg{options}\marg{db}
+%\end{definition}
+% Displays the database \meta{db} in a longtable environment.
+% (User needs to load \sty{longtable}).
+%\changes{2.0}{2009 February 27}{new}
+%\changes{2.10}{2012-07-18}{added omit option}
+% \begin{macrocode}
+\newcommand*{\DTLdisplaylongdb}[2][]{%
+% \end{macrocode}
+% Initialise.
+% \begin{macrocode}
+ \def\@dtl@cap{\@nil}%
+ \def\@dtl@contcap{\@nil}%
+ \def\@dtl@label{\@nil}%
+ \def\@dtl@shortcap{\@dtl@cap}%
+ \def\@dtl@foot{\@nil}%
+ \def\@dtl@lastfoot{\@nil}%
+ \def\@dtl@omitlist{}%
+% \end{macrocode}
+% Set the options
+% \begin{macrocode}
+ \setkeys{displaylong}{#1}%
+% \end{macrocode}
+% Only want "&" between columns
+%\changes{2.13}{2013-01-15}{removed spurious space}
+% \begin{macrocode}
+ \def\@dtl@doamp{\gdef\@dtl@doamp{&}}%
+ \def\@dtl@resetdoamp{\gdef\@dtl@doamp{\gdef\@dtl@doamp{&}}}%
+ \@dtl@resetdostartrow
+% \end{macrocode}
+% Store maximum number of columns
+% \begin{macrocode}
+ \edef\@dtl@maxcols{\expandafter\number
+ \csname dtlcols@#2\endcsname}%
+% \end{macrocode}
+% Subtract number of omitted columns
+% \begin{macrocode}
+ \DTLnumitemsinlist{\@dtl@omitlist}{\@dtl@tmp}%
+ \dtlsub{\@dtl@maxcols}{\@dtl@maxcols}{\@dtl@tmp}%
+ \dtlclip{\@dtl@maxcols}{\@dtl@maxcols}%
+% \end{macrocode}
+% Argument for \env{longtable} environment
+% \begin{macrocode}
+ \def\@dtl@tabargs{}%
+ \dtlforeachkey(\@dtl@key,\@dtl@idx,\@dtl@type,\@dtl@head)%
+ \in{#2}\do
+ {%
+ \expandafter\DTLifinlist\expandafter{\@dtl@key}{\@dtl@omitlist}%
+ {}%
+ {%
+ \dtladdalign\@dtl@tabargs\@dtl@type\@dtl@idx\@dtl@maxcols
+ }%
+ }%
+% \end{macrocode}
+% Start the \env{longtable} environment.
+% \begin{macrocode}
+ \edef\@dtl@dobegintab{\noexpand\begin{longtable}{\@dtl@tabargs}}%
+ \@dtl@dobegintab
+% \end{macrocode}
+% Is a foot required?
+% \begin{macrocode}
+ \ifx\@dtl@foot\@nnil
+ \else
+ \@dtl@foot\endfoot
+ \fi
+% \end{macrocode}
+% Is a last foot required?
+% \begin{macrocode}
+ \ifx\@dtl@lastfoot\@nnil
+ \else
+ \@dtl@lastfoot\endlastfoot
+ \fi
+% \end{macrocode}
+% Is a caption required?
+% \begin{macrocode}
+ \ifx\@dtl@cap\@nnil
+% \end{macrocode}
+% No caption required, just do header row.
+% \begin{macrocode}
+ \@dtl@resetdoamp
+ \dtldisplaystarttab
+ \dtlforeachkey(\@dtl@key,\@dtl@idx,\@dtl@type,\@dtl@head)%
+ \in{#2}\do
+ {%
+ \expandafter\DTLifinlist\expandafter{\@dtl@key}{\@dtl@omitlist}%
+ {}%
+ {%
+ \@dtl@doamp{\dtlheaderformat{\@dtl@head}}%
+ }%
+ }%
+ \@dtl@resetdoamp
+ \@dtl@resetdostartrow
+ \endhead\dtldisplayafterhead
+ \else
+% \end{macrocode}
+% Caption is required
+% \begin{macrocode}
+ \caption[\@dtl@shortcap]{\@dtl@cap}%
+% \end{macrocode}
+% Is a label required?
+% \begin{macrocode}
+ \ifx\@dtl@label\@nnil
+ \else
+ \label{\@dtl@label}%
+ \fi
+ \dtldisplaycr
+% \end{macrocode}
+%\changes{2.21}{2014-03-08}{fixed location of \cs{dtldisplaystarttab}}
+% Do start hook.
+% \begin{macrocode}
+ \dtldisplaystarttab
+% \end{macrocode}
+% Do header row.
+% \begin{macrocode}
+ \@dtl@resetdoamp
+ \dtlforeachkey(\@dtl@key,\@dtl@idx,\@dtl@type,\@dtl@head)%
+ \in{#2}\do
+ {%
+ \expandafter\DTLifinlist\expandafter{\@dtl@key}{\@dtl@omitlist}%
+ {}%
+ {%
+ \@dtl@doamp{\dtlheaderformat{\@dtl@head}}%
+ }%
+ }%
+ \@dtl@resetdoamp
+% \end{macrocode}
+%\changes{2.21}{2014-03-08}{added missing \cs{dtldisplayafterhead}}
+% \begin{macrocode}
+ \dtldisplaycr\dtldisplayafterhead
+ \endfirsthead
+% \end{macrocode}
+% Is a continuation caption required?
+% \begin{macrocode}
+ \ifx\@dtl@contcap\@nnil
+ \caption{\@dtl@cap}%
+ \else
+ \caption{\@dtl@contcap}%
+ \fi
+% \end{macrocode}
+%\changes{2.21}{2014-03-08}{fixed location of \cs{dtldisplaystarttab}}
+% Do start hook.
+% \begin{macrocode}
+ \dtldisplaycr\dtldisplaystarttab
+% \end{macrocode}
+% Do header row.
+% \begin{macrocode}
+ \@dtl@resetdoamp
+ \dtlforeachkey(\@dtl@key,\@dtl@idx,\@dtl@type,\@dtl@head)%
+ \in{#2}\do
+ {%
+ \expandafter\DTLifinlist\expandafter{\@dtl@key}{\@dtl@omitlist}%
+ {}%
+ {%
+ \@dtl@doamp{\dtlheaderformat{\@dtl@head}}%
+ }%
+ }%
+ \@dtl@resetdoamp
+ \@dtl@resetdostartrow
+% \end{macrocode}
+%\changes{2.21}{2014-03-08}{moved misplaced \cs{dtldisplayafterhead}}
+% \begin{macrocode}
+ \dtldisplaycr\dtldisplayafterhead
+ \endhead
+ \fi
+% \end{macrocode}
+% Iterate through each row of the database
+% \begin{macrocode}
+ \@sDTLforeach{#2}{}{%
+ \@dtl@dostartrow
+ \@dtl@resetdoamp
+% \end{macrocode}
+% Iterate through each column
+% \begin{macrocode}
+ \DTLforeachkeyinrow{\@dtl@val}%
+ {%
+ \global\let\@dtl@val\@dtl@val
+ \expandafter\DTLifinlist\expandafter{\dtlkey}{\@dtl@omitlist}%
+ {}%
+ {%
+ \@dtl@doamp
+% \end{macrocode}
+% \cs{DTLforeachkeyinrow} sets \cs{dtltype} to the data type
+% for the current key. This can be used to determine which
+% format to use for this entry.
+% \begin{macrocode}
+ \@dtl@datatype=0\dtltype\relax
+ \ifcase\@dtl@datatype
+ \dtlstringformat\@dtl@val
+ \or
+ \dtlintformat\@dtl@val
+ \or
+ \dtlrealformat\@dtl@val
+ \or
+ \dtlcurrencyformat\@dtl@val
+ \fi
+ }%
+ }%
+ }%
+ \dtldisplayendtab
+ \end{longtable}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%
+%\section{Editing Databases}
+%
+%\begin{macro}{\dtlswaprows}
+%\begin{definition}
+%\cs{dtlswaprows}\marg{db}\marg{row1 idx}\marg{row2 idx}
+%\end{definition}
+% Swaps the rows with indices \meta{row1 idx} and \meta{row2 idx}
+% in the database \meta{db}.
+% (Doesn't check if data base exists or if indices are out of
+% bounds.)
+% \begin{macrocode}
+\newcommand*{\dtlswaprows}[3]{%
+ \ifnum#2=#3\relax
+% \end{macrocode}
+% Attempt to swap row with itself: do nothing.
+% \begin{macrocode}
+ \else
+% \end{macrocode}
+% Let row A be the row with the lower index and row B be the
+% row with ther higher index.
+% \begin{macrocode}
+ \ifnum#2<#3\relax
+ \edef\@dtl@rowAidx{\number#2}%
+ \edef\@dtl@rowBidx{\number#3}%
+ \else
+ \edef\@dtl@rowAidx{\number#3}%
+ \edef\@dtl@rowBidx{\number#2}%
+ \fi
+% \end{macrocode}
+% Split the database around row A.
+% \begin{macrocode}
+ \edef\@dtl@dosplit{\noexpand\dtlgetrow{#1}{\@dtl@rowAidx}}%
+ \@dtl@dosplit
+% \end{macrocode}
+% Store first part of database in \cs{@dtl@firstpart}.
+% \begin{macrocode}
+ \expandafter\def\expandafter\@dtl@firstpart\expandafter
+ {\the\dtlbeforerow}%
+% \end{macrocode}
+% Store row A in \cs{@dtl@toksA}.
+% \begin{macrocode}
+ \@dtl@toksA=\dtlcurrentrow
+% \end{macrocode}
+% Split the second part (everything after row A).
+% \begin{macrocode}
+ \edef\@dtl@dosplit{\noexpand\@dtlgetrow
+ {\the\dtlafterrow}{\@dtl@rowBidx}}%
+ \@dtl@dosplit
+% \end{macrocode}
+% Store the mid part (everything between row A and row B)
+% \begin{macrocode}
+ \expandafter\def\expandafter\@dtl@secondpart\expandafter
+ {\the\dtlbeforerow}%
+% \end{macrocode}
+% Store row B in \cs{@dtl@toksB}.
+% \begin{macrocode}
+ \@dtl@toksB=\dtlcurrentrow
+% \end{macrocode}
+% Store the last part (everything after row B).
+% \begin{macrocode}
+ \expandafter\def\expandafter\@dtl@thirdpart\expandafter
+ {\the\dtlafterrow}%
+% \end{macrocode}
+% Reconstruct database: store first part in \cs{toks@}
+% \begin{macrocode}
+ \toks@=\expandafter{\@dtl@firstpart}%
+% \end{macrocode}
+% Store mid part in \cs{dtl@toks}
+% \begin{macrocode}
+ \@dtl@toks=\expandafter{\@dtl@secondpart}%
+% \end{macrocode}
+% Format data for first part, row B and mid part.
+% \begin{macrocode}
+ \edef\@dtl@tmp{\the\toks@
+ \noexpand\db@row@elt@w%
+ \noexpand\db@row@id@w \@dtl@rowAidx\noexpand\db@row@id@end@%
+ \the\@dtl@toksB
+ \noexpand\db@row@id@w \@dtl@rowAidx\noexpand\db@row@id@end@%
+ \noexpand\db@row@elt@end@%
+ \the\@dtl@toks}%
+% \end{macrocode}
+% Store data so far in \cs{toks@}.
+% \begin{macrocode}
+ \toks@=\expandafter{\@dtl@tmp}%
+% \end{macrocode}
+% Store last part in \cs{dtl@toks}.
+% \begin{macrocode}
+ \@dtl@toks=\expandafter{\@dtl@thirdpart}%
+% \end{macrocode}
+% Format row A and end part.
+% \begin{macrocode}
+ \edef\@dtl@tmp{\the\toks@
+ \noexpand\db@row@elt@w%
+ \noexpand\db@row@id@w \@dtl@rowBidx\noexpand\db@row@id@end@%
+ \the\@dtl@toksA
+ \noexpand\db@row@id@w \@dtl@rowBidx\noexpand\db@row@id@end@%
+ \noexpand\db@row@elt@end@%
+ \the\@dtl@toks}%
+% \end{macrocode}
+% Update the database
+% \begin{macrocode}
+ \expandafter\global\csname dtldb@#1\endcsname=\expandafter
+ {\@dtl@tmp}%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@decrementrows}
+%\begin{definition}
+%\cs{dtl@decrementrows}\marg{toks}\marg{n}
+%\end{definition}
+% decrement by 1 all rows in \meta{toks} with row index above
+% \meta{n}
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\newcommand*{\dtl@decrementrows}[2]{%
+ \def\@dtl@newlist{}%
+ \edef\@dtl@min{\number#2}%
+ \expandafter\@dtl@decrementrows\the#1%
+ \db@row@elt@w%
+ \db@row@id@w \@nil\db@row@id@end@%
+ \db@row@id@w \@nil\db@row@id@end@%
+ \db@row@elt@end@%
+ \@nil
+ #1=\expandafter{\@dtl@newlist}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@decrementrows}
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\def\@dtl@decrementrows\db@row@elt@w\db@row@id@w #1\db@row@id@end@%
+#2\db@row@id@w #3\db@row@id@end@\db@row@elt@end@#4\@nil{%
+ \def\@dtl@thisrow{#1}%
+ \ifx\@dtl@thisrow\@nnil
+ \let\@dtl@donextdec=\@dtl@gobbletonil
+ \else
+ \ifnum\@dtl@thisrow>\@dtl@min
+ \@dtl@tmpcount=\@dtl@thisrow\relax
+ \advance\@dtl@tmpcount by -1\relax
+ \toks@{#2}%
+ \@dtl@toks=\expandafter{\@dtl@newlist}%
+ \edef\@dtl@newlist{\the\@dtl@toks
+ \noexpand\db@row@elt@w% row header
+ \noexpand\db@row@id@w \number\@dtl@tmpcount
+ \noexpand\db@row@id@end@% row id
+ \the\toks@ % row contents
+ \noexpand\db@row@id@w \number\@dtl@tmpcount
+ \noexpand\db@row@id@end@% row id
+ \noexpand\db@row@elt@end@% row end
+ }%
+ \else
+ \toks@{#2}%
+ \@dtl@toks=\expandafter{\@dtl@newlist}%
+ \edef\@dtl@newlist{\the\@dtl@toks
+ \noexpand\db@row@elt@w% row header
+ \noexpand\db@row@id@w #1%
+ \noexpand\db@row@id@end@% row id
+ \the\toks@ % row contents
+ \noexpand\db@row@id@w #3%
+ \noexpand\db@row@id@end@% row id
+ \noexpand\db@row@elt@end@% row end
+ }%
+ \fi
+ \let\@dtl@donextdec=\@dtl@decrementrows
+ \fi
+ \@dtl@donextdec#4\@nil
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLremoverow}
+%\begin{definition}
+%\cs{DTLremoverow}\marg{db}\marg{row index}
+%\end{definition}
+% Remove row with given index from database named \meta{db}.
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\newcommand*{\DTLremoverow}[2]{%
+% \end{macrocode}
+% Check database exists
+% \begin{macrocode}
+ \DTLifdbexists{#1}%
+ {%
+% \end{macrocode}
+% Check index if index is out of bounds
+% \begin{macrocode}
+ \ifnum#2>0\relax
+% \end{macrocode}
+% Check if data base has at least \meta{row index} rows
+% \begin{macrocode}
+ \expandafter\ifnum\csname dtlrows@#1\endcsname<#2\relax
+ \expandafter\ifnum\csname dtlrows@#1\endcsname=1\relax
+ \PackageError{datatool}{Can't remove row `\number#2' from
+ database `#1': no such row}{Database `#1' only has
+ 1 row}%
+ \else
+ \PackageError{datatool}{Can't remove row `\number#2' from
+ database `#1': no such row}{Database `#1' only has
+ \expandafter\number\csname dtlrows@#1\endcsname\space
+ rows}%
+ \fi
+ \else
+ \@DTLremoverow{#1}{#2}%
+ \fi
+ \else
+ \PackageError{datatool}{Can't remove row \number#2: index
+ out of bounds}{Row indices start at 1}%
+ \fi
+ }%
+ {%
+ \PackageError{datatool}{Can't remove row: database `#1' doesn't
+ exist}{}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@DTLremoverow}
+%\begin{definition}
+%\cs{@DTLremoverow}\marg{db}\marg{row index}
+%\end{definition}
+% Doesn't perform any checks for the existence of the database
+% or if the index is in range.
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\newcommand*{\@DTLremoverow}[2]{%
+% \end{macrocode}
+% Get row from data base
+% \begin{macrocode}
+ \edef\dtl@dogetrow{\noexpand\dtlgetrow{#1}{\number#2}}%
+ \dtl@dogetrow
+% \end{macrocode}
+% Update the row indices
+% \begin{macrocode}
+ \expandafter\dtl@decrementrows\expandafter
+ {\dtlbeforerow}{#2}%
+ \expandafter\dtl@decrementrows\expandafter
+ {\dtlafterrow}{#2}%
+% \end{macrocode}
+% Reconstruct database
+% \begin{macrocode}
+ \edef\dtl@tmp{\the\dtlbeforerow \the\dtlafterrow}%
+ \expandafter\global\csname dtldb@#1\endcsname
+ =\expandafter{\dtl@tmp}%
+% \end{macrocode}
+% decrement row counter
+% \begin{macrocode}
+ \expandafter\global\expandafter\advance
+ \csname dtlrows@#1\endcsname by -1\relax
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\section{Database Functions}
+%
+%\begin{macro}{\DTLsumforkeys}
+%\begin{definition}
+%\cs{DTLsumforkeys}\oarg{condition}\oarg{assign list}\marg{db list}\marg{key list}\marg{cmd}
+%\end{definition}
+% Sums all entries for key \meta{key} over all databases listed
+% in \meta{db list},
+% and stores in \meta{cmd}, which must be a control sequence.
+% The first argument \meta{condition} is the same as that
+% for \cs{DTLforeach}. The second optional argument provides
+% an assignment list to pass to \cs{DTLforeach} in case extra
+% information is need by \meta{condition}.
+%\changes{2.0}{2009 February 27}{added second optional argument}
+% \begin{macrocode}
+\newcommand*{\DTLsumforkeys}[1][\boolean{true}\and
+ \DTLisnumerical{\DTLthisval}]{%
+ \def\@dtl@cond{#1}%
+ \@dtlsumforkeys
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtlsumforkeys}
+% \begin{macrocode}
+\newcommand*{\@dtlsumforkeys}[4][]{%
+ \def#4{0}%
+% \end{macrocode}
+% Iterate over all the listed data bases
+% \begin{macrocode}
+ \@for\@dtl@db@name:=#2\do{%
+% \end{macrocode}
+% Iterate through this database (using read only version)
+% \begin{macrocode}
+ \@sDTLforeach{\@dtl@db@name}%
+ {#1}% assignment list
+ {%
+% \end{macrocode}
+% Iterate through key list.
+% \begin{macrocode}
+ \@for\@dtl@key:=#3\do{%
+ \@sdtl@getcolumnindex{\@dtl@col}{\@dtl@db@name}{\@dtl@key}%
+ \dtlcurrentrow=\expandafter{\dtl@thisrow}%
+ \dtlgetentryfromrow{\DTLthisval}{\@dtl@col}{\dtlcurrentrow}%
+ \expandafter\ifthenelse\expandafter{\@dtl@cond}%
+ {\DTLadd{#4}{#4}{\DTLthisval}}{}%
+ }%
+ }%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLsumcolumn}
+%\begin{definition}
+%\cs{DTLsumcolumn}\marg{db}\marg{key}\marg{cmd}
+%\end{definition}
+% Quicker version of \cs{DTLsumforkeys} that just sums over
+% one column (specified by \meta{key}) for a single database
+% (specified by \meta{db}) and stores the result in \meta{cmd}.
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\newcommand*{\DTLsumcolumn}[3]{%
+ \def#3{0}%
+% \end{macrocode}
+% Check data base exists
+% \begin{macrocode}
+ \DTLifdbexists{#1}%
+ {%
+% \end{macrocode}
+% Check column exists
+% \begin{macrocode}
+ \@sDTLifhaskey{#1}{#2}%
+ {%
+ \@sdtlforcolumn{\DTLthisval}{#1}{#2}%
+ {%
+ \DTLadd{#3}{#3}{\DTLthisval}%
+ }%
+ }%
+% \end{macrocode}
+% key not defined for this data base
+% \begin{macrocode}
+ {%
+ \PackageError{datatool}{Key `#2' doesn't
+ exist in database `#1'}{}%
+ }%
+ }%
+% \end{macrocode}
+% data base doesn't exist
+% \begin{macrocode}
+ {%
+ \PackageError{datatool}{Data base `#1' doesn't
+ exist}{}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLmeanforkeys}
+%\begin{definition}
+%\cs{DTLmeanforkeys}\oarg{condition}\oarg{assign list}\marg{db list}\marg{key list}\marg{cmd}
+%\end{definition}
+% Computes the arithmetic mean of all entries for each key in
+% \meta{key list} over all databases in \meta{db list},
+% and stores in \meta{cmd}, which must be a control sequence.
+% The first argument \meta{condition} is the same as that
+% for \cs{DTLforeach}. The second optional argument allows an
+% assignment list to be passed to \cs{DTLforeach}.
+%\changes{2.0}{2009 February 27}{added second optional argument}
+% \begin{macrocode}
+\newcommand*{\DTLmeanforkeys}[1][\boolean{true}\and
+ \DTLisnumerical{\DTLthisval}]{%
+ \def\@dtl@cond{#1}%
+ \@dtlmeanforkeys
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@elements}
+% Count register to keep track of number of elements
+% \begin{macrocode}
+\newcount\@dtl@elements
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtlmeanforkeys}
+% \begin{macrocode}
+\newcommand*{\@dtlmeanforkeys}[4][]{%
+ \def#4{0}%
+ \@dtl@elements=0\relax
+% \end{macrocode}
+% Iterate over all the listed data bases
+% \begin{macrocode}
+ \@for\@dtl@db@name:=#2\do{%
+% \end{macrocode}
+% Iterate through this database (using read only version)
+% \begin{macrocode}
+ \@sDTLforeach{\@dtl@db@name}%
+ {#1}% assignment list
+ {%
+% \end{macrocode}
+% Iterate through key list.
+% \begin{macrocode}
+ \@for\@dtl@key:=#3\do{%
+ \@sdtl@getcolumnindex{\@dtl@col}{\@dtl@db@name}{\@dtl@key}%
+ \dtlcurrentrow=\expandafter{\dtl@thisrow}%
+ \dtlgetentryfromrow{\DTLthisval}{\@dtl@col}{\dtlcurrentrow}%
+ \expandafter\ifthenelse\expandafter{\@dtl@cond}%
+ {%
+ \DTLadd{#4}{#4}{\DTLthisval}%
+ \advance\@dtl@elements by 1\relax
+ }{}%
+ }%
+ }%
+ }%
+% \end{macrocode}
+% Divide total by number of elements summed.
+% \begin{macrocode}
+ \ifnum\@dtl@elements=0\relax
+ \PackageError{datatool}{Unable to evaluate mean: no data}{}%
+ \else
+ \edef\@dtl@n{\number\@dtl@elements}%
+ \DTLdiv{#4}{#4}{\@dtl@n}%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLmeanforcolumn}
+%\begin{definition}
+%\cs{DTLmeanforcolumn}\marg{db}\marg{key}\marg{cmd}
+%\end{definition}
+% Quicker version of \cs{DTLmeanforkeys} that just computes the
+% mean over one column (specified by \meta{key}) for a single
+% database (specified by \meta{db}) and stores the result in
+% \meta{cmd}.
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\newcommand*{\DTLmeanforcolumn}[3]{%
+ \def#3{0}%
+ \@dtl@elements=0\relax
+% \end{macrocode}
+% Check data base exists
+% \begin{macrocode}
+ \DTLifdbexists{#1}%
+ {%
+% \end{macrocode}
+% Check column exists
+% \begin{macrocode}
+ \@sDTLifhaskey{#1}{#2}%
+ {%
+ \@sdtlforcolumn{\DTLthisval}{#1}{#2}%
+ {%
+ \DTLadd{#3}{#3}{\DTLthisval}%
+ \advance\@dtl@elements by 1\relax
+ }%
+ \ifnum\@dtl@elements=0\relax
+ \PackageError{datatool}{Can't compute mean for
+ column `#2' in database `#1': no data}{}%
+ \else
+ \edef\@dtl@n{\number\@dtl@elements}%
+ \DTLdiv{#3}{#3}{\@dtl@n}%
+ \fi
+ }%
+% \end{macrocode}
+% key not defined for this data base
+% \begin{macrocode}
+ {%
+ \PackageError{datatool}{Key `#2' doesn't
+ exist in database `#1'}{}%
+ }%
+ }%
+% \end{macrocode}
+% data base doesn't exist
+% \begin{macrocode}
+ {%
+ \PackageError{datatool}{Data base `#1' doesn't
+ exist}{}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLvarianceforkeys}
+%\begin{definition}
+%\cs{DTLvarianceforkeys}\oarg{condition}\oarg{assign list}\marg{db list}\marg{key list}\marg{cmd}
+%\end{definition}
+% Computes the variance of all entries for each key in
+% \meta{key list} over all databases in \meta{db list},
+% and stores in \meta{cmd}, which must be a control sequence.
+% The first optional argument \meta{condition} is the same as that
+% for \cs{DTLforeach}. The second optional argument is an assignment
+% list to pass to \cs{DTLforeach} in case it is required for the
+% condition.
+%\changes{2.0}{2009 February 27}{added second optional argument}
+% \begin{macrocode}
+\newcommand*{\DTLvarianceforkeys}[1][\boolean{true}\and
+ \DTLisnumerical{\DTLthisval}]{%
+ \def\@dtl@cond{#1}%
+ \@dtlvarianceforkeys
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtlmeanforkeys}
+% \begin{macrocode}
+\newcommand*{\@dtlvarianceforkeys}[4][]{%
+ \@dtlmeanforkeys[#1]{#2}{#3}{\dtl@mean}%
+ \def#4{0}%
+ \@dtl@elements=0\relax
+% \end{macrocode}
+% Iterate over all the listed data bases
+% \begin{macrocode}
+ \@for\@dtl@db@name:=#2\do{%
+% \end{macrocode}
+% Iterate through this database (using read only version)
+% \begin{macrocode}
+ \@sDTLforeach{\@dtl@db@name}%
+ {#1}% assignment list
+ {%
+% \end{macrocode}
+% Iterate through key list.
+% \begin{macrocode}
+ \@for\@dtl@key:=#3\do{%
+ \@sdtl@getcolumnindex{\@dtl@col}{\@dtl@db@name}{\@dtl@key}%
+ \dtlcurrentrow=\expandafter{\dtl@thisrow}%
+ \dtlgetentryfromrow{\DTLthisval}{\@dtl@col}{\dtlcurrentrow}%
+ \expandafter\ifthenelse\expandafter{\@dtl@cond}%
+ {%
+% \end{macrocode}
+% compute $(x_i - \mu)^2$
+% \begin{macrocode}
+ \DTLsub{\dtl@diff}{\DTLthisval}{\dtl@mean}%
+ \DTLmul{\dtl@diff}{\dtl@diff}{\dtl@diff}%
+ \DTLadd{#4}{#4}{\dtl@diff}%
+ \advance\@dtl@elements by 1\relax
+ }{}%
+ }%
+ }%
+ }%
+% \end{macrocode}
+% Divide by number of elements.
+% \begin{macrocode}
+ \ifnum\@dtl@elements=0\relax
+ \PackageError{datatool}{Unable to evaluate variance: no data}{}%
+ \else
+ \edef\@dtl@n{\number\@dtl@elements}%
+ \DTLdiv{#4}{#4}{\@dtl@n}%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLvarianceforcolumn}
+%\begin{definition}
+%\cs{DTLvarianceforcolumn}\marg{db}\marg{key}\marg{cmd}
+%\end{definition}
+% Quicker version of \cs{DTLvarianceforkeys} that just computes the
+% variance over one column (specified by \meta{key}) for a single
+% database (specified by \meta{db}) and stores the result in
+% \meta{cmd}.
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\newcommand*{\DTLvarianceforcolumn}[3]{%
+ \DTLmeanforcolumn{#1}{#2}{\dtl@mean}%
+ \def#3{0}%
+ \@dtl@elements=0\relax
+% \end{macrocode}
+% Check data base exists
+% \begin{macrocode}
+ \DTLifdbexists{#1}%
+ {%
+% \end{macrocode}
+% Check column exists
+% \begin{macrocode}
+ \@sDTLifhaskey{#1}{#2}%
+ {%
+ \@sdtlforcolumn{\DTLthisval}{#1}{#2}%
+ {%
+% \end{macrocode}
+% compute $(x_i - \mu)^2$
+% \begin{macrocode}
+ \DTLsub{\dtl@diff}{\DTLthisval}{\dtl@mean}%
+ \DTLmul{\dtl@diff}{\dtl@diff}{\dtl@diff}%
+ \DTLadd{#3}{#3}{\dtl@diff}%
+ \advance\@dtl@elements by 1\relax
+ }%
+ \ifnum\@dtl@elements=0\relax
+ \PackageError{datatool}{Can't compute variance for
+ column `#2' in database `#1': no data}{}%
+ \else
+ \edef\@dtl@n{\number\@dtl@elements}%
+ \DTLdiv{#3}{#3}{\@dtl@n}%
+ \fi
+ }%
+% \end{macrocode}
+% key not defined for this data base
+% \begin{macrocode}
+ {%
+ \PackageError{datatool}{Key `#2' doesn't
+ exist in database `#1'}{}%
+ }%
+ }%
+% \end{macrocode}
+% data base doesn't exist
+% \begin{macrocode}
+ {%
+ \PackageError{datatool}{Data base `#1' doesn't
+ exist}{}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%
+%\begin{macro}{\DTLsdforkeys}
+%\begin{definition}
+%\cs{DTLsdforkeys}\oarg{condition}\oarg{assign list}\marg{db list}\marg{key list}\marg{cmd}
+%\end{definition}
+% Computes the standard deviation of all entries for each key in
+% \meta{key list} over all databases in \meta{db list},
+% and stores in \meta{cmd}, which must be a control sequence.
+% The first optional argument \meta{condition} is the same as that
+% for \cs{DTLforeach}. The second optional argument is an
+% assignment list for \cs{DTLforeach} in case it is needed for
+% the condition.
+%\changes{2.0}{2009 February 27}{added second optional argument}
+% \begin{macrocode}
+\newcommand*{\DTLsdforkeys}[1][\boolean{true}\and
+\DTLisnumerical{\DTLthisval}]{%
+ \def\@dtl@cond{#1}%
+ \@dtlsdforkeys
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@dtlsdforkeys}
+% \begin{macrocode}
+\newcommand*{\@dtlsdforkeys}[4][]{%
+ \@dtlvarianceforkeys[#1]{#2}{#3}{#4}%
+ \DTLsqrt{#4}{#4}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLsdforcolumn}
+%\begin{definition}
+%\cs{DTLsdforcolumn}\marg{db}\marg{key}\marg{cmd}
+%\end{definition}
+% Quicker version of \cs{DTLsdforkeys} that just computes the
+% standard deviation over one column (specified by \meta{key}) for
+% a single database (specified by \meta{db}) and stores the result
+% in \meta{cmd}.
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\newcommand*{\DTLsdforcolumn}[3]{%
+ \DTLvarianceforcolumn{#1}{#2}{#3}%
+ \DTLsqrt{#3}{#3}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLminforkeys}
+%\begin{definition}
+%\cs{DTLminforkeys}\oarg{condition}\oarg{assign list}\marg{db list}\marg{key list}\marg{cmd}
+%\end{definition}
+% Determines the minimum over all entries for each key in
+% \meta{key list} over all databases in \meta{db list},
+% and stores in \meta{cmd}, which must be a control sequence.
+% The first optional argument \meta{condition} is the same as that
+% for \cs{DTLforeach}. The second optional argument is an
+% assignment list for \cs{DTLforeach} in the event that extra
+% information is need for the condition.
+%\changes{2.0}{2009 February 27}{added second optional argument}
+% \begin{macrocode}
+\newcommand*{\DTLminforkeys}[1][\boolean{true}\and
+ \DTLisnumerical{\DTLthisval}]{%
+ \def\@dtl@cond{#1}%
+ \@dtlminforkeys
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtlminforkeys}
+% \begin{macrocode}
+\newcommand*{\@dtlminforkeys}[4][]{%
+ \def#4{}%
+% \end{macrocode}
+% Iterate over all the listed data bases
+% \begin{macrocode}
+ \@for\@dtl@db@name:=#2\do{%
+% \end{macrocode}
+% Iterate through this database (using read only version)
+% \begin{macrocode}
+ \@sDTLforeach{\@dtl@db@name}%
+ {#1}% assignment list
+ {%
+% \end{macrocode}
+% Iterate through key list.
+% \begin{macrocode}
+ \@for\@dtl@key:=#3\do{%
+ \@sdtl@getcolumnindex{\@dtl@col}{\@dtl@db@name}{\@dtl@key}%
+ \dtlcurrentrow=\expandafter{\dtl@thisrow}%
+ \dtlgetentryfromrow{\DTLthisval}{\@dtl@col}{\dtlcurrentrow}%
+ \expandafter\ifthenelse\expandafter{\@dtl@cond}%
+ {%
+% \end{macrocode}
+%\changes{2.15}{2013-07-10}{Replaced \cs{ifstrempty} with
+%\cs{ifdefempty}}
+% \begin{macrocode}
+ \ifdefempty{#4}%
+ {%
+ \let#4\DTLthisval
+ }%
+ {%
+ \DTLmin{#4}{#4}{\DTLthisval}%
+ }%
+ }{}%
+ }%
+ }%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLminforcolumn}
+%\begin{definition}
+%\cs{DTLminforcolumn}\marg{db}\marg{key}\marg{cmd}
+%\end{definition}
+% Quicker version of \cs{DTLminforkeys} that just finds the
+% minimum value in one column (specified by \meta{key}) for a
+% single database (specified by \meta{db}) and stores the result
+% in \meta{cmd}.
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\newcommand*{\DTLminforcolumn}[3]{%
+ \def#3{}%
+% \end{macrocode}
+% Check data base exists
+% \begin{macrocode}
+ \DTLifdbexists{#1}%
+ {%
+% \end{macrocode}
+% Check column exists
+% \begin{macrocode}
+ \@sDTLifhaskey{#1}{#2}%
+ {%
+ \@sdtlforcolumn{\DTLthisval}{#1}{#2}%
+ {%
+ \ifdefempty{#3}%
+ {%
+ \let#3\DTLthisval
+ }%
+ {%
+ \DTLmin{#3}{#3}{\DTLthisval}%
+ }%
+ }%
+ }%
+% \end{macrocode}
+% key not defined for this data base
+% \begin{macrocode}
+ {%
+ \PackageError{datatool}{Key `#2' doesn't
+ exist in database `#1'}{}%
+ }%
+ }%
+% \end{macrocode}
+% data base doesn't exist
+% \begin{macrocode}
+ {%
+ \PackageError{datatool}{Data base `#1' doesn't
+ exist}{}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%
+%\begin{macro}{\DTLmaxforkeys}
+%\begin{definition}
+%\cs{DTLmaxforkeys}\oarg{condition}\oarg{assign list}\marg{db list}\marg{key list}\marg{cmd}
+%\end{definition}
+% Determines the maximum over all entries for each key in
+% \meta{key list} over all databases in \meta{db list},
+% and stores in \meta{cmd}, which must be a control sequence.
+% The first optional argument \meta{condition} is the same as that
+% for \cs{DTLforeach}. The second optional argument is an
+% assignment list to pass to \cs{DTLforeach} in the event that
+% extra information is required in the condition.
+%\changes{2.0}{2009 February 27}{added second optional argument}
+% \begin{macrocode}
+\newcommand*{\DTLmaxforkeys}[1][\boolean{true}\and
+ \DTLisnumerical{\DTLthisval}]{%
+ \def\@dtl@cond{#1}%
+ \@dtlmaxforkeys
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtlmaxforkeys}
+% \begin{macrocode}
+\newcommand*{\@dtlmaxforkeys}[4][]{%
+ \def#4{}%
+% \end{macrocode}
+% Iterate over all the listed data bases
+% \begin{macrocode}
+ \@for\@dtl@db@name:=#2\do{%
+% \end{macrocode}
+% Iterate through this database (using read only version)
+% \begin{macrocode}
+ \@sDTLforeach{\@dtl@db@name}%
+ {#1}% assignment list
+ {%
+% \end{macrocode}
+% Iterate through key list.
+% \begin{macrocode}
+ \@for\@dtl@key:=#3\do{%
+ \@sdtl@getcolumnindex{\@dtl@col}{\@dtl@db@name}{\@dtl@key}%
+ \dtlcurrentrow=\expandafter{\dtl@thisrow}%
+ \dtlgetentryfromrow{\DTLthisval}{\@dtl@col}{\dtlcurrentrow}%
+ \expandafter\ifthenelse\expandafter{\@dtl@cond}%
+ {%
+ \ifdefempty{#4}%
+ {%
+ \let#4\DTLthisval
+ }%
+ {%
+ \DTLmax{#4}{#4}{\DTLthisval}%
+ }%
+ }{}%
+ }%
+ }%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLmaxforcolumn}
+%\begin{definition}
+%\cs{DTLmaxforcolumn}\marg{db}\marg{key}\marg{cmd}
+%\end{definition}
+% Quicker version of \cs{DTLmaxforkeys} that just finds the
+% maximum value in one column (specified by \meta{key}) for a
+% single database (specified by \meta{db}) and stores the result
+% in \meta{cmd}.
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\newcommand*{\DTLmaxforcolumn}[3]{%
+ \def#3{}%
+% \end{macrocode}
+% Check data base exists
+% \begin{macrocode}
+ \DTLifdbexists{#1}%
+ {%
+% \end{macrocode}
+% Check column exists
+% \begin{macrocode}
+ \@sDTLifhaskey{#1}{#2}%
+ {%
+ \@sdtlforcolumn{\DTLthisval}{#1}{#2}%
+ {%
+ \ifdefempty{#3}%
+ {%
+ \let#3\DTLthisval
+ }%
+ {%
+ \DTLmax{#3}{#3}{\DTLthisval}%
+ }%
+ }%
+ }%
+% \end{macrocode}
+% key not defined for this data base
+% \begin{macrocode}
+ {%
+ \PackageError{datatool}{Key `#2' doesn't
+ exist in database `#1'}{}%
+ }%
+ }%
+% \end{macrocode}
+% data base doesn't exist
+% \begin{macrocode}
+ {%
+ \PackageError{datatool}{Data base `#1' doesn't
+ exist}{}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLcomputebounds}
+%\begin{definition}
+%\cs{DTLcomputebounds}\oarg{condition}\marg{db list}\marg{x key}\marg{y key}\marg{minX cmd}\marg{minY cmd}\marg{maxX cmd}\marg{maxY cmd}
+%\end{definition}
+% Computes the maximum and minimum $x$ and $y$ values over all
+% the databases listed in \meta{db list} where the $x$ value
+% is given by \meta{x key} and the $y$ value is given by
+% \meta{y key}. The results are stored in \meta{minX cmd},
+% \meta{minY cmd}, \meta{maxX cmd} and \meta{maxY cmd} in
+% standard decimal format.
+% \begin{macrocode}
+\newcommand*{\DTLcomputebounds}[8][\boolean{true}]{%
+\let#5=\relax
+\let#6=\relax
+\let#7=\relax
+\let#8=\relax
+\@for\dtl@thisdb:=#2\do{%
+ \@sDTLforeach[#1]{\dtl@thisdb}{\DTLthisX=#3,\DTLthisY=#4}{%
+ \expandafter\DTLconverttodecimal\expandafter{\DTLthisX}{\dtl@decx}%
+ \expandafter\DTLconverttodecimal\expandafter{\DTLthisY}{\dtl@decy}%
+ \ifx#5\relax
+ \let#5=\dtl@decx
+ \let#6=\dtl@decy
+ \let#7=\dtl@decx
+ \let#8=\dtl@decy
+ \else
+ \dtlmin{#5}{#5}{\dtl@decx}%
+ \dtlmin{#6}{#6}{\dtl@decy}%
+ \dtlmax{#7}{#7}{\dtl@decx}%
+ \dtlmax{#8}{#8}{\dtl@decy}%
+ \fi
+ }%
+}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLgetvalueforkey}
+%\begin{definition}
+%\cs{DTLgetvalueforkey}\marg{cmd}\marg{key}\marg{db name}\marg{ref
+% key}\marg{ref value}
+%\end{definition}
+% This (globally) sets \meta{cmd} (a control sequence) to the
+% value of the key specified by \meta{key} in the first row
+% of the database called \meta{db name} which contains the key
+% \meta{ref key} which has the value \meta{value}.
+%\changes{1.01}{2007 Aug 17}{new}
+%\changes{2.0}{2009 February 27}{updated to use new database
+% structure}
+% \begin{macrocode}
+\newcommand*{\DTLgetvalueforkey}[5]{%
+% \end{macrocode}
+% Get row containing referenced (key,value) pair
+% \begin{macrocode}
+ \DTLgetrowforkey{\@dtl@row}{#3}{#4}{#5}%
+% \end{macrocode}
+% Get column number for \meta{key}
+% \begin{macrocode}
+ \@sdtl@getcolumnindex{\@dtl@col}{#3}{#2}%
+% \end{macrocode}
+% Get value for given column
+% \begin{macrocode}
+ {%
+ \dtlcurrentrow=\expandafter{\@dtl@row}%
+ \edef\@dtl@dogetval{\noexpand\dtlgetentryfromcurrentrow
+ {\noexpand\@dtl@val}{\@dtl@col}}%
+ \@dtl@dogetval
+ \global\let#1=\@dtl@val
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLgetrowforkey}
+%\begin{definition}
+%\cs{DTLgetrowforkey}\marg{cmd}\marg{db name}\marg{ref
+% key}\marg{ref value}
+%\end{definition}
+% This (globally) sets \meta{cmd} (a control sequence) to the
+% first row
+% of the database called \meta{db name} which contains the key
+% \meta{ref key} that has the value \meta{value}.
+%\changes{1.01}{2007 Aug 17}{new}
+%\changes{2.0}{2009 February 27}{update to use new database
+% structure}
+% \begin{macrocode}
+\newcommand*{\DTLgetrowforkey}[4]{%
+ \global\let#1=\@empty
+ \@sDTLforeach{#2}{\dtl@refvalue=#3}{%
+ \DTLifnull{\dtl@refvalue}%
+ {}%
+ {%
+ \ifthenelse{\equal{\dtl@refvalue}{#4}}%
+ {%
+ \xdef#1{\the\dtlcurrentrow}%
+ \dtlbreak
+ }%
+ {}%
+ }%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\section{Sorting Databases}
+%
+%\begin{macro}{\@dtl@list}
+% Token register to store data when sorting.
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\newtoks\@dtl@list
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLsort}
+%\begin{definition}
+% \cs{DTLsort}\oarg{replacement keys}\marg{sort criteria}\marg{db name}
+%\end{definition}
+% Sorts database \meta{db name} according to \marg{sort criteria},
+% which must be a comma separated list of keys, and optionally
+% \texttt{=}\meta{order}, where \meta{order} is either
+% "ascending" or "descending". The optional argument is a list of
+% keys to uses if the given key has a null value. The starred
+% version uses a case insensitive string comparison.
+%\changes{1.01}{2007 Aug 17}{added optional argument}
+%\changes{1.01}{2007 Aug 17}{added starred version}
+%\changes{2.0}{2009 February 27}{updated to use new data structure}
+% \begin{macrocode}
+\newcommand*{\DTLsort}{\@ifstar\@sDTLsort\@DTLsort}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@DTLsort}
+% Unstarred (case sensitive) version.
+%\changes{2.23}{2015-07-11}{bug fix: replaced \cs{dtlicompare} with
+%\cs{dtlcompare}}
+% \begin{macrocode}
+\newcommand{\@DTLsort}[3][]{%
+ \dtlsort[#1]{#2}{#3}{\dtlcompare}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@sDTLsort}
+% Starred (case insensitive) version.
+% \begin{macrocode}
+\newcommand*{\@sDTLsort}[3][]{%
+ \dtlsort[#1]{#2}{#3}{\dtlicompare}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlsort}
+%\changes{2.13}{2013-01-15}{new}
+%\begin{definition}
+%\cs{dtlsort}\oarg{replacement keys}\marg{sort criteria}\marg{db
+%name}\marg{handler}
+%\end{definition}
+% More general version where user supplies a handler for the
+% comparison.
+% \begin{macrocode}
+\newcommand{\dtlsort}[4][]{%
+% \end{macrocode}
+% Check the database exists
+% \begin{macrocode}
+ \DTLifdbexists{#3}%
+ {%
+ \ifnum\DTLrowcount{#3}>100\relax
+ \typeout{Sorting `#3' - this may take a while.}%
+ \fi
+% \end{macrocode}
+% Store replacement keys in \cs{@dtl@replacementkeys}.
+% \begin{macrocode}
+ \edef\@dtl@replacementkeys{#1}%
+% \end{macrocode}
+% Store sort order in \cs{@dtl@sortorder}, but check specified keys exist.
+%\changes{2.18}{2013-09-06}{added check for existence of keys listed in sort
+%criteria}
+% \begin{macrocode}
+ \def\@dtl@sortorder{}%
+ \@for\@dtl@level:=#2\do
+ {%
+% \end{macrocode}
+% Get key (stored in \cs{@dtl@key}).
+% \begin{macrocode}
+ \expandafter\@dtl@getsortdirection\@dtl@level=\relax
+% \end{macrocode}
+% Check key exists.
+% \begin{macrocode}
+ \DTLifhaskey{#3}{\@dtl@key}%
+ {%
+% \end{macrocode}
+% Key exists, so add to \cs{@dtl@sortorder}.
+% \begin{macrocode}
+ \ifdefempty\@dtl@sortorder
+ {\let\@dtl@sortorder=\@dtl@level}%
+ {\eappto\@dtl@sortorder{,\@dtl@level}}%
+ }%
+ {%
+% \end{macrocode}
+% Key doesn't exist.
+% \begin{macrocode}
+ \PackageError{datatool}%
+ {%
+ Can't sort on `\@dtl@level'.
+ No such key `\@dtl@key' in database `#3'%
+ }{}%
+ }%
+ }%
+% \end{macrocode}
+% Now check if we have any keys left to sort on.
+% \begin{macrocode}
+ \ifdefempty\@dtl@sortorder
+ {%
+ \PackageWarning{datatool}{No keys provided to sort database `#3'}%
+ }%
+ {%
+% \end{macrocode}
+% Set \cs{@dtl@comparecs} to the required string comparison
+% function. (Using case insensitive comparison macro
+% \cs{dtlicompare}.)
+% \begin{macrocode}
+ \let\@dtl@comparecs=#4%
+% \end{macrocode}
+% Sort the database.
+% \begin{macrocode}
+ \dtl@sortdata{#3}%
+ }%
+ }%
+ {%
+ \PackageError{datatool}{Database `#3' doesn't exist}{}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@rowa}
+% Token register to store first row when sorting.
+% \begin{macrocode}
+\newtoks\@dtl@rowa
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@dtl@rowb}
+% Token register to store comparison row when sorting.
+% \begin{macrocode}
+\newtoks\@dtl@rowb
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@sortdata}
+%\begin{definition}
+%\cs{dtl@sortdata}\marg{db}
+%\end{definition}
+% Sorts the data in named database using an insertion sort
+% algorithm.
+% \cs{@dtl@replacementkeys}, \cs{@dtl@sortorder} and
+% \cs{@dtl@comparecs} must be set prior to use.
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\newcommand*{\dtl@sortdata}[1]{%
+% \end{macrocode}
+% Initialise macro containing sorted data.
+% \begin{macrocode}
+ \def\@dtl@sortedlist{}%
+% \end{macrocode}
+% Store database name.
+% \begin{macrocode}
+ \edef\@dtl@dbname{#1}%
+% \end{macrocode}
+% Iterate through each row and insert into sorted list.
+% \begin{macrocode}
+ \@dtlforeachrow(\@dtl@rowAnum,\@dtl@rowAcontents)\in\@dtl@dbname\do{%
+ \@dtl@rowa=\expandafter{\@dtl@rowAcontents}%
+% \end{macrocode}
+% Create a temporary list
+% \begin{macrocode}
+ \def\@dtl@newlist{}%
+% \end{macrocode}
+% Initialise the insertion for this iteration. Insertion hasn't
+% been done yet.
+% \begin{macrocode}
+ \@dtl@insertdonefalse
+% \end{macrocode}
+% Initialise row index to 0
+% \begin{macrocode}
+ \dtlrownum=0\relax
+% \end{macrocode}
+% Iterate through sorted list.
+% \begin{macrocode}
+ \expandafter\@dtl@foreachrow\@dtl@sortedlist
+ \db@row@elt@w%
+ \db@row@id@w \@nil\db@row@id@end@%
+ \db@row@id@w \@nil\db@row@id@end@%
+ \db@row@elt@end@%
+ \@@{\@dtl@rowBnum}{\@dtl@rowBcontents}%
+ {%
+% \end{macrocode}
+% Store row B in a token register
+% \begin{macrocode}
+ \@dtl@rowb=\expandafter{\@dtl@rowBcontents}%
+% \end{macrocode}
+% Get current row number of sorted list
+% \begin{macrocode}
+ \dtlrownum=\@dtl@rowBnum
+% \end{macrocode}
+% Has the insertion been done?
+% \begin{macrocode}
+ \if@dtl@insertdone
+% \end{macrocode}
+% New element has already been inserted, so just increment the row
+% number to compensate for the inserted row.
+% \begin{macrocode}
+ \advance\dtlrownum by 1\relax
+ \else
+% \end{macrocode}
+% Insertion hasn't been done yet.
+% Compare row A and row B.
+% \begin{macrocode}
+ \@dtl@sortcriteria{\@dtl@rowa}{\@dtl@rowb}%
+% \end{macrocode}
+% If \cs{dtl@sortresult} is negative insert A before B.
+% \begin{macrocode}
+ \ifnum\dtl@sortresult<0\relax
+% \end{macrocode}
+% Insert row A into new list. First store \cs{@dtl@newlist} in
+% \cs{toks@}.
+% \begin{macrocode}
+ \toks@=\expandafter{\@dtl@newlist}%
+% \end{macrocode}
+% Update \cs{@dtl@newlist} to be the old value followed by
+% row A.
+% \begin{macrocode}
+ \edef\@dtl@newlist{%
+% \end{macrocode}
+% Old value:
+% \begin{macrocode}
+ \the\toks@
+% \end{macrocode}
+% Format row A
+% \begin{macrocode}
+ \noexpand\db@row@elt@w%
+ \noexpand\db@row@id@w \number\dtlrownum
+ \noexpand\db@row@id@end@%
+ \the\@dtl@rowa
+ \noexpand\db@row@id@w \number\dtlrownum
+ \noexpand\db@row@id@end@%
+ \noexpand\db@row@elt@end@%
+ }%
+% \end{macrocode}
+% Increment row number to compensate for inserted row.
+% \begin{macrocode}
+ \advance\dtlrownum by 1\relax
+% \end{macrocode}
+% Mark insertion done.
+% \begin{macrocode}
+ \@dtl@insertdonetrue
+ \fi
+ \fi
+% \end{macrocode}
+% Insert row B
+% \begin{macrocode}
+ \toks@=\expandafter{\@dtl@newlist}%
+ \edef\@dtl@newlist{\the\toks@
+% \end{macrocode}
+% row B
+% \begin{macrocode}
+ \noexpand\db@row@elt@w%
+ \noexpand\db@row@id@w \number\dtlrownum
+ \noexpand\db@row@id@end@%
+ \the\@dtl@rowb
+ \noexpand\db@row@id@w \number\dtlrownum
+ \noexpand\db@row@id@end@%
+ \noexpand\db@row@elt@end@%
+ }%
+% \end{macrocode}
+% Repeat loop.
+% \begin{macrocode}
+ }\q@nil
+% \end{macrocode}
+% If row A hasn't been inserted, do so now.
+% \begin{macrocode}
+ \if@dtl@insertdone
+ \else
+% \end{macrocode}
+% \cs{dtlrownum} contains the index of the last row in new list,
+% So increment it to get the new index for row A.
+% \begin{macrocode}
+ \advance\dtlrownum by 1\relax
+% \end{macrocode}
+% Insert row A.
+% \begin{macrocode}
+ \toks@=\expandafter{\@dtl@newlist}%
+ \edef\@dtl@newlist{\the\toks@
+% \end{macrocode}
+% row A
+% \begin{macrocode}
+ \noexpand\db@row@elt@w%
+ \noexpand\db@row@id@w \number\dtlrownum
+ \noexpand\db@row@id@end@%
+ \the\@dtl@rowa
+ \noexpand\db@row@id@w \number\dtlrownum
+ \noexpand\db@row@id@end@%
+ \noexpand\db@row@elt@end@%
+ }%
+ \fi
+% \end{macrocode}
+% Set sorted list to new list.
+% \begin{macrocode}
+ \let\@dtl@sortedlist=\@dtl@newlist
+ }%
+% \end{macrocode}
+% Update database.
+% \begin{macrocode}
+ \expandafter\global\csname dtldb@#1\endcsname=\expandafter
+ {\@dtl@sortedlist}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@sortcriteria}
+%\begin{definition}
+% \cs{@dtl@sortcriteria}\marg{row a toks}\marg{row b toks}
+%\end{definition}
+% \cs{@dtl@dbname} and \cs{@dtl@sortorder} must be set before use
+% \cs{@dtl@sortorder} is a comma separated list of either just keys
+% or \meta{key}=\meta{direction}.
+% (Check keys are valid before use.)
+%\changes{2.0}{2009 February 27}{updated to take account of new
+% database structure}
+% \begin{macrocode}
+\newcommand{\@dtl@sortcriteria}[2]{%
+% \end{macrocode}
+% Iterate through the sort order.
+% \begin{macrocode}
+ \@for\@dtl@level:=\@dtl@sortorder\do
+ {%
+% \end{macrocode}
+% Set \cs{@dtl@sortdirection} to $-1$ (ascending) or $+1$
+% (descending). Key is stored in \cs{@dtl@key}.
+% \begin{macrocode}
+ \expandafter\@dtl@getsortdirection\@dtl@level=\relax
+% \end{macrocode}
+% Initially comparing on the same key
+% \begin{macrocode}
+ \let\@dtl@keya=\@dtl@key
+ \let\@dtl@keyb=\@dtl@key
+% \end{macrocode}
+% Get values corresponding to key from both rows.
+% First get column index corresponding to key.
+% \begin{macrocode}
+ \@sdtl@getcolumnindex{\@dtl@col}{\@dtl@dbname}{\@dtl@key}%
+% \end{macrocode}
+% Get entry for this column from row A and store in \cs{@dtl@a}.
+% \begin{macrocode}
+ \dtlgetentryfromrow{\@dtl@a}{\@dtl@col}{#1}%
+% \end{macrocode}
+% Get entry for this column from row B and store in \cs{@dtl@b}.
+% \begin{macrocode}
+ \dtlgetentryfromrow{\@dtl@b}{\@dtl@col}{#2}%
+% \end{macrocode}
+% Has value from row A been defined?
+% \begin{macrocode}
+ \ifx\@dtl@a\dtlnovalue
+% \end{macrocode}
+% Value hasn't been defined so set to null
+% \begin{macrocode}
+ \@dtl@setnull{\@dtl@a}{\@dtl@key}%
+ \fi
+% \end{macrocode}
+% Has value from row B been defined?
+% \begin{macrocode}
+ \ifx\@dtl@b\dtlnovalue
+% \end{macrocode}
+% Value hasn't been defined so set to null
+% \begin{macrocode}
+ \@dtl@setnull{\@dtl@b}{\@dtl@key}%
+ \fi
+% \end{macrocode}
+% Check if value for row A is null.
+% \begin{macrocode}
+ \DTLifnull{\@dtl@a}%
+ {%
+% \end{macrocode}
+% Value for row A is null, so find the first non null key in list of
+% replacement keys.
+% \begin{macrocode}
+ \@for\@dtl@keya:=\@dtl@replacementkeys\do{%
+% \end{macrocode}
+% Get column corresponding to this key.
+% \begin{macrocode}
+ \@sdtl@getcolumnindex{\@dtl@col}{\@dtl@dbname}{\@dtl@keya}%
+ \dtlgetentryfromrow{\@dtl@a}{\@dtl@col}{#1}%
+% \end{macrocode}
+% Has value for row A been defined?
+% \begin{macrocode}
+ \ifx\@dtl@a\dtlnovalue
+% \end{macrocode}
+% Value for row A hasn't been defined so set to null
+% \begin{macrocode}
+ \@dtl@setnull{\@dtl@a}{\@dtl@key}%
+ \fi
+% \end{macrocode}
+% Is value for row A null? If not null end the loop.
+% \begin{macrocode}
+ \DTLifnull{\@dtl@a}{}{\@endfortrue}%
+ }%
+% \end{macrocode}
+% No non-null value found.
+% \begin{macrocode}
+ \ifx\@dtl@keya\@nnil
+ \let\@dtl@keya\@dtl@key
+ \@dtl@setnull{\@dtl@a}{\@dtl@key}%
+ \fi
+ }%
+ {}%
+% \end{macrocode}
+% Check if value for row B is null.
+% \begin{macrocode}
+ \DTLifnull{\@dtl@b}%
+ {%
+% \end{macrocode}
+% Value for row B is null, so find the first non null key in list of
+% replacement keys.
+% \begin{macrocode}
+ \@for\@dtl@keyb:=\@dtl@replacementkeys\do{%
+% \end{macrocode}
+% Get column corresponding to this key.
+% \begin{macrocode}
+ \@sdtl@getcolumnindex{\@dtl@col}{\@dtl@dbname}{\@dtl@keyb}%
+ \dtlgetentryfromrow{\@dtl@b}{\@dtl@col}{#2}%
+% \end{macrocode}
+% Has value for row B been defined?
+% \begin{macrocode}
+ \ifx\@dtl@b\dtlnovalue
+% \end{macrocode}
+% Value for row B hasn't been defined so set to null.
+% \begin{macrocode}
+ \@dtl@setnull{\@dtl@b}{\@dtl@key}%
+ \fi
+% \end{macrocode}
+% Is value for row B null? If not null end the loop.
+% \begin{macrocode}
+ \DTLifnull{\@dtl@b}{}{\@endfortrue}%
+ }%
+% \end{macrocode}
+% No non-null value found.
+% \begin{macrocode}
+ \ifx\@dtl@keyb\@nnil
+ \let\@dtl@keyb\@dtl@key
+ \@dtl@setnull{\@dtl@b}{\@dtl@key}%
+ \fi
+ }%
+ {}%
+% \end{macrocode}
+% Compare rows A and B. First store the values for row A and B
+% in token registers so that they can be passed to
+% \cs{dtl@compare@}.
+% \begin{macrocode}
+ \@dtl@toksA=\expandafter{\@dtl@a}%
+ \@dtl@toksB=\expandafter{\@dtl@b}%
+% \end{macrocode}
+% Do comparison.
+% \begin{macrocode}
+ \edef\@dtl@docompare{\noexpand\dtl@compare@
+ {\@dtl@keya}{\@dtl@keyb}%
+ {\noexpand\@dtl@toksA}{\noexpand\@dtl@toksB}}%
+ \@dtl@docompare
+% \end{macrocode}
+% Repeat if the two values are considered identical and there
+% are further sorting options.
+% \begin{macrocode}
+ \ifnum\dtl@sortresult=0\relax
+% \end{macrocode}
+% Reset switch to prevent breaking out of outer loop.
+% \begin{macrocode}
+ \@endforfalse
+ \else
+% \end{macrocode}
+% Break out of loop.
+% \begin{macrocode}
+ \@endfortrue
+ \fi
+ }%
+% \end{macrocode}
+% Apply sort direction
+%\changes{2.01}{2009 March 27}{fixed sort direction}
+% \begin{macrocode}
+ \multiply\dtl@sortresult by -\@dtl@sortdirection\relax
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@getsortdirection}
+% Get the direction from either \meta{key} or
+% \meta{key}=\meta{direction}. Sets \cs{@dtl@sortdirection} to
+% either -1 (ascending) or 1 (descending).
+% \begin{macrocode}
+\def\@dtl@getsortdirection#1=#2\relax{%
+% \end{macrocode}
+% Store key in \cs{@dtl@key}.
+% \begin{macrocode}
+ \def\@dtl@key{#1}%
+% \end{macrocode}
+% Store sort direction. This will be empty if no direction was
+% specified.
+% \begin{macrocode}
+ \def\@dtl@sortdirection{#2}%
+% \end{macrocode}
+% Check if a direction was specified.
+% \begin{macrocode}
+ \ifdefempty{\@dtl@sortdirection}%
+ {%
+% \end{macrocode}
+% No direction specified so assume ascending.
+% \begin{macrocode}
+ \def\@dtl@sortdirection{-1}%
+ }%
+ {%
+% \end{macrocode}
+% Get the sort direction from the second argument (needs terminating
+% equal sign removed) and store in \cs{@dtl@sortdirection}.
+% \begin{macrocode}
+ \@dtl@get@sortdirection#2%
+% \end{macrocode}
+% Determine the direction.
+% \changes{2.0}{2009 February 27}{modified to use \cs{ifx} instead
+% of \cs{ifthenelse}}
+% \begin{macrocode}
+ \def\@dtl@dir{ascending}%
+ \ifx\@dtl@sortdirection\@dtl@dir
+% \end{macrocode}
+% Ascending
+% \begin{macrocode}
+ \def\@dtl@sortdirection{-1}%
+ \else
+% \end{macrocode}
+% Check if descending.
+% \begin{macrocode}
+ \def\@dtl@dir{descending}%
+ \ifx\@dtl@sortdirection\@dtl@dir
+% \end{macrocode}
+% Descending
+% \begin{macrocode}
+ \def\@dtl@sortdirection{1}%
+ \else
+% \end{macrocode}
+% Direction not valid. Generate error message.
+% \begin{macrocode}
+ \PackageError{datatool}{Invalid sort direction
+ `\@dtl@sortdirection'}{The sort direction can only be
+ one of `ascending' or `descending'}%
+% \end{macrocode}
+% Assume ascending.
+%\changes{2.13}{2013-01-15}{removed spurious space}
+% \begin{macrocode}
+ \def\@dtl@sortdirection{-1}%
+ \fi
+ \fi
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@dtl@get@sortdirection}
+% Get direction (trims trailing = sign)
+% \begin{macrocode}
+\def\@dtl@get@sortdirection#1={\def\@dtl@sortdirection{#1}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@toksA}
+% \begin{macrocode}
+\newtoks\@dtl@toksA
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@dtl@toksB}
+% \begin{macrocode}
+\newtoks\@dtl@toksB
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtl@compare}
+%\begin{definition}
+%\cs{dtl@compare}\marg{key}\marg{a toks}\marg{b toks}
+%\end{definition}
+% Compares two values according to \meta{key} of database given by
+% \cs{@dtl@dbname}. Sets \cs{dtl@sortresult}. \cs{@dtl@comparecs}
+% must be set to the required comparison macro.
+%\changes{2.0}{2009 February 27}{no longer used}
+% \begin{macrocode}
+\newcommand{\dtl@compare}[3]{%
+ \dtl@compare@{#1}{#1}{#2}{#3}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@compare@}
+%\begin{definition}
+% \cs{dtl@compare@}\marg{keyA}\marg{keyB}\marg{A toks}\marg{B toks}
+%\end{definition}
+% Compare \meta{A} and \meta{B} according \meta{keyA} and
+% \meta{keyB} for database given by \cs{@dtl@dbname}. Sets
+% \cs{dtl@sortresult}.
+% \cs{@dtl@comparecs} must be set before use.
+%\changes{2.0}{2009 February 27}{updated to use new database
+% structure}
+% \begin{macrocode}
+\newcommand{\dtl@compare@}[4]{%
+% \end{macrocode}
+% Get the data type for first key and store in \cs{@dtl@typeA}.
+% \begin{macrocode}
+ \DTLgetdatatype{\@dtl@typeA}{\@dtl@dbname}{#1}%
+% \end{macrocode}
+% Is it unset? If so, assume string
+% \begin{macrocode}
+ \ifx\@dtl@typeA\DTLunsettype
+ \let\@dtl@typeA\DTLstringtype
+ \fi
+% \end{macrocode}
+% Get the data type for the second key and store in \cs{@dtl@typeB}
+% \begin{macrocode}
+ \DTLgetdatatype{\@dtl@typeB}{\@dtl@dbname}{#2}%
+% \end{macrocode}
+% Is it unset? If so, assume string
+% \begin{macrocode}
+ \ifx\@dtl@typeB\DTLunsettype
+ \let\@dtl@typeB\DTLstringtype
+ \fi
+% \end{macrocode}
+% Multiply the two values together
+% \begin{macrocode}
+ \@dtl@tmpcount=\@dtl@typeA\relax
+ \multiply\@dtl@tmpcount by \@dtl@typeB\relax
+% \end{macrocode}
+% If either type is 0 (a string) then the product will also be
+% 0 (string) otherwise it will be one of the numerical types.
+% \begin{macrocode}
+ \ifnum\@dtl@tmpcount=0\relax
+% \end{macrocode}
+% A string, so use comparison function
+% \begin{macrocode}
+ \edef\@dtl@tmpcmp{%
+ \noexpand\@dtl@comparecs{\noexpand\dtl@sortresult}%
+ {\the#3}{\the#4}%
+ }%
+ \@dtl@tmpcmp
+ \ifdtlverbose
+ \edef\@dtl@a{\the#3}%
+ \edef\@dtl@b{\the#4}%
+ \fi
+ \else
+% \end{macrocode}
+% Store the first value
+% \begin{macrocode}
+ \edef\@dtl@a{\the#3}%
+% \end{macrocode}
+% Store the second value
+% \begin{macrocode}
+ \edef\@dtl@b{\the#4}%
+% \end{macrocode}
+% Compare
+% \begin{macrocode}
+ \DTLifnumlt{\@dtl@a}{\@dtl@b}%
+ {%
+% \end{macrocode}
+% $A < B$
+% \begin{macrocode}
+ \dtl@sortresult=-1\relax
+ }%
+ {%
+ \DTLifnumgt{\@dtl@a}{\@dtl@b}%
+ {%
+% \end{macrocode}
+% $A > B$
+% \begin{macrocode}
+ \dtl@sortresult=1\relax
+ }%
+ {%
+% \end{macrocode}
+% $A = B$
+% \begin{macrocode}
+ \dtl@sortresult=0\relax
+ }%
+ }%
+ \fi
+% \end{macrocode}
+% Write comparison result to terminal/log if verbose mode.
+% \begin{macrocode}
+ \ifdtlverbose
+ \@onelevel@sanitize\@dtl@a
+ \@onelevel@sanitize\@dtl@b
+ \dtl@message{`\@dtl@a' <=> `\@dtl@b' = \number\dtl@sortresult}%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\section{Saving a database to an external file}
+%
+%\begin{macro}{\@dtl@write}
+% \begin{macrocode}
+\newwrite\@dtl@write
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLsavedb}
+%\begin{definition}
+% \cs{DTLsavedb}\marg{db name}\marg{filename}
+%\end{definition}
+% Save a database as an ASCII data file using the separator
+% and delimiter given by \cs{@dtl@separator} and \cs{@dtl@delimiter}.
+%\changes{2.0}{2009 February 27}{updated to use new database structure}
+% \begin{macrocode}
+\newcommand*{\DTLsavedb}[2]{%
+ \DTLifdbexists{#1}%
+ {%
+% \end{macrocode}
+% Open output file
+%\changes{2.02}{2009 July 13}{Fixed bug that didn't set the filename}
+% \begin{macrocode}
+ \openout\@dtl@write=#2\relax
+% \end{macrocode}
+% Initialise header row
+% \begin{macrocode}
+ \def\@dtl@header{}%
+% \end{macrocode}
+% Construct the header row
+% \begin{macrocode}
+ \dtlforeachkey(\@dtl@key,\@dtl@col,\@dtl@type,\@dtl@head)%
+ \in{#1}\do
+ {%
+ \IfSubStringInString{\@dtl@separator}{\@dtl@key}%
+ {%
+ \ifdefempty{\@dtl@header}%
+ {%
+ \protected@edef\@dtl@header{%
+ \@dtl@delimiter\@dtl@key\@dtl@delimiter}%
+ }%
+ {%
+ \toks@=\expandafter{\@dtl@header}%
+ \protected@edef\@dtl@header{%
+ \the\toks@\@dtl@separator
+ \@dtl@delimiter\@dtl@key\@dtl@delimiter}%
+ }%
+ }%
+ {%
+ \ifdefempty{\@dtl@header}%
+ {%
+ \protected@edef\@dtl@header{\@dtl@key}%
+ }%
+ {%
+ \toks@=\expandafter{\@dtl@header}%
+ \protected@edef\@dtl@header{\the\toks@
+ \@dtl@separator\@dtl@key}%
+ }%
+ }%
+ }%
+% \end{macrocode}
+% Print header
+% \begin{macrocode}
+ \protected@write\@dtl@write{}{\@dtl@header}%
+% \end{macrocode}
+% Iterate through each row
+% \begin{macrocode}
+ \@sDTLforeach{#1}{}%
+ {%
+% \end{macrocode}
+% Initialise row
+% \begin{macrocode}
+ \def\@dtl@row{}%
+% \end{macrocode}
+% Iterate through each key
+% \begin{macrocode}
+ \DTLforeachkeyinrow{\@dtl@val}%
+ {%
+ \IfSubStringInString{\@dtl@separator}{\@dtl@val}%
+ {%
+ \ifdefempty{\@dtl@row}%
+ {%
+ \protected@edef\@dtl@row{%
+ \@dtl@delimiter\@dtl@val\@dtl@delimiter}%
+ }%
+ {%
+ \toks@=\expandafter{\@dtl@row}%
+ \protected@edef\@dtl@row{\the\toks@\@dtl@separator
+ \@dtl@delimiter\@dtl@val\@dtl@delimiter}%
+ }%
+ }%
+ {%
+ \ifdefempty{\@dtl@row}%
+ {%
+ \protected@edef\@dtl@row{\@dtl@val}%
+ }%
+ {%
+ \toks@=\expandafter{\@dtl@row}%
+ \protected@edef\@dtl@row{\the\toks@\@dtl@separator
+ \@dtl@val}%
+ }%
+ }%
+ }%
+% \end{macrocode}
+% Print row\changes{2.03}{2009 November 15}{Moved outside loop}
+% \begin{macrocode}
+ \protected@write\@dtl@write{}{\@dtl@row}%
+ }%
+% \end{macrocode}
+% Close output file
+% \begin{macrocode}
+ \closeout\@dtl@write
+ }%
+ {%
+ \PackageError{datatool}{Can't save database `#1': no such
+ database}{}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLsavetexdb}
+%\begin{definition}
+% \cs{DTLsavetexdb}\marg{db name}\marg{filename}
+%\end{definition}
+% Save a database as a \LaTeX\ file.
+%\changes{2.0}{2009 February 27}{updated to use new database structure}
+% \begin{macrocode}
+\newcommand*{\DTLsavetexdb}[2]{%
+ \DTLifdbexists{#1}%
+ {%
+% \end{macrocode}
+% Open output file
+% \begin{macrocode}
+ \openout\@dtl@write=#2\relax
+% \end{macrocode}
+% Write new data base definition
+% \begin{macrocode}
+ \protected@write\@dtl@write{}{\string\DTLnewdb{#1}}%
+% \end{macrocode}
+% Iterate through each row
+% \begin{macrocode}
+ \@sDTLforeach{#1}{}%
+ {%
+% \end{macrocode}
+% Start new row
+% \begin{macrocode}
+ \protected@write\@dtl@write{}{\string\DTLnewrow*{#1}}%
+% \end{macrocode}
+% Iterate through each column
+% \begin{macrocode}
+ \DTLforeachkeyinrow{\@dtl@val}%
+ {%
+% \end{macrocode}
+% Is this entry null?
+% \begin{macrocode}
+ \DTLifnull{\@dtl@val}%
+ {\def\@dtl@val{}}%
+ {}%
+% \end{macrocode}
+% Add entry
+% \begin{macrocode}
+ \protected@write\@dtl@write{}{%
+ \string\DTLnewdbentry*{#1}{\dtlkey}{\@dtl@val}}%
+ }%
+ }%
+% \end{macrocode}
+% Save the column headers.
+% \begin{macrocode}
+ \dtlforeachkey(\@dtl@k,\@dtl@c,\@dtl@t,\@dtl@h)\in{#1}\do
+ {%
+ \@onelevel@sanitize\@dtl@h
+ \protected@write\@dtl@write{}{%
+ \string\DTLsetheader*{#1}{\@dtl@k}{\@dtl@h}}%
+ }%
+% \end{macrocode}
+% Store name of database in case required after database loaded:
+%\changes{2.15}{2013-07-10}{added \cs{dtllastloadeddb}}
+% \begin{macrocode}
+ \protected@write{\@dtl@write}{}{\string\def\string\dtllastloadeddb{#1}}%
+% \end{macrocode}
+% Close output file
+% \begin{macrocode}
+ \closeout\@dtl@write
+ }%
+ {%
+ \PackageError{datatool}{Can't save database `#1': no such
+ database}{}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@saverawdbhook}
+% Hook used by \cs{DTLsaverawdb}.
+% \begin{macrocode}
+\newcommand*{\dtl@saverawdbhook}{}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLsaverawdb}
+% Saves given database in its internal form. Not easy for a human to
+% read, but much faster to load.
+%\changes{2.13}{2013-01-15}{new}
+% \begin{macrocode}
+\newcommand*{\DTLsaverawdb}[2]{%
+ \DTLifdbexists{#1}%
+ {%
+% \end{macrocode}
+% Open output file
+% \begin{macrocode}
+ \openout\@dtl@write=#2\relax
+% \end{macrocode}
+% Add code at the start of the output file to check for the
+% existence of the database:
+% \begin{macrocode}
+ \protected@write{\@dtl@write}{}{%
+ \string\DTLifdbexists{#1}\expandafter\@gobble\string\%^^J%
+ {%
+ \string\PackageError{datatool}{Database `#1' ^^Jalready exists}{}%
+ \expandafter\@gobble\string\%^^J%
+ \string\aftergroup\string\endinput
+ }%
+ {%
+ }\expandafter\@gobble\string\%
+ }%
+% \end{macrocode}
+% Scope need to localise definitions:
+% \begin{macrocode}
+ {%
+% \end{macrocode}
+% \begin{macrocode}
+ \def\db@row@elt@w{\expandafter\@gobble\string\%^^J\string\db@row@elt@w\space}%
+ \def\db@row@elt@end@{\expandafter\@gobble\string\%^^J\string\db@row@elt@end@\space}%
+ \def\db@row@id@w{\expandafter\@gobble\string\%^^J\string\db@row@id@w\space}%
+ \def\db@row@id@end@{\expandafter\@gobble\string\%^^J\string\db@row@id@end@\space}%
+ \def\db@col@elt@w{\expandafter\@gobble\string\%^^J\string\db@col@elt@w\space}%
+ \def\db@col@elt@end@{\expandafter\@gobble\string\%^^J\string\db@col@elt@end@\space}%
+ \def\db@col@id@w{\expandafter\@gobble\string\%^^J\string\db@col@id@w\space}%
+ \def\db@col@id@end@{\expandafter\@gobble\string\%^^J\string\db@col@id@end@\space}%
+%
+ \def\db@plist@elt@w{\expandafter\@gobble\string\%^^J\string\db@plist@elt@w\space}%
+ \def\db@plist@elt@end@{\expandafter\@gobble\string\%^^J\string\db@plist@elt@end@\space}%
+ \def\db@key@id@w{\expandafter\@gobble\string\%^^J\string\db@key@id@w\space}%
+ \def\db@key@id@end@{\expandafter\@gobble\string\%^^J\string\db@key@id@end@\space}%
+ \def\db@type@id@w{\expandafter\@gobble\string\%^^J\string\db@type@id@w\space}%
+ \def\db@type@id@end@{\expandafter\@gobble\string\%^^J\string\db@type@id@end@\space}%
+ \def\db@header@id@w{\expandafter\@gobble\string\%^^J\string\db@header@id@w\space}%
+ \def\db@header@id@end@{\expandafter\@gobble\string\%^^J\string\db@header@id@end@\space}%
+% \end{macrocode}
+% Need to ensure the @ character can be used so \ics{makeatletter}
+% is required, but localise the effect.
+% \begin{macrocode}
+ \protected@write{\@dtl@write}{}{\string\bgroup\string\makeatletter}%
+% \end{macrocode}
+% If in verbose mode, add a message to let the user know what's
+% happening when the file is later loaded.
+% \begin{macrocode}
+ \protected@write{\@dtl@write}{}{%
+ \string\dtl@message{Reconstructing database^^J`#1'}%
+ \expandafter\@gobble\string\%}%
+% \end{macrocode}
+% Save the contents of the token register that holds the column
+% information (column id, header, type). (The write is delayed,
+% so the contents are first expanded and stored in a temporary
+% (global) macro to ensure its in the correct format when the write happens.)
+% \begin{macrocode}
+ \protected@write{\@dtl@write}{}{%
+ \string\expandafter
+ \string\global\string\expandafter^^J\string\newtoks
+ \string\csname\space dtlkeys@#1\string\endcsname}%
+ \protected@write{\@dtl@write}{}{%
+ \string\expandafter
+ \string\global^^J
+ \string\csname\space dtlkeys@#1\string\endcsname
+ =\expandafter\@gobble\string\{\expandafter\@gobble\string\%}%
+ \expandafter\protected@xdef\csname dtl@rawwritedbkeys@#1\endcsname{%
+ \the\csname dtlkeys@#1\endcsname}%
+ \protected@write{\@dtl@write}{}{\csname dtl@rawwritedbkeys@#1\endcsname}%
+ \protected@write{\@dtl@write}{}%
+ {\expandafter\@gobble\string\}\expandafter\@gobble\string\%}%
+% \end{macrocode}
+% Hook used by \sty{datagidx}:
+% \begin{macrocode}
+ \dtl@saverawdbhook
+% \end{macrocode}
+% Save the contents of the token register that holds the database
+% body.
+% \begin{macrocode}
+ \protected@write{\@dtl@write}{}{%
+ \string\expandafter\string\global
+ \string\expandafter^^J\string\newtoks
+ \string\csname\space dtldb@#1\string\endcsname}%
+ \protected@write{\@dtl@write}{}{%
+ \string\expandafter
+ \string\global^^J\string\csname\space dtldb@#1\string\endcsname
+ =\expandafter\@gobble\string\{\expandafter\@gobble\string\%}%
+ \expandafter\protected@xdef\csname dtl@rawwritedb@#1\endcsname{\the\csname dtldb@#1\endcsname}%
+ \protected@write{\@dtl@write}{}{\csname dtl@rawwritedb@#1\endcsname}%
+ \protected@write{\@dtl@write}{}{\expandafter\@gobble\string\}\expandafter\@gobble\string\%}%
+% \end{macrocode}
+% Now for the count register that keeps track of the row count.
+% \begin{macrocode}
+ \protected@write{\@dtl@write}{}{\string\expandafter\string\global^^J
+ \string\expandafter\string\newcount
+ \string\csname\space dtlrows@#1\string\endcsname}%
+ \protected@write{\@dtl@write}{}{\string\expandafter\string\global^^J
+ \string\csname\space dtlrows@#1\string\endcsname
+ =\expandafter\number\csname dtlrows@#1\endcsname\string\relax}%
+% \end{macrocode}
+% Similarly for the column count.
+% \begin{macrocode}
+ \protected@write{\@dtl@write}{}{\string\expandafter\string\global^^J
+ \string\expandafter\string\newcount
+ \string\csname\space dtlcols@#1\string\endcsname}%
+ \protected@write{\@dtl@write}{}{\string\expandafter\string\global^^J
+ \string\csname\space dtlcols@#1\string\endcsname
+ =\expandafter\number\csname dtlcols@#1\endcsname\string\relax}%
+% \end{macrocode}
+% Add key mappings
+% \begin{macrocode}
+ \dtlforeachkey(\@dtl@key,\@dtl@col,\@dtl@type,\@dtl@head)\in{#1}\do
+ {%
+ \edef\dtl@tmp{%
+ \string\expandafter^^J
+ \string\gdef
+ \string\csname\space dtl@ci@#1@\@dtl@key\string\endcsname
+ {\csname dtl@ci@#1@\@dtl@key\endcsname}\expandafter\@gobble\string\%
+ }%
+ \expandafter\write\expandafter\@dtl@write\expandafter{\dtl@tmp}%
+ }%
+% \end{macrocode}
+% End the scope for \ics{makeatletter:}
+% \begin{macrocode}
+ \protected@write{\@dtl@write}{}{\string\egroup}%
+% \end{macrocode}
+% End current scope:
+% \begin{macrocode}
+ }%
+% \end{macrocode}
+% Store name of database in case required after database loaded:
+%\changes{2.15}{2013-07-10}{added \cs{dtllastloadeddb}}
+% \begin{macrocode}
+ \protected@write{\@dtl@write}{}{\string\def\string\dtllastloadeddb{#1}}%
+% \end{macrocode}
+% Close output file
+% \begin{macrocode}
+ \closeout\@dtl@write
+ }%
+ {%
+ \PackageError{datatool}{Can't save database `#1': no such
+ database}{}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLprotectedsaverawdb}
+% Like \cs{DTLsaverawdb} but works with fragile contents. If there's a
+% problem with unwanted line breaks every 80 characters, try loading
+% \sty{morewrites} before \sty{datatool}.
+%\changes{2.15}{2013-07-10}{new}
+% \begin{macrocode}
+\newcommand*{\DTLprotectedsaverawdb}[2]{%
+ \DTLifdbexists{#1}%
+ {%
+% \end{macrocode}
+% Open output file
+% \begin{macrocode}
+ \openout\@dtl@write=#2\relax
+% \end{macrocode}
+% Add code at the start of the output file to check for the
+% existence of the database:
+% \begin{macrocode}
+ \protected@write{\@dtl@write}{}{%
+ \string\DTLifdbexists{#1}\expandafter\@gobble\string\%^^J%
+ {%
+ \string\PackageError{datatool}{Database `#1' ^^Jalready exists}{}%
+ \expandafter\@gobble\string\%^^J%
+ \string\aftergroup\string\endinput
+ }%
+ {%
+ }\expandafter\@gobble\string\%
+ }%
+% \end{macrocode}
+% Scope needed to localise definitions:
+% \begin{macrocode}
+ {%
+% \end{macrocode}
+% Need to ensure the @ character can be used so \ics{makeatletter}
+% is required, but localise the effect.
+% \begin{macrocode}
+ \protected@write{\@dtl@write}{}{\string\bgroup\string\makeatletter}%
+% \end{macrocode}
+% If in verbose mode, add a message to let the user know what's
+% happening when the file is later loaded.
+% \begin{macrocode}
+ \protected@write{\@dtl@write}{}{\string\dtl@message{Reconstructing database
+ ^^J`#1'}\expandafter\@gobble\string\%}%
+% \end{macrocode}
+% Start writing the header token definition.
+% \begin{macrocode}
+ \protected@write{\@dtl@write}{}{%
+ \string\expandafter
+ \string\global\string\expandafter^^J\string\newtoks
+ \string\csname\space dtlkeys@#1\string\endcsname}%
+ \protected@write{\@dtl@write}{}{%
+ \string\expandafter
+ \string\global^^J
+ \string\csname\space dtlkeys@#1\string\endcsname
+ =\expandafter\@gobble\string\{\expandafter\@gobble\string\%}%
+% Store the contents of the token register that holds the column
+% information (column id, header, type) and sanitize.
+% \begin{macrocode}
+ \edef\dtl@rawwrite@keys{\the\csname dtlkeys@#1\endcsname}%
+ \@onelevel@sanitize\dtl@rawwrite@keys
+% \end{macrocode}
+% The write can get delayed, so expand after to ensure it has the
+% actual contents of the database rather than
+% \cs{dtl@rawwrite@keys}, which may have changed by the time the
+% write occurs. Include the closing brace of the token contents.
+% \begin{macrocode}
+ \expandafter\write\expandafter\@dtl@write\expandafter
+ {\dtl@rawwrite@keys\expandafter\@gobble\string\}}%
+% \end{macrocode}
+% Similarly for the token register that holds the database
+% body.
+% \begin{macrocode}
+ \protected@write{\@dtl@write}{}{%
+ \string\expandafter\string\global
+ \string\expandafter^^J\string\newtoks
+ \string\csname\space dtldb@#1\string\endcsname}%
+ \protected@write{\@dtl@write}{}{%
+ \string\expandafter
+ \string\global^^J\string\csname\space dtldb@#1\string\endcsname
+ =\expandafter\@gobble\string\{\expandafter\@gobble\string\%}%
+% \end{macrocode}
+% \begin{macrocode}
+ \edef\dtl@rawwrite@db{\the\csname dtldb@#1\endcsname}%
+ \@onelevel@sanitize\dtl@rawwrite@db
+% \end{macrocode}
+% Now write the sanitize contents.
+% \begin{macrocode}
+ \expandafter\write\expandafter\@dtl@write\expandafter
+ {\dtl@rawwrite@db\expandafter\@gobble\string\}}%
+% \end{macrocode}
+% Now for the count register that keeps track of the row count.
+% \begin{macrocode}
+ \protected@write{\@dtl@write}{}{\string\expandafter\string\global^^J
+ \string\expandafter\string\newcount
+ \string\csname\space dtlrows@#1\string\endcsname}%
+ \protected@write{\@dtl@write}{}{\string\expandafter\string\global^^J
+ \string\csname\space dtlrows@#1\string\endcsname
+ =\expandafter\number\csname dtlrows@#1\endcsname\string\relax}%
+% \end{macrocode}
+% Similarly for the column count.
+% \begin{macrocode}
+ \protected@write{\@dtl@write}{}{\string\expandafter\string\global^^J
+ \string\expandafter\string\newcount
+ \string\csname\space dtlcols@#1\string\endcsname}%
+ \protected@write{\@dtl@write}{}{\string\expandafter\string\global^^J
+ \string\csname\space dtlcols@#1\string\endcsname
+ =\expandafter\number\csname dtlcols@#1\endcsname\string\relax}%
+% \end{macrocode}
+% Add key mappings
+% \begin{macrocode}
+ \dtlforeachkey(\@dtl@key,\@dtl@col,\@dtl@type,\@dtl@head)\in{#1}\do
+ {%
+ \edef\dtl@tmp{%
+ \string\expandafter^^J
+ \string\gdef
+ \string\csname\space dtl@ci@#1@\@dtl@key\string\endcsname
+ {\csname dtl@ci@#1@\@dtl@key\endcsname}\expandafter\@gobble\string\%
+ }%
+ \expandafter\write\expandafter\@dtl@write\expandafter{\dtl@tmp}%
+ }%
+% \end{macrocode}
+% End the scope for \ics{makeatletter}:
+% \begin{macrocode}
+ \protected@write{\@dtl@write}{}{\string\egroup}%
+% \end{macrocode}
+% End current scope:
+% \begin{macrocode}
+ }%
+% \end{macrocode}
+% Provide a means to keep track of the last loaded file:
+% \begin{macrocode}
+ \protected@write{\@dtl@write}{}{\string\def\string\dtllastloadeddb{#1}}%
+% \end{macrocode}
+% Close output file
+% \begin{macrocode}
+ \closeout\@dtl@write
+ }%
+ {%
+ \PackageError{datatool}{Can't save database `#1': no such
+ database}{}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\section{Loading a database from an external file}
+%
+%\begin{macro}{\DTLloaddbtex}
+%\begin{definition}
+%\cs{DTLloaddbtex}\marg{cs}\marg{file}
+%\end{definition}
+% Load a \texttt{.dbtex} file and assign the database name to the
+% control sequence \meta{cs}. Checks the file name exists and the
+% control sequence doesn't exist.
+%\changes{2.20}{2014-02-03}{new}
+% \begin{macrocode}
+\newcommand*{\DTLloaddbtex}[2]{%
+ \IfFileExists{#2}%
+ {%
+ \input{#2}%
+ \ifdef#1%
+ {%
+ \PackageError{datatool}{Command \string#1\space is already defined}%
+ {}%
+ }%
+ {%
+ \let#1\dtllastloadeddb
+ }%
+ }%
+ {%
+ \PackageError{datatool}{File `#2' doesn't exist.}{}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@read}
+% \begin{macrocode}
+\newread\@dtl@read
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtl@entrycr}
+% Keep track of current column in data file
+% \begin{macrocode}
+\newcount\dtl@entrycr
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\ifdtlnoheader}
+% The "noheader" option indicates that the file doesn't have a
+% header row.
+% \begin{macrocode}
+\define@boolkey{loaddb}[dtl]{noheader}[true]{}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\ifdtlautokeys}
+%\changes{2.22}{2014-06-10}{new}
+%Assign the default keys even if a header row is supplied.
+% \begin{macrocode}
+\define@boolkey{loaddb}[dtl]{autokeys}[true]{}
+\dtlautokeysfalse
+% \end{macrocode}
+%\end{macro}
+% The "keys" option specifies the list of keys in the same order
+% as the columns in the data file.
+% Each key is stored in \cs{@dtl@inky@}\meta{n} where \meta{n} is the
+% roman numeral representation of the current column.
+% \begin{macrocode}
+\define@key{loaddb}{keys}{%
+ \dtl@entrycr=0\relax
+ \@for\@dtl@key:=#1\do
+ {%
+ \advance\dtl@entrycr by 1\relax
+ \expandafter
+ \edef\csname @dtl@inky@\romannumeral\dtl@entrycr\endcsname{%
+ \@dtl@key}%
+ }%
+}
+% \end{macrocode}
+% The "headers" option specifies the list of headers in the
+% same order as the columns in the data file.
+% \begin{macrocode}
+\define@key{loaddb}{headers}{%
+ \dtl@entrycr=0\relax
+ \@for\@dtl@head:=#1\do
+ {%
+ \advance\dtl@entrycr by 1\relax
+ \toks@=\expandafter{\@dtl@head}%
+ \expandafter
+ \edef\csname @dtl@inhd@\romannumeral\dtl@entrycr\endcsname{%
+ \the\toks@}%
+ }%
+}
+% \end{macrocode}
+%
+% The following is supplied in a patch by Bruno Le Floch:
+%\changes{2.10}{2012-07-18}{added omitlines key}
+% \begin{macrocode}
+\newcount{\dtl@omitlines}
+\define@key{loaddb}{omitlines}{\dtl@omitlines=#1\relax}
+% \end{macrocode}
+%
+%\begin{macro}{\dtldefaultkey}
+% Default key to use if none specified (column index will be
+% appended).
+% \begin{macrocode}
+\newcommand*{\dtldefaultkey}{Column}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@readline}
+%\begin{definition}
+%\cs{@dtl@readline}\marg{file reg}\marg{cs}
+%\end{definition}
+% Reads line from \meta{file reg}, trims end of line character
+% and stores in \meta{cs}.
+% \begin{macrocode}
+\newcommand*{\@dtl@readline}[2]{%
+% \end{macrocode}
+% Read a line from "#1" and store in "#2" but make sure end of line
+% character is removed.
+%\changes{2.29}{2017-11-12}{changed line read}
+% \begin{macrocode}
+ \begingroup
+ \catcode\endlinechar=\active%
+ \global\read#1 to #2%
+ \endgroup%
+% \end{macrocode}
+%If empty the row starts with a comment
+% \begin{macrocode}
+ \ifx#2\empty%
+ \else%
+ \expandafter\@dtl@stripeol#2%
+ \let#2\@dtl@strippedline%
+ \fi%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@stripeol}
+%\changes{2.29}{2017-11-12}{new}
+% \begin{macrocode}
+\begingroup
+\catcode\endlinechar=\active%
+\gdef\@dtl@stripeol#1
+{\gdef\@dtl@strippedline{#1}}
+\endgroup
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@readrawline}
+%\begin{definition}
+%\cs{@dtl@readrawline}\marg{file register}\marg{cs}
+%\end{definition}
+% Reads line from \meta{file register}, trims end of line character,
+% applies mappings and stores in \meta{cs}.
+% \begin{macrocode}
+\newcommand*{\@dtl@readrawline}[2]{%
+% \end{macrocode}
+% Read a line from "#1" and store in "#2"
+% \begin{macrocode}
+ \@dtl@rawread#1 to #2%
+% \end{macrocode}
+% Apply mappings
+% \begin{macrocode}
+ \dtl@domappings\@dtl@line
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\ifDTLnewdbonload}
+% Governs whether or not the database should be defined by
+% \ics{DTLloaddb} and \ics{DTLloadrawdb}.
+%\changes{2.13}{2013-01-15}{new}
+% \begin{macrocode}
+\newif\ifDTLnewdbonload
+% \end{macrocode}
+% Ensure compatibility with previous versions:
+% \begin{macrocode}
+\DTLnewdbonloadtrue
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLloaddb}
+%\begin{definition}
+% \cs{DTLloaddb}\oarg{options}\marg{db name}\marg{filename}
+%\end{definition}
+% Creates a new database called \meta{db name}, and loads the data
+% in \meta{filename} into it. The separator and delimiter used in
+% the file must match \cs{@dtl@separator} and \cs{@dtl@delimiter}.
+% The optional argument is a comma-separated list.
+%\changes{2.0}{2009 February 27}{removed checks to see if the
+% database exists when adding to it}
+%\changes{2.0}{2009 February 27}{added optional argument}
+% \begin{macrocode}
+\newcommand*{\DTLloaddb}{%
+ \let\@dtl@doreadline\@dtl@readline
+ \@dtlloaddb
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtlloaddb}
+% Loads database using \cs{@dtl@doreadline} to read and trim
+% line from file. (\cs{@dtl@doreadline} must be set before use.)
+% \begin{macrocode}
+\newcommand*{\@dtlloaddb}[3][]{%
+% \end{macrocode}
+% Check if file exists
+% \begin{macrocode}
+ \IfFileExists{#3}{%
+% \end{macrocode}
+% File exists. Locally change catcode of double quote character in
+% case it has been made active.
+% \begin{macrocode}
+ \begingroup
+ \catcode`\"12\relax
+% \end{macrocode}
+% Initialise default options
+% \begin{macrocode}
+ \dtlnoheaderfalse
+% \end{macrocode}
+% Get the options
+% \begin{macrocode}
+ \setkeys{loaddb}{#1}%
+% \end{macrocode}
+% Open the file for reading.
+% \begin{macrocode}
+ \openin\@dtl@read=#3%
+ \dtl@message{Reading `#3'}%
+% \end{macrocode}
+% The following supplied in patch by Bruno Le~Floch:
+%\changes{2.10}{2012-07-18}{added code to skip lines}
+% \begin{macrocode}
+ \loop
+ \ifnum \dtl@omitlines > \z@
+ \advance\dtl@omitlines by \m@ne
+ \read\@dtl@read to \@dtl@line
+ \repeat
+% \end{macrocode}
+% Create the database if required.
+% \begin{macrocode}
+ \ifDTLnewdbonload
+ \DTLnewdb{#2}%
+ \fi
+% \end{macrocode}
+% Check if the file is empty.
+% \begin{macrocode}
+ \ifeof\@dtl@read
+% \end{macrocode}
+% File is empty, so just issue a warning.
+% \begin{macrocode}
+ \PackageWarning{datatool}{File `#3' has no data}%
+ \else
+% \end{macrocode}
+% Does the file have a header row?
+% \begin{macrocode}
+ \ifdtlnoheader
+ \else
+% \end{macrocode}
+% Remove initial blank rows
+% \begin{macrocode}
+ \loop
+% \end{macrocode}
+% Set repeat condition to false
+% \begin{macrocode}
+ \@dtl@conditionfalse
+% \end{macrocode}
+% Do nothing if reached the end of file
+% \begin{macrocode}
+ \ifeof\@dtl@read
+ \else
+% \end{macrocode}
+% Read a line from the file and store in \cs{@dtl@line}
+% \begin{macrocode}
+ \@dtl@doreadline\@dtl@read\@dtl@line
+% \end{macrocode}
+% If this is a blank row, set repeat condition to true
+% \begin{macrocode}
+ \ifdefempty{\@dtl@line}%
+ {%
+ \@dtl@conditiontrue
+ }%
+ {%
+ }%
+ \fi
+% \end{macrocode}
+% Repeat loop if necessary
+% \begin{macrocode}
+ \if@dtl@condition
+ \repeat
+% \end{macrocode}
+% Parse the header row. Store the row as
+% \meta{sep}\meta{row}\meta{sep} in \cs{@dtl@lin@}.
+% \begin{macrocode}
+ \protected@edef\@dtl@lin@{%
+ \@dtl@separator\@dtl@line\@dtl@separator}%
+% \end{macrocode}
+% Keep track of columns:
+% \begin{macrocode}
+ \dtl@entrycr=0\relax
+% \end{macrocode}
+% Keep lopping off elements until the end of the row is reached.
+% (That is, until \cs{@dtl@lin@} is \cs{@dtl@separator}.)
+%\changes{2.0}{2009 February 27}{changed \cs{whiledo} to
+% \cs{loop} to improve efficiency}%
+% \begin{macrocode}
+ \loop
+% \end{macrocode}
+% Lopoff the first element and store in \cs{@dtl@key}
+% \begin{macrocode}
+ \expandafter\@dtl@lopoff\@dtl@lin@\to\@dtl@lin@\@dtl@key
+% \end{macrocode}
+% Increment column count.
+% \begin{macrocode}
+ \advance\dtl@entrycr by 1\relax
+% \end{macrocode}
+% If autokeys option is on, add generic key
+%\changes{2.22}{2014-06-10}{added check for autokeys}
+% \begin{macrocode}
+ \ifdtlautokeys
+ \csedef{@dtl@inky@\romannumeral\dtl@entrycr}%
+ {\dtldefaultkey\number\dtl@entrycr}%
+ \else
+% \end{macrocode}
+% If missing a key, add generic one:
+%\changes{2.10}{2012-07-18}{add generic header if missing}
+% \begin{macrocode}
+ \ifdefempty{\@dtl@key}%
+ {%
+ \edef\@dtl@key{\dtldefaultkey\number\dtl@entrycr}%
+ }%
+ {}%
+ \fi
+% \end{macrocode}
+% Store key in \cs{@dtl@toks}
+% \begin{macrocode}
+ \expandafter\@dtl@toks\expandafter{\@dtl@key}%
+% \end{macrocode}
+% Store the key in \cs{@dtl@inky@}\meta{n} where \meta{n} is the
+% roman numeral representation of the current column, unless
+% already defined.
+% \begin{macrocode}
+ \@ifundefined{@dtl@inky@\romannumeral\dtl@entrycr}%
+ {%
+ \expandafter
+ \edef\csname @dtl@inky@\romannumeral
+ \dtl@entrycr\endcsname{\the\@dtl@toks}%
+ }%
+ {%
+% \end{macrocode}
+% If key has been specified in "#1", then use the header found in the
+% file, unless a header has also been specified in "#1"
+% \begin{macrocode}
+ \@ifundefined{@dtl@inhd@\romannumeral\dtl@entrycr}%
+ {%
+ \expandafter
+ \edef\csname @dtl@inhd@\romannumeral
+ \dtl@entrycr\endcsname{\the\@dtl@toks}%
+ }%
+ {}%
+ }%
+% \end{macrocode}
+% Check if the loop should be repeated
+% \begin{macrocode}
+ \ifx\@dtl@lin@\@dtl@separator
+ \@dtl@conditionfalse
+ \else
+ \@dtl@conditiontrue
+ \fi
+% \end{macrocode}
+% Repeat loop if necessary.
+% \begin{macrocode}
+ \if@dtl@condition
+ \repeat
+% \end{macrocode}
+% End if no header
+% \begin{macrocode}
+ \fi
+% \end{macrocode}
+% Now for the rest of the data. If the end of file has been
+% reached, then only the header row is available or file is empty.
+% \begin{macrocode}
+ \ifeof\@dtl@read
+ \ifdtlnoheader
+ \PackageWarning{datatool}{No data in `#3'}%
+ \else
+ \PackageWarning{datatool}{Only header row found in `#3'}%
+ \fi
+ \else
+% \end{macrocode}
+% Iterate through the rest of the file. First set the repeat
+% condition to true:
+% \begin{macrocode}
+ \@dtl@conditiontrue
+ \loop
+% \end{macrocode}
+% Read in a line
+% \begin{macrocode}
+ \@dtl@doreadline\@dtl@read\@dtl@line
+% \end{macrocode}
+% Check if the line is empty.
+%\changes{2.0}{2009 February 27}{changed \cs{ifthenelse} to
+%\cs{ifx} to improve efficiency}
+%\changes{2.10}{2012-07-18}{changed \cs{ifx} to \cs{ifdefempty}}
+% \begin{macrocode}
+ \ifdefempty{\@dtl@line}%
+ {%
+% \end{macrocode}
+% Do nothing if the row is empty.
+% \begin{macrocode}
+ }%
+ {%
+% \end{macrocode}
+% Add a new row to the database. (Don't need to check if the
+% database exists, since it's just been created.)
+% \begin{macrocode}
+ \@sDTLnewrow{#2}%
+% \end{macrocode}
+% Store the row as \meta{sep}\meta{row}\meta{sep} to make the
+% lopping off easier
+% \begin{macrocode}
+ \expandafter\@dtl@toks\expandafter{\@dtl@line}%
+ \edef\@dtl@lin@{\@dtl@separator\the\@dtl@toks
+ \@dtl@separator}%
+% \end{macrocode}
+% Reset the column counter.
+% \begin{macrocode}
+ \dtl@entrycr=0\relax
+% \end{macrocode}
+%\changes{2.0}{2009 February 27}{changed \cs{whiledo} to \cs{loop}
+% to improve efficiency}
+% Iterate through each element in the row. Needs to be grouped
+% since we're already inside a loop.
+% \begin{macrocode}
+ {%
+% \end{macrocode}
+% Initialise repeat condition
+% \begin{macrocode}
+ \@dtl@conditiontrue
+% \end{macrocode}
+% Iterate through the list
+% \begin{macrocode}
+ \loop
+% \end{macrocode}
+% lop off first element and store in \cs{@dtl@thisentry}
+% \begin{macrocode}
+ \expandafter\@dtl@lopoff\@dtl@lin@\to
+ \@dtl@lin@\@dtl@thisentry
+% \end{macrocode}
+% Increment the column count.
+% \begin{macrocode}
+ \advance\dtl@entrycr by 1\relax
+% \end{macrocode}
+% Get the key for this column and store in \cs{@dtl@thiskey}.
+% Use default value if not defined.
+% \begin{macrocode}
+ \@ifundefined{@dtl@inky@\romannumeral\dtl@entrycr}%
+ {%
+ \edef\@dtl@thiskey{\dtldefaultkey
+ \number\dtl@entrycr}%
+ \expandafter\let
+ \csname @dtl@inky@\romannumeral
+ \dtl@entrycr\endcsname\@dtl@thiskey
+ }%
+ {%
+ \edef\@dtl@thiskey{%
+ \csname @dtl@inky@\romannumeral
+ \dtl@entrycr\endcsname}%
+ }%
+% \end{macrocode}
+% Store this entry in \cs{@dtl@toks}
+% \begin{macrocode}
+ \expandafter\@dtl@toks\expandafter{\@dtl@thisentry}%
+% \end{macrocode}
+% Add this entry to the database
+% \begin{macrocode}
+ \edef\@do@dtlnewentry{\noexpand\@sDTLnewdbentry
+ {#2}{\@dtl@thiskey}{\the\@dtl@toks}}%
+ \@do@dtlnewentry
+% \end{macrocode}
+% Check if loop should be terminated
+% \begin{macrocode}
+ \ifx\@dtl@lin@\@dtl@separator
+ \@dtl@conditionfalse
+ \fi
+% \end{macrocode}
+% Repeat loop if necessary
+% \begin{macrocode}
+ \if@dtl@condition
+ \repeat
+ }%
+% \end{macrocode}
+% End of parsing this row
+% \begin{macrocode}
+ }%
+% \end{macrocode}
+% If the end of file has been reached, set the repeat condition
+% to false.
+% \begin{macrocode}
+ \ifeof\@dtl@read \@dtl@conditionfalse\fi
+% \end{macrocode}
+% Repeat if necessary
+% \begin{macrocode}
+ \if@dtl@condition
+ \repeat
+ \fi
+% \end{macrocode}
+% End of first \cs{ifeof}
+% \begin{macrocode}
+ \fi
+% \end{macrocode}
+% Close the input file
+% \begin{macrocode}
+ \closein\@dtl@read
+% \end{macrocode}
+% Set the headers if required
+% \begin{macrocode}
+ \edef\@dtl@maxcols{\expandafter
+ \number\csname dtlcols@#2\endcsname}%
+ \dtlgforint\dtl@entrycr=1\to\@dtl@maxcols\step1\do
+ {%
+ \@ifundefined{@dtl@inhd@\romannumeral\dtl@entrycr}%
+ {}%
+ {%
+ \expandafter\let\expandafter\@dtl@head
+ \csname @dtl@inhd@\romannumeral\dtl@entrycr\endcsname
+ \@dtl@toks=\expandafter{\@dtl@head}%
+ \edef\@dtl@dosetheader{\noexpand\@dtl@setheaderforindex
+ {#2}{\number\dtl@entrycr}{\the\@dtl@toks}}%
+ \@dtl@dosetheader
+ }%
+ }%
+% \end{macrocode}
+% End current scope
+% \begin{macrocode}
+ \endgroup
+% \end{macrocode}
+% End true part of if file exists
+% \begin{macrocode}
+ }{%
+% \end{macrocode}
+% Requested file not found on TeX's path
+% \begin{macrocode}
+ \PackageError{datatool}{Can't load database `#2' (file `#3'
+ doesn't exist)}{}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLloadrawdb}
+%\begin{definition}
+%\cs{DTLloadrawdb}\marg{db name}\marg{filename}
+%\end{definition}
+% Loads a raw database (substitutes "%" $\to$ "\%",
+% "$" $\to$ "\$", "&" $\to$ "\&", "#" $\to$ "\#",
+% "~" $\to$ "\textasciitilde", "_" $\to$ "\_"
+% and "^" $\to$ "\textasciicircum".) The user can add additional
+% mappings.
+% \begin{macrocode}
+\newcommand*\DTLloadrawdb{%
+ \let\@dtl@doreadline\@dtl@readrawline
+ \@dtlloaddb
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@rawread}
+%\begin{definition}
+% \cs{@dtl@rawread}\meta{number}to\meta{cmd}
+%\end{definition}
+% Reads in a raw line from file given by \meta{number}
+% converts special characters and stores in \meta{cmd}
+% \begin{macrocode}
+\begingroup
+\catcode`\%=\active
+\catcode`$=\active
+\catcode`&=\active
+\catcode`~=\active
+\catcode`_=\active
+\catcode`^=\active
+\catcode`#=\active
+\catcode`?=6\relax
+\catcode`<=1\relax
+\catcode`>=2\relax
+\catcode`\{=\active
+\catcode`\}=\active
+\gdef\@dtl@rawread?1to?2<\relax
+<<\catcode`\%=\active
+\catcode`$=\active
+\catcode`&=\active
+\catcode`~=\active
+\catcode`_=\active
+\catcode`^=\active
+\catcode`#=\active
+\catcode`\{=\active
+\catcode`\}=\active
+\def%<\noexpand\%>\relax
+\def$<\noexpand\$>\relax
+\def&<\&>\relax
+\def#<\#>\relax
+\def~<\noexpand\textasciitilde>\relax
+\def_<\noexpand\_>\relax
+\def^<\noexpand\textasciicircum>\relax
+\@dtl@activatebraces
+\@dtl@doreadraw?1?2>>>
+\gdef\@dtl@doreadraw?1?2<\relax
+\begingroup\catcode\endlinechar=\active\global\read?1 to \dtl@tmp\endgroup
+\expandafter\@dtl@stripeol\dtl@tmp
+\let\dtl@tmp\@dtl@strippedline
+\protected@xdef?2<\dtl@tmp>\relax
+>
+\endgroup
+% \end{macrocode}
+%\changes{2.28}{2017-11-10}{changed \cs{xdef} to \cs{protected@xdef}}.
+%\end{macro}
+%\begin{macro}{\@dtl@activatebraces}
+% \cs{@dtl@activatebraces} resets braces for \cs{@dtl@rawread}
+% \begin{macrocode}
+\begingroup
+\catcode`\{=\active
+\catcode`\}=\active
+\catcode`<=1\relax
+\catcode`>=2\relax
+\gdef\@dtl@activatebraces<%
+ \catcode`\{=\active
+ \catcode`\}=\active
+ \def{<\noexpand\{>%
+ \def}<\noexpand\}>%
+>%
+\endgroup
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLrawmap}
+%\begin{definition}
+%\cs{DTLrawmap}\marg{string}\marg{replacement}
+%\end{definition}
+% Additional mappings to perform when reading a raw data file
+% \begin{macrocode}
+\newcommand*{\DTLrawmap}[2]{%
+ \expandafter\@dtl@toks\expandafter{\@dtl@rawmappings}%
+ \ifdefempty{\@dtl@rawmappings}%
+ {%
+ \def\@dtl@rawmappings{{#1}{#2}}%
+ }%
+ {%
+% \end{macrocode}
+%\changes{2.13}{2013-01-15}{removed spurious space}
+% \begin{macrocode}
+ \def\@dtl@tmp{{#1}{#2}}%
+ \protected@edef\@dtl@rawmappings{\the\@dtl@toks,\@dtl@tmp}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@rawmappings}
+% List of mappings.
+% \begin{macrocode}
+\newcommand*{\@dtl@rawmappings}{}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtl@domappings}
+%\begin{definition}
+% \cs{dtl@domappings}\marg{cmd}
+%\end{definition}
+% Do all mappings in string given by \meta{cmd}.
+%\changes{2.10}{2012-07-18}{replaced \cs{DTLsubstitute} with
+%\cs{DTLsubstituteall}}
+% \begin{macrocode}
+\newcommand*{\dtl@domappings}[1]{%
+ \@for\@dtl@map:=\@dtl@rawmappings\do{%
+ \expandafter\DTLsubstituteall\expandafter#1\@dtl@map
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\section{Debugging commands}
+% These commands are provided to assist debugging
+%\begin{macro}{\dtlshowdb}
+%\begin{definition}
+%\cs{dtlshowdb}\marg{db name}
+%\end{definition}
+% Shows the database.
+%\changes{2.0}{2009 February 27}{updated to use new database structure}
+% \begin{macrocode}
+\newcommand*{\dtlshowdb}[1]{%
+ \expandafter\showthe\csname dtldb@#1\endcsname
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlshowdbkeys}
+%\begin{definition}
+%\cs{dtlshowdbkeys}\marg{db name}
+%\end{definition}
+% Shows the key list for the named database.
+%\changes{2.0}{2009 February 27}{updated to use new database structure}
+% \begin{macrocode}
+\newcommand*{\dtlshowdbkeys}[1]{%
+ \expandafter\showthe\csname dtlkeys@#1\endcsname
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlshowtype}
+%\begin{definition}
+%\cs{dtlshowtype}\marg{db name}\marg{key}
+%\end{definition}
+% Show the data type for given key in the named database.
+% This should be an integer from 0 to 3.
+%\changes{2.0}{2009 February 27}{updated to use new database structure}
+% \begin{macrocode}
+\newcommand*{\dtlshowtype}[2]{%
+ \DTLgetdatatype{\@dtl@type}{#1}{#2}\show\@dtl@type
+}
+% \end{macrocode}
+%\end{macro}
+%\iffalse
+% \begin{macrocode}
+%</datatool.sty>
+% \end{macrocode}
+%\fi
+%\iffalse
+% \begin{macrocode}
+%<*datagidx.sty>
+% \end{macrocode}
+%\fi
+%\chapter{datagidx.sty}
+%\changes{2.13}{2013-01-15}{added datagidx package}
+% This package provides a means to produces indices and glossaries
+% without the need for an external indexing application, such as
+% \app{makeindex} or \app{xindy}. However, the code here has
+% been developed to implement the word order style described by the
+% Oxford Style Manual. If you are not writing in English, this may
+% not be applicable to your needs. You may be able to define your
+% own comparison handler to use with \cs{dtlsort}. If not, you'll
+% need to use \app{xindy} with a package such as
+% \sty{glossaries}.
+%
+% Declare package:
+% \begin{macrocode}
+\NeedsTeXFormat{LaTeX2e}
+\ProvidesPackage{datagidx}[2018/12/07 v2.31 (NLCT)]
+% \end{macrocode}
+% Required packages:
+% \begin{macrocode}
+\RequirePackage{datatool}
+\RequirePackage{etoolbox}
+\RequirePackage{xkeyval}
+\RequirePackage{mfirstuc}
+\RequirePackage{xfor}
+\RequirePackage{multicol}
+\RequirePackage{textcase}
+% \end{macrocode}
+%\changes{2.15}{2013-07-10}{added afterpage as a required package}
+% \begin{macrocode}
+\RequirePackage{afterpage}
+% \end{macrocode}
+%
+%\section{Default Settings}
+% These commands need to be defined before the package options are
+% used.
+%\begin{macro}{\datagidx@columns}
+% The number of columns to use for the index/glossary.
+% \begin{macrocode}
+\newcommand*{\datagidx@columns}{2}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLgidxSetColumns}
+% \begin{macrocode}
+\newcommand*{\DTLgidxSetColumns}[1]{%
+ \DTLifint{#1}%
+ {%
+ \def\datagidx@columns{#1}%
+ }%
+ {%
+ \PackageError{datagidx}%
+ {Number of columns must be an integer}%
+ {%
+ You have requested `#1' columns, which can't be parsed as a
+ number%
+ }%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{counter}{DTLgidxChildCount}
+% Child counter.
+% \begin{macrocode}
+\newcounter{DTLgidxChildCount}
+% \end{macrocode}
+%\end{counter}
+%\begin{macro}{\theHDTLgidxChildCount}
+% Reduce duplicate identifier warnings if \sty{hyperref} in use.
+% \begin{macrocode}
+\def\theHDTLgidxChildCount{\Label.\arabic{DTLgidxChildCount}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLgidxChildCountLabel}
+% Label for child counter.
+% \begin{macrocode}
+\newcommand*{\DTLgidxChildCountLabel}{\theDTLgidxChildCount) }
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLgidxChildStyle}
+% Should the child name be displayed? (Default: show name.)
+% If the name shouldn't be displayed, replace with a number.
+% \begin{macrocode}
+\newcommand*{\DTLgidxChildStyle}[1]{#1}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\datagidx@setchildstyle}
+% \begin{macrocode}
+\newcommand*{\datagidx@setchildstyle}[1]{%
+ \ifcase#1\relax
+ \renewcommand*{\DTLgidxChildStyle}[1]{##1}%
+ \or
+ \renewcommand*{\DTLgidxChildStyle}[1]{%
+ \DTLgidxChildCountLabel
+ }%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\datagidx@foreachchild}
+% Iterate through each child label
+% \begin{macrocode}
+\newcommand{\datagidx@foreachchild}{%
+ \datagidx@sort@foreachchild
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\datagidx@setchildsort}
+% \begin{macrocode}
+\newcommand*{\datagidx@setchildsort}[1]{%
+ \ifcase#1\relax
+ \renewcommand*{\datagidx@foreachchild}{%
+ \datagidx@sort@foreachchild
+ }%
+ \or
+ \renewcommand*{\datagidx@foreachchild}{%
+ \datagidx@unsort@foreachchild
+ }%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLgidxPostName}
+% What to put after the name. (Defaults to space.)
+% \begin{macrocode}
+\newcommand*{\DTLgidxPostName}{ }
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLgidxPostChildName}
+% What to put after the child name.
+% \begin{macrocode}
+\newcommand*{\DTLgidxPostChildName}{\DTLgidxPostName}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLgidxNameCase}
+% Should the name have a case change in the index/glossary?
+% (Default: no change.)
+% \begin{macrocode}
+\newcommand*{\DTLgidxNameCase}[1]{#1}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\datagidx@setnamecase}
+% \begin{macrocode}
+\newcommand*{\datagidx@setnamecase}[1]{%
+ \ifcase#1\relax
+ \renewcommand*{\DTLgidxNameCase}[1]{##1}%
+ \or
+ \let\DTLgidxNameCase\MakeTextUppercase
+ \or
+ \let\DTLgidxNameCase\MakeTextLowercase
+ \or
+ \let\DTLgidxNameCase\xmakefirstuc
+ \or
+ \let\DTLgidxNameCase\xcapitalisewords
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLgidxNameFont}
+% The font to use for the name in the index/glossary.
+% (Default: normal font.)
+% \begin{macrocode}
+\newcommand*{\DTLgidxNameFont}[1]{\textnormal{#1}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLgidxPostDescription}
+% What to put after the description. (Defaults to nothing.)
+% \begin{macrocode}
+\newcommand*{\DTLgidxPostDescription}{}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\datagidx@setpostdesc}
+% \begin{macrocode}
+\newcommand*{\datagidx@setpostdesc}[1]{%
+ \ifcase#1\relax
+ \renewcommand*{\DTLgidxPostDescription}{}%
+ \or
+ \renewcommand*{\DTLgidxPostDescription}{.}%
+ \fi
+ }
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLgidxPreLocation}
+% What to put before the location list. (Defaults to en-space.)
+% \begin{macrocode}
+\newcommand*{\DTLgidxPreLocation}{\enspace}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\datagidx@setprelocation}
+% \begin{macrocode}
+\newcommand*{\datagidx@setprelocation}[1]{%
+ \ifcase#1\relax
+ \renewcommand*{\DTLgidxPreLocation}{}%
+ \or
+ \renewcommand*{\DTLgidxPreLocation}{\enspace}%
+ \or
+ \renewcommand*{\DTLgidxPreLocation}{ }%
+ \or
+ \renewcommand*{\DTLgidxPreLocation}{\dotfill}%
+ \or
+ \renewcommand*{\DTLgidxPreLocation}{\hfill}%
+ \fi
+ }
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLgidxLocation}
+% How to display the location. (Defaults to show the location list.)
+% \begin{macrocode}
+\newcommand*{\DTLgidxLocation}{\dtldolocationlist}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\datagidx@setlocation}
+% Should the location list be displayed?
+% \begin{macrocode}
+\newcommand*{\datagidx@setlocation}[1]{%
+ \ifcase#1\relax
+ \renewcommand*{\DTLgidxLocation}{}%
+ \or
+ \renewcommand*{\DTLgidxLocation}{\dtldolocationlist}%
+ \or
+ \renewcommand*{\DTLgidxLocation}{\dtldofirstlocation}%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLgidxSee}
+% How to display the cross-reference list.
+% \begin{macrocode}
+\newcommand*{\DTLgidxSee}{%
+ \DTLifnull{\See}%
+ {}%
+ {%
+ \DTLgidxPreLocation
+ \DTLgidxFormatSee{\seename}{\See}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLgidxSeeAlso}
+% How to display the ``see also'' list.
+% \begin{macrocode}
+\newcommand*{\DTLgidxSeeAlso}{%
+ \DTLifnull{\SeeAlso}%
+ {}%
+ {%
+ \DTLgidxFormatSeeAlso{\seealsoname}{\SeeAlso}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLgidxChildrenSeeAlso}
+% Display the children and the see also attributes.
+% \begin{macrocode}
+\newcommand*{\DTLgidxChildrenSeeAlso}{%
+ \DTLgidxChildren
+ \DTLgidxSeeAlso
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\datagidx@setsee}
+% How should cross-references appear?
+% \begin{macrocode}
+\newcommand*{\datagidx@setsee}[1]{%
+ \ifcase#1\relax
+ \renewcommand*{\DTLgidxSee}{%
+ \DTLifnull{\See}{}%
+ {%
+ , \DTLgidxFormatSee{\seename}{\See}%
+ }%
+ }%
+ \or
+ \renewcommand*{\DTLgidxSee}{%
+ \DTLifnull{\See}{}
+ {%
+ \space(\DTLgidxFormatSee{\seename}{\See})%
+ }%
+ }%
+ \or
+ \renewcommand*{\DTLgidxSee}{%
+ \DTLifnull{\See}{}%
+ {%
+ . \DTLgidxFormatSee{\xmakefirstuc{\seename}}{\See}%
+ }%
+ }%
+ \or
+ \renewcommand*{\DTLgidxSee}{%
+ \DTLifnull{\See}{}
+ {%
+ \space\DTLgidxFormatSee{\seename}{\See}%
+ }%
+ }%
+ \or
+ \renewcommand*{\DTLgidxSee}{%
+ \DTLifnull{\See}{}
+ {%
+ \DTLgidxFormatSee{\seename}{\See}%
+ }%
+ }%
+ \or
+ \renewcommand*{\DTLgidxSee}{%
+ \DTLifnull{\See}{}
+ {%
+ ; \DTLgidxFormatSee{\seename}{\See}%
+ }%
+ }%
+ \or
+ \renewcommand*{\DTLgidxSee}{%
+ \DTLifnull{\See}{}
+ {%
+ \DTLgidxPreLocation\DTLgidxFormatSee{\seename}{\See}%
+ }%
+ }%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLgidxSymDescSep}
+% Separator character between symbol and description if both are
+% present.
+% \begin{macrocode}
+\newcommand*{\DTLgidxSymDescSep}{\space}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\datagidxsymbolwidth}
+% Space to allocate for the symbol. If zero or negative, symbol just
+% occupies its natural space.
+% \begin{macrocode}
+\newlength\datagidxsymbolwidth
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\datagidxlocationwidth}
+% Space to allocate for the location list. If zero or negative, the
+% list just occupies its natural space.
+% \begin{macrocode}
+\newlength\datagidxlocationwidth
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLgidxFormatDesc}
+% How to format the description.
+% \begin{macrocode}
+\newcommand{\DTLgidxFormatDesc}[1]{#1}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLgidxSymbolDescription}
+% How to format the symbol and description fields.
+% \begin{macrocode}
+\newcommand*{\DTLgidxSymbolDescription}{%
+ \DTLgidxSymbolDescLeft
+ \DTLgidxSymbolDescRight
+}
+\newcommand*{\DTLgidxSymbolDescLeft}{%
+ \ifdefempty{\Symbol}{}{(\Symbol)\DTLgidxSymDescSep}%
+}
+\newcommand*{\DTLgidxSymbolDescRight}{%
+ \ifdefempty{\Description}{}%
+ {%
+ \DTLgidxFormatDesc{\Description}\DTLgidxPostDescription
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\if@datagidxsymbolleft}
+% Identifies whether the symbol has been set to left or right.
+% \begin{macrocode}
+\newif\if@datagidxsymbolleft
+\@datagidxsymbollefttrue
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\datagidx@formatsymdesc}
+% \begin{macrocode}
+\newcommand*{\datagidx@formatsymdesc}[1]{%
+ \ifcase#1\relax
+% \end{macrocode}
+% Only symbol
+% \begin{macrocode}
+ \renewcommand*{\DTLgidxSymbolDescLeft}{%
+ \ifdefempty{\Symbol}{}{\Symbol}%
+ }%
+ \renewcommand*{\DTLgidxSymbolDescRight}{}%
+ \@datagidxsymbollefttrue
+ \or
+% \end{macrocode}
+% Only description
+% \begin{macrocode}
+ \renewcommand*{\DTLgidxSymbolDescLeft}{%
+ \ifdefempty{\Description}{}%
+ {%
+ \DTLgidxFormatDesc{\Description}\DTLgidxPostDescription
+ }%
+ }%
+ \renewcommand*{\DTLgidxSymbolDescRight}{}%
+ \@datagidxsymbolleftfalse
+ \or
+% \end{macrocode}
+% (symbol) description
+% \begin{macrocode}
+ \renewcommand*{\DTLgidxSymbolDescLeft}{%
+ \ifdefempty{\Symbol}{}{(\Symbol)\DTLgidxSymDescSep}%
+ }%
+ \renewcommand*{\DTLgidxSymbolDescRight}{%
+ \ifdefempty{\Description}{}%
+ {%
+ \DTLgidxFormatDesc{\Description}\DTLgidxPostDescription
+ }%
+ }%
+ \@datagidxsymbollefttrue
+ \or
+% \end{macrocode}
+% description (symbol)
+% \begin{macrocode}
+ \renewcommand*{\DTLgidxSymbolDescLeft}{%
+ \ifdefempty{\Description}{}%
+ {%
+ \DTLgidxFormatDesc{\Description}%
+ \DTLgidxPostDescription\DTLgidxSymDescSep
+ }%
+ }%
+ \renewcommand*{\DTLgidxSymbolDescRight}{%
+ \ifdefempty{\Symbol}{}{(\Symbol)}%
+ }%
+ \@datagidxsymbolleftfalse
+ \or
+% \end{macrocode}
+% symbol description
+% \begin{macrocode}
+ \renewcommand*{\DTLgidxSymbolDescLeft}{%
+ \ifdefempty{\Symbol}{}{\Symbol\DTLgidxSymDescSep}%
+ }%
+ \renewcommand*{\DTLgidxSymbolDescRight}{%
+ \ifdefempty{\Description}{}%
+ {%
+ \DTLgidxFormatDesc{\Description}%
+ \DTLgidxPostDescription
+ }%
+ }%
+ \@datagidxsymbollefttrue
+ \or
+% \end{macrocode}
+% description symbol
+% \begin{macrocode}
+ \renewcommand*{\DTLgidxSymbolDescLeft}{%
+ \ifdefempty{\Description}{}%
+ {%
+ \DTLgidxFormatDesc{\Description}%
+ \DTLgidxPostDescription\DTLgidxSymDescSep
+ }%
+ }%
+ \renewcommand*{\DTLgidxSymbolDescRight}{%
+ \ifdefempty{\Symbol}{}{\Symbol}%
+ }%
+ \@datagidxsymbolleftfalse
+ \fi
+ }
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLgidxSetCompositor}
+%\begin{definition}
+%\cs{DTLgidxSetCompositor}\marg{symbol}
+%\end{definition}
+%Set the location compositor.
+% \begin{macrocode}
+\newcommand*{\DTLgidxSetCompositor}[1]{%
+ \undef\datagidx@docomplist
+ \DeclareListParser{\datagidx@docomplist}{#1}%
+ \def\datagidx@compositor{#1}%
+}
+% \end{macrocode}
+%\end{macro}
+%Set the default compositor to \texttt{.} (full stop).
+% \begin{macrocode}
+\DTLgidxSetCompositor{.}
+% \end{macrocode}
+%
+% Sorting can take a long time (especially with large databases) but
+% two \LaTeX\ runs are usually required to get the index or glossary
+% up-to-date, so we usually don't need to worry about sorting on the
+% first run (unless the order in some way affects the document,
+% e.g.\ the group headings are to appear in the table of contents).
+% It may also be that some modifications are done to the document
+% that don't require a re-sort. The optimize setting tries to
+% minimize the amount of sorting done to help speed up document
+% compilation.
+%
+% There are to optimization levels: low and high. The low level
+% optimization just sorts every other \LaTeX\ run. This is done by
+% writing to the aux file to determine whether or not the sort
+% should be done next run. This is a cheap and easy hack that won't
+% work if sorting makes the document out-of-date (for example, if
+% the sorted index or glossary affects the table of contents by,
+% say, making the group headings a sectional unit).
+%
+% The high level optimization is more complicated and involves
+% writing the sorted database to an external file and reading it in
+% on the next run. This requires checks to see if the location lists
+% have changed, in which case a new sort may be required.
+%
+%\begin{important}
+% The optimization function is only implemented when the sorting is
+% specified via the sort key. Any explicit sorting done by the user
+% via commands such as \ics{dltsort} are not effected by the
+% optimization setting.
+%\end{important}
+%
+%\begin{macro}{\datagidx@do@sort}
+% Indicate what to do when it's time to sort the index/glossary.
+% This defaults to un-optimised setting to avoid confusing users who
+% don't like to read the manual.
+% \begin{macrocode}
+\newcommand*{\datagidx@do@sort}{\datagidx@sort}
+% \end{macrocode}
+%\end{macro}
+%
+% First deal with the low-level optimization as it's easier to
+% implement.
+%
+%\begin{macro}{\datagidx@optimize@sort}
+% The code to perform when the low optimize setting is on.
+% If the command \ics{datagidx@do@optimize@sort} has been defined,
+% do the sort. If it hasn't been defined, don't sort. If a sort
+% isn't performed, the command definition is written to the aux
+% file. If a sort is performed, the command definition isn't written
+% to the aux file. This will do the sort every other run.
+% \begin{macrocode}
+\newcommand*{\datagidx@optimize@sort}{%
+% \end{macrocode}
+% First, has \cs{datagidx@do@optimize@sort} been defined?
+% \begin{macrocode}
+ \ifdef\datagidx@do@optimize@sort
+ {%
+% \end{macrocode}
+% It has been defined so go ahead and do the sort.
+% \begin{macrocode}
+ \datagidx@sort
+ }%
+ {%
+% \end{macrocode}
+% It hasn't been defined so don't sort. Write the command definition
+% into the aux file for the next run.
+% \begin{macrocode}
+ \protected@write\@auxout{}{%
+ \string\gdef\string\datagidx@do@optimize@sort{}%
+ }%
+% \end{macrocode}
+% Let the user know they need to recompile the document.
+% \begin{macrocode}
+ \global\let\@datagidx@dorerun@warn@sort\@data@rerun@warn@sort
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\if@datagidx@warn}
+% Provide a switch to allow warnings to be suppressed.
+% \begin{macrocode}
+\newif\if@datagidx@warn
+\@datagidx@warntrue
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@datagidx@dorerun@warn}
+% \begin{macrocode}
+\newcommand*\@datagidx@dorerun@warn{}
+\AtEndDocument{\if@datagidx@warn\@datagidx@dorerun@warn\fi}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@datagidx@dorerun@warn@sort}
+% \begin{macrocode}
+\newcommand*\@datagidx@dorerun@warn@sort{}
+\AtEndDocument{\if@datagidx@warn\@datagidx@dorerun@warn@sort\fi}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@datagidx@rerun@warn@sort}
+% Warning issued when a rerun is required to sort the index or
+% glossary.
+% \begin{macrocode}
+\newcommand*\@data@rerun@warn@sort{%
+ \PackageWarningNoLine{datagidx}{Rerun required to sort the
+ index/glossary databases}%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@datagidx@rerun@warn}
+% Warning issued when a rerun is required to update the location
+% lists.
+% \begin{macrocode}
+\newcommand*\@data@rerun@warn{%
+ \PackageWarningNoLine{datagidx}{Rerun required to ensure the
+ index/glossary location lists are up-to-date}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%
+%The high optimize setting is more complicated.
+% This involves writing each database to an external file (named
+% \cs{jobname}-\meta{db label}.gidx). The sort is only performed if
+% new terms are added or used.
+%
+%\begin{macro}{\datagidx@do@highopt@optimize}
+% \begin{macrocode}
+\newcommand*{\datagidx@do@highopt@optimize}{%
+ \renewcommand*{\datagidx@do@sort}{%
+% \end{macrocode}
+% Only sort if database has changed.
+% \begin{macrocode}
+ \ifcsdef{datagidx@do@highopt@sort@\DTLgidxCurrentdb}%
+ {%
+ \csuse{datagidx@do@highopt@sort@\DTLgidxCurrentdb}%
+ }%
+ {%
+% \end{macrocode}
+% Do nothing
+% \begin{macrocode}
+ }%
+% \end{macrocode}
+% Save the database to file.
+% \begin{macrocode}
+ \bgroup
+% \end{macrocode}
+% Hook into write macro to clear certain fields and protect commands
+% like \ics{DTLgidxName}.
+% \begin{macrocode}
+ \def\dtl@saverawdbhook{%
+ \let\db@col@id@w\@datagidx@db@col@id@w
+ \def\DTLgidxName{\string\DTLgidxName\space}%
+ \def\DTLgidxMac{\string\DTLgidxMac\space}%
+ \def\DTLgidxRank{\string\DTLgidxRank\space}%
+ \def\DTLgidxParen{\string\DTLgidxParen\space}%
+ \def\DTLgidxParticle{\string\DTLgidxParticle\space}%
+ \def\DTLgidxOffice{\string\DTLgidxOffice\space}%
+ \def\DTLgidxSaint{\string\DTLgidxSaint\space}%
+ \def\DTLgidxPlace{\string\DTLgidxPlace\space}%
+ \def\DTLgidxIgnore{\string\DTLgidxIgnore\space}%
+ \def\DTLgidxNameNum{\string\DTLgidxNameNum\space}%
+ \def\DTLgidxSubject{\string\DTLgidxSubject\space}%
+ }%
+ \DTLsaverawdb{\DTLgidxCurrentdb}{\datagidxhighoptfilename\DTLgidxCurrentdb}%
+ \egroup
+ }%
+% \end{macrocode}
+% Change the behaviour of \cs{newgidx}
+% \begin{macrocode}
+ \def\newgidx{\datagidx@highopt@newgidx}%
+% \end{macrocode}
+% Change the behaviour of \cs{newterm}
+% \begin{macrocode}
+ \def\newterm{\datagidx@highopt@newterm}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@datagidx@db@col@id@w}
+% A bit of trickery is need to clear the Used and Location fields when
+% writing the raw database to file.
+% \begin{macrocode}
+\def\@datagidx@db@col@id@w#1\db@col@id@end@\db@col@elt@w#2\db@col@elt@end@\db@col@id@w#3\db@col@id@end@{%
+ \expandafter\@gobble\string\%^^J
+ \string\db@col@id@w\space #1%
+ \expandafter\@gobble\string\%^^J
+ \string\db@col@id@end@\space
+ \expandafter\@gobble\string\%^^J
+ \string\db@col@elt@w\space
+ \expandafter\ifnum\csname dtl@ci@\DTLgidxCurrentdb @Used\endcsname=#1\space
+ 0%
+ \else
+ \expandafter\ifnum\csname dtl@ci@\DTLgidxCurrentdb @Location\endcsname=#1\space
+ \else
+ \expandafter\ifnum\csname dtl@ci@\DTLgidxCurrentdb @CurrentLocation\endcsname=#1\space
+ \else
+% \end{macrocode}
+% We also want to prevent the first character of the sort field from
+% being expanded to help get the group correct (in case the user
+% wants to sort on, say, the tilde character).
+% \begin{macrocode}
+ \expandafter\ifnum\csname dtl@ci@\DTLgidxCurrentdb @Sort\endcsname=#1\space
+ \protect#2%
+ \else
+ #2%
+ \fi
+ \fi
+ \fi
+ \fi
+ \expandafter\@gobble\string\%^^J
+ \string\db@col@elt@end@\space
+ \expandafter\@gobble\string\%^^J
+ \string\db@col@id@w\space #3%
+ \expandafter\@gobble\string\%^^J
+ \string\db@col@id@end@\space
+}
+% \end{macrocode}
+%\end{macro}
+%
+% With the `highopt optimize' setting, whenever a location is written to the aux
+% file, if no location has been defined the database needs sorting.
+%
+%\begin{macro}{\datagidx@do@highopt@update}
+% Default does nothing. (Argument is the entry's label.)
+% \begin{macrocode}
+\newcommand*{\datagidx@do@highopt@update}[1]{}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\datagidxhighoptfilename}
+% Expands to the name of the filename associated with the database
+% identified by the argument for the `highopt' setting.
+% \begin{macrocode}
+\newcommand*{\datagidxhighoptfilename}[1]{\jobname-#1.gidx}
+% \end{macrocode}
+%\end{macro}
+%
+%\section{Package Options}
+%
+%\begin{option}{optimize}
+% A boolean option indicating whether or not to optimize the sort.
+% This is only available as a global option. If you want to optimize
+% some glossaries but not others, switch on the optimize function
+% and clear the sort key for the relevant glossaries and manually
+% sort using \ics{dtlsort} before the glossary is displayed.
+% \begin{macrocode}
+\define@choicekey{datagidx.sty}{optimize}[\val\nr]%
+ {off,low,high}[high]%
+ {%
+ \ifcase\nr\relax
+ \renewcommand*{\datagidx@do@sort}{\datagidx@sort}
+ \or
+ \renewcommand*{\datagidx@do@sort}{\datagidx@optimize@sort}
+ \or
+ \datagidx@do@highopt@optimize
+ \fi
+ }
+% \end{macrocode}
+%\end{option}
+%
+%\begin{option}{nowarn}
+% A boolean option to suppress warnings.
+%\changes{2.15}{2013-07-10}{new}
+% \begin{macrocode}
+\define@choicekey{datagidx.sty}{nowarn}[\val\nr]{true,false}[true]%
+{%
+ \ifcase\nr\relax
+ \@datagidx@warnfalse
+ \or
+ \@datagidx@warntrue
+ \fi
+}
+% \end{macrocode}
+%\end{option}
+%
+%\begin{option}{utf8}
+%\changes{2.28}{2017-11-10}{new}
+% \begin{macrocode}
+\define@choicekey{datatool.sty}{utf8}{true,false}[true]{%
+ \setbool{@dtl@utf8}{#1}%
+}
+% \end{macrocode}
+%\end{option}
+%
+% These options govern the general layout of the glossary/index.
+%\begin{option}{columns}
+% The number of columns used by \env{multicols} (or
+% \env{multicols*}). If only one column is specified,
+% \env{multicols} (or \env{multicols*}) isn't used.
+% \begin{macrocode}
+\define@key{datagidx.sty}{columns}%
+{%
+ \DTLgidxSetColumns{#1}%
+}
+% \end{macrocode}
+%\end{option}
+%\begin{option}{child}
+% Indicates whether or not to show the name in child entries.
+% \begin{macrocode}
+\define@choicekey{datagidx.sty}{child}[\val\nr]%
+ {named,noname}%
+ {%
+ \datagidx@setchildstyle\nr
+ }
+% \end{macrocode}
+%\end{option}
+%\begin{option}{namecase}
+% Options for name case.
+% \begin{macrocode}
+\define@choicekey{datagidx.sty}{namecase}[\val\nr]%
+ {nochange,uc,lc,firstuc,capitalise}%
+ {%
+ \datagidx@setnamecase\nr
+ }
+% \end{macrocode}
+%\end{option}
+%
+%\begin{option}{namefont}
+% Option to set the name font.
+% \begin{macrocode}
+\define@key{datagidx.sty}{namefont}%
+{%
+ \renewcommand*{\DTLgidxNameFont}[1]{{#1{##1}}}%
+}
+% \end{macrocode}
+%\end{option}
+%
+%\begin{option}{postname}
+% What to put after the name.
+% \begin{macrocode}
+\define@key{datagidx.sty}{postname}
+{%
+ \renewcommand*{\DTLgidxPostName}{#1}%
+}
+% \end{macrocode}
+%\end{option}
+%
+%\begin{option}{postdesc}
+% what to put after the description.
+% \begin{macrocode}
+\define@choicekey{datagidx.sty}{postdesc}[\val\nr]%
+ {none,dot}%
+ {%
+ \datagidx@setpostdesc\nr
+ }
+% \end{macrocode}
+%\end{option}
+%
+%\begin{option}{prelocation}
+% What to put before the location list.
+% \begin{macrocode}
+\define@choicekey{datagidx.sty}{prelocation}[\val\nr]%
+ {none,enspace,space,dotfill,hfill}%
+ {%
+ \datagidx@setprelocation\nr
+ }
+% \end{macrocode}
+%\end{option}
+%
+%\begin{option}{location}
+% How to display the location list.
+% \begin{macrocode}
+\define@choicekey{datagidx.sty}{location}[\val\nr]%
+ {hide,list,first}%
+ {\datagidx@setlocation\nr}
+% \end{macrocode}
+%\end{option}
+%
+%\begin{option}{see}
+% How to display the cross-reference list.
+% \begin{macrocode}
+\define@choicekey{datagidx.sty}{see}[\val\nr]%
+ {comma,brackets,dot,space,nosep,semicolon,location}%
+ {\datagidx@setsee\nr}
+% \end{macrocode}
+%\end{option}
+%
+%\begin{option}{symbol}
+% How to format the symbol in relation to the description.
+% \begin{macrocode}
+\define@choicekey{datagidx.sty}{symboldesc}[\val\nr]%
+ {symbol,desc,(symbol) desc,desc (symbol),symbol desc,desc symbol}%
+ {\datagidx@formatsymdesc\nr}
+% \end{macrocode}
+%\end{option}
+%
+%\begin{option}{compositor}
+% Location compositor.
+% \begin{macrocode}
+\define@key{datagidx.sty}{compositor}%
+{%
+ \DTLgidxSetCompositor{#1}%
+}%
+% \end{macrocode}
+%\end{option}
+%
+%\begin{option}{final}
+% \begin{macrocode}
+\DeclareOptionX{final}{%
+ \let\datagidxshowifdraft\@gobble
+}
+% \end{macrocode}
+% Set as default:
+% \begin{macrocode}
+\let\datagidxshowifdraft\@gobble
+% \end{macrocode}
+%\end{option}
+%
+%\begin{option}{draft}
+% \begin{macrocode}
+\DeclareOptionX{draft}{%
+ \let\datagidxshowifdraft\@firstofone
+}
+% \end{macrocode}
+%\end{option}
+%
+%\begin{option}{verbose}
+% \begin{macrocode}
+\define@choicekey{datagidx.sty}{verbose}[\val\nr]%
+ {true,false}[true]%
+ {%
+ \csuse{dtlverbose\val}%
+ }
+% \end{macrocode}
+%\end{option}
+%
+% Process package options:
+% \begin{macrocode}
+\ProcessOptionsX
+% \end{macrocode}
+%
+% Database to keep track of all the defined terms.
+% \begin{macrocode}
+\DTLnewdb{datagidx}
+% \end{macrocode}
+%
+%\section{Glossary/Index Formatting}
+%\begin{macro}{\seename}
+% \begin{macrocode}
+\providecommand*{\seename}{see}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\seealsoname}
+% \begin{macrocode}
+\providecommand*{\seealsoname}{see also}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLgidxSeeTagFont}
+% \begin{macrocode}
+\newcommand*{\DTLgidxSeeTagFont}[1]{\emph{#1}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLgidxFormatSee}
+%\begin{definition}
+%\cs{DTLgidxFormatSee}\marg{tag}\marg{label list}
+%\end{definition}
+% \begin{macrocode}
+\newcommand*{\DTLgidxFormatSee}[2]{%
+ \DTLgidxSeeTagFont{#1} \DTLgidxSeeList{#2}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLgidxFormatSeeAlso}
+%\begin{definition}
+%\cs{DTLgidxFormatSeeAlso}\marg{tag}\marg{label list}
+%\end{definition}
+% \begin{macrocode}
+\newcommand*{\DTLgidxFormatSeeAlso}[2]{%
+ \datagidxdoseealso
+ {%
+ \DTLgidxSeeTagFont{#1} \DTLgidxSeeList{#2}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\datagidxdoseealso}
+% \begin{macrocode}
+\newcommand*{\datagidxdoseealso}[1]{%
+ \datagidxseealsostart
+ #1%
+ \datagidxseealsoend
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLgidxSeeList}
+%\begin{definition}
+%\cs{DTLgidxSeeList}\marg{label list}
+%\end{definition}
+% \begin{macrocode}
+\newcommand*{\DTLgidxSeeList}[1]{%
+ \def\datagidx@sep{}%
+ \@for\dtl@thislabel:=#1\do
+ {%
+ \ifx\@xfor@nextelement\@nnil
+% \end{macrocode}
+% Last iteration.
+% \begin{macrocode}
+ \ifdefempty{\datagidx@sep}%
+ {%
+% \end{macrocode}
+% Only one element in the list.
+% \begin{macrocode}
+ }%
+ {%
+% \end{macrocode}
+% Not the only element in the list.
+% \begin{macrocode}
+ \DTLidxSeeLastSep
+ }%
+ \else
+% \end{macrocode}
+% Not last iteration
+% \begin{macrocode}
+ \datagidx@sep
+ \let\datagidx@sep\DTLidxSeeSep
+ \fi
+ \DTLidxFormatSeeItem{\dtl@thislabel}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLidxFormatSeeItem}
+%\begin{definition}
+%\cs{DTLidxFormatSeeItem}\marg{label}
+%\end{definition}
+% \begin{macrocode}
+\newcommand*{\DTLidxFormatSeeItem}[1]{%
+ \DTLgidxFetchEntry{\datagidx@value}{#1}{Name}%
+ \datagidxlink{#1}%
+ {%
+ \datagidx@value
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLidxSeeSep}
+% Separator in cross-reference list.
+% \begin{macrocode}
+\newcommand*{\DTLidxSeeSep}{, }
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLidxSeeLastSep}
+% Final separator in cross-reference list.
+% \begin{macrocode}
+\newcommand*{\DTLidxSeeLastSep}{ \& }
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLgidxDoSeeOrLocation}
+% You should have both a ``see'' list and a location list. This
+% checks if \cs{See} is null. If it isn't null, it does the ``see''
+% part, otherwise it deals with the location list.
+% \begin{macrocode}
+\newcommand*{\DTLgidxDoSeeOrLocation}{%
+ \DTLifnull\See
+ {%
+% \end{macrocode}
+% \cs{See} is null. Do we have a location?
+% \begin{macrocode}
+ \ifdefempty\Location
+ {%
+ }%
+ {%
+ \DTLgidxPreLocation
+ \DTLgidxLocation
+ }%
+ }%
+ {%
+% \end{macrocode}
+% \cs{See} is not null, so do the cross-reference.
+% \begin{macrocode}
+ \DTLgidxSee
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\datagidx@sortchildren}
+% The list of child labels needs to be sorted so that the child list
+% follows the same ordering as the database.
+% \begin{macrocode}
+\newcommand*{\datagidx@sortchildren}{%
+ \def\datagidx@sortedlist{}%
+ \@for\Label:=\Children\do
+ {%
+ \edef\do@getrow{%
+ \noexpand\dtlgetrowforvalue
+ {\DTLgidxCurrentdb}%
+ {\dtlcolumnindex{\DTLgidxCurrentdb}{Label}}%
+ {\Label}%
+ }%
+ \do@getrow
+% \end{macrocode}
+% Row index is stored in \cs{dtlrownum}. Is the sorted list empty?
+% \begin{macrocode}
+ \ifdefempty\datagidx@sortedlist
+ {%
+% \end{macrocode}
+% Yes, it's empty.
+% \begin{macrocode}
+ \edef\datagidx@newsortedlist{{\number\dtlrownum}{\Label}}%
+ }%
+ {%
+% \end{macrocode}
+% No, it's not empty. Need to insert into list.
+% \begin{macrocode}
+ \def\datagidx@newsortedlist{}%
+ \@for\@datagidx@thisval:=\datagidx@sortedlist\do
+ {%
+% \end{macrocode}
+% Get the index:
+% \begin{macrocode}
+ \edef\datagidx@thisidx{\expandafter\@firstoftwo\@datagidx@thisval}%
+% \end{macrocode}
+% Is index greater than \cs{dtlrownum}?
+% \begin{macrocode}
+ \ifnum\datagidx@thisidx>\dtlrownum\relax
+% \end{macrocode}
+% Yes, it is. So insert here.
+% \begin{macrocode}
+ \ifdefempty\datagidx@newsortedlist
+ {%
+ \eappto\datagidx@newsortedlist
+ {%
+ {\number\dtlrownum}{\Label},\@datagidx@thisval
+ }%
+ }%
+ {%
+ \eappto\datagidx@newsortedlist
+ {%
+ ,{\number\dtlrownum}{\Label},\@datagidx@thisval
+ }%
+ }%
+% \end{macrocode}
+% Break out of inner loop.
+% \begin{macrocode}
+ \@endfortrue
+ \else
+ \ifdefempty\datagidx@newsortedlist
+ {%
+ \edef\datagidx@newsortedlist{%
+ \@datagidx@thisval
+ }%
+ }%
+ {%
+ \eappto\datagidx@newsortedlist
+ {%
+ ,\@datagidx@thisval
+ }%
+ }%
+ \fi
+ }%
+% \end{macrocode}
+% Was the loop ended prematurely?
+% \begin{macrocode}
+ \if@endfor
+% \end{macrocode}
+% If loop was ended on the last iteration, \cs{@forremainder} will
+% be empty and there's nothing left to do.
+% \begin{macrocode}
+ \ifdefempty\@forremainder
+ {%
+ }%
+ {%
+% \end{macrocode}
+% Loop prematurely ended, so append remainder to list.
+ \eappto\datagidx@newsortedlist{,\@forremainder}%
+% \begin{macrocode}
+ }%
+ \else
+% \end{macrocode}
+% Loop wasn't prematurely terminated, so new value hasn't been
+% added. Add now.
+% \begin{macrocode}
+ \ifdefempty\datagidx@newsortedlist
+ {%
+ \edef\datagidx@newsortedlist{{\number\dtlrownum}{\Label}}%
+ }%
+ {%
+ \eappto\datagidx@newsortedlist{,{\number\dtlrownum}{\Label}}%
+ }%
+ \fi
+ }%
+% \end{macrocode}
+% Update.
+% \begin{macrocode}
+ \let\datagidx@sortedlist\datagidx@newsortedlist
+% \end{macrocode}
+% Don't break out of outer loop.
+% \begin{macrocode}
+ \@endforfalse
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\datagidx@sort@foreachchild}
+% Sorted iteration through all the child labels.
+% \begin{macrocode}
+\newcommand{\datagidx@sort@foreachchild}[1]{%
+ \datagidx@sortchildren
+% \end{macrocode}
+% Sorted list stored in \cs{datagidx@sortedlist}
+% \begin{macrocode}
+ \@for\@datagidx@thisval:=\datagidx@sortedlist\do
+ {%
+ \edef\Label{\expandafter\@secondoftwo\@datagidx@thisval}%
+ #1%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\datagidx@unsort@foreachchild}
+% Unsorted iteration through all the child labels.
+% \begin{macrocode}
+\newcommand{\datagidx@unsort@foreachchild}[1]{%
+ \@for\Label:=\Children\do
+ {%
+ #1%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%
+%\begin{macro}{\DTLgidxChildren}
+% How to display the children
+% \begin{macrocode}
+\newcommand*{\DTLgidxChildren}{%
+ \bgroup
+ \DTLifnull\Children
+ {}%
+ {%
+ \advance\datagidx@level by 1\relax
+ \datagidxchildstart
+ \let\Parent\Label
+ \datagidx@foreachchild
+ {%
+ \edef\do@getrow{%
+ \noexpand\dtlgetrowforvalue
+ {\DTLgidxCurrentdb}%
+ {\dtlcolumnindex{\DTLgidxCurrentdb}{Label}}%
+ {\Label}%
+ }%
+ \do@getrow
+ \dtlgetentryfromcurrentrow
+ {\Location}%
+ {\dtlcolumnindex{\DTLgidxCurrentdb}{Location}}%
+ \dtlgetentryfromcurrentrow
+ {\See}%
+ {\dtlcolumnindex{\DTLgidxCurrentdb}{See}}%
+ \dtlgetentryfromcurrentrow
+ {\SeeAlso}%
+ {\dtlcolumnindex{\DTLgidxCurrentdb}{SeeAlso}}%
+ \DTLifnull\Location
+ {%
+ \DTLifnull\See
+ {%
+ \DTLifnull\SeeAlso
+ {}%
+ {%
+ \datagidx@displaychild
+ }%
+ }%
+ {%
+ \datagidx@displaychild
+ }%
+ }%
+ {%
+ \datagidx@displaychild
+ }%
+ }%
+ \datagidxchildend
+ }%
+ \egroup
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\datagidxgetchildfields}
+% Get the child fields from the current row.
+% \begin{macrocode}
+\newcommand*{\datagidxgetchildfields}{%
+ \dtlgetentryfromcurrentrow
+ {\Name}%
+ {\dtlcolumnindex{\DTLgidxCurrentdb}{Name}}%
+ \dtlgetentryfromcurrentrow
+ {\Description}%
+ {\dtlcolumnindex{\DTLgidxCurrentdb}{Description}}%
+ \dtlgetentryfromcurrentrow
+ {\Symbol}%
+ {\dtlcolumnindex{\DTLgidxCurrentdb}{Symbol}}%
+ \dtlgetentryfromcurrentrow
+ {\Long}%
+ {\dtlcolumnindex{\DTLgidxCurrentdb}{Long}}%
+ \dtlgetentryfromcurrentrow
+ {\Short}%
+ {\dtlcolumnindex{\DTLgidxCurrentdb}{Short}}%
+ \dtlgetentryfromcurrentrow
+ {\Text}%
+ {\dtlcolumnindex{\DTLgidxCurrentdb}{Text}}%
+ \dtlgetentryfromcurrentrow
+ {\Plural}%
+ {\dtlcolumnindex{\DTLgidxCurrentdb}{Plural}}%
+ \dtlgetentryfromcurrentrow
+ {\Short}%
+ {\dtlcolumnindex{\DTLgidxCurrentdb}{Used}}%
+ \dtlgetentryfromcurrentrow
+ {\Children}%
+ {\dtlcolumnindex{\DTLgidxCurrentdb}{Child}}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\datagidx@displaychild}
+% \begin{macrocode}
+\newcommand*{\datagidx@displaychild}{%
+ \datagidxgetchildfields
+ \datagidxchilditem
+}
+% \end{macrocode}
+%\end{macro}
+%
+%
+% Define some keys for \ics{newgloss}:
+%\begin{macro}{\datagidx@heading}
+% Indicates how to format the heading in the glossary/index.
+% \begin{macrocode}
+\ifdef{\chapter}
+{%
+ \newcommand*{\datagidx@heading}{\chapter*}
+}%
+{%
+ \newcommand*{\datagidx@heading}{\section*}
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLgidxNoHeading}
+% Allow user to suppress the heading. (So to suppress the
+% heading do \texttt{heading=\cs{DTLgidxNoHeading}}).
+% \begin{macrocode}
+\let\DTLgidxNoHeading\@gobble
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\datagidx@postheading}
+% Indicates what to do immediately after the heading.
+% \begin{macrocode}
+\newcommand*{\datagidx@postheading}{}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\datagidx@multicols}
+% Should we use \env{multicols} or \env{multicols*}?
+% \begin{macrocode}
+\newcommand*{\datagidx@multicols}{multicols}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\datagidx@sort}
+% Indicates how to sort the glossary/index.
+% Defaults to word order.
+% \begin{macrocode}
+\newcommand*{\datagidx@sort}{%
+ \dtlsort{Sort,FirstId}{\DTLgidxCurrentdb}{\dtlwordindexcompare}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@idxitem}
+% Some classes, such as \cls{beamer}, don't define \cs{@idxitem} so
+% if it's not already defined, define it here.
+% \begin{macrocode}
+\providecommand{\@idxitem}{\par\hangindent 40\p@}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\datagidxstart}
+% Indicates what to do at the start of the glossary/index.
+% \begin{macrocode}
+\newcommand*{\datagidxstart}%
+{%
+ \bgroup
+ \setlength{\parindent}{0pt}%
+ \setlength{\parskip}{0pt plus 0.3pt}%
+ \let\item\@idxitem
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\datagidxend}
+% Indicates what to do at the end of the glossary/index.
+% \begin{macrocode}
+\newcommand*{\datagidxend}{\egroup}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\datagidxtarget}
+% Provide a means to add a hypertarget if \ics{hypertarget} has been
+% defined.
+% \begin{macrocode}
+\newcommand*{\@datagidxtarget}[2]{%
+ \ifdef\hypertarget
+ {%
+ \bgroup
+ \let\glsadd\@gobble
+ \settoheight\dimen@{#2}%
+ \raisebox{\dimen@}{\hypertarget{#1}{}}%
+ \egroup
+ }%
+ {%
+ }%
+ #2%
+}
+\newcommand*{\datagidxtarget}{\@datagidxtarget}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\datagidxlink}
+% Provide a means to add a link if \ics{hyperlink} has been
+% defined.
+% \begin{macrocode}
+\newcommand*{\@datagidxlink}[2]{%
+ \ifdef\hyperlink
+ {%
+ \hyperlink{#1}{#2}%
+ }%
+ {%
+ #2%
+ }%
+}
+\newcommand*{\datagidxlink}{\@datagidxlink}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLgidxEnableHyper}
+% Enable hyperlinks (if they are defined).
+% \begin{macrocode}
+\newcommand*{\DTLgidxEnableHyper}{%
+ \let\datagidxtarget\@datagidxtarget
+ \let\datagidxlink\@datagidxlink
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLgidxDisableHyper}
+% Disable hyperlinks (if they are defined).
+% \begin{macrocode}
+\newcommand*{\DTLgidxDisableHyper}{%
+ \let\datagidxtarget\@secondoftwo
+ \let\datagidxlink\@secondoftwo
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\datagidxgroupsep}
+% Indicates what to do between groups (after the previous group and
+% before the header of the next group).
+% \begin{macrocode}
+\newcommand*{\datagidxgroupsep}{}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\datagidxgroupheader}
+% Indicates what to do at the start of a group. (The current group
+% label can be accessed via \cs{datagidxcurrentgroup} and the previous
+% group label can be accessed via \cs{datagidxprevgroup}.)
+% \begin{macrocode}
+\newcommand*{\datagidxgroupheader}{}
+% \end{macrocode}
+%\end{macro}
+%
+%
+%\begin{macro}{\datagidxitem}
+% Indicates what to do at the start of each item of the glossary/index.
+% \begin{macrocode}
+\newcommand*{\datagidxitem}{}%
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\datagidxchildstart}
+% Indicates what to do at the start of the child glossary/index.
+% \begin{macrocode}
+\newcommand*{\datagidxchildstart}{}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\datagidxchildend}
+% Indicates what to do at the end of the child glossary/index.
+% \begin{macrocode}
+\newcommand*{\datagidxchildend}{}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\datagidxchilditem}
+% Indicates what to do at the start of each item of the child glossary/index.
+% \begin{macrocode}
+\newcommand*{\datagidxchilditem}{}%
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\datagidxseealsostart}
+% Indicates what to do at the start of the ``see also'' list.
+% \begin{macrocode}
+\newcommand*{\datagidxseealsostart}{}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\datagidxseealsoend}
+% Indicates what to do at the end of the ``see also'' list.
+% \begin{macrocode}
+\newcommand*{\datagidxseealsoend}{}
+% \end{macrocode}
+%\end{macro}
+%
+%
+%\begin{macro}{\datagidx@doifsymlocwidth}
+%\begin{definition}
+%\cs{datagidx@doifsymlocwidth}\marg{indent}\marg{Name code}\marg{Location code}
+%\end{definition}
+% What to do if both the symbol width and the location width have
+% been set.
+% \begin{macrocode}
+\newcommand*{\datagidx@doifsymlocwidth}[3]{%
+% \end{macrocode}
+% Calculate remaining space left for the description.
+% \begin{macrocode}
+ \setlength{\dtl@tmplength}{\linewidth}%
+ \addtolength{\dtl@tmplength}{-#1}%
+ \settowidth{\dimen@}{#2}%
+ \addtolength{\dtl@tmplength}{-\dimen@}%
+ \addtolength{\dtl@tmplength}{-\datagidxsymbolwidth}%
+ \addtolength{\dtl@tmplength}{-\datagidxlocationwidth}%
+ \settowidth{\dimen@}{\DTLgidxPreLocation}%
+ \addtolength{\dtl@tmplength}{-\dimen@}%
+ \settowidth{\dimen@}{\DTLgidxSymDescSep}%
+ \addtolength{\dtl@tmplength}{-\dimen@}%
+ \if@datagidxsymbolleft
+ \begin{minipage}[t]{\datagidxsymbolwidth}%
+ \datagidxsymalign
+ \let\DTLgidxSymDescSep\@empty
+ \DTLgidxSymbolDescLeft
+ \end{minipage}%
+ \DTLgidxSymDescSep
+ \begin{minipage}[t]{\dtl@tmplength}%
+ \let\DTLgidxSymDescSep\@empty
+ \DTLgidxSymbolDescRight
+ \end{minipage}%
+ \else
+ \begin{minipage}[t]{\dtl@tmplength}%
+ \let\DTLgidxSymDescSep\@empty
+ \DTLgidxSymbolDescRight
+ \end{minipage}%
+ \DTLgidxSymDescSep
+ \begin{minipage}[t]{\datagidxsymbolwidth}%
+ \datagidxsymalign
+ \let\DTLgidxSymDescSep\@empty
+ \DTLgidxSymbolDescLeft
+ \end{minipage}%
+ \fi
+ \DTLgidxPreLocation
+ \begin{minipage}[t]{\datagidxlocationwidth}%
+ \datagidxlocalign
+ \let\DTLgidxPreLocation\@empty
+ #3%
+ \end{minipage}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\datagidx@doiflocwidth}
+%\begin{definition}
+%\cs{datagidx@doiflocwidth}\marg{indent}\marg{Name code}\marg{Location code}
+%\end{definition}
+% What to do if only the location width has
+% been set.
+% \begin{macrocode}
+\newcommand*{\datagidx@doiflocwidth}[3]{%
+% \end{macrocode}
+% Calculate remaining space left for the symbol and description.
+% \begin{macrocode}
+ \setlength{\dtl@tmplength}{\linewidth}%
+ \addtolength{\dtl@tmplength}{-#1}%
+ \settowidth{\dimen@}{#2}%
+ \addtolength{\dtl@tmplength}{-\dimen@}%
+ \addtolength{\dtl@tmplength}{-\datagidxlocationwidth}%
+ \settowidth{\dimen@}{\DTLgidxPreLocation}%
+ \addtolength{\dtl@tmplength}{-\dimen@}%
+ \begin{minipage}[t]{\dtl@tmplength}%
+ \DTLgidxSymbolDescription
+ \end{minipage}%
+ \DTLgidxPreLocation
+ \begin{minipage}[t]{\datagidxlocationwidth}%
+ \datagidxlocalign
+ \let\DTLgidxPreLocation\@empty
+ #3%
+ \end{minipage}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\datagidx@doifsymwidth}
+%\begin{definition}
+%\cs{datagidx@doifsymwidth}\marg{indent}\marg{Name code}\marg{Location code}
+%\end{definition}
+% What to do if only the location width has
+% been set.
+% \begin{macrocode}
+\newcommand*{\datagidx@doifsymwidth}[3]{%
+% \end{macrocode}
+% Calculate remaining space left for the description and location.
+% \begin{macrocode}
+ \setlength{\dtl@tmplength}{\linewidth}%
+ \addtolength{\dtl@tmplength}{-#1}%
+ \settowidth{\dimen@}{#2}%
+ \addtolength{\dtl@tmplength}{-\dimen@}%
+ \addtolength{\dtl@tmplength}{-\datagidxsymbolwidth}%
+ \settowidth{\dimen@}{\DTLgidxSymDescSep}%
+ \addtolength{\dtl@tmplength}{-\dimen@}%
+ \if@datagidxsymbolleft
+ \begin{minipage}[t]{\datagidxsymbolwidth}%
+ \datagidxsymalign
+ \let\DTLgidxSymDescSep\@empty
+ \DTLgidxSymbolDescLeft
+ \end{minipage}%
+ \DTLgidxSymDescSep
+ \begin{minipage}[t]{\dtl@tmplength}%
+ \let\DTLgidxSymDescSep\@empty
+ \DTLgidxSymbolDescRight
+ #3%
+ \end{minipage}%
+ \else
+ \begin{minipage}[t]{\dtl@tmplength}%
+ \let\DTLgidxSymDescSep\@empty
+ \DTLgidxSymbolDescRight
+ \end{minipage}%
+ \DTLgidxSymDescSep
+ \begin{minipage}[t]{\datagidxsymbolwidth}%
+ \datagidxsymalign
+ \let\DTLgidxSymDescSep\@empty
+ \DTLgidxSymbolDescLeft
+% \end{macrocode}
+% This arrangement may look a bit weird.
+% \begin{macrocode}
+ #3%
+ \end{minipage}%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\datagidxlocalign}
+% Alignment of the location when the location width has been set.
+% \begin{macrocode}
+\newcommand*{\datagidxlocalign}{\raggedleft}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\datagidxsymalign}
+% Alignment of the symbol when the symbol width has been set.
+% \begin{macrocode}
+\newcommand*{\datagidxsymalign}{\centering}
+% \end{macrocode}
+%\end{macro}
+%
+%
+%\subsection{Predefined styles}
+%
+%\begin{macro}{\datagidxsetstyle}
+% Sets the current index/glossary style
+% \begin{macrocode}
+\newcommand*{\datagidxsetstyle}[1]{%
+ \ifcsdef{datagidx@style@#1}%
+ {%
+ \csuse{datagidx@style@#1}%
+ }%
+ {%
+ \PackageError{datagidx}{Unknown style `#1'}{}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\subsubsection{index}
+%\begin{macro}{\datagidx@style@index}
+% Basic index style.
+% \begin{macrocode}
+\newcommand*{\datagidx@style@index}{%
+ \renewcommand*{\datagidxstart}%
+ {%
+ \bgroup
+ \setlength{\parindent}{0pt}%
+ \setlength{\parskip}{0pt plus 0.3pt}%
+% \end{macrocode}
+% Index columns are usually too narrow for fully justified text.
+% \begin{macrocode}
+ \raggedright
+ \let\item\@idxitem
+% \end{macrocode}
+% Have the symbol or location widths been set?
+% \begin{macrocode}
+ \ifdim\datagidxsymbolwidth>0pt\relax
+% \end{macrocode}
+% Symbol width has been set
+% Has the location width been set?
+% \begin{macrocode}
+ \ifdim\datagidxlocationwidth>0pt\relax
+% \end{macrocode}
+% Both have been set.
+% \begin{macrocode}
+ \def\datagidx@item@body{%
+ \datagidx@doifsymlocwidth{0pt}%
+ {\DTLgidxNameFont{\DTLgidxNameCase{\Name}}}%
+ {%
+ \DTLgidxDoSeeOrLocation
+ }%
+ }%
+ \else
+% \end{macrocode}
+% Location width hasn't been set.
+% \begin{macrocode}
+ \def\datagidx@item@body{%
+ \datagidx@doiflocwidth{0pt}%
+ {\DTLgidxNameFont{\DTLgidxNameCase{\Name}}}%
+ {%
+ \DTLgidxDoSeeOrLocation
+ }%
+ }%
+ \fi
+ \else
+% \end{macrocode}
+% Symbol width hasn't been set
+% Has the location width been set?
+% \begin{macrocode}
+ \ifdim\datagidxlocationwidth>0pt\relax
+% \end{macrocode}
+% Location width has been set.
+% \begin{macrocode}
+ \def\datagidx@item@body{%
+ \datagidx@doiflocwidth{0pt}%
+ {\DTLgidxNameFont{\DTLgidxNameCase{\Name}}}%
+ {%
+ \DTLgidxDoSeeOrLocation
+ }%
+ }%
+ \else
+% \end{macrocode}
+% Neither have been set.
+% \begin{macrocode}
+ \def\datagidx@item@body{%
+ \DTLgidxSymbolDescription
+ \DTLgidxDoSeeOrLocation
+ }%
+ \fi
+ \fi
+ }%
+ \renewcommand*{\datagidxend}{\egroup}%
+ \renewcommand*{\datagidxgroupsep}{\ifdatagidxshowgroups\indexspace\fi}%
+ \renewcommand{\datagidxgroupheader}{%
+ \ifdatagidxshowgroups
+ \item
+ \makebox[\linewidth]%
+ {%
+ \textbf{\DTLgidxGroupHeaderTitle{\datagidxcurrentgroup}}%
+ }%
+ \DTLpar\nobreak\@afterheading
+ \fi
+ }%
+ \renewcommand*{\datagidxitem}{%
+% \end{macrocode}
+% Is this the start of a new group?
+% \begin{macrocode}
+ \ifdefempty\datagidxprevgroup
+ {%
+% \end{macrocode}
+% First item of the list.
+% \begin{macrocode}
+ \datagidxgroupheader
+ }%
+ {%
+% \end{macrocode}
+% Not the first item of the list. Is this item's group the same as
+% the last item's group?
+% \begin{macrocode}
+ \ifdefequal\datagidxcurrentgroup\datagidxprevgroup
+ {%
+% \end{macrocode}
+% Same, so do nothing.
+% \begin{macrocode}
+ }%
+ {%
+% \end{macrocode}
+% Different, so do the separator and the header.
+% \begin{macrocode}
+ \datagidxgroupsep
+ \datagidxgroupheader
+ }%
+ }%
+% \end{macrocode}
+% Now get on with this item.
+% \begin{macrocode}
+ \item
+ \datagidxtarget{\Label}%
+ {%
+ \DTLgidxNameFont{\DTLgidxNameCase{\Name}}%
+ }%
+ \DTLgidxPostName
+ \datagidx@item@body
+ \DTLgidxChildrenSeeAlso
+ }%
+ \renewcommand*{\datagidxchildstart}%
+ {%
+ \bgroup
+ \setlength{\parindent}{0pt}%
+ \setlength{\parskip}{0pt plus 0.3pt}%
+ \let\item\@idxitem
+ }%
+ \renewcommand*{\datagidxchildend}{\egroup}%
+ \renewcommand*{\datagidxchilditem}{%
+ \setlength{\dimen@}{\datagidxindent}%
+ \multiply\dimen@ by \datagidx@level\relax
+ \@idxitem\hspace*{\dimen@}%
+ \refstepcounter{DTLgidxChildCount}%
+ \datagidxtarget{\Label}%
+ {%
+ \DTLgidxChildStyle
+ {%
+ \DTLgidxNameFont{\DTLgidxNameCase{\Name}}%
+ \DTLgidxPostChildName
+ }%
+ }%
+ \DTLgidxSymbolDescription
+ \DTLgidxDoSeeOrLocation
+ \DTLgidxChildrenSeeAlso
+ }%
+ \renewcommand*{\datagidxseealsostart}%
+ {%
+ \bgroup
+ \setlength{\parindent}{0pt}%
+ \setlength{\parskip}{0pt plus 0.3pt}%
+ \setlength{\dimen@}{\datagidxindent}%
+ \advance\datagidx@level by 1\relax
+ \multiply\dimen@ by \datagidx@level\relax
+ \@idxitem\hspace*{\dimen@}%
+ }%
+ \renewcommand{\datagidxseealsoend}{\egroup}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%Make this the default style:
+% \begin{macrocode}
+\datagidx@style@index
+% \end{macrocode}
+%
+%\subsubsection{indexalign}
+% Similar to index style but aligns the descriptions.
+%\begin{macro}{\datagidx@style@indexalign}
+% \begin{macrocode}
+\newcommand*{\datagidx@style@indexalign}{%
+ \renewcommand*{\datagidxstart}%
+ {%
+ \bgroup
+ \setlength{\parindent}{0pt}%
+ \setlength{\parskip}{0pt plus 0.3pt}%
+ \setlength{\datagidxnamewidth}{0pt}%
+ \DTLforeach*{\DTLgidxCurrentdb}%
+ {\Name=Name,\Location=Location,\See=See,\SeeAlso=SeeAlso,%
+ \Parent=Parent}%
+ {%
+ \DTLifnull{\Parent}%
+ {%
+ \datagidx@doifdisplayed
+ {%
+ \settowidth{\dimen@}{\DTLgidxNameFont{\DTLgidxNameCase{\Name}}}%
+ \ifdim\dimen@>\datagidxnamewidth\relax
+ \datagidxnamewidth=\dimen@\relax
+ \fi
+ }%
+ }%
+ {}%
+ }%
+ \settowidth{\dimen@}{\DTLgidxPostName}%
+ \addtolength{\datagidxnamewidth}{\dimen@}%
+ \setlength{\datagidxdescwidth}{\linewidth}%
+ \addtolength{\datagidxdescwidth}{-\datagidxnamewidth}%
+ \ifdim\datagidxsymbolwidth>0pt\relax
+ \addtolength{\datagidxdescwidth}{-\datagidxsymbolwidth}%
+ \settowidth{\dimen@}{\DTLgidxSymDescSep}%
+ \addtolength{\datagidxdescwidth}{-\dimen@}%
+ \fi
+ \ifdim\datagidxlocationwidth>0pt\relax
+ \addtolength{\datagidxdescwidth}{-\datagidxlocationwidth}%
+ \settowidth{\dimen@}{\DTLgidxPreLocation}%
+ \addtolength{\datagidxdescwidth}{-\dimen@}%
+ \fi
+% \end{macrocode}
+% Has the symbol width been set?
+% \begin{macrocode}
+ \ifdim\datagidxsymbolwidth>0pt\relax
+% \end{macrocode}
+% Yes, symbol width has been set.
+% Has the location width been set?
+% \begin{macrocode}
+ \ifdim\datagidxlocationwidth>0pt\relax
+% \end{macrocode}
+% Both symbol and location widths have been set.
+% \begin{macrocode}
+ \if@datagidxsymbolleft
+% \end{macrocode}
+% Symbol is on the left.
+% \begin{macrocode}
+ \def\datagidx@item@body{%
+ \begin{minipage}[t]{\datagidxsymbolwidth}%
+ \datagidxsymalign
+ \let\DTLgidxSymDescSep\@empty
+ \DTLgidxSymbolDescLeft
+ \end{minipage}%
+ \DTLgidxSymDescSep
+ \begin{minipage}[t]{\datagidxdescwidth}%
+ \let\DTLgidxSymDescSep\@empty
+ \setlength{\parskip}{0pt plus 0.3pt}%
+ \DTLgidxSymbolDescRight
+ \end{minipage}%
+ \DTLgidxPreLocation
+ \begin{minipage}[t]{\datagidxlocationwidth}%
+ \datagidxlocalign
+ \let\DTLgidxPreLocation\@empty
+ \DTLgidxDoSeeOrLocation
+ \end{minipage}%
+ }%
+ \else
+% \end{macrocode}
+% Symbol is on the right.
+% \begin{macrocode}
+ \def\datagidx@item@body{%
+ \begin{minipage}[t]{\datagidxdescwidth}%
+ \let\DTLgidxSymDescSep\@empty
+ \DTLgidxSymbolDescLeft
+ \end{minipage}%
+ \DTLgidxSymDescSep
+ \begin{minipage}[t]{\datagidxsymbolwidth}%
+ \datagidxsymalign
+ \let\DTLgidxSymDescSep\@empty
+ \setlength{\parskip}{0pt plus 0.3pt}%
+ \DTLgidxSymbolDescRight
+ \end{minipage}%
+ \DTLgidxPreLocation
+ \begin{minipage}[t]{\datagidxlocationwidth}%
+ \datagidxlocalign
+ \let\DTLgidxPreLocation\@empty
+ \DTLgidxDoSeeOrLocation
+ \end{minipage}%
+ }%
+ \fi
+ \else
+% \end{macrocode}
+% Location width hasn't been set. (Only symbol width has been set.)
+% \begin{macrocode}
+ \if@datagidxsymbolleft
+ \def\datagidx@item@body{%
+ \begin{minipage}[t]{\datagidxsymbolwidth}%
+ \datagidxsymalign
+ \let\DTLgidxSymDescSep\@empty
+ \DTLgidxSymbolDescLeft
+ \end{minipage}%
+ \DTLgidxSymDescSep
+ \begin{minipage}[t]{\datagidxdescwidth}%
+ \let\DTLgidxSymDescSep\@empty
+ \setlength{\parskip}{0pt plus 0.3pt}%
+ \DTLgidxSymbolDescRight
+ \DTLgidxDoSeeOrLocation
+ \end{minipage}%
+ }%
+ \else
+% \end{macrocode}
+% Symbol is on the right.
+% This combination may look weird.
+% \begin{macrocode}
+ \def\datagidx@item@body{%
+ \begin{minipage}[t]{\datagidxdescwidth}%
+ \let\DTLgidxSymDescSep\@empty
+ \DTLgidxSymbolDescLeft
+ \end{minipage}%
+ \DTLgidxSymDescSep
+ \begin{minipage}[t]{\datagidxsymbolwidth}%
+ \datagidxsymalign
+ \let\DTLgidxSymDescSep\@empty
+ \setlength{\parskip}{0pt plus 0.3pt}%
+ \DTLgidxSymbolDescRight
+ \DTLgidxDoSeeOrLocation
+ \end{minipage}%
+ }%
+ \fi
+ \fi
+ \else
+% \end{macrocode}
+% Symbol width hasn't been set.
+% Has the location width been set?
+% \begin{macrocode}
+ \ifdim\datagidxlocationwidth>0pt\relax
+% \end{macrocode}
+% Only location width has been set.
+% \begin{macrocode}
+ \def\datagidx@item@body{%
+ \begin{minipage}[t]{\datagidxdescwidth}%
+ \setlength{\parskip}{0pt plus 0.3pt}%
+ \DTLgidxSymbolDescription
+ \end{minipage}%
+ \DTLgidxPreLocation
+ \begin{minipage}[t]{\datagidxlocationwidth}%
+ \datagidxlocalign
+ \let\DTLgidxPreLocation\@empty
+ \DTLgidxDoSeeOrLocation
+ }%
+ \else
+% \end{macrocode}
+% Neither location nor symbol widths have been set.
+% \begin{macrocode}
+ \def\datagidx@item@body{%
+ \begin{minipage}[t]{\datagidxdescwidth}%
+ \setlength{\parskip}{0pt plus 0.3pt}%
+ \DTLgidxSymbolDescription
+ \DTLgidxDoSeeOrLocation
+ \end{minipage}%
+ }%
+ \fi
+ \fi
+ }%
+ \renewcommand*{\datagidxend}{\egroup}%
+ \renewcommand*{\datagidxgroupsep}{}%
+ \renewcommand*{\datagidxgroupheader}{}%
+ \renewcommand*{\datagidxitem}{%
+% \end{macrocode}
+% Is this the start of a new group?
+% \begin{macrocode}
+ \ifdefempty\datagidxprevgroup
+ {%
+% \end{macrocode}
+% First item of the list.
+% \begin{macrocode}
+ \datagidxgroupheader
+ }%
+ {%
+% \end{macrocode}
+% Not the first item of the list. Is this item's group the same as
+% the last item's group?
+% \begin{macrocode}
+ \ifdefequal\datagidxcurrentgroup\datagidxprevgroup
+ {%
+% \end{macrocode}
+% Same, so do nothing.
+% \begin{macrocode}
+ }%
+ {%
+% \end{macrocode}
+% Different, so do the separator and the header.
+% \begin{macrocode}
+ \datagidxgroupsep
+ \datagidxgroupheader
+ }%
+ }%
+% \end{macrocode}
+% Get on with this item
+% \begin{macrocode}
+ \hangindent0pt\relax
+ \parindent0pt\relax
+ \makebox[\datagidxnamewidth][l]%
+ {%
+ \datagidxtarget{\Label}%
+ {%
+ \DTLgidxNameFont{\DTLgidxNameCase{\Name}}%
+ \DTLgidxPostName
+ }%
+ }%
+ \datagidx@item@body
+ \par
+ \DTLgidxChildrenSeeAlso
+ \par
+ }%
+ \renewcommand*{\datagidxchildstart}%
+ {%
+ \bgroup
+ \setlength{\dimen@}{\datagidxindent}%
+ \multiply\dimen@ by \datagidx@level\relax
+ \setlength{\dtl@tmplength}{\linewidth}%
+ \addtolength{\dtl@tmplength}{-\dimen@}%
+ \setlength{\parindent}{0pt}%
+ \setlength{\parskip}{0pt plus 0.3pt}%
+ \edef\item{\noexpand\parshape=1 \the\dimen@ \the\dtl@tmplength}%
+ \setlength{\datagidxnamewidth}{0pt}%
+ \DTLforeach*{\DTLgidxCurrentdb}%
+ {\Name=Name,\Location=Location,\See=See,\SeeAlso=SeeAlso,%
+ \Parent=Parent}%
+ {%
+ \DTLifnull{\Parent}%
+ {%
+ \datagidx@doifdisplayed
+ {%
+ \settowidth{\dimen@}%
+ {%
+ \DTLgidxChildStyle
+ {%
+ \DTLgidxNameFont{\DTLgidxNameCase{\Name}}%
+ }%
+ }%
+ \ifdim\dimen@>\datagidxnamewidth\relax
+ \datagidxnamewidth=\dimen@\relax
+ \fi
+ }%
+ }%
+ {}%
+ }%
+ \settowidth{\dimen@}{\DTLgidxChildStyle\DTLgidxPostChildName}%
+ \addtolength{\datagidxnamewidth}{\dimen@}%
+ \setlength{\datagidxdescwidth}{\dtl@tmplength}%
+ \addtolength{\datagidxdescwidth}{-\datagidxnamewidth}%
+ }%
+ \renewcommand{\datagidxchildend}{\egroup}%
+ \renewcommand*{\datagidxchilditem}{%
+ \item
+ \refstepcounter{DTLgidxChildCount}%
+ \makebox[\datagidxnamewidth][l]%
+ {%
+ \datagidxtarget{\Label}%
+ {%
+ \DTLgidxChildStyle
+ {%
+ \DTLgidxNameFont{\DTLgidxNameCase{\Name}}%
+ \DTLgidxPostChildName
+ }%
+ }%
+ }%
+ \begin{minipage}[t]{\datagidxdescwidth}%
+ \setlength{\parskip}{0pt plus 0.3pt}%
+ \DTLgidxSymbolDescription
+ \DTLgidxDoSeeOrLocation
+ \DTLgidxChildrenSeeAlso
+ \end{minipage}%
+ \par
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\datagidxindent}
+% Indent used by "index" and "indexalign" styles.
+% \begin{macrocode}
+\newlength\datagidxindent
+\setlength\datagidxindent{10\p@}
+% \end{macrocode}
+%\end{macro}
+%
+%
+%\subsubsection{align}
+%\begin{macro}{\datagidxnamewidth}
+% Length used by "align" and "indexalign" style name.
+% \begin{macrocode}
+\newlength\datagidxnamewidth
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\datagidxdescwidth}
+% Length used by "align" and "indexalign" style description.
+% \begin{macrocode}
+\newlength\datagidxdescwidth
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\datagidx@style@align}
+% \begin{macrocode}
+\newcommand*{\datagidx@style@align}{%
+ \renewcommand*{\datagidxstart}%
+ {%
+ \bgroup
+ \setlength{\parindent}{0pt}%
+ \setlength{\parskip}{0pt plus 0.3pt}%
+ \setlength{\datagidxnamewidth}{0pt}%
+ \DTLforeach*{\DTLgidxCurrentdb}%
+ {\Name=Name,\Location=Location,\See=See,\SeeAlso=SeeAlso,%
+ \Parent=Parent}%
+ {%
+ \DTLifnull{\Parent}%
+ {%
+ \datagidx@doifdisplayed
+ {%
+ \settowidth{\dimen@}{\DTLgidxNameFont{\DTLgidxNameCase{\Name}}}%
+ \ifdim\dimen@>\datagidxnamewidth\relax
+ \datagidxnamewidth=\dimen@\relax
+ \fi
+ }%
+ }%
+ {}%
+ }%
+ \settowidth{\dimen@}{\DTLgidxPostName}%
+ \addtolength{\datagidxnamewidth}{\dimen@}%
+ \setlength{\datagidxdescwidth}{\linewidth}%
+ \addtolength{\datagidxdescwidth}{-\datagidxnamewidth}%
+ \ifdim\datagidxsymbolwidth>0pt\relax
+ \addtolength{\datagidxdescwidth}{-\datagidxsymbolwidth}%
+ \settowidth{\dimen@}{\DTLgidxSymDescSep}%
+ \addtolength{\datagidxdescwidth}{-\dimen@}%
+ \fi
+ \ifdim\datagidxlocationwidth>0pt\relax
+ \addtolength{\datagidxdescwidth}{-\datagidxlocationwidth}%
+ \settowidth{\dimen@}{\DTLgidxPreLocation}%
+ \addtolength{\datagidxdescwidth}{-\dimen@}%
+ \fi
+% \end{macrocode}
+% Has the symbol width been set?
+% \begin{macrocode}
+ \ifdim\datagidxsymbolwidth>0pt\relax
+% \end{macrocode}
+% Yes, symbol width has been set.
+% Has the location width been set?
+% \begin{macrocode}
+ \ifdim\datagidxlocationwidth>0pt\relax
+% \end{macrocode}
+% Both symbol and location widths have been set.
+% \begin{macrocode}
+ \if@datagidxsymbolleft
+% \end{macrocode}
+% Symbol is on the left.
+% \begin{macrocode}
+ \def\datagidx@item@body{%
+ \begin{minipage}[t]{\datagidxsymbolwidth}%
+ \datagidxsymalign
+ \let\DTLgidxSymDescSep\@empty
+ \DTLgidxSymbolDescLeft
+ \end{minipage}%
+ \DTLgidxSymDescSep
+ \begin{minipage}[t]{\datagidxdescwidth}%
+ \let\DTLgidxSymDescSep\@empty
+ \setlength{\parskip}{0pt plus 0.3pt}%
+ \DTLgidxSymbolDescRight
+ \end{minipage}%
+ \DTLgidxPreLocation
+ \begin{minipage}[t]{\datagidxlocationwidth}%
+ \datagidxlocalign
+ \let\DTLgidxPreLocation\@empty
+ \DTLgidxDoSeeOrLocation
+ \DTLgidxChildrenSeeAlso
+ \end{minipage}%
+ }%
+ \else
+% \end{macrocode}
+% Symbol is on the right.
+% \begin{macrocode}
+ \def\datagidx@item@body{%
+ \begin{minipage}[t]{\datagidxdescwidth}%
+ \let\DTLgidxSymDescSep\@empty
+ \DTLgidxSymbolDescLeft
+ \end{minipage}%
+ \DTLgidxSymDescSep
+ \begin{minipage}[t]{\datagidxsymbolwidth}%
+ \datagidxsymalign
+ \let\DTLgidxSymDescSep\@empty
+ \setlength{\parskip}{0pt plus 0.3pt}%
+ \DTLgidxSymbolDescRight
+ \end{minipage}%
+ \DTLgidxPreLocation
+ \begin{minipage}[t]{\datagidxlocationwidth}%
+ \datagidxlocalign
+ \let\DTLgidxPreLocation\@empty
+ \DTLgidxDoSeeOrLocation
+ \DTLgidxChildrenSeeAlso
+ \end{minipage}%
+ }%
+ \fi
+ \else
+% \end{macrocode}
+% Location width hasn't been set. (Only symbol width has been set.)
+% \begin{macrocode}
+ \if@datagidxsymbolleft
+ \def\datagidx@item@body{%
+ \begin{minipage}[t]{\datagidxsymbolwidth}%
+ \datagidxsymalign
+ \let\DTLgidxSymDescSep\@empty
+ \DTLgidxSymbolDescLeft
+ \end{minipage}%
+ \DTLgidxSymDescSep
+ \begin{minipage}[t]{\datagidxdescwidth}%
+ \let\DTLgidxSymDescSep\@empty
+ \setlength{\parskip}{0pt plus 0.3pt}%
+ \DTLgidxSymbolDescRight
+ \DTLgidxDoSeeOrLocation
+ \DTLgidxChildrenSeeAlso
+ \end{minipage}%
+ }%
+ \else
+% \end{macrocode}
+% Symbol is on the right.
+% This combination may look weird.
+% \begin{macrocode}
+ \def\datagidx@item@body{%
+ \begin{minipage}[t]{\datagidxdescwidth}%
+ \let\DTLgidxSymDescSep\@empty
+ \DTLgidxSymbolDescLeft
+ \end{minipage}%
+ \DTLgidxSymDescSep
+ \begin{minipage}[t]{\datagidxsymbolwidth}%
+ \datagidxsymalign
+ \let\DTLgidxSymDescSep\@empty
+ \setlength{\parskip}{0pt plus 0.3pt}%
+ \DTLgidxSymbolDescRight
+ \DTLgidxDoSeeOrLocation
+ \DTLgidxChildrenSeeAlso
+ \end{minipage}%
+ }%
+ \fi
+ \fi
+ \else
+% \end{macrocode}
+% Symbol width hasn't been set.
+% Has the location width been set?
+% \begin{macrocode}
+ \ifdim\datagidxlocationwidth>0pt\relax
+% \end{macrocode}
+% Only location width has been set.
+% \begin{macrocode}
+ \def\datagidx@item@body{%
+ \begin{minipage}[t]{\datagidxdescwidth}%
+ \setlength{\parskip}{0pt plus 0.3pt}%
+ \DTLgidxSymbolDescription
+ \end{minipage}%
+ \DTLgidxPreLocation
+ \begin{minipage}[t]{\datagidxlocationwidth}%
+ \datagidxlocalign
+ \let\DTLgidxPreLocation\@empty
+ \DTLgidxDoSeeOrLocation
+ \DTLgidxChildrenSeeAlso
+ \end{minipage}%
+ }%
+ \else
+% \end{macrocode}
+% Neither location nor symbol widths have been set.
+% \begin{macrocode}
+ \def\datagidx@item@body{%
+ \begin{minipage}[t]{\datagidxdescwidth}%
+ \setlength{\parskip}{0pt plus 0.3pt}%
+ \DTLgidxSymbolDescription
+ \DTLgidxDoSeeOrLocation
+ \DTLgidxChildrenSeeAlso
+ \end{minipage}%
+ }%
+ \fi
+ \fi
+ }%
+ \renewcommand*{\datagidxend}{\egroup}%
+ \renewcommand*{\datagidxgroupsep}{\ifdatagidxshowgroups\indexspace\fi}%
+ \renewcommand{\datagidxgroupheader}{%
+ \ifdatagidxshowgroups
+ \item
+ \makebox[\linewidth]%
+ {%
+ \textbf{\DTLgidxGroupHeaderTitle{\datagidxcurrentgroup}}%
+ }%
+ \DTLpar\nobreak\@afterheading
+ \fi
+ }%
+ \renewcommand*{\datagidxitem}{%
+% \end{macrocode}
+% Is this the start of a new group?
+% \begin{macrocode}
+ \ifdefempty\datagidxprevgroup
+ {%
+% \end{macrocode}
+% First item of the list.
+% \begin{macrocode}
+ \datagidxgroupheader
+ }%
+ {%
+% \end{macrocode}
+% Not the first item of the list. Is this item's group the same as
+% the last item's group?
+% \begin{macrocode}
+ \ifdefequal\datagidxcurrentgroup\datagidxprevgroup
+ {%
+% \end{macrocode}
+% Same, so do nothing.
+% \begin{macrocode}
+ }%
+ {%
+% \end{macrocode}
+% Different, so do the separator and the header.
+% \begin{macrocode}
+ \datagidxgroupsep
+ \datagidxgroupheader
+ }%
+ }%
+ \hangindent0pt\relax
+ \parindent0pt\relax
+ \makebox[\datagidxnamewidth][l]%
+ {%
+ \datagidxtarget{\Label}%
+ {%
+ \DTLgidxNameFont{\DTLgidxNameCase{\Name}}%
+ \DTLgidxPostName
+ }%
+ }%
+ \datagidx@item@body
+ \par
+ }%
+ \renewcommand*{\datagidxchildstart}%
+ {%
+ \bgroup
+ \setlength{\parindent}{0pt}%
+ \setlength{\parskip}{0pt plus 0.3pt}%
+ \setlength{\datagidxnamewidth}{0pt}%
+ \DTLforeach*{\DTLgidxCurrentdb}%
+ {\Name=Name,\Location=Location,\See=See,\SeeAlso=SeeAlso,%
+ \Parent=Parent}%
+ {%
+ \DTLifnull{\Parent}%
+ {%
+ \datagidx@doifdisplayed
+ {%
+ \settowidth{\dimen@}%
+ {%
+ \DTLgidxChildStyle
+ {%
+ \DTLgidxNameFont{\DTLgidxNameCase{\Name}}%
+ }%
+ }%
+ \ifdim\dimen@>\datagidxnamewidth\relax
+ \datagidxnamewidth=\dimen@\relax
+ \fi
+ }%
+ }%
+ {}%
+ }%
+ \settowidth{\dimen@}{\DTLgidxChildStyle\DTLgidxPostChildName}%
+ \addtolength{\datagidxnamewidth}{\dimen@}%
+ \setlength{\datagidxdescwidth}{\linewidth}%
+ \addtolength{\datagidxdescwidth}{-\datagidxnamewidth}%
+ }%
+ \renewcommand{\datagidxchildend}{\egroup}%
+ \renewcommand*{\datagidxchilditem}{%
+ \hangindent0pt\relax
+ \parindent0pt\relax
+ \refstepcounter{DTLgidxChildCount}%
+ \makebox[\datagidxnamewidth][l]%
+ {%
+ \datagidxtarget{\Label}%
+ {%
+ \DTLgidxChildStyle
+ {%
+ \DTLgidxNameFont{\DTLgidxNameCase{\Name}}%
+ \DTLgidxPostChildName
+ }%
+ }%
+ }%
+ \begin{minipage}[t]{\datagidxdescwidth}%
+ \setlength{\parskip}{0pt plus 0.3pt}%
+ \DTLgidxSymbolDescription
+ \DTLgidxDoSeeOrLocation
+ \DTLgidxChildrenSeeAlso
+ \end{minipage}%
+ \par
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\subsubsection{gloss}
+%\begin{macro}{\datagidx@style@gloss}
+% \begin{macrocode}
+\newcommand*{\datagidx@style@gloss}{%
+ \renewcommand*{\datagidxstart}%
+ {%
+ \bgroup
+ \setlength{\parindent}{0pt}%
+ \setlength{\parskip}{0pt plus 0.3pt}%
+ \setlength{\datagidxnamewidth}{0pt}%
+ \DTLforeach*{\DTLgidxCurrentdb}%
+ {\Name=Name,\Location=Location,\See=See,\SeeAlso=SeeAlso,%
+ \Parent=Parent}%
+ {%
+ \DTLifnull{\Parent}%
+ {%
+ \datagidx@doifdisplayed
+ {%
+ \settowidth{\dimen@}{\DTLgidxNameFont{\DTLgidxNameCase{\Name}}}%
+ \ifdim\dimen@>\datagidxnamewidth\relax
+ \datagidxnamewidth=\dimen@\relax
+ \fi
+ }%
+ }%
+ {}%
+ }%
+ \settowidth{\dimen@}{\DTLgidxPostName}%
+ \addtolength{\datagidxnamewidth}{\dimen@}%
+ \setlength{\datagidxdescwidth}{\linewidth}%
+ \addtolength{\datagidxdescwidth}{-\datagidxnamewidth}%
+ }%
+ \renewcommand*{\datagidxend}{\egroup}%
+ \renewcommand*{\datagidxgroupsep}{\ifdatagidxshowgroups\indexspace\fi}%
+ \renewcommand{\datagidxgroupheader}{%
+ \ifdatagidxshowgroups
+ \item
+ \makebox[\linewidth]%
+ {%
+ \textbf{\DTLgidxGroupHeaderTitle{\datagidxcurrentgroup}}%
+ }%
+ \DTLpar\nobreak\@afterheading
+ \fi
+ }%
+ \renewcommand*{\datagidxitem}{%
+% \end{macrocode}
+% Is this the start of a new group?
+% \begin{macrocode}
+ \ifdefempty\datagidxprevgroup
+ {%
+% \end{macrocode}
+% First item of the list.
+% \begin{macrocode}
+ \datagidxgroupheader
+ }%
+ {%
+% \end{macrocode}
+% Not the first item of the list. Is this item's group the same as
+% the last item's group?
+% \begin{macrocode}
+ \ifdefequal\datagidxcurrentgroup\datagidxprevgroup
+ {%
+% \end{macrocode}
+% Same, so do nothing.
+% \begin{macrocode}
+ }%
+ {%
+% \end{macrocode}
+% Different, so do the separator and the header.
+% \begin{macrocode}
+ \datagidxgroupsep
+ \datagidxgroupheader
+ }%
+ }%
+ \hangindent0pt\relax
+ \parindent0pt\relax
+ \makebox[\datagidxnamewidth][l]%
+ {%
+ \datagidxtarget{\Label}%
+ {%
+ \DTLgidxNameFont{\DTLgidxNameCase{\Name}}%
+ \DTLgidxPostName
+ }%
+ }%
+ \begin{minipage}[t]{\datagidxdescwidth}%
+ \setlength{\parskip}{0pt plus 0.3pt}%
+ \@tempswatrue
+ \ifdefempty{\Description}%
+ {%
+ \ifdefempty{\Symbol}%
+ {%
+ \ifdefempty{\Location}{\@tempswafalse}{}%
+ }%
+ {}%
+ }%
+ {}%
+ \if@tempswa
+ \DTLgidxSymbolDescription
+ \DTLgidxDoSeeOrLocation
+% \end{macrocode}
+%\changes{2.14}{2013-06-28}{removed spurious see also line}
+% \begin{macrocode}
+ \else
+ \mbox{}%
+ \fi
+ \DTLgidxChildrenSeeAlso
+ \end{minipage}%
+ \par
+ }%
+ \renewcommand*{\datagidxchildstart}%
+ {%
+ \bgroup
+ \def\datagidx@childsep{}%
+ \setcounter{DTLgidxChildCount}{0}%
+ }%
+ \renewcommand{\datagidxchildend}{\DTLgidxPostChild\egroup}%
+ \renewcommand*{\datagidxchilditem}{%
+ \datagidx@childsep
+ \refstepcounter{DTLgidxChildCount}%
+ \datagidxtarget{\Label}%
+ {%
+ \DTLgidxChildStyle
+ {%
+ \DTLgidxNameFont{\DTLgidxNameCase{\Name}}%
+ \DTLgidxPostChildName
+ }%
+ }%
+ \DTLgidxSymbolDescription
+ \DTLgidxDoSeeOrLocation
+ \DTLgidxChildrenSeeAlso
+ \let\datagidx@childsep\DTLgidxChildSep
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLgidxChildSep}
+% Separator between child entries for gloss style.
+% \begin{macrocode}
+\newcommand*{\DTLgidxChildSep}{ }
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLgidxPostChild}
+%What to put at the end of child entries for gloss style.
+% \begin{macrocode}
+\newcommand*{\DTLgidxPostChild}{}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLgidxDictHead}
+% Group header for dict style.
+% \begin{macrocode}
+\ifdef\chapter
+{%
+ \newcommand\DTLgidxDictHead{%
+ \chapter{\DTLgidxGroupHeaderTitle{\datagidxcurrentgroup}}%
+ }%
+}%
+{%
+ \newcommand\DTLgidxDictHead{%
+ \section{\DTLgidxGroupHeaderTitle{\datagidxcurrentgroup}}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLgidxCategoryNameFont}
+% Font used for `category' entries with `dict' style.
+% \begin{macrocode}
+\newcommand*{\DTLgidxCategoryNameFont}[1]{#1}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLgidxCategorySep}
+% Separator used with `dict' style.
+% \begin{macrocode}
+\newcommand*{\DTLgidxCategorySep}{\space}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLgidxSubCategorySep}
+% Separator used with `dict' style.
+% \begin{macrocode}
+\newcommand*{\DTLgidxSubCategorySep}{\space}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\datagidxdictindent}
+% Indent used by `dict' style.
+% \begin{macrocode}
+\newcommand*{\datagidxdictindent}{1em}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLgidxDictPostItem}
+% What to do at the end of each item in the `dict' style.
+% \begin{macrocode}
+\newcommand{\DTLgidxDictPostItem}{\par}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\datagidx@style@dict}
+% Dictionary style. This assumes a hierarchical structure where the
+% top level entries have a name. The next level is used to indicate
+% a category, such as ``adjective'' or ``noun''. If there is only
+% one meaning this level also has a description. If there is more
+% than one meaning, each meaning should be a child of the category
+% entry. Only third level entries are numbered. The "child" key is
+% ignored in this style. The symbol is ignored. The location and
+% symbols widths are also ignored.
+% \begin{macrocode}
+\newcommand*{\datagidx@style@dict}{%
+ \renewcommand*{\datagidxstart}%
+ {%
+ \bgroup
+ \setlength{\parindent}{0pt}%
+ \setlength{\parskip}{0pt plus 0.3pt}%
+ \dimen@=\linewidth
+ \advance\dimen@ by -\datagidxdictindent\relax
+ \dtl@tmplength=\datagidxdictindent\relax
+ \xdef\datagidxdictparshape{%
+ \noexpand\parshape=2 0pt \the\linewidth\space
+ \the\dtl@tmplength\space \the\dimen@\relax
+ }%
+ \datagidx@level=1\relax
+% \end{macrocode}
+% Index columns are usually too narrow for fully justified text.
+% \begin{macrocode}
+ \raggedright
+ }%
+ \renewcommand*{\datagidxend}{\egroup}%
+ \renewcommand*{\datagidxgroupsep}{}%
+ \renewcommand{\datagidxgroupheader}{%
+ \ifdatagidxshowgroups
+ \datagidxend
+ \datagidx@postend
+ \DTLgidxDictHead
+ \datagidx@prestart
+ \datagidxstart
+ \fi
+ }%
+ \renewcommand*{\datagidxitem}{%
+% \end{macrocode}
+% Is this the start of a new group?
+% \begin{macrocode}
+ \ifdefempty\datagidxprevgroup
+ {%
+% \end{macrocode}
+% First item of the list.
+% \begin{macrocode}
+ \datagidxgroupheader
+ }%
+ {%
+% \end{macrocode}
+% Not the first item of the list. Is this item's group the same as
+% the last item's group?
+% \begin{macrocode}
+ \ifdefequal\datagidxcurrentgroup\datagidxprevgroup
+ {%
+% \end{macrocode}
+% Same, so do nothing.
+% \begin{macrocode}
+ }%
+ {%
+% \end{macrocode}
+% Different, so do the separator and the header.
+% \begin{macrocode}
+ \datagidxgroupsep
+ \datagidxgroupheader
+ }%
+ }%
+% \end{macrocode}
+% Now get on with this item.
+% \begin{macrocode}
+ \datagidxdictparshape
+ \datagidxtarget{\Label}%
+ {%
+ \DTLgidxNameFont{\DTLgidxNameCase{\Name}}%
+ }%
+ \DTLgidxPostName
+% \end{macrocode}
+% Initialise category separator to do nothing.
+% \begin{macrocode}
+ \let\datagidx@catsep\@empty
+ \let\datagidx@subcatsep\@empty
+ \DTLgidxSymbolDescription
+% \end{macrocode}
+% No location list.
+% \begin{macrocode}
+ \DTLgidxChildrenSeeAlso
+ \DTLgidxDictPostItem
+ }%
+ \renewcommand*{\datagidxchildstart}%
+ {%
+ \bgroup
+ }%
+ \renewcommand*{\datagidxchildend}{\egroup}%
+ \renewcommand*{\datagidxchilditem}{%
+% \end{macrocode}
+% Which level are we on?
+% \begin{macrocode}
+ \ifnum\datagidx@level=2\relax
+% \end{macrocode}
+% Category entry
+% \begin{macrocode}
+ \datagidx@catsep
+ \let\datagidx@catsep\DTLgidxCategorySep
+ \let\datagidx@subcapsep\@empty
+ \datagidxtarget{\Label}%
+ {%
+ \DTLgidxChildStyle
+ {%
+ \DTLgidxCategoryNameFont{\DTLgidxNameCase{\Name}}%
+ \DTLgidxPostChildName
+ }%
+ }%
+ \setcounter{DTLgidxChildCount}{0}%
+ \else
+% \end{macrocode}
+% Sub Category entry
+% \begin{macrocode}
+ \datagidx@subcatsep
+ \let\datagidx@subcatsep\DTLgidxSubCategorySep
+ \refstepcounter{DTLgidxChildCount}%
+ \DTLgidxChildCountLabel
+ \DTLgidxPostChildName
+ \fi
+ \DTLgidxSymbolDescription
+ \DTLgidxDoSeeOrLocation
+ \DTLgidxChildrenSeeAlso
+ }%
+ \renewcommand*{\datagidxseealsostart}%
+ {%
+ \bgroup
+ \setlength{\parindent}{0pt}%
+ \setlength{\parskip}{0pt plus 0.3pt}%
+ \setlength{\dimen@}{\datagidxindent}%
+ \advance\datagidx@level by 1\relax
+ \multiply\dimen@ by \datagidx@level\relax
+ \@idxitem\hspace*{\dimen@}%
+ }%
+ \renewcommand{\datagidxseealsoend}{\egroup}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\subsection{Location Lists}
+%\begin{macro}{\dtldofirstlocation}
+% Only display the first location in the list.
+% \begin{macrocode}
+\newcommand*{\dtldofirstlocation}{%
+ \@for\dtl@thisloc:=\Location\do{%
+ \ifdefempty\dtl@thisloc
+ {}%
+ {%
+ \expandafter\datagidx@getlocation\dtl@thisloc
+ \datagidxlink{\datagidx@current@target}%
+ {%
+ \datagidx@formatlocation
+ \datagidx@current@format\datagidx@current@locationstring
+ }%
+% \end{macrocode}
+% Only interested in the first item, so break out of loop.
+% \begin{macrocode}
+ \@endfortrue
+ }%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\datagidx@formatlocation}
+% \begin{macrocode}
+\newcommand*{\datagidx@formatlocation}[2]{%
+ \ifdefempty{#1}%
+ {#2}%
+ {%
+ \ifcsdef{#1}%
+ {%
+ \csuse{#1}{#2}%
+ }%
+ {%
+ \PackageWarning{datagidx}{Unknown format `#1'}%
+ #2%
+ }%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtldolocationlist}
+% Display the location list.
+% \begin{macrocode}
+\newcommand*{\dtldolocationlist}{%
+ \DTLifnull{\Location}%
+ {}%
+ {%
+ \def\datagidx@prev@location{-1}%
+ \def\datagidx@prev@locationstring{}%
+ \def\datagidx@prev@format{}%
+ \def\datagidx@prev@locationformat{}%
+ \def\datagidx@prev@prefix{}%
+ \def\datagidx@prev@target{}%
+ \def\datagidx@location@sep{}%
+ \def\datagidx@location@start{-1}%
+ \expandafter\forcsvlist\expandafter\datagidx@parse@location
+ \expandafter{\Location}%
+ \do@prevlocation % tidy up loose ends
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\if@dtl@sequential}
+% Conditional to keep track of sequences.
+% \begin{macrocode}
+\newif\if@dtl@sequential
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\datagidx@getlocdo}
+% Handler for \cs{datagidx@docomplist}
+% \begin{macrocode}
+\newcommand*\datagidx@getlocdo[1]{%
+ \ifdefempty\datagidx@current@location
+ {}%
+ {%
+ \eappto\datagidx@current@prefix{%
+ \datagidx@current@location\datagidx@compositor
+ }%
+ }%
+ \def\datagidx@current@location{#1}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\datagidx@getlocation}
+% Get the location and store in \cs{current@location}:
+% \begin{macrocode}
+\def\datagidx@getlocation[#1]#2#3{%
+% \end{macrocode}
+% Store the original value.
+% \begin{macrocode}
+ \def\datagidx@current@locationstring{#2}%
+% \end{macrocode}
+% \begin{macrocode}
+ \bgroup
+ \datagidx@escapelocationformat
+ \xdef\datagidx@current@locationformat{#2}%
+ \datagidx@clearlocationformat
+ \xdef\datagidx@current@location{#2}%
+ \egroup
+% \end{macrocode}
+% If the location contains a compositor, we need to get the final
+% element and store the rest as a prefix:
+% \begin{macrocode}
+ \let\datagidx@list\datagidx@current@location
+ \def\datagidx@current@prefix{}%
+ \def\datagidx@current@location{}%
+ \let\do\datagidx@getlocdo
+ \expandafter\datagidx@docomplist
+ \expandafter{\datagidx@list}%
+% \end{macrocode}
+% Store the format:
+% \begin{macrocode}
+ \def\datagidx@current@format{#1}%
+% \end{macrocode}
+% Store the target:
+% \begin{macrocode}
+ \def\datagidx@current@target{#3}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\datagidx@parse@location}
+% Parses the location list (given in the argument).
+% \begin{macrocode}
+\newcommand*{\datagidx@parse@location}[1]{%
+% \end{macrocode}
+% Parse location format.
+% \begin{macrocode}
+ \datagidx@getlocation#1\relax
+% \end{macrocode}
+% If this is the same as the previous location, do nothing.
+% \begin{macrocode}
+ \ifdefequal{\datagidx@prev@locationstring}{\datagidx@current@locationstring}%
+ {%
+% \end{macrocode}
+% If the format is different, let the non-empty format over-ride
+% the empty format.
+%\changes{2.21}{2014-03-08}{replaced \cs{ifstrequal} with
+%\cs{ifdefequal}}
+% \begin{macrocode}
+ \ifdefequal{\datagidx@prev@format}{\datagidx@current@format}%
+ {%
+ }%
+ {%
+ \ifdefempty{\datagidx@current@format}%
+ {%
+% \end{macrocode}
+% Current format is empty, so keep previous unchanged.
+% \begin{macrocode}
+ }%
+ {%
+ \ifdefempty{\datagidx@prev@format}%
+ {%
+% \end{macrocode}
+% Previous format is empty, so update.
+% \begin{macrocode}
+ \let\datagidx@prev@format\datagidx@current@format
+ }%
+ {%
+ \PackageWarning{datagidx}%
+ {%
+ Conflicting location formats `\datagidx@prev@format' and
+ `\datagidx@current@format' for location `\datagidx@current@location'%
+ }%
+ }%
+ }%
+ }%
+ }%
+ {%
+ \@datagidx@parse@location
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@datagidx@parse@location}
+% \begin{macrocode}
+\newcommand*{\@datagidx@parse@location}{%
+% \end{macrocode}
+% Check if we have a sequence.
+% \begin{macrocode}
+ \@dtl@sequentialtrue
+% \end{macrocode}
+% A change in font format breaks the sequence.
+% \begin{macrocode}
+ \ifdefequal{\datagidx@prev@format}{\datagidx@current@format}%
+ {%
+% \end{macrocode}
+% A change in location format breaks the sequence.
+% \begin{macrocode}
+ \ifdefequal{\datagidx@prev@locationformat}{\datagidx@current@locationformat}%
+ {%
+% \end{macrocode}
+% A change in prefix breaks the sequence.
+% \begin{macrocode}
+ \ifdefequal{\datagidx@prev@prefix}{\datagidx@current@prefix}%
+ {%
+ }%
+ {%
+% \end{macrocode}
+% Prefixes are different, so not a sequence.
+% \begin{macrocode}
+ \@dtl@sequentialfalse
+ }%
+ }%
+ {%
+% \end{macrocode}
+% Formats are different, so not a sequence.
+% \begin{macrocode}
+ \@dtl@sequentialfalse
+ }%
+ }%
+ {%
+% \end{macrocode}
+% Formats are different, so not a sequence.
+% \begin{macrocode}
+ \@dtl@sequentialfalse
+ }%
+ \if@dtl@sequential
+% \end{macrocode}
+% Is this location one more than the previous location?
+% \begin{macrocode}
+ \ifnumequal{\datagidx@prev@location+1}{\datagidx@current@location}%
+ {%
+% \end{macrocode}
+% It is one more than previous value.
+% Is this location the same type as the previous location?
+% \begin{macrocode}
+ \ifdefequal
+ \datagidx@current@locationformat
+ \datagidx@prev@locationformat
+ {%
+% \end{macrocode}
+% They are the same, so we have a sequence.
+% \begin{macrocode}
+ \@dtl@sequentialtrue
+ }%
+ {%
+% \end{macrocode}
+% They aren't the same, so we don't have a sequence.
+% \begin{macrocode}
+ \@dtl@sequentialfalse
+ }%
+ }%
+ {%
+ \@dtl@sequentialfalse
+ }%
+ \fi
+% \end{macrocode}
+% Has the sequence flag been set?
+% \begin{macrocode}
+ \if@dtl@sequential
+% \end{macrocode}
+% Yes, we have a sequence.
+% Has the start of the sequence been set?
+% \begin{macrocode}
+ \ifnumequal{\datagidx@location@start}{-1}%
+ {%
+% \end{macrocode}
+% No it hasn't, so set it
+% \begin{macrocode}
+ \let\datagidx@location@start\datagidx@prev@location
+ \let\datagidx@location@startval\datagidx@prev@locationstring
+ \let\datagidx@location@format\datagidx@prev@format
+ \let\datagidx@location@target\datagidx@prev@target
+ }%
+ {%
+ }%
+ \else
+% \end{macrocode}
+% We don't have a sequence, so do the previous location.
+% \begin{macrocode}
+ \do@prevlocation
+ \fi
+% \end{macrocode}
+% Update previous location macros to this location.
+% \begin{macrocode}
+ \let\datagidx@prev@location\datagidx@current@location
+ \let\datagidx@prev@format\datagidx@current@format
+ \let\datagidx@prev@prefix\datagidx@current@prefix
+ \let\datagidx@prev@locationformat\datagidx@current@locationformat
+ \let\datagidx@prev@locationstring\datagidx@current@locationstring
+ \let\datagidx@prev@target\datagidx@current@target
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLgidxLocationSep}
+% Separator between locations.
+% \begin{macrocode}
+\newcommand*{\DTLgidxLocationSep}{, }
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLgidxLocationF}
+% How to format a location list consisting of only two locations.
+% \begin{macrocode}
+\newcommand*{\DTLgidxLocationF}[2]{%
+ #1\DTLgidxLocationSep#2%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLgidxLocationFF}
+% How to format a location list consisting of three or more locations.
+% \begin{macrocode}
+\newcommand*{\DTLgidxLocationFF}[2]{%
+ #1--#2%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\do@prevlocation}
+% Do the previous location in the current list.
+% \begin{macrocode}
+\newcommand*{\do@prevlocation}{%
+% \end{macrocode}
+% Have we come to the end of a sequence?
+% \begin{macrocode}
+ \ifnumequal{\datagidx@location@start}{-1}%
+ {%
+% \end{macrocode}
+% Not the end of a sequence.
+% \begin{macrocode}
+ \ifdefempty{\datagidx@prev@locationstring}%
+ {}%
+ {%
+ \datagidx@location@sep
+ \datagidxlink{\datagidx@prev@target}%
+ {%
+ \datagidx@formatlocation
+ \datagidx@prev@format\datagidx@prev@locationstring
+ }%
+ \def\datagidx@location@sep{\DTLgidxLocationSep}%
+ }%
+ }%
+ {%
+% \end{macrocode}
+% At the end of a sequence.
+% \begin{macrocode}
+ \datagidx@location@sep
+ \do@locrange
+ \def\datagidx@location@sep{\DTLgidxLocationSep}%
+ \def\datagidx@location@start{-1}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\do@locrange}
+% Format the location range.
+% \begin{macrocode}
+\newcommand*{\do@locrange}{%
+% \end{macrocode}
+% Are the start and end locations 2 or more apart?
+% \begin{macrocode}
+ \ifnumgreater{\datagidx@prev@location}{\datagidx@location@start+1}%
+ {%
+% \end{macrocode}
+% Yes, they are, so form a range:
+% \begin{macrocode}
+ \DTLgidxLocationFF
+ {%
+ \datagidxlink{\datagidx@location@target}%
+ {%
+ \datagidx@formatlocation
+ \datagidx@location@format\datagidx@location@startval
+ }%
+ }%
+ {%
+ \datagidxlink{\datagidx@prev@target}%
+ {%
+ \datagidx@formatlocation
+ \datagidx@prev@format\datagidx@prev@locationstring
+ }%
+ }%
+ }%
+ {%
+% \end{macrocode}
+% No, they aren't so don't form a range:
+%\changes{2.15}{2013-07-10}{removed spurious space}
+% \begin{macrocode}
+ \DTLgidxLocationF
+ {%
+ \datagidxlink{\datagidx@location@target}%
+ {%
+ \datagidx@formatlocation
+ \datagidx@location@format\datagidx@location@startval
+ }%
+ }%
+ {%
+ \datagidxlink{\datagidx@prev@target}%
+ {%
+ \datagidx@formatlocation
+ \datagidx@prev@format\datagidx@prev@locationstring
+ }%
+ }%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\section{Defining New Glossary/Index Databases}
+%
+%\begin{macro}{\datagidx@defaultdatabase}
+% The default database to which terms should be added.
+% \begin{macrocode}
+\newcommand*{\datagidx@defaultdatabase}{}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLgidxSetDefaultDB}
+% Allow user to set the default database
+% \begin{macrocode}
+\newcommand*{\DTLgidxSetDefaultDB}[1]{%
+ \renewcommand*{\datagidx@defaultdatabase}{#1}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%Define keys for \cs{newgidx}:
+% \begin{macrocode}
+\define@key{newgloss}{heading}{\renewcommand*{\datagidx@heading}{#1}}
+\define@key{newgloss}{postheading}{%
+ \renewcommand*{\datagidx@postheading}{#1}%
+}
+% \end{macrocode}
+%\begin{macro}{\ifdatagidxbalance}
+%\changes{2.28}{2017-11-10}{new}
+% \begin{macrocode}
+\newif\ifdatagidxbalance
+\datagidxbalancetrue
+% \end{macrocode}
+%\end{macro}
+% \begin{macrocode}
+\define@choicekey{newgloss}{balance}[\val\nr]{true,false}[true]{%
+ \ifcase\nr\relax
+ \renewcommand*{\datagidx@multicols}{multicols}%
+ \datagidxbalancetrue
+ \or
+ \renewcommand*{\datagidx@multicols}{multicols*}%
+ \datagidxbalancefalse
+ \fi
+}
+\define@key{newgloss}{sort}{\renewcommand*{\datagidx@sort}{#1}}
+% \end{macrocode}
+% Default style is `index':
+% \begin{macrocode}
+\newcommand*{\datagidx@style}{index}
+\define@key{newgloss}{style}{\renewcommand*{\datagidx@style}{#1}}
+% \end{macrocode}
+% Define conditional to determine whether or not to show group
+% headers and do sep. (Default is false.)
+%\begin{macro}{\ifdatagidxshowgroups}
+% \begin{macrocode}
+\newif\ifdatagidxshowgroups
+\newcommand*{\datagidx@showgroups}{false}
+% \end{macrocode}
+%\end{macro}
+% \begin{macrocode}
+\define@choicekey{newgloss}{showgroups}{true,false}[true]%
+{%
+ \renewcommand{\datagidx@showgroups}{#1}%
+}%
+% \end{macrocode}
+%
+%\begin{macro}{\newgidx}
+%\begin{definition}
+% \cs{newgloss}\oarg{options}\marg{database name}\marg{title}
+%\end{definition}
+% Define \cs{newgidx} if it hasn't already been defined by the
+% `highopt' optimize setting.
+% \begin{macrocode}
+\ifundef\newgidx
+{%
+ \newcommand*{\newgidx}{\datagidx@newgidx}
+}%
+{}
+% \end{macrocode}
+% May only be used in the preamble (otherwise the entries will be
+% undefined when their locations are read from the aux file).
+% \begin{macrocode}
+\@onlypreamble\newgidx
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\datagidx@highopt@newgidx}
+% The behaviour of \cs{newgidx} when the `highopt' optimize option has
+% been set.
+% \begin{macrocode}
+\newcommand*{\datagidx@highopt@newgidx}[3][]{%
+% \end{macrocode}
+% Get the file name:
+% \begin{macrocode}
+ \edef\datagidx@indexfilename{\datagidxhighoptfilename{#2}}%
+% \end{macrocode}
+% Has the file been created?
+% \begin{macrocode}
+ \IfFileExists{\datagidx@indexfilename}%
+ {%
+% \end{macrocode}
+% File does exists. Load it.
+% \begin{macrocode}
+ \input{\datagidx@indexfilename}%
+% \end{macrocode}
+% Update the `datagidx' database.
+% \begin{macrocode}
+ \bgroup
+ \setkeys{newgloss}{#1}%
+ \datagidx@newgidx@update{#2}{#3}%
+ \egroup
+ }%
+ {%
+% \end{macrocode}
+% File doesn't exist. Behave as normal.
+% \begin{macrocode}
+ \datagidx@newgidx[#1]{#2}{#3}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\loadgidx}
+%\begin{definition}
+%\cs{loadgidx}\oarg{options}\marg{filename}\marg{title}
+%\end{definition}
+%\changes{2.15}{2013-07-10}{new}
+% Loads a datagidx database.
+% \begin{macrocode}
+\newcommand*{\loadgidx}[3][]{%
+% \end{macrocode}
+% Load database:
+% \begin{macrocode}
+ \input{#2}%
+% \end{macrocode}
+% Update the `datagidx' database. (Assume database is already
+% sorted.)
+% \begin{macrocode}
+ \bgroup
+ \setkeys{newgloss}{sort={},#1}%
+ \expandafter\datagidx@newgidx@update\expandafter
+ {\dtllastloadeddb}{#3}%
+ \egroup
+% \end{macrocode}
+% Set this as the default database:
+% \begin{macrocode}
+ \edef\datagidx@defaultdatabase{\dtllastloadeddb}%
+% \end{macrocode}
+% Assign labels to this database.
+% \begin{macrocode}
+ \dtlforcolumn{\Label}{\dtllastloadeddb}{Label}%
+ {%
+ \csxdef{datagidxentry@\Label}{\dtllastloadeddb}%
+ }%
+}
+% \end{macrocode}
+% May only be used in the preamble (otherwise the entries will be
+% undefined when their locations are read from the aux file).
+% \begin{macrocode}
+\@onlypreamble\loadgidx
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\datagidx@newgidx}
+% The normal behaviour of \cs{newgidx}
+% \begin{macrocode}
+\newcommand*{\datagidx@newgidx}[3][]{%
+\bgroup
+ \setkeys{newgloss}{#1}%
+% \end{macrocode}
+% If no default database has been identified, set the default to
+% this database.
+% \begin{macrocode}
+ \ifdefempty{\datagidx@defaultdatabase}%
+ {\xdef\datagidx@defaultdatabase{#2}}%
+ {}%
+ \DTLgnewdb{#2}%
+ \DTLaddcolumn{#2}{Label}%
+ \DTLaddcolumn{#2}{Location}%
+ \DTLaddcolumn{#2}{CurrentLocation}%
+ \DTLaddcolumn{#2}{FirstId}%
+ \DTLaddcolumn{#2}{Name}%
+ \DTLaddcolumn{#2}{Text}%
+ \DTLaddcolumn{#2}{Parent}%
+ \DTLaddcolumn{#2}{Child}%
+ \DTLaddcolumn{#2}{Description}%
+ \DTLaddcolumn{#2}{Used}%
+ \DTLaddcolumn{#2}{Symbol}%
+ \DTLaddcolumn{#2}{Long}%
+ \DTLaddcolumn{#2}{Short}%
+ \DTLaddcolumn{#2}{See}%
+ \DTLaddcolumn{#2}{SeeAlso}%
+ \datagidx@newgidx@update{#2}{#3}%
+\egroup
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\datagidx@newgidx@update}
+% Update the `datagidx' database.
+% \begin{macrocode}
+\newcommand*{\datagidx@newgidx@update}[2]{%
+ \DTLnewrow{datagidx}%
+ \DTLnewdbentry{datagidx}{Glossary}{#1}%
+ \DTLnewdbentry{datagidx}{Title}{#2}%
+ {%
+ \dtlexpandnewvalue
+ \DTLnewdbentry{datagidx}{Heading}{\expandonce\datagidx@heading}%
+ \DTLnewdbentry{datagidx}{PostHeading}{\expandonce\datagidx@postheading}%
+ \DTLnewdbentry{datagidx}{MultiCols}{\expandonce\datagidx@multicols}%
+ \DTLnewdbentry{datagidx}{Sort}{\expandonce\datagidx@sort}%
+ \DTLnewdbentry{datagidx}{Style}{\expandonce\datagidx@style}%
+ \DTLnewdbentry{datagidx}{ShowGroups}{\expandonce\datagidx@showgroups}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\section{Defining New Terms}
+%
+%\subsection{Options}
+% Define some keys for \cs{newterm}:
+%\begin{macro}{\newterm@label}
+% \begin{macrocode}
+\newcommand*{\newterm@label}{}
+\define@key{newterm}{label}{\renewcommand*{\newterm@label}{#1}}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\newterm@parent}
+% \begin{macrocode}
+\newcommand*{\newterm@parent}{}
+\define@key{newterm}{parent}{\renewcommand*{\newterm@parent}{#1}}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\newterm@text}
+% \begin{macrocode}
+\newcommand*{\newterm@text}{}
+\define@key{newterm}{text}{\renewcommand*{\newterm@text}{#1}}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\newterm@description}
+% \begin{macrocode}
+\newcommand*{\newterm@description}{}
+\define@key{newterm}{description}{%
+ \renewcommand*{\newterm@description}{#1}%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\newterm@plural}
+% \begin{macrocode}
+\define@key{newterm}{plural}{\def\newterm@plural{#1}}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\newterm@sort}
+% \begin{macrocode}
+\newcommand*{\newterm@sort}{}
+\define@key{newterm}{sort}{\renewcommand*{\newterm@sort}{#1}}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\newterm@symbol}
+% \begin{macrocode}
+\newcommand*{\newterm@symbol}{}
+\define@key{newterm}{symbol}{\renewcommand*{\newterm@symbol}{#1}}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\newterm@database}
+% \begin{macrocode}
+\newcommand*{\newterm@database}{}
+\define@key{newterm}{database}{\renewcommand*{\newterm@database}{#1}}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\newterm@long}
+% \begin{macrocode}
+\newcommand*{\newterm@long}{}
+\define@key{newterm}{long}{%
+ \renewcommand*{\newterm@long}{#1}%
+ \def\newterm@longplural{#1s}%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\newterm@short}
+% \begin{macrocode}
+\newcommand*{\newterm@short}{}
+\define@key{newterm}{short}{%
+ \renewcommand*{\newterm@short}{#1}%
+ \def\newterm@shortplural{#1s}%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\newterm@longplural}
+% \begin{macrocode}
+\define@key{newterm}{longplural}{%
+ \def\newterm@longplural{#1}%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\newterm@shortplural}
+% \begin{macrocode}
+\define@key{newterm}{shortplural}{%
+ \def\newterm@shortplural{#1}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\newterm@see}
+% ``see'' should not be used with a location list. If you have a
+% location list and want a cross-reference use ``see also'' instead.
+% \begin{macrocode}
+\newcommand*{\newterm@see}{}
+\define@key{newterm}{see}{%
+ \renewcommand*{\newterm@see}{#1}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\newterm@seealso}
+% ``see also'' should be used with a location list (or with child
+% entries with location lists). If an entry has no location list and
+% not child entries use ``see'' instead.
+% \begin{macrocode}
+\newcommand*{\newterm@seealso}{}
+\define@key{newterm}{seealso}{%
+ \renewcommand*{\newterm@seealso}{#1}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\subsection{New Terms}
+%
+%\begin{macro}{\newterm@defaultshook}
+% \begin{macrocode}
+\newcommand*{\newterm@defaultshook}{}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\newterm@extrafields}
+% \begin{macrocode}
+\newcommand*{\newterm@extrafields}{}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLgidxAssignList}
+% Assignment list used by \ics{printterms}
+% \begin{macrocode}
+\newcommand*{\DTLgidxAssignList}{%
+ \Name=Name,\Description=Description,\Used=Used,\Symbol=Symbol,%
+ \Long=Long,\Short=Short,\LongPlural=LongPlural,\ShortPlural=ShortPlural,%
+ \Location=Location,\See=See,\SeeAlso=SeeAlso,%
+ \Text=Text,\Plural=Plural,\CurrentLocation=CurrentLocation,%
+ \Label=Label,\Parent=Parent,\Children=Child,\FirstId=FirstId,\Sort=Sort%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\datagidxtermkeys}
+% Keys defined for \cs{newterm} corresponding to fields (``name'' is
+% added for convenience).
+% \begin{macrocode}
+\newcommand*{\datagidxtermkeys}{%
+ name,description,symbol,long,short,see,seealso,text,plural,%
+ label,parent,sort%
+}
+% \end{macrocode}
+%\end{macro}
+% Access keys corresponding to given fields
+% \begin{macrocode}
+\newcommand*\@datagidx@fieldkey@Name{name}%
+\newcommand*\@datagidx@fieldkey@Description{description}%
+\newcommand*\@datagidx@fieldkey@Symbol{symbol}%
+\newcommand*\@datagidx@fieldkey@Long{long}%
+\newcommand*\@datagidx@fieldkey@Short{short}%
+\newcommand*\@datagidx@fieldkey@See{see}%
+\newcommand*\@datagidx@fieldkey@SeeAlso{seealso}%
+\newcommand*\@datagidx@fieldkey@Text{text}%
+\newcommand*\@datagidx@fieldkey@Plural{plural}%
+\newcommand*\@datagidx@fieldkey@Label{label}%
+\newcommand*\@datagidx@fieldkey@Parent{parent}%
+\newcommand*\@datagidx@fieldkey@Sort{sort}%
+% \end{macrocode}
+%
+%\begin{macro}{\newtermaddfield}
+%\begin{definition}
+%\cs{newtermaddfield}\oarg{db list}\marg{column key}\marg{new term
+%key}\marg{default value}
+%\end{definition}
+% The default value may contain \ics{field}\marg{key} to get the
+% value of another field.
+% \begin{macrocode}
+\newcommand*{\newtermaddfield}[4][]{%
+% \end{macrocode}
+% If optional argument not specified, iterate over all defined
+% glossaries/indices
+% \begin{macrocode}
+ \ifstrempty{#1}%
+ {%
+ \dtlforcolumn{\datagidx@thisidx}{datagidx}{Glossary}%
+ {%
+ \DTLaddcolumn{\datagidx@thisidx}{#2}%
+ }%
+ }%
+ {%
+ \@for\datagidx@thisidx:=#1\do
+ {%
+ \DTLaddcolumn{\datagidx@thisidx}{#2}%
+ }%
+ }%
+ \expandafter\gdef\csname newterm@#3\endcsname{}%
+ \define@key{newterm}{#3}%
+ {%
+ \expandafter\def\csname newterm@#3\endcsname{##1}%
+ }%
+ \gappto\newterm@defaultshook
+ {%
+ \expandafter\protected@edef\csname newterm@#3\endcsname{#4}%
+ }%
+ \gappto\newterm@extrafields
+ {%
+ \protected@edef\datagidx@value{\csname newterm@#3\endcsname}%
+ \DTLnewdbentry{\newterm@database}{#2}{\expandonce\datagidx@value}%
+ }%
+ \xappto\DTLgidxAssignList
+ {%
+ ,\expandafter\noexpand\csname#2\endcsname=#2%
+ }%
+ \xappto\datagidxtermkeys{,#3}%
+ \expandafter\xdef\csname @datagidx@fieldkey@#2\endcsname{#3}%
+ \xappto\datagidxgetchildfields
+ {%
+ \noexpand\dtlgetentryfromcurrentrow
+ {\expandafter\noexpand\csname#2\endcsname}%
+ {\noexpand\dtlcolumnindex{\noexpand\DTLgidxCurrentdb}{#2}}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\newtermlabelhook}
+% \begin{macrocode}
+\newcommand*{\newtermlabelhook}{}
+% \end{macrocode}
+%\end{macro}
+%
+%
+%\begin{macro}{\DTLgidxNoFormat}
+% \begin{macrocode}
+\newcommand*{\DTLgidxNoFormat}[1]{#1}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLgidxGobble}
+% \begin{macrocode}
+\newcommand*{\DTLgidxGobble}[1]{}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLgidxStripBackslash}
+% Argument must be a control sequence. This is stringified and the
+% first character (The backslash) is removed).
+% \begin{macrocode}
+\newcommand*{\DTLgidxStripBackslash}[1]{%
+ \expandafter\@gobble\string#1%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLgidxName}
+%\begin{definition}
+%\cs{DTLgidxName}\marg{forenames}\marg{surname}
+%\end{definition}
+% How to format a person's name in the text.
+% \begin{macrocode}
+\newcommand*{\DTLgidxName}[2]{%
+ #1\space #2%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLgidxNameNum}
+%\begin{definition}
+%\cs{DTLgidxNameNum}\marg{n}
+%\end{definition}
+% The argument \meta{n} should be a number applied to a name
+% (e.g.\ \verb*"James "\cs{DTLgidxNameNum}{1}). This is converted to
+% a two-digit number for sorting but a Roman numeral for the label
+% and in the text.
+% \begin{macrocode}
+\newcommand*{\DTLgidxNameNum}[1]{\@Roman{#1}}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\datagidx@namenum}
+% Conversion for sort key.
+% \begin{macrocode}
+\newcommand*{\datagidx@namenum}[1]{\two@digits{#1}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLgidxPlace}
+%\begin{definition}
+%\cs{DTLgidxPlace}\marg{country}\marg{town/city}
+%\end{definition}
+% How to format a place in the text.
+% \begin{macrocode}
+\newcommand*{\DTLgidxPlace}[2]{%
+ #2%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLgidxSubject}
+%\begin{definition}
+%\cs{DTLgidxSubject}\marg{main}\marg{category}
+%\end{definition}
+% How to format a subject in the text. Ignore the main part in the
+% text.
+% \begin{macrocode}
+\newcommand*{\DTLgidxSubject}[2]{%
+ #2%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLgidxOffice}
+%\begin{definition}
+%\cs{DTLgidxOffice}\marg{office}\marg{name}
+%\end{definition}
+% Put the office in parentheses in the document text.
+% \begin{macrocode}
+\newcommand*{\DTLgidxOffice}[2]{%
+ #2 (#1)%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLgidxIgnore}
+% Show argument in document text, but disregard in the sort and
+% label.
+% \begin{macrocode}
+\newcommand*{\DTLgidxIgnore}[1]{#1}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLgidxMac}
+%\begin{definition}
+%\cs{DTLgidxMac}\marg{text}
+%\end{definition}
+% In the document, just does \meta{text}, but gets converted to
+% ``Mac'' in the sort key. (Unless overridden by the user.)
+% \begin{macrocode}
+\newcommand*{\DTLgidxMac}[1]{#1}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\datagidx@mac}
+%\cs{DTLgidxMac} gets temporarily redefined to \cs{datagidx@mac}
+%when construction the sort key.
+% \begin{macrocode}
+\newcommand*{\datagidx@mac}[1]{Mac}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLgidxSaint}
+%\begin{definition}
+%\cs{DTLgidxSaint}\marg{text}
+%\end{definition}
+% In the document, just does \meta{text}, but gets converted to
+% ``Saint'' in the sort key. (Unless overridden by the user.)
+% \begin{macrocode}
+\newcommand*{\DTLgidxSaint}[1]{#1}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\datagidx@saint}
+%\cs{DTLgidxMac} gets temporarily redefined to \cs{datagidx@saint}
+%when construction the sort key.
+% \begin{macrocode}
+\newcommand*{\datagidx@saint}[1]{Saint}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLgidxRank}
+%\begin{definition}
+%\cs{DTLgidxRank}\marg{rank}\marg{forenames}
+%\end{definition}
+% A person's title, rank or sanctity should be ignored when sorting.
+% \begin{macrocode}
+\newcommand*{\DTLgidxRank}[2]{#1~#2}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\datagidx@rank}
+%\cs{DTLidxRank} gets temporarily redefined to \cs{datagidx@rank}
+%when constructing the sort key. An extra dot is added to the end to
+%ensure names without a rank are sorted before identical names with
+%a rank.
+% \begin{macrocode}
+\newcommand*{\datagidx@rank}[2]{#2.}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLgidxParticle}
+%\begin{definition}
+%\cs{DTLgidxParticle}\marg{particle}\marg{surname}
+%\end{definition}
+% A particle such as ``of'', ``de'' or ``von'' should be ignored when sorting.
+% \begin{macrocode}
+\newcommand*{\DTLgidxParticle}[2]{#1~#2}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\datagidx@particle}
+%\cs{DTLidxParticle} gets temporarily redefined to \cs{datagidx@particle}
+%when constructing the sort key. An extra dot is added to the end to
+%ensure names without a particle are sorted before identical names with
+%a particle.
+% \begin{macrocode}
+\newcommand*{\datagidx@particle}[2]{#2.}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\datagidx@bothoftwo}
+% \begin{macrocode}
+\newcommand*{\datagidx@bothoftwo}[2]{#1#2}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\datagidx@person}
+% Used when constructing the sort key for a name.
+% \begin{macrocode}
+\newcommand*{\datagidx@person}[2]{#2\noexpand\datatoolpersoncomma #1}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\datagidx@place}
+% Used when constructing the sort key for a place.
+% \begin{macrocode}
+\newcommand*{\datagidx@place}[2]{#2\noexpand\datatoolplacecomma #1}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\datagidx@subject}
+% Used when constructing the sort key for a place.
+% \begin{macrocode}
+\newcommand*{\datagidx@subject}[2]{#2\noexpand\datatoolsubjectcomma #1}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\datagidx@paren}
+% Used when constructing the sort key for a parenthesis.
+% \begin{macrocode}
+\newcommand*{\datagidx@paren}[1]{\noexpand\datatoolparenstart #1}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\datagidx@invert}
+% \begin{macrocode}
+\newcommand*{\datagidx@invert}[2]{#2, #1}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLgidxParen}
+% Parenthetical material.
+% \begin{macrocode}
+\newcommand*{\DTLgidxParen}[1]{\space(#1)}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\datagidxwordifygreek}
+% Convert commands like \ics{alpha} into words for indexing and
+% labelling purposes.
+% \begin{macrocode}
+\newcommand*{\datagidxwordifygreek}{%
+ \def\alpha{alpha}%
+ \def\beta{beta}%
+ \def\gamma{gamma}%
+ \def\delta{delta}%
+ \def\epsilon{epsilon}%
+ \def\varepsilon{epsilon}%
+ \def\zeta{zeta}%
+ \def\eta{eta}%
+ \def\theta{theta}%
+ \def\vartheta{theta}%
+ \def\iota{iota}%
+ \def\kappa{kappa}%
+ \def\lambda{lambda}%
+ \def\mu{mu}%
+ \def\nu{nu}%
+ \def\xi{xi}%
+ \def\pi{pi}%
+ \def\varpi{pi}%
+ \def\rho{rho}%
+ \def\varrho{rho}%
+ \def\sigma{sigma}%
+ \def\varsigma{sigma}%
+ \def\tau{tau}%
+ \def\upsilon{upsilon}%
+ \def\phi{phi}%
+ \def\varphi{phi}%
+ \def\chi{chi}%
+ \def\psi{psi}%
+ \def\omega{omega}%
+ \def\Gamma{Gamma}%
+ \def\Delta{Delta}%
+ \def\Theta{Theta}%
+ \def\Lambda{Lambda}%
+ \def\Xi{Xi}%
+ \def\Pi{Pi}%
+ \def\Sigma{Sigma}%
+ \def\Upsilon{Upsilon}%
+ \def\Phi{Phi}%
+ \def\Psi{Psi}%
+ \def\Omega{Omega}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\datagidxextendedtoascii}
+% Convert commands like \ics{aa} into the closest ASCII equivalent.
+%\changes{2.28}{2017-11-10}{new}
+% \begin{macrocode}
+\newcommand{\datagidxextendedtoascii}{%
+ \def\AE{AE}%
+ \def\ae{ae}%
+ \def\OE{OE}%
+ \def\oe{oe}%
+ \def\AA{AA}%
+ \def\aa{aa}%
+ \def\L{L}%
+ \def\l{l}%
+ \def\O{O}%
+ \def\o{o}%
+ \def\SS{SS}%
+ \def\ss{ss}%
+ \def\th{th}%
+ \def\TH{TH}%
+ \def\dh{dh}%
+ \def\DH{DH}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\datagidxconvertchars}
+% Convert commands like \cs{\&}.
+%\changes{2.28}{2017-11-10}{new}
+% \begin{macrocode}
+\newcommand*{\datagidxconvertchars}{%
+ \let~\space
+ \ifdef\andname
+ {%
+ \let\&\andname
+ }%
+ {%
+ \def\&{\expandafter\@gobble\string\&}%
+ }%
+ \def\_{\string_}%
+ \def\${\string$}%
+ \def\#{\expandafter\@gobble\string\#}%
+ \def\%{\expandafter\@gobble\string\%}%
+ \def\{{\expandafter\@gobble\string\{}%
+ \def\}{\expandafter\@gobble\string\}}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\datagidxstripaccents}
+% Strip accents so they don't interfere with the label and sort.
+% If you want to write your own comparison handler macro, you'll
+% need to redefine this if you want accented letters to be sorted
+% differently from the unaccented version. This command should
+% only be used within a scope.
+% \begin{macrocode}
+\newcommand*{\datagidxstripaccents}{%
+% \end{macrocode}
+% These redefinitions will only work with \cs{edef} or \cs{xdef}:
+% \begin{macrocode}
+ \let\add@accent@\@secondoftwo
+ \let\@text@composite@x\@secondoftwo
+ \let\@tabacckludge\@secondoftwo
+% \end{macrocode}
+% The following are need with \cs{protected@edef} or \cs{protected@xdef}:
+% \begin{macrocode}
+ \expandafter\def\csname \encodingdefault-cmd\endcsname##1##2##3{##3}%
+ \expandafter\def\csname OT1-cmd\endcsname##1##2##3{##3}%
+ \expandafter\def\csname T1-cmd\endcsname##1##2##3{##3}%
+ \expandafter\def\csname PD1-cmd\endcsname##1##2##3{##3}%
+ \def\IeC##1{\@gobbletwo##1}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\newterm}
+%\begin{definition}
+% \cs{newterm}\oarg{options}{name}
+%\end{definition}
+% Defaults to normal behaviour.
+% \begin{macrocode}
+\providecommand{\newterm}{\datagidx@newterm}
+% \end{macrocode}
+%\end{macro}
+%
+%May only be used in the preamble. (Terms must be defined before the
+%aux file is read.)
+% \begin{macrocode}
+\@onlypreamble\newterm
+% \end{macrocode}
+%
+%\begin{macro}{\datagidx@setfieldvalues}
+% Sets the values for all the field.
+% \begin{macrocode}
+\newcommand{\datagidx@setfieldvalues}[2]{%
+% \end{macrocode}
+% Set defaults.
+% \begin{macrocode}
+ \def\newterm@name{#2}%
+ \renewcommand*\newterm@label{#2}%
+ \renewcommand*\newterm@text{#2}%
+ \undef\newterm@plural
+ \renewcommand*{\newterm@description}{}%
+ \renewcommand*{\newterm@sort}{#2}%
+ \renewcommand*{\newterm@symbol}{}%
+ \let\newterm@database\datagidx@defaultdatabase
+ \renewcommand*{\newterm@short}{#2}%
+ \undef\newterm@shortplural
+ \renewcommand*{\newterm@long}{#2}%
+ \undef\newterm@longplural
+ \renewcommand*{\newterm@see}{}%
+ \renewcommand*{\newterm@seealso}{}%
+ \renewcommand*{\newterm@parent}{}%
+% \end{macrocode}
+% Allow hook to access other fields.
+% \begin{macrocode}
+ \let\datagidx@orgfield\field
+ \def\field##1{\expandafter\noexpand\csname newterm@##1\endcsname}%
+% \end{macrocode}
+% Hook to make it easier to add extra fields.
+% \begin{macrocode}
+ \newterm@defaultshook
+ \let\field\datagidx@orgfield
+% \end{macrocode}
+% Assign values given in optional argument.
+% \begin{macrocode}
+ \setkeys{newterm}{#1}%
+% \end{macrocode}
+% Temporary redefine commands likely to be contained in the name
+% that may interfere with the label and sort.
+% \begin{macrocode}
+ \bgroup
+% \end{macrocode}
+% Allow users to, say, specify the name as
+% \meta{name}\ics{glsadd}\marg{other label} without having to specify
+% a separate label.
+% \begin{macrocode}
+ \let\glsadd\@gobble
+% \end{macrocode}
+% Strip common formatting commands.
+% \begin{macrocode}
+ \let\MakeUppercase\DTLgidxNoFormat
+ \let\MakeTextUppercase\DTLgidxNoFormat
+ \let\MakeLowercase\DTLgidxNoFormat
+ \let\MakeTextLowercase\DTLgidxNoFormat
+ \let\acronymfont\DTLgidxNoFormat
+ \let\textrm\DTLgidxNoFormat
+ \let\texttt\DTLgidxNoFormat
+ \let\textsf\DTLgidxNoFormat
+ \let\textsc\DTLgidxNoFormat
+ \let\textbf\DTLgidxNoFormat
+ \let\textmd\DTLgidxNoFormat
+ \let\textit\DTLgidxNoFormat
+ \let\textsl\DTLgidxNoFormat
+ \let\emph\DTLgidxNoFormat
+ \let\textsuperscript\DTLgidxNoFormat
+% \end{macrocode}
+% Convert character commands like \cs{\&}.
+% \begin{macrocode}
+ \datagidxconvertchars
+% \end{macrocode}
+% Strip \cs{ensuremath}.
+% \begin{macrocode}
+ \let\ensuremath\DTLgidxNoFormat
+% \end{macrocode}
+% Ensure that inversions are dealt with for the label.
+% \begin{macrocode}
+ \let\DTLgidxParen\@gobble
+ \let\DTLgidxName\@secondoftwo
+ \let\DTLgidxPlace\datagidx@invert
+ \let\DTLgidxSubject\datagidx@invert
+ \let\DTLgidxOffice\@secondoftwo
+ \let\DTLgidxParticle\datagidx@bothoftwo
+% \end{macrocode}
+% Convert Greek maths (such as \cs{alpha}) to text.
+% \begin{macrocode}
+ \datagidxwordifygreek
+% \end{macrocode}
+% Strip accent commands so they don't interfere with the label.
+% \begin{macrocode}
+ \datagidxstripaccents
+ \datagidxextendedtoascii
+% \end{macrocode}
+% Allow user to hook into this.
+% \begin{macrocode}
+ \newtermlabelhook
+% \end{macrocode}
+%There shouldn't really be any fragile commands in \verb|#2| but
+%using \cs{protected@xdef} to be on the safe side.
+% \begin{macrocode}
+ \protected@xdef\newterm@label{\newterm@label}%
+% \end{macrocode}
+% These commands behave differently for the sort key:
+% \begin{macrocode}
+ \let\DTLgidxName\datagidx@person
+ \let\DTLgidxPlace\datagidx@place
+ \let\DTLgidxSubject\datagidx@subject
+ \let\DTLgidxOffice\datagidx@person
+ \let\DTLgidxParen\datagidx@paren
+ \let\DTLgidxMac\datagidx@mac
+ \let\DTLgidxSaint\datagidx@saint
+ \let\DTLgidxIgnore\@gobble
+ \let\DTLgidxRank\datagidx@rank
+ \let\DTLgidxParticle\datagidx@particle
+ \let\DTLgidxNameNum\datagidx@namenum
+% \end{macrocode}
+%Need to use \cs{protected@xdef} here, which means limited support
+%for stripping accents.
+% \begin{macrocode}
+ \protected@xdef\newterm@sort{\newterm@sort}%
+ \egroup
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\datagidx@add@term}
+% Add term (once all fields have been set. Argument is the name
+% field.
+% \begin{macrocode}
+\newcommand*{\datagidx@add@term}[1]{%
+ \global\cslet{datagidxentry@\newterm@label}{\newterm@database}%
+ \DTLnewrow{\newterm@database}%
+ \DTLnewdbentry{\newterm@database}{Name}{#1}%
+ \DTLnewdbentry{\newterm@database}{Used}{0}%
+ {%
+ \dtlexpandnewvalue
+ \DTLnewdbentry{\newterm@database}{Text}{\expandonce\newterm@text}%
+ \DTLnewdbentry{\newterm@database}{Description}{\expandonce\newterm@description}%
+ \DTLnewdbentry{\newterm@database}{Label}{\expandonce\newterm@label}%
+ \DTLnewdbentry{\newterm@database}{Sort}{\expandonce\newterm@sort}%
+ \DTLnewdbentry{\newterm@database}{Symbol}{\expandonce\newterm@symbol}%
+ \DTLnewdbentry{\newterm@database}{Short}{\expandonce\newterm@short}%
+ \DTLnewdbentry{\newterm@database}{Long}{\expandonce\newterm@long}%
+ \ifundef\newterm@plural
+ {%
+ \DTLnewdbentry{\newterm@database}{Plural}{\expandonce\newterm@text s}%
+ }%
+ {%
+ \DTLnewdbentry{\newterm@database}{Plural}{\expandonce\newterm@plural}%
+ }%
+ \ifundef\newterm@shortplural
+ {%
+ \DTLnewdbentry{\newterm@database}{ShortPlural}{\expandonce\newterm@short s}%
+ }%
+ {%
+ \DTLnewdbentry{\newterm@database}{ShortPlural}{\expandonce\newterm@shortplural}%
+ }%
+ \ifundef\newterm@longplural
+ {%
+ \DTLnewdbentry{\newterm@database}{LongPlural}{\expandonce\newterm@long s}%
+ }%
+ {%
+ \DTLnewdbentry{\newterm@database}{LongPlural}{\expandonce\newterm@longplural}%
+ }%
+ \ifdefempty{\newterm@see}%
+ {}%
+ {\DTLnewdbentry{\newterm@database}{See}{\newterm@see}}%
+ \ifdefempty{\newterm@seealso}%
+ {}%
+ {\DTLnewdbentry{\newterm@database}{SeeAlso}{\newterm@seealso}}%
+% \end{macrocode}
+% Hook to make it easier to add extra fields.
+% \begin{macrocode}
+ \newterm@extrafields
+% \end{macrocode}
+% Add parent, if supplied.
+% \begin{macrocode}
+ \ifdefempty{\newterm@parent}%
+ {}%
+ {%
+ \iftermexists{\newterm@parent}%
+ {%
+ \edef\newterm@parentdatabase{\csuse{datagidxentry@\newterm@parent}}%
+% \end{macrocode}
+% Parent entry must belong to same database as child entry.
+% \begin{macrocode}
+ \ifthenelse{\equal{\newterm@parentdatabase}{\newterm@database}}
+ {%
+ \DTLnewdbentry{\newterm@database}{Parent}{\newterm@parent}%
+ \datagidx@addchild{\newterm@database}{\newterm@parent}{\newterm@label}%
+ }%
+ {%
+ \PackageError{datagidx}%
+ {%
+ Parent entry `\newterm@parent' must belong to the
+ same database as child entry `\newterm@label'%
+ }%
+ {%
+ Parent entry is in database
+ `\newterm@parentdatabase' and child entry is in
+ database `\newterm@database'%
+ }%
+ }%
+ }%
+ {%
+ \PackageError{datagidx}%
+ {%
+ Can't assign parent to `\newterm@label':
+ `\newterm@parent' doesn't exist%
+ }%
+ {}%
+ }%
+ }%
+ }%
+% \end{macrocode}
+% Provide user with a means to access the label of the latest defined
+% term:
+% \begin{macrocode}
+ \global\let\datagidxlastlabel\newterm@label
+% \end{macrocode}
+%\changes{2.14}{2013-06-28}{added \cs{postnewtermhook}}
+% Allow user to hook in here
+% \begin{macrocode}
+ \postnewtermhook
+}%
+%\end{macro}
+%
+%\begin{macro}{\postnewtermhook}
+%\changes{2.14}{2013-06-28}{new}
+% \begin{macrocode}
+\newcommand*{\postnewtermhook}{}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\newtermfield}
+%\changes{2.14}{2013-06-28}{new}
+% Expandable access to field name. (No check for existence of the
+% field. Uses \sty{etoolbox's} \cs{csuse}, so expands to an empty
+% string if the field is undefined.)
+% \begin{macrocode}
+\newcommand*{\newtermfield}[1]{\csuse{newterm@#1}}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\ifnewtermfield}
+%\changes{2.14}{2013-06-28}{new}
+% If the named field (given in first argument) is empty or undefined do third argument,
+% otherwise do second argument.
+% \begin{macrocode}
+\newcommand{\ifnewtermfield}[3]{%
+ \ifcsdef{newterm@#1}
+ {%
+ \ifcsempty{newterm@#1}{#3}{#2}%
+ }%
+ {%
+ #3%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\datagidx@newterm}
+% Normal behaviour for \cs{newterm}
+% \begin{macrocode}
+\newcommand{\datagidx@newterm}[2][]{%
+% \end{macrocode}
+% Assign values to all the fields.
+% \begin{macrocode}
+ \datagidx@setfieldvalues{#1}{#2}%
+% \end{macrocode}
+% Check if database exists.
+% \begin{macrocode}
+ \DTLifdbexists{\newterm@database}%
+ {%
+% \end{macrocode}
+% Database exists. Check if term already exists.
+% \begin{macrocode}
+ \iftermexists{\newterm@label}%
+ {%
+ \PackageError{datagidx}{Term `\newterm@label' already
+ exists in database `\newterm@database'}{}%
+ }%
+ {%
+% \end{macrocode}
+% Add this entry to the database.
+% \begin{macrocode}
+ \datagidx@add@term{#2}%
+ }%
+ }%
+ {%
+% \end{macrocode}
+% Database doesn't exist.
+% \begin{macrocode}
+ \PackageError{datagidx}%
+ {Glossary/index data base `\newterm@database' doesn't exist}%
+ {%
+ You must define the glossary/index data base before you can
+ add any terms to it.%
+ }%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\datagidx@highopt@newterm}
+% Used when high optimized setting enabled. This setting must be
+% switched off if the user wants to modify the database.
+% \begin{macrocode}
+\newcommand{\datagidx@highopt@newterm}[2][]{%
+% \end{macrocode}
+% Assign values to all the fields.
+% \begin{macrocode}
+ \datagidx@setfieldvalues{#1}{#2}%
+% \end{macrocode}
+% Check if database exists.
+% \begin{macrocode}
+ \DTLifdbexists{\newterm@database}%
+ {%
+% \end{macrocode}
+% Database exists. If this is the first run, we need to add the term
+% as usual, otherwise we just need to define
+% \cs{datagidxentry@}\meta{label}
+% \begin{macrocode}
+ \edef\dtl@dogetrow{%
+ \noexpand\dtlgetrowindex
+ {\noexpand\dtl@rowidx}%
+ {\newterm@database}%
+ {%
+ \dtlcolumnindex{\newterm@database}{Label}%
+ }%
+ {\newterm@label}}%
+ \dtl@dogetrow
+ \ifx\dtl@rowidx\dtlnovalue
+% \end{macrocode}
+% Hasn't been defined so add.
+% \begin{macrocode}
+ \datagidx@add@term{#2}%
+% \end{macrocode}
+% Database will need to be sorted.
+% \begin{macrocode}
+ \csdef{datagidx@do@highopt@sort@\newterm@database}{\datagidx@sort}%
+ \else
+% \end{macrocode}
+% Has been defined, so just define \cs{datagidxentry@}\meta{label}
+% and \cs{datagidxlastlabel}
+% \begin{macrocode}
+ \global\cslet{datagidxentry@\newterm@label}{\newterm@database}%
+ \global\let\datagidxlastlabel\newterm@label
+ \fi
+ }%
+ {%
+% \end{macrocode}
+% Database doesn't exist.
+% \begin{macrocode}
+ \PackageError{datagidx}%
+ {Glossary/index data base `\newterm@database' doesn't exist}%
+ {%
+ You must define the glossary/index data base before you can
+ add any terms to it.%
+ }%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%
+%\begin{macro}{\datagidx@addchild}
+% \begin{macrocode}
+\newcommand*{\datagidx@addchild}[3]{%
+ \edef\dtl@dogetrow{%
+ \noexpand\dtlgetrowforvalue
+ {#1}%
+ {%
+ \dtlcolumnindex{\newterm@database}{Label}%
+ }%
+ {#2}}%
+ \dtl@dogetrow
+ \dtlgetentryfromcurrentrow
+ {\datagidx@child}%
+ {\dtlcolumnindex{#1}{Child}}%
+ \ifx\datagidx@child\dtlnovalue
+ \edef\datagidx@child{#3}%
+ \else
+ \edef\datagidx@child{\datagidx@child,#3}%
+ \fi
+ \edef\do@update{\noexpand\dtlupdateentryincurrentrow
+ {Child}{\datagidx@child}}%
+ \do@update
+ \dtlrecombine
+}
+% \end{macrocode}
+%\end{macro}
+%\subsection{Defining Acronyms}
+%\begin{macro}{\newacro}
+%\begin{definition}
+%\cs{newacro}\oarg{options}\marg{short}\marg{long}
+%\end{definition}
+% Shortcut command for acronyms.
+% \begin{macrocode}
+\newcommand{\newacro}[3][]{%
+ \newterm
+ [%
+ description={\capitalisewords{#3}},%
+ short={\acronymfont{#2}},%
+ long={#3},%
+ text={\DTLgidxAcrStyle{#3}{\acronymfont{#2}}},%
+ plural={\DTLgidxAcrStyle{#3s}{\acronymfont{#2s}}},%
+ sort={#2},%
+ #1%
+ ]%
+ {\MakeTextUppercase{#2}}%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\acronymfont}
+% The font to use for the acronym.
+% \begin{macrocode}
+\newcommand*{\acronymfont}[1]{#1}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLgidxAcrStyle}
+%\begin{definition}
+%\cs{DTLgidxAcrStyle}\marg{long}\marg{short}
+%\end{definition}
+% \begin{macrocode}
+\newcommand*{\DTLgidxAcrStyle}[2]{#1 (#2)}
+% \end{macrocode}
+%\end{macro}
+%
+%
+%\section{Conditionals}
+%
+%\begin{macro}{\iftermexists}
+%\begin{definition}
+% \cs{iftermexists}\marg{label}\marg{true part}\marg{false part}
+%\end{definition}
+% Check if term with given label exists.
+% \begin{macrocode}
+\newcommand{\iftermexists}[3]{%
+ \ifcsdef{datagidxentry@#1}{#2}{#3}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\datagidxdb}
+%\changes{2.14}{2013-06-28}{new}
+% Gets the label of database containing the given entry. No check is
+% made for the existence of the entry. Expands to empty if label is
+% undefined.
+% \begin{macrocode}
+\newcommand*{\datagidxdb}[1]{%
+ \csuse{datagidxentry@#1}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\ifentryused}
+%\begin{definition}
+% \cs{ifentryused}\marg{label}\marg{true part}\marg{false part}
+%\end{definition}
+% Check if entry with given label has been used.
+% \begin{macrocode}
+\newcommand*{\ifentryused}[3]{%
+ \letcs{\newterm@database}{datagidxentry@#1}%
+% \end{macrocode}
+% \cs{dtlgetrowforvalue} doesn't expand the value when it checks for
+% a match, so make sure label is fully expanded.
+% \begin{macrocode}
+ \edef\dtl@dogetrow{%
+ \noexpand\dtlgetrowforvalue
+ {\newterm@database}%
+ {%
+ \dtlcolumnindex{\newterm@database}{Label}%
+ }%
+ {#1}}%
+ \dtl@dogetrow
+ \dtlgetentryfromcurrentrow
+ {\datagidx@value}%
+ {\dtlcolumnindex{\newterm@database}{Used}}%
+ \ifnum\datagidx@value=1\relax
+ #2%
+ \else
+ #3%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\section{Unsetting and Resetting}
+%
+%\begin{macro}{\glsreset}
+%\begin{definition}
+%\cs{glsunset}\marg{label}
+%\end{definition}
+% Mark as un-used.
+% \begin{macrocode}
+\newcommand*{\glsreset}[1]{%
+% \end{macrocode}
+% Fetch the name of the database with which this entry is
+% associated.
+% \begin{macrocode}
+ \letcs{\newterm@database}{datagidxentry@#1}%
+% \end{macrocode}
+% Get the row associated with this label and make it the current row.
+% \begin{macrocode}
+ \edef\do@getrow{%
+ \noexpand\dtlgetrowforvalue
+ {\newterm@database}%
+ {\dtlcolumnindex{\newterm@database}{Label}}%
+ {#1}%
+ }%
+ \do@getrow
+% \end{macrocode}
+% Update the "Used" field.
+% \begin{macrocode}
+ \dtlreplaceentryincurrentrow
+ {0}{\dtlcolumnindex{\newterm@database}{Used}}%
+% \end{macrocode}
+% Current row has been edited, so we need to merge the current row
+% back into the database.
+% \begin{macrocode}
+ \dtlrecombine
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\glsunset}
+%\begin{definition}
+%\cs{glsunset}\marg{label}
+%\end{definition}
+% Mark as used without affecting location.
+% \begin{macrocode}
+\newcommand*{\glsunset}[1]{%
+% \end{macrocode}
+% Fetch the name of the database with which this entry is
+% associated.
+% \begin{macrocode}
+ \letcs{\newterm@database}{datagidxentry@#1}%
+% \end{macrocode}
+% Get the row associated with this label and make it the current row.
+% \begin{macrocode}
+ \edef\do@getrow{%
+ \noexpand\dtlgetrowforvalue
+ {\newterm@database}%
+ {\dtlcolumnindex{\newterm@database}{Label}}%
+ {#1}%
+ }%
+ \do@getrow
+% \end{macrocode}
+% Update the "Used" field.
+% \begin{macrocode}
+ \dtlreplaceentryincurrentrow
+ {1}{\dtlcolumnindex{\newterm@database}{Used}}%
+% \end{macrocode}
+% Current row has been edited, so we need to merge the current row
+% back into the database.
+% \begin{macrocode}
+ \dtlrecombine
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\glsresetall}
+%\begin{definition}
+%\cs{glsresetall}\marg{db}
+%\end{definition}
+% Resets all entries in the given database.
+% \begin{macrocode}
+\newcommand*{\glsresetall}[1]{%
+ \def\datagidx@list{}%
+ \dtlforcolumn{\datagidx@label}{#1}{Label}%
+ {%
+ \ifdefempty\datagidx@list
+ {%
+ \let\datagidx@list\datagidx@label
+ }%
+ {%
+ \eappto\datagidx@list{,\datagidx@label}%
+ }%
+ }%
+ \@for\datagidx@thislabel:=\datagidx@list\do
+ {%
+ \glsreset{\datagidx@thislabel}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\glsunsetall}
+%\begin{definition}
+%\cs{glsunsetall}\marg{db}
+%\end{definition}
+% Resets all entries in the given database.
+% \begin{macrocode}
+\newcommand*{\glsunsetall}[1]{%
+ \def\datagidx@list{}%
+ \dtlforcolumn{\datagidx@label}{#1}{Label}%
+ {%
+ \ifdefempty\datagidx@list
+ {%
+ \let\datagidx@list\datagidx@label
+ }%
+ {%
+ \eappto\datagidx@list{,\datagidx@label}%
+ }%
+ }%
+ \@for\datagidx@thislabel:=\datagidx@list\do
+ {%
+ \glsunset{\datagidx@thislabel}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\section{Accessing Entry Information}
+%
+%\begin{macro}{\datagidx@anchorcount}
+% Register to make unique anchors.
+% \begin{macrocode}
+\newcount\datagidx@anchorcount
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\datagidx@formatanchor}
+% Format number using six digits.
+% \begin{macrocode}
+\newcommand*{\datagidx@formatanchor}[1]{%
+ \ifnum#1<10000
+ 0%
+ \ifnum#1<1000
+ 0%
+ \ifnum#1<100
+ 0%
+ \ifnum#1<10
+ 0%
+ \fi
+ \fi
+ \fi
+ \fi
+ \number#1%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@datagidx@escloc}
+% \begin{macrocode}
+\newcommand*{\@datagidx@escloc}[2]{%
+ \expandafter\string\csname#1\endcsname{\noexpand\number#2}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\datagidx@escapelocation}
+% \begin{macrocode}
+\newcommand*{\datagidx@escapelocation}{%
+ \def\@arabic{\@datagidx@escloc{@arabic}}%
+ \def\@roman{\@datagidx@escloc{@roman}}%
+ \def\@Roman{\@datagidx@escloc{@Roman}}%
+ \def\@alph{\@datagidx@escloc{@alph}}%
+ \def\@Alph{\@datagidx@escloc{@Alph}}%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\datagidx@escapelocationformat}
+% \begin{macrocode}
+\newcommand*{\datagidx@escapelocationformat}{%
+ \def\@arabic##1{arabic}%
+ \def\@roman##1{roman}%
+ \def\@Roman##1{Roman}%
+ \def\@alph##1{alph}%
+ \def\@Alph##1{Alph}%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\datagidx@clearlocationformat}
+% \begin{macrocode}
+\newcommand*{\datagidx@clearlocationformat}{%
+ \let\@arabic\@firstofone
+ \let\@roman\@firstofone
+ \let\@Roman\@firstofone
+ \let\@alph\@firstofone
+ \let\@Alph\@firstofone
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLgidxAddLocationType}
+% Allow user to add their own location type. Argument must be
+% control sequence name without initial backslash.
+% \begin{macrocode}
+\newcommand*{\DTLgidxAddLocationType}[1]{%
+ \gappto\datagidx@escapelocation{%
+ \expandafter\def\csname#1\endcsname{\@datagidx@escloc{#1}}%
+ }%
+ \gappto\datagidx@escapelocationformat{%
+ \expandafter\def\csname#1\endcsname##1{#1}%
+ }%
+ \gappto\datagidx@clearlocationformat{%
+ \expandafter\let\csname#1\endcsname\@firstofone
+ }%
+}
+% \end{macrocode}
+% May only be used in the preamble. (Needs to be set before the aux
+% file is read.)
+% \begin{macrocode}
+\@onlypreamble\DTLgidxAddLocationType
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\datagidx@target}
+%\begin{definition}
+%\cs{datagidx@target}\marg{label}\marg{format}\marg{location}\marg{text}
+%\end{definition}
+% Make a target if \cs{hypertarget} has been defined.
+% \begin{macrocode}
+\newcommand*{\datagidx@target}[4]{%
+ \global\advance\datagidx@anchorcount by 1\relax
+ \edef\@datagidx@target{datagidx.\datagidx@formatanchor\datagidx@anchorcount}%
+ \ifstrempty{#3}
+ {%
+ \datagidx@write@usedentry{#1}{}%
+ }%
+ {%
+ \bgroup
+ \datagidx@escapelocation
+% \end{macrocode}
+% Need to prevent \cs{@arabic} etc from being expanded just yet (or it
+% will throw the page numbering out of sync for entries that occur
+% by a page break).
+%\changes{2.15}{2013-07-10}{fixed page breaking bug}
+% \begin{macrocode}
+ \def\@arabic{\noexpand\@arabic}%
+ \def\@roman{\noexpand\@roman}%
+ \def\@Roman{\noexpand\@Roman}%
+ \def\@alph{\noexpand\@alph}%
+ \def\@Alph{\noexpand\@Alph}%
+ \protected@edef\@datagidx@dowriteaux{%
+ \noexpand\datagidx@write@usedentry{#1}%
+ {[#2]{#3}{\@datagidx@target}}%
+ }%
+ \@datagidx@dowriteaux
+ \egroup
+ }%
+ \ifdef\hypertarget
+ {%
+% \end{macrocode}
+% Make sure the current line doesn't scroll off the top of the
+% screen.
+% \begin{macrocode}
+ \datagidxshowifdraft
+ {%
+ [\@datagidx@target]%
+ \discretionary{}{}{}%
+ }%
+ \bgroup
+ \let\glsadd\@gobble
+ \settoheight\dimen@{#4}%
+ \raisebox{\dimen@}%
+ {%
+ \datagidxtarget{\@datagidx@target}{}%
+ }%
+ \egroup
+ }%
+ {%
+ }%
+ \datagidxshowifdraft{[#1]\discretionary{}{}{}}%
+ #4%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\glsdispentry}
+%\begin{definition}
+%\cs{glsdispentry}\marg{label}\marg{field}
+%\end{definition}
+% Short cut that fetches and displays a value.
+% \begin{macrocode}
+\DeclareRobustCommand*{\glsdispentry}[2]{%
+ \DTLgidxFetchEntry{\datagidx@dispentryval}{#1}{#2}%
+ \datagidx@dispentryval
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\Glsdispentry}
+%\begin{definition}
+%\cs{Glsdispentry}\marg{label}\marg{field}
+%\end{definition}
+% As previous but makes the first letter upper case.
+% \begin{macrocode}
+\DeclareRobustCommand*{\Glsdispentry}[2]{%
+ \DTLgidxFetchEntry{\datagidx@dispentryval}{#1}{#2}%
+ \xmakefirstuc\datagidx@dispentryval
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLgidxFetchEntry}
+% Fetch value for the given field for the term identified by
+% \meta{label} and store the value in \meta{cs} (a control sequence).
+% \begin{macrocode}
+\newcommand*{\DTLgidxFetchEntry}[3]{%
+% \end{macrocode}
+% Does this entry exist?
+% \begin{macrocode}
+ \ifcsdef{datagidxentry@#2}%
+ {%
+% \end{macrocode}
+% Fetch the name of the database with which this entry is
+% associated.
+% \begin{macrocode}
+ \letcs{\newterm@database}{datagidxentry@#2}%
+% \end{macrocode}
+% Get the row associated with this label and make it the current row.
+% \begin{macrocode}
+ \edef\do@getrow{%
+ \noexpand\dtlgetrowforvalue
+ {\newterm@database}%
+ {\dtlcolumnindex{\newterm@database}{Label}}%
+ {#2}%
+ }%
+ \do@getrow
+% \end{macrocode}
+% Get the entry for the given field in the current row and store in
+% \meta{cs}.
+% \begin{macrocode}
+ \dtlgetentryfromcurrentrow
+ {#1}%
+ {\dtlcolumnindex{\newterm@database}{#3}}%
+ }%
+ {%
+% \end{macrocode}
+% Entry hasn't been defined.
+% \begin{macrocode}
+ \PackageError{datagidx}{No term `#2' defined}{}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\datagidx@parse@formatlabel}
+%\begin{definition}
+%\cs{parse@formatlabel}\marg{\oarg{format}label}
+%\end{definition}
+% Separate format and label from argument.
+% \begin{macrocode}
+\newcommand*{\datagidx@parse@formatlabel}[1]{%
+ \datagidx@parse@format@label@#1\@endparse@formatlabel@
+}
+\newcommand*\datagidx@parse@format@label@{%
+ \@ifnextchar[{\datagidx@parse@formatlabel@}{\datagidx@parse@formatlabel@[]}%
+}
+\def\datagidx@parse@formatlabel@[#1]#2\@endparse@formatlabel@{%
+ \def\datagidx@format{#1}%
+ \def\datagidx@label{#2}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@datagidx@use@entry}
+%\begin{definition}
+%\cs{@datagidx@use@entry}\marg{link text}
+%\end{definition}
+% The label and format should have been stored in
+% \cs{datagidx@label} and \cs{datagidx@format} before calling this
+% macro.
+%\changes{2.19}{2014-01-17}{renamed \cs{datagidx@use@entry} to
+%\cs{@datagidx@use@entry} and removed redundant field argument}
+% \begin{macrocode}
+\newcommand*{\@datagidx@use@entry}[1]{%
+% \end{macrocode}
+% Does this term exist?
+% \begin{macrocode}
+ \ifcsundef{datagidxentry@\datagidx@label}
+ {%
+ \PackageError{datagidx}{Entry `\datagidx@label' doesn't exist}{}%
+ }%
+ {%
+% \end{macrocode}
+% Fetch the name of the database with which this entry is
+% associated.
+% \begin{macrocode}
+ \letcs{\newterm@database}{datagidxentry@\datagidx@label}%
+% \end{macrocode}
+% Get the row associated with this label and make it the current row.
+% \begin{macrocode}
+ \edef\do@getrow{%
+ \noexpand\dtlgetrowforvalue
+ {\newterm@database}%
+ {\dtlcolumnindex{\newterm@database}{Label}}%
+ {\datagidx@label}%
+ }%
+ \do@getrow
+% \end{macrocode}
+% Get the entry for the "FirstId" field and store in \cs{datagidx@id}
+% \begin{macrocode}
+ \dtlgetentryfromcurrentrow
+ {\datagidx@id}%
+ {\dtlcolumnindex{\newterm@database}{FirstId}}%
+% \end{macrocode}
+% If it hasn't been defined set it.
+% \begin{macrocode}
+ \DTLifnull\datagidx@id
+ {%
+% \end{macrocode}
+% Count register hasn't been updated yet.
+% \begin{macrocode}
+ \count@=\datagidx@anchorcount\relax
+ \advance\count@ by 1\relax
+ \dtlappendentrytocurrentrow{FirstId}{\datagidx@formatanchor\count@}%
+ }%
+ {}%
+% \end{macrocode}
+% Update the "Used" field.
+% \begin{macrocode}
+ \dtlreplaceentryincurrentrow
+ {1}{\dtlcolumnindex{\newterm@database}{Used}}%
+% \end{macrocode}
+% Get the parent entry label (if one exists).
+% \begin{macrocode}
+ \dtlgetentryfromcurrentrow
+ {\datagidx@parent}%
+ {\dtlcolumnindex{\newterm@database}{Parent}}%
+% \end{macrocode}
+% Current row has been edited, so we need to merge the current row
+% back into the database.
+% \begin{macrocode}
+ \dtlrecombine
+% \end{macrocode}
+% If parent hasn't be used, give it an empty location.
+% \begin{macrocode}
+ \datagidx@markparent{\newterm@database}{\datagidx@parent}%
+% \end{macrocode}
+% Write the location to the auxiliary file and display value of
+% field.
+% \begin{macrocode}
+ \datagidx@target{\datagidx@label}{\datagidx@format}%
+ {\csuse{the\DTLgidxCounter}}{#1}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLgidxCounter}
+% The counter used for the location lists.
+% \begin{macrocode}
+\newcommand*{\DTLgidxCounter}{page}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\datagidx@markparent}
+% Assign empty location to parent, if location of that parent is null.
+% (Recursive).
+% \begin{macrocode}
+\newcommand*{\datagidx@markparent}[2]{%
+ \ifx#2\dtlnovalue
+% \end{macrocode}
+% Null parent, so break out of recursion.
+% \begin{macrocode}
+ \else
+% \end{macrocode}
+% Write empty location to the auxiliary file.
+% \begin{macrocode}
+ \datagidx@target{#2}{}{}{}%
+% \end{macrocode}
+% Fetch this parent's parent entry.
+% Get the row associated with this and make it the current row.
+% \begin{macrocode}
+ \edef\do@getrow{%
+ \noexpand\dtlgetrowforvalue
+ {#1}%
+ {\dtlcolumnindex{#1}{Label}}%
+ {#2}}%
+ \do@getrow
+% \end{macrocode}
+% Get the entry for the "FirstId" field and store in \cs{datagidx@id}
+% \begin{macrocode}
+ \dtlgetentryfromcurrentrow
+ {\datagidx@id}%
+ {\dtlcolumnindex{\newterm@database}{FirstId}}%
+% \end{macrocode}
+% If it hasn't been defined set it.
+% \begin{macrocode}
+ \DTLifnull\datagidx@id
+ {%
+ \dtlappendentrytocurrentrow{FirstId}{\datagidx@formatanchor\datagidx@anchorcount}%
+ }%
+ {}%
+% \end{macrocode}
+% Get the parent
+% \begin{macrocode}
+ \dtlgetentryfromcurrentrow
+ {\datagidx@parent}%
+ {\dtlcolumnindex{#1}{Parent}}%
+% \end{macrocode}
+% Current row has been edited, so we need to merge the current row
+% back into the database.
+% \begin{macrocode}
+ \dtlrecombine
+% \end{macrocode}
+% Recurse
+% \begin{macrocode}
+ \datagidx@markparent{#1}{\datagidx@parent}%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\datagidx@write@usedentry}
+% Write out location to aux file and add location to the location
+% list for the current run.
+% \begin{macrocode}
+\newcommand*{\datagidx@write@usedentry}[2]{%
+% \end{macrocode}
+% Do update if `highopt optimize' setting is on.
+% \begin{macrocode}
+ \datagidx@do@highopt@update{#1}%
+% \end{macrocode}
+% Write out location to aux file.
+% \begin{macrocode}
+ \protected@write{\@auxout}{}%
+ {%
+ \string\datagidx@usedentry{#1}{#2}%
+ }%
+% \end{macrocode}
+% Add to this run's location field.
+% \begin{macrocode}
+ \protected@edef\datagidx@do@usedentry{%
+ \noexpand\datagidx@xusedentry{CurrentLocation}{#1}{#2}%
+ }%
+% \end{macrocode}
+% If the location counter is the page counter, defer until after the
+% page break.
+%\changes{2.15}{2013-07-10}{Added check for page counter}
+% \begin{macrocode}
+ \expandafter\ifstrequal\expandafter{\DTLgidxCounter}{page}%
+ {%
+ \expandafter\afterpage\expandafter{\datagidx@do@usedentry}%
+ }%
+ {
+ \datagidx@do@usedentry
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\datagidx@xusedentry}
+%\begin{definition}
+%\cs{datagidx@usedentry}\marg{location tag}\marg{label}\marg{location}
+%\end{definition}
+% Like \cs{datagidx@usedentry} but expands the location. Unlike
+% \cs{datagidx@usedentry} the first argument isn't optional.
+% \begin{macrocode}
+\newcommand*{\datagidx@xusedentry}[3]{%
+ \protected@edef\@datagidx@do@xusedentry{%
+ \noexpand\datagidx@usedentry[#1]{#2}{#3}%
+ }%
+ \@datagidx@do@xusedentry
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\datagidx@usedentry}
+%\begin{definition}
+%\cs{datagidx@usedentry}\oarg{location tag}\marg{label}\marg{location}
+%\end{definition}
+% Add to the location list for the given entry.
+% \begin{macrocode}
+\newcommand*{\datagidx@usedentry}[3][Location]{%
+% \end{macrocode}
+% Check if label exists. (It may have been deleted or had a label
+% change.)
+% \begin{macrocode}
+ \ifcsundef{datagidxentry@#2}%
+ {%
+ \PackageWarning{datagidx}{No term `#2' defined. Ignoring}%
+ }%
+ {%
+% Fetch the name of the database with which this entry is
+% associated.
+% \begin{macrocode}
+ \letcs{\newterm@database}{datagidxentry@#2}%
+% \end{macrocode}
+% Get the row associated with this label and make it the current row.
+% \begin{macrocode}
+ \edef\do@getrow{%
+ \noexpand\dtlgetrowforvalue
+ {\newterm@database}%
+ {\dtlcolumnindex{\newterm@database}{Label}}%
+ {#2}%
+ }%
+ \do@getrow
+% \end{macrocode}
+% \begin{macrocode}
+% Get the entry for the \meta{location tag} field in the current row and store in
+% \cs{datagidx@loc}.
+% \begin{macrocode}
+ \dtlgetentryfromcurrentrow
+ {\datagidx@loc}%
+ {\dtlcolumnindex{\newterm@database}{#1}}%
+% \end{macrocode}
+% Check the success of the previous command.
+% \begin{macrocode}
+ \ifx\datagidx@loc\dtlnovalue
+% \end{macrocode}
+% There's no \meta{location tag} field in the current row, so add one with
+% the given location.
+% \begin{macrocode}
+ \def\datagidx@loc{#3}%
+ \dtlappendentrytocurrentrow{#1}{\expandonce\datagidx@loc}%
+ \else
+% \end{macrocode}
+% There is a \meta{location tag} field in the current row, so append the
+% given location to the list, unless one or the other is empty.
+% \begin{macrocode}
+ \ifdefempty{\datagidx@loc}%
+ {%
+ \def\datagidx@loc{#3}%
+ }%
+ {%
+ \ifstrempty{#3}%
+ {}%
+ {%
+ \appto\datagidx@loc{,#3}%
+ }%
+ }%
+% \end{macrocode}
+% and update the entry in the current row.
+% \begin{macrocode}
+ \expandafter\dtlreplaceentryincurrentrow\expandafter
+ {\datagidx@loc}%
+ {\dtlcolumnindex{\newterm@database}{#1}}%
+ \fi
+% \end{macrocode}
+% Current row has been edited, so we need to merge the current row
+% back into the database.
+% \begin{macrocode}
+ \dtlrecombine
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\datagidx@save@loc}
+% Store the current location from the previous run.
+% \begin{macrocode}
+\newcommand*{\datagidx@save@loc}[2]{%
+ \bgroup
+ \datagidx@escapelocation
+ \xdef\datagidx@tmp{#2}%
+ \egroup
+ \expandafter\xdef\csname datagidx@prev@loc@#1\endcsname{\datagidx@tmp}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\glsadd}
+%\begin{definition}
+%\cs{glsadd}\marg{\oarg{format}label}
+%\end{definition}
+% \begin{macrocode}
+\newcommand*{\glsadd}[1]{%
+ \NoCaseChange{\@glsadd{#1}}%
+}
+\DeclareRobustCommand*{\@glsadd}[1]{%
+% \end{macrocode}
+% Check term has been defined.
+% \begin{macrocode}
+ \ifcsundef{datagidxentry@\datagidx@label}%
+ {%
+ \PackageError{datagidx}{Term `\datagidx@label' doesn't exist}{}%
+ }%
+ {%
+% \end{macrocode}
+% \begin{macrocode}
+ \datagidx@parse@formatlabel{#1}%
+% \end{macrocode}
+% Write the location to the auxiliary file.
+% \begin{macrocode}
+ \datagidx@target{\datagidx@label}{\datagidx@format}%
+ {\csuse{the\DTLgidxCounter}}{}%
+% \end{macrocode}
+% Fetch the name of the database with which this entry is
+% associated.
+% \begin{macrocode}
+ \letcs{\newterm@database}{datagidxentry@\datagidx@label}%
+% \end{macrocode}
+% Get the row associated with this label and make it the current row.
+% \begin{macrocode}
+ \edef\do@getrow{%
+ \noexpand\dtlgetrowforvalue
+ {\newterm@database}%
+ {\dtlcolumnindex{\newterm@database}{Label}}%
+ {\datagidx@label}%
+ }%
+ \do@getrow
+% \end{macrocode}
+% Update the "Used" field.
+% \begin{macrocode}
+ \dtlreplaceentryincurrentrow
+ {1}{\dtlcolumnindex{\newterm@database}{Used}}%
+% \end{macrocode}
+% Get the entry for the "FirstId" field and store in \cs{datagidx@id}
+% \begin{macrocode}
+ \dtlgetentryfromcurrentrow
+ {\datagidx@id}%
+ {\dtlcolumnindex{\newterm@database}{FirstId}}%
+% \end{macrocode}
+% If it hasn't been defined set it.
+% \begin{macrocode}
+ \DTLifnull\datagidx@id
+ {%
+ \dtlappendentrytocurrentrow{FirstId}{\datagidx@formatanchor\datagidx@anchorcount}%
+ }%
+ {}%
+% \end{macrocode}
+% Current row has been edited, so we need to merge the current row
+% back into the database.
+% \begin{macrocode}
+ \dtlrecombine
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\datagidx@count}
+% Loop counter used by \cs{glsaddall}
+% \begin{macrocode}
+\newcount\datagidx@count
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\glsaddall}
+%\begin{definition}
+%\cs{glsaddall}\marg{db}
+%\end{definition}
+% Adds all entries in the given database.
+% \begin{macrocode}
+\newcommand*{\glsaddall}[1]{%
+ \DTLifdbexists{#1}%
+ {%
+ \edef\datagidx@rowcount{\number\DTLrowcount{#1}}%
+ \datagidx@count=0\relax
+ \loop
+ \advance\datagidx@count by 1\relax
+ \dtlgetrow{#1}{\datagidx@count}%
+% \end{macrocode}
+% Get the label for this row.
+%\changes{2.19}{2014-01-17}{Fixed bug in database reference}
+% \begin{macrocode}
+ \dtlgetentryfromcurrentrow
+ {\datagidx@label}%
+ {\dtlcolumnindex{#1}{Label}}%
+% \end{macrocode}
+% Write blank location to the auxiliary file but temporarily undefine
+% \cs{hypertarget} as it doesn't make sense to have a target here.
+% \begin{macrocode}
+ \bgroup
+ \undef\hypertarget
+ \datagidx@target{\datagidx@label}{}{}{}%
+ \egroup
+% \end{macrocode}
+% Update the "Used" field.
+%\changes{2.19}{2014-01-17}{Fixed bug in database reference}
+% \begin{macrocode}
+ \dtlreplaceentryincurrentrow
+ {1}{\dtlcolumnindex{#1}{Used}}%
+% \end{macrocode}
+% Get the entry for the "FirstId" field and store in \cs{datagidx@id}
+%\changes{2.19}{2014-01-17}{Fixed bug in database reference}
+% \begin{macrocode}
+ \dtlgetentryfromcurrentrow
+ {\datagidx@id}%
+ {\dtlcolumnindex{#1}{FirstId}}%
+% \end{macrocode}
+% If it hasn't been defined set it.
+% \begin{macrocode}
+ \DTLifnull\datagidx@id
+ {%
+ \dtlappendentrytocurrentrow{FirstId}{\datagidx@formatanchor\datagidx@anchorcount}%
+ }%
+ {}%
+% \end{macrocode}
+% Current row has been edited, so we need to merge the current row
+% back into the database.
+% \begin{macrocode}
+ \dtlrecombine
+% \end{macrocode}
+% Repeat loop if not finished.
+% \begin{macrocode}
+ \ifnum\datagidx@count<\datagidx@rowcount
+ \repeat
+ }%
+ {%
+ \PackageError{datagidx}{Database `#1' doesn't exist}{}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\glslink}
+%\begin{definition}
+%\cs{glslink}\marg{label}\marg{text}
+%\end{definition}
+% Use given entry but user supplies text.
+% \begin{macrocode}
+\DeclareRobustCommand*{\glslink}[2]{%
+ \datagidx@parse@formatlabel{#1}%
+ \datagidxlink{\datagidx@label}%
+ {%
+ \@datagidx@use@entry{#2}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\useentry}
+%\begin{definition}
+%\cs{useentry}\marg{label}\marg{field}
+%\end{definition}
+% Fetch and use the given field for the given entry.
+% \begin{macrocode}
+\DeclareRobustCommand*{\useentry}[2]{%
+ \datagidx@parse@formatlabel{#1}%
+ \DTLgidxFetchEntry{\datagidx@value}{\datagidx@label}{#2}%
+ \datagidxlink{\datagidx@label}%
+ {%
+ \@datagidx@use@entry{\datagidx@value}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\Useentry}
+%\begin{definition}
+%\cs{Useentry}\marg{label}\marg{field}
+%\end{definition}
+% As \cs{useentry}, but capitalise the first word.
+% \begin{macrocode}
+\DeclareRobustCommand*{\Useentry}[2]{%
+ \datagidx@parse@formatlabel{#1}%
+ \DTLgidxFetchEntry{\datagidx@value}{\datagidx@label}{#2}%
+ \datagidxlink{\datagidx@label}%
+ {%
+ \@datagidx@use@entry{\xmakefirstuc{\datagidx@value}}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\USEentry}
+%\begin{definition}
+%\cs{USEentry}\marg{label}\marg{field}
+%\end{definition}
+% As \cs{useentry}, but make the whole term upper case.
+% \begin{macrocode}
+\DeclareRobustCommand*{\USEentry}[2]{%
+ \datagidx@parse@formatlabel{#1}%
+ \DTLgidxFetchEntry{\datagidx@value}{\datagidx@label}{#2}%
+ \datagidxlink{\datagidx@label}%
+ {%
+ \@datagidx@use@entry{\MakeTextUppercase{\datagidx@value}}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\useentrynl}
+%\begin{definition}
+%\cs{useentrynl}\marg{label}\marg{field}
+%\end{definition}
+% Fetch and use the given field for the given entry without creating
+% a hyperlink.
+% \begin{macrocode}
+\DeclareRobustCommand*{\useentrynl}[2]{%
+ \datagidx@parse@formatlabel{#1}%
+ \DTLgidxFetchEntry{\datagidx@value}{\datagidx@label}{#2}%
+ \@datagidx@use@entry{\datagidx@value}%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\Useentrynl}
+%\begin{definition}
+%\cs{Useentrynl}\marg{label}\marg{field}
+%\end{definition}
+% As \cs{useentry}, but capitalise the first word.
+% \begin{macrocode}
+\DeclareRobustCommand*{\Useentrynl}[2]{%
+ \datagidx@parse@formatlabel{#1}%
+ \DTLgidxFetchEntry{\datagidx@value}{\datagidx@label}{#2}%
+ \@datagidx@use@entry{\xmakefirstuc{\datagidx@value}}%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\USEentrynl}
+%\begin{definition}
+%\cs{USEentrynl}\marg{label}\marg{field}
+%\end{definition}
+% As \cs{useentry}, but make the whole term upper case.
+% \begin{macrocode}
+\DeclareRobustCommand*{\USEentrynl}[2]{%
+ \datagidx@parse@formatlabel{#1}%
+ \DTLgidxFetchEntry{\datagidx@value}{\datagidx@label}{#2}%
+ \@datagidx@use@entry{\MakeTextUppercase{\datagidx@value}}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%
+% Short cuts to common fields.
+%\begin{macro}{\gls}
+% \begin{macrocode}
+\DeclareRobustCommand*{\gls}[1]{\useentry{#1}{Text}}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\glspl}
+% \begin{macrocode}
+\DeclareRobustCommand*{\glspl}[1]{\useentry{#1}{Plural}}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\Gls}
+% \begin{macrocode}
+\DeclareRobustCommand*{\Gls}[1]{\Useentry{#1}{Text}}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\Glspl}
+% \begin{macrocode}
+\DeclareRobustCommand*{\Glspl}[1]{\Useentry{#1}{Plural}}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\glsnl}
+% \begin{macrocode}
+\DeclareRobustCommand*{\glsnl}[1]{\useentrynl{#1}{Text}}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\glsplnl}
+% \begin{macrocode}
+\DeclareRobustCommand*{\glsplnl}[1]{\useentrynl{#1}{Plural}}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\Glsnl}
+% \begin{macrocode}
+\DeclareRobustCommand*{\Glsnl}[1]{\Useentrynl{#1}{Text}}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\Glsplnl}
+% \begin{macrocode}
+\DeclareRobustCommand*{\Glsplnl}[1]{\Useentrynl{#1}{Plural}}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\glssym}
+% \begin{macrocode}
+\DeclareRobustCommand*{\glssym}[1]{\useentry{#1}{Symbol}}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\Glssym}
+% \begin{macrocode}
+\DeclareRobustCommand*{\Glssym}[1]{\Useentry{#1}{Symbol}}
+% \end{macrocode}
+%\end{macro}
+%
+%\subsection{Using Acronyms}
+%\begin{macro}{\DTLgidxFormatAcr}
+%\begin{definition}
+%\cs{DTLgidxFormatAcr}\marg{label}\marg{long field}\marg{short field}
+%\end{definition}
+% \begin{macrocode}
+\newcommand*{\DTLgidxFormatAcr}[3]{%
+ \DTLgidxAcrStyle{\glsdispentry{#1}{#2}}{\useentry{#1}{#3}}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLgidxFormatAcrUC}
+%\begin{definition}
+%\cs{DTLgidxFormatAcr}\marg{label}\marg{long field}\marg{short field}
+%\end{definition}
+%As previous but capitalise first word.
+% \begin{macrocode}
+\newcommand*{\DTLgidxFormatAcrUC}[3]{%
+ \DTLgidxAcrStyle{\Glsdispentry{#1}{#2}}{\useentry{#1}{#3}}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\acr}
+% \begin{macrocode}
+\DeclareRobustCommand*{\acr}[1]{%
+ \ifentryused{#1}%
+ {\useentry{#1}{Short}}%
+ {\DTLgidxFormatAcr{#1}{Long}{Short}}%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\acrpl}
+% \begin{macrocode}
+\DeclareRobustCommand*{\acrpl}[1]{%
+ \ifentryused{#1}%
+ {\useentry{#1}{ShortPlural}}%
+ {\DTLgidxFormatAcr{#1}{LongPlural}{ShortPlural}}%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\Acr}
+% \begin{macrocode}
+\DeclareRobustCommand*{\Acr}[1]{%
+ \ifentryused{#1}%
+ {\Useentry{#1}{Short}}%
+ {\DTLgidxFormatAcrUC{#1}{Long}{Short}}%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\Acrpl}
+% \begin{macrocode}
+\DeclareRobustCommand*{\Acrpl}[1]{%
+ \ifentryused{#1}%
+ {\Useentry{#1}{ShortPlural}}%
+ {\DTLgidxFormatAcrUC{#1}{LongPlural}{ShortPlural}}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\section{Displaying Glossaries, Lists of Acronyms, Indices}
+% Define keys for \cs{printterms}:
+% \begin{macrocode}
+\define@key{printterms}{database}{\renewcommand*{\newterm@database}{#1}}
+% \end{macrocode}
+% Options for post description.
+% \begin{macrocode}
+\define@choicekey{printterms}{postdesc}[\val\nr]%
+ {none,dot}%
+ {%
+ \datagidx@setpostdesc\nr
+ }
+% \end{macrocode}
+% Options for pre-location.
+% \begin{macrocode}
+\define@choicekey{printterms}{prelocation}[\val\nr]%
+ {none,enspace,space,dotfill,hfill}%
+ {%
+ \datagidx@setprelocation\nr
+ }
+% \end{macrocode}
+% How to display the location list.
+% \begin{macrocode}
+\define@choicekey{printterms}{location}[\val\nr]%
+ {hide,list,first}%
+ {\datagidx@setlocation\nr}
+% \end{macrocode}
+% How to format the symbol in relation to the description.
+% \begin{macrocode}
+\define@choicekey{printterms}{symboldesc}[\val\nr]%
+ {symbol,desc,(symbol) desc,desc (symbol),symbol desc,desc symbol}%
+ {\datagidx@formatsymdesc\nr}
+% \end{macrocode}
+% How many columns to have.
+% \begin{macrocode}
+\define@key{printterms}{columns}%
+{%
+ \DTLgidxSetColumns{#1}%
+}
+% \end{macrocode}
+% How to format the name.
+% \begin{macrocode}
+\define@choicekey{printterms}{namecase}[\val\nr]%
+ {nochange,uc,lc,firstuc,capitalise}%
+ {%
+ \datagidx@setnamecase\nr
+ }
+% \end{macrocode}
+% \begin{macrocode}
+\define@key{printterms}{namefont}%
+{%
+ \renewcommand*{\DTLgidxNameFont}[1]{{#1{##1}}}%
+}
+% \end{macrocode}
+% \begin{macrocode}
+\define@key{printterms}{postname}
+{%
+ \renewcommand*{\DTLgidxPostName}{#1}%
+}
+% \end{macrocode}
+% \begin{macrocode}
+\define@choicekey{printterms}{see}[\val\nr]%
+ {comma,brackets,dot,space,nosep,semicolon,location}%
+ {\datagidx@setsee\nr}
+% \end{macrocode}
+%
+% \begin{macrocode}
+\define@choicekey{printterms}{child}[\val\nr]%
+ {named,noname}%
+ {%
+ \datagidx@setchildstyle\nr
+ }
+% \end{macrocode}
+% Symbol width
+% \begin{macrocode}
+\define@key{printterms}{symbolwidth}%
+{%
+ \setlength{\datagidxsymbolwidth}{#1}%
+}
+% \end{macrocode}
+% Location width
+% \begin{macrocode}
+\define@key{printterms}{locationwidth}%
+{%
+ \setlength{\datagidxlocationwidth}{#1}%
+}
+% \end{macrocode}
+% Child sort:
+% \begin{macrocode}
+\define@choicekey{printterms}{childsort}[\val\nr]%
+ {true,false}[true]%
+ {%
+ \datagidx@setchildsort\nr
+ }
+% \end{macrocode}
+% Change style:
+% \begin{macrocode}
+\define@choicekey{printterms}{showgroups}{true,false}[true]{%
+ \appto\newterm@styles{showgroups={#1},}%
+}
+% \end{macrocode}
+% \begin{macrocode}
+\define@key{printterms}{style}{\appto\newterm@styles{style={#1},}}
+% \end{macrocode}
+% \begin{macrocode}
+\define@key{printterms}{heading}{\appto\newterm@styles{heading={#1},}}
+% \end{macrocode}
+% \begin{macrocode}
+\define@key{printterms}{postheading}{%
+ \appto\newterm@styles{postheading={#1},}%
+}
+% \end{macrocode}
+% \begin{macrocode}
+\define@key{printterms}{sort}{\appto\newterm@styles{sort={#1},}}
+% \end{macrocode}
+% \begin{macrocode}
+\define@choicekey{printterms}{balance}[\val\nr]{true,false}[true]{%
+ \ifcase\nr\relax
+ \appto\newterm@styles{balance=true,}%
+ \or
+ \appto\newterm@styles{balance=false,}%
+ \fi
+}
+% \end{macrocode}
+%\begin{macro}{\printterms@condition}
+%\changes{2.14}{2013-06-28}{new}
+% \begin{macrocode}
+\newcommand*{\printterms@condition}{\boolean{true}}
+\define@key{printterms}{condition}{\renewcommand*{\printterms@condition}{#1}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\printtermsstartpar}
+%\changes{2.28}{2017-11-10}{new}
+% \begin{macrocode}
+\newcommand{\printtermsstartpar}{\par}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\printterms@setupmulticol}
+%\changes{2.28}{2017-11-10}{new}
+% \begin{macrocode}
+\newcommand*{\printterms@setupmulticol}{%
+ \ifdefempty\datagidx@postheading
+ {%
+ \edef\datagidx@prestart{%
+ \noexpand\datagidx@heading{\noexpand\datagidx@title}%
+ \noexpand\begin{\datagidx@multicols}{\datagidx@columns}%
+ }%
+ }%
+ {%
+ \edef\datagidx@prestart{%
+ \noexpand\datagidx@heading{\noexpand\datagidx@title}%
+ \noexpand\begin{\datagidx@multicols}{\datagidx@columns}%
+ [\noexpand\datagidx@postheading]%
+ }%
+ }%
+ \edef\datagidx@postend{%
+ \noexpand\end{\datagidx@multicols}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\printterms@setuptwocol}
+%\changes{2.28}{2017-11-10}{new}
+% \begin{macrocode}
+\newcommand*{\printterms@setuptwocol}{%
+ \def\datagidx@prestart{%
+ \twocolumn[\datagidx@heading{\datagidx@title}%
+ \datagidx@postheading]}%
+ \if@twocolumn
+ \def\datagidx@postend{}%
+ \else
+ \def\datagidx@postend{\printtermsrestoreonecolumn}%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\printtermsrestoreonecolumn}
+% \begin{macrocode}
+\newcommand{\printtermsrestoreonecolumn}{\onecolumn}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\printterms}
+%\begin{definition}
+%\cs{printterms}[options]
+%\end{definition}
+% Print the list of terms
+% \begin{macrocode}
+\newcommand{\printterms}[1][]{%
+\bgroup
+% \end{macrocode}
+% Set default database.
+% \begin{macrocode}
+ \let\newterm@database\datagidx@defaultdatabase
+% \end{macrocode}
+% Initialise key list for style:
+% \begin{macrocode}
+ \let\newterm@styles\@empty
+% \end{macrocode}
+% Set options:
+% \begin{macrocode}
+ \setkeys{printterms}{#1}%
+% \end{macrocode}
+% Check if database exists.
+% \begin{macrocode}
+ \DTLifdbexists{\newterm@database}%
+ {%
+% \end{macrocode}
+% Provide user the means to access the current database name.
+% \begin{macrocode}
+ \edef\DTLgidxCurrentdb{\newterm@database}%
+% \end{macrocode}
+% Get the fields from datagidx:
+% \begin{macrocode}
+ \edef\do@getrow{\noexpand\dtlgetrowforvalue
+ {datagidx}%
+ {\dtlcolumnindex{datagidx}{Glossary}}%
+ {\newterm@database}%
+ }%
+ \do@getrow
+ \dtlgetentryfromcurrentrow
+ {\datagidx@title}%
+ {\dtlcolumnindex{datagidx}{Title}}%
+ \dtlgetentryfromcurrentrow
+ {\datagidx@heading}%
+ {\dtlcolumnindex{datagidx}{Heading}}%
+ \dtlgetentryfromcurrentrow
+ {\datagidx@postheading}%
+ {\dtlcolumnindex{datagidx}{PostHeading}}%
+ \dtlgetentryfromcurrentrow
+ {\datagidx@multicols}%
+ {\dtlcolumnindex{datagidx}{MultiCols}}%
+ \dtlgetentryfromcurrentrow
+ {\datagidx@sort}%
+ {\dtlcolumnindex{datagidx}{Sort}}%
+ \dtlgetentryfromcurrentrow
+ {\datagidx@style}%
+ {\dtlcolumnindex{datagidx}{Style}}%
+ \dtlgetentryfromcurrentrow
+ {\datagidx@showgroups}%
+ {\dtlcolumnindex{datagidx}{ShowGroups}}%
+% \end{macrocode}
+% Allow user to override style here.
+% \begin{macrocode}
+ \edef\dtl@do@setkeys{\noexpand\setkeys{newgloss}{\expandonce\newterm@styles}}%
+ \dtl@do@setkeys
+% \end{macrocode}
+% Do we need to use \env{multicols}?
+% \begin{macrocode}
+ \ifnum\datagidx@columns>1\relax
+ \ifnum\datagidx@columns=2\relax
+ \ifdatagidxbalance
+ \printterms@setupmulticol
+ \else
+ \printterms@setuptwocol
+ \fi
+ \else
+ \printterms@setupmulticol
+ \fi
+ \else
+ \def\datagidx@prestart{}%
+ \def\datagidx@postend{}%
+ \fi
+ \let\@dtl@dbname\DTLgidxCurrentdb
+% \end{macrocode}
+% Set the style
+% \begin{macrocode}
+ \csuse{datagidxshowgroups\datagidx@showgroups}%
+ \datagidxsetstyle{\datagidx@style}%
+% \end{macrocode}
+% Now display the glossary/index:
+% \begin{macrocode}
+ \def\datagidx@labellist{}%
+ \ifnum\datagidx@columns=1\relax
+ \datagidx@heading{\datagidx@title}%
+ \datagidx@postheading
+ \fi
+ \datagidx@do@sort
+ \datagidx@prestart
+% \end{macrocode}
+%\changes{2.28}{2017-11-10}{added paragraph break at the start}:
+% \begin{macrocode}
+ \printtermsstartpar
+ \datagidxstart
+ \let\DTLgidxName\datagidx@invert
+ \let\DTLgidxPlace\datagidx@invert
+ \let\DTLgidxSubject\datagidx@invert
+ \let\DTLgidxOffice\datagidx@invert
+ \DTLgidxForeachEntry
+ {%
+ \datagidxitem
+ }%
+ \datagidxend
+ \datagidx@postend
+ }%
+ {%
+% \end{macrocode}
+% Database doesn't exist.
+% \begin{macrocode}
+ \PackageError{datagidx}%
+ {Glossary/index data base `\newterm@database' doesn't exist}%
+ {%
+ You must define the glossary/index data base before you can
+ use it.%
+ }%
+ }%
+\egroup
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\datagidx@getgroup}
+% Get the current group.
+% \begin{macrocode}
+\def\datagidx@getgroup#1#2\datagidx@endgetgroup{%
+ \dtl@setcharcode{#1}{\count@}%
+ \dtlifintclosedbetween{\count@}{48}{57}%
+ {%
+ \gdef\datagidxcurrentgroup{Numbers}%
+ }%
+ {%
+ \dtlifintclosedbetween{\count@}{97}{122}%
+ {%
+ \advance\count@ by -96\relax
+ \xdef\datagidxcurrentgroup{\@Alph\count@}%
+ }%
+ {%
+ \dtlifintclosedbetween{\count@}{65}{90}%
+ {%
+ \gdef\datagidxcurrentgroup{#1}%
+ }%
+ {%
+ \gdef\datagidxcurrentgroup{Symbols}%
+ }%
+ }%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLgidxGroupHeaderTitle}
+% Produce the group title from the group label.
+% \begin{macrocode}
+\newcommand*{\DTLgidxGroupHeaderTitle}[1]{%
+ \ifcsdef{datagidx#1name}
+ {%
+ \csuse{datagidx#1name}%
+ }%
+ {%
+ #1%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLgidxForeachEntry}
+%\begin{definition}
+%\cs{DTLgidxForeachEntry}\marg{body}
+%\end{definition}
+% Iterate through the current database, but only do \meta{body}
+% if there is a location or cross-reference.
+%\changes{2.14}{2013-06-28}{Added optional argument when using
+%\cs{DTLforeach}}
+% \begin{macrocode}
+\newcommand{\DTLgidxForeachEntry}[1]{%
+ \def\datagidxprevgroup{}%
+ \edef\datagidx@doforeachentry{%
+ \noexpand\DTLforeach*[\expandonce\printterms@condition]{\DTLgidxCurrentdb}%
+ {\expandonce\DTLgidxAssignList}
+ }%
+ \datagidx@doforeachentry
+ {%
+% \end{macrocode}
+% Iterate through top-level entries.
+% \begin{macrocode}
+ \DTLifnull{\Parent}%
+ {%
+% \end{macrocode}
+% If there's no location, but there is a current location, then
+% document needs updating.
+% \begin{macrocode}
+ \DTLifnull\Location
+ {%
+ \DTLifnull\CurrentLocation
+ {%
+ }%
+ {%
+% \end{macrocode}
+% We have a current location but not a location.
+% \begin{macrocode}
+ \global\let\@datagidx@dorerun@warn\@data@rerun@warn
+ }%
+ }%
+ {%
+% \end{macrocode}
+% We have a location. Is it up-to-date?
+% \begin{macrocode}
+ \ifcsdef{datagidx@prev@loc@\Label}%
+ {%
+% \end{macrocode}
+% Current location was saved in the previous run. Has it changed?
+%\changes{2.15}{2013-07-10}{expanded and sanitize locations before
+%comparing them}%
+% \begin{macrocode}
+ \protected@edef\@prev@location{%
+ \csname datagidx@prev@loc@\Label\endcsname}%
+ \@onelevel@sanitize\@prev@location
+ \protected@edef\@cur@location{\CurrentLocation}%
+ \@onelevel@sanitize\@cur@location
+ \ifdefequal{\@prev@location}{\@cur@location}%
+ {}%
+ {%
+ \global\let\@datagidx@dorerun@warn\@data@rerun@warn
+ }%
+ }%
+ {%
+% \end{macrocode}
+% Current location wasn't saved last run, so rerun required.
+% \begin{macrocode}
+ \global\let\@datagidx@dorerun@warn\@data@rerun@warn
+ }%
+ }%
+ \datagidx@doifdisplayed
+ {%
+% \end{macrocode}
+% Write current location to file to compare current and previous
+% lists. (Can't compare \cs{Location} with \cs{CurrentLocation} as
+% there may be locations occurring across a page boundary.)
+% \begin{macrocode}
+ \edef\datagidx@dowrite{%
+ \noexpand\protected@write\noexpand\@auxout{}%
+ {%
+ \string\datagidx@save@loc{\Label}{\CurrentLocation}%
+ }%
+ }%
+ \datagidx@dowrite
+% \end{macrocode}
+% Initialise level.
+% \begin{macrocode}
+ \datagidx@level=1\relax
+ \expandafter\datagidx@getgroup\Sort{}\datagidx@endgetgroup
+ #1%
+ \global\let\datagidxprevgroup\datagidxcurrentgroup
+ }%
+ }%
+ {}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\datagidx@doifdisplayed}
+%\begin{definition}
+%\cs{datagidx@doifdisplayed}\marg{body}
+%\end{definition}
+% Do \meta{body} if entry should appear in the glossary/index.
+% \cs{Location}, \cs{See} and \cs{SeeAlso} must be set before use.
+% \begin{macrocode}
+\newcommand{\datagidx@doifdisplayed}[1]{%
+ \DTLifnull{\Location}%
+ {%
+ \DTLifnull{\See}
+ {%
+ \DTLifnull{\SeeAlso}{}%
+ {%
+ #1%
+ }%
+ }%
+ {%
+% \end{macrocode}
+% "See" is not null, but have any of the cross-referenced items been
+% used?
+% \begin{macrocode}
+ \@for\dtl@thislabel:=\See\do
+ {%
+% \end{macrocode}
+% Does the cross-referenced term exist?
+% \begin{macrocode}
+ \iftermexists{\dtl@thislabel}%
+ {%
+% \end{macrocode}
+% Has it been used?
+% \begin{macrocode}
+ \ifentryused{\dtl@thislabel}%
+ {%
+ #1%
+% \end{macrocode}
+% Break out of loop.
+% \begin{macrocode}
+ \@endfortrue
+ }%
+ {}%
+ }%
+ {%
+ }%
+ }%
+ }%
+ }%
+ {%
+ #1%
+ }%
+}%
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\datagidx@level}
+% Keep track of current level
+% \begin{macrocode}
+\newcount\datagidx@level
+% \end{macrocode}
+%\end{macro}
+%\iffalse
+% \begin{macrocode}
+%</datagidx.sty>
+% \end{macrocode}
+%\fi
+%\iffalse
+% \begin{macrocode}
+%<*databib.sty>
+% \end{macrocode}
+%\fi
+%\chapter{databib.sty}
+%\label{sec:src:databib}
+%\section{Package Declaration}
+% \begin{macrocode}
+\NeedsTeXFormat{LaTeX2e}
+\ProvidesPackage{databib}[2018/12/07 v2.31 (NLCT)]
+% \end{macrocode}
+% Load required packages:
+% \begin{macrocode}
+\RequirePackage{datatool}
+% \end{macrocode}
+%\section{Package Options}
+%\begin{macro}{\dtlbib@style}
+%The default bib style is stored in \cs{dtlbib@style}.
+% \begin{macrocode}
+\newcommand*{\dtlbib@style}{plain}
+% \end{macrocode}
+%\end{macro}
+% The \pkgopt[databib]{style} package option sets \cs{dtlbib@style}.
+% \begin{macrocode}
+\define@choicekey{databib.sty}{style}{plain,abbrv,alpha}{%
+\def\dtlbib@style{#1}}
+% \end{macrocode}
+% Process package options:
+% \begin{macrocode}
+\ProcessOptionsX
+% \end{macrocode}
+%\section{Loading BBL file}
+%\begin{macro}{\DTLloadbbl}
+%\begin{definition}
+%\cs{DTLloadbib}\oarg{bbl file}\marg{db name}\marg{bib list}
+%\end{definition}
+% \begin{macrocode}
+\newcommand*{\DTLloadbbl}[3][\jobname.bbl]{%
+\bibliographystyle{databib}%
+\if@filesw
+ \immediate\write\@auxout{\string\bibdata{#3}}%
+\fi
+\DTLnewdb{#2}%
+\edef\DTLBIBdbname{#2}%
+\@input@{#1}}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLnewbibrow}
+% \cs{DTLnewbibrow} adds a new row to the bibliography database.
+% (\cs{DTLBIBdbname} must be set prior to use to the name
+% of the \sty{datatool} database which must exist. Any check
+% to determine its existence should be performed when
+% \cs{DTLBIBdbname} is set.)
+%\changes{1.03}{2009 January 27}{removed check if database exists}
+% \begin{macrocode}
+\newcommand*{\DTLnewbibrow}{\@DTLnewrow{\DTLBIBdbname}}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLnewbibitem}
+%\begin{definition}
+%\cs{DTLnewbibitem}\marg{key}\marg{value}
+%\end{definition}
+% Adds a new database entry with the given key and value.
+%\changes{1.03}{2009 January 27}{removed check if database exists}
+% \begin{macrocode}
+\newcommand*{\DTLnewbibitem}[2]{%
+ \@DTLnewdbentry{\DTLBIBdbname}{#1}{#2}}
+% \end{macrocode}
+%\end{macro}
+%\section{Predefined text}
+%\label{sec:src:bibnames}
+%\begin{macro}{\andname}
+% \begin{macrocode}
+\providecommand*{\andname}{and}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\ofname}
+% \begin{macrocode}
+\providecommand*{\ofname}{of}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\inname}
+% \begin{macrocode}
+\providecommand*{\inname}{in}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\etalname}
+% \begin{macrocode}
+\providecommand*{\etalname}{et al.}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\editorname}
+% \begin{macrocode}
+\providecommand*{\editorname}{editor}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\editorsname}
+% \begin{macrocode}
+\providecommand*{\editorsname}{editors}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\volumename}
+% \begin{macrocode}
+\providecommand*{\volumename}{volume}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\numbername}
+% \begin{macrocode}
+\providecommand*{\numbername}{number}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\pagesname}
+% \begin{macrocode}
+\providecommand*{\pagesname}{pages}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\pagename}
+% \begin{macrocode}
+\providecommand*{\pagename}{page}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\editionname}
+% \begin{macrocode}
+\providecommand*{\editionname}{edition}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\techreportname}
+% \begin{macrocode}
+\providecommand*{\techreportname}{Technical report}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\mscthesisname}
+% \begin{macrocode}
+\providecommand*{\mscthesisname}{Master's thesis}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\phdthesisname}
+% \begin{macrocode}
+\providecommand*{\phdthesisname}{PhD thesis}
+% \end{macrocode}
+%\end{macro}
+%
+%
+%\section{Displaying the bibliography}
+%\label{sec:src:displaybib}
+%\begin{definition}
+%\cs{DTLbibliography}\marg{bib dbname}
+%\end{definition}
+% Displays the bibliography for the database \meta{bib dbname}
+% which must have previously been loaded using
+% \cs{DTLloadbbl}.
+%\begin{macro}{\DTLbibliography}
+% \begin{macrocode}
+\newcommand*{\DTLbibliography}[2][\boolean{true}]{%
+ \begin{DTLthebibliography}[#1]{#2}%
+ \DTLforeachbibentry[#1]{#2}{%
+ \DTLbibitem \DTLformatbibentry \DTLendbibitem
+ }%
+ \end{DTLthebibliography}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLformatbibentry}
+%\begin{definition}
+%\cs{DTLformatbibentry}
+%\end{definition}
+% Formats the current bib entry.
+% \begin{macrocode}
+\newcommand*{\DTLformatbibentry}{%
+% \end{macrocode}
+% Check format for this type is defined.
+% \begin{macrocode}
+ \@ifundefined{DTLformat\DBIBentrytype}%
+ {%
+ \PackageError{databib}{Don't know how to format bibliography
+ entries of type `\DBIBentrytype'}{}%
+ }%
+ {%
+% \end{macrocode}
+% Print information to terminal and log file if in verbose mode.
+% \begin{macrocode}
+ \dtl@message{[\DBIBcitekey]}%
+% \end{macrocode}
+% Initialise
+% \begin{macrocode}
+ \DTLstartsentencefalse\DTLmidsentencefalse\DTLperiodfalse
+% \end{macrocode}
+% Format this entry
+% \begin{macrocode}
+ \csname DTLformat\DBIBentrytype\endcsname
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\gDTLformatbibentry}
+%\begin{definition}
+%\cs{gDTLformatbibentry}
+%\end{definition}
+%\changes{2.21}{2014-03-08}{new}
+% Global version.
+% \begin{macrocode}
+\newcommand*{\gDTLformatbibentry}{%
+% \end{macrocode}
+% Check format for this type is defined.
+% \begin{macrocode}
+ \@ifundefined{DTLformat\DBIBentrytype}%
+ {%
+ \PackageError{databib}{Don't know how to format bibliography
+ entries of type `\DBIBentrytype'}{}%
+ }%
+ {%
+% \end{macrocode}
+% Print information to terminal and log file if in verbose mode.
+% \begin{macrocode}
+ \dtl@message{[\DBIBcitekey]}%
+% \end{macrocode}
+% Initialise
+% \begin{macrocode}
+ \global\DTLstartsentencefalse
+ \global\DTLmidsentencefalse
+ \global\DTLperiodfalse
+% \end{macrocode}
+% Format this entry
+% \begin{macrocode}
+ \csname DTLformat\DBIBentrytype\endcsname
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLformatthisbibentry}
+%\begin{definition}
+%\cs{DTLformatthisbibentry}\marg{db}\marg{cite key}
+%\end{definition}
+%\changes{2.22}{2014-06-10}{new}
+% Just does \cs{DTLformatbibentry} for a given entry.
+% \begin{macrocode}
+\newcommand*{\DTLformatthisbibentry}[2]{%
+ \edef\DBIBname{#1}%
+ \edef\DBIBcitekey{#2}%
+ \edtlgetrowforvalue{#1}{\dtlcolumnindex{#1}{CiteKey}}{\DBIBcitekey}%
+ \dtl@gathervalues{#1}{\dtlcurrentrow}%
+ \letcs{\DBIBentrytype}{@dtl@key@EntryType}%
+ \DTLformatbibentry
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLendbibitem}
+% Hook to add extra information at the end of a bibliography item.
+% This does nothing by default.
+% \begin{macrocode}
+\newcommand*{\DTLendbibitem}{}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLwidest}
+%Define a length to store the widest bib entry label
+% \begin{macrocode}
+\newlength\dtl@widest
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLcomputewidestbibentry}
+%\begin{definition}
+%\cs{DTLcomputewidestbibentry}\marg{conditions}\marg{db
+%name}\marg{bib label}\marg{cmd}
+%\end{definition}
+%Computes the widest bibliography entry over all entries satisfying
+%\meta{condition} for the database called \meta{db name}, where
+% the bibliography label is formated according to \meta{bib label} and
+% stores the result in \meta{cmd} which must be a command name.
+% \begin{macrocode}
+\newcommand*{\DTLcomputewidestbibentry}[4]{%
+\dtl@widest=0pt\relax
+\let#4=\@empty
+\DTLforeachbibentry[#1]{#2}{%
+\settowidth{\dtl@tmplength}{#3}%
+\ifdim\dtl@tmplength>\dtl@widest\relax
+ \dtl@widest=\dtl@tmplength
+ \protected@edef#4{#3}%
+\fi
+}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLforeachbibentry}
+%\begin{definition}
+%\cs{DTLforeachbibentry}\oarg{condition}\marg{db name}\marg{text}
+%\end{definition}
+%\begin{definition}
+%\cs{DTLforeachbibentry*}\oarg{condition}\marg{db name}\marg{text}
+%\end{definition}
+% Iterates through the database called \meta{db name} and does
+% \meta{text} if \meta{condition} is met. As with
+% \cs{DTLforeach}, the starred version is read only.
+%\changes{2.21}{2014-03-08}{fixed bug in starred version}
+% \begin{macrocode}
+\newcommand*{\DTLforeachbibentry}{%
+\@ifstar\@sDTLforeachbibentry\@DTLforeachbibentry}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@DTLforeachbibentry}
+% Unstarred version
+% \begin{macrocode}
+\newcommand*{\@DTLforeachbibentry}[3][\boolean{true}]{%
+% \end{macrocode}
+% Store database name.
+% \begin{macrocode}
+ \edef\DBIBname{#2}%
+% \end{macrocode}
+% Reset row counter.
+% \begin{macrocode}
+ \setcounter{DTLbibrow}{0}%
+% \end{macrocode}
+% Iterate through the database.
+% \begin{macrocode}
+ \@DTLforeach{#2}{\DBIBcitekey=CiteKey,\DBIBentrytype=EntryType}%
+ {%
+ \dtl@gathervalues{#2}{\dtlcurrentrow}%
+ \ifthenelse{#1}{\refstepcounter{DTLbibrow}#3}{}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@sDTLforeachbibentry}
+% Starred version
+% \begin{macrocode}
+\newcommand*{\@sDTLforeachbibentry}[3][\boolean{true}]{%
+% \end{macrocode}
+% Store database name.
+% \begin{macrocode}
+ \edef\DBIBname{#2}%
+% \end{macrocode}
+% Reset row counter.
+% \begin{macrocode}
+ \setcounter{DTLbibrow}{0}%
+% \end{macrocode}
+% Iterate through the database (read only).
+% \begin{macrocode}
+ \@sDTLforeach{#2}{\DBIBcitekey=CiteKey,\DBIBentrytype=EntryType}%
+ {%
+ \dtl@gathervalues{#2}{\dtlcurrentrow}%
+ \ifthenelse{#1}{\refstepcounter{DTLbibrow}#3}{}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\gDTLforeachbibentry}
+%\begin{definition}
+%\cs{gDTLforeachbibentry}\oarg{condition}\marg{db name}\marg{text}
+%\end{definition}
+%\begin{definition}
+%\cs{gDTLforeachbibentry*}\oarg{condition}\marg{db name}\marg{text}
+%\end{definition}
+% Global version.
+%\changes{2.21}{2014-03-08}{new}
+% \begin{macrocode}
+\newcommand{\gDTLforeachbibentry}{%
+\@ifstar\@sgDTLforeachbibentry\@gDTLforeachbibentry}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@gDTLforeachbibentry}
+%\changes{2.21}{2014-03-08}{new}
+% Unstarred version
+% \begin{macrocode}
+\newcommand*{\@gDTLforeachbibentry}[3][\boolean{true}]{%
+% \end{macrocode}
+% Store database name.
+% \begin{macrocode}
+ \xdef\DBIBname{#2}%
+% \end{macrocode}
+% Reset row counter.
+% \begin{macrocode}
+ \global\c@DTLbibrow = 0\relax
+% \end{macrocode}
+% Iterate through the database.
+% \begin{macrocode}
+ \@DTLforeach{#2}{\DBIBcitekey=CiteKey,\DBIBentrytype=EntryType}%
+ {%
+ \dtl@g@gathervalues{#2}{\dtlcurrentrow}%
+ \ifthenelse{#1}%
+ {%
+ \refstepcounter{DTLbibrow}%
+ \global\c@DTLbibrow=\c@DTLbibrow
+ #3%
+ }%
+ {}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@sgDTLforeachbibentry}
+%\changes{2.21}{2014-03-08}{new}
+% Starred version
+% \begin{macrocode}
+\newcommand*{\@sgDTLforeachbibentry}[3][\boolean{true}]{%
+% \end{macrocode}
+% Store database name.
+% \begin{macrocode}
+ \xdef\DBIBname{#2}%
+% \end{macrocode}
+% Reset row counter.
+% \begin{macrocode}
+ \global\c@DTLbibrow = 0\relax
+% \end{macrocode}
+% Iterate through the database (read only).
+% \begin{macrocode}
+ \@sDTLforeach{#2}{\DBIBcitekey=CiteKey,\DBIBentrytype=EntryType}%
+ {%
+ \dtl@g@gathervalues{#2}{\dtlcurrentrow}%
+ \ifthenelse{#1}%
+ {%
+ \refstepcounter{DTLbibrow}%
+ \global\c@DTLbibrow=\c@DTLbibrow
+ #3%
+ }%
+ {}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{counter}{DTLbibrow}
+%The counter \ctrfmt{DTLbibrow} keeps track of the current
+%row in the body of \cs{DTLforeachbibentry}. (You can't rely on
+%\ctr{DTLrowi}, \ctr{DTLrowii} and
+% \ctr{DTLrowiii}, as \cs{DTLforeachbibentry} pass the
+% conditions to the optional argument of \cs{DTLforeach}, but
+% instead uses \cs{ifthenelse}, which means that \ctr{DTLrowi}
+% etc will be incremented, even when the given condition is not met.)
+% \begin{macrocode}
+\newcounter{DTLbibrow}
+% \end{macrocode}
+%\end{counter}
+%\begin{macro}{\theHDTLbibrow}
+% Keep \sty{hyperref} happy:
+% \begin{macrocode}
+\def\theHDTLbibrow{\theHDTLrow.bib.\arabic{DTLbibrow}}%
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLbibfield}
+%\begin{definition}
+%\cs{DTLbibfield}\marg{field name}
+%\end{definition}
+% Gets the value assigned to the field \meta{field name} for
+% the current row of \cs{DTLforeachbibentry}. (Doesn't check if
+% the field exists, or if it is being used within
+% \cs{DTLforeachbibentry}.)
+% \begin{macrocode}
+\newcommand*{\DTLbibfield}[1]{\csname @dtl@key@#1\endcsname}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLbibfieldlet}
+%\begin{definition}
+%\cs{DTLbibfield}\marg{cs}\marg{field name}
+%\end{definition}
+% Gets the value assigned to the field \meta{field name} for
+% the current row of \cs{DTLforeachbibentry} and assigns it to the
+% control sequence \meta{cs}. (Doesn't check if
+% the field exists, or if it is being used within
+% \cs{DTLforeachbibentry}.)
+% \begin{macrocode}
+\newcommand*{\DTLbibfieldlet}[2]{%
+ \letcs{#1}{@dtl@key@#2}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLifbibfieldexists}
+%\begin{definition}
+%\cs{DTLifbibfieldexists}\marg{field name}\marg{true part}\marg{false
+%part}
+%\end{definition}
+%Determines whether the given field name exists for the current
+% row of \cs{DTLforeachbibentry}.
+% \begin{macrocode}
+\newcommand*{\DTLifbibfieldexists}[3]{%
+\@ifundefined{@dtl@key@#1}{#3}{%
+\expandafter\DTLifnull\csname @dtl@key@#1\endcsname
+{#3}{#2}}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLifanybibfieldexists}
+%\begin{definition}
+%\cs{DTLifanybibfieldexists}\marg{list of field name}\marg{true part}\marg{false
+%part}
+%\end{definition}
+% Determines whether any of the listed fields exist for the current
+% row of \cs{DTLforeachbibentry}.
+% \begin{macrocode}
+\newcommand*{\DTLifanybibfieldexists}[3]{%
+\@for\dtl@thisfield:=#1\do{%
+\@ifundefined{@dtl@key@\dtl@thisfield}{}{%
+\expandafter\DTLifnull\csname @dtl@key@\dtl@thisfield\endcsname
+{}{%
+\@endfortrue}}}%
+\if@endfor
+ #2%
+\else
+ #3%
+\fi
+\@endforfalse
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\ifDTLperiod}
+% The conditional \cs{ifDTLperiod} is used to keep track of any
+% abbreviations ending with a period, this is to ensure that
+% abbreviations aren't followed by a full stop if they already
+% have a full stop terminating the abbreviation.
+% \begin{macrocode}
+\newif\ifDTLperiod
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLcheckendsperiod}
+%\begin{definition}
+%\cs{DTLcheckendperiod}\marg{string}
+%\end{definition}
+% Checks if \meta{string} ends with a full stop. This sets
+% \cs{ifDTLperiod}.
+% \begin{macrocode}
+\newcommand*{\DTLcheckendsperiod}[1]{%
+\dtl@checkendsperiod#1\@nil\relax}
+% \end{macrocode}
+% \begin{macrocode}
+\def\dtl@checkendsperiod#1#2{%
+\def\@dtl@argi{#1}\def\@dtl@argii{#2}%
+\def\@dtl@period{.}%
+\ifx\@dtl@argi\@nnil
+ \global\DTLperiodfalse
+ \let\@dtl@donext=\relax
+\else
+ \ifx\@dtl@argii\@nnil
+ \ifx\@dtl@argi\@dtl@period
+ \global\DTLperiodtrue
+ \else
+ \global\DTLperiodfalse
+ \fi
+ \let\@dtl@donext=\@gobble
+ \else
+ \let\@dtl@donext=\dtl@checkendsperiod
+ \fi
+\fi
+\@dtl@donext{#2}%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLcheckbibfieldendsperiod}
+%\begin{definition}
+%\cs{DTLcheckbibfieldendperiod}\marg{label}
+%\end{definition}
+% Checks if the bib field \meta{label} ends with a full stop.
+% This sets \cs{ifDTLperiod}.
+% \begin{macrocode}
+\newcommand*{\DTLcheckbibfieldendsperiod}[1]{%
+\protected@edef\@dtl@tmp{\DTLbibfield{#1}}%
+\expandafter\DTLcheckendsperiod\expandafter{\@dtl@tmp}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\ifDTLmidsentence}
+%\begin{definition}
+%\cs{ifDTLmidsentence}
+%\end{definition}
+% Determine whether we are in the middle
+% of a sentence.
+% \begin{macrocode}
+\newif\ifDTLmidsentence
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\ifDTLstartsentence}
+%\begin{definition}
+%\cs{ifDTLstartsentence}
+%\end{definition}
+% Determine whether we are at the start
+% of a sentence.
+% \begin{macrocode}
+\newif\ifDTLstartsentence
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLaddperiod}
+%\begin{definition}
+%\cs{DTLaddperiod}
+%\end{definition}
+%Adds a full stop and sets \cs{DTLmidsentencefalse},
+%\cs{DTLstartsentencetrue} and
+%\cs{DTLperiodfalse}.
+% \begin{macrocode}
+\newcommand*{\DTLaddperiod}{\DTLmidsentencefalse\DTLperiodfalse
+\DTLstartsentencetrue
+\ifDTLperiod\else.\fi}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLaddcomma}
+%\begin{definition}
+%\cs{DTLaddcomma}
+%\end{definition}
+%Adds a comma and sets \cs{DTLmidsentencetrue}, \cs{DTLperiodfalse}
+%and \cs{DTLstartsentencefalse}
+% \begin{macrocode}
+\newcommand*{\DTLaddcomma}{, \DTLmidsentencetrue
+\DTLperiodfalse\DTLstartsentencefalse}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLstartsentencespace}
+%Adds a space if at the start of the sentence, otherwise does
+% nothing. (The space between sentences is added this way, rather
+% than in \cs{DTLaddperiod} otherwise spurious extra space can
+% occur at the end of the bib item. The spacefactor needs to be
+% set manually, because there's stuff in the way of the previous
+% sentence's full stop and this space which confuses the inter
+% sentence spacing (and, of course, the previous sentence could
+% have ended with a capital letter.)
+% \begin{macrocode}
+\newcommand*{\DTLstartsentencespace}{%
+\ifDTLstartsentence\spacefactor=\sfcode`\.\relax\space
+\fi\DTLstartsentencefalse}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLtwoand}
+% In a list of only two author (or editor) names, the text between the
+% two names is given by \cs{DTLtwoand}:
+% \begin{macrocode}
+\newcommand*{\DTLtwoand}{\ \andname\ }
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLandlast}
+% In a list of author (or editor) names, the text between the
+% penultimate and last name is given by \cs{DTLandlast}:
+% \begin{macrocode}
+\newcommand*{\DTLandlast}{, \andname\ }
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLandnotlast}
+% In a list of author (or editor) names, the text between the
+% names (except the penultimate and last name) is given by
+% \cs{DTLandnotlast}:
+% \begin{macrocode}
+\newcommand*{\DTLandnotlast}{, }
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtl@authorcount}
+% Define a count register to keep track of the number of authors:
+% \begin{macrocode}
+\newcount\@dtl@authorcount
+% \end{macrocode}
+%\end{macro}
+%\begin{counter}{DTLmaxauthors}
+% The counter \ctrfmt{DTLmaxauthors} indicates the maximum number of
+% author names to display, if there are more than that number,
+% \cs{etalname} is used.
+% \begin{macrocode}
+\newcounter{DTLmaxauthors}
+\setcounter{DTLmaxauthors}{10}
+% \end{macrocode}
+%\end{counter}
+%\begin{macro}{\DTLformatauthorlist}
+% Format a list of author names (the list is stored in
+% \cs{@dtl@key@Author}):
+% \begin{macrocode}
+\newcommand*{\DTLformatauthorlist}{%
+\DTLifbibfieldexists{Author}{%
+\DTLstartsentencespace
+\@dtl@authorcount=0\relax
+\@for\@dtl@author:=\@dtl@key@Author\do{%
+\advance\@dtl@authorcount by 1\relax}%
+\@dtl@tmpcount=0\relax
+\ifnum\@dtl@authorcount>\c@DTLmaxauthors
+{%
+ \@for\@dtl@author:=\@dtl@key@Author\do{%
+ \advance\@dtl@tmpcount by 1\relax
+ \ifnum\@dtl@tmpcount=1\relax
+ \expandafter\DTLformatauthor\@dtl@author
+ \else
+ \ifnum\@dtl@tmpcount>\c@DTLmaxauthors
+ \DTLandnotlast \etalname
+ \expandafter\DTLcheckendsperiod\expandafter{\etalname}%
+ \@endfortrue
+ \else
+ \DTLandnotlast \expandafter\DTLformatauthor\@dtl@author
+ \fi
+ \fi
+ }%
+}%
+\else
+ \@for\@dtl@author:=\@dtl@key@Author\do{%
+ \advance\@dtl@tmpcount by 1\relax
+ \ifnum\@dtl@tmpcount=1\relax
+ \expandafter\DTLformatauthor\@dtl@author
+ \else
+ \ifnum\@dtl@tmpcount=\@dtl@authorcount
+ \ifnum\@dtl@authorcount=2\relax
+ \DTLtwoand
+ \else
+ \DTLandlast
+ \fi
+ \expandafter\DTLformatauthor\@dtl@author
+ \else
+ \DTLandnotlast \expandafter\DTLformatauthor\@dtl@author
+ \fi
+ \fi
+ }%
+\fi
+}{}%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{counter}{DTLmaxeditors}
+% The counter \ctrfmt{DTLmaxeditors} indicates the maximum number of
+% editor names to display, if there are more than that number,
+% \cs{etalname} is used.
+% \begin{macrocode}
+\newcounter{DTLmaxeditors}
+\setcounter{DTLmaxeditors}{10}
+% \end{macrocode}
+%\end{counter}
+%
+%\begin{macro}{\DTLformateditorlist}
+% Format a list of editor names (the list is stored in
+% \cs{@dtl@key@Editor}):
+% \begin{macrocode}
+\newcommand*{\DTLformateditorlist}{%
+\DTLifbibfieldexists{Editor}{%
+\DTLstartsentencespace
+\@dtl@authorcount=0\relax
+\@for\@dtl@author:=\@dtl@key@Editor\do{%
+\advance\@dtl@authorcount by 1\relax}%
+\@dtl@tmpcount=0\relax
+\ifnum\@dtl@authorcount>\c@DTLmaxeditors
+{%
+ \@for\@dtl@author:=\@dtl@key@Editor\do{%
+ \advance\@dtl@tmpcount by 1\relax
+ \ifnum\@dtl@tmpcount=1\relax
+ \expandafter\DTLformateditor\@dtl@author
+ \else
+ \ifnum\@dtl@tmpcount>\c@DTLmaxeditors
+ \DTLandnotlast \etalname
+ \expandafter\DTLcheckendsperiod\expandafter{\etalname}%
+ \@endfortrue
+ \else
+ \DTLandnotlast \expandafter\DTLformateditor\@dtl@author
+ \fi
+ \fi
+ }%
+}%
+\else
+\@for\@dtl@author:=\@dtl@key@Editor\do{%
+ \advance\@dtl@tmpcount by 1\relax
+ \ifnum\@dtl@tmpcount=1\relax
+ \expandafter\DTLformateditor\@dtl@author
+ \else
+ \ifnum\@dtl@tmpcount=\@dtl@authorcount
+ \ifnum\@dtl@authorcount=2\relax
+ \DTLtwoand
+ \else
+ \DTLandlast
+ \fi
+ \expandafter\DTLformateditor\@dtl@author
+ \else
+ \DTLandnotlast \expandafter\DTLformateditor\@dtl@author
+ \fi
+ \fi
+ }%
+\fi
+,
+\ifnum\@dtl@authorcount=1\relax
+ \editorname
+ \expandafter\DTLcheckendsperiod\expandafter{\editorname}%
+\else
+ \editorsname
+ \expandafter\DTLcheckendsperiod\expandafter{\editorsname}%
+\fi
+}{}%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLformatsurnameonly}
+%\begin{definition}
+%\cs{DTLformatsurnameonly}\marg{von part}\marg{surname}\marg{jr
+%part}\marg{forenames}
+%\end{definition}
+% This is used when only the surname should be displayed. (The
+% final argument, \meta{forenames}, is ignored.)
+% \begin{macrocode}
+\newcommand*{\DTLformatsurnameonly}[4]{%
+\DTLstartsentencespace
+\def\@dtl@tmp{#1}%
+\ifx\@dtl@tmp\@empty\else#1~\fi
+#2%
+\def\@dtl@tmp{#3}%
+\ifx\@dtl@tmp\@empty
+ \DTLcheckendsperiod{#2}%
+\else
+ , #3%
+ \DTLcheckendsperiod{#3}%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLformatforenames}
+%\begin{definition}
+%\cs{DTLformatforenames}\marg{forenames}
+%\end{definition}
+% The format of an author/editor's forenames. If the forenames
+% occur at the start of sentence, a new sentence space is added.
+% The argument is checked to determine whether it ends with a
+% full stop (sometimes the forenames may include initials.)
+% \begin{macrocode}
+\newcommand*{\DTLformatforenames}[1]{%
+\DTLstartsentencespace
+#1%
+\DTLcheckendsperiod{#1}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLformatabbrvforenames}
+%\begin{definition}
+%\cs{DTLformatabbrvforenames}\marg{forenames}
+%\end{definition}
+% The format of an author/editor's abbreviated forenames. The initials
+% may or may not end in a full stop depending on the commands
+% governing the format of \cs{DTLstoreinitials}, so the initials
+% need to be check using \cs{DTLcheckendsperiod}.
+% \begin{macrocode}
+\newcommand*{\DTLformatabbrvforenames}[1]{%
+\DTLstartsentencespace
+\DTLstoreinitials{#1}{\@dtl@tmp}\@dtl@tmp
+\expandafter\DTLcheckendsperiod\expandafter{\@dtl@tmp}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLformatvon}
+%\begin{definition}
+%\cs{DTLformatvon}\marg{von part}
+%\end{definition}
+% The format of the ``von'' part. This does nothing if the argument
+% is empty, otherwise it does the argument followed by a
+% non-breakable space.
+% \begin{macrocode}
+\newcommand*{\DTLformatvon}[1]{%
+\DTLstartsentencespace
+\def\@dtl@tmp{#1}%
+\ifx\@dtl@tmp\@empty
+\else
+ #1~%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLformatsurname}
+%\begin{definition}
+%\cs{DTLformatsurname}\marg{surname}
+%\end{definition}
+% The format of an author/editor's surname.
+% \begin{macrocode}
+\newcommand*{\DTLformatsurname}[1]{%
+\DTLstartsentencespace
+#1\DTLcheckendsperiod{#1}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLformatjr}
+%\begin{definition}
+%\cs{DTLformatjr}\marg{jr part}
+%\end{definition}
+% The format of the ``jr'' part. This does nothing if the
+% argument is empty.
+% \begin{macrocode}
+\newcommand*{\DTLformatjr}[1]{%
+\DTLstartsentencespace
+\def\@dtl@tmp{#1}%
+\ifx\@dtl@tmp\@empty
+\else
+ , #1\DTLcheckendsperiod{#1}%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLformatcrossrefeditor}
+% Format cross reference editors:
+% \begin{macrocode}
+\newcommand*{\DTLformatcrossrefeditor}{%
+\DTLifbibfieldexists{Editor}{%
+\DTLstartsentencespace
+\@dtl@authorcount=0\relax
+\@for\@dtl@author:=\@dtl@key@Editor\do{%
+\advance\@dtl@authorcount by 1\relax}%
+{\@dtl@tmpcount=0\relax
+\@for\@dtl@author:=\@dtl@key@Editor\do{%
+\ifnum\@dtl@authorcount=1\relax
+ \expandafter\DTLformatsurnameonly\@dtl@author
+\else
+ \advance\@dtl@tmpcount by 1\relax
+ \ifnum\@dtl@tmpcount=1\relax
+ \expandafter\DTLformatsurnameonly\@dtl@author
+ \else
+ \ifnum\@dtl@authorcount=2\relax
+ \ \andname\ \expandafter\DTLformatsurnameonly\@dtl@author
+ \else
+ \ \etalname
+ \expandafter\DTLcheckendsperiod\expandafter{\etalname}
+ \fi
+ \@endfortrue
+ \fi
+\fi
+}}%
+}{}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLformatvolnumpages}
+% Format volume, number and pages (of an article).
+% \begin{macrocode}
+\newcommand*{\DTLformatvolnumpages}{%
+\DTLifbibfieldexists{Volume}{%
+\DTLstartsentencespace
+\DTLbibfield{Volume}\DTLperiodfalse}{}%
+\DTLifbibfieldexists{Number}{%
+\DTLstartsentencespace
+(\DTLbibfield{Number})\DTLperiodfalse}{}%
+\DTLifbibfieldexists{Pages}{%
+\DTLifanybibfieldexists{Volume,Number}{:}{%
+\DTLstartsentencespace
+\protected@edef\@dtl@pages{0\DTLbibfield{Pages}}%
+\DTLifnumerical{\@dtl@pages}{\pagename}{\pagesname}~}%
+\DTLbibfield{Pages}\DTLperiodfalse}{}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLformatbvolume}
+% Format book volume.
+% \begin{macrocode}
+\newcommand*{\DTLformatbvolume}{%
+\DTLifbibfieldexists{Volume}{%
+\ifDTLmidsentence
+ \volumename
+\else
+ \DTLstartsentencespace
+ \expandafter\MakeUppercase\volumename
+\fi
+~\DTLbibfield{Volume}%
+\DTLifbibfieldexists{Series}{\ \ofname\
+{\em\DTLbibfield{Series}}\DTLcheckbibfieldendsperiod{Series}}{%
+\DTLcheckbibfieldendsperiod{Volume}}%
+}{}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLformatchapterpages}
+% Format chapter and pages:
+% \begin{macrocode}
+\newcommand*{\DTLformatchapterpages}{%
+\DTLifbibfieldexists{Chapter}{%
+\DTLifbibfieldexists{Type}{%
+\DTLstartsentencespace
+\DTLbibfield{Type}}{%
+\DTLstartsentencespace
+\chaptername}~\DTLbibfield{Chapter}%
+\DTLifbibfieldexists{Pages}{\DTLaddcomma}{%
+\DTLcheckbibfieldendsperiod{Chapter}}}{}%
+\DTLstartsentencespace
+\DTLformatpages}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLformatpages}
+% Format pages:
+% \begin{macrocode}
+\newcommand*{\DTLformatpages}{%
+\DTLifbibfieldexists{Pages}{%
+\DTLstartsentencespace
+\protected@edef\@dtl@pages{0\DTLbibfield{Pages}}%
+\DTLifnumerical{\@dtl@pages}{\pagename}{\pagesname}~%
+\DTLbibfield{Pages}\DTLcheckbibfieldendsperiod{Pages}}{}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLformatnumberseries}
+% Format number and series (of book)
+% \begin{macrocode}
+\newcommand*{\DTLformatnumberseries}{%
+\DTLifbibfieldexists{Volume}{}{%
+\DTLifbibfieldexists{Number}{%
+\ifDTLmidsentence
+ \numbername
+\else
+ \DTLstartsentencespace
+ \expandafter\MakeUppercase\numbername
+\fi~\DTLbibfield{Number}%
+\DTLifbibfieldexists{Series}{\ \inname\ \DTLbibfield{Series}%
+\DTLcheckbibfieldendsperiod{Series}}{%
+\DTLcheckbibfieldendsperiod{Number}}%
+}{%
+\DTLifbibfieldexists{Series}{%
+\DTLstartsentencespace
+\DTLbibfield{Series}%
+\DTLcheckbibfieldendsperiod{Series}}{}}%
+}%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLformatbookcrossref}
+% Format a book cross reference.
+% \begin{macrocode}
+\newcommand*{\DTLformatbookcrossref}{%
+\DTLifbibfieldexists{Volume}{%
+\ifDTLmidsentence
+ \volumename
+\else
+ \DTLstartsentencespace
+ \expandafter\MakeUppercase\volumename
+\fi
+~\DTLbibfield{Volume}\ \ofname\
+}{%
+\ifDTLmidsentence
+ \inname
+\else
+ \DTLstartsentencespace
+ \expandafter\MakeUppercase\inname
+\fi\ }%
+\DTLifbibfieldexists{Editor}{\DTLformatcrossrefeditor}{%
+\DTLifbibfieldexists{Key}{%
+\DTLbibfield{Key}}{%
+\DTLifbibfieldexists{Series}{%
+{\em\DTLbibfield{Series}}}{}%
+}%
+}%
+~\DTLpcite{\DTLbibfield{CrossRef}}%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLformatincollproccrossref}
+% Format `incollections' cross reference.
+% \begin{macrocode}
+\newcommand*{\DTLformatincollproccrossref}{%
+\DTLifbibfieldexists{Editor}{%
+\ifDTLmidsentence
+ \inname
+\else
+ \DTLstartsentencespace
+ \expandafter\MakeUppercase\inname
+\fi\
+\DTLformatcrossrefeditor
+}{%
+\DTLifbibfieldexists{Key}{%
+\ifDTLmidsentence
+ \inname
+\else
+ \DTLstartsentencespace
+ \expandafter\MakeUppercase\inname
+\fi\ \DTLbibfield{Key}%
+}{%
+\DTLifbibfieldexists{BookTitle}{%
+\ifDTLmidsentence
+ \inname
+\else
+ \DTLstartsentencespace
+ \expandafter\MakeUppercase\inname
+\fi\ \DTLformatbooktitle{\DTLbibfield{BookTitle}}}{}%
+}}%
+~\DTLpcite{\DTLbibfield{CrossRef}}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLformatinedbooktitle}
+%Format editor and booktitle:
+% \begin{macrocode}
+\newcommand*{\DTLformatinedbooktitle}{%
+\DTLifbibfieldexists{BookTitle}{%
+\ifDTLmidsentence
+ \inname
+\else
+ \DTLstartsentencespace
+ \expandafter\MakeUppercase\inname
+\fi\
+\DTLifbibfieldexists{Editor}{%
+\DTLformateditorlist\DTLaddcomma \DTLformatbooktitle{\DTLbibfield{BookTitle}}%
+\DTLcheckbibfieldendsperiod{BookTitle}%
+}{\DTLformatbooktitle{\DTLbibfield{BookTitle}}%
+\DTLcheckbibfieldendsperiod{BookTitle}%
+}}{}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLformatdate}
+%Format date.
+% \begin{macrocode}
+\newcommand*{\DTLformatdate}{%
+\DTLifbibfieldexists{Year}{%
+\DTLifbibfieldexists{Month}{%
+\protected@edef\@dtl@tmp{\DTLbibfield{Month}}%
+\ifDTLmidsentence
+ \@dtl@tmp
+\else
+ \DTLstartsentencespace
+ \expandafter\MakeUppercase\@dtl@tmp
+\fi\
+\DTLmidsentencefalse}{}%
+\DTLstartsentencespace
+\DTLbibfield{Year}}{%
+\DTLifbibfieldexists{Month}{%
+\protected@edef\@dtl@tmp{\DTLbibfield{Month}}%
+\ifDTLmidsentence
+ \@dtl@tmp
+\else
+ \DTLstartsentencespace
+ \expandafter\MakeUppercase\@dtl@tmp
+\fi
+\DTLcheckbibfieldendsperiod{Month}%
+}{}}}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLformatarticlecrossref}
+% Format article cross reference.
+% \begin{macrocode}
+\newcommand*{\DTLformatarticlecrossref}{%
+\DTLifbibfieldexists{Key}{%
+\ifDTLmidsentence
+ \inname
+\else
+ \DTLstartsentencespace
+ \expandafter\MakeUppercase\inname
+\fi
+\ {\em\DTLbibfield{Key}}}{%
+\DTLifbibfieldexists{Journal}{%
+\ifDTLmidsentence
+ \inname
+\else
+ \DTLstartsentencespace
+ \expandafter\MakeUppercase\inname
+\fi
+\ {\em\DTLbibfield{Journal}}}{}}%
+~\DTLpcite{\DTLbibfield{CrossRef}}%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLpcite}
+%\changes{2.22}{2014-06-10}{new}
+% \begin{macrocode}
+\newrobustcmd*{\DTLpcite}[1]{%
+ \protected@edef\@dtl@tmp{#1}%
+ \cite{\@dtl@tmp}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\subsection{ifthen conditionals}
+% The conditionals defined in this section may be used in the
+% optional argument of \cs{DTLforeachbibentry}. They may also be
+% used in the first argument of \cs{ifthenelse}, but only if the
+% command occurs within the body of \cs{DTLforeachbibentry}.
+%
+%\begin{macro}{\DTLbibfieldexists}
+%\begin{definition}
+%\cs{DTLbibfieldexists}\marg{field label}
+%\end{definition}
+% Checks if named bib field exists for current entry
+% \begin{macrocode}
+\newcommand*{\DTLbibfieldexists}[1]{%
+\TE@throw\noexpand\dtl@testbibfieldexists{#1}%
+\noexpand\if@dtl@condition}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtl@testbibfieldexists}
+% \begin{macrocode}
+\newcommand*{\dtl@testbibfieldexists}[1]{%
+\DTLifbibfieldexists{#1}{\@dtl@conditiontrue}{\@dtl@conditionfalse}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLbibfieldiseq}
+%\begin{definition}
+%\cs{DTLbibfieldiseq}\marg{field label}\marg{value}
+%\end{definition}
+% Checks if the value of the bib field given by \meta{field label}
+% is equal to \meta{value}. (Uses \cs{dtlcompare} to determine if
+% the values are equal. If the bib field doesn't exist, the
+% condition is false.)
+% \begin{macrocode}
+\newcommand*{\DTLbibfieldiseq}[2]{%
+\TE@throw\noexpand\dtl@testbibfieldiseq{#1}{#2}%
+\noexpand\if@dtl@condition}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtl@testbibfieldiseq}
+% \begin{macrocode}
+\newcommand*{\dtl@testbibfieldiseq}[2]{%
+\DTLifbibfieldexists{#1}{%
+\expandafter\let\expandafter\@dtl@tmp\expandafter
+ =\csname @dtl@key@#1\endcsname
+\expandafter\toks@\expandafter{\@dtl@tmp}%
+\@dtl@toks{#2}%
+\edef\@dtl@docompare{\noexpand\dtlcompare{\noexpand\@dtl@tmpcount}%
+{\the\toks@}{\the\@dtl@toks}}%
+\@dtl@docompare
+\ifnum\@dtl@tmpcount=0\relax
+ \@dtl@conditiontrue
+\else
+ \@dtl@conditionfalse
+\fi
+}{%
+\@dtl@conditionfalse}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLbibfieldislt}
+%\begin{definition}
+%\cs{DTLbibfieldislt}\marg{field label}\marg{value}
+%\end{definition}
+% Checks if the value of the bib field given by \meta{field label}
+% is less than \meta{value}. (If the bib field doesn't exist, the
+% condition is false.)
+% \begin{macrocode}
+\newcommand*{\DTLbibfieldislt}[2]{%
+\TE@throw\noexpand\dtl@testbibfieldislt{#1}{#2}%
+\noexpand\if@dtl@condition}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtl@testbibfieldislt}
+% \begin{macrocode}
+\newcommand*{\dtl@testbibfieldislt}[2]{%
+\DTLifbibfieldexists{#1}{%
+\expandafter\let\expandafter\@dtl@tmp\expandafter
+ =\csname @dtl@key@#1\endcsname
+\expandafter\toks@\expandafter{\@dtl@tmp}%
+\@dtl@toks{#2}%
+\edef\@dtl@docompare{\noexpand\dtlcompare{\noexpand\@dtl@tmpcount}%
+{\the\toks@}{\the\@dtl@toks}}%
+\@dtl@docompare
+\ifnum\@dtl@tmpcount=-1\relax
+ \@dtl@conditiontrue
+\else
+ \@dtl@conditionfalse
+\fi
+}{%
+\@dtl@conditionfalse}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLbibfieldisle}
+%\begin{definition}
+%\cs{DTLbibfieldisle}\marg{field label}\marg{value}
+%\end{definition}
+% Checks if the value of the bib field given by \meta{field label}
+% is less than or equal to \meta{value}.
+% (If the bib field doesn't exist, the
+% condition is false.)
+% \begin{macrocode}
+\newcommand*{\DTLbibfieldisle}[2]{%
+\TE@throw\noexpand\dtl@testbibfieldisle{#1}{#2}%
+\noexpand\if@dtl@condition}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtl@testbibfieldisle}
+% \begin{macrocode}
+\newcommand*{\dtl@testbibfieldisle}[2]{%
+\DTLifbibfieldexists{#1}{%
+\expandafter\let\expandafter\@dtl@tmp\expandafter
+ =\csname @dtl@key@#1\endcsname
+\expandafter\toks@\expandafter{\@dtl@tmp}%
+\@dtl@toks{#2}%
+\edef\@dtl@docompare{\noexpand\dtlcompare{\noexpand\@dtl@tmpcount}%
+{\the\toks@}{\the\@dtl@toks}}%
+\@dtl@docompare
+\ifnum\@dtl@tmpcount<1\relax
+ \@dtl@conditiontrue
+\else
+ \@dtl@conditionfalse
+\fi
+}{%
+\@dtl@conditionfalse}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLbibfieldisgt}
+%\begin{definition}
+%\cs{DTLbibfieldisgt}\marg{field label}\marg{value}
+%\end{definition}
+% Checks if the value of the bib field given by \meta{field label}
+% is greater than \meta{value}. (If the bib field doesn't exist, the
+% condition is false.)
+% \begin{macrocode}
+\newcommand*{\DTLbibfieldisgt}[2]{%
+\TE@throw\noexpand\dtl@testbibfieldisgt{#1}{#2}%
+\noexpand\if@dtl@condition}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtl@testbibfieldisgt}
+% \begin{macrocode}
+\newcommand*{\dtl@testbibfieldisgt}[2]{%
+\DTLifbibfieldexists{#1}{%
+\expandafter\let\expandafter\@dtl@tmp\expandafter
+ =\csname @dtl@key@#1\endcsname
+\expandafter\toks@\expandafter{\@dtl@tmp}%
+\@dtl@toks{#2}%
+\edef\@dtl@docompare{\noexpand\dtlcompare{\noexpand\@dtl@tmpcount}%
+{\the\toks@}{\the\@dtl@toks}}%
+\@dtl@docompare
+\ifnum\@dtl@tmpcount=1\relax
+ \@dtl@conditiontrue
+\else
+ \@dtl@conditionfalse
+\fi
+}{%
+\@dtl@conditionfalse}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLbibfieldisge}
+%\begin{definition}
+%\cs{DTLbibfieldisge}\marg{field label}\marg{value}
+%\end{definition}
+% Checks if the value of the bib field given by \meta{field label}
+% is less than or equal to \meta{value}.
+% (If the bib field doesn't exist, the
+% condition is false.)
+% \begin{macrocode}
+\newcommand*{\DTLbibfieldisge}[2]{%
+\TE@throw\noexpand\dtl@testbibfieldisge{#1}{#2}%
+\noexpand\if@dtl@condition}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtl@testbibfieldisge}
+% \begin{macrocode}
+\newcommand*{\dtl@testbibfieldisge}[2]{%
+\DTLifbibfieldexists{#1}{%
+\expandafter\let\expandafter\@dtl@tmp\expandafter
+ =\csname @dtl@key@#1\endcsname
+\expandafter\toks@\expandafter{\@dtl@tmp}%
+\@dtl@toks{#2}%
+\edef\@dtl@docompare{\noexpand\dtlcompare{\noexpand\@dtl@tmpcount}%
+{\the\toks@}{\the\@dtl@toks}}%
+\@dtl@docompare
+\ifnum\@dtl@tmpcount>-1\relax
+ \@dtl@conditiontrue
+\else
+ \@dtl@conditionfalse
+\fi
+}{%
+\@dtl@conditionfalse}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLbibfieldcontains}
+%\begin{definition}
+%\cs{DTLbibfieldcontains}\marg{field label}\marg{sub string}
+%\end{definition}
+% Checks if the value of the bib field given by \meta{field label}
+% contains \meta{sub string}.
+% (If the bib field doesn't exist, the
+% condition is false.)
+% \begin{macrocode}
+\newcommand*{\DTLbibfieldcontains}[2]{%
+\TE@throw\noexpand\dtl@testbibfieldcontains{#1}{#2}%
+\noexpand\if@dtl@condition}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtl@testbibfieldcontains}
+% \begin{macrocode}
+\newcommand*{\dtl@testbibfieldcontains}[2]{%
+\DTLifbibfieldexists{#1}{%
+\expandafter\let\expandafter\@dtl@tmp\expandafter
+ =\csname @dtl@key@#1\endcsname
+\expandafter\dtl@testifsubstring\expandafter{\@dtl@tmp}{#2}%
+}{\@dtl@conditionfalse}}
+% \end{macrocode}
+%\end{macro}
+%
+%\section{Bibliography Style Macros}
+%\label{sec:src:bibstyle}
+% The macros defined in this section should be redefined by
+% bibliography styles.
+%
+%\begin{environment}{DTLthebibliography}
+% How to format the entire bibliography:
+% \begin{macrocode}
+\newenvironment{DTLthebibliography}[2][\boolean{true}]{%
+\@dtl@tmpcount=0\relax
+\@sDTLforeach[#1]{#2}{}{\advance\@dtl@tmpcount by 1\relax}%
+\begin{thebibliography}{\number\@dtl@tmpcount}
+}{\end{thebibliography}}
+% \end{macrocode}
+%\end{environment}
+%\begin{macro}{\DTLmonthname}
+% The monthname style. The argument must be a number from~1
+% to~12. By default, uses \cs{dtl@monthname}.
+% \begin{macrocode}
+\newcommand*{\DTLmonthname}[1]{%
+\dtl@monthname{#1}}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtl@monthname}
+% Full month names:
+% \begin{macrocode}
+\newcommand*{\dtl@monthname}[1]{%
+\ifcase#1%
+\or January%
+\or February%
+\or March%
+\or April%
+\or May%
+\or June%
+\or July%
+\or August%
+\or September%
+\or October%
+\or November%
+\or December%
+\fi}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtl@abbrvmonthname}
+% Abbreviated months:
+% \begin{macrocode}
+\newcommand*{\dtl@abbrvmonthname}[1]{%
+\ifcase#1%
+\or Jan.%
+\or Feb.%
+\or Mar.%
+\or Apr.%
+\or May%
+\or June%
+\or July%
+\or Aug.%
+\or Sept.%
+\or Oct.%
+\or Nov.%
+\or Dec.%
+\fi}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLbibitem}
+% Define how to start a new bibitem:
+% \begin{macrocode}
+\newcommand*{\DTLbibitem}{\bibitem{\DBIBcitekey}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLmbibitem}
+% As \cs{DTLbibitem} but for \cs{DTLmbibliography}
+% \begin{macrocode}
+\newcommand*{\DTLmbibitem}[1]{\bibitem{#1@\DBIBcitekey}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLcustombibitem}
+%\changes{2.22}{2014-06-10}{new}
+%\begin{definition}
+%\cs{DTLcustombibitem}\marg{item code}\marg{ref text}\marg{cite key}
+%\end{definition}
+% As \cs{DTLbibitem} but user provides \meta{item code} to use in place of
+% \cs{item}. This code can access the cite key using
+% \cs{DBIBcitekey}. The \meta{ref text} is the text associated with
+% this bib item. (For example, if used in an enumerate environment,
+% \meta{ref text} might be \verb|\theenumi|.)
+% \begin{macrocode}
+\newcommand*{\DTLcustombibitem}[3]{%
+ #1%
+ \if@filesw
+ \immediate\write\@auxout{\string\bibcite{#3}{#2}}%
+ \fi
+ \ignorespaces
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLformatauthor}
+%\begin{definition}
+%\cs{DTLformatauthor}\marg{von part}\marg{surname}\marg{junior
+%part}\marg{forenames}
+%\end{definition}
+% The format of an author's name.
+% \begin{macrocode}
+\newcommand*{\DTLformatauthor}[4]{%
+\DTLformatforenames{#4}
+\DTLformatvon{#1}%
+\DTLformatsurname{#2}%
+\DTLformatjr{#3}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLformateditor}
+% The format of an editor's name.
+% \begin{macrocode}
+\newcommand*{\DTLformateditor}[4]{%
+\DTLformatforenames{#4}
+\DTLformatvon{#1}%
+\DTLformatsurname{#2}%
+\DTLformatjr{#3}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLformatedition}
+% The format of an edition:
+% \begin{macrocode}
+\newcommand*{\DTLformatedition}[1]{#1 \editionname}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLformatarticle}
+% The format of an article:
+% \begin{macrocode}
+\newcommand{\DTLformatarticle}{}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLformatbook}
+% The format of a book:
+% \begin{macrocode}
+\newcommand{\DTLformatbook}{}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLformatbooklet}
+% The format of a booklet:
+% \begin{macrocode}
+\newcommand{\DTLformatbooklet}{}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLformatinbook}
+% The format of an ``inbook'' type:
+% \begin{macrocode}
+\newcommand{\DTLformatinbook}{}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLformatincollection}
+% The format of an ``incollection'' type:
+% \begin{macrocode}
+\newcommand{\DTLformatincollection}{}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLformatinproceedings}
+% The format of an ``inproceedings'' type:
+% \begin{macrocode}
+\newcommand{\DTLformatinproceedings}{}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLformatmanual}
+% The format of a manual:
+% \begin{macrocode}
+\newcommand{\DTLformatmanual}{}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLformatmastersthesis}
+% The format of a master's thesis:
+% \begin{macrocode}
+\newcommand{\DTLformatmastersthesis}{}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLformatmisc}
+% The format of a miscellaneous entry:
+% \begin{macrocode}
+\newcommand{\DTLformatmisc}{}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLformatphdthesis}
+% The format of a Ph.D. thesis:
+% \begin{macrocode}
+\newcommand{\DTLformatphdthesis}{}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLformatproceedings}
+% The format of a proceedings:
+% \begin{macrocode}
+\newcommand{\DTLformatproceedings}{}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLformattechreport}
+% The format of a technical report:
+% \begin{macrocode}
+\newcommand{\DTLformattechreport}{}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLformatunpublished}
+% The format of an unpublished work:
+% \begin{macrocode}
+\newcommand{\DTLformatunpublished}{}
+% \end{macrocode}
+%\end{macro}
+%
+% Predefined names (these correspond to the standard \BibTeX\
+% predefined strings of the same name without the leading
+% \cs{DTL}):
+%\begin{macro}{\DTLacmcs}
+% \begin{macrocode}
+\newcommand*{\DTLacmcs}{ACM Computing Surveys}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLacta}
+% \begin{macrocode}
+\newcommand*{\DTLacta}{Acta Informatica}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLcacm}
+% \begin{macrocode}
+\newcommand*{\DTLcacm}{Communications of the ACM}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLibmjrd}
+% \begin{macrocode}
+\newcommand*{\DTLibmjrd}{IBM Journal of Research and Development}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLibmsj}
+% \begin{macrocode}
+\newcommand*{\DTLibmsj}{IBM Systems Journal}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLieeese}
+% \begin{macrocode}
+\newcommand*{\DTLieeese}{IEEE Transactions on Software Engineering}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLieeetc}
+% \begin{macrocode}
+\newcommand*{\DTLieeetc}{IEEE Transactions on Computers}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLieeetcad}
+% \begin{macrocode}
+\newcommand*{\DTLieeetcad}{IEEE Transactions on Computer-Aided Design
+of Integrated Circuits}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLipl}
+% \begin{macrocode}
+\newcommand*{\DTLipl}{Information Processing Letters}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLjacm}
+% \begin{macrocode}
+\newcommand*{\DTLjacm}{Journal of the ACM}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLjcss}
+% \begin{macrocode}
+\newcommand*{\DTLjcss}{Journal of Computer and System Sciences}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLscp}
+% \begin{macrocode}
+\newcommand*{\DTLscp}{Science of Computer Programming}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLsicomp}
+% \begin{macrocode}
+\newcommand*{\DTLsicomp}{SIAM Journal on Computing}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLtocs}
+% \begin{macrocode}
+\newcommand*{\DTLtocs}{ACM Transactions on Computer Systems}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLtods}
+% \begin{macrocode}
+\newcommand*{\DTLtods}{ACM Transactions on Database Systems}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLtog}
+% \begin{macrocode}
+\newcommand*{\DTLtog}{ACM Transactions on Graphics}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLtoms}
+% \begin{macrocode}
+\newcommand*{\DTLtoms}{ACM Transactions on Mathematical Software}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLtoois}
+% \begin{macrocode}
+\newcommand*{\DTLtoois}{ACM Transactions on Office Information
+Systems}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLtoplas}
+% \begin{macrocode}
+\newcommand*{\DTLtoplas}{ACM Transactions on Programming Languages
+and Systems}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLtcs}
+% \begin{macrocode}
+\newcommand*{\DTLtcs}{Theoretical Computer Science}
+% \end{macrocode}
+%\end{macro}
+%
+%\section{Bibliography Styles}
+% Each bibliography style is set by the command
+% \cs{dtlbst@}\meta{style}, where \meta{style} is the name
+% of the bibliography style.
+%
+%\begin{macro}{\dtlbst@plain}
+% The `plain' style:
+% \begin{macrocode}
+\newcommand{\dtlbst@plain}{%
+% \end{macrocode}
+% Set how to format the entire bibliography:
+% \begin{macrocode}
+ \renewenvironment{DTLthebibliography}[2][\boolean{true}]{%
+ \@dtl@tmpcount=0\relax
+ \@sDTLforeach[##1]{##2}{}{\advance\@dtl@tmpcount by 1\relax}%
+ \begin{thebibliography}{\number\@dtl@tmpcount}%
+ }{\end{thebibliography}}%
+% \end{macrocode}
+% Set how to start the bibliography entry:
+% \begin{macrocode}
+ \renewcommand*{\DTLbibitem}{\bibitem{\DBIBcitekey}}%
+ \renewcommand*{\DTLmbibitem}[1]{\bibitem{##1@\DBIBcitekey}}%
+% \end{macrocode}
+% Sets the author name format.
+% \begin{macrocode}
+ \renewcommand*{\DTLformatauthor}[4]{%
+ \DTLformatforenames{##4}
+ \DTLformatvon{##1}%
+ \DTLformatsurname{##2}%
+ \DTLformatjr{##3}}
+% \end{macrocode}
+% Sets the editor name format.
+% \begin{macrocode}
+ \renewcommand*{\DTLformateditor}[4]{%
+ \DTLformatforenames{##4}
+ \DTLformatvon{##1}%
+ \DTLformatsurname{##2}%
+ \DTLformatjr{##3}}
+% \end{macrocode}
+% Sets the edition format.
+% \begin{macrocode}
+ \renewcommand*{\DTLformatedition}[1]{##1 \editionname}%
+% \end{macrocode}
+% Sets the monthname format.
+% \begin{macrocode}
+ \let\DTLmonthname\dtl@monthname
+% \end{macrocode}
+% Sets other predefined names:
+% \begin{macrocode}
+ \renewcommand*{\DTLacmcs}{ACM Computing Surveys}
+ \renewcommand*{\DTLacta}{Acta Informatica}
+ \renewcommand*{\DTLcacm}{Communications of the ACM}
+ \renewcommand*{\DTLibmjrd}{IBM Journal of Research and Development}
+ \renewcommand*{\DTLibmsj}{IBM Systems Journal}
+ \renewcommand*{\DTLieeese}{IEEE Transactions on Software Engineering}
+ \renewcommand*{\DTLieeetc}{IEEE Transactions on Computers}
+ \renewcommand*{\DTLieeetcad}{IEEE Transactions on Computer-Aided Design
+of Integrated Circuits}
+ \renewcommand*{\DTLipl}{Information Processing Letters}
+ \renewcommand*{\DTLjacm}{Journal of the ACM}
+ \renewcommand*{\DTLjcss}{Journal of Computer and System Sciences}
+ \renewcommand*{\DTLscp}{Science of Computer Programming}
+ \renewcommand*{\DTLsicomp}{SIAM Journal on Computing}
+ \renewcommand*{\DTLtocs}{ACM Transactions on Computer Systems}
+ \renewcommand*{\DTLtods}{ACM Transactions on Database Systems}
+ \renewcommand*{\DTLtog}{ACM Transactions on Graphics}
+ \renewcommand*{\DTLtoms}{ACM Transactions on Mathematical Software}
+ \renewcommand*{\DTLtoois}{ACM Transactions on Office Information
+Systems}
+ \renewcommand*{\DTLtoplas}{ACM Transactions on Programming Languages
+and Systems}
+ \renewcommand*{\DTLtcs}{Theoretical Computer Science}
+% \end{macrocode}
+% The format of an article.
+% \begin{macrocode}
+ \renewcommand*{\DTLformatarticle}{%
+ \DTLformatauthorlist
+ \DTLifbibfieldexists{Author}{\DTLaddperiod}{}%
+ \DTLifbibfieldexists{Title}{%
+ \DTLstartsentencespace\DTLbibfield{Title}%
+ \DTLcheckbibfieldendsperiod{Title}%
+ \DTLaddperiod}{}%
+ \DTLifbibfieldexists{CrossRef}{%
+% cross ref field
+ \DTLformatarticlecrossref
+ \DTLifbibfieldexists{Pages}{\DTLaddcomma}{}%
+ \DTLformatpages
+ \DTLaddperiod
+ }{% no cross ref field
+ \DTLifbibfieldexists{Journal}{\DTLstartsentencespace
+ {\em\DTLbibfield{Journal}}%
+ \DTLcheckbibfieldendsperiod{Journal}%
+ \DTLifanybibfieldexists{Number,Volume,Pages,Month,Year}{%
+ \DTLaddcomma}{\DTLaddperiod}}{}%
+ \DTLformatvolnumpages
+ \DTLifanybibfieldexists{Volume,Number,Pages}{%
+ \DTLifanybibfieldexists{Year,Month}{\DTLaddcomma}{%
+ \DTLaddperiod}%
+ \DTLmidsentencefalse}{}%
+ \DTLformatdate
+ \DTLifanybibfieldexists{Year,Month}{\DTLaddperiod}{}%
+ }%
+ \DTLifbibfieldexists{Note}{\DTLstartsentencespace\DTLbibfield{Note}%
+ \DTLcheckbibfieldendsperiod{Note}%
+ \DTLaddperiod}{}%
+ }
+% \end{macrocode}
+% The format of a book.
+% \begin{macrocode}
+\renewcommand*{\DTLformatbook}{%
+ \DTLifbibfieldexists{Author}%
+ {%
+ \DTLformatauthorlist\DTLaddperiod
+ }%
+ {%
+ \DTLformateditorlist
+ \DTLifbibfieldexists{Editor}%
+ {%
+ \DTLaddperiod
+ }%
+ {}%
+ }%
+ \DTLifbibfieldexists{Title}%
+ {%
+ \DTLstartsentencespace
+ \DTLformatbooktitle{\DTLbibfield{Title}}%
+ \DTLcheckbibfieldendsperiod{Title}%
+ }%
+ {}%
+ \DTLifbibfieldexists{CrossRef}%
+ {%
+% \end{macrocode}
+% Cross ref field
+% \begin{macrocode}
+ \DTLifbibfieldexists{Title}{\DTLaddperiod}{}%
+ \DTLformatbookcrossref
+ \DTLifanybibfieldexists{Edition,Month,Year}%
+ {\DTLaddcomma}%
+ {\DTLaddperiod}%
+ }%
+ {%
+% \end{macrocode}
+% no cross ref field
+% \begin{macrocode}
+ \DTLifbibfieldexists{Title}%
+ {%
+ \DTLifbibfieldexists{Volume}{\DTLaddcomma}{\DTLaddperiod}%
+ }%
+ {}%
+ \DTLformatbvolume
+ \DTLformatnumberseries
+ \DTLifanybibfieldexists{Number,Series,Volume}{\DTLaddperiod}{}%
+ \DTLifbibfieldexists{Publisher}%
+ {%
+ \DTLstartsentencespace
+ \DTLbibfield{Publisher}%
+ \DTLcheckbibfieldendsperiod{Publisher}%
+ \DTLifbibfieldexists{Address}%
+ {\DTLaddcomma}%
+ {%
+ \DTLifanybibfieldexists{Month,Year}%
+ {\DTLaddcomma}%
+ {\DTLaddperiod}%
+ }%
+ }%
+ {}%
+ \DTLifbibfieldexists{Address}%
+ {%
+ \DTLstartsentencespace
+ \DTLbibfield{Address}%
+ \DTLcheckbibfieldendsperiod{Address}%
+ \DTLifanybibfieldexists{Month,Year}{\DTLaddcomma}{\DTLaddperiod}%
+ }%
+ {}%
+ }%
+ \DTLifbibfieldexists{Edition}%
+ {%
+ \protected@edef\@dtl@tmp{\DTLformatedition{\DTLbibfield{Edition}}}%
+ \ifDTLmidsentence
+ \@dtl@tmp
+ \else
+ \DTLstartsentencespace\expandafter\MakeUppercase\@dtl@tmp
+ \fi
+ \expandafter\DTLcheckendsperiod\expandafter{\@dtl@tmp}%
+ \DTLifanybibfieldexists{Month,Year}{\DTLaddcomma}{\DTLaddperiod}%
+ }%
+ {}%
+ \DTLformatdate
+ \DTLifanybibfieldexists{Year,Month}{\DTLaddperiod}{}%
+ \DTLifbibfieldexists{Note}%
+ {%
+ \DTLstartsentencespace
+ \DTLbibfield{Note}%
+ \DTLcheckbibfieldendsperiod{Note}%
+ \DTLaddperiod
+ }%
+ {}%
+}%
+% \end{macrocode}
+% The format of a booklet.
+% \begin{macrocode}
+\renewcommand*{\DTLformatbooklet}{%
+\DTLifbibfieldexists{Author}{%
+\DTLformatauthorlist\DTLaddperiod}{}%
+\DTLifbibfieldexists{Title}{\DTLstartsentencespace
+\DTLbibfield{Title}%
+\DTLcheckbibfieldendsperiod{Title}%
+\DTLaddperiod}{}%
+\DTLifbibfieldexists{HowPublished}{%
+\DTLstartsentencespace\DTLbibfield{HowPublished}%
+\DTLcheckbibfieldendsperiod{HowPublished}%
+\DTLifanybibfieldexists{Address,Month,Year}{\DTLaddcomma
+}{\DTLaddperiod}}{}%
+\DTLifbibfieldexists{Address}{\DTLstartsentencespace
+\DTLbibfield{Address}%
+\DTLcheckbibfieldendsperiod{Address}%
+\DTLifanybibfieldexists{Month,Year}{\DTLaddcomma}{\DTLaddperiod}}{}%
+\DTLformatdate
+\DTLifanybibfieldexists{Year,Month}{\DTLaddperiod}{}%
+\DTLifbibfieldexists{Note}{\DTLstartsentencespace\DTLbibfield{Note}%
+\DTLcheckbibfieldendsperiod{Note}%
+\DTLaddperiod}{}%
+}%
+% \end{macrocode}
+% The format of an `inbook' entry.
+% \begin{macrocode}
+\renewcommand*{\DTLformatinbook}{%
+\DTLifbibfieldexists{Author}{%
+\DTLformatauthorlist\DTLaddperiod}{%
+\DTLifbibfieldexists{Editor}{\DTLformateditorlist\DTLaddperiod}{}}%
+\DTLifbibfieldexists{Title}{%
+\DTLstartsentencespace
+{\em\DTLbibfield{Title}}%
+\DTLcheckbibfieldendsperiod{Title}%
+}{}%
+\DTLifbibfieldexists{CrossRef}{%
+% Cross ref entry
+\DTLifbibfieldexists{Title}{%
+\DTLifbibfieldexists{Chapter}{\DTLaddcomma}{\DTLaddperiod}}{}%
+\DTLformatchapterpages
+\DTLifanybibfieldexists{Chapter,Pages}{\DTLaddperiod}{}%
+\DTLformatbookcrossref
+}{% no cross ref
+\DTLifbibfieldexists{Title}{%
+\DTLifanybibfieldexists{Chapter,Volume}{\DTLaddcomma
+}{\DTLaddperiod}}{}%
+\DTLformatbvolume
+\DTLifanybibfieldexists{Volume,Series}{%
+\DTLifanybibfieldexists{Chapter,Pages}{%
+\DTLaddcomma}{\DTLaddperiod}}{}%
+\DTLformatchapterpages
+\DTLifanybibfieldexists{Chapter,Pages}{\DTLaddperiod}{}%
+\DTLifbibfieldexists{Publisher}{%
+\DTLstartsentencespace
+\DTLbibfield{Publisher}%
+\DTLcheckbibfieldendsperiod{Publisher}%
+\DTLifbibfieldexists{Address}{\DTLaddcomma}{}}{}%
+\DTLifbibfieldexists{Address}{%
+\DTLstartsentencespace
+\DTLbibfield{Address}%
+\DTLcheckbibfieldendsperiod{Address}}{}%
+}%
+\DTLifanybibfieldexists{Edition,Month,Year}{\DTLaddcomma
+}{\DTLaddperiod}%
+\DTLifbibfieldexists{Edition}{%
+\protected@edef\@dtl@tmp{\DTLformatedition{\DTLbibfield{Edition}}}%
+\ifDTLmidsentence
+ \@dtl@tmp
+\else
+ \DTLstartsentencespace
+ \expandafter\MakeUppercase\@dtl@tmp
+\fi
+\expandafter\DTLcheckendsperiod\expandafter{\@dtl@tmp}%
+\DTLifanybibfieldexists{Month,Year}{\DTLaddcomma
+}{\DTLaddperiod}%
+}{}%
+\DTLformatdate
+\DTLifanybibfieldexists{Month,Year}{\DTLaddperiod}{}%
+\DTLifbibfieldexists{Note}{%
+\DTLstartsentencespace
+\DTLbibfield{Note}%
+\DTLcheckbibfieldendsperiod{Note}%
+\DTLaddperiod}{}%
+}%
+% \end{macrocode}
+% The format of an `incollection' entry.
+% \begin{macrocode}
+\renewcommand*{\DTLformatincollection}{%
+\DTLifbibfieldexists{Author}{\DTLformatauthorlist\DTLaddperiod}{}%
+\DTLifbibfieldexists{Title}{%
+\DTLstartsentencespace
+\DTLbibfield{Title}%
+\DTLcheckbibfieldendsperiod{Title}%
+\DTLaddperiod}{}%
+\DTLifbibfieldexists{CrossRef}{%
+% cross ref entry
+\DTLformatincollproccrossref
+\DTLifanybibfieldexists{Chapter,Pages}{\DTLaddcomma}{}%
+\DTLformatchapterpages\DTLaddperiod
+}{% no cross ref entry
+\DTLformatinedbooktitle
+\DTLifbibfieldexists{BookTitle}{%
+\DTLifanybibfieldexists{Volume,Series,Chapter,Pages,Number}{%
+\DTLaddcomma}{\DTLaddperiod}}{}%
+\DTLformatbvolume
+\DTLifbibfieldexists{Volume}{%
+\DTLifanybibfieldexists{Number,Series,Chapter,Pages}{%
+\DTLaddcomma}{\DTLaddperiod}}{}%
+\DTLformatnumberseries
+\DTLifanybibfieldexists{Number,Series}{%
+\DTLifanybibfieldexists{Chapter,Pages}{\DTLaddcomma
+}{\DTLaddperiod}}{}%
+\DTLformatchapterpages
+\DTLifanybibfieldexists{Chapter,Pages}{\DTLaddperiod}{}%
+\DTLifbibfieldexists{Publisher}{%
+\DTLstartsentencespace
+\DTLbibfield{Publisher}%
+\DTLcheckbibfieldendsperiod{Publisher}%
+\DTLifanybibfieldexists{Address,Edition,Month,Year}{%
+\DTLaddcomma}{\DTLaddperiod}}{}%
+\DTLifbibfieldexists{Address}{%
+\DTLstartsentencespace
+\DTLbibfield{Address}%
+\DTLcheckbibfieldendsperiod{Address}%
+\DTLifanybibfieldexists{Edition,Month,Year}{%
+\DTLaddcomma}{\DTLaddperiod}}{}%
+\DTLifbibfieldexists{Edition}{%
+\protected@edef\@dtl@tmp{\DTLformatedition{\DTLbibfield{Edition}}}%
+\ifDTLmidsentence
+ \@dtl@tmp
+\else
+ \DTLstartsentencespace
+ \expandafter\MakeUppercase\@dtl@tmp
+\fi
+\expandafter\DTLcheckendsperiod\expandafter{\@dtl@tmp}%
+\DTLifanybibfieldexists{Month,Year}{\DTLaddcomma
+}{\DTLaddperiod}%
+}{}%
+\DTLformatdate
+\DTLifanybibfieldexists{Month,Year}{\DTLaddperiod}{}%
+}%
+\DTLifbibfieldexists{Note}{%
+\DTLstartsentencespace
+\DTLbibfield{Note}%
+\DTLcheckbibfieldendsperiod{Note}%
+\DTLaddperiod}{}%
+}%
+% \end{macrocode}
+% The format of an `inproceedings' entry.
+% \begin{macrocode}
+\renewcommand*{\DTLformatinproceedings}{%
+\DTLifbibfieldexists{Author}{\DTLformatauthorlist
+\DTLaddperiod}{}%
+\DTLifbibfieldexists{Title}{%
+\DTLstartsentencespace
+\DTLbibfield{Title}%
+\DTLcheckbibfieldendsperiod{Title}%
+\DTLaddperiod}{}%
+\DTLifbibfieldexists{CrossRef}{%
+% cross ref entry
+\DTLformatincollproccrossref
+\DTLifbibfieldexists{Pages}{\DTLaddcomma}{%
+\DTLaddperiod}%
+\DTLformatpages
+\DTLifbibfieldexists{Pages}{\DTLaddperiod}{}%
+}{% no cross ref
+\DTLformatinedbooktitle
+\DTLifbibfieldexists{BookTitle}{%
+\DTLifanybibfieldexists{Volume,Series,Pages,Number,Address,%
+Month,Year}{%
+\DTLaddcomma}{\DTLaddperiod}}{}%
+\DTLformatbvolume
+\DTLifbibfieldexists{Volume}{%
+\DTLifanybibfieldexists{Number,Series,Pages,Address,Month,Year}{%
+\DTLaddcomma}{\DTLaddperiod}}{}%
+\DTLformatnumberseries
+\DTLifanybibfieldexists{Number,Series}{%
+\DTLifanybibfieldexists{Pages,Address,Month,Year}{%
+\DTLaddcomma}{\DTLaddperiod}}{}%
+\DTLformatpages
+\DTLifbibfieldexists{Pages}{%
+\DTLifanybibfieldexists{Address,Month,Year}{%
+\DTLaddcomma}{\DTLaddperiod}}{}%
+\DTLifbibfieldexists{Address}{%
+\DTLstartsentencespace
+\DTLbibfield{Address}%
+\DTLcheckbibfieldendsperiod{Address}%
+\DTLifanybibfieldexists{Month,Year}{\DTLaddcomma}{%
+\DTLaddperiod}%
+\DTLformatdate
+\DTLifanybibfieldexists{Month,Year}{\DTLaddperiod}{}%
+\DTLifbibfieldexists{Organization}{%
+\DTLstartsentencespace
+\DTLbibfield{Organization}%
+\DTLcheckbibfieldendsperiod{Organization}%
+\DTLifbibfieldexists{Publisher}{\DTLaddcomma}{%
+\DTLaddperiod}}{}%
+\DTLifbibfieldexists{Publisher}{%
+\DTLstartsentencespace
+\DTLbibfield{Publisher}%
+\DTLcheckbibfieldendsperiod{Publisher}%
+\DTLaddperiod}{}%
+}{%
+\DTLifanybibfieldexists{Publisher,Organization}{%
+\DTLaddperiod}{}%
+\DTLifbibfieldexists{Organization}{%
+\DTLstartsentencespace
+\DTLbibfield{Organization}%
+\DTLcheckbibfieldendsperiod{Organization}%
+\DTLifanybibfieldexists{Publisher,Month,Year}{%
+\DTLaddcomma}{}}{}%
+\DTLifbibfieldexists{Publisher}{%
+\DTLstartsentencespace
+\DTLbibfield{Publisher}%
+\DTLcheckbibfieldendsperiod{Publisher}%
+\DTLifanybibfieldexists{Month,Year}{\DTLaddcomma}{%
+\DTLaddperiod}}{}%
+\DTLformatdate
+\DTLifanybibfieldexists{Month,Year}{\DTLaddperiod}{}%
+}%
+}%
+\DTLifbibfieldexists{Note}{%
+\DTLstartsentencespace
+\DTLbibfield{Note}%
+\DTLcheckbibfieldendsperiod{Note}%
+\DTLaddperiod}{}%
+}%
+% \end{macrocode}
+% The format of a manual.
+% \begin{macrocode}
+\renewcommand*{\DTLformatmanual}{%
+\DTLifbibfieldexists{Author}{\DTLformatauthorlist
+\DTLaddperiod}{%
+\DTLifbibfieldexists{Organization}{%
+\DTLstartsentencespace
+\DTLbibfield{Organization}%
+\DTLcheckbibfieldendsperiod{Organization}%
+\DTLifbibfieldexists{Address}{\DTLaddcomma \DTLbibfield{Address}%
+\DTLcheckbibfieldendsperiod{Address}%
+}{}%
+\DTLaddperiod}{}%
+}%
+\DTLifbibfieldexists{Title}{%
+\DTLstartsentencespace
+{\em\DTLbibfield{Title}}%
+\DTLcheckbibfieldendsperiod{Title}%
+\DTLifbibfieldexists{Author}{%
+\DTLifanybibfieldexists{Organization,Address}{%
+\DTLaddperiod}{\DTLaddcomma}}{%
+\DTLifanybibfieldexists{Organization,Address,Edition,Month,Year}{%
+\DTLaddcomma}{\DTLaddperiod}}}{}%
+\DTLifbibfieldexists{Author}{%
+\DTLifbibfieldexists{Organization}{%
+\DTLstartsentencespace
+\DTLbibfield{Organization}%
+\DTLcheckbibfieldendsperiod{Organization}%
+\DTLifanybibfieldexists{Address,Edition,Month,Year}{%
+\DTLaddcomma}{\DTLaddperiod}}{}%
+\DTLifbibfieldexists{Address}{%
+\DTLstartsentencespace
+\DTLbibfield{Address}%
+\DTLcheckbibfieldendsperiod{Address}%
+\DTLifanybibfieldexists{Edition,Month,Year}{%
+\DTLaddcomma}{\DTLaddperiod}}{}%
+}{%
+\DTLifbibfieldexists{Organization}{}{%
+\DTLifbibfieldexists{Address}{%
+\DTLstartsentencespace
+\DTLbibfield{Address}%
+\DTLcheckbibfieldendsperiod{Address}%
+\DTLifanybibfieldexists{Edition,Month,Year}{\DTLaddcomma}{%
+\DTLaddperiod}}{}}%
+}%
+\DTLifbibfieldexists{Edition}{%
+\protected@edef\@dtl@tmp{\DTLformatedition{\DTLbibfield{Edition}}}%
+\ifDTLmidsentence
+ \@dtl@tmp
+\else
+ \DTLstartsentencespace
+ \expandafter\MakeUppercase\@dtl@tmp
+\fi
+\expandafter\DTLcheckendsperiod\expandafter{\@dtl@tmp}%
+\DTLifanybibfieldexists{Month,Year}{\DTLaddcomma}{%
+\DTLaddperiod}}{}%
+\DTLformatdate
+\DTLifanybibfieldexists{Month,Year}{\DTLaddperiod}{}%
+\DTLifbibfieldexists{Note}{%
+\DTLstartsentencespace
+\DTLbibfield{Note}%
+\DTLcheckbibfieldendsperiod{Note}%
+\DTLaddperiod}{}%
+}%
+% \end{macrocode}
+% The format of a master's thesis.
+% \begin{macrocode}
+\renewcommand*{\DTLformatmastersthesis}{%
+\DTLifbibfieldexists{Author}{\DTLformatauthorlist\DTLaddperiod}{}%
+\DTLifbibfieldexists{Title}{%
+\DTLstartsentencespace
+\DTLbibfield{Title}%
+\DTLcheckbibfieldendsperiod{Title}%
+\DTLaddperiod}{}%
+\DTLifbibfieldexists{Type}{%
+\DTLstartsentencespace
+\DTLbibfield{Type}%
+\DTLcheckbibfieldendsperiod{Type}%
+\DTLifanybibfieldexists{School,Address,Month,Year}{%
+\DTLaddcomma}{\DTLaddperiod}}{}%
+\DTLifbibfieldexists{School}{%
+\DTLstartsentencespace
+\DTLbibfield{School}%
+\DTLcheckbibfieldendsperiod{School}%
+\DTLifanybibfieldexists{Address,Month,Year}{%
+\DTLaddcomma}{\DTLaddperiod}}{}%
+\DTLifbibfieldexists{Address}{%
+\DTLstartsentencespace
+\DTLbibfield{Address}%
+\DTLcheckbibfieldendsperiod{Address}%
+\DTLifanybibfieldexists{Month,Year}{%
+\DTLaddcomma}{\DTLaddperiod}}{}%
+\DTLformatdate
+\DTLifanybibfieldexists{Month,Year}{\DTLaddperiod}{}%
+\DTLifbibfieldexists{Note}{%
+\DTLstartsentencespace
+\DTLbibfield{Note}%
+\DTLcheckbibfieldendsperiod{Note}%
+\DTLaddperiod}{}%
+}%
+% \end{macrocode}
+% The format of a miscellaneous entry.
+% \begin{macrocode}
+\renewcommand*{\DTLformatmisc}{%
+\DTLifbibfieldexists{Author}{\DTLformatauthorlist\DTLaddperiod}{}%
+\DTLifbibfieldexists{Title}{%
+\DTLstartsentencespace
+\DTLbibfield{Title}%
+\DTLcheckbibfieldendsperiod{Title}%
+\DTLifbibfieldexists{HowPublished}{\DTLaddperiod}{%
+\DTLifanybibfieldexists{Month,Year}{\DTLaddcomma}{%
+\DTLaddperiod}%
+}%
+\DTLmidsentencefalse}{}%
+\DTLifbibfieldexists{HowPublished}{%
+\DTLstartsentencespace
+\DTLbibfield{HowPublished}%
+\DTLcheckbibfieldendsperiod{HowPublished}%
+\DTLifanybibfieldexists{Month,Year}{\DTLaddcomma}{%
+\DTLaddperiod}}{}%
+\DTLformatdate
+\DTLifanybibfieldexists{Month,Year}{\DTLaddperiod}{}%
+\DTLifbibfieldexists{Note}{%
+\DTLstartsentencespace
+\DTLbibfield{Note}%
+\DTLcheckbibfieldendsperiod{Note}%
+\DTLaddperiod}{}%
+}%
+% \end{macrocode}
+% The format of a PhD thesis.
+% \begin{macrocode}
+\renewcommand*{\DTLformatphdthesis}{%
+\DTLifbibfieldexists{Author}{\DTLformatauthorlist\DTLaddperiod}{}%
+\DTLifbibfieldexists{Title}{%
+\DTLstartsentencespace
+{\em\DTLbibfield{Title}}%
+\DTLcheckbibfieldendsperiod{Title}%
+\DTLaddperiod}{}%
+\DTLifbibfieldexists{Type}{%
+\DTLstartsentencespace
+\DTLbibfield{Type}%
+\DTLcheckbibfieldendsperiod{Type}%
+\DTLifanybibfieldexists{School,Address,Month,Year}{%
+\DTLaddcomma}{\DTLaddperiod}}{}%
+\DTLifbibfieldexists{School}{%
+\DTLstartsentencespace
+\DTLbibfield{School}%
+\DTLcheckbibfieldendsperiod{School}%
+\DTLifanybibfieldexists{Address,Month,Year}{%
+\DTLaddcomma}{\DTLaddperiod}}{}%
+\DTLifbibfieldexists{Address}{%
+\DTLstartsentencespace
+\DTLbibfield{Address}%
+\DTLcheckbibfieldendsperiod{Address}%
+\DTLifanybibfieldexists{Month,Year}{%
+\DTLaddcomma}{\DTLaddperiod}}{}%
+\DTLformatdate
+\DTLifanybibfieldexists{Month,Year}{\DTLaddperiod}{}%
+\DTLifbibfieldexists{Note}{%
+\DTLstartsentencespace
+\DTLbibfield{Note}%
+\DTLcheckbibfieldendsperiod{Note}%
+\DTLaddperiod}{}%
+}%
+% \end{macrocode}
+% The format of a proceedings.
+% \begin{macrocode}
+\renewcommand*{\DTLformatproceedings}{%
+\DTLifbibfieldexists{Editor}{%
+\DTLformateditorlist\DTLaddperiod}{%
+\DTLifbibfieldexists{Organization}{%
+\DTLstartsentencespace
+\DTLbibfield{Organization}%
+\DTLcheckbibfieldendsperiod{Organization}%
+\DTLaddperiod}{}}%
+\DTLifbibfieldexists{Title}{%
+\DTLstartsentencespace
+{\em\DTLbibfield{Title}}%
+\DTLcheckbibfieldendsperiod{Title}%
+\DTLifanybibfieldexists{Volume,Number,Address,Editor,Publisher,%
+Month,Year}{\DTLaddcomma}{\DTLaddperiod}%
+}{}%
+\DTLformatbvolume
+\DTLifbibfieldexists{Volume}{%
+\DTLifanybibfieldexists{Number,Address,Editor,Publisher,%
+Month,Year}{\DTLaddcomma}{\DTLaddperiod}}{}%
+\DTLformatnumberseries
+\DTLifbibfieldexists{Number}{%
+\DTLifanybibfieldexists{Address,Editor,Publisher,%
+Month,Year}{\DTLaddcomma}{\DTLaddperiod}}{}%
+\DTLifbibfieldexists{Address}{%
+\DTLstartsentencespace
+\DTLbibfield{Address}%
+\DTLcheckbibfieldendsperiod{Address}%
+\DTLifanybibfieldexists{Month,Year}{\DTLaddcomma}{\DTLaddperiod}%
+\DTLformatdate
+\DTLifanybibfieldexists{Month,Year}{\DTLaddperiod}{}%
+\DTLifbibfieldexists{Editor}{\DTLifbibfieldexists{Organization}{%
+\DTLstartsentencespace
+\DTLbibfield{Organization}%
+\DTLcheckbibfieldendsperiod{Organization}%
+\DTLifbibfieldexists{Publisher}{%
+\DTLaddcomma}{\DTLaddperiod}}{}}{}%
+\DTLifbibfieldexists{Publisher}{%
+\DTLstartsentencespace
+\DTLbibfield{Publisher}%
+\DTLcheckbibfieldendsperiod{Publisher}%
+\DTLaddperiod
+}{}%
+}{% no address
+\DTLifbibfieldexists{Editor}{%
+\DTLifbibfieldexists{Organization}{%
+\DTLstartsentencespace
+\DTLbibfield{Organization}%
+\DTLcheckbibfieldendsperiod{Organization}%
+\DTLifanybibfieldexists{Publisher,Month,Year}{%
+\DTLaddcomma}{\DTLaddperiod}}{}%
+}{}%
+\DTLifbibfieldexists{Publisher}{%
+\DTLstartsentencespace
+\DTLbibfield{Publisher}%
+\DTLcheckbibfieldendsperiod{Publisher}%
+\DTLifanybibfieldexists{Month,Year}{\DTLaddcomma}{\DTLaddperiod}}{}%
+\DTLformatdate
+\DTLifanybibfieldexists{Month,Year}{\DTLaddperiod}{}%
+}%
+\DTLifbibfieldexists{Note}{%
+\DTLstartsentencespace
+\DTLbibfield{Note}%
+\DTLcheckbibfieldendsperiod{Note}%
+\DTLaddperiod}{}%
+}%
+% \end{macrocode}
+% The format of a technical report.
+% \begin{macrocode}
+\renewcommand*{\DTLformattechreport}{%
+\DTLifbibfieldexists{Author}{\DTLformatauthorlist\DTLaddperiod}{}%
+\DTLifbibfieldexists{Title}{%
+\DTLstartsentencespace
+\DTLbibfield{Title}%
+\DTLcheckbibfieldendsperiod{Title}%
+\DTLaddperiod}{}%
+\DTLifbibfieldexists{Type}{%
+\DTLstartsentencespace
+\DTLbibfield{Type}%
+\DTLcheckbibfieldendsperiod{Type}%
+\DTLifbibfieldexists{Number}{~}{}}{}%
+\DTLifbibfieldexists{Number}{%
+\DTLstartsentencespace
+\DTLbibfield{Number}%
+\DTLcheckbibfieldendsperiod{Number}%
+}{}%
+\DTLifanybibfieldexists{Type,Number}{%
+\DTLifanybibfieldexists{Institution,Address,Month,Year}{\DTLaddcomma
+}{\DTLaddperiod}}{}%
+\DTLifbibfieldexists{Institution}{%
+\DTLstartsentencespace
+\DTLbibfield{Institution}%
+\DTLcheckbibfieldendsperiod{Institution}%
+\DTLifanybibfieldexists{Address,Month,Year}{\DTLaddcomma
+}{\DTLaddperiod}}{}%
+\DTLifbibfieldexists{Address}{%
+\DTLstartsentencespace
+\DTLbibfield{Address}%
+\DTLcheckbibfieldendsperiod{Address}%
+\DTLifanybibfieldexists{Month,Year}{\DTLaddcomma
+}{\DTLaddperiod}}{}%
+\DTLformatdate
+\DTLifanybibfieldexists{Month,Year}{\DTLaddperiod}{}%
+\DTLifbibfieldexists{Note}{%
+\DTLstartsentencespace
+\DTLbibfield{Note}%
+\DTLcheckbibfieldendsperiod{Note}%
+\DTLaddperiod}{}%
+}%
+% \end{macrocode}
+% The format of an unpublished work.
+% \begin{macrocode}
+\renewcommand*{\DTLformatunpublished}{%
+\DTLifbibfieldexists{Author}{\DTLformatauthorlist\DTLaddperiod}{}%
+\DTLifbibfieldexists{Title}{%
+\DTLstartsentencespace
+\DTLbibfield{Title}%
+\DTLcheckbibfieldendsperiod{Title}%
+\DTLaddperiod}{}%
+\DTLifbibfieldexists{Note}{%
+\DTLstartsentencespace
+\DTLbibfield{Note}%
+\DTLcheckbibfieldendsperiod{Note}%
+\DTLifanybibfieldexists{Month,Year}{\DTLaddcomma}{\DTLaddperiod}}{}%
+\DTLformatdate
+\DTLifanybibfieldexists{Month,Year}{\DTLaddperiod}{}%
+}%
+% \end{macrocode}
+% End of `plain' style.
+% \begin{macrocode}
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLformatbooktitle}
+%\changes{2.22}{2014-06-10}{new}
+% \begin{macrocode}
+\newcommand*{\DTLformatbooktitle}[1]{\emph{#1}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlbst@abbrv}
+% Define `abbrv' style. This is similar to `plain' except that
+% some of the values are abbreviated
+% \begin{macrocode}
+\newcommand{\dtlbst@abbrv}{%
+% \end{macrocode}
+% Base this style on `plain':
+% \begin{macrocode}
+\dtlbst@plain
+% \end{macrocode}
+% Sets the author name format.
+% \begin{macrocode}
+\renewcommand*{\DTLformatauthor}[4]{%
+\DTLformatabbrvforenames{##4}
+\DTLformatvon{##1}%
+\DTLformatsurname{##2}%
+\DTLformatjr{##3}}
+% \end{macrocode}
+% Sets the editor name format.
+% \begin{macrocode}
+\renewcommand*{\DTLformateditor}[4]{%
+\DTLformatabbrvforenames{##4}
+\DTLformatvon{##1}%
+\DTLformatsurname{##2}%
+\DTLformatjr{##3}}
+% \end{macrocode}
+% Sets the monthname format.
+% \begin{macrocode}
+\let\DTLmonthname\dtl@abbrvmonthname
+% \end{macrocode}
+% Sets other predefined names:
+% \begin{macrocode}
+\renewcommand*{\DTLacmcs}{ACM Comput.\ Surv.}
+\renewcommand*{\DTLacta}{Acta Inf.}
+\renewcommand*{\DTLcacm}{Commun.\ ACM}
+\renewcommand*{\DTLibmjrd}{IBM J.\ Res.\ Dev.}
+\renewcommand*{\DTLibmsj}{IBM Syst.~J.}
+\renewcommand*{\DTLieeese}{IEEE Trans. Softw.\ Eng.}
+\renewcommand*{\DTLieeetc}{IEEE Trans.\ Comput.}
+\renewcommand*{\DTLieeetcad}{IEEE Trans.\ Comput.-Aided Design
+Integrated Circuits}
+\renewcommand*{\DTLipl}{Inf.\ Process.\ Lett.}
+\renewcommand*{\DTLjacm}{J.~ACM}
+\renewcommand*{\DTLjcss}{J.~Comput.\ Syst.\ Sci.}
+\renewcommand*{\DTLscp}{Sci.\ Comput.\ Programming}
+\renewcommand*{\DTLsicomp}{SIAM J.~Comput.}
+\renewcommand*{\DTLtocs}{ACM Trans.\ Comput.\ Syst.}
+\renewcommand*{\DTLtods}{ACM Trans.\ Database Syst.}
+\renewcommand*{\DTLtog}{ACM Trans.\ Gr.}
+\renewcommand*{\DTLtoms}{ACM Trans.\ Math. Softw.}
+\renewcommand*{\DTLtoois}{ACM Trans. Office Inf.\ Syst.}
+\renewcommand*{\DTLtoplas}{ACM Trans.\ Prog. Lang.\ Syst.}
+\renewcommand*{\DTLtcs}{Theoretical Comput.\ Sci.}
+% \end{macrocode}
+% End of `abbrv' style.
+% \begin{macrocode}
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlbst@alpha}
+% Define `alpha' style. This is similar to `plain' except that
+% the labels are strings rather than numerical.
+% \begin{macrocode}
+\newcommand{\dtlbst@alpha}{%
+% \end{macrocode}
+% Base this style on `plain':
+% \begin{macrocode}
+\dtlbst@plain
+% \end{macrocode}
+% Set how to format the entire bibliography:
+% \begin{macrocode}
+\renewenvironment{DTLthebibliography}[2][\boolean{true}]{%
+\dtl@createalphabiblabels{##1}{##2}%
+\begin{thebibliography}{\@dtl@widestlabel}%
+}{\end{thebibliography}}%
+% \end{macrocode}
+% Set how to start the bibliography entry:
+% \begin{macrocode}
+\renewcommand*{\DTLbibitem}{%
+\expandafter\bibitem\expandafter
+ [\csname dtl@biblabel@\DBIBcitekey\endcsname]{\DBIBcitekey}}%
+\renewcommand*{\DTLmbibitem}[1]{%
+\expandafter\bibitem\expandafter
+ [\csname dtl@biblabel@\DBIBcitekey\endcsname]{##1@\DBIBcitekey}}%
+% \end{macrocode}
+% End of `alpha' style.
+% \begin{macrocode}
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{dtl@createalphabiblabels}
+%\begin{definition}
+%\cs{dtl@createalphabiblabels}\marg{condition}\marg{db name}
+%\end{definition}
+% Constructs the alpha style bib labels for the given database.
+% (Labels are stored in the control sequence
+%\cs{dtl@biblabel@}\meta{citekey}.) This also sets
+% \cs{@dtl@widestlabel} to the widest label.
+% \begin{macrocode}
+\newcommand*{\dtl@createalphabiblabels}[2]{%
+\dtl@message{Creating bib labels}%
+\begingroup
+\gdef\@dtl@widestlabel{}%
+\dtl@widest=0pt\relax
+\DTLforeachbibentry[#1]{#2}{%
+\dtl@message{\DBIBcitekey}%
+\DTLifbibfieldexists{Author}{%
+ \dtl@listgetalphalabel{\@dtl@thislabel}{\@dtl@key@Author}%
+}{%
+\DTLifbibfieldexists{Editor}{%
+ \dtl@listgetalphalabel{\@dtl@thislabel}{\@dtl@key@Editor}%
+ }{%
+ \DTLifbibfieldexists{Key}{%
+ \expandafter\dtl@get@firstthree\expandafter
+ {\@dtl@key@Key}{\@dtl@thislabel}%
+ }{%
+ \DTLifbibfieldexists{Organization}{%
+ \expandafter\dtl@get@firstthree\expandafter
+ {\@dtl@key@Organization}{\@dtl@thislabel}%
+ }{%
+ \expandafter\dtl@get@firstthree\expandafter
+ {\DBIBentrytype}{\@dtl@thislabel}%
+ }%
+ }}}%
+\DTLifbibfieldexists{Year}{}{\DTLifbibfieldexists{CrossRef}{%
+\DTLgetvalueforkey{\@dtl@key@Year}{Year}{#2}{CiteKey}{%
+\@dtl@key@CrossRef}}{}}%
+\DTLifbibfieldexists{Year}{%
+\expandafter\dtl@get@yearsuffix\expandafter{\@dtl@key@Year}%
+\expandafter\toks@\expandafter{\@dtl@thislabel}%
+\expandafter\@dtl@toks\expandafter{\@dtl@year}%
+\edef\@dtl@thislabel{\the\toks@\the\@dtl@toks}%
+}{}%
+\let\@dtl@s@thislabel=\@dtl@thislabel
+\@onelevel@sanitize\@dtl@s@thislabel
+\@ifundefined{c@biblabel@\@dtl@s@thislabel}{%
+\newcounter{biblabel@\@dtl@s@thislabel}%
+\setcounter{biblabel@\@dtl@s@thislabel}{1}%
+\expandafter\edef\csname @dtl@bibfirst@\@dtl@s@thislabel\endcsname{%
+\DBIBcitekey}%
+\expandafter\global
+\expandafter\let\csname dtl@biblabel@\DBIBcitekey\endcsname=
+ \@dtl@thislabel
+}{%
+\expandafter\ifnum\csname c@biblabel@\@dtl@s@thislabel\endcsname=1\relax
+ \expandafter\let\expandafter\@dtl@tmp
+ \csname @dtl@bibfirst@\@dtl@s@thislabel\endcsname
+ \expandafter\protected@xdef\csname dtl@biblabel@\@dtl@tmp\endcsname{%
+ \@dtl@thislabel a}%
+\fi
+\stepcounter{biblabel@\@dtl@s@thislabel}%
+\expandafter\protected@xdef\csname dtl@biblabel@\DBIBcitekey\endcsname{%
+ \@dtl@thislabel\alph{biblabel@\@dtl@s@thislabel}}%
+}%
+\settowidth{\dtl@tmplength}{%
+ \csname dtl@biblabel@\DBIBcitekey\endcsname}%
+\ifdim\dtl@tmplength>\dtl@widest
+ \dtl@widest=\dtl@tmplength
+ \expandafter\global\expandafter\let\expandafter\@dtl@widestlabel
+ \expandafter=\csname dtl@biblabel@\DBIBcitekey\endcsname
+\fi
+}%
+\endgroup
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@listgetalphalabel}
+% Determine the alpha style label from a list of authors/editors
+% (the first argument must be a control sequence (in which the
+% label is stored), the second argument must be the list of names.)
+% \begin{macrocode}
+\newcommand*{\dtl@listgetalphalabel}[2]{%
+\@dtl@authorcount=0\relax
+\@for\@dtl@author:=#2\do{%
+\advance\@dtl@authorcount by 1\relax}%
+\ifnum\@dtl@authorcount=1\relax
+ \expandafter\dtl@getsinglealphalabel#2{#1}\relax
+\else
+ {%
+ \xdef#1{}%
+ \@dtl@tmpcount=0\relax
+ \def\DTLafterinitials{}\def\DTLbetweeninitials{}%
+ \def\DTLafterinitialbeforehyphen{}\def\DTLinitialhyphen{}%
+ \@for\@dtl@author:=#2\do{%
+ \expandafter\dtl@getauthorinitial\@dtl@author
+ \expandafter\toks@\expandafter{\@dtl@tmp}%
+ \expandafter\@dtl@toks\expandafter{#1}%
+ \xdef#1{\the\@dtl@toks\the\toks@}%
+ \advance\@dtl@tmpcount by 1\relax
+ \ifnum\@dtl@tmpcount>2\relax\@endfortrue\fi
+ }}%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+% Get author's initial (stores in \cs{@dtl@tmp}):
+% \begin{macrocode}
+\newcommand*{\dtl@getauthorinitial}[4]{%
+\def\@dtl@vonpart{#1}%
+\ifx\@dtl@vonpart\@empty
+ \DTLstoreinitials{#2}{\@dtl@tmp}%
+\else
+ \DTLstoreinitials{#1 #2}{\@dtl@tmp}%
+\fi}
+% \end{macrocode}
+% Get label for single author (last argument is control sequence
+% in which to store the label):
+% \begin{macrocode}
+\newcommand*{\dtl@getsinglealphalabel}[5]{%
+\def\@dtl@vonpart{#1}%
+\ifx\@dtl@vonpart\@empty
+ \DTLifSubString{#2}{-}{%
+ {\def\DTLafterinitials{}\def\DTLbetweeninitials{}%
+ \def\DTLafterinitialbeforehyphen{}%
+ \def\DTLinitialhyphen{}%
+ \DTLstoreinitials{#2}{\@dtl@tmp}\global\let#5=\@dtl@tmp}%
+ }{%
+ \dtl@getfirstthree{#5}#2{}{}{}{}\@nil
+ }
+\else
+ {\def\DTLafterinitials{}\def\DTLbetweeninitials{}%
+ \def\DTLafterinitialbeforehyphen{}%
+ \def\DTLinitialhyphen{}%
+ \DTLstoreinitials{#1 #2}{\@dtl@tmp}\global\let#5=\@dtl@tmp}%
+\fi
+}
+% \end{macrocode}
+%Get first three letters from the given string:
+% \begin{macrocode}
+\def\dtl@getfirstthree#1#2#3#4#5\@nil{%
+ \def#1{#2#3#4}%
+}
+\newcommand*{\dtl@get@firstthree}[2]{%
+\dtl@getfirstthree#2#1{}{}{}{}{}\@nil}
+% \end{macrocode}
+%Get year suffix:
+% \begin{macrocode}
+\newcommand*{\dtl@get@yearsuffix}[1]{%
+\dtl@getyearsuffix#1\@nil\relax\relax}
+
+\def\dtl@getyearsuffix#1#2#3{%
+\def\@dtl@argi{#1}\def\@dtl@argii{#2}%
+\def\@dtl@argiii{#3}%
+\ifx\@dtl@argi\@nnil
+ \def\@dtl@year{}%
+ \let\@dtl@donext=\relax
+\else
+ \ifx\@dtl@argii\@nnil
+ \dtl@ifsingle{#1}{%
+ \def\@dtl@year{#1}%
+ \let\@dtl@donext=\relax
+ }{%
+ \def\@dtl@donext{\dtl@getyearsuffix#1#2#3}%
+ }%
+ \else
+ \ifx\@dtl@argiii\@nnil
+ \dtl@ifsingle{#1}{%
+ \dtl@ifsingle{#2}{%
+ \def\@dtl@year{#1#2}%
+ \let\@dtl@donext=\relax
+ }{%
+ \def\@dtl@donext{\dtl@getyearsuffix#2#3}%
+ }%
+ }{%
+ \def\@dtl@donext{\dtl@getyearsuffix#2#3}%
+ }%
+ \else
+ \def\@dtl@donext{\dtl@getyearsuffix{#2}{#3}}%
+ \fi
+ \fi
+\fi
+\@dtl@donext
+}
+% \end{macrocode}
+%
+%\begin{macro}{\DTLbibliographystyle}
+%\begin{definition}
+%\cs{DTLbibliographystyle}\marg{style}
+%\end{definition}
+% Sets the bibliography style.
+% \begin{macrocode}
+\newcommand*{\DTLbibliographystyle}[1]{%
+\@ifundefined{dtlbst@#1}{\PackageError{databib}{Unknown
+bibliography style `#1'}{}}{\csname dtlbst@#1\endcsname}}
+% \end{macrocode}
+%\end{macro}
+%Set the default bibliography style:
+% \begin{macrocode}
+\DTLbibliographystyle{\dtlbib@style}
+% \end{macrocode}
+%
+%\section{Multiple Bibliographies}
+% In order to have multiple bibliographies, there needs to be
+% an aux file for each bibliography. The main bibliography is in
+% \cs{jobname}.aux, but need to provide a means of creating
+% additional aux files.
+%\begin{macro}{\DTLmultibibs}
+%\begin{definition}
+%\cs{DTLmultibibs}\marg{list}
+%\end{definition}
+%\changes{1.01}{2007/08/22}{new}
+% This creates an auxiliary file for each name in \meta{list}.
+% For example, "\DTLmultibibs{foo,bar}" will create the files
+% "foo.aux" and "bar.aux".
+% \begin{macrocode}
+\newcommand*{\DTLmultibibs}[1]{%
+\@for\@dtl@af:=#1\do{%
+\@ifundefined{dtl@aux@\@dtl@af}{%
+\expandafter\newwrite\csname dtl@aux@\@dtl@af\endcsname
+\expandafter\immediate
+\expandafter\openout\csname dtl@aux@\@dtl@af\endcsname=\@dtl@af.aux
+\expandafter\def\csname b@\@dtl@af @*\endcsname{}%
+}{%
+\PackageError{databib}{Can't create auxiliary file `\@dtl@af.aux',
+\expandafter\string\csname dtl@aux@\@dtl@af\endcsname\space
+already exists}{}}}}
+% \end{macrocode}
+% Can only be used in the preamble:
+% \begin{macrocode}
+\@onlypreamble{\DTLmultibibs}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLcite}
+%\begin{definition}
+%\cs{DTLcite}\oarg{text}\marg{mbib}\marg{labels}
+%\end{definition}
+% This is similar to \cs{cite}\oarg{text}\marg{labels}, except
+% 1) the cite information is written to the auxiliary file
+% associated with the multi-bib \meta{mbib} (which must be named
+% in \cs{DTLmultibibs}) and 2) the cross referencing label is
+% constructed from \meta{mbib} and \meta{label} to allow for
+% the same citation to appear in multiple bibliographies.
+% \begin{macrocode}
+\newcommand*{\DTLcite}{\@ifnextchar[{\@tempswatrue \dtl@citex
+}{\@tempswafalse \dtl@citex[]}}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtl@citex}
+% \begin{macrocode}
+\def\dtl@citex[#1]#2#3{%
+\leavevmode\let\@citea\@empty
+\@cite{\@for\@citeb:=#3\do{\@citea
+ \def\@citea{,\penalty \@m \ }%
+ \edef\@citeb{\expandafter\@firstofone\@citeb\@empty}%
+ \if@filesw
+ \@ifundefined{dtl@aux@#2}{%
+ \PackageError{databib}{multibib `#2' not defined}{%
+ You need to define `#2' in \string\DTLmutlibibs}%
+ }{%
+ \expandafter\immediate
+ \expandafter\write\csname dtl@aux@#2\endcsname{%
+ \string\citation{\@citeb}}%
+ }%
+ \fi
+ \@ifundefined{b@#2@\@citeb}{%
+ \hbox{\reset@font\bfseries ?}%
+ \G@refundefinedtrue
+ \@latex@warning{Citation `\@citeb ' on page \thepage \space
+ undefined}%
+ }{%
+ \@cite@ofmt{\csname b@#2@\@citeb \endcsname }%
+ }%
+}}{#1}%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLnocite}
+%\begin{definition}
+%\cs{DTLnocite}\marg{mbib}\marg{key list}
+%\end{definition}
+% As \cs{nocite} but uses the aux file associated with \meta{mbib}
+% which must have been defined using \cs{DTLmultibibs}.
+% \begin{macrocode}
+\newcommand*{\DTLnocite}[2]{%
+\@ifundefined{dtl@aux@#1}{%
+ \PackageError{databib}{multibib `#1' not defined}{%
+ You need to define `#1' in \string\DTLmutlibibs}%
+}{%
+ \@bsphack
+ \ifx\@onlypreamble\document
+ \@for\@citeb:=#2\do{%
+ \edef\@citeb{\expandafter\@firstofone\@citeb}%
+ \if@filesw
+ \expandafter\immediate
+ \expandafter\write\csname dtl@aux@#1\endcsname{%
+ \string\citation{\@citeb}}%
+ \fi
+ \@ifundefined{b@#1@\@citeb}{%
+ \G@refundefinedtrue
+ \@latex@warning{Citation `\@citeb ' undefined}}{}%
+ }%
+ \else
+ \@latex@error{Cannot be used in preamble}\@eha
+ \fi
+ \@esphack
+}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLloadmbbl}
+%\begin{definition}
+%\cs{DTLloadmbib}\marg{mbib}\marg{db name}\marg{bib list}
+%\end{definition}
+% \begin{macrocode}
+\newcommand*{\DTLloadmbbl}[3]{%
+\@ifundefined{dtl@aux@#1}{%
+ \PackageError{databib}{multibib `#1' not defined}{%
+ You need to define `#1' in \string\DTLmutlibibs}%
+}{%
+ \if@filesw
+ \expandafter\immediate\expandafter
+ \write\csname dtl@aux@#1\endcsname{\string\bibstyle{databib}}%
+ \expandafter\immediate\expandafter
+ \write\csname dtl@aux@#1\endcsname{\string\bibdata{#3}}%
+ \fi
+ \DTLnewdb{#2}%
+ \edef\DTLBIBdbname{#2}%
+ \@input@{#1.bbl}%
+}%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{definition}
+%\cs{DTLmbibliography}\oarg{condition}\marg{mbib name}\marg{bib dbname}
+%\end{definition}
+% Displays the bibliography for the database \meta{bib dbname}
+% which must have previously been loaded using
+% \cs{DTLloadmbbl}, where \meta{mbib name} must be listed
+% in \cs{DTLmultibibs}.
+%\begin{macro}{\DTLmbibliography}
+% \begin{macrocode}
+\newcommand*{\DTLmbibliography}[3][\boolean{true}]{%
+\begin{DTLthebibliography}[#1]{#3}%
+\DTLforeachbibentry[#1]{#3}{%
+\DTLmbibitem{#2} \DTLformatbibentry \DTLendbibitem
+}%
+\end{DTLthebibliography}%
+}
+% \end{macrocode}
+%\end{macro}
+%\iffalse
+% \begin{macrocode}
+%</databib.sty>
+% \end{macrocode}
+%\fi
+%\iffalse
+% \begin{macrocode}
+%<*databar.sty>
+% \end{macrocode}
+%\fi
+%\chapter{databar.sty}
+% Declare package:
+% \begin{macrocode}
+\NeedsTeXFormat{LaTeX2e}
+\ProvidesPackage{databar}[2018/12/07 v2.31 (NLCT)]
+% \end{macrocode}
+% Require \sty{xkeyval} package
+% \begin{macrocode}
+\RequirePackage{xkeyval}
+% \end{macrocode}
+% Require \sty{dataplot} package
+% \begin{macrocode}
+\RequirePackage{dataplot}
+% \end{macrocode}
+%\begin{macro}{\ifDTLcolorbarchart}
+% The conditional \cs{ifDTLcolorbarchart} is used to determine
+% whether to use colour or grey scale.
+% \begin{macrocode}
+\newif\ifDTLcolorbarchart
+\DTLcolorbarcharttrue
+% \end{macrocode}
+%\end{macro}
+% Package options to change the conditional:
+% \begin{macrocode}
+\DeclareOption{color}{\DTLcolorbarcharttrue}
+\DeclareOption{gray}{\DTLcolorbarchartfalse}
+% \end{macrocode}
+%\cs{DTLbarXlabelalign} specifies the alignment
+% for the $x$ axis labels.
+% \begin{macrocode}
+\newcommand*{\DTLbarXlabelalign}{left,rotate=-90}
+% \end{macrocode}
+%\cs{DTLbarYticklabelalign} specifies the alignment
+% for the $x$ axis labels.
+% \begin{macrocode}
+\newcommand*{\DTLbarYticklabelalign}{right}
+% \end{macrocode}
+%\begin{macro}{\ifDTLverticalbars}
+% Define boolean keys to govern bar chart orientation.
+% \begin{macrocode}
+\define@boolkey{databar}[DTL]{verticalbars}[true]{%
+\ifDTLverticalbars
+ \def\DTLbarXlabelalign{left,rotate=-90}%
+ \def\DTLbarYticklabelalign{right}
+\else
+ \def\DTLbarXlabelalign{right}%
+ \def\DTLbarYticklabelalign{center}
+\fi}
+% \end{macrocode}
+%\end{macro}
+% Set defaults:
+% \begin{macrocode}
+\DTLverticalbarstrue
+% \end{macrocode}
+% Package options to change \cs{ifDTLverticalbars}
+% \begin{macrocode}
+\DeclareOption{vertical}{\DTLverticalbarstrue
+ \def\DTLbarXlabelalign{left,rotate=-90}%
+ \def\DTLbarYticklabelalign{right}
+}
+\DeclareOption{horizontal}{\DTLverticalbarsfalse
+ \def\DTLbarXlabelalign{right}%
+ \def\DTLbarYticklabelalign{center}
+}
+% \end{macrocode}
+% Process options:
+% \begin{macrocode}
+\ProcessOptions
+% \end{macrocode}
+% Required packages:
+% \begin{macrocode}
+\RequirePackage{datatool}
+\RequirePackage{tikz}
+% \end{macrocode}
+% Define some variables that govern the appearance of the bar
+% chart.
+%
+%\begin{macro}{\DTLbarchartlength}
+% The total height of the bar chart is given by \cs{DTLbarchartheight}
+% \begin{macrocode}
+\newlength\DTLbarchartlength
+\DTLbarchartlength=3in
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLbarwidth}
+% The width of each bar is given by \cs{DTLbarwidth}.
+% \begin{macrocode}
+\newlength\DTLbarwidth
+\DTLbarwidth=1cm
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLbarlabeloffset}
+% The offset from the $x$ axis to the bar label if given by
+% \cs{DTLbarlabeloffset}.
+% \begin{macrocode}
+\newlength\DTLbarlabeloffset
+\setlength\DTLbarlabeloffset{10pt}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLBarXAxisStyle}
+% The style of the $x$ axis is given by \cs{DTLBarXAxisStyle}
+% \begin{macrocode}
+\newcommand*{\DTLBarXAxisStyle}{-}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLBarYAxisStyle}
+% The style of the $y$ axis is given by \cs{DTLBarYAxisStyle}.
+% \begin{macrocode}
+\newcommand*{\DTLBarYAxisStyle}{-}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{counter}{DTLbarroundvar}
+% \ctrfmt{DTLbarroundvar} is a counter governing the number of digits
+% to round to when using \cs{FPround}.
+% \begin{macrocode}
+\newcounter{DTLbarroundvar}
+\setcounter{DTLbarroundvar}{1}
+% \end{macrocode}
+%\end{counter}
+%
+%\begin{macro}{\DTLbardisplayYticklabel}
+%\cs{DTLbardisplayYticklabel} governs how the $y$ tick labels appear.
+% \begin{macrocode}
+\newcommand*{\DTLbardisplayYticklabel}[1]{#1}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLdisplaylowerbarlabel}
+%\cs{DTLdisplaylowerbarlabel} governs how the lower bar labels appear.
+% \begin{macrocode}
+\newcommand*{\DTLdisplaylowerbarlabel}[1]{#1}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLdisplaylowermultibarlabel}
+%\cs{DTLdisplaylowermultibarlabel} governs how the lower multi bar labels appear.
+% \begin{macrocode}
+\newcommand*{\DTLdisplaylowermultibarlabel}[1]{#1}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLdisplayupperbarlabel}
+%\cs{DTLdisplayupperbarlabel} governs how the upper bar labels
+% appear.
+% \begin{macrocode}
+\newcommand*{\DTLdisplayupperbarlabel}[1]{#1}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLdisplayuppermultibarlabel}
+%\cs{DTLdisplayuppermultibarlabel} governs how the upper multi bar
+% labels appear.
+% \begin{macrocode}
+\newcommand*{\DTLdisplayuppermultibarlabel}[1]{#1}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLbaratbegintikz}
+% \cs{DTLbaratbegintikz} specifies any commands
+% to apply at the start of the \env{tikzpicture} environment.
+% By default it does nothing.
+% \begin{macrocode}
+\newcommand*{\DTLbaratbegintikz}{}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLbaratendtikz}
+% \cs{DTLbaratendtikz} specifies any commands
+% to apply at the end of the \env{tikzpicture} environment.
+% By default it does nothing.
+% \begin{macrocode}
+\newcommand*{\DTLbaratendtikz}{}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\ifDTLbarxaxis}
+% The conditional \cs{ifDTLbarxaxis} is used to determine
+% whether or not to display the $x$ axis
+% \begin{macrocode}
+\newif\ifDTLbarxaxis
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\ifDTLbaryaxis}
+% The conditional \cs{ifDTLbaryaxis} is used to determine
+% whether or not to display the $y$ axis.
+% \begin{macrocode}
+\newif\ifDTLbaryaxis
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\ifDTLbarytics}
+% The conditional \cs{ifDTLbarytics} to determine whether
+% or not to display the $y$ tick marks.
+% \begin{macrocode}
+\newif\ifDTLbarytics
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@barcount}
+% The count register \cs{@dtl@barcount} is used to store
+% the current bar index.
+% \begin{macrocode}
+\newcount\@dtl@barcount
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLsetbarcolor}
+%\begin{definition}
+% \cs{DTLsetbarcolor}\marg{n}\marg{color}
+%\end{definition}
+% Assigns colour name \meta{color} to the \meta{n}th bar.
+% \begin{macrocode}
+\newcommand*{\DTLsetbarcolor}[2]{%
+\expandafter\def\csname dtlbar@segcol\romannumeral#1\endcsname{#2}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLgetbarcolor}
+%\begin{definition}
+%\cs{DTLgetbarcolor}\marg{n}
+%\end{definition}
+% Gets the colour specification for the \meta{n}th bar.
+% \begin{macrocode}
+\newcommand*{\DTLgetbarcolor}[1]{%
+\csname dtlbar@segcol\romannumeral#1\endcsname}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLdobarcolor}
+%\begin{definition}
+%\cs{DTLdobarcolor}\marg{n}
+%\end{definition}
+% Sets the colour to that for the \meta{n}th bar.
+% \begin{macrocode}
+\newcommand*{\DTLdobarcolor}[1]{%
+\expandafter\color\expandafter
+{\csname dtlbar@segcol\romannumeral#1\endcsname}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLdocurrentbarcolor}
+%\cs{DTLdocurrentbarcolor}
+% sets the colour to that of the current bar.
+% \begin{macrocode}
+\newcommand*{\DTLdocurrentbarcolor}{%
+\ifnum\dtlforeachlevel=0\relax
+ \PackageError{databar}{Can't use
+ \string\DTLdocurrentbarcolor\space outside
+ \string\DTLbarchart}{}%
+\else
+ \expandafter\DTLdobarcolor\expandafter{%
+ \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname}%
+\fi}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLbaroutlinecolor}
+%\cs{DTLbaroutlinecolor} specifies what colour to draw the
+% outline.
+% \begin{macrocode}
+\newcommand*{\DTLbaroutlinecolor}{black}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLbaroutlinewidth}
+%\cs{DTLbaroutlinewidth} specifies the line width of the outline:
+% Outline is only drawn if the linewidth is greater than 0pt.
+% \begin{macrocode}
+\newlength\DTLbaroutlinewidth
+\DTLbaroutlinewidth=0pt
+% \end{macrocode}
+%\end{macro}
+%
+% Set the default colours. If there are more than eight bars,
+% more colours will need to be defined.
+% \begin{macrocode}
+\ifDTLcolorbarchart
+ \DTLsetbarcolor{1}{red}
+ \DTLsetbarcolor{2}{green}
+ \DTLsetbarcolor{3}{blue}
+ \DTLsetbarcolor{4}{yellow}
+ \DTLsetbarcolor{5}{magenta}
+ \DTLsetbarcolor{6}{cyan}
+ \DTLsetbarcolor{7}{orange}
+ \DTLsetbarcolor{8}{white}
+\else
+ \DTLsetbarcolor{1}{black!15}
+ \DTLsetbarcolor{2}{black!25}
+ \DTLsetbarcolor{3}{black!35}
+ \DTLsetbarcolor{4}{black!45}
+ \DTLsetbarcolor{5}{black!55}
+ \DTLsetbarcolor{6}{black!65}
+ \DTLsetbarcolor{7}{black!75}
+ \DTLsetbarcolor{8}{black!85}
+\fi
+% \end{macrocode}
+%\begin{macro}{\DTLeverybarhook}
+% Code to apply at every bar. The start point of the bar
+% can be accessed via \cs{DTLstartpt}, the mid point of the bar
+% can be accessed via \cs{DTLmidpt} and the end point of the
+% bar can be accessed via \cs{DTLendpt}
+%\changes{2.0}{2009 February 27}{new}%
+% \begin{macrocode}
+\newcommand*{\DTLeverybarhook}{}
+% \end{macrocode}
+%\end{macro}
+%
+% Define keys for \cs{DTLbarchart} optional argument.
+% Set the maximum value of the $y$ axis.
+% \begin{macrocode}
+\define@key{databar}{max}{\def\DTLbarmax{#1}}
+% \end{macrocode}
+% Set the total length of the bar chart
+% \begin{macrocode}
+\define@key{databar}{length}{\DTLbarchartlength=#1\relax
+}
+% \end{macrocode}
+% Set the maximum depth (negative extent)
+% \begin{macrocode}
+\define@key{databar}{maxdepth}{%
+\ifnum#1>0\relax
+ \PackageError{databar}{depth must be zero or negative}{}%
+\else
+ \def\DTLnegextent{#1}%
+\fi}
+% \end{macrocode}
+% Determine which axes should be shown
+% \begin{macrocode}
+\define@choicekey{databar}{axes}[\var\nr]{both,x,y,none}{%
+\ifcase\nr\relax
+ % both
+ \DTLbarxaxistrue
+ \DTLbaryaxistrue
+ \DTLbaryticstrue
+\or
+ % x only
+ \DTLbarxaxistrue
+ \DTLbaryaxisfalse
+ \DTLbaryticsfalse
+\or
+ % y only
+ \DTLbarxaxisfalse
+ \DTLbaryaxistrue
+ \DTLbaryticstrue
+\or
+ % neither
+ \DTLbarxaxisfalse
+ \DTLbaryaxisfalse
+ \DTLbaryticsfalse
+\fi
+}
+% \end{macrocode}
+% Variable used to create the bar chart. (Must be a control
+% sequence.)
+% \begin{macrocode}
+\define@key{databar}{variable}{%
+ \def\DTLbarvariable{#1}%
+}
+% \end{macrocode}
+% Variables used to create the multi bar chart. (Must be a
+% comma separated list of control sequences.)
+% \begin{macrocode}
+\define@key{databar}{variables}{%
+ \def\dtlbar@variables{#1}%
+}
+% \end{macrocode}
+% Bar width
+% \begin{macrocode}
+\define@key{databar}{barwidth}{\setlength{\DTLbarwidth}{#1}}
+% \end{macrocode}
+% Lower bar labels
+% \begin{macrocode}
+\define@key{databar}{barlabel}{%
+\def\dtl@barlabel{#1}}
+\def\dtl@barlabel{}
+% \end{macrocode}
+% Lower bar labels for multi-bar charts
+% \begin{macrocode}
+\define@key{databar}{multibarlabels}{%
+\def\dtl@multibarlabels{#1}}
+\def\dtl@multibarlabels{}
+% \end{macrocode}
+% Gap between groups in multi-bar charts (This should be in $x$ units
+% where 1 $x$ unit is the width of a bar.)
+% \begin{macrocode}
+\define@key{databar}{groupgap}{\def\dtlbar@groupgap{#1}}
+\def\dtlbar@groupgap{1}
+% \end{macrocode}
+% Upper bar labels
+% \begin{macrocode}
+\define@key{databar}{upperbarlabel}{%
+\def\dtl@upperbarlabel{#1}}
+\def\dtl@upperbarlabel{}
+% \end{macrocode}
+% Upper bar labels for multi-bar charts
+% \begin{macrocode}
+\define@key{databar}{uppermultibarlabels}{%
+\def\dtl@uppermultibarlabels{#1}}
+\def\dtl@uppermultibarlabels{}
+% \end{macrocode}
+% Define list of points for $y$ tics. (Must be a comma separated list
+% of decimal numbers.)
+% \begin{macrocode}
+\define@key{databar}{yticpoints}{%
+\def\dtlbar@yticlist{#1}\DTLbaryticstrue\DTLbaryaxistrue}
+\let\dtlbar@yticlist=\relax
+% \end{macrocode}
+% Set the $y$ tick gap:
+% \begin{macrocode}
+\define@key{databar}{yticgap}{%
+\def\dtlbar@yticgap{#1}\DTLbaryticstrue\DTLbaryaxistrue}
+\let\dtlbar@yticgap=\relax
+% \end{macrocode}
+% Define list of labels for $y$ tics.
+% \begin{macrocode}
+\define@key{databar}{yticlabels}{%
+\def\dtlbar@yticlabels{#1}\DTLbaryticstrue\DTLbaryaxistrue}
+\let\dtlbar@yticlabels=\relax
+% \end{macrocode}
+% Define $y$ axis label.
+% \begin{macrocode}
+\define@key{databar}{ylabel}{%
+\def\dtlbar@ylabel{#1}}
+\let\dtlbar@ylabel=\relax
+% \end{macrocode}
+%
+%\begin{macro}{\DTLbarchart}
+%\begin{definition}
+% \cs{DTLbarchart}\oarg{conditions}\marg{option list}\marg{db name}\marg{assign list}
+%\end{definition}
+% Make a bar chart from data given in data base \meta{db name},
+% where \meta{assign list} is a comma-separated list of
+% \meta{cmd}\texttt{=}\meta{key} pairs. \meta{option list} must
+% include \texttt{variable}\texttt{=}\meta{cmd}, where \meta{cmd}
+% is included in \meta{assign list}. The optional argument
+% \meta{conditions} is the same as that for \cs{DTLforeach}.
+% \begin{macrocode}
+\newcommand*{\DTLbarchart}[4][\boolean{true}]{%
+{%
+ \undef\DTLbarvariable
+ \undef\DTLbarmax
+ \undef\DTLnegextent
+ \disable@keys{databar}{variables,multibarlabels,%
+ uppermultibarlabels,groupgap}%
+ \setkeys{databar}{#2}%
+ \ifundef{\DTLbarvariable}%
+ {%
+ \PackageError{databar}%
+ {\string\DTLbarchart\space missing variable}%
+ {You haven't use the "variable" key}%
+ }%
+ {%
+% \end{macrocode}
+% Compute the maximum bar height, unless \cs{DTLbarmax} has been
+% set.
+%\changes{1.01}{2007 Aug 17}{uses \cs{@sDTLforeach} instead of
+%\cs{DTLforeach}}
+% \begin{macrocode}
+ \ifundef{\DTLbarmax}%
+ {%
+ \@sDTLforeach[#1]{#3}{#4}{%
+ \expandafter\DTLconverttodecimal\expandafter
+ {\DTLbarvariable}{\dtl@barvar}%
+ \ifundef{\DTLbarmax}%
+ {%
+ \let\DTLbarmax=\dtl@barvar
+ }%
+ {%
+ \let\dtl@old=\DTLbarmax
+ \dtlmax{\DTLbarmax}{\dtl@old}{\dtl@barvar}%
+ }%
+ }%
+ \ifx\dtlbar@yticgap\relax
+ \else
+ \let\dtl@thistick=\dtlbar@yticgap
+ \whiledo{\DTLisFPopenbetween{\dtl@thistick}{0}{\DTLbarmax}}%
+ {%
+ \dtladd{\dtl@thistick}{\dtl@thistick}{\dtlbar@yticgap}%
+ }%
+ \let\DTLbarmax=\dtl@thistick
+ \fi
+ }%
+ {}%
+% \end{macrocode}
+% Compute the bar depth, unless \cs{DTLnegextent} has been
+% set.
+% \begin{macrocode}
+ \ifundef{\DTLnegextent}%
+ {%
+ \def\DTLnegextent{0}%
+ \@sDTLforeach[#1]{#3}{#4}{%
+ \expandafter\DTLconverttodecimal\expandafter
+ {\DTLbarvariable}{\dtl@barvar}%
+ \let\dtl@old=\DTLnegextent
+ \DTLmin{\DTLnegextent}{\dtl@old}{\dtl@barvar}%
+ }%
+ \ifx\dtlbar@yticgap\relax
+ \else
+ \ifthenelse{\DTLisFPlt{\DTLnegextent}{0}}%
+ {%
+ \edef\dtl@thistick{0}%
+ \whiledo{\DTLisFPclosedbetween{\dtl@thistick}{\DTLnegextent}{0}}{%
+ \dtlsub{\dtl@thistick}{\dtl@thistick}{\dtlbar@yticgap}%
+ }%
+ \let\DTLnegextent=\dtl@thistick
+ }{}%
+ \fi
+ }%
+ {}%
+% \end{macrocode}
+% Determine scaling factor
+% \begin{macrocode}
+ \@dtl@tmpcount=\DTLbarchartlength
+ \dtlsub{\dtl@extent}{\DTLbarmax}{\DTLnegextent}%
+ \dtldiv{\dtl@unit}{\number\@dtl@tmpcount}{\dtl@extent}%
+% \end{macrocode}
+% Construct $y$ tick list if required
+% \begin{macrocode}
+ \setlength{\dtl@yticlabelwidth}{0pt}%
+ \ifDTLbarytics
+ \ifx\dtlbar@yticlist\relax
+ \ifx\dtlbar@yticgap\relax
+ \@dtl@tmpcount=\DTLmintickgap
+ \divide\@dtl@tmpcount by 65536\relax
+ \dtldiv{\dtl@mingap}{\number\@dtl@tmpcount}{\dtl@unit}%
+ \dtl@constructticklist\DTLnegextent\DTLbarmax
+ \dtl@mingap\dtlbar@yticlist
+ \else
+ \dtl@constructticklistwithgapz
+ \DTLnegextent\DTLbarmax\dtlbar@yticlist\dtlbar@yticgap
+ \fi
+ \fi
+ \ifx\dtlbar@ylabel\relax
+ \else
+ \ifx\dtlbar@yticlabels\relax
+ \@for\dtl@thislabel:=\dtlbar@yticlist\do{%
+ \dtlround{\dtl@thislabel}{\dtl@thislabel}
+ {\c@DTLbarroundvar}%
+ \ifDTLverticalbars
+ \settowidth{\dtl@tmplength}{%
+ \DTLbardisplayYticklabel{\dtl@thislabel}}%
+ \else
+ \settoheight{\dtl@tmplength}{%
+ \DTLbardisplayYticklabel{\dtl@thislabel}}%
+ \edef\@dtl@h{\the\dtl@tmplength}%
+ \settodepth{\dtl@tmplength}{%
+ \DTLbardisplayYticklabel{\dtl@thislabel}}%
+ \addtolength{\dtl@tmplength}{\@dtl@h}%
+ \addtolength{\dtl@tmplength}{\baselineskip}%
+ \fi
+ \ifdim\dtl@tmplength>\dtl@yticlabelwidth
+ \setlength{\dtl@yticlabelwidth}{\dtl@tmplength}%
+ \fi
+ }%
+ \else
+ \@for\dtl@thislabel:=\dtlbar@yticlabels\do{%
+ \ifDTLverticalbars
+ \settowidth{\dtl@tmplength}{%
+ \DTLbardisplayYticklabel{\dtl@thislabel}}%
+ \else
+ \settoheight{\dtl@tmplength}{%
+ \DTLbardisplayYticklabel{\dtl@thislabel}}%
+ \edef\@dtl@h{\the\dtl@tmplength}%
+ \settodepth{\dtl@tmplength}{%
+ \DTLbardisplayYticklabel{\dtl@thislabel}}%
+ \addtolength{\dtl@tmplength}{\@dtl@h}%
+ \addtolength{\dtl@tmplength}{\baselineskip}%
+ \fi
+ \ifdim\dtl@tmplength>\dtl@yticlabelwidth
+ \setlength{\dtl@yticlabelwidth}{\dtl@tmplength}%
+ \fi
+ }%
+ \fi
+ \fi
+ \fi
+% \end{macrocode}
+% Store the width of the bar chart in \cs{DTLbarchartwidth}
+% \begin{macrocode}
+ \edef\DTLbarchartwidth{\expandafter\number\csname dtlrows@#3\endcsname}
+% \end{macrocode}
+% Do the bar chart
+% \begin{macrocode}
+ \begin{tikzpicture}
+% \end{macrocode}
+% Set unit vectors
+% \begin{macrocode}
+ \ifDTLverticalbars
+ \pgfsetyvec{\pgfpoint{0pt}{\dtl@unit sp}}%
+ \pgfsetxvec{\pgfpoint{\DTLbarwidth}{0pt}}%
+ \else
+ \pgfsetxvec{\pgfpoint{\dtl@unit sp}{0pt}}%
+ \pgfsetyvec{\pgfpoint{0pt}{\DTLbarwidth}}%
+ \fi
+% \end{macrocode}
+% Begin hook
+% \begin{macrocode}
+ \DTLbaratbegintikz
+% \end{macrocode}
+% Initialise
+% \begin{macrocode}
+ \def\@dtl@start{0}%
+% \end{macrocode}
+% Iterate through data
+% \begin{macrocode}
+ \@sDTLforeach[#1]{#3}{#4}{%
+% \end{macrocode}
+% Store the bar number in \cs{@dtl@bar}
+% \begin{macrocode}
+ \expandafter\let\expandafter\@dtl@bar
+ \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname%
+% \end{macrocode}
+% Convert variable to decimal
+% \begin{macrocode}
+ \expandafter\DTLconverttodecimal\expandafter
+ {\DTLbarvariable}{\dtl@variable}%
+% \end{macrocode}
+% Draw bars
+% \begin{macrocode}
+ \begin{scope}
+ \DTLdocurrentbarcolor
+ \ifDTLverticalbars
+ \fill (\@dtl@start,0) -- (\@dtl@start,\dtl@variable)
+ -- (\@dtl@bar,\dtl@variable) -- (\@dtl@bar,0) -- cycle;
+ \else
+ \fill (0,\@dtl@start) -- (\dtl@variable,\@dtl@start)
+ -- (\dtl@variable,\@dtl@bar) -- (0,\@dtl@bar) -- cycle;
+ \fi
+ \end{scope}
+% \end{macrocode}
+% Draw outline
+% \begin{macrocode}
+ \begin{scope}
+ \ifdim\DTLbaroutlinewidth>0pt
+ \expandafter\color\expandafter{\DTLbaroutlinecolor}
+ \ifDTLverticalbars
+ \draw (\@dtl@start,0) -- (\@dtl@start,\dtl@variable)
+ -- (\@dtl@bar,\dtl@variable) -- (\@dtl@bar,0) -- cycle;
+ \else
+ \draw (0,\@dtl@start) -- (\dtl@variable,\@dtl@start)
+ -- (\dtl@variable,\@dtl@bar) -- (0,\@dtl@bar) -- cycle;
+ \fi
+ \fi
+ \end{scope}
+% \end{macrocode}
+% Draw lower $x$ labels
+% \begin{macrocode}
+ \ifDTLverticalbars
+ \edef\dtl@textopt{%
+ at={\noexpand\pgfpointadd
+ {\noexpand\pgfpointxy{\@dtl@start.5}{0}}
+ {\noexpand\pgfpoint{0pt}{-\noexpand\DTLbarlabeloffset}}},
+ \DTLbarXlabelalign
+ }%
+% \end{macrocode}
+% Set \cs{DTLstartpt} to the starting point.
+% \begin{macrocode}
+ \edef\DTLstartpt{\noexpand\pgfpointxy{\@dtl@start.5}{0}}%
+ \else
+ \edef\dtl@textopt{%
+ at={\noexpand\pgfpointadd
+ {\noexpand\pgfpointxy{0}{\@dtl@start.5}}
+ {\noexpand\pgfpoint{-\noexpand\DTLbarlabeloffset}{0pt}}},
+ \DTLbarXlabelalign
+ }%
+% \end{macrocode}
+% Set \cs{DTLstartpt} to the starting point.
+% \begin{macrocode}
+ \edef\DTLstartpt{\noexpand\pgfpointxy{0}{\@dtl@start.5}}%
+ \fi
+ \expandafter\pgftext\expandafter[\dtl@textopt]{%
+ \DTLdisplaylowerbarlabel{\dtl@barlabel}}
+% \end{macrocode}
+% Draw upper $x$ labels
+% \begin{macrocode}
+ \ifDTLverticalbars
+% \end{macrocode}
+% Vertical bars
+% \begin{macrocode}
+ \expandafter\DTLifnumlt\expandafter{\DTLbarvariable}{0}%
+ {
+ \edef\dtl@textopt{%
+ at={\noexpand\pgfpointadd
+ {\noexpand\pgfpointxy{\@dtl@start.5}{\dtl@variable}}
+ {\noexpand\pgfpoint{0pt}{-\noexpand\DTLbarlabeloffset}}}
+ }%
+ }{%
+ \edef\dtl@textopt{%
+ at={\noexpand\pgfpointadd
+ {\noexpand\pgfpointxy{\@dtl@start.5}{\dtl@variable}}
+ {\noexpand\pgfpoint{0pt}{\noexpand\DTLbarlabeloffset}}}
+ }%
+ }
+% \end{macrocode}
+% Set \cs{DTLendpt} to the end point.
+% \begin{macrocode}
+ \edef\DTLendpt{\noexpand\pgfpointxy{\@dtl@start.5}{\dtl@variable}}%
+ \else
+% \end{macrocode}
+% Horizontal bars
+% \begin{macrocode}
+ \expandafter\DTLifnumlt\expandafter{\DTLbarvariable}{0}%
+ {
+ \edef\dtl@textopt{right,
+ at={\noexpand\pgfpointadd
+ {\noexpand\pgfpointxy{\dtl@variable}{\@dtl@start.5}}
+ {\noexpand\pgfpoint{-\noexpand\DTLbarlabeloffset}{0pt}}}
+ }%
+ }{%
+ \edef\dtl@textopt{left,
+ at={\noexpand\pgfpointadd
+ {\noexpand\pgfpointxy{\dtl@variable}{\@dtl@start.5}}
+ {\noexpand\pgfpoint{\noexpand\DTLbarlabeloffset}{0pt}}}
+ }%
+ }
+% \end{macrocode}
+% Set \cs{DTLendpt} to the end point.
+% \begin{macrocode}
+ \edef\DTLendpt{\noexpand\pgfpointxy{\dtl@variable}{\@dtl@start.5}}%
+ \fi
+ \expandafter\pgftext\expandafter[\dtl@textopt]{%
+ \DTLdisplayupperbarlabel{\dtl@upperbarlabel}}
+% \end{macrocode}
+% Set the mid point
+% \begin{macrocode}
+ \def\DTLmidpt{\pgfpointlineattime{0.5}{\DTLstartpt}{\DTLendpt}}%
+% \end{macrocode}
+% Do every bar hook
+%\changes{2.0}{2009 February 27}{added \cs{DTLeverybarhook}}%
+% \begin{macrocode}
+ \DTLeverybarhook
+% \end{macrocode}
+% End of loop
+% \begin{macrocode}
+ \edef\@dtl@start{\number\@dtl@bar}%
+ }%
+% \end{macrocode}
+% Draw $x$ axis
+% \begin{macrocode}
+ \ifDTLbarxaxis
+ \ifDTLverticalbars
+ \expandafter\draw\expandafter[\DTLBarXAxisStyle]
+ (0,0) -- (\DTLbarchartwidth,0);
+ \else
+ \expandafter\draw\expandafter[\DTLBarXAxisStyle]
+ (0,0) -- (0,\DTLbarchartwidth);
+ \fi
+ \fi
+% \end{macrocode}
+% Draw $y$ axis
+% \begin{macrocode}
+ \ifDTLbaryaxis
+ \ifDTLverticalbars
+ \expandafter\draw\expandafter[\DTLBarYAxisStyle]
+ (0,\DTLnegextent) -- (0,\DTLbarmax);
+ \else
+ \expandafter\draw\expandafter[\DTLBarYAxisStyle]
+ (\DTLnegextent,0) -- (\DTLbarmax,0);
+ \fi
+ \fi
+% \end{macrocode}
+% Plot $y$ tick marks if required
+% \begin{macrocode}
+ \ifx\dtlbar@yticlist\relax
+ \else
+ \@for\dtl@thistick:=\dtlbar@yticlist\do{%
+ \ifDTLverticalbars
+ \pgfpathmoveto{\pgfpointxy{0}{\dtl@thistick}}
+ \pgfpathlineto{
+ \pgfpointadd{\pgfpointxy{0}{\dtl@thistick}}
+ {\pgfpoint{-\DTLticklength}{0pt}}}
+ \else
+ \pgfpathmoveto{\pgfpointxy{\dtl@thistick}{0}}
+ \pgfpathlineto{
+ \pgfpointadd{\pgfpointxy{\dtl@thistick}{0}}
+ {\pgfpoint{0pt}{-\DTLticklength}}}
+ \fi
+ \pgfusepath{stroke}
+ \ifx\dtlbar@yticlabels\relax
+ \dtlround{\dtl@thislabel}{\dtl@thistick}
+ {\c@DTLbarroundvar}%
+ \else
+ \dtl@chopfirst\dtlbar@yticlabels\dtl@thislabel\dtl@rest
+ \let\dtlbar@yticlabels=\dtl@rest
+ \fi
+ \ifDTLverticalbars
+ \edef\dtl@textopt{\DTLbarYticklabelalign,%
+ at={\noexpand\pgfpointadd
+ {\noexpand\pgfpointxy{0}{\dtl@thistick}}
+ {\noexpand\pgfpoint{-\noexpand\DTLticklabeloffset}{0pt}},
+ }}%
+ \else
+ \edef\dtl@textopt{\DTLbarYticklabelalign,
+ at={\noexpand\pgfpointadd
+ {\noexpand\pgfpointxy{\dtl@thistick}{0}}
+ {\noexpand\pgfpoint{0pt}{-\noexpand\DTLticklabeloffset}}
+ }}%
+ \fi
+ \expandafter\pgftext\expandafter[\dtl@textopt]{%
+ \DTLbardisplayYticklabel{\dtl@thislabel}}
+ }%
+ \fi
+% \end{macrocode}
+% Plot the $y$ label if required
+% \begin{macrocode}
+ \ifx\dtlbar@ylabel\relax
+ \else
+ \addtolength{\dtl@yticlabelwidth}{\baselineskip}%
+ \setlength{\dtl@tmplength}{0.5\DTLbarchartlength}
+ \ifDTLverticalbars
+ \pgftext[bottom,center,at={\pgfpointadd
+ {\pgfpointxy{0}{\DTLnegextent}}%
+ {\pgfpoint{-\dtl@yticlabelwidth}{\dtl@tmplength}}},
+ rotate=90]{%
+ \dtlbar@ylabel}
+ \else
+ \pgftext[bottom,center,at={\pgfpointadd
+ {\pgfpointxy{\DTLnegextent}{0}}%
+ {\pgfpoint{\dtl@tmplength}{-\dtl@yticlabelwidth}}}]{%
+ \dtlbar@ylabel}
+ \fi
+ \fi
+% \end{macrocode}
+% Finish bar chart
+% \begin{macrocode}
+ \DTLbaratendtikz
+ \end{tikzpicture}
+ }%
+}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLmultibarchart}
+%\begin{definition}
+% \cs{DTLmultibarchart}\oarg{conditions}\marg{option list}\marg{db name}\marg{assign list}
+%\end{definition}
+% Make a multi-bar chart from data given in data base \meta{db name},
+% where \meta{assign list} is a comma-separated list of
+% \meta{cmd}\texttt{=}\meta{key} pairs. \meta{option list} must
+% include the \texttt{variables} key which must be a comma separated
+% list of commands, where each command
+% is included in \meta{assign list}. The optional argument
+% \meta{conditions} is the same as that for \cs{DTLforeach}.
+% \begin{macrocode}
+\newcommand*{\DTLmultibarchart}[4][\boolean{true}]{%
+{\let\dtlbar@variables=\relax
+\let\DTLbarmax=\relax
+\let\DTLnegextent=\relax
+\disable@keys{databar}{variable,upperbarlabel}%
+\setkeys{databar}{#2}%
+\ifx\dtlbar@variables\relax
+ \PackageError{databar}{\string\DTLmultibarchart\space missing variables setting}{}%
+\else
+% \end{macrocode}
+% Compute the maximum bar height, unless \cs{DTLbarmax} has been
+% set.
+%\changes{1.01}{2007 Aug 17}{uses \cs{@sDTLforeach} instead of
+%\cs{DTLforeach}}
+% \begin{macrocode}
+ \ifx\DTLbarmax\relax
+ \@sDTLforeach[#1]{#3}{#4}{%
+ \@for\DTLbarvariable:=\dtlbar@variables\do{%
+ \expandafter\DTLconverttodecimal\expandafter
+ {\DTLbarvariable}{\dtl@barvar}%
+ \ifx\DTLbarmax\relax
+ \let\DTLbarmax=\dtl@barvar
+ \else
+ \let\dtl@old=\DTLbarmax
+ \dtlmax{\DTLbarmax}{\dtl@old}{\dtl@barvar}%
+ \fi
+ }%
+ }%
+ \ifx\dtlbar@yticgap\relax
+ \else
+ \let\dtl@thistick=\dtlbar@yticgap%
+ \whiledo{\DTLisFPopenbetween{\dtl@thistick}{0}{\DTLbarmax}}{%
+ \dtladd{\dtl@thistick}{\dtl@thistick}{\dtlbar@yticgap}%
+ }%
+ \let\DTLbarmax=\dtl@thistick
+ \fi
+ \fi
+% \end{macrocode}
+% Compute the bar depth, unless \cs{DTLnegextent} has been
+% set.
+% \begin{macrocode}
+ \ifx\DTLnegextent\relax
+ \def\DTLnegextent{0}%
+ \@sDTLforeach[#1]{#3}{#4}{%
+ \@for\DTLbarvariable:=\dtlbar@variables\do{%
+ \expandafter\DTLconverttodecimal\expandafter
+ {\DTLbarvariable}{\dtl@barvar}%
+ \let\dtl@old=\DTLnegextent
+ \DTLmin{\DTLnegextent}{\dtl@old}{\dtl@barvar}%
+ }%
+ }%
+ \ifx\dtlbar@yticgap\relax
+ \else
+ \ifthenelse{\DTLisFPlt{\DTLnegextent}{0}}{%
+ \edef\dtl@thistick{0}%
+ \whiledo{\DTLisFPclosedbetween{\dtl@thistick}{\DTLnegextent}{0}}{%
+ \dtlsub{\dtl@thistick}{\dtl@thistick}{\dtlbar@yticgap}%
+ }%
+ \let\DTLnegextent=\dtl@thistick
+ }{}%
+ \fi
+ \fi
+% \end{macrocode}
+% Determine scaling factor
+% \begin{macrocode}
+ \@dtl@tmpcount=\DTLbarchartlength
+ \dtlsub{\dtl@extent}{\DTLbarmax}{\DTLnegextent}%
+ \dtldiv{\dtl@unit}{\number\@dtl@tmpcount}{\dtl@extent}%
+% \end{macrocode}
+% Construct $y$ tick list if required
+% \begin{macrocode}
+ \setlength{\dtl@yticlabelwidth}{0pt}%
+ \ifDTLbarytics
+ \ifx\dtlbar@yticlist\relax
+ \ifx\dtlbar@yticgap\relax
+ \@dtl@tmpcount=\DTLmintickgap
+ \divide\@dtl@tmpcount by 65536\relax
+ \dtldiv{\dtl@mingap}{\number\@dtl@tmpcount}{\dtl@unit}%
+ \dtl@constructticklist\DTLnegextent\DTLbarmax
+ \dtl@mingap\dtlbar@yticlist
+ \else
+ \dtl@constructticklistwithgapz
+ \DTLnegextent\DTLbarmax\dtlbar@yticlist\dtlbar@yticgap
+ \fi
+ \fi
+ \ifx\dtlbar@ylabel\relax
+ \else
+ \ifx\dtlbar@yticlabels\relax
+ \@for\dtl@thislabel:=\dtlbar@yticlist\do{%
+ \dtlround{\dtl@thislabel}{\dtl@thislabel}
+ {\c@DTLbarroundvar}%
+ \ifDTLverticalbars
+ \settowidth{\dtl@tmplength}{%
+ \DTLbardisplayYticklabel{\dtl@thislabel}}%
+ \else
+ \settoheight{\dtl@tmplength}{%
+ \DTLbardisplayYticklabel{\dtl@thislabel}}%
+ \edef\@dtl@h{\the\dtl@tmplength}%
+ \settodepth{\dtl@tmplength}{%
+ \DTLbardisplayYticklabel{\dtl@thislabel}}%
+ \addtolength{\dtl@tmplength}{\@dtl@h}%
+ \addtolength{\dtl@tmplength}{\baselineskip}%
+ \fi
+ \ifdim\dtl@tmplength>\dtl@yticlabelwidth
+ \setlength{\dtl@yticlabelwidth}{\dtl@tmplength}%
+ \fi
+ }%
+ \else
+ \@for\dtl@thislabel:=\dtlbar@yticlabels\do{%
+ \ifDTLverticalbars
+ \settowidth{\dtl@tmplength}{%
+ \DTLbardisplayYticklabel{\dtl@thislabel}}%
+ \else
+ \settoheight{\dtl@tmplength}{%
+ \DTLbardisplayYticklabel{\dtl@thislabel}}%
+ \edef\@dtl@h{\the\dtl@tmplength}%
+ \settodepth{\dtl@tmplength}{%
+ \DTLbardisplayYticklabel{\dtl@thislabel}}%
+ \addtolength{\dtl@tmplength}{\@dtl@h}%
+ \addtolength{\dtl@tmplength}{\baselineskip}%
+ \fi
+ \ifdim\dtl@tmplength>\dtl@yticlabelwidth
+ \setlength{\dtl@yticlabelwidth}{\dtl@tmplength}%
+ \fi
+ }%
+ \fi
+ \fi
+ \fi
+% \end{macrocode}
+% Calculate the offset for the lower label and number of labels
+% \begin{macrocode}
+\dtl@xticlabelheight=0pt\relax
+\@dtl@tmpcount=0\relax
+\@for\dtl@thislabel:=\dtl@multibarlabels\do{%
+ \advance\@dtl@tmpcount by 1\relax
+ \settoheight{\dtl@tmplength}{\tikz\expandafter\pgftext\expandafter
+ [\DTLbarXlabelalign]{\DTLdisplaylowerbarlabel{\dtl@thislabel}};}%
+ \edef\@dtl@h{\the\dtl@tmplength}%
+ \settodepth{\dtl@tmplength}{\tikz\expandafter\pgftext\expandafter
+ [\DTLbarXlabelalign]{\DTLdisplaylowerbarlabel{\dtl@thislabel}};}%
+ \addtolength{\dtl@tmplength}{\@dtl@h}%
+ \addtolength{\dtl@tmplength}{\baselineskip}%
+ \ifdim\dtl@tmplength>\dtl@xticlabelheight
+ \setlength{\dtl@xticlabelheight}{\dtl@tmplength}%
+ \fi
+}
+% \end{macrocode}
+% Calculate number of bars per group
+% \begin{macrocode}
+\@dtl@tmpcount=0\relax
+\@for\dtl@this:=\dtlbar@variables\do{%
+ \advance\@dtl@tmpcount by 1\relax
+}%
+\edef\DTLbargroupwidth{\number\@dtl@tmpcount}%
+% \end{macrocode}
+% Compute the total width of the bar chart (in terms of
+% the $x$ unit vector.)
+% \begin{macrocode}
+\edef\dtl@n{\expandafter\number\csname dtlrows@#3\endcsname}
+\dtlmul{\dtl@tmpi}{\dtl@n}{\DTLbargroupwidth}
+\dtlsub{\dtl@tmpii}{\dtl@n}{1}%
+\dtlmul{\dtl@tmpii}{\dtl@tmpii}{\dtlbar@groupgap}%
+\dtladd{\DTLbarchartwidth}{\dtl@tmpi}{\dtl@tmpii}
+% \end{macrocode}
+% Do the bar chart
+% \begin{macrocode}
+\begin{tikzpicture}
+% \end{macrocode}
+% Set unit vectors
+% \begin{macrocode}
+\ifDTLverticalbars
+ \pgfsetyvec{\pgfpoint{0pt}{\dtl@unit sp}}%
+ \pgfsetxvec{\pgfpoint{\DTLbarwidth}{0pt}}%
+\else
+ \pgfsetxvec{\pgfpoint{\dtl@unit sp}{0pt}}%
+ \pgfsetyvec{\pgfpoint{0pt}{\DTLbarwidth}}%
+\fi
+% \end{macrocode}
+% Begin hook
+% \begin{macrocode}
+\DTLbaratbegintikz
+% \end{macrocode}
+% Initialise
+% \begin{macrocode}
+\def\@dtl@start{0}%
+% \end{macrocode}
+% Iterate through data
+% \begin{macrocode}
+\@sDTLforeach[#1]{#3}{#4}{%
+% \end{macrocode}
+% Store the bar number in \cs{@dtl@bar}
+% \begin{macrocode}
+\@dtl@barcount = 1\relax
+% \end{macrocode}
+% Set the multibar label lists
+% \begin{macrocode}
+\let\dtl@multibar@labels=\dtl@multibarlabels
+\let\dtl@uppermultibar@labels=\dtl@uppermultibarlabels
+% \end{macrocode}
+% Compute mid point over group
+% \begin{macrocode}
+\dtlmul{\dtl@multimidpt}{\DTLbargroupwidth}{0.5}%
+\dtladd{\dtl@multimidpt}{\dtl@multimidpt}{\@dtl@start}%
+% \end{macrocode}
+% Iterate through each variable
+% \begin{macrocode}
+\@for\DTLbarvariable:=\dtlbar@variables\do{%
+% \end{macrocode}
+% Set end point
+% \begin{macrocode}
+\dtladd{\@dtl@endpt}{\@dtl@start}{1}%
+% \end{macrocode}
+% Convert variable to decimal
+% \begin{macrocode}
+\expandafter\DTLconverttodecimal\expandafter
+ {\DTLbarvariable}{\dtl@variable}%
+% \end{macrocode}
+% Get the current lower label:
+% \begin{macrocode}
+\dtl@chopfirst\dtl@multibar@labels\dtl@thisbarlabel\dtl@rest
+\let\dtl@multibar@labels=\dtl@rest
+% \end{macrocode}
+% Get the current upper label:
+% \begin{macrocode}
+\dtl@chopfirst\dtl@uppermultibar@labels\dtl@thisupperbarlabel\dtl@rest
+\let\dtl@uppermultibar@labels=\dtl@rest
+% \end{macrocode}
+% Draw bars
+% \begin{macrocode}
+\begin{scope}
+ \expandafter\color\expandafter{\DTLgetbarcolor{\@dtl@barcount}}%
+ \ifDTLverticalbars
+ \fill (\@dtl@start,0) -- (\@dtl@start,\dtl@variable)
+ -- (\@dtl@endpt,\dtl@variable) -- (\@dtl@endpt,0) -- cycle;
+ \else
+ \fill (0,\@dtl@start) -- (\dtl@variable,\@dtl@start)
+ -- (\dtl@variable,\@dtl@endpt) -- (0,\@dtl@endpt) -- cycle;
+ \fi
+\end{scope}
+% \end{macrocode}
+% Draw outline
+% \begin{macrocode}
+\begin{scope}
+\ifdim\DTLbaroutlinewidth>0pt
+ \expandafter\color\expandafter{\DTLbaroutlinecolor}
+ \ifDTLverticalbars
+ \draw (\@dtl@start,0) -- (\@dtl@start,\dtl@variable)
+ -- (\@dtl@endpt,\dtl@variable) -- (\@dtl@endpt,0) -- cycle;
+ \else
+ \draw (0,\@dtl@start) -- (\dtl@variable,\@dtl@start)
+ -- (\dtl@variable,\@dtl@endpt) -- (0,\@dtl@endpt) -- cycle;
+ \fi
+\fi
+\end{scope}
+% \end{macrocode}
+% Calculate mid point
+% \begin{macrocode}
+\dtladd{\@dtl@midpt}{\@dtl@start}{0.5}%
+% \end{macrocode}
+% Draw lower $x$ labels
+% \begin{macrocode}
+\ifDTLverticalbars
+ \edef\dtl@textopt{%
+ at={\noexpand\pgfpointadd
+ {\noexpand\pgfpointxy{\@dtl@midpt}{0}}
+ {\noexpand\pgfpoint{0pt}{-\noexpand\DTLbarlabeloffset}}},
+ \DTLbarXlabelalign
+ }%
+ \edef\DTLstartpt{\noexpand\pgfpointxy{\@dtl@midpt}{0}}%
+\else
+ \edef\dtl@textopt{%
+ at={\noexpand\pgfpointadd
+ {\noexpand\pgfpointxy{0}{\@dtl@midpt}}
+ {\noexpand\pgfpoint{-\noexpand\DTLbarlabeloffset}{0pt}}},
+ \DTLbarXlabelalign
+ }%
+ \edef\DTLstartpt{\noexpand\pgfpointxy{0}{\@dtl@midpt}}%
+\fi
+ \expandafter\pgftext\expandafter[\dtl@textopt]{%
+ \DTLdisplaylowermultibarlabel{\dtl@thisbarlabel}}
+% \end{macrocode}
+% Draw upper $x$ labels
+% \begin{macrocode}
+\ifDTLverticalbars
+ \expandafter\DTLifnumlt\expandafter{\DTLbarvariable}{0}
+ {
+ \edef\dtl@textopt{%
+ at={\noexpand\pgfpointadd
+ {\noexpand\pgfpointxy{\@dtl@midpt}{\dtl@variable}}
+ {\noexpand\pgfpoint{0pt}{-\noexpand\DTLbarlabeloffset}}}
+ }%
+ }{%
+ \edef\dtl@textopt{%
+ at={\noexpand\pgfpointadd
+ {\noexpand\pgfpointxy{\@dtl@midpt}{\dtl@variable}}
+ {\noexpand\pgfpoint{0pt}{\noexpand\DTLbarlabeloffset}}}
+ }%
+ }
+ \edef\DTLendpt{\noexpand\pgfpointxy{\@dtl@midpt}{\dtl@variable}}%
+\else
+ \expandafter\DTLifnumlt\expandafter{\DTLbarvariable}{0}
+ {
+ \edef\dtl@textopt{right,
+ at={\noexpand\pgfpointadd
+ {\noexpand\pgfpointxy{\dtl@variable}{\@dtl@midpt}}
+ {\noexpand\pgfpoint{-\noexpand\DTLbarlabeloffset}{0pt}}}
+ }%
+ }{%
+ \edef\dtl@textopt{left,
+ at={\noexpand\pgfpointadd
+ {\noexpand\pgfpointxy{\dtl@variable}{\@dtl@midpt}}
+ {\noexpand\pgfpoint{\noexpand\DTLbarlabeloffset}{0pt}}}
+ }%
+ }
+ \edef\DTLendpt{\noexpand\pgfpointxy{\dtl@variable}{\@dtl@midpt}}%
+\fi
+ \expandafter\pgftext\expandafter[\dtl@textopt]{%
+ \DTLdisplayuppermultibarlabel{\dtl@thisupperbarlabel}}
+% \end{macrocode}
+% Set the mid point
+% \begin{macrocode}
+\def\DTLmidpt{\pgfpointlineattime{0.5}{\DTLstartpt}{\DTLendpt}}%
+% \end{macrocode}
+% Do every bar hook
+%\changes{2.0}{2009 February 27}{added \cs{DTLeverybarhook}}%
+% \begin{macrocode}
+\DTLeverybarhook
+% \end{macrocode}
+% End of loop increment loop variables
+% \begin{macrocode}
+ \dtladd{\@dtl@start}{\@dtl@start}{1}%
+ \advance\@dtl@barcount by 1\relax
+}%
+% Draw lower group $x$ labels
+% \begin{macrocode}
+\setlength{\dtl@tmplength}{\DTLbarlabeloffset}%
+\addtolength{\dtl@tmplength}{\dtl@xticlabelheight}%
+\ifDTLverticalbars
+ \edef\dtl@textopt{%
+ at={\noexpand\pgfpointadd
+ {\noexpand\pgfpointxy{\dtl@multimidpt}{0}}
+ {\noexpand\pgfpoint{0pt}{-\noexpand\dtl@tmplength}}},
+ \DTLbarXlabelalign
+ }%
+\else
+ \edef\dtl@textopt{%
+ at={\noexpand\pgfpointadd
+ {\noexpand\pgfpointxy{0}{\dtl@multimidpt}}
+ {\noexpand\pgfpoint{-\noexpand\dtl@tmplength}{0pt}}},
+ \DTLbarXlabelalign
+ }%
+\fi
+ \expandafter\pgftext\expandafter[\dtl@textopt]{%
+ \DTLdisplaylowerbarlabel{\dtl@barlabel}}
+% \end{macrocode}
+% Increment starting position by \cs{dtlbar@groupgap}
+% \begin{macrocode}
+ \dtladd{\@dtl@start}{\@dtl@start}{\dtlbar@groupgap}%
+}
+% \end{macrocode}
+% Draw $x$ axis
+% \begin{macrocode}
+\ifDTLbarxaxis
+ \ifDTLverticalbars
+ \expandafter\draw\expandafter[\DTLBarXAxisStyle]
+ (0,0) -- (\DTLbarchartwidth,0);
+ \else
+ \expandafter\draw\expandafter[\DTLBarXAxisStyle]
+ (0,0) -- (0,\DTLbarchartwidth);
+ \fi
+\fi
+% \end{macrocode}
+% Draw $y$ axis
+% \begin{macrocode}
+\ifDTLbaryaxis
+ \ifDTLverticalbars
+ \expandafter\draw\expandafter[\DTLBarYAxisStyle]
+ (0,\DTLnegextent) -- (0,\DTLbarmax);
+ \else
+ \expandafter\draw\expandafter[\DTLBarYAxisStyle]
+ (\DTLnegextent,0) -- (\DTLbarmax,0);
+ \fi
+\fi
+% \end{macrocode}
+% Plot $y$ tick marks if required
+% \begin{macrocode}
+\ifx\dtlbar@yticlist\relax
+\else
+ \@for\dtl@thistick:=\dtlbar@yticlist\do{%
+ \ifDTLverticalbars
+ \pgfpathmoveto{\pgfpointxy{0}{\dtl@thistick}}
+ \pgfpathlineto{
+ \pgfpointadd{\pgfpointxy{0}{\dtl@thistick}}
+ {\pgfpoint{-\DTLticklength}{0pt}}}
+ \else
+ \pgfpathmoveto{\pgfpointxy{\dtl@thistick}{0}}
+ \pgfpathlineto{
+ \pgfpointadd{\pgfpointxy{\dtl@thistick}{0}}
+ {\pgfpoint{0pt}{-\DTLticklength}}}
+ \fi
+ \pgfusepath{stroke}
+ \ifx\dtlbar@yticlabels\relax
+ \dtlround{\dtl@thislabel}{\dtl@thistick}
+ {\c@DTLbarroundvar}%
+ \else
+ \dtl@chopfirst\dtlbar@yticlabels\dtl@thislabel\dtl@rest
+ \let\dtlbar@yticlabels=\dtl@rest
+ \fi
+ \ifDTLverticalbars
+ \edef\dtl@textopt{\DTLbarYticklabelalign,%
+ at={\noexpand\pgfpointadd
+ {\noexpand\pgfpointxy{0}{\dtl@thistick}}
+ {\noexpand\pgfpoint{-\noexpand\DTLticklabeloffset}{0pt}},
+ }}%
+ \else
+ \edef\dtl@textopt{\DTLbarYticklabelalign,
+ at={\noexpand\pgfpointadd
+ {\noexpand\pgfpointxy{\dtl@thistick}{0}}
+ {\noexpand\pgfpoint{0pt}{-\noexpand\DTLticklabeloffset}}
+ }}%
+ \fi
+ \expandafter\pgftext\expandafter[\dtl@textopt]{%
+ \DTLbardisplayYticklabel{\dtl@thislabel}}
+ }%
+\fi
+% \end{macrocode}
+% Plot the $y$ label if required
+% \begin{macrocode}
+\ifx\dtlbar@ylabel\relax
+\else
+ \addtolength{\dtl@yticlabelwidth}{\baselineskip}%
+ \setlength{\dtl@tmplength}{0.5\DTLbarchartlength}
+ \ifDTLverticalbars
+ \pgftext[bottom,center,at={\pgfpointadd
+ {\pgfpointxy{0}{\DTLnegextent}}%
+ {\pgfpoint{-\dtl@yticlabelwidth}{\dtl@tmplength}}},
+ rotate=90]{%
+ \dtlbar@ylabel}
+ \else
+ \pgftext[bottom,center,at={\pgfpointadd
+ {\pgfpointxy{\DTLnegextent}{0}}%
+ {\pgfpoint{\dtl@tmplength}{-\dtl@yticlabelwidth}}}]{%
+ \dtlbar@ylabel}
+ \fi
+\fi
+% \end{macrocode}
+% Finish bar chart
+% \begin{macrocode}
+\DTLbaratendtikz
+\end{tikzpicture}
+\fi
+}}
+% \end{macrocode}
+%\end{macro}
+%\iffalse
+% \begin{macrocode}
+%</databar.sty>
+% \end{macrocode}
+%\fi
+%\iffalse
+% \begin{macrocode}
+%<*datapie.sty>
+% \end{macrocode}
+%\fi
+%\chapter{datapie.sty}
+% Declare package:
+% \begin{macrocode}
+\NeedsTeXFormat{LaTeX2e}
+\ProvidesPackage{datapie}[2018/12/07 v2.31 (NLCT)]
+% \end{macrocode}
+% Require \sty{xkeyval} package
+% \begin{macrocode}
+\RequirePackage{xkeyval}
+% \end{macrocode}
+%\begin{macro}{\ifDTLcolorpiechart}
+% The conditional \cs{ifDTLcolorpiechart} is to determine
+% whether to use colour or grey scale.
+% \begin{macrocode}
+\newif\ifDTLcolorpiechart
+\DTLcolorpiecharttrue
+% \end{macrocode}
+%\end{macro}
+% Package options to change the conditional:
+% \begin{macrocode}
+\DeclareOption{color}{\DTLcolorpiecharttrue}
+\DeclareOption{gray}{\DTLcolorpiechartfalse}
+% \end{macrocode}
+%\begin{macro}{\ifDTLrotateinner}
+% Define boolean keys to govern label rotations.
+% \begin{macrocode}
+\define@boolkey{datapie}[DTL]{rotateinner}[true]{}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\ifDTLrotateouter}
+% \begin{macrocode}
+\define@boolkey{datapie}[DTL]{rotateouter}[true]{}
+% \end{macrocode}
+%\end{macro}
+% Set defaults:
+% \begin{macrocode}
+\DTLrotateinnerfalse
+\DTLrotateouterfalse
+% \end{macrocode}
+% Package options to change \cs{DTLrotateinner}
+% \begin{macrocode}
+\DeclareOption{rotateinner}{\DTLrotateinnertrue}
+\DeclareOption{norotateinner}{\DTLrotateinnerfalse}
+% \end{macrocode}
+% Package options to change \cs{DTLrotateouter}
+% \begin{macrocode}
+\DeclareOption{rotateouter}{\DTLrotateoutertrue}
+\DeclareOption{norotateouter}{\DTLrotateouterfalse}
+% \end{macrocode}
+% Process options:
+% \begin{macrocode}
+\ProcessOptions
+% \end{macrocode}
+% Required packages:
+% \begin{macrocode}
+\RequirePackage{datatool}
+\RequirePackage{tikz}
+% \end{macrocode}
+% Define some variables that govern the appearance of the pie
+% chart.
+%
+%\begin{macro}{\DTLradius}
+% The radius of the pie chart is given by \cs{DTLradius}.
+% \begin{macrocode}
+\newlength\DTLradius
+\DTLradius=2cm
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLinnerratio}
+% The inner label offset ratio is given by \cs{DTLinnerratio}
+% \begin{macrocode}
+\newcommand*{\DTLinnerratio}{0.5}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLouterratio}
+% The outer label offset ratio is given by \cs{DTLouterratio}.
+% \begin{macrocode}
+\newcommand*{\DTLouterratio}{1.25}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLcutawayratio}
+% The cutaway offset ratio is given by \cs{DTLcutawayratio}.
+% \begin{macrocode}
+\newcommand*\DTLcutawayratio{0.2}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLstartangle}
+% The angle of the first segment is given by \cs{DTLstartangle}.
+% \begin{macrocode}
+\newcommand*{\DTLstartangle}{0}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtl@inneroffset}
+% \begin{macrocode}
+\newlength\dtl@inneroffset
+\dtl@inneroffset=\DTLinnerratio\DTLradius
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtl@outeroffset}
+% \begin{macrocode}
+\newlength\dtl@outeroffset
+\dtl@outeroffset=\DTLouterratio\DTLradius
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtl@cutawayoffset}
+% \begin{macrocode}
+\newlength\dtl@cutawayoffset
+\dtl@cutawayoffset=\DTLcutawayratio\DTLradius
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@piecutaways}
+% \cs{dtl@piecutaways} is a comma separated list of segments that
+% need to be cut away from the pie chart.
+% \begin{macrocode}
+\newcommand*{\dtl@piecutaways}{}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtl@innerlabel}
+% \cs{dtl@innerlabel} specifies the label to appear inside
+% the segment. By default this is the variable used to create
+% the pie chart.
+% \begin{macrocode}
+\def\dtl@innerlabel{\DTLpievariable}%
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtl@outerlabel}
+% \begin{macrocode}
+\def\dtl@outerlabel{}%
+% \end{macrocode}
+%\end{macro}
+%\begin{counter}{DTLpieroundvar}
+% \ctrfmt{DTLpieroundvar} is a counter governing the number of digits
+% to round to when using \cs{FPround}.
+% \begin{macrocode}
+\newcounter{DTLpieroundvar}
+\setcounter{DTLpieroundvar}{1}
+% \end{macrocode}
+%\end{counter}
+%
+%\begin{macro}{\DTLdisplayinnerlabel}
+%\begin{definition}
+%\cs{DTLdisplayinnerlabel}\marg{label}
+%\end{definition}
+% This is used to format the inner label. This just does the
+% label by default.
+% \begin{macrocode}
+\newcommand*{\DTLdisplayinnerlabel}[1]{#1}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLdisplayouterlabel}
+%\begin{definition}
+%\cs{DTLdisplayouterlabel}\marg{label}
+%\end{definition}
+% This is used to format the outer label. This just does the
+% label by default.
+% \begin{macrocode}
+\newcommand*{\DTLdisplayouterlabel}[1]{#1}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLpiepercent}
+%\cs{DTLpiepercent}
+% returns the percentage value of the current segment.
+% \begin{macrocode}
+\newcommand*{\DTLpiepercent}{%
+\ifnum\dtlforeachlevel=0\relax
+ \PackageError{datapie}{Can't use
+ \string\DTLpiepercent\space outside
+ \string\DTLpiechart}{}%
+\else
+ \csname dtl@piepercent@\romannumeral\@dtl@seg\endcsname
+\fi}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLpieatbegintikz}
+% \cs{DTLpieatbegintikz} specifies any commands
+% to apply at the start of the \env{tikzpicture} environment.
+% By default it does nothing.
+% \begin{macrocode}
+\newcommand*{\DTLpieatbegintikz}{}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLpieatendtikz}
+% \cs{DTLpieatendtikz} specifies any commands
+% to apply at the end of the \env{tikzpicture} environment.
+% By default it does nothing.
+% \begin{macrocode}
+\newcommand*{\DTLpieatendtikz}{}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLsetpiesegmentcolor}
+%\begin{definition}
+% \cs{DTLsetpiesegmentcolor}\marg{n}\marg{color}
+%\end{definition}
+% Assign colour name \meta{color} to the \meta{n}th segment.
+% \begin{macrocode}
+\newcommand*{\DTLsetpiesegmentcolor}[2]{%
+\expandafter\def\csname dtlpie@segcol\romannumeral#1\endcsname{#2}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLgetpiesegmentcolor}
+%\begin{definition}
+%\cs{DTLgetpiesegmentcolor}\marg{n}
+%\end{definition}
+% Get the colour specification for segment \meta{n}
+% \begin{macrocode}
+\newcommand*{\DTLgetpiesegmentcolor}[1]{%
+\csname dtlpie@segcol\romannumeral#1\endcsname}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLdopiesegmentcolor}
+%\begin{definition}
+%\cs{DTLdopiesegmentcolor}\marg{n}
+%\end{definition}
+% Set the colour to that for segment \meta{n}
+% \begin{macrocode}
+\newcommand*{\DTLdopiesegmentcolor}[1]{%
+\expandafter\color\expandafter
+{\csname dtlpie@segcol\romannumeral#1\endcsname}}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLdocurrentpiesegmentcolor}
+%\cs{DTLdocurrentpiesegmentcolor}
+% sets the colour to that of the current segment.
+% \begin{macrocode}
+\newcommand*{\DTLdocurrentpiesegmentcolor}{%
+\ifnum\dtlforeachlevel=0\relax
+ \PackageError{datapie}{Can't use
+ \string\DTLdocurrentpiesegmentcolor\space outside
+ \string\DTLpiechart}{}%
+\else
+ \expandafter\DTLdopiesegmentcolor\expandafter{%
+ \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname}%
+\fi}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLpieoutlinecolor}
+%\cs{DTLpieoutlinecolor} specifies what colour to draw the
+% outline.
+% \begin{macrocode}
+\newcommand*{\DTLpieoutlinecolor}{black}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLpieoutlinewidth}
+%\cs{DTLpieoutlinewidth} specifies the line width of the outline:
+% Outline is only drawn if the linewidth is greater than 0pt.
+% \begin{macrocode}
+\newlength\DTLpieoutlinewidth
+\DTLpieoutlinewidth=0pt
+% \end{macrocode}
+%\end{macro}
+%
+% Set the default colours. If there are more than eight segments,
+% more colours will need to be defined.
+% \begin{macrocode}
+\ifDTLcolorpiechart
+ \DTLsetpiesegmentcolor{1}{red}
+ \DTLsetpiesegmentcolor{2}{green}
+ \DTLsetpiesegmentcolor{3}{blue}
+ \DTLsetpiesegmentcolor{4}{yellow}
+ \DTLsetpiesegmentcolor{5}{magenta}
+ \DTLsetpiesegmentcolor{6}{cyan}
+ \DTLsetpiesegmentcolor{7}{orange}
+ \DTLsetpiesegmentcolor{8}{white}
+\else
+ \DTLsetpiesegmentcolor{1}{black!15}
+ \DTLsetpiesegmentcolor{2}{black!25}
+ \DTLsetpiesegmentcolor{3}{black!35}
+ \DTLsetpiesegmentcolor{4}{black!45}
+ \DTLsetpiesegmentcolor{5}{black!55}
+ \DTLsetpiesegmentcolor{6}{black!65}
+ \DTLsetpiesegmentcolor{7}{black!75}
+ \DTLsetpiesegmentcolor{8}{black!85}
+\fi
+% \end{macrocode}
+% Define keys for \cs{DTLpiechart} optional argument.
+% Set the starting angle of the first segment.
+% \begin{macrocode}
+\define@key{datapie}{start}{\def\DTLstartangle{#1}}
+% \end{macrocode}
+% Set the radius of the pie chart (must be set prior to
+% inneroffset and outeroffset keys.)
+% \begin{macrocode}
+\define@key{datapie}{radius}{\DTLradius=#1\relax
+\dtl@inneroffset=\DTLinnerratio\DTLradius
+\dtl@outeroffset=\DTLouterratio\DTLradius
+\dtl@cutawayoffset=\DTLcutawayratio\DTLradius}
+% \end{macrocode}
+% Set the inner ratio.
+% \begin{macrocode}
+\define@key{datapie}{innerratio}{%
+\def\DTLinnerratio{#1}%
+\dtl@inneroffset=\DTLinnerratio\DTLradius}
+% \end{macrocode}
+% Set the outer ratio
+% \begin{macrocode}
+\define@key{datapie}{outerratio}{%
+\def\DTLouterratio{#1}%
+\dtl@outeroffset=\DTLouterratio\DTLradius}
+% \end{macrocode}
+% The cutaway offset ratio
+% \begin{macrocode}
+\define@key{datapie}{cutawayratio}{%
+\def\DTLcutawayratio{#1}%
+\dtl@cutawayoffset=\DTLcutawayratio\DTLradius}
+% \end{macrocode}
+% Set the inner offset as an absolute value (not dependent
+% on the radius.)
+% \begin{macrocode}
+\define@key{datapie}{inneroffset}{%
+\dtl@inneroffset=#1}
+% \end{macrocode}
+% Set the outer offset as an absolute value (not dependent
+% on the radius.)
+% \begin{macrocode}
+\define@key{datapie}{outeroffset}{%
+\dtl@outeroffset=#1}
+% \end{macrocode}
+% Set the cutaway offset as an absolute value (not dependent
+% on the radius.)
+% \begin{macrocode}
+\define@key{datapie}{cutawayoffset}{%
+\dtl@cutawayoffset=#1}
+% \end{macrocode}
+% List of cut away segments.
+% \begin{macrocode}
+\define@key{datapie}{cutaway}{%
+\renewcommand*{\dtl@piecutaways}{#1}}
+% \end{macrocode}
+% Variable used to create the pie chart. (Must be a control
+% sequence.)
+% \begin{macrocode}
+\define@key{datapie}{variable}{%
+\def\DTLpievariable{#1}}
+% \end{macrocode}
+% Inner label
+% \begin{macrocode}
+\define@key{datapie}{innerlabel}{%
+\def\dtl@innerlabel{#1}}
+% \end{macrocode}
+% Outer label
+% \begin{macrocode}
+\define@key{datapie}{outerlabel}{%
+\def\dtl@outerlabel{#1}}
+% \end{macrocode}
+%
+%\begin{macro}{\DTLpiechart}
+%\begin{definition}
+% \cs{DTLpiechart}\oarg{conditions}\marg{option list}\marg{db name}\marg{assign list}
+%\end{definition}
+% Make a pie chart from data given in data base \meta{db name},
+% where \meta{assign list} is a comma-separated list of
+% \meta{cmd}\texttt{=}\meta{key} pairs. \meta{option list} must
+% include \texttt{variable}\texttt{=}\meta{cmd}, where \meta{cmd}
+% is included in \meta{assign list}. The optional argument
+% \meta{conditions} is the same as that for \cs{DTLforeach}.
+%\changes{2.26}{2016-07-20}{replaced fp commands}
+% \begin{macrocode}
+\newcommand*{\DTLpiechart}[4][\boolean{true}]{%
+\bgroup
+ \let\DTLpievariable=\relax
+ \setkeys{datapie}{#2}%
+ \ifx\DTLpievariable\relax
+ \PackageError{datapie}%
+ {\string\DTLpiechart\space missing variable}{}%
+ \else
+% \end{macrocode}
+% Compute the total.
+%\changes{1.01}{2007 Aug 17}{uses \cs{@sDTLforeach} instead of
+%\cs{DTLforeach}}
+% \begin{macrocode}
+ \def\dtl@total{0}%
+ \@sDTLforeach[#1]{#3}{#4}{%
+ \let\dtl@oldtotal=\dtl@total
+ \expandafter\DTLconverttodecimal\expandafter
+ {\DTLpievariable}{\dtl@variable}%
+ \dtladd{\dtl@total}{\dtl@variable}{\dtl@total}%
+ }%
+% \end{macrocode}
+% Compute the angles
+% \begin{macrocode}
+ \expandafter\DTLconverttodecimal\expandafter
+ {\DTLstartangle}{\@dtl@start}%
+ \@sDTLforeach[#1]{#3}{#4}{%
+ \expandafter\DTLconverttodecimal\expandafter
+ {\DTLpievariable}{\dtl@variable}%
+ \dtl@computeangles
+ {\csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname}%
+ {\dtl@variable}%
+ \expandafter\@dtl@seg\expandafter=
+ \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname%
+ \dtlmul{\dtl@tmp}{\dtl@variable}{100}%
+ \let\dtl@old=\dtl@tmp
+ \dtldiv{\dtl@tmp}{\dtl@old}{\dtl@total}%
+ \expandafter\dtlround
+ \csname dtl@piepercent@\romannumeral\@dtl@seg\endcsname\dtl@tmp
+ \c@DTLpieroundvar
+ }%
+% \end{macrocode}
+% Compute the offsets for each cut away segment
+% \begin{macrocode}
+ \@for\dtl@row:=\dtl@piecutaways\do{%
+ \expandafter\@dtl@set@off\dtl@row-\relax
+ }%
+% \end{macrocode}
+% Set the starting angle
+% \begin{macrocode}
+ \let\dtl@start=\DTLstartangle
+% \end{macrocode}
+% Do the pie chart
+% \begin{macrocode}
+ \begin{tikzpicture}
+ \DTLpieatbegintikz
+ \@sDTLforeach[#1]{#3}{#4}%
+ {%
+% \end{macrocode}
+% Store the segment number in \cs{@dtl@seg}
+% \begin{macrocode}
+ \expandafter\@dtl@seg\expandafter=
+ \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname%
+% \end{macrocode}
+% Set the start angle.
+% \begin{macrocode}
+ \edef\dtl@start{%
+ \csname dtl@sang@\romannumeral\@dtl@seg\endcsname}%
+% \end{macrocode}
+% Set the extent
+% \begin{macrocode}
+ \edef\dtl@extent{%
+ \csname dtl@angle@\romannumeral\@dtl@seg\endcsname}%
+% \end{macrocode}
+% Compute the end angle
+% \begin{macrocode}
+ \dtladd{\dtl@endangle}{\dtl@start}{\dtl@extent}%
+% \end{macrocode}
+% Compute the shift.
+% \begin{macrocode}
+ \edef\dtl@angle{%
+ \csname dtl@cut@angle@\romannumeral\@dtl@seg\endcsname}%
+ \let\dtl@old=\dtl@angle
+ \dtl@truncatedecimal\dtl@angle
+ \ifnum\dtl@angle>180\relax
+ \dtlsub{\dtl@angle}{\dtl@old}{360}%
+ \dtl@truncatedecimal\dtl@angle
+ \fi
+ \edef\dtl@cutlen{%
+ \csname dtl@cut@len@\romannumeral\@dtl@seg\endcsname
+ }%
+ \edef\@dtl@shift{(\dtl@angle:\dtl@cutlen)}%
+% \end{macrocode}
+% Compute the mid way angle.
+% \begin{macrocode}
+ \dtlmul{\dtl@angle}{\dtl@extent}{0.5}%
+ \dtladd{\dtl@midangle}{\dtl@angle}{\dtl@start}%
+% \end{macrocode}
+% Draw the segment.
+% \begin{macrocode}
+ \begin{scope}[shift={\@dtl@shift}]%
+% \end{macrocode}
+%\changes{2.26}{2016-07-20}{removed truncation (caused minor gap between
+%first and last segments)}
+% \begin{macrocode}
+ \fill[color=\DTLgetpiesegmentcolor\@dtl@seg] (0,0) --
+ (\dtl@start:\DTLradius)
+ arc (\dtl@start:\dtl@endangle:\DTLradius) -- cycle;
+% \end{macrocode}
+% Draw the outline if required:
+% \begin{macrocode}
+ \ifdim\DTLpieoutlinewidth>0pt\relax
+ \draw[color=\DTLpieoutlinecolor,%
+ line width=\DTLpieoutlinewidth]
+ (0,0) -- (\dtl@start:\DTLradius)
+ arc (\dtl@start:\dtl@endangle:\DTLradius) -- cycle;
+ \fi
+% \end{macrocode}
+% Convert decimal to an integer
+% \begin{macrocode}
+ \dtl@truncatedecimal\dtl@midangle
+% \end{macrocode}
+% Determine whether to rotate inner labels
+% \begin{macrocode}
+ \ifDTLrotateinner
+% \end{macrocode}
+% If the mid way angle is between 90 and 270, the text will look
+% upside-down, so adjust accordingly.
+%\changes{2.26}{2016-07-20}{replaced \cs{ifthen}}
+% \begin{macrocode}
+ \dtlifnumopenbetween{\dtl@midangle}{90}{270}%
+ {%
+ \let\@dtl@next\@firstoftwo
+ }%
+ {%
+ \dtlifnumlt{\dtl@midangle}{-90}%
+ {\let\@dtl@next\@firstoftwo}%
+ {\let\@dtl@next\@secondoftwo}%
+ }%
+ \@dtl@next
+ {%
+ \dtlsub{\dtl@labelangle}{\dtl@midangle}{180}%
+ \dtl@truncatedecimal\dtl@labelangle
+ \edef\dtl@innernodeopt{anchor=east,rotate=\dtl@labelangle}%
+ }%
+ {%
+ \edef\dtl@innernodeopt{anchor=west,rotate=\dtl@midangle}%
+ }%
+% \end{macrocode}
+% Don't rotate inner labels
+% \begin{macrocode}
+ \else
+ \edef\dtl@innernodeopt{anchor=center}%
+ \fi
+% \end{macrocode}
+% Determine whether to rotate outer labels
+% \begin{macrocode}
+ \ifDTLrotateouter
+% \end{macrocode}
+% If the mid way angle is between 90 and 270, the text will look
+% upside-down, so adjust accordingly.
+% \begin{macrocode}
+ \dtlifnumopenbetween{\dtl@midangle}{90}{270}%
+ {%
+ \let\@dtl@next\@firstoftwo
+ }%
+ {%
+ \dtlifnumlt{\dtl@midangle}{-90}%
+ {\let\@dtl@next\@firstoftwo}%
+ {\let\@dtl@next\@secondoftwo}%
+ }%
+ \@dtl@next
+ {%
+ \dtlsub{\dtl@labelangle}{\dtl@midangle}{180}%
+ \dtl@truncatedecimal\dtl@labelangle
+ \edef\dtl@outernodeopt{anchor=east,rotate=\dtl@labelangle}%
+ }%
+ {%
+ \edef\dtl@outernodeopt{anchor=west,rotate=\dtl@midangle}%
+ }%
+% \end{macrocode}
+% Don't rotate outer labels
+% \begin{macrocode}
+ \else
+% \end{macrocode}
+% If ($\theta>-45$ and $\theta < 45$) or $\theta=45$ or $\theta>315$
+% \begin{macrocode}
+ \dtlifnumeq{\dtl@midangle}{45}
+ {%
+ \let\@dtl@next\@firstoftwo
+ }%
+ {%
+ \dtlifnumgt{\dtl@midangle}{315}
+ {%
+ \let\@dtl@next\@firstoftwo
+ }%
+ {%
+ \dtlifnumopenbetween{\dtl@midangle}{-45}{45}%
+ {%
+ \let\@dtl@next\@firstoftwo
+ }%
+ {%
+ \let\@dtl@next\@secondoftwo
+ }%
+ }%
+ }%
+ \@dtl@next
+ {%
+% \end{macrocode}
+% East quadrant
+% \begin{macrocode}
+ \edef\dtl@outernodeopt{anchor=west}%
+ }%
+ {%
+ \dtlifnumopenbetween{\dtl@midangle}{45}{135}%
+ {%
+ \let\@dtl@next\@firstoftwo
+ }%
+ {%
+ \dtlifnumeq{\dtl@midangle}{135}%
+ {%
+ \let\@dtl@next\@firstoftwo
+ }%
+ {%
+ \let\@dtl@next\@secondoftwo
+ }%
+ }%
+ \@dtl@next
+ {%
+% \end{macrocode}
+% North quadrant
+% \begin{macrocode}
+ \edef\dtl@outernodeopt{anchor=south}%
+ }%
+ {%
+% \end{macrocode}
+%If ($\theta>135$ and $\theta<225$) or $\theta=225$ or $\theta=-135$
+%or $\theta<-135$
+% \begin{macrocode}
+ \dtlifnumopenbetween{\dtl@midangle}{135}{225}%
+ {%
+ \let\@dtl@next\@firstoftwo
+ }%
+ {%
+ \dtlifnumeq{\dtl@midangle}{225}%
+ {%
+ \let\@dtl@next\@firstoftwo
+ }%
+ {%
+ \dtlifnumeq{\dtl@midangle}{-135}%
+ {%
+ \let\@dtl@next\@firstoftwo
+ }%
+ {%
+ \dtlifnumlt{\dtl@midangle}{-135}%
+ {%
+ \let\@dtl@next\@firstoftwo
+ }%
+ {%
+ \let\@dtl@next\@secondoftwo
+ }%
+ }%
+ }%
+ }%
+ \@dtl@next
+ {%
+% \end{macrocode}
+% West quadrant
+% \begin{macrocode}
+ \edef\dtl@outernodeopt{anchor=east}%
+ }%
+ {%
+ \edef\dtl@outernodeopt{anchor=north}%
+ }%
+ }%
+ }%
+ \fi
+% \end{macrocode}
+% Draw inner and outer labels
+% \begin{macrocode}
+ \edef\@dtl@dolabel{%
+ \noexpand\draw (\dtl@midangle:\the\dtl@inneroffset)
+ node[\dtl@innernodeopt]{%
+ \noexpand\DTLdisplayinnerlabel{\noexpand\dtl@innerlabel}};
+ }%
+ \@dtl@dolabel
+ \edef\@dtl@dolabel{%
+ \noexpand\draw (\dtl@midangle:\the\dtl@outeroffset)
+ node[\dtl@outernodeopt]{%
+ \noexpand\DTLdisplayouterlabel{\noexpand\dtl@outerlabel}};
+ }%
+ \@dtl@dolabel
+ \end{scope}%
+ }%
+ \DTLpieatendtikz
+ \end{tikzpicture}%
+ \fi
+\egroup
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@computeangles}
+%\begin{definition}
+%\cs{dtl@computeangles}\marg{n}\marg{variable}
+%\end{definition}
+% Compute the angles for segment \meta{n}. This sets
+% \cs{dtl@sang@}\meta{n} (start angle),
+% \cs{dtl@angle@}\meta{n} (extent angle),
+% \cs{dtl@cut@angle@}\meta{n} (cut away angle) and
+% \cs{dtl@cut@len@}\meta{n} (cut away length).
+%\changes{2.26}{2016-07-20}{replaced fp commands}
+% \begin{macrocode}
+\newcommand*{\dtl@computeangles}[2]{%
+ \dtlifnumgt{\@dtl@start}{180}%
+ {%
+% \end{macrocode}
+% if $\mathrm{startangle} > 180$
+% \begin{macrocode}
+ \let\dtl@old=\@dtl@start
+% \end{macrocode}
+% $\mathrm{startangle} := \mathrm{startangle} - 360$
+% \begin{macrocode}
+ \dtlsub{\@dtl@start}{\dtl@old}{360}%
+ }%
+ {}%
+ \dtlifnumlt{\@dtl@start}{-180}%
+ {%
+% \end{macrocode}
+% if $\mathrm{startangle} < -180$
+% \begin{macrocode}
+ \let\dtl@old=\@dtl@start
+% \end{macrocode}
+% $\mathrm{startangle} = \mathrm{startangle} + 360$
+% \begin{macrocode}
+ \dtladd{\@dtl@start}{\dtl@old}{360}%
+ }%
+ {}%
+ \expandafter\edef\csname dtl@sang@\romannumeral#1\endcsname{%
+ \@dtl@start}%
+ \dtlmul{\dtl@angle}{360}{#2}%
+ \let\dtl@old=\dtl@angle
+ \dtldiv{\dtl@angle}{\dtl@old}{\dtl@total}%
+ \expandafter\let\csname dtl@angle@\romannumeral#1\endcsname=\dtl@angle
+ \let\dtl@old=\@dtl@start
+ \dtladd{\@dtl@start}{\dtl@old}{\dtl@angle}%
+ \expandafter\def\csname dtl@cut@angle@\romannumeral#1\endcsname{0}%
+ \expandafter\def\csname dtl@cut@len@\romannumeral#1\endcsname{0cm}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+% Set the offset angles.
+%\begin{macro}{\@dtl@set@off}
+% \begin{macrocode}
+\def\@dtl@set@off#1-#2\relax{%
+ \ifstrempty{#2}%
+ {%
+ \@@dtl@set@off{#1}%
+ }%
+ {%
+ \@@dtl@set@offr#1-#2\relax
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+% Set offset for individual segment:
+%\begin{macro}{\@@dtl@set@off}
+%\changes{2.26}{2016-07-20}{replaced fp commands}
+% \begin{macrocode}
+\newcommand*{\@@dtl@set@off}[1]{%
+ \edef\dtl@old{\csname dtl@angle@\romannumeral#1\endcsname}%
+ \dtlmul{\dtl@angle}{\dtl@old}{0.5}%
+ \let\dtl@old=\dtl@angle
+ \edef\dtl@sang{\csname dtl@sang@\romannumeral#1\endcsname}%
+ \dtladd{\dtl@angle}{\dtl@old}{\dtl@sang}%
+ \expandafter\edef\csname dtl@cut@angle@\romannumeral#1\endcsname{%
+ \dtl@angle}%
+ \expandafter\edef\csname dtl@cut@len@\romannumeral#1\endcsname{%
+ \the\dtl@cutawayoffset}%
+}
+% \end{macrocode}
+%\end{macro}
+% Define count register to keep track of segments
+%\begin{macro}{\@dtl@seg}
+% \begin{macrocode}
+\newcount\@dtl@seg
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@@dtl@setoffr}
+% Set offset for a range of segments
+%\changes{2.26}{2016-07-20}{replaced fp commands}
+% \begin{macrocode}
+\def\@@dtl@set@offr#1-#2-\relax{%
+ \ifnum#1>#2\relax
+ \PackageError{datapie}{Segment ranges must go in ascending order}{%
+ Try #2-#1 instead of #1-#2}%
+ \else
+ \def\dtl@angle{0}%
+ \@dtl@seg=#1\relax
+ \whiledo{\not\(\@dtl@seg > #2\)}{%
+ \let\dtl@old=\dtl@angle
+ \edef\dtl@segang{\csname dtl@angle@\romannumeral\@dtl@seg\endcsname}%
+ \dtladd{\dtl@angle}{\dtl@old}{\dtl@segang}%
+ \advance\@dtl@seg by 1\relax
+ }%
+ \let\dtl@old=\dtl@angle
+ \dtlmul{\dtl@angle}{\dtl@old}{0.5}%
+ \edef\dtl@sang{\csname dtl@sang@\romannumeral#1\endcsname}%
+ \let\dtl@old=\dtl@angle
+ \dtladd{\dtl@angle}{\dtl@old}{\dtl@sang}%
+ \@dtl@seg=#1\relax
+ \whiledo{\not\(\@dtl@seg > #2\)}{%
+ \expandafter
+ \let\csname dtl@cut@angle@\romannumeral\@dtl@seg\endcsname
+ =\dtl@angle
+ \expandafter
+ \edef\csname dtl@cut@len@\romannumeral\@dtl@seg\endcsname{%
+ \the\dtl@cutawayoffset}
+ \advance\@dtl@seg by 1\relax
+ }%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%\iffalse
+% \begin{macrocode}
+%</datapie.sty>
+% \end{macrocode}
+%\fi
+%\iffalse
+% \begin{macrocode}
+%<*dataplot.sty>
+% \end{macrocode}
+%\fi
+%\chapter{dataplot.sty}
+% Declare package:
+% \begin{macrocode}
+\NeedsTeXFormat{LaTeX2e}
+\ProvidesPackage{dataplot}[2018/12/07 v2.31 (NLCT)]
+% \end{macrocode}
+% Required packages
+% \begin{macrocode}
+\RequirePackage{xkeyval}
+\RequirePackage{tikz}
+\RequirePackage{datatool}
+% \end{macrocode}
+% Load TikZ plot libraries
+% \begin{macrocode}
+\usetikzlibrary{plotmarks}
+\usetikzlibrary{plothandlers}
+% \end{macrocode}
+% Load calc library
+%\changes{2.14}{2013-06-28}{added calc library requirement}
+% \begin{macrocode}
+\usetikzlibrary{calc}
+% \end{macrocode}
+%
+%\begin{macro}{\DTLplotstream}
+%\begin{definition}
+%\cs{DTLplotstream}\oarg{condition}\marg{db name}\marg{x key}\marg{y key}
+%\end{definition}
+% Add points to a stream from the database called \meta{db name}
+% where the $x$ co-ordinates are given by the key \meta{x key}
+% and the $y$ co-ordinates are given by the key \meta{y key}.
+% The optional argument \meta{condition} is the same as that
+% for \cs{DTLforeach}
+%\changes{1.01}{2007 Aug 17}{uses \cs{@sDTLforeach} instead of
+%\cs{DTLforeach}}
+% \begin{macrocode}
+\newcommand*{\DTLplotstream}[4][\boolean{true}]{%
+ \@sDTLforeach[#1]{#2}{\dtl@x=#3,\dtl@y=#4}{%
+ \DTLconverttodecimal{\dtl@x}{\dtl@decx}%
+ \DTLconverttodecimal{\dtl@y}{\dtl@decy}%
+ \pgfplotstreampoint{\pgfpointxy{\dtl@decx}{\dtl@decy}}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLplotmarks}
+%\cs{DTLplotmarks} contains a list of plot marks used by
+%\cs{DTLplot}.
+% \begin{macrocode}
+\newcommand*{\DTLplotmarks}{%
+ \pgfuseplotmark{o},%
+ \pgfuseplotmark{x},%
+ \pgfuseplotmark{+},%
+ \pgfuseplotmark{square},%
+ \pgfuseplotmark{triangle},%
+ \pgfuseplotmark{diamond},%
+ \pgfuseplotmark{pentagon},%
+ \pgfuseplotmark{asterisk},%
+ \pgfuseplotmark{star}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLplotmarkcolors}
+%\cs{DTLplotmarkcolors} contains a list of the plot mark colours.
+% \begin{macrocode}
+\newcommand*{\DTLplotmarkcolors}{%
+ red,%
+ green,%
+ blue,%
+ yellow,%
+ magenta,%
+ cyan,%
+ orange,%
+ black,%
+ gray}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLplotlines}
+%\cs{DTLplotlines} contains a list of dash patterns used by
+%\cs{DLTplot}.
+%\changes{1.03}{2009 January 27}{fixed error in solid line setting}
+% \begin{macrocode}
+\newcommand*{\DTLplotlines}{%
+ \pgfsetdash{}{0pt},% solid line
+ \pgfsetdash{{10pt}{5pt}}{0pt},%
+ \pgfsetdash{{5pt}{5pt}}{0pt},%
+ \pgfsetdash{{1pt}{5pt}}{0pt},%
+ \pgfsetdash{{5pt}{5pt}{1pt}{5pt}}{0pt},%
+ \pgfsetdash{{1pt}{3pt}}{0pt},%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLplotlinecolors}
+%\cs{DTLplotlinecolors} contains a list of the plot line colours.
+% \begin{macrocode}
+\newcommand*{\DTLplotlinecolors}{%
+ red,%
+ green,%
+ blue,%
+ yellow,%
+ magenta,%
+ cyan,%
+ orange,%
+ black,%
+ gray}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLplotwidth}
+% The default total plot width is stored in the length
+% \cs{dtlplotwidth}
+% \begin{macrocode}
+\newlength\DTLplotwidth
+\setlength\DTLplotwidth{4in}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLplotheight}
+% The default total plot height is stored in the length
+% \cs{dtlplotheight}
+% \begin{macrocode}
+\newlength\DTLplotheight
+\setlength\DTLplotheight{4in}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLticklength}
+% The length of the tick marks is given by \cs{DTLticklength}
+% \begin{macrocode}
+\newlength\DTLticklength
+\setlength\DTLticklength{5pt}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLminorticklength}
+% The length of the minor tick marks is given by
+% \cs{DTLminorticklength}.
+% \begin{macrocode}
+\newlength\DTLminorticklength
+\setlength\DTLminorticklength{2pt}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLticklabeloffset}
+% The offset from the axis to the tick label is given by
+% \cs{DTLticklabeloffset}.
+% \begin{macrocode}
+\newlength\DTLticklabeloffset
+\setlength\DTLticklabeloffset{8pt}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtl@xticlabelheight}
+% \cs{dtl@xticlabelheight} is used to store the height of
+% the $x$ tick labels.
+% \begin{macrocode}
+\newlength\dtl@xticlabelheight
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtl@yticlabelwidth}
+% \cs{dtl@yticlabelwidth} is used to store the width of
+% the $y$ tick labels.
+% \begin{macrocode}
+\newlength\dtl@yticlabelwidth
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLmintickgap}
+% \cs{DTLmintickgap} stores the suggested minimum distance between
+% tick marks where the gap is not specified.
+% \begin{macrocode}
+\newlength\DTLmintickgap
+\setlength\DTLmintickgap{20pt}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLminminortickgap}
+% The suggested minimum distance between minor tick marks where the
+% gap is not specified is given by \cs{DTLminminortickgap}.
+% \begin{macrocode}
+\newlength\DTLminminortickgap
+\setlength\DTLminminortickgap{5pt}
+% \end{macrocode}
+%\end{macro}
+%\begin{counter}{DTLplotroundvar}
+% Round $x$ tick labels to the number of digits given by
+% the counter \ctrfmt{DTLplotroundXvar}.
+% \begin{macrocode}
+\newcounter{DTLplotroundXvar}
+\setcounter{DTLplotroundXvar}{2}
+% \end{macrocode}
+%\end{counter}
+%\begin{counter}{DTLplotroundYvar}
+% Round $y$ tick labels to the number of digits given by
+% the counter \ctrfmt{DTLplotroundYvar}.
+% \begin{macrocode}
+\newcounter{DTLplotroundYvar}
+\setcounter{DTLplotroundYvar}{2}
+% \end{macrocode}
+%\end{counter}
+%\begin{macro}{\ifDTLxaxis}
+% The conditional \cs {ifDTLxaxis} is used to determine whether or
+% not to display the $x$ axis.
+% \begin{macrocode}
+\newif\ifDTLxaxis
+\DTLxaxistrue
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLXAxisStyle}
+% The style of the $x$ axis is given by \cs{DTLXAxisStyle}. This
+% is just a solid line by default.
+% \begin{macrocode}
+\newcommand*{\DTLXAxisStyle}{-}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\ifDTLyaxis}
+% The conditional \cs{ifDTLyaxis} is used to determine whether or
+% not to display the $y$ axis
+% \begin{macrocode}
+\newif\ifDTLyaxis
+\DTLyaxistrue
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLYAxisStyle}
+% The style of the $y$ axis is given by \cs{DTLYAxisStyle}. This
+% is just a solid line by default.
+% \begin{macrocode}
+\newcommand*{\DTLYAxisStyle}{-}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLmajorgridstyle}
+% The style of the major grid lines is given by
+% \cs{DTLmajorgridstyle}.
+% \begin{macrocode}
+\newcommand*{\DTLmajorgridstyle}{color=gray,-}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLminorgridstyle}
+% The style of the minor grid lines is given by
+% \cs{DTLminorgridstyle}.
+% \begin{macrocode}
+\newcommand*{\DTLminorgridstyle}{color=gray,loosely dotted}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\ifDTLxticsin}
+% The conditional \cs{ifDTLxticsin} is used to determine whether
+% the $x$ tics should point in or out.
+% \begin{macrocode}
+\newif\ifDTLxticsin
+\DTLxticsintrue
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\ifDTLyticsin}
+% The conditional \cs{ifDTLyticsin} is used to determine whether
+% the $y$ tics should point in or out.
+% \begin{macrocode}
+\newif\ifDTLyticsin
+\DTLyticsintrue
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtl@legendsetting}
+% The legend setting is stored in the count register
+% \cs{dtl@legendsetting}.
+% \begin{macrocode}
+\newcount\dtl@legendsetting
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLlegendxoffset}
+% The gap between the border of plot and legend is given by the
+% lengths \cs{DTLlegendxoffset} and \cs{DTLlegendyoffset}
+% \begin{macrocode}
+\newlength\DTLlegendxoffset
+\setlength\DTLlegendxoffset{10pt}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLlegendyoffset}
+% \begin{macrocode}
+\newlength\DTLlegendyoffset
+\setlength\DTLlegendyoffset{10pt}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLformatlegend}
+%\begin{definition}
+%\cs{DTLformatlegend}\marg{legend}
+%\end{definition}
+% This formats the legend.
+% \begin{macrocode}
+\newcommand*{\DTLformatlegend}[1]{%
+\setlength{\fboxrule}{1.1pt}%
+\fcolorbox{black}{white}{#1}}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\ifDTLshowmarkers}
+% The conditional \cs{ifDTLshowmarkers} is used to specify
+% whether or not to use markers.
+% \begin{macrocode}
+\newif\ifDTLshowmarkers
+\DTLshowmarkerstrue
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\ifDTLshowlines}
+% The conditional \cs{ifDTLshowlines} is used to specify
+% whether or not to use lines.
+% \begin{macrocode}
+\newif\ifDTLshowlines
+\DTLshowlinesfalse
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLplotatbegintikz}
+% \cs{DTLplotatbegintikz} is a hook to insert stuff at the
+% start of the \env{tikzpicture}
+% environment (after the unit vectors have been set).
+% \begin{macrocode}
+\newcommand*{\DTLplotatbegintikz}{}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlplothandlermark}
+%\changes{2.15}{2013-07-10}{new}
+% Provide a convenient access to \cs{pgfplothandlermark} that
+% reverses the effect of the plot scaling.
+% \begin{macrocode}
+\newcommand*{\@dtlplothandlermark}[1]{%
+ \pgfplothandlermark
+ {%
+ \pgfmathparse{1/\dtl@scale@x}%
+ \pgftransformxscale{\pgfmathresult}%
+ \pgfmathparse{1/\dtl@scale@y}%
+ \pgftransformyscale{\pgfmathresult}%
+ #1%
+ }%
+}
+% \end{macrocode}
+% Just in case a user attempts to use \cs{dtlplothandermark} outside
+% \ics{DTLplot}:
+% \begin{macrocode}
+\newcommand*{\dtlplothandlermark}[1]{%
+ \PackageWarning{dataplot}{\string\dtlplothandlermark\space
+ found outside \string\DTLplot}%
+ \pgfplothandlermark{#1}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLplotatendtikz}
+% \cs{DTLplotatendtikz} is a hook to insert stuff at the end
+% of the \env{tikzpicture} environment.
+% \begin{macrocode}
+\newcommand*{\DTLplotatendtikz}{}
+% \end{macrocode}
+%\end{macro}
+%
+% Plot settings. The database key for the $x$ value is
+% given by the "x" setting:
+% \begin{macrocode}
+\define@key{dataplot}{x}{%
+\def\dtl@xkey{#1}}
+% \end{macrocode}
+% The database key for the $y$ value is given by the "y" setting:
+% \begin{macrocode}
+\define@key{dataplot}{y}{%
+\def\dtl@ykey{#1}}
+% \end{macrocode}
+% The list of plot mark colours is given by the "markcolors" setting.
+% (This should be a comma separated list of colour names.)
+% \begin{macrocode}
+\define@key{dataplot}{markcolors}{%
+\def\DTLplotmarkcolors{#1}}
+% \end{macrocode}
+% The list of plot line colours is given by the "linecolors" setting.
+% (This should be a comma separated list of colour names.)
+% \begin{macrocode}
+\define@key{dataplot}{linecolors}{%
+\def\DTLplotlinecolors{#1}}
+% \end{macrocode}
+% The list of plot mark and line colours is given by the "colors"
+% setting. (This should be a comma separated list of colour names.)
+% \begin{macrocode}
+\define@key{dataplot}{colors}{%
+\def\DTLplotmarkcolors{#1}%
+\def\DTLplotlinecolors{#1}}
+% \end{macrocode}
+% The list of plot marks is given by the "marks" setting. (This
+% should be a comma separated list of code that generates
+% pgf plot marks.)
+% \begin{macrocode}
+\define@key{dataplot}{marks}{%
+\def\DTLplotmarks{#1}}
+% \end{macrocode}
+% The list of plot line styles is given by the "lines" setting. (This
+% should be a comma separated list of code that sets the line
+% style.) An empty set will create solid lines.
+% \begin{macrocode}
+\define@key{dataplot}{lines}{%
+\def\DTLplotlines{#1}}
+% \end{macrocode}
+% The total width of the plot is given by the "width" setting.
+% \begin{macrocode}
+\define@key{dataplot}{width}{%
+\setlength\DTLplotwidth{#1}}
+% \end{macrocode}
+% The total height of the plot is given by the "height" setting.
+% \begin{macrocode}
+\define@key{dataplot}{height}{%
+\setlength\DTLplotheight{#1}}
+% \end{macrocode}
+% Determine whether to show lines, markers or both
+% \begin{macrocode}
+\define@choicekey{dataplot}{style}[\val\nr]{both,lines,markers}{%
+\ifcase\nr\relax
+ \DTLshowlinestrue
+ \DTLshowmarkerstrue
+\or
+ \DTLshowlinestrue
+ \DTLshowmarkersfalse
+\or
+ \DTLshowmarkerstrue
+ \DTLshowlinesfalse
+\fi}
+% \end{macrocode}
+% Determine whether or not to display the axes
+% \begin{macrocode}
+\define@choicekey{dataplot}{axes}[\val\nr]{both,x,y,none}[both]{%
+\ifcase\nr\relax
+ % both
+ \DTLxaxistrue
+ \DTLxticstrue
+ \DTLyaxistrue
+ \DTLyticstrue
+\or % x
+ \DTLxaxistrue
+ \DTLxticstrue
+ \DTLyaxisfalse
+ \DTLyticsfalse
+\or % y
+ \DTLxaxisfalse
+ \DTLxticsfalse
+ \DTLyaxistrue
+ \DTLyticstrue
+\or % none
+ \DTLxaxisfalse
+ \DTLxticsfalse
+ \DTLyaxisfalse
+ \DTLyticsfalse
+\fi
+}
+% \end{macrocode}
+%\begin{macro}{\ifDTLbox}
+% Enclose plot in a box
+% \begin{macrocode}
+\define@boolkey{dataplot}[DTL]{box}[true]{}
+\DTLboxfalse
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\ifDTLxticstrue}
+% Condition to determine whether to show the $x$ tick marks
+% \begin{macrocode}
+\define@boolkey{dataplot}[DTL]{xtics}[true]{}
+\DTLxticstrue
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\ifDTLyticstrue}
+% Condition to determine whether to show the $y$ tick marks
+% \begin{macrocode}
+\define@boolkey{dataplot}[DTL]{ytics}[true]{}
+\DTLyticstrue
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\ifDTLxminortics}
+% Condition to determine whether to show the $x$ minor tick marks
+% \begin{macrocode}
+\define@boolkey{dataplot}[DTL]{xminortics}[true]{%
+\ifDTLxminortics \DTLxticstrue\fi}
+\DTLxminorticsfalse
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\ifDTLyminortics}
+% Condition to determine whether to show the $y$ minor tick marks
+% \begin{macrocode}
+\define@boolkey{dataplot}[DTL]{yminortics}[true]{%
+\ifDTLyminortics \DTLyticstrue\fi}
+\DTLyminorticsfalse
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\ifDTLgrid}
+% Determine whether to draw the grid
+% \begin{macrocode}
+\define@boolkey{dataplot}[DTL]{grid}[true]{}
+% \end{macrocode}
+%\end{macro}
+% Determine whether the $x$ tick marks should point
+% in or out:
+% \begin{macrocode}
+\define@choicekey{dataplot}{xticdir}[\val\nr]{in,out}{%
+\ifcase\nr\relax
+ \DTLxticsintrue
+\or
+ \DTLxticsinfalse
+\fi
+}
+% \end{macrocode}
+% Determine whether the $y$ tick marks should point
+% in or out:
+% \begin{macrocode}
+\define@choicekey{dataplot}{yticdir}[\val\nr]{in,out}{%
+\ifcase\nr\relax
+ \DTLyticsintrue
+\or
+ \DTLyticsinfalse
+\fi
+}
+% \end{macrocode}
+% Determine whether the $x$ and $y$ tick marks should point
+% in or out;
+% \begin{macrocode}
+\define@choicekey{dataplot}{ticdir}[\val\nr]{in,out}{%
+\ifcase\nr\relax
+ \DTLxticsintrue
+ \DTLyticsintrue
+\or
+ \DTLxticsinfalse
+ \DTLyticsinfalse
+\fi
+}
+% \end{macrocode}
+% Set the bounds of the graph (value must be in the form
+% \meta{min x}","\meta{min y}","\meta{max x}","\meta{max y}
+% (bounds overrides minx, miny, maxx and maxy settings.)
+% \begin{macrocode}
+\define@key{dataplot}{bounds}{%
+\def\dtl@bounds{#1}}
+\let\dtl@bounds=\relax
+% \end{macrocode}
+% Set only the lower $x$ bound
+% \begin{macrocode}
+\define@key{dataplot}{minx}{%
+\def\dtl@minx{#1}}
+\let\dtl@minx=\relax
+% \end{macrocode}
+% Set only the upper $x$ bound:
+% \begin{macrocode}
+\define@key{dataplot}{maxx}{%
+\def\dtl@maxx{#1}}
+\let\dtl@maxx=\relax
+% \end{macrocode}
+% Set only the lower $y$ bound:
+% \begin{macrocode}
+\define@key{dataplot}{miny}{%
+\def\dtl@miny{#1}}
+\let\dtl@miny=\relax
+% \end{macrocode}
+% Set only the upper $y$ bound:
+% \begin{macrocode}
+\define@key{dataplot}{maxy}{%
+\def\dtl@maxy{#1}}
+\let\dtl@maxy=\relax
+% \end{macrocode}
+% Define list of points for $x$ ticks. (Must be a comma separated
+% list of decimal numbers.)
+% \begin{macrocode}
+\define@key{dataplot}{xticpoints}{%
+\def\dtl@xticlist{#1}\DTLxticstrue\DTLxaxistrue}
+\let\dtl@xticlist=\relax
+% \end{macrocode}
+% Define list of points for $y$ ticks. (Must be a comma separated
+% list of decimal numbers.)
+% \begin{macrocode}
+\define@key{dataplot}{yticpoints}{%
+\def\dtl@yticlist{#1}\DTLyticstrue\DTLyaxistrue}
+\let\dtl@yticlist=\relax
+% \end{macrocode}
+% Define a the gap between $x$ tick marks (xticpoints overrides
+% xticgap)
+% \begin{macrocode}
+\define@key{dataplot}{xticgap}{\def\dtl@xticgap{#1}%
+\DTLxticstrue\DTLxaxistrue}
+\let\dtl@xticgap=\relax
+% \end{macrocode}
+% Define a the gap between $y$ tick marks (yticpoints overrides
+% yticgap)
+% \begin{macrocode}
+\define@key{dataplot}{yticgap}{\def\dtl@yticgap{#1}%
+\DTLyticstrue\DTLyaxistrue}
+\let\dtl@yticgap=\relax
+% \end{macrocode}
+% Define comma separated list of labels for $x$ ticks.
+% \begin{macrocode}
+\define@key{dataplot}{xticlabels}{%
+\def\dtl@xticlabels{#1}\DTLxticstrue\DTLxaxistrue}
+\let\dtl@xticlabels=\relax
+% \end{macrocode}
+% Define comma separated list of labels for $y$ ticks.
+% \begin{macrocode}
+\define@key{dataplot}{yticlabels}{%
+\def\dtl@yticlabels{#1}\DTLyticstrue\DTLyaxistrue}
+\let\dtl@yticlabels=\relax
+% \end{macrocode}
+% Define $x$ axis label
+% \begin{macrocode}
+\define@key{dataplot}{xlabel}{%
+\def\dtl@xlabel{#1}}
+\let\dtl@xlabel=\relax
+% \end{macrocode}
+% Define $y$ axis label
+% \begin{macrocode}
+\define@key{dataplot}{ylabel}{%
+\def\dtl@ylabel{#1}}
+\let\dtl@ylabel=\relax
+% \end{macrocode}
+% The legend setting may be one of: "none" (don't show it),
+% "north", "northeast", "east", "southeast", "south", "southwest",
+% "west", or "northwest". These set the count register
+% \cs{dtl@legendsetting}.
+% \begin{macrocode}
+\define@choicekey{dataplot}{legend}[\val\nr]{none,north,northeast,%
+east,southeast,south,southwest,west,northwest}[northeast]{%
+\dtl@legendsetting=\nr\relax
+}
+% \end{macrocode}
+% Legend labels (comma separated list). If omitted, the database
+% name is used.
+% \begin{macrocode}
+\define@key{dataplot}{legendlabels}{\def\dtl@legendlabels{#1}}
+% \end{macrocode}
+%
+%\begin{macro}{\DTLplot}
+%\begin{definition}
+%\cs{DTLplot}\oarg{condition}\marg{db list}\marg{settings}
+%\end{definition}
+% Creates a plot (inside a \env{tikzpicture} environment) of all
+% the data given in the databases listed in \meta{db list}.
+% \begin{macrocode}
+\newcommand*{\DTLplot}[3][\boolean{true}]{%
+\bgroup
+ \let\dtl@xkey=\relax
+ \let\dtl@ykey=\relax
+ \let\dtl@legendlabels=\relax
+ \setkeys{dataplot}{#3}%
+ \let\dtl@plotmarklist=\DTLplotmarks
+ \let\dtl@plotlinelist=\DTLplotlines
+ \let\dtl@plotmarkcolorlist=\DTLplotmarkcolors
+ \let\dtl@plotlinecolorlist=\DTLplotlinecolors
+ \def\dtl@legend{}%
+ \ifx\dtl@legendlabels\relax
+ \edef\dtl@legendlabels{#2}%
+ \fi
+ \ifx\dtl@xkey\relax
+ \PackageError{dataplot}{Missing x setting for
+ \string\DTLplot}{}%
+ \else
+ \ifx\dtl@ykey\relax
+ \PackageError{dataplot}{Missing y setting for
+ \string\DTLplot}{}%
+ \else
+% \end{macrocode}
+% If user didn't specified bounds,
+% compute the maximum and minimum $x$ and $y$ values over
+% all the databases listed.
+% \begin{macrocode}
+ \ifx\dtl@bounds\relax
+ \DTLcomputebounds[#1]{#2}{\dtl@xkey}{\dtl@ykey}
+ {\DTLminX}{\DTLminY}{\DTLmaxX}{\DTLmaxY}%
+ \ifx\dtl@minx\relax
+ \else
+ \let\DTLminX=\dtl@minx
+ \fi
+ \ifx\dtl@maxx\relax
+ \else
+ \let\DTLmaxX=\dtl@maxx
+ \fi
+ \ifx\dtl@miny\relax
+ \else
+ \let\DTLminY=\dtl@miny
+ \fi
+ \ifx\dtl@maxy\relax
+ \else
+ \let\DTLmaxY=\dtl@maxy
+ \fi
+% \end{macrocode}
+% Otherwise extract information from \cs{dtl@bounds}
+% \begin{macrocode}
+ \else
+ \expandafter\dtl@getbounds\dtl@bounds\@nil
+ \fi
+% \end{macrocode}
+% Determine scaling factors and offsets. The $x$-scale factor is
+% given by:
+%\[
+% s_x = \frac{W}{x_{\max}-x_{\min}}
+%\]
+% where $W$ is the plot width. The $x$ offset is $-s_x x_{\min}$.
+% Similarly for $y$.
+%\changes{2.14}{2013-06-28}{replaced \cs{FPsub} etc with \cs{dtlsub} etc}
+% \begin{macrocode}
+ \@dtl@tmpcount=\DTLplotwidth
+ \divide\@dtl@tmpcount by 65536\relax
+ \dtlsub{\dtl@dx}{\DTLmaxX}{\DTLminX}%
+ \dtldiv{\dtl@scale@x}{\number\@dtl@tmpcount}{\dtl@dx}%
+ \dtlmul{\dtl@offset@x}{-\dtl@scale@x}{\DTLminX}%
+ \@dtl@tmpcount=\DTLplotheight
+ \divide\@dtl@tmpcount by 65536\relax
+ \dtlsub{\dtl@dy}{\DTLmaxY}{\DTLminY}%
+ \dtldiv{\dtl@scale@y}{\number\@dtl@tmpcount}{\dtl@dy}%
+ \dtlmul{\dtl@offset@y}{-\dtl@scale@y}{\DTLminY}%
+% \end{macrocode}
+% If x tics specified, construct a list of x tic points if not
+% already specified.
+% \begin{macrocode}
+ \ifDTLxtics
+ \ifx\dtl@xticlist\relax
+ \ifx\dtl@xticgap\relax
+% \end{macrocode}
+% Get the min tick gap in data co-ordinates
+% \begin{macrocode}
+ \dtlsub{\dtl@mingap}{\number\DTLmintickgap}{\dtl@offset@x}%
+ \dtldiv{\dtl@mingap}{\dtl@mingap}{\dtl@scale@x}%
+ \dtldiv{\dtl@mingap}{\dtl@mingap}{65536}%
+% \end{macrocode}
+% construct tick list
+% \begin{macrocode}
+ \dtl@constructticklist\DTLminX\DTLmaxX
+ \dtl@mingap\dtl@xticlist
+ \else
+ \DTLifFPopenbetween{0}{\DTLminX}{\DTLmaxX}{%
+ \dtl@constructticklistwithgapz
+ \DTLminX\DTLmaxX\dtl@xticlist\dtl@xticgap}{%
+ \dtl@constructticklistwithgap
+ \DTLminX\DTLmaxX\dtl@xticlist\dtl@xticgap}%
+ \fi
+ \fi
+% \end{macrocode}
+% Construct a list of $x$ minor tick points if required
+% \begin{macrocode}
+ \let\dtl@xminorticlist\@empty
+ \ifDTLxminortics
+ \let\dtl@prevtick=\relax
+ \@for\dtl@nexttick:=\dtl@xticlist\do{%
+ \ifx\dtl@prevtick\relax
+ \else
+ \dtl@constructminorticklist
+ \dtl@prevtick\dtl@nexttick\dtl@scale@x\dtl@xminorticlist
+ \fi
+ \let\dtl@prevtick=\dtl@nexttick
+ }%
+ \fi
+% \end{macrocode}
+% Determine the height of the $x$ tick labels.
+% \begin{macrocode}
+ \ifx\dtl@xticlabels\relax
+ \settoheight{\dtl@xticlabelheight}{\dtl@xticlist}%
+ \else
+ \settoheight{\dtl@xticlabelheight}{\dtl@xticlabels}%
+ \fi
+ \else
+ \setlength{\dtl@xticlabelheight}{0pt}%
+ \fi
+% \end{macrocode}
+% If y tics specified, construct a list of y tic points if not
+% already specified.
+% \begin{macrocode}
+ \setlength{\dtl@yticlabelwidth}{0pt}%
+ \ifDTLytics
+ \ifx\dtl@yticlist\relax
+ \ifx\dtl@yticgap\relax
+% \end{macrocode}
+% Get the min tick gap in data co-ordinates
+% \begin{macrocode}
+ \dtlsub{\dtl@mingap}{\number\DTLmintickgap}{\dtl@offset@y}%
+ \dtldiv{\dtl@mingap}{\dtl@mingap}{\dtl@scale@y}%
+ \dtldiv{\dtl@mingap}{\dtl@mingap}{65536}%
+% \end{macrocode}
+% construct tick list
+% \begin{macrocode}
+ \dtl@constructticklist\DTLminY\DTLmaxY
+ \dtl@mingap\dtl@yticlist
+ \else
+ \DTLifFPopenbetween{0}{\DTLminY}{\DTLmaxY}{%
+ \dtl@constructticklistwithgapz
+ \DTLminY\DTLmaxY\dtl@yticlist\dtl@yticgap}{%
+ \dtl@constructticklistwithgap
+ \DTLminY\DTLmaxY\dtl@yticlist\dtl@yticgap}%
+ \fi
+ \fi
+% \end{macrocode}
+% Construct a list of $y$ minor tick points if required
+% \begin{macrocode}
+ \let\dtl@yminorticlist\@empty
+ \ifDTLyminortics
+ \let\dtl@prevtick=\relax
+ \@for\dtl@nexttick:=\dtl@yticlist\do{%
+ \ifx\dtl@prevtick\relax
+ \else
+ \dtl@constructminorticklist
+ \dtl@prevtick\dtl@nexttick\dtl@scale@y\dtl@yminorticlist
+ \fi
+ \let\dtl@prevtick=\dtl@nexttick
+ }%
+ \fi
+% \end{macrocode}
+% Determine the width of the $y$ tick labels.
+%\changes{2.14}{2013-06-28}{replaced \cs{FPround} with \cs{dtlround}}
+% \begin{macrocode}
+ \ifx\dtl@ylabel\relax
+ \else
+ \ifx\dtl@yticlabels\relax
+ \@for\dtl@thislabel:=\dtl@yticlist\do{%
+ \dtlround{\dtl@thislabel}{\dtl@thislabel}
+ {\c@DTLplotroundYvar}%
+ \settowidth{\dtl@tmplength}{\dtl@thislabel}%
+ \ifdim\dtl@tmplength>\dtl@yticlabelwidth
+ \setlength{\dtl@yticlabelwidth}{\dtl@tmplength}%
+ \fi
+ }%
+ \else
+ \@for\dtl@thislabel:=\dtl@yticlabels\do{%
+ \settowidth{\dtl@tmplength}{\dtl@thislabel}%
+ \ifdim\dtl@tmplength>\dtl@yticlabelwidth
+ \setlength{\dtl@yticlabelwidth}{\dtl@tmplength}%
+ \fi
+ }%
+ \fi
+ \fi
+ \fi
+% \end{macrocode}
+% Start the picture.
+% \begin{macrocode}
+ \begin{tikzpicture}
+% \end{macrocode}
+% Set the $x$ and $y$ unit vectors.
+% \begin{macrocode}
+ \pgfsetxvec{\pgfpoint{1pt}{0pt}}%
+ \pgfsetyvec{\pgfpoint{0pt}{1pt}}%
+% \end{macrocode}
+% Set the transformation matrix, so user can plot things using the
+% data co-ordinate space, but scope it, so it doesn't affect any plot
+% marks later
+% \begin{macrocode}
+ \begin{scope}
+ \pgftransformcm{\dtl@scale@x}{0}{0}{\dtl@scale@y}%
+ {\pgfpoint{\dtl@offset@x pt}{\dtl@offset@y pt}}%
+% \end{macrocode}
+% Add any extra information the user requires
+% \begin{macrocode}
+ \let\dtlplothandlermark\@dtlplothandlermark
+ \DTLplotatbegintikz
+% \end{macrocode}
+% Determine whether to put a box around the plot
+% \begin{macrocode}
+ \ifDTLbox
+ \draw (\DTLminX,\DTLminY) -- (\DTLmaxX,\DTLminY) --
+ (\DTLmaxX,\DTLmaxY) -- (\DTLminX,\DTLmaxY) --
+ cycle;
+ \else
+% \end{macrocode}
+% Plot $x$ axis if required.
+% \begin{macrocode}
+ \ifDTLxaxis
+ \expandafter\draw\expandafter[\DTLXAxisStyle]
+ (\DTLminX,\DTLminY) -- (\DTLmaxX,\DTLminY);
+ \fi
+% \end{macrocode}
+% Plot $y$ axis if required.
+% \begin{macrocode}
+ \ifDTLyaxis
+ \expandafter\draw\expandafter[\DTLYAxisStyle]
+ (\DTLminX,\DTLminY) -- (\DTLminX,\DTLmaxY);
+ \fi
+ \fi
+% \end{macrocode}
+% Plot grid if required
+% \begin{macrocode}
+ \ifDTLgrid
+ \ifDTLxminortics
+ \@for\dtl@thistick:=\dtl@xminorticlist\do{%
+ \expandafter\draw\expandafter[\DTLminorgridstyle]
+ (\dtl@thistick,\DTLminY) -- (\dtl@thistick,\DTLmaxY);
+ }%
+ \fi
+ \ifDTLyminortics
+ \@for\dtl@thistick:=\dtl@yminorticlist\do{%
+ \expandafter\draw\expandafter[\DTLminorgridstyle]
+ (\DTLminX,\dtl@thistick) -- (\DTLmaxX,\dtl@thistick);
+ }%
+ \fi
+ \@for\dtl@thistick:=\dtl@xticlist\do{%
+ \expandafter\draw\expandafter[\DTLmajorgridstyle]
+ (\dtl@thistick,\DTLminY) -- (\dtl@thistick,\DTLmaxY);
+ }%
+ \@for\dtl@thistick:=\dtl@yticlist\do{%
+ \expandafter\draw\expandafter[\DTLmajorgridstyle]
+ (\DTLminX,\dtl@thistick) -- (\DTLmaxX,\dtl@thistick);
+ }%
+ \fi
+% \end{macrocode}
+% Plot $x$ tics if required.
+% \begin{macrocode}
+ \ifDTLxtics
+% \end{macrocode}
+% Get tick length in terms of canvas co-ordinates
+% \begin{macrocode}
+ \dtlsub{\dtl@ticklength}{\number\DTLticklength}{-\dtl@offset@y}%
+ \dtldiv{\dtl@ticklength}{\dtl@ticklength}{\dtl@scale@y}%
+ \dtldiv{\dtl@ticklength}{\dtl@ticklength}{65536}%
+% \end{macrocode}
+% Get tick label offset in terms of canvas co-ordinates
+% \begin{macrocode}
+ \addtolength\dtl@xticlabelheight{\DTLticklabeloffset}%
+ \dtlsub{\dtl@ticlabeloffset}{\number\dtl@xticlabelheight}{-\dtl@offset@y}%
+ \dtldiv{\dtl@ticlabeloffset}{\dtl@ticlabeloffset}{\dtl@scale@y}%
+ \dtldiv{\dtl@ticlabeloffset}{\dtl@ticlabeloffset}{65536}%
+% \end{macrocode}
+% Iterate through tick list.
+% \begin{macrocode}
+ \@for\dtl@thistick:=\dtl@xticlist\do{%
+% \end{macrocode}
+% Store tick label in \cs{dtl@thislabel}
+% \begin{macrocode}
+ \let\dtl@thisticklabel\dtl@thistick
+ \ifx\dtl@xticlabels\relax
+ \dtlround{\dtl@thislabel}{\dtl@thistick}
+ {\c@DTLplotroundXvar}%
+ \else
+ \dtl@chopfirst\dtl@xticlabels\dtl@thislabel\dtl@rest
+ \let\dtl@xticlabels=\dtl@rest
+ \fi
+% \end{macrocode}
+% Draw tick.
+% \begin{macrocode}
+ \ifDTLxticsin
+ \draw (\dtl@thistick,\DTLminY) -- ++(0,\dtl@ticklength);
+ \draw (\dtl@thistick,\DTLminY)
+ ++ (0,-\dtl@ticlabeloffset) node {\dtl@thislabel};
+ \else
+ \draw (\dtl@thistick,\DTLminY) -- ++(0,-\dtl@ticklength)
+ ++ (0,-\dtl@ticlabeloffset) node {\dtl@thislabel};
+ \fi
+% \end{macrocode}
+% Draw opposite tick, if box setting is on.
+% \begin{macrocode}
+ \ifDTLbox
+ \ifDTLxticsin
+ \draw (\dtl@thistick,\DTLmaxY) -- ++(0,-\dtl@ticklength);
+ \else
+ \draw (\dtl@thistick,\DTLmaxY) -- ++(0,\dtl@ticklength);
+ \fi
+ \fi
+ }%
+ \fi
+% \end{macrocode}
+% Plot $x$ label if required.
+% \begin{macrocode}
+ \ifx\dtl@xlabel\relax
+ \else
+% \end{macrocode}
+% Get baseline in terms of canvas co-ordinates
+% \begin{macrocode}
+ \dtladd{\dtl@x}{\number\baselineskip}{\dtl@offset@y}%
+ \dtldiv{\dtl@x}{\dtl@x}{\dtl@scale@y}%
+ \dtldiv{\dtl@x}{\dtl@x}{65536}%
+ \dtladd{\dtl@ticlabeloffset}{\dtl@ticlabeloffset}{\dtl@x}%
+% \end{macrocode}
+% Get halfway position
+% \begin{macrocode}
+ \dtlmul{\dtl@x}{\dtl@dx}{0.5}%
+ \draw (\DTLminX,\DTLminY) ++(\dtl@x,-\dtl@ticlabeloffset)
+ node[anchor=north] {\dtl@xlabel};
+ \fi
+% \end{macrocode}
+% Plot the $x$ minor ticks if required
+% \begin{macrocode}
+ \ifDTLxminortics
+% \end{macrocode}
+% Get tick length in terms of canvas co-ordinates
+% \begin{macrocode}
+ \dtlsub{\dtl@ticklength}{\number\DTLminorticklength}{-\dtl@offset@y}%
+ \dtldiv{\dtl@ticklength}{\dtl@ticklength}{\dtl@scale@y}%
+ \dtldiv{\dtl@ticklength}{\dtl@ticklength}{65536}%
+% \end{macrocode}
+% Iterate through minor ticks.
+% \begin{macrocode}
+ \@for\dtl@thistick:=\dtl@xminorticlist\do{%
+ \ifDTLxticsin
+ \draw (\dtl@thistick,\DTLminY) -- ++(0,\dtl@ticklength);
+ \draw (\dtl@thistick,\DTLminY)
+ ++ (0,-\dtl@ticlabeloffset) node[anchor=north] {\dtl@thislabel};
+ \else
+ \draw (\dtl@thistick,\DTLminY) -- ++(0,-\dtl@ticklength)
+ ++ (0,-\dtl@ticlabeloffset) node[anchor=north] {\dtl@thislabel};
+ \fi
+% \end{macrocode}
+% Draw opposite tick, if box setting is on.
+% \begin{macrocode}
+ \ifDTLbox
+ \ifDTLxticsin
+ \draw (\dtl@thistick,\DTLmaxY) -- ++(0,-\dtl@ticklength);
+ \else
+ \draw (\dtl@thistick,\DTLmaxY) -- ++(0,\dtl@ticklength);
+ \fi
+ \fi
+ }%
+ \fi
+% \end{macrocode}
+% Plot $y$ tics if required.
+% \begin{macrocode}
+ \ifDTLytics
+% \end{macrocode}
+% Get tick length in terms of canvas co-ordinates
+% \begin{macrocode}
+ \dtlsub{\dtl@ticklength}{\number\DTLticklength}{-\dtl@offset@x}%
+ \dtldiv{\dtl@ticklength}{\dtl@ticklength}{\dtl@scale@x}%
+ \dtldiv{\dtl@ticklength}{\dtl@ticklength}{65536}%
+% \end{macrocode}
+% Get tick label offset in terms of canvas co-ordinates
+% \begin{macrocode}
+ \dtladd{\dtl@ticlabeloffset}{\number\DTLticklabeloffset}{0}%
+ \dtlsub{\dtl@ticlabeloffset}{\number\DTLticklabeloffset}{-\dtl@offset@x}%
+ \dtldiv{\dtl@ticlabeloffset}{\dtl@ticlabeloffset}{\dtl@scale@x}%
+ \dtldiv{\dtl@ticlabeloffset}{\dtl@ticlabeloffset}{65536}%
+% \end{macrocode}
+% Iterate through tick list.
+% \begin{macrocode}
+ \@for\dtl@thistick:=\dtl@yticlist\do{%
+% \end{macrocode}
+% Store tick label in \cs{dtl@thislabel}
+% \begin{macrocode}
+ \let\dtl@thisticklabel\dtl@thistick
+ \ifx\dtl@yticlabels\relax
+ \dtlround{\dtl@thislabel}{\dtl@thistick}
+ {\c@DTLplotroundXvar}%
+ \else
+ \dtl@chopfirst\dtl@yticlabels\dtl@thislabel\dtl@rest
+ \let\dtl@yticlabels=\dtl@rest
+ \fi
+% \end{macrocode}
+% Draw tick.
+% \begin{macrocode}
+ \ifDTLyticsin
+ \draw (\DTLminX,\dtl@thistick) -- ++(\dtl@ticklength,0);
+ \draw (\DTLminX,\dtl@thistick)
+ ++ (-\dtl@ticlabeloffset,0) node[anchor=east] {\dtl@thislabel};
+ \else
+ \draw (\DTLminX,\dtl@thistick) -- ++(-\dtl@ticklength,0)
+ ++ (-\dtl@ticlabeloffset,0) node[anchor=east] {\dtl@thislabel};
+ \fi
+% \end{macrocode}
+% Draw opposite tick, if box setting is on.
+% \begin{macrocode}
+ \ifDTLbox
+ \ifDTLyticsin
+ \draw (\DTLmaxX,\dtl@thistick) -- ++(-\dtl@ticklength,0);
+ \else
+ \draw (\DTLmaxX,\dtl@thistick) -- ++(\dtl@ticklength,0);
+ \fi
+ \fi
+ }%
+ \fi
+% \end{macrocode}
+% Plot $y$ label if required.
+% \begin{macrocode}
+ \ifx\dtl@ylabel\relax
+ \else
+ \setlength{\dtl@tmplength}{\baselineskip}%
+ \addtolength{\dtl@tmplength}{\dtl@yticlabelwidth}%
+ \addtolength{\dtl@tmplength}{\DTLticklabeloffset}%
+ \dtlsub{\dtl@ticlabeloffset}{\number\dtl@tmplength}{-\dtl@offset@x}%
+ \dtldiv{\dtl@ticlabeloffset}{\dtl@ticlabeloffset}{\dtl@scale@x}%
+ \dtldiv{\dtl@ticlabeloffset}{\dtl@ticlabeloffset}{65536}%
+% \end{macrocode}
+% Get halfway position
+% \begin{macrocode}
+ \dtlmul{\dtl@y}{\dtl@dy}{0.5}%
+ \draw (\DTLminX,\DTLminY) ++(-\dtl@ticlabeloffset,\dtl@y)
+ node[rotate=90,anchor=south] {\dtl@ylabel};
+ \fi
+% \end{macrocode}
+% Plot the $y$ minor ticks if required
+% \begin{macrocode}
+ \ifDTLyminortics
+% \end{macrocode}
+% Get tick length in terms of canvas co-ordinates
+% \begin{macrocode}
+ \dtlsub{\dtl@ticklength}{\number\DTLminorticklength}{-\dtl@offset@x}%
+ \dtldiv{\dtl@ticklength}{\dtl@ticklength}{\dtl@scale@x}%
+ \dtldiv{\dtl@ticklength}{\dtl@ticklength}{65536}%
+% \end{macrocode}
+% Iterate through minor ticks.
+% \begin{macrocode}
+ \@for\dtl@thistick:=\dtl@yminorticlist\do{%
+ \ifDTLyticsin
+ \draw (\DTLminX,\dtl@thistick) -- ++(\dtl@ticklength,0);
+ \else
+ \draw (\DTLminX,\dtl@thistick) -- ++(-\dtl@ticklength,0);
+ \fi
+% \end{macrocode}
+% Draw opposite tick, if box setting is on.
+% \begin{macrocode}
+ \ifDTLbox
+ \ifDTLyticsin
+ \draw (\DTLmaxX,\dtl@thistick) -- ++(-\dtl@ticklength,0);
+ \else
+ \draw (\DTLmaxX,\dtl@thistick) -- ++(\dtl@ticklength,0);
+ \fi
+ \fi
+ }%
+ \fi
+% \end{macrocode}
+% End the transformation scope. (Don't want marker shapes to be
+% scaled or skewed.)
+% \begin{macrocode}
+ \end{scope}
+% \end{macrocode}
+% Iterate through each database
+% \begin{macrocode}
+ \@for\dtl@thisdb:=#2\do{%
+% \end{macrocode}
+% Get the current plot mark colour.
+% \begin{macrocode}
+ \ifx\dtl@plotmarkcolorlist\@empty
+ \let\dtl@plotmarkcolorlist=\DTLplotmarkcolors
+ \fi
+ \dtl@chopfirst\dtl@plotmarkcolorlist\dtl@thisplotmarkcolor
+ \dtl@remainder
+ \let\dtl@plotmarkcolorlist=\dtl@remainder
+% \end{macrocode}
+% Get the current plot mark, and store in \cs{dtl@mark}
+% \begin{macrocode}
+ \ifDTLshowmarkers
+ \ifx\dtl@plotmarklist\@empty
+ \let\dtl@plotmarklist=\DTLplotmarks
+ \fi
+ \dtl@chopfirst\dtl@plotmarklist\dtl@thisplotmark
+ \dtl@remainder
+ \let\dtl@plotmarklist=\dtl@remainder
+ \ifx\dtl@thisplotmark\relax
+ \let\dtl@mark=\relax
+ \else
+ \expandafter\toks@\expandafter{\dtl@thisplotmark}%
+ \ifx\dtl@thisplotmarkcolor\@empty
+ \edef\dtl@mark{\the\toks@}%
+ \else
+ \edef\dtl@mark{%
+ \noexpand\color{\dtl@thisplotmarkcolor}%
+ \the\toks@}%
+ \fi
+ \fi
+ \else
+ \let\dtl@mark=\relax
+ \fi
+% \end{macrocode}
+% Get the current plot line colour.
+% \begin{macrocode}
+ \ifx\dtl@plotlinecolorlist\@empty
+ \let\dtl@plotlinecolorlist=\DTLplotlinecolors
+ \fi
+ \dtl@chopfirst\dtl@plotlinecolorlist\dtl@thisplotlinecolor
+ \dtl@remainder
+ \let\dtl@plotlinecolorlist=\dtl@remainder
+% \end{macrocode}
+% Get the current line style, and store in \cs{dtl@linestyle}
+% \begin{macrocode}
+ \ifDTLshowlines
+ \ifx\dtl@plotlinelist\@empty
+ \let\dtl@plotlinelist=\DTLplotlines
+ \fi
+ \dtl@chopfirst\dtl@plotlinelist\dtl@thisplotline
+ \dtl@remainder
+ \let\dtl@plotlinelist=\dtl@remainder
+ \expandafter\ifx\dtl@thisplotline\relax
+ \let\dtl@linestyle=\relax
+ \else
+ \expandafter\toks@\expandafter{\dtl@thisplotline}%
+ \ifx\dtl@thisplotlinecolor\@empty
+ \edef\dtl@linestyle{\the\toks@}%
+ \else
+ \edef\dtl@linestyle{%
+ \noexpand\color{\dtl@thisplotlinecolor}%
+ \the\toks@}%
+ \fi
+ \fi
+ \else
+ \let\dtl@linestyle=\relax
+ \fi
+% \end{macrocode}
+% Append this plot setting to the legend.
+% \begin{macrocode}
+ \ifnum\dtl@legendsetting>0\relax
+ \dtl@chopfirst\dtl@legendlabels\dtl@thislabel\dtl@rest
+ \let\dtl@legendlabels=\dtl@rest
+ \expandafter\toks@\expandafter{\dtl@mark}%
+ \expandafter\@dtl@toks\expandafter{\dtl@linestyle}%
+ \edef\dtl@addtolegend{\noexpand\DTLaddtoplotlegend
+ {\the\toks@}{\the\@dtl@toks}{\dtl@thislabel}}%
+ \dtl@addtolegend
+ \fi
+% \end{macrocode}
+% Store stream in \cs{dtl@stream}
+% \begin{macrocode}
+ \def\dtl@stream{\pgfplotstreamstart}%
+% \end{macrocode}
+% Only plot points that lie inside bounds.
+%\changes{1.01}{2007 Aug 17}{uses \cs{@sDTLforeach} instead of
+%\cs{DTLforeach}}
+% \begin{macrocode}
+ \@sDTLforeach[#1]{\dtl@thisdb}{\dtl@x=\dtl@xkey,%
+ \dtl@y=\dtl@ykey}{%
+ \DTLconverttodecimal{\dtl@x}{\dtl@decx}%
+ \DTLconverttodecimal{\dtl@y}{\dtl@decy}%
+ \ifthenelse{%
+ \DTLisclosedbetween{\dtl@x}{\DTLminX}{\DTLmaxX}%
+ \and
+ \DTLisclosedbetween{\dtl@y}{\DTLminY}{\DTLmaxY}%
+ }%
+ {%
+ \expandafter\toks@\expandafter{\dtl@stream}%
+% \end{macrocode}
+% Apply transformation to co-ordinates
+% \begin{macrocode}
+ \dtlmul{\dtl@decx}{\dtl@decx}{\dtl@scale@x}%
+ \dtladd{\dtl@decx}{\dtl@decx}{\dtl@offset@x}%
+ \dtlround{\dtl@decx}{\dtl@decx}{1}%
+ \dtlmul{\dtl@decy}{\dtl@decy}{\dtl@scale@y}%
+ \dtladd{\dtl@decy}{\dtl@decy}{\dtl@offset@y}%
+ \dtlround{\dtl@decy}{\dtl@decy}{1}%
+ \edef\dtl@stream{\the\toks@
+ \noexpand\pgfplotstreampoint
+ {\noexpand\pgfpointxy{\dtl@decx}{\dtl@decy}}}%
+ }{}%
+ }%
+ \expandafter\toks@\expandafter{\dtl@stream}%
+ \edef\dtl@stream{\the\toks@\noexpand\pgfplotstreamend}%
+% \end{macrocode}
+% End plot stream and draw path.
+% \begin{macrocode}
+ \ifx\dtl@linestyle\relax
+ \else
+ \begin{scope}
+ \dtl@linestyle
+ \pgfplothandlerlineto
+ \dtl@stream
+ \pgfusepath{stroke}
+ \end{scope}
+ \fi
+ \ifx\dtl@mark\relax
+ \else
+ \begin{scope}
+ \pgfplothandlermark{\dtl@mark}%
+ \dtl@stream
+ \pgfusepath{stroke}
+ \end{scope}
+ \fi
+ }%
+% \end{macrocode}
+% Plot legend if required.
+% \begin{macrocode}
+ \ifcase\dtl@legendsetting
+ % none
+ \or % north
+ \dtlmul{\dtl@decx}{\dtl@dx}{0.5}%
+ \dtladd{\dtl@decx}{\DTLminX}{\dtl@decx}%
+ \dtlmul{\dtl@decx}{\dtl@decx}{\dtl@scale@x}%
+ \dtladd{\dtl@decx}{\dtl@decx}{\dtl@offset@x}%
+ \dtlmul{\dtl@decy}{\DTLmaxY}{\dtl@scale@y}%
+ \dtladd{\dtl@decy}{\dtl@decy}{\dtl@offset@y}%
+ \draw (\dtl@decx,\dtl@decy) ++(0,-\DTLlegendyoffset)
+ node[anchor=north]
+ {\DTLformatlegend
+ {\begin{tabular}{cl}\dtl@legend\end{tabular}}%
+ };
+ \or % north east
+ \dtlmul{\dtl@decx}{\DTLmaxX}{\dtl@scale@x}%
+ \dtladd{\dtl@decx}{\dtl@decx}{\dtl@offset@x}%
+ \dtlmul{\dtl@decy}{\DTLmaxY}{\dtl@scale@y}%
+ \dtladd{\dtl@decy}{\dtl@decy}{\dtl@offset@y}%
+ \draw (\dtl@decx,\dtl@decy) ++(-\DTLlegendxoffset,-\DTLlegendyoffset)
+ node[anchor=north east]
+ {\DTLformatlegend
+ {\begin{tabular}{cl}\dtl@legend\end{tabular}}%
+ };
+ \or % east
+ \dtlmul{\dtl@decy}{\dtl@dy}{0.5}%
+ \dtladd{\dtl@decy}{\DTLminY}{\dtl@decy}%
+ \dtlmul{\dtl@decy}{\dtl@decy}{\dtl@scale@y}%
+ \dtladd{\dtl@decy}{\dtl@decy}{\dtl@offset@y}%
+ \dtlmul{\dtl@decx}{\DTLmaxX}{\dtl@scale@x}%
+ \dtladd{\dtl@decx}{\dtl@decx}{\dtl@offset@x}%
+ \draw (\dtl@decx,\dtl@decy) ++(-\DTLlegendxoffset,0)
+ node[anchor=east]
+ {\DTLformatlegend
+ {\begin{tabular}{cl}\dtl@legend\end{tabular}}%
+ };
+ \or % south east
+ \dtlmul{\dtl@decx}{\DTLmaxX}{\dtl@scale@x}%
+ \dtladd{\dtl@decx}{\dtl@decx}{\dtl@offset@x}%
+ \dtlmul{\dtl@decy}{\DTLminY}{\dtl@scale@y}%
+ \dtladd{\dtl@decy}{\dtl@decy}{\dtl@offset@y}%
+ \draw (\dtl@decx,\dtl@decy) ++(-\DTLlegendxoffset,\DTLlegendyoffset)
+ node[anchor=south east]
+ {\DTLformatlegend
+ {\begin{tabular}{cl}\dtl@legend\end{tabular}}%
+ };
+ \or % south
+ \dtlmul{\dtl@decx}{\dtl@dx}{0.5}%
+ \dtladd{\dtl@decx}{\DTLminX}{\dtl@decx}%
+ \dtlmul{\dtl@decx}{\dtl@decx}{\dtl@scale@x}%
+ \dtladd{\dtl@decx}{\dtl@decx}{\dtl@offset@x}%
+ \dtlmul{\dtl@decy}{\DTLminY}{\dtl@scale@y}%
+ \dtladd{\dtl@decy}{\dtl@decy}{\dtl@offset@y}%
+ \draw (\dtl@decx,\dtl@decy) ++(0,\DTLlegendyoffset)
+ node[anchor=south]
+ {\DTLformatlegend
+ {\begin{tabular}{cl}\dtl@legend\end{tabular}}%
+ };
+ \or % south west
+ \dtlmul{\dtl@decx}{\DTLminX}{\dtl@scale@x}%
+ \dtladd{\dtl@decx}{\dtl@decx}{\dtl@offset@x}%
+ \dtlmul{\dtl@decy}{\DTLminY}{\dtl@scale@y}%
+ \dtladd{\dtl@decy}{\dtl@decy}{\dtl@offset@y}%
+ \draw (\dtl@decx,\dtl@decy) ++(\DTLlegendxoffset,\DTLlegendyoffset)
+ node[anchor=south west]
+ {\DTLformatlegend
+ {\begin{tabular}{cl}\dtl@legend\end{tabular}}%
+ };
+ \or % west
+ \dtlmul{\dtl@decy}{\dtl@dy}{0.5}%
+ \dtladd{\dtl@decy}{\DTLminY}{\dtl@decy}%
+ \dtlmul{\dtl@decy}{\dtl@decy}{\dtl@scale@y}%
+ \dtladd{\dtl@decy}{\dtl@decy}{\dtl@offset@y}%
+ \dtlmul{\dtl@decx}{\DTLminX}{\dtl@scale@x}%
+ \dtladd{\dtl@decx}{\dtl@decx}{\dtl@offset@x}%
+ \draw (\dtl@decx,\dtl@decy) ++(\DTLlegendxoffset,0)
+ node[anchor=west]
+ {\DTLformatlegend
+ {\begin{tabular}{cl}\dtl@legend\end{tabular}}%
+ };
+ \or % north west
+ \dtlmul{\dtl@decx}{\DTLminX}{\dtl@scale@x}%
+ \dtladd{\dtl@decx}{\dtl@decx}{\dtl@offset@x}%
+ \dtlmul{\dtl@decy}{\DTLmaxY}{\dtl@scale@y}%
+ \dtladd{\dtl@decy}{\dtl@decy}{\dtl@offset@y}%
+ \draw (\dtl@decx,\dtl@decy) ++(\DTLlegendxoffset,-\DTLlegendyoffset)
+ node[anchor=north west]
+ {\DTLformatlegend
+ {\begin{tabular}{cl}\dtl@legend\end{tabular}}%
+ };
+ \fi
+% \end{macrocode}
+% Set the transformation matrix, so user can plot things using the
+% data co-ordinate space
+% \begin{macrocode}
+ \pgftransformcm{\dtl@scale@x}{0}{0}{\dtl@scale@y}%
+ {\pgfpoint{\dtl@offset@x pt}{\dtl@offset@y pt}}%
+% \end{macrocode}
+% End hook
+% \begin{macrocode}
+ \let\dtlplothandlermark\@dtlplothandlermark
+ \DTLplotatendtikz
+ \end{tikzpicture}
+ \fi
+ \fi
+\egroup
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@getbounds}
+% Extract bounds:
+%\changes{2.14}{2013-06-28}{changed \cs{FPifgt} to \cs{dtlifnumgt}}
+% \begin{macrocode}
+\def\dtl@getbounds#1,#2,#3,#4\@nil{%
+\def\DTLminX{#1}%
+\def\DTLminY{#2}%
+\def\DTLmaxX{#3}%
+\def\DTLmaxY{#4}%
+\dtlifnumgt{\DTLminX}{\DTLmaxX}
+{%
+ \PackageError{dataplot}{Min X > Max X in bounds #1,#2,#3,#4}{%
+ The bounds must be specified as minX,minY,maxX,maxY}%
+}{}%
+\dtlifnumgt{\DTLminY}{\DTLmaxY}
+{%
+ \PackageError{dataplot}{Min Y > Max Y in bounds #1,#2,#3,#4}{%
+ The bounds must be specified as minX,minY,maxX,maxY}%
+}{}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@constructticklist}
+%\begin{definition}
+%\cs{dtl@constructticklist}\marg{min}\marg{max}\marg{min gap}\marg{list}
+%\end{definition}
+% Constructs a list of tick points between \meta{min} and \meta{max}
+% and store in \meta{list} (a control sequence.)
+%\changes{2.14}{2013-06-28}{replaced \cs{FPsub} with \cs{dtlsub} etc}
+% \begin{macrocode}
+\newcommand*{\dtl@constructticklist}[4]{%
+ \DTLifFPopenbetween{0}{#1}{#2}%
+ {%
+% \end{macrocode}
+% Tick list straddles the origin.
+% \begin{macrocode}
+ \dtlsub{\@dtl@width}{0}{#1}%
+ \dtldiv{\@dtl@neggap}{\@dtl@width}{10}%
+ \dtlifnumlt{\@dtl@neggap}{#3}%
+ {%
+ \edef\@dtl@neggap{#3}%
+ }%
+ {}%
+ \dtldiv{\@dtl@posgap}{#2}{10}%
+ \dtlifnumlt{\@dtl@posgap}{#3}%
+ {%
+ \edef\@dtl@posgap{#3}%
+ }%
+ {}%
+ \dtlmax{\@dtl@gap}{\@dtl@neggap}{\@dtl@posgap}%
+% \end{macrocode}
+% Don't construct a list if minimum gap is greater than plot width
+% \begin{macrocode}
+ \dtlifnumgt{\@dtl@gap}{\@dtl@width}%
+ {}%
+ {%
+ \dtl@constructticklistwithgapz{#1}{#2}{#4}{\@dtl@gap}%
+ }%
+ }%
+ {%
+% \end{macrocode}
+% Tick list doesn't straddle the origin.
+% \begin{macrocode}
+ \dtlsub{\@dtl@width}{#2}{#1}%
+ \dtldiv{\@dtl@gap}{\@dtl@width}{10}%
+ \dtlifnumlt{\@dtl@gap}{#3}%
+ {%
+% \end{macrocode}
+% Don't construct a list if minimum gap is greater than plot width
+% \begin{macrocode}
+ \dtlifnumgt{#3}{\@dtl@width}%
+ {%
+ \def#4{#1,#2}%
+ }%
+ {%
+ \dtl@constructticklistwithgap{#1}{#2}{#4}{#3}%
+ }
+ }%
+ {%
+ \dtl@constructticklistwithgap{#1}{#2}{#4}{\@dtl@gap}%
+ }%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@constructticklistwithgap}
+%\begin{definition}
+%\cs{dtl@constructticklistwithgap}\marg{min}\marg{max}\marg{list}\marg{gap}
+%\end{definition}
+% Constructs a list of tick points between \meta{min} and \meta{max}
+% and store in \meta{list} (a control sequence) using the gap given
+% by \meta{gap} where the gap is given in user co-ordinates.
+%\changes{2.14}{2013-06-28}{replaced \cs{FPadd} with \cs{dtladd}}
+% \begin{macrocode}
+\newcommand*{\dtl@constructticklistwithgap}[4]{%
+\edef\@dtl@thistick{#1}%
+\edef#3{#1}%
+\dtladd{\@dtl@thistick}{\@dtl@thistick}{#4}%
+\whiledo{\DTLisFPopenbetween{\@dtl@thistick}{#1}{#2}}{%
+ \expandafter\toks@\expandafter{\@dtl@thistick}%
+ \edef#3{#3,\the\toks@}%
+ \dtladd{\@dtl@thistick}{\@dtl@thistick}{#4}%
+}%
+\expandafter\toks@\expandafter{#2}%
+\edef#3{#3,\the\toks@}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@constructticklistwithgapz}
+%\begin{definition}
+%\cs{dtl@constructticklistwithgapz}\marg{min}\marg{max}\marg{list}\marg{gap}
+%\end{definition}
+% Constructs a list of tick points between \meta{min} and \meta{max}
+% and store in \meta{list} (a control sequence) using the gap given
+% by \meta{gap} where the tick list straddles zero.
+%\changes{2.14}{2013-06-28}{replaced \cs{FPadd} with \cs{dtladd} etc}
+% \begin{macrocode}
+\newcommand*{\dtl@constructticklistwithgapz}[4]{%
+ \edef\@dtl@thistick{0}%
+ \edef#3{0}%
+ \dtladd{\@dtl@thistick}{\@dtl@thistick}{#4}%
+ \whiledo{\DTLisFPopenbetween{\@dtl@thistick}{0}{#2}}%
+ {%
+ \expandafter\toks@\expandafter{\@dtl@thistick}%
+ \edef#3{#3,\the\toks@}%
+ \dtladd{\@dtl@thistick}{\@dtl@thistick}{#4}%
+ }%
+ \expandafter\toks@\expandafter{#2}%
+ \edef#3{#3,\the\toks@}%
+ \dtlifnumeq{#1}{0}%
+ {}%
+ {%
+ \edef\@dtl@thistick{0}%
+ \dtlsub{\@dtl@thistick}{\@dtl@thistick}{#4}%
+ \whiledo{\DTLisFPopenbetween{\@dtl@thistick}{#1}{0}}%
+ {%
+ \expandafter\toks@\expandafter{\@dtl@thistick}%
+ \edef#3{\the\toks@,#3}%
+ \dtlsub{\@dtl@thistick}{\@dtl@thistick}{#4}%
+ }%
+ \expandafter\toks@\expandafter{#1}%
+ \edef#3{\the\toks@,#3}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@constructminorticklist}
+%\begin{definition}
+%\cs{dtl@constructminorticklist}\marg{min}\marg{max}\marg{scale factor}\marg{list}
+%\end{definition}
+% Constructs a list of minor tick points between \meta{min} and \meta{max}
+% and append to \meta{list} (a control sequence.)
+%\changes{2.14}{2013-06-28}{replaced \cs{FPsub} with \cs{dtlsub} etc}
+% \begin{macrocode}
+\newcommand*{\dtl@constructminorticklist}[4]{%
+ \dtlsub{\@dtl@width}{#2}{#1}%
+ \dtlmul{\@dtl@width}{\@dtl@width}{#3}%
+ \dtldiv{\@dtl@gap}{\@dtl@width}{10}%
+ \setlength\dtl@tmplength{\@dtl@gap sp}%
+ \ifdim\dtl@tmplength<\DTLminminortickgap
+ \dtldiv{\@dtl@gap}{\@dtl@width}{4}%
+ \setlength\dtl@tmplength{\@dtl@gap sp}%
+ \ifdim\dtl@tmplength<\DTLminminortickgap
+ \dtldiv{\@dtl@gap}{\@dtl@width}{2}%
+ \setlength\dtl@tmplength{\@dtl@gap sp}%
+ \ifdim\dtl@tmplength<\DTLminminortickgap
+ \let\@dtl@gap=\@dtl@width
+ \fi
+ \fi
+ \fi
+ \dtldiv{\@dtl@gap}{\@dtl@gap}{#3}%
+ \dtl@constructticklistwithgapex{#1}{#2}{\dtl@tmp}{\@dtl@gap}%
+ \ifx#4\@empty
+ \let#4=\dtl@tmp
+ \else
+ \expandafter\toks@\expandafter{#4}%
+ \edef#4{#4,\dtl@tmp}%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@constructticklistwithgapex}
+%\begin{definition}
+%\cs{dtl@constructticklistwithgapex}\marg{min}\marg{max}\marg{list}\marg{gap}
+%\end{definition}
+% Constructs a list of tick points between \meta{min} and \meta{max}
+% and store in \meta{list} (a control sequence) using the gap given
+% by \meta{gap} where the gap is given in user co-ordinates.
+% The end points are excluded from the list.
+%\changes{2.14}{2013-06-28}{replaced \cs{FPadd} with \cs{dtladd} and
+%changed third argument to minimum gap width (in data co-ordinates)}
+% \begin{macrocode}
+\newcommand*{\dtl@constructticklistwithgapex}[4]{%
+\edef\@dtl@thistick{#1}%
+\let#3=\@empty
+\dtladd{\@dtl@thistick}{\@dtl@thistick}{#4}%
+\whiledo{\DTLisFPopenbetween{\@dtl@thistick}{#1}{#2}}{%
+ \expandafter\toks@\expandafter{\@dtl@thistick}%
+ \ifx#3\@empty
+ \edef#3{\the\toks@}%
+ \else
+ \edef#3{#3,\the\toks@}%
+ \fi
+ \dtladd{\@dtl@thistick}{\@dtl@thistick}{#4}%
+}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLaddtoplotlegend}
+%\begin{definition}
+%\cs{DTLaddtoplotlegend}\marg{marker}\marg{line style}\marg{label}
+%\end{definition}
+% Adds entry to legend.
+%\changes{2.15}{2013-07-10}{Used \cs{xdef} instead of \cs{edef} as
+%may be scoped.}
+% \begin{macrocode}
+\newcommand*{\DTLaddtoplotlegend}[3]{%
+\def\dtl@legendline{}%
+\ifx\relax#2\relax
+\else
+ \toks@{#2%
+ \pgfpathmoveto{\pgfpoint{-10pt}{0pt}}%
+ \pgfpathlineto{\pgfpoint{10pt}{0pt}}%
+ \pgfusepath{stroke}}%
+ \edef\dtl@legendline{\the\toks@}%
+\fi
+\ifx\relax#1\relax
+\else
+ \toks@{#1}%
+ \expandafter\@dtl@toks\expandafter{\dtl@legendline}%
+ \edef\dtl@legendline{\the\@dtl@toks\the\toks@}%
+\fi
+\expandafter\toks@\expandafter{\dtl@legendline}%
+\ifx\dtl@legend\@empty
+ \xdef\dtl@legend{\noexpand\tikz\the\toks@; \noexpand& #3}%
+\else
+ \expandafter\@dtl@toks\expandafter{\dtl@legend}%
+ \xdef\dtl@legend{\the\@dtl@toks\noexpand\\%
+ \noexpand\tikz\the\toks@; \noexpand& #3}%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%\iffalse
+% \begin{macrocode}
+%</dataplot.sty>
+% \end{macrocode}
+%\fi
+%\iffalse
+% \begin{macrocode}
+%<*person.sty>
+% \end{macrocode}
+%\fi
+%\chapter{person.sty}\label{sec:code:person}
+%\section{Package Declaration}
+% Package identification:
+% \begin{macrocode}
+\NeedsTeXFormat{LaTeX2e}
+\ProvidesPackage{person}[2018/12/07 v2.31 (NLCT)]
+% \end{macrocode}
+% Requires the \sty{ifthen} package.
+% \begin{macrocode}
+\RequirePackage{ifthen}
+\RequirePackage{datatool}
+% \end{macrocode}
+%\section{Defining People}
+%\begin{counter}{people}
+% Keep count of the number of people who have been defined:
+% \begin{macrocode}
+\newcounter{people}
+% \end{macrocode}
+%\end{counter}
+%\begin{counter}{person}
+% Temporary counter
+% \begin{macrocode}
+\newcounter{person}
+% \end{macrocode}
+%\end{counter}
+%\begin{macro}{\@people@list}
+% Keep a list of labels for each person who has been defined:
+% \begin{macrocode}
+\newcommand*{\@people@list}{,}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@get@firstperson}
+% Get the first person's name in \cs{@people@list}, and store in
+% the argument (which must be a control sequence.)
+% \begin{macrocode}
+\newcommand*{\@get@firstperson}[1]{%
+ \expandafter\@@get@firstperson\@people@list,\@nil{#1}}
+ \def\@@get@firstperson,#1,#2\@nil#3{%
+ \def#3{#1}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\malelabels}
+% List of labels that can be used to indicate that a person is
+% male (when defining a person using \cs{newperson}).
+% \begin{macrocode}
+\newcommand*{\malelabels}{male,Male,MALE,M,m}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\addmalelabel}
+% Adds a label to the list of male labels.
+% \begin{macrocode}
+\newcommand*{\addmalelabel}[1]{%
+ \expandafter\@dtl@toksA\expandafter{\malelabels}%
+ \expandafter\@dtl@toksB\expandafter{#1}%
+ \edef\malelabels{\the\@dtl@toksA,\the\@dtl@toksB}%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\addfemalelabel}
+% Adds a label to the list of female labels.
+% \begin{macrocode}
+\newcommand*{\addfemalelabel}[1]{%
+ \expandafter\@dtl@toksA\expandafter{\femalelabels}%
+ \expandafter\@dtl@toksB\expandafter{#1}%
+ \edef\femalelabels{\the\@dtl@toksA,\the\@dtl@toksB}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\femalelabels}
+% List of labels that can be used to indicate that a person is
+% female (when defining a person using \cs{newperson}).
+% \begin{macrocode}
+\newcommand*{\femalelabels}{female,Female,FEMALE,F,f}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\ifmalelabel}
+% Determines if first argument is contained in the list of male
+% labels. (One level expansion is performed on the first object
+% in first argument.)
+% If true does second argument, otherwise does third argument.
+% \begin{macrocode}
+\newcommand{\ifmalelabel}[3]{%
+ \expandafter\DTLifinlist\expandafter{#1}{\malelabels}{#2}{#3}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\iffemalelabel}
+% Determines if first argument is contained in the list of female
+% labels. (One level expansion is performed on the first object
+% in first argument.)
+% If true does second argument, otherwise does third argument.
+% \begin{macrocode}
+\newcommand{\iffemalelabel}[3]{%
+ \expandafter\DTLifinlist\expandafter{#1}{\femalelabels}{#2}{#3}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\newperson}
+% Define a new person. The optional argument specifies a label
+% with which to refer to that person. If omitted, \texttt{anon}
+% is used. If more than one person is defined, the optional
+% argument will be required to specify a unique label. The
+% compulsory arguments are the person's full name, their
+% familiar name and their gender.
+% \begin{macrocode}
+\newcommand*{\newperson}[4][anon]{%
+ \@ifundefined{person@#1@name}%
+ {%
+ \ifmalelabel{#4}%
+ {%
+ \expandafter\gdef\csname person@#1@gender\endcsname{male}%
+ }%
+ {%
+ \iffemalelabel{#4}%
+ {%
+ \expandafter\gdef\csname person@#1@gender\endcsname{female}%
+ }%
+ {%
+ \PackageError{person}{Unknown gender `#4' for person
+ `#1'}{Allowed gender labels are: \malelabels\space or
+ \femalelabels}%
+ \@namedef{person@#1@gender}{other}%
+ }%
+ }%
+ \expandafter
+ \protected@xdef\csname person@#1@fullname\endcsname{#2}%
+ \expandafter
+ \protected@xdef\csname person@#1@name\endcsname{#3}%
+ \protected@xdef\@people@list{\@people@list#1,}%
+ \stepcounter{people}%
+ }%
+ {%
+ \PackageError{person}{Person `#1' has already been defined}{}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\section{Remove People}
+%
+%\begin{macro}{\removeperson}
+% Removes person identified by their label from the list.
+% \begin{macrocode}
+\newcommand*{\removeperson}[1][anon]{%
+ \edef\@person@label{#1}%
+ \expandafter\@removeperson\expandafter{\@person@label}%
+}
+% \end{macrocode}
+% The label has to be full expanded for the internal command.
+% \begin{macrocode}
+\newcommand*{\@removeperson}[1]{%
+ \ifpersonexists{#1}%
+ {%
+% \end{macrocode}
+% Remove label from list of people.
+% \begin{macrocode}
+ \def\@remove@person##1,#1,##2\@nil{%
+ \def\@prsn@pre{##1}\def\@prsn@post{##2}}%
+ \expandafter\@remove@person\@people@list\@nil
+ \xdef\@people@list{\@prsn@pre,\@prsn@post}%
+% \end{macrocode}
+% Decrement number of people:
+% \begin{macrocode}
+ \addtocounter{people}{-1}%
+% \end{macrocode}
+% Undefine associated control sequences:
+% \begin{macrocode}
+ \expandafter\global\expandafter
+ \let\csname person@#1@name\endcsname\undefined
+ \expandafter\global\expandafter
+ \let\csname person@#1@fullname\endcsname\undefined
+ \expandafter\global\expandafter
+ \let\csname person@#1@gender\endcsname\undefined
+ }%
+ {%
+ \PackageError{person}{Can't remove person `#1': no such
+ person}{}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\removepeople}
+% Removes the people listed.
+% \begin{macrocode}
+\newcommand*{\removepeople}[1]{%
+ \@for\@thisperson:=#1\do{%
+ \ifx\@thisperson\@empty
+ \else
+ \expandafter\removeperson\expandafter[\@thisperson]%
+ \fi
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\removeallpeople}
+% Removes everyone.
+% \begin{macrocode}
+\newcommand*{\removeallpeople}{%
+ \@for\@thisperson:=\@people@list\do{%
+ \expandafter\global\expandafter
+ \let\csname person@\@thisperson @name\endcsname\undefined
+ \expandafter\global\expandafter
+ \let\csname person@\@thisperson @fullname\endcsname\undefined
+ \expandafter\global\expandafter
+ \let\csname person@\@thisperson @gender\endcsname\undefined
+ }%
+ \setcounter{people}{0}%
+ \gdef\@people@list{,}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\section{Conditionals and Loops}
+%\begin{macro}{\ifpersonexists}
+% If person whose label is given by the first argument exists, then
+% do the second argument otherwise do third argument.
+% \begin{macrocode}
+\newcommand{\ifpersonexists}[3]{%
+ \@ifundefined{person@#1@name}{#3}{#2}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\ifmale}
+% If the person given by the label in the first argument is male,
+% do the second argument, otherwise do the third argument.
+%\changes{2.23}{2015-07-11}{bug fix: replaced \cs{@thisperson} with \#1}
+% \begin{macrocode}
+\newcommand{\ifmale}[3]{%
+ \ifpersonexists{#1}%
+ {%
+ \edef\@gender{\csname person@#1@gender\endcsname}%
+ \ifx\@gender\@male@label
+ #2%
+ \else
+ #3%
+ \fi
+ }%
+ {%
+ \PackageError{person}{Person `#1' doesn't exist.}{}%
+ }%
+}
+\def\@male@label{male}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\ifallmale}
+% If all people listed in first argument are male, do the second
+% argument otherwise do the third argument. If the first argument
+% is omitted, all defined people are checked.
+% \begin{macrocode}
+\newcommand{\ifallmale}[3][\@people@list]{%
+ \@for\@thisperson:=#1\do{%
+ \ifpersonexists{\@thisperson}%
+ {%
+ \edef\@gender{\csname person@\@thisperson @gender\endcsname}%
+ \ifx\@gender\@male@label
+ \else
+ \@endfortrue
+ \fi
+ }%
+ {%
+ \PackageError{person}{Person `#1' doesn't exist.}{}%
+ }%
+ }%
+ \if@endfor
+ #3%
+ \else
+ #2%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\iffemale}
+% If the person given by the label in the first argument is female,
+% do the second argument, otherwise do the third argument.
+%\changes{2.23}{2015-07-11}{bug fix: replaced \cs{@thisperson} with \#1}
+% \begin{macrocode}
+\newcommand{\iffemale}[3]{%
+ \ifpersonexists{#1}%
+ {%
+ \edef\@gender{\csname person@#1@gender\endcsname}%
+ \ifx\@gender\@female@label
+ #2%
+ \else
+ #3%
+ \fi
+ }%
+ {%
+ \PackageError{person}{Person `#1' doesn't exist.}{}%
+ }%
+}
+\def\@female@label{female}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\ifallfemale}
+% If all people listed in first argument are female, do the second
+% argument otherwise do the third argument.
+% \begin{macrocode}
+\newcommand{\ifallfemale}[3][\@people@list]{%
+ \@for\@thisperson:=#1\do{%
+ \edef\@gender{\csname person@\@thisperson @gender\endcsname}%
+ \ifx\@gender\@female@label
+ \else
+ \@endfortrue
+ \fi
+ }%
+ \if@endfor
+ #3%
+ \else
+ #2%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\foreachperson}
+%\begin{definition}
+%\cs{foreachperson}(\meta{name cs},\meta{full name cs},\meta{gender cs},\meta{label cs})\cs{in}\marg{list}\cs{do}\marg{body}
+%\end{definition}
+% Iterates through list of people the \cs{in}\marg{list} is optional.
+% If omitted, the list of all defined people is used.
+% \begin{macrocode}
+\def\foreachperson(#1,#2,#3,#4)#5{%
+ \ifx#5\in
+ \def\@do@foreachperson{\@foreachperson(#1,#2,#3,#4)#5}%
+ \else
+ \def\@do@foreachperson{%
+ \@foreachperson(#1,#2,#3,#4)\in\@people@list#5}%
+ \fi
+ \@do@foreachperson
+}
+\long\def\@foreachperson(#1,#2,#3,#4)\in#5\do#6{%
+ \@for#4:=#5\do{%
+ \ifx#4\@empty
+ \else
+ \ifpersonexists{#4}%
+ {%
+ \expandafter
+ \let\expandafter#1\csname person@#4@name\endcsname
+ \expandafter
+ \let\expandafter#2\csname person@#4@fullname\endcsname
+ \expandafter
+ \let\expandafter#3\csname person@#4@gender\endcsname
+ \ifx#3\@male@label
+ \let#3\malename
+ \else
+ \ifx#3\@female@label
+ \let#3\femalename
+ \fi
+ \fi
+ #6%
+ }%
+ {%
+ \PackageError{person}{Person `#4' doesn't exist}{}%
+ }%
+ \fi
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\section{Predefined Words}\label{sec:code:peoplenames}
+% These commands should be redefined if
+% you are writing in another language, but note that these
+% are structured according to English grammar.
+%\begin{macro}{\malepronoun}
+% \begin{macrocode}
+\newcommand*{\malepronoun}{he}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\femalepronoun}
+% \begin{macrocode}
+\newcommand*{\femalepronoun}{she}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\pluralpronoun}
+% \begin{macrocode}
+\newcommand*{\pluralpronoun}{they}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\maleobjpronoun}
+% \begin{macrocode}
+\newcommand*{\maleobjpronoun}{him}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\femaleobjpronoun}
+% \begin{macrocode}
+\newcommand*{\femaleobjpronoun}{her}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\pluralobjpronoun}
+% \begin{macrocode}
+\newcommand*{\pluralobjpronoun}{them}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\malepossadj}
+% \begin{macrocode}
+\newcommand*{\malepossadj}{his}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\femalepossadj}
+% \begin{macrocode}
+\newcommand*{\femalepossadj}{her}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\pluralpossadj}
+% \begin{macrocode}
+\newcommand*{\pluralpossadj}{their}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\maleposspronoun}
+% \begin{macrocode}
+\newcommand*{\maleposspronoun}{his}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\femaleposspronoun}
+% \begin{macrocode}
+\newcommand*{\femaleposspronoun}{hers}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\pluralposspronoun}
+% \begin{macrocode}
+\newcommand*{\pluralposspronoun}{theirs}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\malechild}
+% \begin{macrocode}
+\newcommand*{\malechild}{son}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\femalechild}
+% \begin{macrocode}
+\newcommand*{\femalechild}{daughter}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\pluralchild}
+% \begin{macrocode}
+\newcommand*{\pluralchild}{children}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\malechildren}
+% \begin{macrocode}
+\newcommand*{\malechildren}{sons}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\femalechildren}
+% \begin{macrocode}
+\newcommand*{\femalechildren}{daughters}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\maleparent}
+% \begin{macrocode}
+\newcommand*{\maleparent}{father}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\femaleparent}
+% \begin{macrocode}
+\newcommand*{\femaleparent}{mother}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\pluralparent}
+% \begin{macrocode}
+\newcommand*{\pluralparent}{parents}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\malesibling}
+% \begin{macrocode}
+\newcommand*{\malesibling}{brother}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\femalesibling}
+% \begin{macrocode}
+\newcommand*{\femalesibling}{sister}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\pluralsibling}
+% \begin{macrocode}
+\newcommand*{\pluralsibling}{siblings}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\malesiblings}
+% \begin{macrocode}
+\newcommand*{\malesiblings}{brothers}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\femalesiblings}
+% \begin{macrocode}
+\newcommand*{\femalesiblings}{sisters}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\andname}
+% Define \cs{andname} if it hasn't already been defined:
+% \begin{macrocode}
+\providecommand*{\andname}{and}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\malename}
+% \begin{macrocode}
+\newcommand*{\malename}{male}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\femalename}
+% \begin{macrocode}
+\newcommand*{\femalename}{female}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\personsep}
+% Separator to use between people (but not the between the last
+% two).
+% \begin{macrocode}
+\newcommand*{\personsep}{, }
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\personlastsep}
+% Separator to use between last two people.
+% \begin{macrocode}
+\newcommand*{\personlastsep}{\space\andname\space}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\twopeoplesep}
+% Separator to use when list only contains two people.
+% \begin{macrocode}
+\newcommand*{\twopeoplesep}{\space\andname\space}
+% \end{macrocode}
+%\end{macro}
+%
+%\section{Displaying Information}
+%\begin{macro}{\personfullname}
+% The person's full name can be displayed using
+% \cs{personfullname}\oarg{label}, where \meta{label} is the
+% unique label used when defining that person. If \meta{label}
+% is omitted, \texttt{anon} is used.
+% \begin{macrocode}
+\newcommand*{\personfullname}[1][anon]{%
+ \@ifundefined{person@#1@fullname}%
+ {%
+ \PackageError{person}{Person `#1' has not been defined}{}%
+ }%
+ {%
+ \csname person@#1@fullname\endcsname
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\peoplefullname}
+% List all defined people's full names. This iterates through all
+% labels in \cs{@people@list}.
+% \begin{macrocode}
+\newcommand*{\peoplefullname}{%
+ \setcounter{person}{1}%
+ \@for\@thisperson:=\@people@list\do{%
+ \ifthenelse{\equal{\@thisperson}{}}%
+ {}%
+ {%
+ \personfullname[\@thisperson]%
+ \stepcounter{person}%
+ \ifnum\c@people=1\relax
+ \else
+ \ifnum\c@person=\c@people
+ \ifnum\c@people=2\relax
+ \twopeoplesep
+ \else
+ \personlastsep
+ \fi
+ \else
+ \ifnum\c@person<\c@people
+ \personsep
+ \fi
+ \fi
+ \fi
+ }%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\personname}
+% As \cs{personfullname}, but for the person's familiar name.
+% \begin{macrocode}
+\newcommand*{\personname}[1][anon]{%
+ \@ifundefined{person@#1@name}%
+ {%
+ \PackageError{person}{Person `#1' has not been defined}{}%
+ }%
+ {%
+ \csname person@#1@name\endcsname
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\peoplename}
+% List all defined people's familiar names. This iterates through all
+% labels in \cs{@people@list}.
+% \begin{macrocode}
+\newcommand*{\peoplename}{%
+ \setcounter{person}{1}%
+ \@for\@thisperson:=\@people@list\do{%
+ \ifthenelse{\equal{\@thisperson}{}}%
+ {}%
+ {%
+ \personname[\@thisperson]%
+ \stepcounter{person}%
+ \ifnum\c@people=1\relax
+ \else
+ \ifnum\c@person=\c@people
+ \ifnum\c@people=2\relax
+ \twopeoplesep
+ \else
+ \personlastsep
+ \fi
+ \else
+ \ifnum\c@person<\c@people
+ \personsep
+ \fi
+ \fi
+ \fi
+ }%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\personpronoun}
+% Display the pronoun (he/she) according to the person's gender.
+% \begin{macrocode}
+\newcommand*{\personpronoun}[1][anon]{%
+ \@ifundefined{person@#1@gender}%
+ {%
+ \PackageError{person}{Person `#1' has not been defined}{}%
+ }%
+ {%
+ \edef\@gender{\csname person@#1@gender\endcsname}%
+ \csname\@gender pronoun\endcsname
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\Personpronoun}
+% As above, but make the first letter uppercase.
+% \begin{macrocode}
+\newcommand*{\Personpronoun}[1][anon]{%
+ \@ifundefined{person@#1@gender}%
+ {%
+ \PackageError{person}{Person `#1' has not been defined}{}%
+ }%
+ {%
+ \edef\@gender{\csname person@#1@gender\endcsname}%
+ \expandafter\expandafter\expandafter
+ \MakeUppercase\csname\@gender pronoun\endcsname
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\peoplepronoun}
+% If there is more than one person, \cs{peoplepronoun} will use
+% \cs{pluralpronoun}, otherwise it will use \cs{personpronoun}.
+% \begin{macrocode}
+\newcommand*{\peoplepronoun}{%
+ \ifnum\c@people>1\relax
+ \pluralpronoun
+ \else
+ \@get@firstperson{\@thisperson}%
+ \personpronoun[\@thisperson]%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\Peoplepronoun}
+% As above, but first letter in upper case
+% \begin{macrocode}
+\newcommand*{\Peoplepronoun}{%
+ \ifnum\c@people>1\relax
+ \expandafter\MakeUppercase\pluralpronoun
+ \else
+ \@get@firstperson{\@thisperson}%
+ \Personpronoun[\@thisperson]%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\personobjpronoun}
+% Display the objective pronoun (him/her) according to the person's
+% gender.
+% \begin{macrocode}
+\newcommand*{\personobjpronoun}[1][anon]{%
+ \@ifundefined{person@#1@gender}%
+ {%
+ \PackageError{person}{Person `#1' has not been defined}{}%
+ }%
+ {%
+ \edef\@gender{\csname person@#1@gender\endcsname}%
+ \csname\@gender objpronoun\endcsname
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\Personobjpronoun}
+% As above, but make the first letter uppercase.
+% \begin{macrocode}
+\newcommand*{\Personobjpronoun}[1][anon]{%
+ \@ifundefined{person@#1@gender}%
+ {%
+ \PackageError{person}{Person `#1' has not been defined}{}%
+ }%
+ {%
+ \edef\@gender{\csname person@#1@gender\endcsname}%
+ \expandafter\expandafter\expandafter
+ \MakeUppercase\csname\@gender objpronoun\endcsname
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\peopleobjpronoun}
+% If there is more than one person, \cs{peopleobjpronoun} will use
+% \cs{pluralobjpronoun}, otherwise it will use \cs{personobjpronoun}.
+% \begin{macrocode}
+\newcommand*{\peopleobjpronoun}{%
+ \ifnum\c@people>1\relax
+ \pluralobjpronoun
+ \else
+ \@get@firstperson{\@thisperson}%
+ \personobjpronoun[\@thisperson]%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\Peopleobjpronoun}
+% As above, but first letter in upper case
+% \begin{macrocode}
+\newcommand*{\Peopleobjpronoun}{%
+ \ifnum\c@people>1\relax
+ \expandafter\MakeUppercase\pluralobjpronoun
+ \else
+ \@get@firstperson{\@thisperson}%
+ \Personobjpronoun[\@thisperson]%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\personpssadj}
+% Display the possessive adjective (his/her) according to the person's
+% gender.
+% \begin{macrocode}
+\newcommand*{\personpossadj}[1][anon]{%
+ \@ifundefined{person@#1@gender}%
+ {%
+ \PackageError{person}{Person `#1' has not been defined}{}%
+ }%
+ {%
+ \edef\@gender{\csname person@#1@gender\endcsname}%
+ \csname\@gender possadj\endcsname
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\Personpossadj}
+% As above, but make the first letter uppercase.
+% \begin{macrocode}
+\newcommand*{\Personpossadj}[1][anon]{%
+ \@ifundefined{person@#1@gender}%
+ {%
+ \PackageError{person}{Person `#1' has not been defined}{}%
+ }%
+ {%
+ \edef\@gender{\csname person@#1@gender\endcsname}%
+ \expandafter\expandafter\expandafter
+ \MakeUppercase\csname\@gender possadj\endcsname
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\peoplepossadj}
+% If there is more than one person, \cs{peoplepossadj} will use
+% \cs{pluralpossadj}, otherwise it will use \cs{personpossadj}.
+% \begin{macrocode}
+\newcommand*{\peoplepossadj}{%
+ \ifnum\c@people>1\relax
+ \pluralpossadj
+ \else
+ \@get@firstperson{\@thisperson}%
+ \personpossadj[\@thisperson]%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\Peoplepossadj}
+% As above, but first letter in upper case
+% \begin{macrocode}
+\newcommand*{\Peoplepossadj}{%
+ \ifnum\c@people>1\relax
+ \expandafter\MakeUppercase\pluralpossadj
+ \else
+ \@get@firstperson{\@thisperson}%
+ \Personpossadj[\@thisperson]%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\personposspronoun}
+% Display possessive pronoun (his/hers) according to the
+% person's gender.
+% \begin{macrocode}
+\newcommand*{\personposspronoun}[1][anon]{%
+ \@ifundefined{person@#1@gender}%
+ {%
+ \PackageError{person}{Person `#1' has not been defined}{}%
+ }%
+ {%
+ \edef\@gender{\csname person@#1@gender\endcsname}%
+ \csname\@gender posspronoun\endcsname
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\Personposspronoun}
+% As above, but make the first letter uppercase.
+% \begin{macrocode}
+\newcommand*{\Personposspronoun}[1][anon]{%
+ \@ifundefined{person@#1@gender}%
+ {%
+ \PackageError{person}{Person `#1' has not been defined}{}%
+ }%
+ {%
+ \edef\@gender{\csname person@#1@gender\endcsname}%
+ \expandafter\expandafter\expandafter
+ \MakeUppercase\csname\@gender posspronoun\endcsname
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\peopleposspronoun}
+% If there is more than one person, \cs{peopleposspronoun} will use
+% \cs{pluralposspronoun}, otherwise it will use \cs{personposspronoun}.
+% \begin{macrocode}
+\newcommand*{\peopleposspronoun}{%
+ \ifnum\c@people>1\relax
+ \pluralposspronoun
+ \else
+ \@get@firstperson{\@thisperson}%
+ \personposspronoun[\@thisperson]%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\Peopleposspronoun}
+% As above, but first letter in upper case
+% \begin{macrocode}
+\newcommand*{\Peopleposspronoun}{%
+ \ifnum\c@people>1\relax
+ \expandafter\MakeUppercase\pluralposspronoun
+ \else
+ \@get@firstperson{\@thisperson}%
+ \Personposspronoun[\@thisperson]%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\personchild}
+% Display this person's relationship to their parent (i.e.\ son
+% or daughter).
+% \begin{macrocode}
+\newcommand*{\personchild}[1][anon]{%
+ \@ifundefined{person@#1@gender}%
+ {%
+ \PackageError{person}{Person `#1' has not been defined}{}%
+ }%
+ {%
+ \edef\@gender{\csname person@#1@gender\endcsname}%
+ \csname\@gender child\endcsname
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\Personchild}
+% As above, but make first letter uppercase.
+% \begin{macrocode}
+\newcommand*{\Personchild}[1][anon]{%
+ \@ifundefined{person@#1@gender}%
+ {%
+ \PackageError{person}{Person `#1' has not been defined}{}%
+ }%
+ {%
+ \edef\@gender{\csname person@#1@gender\endcsname}%
+ \expandafter\expandafter\expandafter\MakeUppercase
+ \csname\@gender child\endcsname
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\peoplechild}
+% If there is more than one person, \cs{peoplechild} will use
+% \cs{malechildren} (if all male), \cs{femalechildren} (if all
+% female) or \cs{pluralchild} (if mixed), otherwise it will use
+% \cs{personchild}.
+% \begin{macrocode}
+\newcommand*{\peoplechild}{%
+ \ifnum\c@people>1\relax
+ \ifallmale
+ {\malechildren}%
+ {\ifallfemale{\femalechildren}{\pluralchild}}%
+ \else
+ \@get@firstperson{\@thisperson}%
+ \personchild[\@thisperson]%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\Peoplechild}
+% As above but first letter is made uppercase.
+% \begin{macrocode}
+\newcommand*{\Peoplechild}{%
+ \ifnum\c@people>1\relax
+ \ifallmale
+ {\expandafter\MakeUppercase\malechildren}%
+ {\ifallfemale
+ {\expandafter\MakeUppercase\femalechildren}
+ {\expandafter\MakeUppercase\pluralchild}}%
+ \else
+ \@get@firstperson{\@thisperson}%
+ \Personchild[\@thisperson]%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\personparent}
+% Display this person's relationship to their child (i.e.\ father
+% or mother).
+% \begin{macrocode}
+\newcommand*{\personparent}[1][anon]{%
+ \@ifundefined{person@#1@gender}%
+ {%
+ \PackageError{person}{Person `#1' has not been defined}{}%
+ }%
+ {%
+ \edef\@gender{\csname person@#1@gender\endcsname}%
+ \csname\@gender parent\endcsname
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\Personparent}
+% As above, but make the first letter uppercase.
+% \begin{macrocode}
+\newcommand*{\Personparent}[1][anon]{%
+ \@ifundefined{person@#1@gender}%
+ {%
+ \PackageError{person}{Person `#1' has not been defined}{}%
+ }%
+ {%
+ \edef\@gender{\csname person@#1@gender\endcsname}%
+ \expandafter\expandafter\expandafter\MakeUppercase
+ \csname\@gender parent\endcsname
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\peopleparent}
+% If there is more than one person, \cs{peopleparent} will use
+% \cs{pluralparent}, otherwise it will use \cs{personparent}.
+% \begin{macrocode}
+\newcommand*{\peopleparent}{%
+ \ifnum\c@people>1\relax
+ \pluralparent
+ \else
+ \@get@firstperson{\@thisperson}%
+ \personparent[\@thisperson]%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\Peopleparent}
+% As above, but make first letter uppercase.
+% \begin{macrocode}
+\newcommand*{\Peopleparent}{%
+ \ifnum\c@people>1\relax
+ \expandafter\MakeUppercase\pluralparent
+ \else
+ \@get@firstperson{\@thisperson}%
+ \Personparent[\@thisperson]%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\personsibling}
+% Display this person's relationship to their siblings (i.e.\
+% brother or sister).
+% \begin{macrocode}
+\newcommand*{\personsibling}[1][anon]{%
+ \@ifundefined{person@#1@gender}%
+ {%
+ \PackageError{person}{Person `#1' has not been defined}{}%
+ }%
+ {%
+ \edef\@gender{\csname person@#1@gender\endcsname}%
+ \csname\@gender sibling\endcsname
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\Personsibling}
+% Display this person's relationship to their siblings (i.e.\
+% brother or sister).
+% \begin{macrocode}
+\newcommand*{\Personsibling}[1][anon]{%
+ \@ifundefined{person@#1@gender}%
+ {%
+ \PackageError{person}{Person `#1' has not been defined}{}%
+ }%
+ {%
+ \edef\@gender{\csname person@#1@gender\endcsname}%
+ \expandafter\expandafter\expandafter\MakeUppercase
+ \csname\@gender sibling\endcsname
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\peoplesibling}
+% If there is more than one person, \cs{peoplesibling} will use
+% \cs{malesiblings} (if all male), \cs{femalesiblings} (if all
+% female) or \cs{pluralsibling} (if mixed), otherwise it will use
+% \cs{personsibling}.
+% \begin{macrocode}
+\newcommand*{\peoplesibling}{%
+ \ifnum\c@people>1\relax
+ \ifallmale
+ {\malesiblings}%
+ {\ifallfemale{\femalesiblings}{\pluralsibling}}%
+ \else
+ \@get@firstperson{\@thisperson}%
+ \personsibling[\@thisperson]%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\persongender}
+% Displays the given person's gender (\cs{malename} or
+% \cs{femalename}).
+%\changes{2.23}{2015-07-11}{bug fix: replaced \cs{ifpersonmale} with
+%\cs{ifmale}}
+% \begin{macrocode}
+\newcommand*{\persongender}[1]{%
+ \ifmale{#1}{\malename}{\femalename}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\section{Extracting Information}
+%
+%\begin{macro}{\getpersongender}
+% Gets person's gender and stores in first argument which must be
+% a control sequence.
+%\changes{2.23}{2015-07-11}{bug fix: replaced \cs{ifpersonmale} with
+%\cs{ifmale}}
+% \begin{macrocode}
+\newcommand*{\getpersongender}[2]{%
+ \ifmale{#2}{\let#1\malename}{\let#1\femalename}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\getpersonname}
+% Gets person's name and stores in first argument which must be
+% a control sequence.
+% \begin{macrocode}
+\newcommand*{\getpersonname}[2]{%
+ \ifpersonexists{#2}%
+ {%
+ \expandafter\let\expandafter#1\csname person@#2@name\endcsname
+ }%
+ {%
+ \PackageError{person}{Person `#2' doesn't exist}{}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\getpersonfullname}
+% Gets person's full name and stores in first argument which must be
+% a control sequence.
+% \begin{macrocode}
+\newcommand*{\getpersonfullname}[2]{%
+ \ifpersonexists{#2}%
+ {%
+ \expandafter
+ \let\expandafter#1\csname person@#2@fullname\endcsname
+ }%
+ {%
+ \PackageError{person}{Person `#2' doesn't exist}{}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%\iffalse
+% \begin{macrocode}
+%</person.sty>
+% \end{macrocode}
+%\fi
+%\iffalse
+% \begin{macrocode}
+%<*databib.bst>
+% \end{macrocode}
+%\fi
+%\iffalse
+% \begin{macrocode}
+ENTRY
+ { address
+ author
+ booktitle
+ chapter
+ edition
+ editor
+ howpublished
+ institution
+ journal
+ key
+ month
+ note
+ number
+ organization
+ pages
+ publisher
+ school
+ series
+ title
+ type
+ volume
+ year
+ isbn
+ doi
+ pubmed
+ url
+ abstract
+ file
+ eprints
+ }
+ {}
+ { label }
+
+INTEGERS { output.state before.all mid.sentence after.sentence after.block }
+
+FUNCTION {init.state.consts}
+{ #0 'before.all :=
+ #1 'mid.sentence :=
+ #2 'after.sentence :=
+ #3 'after.block :=
+}
+
+STRINGS { s t }
+
+FUNCTION {output.nonnull}
+{ 's :=
+ output.state before.all =
+ {
+ "%" * write$
+ newline$
+ }
+ { newline$
+ %add.period$ " " * write$
+ }
+ if$
+ % if$
+ % mid.sentence 'output.state :=
+ % }
+ %if$
+ s
+}
+
+FUNCTION {output}
+{ duplicate$ empty$
+ 'pop$
+ 'output.nonnull
+ if$
+}
+
+FUNCTION {output.check}
+{ 't :=
+ duplicate$ empty$
+ { pop$ "empty " t * " in " * cite$ * warning$ }
+ {
+ output.nonnull
+ }
+ if$
+}
+
+FUNCTION {output.bibitem}
+{ "\DTLnewbibrow" write$
+ newline$
+ "\DTLnewbibitem {CiteKey}{" write$
+ cite$ write$
+ "}%" write$
+ newline$
+ ""
+ before.all 'output.state :=
+}
+
+FUNCTION {fin.entry}
+{ "%" *
+ write$
+ newline$
+}
+
+FUNCTION {new.block}
+{ output.state before.all =
+ 'skip$
+ { after.block 'output.state := }
+ if$
+}
+
+FUNCTION {new.sentence}
+{ output.state after.block =
+ 'skip$
+ { output.state before.all =
+'skip$
+{ after.sentence 'output.state := }
+ if$
+ }
+ if$
+}
+
+FUNCTION {not}
+{ { #0 }
+ { #1 }
+ if$
+}
+
+FUNCTION {and}
+{ 'skip$
+ { pop$ #0 }
+ if$
+}
+
+FUNCTION {or}
+{ { pop$ #1 }
+ 'skip$
+ if$
+}
+
+FUNCTION {new.block.checka}
+{ empty$
+ 'skip$
+ 'new.block
+ if$
+}
+
+FUNCTION {new.block.checkb}
+{ empty$
+ swap$ empty$
+ and
+ 'skip$
+ 'new.block
+ if$
+}
+
+FUNCTION {new.sentence.checka}
+{ empty$
+ 'skip$
+ 'new.sentence
+ if$
+}
+
+FUNCTION {new.sentence.checkb}
+{ empty$
+ swap$ empty$
+ and
+ 'skip$
+ 'new.sentence
+ if$
+}
+
+FUNCTION {field.or.null}
+{ duplicate$ empty$
+ { pop$ "" }
+ 'skip$
+ if$
+}
+
+FUNCTION {emphasize}
+{ duplicate$ empty$
+ { pop$ "" }
+ { "{\em " swap$ * "}" * }
+ if$
+}
+
+FUNCTION {group}
+{ duplicate$ empty$
+ { pop$ "" }
+ { "{" swap$ * "}" * }
+ if$
+}
+
+INTEGERS { nameptr namesleft numnames }
+
+FUNCTION {format.names}
+{
+ 's :=
+ #1 'nameptr :=
+ s num.names$ 'numnames :=
+ numnames 'namesleft :=
+ { namesleft #0 > }
+ {
+ %s nameptr "{vv,}{ll,}{jj,}{ff}" format.name$ 't :=
+ "{" *
+ s nameptr "{vv}" format.name$ 't :=
+ t * "}" *
+ "{" *
+ s nameptr "{ll}" format.name$ 't :=
+ t * "}{" *
+ s nameptr "{jj}" format.name$ 't :=
+ t * "}" *
+ "{" *
+ s nameptr "{ff}" format.name$ 't :=
+ t * "}" *
+ s nameptr "" format.name$ 't :=
+ namesleft #1 >
+ { "," * }
+ { }
+ if$
+ nameptr #1 >
+{
+ t *
+}
+'t
+ if$
+ nameptr #1 + 'nameptr :=
+ namesleft #1 - 'namesleft :=
+ }
+ while$
+ "}" *
+}
+
+FUNCTION {format.authors}
+{
+ author empty$
+ { "" }
+ { author
+ "\DTLnewbibitem {Author}{" write$
+ format.names }
+ if$
+}
+
+FUNCTION {format.editors}
+{ editor empty$
+ { "" }
+ { editor
+ "\DTLnewbibitem {Editor}{" write$
+ format.names
+ }
+ if$
+}
+
+FUNCTION {format.title}
+{ title empty$
+ { "" }
+ {
+ "\DTLnewbibitem {Title}"
+ title "t" change.case$ group *
+ }
+ if$
+}
+
+FUNCTION {format.howpublished}
+{ howpublished empty$
+ { "" }
+ {
+ howpublished
+ "\DTLnewbibitem {HowPublished}" swap$ group *
+ }
+ if$
+}
+
+FUNCTION {format.organization}
+{ organization empty$
+ { "" }
+ {
+ organization
+ "\DTLnewbibitem {Organization}" swap$ group *
+ }
+ if$
+}
+
+FUNCTION {format.institution}
+{ institution empty$
+ { "" }
+ {
+ institution
+ "\DTLnewbibitem {Institution}" swap$ group *
+ }
+ if$
+}
+
+FUNCTION {format.key}
+{ key empty$
+ { "" }
+ {
+ key
+ "\DTLnewbibitem {Key}" swap$ group *
+ }
+ if$
+}
+
+FUNCTION {format.note}
+{ note empty$
+ { "" }
+ {
+ note
+ "\DTLnewbibitem {Note}" swap$ group *
+ }
+ if$
+}
+
+FUNCTION {format.isbn}
+{ isbn empty$
+ { "" }
+ {
+ isbn
+ "\DTLnewbibitem {ISBN}" swap$ group *
+ }
+ if$
+}
+
+FUNCTION {format.doi}
+{ doi empty$
+ { "" }
+ {
+ doi
+ "\DTLnewbibitem {DOI}" swap$ group *
+ }
+ if$
+}
+
+FUNCTION {format.pubmed}
+{ pubmed empty$
+ { "" }
+ {
+ pubmed
+ "\DTLnewbibitem {PubMed}" swap$ group *
+ }
+ if$
+}
+
+FUNCTION {format.abstract}
+{ abstract empty$
+ { "" }
+ {
+ abstract
+ "\DTLnewbibitem {Abstract}" swap$ group *
+ }
+ if$
+}
+
+FUNCTION {format.url}
+{ url empty$
+ { "" }
+ {
+ url
+ "\DTLnewbibitem {Url}" swap$ group *
+ }
+ if$
+}
+
+FUNCTION {format.file}
+{ file empty$
+ { "" }
+ {
+ file
+ "\DTLnewbibitem {File}" swap$ group *
+ }
+ if$
+}
+
+FUNCTION {format.eprints}
+{ eprints empty$
+ { "" }
+ {
+ eprints
+ "\DTLnewbibitem {Eprints}" swap$ group *
+ }
+ if$
+}
+
+FUNCTION {format.address}
+{ address empty$
+ { "" }
+ {
+ address
+ "\DTLnewbibitem {Address}" swap$ group *
+ }
+ if$
+}
+
+FUNCTION {format.school}
+{ school empty$
+ { "" }
+ {
+ school
+ "\DTLnewbibitem {School}" swap$ group *
+ }
+ if$
+}
+
+FUNCTION {format.publisher}
+{ publisher empty$
+ { "" }
+ {
+ publisher
+ "\DTLnewbibitem {Publisher}" swap$ group *
+ }
+ if$
+}
+
+FUNCTION {n.dashify}
+{ 't :=
+ ""
+ { t empty$ not }
+ { t #1 #1 substring$ "-" =
+{ t #1 #2 substring$ "--" = not
+ { "--" *
+ t #2 global.max$ substring$ 't :=
+ }
+ { { t #1 #1 substring$ "-" = }
+{ "-" *
+ t #2 global.max$ substring$ 't :=
+}
+ while$
+ }
+ if$
+}
+{ t #1 #1 substring$ *
+ t #2 global.max$ substring$ 't :=
+}
+ if$
+ }
+ while$
+}
+
+FUNCTION {format.date}
+{ year empty$
+ { month empty$
+{ "" }
+{ "there's a month but no year in " cite$ * warning$
+ "\DTLnewbibitem {Month}" *
+ month group
+}
+ if$
+ }
+ { month empty$
+{ }
+{ "\DTLnewbibitem {Month}{" * month * "}" * }
+ if$
+ "\DTLnewbibitem {Year}{" * year * "}"
+ }
+ if$
+}
+
+FUNCTION {format.btitle}
+{ title
+ "\DTLnewbibitem {Title}{" swap$ *
+ "}" *
+}
+
+FUNCTION {tie.or.space.connect}
+{ duplicate$ text.length$ #3 <
+ { "~" }
+ { " " }
+ if$
+ swap$ * *
+}
+
+FUNCTION {either.or.check}
+{ empty$
+ 'pop$
+ { "can't use both " swap$ * " fields in " * cite$ * warning$ }
+ if$
+}
+
+FUNCTION {format.bvolume}
+{ volume empty$
+ { "" }
+ {
+ "\DTLnewbibitem {Volume}{" volume * "}" *
+ series empty$
+'skip$
+{
+ "\DTLnewbibitem {Series}" * series group *
+ }
+ if$
+ "volume and number" number either.or.check
+ }
+ if$
+}
+
+FUNCTION {format.number.series}
+{ volume empty$
+ { number empty$
+{
+ %series field.or.null group
+ series empty$
+ { "" }
+ { "\DTLnewbibitem {Series}" * series group }
+ if$
+ }
+{
+ "\DTLnewbibitem {Number}" number group *
+ series empty$
+ { "there's a number but no series in " cite$ * warning$ }
+ { "\DTLnewbibitem {Series}{" * series * "}" * }
+ if$
+}
+ if$
+ }
+ { "" }
+ if$
+}
+
+FUNCTION {format.edition}
+{ edition empty$
+ { "" }
+ {
+ "\DTLnewbibitem {Edition}"
+ edition "l" change.case$ group *
+ }
+ if$
+}
+
+INTEGERS { multiresult }
+
+FUNCTION {multi.page.check}
+{ 't :=
+ #0 'multiresult :=
+ { multiresult not
+ t empty$ not
+ and
+ }
+ { t #1 #1 substring$
+ duplicate$ "-" =
+ swap$ duplicate$ "," =
+ swap$ "+" =
+ or or
+{ #1 'multiresult := }
+{ t #2 global.max$ substring$ 't := }
+ if$
+ }
+ while$
+ multiresult
+}
+
+FUNCTION {format.pages}
+{ pages empty$
+ { "" }
+ { pages multi.page.check
+{ "\DTLnewbibitem {Pages}" pages n.dashify
+ group * }
+{ "\DTLnewbibitem {Pages}" pages
+ group *}
+ if$
+ }
+ if$
+}
+
+FUNCTION {format.vol.num.pages}
+{
+ volume empty$
+ { "" }
+ {
+ "\DTLnewbibitem {Volume}{" volume * "}" *
+ }
+ if$
+ number empty$
+ 'skip$
+ { "\DTLnewbibitem {Number}{" number * "}\relax " * *
+ volume empty$
+{ "there's a number but no volume in " cite$ * warning$ }
+'skip$
+ if$
+ }
+ if$
+ pages empty$
+ 'skip$
+ { duplicate$ empty$
+{ pop$ format.pages }
+{ "\DTLnewbibitem {Pages}" * pages n.dashify group * }
+ if$
+ }
+ if$
+}
+
+FUNCTION {format.chapter.pages}
+{ chapter empty$
+ 'format.pages
+ { type empty$
+{ "\DTLnewbibitem {Type}{chapter}" }
+{ "\DTLnewbibitem {Type}" type "l" change.case$ group *}
+ if$
+ "\DTLnewbibitem {Chapter}{" * chapter * "}" *
+ pages empty$
+'skip$
+{ format.pages * }
+ if$
+ }
+ if$
+}
+
+FUNCTION {format.in.ed.booktitle}
+{ booktitle empty$
+ { "" }
+ {
+ "\DTLnewbibitem {BookTitle}" booktitle group *
+ editor empty$
+ {}
+ {
+ "\DTLnewbibitem {Editor}{" *
+ editor format.names *
+ }
+ if$
+ }
+ if$
+}
+
+FUNCTION {empty.misc.check}
+{ author empty$ title empty$ howpublished empty$
+ month empty$ year empty$ note empty$
+ and and and and and
+ { "all relevant fields are empty in " cite$ * warning$ }
+ 'skip$
+ if$
+}
+
+FUNCTION {format.thesis.type}
+{ type empty$
+ 'skip$
+ { pop$
+ type "t" change.case$
+ "\DTLnewbibitem {Type}" swap$ group *
+ }
+ if$
+}
+
+FUNCTION {format.tr.number}
+{
+ type empty$
+ { "\techreportname " }
+ 'type
+ if$
+ number empty$
+ { "t" change.case$ "\DTLnewbibitem {Type}" swap$ group *}
+ { "\DTLnewbibitem {Type}" swap$ group *
+ "\DTLnewbibitem {Number}" *
+ number group * }
+ if$
+}
+
+FUNCTION {format.article.crossref}
+{ key empty$
+ { journal empty$
+{ "need key or journal for " cite$ * " to crossref " * crossref *
+ warning$
+ ""
+}
+{
+ "\DTLnewbibitem {Journal}" journal group *
+ }
+ if$
+ }
+ {
+ ""
+ }
+ if$
+ "\DTLnewbibitem {CrossRef}{" * crossref * "}" *
+}
+
+FUNCTION {format.crossref.editor}
+{ format.editors
+}
+
+FUNCTION {format.book.crossref}
+{ volume empty$
+ { "empty volume in " cite$ * "'s crossref of " * crossref * warning$
+ }
+ {
+ "\DTLnewbibitem {Volume}"
+ volume group *
+ }
+ if$
+ editor empty$
+ editor field.or.null author field.or.null =
+ or
+ { key empty$
+{ series empty$
+ { "need editor, key, or series for " cite$ * " to crossref " *
+ crossref * warning$
+ "" *
+ }
+ {
+ "\DTLnewbibitem {Series}{" * series *
+ "}" *
+ }
+ if$
+}
+{ ""
+ }
+ if$
+ }
+ {
+ format.crossref.editor *
+ }
+ if$
+ "\DTLnewbibitem {CrossRef}{" * crossref * "}" *
+}
+
+FUNCTION {format.incoll.inproc.crossref}
+{ editor empty$
+ editor field.or.null author field.or.null =
+ or
+ { key empty$
+{ booktitle empty$
+ { "need editor, key, or booktitle for " cite$ * " to crossref " *
+ crossref * warning$
+ ""
+ }
+ { "\DTLnewbibitem {BookTitle}{" booktitle * "}" * }
+ if$
+}
+{ "" }
+ if$
+ }
+ {
+ "\DTLnewbibitem {Editor}{" *
+ editor format.names
+ }
+ if$
+ "\DTLnewbibitem {CrossRef}{" * crossref * "}" *
+}
+
+FUNCTION {article}
+{ output.bibitem
+ "\DTLnewbibitem {EntryType}{article}%" write$
+ newline$
+ format.authors "author"
+ output.check
+ format.title "title" output.check
+ new.block
+ crossref missing$
+ {
+ journal missing$
+ {
+ }
+ {
+ "\DTLnewbibitem {Journal}" *
+ }
+ if$
+ journal group "journal" output.check
+ format.vol.num.pages output
+ format.date "year" output.check
+ }
+ { format.article.crossref output.nonnull
+ format.pages output
+ }
+ if$
+ new.block
+ format.key output
+ format.note output
+ format.isbn output
+ format.doi output
+ format.pubmed output
+ format.url output
+ format.abstract output
+ format.file output
+ fin.entry
+}
+
+FUNCTION {book}
+{ output.bibitem
+ "\DTLnewbibitem {EntryType}{book}%" write$
+ newline$
+ author empty$
+ { format.editors "author and editor" output.check }
+ { format.authors output.nonnull
+ crossref missing$
+{ "author and editor" editor either.or.check
+ }
+'skip$
+ if$
+ }
+ if$
+ new.block
+ format.btitle "title" output.check
+ crossref missing$
+ { format.bvolume output
+ new.block
+ format.number.series output
+ %new.sentence
+ format.publisher "publisher" output.check
+ format.address output
+ }
+ { new.block
+ format.book.crossref output.nonnull
+ }
+ if$
+ format.edition output
+ format.date "year" output.check
+ new.block
+ format.key output
+ format.note output
+ format.isbn output
+ format.doi output
+ format.pubmed output
+ format.url output
+ format.abstract output
+ format.file output
+ fin.entry
+}
+
+FUNCTION {booklet}
+{ output.bibitem
+ "\DTLnewbibitem {EntryType}{booklet}%" write$
+ newline$
+ format.authors output
+ new.block
+ format.title "title" output.check
+ howpublished address new.block.checkb
+ format.howpublished output
+ format.address output
+ format.date output
+ new.block
+ format.key output
+ format.note output
+ format.isbn output
+ format.doi output
+ format.pubmed output
+ format.url output
+ format.abstract output
+ format.file output
+ fin.entry
+}
+
+FUNCTION {inbook}
+{ output.bibitem
+ "\DTLnewbibitem {EntryType}{inbook}%" write$
+ newline$
+ author empty$
+ { format.editors "author and editor" output.check }
+ { format.authors output.nonnull
+ crossref missing$
+{ "author and editor" editor either.or.check }
+'skip$
+ if$
+ }
+ if$
+ new.block
+ format.btitle "title" output.check
+ crossref missing$
+ { format.bvolume output
+ format.chapter.pages "chapter and pages" output.check
+ new.block
+ format.number.series output
+ new.sentence
+ format.publisher "publisher" output.check
+ format.address output
+ }
+ { format.chapter.pages "chapter and pages" output.check
+ new.block
+ format.book.crossref output.nonnull
+ }
+ if$
+ format.edition output
+ format.date "year" output.check
+ new.block
+ format.key output
+ format.note output
+ format.isbn output
+ format.doi output
+ format.pubmed output
+ format.url output
+ format.abstract output
+ format.file output
+ fin.entry
+}
+
+FUNCTION {incollection}
+{ output.bibitem
+ "\DTLnewbibitem {EntryType}{incollection}%" write$
+ newline$
+ format.authors "author" output.check
+ format.title "title" output.check
+ crossref missing$
+ { format.in.ed.booktitle "booktitle" output.check
+ format.bvolume output
+ format.number.series output
+ format.chapter.pages output
+ new.sentence
+ format.publisher "publisher" output.check
+ format.address output
+ format.edition output
+ format.date "year" output.check
+ }
+ { format.incoll.inproc.crossref output.nonnull
+ format.chapter.pages output
+ }
+ if$
+ format.key output
+ format.note output
+ format.isbn output
+ format.doi output
+ format.pubmed output
+ format.url output
+ format.abstract output
+ format.file output
+ fin.entry
+}
+
+FUNCTION {inproceedings}
+{ output.bibitem
+ "\DTLnewbibitem {EntryType}{inproceedings}%" write$
+ newline$
+ format.authors "author" output.check
+ format.title "title" output.check
+ crossref missing$
+ { format.in.ed.booktitle "booktitle" output.check
+ format.bvolume output
+ format.number.series output
+ format.pages output
+ address empty$
+{ %organization publisher new.sentence.checkb
+ format.organization write$
+ format.publisher output
+}
+{ format.address write$
+ new.sentence
+ format.organization output
+ format.publisher output
+}
+ if$
+ format.date "year" output.check
+ }
+ {
+ format.incoll.inproc.crossref output.nonnull
+ format.pages output
+ }
+ if$
+ format.key output
+ format.note output
+ format.isbn output
+ format.doi output
+ format.pubmed output
+ format.url output
+ format.abstract output
+ format.file output
+ fin.entry
+}
+
+FUNCTION {conference} { inproceedings }
+
+FUNCTION {manual}
+{ output.bibitem
+ "\DTLnewbibitem {EntryType}{manual}%" write$
+ newline$
+ author empty$
+ { organization empty$
+'skip$
+{ format.organization output
+ format.address output
+}
+ if$
+ }
+ { format.authors output }
+ if$
+ new.block
+ format.btitle "title" output.check
+ author empty$
+ { organization empty$
+{ address new.block.checka
+ address output
+}
+'skip$
+ if$
+ }
+ { %organization address new.block.checkb
+ format.organization output
+ format.address output
+ }
+ if$
+ format.edition output
+ format.date output
+ new.block
+ format.key output
+ format.note output
+ format.isbn output
+ format.doi output
+ format.pubmed output
+ format.url output
+ format.abstract output
+ format.file output
+ fin.entry
+}
+
+FUNCTION {mastersthesis}
+{ output.bibitem
+ "\DTLnewbibitem {EntryType}{mastersthesis}%" write$
+ newline$
+ format.authors "author" output.check
+ new.block
+ format.title "title" output.check
+ new.block
+ "\DTLnewbibitem {Type}{\mscthesisname }"
+ format.thesis.type output.nonnull
+ format.school "school" output.check
+ format.address output
+ format.date "year" output.check
+ new.block
+ format.key output
+ format.note output
+ format.isbn output
+ format.doi output
+ format.pubmed output
+ format.url output
+ format.abstract output
+ format.file output
+ fin.entry
+}
+
+FUNCTION {misc}
+{ output.bibitem
+ "\DTLnewbibitem {EntryType}{misc}%" write$
+ newline$
+ format.authors output
+ title howpublished new.block.checkb
+ format.title output
+ %howpublished new.block.checka
+ format.howpublished output
+ format.date output
+ new.block
+ format.key output
+ format.note output
+ format.isbn output
+ format.doi output
+ format.pubmed output
+ format.url output
+ format.abstract output
+ format.file output
+ fin.entry
+ empty.misc.check
+}
+
+FUNCTION {phdthesis}
+{ output.bibitem
+ "\DTLnewbibitem {EntryType}{phdthesis}%" write$
+ newline$
+ format.authors "author" output.check
+ new.block
+ format.btitle "title" output.check
+ new.block
+ "\DTLnewbibitem {Type}{\phdthesisname }"
+ format.thesis.type output.nonnull
+ format.school "school" output.check
+ format.address output
+ format.date "year" output.check
+ new.block
+ format.key output
+ format.note output
+ format.isbn output
+ format.doi output
+ format.pubmed output
+ format.url output
+ format.abstract output
+ format.file output
+ fin.entry
+}
+
+FUNCTION {proceedings}
+{ output.bibitem
+ "\DTLnewbibitem {EntryType}{proceedings}%" write$
+ newline$
+ editor empty$
+ { format.organization output }
+ { format.editors output.nonnull }
+ if$
+ new.block
+ format.btitle "title" output.check
+ format.bvolume output
+ format.number.series output
+ address empty$
+ { editor empty$
+{ publisher new.sentence.checka }
+{ organization publisher new.sentence.checkb
+ format.organization output
+}
+ if$
+ format.publisher output
+ format.date "year" output.check
+ }
+ { format.address output
+ format.date "year" output.check
+ new.sentence
+ editor empty$
+'skip$
+{ format.organization output }
+ if$
+ format.publisher output
+ }
+ if$
+ new.block
+ format.key output
+ format.note output
+ format.isbn output
+ format.doi output
+ format.pubmed output
+ format.url output
+ format.abstract output
+ format.file output
+ fin.entry
+}
+
+FUNCTION {techreport}
+{ output.bibitem
+ "\DTLnewbibitem {EntryType}{techreport}%" write$
+ newline$
+ format.authors "author" output.check
+ new.block
+ format.title "title" output.check
+ new.block
+ format.tr.number output.nonnull
+ format.institution "institution" output.check
+ format.address output
+ format.date "year" output.check
+ new.block
+ format.key output
+ format.note output
+ format.isbn output
+ format.doi output
+ format.pubmed output
+ format.url output
+ format.abstract output
+ format.file output
+ fin.entry
+}
+
+FUNCTION {unpublished}
+{ output.bibitem
+ "\DTLnewbibitem {EntryType}{unpublished}%" write$
+ newline$
+ format.authors "author" output.check
+ new.block
+ format.title "title" output.check
+ new.block
+ format.key output
+ format.note output
+ format.isbn output
+ format.doi output
+ format.pubmed output
+ format.url output
+ format.abstract output
+ format.file output
+ format.date output
+ fin.entry
+}
+
+FUNCTION {default.type} { misc }
+
+MACRO {jan} {"\DTLmonthname{01}"}
+
+MACRO {feb} {"\DTLmonthname{02}"}
+
+MACRO {mar} {"\DTLmonthname{03}"}
+
+MACRO {apr} {"\DTLmonthname{04}"}
+
+MACRO {may} {"\DTLmonthname{05}"}
+
+MACRO {jun} {"\DTLmonthname{06}"}
+
+MACRO {jul} {"\DTLmonthname{07}"}
+
+MACRO {aug} {"\DTLmonthname{08}"}
+
+MACRO {sep} {"\DTLmonthname{09}"}
+
+MACRO {oct} {"\DTLmonthname{10}"}
+
+MACRO {nov} {"\DTLmonthname{11}"}
+
+MACRO {dec} {"\DTLmonthname{12}"}
+
+MACRO {acmcs} {"\DTLacmcs "}
+
+MACRO {acta} {"\DTLacta "}
+
+MACRO {cacm} {"\DTLcacm "}
+
+MACRO {ibmjrd} {"\DTLibmjrd "}
+
+MACRO {ibmsj} {"\DTLibmsj "}
+
+MACRO {ieeese} {"\DTLieeese "}
+
+MACRO {ieeetc} {"\DTLieeetc "}
+
+MACRO {ieeetcad} {"\DTLieeetcad "}
+
+MACRO {ipl} {"\DTLipl "}
+
+MACRO {jacm} {"\DTLjacm "}
+
+MACRO {jcss} {"\DTLjcss "}
+
+MACRO {scp} {"\DTLscp "}
+
+MACRO {sicomp} {"\DTLsicomp "}
+
+MACRO {tocs} {"\DTLtocs "}
+
+MACRO {tods} {"\DTLtods "}
+
+MACRO {tog} {"\DTLtog "}
+
+MACRO {toms} {"\DTLtoms "}
+
+MACRO {toois} {"\DTLtoois "}
+
+MACRO {toplas} {"\DTLtoplas "}
+
+MACRO {tcs} {"\DTLtcs "}
+
+READ
+
+STRINGS { longest.label }
+
+INTEGERS { number.label longest.label.width }
+
+FUNCTION {initialize.longest.label}
+{ "" 'longest.label :=
+ #1 'number.label :=
+ #0 'longest.label.width :=
+}
+
+FUNCTION {longest.label.pass}
+{ number.label int.to.str$ 'label :=
+ number.label #1 + 'number.label :=
+ label width$ longest.label.width >
+ { label 'longest.label :=
+ label width$ 'longest.label.width :=
+ }
+ 'skip$
+ if$
+}
+
+EXECUTE {initialize.longest.label}
+
+ITERATE {longest.label.pass}
+
+FUNCTION {begin.bib}
+{ preamble$ empty$
+ 'skip$
+ { preamble$ write$ newline$ }
+ if$
+}
+
+EXECUTE {begin.bib}
+
+EXECUTE {init.state.consts}
+
+ITERATE {call.type$}
+
+FUNCTION {end.bib}
+{
+}
+
+EXECUTE {end.bib}
+% \end{macrocode}
+%\fi
+%\iffalse
+% \begin{macrocode}
+%</databib.bst>
+% \end{macrocode}
+%\fi
+%\Finale
+\endinput