summaryrefslogtreecommitdiff
path: root/Master/texmf-dist
diff options
context:
space:
mode:
authorDr. Clea F. Rees <cfrees@imapmail.org>2009-03-01 20:35:54 +0000
committerDr. Clea F. Rees <cfrees@imapmail.org>2009-03-01 20:35:54 +0000
commitde3f0b6a3f872b5de7a6efb9d84a368e5c059f61 (patch)
tree65b5e1f7f1f5716388d91f55e222a1221a882df4 /Master/texmf-dist
parent98b2e0029dce671be04c9bd02fa94109e0c67ad1 (diff)
datatool new version
git-svn-id: svn://tug.org/texlive/trunk@12277 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist')
-rw-r--r--Master/texmf-dist/bibtex/bst/datatool/databib.bst26
-rw-r--r--Master/texmf-dist/doc/latex/datatool/CHANGES80
-rw-r--r--Master/texmf-dist/doc/latex/datatool/README206
-rw-r--r--Master/texmf-dist/doc/latex/datatool/datatool.pdfbin0 -> 1455516 bytes
-rw-r--r--Master/texmf-dist/doc/latex/datatool/doc/CHANGES32
-rw-r--r--Master/texmf-dist/doc/latex/datatool/doc/datatool.pdfbin1180800 -> 0 bytes
-rw-r--r--Master/texmf-dist/source/latex/datatool/datatool.dtx8925
-rw-r--r--Master/texmf-dist/source/latex/datatool/datatool.ins4
-rw-r--r--Master/texmf-dist/tex/latex/datatool/databar.sty20
-rw-r--r--Master/texmf-dist/tex/latex/datatool/databib.sty149
-rw-r--r--Master/texmf-dist/tex/latex/datatool/datapie.sty4
-rw-r--r--Master/texmf-dist/tex/latex/datatool/dataplot.sty71
-rw-r--r--Master/texmf-dist/tex/latex/datatool/datatool.sty3419
13 files changed, 9749 insertions, 3187 deletions
diff --git a/Master/texmf-dist/bibtex/bst/datatool/databib.bst b/Master/texmf-dist/bibtex/bst/datatool/databib.bst
index c114335a843..7999f9f6c08 100644
--- a/Master/texmf-dist/bibtex/bst/datatool/databib.bst
+++ b/Master/texmf-dist/bibtex/bst/datatool/databib.bst
@@ -7,7 +7,7 @@
%% datatool.dtx (with options: `databib.bst')
%%
%% datatool.dtx
-%% Copyright 2007 Nicola Talbot
+%% Copyright 2009 Nicola Talbot
%%
%% This work may be distributed and/or modified under the
%% conditions of the LaTeX Project Public License, either version 1.3
@@ -52,6 +52,7 @@ ENTRY
pubmed
url
abstract
+ file
}
{}
{ label }
@@ -378,6 +379,16 @@ FUNCTION {format.url}
if$
}
+FUNCTION {format.file}
+{ file empty$
+ { "" }
+ {
+ file
+ "\DTLnewbibitem {File}" swap$ group *
+ }
+ if$
+}
+
FUNCTION {format.address}
{ address empty$
{ "" }
@@ -758,6 +769,7 @@ FUNCTION {article}
format.pubmed output
format.url output
format.abstract output
+ format.file output
fin.entry
}
@@ -799,6 +811,7 @@ FUNCTION {book}
format.pubmed output
format.url output
format.abstract output
+ format.file output
fin.entry
}
@@ -821,6 +834,7 @@ FUNCTION {booklet}
format.pubmed output
format.url output
format.abstract output
+ format.file output
fin.entry
}
@@ -863,6 +877,7 @@ FUNCTION {inbook}
format.pubmed output
format.url output
format.abstract output
+ format.file output
fin.entry
}
@@ -894,6 +909,7 @@ FUNCTION {incollection}
format.pubmed output
format.url output
format.abstract output
+ format.file output
fin.entry
}
@@ -933,6 +949,7 @@ FUNCTION {inproceedings}
format.pubmed output
format.url output
format.abstract output
+ format.file output
fin.entry
}
@@ -977,6 +994,7 @@ FUNCTION {manual}
format.pubmed output
format.url output
format.abstract output
+ format.file output
fin.entry
}
@@ -1001,6 +1019,7 @@ FUNCTION {mastersthesis}
format.pubmed output
format.url output
format.abstract output
+ format.file output
fin.entry
}
@@ -1022,6 +1041,7 @@ FUNCTION {misc}
format.pubmed output
format.url output
format.abstract output
+ format.file output
fin.entry
empty.misc.check
}
@@ -1047,6 +1067,7 @@ FUNCTION {phdthesis}
format.pubmed output
format.url output
format.abstract output
+ format.file output
fin.entry
}
@@ -1090,6 +1111,7 @@ FUNCTION {proceedings}
format.pubmed output
format.url output
format.abstract output
+ format.file output
fin.entry
}
@@ -1113,6 +1135,7 @@ FUNCTION {techreport}
format.pubmed output
format.url output
format.abstract output
+ format.file output
fin.entry
}
@@ -1131,6 +1154,7 @@ FUNCTION {unpublished}
format.pubmed output
format.url output
format.abstract output
+ format.file output
format.date output
fin.entry
}
diff --git a/Master/texmf-dist/doc/latex/datatool/CHANGES b/Master/texmf-dist/doc/latex/datatool/CHANGES
new file mode 100644
index 00000000000..4b9d5b36183
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/datatool/CHANGES
@@ -0,0 +1,80 @@
+v2.0 (2009/02/27):
+ datatool.sty:
+
+ * Rewritten database internal representation to make the code
+ faster (thanks to Morten H\o gholm for the suggestion)
+ * added etex as a required package
+ * Database columns can now have an associated header (in addition
+ to the key)
+ * added \DTLdisplaydb and \DTLdisplaylongdb
+ * added \DTLremoverow
+ * \DTLloaddb, \DTLloadrawdb:
+ - removed unnecessary checks to determine if database
+ exists when adding entries.
+ - added optional argument
+ - can now also load files without header row
+ * \DTLsumforkeys, \DTLmeanforkeys, \DTLvarianceforkeys,
+ \DTLsdforkeys, \DTLminforkeys and \DTLmaxforkeys now have a
+ second optional argument
+ * added \DTLsumcolumn, \DTLmeanforcolumn, \DTLvarianceforcolumn,
+ \DTLsdforcolumn, \DTLminforcolumn and \DTLmaxforcolumn
+ * added \dtlforeachkey
+ * added \dtlforint and \dtlgforint
+ * added \dtlforcolumn and \dtlforcolumnidx
+ * added \DTLcolumncount
+ * added starred versions of:
+ - \DTLifdbempty
+ - \DTLnewrow
+ * added \DTLifhaskey
+ * added \DTLgetcolumnindex
+ * added \DTLunsettype, \DTLstringtype, \DTLinttype, \DTLrealtype
+ and \DTLcurrencytype
+ * added \DTLgetdatatype
+ * removed \@dtl@setidtype
+ * removed \@dtl@setkeys
+ * removed \@dtl@getidtype
+ * removed \@dtl@ifrowcontains
+ * removed \dtl@getentryvalue
+ * removed \dtl@getentryid
+ * added \dtlgetentryfromcurrentrow
+ * added \dtlforcolumnindex
+
+ dataplot.sty
+ * fixed bug causing ! Argument of \pgfmath@afterquick has an extra }
+ error
+
+ databar.sty
+ * added \DTLeverybarhook
+
+v1.01 (2007/08/17) :
+ * Added databib package.
+
+ * datatool.sty:
+
+ - Fixed bug in datatool caused when certain commands occur
+ in database entries or when the data type is tested.
+ - Fixed bug in \DTLsubstituteall (caused problems when certain
+ - commands occurred in string)
+ - Added \DTLsplitstring
+ - Added \DTLifSubString and \DTLisSubString
+ - Added \DTLifStartsWith and \DTLisPrefix
+ - Added case insensitive string tests
+ - \DTLinitials and \DTLstoreinitials now work with ~ and \space
+ - \DTLinitials and \DTLstoreinitials now use \DTLinitialhyphen
+ - Added \dtlcompare (no longer using compare.tex)
+ - Added \DTLgetvalueforkey
+ - Added \DTLgetrowforkey
+ - Added optional argument to \DTLsort
+ - Fixed bug causing expansion in \DTLsort
+ - Fixed bug in \DTLsdforall and \DTLvarianceforall
+ - Removed extraneous spaces in \DTLaddall, \DTLminall,
+ \DTLmaxall, \DTLmeanforall, \DTLsdforall and \DTLvarianceforall
+ - Fixed bug in \DTLiflastrow
+ - Fixed bug in \DTLremovecurrentrow
+
+ * Manual:
+ - added code that produces fig "Student Marks (with average scores".
+ - fixed typos in examples "Editing Database Rows" & "Mail Merging"
+ - added section on null values
+
+v1.0 (2007/07/23) : Initial Release
diff --git a/Master/texmf-dist/doc/latex/datatool/README b/Master/texmf-dist/doc/latex/datatool/README
index 581ed50375f..ad9f718294a 100644
--- a/Master/texmf-dist/doc/latex/datatool/README
+++ b/Master/texmf-dist/doc/latex/datatool/README
@@ -1,101 +1,105 @@
-LaTeX Bundle : datatool v1.01 (datatool.sty, datapie.sty, dataplot.sty, databar.sty, databib.sty)
-
-Last Modified : 17 Aug 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.
-
-databib.sty:
-
- Provides commands to convert a BibTeX database into a datatool
- database.
-
-*The datatool bundle replaces the csvtools bundle which is now obsolete.*
-
-The datatool.sty package requires the following packages/files:
-
-xkeyval
-xfor
-fp
-substr
-
-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/
-
+LaTeX Bundle : datatool v2.0 (datatool.sty, datapie.sty, dataplot.sty, databar.sty, databib.sty)
+
+Last Modified : 27 February 2009
+
+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.
+
+databib.sty:
+
+ Provides commands to convert a BibTeX database into a datatool
+ database.
+
+*The datatool bundle replaces the csvtools bundle which is now obsolete.*
+
+REQUIRED PACKAGES:
+
+The datatool.sty package requires the following packages/files:
+
+xkeyval
+ifthen
+xfor
+fp
+substr
+etex
+
+The datapie.sty, dataplot.sty and databar.sty packages
+additionally require the tikz/pgf bundle.
+
+*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/datatool.pdf b/Master/texmf-dist/doc/latex/datatool/datatool.pdf
new file mode 100644
index 00000000000..d45aac71de9
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/datatool/datatool.pdf
Binary files differ
diff --git a/Master/texmf-dist/doc/latex/datatool/doc/CHANGES b/Master/texmf-dist/doc/latex/datatool/doc/CHANGES
deleted file mode 100644
index a898c349e78..00000000000
--- a/Master/texmf-dist/doc/latex/datatool/doc/CHANGES
+++ /dev/null
@@ -1,32 +0,0 @@
-v1.01 (2007/08/17) :
- * Added databib package.
-
- * datatool.sty:
-
- - Fixed bug in datatool caused when certain commands occur
- in database entries or when the data type is tested.
- - Fixed bug in \DTLsubstituteall (caused problems when certain
- - commands occurred in string)
- - Added \DTLsplitstring
- - Added \DTLifSubString and \DTLisSubString
- - Added \DTLifStartsWith and \DTLisPrefix
- - Added case insensitive string tests
- - \DTLinitials and \DTLstoreinitials now work with ~ and \space
- - \DTLinitials and \DTLstoreinitials now use \DTLinitialhyphen
- - Added \dtlcompare (no longer using compare.tex)
- - Added \DTLgetvalueforkey
- - Added \DTLgetrowforkey
- - Added optional argument to \DTLsort
- - Fixed bug causing expansion in \DTLsort
- - Fixed bug in \DTLsdforall and \DTLvarianceforall
- - Removed extraneous spaces in \DTLaddall, \DTLminall,
- \DTLmaxall, \DTLmeanforall, \DTLsdforall and \DTLvarianceforall
- - Fixed bug in \DTLiflastrow
- - Fixed bug in \DTLremovecurrentrow
-
- * Manual:
- - added code that produces fig "Student Marks (with average scores".
- - fixed typos in examples "Editing Database Rows" & "Mail Merging"
- - added section on null values
-
-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
deleted file mode 100644
index eb622488c8e..00000000000
--- a/Master/texmf-dist/doc/latex/datatool/doc/datatool.pdf
+++ /dev/null
Binary files differ
diff --git a/Master/texmf-dist/source/latex/datatool/datatool.dtx b/Master/texmf-dist/source/latex/datatool/datatool.dtx
index f2afe8ec4b3..fe88d5377eb 100644
--- a/Master/texmf-dist/source/latex/datatool/datatool.dtx
+++ b/Master/texmf-dist/source/latex/datatool/datatool.dtx
@@ -2,12 +2,12 @@
% datatool.dtx generated using makedtx version 0.94b (c) Nicola Talbot
% Command line args:
% -macrocode "databib.bst"
-% -src "datatool.sty=>datatool.sty"
-% -src "datapie.sty=>datapie.sty"
-% -src "dataplot.sty=>dataplot.sty"
-% -src "databar.sty=>databar.sty"
-% -src "databib.sty=>databib.sty"
-% -src "databib.bst=>databib.bst"
+% -src "datatool.sty\Z=>datatool.sty"
+% -src "datapie.sty\Z=>datapie.sty"
+% -src "dataplot.sty\Z=>dataplot.sty"
+% -src "databar.sty\Z=>databar.sty"
+% -src "databib.sty\Z=>databib.sty"
+% -src "databib.bst\Z=>databib.bst"
% -author "Nicola Talbot"
% -dir "source"
% -setambles ".*\.bst=>\nopreamble\usepreamble\defaultpreamble\nopostamble"
@@ -15,7 +15,7 @@
% -doc "manual.tex"
% -codetitle "datatool.sty"
% datatool
-% Created on 2007/8/19 14:27
+% Created on 2009/2/27 13:27
%\fi
%\iffalse
%<*package>
@@ -38,7 +38,7 @@
%\fi
% \iffalse
% Doc-Source file to use with LaTeX2e
-% Copyright (C) 2007 Nicola Talbot, all rights reserved.
+% Copyright (C) 2009 Nicola Talbot, all rights reserved.
% \fi
% \iffalse
%<*driver>
@@ -49,6 +49,9 @@
\usepackage{textcomp}
\usepackage{graphicx}
\usepackage{colortbl}
+\usepackage{cmap}
+\usepackage[T1]{fontenc}
+\usepackage[utf8]{inputenc}
\usepackage[colorlinks,
bookmarks,
hyperindex=false,
@@ -77,7 +80,7 @@
\makeatother
\RecordChanges
\PageIndex
-\CheckSum{13202}
+\CheckSum{15413}
\newcommand*{\sty}[1]{\textsf{#1}}
\newcommand*{\env}[1]{\textsf{#1}}
@@ -100,7 +103,8 @@
\newsavebox\defsbox
\newlength\defwidth
-\newenvironment{definition}{%
+\newenvironment{definition}[1][]{%
+\def\defarg{#1}%
\setlength{\fboxsep}{4pt}\setlength{\fboxrule}{1.25pt}%
\begin{lrbox}{\defsbox}%
\setlength\defwidth\linewidth
@@ -112,7 +116,7 @@
\end{lrbox}%
\vskip10pt
\noindent
-\fcolorbox{black}{defbackground}{\usebox\defsbox}%
+\defarg\fcolorbox{black}{defbackground}{\usebox\defsbox}%
\vskip10pt
}
@@ -132,6 +136,9 @@
\newcommand*{\pkgopt}[2][datatool]{\textsf{#2}\index
{#1 package options=\textsf{#1} package options>#2=\textsf{#2}|hyperpage}}
+\newcommand*{\cmdopt}[2]{\textsf{#2}\index{#1 options=\cs{#1}
+options>#2=\textsf{#2}|hyperpage}}
+
\newcounter{example}
\newcommand*{\examplename}{example}
\makeatletter
@@ -166,7 +173,7 @@
%\MakeShortVerb{"}
%\DeleteShortVerb{\|}
%
-% \title{datatool v 1.01: Databases and data manipulation}
+% \title{datatool v 2.0: Databases and data manipulation}
% \author{Nicola L.C. Talbot\\[10pt]
%School of Computing Sciences\\
%University of East Anglia\\
@@ -174,7 +181,7 @@
%NR4 7TJ. United Kingdom.\\
%\url{http://theoval.cmp.uea.ac.uk/~nlct/}}
%
-% \date{17th August 2007}
+% \date{27th February 2009}
% \maketitle
%\tableofcontents
%\listofexamples
@@ -192,14 +199,14 @@
%\begin{itemize}
%\item Create or load databases.
%\item Sort rows of a database (either numerically or alphabetically,
-%ascending or descending.)
+%ascending or descending).
%\item Perform repetitive operations on each row of a database
-%(e.g.\ mail merging.) Conditions may be imposed to exclude rows.
+%(e.g.\ mail merging). Conditions may be imposed to exclude rows.
%\item Determine whether 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.)
+%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.
@@ -233,7 +240,8 @@
%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.)
+%impressions. The \sty{pgf} manual provides a more in-depth
+%discussion on the matter.)
%
%The \sty{dataplot} package can be used to convert a database into
%a two dimensional plot using markers and/or lines. Three dimensional
@@ -252,14 +260,13 @@
%\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.)
+%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}
+%\begin{definition}[\DescribeMacro{\DTLsetnumberchars}]%
%\cs{DTLsetnumberchars}\marg{number group character}\marg{decimal character}
%\end{definition}
%Note that scientific notation is not supported, and the number group
@@ -273,8 +280,7 @@
%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}
+%\begin{definition}[\DescribeMacro{\DTLnewcurrencysymbol}]%
%\cs{DTLnewcurrencysymbol}\marg{symbol}
%\end{definition}
%
@@ -288,9 +294,7 @@
%
%The following conditionals are provided by the \sty{datatool}
%package:
-%
-%\DescribeMacro{\DTLifint}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLifint}]%
%\cs{DTLifint}\marg{text}\marg{true part}\marg{false part}
%\end{definition}
%If \meta{text} is an integer then do \meta{true part}, otherwise
@@ -334,8 +338,7 @@
%\DTLsetnumberchars{,}{.}\relax
%\DTLifint{2,536m}{integer}{not an integer}.
%
-%\DescribeMacro{\DTLifreal}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLifreal}]%
%\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
@@ -379,8 +382,7 @@
%\DTLsetnumberchars{,}{.}\relax
%\DTLifreal{\$1.00}{real}{not real}.
%
-%\DescribeMacro{\DTLifcurrency}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLifcurrency}]%
%\cs{DTLifcurrency}\marg{text}\marg{true part}\marg{false part}
%\end{definition}
%If \meta{text} is currency, then do \meta{true part}, otherwise
@@ -448,8 +450,7 @@
%\DTLnewcurrencysymbol{\euro}\relax
%\DTLifcurrency{\euro5.99}{currency}{not currency}.
%
-%\DescribeMacro{\DTLifcurrencyunit}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLifcurrencyunit}]%
%\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
@@ -469,8 +470,7 @@
%\def\cost{\euro10.50}\relax
%\DTLifcurrencyunit{\cost}{\euro}{euros}{not euros}.
%
-%\DescribeMacro{\DTLifnumerical}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLifnumerical}]%
%\cs{DTLifnumerical}\marg{text}\marg{true part}\marg{false part}
%\end{definition}
%If \meta{text} is numerical (either an integer, real number or
@@ -502,15 +502,13 @@
%\DTLsetnumberchars{,}{.}\relax
%\DTLifnumerical{\$1,000.0}{number}{string}.
%
-%\DescribeMacro{\DTLifstring}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLifstring}]%
%\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}
+%\begin{definition}[\DescribeMacro{\DTLifcasedatatype}]%
%\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}
@@ -523,14 +521,13 @@
%produces:
%\DTLifcasedatatype{1,000}{string}{integer}{real}{currency}.
%
-%\DescribeMacro{\DTLifnumeq}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLifnumeq}]%
%\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
+%currency). The currency symbol is ignored when determining
%equality. For example
%\begin{verbatim}
%\DTLifnumeq{\pounds10.50}{10.5}{true}{false}
@@ -544,12 +541,10 @@
%produces:
%\DTLifnumeq{\pounds10.50}{\$10.50}{true}{false}.
%
-%\DescribeMacro{\DTLifstringeq}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLifstringeq}]%
%\cs{DTLifstringeq}\marg{string1}\marg{string2}\marg{true part}\marg{false part}
%\end{definition}
-%\DescribeMacro{\DTLifstringeq*}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLifstringeq*}]%
%\cs{DTLifstringeq*}\marg{string1}\marg{string2}\marg{true part}\marg{false part}
%\end{definition}
%If \meta{string1} and \meta{string2} are the same, then do
@@ -596,12 +591,10 @@
%produces:
%\DTLifstringeq{an apple}{an apple}{true}{false}.
%
-%\DescribeMacro{\DTLifeq}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLifeq}]%
%\cs{DTLifeq}\marg{arg1}\marg{arg2}\marg{true part}\marg{false part}
%\end{definition}
-%\DescribeMacro{\DTLifeq*}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLifeq*}]%
%\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
@@ -609,22 +602,19 @@
%\cs{DTLifstringeq} (when using \cs{DTLifeq}) or \cs{DTLifstringeq*}
%(when using \cs{DTLifeq*}).
%
-%\DescribeMacro{\DTLifnumlt}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLifnumlt}]%
%\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.)
+%currency).
%
-%\DescribeMacro{\DTLifstringlt}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLifstringlt}]%
%\cs{DTLifstringlt}\marg{string1}\marg{string2}\marg{true
%part}\marg{false part}
%\end{definition}
-%\DescribeMacro{\DTLifstringlt*}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLifstringlt*}]%
%\cs{DTLifstringlt*}\marg{string1}\marg{string2}\marg{true
%part}\marg{false part}
%\end{definition}
@@ -661,12 +651,10 @@
%produces:
%\DTLifstringlt*{B}{a}{less}{not less}.
%
-%\DescribeMacro{\DTLiflt}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLiflt}]%
%\cs{DTLiflt}\marg{arg1}\marg{arg2}\marg{true part}\marg{false part}
%\end{definition}
-%\DescribeMacro{\DTLiflt*}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLiflt*}]%
%\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
@@ -674,22 +662,19 @@
%to \cs{DTLstringlt} (when using \cs{DTLiflt}) or
%\cs{DTLstringlt*} (when using \cs{DTLiflt*}).
%
-%\DescribeMacro{\DTLifnumgt}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLifnumgt}]%
%\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.)
+%currency).
%
-%\DescribeMacro{\DTLifstringgt}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLifstringgt}]%
%\cs{DTLifstringgt}\marg{string1}\marg{string2}\marg{true
%part}\marg{false part}
%\end{definition}
-%\DescribeMacro{\DTLifstringgt*}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLifstringgt*}]%
%\cs{DTLifstringgt*}\marg{string1}\marg{string2}\marg{true
%part}\marg{false part}
%\end{definition}
@@ -726,12 +711,10 @@
%produces:
%\DTLifstringgt*{B}{a}{greater}{not greater}.
%
-%\DescribeMacro{\DTLifgt}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLifgt}]%
%\cs{DTLifgt}\marg{arg1}\marg{arg2}\marg{true part}\marg{false part}
%\end{definition}
-%\DescribeMacro{\DTLifgt*}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLifgt*}]%
%\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
@@ -739,14 +722,13 @@
%to \cs{DTLstringgt} (when using \cs{DTLifgt}) or
%\cs{DTLstringgt*} (when using \cs{DTLifgt*}).
%
-%\DescribeMacro{\DTLifnumclosedbetween}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLifnumclosedbetween}]%
%\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
+%currency). The currency symbol is ignored when determining
%equality. For example:
%\begin{verbatim}
%\DTLifnumclosedbetween{5.4}{5}{7}{inside}{outside}
@@ -760,12 +742,10 @@
%produces:
%\DTLifnumclosedbetween{5}{5}{7}{inside}{outside}.
%
-%\DescribeMacro{\DTLifstringclosedbetween}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLifstringclosedbetween}]%
%\cs{DTLifstringclosedbetween}\marg{string}\marg{min}\marg{max}\marg{true part}\marg{false part}
%\end{definition}
-%\DescribeMacro{\DTLifstringclosedbetween*}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLifstringclosedbetween*}]%
%\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
@@ -773,12 +753,10 @@
%\meta{min} or \meta{max}. The starred version ignores the case,
%the unstarred version is case sensitive.
%
-%\DescribeMacro{\DTLifclosedbetween}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLifclosedbetween}]%
%\cs{DTLifclosedbetween}\marg{arg}\marg{min}\marg{max}\marg{true part}\marg{false part}
%\end{definition}
-%\DescribeMacro{\DTLifclosedbetween*}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLifclosedbetween*}]%
%\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
@@ -787,14 +765,13 @@
%or
%\cs{DTLifstringclosedbetween*} (when using \cs{DTLifclosedbetween*}).
%
-%\DescribeMacro{\DTLifnumopenbetween}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLifnumopenbetween}]%
%\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
+%currency). Again, the currency symbol is ignored when determining
%equality. For example:
%\begin{verbatim}
%\DTLifnumopenbetween{5.4}{5}{7}{inside}{outside}
@@ -808,12 +785,10 @@
%produces:
%\DTLifnumopenbetween{5}{5}{7}{inside}{outside}.
%
-%\DescribeMacro{\DTLifstringopenbetween}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLifstringopenbetween}]%
%\cs{DTLifstringopenbetween}\marg{string}\marg{min}\marg{max}\marg{true part}\marg{false part}
%\end{definition}
-%\DescribeMacro{\DTLifstringopenbetween*}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLifstringopenbetween*}]%
%\cs{DTLifstringopenbetween*}\marg{string}\marg{min}\marg{max}\marg{true part}\marg{false part}
%\end{definition}
%This determines if \meta{string} is between \meta{min} and
@@ -821,12 +796,10 @@
%The starred version ignores the case,
%the unstarred version is case sensitive.
%
-%\DescribeMacro{\DTLifopenbetween}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLifopenbetween}]%
%\cs{DTLifopenbetween}\marg{arg}\marg{min}\marg{max}\marg{true part}\marg{false part}
%\end{definition}
-%\DescribeMacro{\DTLifopenbetween*}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLifopenbetween*}]%
%\cs{DTLifopenbetween*}\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
@@ -834,28 +807,25 @@
%\cs{DTLifstringopenbetween} (when using \cs{DTLifopenbetween})
%\cs{DTLifstringopenbetween*} (when using \cs{DTLifopenbetween*}).
%
-%\DescribeMacro{\DTLifFPclosedbetween}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLifFPclosedbetween}]%
%\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.)
+%a decimal point).
%
-%\DescribeMacro{\DTLifFPopenbetween}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLifFPopenbetween}]%
%\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.)
+%a decimal point).
%
-%\DescribeMacro{\DTLifAllUpperCase}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLifAllUpperCase}]%
%\cs{DTLifAllUpperCase}\marg{string}\marg{true part}\marg{false part}
%\end{definition}
%Tests if \meta{string} is all upper case. For example:
@@ -886,8 +856,7 @@
%produces:
%\DTLifAllUpperCase{MAN{\OE}UVRE}{all upper}{not all upper}.
%
-%\DescribeMacro{\DTLifAllLowerCase}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLifAllLowerCase}]%
%\cs{DTLifAllLowerCase}\marg{string}\marg{true part}\marg{false part}
%\end{definition}
%Tests if \meta{string} is all lower case. For example:
@@ -918,8 +887,7 @@
%produces:
%\DTLifAllLowerCase{man{\oe}uvre}{all lower}{not all lower}.
%
-%\DescribeMacro{\DTLifSubString}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLifSubString}]%
%\cs{DTLifSubString}\marg{string}\marg{substring}\marg{true
%part}\marg{false part}
%\end{definition}
@@ -959,8 +927,7 @@
%produces:
%\DTLifSubString{An Apple}{app}{is substring}{isn't substring}.
%
-%\DescribeMacro{\DTLifStartsWith}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLifStartsWith}]%
%\cs{DTLifStartsWith}\marg{string}\marg{substring}\marg{true
%part}\marg{false part}
%\end{definition}
@@ -995,10 +962,11 @@
%\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}.
+%\cs{whiledo}. These may be used with the boolean operations
+%\cs{not}, \cs{and} and \cs{or} provided by the \sty{ifthen} package.
+%See the \sty{ifthen} documentation for further details.
%
-%\DescribeMacro{\DTLisstring}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLisstring}]%
%\cs{DTLisstring}\marg{text}
%\end{definition}
%Tests if \meta{text} is a string. For example:
@@ -1008,11 +976,10 @@
%produces:
%\ifthenelse{\DTLisstring{some text}}{string}{not a string}.
%
-%\DescribeMacro{\DTLisnumerical}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLisnumerical}]%
%\cs{DTLisnumerical}\marg{text}
%\end{definition}
-%Tests if \meta{text} is numerical (i.e.\ not a string.) For example:
+%Tests if \meta{text} is numerical (i.e.\ not a string). For example:
%\begin{verbatim}
%\ifthenelse{\DTLisnumerical{\$10.95}}{numerical}{not numerical}
%\end{verbatim}
@@ -1031,7 +998,7 @@
%\begin{verbatim}
%\ifthenelse{\DTLisnumerical{\pounds10.95}}{numerical}{not numerical}
%\end{verbatim}
-%produces
+%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:
@@ -1046,12 +1013,11 @@
%\def\cost{\pounds10.95}%
%\ifthenelse{\DTLisnumerical{\noexpand\cost}}{numerical}{not numerical}
%\end{verbatim}
-%produces
+%produces:
%\def\cost{\pounds10.95}\relax
%\ifthenelse{\DTLisnumerical{\noexpand\cost}}{numerical}{not numerical}.
%
-%\DescribeMacro{\DTLiscurrency}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLiscurrency}]%
%\cs{DTLiscurrency}\marg{text}
%\end{definition}
%Tests if \meta{text} is currency. For example:
@@ -1064,18 +1030,17 @@
%The same warning given above for \cs{DTLisnumerical} also applies
%here.
%
-%\DescribeMacro{\DTLiscurrencyunit}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLiscurrencyunit}]%
%\cs{DTLiscurrencyunit}\marg{text}\marg{symbol}
%\end{definition}
-%Tests if \meta{text} is currency, and uses \meta{symbol} as the unit
+%Tests if \meta{text} is currency and that currency 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}
+%\ifthenelse{\DTLiscurrencyunit{\$6.99}{\$}}{dollars}{not dollars}.
%Another example:
%\begin{verbatim}
%\def\cost{\euro10.50}%
@@ -1087,20 +1052,18 @@
%\ifthenelse{\DTLiscurrencyunit{\noexpand\cost}{\noexpand\euro}}%
%{euros}{not euros}. Again note the use of \cs{noexpand}.
%
-%\DescribeMacro{\DTLisreal}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLisreal}]%
%\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:
+%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}
+%\begin{definition}[\DescribeMacro{\DTLisint}]%
%\cs{DTLisint}\marg{text}
%\end{definition}
%Tests if \meta{text} is an integer. For example:
@@ -1110,8 +1073,7 @@
%produces:
%\ifthenelse{\DTLisint{153}}{integer}{not an integer}.
%
-%\DescribeMacro{\DTLislt}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLislt}]%
%\cs{DTLislt}\marg{arg1}\marg{arg2}
%\end{definition}
%This checks if \meta{arg1} is less than \meta{arg2}. As with
@@ -1121,8 +1083,7 @@
%version of this command, but you can instead use \cs{DTLisilt}
%to ignore the case.)
%
-%\DescribeMacro{\DTLisilt}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLisilt}]%
%\cs{DTLisilt}\marg{arg1}\marg{arg2}
%\end{definition}
%This checks if \meta{arg1} is less than \meta{arg2}. As with
@@ -1130,8 +1091,7 @@
%a numerical comparison is used, otherwise a case insensitive
%alphabetical comparison is used.
%
-%\DescribeMacro{\DTLisgt}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLisgt}]%
%\cs{DTLisgt}\marg{arg1}\marg{arg2}
%\end{definition}
%This checks if \meta{arg1} is greater than \meta{arg2}. As with
@@ -1141,8 +1101,7 @@
%version of this command, instead use \cs{DTLisigt} to
%ignore the case.)
%
-%\DescribeMacro{\DTLisigt}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLisigt}]%
%\cs{DTLisigt}\marg{arg1}\marg{arg2}
%\end{definition}
%This checks if \meta{arg1} is greater than \meta{arg2}. As with
@@ -1150,8 +1109,7 @@
%a numerical comparison is used, otherwise a case insensitive
%alphabetical comparison is used.
%
-%\DescribeMacro{\DTLiseq}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLiseq}]%
%\cs{DTLiseq}\marg{arg1}\marg{arg2}
%\end{definition}
%This checks if \meta{arg1} is equal to \meta{arg2}. As with
@@ -1160,8 +1118,7 @@
%alphabetical comparison is used. (Note that there is no starred
%version of this command, instead use \cs{DTLisieq}.)
%
-%\DescribeMacro{\DTLisieq}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLisieq}]%
%\cs{DTLisieq}\marg{arg1}\marg{arg2}
%\end{definition}
%This checks if \meta{arg1} is equal to \meta{arg2}. As with
@@ -1169,108 +1126,96 @@
%a numerical comparison is used, otherwise a case insensitive
%alphabetical comparison is used.
%
-%\DescribeMacro{\DTLisclosedbetween}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLisclosedbetween}]%
%\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
+%\meta{max} (end points included). As with
%\cs{DTLifclosedbetween}, if the arguments are numerical,
%a numerical comparison is used, otherwise a case sensitive
%alphabetical comparison is used. (Note that there is no starred
%version of this command, instead use \cs{DTLisiclosedbetween}.)
%
-%\DescribeMacro{\DTLisiclosedbetween}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLisiclosedbetween}]%
%\cs{DTLisiclosedbetween}\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
+%\meta{max} (end points included). As with
%\cs{DTLifclosedbetween*}, if the arguments are numerical,
%a numerical comparison is used, otherwise a case insensitive
%alphabetical comparison is used.
%
-%\DescribeMacro{\DTLisopenbetween}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLisopenbetween}]%
%\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
+%\meta{max} (end points excluded). As with
%\cs{DTLifopenbetween}, if the arguments are numerical,
%a numerical comparison is used, otherwise a case sensitive
%alphabetical comparison is used. (Note that there is no starred
%version of this command, instead use \cs{DTLisiopenbetween}.)
%
-%\DescribeMacro{\DTLisiopenbetween}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLisiopenbetween}]%
%\cs{DTLisiopenbetween}\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
+%\meta{max} (end points excluded). As with
%\cs{DTLifopenbetween*}, if the arguments are numerical,
%a numerical comparison is used, otherwise a case insensitive
%alphabetical comparison is used.
%
-%\DescribeMacro{\DTLisFPlt}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLisFPlt}]%
%\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.)
+%separators, no currency and a full stop as a decimal point).
%
-%\DescribeMacro{\DTLisFPlteq}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLisFPlteq}]%
%\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.)
+%separators, no currency and a full stop as a decimal point).
%
-%\DescribeMacro{\DTLisFPgt}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLisFPgt}]%
%\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.)
+%separators, no currency and a full stop as a decimal point).
%
-%\DescribeMacro{\DTLisFPgteq}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLisFPgteq}]%
%\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.)
+%separators, no currency and a full stop as a decimal point).
%
-%\DescribeMacro{\DTLisFPeq}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLisFPeq}]%
%\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.)
+%separators, no currency and a full stop as a decimal point).
%
-%\DescribeMacro{\DTLisFPclosedbetween}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLisFPclosedbetween}]%
%\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
+%\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.)
+%separators, no currency and a full stop as a decimal point).
%
-%\DescribeMacro{\DTLisFPopenbetween}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLisFPopenbetween}]%
%\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
+%\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.)
+%separators, no currency and a full stop as a decimal point).
%
-%\DescribeMacro{\DTLisSubString}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLisSubString}]%
%\cs{DTLisSubString}\marg{string}\marg{substring}
%\end{definition}
%This checks if \meta{substring} is contained in \meta{string}.
@@ -1278,8 +1223,7 @@
%\cs{DTLisSubString}. This command performs a case sensitive
%match.
%
-%\DescribeMacro{\DTLisPrefix}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLisPrefix}]%
%\cs{DTLisPrefix}\marg{string}\marg{prefix}
%\end{definition}
%This checks if \meta{string} starts with \meta{prefix}.
@@ -1295,8 +1239,7 @@
%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}
+%\begin{definition}[\DescribeMacro{\DTLconverttodecimal}]%
%\cs{DTLconverttodecimal}\marg{num}\marg{cmd}
%\end{definition}
%The decimal number will be stored in \meta{cmd} which must be
@@ -1305,12 +1248,11 @@
%\DTLconverttodecimal{1,563.54}{\mynum}
%\end{verbatim}
%\DTLconverttodecimal{1,563.54}{\mynum}\relax
-%will define \cs{mynum} to be \texttt{\mynum}. The command
+%will define \cs{mynum} to be \texttt{\mynum}. The command \cs{mynum}
%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}
+%\begin{definition}[\DescribeMacro{\DTLdecimaltolocale}]%
%\cs{DTLdecimaltolocale}\marg{number}\marg{cmd}
%\end{definition}
%This converts a plain decimal number \meta{number} (that uses a full
@@ -1323,8 +1265,7 @@
%\DTLdecimaltolocale{6795.3}{\mynum}
%will define \cs{mynum} to be \texttt{\mynum}.
%
-%\DescribeMacro{\DTLdecimaltocurrency}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLdecimaltocurrency}]%
%\cs{DTLdecimaltocurrency}\marg{number}\marg{cmd}
%\end{definition}
%This will convert a plain decimal number \meta{number} into a
@@ -1347,8 +1288,7 @@
%\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}
+%\begin{definition}[\DescribeMacro{\DTLsetdefaultcurrency}]%
%\cs{DTLsetdefaultcurrency}\marg{symbol}
%\end{definition}
%For example:
@@ -1366,12 +1306,11 @@
%back into the locale format using
%\cs{DTLdecimaltolocale} or \cs{DTLdecimaltocurrency}.
%
-%\DescribeMacro{\DTLadd}
-%\begin{definition}
+%
+%\begin{definition}[\DescribeMacro{\DTLadd}]%
%\cs{DTLadd}\marg{cmd}\marg{num1}\marg{num2}
%\end{definition}
-%\DescribeMacro{\DTLgadd}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLgadd}]%
%\cs{DTLgadd}\marg{cmd}\marg{num1}\marg{num2}
%\end{definition}
%This sets the control sequence \meta{cmd} to \meta{num1}+\meta{num2}.
@@ -1384,8 +1323,8 @@
%\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:
+%\cs{DTLconverttodecimal} can convert currency to a real
+%number, you can also add prices. For example:
%\begin{verbatim}
%\DTLadd{\result}{\pounds3,562.65}{\pounds452.2}\result
%\end{verbatim}
@@ -1410,12 +1349,10 @@
%produces:
%\DTLadd{\result}{3,562.65}{\$452.2}\result.
%
-%\DescribeMacro{\DTLaddall}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLaddall}]%
%\cs{DTLaddall}\marg{cmd}\marg{number list}
%\end{definition}
-%\DescribeMacro{\DTLgaddall}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLgaddall}]%
%\cs{DTLgaddall}\marg{cmd}\marg{number list}
%\end{definition}
%This sets the control sequence \meta{cmd} to the sum of all
@@ -1435,12 +1372,10 @@
%produces:
%\DTLaddall{\total}{{1,525},{2,340},500}\total.
%
-%\DescribeMacro{\DTLsub}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLsub}]%
%\cs{DTLsub}\marg{cmd}\marg{num1}\marg{num2}
%\end{definition}
-%\DescribeMacro{\DTLgsub}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLgsub}]%
%\cs{DTLgsub}\marg{cmd}\marg{num1}\marg{num2}
%\end{definition}
%This sets the control sequence \meta{cmd} to
@@ -1456,12 +1391,10 @@
%\DTLsub{\result}{3,562.65}{412.2}\result. As with \cs{DTLadd},
%\meta{num1} and \meta{num2} may be currency.
%
-%\DescribeMacro{\DTLmul}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLmul}]%
%\cs{DTLmul}\marg{cmd}\marg{num1}\marg{num2}
%\end{definition}
-%\DescribeMacro{\DTLgmul}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLgmul}]%
%\cs{DTLgmul}\marg{cmd}\marg{num1}\marg{num2}
%\end{definition}
%This sets the control sequence \meta{cmd} to
@@ -1494,12 +1427,10 @@
%which will produce:
%\DTLmul{\result}{\$2}{\pounds568.95}\result.
%
-%\DescribeMacro{\DTLdiv}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLdiv}]%
%\cs{DTLdiv}\marg{cmd}\marg{num1}\marg{num2}
%\end{definition}
-%\DescribeMacro{\DTLgdiv}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLgdiv}]%
%\cs{DTLgdiv}\marg{cmd}\marg{num1}\marg{num2}
%\end{definition}
%This sets the control sequence \meta{cmd} to
@@ -1527,12 +1458,10 @@
%will produce:
%\DTLdiv{\result}{\$501}{2}\result.
%
-%\DescribeMacro{\DTLabs}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLabs}]%
%\cs{DTLabs}\marg{cmd}\marg{num}
%\end{definition}
-%\DescribeMacro{\DTLgabs}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLgabs}]%
%\cs{DTLgabs}\marg{cmd}\marg{num}
%\end{definition}
%This sets \meta{cmd} to the absolute value of \meta{num}.
@@ -1544,12 +1473,10 @@
%produces:
%\DTLabs{\result}{-\pounds2.50}\result.
%
-%\DescribeMacro{\DTLneg}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLneg}]%
%\cs{DTLneg}\marg{cmd}\marg{num}
%\end{definition}
-%\DescribeMacro{\DTLgneg}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLgneg}]%
%\cs{DTLgneg}\marg{cmd}\marg{num}
%\end{definition}
%This sets \meta{cmd} to the negative of \meta{num}.
@@ -1561,12 +1488,10 @@
%produces:
%\DTLneg{\result}{\pounds2.50}\result.
%
-%\DescribeMacro{\DTLsqrt}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLsqrt}]%
%\cs{DTLsqrt}\marg{cmd}\marg{num}
%\end{definition}
-%\DescribeMacro{\DTLgsqrt}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLgsqrt}]%
%\cs{DTLgsqrt}\marg{cmd}\marg{num}
%\end{definition}
%This sets \meta{cmd} to the sqrt root of \meta{num}.
@@ -1578,12 +1503,10 @@
%produces:
%\DTLsqrt{\result}{2}\result.
%
-%\DescribeMacro{\DTLmin}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLmin}]%
%\cs{DTLmin}\marg{cmd}\marg{num1}\marg{num2}
%\end{definition}
-%\DescribeMacro{\DTLgmin}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLgmin}]%
%\cs{DTLgmin}\marg{cmd}\marg{num1}\marg{num2}
%\end{definition}
%This sets the control sequence \meta{cmd} to the minimum of
@@ -1616,12 +1539,10 @@
%\DTLmin{\result}{\pounds5}{\$6}\result, which may not necessarily
%be true!
%
-%\DescribeMacro{\DTLminall}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLminall}]%
%\cs{DTLminall}\marg{cmd}\marg{number list}
%\end{definition}
-%\DescribeMacro{\DTLgminall}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLgminall}]%
%\cs{DTLgminall}\marg{cmd}\marg{number list}
%\end{definition}
%This sets the control sequence \meta{cmd} to the minimum of all
@@ -1641,12 +1562,10 @@
%produces:
%\DTLminall{\theMin}{{1,525},{2,340},500}\theMin.
%
-%\DescribeMacro{\DTLmax}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLmax}]%
%\cs{DTLmax}\marg{cmd}\marg{num1}\marg{num2}
%\end{definition}
-%\DescribeMacro{\DTLgmax}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLgmax}]%
%\cs{DTLgmax}\marg{cmd}\marg{num1}\marg{num2}
%\end{definition}
%This sets the control sequence \meta{cmd} to the maximum of
@@ -1661,12 +1580,10 @@
%Again, \meta{num1} and \meta{num2} may
%be currency, but the same warnings for \cs{DTLmin} apply.
%
-%\DescribeMacro{\DTLmaxall}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLmaxall}]%
%\cs{DTLmaxall}\marg{cmd}\marg{number list}
%\end{definition}
-%\DescribeMacro{\DTLgmaxall}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLgmaxall}]%
%\cs{DTLgmaxall}\marg{cmd}\marg{number list}
%\end{definition}
%This sets the control sequence \meta{cmd} to the maximum of all
@@ -1686,12 +1603,10 @@
%produces:
%\DTLmaxall{\theMax}{{1,525},{2,340},500}\theMax.
%
-%\DescribeMacro{\DTLmeanforall}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLmeanforall}]%
%\cs{DTLmeanforall}\marg{cmd}\marg{number list}
%\end{definition}
-%\DescribeMacro{\DTLgmeanall}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLgmeanall}]%
%\cs{DTLgmeanforall}\marg{cmd}\marg{number list}
%\end{definition}
%This sets the control sequence \meta{cmd} to the arithmetic mean of all
@@ -1711,12 +1626,10 @@
%produces:
%\DTLmeanforall{\theMean}{{1,525},{2,340},500}\theMean.
%
-%\DescribeMacro{\DTLvarianceforall}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLvarianceforall}]%
%\cs{DTLvarianceforall}\marg{cmd}\marg{number list}
%\end{definition}
-%\DescribeMacro{\DTLgvarianceforall}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLgvarianceforall}]%
%\cs{DTLgvarianceforall}\marg{cmd}\marg{number list}
%\end{definition}
%This sets the control sequence \meta{cmd} to the variance of all
@@ -1731,12 +1644,10 @@
%Again note that if any of the numbers in \meta{number list}
%contain a comma, you must group the number.
%
-%\DescribeMacro{\DTLsdforall}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLsdforall}]%
%\cs{DTLsdforall}\marg{cmd}\marg{number list}
%\end{definition}
-%\DescribeMacro{\DTLgsdforall}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLgsdforall}]%
%\cs{DTLgsdforall}\marg{cmd}\marg{number list}
%\end{definition}
%This sets the control sequence \meta{cmd} to the standard deviation of all
@@ -1756,38 +1667,40 @@
%produces:
%\DTLsdforall{\theSD}{{1,525},{2,340},500}\theSD.
%
-%\DescribeMacro{\DTLround}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLround}]%
%\cs{DTLround}\marg{cmd}\marg{num}\marg{num digits}
%\end{definition}
-%\DescribeMacro{\DTLground}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLground}]%
%\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.
+%\meta{cmd} globally. Example:
+%\begin{verbatim}
+%\DTLround{\result}{3.135276}{2}\result
+%\end{verbatim}
+%produces: \DTLround{\result}{3.135276}{2}\result.
%
-%\DescribeMacro{\DTLtrunc}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLtrunc}]%
%\cs{DTLtrunc}\marg{cmd}\marg{num}\marg{num digits}
%\end{definition}
-%\DescribeMacro{\DTLgtrunc}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLgtrunc}]%
%\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.
+%\meta{cmd} globally. Example:
+%\begin{verbatim}
+%\DTLtrunc{\result}{3.135276}{2}\result
+%\end{verbatim}
+%produces: \DTLtrunc{\result}{3.135276}{2}\result.
%
-%\DescribeMacro{\DTLclip}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLclip}]%
%\cs{DTLclip}\marg{cmd}\marg{num}
%\end{definition}
-%\DescribeMacro{\DTLgclip}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLgclip}]%
%\cs{DTLgclip}\marg{cmd}\marg{num}
%\end{definition}
%This sets \meta{cmd} to \meta{num} with all unnecessary 0's
@@ -1804,8 +1717,7 @@
%if one string is contained in another string. In addition,
%the \sty{datatool} provides the following macros:
%
-%\DescribeMacro{\DTLsubstitute}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLsubstitute}]%
%\cs{DTLsubstitute}\marg{cmd}\marg{original}\marg{replacement}
%\end{definition}
%This replaces the first occurrence of \meta{original} in
@@ -1817,8 +1729,7 @@
%produces:
%\def\mystr{abcdce}\DTLsubstitute{\mystr}{c}{z}\mystr.
%
-%\DescribeMacro{\DTLsubstituteall}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLsubstituteall}]%
%\cs{DTLsubstituteall}\marg{cmd}\marg{original}\marg{replacement}
%\end{definition}
%This replaces all occurrences of \meta{original} in
@@ -1830,8 +1741,7 @@
%produces:
%\def\mystr{abcdce}\DTLsubstituteall{\mystr}{c}{z}\mystr.
%
-%\DescribeMacro{\DTLsplitstring}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLsplitstring}]%
%\cs{DTLsplitstring}\marg{string}\marg{split text}\marg{before
%cmd}\marg{after cmd}
%\end{definition}
@@ -1869,8 +1779,7 @@
%{\mystr}{c}{\beforepart}{\afterpart}\relax
%Before part: ``\beforepart''. After part: ``\afterpart''.
%
-%\DescribeMacro{\DTLinitials}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLinitials}]%
%\cs{DTLinitials}\marg{string}
%\end{definition}
%This converts \meta{string} (typically a name) into initials.
@@ -1879,12 +1788,12 @@
%\DTLinitials{Mary Ann}
%\end{verbatim}
%produces:
-%\DTLinitials{Mary Ann} (including the final full stop.) Note that
+%\DTLinitials{Mary Ann} (including the final full stop). Note that
%\begin{verbatim}
%\DTLinitials{Mary-Ann}
%\end{verbatim}
%produces:
-%\DTLinitials{Mary-Ann} (including the final full stop.)
+%\DTLinitials{Mary-Ann} (including the final full stop).
%Be careful if the initial letter has an
%accent. The accented letter needs to be placed in a group, if
%you want the initial to also have an accent, otherwise the
@@ -1917,8 +1826,7 @@
%produces:
%\DTLinitials{\MakeUppercase{mary ann}}
%
-%\DescribeMacro{\DTLstoreinitials}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLstoreinitials}]%
%\cs{DTLstoreinitials}\marg{string}\marg{cmd}
%\end{definition}
%This converts \meta{string} into initials and stores the
@@ -1933,30 +1841,26 @@
%
%Both the above commands rely on the following to format the
%initials:
-%\DescribeMacro{\DTLafterinitials}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLafterinitials}]%
%\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}
+%\begin{definition}[\DescribeMacro{\DTLbetweeninitials}]%
%\cs{DTLbetweeninitials}
%\end{definition}
%This indicates what to do between initials. This does a
%full stop by default.
%
-%\DescribeMacro{\DTLinitialhyphen}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLinitialhyphen}]%
%\cs{DTLinitialhyphen}
%\end{definition}
%This indicates what to do at a hyphen. This simply does a hyphen
%by default, but can be redefined to do nothing to prevent the
%hyphen appearing in the initials.
%
-%\DescribeMacro{\DTLafterinitialbeforehyphen}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLafterinitialbeforehyphen}]%
%\cs{DTLafterinitialbeforehyphen}
%\end{definition}
%This indicates what to do between an initial and a hyphen.
@@ -1993,31 +1897,40 @@
%it is possible to iterate through each row of data, to make it
%easier to perform repetitive actions, such as mail merging.
%
+%\importantpar Whilst \TeX\ is an excellent typesetting language,
+%it is not designed as a database management system, and
+%attempting to use it as such is like trying to fasten a screw
+%with a knife instead of a screwdriver: it can be done, but requires
+%great care and is more time consuming. Version 2.0 of the
+%\sty{datatool} package uses a completely different method of storing
+%the data to previous versions.\footnote{Thanks to Morten H\o gholm
+%for the suggestion.} As a result, the code is much more efficient,
+%however, large databases and complex operations will still slow the
+%time taken to process your document. Therefore, if you can, it is
+%better to do the complex operations using whatever system created
+%the data in the first place.
+%
%\subsection{Creating a New Database}
%\label{sec:newdb}
%
-%\DescribeMacro{\DTLnewdb}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLnewdb}]%
%\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}
+%\begin{definition}[\DescribeMacro{\DTLifdbempty}]%
%\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}
+%\begin{definition}[\DescribeMacro{\DTLrowcount}]%
%\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}
+%\begin{definition}[\DescribeMacro{\DTLnewrow}]%
%\cs{DTLnewrow}\marg{db name}
%\end{definition}
%This command starts a new row in the database called \meta{db name}.
@@ -2056,8 +1969,7 @@
%which produces:
%\DTLrowcount{mydata}.
%
-%\DescribeMacro{\DTLnewdbentry}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLnewdbentry}]%
%\cs{DTLnewdbentry}\marg{db name}\marg{key}\marg{value}
%\end{definition}
%This creates a new entry with the identifier \meta{key} whose value
@@ -2070,29 +1982,53 @@
%Adds an entry with identifier \texttt{Surname} and value
%\texttt{Smith} to the last row of the database named
%\texttt{mydata}, and then adds an entry with identifier
-%\texttt{FirstName} and value \texttt{John}.
+%\texttt{FirstName} and value \texttt{John}. Note that the
+%key should not contain any fragile commands. It is generally
+%best to only use non-active characters in the key.
%
%\importantpar 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}
+%\begin{definition}[\DescribeMacro{\DTLpar}]%
%\cs{DTLpar}
%\end{definition}
%
-%\DescribeMacro{\DTLaddentryforrow}
-%\begin{definition}
-%\cs{DTLaddentryforrow}\marg{db name}\marg{assign list}\marg{condition}\marg{key}\marg{value}
+%For example:
+%\begin{verbatim}
+%\DTLnewdbentry{mydata}{Description}{First paragraph.\DTLpar
+%Second paragraph.}
+%\end{verbatim}
+%
+%\begin{definition}[\DescribeMacro{\DTLaddentryforrow}]%
+%\cs{DTLaddentryforrow}\marg{db}\marg{assign list}\marg{condition}\marg{key}\marg{value}
%\end{definition}
%This adds the entry with the key given by \meta{key} and value
%given by \meta{value} to the first row in the database
-%\meta{db name} which satisfies the condition given by
+%\meta{db} which satisfies the condition given by
%\meta{condition}. The \meta{assign list} argument is the same
%as for \cs{DTLforeach} (described in \autoref{sec:dbforeach})
%and may be used to set the values which are to be tested in
%\meta{condition} (where, again, \meta{condition} is the same
-%as for \cs{DTLforeach}).
+%as for \cs{DTLforeach}). For example:
+%\begin{verbatim}
+%\DTLaddentryforrow{mydata}{\firstname=FirstName,\surname=Surname}%
+%{\DTLiseq{\firstname}{John}\and\DTLiseq{\surname}{Smith}}%
+%{Score}{75}
+%\end{verbatim}
+%
+%\begin{definition}[\DescribeMacro{\DTLsetheader}]%
+%\cs{DTLsetheader}\marg{db}\marg{key}\marg{header}
+%\end{definition}
+%This assigns a header for a given key in the database named
+%\meta{db}. This is used by \cs{DTLdisplaydb} and
+%\cs{DTLdisplaylongdb} in the header row (see
+%\autoref{sec:displaydb}). If you don't assign
+%a header, the header will be given by the key.
+%For example:
+%\begin{verbatim}
+%\DTLsetheader{mydata}{Price}{Price (\$)}
+%\end{verbatim}
%
%\subsection{Loading a Database from an External ASCII File}
%\label{sec:loaddb}
@@ -2100,30 +2036,61 @@
%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}
+%\begin{definition}[\DescribeMacro{\DTLloaddb}]%
+%\cs{DTLloaddb}\oarg{options}\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,
+%The filename may 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
+%using \ics{DTLnewdbentry}. The optional argument \meta{options}
+%is a key=value list of options. Available options are:
+%\begin{description}
+%\item[\cmdopt{DTLloaddb}{noheader}] This is a boolean value and
+%indicates if the file does not contain a header. If no value is
+%supplied, "true" is assumed (i.e.\ the file doesn't contain a header
+%row). If this option is omitted, it is assumed that the file
+%contains a header row.
+%
+%\item[\cmdopt{DTLloaddb}{keys}] This is a comma-separated list of
+%keys to use, where the keys are listed in the same order as the
+%columns. If the file has a header, these keys will override the
+%values given in the header row. If the file has no header row and no
+%keys are supplied in \meta{options}, then the keys will be given by
+%\cs{dtldefaultkey}\meta{n}, where \meta{n} is the column number and
+%\DescribeMacro{\dtldefaultkey}\cs{dtldefaultkey} defaults to
+%``\dtldefaultkey''. Note that the list of keys must be delimited by
+%braces since they contain commas. For example:
+%\begin{verbatim}
+%\DTLloaddb[noheader,keys={Temperature,Time,T2G}]{data}{data.csv}
+%\end{verbatim}
+%
+%\item[\cmdopt{DTLloaddb}{headers}] This is a comma-separated list of
+%headers. If not supplied, the header will be the same as that given
+%in the header row, or the key if there is no header row. Note that
+%the list of headers must be delimited by braces since they contain
+%commas. For example:
+%\begin{verbatim}
+%\DTLloaddb[noheader,keys={Temperature,Time,T2G},%
+%headers={\shortstack{Incubation\\Temperature},%
+%\shortstack{Incubation\\Time},%
+%\shortstack{Time to\\Growth}}]{data}{data.csv}
+%\end{verbatim}
+%\end{description}
+%
+%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}
+%\begin{definition}[\DescribeMacro{\DTLsettabseparator}]%
%\cs{DTLsettabseparator}
%\end{definition}
%To set the separator to a character other than a tab, you need to use
-%\DescribeMacro{\DTLsetseparator}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLsetseparator}]%
%\cs{DTLsetseparator}\marg{character}
%\end{definition}
%The delimiter can be changed using
-%\DescribeMacro{\DTLsetdelimiter}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLsetdelimiter}]%
%\cs{DTLsetdelimiter}\marg{character}
%\end{definition}
%
@@ -2181,9 +2148,8 @@
%"&" 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}
+%\begin{definition}[\DescribeMacro{\DTLloadrawdb}]%
+%\cs{DTLloadrawdb}\oarg{options}\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 which produce that
@@ -2212,7 +2178,7 @@
%\cs{DTLloadrawdb} (note that the backslash retains its active state)}
%\label{tab:rawmappings}
%\begin{center}
-%\begin{tabular}{ll}
+%\begin{tabular}{cl}
%Character & Mapping\\
%\verb|%| & \verb|\%|\\
%\verb|$| & \verb|\$|\\
@@ -2241,8 +2207,7 @@
%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}
+%\begin{definition}[\DescribeMacro{\DTLrawmap}]%
%\cs{DTLrawmap}\marg{string}\marg{replacement}
%\end{definition}
%For example:\par
@@ -2251,8 +2216,8 @@
%\cs{DTLrawmap}\char`\{\pounds\char`\}\char`\{\cs{pounds}\char`\}
%\end{ttfamily}
%\vskip\baselineskip\noindent
-%will convert all occurrences\footnote{when it is loaded into the
-%\LaTeX\ database, it does not modify the data file!} of
+%will replace all occurrences\footnote{when it is loaded into the
+%\LaTeX\ database, it does not modify the data file!}\ of
%\texttt{\pounds} with \cs{pounds}. Naturally, the mappings must be
%set \emph{prior} to loading the data with \cs{DTLloadrawdb}.
%
@@ -2262,6 +2227,330 @@
%of \cs{par}, but remember that each row of data in an external data
%file must not have a line break.
%
+%\subsection{Displaying the Contents of a Database}
+%\label{sec:displaydb}
+%
+%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 display the
+%entire database in a \env{tabular} or \env{longtable}
+%environment.
+%
+%\begin{definition}[\DescribeMacro{\DTLdisplaydb}]%
+%\cs{DTLdisplaydb}\marg{db}
+%\end{definition}
+%This displays the database given by \meta{db} in a \env{tabular}
+%environment. The first row displays the headers for the database
+%in bold, the subsequent rows display the values for each key
+%in each row of the database.
+%
+%\begin{definition}[\DescribeMacro{\DTLdisplaylongdb}]%
+%\cs{DTLdisplaylongdb}\oarg{options}\marg{db}
+%\end{definition}
+%This is like \cs{DTLdisplaydb} except that it uses the
+%\env{longtable} environment instead of the \env{tabular}
+%environment. Note that if you use this command, you must load
+%\sty{longtable}, as it is not loaded by \sty{datatool}.
+%The optional argument \meta{options} is a comma-separated list
+%of key=value pairs. The following keys are available:
+%\begin{description}
+%\item[caption] The caption for the \env{longtable}.
+%
+%\item[contcaption] The continuation caption.
+%
+%\item[shortcaption] The caption to be used in the list of figures.
+%
+%\item[label] The label for this table.
+%
+%\item[foot] The \env{longtable}'s foot.
+%
+%\item[lastfoot] The foot for the last page of the \env{longtable}.
+%\end{description}
+%For example, suppose I have a database called "iris", then I can
+%display the contents in a \env{longtable} using:
+%\begin{verbatim}
+%\DTLdisplaylongdb[%
+%caption={Iris Data},%
+%label={tab:iris},%
+%contcaption={Iris Data (continued)},%
+%foot={\em Continued overleaf},%
+%lastfoot={}%
+%]{iris}
+%\end{verbatim}
+%I can then reference the table using \verb|\ref{tab:iris}|.
+%
+%See the \sty{longtable} documentation for details on how to
+%change the \env{longtable} settings, such as how to change the
+%table so that it is left aligned instead of centred on the page.
+%
+%Note that if you want more control over the way the data is
+%displayed, for example, you want to filter rows or columns, you will
+%need to use \cs{DTLforeach}, described in \autoref{sec:dbforeach}.
+%
+%\begin{example}{Displaying the Contents of a Database}{ex:displaydb}
+%Suppose I have a file called \texttt{t2g.csv} that contains the
+%following:
+%\begin{verbatim}
+%40,120,40
+%40,90,60
+%35,180,20
+%55,190,40
+%\end{verbatim}
+%This represents time to growth data, where the first column
+%is the incubation temperature, the second column is the incubation
+%time and the third column is the time to growth. This file has no
+%header row, so when it is loaded, the \cmdopt{DTLloaddb}{noheaders}
+%option is required. Note that \cs{DTLdisplaydb} only puts the data
+%in a \env{tabular} environment, so \cs{DTLdisplaydb} needs to be
+%put in a \env{table} environment with a caption to make it a float.
+%
+%First load the data base, setting the keys and headers:
+%\begin{verbatim}
+%\DTLloaddb[noheader,%
+%keys={Temperature,Time,T2G},%
+%headers={\shortstack{Incubation\\Temperature},%
+%\shortstack{Incubation\\Time},\shortstack{Time to\\Growth}}%
+%]{t2g}{t2g.csv}
+%\end{verbatim}
+%\DTLnewdb{t2g}\relax
+%\DTLnewrow*{t2g}\relax
+%\DTLnewdbentry*{t2g}{Temperature}{40}\relax
+%\DTLnewdbentry*{t2g}{Time}{120}\relax
+%\DTLnewdbentry*{t2g}{T2G}{40}\relax
+%\DTLnewrow*{t2g}\relax
+%\DTLnewdbentry*{t2g}{Temperature}{40}\relax
+%\DTLnewdbentry*{t2g}{Time}{90}\relax
+%\DTLnewdbentry*{t2g}{T2G}{60}\relax
+%\DTLnewrow*{t2g}\relax
+%\DTLnewdbentry*{t2g}{Temperature}{35}\relax
+%\DTLnewdbentry*{t2g}{Time}{180}\relax
+%\DTLnewdbentry*{t2g}{T2G}{20}\relax
+%\DTLnewrow*{t2g}\relax
+%\DTLnewdbentry*{t2g}{Temperature}{55}\relax
+%\DTLnewdbentry*{t2g}{Time}{190}\relax
+%\DTLnewdbentry*{t2g}{T2G}{40}\relax
+%\DTLsetheader*{t2g}{Temperature}{\shortstack{Incubation\\Temperature}}\relax
+%\DTLsetheader*{t2g}{Time}{\shortstack {Incubation\\Time}}\relax
+%\DTLsetheader*{t2g}{T2G}{\shortstack {Time to\\Growth}}\relax
+%
+%Now display the data in a table:
+%\begin{verbatim}
+%\begin{table}[htbp]
+%\caption{Time to Growth Data}
+%\vspace{\baselineskip}
+%\centering
+%\DTLdisplaydb{t2g}
+%\end{table}
+%\end{verbatim}
+%The result is shown in \autoref{tab:t2g}.
+%\begin{table}[htbp]
+%\caption{Time to Growth Data}
+%\label{tab:t2g}
+%\vspace{\baselineskip}
+%\centering
+%\DTLdisplaydb{t2g}
+%\end{table}
+%\end{example}
+%
+%Each column in the database has an associated data type which
+%indicates what type of data is in that column. This may be one
+%of: string, integer, real number or currency. If a column contains
+%more than one type, the data type is determined as follows:
+%\begin{itemize}
+%\item If the column contains at least one string, then the column
+%data type is string.
+%
+%\item If the column doesn't contain a string, but contains at least
+%one currency, then the column data type is currency.
+%
+%\item If the column contains only real numbers and integers, the
+%column data type is real number.
+%
+%\item The column data type is integer if the column only
+%contains integers.
+%\end{itemize}
+%The column data type is updated whenever a new entry is added
+%to the database. Note that the column data type is not adjusted
+%when an entry is removed from the database.
+%
+%The column alignments used by \cs{DTLdisplaydb} are given by:
+%\begin{definition}[\DescribeMacro{\dtlstringalign}]%
+%\cs{dtlstringalign}
+%\end{definition}\noindent
+%The string alignment defaults to \texttt{l} (left aligned).
+%
+%\begin{definition}[\DescribeMacro{\dtlintalign}]%
+%\cs{dtlintalign}
+%\end{definition}\noindent
+%The integer alignment defaults to \texttt{r} (right aligned).
+%
+%\begin{definition}[\DescribeMacro{\dtlrealalign}]%
+%\cs{dtlrealalign}
+%\end{definition}\noindent
+%The alignment for real numbers defaults to \texttt{r} (right
+%aligned).
+%
+%\begin{definition}[\DescribeMacro{\dtlcurrencyalign}]%
+%\cs{dtlcurrencyalign}
+%\end{definition}\noindent
+%The currency alignment defaults to \texttt{r} (right aligned).
+%
+%You can redefine these to change the column alignments. For
+%example, if you want columns containing strings to have the
+%alignment "p{2in}", then you can redefine \cs{dtlstringalign} as
+%follows:
+%\begin{verbatim}
+%\renewcommand{\dtlstringalign}{p{2in}}
+%\end{verbatim}
+%
+%\importantpar You can't use \sty{siunitx}'s "S" column alignment
+%with either \cs{DTLdisplaydb} or \cs{DTLdisplaylongdb}. Instead, you
+%will need to use \cs{DTLforeach}. The \sty{siunitx} documentation
+%provides an example.
+%
+%In addition to the \cs{dtl}\meta{type}"align" commands above, you
+%can also modify the \env{tabular} column styles by redefining
+%\DescribeMacro{\dtlbeforecols}\cs{dtlbeforecols},
+%\DescribeMacro{\dtlbetweencols}\cs{dtlbetweencols} and
+%\DescribeMacro{\dtlaftercols}\cs{dtlaftercols}. For example, to
+%place a vertical line before the start of the first column and
+%after the last column, do:
+%\begin{verbatim}
+%\renewcommand{\dtlbeforecols}{|}
+%\renewcommand{\dtlaftercols}{|}
+%\end{verbatim}
+%If you additionally want vertical lines between columns, do:
+%\begin{verbatim}
+%\renewcommand{\dtlbetweencols}{|}
+%\end{verbatim}
+%
+%Limited modifications can be made to the way the data is displayed
+%with \cs{DTLdisplaydb} and \cs{DTLdisplaylongdb}.
+%The commands controlling the formatting are described below.
+%If a more complicated layout is required, you will need to use
+%\cs{DTLforeach} described in \autoref{sec:dbforeach}.
+%
+%\begin{definition}[\DescribeMacro{\dtlheaderformat}]%
+%\cs{dtlheaderformat}\marg{header}
+%\end{definition}
+%This indicates how to format a column header, where the header is
+%given by \meta{header}. This defaults to
+%\cs{null}\cs{hfil}\cs{textbf}\marg{header}\cs{hfil}\cs{null}.
+%
+%\begin{definition}[\DescribeMacro{\dtlstringformat}]%
+%\cs{dtlstringformat}\marg{text}
+%\end{definition}
+%This specifies how to format each entry in the columns that contain
+%strings. This defaults to just displaying \meta{text}.
+%
+%\begin{definition}[\DescribeMacro{\dtlintformat}]%
+%\cs{dtlintformat}\marg{text}
+%\end{definition}
+%This specifies how to format each entry in the columns that contain
+%only integers. This defaults to just displaying \meta{text}.
+%
+%\begin{definition}[\DescribeMacro{\dtlrealformat}]%
+%\cs{dtlrealformat}\marg{text}
+%\end{definition}
+%This specifies how to format each entry in the columns that contain
+%only real numbers or a mixture of real numbers and integers. This
+%defaults to just displaying \meta{text}.
+%
+%\begin{definition}[\DescribeMacro{\dtlcurrencyformat}]%
+%\cs{dtlcurrencyformat}\marg{text}
+%\end{definition}
+%This specifies how to format each entry in the columns that contain
+%only currency or currency mixed with real numbers and/or integers.
+%This defaults to just displaying \meta{text}.
+%
+%\begin{definition}[\DescribeMacro{\dtldisplaystarttab}]%
+%\cs{dtldisplaystarttab}
+%\end{definition}
+%This is a hook to add something at the beginning of the
+%\env{tabular} environment. This defaults to nothing.
+%
+%\begin{definition}[\DescribeMacro{\dtldisplayendtab}]%
+%\cs{dtldisplayendtab}
+%\end{definition}
+%This is a hook to add something at the end of the
+%\env{tabular} environment. This defaults to nothing.
+%
+%\begin{definition}[\DescribeMacro{\dtldisplayafterhead}]%
+%\cs{dtldisplayafterhead}
+%\end{definition}
+%This is a hook to add something after the header row, before
+%the first row of data. This defaults to nothing.
+%
+%\begin{definition}[\DescribeMacro{\dtldisplaystartrow}]%
+%\cs{dtldisplaystartrow}
+%\end{definition}
+%This is a hook to add something at the start of each row, but
+%not including the header row or the first row of data. This
+%defaults to nothing.
+%
+%\begin{example}{Balance Sheet}{ex:balance}
+%Suppose you have a file called "balance.csv" that contains
+%the following:
+%\begin{verbatim}
+%Description,In,Out,Balance
+%Travel expenses,,230,-230
+%Conference fees,,400,-630
+%Grant,700,,70
+%Train fare,,70,0
+%\end{verbatim}
+%\DTLnewdb{balance}\relax
+%\DTLnewrow{balance}\relax
+%\DTLnewdbentry{balance}{Description}{Travel expenses}\relax
+%\DTLnewdbentry{balance}{In}{}\relax
+%\DTLnewdbentry{balance}{Out}{230.00}\relax
+%\DTLnewdbentry{balance}{Balance}{-230.00}\relax
+%\DTLnewrow{balance}\relax
+%\DTLnewdbentry{balance}{Description}{Conference fees}\relax
+%\DTLnewdbentry{balance}{In}{}\relax
+%\DTLnewdbentry{balance}{Out}{400.00}\relax
+%\DTLnewdbentry{balance}{Balance}{-630.00}\relax
+%\DTLnewrow{balance}\relax
+%\DTLnewdbentry{balance}{Description}{Grant}\relax
+%\DTLnewdbentry{balance}{In}{700.00}\relax
+%\DTLnewdbentry{balance}{Out}{}\relax
+%\DTLnewdbentry{balance}{Balance}{70.00}\relax
+%\DTLnewrow{balance}\relax
+%\DTLnewdbentry{balance}{Description}{Train Fare}\relax
+%\DTLnewdbentry{balance}{In}{}\relax
+%\DTLnewdbentry{balance}{Out}{70.00}\relax
+%\DTLnewdbentry{balance}{Balance}{0.00}\relax
+%\DTLsetheader{balance}{In}{In (\pounds)}\relax
+%\DTLsetheader{balance}{Out}{Out (\pounds)}\relax
+%\DTLsetheader{balance}{Balance}{Balance (\pounds)}\relax
+%The data can be loaded using:
+%\begin{verbatim}
+%\DTLloaddb[headers={Description,In (\pounds),Out (pounds),Balance
+%(pounds)}]{balance}{balance.csv}
+%\end{verbatim}
+%
+%Suppose I want negative numbers to be displayed in red. I can do
+%this by redefining \cs{dtlrealformat} to check if the entry
+%is negative. For example:
+%\begin{verbatim}
+%\begin{table}[htbp]
+%\caption{Balance Sheet}
+%\renewcommand*{\dtlrealformat}[1]{\DTLiflt{#1}{0}{\color{red}}{}#1}
+%\vspace{\baselineskip}
+%\centering
+%\DTLdisplaydb{balance}
+%\end{table}
+%\end{verbatim}
+%This produces \autoref{tab:balance}.
+%\begin{table}[htbp]
+%\caption{Balance Sheet}
+%\label{tab:balance}
+%\renewcommand*{\dtlrealformat}[1]{\DTLiflt{#1}{0}{\color{red}}{}#1}
+%\vspace{\baselineskip}
+%\centering
+%\DTLdisplaydb{balance}
+%\end{table}
+%\end{example}
+%
%\subsection{Iterating Through a Database}
%\label{sec:dbforeach}
%
@@ -2270,12 +2559,10 @@
%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}
+%\begin{definition}[\DescribeMacro{\DTLforeach}]%
%\cs{DTLforeach}\oarg{condition}\marg{db name}\marg{assign list}\marg{text}
%\end{definition}
-%\DescribeMacro{\DTLforeach*}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLforeach*}]%
%\cs{DTLforeach*}\oarg{condition}\marg{db name}\marg{assign list}\marg{text}
%\end{definition}
%This will iterate through each row of the database called
@@ -2295,16 +2582,15 @@
%
%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
+%provided by the \sty{ifthen} package (such as \cs{not}, \cs{and},
+%\cs{or}), as well as the commands
%described in \autoref{sec:ifthen}. The default value of
%\meta{condition} is "\boolean{true}".
%
%The starred version \cs{DTLforeach*} is a read-only version.
%If you want to modify the database using any of the commands
%described in \autoref{sec:editdb}, you must use the unstarred
-%version. The starred version is slightly quicker, however the
-%difference will probably only be noticeable for very large
-%databases.
+%version. The starred version is faster.
%
%\begin{example}{Student scores}{ex:scores}
%Suppose you have a data file called \texttt{studentscores.csv} that
@@ -2393,31 +2679,102 @@
%\counterfmt{DTLrowi},
%\counterfmt{DTLrowii} and
%\counterfmt{DTLrowiii} which keep track of
-%the current row.
+%the current row.
%
-%\importantpar Note that these counters are only incremented
-%when \meta{condition} is satisfied. These counters are incremented
+%\importantpar Note that these counters are only incremented when
+%\meta{condition} is satisfied, therefore they will not have the
+%correct value in \meta{condition}. 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
+%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.
+%should therefore be the first command in \meta{text} to ensure that
+%it references the current row counter.
%
-%\DescribeMacro{\DTLcurrentindex}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLcurrentindex}]%
%\cs{DTLcurrentindex}
%\end{definition}
-%At the start of each iteration, \cs{DTLcurrentindex} is set
-%to the arabic value of the current row counter.
+%At the start of each iteration in \cs{DTLforeach},
+%\cs{DTLcurrentindex} is set to the arabic value of the current row
+%counter. Note that this is only set after the condition is tested,
+%so it should only be used in the body of \cs{DTLforeach} not in
+%the condition. It is also only set locally, so if you use it in
+%a tabular environment, it can only be used before the first instance
+%of \verb|\\| or \verb|&| in the current iteration.
%
-%\DescribeMacro{\DTLforeachkeyinrow}
-%\begin{definition}
+%Within the body of \ics{DTLforeach} (i.e.\ within \meta{text})
+%the following conditionals may be used:
+%\begin{definition}[\DescribeMacro{\DTLiffirstrow}]%
+%\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}.
+%
+%\begin{definition}[\DescribeMacro{\DTLifoddrow}]%
+%\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{definition}[\DescribeMacro{\DTLsavelastrowcount}]%
+%\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{definition}[\DescribeMacro{\DTLforeachkeyinrow}]%
%\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.)
+%This iterates through each key in the current row, (globally) assigns
+%\meta{cmd} to the value of that key, and does \meta{text}
+%(\meta{cmd} must be a control sequence and may be used in
+%\meta{text}). This command may only be used in the body of
+%\cs{DTLforeach}. At each iteration, \cs{DTLforeachkeyinrow} sets
+%\cs{dtlkey} to the current key, \cs{dtlcol} to the current column
+%index, \cs{dtltype} to the data type for the current column,
+%and \cs{dtlheader} to the header for the current column. Note that
+%\cs{dtltype} corresponds to the column type but if the entries in
+%the column have mixed types, it may not correspond to the type
+%of the current entry.
+%
+%\begin{definition}[\DescribeMacro{\dtlforeachkey}]%
+%\cs{dtlforeachkey}(\meta{key cs},\meta{col cs},\meta{type
+%cs},\meta{header cs})\cs{in}\marg{db}\cs{do}\marg{body}
+%\end{definition}
+%This iterates through all the keys in the database given by
+%\meta{db}. In each iteration, \meta{key cs} is set to the key,
+%\meta{col cs} is set to the column index, \meta{type cs} is
+%set to the data type, \meta{header cs} is set to the header
+%for that column, and then \meta{body} is done. Note that
+%\meta{key cs}, \meta{col cs}, \meta{type cs} and \meta{header cs}
+%must all be control sequences. No check is performed to determine
+%if that control sequence already exists, and the control
+%sequences are defined globally (since it's likely that
+%\cs{dtlforeachkey} may be used within a \env{tabular}
+%environment), so you need to make sure you don't override an
+%existing command of the same name. The data type may have the
+%following values: 0 (string), 1 (integer), 2 (real number), 3
+%(currency) or it will be empty if the column has no entries.
+%
+%\begin{definition}[\DescribeMacro{\dtlforcolumn}]%
+%\cs{dtlforcolumn}\marg{cs}\marg{db}\marg{key}\marg{body}
+%\end{definition}
+%This iterates through the column given by \meta{key} in the
+%database given by \meta{db} and applies \meta{body}. In each
+%iteration, \meta{cs} (which must be a control sequence) is set to
+%the current element in the column and may be used in \meta{body}.
+%
+%\begin{definition}[\DescribeMacro{\dtlbreak}]%
+%\cs{dtlbreak}
+%\end{definition}
+%You can break out of most of the loops provided by \sty{datatool}
+%using \cs{dtlbreak}. Note, however, that it doesn't break the loop
+%until the end of the current iteration. There is no provision for
+%a "next" or "continue" style command.
+%
+%Additional loop commands provided by \sty{datatool} are
+%described in \autoref{sec:code:loops}.
%
%\begin{example}{Student Scores---Labelling}{ex:label}
%In the previous example, the student scores, stored in the
@@ -2444,7 +2801,7 @@
%\bfseries First Name &
%\bfseries Surname &
%\bfseries Score (\%)%
-%\DTLforeach{scores}{%
+%\DTLforeach*{scores}{%
%\firstname=FirstName,\surname=Surname,\score=Score}{%
%\label{row:\score}\\\theDTLrowi &
%\firstname & \surname & \score}%
@@ -2458,10 +2815,16 @@
%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
+%Notes:
+%\begin{itemize}
+%\item the \cs{label} command is placed before
%"\\" to ensure that it is in the same scope as the command
%"\refstepcounter{DTLrowi}".
%
+%\item To avoid unwanted spaces the end of line characters are
+%commented out with the percent (\texttt{\%}) symbol.
+%\end{itemize}
+%
%\begin{table}[htbp]
%\caption[Student scores (labelling rows)]{Student
%scores}\label{tab:scoreslab}
@@ -2471,21 +2834,13 @@
%\bfseries First Name &
%\bfseries Surname &
%\bfseries Score (\%)\relax
-%\DTLforeach{scores}{\firstname=FirstName,\surname=Surname,\score=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.
@@ -2502,7 +2857,7 @@
%\bfseries First Name &
%\bfseries Surname &
%\bfseries Score (\%)%
-%\DTLforeach[\DTLisgt{\score}{60}]{scores}{%
+%\DTLforeach*[\DTLisgt{\score}{60}]{scores}{%
%\firstname=FirstName,\surname=Surname,\score=Score}{%
%\\
%\firstname & \surname & \score}
@@ -2525,7 +2880,7 @@
%\bfseries First Name &
%\bfseries Surname &
%\bfseries Score (\%)\relax
-%\DTLforeach[\DTLisgt{\score}{60}]{scores}{\firstname=FirstName,\surname=Surname,\score=Score}{\relax
+%\DTLforeach*[\DTLisgt{\score}{60}]{scores}{\firstname=FirstName,\surname=Surname,\score=Score}{\relax
%\\
%\firstname & \surname & \score}
%\end{tabular}
@@ -2544,7 +2899,7 @@
%\bfseries First Name &
%\bfseries Surname &
%\bfseries Score (\%)%
-%\DTLforeach[\DTLisopenbetween{\surname}{B}{C}]{scores}{%
+%\DTLforeach*[\DTLisopenbetween{\surname}{B}{C}]{scores}{%
%\firstname=FirstName,\surname=Surname,\score=Score}{%
%\\
%\firstname & \surname & \score}
@@ -2561,7 +2916,7 @@
%\bfseries First Name &
%\bfseries Surname &
%\bfseries Score (\%)\relax
-%\DTLforeach[\DTLisopenbetween{\surname}{B}{C}]{scores}
+%\DTLforeach*[\DTLisopenbetween{\surname}{B}{C}]{scores}
%{\firstname=FirstName,\surname=Surname,\score=Score}{\relax
%\\
%\firstname & \surname & \score}
@@ -2570,21 +2925,68 @@
%
%\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}.
+%\begin{example}{Breaking Out of a Loop}{ex:dtlbreak}
+%Suppose I only want to display the first three rows of a database.
+%I could do:\footnote{Recall that \counterfmt{DTLrowi} is incremented
+%after the condition is tested, so it will be out by 1 when the
+%condition is tested which is why \texttt{<3} is used instead of
+%\texttt{<4}.}
+%\begin{verbatim}
+%\DTLforeach*[\value{DTLrowi}<3]{scores}%
+%{\firstname=FirstName,\surname=Surname,\score=Score}{%
+%\\\firstname & \surname & \score
+%}
+%\end{verbatim}
+%However, this isn't very efficient, as it still has to iterate
+%through the entire database, checking if the condition is met. If
+%the database has over 100 entries, this will slow the time taken
+%to create the table. It would therefore be much more efficient
+%to break out of the loop when row count exceeds 3:
+%\begin{verbatim}
+%\begin{table}[htbp]
+%\caption{First Three Rows}
+%\centering
+%\vskip\baselineskip
+%\begin{tabular}{llr}
+%\bfseries First Name & \bfseries Surname & \bfseries Score (\%)%
+%\DTLforeach*{scores}%
+%{\firstname=FirstName,\surname=Surname,\score=Score}{%
+%\ifthenelse{\DTLcurrentindex=3}{\dtlbreak}{}%
+%\\\firstname & \surname & \score
+%}%
+%\end{tabular}
+%\end{table}
+%\end{verbatim}
+%This produces \autoref{tab:dtlbreak}. Note that the loop is not
+%broken until the end of the current iteration, so even though
+%\cs{dtlbreak} occurs at the start of the third row, the loop isn't
+%finished until the third row is completed. (Recall that
+%\cs{DTLcurrentindex} must be used before the first instance of
+%\verb|\\| or \verb|&|.) Alternatively, you can use
+%\counterfmt{DTLrowi} instead:
+%\begin{verbatim}
+%\DTLforeach{scores}%
+%{\firstname=FirstName,\surname=Surname,\score=Score}{%
+%\\\firstname & \surname & \score
+%\ifthenelse{\value{DTLrowi}=3}{\dtlbreak}{}%
+%}%
+%\end{verbatim}
%
-%\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{table}[htbp]
+%\caption{First Three Rows}
+%\label{tab:dtlbreak}%
+%\centering
+%\vskip\baselineskip
+%\begin{tabular}{llr}
+%\bfseries First Name & \bfseries Surname & \bfseries Score (\%)\relax
+%\DTLforeach*{scores}%
+%{\firstname=FirstName,\surname=Surname,\score=Score}{%
+%\ifthenelse{\DTLcurrentindex=3}{\dtlbreak}{}\relax
+%\\\firstname & \surname & \score
+%}%
+%\end{tabular}
+%\end{table}
+%\end{example}
%
%\begin{example}{Stripy Tables}{ex:stripy}
%This example uses the same database as in the previous examples.
@@ -2599,7 +3001,7 @@
%\bfseries First Name &
%\bfseries Surname &
%\bfseries Score (\%)%
-%\DTLforeach{scores}{%
+%\DTLforeach*{scores}{%
%\firstname=FirstName,\surname=Surname,\score=Score}{%
%\\\DTLifoddrow{\rowcolor{blue}}{\rowcolor{green}}%
%\firstname & \surname & \score}%
@@ -2616,7 +3018,7 @@
%\bfseries First Name &
%\bfseries Surname &
%\bfseries Score (\%)\relax
-%\DTLforeach{scores}{\firstname=FirstName,\surname=Surname,\score=Score}{\relax
+%\DTLforeach*{scores}{\firstname=FirstName,\surname=Surname,\score=Score}{\relax
%\\\DTLifoddrow{\rowcolor{blue}}{\rowcolor{green}}\relax
%\firstname & \surname & \score}\relax
%\end{tabular}
@@ -2639,7 +3041,7 @@
%\bfseries First Name &
%\bfseries Surname &
%\bfseries Score (\%)%
-%\DTLforeach{scores}{\firstname=FirstName,\surname=Surname,\score=Score}{%
+%\DTLforeach*{scores}{\firstname=FirstName,\surname=Surname,\score=Score}{%
%\DTLifoddrow{\\}{&}%
%\firstname & \surname & \score}%
%\end{tabular}
@@ -2659,13 +3061,196 @@
%\bfseries First Name &
%\bfseries Surname &
%\bfseries Score (\%)\relax
-%\DTLforeach{scores}{\firstname=FirstName,\surname=Surname,\score=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}{Iterating Through Keys in a Row}{ex:foreachkey}
+%Suppose you have lots of columns in your database, and you
+%want to display them all without having to set a variable for
+%each column. You can leave the assignment list in \cs{DTLforeach}
+%blank, and iterate through the keys using \cs{DTLforeachkeyinrow}.
+%For example:
+%\begin{verbatim}
+%\begin{table}[htbp]
+%\caption{Student Scores (Iterating Through Keys)}
+%\vskip\baselineskip
+%\centering
+%\begin{tabular}{llll}
+%\bfseries First Name & \bfseries Surname &
+%\bfseries Registration No. &
+%\bfseries Score (\%)%
+%\DTLforeach*{scores}{}{%
+%\\\gdef\doamp{\gdef\doamp{&}}%
+%\DTLforeachkeyinrow{\thisValue}{\doamp\thisValue}}%
+%\end{tabular}
+%\end{table}
+%\end{verbatim}
+%This produces \autoref{tab:foreachkey}.
+%\begin{table}[htbp]
+%\caption{Student Scores (Iterating Through Keys)}
+%\label{tab:foreachkey}
+%\vskip\baselineskip
+%\centering
+%\begin{tabular}{llll}
+%\bfseries First Name & \bfseries Surname &
+%\bfseries Registration No. &
+%\bfseries Score (\%)\relax
+%\DTLforeach*{scores}{}{%
+%\\\gdef\doamp{\gdef\doamp{&}}\relax
+%\DTLforeachkeyinrow{\thisValue}{\doamp\thisValue}}\relax
+%\end{tabular}
+%\end{table}
+%
+%Note that the "&" must be between columns, so I have defined
+%a command called \cs{doamp} that on first use redefines
+%itself to do "&". So, for each row, at the start of
+%the key iteration, \cs{doamp} does nothing, and on subsequent
+%iterations it does "&". This ensures that the correct number of
+%"&"s are used. Since each cell in the \env{tabular} environment
+%is scoped, \cs{gdef} is needed instead of \cs{def}.
+%
+%In the above, I needed to know how many columns are in the
+%database, and the order that the headings should appear. If you
+%are unsure, you can use \cs{dtlforeachkey} to determine the
+%number of columns and to display the header row. For example:
+%\begin{verbatim}
+% \begin{table}[htbp]
+% \caption{Student Scores}
+% \vskip\baselineskip
+% \centering
+% % Work out the column alignments.
+% \def\colalign{}%
+% \dtlforeachkey(\theKey,\theCol,\theType,\theHead)\in{scores}\do
+% {\edef\colalign{\colalign l}}%
+% % Begin the tabular environment.
+% \edef\dobegintabular{\noexpand\begin{tabular}{\colalign}}%
+% \dobegintabular
+% % Do the header row.
+% \gdef\doamp{\gdef\doamp{&}}%
+% \dtlforeachkey(\theKey,\theCol,\theType,\theHead)\in{scores}\do
+% {\doamp\bfseries \theHead}%
+% % Iterate through the data.
+% \DTLforeach*{scores}{}{%
+% \\\gdef\doamp{\gdef\doamp{&}}%
+% \DTLforeachkeyinrow{\thisValue}{\doamp\thisValue}}%
+% \end{tabular}
+% \end{table}
+%\end{verbatim}
+%
+%\begin{table}[htbp]
+%\caption{Student Scores (Using \cs{dtlforeachkey} and
+%\cs{DTLforeachkeyinrow})}
+%\label{tab:foreachkey2}
+%\vskip\baselineskip
+%\centering
+%\def\colalign{}%
+%\dtlforeachkey(\theKey,\theCol,\theType,\theHead)\in{scores}\do
+%{\edef\colalign{\colalign l}}%
+%\edef\dobegintabular{\noexpand\begin{tabular}{\colalign}}\relax
+%\dobegintabular
+%\gdef\doamp{\gdef\doamp{&}}\relax
+%\dtlforeachkey(\theKey,\theCol,\theType,\theHead)\in{scores}\do
+%{\doamp\bfseries \theHead}\relax
+%\DTLforeach*{scores}{}{%
+%\\\gdef\doamp{\gdef\doamp{&}}\relax
+%\DTLforeachkeyinrow{\thisValue}{\doamp\thisValue}}\relax
+%\end{tabular}
+%\end{table}
+%
+%Notes:
+%\begin{itemize}
+%\item In order to determine the column alignment for the
+%\env{tabular} environment, I first define \cs{colalign} to
+%nothing, and then I iterate through the keys appending
+%\texttt{l} to \cs{colalign}. Since \cs{colalign} only contains
+%alphabetical characters, I can just use \cs{edef} for this. I
+%could modify this to check the data type and, say, use \texttt{l}
+%(left alignment) for columns containing strings and \texttt{c}
+%(centred) for the other columns:
+%\begin{verbatim}
+%\dtlforeachkey(\theKey,\theCol,\theType,\theHead)\in{scores}\do
+%{\ifnum\theType=0\relax
+% \edef\colalign{\colalign l}% column contains strings
+% \else
+% \edef\colalign{\colalign c}% column contains numerical values
+% \fi
+%}%
+%\end{verbatim}
+%
+%\item To ensure \cs{colalign} gets correct expanded when passed
+%to the \env{tabular} environment I temporarily define
+%\cs{dobegintabular} to the code required to start the
+%\env{tabular} environment:
+%\begin{verbatim}
+%\edef\dobegintabular{\noexpand\begin{tabular}{\colalign}}%
+%\end{verbatim}
+%This sets \cs{dobegintabular} to \verb|\begin{tabular}{llll}|.
+%After defining \cs{dobegintabular}, I then need to use it.
+%
+%\item As before, I use \cs{doamp} to put the ampersands between
+%columns.
+%
+%\item Recall that I can set the headers using \cs{DTLsetheader}
+%or using the \cmdopt{DTLloaddb}{headers} key when loading the data
+%from an external file. For example:
+%\begin{verbatim}
+%\DTLsetheaders{scores}{FirstName}{First Name}
+%\DTLsetheaders{scores}{Score}{Score (\%)}
+%\end{verbatim}
+%\end{itemize}
+%
+%Recall that \cs{DTLforeachkeyinrow} sets \cs{dtlkey} to the
+%current key. This can be used to filter out columns. Alternatively,
+%if you know the column index, you can test \cs{dtlcol} instead.
+%The following code modifies the above example so that it filters
+%out the column whose key is \texttt{StudentNo}:
+%\begin{verbatim}
+%\begin{table}[htbp]
+%\caption{Student Scores (Filtering Out a Column)}
+%\vskip\baselineskip
+%\centering
+%\def\colalign{}%
+%\dtlforeachkey(\theKey,\theCol,\theType,\theHead)\in{scores}\do
+%{\DTLifeq{\theKey}{StudentNo}{}{\edef\colalign{\colalign l}}}%
+%\edef\dobegintabular{\noexpand\begin{tabular}{\colalign}}%
+%\dobegintabular
+%\gdef\doamp{\gdef\doamp{&}}%
+%\dtlforeachkey(\theKey,\theCol,\theType,\theHead)\in{scores}\do
+%{\DTLifeq{\theKey}{StudentNo}{}{\doamp\bfseries \theHead}}%
+%\DTLforeach*{scores}{}{%
+%\\\gdef\doamp{\gdef\doamp{&}}%
+%\DTLforeachkeyinrow{\thisValue}{%
+% \DTLifeq{\dtlkey}{StudentNo}{}{\doamp\thisValue}}}%
+%\end{tabular}
+%\end{table}
+%\end{verbatim}
+%The result is shown in \autoref{tab:foreachkey3}.
+%
+%\begin{table}[htbp]
+%\caption{Student Scores (Filtering Out a Column)}
+%\label{tab:foreachkey3}
+%\vskip\baselineskip
+%\centering
+%\def\colalign{}%
+%\dtlforeachkey(\theKey,\theCol,\theType,\theHead)\in{scores}\do
+%{\DTLifeq{\theKey}{StudentNo}{}{\edef\colalign{\colalign l}}}%
+%\edef\dobegintabular{\noexpand\begin{tabular}{\colalign}}\relax
+%\dobegintabular
+%\gdef\doamp{\gdef\doamp{&}}\relax
+%\dtlforeachkey(\theKey,\theCol,\theType,\theHead)\in{scores}\do
+%{\DTLifeq{\theKey}{StudentNo}{}{\doamp\bfseries \theHead}}\relax
+%\DTLforeach*{scores}{}{%
+%\\\gdef\doamp{\gdef\doamp{&}}\relax
+%\DTLforeachkeyinrow{\thisValue}{\relax
+%\DTLifeq{\dtlkey}{StudentNo}{}{\doamp\thisValue}}}\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:
@@ -2791,11 +3376,101 @@
%}
%\end{example}
%
+%\begin{example}{Dynamically Allocating Field Name}{ex:dyn}
+%(This example was suggested by Bill~Hobbs.) Suppose you have a
+%directory containing members of multiple clubs. The CSV file
+%(say, \texttt{clubs.csv}) may look something like:
+%\begin{verbatim}
+%First Name,Surname,Rockin,Single
+%John,"Smith, Jr",member,
+%Jane,Brown,,friend
+%Andy,Brown,friend,member
+%Z\"oe,Adams,member,member
+%Roger,Brady,friend,friend
+%Clare,Verdon,member,
+%\end{verbatim}
+%\DTLnewdb{clubs}\relax
+%\DTLnewrow{clubs}\relax
+%\DTLnewdbentry{clubs}{First Name}{John}\relax
+%\DTLnewdbentry{clubs}{Surname}{Smith, Jr}\relax
+%\DTLnewdbentry{clubs}{Rockin}{member}\relax
+%\DTLnewdbentry{clubs}{Single}{}\relax
+%\DTLnewrow{clubs}\relax
+%\DTLnewdbentry{clubs}{First Name}{Jane}\relax
+%\DTLnewdbentry{clubs}{Surname}{Brown}\relax
+%\DTLnewdbentry{clubs}{Rockin}{}\relax
+%\DTLnewdbentry{clubs}{Single}{friend}\relax
+%\DTLnewrow{clubs}\relax
+%\DTLnewdbentry{clubs}{First Name}{Andy}\relax
+%\DTLnewdbentry{clubs}{Surname}{Brown}\relax
+%\DTLnewdbentry{clubs}{Rockin}{friend}\relax
+%\DTLnewdbentry{clubs}{Single}{member}\relax
+%\DTLnewrow{clubs}\relax
+%\DTLnewdbentry{clubs}{First Name}{Z\"oe}\relax
+%\DTLnewdbentry{clubs}{Surname}{Adams}\relax
+%\DTLnewdbentry{clubs}{Rockin}{member}\relax
+%\DTLnewdbentry{clubs}{Single}{member}\relax
+%\DTLnewrow{clubs}\relax
+%\DTLnewdbentry{clubs}{First Name}{Roger}\relax
+%\DTLnewdbentry{clubs}{Surname}{Brady}\relax
+%\DTLnewdbentry{clubs}{Rockin}{friend}\relax
+%\DTLnewdbentry{clubs}{Single}{friend}\relax
+%\DTLnewrow{clubs}\relax
+%\DTLnewdbentry{clubs}{First Name}{Clare}\relax
+%\DTLnewdbentry{clubs}{Surname}{Verdon}\relax
+%\DTLnewdbentry{clubs}{Rockin}{member}\relax
+%\DTLnewdbentry{clubs}{Single}{}\relax
+%(Blank entries indicate that the person is not a member of that
+%club.) The data can be loaded as follows:
+%\begin{verbatim}
+%\DTLloaddb{clubs}{clubs.csv}
+%\end{verbatim}
+%Suppose at the beginning of your document you have specified
+%which club you are interested in ("Rockin" or "Single") and
+%store it in \cs{DIdent}:
+%\begin{verbatim}
+%\newcommand{\DIdent}{Rockin}
+%\end{verbatim}
+%\newcommand{\DIdent}{Rockin}\relax
+%You can now display the members for this particular club as
+%follows:
+%\begin{verbatim}
+%\begin{table}[htbp]
+%\caption{Club Membership}
+%\vskip\baselineskip
+%\centering
+%\begin{tabular}{lll}
+%\bfseries First Name & \bfseries Surname & \bfseries Status
+%\DTLforeach*[\not\DTLiseq{\status}{}]{clubs}
+%{\firstname=First Name,\surname=Surname,\status=\DIdent}{%
+%\\\firstname & \surname & \status
+%}%
+%\end{tabular}
+%\end{table}
+%\end{verbatim}
+%The result is shown in \autoref{tab:dyn}.
+%
+%\begin{table}[htbp]
+%\caption{Club Membership}
+%\label{tab:dyn}
+%\vskip\baselineskip
+%\centering
+%\begin{tabular}{lll}
+%\bfseries First Name & \bfseries Surname & \bfseries Status
+%\DTLforeach*[\not\DTLiseq{\status}{}]{clubs}
+%{\firstname=First Name,\surname=Surname,\status=\DIdent}{\relax
+%\\\firstname & \surname & \status
+%}\relax
+%\end{tabular}
+%\end{table}
+%\end{example}
+%
%\subsection{Null Values}
%If a database is created using \cs{DTLnewdb}, \cs{DTLnewrow}
%and \cs{DTLnewdbentry} (rather than loading it from an ASCII
%file), it is possible for some of the entries to have null values
%when a value is not assigned to a given key for a given row.
+%(Note that a null value is not the same as an empty value.)
%
%When you iterate through the database using \cs{DTLforeach}
%(described in \autoref{sec:dbforeach}),
@@ -2803,20 +3478,17 @@
%in the \meta{values} argument will be set to a null value. This
%value depends on the data type associated with the given key.
%
-%\DescribeMacro{\DTLstringnull}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLstringnull}]%
%\cs{DTLstringnull}
%\end{definition}
%This is the null value for a string.
%
-%\DescribeMacro{\DTLnumbernull}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLnumbernull}]%
%\cs{DTLnumbernull}
%\end{definition}
%This is the null value for a number.
%
-%\DescribeMacro{\DTLifnull}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLifnull}]%
%\cs{DTLifnull}\marg{cmd}\marg{true part}\marg{false part}
%\end{definition}
%This checks if \meta{cmd} is null where \meta{cmd} is a command name,
@@ -2991,29 +3663,26 @@
%\subsection{Editing Database Rows}
%\label{sec:editdb}
%
-%In the body of the \ics{DTLforeach} loop, you can use the following
-%to edit the current row:
-%\DescribeMacro{\DTLappendtorow}
-%\begin{definition}
+%In the body of the \ics{DTLforeach} loop,\footnote{Only the
+%unstarred version of \cs{DTLforeach}; the starred version is
+%read-only.}\ you can use the following to edit the current row:
+%\begin{definition}[\DescribeMacro{\DTLappendtorow}]%
%\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}
+%\begin{definition}[\DescribeMacro{\DTLreplaceentryforrow}]%
%\cs{DTLreplaceentryforrow}\marg{key}\marg{value}
%\end{definition}
%This replaces the entry for \meta{key} with \meta{value}.
%
-%\DescribeMacro{\DTLremoveentryfromrow}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLremoveentryfromrow}]%
%\cs{DTLremoveentryfromrow}\marg{key}
%\end{definition}
-%This the entry for \meta{key} from the current row.
+%This removes the entry for \meta{key} from the current row.
%
-%\DescribeMacro{\DTLremovecurrentrow}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLremovecurrentrow}]%
%\cs{DTLremovecurrentrow}
%\end{definition}
%This removes the current row from the database.
@@ -3100,7 +3769,7 @@
%\begin{table}[htbp]
%\caption{Student marks}
%\centering
-%\begin{tabular}{llrrrr}
+%\begin{tabular}{llcccc}
%\bfseries Surname & \bfseries First Name &
%\bfseries Assign 1 &
%\bfseries Assign 2 &
@@ -3127,7 +3796,7 @@
%\caption[Student marks (with averages)]{Student
%marks}\label{tab:meanmarks}
%\centering
-%\begin{tabular}{llrrrr}
+%\begin{tabular}{llcccc}
%\bfseries Surname & \bfseries First Name &
%\bfseries Assign 1 &
%\bfseries Assign 2 &
@@ -3223,29 +3892,40 @@
%\end{table}
%\end{example}
%
-%\DescribeMacro{\DTLsumforkeys}
-%\begin{definition}
-%\cs{DTLsumforkeys}\oarg{condition}\marg{db list}\marg{key list}\marg{cmd}
+%\begin{definition}[\DescribeMacro{\DTLsumforkeys}]%
+%\cs{DTLsumforkeys}\oarg{condition}\oarg{assign list}\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:
+%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 second optional argument \meta{assign list} is the same
+%as the assignment list used by \ics{DTLforeach}, so that you can use
+%the information in \meta{condition}. 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}
+%\begin{definition}[\DescribeMacro{\DTLsumcolumn}]%
+%\cs{DTLsumcolumn}\marg{db}\marg{key}\marg{cmd}
+%\end{definition}
+%This is a faster version of \cs{DTLsumforkeys} that only sums
+%the entries in a single column (specified by \meta{key}) for
+%a single database (specified by \meta{db}) and doesn't provide any
+%filtering. The result is stored in \meta{cmd} which must be
+%a control sequence.
+%
+%\begin{definition}[\DescribeMacro{\DTLmeanforkeys}]%
+%\cs{DTLmeanforkeys}\oarg{condition}\oarg{assign list}\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}
+%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
+%second optional argument \meta{assign list} is the same as the
+%assignment list used by \ics{DTLforeach}, so that you can use the
+%information in \meta{condition}. The result is stored in \meta{cmd}
%which must be a control sequence. For example:
%\begin{verbatim}
%\DTLmeanforkeys{scores}{Score}{\average}
@@ -3253,55 +3933,105 @@
%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}
+%\begin{definition}[\DescribeMacro{\DTLmeanforcolumn}]%
+%\cs{DTLmeanforcolumn}\marg{db}\marg{key}\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.
+%This is a faster version of \cs{DTLmeanforkeys} that only computes
+%the mean for a single column (specified by \meta{key}) for
+%a single database (specified by \meta{db}) and doesn't provide any
+%filtering. 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}
+%\begin{definition}[\DescribeMacro{\DTLvarianceforkeys}]%
+%\cs{DTLvarianceforkeys}\oarg{condition}\oarg{assign list}\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 second
+%optional argument \meta{assign list} is the same as the assignment
+%list used by \ics{DTLforeach}, so that you can use the information
+%in \meta{condition}. The result is stored in \meta{cmd} which must
+%be a control sequence.
+%
+%\begin{definition}[\DescribeMacro{\DTLvarianceforcolumn}]%
+%\cs{DTLvarianceforcolumn}\marg{db}\marg{key}\marg{cmd}
+%\end{definition}
+%This is a faster version of \cs{DTLvarianceforkeys} that only
+%computes the variance for a single column (specified by \meta{key})
+%for a single database (specified by \meta{db}) and doesn't provide
+%any filtering. The result is stored in \meta{cmd} which must be a
+%control sequence.
+%
+%\begin{definition}[\DescribeMacro{\DTLsdforkeys}]%
+%\cs{DTLsdforkeys}\oarg{condition}\oarg{assign list}\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}
+%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
+%second optional argument \meta{assign list} is the same as the
+%assignment list used by \ics{DTLforeach}, so that you can use the
+%information in \meta{condition}. 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}
+%\begin{definition}[\DescribeMacro{\DTLsdforcolumn}]%
+%\cs{DTLsdforcolumn}\marg{db}\marg{key}\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
+%This is a faster version of \cs{DTLsdforkeys} that only computes the
+%standard deviation for a single column (specified by \meta{key}) for
+%a single database (specified by \meta{db}) and doesn't provide any
+%filtering. The result is stored in \meta{cmd} which must be a
+%control sequence.
+%
+%\begin{definition}[\DescribeMacro{\DTLminforkeys}]%
+%\cs{DTLminforkeys}\oarg{condition}\oarg{assign list}\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} where \meta{condition} is true. The second optional argument
+%\meta{assign list} is the same as the assignment list used by
+%\ics{DTLforeach}, so that you can use the information in
+%\meta{condition}. The result is stored 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}
+%\begin{definition}[\DescribeMacro{\DTLminforcolumn}]%
+%\cs{DTLminforcolumn}\marg{db}\marg{key}\marg{cmd}
+%\end{definition}
+%This is a faster version of \cs{DTLminforkeys} that only computes
+%the minimum for a single column (specified by \meta{key}) for
+%a single database (specified by \meta{db}) and doesn't provide any
+%filtering. The result is stored in \meta{cmd} which must be
+%a control sequence.
+%
+%\begin{definition}[\DescribeMacro{\DTLmaxforkeys}]%
+%\cs{DTLmaxforkeys}\oarg{condition}\oarg{assign list}\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
+%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} where \meta{condition} is true. The second optional argument
+%\meta{assign list} is the same as the assignment list used by
+%\ics{DTLforeach}, so that you can use the information in
+%\meta{condition}. The result is stored 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}
+%\begin{definition}[\DescribeMacro{\DTLmaxforcolumn}]%
+%\cs{DTLmaxforcolumn}\marg{db}\marg{key}\marg{cmd}
+%\end{definition}
+%This is a faster version of \cs{DTLmaxforkeys} that only computes
+%the maximum for a single column (specified by \meta{key}) for
+%a single database (specified by \meta{db}) and doesn't provide any
+%filtering. The result is stored in \meta{cmd} which must be
+%a control sequence.
+%
+%\begin{definition}[\DescribeMacro{\DTLcomputebounds}]%
+%\cs{DTLcomputebounds}\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
@@ -3350,12 +4080,10 @@
%\subsection{Sorting a Database}
%\label{sec:sort}
%
-%\DescribeMacro{\DTLsort}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLsort}]%
%\cs{DTLsort}\oarg{replacement key list}\marg{sort criteria}\marg{db name}
%\end{definition}
-%\DescribeMacro{\DTLsort*}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLsort*}]%
%\cs{DTLsort*}\oarg{replacement key list}\marg{sort criteria}\marg{db name}
%\end{definition}
%This will sort the database called \meta{db name} according to
@@ -3644,8 +4372,7 @@
%\subsection{Saving a Database to an External File}
%\label{sec:savedb}
%
-%\DescribeMacro{\DTLsavedb}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLsavedb}]%
%\cs{DTLsavedb}\marg{db name}\marg{filename}
%\end{definition}
%This writes the database called \meta{db name} to a file called
@@ -3656,12 +4383,11 @@
%\DTLsettabdelimiter
%\DTLsavedb{scores}{scores.txt}
%\end{verbatim}
-%will create a file called "scores.txt", and save the data in a
+%will create a file called "scores.txt" and will save the data in a
%tab separated format. (The delimiters will only be used if a
%given entry contains the separator character.)
%
-%\DescribeMacro{\DTLsavetexdb}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLsavetexdb}]%
%\cs{DTLsavetexdb}\marg{db name}\marg{filename}
%\end{definition}
%This writes the database called \meta{db name} to a \LaTeX\ file
@@ -3672,29 +4398,28 @@
%\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
+%so you need to explicitly load \sty{datapie} if you want to use any of the
+%commands defined in this section. You will also 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]{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.)
+%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.)
+%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}
+%\begin{definition}[\DescribeMacro{\DTLpiechart}]%
%\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
@@ -3771,7 +4496,7 @@
%\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
+%(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
@@ -3968,8 +4693,7 @@
%
%\subsection{Pie Chart Variables}
%
-%\DescribeMacro{\DTLpievariable}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLpievariable}]%
%\cs{DTLpievariable}
%\end{definition}
%This command is set to the variable given by the
@@ -3977,8 +4701,7 @@
%argument of \cs{DTLpiechart}. The \setting{DTLpiechart}{innerlabel}
%is set to \cs{DTLpievariable} by default.
%
-%\DescribeMacro{\DTLpiepercent}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLpiepercent}]%
%\cs{DTLpiepercent}
%\end{definition}
%This command is set to the percentage value of \cs{DTLpievariable}.
@@ -4006,8 +4729,7 @@
%\begin{figure}[htbp]
%\centering
%\DTLpiechart{variable=\quantity,innerlabel={\DTLpiepercent
-%\%},outerlabel={\name\ (\DTLpievariable)}}{fruit}{%
-%\name=Name,\quantity=Quantity}
+%\%},outerlabel={\name\ (\DTLpievariable)}}{fruit}{\name=Name,\quantity=Quantity}
%\caption{A pie chart (changing the labels)}
%\label{fig:piechartlabels}
%\end{figure}
@@ -4015,15 +4737,13 @@
%
%\subsection{Pie Chart Label Formatting}
%
-%\DescribeMacro{\DTLdisplayinnerlabel}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLdisplayinnerlabel}]%
%\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}
+%\begin{definition}[\DescribeMacro{\DTLdisplayouterlabel}]%
%\cs{DTLdisplayouterlabel}\marg{text}
%\end{definition}
%This governs how the outer label is formatted, where \meta{text}
@@ -4053,8 +4773,7 @@
%\renewcommand*{\DTLdisplayinnerlabel}[1]{\textsf{#1}}
%\renewcommand*{\DTLdisplayouterlabel}[1]{\textsf{#1}}
%\DTLpiechart{variable=\quantity,innerlabel={\DTLpiepercent
-%\%},outerlabel={\name\ (\DTLpievariable)}}{fruit}{%
-%\name=Name,\quantity=Quantity}
+%\%},outerlabel={\name\ (\DTLpievariable)}}{fruit}{\name=Name,\quantity=Quantity}
%\caption{A pie chart (changing the label format)}
%\label{fig:piechartlabelformat}
%\end{figure}
@@ -4063,42 +4782,43 @@
%\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}
+%eight segments of the pie chart. If you require more than
+%eight segments or if you want to change the default colours, you
+%will need to use
+%\begin{definition}[\DescribeMacro{\DTLsetpiesegmentcolor}]%
%\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}
+%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}.
+%
+%It is a good idea to set the colours so that each segment colour
+%is somehow relevant to whatever the segment represents. For
+%example, in the previous examples of pie charts depicting fruit,
+%some of default colours were inappropriate. Whilst red is
+%appropriate for apples and green is appropriate for pears, blue
+%doesn't really correspond to lemons or limes.
+%
+%\begin{definition}[\DescribeMacro{\DTLdopiesegmentcolor}]%
%\cs{DTLdopiesegmentcolor}\meta{n}
%\end{definition}
%This sets the current text colour to that of the \meta{n}th
%segment.
%
-%\DescribeMacro{\DTLdocurrentpiesegmentcolor}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLdocurrentpiesegmentcolor}]%
%\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}
+%\begin{definition}[\DescribeMacro{\DTLpieoutlinecolor}]%
%\cs{DTLpieoutlinecolor}
%\end{definition}
%This sets the outline colour for the pie chart. The default is
%black.
%
-%\DescribeMacro{\DTLpieoutlinewidth}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLpieoutlinewidth}]%
%\cs{DTLpieoutlinewidth}
%\end{definition}
%This is a length that governs the line width of the outline. The
@@ -4110,13 +4830,15 @@
%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}.
+%of the segment to which it belongs. The third segment (lemons and
+%limes) is set to yellow and the fourth segment (peaches) is set
+%to pink. In addition, a legend is created using \ics{DTLforeach}.
%\begin{verbatim}
%\begin{figure}[htbp]
%\centering
%\setlength{\DTLpieoutlinewidth}{2pt}
+%\DTLsetpiesegmentcolor{3}{yellow}
+%\DTLsetpiesegmentcolor{4}{pink}
%\renewcommand*{\DTLdisplayinnerlabel}[1]{\textsf{#1}}
%\renewcommand*{\DTLdisplayouterlabel}[1]{%
%\DTLdocurrentpiesegmentcolor
@@ -4144,13 +4866,14 @@
%\begin{figure}[htbp]
%\centering
%\setlength{\DTLpieoutlinewidth}{2pt}
+%\DTLsetpiesegmentcolor{3}{yellow}
+%\DTLsetpiesegmentcolor{4}{pink}
%\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}
+%\%},outerlabel={\name\\(\DTLpievariable)}}{fruit}{\name=Name,\quantity=Quantity}
%\begin{tabular}[b]{ll}
%\DTLforeach{fruit}{\name=Name}{\DTLiffirstrow{}{\\}\relax
%\DTLdocurrentpiesegmentcolor\rule{10pt}{10pt} &
@@ -4165,20 +4888,18 @@
%\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.)
+%a \env{tikzpicture} environment (defined by the \sty{tikz} package).
%
-%\DescribeMacro{\DTLpieatbegintikz}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLpieatbegintikz}]%
%\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.
+%chart (but be careful not to distort the chart).
%
-%\DescribeMacro{\DTLpieatendtikz}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLpieatendtikz}]%
%\cs{DTLpieatendtikz}
%\end{definition}
%The macro \cs{DTLpieatendtikz} is called at the end of the
@@ -4191,6 +4912,8 @@
%\begin{verbatim}
%\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}
@@ -4219,8 +4942,8 @@
%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}
+%
+%\begin{definition}[\DescribeMacro{\DTLplot}]%
%\cs{DTLplot}\oarg{condition}\marg{db list}\marg{settings}
%\end{definition}
%This command creates a plot (inside a \env{tikzpicture} environment)
@@ -4236,7 +4959,7 @@
%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:
+%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.
@@ -4284,7 +5007,7 @@
%\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
+%"lines" (only lines) or "markers" (only markers). The default is
%"markers".
%
%\item[\setting{DTLplot}{axes}] This setting governs whether
@@ -4587,13 +5310,11 @@
%
%The \sty{datatool} package provides two hooks used at the beginning
%and end of the \env{tikzpicture} environment:
-%\DescribeMacro{\DTLplotatbegintikz}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLplotatbegintikz}]%
%\cs{DTLplotatbegintikz}
%\end{definition}\noindent
%and
-%\DescribeMacro{\DTLplotatendtikz}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLplotatendtikz}]%
%\cs{DTLplotatendtikz}
%\end{definition}
%They are both defined to do nothing by default, but can be redefined
@@ -4601,8 +5322,7 @@
%using these hooks, so you can use the same co-ordinates as those
%in the data sets.
%
-%\DescribeMacro{\DTLaddtoplotlegend}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLaddtoplotlegend}]%
%\cs{DTLaddtoplotlegend}\marg{marker}\marg{line style}\marg{text}
%\end{definition}
%This adds a new row to the plot legend where \meta{marker} is
@@ -4656,45 +5376,39 @@
%the plot created using \ics{DTLplot}. These lengths can be
%changed using \cs{setlength}.
%
-%\DescribeMacro{\DTLplotwidth}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLplotwidth}]%
%\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}
+%\begin{definition}[\DescribeMacro{\DTLplotheight}]%
%\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}
+%\begin{definition}[\DescribeMacro{\DTLticklength}]%
%\cs{DTLticklength}
%\end{definition}
%This governs the length of the tick marks. The default value is
%5pt.
%
-%\DescribeMacro{\DTLminorticklength}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLminorticklength}]%
%\cs{DTLminorticklength}
%\end{definition}
%This governs the length of the minor tick marks. The default value is
%2pt.
%
-%\DescribeMacro{\DTLticklabeloffset}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLticklabeloffset}]%
%\cs{DTLticklabeloffset}
%\end{definition}
%This governs the distance from the axis to the tick labels. The
%default value is 8pt.
%
-%\DescribeMacro{\DTLmintickgap}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLmintickgap}]%
%\cs{DTLmintickgap}
%\end{definition}
%This is the minimum distance allowed between tick marks. If the
@@ -4702,15 +5416,13 @@
%be tick marks at either end of the axis. The default value is
%20pt.
%
-%\DescribeMacro{\DTLlegendxoffset}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLlegendxoffset}]%
%\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}
+%\begin{definition}[\DescribeMacro{\DTLlegendyoffset}]%
%\cs{DTLlegendyoffset}
%\end{definition}
%This is the vertical distance from the border of the plot to the
@@ -4741,8 +5453,7 @@
%These macros govern the appearance of plots created using
%\ics{DTLplot}. They can be changed using \cs{renewcommand}.
%
-%\DescribeMacro{\DTLplotmarks}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLplotmarks}]%
%\cs{DTLplotmarks}
%\end{definition}
%This must be a comma separated list of \sty{pgf} code to create the
@@ -4751,8 +5462,7 @@
%for generating plots using \cs{pgfuseplotmark}. See the \sty{pgf}
%manual for more details.
%
-%\DescribeMacro{\DTLplotmarkcolors}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLplotmarkcolors}]%
%\cs{DTLplotmarkcolors}
%\end{definition}
%This must be a comma separated list of defined colours to apply to the
@@ -4760,8 +5470,7 @@
%listed. If this macro is set to empty, the current colour will
%be used instead.
%
-%\DescribeMacro{\DTLplotlines}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLplotlines}]%
%\cs{DTLplotlines}
%\end{definition}
%This must be a comma separated list of \sty{pgf} code to set the
@@ -4770,8 +5479,7 @@
%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}
+%\begin{definition}[\DescribeMacro{\DTLplotlinecolors}]%
%\cs{DTLplotlinecolors}
%\end{definition}
%This must be a comma separated list of defined colours to apply to the
@@ -4779,9 +5487,8 @@
%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}
+%\begin{definition}[\DescribeMacro{\DTLXAxisStyle}]%
+%\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 "-"
@@ -4793,15 +5500,13 @@
%\renewcommand*{\DTLXAxisStyle}{->}
%\end{verbatim}
%
-%\DescribeMacro{\DTLYAxisStyle}
-%\begin{definition}
-%\cs{DTLyaxisstyle}
+%\begin{definition}[\DescribeMacro{\DTLYAxisStyle}]%
+%\cs{DTLYAxisStyle}
%\end{definition}
%This governs the style of the $y$ axis. It is analogous to
-%\cs{DTLxaxisstyle} described above.
+%\cs{DTLXAxisStyle} described above.
%
-%\DescribeMacro{\DTLmajorgridstyle}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLmajorgridstyle}]%
%\cs{DTLmajorgridstyle}
%\end{definition}
%This specifies the format of the major grid lines.
@@ -4809,8 +5514,7 @@
%optional argument of \cs{draw}. The default value is
%"color=gray,-" which indicates a grey solid line.
%
-%\DescribeMacro{\DTLminorgridstyle}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLminorgridstyle}]%
%\cs{DTLminorgridstyle}
%\end{definition}
%This specifies the format of the minor grid lines.
@@ -4818,8 +5522,7 @@
%optional argument of \cs{draw}. The default value is
%"color=gray,loosely dotted" which indicates a grey dotted line.
%
-%\DescribeMacro{\DTLformatlegend}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLformatlegend}]%
%\cs{DTLformatlegend}\marg{legend}
%\end{definition}
%This formats the entire legend, which is passed as the argument.
@@ -4827,8 +5530,8 @@
%a white background, a black frame.
%
%\subsection{Adding to a Plot Stream}
-%\DescribeMacro{\DTLplotstream}
-%\begin{definition}
+%
+%\begin{definition}[\DescribeMacro{\DTLplotstream}]%
%\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}
@@ -5009,7 +5712,8 @@
%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}".
+%"\usepackage{databar}". You must also have the \sty{pgf} package
+%installed.
%
%Bar charts can either be vertical or horizontal, the default is
%vertical. In this section the $x$ axis refers to the horizontal
@@ -5033,23 +5737,22 @@
%The \sty{databar} package options are as follows:
%\begin{description}
%\item[{\pkgopt[databar]{color}}] Created coloured bar charts
-%(default.)
+%(default).
%
%\item[{\pkgopt[databar]{gray}}] Created grey scale bar charts.
%
%\item[{\pkgopt[databar]{vertical}}] Created vertical bar charts
-%(default.)
+%(default).
%
%\item[{\pkgopt[databar]{horizontal}}] Created horizontal bar charts.
%\end{description}
%
%
-%\DescribeMacro{\DTLbarchart}
-%\begin{definition}
+%
+%\begin{definition}[\DescribeMacro{\DTLbarchart}]%
%\cs{DTLbarchart}\oarg{condition}\marg{db name}\marg{settings}\marg{values}
%\end{definition}
-%\DescribeMacro{\DTLmultibarchart}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLmultibarchart}]%
%\cs{DTLmultibarchart}\oarg{condition}\marg{db name}\marg{settings}\marg{values}
%\end{definition}
%These commands both create a bar chart from the information in
@@ -5145,7 +5848,7 @@
%\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.
+%bar chart). If the value is omitted, "true" is assumed.
%\end{description}
%
%\begin{example}{A Basic Bar Chart}{ex:barchart}
@@ -5171,22 +5874,20 @@
%
%\subsection{Changing the Appearance of a Bar Chart}
%
-%\DescribeMacro{\DTLbarchartlength}
-%\begin{definition}
+%
+%\begin{definition}[\DescribeMacro{\DTLbarchartlength}]%
%\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}
+%\begin{definition}[\DescribeMacro{\DTLbarwidth}]%
%\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}
+%\begin{definition}[\DescribeMacro{\DTLbarlabeloffset}]%
%\cs{DTLbarlabeloffset}
%\end{definition}
%This specifies the distance from the $x$ axis to the lower bar label.
@@ -5201,58 +5902,75 @@
%counter \counterfmt{DTLbarroundvar}. You must use \cs{setcounter}
%to change this value.
%
-%\DescribeMacro{\DTLsetbarcolor}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLsetbarcolor}]%
%\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.
+%It is recommended that you set the colour of each bar to
+%correspond with whatever the bar represents.
%
-%\DescribeMacro{\DTLdobarcolor}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLdobarcolor}]%
%\cs{DTLdobarcolor}\marg{n}
%\end{definition}
%This sets the current colour to the colour of the \meta{n}th bar.
%
-%\DescribeMacro{\DTLbaroutlinecolor}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLbaroutlinecolor}]%
%\cs{DTLbaroutlinecolor}
%\end{definition}
%This macro contains the colour of the bar outlines. This defaults
%to "black".
%
-%\DescribeMacro{\DTLbaroutlinewidth}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLbaroutlinewidth}]%
%\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}
+%
+%\begin{definition}[\DescribeMacro{\DTLbaratbegintikz}]%
%\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}
+%\begin{definition}[\DescribeMacro{\DTLbaratendtikz}]%
%\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}
+%\begin{definition}[\DescribeMacro{\DTLeverybarhook}]%
+%\cs{DTLeverybarhook}
+%\end{definition}
+%The specifies code to apply at every bar. Within the definition
+%of \cs{DTLeverybarhook} you can use the commands
+%\DescribeMacro{\DTLstartpt}\cs{DTLstartpt} (the start
+%of the bar), \DescribeMacro{\DTLmidpt}\cs{DTLmidpt}
+%(the mid point of the bar) and
+%\DescribeMacro{\DTLendpt}\cs{DTLendpt} (the end of the bar). For
+%example (using the earlier "fruit" database):
+%\begin{verbatim}
+%\renewcommand*{\DTLeverybarhook}{%
+%\pgftext[at=\DTLmidpt]{\insertName\space(\insertValue)}%
+%}
+%\DTLbarchart{variable=\insertValue,axes=both,
+%ylabel=Quantity,max=50,verticalbars=false
+%}%
+%{fruit}{\insertValue=Value,\insertName=Name}
+%\end{verbatim}
+%This puts the name followed by the quantity in brackets in the
+%middle of the bar.
+%
+%\begin{definition}[\DescribeMacro{\ifDTLverticalbars}]%
%\cs{ifDTLverticalbars}
%\end{definition}
%This conditional governs whether the chart uses vertical or
%horizontal bars.
%
-%\DescribeMacro{\DTLbarXlabelalign}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLbarXlabelalign}]%
%\cs{DTLbarXlabelalign}
%\end{definition}
%This specifies the text alignment of the lower bar labels. This
@@ -5262,57 +5980,51 @@
%package option or the \setting{DTLbarchart}{verticalbars}"=false"
%setting.
%
-%\DescribeMacro{\DTLbarYticklabelalign}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLbarYticklabelalign}]%
%\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}
+%\begin{definition}[\DescribeMacro{\DTLbardisplayYticklabel}]%
%\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}
+%\begin{definition}[\DescribeMacro{\DTLdisplaylowerbarlabel}]%
%\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}
+%\begin{definition}[\DescribeMacro{\DTLdisplaylowermultibarlabel}]%
%\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}
+%\begin{definition}[\DescribeMacro{\DTLdisplayupperbarlabel}]%
%\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}
+%\begin{definition}[\DescribeMacro{\DTLdisplayuppermultibarlabel}]%
%\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}
+%\begin{example}{A 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
+%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.
@@ -5332,8 +6044,7 @@
%\centering
%\setlength{\DTLbaroutlinewidth}{1pt}
%\DTLbarchart{variable=\theQuantity,barlabel=\theName,
-%upperbarlabel=\theQuantity}{fruit}{%
-%\theQuantity=Quantity,\theName=Name}
+%upperbarlabel=\theQuantity}{fruit}{\theQuantity=Quantity,\theName=Name}
%\caption[A bar chart (labelled)]{A bar chart}
%\label{fig:annotebarchart}
%\end{figure}
@@ -5414,8 +6125,7 @@
%Both \cs{DTLbarchart} and \cs{DTLmultibarchart} set the following
%macros, which may be used in \cs{DTLbaratbegintikz} and
%\cs{DTLbaratendtikz}:
-%\DescribeMacro{\DTLbarchartwidth}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLbarchartwidth}]%
%\cs{DTLbarchartwidth}
%\end{definition}
%This is the overall width of the bar chart. In the case of
@@ -5428,18 +6138,16 @@
%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.)
+%group gap (as specified by the \setting{DTLmultibarchart}{groupgap} setting).
%
-%\DescribeMacro{\DTLnegextent}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLnegextent}]%
%\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}
+%\begin{definition}[\DescribeMacro{\DTLbarmax}]%
%\cs{DTLbarmax}
%\end{definition}
%This is set to the maximum extent of the bar chart. (This value
@@ -5585,7 +6293,7 @@
%\end{example}
%
%\section{Converting a \texorpdfstring{\BibTeX}{BibTeX} database
-%into a datatool database
+%into a \texorpdfstring{\sty{datatool}}{datatool} database
%(\texorpdfstring{\sty{databib}}{databib} package)}
%\label{sec:databib}
%
@@ -5622,12 +6330,12 @@
%
%\BibTeX\ is an external application used in conjunction with \LaTeX.
%When you run \BibTeX, you need to specify the name of the document's
-%auxiliary file (without the \ext{aux} extension.) \BibTeX\ then reads
+%auxiliary file (without the \ext{aux} extension). \BibTeX\ then reads
%this file and looks for the commands \cs{bibstyle} (which indicates
%which bibliography style (\ext{bst}) file to load), \cs{bibdata}
%(which indicates which bibliography database (\ext{bib}) files to
%load) and \cs{citation} (produced by \cs{cite} and \cs{nocite}, which
-%indicates which entries should be included in the bibliography.)
+%indicates which entries should be included in the bibliography).
%\BibTeX\ then creates a file with the extension \ext{bbl} which
%contains the bibliography, formatted according to the layout defined
%in the bibliography style file.
@@ -5797,13 +6505,12 @@
%\label{sec:loadbbl}
%
%The \sty{databib} package always requires the \texttt{databib.bst}
-%bibliography style file (which is supplied with this bundle.)
+%bibliography style file (which is supplied with this bundle).
%You need to use \cs{cite} or \cs{nocite} as usual. If you want to
%add all entries in the \ext{bib} file to the \sty{datatool} database,
%you can use "\nocite{*}".
%
-%\DescribeMacro{\DTLloadbbl}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLloadbbl}]%
%\cs{DTLloadbbl}\oarg{bbl name}\marg{db name}\marg{bib list}
%\end{definition}
%This command performs several functions:
@@ -5836,7 +6543,7 @@
%information will be added to \meta{db name}.
%
%\importantpar Note that
-%\cs{DTLloaddb} doesn't generate any text. Once you have loaded
+%\cs{DTLloadbbl} doesn't generate any text. Once you have loaded
%the data, you can display the bibliography uses
%\cs{DTLbibliography} (described below) or you can iterate
%through it using \cs{DTLforeachbibentry} described in
@@ -5846,18 +6553,18 @@
%the following additional fields: "isbn", "doi", "pubmed", "url"
%and "abstract".
%However these fields are ignored by the three predefined
-%\sty{databib} styles ("plain", "abbrv" and "alpha".) If you
+%\sty{databib} styles ("plain", "abbrv" and "alpha"). If you
%want these fields to be displayed in the bibliography you will
-%need to modify the bibliography style (see \autoref{sec:modbibstyle}.)
+%need to modify the bibliography style (see \autoref{sec:modbibstyle}).
%
%\subsection{Displaying a \texorpdfstring{\sty{databib}}{databib}
%database}
%\label{sec:thebib}
%
%A \sty{databib} database which has been loaded using
-%\cs{DTLloaddb} (described in \autoref{sec:loadbbl}) can be
+%\cs{DTLloadbbl} (described in \autoref{sec:loadbbl}) can be
%displayed using:
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLbibliography}]
%\cs{DTLbibliography}\oarg{conditions}\marg{db name}
%\end{definition}\noindent
%where \meta{db name} is the name of the database.
@@ -5867,8 +6574,7 @@
%\cs{DTLforeach} \emph{In addition}, you may use the following
%commands:
%
-%\DescribeMacro{\DTLbibfieldexists}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLbibfieldexists}]%
%\cs{DTLbibfieldexists}\marg{field label}
%\end{definition}
%This tests whether the field with the given label exists for the
@@ -5888,8 +6594,7 @@
%\DTLbibliography[\DTLbibfieldexists{Year}]{mybib}
%\end{verbatim}
%
-%\DescribeMacro{\DTLbibfieldiseq}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLbibfieldiseq}]%
%\cs{DTLbibfieldiseq}\marg{field label}\marg{value}
%\end{definition}
%This tests whether the value of the field given by
@@ -5901,8 +6606,7 @@
%\DTLbibliography[\DTLbibfieldiseq{Year}{2004}]{mybib}
%\end{verbatim}
%
-%\DescribeMacro{\DTLbibfieldcontains}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLbibfieldcontains}]%
%\cs{DTLbibfieldcontains}\marg{field label}\marg{sub string}
%\end{definition}
%This tests whether the value of the field given by \meta{field label}
@@ -5913,8 +6617,7 @@
%\DTLbibliography[\DTLbibfieldcontains{Author}{Knuth}]{mybib}
%\end{verbatim}
%
-%\DescribeMacro{\DTLbibfieldislt}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLbibfieldislt}]%
%\cs{DTLbibfieldislt}\marg{field label}\marg{value}
%\end{definition}
%This tests whether the value of the field given by \meta{field label}
@@ -5926,8 +6629,7 @@
%\DTLbibliography[\DTLbibfieldislt{Year}{1983}]{mybib}
%\end{verbatim}
%
-%\DescribeMacro{\DTLbibfieldisle}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLbibfieldisle}]%
%\cs{DTLbibfieldisle}\marg{field label}\marg{value}
%\end{definition}
%This tests whether the value of the field given by \meta{field label}
@@ -5939,8 +6641,7 @@
%\DTLbibliography[\DTLbibfieldisle{Year}{1983}]{mybib}
%\end{verbatim}
%
-%\DescribeMacro{\DTLbibfieldisgt}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLbibfieldisgt}]%
%\cs{DTLbibfieldisgt}\marg{field label}\marg{value}
%\end{definition}
%This tests whether the value of the field given by \meta{field label}
@@ -5952,8 +6653,7 @@
%\DTLbibliography[\DTLbibfieldisgt{Year}{1983}]{mybib}
%\end{verbatim}
%
-%\DescribeMacro{\DTLbibfieldisge}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLbibfieldisge}]%
%\cs{DTLbibfieldisge}\marg{field label}\marg{value}
%\end{definition}
%This tests whether the value of the field given by \meta{field label}
@@ -5968,7 +6668,8 @@
%Note that \cs{DTLbibliography} uses \cs{DTLforeachbibentry}
%(described in \autoref{sec:foreachbib}) so you may also use
%test the value of the counter \counterfmt{DTLbibrow} within
-%\meta{conditions}.
+%\meta{conditions}. You may also use the boolean commands defined
+%by the \sty{ifthen} package, such as \ics{not}.
%
%\begin{example}{Creating a list of publications since a given year}{ex:bibsince2000}
%Suppose my boss has asked me to produce a list of my
@@ -6012,7 +6713,7 @@
%\bibstyle{databib}
%\end{verbatim}
%to the auxiliary file. This tells \BibTeX\ to use "databib.bst"
-%(which is supplied with this package.) You therefore shouldn't
+%(which is supplied with this package). You therefore shouldn't
%use \cs{bibliographystyle}.
%
%\item writes the line
@@ -6032,7 +6733,7 @@
%\end{enumerate}
%
%\item In my \BibTeX\ database ("nlct.bib" in this example), I
-%have remember to use the \BibTeX\ month macros: "jan", "feb"
+%have remembered to use the \BibTeX\ month macros: "jan", "feb"
%etc. This means that the months are stored in the database in
%the form \cs{DTLmonthname}\marg{nn}, where \meta{nn} is a two
%digit number from 01 to 12. \cs{DTLsort} ignores command names
@@ -6085,7 +6786,7 @@
%The style of the bibliography produced using \cs{DTLbibliography}
%depends on the \pkgopt[databib]{style}
%package option, or can be set using
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLbibliographystyle}]%
%\cs{DTLbibliographystyle}\marg{style}
%\end{definition}
%Note that this is \emph{not} the same as \cs{bibliographystyle},
@@ -6103,7 +6804,7 @@
%standard \BibTeX\ styles of the same name, but are by no means
%identical. The most notable difference is that these styles
%do not sort the bibliography. It is up to you to sort the
-%bibliography using \cs{DTLsort} (described in \autoref{sec:sort}.)
+%bibliography using \cs{DTLsort} (described in \autoref{sec:sort}).
%
%\subsubsection{Modifying an existing style}
%\label{sec:modbibstyle}
@@ -6116,12 +6817,10 @@
%\autoref{sec:src:bibnames}, \autoref{sec:src:displaybib}
%and \autoref{sec:src:bibstyle}.
%
-%\DescribeMacro{\DTLformatauthor}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLformatauthor}]%
%\cs{DTLformatauthor}\marg{von part}\marg{surname}\marg{jr part}\marg{forenames}
%\end{definition}
-%\DescribeMacro{\DTLformateditor}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLformateditor}]%
%\cs{DTLformateditor}\marg{von part}\marg{surname}\marg{jr part}\marg{forenames}
%\end{definition}
%These commands are used to format an author/editor's name,
@@ -6134,8 +6833,7 @@
%
%Within \cs{DTLformatauthor} and \cs{DTLformateditor}, you may
%use the following commands:
-%\DescribeMacro{\DTLformatforenames}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLformatforenames}]%
%\cs{DTLformatforenames}\marg{forenames}
%\end{definition}
%This is used by the "plain" style to display the author's
@@ -6144,12 +6842,11 @@
%\cs{DTLcheckendsperiod} to prevent a sentence ending full stop
%from following an abbreviation full stop}.
%
-%\DescribeMacro{\DTLformatabbrvforenames}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLformatabbrvforenames}]%
%\cs{DTLformatabbrvforenames}\marg{forenames}
%\end{definition}
%This is used by the "abbrv" style to display the author's
-%initials (which are determined from \meta{forenames}.)
+%initials (which are determined from \meta{forenames}).
%Note that if any of the authors has a name starting with an
%accent, the accented letter must be grouped in order for this
%command to work. For example:
@@ -6160,25 +6857,22 @@
%in \autoref{sec:strings}, so if you want to change the way the
%initials are displayed (e.g.\ put a space between them) you will
%need to redefine the commands used by \cs{DTLstoreinitials} (such
-%as \cs{DTLbetweeninitials}.)
+%as \cs{DTLbetweeninitials}).
%
-%\DescribeMacro{\DTLformatsurname}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLformatsurname}]%
%\cs{DTLformatsurname}\marg{surname}
%\end{definition}
%This displays its argument by default\footnote{It also checks
%whether the surname ends with a full stop using
%\cs{DTLcheckendsperiod}}.
%
-%\DescribeMacro{\DTLformatvon}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLformatvon}]%
%\cs{DTLformatvon}\marg{von part}
%\end{definition}
%If the \meta{von part} is empty, this command does nothing,
%otherwise it displays its argument followed by a
%non-breakable space.
-%\DescribeMacro{\DTLformatjr}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLformatjr}]%
%\cs{DTLformatjr}\marg{jr part}
%\end{definition}
%If the \meta{jr part} is empty, this command displays nothing,
@@ -6284,7 +6978,7 @@
%\begin{example}{Highlighting a given author}{ex:highlightauthor}
%Suppose my boss wants me to produce a list of all my publications
%(which I have stored in the file "nlct.bib", as in
-%\autoref{ex:bibsince2000}.) Most of my
+%\autoref{ex:bibsince2000}). Most of my
%publications have multiple co-authors, but suppose my boss would
%like me to highlight my name so that when he skims through
%the document, he can easily see my name in the list of
@@ -6348,12 +7042,10 @@
%to list journal papers and conference proceedings in separate
%sections. In which case, you may find it easier to iterate through
%the bibliography using:
-%\DescribeMacro{\DTLforeachbib}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLforeachbib}]%
%\cs{DTLforeachbib}\oarg{condition}\marg{db name}\marg{text}
%\end{definition}
-%\DescribeMacro{\DTLforeachbib*}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLforeachbib*}]%
%\cs{DTLforeachbib*}\oarg{condition}\marg{db name}\marg{text}
%\end{definition}
%This iterates through the \sty{databib} database called
@@ -6364,7 +7056,7 @@
%\begin{itemize}
%\item \cs{DBIBcitekey} \DescribeMacro{\DBIBcitekey}This is the
%unique label which identifies the current entry (as used in the
-%argument of \cs{cite} and \cs{nocite}.)
+%argument of \cs{cite} and \cs{nocite}).
%
%\item \cs{DBIBentrytype} \DescribeMacro{\DBIBentrytype}This
%is the current entry type, and will be one of: "article", "book",
@@ -6372,12 +7064,11 @@
%"manual", "mastersthesis", "misc", "phdthesis", "proceedings",
%"techreport" or "unpublished". (Note that even if you used the
%entry type "conference" in your \ext{bib} file, its entry type
-%will be set to "inproceedings".)
+%will be set to "inproceedings").
%\end{itemize}
%
%The remaining fields may be accessed using:
-%\DescribeMacro{\DTLbibfield}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLbibfield}]%
%\cs{DTLbibfield}\marg{field label}
%\end{definition}\noindent
%where \meta{field label} may be one of: "Address", "Author",
@@ -6388,8 +7079,7 @@
%"Abstract" or "Url".
%
%You can determine if a field exists for a given entry using
-%\DescribeMacro{\DTLifbibfieldexists}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLifbibfieldexists}]%
%\cs{DTLifbibfieldexists}\marg{field label}\marg{true part}\marg{false
%part}
%\end{definition}
@@ -6397,8 +7087,7 @@
%bibliography entry, it does \meta{true part}, otherwise it
%does \meta{false part}.
%
-%\DescribeMacro{\DTLifbibanyfieldexists}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLifbibanyfieldexists}]%
%\cs{DTLifanybibfieldexists}\marg{field label list}\marg{true
%part}\marg{false part}
%\end{definition}
@@ -6408,8 +7097,7 @@
%current bibliography item, this does \meta{true part}, otherwise
%it does \meta{false part}.
%
-%\DescribeMacro{\DTLformatbibentry}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLformatbibentry}]%
%\cs{DTLformatbibentry}
%\end{definition}
%This formats the bibliography entry for the current row. It
@@ -6418,8 +7106,7 @@
%is given by \cs{DBIBentrytype}. These commands are defined
%by the bibliography style.
%
-%\DescribeMacro{\DTLcomputewidestbibentry}
-%\begin{definition}
+%\begin{definition}[\DescribeMacro{\DTLcomputewidestbibentry}]%
%\cs{DTLcomputewidestbibentry}\marg{conditions}\marg{db
%name}\marg{bib label}\marg{cmd}
%\end{definition}
@@ -6477,9 +7164,145 @@
%\end{verbatim}
%\end{example}
%
+%\subsection{Multiple Bibliographies}
+%\label{sec:multibib}
+%
+%It is possible to have more than one bibliography in a document,
+%but it then becomes necessary to have a separate auxiliary file
+%for each bibliography, and each auxiliary file must then be
+%passed to \BibTeX. In order to do this, you need to use
+%\begin{definition}[\DescribeMacro{\DTLmultibibs}]%
+%\cs{DTLmultibibs}\marg{name list}
+%\end{definition}
+%where \meta{name list} is a comma separated list of names,
+%\meta{name}. For each \meta{name}, this command creates an
+%auxiliary file called \meta{name}".aux" (note that this
+%command may only be used in the preamble).
+%
+%When you want to cite an entry for a given bibliography named
+%in \cs{DTLmultibibs}, you must use:
+%\begin{definition}[\DescribeMacro{\DTLcite}]%
+%\cs{DTLcite}\oarg{text}\marg{mbib}\marg{cite key list}
+%\end{definition}\noindent
+%This is analogous to \cs{cite}\oarg{text}\marg{cite key list},
+%but writes the \cs{citation} command to \meta{mbib}".aux" instead
+%of to the document's main auxiliary file. It also ensures that
+%the cross-referencing labels are based on \meta{mbib}, to allow
+%you to have the same reference in more than one bibliography
+%without incurring a ``multiply defined'' warning message. Note
+%that you can still use \cs{cite} to add citation information to
+%the main auxiliary file.
+%
+%If you want to add an entry to the bibliography without producing
+%any text, you can use
+%\begin{definition}[\DescribeMacro{\DTLnocite}]
+%\cs{DTLnocite}\marg{mbib}\marg{cite key list}
+%\end{definition}\noindent
+%which is analogous to \cs{nocite}\marg{cite key list}, where
+%again the citation information is written to \meta{mbib}".aux"
+%instead of the document's main auxiliary file.
+%
+%Note that for both \cs{DTLcite} and \cs{DTLnocite} the
+%\meta{mbib} part must be one of the names listed in
+%\cs{DTLmultibibs}.
+%
+%\begin{definition}[\DescribeMacro{\DTLloadmbbl}]%
+%\cs{DTLloadmbbl}\marg{mbib}\marg{db name}\marg{bib list}
+%\end{definition}
+%This is analogous to \cs{DTLloadbbl}\marg{db name}\marg{bib list}
+%described in \autoref{sec:loadbbl}. (Again \meta{mbib} must be
+%one of the names listed in \cs{DTLmultibibs}.) This creates
+%a new \sty{datatool} database called \meta{db name} and loads the
+%bibliography information from \meta{mbib}".bbl" (if it exists).
+%
+%\begin{definition}[\DescribeMacro{\DTLmbibliography}]%
+%\cs{DTLmbibliography}\oarg{condition}\marg{mbib}\marg{db name}
+%\end{definition}
+%This is analogous to \cs{DTLbibliography}\oarg{condition}\marg{db name},
+%but is required when displaying a bibliography in which elements have
+%been cited using \cs{DTLcite} and \cs{DTLnocite}.
+%
+%\begin{example}{Multiple Bibliographies}{ex:multibib}
+%Suppose I need to create a document which contains a section listing
+%all my publications, but I also need to have separate sections
+%covering each of my research topics, with a mini-bibliography
+%at the end of each section. As in the earlier examples, all my
+%publications are stored in the file "nlct.bib" which is somewhere
+%on \TeX's path. Note that there will be some duplication as the
+%references in the mini-bibliographies will also appear in the
+%main bibliography at the end of the document, but using
+%\cs{DTLcite} and \cs{DTLmbibliography} ensures that all the
+%cross-referencing labels (and hyperlinks if they are enabled)
+%are unique.
+%\begin{verbatim}
+%\documentclass{article}
+%\usepackage{databib}
+%\DTLmultibibs{kernel,food}
+%\begin{document}
+%\section{Kernel methods}
+%In this section I'm going to describe some research work into
+%kernel methods, and in the process I'm going to cite some related
+%papers \DTLcite{kernel}{Cawley2007a,Cawley2006a}.
+%
+%\DTLloadmbbl{kernel}{kernelDB}{nlct}
+%\DTLmbibliography{kernel}{kernelDB}
+%
+%\section{Food research}
+%
+%In this section I'm going to describe some research work
+%in the area of food safety, and in the process, I'm going
+%to cite some related papers \DTLcite{food}{Peck1999,Barker1999a}
+%
+%\DTLloadmbbl{food}{foodDB}{nlct}
+%\DTLmbibliography{food}{foodDB}
+%
+%\cite{*}
+%\renewcommand{\refname}{Complete List of Publications}
+%\DTLloadbbl{fullDB}{nlct}
+%\DTLbibliography{fullDB}
+%\end{document}
+%\end{verbatim}
+%Notes:
+%\begin{enumerate}
+%\item This will create the files "kernel.aux" and "food.aux".
+%These will have to be passed to \BibTeX, in addition to the
+%documents main auxiliary file. So, if my document is called
+%"researchwork.tex", then I need to do:
+%\begin{verbatim}
+%latex researchwork
+%bibtex researchwork
+%bibtex kernel
+%bibtex food
+%latex researchwork
+%latex researchwork
+%\end{verbatim}
+%
+%\item "\cite{*}" is used to add all the entries in the bib file
+%to the main bibliography database. As before, \cs{DTLloadbbl}
+%and \cs{DTLbibliography} are used to load and display the main
+%bibliography.
+%\end{enumerate}
+%\end{example}
+%
+%\importantpar Don't try to directly input the ".bbl" file using
+%\cs{input} (or \cs{include}) instead of using \cs{DTLloadbbl}
+%or \cs{DTLloadmbbl} as these commands store the name of the required
+%database and initialise the database before loading the
+%\texttt{.bbl} file. Similarly, don't just copy the contents of
+%the ".bbl" file into your document without first defining the
+%database using \ics{DTLnewdb} and setting \ics{DTLBIBdbname} to
+%the name of the database.
+%
% \StopEventually{\clearpage\phantomsection
%\addcontentsline{toc}{section}{\refname}
% \DTLbibliography{docbib}
+%\section{Acknowledgements}
+%
+%Many thanks to Morten~H\o gholm for suggesting a much more
+%efficient way of storing the information in databases which
+%has significantly improved the time it takes to \LaTeX\ documents
+%containing large databases.
+%
%\phantomsection
%\addcontentsline{toc}{section}{Change History}\PrintChanges
%\phantomsection
@@ -6497,7 +7320,7 @@
%\subsection{Package Declaration}
% \begin{macrocode}
\NeedsTeXFormat{LaTeX2e}
-\ProvidesPackage{datatool}[2007/08/17 v1.01 (NLCT)]
+\ProvidesPackage{datatool}[2009/02/27 v2.0 (NLCT)]
% \end{macrocode}
% Load required packages:
% \begin{macrocode}
@@ -6507,6 +7330,10 @@
\RequirePackage{fp}
\RequirePackage{substr}
% \end{macrocode}
+%\changes{2.0}{2009 February 27}{added etex as a required package}
+% \begin{macrocode}
+\RequirePackage{etex}
+% \end{macrocode}
%
%\subsection{Package Options}
%\begin{macro}{\@dtl@separator}
@@ -8565,17 +9392,15 @@
%\end{definition}
% Test if the current row is the first row. (This takes
% \meta{condition}, the optional argument of \cs{DTLforeach},
-% into account.)
+% into account, so it may not correspond to row~1 of the
+% database.) Can only be used in \cs{DTLforeachrow}.
+%\changes{2.0}{2009 February 27}{modified to have different
+% definition depending on location}
% \begin{macrocode}
\newcommand{\DTLiffirstrow}[2]{%
-\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}
+ \PackageError{datatool}{\string\DTLiffirstrow\space can only
+ be used inside \string\DTLforeach}{}%
+}
% \end{macrocode}
%\end{macro}
%
@@ -8595,17 +9420,13 @@
% have to iterate through the database to count up the number
% of rows which meet the condition, and then do another pass,
% checking if the current row has reached that number.
-% This command requires at least v1.02 of the \sty{xfor} package.
%\changes{1.01}{2007 Aug 17}{fixed bug}
+%\changes{2.0}{2009 February 27}{modified to have different
+% definition depending on location}
% \begin{macrocode}
\newcommand{\DTLiflastrow}[2]{%
-\ifnum\dtlforeachlevel=0\relax
- \PackageError{datatool}{\string\DTLiflastrow\space can only
- be used inside \string\DTLforeach}{}%
-\else
-\ifx\@dtl@nextrow\@nnil
-#1\else #2\fi
-\fi
+ \PackageError{datatool}{\string\DTLiflastrow\space can only
+ be used inside \string\DTLforeach}{}%
}
% \end{macrocode}
%\end{macro}
@@ -8616,16 +9437,12 @@
%\end{definition}
% Determines whether the current row is odd (takes the optional
% argument of \cs{DTLforeach} into account.)
+%\changes{2.0}{2009 February 27}{modified to have different
+% definition depending on location}
% \begin{macrocode}
\newcommand{\DTLifoddrow}[2]{%
-\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
+ \PackageError{datatool}{\string\DTLifoddrow\space can only
+ be used inside \string\DTLforeach}{}%
}
% \end{macrocode}
%\end{macro}
@@ -9078,26 +9895,85 @@
%\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.
+% As from v2.0, the internal structure of the database has changed
+% to make it more efficient.\footnote{Thanks to Morten H\o gholm
+% for the suggestion.} The database is now stored in a token
+% register instead of a macro. Each row is represented as:\par
+%\verb|\db@row@elt@w|%
+%\verb|\db@row@id@w| \meta{row idx}\verb|\db@row@id@end@|%
+%\meta{column data}%
+%\verb|\db@row@id@w| \meta{row idx}\verb|\db@row@id@end@|%
+%\verb|\db@row@elt@end@|\par
+% where \meta{row idx} is the row index and \meta{column data} is
+% the data for each column in the row. Each column for a given
+% row is stored as:\par
+%\verb|\db@col@id@w| \meta{column idx}\verb|\db@col@id@end@|%
+%\verb|\db@col@elt@w| \meta{value}\verb|\db@col@elt@end@|%
+%\verb|\db@col@id@w| \meta{column idx}\verb|\db@col@id@end@|\par
+% where \meta{column idx} is the column index and \meta{value}
+% is the entry for the given column and row.
+%
+% Each row only has an associated index, but columns have
+% a unique identifying key as well as an associated index. Columns
+% also have an associated data type which may be: 0 (column
+% contains strings), 1 (column contains integers), 2 (column
+% contains real numbers), 3 (column contains currency) or
+% \meta{empty} (column contains no data). Since the key sometimes
+% has to be expanded, a header is also available in the event
+% that the user wants to use \cs{DTLdisplaydb} or
+% \cs{DTLdisplaylongdb} and requires a column header that would
+% cause problems if used as a key. The general column
+% information is stored in a token register where each column
+% has information stored in the form:\par
+%\verb|\db@plist@elt@w|%
+%\verb|\db@col@id@w| \meta{index}\verb|\db@col@id@end@|%
+%\verb|\db@key@id@w| \meta{key}\verb|\db@key@id@end@|%
+%\verb|\db@type@id@w| \meta{type}\verb|\db@type@id@end@|%
+%\verb|\db@header@id@w| \meta{type}\verb|\db@header@id@end@|%
+%\verb|\db@col@id@w| \meta{index}\verb|\db@col@id@end@|%
+%\verb|\db@plist@elt@end@|
+%
+% The column name (\meta{key}) is mapped to the column index
+% using \cs{dtl@ci@}\meta{db}"@"\meta{key} where \meta{db} is
+% the database name.
%
%\begin{macro}{\DTLnewdb}
+%\changes{2.0}{2009 February 27}{Changed way database is stored}
% \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.
+% initialises a database called \meta{name}.
% \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}
+% Check if there is already a database with this name.
+% \begin{macrocode}
+ \DTLifdbexists{#1}%
+ {%
+ \PackageError{datatool}{Database `#1' already exists}{}%
+ }%
+ {%
+% \end{macrocode}
+% Define new database. Add information message if in verbose
+% mode.
+% \begin{macrocode}
+ \dtl@message{Creating database `#1'}%
+% \end{macrocode}
+% Define token register used to store the contents of the database.
+% \begin{macrocode}
+ \expandafter\newtoks\csname dtldb@#1\endcsname
+% \end{macrocode}
+% Define token register used to store the column header information.
+% \begin{macrocode}
+ \expandafter\newtoks\csname dtlkeys@#1\endcsname{}%
+% \end{macrocode}
+% Define count register used to store the row count.
+% \begin{macrocode}
+ \expandafter\newcount\csname dtlrows@#1\endcsname
+% \end{macrocode}
+% Define count register used to store the column count.
+% \begin{macrocode}
+ \expandafter\newcount\csname dtlcols@#1\endcsname
+ }%
+}
% \end{macrocode}
%\end{macro}
%
@@ -9106,26 +9982,55 @@
% \cs{DTLrowcount}\marg{db name}
%\end{definition}
% The number of rows in the database called \meta{db name}.
+% (Doesn't check if database exists.)
% \begin{macrocode}
\newcommand*{\DTLrowcount}[1]{%
\expandafter\number\csname dtlrows@#1\endcsname}
% \end{macrocode}
%\end{macro}
%
+%\begin{macro}{\DTLcolumncount}
+%\begin{definition}
+% \cs{DTLcolumncount}\marg{db name}
+%\end{definition}
+% The number of columns in the database called \meta{db name}.
+% (Doesn't check if database exists.)
+%\changes{2.0}{2009 February 27}{new}%
+% \begin{macrocode}
+\newcommand*{\DTLcolumncount}[1]{%
+\expandafter\number\csname dtlcols@#1\endcsname}
+% \end{macrocode}
+%\end{macro}
+%
%\begin{macro}{\DTLifdbempty}
%\begin{definition}
-% \cs{DTLifempty}\marg{name}\marg{true part}\marg{false part}
+% \cs{DTLifdbempty}\marg{name}\marg{true part}\marg{false part}
%\end{definition}
-% Check if named database is empty (i.e.\ no rows have been added.)
+% Check if named database is empty (i.e.\ no rows have been added).
% \begin{macrocode}
\newcommand{\DTLifdbempty}[3]{%
-\DTLifdbexists{#1}{%
-\expandafter\ifx\csname dtldb@#1\endcsname\@empty
- #2%
-\else
- #3%
-\fi}{%
-\PackageError{Database `#1' doesn't exist}{}{}}}
+ \DTLifdbexists{#1}%
+ {\@DTLifdbempty{#1}{#2}{#3}}%
+ {\PackageError{Can't check if database `#1' is empty:
+ database doesn't exist}{}{}}%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@DTLifdbempty}
+%\begin{definition}
+% \cs{@sDTLifdbempty}\marg{name}\marg{true part}\marg{false part}
+%\end{definition}
+% Check if named existing database is empty. (No check performed
+% to determine if the database exists.)
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\newcommand{\@DTLifdbempty}[3]{%
+ \expandafter\ifnum\csname dtlrows@#1\endcsname=0\relax
+ #2%
+ \else
+ #3%
+ \fi
+}
% \end{macrocode}
%\end{macro}
%
@@ -9133,255 +10038,845 @@
%\begin{definition}
% \cs{DTLnewrow}\marg{db name}
%\end{definition}
-% Add a new row to named database.
+% Add a new row to named database. The starred version doesn't
+% check for the existence of the database.
+% \begin{macrocode}
+\newcommand*{\DTLnewrow}{%
+ \@ifstar\@sDTLnewrow\@DTLnewrow
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@DTLnewrow}
+%\begin{definition}
+% \cs{@DTLnewrow}\marg{db name}
+%\end{definition}
+% Add a new row to named database. (Checks for the existance
+% of the database.)
+% \begin{macrocode}
+\newcommand*{\@DTLnewrow}[1]{%
+\DTLifdbexists{#1}%
+ {\@sDTLnewrow{#1}}%
+ {\PackageErrors{datatool}{Can't add new row to database `#1':
+ database doesn't exist}{}}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@sDTLnewrow}
+%\begin{definition}
+% \cs{@DTLnewrow}\marg{db name}
+%\end{definition}
+% Add a new row to named existing database. (No check performed
+% to determine if the database exists.)
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\newcommand*{\@sDTLnewrow}[1]{%
+% \end{macrocode}
+% Increment row count.
+% \begin{macrocode}
+ \global\advance\csname dtlrows@#1\endcsname by 1\relax
+% \end{macrocode}
+% Append an empty row to the database
+% \begin{macrocode}
+ \toks@gput@right@cx{dtldb@#1}{%
+ \noexpand\db@row@elt@w%
+ \noexpand\db@row@id@w \number\csname dtlrows@#1\endcsname
+ \noexpand\db@row@id@end@%
+ \noexpand\db@row@id@w \number\csname dtlrows@#1\endcsname
+ \noexpand\db@row@id@end@%
+ \noexpand\db@row@elt@end@%
+ }%
+% \end{macrocode}
+% Display message on terminal and log file if in verbose mode.
% \begin{macrocode}
-\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{macro}{\DTLnewdbentry}
+%\begin{macro}{\dtlcolumnnum}
+% Count register to keep track of column index.
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\newcount\dtlcolumnnum
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtlrownum}
+% Count register to keep track of row index.
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\newcount\dtlrownum
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLifhaskey}
%\begin{definition}
-% \cs{DTLnewdbentry}\marg{db name}\marg{id}\marg{value}.
+%\cs{DTLifhaskey}\meta{db name}\meta{key}\meta{true part}\meta{false
+% part}
%\end{definition}
-% Adds an entry to the last row (adds new row if database is empty.)
+% Checks if the named database \meta{db name} has a column with label
+% \meta{key}. If column exists, do \meta{true part} otherwise
+% do \meta{false part}. The starred version doesn't check if
+% the named database exists.
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\newcommand*{\DTLifhaskey}{\@ifstar\@sDTLifhaskey\@DTLifhaskey}
+% \end{macrocode}
+%\end{macro}
%
-% 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}{\@DTLifhaskey}
+% Unstarred version of \cs{DTLifhaskey}
% \begin{macrocode}
-\newcommand{\DTLnewdbentry}[3]{%
+\newcommand{\@DTLifhaskey}[4]{%
+ \DTLifdbexists{#1}%
+ {%
+ \@sDTLifhaskey{#1}{#2}{#3}{#4}%
+ }%
+ {%
+ \PackageError{datatool}{Database `#1' doesn't exist}{}%
+ }%
+}
% \end{macrocode}
-% Set \cs{@dtl@dbvalue} to the value of this entry.
+%\end{macro}
+%\begin{macro}{\@sDTLifhaskey}
+% Starred version of \cs{DTLifhaskey}
% \begin{macrocode}
-\@dtl@toks{#3}%
-\edef\@dtl@dbvalue{\the\@dtl@toks}%
+\newcommand{\@sDTLifhaskey}[4]{%
+ \@ifundefined{dtl@ci@#1@#2}%
+ {%
% \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.
+% Key not defined
% \begin{macrocode}
-\edef\@dtl@dbid{#2}%
+ #4%
+ }%
+ {%
% \end{macrocode}
-% Set up the correct entry format:
+% Key defined
% \begin{macrocode}
-\edef\@dtl@dbentry{{\@dtl@dbid}{\the\@dtl@toks}}%
+ #3%
+ }%
+}
% \end{macrocode}
-% If database is empty, add new row.
+%\end{macro}
+%
+%\begin{macro}{\DTLgetcolumnindex}
+%\begin{definition}
+%\cs{DTLgetcolumnindex}\marg{cs}\marg{db}\marg{key}
+%\end{definition}
+% Gets index for column with label \meta{key} from database
+% \meta{db} and stores in \meta{cs} which must be a control
+% sequence.
+% Unstarred version checks if database and key exist, unstarred
+% version doesn't perform any checks.
+%\changes{2.0}{2009 February 27}{new}
% \begin{macrocode}
-\DTLifdbempty{#1}{\DTLnewrow{#1}}{}%
+\newcommand*{\DTLgetcolumnindex}{%
+ \@ifstar\@sdtl@getcolumnindex\@dtl@getcolumnindex
+}
% \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}.)
+%\end{macro}
+%
+%\begin{macro}{\@dtl@getcolumnindex}
+% Unstarred version of \cs{DTLgetcolumnindex}
+%\changes{2.0}{2009 February 27}{new}
% \begin{macrocode}
-\expandafter\dtl@choplast\expandafter{%
-\csname dtldb@#1\endcsname}{\@dtl@dbrest}{\@dtl@dblastrow}%
+\newcommand*{\@dtl@getcolumnindex}[3]{%
% \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.
+% Check if database exists.
% \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}}{%
+ \DTLifdbexists{#2}%
+ {%
% \end{macrocode}
-% Append entry to last row
+% Database exists. Now check if key exists.
% \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}%
-}%
+ \@sDTLifhaskey{#2}{#3}%
+ {%
% \end{macrocode}
-% Reconstruct list.
+% Key exists so go ahead and get column index.
% \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}}%
-}%
+ \@sdtl@getcolumnindex{#1}{#2}{#3}%
+ }%
+ {%
% \end{macrocode}
-% Set the keys
+% Key doesn't exists in named database.
% \begin{macrocode}
-\@dtl@setidtype{#1}{#2}{#3}%
-\expandafter\@dtl@setkeys\expandafter{#2}{#1}%
-}%
-\dtl@message{Added #2\space -> #3\space to database `#1'}%
+ \PackageError{datatool}{Database `#2' doesn't contain
+ key `#3'}{}%
+ }%
+ }%
+ {%
+% \end{macrocode}
+% Named database doesn't exist.
+% \begin{macrocode}
+ \PackageError{datatool}{Database `#2' doesn't exist}{}%
+ }%
}
% \end{macrocode}
%\end{macro}
%
-%\begin{macro}{\@dtl@setidtype}
+%\begin{macro}{\@dtl@getcolumnindex}
+% Starred version of \cs{DTLgetcolumnindex}.
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\newcommand*{\@sdtl@getcolumnindex}[3]{%
+ \expandafter\let\expandafter#1\csname dtl@ci@#2@#3\endcsname
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@columnindex}
%\begin{definition}
-% \cs{@dtl@setidtype}\marg{db name}\marg{id}\marg{value}
+% \cs{dtl@columnindex}\marg{db}\marg{key}
%\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.
-%\changes{1.01}{2007 Aug 17}{Added currency check}
-%\changes{1.01}{2007 Aug 17}{Fixed bug when setting
-% \cs{@dtl@tmpcount}}
+% Column index corresponding to \meta{key} in database \meta{db}.
+% (No check for existance of database or key.)
+%\changes{2.0}{2009 February 27}{new}
% \begin{macrocode}
-\newcommand{\@dtl@setidtype}[3]{%
+\newcommand*{\dtl@columnindex}[2]{%
+ \csname dtl@ci@#1@#2\endcsname
+}
% \end{macrocode}
-% Check the data type of this value.
+%\end{macro}
+%
+%\begin{macro}{\DTLgetkeyforcolumn}
+%\begin{definition}
+%\cs{DTLgetkeyforcolumn}\marg{key cs}\marg{db}\marg{column index}
+%\end{definition}
+% Gets the key associated with the given column index and stores
+% in \meta{key cs}. Unstarred version doesn't perform checks.
% \begin{macrocode}
-\@dtl@checknumerical{#3}%
+\newcommand*{\DTLgetkeyforcolumn}{%
+ \@ifstar\@sdtlgetkeyforcolumn\@dtlgetkeyforcolumn}
% \end{macrocode}
-% Store value if \cs{@dtl@value} to make it easier to test if it
-% is empty.
+%\end{macro}
+%
+%\begin{macro}{\@dtlgetkeyforcolumn}
% \begin{macrocode}
-\def\@dtl@value{#3}%
+\newcommand*{\@dtlgetkeyforcolumn}[3]{%
+ \DTLifdbexists{#2}%
+ {%
% \end{macrocode}
-% Determine if this key already has a data type assigned to it.
+% Check if index is in range.
% \begin{macrocode}
-\@ifundefined{@dtl@idtype@#1@#2}{%
+ \ifnum#3<1\relax
+ \PackageError{datatool}{Invalid column index \number#3}{%
+ Column indices start at 1}%
+ \else
+ \expandafter\ifnum\csname dtlcols@#2\endcsname<#3\relax
+ \PackageError{datatool}{Index \number#3\space out of
+ range for database `#2'}{Database `#2' only has
+ \expandafter\number\csname dtlcols@#2\endcsname\space
+ columns}%
+ \else
+ \@sdtlgetkeyforcolumn{#1}{#2}{#3}%
+ \fi
+ \fi
+ }%
+ {%
+ \PackageError{datatool}{Database `#2' doesn't exists}{}%
+ }%
+}
% \end{macrocode}
-% This key doesn't have an associated data type, so set it to
-% this value's data type, unless the value is empty.
+%\end{macro}
+%
+%\begin{macro}{\@sdtlgetkeyforcolumn}
+%\begin{definition}
+%\cs{@sdtlgetkeyforcolumn}\marg{key cs}\marg{db}\marg{column index}
+%\end{definition}
+% Gets the key associated with the given column index and stores
+% in \meta{key cs}
% \begin{macrocode}
-\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
-}{%
+\newcommand*{\@sdtlgetkeyforcolumn}[3]{%
+ \edef\@dtl@dogetkeyforcolumn{\noexpand\@dtl@getkeyforcolumn
+ {\noexpand#1}{#2}{\number#3}}%
+ \@dtl@dogetkeyforcolumn
+}
% \end{macrocode}
-% This key already has an associated data type, but may need updating.
+%\end{macro}
+%\begin{macro}{\@dtl@getkeyforcolumn}
+% Column index must be fully expanded before use.
% \begin{macrocode}
-\ifx\@dtl@value\@empty
+\newcommand*{\@dtl@getkeyforcolumn}[3]{%
+ \def\@dtl@get@keyforcolumn##1% before stuff
+ \db@plist@elt@w% start of block
+ \db@col@id@w #3\db@col@id@end@% index
+ \db@key@id@w ##2\db@key@id@end@% key
+ \db@type@id@w ##3\db@type@id@end@% data type
+ \db@header@id@w ##4\db@header@id@end@% header
+ \db@col@id@w #3\db@col@id@end@% index
+ \db@plist@elt@end@% end of block
+ ##5\q@nil{\def#1{##2}}%
+ \edef\@dtl@tmp{\expandafter\the\csname dtldb@#2\endcsname}%
+ \expandafter\@dtl@getkeyforcolumn\@dtl@tmp
+ \db@plist@elt@w% start of block
+ \db@col@id@w #3\db@col@id@end@ index
+ \db@key@id@w \@nil\db@key@id@end@% key
+ \db@type@id@w \db@type@id@end@% data type
+ \db@header@id@w \db@header@id@end@% header
+ \db@col@id@w #3\db@col@id@end@% index
+ \db@plist@elt@end@% end of block
+ \q@nil
+}
% \end{macrocode}
-% The value is empty, so do nothing.
+%\end{macro}
+%
+% Define some commands to indicate the various data types a database
+% may contain.
+%\begin{macro}{\DTLunsettype}
+% Unknown data type. (All entries in the column are blank so the
+% type can't be determined.)
+%\changes{2.0}{2009 February 27}{new}
% \begin{macrocode}
-\else
- \expandafter\ifx\csname @dtl@idtype@#1@#2\endcsname\@empty
+\def\DTLunsettype{}
% \end{macrocode}
-% The data type is currently unset (all previous values for this
-% key were empty) so set the data type for this key to the data type
-% of the given value.
+%\end{macro}
+%\begin{macro}{\DTLstringtype}
+% Data type representing strings.
+%\changes{2.0}{2009 February 27}{new}
% \begin{macrocode}
- \expandafter\xdef\csname @dtl@idtype@#1@#2\endcsname{%
- \the\@dtl@datatype}%
- \else
+\def\DTLstringtype{0}
% \end{macrocode}
-% Store the data type currently associated with this key in
-% \cs{@dtl@tmpcount}.
+%\end{macro}
+%\begin{macro}{\DTLinttype}
+% Data type representing integers.
+%\changes{2.0}{2009 February 27}{new}
% \begin{macrocode}
- \expandafter\@dtl@tmpcount\expandafter=
- \csname @dtl@idtype@#1@#2\endcsname\relax
+\def\DTLinttype{1}
% \end{macrocode}
-% Determine whether to update the data type associated with this key.
+%\end{macro}
+%\begin{macro}{\DTLrealtype}
+% Data type representing real numbers.
+%\changes{2.0}{2009 February 27}{new}
% \begin{macrocode}
- \ifcase\@dtl@tmpcount
+\def\DTLrealtype{2}
% \end{macrocode}
-% The current data type is a string, so leave as it is
-% (string overrides all the other types.)
+%\end{macro}
+%\begin{macro}{\DTLcurrencytype}
+% Data type representing currency.
+%\changes{2.0}{2009 February 27}{new}
% \begin{macrocode}
- \or
+\def\DTLcurrencytype{3}
% \end{macrocode}
-% The current data type is an int, so set the data type of the given
-% value (all other data types override int.)
+%\end{macro}
+%
+%\begin{macro}{\DTLgetdatatype}
+%\begin{definition}
+%\cs{DTLgetdatatype}\marg{cs}\marg{db}\marg{key}
+%\end{definition}
+% Gets data type associated with column labelled \meta{key} in
+% database \meta{db} and stores in \meta{cs}. Type may be:
+% \meta{empty} (unset), 0 (string), 1 (int),
+% 2 (real), 3 (currency). Unstarred version checks if the database
+% and key exist, starred version doesn't.
+%\changes{2.0}{2009 February 27}{new}
% \begin{macrocode}
- \expandafter\xdef\csname @dtl@idtype@#1@#2\endcsname{%
- \the\@dtl@datatype}%
- \or
+\newcommand*{\DTLgetdatatype}{%
+ \@ifstar\@sdtlgetdatatype\@dtlgetdatatype
+}
% \end{macrocode}
-% The current data type is a real, set to real unless the given value
-% is a string or currency (real overrides int, but not string or
-% currency.)
+%\end{macro}
+%
+%\begin{macro}{\@dtlgetdatatype}
+% Unstarred version of \cs{DTLgetdatatype}.
+%\changes{2.0}{2009 February 27}{new}
% \begin{macrocode}
- \ifnum\@dtl@datatype=0\relax
- \expandafter\gdef\csname @dtl@idtype@#1@#2\endcsname{0}%
+\newcommand*{\@dtlgetdatatype}[3]{%
+% \end{macrocode}
+% Check if database exists.
+% \begin{macrocode}
+ \DTLifdbexists{#2}%
+ {%
+% \end{macrocode}
+% Check if key exists in this database.
+% \begin{macrocode}
+ \@sDTLifhaskey{#2}{#3}%
+ {%
+% \end{macrocode}
+% Get data type for this database and key.
+% \begin{macrocode}
+ \@sdtlgetdatatype{#1}{#2}{#3}%
+ }%
+ {%
+% \end{macrocode}
+% Key doesn't exist in this database.
+% \begin{macrocode}
+ \PackageError{datatool}{Key `#3' undefined in database `#2'}{}%
+ }%
+ }%
+ {%
+% \end{macrocode}
+% Database doesn't exist.
+% \begin{macrocode}
+ \PackageError{datatool}{Database `#2' doesn't exist}{}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@sdtlgetdatatype}
+% Starred version of \cs{DTLgetdatatype}. This ensures that
+% the key is fully expanded before begin passed to
+% \cs{@dtl@getdatatype}.
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\newcommand*{\@sdtlgetdatatype}[3]{%
+ \edef\@dtl@dogetdata{\noexpand\@dtl@getdatatype{\noexpand#1}%
+ {\expandafter\the\csname dtlkeys@#2\endcsname}%
+ {\dtl@columnindex{#2}{#3}}}%
+ \@dtl@dogetdata
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@getdatatype}
+%\begin{definition}
+%\cs{@dtl@getdatatype}\marg{cs}\marg{data specs}\marg{column index}
+%\end{definition}
+% Column index must be expanded.
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\newcommand*{\@dtl@getdatatype}[3]{%
+ \def\@dtl@get@keydata##1% stuff before
+ \db@plist@elt@w% start of key block
+ \db@col@id@w #3\db@col@id@end@% column index
+ \db@key@id@w ##2\db@key@id@end@% key id
+ \db@type@id@w ##3\db@type@id@end@% data type
+ \db@header@id@w ##4\db@header@id@end@% header
+ \db@col@id@w #3\db@col@id@end@% column index
+ \db@plist@elt@end@% end of key block
+ ##5% stuff afterwards
+ \q@nil{\def#1{##3}}%
+ \@dtl@get@keydata#2\q@nil
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@getprops}
+%\begin{definition}
+%\cs{@dtl@getprops}\marg{key cs}\marg{type cs}\marg{header toks}\marg{before toks}\marg{after toks}\marg{data specs}\marg{column index}
+%\end{definition}
+% Column index must be expanded.
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\newcommand*{\@dtl@getprops}[7]{%
+ \def\@dtl@get@keydata##1% stuff before
+ \db@plist@elt@w% start of key block
+ \db@col@id@w #7\db@col@id@end@% column index
+ \db@key@id@w ##2\db@key@id@end@% key id
+ \db@type@id@w ##3\db@type@id@end@% data type
+ \db@header@id@w ##4\db@header@id@end@% header
+ \db@col@id@w #7\db@col@id@end@% column index
+ \db@plist@elt@end@% end of key block
+ ##5% stuff afterwards
+ \q@nil{%
+ \def#1{##2}% key
+ \def#2{##3}% data type
+ #3={##4}% header
+ #4={##1}% before stuff
+ #5={##5}% after stuff
+ }%
+ \@dtl@get@keydata#6\q@nil
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@before}
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\newtoks\@dtl@before
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@dtl@after}
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\newtoks\@dtl@after
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@dtl@colhead}
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\newtoks\@dtl@colhead
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@updatekeys}
+%\begin{definition}
+%\cs{@dtl@updatekeys}\marg{db}\marg{key}\marg{value}
+%\end{definition}
+% Adds key to database's key list if it doesn't exist.
+% The value is used to update the data type associated with that key.
+% Key must be fully expanded. Doesn't check if database exists.
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\newcommand*{\@dtl@updatekeys}[3]{%
+% \end{macrocode}
+% Check if key already exists
+% \begin{macrocode}
+ \@sDTLifhaskey{#1}{#2}%
+ {%
+% \end{macrocode}
+% Key exists, may need to update data type. First get the
+% column index.
+% \begin{macrocode}
+ \expandafter\dtlcolumnnum\expandafter
+ =\dtl@columnindex{#1}{#2}\relax
+% \end{macrocode}
+% Get the properties for this column
+% \begin{macrocode}
+ \edef\@dtl@dogetprops{\noexpand\@dtl@getprops
+ {\noexpand\@dtl@key}{\noexpand\@dtl@type}%
+ {\noexpand\@dtl@colhead}{\noexpand\@dtl@before}%
+ {\noexpand\@dtl@after}{\the\csname dtlkeys@#1\endcsname}%
+ {\number\dtlcolumnnum}}
+ \@dtl@dogetprops
+% \end{macrocode}
+% Is the value empty?
+% \begin{macrocode}
+ \def\@dtl@tmp{#3}%
+ \ifx\@dtl@tmp\@empty
+% \end{macrocode}
+% Leave data type as it is
+% \begin{macrocode}
+ \else
+% \end{macrocode}
+% Make a copy of current data type
+% \begin{macrocode}
+ \let\@dtl@oldtype\@dtl@type
+% \end{macrocode}
+% Check the data type for this entry (stored in \cs{@dtl@datatype})
+% \begin{macrocode}
+ \@dtl@checknumerical{#3}%
+% \end{macrocode}
+% If this column currently has no data type assigned to it
+% then use the new type.
+% \begin{macrocode}
+ \ifx\@dtl@type\@empty
+ \edef\@dtl@type{\number\@dtl@datatype}%
\else
- \ifnum\@dtl@datatype=3\relax
- \expandafter\gdef\csname @dtl@idtype@#1@#2\endcsname{3}%
- \else
- \expandafter\gdef\csname @dtl@idtype@#1@#2\endcsname{2}%
+% \end{macrocode}
+% This column already has an associated data type but it may
+% need updating.
+% \begin{macrocode}
+ \ifcase\@dtl@datatype % string
+% \end{macrocode}
+% String overrides all other types
+% \begin{macrocode}
+ \def\@dtl@type{0}%
+ \or % int
+% \end{macrocode}
+% All other types override int, so leave it as it is
+% \begin{macrocode}
+ \or % real
+% \end{macrocode}
+% Real overrides int, but not currency or string
+% \begin{macrocode}
+ \ifnum\@dtl@type=1\relax
+ \def\@dtl@type{2}%
+ \fi
+ \or % currency
+% \end{macrocode}
+% Currency overrides int and real but not string
+% \begin{macrocode}
+ \ifnum\@dtl@type>0\relax
+ \def\@dtl@type{3}%
+ \fi
\fi
\fi
- \or
% \end{macrocode}
-% The current data type is currency, so set to currency unless
-% the given value is a string (currency overrides real and int,
-% but not string.)
+% Has the data type been updated?
+% \begin{macrocode}
+ \ifx\@dtl@oldtype\@dtl@type
+% \end{macrocode}
+% No change needed
% \begin{macrocode}
- \ifnum\@dtl@datatype=0\relax
- \expandafter\gdef\csname @dtl@idtype@#1@#2\endcsname{0}%
\else
- \expandafter\gdef\csname @dtl@idtype@#1@#2\endcsname{3}%
+% \end{macrocode}
+% Update required
+% \begin{macrocode}
+ \toks@gconcat@middle@cx{dtlkeys@#1}%
+ {\@dtl@before}%
+ {%
+ \noexpand\db@plist@elt@w% start of key block
+ \noexpand\db@col@id@w \the\dtlcolumnnum
+ \noexpand\db@col@id@end@% column index
+ \noexpand\db@key@id@w #2\noexpand\db@key@id@end@% key id
+ \noexpand\db@type@id@w \@dtl@type
+ \noexpand\db@type@id@end@% data type
+ \noexpand\db@header@id@w \the\@dtl@colhead
+ \noexpand\db@header@id@end@% header
+ \noexpand\db@col@id@w \the\dtlcolumnnum
+ \noexpand\db@col@id@end@% column index
+ \noexpand\db@plist@elt@end@% end of key block
+ }%
+ {\@dtl@after}%
\fi
\fi
- \fi
-\fi
-}%
+ }%
+ {%
+% \end{macrocode}
+% Key doesn't exist. Increment column count.
+% \begin{macrocode}
+ \expandafter\global\expandafter\advance
+ \csname dtlcols@#1\endcsname by 1\relax
+ \dtlcolumnnum=\csname dtlcols@#1\endcsname\relax
+% \end{macrocode}
+% Set column index for this key
+% \begin{macrocode}
+ \expandafter\xdef\csname dtl@ci@#1@#2\endcsname{%
+ \number\dtlcolumnnum}%
+% \end{macrocode}
+% Get data type for this entry (stored in \cs{@dtl@datatype})
+% \begin{macrocode}
+ \def\@dtl@tmp{#3}%
+ \ifx\@dtl@tmp\@empty
+ \edef\@dtl@type{}% don't know data type yet
+ \else
+ \@dtl@checknumerical{#3}%
+ \edef\@dtl@type{\number\@dtl@datatype}%
+ \fi
+% \end{macrocode}
+% Append to property list
+% \begin{macrocode}
+ \toks@gput@right@cx{dtlkeys@#1}%
+ {%
+ \noexpand\db@plist@elt@w
+ \noexpand\db@col@id@w \the\dtlcolumnnum
+ \noexpand\db@col@id@end@
+ \noexpand\db@key@id@w #2\noexpand\db@key@id@end@
+ \noexpand\db@type@id@w \@dtl@type
+ \noexpand\db@type@id@end@
+ \noexpand\db@header@id@w #2\noexpand\db@header@id@end@
+ \noexpand\db@col@id@w \the\dtlcolumnnum
+ \noexpand\db@col@id@end@
+ \noexpand\db@plist@elt@end@
+ }%
+ }%
}
% \end{macrocode}
-%\end{macro}
+%\end{macro}
%
-%\begin{macro}{\@dtl@setkeys}
+%\begin{macro}{\DTLsetheader}
%\begin{definition}
-%\cs{@dtl@setkeys}\marg{key}\marg{db name}
+%\cs{DTLsetheader}\marg{db}\marg{key}\marg{header}
%\end{definition}
-% Adds \marg{key} to \cs{dtlkeys@}\meta{db name} if not already
-% in it.
+% Sets header for column given by \meta{key} in database \meta{db}.
+% Starred version doesn't check for existance of database or key.
% \begin{macrocode}
-\newcommand*{\@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}{}%
+\newcommand*{\DTLsetheader}{\@ifstar\@sDTLsetheader\@DTLsetheader}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@DTLsetheader}
+% Unstarred version
+% \begin{macrocode}
+\newcommand*{\@DTLsetheader}[3]{%
+% \end{macrocode}
+% Check if database exists
+% \begin{macrocode}
+ \DTLifdbexists{#1}%
+ {%
+% \end{macrocode}
+% Check if key exists.
+% \begin{macrocode}
+ \@sDTLifhaskey{#1}{#2}%
+ {%
+ \@sDTLsetheader{#1}{#2}{#3}%
+ }%
+ {%
+ \PackageError{datatool}{Database `#1' doesn't contain key
+ `#2'}{}%
+ }%
+ }%
+ {%
+ \PackageError{datatool}{Database `#1' doesn't exist}{}%
}%
- \if@endfor
- \else
- \expandafter\xdef\csname dtlkeys@#2\endcsname{\the\@dtl@toks,#1}%
- \fi
-\fi
}
% \end{macrocode}
%\end{macro}
%
-%\begin{macro}{\@dtl@getidtype}
+%\begin{macro}{\@sDTLsetheader}
+% Starred version
+% \begin{macrocode}
+\newcommand*{\@sDTLsetheader}[3]{%
+ \expandafter\dtlcolumnnum\expandafter
+ =\dtl@columnindex{#1}{#2}\relax
+ \@dtl@setheaderforindex{#1}{\dtlcolumnnum}{#3}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@setheaderforindex}
%\begin{definition}
-% \cs{@dtl@getidtype}\marg{db name}\marg{id}
+%\cs{@dtl@setheaderforindex}\marg{db}\marg{column index}\marg{header}
%\end{definition}
-% Gets the data type for \meta{id} in given database.
+% Sets the header for column given by \meta{column index} in
+% database \meta{db}. The header must be expanded.
+% \begin{macrocode}
+\newcommand*{\@dtl@setheaderforindex}[3]{%
+% \end{macrocode}
+% Get the properties for this column
+% \begin{macrocode}
+ \edef\@dtl@dogetprops{\noexpand\@dtl@getprops
+ {\noexpand\@dtl@key}{\noexpand\@dtl@type}%
+ {\noexpand\@dtl@colhead}{\noexpand\@dtl@before}%
+ {\noexpand\@dtl@after}{\the\csname dtlkeys@#1\endcsname}%
+ {\number#2}}
+ \@dtl@dogetprops
+% \end{macrocode}
+% Store the header in \cs{@dtl@toks}
+% \begin{macrocode}
+ \@dtl@colhead={#3}%
+% \end{macrocode}
+% Reconstruct property list
+% \begin{macrocode}
+ \edef\@dtl@colnum{\number#2}\relax
+ \toks@gconcat@middle@cx{dtlkeys@#1}%
+ {\@dtl@before}%
+ {%
+ \noexpand\db@plist@elt@w% start of block
+ \noexpand\db@col@id@w \@dtl@colnum
+ \noexpand\db@col@id@end@% index
+ \noexpand\db@key@id@w \@dtl@key\noexpand\db@key@id@end@% key
+ \noexpand\db@type@id@w \@dtl@type
+ \noexpand\db@type@id@end@% data type
+ \noexpand\db@header@id@w \the\@dtl@colhead
+ \noexpand\db@header@id@end@% header
+ \noexpand\db@col@id@w \@dtl@colnum
+ \noexpand\db@col@id@end@% index
+ \noexpand\db@plist@elt@end@% end of block
+ }%
+ {\@dtl@after}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLnewdbentry}
+%\begin{definition}
+% \cs{DTLnewdbentry}\marg{db name}\marg{id}\marg{value}.
+%\end{definition}
+% Adds an entry to the last row (adds new row if database is empty)
+% and updates general column information if necessary. The
+% starred version doesn't check if the database exists.
+% \begin{macrocode}
+\newcommand{\DTLnewdbentry}{%
+ \@ifstar\@sDTLnewdbentry\@DTLnewdbentry
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@DTLnewdbentry}
+% Unstarred version of \cs{DTLnewdbentry}.
% \begin{macrocode}
-\newcommand*{\@dtl@getidtype}[2]{%
-\csname @dtl@idtype@#1@#2\endcsname}
+\newcommand{\@DTLnewdbentry}[3]{%
+ \DTLifdbexists{#1}%
+ {\@sDTLnewdbentry{#1}{#2}{#3}}%
+ {\PackageError{datatool}{Can't add new entry to database `#1':
+ database doesn't exist}{}}%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@sDTLnewdbentry}
+% Starred version of \cs{DTLnewdbentry} (doesn't check if the database exists).
+% \begin{macrocode}
+\newcommand*{\@sDTLnewdbentry}[3]{%
+% \end{macrocode}
+% Update key list
+% \begin{macrocode}
+ \@dtl@updatekeys{#1}{#2}{#3}%
+% \end{macrocode}
+% Get the column index
+% \begin{macrocode}
+ \expandafter\dtlcolumnnum\expandafter
+ =\dtl@columnindex{#1}{#2}\relax
+% \end{macrocode}
+% Get the current row:
+% \begin{macrocode}
+ \edef\dtl@dogetrow{\noexpand\dtlgetrow{#1}%
+ {\number\csname dtlrows@#1\endcsname}}%
+ \dtl@dogetrow
+% \end{macrocode}
+% Check if this row already has an entry for the given column.
+% \begin{macrocode}
+ \edef\dtl@dogetentry{\noexpand\dtlgetentryfromcurrentrow
+ {\noexpand\dtl@entry}{\number\dtlcolumnnum}%
+ }%
+ \dtl@dogetentry
+ \ifx\dtl@entry\dtlnovalue
+% \end{macrocode}
+% Store the value of this entry in \cs{@dtl@toks}
+% \begin{macrocode}
+ \@dtl@toks{#3}%
+% \end{macrocode}
+% There are no entries in this row for the given column.
+% Add this entry.
+% \begin{macrocode}
+ \toks@gconcat@middle@cx{dtldb@#1}%
+ {\dtlbeforerow}%
+ {%
+% \end{macrocode}
+% Start of this row:
+% \begin{macrocode}
+ \noexpand\db@row@elt@w%
+% \end{macrocode}
+% Row ID:
+% \begin{macrocode}
+ \noexpand\db@row@id@w \number\csname dtlrows@#1\endcsname
+ \noexpand\db@row@id@end@%
+% \end{macrocode}
+% Current row so far
+% \begin{macrocode}
+ \the\dtlcurrentrow
+% \end{macrocode}
+% New column:
+% Column ID
+% \begin{macrocode}
+ \noexpand\db@col@id@w \number\dtlcolumnnum
+ \noexpand\db@col@id@end@%
+% \end{macrocode}
+% Value:
+% \begin{macrocode}
+ \noexpand\db@col@elt@w \the\@dtl@toks
+ \noexpand\db@col@elt@end@%
+% \end{macrocode}
+% Column ID:
+% \begin{macrocode}
+ \noexpand\db@col@id@w \number\dtlcolumnnum
+ \noexpand\db@col@id@end@%
+% \end{macrocode}
+% Row ID:
+% \begin{macrocode}
+ \noexpand\db@row@id@w \number\csname dtlrows@#1\endcsname
+ \noexpand\db@row@id@end@%
+% \end{macrocode}
+% End of this row
+% \begin{macrocode}
+ \noexpand\db@row@elt@end@%
+ }%
+% \end{macrocode}
+% Rest (this should be empty)
+% \begin{macrocode}
+ {\dtlafterrow}%
+% \end{macrocode}
+% Print information message if in verbose mode.
+% \begin{macrocode}
+ \dtl@message{Added #2\space -> #3\space to database `#1'}%
+ \else
+% \end{macrocode}
+% There's already an entry for the given column in this row
+% \begin{macrocode}
+ \PackageError{datatool}{Can't add entry with ID `#2' to
+ current row of database `#1'}{There is already an entry with
+ this ID in the current row}%
+ \fi
+}
% \end{macrocode}
%\end{macro}
%
+%\changes{2.0}{2009 February 27}{removed \cs{@dtl@setidtype}}
+%\changes{2.0}{2009 February 27}{removed \cs{@dtl@setkeys}}
+%\changes{2.0}{2009 February 27}{removed \cs{@dtl@getidtype}}
+%
%\begin{macro}{\DTLifdbexists}
%\begin{definition}
%\cs{DTLifdbexists}\marg{db name}\marg{true part}\marg{false part}
@@ -9389,59 +10884,986 @@ the current row}}{%
% Checks if a data base with the given name exists.
% \begin{macrocode}
\newcommand{\DTLifdbexists}[3]{%
-\@ifundefined{dtldb@#1}{#3}{#2}}
+ \@ifundefined{dtldb@#1}{#3}{#2}}
% \end{macrocode}
%\end{macro}
%
-%\begin{macro}{\dtl@ifrowcontains}
+%\changes{2.0}{2009 February 27}{removed \cs{@dtl@ifrowcontains}}
+%\changes{2.0}{2009 February 27}{removed \cs{dtl@getentryvalue}}
+%\changes{2.0}{2009 February 27}{removed \cs{dtl@getentryid}}
+%
+%\subsection{Accessing Data}
+%
+%\begin{macro}{\@dtl@assign}
%\begin{definition}
-% \cs{dtl@ifrowcontains}\meta{id}\meta{cmd}\meta{true part}\meta{false
-%part}
+%\cs{@dtl@assign}\marg{list}\marg{db}
%\end{definition}
-% Checks 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}.
+% Assigns commands according to the given keys.
+% The current row must be stored in \cs{dtlcurrentrow}.
+%\changes{2.0}{2009 February 27}{updated to use new database
+% structure}
% \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
+\newcommand*{\@dtl@assign}[2]{%
+ \@dtl@assigncmd#1,\@nil\@@{#2}%
}
% \end{macrocode}
%\end{macro}
%
-%\begin{macro}{\dtl@getentryid}
+%\begin{macro}{\@dtl@assigncmd}
%\begin{definition}
-% \cs{dtl@getentryid}\meta{entry cmd}\meta{id cmd}
+% \cs{@dtl@assigncmd}\meta{cmd}=\meta{id}\cs{@nil}
%\end{definition}
-% Gets the ID for an entry given by \meta{entry cmd}, and stores in
-% in \meta{id cmd}.
% \begin{macrocode}
-\newcommand*{\dtl@getentryid}[2]{\expandafter\@dtl@getentryid#1#2}
-\long\def\@dtl@getentryid#1#2#3{\def#3{#1}}
+\def\@dtl@assigncmd#1=#2,#3\@@#4{%
+% \end{macrocode}
+% get entry for ID given by \#2 and store in \#1
+% \begin{macrocode}
+ \@sDTLifhaskey{#4}{#2}%
+ {%
+ \edef\@dtl@dogetentry{%
+ \noexpand\dtlgetentryfromcurrentrow
+ {\noexpand#1}{\dtl@columnindex{#4}{#2}}}%
+ \@dtl@dogetentry
+% \end{macrocode}
+% Set to null if required
+% \begin{macrocode}
+ \ifx#1\dtlnovalue
+ \@@dtl@setnull{#1}{#2}%
+ \fi
+% \end{macrocode}
+% Make it global
+% \begin{macrocode}
+ \global\let#1=#1\relax
+ }%
+ {%
+ \PackageError{datatool}{Can't assign \string#1\space: there
+ is no key `#2' in data base `#4'}{}%
+% \end{macrocode}
+% Set to null
+% \begin{macrocode}
+ \global\let#1\DTLstringnull
+ }%
+% \end{macrocode}
+% Recurse?
+% \begin{macrocode}
+ \def\dtl@tmp{#3}%
+ \ifx\@nnil\dtl@tmp
+ \let\@dtl@next\@dtl@assigncmdnoop
+ \else
+ \let\@dtl@next\@dtl@assigncmd
+ \fi
+ \@dtl@next#3\@@{#4}%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@dtl@assigncmdnoop}
+% End loop
+% \begin{macrocode}
+\def\@dtl@assigncmdnoop#1\@@#2{}
% \end{macrocode}
%\end{macro}
%
-%\begin{macro}{\dtl@getentryvalue}
+%\begin{macro}{\@dtl@setnull}
+%\cs{@dtl@setnull}\marg{cmd}\marg{id} sets \meta{cmd} to either
+% \cs{DTLstringnull} or \cs{DTLnumbernull} depending on the data
+% type for \meta{id}. (Database
+% name should be stored in \cs{@dtl@dbname} prior to use.)
+%\changes{2.0}{2009 February 27}{modified to use new database
+% structure}
+% \begin{macrocode}
+\newcommand*{\@dtl@setnull}[2]{%
+% \end{macrocode}
+% Check if database given by \cs{@dtl@dbname} has the required key.
+% \begin{macrocode}
+ \@sDTLifhaskey{\@dtl@dbname}{#2}%
+ {%
+% \end{macrocode}
+% Set to null
+% \begin{macrocode}
+ \@@dtl@setnull{#1}{#2}%
+ }%
+ {%
+% \end{macrocode}
+% Key not defined in database \cs{@dtl@dbname}.
+% \begin{macrocode}
+ \global\let#1=\DTLstringnull
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@@dtl@setnull}
+% As above, but doesn't check if key exists
+% \begin{macrocode}
+\newcommand*{\@@dtl@setnull}[2]{%
+% \end{macrocode}
+% Get the data type associated with this key and store in
+% \cs{@dtl@type}.
+% \begin{macrocode}
+ \@sdtlgetdatatype{\@dtl@type}{\@dtl@dbname}{#2}%
+% \end{macrocode}
+% Check data type.
+% \begin{macrocode}
+ \ifnum0\@dtl@type=0\relax
+% \end{macrocode}
+% Data type is \meta{empty} or 0, so set to string null.
+% \begin{macrocode}
+ \global\let#1=\DTLstringnull
+ \else
+% \end{macrocode}
+% Data type is numerical, so set to number null.
+% \begin{macrocode}
+ \global\let#1=\DTLnumbernull
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLstringnull}
+% String null value:
+% \begin{macrocode}
+\newcommand*{\DTLstringnull}{NULL}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLnumbernull}
+% Number null value:
+% \begin{macrocode}
+\newcommand*{\DTLnumbernull}{0}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLifnull}
+%\begin{definition}
+%\cs{DTLifnull}\marg{value}\marg{true part}\marg{false part}
+%\end{definition}
+% Checks if \meta{value} is null (either \cs{DTLstringnull} or
+% \cs{DTLnumbernull}) if true, does \meta{true part} otherwise
+% does \meta{false part}.
+% \begin{macrocode}
+\newcommand*{\DTLifnull}[3]{%
+ \ifx\DTLstringnull#1\relax
+ #2%
+ \else
+ \ifx\DTLnumbernull#1\relax
+ #2%
+ \else
+ #3%
+ \fi
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtlnovalue}
+% \begin{macrocode}
+\def\@dtlnovalue{Undefined Value}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtlnovalue}
+% \begin{macrocode}
+\def\dtlnovalue{\@dtlnovalue}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLgetkeydata}
%\begin{definition}
-% \cs{dtl@getentryvalue}\meta{entry cmd}\meta{cmd}
+%\cs{DTLgetkeydata}\marg{key}\marg{db}\marg{col cs}\marg{type cs}\marg{header cs}
%\end{definition}
-% Stores the entry value in \meta{cmd} for
-% entry given by \meta{entry cmd}.
+% Gets data for given key in database \meta{db}: the column index is
+% stored in \meta{col cs} and data type is stored in \meta{type cs}.
+% The unstarred version checks for the existance of the database
+% and key, the starred version doesn't.
% \begin{macrocode}
-\newcommand*{\dtl@getentryvalue}[2]{%
-\expandafter\@dtl@getentryvalue#1#2}
-\long\def\@dtl@getentryvalue#1#2#3{\gdef#3{#2}}
+\newcommand*{\DTLgetkeydata}{%
+ \@ifstar\@sdtlgetkeydata\@dtlgetkeydata
+}
% \end{macrocode}
%\end{macro}
%
+%\begin{macro}{\@dtlgetkeydata}
+% Unstarred version of \cs{DTLgetkeydata}
+% \begin{macrocode}
+\newcommand*{\@dtlgetkeydata}[5]{%
+% \end{macrocode}
+% Check if the database exists.
+% \begin{macrocode}
+ \DTLifdbexists{#2}%
+ {%
+% \end{macrocode}
+% Check if the given key exists in the database.
+% \begin{macrocode}
+ \@sDTLifhaskey{#2}{#1}%
+ {%
+% \end{macrocode}
+% Get the data.
+% \begin{macrocode}
+ \@sdtlgetkeydata{#1}{#2}{#3}{#4}{#5}%
+ }%
+ {%
+% \end{macrocode}
+% Key not defined in the given database.
+% \begin{macrocode}
+ \PackageError{datatool}{Key `#1' not defined in database
+ `#2'}{}%
+ }%
+ }%
+ {%
+% \end{macrocode}
+% Database not defined.
+% \begin{macrocode}
+ \PackageError{datatool}{Database `#2' doesn't exist}{}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@sdtlgetkeydata}
+%\cs{@sdtlgetkeydata}\marg{key}\marg{db}\marg{col cs}\marg{type cs}\marg{header cs}
+% Starred verison of \cs{DTLgetkeydata}.
+% \begin{macrocode}
+\newcommand*{\@sdtlgetkeydata}[5]{%
+ \@sdtl@getcolumnindex{#3}{#2}{#1}%
+ \edef\@dtl@dogetkeydata{\noexpand\@dtl@getprops
+ {\noexpand\@dtl@key}{\noexpand#4}{\noexpand\@dtl@colhead}%
+ {\noexpand\@dtl@before}{\noexpand\@dtl@after}%
+ {\expandafter\the\csname dtlkeys@#2\endcsname}%
+ {#3}}%
+ \@dtl@dogetkeydata
+ \edef#5{\the\@dtl@toks}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@gathervalues}
+%\begin{definition}
+%\cs{dtl@gathervalues}\oarg{label}\marg{db name}\marg{row toks}
+%\end{definition}
+% Stores each element of \meta{row} in \meta{db name} into
+% the command \cs{@dtl@}\meta{label}\texttt{@}\meta{key},
+% where \meta{key} is the
+% key for that element, and \meta{label} defaults to "key".
+%\changes{2.0}{2009 February 27}{updated to use new database structure}
+% \begin{macrocode}
+\newcommand{\dtl@gathervalues}[3][key]{%
+ \dtlforeachkey(\@dtl@key,\@dtl@col,\@dtl@type,\@dtl@head)\in{#2}\do
+ {%
+ \dtlgetentryfromrow{\@dtl@tmp}{\@dtl@col}{\dtlcurrentrow}%
+ \ifx\@dtl@tmp\dtlnovalue
+ \@dtl@setnull{\@dtl@tmp}{\@dtl@key}%
+ \fi
+ \expandafter\let\csname @dtl@#1@\@dtl@key\endcsname\@dtl@tmp
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlcurrentrow}
+% Define token register to store current row.
+% \begin{macrocode}
+\newtoks\dtlcurrentrow
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtlbeforerow}
+% Define token register to store everything before the current row.
+% \begin{macrocode}
+\newtoks\dtlbeforerow
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtlafterrow}
+% Define token register to store everything after the current row.
+% \begin{macrocode}
+\newtoks\dtlafterrow
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlgetrow}
+%\begin{definition}
+%\cs{dtlgetrow}\marg{db}\marg{row idx}
+%\end{definition}
+% Gets row with index \meta{row idx} from database named \meta{db}
+% and stores the row in \cs{dtlcurrentrow}, the preceding rows in
+% \cs{dtlbeforerow} and the following rows in \cs{dtlafterrow}.
+% This assumes that the given row exists.
+% \begin{macrocode}
+\newcommand*{\dtlgetrow}[2]{%
+ \expandafter\toks@\expandafter=\csname dtldb@#1\endcsname
+ \edef\@dtl@dogetrow{\noexpand\@dtlgetrow{\the\toks@}{\number#2}}%
+ \@dtl@dogetrow
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtlgetrow}
+%\begin{definition}
+%\cs{@dtlgetrow}\marg{data specs}\marg{row idx}
+% Gets the row specs from \meta{data specs} for row with index
+% \meta{row idx} which must be fully expanded.
+%\end{definition}
+% \begin{macrocode}
+\newcommand*{\@dtlgetrow}[2]{%
+ \def\@dtl@getrow##1% before stuff
+ \db@row@elt@w% start of the row
+ \db@row@id@w #2\db@row@id@end@% row id
+ ##2%
+ \db@row@id@w #2\db@row@id@end@% row id
+ \db@row@elt@end@% end of the row
+ ##3% after stuff
+ \q@nil{\dtlbeforerow={##1}\dtlcurrentrow={##2}\dtlafterrow={##3}}%
+ \@dtl@getrow#1\q@nil
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlgetentryfromcurrentrow}
+%\begin{definition}
+%\cs{dtlgetentryfromcurrentrow}\marg{cs}\marg{col num}
+%\end{definition}
+% Gets value for column \meta{col num} from \cs{dtlcurrentrow}
+% and stores in \meta{cs}. If not found, \meta{cs} is set to
+% \cs{dtlnovalue}.
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\newcommand*{\dtlgetentryfromcurrentrow}[2]{%
+ \dtlgetentryfromrow{#1}{#2}{\dtlcurrentrow}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlgetentryfromrow}
+%\begin{definition}
+%\cs{dtlgetentryfromrow}\marg{cs}\marg{col num}\marg{row toks}
+%\end{definition}
+% \begin{macrocode}
+\newcommand*{\dtlgetentryfromrow}[3]{%
+ \edef\@dtl@do@getentry{\noexpand\dtl@getentryfromrow
+ {\noexpand#1}{\number#2}{\the#3}}%
+ \@dtl@do@getentry
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@getentryfromrow}
+%\begin{definition}
+%\cs{dtl@getentryfromrow}\marg{cs}\marg{col num}\marg{row specs}
+%\end{definition}
+% \begin{macrocode}
+\newcommand*{\dtl@getentryfromrow}[3]{%
+ \def\dtl@dogetentry##1% before stuff
+ \db@col@id@w #2\db@col@id@end@% Column id
+ \db@col@elt@w ##2\db@col@elt@end@% Value
+ \db@col@id@w #2\db@col@id@end@% Column id
+ ##3% Remaining stuff
+ \q@nil{\def#1{##2}}%
+ \dtl@dogetentry#3%
+ \db@col@id@w #2\db@col@id@end@%
+ \db@col@elt@w \@dtlnovalue\db@col@elt@end@%
+ \db@col@id@w #2\db@col@id@end@%
+ \q@nil
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLgetvalue}
+%\begin{definition}
+%\cs{DTLgetvalue}\marg{cs}\marg{db}\marg{r}\marg{c}
+%\end{definition}
+% Gets the element in row \meta{r}, column \meta{c} from database
+% \meta{db} and stores in \meta{cs}.
+% \begin{macrocode}
+\newcommand*{\DTLgetvalue}[4]{%
+ \edef\dtl@dogetvalue{\noexpand\dtl@getvalue{\noexpand#1}{#2}%
+ {\number#3}{\number#4}}%
+ \dtl@dogetvalue
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@getvalue}
+% \begin{macrocode}
+\newcommand*{\dtl@getvalue}[4]{%
+ \def\@dtl@getvalue ##1% stuff before row <r>
+ \db@row@id@w #3\db@row@id@end@% row <r> id
+ ##2% stuff in row <r> before column <c>
+ \db@col@id@w #4\db@col@id@end@% column <c> id
+ \db@col@elt@w ##3\db@col@elt@end@% value
+ ##4% stuff after value
+ \q@nil{\def#1{##3}}%
+ \toks@=\csname dtldb@#2\endcsname
+ \expandafter\@dtl@getvalue\the\toks@% contents of data base
+ \db@row@id@w #3\db@row@id@end@%
+ \db@col@id@w #4\db@col@id@end@%
+ \db@col@elt@w \@dtlnovalue\db@col@elt@end@% undefined value
+ \q@nil
+ \ifx#1\dtlnovalue
+ \PackageError{datatool}{There is no element at (row=#3,
+ column=#4) in database `#2'}{}%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLgetlocation}
+%\begin{definition}
+%\cs{DTLgetlocation}\marg{row cs}\marg{column cs}\marg{database}%
+%\marg{value}
+%\end{definition}
+% Assigns \meta{row cs} and \meta{column cs} to the indices of the
+% first entry in \meta{database} that matches \meta{value}.
+% \begin{macrocode}
+\newcommand*{\DTLgetlocation}[4]{%
+ \def\@dtl@getlocation##1% stuff before value
+ \db@col@elt@w #4\db@col@elt@end@% value
+ \db@col@id@w ##2\db@col@id@end@% column id
+ ##3% stuff after this column
+ \db@row@id@w ##4\db@row@id@end@% row id
+ ##5% stuff after row
+ \q@nil{\def#1{##4}\def#2{##2}}%
+ \toks@=\csname dtldb@#3\endcsname
+ \expandafter\@dtl@getlocation\the\toks@% contents of data base
+ \db@col@elt@w #4\db@col@elt@end@% value
+ \db@col@id@w \@dtlnovalue\db@col@id@end@% undefined column id
+ \db@row@id@w \@dtlnovalue\db@row@id@end@% undefined row id
+ \q@nil
+ \ifx#1\dtlnovalue
+ \PackageError{datatool}{There is no element `#4' in
+ database `#3'}{}%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+
+%\subsection{Iterating Through Databases}
+%\label{sec:code:loops}
+%
+%\begin{macro}{\dtlbreak}
+% Break out of loop at the end of current iteration.
+% \begin{macrocode}
+\newcommand*{\dtlbreak}{%
+ \PackageError{datatool}{Can't break out of anything}{}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlforint}
+%\begin{definition}
+%\cs{dtlforint}\meta{ct}=\meta{start}\cs{to}\meta{end}\cs{step}%
+%\meta{inc}\cs{do}\marg{body}
+%\end{definition}
+% \meta{ct} is a count register, \meta{start}, \meta{end} and
+% \meta{inc} are integers.
+% Group if nested or use \cs{dtlgforint}.
+% An infinite loop may result if \meta{inc}$=0$ and
+% \meta{start} $\le$ \meta{end} and \cs{dtlbreak} isn't used.
+% \begin{macrocode}
+\long\def\dtlforint#1=#2\to#3\step#4\do#5{%
+% \end{macrocode}
+% Make a copy of old version of break function
+% \begin{macrocode}
+ \let\@dtl@orgbreak\dtlbreak
+ \def\@dtl@endloophook{}%
+% \end{macrocode}
+% Setup break function for the loop (sets \meta{ct} to \meta{end}
+% at the end of the current iteration).
+% \begin{macrocode}
+ \def\dtlbreak{\def\@dtl@endloophook{#1=#3}}%
+% \end{macrocode}
+% Initialise \meta{ct}
+% \begin{macrocode}
+ #1=#2\relax
+% \end{macrocode}
+% Check if the steps are positive or negative.
+% \begin{macrocode}
+ \ifnum#4<0\relax
+% \end{macrocode}
+% Counting down
+% \begin{macrocode}
+ \whiledo{\(#1>#3\)\TE@or\(#1=#3\)}%
+ {%
+ #5%
+ \@dtl@endloophook
+ \advance#1 by #4\relax
+ }%
+ \else
+% \end{macrocode}
+% Counting up
+% \begin{macrocode}
+ \whiledo{\(#1<#3\)\TE@or\(#1=#3\)}%
+ {%
+ #5%
+ \@dtl@endloophook
+ \advance#1 by #4\relax
+ }%
+ \fi
+% \end{macrocode}
+% Restore break function.
+% \begin{macrocode}
+ \let\dtlbreak\@dtl@orgbreak
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@foreach@level}
+% Count register to keep track of global nested loops.
+% \begin{macrocode}
+\newcount\@dtl@foreach@level
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlgforint}
+%\begin{definition}
+%\cs{dtlgforint}\meta{ct}=\meta{start}\cs{to}\meta{end}\cs{step}%
+%\meta{inc}\cs{do}\marg{body}
+%\end{definition}
+% \meta{ct} is a count register, \meta{start}, \meta{end} and
+% \meta{inc} are integers.
+% An infinite loop may result if \meta{inc}=0 and \meta{start} $\le$
+% \meta{end} and \cs{dtlbreak} isn't used.
+% \begin{macrocode}
+\long\def\dtlgforint#1=#2\to#3\step#4\do#5{%
+% \end{macrocode}
+% Initialise
+% \begin{macrocode}
+ \global#1=#2\relax
+% \end{macrocode}
+% Increment level counter to allow for nested loops
+% \begin{macrocode}
+ \global\advance\@dtl@foreach@level by 1\relax
+% \end{macrocode}
+% Set up end loop hook
+% \begin{macrocode}
+ \expandafter\global\expandafter
+ \let\csname @dtl@endhook@\the\@dtl@foreach@level\endcsname
+ \relax
+% \end{macrocode}
+% Set up the break function:
+% Copy current definition
+% \begin{macrocode}
+ \expandafter\global\expandafter
+ \let\csname @dtl@break@\the\@dtl@foreach@level\endcsname
+ \dtlbreak
+% \end{macrocode}
+% Set up definition for this level (sets <ct> to <end> at the end
+% of the current iteration).
+% \begin{macrocode}
+ \gdef\dtlbreak{\expandafter
+ \gdef\csname @dtl@endhook@\the\@dtl@foreach@level\endcsname{%
+ #1=#3}}%
+% \end{macrocode}
+% check the direction
+% \begin{macrocode}
+ \ifnum#4<0\relax
+% \end{macrocode}
+% Counting down
+% \begin{macrocode}
+ \whiledo{\(#1>#3\)\TE@or\(#1=#3\)}%
+ {%
+ #5%
+ \csname @dtl@endhook@\the\@dtl@foreach@level\endcsname
+ \global\advance#1 by #4\relax
+ }%
+ \else
+% \end{macrocode}
+% Counting up (or 0 increments)
+% \begin{macrocode}
+ \whiledo{\(#1<#3\)\TE@or\(#1=#3\)}%
+ {%
+ #5%
+ \csname @dtl@endhook@\the\@dtl@foreach@level\endcsname
+ \global\advance#1 by #4\relax
+ }%
+ \fi
+% \end{macrocode}
+% Restore break function
+% \begin{macrocode}
+ \expandafter\global\expandafter\let\expandafter\dtlbreak
+ \csname @dtl@break@\the\@dtl@foreach@level\endcsname
+% \end{macrocode}
+% Decrement level counter
+% \begin{macrocode}
+ \global\advance\@dtl@foreach@level by -1\relax
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtlforeachrow}
+%\begin{definition}
+%\cs{@dtlforeachrow}(\meta{idx cs},\meta{row cs})\cs{in}\marg{db}%
+%\cs{do}\marg{body}
+%\end{definition}
+% Iterates through each row in database. Assigns the current row
+% index to \meta{idx cs} and the row specs to \meta{row cs}
+% \begin{macrocode}
+\long\def\@dtlforeachrow(#1,#2)\in#3\do#4{%
+ \edef\dtl@tmp{\expandafter\the\csname dtldb@#3\endcsname}%
+ \expandafter\@dtl@foreachrow\dtl@tmp
+ \db@row@elt@w%
+ \db@row@id@w \@nil\db@row@id@end@%
+ \db@row@id@w \@nil\db@row@id@end@%
+ \db@row@elt@end@%
+ \@@{#1}{#2}{#4}\q@nil
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@foreachrow}
+% \begin{macrocode}
+\long\def\@dtl@foreachrow\db@row@elt@w%
+\db@row@id@w #1\db@row@id@end@%
+#2\db@row@id@w #3\db@row@id@end@%
+\db@row@elt@end@#4\@@#5#6#7\q@nil{%
+% \end{macrocode}
+% Define control sequence given by "#5"
+% \begin{macrocode}
+ \gdef#5{#1}%
+% \end{macrocode}
+% Hide the loop body in a macro
+% \begin{macrocode}
+ \gdef\@dtl@loopbody{#7}%
+% \end{macrocode}
+% Increment level counter to allow for nested loops
+% \begin{macrocode}
+ \global\advance\@dtl@foreach@level by 1\relax
+% \end{macrocode}
+% Check if we have reached the end of the loop
+% \begin{macrocode}
+ \ifx#5\@nnil
+ \expandafter\global\expandafter
+ \let\csname @dtl@foreachnext\the\@dtl@foreach@level\endcsname
+ =\@dtl@foreachnoop
+ \else
+ \gdef#6{#2}%
+% \end{macrocode}
+% Set up the break function:
+% Make a copy of current break function
+% \begin{macrocode}
+ \expandafter\let
+ \csname @dtl@break@\the\@dtl@foreach@level\endcsname
+ \dtlbreak
+% \end{macrocode}
+% Setup break function for this level
+% \begin{macrocode}
+ \gdef\dtlbreak{\expandafter\global\expandafter
+ \let\csname @dtl@foreachnext\the\@dtl@foreach@level\endcsname
+ =\@dtl@foreachnoop}%
+% \end{macrocode}
+% Initialise
+% \begin{macrocode}
+ \expandafter\global\expandafter
+ \let\csname @dtl@foreachnext\the\@dtl@foreach@level\endcsname
+ =\@dtl@foreachrow
+% \end{macrocode}
+% Do body of loop
+% \begin{macrocode}
+ \@dtl@loopbody
+% \end{macrocode}
+% Restore break function
+% \begin{macrocode}
+ \expandafter\let\expandafter\dtlbreak
+ \csname @dtl@break@\the\@dtl@foreach@level\endcsname
+ \fi
+% \end{macrocode}
+% Set up what to do next.
+% \begin{macrocode}
+ \expandafter\let\expandafter\@dtl@foreachnext
+ \csname @dtl@foreachnext\the\@dtl@foreach@level\endcsname
+% \end{macrocode}
+% Decrement level counter.
+% \begin{macrocode}
+ \global\advance\@dtl@foreach@level by -1\relax
+% \end{macrocode}
+% Repeat loop if necessary.
+% \begin{macrocode}
+ \@dtl@foreachnext#4\@@{#5}{#6}{#7}\q@nil
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@foreachnoop}
+% \begin{macrocode}
+\long\def\@dtl@foreachnoop#1\@@#2\q@nil{}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlforeachkey}
+%\begin{definition}
+%\cs{dtlforeachkey}(\meta{key cs},\meta{col cs},\meta{type cs},\meta{header cs})%
+%\cs{in}\marg{db}\cs{do}\marg{body}
+%\end{definition}
+% Iterates through all the keys in database \meta{db}. In each
+% iteration, \meta{key cs} stores the key, \meta{col cs} stores the
+% column index and \meta{type cs} stores the data type.
+% \begin{macrocode}
+\long\def\dtlforeachkey(#1,#2,#3,#4)\in#5\do#6{%
+ \gdef\@dtl@loopbody{#6}%
+ \edef\@dtl@keys{\expandafter\the\csname dtlkeys@#5\endcsname}%
+ \expandafter\@dtl@foreachkey\@dtl@keys
+ \db@plist@elt@w%
+ \db@col@id@w -1\db@col@id@end@%
+ \db@key@id@w \db@key@id@end@%
+ \db@type@id@w \db@type@id@end@%
+ \db@header@id@w \db@header@id@end@%
+ \db@col@id@w -1\db@col@id@end@%
+ \db@plist@elt@end@%
+ \@@{\@dtl@updatefkcs{#1}{#2}{#3}{#4}}\q@nil
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@updatefkcs}
+% \begin{macrocode}
+\newcommand*{\@dtl@updatefkcs}[8]{%
+ \gdef#1{#5}%
+ \gdef#2{#6}%
+ \gdef#3{#7}%
+ \gdef#4{#8}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@foreachkey}
+% Sets everything globally in case it occurs in a tabular environment
+% Loop body needs to be stored in \cs{@dtl@loopbody}.
+% "#7" indicates an update macro.
+% \begin{macrocode}
+\long\def\@dtl@foreachkey\db@plist@elt@w%
+\db@col@id@w #1\db@col@id@end@%
+\db@key@id@w #2\db@key@id@end@%
+\db@type@id@w #3\db@type@id@end@%
+\db@header@id@w #4\db@header@id@end@%
+\db@col@id@w #5\db@col@id@end@%
+\db@plist@elt@end@#6\@@#7\q@nil{%
+ \ifnum#1=-1\relax
+% \end{macrocode}
+% Terminate loop
+% \begin{macrocode}
+ \let\@dtl@foreachnext\@dtl@foreachnoop
+ \else
+% \end{macrocode}
+% Set up loop variables
+% \begin{macrocode}
+ #7{#2}{#1}{#3}{#4}%
+% \end{macrocode}
+% Increment level counter to allow for nested loops
+% \begin{macrocode}
+ \global\advance\@dtl@foreach@level by 1\relax
+% \end{macrocode}
+% Set up the break function
+% \begin{macrocode}
+ \expandafter\let
+ \csname @dtl@break@\the\@dtl@foreach@level\endcsname
+ \dtlbreak
+ \gdef\dtlbreak{\expandafter\global\expandafter
+ \let\csname @dtl@foreachnext\the\@dtl@foreach@level\endcsname
+ =\@dtl@foreachnoop}%
+% \end{macrocode}
+% Initialise
+% \begin{macrocode}
+ \expandafter\global\expandafter
+ \let\csname @dtl@foreachnext\the\@dtl@foreach@level\endcsname
+ =\@dtl@foreachkey
+% \end{macrocode}
+% Do body of loop
+% \begin{macrocode}
+ \@dtl@loopbody
+% \end{macrocode}
+% Set up what to do next
+% \begin{macrocode}
+ \expandafter\let\expandafter\@dtl@foreachnext
+ \csname @dtl@foreachnext\the\@dtl@foreach@level\endcsname
+% \end{macrocode}
+% Restore break function
+% \begin{macrocode}
+ \expandafter\let\expandafter\dtlbreak
+ \csname @dtl@break@\the\@dtl@foreach@level\endcsname
+% \end{macrocode}
+% Decrement level counter
+% \begin{macrocode}
+ \global\advance\@dtl@foreach@level by -1\relax
+ \fi
+% \end{macrocode}
+% Recurse if necessary
+% \begin{macrocode}
+ \@dtl@foreachnext#6\@@{#7}\q@nil
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlforcolumn}
+%\begin{definition}
+%\cs{dtlforcolumn}\marg{cs}\marg{db}\marg{key}\marg{body}
+%\end{definition}
+% Iterates through column given by \meta{key} in database \meta{db}.
+% \meta{cs} is assign to the element of the column in the
+% current iteration. Starred version doesn't check if data base
+% exists
+% \begin{macrocode}
+\newcommand*{\dtlforcolumn}{\@ifstar\@sdtlforcolumn\@dtlforcolumn}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtlforcolumn}
+% \begin{macrocode}
+\newcommand{\@dtlforcolumn}[4]{%
+% \end{macrocode}
+% Check if data base exists
+% \begin{macrocode}
+ \DTLifdbexists{#2}%
+ {%
+ \@dtlifhaskey{#2}{#3}%
+ {%
+ \@sdtlforcolumn{#1}{#2}{#3}{#4}%
+ }%
+% \end{macrocode}
+% key not in data base
+% \begin{macrocode}
+ {%
+ \PackageError{datatool}{Database `#2' doesn't contain
+ key `#3'}{}%
+ }%
+ }%
+%
+ {%
+ \PackageError{datatool}{Database `#2' doesn't exist}{}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@sdtlforcolumn}
+% \begin{macrocode}
+\newcommand{\@sdtlforcolumn}[4]{%
+ \toks@{#4}%
+ \edef\@dtl@doforcol{\noexpand\dtl@forcolumn{\noexpand#1}%
+ {\expandafter\the\csname dtldb@#2\endcsname}%
+ {\dtl@columnindex{#2}{#3}}{\the\toks@}%
+ }%
+ \@dtl@doforcol%
+}
+% end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlforcolumnidx}
+%\begin{definition}
+%\cs{dtlforcolumnidx}\marg{cs}\marg{db}\marg{col num}\marg{body}
+%\end{definition}
+% Iterates through the column with index <col num> in database <db>.
+% Starred version doesn't check if database exists.
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\newcommand*{\dtlforcolumnidx}{%
+ \@ifstar\@sdtlforcolumnidx\@dtlforcolumnidx
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtlforcolumnidx}
+% \begin{macrocode}
+\newcommand{\@dtlforcolumnidx}[4]{%
+ \DTLifdbexists{#2}%
+ {%
+ \expandafter\ifnum\csname dtlcols@#2\endcsname<#3\relax
+ \PackageError{datatool}{Column index \number#3\space out of
+ bounds for database `#2'}{Database `#2' only has
+ \expandafter\number\csname dtlcols@#2\endcsname\space
+ columns}%
+ \else
+ \ifnum#3<1\relax
+ \PackageError{datatool}{Column index \number#3\space out of
+ bounds for database `#2'}{Indices start from 1}%
+ \else
+ \@sdtlforcolumnidx{#1}{#2}{#3}{#4}%
+ \fi
+ \fi
+ }%
+% \end{macrocode}
+% data base doesn't exist
+% \begin{macrocode}
+ {%
+ \PackageError{datatool}{Database `#2' doesn't exist}{}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@sdtlforcolumnidx}
+% \begin{macrocode}
+\newcommand{\@sdtlforcolumnidx}[4]{%
+ \toks@{#4}%
+ \edef\@dtl@doforcol{\noexpand\dtl@forcolumn{\noexpand#1}%
+ {\expandafter\the\csname dtldb@#2\endcsname}%
+ {\number#3}{\the\toks@}%
+ }%
+ \@dtl@doforcol
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@forcolumn}
+%\begin{definition}
+%\cs{dtl@forcolumn}\marg{cs}\marg{db specs}\marg{col num}\marg{body}
+%\end{definition}
+% \meta{col num} needs to be fully expanded
+% \begin{macrocode}
+\newcommand{\dtl@forcolumn}[4]{%
+% \end{macrocode}
+% make a copy of break function
+% \begin{macrocode}
+ \let\@dtl@oldbreak\dtlbreak
+% \end{macrocode}
+% set up break function
+% \begin{macrocode}
+ \def\dtlbreak{\let\@dtl@forcolnext=\@dtl@forcolnoop}%
+% \end{macrocode}
+% define loop macro for this column
+% \begin{macrocode}
+ \def\@dtl@forcolumn##1% before stuff
+ \db@col@id@w #3\db@col@id@end@% column index
+ \db@col@elt@w ##2\db@col@elt@end@% entry
+ \db@col@id@w #3\db@col@id@end@% column index
+ ##3% after stuff
+ \q@nil{%
+ \def#1{##2}% assign value to <cs>
+% \end{macrocode}
+% check if end of loop
+% \begin{macrocode}
+ \ifx#1\@nnil
+ \let\@dtl@forcolnext=\@dtl@forcolnoop
+ \else
+% \end{macrocode}
+% do body of loop
+% \begin{macrocode}
+ #4%
+ \let\@dtl@forcolnext=\@dtl@forcolumn
+ \fi
+% \end{macrocode}
+% repeat if necessary
+% \begin{macrocode}
+ \@dtl@forcolnext##3\q@nil
+ }%
+% \end{macrocode}
+% do loop
+% \begin{macrocode}
+ \@dtl@forcolumn#2%
+ \db@col@id@w #3\db@col@id@end@%
+ \db@col@elt@w \@nil\db@col@elt@end@%
+ \db@col@id@w #3\db@col@id@end@\q@nil
+% \end{macrocode}
+% restore break function
+% \begin{macrocode}
+ \let\dtlbreak\@dtl@oldbreak
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@dtl@forcolnoop}
+% \begin{macrocode}
+\def\@dtl@forcolnoop#1\q@nil{}
+% \end{macrocode}
+%\end{macro}
+
%\begin{macro}{\dtlforeachlevel}
%\cs{DTLforeach} can only be nested up to three levels.
% \cs{dtlforeachlevel} keeps track of the current level.
% \begin{macrocode}
-\global\newcount\dtlforeachlevel
+\newcount\dtlforeachlevel
% \end{macrocode}
%\end{macro}
%
@@ -9462,6 +11884,24 @@ the current row}}{%
\def\theHDTLrowiii{\theHDTLrowii.\arabic{DTLrowiii}}
% \end{macrocode}
%
+% \begin{macrocode}
+\newcount\dtl@rowi
+\newcount\dtl@rowii
+\newcount\dtl@rowiii
+% \end{macrocode}
+%
+% \begin{macrocode}
+\newtoks\@dtl@curi
+\newtoks\@dtl@previ
+\newtoks\@dtl@nexti
+\newtoks\@dtl@curii
+\newtoks\@dtl@previi
+\newtoks\@dtl@nextii
+\newtoks\@dtl@curiii
+\newtoks\@dtl@previii
+\newtoks\@dtl@nextiii
+% \end{macrocode}
+%
%\begin{macro}{\DTLsaverowcount}
%\begin{definition}
%\cs{DTLsavelastrowcount}\marg{cmd}
@@ -9506,117 +11946,273 @@ the current row}}{%
%\begin{macro}{\@DTLforeach}
% \cs{@DTLforeach} is the unstarred version of \cs{DTLforeach}.
% The database is reconstructed to allow for rows to be edited.
+% Use the starred version for faster access.
+%\changes{2.0}{2009 February 27}{updated to use new database structure}
% \begin{macrocode}
\newcommand{\@DTLforeach}[4][\boolean{true}]{%
% \end{macrocode}
% Check database exists
% \begin{macrocode}
-\DTLifdbexists{#2}{%
+ \DTLifdbexists{#2}%
+ {%
% \end{macrocode}
% Keep \sty{hyperref} happy
% \begin{macrocode}
-\refstepcounter{DTLrow}%
-\global\c@DTLrow=\c@DTLrow
+ \refstepcounter{DTLrow}%
+% \end{macrocode}
+% Make it global (so that it works in tabular environment)
+% \begin{macrocode}
+ \global\c@DTLrow=\c@DTLrow\relax
% \end{macrocode}
% Store database name
% \begin{macrocode}
-\gdef\@dtl@dbname{#2}%
+ \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
+ \global\advance\dtlforeachlevel by 1\relax
+ \ifnum\dtlforeachlevel>3\relax
+ \PackageError{datatool}{\string\DTLforeach\space nested too
+ deeply}{Only 3 levels are allowed}%
+ \else
+ \@DTLifdbempty{#2}%
+% \end{macrocode}
+% Do nothing if database is empty
+% \begin{macrocode}
+ {}%
+ {%
% \end{macrocode}
% Set level dependent information (needs to be global to ensure
-% it works in the \env{tabular} environment.) Row counter:
+% it works in the \env{tabular} environment). Row counter:
% \begin{macrocode}
- \expandafter\global
- \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname = 0\relax
+ \expandafter\global
+ \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname
+ = 0\relax
% \end{macrocode}
-% Construct updated database:
+% Store previous value of \cs{DTLiffirstrow}
% \begin{macrocode}
- \expandafter\global\expandafter\let
- \csname @dtl@foreachrows@\romannumeral\dtlforeachlevel\endcsname
- =\@empty
+ \expandafter\global\expandafter\let%
+ \csname @dtl@iffirstrow\the\dtlforeachlevel\endcsname
+ \DTLiffirstrow
% \end{macrocode}
-% Database name:
+% Define current \cs{DTLiffirstrow}
% \begin{macrocode}
- \expandafter\global\expandafter\let
- \csname @dtl@dbname@\romannumeral\dtlforeachlevel\endcsname
- =\@dtl@dbname
+ \gdef\DTLiffirstrow##1##2{%
+ \expandafter\ifnum
+ \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname
+ =1\relax
+ ##1%
+ \else
+ ##2%
+ \fi}%
% \end{macrocode}
-% Iterate through each row
+% Store previous value of \cs{DTLiflastrow}
% \begin{macrocode}
- \expandafter\let\expandafter\@dtl@db\csname dtldb@#2\endcsname%
- \@for\@dtl@currentrow:=\@dtl@db\do{%
+ \expandafter\global\expandafter\let%
+ \csname @dtl@iflastrow\the\dtlforeachlevel\endcsname
+ \DTLiflastrow
% \end{macrocode}
-% Set current row macro for this level
+% Define current \cs{DTLiflastrow}
% \begin{macrocode}
- \expandafter\global\expandafter
- \let\csname @dtl@thiscurrentrow@\romannumeral\dtlforeachlevel
- \endcsname=\@dtl@currentrow
+ \gdef\DTLiflastrow##1##2{%
+ \expandafter\ifnum
+ \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname
+ =\csname dtlcols@#2\endcsname\relax
+ ##1%
+ \else
+ ##2%
+ \fi}%
+% \end{macrocode}
+% Store previous value of \cs{DTLifoddrow}
+% \begin{macrocode}
+ \expandafter\global\expandafter\let%
+ \csname @dtl@ifoddrow\the\dtlforeachlevel\endcsname
+ \DTLifoddrow
+% \end{macrocode}
+% Define current \cs{DTLifoddrow}
+% \begin{macrocode}
+ \gdef\DTLifoddrow##1##2{%
+ \expandafter\ifodd
+ \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname
+ ##1%
+ \else
+ ##2%
+ \fi}%
% \end{macrocode}
-% Globally assign next element (note that there is no check to
-% determine if the next element will be skipped.)
-%\changes{1.01}{2007 Aug 17}{set \cs{@dtl@nextrow}}
+% Store data base name for current level
% \begin{macrocode}
- \global\let\@dtl@nextrow\@xfor@nextelement
+ \expandafter\global\expandafter\let
+ \csname @dtl@dbname@\romannumeral\dtlforeachlevel\endcsname
+ =\@dtl@dbname
+% \end{macrocode}
+% Mark it as not read only
+% \begin{macrocode}
+ \expandafter\global\expandafter\let
+ \csname @dtl@ro@\romannumeral\dtlforeachlevel\endcsname
+ = 0\relax
+% \end{macrocode}
+% Loop through each row.
+% Loop counter given by \cs{dtl@row@}\meta{level}
+% \begin{macrocode}
+ \dtlgforint
+ \csname dtl@row\romannumeral\dtlforeachlevel\endcsname
+ =1\to\csname dtlrows@#2\endcsname\step1\do
+ {%
+% \end{macrocode}
+% Get current row from the data base
+% \begin{macrocode}
+ \@dtl@tmpcount=
+ \csname dtl@row\romannumeral\dtlforeachlevel\endcsname
+ \edef\dtl@dogetrow{\noexpand\dtlgetrow{#2}%
+ {\number\@dtl@tmpcount}}%
+ \dtl@dogetrow
+% \end{macrocode}
+% Store the current row for this level
+% \begin{macrocode}
+ \expandafter\global
+ \csname @dtl@cur\romannumeral\dtlforeachlevel\endcsname
+ = \dtlcurrentrow
+% \end{macrocode}
+% Store the previous rows for this level
+% \begin{macrocode}
+ \expandafter\global
+ \csname @dtl@prev\romannumeral\dtlforeachlevel\endcsname
+ = \dtlbeforerow
+% \end{macrocode}
+% Store the subsequent rows for this level
+% \begin{macrocode}
+ \expandafter\global
+ \csname @dtl@next\romannumeral\dtlforeachlevel\endcsname
+ = \dtlafterrow
% \end{macrocode}
% Assign commands to the required entries
% \begin{macrocode}
- \ifx\relax#3\relax
- \else
- \@dtl@assign{#3}%
- \fi
+ \ifx\relax#3\relax
+ \else
+ \@dtl@assign{#3}{#2}%
+ \fi
% \end{macrocode}
% Do the main body of text if condition is satisfied
% \begin{macrocode}
- \ifthenelse{#1}{%
- \refstepcounter{DTLrow\romannumeral\dtlforeachlevel}%
- \expandafter\edef\expandafter\DTLcurrentindex\expandafter
- {\arabic{DTLrow\romannumeral\dtlforeachlevel}}%
- #4%
- }{}%
+ \ifthenelse{#1}%
+ {%
+% \end{macrocode}
+% Increment user row counter
+% \begin{macrocode}
+ \refstepcounter{DTLrow\romannumeral\dtlforeachlevel}%
+ \expandafter\edef\expandafter\DTLcurrentindex%
+ \expandafter{%
+ \arabic{DTLrow\romannumeral\dtlforeachlevel}}%
+ #4%
+% \end{macrocode}
+% Has this row been marked for deletion?
+% \begin{macrocode}
+ \edef\@dtl@tmp{\expandafter\the
+ \csname @dtl@cur\romannumeral
+ \dtlforeachlevel\endcsname}%
+ \ifx\@dtl@tmp\@nnil
+% \end{macrocode}
+% Row needs to be deleted
+% Decrement row indices for rows with a higher index than this one
+% \begin{macrocode}
+ \expandafter\dtl@decrementrows\expandafter
+ {\csname @dtl@prev\romannumeral
+ \dtlforeachlevel\endcsname
+ }{\csname dtl@row\romannumeral
+ \dtlforeachlevel\endcsname}%
+ \expandafter\dtl@decrementrows\expandafter
+ {\csname @dtl@next\romannumeral
+ \dtlforeachlevel\endcsname
+ }{\csname dtl@row\romannumeral
+ \dtlforeachlevel\endcsname}%
+% \end{macrocode}
+% Reconstruct data base without this row
+% \begin{macrocode}
+ \edef\@dtl@tmp{%
+ \expandafter\the
+ \csname @dtl@prev\romannumeral
+ \dtlforeachlevel\endcsname
+ \expandafter\the
+ \csname @dtl@next\romannumeral
+ \dtlforeachlevel\endcsname
+ }%
+ \expandafter\global\expandafter
+ \csname dtldb@#2\endcsname\expandafter{\@dtl@tmp}%
+% \end{macrocode}
+% Decrement the row count for this database:
+% \begin{macrocode}
+ \expandafter\global\expandafter
+ \advance\csname dtlrows@#2\endcsname by -1\relax
+% \end{macrocode}
+% Decrement the counter for this loop
+% \begin{macrocode}
+ \expandafter\global\expandafter
+ \advance\csname dtl@row\romannumeral
+ \dtlforeachlevel\endcsname by -1\relax
+ \else
% \end{macrocode}
-% Reconstruct database
+% Reconstruct data base
+% \begin{macrocode}
+ \@dtl@before=\csname @dtl@prev\romannumeral
+ \dtlforeachlevel\endcsname
+ \@dtl@after=\csname @dtl@next\romannumeral
+ \dtlforeachlevel\endcsname
+ \toks@gconcat@middle@cx{dtldb@#2}%
+ {\@dtl@before}%
+ {%
+% \end{macrocode}
+% This row
+% \begin{macrocode}
+ \noexpand\db@row@elt@w%
+ \noexpand\db@row@id@w \expandafter\number
+ \csname dtl@row\romannumeral
+ \dtlforeachlevel\endcsname
+ \noexpand\db@row@id@end@%
+ \expandafter\the
+ \csname @dtl@cur\romannumeral
+ \dtlforeachlevel\endcsname
+ \noexpand\db@row@id@w \expandafter\number
+ \csname dtl@row\romannumeral
+ \dtlforeachlevel\endcsname
+ \noexpand\db@row@id@end@%
+ \noexpand\db@row@elt@end@%
+ }%
+ {\@dtl@after}%
+ \fi
+ }%
+% \end{macrocode}
+% Condition not met so ignore
% \begin{macrocode}
- \expandafter\let\expandafter\@dtl@thiscurrentrow
- \csname @dtl@thiscurrentrow@\romannumeral\dtlforeachlevel\endcsname
+ {}%
+ }%
% \end{macrocode}
-% Don't add this row if it is now empty
+% Restore previous value of \cs{DTLiffirstrow}
% \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}}%
+ \expandafter\global\expandafter\let\expandafter\DTLiffirstrow
+ \csname @dtl@iffirstrow\the\dtlforeachlevel\endcsname
+% \end{macrocode}
+% Restore previous value of \cs{DTLiflastrow}
+% \begin{macrocode}
+ \expandafter\global\expandafter\let\expandafter\DTLiflastrow
+ \csname @dtl@iflastrow\the\dtlforeachlevel\endcsname
+% \end{macrocode}
+% Restore previous value of \cs{DTLifoddrow}
+% \begin{macrocode}
+ \expandafter\global\expandafter\let\expandafter\DTLifoddrow
+ \csname @dtl@ifoddrow\the\dtlforeachlevel\endcsname
+ }%
\fi
- \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}
+% Decrement level
+% \begin{macrocode}
+ \global\advance\dtlforeachlevel by -1\relax
+ }%
+% \end{macrocode}
+% else part (data base doesn't exist):
+% \begin{macrocode}
+ {%
+ \PackageError{datatool}{Database `#2' doesn't exist}{}%
+ }%
}
% \end{macrocode}
%\end{macro}
@@ -9624,82 +12220,202 @@ deeply}{}%
%\begin{macro}{\@sDTLforeach}
% \cs{@sDTLforeach} is the starred version of \cs{DTLforeach}.
% The database rows can't be edited.
+%\changes{2.0}{2009 February 27}{updated to use new database structure}
% \begin{macrocode}
\newcommand{\@sDTLforeach}[4][\boolean{true}]{%
% \end{macrocode}
% Check database exists
% \begin{macrocode}
-\DTLifdbexists{#2}{%
+ \DTLifdbexists{#2}%
+ {%
% \end{macrocode}
% Keep \sty{hyperref} happy
% \begin{macrocode}
-\refstepcounter{DTLrow}%
-\global\c@DTLrow=\c@DTLrow
+ \refstepcounter{DTLrow}%
% \end{macrocode}
-% Store database name
+% Make it global (so that it works in tabular environment)
% \begin{macrocode}
-\gdef\@dtl@dbname{#2}%
+ \global\c@DTLrow=\c@DTLrow
% \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
+ \global\advance\dtlforeachlevel by 1\relax
+ \ifnum\dtlforeachlevel>3\relax
+ \PackageError{datatool}{\string\DTLforeach\space nested too
+ deeply}{Only 3 levels are allowed}%
+ \else
+ \@DTLifdbempty{#2}%
+% \end{macrocode}
+% Do nothing if database is empty
+% \begin{macrocode}
+ {}%
+ {%
% \end{macrocode}
% Set level dependent information (needs to be global to ensure
-% it works in the \env{tabular} environment.) Row counter:
+% it works in the \env{tabular} environment). Row counter:
% \begin{macrocode}
- \expandafter\global
- \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname = 0\relax
+ \expandafter\global
+ \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname
+ = 0\relax
% \end{macrocode}
-% Set database name to \cs{@nnil} to indicate that this is read only:
+% Store previous value of \cs{DTLiffirstrow}
% \begin{macrocode}
- \expandafter\global\expandafter\let
- \csname @dtl@dbname@\romannumeral\dtlforeachlevel\endcsname
- =\@nnil
+ \expandafter\global\expandafter\let%
+ \csname @dtl@iffirstrow\the\dtlforeachlevel\endcsname
+ \DTLiffirstrow
% \end{macrocode}
-% Iterate through each row
+% Define current \cs{DTLiffirstrow}
% \begin{macrocode}
- \expandafter\let\expandafter\@dtl@db\csname dtldb@#2\endcsname%
- \@for\@dtl@currentrow:=\@dtl@db\do{%
+ \gdef\DTLiffirstrow##1##2{%
+ \expandafter\ifnum
+ \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname
+ =1\relax
+ ##1%
+ \else
+ ##2%
+ \fi}%
% \end{macrocode}
-% Set current row macro for this level
+% Store previous value of \cs{DTLiflastrow}
% \begin{macrocode}
- \expandafter\global\expandafter
- \let\csname @dtl@thiscurrentrow@\romannumeral\dtlforeachlevel
- \endcsname=\@dtl@currentrow
+ \expandafter\global\expandafter\let%
+ \csname @dtl@iflastrow\the\dtlforeachlevel\endcsname
+ \DTLiflastrow
+% \end{macrocode}
+% Define current \cs{DTLiflastrow}
+% \begin{macrocode}
+ \gdef\DTLiflastrow##1##2{%
+ \expandafter\ifnum
+ \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname
+ =\csname dtlcols@#2\endcsname\relax
+ ##1%
+ \else
+ ##2%
+ \fi}%
+% \end{macrocode}
+% Store previous value of \cs{DTLifoddrow}
+% \begin{macrocode}
+ \expandafter\global\expandafter\let%
+ \csname @dtl@ifoddrow\the\dtlforeachlevel\endcsname
+ \DTLifoddrow
+% \end{macrocode}
+% Define current \cs{DTLifoddrow}
+% \begin{macrocode}
+ \gdef\DTLifoddrow##1##2{%
+ \expandafter\ifodd
+ \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname
+ ##1%
+ \else
+ ##2%
+ \fi}%
+% \end{macrocode}
+% Store data base name for current level
+% \begin{macrocode}
+ \expandafter\gdef\csname @dtl@dbname@\romannumeral
+ \dtlforeachlevel\endcsname{#2}%
+% \end{macrocode}
+% Mark it as read only
+% \begin{macrocode}
+ \expandafter\global\expandafter\let
+ \csname @dtl@ro@\romannumeral\dtlforeachlevel\endcsname
+ = 1\relax
% \end{macrocode}
-% Globally assign next element (note that there is no check to
-% determine if the next element will be skipped.)
-%\changes{1.01}{2007 Aug 17}{set \cs{@dtl@nextrow}}
+% Iterate through each row.
% \begin{macrocode}
- \global\let\@dtl@nextrow\@xfor@nextelement
+ \@dtlforeachrow(\dtl@thisidx,\dtl@thisrow)\in{#2}\do%
+ {%
+% \end{macrocode}
+% Assign row number (not sure if this is needed here)
+% \begin{macrocode}
+ \csname dtl@row\romannumeral\dtlforeachlevel\endcsname
+ = \dtl@thisidx\relax
+% \end{macrocode}
+% Store the current row specs for this level
+% \begin{macrocode}
+ \expandafter\global
+ \csname @dtl@cur\romannumeral\dtlforeachlevel\endcsname
+ = \expandafter{\dtl@thisrow}%
% \end{macrocode}
% Assign commands to the required entries
% \begin{macrocode}
- \ifx\relax#3\relax
- \else
- \@dtl@assign{#3}%
- \fi
+ \ifx\relax#3\relax
+ \else
+% \end{macrocode}
+% Need to set \cs{dtlcurrentrow} for \cs{@dtl@assign}
+% \begin{macrocode}
+ \dtlcurrentrow=\expandafter{\dtl@thisrow}%
+ \@dtl@assign{#3}{#2}%
+ \fi
% \end{macrocode}
% Do the main body of text if condition is satisfied
% \begin{macrocode}
- \ifthenelse{#1}{%
- \refstepcounter{DTLrow\romannumeral\dtlforeachlevel}%
- \expandafter\edef\expandafter\DTLcurrentindex\expandafter
- {\arabic{DTLrow\romannumeral\dtlforeachlevel}}%
- #4%
- }{}%
+ \ifthenelse{#1}%
+ {%
% \end{macrocode}
+% Increment user row counter
% \begin{macrocode}
-\@endforfalse
-}%
-\fi
-\global\advance\dtlforeachlevel by -1\relax
-}{%
-\PackageError{datatool}{Database `#2' doesn't exist}{}}%
+ \refstepcounter{DTLrow\romannumeral\dtlforeachlevel}%
+ \expandafter\edef\expandafter\DTLcurrentindex%
+ \expandafter{%
+ \arabic{DTLrow\romannumeral\dtlforeachlevel}}%
+ #4%
+ }%
+% \end{macrocode}
+% Condition not met so ignore
+% \begin{macrocode}
+ {}%
+ }%
+% \end{macrocode}
+% Restore previous value of \cs{DTLiffirstrow}
+% \begin{macrocode}
+ \expandafter\global\expandafter\let\expandafter\DTLiffirstrow
+ \csname @dtl@iffirstrow\the\dtlforeachlevel\endcsname
+% \end{macrocode}
+% Restore previous value of \cs{DTLiflastrow}
+% \begin{macrocode}
+ \expandafter\global\expandafter\let\expandafter\DTLiflastrow
+ \csname @dtl@iflastrow\the\dtlforeachlevel\endcsname
+% \end{macrocode}
+% Restore previous value of \cs{DTLifoddrow}
+% \begin{macrocode}
+ \expandafter\global\expandafter\let\expandafter\DTLifoddrow
+ \csname @dtl@ifoddrow\the\dtlforeachlevel\endcsname
+ }%
+ \fi
+% \end{macrocode}
+% Decrement level
+% \begin{macrocode}
+ \global\advance\dtlforeachlevel by -1\relax
+ }%
+% \end{macrocode}
+% else part (data base doesn't exist):
+% \begin{macrocode}
+ {%
+ \PackageError{datatool}{Database `#2' doesn't exist}{}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtlifreadonly}
+%\begin{definition}
+%\cs{@dtlifreadonly}\marg{true part}\marg{false part}
+%\end{definition}
+% Checks if current loop level is read only
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\newcommand*{\@dtlifreadonly}[2]{%
+ \expandafter\ifx
+ \csname @dtl@ro@\romannumeral\dtlforeachlevel\endcsname1\relax
+% \end{macrocode}
+% Read only
+% \begin{macrocode}
+ #1%
+ \else
+% \end{macrocode}
+% Not read only
+% \begin{macrocode}
+ #2%
+ \fi
}
% \end{macrocode}
%\end{macro}
@@ -9709,78 +12425,90 @@ deeply}{}%
%\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
+% \cs{@dtl@cur}\meta{n} where \meta{n} is roman
% numeral value of \cs{dtlforeachlevel}.
+% One level expansion is applied to \meta{value}.
+%\changes{2.0}{2009 February 27}{updated to use new database structure}
% \begin{macrocode}
\newcommand*{\DTLappendtorow}[2]{%
-\ifnum\dtlforeachlevel=0\relax
- \PackageError{datatool}{\string\DTLappendtorow\space can only
- be used inside \string\DTLforeach}{}%
-\else
+ \ifnum\dtlforeachlevel=0\relax
+ \PackageError{datatool}{\string\DTLappendrow\space can only be
+ used inside \string\DTLforeach}{}%
+ \else
% \end{macrocode}
% Set \cs{@dtl@thisdb} to the current database name:
% \begin{macrocode}
- \expandafter\let\expandafter\@dtl@thisdb
- \csname @dtl@dbname@\romannumeral\dtlforeachlevel\endcsname
+ \expandafter\let\expandafter\@dtl@thisdb
+ \csname @dtl@dbname@\romannumeral\dtlforeachlevel\endcsname
% \end{macrocode}
% Check this isn't in \cs{DTLforeach*}
% \begin{macrocode}
- \ifx\@dtl@thisdb\@nnil
- \PackageError{datatool}{\string\DTLappendtorow\space can't
- be used inside \string\DTLforeach*}{The starred version of
- \string\DTLforeach\space is read only}%
- \else
+ \@dtlifreadonly
+ {%
+ \PackageError{datatool}{\string\DTLappendtorow\space can't
+ be used inside \DTLforeach*}{The starred version of
+ \string\DTLforeach\space is read only}%
+ }%
+ {%
% \end{macrocode}
-% Set \cs{@dtl@dbvalue} to the value of this entry
+% Store current row number in \cs{dtlrownum}
% \begin{macrocode}
- \expandafter\@dtl@toks\expandafter{#2}%
- \edef\@dtl@dbvalue{\the\@dtl@toks}%
+ \dtlrownum=
+ \csname dtl@row\romannumeral\dtlforeachlevel\endcsname\relax
% \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.
+% Update information about this column (adding new column if
+% necessary)
% \begin{macrocode}
- \edef\@dtl@dbid{#1}%
+ \@dtl@updatekeys{\@dtl@thisdb}{#1}{#2}%
% \end{macrocode}
-% Set up the correct entry format:
+% Get column index and store in \cs{dtlcolumnnum}
% \begin{macrocode}
- \edef\@dtl@dbentry{{\@dtl@dbid}{\the\@dtl@toks}}%
+ \expandafter\dtlcolumnnum\expandafter
+ =\dtl@columnindex{\@dtl@thisdb}{#1}\relax
% \end{macrocode}
-% Set \cs{@dtl@thisrow} to the current row.
+% Set \cs{dtlcurrentrow} to the current row
% \begin{macrocode}
- \expandafter\let\expandafter\@dtl@thisrow
- \csname @dtl@thiscurrentrow@\romannumeral\dtlforeachlevel\endcsname
+ \dtlcurrentrow =
+ \csname @dtl@cur\romannumeral\dtlforeachlevel\endcsname
% \end{macrocode}
-% Check if there is already an entry with this key
+% Does this row already have 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}}{%
+ \edef\dtl@dogetentry{\noexpand\dtlgetentryfromcurrentrow
+ {\noexpand\dtl@entry}{\number\dtlcolumnnum}%
+ }%
+ \dtl@dogetentry
+ \ifx\dtl@entry\dtlnovalue
% \end{macrocode}
-% Append entry to last row
+% There are no entries in this row for the given key.
+% Store value in \cs{@dtl@toks} with one level expansion.
% \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
- }
+ \expandafter\@dtl@toks\expandafter{#2}%
% \end{macrocode}
-% Update key list
+% Append this entry to the current row.
% \begin{macrocode}
- \@dtl@setidtype{\@dtl@thisdb}{#1}{#2}%
- \expandafter\@dtl@setkeys\expandafter{#1}{\@dtl@thisdb}%
+ \toks@gput@right@cx{@dtl@cur\romannumeral\dtlforeachlevel}%
+ {%
+ \noexpand\db@col@id@w \number\dtlcolumnnum
+ \noexpand\db@col@id@end@
+ \noexpand\db@col@elt@w \the\@dtl@toks
+ \noexpand\db@col@elt@end@
+ \noexpand\db@col@id@w \number\dtlcolumnnum
+ \noexpand\db@col@id@end@
+ }%
% \end{macrocode}
-% end the \cs{ifx} and \cs{ifnum}
+% Print information to terminal and log file if in verbose mode.
% \begin{macrocode}
- \fi
-\fi
+ \dtl@message{Appended #1\space -> #2\space to database
+ `\@dtl@thisdb'}%
+ \else
+% \end{macrocode}
+% There is already an entry in this row for the given key
+% \begin{macrocode}
+ \PackageError{datatool}{Can't append entry to row:
+ there is already an entry for key `#1' in this row}{}%
+ \fi
+ }%
+ \fi
}
% \end{macrocode}
%\end{macro}
@@ -9791,62 +12519,95 @@ deeply}{}%
%\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
+% \cs{@dtl@cur}\meta{n} where \meta{n} is roman
% numeral value of \cs{dtlforeachlevel}.
+%\changes{2.0}{2009 February 27}{updated to use new database structure}
% \begin{macrocode}
\newcommand*{\DTLremoveentryfromrow}[1]{%
-\ifnum\dtlforeachlevel=0\relax
- \PackageError{datatool}{\string\DTLremoveentryfromrow\space can only
- be used inside \string\DTLforeach}{}%
-\else
+ \ifnum\dtlforeachlevel=0\relax
+ \PackageError{datatool}{\string\DTLremoventryfromrow\space
+ can only be used inside \string\DTLforeach}{}%
+ \else
% \end{macrocode}
% Set \cs{@dtl@thisdb} to the current database name:
% \begin{macrocode}
- \expandafter\let\expandafter\@dtl@thisdb
- \csname @dtl@dbname@\romannumeral\dtlforeachlevel\endcsname
+ \expandafter\let\expandafter\@dtl@thisdb
+ \csname @dtl@dbname@\romannumeral\dtlforeachlevel\endcsname
% \end{macrocode}
% Check this isn't in \cs{DTLforeach*}
% \begin{macrocode}
- \ifx\@dtl@thisdb\@nnil
- \PackageError{datatool}{\string\DTLremoveentryfromrow\space can't
- be used inside \string\DTLforeach*}{The starred version of
- \string\DTLforeach\space is read only}%
- \else
+ \@dtlifreadonly
+ {%
+ \PackageError{datatool}{\string\DTLremoveentryfromrow\space
+ can't be used inside \string\DTLforeach*}{The starred
+ version of \string\DTLforeach\space is read only}%
+ }%
+ {%
% \end{macrocode}
-% Set \cs{@dtl@thisrow} to the current row.
+% Store current row number in \cs{dtlrownum}
% \begin{macrocode}
- \expandafter\let\expandafter\@dtl@thisrow
- \csname @dtl@thiscurrentrow@\romannumeral\dtlforeachlevel\endcsname
+ \dtlrownum=
+ \csname dtl@row\romannumeral\dtlforeachlevel\endcsname\relax
% \end{macrocode}
-% Check row contains an entry with this key
+% Is there a column corresponding to this key?
% \begin{macrocode}
- \dtl@ifrowcontains{#1}{\@dtl@thisrow}{%
+ \@dtlifhaskey{\@dtl@thisdb}{#1}%
+ {%
% \end{macrocode}
-% Split row list
+% There exists a column for this key, so get the index:
% \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}{}%
- }%
+ \dtl@getcolumnindex{\thiscol}{\@dtl@thisdb}{#1}\relax
+ \dtlcolumnnum=\thiscol\relax
+% \end{macrocode}
+% Set \cs{dtlcurrentrow} to the current row
+% \begin{macrocode}
+ \dtlcurrentrow =
+ \csname @dtl@cur\romannumeral\dtlforeachlevel\endcsname
+% \end{macrocode}
+% Does this row have an entry with this key?
+% \begin{macrocode}
+ \edef\dtl@dogetentry{\noexpand\dtlgetentryfromcurrentrow
+ {\noexpand\dtl@entry}{\number\dtlcolumnnum}%
+ }%
+ \dtl@dogetentry
+ \ifx\dtl@entry\dtlnovalue
+% \end{macrocode}
+% This row doesn't contain an entry with this key
+% \begin{macrocode}
+ \PackageError{datatool}{Can't remove entry given by `#1'
+ from current row in database `\@dtl@thisdb': no such
+ entry}{The current row doesn't contain an entry for
+ key `#1'}%
+ \else
+% \end{macrocode}
+% Split the current row around the unwanted entry
+% \begin{macrocode}
+ \edef\@dtl@dosplitrow{%
+ \noexpand\dtlsplitrow{\the\dtlcurrentrow}%
+ {\number\dtlcolumnnum}{\noexpand\dtl@pre}%
+ {\noexpand\dtl@post}%
+ }%
+ \@dtl@dosplitrow
+% \end{macrocode}
+% Reconstruct row without unwanted entry
+% \begin{macrocode}
+ \expandafter\@dtl@toks\expandafter{\dtl@pre}%
+ \expandafter\toks@\expandafter{\dtl@post}%
+ \edef\@dtl@tmp{\the\@dtl@toks \the\toks@}%
+ \dtlcurrentrow=\expandafter{\@dtl@tmp}%
+ \expandafter\global
+ \csname @dtl@cur\romannumeral\dtlforeachlevel\endcsname
+ = \dtlcurrentrow
+ \dtl@message{Removed entry given by #1\space from current
+ row of database `\@dtl@thisdb'}%
+ \fi
+ }%
+ {%
+ \PackageError{datatool}{Can't remove entry given by
+ `#1' - no such key exists}{}%
+ }%
+ }%
\fi
-\fi
}
% \end{macrocode}
%\end{macro}
@@ -9857,78 +12618,110 @@ deeply}{}%
%\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
+% (The current row is given by the token register
+% \cs{@dtl@cur}\meta{n} where \meta{n} is roman
% numeral value of \cs{dtlforeachlevel}.
+%\changes{2.0}{2009 February 27}{updated to use new database structure}
% \begin{macrocode}
\newcommand*{\DTLreplaceentryforrow}[2]{%
-\ifnum\dtlforeachlevel=0\relax
- \PackageError{datatool}{\string\DTLreplaceentryforrow\space can only
- be used inside \string\DTLforeach}{}%
-\else
+ \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
+ \expandafter\let\expandafter\@dtl@thisdb
+ \csname @dtl@dbname@\romannumeral\dtlforeachlevel\endcsname
% \end{macrocode}
% Check this isn't in \cs{DTLforeach*}
% \begin{macrocode}
- \ifx\@dtl@thisdb\@nnil
- \PackageError{datatool}{\string\DTLreplaceentryforrow\space can't
- be used inside \string\DTLforeach*}{The starred version of
- \string\DTLforeach\space is read only}%
- \else
+ \@dtlifreadonly
+ {%
+ \PackageError{datatool}{\string\DTLreplaceentryforrow\space
+ can't be used inside \string\DTLforeach*}{The starred version
+ of \string\DTLforeach\space is read only}%
+ }%
+ {%
% \end{macrocode}
-% Set \cs{@dtl@dbvalue} to the value of this entry
+% Store current row number in \cs{dtlrownum}
% \begin{macrocode}
- \expandafter\@dtl@toks\expandafter{#2}%
- \edef\@dtl@dbvalue{\the\@dtl@toks}%
+ \dtlrownum=
+ \csname dtl@row\romannumeral\dtlforeachlevel\endcsname\relax
% \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.
+% Is there a column corresponding to this key?
% \begin{macrocode}
- \edef\@dtl@dbid{#1}%
+ \@dtlifhaskey{\@dtl@thisdb}{#1}%
+ {%
% \end{macrocode}
-% Set up the correct entry format:
+% There exists a column for this key, so get the index:
% \begin{macrocode}
- \edef\dtl@newentry{{\@dtl@dbid}{\the\@dtl@toks}}%
+ \dtl@getcolumnindex{\thiscol}{\@dtl@thisdb}{#1}\relax
+ \dtlcolumnnum=\thiscol\relax
% \end{macrocode}
-% Set \cs{@dtl@thisrow} to the current row.
+% Set \cs{dtlcurrentrow} to the current row
% \begin{macrocode}
- \expandafter\let\expandafter\@dtl@thisrow
- \csname @dtl@thiscurrentrow@\romannumeral\dtlforeachlevel\endcsname
+ \dtlcurrentrow =
+ \csname @dtl@cur\romannumeral\dtlforeachlevel\endcsname
% \end{macrocode}
-% Check row contains an entry with this key
+% Does this row have an entry with this key?
% \begin{macrocode}
- \dtl@ifrowcontains{#1}{\@dtl@thisrow}{%
+ \edef\dtl@dogetentry{\noexpand\dtlgetentryfromcurrentrow
+ {\noexpand\dtl@entry}{\number\dtlcolumnnum}%
+ }%
+ \dtl@dogetentry
+ \ifx\dtl@entry\dtlnovalue
% \end{macrocode}
-% Split row list
+% This row doesn't contain an entry with this key
% \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}{}%
- }%
+ \PackageError{datatool}{Can't replace entry given by `#1'
+ from current row in database `\@dtl@thisdb': no such
+ entry}{The current row doesn't contain an entry for
+ key `#1'}%
+ \else
+% \end{macrocode}
+% Split the current row around the requested entry
+% \begin{macrocode}
+ \edef\@dtl@dosplitrow{%
+ \noexpand\dtlsplitrow{\the\dtlcurrentrow}%
+ {\number\dtlcolumnnum}{\noexpand\dtl@pre}%
+ {\noexpand\dtl@post}%
+ }%
+ \@dtl@dosplitrow
+% \end{macrocode}
+% Reconstruct row with new entry
+% \begin{macrocode}
+ \@dtl@toks{#2}% new value
+ \expandafter\@dtl@before\expandafter{\dtl@pre}%
+ \expandafter\@dtl@after\expandafter{\dtl@post}%
+ \toks@gconcat@middle@cx
+ {@dtl@cur\romannumeral\dtlforeachlevel}%
+ {\@dtl@before}%
+ {%
+ \noexpand\db@col@id@w \number\dtlcolumnnum
+ \noexpand\db@col@id@end@%
+ \noexpand\db@col@elt@w \the\@dtl@toks
+ \noexpand\db@col@elt@end@%
+ \noexpand\db@col@id@w \number\dtlcolumnnum
+ \noexpand\db@col@id@end@%
+ }%
+ {\@dtl@after}%
+% \end{macrocode}
+% Print information to terminal and log file if in verbose mode.
+% \begin{macrocode}
+ \dtl@message{Updated #1\space -> #2\space in database
+ `\@dtl@thisdb'}%
+ \fi
+ }%
+ {%
+% \end{macrocode}
+% There doesn't exist a column for this key.
+% \begin{macrocode}
+ \PackageError{datatool}{Can't replace key `#1' - no such
+ key in database `\@dtl@thisdb'}{}%
+ }%
+ }%
\fi
-\fi
}
% \end{macrocode}
%\end{macro}
@@ -9940,29 +12733,85 @@ deeply}{}%
% Removes current row. This just sets the current row to empty
%\changes{1.01}{2007 Aug 17}{fix bug caused by missing \cs{fi}
% and unrequired argument}
+%\changes{2.0}{2009 February 27}{updated to use new database structure}
% \begin{macrocode}
\newcommand*{\DTLremovecurrentrow}{%
-\ifnum\dtlforeachlevel=0\relax
- \PackageError{datatool}{\string\DTLremovecurrentrow\space can only
- be used inside \string\DTLforeach}{}%
-\else
+ \ifnum\dtlforeachlevel=0\relax
+ \PackageError{datatool}{\string\DTLremovecurrentrow\space can
+ only be used inside \string\DTLforeach}{}%
+ \else
+% \end{macrocode}
+% Set \cs{@dtl@thisdb} to the current database name:
+% \begin{macrocode}
+ \expandafter\let\expandafter\@dtl@thisdb
+ \csname @dtl@dbname@\romannumeral\dtlforeachlevel\endcsname
% \end{macrocode}
% Check this isn't in \cs{DTLforeach*}
% \begin{macrocode}
- \expandafter\ifx
- \csname @dtl@dbname@\romannumeral\dtlforeachlevel\endcsname\@nnil
- \PackageError{datatool}{\string\DTLremovecurrentrow\space can't
- be used inside \string\DTLforeach*}{The starred version of
- \string\DTLforeach\space is read only}%
- \else
+ \@dtlifreadonly
+ {%
+ \PackageError{datatool}{\string\DTLreplaceentryforrow\space
+ can't be used inside \string\DTLforeach*}{The starred version
+ of \string\DTLforeach\space is read only}%
+ }%
+ {%
% \end{macrocode}
-% Set current row to empty.
+% Set the current row to \cs{@nil} (\cs{DTLforeach} needs to check
+% for this)
% \begin{macrocode}
- \expandafter\let
- \csname @dtl@thiscurrentrow@\romannumeral\dtlforeachlevel\endcsname
- =\@empty
+ \expandafter\global
+ \csname @dtl@cur\romannumeral\dtlforeachlevel\endcsname
+ ={\@nil}%
+ }%
\fi
-\fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLaddentryforrow}
+%\begin{definition}
+%\cs{DTLaddentryforrow}\marg{db name}\marg{assign list}\marg{condition}\marg{key}\marg{value}
+%\end{definition}
+% Adds the entry with key given by \meta{key} and value given by
+% \meta{value} to the first row in the database \meta{db name}
+% which satisfies the condition given by \meta{condition}. The
+% \meta{assign list} is the same as for \cs{DTLforeach} and may
+% be used to set the values which are to be tested in \meta{condition}.
+%\changes{2.0}{2009 February 27}{updated to use new database structure}
+% \begin{macrocode}
+\newcommand{\DTLaddentryforrow}[5]{%
+% \end{macrocode}
+% Iterate through the data base until condition is met
+% \begin{macrocode}
+ \DTLifdbexists{#1}%
+ {
+ \def\@dtl@notdone{\PackageError{datatool}{Unable to add entry
+ given by key `#4': condition not met for any row in database
+ `#1'}{}}%
+% \end{macrocode}
+% Iterate through each row
+% \begin{macrocode}
+ \DTLforeach[#3]{#1}{#2}%
+ {%
+% \end{macrocode}
+% add entry to this row
+% \begin{macrocode}
+ \DTLappendtorow{#4}{#5}%
+% \end{macrocode}
+% disable error message
+% \begin{macrocode}
+ \let\@dtl@notdone\relax
+% \end{macrocode}
+% break out of loop
+% \begin{macrocode}
+ \dtlbreak
+ }%
+ \@dtl@notdone
+ }%
+ {%
+ \PackageError{datatool}{Unable to add entry given by key `#4':
+ database `#1' doesn't exist}{}%
+ }%
}
% \end{macrocode}
%\end{macro}
@@ -9973,429 +12822,1440 @@ deeply}{}%
%\end{definition}
% Iterates through each key in the current row of \cs{DTLforeach},
% and does \meta{text}.
+%\changes{2.0}{2009 February 27}{updated to use new database structure}
% \begin{macrocode}
\newcommand*{\DTLforeachkeyinrow}[2]{%
-\ifnum\dtlforeachlevel=0\relax
- \PackageError{datatool}{\string\DTLforeachkeyinrow\space can only
- be used inside \string\DTLforeach}{}%
-\else
+ \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.
+% Set \cs{@dtl@thisdb} to the current database name:
% \begin{macrocode}
- \expandafter\let\expandafter\@dtl@thisrow
- \csname @dtl@thiscurrentrow@\romannumeral\dtlforeachlevel\endcsname
+ \expandafter\let\expandafter\@dtl@thisdb
+ \csname @dtl@dbname@\romannumeral\dtlforeachlevel\endcsname
% \end{macrocode}
-% Iterate through the row
+% Iterate through key list
% \begin{macrocode}
- \@for\dtl@thisentry:=\@dtl@thisrow\do{%
- \dtl@getentryvalue\dtl@thisentry{#1}%
- #2%
- }%
-\fi
+ \dtlforeachkey(\dtlkey,\dtlcol,\dtltype,\dtlheader)\in
+ \@dtl@thisdb\do{%
+% \end{macrocode}
+% store row in \cs{dtlcurrentrow}
+% (This may get nested so need to do it here instead of
+% outside this loop in case
+% \meta{text} changes it.)
+% \begin{macrocode}
+ \dtlcurrentrow =
+ \csname @dtl@cur\romannumeral\dtlforeachlevel\endcsname
+% \end{macrocode}
+% Get the value for this key and store in "#1"
+% \begin{macrocode}
+ \edef\dtl@dogetentry{\noexpand\dtlgetentryfromcurrentrow
+ {\noexpand#1}{\dtlcol}}%
+ \dtl@dogetentry
+% \end{macrocode}
+% Check if null
+% \begin{macrocode}
+ \ifx#1\dtlnovalue
+ \ifnum0\dtltype=0\relax
+% \end{macrocode}
+% Data type is \meta{empty} or 0, so set to string null.
+% \begin{macrocode}
+ \let#1=\DTLstringnull
+ \else
+% \end{macrocode}
+% Data type is numerical, so set to number null.
+% \begin{macrocode}
+ \let#1=\DTLnumbernull
+ \fi
+ \fi
+% \end{macrocode}
+% Make "#1" global in case this is in a tabular environment (or
+% something similar)
+% \begin{macrocode}
+ \global\let#1#1%
+% \end{macrocode}
+% Store loop body so that any scoping commands (such as "&") don't
+% cause a problem for \cs{ifx}
+% \begin{macrocode}
+ \def\@dtl@loop@body{#2}%
+ \@dtl@loop@body
+ }%
+ \fi
}
% \end{macrocode}
%\end{macro}
%
-%\begin{macro}{\DTLaddentryforrow}
+%\subsection{Displaying Database}
+% This section defines commands to display the entire database
+% in a \env{tabular} or \env{longtable} environment.
+%
+%\begin{macro}{\dtlbetweencols}
+% This specifies what to put between the column alignment
+% specifiers.
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\newcommand*{\dtlbetweencols}{}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtlbeforecols}
+% This specifies what to put before the first column alignment
+% specifier.
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\newcommand*{\dtlbeforecols}{}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtlaftercols}
+% This specifies what to put after the last column alignment
+% specifier.
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\newcommand*{\dtlaftercols}{}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlstringalign}
+% Alignment character for columns containing strings
+% \begin{macrocode}
+\newcommand*{\dtlstringalign}{l}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtlintalign}
+% Alignment character for columns containing integers
+% \begin{macrocode}
+\newcommand*{\dtlintalign}{r}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtlrealalign}
+% Alignment character for columns containing real numbers
+% \begin{macrocode}
+\newcommand*{\dtlrealalign}{r}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtlcurrencyalign}
+% Alignment character for columns containing currency numbers
+% \begin{macrocode}
+\newcommand*{\dtlcurrencyalign}{r}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtladdalign}
%\begin{definition}
-%\cs{DTLaddentryforrow}\marg{db name}\marg{assign list}\marg{condition}\marg{key}\marg{value}
+%\cs{dtladdalign}\marg{cs}\marg{type}\marg{col num}\marg{max cols}
%\end{definition}
-% Adds the entry with key given by \meta{key} and value given by
-% \meta{value} to the first row in the database \meta{db name}
-% which satisfies the condition given by \meta{condition}. The
-% \meta{assign list} is the same as for \cs{DTLforeach} and may
-% be used to set the values which are to be tested in \meta{condition}.
+% Adds tabular column alignment character to \meta{cs} for column
+% \meta{col num} which contains data type \meta{type}.
+%\changes{2.0}{2009 February 27}{new}
% \begin{macrocode}
-\newcommand{\DTLaddentryforrow}[5]{%
-\gdef\@dtl@dbname{#1}%
-\DTLifdbexists{#1}{%
+\newcommand*{\dtladdalign}[4]{%
+ \ifnum#3=1\relax
+ \protected@edef#1{\dtlbeforecols}%
+ \else
+ \protected@edef#1{#1\dtlbetweencols}%
+ \fi
+ \ifx\@empty#2\@empty
+ \protected@edef#1{#1c}%
+ \else
+ \ifcase#2\relax
% \end{macrocode}
-% Set \cs{@dtl@dbvalue} to the value of this entry
+% string
% \begin{macrocode}
- \expandafter\@dtl@toks\expandafter{#5}%
- \edef\@dtl@dbvalue{\the\@dtl@toks}%
+ \protected@edef#1{#1\dtlstringalign}%
+ \or
% \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.
+% integer
% \begin{macrocode}
- \edef\@dtl@dbid{#4}%
+ \protected@edef#1{#1\dtlintalign}%
+ \or
% \end{macrocode}
-% Set up the correct entry format:
+% real number
% \begin{macrocode}
- \edef\@dtl@dbentry{{\@dtl@dbid}{\the\@dtl@toks}}%
+ \protected@edef#1{#1\dtlrealalign}%
+ \or
% \end{macrocode}
-% Store the database in \cs{@dtl@db}
+% currency
% \begin{macrocode}
- \expandafter
- \let\expandafter\@dtl@db\csname dtldb@\@dtl@dbname\endcsname%
- \let\@dtl@prerow=\@empty
+ \protected@edef#1{#1\dtlcurrencyalign}%
+ \else
% \end{macrocode}
-% Iterate through each row of the database
+% Unknown type
% \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}}%
+ \protected@edef#1{#1c}%
+ \PackageError{datatool}{Unknown data type `#2'}{}%
\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}{}}%
+ \ifnum#3=#4\relax
+ \protected@edef#1{#1\dtlaftercols}%
+ \fi
}
% \end{macrocode}
%\end{macro}
%
-%\begin{macro}{\@dtl@assign}
+%\begin{macro}{\dtlheaderformat}
%\begin{definition}
-%\cs{@dtl@assign}\oarg{row}\marg{values}
+%\cs{dtlheaderformat}\marg{text}
%\end{definition}
-% Assigns each command in
-% \meta{values} (see above) to the value of the corresponding
-% ID for the row given by \meta{row} (which defaults to
-% \cs{@dtl@currentrow} if absent.)
+% Specifies how to format the column title.
+%\changes{2.0}{2009 February 27}{new}
% \begin{macrocode}
-\newcommand*{\@dtl@assign}[2][\@dtl@currentrow]{%
-\@dtl@assigncmd#2,\relax\@@{#1}%
-}
+\newcommand*{\dtlheaderformat}[1]{\null\hfil\textbf{#1}\hfil\null}
% \end{macrocode}
%\end{macro}
-%\begin{macro}{\@dtl@assigncmd}
+%
+%\begin{macro}{\dtlstringformat}
%\begin{definition}
-% \cs{\@dtl@assigncmd}\meta{cmd}=\meta{id}\cs{@nil}
+%\cs{dtlstringformat}\marg{text}
%\end{definition}
-% Assign \meta{cmd} to value given by \meta{id}
+% Specifies how to format entries in columns with string data type.
+%\changes{2.0}{2009 February 27}{new}
% \begin{macrocode}
-\def\@dtl@assigncmd#1=#2,#3\@@#4{%
-\@for\@dtl@entry:=#4\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\@@{#4}%
+\newcommand*{\dtlstringformat}[1]{#1}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtlintformat}
+%\begin{definition}
+%\cs{dtlintformat}\marg{text}
+%\end{definition}
+% Specifies how to format entries in columns with integer data type.
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\newcommand*{\dtlintformat}[1]{#1}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtlrealformat}
+%\begin{definition}
+%\cs{dtlrealformat}\marg{text}
+%\end{definition}
+% Specifies how to format entries in columns with real data type.
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\newcommand*{\dtlrealformat}[1]{#1}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtlcurrencyformat}
+%\begin{definition}
+%\cs{dtlcurrencyformat}\marg{text}
+%\end{definition}
+% Specifies how to format entries in columns with currency data type.
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\newcommand*{\dtlcurrencyformat}[1]{#1}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtldisplaystarttab}
+% Indicates what to do just after "\begin{tabular}"\marg{column specs}
+% (e.g.\ \cs{hline}).
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\newcommand*{\dtldisplaystarttab}{}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtldisplayendtab}
+% Indicates what to do just before "\end{tabular}".
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\newcommand*{\dtldisplayendtab}{}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtldisplayafterhead}
+% Indicates what to do after the header row, before the first row
+% of data.
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\newcommand*{\dtldisplayafterhead}{}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtldisplaystartrow}
+% Indicates what to do at the start of each row (not including
+% the header row or the first row of data).
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\newcommand*{\dtldisplaystartrow}{}
+% \end{macrocode}
+%\end{macro}
+
+%\begin{macro}{\DTLdisplaydb}
+%\begin{definition}
+%\cs{DTLdisplaydb}\marg{db}
+%\end{definition}
+% Displays the database \meta{db} in a tabular environment.
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\newcommand*{\DTLdisplaydb}[1]{%
+% \end{macrocode}
+% Initialise:
+% only want "&" between columns
+% \begin{macrocode}
+ \def\@dtl@doamp{\gdef\@dtl@doamp{&}}
+ \def\@dtl@resetdoamp{\gdef\@dtl@doamp{\gdef\@dtl@doamp{&}}}
+% \end{macrocode}
+% Store maximum number of columns
+% \begin{macrocode}
+ \edef\@dtl@maxcols{\expandafter\number
+ \csname dtlcols@#1\endcsname}%
+% \end{macrocode}
+% Argument for tabular environment
+% \begin{macrocode}
+ \def\@dtl@tabargs{}%
+ \dtlforeachkey(\@dtl@key,\@dtl@idx,\@dtl@type,\@dtl@head)%
+ \in{#1}\do
+ {%
+ \dtladdalign\@dtl@tabargs\@dtl@type\@dtl@idx\@dtl@maxcols
+ }%
+% \end{macrocode}
+% Begin tabular environment
+% \begin{macrocode}
+ \edef\@dtl@dobegintab{\noexpand\begin{tabular}{\@dtl@tabargs}}%
+ \@dtl@dobegintab
+% \end{macrocode}
+% Do start hook
+% \begin{macrocode}
+ \dtldisplaystarttab
+% \end{macrocode}
+% Reset \cs{@dtl@doamp} so it doesn't do an ampersand at the
+% start of the first column.
+% \begin{macrocode}
+ \@dtl@resetdoamp
+% \end{macrocode}
+% Do the header row.
+% \begin{macrocode}
+ \dtlforeachkey(\@dtl@key,\@dtl@idx,\@dtl@type,\@dtl@head)%
+ \in{#1}\do
+ {%
+ \@dtl@doamp
+ \dtlheaderformat{\@dtl@head}%
+ }%
+ \\%
+% \end{macrocode}
+% Do the after header hook
+% \begin{macrocode}
+ \dtldisplayafterhead
+% \end{macrocode}
+% Reset \cs{@dtl@doamp} so it doesn't do an ampersand at the
+% start of the first column.
+% \begin{macrocode}
+ \@dtl@resetdoamp
+% \end{macrocode}
+% Iterate through each row of the database
+% \begin{macrocode}
+ \DTLforeach*{#1}{}{%
+% \end{macrocode}
+% Do the start row hook if not the first row
+% \begin{macrocode}
+ \DTLiffirstrow{}{\\\dtldisplaystartrow}%
+% \end{macrocode}
+% Reset \cs{@dtl@doamp} so it doesn't do an ampersand at the
+% start of the first column.
+% \begin{macrocode}
+ \@dtl@resetdoamp
+% \end{macrocode}
+% Iterate through each column.
+% \begin{macrocode}
+ \DTLforeachkeyinrow{\@dtl@val}%
+ {%
+% \end{macrocode}
+% Need to make value global as it needs to be used after the
+% ampersand.
+% \begin{macrocode}
+ \global\let\@dtl@val\@dtl@val
+ \@dtl@doamp
+% \end{macrocode}
+% \cs{DTLforeachkeyinrow} sets \cs{dtltype} to the data type
+% for the current key. This can be used to determine which
+% format to use for this entry.
+% \begin{macrocode}
+ \@dtl@datatype=0\dtltype\relax
+ \ifcase\@dtl@datatype
+ \dtlstringformat\@dtl@val
+ \or
+ \dtlintformat\@dtl@val
+ \or
+ \dtlrealformat\@dtl@val
+ \or
+ \dtlcurrencyformat\@dtl@val
+ \else
+ \@dtl@val
+ \fi
+ }%
+ }%
+ \dtldisplayendtab
+ \end{tabular}%
}
% \end{macrocode}
%\end{macro}
-%\begin{macro}{\@dtl@assigncmdnoop}
-% End loop
+%
+% Define keys to use in the optional argument of
+% \cs{DTLdisplaylongdb}.
+%
+% The caption key sets the caption for the longtable.
% \begin{macrocode}
-\def\@dtl@assigncmdnoop#1\@@#2{}
+\define@key{displaylong}{caption}{\def\@dtl@cap{#1}}
+% \end{macrocode}
+% The contcaption key sets the continuation caption for the
+% longtable.
+% \begin{macrocode}
+\define@key{displaylong}{contcaption}{\def\@dtl@contcap{#1}}
+% \end{macrocode}
+% The shortcaption key sets the lof caption for the longtable.
+% \begin{macrocode}
+\define@key{displaylong}{shortcaption}{\def\@dtl@shortcap{#1}}
+% \end{macrocode}
+% The label key sets the label for the longtable.
+% \begin{macrocode}
+\define@key{displaylong}{label}{\def\@dtl@label{#1}}
+% \end{macrocode}
+% The foot key sets the longtable foot
+% \begin{macrocode}
+\define@key{displaylong}{foot}{\def\@dtl@foot{#1}}
+% \end{macrocode}
+% The lastfoot key sets the longtable last foot
+% \begin{macrocode}
+\define@key{displaylong}{lastfoot}{\def\@dtl@lastfoot{#1}}
+% \end{macrocode}
+%
+%\begin{macro}{\@dtl@resetdostartrow}
+% Resets start row hook so that it skips the first row.
+% \begin{macrocode}
+\newcommand*{\@dtl@resetdostartrow}{%
+ \gdef\@dtl@dostartrow{%
+ \gdef\@dtl@dostartrow{\\\dtldisplaystartrow}}%
+}
% \end{macrocode}
%\end{macro}
-%\begin{macro}{\@dtl@setnull}
-%\cs{@dtl@setnull}\marg{cmd}\marg{id} sets \meta{cmd} to either
-% \cs{DTLstringnull} or \cs{DTLnumbernull} depending on the data
-% type for \meta{id}. (Database
-% name should be stored in \cs{@dtl@dbname} prior to use.
+%
+%\begin{macro}{\DTLdisplaylongdb}
+%\begin{definition}
+%\cs{DTLdisplaylongdb}\oarg{options}\marg{db}
+%\end{definition}
+% Displays the database \meta{db} in a longtable environment.
+% (User needs to load \sty{longtable}).
+%\changes{2.0}{2009 February 27}{new}
% \begin{macrocode}
-\newcommand*{\@dtl@setnull}[2]{%
-\@ifundefined{@dtl@idtype@\@dtl@dbname @#2}{%
-\global\let#1=\DTLstringnull}{%
-\edef\@dtl@tmp{0\@dtl@getidtype{\@dtl@dbname}{#2}}%
-\expandafter\ifnum\@dtl@tmp=0\relax
- \global\let#1=\DTLstringnull
-\else
- \global\let#1=\DTLnumbernull
-\fi
-}}
+\newcommand*{\DTLdisplaylongdb}[2][]{%
+% \end{macrocode}
+% Initialise.
+% \begin{macrocode}
+ \def\@dtl@cap{\@nil}%
+ \def\@dtl@contcap{\@nil}%
+ \def\@dtl@label{\@nil}%
+ \def\@dtl@shortcap{\@dtl@cap}%
+ \def\@dtl@foot{\@nil}%
+ \def\@dtl@lastfoot{\@nil}%
+% \end{macrocode}
+% Set the options
+% \begin{macrocode}
+ \setkeys{displaylong}{#1}%
+% \end{macrocode}
+% Only want "&" between columns
+% \begin{macrocode}
+ \def\@dtl@doamp{\gdef\@dtl@doamp{&}}
+ \def\@dtl@resetdoamp{\gdef\@dtl@doamp{\gdef\@dtl@doamp{&}}}
+ \@dtl@resetdostartrow
+% \end{macrocode}
+% Store maximum number of columns
+% \begin{macrocode}
+ \edef\@dtl@maxcols{\expandafter\number
+ \csname dtlcols@#2\endcsname}%
+% \end{macrocode}
+% Argument for \env{longtable} environment
+% \begin{macrocode}
+ \def\@dtl@tabargs{}%
+ \dtlforeachkey(\@dtl@key,\@dtl@idx,\@dtl@type,\@dtl@head)%
+ \in{#2}\do
+ {%
+ \dtladdalign\@dtl@tabargs\@dtl@type\@dtl@idx\@dtl@maxcols
+ }%
+% \end{macrocode}
+% Start the \env{longtable} environment.
+% \begin{macrocode}
+ \edef\@dtl@dobegintab{\noexpand\begin{longtable}{\@dtl@tabargs}}%
+ \@dtl@dobegintab
+% \end{macrocode}
+% Do start hook.
+% \begin{macrocode}
+ \dtldisplaystarttab
+% \end{macrocode}
+% Is a foot required?
+% \begin{macrocode}
+ \ifx\@dtl@foot\@nnil
+ \else
+ \@dtl@foot\endfoot
+ \fi
+% \end{macrocode}
+% Is a last foot required?
+% \begin{macrocode}
+ \ifx\@dtl@lastfoot\@nnil
+ \else
+ \@dtl@lastfoot\endlastfoot
+ \fi
+% \end{macrocode}
+% Is a caption required?
+% \begin{macrocode}
+ \ifx\@dtl@cap\@nnil
+% \end{macrocode}
+% No caption required, just do header row.
+% \begin{macrocode}
+ \@dtl@resetdoamp
+ \dtlforeachkey(\@dtl@key,\@dtl@idx,\@dtl@type,\@dtl@head)%
+ \in{#2}\do
+ {\@dtl@doamp{\dtlheaderformat{\@dtl@head}}}%
+ \@dtl@resetdoamp
+ \@dtl@resetdostartrow
+ \endhead\dtldisplayafterhead
+ \else
+% \end{macrocode}
+% Caption is required
+% \begin{macrocode}
+ \caption[\@dtl@shortcap]{\@dtl@cap}%
+% \end{macrocode}
+% Is a label required?
+% \begin{macrocode}
+ \ifx\@dtl@label\@nnil
+ \else
+ \label{\@dtl@label}%
+ \fi
+ \\%
+% \end{macrocode}
+% Do header row.
+% \begin{macrocode}
+ \@dtl@resetdoamp
+ \dtlforeachkey(\@dtl@key,\@dtl@idx,\@dtl@type,\@dtl@head)%
+ \in{#2}\do
+ {\@dtl@doamp{\dtlheaderformat{\@dtl@head}}}%
+ \@dtl@resetdoamp
+ \@dtl@resetdostartrow
+ \endfirsthead
+% \end{macrocode}
+% Is a continuation caption required?
+% \begin{macrocode}
+ \ifx\@dtl@contcap\@nnil
+ \caption{\@dtl@cap}%
+ \else
+ \caption{\@dtl@contcap}%
+ \fi
+ \\%
+% \end{macrocode}
+% Do header row.
+% \begin{macrocode}
+ \@dtl@resetdoamp
+ \dtlforeachkey(\@dtl@key,\@dtl@idx,\@dtl@type,\@dtl@head)%
+ \in{#2}\do
+ {\@dtl@doamp{\dtlheaderformat{\@dtl@head}}}%
+ \@dtl@resetdoamp
+ \@dtl@resetdostartrow
+ \endhead\dtldisplayafterhead
+ \fi
+% \end{macrocode}
+% Iterate through each row of the database
+% \begin{macrocode}
+ \DTLforeach*{#2}{}{%
+ \@dtl@dostartrow
+ \@dtl@resetdoamp
+% \end{macrocode}
+% Iterate through each column
+% \begin{macrocode}
+ \DTLforeachkeyinrow{\@dtl@val}%
+ {%
+ \global\let\@dtl@val\@dtl@val
+ \@dtl@doamp
+% \end{macrocode}
+% \cs{DTLforeachkeyinrow} sets \cs{dtltype} to the data type
+% for the current key. This can be used to determine which
+% format to use for this entry.
+% \begin{macrocode}
+ \@dtl@datatype=0\dtltype\relax
+ \ifcase\@dtl@datatype
+ \dtlstringformat\@dtl@val
+ \or
+ \dtlintformat\@dtl@val
+ \or
+ \dtlrealformat\@dtl@val
+ \or
+ \dtlcurrencyformat\@dtl@val
+ \fi
+ }%
+ }%
+ \dtldisplayendtab
+ \end{longtable}%
+}
% \end{macrocode}
%\end{macro}
-%\begin{macro}{\DTLstringnull}
-% String null value:
+%
+%
+%\subsection{Editing Databases}
+%
+%\begin{macro}{\dtlswaprows}
+%\begin{definition}
+%\cs{dtlswaprows}\marg{db}\marg{row1 idx}\marg{row2 idx}
+%\end{definition}
+% Swaps the rows with indices \meta{row1 idx} and \meta{row2 idx}
+% in the database \meta{db}.
+% (Doesn't check if data base exists of if indices are out of
+% bounds.)
% \begin{macrocode}
-\newcommand*{\DTLstringnull}{NULL}
+\newcommand*{\dtlswaprows}[3]{%
+ \ifnum#2=#3\relax
+% \end{macrocode}
+% Attempt to swap row with itself: do nothing.
+% \begin{macrocode}
+ \else
+% \end{macrocode}
+% Let row A be the row with the lower index and row B be the
+% row with ther higher index.
+% \begin{macrocode}
+ \ifnum#2<#3\relax
+ \edef\@dtl@rowAidx{\number#2}%
+ \edef\@dtl@rowBidx{\number#3}%
+ \else
+ \edef\@dtl@rowAidx{\number#3}%
+ \edef\@dtl@rowBidx{\number#2}%
+ \fi
+% \end{macrocode}
+% Split the database around row A.
+% \begin{macrocode}
+ \edef\@dtl@dosplit{\noexpand\dtlgetrow{#1}{\@dtl@rowAidx}}%
+ \@dtl@dosplit
+% \end{macrocode}
+% Store first part of database in \cs{@dtl@firstpart}.
+% \begin{macrocode}
+ \expandafter\def\expandafter\@dtl@firstpart\expandafter
+ {\the\dtlbeforerow}%
+% \end{macrocode}
+% Store row A in \cs{@dtl@toksA}.
+% \begin{macrocode}
+ \@dtl@toksA=\dtlcurrentrow
+% \end{macrocode}
+% Split the second part (everything after row A).
+% \begin{macrocode}
+ \edef\@dtl@dosplit{\noexpand\@dtlgetrow
+ {\the\dtlafterrow}{\@dtl@rowBidx}}%
+ \@dtl@dosplit
+% \end{macrocode}
+% Store the mid part (everything between row A and row B)
+% \begin{macrocode}
+ \expandafter\def\expandafter\@dtl@secondpart\expandafter
+ {\the\dtlbeforerow}%
+% \end{macrocode}
+% Store row B in \cs{@dtl@toksB}.
+% \begin{macrocode}
+ \@dtl@toksB=\dtlcurrentrow
+% \end{macrocode}
+% Store the last part (everything after row B).
+% \begin{macrocode}
+ \expandafter\def\expandafter\@dtl@thirdpart\expandafter
+ {\the\dtlafterrow}%
+% \end{macrocode}
+% Reconstruct database: store first part in \cs{toks@}
+% \begin{macrocode}
+ \toks@=\expandafter{\@dtl@firstpart}%
+% \end{macrocode}
+% Store mid part in \cs{dtl@toks}
+% \begin{macrocode}
+ \@dtl@toks=\expandafter{\@dtl@secondpart}%
+% \end{macrocode}
+% Format data for first part, row B and mid part.
+% \begin{macrocode}
+ \edef\@dtl@tmp{\the\toks@
+ \noexpand\db@row@elt@w%
+ \noexpand\db@row@id@w \@dtl@rowAidx\noexpand\db@row@id@end@%
+ \the\@dtl@toksB
+ \noexpand\db@row@id@w \@dtl@rowAidx\noexpand\db@row@id@end@%
+ \noexpand\db@row@elt@end@%
+ \the\@dtl@toks}%
+% \end{macrocode}
+% Store data so far in \cs{toks@}.
+% \begin{macrocode}
+ \toks@=\expandafter{\@dtl@tmp}%
+% \end{macrocode}
+% Store last part in \cs{dtl@toks}.
+% \begin{macrocode}
+ \@dtl@toks=\expandafter{\@dtl@thirdpart}%
+% \end{macrocode}
+% Format row A and end part.
+% \begin{macrocode}
+ \edef\@dtl@tmp{\the\toks@
+ \noexpand\db@row@elt@w%
+ \noexpand\db@row@id@w \@dtl@rowBidx\noexpand\db@row@id@end@%
+ \the\@dtl@toksA
+ \noexpand\db@row@id@w \@dtl@rowBidx\noexpand\db@row@id@end@%
+ \noexpand\db@row@elt@end@%
+ \the\@dtl@toks}%
+% \end{macrocode}
+% Update the database
+% \begin{macrocode}
+ \expandafter\global\csname dtldb@#1\endcsname=\expandafter
+ {\@dtl@tmp}%
+ \fi
+}
% \end{macrocode}
%\end{macro}
-%\begin{macro}{\DTLnumbernull}
-% Number null value:
+%
+%\begin{macro}{\dtl@decrementrows}
+%\begin{definition}
+%\cs{dtl@decrementrows}\marg{toks}\marg{n}
+%\end{definition}
+% decrement by 1 all rows in \meta{toks} with row index above
+% \meta{n}
+%\changes{2.0}{2009 February 27}{new}
% \begin{macrocode}
-\newcommand*{\DTLnumbernull}{0}
+\newcommand*{\dtl@decrementrows}[2]{%
+ \def\@dtl@newlist{}%
+ \edef\@dtl@min{\number#2}%
+ \expandafter\@dtl@decrementrows\the#1%
+ \db@row@elt@w%
+ \db@row@id@w \@nil\db@row@id@end@%
+ \db@row@id@w \@nil\db@row@id@end@%
+ \db@row@elt@end@%
+ \@nil
+ #1=\expandafter{\@dtl@newlist}%
+}
% \end{macrocode}
%\end{macro}
-%\begin{macro}{\DTLifnull}
+%
+%\begin{macro}{\@dtl@decrementrows}
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\def\@dtl@decrementrows\db@row@elt@w\db@row@id@w #1\db@row@id@end@%
+#2\db@row@id@w #3\db@row@id@end@\db@row@elt@end@#4\@nil{%
+ \def\@dtl@thisrow{#1}%
+ \ifx\@dtl@thisrow\@nnil
+ \let\@dtl@donextdec=\@dtl@gobbletonil
+ \else
+ \ifnum\@dtl@thisrow>\@dtl@min
+ \@dtl@tmpcount=\@dtl@thisrow\relax
+ \advance\@dtl@tmpcount by -1\relax
+ \toks@{#2}%
+ \@dtl@toks=\expandafter{\@dtl@newlist}%
+ \edef\@dtl@newlist{\the\@dtl@toks
+ \noexpand\db@row@elt@w% row header
+ \noexpand\db@row@id@w \number\@dtl@tmpcount
+ \noexpand\db@row@id@end@% row id
+ \the\toks@ % row contents
+ \noexpand\db@row@id@w \number\@dtl@tmpcount
+ \noexpand\db@row@id@end@% row id
+ \noexpand\db@row@elt@end@% row end
+ }%
+ \else
+ \toks@{#2}%
+ \@dtl@toks=\expandafter{\@dtl@newlist}%
+ \edef\@dtl@newlist{\the\@dtl@toks
+ \noexpand\db@row@elt@w% row header
+ \noexpand\db@row@id@w #1%
+ \noexpand\db@row@id@end@% row id
+ \the\toks@ % row contents
+ \noexpand\db@row@id@w #3%
+ \noexpand\db@row@id@end@% row id
+ \noexpand\db@row@elt@end@% row end
+ }%
+ \fi
+ \let\@dtl@donextdec=\@dtl@decrementrows
+ \fi
+ \@dtl@donextdec#4\@nil
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLremoverow}
%\begin{definition}
-%\cs{DTLifnull}\marg{value}\marg{true part}\marg{false part}
+%\cs{DTLremoverow}\marg{db}\marg{row index}
%\end{definition}
-% Checks if \meta{value} is null (either \cs{DTLstringnull} or
-% \cs{DTLnumbernull}) if true, does \meta{true part} otherwise
-% does \meta{false part}.
+% Remove row with given index from database named \meta{db}.
+%\changes{2.0}{2009 February 27}{new}
% \begin{macrocode}
-\newcommand*{\DTLifnull}[3]{%
-\ifx\DTLstringnull#1\relax
- #2%
-\else
- \ifx\DTLnumbernull#1\relax
- #2%
- \else
- #3%
- \fi
-\fi}
+\newcommand*{\DTLremoverow}[2]{%
+% \end{macrocode}
+% Check database exists
+% \begin{macrocode}
+ \DTLifdbexists{#1}%
+ {%
+% \end{macrocode}
+% Check index if index is out of bounds
+% \begin{macrocode}
+ \ifnum#2>0\relax
+% \end{macrocode}
+% Check if data base has at least \meta{row index} rows
+% \begin{macrocode}
+ \expandafter\ifnum\csname dtlrows@#1\endcsname<#2\relax
+ \expandafter\ifnum\csname dtlrows@#1\endcsname=1\relax
+ \PackageError{datatool}{Can't remove row `\number#2' from
+ database `#1': no such row}{Database `#1' only has
+ 1 row}%
+ \else
+ \PackageError{datatool}{Can't remove row `\number#2' from
+ database `#1': no such row}{Database `#1' only has
+ \expandafter\number\csname dtlrows@#1\endcsname\space
+ rows}%
+ \fi
+ \else
+ \@DTLremoverow{#1}{#2}%
+ \fi
+ \else
+ \PackageError{datatool}{Can't remove row \number#2: index
+ out of bounds}{Row indices start at 1}%
+ \fi
+ }%
+ {%
+ \PackageError{datatool}{Can't remove row: database `#1' doesn't
+ exist}{}%
+ }%
+}
% \end{macrocode}
%\end{macro}
%
-%\begin{macro}{\dtl@gathervalues}
+%\begin{macro}{\@DTLremoverow}
%\begin{definition}
-%\cs{dtl@gathervalues}\oarg{label}\marg{db name}\marg{row}
+%\cs{@DTLremoverow}\marg{db}\marg{row index}
%\end{definition}
-% Stores each element of \meta{row} in \meta{db name} into
-% the command \cs{@dtl@}\meta{label}\texttt{@}\meta{key},
-% where \meta{key} is the
-% key for that element, and \meta{label} defaults to "key".
+% Doesn't perform any checks for the existance of the database
+% or if the index is in range.
+%\changes{2.0}{2009 February 27}{new}
% \begin{macrocode}
-\newcommand{\dtl@gathervalues}[3][key]{%
-\expandafter\let\expandafter\@dtl@tmp\expandafter
- =\csname dtlkeys@#2\endcsname%
-\def\@dtl@list{}%
-\@for\dtl@key:=\@dtl@tmp\do{%
- \expandafter\@dtl@setnull\expandafter{%
- \csname @dtl@#1@\dtl@key\endcsname}{\dtl@key}%
- \@for\dtl@thiselement:=#3\do{%
- \dtl@getentryid\dtl@thiselement\@dtl@id
- \ifthenelse{\equal{\@dtl@id}{\dtl@key}}{%
- \dtl@getentryvalue\dtl@thiselement\@dtl@value%
- \expandafter\toks@\expandafter{\@dtl@value}%
- \expandafter\edef\csname @dtl@#1@\dtl@key\endcsname{%
- \the\toks@}%
- \@endfortrue}{}%
- }%
-\@endforfalse
-}%
+\newcommand*{\@DTLremoverow}[2]{%
+% \end{macrocode}
+% Get row from data base
+% \begin{macrocode}
+ \edef\dtl@dogetrow{\noexpand\dtlgetrow{#1}{\number#2}}%
+ \dtl@dogetrow
+% \end{macrocode}
+% Update the row indices
+% \begin{macrocode}
+ \expandafter\dtl@decrementrows\expandafter
+ {\dtlbeforerow}{#2}%
+ \expandafter\dtl@decrementrows\expandafter
+ {\dtlafterrow}{#2}%
+% \end{macrocode}
+% Reconstruct database
+% \begin{macrocode}
+ \edef\dtl@tmp{\the\dtlbeforerow \the\dtlafterrow}%
+ \expandafter\global\csname dtldb@#1\endcsname
+ =\expandafter{\dtl@tmp}%
+% \end{macrocode}
+% decrement row counter
+% \begin{macrocode}
+ \expandafter\global\expandafter\advance
+ \csname dtlrows@#1\endcsname by -1\relax
}
% \end{macrocode}
%\end{macro}
%
+%\subsection{Database Functions}
+%
%\begin{macro}{\DTLsumforkeys}
%\begin{definition}
-%\cs{DTLsumforkeys}\oarg{condition}\marg{db list}\marg{key list}\marg{cmd}
+%\cs{DTLsumforkeys}\oarg{condition}\oarg{assign list}\marg{db list}\marg{key list}\marg{cmd}
%\end{definition}
% Sums all entries for key \meta{key} over all databases listed
% in \meta{db list},
% and stores in \meta{cmd}, which must be a control sequence.
-% The optional argument \meta{condition} is the same as that
-% for \cs{DTLforeach}.
+% The first argument \meta{condition} is the same as that
+% for \cs{DTLforeach}. The second optional argument provides
+% an assignment list to pass to \cs{DTLforeach} in case extra
+% information is need by \meta{condition}.
+%\changes{2.0}{2009 February 27}{added second optional argument}
% \begin{macrocode}
-\newcommand*{\DTLsumforkeys}[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}{}%
+\newcommand*{\DTLsumforkeys}[1][\boolean{true}\and
+ \DTLisnumerical{\DTLthisval}]{%
+ \def\@dtl@cond{#1}%
+ \@dtlsumforkeys
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtlsumforkeys}
+% \begin{macrocode}
+\newcommand*{\@dtlsumforkeys}[4][]{%
+ \def#4{0}%
+% \end{macrocode}
+% Iterate over all the listed data bases
+% \begin{macrocode}
+ \@for\@dtl@dbname:=#2\do{%
+% \end{macrocode}
+% Iterate through this database (using read only version)
+% \begin{macrocode}
+ \@sDTLforeach{\@dtl@dbname}%
+ {#1}% assignment list
+ {%
+% \end{macrocode}
+% Iterate through key list.
+% \begin{macrocode}
+ \@for\@dtl@key:=#3\do{%
+ \@sdtl@getcolumnindex{\@dtl@col}{\@dtl@dbname}{\@dtl@key}%
+ \dtlcurrentrow=\expandafter{\dtl@thisrow}%
+ \dtlgetentryfromrow{\DTLthisval}{\@dtl@col}{\dtlcurrentrow}%
+ \expandafter\ifthenelse\expandafter{\@dtl@cond}%
+ {\DTLadd{#4}{#4}{\DTLthisval}}{}%
+ }%
+ }%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLsumcolumn}
+%\begin{definition}
+%\cs{DTLsumcolumn}\marg{db}\marg{key}\marg{cmd}
+%\end{definition}
+% Quicker version of \cs{DTLsumforkeys} that just sums over
+% one column (specified by \meta{key}) for a single database
+% (specified by \meta{db}) and stores the result in \meta{cmd}.
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\newcommand*{\DTLsumcolumn}[3]{%
+ \def#3{0}%
+% \end{macrocode}
+% Check data base exists
+% \begin{macrocode}
+ \DTLifdbexists{#1}%
+ {%
+% \end{macrocode}
+% Check column exists
+% \begin{macrocode}
+ \@sDTLifhaskey{#1}{#2}%
+ {%
+ \@sdtlforcolumn{\DTLthisval}{#1}{#2}%
+ {%
+ \DTLadd{#3}{#3}{\DTLthisval}%
+ }%
+ }%
+% \end{macrocode}
+% key not defined for this data base
+% \begin{macrocode}
+ {%
+ \PackageError{datatool}{Key `#2' doesn't
+ exist in database `#1'}{}%
+ }%
+ }%
+% \end{macrocode}
+% data base doesn't exist
+% \begin{macrocode}
+ {%
+ \PackageError{datatool}{Data base `#1' doesn't
+ exist}{}%
}%
-}%
}
% \end{macrocode}
%\end{macro}
%
%\begin{macro}{\DTLmeanforkeys}
%\begin{definition}
-%\cs{DTLmeanforkeys}\oarg{condition}\marg{db list}\marg{key list}\marg{cmd}
+%\cs{DTLmeanforkeys}\oarg{condition}\oarg{assign list}\marg{db list}\marg{key list}\marg{cmd}
%\end{definition}
% Computes the arithmetic mean of all entries for each key in
% \meta{key list} over all databases in \meta{db list},
% and stores in \meta{cmd}, which must be a control sequence.
-% The optional argument \meta{condition} is the same as that
-% for \cs{DTLforeach}.
+% The first argument \meta{condition} is the same as that
+% for \cs{DTLforeach}. The second optional argument allows an
+% assignment list to be passed to \cs{DTLforeach}.
+%\changes{2.0}{2009 February 27}{added second optional argument}
% \begin{macrocode}
-\newcommand*{\DTLmeanforkeys}[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
+\newcommand*{\DTLmeanforkeys}[1][\boolean{true}\and
+ \DTLisnumerical{\DTLthisval}]{%
+ \def\@dtl@cond{#1}%
+ \@dtlmeanforkeys
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@elements}
+% Count register to keep track of number of elements
+% \begin{macrocode}
+\newcount\@dtl@elements
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtlmeanforkeys}
+% \begin{macrocode}
+\newcommand*{\@dtlmeanforkeys}[4][]{%
+ \def#4{0}%
+ \@dtl@elements=0\relax
+% \end{macrocode}
+% Iterate over all the listed data bases
+% \begin{macrocode}
+ \@for\@dtl@dbname:=#2\do{%
+% \end{macrocode}
+% Iterate through this database (using read only version)
+% \begin{macrocode}
+ \@sDTLforeach{\@dtl@dbname}%
+ {#1}% assignment list
+ {%
+% \end{macrocode}
+% Iterate through key list.
+% \begin{macrocode}
+ \@for\@dtl@key:=#3\do{%
+ \@sdtl@getcolumnindex{\@dtl@col}{\@dtl@dbname}{\@dtl@key}%
+ \dtlcurrentrow=\expandafter{\dtl@thisrow}%
+ \dtlgetentryfromrow{\DTLthisval}{\@dtl@col}{\dtlcurrentrow}%
+ \expandafter\ifthenelse\expandafter{\@dtl@cond}%
+ {%
+ \DTLadd{#4}{#4}{\DTLthisval}%
+ \advance\@dtl@elements by 1\relax
+ }{}%
+ }%
+ }%
+ }%
+% \end{macrocode}
+% Divide total by number of elements summed.
+% \begin{macrocode}
+ \ifnum\@dtl@elements=0\relax
+ \PackageError{datatool}{Unable to evaluate mean: no data}{}%
+ \else
+ \edef\@dtl@n{\number\@dtl@elements}%
+ \DTLdiv{#4}{#4}{\@dtl@n}%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLmeanforcolumn}
+%\begin{definition}
+%\cs{DTLmeanforcolumn}\marg{db}\marg{key}\marg{cmd}
+%\end{definition}
+% Quicker version of \cs{DTLmeanforkeys} that just computes the
+% mean over one column (specified by \meta{key}) for a single
+% database (specified by \meta{db}) and stores the result in
+% \meta{cmd}.
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\newcommand*{\DTLmeanforcolumn}[3]{%
+ \def#3{0}%
+ \@dtl@elements=0\relax
+% \end{macrocode}
+% Check data base exists
+% \begin{macrocode}
+ \DTLifdbexists{#1}%
+ {%
+% \end{macrocode}
+% Check column exists
+% \begin{macrocode}
+ \@sDTLifhaskey{#1}{#2}%
+ {%
+ \@sdtlforcolumn{\DTLthisval}{#1}{#2}%
+ {%
+ \DTLadd{#3}{#3}{\DTLthisval}%
+ \advance\@dtl@elements by 1\relax
+ }%
+ \ifnum\@dtl@elements=0\relax
+ \PackageError{datatool}{Can't compute mean for
+ column `#2' in database `#1': no data}{}%
+ \else
+ \edef\@dtl@n{\number\@dtl@elements}%
+ \DTLdiv{#3}{#3}{\@dtl@n}%
+ \fi
+ }%
+% \end{macrocode}
+% key not defined for this data base
+% \begin{macrocode}
+ {%
+ \PackageError{datatool}{Key `#2' doesn't
+ exist in database `#1'}{}%
+ }%
+ }%
+% \end{macrocode}
+% data base doesn't exist
+% \begin{macrocode}
+ {%
+ \PackageError{datatool}{Data base `#1' doesn't
+ exist}{}%
+ }%
}
% \end{macrocode}
%\end{macro}
%
%\begin{macro}{\DTLvarianceforkeys}
%\begin{definition}
-%\cs{DTLvarianceforkeys}\oarg{condition}\marg{db list}\marg{key list}\marg{cmd}
+%\cs{DTLvarianceforkeys}\oarg{condition}\oarg{assign list}\marg{db list}\marg{key list}\marg{cmd}
%\end{definition}
% Computes the variance of all entries for each key in
% \meta{key list} over all databases in \meta{db list},
% and stores in \meta{cmd}, which must be a control sequence.
-% The optional argument \meta{condition} is the same as that
-% for \cs{DTLforeach}.
+% The first optional argument \meta{condition} is the same as that
+% for \cs{DTLforeach}. The second optional argument is an assignment
+% list to pass to \cs{DTLforeach} in case it is required for the
+% condition.
+%\changes{2.0}{2009 February 27}{added second optional argument}
% \begin{macrocode}
-\newcommand*{\DTLvarianceforkeys}[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}{}%
+\newcommand*{\DTLvarianceforkeys}[1][\boolean{true}\and
+ \DTLisnumerical{\DTLthisval}]{%
+ \def\@dtl@cond{#1}%
+ \@dtlvarianceforkeys
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtlmeanforkeys}
+% \begin{macrocode}
+\newcommand*{\@dtlvarianceforkeys}[4][]{%
+ \@dtlmeanforkeys[#1]{#2}{#3}{\dtl@mean}%
+ \def#4{0}%
+ \@dtl@elements=0\relax
+% \end{macrocode}
+% Iterate over all the listed data bases
+% \begin{macrocode}
+ \@for\@dtl@dbname:=#2\do{%
+% \end{macrocode}
+% Iterate through this database (using read only version)
+% \begin{macrocode}
+ \@sDTLforeach{\@dtl@dbname}%
+ {#1}% assignment list
+ {%
+% \end{macrocode}
+% Iterate through key list.
+% \begin{macrocode}
+ \@for\@dtl@key:=#3\do{%
+ \@sdtl@getcolumnindex{\@dtl@col}{\@dtl@dbname}{\@dtl@key}%
+ \dtlcurrentrow=\expandafter{\dtl@thisrow}%
+ \dtlgetentryfromrow{\DTLthisval}{\@dtl@col}{\dtlcurrentrow}%
+ \expandafter\ifthenelse\expandafter{\@dtl@cond}%
+ {%
+% \end{macrocode}
+% compute $(x_i - \mu)^2$
+% \begin{macrocode}
+ \DTLsub{\dtl@diff}{\DTLthisval}{\dtl@mean}%
+ \DTLmul{\dtl@diff}{\dtl@diff}{\dtl@diff}%
+ \DTLadd{#4}{#4}{\dtl@diff}%
+ \advance\@dtl@elements by 1\relax
+ }{}%
+ }%
+ }%
}%
-}%
-\ifnum\dtl@n=0\relax
- \PackageError{datatool}{Can't compute variance, no data!}{}%
-\else
- \DTLdiv{#4}{#4}{\dtl@n}%
-\fi
+% \end{macrocode}
+% Divide by number of elements.
+% \begin{macrocode}
+ \ifnum\@dtl@elements=0\relax
+ \PackageError{datatool}{Unable to evaluate variance: no data}{}%
+ \else
+ \edef\@dtl@n{\number\@dtl@elements}%
+ \DTLdiv{#4}{#4}{\@dtl@n}%
+ \fi
}
% \end{macrocode}
%\end{macro}
%
+%\begin{macro}{\DTLvarianceforcolumn}
+%\begin{definition}
+%\cs{DTLvarianceforcolumn}\marg{db}\marg{key}\marg{cmd}
+%\end{definition}
+% Quicker version of \cs{DTLvarianceforkeys} that just computes the
+% variance over one column (specified by \meta{key}) for a single
+% database (specified by \meta{db}) and stores the result in
+% \meta{cmd}.
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\newcommand*{\DTLvarianceforcolumn}[3]{%
+ \DTLmeanforcolumn{#1}{#2}{\dtl@mean}%
+ \def#3{0}%
+ \@dtl@elements=0\relax
+% \end{macrocode}
+% Check data base exists
+% \begin{macrocode}
+ \DTLifdbexists{#1}%
+ {%
+% \end{macrocode}
+% Check column exists
+% \begin{macrocode}
+ \@sDTLifhaskey{#1}{#2}%
+ {%
+ \@sdtlforcolumn{\DTLthisval}{#1}{#2}%
+ {%
+% \end{macrocode}
+% compute $(x_i - \mu)^2$
+% \begin{macrocode}
+ \DTLsub{\dtl@diff}{\DTLthisval}{\dtl@mean}%
+ \DTLmul{\dtl@diff}{\dtl@diff}{\dtl@diff}%
+ \DTLadd{#3}{#3}{\dtl@diff}%
+ \advance\@dtl@elements by 1\relax
+ }%
+ \ifnum\@dtl@elements=0\relax
+ \PackageError{datatool}{Can't compute variance for
+ column `#2' in database `#1': no data}{}%
+ \else
+ \edef\@dtl@n{\number\@dtl@elements}%
+ \DTLdiv{#3}{#3}{\@dtl@n}%
+ \fi
+ }%
+% \end{macrocode}
+% key not defined for this data base
+% \begin{macrocode}
+ {%
+ \PackageError{datatool}{Key `#2' doesn't
+ exist in database `#1'}{}%
+ }%
+ }%
+% \end{macrocode}
+% data base doesn't exist
+% \begin{macrocode}
+ {%
+ \PackageError{datatool}{Data base `#1' doesn't
+ exist}{}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%
%\begin{macro}{\DTLsdforkeys}
%\begin{definition}
-%\cs{DTLsdforkeys}\oarg{condition}\marg{db list}\marg{key list}\marg{cmd}
+%\cs{DTLsdforkeys}\oarg{condition}\oarg{assign list}\marg{db list}\marg{key list}\marg{cmd}
%\end{definition}
% Computes the standard deviation of all entries for each key in
% \meta{key list} over all databases in \meta{db list},
% and stores in \meta{cmd}, which must be a control sequence.
-% The optional argument \meta{condition} is the same as that
-% for \cs{DTLforeach}.
+% The first optional argument \meta{condition} is the same as that
+% for \cs{DTLforeach}. The second optional argument is an
+% assignment list for \cs{DTLforeach} in case it is needed for
+% the condition.
+%\changes{2.0}{2009 February 27}{added second optional argument}
% \begin{macrocode}
-\newcommand*{\DTLsdforkeys}[4][\boolean{true}\and
+\newcommand*{\DTLsdforkeys}[1][\boolean{true}\and
\DTLisnumerical{\DTLthisval}]{%
-\DTLvarianceforkeys[#1]{#2}{#3}{#4}%
-\DTLsqrt{#4}{#4}%
+ \def\@dtl@cond{#1}%
+ \@dtlsdforkeys
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@dtlsdforkeys}
+% \begin{macrocode}
+\newcommand*{\@dtlsdforkeys}[4][]{%
+ \@dtlvarianceforkeys[#1]{#2}{#3}{#4}%
+ \DTLsqrt{#4}{#4}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLsdforcolumn}
+%\begin{definition}
+%\cs{DTLsdforcolumn}\marg{db}\marg{key}\marg{cmd}
+%\end{definition}
+% Quicker version of \cs{DTLsdforkeys} that just computes the
+% standard deviation over one column (specified by \meta{key}) for
+% a single database (specified by \meta{db}) and stores the result
+% in \meta{cmd}.
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\newcommand*{\DTLsdforcolumn}[3]{%
+ \DTLvarianceforcolumn{#1}{#2}{#3}%
+ \DTLsqrt{#3}{#3}%
}
% \end{macrocode}
%\end{macro}
%
%\begin{macro}{\DTLminforkeys}
%\begin{definition}
-%\cs{DTLminforkeys}\oarg{condition}\marg{db list}\marg{key list}\marg{cmd}
+%\cs{DTLminforkeys}\oarg{condition}\oarg{assign list}\marg{db list}\marg{key list}\marg{cmd}
%\end{definition}
% Determines the minimum over all entries for each key in
% \meta{key list} over all databases in \meta{db list},
% and stores in \meta{cmd}, which must be a control sequence.
-% The optional argument \meta{condition} is the same as that
-% for \cs{DTLforeach}.
+% The first optional argument \meta{condition} is the same as that
+% for \cs{DTLforeach}. The second optional argument is an
+% assignment list for \cs{DTLforeach} in the event that extra
+% information is need for the condition.
+%\changes{2.0}{2009 February 27}{added second optional argument}
% \begin{macrocode}
-\newcommand*{\DTLminforkeys}[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}{}%
+\newcommand*{\DTLminforkeys}[1][\boolean{true}\and
+ \DTLisnumerical{\DTLthisval}]{%
+ \def\@dtl@cond{#1}%
+ \@dtlminforkeys
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtlminforkeys}
+% \begin{macrocode}
+\newcommand*{\@dtlminforkeys}[4][]{%
+ \def#4{}%
+% \end{macrocode}
+% Iterate over all the listed data bases
+% \begin{macrocode}
+ \@for\@dtl@dbname:=#2\do{%
+% \end{macrocode}
+% Iterate through this database (using read only version)
+% \begin{macrocode}
+ \@sDTLforeach{\@dtl@dbname}%
+ {#1}% assignment list
+ {%
+% \end{macrocode}
+% Iterate through key list.
+% \begin{macrocode}
+ \@for\@dtl@key:=#3\do{%
+ \@sdtl@getcolumnindex{\@dtl@col}{\@dtl@dbname}{\@dtl@key}%
+ \dtlcurrentrow=\expandafter{\dtl@thisrow}%
+ \dtlgetentryfromrow{\DTLthisval}{\@dtl@col}{\dtlcurrentrow}%
+ \expandafter\ifthenelse\expandafter{\@dtl@cond}%
+ {%
+ \ifx#4\@empty
+ \let#4\DTLthisval
+ \else
+ \DTLmin{#4}{#4}{\DTLthisval}%
+ \fi
+ }{}%
+ }%
+ }%
}%
-}}
+}
% \end{macrocode}
%\end{macro}
%
+%\begin{macro}{\DTLminforcolumn}
+%\begin{definition}
+%\cs{DTLminforcolumn}\marg{db}\marg{key}\marg{cmd}
+%\end{definition}
+% Quicker version of \cs{DTLminforkeys} that just finds the
+% minimum value in one column (specified by \meta{key}) for a
+% single database (specified by \meta{db}) and stores the result
+% in \meta{cmd}.
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\newcommand*{\DTLminforcolumn}[3]{%
+ \def#3{}%
+% \end{macrocode}
+% Check data base exists
+% \begin{macrocode}
+ \DTLifdbexists{#1}%
+ {%
+% \end{macrocode}
+% Check column exists
+% \begin{macrocode}
+ \@sDTLifhaskey{#1}{#2}%
+ {%
+ \@sdtlforcolumn{\DTLthisval}{#1}{#2}%
+ {%
+ \ifx#3\@empty
+ \let#3\DTLthisval
+ \else
+ \DTLmin{#3}{#3}{\DTLthisval}%
+ \fi
+ }%
+ }%
+% \end{macrocode}
+% key not defined for this data base
+% \begin{macrocode}
+ {%
+ \PackageError{datatool}{Key `#2' doesn't
+ exist in database `#1'}{}%
+ }%
+ }%
+% \end{macrocode}
+% data base doesn't exist
+% \begin{macrocode}
+ {%
+ \PackageError{datatool}{Data base `#1' doesn't
+ exist}{}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%
%\begin{macro}{\DTLmaxforkeys}
%\begin{definition}
-%\cs{DTLmaxforkeys}\oarg{condition}\marg{db list}\marg{key list}\marg{cmd}
+%\cs{DTLmaxforkeys}\oarg{condition}\oarg{assign list}\marg{db list}\marg{key list}\marg{cmd}
%\end{definition}
% Determines the maximum over all entries for each key in
% \meta{key list} over all databases in \meta{db list},
% and stores in \meta{cmd}, which must be a control sequence.
-% The optional argument \meta{condition} is the same as that
-% for \cs{DTLforeach}.
+% The first optional argument \meta{condition} is the same as that
+% for \cs{DTLforeach}. The second optional argument is an
+% assignment list to pass to \cs{DTLforeach} in the event that
+% extra information is required in the condition.
+%\changes{2.0}{2009 February 27}{added second optional argument}
% \begin{macrocode}
-\newcommand*{\DTLmaxforkeys}[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}{}%
+\newcommand*{\DTLmaxforkeys}[1][\boolean{true}\and
+ \DTLisnumerical{\DTLthisval}]{%
+ \def\@dtl@cond{#1}%
+ \@dtlmaxforkeys
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtlmaxforkeys}
+% \begin{macrocode}
+\newcommand*{\@dtlmaxforkeys}[4][]{%
+ \def#4{}%
+% \end{macrocode}
+% Iterate over all the listed data bases
+% \begin{macrocode}
+ \@for\@dtl@dbname:=#2\do{%
+% \end{macrocode}
+% Iterate through this database (using read only version)
+% \begin{macrocode}
+ \@sDTLforeach{\@dtl@dbname}%
+ {#1}% assignment list
+ {%
+% \end{macrocode}
+% Iterate through key list.
+% \begin{macrocode}
+ \@for\@dtl@key:=#3\do{%
+ \@sdtl@getcolumnindex{\@dtl@col}{\@dtl@dbname}{\@dtl@key}%
+ \dtlcurrentrow=\expandafter{\dtl@thisrow}%
+ \dtlgetentryfromrow{\DTLthisval}{\@dtl@col}{\dtlcurrentrow}%
+ \expandafter\ifthenelse\expandafter{\@dtl@cond}%
+ {%
+ \ifx#4\@empty
+ \let#4\DTLthisval
+ \else
+ \DTLmax{#4}{#4}{\DTLthisval}%
+ \fi
+ }{}%
+ }%
+ }%
}%
-}}
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLmaxforcolumn}
+%\begin{definition}
+%\cs{DTLmaxforcolumn}\marg{db}\marg{key}\marg{cmd}
+%\end{definition}
+% Quicker version of \cs{DTLmaxforkeys} that just finds the
+% maximum value in one column (specified by \meta{key}) for a
+% single database (specified by \meta{db}) and stores the result
+% in \meta{cmd}.
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\newcommand*{\DTLmaxforcolumn}[3]{%
+ \def#3{}%
+% \end{macrocode}
+% Check data base exists
+% \begin{macrocode}
+ \DTLifdbexists{#1}%
+ {%
+% \end{macrocode}
+% Check column exists
+% \begin{macrocode}
+ \@sDTLifhaskey{#1}{#2}%
+ {%
+ \@sdtlforcolumn{\DTLthisval}{#1}{#2}%
+ {%
+ \ifx#3\@empty
+ \let#3\DTLthisval
+ \else
+ \DTLmax{#3}{#3}{\DTLthisval}%
+ \fi
+ }%
+ }%
+% \end{macrocode}
+% key not defined for this data base
+% \begin{macrocode}
+ {%
+ \PackageError{datatool}{Key `#2' doesn't
+ exist in database `#1'}{}%
+ }%
+ }%
+% \end{macrocode}
+% data base doesn't exist
+% \begin{macrocode}
+ {%
+ \PackageError{datatool}{Data base `#1' doesn't
+ exist}{}%
+ }%
+}
% \end{macrocode}
%\end{macro}
%
@@ -10446,17 +14306,29 @@ deeply}{}%
% of the database called \meta{db name} which contains the key
% \meta{ref key} which has the value \meta{value}.
%\changes{1.01}{2007 Aug 17}{new}
+%\changes{2.0}{2009 February 27}{updated to use new database
+% structure}
% \begin{macrocode}
\newcommand*{\DTLgetvalueforkey}[5]{%
-{%
-\global\let#1=\DTLstringnull
-\@sDTLforeach{#3}{\dtl@valueA=#2,\dtl@refvalue=#4}{%
-\DTLifnull{\dtl@refvalue}{}{%
-\ifthenelse{\equal{\dtl@refvalue}{#5}}{%
-\global\let#1=\dtl@valueA
-\@endfortrue
-}{}}}%
-}}
+% \end{macrocode}
+% Get row containing referenced (key,value) pair
+% \begin{macrocode}
+ \DTLgetrowforkey{\@dtl@row}{#3}{#4}{#5}%
+% \end{macrocode}
+% Get column number for \meta{key}
+% \begin{macrocode}
+ \@sdtl@getcolumnindex{\@dtl@col}{#3}{#2}%
+% \end{macrocode}
+% Get value for given column
+% \begin{macrocode}
+ {%
+ \dtlcurrentrow=\expandafter{\@dtl@row}%
+ \edef\@dtl@dogetval{\noexpand\dtlgetentryfromcurrentrow
+ {\noexpand\@dtl@val}{\@dtl@col}}%
+ \@dtl@dogetval
+ \global\let#1=\@dtl@val
+ }%
+}
% \end{macrocode}
%\end{macro}
%
@@ -10468,20 +14340,58 @@ deeply}{}%
% This (globally) sets \meta{cmd} (a control sequence) to the
% first row
% of the database called \meta{db name} which contains the key
-% \meta{ref key} which has the value \meta{value}.
+% \meta{ref key} that has the value \meta{value}.
%\changes{1.01}{2007 Aug 17}{new}
+%\changes{2.0}{2009 February 27}{update to use new database
+% structure}
% \begin{macrocode}
\newcommand*{\DTLgetrowforkey}[4]{%
-{%
-\global\let#1=\@empty
-\@sDTLforeach{#2}{\dtl@refvalue=#3}{%
-\DTLifnull{\dtl@refvalue}{}{%
-\ifthenelse{\equal{\dtl@refvalue}{#4}}{%
-\expandafter\global\expandafter\let\expandafter#1
- \csname @dtl@thiscurrentrow@\romannumeral\dtlforeachlevel\endcsname
-\@endfortrue
-}{}}}%
-}}
+ \global\let#1=\@empty
+ \@sDTLforeach{#2}{\dtl@refvalue=#3}{%
+ \DTLifnull{\dtl@refvalue}%
+ {}%
+ {%
+ \ifthenelse{\equal{\dtl@refvalue}{#4}}%
+ {%
+ \xdef#1{\the\dtlcurrentrow}%
+ \dtlbreak
+ }%
+ {}%
+ }%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtlsplitrow}
+%\begin{definition}
+%\cs{dtlsplitrow}\marg{row specs}\marg{col num}\marg{before
+% cs}\marg{after cs}
+%\end{definition}
+% Splits the row around the entry given by \meta{col num}. The
+% entries before the split are stored in \meta{before cs} and the
+% entries after the split are stored in \meta{after cs}.
+% \meta{row specs} and \meta{col num} need to be expanded before use.
+% \begin{macrocode}
+\newcommand*{\dtlsplitrow}[4]{%
+ \def\@dtlsplitrow##1%before stuff
+ \db@col@id@w #2\db@col@id@end@% column id
+ ##2% unwanted stuff
+ \db@col@id@w #2\db@col@id@end@% column id
+ ##3% after stuff
+ \q@nil{\def#3{##1}\def#4{##3}}%
+ \@dtlsplitrow#1\q@nil
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\subsection{Sorting Databases}
+%
+%\begin{macro}{\@dtl@list}
+% Token register to store data when sorting.
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\newtoks\@dtl@list
% \end{macrocode}
%\end{macro}
%
@@ -10497,6 +14407,7 @@ deeply}{}%
% version uses a case insensitive string comparison.
%\changes{1.01}{2007 Aug 17}{added optional argument}
%\changes{1.01}{2007 Aug 17}{added starred version}
+%\changes{2.0}{2009 February 27}{updated to use new data structure}
% \begin{macrocode}
\newcommand*{\DTLsort}{\@ifstar\@sDTLsort\@DTLsort}
% \end{macrocode}
@@ -10505,257 +14416,623 @@ deeply}{}%
%\begin{macro}{\@DTLsort}
% Unstarred (case sensitive) version.
% \begin{macrocode}
-\newcommand*{\@DTLsort}[3][]{%
-\edef\@dtl@replacementkeys{#1}%
-\edef\@dtl@sortorder{#2}%
-\edef\@dtl@dbname{#3}%
-\let\@dtl@comparecs=\dtlcompare
-\expandafter\let\expandafter\@dtl@list\csname dtldb@#3\endcsname
-\dtl@sortlist{\@dtl@list}{\@dtl@sortcriteria}%
-\expandafter\global\expandafter
- \let\csname dtldb@#3\endcsname=\@dtl@list}
+\newcommand{\@DTLsort}[3][]{%
+% \end{macrocode}
+% Check the database exists
+% \begin{macrocode}
+ \DTLifdbexists{#3}%
+ {%
+% \end{macrocode}
+% Store replacement keys in \cs{@dtl@replacementkeys}.
+% \begin{macrocode}
+ \edef\@dtl@replacementkeys{#1}%
+% \end{macrocode}
+% Store sort order in \cs{@dtl@sortorder}.
+% \begin{macrocode}
+ \edef\@dtl@sortorder{#2}%
+% \end{macrocode}
+% Set \cs{@dtl@comparecs} to the required string comparison
+% function. (Using case sensitive comparison macro \cs{dtlcompare}.)
+% \begin{macrocode}
+ \let\@dtl@comparecs=\dtlcompare
+% \end{macrocode}
+% Sort the database.
+% \begin{macrocode}
+ \dtl@sortdata{#3}%
+ }%
+ {%
+ \PackageError{datatool}{Database `#3' doesn't exist}{}%
+ }%
+}
% \end{macrocode}
%\end{macro}
+%
%\begin{macro}{\@sDTLsort}
% Starred (case insensitive) version.
% \begin{macrocode}
-\newcommand*{\@sDTLsort}[3][]{%
-\edef\@dtl@replacementkeys{#1}%
-\edef\@dtl@sortorder{#2}%
-\edef\@dtl@dbname{#3}%
-\let\@dtl@comparecs=\dtlicompare
-\expandafter\let\expandafter\@dtl@list\csname dtldb@#3\endcsname
-\dtl@sortlist{\@dtl@list}{\@dtl@sortcriteria}%
-\expandafter\global\expandafter
- \let\csname dtldb@#3\endcsname=\@dtl@list}
+\newcommand{\@sDTLsort}[3][]{%
+% \end{macrocode}
+% Check the database exists
+% \begin{macrocode}
+ \DTLifdbexists{#3}%
+ {%
+% \end{macrocode}
+% Store replacement keys in \cs{@dtl@replacementkeys}.
+% \begin{macrocode}
+ \edef\@dtl@replacementkeys{#1}%
+% \end{macrocode}
+% Store sort order in \cs{@dtl@sortorder}.
+% \begin{macrocode}
+ \edef\@dtl@sortorder{#2}%
+% \end{macrocode}
+% Set \cs{@dtl@comparecs} to the required string comparison
+% function. (Using case insensitive comparison macro
+% \cs{dtlicompare}.)
+% \begin{macrocode}
+ \let\@dtl@comparecs=\dtlicompare
+% \end{macrocode}
+% Sort the database.
+% \begin{macrocode}
+ \dtl@sortdata{#3}%
+ }%
+ {%
+ \PackageError{datatool}{Database `#3' doesn't exist}{}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@rowa}
+% Token register to store first row when sorting.
+% \begin{macrocode}
+\newtoks\@dtl@rowa
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@dtl@rowb}
+% Token register to store comparison row when sorting.
+% \begin{macrocode}
+\newtoks\@dtl@rowb
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@sortdata}
+%\begin{definition}
+%\cs{dtl@sortdata}\marg{db}
+%\end{definition}
+% Sorts the data in named database using an insertion sort
+% algorithm.
+% \cs{@dtl@replacementkeys}, \cs{@dtl@sortorder} and
+% \cs{@dtl@comparecs} must be set prior to use.
+%\changes{2.0}{2009 February 27}{new}
+% \begin{macrocode}
+\newcommand*{\dtl@sortdata}[1]{%
+% \end{macrocode}
+% Initialise macro containing sorted data.
+% \begin{macrocode}
+ \def\@dtl@sortedlist{}%
+% \end{macrocode}
+% Store database name.
+% \begin{macrocode}
+ \edef\@dtl@dbname{#1}%
+% \end{macrocode}
+% Iterate through each row and insert into sorted list.
+% \begin{macrocode}
+ \@dtlforeachrow(\@dtl@rowAnum,\@dtl@rowAcontents)\in{#1}\do{%
+ \@dtl@rowa=\expandafter{\@dtl@rowAcontents}%
+% \end{macrocode}
+% Create a temporary list
+% \begin{macrocode}
+ \def\@dtl@newlist{}%
+% \end{macrocode}
+% Initialise the insertion for this iteration. Insertion hasn't
+% been done yet.
+% \begin{macrocode}
+ \@dtl@insertdonefalse
+% \end{macrocode}
+% Initialise row index to 0
+% \begin{macrocode}
+ \dtlrownum=0\relax
+% \end{macrocode}
+% Iterate through sorted list.
+% \begin{macrocode}
+ \expandafter\@dtl@foreachrow\@dtl@sortedlist
+ \db@row@elt@w%
+ \db@row@id@w \@nil\db@row@id@end@%
+ \db@row@id@w \@nil\db@row@id@end@%
+ \db@row@elt@end@%
+ \@@{\@dtl@rowBnum}{\@dtl@rowBcontents}{%
+% \end{macrocode}
+% Store row B in a token register
+% \begin{macrocode}
+ \@dtl@rowb=\expandafter{\@dtl@rowBcontents}%
+% \end{macrocode}
+% Get current row number of sorted list
+% \begin{macrocode}
+ \dtlrownum=\@dtl@rowBnum
+% \end{macrocode}
+% Has the insertion been done?
+% \begin{macrocode}
+ \if@dtl@insertdone
+% \end{macrocode}
+% New element has already been inserted, so just increment the row
+% number to compensate for the inserted row.
+% \begin{macrocode}
+ \advance\dtlrownum by 1\relax
+ \else
+% \end{macrocode}
+% Insertion hasn't been done yet.
+% Compare row A and row B.
+% \begin{macrocode}
+ \@dtl@sortcriteria{\@dtl@rowa}{\@dtl@rowb}%
+% \end{macrocode}
+% If \cs{dtl@sortresult} is negative insert A before B.
+% \begin{macrocode}
+ \ifnum\dtl@sortresult<0\relax
+% \end{macrocode}
+% Insert row A into new list. First store \cs{@dtl@newlist} in
+% \cs{toks@}.
+% \begin{macrocode}
+ \toks@=\expandafter{\@dtl@newlist}%
+% \end{macrocode}
+% Update \cs{@dtl@newlist} to be the old value followed by
+% row A.
+% \begin{macrocode}
+ \edef\@dtl@newlist{%
+% \end{macrocode}
+% Old value:
+% \begin{macrocode}
+ \the\toks@
+% \end{macrocode}
+% Format row A
+% \begin{macrocode}
+ \noexpand\db@row@elt@w%
+ \noexpand\db@row@id@w \number\dtlrownum
+ \noexpand\db@row@id@end@%
+ \the\@dtl@rowa
+ \noexpand\db@row@id@w \number\dtlrownum
+ \noexpand\db@row@id@end@%
+ \noexpand\db@row@elt@end@%
+ }%
+% \end{macrocode}
+% Increment row number to compensate for inserted row.
+% \begin{macrocode}
+ \advance\dtlrownum by 1\relax
+% \end{macrocode}
+% Mark insertion done.
+% \begin{macrocode}
+ \@dtl@insertdonetrue
+ \fi
+ \fi
+% \end{macrocode}
+% Insert row B
+% \begin{macrocode}
+ \toks@=\expandafter{\@dtl@newlist}%
+ \edef\@dtl@newlist{\the\toks@
+% \end{macrocode}
+% row B
+% \begin{macrocode}
+ \noexpand\db@row@elt@w%
+ \noexpand\db@row@id@w \number\dtlrownum
+ \noexpand\db@row@id@end@%
+ \the\@dtl@rowb
+ \noexpand\db@row@id@w \number\dtlrownum
+ \noexpand\db@row@id@end@%
+ \noexpand\db@row@elt@end@%
+ }%
+% \end{macrocode}
+% Repeat loop.
+% \begin{macrocode}
+ }\q@nil
+% \end{macrocode}
+% If row A hasn't been inserted, do so now.
+% \begin{macrocode}
+ \if@dtl@insertdone
+ \else
+% \end{macrocode}
+% \cs{dtlrownum} contains the index of the last row in new list,
+% So increment it to get the new index for row A.
+% \begin{macrocode}
+ \advance\dtlrownum by 1\relax
+% \end{macrocode}
+% Insert row A.
+% \begin{macrocode}
+ \toks@=\expandafter{\@dtl@newlist}%
+ \edef\@dtl@newlist{\the\toks@
+% \end{macrocode}
+% row A
+% \begin{macrocode}
+ \noexpand\db@row@elt@w%
+ \noexpand\db@row@id@w \number\dtlrownum
+ \noexpand\db@row@id@end@%
+ \the\@dtl@rowa
+ \noexpand\db@row@id@w \number\dtlrownum
+ \noexpand\db@row@id@end@%
+ \noexpand\db@row@elt@end@%
+ }%
+ \fi
+% \end{macrocode}
+% Set sorted list to new list.
+% \begin{macrocode}
+ \let\@dtl@sortedlist=\@dtl@newlist
+ }%
+% \end{macrocode}
+% Update database.
+% \begin{macrocode}
+ \expandafter\global\csname dtldb@#1\endcsname=\expandafter
+ {\@dtl@sortedlist}%
+}
% \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@dtl@sortcriteria}
%\begin{definition}
-% \cs{@dtl@sortcriteria}\marg{a}\marg{b}
+% \cs{@dtl@sortcriteria}\marg{row a toks}\marg{row b toks}
%\end{definition}
-% Sort criteria. \cs{@dtl@dbname} and
-% \cs{@dtl@sortorder} must be set before use.
+% \cs{@dtl@dbname} and \cs{@dtl@sortorder} must be set before use
+% \cs{@dtl@sortorder} is a comma separated list of either just keys
+% or \meta{key}=\meta{direction}.
+% (Check keys are valid before use.)
+%\changes{2.0}{2009 February 27}{updated to take account of new
+% database structure}
% \begin{macrocode}
\newcommand{\@dtl@sortcriteria}[2]{%
-\@for\@dtl@level:=\@dtl@sortorder\do{%
- \expandafter\@dtl@getsortdirection\@dtl@level=\relax%
- \@ifundefined{@dtl@idtype@\@dtl@dbname @\@dtl@key}{%
- \ifx\@dtl@replacementkeys\@empty
- \PackageError{datatool}{Unknown key `\@dtl@key' for database
- `\@dtl@dbname'}{}%
- \else
- \dtl@gathervalues[keya]{\@dtl@dbname}{#1}%
- \dtl@gathervalues[keyb]{\@dtl@dbname}{#2}%
- \@ifundefined{@dtl@keya@\@dtl@key}{%
- \@dtl@setnull{\@dtl@tmpa}{\@dtl@key}%
- }{%
- \expandafter\let\expandafter\@dtl@tmpa\expandafter
- =\csname @dtl@keya@\@dtl@key\endcsname}%
- \@ifundefined{@dtl@keyb@\@dtl@key}{%
- \@dtl@setnull{\@dtl@tmpb}{\@dtl@key}%
- }{%
- \expandafter\let\expandafter\@dtl@tmpb\expandafter
- =\csname @dtl@keyb@\@dtl@key\endcsname}%
- \let\@dtl@keya=\@dtl@key
- \let\@dtl@keyb=\@dtl@key
- \DTLifnull{\@dtl@tmpa}{%
- % find first non null key in list of replacement keys
- \@for\@dtl@keya:=\@dtl@replacementkeys\do{%
- \@ifundefined{@dtl@keya@\@dtl@keya}{}{%
- \expandafter\let\expandafter\@dtl@tmpa\expandafter
- =\csname @dtl@keya@\@dtl@keya\endcsname
- \DTLifnull{\@dtl@tmpa}{}{\@endfortrue}}%
- }%
- \if@endfor \else\let\@dtl@keya=\@dtl@key \fi
- \@endforfalse
- }{}%
- \DTLifnull{\@dtl@tmpb}{%
- % find first non null key in list of replacement keys
- \@for\@dtl@keyb:=\@dtl@replacementkeys\do{%
- \@ifundefined{@dtl@keyb@\@dtl@keyb}{}{%
- \expandafter\let\expandafter\@dtl@tmpb\expandafter
- =\csname @dtl@keyb@\@dtl@keyb\endcsname
- \DTLifnull{\@dtl@tmpb}{}{\@endfortrue}}%
- }%
- \if@endfor \else\let\@dtl@keyb=\@dtl@key \fi
- \@endforfalse
- }{}%
- \@ifundefined{@dtl@idtype@\@dtl@dbname @\@dtl@keya}{%
- \@ifundefined{@dtl@idtype@\@dtl@dbname @\@dtl@keyb}{%
- \dtl@sortresult=0\relax}{\dtl@sortresult=-1\relax}%
- }{%
- \@ifundefined{@dtl@idtype@\@dtl@dbname @\@dtl@keyb}{%
- \dtl@sortresult=1\relax}{%
- \dtl@compare@{\@dtl@keya}{\@dtl@keyb}{#1}{#2}%
- }%
- }%
- \fi
- }{%
- \ifx\@dtl@replacementkeys\@empty
- \dtl@compare{\@dtl@key}{#1}{#2}%
- \else
- \dtl@gathervalues[keya]{\@dtl@dbname}{#1}%
- \dtl@gathervalues[keyb]{\@dtl@dbname}{#2}%
- \@ifundefined{@dtl@keya@\@dtl@key}{%
- \@dtl@setnull{\@dtl@tmpa}{\@dtl@key}%
- }{%
- \expandafter\let\expandafter\@dtl@tmpa\expandafter
- =\csname @dtl@keya@\@dtl@key\endcsname}%
- \@ifundefined{@dtl@keyb@\@dtl@key}{%
- \@dtl@setnull{\@dtl@tmpb}{\@dtl@key}%
- }{%
- \expandafter\let\expandafter\@dtl@tmpb\expandafter
- =\csname @dtl@keyb@\@dtl@key\endcsname}%
- \let\@dtl@keya=\@dtl@key
- \let\@dtl@keyb=\@dtl@key
- \DTLifnull{\@dtl@tmpa}{%
- % find first non null key in list of replacement keys
- \@for\@dtl@keya:=\@dtl@replacementkeys\do{%
- \@ifundefined{@dtl@keya@\@dtl@keya}{}{%
- \expandafter\let\expandafter\@dtl@tmpa\expandafter
- =\csname @dtl@keya@\@dtl@keya\endcsname
- \DTLifnull{\@dtl@tmpa}{}{\@endfortrue}}%
- }%
- \if@endfor \else\let\@dtl@keya=\@dtl@key \fi
- \@endforfalse
- }{}%
- \DTLifnull{\@dtl@tmpb}{%
- % find first non null key in list of replacement keys
- \@for\@dtl@keyb:=\@dtl@replacementkeys\do{%
- \@ifundefined{@dtl@keyb@\@dtl@keyb}{}{%
- \expandafter\let\expandafter\@dtl@tmpb\expandafter
- =\csname @dtl@keyb@\@dtl@keyb\endcsname
- \DTLifnull{\@dtl@tmpb}{}{\@endfortrue}}%
- }%
- \if@endfor \else\let\@dtl@keyb=\@dtl@key \fi
- \@endforfalse
- }{}%
- \dtl@compare@{\@dtl@keya}{\@dtl@keyb}{#1}{#2}%
- \fi
- \multiply\dtl@sortresult by \@dtl@sortdirection\relax
- \ifnum\dtl@sortresult=0\relax
- \else
- \@endfortrue
- \fi
- }%
-}%
+% \end{macrocode}
+% Iterate through the sort order.
+% \begin{macrocode}
+ \@for\@dtl@level:=\@dtl@sortorder\do{%
+% \end{macrocode}
+% Set \cs{@dtl@sortdirection} to $-1$ (ascending) or $+1$
+% (descending). Key is stored in \cs{@dtl@key}.
+% \begin{macrocode}
+ \expandafter\@dtl@getsortdirection\@dtl@level=\relax
+% \end{macrocode}
+% Initially comparing on the same key
+% \begin{macrocode}
+ \let\@dtl@keya=\@dtl@key
+ \let\@dtl@keyb=\@dtl@key
+% \end{macrocode}
+% Get values corresponding to key from both rows.
+% First get column index corresponding to key.
+% \begin{macrocode}
+ \@sdtl@getcolumnindex{\@dtl@col}{\@dtl@dbname}{\@dtl@key}%
+% \end{macrocode}
+% Get entry for this column from row A and store in \cs{@dtl@a}.
+% \begin{macrocode}
+ \dtlgetentryfromrow{\@dtl@a}{\@dtl@col}{#1}%
+% \end{macrocode}
+% Get entry for this column from row B and store in \cs{@dtl@b}.
+% \begin{macrocode}
+ \dtlgetentryfromrow{\@dtl@b}{\@dtl@col}{#2}%
+% \end{macrocode}
+% Has value from row A been defined?
+% \begin{macrocode}
+ \ifx\@dtl@a\dtlnovalue
+% \end{macrocode}
+% Value hasn't been defined so set to null
+% \begin{macrocode}
+ \@dtl@setnull{\@dtl@a}{\@dtl@key}%
+ \fi
+% \end{macrocode}
+% Has value from row B been defined?
+% \begin{macrocode}
+ \ifx\@dtl@b\dtlnovalue
+% \end{macrocode}
+% Value hasn't been defined so set to null
+% \begin{macrocode}
+ \@dtl@setnull{\@dtl@b}{\@dtl@key}%
+ \fi
+% \end{macrocode}
+% Check if value for row A is null.
+% \begin{macrocode}
+ \DTLifnull{\@dtl@a}%
+ {%
+% \end{macrocode}
+% Value for row A is null, so find the first non null key in list of
+% replacement keys.
+% \begin{macrocode}
+ \@for\@dtl@keya:=\@dtl@replacementkeys\do{%
+% \end{macrocode}
+% Get column corresponding to this key.
+% \begin{macrocode}
+ \@sdtl@getcolumnindex{\@dtl@col}{\@dtl@dbname}{\@dtl@keya}%
+ \dtlgetentryfromrow{\@dtl@a}{\@dtl@col}{#1}%
+% \end{macrocode}
+% Has value for row A been defined?
+% \begin{macrocode}
+ \ifx\@dtl@a\dtlnovalue
+% \end{macrocode}
+% Value for row A hasn't been defined so set to null
+% \begin{macrocode}
+ \@dtl@setnull{\@dtl@a}{\@dtl@key}%
+ \fi
+% \end{macrocode}
+% Is value for row A null? If not null end the loop.
+% \begin{macrocode}
+ \DTLifnull{\@dtl@a}{}{\@endfortrue}%
+ }%
+% \end{macrocode}
+% No non-null value found.
+% \begin{macrocode}
+ \ifx\@dtl@keya\@nnil
+ \let\@dtl@keya\@dtl@key
+ \@dtl@setnull{\@dtl@a}{\@dtl@key}%
+ \fi
+ }%
+ {}%
+% \end{macrocode}
+% Check if value for row B is null.
+% \begin{macrocode}
+ \DTLifnull{\@dtl@b}%
+ {%
+% \end{macrocode}
+% Value for row B is null, so find the first non null key in list of
+% replacement keys.
+% \begin{macrocode}
+ \@for\@dtl@keyb:=\@dtl@replacementkeys\do{%
+% \end{macrocode}
+% Get column corresponding to this key.
+% \begin{macrocode}
+ \@sdtl@getcolumnindex{\@dtl@col}{\@dtl@dbname}{\@dtl@keyb}%
+ \dtlgetentryfromrow{\@dtl@b}{\@dtl@col}{#2}%
+% \end{macrocode}
+% Has value for row B been defined?
+% \begin{macrocode}
+ \ifx\@dtl@b\dtlnovalue
+% \end{macrocode}
+% Value for row B hasn't been defined so set to null.
+% \begin{macrocode}
+ \@dtl@setnull{\@dtl@b}{\@dtl@key}%
+ \fi
+% \end{macrocode}
+% Is value for row B null? If not null end the loop.
+% \begin{macrocode}
+ \DTLifnull{\@dtl@b}{}{\@endfortrue}%
+ }%
+% \end{macrocode}
+% No non-null value found.
+% \begin{macrocode}
+ \ifx\@dtl@keyb\@nnil
+ \let\@dtl@keyb\@dtl@key
+ \@dtl@setnull{\@dtl@b}{\@dtl@key}%
+ \fi
+ }%
+ {}%
+% \end{macrocode}
+% Compare rows A and B. First store the values for row A and B
+% in token registers so that they can be passed to
+% \cs{dtl@compare@}.
+% \begin{macrocode}
+ \@dtl@toksA=\expandafter{\@dtl@a}%
+ \@dtl@toksB=\expandafter{\@dtl@b}%
+% \end{macrocode}
+% Do comparison.
+% \begin{macrocode}
+ \edef\@dtl@docompare{\noexpand\dtl@compare@
+ {\@dtl@keya}{\@dtl@keyb}%
+ {\noexpand\@dtl@toksA}{\noexpand\@dtl@toksB}}%
+ \@dtl@docompare
+% \end{macrocode}
+% Repeat if the two values are considered identical and there
+% are further sorting options.
+% \begin{macrocode}
+ \ifnum\dtl@sortresult=0\relax
+% \end{macrocode}
+% Reset switch to prevent breaking out of outer loop.
+% \begin{macrocode}
+ \@endforfalse
+ \else
+% \end{macrocode}
+% Break out of loop.
+% \begin{macrocode}
+ \@endfortrue
+ \fi
+ }%
}
% \end{macrocode}
%\end{macro}
+%
%\begin{macro}{\@dtl@getsortdirection}
% Get the direction from either \meta{key} or
% \meta{key}=\meta{direction}. Sets \cs{@dtl@sortdirection} to
% either -1 (ascending) or 1 (descending).
% \begin{macrocode}
\def\@dtl@getsortdirection#1=#2\relax{%
-\def\@dtl@key{#1}%
-\def\@dtl@sortdirection{#2}%
-\ifx\@dtl@sortdirection\@empty
- \def\@dtl@sortdirection{-1}%
-\else
- \@dtl@get@sortdirection#2%
- \ifthenelse{\equal{\@dtl@sortdirection}{ascending}}{%
- \def\@dtl@sortdirection{-1}}{%
- \ifthenelse{\equal{\@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}
+% Store key in \cs{@dtl@key}.
+% \begin{macrocode}
+ \def\@dtl@key{#1}%
+% \end{macrocode}
+% Store sort direction. This will be empty if no direction was
+% specified.
+% \begin{macrocode}
+ \def\@dtl@sortdirection{#2}%
+% \end{macrocode}
+% Check if a direction was specified.
+% \begin{macrocode}
+ \ifx\@dtl@sortdirection\@empty
+% \end{macrocode}
+% No direction specified so assume ascending.
+% \begin{macrocode}
+ \def\@dtl@sortdirection{-1}%
+ \else
+% \end{macrocode}
+% Get the sort direction from the second argument (needs terminating
+% equal sign removed) and store in \cs{@dtl@sortdirection}.
+% \begin{macrocode}
+ \@dtl@get@sortdirection#2%
+% \end{macrocode}
+% Determine the direction.
+% \changes{2.0}{2009 February 27}{modified to use \cs{ifx} instead
+% of \cs{ifthenelse}}
+% \begin{macrocode}
+ \def\@dtl@dir{ascending}%
+ \ifx\@dtl@sortdirection\@dtl@dir
+% \end{macrocode}
+% Ascending
+% \begin{macrocode}
+ \def\@dtl@sortdirection{-1}%
+ \else
+% \end{macrocode}
+% Check if descending.
+% \begin{macrocode}
+ \def\@dtl@dir{descending}%
+ \ifx\@dtl@sortdirection\@dtl@dir
+% \end{macrocode}
+% Descending
+% \begin{macrocode}
+ \def\@dtl@sortdirection{1}%
+ \else
+% \end{macrocode}
+% Direction not valid. Generate error message.
+% \begin{macrocode}
+ \PackageError{datatool}{Invalid sort direction
+ `\@dtl@sortdirection'}{The sort direction can only be
+ one of `ascending' or `descending'}%
+% \end{macrocode}
+% Assume ascending.
+% \begin{macrocode}
+ \def\@dtl@sortdirection{-1}
+ \fi
+ \fi
+ \fi
}
% \end{macrocode}
%\end{macro}
%\begin{macro}{\@dtl@get@sortdirection}
-% Get direction
+% Get direction (trims trailing = sign)
% \begin{macrocode}
\def\@dtl@get@sortdirection#1={\def\@dtl@sortdirection{#1}}
% \end{macrocode}
%\end{macro}
%
+%\begin{macro}{\@dtl@toksA}
+% \begin{macrocode}
+\newtoks\@dtl@toksA
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@dtl@toksB}
+% \begin{macrocode}
+\newtoks\@dtl@toksB
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@dtl@toks}
+% \begin{macrocode}
+\newtoks\@dtl@toks
+% \end{macrocode}
+%\end{macro}
+%
%\begin{macro}{\dtl@compare}
%\begin{definition}
-%\cs{dtl@compare}\marg{key}\marg{a}\marg{b}
+%\cs{dtl@compare}\marg{key}\marg{a toks}\marg{b toks}
%\end{definition}
-% Compares \meta{a} and \meta{b} according to \meta{key} of
-% database given by \cs{@dtl@dbname}. Sets \cs{dtl@sortresult}.
-% \cs{@dtl@comparecs} must be set to the required comparison macro.
+% Compares two values according to \meta{key} of database given by
+% \cs{@dtl@dbname}. Sets \cs{dtl@sortresult}. \cs{@dtl@comparecs}
+% must be set to the required comparison macro.
+%\changes{2.0}{2009 February 27}{no longer used}
% \begin{macrocode}
-\newtoks\@dtl@toksA\newtoks\@dtl@toksB
\newcommand{\dtl@compare}[3]{%
-\dtl@gathervalues{\@dtl@dbname}{#2}%
-\expandafter\let\expandafter\@dtl@tmp\expandafter
- =\csname @dtl@key@#1\endcsname
-\expandafter\@dtl@toksA\expandafter{\@dtl@tmp}%
-\edef\@dtl@a{\the\@dtl@toksA}%
-\dtl@gathervalues{\@dtl@dbname}{#3}%
-\expandafter\let\expandafter\@dtl@tmp\expandafter
- =\csname @dtl@key@#1\endcsname
-\expandafter\@dtl@toksB\expandafter{\@dtl@tmp}%
-\edef\@dtl@b{\the\@dtl@toksB}%
-\expandafter\@dtl@datatype\expandafter=
- \csname @dtl@idtype@\@dtl@dbname @#1\endcsname\relax
-\ifnum\@dtl@datatype=0\relax
- \edef\@dtl@tmpcmp{%
- \noexpand\@dtl@comparecs{\noexpand\dtl@sortresult}%
- {\the\@dtl@toksA}{\the\@dtl@toksB}}%
- \@dtl@tmpcmp
-\else
- \DTLifnumlt{\@dtl@a}{\@dtl@b}{\dtl@sortresult=-1\relax}{%
- \DTLifnumgt{\@dtl@a}{\@dtl@b}{\dtl@sortresult=1\relax}{%
- \dtl@sortresult=0\relax}}%
-\fi
-\ifdtlverbose
-\@onelevel@sanitize\@dtl@a
-\@onelevel@sanitize\@dtl@b
-\fi
-\dtl@message{`\@dtl@a' <=> `\@dtl@b' = \number\dtl@sortresult}%
+ \dtl@compare@{#1}{#1}{#2}{#3}%
}
% \end{macrocode}
%\end{macro}
%
%\begin{macro}{\dtl@compare@}
%\begin{definition}
-%\cs{dtl@compare@}\marg{keya}\marg{keyb}\marg{a}\marg{b}
+% \cs{dtl@compare@}\marg{keyA}\marg{keyB}\marg{A toks}\marg{B toks}
%\end{definition}
-% Compare \meta{a} and \meta{b} according to \meta{keya}
-% and \meta{keyb} of
-% database given by \cs{@dtl@dbname}. Sets \cs{dtl@sortresult}.
-% \cs{@dtl@comparecs} must be set.
+% Compare \meta{A} and \meta{B} according \meta{keyA} and
+% \meta{keyB} for database given by \cs{@dtl@dbname}. Sets
+% \cs{dtl@sortresult}.
+% \cs{@dtl@comparecs} must be set before use.
+%\changes{2.0}{2009 February 27}{updated to use new database
+% structure}
% \begin{macrocode}
\newcommand{\dtl@compare@}[4]{%
-\dtl@gathervalues{\@dtl@dbname}{#3}%
-\expandafter\let\expandafter\@dtl@tmp\expandafter
- =\csname @dtl@key@#1\endcsname
-\expandafter\@dtl@toksA\expandafter{\@dtl@tmp}%
-\edef\@dtl@a{\the\@dtl@toksA}%
-\dtl@gathervalues{\@dtl@dbname}{#4}%
-\expandafter\let\expandafter\@dtl@tmp\expandafter
- =\csname @dtl@key@#2\endcsname
-\expandafter\@dtl@toksB\expandafter{\@dtl@tmp}%
-\edef\@dtl@b{\the\@dtl@toksB}%
-\expandafter\@dtl@tmpcount\expandafter=
- \csname @dtl@idtype@\@dtl@dbname @#1\endcsname\relax
-\expandafter\@dtl@datatype\expandafter=
- \csname @dtl@idtype@\@dtl@dbname @#2\endcsname\relax
-\multiply\@dtl@datatype by \@dtl@tmpcount\relax
-\ifnum\@dtl@datatype=0\relax
- \edef\@dtl@tmpcmp{%
- \noexpand\@dtl@comparecs{\noexpand\dtl@sortresult}%
- {\the\@dtl@toksA}{\the\@dtl@toksB}}%
- \@dtl@tmpcmp
-\else
- \DTLifnumlt{\@dtl@a}{\@dtl@b}{\dtl@sortresult=-1\relax}{%
- \DTLifnumgt{\@dtl@a}{\@dtl@b}{\dtl@sortresult=1\relax}{%
- \dtl@sortresult=0\relax}}%
-\fi
-\ifdtlverbose
-\@onelevel@sanitize\@dtl@a
-\@onelevel@sanitize\@dtl@b
-\fi
-\dtl@message{`\@dtl@a' <=> `\@dtl@b' = \number\dtl@sortresult}%
+% \end{macrocode}
+% Get the data type for first key and store in \cs{@dtl@typeA}.
+% \begin{macrocode}
+ \DTLgetdatatype{\@dtl@typeA}{\@dtl@dbname}{#1}%
+% \end{macrocode}
+% Is it unset? If so, assume string
+% \begin{macrocode}
+ \ifx\@dtl@typeA\DTLunsettype
+ \let\@dtl@typeA\DTLstringtype
+ \fi
+% \end{macrocode}
+% Get the data type for the second key and store in \cs{@dtl@typeB}
+% \begin{macrocode}
+ \DTLgetdatatype{\@dtl@typeB}{\@dtl@dbname}{#2}%
+% \end{macrocode}
+% Is it unset? If so, assume string
+% \begin{macrocode}
+ \ifx\@dtl@typeB\DTLunsettype
+ \let\@dtl@typeB\DTLstringtype
+ \fi
+% \end{macrocode}
+% Multiply the two values together
+% \begin{macrocode}
+ \@dtl@tmpcount=\@dtl@typeA\relax
+ \multiply\@dtl@tmpcount by \@dtl@typeB\relax
+% \end{macrocode}
+% If either type is 0 (a string) then the product will also be
+% 0 (string) otherwise it will be one of the numerical types.
+% \begin{macrocode}
+ \ifnum\@dtl@tmpcount=0\relax
+% \end{macrocode}
+% A string, so use comparison function
+% \begin{macrocode}
+ \edef\@dtl@tmpcmp{%
+ \noexpand\@dtl@comparecs{\noexpand\dtl@sortresult}%
+ {\the#3}{\the#4}%
+ }%
+ \@dtl@tmpcmp
+ \ifdtlverbose
+ \edef\@dtl@a{\the#3}%
+ \edef\@dtl@b{\the#4}%
+ \fi
+ \else
+% \end{macrocode}
+% Store the first value
+% \begin{macrocode}
+ \edef\@dtl@a{\the#3}%
+% \end{macrocode}
+% Store the second value
+% \begin{macrocode}
+ \edef\@dtl@b{\the#4}%
+% \end{macrocode}
+% Compare
+% \begin{macrocode}
+ \DTLifnumlt{\@dtl@a}{\@dtl@b}%
+ {%
+% \end{macrocode}
+% $A < B$
+% \begin{macrocode}
+ \dtl@sortresult=-1\relax
+ }%
+ {%
+ \DTLifnumgt{\@dtl@a}{\@dtl@b}%
+ {%
+% \end{macrocode}
+% $A > B$
+% \begin{macrocode}
+ \dtl@sortresult=1\relax
+ }%
+ {%
+% \end{macrocode}
+% $A = B$
+% \begin{macrocode}
+ \dtl@sortresult=0\relax
+ }%
+ }%
+ \fi
+% \end{macrocode}
+% Write comparison result to terminal/log if verbose mode.
+% \begin{macrocode}
+ \ifdtlverbose
+ \@onelevel@sanitize\@dtl@a
+ \@onelevel@sanitize\@dtl@b
+ \dtl@message{`\@dtl@a' <=> `\@dtl@b' = \number\dtl@sortresult}%
+ \fi
}
% \end{macrocode}
%\end{macro}
@@ -10867,7 +15144,6 @@ deeply}{}%
% Inserts \meta{element} into the sorted list \meta{sorted-list}
% according to the criteria given by \meta{criteria cmd} (see above.)
% \begin{macrocode}
-\newtoks\@dtl@toks
\newcommand{\dtl@insertinto}[3]{%
\def\@dtl@newsortedlist{}%
\@dtl@insertdonefalse
@@ -10926,6 +15202,42 @@ deeply}{}%
% \end{macrocode}
%\end{macro}
%
+% \subsection{General Token Utilities}
+%\begin{macro}{\toks@gput@right@cx}
+%\begin{definition}
+%\cs{toks@gput@right@cx}\marg{toks name}\marg{stuff}
+%\end{definition}
+% Globally appends stuff to token register \cs{}\meta{toks name}
+% \begin{macrocode}
+\newcommand{\toks@gput@right@cx}[2]{%
+ \def\@toks@name{#1}%
+ \edef\@dtl@stuff{#2}%
+ \global\csname\@toks@name\endcsname\expandafter
+ \expandafter\expandafter{\expandafter\the
+ \csname\expandafter\@toks@name\expandafter\endcsname\@dtl@stuff}%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\toks@gconcat@middle@cx}
+%\begin{definition}
+%\cs{toks@gconcat@middle@cx}\marg{toks name}\marg{before toks}\marg{stuff}\marg{after toks}
+%\end{definition}
+% Globally sets token register \cs{}\meta{toks name} to
+% the contents of \meta{before toks} concatenated with
+% \meta{stuff} (expanded) and the contents of \meta{after toks}
+% \begin{macrocode}
+\newcommand{\toks@gconcat@middle@cx}[4]{%
+ \def\@toks@name{#1}%
+ \edef\@dtl@stuff{#3}%
+ \global\csname\@toks@name\endcsname\expandafter\expandafter
+ \expandafter\expandafter\expandafter
+ \expandafter\expandafter{\expandafter\expandafter\expandafter
+ \the\expandafter\expandafter\expandafter#2%
+ \expandafter\@dtl@stuff\the#4}%
+}
+% \end{macrocode}
+%\end{macro}
+%
% \subsection{Floating Point Arithmetic}
% The commands defined in this section all use the equivalent
% commands provided by the \sty{fp} package, but first convert
@@ -11546,8 +15858,8 @@ deeply}{}%
% \end{macrocode}
%\end{macro}
%
-%\begin{macro}{\DTLinitials}
%\subsection{String Macros}
+%\begin{macro}{\DTLinitials}
%\begin{definition}
%\cs{DTLinitials}\marg{string}
%\end{definition}
@@ -11884,62 +16196,101 @@ deeply}{}%
%\end{definition}
% Save a database as an ASCII data file using the separator
% and delimiter given by \cs{@dtl@separator} and \cs{@dtl@delimiter}.
+%\changes{2.0}{2009 February 27}{updated to use new database structure}
% \begin{macrocode}
\newcommand*{\DTLsavedb}[2]{%
-\DTLifdbexists{#1}{%
-\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}{}%
-}}
+ \DTLifdbexists{#1}%
+ {%
+% \end{macrocode}
+% Open output file
+% \begin{macrocode}
+ \openout\@dtl@write
+% \end{macrocode}
+% Initialise header row
+% \begin{macrocode}
+ \def\@dtl@header{}%
+% \end{macrocode}
+% Construct the header row
+% \begin{macrocode}
+ \dtlforeachkey(\@dtl@key,\@dtl@col,\@dtl@type,\@dtl@head)%
+ \in{#1}\do
+ {%
+ \IfSubStringInString{\@dtl@separator}{\@dtl@key}%
+ {%
+ \ifx\@dtl@header\@empty
+ \protected@edef\@dtl@header{%
+ \@dtl@delimiter\@dtl@key\@dtl@delimiter}%
+ \else
+ \toks@=\expandafter{\@dtl@header}%
+ \protected@edef\@dtl@header{%
+ \the\toks@\@dtl@separator
+ \@dtl@delimiter\@dtl@key\@dtl@delimiter}%
+ \fi
+ }%
+ {%
+ \ifx\@dtl@header\@empty
+ \protected@edef\@dtl@header{\@dtl@key}%
+ \else
+ \toks@=\expandafter{\@dtl@header}%
+ \protected@edef\@dtl@header{\the\toks@
+ \@dtl@separator\@dtl@key}%
+ \fi
+ }%
+ }%
+% \end{macrocode}
+% Print header
+% \begin{macrocode}
+ \protected@write\@dtl@write{}{\@dtl@header}%
+% \end{macrocode}
+% Iterate through each row
+% \begin{macrocode}
+ \@sDTLforeach{#1}{}%
+ {%
+% \end{macrocode}
+% Initialise row
+% \begin{macrocode}
+ \def\@dtl@row{}%
+% \end{macrocode}
+% Iterate through each key
+% \begin{macrocode}
+ \DTLforeachkeyinrow{\@dtl@val}%
+ {%
+ \IfSubStringInString{\@dtl@separator}{\@dtl@val}%
+ {%
+ \ifx\@dtl@row\@empty
+ \protected@edef\@dtl@row{%
+ \@dtl@delimiter\@dtl@val\@dtl@delimiter}%
+ \else
+ \toks@=\expandafter{\@dtl@row}%
+ \protected@edef\@dtl@row{\the\toks@\@dtl@separator
+ \@dtl@delimiter\@dtl@val\@dtl@delimiter}%
+ \fi
+ }%
+ {%
+ \ifx\@dtl@row\@empty
+ \protected@edef\@dtl@row{\@dtl@val}%
+ \else
+ \toks@=\expandafter{\@dtl@row}%
+ \protected@edef\@dtl@row{\the\toks@\@dtl@separator
+ \@dtl@val}%
+ \fi
+ }%
+% \end{macrocode}
+% Print row
+% \begin{macrocode}
+ \protected@write\@dtl@write{}{\@dtl@row}%
+ }%
+ }%
+% \end{macrocode}
+% Close output file
+% \begin{macrocode}
+ \closeout\@dtl@write
+ }%
+ {%
+ \PackageError{datatool}{Can't save database `#1': no such
+ database}{}%
+ }%
+}
% \end{macrocode}
%\end{macro}
%
@@ -11948,35 +16299,73 @@ deeply}{}%
% \cs{DTLsavetexdb}\marg{db name}\marg{filename}
%\end{definition}
% Save a database as a \LaTeX\ file.
+%\changes{2.0}{2009 February 27}{updated to use new database structure}
% \begin{macrocode}
\newcommand*{\DTLsavetexdb}[2]{%
-\DTLifdbexists{#1}{%
-\def\@dtl@dbname{#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{%
-\expandafter\DTLifnull\csname @dtl@key@\@dtl@key\endcsname
-{}{%
-\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}{}%
-}}
+ \DTLifdbexists{#1}%
+ {%
+% \end{macrocode}
+% Open output file
+% \begin{macrocode}
+ \openout\@dtl@write=#2\relax
+% \end{macrocode}
+% Write new data base definition
+% \begin{macrocode}
+ \protected@write\@dtl@write{}{\string\DTLnewdb{#1}}%
+% \end{macrocode}
+% Iterate through each row
+% \begin{macrocode}
+ \@sDTLforeach{#1}{}%
+ {%
+% \end{macrocode}
+% Start new row
+% \begin{macrocode}
+ \protected@write\@dtl@write{}{\string\DTLnewrow*{#1}}%
+% \end{macrocode}
+% Iterate through each column
+% \begin{macrocode}
+ \DTLforeachkeyinrow{\@dtl@val}%
+ {%
+% \end{macrocode}
+% Is this entry null?
+% \begin{macrocode}
+ \DTLifnull{\@dtl@val}%
+ {\def\@dtl@val{}}%
+ {}%
+% \end{macrocode}
+% Add entry
+% \begin{macrocode}
+ \protected@write\@dtl@write{}{%
+ \string\DTLnewdbentry*{#1}{\dtlkey}{\@dtl@val}}%
+ }%
+ }%
+% \end{macrocode}
+% Save the column headers.
+% \begin{macrocode}
+ \dtlforeachkey(\@dtl@k,\@dtl@c,\@dtl@t,\@dtl@h)\in{#1}\do
+ {%
+ \@onelevel@sanitize\@dtl@h
+ \protected@write\@dtl@write{}{%
+ \string\DTLsetheader*{#1}{\@dtl@k}{\@dtl@h}}%
+ }%
+% \end{macrocode}
+% Close output file
+% \begin{macrocode}
+ \closeout\@dtl@write
+ }%
+ {%
+ \PackageError{datatool}{Can't save database `#1': no such
+ database}{}%
+ }%
+}
% \end{macrocode}
%\end{macro}
%
%\subsection{Loading a database from an external file}
%
+% \begin{macrocode}
+\newcommand{\@longempty}{}
+% \end{macrocode}
%\begin{macro}{\@dtl@read}
% \begin{macrocode}
\newread\@dtl@read
@@ -11988,84 +16377,426 @@ deeply}{}%
\newcount\dtl@entrycr
% \end{macrocode}
%\end{macro}
+%
+%\begin{macro}{\ifdtlnoheader}
+% The "noheader" option indicates that the file doesn't have a
+% header row.
+% \begin{macrocode}
+\define@boolkey{loaddb}[dtl]{noheader}[true]{}
+% \end{macrocode}
+%\end{macro}
+% The "keys" option specifies the list of keys in the same order
+% as the columns in the data file.
+% Each key is stored in \cs{@dtl@inky@}\meta{n} where \meta{n} is the
+% roman numeral representation of the current column.
+% \begin{macrocode}
+\define@key{loaddb}{keys}{%
+ \dtl@entrycr=0\relax
+ \@for\@dtl@key:=#1\do
+ {%
+ \advance\dtl@entrycr by 1\relax
+ \expandafter
+ \edef\csname @dtl@inky@\romannumeral\dtl@entrycr\endcsname{%
+ \@dtl@key}%
+ }%
+}
+% \end{macrocode}
+% The "headers" option specifies the list of headers in the
+% same order as the columns in the data file.
+% \begin{macrocode}
+\define@key{loaddb}{headers}{%
+ \dtl@entrycr=0\relax
+ \@for\@dtl@head:=#1\do
+ {%
+ \advance\dtl@entrycr by 1\relax
+ \toks@=\expandafter{\@dtl@head}%
+ \expandafter
+ \edef\csname @dtl@inhd@\romannumeral\dtl@entrycr\endcsname{%
+ \the\toks@}%
+ }%
+}
+% \end{macrocode}
+%
+%\begin{macro}{\dtldefaultkey}
+% Default key to use if none specified (column index will be
+% appended).
+% \begin{macrocode}
+\newcommand*{\dtldefaultkey}{Column}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@readline}
+%\begin{definition}
+%\cs{@dtl@readline}\marg{file reg}\marg{cs}
+%\end{definition}
+% Reads line from \meta{file reg}, trims end of line character
+% and stores in \meta{cs}.
+% \begin{macrocode}
+\newcommand*{\@dtl@readline}[2]{%
+% Read a line from "#1" and store in "#2"
+% \begin{macrocode}
+ \read#1 to #2%
+% \end{macrocode}
+% Trim the end of line character
+% \begin{macrocode}
+ \dtl@trim#2%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@readrawline}
+%\begin{definition}
+%\cs{@dtl@readrawline}\marg{file register}\marg{cs}
+%\end{definition}
+% Reads line from \meta{file register}, trims end of line character,
+% applies mappings and stores in \meta{cs}.
+% \begin{macrocode}
+\newcommand*{\@dtl@readrawline}[2]{%
+% Read a line from "#1" and store in "#2"
+% \begin{macrocode}
+ \@dtl@rawread#1 to #2%
+% \end{macrocode}
+% Trim the end of line character
+% \begin{macrocode}
+ \dtl@trim#2%
+% \end{macrocode}
+% Apply mappings
+% \begin{macrocode}
+ \dtl@domappings\@dtl@line
+}
+% \end{macrocode}
+%\end{macro}
+
%\begin{macro}{\DTLloaddb}
%\begin{definition}
-% \cs{DTLloaddb}\marg{db name}\marg{filename}
+% \cs{DTLloaddb}\oarg{options}\marg{db name}\marg{filename}
%\end{definition}
-% Creates a new database called \meta{db name}, and load the data in
-% \meta{filename} into it. The separator and delimiter used in
+% Creates a new database called \meta{db name}, and loads the data
+% in \meta{filename} into it. The separator and delimiter used in
% the file must match \cs{@dtl@separator} and \cs{@dtl@delimiter}.
+% The optional argument is a comma-separated list.
+%\changes{2.0}{2009 February 27}{removed checks to see if the
+% database exists when adding to it}
+%\changes{2.0}{2009 February 27}{added optional argument}
+% \begin{macrocode}
+\newcommand*{\DTLloaddb}{%
+ \let\@dtl@doreadline\@dtl@readline
+ \@dtlloaddb
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtlloaddb}
+% Loads database using \cs{@dtl@doreadline} to read and trim
+% line from file. (\cs{@dtl@doreadline} must be set before use.)
+% \begin{macrocode}
+\newcommand*{\@dtlloaddb}[3][]{%
+% \end{macrocode}
+% Check if file exists
+% \begin{macrocode}
+ \IfFileExists{#3}{%
+% \end{macrocode}
+% File exists. Locally change catcode of double quote character in
+% case it has been made active.
+% \begin{macrocode}
+ \begingroup
+ \catcode`\"12\relax
+% \end{macrocode}
+% Initialise default options
+% \begin{macrocode}
+ \dtlnoheaderfalse
+% \end{macrocode}
+% Get the options
+% \begin{macrocode}
+ \setkeys{loaddb}{#1}%
+% \end{macrocode}
+% Open the file for reading.
+% \begin{macrocode}
+ \openin\@dtl@read=#3%
+ \dtl@message{Reading `#3'}%
+% \end{macrocode}
+% Create the new database.
+% \begin{macrocode}
+ \DTLnewdb{#2}%
+% \end{macrocode}
+% Check if the file is empty.
% \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
+% \end{macrocode}
+% File is empty, so just issue a warning.
+% \begin{macrocode}
+ \PackageWarning{datatool}{File `#3' has no data}%
\else
- \read\@dtl@read to \@dtl@line
- \dtl@trim\@dtl@line
- \if\@dtl@line\par
- \@dtl@conditiontrue
+% \end{macrocode}
+% Does the file have a header row?
+% \begin{macrocode}
+ \ifdtlnoheader
+ \else
+% \end{macrocode}
+% Remove initial blank rows
+% \begin{macrocode}
+ \loop
+% \end{macrocode}
+% Set repeat condition to false
+% \begin{macrocode}
+ \@dtl@conditionfalse
+% \end{macrocode}
+% Do nothing if reached the end of file
+% \begin{macrocode}
+ \ifeof\@dtl@read
+ \else
+% \end{macrocode}
+% Read a line from the file and store in \cs{@dtl@line}
+% \begin{macrocode}
+ \@dtl@doreadline\@dtl@read\@dtl@line
+% \end{macrocode}
+% If this is a blank row, set repeat condition to true
+% \begin{macrocode}
+ \ifx\@dtl@line\@longempty
+ \@dtl@conditiontrue
+ \fi
+ \fi
+% \end{macrocode}
+% Repeat loop if necessary
+% \begin{macrocode}
+ \if@dtl@condition
+ \repeat
+% \end{macrocode}
+% Parse the header row. Store the row as
+% \meta{sep}\meta{row}\meta{sep} in \cs{@dtl@lin@}.
+% \begin{macrocode}
+ \protected@edef\@dtl@lin@{%
+ \@dtl@separator\@dtl@line\@dtl@separator}%
+% \end{macrocode}
+% Keep track of columns:
+% \begin{macrocode}
+ \dtl@entrycr=0\relax
+% \end{macrocode}
+% Keep lopping off elements until the end of the row is reached.
+% (That is, until \cs{@dtl@lin@} is \cs{@dtl@separator}.)
+%\changes{2.0}{2009 February 27}{changed \cs{whiledo} to
+% \cs{loop} to improve efficiency}%
+% \begin{macrocode}
+ \loop
+% \end{macrocode}
+% Lopoff the first element and store in \cs{@dtl@key}
+% \begin{macrocode}
+ \expandafter\@dtl@lopoff\@dtl@lin@\to\@dtl@lin@\@dtl@key
+% \end{macrocode}
+% Increment column count.
+% \begin{macrocode}
+ \advance\dtl@entrycr by 1\relax
+% \end{macrocode}
+% Store key in \cs{@dtl@toks}
+% \begin{macrocode}
+ \expandafter\@dtl@toks\expandafter{\@dtl@key}%
+% \end{macrocode}
+% Store the key in \cs{@dtl@inky@}\meta{n} where \meta{n} is the
+% roman numeral representation of the current column, unless
+% already defined.
+% \begin{macrocode}
+ \@ifundefined{@dtl@inky@\romannumeral\dtl@entrycr}%
+ {%
+ \expandafter
+ \edef\csname @dtl@inky@\romannumeral
+ \dtl@entrycr\endcsname{\the\@dtl@toks}%
+ }%
+ {%
+% \end{macrocode}
+% If key has been specified in "#1", then use the header found in the
+% file, unless a header has also been specified in "#1"
+% \begin{macrocode}
+ \@ifundefined{@dtl@inhd@\romannumeral\dtl@entrycr}%
+ {%
+ \expandafter
+ \edef\csname @dtl@inhd@\romannumeral
+ \dtl@entrycr\endcsname{\the\@dtl@toks}%
+ }%
+ {}%
+ }%
+% \end{macrocode}
+% Check if the loop should be repeated
+% \begin{macrocode}
+ \ifx\@dtl@lin@\@dtl@separator
+ \@dtl@conditionfalse
+ \else
+ \@dtl@conditiontrue
+ \fi
+% \end{macrocode}
+% Repeat loop if necessary.
+% \begin{macrocode}
+ \if@dtl@condition
+ \repeat
+% \end{macrocode}
+% End if no header
+% \begin{macrocode}
\fi
+% \end{macrocode}
+% Now for the rest of the data. If the end of file has been
+% reached, then only the header row is available or file is empty.
+% \begin{macrocode}
+ \ifeof\@dtl@read
+ \ifdtlnoheader
+ \PackageWarning{datatool}{No data in `#3'}%
+ \else
+ \PackageWarning{datatool}{Only header row found in `#3'}%
+ \fi
+ \else
+% \end{macrocode}
+% Iterate through the rest of the file. First set the repeat
+% condition to true:
+% \begin{macrocode}
+ \@dtl@conditiontrue
+ \loop
+% \end{macrocode}
+% Read in a line
+% \begin{macrocode}
+ \@dtl@doreadline\@dtl@read\@dtl@line
+% \end{macrocode}
+% Check if the line is empty.
+%\changes{2.0}{2009 February 27}{changed \cs{ifthenelse} to
+%\cs{ifx} to improve efficiency}
+% \begin{macrocode}
+ \ifx\@dtl@line\@longempty
+% \end{macrocode}
+% Do nothing if the row is empty.
+% \begin{macrocode}
+ \else
+% \end{macrocode}
+% Add a new row to the database. (Don't need to check if the
+% database exists, since it's just been created.)
+% \begin{macrocode}
+ \@sDTLnewrow{#2}%
+% \end{macrocode}
+% Store the row as \meta{sep}\meta{row}\meta{sep} to make the
+% lopping off easier
+% \begin{macrocode}
+ \expandafter\@dtl@toks\expandafter{\@dtl@line}%
+ \edef\@dtl@lin@{\@dtl@separator\the\@dtl@toks
+ \@dtl@separator}%
+% \end{macrocode}
+% Reset the column counter.
+% \begin{macrocode}
+ \dtl@entrycr=0\relax
+% \end{macrocode}
+%\changes{2.0}{2009 February 27}{changed \cs{whiledo} to \cs{loop}
+% to improve efficiency}
+% Iterate through each element in the row. Needs to be grouped
+% since we're already inside a loop.
+% \begin{macrocode}
+ {%
+% \end{macrocode}
+% Initialise repeat condition
+% \begin{macrocode}
+ \@dtl@conditiontrue
+% \end{macrocode}
+% Iterate through the list
+% \begin{macrocode}
+ \loop
+% \end{macrocode}
+% lop off first element and store in \cs{@dtl@thisentry}
+% \begin{macrocode}
+ \expandafter\@dtl@lopoff\@dtl@lin@\to
+ \@dtl@lin@\@dtl@thisentry
+% \end{macrocode}
+% Increment the column count.
+% \begin{macrocode}
+ \advance\dtl@entrycr by 1\relax
+% \end{macrocode}
+% Get the key for this column and store in \cs{@dtl@thiskey}.
+% Use default value if not defined.
+% \begin{macrocode}
+ \@ifundefined{@dtl@inky@\romannumeral\dtl@entrycr}%
+ {%
+ \edef\@dtl@thiskey{\dtldefaultkey
+ \number\dtl@entrycr}%
+ \expandafter\let
+ \csname @dtl@inky@\romannumeral
+ \dtl@entrycr\endcsname\@dtl@thiskey
+ }%
+ {%
+ \edef\@dtl@thiskey{%
+ \csname @dtl@inky@\romannumeral
+ \dtl@entrycr\endcsname}%
+ }%
+% \end{macrocode}
+% Store this entry in \cs{@dtl@toks}
+% \begin{macrocode}
+ \expandafter\@dtl@toks\expandafter{\@dtl@thisentry}%
+% \end{macrocode}
+% Add this entry to the database
+% \begin{macrocode}
+ \edef\@do@dtlnewentry{\noexpand\@sDTLnewdbentry
+ {#2}{\@dtl@thiskey}{\the\@dtl@toks}}%
+ \@do@dtlnewentry
+% \end{macrocode}
+% Check if loop should be terminated
+% \begin{macrocode}
+ \ifx\@dtl@lin@\@dtl@separator
+ \@dtl@conditionfalse
+ \fi
+% \end{macrocode}
+% Repeat loop if necessary
+% \begin{macrocode}
+ \if@dtl@condition
+ \repeat
+ }%
+% \end{macrocode}
+% End of parsing this row
+% \begin{macrocode}
+ \fi
+% \end{macrocode}
+% If the end of file has been reached, set the repeat condition
+% to false.
+% \begin{macrocode}
+ \ifeof\@dtl@read \@dtl@conditionfalse\fi
+% \end{macrocode}
+% Repeat if necessary
+% \begin{macrocode}
+ \if@dtl@condition
+ \repeat
+ \fi
+% \end{macrocode}
+% End of first \cs{ifeof}
+% \begin{macrocode}
\fi
- \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}%
- \expandafter\@dtl@toks\expandafter{\@dtl@thisentry}%
- \edef\@do@dtlnewentry{\noexpand\DTLnewdbentry
- {#1}{\@dtl@thiskey}{\the\@dtl@toks}}%
- \@do@dtlnewentry
- }%
- }%
- \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}
+% Close the input file
+% \begin{macrocode}
+ \closein\@dtl@read
+% \end{macrocode}
+% Set the headers if required
+% \begin{macrocode}
+ \edef\@dtl@maxcols{\expandafter
+ \number\csname dtlcols@#2\endcsname}%
+ \dtlgforint\dtl@entrycr=1\to\@dtl@maxcols\step1\do
+ {%
+ \@ifundefined{@dtl@inhd@\romannumeral\dtl@entrycr}%
+ {}%
+ {%
+ \expandafter\let\expandafter\@dtl@head
+ \csname @dtl@inhd@\romannumeral\dtl@entrycr\endcsname
+ \@dtl@toks=\expandafter{\@dtl@head}%
+ \edef\@dtl@dosetheader{\noexpand\@dtl@setheaderforindex
+ {#2}{\number\dtl@entrycr}{\the\@dtl@toks}}%
+ \@dtl@dosetheader
+ }%
+ }%
+% \end{macrocode}
+% End current scope
+% \begin{macrocode}
+ \endgroup
+% \end{macrocode}
+% End true part of if file exists
+% \begin{macrocode}
+ }{%
+% \end{macrocode}
+% Requested file not found on TeX's path
+% \begin{macrocode}
+ \PackageError{datatool}{Can't load database `#2' (file `#3'
+ doesn't exist)}{}%
+ }%
+}
% \end{macrocode}
%\end{macro}
%
@@ -12110,75 +16841,10 @@ doesn't exist)}{}%
% "~" $\to$ "\textasciitilde", "_" $\to$ "\_"
% and "^" $\to$ "\textasciicircum".)
% \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}%
- \expandafter\@dtl@toks\expandafter{\@dtl@thisentry}%
- \edef\@do@dtlnewentry{\noexpand\DTLnewdbentry
- {#1}{\@dtl@thiskey}{\the\@dtl@toks}}%
- \@do@dtlnewentry
- }%
- }%
- \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)}{}%
-}}
+\newcommand*\DTLloadrawdb{%
+ \let\@dtl@doreadline\@dtl@readrawline
+ \@dtlloaddb
+}
% \end{macrocode}
%\end{macro}
%
@@ -12380,6 +17046,31 @@ doesn't exist)}{}%
% \end{macrocode}
%\end{macro}
%
+%\begin{macro}{\DTLifinlist}
+%\cs{DTLifinlist}\marg{element}\marg{list}\marg{true part}\marg{false part}
+% If \meta{element} is contained in the comma-separated list given
+% by \meta{list}, then do \meta{true part} otherwise do false
+% part. (Does a one level expansion on \meta{list})
+% \begin{macrocode}
+\newcommand*{\DTLifinlist}[4]{%
+ \def\@dtl@doifinlist##1,#1,##2\end@dtl@doifinlist{%
+ \def\@before{##1}%
+ \def\@after{##2}%
+ }%
+ \expandafter\@dtl@doifinlist\expandafter,#2,#1,\@nil
+ \end@dtl@doifinlist
+ \ifx\@after\@nnil
+% not found
+ #4%
+ \else
+% found
+ #3%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%
%\subsection{Currencies}
%\begin{macro}{\@dtl@currencies}
% \cs{@dtl@currencies} stores all known currencies.
@@ -12495,9 +17186,10 @@ doesn't exist)}{}%
%\cs{dtlshowdb}\marg{db name}
%\end{definition}
% Shows the database.
+%\changes{2.0}{2009 February 27}{updated to use new database structure}
% \begin{macrocode}
\newcommand*{\dtlshowdb}[1]{%
-\expandafter\show\csname dtldb@#1\endcsname}
+\expandafter\showthe\csname dtldb@#1\endcsname}
% \end{macrocode}
%\end{macro}
%
@@ -12506,9 +17198,10 @@ doesn't exist)}{}%
%\cs{dtlshowdbkeys}\marg{db name}
%\end{definition}
% Shows the key list for the named database.
+%\changes{2.0}{2009 February 27}{updated to use new database structure}
% \begin{macrocode}
\newcommand*{\dtlshowdbkeys}[1]{%
-\expandafter\show\csname dtlkeys@#1\endcsname}
+\expandafter\showthe\csname dtlkeys@#1\endcsname}
% \end{macrocode}
%\end{macro}
%
@@ -12518,9 +17211,11 @@ doesn't exist)}{}%
%\end{definition}
% Show the data type for given key in the named database.
% This should be an integer from 0 to 3.
+%\changes{2.0}{2009 February 27}{updated to use new database structure}
% \begin{macrocode}
\newcommand*{\dtlshowtype}[2]{%
-\expandafter\show\csname @dtl@idtype@#1@#2\endcsname}
+ \DTLgetdatatype{\@dtl@type}{#1}{#2}\show\@dtl@type
+}
% \end{macrocode}
%\end{macro}
%\iffalse
@@ -12537,7 +17232,7 @@ doesn't exist)}{}%
% Declare package:
% \begin{macrocode}
\NeedsTeXFormat{LaTeX2e}
-\ProvidesPackage{datapie}[2007/08/17 v1.01 (NLCT)]
+\ProvidesPackage{datapie}[2007/02/27 v2.0 (NLCT)]
% \end{macrocode}
% Require \sty{xkeyval} package
% \begin{macrocode}
@@ -13213,7 +17908,7 @@ Try #2-#1 instead of #1-#2}%
% Declare package:
% \begin{macrocode}
\NeedsTeXFormat{LaTeX2e}
-\ProvidesPackage{dataplot}[2007/08/17 v1.01 (NLCT)]
+\ProvidesPackage{dataplot}[2009/02/27 v2.0 (NLCT)]
% \end{macrocode}
% Required packages
% \begin{macrocode}
@@ -13252,15 +17947,16 @@ Try #2-#1 instead of #1-#2}%
%\cs{DTLplot}.
% \begin{macrocode}
\newcommand*{\DTLplotmarks}{%
-\pgfuseplotmark{o},%
-\pgfuseplotmark{x},%
-\pgfuseplotmark{+},%
-\pgfuseplotmark{square},%
-\pgfuseplotmark{triangle},%
-\pgfuseplotmark{diamond},%
-\pgfuseplotmark{pentagon},%
-\pgfuseplotmark{asterisk},%
-\pgfuseplotmark{star}}
+ \pgfuseplotmark{o},%
+ \pgfuseplotmark{x},%
+ \pgfuseplotmark{+},%
+ \pgfuseplotmark{square},%
+ \pgfuseplotmark{triangle},%
+ \pgfuseplotmark{diamond},%
+ \pgfuseplotmark{pentagon},%
+ \pgfuseplotmark{asterisk},%
+ \pgfuseplotmark{star}%
+}
% \end{macrocode}
%\end{macro}
%
@@ -13268,28 +17964,29 @@ Try #2-#1 instead of #1-#2}%
%\cs{DTLplotmarkcolors} contains a list of the plot mark colours.
% \begin{macrocode}
\newcommand*{\DTLplotmarkcolors}{%
-red,%
-green,%
-blue,%
-yellow,%
-magenta,%
-cyan,%
-orange,%
-black,%
-gray}
+ red,%
+ green,%
+ blue,%
+ yellow,%
+ magenta,%
+ cyan,%
+ orange,%
+ black,%
+ gray}
% \end{macrocode}
%\end{macro}
%\begin{macro}{\DTLplotlines}
%\cs{DTLplotlines} contains a list of dash patterns used by
%\cs{DLTplot}.
+%\changes{1.03}{2009 January 27}{fixed error in solid line setting}
% \begin{macrocode}
\newcommand*{\DTLplotlines}{%
-\pgfsetdash{}{{0pt}},% solid line
-\pgfsetdash{{10pt}{5pt}}{0pt},%
-\pgfsetdash{{5pt}{5pt}}{0pt},%
-\pgfsetdash{{1pt}{5pt}}{0pt},%
-\pgfsetdash{{5pt}{5pt}{1pt}{5pt}}{0pt},%
-\pgfsetdash{{1pt}{3pt}}{0pt},%
+ \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}
@@ -13297,15 +17994,15 @@ gray}
%\cs{DTLplotlinecolors} contains a list of the plot line colours.
% \begin{macrocode}
\newcommand*{\DTLplotlinecolors}{%
-red,%
-green,%
-blue,%
-yellow,%
-magenta,%
-cyan,%
-orange,%
-black,%
-gray}
+ red,%
+ green,%
+ blue,%
+ yellow,%
+ magenta,%
+ cyan,%
+ orange,%
+ black,%
+ gray}
% \end{macrocode}
%\end{macro}
%
@@ -14635,7 +19332,7 @@ east,southeast,south,southwest,west,northwest}[northeast]{%
% Declare package:
% \begin{macrocode}
\NeedsTeXFormat{LaTeX2e}
-\ProvidesPackage{databar}[2007/08/17 v1.01 (NLCT)]
+\ProvidesPackage{databar}[2009/02/27 v2.0 (NLCT)]
% \end{macrocode}
% Require \sty{xkeyval} package
% \begin{macrocode}
@@ -14924,6 +19621,16 @@ east,southeast,south,southwest,west,northwest}[northeast]{%
\DTLsetbarcolor{8}{black!85}
\fi
% \end{macrocode}
+%\begin{macro}{\DTLeverybarhook}
+% Code to apply at every bar. The start point of the bar
+% can be accessed via \cs{DTLstartpt}, the mid point of the bar
+% can be accessed via \cs{DTLmidpt} and the end point of the
+% bar can be accessed via \cs{DTLendpt}
+%\changes{2.0}{2009 February 27}{new}%
+% \begin{macrocode}
+\newcommand*{\DTLeverybarhook}{}
+% \end{macrocode}
+%\end{macro}
%
% Define keys for \cs{DTLbarchart} optional argument.
% Set the maximum value of the $y$ axis.
@@ -15061,7 +19768,8 @@ east,southeast,south,southwest,west,northwest}[northeast]{%
uppermultibarlabels,groupgap}%
\setkeys{databar}{#2}%
\ifx\DTLbarvariable\relax
- \PackageError{databar}{\string\DTLbarchart\space missing variable}{}%
+ \PackageError{databar}{\string\DTLbarchart\space missing
+ variable}{You haven't use the "variable" key}%
\else
% \end{macrocode}
% Compute the maximum bar height, unless \cs{DTLbarmax} has been
@@ -15253,6 +19961,10 @@ uppermultibarlabels,groupgap}%
{\noexpand\pgfpoint{0pt}{-\noexpand\DTLbarlabeloffset}}},
\DTLbarXlabelalign
}%
+% \end{macrocode}
+% Set \cs{DTLstartpt} to the starting point.
+% \begin{macrocode}
+ \edef\DTLstartpt{\noexpand\pgfpointxy{\@dtl@start.5}{0}}%
\else
\edef\dtl@textopt{%
at={\noexpand\pgfpointadd
@@ -15260,6 +19972,10 @@ uppermultibarlabels,groupgap}%
{\noexpand\pgfpoint{-\noexpand\DTLbarlabeloffset}{0pt}}},
\DTLbarXlabelalign
}%
+% \end{macrocode}
+% Set \cs{DTLstartpt} to the starting point.
+% \begin{macrocode}
+ \edef\DTLstartpt{\noexpand\pgfpointxy{0}{\@dtl@start.5}}%
\fi
\expandafter\pgftext\expandafter[\dtl@textopt]{%
\DTLdisplaylowerbarlabel{\dtl@barlabel}}
@@ -15267,6 +19983,9 @@ uppermultibarlabels,groupgap}%
% Draw upper $x$ labels
% \begin{macrocode}
\ifDTLverticalbars
+% \end{macrocode}
+% Vertical bars
+% \begin{macrocode}
\expandafter\DTLifnumlt\expandafter{\DTLbarvariable}{0}
{
\edef\dtl@textopt{%
@@ -15281,7 +20000,14 @@ uppermultibarlabels,groupgap}%
{\noexpand\pgfpoint{0pt}{\noexpand\DTLbarlabeloffset}}}
}%
}
+% \end{macrocode}
+% Set \cs{DTLendpt} to the end point.
+% \begin{macrocode}
+ \edef\DTLendpt{\noexpand\pgfpointxy{\@dtl@start.5}{\dtl@variable}}%
\else
+% \end{macrocode}
+% Horizontal bars
+% \begin{macrocode}
\expandafter\DTLifnumlt\expandafter{\DTLbarvariable}{0}
{
\edef\dtl@textopt{right,
@@ -15296,10 +20022,23 @@ uppermultibarlabels,groupgap}%
{\noexpand\pgfpoint{\noexpand\DTLbarlabeloffset}{0pt}}}
}%
}
+% \end{macrocode}
+% Set \cs{DTLendpt} to the end point.
+% \begin{macrocode}
+ \edef\DTLendpt{\noexpand\pgfpointxy{\dtl@variable}{\@dtl@start.5}}%
\fi
\expandafter\pgftext\expandafter[\dtl@textopt]{%
\DTLdisplayupperbarlabel{\dtl@upperbarlabel}}
% \end{macrocode}
+% Set the mid point
+% \begin{macrocode}
+\def\DTLmidpt{\pgfpointlineattime{0.5}{\DTLstartpt}{\DTLendpt}}%
+% \end{macrocode}
+% Do every bar hook
+%\changes{2.0}{2009 February 27}{added \cs{DTLeverybarhook}}%
+% \begin{macrocode}
+ \DTLeverybarhook
+% \end{macrocode}
% End of loop
% \begin{macrocode}
\edef\@dtl@start{\number\@dtl@bar}%
@@ -15677,6 +20416,7 @@ uppermultibarlabels,groupgap}%
{\noexpand\pgfpoint{0pt}{-\noexpand\DTLbarlabeloffset}}},
\DTLbarXlabelalign
}%
+ \edef\DTLstartpt{\noexpand\pgfpointxy{\@dtl@midpt}{0}}%
\else
\edef\dtl@textopt{%
at={\noexpand\pgfpointadd
@@ -15684,6 +20424,7 @@ uppermultibarlabels,groupgap}%
{\noexpand\pgfpoint{-\noexpand\DTLbarlabeloffset}{0pt}}},
\DTLbarXlabelalign
}%
+ \edef\DTLstartpt{\noexpand\pgfpointxy{0}{\@dtl@midpt}}%
\fi
\expandafter\pgftext\expandafter[\dtl@textopt]{%
\DTLdisplaylowermultibarlabel{\dtl@thisbarlabel}}
@@ -15705,6 +20446,7 @@ uppermultibarlabels,groupgap}%
{\noexpand\pgfpoint{0pt}{\noexpand\DTLbarlabeloffset}}}
}%
}
+ \edef\DTLendpt{\noexpand\pgfpointxy{\@dtl@midpt}{\dtl@variable}}%
\else
\expandafter\DTLifnumlt\expandafter{\DTLbarvariable}{0}
{
@@ -15720,10 +20462,20 @@ uppermultibarlabels,groupgap}%
{\noexpand\pgfpoint{\noexpand\DTLbarlabeloffset}{0pt}}}
}%
}
+ \edef\DTLendpt{\noexpand\pgfpointxy{\dtl@variable}{\@dtl@midpt}}%
\fi
\expandafter\pgftext\expandafter[\dtl@textopt]{%
\DTLdisplayuppermultibarlabel{\dtl@thisupperbarlabel}}
% \end{macrocode}
+% Set the mid point
+% \begin{macrocode}
+\def\DTLmidpt{\pgfpointlineattime{0.5}{\DTLstartpt}{\DTLendpt}}%
+% \end{macrocode}
+% Do every bar hook
+%\changes{2.0}{2009 February 27}{added \cs{DTLeverybarhook}}%
+% \begin{macrocode}
+\DTLeverybarhook
+% \end{macrocode}
% End of loop increment loop variables
% \begin{macrocode}
\FPadd{\@dtl@start}{\@dtl@start}{1}%
@@ -15865,7 +20617,7 @@ uppermultibarlabels,groupgap}%
%\subsection{Package Declaration}
% \begin{macrocode}
\NeedsTeXFormat{LaTeX2e}
-\ProvidesPackage{databib}[2007/08/17 v1.0 (NLCT)]
+\ProvidesPackage{databib}[2009/02/27 v2.0 (NLCT)]
% \end{macrocode}
% Load required packages:
% \begin{macrocode}
@@ -15906,9 +20658,12 @@ uppermultibarlabels,groupgap}%
%\begin{macro}{\DTLnewbibrow}
% \cs{DTLnewbibrow} adds a new row to the bibliography database.
% (\cs{DTLBIBdbname} must be set prior to use to the name
-% of the \sty{datatool} database.)
+% of the \sty{datatool} database which must exist. Any check
+% to determine its existence should be performed when
+% \cs{DTLBIBdbname} is set.)
+%\changes{1.03}{2009 January 27}{removed check if database exists}
% \begin{macrocode}
-\newcommand*{\DTLnewbibrow}{\DTLnewrow{\DTLBIBdbname}}
+\newcommand*{\DTLnewbibrow}{\@DTLnewrow{\DTLBIBdbname}}
% \end{macrocode}
%\end{macro}
%\begin{macro}{\DTLnewbibitem}
@@ -15916,9 +20671,10 @@ uppermultibarlabels,groupgap}%
%\cs{DTLnewbibitem}\marg{key}\marg{value}
%\end{definition}
% Adds a new database entry with the given key and value.
+%\changes{1.03}{2009 January 27}{removed check if database exists}
% \begin{macrocode}
\newcommand*{\DTLnewbibitem}[2]{%
-\DTLnewdbentry{\DTLBIBdbname}{#1}{#2}}
+ \@DTLnewdbentry{\DTLBIBdbname}{#1}{#2}}
% \end{macrocode}
%\end{macro}
%\subsection{Predefined text}
@@ -16006,11 +20762,11 @@ uppermultibarlabels,groupgap}%
%\begin{macro}{\DTLbibliography}
% \begin{macrocode}
\newcommand*{\DTLbibliography}[2][\boolean{true}]{%
-\begin{DTLthebibliography}[#1]{#2}%
-\DTLforeachbibentry[#1]{#2}{%
-\DTLbibitem \DTLformatbibentry \DTLendbibitem
-}%
-\end{DTLthebibliography}%
+ \begin{DTLthebibliography}[#1]{#2}%
+ \DTLforeachbibentry[#1]{#2}{%
+ \DTLbibitem \DTLformatbibentry \DTLendbibitem
+ }%
+ \end{DTLthebibliography}%
}
% \end{macrocode}
%\end{macro}
@@ -16022,12 +20778,28 @@ uppermultibarlabels,groupgap}%
% Formats the current bib entry.
% \begin{macrocode}
\newcommand*{\DTLformatbibentry}{%
-\@ifundefined{DTLformat\DBIBentrytype}{%
-\PackageError{databib}{Don't know how to format bibliography entries
-of type `\DBIBentrytype'}{}}{%
-\dtl@message{[\DBIBcitekey]}%
-\DTLstartsentencefalse\DTLmidsentencefalse\DTLperiodfalse
-\csname DTLformat\DBIBentrytype\endcsname}%
+% \end{macrocode}
+% Check format for this type is defined.
+% \begin{macrocode}
+ \@ifundefined{DTLformat\DBIBentrytype}%
+ {%
+ \PackageError{databib}{Don't know how to format bibliography
+ entries of type `\DBIBentrytype'}{}%
+ }%
+ {%
+% \end{macrocode}
+% Print information to terminal and log file if in verbose mode.
+% \begin{macrocode}
+ \dtl@message{[\DBIBcitekey]}%
+% \end{macrocode}
+% Initialise
+% \begin{macrocode}
+ \DTLstartsentencefalse\DTLmidsentencefalse\DTLperiodfalse
+% \end{macrocode}
+% Format this entry
+% \begin{macrocode}
+ \csname DTLformat\DBIBentrytype\endcsname
+ }%
}
% \end{macrocode}
%\end{macro}
@@ -16089,20 +20861,46 @@ of type `\DBIBentrytype'}{}}{%
% Unstarred version
% \begin{macrocode}
\newcommand*{\@DTLforeachbibentry}[3][\boolean{true}]{%
-\edef\DBIBname{#2}\setcounter{DTLbibrow}{0}%
-\@DTLforeach{#2}{\DBIBcitekey=CiteKey,\DBIBentrytype
-=EntryType}{\dtl@gathervalues{#2}{\@dtl@currentrow}%
-\ifthenelse{#1}{\refstepcounter{DTLbibrow}#3}{}}}
+% \end{macrocode}
+% Store database name.
+% \begin{macrocode}
+ \edef\DBIBname{#2}%
+% \end{macrocode}
+% Reset row counter.
+% \begin{macrocode}
+ \setcounter{DTLbibrow}{0}%
+% \end{macrocode}
+% Iterate through the database.
+% \begin{macrocode}
+ \@DTLforeach{#2}{\DBIBcitekey=CiteKey,\DBIBentrytype=EntryType}%
+ {%
+ \dtl@gathervalues{#2}{\dtlcurrentrow}%
+ \ifthenelse{#1}{\refstepcounter{DTLbibrow}#3}{}%
+ }%
+}
% \end{macrocode}
%\end{macro}
%\begin{macro}{\@sDTLforeachbibentry}
% Starred version
% \begin{macrocode}
\newcommand*{\@sDTLforeachbibentry}[3][\boolean{true}]{%
-\edef\DBIBname{#2}\setcounter{DTLbibrow}{0}%
-\@sDTLforeach{#2}{\DBIBcitekey=CiteKey,\DBIBentrytype
-=EntryType}{\dtl@gathervalues{#2}{\@dtl@currentrow}%
-\ifthenelse{#1}{\refstepcounter{DTLbibrow}#3}{}}}
+% \end{macrocode}
+% Store database name.
+% \begin{macrocode}
+ \edef\DBIBname{#2}%
+% \end{macrocode}
+% Reset row counter.
+% \begin{macrocode}
+ \setcounter{DTLbibrow}{0}%
+% \end{macrocode}
+% Iterate through the database (read only).
+% \begin{macrocode}
+ \@sDTLforeach{#2}{\DBIBcitekey=CiteKey,\DBIBentrytype=EntryType}%
+ {%
+ \dtl@gathervalues{#2}{\dtlcurrentrow}%
+ \ifthenelse{#1}{\refstepcounter{DTLbibrow}#3}{}%
+ }%
+}
% \end{macrocode}
%\end{macro}
%
@@ -17113,6 +21911,13 @@ of type `\DBIBentrytype'}{}}{%
% \end{macrocode}
%\end{macro}
%
+%\begin{macro}{\DTLmbibitem}
+% As \cs{DTLbibitem} but for \cs{DTLmbibliography}
+% \begin{macrocode}
+\newcommand*{\DTLmbibitem}[1]{\bibitem{#1@\DBIBcitekey}}
+% \end{macrocode}
+%\end{macro}
+%
%\begin{macro}{\DTLformatauthor}
%\begin{definition}
%\cs{DTLformatauthor}\marg{von part}\marg{surname}\marg{junior
@@ -17384,6 +22189,7 @@ and Systems}
% Set how to start the bibliography entry:
% \begin{macrocode}
\renewcommand*{\DTLbibitem}{\bibitem{\DBIBcitekey}}%
+\renewcommand*{\DTLmbibitem}[1]{\bibitem{##1@\DBIBcitekey}}%
% \end{macrocode}
% Sets the author name format.
% \begin{macrocode}
@@ -18132,6 +22938,9 @@ Integrated Circuits}
\renewcommand*{\DTLbibitem}{%
\expandafter\bibitem\expandafter
[\csname dtl@biblabel@\DBIBcitekey\endcsname]{\DBIBcitekey}}%
+\renewcommand*{\DTLmbibitem}[1]{%
+\expandafter\bibitem\expandafter
+ [\csname dtl@biblabel@\DBIBcitekey\endcsname]{##1@\DBIBcitekey}}%
% \end{macrocode}
% \begin{macrocode}
% \end{macrocode}
@@ -18342,6 +23151,157 @@ bibliography style `#1'}{}}{\csname dtlbst@#1\endcsname}}
% \begin{macrocode}
\DTLbibliographystyle{\dtlbib@style}
% \end{macrocode}
+%
+%\subsection{Multiple Bibliographies}
+% In order to have multiple bibliographies, there needs to be
+% an aux file for each bibliography. The main bibliography is in
+% \cs{jobname}.aux, but need to provide a means of creating
+% additional aux files.
+%\begin{macro}{\DTLmultibibs}
+%\begin{definition}
+%\cs{DTLmultibibs}\marg{list}
+%\end{definition}
+%\changes{1.01}{2007/08/22}{new}
+% This creates an auxiliary file for each name in \meta{list}.
+% For example, "\DTLmultibibs{foo,bar}" will create the files
+% "foo.aux" and "bar.aux".
+% \begin{macrocode}
+\newcommand*{\DTLmultibibs}[1]{%
+\@for\@dtl@af:=#1\do{%
+\@ifundefined{dtl@aux@\@dtl@af}{%
+\expandafter\newwrite\csname dtl@aux@\@dtl@af\endcsname
+\expandafter\immediate
+\expandafter\openout\csname dtl@aux@\@dtl@af\endcsname=\@dtl@af.aux
+\expandafter\def\csname b@\@dtl@af @*\endcsname{}%
+}{%
+\PackageError{databib}{Can't create auxiliary file `\@dtl@af.aux',
+\expandafter\string\csname dtl@aux@\@dtl@af\endcsname\space
+already exists}{}}}}
+% \end{macrocode}
+% Can only be used in the preamble:
+% \begin{macrocode}
+\@onlypreamble{\DTLmultibibs}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLcite}
+%\begin{definition}
+%\cs{DTLcite}\oarg{text}\marg{mbib}\marg{labels}
+%\end{definition}
+% This is similar to \cs{cite}\oarg{text}\marg{labels}, except
+% 1) the cite information is written to the auxiliary file
+% associated with the multi-bib \meta{mbib} (which must be named
+% in \cs{DTLmultibibs}) and 2) the cross referencing label is
+% constructed from \meta{mbib} and \meta{label} to allow for
+% the same citation to appear in multiple bibliographies.
+% \begin{macrocode}
+\newcommand*{\DTLcite}{\@ifnextchar[{\@tempswatrue \dtl@citex
+}{\@tempswafalse \dtl@citex[]}}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtl@citex}
+% \begin{macrocode}
+\def\dtl@citex[#1]#2#3{%
+\leavevmode\let\@citea\@empty
+\@cite{\@for\@citeb:=#3\do{\@citea
+ \def\@citea{,\penalty \@m \ }%
+ \edef\@citeb{\expandafter\@firstofone\@citeb\@empty}%
+ \if@filesw
+ \@ifundefined{dtl@aux@#2}{%
+ \PackageError{databib}{multibib `#2' not defined}{%
+ You need to define `#2' in \string\DTLmutlibibs}%
+ }{%
+ \expandafter\immediate
+ \expandafter\write\csname dtl@aux@#2\endcsname{%
+ \string\citation{\@citeb}}%
+ }%
+ \fi
+ \@ifundefined{b@#2@\@citeb}{%
+ \hbox{\reset@font\bfseries ?}%
+ \G@refundefinedtrue
+ \@latex@warning{Citation `\@citeb ' on page \thepage \space
+ undefined}%
+ }{%
+ \@cite@ofmt{\csname b@#2@\@citeb \endcsname }%
+ }%
+}}{#1}%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLnocite}
+%\begin{definition}
+%\cs{DTLnocite}\marg{mbib}\marg{key list}
+%\end{definition}
+% As \cs{nocite} but uses the aux file associated with \meta{mbib}
+% which must have been defined using \cs{DTLmultibibs}.
+% \begin{macrocode}
+\newcommand*{\DTLnocite}[2]{%
+\@ifundefined{dtl@aux@#1}{%
+ \PackageError{databib}{multibib `#1' not defined}{%
+ You need to define `#1' in \string\DTLmutlibibs}%
+}{%
+ \@bsphack
+ \ifx\@onlypreamble\document
+ \@for\@citeb:=#2\do{%
+ \edef\@citeb{\expandafter\@firstofone\@citeb}%
+ \if@filesw
+ \expandafter\immediate
+ \expandafter\write\csname dtl@aux@#1\endcsname{%
+ \string\citation{\@citeb}}%
+ \fi
+ \@ifundefined{b@#1@\@citeb}{%
+ \G@refundefinedtrue
+ \@latex@warning{Citation `\@citeb ' undefined}}{}%
+ }%
+ \else
+ \@latex@error{Cannot be used in preamble}\@eha
+ \fi
+ \@esphack
+}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLloadmbbl}
+%\begin{definition}
+%\cs{DTLloadmbib}\marg{mbib}\marg{db name}\marg{bib list}
+%\end{definition}
+% \begin{macrocode}
+\newcommand*{\DTLloadmbbl}[3]{%
+\@ifundefined{dtl@aux@#1}{%
+ \PackageError{databib}{multibib `#1' not defined}{%
+ You need to define `#1' in \string\DTLmutlibibs}%
+}{%
+ \if@filesw
+ \expandafter\immediate\expandafter
+ \write\csname dtl@aux@#1\endcsname{\string\bibstyle{databib}}%
+ \expandafter\immediate\expandafter
+ \write\csname dtl@aux@#1\endcsname{\string\bibdata{#3}}%
+ \fi
+ \DTLnewdb{#2}%
+ \edef\DTLBIBdbname{#2}%
+ \@input@{#1.bbl}%
+}%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{definition}
+%\cs{DTLmbibliography}\oarg{condition}\marg{mbib name}\marg{bib dbname}
+%\end{definition}
+% Displays the bibliography for the database \meta{bib dbname}
+% which must have previously been loaded using
+% \cs{DTLloadmbbl}, where \meta{mbib name} must be listed
+% in \cs{DTLmultibibs}.
+%\begin{macro}{\DTLmbibliography}
+% \begin{macrocode}
+\newcommand*{\DTLmbibliography}[3][\boolean{true}]{%
+\begin{DTLthebibliography}[#1]{#3}%
+\DTLforeachbibentry[#1]{#3}{%
+\DTLmbibitem{#2} \DTLformatbibentry \DTLendbibitem
+}%
+\end{DTLthebibliography}%
+}
+% \end{macrocode}
+%\end{macro}
%\iffalse
% \begin{macrocode}
%</databib.sty>
@@ -18357,6 +23317,7 @@ bibliography style `#1'}{}}{\csname dtlbst@#1\endcsname}}
% \begin{macrocode}
% Bibliography style `databib'
% This style is provided for use with the databib package.
+% v1.01 (2007/08/22) - added "file" field
ENTRY
{ address
@@ -18386,6 +23347,7 @@ ENTRY
pubmed
url
abstract
+ file
}
{}
{ label }
@@ -18722,6 +23684,16 @@ FUNCTION {format.url}
if$
}
+FUNCTION {format.file}
+{ file empty$
+ { "" }
+ {
+ file
+ "\DTLnewbibitem {File}" swap$ group *
+ }
+ if$
+}
+
FUNCTION {format.address}
{ address empty$
{ "" }
@@ -19116,6 +24088,7 @@ FUNCTION {article}
format.pubmed output
format.url output
format.abstract output
+ format.file output
fin.entry
}
@@ -19157,6 +24130,7 @@ FUNCTION {book}
format.pubmed output
format.url output
format.abstract output
+ format.file output
fin.entry
}
@@ -19179,6 +24153,7 @@ FUNCTION {booklet}
format.pubmed output
format.url output
format.abstract output
+ format.file output
fin.entry
}
@@ -19221,6 +24196,7 @@ FUNCTION {inbook}
format.pubmed output
format.url output
format.abstract output
+ format.file output
fin.entry
}
@@ -19252,6 +24228,7 @@ FUNCTION {incollection}
format.pubmed output
format.url output
format.abstract output
+ format.file output
fin.entry
}
@@ -19291,6 +24268,7 @@ FUNCTION {inproceedings}
format.pubmed output
format.url output
format.abstract output
+ format.file output
fin.entry
}
@@ -19335,6 +24313,7 @@ FUNCTION {manual}
format.pubmed output
format.url output
format.abstract output
+ format.file output
fin.entry
}
@@ -19359,6 +24338,7 @@ FUNCTION {mastersthesis}
format.pubmed output
format.url output
format.abstract output
+ format.file output
fin.entry
}
@@ -19380,6 +24360,7 @@ FUNCTION {misc}
format.pubmed output
format.url output
format.abstract output
+ format.file output
fin.entry
empty.misc.check
}
@@ -19405,6 +24386,7 @@ FUNCTION {phdthesis}
format.pubmed output
format.url output
format.abstract output
+ format.file output
fin.entry
}
@@ -19448,6 +24430,7 @@ FUNCTION {proceedings}
format.pubmed output
format.url output
format.abstract output
+ format.file output
fin.entry
}
@@ -19471,6 +24454,7 @@ FUNCTION {techreport}
format.pubmed output
format.url output
format.abstract output
+ format.file output
fin.entry
}
@@ -19489,6 +24473,7 @@ FUNCTION {unpublished}
format.pubmed output
format.url output
format.abstract output
+ format.file output
format.date output
fin.entry
}
diff --git a/Master/texmf-dist/source/latex/datatool/datatool.ins b/Master/texmf-dist/source/latex/datatool/datatool.ins
index 87c233613df..38bc0ad7fe9 100644
--- a/Master/texmf-dist/source/latex/datatool/datatool.ins
+++ b/Master/texmf-dist/source/latex/datatool/datatool.ins
@@ -1,10 +1,10 @@
-% datatool.ins generated using makedtx version 0.94b 2007/8/19 14:27
+% datatool.ins generated using makedtx version 0.94b 2009/2/27 13:27
\input docstrip
\preamble
datatool.dtx
- Copyright 2007 Nicola Talbot
+ Copyright 2009 Nicola Talbot
This work may be distributed and/or modified under the
conditions of the LaTeX Project Public License, either version 1.3
diff --git a/Master/texmf-dist/tex/latex/datatool/databar.sty b/Master/texmf-dist/tex/latex/datatool/databar.sty
index 63b5f505912..ecf8ce763bf 100644
--- a/Master/texmf-dist/tex/latex/datatool/databar.sty
+++ b/Master/texmf-dist/tex/latex/datatool/databar.sty
@@ -7,7 +7,7 @@
%% datatool.dtx (with options: `databar.sty,package')
%%
%% datatool.dtx
-%% Copyright 2007 Nicola Talbot
+%% Copyright 2009 Nicola Talbot
%%
%% This work may be distributed and/or modified under the
%% conditions of the LaTeX Project Public License, either version 1.3
@@ -39,7 +39,7 @@
%% Grave accent \` Left brace \{ Vertical bar \|
%% Right brace \} Tilde \~}
\NeedsTeXFormat{LaTeX2e}
-\ProvidesPackage{databar}[2007/08/17 v1.01 (NLCT)]
+\ProvidesPackage{databar}[2009/02/27 v2.0 (NLCT)]
\RequirePackage{xkeyval}
\RequirePackage{dataplot}
\newif\ifDTLcolorbarchart
@@ -128,6 +128,7 @@
\DTLsetbarcolor{7}{black!75}
\DTLsetbarcolor{8}{black!85}
\fi
+\newcommand*{\DTLeverybarhook}{}
\define@key{databar}{max}{\def\DTLbarmax{#1}}
\define@key{databar}{length}{\DTLbarchartlength=#1\relax
}
@@ -199,7 +200,8 @@
uppermultibarlabels,groupgap}%
\setkeys{databar}{#2}%
\ifx\DTLbarvariable\relax
- \PackageError{databar}{\string\DTLbarchart\space missing variable}{}%
+ \PackageError{databar}{\string\DTLbarchart\space missing
+ variable}{You haven't use the "variable" key}%
\else
\ifx\DTLbarmax\relax
\@sDTLforeach[#1]{#3}{#4}{%
@@ -342,6 +344,7 @@ uppermultibarlabels,groupgap}%
{\noexpand\pgfpoint{0pt}{-\noexpand\DTLbarlabeloffset}}},
\DTLbarXlabelalign
}%
+ \edef\DTLstartpt{\noexpand\pgfpointxy{\@dtl@start.5}{0}}%
\else
\edef\dtl@textopt{%
at={\noexpand\pgfpointadd
@@ -349,6 +352,7 @@ uppermultibarlabels,groupgap}%
{\noexpand\pgfpoint{-\noexpand\DTLbarlabeloffset}{0pt}}},
\DTLbarXlabelalign
}%
+ \edef\DTLstartpt{\noexpand\pgfpointxy{0}{\@dtl@start.5}}%
\fi
\expandafter\pgftext\expandafter[\dtl@textopt]{%
\DTLdisplaylowerbarlabel{\dtl@barlabel}}
@@ -367,6 +371,7 @@ uppermultibarlabels,groupgap}%
{\noexpand\pgfpoint{0pt}{\noexpand\DTLbarlabeloffset}}}
}%
}
+ \edef\DTLendpt{\noexpand\pgfpointxy{\@dtl@start.5}{\dtl@variable}}%
\else
\expandafter\DTLifnumlt\expandafter{\DTLbarvariable}{0}
{
@@ -382,9 +387,12 @@ uppermultibarlabels,groupgap}%
{\noexpand\pgfpoint{\noexpand\DTLbarlabeloffset}{0pt}}}
}%
}
+ \edef\DTLendpt{\noexpand\pgfpointxy{\dtl@variable}{\@dtl@start.5}}%
\fi
\expandafter\pgftext\expandafter[\dtl@textopt]{%
\DTLdisplayupperbarlabel{\dtl@upperbarlabel}}
+\def\DTLmidpt{\pgfpointlineattime{0.5}{\DTLstartpt}{\DTLendpt}}%
+ \DTLeverybarhook
\edef\@dtl@start{\number\@dtl@bar}%
}
\ifDTLbarxaxis
@@ -653,6 +661,7 @@ uppermultibarlabels,groupgap}%
{\noexpand\pgfpoint{0pt}{-\noexpand\DTLbarlabeloffset}}},
\DTLbarXlabelalign
}%
+ \edef\DTLstartpt{\noexpand\pgfpointxy{\@dtl@midpt}{0}}%
\else
\edef\dtl@textopt{%
at={\noexpand\pgfpointadd
@@ -660,6 +669,7 @@ uppermultibarlabels,groupgap}%
{\noexpand\pgfpoint{-\noexpand\DTLbarlabeloffset}{0pt}}},
\DTLbarXlabelalign
}%
+ \edef\DTLstartpt{\noexpand\pgfpointxy{0}{\@dtl@midpt}}%
\fi
\expandafter\pgftext\expandafter[\dtl@textopt]{%
\DTLdisplaylowermultibarlabel{\dtl@thisbarlabel}}
@@ -678,6 +688,7 @@ uppermultibarlabels,groupgap}%
{\noexpand\pgfpoint{0pt}{\noexpand\DTLbarlabeloffset}}}
}%
}
+ \edef\DTLendpt{\noexpand\pgfpointxy{\@dtl@midpt}{\dtl@variable}}%
\else
\expandafter\DTLifnumlt\expandafter{\DTLbarvariable}{0}
{
@@ -693,9 +704,12 @@ uppermultibarlabels,groupgap}%
{\noexpand\pgfpoint{\noexpand\DTLbarlabeloffset}{0pt}}}
}%
}
+ \edef\DTLendpt{\noexpand\pgfpointxy{\dtl@variable}{\@dtl@midpt}}%
\fi
\expandafter\pgftext\expandafter[\dtl@textopt]{%
\DTLdisplayuppermultibarlabel{\dtl@thisupperbarlabel}}
+\def\DTLmidpt{\pgfpointlineattime{0.5}{\DTLstartpt}{\DTLendpt}}%
+\DTLeverybarhook
\FPadd{\@dtl@start}{\@dtl@start}{1}%
\advance\@dtl@barcount by 1\relax
}%
diff --git a/Master/texmf-dist/tex/latex/datatool/databib.sty b/Master/texmf-dist/tex/latex/datatool/databib.sty
index 2b168d64dd4..44160a138d9 100644
--- a/Master/texmf-dist/tex/latex/datatool/databib.sty
+++ b/Master/texmf-dist/tex/latex/datatool/databib.sty
@@ -7,7 +7,7 @@
%% datatool.dtx (with options: `databib.sty,package')
%%
%% datatool.dtx
-%% Copyright 2007 Nicola Talbot
+%% Copyright 2009 Nicola Talbot
%%
%% This work may be distributed and/or modified under the
%% conditions of the LaTeX Project Public License, either version 1.3
@@ -39,7 +39,7 @@
%% Grave accent \` Left brace \{ Vertical bar \|
%% Right brace \} Tilde \~}
\NeedsTeXFormat{LaTeX2e}
-\ProvidesPackage{databib}[2007/08/17 v1.0 (NLCT)]
+\ProvidesPackage{databib}[2009/02/27 v2.0 (NLCT)]
\RequirePackage{datatool}
\newcommand*{\dtlbib@style}{plain}
\define@choicekey{databib.sty}{style}{plain,abbrv,alpha}{%
@@ -53,9 +53,9 @@
\DTLnewdb{#2}%
\edef\DTLBIBdbname{#2}%
\@input@{#1}}
-\newcommand*{\DTLnewbibrow}{\DTLnewrow{\DTLBIBdbname}}
+\newcommand*{\DTLnewbibrow}{\@DTLnewrow{\DTLBIBdbname}}
\newcommand*{\DTLnewbibitem}[2]{%
-\DTLnewdbentry{\DTLBIBdbname}{#1}{#2}}
+ \@DTLnewdbentry{\DTLBIBdbname}{#1}{#2}}
\providecommand*{\andname}{and}
\providecommand*{\ofname}{of}
\providecommand*{\inname}{in}
@@ -71,19 +71,23 @@
\providecommand*{\mscthesisname}{Master's thesis}
\providecommand*{\phdthesisname}{PhD thesis}
\newcommand*{\DTLbibliography}[2][\boolean{true}]{%
-\begin{DTLthebibliography}[#1]{#2}%
-\DTLforeachbibentry[#1]{#2}{%
-\DTLbibitem \DTLformatbibentry \DTLendbibitem
-}%
-\end{DTLthebibliography}%
+ \begin{DTLthebibliography}[#1]{#2}%
+ \DTLforeachbibentry[#1]{#2}{%
+ \DTLbibitem \DTLformatbibentry \DTLendbibitem
+ }%
+ \end{DTLthebibliography}%
}
\newcommand*{\DTLformatbibentry}{%
-\@ifundefined{DTLformat\DBIBentrytype}{%
-\PackageError{databib}{Don't know how to format bibliography entries
-of type `\DBIBentrytype'}{}}{%
-\dtl@message{[\DBIBcitekey]}%
-\DTLstartsentencefalse\DTLmidsentencefalse\DTLperiodfalse
-\csname DTLformat\DBIBentrytype\endcsname}%
+ \@ifundefined{DTLformat\DBIBentrytype}%
+ {%
+ \PackageError{databib}{Don't know how to format bibliography
+ entries of type `\DBIBentrytype'}{}%
+ }%
+ {%
+ \dtl@message{[\DBIBcitekey]}%
+ \DTLstartsentencefalse\DTLmidsentencefalse\DTLperiodfalse
+ \csname DTLformat\DBIBentrytype\endcsname
+ }%
}
\newcommand*{\DTLendbibitem}{}
\newlength\dtl@widest
@@ -101,15 +105,23 @@ of type `\DBIBentrytype'}{}}{%
\newcommand*{\DTLforeachbibentry}{%
\@ifstar\@DTLforeachbibentry\@DTLforeachbibentry}
\newcommand*{\@DTLforeachbibentry}[3][\boolean{true}]{%
-\edef\DBIBname{#2}\setcounter{DTLbibrow}{0}%
-\@DTLforeach{#2}{\DBIBcitekey=CiteKey,\DBIBentrytype
-=EntryType}{\dtl@gathervalues{#2}{\@dtl@currentrow}%
-\ifthenelse{#1}{\refstepcounter{DTLbibrow}#3}{}}}
+ \edef\DBIBname{#2}%
+ \setcounter{DTLbibrow}{0}%
+ \@DTLforeach{#2}{\DBIBcitekey=CiteKey,\DBIBentrytype=EntryType}%
+ {%
+ \dtl@gathervalues{#2}{\dtlcurrentrow}%
+ \ifthenelse{#1}{\refstepcounter{DTLbibrow}#3}{}%
+ }%
+}
\newcommand*{\@sDTLforeachbibentry}[3][\boolean{true}]{%
-\edef\DBIBname{#2}\setcounter{DTLbibrow}{0}%
-\@sDTLforeach{#2}{\DBIBcitekey=CiteKey,\DBIBentrytype
-=EntryType}{\dtl@gathervalues{#2}{\@dtl@currentrow}%
-\ifthenelse{#1}{\refstepcounter{DTLbibrow}#3}{}}}
+ \edef\DBIBname{#2}%
+ \setcounter{DTLbibrow}{0}%
+ \@sDTLforeach{#2}{\DBIBcitekey=CiteKey,\DBIBentrytype=EntryType}%
+ {%
+ \dtl@gathervalues{#2}{\dtlcurrentrow}%
+ \ifthenelse{#1}{\refstepcounter{DTLbibrow}#3}{}%
+ }%
+}
\newcounter{DTLbibrow}
\def\theHDTLbibrow{\theHDTLrow.bib.\arabic{DTLbibrow}}%
\newcommand*{\DTLbibfield}[1]{\csname @dtl@key@#1\endcsname}
@@ -667,6 +679,7 @@ of type `\DBIBentrytype'}{}}{%
\or Dec.%
\fi}
\newcommand*{\DTLbibitem}{\bibitem{\DBIBcitekey}}
+\newcommand*{\DTLmbibitem}[1]{\bibitem{#1@\DBIBcitekey}}
\newcommand*{\DTLformatauthor}[4]{%
\DTLformatforenames{#4}
\DTLformatvon{#1}%
@@ -721,6 +734,7 @@ and Systems}
\begin{thebibliography}{\number\@dtl@tmpcount}%
}{\end{thebibliography}}%
\renewcommand*{\DTLbibitem}{\bibitem{\DBIBcitekey}}%
+\renewcommand*{\DTLmbibitem}[1]{\bibitem{##1@\DBIBcitekey}}%
\renewcommand*{\DTLformatauthor}[4]{%
\DTLformatforenames{##4}
\DTLformatvon{##1}%
@@ -1366,6 +1380,9 @@ Integrated Circuits}
\renewcommand*{\DTLbibitem}{%
\expandafter\bibitem\expandafter
[\csname dtl@biblabel@\DBIBcitekey\endcsname]{\DBIBcitekey}}%
+\renewcommand*{\DTLmbibitem}[1]{%
+\expandafter\bibitem\expandafter
+ [\csname dtl@biblabel@\DBIBcitekey\endcsname]{##1@\DBIBcitekey}}%
}
\newcommand*{\dtl@createalphabiblabels}[2]{%
\dtl@message{Creating bib labels}%
@@ -1524,6 +1541,92 @@ Integrated Circuits}
\@ifundefined{dtlbst@#1}{\PackageError{databib}{Unknown
bibliography style `#1'}{}}{\csname dtlbst@#1\endcsname}}
\DTLbibliographystyle{\dtlbib@style}
+\newcommand*{\DTLmultibibs}[1]{%
+\@for\@dtl@af:=#1\do{%
+\@ifundefined{dtl@aux@\@dtl@af}{%
+\expandafter\newwrite\csname dtl@aux@\@dtl@af\endcsname
+\expandafter\immediate
+\expandafter\openout\csname dtl@aux@\@dtl@af\endcsname=\@dtl@af.aux
+\expandafter\def\csname b@\@dtl@af @*\endcsname{}%
+}{%
+\PackageError{databib}{Can't create auxiliary file `\@dtl@af.aux',
+\expandafter\string\csname dtl@aux@\@dtl@af\endcsname\space
+already exists}{}}}}
+\@onlypreamble{\DTLmultibibs}
+\newcommand*{\DTLcite}{\@ifnextchar[{\@tempswatrue \dtl@citex
+}{\@tempswafalse \dtl@citex[]}}
+\def\dtl@citex[#1]#2#3{%
+\leavevmode\let\@citea\@empty
+\@cite{\@for\@citeb:=#3\do{\@citea
+ \def\@citea{,\penalty \@m \ }%
+ \edef\@citeb{\expandafter\@firstofone\@citeb\@empty}%
+ \if@filesw
+ \@ifundefined{dtl@aux@#2}{%
+ \PackageError{databib}{multibib `#2' not defined}{%
+ You need to define `#2' in \string\DTLmutlibibs}%
+ }{%
+ \expandafter\immediate
+ \expandafter\write\csname dtl@aux@#2\endcsname{%
+ \string\citation{\@citeb}}%
+ }%
+ \fi
+ \@ifundefined{b@#2@\@citeb}{%
+ \hbox{\reset@font\bfseries ?}%
+ \G@refundefinedtrue
+ \@latex@warning{Citation `\@citeb ' on page \thepage \space
+ undefined}%
+ }{%
+ \@cite@ofmt{\csname b@#2@\@citeb \endcsname }%
+ }%
+}}{#1}%
+}
+\newcommand*{\DTLnocite}[2]{%
+\@ifundefined{dtl@aux@#1}{%
+ \PackageError{databib}{multibib `#1' not defined}{%
+ You need to define `#1' in \string\DTLmutlibibs}%
+}{%
+ \@bsphack
+ \ifx\@onlypreamble\document
+ \@for\@citeb:=#2\do{%
+ \edef\@citeb{\expandafter\@firstofone\@citeb}%
+ \if@filesw
+ \expandafter\immediate
+ \expandafter\write\csname dtl@aux@#1\endcsname{%
+ \string\citation{\@citeb}}%
+ \fi
+ \@ifundefined{b@#1@\@citeb}{%
+ \G@refundefinedtrue
+ \@latex@warning{Citation `\@citeb ' undefined}}{}%
+ }%
+ \else
+ \@latex@error{Cannot be used in preamble}\@eha
+ \fi
+ \@esphack
+}%
+}
+\newcommand*{\DTLloadmbbl}[3]{%
+\@ifundefined{dtl@aux@#1}{%
+ \PackageError{databib}{multibib `#1' not defined}{%
+ You need to define `#1' in \string\DTLmutlibibs}%
+}{%
+ \if@filesw
+ \expandafter\immediate\expandafter
+ \write\csname dtl@aux@#1\endcsname{\string\bibstyle{databib}}%
+ \expandafter\immediate\expandafter
+ \write\csname dtl@aux@#1\endcsname{\string\bibdata{#3}}%
+ \fi
+ \DTLnewdb{#2}%
+ \edef\DTLBIBdbname{#2}%
+ \@input@{#1.bbl}%
+}%
+}
+\newcommand*{\DTLmbibliography}[3][\boolean{true}]{%
+\begin{DTLthebibliography}[#1]{#3}%
+\DTLforeachbibentry[#1]{#3}{%
+\DTLmbibitem{#2} \DTLformatbibentry \DTLendbibitem
+}%
+\end{DTLthebibliography}%
+}
\endinput
%%
%% End of file `databib.sty'.
diff --git a/Master/texmf-dist/tex/latex/datatool/datapie.sty b/Master/texmf-dist/tex/latex/datatool/datapie.sty
index 418f8a045a2..f1af8129159 100644
--- a/Master/texmf-dist/tex/latex/datatool/datapie.sty
+++ b/Master/texmf-dist/tex/latex/datatool/datapie.sty
@@ -7,7 +7,7 @@
%% datatool.dtx (with options: `datapie.sty,package')
%%
%% datatool.dtx
-%% Copyright 2007 Nicola Talbot
+%% Copyright 2009 Nicola Talbot
%%
%% This work may be distributed and/or modified under the
%% conditions of the LaTeX Project Public License, either version 1.3
@@ -39,7 +39,7 @@
%% Grave accent \` Left brace \{ Vertical bar \|
%% Right brace \} Tilde \~}
\NeedsTeXFormat{LaTeX2e}
-\ProvidesPackage{datapie}[2007/08/17 v1.01 (NLCT)]
+\ProvidesPackage{datapie}[2007/02/27 v2.0 (NLCT)]
\RequirePackage{xkeyval}
\newif\ifDTLcolorpiechart
\DTLcolorpiecharttrue
diff --git a/Master/texmf-dist/tex/latex/datatool/dataplot.sty b/Master/texmf-dist/tex/latex/datatool/dataplot.sty
index 83eaef56ebb..48500c6843c 100644
--- a/Master/texmf-dist/tex/latex/datatool/dataplot.sty
+++ b/Master/texmf-dist/tex/latex/datatool/dataplot.sty
@@ -7,7 +7,7 @@
%% datatool.dtx (with options: `dataplot.sty,package')
%%
%% datatool.dtx
-%% Copyright 2007 Nicola Talbot
+%% Copyright 2009 Nicola Talbot
%%
%% This work may be distributed and/or modified under the
%% conditions of the LaTeX Project Public License, either version 1.3
@@ -39,7 +39,7 @@
%% Grave accent \` Left brace \{ Vertical bar \|
%% Right brace \} Tilde \~}
\NeedsTeXFormat{LaTeX2e}
-\ProvidesPackage{dataplot}[2007/08/17 v1.01 (NLCT)]
+\ProvidesPackage{dataplot}[2009/02/27 v2.0 (NLCT)]
\RequirePackage{xkeyval}
\RequirePackage{tikz}
\RequirePackage{datatool}
@@ -51,43 +51,44 @@
\DTLconverttodecimal{\dtl@y}{\dtl@decy}%
\pgfplotstreampoint{\pgfpointxy{\dtl@decx}{\dtl@decy}}}}
\newcommand*{\DTLplotmarks}{%
-\pgfuseplotmark{o},%
-\pgfuseplotmark{x},%
-\pgfuseplotmark{+},%
-\pgfuseplotmark{square},%
-\pgfuseplotmark{triangle},%
-\pgfuseplotmark{diamond},%
-\pgfuseplotmark{pentagon},%
-\pgfuseplotmark{asterisk},%
-\pgfuseplotmark{star}}
+ \pgfuseplotmark{o},%
+ \pgfuseplotmark{x},%
+ \pgfuseplotmark{+},%
+ \pgfuseplotmark{square},%
+ \pgfuseplotmark{triangle},%
+ \pgfuseplotmark{diamond},%
+ \pgfuseplotmark{pentagon},%
+ \pgfuseplotmark{asterisk},%
+ \pgfuseplotmark{star}%
+}
\newcommand*{\DTLplotmarkcolors}{%
-red,%
-green,%
-blue,%
-yellow,%
-magenta,%
-cyan,%
-orange,%
-black,%
-gray}
+ red,%
+ green,%
+ blue,%
+ yellow,%
+ magenta,%
+ cyan,%
+ orange,%
+ black,%
+ gray}
\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},%
+ \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},%
}
\newcommand*{\DTLplotlinecolors}{%
-red,%
-green,%
-blue,%
-yellow,%
-magenta,%
-cyan,%
-orange,%
-black,%
-gray}
+ red,%
+ green,%
+ blue,%
+ yellow,%
+ magenta,%
+ cyan,%
+ orange,%
+ black,%
+ gray}
\newlength\DTLplotwidth
\setlength\DTLplotwidth{4in}
\newlength\DTLplotheight
diff --git a/Master/texmf-dist/tex/latex/datatool/datatool.sty b/Master/texmf-dist/tex/latex/datatool/datatool.sty
index 099417295be..6925836a74c 100644
--- a/Master/texmf-dist/tex/latex/datatool/datatool.sty
+++ b/Master/texmf-dist/tex/latex/datatool/datatool.sty
@@ -7,7 +7,7 @@
%% datatool.dtx (with options: `datatool.sty,package')
%%
%% datatool.dtx
-%% Copyright 2007 Nicola Talbot
+%% Copyright 2009 Nicola Talbot
%%
%% This work may be distributed and/or modified under the
%% conditions of the LaTeX Project Public License, either version 1.3
@@ -39,12 +39,13 @@
%% Grave accent \` Left brace \{ Vertical bar \|
%% Right brace \} Tilde \~}
\NeedsTeXFormat{LaTeX2e}
-\ProvidesPackage{datatool}[2007/08/17 v1.01 (NLCT)]
+\ProvidesPackage{datatool}[2009/02/27 v2.0 (NLCT)]
\RequirePackage{xkeyval}
\RequirePackage{ifthen}
\RequirePackage{xfor}
\RequirePackage{fp}
\RequirePackage{substr}
+\RequirePackage{etex}
\newcommand*{\@dtl@separator}{,}
\newcommand*{\DTLsetseparator}[1]{%
\renewcommand*{\@dtl@separator}{#1}%
@@ -1220,32 +1221,16 @@
\@dtl@dovalue
}
\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}
+ \PackageError{datatool}{\string\DTLiffirstrow\space can only
+ be used inside \string\DTLforeach}{}%
+}
\newcommand{\DTLiflastrow}[2]{%
-\ifnum\dtlforeachlevel=0\relax
- \PackageError{datatool}{\string\DTLiflastrow\space can only
- be used inside \string\DTLforeach}{}%
-\else
-\ifx\@dtl@nextrow\@nnil
-#1\else #2\fi
-\fi
+ \PackageError{datatool}{\string\DTLiflastrow\space can only
+ be used inside \string\DTLforeach}{}%
}
\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
+ \PackageError{datatool}{\string\DTLifoddrow\space can only
+ be used inside \string\DTLforeach}{}%
}
\newif\if@dtl@condition
\newcommand*{\dtl@testlt}[2]{%
@@ -1373,145 +1358,808 @@
\TE@throw\noexpand\dtl@testcurrencyunit{#1}{#2}%
\noexpand\if@dtl@condition}
\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}}
+ \DTLifdbexists{#1}%
+ {%
+ \PackageError{datatool}{Database `#1' already exists}{}%
+ }%
+ {%
+ \dtl@message{Creating database `#1'}%
+ \expandafter\newtoks\csname dtldb@#1\endcsname
+ \expandafter\newtoks\csname dtlkeys@#1\endcsname{}%
+ \expandafter\newcount\csname dtlrows@#1\endcsname
+ \expandafter\newcount\csname dtlcols@#1\endcsname
+ }%
+}
\newcommand*{\DTLrowcount}[1]{%
\expandafter\number\csname dtlrows@#1\endcsname}
+\newcommand*{\DTLcolumncount}[1]{%
+\expandafter\number\csname dtlcols@#1\endcsname}
\newcommand{\DTLifdbempty}[3]{%
-\DTLifdbexists{#1}{%
-\expandafter\ifx\csname dtldb@#1\endcsname\@empty
- #2%
-\else
- #3%
-\fi}{%
-\PackageError{Database `#1' doesn't exist}{}{}}}
-\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
+ \DTLifdbexists{#1}%
+ {\@DTLifdbempty{#1}{#2}{#3}}%
+ {\PackageError{Can't check if database `#1' is empty:
+ database doesn't exist}{}{}}%
+}
+\newcommand{\@DTLifdbempty}[3]{%
+ \expandafter\ifnum\csname dtlrows@#1\endcsname=0\relax
+ #2%
+ \else
+ #3%
+ \fi
+}
+\newcommand*{\DTLnewrow}{%
+ \@ifstar\@sDTLnewrow\@DTLnewrow
+}
+\newcommand*{\@DTLnewrow}[1]{%
+\DTLifdbexists{#1}%
+ {\@sDTLnewrow{#1}}%
+ {\PackageErrors{datatool}{Can't add new row to database `#1':
+ database doesn't exist}{}}%
+}
+\newcommand*{\@sDTLnewrow}[1]{%
+ \global\advance\csname dtlrows@#1\endcsname by 1\relax
+ \toks@gput@right@cx{dtldb@#1}{%
+ \noexpand\db@row@elt@w%
+ \noexpand\db@row@id@w \number\csname dtlrows@#1\endcsname
+ \noexpand\db@row@id@end@%
+ \noexpand\db@row@id@w \number\csname dtlrows@#1\endcsname
+ \noexpand\db@row@id@end@%
+ \noexpand\db@row@elt@end@%
+ }%
\dtl@message{New row added to database `#1'}%
-}}
-\newcommand{\DTLnewdbentry}[3]{%
-\@dtl@toks{#3}%
-\edef\@dtl@dbvalue{\the\@dtl@toks}%
-\edef\@dtl@dbid{#2}%
-\edef\@dtl@dbentry{{\@dtl@dbid}{\the\@dtl@toks}}%
-\DTLifdbempty{#1}{\DTLnewrow{#1}}{}%
-\expandafter\dtl@choplast\expandafter{%
-\csname dtldb@#1\endcsname}{\@dtl@dbrest}{\@dtl@dblastrow}%
-\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}}{%
-\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}%
-}%
-\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}}%
-}%
-\@dtl@setidtype{#1}{#2}{#3}%
-\expandafter\@dtl@setkeys\expandafter{#2}{#1}%
-}%
-\dtl@message{Added #2\space -> #3\space to database `#1'}%
}
-\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\relax
- \ifcase\@dtl@tmpcount
- \or
- \expandafter\xdef\csname @dtl@idtype@#1@#2\endcsname{%
- \the\@dtl@datatype}%
- \or
- \ifnum\@dtl@datatype=0\relax
- \expandafter\gdef\csname @dtl@idtype@#1@#2\endcsname{0}%
+\newcount\dtlcolumnnum
+\newcount\dtlrownum
+\newcommand*{\DTLifhaskey}{\@ifstar\@sDTLifhaskey\@DTLifhaskey}
+\newcommand{\@DTLifhaskey}[4]{%
+ \DTLifdbexists{#1}%
+ {%
+ \@sDTLifhaskey{#1}{#2}{#3}{#4}%
+ }%
+ {%
+ \PackageError{datatool}{Database `#1' doesn't exist}{}%
+ }%
+}
+\newcommand{\@sDTLifhaskey}[4]{%
+ \@ifundefined{dtl@ci@#1@#2}%
+ {%
+ #4%
+ }%
+ {%
+ #3%
+ }%
+}
+\newcommand*{\DTLgetcolumnindex}{%
+ \@ifstar\@sdtl@getcolumnindex\@dtl@getcolumnindex
+}
+\newcommand*{\@dtl@getcolumnindex}[3]{%
+ \DTLifdbexists{#2}%
+ {%
+ \@sDTLifhaskey{#2}{#3}%
+ {%
+ \@sdtl@getcolumnindex{#1}{#2}{#3}%
+ }%
+ {%
+ \PackageError{datatool}{Database `#2' doesn't contain
+ key `#3'}{}%
+ }%
+ }%
+ {%
+ \PackageError{datatool}{Database `#2' doesn't exist}{}%
+ }%
+}
+\newcommand*{\@sdtl@getcolumnindex}[3]{%
+ \expandafter\let\expandafter#1\csname dtl@ci@#2@#3\endcsname
+}
+\newcommand*{\dtl@columnindex}[2]{%
+ \csname dtl@ci@#1@#2\endcsname
+}
+\newcommand*{\DTLgetkeyforcolumn}{%
+ \@ifstar\@sdtlgetkeyforcolumn\@dtlgetkeyforcolumn}
+\newcommand*{\@dtlgetkeyforcolumn}[3]{%
+ \DTLifdbexists{#2}%
+ {%
+ \ifnum#3<1\relax
+ \PackageError{datatool}{Invalid column index \number#3}{%
+ Column indices start at 1}%
+ \else
+ \expandafter\ifnum\csname dtlcols@#2\endcsname<#3\relax
+ \PackageError{datatool}{Index \number#3\space out of
+ range for database `#2'}{Database `#2' only has
+ \expandafter\number\csname dtlcols@#2\endcsname\space
+ columns}%
\else
- \ifnum\@dtl@datatype=3\relax
- \expandafter\gdef\csname @dtl@idtype@#1@#2\endcsname{3}%
- \else
- \expandafter\gdef\csname @dtl@idtype@#1@#2\endcsname{2}%
+ \@sdtlgetkeyforcolumn{#1}{#2}{#3}%
+ \fi
+ \fi
+ }%
+ {%
+ \PackageError{datatool}{Database `#2' doesn't exists}{}%
+ }%
+}
+\newcommand*{\@sdtlgetkeyforcolumn}[3]{%
+ \edef\@dtl@dogetkeyforcolumn{\noexpand\@dtl@getkeyforcolumn
+ {\noexpand#1}{#2}{\number#3}}%
+ \@dtl@dogetkeyforcolumn
+}
+\newcommand*{\@dtl@getkeyforcolumn}[3]{%
+ \def\@dtl@get@keyforcolumn##1% before stuff
+ \db@plist@elt@w% start of block
+ \db@col@id@w #3\db@col@id@end@% index
+ \db@key@id@w ##2\db@key@id@end@% key
+ \db@type@id@w ##3\db@type@id@end@% data type
+ \db@header@id@w ##4\db@header@id@end@% header
+ \db@col@id@w #3\db@col@id@end@% index
+ \db@plist@elt@end@% end of block
+ ##5\q@nil{\def#1{##2}}%
+ \edef\@dtl@tmp{\expandafter\the\csname dtldb@#2\endcsname}%
+ \expandafter\@dtl@getkeyforcolumn\@dtl@tmp
+ \db@plist@elt@w% start of block
+ \db@col@id@w #3\db@col@id@end@ index
+ \db@key@id@w \@nil\db@key@id@end@% key
+ \db@type@id@w \db@type@id@end@% data type
+ \db@header@id@w \db@header@id@end@% header
+ \db@col@id@w #3\db@col@id@end@% index
+ \db@plist@elt@end@% end of block
+ \q@nil
+}
+\def\DTLunsettype{}
+\def\DTLstringtype{0}
+\def\DTLinttype{1}
+\def\DTLrealtype{2}
+\def\DTLcurrencytype{3}
+\newcommand*{\DTLgetdatatype}{%
+ \@ifstar\@sdtlgetdatatype\@dtlgetdatatype
+}
+\newcommand*{\@dtlgetdatatype}[3]{%
+ \DTLifdbexists{#2}%
+ {%
+ \@sDTLifhaskey{#2}{#3}%
+ {%
+ \@sdtlgetdatatype{#1}{#2}{#3}%
+ }%
+ {%
+ \PackageError{datatool}{Key `#3' undefined in database `#2'}{}%
+ }%
+ }%
+ {%
+ \PackageError{datatool}{Database `#2' doesn't exist}{}%
+ }%
+}
+\newcommand*{\@sdtlgetdatatype}[3]{%
+ \edef\@dtl@dogetdata{\noexpand\@dtl@getdatatype{\noexpand#1}%
+ {\expandafter\the\csname dtlkeys@#2\endcsname}%
+ {\dtl@columnindex{#2}{#3}}}%
+ \@dtl@dogetdata
+}
+\newcommand*{\@dtl@getdatatype}[3]{%
+ \def\@dtl@get@keydata##1% stuff before
+ \db@plist@elt@w% start of key block
+ \db@col@id@w #3\db@col@id@end@% column index
+ \db@key@id@w ##2\db@key@id@end@% key id
+ \db@type@id@w ##3\db@type@id@end@% data type
+ \db@header@id@w ##4\db@header@id@end@% header
+ \db@col@id@w #3\db@col@id@end@% column index
+ \db@plist@elt@end@% end of key block
+ ##5% stuff afterwards
+ \q@nil{\def#1{##3}}%
+ \@dtl@get@keydata#2\q@nil
+}
+\newcommand*{\@dtl@getprops}[7]{%
+ \def\@dtl@get@keydata##1% stuff before
+ \db@plist@elt@w% start of key block
+ \db@col@id@w #7\db@col@id@end@% column index
+ \db@key@id@w ##2\db@key@id@end@% key id
+ \db@type@id@w ##3\db@type@id@end@% data type
+ \db@header@id@w ##4\db@header@id@end@% header
+ \db@col@id@w #7\db@col@id@end@% column index
+ \db@plist@elt@end@% end of key block
+ ##5% stuff afterwards
+ \q@nil{%
+ \def#1{##2}% key
+ \def#2{##3}% data type
+ #3={##4}% header
+ #4={##1}% before stuff
+ #5={##5}% after stuff
+ }%
+ \@dtl@get@keydata#6\q@nil
+}
+\newtoks\@dtl@before
+\newtoks\@dtl@after
+\newtoks\@dtl@colhead
+\newcommand*{\@dtl@updatekeys}[3]{%
+ \@sDTLifhaskey{#1}{#2}%
+ {%
+ \expandafter\dtlcolumnnum\expandafter
+ =\dtl@columnindex{#1}{#2}\relax
+ \edef\@dtl@dogetprops{\noexpand\@dtl@getprops
+ {\noexpand\@dtl@key}{\noexpand\@dtl@type}%
+ {\noexpand\@dtl@colhead}{\noexpand\@dtl@before}%
+ {\noexpand\@dtl@after}{\the\csname dtlkeys@#1\endcsname}%
+ {\number\dtlcolumnnum}}
+ \@dtl@dogetprops
+ \def\@dtl@tmp{#3}%
+ \ifx\@dtl@tmp\@empty
+ \else
+ \let\@dtl@oldtype\@dtl@type
+ \@dtl@checknumerical{#3}%
+ \ifx\@dtl@type\@empty
+ \edef\@dtl@type{\number\@dtl@datatype}%
+ \else
+ \ifcase\@dtl@datatype % string
+ \def\@dtl@type{0}%
+ \or % int
+ \or % real
+ \ifnum\@dtl@type=1\relax
+ \def\@dtl@type{2}%
+ \fi
+ \or % currency
+ \ifnum\@dtl@type>0\relax
+ \def\@dtl@type{3}%
+ \fi
\fi
\fi
- \or
- \ifnum\@dtl@datatype=0\relax
- \expandafter\gdef\csname @dtl@idtype@#1@#2\endcsname{0}%
+ \ifx\@dtl@oldtype\@dtl@type
\else
- \expandafter\gdef\csname @dtl@idtype@#1@#2\endcsname{3}%
+ \toks@gconcat@middle@cx{dtlkeys@#1}%
+ {\@dtl@before}%
+ {%
+ \noexpand\db@plist@elt@w% start of key block
+ \noexpand\db@col@id@w \the\dtlcolumnnum
+ \noexpand\db@col@id@end@% column index
+ \noexpand\db@key@id@w #2\noexpand\db@key@id@end@% key id
+ \noexpand\db@type@id@w \@dtl@type
+ \noexpand\db@type@id@end@% data type
+ \noexpand\db@header@id@w \the\@dtl@colhead
+ \noexpand\db@header@id@end@% header
+ \noexpand\db@col@id@w \the\dtlcolumnnum
+ \noexpand\db@col@id@end@% column index
+ \noexpand\db@plist@elt@end@% end of key block
+ }%
+ {\@dtl@after}%
\fi
\fi
- \fi
-\fi
-}%
+ }%
+ {%
+ \expandafter\global\expandafter\advance
+ \csname dtlcols@#1\endcsname by 1\relax
+ \dtlcolumnnum=\csname dtlcols@#1\endcsname\relax
+ \expandafter\xdef\csname dtl@ci@#1@#2\endcsname{%
+ \number\dtlcolumnnum}%
+ \def\@dtl@tmp{#3}%
+ \ifx\@dtl@tmp\@empty
+ \edef\@dtl@type{}% don't know data type yet
+ \else
+ \@dtl@checknumerical{#3}%
+ \edef\@dtl@type{\number\@dtl@datatype}%
+ \fi
+ \toks@gput@right@cx{dtlkeys@#1}%
+ {%
+ \noexpand\db@plist@elt@w
+ \noexpand\db@col@id@w \the\dtlcolumnnum
+ \noexpand\db@col@id@end@
+ \noexpand\db@key@id@w #2\noexpand\db@key@id@end@
+ \noexpand\db@type@id@w \@dtl@type
+ \noexpand\db@type@id@end@
+ \noexpand\db@header@id@w #2\noexpand\db@header@id@end@
+ \noexpand\db@col@id@w \the\dtlcolumnnum
+ \noexpand\db@col@id@end@
+ \noexpand\db@plist@elt@end@
+ }%
+ }%
}
-\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}{}%
+\newcommand*{\DTLsetheader}{\@ifstar\@sDTLsetheader\@DTLsetheader}
+\newcommand*{\@DTLsetheader}[3]{%
+ \DTLifdbexists{#1}%
+ {%
+ \@sDTLifhaskey{#1}{#2}%
+ {%
+ \@sDTLsetheader{#1}{#2}{#3}%
+ }%
+ {%
+ \PackageError{datatool}{Database `#1' doesn't contain key
+ `#2'}{}%
+ }%
+ }%
+ {%
+ \PackageError{datatool}{Database `#1' doesn't exist}{}%
+ }%
+}
+\newcommand*{\@sDTLsetheader}[3]{%
+ \expandafter\dtlcolumnnum\expandafter
+ =\dtl@columnindex{#1}{#2}\relax
+ \@dtl@setheaderforindex{#1}{\dtlcolumnnum}{#3}%
+}
+\newcommand*{\@dtl@setheaderforindex}[3]{%
+ \edef\@dtl@dogetprops{\noexpand\@dtl@getprops
+ {\noexpand\@dtl@key}{\noexpand\@dtl@type}%
+ {\noexpand\@dtl@colhead}{\noexpand\@dtl@before}%
+ {\noexpand\@dtl@after}{\the\csname dtlkeys@#1\endcsname}%
+ {\number#2}}
+ \@dtl@dogetprops
+ \@dtl@colhead={#3}%
+ \edef\@dtl@colnum{\number#2}\relax
+ \toks@gconcat@middle@cx{dtlkeys@#1}%
+ {\@dtl@before}%
+ {%
+ \noexpand\db@plist@elt@w% start of block
+ \noexpand\db@col@id@w \@dtl@colnum
+ \noexpand\db@col@id@end@% index
+ \noexpand\db@key@id@w \@dtl@key\noexpand\db@key@id@end@% key
+ \noexpand\db@type@id@w \@dtl@type
+ \noexpand\db@type@id@end@% data type
+ \noexpand\db@header@id@w \the\@dtl@colhead
+ \noexpand\db@header@id@end@% header
+ \noexpand\db@col@id@w \@dtl@colnum
+ \noexpand\db@col@id@end@% index
+ \noexpand\db@plist@elt@end@% end of block
}%
- \if@endfor
+ {\@dtl@after}%
+}
+\newcommand{\DTLnewdbentry}{%
+ \@ifstar\@sDTLnewdbentry\@DTLnewdbentry
+}
+\newcommand{\@DTLnewdbentry}[3]{%
+ \DTLifdbexists{#1}%
+ {\@sDTLnewdbentry{#1}{#2}{#3}}%
+ {\PackageError{datatool}{Can't add new entry to database `#1':
+ database doesn't exist}{}}%
+}
+\newcommand*{\@sDTLnewdbentry}[3]{%
+ \@dtl@updatekeys{#1}{#2}{#3}%
+ \expandafter\dtlcolumnnum\expandafter
+ =\dtl@columnindex{#1}{#2}\relax
+ \edef\dtl@dogetrow{\noexpand\dtlgetrow{#1}%
+ {\number\csname dtlrows@#1\endcsname}}%
+ \dtl@dogetrow
+ \edef\dtl@dogetentry{\noexpand\dtlgetentryfromcurrentrow
+ {\noexpand\dtl@entry}{\number\dtlcolumnnum}%
+ }%
+ \dtl@dogetentry
+ \ifx\dtl@entry\dtlnovalue
+ \@dtl@toks{#3}%
+ \toks@gconcat@middle@cx{dtldb@#1}%
+ {\dtlbeforerow}%
+ {%
+ \noexpand\db@row@elt@w%
+ \noexpand\db@row@id@w \number\csname dtlrows@#1\endcsname
+ \noexpand\db@row@id@end@%
+ \the\dtlcurrentrow
+ \noexpand\db@col@id@w \number\dtlcolumnnum
+ \noexpand\db@col@id@end@%
+ \noexpand\db@col@elt@w \the\@dtl@toks
+ \noexpand\db@col@elt@end@%
+ \noexpand\db@col@id@w \number\dtlcolumnnum
+ \noexpand\db@col@id@end@%
+ \noexpand\db@row@id@w \number\csname dtlrows@#1\endcsname
+ \noexpand\db@row@id@end@%
+ \noexpand\db@row@elt@end@%
+ }%
+ {\dtlafterrow}%
+ \dtl@message{Added #2\space -> #3\space to database `#1'}%
\else
- \expandafter\xdef\csname dtlkeys@#2\endcsname{\the\@dtl@toks,#1}%
+ \PackageError{datatool}{Can't add entry with ID `#2' to
+ current row of database `#1'}{There is already an entry with
+ this ID in the current row}%
\fi
-\fi
}
-\newcommand*{\@dtl@getidtype}[2]{%
-\csname @dtl@idtype@#1@#2\endcsname}
\newcommand{\DTLifdbexists}[3]{%
-\@ifundefined{dtldb@#1}{#3}{#2}}
-\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
-}
-\newcommand*{\dtl@getentryid}[2]{\expandafter\@dtl@getentryid#1#2}
-\long\def\@dtl@getentryid#1#2#3{\def#3{#1}}
-\newcommand*{\dtl@getentryvalue}[2]{%
-\expandafter\@dtl@getentryvalue#1#2}
-\long\def\@dtl@getentryvalue#1#2#3{\gdef#3{#2}}
-\global\newcount\dtlforeachlevel
+ \@ifundefined{dtldb@#1}{#3}{#2}}
+\newcommand*{\@dtl@assign}[2]{%
+ \@dtl@assigncmd#1,\@nil\@@{#2}%
+}
+\def\@dtl@assigncmd#1=#2,#3\@@#4{%
+ \@sDTLifhaskey{#4}{#2}%
+ {%
+ \edef\@dtl@dogetentry{%
+ \noexpand\dtlgetentryfromcurrentrow
+ {\noexpand#1}{\dtl@columnindex{#4}{#2}}}%
+ \@dtl@dogetentry
+ \ifx#1\dtlnovalue
+ \@@dtl@setnull{#1}{#2}%
+ \fi
+ \global\let#1=#1\relax
+ }%
+ {%
+ \PackageError{datatool}{Can't assign \string#1\space: there
+ is no key `#2' in data base `#4'}{}%
+ \global\let#1\DTLstringnull
+ }%
+ \def\dtl@tmp{#3}%
+ \ifx\@nnil\dtl@tmp
+ \let\@dtl@next\@dtl@assigncmdnoop
+ \else
+ \let\@dtl@next\@dtl@assigncmd
+ \fi
+ \@dtl@next#3\@@{#4}%
+}
+\def\@dtl@assigncmdnoop#1\@@#2{}
+\newcommand*{\@dtl@setnull}[2]{%
+ \@sDTLifhaskey{\@dtl@dbname}{#2}%
+ {%
+ \@@dtl@setnull{#1}{#2}%
+ }%
+ {%
+ \global\let#1=\DTLstringnull
+ }%
+}
+\newcommand*{\@@dtl@setnull}[2]{%
+ \@sdtlgetdatatype{\@dtl@type}{\@dtl@dbname}{#2}%
+ \ifnum0\@dtl@type=0\relax
+ \global\let#1=\DTLstringnull
+ \else
+ \global\let#1=\DTLnumbernull
+ \fi
+}
+\newcommand*{\DTLstringnull}{NULL}
+\newcommand*{\DTLnumbernull}{0}
+\newcommand*{\DTLifnull}[3]{%
+ \ifx\DTLstringnull#1\relax
+ #2%
+ \else
+ \ifx\DTLnumbernull#1\relax
+ #2%
+ \else
+ #3%
+ \fi
+ \fi
+}
+\def\@dtlnovalue{Undefined Value}
+\def\dtlnovalue{\@dtlnovalue}
+\newcommand*{\DTLgetkeydata}{%
+ \@ifstar\@sdtlgetkeydata\@dtlgetkeydata
+}
+\newcommand*{\@dtlgetkeydata}[5]{%
+ \DTLifdbexists{#2}%
+ {%
+ \@sDTLifhaskey{#2}{#1}%
+ {%
+ \@sdtlgetkeydata{#1}{#2}{#3}{#4}{#5}%
+ }%
+ {%
+ \PackageError{datatool}{Key `#1' not defined in database
+ `#2'}{}%
+ }%
+ }%
+ {%
+ \PackageError{datatool}{Database `#2' doesn't exist}{}%
+ }%
+}
+\newcommand*{\@sdtlgetkeydata}[5]{%
+ \@sdtl@getcolumnindex{#3}{#2}{#1}%
+ \edef\@dtl@dogetkeydata{\noexpand\@dtl@getprops
+ {\noexpand\@dtl@key}{\noexpand#4}{\noexpand\@dtl@colhead}%
+ {\noexpand\@dtl@before}{\noexpand\@dtl@after}%
+ {\expandafter\the\csname dtlkeys@#2\endcsname}%
+ {#3}}%
+ \@dtl@dogetkeydata
+ \edef#5{\the\@dtl@toks}%
+}
+\newcommand{\dtl@gathervalues}[3][key]{%
+ \dtlforeachkey(\@dtl@key,\@dtl@col,\@dtl@type,\@dtl@head)\in{#2}\do
+ {%
+ \dtlgetentryfromrow{\@dtl@tmp}{\@dtl@col}{\dtlcurrentrow}%
+ \ifx\@dtl@tmp\dtlnovalue
+ \@dtl@setnull{\@dtl@tmp}{\@dtl@key}%
+ \fi
+ \expandafter\let\csname @dtl@#1@\@dtl@key\endcsname\@dtl@tmp
+ }%
+}
+\newtoks\dtlcurrentrow
+\newtoks\dtlbeforerow
+\newtoks\dtlafterrow
+\newcommand*{\dtlgetrow}[2]{%
+ \expandafter\toks@\expandafter=\csname dtldb@#1\endcsname
+ \edef\@dtl@dogetrow{\noexpand\@dtlgetrow{\the\toks@}{\number#2}}%
+ \@dtl@dogetrow
+}
+\newcommand*{\@dtlgetrow}[2]{%
+ \def\@dtl@getrow##1% before stuff
+ \db@row@elt@w% start of the row
+ \db@row@id@w #2\db@row@id@end@% row id
+ ##2%
+ \db@row@id@w #2\db@row@id@end@% row id
+ \db@row@elt@end@% end of the row
+ ##3% after stuff
+ \q@nil{\dtlbeforerow={##1}\dtlcurrentrow={##2}\dtlafterrow={##3}}%
+ \@dtl@getrow#1\q@nil
+}
+\newcommand*{\dtlgetentryfromcurrentrow}[2]{%
+ \dtlgetentryfromrow{#1}{#2}{\dtlcurrentrow}%
+}
+\newcommand*{\dtlgetentryfromrow}[3]{%
+ \edef\@dtl@do@getentry{\noexpand\dtl@getentryfromrow
+ {\noexpand#1}{\number#2}{\the#3}}%
+ \@dtl@do@getentry
+}
+\newcommand*{\dtl@getentryfromrow}[3]{%
+ \def\dtl@dogetentry##1% before stuff
+ \db@col@id@w #2\db@col@id@end@% Column id
+ \db@col@elt@w ##2\db@col@elt@end@% Value
+ \db@col@id@w #2\db@col@id@end@% Column id
+ ##3% Remaining stuff
+ \q@nil{\def#1{##2}}%
+ \dtl@dogetentry#3%
+ \db@col@id@w #2\db@col@id@end@%
+ \db@col@elt@w \@dtlnovalue\db@col@elt@end@%
+ \db@col@id@w #2\db@col@id@end@%
+ \q@nil
+}
+\newcommand*{\DTLgetvalue}[4]{%
+ \edef\dtl@dogetvalue{\noexpand\dtl@getvalue{\noexpand#1}{#2}%
+ {\number#3}{\number#4}}%
+ \dtl@dogetvalue
+}
+\newcommand*{\dtl@getvalue}[4]{%
+ \def\@dtl@getvalue ##1% stuff before row <r>
+ \db@row@id@w #3\db@row@id@end@% row <r> id
+ ##2% stuff in row <r> before column <c>
+ \db@col@id@w #4\db@col@id@end@% column <c> id
+ \db@col@elt@w ##3\db@col@elt@end@% value
+ ##4% stuff after value
+ \q@nil{\def#1{##3}}%
+ \toks@=\csname dtldb@#2\endcsname
+ \expandafter\@dtl@getvalue\the\toks@% contents of data base
+ \db@row@id@w #3\db@row@id@end@%
+ \db@col@id@w #4\db@col@id@end@%
+ \db@col@elt@w \@dtlnovalue\db@col@elt@end@% undefined value
+ \q@nil
+ \ifx#1\dtlnovalue
+ \PackageError{datatool}{There is no element at (row=#3,
+ column=#4) in database `#2'}{}%
+ \fi
+}
+\newcommand*{\DTLgetlocation}[4]{%
+ \def\@dtl@getlocation##1% stuff before value
+ \db@col@elt@w #4\db@col@elt@end@% value
+ \db@col@id@w ##2\db@col@id@end@% column id
+ ##3% stuff after this column
+ \db@row@id@w ##4\db@row@id@end@% row id
+ ##5% stuff after row
+ \q@nil{\def#1{##4}\def#2{##2}}%
+ \toks@=\csname dtldb@#3\endcsname
+ \expandafter\@dtl@getlocation\the\toks@% contents of data base
+ \db@col@elt@w #4\db@col@elt@end@% value
+ \db@col@id@w \@dtlnovalue\db@col@id@end@% undefined column id
+ \db@row@id@w \@dtlnovalue\db@row@id@end@% undefined row id
+ \q@nil
+ \ifx#1\dtlnovalue
+ \PackageError{datatool}{There is no element `#4' in
+ database `#3'}{}%
+ \fi
+}
+
+\newcommand*{\dtlbreak}{%
+ \PackageError{datatool}{Can't break out of anything}{}%
+}
+\long\def\dtlforint#1=#2\to#3\step#4\do#5{%
+ \let\@dtl@orgbreak\dtlbreak
+ \def\@dtl@endloophook{}%
+ \def\dtlbreak{\def\@dtl@endloophook{#1=#3}}%
+ #1=#2\relax
+ \ifnum#4<0\relax
+ \whiledo{\(#1>#3\)\TE@or\(#1=#3\)}%
+ {%
+ #5%
+ \@dtl@endloophook
+ \advance#1 by #4\relax
+ }%
+ \else
+ \whiledo{\(#1<#3\)\TE@or\(#1=#3\)}%
+ {%
+ #5%
+ \@dtl@endloophook
+ \advance#1 by #4\relax
+ }%
+ \fi
+ \let\dtlbreak\@dtl@orgbreak
+}
+\newcount\@dtl@foreach@level
+\long\def\dtlgforint#1=#2\to#3\step#4\do#5{%
+ \global#1=#2\relax
+ \global\advance\@dtl@foreach@level by 1\relax
+ \expandafter\global\expandafter
+ \let\csname @dtl@endhook@\the\@dtl@foreach@level\endcsname
+ \relax
+ \expandafter\global\expandafter
+ \let\csname @dtl@break@\the\@dtl@foreach@level\endcsname
+ \dtlbreak
+ \gdef\dtlbreak{\expandafter
+ \gdef\csname @dtl@endhook@\the\@dtl@foreach@level\endcsname{%
+ #1=#3}}%
+ \ifnum#4<0\relax
+ \whiledo{\(#1>#3\)\TE@or\(#1=#3\)}%
+ {%
+ #5%
+ \csname @dtl@endhook@\the\@dtl@foreach@level\endcsname
+ \global\advance#1 by #4\relax
+ }%
+ \else
+ \whiledo{\(#1<#3\)\TE@or\(#1=#3\)}%
+ {%
+ #5%
+ \csname @dtl@endhook@\the\@dtl@foreach@level\endcsname
+ \global\advance#1 by #4\relax
+ }%
+ \fi
+ \expandafter\global\expandafter\let\expandafter\dtlbreak
+ \csname @dtl@break@\the\@dtl@foreach@level\endcsname
+ \global\advance\@dtl@foreach@level by -1\relax
+}
+\long\def\@dtlforeachrow(#1,#2)\in#3\do#4{%
+ \edef\dtl@tmp{\expandafter\the\csname dtldb@#3\endcsname}%
+ \expandafter\@dtl@foreachrow\dtl@tmp
+ \db@row@elt@w%
+ \db@row@id@w \@nil\db@row@id@end@%
+ \db@row@id@w \@nil\db@row@id@end@%
+ \db@row@elt@end@%
+ \@@{#1}{#2}{#4}\q@nil
+}
+\long\def\@dtl@foreachrow\db@row@elt@w%
+\db@row@id@w #1\db@row@id@end@%
+#2\db@row@id@w #3\db@row@id@end@%
+\db@row@elt@end@#4\@@#5#6#7\q@nil{%
+ \gdef#5{#1}%
+ \gdef\@dtl@loopbody{#7}%
+ \global\advance\@dtl@foreach@level by 1\relax
+ \ifx#5\@nnil
+ \expandafter\global\expandafter
+ \let\csname @dtl@foreachnext\the\@dtl@foreach@level\endcsname
+ =\@dtl@foreachnoop
+ \else
+ \gdef#6{#2}%
+ \expandafter\let
+ \csname @dtl@break@\the\@dtl@foreach@level\endcsname
+ \dtlbreak
+ \gdef\dtlbreak{\expandafter\global\expandafter
+ \let\csname @dtl@foreachnext\the\@dtl@foreach@level\endcsname
+ =\@dtl@foreachnoop}%
+ \expandafter\global\expandafter
+ \let\csname @dtl@foreachnext\the\@dtl@foreach@level\endcsname
+ =\@dtl@foreachrow
+ \@dtl@loopbody
+ \expandafter\let\expandafter\dtlbreak
+ \csname @dtl@break@\the\@dtl@foreach@level\endcsname
+ \fi
+ \expandafter\let\expandafter\@dtl@foreachnext
+ \csname @dtl@foreachnext\the\@dtl@foreach@level\endcsname
+ \global\advance\@dtl@foreach@level by -1\relax
+ \@dtl@foreachnext#4\@@{#5}{#6}{#7}\q@nil
+}
+\long\def\@dtl@foreachnoop#1\@@#2\q@nil{}
+\long\def\dtlforeachkey(#1,#2,#3,#4)\in#5\do#6{%
+ \gdef\@dtl@loopbody{#6}%
+ \edef\@dtl@keys{\expandafter\the\csname dtlkeys@#5\endcsname}%
+ \expandafter\@dtl@foreachkey\@dtl@keys
+ \db@plist@elt@w%
+ \db@col@id@w -1\db@col@id@end@%
+ \db@key@id@w \db@key@id@end@%
+ \db@type@id@w \db@type@id@end@%
+ \db@header@id@w \db@header@id@end@%
+ \db@col@id@w -1\db@col@id@end@%
+ \db@plist@elt@end@%
+ \@@{\@dtl@updatefkcs{#1}{#2}{#3}{#4}}\q@nil
+}
+\newcommand*{\@dtl@updatefkcs}[8]{%
+ \gdef#1{#5}%
+ \gdef#2{#6}%
+ \gdef#3{#7}%
+ \gdef#4{#8}%
+}
+\long\def\@dtl@foreachkey\db@plist@elt@w%
+\db@col@id@w #1\db@col@id@end@%
+\db@key@id@w #2\db@key@id@end@%
+\db@type@id@w #3\db@type@id@end@%
+\db@header@id@w #4\db@header@id@end@%
+\db@col@id@w #5\db@col@id@end@%
+\db@plist@elt@end@#6\@@#7\q@nil{%
+ \ifnum#1=-1\relax
+ \let\@dtl@foreachnext\@dtl@foreachnoop
+ \else
+ #7{#2}{#1}{#3}{#4}%
+ \global\advance\@dtl@foreach@level by 1\relax
+ \expandafter\let
+ \csname @dtl@break@\the\@dtl@foreach@level\endcsname
+ \dtlbreak
+ \gdef\dtlbreak{\expandafter\global\expandafter
+ \let\csname @dtl@foreachnext\the\@dtl@foreach@level\endcsname
+ =\@dtl@foreachnoop}%
+ \expandafter\global\expandafter
+ \let\csname @dtl@foreachnext\the\@dtl@foreach@level\endcsname
+ =\@dtl@foreachkey
+ \@dtl@loopbody
+ \expandafter\let\expandafter\@dtl@foreachnext
+ \csname @dtl@foreachnext\the\@dtl@foreach@level\endcsname
+ \expandafter\let\expandafter\dtlbreak
+ \csname @dtl@break@\the\@dtl@foreach@level\endcsname
+ \global\advance\@dtl@foreach@level by -1\relax
+ \fi
+ \@dtl@foreachnext#6\@@{#7}\q@nil
+}
+\newcommand*{\dtlforcolumn}{\@ifstar\@sdtlforcolumn\@dtlforcolumn}
+\newcommand{\@dtlforcolumn}[4]{%
+ \DTLifdbexists{#2}%
+ {%
+ \@dtlifhaskey{#2}{#3}%
+ {%
+ \@sdtlforcolumn{#1}{#2}{#3}{#4}%
+ }%
+ {%
+ \PackageError{datatool}{Database `#2' doesn't contain
+ key `#3'}{}%
+ }%
+ }%
+ {%
+ \PackageError{datatool}{Database `#2' doesn't exist}{}%
+ }%
+}
+\newcommand{\@sdtlforcolumn}[4]{%
+ \toks@{#4}%
+ \edef\@dtl@doforcol{\noexpand\dtl@forcolumn{\noexpand#1}%
+ {\expandafter\the\csname dtldb@#2\endcsname}%
+ {\dtl@columnindex{#2}{#3}}{\the\toks@}%
+ }%
+ \@dtl@doforcol%
+}
+\newcommand*{\dtlforcolumnidx}{%
+ \@ifstar\@sdtlforcolumnidx\@dtlforcolumnidx
+}
+\newcommand{\@dtlforcolumnidx}[4]{%
+ \DTLifdbexists{#2}%
+ {%
+ \expandafter\ifnum\csname dtlcols@#2\endcsname<#3\relax
+ \PackageError{datatool}{Column index \number#3\space out of
+ bounds for database `#2'}{Database `#2' only has
+ \expandafter\number\csname dtlcols@#2\endcsname\space
+ columns}%
+ \else
+ \ifnum#3<1\relax
+ \PackageError{datatool}{Column index \number#3\space out of
+ bounds for database `#2'}{Indices start from 1}%
+ \else
+ \@sdtlforcolumnidx{#1}{#2}{#3}{#4}%
+ \fi
+ \fi
+ }%
+ {%
+ \PackageError{datatool}{Database `#2' doesn't exist}{}%
+ }%
+}
+\newcommand{\@sdtlforcolumnidx}[4]{%
+ \toks@{#4}%
+ \edef\@dtl@doforcol{\noexpand\dtl@forcolumn{\noexpand#1}%
+ {\expandafter\the\csname dtldb@#2\endcsname}%
+ {\number#3}{\the\toks@}%
+ }%
+ \@dtl@doforcol
+}
+\newcommand{\dtl@forcolumn}[4]{%
+ \let\@dtl@oldbreak\dtlbreak
+ \def\dtlbreak{\let\@dtl@forcolnext=\@dtl@forcolnoop}%
+ \def\@dtl@forcolumn##1% before stuff
+ \db@col@id@w #3\db@col@id@end@% column index
+ \db@col@elt@w ##2\db@col@elt@end@% entry
+ \db@col@id@w #3\db@col@id@end@% column index
+ ##3% after stuff
+ \q@nil{%
+ \def#1{##2}% assign value to <cs>
+ \ifx#1\@nnil
+ \let\@dtl@forcolnext=\@dtl@forcolnoop
+ \else
+ #4%
+ \let\@dtl@forcolnext=\@dtl@forcolumn
+ \fi
+ \@dtl@forcolnext##3\q@nil
+ }%
+ \@dtl@forcolumn#2%
+ \db@col@id@w #3\db@col@id@end@%
+ \db@col@elt@w \@nil\db@col@elt@end@%
+ \db@col@id@w #3\db@col@id@end@\q@nil
+ \let\dtlbreak\@dtl@oldbreak
+}
+\def\@dtl@forcolnoop#1\q@nil{}
+
+\newcount\dtlforeachlevel
\newcounter{DTLrowi}
\newcounter{DTLrowii}
\newcounter{DTLrowiii}
@@ -1520,6 +2168,18 @@ the current row}}{%
\def\theHDTLrowi{\theHDTLrow.\arabic{DTLrowi}}
\def\theHDTLrowii{\theHDTLrowi.\arabic{DTLrowii}}
\def\theHDTLrowiii{\theHDTLrowii.\arabic{DTLrowiii}}
+\newcount\dtl@rowi
+\newcount\dtl@rowii
+\newcount\dtl@rowiii
+\newtoks\@dtl@curi
+\newtoks\@dtl@previ
+\newtoks\@dtl@nexti
+\newtoks\@dtl@curii
+\newtoks\@dtl@previi
+\newtoks\@dtl@nextii
+\newtoks\@dtl@curiii
+\newtoks\@dtl@previii
+\newtoks\@dtl@nextiii
\newcommand*{\DTLsavelastrowcount}[1]{%
\ifnum\dtlforeachlevel>2\relax
\def#1{0}%
@@ -1535,492 +2195,1098 @@ the current row}}{%
\fi}
\newcommand*{\DTLforeach}{\@ifstar\@sDTLforeach\@DTLforeach}
\newcommand{\@DTLforeach}[4][\boolean{true}]{%
-\DTLifdbexists{#2}{%
-\refstepcounter{DTLrow}%
-\global\c@DTLrow=\c@DTLrow
-\gdef\@dtl@dbname{#2}%
-\global\advance\dtlforeachlevel by 1\relax
-\ifnum\dtlforeachlevel>3\relax
- \PackageError{datatool}{\string\DTLforeach\space nested too
-deeply}{}%
-\else
- \expandafter\global
- \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname = 0\relax
- \expandafter\global\expandafter\let
- \csname @dtl@foreachrows@\romannumeral\dtlforeachlevel\endcsname
- =\@empty
- \expandafter\global\expandafter\let
- \csname @dtl@dbname@\romannumeral\dtlforeachlevel\endcsname
- =\@dtl@dbname
- \expandafter\let\expandafter\@dtl@db\csname dtldb@#2\endcsname%
- \@for\@dtl@currentrow:=\@dtl@db\do{%
- \expandafter\global\expandafter
- \let\csname @dtl@thiscurrentrow@\romannumeral\dtlforeachlevel
- \endcsname=\@dtl@currentrow
- \global\let\@dtl@nextrow\@xfor@nextelement
- \ifx\relax#3\relax
- \else
- \@dtl@assign{#3}%
- \fi
- \ifthenelse{#1}{%
- \refstepcounter{DTLrow\romannumeral\dtlforeachlevel}%
- \expandafter\edef\expandafter\DTLcurrentindex\expandafter
- {\arabic{DTLrow\romannumeral\dtlforeachlevel}}%
- #4%
- }{}%
- \expandafter\let\expandafter\@dtl@thiscurrentrow
- \csname @dtl@thiscurrentrow@\romannumeral\dtlforeachlevel\endcsname
- \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}}%
+ \DTLifdbexists{#2}%
+ {%
+ \refstepcounter{DTLrow}%
+ \global\c@DTLrow=\c@DTLrow\relax
+ \gdef\@dtl@dbname{#2}%
+ \global\advance\dtlforeachlevel by 1\relax
+ \ifnum\dtlforeachlevel>3\relax
+ \PackageError{datatool}{\string\DTLforeach\space nested too
+ deeply}{Only 3 levels are allowed}%
\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}}%
+ \@DTLifdbempty{#2}%
+ {}%
+ {%
+ \expandafter\global
+ \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname
+ = 0\relax
+ \expandafter\global\expandafter\let%
+ \csname @dtl@iffirstrow\the\dtlforeachlevel\endcsname
+ \DTLiffirstrow
+ \gdef\DTLiffirstrow##1##2{%
+ \expandafter\ifnum
+ \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname
+ =1\relax
+ ##1%
+ \else
+ ##2%
+ \fi}%
+ \expandafter\global\expandafter\let%
+ \csname @dtl@iflastrow\the\dtlforeachlevel\endcsname
+ \DTLiflastrow
+ \gdef\DTLiflastrow##1##2{%
+ \expandafter\ifnum
+ \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname
+ =\csname dtlcols@#2\endcsname\relax
+ ##1%
+ \else
+ ##2%
+ \fi}%
+ \expandafter\global\expandafter\let%
+ \csname @dtl@ifoddrow\the\dtlforeachlevel\endcsname
+ \DTLifoddrow
+ \gdef\DTLifoddrow##1##2{%
+ \expandafter\ifodd
+ \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname
+ ##1%
+ \else
+ ##2%
+ \fi}%
+ \expandafter\global\expandafter\let
+ \csname @dtl@dbname@\romannumeral\dtlforeachlevel\endcsname
+ =\@dtl@dbname
+ \expandafter\global\expandafter\let
+ \csname @dtl@ro@\romannumeral\dtlforeachlevel\endcsname
+ = 0\relax
+ \dtlgforint
+ \csname dtl@row\romannumeral\dtlforeachlevel\endcsname
+ =1\to\csname dtlrows@#2\endcsname\step1\do
+ {%
+ \@dtl@tmpcount=
+ \csname dtl@row\romannumeral\dtlforeachlevel\endcsname
+ \edef\dtl@dogetrow{\noexpand\dtlgetrow{#2}%
+ {\number\@dtl@tmpcount}}%
+ \dtl@dogetrow
+ \expandafter\global
+ \csname @dtl@cur\romannumeral\dtlforeachlevel\endcsname
+ = \dtlcurrentrow
+ \expandafter\global
+ \csname @dtl@prev\romannumeral\dtlforeachlevel\endcsname
+ = \dtlbeforerow
+ \expandafter\global
+ \csname @dtl@next\romannumeral\dtlforeachlevel\endcsname
+ = \dtlafterrow
+ \ifx\relax#3\relax
+ \else
+ \@dtl@assign{#3}{#2}%
+ \fi
+ \ifthenelse{#1}%
+ {%
+ \refstepcounter{DTLrow\romannumeral\dtlforeachlevel}%
+ \expandafter\edef\expandafter\DTLcurrentindex%
+ \expandafter{%
+ \arabic{DTLrow\romannumeral\dtlforeachlevel}}%
+ #4%
+ \edef\@dtl@tmp{\expandafter\the
+ \csname @dtl@cur\romannumeral
+ \dtlforeachlevel\endcsname}%
+ \ifx\@dtl@tmp\@nnil
+ \expandafter\dtl@decrementrows\expandafter
+ {\csname @dtl@prev\romannumeral
+ \dtlforeachlevel\endcsname
+ }{\csname dtl@row\romannumeral
+ \dtlforeachlevel\endcsname}%
+ \expandafter\dtl@decrementrows\expandafter
+ {\csname @dtl@next\romannumeral
+ \dtlforeachlevel\endcsname
+ }{\csname dtl@row\romannumeral
+ \dtlforeachlevel\endcsname}%
+ \edef\@dtl@tmp{%
+ \expandafter\the
+ \csname @dtl@prev\romannumeral
+ \dtlforeachlevel\endcsname
+ \expandafter\the
+ \csname @dtl@next\romannumeral
+ \dtlforeachlevel\endcsname
+ }%
+ \expandafter\global\expandafter
+ \csname dtldb@#2\endcsname\expandafter{\@dtl@tmp}%
+ \expandafter\global\expandafter
+ \advance\csname dtlrows@#2\endcsname by -1\relax
+ \expandafter\global\expandafter
+ \advance\csname dtl@row\romannumeral
+ \dtlforeachlevel\endcsname by -1\relax
+ \else
+ \@dtl@before=\csname @dtl@prev\romannumeral
+ \dtlforeachlevel\endcsname
+ \@dtl@after=\csname @dtl@next\romannumeral
+ \dtlforeachlevel\endcsname
+ \toks@gconcat@middle@cx{dtldb@#2}%
+ {\@dtl@before}%
+ {%
+ \noexpand\db@row@elt@w%
+ \noexpand\db@row@id@w \expandafter\number
+ \csname dtl@row\romannumeral
+ \dtlforeachlevel\endcsname
+ \noexpand\db@row@id@end@%
+ \expandafter\the
+ \csname @dtl@cur\romannumeral
+ \dtlforeachlevel\endcsname
+ \noexpand\db@row@id@w \expandafter\number
+ \csname dtl@row\romannumeral
+ \dtlforeachlevel\endcsname
+ \noexpand\db@row@id@end@%
+ \noexpand\db@row@elt@end@%
+ }%
+ {\@dtl@after}%
+ \fi
+ }%
+ {}%
+ }%
+ \expandafter\global\expandafter\let\expandafter\DTLiffirstrow
+ \csname @dtl@iffirstrow\the\dtlforeachlevel\endcsname
+ \expandafter\global\expandafter\let\expandafter\DTLiflastrow
+ \csname @dtl@iflastrow\the\dtlforeachlevel\endcsname
+ \expandafter\global\expandafter\let\expandafter\DTLifoddrow
+ \csname @dtl@ifoddrow\the\dtlforeachlevel\endcsname
+ }%
\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}{}}%
+ \global\advance\dtlforeachlevel by -1\relax
+ }%
+ {%
+ \PackageError{datatool}{Database `#2' doesn't exist}{}%
+ }%
}
\newcommand{\@sDTLforeach}[4][\boolean{true}]{%
-\DTLifdbexists{#2}{%
-\refstepcounter{DTLrow}%
-\global\c@DTLrow=\c@DTLrow
-\gdef\@dtl@dbname{#2}%
-\global\advance\dtlforeachlevel by 1\relax
-\ifnum\dtlforeachlevel>3\relax
- \PackageError{datatool}{\string\DTLforeach\space nested too
-deeply}{}%
-\else
- \expandafter\global
- \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname = 0\relax
- \expandafter\global\expandafter\let
- \csname @dtl@dbname@\romannumeral\dtlforeachlevel\endcsname
- =\@nnil
- \expandafter\let\expandafter\@dtl@db\csname dtldb@#2\endcsname%
- \@for\@dtl@currentrow:=\@dtl@db\do{%
- \expandafter\global\expandafter
- \let\csname @dtl@thiscurrentrow@\romannumeral\dtlforeachlevel
- \endcsname=\@dtl@currentrow
- \global\let\@dtl@nextrow\@xfor@nextelement
- \ifx\relax#3\relax
+ \DTLifdbexists{#2}%
+ {%
+ \refstepcounter{DTLrow}%
+ \global\c@DTLrow=\c@DTLrow
+ \global\advance\dtlforeachlevel by 1\relax
+ \ifnum\dtlforeachlevel>3\relax
+ \PackageError{datatool}{\string\DTLforeach\space nested too
+ deeply}{Only 3 levels are allowed}%
+ \else
+ \@DTLifdbempty{#2}%
+ {}%
+ {%
+ \expandafter\global
+ \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname
+ = 0\relax
+ \expandafter\global\expandafter\let%
+ \csname @dtl@iffirstrow\the\dtlforeachlevel\endcsname
+ \DTLiffirstrow
+ \gdef\DTLiffirstrow##1##2{%
+ \expandafter\ifnum
+ \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname
+ =1\relax
+ ##1%
+ \else
+ ##2%
+ \fi}%
+ \expandafter\global\expandafter\let%
+ \csname @dtl@iflastrow\the\dtlforeachlevel\endcsname
+ \DTLiflastrow
+ \gdef\DTLiflastrow##1##2{%
+ \expandafter\ifnum
+ \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname
+ =\csname dtlcols@#2\endcsname\relax
+ ##1%
+ \else
+ ##2%
+ \fi}%
+ \expandafter\global\expandafter\let%
+ \csname @dtl@ifoddrow\the\dtlforeachlevel\endcsname
+ \DTLifoddrow
+ \gdef\DTLifoddrow##1##2{%
+ \expandafter\ifodd
+ \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname
+ ##1%
+ \else
+ ##2%
+ \fi}%
+ \expandafter\gdef\csname @dtl@dbname@\romannumeral
+ \dtlforeachlevel\endcsname{#2}%
+ \expandafter\global\expandafter\let
+ \csname @dtl@ro@\romannumeral\dtlforeachlevel\endcsname
+ = 1\relax
+ \@dtlforeachrow(\dtl@thisidx,\dtl@thisrow)\in{#2}\do%
+ {%
+ \csname dtl@row\romannumeral\dtlforeachlevel\endcsname
+ = \dtl@thisidx\relax
+ \expandafter\global
+ \csname @dtl@cur\romannumeral\dtlforeachlevel\endcsname
+ = \expandafter{\dtl@thisrow}%
+ \ifx\relax#3\relax
+ \else
+ \dtlcurrentrow=\expandafter{\dtl@thisrow}%
+ \@dtl@assign{#3}{#2}%
+ \fi
+ \ifthenelse{#1}%
+ {%
+ \refstepcounter{DTLrow\romannumeral\dtlforeachlevel}%
+ \expandafter\edef\expandafter\DTLcurrentindex%
+ \expandafter{%
+ \arabic{DTLrow\romannumeral\dtlforeachlevel}}%
+ #4%
+ }%
+ {}%
+ }%
+ \expandafter\global\expandafter\let\expandafter\DTLiffirstrow
+ \csname @dtl@iffirstrow\the\dtlforeachlevel\endcsname
+ \expandafter\global\expandafter\let\expandafter\DTLiflastrow
+ \csname @dtl@iflastrow\the\dtlforeachlevel\endcsname
+ \expandafter\global\expandafter\let\expandafter\DTLifoddrow
+ \csname @dtl@ifoddrow\the\dtlforeachlevel\endcsname
+ }%
+ \fi
+ \global\advance\dtlforeachlevel by -1\relax
+ }%
+ {%
+ \PackageError{datatool}{Database `#2' doesn't exist}{}%
+ }%
+}
+\newcommand*{\@dtlifreadonly}[2]{%
+ \expandafter\ifx
+ \csname @dtl@ro@\romannumeral\dtlforeachlevel\endcsname1\relax
+ #1%
\else
- \@dtl@assign{#3}%
+ #2%
\fi
- \ifthenelse{#1}{%
- \refstepcounter{DTLrow\romannumeral\dtlforeachlevel}%
- \expandafter\edef\expandafter\DTLcurrentindex\expandafter
- {\arabic{DTLrow\romannumeral\dtlforeachlevel}}%
- #4%
- }{}%
-\@endforfalse
-}%
-\fi
-\global\advance\dtlforeachlevel by -1\relax
-}{%
-\PackageError{datatool}{Database `#2' doesn't exist}{}}%
}
\newcommand*{\DTLappendtorow}[2]{%
-\ifnum\dtlforeachlevel=0\relax
- \PackageError{datatool}{\string\DTLappendtorow\space can only
- be used inside \string\DTLforeach}{}%
-\else
- \expandafter\let\expandafter\@dtl@thisdb
- \csname @dtl@dbname@\romannumeral\dtlforeachlevel\endcsname
- \ifx\@dtl@thisdb\@nnil
- \PackageError{datatool}{\string\DTLappendtorow\space can't
- be used inside \string\DTLforeach*}{The starred version of
- \string\DTLforeach\space is read only}%
- \else
- \expandafter\@dtl@toks\expandafter{#2}%
- \edef\@dtl@dbvalue{\the\@dtl@toks}%
- \edef\@dtl@dbid{#1}%
- \edef\@dtl@dbentry{{\@dtl@dbid}{\the\@dtl@toks}}%
- \expandafter\let\expandafter\@dtl@thisrow
- \csname @dtl@thiscurrentrow@\romannumeral\dtlforeachlevel\endcsname
- \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}}{%
- \expandafter\@dtl@toks\expandafter{\@dtl@dbentry}%
- \ifx\@dtl@thisrow\@empty
- \expandafter
- \xdef\csname @dtl@thiscurrentrow@\romannumeral\dtlforeachlevel\endcsname{%
- \the\@dtl@toks}%
+ \ifnum\dtlforeachlevel=0\relax
+ \PackageError{datatool}{\string\DTLappendrow\space can only be
+ used inside \string\DTLforeach}{}%
\else
- \expandafter\toks@\expandafter{\@dtl@thisrow}%
- \expandafter
- \xdef\csname @dtl@thiscurrentrow@\romannumeral\dtlforeachlevel\endcsname{%
- \the\toks@,\the\@dtl@toks}%
+ \expandafter\let\expandafter\@dtl@thisdb
+ \csname @dtl@dbname@\romannumeral\dtlforeachlevel\endcsname
+ \@dtlifreadonly
+ {%
+ \PackageError{datatool}{\string\DTLappendtorow\space can't
+ be used inside \DTLforeach*}{The starred version of
+ \string\DTLforeach\space is read only}%
+ }%
+ {%
+ \dtlrownum=
+ \csname dtl@row\romannumeral\dtlforeachlevel\endcsname\relax
+ \@dtl@updatekeys{\@dtl@thisdb}{#1}{#2}%
+ \expandafter\dtlcolumnnum\expandafter
+ =\dtl@columnindex{\@dtl@thisdb}{#1}\relax
+ \dtlcurrentrow =
+ \csname @dtl@cur\romannumeral\dtlforeachlevel\endcsname
+ \edef\dtl@dogetentry{\noexpand\dtlgetentryfromcurrentrow
+ {\noexpand\dtl@entry}{\number\dtlcolumnnum}%
+ }%
+ \dtl@dogetentry
+ \ifx\dtl@entry\dtlnovalue
+ \expandafter\@dtl@toks\expandafter{#2}%
+ \toks@gput@right@cx{@dtl@cur\romannumeral\dtlforeachlevel}%
+ {%
+ \noexpand\db@col@id@w \number\dtlcolumnnum
+ \noexpand\db@col@id@end@
+ \noexpand\db@col@elt@w \the\@dtl@toks
+ \noexpand\db@col@elt@end@
+ \noexpand\db@col@id@w \number\dtlcolumnnum
+ \noexpand\db@col@id@end@
+ }%
+ \dtl@message{Appended #1\space -> #2\space to database
+ `\@dtl@thisdb'}%
+ \else
+ \PackageError{datatool}{Can't append entry to row:
+ there is already an entry for key `#1' in this row}{}%
+ \fi
+ }%
\fi
- }
- \@dtl@setidtype{\@dtl@thisdb}{#1}{#2}%
- \expandafter\@dtl@setkeys\expandafter{#1}{\@dtl@thisdb}%
- \fi
-\fi
}
\newcommand*{\DTLremoveentryfromrow}[1]{%
-\ifnum\dtlforeachlevel=0\relax
- \PackageError{datatool}{\string\DTLremoveentryfromrow\space can only
- be used inside \string\DTLforeach}{}%
-\else
- \expandafter\let\expandafter\@dtl@thisdb
- \csname @dtl@dbname@\romannumeral\dtlforeachlevel\endcsname
- \ifx\@dtl@thisdb\@nnil
- \PackageError{datatool}{\string\DTLremoveentryfromrow\space can't
- be used inside \string\DTLforeach*}{The starred version of
- \string\DTLforeach\space is read only}%
+ \ifnum\dtlforeachlevel=0\relax
+ \PackageError{datatool}{\string\DTLremoventryfromrow\space
+ can only be used inside \string\DTLforeach}{}%
\else
- \expandafter\let\expandafter\@dtl@thisrow
- \csname @dtl@thiscurrentrow@\romannumeral\dtlforeachlevel\endcsname
- \dtl@ifrowcontains{#1}{\@dtl@thisrow}{%
- \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}{}%
- }%
+ \expandafter\let\expandafter\@dtl@thisdb
+ \csname @dtl@dbname@\romannumeral\dtlforeachlevel\endcsname
+ \@dtlifreadonly
+ {%
+ \PackageError{datatool}{\string\DTLremoveentryfromrow\space
+ can't be used inside \string\DTLforeach*}{The starred
+ version of \string\DTLforeach\space is read only}%
+ }%
+ {%
+ \dtlrownum=
+ \csname dtl@row\romannumeral\dtlforeachlevel\endcsname\relax
+ \@dtlifhaskey{\@dtl@thisdb}{#1}%
+ {%
+ \dtl@getcolumnindex{\thiscol}{\@dtl@thisdb}{#1}\relax
+ \dtlcolumnnum=\thiscol\relax
+ \dtlcurrentrow =
+ \csname @dtl@cur\romannumeral\dtlforeachlevel\endcsname
+ \edef\dtl@dogetentry{\noexpand\dtlgetentryfromcurrentrow
+ {\noexpand\dtl@entry}{\number\dtlcolumnnum}%
+ }%
+ \dtl@dogetentry
+ \ifx\dtl@entry\dtlnovalue
+ \PackageError{datatool}{Can't remove entry given by `#1'
+ from current row in database `\@dtl@thisdb': no such
+ entry}{The current row doesn't contain an entry for
+ key `#1'}%
+ \else
+ \edef\@dtl@dosplitrow{%
+ \noexpand\dtlsplitrow{\the\dtlcurrentrow}%
+ {\number\dtlcolumnnum}{\noexpand\dtl@pre}%
+ {\noexpand\dtl@post}%
+ }%
+ \@dtl@dosplitrow
+ \expandafter\@dtl@toks\expandafter{\dtl@pre}%
+ \expandafter\toks@\expandafter{\dtl@post}%
+ \edef\@dtl@tmp{\the\@dtl@toks \the\toks@}%
+ \dtlcurrentrow=\expandafter{\@dtl@tmp}%
+ \expandafter\global
+ \csname @dtl@cur\romannumeral\dtlforeachlevel\endcsname
+ = \dtlcurrentrow
+ \dtl@message{Removed entry given by #1\space from current
+ row of database `\@dtl@thisdb'}%
+ \fi
+ }%
+ {%
+ \PackageError{datatool}{Can't remove entry given by
+ `#1' - no such key exists}{}%
+ }%
+ }%
\fi
-\fi
}
\newcommand*{\DTLreplaceentryforrow}[2]{%
-\ifnum\dtlforeachlevel=0\relax
- \PackageError{datatool}{\string\DTLreplaceentryforrow\space can only
- be used inside \string\DTLforeach}{}%
-\else
- \expandafter\let\expandafter\@dtl@thisdb
- \csname @dtl@dbname@\romannumeral\dtlforeachlevel\endcsname
- \ifx\@dtl@thisdb\@nnil
- \PackageError{datatool}{\string\DTLreplaceentryforrow\space can't
- be used inside \string\DTLforeach*}{The starred version of
- \string\DTLforeach\space is read only}%
+ \ifnum\dtlforeachlevel=0\relax
+ \PackageError{datatool}{\string\DTLreplaceentryforrow\space
+ can only be used inside \string\DTLforeach}{}%
\else
- \expandafter\@dtl@toks\expandafter{#2}%
- \edef\@dtl@dbvalue{\the\@dtl@toks}%
- \edef\@dtl@dbid{#1}%
- \edef\dtl@newentry{{\@dtl@dbid}{\the\@dtl@toks}}%
- \expandafter\let\expandafter\@dtl@thisrow
- \csname @dtl@thiscurrentrow@\romannumeral\dtlforeachlevel\endcsname
- \dtl@ifrowcontains{#1}{\@dtl@thisrow}{%
- \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}{}%
- }%
+ \expandafter\let\expandafter\@dtl@thisdb
+ \csname @dtl@dbname@\romannumeral\dtlforeachlevel\endcsname
+ \@dtlifreadonly
+ {%
+ \PackageError{datatool}{\string\DTLreplaceentryforrow\space
+ can't be used inside \string\DTLforeach*}{The starred version
+ of \string\DTLforeach\space is read only}%
+ }%
+ {%
+ \dtlrownum=
+ \csname dtl@row\romannumeral\dtlforeachlevel\endcsname\relax
+ \@dtlifhaskey{\@dtl@thisdb}{#1}%
+ {%
+ \dtl@getcolumnindex{\thiscol}{\@dtl@thisdb}{#1}\relax
+ \dtlcolumnnum=\thiscol\relax
+ \dtlcurrentrow =
+ \csname @dtl@cur\romannumeral\dtlforeachlevel\endcsname
+ \edef\dtl@dogetentry{\noexpand\dtlgetentryfromcurrentrow
+ {\noexpand\dtl@entry}{\number\dtlcolumnnum}%
+ }%
+ \dtl@dogetentry
+ \ifx\dtl@entry\dtlnovalue
+ \PackageError{datatool}{Can't replace entry given by `#1'
+ from current row in database `\@dtl@thisdb': no such
+ entry}{The current row doesn't contain an entry for
+ key `#1'}%
+ \else
+ \edef\@dtl@dosplitrow{%
+ \noexpand\dtlsplitrow{\the\dtlcurrentrow}%
+ {\number\dtlcolumnnum}{\noexpand\dtl@pre}%
+ {\noexpand\dtl@post}%
+ }%
+ \@dtl@dosplitrow
+ \@dtl@toks{#2}% new value
+ \expandafter\@dtl@before\expandafter{\dtl@pre}%
+ \expandafter\@dtl@after\expandafter{\dtl@post}%
+ \toks@gconcat@middle@cx
+ {@dtl@cur\romannumeral\dtlforeachlevel}%
+ {\@dtl@before}%
+ {%
+ \noexpand\db@col@id@w \number\dtlcolumnnum
+ \noexpand\db@col@id@end@%
+ \noexpand\db@col@elt@w \the\@dtl@toks
+ \noexpand\db@col@elt@end@%
+ \noexpand\db@col@id@w \number\dtlcolumnnum
+ \noexpand\db@col@id@end@%
+ }%
+ {\@dtl@after}%
+ \dtl@message{Updated #1\space -> #2\space in database
+ `\@dtl@thisdb'}%
+ \fi
+ }%
+ {%
+ \PackageError{datatool}{Can't replace key `#1' - no such
+ key in database `\@dtl@thisdb'}{}%
+ }%
+ }%
\fi
-\fi
}
\newcommand*{\DTLremovecurrentrow}{%
-\ifnum\dtlforeachlevel=0\relax
- \PackageError{datatool}{\string\DTLremovecurrentrow\space can only
- be used inside \string\DTLforeach}{}%
-\else
- \expandafter\ifx
- \csname @dtl@dbname@\romannumeral\dtlforeachlevel\endcsname\@nnil
- \PackageError{datatool}{\string\DTLremovecurrentrow\space can't
- be used inside \string\DTLforeach*}{The starred version of
- \string\DTLforeach\space is read only}%
+ \ifnum\dtlforeachlevel=0\relax
+ \PackageError{datatool}{\string\DTLremovecurrentrow\space can
+ only be used inside \string\DTLforeach}{}%
\else
- \expandafter\let
- \csname @dtl@thiscurrentrow@\romannumeral\dtlforeachlevel\endcsname
- =\@empty
+ \expandafter\let\expandafter\@dtl@thisdb
+ \csname @dtl@dbname@\romannumeral\dtlforeachlevel\endcsname
+ \@dtlifreadonly
+ {%
+ \PackageError{datatool}{\string\DTLreplaceentryforrow\space
+ can't be used inside \string\DTLforeach*}{The starred version
+ of \string\DTLforeach\space is read only}%
+ }%
+ {%
+ \expandafter\global
+ \csname @dtl@cur\romannumeral\dtlforeachlevel\endcsname
+ ={\@nil}%
+ }%
\fi
-\fi
+}
+\newcommand{\DTLaddentryforrow}[5]{%
+ \DTLifdbexists{#1}%
+ {
+ \def\@dtl@notdone{\PackageError{datatool}{Unable to add entry
+ given by key `#4': condition not met for any row in database
+ `#1'}{}}%
+ \DTLforeach[#3]{#1}{#2}%
+ {%
+ \DTLappendtorow{#4}{#5}%
+ \let\@dtl@notdone\relax
+ \dtlbreak
+ }%
+ \@dtl@notdone
+ }%
+ {%
+ \PackageError{datatool}{Unable to add entry given by key `#4':
+ database `#1' doesn't exist}{}%
+ }%
}
\newcommand*{\DTLforeachkeyinrow}[2]{%
-\ifnum\dtlforeachlevel=0\relax
- \PackageError{datatool}{\string\DTLforeachkeyinrow\space can only
- be used inside \string\DTLforeach}{}%
-\else
- \expandafter\let\expandafter\@dtl@thisrow
- \csname @dtl@thiscurrentrow@\romannumeral\dtlforeachlevel\endcsname
- \@for\dtl@thisentry:=\@dtl@thisrow\do{%
- \dtl@getentryvalue\dtl@thisentry{#1}%
- #2%
- }%
-\fi
+ \ifnum\dtlforeachlevel=0\relax
+ \PackageError{datatool}{\string\DTLforeachkeyinrow\space can only
+ be used inside \string\DTLforeach}{}%
+ \else
+ \expandafter\let\expandafter\@dtl@thisdb
+ \csname @dtl@dbname@\romannumeral\dtlforeachlevel\endcsname
+ \dtlforeachkey(\dtlkey,\dtlcol,\dtltype,\dtlheader)\in
+ \@dtl@thisdb\do{%
+ \dtlcurrentrow =
+ \csname @dtl@cur\romannumeral\dtlforeachlevel\endcsname
+ \edef\dtl@dogetentry{\noexpand\dtlgetentryfromcurrentrow
+ {\noexpand#1}{\dtlcol}}%
+ \dtl@dogetentry
+ \ifx#1\dtlnovalue
+ \ifnum0\dtltype=0\relax
+ \let#1=\DTLstringnull
+ \else
+ \let#1=\DTLnumbernull
+ \fi
+ \fi
+ \global\let#1#1%
+ \def\@dtl@loop@body{#2}%
+ \@dtl@loop@body
+ }%
+ \fi
}
-\newcommand{\DTLaddentryforrow}[5]{%
-\gdef\@dtl@dbname{#1}%
-\DTLifdbexists{#1}{%
- \expandafter\@dtl@toks\expandafter{#5}%
- \edef\@dtl@dbvalue{\the\@dtl@toks}%
- \edef\@dtl@dbid{#4}%
- \edef\@dtl@dbentry{{\@dtl@dbid}{\the\@dtl@toks}}%
- \expandafter
- \let\expandafter\@dtl@db\csname dtldb@\@dtl@dbname\endcsname%
- \let\@dtl@prerow=\@empty
- \@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}}%
+\newcommand*{\dtlbetweencols}{}
+\newcommand*{\dtlbeforecols}{}
+\newcommand*{\dtlaftercols}{}
+\newcommand*{\dtlstringalign}{l}
+\newcommand*{\dtlintalign}{r}
+\newcommand*{\dtlrealalign}{r}
+\newcommand*{\dtlcurrencyalign}{r}
+\newcommand*{\dtladdalign}[4]{%
+ \ifnum#3=1\relax
+ \protected@edef#1{\dtlbeforecols}%
+ \else
+ \protected@edef#1{#1\dtlbetweencols}%
+ \fi
+ \ifx\@empty#2\@empty
+ \protected@edef#1{#1c}%
+ \else
+ \ifcase#2\relax
+ \protected@edef#1{#1\dtlstringalign}%
+ \or
+ \protected@edef#1{#1\dtlintalign}%
+ \or
+ \protected@edef#1{#1\dtlrealalign}%
+ \or
+ \protected@edef#1{#1\dtlcurrencyalign}%
\else
- \expandafter\toks@\expandafter{\@dtl@currentrow}%
- \edef\@dtl@currentrow{\the\toks@,{\the\@dtl@toks}}%
+ \protected@edef#1{#1c}%
+ \PackageError{datatool}{Unknown data type `#2'}{}%
\fi
- \@endfortrue
- }{%
+ \fi
+ \ifnum#3=#4\relax
+ \protected@edef#1{#1\dtlaftercols}%
+ \fi
+}
+\newcommand*{\dtlheaderformat}[1]{\null\hfil\textbf{#1}\hfil\null}
+\newcommand*{\dtlstringformat}[1]{#1}
+\newcommand*{\dtlintformat}[1]{#1}
+\newcommand*{\dtlrealformat}[1]{#1}
+\newcommand*{\dtlcurrencyformat}[1]{#1}
+\newcommand*{\dtldisplaystarttab}{}
+\newcommand*{\dtldisplayendtab}{}
+\newcommand*{\dtldisplayafterhead}{}
+\newcommand*{\dtldisplaystartrow}{}
+
+\newcommand*{\DTLdisplaydb}[1]{%
+ \def\@dtl@doamp{\gdef\@dtl@doamp{&}}
+ \def\@dtl@resetdoamp{\gdef\@dtl@doamp{\gdef\@dtl@doamp{&}}}
+ \edef\@dtl@maxcols{\expandafter\number
+ \csname dtlcols@#1\endcsname}%
+ \def\@dtl@tabargs{}%
+ \dtlforeachkey(\@dtl@key,\@dtl@idx,\@dtl@type,\@dtl@head)%
+ \in{#1}\do
+ {%
+ \dtladdalign\@dtl@tabargs\@dtl@type\@dtl@idx\@dtl@maxcols
+ }%
+ \edef\@dtl@dobegintab{\noexpand\begin{tabular}{\@dtl@tabargs}}%
+ \@dtl@dobegintab
+ \dtldisplaystarttab
+ \@dtl@resetdoamp
+ \dtlforeachkey(\@dtl@key,\@dtl@idx,\@dtl@type,\@dtl@head)%
+ \in{#1}\do
+ {%
+ \@dtl@doamp
+ \dtlheaderformat{\@dtl@head}%
+ }%
+ \\%
+ \dtldisplayafterhead
+ \@dtl@resetdoamp
+ \DTLforeach*{#1}{}{%
+ \DTLiffirstrow{}{\\\dtldisplaystartrow}%
+ \@dtl@resetdoamp
+ \DTLforeachkeyinrow{\@dtl@val}%
+ {%
+ \global\let\@dtl@val\@dtl@val
+ \@dtl@doamp
+ \@dtl@datatype=0\dtltype\relax
+ \ifcase\@dtl@datatype
+ \dtlstringformat\@dtl@val
+ \or
+ \dtlintformat\@dtl@val
+ \or
+ \dtlrealformat\@dtl@val
+ \or
+ \dtlcurrencyformat\@dtl@val
+ \else
+ \@dtl@val
+ \fi
+ }%
+ }%
+ \dtldisplayendtab
+ \end{tabular}%
+}
+\define@key{displaylong}{caption}{\def\@dtl@cap{#1}}
+\define@key{displaylong}{contcaption}{\def\@dtl@contcap{#1}}
+\define@key{displaylong}{shortcaption}{\def\@dtl@shortcap{#1}}
+\define@key{displaylong}{label}{\def\@dtl@label{#1}}
+\define@key{displaylong}{foot}{\def\@dtl@foot{#1}}
+\define@key{displaylong}{lastfoot}{\def\@dtl@lastfoot{#1}}
+\newcommand*{\@dtl@resetdostartrow}{%
+ \gdef\@dtl@dostartrow{%
+ \gdef\@dtl@dostartrow{\\\dtldisplaystartrow}}%
+}
+\newcommand*{\DTLdisplaylongdb}[2][]{%
+ \def\@dtl@cap{\@nil}%
+ \def\@dtl@contcap{\@nil}%
+ \def\@dtl@label{\@nil}%
+ \def\@dtl@shortcap{\@dtl@cap}%
+ \def\@dtl@foot{\@nil}%
+ \def\@dtl@lastfoot{\@nil}%
+ \setkeys{displaylong}{#1}%
+ \def\@dtl@doamp{\gdef\@dtl@doamp{&}}
+ \def\@dtl@resetdoamp{\gdef\@dtl@doamp{\gdef\@dtl@doamp{&}}}
+ \@dtl@resetdostartrow
+ \edef\@dtl@maxcols{\expandafter\number
+ \csname dtlcols@#2\endcsname}%
+ \def\@dtl@tabargs{}%
+ \dtlforeachkey(\@dtl@key,\@dtl@idx,\@dtl@type,\@dtl@head)%
+ \in{#2}\do
+ {%
+ \dtladdalign\@dtl@tabargs\@dtl@type\@dtl@idx\@dtl@maxcols
}%
- \expandafter\@dtl@toks\expandafter{\@dtl@currentrow}%
- \ifx\@dtl@prerow\@empty
- \edef\@dtl@prerow{{\the\@dtl@toks}}%
+ \edef\@dtl@dobegintab{\noexpand\begin{longtable}{\@dtl@tabargs}}%
+ \@dtl@dobegintab
+ \dtldisplaystarttab
+ \ifx\@dtl@foot\@nnil
\else
- \expandafter\toks@\expandafter{\@dtl@prerow}%
- \edef\@dtl@prerow{\the\toks@,{\the\@dtl@toks}}%
+ \@dtl@foot\endfoot
\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}{}}%
+ \ifx\@dtl@lastfoot\@nnil
+ \else
+ \@dtl@lastfoot\endlastfoot
+ \fi
+ \ifx\@dtl@cap\@nnil
+ \@dtl@resetdoamp
+ \dtlforeachkey(\@dtl@key,\@dtl@idx,\@dtl@type,\@dtl@head)%
+ \in{#2}\do
+ {\@dtl@doamp{\dtlheaderformat{\@dtl@head}}}%
+ \@dtl@resetdoamp
+ \@dtl@resetdostartrow
+ \endhead\dtldisplayafterhead
+ \else
+ \caption[\@dtl@shortcap]{\@dtl@cap}%
+ \ifx\@dtl@label\@nnil
+ \else
+ \label{\@dtl@label}%
+ \fi
+ \\%
+ \@dtl@resetdoamp
+ \dtlforeachkey(\@dtl@key,\@dtl@idx,\@dtl@type,\@dtl@head)%
+ \in{#2}\do
+ {\@dtl@doamp{\dtlheaderformat{\@dtl@head}}}%
+ \@dtl@resetdoamp
+ \@dtl@resetdostartrow
+ \endfirsthead
+ \ifx\@dtl@contcap\@nnil
+ \caption{\@dtl@cap}%
+ \else
+ \caption{\@dtl@contcap}%
+ \fi
+ \\%
+ \@dtl@resetdoamp
+ \dtlforeachkey(\@dtl@key,\@dtl@idx,\@dtl@type,\@dtl@head)%
+ \in{#2}\do
+ {\@dtl@doamp{\dtlheaderformat{\@dtl@head}}}%
+ \@dtl@resetdoamp
+ \@dtl@resetdostartrow
+ \endhead\dtldisplayafterhead
+ \fi
+ \DTLforeach*{#2}{}{%
+ \@dtl@dostartrow
+ \@dtl@resetdoamp
+ \DTLforeachkeyinrow{\@dtl@val}%
+ {%
+ \global\let\@dtl@val\@dtl@val
+ \@dtl@doamp
+ \@dtl@datatype=0\dtltype\relax
+ \ifcase\@dtl@datatype
+ \dtlstringformat\@dtl@val
+ \or
+ \dtlintformat\@dtl@val
+ \or
+ \dtlrealformat\@dtl@val
+ \or
+ \dtlcurrencyformat\@dtl@val
+ \fi
+ }%
+ }%
+ \dtldisplayendtab
+ \end{longtable}%
}
-\newcommand*{\@dtl@assign}[2][\@dtl@currentrow]{%
-\@dtl@assigncmd#2,\relax\@@{#1}%
+\newcommand*{\dtlswaprows}[3]{%
+ \ifnum#2=#3\relax
+ \else
+ \ifnum#2<#3\relax
+ \edef\@dtl@rowAidx{\number#2}%
+ \edef\@dtl@rowBidx{\number#3}%
+ \else
+ \edef\@dtl@rowAidx{\number#3}%
+ \edef\@dtl@rowBidx{\number#2}%
+ \fi
+ \edef\@dtl@dosplit{\noexpand\dtlgetrow{#1}{\@dtl@rowAidx}}%
+ \@dtl@dosplit
+ \expandafter\def\expandafter\@dtl@firstpart\expandafter
+ {\the\dtlbeforerow}%
+ \@dtl@toksA=\dtlcurrentrow
+ \edef\@dtl@dosplit{\noexpand\@dtlgetrow
+ {\the\dtlafterrow}{\@dtl@rowBidx}}%
+ \@dtl@dosplit
+ \expandafter\def\expandafter\@dtl@secondpart\expandafter
+ {\the\dtlbeforerow}%
+ \@dtl@toksB=\dtlcurrentrow
+ \expandafter\def\expandafter\@dtl@thirdpart\expandafter
+ {\the\dtlafterrow}%
+ \toks@=\expandafter{\@dtl@firstpart}%
+ \@dtl@toks=\expandafter{\@dtl@secondpart}%
+ \edef\@dtl@tmp{\the\toks@
+ \noexpand\db@row@elt@w%
+ \noexpand\db@row@id@w \@dtl@rowAidx\noexpand\db@row@id@end@%
+ \the\@dtl@toksB
+ \noexpand\db@row@id@w \@dtl@rowAidx\noexpand\db@row@id@end@%
+ \noexpand\db@row@elt@end@%
+ \the\@dtl@toks}%
+ \toks@=\expandafter{\@dtl@tmp}%
+ \@dtl@toks=\expandafter{\@dtl@thirdpart}%
+ \edef\@dtl@tmp{\the\toks@
+ \noexpand\db@row@elt@w%
+ \noexpand\db@row@id@w \@dtl@rowBidx\noexpand\db@row@id@end@%
+ \the\@dtl@toksA
+ \noexpand\db@row@id@w \@dtl@rowBidx\noexpand\db@row@id@end@%
+ \noexpand\db@row@elt@end@%
+ \the\@dtl@toks}%
+ \expandafter\global\csname dtldb@#1\endcsname=\expandafter
+ {\@dtl@tmp}%
+ \fi
}
-\def\@dtl@assigncmd#1=#2,#3\@@#4{%
-\@for\@dtl@entry:=#4\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\@@{#4}%
+\newcommand*{\dtl@decrementrows}[2]{%
+ \def\@dtl@newlist{}%
+ \edef\@dtl@min{\number#2}%
+ \expandafter\@dtl@decrementrows\the#1%
+ \db@row@elt@w%
+ \db@row@id@w \@nil\db@row@id@end@%
+ \db@row@id@w \@nil\db@row@id@end@%
+ \db@row@elt@end@%
+ \@nil
+ #1=\expandafter{\@dtl@newlist}%
+}
+\def\@dtl@decrementrows\db@row@elt@w\db@row@id@w #1\db@row@id@end@%
+#2\db@row@id@w #3\db@row@id@end@\db@row@elt@end@#4\@nil{%
+ \def\@dtl@thisrow{#1}%
+ \ifx\@dtl@thisrow\@nnil
+ \let\@dtl@donextdec=\@dtl@gobbletonil
+ \else
+ \ifnum\@dtl@thisrow>\@dtl@min
+ \@dtl@tmpcount=\@dtl@thisrow\relax
+ \advance\@dtl@tmpcount by -1\relax
+ \toks@{#2}%
+ \@dtl@toks=\expandafter{\@dtl@newlist}%
+ \edef\@dtl@newlist{\the\@dtl@toks
+ \noexpand\db@row@elt@w% row header
+ \noexpand\db@row@id@w \number\@dtl@tmpcount
+ \noexpand\db@row@id@end@% row id
+ \the\toks@ % row contents
+ \noexpand\db@row@id@w \number\@dtl@tmpcount
+ \noexpand\db@row@id@end@% row id
+ \noexpand\db@row@elt@end@% row end
+ }%
+ \else
+ \toks@{#2}%
+ \@dtl@toks=\expandafter{\@dtl@newlist}%
+ \edef\@dtl@newlist{\the\@dtl@toks
+ \noexpand\db@row@elt@w% row header
+ \noexpand\db@row@id@w #1%
+ \noexpand\db@row@id@end@% row id
+ \the\toks@ % row contents
+ \noexpand\db@row@id@w #3%
+ \noexpand\db@row@id@end@% row id
+ \noexpand\db@row@elt@end@% row end
+ }%
+ \fi
+ \let\@dtl@donextdec=\@dtl@decrementrows
+ \fi
+ \@dtl@donextdec#4\@nil
+}
+\newcommand*{\DTLremoverow}[2]{%
+ \DTLifdbexists{#1}%
+ {%
+ \ifnum#2>0\relax
+ \expandafter\ifnum\csname dtlrows@#1\endcsname<#2\relax
+ \expandafter\ifnum\csname dtlrows@#1\endcsname=1\relax
+ \PackageError{datatool}{Can't remove row `\number#2' from
+ database `#1': no such row}{Database `#1' only has
+ 1 row}%
+ \else
+ \PackageError{datatool}{Can't remove row `\number#2' from
+ database `#1': no such row}{Database `#1' only has
+ \expandafter\number\csname dtlrows@#1\endcsname\space
+ rows}%
+ \fi
+ \else
+ \@DTLremoverow{#1}{#2}%
+ \fi
+ \else
+ \PackageError{datatool}{Can't remove row \number#2: index
+ out of bounds}{Row indices start at 1}%
+ \fi
+ }%
+ {%
+ \PackageError{datatool}{Can't remove row: database `#1' doesn't
+ exist}{}%
+ }%
}
-\def\@dtl@assigncmdnoop#1\@@#2{}
-\newcommand*{\@dtl@setnull}[2]{%
-\@ifundefined{@dtl@idtype@\@dtl@dbname @#2}{%
-\global\let#1=\DTLstringnull}{%
-\edef\@dtl@tmp{0\@dtl@getidtype{\@dtl@dbname}{#2}}%
-\expandafter\ifnum\@dtl@tmp=0\relax
- \global\let#1=\DTLstringnull
-\else
- \global\let#1=\DTLnumbernull
-\fi
-}}
-\newcommand*{\DTLstringnull}{NULL}
-\newcommand*{\DTLnumbernull}{0}
-\newcommand*{\DTLifnull}[3]{%
-\ifx\DTLstringnull#1\relax
- #2%
-\else
- \ifx\DTLnumbernull#1\relax
- #2%
- \else
- #3%
- \fi
-\fi}
-\newcommand{\dtl@gathervalues}[3][key]{%
-\expandafter\let\expandafter\@dtl@tmp\expandafter
- =\csname dtlkeys@#2\endcsname%
-\def\@dtl@list{}%
-\@for\dtl@key:=\@dtl@tmp\do{%
- \expandafter\@dtl@setnull\expandafter{%
- \csname @dtl@#1@\dtl@key\endcsname}{\dtl@key}%
- \@for\dtl@thiselement:=#3\do{%
- \dtl@getentryid\dtl@thiselement\@dtl@id
- \ifthenelse{\equal{\@dtl@id}{\dtl@key}}{%
- \dtl@getentryvalue\dtl@thiselement\@dtl@value%
- \expandafter\toks@\expandafter{\@dtl@value}%
- \expandafter\edef\csname @dtl@#1@\dtl@key\endcsname{%
- \the\toks@}%
- \@endfortrue}{}%
- }%
-\@endforfalse
-}%
+\newcommand*{\@DTLremoverow}[2]{%
+ \edef\dtl@dogetrow{\noexpand\dtlgetrow{#1}{\number#2}}%
+ \dtl@dogetrow
+ \expandafter\dtl@decrementrows\expandafter
+ {\dtlbeforerow}{#2}%
+ \expandafter\dtl@decrementrows\expandafter
+ {\dtlafterrow}{#2}%
+ \edef\dtl@tmp{\the\dtlbeforerow \the\dtlafterrow}%
+ \expandafter\global\csname dtldb@#1\endcsname
+ =\expandafter{\dtl@tmp}%
+ \expandafter\global\expandafter\advance
+ \csname dtlrows@#1\endcsname by -1\relax
+}
+\newcommand*{\DTLsumforkeys}[1][\boolean{true}\and
+ \DTLisnumerical{\DTLthisval}]{%
+ \def\@dtl@cond{#1}%
+ \@dtlsumforkeys
+}
+\newcommand*{\@dtlsumforkeys}[4][]{%
+ \def#4{0}%
+ \@for\@dtl@dbname:=#2\do{%
+ \@sDTLforeach{\@dtl@dbname}%
+ {#1}% assignment list
+ {%
+ \@for\@dtl@key:=#3\do{%
+ \@sdtl@getcolumnindex{\@dtl@col}{\@dtl@dbname}{\@dtl@key}%
+ \dtlcurrentrow=\expandafter{\dtl@thisrow}%
+ \dtlgetentryfromrow{\DTLthisval}{\@dtl@col}{\dtlcurrentrow}%
+ \expandafter\ifthenelse\expandafter{\@dtl@cond}%
+ {\DTLadd{#4}{#4}{\DTLthisval}}{}%
+ }%
+ }%
+ }%
}
-\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}{}%
+\newcommand*{\DTLsumcolumn}[3]{%
+ \def#3{0}%
+ \DTLifdbexists{#1}%
+ {%
+ \@sDTLifhaskey{#1}{#2}%
+ {%
+ \@sdtlforcolumn{\DTLthisval}{#1}{#2}%
+ {%
+ \DTLadd{#3}{#3}{\DTLthisval}%
+ }%
+ }%
+ {%
+ \PackageError{datatool}{Key `#2' doesn't
+ exist in database `#1'}{}%
+ }%
+ }%
+ {%
+ \PackageError{datatool}{Data base `#1' doesn't
+ exist}{}%
}%
-}%
}
-\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
-}
-\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}{}%
+\newcommand*{\DTLmeanforkeys}[1][\boolean{true}\and
+ \DTLisnumerical{\DTLthisval}]{%
+ \def\@dtl@cond{#1}%
+ \@dtlmeanforkeys
+}
+\newcount\@dtl@elements
+\newcommand*{\@dtlmeanforkeys}[4][]{%
+ \def#4{0}%
+ \@dtl@elements=0\relax
+ \@for\@dtl@dbname:=#2\do{%
+ \@sDTLforeach{\@dtl@dbname}%
+ {#1}% assignment list
+ {%
+ \@for\@dtl@key:=#3\do{%
+ \@sdtl@getcolumnindex{\@dtl@col}{\@dtl@dbname}{\@dtl@key}%
+ \dtlcurrentrow=\expandafter{\dtl@thisrow}%
+ \dtlgetentryfromrow{\DTLthisval}{\@dtl@col}{\dtlcurrentrow}%
+ \expandafter\ifthenelse\expandafter{\@dtl@cond}%
+ {%
+ \DTLadd{#4}{#4}{\DTLthisval}%
+ \advance\@dtl@elements by 1\relax
+ }{}%
+ }%
+ }%
}%
-}%
-\ifnum\dtl@n=0\relax
- \PackageError{datatool}{Can't compute variance, no data!}{}%
-\else
- \DTLdiv{#4}{#4}{\dtl@n}%
-\fi
+ \ifnum\@dtl@elements=0\relax
+ \PackageError{datatool}{Unable to evaluate mean: no data}{}%
+ \else
+ \edef\@dtl@n{\number\@dtl@elements}%
+ \DTLdiv{#4}{#4}{\@dtl@n}%
+ \fi
}
-\newcommand*{\DTLsdforkeys}[4][\boolean{true}\and
-\DTLisnumerical{\DTLthisval}]{%
-\DTLvarianceforkeys[#1]{#2}{#3}{#4}%
-\DTLsqrt{#4}{#4}%
+\newcommand*{\DTLmeanforcolumn}[3]{%
+ \def#3{0}%
+ \@dtl@elements=0\relax
+ \DTLifdbexists{#1}%
+ {%
+ \@sDTLifhaskey{#1}{#2}%
+ {%
+ \@sdtlforcolumn{\DTLthisval}{#1}{#2}%
+ {%
+ \DTLadd{#3}{#3}{\DTLthisval}%
+ \advance\@dtl@elements by 1\relax
+ }%
+ \ifnum\@dtl@elements=0\relax
+ \PackageError{datatool}{Can't compute mean for
+ column `#2' in database `#1': no data}{}%
+ \else
+ \edef\@dtl@n{\number\@dtl@elements}%
+ \DTLdiv{#3}{#3}{\@dtl@n}%
+ \fi
+ }%
+ {%
+ \PackageError{datatool}{Key `#2' doesn't
+ exist in database `#1'}{}%
+ }%
+ }%
+ {%
+ \PackageError{datatool}{Data base `#1' doesn't
+ exist}{}%
+ }%
}
-\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}{}%
+\newcommand*{\DTLvarianceforkeys}[1][\boolean{true}\and
+ \DTLisnumerical{\DTLthisval}]{%
+ \def\@dtl@cond{#1}%
+ \@dtlvarianceforkeys
+}
+\newcommand*{\@dtlvarianceforkeys}[4][]{%
+ \@dtlmeanforkeys[#1]{#2}{#3}{\dtl@mean}%
+ \def#4{0}%
+ \@dtl@elements=0\relax
+ \@for\@dtl@dbname:=#2\do{%
+ \@sDTLforeach{\@dtl@dbname}%
+ {#1}% assignment list
+ {%
+ \@for\@dtl@key:=#3\do{%
+ \@sdtl@getcolumnindex{\@dtl@col}{\@dtl@dbname}{\@dtl@key}%
+ \dtlcurrentrow=\expandafter{\dtl@thisrow}%
+ \dtlgetentryfromrow{\DTLthisval}{\@dtl@col}{\dtlcurrentrow}%
+ \expandafter\ifthenelse\expandafter{\@dtl@cond}%
+ {%
+ \DTLsub{\dtl@diff}{\DTLthisval}{\dtl@mean}%
+ \DTLmul{\dtl@diff}{\dtl@diff}{\dtl@diff}%
+ \DTLadd{#4}{#4}{\dtl@diff}%
+ \advance\@dtl@elements by 1\relax
+ }{}%
+ }%
+ }%
}%
-}}
-\newcommand*{\DTLmaxforkeys}[4][\boolean{true}\and
+ \ifnum\@dtl@elements=0\relax
+ \PackageError{datatool}{Unable to evaluate variance: no data}{}%
+ \else
+ \edef\@dtl@n{\number\@dtl@elements}%
+ \DTLdiv{#4}{#4}{\@dtl@n}%
+ \fi
+}
+\newcommand*{\DTLvarianceforcolumn}[3]{%
+ \DTLmeanforcolumn{#1}{#2}{\dtl@mean}%
+ \def#3{0}%
+ \@dtl@elements=0\relax
+ \DTLifdbexists{#1}%
+ {%
+ \@sDTLifhaskey{#1}{#2}%
+ {%
+ \@sdtlforcolumn{\DTLthisval}{#1}{#2}%
+ {%
+ \DTLsub{\dtl@diff}{\DTLthisval}{\dtl@mean}%
+ \DTLmul{\dtl@diff}{\dtl@diff}{\dtl@diff}%
+ \DTLadd{#3}{#3}{\dtl@diff}%
+ \advance\@dtl@elements by 1\relax
+ }%
+ \ifnum\@dtl@elements=0\relax
+ \PackageError{datatool}{Can't compute variance for
+ column `#2' in database `#1': no data}{}%
+ \else
+ \edef\@dtl@n{\number\@dtl@elements}%
+ \DTLdiv{#3}{#3}{\@dtl@n}%
+ \fi
+ }%
+ {%
+ \PackageError{datatool}{Key `#2' doesn't
+ exist in database `#1'}{}%
+ }%
+ }%
+ {%
+ \PackageError{datatool}{Data base `#1' doesn't
+ exist}{}%
+ }%
+}
+\newcommand*{\DTLsdforkeys}[1][\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}{}%
+ \def\@dtl@cond{#1}%
+ \@dtlsdforkeys
+}
+\newcommand*{\@dtlsdforkeys}[4][]{%
+ \@dtlvarianceforkeys[#1]{#2}{#3}{#4}%
+ \DTLsqrt{#4}{#4}%
+}
+\newcommand*{\DTLsdforcolumn}[3]{%
+ \DTLvarianceforcolumn{#1}{#2}{#3}%
+ \DTLsqrt{#3}{#3}%
+}
+\newcommand*{\DTLminforkeys}[1][\boolean{true}\and
+ \DTLisnumerical{\DTLthisval}]{%
+ \def\@dtl@cond{#1}%
+ \@dtlminforkeys
+}
+\newcommand*{\@dtlminforkeys}[4][]{%
+ \def#4{}%
+ \@for\@dtl@dbname:=#2\do{%
+ \@sDTLforeach{\@dtl@dbname}%
+ {#1}% assignment list
+ {%
+ \@for\@dtl@key:=#3\do{%
+ \@sdtl@getcolumnindex{\@dtl@col}{\@dtl@dbname}{\@dtl@key}%
+ \dtlcurrentrow=\expandafter{\dtl@thisrow}%
+ \dtlgetentryfromrow{\DTLthisval}{\@dtl@col}{\dtlcurrentrow}%
+ \expandafter\ifthenelse\expandafter{\@dtl@cond}%
+ {%
+ \ifx#4\@empty
+ \let#4\DTLthisval
+ \else
+ \DTLmin{#4}{#4}{\DTLthisval}%
+ \fi
+ }{}%
+ }%
+ }%
}%
-}}
+}
+\newcommand*{\DTLminforcolumn}[3]{%
+ \def#3{}%
+ \DTLifdbexists{#1}%
+ {%
+ \@sDTLifhaskey{#1}{#2}%
+ {%
+ \@sdtlforcolumn{\DTLthisval}{#1}{#2}%
+ {%
+ \ifx#3\@empty
+ \let#3\DTLthisval
+ \else
+ \DTLmin{#3}{#3}{\DTLthisval}%
+ \fi
+ }%
+ }%
+ {%
+ \PackageError{datatool}{Key `#2' doesn't
+ exist in database `#1'}{}%
+ }%
+ }%
+ {%
+ \PackageError{datatool}{Data base `#1' doesn't
+ exist}{}%
+ }%
+}
+\newcommand*{\DTLmaxforkeys}[1][\boolean{true}\and
+ \DTLisnumerical{\DTLthisval}]{%
+ \def\@dtl@cond{#1}%
+ \@dtlmaxforkeys
+}
+\newcommand*{\@dtlmaxforkeys}[4][]{%
+ \def#4{}%
+ \@for\@dtl@dbname:=#2\do{%
+ \@sDTLforeach{\@dtl@dbname}%
+ {#1}% assignment list
+ {%
+ \@for\@dtl@key:=#3\do{%
+ \@sdtl@getcolumnindex{\@dtl@col}{\@dtl@dbname}{\@dtl@key}%
+ \dtlcurrentrow=\expandafter{\dtl@thisrow}%
+ \dtlgetentryfromrow{\DTLthisval}{\@dtl@col}{\dtlcurrentrow}%
+ \expandafter\ifthenelse\expandafter{\@dtl@cond}%
+ {%
+ \ifx#4\@empty
+ \let#4\DTLthisval
+ \else
+ \DTLmax{#4}{#4}{\DTLthisval}%
+ \fi
+ }{}%
+ }%
+ }%
+ }%
+}
+\newcommand*{\DTLmaxforcolumn}[3]{%
+ \def#3{}%
+ \DTLifdbexists{#1}%
+ {%
+ \@sDTLifhaskey{#1}{#2}%
+ {%
+ \@sdtlforcolumn{\DTLthisval}{#1}{#2}%
+ {%
+ \ifx#3\@empty
+ \let#3\DTLthisval
+ \else
+ \DTLmax{#3}{#3}{\DTLthisval}%
+ \fi
+ }%
+ }%
+ {%
+ \PackageError{datatool}{Key `#2' doesn't
+ exist in database `#1'}{}%
+ }%
+ }%
+ {%
+ \PackageError{datatool}{Data base `#1' doesn't
+ exist}{}%
+ }%
+}
\newcommand*{\DTLcomputebounds}[8][\boolean{true}]{%
\let#5=\relax
\let#6=\relax
@@ -2045,228 +3311,266 @@ deeply}{}%
}%
}
\newcommand*{\DTLgetvalueforkey}[5]{%
-{%
-\global\let#1=\DTLstringnull
-\@sDTLforeach{#3}{\dtl@valueA=#2,\dtl@refvalue=#4}{%
-\DTLifnull{\dtl@refvalue}{}{%
-\ifthenelse{\equal{\dtl@refvalue}{#5}}{%
-\global\let#1=\dtl@valueA
-\@endfortrue
-}{}}}%
-}}
+ \DTLgetrowforkey{\@dtl@row}{#3}{#4}{#5}%
+ \@sdtl@getcolumnindex{\@dtl@col}{#3}{#2}%
+ {%
+ \dtlcurrentrow=\expandafter{\@dtl@row}%
+ \edef\@dtl@dogetval{\noexpand\dtlgetentryfromcurrentrow
+ {\noexpand\@dtl@val}{\@dtl@col}}%
+ \@dtl@dogetval
+ \global\let#1=\@dtl@val
+ }%
+}
\newcommand*{\DTLgetrowforkey}[4]{%
-{%
-\global\let#1=\@empty
-\@sDTLforeach{#2}{\dtl@refvalue=#3}{%
-\DTLifnull{\dtl@refvalue}{}{%
-\ifthenelse{\equal{\dtl@refvalue}{#4}}{%
-\expandafter\global\expandafter\let\expandafter#1
- \csname @dtl@thiscurrentrow@\romannumeral\dtlforeachlevel\endcsname
-\@endfortrue
-}{}}}%
-}}
+ \global\let#1=\@empty
+ \@sDTLforeach{#2}{\dtl@refvalue=#3}{%
+ \DTLifnull{\dtl@refvalue}%
+ {}%
+ {%
+ \ifthenelse{\equal{\dtl@refvalue}{#4}}%
+ {%
+ \xdef#1{\the\dtlcurrentrow}%
+ \dtlbreak
+ }%
+ {}%
+ }%
+ }%
+}
+\newcommand*{\dtlsplitrow}[4]{%
+ \def\@dtlsplitrow##1%before stuff
+ \db@col@id@w #2\db@col@id@end@% column id
+ ##2% unwanted stuff
+ \db@col@id@w #2\db@col@id@end@% column id
+ ##3% after stuff
+ \q@nil{\def#3{##1}\def#4{##3}}%
+ \@dtlsplitrow#1\q@nil
+}
+\newtoks\@dtl@list
\newcommand*{\DTLsort}{\@ifstar\@sDTLsort\@DTLsort}
-\newcommand*{\@DTLsort}[3][]{%
-\edef\@dtl@replacementkeys{#1}%
-\edef\@dtl@sortorder{#2}%
-\edef\@dtl@dbname{#3}%
-\let\@dtl@comparecs=\dtlcompare
-\expandafter\let\expandafter\@dtl@list\csname dtldb@#3\endcsname
-\dtl@sortlist{\@dtl@list}{\@dtl@sortcriteria}%
-\expandafter\global\expandafter
- \let\csname dtldb@#3\endcsname=\@dtl@list}
-\newcommand*{\@sDTLsort}[3][]{%
-\edef\@dtl@replacementkeys{#1}%
-\edef\@dtl@sortorder{#2}%
-\edef\@dtl@dbname{#3}%
-\let\@dtl@comparecs=\dtlicompare
-\expandafter\let\expandafter\@dtl@list\csname dtldb@#3\endcsname
-\dtl@sortlist{\@dtl@list}{\@dtl@sortcriteria}%
-\expandafter\global\expandafter
- \let\csname dtldb@#3\endcsname=\@dtl@list}
+\newcommand{\@DTLsort}[3][]{%
+ \DTLifdbexists{#3}%
+ {%
+ \edef\@dtl@replacementkeys{#1}%
+ \edef\@dtl@sortorder{#2}%
+ \let\@dtl@comparecs=\dtlcompare
+ \dtl@sortdata{#3}%
+ }%
+ {%
+ \PackageError{datatool}{Database `#3' doesn't exist}{}%
+ }%
+}
+\newcommand{\@sDTLsort}[3][]{%
+ \DTLifdbexists{#3}%
+ {%
+ \edef\@dtl@replacementkeys{#1}%
+ \edef\@dtl@sortorder{#2}%
+ \let\@dtl@comparecs=\dtlicompare
+ \dtl@sortdata{#3}%
+ }%
+ {%
+ \PackageError{datatool}{Database `#3' doesn't exist}{}%
+ }%
+}
+\newtoks\@dtl@rowa
+\newtoks\@dtl@rowb
+\newcommand*{\dtl@sortdata}[1]{%
+ \def\@dtl@sortedlist{}%
+ \edef\@dtl@dbname{#1}%
+ \@dtlforeachrow(\@dtl@rowAnum,\@dtl@rowAcontents)\in{#1}\do{%
+ \@dtl@rowa=\expandafter{\@dtl@rowAcontents}%
+ \def\@dtl@newlist{}%
+ \@dtl@insertdonefalse
+ \dtlrownum=0\relax
+ \expandafter\@dtl@foreachrow\@dtl@sortedlist
+ \db@row@elt@w%
+ \db@row@id@w \@nil\db@row@id@end@%
+ \db@row@id@w \@nil\db@row@id@end@%
+ \db@row@elt@end@%
+ \@@{\@dtl@rowBnum}{\@dtl@rowBcontents}{%
+ \@dtl@rowb=\expandafter{\@dtl@rowBcontents}%
+ \dtlrownum=\@dtl@rowBnum
+ \if@dtl@insertdone
+ \advance\dtlrownum by 1\relax
+ \else
+ \@dtl@sortcriteria{\@dtl@rowa}{\@dtl@rowb}%
+ \ifnum\dtl@sortresult<0\relax
+ \toks@=\expandafter{\@dtl@newlist}%
+ \edef\@dtl@newlist{%
+ \the\toks@
+ \noexpand\db@row@elt@w%
+ \noexpand\db@row@id@w \number\dtlrownum
+ \noexpand\db@row@id@end@%
+ \the\@dtl@rowa
+ \noexpand\db@row@id@w \number\dtlrownum
+ \noexpand\db@row@id@end@%
+ \noexpand\db@row@elt@end@%
+ }%
+ \advance\dtlrownum by 1\relax
+ \@dtl@insertdonetrue
+ \fi
+ \fi
+ \toks@=\expandafter{\@dtl@newlist}%
+ \edef\@dtl@newlist{\the\toks@
+ \noexpand\db@row@elt@w%
+ \noexpand\db@row@id@w \number\dtlrownum
+ \noexpand\db@row@id@end@%
+ \the\@dtl@rowb
+ \noexpand\db@row@id@w \number\dtlrownum
+ \noexpand\db@row@id@end@%
+ \noexpand\db@row@elt@end@%
+ }%
+ }\q@nil
+ \if@dtl@insertdone
+ \else
+ \advance\dtlrownum by 1\relax
+ \toks@=\expandafter{\@dtl@newlist}%
+ \edef\@dtl@newlist{\the\toks@
+ \noexpand\db@row@elt@w%
+ \noexpand\db@row@id@w \number\dtlrownum
+ \noexpand\db@row@id@end@%
+ \the\@dtl@rowa
+ \noexpand\db@row@id@w \number\dtlrownum
+ \noexpand\db@row@id@end@%
+ \noexpand\db@row@elt@end@%
+ }%
+ \fi
+ \let\@dtl@sortedlist=\@dtl@newlist
+ }%
+ \expandafter\global\csname dtldb@#1\endcsname=\expandafter
+ {\@dtl@sortedlist}%
+}
\newcommand{\@dtl@sortcriteria}[2]{%
-\@for\@dtl@level:=\@dtl@sortorder\do{%
- \expandafter\@dtl@getsortdirection\@dtl@level=\relax%
- \@ifundefined{@dtl@idtype@\@dtl@dbname @\@dtl@key}{%
- \ifx\@dtl@replacementkeys\@empty
- \PackageError{datatool}{Unknown key `\@dtl@key' for database
- `\@dtl@dbname'}{}%
- \else
- \dtl@gathervalues[keya]{\@dtl@dbname}{#1}%
- \dtl@gathervalues[keyb]{\@dtl@dbname}{#2}%
- \@ifundefined{@dtl@keya@\@dtl@key}{%
- \@dtl@setnull{\@dtl@tmpa}{\@dtl@key}%
- }{%
- \expandafter\let\expandafter\@dtl@tmpa\expandafter
- =\csname @dtl@keya@\@dtl@key\endcsname}%
- \@ifundefined{@dtl@keyb@\@dtl@key}{%
- \@dtl@setnull{\@dtl@tmpb}{\@dtl@key}%
- }{%
- \expandafter\let\expandafter\@dtl@tmpb\expandafter
- =\csname @dtl@keyb@\@dtl@key\endcsname}%
- \let\@dtl@keya=\@dtl@key
- \let\@dtl@keyb=\@dtl@key
- \DTLifnull{\@dtl@tmpa}{%
- % find first non null key in list of replacement keys
- \@for\@dtl@keya:=\@dtl@replacementkeys\do{%
- \@ifundefined{@dtl@keya@\@dtl@keya}{}{%
- \expandafter\let\expandafter\@dtl@tmpa\expandafter
- =\csname @dtl@keya@\@dtl@keya\endcsname
- \DTLifnull{\@dtl@tmpa}{}{\@endfortrue}}%
- }%
- \if@endfor \else\let\@dtl@keya=\@dtl@key \fi
- \@endforfalse
- }{}%
- \DTLifnull{\@dtl@tmpb}{%
- % find first non null key in list of replacement keys
- \@for\@dtl@keyb:=\@dtl@replacementkeys\do{%
- \@ifundefined{@dtl@keyb@\@dtl@keyb}{}{%
- \expandafter\let\expandafter\@dtl@tmpb\expandafter
- =\csname @dtl@keyb@\@dtl@keyb\endcsname
- \DTLifnull{\@dtl@tmpb}{}{\@endfortrue}}%
- }%
- \if@endfor \else\let\@dtl@keyb=\@dtl@key \fi
- \@endforfalse
- }{}%
- \@ifundefined{@dtl@idtype@\@dtl@dbname @\@dtl@keya}{%
- \@ifundefined{@dtl@idtype@\@dtl@dbname @\@dtl@keyb}{%
- \dtl@sortresult=0\relax}{\dtl@sortresult=-1\relax}%
- }{%
- \@ifundefined{@dtl@idtype@\@dtl@dbname @\@dtl@keyb}{%
- \dtl@sortresult=1\relax}{%
- \dtl@compare@{\@dtl@keya}{\@dtl@keyb}{#1}{#2}%
- }%
- }%
- \fi
- }{%
- \ifx\@dtl@replacementkeys\@empty
- \dtl@compare{\@dtl@key}{#1}{#2}%
- \else
- \dtl@gathervalues[keya]{\@dtl@dbname}{#1}%
- \dtl@gathervalues[keyb]{\@dtl@dbname}{#2}%
- \@ifundefined{@dtl@keya@\@dtl@key}{%
- \@dtl@setnull{\@dtl@tmpa}{\@dtl@key}%
- }{%
- \expandafter\let\expandafter\@dtl@tmpa\expandafter
- =\csname @dtl@keya@\@dtl@key\endcsname}%
- \@ifundefined{@dtl@keyb@\@dtl@key}{%
- \@dtl@setnull{\@dtl@tmpb}{\@dtl@key}%
- }{%
- \expandafter\let\expandafter\@dtl@tmpb\expandafter
- =\csname @dtl@keyb@\@dtl@key\endcsname}%
- \let\@dtl@keya=\@dtl@key
- \let\@dtl@keyb=\@dtl@key
- \DTLifnull{\@dtl@tmpa}{%
- % find first non null key in list of replacement keys
- \@for\@dtl@keya:=\@dtl@replacementkeys\do{%
- \@ifundefined{@dtl@keya@\@dtl@keya}{}{%
- \expandafter\let\expandafter\@dtl@tmpa\expandafter
- =\csname @dtl@keya@\@dtl@keya\endcsname
- \DTLifnull{\@dtl@tmpa}{}{\@endfortrue}}%
- }%
- \if@endfor \else\let\@dtl@keya=\@dtl@key \fi
- \@endforfalse
- }{}%
- \DTLifnull{\@dtl@tmpb}{%
- % find first non null key in list of replacement keys
- \@for\@dtl@keyb:=\@dtl@replacementkeys\do{%
- \@ifundefined{@dtl@keyb@\@dtl@keyb}{}{%
- \expandafter\let\expandafter\@dtl@tmpb\expandafter
- =\csname @dtl@keyb@\@dtl@keyb\endcsname
- \DTLifnull{\@dtl@tmpb}{}{\@endfortrue}}%
- }%
- \if@endfor \else\let\@dtl@keyb=\@dtl@key \fi
- \@endforfalse
- }{}%
- \dtl@compare@{\@dtl@keya}{\@dtl@keyb}{#1}{#2}%
- \fi
- \multiply\dtl@sortresult by \@dtl@sortdirection\relax
- \ifnum\dtl@sortresult=0\relax
- \else
- \@endfortrue
- \fi
- }%
-}%
+ \@for\@dtl@level:=\@dtl@sortorder\do{%
+ \expandafter\@dtl@getsortdirection\@dtl@level=\relax
+ \let\@dtl@keya=\@dtl@key
+ \let\@dtl@keyb=\@dtl@key
+ \@sdtl@getcolumnindex{\@dtl@col}{\@dtl@dbname}{\@dtl@key}%
+ \dtlgetentryfromrow{\@dtl@a}{\@dtl@col}{#1}%
+ \dtlgetentryfromrow{\@dtl@b}{\@dtl@col}{#2}%
+ \ifx\@dtl@a\dtlnovalue
+ \@dtl@setnull{\@dtl@a}{\@dtl@key}%
+ \fi
+ \ifx\@dtl@b\dtlnovalue
+ \@dtl@setnull{\@dtl@b}{\@dtl@key}%
+ \fi
+ \DTLifnull{\@dtl@a}%
+ {%
+ \@for\@dtl@keya:=\@dtl@replacementkeys\do{%
+ \@sdtl@getcolumnindex{\@dtl@col}{\@dtl@dbname}{\@dtl@keya}%
+ \dtlgetentryfromrow{\@dtl@a}{\@dtl@col}{#1}%
+ \ifx\@dtl@a\dtlnovalue
+ \@dtl@setnull{\@dtl@a}{\@dtl@key}%
+ \fi
+ \DTLifnull{\@dtl@a}{}{\@endfortrue}%
+ }%
+ \ifx\@dtl@keya\@nnil
+ \let\@dtl@keya\@dtl@key
+ \@dtl@setnull{\@dtl@a}{\@dtl@key}%
+ \fi
+ }%
+ {}%
+ \DTLifnull{\@dtl@b}%
+ {%
+ \@for\@dtl@keyb:=\@dtl@replacementkeys\do{%
+ \@sdtl@getcolumnindex{\@dtl@col}{\@dtl@dbname}{\@dtl@keyb}%
+ \dtlgetentryfromrow{\@dtl@b}{\@dtl@col}{#2}%
+ \ifx\@dtl@b\dtlnovalue
+ \@dtl@setnull{\@dtl@b}{\@dtl@key}%
+ \fi
+ \DTLifnull{\@dtl@b}{}{\@endfortrue}%
+ }%
+ \ifx\@dtl@keyb\@nnil
+ \let\@dtl@keyb\@dtl@key
+ \@dtl@setnull{\@dtl@b}{\@dtl@key}%
+ \fi
+ }%
+ {}%
+ \@dtl@toksA=\expandafter{\@dtl@a}%
+ \@dtl@toksB=\expandafter{\@dtl@b}%
+ \edef\@dtl@docompare{\noexpand\dtl@compare@
+ {\@dtl@keya}{\@dtl@keyb}%
+ {\noexpand\@dtl@toksA}{\noexpand\@dtl@toksB}}%
+ \@dtl@docompare
+ \ifnum\dtl@sortresult=0\relax
+ \@endforfalse
+ \else
+ \@endfortrue
+ \fi
+ }%
}
\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%
- \ifthenelse{\equal{\@dtl@sortdirection}{ascending}}{%
- \def\@dtl@sortdirection{-1}}{%
- \ifthenelse{\equal{\@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
+ \def\@dtl@key{#1}%
+ \def\@dtl@sortdirection{#2}%
+ \ifx\@dtl@sortdirection\@empty
+ \def\@dtl@sortdirection{-1}%
+ \else
+ \@dtl@get@sortdirection#2%
+ \def\@dtl@dir{ascending}%
+ \ifx\@dtl@sortdirection\@dtl@dir
+ \def\@dtl@sortdirection{-1}%
+ \else
+ \def\@dtl@dir{descending}%
+ \ifx\@dtl@sortdirection\@dtl@dir
+ \def\@dtl@sortdirection{1}%
+ \else
+ \PackageError{datatool}{Invalid sort direction
+ `\@dtl@sortdirection'}{The sort direction can only be
+ one of `ascending' or `descending'}%
+ \def\@dtl@sortdirection{-1}
+ \fi
+ \fi
+ \fi
}
\def\@dtl@get@sortdirection#1={\def\@dtl@sortdirection{#1}}
-\newtoks\@dtl@toksA\newtoks\@dtl@toksB
+\newtoks\@dtl@toksA
+\newtoks\@dtl@toksB
+\newtoks\@dtl@toks
\newcommand{\dtl@compare}[3]{%
-\dtl@gathervalues{\@dtl@dbname}{#2}%
-\expandafter\let\expandafter\@dtl@tmp\expandafter
- =\csname @dtl@key@#1\endcsname
-\expandafter\@dtl@toksA\expandafter{\@dtl@tmp}%
-\edef\@dtl@a{\the\@dtl@toksA}%
-\dtl@gathervalues{\@dtl@dbname}{#3}%
-\expandafter\let\expandafter\@dtl@tmp\expandafter
- =\csname @dtl@key@#1\endcsname
-\expandafter\@dtl@toksB\expandafter{\@dtl@tmp}%
-\edef\@dtl@b{\the\@dtl@toksB}%
-\expandafter\@dtl@datatype\expandafter=
- \csname @dtl@idtype@\@dtl@dbname @#1\endcsname\relax
-\ifnum\@dtl@datatype=0\relax
- \edef\@dtl@tmpcmp{%
- \noexpand\@dtl@comparecs{\noexpand\dtl@sortresult}%
- {\the\@dtl@toksA}{\the\@dtl@toksB}}%
- \@dtl@tmpcmp
-\else
- \DTLifnumlt{\@dtl@a}{\@dtl@b}{\dtl@sortresult=-1\relax}{%
- \DTLifnumgt{\@dtl@a}{\@dtl@b}{\dtl@sortresult=1\relax}{%
- \dtl@sortresult=0\relax}}%
-\fi
-\ifdtlverbose
-\@onelevel@sanitize\@dtl@a
-\@onelevel@sanitize\@dtl@b
-\fi
-\dtl@message{`\@dtl@a' <=> `\@dtl@b' = \number\dtl@sortresult}%
+ \dtl@compare@{#1}{#1}{#2}{#3}%
}
\newcommand{\dtl@compare@}[4]{%
-\dtl@gathervalues{\@dtl@dbname}{#3}%
-\expandafter\let\expandafter\@dtl@tmp\expandafter
- =\csname @dtl@key@#1\endcsname
-\expandafter\@dtl@toksA\expandafter{\@dtl@tmp}%
-\edef\@dtl@a{\the\@dtl@toksA}%
-\dtl@gathervalues{\@dtl@dbname}{#4}%
-\expandafter\let\expandafter\@dtl@tmp\expandafter
- =\csname @dtl@key@#2\endcsname
-\expandafter\@dtl@toksB\expandafter{\@dtl@tmp}%
-\edef\@dtl@b{\the\@dtl@toksB}%
-\expandafter\@dtl@tmpcount\expandafter=
- \csname @dtl@idtype@\@dtl@dbname @#1\endcsname\relax
-\expandafter\@dtl@datatype\expandafter=
- \csname @dtl@idtype@\@dtl@dbname @#2\endcsname\relax
-\multiply\@dtl@datatype by \@dtl@tmpcount\relax
-\ifnum\@dtl@datatype=0\relax
- \edef\@dtl@tmpcmp{%
- \noexpand\@dtl@comparecs{\noexpand\dtl@sortresult}%
- {\the\@dtl@toksA}{\the\@dtl@toksB}}%
- \@dtl@tmpcmp
-\else
- \DTLifnumlt{\@dtl@a}{\@dtl@b}{\dtl@sortresult=-1\relax}{%
- \DTLifnumgt{\@dtl@a}{\@dtl@b}{\dtl@sortresult=1\relax}{%
- \dtl@sortresult=0\relax}}%
-\fi
-\ifdtlverbose
-\@onelevel@sanitize\@dtl@a
-\@onelevel@sanitize\@dtl@b
-\fi
-\dtl@message{`\@dtl@a' <=> `\@dtl@b' = \number\dtl@sortresult}%
+ \DTLgetdatatype{\@dtl@typeA}{\@dtl@dbname}{#1}%
+ \ifx\@dtl@typeA\DTLunsettype
+ \let\@dtl@typeA\DTLstringtype
+ \fi
+ \DTLgetdatatype{\@dtl@typeB}{\@dtl@dbname}{#2}%
+ \ifx\@dtl@typeB\DTLunsettype
+ \let\@dtl@typeB\DTLstringtype
+ \fi
+ \@dtl@tmpcount=\@dtl@typeA\relax
+ \multiply\@dtl@tmpcount by \@dtl@typeB\relax
+ \ifnum\@dtl@tmpcount=0\relax
+ \edef\@dtl@tmpcmp{%
+ \noexpand\@dtl@comparecs{\noexpand\dtl@sortresult}%
+ {\the#3}{\the#4}%
+ }%
+ \@dtl@tmpcmp
+ \ifdtlverbose
+ \edef\@dtl@a{\the#3}%
+ \edef\@dtl@b{\the#4}%
+ \fi
+ \else
+ \edef\@dtl@a{\the#3}%
+ \edef\@dtl@b{\the#4}%
+ \DTLifnumlt{\@dtl@a}{\@dtl@b}%
+ {%
+ \dtl@sortresult=-1\relax
+ }%
+ {%
+ \DTLifnumgt{\@dtl@a}{\@dtl@b}%
+ {%
+ \dtl@sortresult=1\relax
+ }%
+ {%
+ \dtl@sortresult=0\relax
+ }%
+ }%
+ \fi
+ \ifdtlverbose
+ \@onelevel@sanitize\@dtl@a
+ \@onelevel@sanitize\@dtl@b
+ \dtl@message{`\@dtl@a' <=> `\@dtl@b' = \number\dtl@sortresult}%
+ \fi
}
\newcommand*{\dtl@choplast}[3]{%
\let#2\@empty
@@ -2306,7 +3610,6 @@ deeply}{}%
\@endforfalse}%
\let#1=\@dtl@sortedlist
}
-\newtoks\@dtl@toks
\newcommand{\dtl@insertinto}[3]{%
\def\@dtl@newsortedlist{}%
\@dtl@insertdonefalse
@@ -2351,6 +3654,22 @@ deeply}{}%
}
\newif\if@dtl@insertdone
\newcount\dtl@sortresult
+\newcommand{\toks@gput@right@cx}[2]{%
+ \def\@toks@name{#1}%
+ \edef\@dtl@stuff{#2}%
+ \global\csname\@toks@name\endcsname\expandafter
+ \expandafter\expandafter{\expandafter\the
+ \csname\expandafter\@toks@name\expandafter\endcsname\@dtl@stuff}%
+}
+\newcommand{\toks@gconcat@middle@cx}[4]{%
+ \def\@toks@name{#1}%
+ \edef\@dtl@stuff{#3}%
+ \global\csname\@toks@name\endcsname\expandafter\expandafter
+ \expandafter\expandafter\expandafter
+ \expandafter\expandafter{\expandafter\expandafter\expandafter
+ \the\expandafter\expandafter\expandafter#2%
+ \expandafter\@dtl@stuff\the#4}%
+}
\newcommand*{\DTLadd}[3]{%
\DTLconverttodecimal{#2}{\@dtl@numi}%
\DTLconverttodecimal{#3}{\@dtl@numii}%
@@ -2909,155 +4228,270 @@ deeply}{}%
}}}
\newwrite\@dtl@write
\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}{}%
-}}
+ \DTLifdbexists{#1}%
+ {%
+ \openout\@dtl@write
+ \def\@dtl@header{}%
+ \dtlforeachkey(\@dtl@key,\@dtl@col,\@dtl@type,\@dtl@head)%
+ \in{#1}\do
+ {%
+ \IfSubStringInString{\@dtl@separator}{\@dtl@key}%
+ {%
+ \ifx\@dtl@header\@empty
+ \protected@edef\@dtl@header{%
+ \@dtl@delimiter\@dtl@key\@dtl@delimiter}%
+ \else
+ \toks@=\expandafter{\@dtl@header}%
+ \protected@edef\@dtl@header{%
+ \the\toks@\@dtl@separator
+ \@dtl@delimiter\@dtl@key\@dtl@delimiter}%
+ \fi
+ }%
+ {%
+ \ifx\@dtl@header\@empty
+ \protected@edef\@dtl@header{\@dtl@key}%
+ \else
+ \toks@=\expandafter{\@dtl@header}%
+ \protected@edef\@dtl@header{\the\toks@
+ \@dtl@separator\@dtl@key}%
+ \fi
+ }%
+ }%
+ \protected@write\@dtl@write{}{\@dtl@header}%
+ \@sDTLforeach{#1}{}%
+ {%
+ \def\@dtl@row{}%
+ \DTLforeachkeyinrow{\@dtl@val}%
+ {%
+ \IfSubStringInString{\@dtl@separator}{\@dtl@val}%
+ {%
+ \ifx\@dtl@row\@empty
+ \protected@edef\@dtl@row{%
+ \@dtl@delimiter\@dtl@val\@dtl@delimiter}%
+ \else
+ \toks@=\expandafter{\@dtl@row}%
+ \protected@edef\@dtl@row{\the\toks@\@dtl@separator
+ \@dtl@delimiter\@dtl@val\@dtl@delimiter}%
+ \fi
+ }%
+ {%
+ \ifx\@dtl@row\@empty
+ \protected@edef\@dtl@row{\@dtl@val}%
+ \else
+ \toks@=\expandafter{\@dtl@row}%
+ \protected@edef\@dtl@row{\the\toks@\@dtl@separator
+ \@dtl@val}%
+ \fi
+ }%
+ \protected@write\@dtl@write{}{\@dtl@row}%
+ }%
+ }%
+ \closeout\@dtl@write
+ }%
+ {%
+ \PackageError{datatool}{Can't save database `#1': no such
+ database}{}%
+ }%
+}
\newcommand*{\DTLsavetexdb}[2]{%
-\DTLifdbexists{#1}{%
-\def\@dtl@dbname{#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{%
-\expandafter\DTLifnull\csname @dtl@key@\@dtl@key\endcsname
-{}{%
-\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}{}%
-}}
+ \DTLifdbexists{#1}%
+ {%
+ \openout\@dtl@write=#2\relax
+ \protected@write\@dtl@write{}{\string\DTLnewdb{#1}}%
+ \@sDTLforeach{#1}{}%
+ {%
+ \protected@write\@dtl@write{}{\string\DTLnewrow*{#1}}%
+ \DTLforeachkeyinrow{\@dtl@val}%
+ {%
+ \DTLifnull{\@dtl@val}%
+ {\def\@dtl@val{}}%
+ {}%
+ \protected@write\@dtl@write{}{%
+ \string\DTLnewdbentry*{#1}{\dtlkey}{\@dtl@val}}%
+ }%
+ }%
+ \dtlforeachkey(\@dtl@k,\@dtl@c,\@dtl@t,\@dtl@h)\in{#1}\do
+ {%
+ \@onelevel@sanitize\@dtl@h
+ \protected@write\@dtl@write{}{%
+ \string\DTLsetheader*{#1}{\@dtl@k}{\@dtl@h}}%
+ }%
+ \closeout\@dtl@write
+ }%
+ {%
+ \PackageError{datatool}{Can't save database `#1': no such
+ database}{}%
+ }%
+}
+\newcommand{\@longempty}{}
\newread\@dtl@read
\newcount\dtl@entrycr
-\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
+\define@boolkey{loaddb}[dtl]{noheader}[true]{}
+\define@key{loaddb}{keys}{%
+ \dtl@entrycr=0\relax
+ \@for\@dtl@key:=#1\do
+ {%
+ \advance\dtl@entrycr by 1\relax
+ \expandafter
+ \edef\csname @dtl@inky@\romannumeral\dtl@entrycr\endcsname{%
+ \@dtl@key}%
+ }%
+}
+\define@key{loaddb}{headers}{%
+ \dtl@entrycr=0\relax
+ \@for\@dtl@head:=#1\do
+ {%
+ \advance\dtl@entrycr by 1\relax
+ \toks@=\expandafter{\@dtl@head}%
+ \expandafter
+ \edef\csname @dtl@inhd@\romannumeral\dtl@entrycr\endcsname{%
+ \the\toks@}%
+ }%
+}
+\newcommand*{\dtldefaultkey}{Column}
+\newcommand*{\@dtl@readline}[2]{%
+ \read#1 to #2%
+ \dtl@trim#2%
+}
+\newcommand*{\@dtl@readrawline}[2]{%
+ \@dtl@rawread#1 to #2%
+ \dtl@trim#2%
+ \dtl@domappings\@dtl@line
+}
+
+\newcommand*{\DTLloaddb}{%
+ \let\@dtl@doreadline\@dtl@readline
+ \@dtlloaddb
+}
+\newcommand*{\@dtlloaddb}[3][]{%
+ \IfFileExists{#3}{%
+ \begingroup
+ \catcode`\"12\relax
+ \dtlnoheaderfalse
+ \setkeys{loaddb}{#1}%
+ \openin\@dtl@read=#3%
+ \dtl@message{Reading `#3'}%
+ \DTLnewdb{#2}%
\ifeof\@dtl@read
+ \PackageWarning{datatool}{File `#3' has no data}%
\else
- \read\@dtl@read to \@dtl@line
- \dtl@trim\@dtl@line
- \if\@dtl@line\par
- \@dtl@conditiontrue
+ \ifdtlnoheader
+ \else
+ \loop
+ \@dtl@conditionfalse
+ \ifeof\@dtl@read
+ \else
+ \@dtl@doreadline\@dtl@read\@dtl@line
+ \ifx\@dtl@line\@longempty
+ \@dtl@conditiontrue
+ \fi
+ \fi
+ \if@dtl@condition
+ \repeat
+ \protected@edef\@dtl@lin@{%
+ \@dtl@separator\@dtl@line\@dtl@separator}%
+ \dtl@entrycr=0\relax
+ \loop
+ \expandafter\@dtl@lopoff\@dtl@lin@\to\@dtl@lin@\@dtl@key
+ \advance\dtl@entrycr by 1\relax
+ \expandafter\@dtl@toks\expandafter{\@dtl@key}%
+ \@ifundefined{@dtl@inky@\romannumeral\dtl@entrycr}%
+ {%
+ \expandafter
+ \edef\csname @dtl@inky@\romannumeral
+ \dtl@entrycr\endcsname{\the\@dtl@toks}%
+ }%
+ {%
+ \@ifundefined{@dtl@inhd@\romannumeral\dtl@entrycr}%
+ {%
+ \expandafter
+ \edef\csname @dtl@inhd@\romannumeral
+ \dtl@entrycr\endcsname{\the\@dtl@toks}%
+ }%
+ {}%
+ }%
+ \ifx\@dtl@lin@\@dtl@separator
+ \@dtl@conditionfalse
+ \else
+ \@dtl@conditiontrue
+ \fi
+ \if@dtl@condition
+ \repeat
\fi
+ \ifeof\@dtl@read
+ \ifdtlnoheader
+ \PackageWarning{datatool}{No data in `#3'}%
+ \else
+ \PackageWarning{datatool}{Only header row found in `#3'}%
+ \fi
+ \else
+ \@dtl@conditiontrue
+ \loop
+ \@dtl@doreadline\@dtl@read\@dtl@line
+ \ifx\@dtl@line\@longempty
+ \else
+ \@sDTLnewrow{#2}%
+ \expandafter\@dtl@toks\expandafter{\@dtl@line}%
+ \edef\@dtl@lin@{\@dtl@separator\the\@dtl@toks
+ \@dtl@separator}%
+ \dtl@entrycr=0\relax
+ {%
+ \@dtl@conditiontrue
+ \loop
+ \expandafter\@dtl@lopoff\@dtl@lin@\to
+ \@dtl@lin@\@dtl@thisentry
+ \advance\dtl@entrycr by 1\relax
+ \@ifundefined{@dtl@inky@\romannumeral\dtl@entrycr}%
+ {%
+ \edef\@dtl@thiskey{\dtldefaultkey
+ \number\dtl@entrycr}%
+ \expandafter\let
+ \csname @dtl@inky@\romannumeral
+ \dtl@entrycr\endcsname\@dtl@thiskey
+ }%
+ {%
+ \edef\@dtl@thiskey{%
+ \csname @dtl@inky@\romannumeral
+ \dtl@entrycr\endcsname}%
+ }%
+ \expandafter\@dtl@toks\expandafter{\@dtl@thisentry}%
+ \edef\@do@dtlnewentry{\noexpand\@sDTLnewdbentry
+ {#2}{\@dtl@thiskey}{\the\@dtl@toks}}%
+ \@do@dtlnewentry
+ \ifx\@dtl@lin@\@dtl@separator
+ \@dtl@conditionfalse
+ \fi
+ \if@dtl@condition
+ \repeat
+ }%
+ \fi
+ \ifeof\@dtl@read \@dtl@conditionfalse\fi
+ \if@dtl@condition
+ \repeat
+ \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}%
- \expandafter\@dtl@toks\expandafter{\@dtl@thisentry}%
- \edef\@do@dtlnewentry{\noexpand\DTLnewdbentry
- {#1}{\@dtl@thiskey}{\the\@dtl@toks}}%
- \@do@dtlnewentry
- }%
- }%
- \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)}{}%
-}}
+ \closein\@dtl@read
+ \edef\@dtl@maxcols{\expandafter
+ \number\csname dtlcols@#2\endcsname}%
+ \dtlgforint\dtl@entrycr=1\to\@dtl@maxcols\step1\do
+ {%
+ \@ifundefined{@dtl@inhd@\romannumeral\dtl@entrycr}%
+ {}%
+ {%
+ \expandafter\let\expandafter\@dtl@head
+ \csname @dtl@inhd@\romannumeral\dtl@entrycr\endcsname
+ \@dtl@toks=\expandafter{\@dtl@head}%
+ \edef\@dtl@dosetheader{\noexpand\@dtl@setheaderforindex
+ {#2}{\number\dtl@entrycr}{\the\@dtl@toks}}%
+ \@dtl@dosetheader
+ }%
+ }%
+ \endgroup
+ }{%
+ \PackageError{datatool}{Can't load database `#2' (file `#3'
+ doesn't exist)}{}%
+ }%
+}
\newcommand{\dtl@trim}[1]{%
\def\@dtl@trmstr{}%
\expandafter\@dtl@starttrim#1\@nil%
@@ -3072,75 +4506,10 @@ doesn't exist)}{}%
\@dtl@dotrim%
}
\long\def\@dtl@trim#1 \@nil{\long\def\@dtl@trmstr{#1}}
-\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}%
- \expandafter\@dtl@toks\expandafter{\@dtl@thisentry}%
- \edef\@do@dtlnewentry{\noexpand\DTLnewdbentry
- {#1}{\@dtl@thiskey}{\the\@dtl@toks}}%
- \@do@dtlnewentry
- }%
- }%
- \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)}{}%
-}}
+\newcommand*\DTLloadrawdb{%
+ \let\@dtl@doreadline\@dtl@readrawline
+ \@dtlloaddb
+}
\begingroup
\catcode`\%=\active
\catcode`$=\active
@@ -3258,6 +4627,19 @@ doesn't exist)}{}%
\@dtl@dosubstnext{#1}{#2}%
}
\def\@dtl@dosubstitutenoop#1#2{}
+\newcommand*{\DTLifinlist}[4]{%
+ \def\@dtl@doifinlist##1,#1,##2\end@dtl@doifinlist{%
+ \def\@before{##1}%
+ \def\@after{##2}%
+ }%
+ \expandafter\@dtl@doifinlist\expandafter,#2,#1,\@nil
+ \end@dtl@doifinlist
+ \ifx\@after\@nnil
+ #4%
+ \else
+ #3%
+ \fi
+}
\newcommand*{\@dtl@currencies}{\$,\pounds}
\newcommand*{\DTLnewcurrencysymbol}[1]{%
\expandafter\toks@\expandafter{\@dtl@currencies}%
@@ -3308,11 +4690,12 @@ doesn't exist)}{}%
\fi
}
\newcommand*{\dtlshowdb}[1]{%
-\expandafter\show\csname dtldb@#1\endcsname}
+\expandafter\showthe\csname dtldb@#1\endcsname}
\newcommand*{\dtlshowdbkeys}[1]{%
-\expandafter\show\csname dtlkeys@#1\endcsname}
+\expandafter\showthe\csname dtlkeys@#1\endcsname}
\newcommand*{\dtlshowtype}[2]{%
-\expandafter\show\csname @dtl@idtype@#1@#2\endcsname}
+ \DTLgetdatatype{\@dtl@type}{#1}{#2}\show\@dtl@type
+}
\endinput
%%
%% End of file `datatool.sty'.