summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2007-07-26 18:02:36 +0000
committerKarl Berry <karl@freefriends.org>2007-07-26 18:02:36 +0000
commit8665cea26b952c96c5d217d4d2632424e0ec2996 (patch)
tree7f468a7015a1c0c9345fe8ce87ddfd8b58538cef
parentfbabe9c02ed44f25fc959d8917d915e6ac774181 (diff)
new latex package datatool
git-svn-id: svn://tug.org/texlive/trunk@4655 c570f23f-e606-0410-a88d-b1316a301751
-rwxr-xr-xBuild/tools/tpm-ctan-check3
-rw-r--r--Master/texmf-dist/doc/latex/datatool/README97
-rw-r--r--Master/texmf-dist/doc/latex/datatool/doc/CHANGES1
-rw-r--r--Master/texmf-dist/doc/latex/datatool/doc/datatool.pdfbin0 -> 888470 bytes
-rw-r--r--Master/texmf-dist/doc/latex/datatool/source/datatool.dtx12428
-rw-r--r--Master/texmf-dist/doc/latex/datatool/source/datatool.ins25
-rw-r--r--Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc1
-rw-r--r--Master/tlpkg/tlpsrc/datatool.tlpsrc2
8 files changed, 12556 insertions, 1 deletions
diff --git a/Build/tools/tpm-ctan-check b/Build/tools/tpm-ctan-check
index 74d3167a3a8..8a63062466e 100755
--- a/Build/tools/tpm-ctan-check
+++ b/Build/tools/tpm-ctan-check
@@ -32,7 +32,8 @@ my @WorkingTPM = qw(
crop crossreference csquotes csvtools ctable cursolatex cursor cuisine
currvita curve curve2e curves
custom-bib cyrillic
- dancers dashbox dateiliste datetime dcpic decimal delimtxt digiconfigs
+ dancers dashbox datatool
+ dateiliste datetime dcpic decimal delimtxt digiconfigs
dinat dingbat directory disser dk-bib dlfltxb doi doipubmed dottex
doublestroke dpfloat
draftwatermark dramatist dtxtut dvdcoll dvipsconfig dyntree
diff --git a/Master/texmf-dist/doc/latex/datatool/README b/Master/texmf-dist/doc/latex/datatool/README
new file mode 100644
index 00000000000..34e1b34558a
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/datatool/README
@@ -0,0 +1,97 @@
+LaTeX Bundle : datatool v1.0 (datatool.sty, datapie.sty, dataplot.sty, databar.sty)
+
+Last Modified : 23 July 2007
+
+Author : Nicola Talbot
+
+datatool.sty:
+
+ Databases can be created using LaTeX commands or loaded
+ from external ASCII files, such as comma or tab separated
+ variable files.
+
+ Databases can be sorted numerically or alphabetically
+ (descending or ascending.)
+
+ Repetitive operations can be performed on each row of
+ data in a database (such as mail merging.) Conditions
+ can be imposed to exclude rows.
+
+ Commands are provided to determine if an argument is
+ an integer, a real number, currency or a string.
+ (Scientific notation is currently not supported.)
+
+ Locale dependent number settings are supported
+ (such as a comma as a decimal character and full stop as
+ a number group character.)
+
+ Commands are provided to convert between locale dependent
+ numbers/currency and the standard decimal format required
+ by the fp package enabling fixed point arithmetic to be
+ performed on elements of the database.
+
+ Strings can be tested to determine if they are all upper
+ or all lower case.
+
+ Names can be converted to initials using \DTLinitials.
+
+datapie.sty:
+
+ A database defined by datatool.sty can be converted into a
+ pie chart.
+
+ Segments can be separated from the rest of the chart to make
+ them stand out.
+
+ Colour/grey scale options.
+
+ Predefined segment colours can be changed.
+
+ Hooks provided to annotate chart.
+
+dataplot.sty:
+
+ A database defined by datatool.sty may be plotted as a 2D
+ scatter or line plot
+
+ Settings provided to govern the appearance of the chart.
+ (e.g. show/hide axes, legend, grid, major/minor tick marks.)
+
+ Hooks provided to add extra information to the plot
+
+databar.sty:
+
+ A database defined by datatool.sty can be converted into a
+ bar chart.
+
+ Colour/grey scale options.
+
+ Predefined bar colours can be changed.
+
+ Horizontal or vertical formats provided.
+
+ Hooks provided to annotate chart.
+
+*The datatool bundle replaces the csvtools bundle which is now obsolete.*
+
+The datatool.sty package requires the following packages/files:
+
+xkeyval
+xfor
+fp
+substr
+compare.tex
+
+The datapie.sty, dataplot.sty and databar.sty packages requires
+the tikz/pgf package.
+
+*Remember to refresh TeX's database*
+
+The package and documentation source code is also supplied as a
+dtx and ins file located in texmf/source.
+
+This material is subject to the LaTeX Project Public License.
+See http://www.ctan.org/tex-archive/help/Catalogue/licenses.lppl.html for the details of that license.
+
+http://theoval.cmp.uea.ac.uk/~nlct/
+
diff --git a/Master/texmf-dist/doc/latex/datatool/doc/CHANGES b/Master/texmf-dist/doc/latex/datatool/doc/CHANGES
new file mode 100644
index 00000000000..11c7fa0086c
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/datatool/doc/CHANGES
@@ -0,0 +1 @@
+v1.0 (2007/07/23) : Initial Release
diff --git a/Master/texmf-dist/doc/latex/datatool/doc/datatool.pdf b/Master/texmf-dist/doc/latex/datatool/doc/datatool.pdf
new file mode 100644
index 00000000000..7a2784f1ee0
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/datatool/doc/datatool.pdf
Binary files differ
diff --git a/Master/texmf-dist/doc/latex/datatool/source/datatool.dtx b/Master/texmf-dist/doc/latex/datatool/source/datatool.dtx
new file mode 100644
index 00000000000..a7363848b5a
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/datatool/source/datatool.dtx
@@ -0,0 +1,12428 @@
+%\iffalse
+% datatool.dtx generated using makedtx version 0.93b (c) Nicola Talbot
+% Command line args:
+% -src "datatool.sty=>datatool.sty"
+% -src "datapie.sty=>datapie.sty"
+% -src "dataplot.sty=>dataplot.sty"
+% -src "databar.sty=>databar.sty"
+% -doc "manual.tex"
+% -author "Nicola Talbot"
+% -codetitle "datatool.sty"
+% -dir "source"
+% datatool
+% Created on 2007/7/23 22:53
+%\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) 2007 Nicola Talbot, all rights reserved.
+% \fi
+% \iffalse
+%<*driver>
+\documentclass[a4paper]{ltxdoc}
+\usepackage{ifthen}
+\usepackage{alltt}
+\usepackage[verbose=false]{datatool}
+\usepackage{datapie,databar}
+\usepackage{textcomp}
+\usepackage{graphicx}
+\usepackage{colortbl}
+\usepackage[colorlinks,
+ bookmarks,
+ hyperindex=false,
+ pdfauthor={Nicola L.C. Talbot},
+ pdftitle={datatool: Databases and data manipulation},
+ pdfkeywords={LaTeX,package,database,data,chart,plot}]{hyperref}
+\usetikzlibrary{snakes}
+
+ %hyperindex conflicts with doc
+ %(end up with |usage|hyperpage in indexentry)
+ %This unfortunately means that the changes section doesn't
+ %have active links, but at least it will keep makeindex happy.
+
+\renewcommand{\usage}[1]{\textit{\hyperpage{#1}}}
+\renewcommand{\main}[1]{\hyperpage{#1}}
+\newcommand{\see}[2]{\emph{see} #1}
+\makeatletter
+\def\index@prologue{\section*{Index}}
+
+ % commands are too wide for a 3 column index
+ \def\theindex{\@restonecoltrue\if@twocolumn\@restonecolfalse\fi
+ \columnseprule \z@ \columnsep 35\p@
+ \twocolumn[\index@prologue]%
+ \IndexParms \let\item\@idxitem \ignorespaces}
+ \def\endtheindex{\if@restonecol\onecolumn\else\clearpage\fi}
+\makeatother
+\RecordChanges
+\PageIndex
+\CheckSum{8992}
+\CodelineNumbered
+
+\newcommand*{\sty}[1]{\textsf{#1}}
+\newcommand*{\env}[1]{\textsf{#1}}
+\definecolor{defbackground}{rgb}{0.8,1,1}
+
+\makeatletter
+\newcommand*{\setting}[2]{\textsf{#2}\relax
+\@for\thiscmd:=#1\do{%
+\edef\doindex{\noexpand\index
+{\thiscmd\space settings=\noexpand\cs{\thiscmd} settings>#2=\noexpand
+\textsf{#2}|hyperpage}}\doindex
+}}
+\makeatother
+
+\newcommand*{\counterfmt}[1]{\texttt{#1}\index
+{#1 counter=\texttt{#1} counter|hyperpage}}
+
+\newcommand*{\ics}[1]{\cs{#1}\SpecialMainIndex{#1}}
+
+\newsavebox\defsbox
+\newenvironment{definition}{%
+\begin{lrbox}{\defsbox}%
+\begin{minipage}{\linewidth}
+}{%
+\end{minipage}
+\end{lrbox}%
+\vskip10pt
+\noindent
+{\setlength{\fboxsep}{4pt}\setlength{\fboxrule}{1.25pt}%
+\fcolorbox{black}{defbackground}{\usebox\defsbox}%
+}\vskip10pt
+}
+
+\newcommand*{\pkgopt}[2][datatool]{\textsf{#2}\index
+{#1 package options=\textsf{#1} package options>#2=\textsf{#2}|hyperpage}}
+
+\newcounter{example}
+\newcommand*{\examplename}{example}
+\makeatletter
+\newenvironment{example}[2]{\refstepcounter{example}\label{#2}%
+\par\vskip10pt\noindent
+\textbf{\large Example \theexample\ (#1)}%
+\addcontentsline{loe}{section}{\protect\numberline{\theexample}#1}%
+\nopagebreak\par\vskip10pt\nopagebreak
+}%
+{\begin{center}\rule{2in}{1pt}\end{center}}
+
+\newcommand*{\listofexamples}{\section*{List of Examples}%
+\@starttoc{loe}}
+\makeatother
+
+
+\begin{document}
+\DocInput{datatool.dtx}
+\end{document}
+%</driver>
+%\fi
+%\MakeShortVerb{"}
+%\DeleteShortVerb{\|}
+%
+% \title{datatool v 1.0: Databases and data manipulation}
+% \author{Nicola L.C. Talbot\\[10pt]
+%School of Computing Sciences\\
+%University of East Anglia\\
+%Norwich. Norfolk\\
+%NR4 7TJ. United Kingdom.\\
+%\url{http://theoval.cmp.uea.ac.uk/~nlct/}}
+%
+% \date{23rd July 2007}
+% \maketitle
+%\tableofcontents
+%\listofexamples
+%
+% \section{Introduction}
+%
+% \changes{1.0}{2007 July 22}{Initial version}
+%The \sty{datatool} bundle consists of the following
+%packages: \sty{datatool}, \sty{datapie}, \sty{dataplot} and
+%\sty{databar}.
+%
+%The \sty{datatool} package can be used to:
+%\begin{itemize}
+%\item Create or load databases.
+%\item Sort rows of a database (either numerically or alphabetically,
+%ascending or descending.)
+%\item Perform repetitive operations on each row of a database
+%(e.g.\ mail merging.) Conditions may be imposed to exclude rows.
+%\item Determine where an argument is an integer, a real number,
+%currency or a string. (Scientific notation is currently not
+%supported.) Locale dependent number settings are supported (such
+%as a comma as a decimal character and a full stop as a number
+%group character.)
+%\item Convert locale dependent numbers/currency to the decimal
+%format required by the \sty{fp} package, enabling fixed point
+%arithmetic to be performed on elements of the database.
+%\item Names can be converted to initials.
+%\item Strings can be tested to determine if they are all
+%upper or lower case.
+%\end{itemize}
+%
+%The \sty{datapie} package can be used to convert a database into
+%a pie chart:
+%\begin{itemize}
+%\item Segments can be separated from the rest of the chart to make
+%them stand out.
+%\item Colour/grey scale options.
+%\item Predefined segment colours can be changed.
+%\item Hooks provided to add extra information to the chart
+%\end{itemize}
+%
+%The \sty{databar} package can be used to convert a database into
+%a bar chart:
+%\begin{itemize}
+%\item Colour/grey scale options.
+%\item Predefined bar colours can be changed.
+%\item Hooks provided to add extra information to the chart
+%\end{itemize}
+%
+%(The \sty{datapie} and \sty{databar} packages do not support the
+%creation of 3D charts, and I have no plans to implement them at any
+%later date. The use of 3D charts should be discouraged. They may look
+%pretty, but the purpose of a chart is to be informative. Three
+%dimensional graphics cause distortion, which can result in misleading
+%impressions.)
+%
+%The \sty{dataplot} package can be used to convert a database into
+%a two dimensional plot using markers and/or lines. Three dimensional
+%plots are currently not supported.
+%
+%\textbf{This package replaces the \sty{csvtools} package which is now
+%obsolete.}
+%
+%\section{Data Types}
+%\label{sec:datatypes}
+%
+%The \sty{datatool} package recognises four data types: integers,
+%real numbers, currency and strings.
+%
+%\begin{description}
+%\item[Integers] An integer is a sequence of digits, optionally
+%groups of three digits may be separated by the number group character.
+%The default number group character is a comma (,) but may be
+%changed using \cs{DTLsetnumberchars} (see below.)
+%
+%\item[Real Numbers] A real number is an integer followed by the
+%decimal character followed by one or more digits. The decimal
+%character is a full stop (.) by default. The number group
+%and decimal characters may be changed using
+%\DescribeMacro{\DTLsetnumberchars}
+%\begin{definition}
+%\cs{DTLsetnumberchars}\marg{number group character}\marg{decimal character}
+%\end{definition}
+%Note that scientific notation is not supported, and the number group
+%character may not be used after the decimal character.
+%
+%\item[Currency] A currency symbol followed by an integer or
+%real number is considered to be the currency data type.
+%There are two predefined currency symbols, "\$" and \cs{pounds}.
+%In addition, if any of the following commands are defined at the
+%start of the document, they are also considered to be a currency
+%symbol: \cs{texteuro}, \cs{textdollar}, \cs{textstirling},
+%\cs{textyen}, \cs{textwon}, \cs{textcurrency}, \cs{euro}
+%and \cs{yen}. Additional currency symbols can be defined using
+%\DescribeMacro{\DTLnewcurrencysymbol}
+%\begin{definition}
+%\cs{DTLnewcurrencysymbol}\marg{symbol}
+%\end{definition}
+%
+%\item[Strings] Anything that doesn't belong to the above three
+%types is considered to be a string.
+%
+%\end{description}
+%
+%\subsection{Conditionals}
+%\label{sec:ifconditions}
+%
+%The following conditionals are provided by the \sty{datatool}
+%package:
+%
+%\DescribeMacro{\DTLifint}
+%\begin{definition}
+%\cs{DTLifint}\marg{text}\marg{true part}\marg{false part}
+%\end{definition}
+%If \meta{text} is an integer then do \meta{true part}, otherwise
+%do \meta{false part}. For example
+%\begin{verbatim}
+%\DTLifint{2536}{integer}{not an integer}
+%\end{verbatim}
+%produces:
+%\DTLifint{2536}{integer}{not an integer}.
+%
+%The number group character may appear in the number, for example:
+%\begin{verbatim}
+%\DTLifint{2,536}{integer}{not an integer}
+%\end{verbatim}
+%produces:
+%\DTLifint{2,536}{integer}{not an integer}.
+%However, the number group character may only be followed by a group
+%of three digits. For example:
+%\begin{verbatim}
+%\DTLifint{2,5,3,6}{integer}{not an integer}
+%\end{verbatim}
+%produces:
+%\DTLifint{2,5,3,6}{integer}{not an integer}.
+%The number group character may be changed. For example:
+%\begin{verbatim}
+%\DTLsetnumberchars{.}{,}%
+%\DTLifint{2,536}{integer}{not an integer}
+%\end{verbatim}
+%this now produces:
+%\DTLsetnumberchars{.}{,}\relax
+%\DTLifint{2,536}{integer}{not an integer}, since 2,536 is now
+%a real number.
+%
+%Note that nothing else can be appended or prepended to the
+%number. For example:
+%\begin{verbatim}
+%\DTLsetnumberchars{,}{.}%
+%\DTLifint{2,536m}{integer}{not an integer}
+%\end{verbatim}
+%produces:
+%\DTLsetnumberchars{,}{.}\relax
+%\DTLifint{2,536m}{integer}{not an integer}.
+%
+%\DescribeMacro{\DTLifreal}
+%\begin{definition}
+%\cs{DTLifreal}\marg{text}\marg{true part}\marg{false part}
+%\end{definition}
+%If \meta{text} is a real number then do \meta{true part}, otherwise
+%do \meta{false part}. For example
+%\begin{verbatim}
+%\DTLifreal{1000.0}{real}{not real}
+%\end{verbatim}
+%produces:
+%\DTLifreal{1000.0}{real}{not real}.
+%
+%Note that an integer is not a real number:
+%\begin{verbatim}
+%\DTLifreal{1,000}{real}{not real}
+%\end{verbatim}
+%produces:
+%\DTLifreal{1,000}{real}{not real}.
+%
+%Whereas
+%\begin{verbatim}
+%\DTLifreal{1,000.0}{real}{not real}
+%\end{verbatim}
+%produces:
+%\DTLifreal{1,000.0}{real}{not real}.
+%
+%However
+%\begin{verbatim}
+%\DTLsetnumberchars{.}{,}%
+%\DTLifreal{1,000}{real}{not real}
+%\end{verbatim}
+%produces:
+%\DTLsetnumberchars{.}{,}\relax
+%\DTLifreal{1,000}{real}{not real} since the comma is now
+%the decimal character.
+%
+%Currency is not considered to be real:
+%\begin{verbatim}
+%\DTLsetnumberchars{,}{.}%
+%\DTLifreal{\$1.00}{real}{not real}
+%\end{verbatim}
+%produces:
+%\DTLsetnumberchars{,}{.}\relax
+%\DTLifreal{\$1.00}{real}{not real}.
+%
+%\DescribeMacro{\DTLifcurrency}
+%\begin{definition}
+%\cs{DTLifcurrency}\marg{text}\marg{true part}\marg{false part}
+%\end{definition}
+%If \meta{text} is currency, then do \meta{true part}, otherwise
+%do false part. For example:
+%\begin{verbatim}
+%\DTLifcurrency{\$5.99}{currency}{not currency}
+%\end{verbatim}
+%produces:
+%\DTLifcurrency{\$5.99}{currency}{not currency}. Similarly:
+%\begin{verbatim}
+%\DTLifcurrency{\pounds5.99}{currency}{not currency}
+%\end{verbatim}
+%produces:
+%\DTLifcurrency{\pounds5.99}{currency}{not currency}.
+%Note, however, that
+%\begin{verbatim}
+%\DTLifcurrency{US\$5.99}{currency}{not currency}
+%\end{verbatim}
+%produces:
+%\DTLifcurrency{US\$5.99}{currency}{not currency}. If you want
+%this to be considered currency, you will have to add the
+%sequence "US\$" to the set of currency symbols:
+%\begin{verbatim}
+%\DTLnewcurrencysymbol{US\$}%
+%\DTLifcurrency{US\$5.99}{currency}{not currency}
+%\end{verbatim}
+%this now produces:
+%\DTLnewcurrencysymbol{US\$}\relax
+%\DTLifcurrency{US\$5.99}{currency}{not currency}.
+%
+%This document has used the \sty{textcomp} package which defines
+%\cs{texteuro}, so this is also considered to be currency. For
+%example:
+%\begin{verbatim}
+%\DTLifcurrency{\texteuro5.99}{currency}{not currency}
+%\end{verbatim}
+%produces:
+%\DTLifcurrency{\texteuro5.99}{currency}{not currency}.
+%
+%The preferred method is to display the euro symbol in a sans-serif
+%font, but
+%\begin{verbatim}
+%\DTLifcurrency{\textsf{\texteuro}5.99}{currency}{not currency}
+%\end{verbatim}
+%will produce:
+%\DTLifcurrency{\textsf{\texteuro}5.99}{currency}{not currency}.
+%
+%It is better to define a new command, for example:
+%\begin{verbatim}
+%\DeclareRobustCommand*{\euro}{\textsf{\texteuro}}
+%\end{verbatim}
+%and add that command to the list of currency symbols. In fact,
+%in this case, if you define the command \cs{euro} in the
+%preamble, it will automatically be added to the list of known
+%currency symbols. If however you define \cs{euro} in the document,
+%you will have to add it using \ics{DTLnewcurrencysymbol}. For
+%example:
+%\begin{verbatim}
+%\newcommand*{\euro}{\textsf{\texteuro}}%
+%\DTLnewcurrencysymbol{\euro}%
+%\DTLifcurrency{\euro5.99}{currency}{not currency}
+%\end{verbatim}
+%produces:
+%\DeclareRobustCommand*{\euro}{\textsf{\texteuro}}\relax
+%\DTLnewcurrencysymbol{\euro}\relax
+%\DTLifcurrency{\euro5.99}{currency}{not currency}.
+%
+%\DescribeMacro{\DTLifcurrencyunit}
+%\begin{definition}
+%\cs{DTLifcurrencyunit}\marg{text}\marg{symbol}\marg{true part}\marg{false part}
+%\end{definition}
+%If \meta{text} is currency, and uses \meta{symbol} as the unit of
+%currency, then do \meta{true part} otherwise do \meta{false part}.
+%For example:
+%\begin{verbatim}
+%\DTLifcurrencyunit{\$6.99}{\$}{dollars}{not dollars}
+%\end{verbatim}
+%produces:
+%\DTLifcurrencyunit{\$6.99}{\$}{dollars}{not dollars}.
+%Another example:
+%\begin{verbatim}
+%\def\cost{\euro10.50}%
+%\DTLifcurrencyunit{\cost}{\euro}{euros}{not euros}
+%\end{verbatim}
+%produces:
+%\def\cost{\euro10.50}\relax
+%\DTLifcurrencyunit{\cost}{\euro}{euros}{not euros}.
+%
+%\DescribeMacro{\DTLifnumerical}
+%\begin{definition}
+%\cs{DTLifnumerical}\marg{text}\marg{true part}\marg{false part}
+%\end{definition}
+%If \meta{text} is numerical (either an integer, real number or
+%currency) then do \meta{true part} otherwise do
+%\meta{false part}.
+%For example:
+%\begin{verbatim}
+%\DTLifnumerical{1,000.0}{number}{string}.
+%\end{verbatim}
+%produces: \DTLifnumerical{1,000.0}{number}{string}.
+%Whereas
+%\begin{verbatim}
+%\DTLsetnumberchars{.}{,}%
+%\DTLifnumerical{1,000.0}{number}{string}.
+%\end{verbatim}
+%produces:
+%\DTLsetnumberchars{.}{,}\relax
+%\DTLifnumerical{1,000.0}{number}{string}.
+%Since the number group character is now a full stop, and the
+%decimal character is now a comma. (The number group character
+%may only appear before the decimal character, not after it.)
+%
+%Currency is also considered to be numerical:
+%\begin{verbatim}
+%\DTLsetnumberchars{,}{.}%
+%\DTLifnumerical{\$1,000.0}{number}{string}.
+%\end{verbatim}
+%produces:
+%\DTLsetnumberchars{,}{.}\relax
+%\DTLifnumerical{\$1,000.0}{number}{string}.
+%
+%\DescribeMacro{\DTLifstring}
+%\begin{definition}
+%\cs{DTLifstring}\marg{text}\marg{true part}\marg{false part}
+%\end{definition}
+%This is the opposite of \cs{DTLifnumerical}. If \meta{text} is
+%not numerical, do \meta{true part}, otherwise do \meta{false part}.
+%
+%\DescribeMacro{\DTLifcasedatatype}
+%\begin{definition}
+%\cs{DTLifcasedatatype}\marg{text}\marg{string case}\marg{int case}\marg{real case}\marg{currency case}
+%\end{definition}
+%If \meta{text} is a string do \meta{string case}, if \meta{text}
+%is an integer do \meta{int case}, if \meta{text} is a real number
+%do \meta{real case}, if \meta{text} is currency do
+%\meta{currency case}. For example:
+%\begin{verbatim}
+%\DTLifcasedatatype{1,000}{string}{integer}{real}{currency}
+%\end{verbatim}
+%produces:
+%\DTLifcasedatatype{1,000}{string}{integer}{real}{currency}.
+%
+%\DescribeMacro{\DTLifnumlt}
+%\begin{definition}
+%\cs{DTLifnumlt}\marg{num1}\marg{num2}\marg{true part}\marg{false part}
+%\end{definition}
+%If \meta{num1} is less than \meta{num2}, then do \meta{true part},
+%otherwise do \meta{false part}. Note that both \meta{num1} and
+%\meta{num2} must be numerical (either integers, real numbers or
+%currency.)
+%
+%\DescribeMacro{\DTLifstringlt}
+%\begin{definition}
+%\cs{DTLifstringlt}\marg{string1}\marg{string2}\marg{true part}\marg{false part}
+%\end{definition}
+%If \meta{string1} is alphabetically less than \meta{string2}, then do
+%\meta{true part}, otherwise do \meta{false part}.
+%For example:
+%\begin{verbatim}
+%\DTLifstringlt{aardvark}{zebra}{less}{not less}
+%\end{verbatim}
+%produces:
+%\DTLifstringlt{aardvark}{zebra}{less}{not less}.
+%
+%Note that both \meta{string1} and \meta{string2} are considered to be
+%strings, so for example:
+%\begin{verbatim}
+%\DTLifstringlt{2}{10}{less}{not less}
+%\end{verbatim}
+%produces:
+%\DTLifstringlt{2}{10}{less}{not less}, since the string "2"
+%comes after the string "10" when arranged alphabetically.
+%
+%\DescribeMacro{\DTLiflt}
+%\begin{definition}
+%\cs{DTLiflt}\marg{arg1}\marg{arg2}\marg{true part}\marg{false part}
+%\end{definition}
+%If \meta{arg1} and \meta{arg2} are both numerical, then this
+%is equivalent to \cs{DTLifnumlt}, otherwise it is equivalent
+%to \cs{DTLstringlt}.
+%
+%\DescribeMacro{\DTLifnumgt}
+%\begin{definition}
+%\cs{DTLifnumgt}\marg{num1}\marg{num2}\marg{true part}\marg{false part}
+%\end{definition}
+%If \meta{num1} is greater than \meta{num2}, then do \meta{true part},
+%otherwise do \meta{false part}. Note that both \meta{num1} and
+%\meta{num2} must be numerical (either integers, real numbers or
+%currency.)
+%
+%\DescribeMacro{\DTLifstringgt}
+%\begin{definition}
+%\cs{DTLifstringgt}\marg{string1}\marg{string2}\marg{true part}\marg{false part}
+%\end{definition}
+%If \meta{string1} is alphabetically greater than \meta{string2}, then
+%do \meta{true part}, otherwise do \meta{false part}. For example:
+%\begin{verbatim}
+%\DTLifstringgt{aardvark}{zebra}{greater}{not greater}
+%\end{verbatim}
+%produces:
+%\DTLifstringgt{aardvark}{zebra}{greater}{not greater}.
+%
+%Note that both \meta{string1} and \meta{string2} are considered to be
+%strings, so for example:
+%\begin{verbatim}
+%\DTLifstringgt{2}{10}{greater}{not greater}
+%\end{verbatim}
+%produces:
+%\DTLifstringgt{2}{10}{greater}{not greater}, since the string "2"
+%comes after the string "10" when arranged alphabetically.
+%
+%\DescribeMacro{\DTLifgt}
+%\begin{definition}
+%\cs{DTLifgt}\marg{arg1}\marg{arg2}\marg{true part}\marg{false part}
+%\end{definition}
+%If \meta{arg1} and \meta{arg2} are both numerical, then this
+%is equivalent to \cs{DTLifnumgt}, otherwise it is equivalent
+%to \cs{DTLstringgt}.
+%
+%\DescribeMacro{\DTLifnumeq}
+%\begin{definition}
+%\cs{DTLifnumeq}\marg{num1}\marg{num2}\marg{true part}\marg{false part}
+%\end{definition}
+%If \meta{num1} is equal to \meta{num2}, then do \meta{true part},
+%otherwise do \meta{false part}. Note that both \meta{num1} and
+%\meta{num2} must be numerical (either integers, real numbers or
+%currency.) The currency symbol is ignored when determining
+%equality. For example
+%\begin{verbatim}
+%\DTLifnumeq{\pounds10.50}{10.5}{true}{false}
+%\end{verbatim}
+%produces:
+%\DTLifnumeq{\pounds10.50}{10.5}{true}{false}, since they are
+%considered to be numerically equivalent. Likewise:
+%\begin{verbatim}
+%\DTLifnumeq{\pounds10.50}{\$10.50}{true}{false}
+%\end{verbatim}
+%produces:
+%\DTLifnumeq{\pounds10.50}{\$10.50}{true}{false}.
+%
+%\DescribeMacro{\DTLifstringeq}
+%\begin{definition}
+%\cs{DTLifstringeq}\marg{string1}\marg{string2}\marg{true part}\marg{false part}
+%\end{definition}
+%If \meta{string1} and \meta{string2} are identical, then do
+%\meta{true part}, otherwise do \meta{false part}. Again, both
+%\meta{string1} and \meta{string2} are considered to be strings,
+%so for example:
+%\begin{verbatim}
+%\DTLifstringeq{10.50}{10.5}{true}{false}
+%\end{verbatim}
+%produces:
+%\DTLifstringeq{10.50}{10.5}{true}{false}.
+%
+%Note that the comparison is case sensitive, so for example:
+%\begin{verbatim}
+%\DTLifstringeq{Text}{text}{true}{false}
+%\end{verbatim}
+%produces:
+%\DTLifstringeq{Text}{text}{true}{false}.
+%
+%\DescribeMacro{\DTLifeq}
+%\begin{definition}
+%\cs{DTLifeq}\marg{arg1}\marg{arg2}\marg{true part}\marg{false part}
+%\end{definition}
+%If both \meta{arg1} and \meta{arg2} are numerical, then this is
+%equivalent to \cs{DTLifnumeq}, otherwise it is equivalent to
+%\cs{DTLifstringeq}.
+%
+%\DescribeMacro{\DTLifnumclosedbetween}
+%\begin{definition}
+%\cs{DTLifnumclosedbetween}\marg{num}\marg{min}\marg{max}\marg{true part}\marg{false part}
+%\end{definition}
+%If \meta{min} $\leq$ \meta{num} $\leq$ \meta{max} then do \meta{true part},
+%otherwise do \meta{false part}. Note that \meta{num}, \meta{min} and
+%\meta{max} must be numerical (either integers, real numbers or
+%currency.) The currency symbol is ignored when determining
+%equality. For example:
+%\begin{verbatim}
+%\DTLifnumclosedbetween{5.4}{5}{7}{inside}{outside}
+%\end{verbatim}
+%produces:
+%\DTLifnumclosedbetween{5.4}{5}{7}{inside}{outside}.
+%Note that the closed range includes end points:
+%\begin{verbatim}
+%\DTLifnumclosedbetween{5}{5}{7}{inside}{outside}
+%\end{verbatim}
+%produces:
+%\DTLifnumclosedbetween{5}{5}{7}{inside}{outside}.
+%
+%\DescribeMacro{\DTLifstringclosedbetween}
+%\begin{definition}
+%\cs{DTLifstringclosedbetween}\marg{string}\marg{min}\marg{max}\marg{true part}\marg{false part}
+%\end{definition}
+%This determines if \meta{string} is between \meta{min} and
+%\meta{max} in the alphabetical sense, or is equal to either
+%\meta{min} or \meta{max}.
+%
+%\DescribeMacro{\DTLifclosedbetween}
+%\begin{definition}
+%\cs{DTLifclosedbetween}\marg{arg}\marg{min}\marg{max}\marg{true part}\marg{false part}
+%\end{definition}
+%If \meta{arg}, \meta{min} and \meta{max} are numerical, then this is
+%equivalent to \cs{DTLifnumclosedbetween}, otherwise it is equivalent to
+%\cs{DTLifstringclosedbetween}.
+%
+%\DescribeMacro{\DTLifnumopenbetween}
+%\begin{definition}
+%\cs{DTLifnumopenbetween}\marg{num}\marg{min}\marg{max}\marg{true part}\marg{false part}
+%\end{definition}
+%If \meta{min} $<$ \meta{num} $<$ \meta{max} then do \meta{true part},
+%otherwise do \meta{false part}. Note that \meta{num}, \meta{min} and
+%\meta{max} must be numerical (either integers, real numbers or
+%currency.) Again, the currency symbol is ignored when determining
+%equality. For example:
+%\begin{verbatim}
+%\DTLifnumclosedbetween{5.4}{5}{7}{inside}{outside}
+%\end{verbatim}
+%produces:
+%\DTLifnumclosedbetween{5.4}{5}{7}{inside}{outside}.
+%Note that end points are not included. For example:
+%\begin{verbatim}
+%\DTLifnumclosedbetween{5}{5}{7}{inside}{outside}
+%\end{verbatim}
+%produces:
+%\DTLifnumclosedbetween{5}{5}{7}{inside}{outside}.
+%
+%\DescribeMacro{\DTLifstringclosedbetween}
+%\begin{definition}
+%\cs{DTLifstringclosedbetween}\marg{string}\marg{min}\marg{max}\marg{true part}\marg{false part}
+%\end{definition}
+%This determines if \meta{string} is between \meta{min} and
+%\meta{max} in the alphabetical sense, or is equal to either
+%\meta{min} or \meta{max}.
+%
+%\DescribeMacro{\DTLifclosedbetween}
+%\begin{definition}
+%\cs{DTLifclosedbetween}\marg{arg}\marg{min}\marg{max}\marg{true part}\marg{false part}
+%\end{definition}
+%If \meta{arg}, \meta{min} and \meta{max} are numerical, then this is
+%equivalent to \cs{DTLifnumclosedbetween}, otherwise it is equivalent to
+%\cs{DTLifstringclosedbetween}.
+%
+%\DescribeMacro{\DTLifFPclosedbetween}
+%\begin{definition}
+%\cs{DTLifFPclosedbetween}\marg{num}\marg{min}\marg{max}\marg{true part}\marg{false part}
+%\end{definition}
+%If \meta{min} $\leq$ \meta{num} $\leq$ \meta{max} then do \meta{true part},
+%otherwise do \meta{false part} where \meta{num}, \meta{min}
+%and \meta{max} are all in standard fixed point notation (i.e.\
+%no number group separator, no currency symbols and a full stop as
+%a decimal point.)
+%
+%\DescribeMacro{\DTLifFPopenbetween}
+%\begin{definition}
+%\cs{DTLifFPopenbetween}\marg{num}\marg{min}\marg{max}\marg{true part}\marg{false part}
+%\end{definition}
+%If \meta{min} $<$ \meta{num} $<$ \meta{max} then do \meta{true part},
+%otherwise do \meta{false part} where \meta{num}, \meta{min}
+%and \meta{max} are all in standard fixed point notation (i.e.\
+%no number group separator, no currency symbols and a full stop as
+%a decimal point.)
+%
+%\DescribeMacro{\DTLifAllUpperCase}
+%\begin{definition}
+%\cs{DTLifAllUpperCase}\marg{string}\marg{true part}\marg{false part}
+%\end{definition}
+%Tests if \meta{string} is all upper case. For example:
+%\begin{verbatim}
+%\DTLifAllUpperCase{WORD}{all upper}{not all upper}
+%\end{verbatim}
+%produces:
+%\DTLifAllUpperCase{WORD}{all upper}{not all upper},
+%whereas
+%\begin{verbatim}
+%\DTLifAllUpperCase{Word}{all upper}{not all upper}
+%\end{verbatim}
+%produces:
+%\DTLifAllUpperCase{Word}{all upper}{not all upper}.
+%Note also that:
+%\begin{verbatim}
+%\DTLifAllUpperCase{\MakeUppercase{word}}{all upper}{not all upper}
+%\end{verbatim}
+%also produces:
+%\DTLifAllUpperCase{\MakeUppercase{word}}{all upper}{not all upper}.
+%\cs{MakeTextUppercase} (defined in David Carlisle's \sty{textcase}
+%package) and \cs{uppercase} are also detected, otherwise, if
+%a command is encountered, the case of the command is considered.
+%For example:
+%\begin{verbatim}
+%\DTLifAllUpperCase{MAN{\OE}UVRE}{all upper}{not all upper}
+%\end{verbatim}
+%produces:
+%\DTLifAllUpperCase{MAN{\OE}UVRE}{all upper}{not all upper}.
+%
+%\DescribeMacro{\DTLifAllLowerCase}
+%\begin{definition}
+%\cs{DTLifAllLowerCase}\marg{string}\marg{true part}\marg{false part}
+%\end{definition}
+%Tests if \meta{string} is all lower case. For example:
+%\begin{verbatim}
+%\DTLifAllLowerCase{word}{all lower}{not all lower}
+%\end{verbatim}
+%produces:
+%\DTLifAllLowerCase{word}{all lower}{not all lower},
+%whereas
+%\begin{verbatim}
+%\DTLifAllLowerCase{Word}{all lower}{not all lower}
+%\end{verbatim}
+%produces:
+%\DTLifAllLowerCase{Word}{all lower}{not all lower}.
+%Note also that:
+%\begin{verbatim}
+%\DTLifAllLowerCase{\MakeLowercase{WORD}}{all lower}{not all lower}
+%\end{verbatim}
+%also produces:
+%\DTLifAllLowerCase{\MakeLowercase{WORD}}{all lower}{not all lower}.
+%\cs{MakeTextLowercase} (defined in David Carlisle's \sty{textcase}
+%package) and \cs{lowercase} are also detected, otherwise, if
+%a command is encountered, the case of the command is considered.
+%For example:
+%\begin{verbatim}
+%\DTLifAllLowerCase{man{\oe}uvre}{all lower}{not all lower}
+%\end{verbatim}
+%produces:
+%\DTLifAllLowerCase{man{\oe}uvre}{all lower}{not all lower}.
+%
+%\subsection{\texorpdfstring{\sty{ifthen}}{ifthen} conditionals}
+%\label{sec:ifthen}
+%
+%The commands described in the previous section can not be
+%used as the conditional part of the \cs{ifthenelse} or
+%\cs{whiledo} commands provided by the \sty{ifthen} package.
+%This section describes analogous commands which may only be
+%used in the conditional argument of \cs{ifthenelse} and
+%\cs{whiledo}.
+%
+%\DescribeMacro{\DTLisstring}
+%\begin{definition}
+%\cs{DTLisstring}\marg{text}
+%\end{definition}
+%Tests if \meta{text} is a string. For example:
+%\begin{verbatim}
+%\ifthenelse{\DTLisstring{some text}}{string}{not a string}
+%\end{verbatim}
+%produces:
+%\ifthenelse{\DTLisstring{some text}}{string}{not a string}.
+%
+%\DescribeMacro{\DTLisnumerical}
+%\begin{definition}
+%\cs{DTLisnumerical}\marg{text}
+%\end{definition}
+%Tests if \meta{text} is numerical (i.e.\ not a string.) For example:
+%\begin{verbatim}
+%\ifthenelse{\DTLisnumerical{\$10.95}}{numerical}{not numerical}
+%\end{verbatim}
+%produces:
+%\ifthenelse{\DTLisnumerical{\$10.95}}{numerical}{not numerical}.
+%
+%Note however that \cs{DTLisnumerical} requires more care than
+%\cs{DTLifnumerical} when used with some of the other currency
+%symbols. Consider:
+%\begin{verbatim}
+%\DTLifnumerical{\pounds10.95}{numerical}{not numerical}
+%\end{verbatim}
+%This produces:
+%\DTLifnumerical{\pounds10.95}{numerical}{not numerical}.
+%However
+%\begin{verbatim}
+%\ifthenelse{\DTLisnumerical{\pounds10.95}}{numerical}{not numerical}
+%\end{verbatim}
+%produces
+%\ifthenelse{\DTLisnumerical{\pounds10.95}}{numerical}{not numerical}.
+%This is due to the expansion that occurs within \cs{ifthenelse}.
+%This can be prevented using \cs{noexpand}, for example:
+%\begin{verbatim}
+%\ifthenelse{\DTLisnumerical{\noexpand\pounds10.95}}{numerical}{not numerical}
+%\end{verbatim}
+%produces:
+%\ifthenelse{\DTLisnumerical{\noexpand\pounds10.95}}{numerical}{not numerical}.
+%
+%Likewise:
+%\begin{verbatim}
+%\def\cost{\pounds10.95}%
+%\ifthenelse{\DTLisnumerical{\noexpand\cost}}{numerical}{not numerical}
+%\end{verbatim}
+%produces
+%\def\cost{\pounds10.95}\relax
+%\ifthenelse{\DTLisnumerical{\noexpand\cost}}{numerical}{not numerical}.
+%
+%\DescribeMacro{\DTLiscurrency}
+%\begin{definition}
+%\cs{DTLiscurrency}\marg{text}
+%\end{definition}
+%Tests if \meta{text} is currency. For example:
+%\begin{verbatim}
+%\ifthenelse{\DTLiscurrency{\$10.95}}{currency}{not currency}
+%\end{verbatim}
+%produces:
+%\ifthenelse{\DTLiscurrency{\$10.95}}{currency}{not currency}.
+%
+%The same warning given above for \cs{DTLisnumerical} also applies
+%here.
+%
+%\DescribeMacro{\DTLiscurrencyunit}
+%\begin{definition}
+%\cs{DTLiscurrencyunit}\marg{text}\marg{symbol}
+%\end{definition}
+%Tests if \meta{text} is currency, and uses \meta{symbol} as the unit
+%of currency.
+%For example:
+%\begin{verbatim}
+%\ifthenelse{\DTLiscurrencyunit{\$6.99}{\$}}{dollars}{not dollars}
+%\end{verbatim}
+%produces:
+%\ifthenelse{\DTLiscurrencyunit{\$6.99}{\$}}{dollars}{not dollars}
+%Another example:
+%\begin{verbatim}
+%\def\cost{\euro10.50}%
+%\ifthenelse{\DTLiscurrencyunit{\noexpand\cost}{\noexpand\euro}}%
+%{euros}{not euros}
+%\end{verbatim}
+%produces:
+%\def\cost{\euro10.50}\relax
+%\ifthenelse{\DTLiscurrencyunit{\noexpand\cost}{\noexpand\euro}}%
+%{euros}{not euros}. Again note the use of \cs{noexpand}.
+%
+%\DescribeMacro{\DTLisreal}
+%\begin{definition}
+%\cs{DTLisreal}\marg{text}
+%\end{definition}
+%Tests if \meta{text} is a fixed point number (again, an integer is
+%not considered to be a fixed point number.) For example:
+%\begin{verbatim}
+%\ifthenelse{\DTLisreal{1.5}}{real}{not real}
+%\end{verbatim}
+%produces:
+%\ifthenelse{\DTLisreal{1.5}}{real}{not real}.
+%
+%\DescribeMacro{\DTLisint}
+%\begin{definition}
+%\cs{DTLisint}\marg{text}
+%\end{definition}
+%Tests if \meta{text} is an integer. For example:
+%\begin{verbatim}
+%\ifthenelse{\DTLisint{153}}{integer}{not an integer}
+%\end{verbatim}
+%produces:
+%\ifthenelse{\DTLisint{153}}{integer}{not an integer}.
+%
+%\DescribeMacro{\DTLislt}
+%\begin{definition}
+%\cs{DTLislt}\marg{arg1}\marg{arg2}
+%\end{definition}
+%This checks if \meta{arg1} is less than \meta{arg2}. As with
+%\cs{DTLiflt}, if \meta{arg1} and \meta{arg2} are numerical,
+%a numerical comparison is used, otherwise an alphabetical
+%comparison is used.
+%
+%\DescribeMacro{\DTLisgt}
+%\begin{definition}
+%\cs{DTLisgt}\marg{arg1}\marg{arg2}
+%\end{definition}
+%This checks if \meta{arg1} is greater than \meta{arg2}. As with
+%\cs{DTLifgt}, if \meta{arg1} and \meta{arg2} are numerical,
+%a numerical comparison is used, otherwise an alphabetical
+%comparison is used.
+%
+%\DescribeMacro{\DTLiseq}
+%\begin{definition}
+%\cs{DTLiseq}\marg{arg1}\marg{arg2}
+%\end{definition}
+%This checks if \meta{arg1} is equal to \meta{arg2}. As with
+%\cs{DTLifeq}, if \meta{arg1} and \meta{arg2} are numerical,
+%a numerical comparison is used, otherwise an alphabetical
+%comparison is used.
+%
+%\DescribeMacro{\DTLisclosedbetween}
+%\begin{definition}
+%\cs{DTLisclosedbetween}\marg{arg}\marg{min}\marg{max}
+%\end{definition}
+%This checks if \meta{arg} lies between \meta{min} and
+%\meta{max} (end points included.) As with
+%\cs{DTLifclosedbetween}, if the arguments are numerical,
+%a numerical comparison is used, otherwise an alphabetical
+%comparison is used.
+%
+%\DescribeMacro{\DTLisopenbetween}
+%\begin{definition}
+%\cs{DTLisopenbetween}\marg{arg}\marg{min}\marg{max}
+%\end{definition}
+%This checks if \meta{arg} lies between \meta{min} and
+%\meta{max} (end points excluded.) As with
+%\cs{DTLifopenbetween}, if the arguments are numerical,
+%a numerical comparison is used, otherwise an alphabetical
+%comparison is used.
+%
+%\DescribeMacro{\DTLisFPlt}
+%\begin{definition}
+%\cs{DTLisFPlt}\marg{num1}\marg{num2}
+%\end{definition}
+%This checks if \meta{num1} is less than \meta{num2}, where both
+%numbers are in standard fixed point format (i.e.\ no number group
+%separators, no currency and a full stop as a decimal point.)
+%
+%\DescribeMacro{\DTLisFPlteq}
+%\begin{definition}
+%\cs{DTLisFPlteq}\marg{num1}\marg{num2}
+%\end{definition}
+%This checks if \meta{num1} is less than or equal to \meta{num2}, where both
+%numbers are in standard fixed point format (i.e.\ no number group
+%separators, no currency and a full stop as a decimal point.)
+%
+%\DescribeMacro{\DTLisFPgt}
+%\begin{definition}
+%\cs{DTLisFPgt}\marg{num1}\marg{num2}
+%\end{definition}
+%This checks if \meta{num1} is greater than \meta{num2}, where both
+%numbers are in standard fixed point format (i.e.\ no number group
+%separators, no currency and a full stop as a decimal point.)
+%
+%\DescribeMacro{\DTLisFPgteq}
+%\begin{definition}
+%\cs{DTLisFPgteq}\marg{num1}\marg{num2}
+%\end{definition}
+%This checks if \meta{num1} is greater than or equal to \meta{num2}, where both
+%numbers are in standard fixed point format (i.e.\ no number group
+%separators, no currency and a full stop as a decimal point.)
+%
+%\DescribeMacro{\DTLisFPeq}
+%\begin{definition}
+%\cs{DTLisFPeq}\marg{num1}\marg{num2}
+%\end{definition}
+%This checks if \meta{num1} is equal to \meta{num2}, where both
+%numbers are in standard fixed point format (i.e.\ no number group
+%separators, no currency and a full stop as a decimal point.)
+%
+%\DescribeMacro{\DTLisFPclosedbetween}
+%\begin{definition}
+%\cs{DTLisFPclosedbetween}\marg{num}\marg{min}\marg{max}
+%\end{definition}
+%This checks if \meta{num} lies between \meta{min} and
+%\meta{max} (end points included.) All arguments must be
+%numbers in standard fixed point format (i.e.\ no number group
+%separators, no currency and a full stop as a decimal point.)
+%
+%\DescribeMacro{\DTLisFPopenbetween}
+%\begin{definition}
+%\cs{DTLisFPopenbetween}\marg{num}\marg{min}\marg{max}
+%\end{definition}
+%This checks if \meta{num} lies between \meta{min} and
+%\meta{max} (end points excluded.) All arguments must be
+%numbers in standard fixed point format (i.e.\ no number group
+%separators, no currency and a full stop as a decimal point.)
+%
+%\section{Fixed Point Arithmetic}
+%\label{sec:fp}
+%
+%The \sty{datatool} package uses the \sty{fp} package to perform
+%fixed point arithmetic, however all numbers must be converted
+%from the locale dependent format into the format required by the
+%\sty{fp} package. A numerical value (i.e.\ an integer, a real
+%or currency) can be converted into a plain decimal number using
+%\DescribeMacro{\DTLconverttodecimal}
+%\begin{definition}
+%\cs{DTLconverttodecimal}\marg{num}\marg{cmd}
+%\end{definition}
+%The decimal number will be stored in \meta{cmd} which must be
+%a control sequence. For example:
+%\begin{verbatim}
+%\DTLconverttodecimal{1,563.54}{\mynum}
+%\end{verbatim}
+%\DTLconverttodecimal{1,563.54}{\mynum}\relax
+%will define \cs{mynum} to be \texttt{\mynum}. The command
+%can then be used in any of the arithmetic macros provided by the
+%\sty{fp} package. There are two commands provided to perform
+%the reverse:
+%\DescribeMacro{\DTLdecimaltolocale}
+%\begin{definition}
+%\cs{DTLdecimaltolocale}\marg{number}\marg{cmd}
+%\end{definition}
+%This converts a plain decimal number \meta{number} (that uses a full
+%stop as the decimal character and has no number group characters)
+%into a locale dependent format. The resulting number is stored
+%in \meta{cmd}, which must be a control sequence. For example:
+%\begin{verbatim}
+%\DTLdecimaltolocale{6795.3}{\mynum}
+%\end{verbatim}
+%\DTLdecimaltolocale{6795.3}{\mynum}
+%will define \cs{mynum} to be \texttt{\mynum}.
+%
+%\DescribeMacro{\DTLdecimaltocurrency}
+%\begin{definition}
+%\cs{DTLdecimaltocurrency}\marg{number}\marg{cmd}
+%\end{definition}
+%This will convert a plain decimal number \meta{number} into a
+%locale dependent currency format. For example:
+%\begin{verbatim}
+%\DTLdecimaltocurrency{267.5}{\price}\price
+%\end{verbatim}
+%will produce:
+%\DTLdecimaltocurrency{267.5}{\price}\price.
+%
+%The currency symbol used by \cs{DTLdecimaltocurrency} is
+%initially "\$", but will use the currency last encountered.
+%So, for example
+%\begin{verbatim}
+%\DTLifcurrency{\texteuro45.00}{}{}%
+%\DTLdecimaltocurrency{267.5}{\price}\price
+%\end{verbatim}
+%will produce:
+%\DTLifcurrency{\texteuro45.00}{}{}\relax
+%\DTLdecimaltocurrency{267.5}{\price}\price. This is because
+%the last currency symbol to be encountered was \cs{texteuro}.
+%You can reset the currency symbol using the command:
+%\DescribeMacro{\DTLsetdefaultcurrency}
+%\begin{definition}
+%\cs{DTLsetdefaultcurrency}\marg{symbol}
+%\end{definition}
+%For example:
+%\begin{verbatim}
+%\DTLsetdefaultcurrency{\textyen}%
+%\DTLdecimaltocurrency{267.5}{\price}\price
+%\end{verbatim}
+%will produce:
+%\DTLsetdefaultcurrency{\textyen}\relax
+%\DTLdecimaltocurrency{267.5}{\price}\price
+%
+%The \sty{datatool} package provides convenience commands which
+%use \cs{DTLconverttodecimal}, and then use the basic macros provided
+%by the \sty{fp} package. The resulting value is then converted
+%back into the locale format using
+%\cs{DTLdecimaltolocale} or \cs{DTLdecimaltocurrency}.
+%
+%\DescribeMacro{\DTLadd}
+%\begin{definition}
+%\cs{DTLadd}\marg{cmd}\marg{num1}\marg{num2}
+%\end{definition}
+%\DescribeMacro{\DTLgadd}
+%\begin{definition}
+%\cs{DTLgadd}\marg{cmd}\marg{num1}\marg{num2}
+%\end{definition}
+%This sets the control sequence \meta{cmd} to \meta{num1}+\meta{num2}.
+%\cs{DLTadd} sets \meta{cmd} locally, while \cs{DTLgadd} sets
+%\meta{cmd} globally.
+%
+%For example:
+%\begin{verbatim}
+%\DTLadd{\result}{3,562.65}{412.2}\result
+%\end{verbatim}
+%will produce:
+%\DTLadd{\result}{3,562.65}{412.2}\result. Since
+%\cs{DTLconverttodecimal} can also convert currency, you can
+%also add prices. For example:
+%\begin{verbatim}
+%\DTLadd{\result}{\pounds3,562.65}{\pounds452.2}\result
+%\end{verbatim}
+%produces:
+%\DTLadd{\result}{\pounds3,562.65}{\pounds452.2}\result.
+%
+%Note that \sty{datatool} isn't aware of exchange rates! If you
+%use different currency symbols, the last symbol will be used.
+%For example
+%\begin{verbatim}
+%\DTLadd{\result}{\pounds3,562.65}{\euro452.2}\result
+%\end{verbatim}
+%produces:
+%\DTLadd{\result}{\pounds3,562.65}{\euro452.2}\result.
+%
+%Likewise, if one value is a number and the other is a currency,
+%the type of the last value, \meta{num2}, will be used for the
+%result. For example:
+%\begin{verbatim}
+%\DTLadd{\result}{3,562.65}{\$452.2}\result
+%\end{verbatim}
+%produces:
+%\DTLadd{\result}{3,562.65}{\$452.2}\result.
+%
+%\DescribeMacro{\DTLaddall}
+%\begin{definition}
+%\cs{DTLaddall}\marg{cmd}\marg{number list}
+%\end{definition}
+%\DescribeMacro{\DTLgaddall}
+%\begin{definition}
+%\cs{DTLgaddall}\marg{cmd}\marg{number list}
+%\end{definition}
+%This sets the control sequence \meta{cmd} to the sum of all
+%the numbers in \meta{number list}.
+%\cs{DLTaddall} sets \meta{cmd} locally, while \cs{DTLgaddall} sets
+%\meta{cmd} globally. Example:
+%\begin{verbatim}
+%\DTLaddall{\total}{25.1,45.2,35.6}\total
+%\end{verbatim}
+%produces:
+%\DTLaddall{\total}{25.1,45.2,35.6}\total.
+%Note that if any of the numbers in \meta{number list} contain
+%a comma, you must group the number. Example:
+%\begin{verbatim}
+%\DTLaddall{\total}{{1,525},{2,340},500}\total
+%\end{verbatim}
+%produces:
+%\DTLaddall{\total}{{1,525},{2,340},500}\total.
+%
+%\DescribeMacro{\DTLsub}
+%\begin{definition}
+%\cs{DTLsub}\marg{cmd}\marg{num1}\marg{num2}
+%\end{definition}
+%\DescribeMacro{\DTLgsub}
+%\begin{definition}
+%\cs{DTLgsub}\marg{cmd}\marg{num1}\marg{num2}
+%\end{definition}
+%This sets the control sequence \meta{cmd} to
+%\meta{num1}$-$\meta{num2}.
+%\cs{DLTsub} sets \meta{cmd} locally, while \cs{DTLgsub} sets
+%\meta{cmd} globally.
+%
+%For example:
+%\begin{verbatim}
+%\DTLsub{\result}{3,562.65}{412.2}\result
+%\end{verbatim}
+%will produce:
+%\DTLsub{\result}{3,562.65}{412.2}\result. As with \cs{DTLadd},
+%\meta{num1} and \meta{num2} may be currency.
+%
+%\DescribeMacro{\DTLmul}
+%\begin{definition}
+%\cs{DTLmul}\marg{cmd}\marg{num1}\marg{num2}
+%\end{definition}
+%\DescribeMacro{\DTLgmul}
+%\begin{definition}
+%\cs{DTLgmul}\marg{cmd}\marg{num1}\marg{num2}
+%\end{definition}
+%This sets the control sequence \meta{cmd} to
+%\meta{num1}$\times$\meta{num2}.
+%\cs{DLTmul} sets \meta{cmd} locally, while \cs{DTLgmul} sets
+%\meta{cmd} globally.
+%
+%For example:
+%\begin{verbatim}
+%\DTLmul{\result}{568.95}{2}\result
+%\end{verbatim}
+%will produce:
+%\DTLmul{\result}{568.95}{2}\result. Again, \meta{num1} or
+%\meta{num2} may be currency, but unlike \cs{DTLadd} and \cs{DTLsub},
+%currency overrides integer/real. For example:
+%\begin{verbatim}
+%\DTLmul{\result}{\pounds568.95}{2}\result
+%\end{verbatim}
+%will produce:
+%\DTLmul{\result}{\pounds568.95}{2}\result. Likewise,
+%\begin{verbatim}
+%\DTLmul{\result}{2}{\pounds568.95}\result
+%\end{verbatim}
+%will produce:
+%\DTLmul{\result}{2}{\pounds568.95}\result. Although it doesn't make
+%sense to multiply two currencies, \sty{datatool} will allow
+%\begin{verbatim}
+%\DTLmul{\result}{\$2}{\pounds568.95}\result
+%\end{verbatim}
+%which will produce:
+%\DTLmul{\result}{\$2}{\pounds568.95}\result.
+%
+%\DescribeMacro{\DTLdiv}
+%\begin{definition}
+%\cs{DTLdiv}\marg{cmd}\marg{num1}\marg{num2}
+%\end{definition}
+%\DescribeMacro{\DTLgdiv}
+%\begin{definition}
+%\cs{DTLgdiv}\marg{cmd}\marg{num1}\marg{num2}
+%\end{definition}
+%This sets the control sequence \meta{cmd} to
+%\meta{num1}$\div$\meta{num2}.
+%\cs{DLTdiv} sets \meta{cmd} locally, while \cs{DTLgdiv} sets
+%\meta{cmd} globally.
+%
+%For example:
+%\begin{verbatim}
+%\DTLdiv{\result}{501}{2}\result
+%\end{verbatim}
+%will produce:
+%\DTLdiv{\result}{501}{2}\result. Again, \meta{num1} or \meta{num2}
+%may be currency, but the resulting type will be not be a currency
+%if both \meta{num1} and \meta{num2} use the same currency symbol.
+%For example:
+%\begin{verbatim}
+%\DTLdiv{\result}{\$501}{\$2}\result
+%\end{verbatim}
+%will produce:
+%\DTLdiv{\result}{\$501}{\$2}\result. Whereas
+%\begin{verbatim}
+%\DTLdiv{\result}{\$501}{2}\result
+%\end{verbatim}
+%will produce:
+%\DTLdiv{\result}{\$501}{2}\result.
+%
+%\DescribeMacro{\DTLabs}
+%\begin{definition}
+%\cs{DTLabs}\marg{cmd}\marg{num}
+%\end{definition}
+%\DescribeMacro{\DTLgabs}
+%\begin{definition}
+%\cs{DTLgabs}\marg{cmd}\marg{num}
+%\end{definition}
+%This sets \meta{cmd} to the absolute value of \meta{num}.
+%\cs{DLTabs} sets \meta{cmd} locally, while \cs{DTLgabs} sets
+%\meta{cmd} globally. Example:
+%\begin{verbatim}
+%\DTLabs{\result}{-\pounds2.50}\result
+%\end{verbatim}
+%produces:
+%\DTLabs{\result}{-\pounds2.50}\result.
+%
+%\DescribeMacro{\DTLneg}
+%\begin{definition}
+%\cs{DTLneg}\marg{cmd}\marg{num}
+%\end{definition}
+%\DescribeMacro{\DTLgneg}
+%\begin{definition}
+%\cs{DTLgneg}\marg{cmd}\marg{num}
+%\end{definition}
+%This sets \meta{cmd} to the negative of \meta{num}.
+%\cs{DLTneg} sets \meta{cmd} locally, while \cs{DTLgneg} sets
+%\meta{cmd} globally. Example:
+%\begin{verbatim}
+%\DTLneg{\result}{\pounds2.50}\result
+%\end{verbatim}
+%produces:
+%\DTLneg{\result}{\pounds2.50}\result.
+%
+%\DescribeMacro{\DTLsqrt}
+%\begin{definition}
+%\cs{DTLsqrt}\marg{cmd}\marg{num}
+%\end{definition}
+%\DescribeMacro{\DTLgsqrt}
+%\begin{definition}
+%\cs{DTLgsqrt}\marg{cmd}\marg{num}
+%\end{definition}
+%This sets \meta{cmd} to the sqrt root of \meta{num}.
+%\cs{DLTsqrt} sets \meta{cmd} locally, while \cs{DTLgsqrt} sets
+%\meta{cmd} globally. Example:
+%\begin{verbatim}
+%\DTLsqrt{\result}{2}\result
+%\end{verbatim}
+%produces:
+%\DTLsqrt{\result}{2}\result.
+%
+%\DescribeMacro{\DTLmin}
+%\begin{definition}
+%\cs{DTLmin}\marg{cmd}\marg{num1}\marg{num2}
+%\end{definition}
+%\DescribeMacro{\DTLgmin}
+%\begin{definition}
+%\cs{DTLgmin}\marg{cmd}\marg{num1}\marg{num2}
+%\end{definition}
+%This sets the control sequence \meta{cmd} to the minimum of
+%\meta{num1} and \meta{num2}.
+%\cs{DLTmin} sets \meta{cmd} locally, while \cs{DTLgmin} sets
+%\meta{cmd} globally. For example:
+%\begin{verbatim}
+%\DTLmin{\result}{256}{32}\result
+%\end{verbatim}
+%produces:
+%\DTLmin{\result}{256}{32}\result.
+%Again, \meta{num1} and \meta{num2} may
+%be currency. For example:
+%\begin{verbatim}
+%\DTLmin{\result}{256}{\pounds32}\result
+%\end{verbatim}
+%produces:
+%\DTLmin{\result}{256}{\pounds32}\result, whereas
+%\begin{verbatim}
+%\DTLmin{\result}{\pounds256}{32}\result
+%\end{verbatim}
+%produces:
+%\DTLmin{\result}{\pounds256}{32}\result. As mentioned above,
+%\sty{datatool} doesn't know about exchange rates, so be careful
+%about mixing currencies. For example:
+%\begin{verbatim}
+%\DTLmin{\result}{\pounds5}{\$6}\result
+%\end{verbatim}
+%produces:
+%\DTLmin{\result}{\pounds5}{\$6}\result, which may not necessarily
+%be true!
+%
+%\DescribeMacro{\DTLminall}
+%\begin{definition}
+%\cs{DTLminall}\marg{cmd}\marg{number list}
+%\end{definition}
+%\DescribeMacro{\DTLgminall}
+%\begin{definition}
+%\cs{DTLgminall}\marg{cmd}\marg{number list}
+%\end{definition}
+%This sets the control sequence \meta{cmd} to the minimum of all
+%the numbers in \meta{number list}.
+%\cs{DLTminall} sets \meta{cmd} locally, while \cs{DTLgminall} sets
+%\meta{cmd} globally. Example:
+%\begin{verbatim}
+%\DTLminall{\theMin}{25.1,45.2,35.6}\theMin
+%\end{verbatim}
+%produces:
+%\DTLminall{\theMin}{25.1,45.2,35.6}\theMin.
+%Note that if any of the numbers in \meta{number list} contain
+%a comma, you must group the number. Example:
+%\begin{verbatim}
+%\DTLminall{\theMin}{{1,525},{2,340},500}\theMin
+%\end{verbatim}
+%produces:
+%\DTLminall{\theMin}{{1,525},{2,340},500}\theMin.
+%
+%\DescribeMacro{\DTLmax}
+%\begin{definition}
+%\cs{DTLmax}\marg{cmd}\marg{num1}\marg{num2}
+%\end{definition}
+%\DescribeMacro{\DTLgmax}
+%\begin{definition}
+%\cs{DTLgmax}\marg{cmd}\marg{num1}\marg{num2}
+%\end{definition}
+%This sets the control sequence \meta{cmd} to the maximum of
+%\meta{num1} and \meta{num2}.
+%\cs{DLTmax} sets \meta{cmd} locally, while \cs{DTLgmax} sets
+%\meta{cmd} globally. For example:
+%\begin{verbatim}
+%\DTLmax{\result}{256}{32}\result
+%\end{verbatim}
+%produces:
+%\DTLmax{\result}{256}{32}\result.
+%Again, \meta{num1} and \meta{num2} may
+%be currency, but the same warnings for \cs{DTLmin} apply.
+%
+%\DescribeMacro{\DTLmaxall}
+%\begin{definition}
+%\cs{DTLmaxall}\marg{cmd}\marg{number list}
+%\end{definition}
+%\DescribeMacro{\DTLgmaxall}
+%\begin{definition}
+%\cs{DTLgmaxall}\marg{cmd}\marg{number list}
+%\end{definition}
+%This sets the control sequence \meta{cmd} to the maximum of all
+%the numbers in \meta{number list}.
+%\cs{DLTmaxall} sets \meta{cmd} locally, while \cs{DTLgmaxall} sets
+%\meta{cmd} globally. Example:
+%\begin{verbatim}
+%\DTLmaxall{\theMax}{25.1,45.2,35.6}\theMax
+%\end{verbatim}
+%produces:
+%\DTLmaxall{\theMax}{25.1,45.2,35.6}\theMax.
+%Note that if any of the numbers in \meta{number list} contain
+%a comma, you must group the number. Example:
+%\begin{verbatim}
+%\DTLmaxall{\theMax}{{1,525},{2,340},500}\theMax
+%\end{verbatim}
+%produces:
+%\DTLmaxall{\theMax}{{1,525},{2,340},500}\theMax.
+%
+%\DescribeMacro{\DTLmeanforall}
+%\begin{definition}
+%\cs{DTLmeanforall}\marg{cmd}\marg{number list}
+%\end{definition}
+%\DescribeMacro{\DTLgmeanall}
+%\begin{definition}
+%\cs{DTLgmeanforall}\marg{cmd}\marg{number list}
+%\end{definition}
+%This sets the control sequence \meta{cmd} to the arithmetic mean of all
+%the numbers in \meta{number list}.
+%\cs{DLTmeanforall} sets \meta{cmd} locally, while \cs{DTLgmeanforall} sets
+%\meta{cmd} globally. Example:
+%\begin{verbatim}
+%\DTLmeanforall{\theMean}{25.1,45.2,35.6}\theMean
+%\end{verbatim}
+%produces:
+%\DTLmeanforall{\theMean}{25.1,45.2,35.6}\theMean.
+%Note that if any of the numbers in \meta{number list} contain
+%a comma, you must group the number. Example:
+%\begin{verbatim}
+%\DTLmeanforall{\theMean}{{1,525},{2,340},500}\theMean
+%\end{verbatim}
+%produces:
+%\DTLmeanforall{\theMean}{{1,525},{2,340},500}\theMean.
+%
+%\DescribeMacro{\DTLvarianceforall}
+%\begin{definition}
+%\cs{DTLvarianceforall}\marg{cmd}\marg{number list}
+%\end{definition}
+%\DescribeMacro{\DTLgvarianceforall}
+%\begin{definition}
+%\cs{DTLgvarianceforall}\marg{cmd}\marg{number list}
+%\end{definition}
+%This sets the control sequence \meta{cmd} to the variance of all
+%the numbers in \meta{number list}.
+%\cs{DLTvarianceforall} sets \meta{cmd} locally, while \cs{DTLgvarianceforall} sets
+%\meta{cmd} globally. Example:
+%\begin{verbatim}
+%\DTLvarianceforall{\theVar}{25.1,45.2,35.6}\theVar
+%\end{verbatim}
+%produces:
+%\DTLvarianceforall{\theVar}{25.1,45.2,35.6}\theVar.
+%Again note that if any of the numbers in \meta{number list}
+%contain a comma, you must group the number.
+%
+%\DescribeMacro{\DTLsdforall}
+%\begin{definition}
+%\cs{DTLsdforall}\marg{cmd}\marg{number list}
+%\end{definition}
+%\DescribeMacro{\DTLgsdforall}
+%\begin{definition}
+%\cs{DTLgsdforall}\marg{cmd}\marg{number list}
+%\end{definition}
+%This sets the control sequence \meta{cmd} to the standard deviation of all
+%the numbers in \meta{number list}.
+%\cs{DLTsdforall} sets \meta{cmd} locally, while \cs{DTLgsdforall} sets
+%\meta{cmd} globally. Example:
+%\begin{verbatim}
+%\DTLsdforall{\theSD}{25.1,45.2,35.6}\theSD
+%\end{verbatim}
+%produces:
+%\DTLsdforall{\theSD}{25.1,45.2,35.6}\theSD.
+%Note that if any of the numbers in \meta{number list} contain
+%a comma, you must group the number. Example:
+%\begin{verbatim}
+%\DTLsdforall{\theSD}{{1,525},{2,340},500}\theSD
+%\end{verbatim}
+%produces:
+%\DTLsdforall{\theSD}{{1,525},{2,340},500}\theSD.
+%
+%\DescribeMacro{\DTLround}
+%\begin{definition}
+%\cs{DTLround}\marg{cmd}\marg{num}\marg{num digits}
+%\end{definition}
+%\DescribeMacro{\DTLground}
+%\begin{definition}
+%\cs{DTLground}\marg{cmd}\marg{num}\marg{num digits}
+%\end{definition}
+%This sets \meta{cmd} to \meta{num} rounded to \meta{num digits}
+%after the decimal character.
+%\cs{DLTround} sets \meta{cmd} locally, while \cs{DTLground} sets
+%\meta{cmd} globally.
+%
+%\DescribeMacro{\DTLtrunc}
+%\begin{definition}
+%\cs{DTLtrunc}\marg{cmd}\marg{num}\marg{num digits}
+%\end{definition}
+%\DescribeMacro{\DTLgtrunc}
+%\begin{definition}
+%\cs{DTLgtrunc}\marg{cmd}\marg{num}\marg{num digits}
+%\end{definition}
+%This sets \meta{cmd} to \meta{num} truncated to \meta{num digits}
+%after the decimal character.
+%\cs{DLTtrunc} sets \meta{cmd} locally, while \cs{DTLgtrunc} sets
+%\meta{cmd} globally.
+%
+%\DescribeMacro{\DTLclip}
+%\begin{definition}
+%\cs{DTLclip}\marg{cmd}\marg{num}
+%\end{definition}
+%\DescribeMacro{\DTLgclip}
+%\begin{definition}
+%\cs{DTLgclip}\marg{cmd}\marg{num}
+%\end{definition}
+%This sets \meta{cmd} to \meta{num} with all unnecessary 0's
+%removed.
+%\cs{DLTclip} sets \meta{cmd} locally, while \cs{DTLgclip} sets
+%\meta{cmd} globally.
+%
+%\section{Strings}
+%
+%Strings are considered to be anything non-numerical. The
+%\sty{datatool} package loads the \sty{substr} package, so
+%you can use the commands defined in that package to determine
+%if one string is contained in another string. In addition,
+%the \sty{datatool} provides the following macros:
+%
+%\DescribeMacro{\DTLinitials}
+%\begin{definition}
+%\cs{DTLinitials}\marg{string}
+%\end{definition}
+%This converts \meta{string} (typically a name) into initials.
+%For example:
+%\begin{verbatim}
+%\DTLinitials{Mary Ann}
+%\end{verbatim}
+%produces:
+%\DTLinitials{Mary Ann}. Note that
+%\begin{verbatim}
+%\DTLinitials{Mary-Ann}
+%\end{verbatim}
+%produces:
+%\DTLinitials{Mary-Ann}.
+%
+%\DescribeMacro{\DTLstoreinitials}
+%\begin{definition}
+%\cs{DTLstoreinitials}\marg{string}\marg{cmd}
+%\end{definition}
+%This converts \meta{string} into initials and stores the
+%result in \meta{cmd}.
+%
+%The above commands rely on the following to format the
+%initials:
+%\DescribeMacro{\DTLafterinitials}
+%\begin{definition}
+%\cs{DTLafterinitials}
+%\end{definition}
+%This indicates what to do at the end of the initials. This
+%simply does a full stop by default.
+%
+%\DescribeMacro{\DTLbetweeninitials}
+%\begin{definition}
+%\cs{DTLbetweeninitials}
+%\end{definition}
+%This indicates what to do between initials. This does a
+%full stop followed by a space by default.
+%
+%\DescribeMacro{\DTLafterinitialbeforehyphen}
+%\begin{definition}
+%\cs{DTLafterinitialbeforehyphen}
+%\end{definition}
+%This indicates what to do between an initial and a hyphen.
+%This simply does a full stop by default.
+%
+%\section{Databases}
+%\label{sec:databases}
+%
+%The \sty{datatool} package provides a means of creating and
+%loading databases. Once a database has been created (or loaded),
+%it is possible to iterate through each row of data, to make it
+%easier to perform repetitive actions, such as mail merging.
+%
+%\subsection{Creating a New Database}
+%\label{sec:newdb}
+%
+%\DescribeMacro{\DTLnewdb}
+%\begin{definition}
+%\cs{DTLnewdb}\marg{db name}
+%\end{definition}
+%This command creates a new empty database called \meta{db name}. You
+%can test if a database is empty using:
+%\DescribeMacro{\DTLifdbempty}
+%\begin{definition}
+%\cs{DTLifdbempty}\marg{db name}\marg{true part}\marg{false part}
+%\end{definition}
+%If the database called \meta{db name} is empty, do \meta{true part},
+%otherwise do \meta{false part}.
+%
+%\DescribeMacro{\DTLrowcount}
+%\begin{definition}
+%\cs{DTLrowcount}\marg{db name}
+%\end{definition}
+%This command displays the number of rows in the database called
+%\meta{db name}.
+%
+%\DescribeMacro{\DTLnewrow}
+%\begin{definition}
+%\cs{DTLnewrow}\marg{db name}
+%\end{definition}
+%This command starts a new row in the database called \meta{db name}.
+%This new row becomes the current row when adding new entries.
+%
+%For example, the following creates an empty database called
+%\texttt{mydata}:
+%\begin{verbatim}
+%\DTLnewdb{mydata}
+%\end{verbatim}
+%\DTLnewdb{mydata}\relax
+%The following tests if the database is empty:
+%\begin{verbatim}
+%\DTLifdbempty{mydata}{empty}{not empty}!
+%\end{verbatim}
+%This produces:
+%\DTLifdbempty{mydata}{empty}{not empty}!
+%
+%The following adds an empty row to the database, this is the
+%first row of the database:
+%\begin{verbatim}
+%\DTLnewrow{mydata}
+%\end{verbatim}
+%\DTLnewrow{mydata}\relax
+%Note that even though the only row in the database is currently
+%empty, the database is no longer considered to be empty:
+%\begin{verbatim}
+%\DTLifdbempty{mydata}{empty}{not empty}!
+%\end{verbatim}
+%This now produces:
+%\DTLifdbempty{mydata}{empty}{not empty}! The row count is
+%given by
+%\begin{verbatim}
+%\DTLrowcount{mydata}
+%\end{verbatim}
+%which produces:
+%\DTLrowcount{mydata}.
+%
+%\DescribeMacro{\DTLnewdbentry}
+%\begin{definition}
+%\cs{DTLnewdbentry}\marg{db name}\marg{key}\marg{value}
+%\end{definition}
+%This creates a new entry with the identifier \meta{key} whose value
+%is \meta{value} and adds it to the current row of the database
+%called \meta{db name}. For example:
+%\begin{verbatim}
+%\DTLnewdbentry{mydata}{Surname}{Smith}
+%\DTLnewdbentry{mydata}{FirstName}{John}
+%\end{verbatim}
+%Adds an entry with identifier \texttt{Surname} and value
+%\texttt{Smith} to the current row of the database named
+%\texttt{mydata}, and then adds an entry with identifier
+%\texttt{FirstName} and value \texttt{John}.
+%
+%Note that database entries can't contain paragraph breaks as
+%many of the macros used by \sty{datatool} are short commands.
+%If you do need a paragraph break in an entry, you can instead
+%use the command:
+%\DescribeMacro{\DTLpar}
+%\begin{definition}
+%\cs{DTLpar}
+%\end{definition}
+%
+%\subsection{Loading a Database from an External ASCII File}
+%\label{sec:loaddb}
+%
+%Instead of using the commands described in \autoref{sec:newdb}
+%to create a new database, you can load a database from an
+%external ASCII file using:
+%\DescribeMacro{\DTLloaddb}
+%\begin{definition}
+%\cs{DTLloaddb}\marg{db name}\marg{filename}
+%\end{definition}
+%This creates a new database called \meta{db name}, and fills
+%it with the entries given in the file \meta{filename}.
+%The filename must have a header row at the start of the file,
+%which provides the \meta{key} when creating a new database entry
+%using \ics{DTLnewdbentry}. By default, the entries in the database
+%must be separated by a comma, and optionally delimited by the
+%double quote character (\verb|"|). The separator can be changed
+%to a tab separator using the command:
+%\DescribeMacro{\DTLsettabseparator}
+%\begin{definition}
+%\cs{DTLsettabseparator}
+%\end{definition}
+%To set the separator to a character other than a tab, you need to use
+%\DescribeMacro{\DTLsetseparator}
+%\begin{definition}
+%\cs{DTLsetseparator}\marg{character}
+%\end{definition}
+%The delimiter can be changed using
+%\DescribeMacro{\DTLsetdelimiter}
+%\begin{definition}
+%\cs{DTLsetdelimiter}\marg{character}
+%\end{definition}
+%
+%For example, suppose you have a file called \texttt{mydata.csv}
+%which contains the following:
+%\begin{verbatim}
+%FirstName,Surname,Score
+%John,"Smith, Jr",68
+%Jane,Brown,75
+%Andy,Brown,42
+%Z\"oe,Adams,52
+%\end{verbatim}
+%then
+%\begin{verbatim}
+%\DTLloaddb{mydata}{mydata.csv}
+%\end{verbatim}
+%is equivalent to:
+%\begin{verbatim}
+%\DTLnewdb{mydata}
+%\DTLnewrow{mydata}%
+%\DTLnewdbentry{mydata}{FirstName}{John}%
+%\DTLnewdbentry{mydata}{Surname}{Smith, Jr}%
+%\DTLnewdbentry{mydata}{Score}{68}%
+%\DTLnewrow{mydata}%
+%\DTLnewdbentry{mydata}{FirstName}{Jane}%
+%\DTLnewdbentry{mydata}{Surname}{Brown}%
+%\DTLnewdbentry{mydata}{Score}{75}%
+%\DTLnewrow{mydata}%
+%\DTLnewdbentry{mydata}{FirstName}{Andy}%
+%\DTLnewdbentry{mydata}{Surname}{Brown}%
+%\DTLnewdbentry{mydata}{Score}{42}%
+%\DTLnewrow{mydata}%
+%\DTLnewdbentry{mydata}{FirstName}{Z\"oe}%
+%\DTLnewdbentry{mydata}{Score}{52}%
+%\DTLnewdbentry{mydata}{Surname}{Adams}%
+%\end{verbatim}
+%Note that the entry \texttt{Smith, Jr} had to be delimited in
+%\texttt{mydata.csv} using the double quote character since it
+%contained a comma which is used as the separator.
+%
+%The file used in the above example contained a \LaTeX\ command,
+%namely \verb|\"|. When using \ics{DTLloaddb} all the special
+%characters that appear in the command retain their \LaTeX\ meaning
+%when the file is loaded. It is likely however that the data file
+%may have been created by another application that is not \TeX-aware,
+%for example a spreadsheet application. For example, suppose you
+%have a file called, say, \texttt{products.csv} which looks
+%like:
+%\begin{verbatim}
+%Product,Cost
+%Fruit & Veg,$1.25
+%Stationary,$0.80
+%\end{verbatim}
+%This file contains two of \TeX's special characters, namely
+%"&" and \verb|$|. In this case, if you try to load the file
+%using \ics{DTLloaddb}, you will encounter errors. Instead you
+%can use:
+%\DescribeMacro{\DTLloadrawdb}
+%\begin{definition}
+%\cs{DTLloadrawdb}\marg{db name}\marg{filename}
+%\end{definition}
+%This is the same as \ics{DTLloaddb} except that it maps nine of
+%the ten special characters onto commands that produce that
+%symbol. The only character that retains its active state is the
+%backslash character, so you will still need to check the file
+%for backslash characters. The mappings used are listed in
+%\autoref{tab:rawmappings}. So using the file \texttt{products.csv},
+%as described above,
+%\begin{verbatim}
+%\DTLloadrawdb{mydata}{products.csv}
+%\end{verbatim}
+%is equivalent to:
+%\begin{verbatim}
+%\DTLnewdb{mydata}
+%\DTLnewrow{mydata}%
+%\DTLnewdbentry{mydata}{Product}{Fruit \& Veg}%
+%\DTLnewdbentry{mydata}{Cost}{\$1.25}%
+%\DTLnewrow{mydata}%
+%\DTLnewdbentry{mydata}{Product}{Stationary}%
+%\DTLnewdbentry{mydata}{Cost}{\$0.80}%
+%\end{verbatim}
+%
+%\begin{table}[htbp]
+%\caption{Special character mappings used by \cs{DTLloadrawdb}
+%(note that the backslash retains its active state)}
+%\label{tab:rawmappings}
+%\begin{center}
+%\begin{tabular}{ll}
+%Character & Mapping\\
+%\verb|%| & \verb|\%|\\
+%\verb|$| & \verb|\$|\\
+%\verb|&| & \verb|\&|\\
+%\verb|#| & \verb|\#|\\
+%\verb|_| & \verb|\_|\\
+%\verb|{| & \verb|\{|\\
+%\verb|}| & \verb|\}|\\
+%\verb|~| & \cs{textasciitilde}\\
+%\verb|^| & \cs{textasciicircum}
+%\end{tabular}
+%\end{center}
+%\end{table}
+%
+%It may be that there are other characters that require mapping.
+%For example, the file \texttt{products.csv} may instead look like:\par
+%\vskip\baselineskip
+%\begin{ttfamily}\obeylines\setlength{\parindent}{0pt}
+%Product,Cost
+%Fruit \& Veg,\pounds1.25
+%Stationary,\pounds0.80
+%\end{ttfamily}
+%\vskip\baselineskip
+%The pound character is not an internationally standard keyboard
+%character, and does not achieve the desired effect when used
+%in a \LaTeX\ document. It will therefore be necessary to convert
+%this symbol to an appropriate control sequence. This can be done
+%using the command:
+%\DescribeMacro{\DTLrawmap}
+%\begin{definition}
+%\cs{DTLrawmap}\marg{string}\marg{replacement}
+%\end{definition}
+%For example:\par
+%\vskip\baselineskip
+%\begin{ttfamily}\obeylines\setlength{\parindent}{0pt}
+%\cs{DTLrawmap}\char`\{\pounds\char`\}\char`\{\cs{pounds}\char`\}
+%\end{ttfamily}
+%\vskip\baselineskip\noindent
+%will convert all occurrences\footnote{in the \LaTeX\ database, not
+%in the data file itself!} of \texttt{\pounds} with \cs{pounds}.
+%
+%Note that the warning in the previous section about no paragraph
+%breaks in an entry also applies to entries loaded from a database.
+%If you do need a paragraph break, use \ics{DTLpar} instead of
+%\cs{par}, but remember that each row of data in an external data file
+%must not have a line break.
+%
+%\subsection{Iterating Through a Database}
+%\label{sec:dbforeach}
+%
+%Once you have created a database, either loading it from an
+%external file, as described in \autoref{sec:loaddb}, or using the
+%commands described in \autoref{sec:newdb}, you can then iterate
+%through each row of the database and access elements in that row.
+%
+%\DescribeMacro{\DTLforeach}
+%\begin{definition}
+%\cs{DTLforeach}\oarg{condition}\marg{db name}\marg{values}\marg{text}
+%\end{definition}
+%This will iterate through each row of the database called
+%\meta{db name}, applying \meta{text} to each row of the database
+%where \meta{condition} is met. The argument \meta{values} is a
+%comma separated list of \meta{cmd}"="\meta{key} pairs. At the
+%start of each row, each command \meta{cmd} in the \meta{values}
+%list will be set to the value of the entry given by \meta{key}.
+%These commands may then be used in \meta{text}.
+%Note that this assignment is done globally to ensure that
+%\cs{DLTforeach} works correctly in a \env{tabular} environment.
+%Since you may want to use the same set of commands in a later
+%\cs{DTLforeach}, the commands are not checked to determine if they
+%already exist. It is therefore important that you check you
+%are not using an existing command whose value should not be changed.
+%
+%The optional argument \meta{condition} is a condition in the
+%form allowed by \cs{ifthenelse}. This includes the commands
+%provided by the \sty{ifthen} package, as well as the commands
+%described in \autoref{sec:ifthen}. The default value of
+%\meta{condition} is "\boolean{true}".
+%
+%\begin{example}{Student scores}{ex:scores}
+%Suppose you have a data file called \texttt{studentscores.csv} that
+%contains the following:
+%\begin{verbatim}
+%FirstName,Surname,StudentNo,Score
+%John,"Smith, Jr",102689,68
+%Jane,Brown,102647,75
+%Andy,Brown,103569,42
+%Z\"oe,Adams,105987,52
+%Roger,Brady,106872,58
+%Clare,Verdon,104356,45
+%\end{verbatim}
+%\DTLnewdb{scores}\relax
+%\DTLnewrow{scores}\relax
+%\DTLnewdbentry{scores}{FirstName}{John}\relax
+%\DTLnewdbentry{scores}{Surname}{Smith, Jr}\relax
+%\DTLnewdbentry{scores}{StudentNo}{102689}\relax
+%\DTLnewdbentry{scores}{Score}{68}\relax
+%\DTLnewrow{scores}\relax
+%\DTLnewdbentry{scores}{FirstName}{Jane}\relax
+%\DTLnewdbentry{scores}{Surname}{Brown}\relax
+%\DTLnewdbentry{scores}{StudentNo}{102647}\relax
+%\DTLnewdbentry{scores}{Score}{75}\relax
+%\DTLnewrow{scores}\relax
+%\DTLnewdbentry{scores}{FirstName}{Andy}\relax
+%\DTLnewdbentry{scores}{Surname}{Brown}\relax
+%\DTLnewdbentry{scores}{StudentNo}{103569}\relax
+%\DTLnewdbentry{scores}{Score}{42}\relax
+%\DTLnewrow{scores}\relax
+%\DTLnewdbentry{scores}{FirstName}{Z\"oe}\relax
+%\DTLnewdbentry{scores}{Score}{52}\relax
+%\DTLnewdbentry{scores}{StudentNo}{105987}\relax
+%\DTLnewdbentry{scores}{Surname}{Adams}\relax
+%\DTLnewrow{scores}\relax
+%\DTLnewdbentry{scores}{FirstName}{Roger}\relax
+%\DTLnewdbentry{scores}{Score}{58}\relax
+%\DTLnewdbentry{scores}{StudentNo}{106872}\relax
+%\DTLnewdbentry{scores}{Surname}{Brady}\relax
+%\DTLnewrow{scores}\relax
+%\DTLnewdbentry{scores}{FirstName}{Clare}\relax
+%\DTLnewdbentry{scores}{Score}{45}\relax
+%\DTLnewdbentry{scores}{StudentNo}{104356}\relax
+%\DTLnewdbentry{scores}{Surname}{Verdon}\relax
+%and you load the data into a database called "scores" using:
+%\begin{verbatim}
+%\DTLloaddb{scores}{studentscores.csv}
+%\end{verbatim}
+%you can then display the database in a table as follows:
+%\begin{verbatim}
+%\begin{table}[htbp]
+%\caption{Student Scores}\label{tab:scores}
+%\centering
+%\begin{tabular}{llr}
+%\bfseries First Name &
+%\bfseries Surname &
+%\bfseries Score (\%)%
+%\DTLforeach{scores}{%
+%\firstname=FirstName,\surname=Surname,\score=Score}{%
+%\\
+%\firstname & \surname & \score}
+%\end{tabular}
+%\end{table}
+%\end{verbatim}
+%This produces \autoref{tab:scores}. (Note that since I didn't
+%need the student registration number, I didn't bother to
+%assign a command to the key "StudentNo".)
+%
+%\begin{table}[htbp]
+%\caption{Student Scores}\label{tab:scores}
+%\centering
+%\begin{tabular}{llr}
+%\bfseries First Name &
+%\bfseries Surname &
+%\bfseries Score (\%)\relax
+%\DTLforeach{scores}{\firstname=FirstName,\surname=Surname,\score=Score}{\relax
+%\\
+%\firstname & \surname & \score}
+%\end{tabular}
+%\end{table}
+%\end{example}
+%
+%The macro \ics{DTLforeach} may be nested up to three times. Each
+%level uses the corresponding counters:
+%\counterfmt{DTLrowi},
+%\counterfmt{DTLrowii} and
+%\counterfmt{DTLrowiii} that keep track of
+%the current row. Note that these counters are only incremented
+%when \meta{condition} is satisfied. These counters are incremented
+%using \cs{refstepcounter} before the start of \meta{text}, so they
+%may be referenced using \cs{label}, however remember that \cs{label}
+%references the last counter to be incremented using
+%\cs{refstepcounter} \emph{in the current scope}. The \cs{label}
+%should therefore be the first command in \meta{text} to ensure
+%that it references the current row counter.
+%
+%\DescribeMacro{\DTLcurrentindex}
+%\begin{definition}
+%\cs{DTLcurrentindex}
+%\end{definition}
+%At the start of each iteration, \cs{DTLcurrentindex} is set
+%to the arabic value of the current row counter.
+%
+%\begin{example}{Student Scores---Labelling}{ex:label}
+%In the previous example, the student scores, stored in the
+%database "scores" were placed in a table. In this example the
+%table will be modified slightly to number each student according
+%to the row. Suppose I also want to identify which row Jane Brown
+%is in, and reference it in the text. The easiest way to do this
+%is to construct a label on each row which uniquely identifies
+%that student. The label can't simply be constructed from the
+%surname, as there are two students with the same surname. In order
+%to create a unique label, I can either construct a label from
+%both the surname and the first name, or I can use the student's
+%registration number, or I can use the student's score, since all
+%the scores are unique. The former method will cause a problem since
+%one of the names (Z\"oe) contains an accent command. Although
+%the registration numbers are all unique, they are not particularly
+%memorable, so I shall instead use the scores.
+%\begin{verbatim}
+%\begin{table}[htbp]
+%\caption{Student Scores}\label{tab:scoreslab}
+%\centering
+%\begin{tabular}{cllc}
+%\bfseries Row &
+%\bfseries First Name &
+%\bfseries Surname &
+%\bfseries Score (\%)%
+%\DTLforeach{scores}{%
+%\firstname=FirstName,\surname=Surname,\score=Score}{%
+%\label{row:\score}\\\theDTLrowi &
+%\firstname & \surname & \score}%
+%\end{tabular}
+%\end{table}
+%
+%Jane Brown scored the highest (75\%), her score can be seen on
+%row~\ref{row:75}.
+%\end{verbatim}
+%This produces \autoref{tab:scoreslab} and the following text:
+%Jane Brown scored the highest (75\%), her score can be seen on
+%row~\ref*{row:75}.
+%
+%\textbf{Note:} the \cs{label} command is placed before
+%"\\" to ensure that it is in the same scope as the command
+%"\refstepcounter{DTLrowi}".
+%
+%\begin{table}[htbp]
+%\caption{Student Scores}\label{tab:scoreslab}
+%\centering
+%\begin{tabular}{cllc}
+%\bfseries Row &
+%\bfseries First Name &
+%\bfseries Surname &
+%\bfseries Score (\%)\relax
+%\DTLforeach{scores}{\firstname=FirstName,\surname=Surname,\score=Score}{\relax
+%\label{row:\score}\\\theDTLrowi &
+%\firstname & \surname & \score}\relax
+%\end{tabular}
+%\end{table}
+%\end{example}
+%
+%\DescribeMacro{\DTLsavelastrowcount}
+%\begin{definition}
+%\cs{DTLsavelastrowcount}\marg{cmd}
+%\end{definition}
+%This command will store the value of the row counter used in
+%the last occurrence of \ics{DTLforeach} in the control sequence
+%\meta{cmd}.
+%
+%\begin{example}{Filtering Rows}{ex:filter}
+%As mentioned earlier, the optional argument \meta{condition} of
+%\ics{DTLforeach} provides a means to exclude certain rows.
+%This example uses the database defined in \autoref{ex:scores},
+%but only displays the information for students whose marks are
+%above 60. At the end of the table, \cs{DTLsavelastrowcount}
+%is used to store the number of rows in the table. (Note that
+%\cs{DTLsavelastrowcount} is outside of \ics{DTLforeach}.)
+%\begin{verbatim}
+%\begin{table}[htbp]
+%\caption{Top Student Scores}\label{tab:topscores}
+%\centering
+%\begin{tabular}{llr}
+%\bfseries First Name &
+%\bfseries Surname &
+%\bfseries Score (\%)%
+%\DTLforeach[\DTLisgt{\score}{60}]{scores}{%
+%\firstname=FirstName,\surname=Surname,\score=Score}{%
+%\\
+%\firstname & \surname & \score}
+%\end{tabular}
+%
+%\DTLsavelastrowcount{\n}%
+%\n\ students scored above 60\%.
+%\end{table}
+%\end{verbatim}
+%This produces \autoref{tab:topscores}. Note that in this example,
+%I could have specified the condition as "\score>60" since all
+%the scores are integers, however, as it's possible that an entry
+%may feasibly have a decimal score I have used \ics{DTLisgt} instead.
+%
+%\begin{table}[htbp]
+%\caption{Top Student Scores}\label{tab:topscores}
+%\centering
+%\begin{tabular}{llr}
+%\bfseries First Name &
+%\bfseries Surname &
+%\bfseries Score (\%)\relax
+%\DTLforeach[\DTLisgt{\score}{60}]{scores}{\firstname=FirstName,\surname=Surname,\score=Score}{\relax
+%\\
+%\firstname & \surname & \score}
+%\end{tabular}
+%
+%\DTLsavelastrowcount{\n}\relax
+%\n\ students scored above 60\%.
+%\end{table}
+%
+%Suppose now, I only want to display the scores for students whose
+%surname begins with `B'. I can do this as follows:
+%\begin{verbatim}
+%\begin{table}[htbp]
+%\caption{Student Scores (B)}\label{tab:Bscores}
+%\centering
+%\begin{tabular}{llr}
+%\bfseries First Name &
+%\bfseries Surname &
+%\bfseries Score (\%)%
+%\DTLforeach[\DTLisgt{\surname}{B}\and\DTLislt{\surname}{C}]{scores}{%
+%\firstname=FirstName,\surname=Surname,\score=Score}{%
+%\\
+%\firstname & \surname & \score}
+%\end{tabular}
+%\end{table}
+%\end{verbatim}
+%This produces \autoref{tab:Bscores}.
+%
+%\begin{table}[htbp]
+%\caption{Student Scores (B)}\label{tab:Bscores}
+%\centering
+%\begin{tabular}{llr}
+%\bfseries First Name &
+%\bfseries Surname &
+%\bfseries Score (\%)\relax
+%\DTLforeach[\DTLisgt{\surname}{B}\and\DTLislt{\surname}{C}]{scores}
+%{\firstname=FirstName,\surname=Surname,\score=Score}{\relax
+%\\
+%\firstname & \surname & \score}
+%\end{tabular}
+%\end{table}
+%
+%\end{example}
+%
+%Within the body of \ics{DTLforeach} (i.e.\ within \meta{text})
+%the following conditionals may be used:
+%\DescribeMacro{\DTLiffirstrow}
+%\begin{definition}
+%\cs{DTLiffirstrow}\marg{true part}\marg{false part}
+%\end{definition}
+%If the current row is the first row, then do \meta{true part},
+%otherwise do \meta{false part}.
+%
+%\DescribeMacro{\DTLiflastrow}
+%\begin{definition}
+%\cs{DTLiflastrow}\marg{true part}\marg{false part}
+%\end{definition}
+%If the current row is the last row, then do \meta{true part},
+%otherwise do \meta{false part}.
+%
+%\DescribeMacro{\DTLifoddrow}
+%\begin{definition}
+%\cs{DTLifoddrow}\marg{true part}\marg{false part}
+%\end{definition}
+%If the current row number is an odd number, then do \meta{true part},
+%otherwise do \meta{false part}.
+%
+%\begin{example}{Stripy Tables}{ex:stripy}
+%This example uses the same database as in the previous examples.
+%It requires the \sty{colortbl} package, which provides the
+%command \cs{rowcolor}. The command \cs{DTLifoddrow} is used
+%to produce a striped table.
+%\begin{verbatim}
+%\begin{table}[htbp]
+%\caption{A Stripy Table}\label{tab:stripy}
+%\centering
+%\begin{tabular}{llc}
+%\bfseries First Name &
+%\bfseries Surname &
+%\bfseries Score (\%)%
+%\DTLforeach{scores}{%
+%\firstname=FirstName,\surname=Surname,\score=Score}{%
+%\\\DTLifoddrow{\rowcolor{blue}}{\rowcolor{green}}%
+%\firstname & \surname & \score}%
+%\end{tabular}
+%\end{table}
+%\end{verbatim}
+%This produces \autoref{tab:stripy}.
+%
+%\begin{table}[htbp]
+%\caption{A Stripy Table}\label{tab:stripy}
+%\centering
+%\begin{tabular}{llc}
+%\bfseries First Name &
+%\bfseries Surname &
+%\bfseries Score (\%)\relax
+%\DTLforeach{scores}{\firstname=FirstName,\surname=Surname,\score=Score}{\relax
+%\\\DTLifoddrow{\rowcolor{blue}}{\rowcolor{green}}\relax
+%\firstname & \surname & \score}\relax
+%\end{tabular}
+%\end{table}
+%\end{example}
+%
+%\begin{example}{Two Database Rows per Tabular Row}{ex:2rows}
+%In order to save space, you may want two database rows per
+%tabular row, when displaying a database in a \env{tabular}
+%environment. This can be accomplished using \ics{DTLifoddrow}.
+%For example
+%\begin{verbatim}
+%\begin{table}[htbp]
+%\caption{Two Database Rows per Tabular Row}\label{tab:2rows}
+%\centering
+%\begin{tabular}{llcllc}
+%\bfseries First Name &
+%\bfseries Surname &
+%\bfseries Score (\%) &
+%\bfseries First Name &
+%\bfseries Surname &
+%\bfseries Score (\%)\relax
+%\DTLforeach{scores}{\firstname=FirstName,\surname=Surname,\score=Score}{\relax
+%\DTLifoddrow{\\}{&}\relax
+%\firstname & \surname & \score}\relax
+%\end{tabular}
+%\end{table}
+%\end{verbatim}
+%produces \autoref{tab:2rows}
+%
+%\begin{table}[htbp]
+%\caption{Two Database Rows per Tabular Row}\label{tab:2rows}
+%\centering
+%\begin{tabular}{llcllc}
+%\bfseries First Name &
+%\bfseries Surname &
+%\bfseries Score (\%) &
+%\bfseries First Name &
+%\bfseries Surname &
+%\bfseries Score (\%)\relax
+%\DTLforeach{scores}{\firstname=FirstName,\surname=Surname,\score=Score}{\relax
+%\DTLifoddrow{\\}{&}\relax
+%\firstname & \surname & \score}\relax
+%\end{tabular}
+%\end{table}
+%\end{example}
+%
+%\begin{example}{Nested \cs{DTLforeach}}{ex:nested}
+%In this example I have a CSV file called "index.csv" which
+%contains:
+%\begin{verbatim}
+%File,Temperature,NaCl,pH
+%exp25a.csv,25,4.7,0.5
+%exp25b.csv,25,4.8,1.5
+%exp30a.csv,30,5.12,4.5
+%\end{verbatim}
+%\DTLnewdb{index}\relax
+%\DTLnewrow{index}\relax
+%\DTLnewdbentry{index}{File}{exp25a.csv}\relax
+%\DTLnewdbentry{index}{Temperature}{25}\relax
+%\DTLnewdbentry{index}{NaCl}{4.7}\relax
+%\DTLnewdbentry{index}{pH}{0.5}\relax
+%\DTLnewrow{index}\relax
+%\DTLnewdbentry{index}{File}{exp25b.csv}\relax
+%\DTLnewdbentry{index}{Temperature}{25}\relax
+%\DTLnewdbentry{index}{NaCl}{4.8}\relax
+%\DTLnewdbentry{index}{pH}{1.5}\relax
+%\DTLnewrow{index}\relax
+%\DTLnewdbentry{index}{File}{exp30a.csv}\relax
+%\DTLnewdbentry{index}{Temperature}{30}\relax
+%\DTLnewdbentry{index}{NaCl}{5.12}\relax
+%\DTLnewdbentry{index}{pH}{4.5}\relax
+%The first column of this file contains the name of another
+%CSV file which has the results of a time to growth experiment
+%performed at the given incubation temperature, salt concentration
+%and pH. The file "exp25a.csv" contains the following:
+%\begin{verbatim}
+%Time,Log Count
+%0,3.75
+%23,3.9
+%45,4.0
+%\end{verbatim}
+%\DTLnewdb{exp25a.csv}\relax
+%\DTLnewrow{exp25a.csv}\relax
+%\DTLnewdbentry{exp25a.csv}{Time}{0}\relax
+%\DTLnewdbentry{exp25a.csv}{Log Count}{3.75}\relax
+%\DTLnewrow{exp25a.csv}\relax
+%\DTLnewdbentry{exp25a.csv}{Time}{23}\relax
+%\DTLnewdbentry{exp25a.csv}{Log Count}{3.9}\relax
+%\DTLnewrow{exp25a.csv}\relax
+%\DTLnewdbentry{exp25a.csv}{Time}{45}\relax
+%\DTLnewdbentry{exp25a.csv}{Log Count}{4.0}\relax
+%The file "exp25b.csv" contains the following:
+%\begin{verbatim}
+%Time,Log Count
+%0,3.6
+%60,3.8
+%120,4.0
+%\end{verbatim}
+%\DTLnewdb{exp25b.csv}\relax
+%\DTLnewrow{exp25b.csv}\relax
+%\DTLnewdbentry{exp25b.csv}{Time}{0}\relax
+%\DTLnewdbentry{exp25b.csv}{Log Count}{3.6}\relax
+%\DTLnewrow{exp25b.csv}\relax
+%\DTLnewdbentry{exp25b.csv}{Time}{60}\relax
+%\DTLnewdbentry{exp25b.csv}{Log Count}{3.8}\relax
+%\DTLnewrow{exp25b.csv}\relax
+%\DTLnewdbentry{exp25b.csv}{Time}{120}\relax
+%\DTLnewdbentry{exp25b.csv}{Log Count}{4.0}\relax
+%The file "exp30a.csv" contains the following:
+%\begin{verbatim}
+%Time,Log Count
+%0,3.73
+%23,3.67
+%60,4.9
+%\end{verbatim}
+%\DTLnewdb{exp30a.csv}\relax
+%\DTLnewrow{exp30a.csv}\relax
+%\DTLnewdbentry{exp30a.csv}{Time}{0}\relax
+%\DTLnewdbentry{exp30a.csv}{Log Count}{3.73}\relax
+%\DTLnewrow{exp30a.csv}\relax
+%\DTLnewdbentry{exp30a.csv}{Time}{23}\relax
+%\DTLnewdbentry{exp30a.csv}{Log Count}{3.67}\relax
+%\DTLnewrow{exp30a.csv}\relax
+%\DTLnewdbentry{exp30a.csv}{Time}{60}\relax
+%\DTLnewdbentry{exp30a.csv}{Log Count}{4.9}\relax
+%Suppose I now want to iterate through "index.csv", load the given
+%file, and create a table for that data. I can do this using
+%nested \ics{DTLforeach} as follows:
+%\begin{verbatim}
+%% load index data file
+%\DTLloaddb{index}{index.csv}
+%
+%% iterate through index database
+%\DTLforeach{index}{\theFile=File,\theTemp=Temperature,%
+%\theNaCl=NaCl,\thepH=pH}{%
+%% load results file into database of the same name
+%\DTLloaddb{\theFile}{\theFile}%
+%% Create a table
+%\begin{table}[htbp]
+%\caption{Temperature = \theTemp, NaCl = \theNaCl,
+%pH = \thepH}\label{tab:\theFile}
+%\centering
+%\begin{tabular}{rl}
+%\bfseries Time & \bfseries Log Count
+%\DTLforeach{\theFile}{\theTime=Time,\theLogCount=Log Count}{%
+%\\\theTime & \theLogCount}%
+%\end{tabular}
+%\end{table}
+%}
+%\end{verbatim}
+%This creates \autoref{tab:exp25a.csv} to \autoref{tab:exp30a.csv}.
+%(Note that each table is given a label that is based on the
+%database name, to ensure that it is unique.)
+%
+%\DTLforeach{index}{\theFile=File,\theTemp=Temperature,\theNaCl
+%=NaCl,\thepH=pH}{
+%\begin{table}[htbp]
+%\caption{Temperature = \theTemp, NaCl = \theNaCl,
+%pH = \thepH}\label{tab:\theFile}
+%\centering
+%\begin{tabular}{rl}
+%\bfseries Time & \bfseries Log Count
+%\DTLforeach{\theFile}{\theTime=Time,\theLogCount=Log Count}{
+%\\\theTime & \theLogCount}%
+%\end{tabular}
+%\end{table}
+%}
+%\end{example}
+%
+%\subsection{Editing Database Rows}
+%
+%In the body of the \ics{DTLforeach} loop, you can use the following
+%to edit the current row:
+%\DescribeMacro{\DTLappendtorow}
+%\begin{definition}
+%\cs{DTLappendtorow}\marg{key}\marg{value}
+%\end{definition}
+%This appends a new entry with the given \meta{key} and \meta{value}
+%to the current row.
+%
+%\DescribeMacro{\DTLreplaceentryforrow}
+%\begin{definition}
+%\cs{DTLreplaceentryforrow}\marg{key}\marg{value}
+%\end{definition}
+%This replaces the entry for \meta{key} with \meta{value}.
+%
+%\DescribeMacro{\DTLremoveentryfromrow}
+%\begin{definition}
+%\cs{DTLremoveentryfromrow}\marg{key}
+%\end{definition}
+%This the entry for \meta{key} from the current row.
+%
+%\DescribeMacro{\DTLremovecurrentrow}
+%\begin{definition}
+%\cs{DTLremovecurrentrow}
+%\end{definition}
+%This removes the current row from the database.
+%
+%\DescribeMacro{\DTLforeachkeyinrow}
+%\begin{definition}
+%\cs{DTLforeachkeyinrow}\marg{cmd}\marg{text}
+%\end{definition}
+%This iterates through each key in the current row, assigns
+%\meta{cmd} to the value of that key, and does \meta{text}.
+%(\meta{cmd} must be a control sequence.)
+%
+%\begin{example}{Editing Database Rows}{ex:editdb}
+%In this example I have a CSV file called "marks.csv" that contains
+%student marks for three assignments:
+%\DTLnewdb{marks}\relax
+%\DTLnewrow{marks}\relax
+%\DTLnewdbentry{marks}{FirstName}{John}\relax
+%\DTLnewdbentry{marks}{Surname}{Smith, Jr}\relax
+%\DTLnewdbentry{marks}{StudentNo}{102689}\relax
+%\DTLnewdbentry{marks}{Assignment 1}{68}\relax
+%\DTLnewdbentry{marks}{Assignment 2}{57}\relax
+%\DTLnewdbentry{marks}{Assignment 3}{72}\relax
+%\DTLnewrow{marks}\relax
+%\DTLnewdbentry{marks}{FirstName}{Jane}\relax
+%\DTLnewdbentry{marks}{Surname}{Brown}\relax
+%\DTLnewdbentry{marks}{StudentNo}{102647}\relax
+%\DTLnewdbentry{marks}{Assignment 1}{75}\relax
+%\DTLnewdbentry{marks}{Assignment 2}{84}\relax
+%\DTLnewdbentry{marks}{Assignment 3}{80}\relax
+%\DTLnewrow{marks}\relax
+%\DTLnewdbentry{marks}{FirstName}{Andy}\relax
+%\DTLnewdbentry{marks}{Surname}{Brown}\relax
+%\DTLnewdbentry{marks}{StudentNo}{103569}\relax
+%\DTLnewdbentry{marks}{Assignment 1}{42}\relax
+%\DTLnewdbentry{marks}{Assignment 2}{52}\relax
+%\DTLnewdbentry{marks}{Assignment 3}{54}\relax
+%\DTLnewrow{marks}\relax
+%\DTLnewdbentry{marks}{FirstName}{Z\"oe}\relax
+%\DTLnewdbentry{marks}{Surname}{Adams}\relax
+%\DTLnewdbentry{marks}{StudentNo}{105987}\relax
+%\DTLnewdbentry{marks}{Assignment 1}{52}\relax
+%\DTLnewdbentry{marks}{Assignment 2}{48}\relax
+%\DTLnewdbentry{marks}{Assignment 3}{57}\relax
+%\DTLnewrow{marks}\relax
+%\DTLnewdbentry{marks}{FirstName}{Roger}\relax
+%\DTLnewdbentry{marks}{Surname}{Brady}\relax
+%\DTLnewdbentry{marks}{StudentNo}{106872}\relax
+%\DTLnewdbentry{marks}{Assignment 1}{58}\relax
+%\DTLnewdbentry{marks}{Assignment 2}{60}\relax
+%\DTLnewdbentry{marks}{Assignment 3}{62}\relax
+%\DTLnewrow{marks}\relax
+%\DTLnewdbentry{marks}{FirstName}{Clare}\relax
+%\DTLnewdbentry{marks}{Surname}{Verdon}\relax
+%\DTLnewdbentry{marks}{StudentNo}{104356}\relax
+%\DTLnewdbentry{marks}{Assignment 1}{45}\relax
+%\DTLnewdbentry{marks}{Assignment 2}{50}\relax
+%\DTLnewdbentry{marks}{Assignment 3}{48}\relax
+%\begin{ttfamily}\setlength{\parindent}{0pt}\par
+%Surname,FirstName,StudentNo,Assignment 1,Assignment 2,Assignment 3
+%
+%\DTLforeach{marks}{\surname=Surname,\firstname=FirstName,\regNo
+%=StudentNo,\assignI=Assignment 1,\assignII
+%=Assignment 2,\assignIII=Assignment 3}{\relax
+%\surname,\firstname,\regNo,\assignI,\assignII\assignIII\par
+%}
+%\end{ttfamily}\par\noindent
+%First load this into a database called "marks":
+%\begin{verbatim}
+%\DTLloaddb{marks}{marks.csv}
+%\end{verbatim}
+%Suppose now I want to compute the average mark for each
+%student, and append this to the database. I can do this as
+%follows:
+%\begin{verbatim}
+%\DTLforeach{marks}{%
+%\assignI=Assignment 1,%
+%\assignII=Assignment 2,%
+%\assignIII=Assignment 3}{%
+%\DTLmeanforall{\theMean}{\assignI,\assignII,\assignIII}%
+%\DTLappendtorow{Average}{\theMean}}
+%\end{verbatim}
+%\DTLforeach{marks}{\assignI=Assignment 1,\assignII
+%=Assignment 2,\assignIII=Assignment 3}{\relax
+%\DTLmeanforall{\theMean}{\assignI,\assignII,\assignIII}%
+%\DTLappendtorow{Average}{\theMean}}\relax
+%For each row in the "marks" database, I now have an extra key
+%called "Average" that contains the average mark over all three
+%assignments for a given student. I can now put this data into
+%a table:
+%\begin{verbatim}
+%\begin{table}[htbp]
+%\caption{Student Marks}
+%\centering
+%\begin{tabular}{llrrrr}
+%\bfseries Surname & \bfseries First Name &
+%\bfseries Assign 1 &
+%\bfseries Assign 2 &
+%\bfseries Assign 3 &
+%\bfseries Average Mark%
+%\DTLforeach{marks}{\surname=Surname,\firstname=FirstName,\average
+%=Average,\assignI=Assignment 1,\assignII=Assignment 2,\assignIII
+%=Assignment 3}{\\\surname
+%& \firstname & \assignI & \assignII & \assignIII &
+%\DTLround{\average}{\average}{2}\average}\relax
+%\end{tabular}
+%\end{table}
+%\end{verbatim}
+%This produces \autoref{tab:meanmarks}.
+%
+%Note that if I only wanted the averages for the table and nothing
+%else, I could simply have computed the average in each row of the
+%table and displayed it without adding the information to the
+%database, however I am going to reuse this information in
+%\autoref{ex:multibar}, so adding it to the database means that
+%I don't need to recompute the mean.
+%
+%\begin{table}[htbp]
+%\caption{Student Marks}\label{tab:meanmarks}
+%\centering
+%\begin{tabular}{llrrrr}
+%\bfseries Surname & \bfseries First Name &
+%\bfseries Assign 1 &
+%\bfseries Assign 2 &
+%\bfseries Assign 3 &
+%\bfseries Average Mark\relax
+%\DTLforeach{marks}{\surname=Surname,\firstname=FirstName,\average
+%=Average,\assignI=Assignment 1,\assignII=Assignment 2,\assignIII
+%=Assignment 3}{\\\surname
+%& \firstname & \assignI & \assignII & \assignIII &
+%\DTLround{\average}{\average}{2}\average}\relax
+%\end{tabular}
+%\end{table}
+%
+%\end{example}
+%
+%\subsection{Arithmetical Computations on Database Entries}
+%
+%The commands used in \autoref{sec:fp} can be used on database
+%entries. You can, of course, directly use the commands provided
+%by the \sty{fp} package if you know that the values are in the
+%correct format (i.e.\ no currency symbols, no number group
+%separators and a full stop as the decimal point) but if this may
+%not be the case, then you should use the commands described in
+%\autoref{sec:fp}. If you want to use a command provided by the
+%\sty{fp} package, that does not have a wrapper function in
+%\sty{datatool}, then you will need to convert the value using
+%\ics{DTLconverttodecimal}, and convert it back using either
+%\ics{DTLdecimaltolocale} or \ics{DTLdecimaltocurrency}.
+%
+%\begin{example}{Arithmetical Computations}{ex:mean}
+%In this example, I am going to produce a table similar to
+%\autoref{tab:scores}, except that I want to add an extra row at the
+%end which contains the average score.
+%\begin{verbatim}
+%\begin{table}[htbp]
+%\caption{Student Scores (Including Average)}\label{tab:mean}
+%\centering
+%\def\total{0}%
+%\begin{tabular}{llr}
+%\bfseries First Name &
+%\bfseries Surname &
+%\bfseries Score (\%)%
+%\DTLforeach{scores}{%
+%\firstname=FirstName,\surname=Surname,\score=Score}{%
+%\\
+%\firstname & \surname &
+%\DTLgadd{\total}{\score}{\total}%
+%\score
+%}\\
+%\multicolumn{2}{l}{\bfseries Average Score} &
+%\DTLsavelastrowcount{\n}%
+%\DTLdiv{\average}{\total}{\n}%
+%\DTLround{\average}{\average}{2}%
+%\average
+%\end{tabular}
+%\end{table}
+%\end{verbatim}
+%This produces \autoref{tab:mean}.
+%\textbf{Notes:}
+%\begin{itemize}
+%\item I had to use \ics{DTLgadd} rather than \ics{DTLadd} since it
+%occurs within a \env{tabular} environment which puts each entry
+%in a local scope.
+%
+%\item I used \ics{DTLsavelastrowcount} to store the number of
+%rows produced by \ics{DTLforeach} in the control sequence \cs{n}.
+%
+%\item I used \ics{DTLround} to round the average score to 2 decimal
+%places.
+%\end{itemize}
+%
+%\begin{table}[htbp]
+%\caption{Student Scores (Including Average)}\label{tab:mean}
+%\centering
+%\def\total{0}\relax
+%\begin{tabular}{llr}
+%\bfseries First Name &
+%\bfseries Surname &
+%\bfseries Score (\%)\relax
+%\DTLforeach{scores}{\firstname=FirstName,\surname=Surname,\score=Score}{\relax
+%\\
+%\firstname & \surname &
+%\DTLgadd{\total}{\score}{\total}\relax
+%\score
+%}\\
+%\multicolumn{2}{l}{\bfseries Average Score} &
+%\DTLsavelastrowcount{\n}\relax
+%\DTLdiv{\average}{\total}{\n}\relax
+%\DTLround{\average}{\average}{2}\relax
+%\average
+%\end{tabular}
+%\end{table}
+%\end{example}
+%
+%\DescribeMacro{\DTLsumforkeys}
+%\begin{definition}
+%\cs{DTLsumforkeys}\oarg{condition}\marg{db list}\marg{key list}\marg{cmd}
+%\end{definition}
+%This command sums all the entries over all the databases listed in
+%the comma separated list of database names \meta{db list} for each key in
+%\meta{key list} where the condition given by
+%\meta{condition} is true. The result is stored in \meta{cmd}
+%which must be a control sequence. For example:
+%\begin{verbatim}
+%\DTLsumforkeys{scores}{Score}{\total}
+%\end{verbatim}
+%sets \cs{total} to the sum of all the scores in the database
+%called "scores".
+%
+%\DescribeMacro{\DTLmeanforkeys}
+%\begin{definition}
+%\cs{DTLmeanforkeys}\oarg{condition}\marg{db list}\marg{key list}\marg{cmd}
+%\end{definition}
+%This command computes the arithmetic mean of all the entries over
+%all the databases listed in \meta{db list} for all keys in \meta{key list} where
+%the condition
+%given by \meta{condition} is true. The result is stored in \meta{cmd}
+%which must be a control sequence. For example:
+%\begin{verbatim}
+%\DTLmeanforkeys{scores}{Score}{\average}
+%\end{verbatim}
+%sets \cs{average} to the mean of all the scores in the database
+%called "scores".
+%
+%\DescribeMacro{\DTLvarianceforkeys}
+%\begin{definition}
+%\cs{DTLvarianceforkeys}\oarg{condition}\marg{db list}\marg{key list}\marg{cmd}
+%\end{definition}
+%This command computes the variance of all the entries over
+%all the databases listed in \meta{db list} for all keys in \meta{key list} where
+%the condition
+%given by \meta{condition} is true. The result is stored in \meta{cmd}
+%which must be a control sequence.
+%
+%\DescribeMacro{\DTLsdforkeys}
+%\begin{definition}
+%\cs{DTLsdforkeys}\oarg{condition}\marg{db list}\marg{key list}\marg{cmd}
+%\end{definition}
+%This command computes the standard deviation of all the entries over
+%all the databases listed in \meta{db list} for all keys in \meta{key list} where
+%the condition
+%given by \meta{condition} is true. The result is stored in \meta{cmd}
+%which must be a control sequence.
+%
+%\DescribeMacro{\DTLminforkeys}
+%\begin{definition}
+%\cs{DTLminforkeys}\oarg{condition}\marg{db list}\marg{key list}\marg{cmd}
+%\end{definition}
+%This command determines the minimum value over all entries
+%for all keys in \meta{key list} over all the databases listed in \meta{db list}
+%and stores
+%in \meta{cmd}, which must be a control sequence. For example
+%\begin{verbatim}
+%\DTLminforkeys{scores}{Score}{\theMin}
+%\end{verbatim}
+%sets \cs{theMin} to the minimum score in the database.
+%
+%\DescribeMacro{\DTLmaxforkeys}
+%\begin{definition}
+%\cs{DTLmaxforkeys}\oarg{condition}\marg{db list}\marg{key list}\marg{cmd}
+%\end{definition}
+%This command determines the maximum value over all entries
+%for all keys in \meta{key list} over all the databases listed in \meta{db list}
+%and stores
+%in \meta{cmd}, which must be a control sequence. For example
+%\begin{verbatim}
+%\DTLminforkeys{scores}{Score}{\theMax}
+%\end{verbatim}
+%sets \cs{theMax} to the minimum score in the database.
+%
+%\DescribeMacro{\DTLcomputebounds}
+%\begin{definition}
+%\cs{DTLcomputebounds}\marg{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}.
+%
+%\begin{example}{Mail Merging}{ex:mailmerging}
+%This example uses the database given in \autoref{ex:scores} and
+%uses \ics{DTLmeanforkey} to determine the average score. A letter
+%is then created for each student to inform them of their score
+%and the class average.
+%
+%\begin{verbatim}
+%\documentclass{letter}
+%
+%\usepackage{datatool}
+%
+%\begin{document}
+%% load database
+%\DTLloaddb{scores}{studentscores.csv}
+%% compute arithmetic mean for key `Score'
+%\DTLmeanforkey{scores}{Score}{\average}
+%% Round the average to 2 decimal places
+%\DTLround{\average}{\average}{2}
+%% Save the highest score in \maxscore
+%\DTLmaxforkey{scores}{Score}{\maxscore}
+%
+%\DTLforeach{scores}{\firstname=FirstName,\surname=Surname,%
+%\score=Score}{%
+%\begin{letter}{}
+%\opening{Dear \firstname\ \surname}
+%
+%\DTLifnumgt{\score}{60}{Congratulations you}{You} achieved a score
+%of \score\% which was \DTLifnumgt{\score}{\average}{above}{below}
+%the average of \average\%. \DTLifnumeq{\score}{\maxscore}{You
+%achieved the highest score}{The top score was \maxscore}.
+%
+%\closing{Yours Sincerely}
+%\end{letter}
+%}
+%\end{document}
+%\end{verbatim}
+%\end{example}
+%
+%\subsection{Sorting a Database}
+%\label{sec:sort}
+%
+%\DescribeMacro{\DTLsort}
+%\begin{definition}
+%\cs{DTLsort}\marg{sort criteria}\marg{db name}
+%\end{definition}
+%This will sort the database called \meta{db name} according to
+%the criteria given by \meta{sort criteria}, which must be a
+%comma separated list of keys and optionally "="\meta{order}, where
+%\meta{order} is either "ascending" or "descending". If the order
+%is omitted, "ascending" is assumed. The database keeps track of
+%the data type for a given key, and uses this to determine whether
+%an alphabetical or numerical sort is required.
+%
+%\begin{example}{Sorting a Database}{ex:sort}
+%This example uses the database called "scores" defined in
+%\autoref{ex:scores}. First, I am going to sort the database
+%according to the student scores in descending order (highest to
+%lowest) and display the database in a table
+%\begin{verbatim}
+%\begin{table}[htbp]
+%\caption{Student Scores (Sorted by Score)}\label{tab:sortscores}
+%\centering
+%\DTLsort{Score=descending}{scores}%
+%\begin{tabular}{llr}
+%\bfseries First Name &
+%\bfseries Surname &
+%\bfseries Score (\%)%
+%\DTLforeach{scores}{%
+%\firstname=FirstName,\surname=Surname,\score=Score}{%
+%\\
+%\firstname & \surname & \score}
+%\end{tabular}
+%\end{table}
+%\end{verbatim}
+%This produces \autoref{tab:sortscores}.
+%
+%\begin{table}[htbp]
+%\caption{Student Scores (Sorted by Score)}\label{tab:sortscores}
+%\centering
+%\DTLsort{Score=descending}{scores}\relax
+%\begin{tabular}{llr}
+%\bfseries First Name &
+%\bfseries Surname &
+%\bfseries Score (\%)\relax
+%\DTLforeach{scores}{\firstname=FirstName,\surname=Surname,\score=Score}{\relax
+%\\
+%\firstname & \surname & \score}
+%\end{tabular}
+%\end{table}
+%
+%Now I am going to sort the database according to
+%surname and then first name, and display it in a table. Note that
+%since I want to sort in ascending order, I can omit the
+%"=ascending" part of the sort criteria. I have also decided to
+%reverse the first and second columns, so that the surname is
+%in the first column.
+%\begin{verbatim}
+%\begin{table}[htbp]
+%\caption{Student Scores (Sorted by Name)}\label{tab:sortname}
+%\centering
+%\DTLsort{Surname,FirstName}{scores}%
+%\begin{tabular}{llr}
+%\bfseries Surname &
+%\bfseries First Name &
+%\bfseries Score (\%)%
+%\DTLforeach{scores}{%
+%\firstname=FirstName,\surname=Surname,\score=Score}{%
+%\\
+%\surname & \firstname & \score}
+%\end{tabular}
+%\end{table}
+%\end{verbatim}
+%This produces \autoref{tab:sortname}.
+%\begin{table}[htbp]
+%\caption{Student Scores (Sorted by Name)}\label{tab:sortname}
+%\centering
+%\DTLsort{Surname,FirstName}{scores}\relax
+%\begin{tabular}{llr}
+%\bfseries Surname &
+%\bfseries First Name &
+%\bfseries Score (\%)\relax
+%\DTLforeach{scores}{\firstname=FirstName,\surname=Surname,\score=Score}{\relax
+%\\
+%\surname & \firstname & \score}
+%\end{tabular}
+%\end{table}
+%
+%\end{example}
+%
+%\subsection{Saving a Database to an External File}
+%\label{sec:savedb}
+%
+%\DescribeMacro{\DTLsavedb}
+%\begin{definition}
+%\cs{DTLsavedb}\marg{db name}\marg{filename}
+%\end{definition}
+%This writes the database called \meta{db name} to a file called
+%\meta{filename}. The separator and delimiter characters used
+%are as given by \ics{DTLsetseparator} (or \ics{DTLsettabseparator})
+%and \ics{DTLsetdelimiter}. For example:
+%\begin{verbatim}
+%\DTLsettabdelimiter
+%\DTLsavedb{scores}{scores.txt}
+%\end{verbatim}
+%
+%\DescribeMacro{\DTLsavetexdb}
+%\begin{definition}
+%\cs{DTLsavetexdb}\marg{db name}\marg{filename}
+%\end{definition}
+%This writes the database called \meta{db name} to a \LaTeX\ file
+%called \meta{filename}, where the database is stored as
+%a combination of \ics{DTLnewdb}, \ics{DTLnewrow} and \ics{DTLnewdbentry} commands.
+%
+%\section{Pie Charts (\texorpdfstring{\sty{datapie}}{datapie} package)}
+%
+%The \sty{datapie} package is not loaded by the \sty{datatool} package,
+%so you need to load \sty{datapie} if you want to use any of the
+%commands defined in this section. You will need to have the
+%\sty{pgf}/\sty{tikz} packages installed. The \sty{datapie} package
+%may be given the following options:
+%\begin{description}
+%\item[{\pkgopt[datapie]{color}}] Colour option (default.)
+%\item[{\pkgopt[datapie]{monochrome}}] Monochrome option.
+%\item[{\pkgopt[datapie]{rotateinner}}]
+%Rotate inner labels so that they are aligned
+%with the pie chart radial axis.
+%\item[{\pkgopt[datapie]{norotateinner}}]
+%Don't rotate inner labels (default.)
+%\item[{\pkgopt[datapie]{rotateouter}}]
+%Rotate outer labels so that they are aligned
+%with the pie chart radial axis.
+%\item[{\pkgopt[datapie]{norotateouter}}]
+%Don't rotate outer labels (default.)
+%\end{description}
+%
+%Numerical information contained in a database created by the
+%\sty{datatool} package can be converted into a pie chart using
+%\DescribeMacro{\DTLpiechart}
+%\begin{definition}
+%\cs{DTLpiechart}\oarg{condition}\marg{settings list}\marg{db name}\marg{values}
+%\end{definition}\noindent
+%where \meta{db name} is the name of the database, and
+%\meta{condition} has the same form as the optional argument
+%to \ics{DTLforeach} described in \autoref{sec:dbforeach}. If
+%\meta{condition} is false, that information is omitted from the
+%construction of the pie chart. The argument \meta{values} is a
+%comma separated list of \meta{cmd}"="\meta{key} pairs, the same
+%as that required by the penultimate argument of \ics{DTLforeach}.
+%The \meta{settings list} is a comma separated list of
+%\meta{setting}=\meta{value} pairs, where \meta{setting} can be any of
+%the following:
+%\begin{description}
+%\item[\setting{DTLpiechart}{variable}]
+%This specifies the control sequence to use that
+%contains the value used to construct the pie chart. The control
+%sequence must be one of the control sequences to appear in
+%the assignment list \meta{values}. This setting is required.
+%
+%\item[\setting{DTLpiechart}{start}]
+%This is the starting angle of the first segment. The
+%value is 0 by default.
+%
+%\item[\setting{DTLpiechart}{radius}]
+%This is the radius of the pie chart. The default value
+%is 2cm.
+%
+%\item[\setting{DTLpiechart}{innerratio}]
+%The distance from the centre of the
+%pie chart to the point where the inner labels are placed is given
+%by this value multiplied by the ratio. The default value is 0.5.
+%
+%\item[\setting{DTLpiechart}{outerratio}]
+%The distance from the centre of the
+%pie chart to the point where the outer labels are placed is given
+%by this value multiplied by the ratio. The default value is 1.25.
+%
+%\item[\setting{DTLpiechart}{cutawayratio}]
+%The distance from the centre of the pie chart
+%to the point of cutaway segments is given by this value multiplied
+%by the ratio. The default value is 0.2.
+%
+%\item[\setting{DTLpiechart}{inneroffset}]
+%This is the absolute distance from the centre
+%of the pie chart to the point where the inner labels are placed.
+%You should use only one or other of \setting{DTLpiechart}{innerratio}
+%and \setting{DTLpiechart}{inneroffset}, not both. If you also want to
+%specify the radius, you must use \setting{DTLpiechart}{ratio}
+%before \setting{DTLpiechart}{inneroffset}. If omitted, the inner
+%offset is obtained from the ratio multiplied by the
+%\setting{DTLpiechart}{innerratio} value.
+%
+%\item[\setting{DTLpiechart}{outeroffset}]
+%This is the absolute distance from the centre
+%of the pie chart to the point where the outer labels are placed.
+%You should use only one or other of \setting{DTLpiechart}{outerratio}
+%and \setting{DTLpiechart}{outeroffset}, not both. If you also want to
+%specify the radius, you must use \setting{DTLpiechart}{ratio}
+%before \setting{DTLpiechart}{outeroffset}. If omitted, the outer
+%offset is obtained from the ratio multiplied by the
+%\setting{DTLpiechart}{outerratio} value.
+%
+%\item[\setting{DTLpiechart}{cutawayoffset}]
+%This is the absolute distance from the centre of
+%the pie chart to the point of the cutaway segments. You should use
+%only one or other of \setting{DTLpiechart}{cutawayratio} and
+%\setting{DTLpiechart}{cutawayoffset}, not both. If
+%you also want to specify the radius, you must use
+%\setting{DTLpiechart}{ratio} before
+%\setting{DTLpiechart}{cutawayoffset}. If omitted, the cutaway offset
+%is obtained from the ratio multiplied by the
+%\setting{DTLpiechart}{cutawayratio} value.
+%
+%\item[\setting{DTLpiechart}{cutaway}]
+%This is a list of cutaway segments. This should be
+%a comma separated list of individual numbers, or number ranges
+%(separated by a dash.) For example "cutaway={1,3}" will separate
+%the first and third segments from the rest of the pie chart, offset
+%by the value of the \setting{DTLpiechart}{cutawayoffset} setting,
+%whereas "cutaway={1-3}" will separate the
+%first three segments from the rest of the pie chart. If omitted,
+%the pie chart will be whole.
+%
+%\item[\setting{DTLpiechart}{innerlabel}]
+%The value of this is positioned in the middle of each segment at a
+%distance of \setting{DTLpiechart}{inneroffset} from the centre
+%of the pie chart. The default is the same as the value of
+%\setting{DTLpiechart}{variable}.
+%
+%\item[\setting{DTLpiechart}{outerlabel}]
+%The value of this is positioned at a distance of
+%\setting{DTLpiechart}{outeroffset} from the centre of the pie chart.
+%The default is empty.
+%
+%\item[\setting{DTLpiechart}{rotateinner}] This is a boolean setting,
+%so it can only take the values "true" and "false". If the value is
+%omitted "true" is assumed. If true, the inner labels are rotated
+%along the spokes of the pie chart, otherwise the inner labels are not
+%rotated. There are analogous package options
+%\pkgopt[datapie]{rotateinner} and \pkgopt[datapie]{norotateinner}.
+%
+%\item[\setting{DTLpiechart}{rotateouter}]
+%This is a boolean setting, so it can only take
+%the values "true" and "false". If the value is omitted "true" is
+%assumed. If true, the outer labels are rotated along the spokes of
+%the pie chart, otherwise the outer labels are not rotated.
+%There are analogous package options
+%\pkgopt[datapie]{rotateouter} and \pkgopt[datapie]{norotateouter}.
+%
+%\end{description}
+%
+%\begin{example}{A Pie Chart}{ex:piechart}
+%This example loads data from a file called "fruit.csv" which contains
+%the following:
+%\begin{verbatim}
+%Name,Quantity
+%"Apples",30
+%"Pears",25
+%"Lemons,Limes",40.5
+%"Peaches",34.5
+%"Cherries",20
+%\end{verbatim}
+%First load the data:
+%\begin{verbatim}
+%\DTLloaddb{fruit}{fruit.csv}
+%\end{verbatim}
+%\DTLnewdb{fruit}\relax
+%\DTLnewrow{fruit}\relax
+%\DTLnewdbentry{fruit}{Name}{Apples}\relax
+%\DTLnewdbentry{fruit}{Quantity}{30}\relax
+%\DTLnewrow{fruit}\relax
+%\DTLnewdbentry{fruit}{Name}{Pears}\relax
+%\DTLnewdbentry{fruit}{Quantity}{25}\relax
+%\DTLnewrow{fruit}\relax
+%\DTLnewdbentry{fruit}{Name}{Lemons,Limes}\relax
+%\DTLnewdbentry{fruit}{Quantity}{40.5}\relax
+%\DTLnewrow{fruit}\relax
+%\DTLnewdbentry{fruit}{Name}{Peaches}\relax
+%\DTLnewdbentry{fruit}{Quantity}{34.5}\relax
+%\DTLnewrow{fruit}\relax
+%\DTLnewdbentry{fruit}{Name}{Cherries}\relax
+%\DTLnewdbentry{fruit}{Quantity}{20}\relax
+%Now create a pie chart in a figure:
+%\begin{verbatim}
+%\begin{figure}[htbp]
+%\centering
+%\DTLpiechart{variable=\quantity}{fruit}{\name=Name,\quantity=Quantity}
+%\caption{A Pie Chart}
+%\end{figure}
+%\end{verbatim}
+%This creates \autoref{fig:piechart}.
+%
+%\begin{figure}[htbp]
+%\centering
+%\DTLpiechart{variable=\quantity}{fruit}{\name=Name,\quantity=Quantity}
+%\caption{A Pie Chart}
+%\label{fig:piechart}
+%\end{figure}
+%
+%There are no outer labels by default, but they can be set
+%using the \setting{DTLpiechart}{outerlabel} setting.
+%The following sets the outer label to the value of the "Name" key:
+%\begin{verbatim}
+%\begin{figure}[htbp]
+%\centering
+%\DTLpiechart{variable=\quantity,outerlabel=\name}{fruit}{%
+%\name=Name,\quantity=Quantity}
+%\caption{A Pie Chart (Outer labels set)}
+%\end{figure}
+%\end{verbatim}
+%This creates \autoref{fig:piechartouter}.
+%
+%\begin{figure}[htbp]
+%\centering
+%\DTLpiechart{variable=\quantity,outerlabel=\name}{fruit}
+%{\name=Name,\quantity=Quantity}
+%\caption{A Pie Chart (Outer labels set)}
+%\label{fig:piechartouter}
+%\end{figure}
+%
+%You may prefer the labels to be rotated. The following
+%switches on the rotation for the inner and outer labels:
+%\begin{verbatim}
+%\begin{figure}[htbp]
+%\centering
+%\DTLpiechart{variable=\quantity,outerlabel=\name,%
+%rotateinner,rotateouter}{fruit}{%
+%\name=Name,\quantity=Quantity}
+%\caption{A Pie Chart (Rotation enabled)}
+%\end{figure}
+%\end{verbatim}
+%This creates \autoref{fig:piechartrot}.
+%
+%\begin{figure}[htbp]
+%\centering
+%\DTLpiechart{variable=\quantity,outerlabel=\name
+%,rotateinner,rotateouter}{fruit}
+%{\name=Name,\quantity=Quantity}
+%\caption{A Pie Chart (Rotation enabled)}
+%\label{fig:piechartrot}
+%\end{figure}
+%\end{example}
+%
+%\begin{example}{Separating Segments from the Pie Chart}{ex:cutaway}
+%You may want to separate one or more segments from the pie chart,
+%perhaps to emphasize them. You can do this using the
+%\setting{DTLpiechart}{cutaway}
+%setting. The following separates the first and third segments
+%from the pie chart:
+%\begin{verbatim}
+%\begin{figure}[htbp]
+%\centering
+%\DTLpiechart{variable=\quantity,outerlabel=\name,%
+%cutaway={1,3}}{fruit}{%
+%\name=Name,\quantity=Quantity}
+%\caption{A Pie Chart with Cutaway Segments}
+%\end{figure}
+%\end{verbatim}
+%This produces \autoref{fig:piecutaway}.
+%
+%\begin{figure}[htbp]
+%\centering
+%\DTLpiechart{variable=\quantity,outerlabel=\name
+%,cutaway={1,3}}{fruit}{\name=Name,\quantity=Quantity}
+%\caption{A Pie Chart with Cutaway Segments}
+%\label{fig:piecutaway}
+%\end{figure}
+%
+%Alternatively I can specify a range of segments. The following
+%separates the first two segments:
+%\begin{verbatim}
+%\begin{figure}[htbp]
+%\centering
+%\DTLpiechart{variable=\quantity,outerlabel=\name,%
+%cutaway={1-2}}{fruit}{%
+%\name=Name,\quantity=Quantity}
+%\caption{A Pie Chart with Cutaway Segments (\texttt{cutaway=\{1-2\}})}
+%\end{figure}
+%\end{verbatim}
+%This produces \autoref{fig:piecutaway2}.
+%
+%\begin{figure}[htbp]
+%\centering
+%\DTLpiechart{variable=\quantity,outerlabel=\name
+%,cutaway={1-2}}{fruit}{\name=Name,\quantity=Quantity}
+%\caption{A Pie Chart with Cutaway Segments (\texttt{cutaway=\{1-2\}})}
+%\label{fig:piecutaway2}
+%\end{figure}
+%
+%Notice the difference between \autoref{fig:piecutaway2} and
+%\autoref{fig:piecutaway3} which was produced using:
+%\begin{verbatim}
+%\begin{figure}[htbp]
+%\centering
+%\DTLpiechart{variable=\quantity,outerlabel=\name,%
+%cutaway={1,2}}{fruit}{%
+%\name=Name,\quantity=Quantity}
+%\caption{A Pie Chart with Cutaway Segments (\texttt{cutaway=\{1,2\}})}
+%\end{figure}
+%\end{verbatim}
+%
+%\begin{figure}[htbp]
+%\centering
+%\DTLpiechart{variable=\quantity,outerlabel=\name
+%,cutaway={1,2}}{fruit}{\name=Name,\quantity=Quantity}
+%\caption{A Pie Chart with Cutaway Segments (\texttt{cutaway=\{1,2\}})}
+%\label{fig:piecutaway3}
+%\end{figure}
+%
+%\end{example}
+%
+%\subsection{Pie Chart Variables}
+%
+%\DescribeMacro{\DTLpievariable}
+%\begin{definition}
+%\cs{DTLpievariable}
+%\end{definition}
+%This command is set to the variable given by the
+%\setting{DTLpiechart}{variable} setting in the \meta{settings list}
+%argument of \cs{DTLpiechart}. The \setting{DTLpiechart}{innerlabel}
+%is set to \cs{DTLpievariable} by default.
+%
+%\DescribeMacro{\DTLpiepercent}
+%\begin{definition}
+%\cs{DTLpiepercent}
+%\end{definition}
+%This command is set to the percentage value of \cs{DTLpievariable}.
+%The percentage value is rounded to \meta{n} digits, where \meta{n}
+%is the value of the \LaTeX\ counter
+%\counterfmt{DTLpieroundvar}.
+%
+%\begin{example}{Changing the Inner and Outer Labels}{ex:pielabels}
+%This example uses the database defined in \autoref{ex:piechart}.
+%The inner label is now set to the percentage value, rather than
+%the actual value, and the outer label is set to the name with
+%the actual value in parentheses.
+%\begin{verbatim}
+%\begin{figure}[htbp]
+%\centering
+%\DTLpiechart{variable=\quantity,%
+%innerlabel={\DTLpiepercent\%},%
+%outerlabel={\name\ (\DTLpievariable)}}{fruit}{%
+%\name=Name,\quantity=Quantity}
+%\caption{A Pie Chart (Changing the labels)}
+%\end{figure}
+%\end{verbatim}
+%This produces \autoref{fig:piechartlabels}.
+%
+%\begin{figure}[htbp]
+%\centering
+%\DTLpiechart{variable=\quantity,innerlabel={\DTLpiepercent
+%\%},outerlabel={\name\ (\DTLpievariable)}}{fruit}{%
+%\name=Name,\quantity=Quantity}
+%\caption{A Pie Chart (Changing the labels)}
+%\label{fig:piechartlabels}
+%\end{figure}
+%\end{example}
+%
+%\subsection{Pie Chart Label Formatting}
+%
+%\DescribeMacro{\DTLdisplayinnerlabel}
+%\begin{definition}
+%\cs{DTLdisplayinnerlabel}\marg{text}
+%\end{definition}
+%This governs how the inner label is formatted, where \meta{text}
+%is the text of the inner label. The default is to just do \meta{text}.
+%
+%\DescribeMacro{\DTLdisplayouterlabel}
+%\begin{definition}
+%\cs{DTLdisplayouterlabel}\marg{text}
+%\end{definition}
+%This governs how the outer label is formatted, where \meta{text}
+%is the text of the outer label. The default is to just do \meta{text}.
+%
+%\begin{example}{Changing the Inner and Outer Label
+%Format}{ex:pielabelformat}
+%This example extends \autoref{ex:pielabels}.
+%The inner and outer labels are now both typeset in a sans-serif
+%font:
+%\begin{verbatim}
+%\begin{figure}[htbp]
+%\centering
+%\renewcommand*{\DTLdisplayinnerlabel}[1]{\textsf{#1}}
+%\renewcommand*{\DTLdisplayouterlabel}[1]{\textsf{#1}}
+%\DTLpiechart{variable=\quantity,%
+%innerlabel={\DTLpiepercent\%},%
+%outerlabel={\name\ (\DTLpievariable)}}{fruit}{%
+%\name=Name,\quantity=Quantity}
+%\caption{A Pie Chart (Changing the label format)}
+%\end{figure}
+%\end{verbatim}
+%This produces \autoref{fig:piechartlabelformat}.
+%
+%\begin{figure}[htbp]
+%\centering
+%\renewcommand*{\DTLdisplayinnerlabel}[1]{\textsf{#1}}
+%\renewcommand*{\DTLdisplayouterlabel}[1]{\textsf{#1}}
+%\DTLpiechart{variable=\quantity,innerlabel={\DTLpiepercent
+%\%},outerlabel={\name\ (\DTLpievariable)}}{fruit}{%
+%\name=Name,\quantity=Quantity}
+%\caption{A Pie Chart (Changing the label format)}
+%\label{fig:piechartlabelformat}
+%\end{figure}
+%\end{example}
+%
+%\subsection{Pie Chart Colours}
+%
+%The \sty{datapie} package predefines colours for the first
+%eight segments of the pie chart. If you require more than
+%eight segments, you will need to use
+%\DescribeMacro{\DTLsetpiesegmentcolor}
+%\begin{definition}
+%\cs{DTLsetpiesegmentcolor}\marg{n}\marg{color}
+%\end{definition}\noindent
+%to set the colours for any additional segments, or you can use
+%it to change the default colours. The first argument \meta{n}
+%is the segment index (starting from 1), and the second argument
+%\meta{color} is a colour specifier as used in commands such as
+%\cs{color}.
+%
+%\DescribeMacro{\DTLdopiesegmentcolor}
+%\begin{definition}
+%\cs{DTLdopiesegmentcolor}\meta{n}
+%\end{definition}
+%This sets the current text colour to that of the \meta{n}th
+%segment.
+%
+%\DescribeMacro{\DTLdocurrentpiesegmentcolor}
+%\begin{definition}
+%\cs{DTLdocurrentpiesegmentcolor}
+%\end{definition}
+%This sets the current text colour to that of the current pie
+%segment. This command may only be used within a pie chart, or
+%within the body of \ics{DTLforeach}.
+%
+%\DescribeMacro{\DTLpieoutlinecolor}
+%\begin{definition}
+%\cs{DTLpieoutlinecolor}
+%\end{definition}
+%This sets the outline colour for the pie chart. The default is
+%black.
+%
+%\DescribeMacro{\DTLpieoutlinewidth}
+%\begin{definition}
+%\cs{DTLpieoutlinewidth}
+%\end{definition}
+%This is a length that governs the line width of the outline. The
+%default value is 0pt, but can be changed using \cs{setlength}.
+%The outline is only drawn if \cs{DTLpieoutlinewidth} is greater
+%than 0pt.
+%
+%\begin{example}{Pie Segment Colours}{ex:piecolours}
+%This example extends \autoref{ex:pielabelformat}.
+%It sets the outline thickness to 2pt, and
+%the outer label is now set in the same colour as the fill colour
+%of the segment to which it belongs.
+%In addition, a legend is created using
+%\ics{DTLforeach}.
+%\begin{verbatim}
+%\begin{figure}[htbp]
+%\centering
+%\setlength{\DTLpieoutlinewidth}{2pt}
+%\renewcommand*{\DTLdisplayinnerlabel}[1]{\textsf{#1}}
+%\renewcommand*{\DTLdisplayouterlabel}[1]{%
+%\DTLdocurrentpiesegmentcolor
+%\textsf{\shortstack{#1}}}
+%\DTLpiechart{variable=\quantity,%
+%innerlabel={\DTLpiepercent\%},%
+%outerlabel={\name\\(\DTLpievariable)}}{fruit}{%
+%\name=Name,\quantity=Quantity}
+%\begin{tabular}[b]{ll}
+%\DTLforeach{fruit}{\name=Name}{\DTLiffirstrow{}{\\}%
+%\DTLdocurrentpiesegmentcolor\rule{10pt}{10pt} &
+%\name
+%}
+%\end{tabular}
+%\caption{A Pie Chart (Using Segment Colours and Outline)}
+%\end{figure}
+%\end{verbatim}
+%This produces \autoref{fig:piesegcolour}. (The format of the
+%outer label has been changed to use \cs{shortstack} to
+%prevent the outer labels from taking up so much horizontal
+%space. The \setting{DTLpiechart}{outerlabel} setting has also been
+%modified to use "\\" after the name to move the percentage value onto
+%the next row.)
+%
+%\begin{figure}[htbp]
+%\centering
+%\setlength{\DTLpieoutlinewidth}{2pt}
+%\renewcommand*{\DTLdisplayinnerlabel}[1]{\textsf{#1}}
+%\renewcommand*{\DTLdisplayouterlabel}[1]{\relax
+%\DTLdocurrentpiesegmentcolor
+%\textsf{\shortstack{#1}}}
+%\DTLpiechart{variable=\quantity,innerlabel={\DTLpiepercent
+%\%},outerlabel={\name\\(\DTLpievariable)}}{fruit}{%
+%\name=Name,\quantity=Quantity}
+%\begin{tabular}[b]{ll}
+%\DTLforeach{fruit}{\name=Name}{\DTLiffirstrow{}{\\}\relax
+%\DTLdocurrentpiesegmentcolor\rule{10pt}{10pt} &
+%\name
+%}
+%\end{tabular}
+%\caption{A Pie Chart (Using Segment Colours and Outline)}
+%\label{fig:piesegcolour}
+%\end{figure}
+%\end{example}
+%
+%\subsection{Adding Extra Commands Before and After the Pie Chart}
+%
+%The pie charts created using \ics{DTLpiechart} are placed inside
+%a \env{tikzpicture} environment (defined by the \sty{tikz} package.)
+%
+%\DescribeMacro{\DTLpieatbegintikz}
+%\begin{definition}
+%\cs{DTLpieatbegintikz}
+%\end{definition}
+%The macro \cs{DTLpieatbegintikz} is called at the start of the
+%\env{tikzpicture} environment, allowing you to change the
+%\env{tikzpicture} settings. By default \cs{DTLpieatbegintikz}
+%does nothing, but you can redefine it to, say, scale the pie
+%chart.
+%
+%\DescribeMacro{\DTLpieatendtikz}
+%\begin{definition}
+%\cs{DTLpieatendtikz}
+%\end{definition}
+%The macro \cs{DTLpieatendtikz} is called at the end of the
+%\env{tikzpicture} environment, allowing you add additional
+%graphics to the pie chart. This does nothing by default.
+%
+%\begin{example}{Adding Information to the Pie Chart}{ex:piescale}
+%This example modifies \autoref{ex:piechart}. It redefines
+%\cs{DTLpieatendtikz} to add an annotated arrow.
+%\begin{verbatim}
+%\begin{figure}[htbp]
+%\centering
+%\DTLpiechart{variable=\quantity}{fruit}{%
+%\name=Name,\quantity=Quantity}
+%\caption{An Annotated Pie Chart}
+%\end{figure}
+%\end{verbatim}
+%This produces \autoref{fig:pieannote}. (Note that the centre
+%of the pie chart is the origin of the TikZ picture.)
+%
+%\begin{figure}[htbp]
+%\centering
+%\renewcommand*{\DTLpieatendtikz}{%
+%\draw[<-] (45:1.5cm) -- (40:2.5cm)node[right]{Apples};}
+%\DTLpiechart{variable=\quantity}{fruit}{\name=Name,\quantity=Quantity}
+%\caption{An Annotated Pie Chart}
+%\label{fig:pieannote}
+%\end{figure}
+%\end{example}
+%
+%\section{Scatter and Line Plots (\texorpdfstring{\sty{dataplot}}{dataplot}
+%package)}
+%
+%The \sty{dataplot} package provides commands for creating
+%scatter or line plots from databases. It uses the pgf/TikZ plot
+%handler library to create the plots. See the \sty{pgf} manual for
+%more detail on pgf streams and plot handles. The \sty{dataplot}
+%package is not loaded by \sty{datatool} so if you want to use
+%it you need to load it explicitly using "\usepackage{dataplot}".
+%
+%\DescribeMacro{\DTLplot}
+%\begin{definition}
+%\cs{DTLplot}\oarg{condition}\marg{db list}\marg{settings}
+%\end{definition}
+%This command creates a plot (inside a \env{tikzpicture} environment)
+%of all the data given in the databases listed in \meta{db list},
+%which should be a comma separated list of database names.
+%The optional argument \meta{condition} is the same as that for
+%\ics{DTLforeach}. The \meta{settings} argument is a comma separated
+%list of \meta{setting}"="\meta{value} pairs. There are two settings
+%that must be specified \setting{DTLplot}{x} and \setting{DTLplot}{y}.
+%The other settings are optional. Note that any value that contains
+%a comma, must be enclosed in braces. For example
+%"colors={red,cyan,blue}". Note where any setting requires
+%a number, or list of numbers (such as \setting{DTLplot}{bounds})
+%the number must be supplied in standard decimal notation (i.e.\
+%no currency, no number groups, and a full stop as the decimal
+%point.) Available settings are as follows:
+%\begin{description}
+%\item[\setting{DTLplot}{x}] The database key
+%that specifies the $x$ co-ordinates. This setting is required.
+%
+%\item[\setting{DTLplot}{y}] The database key that specifies
+%the $y$ co-ordinates. This setting is required.
+%
+%\item[\setting{DTLplot}{markcolors}] A comma separated list of colour
+%names for the markers. An empty value will use the current colour.
+%
+%\item[\setting{DTLplot}{linecolors}] A comma separated list of colour
+%names for the plot lines. An empty value will use the current colour.
+%
+%\item[\setting{DTLplot}{colors}] A comma separated list of colour
+%names for the lines and markers.
+%
+%\item[\setting{DTLplot}{marks}] A comma separated list of
+%code to generate plot marks. (This should typically be a list
+%of \cs{pgfuseplotmark} commands, see the \sty{pgf} manual for
+%further details.) You may use \cs{relax} as an element
+%of the list to suppress markers for the corresponding plot.
+%For example: "marks={\pgfuseplotmark{o},\relax}" will use an
+%open circle marker for the first database, and no markers for the
+%second database listed in \meta{db list}.
+%
+%\item[\setting{DTLplot}{lines}] A comma separated list of
+%line style settings. (This should typically be a list of
+%\cs{pgfsetdash} commands, see the \sty{pgf} manual for
+%further details on how to set the line style.) An empty value
+%will use the current line style.
+%You may use \cs{relax} as an element
+%of the list to suppress line for the corresponding plot.
+%For example: "lines={\relax,\pgfsetdash{}{0pt}}"
+%will have no lines for the first database, and a solid line
+%for the second database listed in \meta{db list}.
+%
+%\item[\setting{DTLplot}{width}] The width of the plot. This must
+%be a length. The plot width does not include outer tick marks or
+%labels.
+%
+%\item[\setting{DTLplot}{height}] The height of the plot. This must
+%be a length. The plot height does not include outer tick marks
+%or labels.
+%
+%\item[\setting{DTLplot}{style}] This setting governs whether
+%to use lines or markers in the plot, and may take one of
+%the following values: "both" (lines and markers),
+%"lines" (only lines) or "markers" (only markers.) The default is
+%"markers".
+%
+%\item[\setting{DTLplot}{axes}] This setting governs whether
+%to display the axes, and may take one of
+%the following values: "both", "x", "y" or "none". If no value
+%is specified, "both" is assumed.
+%
+%\item[\setting{DTLplot}{box}] This setting governs whether
+%or not to surround the plot in a box. It is a boolean setting,
+%taking only the values "true" and "false". If no value is
+%specified, "true" is assumed.
+%
+%\item[\setting{DTLplot}{xtics}] This setting governs whether
+%or not to display the $x$ tick marks. It is a boolean setting,
+%taking only the values "true" and "false". If no value is
+%specified "true" is assumed. If the \setting{DTLplot}{axes}
+%setting is set to "both" or "x", this value will automatically
+%be set to "true", otherwise it will be set to "false".
+%
+%\item[\setting{DTLplot}{ytics}] This setting governs whether
+%or not to display the $y$ ticks. It is a boolean setting,
+%taking only the values "true" and "false". If no value is
+%specified "true" is assumed. If the \setting{DTLplot}{axes}
+%setting is set to "both" or "y", this value will automatically
+%be set to "true", otherwise it will be set to "false".
+%
+%
+%\item[\setting{DTLplot}{xminortics}] This setting governs whether
+%or not to display the $x$ minor tick marks. It is a boolean
+%setting, taking only the values "true" and "false". If no value is
+%specified "true" is assumed. This setting also sets the
+%$x$ major tick marks on if the value is "true".
+%
+%\item[\setting{DTLplot}{yminortics}] This setting governs whether
+%or not to display the $y$ minor tick marks. It is a boolean
+%setting, taking only the values "true" and "false". If no value is
+%specified "true" is assumed. This setting also sets the
+%$y$ major tick marks on if the value is "true".
+%
+%\item[\setting{DTLplot}{xticdir}] This sets the $x$ tick direction,
+%and may only take the values "in" or "out".
+%
+%\item[\setting{DTLplot}{yticdir}] This sets the $y$ tick direction,
+%and may only take the values "in" or "out".
+%
+%\item[\setting{DTLplot}{ticdir}] This sets the $x$ and $y$ tick
+%direction, and may only take the values "in" or "out".
+%
+%\item[\setting{DTLplot}{bounds}] The value must be in the form
+%\meta{min x}","\meta{min y}","\meta{max x}","\meta{max y}. This
+%sets the graph bounds to the given values. If omitted the
+%bounds are computed from the maximum and minimum values of the
+%data. For example
+%\begin{verbatim}
+%\DTLplot{data1,data2}{x=Height,y=Weight,bounds={0,0,10,20}}
+%\end{verbatim}
+%Note that the \setting{DTLplot}{bounds} setting overrides
+%the \setting{DTLplot}{minx}, \setting{DTLplot}{maxx},
+%\setting{DTLplot}{miny} and \setting{DTLplot}{maxy} settings.
+%
+%\item[\setting{DTLplot}{minx}] The value is the minimum value
+%of the $x$ axis.
+%
+%\item[\setting{DTLplot}{miny}] The value is the minimum value
+%of the $y$ axis.
+%
+%\item[\setting{DTLplot}{maxx}] The value is the maximum value
+%of the $x$ axis.
+%
+%\item[\setting{DTLplot}{maxy}] The value is the maximum value
+%of the $y$ axis.
+%
+%\item[\setting{DTLplot}{xticpoints}] The value must be a comma
+%separated list of decimal numbers indicating where to put the
+%$x$ tick marks. If omitted, the $x$ tick marks are placed at
+%equal intervals along the $x$ axis such that each interval is
+%not less than the length given by \ics{DTLmintickgap}.
+%This setting overrides \setting{DTLplot}{xticgap}.
+%
+%\item[\setting{DTLplot}{xticgap}] This value specifies the
+%gap between the $x$ tick marks.
+%
+%\item[\setting{DTLplot}{yticpoints}] The value must be a comma
+%separated list of decimal numbers indicating where to put the
+%$y$ tick marks. If omitted, the $y$ tick marks are placed at
+%equal intervals along the $y$ axis such that each interval is
+%not less than the length given by \ics{DTLmintickgap}.
+%This setting overrides \setting{DTLplot}{yticgap}.
+%
+%\item[\setting{DTLplot}{yticgap}] This value specifies the
+%gap between the $y$ tick marks.
+%
+%\item[\setting{DTLplot}{grid}] This is a boolean value that
+%specifies whether or not to display the grid. If no value
+%is given, "true" is assumed. The minor grid lines are only
+%displayed if the minor tick marks are set.
+%
+%\item[\setting{DTLplot}{xticlabels}] The value must be a comma
+%separated list of labels for each $x$ tick mark. If omitted,
+%the labels are the value of the $x$ tick position, rounded
+%\meta{n} digits after the decimal point, where \meta{n} is
+%given by the value of the counter \counterfmt{DTLplotroundXvar}.
+%
+%\item[\setting{DTLplot}{yticlabels}] The value must be a comma
+%separated list of labels for each $y$ tick mark. If omitted,
+%the labels are the value of the $y$ tick position, rounded
+%\meta{n} digits after the decimal point, where \meta{n} is
+%given by the value of the counter \counterfmt{DTLplotroundYvar}.
+%
+%\item[\setting{DTLplot}{xlabel}] The value is the label for
+%the $x$ axis. If omitted, the axis has no label.
+%
+%\item[\setting{DTLplot}{ylabel}] The value is the label for
+%the $y$ axis. If omitted, the axis has no label.
+%
+%\item[\setting{DTLplot}{legend}] This setting governs whether
+%or not to display the legend, and where it should be displayed.
+%It may take one of the following values "none" (don't display
+%the legend), "north", "northeast", "east", "southeast", "south",
+%"southwest", "west" or "northwest". If the value is omitted,
+%"northeast" is assumed.
+%
+%\item[\setting{DTLplot}{legendlabels}] The value must be a comma
+%separated list of labels for the legend. If omitted, the database
+%names are used.
+%
+%\end{description}
+%
+%\begin{example}{A Basic Graph}{ex:basicplot}
+%Suppose you have a file called "groupa.csv" that contains the
+%following:
+%\DTLnewdb{groupa}\relax
+%\DTLnewrow{groupa}\relax
+%\DTLnewdbentry{groupa}{Height}{1.55}\relax
+%\DTLnewdbentry{groupa}{Weight}{45.4}\relax
+%\DTLnewrow{groupa}\relax
+%\DTLnewdbentry{groupa}{Height}{1.54}\relax
+%\DTLnewdbentry{groupa}{Weight}{48.0}\relax
+%\DTLnewrow{groupa}\relax
+%\DTLnewdbentry{groupa}{Height}{1.56}\relax
+%\DTLnewdbentry{groupa}{Weight}{58.0}\relax
+%\DTLnewrow{groupa}\relax
+%\DTLnewdbentry{groupa}{Height}{1.56}\relax
+%\DTLnewdbentry{groupa}{Weight}{50.2}\relax
+%\DTLnewrow{groupa}\relax
+%\DTLnewdbentry{groupa}{Height}{1.57}\relax
+%\DTLnewdbentry{groupa}{Weight}{46.0}\relax
+%\DTLnewrow{groupa}\relax
+%\DTLnewdbentry{groupa}{Height}{1.58}\relax
+%\DTLnewdbentry{groupa}{Weight}{48.3}\relax
+%\DTLnewrow{groupa}\relax
+%\DTLnewdbentry{groupa}{Height}{1.59}\relax
+%\DTLnewdbentry{groupa}{Weight}{56.5}\relax
+%\DTLnewrow{groupa}\relax
+%\DTLnewdbentry{groupa}{Height}{1.59}\relax
+%\DTLnewdbentry{groupa}{Weight}{58.1}\relax
+%\DTLnewrow{groupa}\relax
+%\DTLnewdbentry{groupa}{Height}{1.60}\relax
+%\DTLnewdbentry{groupa}{Weight}{60.9}\relax
+%\DTLnewrow{groupa}\relax
+%\DTLnewdbentry{groupa}{Height}{1.62}\relax
+%\DTLnewdbentry{groupa}{Weight}{56.3}\relax
+%\begin{ttfamily}\obeylines\setlength{\parindent}{0pt}
+%Height,Weight
+%\DTLforeach{groupa}{\x=Height,\y=Weight}{\x,\y
+%}\end{ttfamily}\par\noindent
+%First load this into a database called "groupa":
+%\begin{verbatim}
+%\DTLloaddb{groupa}{groupa.csv}
+%\end{verbatim}
+%The data can now be converted into a scatter plot as follows:
+%\begin{verbatim}
+%\begin{figure}[htbp]
+%\centering
+%\DTLplot{groupa}{x=Height,y=Weight}
+%\caption{A Scatter Plot}
+%\end{figure}
+%\end{verbatim}
+%This produces \autoref{fig:basicplot}.
+%
+%\begin{figure}[htbp]
+%\centering
+%\DTLplot{groupa}{x=Height,y=Weight}
+%\caption{A Scatter Plot}
+%\label{fig:basicplot}
+%\end{figure}
+%
+%Alternatively, you can use the \setting{DTLplot}{style} setting
+%to change it into a line plot:
+%\begin{verbatim}
+%\begin{figure}[htbp]
+%\centering
+%\DTLplot{groupa}{x=Height,y=Weight,style=lines}
+%\caption{A Line Plot}
+%\end{figure}
+%\end{verbatim}
+%This produces \autoref{fig:basiclineplot}.
+%
+%\begin{figure}[htbp]
+%\centering
+%\DTLplot{groupa}{x=Height,y=Weight,style=lines}
+%\caption{A Line Plot}
+%\label{fig:basiclineplot}
+%\end{figure}
+%\end{example}
+%
+%\begin{example}{Plotting Multiple Data Sets}{ex:2db}
+%In this example, I shall use the database called "groupa" defined
+%in \autoref{ex:basicplot}, and another database called "groupb"
+%which is loaded from the file "groupb.csv" which contains the
+%following:
+%\DTLnewdb{groupb}
+%\DTLnewrow{groupb}\relax
+%\DTLnewdbentry{groupb}{Height}{1.54}\relax
+%\DTLnewdbentry{groupb}{Weight}{48.4}\relax
+%\DTLnewrow{groupb}\relax
+%\DTLnewdbentry{groupb}{Height}{1.54}\relax
+%\DTLnewdbentry{groupb}{Weight}{42.0}\relax
+%\DTLnewrow{groupb}\relax
+%\DTLnewdbentry{groupb}{Height}{1.55}\relax
+%\DTLnewdbentry{groupb}{Weight}{64.0}\relax
+%\DTLnewrow{groupb}\relax
+%\DTLnewdbentry{groupb}{Height}{1.56}\relax
+%\DTLnewdbentry{groupb}{Weight}{58.2}\relax
+%\DTLnewrow{groupb}\relax
+%\DTLnewdbentry{groupb}{Height}{1.56}\relax
+%\DTLnewdbentry{groupb}{Weight}{49.0}\relax
+%\DTLnewrow{groupb}\relax
+%\DTLnewdbentry{groupb}{Height}{1.57}\relax
+%\DTLnewdbentry{groupb}{Weight}{40.3}\relax
+%\DTLnewrow{groupb}\relax
+%\DTLnewdbentry{groupb}{Height}{1.58}\relax
+%\DTLnewdbentry{groupb}{Weight}{51.5}\relax
+%\DTLnewrow{groupb}\relax
+%\DTLnewdbentry{groupb}{Height}{1.58}\relax
+%\DTLnewdbentry{groupb}{Weight}{63.1}\relax
+%\DTLnewrow{groupb}\relax
+%\DTLnewdbentry{groupb}{Height}{1.59}\relax
+%\DTLnewdbentry{groupb}{Weight}{74.9}\relax
+%\DTLnewrow{groupb}\relax
+%\DTLnewdbentry{groupb}{Height}{1.59}\relax
+%\DTLnewdbentry{groupb}{Weight}{59.3}\relax
+%\begin{ttfamily}\obeylines\setlength{\parindent}{0pt}
+%Height,Weight
+%\DTLforeach{groupb}{\x=Height,\y=Weight}{\x,\y
+%}\end{ttfamily}\par\noindent
+%First load this into a database called "groupb":
+%\begin{verbatim}
+%\DTLloaddb{groupb}{groupb.csv}
+%\end{verbatim}
+%I can now plot both groups in the same graph, but I want a smaller
+%graph than \autoref{fig:basicplot} and \autoref{fig:basiclineplot},
+%so I am going to set the plot width and height to 3in:
+%\begin{verbatim}
+%\begin{figure}[htbp]
+%\centering
+%\DTLplot{groupa,groupb}{x=Height,y=Weight,width=3in,height=3in}
+%\caption{A Scatter Plot}
+%\end{figure}
+%\end{verbatim}
+%This produces \autoref{fig:2db}.
+%
+%\begin{figure}[htbp]
+%\centering
+%\DTLplot{groupa,groupb}{x=Height,y=Weight,width=3in,height=3in}
+%\caption{A Scatter Plot}
+%\end{figure}
+%\label{fig:2db}
+%
+%Now let's add a legend using the \setting{DTLplot}{legend} setting,
+%with the legend labels "Group A" and "Group B",
+%and set the $x$ tick intervals using \setting{DTLplot}{xticpoints}
+%setting. I am also going to set the $x$ axis label to
+%"Height (m)" and the $y$ axis label to "Weight (kg)", and place
+%a box around the plot.
+%\begin{verbatim}
+%\begin{figure}[htbp]
+%\centering
+%\DTLplot{groupa,groupb}{x=Height,y=Weight,
+%width=3in,height=3in,legend,legendlabels={Group A,Group B},
+%xlabel={Height (m)},ylabel={Weight (kg)},box,
+%xticpoints={1.54,1.55,1.56,1.57,1.58,1.59,1.60,1.61,1.62}}
+%\caption{A Scatter Plot}
+%\end{figure}
+%\end{verbatim}
+%This produces \autoref{fig:legend}.
+%
+%\begin{figure}[htbp]
+%\centering
+%\DTLplot{groupa,groupb}{x=Height,y=Weight,legend,
+%width=3in,height=3in,legendlabels={Group A,Group B},
+%xlabel={Height (m)},ylabel={Weight (kg)},box,
+%xticpoints={1.54,1.55,1.56,1.57,1.58,1.59,1.60,1.61,1.62}}
+%\caption{A Scatter Plot}
+%\label{fig:legend}
+%\end{figure}
+%\end{example}
+%
+%\subsection{Adding Information to the Plot}
+%
+%The \sty{datatool} package provides two hooks used at the beginning
+%and end of the \env{tikzpicture} environment:
+%\DescribeMacro{\DTLplotatbegintikz}
+%\begin{definition}
+%\cs{DTLplotatbegintikz}
+%\end{definition}\noindent
+%and
+%\DescribeMacro{\DTLplotatendtikz}
+%\begin{definition}
+%\cs{DTLplotatendtikz}
+%\end{definition}
+%They are both defined to do nothing by default, but can be redefined
+%to add commands to the image. The unit vectors are set prior to
+%using these hooks, so you can use the same co-ordinates as those
+%in the data sets.
+%
+%\DescribeMacro{\DTLaddtoplotlegend}
+%\begin{definition}
+%\cs{DTLaddtoplotlegend}\marg{marker}\marg{line style}\marg{text}
+%\end{definition}
+%This adds a new row to the plot legend where \meta{marker} is
+%code to produce the marker, \meta{line style} is code to set
+%the line style and \meta{text} is a textual label. You can
+%use \cs{relax} to suppress the marker or line. For example:
+%\begin{verbatim}
+%\DTLaddtoplotlegend{\pgfuseplotmark{x}}{\relax}{Some Data}
+%\end{verbatim}
+%Note that the legend is plotted before \cs{DTLplotatendtikz},
+%so if you want to add information to the legend you will need
+%to do the in \cs{DTLplotatstarttikz}.
+%
+%\begin{example}{Adding Information to a Plot}{ex:addtoplot}
+%Returning to the plots created in \autoref{ex:2db}, suppose
+%I now want to annotate the plot, say I want to draw your notice
+%to a particular point, say the point (1.58,48.3), then I can
+%redefine \cs{DTLplotatendtikz} to draw an annotated arrow to
+%that point:
+%\begin{verbatim}
+%\renewcommand*{\DTLplotatendtikz}{%
+%\draw[<-,line width=1pt] (1.58,48.3) -- (1.6,43)
+% node[below]{interesting point};
+%}
+%\end{verbatim}
+%So \autoref{fig:legend} now looks like \autoref{fig:annote}.
+%
+%\begin{figure}[htbp]
+%\renewcommand*{\DTLplotatendtikz}{%
+%\draw[<-,line width=1pt] (1.58,48.3) -- (1.6,43)
+% node[below]{interesting point};
+%}
+%\centering
+%\DTLplot{groupa,groupb}{x=Height,y=Weight,legend,
+%width=3in,height=3in,legendlabels={Group A,Group B},box,
+%xlabel={Height (m)},ylabel={Weight (kg)},
+%xticpoints={1.54,1.55,1.56,1.57,1.58,1.59,1.60,1.61,1.62}}
+%\caption{A Scatter Plot}
+%\label{fig:annote}
+%\end{figure}
+%\end{example}
+%
+%\subsection{Global Plot Settings}
+%
+%\subsubsection{Lengths}
+%This section describes the lengths that govern the appearance of
+%the plot created using \ics{DTLplot}. These lengths can be
+%changed using \cs{setlength}.
+%
+%\DescribeMacro{\DTLplotwidth}
+%\begin{definition}
+%\cs{DTLplotwidth}
+%\end{definition}
+%This length governs the length of the $x$ axis. Note that the plot
+%width does not include any outer tick marks or labels. The default
+%value is 4in.
+%
+%\DescribeMacro{\DTLplotheight}
+%\begin{definition}
+%\cs{DTLplotheight}
+%\end{definition}
+%This length governs the length of the $y$ axis. Note that the plot
+%height does not include any outer tick marks or labels. The default
+%value is 4in
+%
+%\DescribeMacro{\DTLticklength}
+%\begin{definition}
+%\cs{DTLticklength}
+%\end{definition}
+%This governs the length of the tick marks. The default value is
+%5pt.
+%
+%\DescribeMacro{\DTLminorticklength}
+%\begin{definition}
+%\cs{DTLminorticklength}
+%\end{definition}
+%This governs the length of the minor tick marks. The default value is
+%2pt.
+%
+%\DescribeMacro{\DTLticklabeloffset}
+%\begin{definition}
+%\cs{DTLticklabeloffset}
+%\end{definition}
+%This governs the distance from the axis to the tick labels. The
+%default value is 8pt.
+%
+%\DescribeMacro{\DTLmintickgap}
+%\begin{definition}
+%\cs{DTLmintickgap}
+%\end{definition}
+%This is the minimum distance allowed between tick marks. If the
+%plot width or height is less than this distance there will only
+%be tick marks at either end of the axis. The default value is
+%20pt.
+%
+%\DescribeMacro{\DTLlegendxoffset}
+%\begin{definition}
+%\cs{DTLlegendxoffset}
+%\end{definition}
+%This is the horizontal distance from the border of the plot to the
+%outer border of the legend. The default value is 10pt.
+%
+%\DescribeMacro{\DTLlegendyoffset}
+%\begin{definition}
+%\cs{DTLlegendyoffset}
+%\end{definition}
+%This is the vertical distance from the border of the plot to the
+%outer border of the legend. The default value is 10pt.
+%
+%\subsubsection{Counters}
+%These counters govern the appearance of plots
+%created using \ics{DTLplot}. The value of the counters can be
+%changed using \cs{setcounter}.
+%
+%\begin{definition}
+%\counterfmt{DTLplotroundXvar}
+%\end{definition}
+%Unless you specify your own tick labels, the $x$ tick labels will
+%be given by the tick points rounded to \meta{n} digits after the
+%decimal point, where \meta{n} is the value of the counter
+%\counterfmt{DTLplotroundXvar}.
+%
+%\begin{definition}
+%\counterfmt{DTLplotroundYvar}
+%\end{definition}
+%Unless you specify your own tick labels, the $y$ tick labels will
+%be given by the tick points rounded to \meta{n} digits after the
+%decimal point, where \meta{n} is the value of the counter
+%\counterfmt{DTLplotroundYvar}.
+%
+%\subsubsection{Macros}
+%These macros govern the appearance of plots created using
+%\ics{DTLplot}. They can be changed using \cs{renewcommand}.
+%
+%\DescribeMacro{\DTLplotmarks}
+%\begin{definition}
+%\cs{DTLplotmarks}
+%\end{definition}
+%This must be a comma separated list of \sty{pgf} code to create the
+%plot marks. \ics{DTLplot} cycles through this list for each
+%database listed. The \sty{pgf} package provides convenient commands
+%for generating plots using \cs{pgfuseplotmark}. See the \sty{pgf}
+%manual for more details.
+%
+%\DescribeMacro{\DTLplotmarkcolors}
+%\begin{definition}
+%\cs{DTLplotmarkcolors}
+%\end{definition}
+%This must be a comma separated list of defined colours to apply to the
+%plot marks. \ics{DTLplot} cycles through this list for each database
+%listed. If this macro is set to empty, the current colour will
+%be used instead.
+%
+%\DescribeMacro{\DTLplotlines}
+%\begin{definition}
+%\cs{DTLplotlines}
+%\end{definition}
+%This must be a comma separated list of \sty{pgf} code to set the
+%style of the plot lines. \ics{DTLplot} cycles through this list for
+%each database listed. Dash patterns can be set using \cs{pgfsetdash},
+%see the \sty{pgf} manual for more details. If \cs{DTLplotlines} is
+%set to empty the current line style will be used instead.
+%
+%\DescribeMacro{\DTLplotlinecolors}
+%\begin{definition}
+%\cs{DTLplotlinecolors}
+%\end{definition}
+%This must be a comma separated list of defined colours to apply to the
+%plot lines. \cs{DTLplot} cycles through this list for each database
+%listed. If this macro is set to empty, the current colour will
+%be used instead. The default is the same as \cs{DTLplotmarkcolors}.
+%
+%\DescribeMacro{\DTLXAxisStyle}
+%\begin{definition}
+%\cs{DTLxaxisstyle}
+%\end{definition}
+%This governs the style of the $x$ axis. It is passed as the optional
+%argument to the TikZ \cs{draw} command. By default it is just "-"
+%which is a solid line style with no start or end arrows. The $x$
+%axis line starts from the bottom left corner of the plot and extends
+%to the bottom right corner of the plot. So if you want the $x$ axis
+%to have an arrow head at the right end, you can do:
+%\begin{verbatim}
+%\renewcommand*{\DTLXAxisStyle}{->}
+%\end{verbatim}
+%
+%\DescribeMacro{\DTLYAxisStyle}
+%\begin{definition}
+%\cs{DTLyaxisstyle}
+%\end{definition}
+%This governs the style of the $y$ axis. It is analogous to
+%\cs{DTLxaxisstyle} described above.
+%
+%\DescribeMacro{\DTLmajorgridstyle}
+%\begin{definition}
+%\cs{DTLmajorgridstyle}
+%\end{definition}
+%This specifies the format of the major grid lines.
+%It may be set to any TikZ setting that you can pass to the
+%optional argument of \cs{draw}. The default value is
+%"color=gray,-" which indicates a grey solid line.
+%
+%\DescribeMacro{\DTLminorgridstyle}
+%\begin{definition}
+%\cs{DTLminorgridstyle}
+%\end{definition}
+%This specifies the format of the minor grid lines.
+%It may be set to any TikZ setting that you can pass to the
+%optional argument of \cs{draw}. The default value is
+%"color=gray,loosely dotted" which indicates a grey dotted line.
+%
+%\DescribeMacro{\DTLformatlegend}
+%\begin{definition}
+%\cs{DTLformatlegend}\marg{legend}
+%\end{definition}
+%This formats the entire legend, which is passed as the argument.
+%The default is to set the legend with
+%a white background, a black frame.
+%
+%\subsection{Adding to a Plot Stream}
+%\DescribeMacro{\DTLplotstream}
+%\begin{definition}
+%\cs{DTLplotstream}\oarg{condition}\marg{db name}\marg{x key}\marg{y key}
+%\end{definition}
+%This adds 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}.
+%(\ics{DTLconverttodecimal} is used to convert locale dependent
+%values to a standard decimal that is recognised by the
+%\sty{pgf} package.)
+%The optional argument \meta{condition} is the same as that
+%for \ics{DTLforeach}.
+%
+%\begin{example}{Adding to a Plot Stream}{ex:plotstream}
+%Suppose you have a CSV file called "data.csv" containing the
+%following:
+%\begin{verbatim}
+%x,y
+%0,0
+%1,1
+%2,0.5
+%1.5,0.3
+%\end{verbatim}
+%\DTLnewdb{data}\relax
+%\DTLnewrow{data}\relax
+%\DTLnewdbentry{data}{x}{0}\relax
+%\DTLnewdbentry{data}{y}{0}\relax
+%\DTLnewrow{data}\relax
+%\DTLnewdbentry{data}{x}{1}\relax
+%\DTLnewdbentry{data}{y}{1}\relax
+%\DTLnewrow{data}\relax
+%\DTLnewdbentry{data}{x}{2}\relax
+%\DTLnewdbentry{data}{y}{0.5}\relax
+%\DTLnewrow{data}\relax
+%\DTLnewdbentry{data}{x}{1.5}\relax
+%\DTLnewdbentry{data}{y}{0.3}\relax
+%First load the file into a database called "data":
+%\begin{verbatim}
+%\DTLloaddb{data}{data.csv}
+%\end{verbatim}
+%Now create a figure containing this data:
+%\begin{verbatim}
+%\begin{figure}[tbhp]
+%\centering
+%\begin{tikzpicture}
+%\pgfplothandlermark{\pgfuseplotmark{o}}
+%\pgfplotstreamstart
+%\DTLplotstream{data}{x}{y}%
+%\pgfplotstreamend
+%\pgfusepath{stroke}
+%\end{tikzpicture}
+%\caption{Adding to a Plot Stream}
+%\end{figure}
+%\end{verbatim}
+%This produces \autoref{fig:plotstream}.
+%
+%\begin{figure}[tbhp]
+%\centering
+%\begin{tikzpicture}
+%\pgfplothandlermark{\pgfuseplotmark{o}}
+%\pgfplotstreamstart
+%\DTLplotstream{data}{x}{y}%
+%\pgfplotstreamend
+%\pgfusepath{stroke}
+%\end{tikzpicture}
+%\caption{Adding to a Plot Stream}
+%\label{fig:plotstream}
+%\end{figure}
+%\end{example}
+%
+%\begin{example}{Plotting Multiple Keys in the Same
+%Database}{ex:multikey}
+%Suppose I have conducted two time to growth experiments. For each
+%experiment, I have recorded the log count at set times, and I have
+%recorded this information in the same data file called, say,
+%"growth.csv" which contains the following:
+%\begin{verbatim}
+%Time,Experiment 1,Experiment 2
+%0,3.73,3.6
+%23,3.67,3.7
+%60,4.9,3.8
+%\end{verbatim}
+%\DTLnewdb{growth}\DTLnewrow{growth}\relax
+%\DTLnewdbentry{growth}{Time}{0}\relax
+%\DTLnewdbentry{growth}{Experiment 1}{3.73}\relax
+%\DTLnewdbentry{growth}{Experiment 2}{3.6}\relax
+%\DTLnewrow{growth}\relax
+%\DTLnewdbentry{growth}{Time}{23}\relax
+%\DTLnewdbentry{growth}{Experiment 1}{3.67}\relax
+%\DTLnewdbentry{growth}{Experiment 2}{3.7}\relax
+%\DTLnewrow{growth}\relax
+%\DTLnewdbentry{growth}{Time}{60}\relax
+%\DTLnewdbentry{growth}{Experiment 1}{4.9}\relax
+%\DTLnewdbentry{growth}{Experiment 2}{3.8}\relax
+%I can load the data into a database using:
+%\begin{verbatim}
+%\DTLloaddb{growth}{growth.csv}
+%\end{verbatim}
+%However, I'd like to plot both results on the same graph. Since they
+%are contained in the same database, I can't use the method I used
+%in \autoref{ex:2db}. Instead I can use a combination of
+%\ics{DTLplot} and \ics{DTLplotstream}:
+%\begin{verbatim}
+%\begin{figure}[tbhp]
+%\centering
+%% computer bounds
+%\DTLminforkeys{growth}{Time}{\minX}
+%\DTLminforkeys{growth}{Experiment 1,Experiment 2}{\minY}
+%\DTLmaxforkeys{growth}{Time}{\maxX}
+%\DTLmaxforkeys{growth}{Experiment 1,Experiment 2}{\maxY}
+%% round x tick labels
+%\setcounter{DTLplotroundXvar}{0}
+%% redefine \DTLplotatbegintikz to plot the data for Experiment 1
+%\renewcommand*{\DTLplotatbegintikz}{%
+%% set plot mark
+%\pgfplothandlermark{\color{green}\pgfuseplotmark{x}}
+%% start plot stream
+%\pgfplotstreamstart
+%% add data from Experiment 1 to plot stream
+%\DTLplotstream{growth}{Time}{Experiment 1}%
+%% end plot stream
+%\pgfplotstreamend
+%% stroke path
+%\pgfusepath{stroke}
+%% add information to legend (no line is require so use \relax)
+%\DTLaddtoplotlegend{\color{green}%
+%\pgfuseplotmark{x}}{\relax}{Experiment 1}
+%}
+%% now plot the data for Experiment 2
+%\DTLplot{growth}{x=Time,y=Experiment 2,legend,
+%width=3in,height=3in,bounds={\minX,\minY,\maxX,\maxY},
+%xlabel={Time},ylabel={Log Count},
+%legendlabels={Experiment 2}}
+%\caption{Time to Growth Data}
+%\end{figure}
+%\end{verbatim}
+%This produces \autoref{fig:multikey}.
+%Notes:
+%\begin{itemize}
+%\item I redefined \ics{DTLplotatbegintikz} in order to add
+%the new plot to the legend, since \ics{DTLplotatendtikz} is
+%used after the legend is plotted. The $x$ and $y$ unit vectors
+%are set before \ics{DTLplotatbegintikz} so I don't need to
+%worry about the co-ordinates.
+%\item I set the counter \counterfmt{DTLplotroundXvar} to zero
+%otherwise the $x$ axis would have looked too cluttered.
+%\item I have used \ics{DTLminforkeys} and \ics{DTLmaxforkeys} to
+%determine the bounds since \ics{DTLplot} won't take the data
+%for Experiment 1 into account when computing the bounds.
+%\end{itemize}
+%
+%\begin{figure}[htbp]
+%\DTLminforkeys{growth}{Time}{\minX}
+%\DTLminforkeys{growth}{Experiment 1,Experiment 2}{\minY}
+%\DTLmaxforkeys{growth}{Time}{\maxX}
+%\DTLmaxforkeys{growth}{Experiment 1,Experiment 2}{\maxY}
+%\setcounter{DTLplotroundXvar}{0}
+%\renewcommand*{\DTLplotatbegintikz}{%
+%\pgfplothandlermark{\color{green}\pgfuseplotmark{x}}
+%\pgfplotstreamstart
+%\DTLplotstream{growth}{Time}{Experiment 1}%
+%\pgfplotstreamend
+%\pgfusepath{stroke}
+%\DTLaddtoplotlegend{\color{green}\pgfuseplotmark{x}}{\relax}{Experiment 1}
+%}
+%\centering
+%\DTLplot{growth}{x=Time,y=Experiment 2,legend,
+%width=3in,height=3in,bounds={\minX,\minY,\maxX,\maxY},
+%xlabel={Time},ylabel={Log Count},
+%legendlabels={Experiment 2}}
+%\caption{Time to Growth Data}
+%\label{fig:multikey}
+%\end{figure}
+%\end{example}
+%
+%\section{Bar Charts (\texorpdfstring{databar}{databar} package)}
+%
+%The \sty{databar} package provides commands for creating bar charts.
+%It is not loaded by the \sty{datatool} package, so if you want to
+%use it you will need to load it explicitly using
+%"\usepackage{databar}".
+%
+%Bar charts can either be vertical or horizontal, the default is
+%vertical. In this section the $x$ axis refers to the horizontal
+%axis when plotting a vertical bar chart and to the vertical axis
+%when plotting a horizontal bar chart. The $x$ axis units are in
+%increments of one bar. The $y$ axis refers to the vertical axis
+%when plotting a vertical bar chart and to the horizontal axis when
+%plotting a horizontal bar chart. The $y$ axis uses the same
+%co-ordinates as the data. The bars may have an upper and lower
+%label. In a vertical bar chart, the lower label is placed below
+%the $x$ axis and the upper label is placed above the top of the bar.
+%In a horizontal bar chart, the lower label is placed to the left of
+%the $x$ axis and the upper label is placed to the right of the
+%end of the bar. (This is actually a misnomer as it is possible
+%for the ``upper'' label to be below the ``lower'' label if a
+%bar has a negative value, however the bars are considered to
+%be anchored on the $x$ axis, and the other end of the bar is
+%considered to be the ``upper'' end, regardless of its
+%direction.)
+%
+%The \sty{databar} package options are as follows:
+%\begin{description}
+%\item[{\pkgopt[databar]{color}}] Created coloured bar charts
+%(default.)
+%
+%\item[{\pkgopt[databar]{gray}}] Created grey scale bar charts.
+%
+%\item[{\pkgopt[databar]{vertical}}] Created vertical bar charts
+%(default.)
+%
+%\item[{\pkgopt[databar]{horizontal}}] Created horizontal bar charts.
+%\end{description}
+%
+%
+%\DescribeMacro{\DTLbarchart}
+%\begin{definition}
+%\cs{DTLbarchart}\oarg{condition}\marg{db name}\marg{settings}\marg{values}
+%\end{definition}
+%\DescribeMacro{\DTLmultibarchart}
+%\begin{definition}
+%\cs{DTLmultibarchart}\oarg{condition}\marg{db name}\marg{settings}\marg{values}
+%\end{definition}
+%These commands both create a bar chart from the information in
+%the database \meta{db name}, where \meta{condition} is the same
+%as the optional argument for \ics{DTLforeach} described in
+%\autoref{sec:dbforeach}, and \meta{values} is the same as the
+%penultimate argument of \ics{DTLforeach}. The \meta{settings}
+%argument is a \meta{setting}"="\meta{value} list of settings. The
+%first command, \cs{DLTbarchart}, will draw a bar chart for a
+%given column of data in the database, whereas the second command,
+%\cs{DTLmultibarchart}, will draw a bar chart that is divided into
+%groups of bars where each bar within a group represents data from
+%several columns of a given row in the database.
+%
+%The \setting{DTLbarchart}{variable} setting is
+%required for \cs{DTLbarchart} and the
+%\setting{DTLmultibarchart}{variables}, the other settings are
+%optional (though some may only be used for one of
+%\cs{DTLbarchart} and \cs{DLTmultibarchart}), and are as follows:
+%
+%\begin{description}
+%\item[\setting{DTLbarchart}{variable}]
+%This specifies the control sequence to use that
+%contains the value used to construct the bar chart. The control
+%sequence must be one of the control sequences to appear in
+%the assignment list \meta{values}. This setting is required
+%for \cs{DTLbarchart}, and is unavailable for \cs{DTLmultibarchart}.
+%
+%\item[\setting{DTLmultibarchart}{variables}]
+%This specifies a list of control sequences to use which
+%contain the values used to construct the bar chart. Each control
+%sequence must be one of the control sequences to appear in
+%the assignment list \meta{values}. This setting is required
+%for \cs{DTLmultibarchart}, and is unavailable for
+%\cs{DTLbarchart}.
+%
+%\item[\setting{DTLbarchart,DTLmultibarchart}{max}]
+%This specifies the maximum value on the $y$ axis. (This should
+%be a standard decimal value.)
+%
+%\item[\setting{DTLbarchart,DTLmultibarchart}{length}]
+%This specifies the overall length of the $y$ axis, and must
+%be a dimension.
+%
+%\item[\setting{DTLbarchart,DTLmultibarchart}{maxdepth}]
+%This must be a zero or negative number. It specifies the maximum
+%depth of the $y$ axis. (This should be a standard decimal value.)
+%
+%\item[\setting{DTLbarchart,DTLmultibarchart}{axes}]
+%This setting specifies which axes to display. This may take one
+%of the following values: "both", "x", "y" or "none".
+%
+%\item[\setting{DTLbarchart,DTLmultibarchart}{barlabel}]
+%This setting specifies the lower bar label. When used with
+%\cs{DTLmultibarchart} it indicates the group label.
+%
+%\item[\setting{DTLmultibarchart}{multibarlabels}]
+%This setting should contain a comma separated list of labels
+%for each bar within a group for \cs{DTLmultibarchart}. This
+%setting is not available for \cs{DTLbarchart}.
+%
+%\item[\setting{DTLbarchart}{upperbarlabel}]
+%This setting specifies the upper bar label. This setting
+%is not available for \cs{DTLmultibarchart}.
+%
+%\item[\setting{DTLmultibarchart}{uppermultibarlabels}]
+%This setting must be a comma separated list of upper bar
+%labels for each bar within a group. This setting is not
+%available for \cs{DTLbarchart}.
+%
+%\item[\setting{DTLbarchart,DTLmultibarchart}{yticpoints}]
+%This must be a comma separated list of tick locations for the
+%$y$ axis. (These should be standard decimal values.)
+%This setting overrides \setting{DTLbarchart}{yticgap}.
+%
+%\item[\setting{DTLbarchart,DTLmultibarchart}{yticgap}]
+%This specifies the gap between the $y$ tick marks. (This should
+%be a standard decimal value.)
+%
+%\item[\setting{DTLbarchart,DTLmultibarchart}{yticlabels}]
+%This must be a comma separated list of tick labels for the
+%$y$ axis.
+%
+%\item[\setting{DTLbarchart,DTLmultibarchart}{ylabel}]
+%This specifies the label for the $y$ axis.
+%
+%\item[\setting{DTLmultibarchart}{groupgap}] This specifies
+%the gap between groups when using \cs{DTLmultibarchart}.
+%This value is given as a multiple of the bar width. The
+%default value is 1, which indicates a gap of one bar width.
+%This setting is not available for \cs{DTLbarchart}.
+%
+%\item[\setting{DTLbarchart,DTLmultibarchart}{verticalbars}]
+%This is a boolean setting, so it can only take the values
+%"true" (do a vertical bar chart) or "false" (do a horizontal
+%bar chart.) If the value is omitted, "true" is assumed.
+%\end{description}
+%
+%\begin{example}{A Basic Bar Chart}{ex:barchart}
+%Recall \autoref{ex:piechart} defined a database called "fruit".
+%This example will be using that database to plot a bar chart.
+%The following plots a basic vertical bar chart:
+%\begin{verbatim}
+%\begin{figure}[htbp]
+%\centering
+%\DTLbarchart{variable=\theQuantity}{fruit}{\theQuantity=Quantity}
+%\caption{A Basic Bar Chart}
+%\end{figure}
+%\end{verbatim}
+%This produces \autoref{fig:barchart}.
+%
+%\begin{figure}[htbp]
+%\centering
+%\DTLbarchart{variable=\theQuantity}{fruit}{\theQuantity=Quantity}
+%\caption{A Basic Bar Chart}
+%\label{fig:barchart}
+%\end{figure}
+%\end{example}
+%
+%\subsection{Changing the Appearance of a Bar Chart}
+%
+%\DescribeMacro{\DTLbarchartlength}
+%\begin{definition}
+%\cs{DTLbarchartlength}
+%\end{definition}
+%This specifies the total length of the $y$ axis. You must use
+%\cs{setlength} to change this value. The default value is 3in.
+%
+%\DescribeMacro{\DTLbarwidth}
+%\begin{definition}
+%\cs{DTLbarwidth}
+%\end{definition}
+%This specifies the width of each bar. You must use \cs{setlength}
+%to change this value. The default value is 1cm.
+%
+%\DescribeMacro{\DTLbarlabeloffset}
+%\begin{definition}
+%\cs{DTLbarlabeloffset}
+%\end{definition}
+%This specifies the distance from the $x$ axis to the lower bar label.
+%You must use \cs{setlength} to change this value. The default value
+%is 10pt.
+%
+%\begin{definition}
+%\counterfmt{DTLbarroundvar}
+%\end{definition}
+%The $y$ tick labels are rounded to \meta{n} digits after the
+%decimal point, where \meta{n} is given by the value of the
+%counter \counterfmt{DTLbarroundvar}. You must use \cs{setcounter}
+%to change this value.
+%
+%\DescribeMacro{\DTLsetbarcolor}
+%\begin{definition}
+%\cs{DTLsetbarcolor}\marg{n}\marg{color}
+%\end{definition}
+%This sets the \meta{n}th bar colour to \meta{color}.
+%Only the first eight bars have a colour defined by default. If you
+%need more than eight bars, you will need to define more bar colours.
+%
+%\DescribeMacro{\DTLdobarcolor}
+%\begin{definition}
+%\cs{DTLdobarcolor}\marg{n}
+%\end{definition}
+%This sets the current colour to the colour of the \meta{n}th bar.
+%
+%\DescribeMacro{\DTLbaroutlinecolor}
+%\begin{definition}
+%\cs{DTLbaroutlinecolor}
+%\end{definition}
+%This macro contains the colour of the bar outlines. This defaults
+%to "black".
+%
+%\DescribeMacro{\DTLbaroutlinewidth}
+%\begin{definition}
+%\cs{DTLbaroutlinewidth}
+%\end{definition}
+%This length specifies the line width for the bar outlines. If it
+%is 0pt, the outline is not drawn. The default value is 0pt.
+%
+%\DescribeMacro{\DTLbaratbegintikz}
+%\begin{definition}
+%\cs{DTLbaratbegintikz}
+%\end{definition}
+%This specifies any additional commands to add to the start of
+%the plot. It defaults to nothing, and is called after the
+%unit vectors are set.
+%
+%\DescribeMacro{\DTLbaratendtikz}
+%\begin{definition}
+%\cs{DTLbaratendtikz}
+%\end{definition}
+%This specifies any additional commands to add to the end of
+%the plot. It defaults to nothing.
+%
+%\DescribeMacro{\ifDTLverticalbars}
+%\begin{definition}
+%\cs{ifDTLverticalbars}
+%\end{definition}
+%This conditional governs whether the chart uses vertical or
+%horizontal bars.
+%
+%\DescribeMacro{\DTLbarXlabelalign}
+%\begin{definition}
+%\cs{DTLbarXlabelalign}
+%\end{definition}
+%This specifies the text alignment of the lower bar labels. This
+%defaults to "left,rotate=-90" if you use the \pkgopt[databar]{vertical}
+%package option or the \setting{DTLbarchart}{verticalbars} setting,
+%and defaults to "right" if you use the \pkgopt[databar]{horizontal}
+%package option or the \setting{DTLbarchart}{verticalbars}"=false"
+%setting.
+%
+%\DescribeMacro{\DTLbarYticklabelalign}
+%\begin{definition}
+%\cs{DTLbarYlabelalign}
+%\end{definition}
+%This specifies the text alignment of the $y$ axis labels. This
+%defaults to "right" for vertical bar charts and "center" for
+%horizontal bar charts.
+%
+%\DescribeMacro{\DTLbardisplayYticklabel}
+%\begin{definition}
+%\cs{DTLbardisplayYticklabel}\marg{text}
+%\end{definition}
+%This specifies how to display the $y$ tick label. The argument
+%is the tick label.
+%
+%\DescribeMacro{\DTLdisplaylowerbarlabel}
+%\begin{definition}
+%\cs{DTLdisplaylowerbarlabel}\marg{text}
+%\end{definition}
+%This specifies how to display the lower bar label for
+%\cs{DTLbarchart} and the lower bar group label for
+%\cs{DTLmultibarchart}. The argument is the label.
+%
+%\DescribeMacro{\DTLdisplaylowermultibarlabel}
+%\begin{definition}
+%\cs{DTLdisplaylowermultibarlabel}\marg{text}
+%\end{definition}
+%This specifies how to display the lower bar label for
+%\cs{DTLmultibarchart}. The argument is the label. This
+%command is ignored by \cs{DTLbarchart}.
+%
+%\DescribeMacro{\DTLdisplayupperbarlabel}
+%\begin{definition}
+%\cs{DTLdisplayupperbarlabel}\marg{text}
+%\end{definition}
+%This specifies how to display the upper bar label for
+%\cs{DTLbarchart} and the upper bar group label for
+%\cs{DTLmultibarchart}. The argument is the label.
+%
+%\DescribeMacro{\DTLdisplayuppermultibarlabel}
+%\begin{definition}
+%\cs{DTLdisplayuppermultibarlabel}\marg{text}
+%\end{definition}
+%This specifies how to display the upper bar label for
+%\cs{DTLmultibarchart}. The argument is the label. This
+%command is ignored by \cs{DTLbarchart}.
+%
+%\begin{example}{An Labelled Bar Chart}{ex:annotebarchart}
+%This example extends \autoref{ex:barchart} so that the chart is
+%a bit more informative (which is after all the whole point of
+%a chart.) This chart now has a label below each bar, as well
+%as a label above the bar. The lower label uses the value of the
+%"Name" key, and the upper label uses the quantity. I have also
+%set the outline width so each bar has a border.
+%\begin{verbatim}
+%\begin{figure}[htbp]
+%\setlength{\DTLbaroutlinewidth}{1pt}
+%\centering
+%\DTLbarchart{variable=\theQuantity,barlabel=\theName,%
+%upperbarlabel=\theQuantity}{fruit}{%
+%\theQuantity=Quantity,\theName=Name}
+%\caption{A Basic Bar Chart}
+%\end{figure}
+%\end{verbatim}
+%This produces \autoref{fig:annotebarchart}.
+%
+%\begin{figure}[htbp]
+%\centering
+%\setlength{\DTLbaroutlinewidth}{1pt}
+%\DTLbarchart{variable=\theQuantity,barlabel=\theName,
+%upperbarlabel=\theQuantity}{fruit}{%
+%\theQuantity=Quantity,\theName=Name}
+%\caption{A Bar Chart}
+%\label{fig:annotebarchart}
+%\end{figure}
+%\end{example}
+%
+%\begin{example}{Profit/Loss Bar Chart}{ex:profit}
+%Suppose I have a file called "profits.csv" that looks like:
+%\DTLnewdb{profits}
+%\DTLnewrow{profits}
+%\DTLnewdbentry{profits}{Year}{2000}\relax
+%\DTLnewdbentry{profits}{Profit}{\protect\pounds2,525}\relax
+%\DTLnewrow{profits}
+%\DTLnewdbentry{profits}{Year}{2001}\relax
+%\DTLnewdbentry{profits}{Profit}{\protect\pounds3,752}\relax
+%\DTLnewrow{profits}
+%\DTLnewdbentry{profits}{Year}{2002}\relax
+%\DTLnewdbentry{profits}{Profit}{-\protect\pounds1,520}\relax
+%\DTLnewrow{profits}
+%\DTLnewdbentry{profits}{Year}{2003}\relax
+%\DTLnewdbentry{profits}{Profit}{\protect\pounds1,270}\relax
+%\begin{verbatim}
+%Year,Profit
+%2000,\pounds2,535
+%2001,\pounds3,752
+%2002,-\pounds1,520
+%2003,\pounds1,270
+%\end{verbatim}
+%First I can load this file into a database called "profits":
+%\begin{verbatim}
+%\DTLloaddb{profits}{profits.csv}
+%\end{verbatim}
+%Now I can plot the data as a bar chart:
+%\begin{verbatim}
+%\begin{figure}[htbp]
+%\centering
+%% Set the width of each bar to 10pt
+%\setlength{\DTLbarwidth}{10pt}
+%% Set the outline width to 1pt
+%\setlength{\DTLbaroutlinewidth}{1pt}
+%% Round the $y$ tick labels to integers
+%\setcounter{DTLbarroundvar}{0}
+%% Adjust the tick label offset
+%\setlength{\DTLticklabeloffset}{20pt}
+%% Change the y tick label alignment
+%\renewcommand*{\DTLbarYticklabelalign}{left}
+%% Rotate the y tick labels
+%\renewcommand*{\DTLbardisplayYticklabel}[1]{\rotatebox{-45}{#1}}
+%% Set the bar colours depending on the value of \theProfit
+%\DTLforeach{profits}{\theProfit=Profit}{%
+%\ifthenelse{\DTLislt{\theProfit}{0}}
+%{\DTLsetbarcolor{\DTLcurrentindex}{red}}
+%{\DTLsetbarcolor{\DTLcurrentindex}{blue}}}
+%% Do the bar chart
+%\DTLbarchart{variable=\theProfit,upperbarlabel=\theYear,
+%ylabel={Profit/Loss (\pounds)},verticalbars=false,
+%maxdepth=-2000,max=4000}{profits}
+%{\theProfit=Profit,\theYear=Year}
+%\caption{Profits for 2000--2003}
+%\end{figure}
+%\end{verbatim}
+%This produces \autoref{fig:profits}. Notes:
+%\begin{enumerate}
+%\item This example uses \cs{rotatebox}, so the \sty{graphics}
+%or \sty{graphicx} package is required.
+%\item The $y$ tick labels are too wide to fit horizontally
+%so they have been rotated to avoid overlapping with their
+%neighbour.
+%\item Rotating the $y$ tick labels puts them too close to
+%the $y$ axis, so \ics{DTLticklabeloffset} is made larger to
+%compensate.
+%\item Remember not to use \cs{year} as an assignment command
+%as this command already exists!
+%\item Before the bar chart is created I have iterated through
+%the database, setting the bar colour to red or blue
+%depending on the value of \cs{theProfit}.
+%\end{enumerate}
+%
+%Both \cs{DTLbarchart} and \cs{DTLmultibarchart} set the following
+%macros, which may be used in \cs{DTLbaratbegintikz} and
+%\cs{DTLbaratendtikz}:
+%\DescribeMacro{\DTLbarchartwidth}
+%\begin{definition}
+%\cs{DTLbarchartwidth}
+%\end{definition}
+%This is the overall width of the bar chart. In the case of
+%\cs{DTLbarchart} this is just the number of bars. In the case
+%of \cs{DTLmultibarchart} it is computed as:
+%\begin{displaymath}
+%m \times n + (m-1)\times g
+%\end{displaymath}
+%where $m$ is the number of bar groups (i.e.\ the number of rows
+%of data), $n$ is the number of bars within a group (i.e.\
+%the number of commands listed in the
+%\setting{DTLmultibarchart}{variables}) setting and $g$ is the
+%group gap (as specified by the \setting{DTLmultibarchart}{groupgap} setting.)
+%
+%\DescribeMacro{\DTLnegextent}
+%\begin{definition}
+%\cs{DTLnegextent}
+%\end{definition}
+%This is set to the negative extent of the bar chart. (This value
+%may either be zero or negative, and corresponds to the
+%\setting{DTLbarchart,DTLmultibarchart}{maxdepth} setting.)
+%
+%\DescribeMacro{\DTLbarmax}
+%\begin{definition}
+%\cs{DTLbarmax}
+%\end{definition}
+%This is set to the maximum extent of the bar chart. (This value
+%corresponds to the
+%\setting{DTLbarchart,DTLmultibarchart}{max} setting.)
+%
+%\begin{figure}[htbp]
+%\centering
+%\setlength{\DTLbarwidth}{10pt}
+%\setlength{\DTLbaroutlinewidth}{1pt}
+%\setlength{\DTLticklabeloffset}{20pt}
+%\setcounter{DTLbarroundvar}{0}
+%\renewcommand*{\DTLbarYticklabelalign}{left}
+%\renewcommand*{\DTLbardisplayYticklabel}[1]{\rotatebox{-45}{#1}}
+%\DTLforeach{profits}{\theProfit=Profit}{\relax
+%\ifthenelse{\DTLislt{\theProfit}{0}}
+%{\DTLsetbarcolor{\DTLcurrentindex}{red}}
+%{\DTLsetbarcolor{\DTLcurrentindex}{blue}}}
+%\DTLbarchart{variable=\theProfit,upperbarlabel=\theYear,
+%ylabel={Profit/Loss (\pounds)},verticalbars=false,
+%maxdepth=-2000,max=4000
+%}{profits}
+%{\theProfit=Profit,\theYear=Year}
+%\caption{Profits for 2000--2003}
+%\label{fig:profits}
+%\end{figure}
+%
+%\end{example}
+%
+%\begin{example}{A Multi-Bar Chart}{ex:multibar}
+%This example uses the "marks" database described in
+%\autoref{ex:editdb}.
+%Recall that this database stores student marks for three
+%assignments. The keys for the assignment marks are
+%\texttt{Assignment 1}, \texttt{Assignment 2} and
+%\texttt{Assignment 3}, respectively. I can convert this
+%data into a bar chart using the following:
+%\begin{verbatim}
+%\begin{figure}[htbp]
+%\centering
+%\DTLmultibarchart{variables={\assignI,\assignII,\assignIII},
+%barwidth=10pt,uppermultibarlabels={\assignI,\assignII,\assignIII},
+%barlabel={\firstname\ \surname}}{marks}{%
+%\surname=Surname,\firstname=FirstName,\assignI=Assignment 1,%
+%\assignII=Assignment 2,\assignIII=Assignment 3}
+%\caption{Student Marks}
+%\end{figure}
+%\end{verbatim}
+%This produces \autoref{fig:multibar}. Notes:
+%\begin{enumerate}
+%\item I used "variables={\assignI,\assignII,\assignIII}" to
+%set the variable to use for each bar within a group. This means
+%that there will be three bars in each group.
+%\item I have set the bar width to 10pt, otherwise the chart
+%will be too wide.
+%\item I used "uppermultibarlabels={\assignI,\assignII,\assignIII}"
+%to set the upper labels for each bar within a group. This
+%will print the assignment mark above the relevant bar.
+%\item I used "barlabel={\firstname\ \surname}" to place the
+%student's name below the group corresponding to that student.
+%\end{enumerate}
+%
+%\begin{figure}[htbp]
+%\centering
+%\DTLmultibarchart{variables={\assignI,\assignII,\assignIII},
+%barwidth=10pt,uppermultibarlabels={\assignI,\assignII,\assignIII},
+%barlabel={\firstname\ \surname}}{marks}
+%{\surname=Surname,\firstname=FirstName,\assignI=Assignment 1,\assignII=Assignment 2,\assignIII=Assignment 3}
+%\caption{Student Marks}\label{fig:multibar}
+%\end{figure}
+%
+%Recall that \autoref{ex:editdb} computed the average score over
+%for each student, and saved it with the key "Average". This
+%information can be added to the bar chart. It might also be
+%useful to compute the average over all students and add this
+%information to the chart. This is done as follows:
+%\begin{verbatim}
+%\end{verbatim}
+%which produces \autoref{fig:multibarmean}. Notes:
+%\begin{enumerate}
+%\item I've used the TikZ snake library to create a brace, so
+%I need to put
+%\begin{verbatim}
+%\usetikzlibrary{snakes}
+%\end{verbatim}
+%in the preamble. See the \sty{pgf} manual for more details on
+%how to use this library.
+%
+%\item I used \ics{DTLbargroupwidth} to indicate the width of
+%each bar group.
+%
+%\item I used \ics{DTLbarchartwidth} to indicate the width of the
+%entire bar chart
+%\end{enumerate}
+%
+%\begin{figure}[htbp]
+%\centering
+%\DTLmeanforkeys{marks}{Average}{\overallmean}
+%\DTLround{\overallmean}{\overallmean}{2}
+%\renewcommand*{\DTLbaratendtikz}{\draw[lightgray,loosely dotted] (0,\overallmean) --
+%(\DTLbarchartwidth,\overallmean) node[right,black]{Average (\overallmean)};}
+%\renewcommand*{\DTLdisplaylowerbarlabel}[1]{\relax
+%\tikz[baseline=(current bounding box.center)]{
+%\draw[snake=brace,rotate=-90](0,0) -- (\DTLbargroupwidth,0);}
+%\DTLround{\theMean}{\theMean}{2}\relax
+%\shortstack{#1\\(Average: \theMean)}}
+%\DTLmultibarchart{variables={\assignI,\assignII,\assignIII},
+%barwidth=10pt,uppermultibarlabels={\assignI,\assignII,\assignIII},
+%barlabel={\firstname\ \surname}}{marks}
+%{\surname=Surname,\firstname=FirstName,\assignI=Assignment 1,\assignII=Assignment 2,\assignIII=Assignment 3,\theMean=Average}
+%\caption{Student Marks (with average scores)}
+%\label{fig:multibarmean}
+%\end{figure}
+%\end{example}
+%
+% \StopEventually{\clearpage\phantomsection
+%\addcontentsline{toc}{section}{Index}\PrintIndex}
+%
+%
+%
+%\section{datatool.sty}
+%\iffalse
+% \begin{macrocode}
+%<*datatool.sty>
+% \end{macrocode}
+%\fi
+%\subsection{Package Declaration}
+% \begin{macrocode}
+\NeedsTeXFormat{LaTeX2e}
+\ProvidesPackage{datatool}[2007/07/23 v1.0 (NLCT)]
+% \end{macrocode}
+% Load required packages:
+% \begin{macrocode}
+\RequirePackage{xkeyval}
+\RequirePackage{ifthen}
+\RequirePackage{xfor}
+\RequirePackage{fp}
+\RequirePackage{substr}
+% \end{macrocode}
+%
+%\subsection{Package Options}
+% Define macro to store data separator character (comma by default)
+% This is the separator used in external data files, not in the
+% \LaTeX\ code, which always uses a comma separator.
+%\begin{macro}{\@dtl@separator}
+% \begin{macrocode}
+\newcommand*{\@dtl@separator}{,}
+% \end{macrocode}
+%\end{macro}
+% Provide a command for setting the data separator. This sets
+% \cs{@dtl@separator}, and constructs the relevent macros that
+% require this character to be hardcoded into their definition.
+%\begin{macro}{\DTLsetseparator}
+% \begin{macrocode}
+\newcommand*{\DTLsetseparator}[1]{%
+\renewcommand*{\@dtl@separator}{#1}%
+\@dtl@construct@lopoffs
+}
+% \end{macrocode}
+%\end{macro}
+% Make it easier to set a tab separator
+%\begin{macro}{\DTLsettabseparator}
+\begingroup
+\catcode`\ 12
+\gdef\DTLsettabseparator{%
+ \catcode`\ 12
+ \DTLsetseparator{ }%
+}
+\endgroup
+%\end{macro}
+%
+% Define a macro to store data delimiter character (double quote
+% by default.) This is used in external data files, not in the
+% \LaTeX\ code.
+%\begin{macro}{\@dtl@delimiter}
+% \begin{macrocode}
+\begingroup
+\catcode`\"12\relax
+\gdef\@dtl@delimiter{"}
+\endgroup
+% \end{macrocode}
+%\end{macro}
+% Define a macro that sets the delimiter.
+%\begin{macro}{\DTLsetdelimiter}
+% \begin{macrocode}
+\newcommand*\DTLsetdelimiter[1]{%
+\renewcommand*{\@dtl@delimiter}{#1}%
+\@dtl@construct@lopoffs}
+% \end{macrocode}
+%\end{macro}
+% \cs{@dtl@construct@lopoff}\meta{separator char}\meta{delimiter char}
+% defines
+% \cs{@dtl@lopoff}\meta{first element}\meta{sep}\meta{rest of list}\cs{to}\meta{cmd1}\meta{cmd2}
+% for the current separator and delimiter.
+%\begin{macro}{\@dtl@construct@lopoff}
+% \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\@dtl@qlopoff#1##1##2\noexpand\to##3##4\relax
+\noexpand\else
+\noexpand\@dtl@lop@ff#1##1##2\noexpand\to##3##4\relax
+\noexpand\fi
+}}
+% \end{macrocode}
+%\end{macro}
+% Define command to construct macro \cs{@dtl@qlopoff} to be used
+% when the entry is surrounded by the current delimiter value.
+% Syntax:
+%\begin{definition}
+% \cs{@dtl@construct@qlopoff}\meta{separator char}\meta{delimiter char}
+%\end{definition}
+%\begin{macro}{\@dtl@construct@qlopoff}
+% \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}\noexpand\def##3{#1##2}%
+}}
+% \end{macrocode}
+%\end{macro}
+% Define command to construct macro \cs{@dtl@lop@ff} to be used when
+% the entry isn't surrouded by the delimiter.
+%Syntax:
+%\begin{definition}
+% \cs{@dtl@construct@lop@ff}\meta{separator char}
+%\end{definition}
+%\begin{macro}{\@dtl@construct@lop@ff}
+% \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}
+% Construct all the lopoff macros.
+%\begin{macro}{\@dtl@construct@lopoffs}
+% \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}
+% Define the decimal character
+%\begin{macro}{\@dtl@decimal}
+% \begin{macrocode}
+\newcommand*{\@dtl@decimal}{.}
+% \end{macrocode}
+%\end{macro}
+%Define the number group character
+%\begin{macro}{\@dtl@numbergroupchar}
+% \begin{macrocode}
+\newcommand*{\@dtl@numbergroupchar}{,}
+% \end{macrocode}
+%\end{macro}
+%\begin{definition}
+%\cs{DTLsetnumberchars}\marg{number group char}\marg{decimal char}
+%\end{definition}
+% Sets the decimal character and number group
+% characters.
+%\begin{macro}{\DTLsetnumberchars}
+% \begin{macrocode}
+\newcommand*{\DTLsetnumberchars}[2]{%
+\renewcommand*{\@dtl@numbergroupchar}{#1}%
+\renewcommand*{\@dtl@decimal}{#2}%
+\@dtl@construct@getnums
+\@dtl@construct@stripnumgrpchar{#1}}
+% \end{macrocode}
+%\end{macro}
+%
+% Construct macros for extracting integer and
+% fractional parts from a real number using the decimal character
+% given by "#1".
+%
+%\begin{definition}
+% \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.
+%
+%\begin{macro}{\@dtl@construct@getintfrac}
+% \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\ifx\noexpand\@empty\noexpand\@dtl@fracpart
+ \noexpand\def\noexpand\@dtl@fracpart{0}%
+\noexpand\else
+ \noexpand\@dtl@getfracpart##2\noexpand\relax
+ \noexpand\@dtl@choptrailingzeroes{\noexpand\@dtl@fracpart}%
+\noexpand\fi
+}%
+\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\ifx\noexpand\@dtl@org@currency\noexpand\@empty
+ \noexpand\else
+ \noexpand\let\noexpand\@dtl@currency\noexpand\@dtl@org@currency
+ \noexpand\fi
+\noexpand\expandafter
+\noexpand\@dtl@getintfrac\noexpand\@dtl@tmp#1\noexpand\relax
+\noexpand\edef##2{\noexpand\@dtl@intpart.\noexpand\@dtl@fracpart}}%
+}
+% \end{macrocode}
+%\end{macro}
+% Define command to call the above with the relevant decimal
+% character:
+%\begin{macro}{\@dtl@construct@getnums}
+% \begin{macrocode}
+\newcommand*{\@dtl@construct@getnums}{%
+\expandafter\@dtl@construct@getintfrac\expandafter{\@dtl@decimal}}
+% \end{macrocode}
+%\end{macro}
+% Get the integer (adjusting for repeating +/- signs if neccessary)
+% Sets \cs{@dtl@intpart}.
+%\begin{macro}{\@dtl@get@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{definition}
+% \cs{@dtl@choptrailingzeroes}\marg{cmd}
+%\end{definition}
+% Chop trailing zeroes from number given by \meta{cmd}.
+%\begin{macro}{\@dtl@choptrailingzeroes}
+% \begin{macrocode}
+\newcommand*{\@dtl@choptrailingzeroes}[1]{%
+\def\@dtl@tmpcpz{}%
+\expandafter\@dtl@chop@trailingzeroes#1\@nil%
+\let#1=\@dtl@tmpcpz
+}
+% \end{macrocode}
+%\end{macro}
+%
+% 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{macro}{\@dtl@chop@trailingzeroes}
+% \begin{macrocode}
+\def\@dtl@chop@trailingzeroes#1#2\@nil{%
+\FPifeq{#2}{0}%
+ \edef\@dtl@tmpcpz{\@dtl@tmpcpz#1}%
+ \let\@dtl@chopzeroesnext=\@dtl@chop@trailingzeroesnoop
+\else
+ \edef\@dtl@tmpcpz{\@dtl@tmpcpz#1}%
+ \let\@dtl@chopzeroesnext=\@dtl@chop@trailingzeroes
+\fi
+\@dtl@chopzeroesnext#2\@nil
+}
+% \end{macrocode}
+%\end{macro}
+% No-op macro to end recursion
+%\begin{macro}{\@dtl@chop@trailingzeroesnoop}
+% \begin{macrocode}
+\def\@dtl@chop@trailingzeroesnoop#1\@nil{}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{definition}
+%\cs{dtl@truncatedecimal}\meta{cmd}
+%\end{definition}
+%Truncates decimal given by \meta{cmd} to an integer (assumes in
+% decimal format with full stop as decimal point)
+%\begin{macro}{\dtl@truncatedecimal}
+% \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{definition}
+% \cs{@dtl@strip@numgrpchar}\marg{cmd}
+%\end{definition}
+% Strip the number group character from the number given by
+% \meta{cmd}.
+%\begin{macro}{\@dtl@strip@numgrpchar}
+% \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}
+%
+% Define command to construct macro \cs{@@dtl@strip@numgrpchar}
+%\begin{macro}{\@dtl@construct@stripnumgrpchar}
+% \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{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{macro}{\DTLdecimaltolocale}
+% \begin{macrocode}
+\newcommand*{\DTLdecimaltolocale}[2]{%
+\edef\@dtl@tmpdtl{#1}%
+\expandafter\@dtl@decimaltolocale\@dtl@tmpdtl.\relax
+\FPifeq{\@dtl@fracpart}{0}%
+ \edef#2{\@dtl@intpart}%
+\else
+ \edef#2{\@dtl@intpart\@dtl@decimal\@dtl@fracpart}%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+% Convert the integer part (store in \cs{@dtl@intpart})
+%\begin{macro}{\@dtl@decimaltolocale}
+% \begin{macrocode}
+\def\@dtl@decimaltolocale#1.#2\relax{%
+\@dtl@decimaltolocaleint{#1}%
+\def\@dtl@fracpart{#2}%
+\ifx\@dtl@fracpart\@empty
+ \def\@dtl@fracpart{0}%
+\else
+ \@dtl@decimaltolocalefrac#2\relax
+\fi
+}
+% \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}
+% Counts the number of digits until "#2" is a full stop.
+% (increments \cs{@dtl@tmpcount}.)
+%\begin{macro}{\@dtl@countdigits}
+% \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}
+%
+% Convert the fractional part (store in \cs{@dtl@fracpart})
+%\begin{macro}{\@dtl@decimaltolocalefrac}
+% \begin{macrocode}
+% \end{macrocode}
+\def\@dtl@decimaltolocalefrac#1.\relax{%
+\def\@dtl@fracpart{#1}%
+\@dtl@choptrailingzeroes{\@dtl@fracpart}%
+}
+%\end{macro}
+%
+%\begin{definition}
+% \cs{DTLdecimaltocurrency}\marg{number}\marg{cmd}
+%\end{definition}
+% Define command to convert a decimal number into the locale
+% dependent currency format. Stores result in \meta{cmd} which must be
+% a control sequence.
+%\begin{macro}{\DTLdecimaltocurrency}
+% \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}%
+\FPifeq{\@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
+\else
+ \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
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+% Set the defaults:
+% \begin{macrocode}
+\@dtl@construct@lopoffs
+\@dtl@construct@getnums
+\expandafter\@dtl@construct@stripnumgrpchar\expandafter
+{\@dtl@numbergroupchar}
+% \end{macrocode}
+% Define key for package option \pkgopt{separator}.
+% \begin{macrocode}
+\define@key{datatool.sty}{separator}{%
+\DTLsetseparator{#1}}
+% \end{macrocode}
+% Define key for package option \pkgopt{delimiter}.
+% \begin{macrocode}
+\define@key{datatool.sty}{delimiter}{%
+\DTLsetdelimiter{#1}}
+% \end{macrocode}
+% Define key for package option \pkgopt{verbose}. (This also
+% switches the \sty{fp} messages on/off)
+% \begin{macrocode}
+\define@boolkey{datatool.sty}[dtl]{verbose}[true]{%
+\ifdtlverbose \FPmessagestrue\else \FPmessagesfalse\fi}
+% \end{macrocode}
+% Display message only if verbose option set:
+% \begin{macrocode}
+\newcommand*{\dtl@message}[1]{%
+\ifdtlverbose \typeout{#1}\fi}
+% \end{macrocode}
+% Process package options:
+% \begin{macrocode}
+\ProcessOptionsX
+% \end{macrocode}
+% Requires \texttt{compare.tex}, unless \cs{compare} has already
+% been defined. If paragraph breaks are allowed, these commands
+% need to be defined to be long.
+% \begin{macrocode}
+\@ifundefined{compare}{\input{compare}}{}
+% \end{macrocode}
+%
+% Many of the commands used by this package are short commands
+% (such as \cs{compare}.) This means that you can't use \cs{par}
+% in the data. To get around this, define the robust command
+% \cs{DTLpar} to use instead.
+%\begin{macro}{\DTLpar}
+% \begin{macrocode}
+\DeclareRobustCommand\DTLpar{\@par}
+% \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}
+% Define temporary count register
+%\begin{macro}{\@dtl@tmpcount}
+% \begin{macrocode}
+\newcount\@dtl@tmpcount
+% \end{macrocode}
+%\end{macro}
+% Define count register to count the digits between the number
+% group separator.
+%\begin{macro}{\@dtl@numgrpsepcount}
+% \begin{macrocode}
+\newcount\@dtl@numgrpsepcount
+% \end{macrocode}
+%\end{macro}
+%
+% Define a macro that checks if the argument is numerical
+% (includes decimal numbers, but not scientific notation.)
+% Sets \cs{@dtl@datatype}, as described above.
+%\begin{macro}{\@dtl@checknumerical}
+% \begin{macrocode}
+\newcommand{\@dtl@checknumerical}[1]{%
+\@dtl@numgrpsepfalse
+\def\@dtl@tmp{#1}%
+\ifx\@empty#1\@empty
+ \@dtl@datatype=0\relax
+\else
+ \dtl@ifsingle{#1}%
+ {\expandafter\toks@\expandafter{#1}%
+ \edef\@dtl@tmp{\the\toks@}}%
+ {\def\@dtl@tmp{#1}}%
+ \@dtl@tmpcount=0\relax
+ \@dtl@datatype=0\relax
+ \@dtl@numgrpsepcount=2\relax
+ \@dtl@standardize@currency\@dtl@tmp
+ \ifx\@dtl@org@currency\@empty
+ \else
+ \let\@dtl@currency\@dtl@org@currency
+ \fi
+ \expandafter\@dtl@checknumericalstart\@dtl@tmp\@nil\@nil
+\fi
+\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}
+% Check first character for checknumerical process to see if
+% it's a plus or minus sign.
+%\begin{macro}{\@dtl@checknumericalstart}
+% \begin{macrocode}
+\def\@dtl@checknumericalstart#1#2\@nil\@nil{%
+\ifx#1\protect
+ \@dtl@checknumericalstart#2\@nil\@nil\relax
+\else
+ \if-#1\relax
+ \def\@dtl@tmp{#2}%
+ \ifx\@empty\@dtl@tmp
+ \@dtl@datatype=0\relax
+ \else
+ \ifnum\@dtl@datatype=0\relax
+ \@dtl@datatype=1\relax
+ \fi
+ \@dtl@checknumericalstart#2\@nil\@nil\relax
+ \fi
+ \else
+ \if+#1\relax
+ \def\@dtl@tmp{#2}%
+ \ifx\@empty\@dtl@tmp
+ \@dtl@datatype=0\relax
+ \else
+ \ifnum\@dtl@datatype=0\relax
+ \@dtl@datatype=1\relax
+ \fi
+ \@dtl@checknumericalstart#2\@nil\@nil\relax
+ \fi
+ \else
+ \def\@dtl@tmp{#1}%
+ \ifx#1\$\relax
+ \@dtl@datatype=3\relax
+ \@dtl@checknumericalstart#2\@nil\@nil\relax
+ \else
+ \ifx\@empty\@dtl@tmp
+ \@dtl@datatype=0\relax
+ \else
+ \ifnum\@dtl@datatype=0\relax
+ \@dtl@datatype=1\relax
+ \fi
+ \@dtl@checknumericalloop#1#2\@nil\@nil\relax
+ \fi
+ \fi
+ \fi
+ \fi
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+% The conditional \cs{if@dtl@numgrpsep} is set the first time
+% \cs{@dtl@checknumericalloop} encounters the number group
+% separator.
+%\begin{macro}{\if@dtl@numgrpsep}
+% \begin{macrocode}
+\newif\if@dtl@numgrpsep
+% \end{macrocode}
+%\end{macro}
+% 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.
+%\begin{macro}{\@dtl@checknumericalloop}
+% \begin{macrocode}
+\def\@dtl@checknumericalloop#1#2\@nil{%
+\def\@dtl@tmp{#1}%
+\ifx\@nnil\@dtl@tmp\relax
+ \let\@dtl@chcknumnext=\@dtl@checknumericalnoop%
+\else
+ \ifthenelse{\equal{#1}{0}\or
+ \equal{#1}{1}\or
+ \equal{#1}{2}\or
+ \equal{#1}{3}\or
+ \equal{#1}{4}\or
+ \equal{#1}{5}\or
+ \equal{#1}{6}\or
+ \equal{#1}{7}\or
+ \equal{#1}{8}\or
+ \equal{#1}{9}\or
+ \equal{#1}{\@dtl@decimal}}{%
+ \let\@dtl@chcknumnext=\@dtl@checknumericalloop%
+ \ifthenelse{\equal{#1}{\@dtl@decimal}}{%
+ \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
+ }{%
+ \ifnum\@dtl@numgrpsepcount=-1\relax
+ \else
+ \advance\@dtl@numgrpsepcount by 1\relax
+ \fi}%
+}{\ifthenelse{\equal{#1}{\@dtl@numbergroupchar}}{%
+ \@dtl@numgrpseptrue
+ \ifnum\@dtl@numgrpsepcount<3\relax
+ \@dtl@datatype=0\relax
+ \let\@dtl@chcknumnext=\@dtl@checknumericalnoop
+ \else
+ \@dtl@numgrpsepcount=0\relax
+ \fi}{%
+ \@dtl@datatype=0\relax
+ \let\@dtl@chcknumnext=\@dtl@checknumericalnoop
+}}%
+ \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}
+% End loop
+%\begin{macro}{\@dtl@checknumericalnoop}
+% \begin{macrocode}
+\def\@dtl@checknumericalnoop#1\@nil#2{}
+% \end{macrocode}
+%\end{macro}
+%
+% Define \cs{DTLifnumerical} which tests the first argument, if
+% its numerical do second argument, otherwise do third argument.
+%\begin{macro}{\DTLifnumerical}
+% \begin{macrocode}
+\newcommand{\DTLifnumerical}[3]{%
+\@dtl@checknumerical{#1}%
+\ifnum\@dtl@datatype=0\relax#3\else#2\fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+% Define \cs{DTLifreal} which tests the first argument, if
+% it's a real number (not an integer) do second argument,
+% otherwise do third argument.
+%\begin{macro}{\DTLifreal}
+% \begin{macrocode}
+\newcommand{\DTLifreal}[3]{%
+\@dtl@checknumerical{#1}%
+\ifnum\@dtl@datatype=2\relax #2\else #3\fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+% Define \cs{DTLifint} which tests the first argument, if
+% it's an integer do second argument,
+% otherwise do third argument.
+%\begin{macro}{\DTLifint}
+% \begin{macrocode}
+\newcommand{\DTLifint}[3]{%
+\@dtl@checknumerical{#1}%
+\ifnum\@dtl@datatype=1\relax #2\else #3\fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+% Define \cs{DTLifstring} which tests the first argument, if
+% it's a string do second argument,
+% otherwise do third argument.
+%\begin{macro}{\DTLifstring}
+% \begin{macrocode}
+\newcommand{\DTLifstring}[3]{%
+\@dtl@checknumerical{#1}%
+\ifnum\@dtl@datatype=0\relax #2\else #3\fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+% Define \cs{DTLifcurrency} which tests the first argument, if
+% it starts with the currency symbol do second argument,
+% otherwise do third argument.
+%\begin{macro}{\DTLifcurrency}
+% \begin{macrocode}
+\newcommand{\DTLifcurrency}[3]{%
+\@dtl@checknumerical{#1}%
+\ifnum\@dtl@datatype=3\relax #2\else #3\fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+% Define \cs{DTLifcurrencyunit} which tests if the first argument
+% is currency, and uses the currency unit given by the
+% second argument. If true do third argument, otherwise
+% do fourth argument.
+%\begin{macro}{\DTLifcurrencyunit}
+% \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}
+%
+% Define \cs{DTLifcasedatatype} which tests the first argument.
+% If it is a string, do second argument, if it is an integer
+% do third argument, if it is a real number, do fourth argument,
+% if it is currency, do fifth argument.
+%\begin{macro}{\DTLifcasedatatype}
+% \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}
+%
+% Test if both arguments are numerical. This sets
+% the conditional \cs{if@dtl@condition}
+%\begin{macro}{\dtl@testbothnumerical}
+% \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{definition}
+%\cs{DTLifnumlt}\marg{num1}\marg{num2}\marg{true part}\marg{false part}
+%\end{definition}
+% Determine if \marg{num1} < \marg{num2}. Both numbers
+% need to have the decimal separator changed to a dot
+% to ensure that it works with \cs{FPiflt}
+%\begin{macro}{\DTLifnumlt}
+% \begin{macrocode}
+\newcommand*{\DTLifnumlt}[4]{%
+ \DTLconverttodecimal{#1}{\@dtl@numi}%
+ \DTLconverttodecimal{#2}{\@dtl@numii}%
+ \FPiflt{\@dtl@numi}{\@dtl@numii}%
+ #3%
+ \else
+ #4%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{definition}
+%\cs{DTLifstringlt}\marg{string1}\marg{string2}\marg{true part}\marg{false part}
+%\end{definition}
+% String comparison
+%\begin{macro}{\DTLifstringlt}
+% \begin{macrocode}
+\newcommand*{\DTLifstringlt}[4]{%
+\protected@edef\@dtl@tmpcmp{\noexpand\compare{#1}{#2}}%
+ \expandafter\ifnum\@dtl@tmpcmp<0\relax
+ #3%
+ \else
+ #4%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{definition}
+%\cs{DTLiflt}\marg{arg1}\marg{arg2}\marg{true part}\marg{false part}
+%\end{definition}
+% Do \cs{DTLifnumlt} if both \meta{arg1} and \meta{arg2} are
+% numerical, otherwise do \cs{DTifstringlt}.
+%\begin{macro}{\DTLiflt}
+% \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}
+%\end{macro}
+%
+%\begin{definition}
+%\cs{DTLifnumgt}\marg{num1}\marg{num2}\marg{true part}\marg{false part}
+%\end{definition}
+% Determine if \marg{num1} > \marg{num2}. Both numbers
+% need to have the decimal separator changed to a dot
+% to ensure that it works with \cs{FPifgt}
+%\begin{macro}{\DTLifnumgt}
+% \begin{macrocode}
+\newcommand*{\DTLifnumgt}[4]{%
+ \DTLconverttodecimal{#1}{\@dtl@numi}%
+ \DTLconverttodecimal{#2}{\@dtl@numii}%
+ \FPifgt{\@dtl@numi}{\@dtl@numii}%
+ #3%
+ \else
+ #4%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{definition}
+%\cs{DTLifstringgt}\marg{string1}\marg{string2}\marg{true part}\marg{false part}
+%\end{definition}
+% String comparison
+%\begin{macro}{\DTLifstringgt}
+% \begin{macrocode}
+\newcommand*{\DTLifstringgt}[4]{%
+\protected@edef\@dtl@tmpcmp{\noexpand\compare{#1}{#2}}%
+ \expandafter\ifnum\@dtl@tmpcmp>0\relax
+ #3%
+ \else
+ #4%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{definition}
+%\cs{DTLifgt}\marg{arg1}\marg{arg2}\marg{true part}\marg{false part}
+%\end{definition}
+% Do \cs{DTLifnumgt} if both \meta{arg1} and \meta{arg2} are
+% numerical, otherwise do \cs{DTifstringgt}.
+%\begin{macro}{\DTLifgt}
+% \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}
+%\end{macro}
+%
+%\begin{definition}
+%\cs{DTLifnumeq}\marg{num1}\marg{num2}\marg{true part}\marg{false part}
+%\end{definition}
+% Determine if \marg{num1} = \marg{num2}. Both numbers
+% need to have the decimal separator changed to a dot
+% to ensure that it works with \cs{FPifeq}
+%\begin{macro}{\DTLifnumeq}
+% \begin{macrocode}
+\newcommand*{\DTLifnumeq}[4]{%
+ \DTLconverttodecimal{#1}{\@dtl@numi}%
+ \DTLconverttodecimal{#2}{\@dtl@numii}%
+ \FPifeq{\@dtl@numi}{\@dtl@numii}%
+ #3%
+ \else
+ #4%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{definition}
+%\cs{DTLifstringeq}\marg{string1}\marg{string2}\marg{true part}\marg{false part}
+%\end{definition}
+% String comparison
+%\begin{macro}{\DTLifstringeq}
+% \begin{macrocode}
+\newcommand*{\DTLifstringeq}[4]{%
+\protected@edef\@dtl@tmpcmp{\noexpand\compare{#1}{#2}}%
+ \expandafter\ifnum\@dtl@tmpcmp=0\relax
+ #3%
+ \else
+ #4%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{definition}
+%\cs{DTLifeq}\marg{arg1}\marg{arg2}\marg{true part}\marg{false part}
+%\end{definition}
+% Do \cs{DTLifnumeq} if both \meta{arg1} and \meta{arg2} are
+% numerical, otherwise do \cs{DTifstringeq}.
+%\begin{macro}{\DTLifeq}
+% \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}
+%\end{macro}
+%
+%\begin{definition}
+%\cs{DTLifnumclosedbetween}\marg{num}\marg{min}\marg{max}\marg{true part}\marg{false part}
+%\end{definition}
+% Determine if \meta{min} $\leq$ \meta{num} $\leq$ \meta{max}.
+%\begin{macro}{\DTLifnumclosedbetween}
+% \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{definition}
+%\cs{DTLifstringclosedbetween}\marg{string}\marg{min}\marg{max}\marg{true part}\marg{false part}
+%\end{definition}
+% String comparison
+%\begin{macro}{\DTLifstringclosedbetween}
+% \begin{macrocode}
+\newcommand*{\DTLifstringclosedbetween}[5]{%
+\protected@edef\@dtl@tmpcmp{\noexpand\compare{#1}{#2}}%
+\let\@dtl@dovalue\relax
+\expandafter\ifnum\@dtl@tmpcmp<0\relax
+ \def\@dtl@dovalue{#5}%
+\fi
+\ifx\@dtl@dovalue\relax
+ \protected@edef\@dtl@tmpcmp{\noexpand\compare{#1}{#3}}%
+ \expandafter\ifnum\@dtl@tmpcmp>0\relax
+ \def\@dtl@dovalue{#5}%
+ \else
+ \def\@dtl@dovalue{#4}%
+ \fi
+\fi
+\@dtl@dovalue
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{definition}
+%\cs{DTLifclosedbetween}\marg{arg}\marg{min}\marg{max}\marg{true part}\marg{false part}
+%\end{definition}
+% Do \cs{DTLifnumclosedbetween} if \marg{arg}, \meta{min} and \meta{max} are
+% numerical, otherwise do \cs{DTifstringclosedbetween}.
+%\begin{macro}{\DTLifclosedbetween}
+% \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}
+%\end{macro}
+%
+%\begin{definition}
+%\cs{DTLifnumopenbetween}\marg{num}\marg{min}\marg{max}\marg{true part}\marg{false part}
+%\end{definition}
+% Determine if \meta{min} $<$ \meta{num} $<$ \meta{max}.
+%\begin{macro}{\DTLifnumopenbetween}
+% \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{definition}
+%\cs{DTLifstringopenbetween}\marg{string}\marg{min}\marg{max}\marg{true part}\marg{false part}
+%\end{definition}
+% String comparison
+%\begin{macro}{\DTLifstringopenbetween}
+% \begin{macrocode}
+\newcommand*{\DTLifstringopenbetween}[5]{%
+\protected@edef\@dtl@tmpcmp{\noexpand\compare{#1}{#2}}%
+\let\@dtl@dovalue\relax
+\expandafter\ifnum\@dtl@tmpcmp>0\relax
+\else
+ \def\@dtl@dovalue{#5}%
+\fi
+\ifx\@dtl@dovalue\relax
+ \protected@edef\@dtl@tmpcmp{\noexpand\compare{#1}{#3}}%
+ \expandafter\ifnum\@dtl@tmpcmp<0\relax
+ \def\@dtl@dovalue{#4}%
+ \else
+ \def\@dtl@dovalue{#5}%
+ \fi
+\fi
+\@dtl@dovalue
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{definition}
+%\cs{DTLifopenbetween}\marg{arg}\marg{min}\marg{max}\marg{true part}\marg{false part}
+%\end{definition}
+% Do \cs{DTLifnumopenbetween} if \marg{arg}, \meta{min} and \meta{max} are
+% numerical, otherwise do \cs{DTifstringopenbetween}.
+%\begin{macro}{\DTLifopenbetween}
+% \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}
+%\end{macro}
+%
+%\begin{definition}
+%\cs{DTLifFPopenbetween}\marg{num}\marg{min}\marg{max}\marg{true part}\marg{false part}
+%\end{definition}
+% Determine if \meta{min} $<$ \meta{num} $<$ \meta{max} where
+% all arguments are in standard fixed point notation.
+%\begin{macro}{\DTLifFPopenbetween}
+% \begin{macrocode}
+\newcommand*{\DTLifFPopenbetween}[5]{%
+ \let\@dtl@dovalue\relax
+ \FPifgt{#1}{#2}%
+ \else
+ \def\@dtl@dovalue{#5}%
+ \fi
+ \FPiflt{#1}{#3}%
+ \ifx\@dtl@dovalue\relax
+ \def\@dtl@dovalue{#4}%
+ \fi
+ \else
+ \def\@dtl@dovalue{#5}%
+ \fi
+\@dtl@dovalue
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{definition}
+%\cs{DTLifFPclosedbetween}\marg{num}\marg{min}\marg{max}\marg{true part}\marg{false part}
+%\end{definition}
+% Determine if \meta{min} $\leq$ \meta{num} $\leq$ \meta{max}.
+%\begin{macro}{\DTLifFPclosedbetween}
+% \begin{macrocode}
+\newcommand*{\DTLifFPclosedbetween}[5]{%
+ \let\@dtl@dovalue\relax
+ \FPifgt{#1}{#3}%
+ \def\@dtl@dovalue{#5}%
+ \fi
+ \FPiflt{#1}{#2}%
+ \ifx\@dtl@dovalue\relax
+ \def\@dtl@dovalue{#5}%
+ \fi
+ \else
+ \def\@dtl@dovalue{#4}%
+ \fi
+\@dtl@dovalue
+}
+% \end{macrocode}
+%\end{macro}
+%
+% The following conditionals are only meant to be used within
+% \cs{DTLforeach} as they depend on the counter
+% \texttt{DTLrow}\meta{n}.
+%
+%\begin{definition}
+%\cs{DTLiffirstrow}\marg{true part}\marg{false part}
+%\end{definition}
+%\begin{macro}{\DTLiffirstrow}
+% \begin{macrocode}
+\newcommand{\DTLiffirstrow}[2]{%
+\ifnum\dtlforeachlevel=0\relax
+ \PackageError{datatool}{\string\DTLiffirstrow\space can only
+ be used inside \string\DTLforeach}{}%
+\else
+\expandafter\ifnum\csname c@DTLrow\romannumeral
+\dtlforeachlevel\endcsname
+=1\relax#1\else#2\fi
+\fi}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{definition}
+%\cs{DTLiflastrow}\marg{true part}\marg{false part}
+%\end{definition}
+%\begin{macro}{\DTLiflastrow}
+% \begin{macrocode}
+\newcommand{\DTLiflastrow}[2]{%
+\ifnum\dtlforeachlevel=0\relax
+ \PackageError{datatool}{\string\DTLiflastrow\space can only
+ be used inside \string\DTLforeach}{}%
+\else
+\expandafter\ifnum\csname c@DTLrow\romannumeral
+\dtlforeachlevel\endcsname=
+\value{DTLrow\romannumeral\dtlforeachlevel}%
+#1\else #2\fi
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{definition}
+%\cs{DTLifoddrow}\marg{true part}\marg{false part}
+%\end{definition}
+%\begin{macro}{\DTLifoddrow}
+% \begin{macrocode}
+\newcommand{\DTLifoddrow}[2]{%
+\ifnum\dtlforeachlevel=0\relax
+ \PackageError{datatool}{\string\DTLifoddrow\space can only
+ be used inside \string\DTLforeach}{}%
+\else
+\expandafter\ifodd\csname c@DTLrow\romannumeral
+\dtlforeachlevel\endcsname
+#1\else #2\fi
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+% \subsection{ifthen Conditionals}
+% The following commands provide conditionals \cs{DTLis}\ldots\
+% that can be used in \cs{ifthenelse}. First need to define
+% a new conditional:
+%\begin{macro}{\if@dtl@condition}
+% \begin{macrocode}
+\newif\if@dtl@condition
+% \end{macrocode}
+%\end{macro}
+%
+% Command to test if first argument is less than second argument.
+% If either argument is a string, a string comparison is used
+% instead.
+% This sets \cs{if@dtl@condition}.
+%\begin{macro}{\dtl@testlt}
+% \begin{macrocode}
+\newcommand*{\dtl@testlt}[2]{%
+\DTLiflt{#1}{#2}{\@dtl@conditiontrue}{\@dtl@conditionfalse}}
+% \end{macrocode}
+%\end{macro}
+% Provide conditional command for use in \cs{ifthenelse}
+%\begin{macro}{\DTLislt}
+% \begin{macrocode}
+\newcommand*{\DTLislt}[2]{%
+\TE@throw\noexpand\dtl@testlt{#1}{#2}\noexpand\if@dtl@condition}
+% \end{macrocode}
+%\end{macro}
+%
+% Command to test if first number is greater than second number.
+% This sets \cs{if@dtl@condition}.
+%\begin{macro}{\dtl@testgt}
+% \begin{macrocode}
+\newcommand*{\dtl@testgt}[2]{%
+\DTLifgt{#1}{#2}{\@dtl@conditiontrue}{\@dtl@conditionfalse}}
+% \end{macrocode}
+%\end{macro}
+% Provide conditional command for use in \cs{ifthenelse}
+%\begin{macro}{\DTLisgt}
+% \begin{macrocode}
+\newcommand*{\DTLisgt}[2]{%
+\TE@throw\noexpand\dtl@testgt{#1}{#2}\noexpand\if@dtl@condition}
+% \end{macrocode}
+%\end{macro}
+%
+% Command to test if first number is equal to the second number.
+% This sets \cs{if@dtl@condition}.
+%\begin{macro}{\dtl@testeq}
+% \begin{macrocode}
+\newcommand*{\dtl@testeq}[2]{%
+\DTLifeq{#1}{#2}{\@dtl@conditiontrue}{\@dtl@conditionfalse}}
+% \end{macrocode}
+%\end{macro}
+% Provide conditional command for use in \cs{ifthenelse}
+%\begin{macro}{\DTLiseq}
+% \begin{macrocode}
+\newcommand*{\DTLiseq}[2]{%
+\TE@throw\noexpand\dtl@testeq{#1}{#2}\noexpand\if@dtl@condition}
+% \end{macrocode}
+%\end{macro}
+%
+% Command to test if first number lies between second and third
+% numbers. (End points included.) This sets \cs{if@dtl@condition}.
+%\begin{macro}{\dtl@testclosedbetween}
+% \begin{macrocode}
+\newcommand*{\dtl@testclosedbetween}[3]{%
+\DTLifclosedbetween{#1}{#2}{#3}{\@dtl@conditiontrue}{\@dtl@conditionfalse}}
+% \end{macrocode}
+%\end{macro}
+% Provide conditional command for use in \cs{ifthenelse}
+%\begin{macro}{\DTLisclosedbetween}
+% \begin{macrocode}
+\newcommand*{\DTLisclosedbetween}[3]{%
+\TE@throw\noexpand\dtl@testclosedbetween{#1}{#2}{#3}%
+\noexpand\if@dtl@condition}
+% \end{macrocode}
+%\end{macro}
+%
+% Command to test if first number lies between second and third
+% numbers. (End points excluded.) This sets \cs{if@dtl@condition}.
+%\begin{macro}{\dtl@testopenbetween}
+% \begin{macrocode}
+\newcommand*{\dtl@testopenbetween}[3]{%
+\DTLifopenbetween{#1}{#2}{#3}{\@dtl@conditiontrue}{\@dtl@conditionfalse}}
+% \end{macrocode}
+%\end{macro}
+% Provide conditional command for use in \cs{ifthenelse}
+%\begin{macro}{\DTLisopenbetween}
+% \begin{macrocode}
+\newcommand*{\DTLisopenbetween}[3]{%
+\TE@throw\noexpand\dtl@testopenbetween{#1}{#2}{#3}%
+\noexpand\if@dtl@condition}
+% \end{macrocode}
+%\end{macro}
+%
+% 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{macro}{\dtl@testclosedbetween}
+% \begin{macrocode}
+\newcommand*{\dtl@testFPclosedbetween}[3]{%
+\DTLifFPclosedbetween{#1}{#2}{#3}%
+{\@dtl@conditiontrue}{\@dtl@conditionfalse}}
+% \end{macrocode}
+%\end{macro}
+% Provide conditional command for use in \cs{ifthenelse}
+%\begin{macro}{\DTLisFPclosedbetween}
+% \begin{macrocode}
+\newcommand*{\DTLisFPclosedbetween}[3]{%
+\TE@throw\noexpand\dtl@testFPclosedbetween{#1}{#2}{#3}%
+\noexpand\if@dtl@condition}
+% \end{macrocode}
+%\end{macro}
+%
+% 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{macro}{\dtl@testopenbetween}
+% \begin{macrocode}
+\newcommand*{\dtl@testFPopenbetween}[3]{%
+\DTLifFPopenbetween{#1}{#2}{#3}{\@dtl@conditiontrue}{\@dtl@conditionfalse}}
+% \end{macrocode}
+%\end{macro}
+% Provide conditional command for use in \cs{ifthenelse}
+%\begin{macro}{\DTLisFPopenbetween}
+% \begin{macrocode}
+\newcommand*{\DTLisFPopenbetween}[3]{%
+\TE@throw\noexpand\dtl@testFPopenbetween{#1}{#2}{#3}%
+\noexpand\if@dtl@condition}
+% \end{macrocode}
+%\end{macro}
+%
+% 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{macro}{\dtl@testFPislt}
+% \begin{macrocode}
+\newcommand*{\dtl@testFPislt}[2]{%
+\FPiflt{#1}{#2}\@dtl@conditiontrue\else\@dtl@conditionfalse\fi}
+% \end{macrocode}
+%\end{macro}
+% Provide conditional command for use in \cs{ifthenelse}
+%\begin{macro}{\DTLisFPlt}
+% \begin{macrocode}
+\newcommand*{\DTLisFPlt}[2]{%
+\TE@throw\noexpand\dtl@testFPislt{#1}{#2}%
+\noexpand\if@dtl@condition}
+% \end{macrocode}
+%\end{macro}
+%
+% 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{macro}{\dtl@testFPisgt}
+% \begin{macrocode}
+\newcommand*{\dtl@testFPisgt}[2]{%
+\FPifgt{#1}{#2}\@dtl@conditiontrue\else\@dtl@conditionfalse\fi}
+% \end{macrocode}
+%\end{macro}
+% Provide conditional command for use in \cs{ifthenelse}
+%\begin{macro}{\DTLisFPgt}
+% \begin{macrocode}
+\newcommand*{\DTLisFPgt}[2]{%
+\TE@throw\noexpand\dtl@testFPisgt{#1}{#2}%
+\noexpand\if@dtl@condition}
+% \end{macrocode}
+%\end{macro}
+%
+% Command to test if two numbers are equal, where both numbers
+% are in standard decimal format
+%\begin{macro}{\dtl@testFPiseq}
+% \begin{macrocode}
+\newcommand*{\dtl@testFPiseq}[2]{%
+\FPifeq{#1}{#2}\@dtl@conditiontrue\else\@dtl@conditionfalse\fi}
+% \end{macrocode}
+%\end{macro}
+% Provide conditional command for use in \cs{ifthenelse}
+%\begin{macro}{\DTLisFPeq}
+% \begin{macrocode}
+\newcommand*{\DTLisFPeq}[2]{%
+\TE@throw\noexpand\dtl@testFPiseq{#1}{#2}%
+\noexpand\if@dtl@condition}
+% \end{macrocode}
+%\end{macro}
+%
+% 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{macro}{\dtl@testFPislteq}
+% \begin{macrocode}
+\newcommand*{\dtl@testFPislteq}[2]{%
+\FPiflt{#1}{#2}\@dtl@conditiontrue\else\@dtl@conditionfalse\fi
+\if@dtl@condition
+\else
+ \dtl@testFPiseq{#1}{#2}%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+% Provide conditional command for use in \cs{ifthenelse}
+%\begin{macro}{\DTLisFPlteq}
+% \begin{macrocode}
+\newcommand*{\DTLisFPlteq}[2]{%
+\TE@throw\noexpand\dtl@testFPislteq{#1}{#2}%
+\noexpand\if@dtl@condition}
+% \end{macrocode}
+%\end{macro}
+%
+% 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{macro}{\dtl@testFPisgteq}
+% \begin{macrocode}
+\newcommand*{\dtl@testFPisgteq}[2]{%
+\FPifgt{#1}{#2}\@dtl@conditiontrue\else\@dtl@conditionfalse\fi
+\if@dtl@condition
+\else
+ \dtl@testFPiseq{#1}{#2}%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+% Provide conditional command for use in \cs{ifthenelse}
+%\begin{macro}{\DTLisFPgteq}
+% \begin{macrocode}
+\newcommand*{\DTLisFPgteq}[2]{%
+\TE@throw\noexpand\dtl@testFPisgteq{#1}{#2}%
+\noexpand\if@dtl@condition}
+% \end{macrocode}
+%\end{macro}
+%
+%
+% Command to test if argument is a string. This sets
+% \cs{if@dtl@condition}
+%\begin{macro}{\dtl@teststring}
+% \begin{macrocode}
+\newcommand*{\dtl@teststring}[1]{%
+\DTLifstring{#1}{\@dtl@conditiontrue}{\@dtl@conditionfalse}}
+% \end{macrocode}
+%\end{macro}
+% Provide conditional command for use in \cs{ifthenelse}
+%\begin{macro}{\DTLisstring}
+% \begin{macrocode}
+\newcommand*{\DTLisstring}[1]{%
+\TE@throw\noexpand\dtl@teststring{#1}\noexpand\if@dtl@condition}
+% \end{macrocode}
+%\end{macro}
+%
+% Command to test if argument is a numerical. This sets
+% \cs{if@dtl@condition}
+%\begin{macro}{\dtl@testnumerical}
+% \begin{macrocode}
+\newcommand*{\dtl@testnumerical}[1]{%
+\DTLifnumerical{#1}{\@dtl@conditiontrue}{\@dtl@conditionfalse}%
+}
+% \end{macrocode}
+%\end{macro}
+% Provide conditional command for use in \cs{ifthenelse}
+%\begin{macro}{\DTLisnumerical}
+% \begin{macrocode}
+\newcommand*{\DTLisnumerical}[1]{%
+\TE@throw\noexpand\dtl@testnumerical{#1}\noexpand\if@dtl@condition}
+% \end{macrocode}
+%\end{macro}
+%
+% Command to test if argument is an integer. This sets
+% \cs{if@dtl@condition}
+%\begin{macro}{\dtl@testint}
+% \begin{macrocode}
+\newcommand*{\dtl@testint}[1]{%
+\DTLifint{#1}{\@dtl@conditiontrue}{\@dtl@conditionfalse}}
+% \end{macrocode}
+%\end{macro}
+% Provide conditional command for use in \cs{ifthenelse}
+%\begin{macro}{\DTLisint}
+% \begin{macrocode}
+\newcommand*{\DTLisint}[1]{%
+\TE@throw\noexpand\dtl@testint{#1}\noexpand\if@dtl@condition}
+% \end{macrocode}
+%\end{macro}
+%
+% Command to test if argument is a real. This sets
+% \cs{if@dtl@condition}
+%\begin{macro}{\dtl@testreal}
+% \begin{macrocode}
+\newcommand*{\dtl@testreal}[1]{%
+\DTLifreal{#1}{\@dtl@conditiontrue}{\@dtl@conditionfalse}}
+% \end{macrocode}
+%\end{macro}
+% Provide conditional command for use in \cs{ifthenelse}
+%\begin{macro}{\DTLisreal}
+% \begin{macrocode}
+\newcommand*{\DTLisreal}[1]{%
+\TE@throw\noexpand\dtl@testreal{#1}\noexpand\if@dtl@condition}
+% \end{macrocode}
+%\end{macro}
+%
+% Command to test if argument is a currency. This sets
+% \cs{if@dtl@condition}
+%\begin{macro}{\dtl@testcurrency}
+% \begin{macrocode}
+\newcommand*{\dtl@testcurrency}[1]{%
+\DTLifcurrency{#1}{\@dtl@conditiontrue}{\@dtl@conditionfalse}}
+% \end{macrocode}
+%\end{macro}
+% Provide conditional command for use in \cs{ifthenelse}
+%\begin{macro}{\DTLiscurrency}
+% \begin{macrocode}
+\newcommand*{\DTLiscurrency}[1]{%
+\TE@throw\noexpand\dtl@testcurrency{#1}\noexpand\if@dtl@condition}
+% \end{macrocode}
+%\end{macro}
+%
+% Command to test if argument is a currency with given unit. This sets
+% \cs{if@dtl@condition}
+%\begin{macro}{\dtl@testcurrencyunit}
+% \begin{macrocode}
+\newcommand*{\dtl@testcurrencyunit}[2]{%
+\DTLifcurrencyunit{#1}{#2}{\@dtl@conditiontrue}{\@dtl@conditionfalse}}
+% \end{macrocode}
+%\end{macro}
+% Provide conditional command for use in \cs{ifthenelse}
+%\begin{macro}{\DTLiscurrencyunit}
+% \begin{macrocode}
+\newcommand*{\DTLiscurrencyunit}[2]{%
+\TE@throw\noexpand\dtl@testcurrencyunit{#1}{#2}%
+\noexpand\if@dtl@condition}
+% \end{macrocode}
+%\end{macro}
+%
+% \subsection{Defining New Databases}
+% A database is stored internally as a list of lists, where each list
+% is a row of data. The data is stored as a comma separated list of
+% \marg{id}\marg{value} pairs, where \meta{id} is an
+% identifier
+% and \meta{value} is the value. \cs{DTLnewdb}\marg{name}
+% initialises a database called \meta{name}. The keys associated
+% with this database are stored in \cs{dtlkeys@}\meta{name}
+% A new count register \cs{dtlrows@}\meta{db name} is created.
+% This stores the total number of rows in the data base.
+%\begin{macro}{\DTLnewdb}
+% \begin{macrocode}
+\newcommand*{\DTLnewdb}[1]{%
+\DTLifdbexists{#1}{%
+\PackageError{datatool}{Database `#1' already exists}{}}{%
+\dtl@message{Creating database `#1'}%
+\expandafter\gdef\csname dtldb@#1\endcsname{}%
+\expandafter\gdef\csname dtlkeys@#1\endcsname{}%
+\expandafter\global\expandafter\newcount\csname dtlrows@#1\endcsname}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{definition}
+% \cs{DTLrowcount}\marg{db name}
+%\end{definition}
+% Number of rows in \meta{db name}
+%\begin{macro}{\DTLrowcount}
+% \begin{macrocode}
+\newcommand*{\DTLrowcount}[1]{%
+\expandafter\number\csname dtlrows@#1\endcsname}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{definition}
+% \cs{DTLifempty}\marg{name}\marg{true part}\marg{false part}
+%\end{definition}
+% Check if named database is empty (i.e.\ no rows have been added.)
+%\begin{macro}{\DTLifdbempty}
+% \begin{macrocode}
+\newcommand{\DTLifdbempty}[3]{%
+\DTLifdbexists{#1}{%
+\expandafter\ifx\csname dtldb@#1\endcsname\@empty
+ #2%
+\else
+ #3%
+\fi}{%
+\PackageError{Database `#1' doesn't exist}{}{}}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{definition}
+% \cs{DTLnewrow}\marg{db name}
+%\end{definition}
+% Add a new row to named database.
+%\begin{macro}{\DTLnewrow}
+% \begin{macrocode}
+\newcommand*{\DTLnewrow}[1]{%
+\DTLifdbempty{#1}{%
+ \expandafter\gdef\csname dtldb@#1\endcsname{{}}%
+ \expandafter\global\expandafter\advance
+ \csname dtlrows@#1\endcsname by 1\relax
+ \dtl@message{New row added to database `#1'}%
+}{%
+ \expandafter\let\expandafter\@dtl@olddb\csname dtldb@#1\endcsname%
+ \expandafter\toks@\expandafter{\@dtl@olddb,{}}%
+ \expandafter\xdef\csname dtldb@#1\endcsname{\the\toks@}%
+ \expandafter\global\expandafter\advance
+ \csname dtlrows@#1\endcsname by 1\relax
+ \dtl@message{New row added to database `#1'}%
+}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{definition}
+% \cs{DTLnewdbentry}\marg{db name}\marg{id}\marg{value}.
+%\end{definition}
+% Add an entry to the last row (adds new row if database is empty.)
+%
+% When a new entry is added, the control sequence
+% \cs{@dtl@idtype@}\meta{db name}\texttt{@}\meta{id} is checked.
+% This keeps track of the type of all the entries with the given ID
+% for the given database. If this control
+% sequence doesn't exist, a new one is created, and set to the
+% relevant type: 0 (string), 1 (int) or 2 (real). If it exists,
+% then it is set as follows: if has a value of 0 (string), it
+% remains unchanged. If it has another value, then it is set to
+% 2 (real) if it was either 1 or 2 and \meta{value} is 2, it is
+% set to 1 if \meta{value} is 1, otherwise it remains unchanged.
+%\begin{macro}{\DTLnewdbentry}
+% \begin{macrocode}
+\newcommand{\DTLnewdbentry}[3]{%
+% \end{macrocode}
+% Set \cs{@dtl@dbvalue} to the value of this entry
+% \begin{macrocode}
+\expandafter\@dtl@toks\expandafter{#3}%
+\edef\@dtl@dbvalue{\the\@dtl@toks}%
+% \end{macrocode}
+% Set \cs{@dtl@dbid} to the entry ID. This uses \cs{edef} to allow
+% for the ID to be stored in a control sequence.
+% \begin{macrocode}
+\edef\@dtl@dbid{#2}%
+% \end{macrocode}
+% Set up the correct entry format:
+% \begin{macrocode}
+\long\edef\@dtl@dbentry{{\@dtl@dbid}{\the\@dtl@toks}}%
+% \end{macrocode}
+% If database is empty, add new row.
+% \begin{macrocode}
+\DTLifdbempty{#1}{\DTLnewrow{#1}}{}%
+% \end{macrocode}
+% Add the entry to the last row of the database:
+% Split the database into the last row
+% (\cs{@dtl@dblastrow}), and everything except the last row
+% (\cs{@dtl@dbrest}.)
+% \begin{macrocode}
+\expandafter\dtl@choplast\expandafter{%
+\csname dtldb@#1\endcsname}{\@dtl@dbrest}{\@dtl@dblastrow}%
+% \end{macrocode}
+% Check if the last row already contains an entry with this ID.
+% If so, generate an error, otherwise append this entry to the
+% row, and reconstruct database list.
+% \begin{macrocode}
+\dtl@ifrowcontains{#2}{\@dtl@dblastrow}{%
+\PackageError{datatool}{Can't add entry with ID `#2' to current
+row of database `#1'}{There is already an entry with this ID on
+the current row}}{%
+% \end{macrocode}
+% Append entry to last row
+% \begin{macrocode}
+\expandafter\@dtl@toks\expandafter{\@dtl@dbentry}%
+\ifthenelse{\equal{}{\@dtl@dblastrow}}{%
+ \edef\@dtl@dblastrow{\the\@dtl@toks}%
+}{%
+ \expandafter\toks@\expandafter{\@dtl@dblastrow}%
+ \edef\@dtl@dblastrow{\the\toks@,\the\@dtl@toks}%
+}%
+% \end{macrocode}
+% Reconstruct list.
+% \begin{macrocode}
+\expandafter\@dtl@toks\expandafter{\@dtl@dblastrow}%
+\ifthenelse{\equal{}{\@dtl@dbrest}}{%
+ \expandafter\long\expandafter\xdef\csname dtldb@#1\endcsname{%
+ {\the\@dtl@toks}}%
+}{%
+ \expandafter\toks@\expandafter{\@dtl@dbrest}%
+ \expandafter\long\expandafter\xdef\csname dtldb@#1\endcsname{%
+ \the\toks@,{\the\@dtl@toks}}%
+}%
+% \end{macrocode}
+% Set the keys
+% \begin{macrocode}
+\@dtl@setidtype{#1}{#2}{#3}%
+\expandafter\@dtl@setkeys\expandafter{#2}{#1}%
+}%
+\dtl@message{Added #2\space -> #3\space to database `#1'}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{definition}
+% \cs{@dtl@setidtype}\marg{db name}\marg{id}\marg{value}
+%\end{definition}
+% Set the type for \meta{id} according to \meta{value}.
+% If \meta{value} is empty, leave \cs{@dtl@idtype}\meta{id}
+% unchanged (if defined) or define as empty if not defined.
+%\begin{macro}{\@dtl@setidtype}
+% \begin{macrocode}
+\newcommand{\@dtl@setidtype}[3]{%
+\@dtl@checknumerical{#3}%
+\def\@dtl@value{#3}%
+\@ifundefined{@dtl@idtype@#1@#2}{%
+\ifx\@dtl@value\@empty
+ \expandafter\gdef\csname @dtl@idtype@#1@#2\endcsname{}%
+\else
+ \expandafter\xdef\csname @dtl@idtype@#1@#2\endcsname{%
+ \the\@dtl@datatype}%
+\fi
+}{%
+\ifx\@dtl@value\@empty
+\else
+ \expandafter\ifx\csname @dtl@idtype@#1@#2\endcsname\@empty
+ \expandafter\xdef\csname @dtl@idtype@#1@#2\endcsname{%
+ \the\@dtl@datatype}%
+ \else
+ \expandafter\@dtl@tmpcount\expandafter=
+ \csname @dtl@idtype@#1@#2\endcsname
+ \ifcase\@dtl@tmpcount
+ % string, leave as it is
+ \or
+ % int, set to whatever \@dtl@datatype is
+ \expandafter\xdef\csname @dtl@idtype@#1@#2\endcsname{%
+ \the\@dtl@datatype}%
+ \or
+ % real, set to real unless <value> is a string
+ \ifnum\@dtl@datatype=0\relax
+ \expandafter\gdef\csname @dtl@idtype@#1@#2\endcsname{0}%
+ \else
+ \expandafter\gdef\csname @dtl@idtype@#1@#2\endcsname{2}%
+ \fi
+ \fi
+ \fi
+\fi
+}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{definition}
+%\cs{@dtl@setkeys}\marg{key}\marg{db name}
+%\end{definition}
+% Adds \marg{key} to \cs{dtlkeys@}\meta{db name} if not already
+% in it.
+%\begin{macro}{\@dtl@setkeys}
+% \begin{macrocode}
+\newcommand*{\@dtl@setkeys}[2]{%
+\edef\@dtl@tmp{\csname dtlkeys@#2\endcsname}%
+\expandafter\@dtl@toks\expandafter{\@dtl@tmp}%
+\expandafter\ifx\csname dtlkeys@#2\endcsname\@empty
+ \expandafter\gdef\csname dtlkeys@#2\endcsname{#1}%
+\else
+ \@for\dtl@key:=\@dtl@tmp\do{%
+ \ifthenelse{\equal{\dtl@key}{#1}}{\@endfortrue}{}%
+ }%
+ \if@endfor
+ \else
+ \expandafter\xdef\csname dtlkeys@#2\endcsname{\the\@dtl@toks,#1}%
+ \fi
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{definition}
+% \cs{@dtl@getidtype}\marg{db name}\marg{id}
+%\end{definition}
+% Get the data type for \meta{id} in given database.
+%\begin{macro}{\@dtl@getidtype}
+% \begin{macrocode}
+\newcommand*{\@dtl@getidtype}[2]{%
+\csname @dtl@idtype@#1@#2\endcsname}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{definition}
+%\cs{DTLifdbexists}\marg{db name}\marg{true part}\marg{false part}
+%\end{definition}
+% Check if a data base with the given name exists:
+%\begin{macro}{\DTLifdbexists}
+% \begin{macrocode}
+\newcommand{\DTLifdbexists}[3]{%
+\@ifundefined{dtldb@#1}{#3}{#2}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{definition}
+% \cs{dtl@ifrowcontains}\meta{id}\meta{cmd}\meta{true part}\meta{false
+%part}
+%\end{definition}
+% Check to see if the row given by \meta{cmd} contains an
+% entry with ID given by \meta{id}. If true, do \meta{true part},
+% otherwise do \meta{false part}.
+%\begin{macro}{\dtl@ifrowcontains}
+% \begin{macrocode}
+\newcommand{\dtl@ifrowcontains}[4]{%
+\@for\@dtl@element:=#2\do{%
+\dtl@getentryid{\@dtl@element}{\@dtl@entryid}%
+\ifthenelse{\equal{#1}{\@dtl@entryid}}{\@endfortrue}{}%
+}%
+\if@endfor #3\else #4\fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{definition}
+% \cs{dtl@getentryid}\meta{entry cmd}\meta{id cmd}
+%\end{definition}
+% Get the ID for an entry given by \meta{entry cmd}, and stores in
+% in \meta{id cmd}.
+%\begin{macro}{\dtl@getentryid}
+% \begin{macrocode}
+\newcommand*{\dtl@getentryid}[2]{\expandafter\@dtl@getentryid#1#2}
+\long\def\@dtl@getentryid#1#2#3{\def#3{#1}}
+% \end{macrocode}
+%\end{macro}
+%\begin{definition}
+% \cs{dtl@getentryvalue}\meta{entry cmd}\meta{cmd}
+%\end{definition}
+% Stores the entry value in \meta{cmd} for
+% entry given by \meta{entry cmd}.
+%\begin{macro}{\dtl@getentryvalue}
+% \begin{macrocode}
+\newcommand*{\dtl@getentryvalue}[2]{%
+\expandafter\@dtl@getentryvalue#1#2}
+\long\def\@dtl@getentryvalue#1#2#3{\gdef#3{#2}}
+% \end{macrocode}
+%\end{macro}
+%
+%\cs{DTLforeach} can only be nested up to three levels.
+% \cs{dtlforeachlevel} keeps track of the current level.
+%\begin{macro}{\dtlforeachlevel}
+% \begin{macrocode}
+\global\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}
+\newcommand*{\theHDTLrow}{\arabic{DTLrow}}
+\newcommand*{\theHDTLrowi}{\theHDTLrow.\arabic{DTLrowi}}
+\newcommand*{\theHDTLrowii}{\theHDTLrowi.\arabic{DTLrowii}}
+\newcommand*{\theHDTLrowiii}{\theHDTLrowii.\arabic{DTLrowiii}}
+% \end{macrocode}
+%
+%\begin{definition}
+%\cs{DTLsavelastrowcount}\marg{cmd}
+%\end{definition}
+% Stores the maximum row count for the last \cs{DTLforeach}.
+%\begin{macro}{\DTLsaverowcount}
+% \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{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 is reconstructed to allow for
+% rows to be edited.
+%\begin{macro}{\DTLforeach}
+% \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}%
+\global\c@DTLrow=\c@DTLrow
+% \end{macrocode}
+% Store database name
+% \begin{macrocode}
+\gdef\@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}{}%
+\else
+% \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}
+% Construct updated database:
+% \begin{macrocode}
+ \expandafter\global\expandafter\let
+ \csname @dtl@foreachrows@\romannumeral\dtlforeachlevel\endcsname
+ =\@empty
+% \end{macrocode}
+% Database name:
+% \begin{macrocode}
+ \expandafter\global\expandafter\let
+ \csname @dtl@dbname@\romannumeral\dtlforeachlevel\endcsname
+ =\@dtl@dbname
+% \end{macrocode}
+% Iterate through each row
+% \begin{macrocode}
+ \expandafter\let\expandafter\@dtl@db\csname dtldb@#2\endcsname%
+ \@for\@dtl@currentrow:=\@dtl@db\do{%
+% \end{macrocode}
+% Set current row macro for this level
+% \begin{macrocode}
+ \expandafter\global\expandafter
+ \let\csname @dtl@thiscurrentrow@\romannumeral\dtlforeachlevel
+ \endcsname=\@dtl@currentrow
+% \end{macrocode}
+% Assign commands to the required entries
+% \begin{macrocode}
+ \ifx\relax#3\relax
+ \else
+ \@dtl@assign{#3}%
+ \fi
+% \end{macrocode}
+% Do the main body of text if condition is satisfied
+% \begin{macrocode}
+ \ifthenelse{#1}{%
+ \refstepcounter{DTLrow\romannumeral\dtlforeachlevel}%
+ \expandafter\edef\expandafter\DTLcurrentindex\expandafter
+ {\arabic{DTLrow\romannumeral\dtlforeachlevel}}%
+ #4%
+ }{}%
+% \end{macrocode}
+% Reconstruct database
+% \begin{macrocode}
+ \expandafter\let\expandafter\@dtl@thiscurrentrow
+ \csname @dtl@thiscurrentrow@\romannumeral\dtlforeachlevel\endcsname
+% \end{macrocode}
+% Don't add this row if it is now empty
+% \begin{macrocode}
+ \ifx\@dtl@thiscurrentrow\@empty
+ \else
+ \expandafter\@dtl@toks\expandafter{\@dtl@thiscurrentrow}%
+ \expandafter
+ \ifx
+ \csname @dtl@foreachrows@\romannumeral\dtlforeachlevel\endcsname
+ \@empty
+ \expandafter
+ \xdef\csname @dtl@foreachrows@\romannumeral\dtlforeachlevel\endcsname{{\the\@dtl@toks}}%
+ \else
+ \expandafter\let\expandafter\@dtl@foreachrows\expandafter
+ =\csname @dtl@foreachrows@\romannumeral\dtlforeachlevel\endcsname
+ \expandafter\toks@\expandafter{\@dtl@foreachrows}%
+ \expandafter
+ \xdef\csname @dtl@foreachrows@\romannumeral\dtlforeachlevel\endcsname{\the\toks@,{\the\@dtl@toks}}%
+ \fi
+ \fi
+\@endforfalse
+}%
+ \expandafter\let\expandafter\@dtl@foreachrows\expandafter
+ =\csname @dtl@foreachrows@\romannumeral\dtlforeachlevel\endcsname
+\expandafter\global
+ \expandafter\let\csname dtldb@#2\endcsname=\@dtl@foreachrows
+\fi
+\global\advance\dtlforeachlevel by -1\relax
+}{%
+\PackageError{datatool}{Database `#2' doesn't exist}{}}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{definition}
+%\cs{DTLappendtorow}\marg{key}\marg{value}
+%\end{definition}
+% Appends entry to current row. (The current row is given by
+% \cs{@dtl@thiscurrentrow@}\meta{n} where \meta{n} is roman
+% numeral value of \cs{dtlforeachlevel}.
+%\begin{macro}{\DTLappendtorow}
+% \begin{macrocode}
+\newcommand*{\DTLappendtorow}[2]{%
+\ifnum\dtlforeachlevel=0\relax
+ \PackageError{datatool}{\string\DTLappendtorow\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}
+% Set \cs{@dtl@dbvalue} to the value of this entry
+% \begin{macrocode}
+ \expandafter\@dtl@toks\expandafter{#2}%
+ \edef\@dtl@dbvalue{\the\@dtl@toks}%
+% \end{macrocode}
+% Set \cs{@dtl@dbid} to the entry ID. This uses \cs{edef} to allow
+% for the ID to be stored in a control sequence.
+% \begin{macrocode}
+ \edef\@dtl@dbid{#1}%
+% \end{macrocode}
+% Set up the correct entry format:
+% \begin{macrocode}
+ \edef\@dtl@dbentry{{\@dtl@dbid}{\the\@dtl@toks}}%
+% \end{macrocode}
+% Set \cs{@dtl@thisrow} to the current row.
+% \begin{macrocode}
+ \expandafter\let\expandafter\@dtl@thisrow
+ \csname @dtl@thiscurrentrow@\romannumeral\dtlforeachlevel\endcsname
+% \end{macrocode}
+% Check if there is already an entry with this key
+% \begin{macrocode}
+ \dtl@ifrowcontains{#1}{\@dtl@thisrow}{%
+ \PackageError{datatool}{Can't add entry with ID `#1' to current
+ row of database `\@dtl@thisdb'}{There is already an entry with
+ this ID on the current row}}{%
+% \end{macrocode}
+% Append entry to last row
+% \begin{macrocode}
+ \expandafter\@dtl@toks\expandafter{\@dtl@dbentry}%
+ \ifx\@dtl@thisrow\@empty
+ \expandafter
+ \xdef\csname @dtl@thiscurrentrow@\romannumeral\dtlforeachlevel\endcsname{\the\@dtl@toks}%
+ \else
+ \expandafter\toks@\expandafter{\@dtl@thisrow}%
+ \expandafter
+ \xdef\csname @dtl@thiscurrentrow@\romannumeral\dtlforeachlevel\endcsname{\the\toks@,\the\@dtl@toks}%
+ \fi
+ }
+% \end{macrocode}
+% Update key list
+% \begin{macrocode}
+ \@dtl@setidtype{\@dtl@thisdb}{#1}{#2}%
+ \expandafter\@dtl@setkeys\expandafter{#1}{\@dtl@thisdb}%
+% \end{macrocode}
+% end the \cs{ifnum}
+% \begin{macrocode}
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\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@thiscurrentrow@}\meta{n} where \meta{n} is roman
+% numeral value of \cs{dtlforeachlevel}.
+%\begin{macro}{\DTLremoveentryfromrow}
+% \begin{macrocode}
+\newcommand*{\DTLremoveentryfromrow}[1]{%
+\ifnum\dtlforeachlevel=0\relax
+ \PackageError{datatool}{\string\DTLremoveentryfromrow\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}
+% Set \cs{@dtl@thisrow} to the current row.
+% \begin{macrocode}
+ \expandafter\let\expandafter\@dtl@thisrow
+ \csname @dtl@thiscurrentrow@\romannumeral\dtlforeachlevel\endcsname
+% \end{macrocode}
+% Check row contains an entry with this key
+% \begin{macrocode}
+ \dtl@ifrowcontains{#1}{\@dtl@thisrow}{%
+% \end{macrocode}
+% Split row list
+% \begin{macrocode}
+ \let\@dtl@pre=\@empty
+ \@for\dtl@thisentry:=\@dtl@thisrow\do{%
+ \dtl@getentryid\dtl@thisentry\@dtl@id
+ \ifthenelse{\equal{\@dtl@id}{#1}}{%
+ }{%
+ \expandafter\@dtl@toks\expandafter{\dtl@thisentry}%
+ \ifx\@dtl@pre\@empty
+ \edef\@dtl@pre{{\the\@dtl@toks}}%
+ \else
+ \expandafter\toks@\expandafter{\@dtl@pre}%
+ \edef\@dtl@pre{\the\toks@,{\the\@dtl@toks}}%
+ \fi
+ }
+ }%
+ \expandafter\let
+ \csname @dtl@thiscurrentrow@\romannumeral\dtlforeachlevel\endcsname
+ =\@dtl@pre
+ }{%
+ \PackageError{datatool}{Can't remove entry given by key `#1'
+ from current row in database `\@dtl@thisdb', no such entry}{}%
+ }%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\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
+% \cs{@dtl@thiscurrentrow@}\meta{n} where \meta{n} is roman
+% numeral value of \cs{dtlforeachlevel}.
+%\begin{macro}{\DTLreplaceentryforrow}
+% \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}
+% Set \cs{@dtl@dbvalue} to the value of this entry
+% \begin{macrocode}
+ \expandafter\@dtl@toks\expandafter{#2}%
+ \edef\@dtl@dbvalue{\the\@dtl@toks}%
+% \end{macrocode}
+% Set \cs{@dtl@dbid} to the entry ID. This uses \cs{edef} to allow
+% for the ID to be stored in a control sequence.
+% \begin{macrocode}
+ \edef\@dtl@dbid{#1}%
+% \end{macrocode}
+% Set up the correct entry format:
+% \begin{macrocode}
+ \edef\dtl@newentry{{\@dtl@dbid}{\the\@dtl@toks}}%
+% \end{macrocode}
+% Set \cs{@dtl@thisrow} to the current row.
+% \begin{macrocode}
+ \expandafter\let\expandafter\@dtl@thisrow
+ \csname @dtl@thiscurrentrow@\romannumeral\dtlforeachlevel\endcsname
+% \end{macrocode}
+% Check row contains an entry with this key
+% \begin{macrocode}
+ \dtl@ifrowcontains{#1}{\@dtl@thisrow}{%
+% \end{macrocode}
+% Split row list
+% \begin{macrocode}
+ \let\@dtl@pre=\@empty
+ \@for\dtl@thisentry:=\@dtl@thisrow\do{%
+ \dtl@getentryid\dtl@thisentry\@dtl@id
+ \ifthenelse{\equal{\@dtl@id}{#1}}{%
+ \expandafter\@dtl@toks\expandafter{\dtl@newentry}%
+ }{%
+ \expandafter\@dtl@toks\expandafter{\dtl@thisentry}%
+ }
+ \ifx\@dtl@pre\@empty
+ \edef\@dtl@pre{{\the\@dtl@toks}}%
+ \else
+ \expandafter\toks@\expandafter{\@dtl@pre}%
+ \edef\@dtl@pre{\the\toks@,{\the\@dtl@toks}}%
+ \fi
+ }%
+ \expandafter\let
+ \csname @dtl@thiscurrentrow@\romannumeral\dtlforeachlevel\endcsname
+ =\@dtl@pre
+ }{%
+ \PackageError{datatool}{Can't remove entry given by key `#1'
+ from current row in database `\@dtl@thisdb', no such entry}{}%
+ }%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{definition}
+%\cs{DTLremovecurrentrow}
+%\end{definition}
+% Removes current row. This just sets the current row to empty
+%\begin{macro}{\DTLremoveentryfromrow}
+% \begin{macrocode}
+\newcommand*{\DTLremovecurrentrow}[1]{%
+\ifnum\dtlforeachlevel=0\relax
+ \PackageError{datatool}{\string\DTLremovecurrentrow\space can only
+ be used inside \string\DTLforeach}{}%
+\else
+% \end{macrocode}
+% Set current row to empty.
+% \begin{macrocode}
+ \expandafter\let
+ \csname @dtl@thiscurrentrow@\romannumeral\dtlforeachlevel\endcsname
+ =\@empty
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{definition}
+%\cs{DTLforeachkeyinrow}\marg{cmd}\marg{text}
+%\end{definition}
+% Iterates through each key in the row, and does \meta{text}.
+%\begin{macro}{\DTLforeachkeyinrow}
+% \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@thisrow} to the current row.
+% \begin{macrocode}
+ \expandafter\let\expandafter\@dtl@thisrow
+ \csname @dtl@thiscurrentrow@\romannumeral\dtlforeachlevel\endcsname
+% \end{macrocode}
+% Iterate through the row
+% \begin{macrocode}
+ \@for\dtl@thisentry:=\@dtl@thisrow\do{%
+ \dtl@getentryvalue\dtl@thisentry{#1}%
+ #2%
+ }%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%
+%\begin{definition}
+%\cs{DTLaddentryforrow}\marg{db name}\marg{assign list}\marg{condition}\marg{key}\marg{value}
+%\end{definition}
+%\begin{macro}{\DTLaddentryforrow}
+% \begin{macrocode}
+\newcommand{\DTLaddentryforrow}[5]{%
+\gdef\@dtl@dbname{#1}%
+\DTLifdbexists{#1}{%
+% \end{macrocode}
+% Set \cs{@dtl@dbvalue} to the value of this entry
+% \begin{macrocode}
+ \expandafter\@dtl@toks\expandafter{#5}%
+ \edef\@dtl@dbvalue{\the\@dtl@toks}%
+% \end{macrocode}
+% Set \cs{@dtl@dbid} to the entry ID. This uses \cs{edef} to allow
+% for the ID to be stored in a control sequence.
+% \begin{macrocode}
+ \edef\@dtl@dbid{#4}%
+% \end{macrocode}
+% Set up the correct entry format:
+% \begin{macrocode}
+ \edef\@dtl@dbentry{{\@dtl@dbid}{\the\@dtl@toks}}%
+% \end{macrocode}
+% Store the database in \cs{@dtl@db}
+% \begin{macrocode}
+ \expandafter
+ \let\expandafter\@dtl@db\csname dtldb@\@dtl@dbname\endcsname%
+ \let\@dtl@prerow=\@empty
+% \end{macrocode}
+% Iterate through each row of the database
+% \begin{macrocode}
+ \@for\@dtl@currentrow:=\@dtl@db\do{%
+ \@dtl@assign{#2}%
+ \ifthenelse{#3}{%
+ \expandafter\@dtl@toks\expandafter{\@dtl@dbentry}%
+ \ifx\@dtl@currentrow\@empty
+ \edef\@dtl@currentrow{{\the\@dtl@toks}}%
+ \else
+ \expandafter\toks@\expandafter{\@dtl@currentrow}%
+ \edef\@dtl@currentrow{\the\toks@,{\the\@dtl@toks}}%
+ \fi
+ \@endfortrue
+ }{%
+ }%
+ \expandafter\@dtl@toks\expandafter{\@dtl@currentrow}%
+ \ifx\@dtl@prerow\@empty
+ \edef\@dtl@prerow{{\the\@dtl@toks}}%
+ \else
+ \expandafter\toks@\expandafter{\@dtl@prerow}%
+ \edef\@dtl@prerow{\the\toks@,{\the\@dtl@toks}}%
+ \fi
+}%
+\if@endfor
+ \expandafter\@dtl@toks\expandafter{\@forremainder}%
+ \expandafter\toks@\expandafter{\@dtl@prerow}%
+ \edef\@dtl@prerow{\the\toks@,{\the\@dtl@toks}}%
+ \expandafter\global\expandafter
+ \let\csname dtldb@\@dtl@dbname\endcsname=\@dtl@prerow
+\else
+ \PackageError{datatool}{Unable to add `#5' for key `#4' - condition
+ not met for any row in database `#1'}{}%
+\fi
+\@endforfalse
+}{%
+\PackageError{datatool}{Database `#1' doesn't exist}{}}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\cs{@dtl@assign}\marg{values} assigns each command in
+% \meta{values} (see above) to the value of the corresponding
+% ID for the row given by \cs{@dtl@currentrow}.
+%\begin{macro}{\@dtl@assign}
+% \begin{macrocode}
+\newcommand*{\@dtl@assign}[1]{%
+\@dtl@assigncmd#1,\relax\@@
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{definition}
+% \cs{\@dtl@assigncmd}\meta{cmd}=\meta{id}\cs{@nil}
+%\end{definition}
+% Assign \meta{cmd} to value given by \meta{id}
+%\begin{macro}{\@dtl@assigncmd}
+% \begin{macrocode}
+\def\@dtl@assigncmd#1=#2,#3\@@{%
+\@for\@dtl@entry:=\@dtl@currentrow\do{%
+\dtl@getentryid\@dtl@entry\@dtl@id
+\ifthenelse{\equal{\@dtl@id}{#2}}{%
+\dtl@getentryvalue\@dtl@entry#1%
+\@endfortrue}{}%
+}%
+\if@endfor
+\else
+ \@dtl@setnull{#1}{#2}%
+\fi
+\@endforfalse
+\ifx\relax#3%
+ \let\@dtl@next=\@dtl@assigncmdnoop
+\else
+ \let\@dtl@next=\@dtl@assigncmd
+\fi
+\@dtl@next#3\@@
+}
+% \end{macrocode}
+%\end{macro}
+% End loop
+%\begin{macro}{\@dtl@assigncmdnoop}
+% \begin{macrocode}
+\def\@dtl@assigncmdnoop#1\@@{}
+% \end{macrocode}
+%\end{macro}
+%\cs{@dtl@setnull}\marg{cmd}\marg{id} sets \meta{cmd} to either
+% NULL or 0 depending on the data type for \meta{id}. (Database
+% name should be stored in \cs{@dtl@dbname} prior to use.
+%\begin{macro}{\@dtl@setnull}
+% \begin{macrocode}
+\newcommand*{\@dtl@setnull}[2]{%
+\@ifundefined{@dtl@idtype@\@dtl@dbname @#2}{%
+\PackageError{datatool}{Key `#2' not defined in database
+`\@dtl@dbname'}{}}{%
+\edef\@dtl@tmp{0\@dtl@getidtype{\@dtl@dbname}{#2}}%
+\expandafter\ifnum\@dtl@tmp=0\relax
+ \gdef#1{NULL}%
+\else
+ \gdef#1{0}%
+\fi
+}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{definition}
+%\cs{dtl@gathervalues}\marg{db name}\marg{row}
+%\end{definition}
+% Stores each element of \meta{row} in \meta{db name} into
+% the command \cs{@dtl@key@}\meta{key}, where \meta{key} is the
+% key for that element.
+%\begin{macro}{\dtl@gathervalues}
+% \begin{macrocode}
+\newcommand{\dtl@gathervalues}[2]{%
+\edef\@dtl@tmp{\csname dtlkeys@#1\endcsname}%
+\def\@dtl@list{}%
+\@for\dtl@key:=\@dtl@tmp\do{%
+ \expandafter\@dtl@setnull\expandafter{%
+ \csname @dtl@key@\dtl@key\endcsname}{\dtl@key}%
+ \@for\dtl@thiselement:=#2\do{%
+ \dtl@getentryid\dtl@thiselement\@dtl@id
+ \DTLifstringeq{\@dtl@id}{\dtl@key}{%
+ \dtl@getentryvalue\dtl@thiselement\@dtl@value%
+ \expandafter\protected@edef\csname @dtl@key@\dtl@key\endcsname{\@dtl@value}%
+ \@endfortrue}{}%
+ }%
+\@endforfalse
+}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{definition}
+%\cs{DTLsumforkeys}\oarg{condition}\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 optional argument \meta{condition} is the same as that
+% for \cs{DTLforeach}.
+%\begin{macro}{\DTLsumforkeys}
+% \begin{macrocode}
+\newcommand*{\DTLsumforkeys}[4][\boolean{true}\and
+\DTLisnumerical{\DTLthisval}]{%
+\def#4{0}%
+\@for\@dtl@dbname:=#2\do{%
+ \DTLifdbexists{\@dtl@dbname}{%
+ \expandafter
+ \let\expandafter\@dtl@db\csname dtldb@\@dtl@dbname\endcsname%
+ \@for\@dtl@currentrow:=\@dtl@db\do{%
+ \dtl@gathervalues{\@dtl@dbname}{\@dtl@currentrow}%
+ \@for\@dtl@key:=#3\do{%
+ \protected@edef\DTLthisval{%
+ \csname @dtl@key@\@dtl@key\endcsname}%
+ \ifthenelse{#1}{\DTLadd{#4}{#4}{\DTLthisval}}{}%
+ }}%
+ }{\PackageError{datatool}{Database `\@dtl@dbname' doesn't exist}{}%
+ }%
+}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{definition}
+%\cs{DTLmeanforkeys}\oarg{condition}\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 optional argument \meta{condition} is the same as that
+% for \cs{DTLforeach}.
+%\begin{macro}{\DTLmeanforkeys}
+% \begin{macrocode}
+\newcommand*{\DTLmeanforkeys}[4][\boolean{true}\and
+\DTLisnumerical{\DTLthisval}]{%
+\def#4{0}%
+\def\dtl@n{0}%
+\@for\@dtl@dbname:=#2\do{%
+\DTLifdbexists{\@dtl@dbname}{%
+ \expandafter
+ \let\expandafter\@dtl@db\csname dtldb@\@dtl@dbname\endcsname%
+ \@for\@dtl@currentrow:=\@dtl@db\do{%
+ \dtl@gathervalues{\@dtl@dbname}{\@dtl@currentrow}%
+ \@for\@dtl@key:=#3\do{%
+ \protected@edef\DTLthisval{%
+ \csname @dtl@key@\@dtl@key\endcsname}%
+ \ifthenelse{#1}{%
+ \DTLadd{#4}{#4}{\DTLthisval}%
+ \DTLadd{\dtl@n}{\dtl@n}{1}%
+ }{}%
+ }}%
+}{\PackageError{datatool}{Database `\@dtl@dbname' doesn't exist}{}}}%
+\ifnum\dtl@n=0\relax
+ \PackageError{datatool}{Can't compute mean, no data!}{}%
+\else
+ \DTLdiv{#4}{#4}{\dtl@n}%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{definition}
+%\cs{DTLvarianceforkeys}\oarg{condition}\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 optional argument \meta{condition} is the same as that
+% for \cs{DTLforeach}.
+%\begin{macro}{\DTLvarianceforkeys}
+% \begin{macrocode}
+\newcommand*{\DTLvarianceforkeys}[4][\boolean{true}\and
+\DTLisnumerical{\DTLthisval}]{%
+\DTLmeanforkeys[#1]{#2}{#3}{\dtl@mean}%
+\def#4{0}%
+\@for\@dtl@dbname:=#2\do{%
+ \DTLifdbexists{\@dtl@dbname}{%
+ \expandafter
+ \let\expandafter\@dtl@db\csname dtldb@\@dtl@dbname\endcsname
+ \@for\@dtl@currentrow:=\@dtl@db\do{%
+ \dtl@gathervalues{\@dtl@dbname}{\@dtl@currentrow}%
+ \@for\@dtl@key:=#3\do{%
+ \protected@edef\DTLthisval{%
+ \csname @dtl@key@\@dtl@key\endcsname}%
+ \ifthenelse{#1}{%
+ \DTLsub{\dtl@diff}{\DTLthisval}{\dtl@mean}%
+ \DTLmul{\dtl@diff}{\dtl@diff}{\dtl@diff}%
+ \DTLadd{#4}{#4}{\dtl@diff}%
+ }{}%
+ }}%
+ }{\PackageError{datatool}{Database `\@dtl@dbname' doesn't exist}{}%
+ }%
+}%
+\ifnum\dtl@n=0\relax
+ \PackageError{datatool}{Can't compute variance, no data!}{}%
+\else
+ \DTLdiv{#4}{#4}{\dtl@n}%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{definition}
+%\cs{DTLsdforkeys}\oarg{condition}\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 optional argument \meta{condition} is the same as that
+% for \cs{DTLforeach}.
+%\begin{macro}{\DTLsdforkeys}
+% \begin{macrocode}
+\newcommand*{\DTLsdforkeys}[4][\boolean{true}\and
+\DTLisnumerical{\DTLthisval}]{%
+\DTLvarianceforkeys[#1]{#2}{#3}{#4}%
+\DTLsqrt{#4}{#4}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{definition}
+%\cs{DTLminforkeys}\oarg{condition}\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 optional argument \meta{condition} is the same as that
+% for \cs{DTLforeach}.
+%\begin{macro}{\DTLminforkeys}
+% \begin{macrocode}
+\newcommand*{\DTLminforkeys}[4][\boolean{true}\and
+\DTLisnumerical{\DTLthisval}]{%
+\def#4{}%
+\@for\@dtl@dbname:=#2\do{%
+\DTLifdbexists{\@dtl@dbname}{%
+ \expandafter
+ \let\expandafter\@dtl@db\csname dtldb@\@dtl@dbname\endcsname%
+ \@for\@dtl@currentrow:=\@dtl@db\do{%
+ \dtl@gathervalues{\@dtl@dbname}{\@dtl@currentrow}%
+ \@for\@dtl@key:=#3\do{%
+ \protected@edef\DTLthisval{%
+ \csname @dtl@key@\@dtl@key\endcsname}%
+ \ifthenelse{#1}{%
+ \ifx#4\@empty
+ \let#4=\DTLthisval
+ \else
+ \DTLmin{#4}{#4}{\DTLthisval}%
+ \fi
+ }{}%
+}}%
+ }{\PackageError{datatool}{Database `\@dtl@dbname' doesn't exist}{}%
+ }%
+}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{definition}
+%\cs{DTLmaxforkeys}\oarg{condition}\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 optional argument \meta{condition} is the same as that
+% for \cs{DTLforeach}.
+%\begin{macro}{\DTLmaxforkeys}
+% \begin{macrocode}
+\newcommand*{\DTLmaxforkeys}[4][\boolean{true}\and
+\DTLisnumerical{\DTLthisval}]{%
+\def#4{}%
+\@for\@dtl@dbname:=#2\do{%
+\DTLifdbexists{\@dtl@dbname}{%
+ \expandafter
+ \let\expandafter\@dtl@db\csname dtldb@\@dtl@dbname\endcsname%
+ \@for\@dtl@currentrow:=\@dtl@db\do{%
+ \dtl@gathervalues{\@dtl@dbname}{\@dtl@currentrow}%
+ \@for\@dtl@key:=#3\do{%
+ \protected@edef\DTLthisval{%
+ \csname @dtl@key@\@dtl@key\endcsname}%
+ \ifthenelse{#1}{%
+ \ifx#4\@empty
+ \let#4=\DTLthisval
+ \else
+ \DTLmax{#4}{#4}{\DTLthisval}%
+ \fi
+ }{}%
+}}%
+ }{\PackageError{datatool}{Database `\@dtl@dbname' doesn't exist}{}%
+ }%
+}}
+% \end{macrocode}
+%\end{macro}
+%
+%\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{macro}{\DTLcomputebounds}
+% \begin{macrocode}
+\newcommand*{\DTLcomputebounds}[8][\boolean{true}]{%
+\let#5=\relax
+\let#6=\relax
+\let#7=\relax
+\let#8=\relax
+\@for\dtl@thisdb:=#2\do{%
+ \DTLforeach[#1]{\dtl@thisdb}{\DTLthisX=#3,\DTLthisY=#4}{%
+ \DTLconverttodecimal{\DTLthisX}{\dtl@decx}%
+ \DTLconverttodecimal{\DTLthisY}{\dtl@decy}%
+ \ifx#5\relax
+ \let#5=\dtl@decx
+ \let#6=\dtl@decy
+ \let#7=\dtl@decx
+ \let#8=\dtl@decy
+ \else
+ \FPmin{#5}{#5}{\dtl@decx}%
+ \FPmin{#6}{#6}{\dtl@decy}%
+ \FPmax{#7}{#7}{\dtl@decx}%
+ \FPmax{#8}{#8}{\dtl@decy}%
+ \fi
+ }%
+}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{definition}
+% \cs{DTLsort}\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".
+%\begin{macro}{\DTLsort}
+% \begin{macrocode}
+\newcommand*{\DTLsort}[2]{%
+\edef\@dtl@sortorder{#1}%
+\edef\@dtl@dbname{#2}%
+\protected@edef\@dtl@list{\csname dtldb@#2\endcsname}%
+\dtl@sortlist{\@dtl@list}{\@dtl@sortcriteria}%
+\expandafter\global\expandafter
+ \let\csname dtldb@#2\endcsname=\@dtl@list}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{definition}
+% \cs{@dtl@sortcriteria}\marg{a}\marg{b}
+%\end{definition}
+% Sort criteria. \cs{@dtl@currentrow} and
+% \cs{@dtl@sortorder} must be set before use.
+%\begin{macro}{\@dtl@sortcriteria}
+% \begin{macrocode}
+\newcommand{\@dtl@sortcriteria}[2]{%
+\@for\@dtl@level:=\@dtl@sortorder\do{%
+ \expandafter\@dtl@getsortdirection\@dtl@level=\relax%
+ \dtl@compare{\@dtl@key}{#1}{#2}%
+ \multiply\dtl@sortresult by \@dtl@sortdirection\relax
+ \ifnum\dtl@sortresult=0\relax
+ \else
+ \@endfortrue
+ \fi
+}%
+}
+% \end{macrocode}
+%\end{macro}
+% Get the direction from either \meta{key} or
+% \meta{key}=\meta{direction}. Sets \cs{@dtl@sortdirection} to
+% either -1 (ascending) or 1 (descending).
+%\begin{macro}{\@dtl@getsortdirection}
+% \begin{macrocode}
+\def\@dtl@getsortdirection#1=#2\relax{%
+\def\@dtl@key{#1}%
+\def\@dtl@sortdirection{#2}%
+\ifx\@dtl@sortdirection\@empty
+ \def\@dtl@sortdirection{-1}%
+\else
+ \@dtl@get@sortdirection#2%
+ \DTLifstringeq{\@dtl@sortdirection}{ascending}{%
+ \def\@dtl@sortdirection{-1}}{%
+ \DTLifstringeq{\@dtl@sortdirection}{descending}{%
+ \def\@dtl@sortdirection{1}}{%
+ \PackageError{datatool}{Invalid sort direction
+ `\@dtl@sortdirection'}{%
+ The sort direction can only be one of `ascending' or
+ `descending'}\def\@dtl@sortdirection{-1}}}%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+% Get direction
+%\begin{macro}{\@dtl@get@sortdirection}
+% \begin{macrocode}
+\def\@dtl@get@sortdirection#1={\def\@dtl@sortdirection{#1}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{definition}
+%\cs{dtl@compare}\marg{key}\marg{a}\marg{b}
+%\end{definition}
+% Compare \meta{a} and \meta{b} according to \meta{key} of
+% database given by \cs{@dtl@dbname}. Sets \cs{dtl@sortresult}.
+%\begin{macro}{\dtl@compare}
+% \begin{macrocode}
+\newcommand{\dtl@compare}[3]{%
+\protected@edef\dtl@arga{#2}\protected@edef\dtl@argb{#3}%
+\dtl@gathervalues{\@dtl@dbname}{\dtl@arga}%
+\protected@edef\@dtl@a{\csname @dtl@key@#1\endcsname}%
+\dtl@gathervalues{\@dtl@dbname}{\dtl@argb}%
+\protected@edef\@dtl@b{\csname @dtl@key@#1\endcsname}%
+\expandafter\@dtl@datatype\expandafter=
+ \csname @dtl@idtype@\@dtl@dbname @#1\endcsname\relax
+\ifnum\@dtl@datatype=0\relax
+ \edef\@dtl@result{\noexpand\compare{\@dtl@a}{\@dtl@b}}%
+ \expandafter\dtl@sortresult\expandafter=\@dtl@result\relax
+\else
+ \DTLifnumlt{\@dtl@a}{\@dtl@b}{\dtl@sortresult=-1\relax}{%
+ \DTLifnumgt{\@dtl@a}{\@dtl@b}{\dtl@sortresult=1\relax}{%
+ \dtl@sortresult=0\relax}}%
+\fi
+\dtl@message{`\@dtl@a' <=> `\@dtl@b' = \number\dtl@sortresult}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\subsection{General List Utilities}
+%
+%\begin{definition}
+% \cs{dtl@choplast}\marg{list}\marg{rest}\marg{last}
+%\end{definition}
+% Chop 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{macro}{\dtl@choplast}
+% \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{%
+\ifx#3\@empty
+% \end{macrocode}
+% First iteration, don't set \meta{rest}.
+% \begin{macrocode}
+\else
+ \ifx#2\@empty
+% \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@}}%
+ \else
+% \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@}}%
+ \fi
+\fi
+% \end{macrocode}
+% Now set \meta{last} to current element.
+% \begin{macrocode}
+\let#3=\@dtl@element%
+}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{definition}
+% \cs{dtl@chopfirst}\marg{list}\marg{first}\marg{rest}
+%\end{definition}
+% Chop 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{macro}{\dtl@chopfirst}
+% \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}
+%
+%\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{a} less than \meta{b}), 0 (\meta{a} is
+% equal to \meta{b}) or 1 (\meta{a} is greater than \meta{b}.)
+%\begin{macro}{\dtl@sortlist}
+% \begin{macrocode}
+\newcommand{\dtl@sortlist}[2]{%
+\def\@dtl@sortedlist{}%
+\@for\@dtl@currentrow:=#1\do{%
+\dtl@insertinto{\@dtl@currentrow}{\@dtl@sortedlist}{#2}%
+\@endforfalse}%
+\let#1=\@dtl@sortedlist
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\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{macro}{\dtl@insertinto}
+% \begin{macrocode}
+\newtoks\@dtl@toks
+\newcommand{\dtl@insertinto}[3]{%
+\def\@dtl@newsortedlist{}%
+\@dtl@insertdonefalse
+\@for\dtl@srtelement:=#2\do{%
+\expandafter\toks@\expandafter{\@dtl@newsortedlist}%
+\if@dtl@insertdone
+ \protected@edef\@dtl@newstuff{{\dtl@srtelement}}%
+\else
+ \expandafter#3\expandafter{\dtl@srtelement}{#1}%
+ \ifnum\dtl@sortresult<0\relax
+ \protected@edef\@dtl@newstuff{{#1},{\dtl@srtelement}}%
+ \@dtl@insertdonetrue
+ \else
+ \protected@edef\@dtl@newstuff{{\dtl@srtelement}}%
+ \fi
+\fi
+\ifx\@dtl@newsortedlist\@empty
+ \protected@edef\@dtl@newsortedlist{\@dtl@newstuff}%
+\else
+ \expandafter\toks@\expandafter{\@dtl@newsortedlist}%
+ \protected@edef\@dtl@newsortedlist{\the\toks@,\@dtl@newstuff}%
+\fi
+\@endforfalse
+}%
+ \ifx\@dtl@newsortedlist\@empty
+ \protected@edef\@dtl@newsortedlist{{#1}}%
+ \else
+ \if@dtl@insertdone
+ \else
+ \expandafter\toks@\expandafter{\@dtl@newsortedlist}%
+ \protected@edef\@dtl@newsortedlist{\the\toks@,{#1}}%
+ \fi
+ \fi
+\global\let#2=\@dtl@newsortedlist
+}
+% \end{macrocode}
+%\end{macro}
+% Define conditional to indicate whether the new entry has
+% been inserted into the sorted list.
+%\begin{macro}{\if@dtl@insertdone}
+% \begin{macrocode}
+\newif\if@dtl@insertdone
+% \end{macrocode}
+%\end{macro}
+% Define \cs{dtl@sortresult} to be set by comparision macro.
+%\begin{macro}{\dtl@sortresult}
+% \begin{macrocode}
+\newcount\dtl@sortresult
+% \end{macrocode}
+%\end{macro}
+%
+% \subsection{Floating Point Arithmetic}
+% The commands defined in this section all use the equivalent
+% commands provided by the \sty{fp} package, but first convert
+% the decimal number into the required format.
+%
+%\begin{definition}
+% \cs{DTLadd}\marg{cmd}\marg{num1}\marg{num2}
+%\end{definition}
+% Sets \meta{cmd} = \meta{num1} + \meta{num2}
+%\begin{macro}{\DTLadd}
+% \begin{macrocode}
+\newcommand*{\DTLadd}[3]{%
+\DTLconverttodecimal{#2}{\@dtl@numi}%
+\DTLconverttodecimal{#3}{\@dtl@numii}%
+\FPadd{\@dtl@tmp}{\@dtl@numi}{\@dtl@numii}%
+\ifx\@dtl@replaced\@empty
+ \DTLdecimaltolocale{\@dtl@tmp}{#1}%
+\else
+ \DTLdecimaltocurrency{\@dtl@tmp}{#1}%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+% Global version
+%\begin{macro}{\DTLgadd}
+% \begin{macrocode}
+\newcommand*{\DTLgadd}[3]{%
+\DTLadd{\@dtl@tmpii}{#2}{#3}%
+\global\let#1=\@dtl@tmpii
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\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.
+%\begin{macro}{\DTLaddall}
+% \begin{macrocode}
+\newcommand*{\DTLaddall}[2]{%
+\def\@dtl@sum{0}%
+\@for\dtl@thisval:=#2\do{%
+ \DTLconverttodecimal{\dtl@thisval}{\@dtl@num}%
+ \FPadd{\@dtl@sum}{\@dtl@sum}{\@dtl@num}%
+}
+\ifx\@dtl@replaced\@empty
+ \DTLdecimaltolocale{\@dtl@sum}{#1}%
+\else
+ \DTLdecimaltocurrency{\@dtl@sum}{#1}%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{definition}
+%\cs{DTLgaddall}\marg{cmd}\marg{num list}
+%\end{definition}
+% Global version
+%\begin{macro}{\DTLgaddall}
+% \begin{macrocode}
+\newcommand*{\DTLgaddall}[2]{%
+\DTLaddall{\@dtl@tmpi}{#2}%
+\global\let#1=\@dtl@tmpi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{definition}
+% \cs{DTLsub}\marg{cmd}\marg{num1}\marg{num2}
+%\end{definition}
+% Sets \meta{cmd} = \meta{num1} - \meta{num2}
+%\begin{macro}{\DTLsub}
+% \begin{macrocode}
+\newcommand*{\DTLsub}[3]{%
+\DTLconverttodecimal{#2}{\@dtl@numi}%
+\DTLconverttodecimal{#3}{\@dtl@numii}%
+\FPsub{\@dtl@tmp}{\@dtl@numi}{\@dtl@numii}%
+\ifx\@dtl@replaced\@empty
+ \DTLdecimaltolocale{\@dtl@tmp}{#1}%
+\else
+ \DTLdecimaltocurrency{\@dtl@tmp}{#1}%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+% Global version
+%\begin{macro}{\DTLgsub}
+% \begin{macrocode}
+\newcommand*{\DTLgsub}[3]{%
+\DTLsub{\@dtl@tmpii}{#2}{#3}%
+\global\let#1=\@dtl@tmpii
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{definition}
+% \cs{DTLmul}\marg{cmd}\marg{num1}\marg{num2}
+%\end{definition}
+% Sets \meta{cmd} = \meta{num1} * \meta{num2}
+%\begin{macro}{\DTLmul}
+% \begin{macrocode}
+\newcommand*{\DTLmul}[3]{%
+\let\@dtl@thisreplaced=\@empty
+\DTLconverttodecimal{#2}{\@dtl@numi}%
+\ifx\@dtl@replaced\@empty
+\else
+ \let\@dtl@thisreplaced=\@dtl@replaced
+\fi
+\DTLconverttodecimal{#3}{\@dtl@numii}%
+\ifx\@dtl@replaced\@empty
+\else
+ \let\@dtl@thisreplaced=\@dtl@replaced
+\fi
+\FPmul{\@dtl@tmp}{\@dtl@numi}{\@dtl@numii}%
+\ifx\@dtl@thisreplaced\@empty
+ \DTLdecimaltolocale{\@dtl@tmp}{#1}%
+\else
+ \DTLdecimaltocurrency{\@dtl@tmp}{#1}%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+% Global version
+%\begin{macro}{\DTLgmul}
+% \begin{macrocode}
+\newcommand*{\DTLgmul}[3]{%
+\DTLmul{\@dtl@tmpii}{#2}{#3}%
+\global\let#1=\@dtl@tmpii
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{definition}
+% \cs{DTLdiv}\marg{cmd}\marg{num1}\marg{num2}
+%\end{definition}
+% Sets \meta{cmd} = \meta{num1} / \meta{num2}
+%\begin{macro}{\DTLdiv}
+% \begin{macrocode}
+\newcommand*{\DTLdiv}[3]{%
+\let\@dtl@thisreplaced=\@empty
+\DTLconverttodecimal{#2}{\@dtl@numi}%
+\ifx\@dtl@replaced\@empty
+\else
+ \let\@dtl@thisreplaced=\@dtl@replaced
+\fi
+\DTLconverttodecimal{#3}{\@dtl@numii}%
+\FPdiv{\@dtl@tmp}{\@dtl@numi}{\@dtl@numii}%
+\ifx\@dtl@thisreplaced\@empty
+ \DTLdecimaltolocale{\@dtl@tmp}{#1}%
+\else
+ \ifx\@dtl@thisreplaced\@dtl@replaced
+ \DTLdecimaltolocale{\@dtl@tmp}{#1}%
+ \else
+ \DTLdecimaltocurrency{\@dtl@tmp}{#1}%
+ \fi
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+% Global version
+%\begin{macro}{\DTLgdiv}
+% \begin{macrocode}
+\newcommand*{\DTLgdiv}[3]{%
+\DTLdiv{\@dtl@tmpii}{#2}{#3}%
+\global\let#1=\@dtl@tmpii
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{definition}
+% \cs{DTLabs}\marg{cmd}\marg{num}
+%\end{definition}
+% Sets \meta{cmd} = abs(\meta{num})
+%\begin{macro}{\DTLabs}
+% \begin{macrocode}
+\newcommand*{\DTLabs}[2]{%
+\DTLconverttodecimal{#2}{\@dtl@numi}%
+\FPabs{\@dtl@tmp}{\@dtl@numi}%
+\ifx\@dtl@replaced\@empty
+ \DTLdecimaltolocale{\@dtl@tmp}{#1}%
+\else
+ \DTLdecimaltocurrency{\@dtl@tmp}{#1}%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+% Global version
+%\begin{macro}{\DTLgabs}
+% \begin{macrocode}
+\newcommand*{\DTLgabs}[2]{%
+\DTLabs{\@dtl@tmpii}{#2}%
+\global\let#1=\@dtl@tmpii
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{definition}
+% \cs{DTLneg}\marg{cmd}\marg{num}
+%\end{definition}
+% Sets \meta{cmd} = -\meta{num}
+%\begin{macro}{\DTLneg}
+% \begin{macrocode}
+\newcommand*{\DTLneg}[2]{%
+\DTLconverttodecimal{#2}{\@dtl@numi}%
+\FPneg{\@dtl@tmp}{\@dtl@numi}%
+\ifx\@dtl@replaced\@empty
+ \DTLdecimaltolocale{\@dtl@tmp}{#1}%
+\else
+ \DTLdecimaltocurrency{\@dtl@tmp}{#1}%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+% Global version
+%\begin{macro}{\DTLgneg}
+% \begin{macrocode}
+\newcommand*{\DTLgneg}[2]{%
+\DTLneg{\@dtl@tmpii}{#2}%
+\global\let#1=\@dtl@tmpii
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{definition}
+% \cs{DTLsqrt}\marg{cmd}\marg{num}
+%\end{definition}
+% Sets \meta{cmd} = sqrt(\meta{num})
+%\begin{macro}{\DTLsqrt}
+% \begin{macrocode}
+\newcommand*{\DTLsqrt}[2]{%
+\DTLconverttodecimal{#2}{\@dtl@numi}%
+\FProot{\@dtl@tmpi}{\@dtl@numi}{2}%
+\ifx\@dtl@replaced\@empty
+ \DTLdecimaltolocale{\@dtl@tmpi}{#1}%
+\else
+ \DTLdecimaltocurrency{\@dtl@tmpi}{#1}%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+% Global version
+%\begin{macro}{\DTLgsqrt}
+% \begin{macrocode}
+\newcommand*{\DTLgsqrt}[2]{%
+\DTLsqrt{\@dtl@tmpii}{#2}%
+\global\let#1=\@dtl@tmpii
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{definition}
+% \cs{DTLmin}\marg{cmd}\marg{num1}\marg{num2}
+%\end{definition}
+% Sets \meta{cmd} = min(\meta{num1}, \meta{num2})
+%\begin{macro}{\DTLmin}
+% \begin{macrocode}
+\newcommand*{\DTLmin}[3]{%
+\DTLconverttodecimal{#2}{\@dtl@numi}%
+\DTLconverttodecimal{#3}{\@dtl@numii}%
+\FPiflt{\@dtl@numi}{\@dtl@numii}%
+ \dtl@ifsingle{#2}{%
+ \let#1=#2}{%
+ \def#1{#2}}%
+\else
+ \dtl@ifsingle{#3}{%
+ \let#1=#3}{%
+ \def#1{#3}}%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+% Global version
+%\begin{macro}{\DTLgmin}
+% \begin{macrocode}
+\newcommand*{\DTLgmin}[3]{%
+\DTLmin{\@dtl@tmpii}{#2}{#3}%
+\global\let#1=\@dtl@tmpii
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\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.
+%\begin{macro}{\DTLminall}
+% \begin{macrocode}
+\newcommand*{\DTLminall}[2]{%
+\let\@dtl@min=\@empty
+\@for\dtl@thisval:=#2\do{%
+ \DTLconverttodecimal{\dtl@thisval}{\@dtl@num}%
+ \ifx\@dtl@min\@empty
+ \let\@dtl@min=\@dtl@num
+ \else
+ \FPmin{\@dtl@min}{\@dtl@min}{\@dtl@num}%
+ \fi
+}
+\ifx\@dtl@replaced\@empty
+ \DTLdecimaltolocale{\@dtl@min}{#1}%
+\else
+ \DTLdecimaltocurrency{\@dtl@min}{#1}%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{definition}
+%\cs{DTLgminall}\marg{cmd}\marg{num list}
+%\end{definition}
+% Global version
+%\begin{macro}{\DTLgminall}
+% \begin{macrocode}
+\newcommand*{\DTLgminall}[2]{%
+\DTLminall{\@dtl@tmpi}{#2}%
+\global\let#1=\@dtl@tmpi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{definition}
+% \cs{DTLmax}\marg{cmd}\marg{num1}\marg{num2}
+%\end{definition}
+% Sets \meta{cmd} = max(\meta{num1}, \meta{num2})
+%\begin{macro}{\DTLmax}
+% \begin{macrocode}
+\newcommand*{\DTLmax}[3]{%
+\DTLconverttodecimal{#2}{\@dtl@numi}%
+\DTLconverttodecimal{#3}{\@dtl@numii}%
+\FPmax{\@dtl@tmp}{\@dtl@numi}{\@dtl@numii}%
+\FPifgt{\@dtl@numi}{\@dtl@numii}%
+ \dtl@ifsingle{#2}{%
+ \let#1=#2}{%
+ \def#1{#2}}%
+\else
+ \dtl@ifsingle{#3}{%
+ \let#1=#3}{%
+ \def#1{#3}}%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+% Global version
+%\begin{macro}{\DTLgmax}
+% \begin{macrocode}
+\newcommand*{\DTLgmax}[3]{%
+\DTLmax{\@dtl@tmpii}{#2}{#3}%
+\global\let#1=\@dtl@tmpii
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\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.
+%\begin{macro}{\DTLmaxall}
+% \begin{macrocode}
+\newcommand*{\DTLmaxall}[2]{%
+\let\@dtl@max=\@empty
+\@for\dtl@thisval:=#2\do{%
+ \DTLconverttodecimal{\dtl@thisval}{\@dtl@num}%
+ \ifx\@dtl@max\@empty
+ \let\@dtl@max\@dtl@num
+ \else
+ \FPmax{\@dtl@max}{\@dtl@max}{\@dtl@num}%
+ \fi
+}
+\ifx\@dtl@replaced\@empty
+ \DTLdecimaltolocale{\@dtl@max}{#1}%
+\else
+ \DTLdecimaltocurrency{\@dtl@max}{#1}%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{definition}
+%\cs{DTLgmaxall}\marg{cmd}\marg{num list}
+%\end{definition}
+% Global version
+%\begin{macro}{\DTLgmaxall}
+% \begin{macrocode}
+\newcommand*{\DTLgmaxall}[2]{%
+\DTLmaxall{\@dtl@tmpi}{#2}%
+\global\let#1=\@dtl@tmpi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\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.
+%\begin{macro}{\DTLmeanforall}
+% \begin{macrocode}
+\newcommand*{\DTLmeanforall}[2]{%
+\def\@dtl@mean{0}%
+\def\@dtl@n{0}%
+\@for\dtl@thisval:=#2\do{%
+ \DTLconverttodecimal{\dtl@thisval}{\@dtl@num}%
+ \FPadd{\@dtl@mean}{\@dtl@mean}{\@dtl@num}%
+ \FPadd{\@dtl@n}{\@dtl@n}{1}%
+}
+\FPdiv{\@dtl@mean}{\@dtl@mean}{\@dtl@n}%
+\ifx\@dtl@replaced\@empty
+ \DTLdecimaltolocale{\@dtl@mean}{#1}%
+\else
+ \DTLdecimaltocurrency{\@dtl@mean}{#1}%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{definition}
+%\cs{DTLgmeanforall}\marg{cmd}\marg{num list}
+%\end{definition}
+% Global version
+%\begin{macro}{\DTLgmeanforall}
+% \begin{macrocode}
+\newcommand*{\DTLgmeanforall}[2]{%
+\DTLmeanforall{\@dtl@tmpi}{#2}%
+\global\let#1=\@dtl@tmpi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\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.
+%\begin{macro}{\DTLvarianceforall}
+% \begin{macrocode}
+\newcommand*{\DTLvarianceforall}[2]{%
+\def\@dtl@mean{0}%
+\def\@dtl@n{0}%
+\let\@dtl@decvals=\@empty
+\@for\dtl@thisval:=#2\do{%
+ \DTLconverttodecimal{\dtl@thisval}{\@dtl@num}%
+ \ifx\@dtl@decvals\@empty
+ \let\@dtl@decvals=\@dtl@num
+ \else
+ \edef\@dtl@decvals{\@dtl@decvals,\@dtl@num}%
+ \fi
+ \FPadd{\@dtl@mean}{\@dtl@mean}{\@dtl@num}%
+ \FPadd{\@dtl@n}{\@dtl@n}{1}%
+}
+\FPdiv{\@dtl@mean}{\@dtl@mean}{\@dtl@n}%
+\def\@dtl@var{0}%
+\@for\dtl@num:=\@dtl@decvals\do{%
+ \FPsub{\@dtl@diff}{\@dtl@var}{\@dtl@mean}%
+ \FPmul{\@dtl@diff}{\@dtl@diff}{\@dtl@diff}%
+ \FPadd{\@dtl@var}{\@dtl@var}{\@dtl@diff}%
+}
+\FPdiv{\@dtl@var}{\@dtl@var}{\@dtl@n}%
+\ifx\@dtl@replaced\@empty
+ \DTLdecimaltolocale{\@dtl@var}{#1}%
+\else
+ \DTLdecimaltocurrency{\@dtl@var}{#1}%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{definition}
+%\cs{DTLgvarianceforall}\marg{cmd}\marg{num list}
+%\end{definition}
+% Global version
+%\begin{macro}{\DTLgvarianceforall}
+% \begin{macrocode}
+\newcommand*{\DTLgvarianceforall}[2]{%
+\DTLvarianceforall{\@dtl@tmpi}{#2}%
+\global\let#1=\@dtl@tmpi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\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.
+%\begin{macro}{\DTLsdforall}
+% \begin{macrocode}
+\newcommand*{\DTLsdforall}[2]{%
+\def\@dtl@mean{0}%
+\def\@dtl@n{0}%
+\let\@dtl@decvals=\@empty
+\@for\dtl@thisval:=#2\do{%
+ \DTLconverttodecimal{\dtl@thisval}{\@dtl@num}%
+ \ifx\@dtl@decvals\@empty
+ \let\@dtl@decvals=\@dtl@num
+ \else
+ \edef\@dtl@decvals{\@dtl@decvals,\@dtl@num}%
+ \fi
+ \FPadd{\@dtl@mean}{\@dtl@mean}{\@dtl@num}%
+ \FPadd{\@dtl@n}{\@dtl@n}{1}%
+}
+\FPdiv{\@dtl@mean}{\@dtl@mean}{\@dtl@n}%
+\def\@dtl@sd{0}%
+\@for\dtl@num:=\@dtl@decvals\do{%
+ \FPsub{\@dtl@diff}{\@dtl@num}{\@dtl@mean}%
+ \FPmul{\@dtl@diff}{\@dtl@diff}{\@dtl@diff}%
+ \FPadd{\@dtl@sd}{\@dtl@sd}{\@dtl@diff}%
+}
+\FPdiv{\@dtl@sd}{\@dtl@sd}{\@dtl@n}%
+\FProot{\@dtl@sd}{\@dtl@sd}{2}%
+\ifx\@dtl@replaced\@empty
+ \DTLdecimaltolocale{\@dtl@sd}{#1}%
+\else
+ \DTLdecimaltocurrency{\@dtl@sd}{#1}%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{definition}
+%\cs{DTLgsdforall}\marg{cmd}\marg{num list}
+%\end{definition}
+% Global version
+%\begin{macro}{\DTLgsdforall}
+% \begin{macrocode}
+\newcommand*{\DTLgsdforall}[2]{%
+\DTLsdforall{\@dtl@tmpi}{#2}%
+\global\let#1=\@dtl@tmpi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\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{macro}{\DTLround}
+% \begin{macrocode}
+\newcommand*{\DTLround}[3]{%
+\DTLconverttodecimal{#2}{\@dtl@numi}%
+\FPround{\@dtl@tmp}{\@dtl@numi}{#3}%
+\ifx\@dtl@replaced\@empty
+ \DTLdecimaltolocale{\@dtl@tmp}{#1}%
+\else
+ \DTLdecimaltocurrency{\@dtl@tmp}{#1}%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+% Global version
+%\begin{macro}{\DTLground}
+% \begin{macrocode}
+\newcommand*{\DTLground}[3]{%
+\DTLround{\@dtl@tmpii}{#2}{#3}%
+\global\let#1=\@dtl@tmpii
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\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{macro}{\DTLtrunc}
+% \begin{macrocode}
+\newcommand*{\DTLtrunc}[3]{%
+\DTLconverttodecimal{#2}{\@dtl@numi}%
+\FPtrunc{\@dtl@tmp}{\@dtl@numi}{#3}%
+\ifx\@dtl@replaced\@empty
+ \DTLdecimaltolocale{\@dtl@tmp}{#1}%
+\else
+ \DTLdecimaltocurrency{\@dtl@tmp}{#1}%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+% Global version
+%\begin{macro}{\DTLgtrunc}
+% \begin{macrocode}
+\newcommand*{\DTLgtrunc}[3]{%
+\DTLtrunc{\@dtl@tmpii}{#2}{#3}%
+\global\let#1=\@dtl@tmpii
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{definition}
+% \cs{DTLclip}\marg{cmd}\marg{num}
+%\end{definition}
+% Sets \meta{cmd} to \meta{num} with all unnecessary 0's removed.
+%\begin{macro}{\DTLclip}
+% \begin{macrocode}
+\newcommand*{\DTLclip}[2]{%
+\DTLconverttodecimal{#2}{\@dtl@numi}%
+\FPclip{\@dtl@tmp}{\@dtl@numi}%
+\ifx\@dtl@replaced\@empty
+ \DTLdecimaltolocale{\@dtl@tmp}{#1}%
+\else
+ \DTLdecimaltocurrency{\@dtl@tmp}{#1}%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+% Global version
+%\begin{macro}{\DTLgclip}
+% \begin{macrocode}
+\newcommand*{\DTLgclip}[3]{%
+\DTLclip{\@dtl@tmpii}{#2}%
+\global\let#1=\@dtl@tmpii
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\subsection{String Macros}
+%\begin{definition}
+%\cs{DTLinitials}\marg{string}
+%\end{definition}
+% Convert a string into initials.
+%\begin{macro}{\DTLinitials}
+% \begin{macrocode}
+\newcommand*{\DTLinitials}[1]{%
+\def\dtl@initialscmd{}%
+\protected@edef\dtl@string{#1}%
+\expandafter\dtl@initials\dtl@string{} \@nil
+\dtl@initialscmd}
+% \end{macrocode}
+%\end{macro}
+%\begin{definition}
+%\cs{DTLstoreinitials}\marg{string}\marg{cmd}
+%\end{definition}
+% Convert a string into initials and store in \meta{cmd}
+%\begin{macro}{\DTLstoreinitials}
+% \begin{macrocode}
+\newcommand*{\DTLstoreinitials}[2]{%
+\def\dtl@initialscmd{}%
+\protected@edef\dtl@string{#1}%
+\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{%
+\def\dtl@tmp{#3}%
+\dtl@initialshyphen#2-{}\dtl@endhyp
+\expandafter\@dtl@toks\expandafter{\dtl@initialscmd}%
+\toks@{#1}%
+\ifx\dtl@inithyphen\@empty
+\else
+ \edef\dtl@initialscmd{\the\@dtl@toks\the\toks@}%
+ \expandafter\@dtl@toks\expandafter{\dtl@initialscmd}%
+ \expandafter\toks@\expandafter{\dtl@inithyphen}%
+\fi
+\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}%
+\ifx\dtl@inithyphen\@empty
+\else
+ \edef\dtl@inithyphen{\DTLafterinitialbeforehyphen-#2}%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+% Define what to do after the final initial:
+%\begin{macro}{\DTLafterinitials}
+% \begin{macrocode}
+\newcommand*{\DTLafterinitials}{.}
+% \end{macrocode}
+%\end{macro}
+% Define what to do between initials:
+%\begin{macro}{\DTLbetweeninitials}
+% \begin{macrocode}
+\newcommand*{\DTLbetweeninitials}{.}
+% \end{macrocode}
+%\end{macro}
+% Define what to do before a hyphen:
+%\begin{macro}{\DTLafterinitialbeforehyphen}
+% \begin{macrocode}
+\newcommand*{\DTLafterinitialbeforehyphen}{.}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLifAllUpperCase}
+% \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@testifcasenoop
+ \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@testifcasenoop
+ \fi
+ \fi
+}}}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtl@testifcasenoop}
+% \begin{macrocode}
+\def\dtl@testifcasenoop#1\@nil{}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLifAllLowerCase}
+% \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@testifcasenoop
+ \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@testifcasenoop
+ \fi
+ \fi
+}}}
+% \end{macrocode}
+%\end{macro}
+%
+%\subsection{Saving a database to an external file}
+%
+%\begin{macro}{\@dtl@write}
+% \begin{macrocode}
+\newwrite\@dtl@write
+% \end{macrocode}
+%\end{macro}
+%\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}.
+%\begin{macro}{\DTLsavedb}
+% \begin{macrocode}
+\newcommand*{\DTLsavedb}[2]{%
+\DTLifdbexists{#1}{%
+\openout\@dtl@write=#2%
+\edef\@dtl@keys{\csname dtlkeys@#1\endcsname}%
+\def\@dtl@header{}%
+\@for\@dtl@key:=\@dtl@keys\do{%
+\expandafter\@dtl@toks\expandafter{\@dtl@header}%
+\ifx\@dtl@header\@empty
+ \IfSubStringInString{\@dtl@separator}{\@dtl@key}{%
+ \protected@edef\@dtl@header{%
+ \@dtl@delimiter\@dtl@key\@dtl@delimiter}%
+ }{%
+ \protected@edef\@dtl@header{\@dtl@key}%
+ }%
+\else
+ \IfSubStringInString{\@dtl@separator}{\@dtl@key}{%
+ \protected@edef\@dtl@header{\the\@dtl@toks\@dtl@separator
+ \@dtl@delimiter\@dtl@key\@dtl@delimiter}%
+ }{%
+ \protected@edef\@dtl@header{\the\@dtl@toks\@dtl@separator
+ \@dtl@key}%
+ }%
+\fi
+}%
+\protected@write\@dtl@write{}{\@dtl@header}%
+\expandafter\let\expandafter\@dtl@db\csname dtldb@#1\endcsname%
+\@for\@dtl@currentrow:=\@dtl@db\do{%
+\dtl@gathervalues{#1}{\@dtl@currentrow}%
+\def\@dtl@outputrow{}%
+\@for\@dtl@key:=\@dtl@keys\do{%
+\protected@edef\@dtl@element{\csname @dtl@key@\@dtl@key\endcsname}%
+\expandafter\@dtl@toks\expandafter{\@dtl@outputrow}%
+\ifx\@dtl@outputrow\@empty
+ \IfSubStringInString{\@dtl@separator}{\@dtl@element}{%
+ \protected@edef\@dtl@outputrow{%
+ \@dtl@delimiter\@dtl@element\@dtl@delimiter}%
+ }{%
+ \protected@edef\@dtl@outputrow{\@dtl@element}%
+ }%
+\else
+ \IfSubStringInString{\@dtl@separator}{\@dtl@element}{%
+ \protected@edef\@dtl@outputrow{\the\@dtl@toks\@dtl@separator
+ \@dtl@delimiter\@dtl@element\@dtl@delimiter}%
+ }{%
+ \protected@edef\@dtl@outputrow{\the\@dtl@toks\@dtl@separator
+ \@dtl@element}%
+ }%
+\fi
+}%
+\protected@write\@dtl@write{}{\@dtl@outputrow}%
+}%
+\closeout\@dtl@write
+}{%
+\PackageError{datatool}{Database `#1' doesn't exist}{}%
+}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{definition}
+% \cs{DTLsavetexdb}\marg{db name}\marg{filename}
+%\end{definition}
+% Save a database as a \LaTeX\ file.
+%\begin{macro}{\DTLsavetexdb}
+% \begin{macrocode}
+\newcommand*{\DTLsavetexdb}[2]{%
+\DTLifdbexists{#1}{%
+\openout\@dtl@write=#2%
+\edef\@dtl@keys{\csname dtlkeys@#1\endcsname}%
+\protected@write\@dtl@write{}{\string\DTLnewdb{#1}}%
+\expandafter\let\expandafter\@dtl@db\csname dtldb@#1\endcsname%
+\@for\@dtl@currentrow:=\@dtl@db\do{%
+\dtl@gathervalues{#1}{\@dtl@currentrow}%
+\protected@write\@dtl@write{}{\string\DTLnewrow{#1}}%
+\@for\@dtl@key:=\@dtl@keys\do{%
+\protected@edef\@dtl@element{\csname @dtl@key@\@dtl@key\endcsname}%
+\protected@write\@dtl@write{}{\string\DTLnewdbentry
+ {#1}{\@dtl@key}{\@dtl@element}}%
+}%
+}%
+\closeout\@dtl@write
+}{%
+\PackageError{datatool}{Database `#1' doesn't exist}{}%
+}}
+% \end{macrocode}
+%\end{macro}
+%
+%\subsection{Loading a database from an external file}
+%
+%\begin{macro}{\@dtl@read}
+% \begin{macrocode}
+\newread\@dtl@read
+% \end{macrocode}
+%\end{macro}
+% Keep track of current column in data file
+%\begin{macro}{\dtl@entrycr}
+% \begin{macrocode}
+\newcount\dtl@entrycr
+% \end{macrocode}
+%\end{macro}
+%\begin{definition}
+% \cs{DTLloaddb}\marg{db name}\marg{filename}
+%\end{definition}
+% Create a new database called \meta{db name}, and load the data in
+% \meta{filename} into it. The separator and delimiter used in
+% the file must match \cs{@dtl@separator} and \cs{@dtl@delimiter}.
+%\begin{macro}{\DTLloaddb}
+% \begin{macrocode}
+\gdef\DTLloaddb#1#2{%
+\IfFileExists{#2}{%
+\begingroup
+\catcode`\"12\relax
+\openin\@dtl@read=#2%
+\dtl@message{Reading `#2'}%
+\DTLnewdb{#1}%
+\ifeof\@dtl@read
+\else
+ \loop
+ \@dtl@conditionfalse
+ \ifeof\@dtl@read
+ \else
+ \read\@dtl@read to \@dtl@line
+ \dtl@trim\@dtl@line
+ \if\@dtl@line\par
+ \@dtl@conditiontrue
+ \fi
+ \fi
+ \if@dtl@condition
+ \repeat
+ \ifeof\@dtl@read
+ \else
+ \protected@edef\@dtl@lin@{\@dtl@separator\@dtl@line\@dtl@separator}%
+ \@dtl@tmpcount=0\relax
+ \whiledo{\not\equal{\@dtl@lin@}{\@dtl@separator}}{%
+ \expandafter\@dtl@lopoff\@dtl@lin@\to\@dtl@lin@\@dtl@key
+ \advance\@dtl@tmpcount by 1\relax
+ \expandafter\@dtl@toks\expandafter{\@dtl@key}%
+ \expandafter
+ \edef\csname @dtl@inky@\romannumeral\@dtl@tmpcount\endcsname{%
+ \the\@dtl@toks}%
+ }%
+ \ifeof\@dtl@read
+ \else
+ \@dtl@conditiontrue
+ \loop
+ \read\@dtl@read to \@dtl@line
+ \dtl@trim\@dtl@line
+ \ifthenelse{\equal{\@dtl@line}{}}{}%
+ {%
+ \DTLnewrow{#1}%
+ \expandafter\@dtl@toks\expandafter{\@dtl@line}%
+ \edef\@dtl@lin@{\@dtl@separator\the\@dtl@toks
+ \@dtl@separator}%
+ \dtl@entrycr=0\relax
+ \whiledo{\not\equal{\@dtl@lin@}{\@dtl@separator}}{%
+ \expandafter\@dtl@lopoff\@dtl@lin@\to
+ \@dtl@lin@\@dtl@thisentry
+ \advance\dtl@entrycr by 1\relax
+ \edef\@dtl@thiskey{%
+ \csname @dtl@inky@\romannumeral\dtl@entrycr\endcsname}%
+ \DTLnewdbentry{#1}{\@dtl@thiskey}{\@dtl@thisentry}%
+ }%
+ }%
+ \ifeof\@dtl@read \@dtl@conditionfalse\fi
+ \if@dtl@condition
+ \repeat
+ \fi
+ \fi
+\fi
+\closein\@dtl@read
+\endgroup
+}{%
+\PackageError{datatool}{Can't load database `#1' (file `#2'
+doesn't exist)}{}%
+}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{definition}
+%\cs{dtl@trim}\marg{line}
+%\end{definition}
+% Trims the trailing space from \meta{line}.
+%\begin{macro}{\dtl@trim}
+% \begin{macrocode}
+\newcommand{\dtl@trim}[1]{%
+\def\@dtl@trmstr{}%
+\expandafter\@dtl@starttrim#1\@nil%
+\let#1=\@dtl@trmstr
+}
+% \end{macrocode}
+%\end{macro}
+% Start trimming
+%\begin{macro}{\@dtl@starttrim}
+% \begin{macrocode}
+\long\def\@dtl@starttrim#1#2{%
+\ifx\par#1%
+ \def\@dtl@dotrim{\@dtl@trim{} #2}%
+\else
+ \def\@dtl@dotrim{\@dtl@trim#1#2}%
+\fi
+\@dtl@dotrim%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@dtl@trim}
+% \begin{macrocode}
+\long\def\@dtl@trim#1 \@nil{\long\def\@dtl@trmstr{#1}}
+% \end{macrocode}
+%\end{macro}
+%
+% Load a raw database (substitutes "%" $\to$ "\%",
+% "$" $\to$ "\$", "&" $\to$ "\&", "#" $\to$ "\#",
+% "~" $\to$ "\textasciitilde", "_" $\to$ "\_"
+% and "^" $\to$ "\textasciicircum".)
+%\begin{macro}{\DTLloadrawdb}
+% \begin{macrocode}
+\gdef\DTLloadrawdb#1#2{%
+\IfFileExists{#2}{%
+\openin\@dtl@read=#2%
+\dtl@message{Reading `#2'}%
+\DTLnewdb{#1}%
+\ifeof\@dtl@read
+\else
+ \loop
+ \@dtl@conditionfalse
+ \ifeof\@dtl@read
+ \else
+ \@dtl@rawread\@dtl@read to\@dtl@line
+ \dtl@trim\@dtl@line
+ \if\@dtl@line\par
+ \@dtl@conditiontrue
+ \fi
+ \fi
+ \if@dtl@condition
+ \repeat
+ \ifeof\@dtl@read
+ \else
+ \dtl@domappings\@dtl@line
+ \protected@edef\@dtl@lin@{\@dtl@separator\@dtl@line\@dtl@separator}%
+ \@dtl@tmpcount=0\relax
+ \whiledo{\not\equal{\@dtl@lin@}{\@dtl@separator}}{%
+ \expandafter\@dtl@lopoff\@dtl@lin@\to\@dtl@lin@\@dtl@key
+ \advance\@dtl@tmpcount by 1\relax
+ \expandafter\@dtl@toks\expandafter{\@dtl@key}%
+ \expandafter
+ \edef\csname @dtl@inky@\romannumeral\@dtl@tmpcount\endcsname{%
+ \the\@dtl@toks}%
+ }%
+ \ifeof\@dtl@read
+ \else
+ \@dtl@conditiontrue
+ \loop
+ \@dtl@rawread\@dtl@read to\@dtl@line
+ \dtl@trim\@dtl@line
+ \ifthenelse{\equal{\@dtl@line}{}}{}%
+ {%
+ \DTLnewrow{#1}%
+ \dtl@domappings\@dtl@line
+ \expandafter\@dtl@toks\expandafter{\@dtl@line}%
+ \edef\@dtl@lin@{\@dtl@separator\the\@dtl@toks
+ \@dtl@separator}%
+ \dtl@entrycr=0\relax
+ \whiledo{\not\equal{\@dtl@lin@}{\@dtl@separator}}{%
+ \expandafter\@dtl@lopoff\@dtl@lin@\to
+ \@dtl@lin@\@dtl@thisentry
+ \advance\dtl@entrycr by 1\relax
+ \edef\@dtl@thiskey{%
+ \csname @dtl@inky@\romannumeral\dtl@entrycr\endcsname}%
+ \DTLnewdbentry{#1}{\@dtl@thiskey}{\@dtl@thisentry}%
+ }%
+ }%
+ \ifeof\@dtl@read \@dtl@conditionfalse\fi
+ \if@dtl@condition
+ \repeat
+ \fi
+ \fi
+\fi
+\closein\@dtl@read
+}{%
+\PackageError{datatool}{Can't load database `#1' (file `#2'
+doesn't exist)}{}%
+}}
+% \end{macrocode}
+%\end{macro}
+%
+%\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{macro}{\@dtl@rawread}
+% \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
+\read?1 to \tmp
+\xdef?2<\tmp>\relax
+>
+\endgroup
+% \end{macrocode}
+%\end{macro}
+% \cs{@dtl@activatebraces} resets braces for \cs{@dtl@rawread}
+%\begin{macro}{\@dtl@activatebraces}
+% \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{definition}
+%\cs{DTLrawmap}\marg{string}\marg{replacement}
+%\end{definition}
+% Additional mappings to perform when reading a raw data file
+%\begin{macro}{\DTLrawmap}
+% \begin{macrocode}
+\newcommand*{\DTLrawmap}[2]{%
+\expandafter\@dtl@toks\expandafter{\@dtl@rawmappings}%
+\ifx\@dtl@rawmappings\@empty
+ \def\@dtl@rawmappings{{#1}{#2}}%
+\else
+ \def\@dtl@tmp{{#1}{#2}}
+ \protected@edef\@dtl@rawmappings{\the\@dtl@toks,\@dtl@tmp}
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@rawmappings}
+% \begin{macrocode}
+\newcommand*{\@dtl@rawmappings}{}
+% \end{macrocode}
+%\end{macro}
+%\begin{definition}
+% \cs{dtl@domappings}\marg{cmd}
+%\end{definition}
+% Do all mappings in string given by \meta{cmd}.
+%\begin{macro}{\dtl@domappings}
+% \begin{macrocode}
+\newcommand*{\dtl@domappings}[1]{%
+\@for\@dtl@map:=\@dtl@rawmappings\do{%
+ \expandafter\DTLsubstitute\expandafter#1\@dtl@map
+}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{definition}
+%\cs{DTLsubstitute}\marg{cmd}\marg{original}\marg{replacement}
+%\end{definition}
+% Substitutes first occurence of \meta{original} with
+% \marg{replacement} within the string given by \meta{cmd}
+%\begin{macro}{\DTLsubstitute}
+% \begin{macrocode}
+\newcommand{\DTLsubstitute}[3]{%
+\def\dtl@splitstr##1#2##2\@nil{%
+\def\@dtl@beforepart{##1}%
+\def\@dtl@afterpart{##2}%
+\ifx\@dtl@afterpart\@empty
+ \let\@dtl@replaced=\@empty
+\else
+ \def\@dtl@replaced{#2}%
+ \dtl@split@str##2\@nil
+\fi
+}%
+\def\dtl@split@str##1#2\@nil{%
+\def\@dtl@afterpart{##1}}%
+\expandafter\dtl@splitstr#1#2\@nil
+\ifx\@dtl@replaced\@empty
+\else
+ \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}%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{definition}
+%\cs{DTLsubstituteall}\marg{cmd}\marg{original}\marg{replacement}
+%\end{definition}
+% Substitutes all occurences of \meta{original} with
+% \marg{replacement} within the string given by \meta{cmd}
+%\begin{macro}{\DTLsubstituteall}
+% \begin{macrocode}
+\newcommand{\DTLsubstituteall}[3]{%
+\def\dtl@splitstr##1#2##2\@nil{%
+\def\@dtl@beforepart{##1}\def\@dtl@afterpart{##2}}%
+\let\@dtl@replaced=\@empty
+\IfSubStringInString{#2}{#1}{%
+ \expandafter\dtl@splitstr#1\@nil
+ \expandafter\toks@\expandafter{#2}%
+ \edef\@dtl@replaced{\the\toks@}%
+ \def#1{}%
+ \@dtl@conditiontrue
+ \loop
+ \expandafter\@dtl@toks\expandafter{\@dtl@beforepart}%
+ \expandafter\toks@\expandafter{#1}%
+ \protected@edef#1{\the\toks@\the\@dtl@toks#3}%
+ \IfSubStringInString{#2}{\@dtl@afterpart}{%
+ \expandafter\dtl@splitstr\@dtl@afterpart\@nil
+ }{\@dtl@conditionfalse}%
+ \if@dtl@condition
+ \repeat
+ \expandafter\@dtl@toks\expandafter{\@dtl@afterpart}%
+ \expandafter\toks@\expandafter{#1}%
+ \edef#1{\the\toks@\the\@dtl@toks}%
+}{}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\subsection{Currencies}
+% \cs{@dtl@currencies} stores all known currencies.
+%\begin{macro}{\@dtl@currencies}
+% \begin{macrocode}
+\newcommand*{\@dtl@currencies}{\$,\pounds}
+% \end{macrocode}
+%\end{macro}
+%\begin{definition}
+% \cs{DTLaddcurrency}\marg{symbol}
+%\end{definition}
+% Adds \meta{symbol} to the list of known currencies
+%\begin{macro}{\DTLnewcurrencysymbol}
+% \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{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{macro}{\@dtl@standardize@currency}
+% \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
+ \ifx\@dtl@replaced\@empty
+ \else
+ \let\@dtl@org@currency=\@dtl@replaced
+ \@endfortrue
+ \fi
+}%
+\@endforfalse}
+% \end{macrocode}
+%\end{macro}
+%
+%\cs{@dtl@currency} is set by \cs{DTLlocaltodecimal} and
+%\cs{@dtl@checknumerical}. It is used by \cs{DTLdecimaltocurrency}.
+% Set to "\$" by default.
+%\begin{macro}{\@dtl@currency}
+% \begin{macrocode}
+\newcommand*{\@dtl@currency}{\$}
+% \end{macrocode}
+%\end{macro}
+%\cs{DTLsetdefaultcurrency}\marg{symbol} sets the default currency.
+%\begin{macro}{\DTLsetdefaultcurrency}
+% \begin{macrocode}
+\newcommand*{\DTLsetdefaultcurrency}[1]{%
+\renewcommand*{\@dtl@currency}{#1}}
+% \end{macrocode}
+%\end{macro}
+%
+%\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{macro}{\dtl@ifsingle}
+% \begin{macrocode}
+\newcommand{\dtl@ifsingle}[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}%
+\ifx\dtl@sg@arg\@empty
+ #3%
+\else
+ #4%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\subsection{Debugging commands}
+% These commands are provided to assist debugging
+%\begin{definition}
+%\cs{dtlshowdb}\marg{db name}
+%\end{definition}
+% Shows the database.
+%\begin{macro}{\dtlshowdb}
+% \begin{macrocode}
+\newcommand*{\dtlshowdb}[1]{%
+\expandafter\show\csname dtldb@#1\endcsname}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{definition}
+%\cs{dtlshowdbkeys}\marg{db name}
+%\end{definition}
+% Shows the key list for the named database.
+%\begin{macro}{\dtlshowdbkeys}
+% \begin{macrocode}
+\newcommand*{\dtlshowdbkeys}[1]{%
+\expandafter\show\csname dtlkeys@#1\endcsname}
+% \end{macrocode}
+%\end{macro}
+%
+%\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.
+%\begin{macro}{\dtlshowtype}
+% \begin{macrocode}
+\newcommand*{\dtlshowtype}[2]{%
+\expandafter\show\csname @dtl@idtype@#1@#2\endcsname}
+% \end{macrocode}
+%\end{macro}
+%\iffalse
+% \begin{macrocode}
+%</datatool.sty>
+% \end{macrocode}
+%\fi
+%\iffalse
+% \begin{macrocode}
+%<*datapie.sty>
+% \end{macrocode}
+%\fi
+%\section{datapie.sty}
+% Declare package:
+% \begin{macrocode}
+\NeedsTeXFormat{LaTeX2e}
+\ProvidesPackage{datapie}[2007/07/23 v1.0 (NLCT)]
+% \end{macrocode}
+% Require \sty{xkeyval} package
+% \begin{macrocode}
+\RequirePackage{xkeyval}
+% \end{macrocode}
+% Define a conditional to determine whether to use colour or
+% grey scale.
+%\begin{macro}{\ifDTLcolorpiechart}
+% \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}
+% Define boolean keys to govern label rotations.
+%\begin{macro}{\ifDTLrotateinner}
+% \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.
+%
+% The radius of the pie chart:
+%\begin{macro}{\DTLradius}
+% \begin{macrocode}
+\newlength\DTLradius
+\DTLradius=2cm
+% \end{macrocode}
+%\end{macro}
+% Inner label offset ratio
+%\begin{macro}{\DTLinnerratio}
+% \begin{macrocode}
+\newcommand*{\DTLinnerratio}{0.5}
+% \end{macrocode}
+%\end{macro}
+% Outer label offset ratio
+%\begin{macro}{\DTLouterratio}
+% \begin{macrocode}
+\newcommand*{\DTLouterratio}{1.25}
+% \end{macrocode}
+%\end{macro}
+% Cutaway offset ration
+%\begin{macro}{\DTLcutawayratio}
+% \begin{macrocode}
+\newcommand*\DTLcutawayratio{0.2}
+% \end{macrocode}
+%\end{macro}
+% The angle of the first segment
+%\begin{macro}{\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}
+%
+% \cs{dtl@piecutaways} is a comma separated list of segments that
+% need to be cut away from the pie chart.
+%\begin{macro}{\dtl@piecutaways}
+% \begin{macrocode}
+\newcommand*{\dtl@piecutaways}{}
+% \end{macrocode}
+%\end{macro}
+% \cs{dtl@innerlabel} specifies the label to appear inside
+% the segment. By default this is the variable used to create
+% the pie chart.
+%\begin{macro}{\dtl@innerlabel}
+% \begin{macrocode}
+\def\dtl@innerlabel{\DTLpievariable}%
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtl@outerlabel}
+% \begin{macrocode}
+\def\dtl@outerlabel{}%
+% \end{macrocode}
+%\end{macro}
+% \counterfmt{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}
+%
+%\begin{definition}
+%\cs{DTLdisplayinnerlabel}\marg{label}
+%\end{definition}
+% Command used to format the inner label. This just does the
+% label by default.
+%\begin{macro}{\DTLdisplayinnerlabel}
+% \begin{macrocode}
+\newcommand*{\DTLdisplayinnerlabel}[1]{#1}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{definition}
+%\cs{DTLdisplayouterlabel}\marg{label}
+%\end{definition}
+% Command used to format the outer label. This just does the
+% label by default.
+%\begin{macro}{\DTLdisplayouterlabel}
+% \begin{macrocode}
+\newcommand*{\DTLdisplayouterlabel}[1]{#1}
+% \end{macrocode}
+%\end{macro}
+%
+%\cs{DTLpiepercent}
+% returns the percentage value of the current segment.
+%\begin{macro}{\DTLpiepercent}
+% \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}
+%
+% \cs{DTLpieatbegintikz} specifies any commands
+% to apply at the start of the \env{tikzpicture} environment.
+% By default it does nothing, but can be set
+% to any of the \sty{pgf} package's transformation commands, e.g.\
+%\begin{verbatim}
+%\renewcommand*{\DTLpieatbegintikz}{%
+%\pgftransformcm{2}{0}{0}{1}{\pgforigin}}
+%\end{verbatim}
+%\begin{macro}{\DTLpieatbegintikz}
+% \begin{macrocode}
+\newcommand*{\DTLpieatbegintikz}{}
+% \end{macrocode}
+%\end{macro}
+%
+% \cs{DTLpieatendtikz} specifies any commands
+% to apply at the end of the \env{tikzpicture} environment.
+% By default it does nothing.
+%\begin{macro}{\DTLpieatendtikz}
+% \begin{macrocode}
+\newcommand*{\DTLpieatendtikz}{}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{definition}
+% \cs{DTLsetpiesegmentcolor}\marg{n}\marg{color}
+%\end{definition}
+% Assign colour name \meta{color} to the \meta{n}th segment.
+%\begin{macro}{\DTLsetpiesegmentcolor}
+% \begin{macrocode}
+\newcommand*{\DTLsetpiesegmentcolor}[2]{%
+\expandafter\def\csname dtlpie@segcol\romannumeral#1\endcsname{#2}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{definition}
+%\cs{DTLgetpiesegmentcolor}\marg{n}
+%\end{definition}
+% Get the colour specification for segment \meta{n}
+%\begin{macro}{\DTLgetpiesegmentcolor}
+% \begin{macrocode}
+\newcommand*{\DTLgetpiesegmentcolor}[1]{%
+\csname dtlpie@segcol\romannumeral#1\endcsname}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{definition}
+%\cs{DTLdopiesegmentcolor}\marg{n}
+%\end{definition}
+% Set the colour to that for segment \meta{n}
+%\begin{macro}{\DTLdopiesegmentcolor}
+% \begin{macrocode}
+\newcommand*{\DTLdopiesegmentcolor}[1]{%
+\expandafter\color\expandafter
+{\csname dtlpie@segcol\romannumeral#1\endcsname}}
+% \end{macrocode}
+%\end{macro}
+%\cs{DTLdocurrentpiesegmentcolor}
+% sets the colour to that of the current segment.
+%\begin{macro}{\DTLdocurrentpiesegmentcolor}
+% \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}
+%
+%\cs{DTLpieoutlinecolor} specifies what colour to draw the
+% outline.
+%\begin{macro}{\DTLpieoutlinecolor}
+% \begin{macrocode}
+\newcommand*{\DTLpieoutlinecolor}{black}
+% \end{macrocode}
+%\end{macro}
+%
+%\cs{DTLpieoutlinewidth} specifies the line width of the outline:
+% Outline is only drawn if the linewidth is greater than 0pt.
+%\begin{macro}{\DTLpieoutlinewidth}
+% \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{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}.
+%\begin{macro}{\DTLpiechart}
+% \begin{macrocode}
+\newcommand*{\DTLpiechart}[4][\boolean{true}]{%
+{\let\DTLpievariable=\relax
+\setkeys{datapie}{#2}%
+\ifx\DTLpievariable\relax
+ \PackageError{datapie}{\string\DTLpiechart\space missing variable}{}%
+\else
+% \end{macrocode}
+% Compute the total.
+% \begin{macrocode}
+\def\dtl@total{0}%
+\DTLforeach[#1]{#3}{#4}{%
+\let\dtl@oldtotal=\dtl@total
+\expandafter\DTLconverttodecimal\expandafter
+ {\DTLpievariable}{\dtl@variable}%
+\FPadd{\dtl@total}{\dtl@variable}{\dtl@total}%
+}%
+% \end{macrocode}
+% Compute the angles
+% \begin{macrocode}
+\expandafter\DTLconverttodecimal\expandafter
+ {\DTLstartangle}{\@dtl@start}%
+\DTLforeach[#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%
+\FPmul{\dtl@tmp}{\dtl@variable}{100}%
+\let\dtl@old=\dtl@tmp
+\FPdiv{\dtl@tmp}{\dtl@old}{\dtl@total}%
+\expandafter\FPround
+\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
+\DTLforeach[#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}
+\FPadd{\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
+ \FPsub{\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}
+\FPmul{\dtl@angle}{\dtl@extent}{0.5}%
+\FPadd{\dtl@midangle}{\dtl@angle}{\dtl@start}%
+% \end{macrocode}
+% Draw the segment.
+% \begin{macrocode}
+\begin{scope}[shift={\@dtl@shift}]%
+\dtl@truncatedecimal\dtl@start
+\dtl@truncatedecimal\dtl@endangle
+\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.
+% \begin{macrocode}
+\ifthenelse{\(\dtl@midangle > 90 \and \dtl@midangle < 270\)
+\TE@or \dtl@midangle < -90}{%
+ \FPsub{\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}
+\ifthenelse{\(\dtl@midangle > 90 \and \dtl@midangle < 270\)
+\TE@or \dtl@midangle < -90}{%
+ \FPsub{\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
+ \ifthenelse{\(\dtl@midangle<45\and\dtl@midangle>-45\)
+ \TE@or \dtl@midangle=45
+ \TE@or \dtl@midangle>315}{%
+ % east quadrant
+ \edef\dtl@outernodeopt{anchor=west}%
+ }{%
+ \ifthenelse{\(\dtl@midangle<135\and\dtl@midangle>45\)
+ \TE@or \dtl@midangle=135}{%
+ % north quadrant
+ \edef\dtl@outernodeopt{anchor=south}%
+ }{%
+ \ifthenelse{\(\dtl@midangle<225\and\dtl@midangle>135\)
+ \TE@or \dtl@midangle=225
+ \TE@or \dtl@midangle=-135
+ \TE@or \dtl@midangle<-135}{%
+ % west quadrant
+ \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
+}}
+% \end{macrocode}
+%\end{macro}
+%
+%\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).
+%\begin{macro}{\dtl@computeangles}
+% \begin{macrocode}
+\newcommand*{\dtl@computeangles}[2]{%
+\FPifgt{\@dtl@start}{180}%
+% if startangle > 180
+ \let\dtl@old=\@dtl@start
+% startangle = startangle - 360
+ \FPsub{\@dtl@start}{\dtl@old}{360}%
+\fi
+\FPiflt{\@dtl@start}{-180}%
+% if startangle < -180
+ \let\dtl@old=\@dtl@start
+% startangle = startangle + 360
+ \FPadd{\@dtl@start}{\dtl@old}{360}%
+\fi
+\expandafter\edef\csname dtl@sang@\romannumeral#1\endcsname{%
+\@dtl@start}%
+\FPmul{\dtl@angle}{360}{#2}%
+\let\dtl@old=\dtl@angle
+\FPdiv{\dtl@angle}{\dtl@old}{\dtl@total}%
+\expandafter\let\csname dtl@angle@\romannumeral#1\endcsname=\dtl@angle
+\let\dtl@old=\@dtl@start
+\FPadd{\@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{%
+\ifthenelse{\equal{#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}
+% \begin{macrocode}
+\newcommand*{\@@dtl@set@off}[1]{%
+\edef\dtl@old{\csname dtl@angle@\romannumeral#1\endcsname}%
+\FPmul{\dtl@angle}{\dtl@old}{0.5}%
+\let\dtl@old=\dtl@angle
+\edef\dtl@sang{\csname dtl@sang@\romannumeral#1\endcsname}%
+\FPadd{\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}
+% Set offset for a range of segments
+%\begin{macro}{\@@dtl@setoffr}
+% \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}%
+ \FPadd{\dtl@angle}{\dtl@old}{\dtl@segang}%
+ \advance\@dtl@seg by 1\relax
+ }%
+ \let\dtl@old=\dtl@angle
+ \FPmul{\dtl@angle}{\dtl@old}{0.5}%
+ \edef\dtl@sang{\csname dtl@sang@\romannumeral#1\endcsname}%
+ \let\dtl@old=\dtl@angle
+ \FPadd{\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
+%\section{dataplot.sty}
+% Declare package:
+% \begin{macrocode}
+\NeedsTeXFormat{LaTeX2e}
+\ProvidesPackage{dataplot}[2007/07/23 v1.0 (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}
+%\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}
+%\begin{macro}{\DTLplotstream}
+% \begin{macrocode}
+\newcommand*{\DTLplotstream}[4][\boolean{true}]{%
+\DTLforeach[#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}
+%
+%\cs{DTLplotmarks} contains a list of plot marks used by
+%\cs{DTLplot}.
+%\begin{macro}{\DTLplotmarks}
+% \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}
+%
+%\cs{DTLplotmarkcolors} contains a list of the plot mark colours.
+%\begin{macro}{\DTLplotmarkcolors}
+% \begin{macrocode}
+\newcommand*{\DTLplotmarkcolors}{%
+red,%
+green,%
+blue,%
+yellow,%
+magenta,%
+cyan,%
+orange,%
+black,%
+gray}
+% \end{macrocode}
+%\end{macro}
+%\cs{DTLplotlines} contains a list of dash patterns used by
+%\cs{DLTplot}.
+%\begin{macro}{\DTLplotlines}
+% \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}
+%\cs{DTLplotlinecolors} contains a list of the plot line colours.
+%\begin{macro}{\DTLplotlinecolors}
+% \begin{macrocode}
+\newcommand*{\DTLplotlinecolors}{%
+red,%
+green,%
+blue,%
+yellow,%
+magenta,%
+cyan,%
+orange,%
+black,%
+gray}
+% \end{macrocode}
+%\end{macro}
+%
+% The default total plot width is stored in the length
+% \cs{dtlplotwidth}
+%\begin{macro}{\DTLplotwidth}
+% \begin{macrocode}
+\newlength\DTLplotwidth
+\setlength\DTLplotwidth{4in}
+% \end{macrocode}
+%\end{macro}
+%
+% The default total plot height is stored in the length
+% \cs{dtlplotheight}
+%\begin{macro}{\DTLplotheight}
+% \begin{macrocode}
+\newlength\DTLplotheight
+\setlength\DTLplotheight{4in}
+% \end{macrocode}
+%\end{macro}
+%
+% The length of the tick marks is given by
+%\begin{macro}{\DTLticklength}
+% \begin{macrocode}
+\newlength\DTLticklength
+\setlength\DTLticklength{5pt}
+% \end{macrocode}
+%\end{macro}
+% The length of the minor tick marks is given by
+%\begin{macro}{\DTLminorticklength}
+% \begin{macrocode}
+\newlength\DTLminorticklength
+\setlength\DTLminorticklength{2pt}
+% \end{macrocode}
+%\end{macro}
+% The offset from the axis to the tick label is given by
+%\begin{macro}{\DTLticklabeloffset}
+% \begin{macrocode}
+\newlength\DTLticklabeloffset
+\setlength\DTLticklabeloffset{8pt}
+% \end{macrocode}
+%\end{macro}
+% Length to store the height of the $x$ tick labels
+%\begin{macro}{\dtl@xticlabelheight}
+% \begin{macrocode}
+\newlength\dtl@xticlabelheight
+% \end{macrocode}
+%\end{macro}
+% Length to store the width of the $y$ tick labels
+%\begin{macro}{\dtl@yticlabelwidth}
+% \begin{macrocode}
+\newlength\dtl@yticlabelwidth
+% \end{macrocode}
+%\end{macro}
+% Suggested minimum distance between tick marks where the gap
+% is not specified.
+%\begin{macro}{\DTLmintickgap}
+% \begin{macrocode}
+\newlength\DTLmintickgap
+\setlength\DTLmintickgap{20pt}
+% \end{macrocode}
+%\end{macro}
+% Suggested minimum distance between minor tick marks where the gap
+% is not specified.
+%\begin{macro}{\DTLminminortickgap}
+% \begin{macrocode}
+\newlength\DTLminminortickgap
+\setlength\DTLminminortickgap{5pt}
+% \end{macrocode}
+%\end{macro}
+% Round $x$ tick labels to the number of digits given by
+% the counter \counterfmt{DTLplotroundXvar}.
+% \begin{macrocode}
+\newcounter{DTLplotroundXvar}
+\setcounter{DTLplotroundXvar}{2}
+% \end{macrocode}
+% Round $y$ tick labels to the number of digits given by
+% the counter \counterfmt{DTLplotroundYvar}.
+% \begin{macrocode}
+\newcounter{DTLplotroundYvar}
+\setcounter{DTLplotroundYvar}{2}
+% \end{macrocode}
+% Conditional to determine whether or not to display the $x$ axis
+%\begin{macro}{\ifDTLxaxis}
+% \begin{macrocode}
+\newif\ifDTLxaxis
+\DTLxaxistrue
+% \end{macrocode}
+%\end{macro}
+% The style of the $x$ axis is just a solid line by default
+%\begin{macro}{\DTLXAxisStyle}
+% \begin{macrocode}
+\newcommand*{\DTLXAxisStyle}{-}
+% \end{macrocode}
+%\end{macro}
+%
+% Conditional to determine whether or not to display the $y$ axis
+%\begin{macro}{\ifDTLyaxis}
+% \begin{macrocode}
+\newif\ifDTLyaxis
+\DTLyaxistrue
+% \end{macrocode}
+%\end{macro}
+% The style of the $y$ axis is just a solid line by default
+%\begin{macro}{\DTLYAxisStyle}
+% \begin{macrocode}
+\newcommand*{\DTLYAxisStyle}{-}
+% \end{macrocode}
+%\end{macro}
+% The style of the major grid lines:
+%\begin{macro}{\DTLmajorgridstyle}
+% \begin{macrocode}
+\newcommand*{\DTLmajorgridstyle}{color=gray,-}
+% \end{macrocode}
+%\end{macro}
+% The style of the minor grid lines:
+%\begin{macro}{\DTLminorgridstyle}
+% \begin{macrocode}
+\newcommand*{\DTLminorgridstyle}{color=gray,loosely dotted}
+% \end{macrocode}
+%\end{macro}
+%
+% Conditional to determine whether the $x$ tics should point in or
+% out.
+%\begin{macro}{\ifDTLxticsin}
+% \begin{macrocode}
+\newif\ifDTLxticsin
+\DTLxticsintrue
+% \end{macrocode}
+%\end{macro}
+% Conditional to determine whether the $y$ tics should point in or
+% out.
+%\begin{macro}{\ifDTLyticsin}
+% \begin{macrocode}
+\newif\ifDTLyticsin
+\DTLyticsintrue
+% \end{macrocode}
+%\end{macro}
+% Count register to determine the legend setting.
+%\begin{macro}{\dtl@legendsetting}
+% \begin{macrocode}
+\newcount\dtl@legendsetting
+% \end{macrocode}
+%\end{macro}
+% Gap between border of plot and legend is given by the
+% lengths \cs{DTLlegendxoffset} and \cs{DTLlegendyoffset}
+%\begin{macro}{\DTLlegendxoffset}
+% \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}
+% Macro to display the legend:
+%\begin{macro}{\DTLformatlegend}
+% \begin{macrocode}
+\newcommand*{\DTLformatlegend}[1]{%
+\setlength{\fboxrule}{1.1pt}%
+\fcolorbox{black}{white}{#1}}
+% \end{macrocode}
+%\end{macro}
+% Conditional to specify whether or not to use markers
+%\begin{macro}{\ifDTLshowmarkers}
+% \begin{macrocode}
+\newif\ifDTLshowmarkers
+\DTLshowmarkerstrue
+% \end{macrocode}
+%\end{macro}
+% Conditional to specify whether or not to use lines
+%\begin{macro}{\ifDTLshowlines}
+% \begin{macrocode}
+\newif\ifDTLshowlines
+\DTLshowlinesfalse
+% \end{macrocode}
+%\end{macro}
+% Hook to insert stuff at the start of the \env{tikzpicture}
+% environment (after the unit vectors have been set).
+%\begin{macro}{\DTLplotatbegintikz}
+% \begin{macrocode}
+\newcommand*{\DTLplotatbegintikz}{}
+% \end{macrocode}
+%\end{macro}
+% Hook to insert stuff at the end of the \env{tikzpicture}
+% environment.
+%\begin{macro}{\DTLplotatendtikz}
+% \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}
+% Enclose plot in a box
+% \begin{macrocode}
+\define@boolkey{dataplot}[DTL]{box}[true]{}
+\DTLboxfalse
+% \end{macrocode}
+% Condition to determine whether to show the $x$ tick marks
+% \begin{macrocode}
+\define@boolkey{dataplot}[DTL]{xtics}[true]{}
+\DTLxticstrue
+% \end{macrocode}
+% Condition to determine whether to show the $y$ tick marks
+% \begin{macrocode}
+\define@boolkey{dataplot}[DTL]{ytics}[true]{}
+\DTLyticstrue
+% \end{macrocode}
+% 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}
+% 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}
+% Determine whether to draw the grid
+% \begin{macrocode}
+\define@boolkey{dataplot}[DTL]{grid}[true]{}
+% \end{macrocode}
+% 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}
+%
+% Temporary length:
+%\begin{macro}{\dtl@tmplength}
+% \begin{macrocode}
+\newlength\dtl@tmplength
+% \end{macrocode}
+%\end{macro}
+%
+%\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{macro}{\DTLplot}
+% \begin{macrocode}
+\newcommand*{\DTLplot}[3][\boolean{true}]{{%
+\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.
+% \begin{macrocode}
+ \@dtl@tmpcount=\DTLplotwidth
+ \FPsub{\dtl@dx}{\DTLmaxX}{\DTLminX}%
+ \FPdiv{\dtl@unit@x}{\number\@dtl@tmpcount}{\dtl@dx}%
+ \@dtl@tmpcount=\DTLplotheight
+ \FPsub{\dtl@dy}{\DTLmaxY}{\DTLminY}%
+ \FPdiv{\dtl@unit@y}{\number\@dtl@tmpcount}{\dtl@dy}%
+% \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
+ \dtl@constructticklist\DTLminX\DTLmaxX
+ \dtl@unit@x\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@unit@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
+ \dtl@constructticklist\DTLminY\DTLmaxY
+ \dtl@unit@y\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@unit@y\dtl@yminorticlist
+ \fi
+ \let\dtl@prevtick=\dtl@nexttick
+ }%
+ \fi
+% \end{macrocode}
+% Determine the width of the $y$ tick labels.
+% \begin{macrocode}
+ \ifx\dtl@ylabel\relax
+ \else
+ \ifx\dtl@yticlabels\relax
+ \@for\dtl@thislabel:=\dtl@yticlist\do{%
+ \FPround{\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
+% \end{macrocode}
+% Start the picture.
+% \begin{macrocode}
+ \begin{tikzpicture}
+% \end{macrocode}
+% Set the $x$ and $y$ unit vectors.
+% \begin{macrocode}
+ \pgfsetxvec{\pgfpoint{\dtl@unit@x sp}{0pt}}%
+ \pgfsetyvec{\pgfpoint{0pt}{\dtl@unit@y sp}}%
+% \end{macrocode}
+% Add any extra information the user requires
+% \begin{macrocode}
+ \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
+ \addtolength\dtl@xticlabelheight{\DTLticklabeloffset}%
+ \@for\dtl@thistick:=\dtl@xticlist\do{%
+ \pgfpathmoveto{\pgfpointxy{\dtl@thistick}{\DTLminY}}
+ \ifDTLxticsin
+ \pgfpathlineto{
+ \pgfpointadd{\pgfpointxy{\dtl@thistick}{\DTLminY}}
+ {\pgfpoint{0pt}{\DTLticklength}}}
+ \else
+ \pgfpathlineto{
+ \pgfpointadd{\pgfpointxy{\dtl@thistick}{\DTLminY}}
+ {\pgfpoint{0pt}{-\DTLticklength}}}
+ \fi
+ \ifDTLbox
+ \pgfpathmoveto{\pgfpointxy{\dtl@thistick}{\DTLmaxY}}
+ \ifDTLxticsin
+ \pgfpathlineto{
+ \pgfpointadd{\pgfpointxy{\dtl@thistick}{\DTLmaxY}}
+ {\pgfpoint{0pt}{-\DTLticklength}}}
+ \else
+ \pgfpathlineto{
+ \pgfpointadd{\pgfpointxy{\dtl@thistick}{\DTLmaxY}}
+ {\pgfpoint{0pt}{\DTLticklength}}}
+ \fi
+ \fi
+ \pgfusepath{stroke}%
+% \end{macrocode}
+% Plot the tick labels
+% \begin{macrocode}
+ \ifx\dtl@xticlabels\relax
+ \FPround{\dtl@thislabel}{\dtl@thistick}
+ {\c@DTLplotroundXvar}%
+ \else
+ \dtl@chopfirst\dtl@xticlabels\dtl@thislabel\dtl@rest
+ \let\dtl@xticlabels=\dtl@rest
+ \fi
+ \pgftext[base,center,at={\pgfpointadd
+ {\pgfpointxy{\dtl@thistick}{\DTLminY}}
+ {\pgfpoint{0pt}{-\dtl@xticlabelheight}}}]
+ {\dtl@thislabel}
+ }%
+ \fi
+% \end{macrocode}
+% Plot $x$ label if required.
+% \begin{macrocode}
+ \ifx\dtl@xlabel\relax
+ \else
+ \addtolength{\dtl@xticlabelheight}{\baselineskip}%
+ \setlength{\dtl@tmplength}{0.5\DTLplotwidth}
+ \pgftext[base,center,at={\pgfpointadd
+ {\pgfpointxy{\DTLminX}{\DTLminY}}%
+ {\pgfpoint{\dtl@tmplength}{-\dtl@xticlabelheight}}}]{%
+ \dtl@xlabel}
+ \fi
+% \end{macrocode}
+% Plot the $x$ minor ticks if required
+% \begin{macrocode}
+ \ifDTLxminortics
+ \@for\dtl@thistick:=\dtl@xminorticlist\do{%
+ \pgfpathmoveto{\pgfpointxy{\dtl@thistick}{\DTLminY}}
+ \ifDTLxticsin
+ \pgfpathlineto{
+ \pgfpointadd{\pgfpointxy{\dtl@thistick}{\DTLminY}}
+ {\pgfpoint{0pt}{\DTLminorticklength}}}
+ \else
+ \pgfpathlineto{
+ \pgfpointadd{\pgfpointxy{\dtl@thistick}{\DTLminY}}
+ {\pgfpoint{0pt}{-\DTLminorticklength}}}
+ \fi
+ \ifDTLbox
+ \pgfpathmoveto{\pgfpointxy{\dtl@thistick}{\DTLmaxY}}
+ \ifDTLxticsin
+ \pgfpathlineto{
+ \pgfpointadd{\pgfpointxy{\dtl@thistick}{\DTLmaxY}}
+ {\pgfpoint{0pt}{-\DTLminorticklength}}}
+ \else
+ \pgfpathlineto{
+ \pgfpointadd{\pgfpointxy{\dtl@thistick}{\DTLmaxY}}
+ {\pgfpoint{0pt}{\DTLminorticklength}}}
+ \fi
+ \fi
+ }%
+ \fi
+% \end{macrocode}
+% Plot $y$ tics if required.
+% \begin{macrocode}
+ \ifDTLytics
+ \@for\dtl@thistick:=\dtl@yticlist\do{%
+ \pgfpathmoveto{\pgfpointxy{\DTLminX}{\dtl@thistick}}
+ \ifDTLyticsin
+ \pgfpathlineto{
+ \pgfpointadd{\pgfpointxy{\DTLminX}{\dtl@thistick}}
+ {\pgfpoint{\DTLticklength}{0pt}}}
+ \else
+ \pgfpathlineto{
+ \pgfpointadd{\pgfpointxy{\DTLminX}{\dtl@thistick}}
+ {\pgfpoint{-\DTLticklength}{0pt}}}
+ \fi
+ \ifDTLbox
+ \pgfpathmoveto{\pgfpointxy{\DTLmaxX}{\dtl@thistick}}
+ \ifDTLyticsin
+ \pgfpathlineto{
+ \pgfpointadd{\pgfpointxy{\DTLmaxX}{\dtl@thistick}}
+ {\pgfpoint{-\DTLticklength}{0pt}}}
+ \else
+ \pgfpathlineto{
+ \pgfpointadd{\pgfpointxy{\DTLmaxX}{\dtl@thistick}}
+ {\pgfpoint{\DTLticklength}{0pt}}}
+ \fi
+ \fi
+ \pgfusepath{stroke}
+% \end{macrocode}
+% Plot the $y$ tick labels if required
+% \begin{macrocode}
+ \ifx\dtl@yticlabels\relax
+ \FPround{\dtl@thislabel}{\dtl@thistick}
+ {\c@DTLplotroundYvar}%
+ \else
+ \dtl@chopfirst\dtl@yticlabels\dtl@thislabel\dtl@rest
+ \let\dtl@yticlabels=\dtl@rest
+ \fi
+ \pgftext[right,at={\pgfpointadd
+ {\pgfpointxy{\DTLminX}{\dtl@thistick}}
+ {\pgfpoint{-\DTLticklabeloffset}{0pt}}}]
+ {\dtl@thislabel}
+ }%
+ \fi
+% \end{macrocode}
+% Plot $y$ label if required.
+% \begin{macrocode}
+ \ifx\dtl@ylabel\relax
+ \else
+ \addtolength{\dtl@yticlabelwidth}{\baselineskip}%
+ \setlength{\dtl@tmplength}{0.5\DTLplotheight}
+ \pgftext[bottom,center,at={\pgfpointadd
+ {\pgfpointxy{\DTLminX}{\DTLminY}}%
+ {\pgfpoint{-\dtl@yticlabelwidth}{\dtl@tmplength}}},
+ rotate=90]{%
+ \dtl@ylabel}
+ \fi
+% \end{macrocode}
+% Plot the $y$ minor ticks if required
+% \begin{macrocode}
+ \ifDTLyminortics
+ \@for\dtl@thistick:=\dtl@yminorticlist\do{%
+ \pgfpathmoveto{\pgfpointxy{\DTLminX}{\dtl@thistick}}
+ \ifDTLyticsin
+ \pgfpathlineto{
+ \pgfpointadd{\pgfpointxy{\DTLminX}{\dtl@thistick}}
+ {\pgfpoint{\DTLminorticklength}{0pt}}}
+ \else
+ \pgfpathlineto{
+ \pgfpointadd{\pgfpointxy{\DTLminX}{\dtl@thistick}}
+ {\pgfpoint{-\DTLminorticklength}{0pt}}}
+ \fi
+ \ifDTLbox
+ \pgfpathmoveto{\pgfpointxy{\DTLmaxX}{\dtl@thistick}}
+ \ifDTLyticsin
+ \pgfpathlineto{
+ \pgfpointadd{\pgfpointxy{\DTLmaxX}{\dtl@thistick}}
+ {\pgfpoint{-\DTLminorticklength}{0pt}}}
+ \else
+ \pgfpathlineto{
+ \pgfpointadd{\pgfpointxy{\DTLmaxX}{\dtl@thistick}}
+ {\pgfpoint{\DTLminorticklength}{0pt}}}
+ \fi
+ \fi
+ \pgfusepath{stroke}
+ }%
+ \fi
+% \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.
+% \begin{macrocode}
+ \DTLforeach[#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}%
+ \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
+ \pgftext[top,center,at={\pgfpointadd
+ {\pgfpointxy{\DTLminX}{\DTLmaxY}}
+ {\pgfpoint{0.5\DTLplotwidth}{-\DTLlegendyoffset}}}]
+ {\DTLformatlegend
+ {\begin{tabular}{cl}\dtl@legend\end{tabular}}}
+ \or % north east
+ \pgftext[top,right,at={\pgfpointadd
+ {\pgfpointxy{\DTLmaxX}{\DTLmaxY}}
+ {\pgfpoint{-\DTLlegendxoffset}{-\DTLlegendyoffset}}}]
+ {\DTLformatlegend
+ {\begin{tabular}{cl}\dtl@legend\end{tabular}}}
+ \or % east
+ \pgftext[center,right,at={\pgfpointadd
+ {\pgfpointxy{\DTLmaxX}{\DTLminY}}
+ {\pgfpoint{-\DTLlegendxoffset}{0.5\DTLplotheight}}}]
+ {\DTLformatlegend
+ {\begin{tabular}{cl}\dtl@legend\end{tabular}}}
+ \or % south east
+ \pgftext[bottom,right,at={\pgfpointadd
+ {\pgfpointxy{\DTLmaxX}{\DTLminY}}
+ {\pgfpoint{-\DTLlegendxoffset}{\DTLlegendyoffset}}}]
+ {\DTLformatlegend
+ {\begin{tabular}{cl}\dtl@legend\end{tabular}}}
+ \or % south
+ \pgftext[center,bottom,at={\pgfpointadd
+ {\pgfpointxy{\DTLminX}{\DTLminY}}
+ {\pgfpoint{0.5\DTLplotwidth}{\DTLlegendyoffset}}}]
+ {\DTLformatlegend
+ {\begin{tabular}{cl}\dtl@legend\end{tabular}}}
+ \or % south west
+ \pgftext[bottom,left,at={\pgfpointadd
+ {\pgfpointxy{\DTLminX}{\DTLminY}}
+ {\pgfpoint{\DTLlegendxoffset}{\DTLlegendyoffset}}}]
+ {\DTLformatlegend
+ {\begin{tabular}{cl}\dtl@legend\end{tabular}}}
+ \or % west
+ \pgftext[center,left,at={\pgfpointadd
+ {\pgfpointxy{\DTLminX}{\DTLminY}}
+ {\pgfpoint{\DTLlegendxoffset}{0.5\DTLplotheight}}}]
+ {\DTLformatlegend
+ {\begin{tabular}{cl}\dtl@legend\end{tabular}}}
+ \or % north west
+ \pgftext[top,left,at={\pgfpointadd
+ {\pgfpointxy{\DTLminX}{\DTLmaxY}}
+ {\pgfpoint{\DTLlegendxoffset}{-\DTLlegendyoffset}}}]
+ {\DTLformatlegend
+ {\begin{tabular}{cl}\dtl@legend\end{tabular}}}
+ \fi
+ \DTLplotatendtikz
+ \end{tikzpicture}
+ \fi
+ \fi
+\fi
+}}
+% \end{macrocode}
+%\end{macro}
+%
+% Extract bounds:
+%\begin{macro}{\dtl@getbounds}
+% \begin{macrocode}
+\def\dtl@getbounds#1,#2,#3,#4\@nil{%
+\def\DTLminX{#1}%
+\def\DTLminY{#2}%
+\def\DTLmaxX{#3}%
+\def\DTLmaxY{#4}%
+\FPifgt{\DTLminX}{\DTLmaxX}
+ \PackageError{dataplot}{Min X > Max X in bounds #1,#2,#3,#4}{%
+ The bounds must be specified as minX,minY,maxX,maxY}%
+\fi
+\FPifgt{\DTLminY}{\DTLmaxY}
+ \PackageError{dataplot}{Min Y > Max Y in bounds #1,#2,#3,#4}{%
+ The bounds must be specified as minX,minY,maxX,maxY}%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{definition}
+%\cs{dtl@constructticklist}\marg{min}\marg{max}\marg{scale factor}\marg{list}
+%\end{definition}
+% Construct a list of tick points between \meta{min} and \meta{max}
+% and store in \meta{list} (a control sequence.)
+%\begin{macro}{\dtl@constructticklist}
+% \begin{macrocode}
+\newcommand*{\dtl@constructticklist}[4]{%
+\DTLifFPopenbetween{0}{#1}{#2}{%
+ \FPsub{\@dtl@width}{0}{#1}%
+ \FPmul{\@dtl@width}{\@dtl@width}{#3}%
+ \FPdiv{\@dtl@neggap}{\@dtl@width}{10}%
+ \setlength\dtl@tmplength{\@dtl@neggap sp}%
+ \ifdim\dtl@tmplength<\DTLmintickgap
+ \FPdiv{\@dtl@neggap}{\@dtl@width}{4}%
+ \setlength\dtl@tmplength{\@dtl@neggap sp}%
+ \ifdim\dtl@tmplength<\DTLmintickgap
+ \FPdiv{\@dtl@neggap}{\@dtl@width}{2}%
+ \setlength\dtl@tmplength{\@dtl@neggap sp}%
+ \ifdim\dtl@tmplength<\DTLmintickgap
+ \let\@dtl@neggap=\@dtl@width
+ \fi
+ \fi
+ \fi
+ \FPmul{\@dtl@width}{#2}{#3}%
+ \FPdiv{\@dtl@posgap}{\@dtl@width}{10}%
+ \setlength\dtl@tmplength{\@dtl@posgap sp}%
+ \ifdim\dtl@tmplength<\DTLmintickgap
+ \FPdiv{\@dtl@posgap}{\@dtl@width}{4}%
+ \setlength\dtl@tmplength{\@dtl@posgap sp}%
+ \ifdim\dtl@tmplength<\DTLmintickgap
+ \FPdiv{\@dtl@posgap}{\@dtl@width}{2}%
+ \setlength\dtl@tmplength{\@dtl@posgap sp}%
+ \ifdim\dtl@tmplength<\DTLmintickgap
+ \let\@dtl@posgap=\@dtl@width
+ \fi
+ \fi
+ \fi
+ \FPmax{\@dtl@gap}{\@dtl@neggap}{\@dtl@posgap}%
+ \FPdiv{\@dtl@gap}{\@dtl@gap}{#3}%
+ \dtl@constructticklistwithgapz{#1}{#2}{#4}{\@dtl@gap}%
+}{%
+ \FPsub{\@dtl@width}{#2}{#1}%
+ \FPmul{\@dtl@width}{\@dtl@width}{#3}%
+ \FPdiv{\@dtl@gap}{\@dtl@width}{10}%
+ \setlength\dtl@tmplength{\@dtl@gap sp}%
+ \ifdim\dtl@tmplength<\DTLmintickgap
+ \FPdiv{\@dtl@gap}{\@dtl@width}{4}%
+ \setlength\dtl@tmplength{\@dtl@gap sp}%
+ \ifdim\dtl@tmplength<\DTLmintickgap
+ \FPdiv{\@dtl@gap}{\@dtl@width}{2}%
+ \setlength\dtl@tmplength{\@dtl@gap sp}%
+ \ifdim\dtl@tmplength<\DTLmintickgap
+ \let\@dtl@gap=\@dtl@width
+ \fi
+ \fi
+ \fi
+ \FPdiv{\@dtl@gap}{\@dtl@gap}{#3}%
+ \dtl@constructticklistwithgap{#1}{#2}{#4}{\@dtl@gap}%
+}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{definition}
+%\cs{dtl@constructticklistwithgap}\marg{min}\marg{max}\marg{list}\marg{gap}
+%\end{definition}
+% Construct 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.
+%\begin{macro}{\dtl@constructticklistwithgap}
+% \begin{macrocode}
+\newcommand*{\dtl@constructticklistwithgap}[4]{%
+\edef\@dtl@thistick{#1}%
+\edef#3{#1}%
+\FPadd{\@dtl@thistick}{\@dtl@thistick}{#4}%
+\whiledo{\DTLisFPopenbetween{\@dtl@thistick}{#1}{#2}}{%
+ \expandafter\toks@\expandafter{\@dtl@thistick}%
+ \edef#3{#3,\the\toks@}%
+ \FPadd{\@dtl@thistick}{\@dtl@thistick}{#4}%
+}%
+\expandafter\toks@\expandafter{#2}%
+\edef#3{#3,\the\toks@}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{definition}
+%\cs{dtl@constructticklistwithgapz}\marg{min}\marg{max}\marg{list}\marg{gap}
+%\end{definition}
+% Construct 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.
+%\begin{macro}{\dtl@constructticklistwithgapz}
+% \begin{macrocode}
+\newcommand*{\dtl@constructticklistwithgapz}[4]{%
+\edef\@dtl@thistick{0}%
+\edef#3{0}%
+\FPadd{\@dtl@thistick}{\@dtl@thistick}{#4}%
+\whiledo{\DTLisFPopenbetween{\@dtl@thistick}{0}{#2}}{%
+ \expandafter\toks@\expandafter{\@dtl@thistick}%
+ \edef#3{#3,\the\toks@}%
+ \FPadd{\@dtl@thistick}{\@dtl@thistick}{#4}%
+}%
+\expandafter\toks@\expandafter{#2}%
+\edef#3{#3,\the\toks@}%
+\FPifeq{#1}{0}%
+\else
+\edef\@dtl@thistick{0}%
+ \FPsub{\@dtl@thistick}{\@dtl@thistick}{#4}%
+ \whiledo{\DTLisFPopenbetween{\@dtl@thistick}{#1}{0}}{%
+ \expandafter\toks@\expandafter{\@dtl@thistick}%
+ \edef#3{\the\toks@,#3}%
+ \FPsub{\@dtl@thistick}{\@dtl@thistick}{#4}%
+ }%
+ \expandafter\toks@\expandafter{#1}%
+ \edef#3{\the\toks@,#3}%
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{definition}
+%\cs{dtl@constructminorticklist}\marg{min}\marg{max}\marg{scale factor}\marg{list}
+%\end{definition}
+% Construct a list of minor tick points between \meta{min} and \meta{max}
+% and append to \meta{list} (a control sequence.)
+%\begin{macro}{\dtl@constructminorticklist}
+% \begin{macrocode}
+\newcommand*{\dtl@constructminorticklist}[4]{%
+ \FPsub{\@dtl@width}{#2}{#1}%
+ \FPmul{\@dtl@width}{\@dtl@width}{#3}%
+ \FPdiv{\@dtl@gap}{\@dtl@width}{10}%
+ \setlength\dtl@tmplength{\@dtl@gap sp}%
+ \ifdim\dtl@tmplength<\DTLminminortickgap
+ \FPdiv{\@dtl@gap}{\@dtl@width}{4}%
+ \setlength\dtl@tmplength{\@dtl@gap sp}%
+ \ifdim\dtl@tmplength<\DTLminminortickgap
+ \FPdiv{\@dtl@gap}{\@dtl@width}{2}%
+ \setlength\dtl@tmplength{\@dtl@gap sp}%
+ \ifdim\dtl@tmplength<\DTLminminortickgap
+ \let\@dtl@gap=\@dtl@width
+ \fi
+ \fi
+ \fi
+ \FPdiv{\@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{definition}
+%\cs{dtl@constructticklistwithgapex}\marg{min}\marg{max}\marg{list}\marg{gap}
+%\end{definition}
+% Construct 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.
+%\begin{macro}{\dtl@constructticklistwithgapex}
+% \begin{macrocode}
+\newcommand*{\dtl@constructticklistwithgapex}[4]{%
+\edef\@dtl@thistick{#1}%
+\let#3=\@empty
+\FPadd{\@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
+ \FPadd{\@dtl@thistick}{\@dtl@thistick}{#4}%
+}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{definition}
+%\cs{DTLaddtoplotlegend}\marg{marker}\marg{line style}\marg{label}
+%\end{definition}
+% Add entry to legend.
+%\begin{macro}{\DTLaddtoplotlegend}
+% \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
+ \edef\dtl@legend{\noexpand\tikz\the\toks@; \noexpand& #3}%
+\else
+ \expandafter\@dtl@toks\expandafter{\dtl@legend}%
+ \edef\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}
+%<*databar.sty>
+% \end{macrocode}
+%\fi
+%\section{databar.sty}
+% Declare package:
+% \begin{macrocode}
+\NeedsTeXFormat{LaTeX2e}
+\ProvidesPackage{databar}[2007/07/23 v1.0 (NLCT)]
+% \end{macrocode}
+% Require \sty{xkeyval} package
+% \begin{macrocode}
+\RequirePackage{xkeyval}
+% \end{macrocode}
+% Require \sty{dataplot} package
+% \begin{macrocode}
+\RequirePackage{dataplot}
+% \end{macrocode}
+% Define a conditional to determine whether to use colour or
+% grey scale.
+%\begin{macro}{\ifDTLcolorbarchart}
+% \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}
+% Define boolean keys to govern bar chart orientation.
+%\begin{macro}{\ifDTLverticalbars}
+% \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.
+%
+% The total height of the bar chart
+%\begin{macro}{\DTLbarchartlength}
+% \begin{macrocode}
+\newlength\DTLbarchartlength
+\DTLbarchartlength=3in
+% \end{macrocode}
+%\end{macro}
+%
+% The width of each bar
+%\begin{macro}{\DTLbarwidth}
+% \begin{macrocode}
+\newlength\DTLbarwidth
+\DTLbarwidth=1cm
+% \end{macrocode}
+%\end{macro}
+%
+% The offset from the $x$ axis to the bar label
+%\begin{macro}{\DTLbarlabeloffset}
+% \begin{macrocode}
+\newlength\DTLbarlabeloffset
+\setlength\DTLbarlabeloffset{10pt}
+% \end{macrocode}
+%\end{macro}
+% The style of the $x$ axis
+%\begin{macro}{\DTLBarXAxisStyle}
+% \begin{macrocode}
+\newcommand*{\DTLBarXAxisStyle}{-}
+% \end{macrocode}
+%\end{macro}
+% The style of the $y$ axis
+%\begin{macro}{\DTLBarYAxisStyle}
+% \begin{macrocode}
+\newcommand*{\DTLBarYAxisStyle}{-}
+% \end{macrocode}
+%\end{macro}
+%
+% \counterfmt{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}
+%
+%\cs{DTLbardisplayYticklabel} governs how the $y$ tick labels appear.
+%\begin{macro}{\DTLbardisplayYticklabel}
+% \begin{macrocode}
+\newcommand*{\DTLbardisplayYticklabel}[1]{#1}
+% \end{macrocode}
+%\end{macro}
+%\cs{DTLdisplaylowerbarlabel} governs how the lower bar labels appear.
+%\begin{macro}{\DTLdisplaylowerbarlabel}
+% \begin{macrocode}
+\newcommand*{\DTLdisplaylowerbarlabel}[1]{#1}
+% \end{macrocode}
+%\end{macro}
+%\cs{DTLdisplaylowermultibarlabel} governs how the lower multi bar labels appear.
+%\begin{macro}{\DTLdisplaylowermultibarlabel}
+% \begin{macrocode}
+\newcommand*{\DTLdisplaylowermultibarlabel}[1]{#1}
+% \end{macrocode}
+%\end{macro}
+%\cs{DTLdisplayupperbarlabel} governs how the upper bar labels
+% appear.
+%\begin{macro}{\DTLdisplayupperbarlabel}
+% \begin{macrocode}
+\newcommand*{\DTLdisplayupperbarlabel}[1]{#1}
+% \end{macrocode}
+%\end{macro}
+%\cs{DTLdisplayuppermultibarlabel} governs how the upper multi bar
+% labels appear.
+%\begin{macro}{\DTLdisplayuppermultibarlabel}
+% \begin{macrocode}
+\newcommand*{\DTLdisplayuppermultibarlabel}[1]{#1}
+% \end{macrocode}
+%\end{macro}
+%
+% \cs{DTLbaratbegintikz} specifies any commands
+% to apply at the start of the \env{tikzpicture} environment.
+% By default it does nothing.
+%\begin{macro}{\DTLbaratbegintikz}
+% \begin{macrocode}
+\newcommand*{\DTLbaratbegintikz}{}
+% \end{macrocode}
+%\end{macro}
+%
+% \cs{DTLbaratendtikz} specifies any commands
+% to apply at the end of the \env{tikzpicture} environment.
+% By default it does nothing.
+%\begin{macro}{\DTLbaratendtikz}
+% \begin{macrocode}
+\newcommand*{\DTLbaratendtikz}{}
+% \end{macrocode}
+%\end{macro}
+%
+% Conditional to determine whether or not to display the $x$
+% axis
+%\begin{macro}{\ifDTLbarxaxis}
+% \begin{macrocode}
+\newif\ifDTLbarxaxis
+% \end{macrocode}
+%\end{macro}
+% Conditional to determine whether or not to display the $y$
+% axis
+%\begin{macro}{\ifDTLbaryaxis}
+% \begin{macrocode}
+\newif\ifDTLbaryaxis
+% \end{macrocode}
+%\end{macro}
+% Conditional to determine whether or not to display the $y$
+% tick marks
+%\begin{macro}{\ifDTLbarytics}
+% \begin{macrocode}
+\newif\ifDTLbarytics
+% \end{macrocode}
+%\end{macro}
+%
+% Define count register to store the current bar index:
+%\begin{macro}{\@dtl@barcount}
+% \begin{macrocode}
+\newcount\@dtl@barcount
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{definition}
+% \cs{DTLsetbarcolor}\marg{n}\marg{color}
+%\end{definition}
+% Assign colour name \meta{color} to the \meta{n}th bar.
+%\begin{macro}{\DTLsetbarcolor}
+% \begin{macrocode}
+\newcommand*{\DTLsetbarcolor}[2]{%
+\expandafter\def\csname dtlbar@segcol\romannumeral#1\endcsname{#2}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{definition}
+%\cs{DTLgetbarcolor}\marg{n}
+%\end{definition}
+% Get the colour specification for the \meta{n}th bar
+%\begin{macro}{\DTLgetbarcolor}
+% \begin{macrocode}
+\newcommand*{\DTLgetbarcolor}[1]{%
+\csname dtlbar@segcol\romannumeral#1\endcsname}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{definition}
+%\cs{DTLdobarcolor}\marg{n}
+%\end{definition}
+% Set the colour to that for the \meta{n}th bar
+%\begin{macro}{\DTLdobarcolor}
+% \begin{macrocode}
+\newcommand*{\DTLdobarcolor}[1]{%
+\expandafter\color\expandafter
+{\csname dtlbar@segcol\romannumeral#1\endcsname}}
+% \end{macrocode}
+%\end{macro}
+%
+%\cs{DTLdocurrentbarcolor}
+% sets the colour to that of the current bar.
+%\begin{macro}{\DTLdocurrentbarcolor}
+% \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}
+%
+%\cs{DTLbaroutlinecolor} specifies what colour to draw the
+% outline.
+%\begin{macro}{\DTLbaroutlinecolor}
+% \begin{macrocode}
+\newcommand*{\DTLbaroutlinecolor}{black}
+% \end{macrocode}
+%\end{macro}
+%
+%\cs{DTLbaroutlinewidth} specifies the line width of the outline:
+% Outline is only drawn if the linewidth is greater than 0pt.
+%\begin{macro}{\DTLbaroutlinewidth}
+% \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}
+%
+% 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{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{macro}{\DTLbarchart}
+% \begin{macrocode}
+\newcommand*{\DTLbarchart}[4][\boolean{true}]{%
+{\let\DTLbarvariable=\relax
+\let\DTLbarmax=\relax
+\let\DTLnegextent=\relax
+\disable@keys{databar}{variables,multibarlabels,%
+uppermultibarlabels,groupgap}%
+\setkeys{databar}{#2}%
+\ifx\DTLbarvariable\relax
+ \PackageError{databar}{\string\DTLbarchart\space missing variable}{}%
+\else
+% \end{macrocode}
+% Compute the maximum bar height, unless \cs{DTLbarmax} has been
+% set.
+% \begin{macrocode}
+ \ifx\DTLbarmax\relax
+ \DTLforeach[#1]{#3}{#4}{%
+ \expandafter\DTLconverttodecimal\expandafter
+ {\DTLbarvariable}{\dtl@barvar}%
+ \ifx\DTLbarmax\relax
+ \let\DTLbarmax=\dtl@barvar
+ \else
+ \let\dtl@old=\DTLbarmax
+ \FPmax{\DTLbarmax}{\dtl@old}{\dtl@barvar}%
+ \fi
+ }%
+ \ifx\dtlbar@yticgap\relax
+ \else
+ \let\dtl@thistick=\dtlbar@yticgap%
+ \whiledo{\DTLisFPopenbetween{\dtl@thistick}{0}{\DTLbarmax}}{%
+ \FPadd{\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}%
+ \DTLforeach[#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}}{%
+ \FPsub{\dtl@thistick}{\dtl@thistick}{\dtlbar@yticgap}%
+ }%
+ \let\DTLnegextent=\dtl@thistick
+ }{}%
+ \fi
+ \fi
+% \end{macrocode}
+% Determine scaling factor
+% \begin{macrocode}
+ \@dtl@tmpcount=\DTLbarchartlength
+ \FPsub{\dtl@extent}{\DTLbarmax}{\DTLnegextent}%
+ \FPdiv{\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@constructticklist\DTLnegextent\DTLbarmax
+ \dtl@unit\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{%
+ \FPround{\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}
+\DTLforeach[#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
+ }%
+\else
+ \edef\dtl@textopt{%
+ at={\noexpand\pgfpointadd
+ {\noexpand\pgfpointxy{0}{\@dtl@start.5}}
+ {\noexpand\pgfpoint{-\noexpand\DTLbarlabeloffset}{0pt}}},
+ \DTLbarXlabelalign
+ }%
+\fi
+ \expandafter\pgftext\expandafter[\dtl@textopt]{%
+ \DTLdisplaylowerbarlabel{\dtl@barlabel}}
+% \end{macrocode}
+% Draw upper $x$ labels
+% \begin{macrocode}
+\ifDTLverticalbars
+ \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}}}
+ }%
+ }
+\else
+ \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}}}
+ }%
+ }
+\fi
+ \expandafter\pgftext\expandafter[\dtl@textopt]{%
+ \DTLdisplayupperbarlabel{\dtl@upperbarlabel}}
+% \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
+ \FPround{\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}
+%
+%\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{macro}{\DTLmultibarchart}
+% \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.
+% \begin{macrocode}
+ \ifx\DTLbarmax\relax
+ \DTLforeach[#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
+ \FPmax{\DTLbarmax}{\dtl@old}{\dtl@barvar}%
+ \fi
+ }%
+ }%
+ \ifx\dtlbar@yticgap\relax
+ \else
+ \let\dtl@thistick=\dtlbar@yticgap%
+ \whiledo{\DTLisFPopenbetween{\dtl@thistick}{0}{\DTLbarmax}}{%
+ \FPadd{\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}%
+ \DTLforeach[#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}}{%
+ \FPsub{\dtl@thistick}{\dtl@thistick}{\dtlbar@yticgap}%
+ }%
+ \let\DTLnegextent=\dtl@thistick
+ }{}%
+ \fi
+ \fi
+% \end{macrocode}
+% Determine scaling factor
+% \begin{macrocode}
+ \@dtl@tmpcount=\DTLbarchartlength
+ \FPsub{\dtl@extent}{\DTLbarmax}{\DTLnegextent}%
+ \FPdiv{\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@constructticklist\DTLnegextent\DTLbarmax
+ \dtl@unit\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{%
+ \FPround{\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}
+\FPmul{\dtl@tmpi}{\dtl@n}{\DTLbargroupwidth}
+\FPsub{\dtl@tmpii}{\dtl@n}{1}%
+\FPmul{\dtl@tmpii}{\dtl@tmpii}{\dtlbar@groupgap}%
+\FPadd{\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}
+\DTLforeach[#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}
+\FPmul{\dtl@multimidpt}{\DTLbargroupwidth}{0.5}%
+\FPadd{\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}
+\FPadd{\@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}
+\FPadd{\@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
+ }%
+\else
+ \edef\dtl@textopt{%
+ at={\noexpand\pgfpointadd
+ {\noexpand\pgfpointxy{0}{\@dtl@midpt}}
+ {\noexpand\pgfpoint{-\noexpand\DTLbarlabeloffset}{0pt}}},
+ \DTLbarXlabelalign
+ }%
+\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}}}
+ }%
+ }
+\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}}}
+ }%
+ }
+\fi
+ \expandafter\pgftext\expandafter[\dtl@textopt]{%
+ \DTLdisplayuppermultibarlabel{\dtl@thisupperbarlabel}}
+% \end{macrocode}
+% End of loop increment loop variables
+% \begin{macrocode}
+ \FPadd{\@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}
+ \FPadd{\@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
+ \FPround{\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
+%\Finale
+\endinput
diff --git a/Master/texmf-dist/doc/latex/datatool/source/datatool.ins b/Master/texmf-dist/doc/latex/datatool/source/datatool.ins
new file mode 100644
index 00000000000..8966a25bcbe
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/datatool/source/datatool.ins
@@ -0,0 +1,25 @@
+% datatool.ins generated using makedtx version 0.93b 2007/7/23 22:53
+\input docstrip
+
+\preamble
+Copyright (C) 2007 Nicola Talbot, all rights reserved.
+If you modify this file, you must change its name first.
+You are NOT ALLOWED to distribute this file alone. You are NOT
+ALLOWED to take money for the distribution or use of either this
+file or a changed version, except for a nominal charge for copying
+etc.
+\endpreamble
+
+\askforoverwritefalse
+
+\generate{\file{datapie.sty}{\usepreamble\defaultpreamble
+\usepostamble\defaultpostamble\from{datatool.dtx}{datapie.sty,package}}
+\file{dataplot.sty}{\usepreamble\defaultpreamble
+\usepostamble\defaultpostamble\from{datatool.dtx}{dataplot.sty,package}}
+\file{datatool.sty}{\usepreamble\defaultpreamble
+\usepostamble\defaultpostamble\from{datatool.dtx}{datatool.sty,package}}
+\file{databar.sty}{\usepreamble\defaultpreamble
+\usepostamble\defaultpostamble\from{datatool.dtx}{databar.sty,package}}
+}
+
+\endbatchfile
diff --git a/Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc b/Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc
index 2be884767e6..1c36367beb5 100644
--- a/Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc
+++ b/Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc
@@ -90,6 +90,7 @@ depend Package/cv
depend Package/cwpuzzle
depend Package/dashbox
depend Package/dashrule
+depend Package/datatool
depend Package/dateiliste
depend Package/datenumber
depend Package/datetime
diff --git a/Master/tlpkg/tlpsrc/datatool.tlpsrc b/Master/tlpkg/tlpsrc/datatool.tlpsrc
new file mode 100644
index 00000000000..2ab8067985c
--- /dev/null
+++ b/Master/tlpkg/tlpsrc/datatool.tlpsrc
@@ -0,0 +1,2 @@
+name datatool
+category Package