summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/source/latex/datatool
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2009-11-16 01:44:59 +0000
committerKarl Berry <karl@freefriends.org>2009-11-16 01:44:59 +0000
commit2b1511b76524ed6e4b906094ee4a63aacf7d68e5 (patch)
tree7e7f3ab490a4e0c1140ba03ed59373be4c4dd226 /Master/texmf-dist/source/latex/datatool
parentfaaa36262649a67fb85d27b3e605d94da0b75fa4 (diff)
datalog 2.03 (15nov09)
git-svn-id: svn://tug.org/texlive/trunk@16023 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/source/latex/datatool')
-rw-r--r--Master/texmf-dist/source/latex/datatool/datatool.dtx3732
-rw-r--r--Master/texmf-dist/source/latex/datatool/datatool.ins6
2 files changed, 2803 insertions, 935 deletions
diff --git a/Master/texmf-dist/source/latex/datatool/datatool.dtx b/Master/texmf-dist/source/latex/datatool/datatool.dtx
index 8db14f657ed..fcae77779b6 100644
--- a/Master/texmf-dist/source/latex/datatool/datatool.dtx
+++ b/Master/texmf-dist/source/latex/datatool/datatool.dtx
@@ -2,20 +2,21 @@
% datatool.dtx generated using makedtx version 0.94b (c) Nicola Talbot
% Command line args:
% -macrocode "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"
+% -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"
+% -src "person\.sty\Z=>person.sty"
% -author "Nicola Talbot"
% -dir "source"
% -setambles ".*\.bst=>\nopreamble\usepreamble\defaultpreamble\nopostamble"
% -comment "databib.bst"
-% -doc "manual.tex"
+% -doc "datatool-manual.tex"
% -codetitle "datatool.sty"
% datatool
-% Created on 2009/7/13 10:04
+% Created on 2009/11/15 15:10
%\fi
%\iffalse
%<*package>
@@ -43,15 +44,17 @@
% \iffalse
%<*driver>
\documentclass[a4paper]{ltxdoc}
+\usepackage{dox}
\usepackage{ifthen}
\usepackage[verbose=false]{datatool}
-\usepackage{datapie,databar,databib}
+\usepackage{datapie,databar,databib,person}
\usepackage{textcomp}
\usepackage{graphicx}
\usepackage{colortbl}
\usepackage{cmap}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
+\usepackage{caption}
\usepackage[colorlinks,
bookmarks,
hyperindex=false,
@@ -80,7 +83,7 @@
\makeatother
\RecordChanges
\PageIndex
-\CheckSum{15418}
+\CheckSum{16375}
\newcommand*{\sty}[1]{\textsf{#1}}
\newcommand*{\env}[1]{\textsf{#1}}
@@ -96,11 +99,6 @@
}}
\makeatother
-\newcommand*{\counterfmt}[1]{\texttt{#1}\index
-{#1 counter=\texttt{#1} counter|hyperpage}}
-
-\newcommand*{\ics}[1]{\cs{#1}\SpecialMainIndex{#1}}
-
\newsavebox\defsbox
\newlength\defwidth
\newenvironment{definition}[1][]{%
@@ -118,6 +116,8 @@
\noindent
\defarg\fcolorbox{black}{defbackground}{\usebox\defsbox}%
\vskip10pt
+\noindent
+\ignorespacesafterend
}
\newlength\tmplength
@@ -133,6 +133,14 @@
\hangafter=-2\relax
}
+\doxitem{Counter}{counter}{counters}
+
+\newcommand*{\ctrfmt}[1]{\texttt{#1}}
+\newcommand*{\ctr}[1]{\ctrfmt{#1}\SpecialMainCounterIndex{#1}}
+\newcommand*{\desctr}[1]{\ctrfmt{#1}\DescribeCounter{#1}}
+
+\newcommand*{\ics}[1]{\cs{#1}\SpecialMainIndex{#1}}
+
\newcommand*{\pkgopt}[2][datatool]{\textsf{#2}\index
{#1 package options=\textsf{#1} package options>#2=\textsf{#2}|hyperpage}}
@@ -173,7 +181,7 @@ options>#2=\textsf{#2}|hyperpage}}
%\MakeShortVerb{"}
%\DeleteShortVerb{\|}
%
-% \title{datatool v 2.02: Databases and data manipulation}
+% \title{datatool v 2.03: Databases and data manipulation}
% \author{Nicola L.C. Talbot\\[10pt]
%School of Computing Sciences\\
%University of East Anglia\\
@@ -181,11 +189,16 @@ options>#2=\textsf{#2}|hyperpage}}
%NR4 7TJ. United Kingdom.\\
%\url{http://theoval.cmp.uea.ac.uk/~nlct/}}
%
-% \date{13th July 2009}
+% \date{15th November 2009}
% \maketitle
+%
+%\pdfbookmark[1]{Contents}{contents}
%\tableofcontents
+%\pdfbookmark[1]{List of Examples}{examples}
%\listofexamples
+%\pdfbookmark[1]{List of Figures}{figures}
%\listoffigures
+%\pdfbookmark[1]{List of Tables}{tables}
%\listoftables
%
% \section{Introduction}
@@ -1930,6 +1943,12 @@ options>#2=\textsf{#2}|hyperpage}}
%This command displays the number of rows in the database called
%\meta{db name}.
%
+%\begin{definition}[\DescribeMacro{\DTLcolumncount}]%
+%\cs{DTLcolumncount}\marg{db name}
+%\end{definition}
+%This command displays the number of columns (or keys) in the
+%database called \meta{db name}.
+%
%\begin{definition}[\DescribeMacro{\DTLnewrow}]%
%\cs{DTLnewrow}\marg{db name}
%\end{definition}
@@ -1967,7 +1986,11 @@ options>#2=\textsf{#2}|hyperpage}}
%\DTLrowcount{mydata}
%\end{verbatim}
%which produces:
-%\DTLrowcount{mydata}.
+%\DTLrowcount{mydata}. The column count is given by
+%\begin{verbatim}
+%\DTLcolumncount{mydata}
+%\end{verbatim}
+%which produces: \DTLcolumncount{mydata}.
%
%\begin{definition}[\DescribeMacro{\DTLnewdbentry}]%
%\cs{DTLnewdbentry}\marg{db name}\marg{key}\marg{value}
@@ -1986,6 +2009,17 @@ options>#2=\textsf{#2}|hyperpage}}
%key should not contain any fragile commands. It is generally
%best to only use non-active characters in the key.
%
+%The value isn't expanded by default, but you can change this
+%using the declaration:
+%\begin{definition}[\DescribeMacro{\dtlexpandnewvalue}]
+%\cs{dtlexpandnewvalue}
+%\end{definition}
+%This can be localised by placing it in a group, or you can
+%switch back using:
+%\begin{definition}[\DescribeMacro{\dtlnoexpandnewvalue}]
+%\cs{dtlnoexpandnewvalue}
+%\end{definition}
+%
%\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
@@ -2016,6 +2050,8 @@ options>#2=\textsf{#2}|hyperpage}}
%{\DTLiseq{\firstname}{John}\and\DTLiseq{\surname}{Smith}}%
%{Score}{75}
%\end{verbatim}
+%Note that unlike \cs{DTLnewdbentry}, the value is always expanded
+%when adding an entry using \cs{DTLaddentryforrow}.
%
%\begin{definition}[\DescribeMacro{\DTLsetheader}]%
%\cs{DTLsetheader}\marg{db}\marg{key}\marg{header}
@@ -2177,7 +2213,7 @@ options>#2=\textsf{#2}|hyperpage}}
%\cs{DTLloadrawdb}]{Special character mappings used by
%\cs{DTLloadrawdb} (note that the backslash retains its active state)}
%\label{tab:rawmappings}
-%\begin{center}
+%\centering
%\begin{tabular}{cl}
%Character & Mapping\\
%\verb|%| & \verb|\%|\\
@@ -2190,7 +2226,6 @@ options>#2=\textsf{#2}|hyperpage}}
%\verb|~| & \cs{textasciitilde}\\
%\verb|^| & \cs{textasciicircum}
%\end{tabular}
-%\end{center}
%\end{table}
%
%It may be that there are other characters that require mapping.
@@ -2204,7 +2239,7 @@ options>#2=\textsf{#2}|hyperpage}}
%\vskip\baselineskip
%The pound character is not an internationally standard keyboard
%character, and does not generally achieve the desired effect when used
-%in a \LaTeX\ document. It will therefore be necessary to convert
+%in a \LaTeX\ document. It may therefore be necessary to convert
%this symbol to an appropriate control sequence. This can be done
%using the command:
%\begin{definition}[\DescribeMacro{\DTLrawmap}]%
@@ -2249,8 +2284,8 @@ options>#2=\textsf{#2}|hyperpage}}
%\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}.
+%environment. Note that if you use this command, you must load the
+%\sty{longtable} package, 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}
@@ -2337,7 +2372,6 @@ options>#2=\textsf{#2}|hyperpage}}
%\begin{verbatim}
%\begin{table}[htbp]
%\caption{Time to Growth Data}
-%\vspace{\baselineskip}
%\centering
%\DTLdisplaydb{t2g}
%\end{table}
@@ -2346,7 +2380,6 @@ options>#2=\textsf{#2}|hyperpage}}
%\begin{table}[htbp]
%\caption{Time to Growth Data}
%\label{tab:t2g}
-%\vspace{\baselineskip}
%\centering
%\DTLdisplaydb{t2g}
%\end{table}
@@ -2524,8 +2557,8 @@ options>#2=\textsf{#2}|hyperpage}}
%\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}
+%\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
@@ -2535,7 +2568,6 @@ options>#2=\textsf{#2}|hyperpage}}
%\begin{table}[htbp]
%\caption{Balance Sheet}
%\renewcommand*{\dtlrealformat}[1]{\DTLiflt{#1}{0}{\color{red}}{}#1}
-%\vspace{\baselineskip}
%\centering
%\DTLdisplaydb{balance}
%\end{table}
@@ -2545,7 +2577,6 @@ options>#2=\textsf{#2}|hyperpage}}
%\caption{Balance Sheet}
%\label{tab:balance}
%\renewcommand*{\dtlrealformat}[1]{\DTLiflt{#1}{0}{\color{red}}{}#1}
-%\vspace{\baselineskip}
%\centering
%\DTLdisplaydb{balance}
%\end{table}
@@ -2676,9 +2707,9 @@ options>#2=\textsf{#2}|hyperpage}}
%
%The macro \ics{DTLforeach} may be nested up to three times. Each
%level uses the corresponding counters:
-%\counterfmt{DTLrowi},
-%\counterfmt{DTLrowii} and
-%\counterfmt{DTLrowiii} which keep track of
+%\desctr{DTLrowi},
+%\desctr{DTLrowii} and
+%\desctr{DTLrowiii} which keep track of
%the current row.
%
%\importantpar Note that these counters are only incremented when
@@ -2738,33 +2769,6 @@ options>#2=\textsf{#2}|hyperpage}}
%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}
@@ -2927,7 +2931,7 @@ options>#2=\textsf{#2}|hyperpage}}
%
%\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
+%I could do:\footnote{Recall that \ctr{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}.}
@@ -2946,7 +2950,6 @@ options>#2=\textsf{#2}|hyperpage}}
%\begin{table}[htbp]
%\caption{First Three Rows}
%\centering
-%\vskip\baselineskip
%\begin{tabular}{llr}
%\bfseries First Name & \bfseries Surname & \bfseries Score (\%)%
%\DTLforeach*{scores}%
@@ -2963,7 +2966,7 @@ options>#2=\textsf{#2}|hyperpage}}
%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:
+%\ctr{DTLrowi} instead:
%\begin{verbatim}
%\DTLforeach{scores}%
%{\firstname=FirstName,\surname=Surname,\score=Score}{%
@@ -2976,7 +2979,6 @@ options>#2=\textsf{#2}|hyperpage}}
%\caption{First Three Rows}
%\label{tab:dtlbreak}%
%\centering
-%\vskip\baselineskip
%\begin{tabular}{llr}
%\bfseries First Name & \bfseries Surname & \bfseries Score (\%)\relax
%\DTLforeach*{scores}%
@@ -3077,7 +3079,6 @@ options>#2=\textsf{#2}|hyperpage}}
%\begin{verbatim}
%\begin{table}[htbp]
%\caption{Student Scores (Iterating Through Keys)}
-%\vskip\baselineskip
%\centering
%\begin{tabular}{llll}
%\bfseries First Name & \bfseries Surname &
@@ -3093,7 +3094,6 @@ options>#2=\textsf{#2}|hyperpage}}
%\begin{table}[htbp]
%\caption{Student Scores (Iterating Through Keys)}
%\label{tab:foreachkey}
-%\vskip\baselineskip
%\centering
%\begin{tabular}{llll}
%\bfseries First Name & \bfseries Surname &
@@ -3120,7 +3120,6 @@ options>#2=\textsf{#2}|hyperpage}}
%\begin{verbatim}
% \begin{table}[htbp]
% \caption{Student Scores}
-% \vskip\baselineskip
% \centering
% % Work out the column alignments.
% \def\colalign{}%
@@ -3145,7 +3144,6 @@ options>#2=\textsf{#2}|hyperpage}}
%\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
@@ -3211,7 +3209,6 @@ options>#2=\textsf{#2}|hyperpage}}
%\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
@@ -3233,7 +3230,6 @@ options>#2=\textsf{#2}|hyperpage}}
%\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
@@ -3437,7 +3433,6 @@ options>#2=\textsf{#2}|hyperpage}}
%\begin{verbatim}
%\begin{table}[htbp]
%\caption{Club Membership}
-%\vskip\baselineskip
%\centering
%\begin{tabular}{lll}
%\bfseries First Name & \bfseries Surname & \bfseries Status
@@ -3453,7 +3448,6 @@ options>#2=\textsf{#2}|hyperpage}}
%\begin{table}[htbp]
%\caption{Club Membership}
%\label{tab:dyn}
-%\vskip\baselineskip
%\centering
%\begin{tabular}{lll}
%\bfseries First Name & \bfseries Surname & \bfseries Status
@@ -3559,9 +3553,9 @@ options>#2=\textsf{#2}|hyperpage}}
%for this database as a numerical key, since all elements in the
%database with that key are numerical, whereas it has
%identified the key "Email2" as a string, since there is at least
-%one element in this database with that key that is a string.
-%Null numerical values are set to \cs{DTLnumbernull} (0),
-%and null strings are set to \cs{DTLstringnull} (NULL).
+%one element in this database with that key that is a string. Null
+%numerical values are set to \cs{DTLnumbernull} (\DTLnumbernull), and
+%null strings are set to \cs{DTLstringnull} (\DTLstringnull).
%
%The following code checks each value to determine whether it
%is null using \cs{DTLifnull}. If it is, the text \emph{Missing}
@@ -3663,6 +3657,19 @@ options>#2=\textsf{#2}|hyperpage}}
%\subsection{Editing Database Rows}
%\label{sec:editdb}
%
+%A row can be removed from a data base using:
+%\begin{definition}[\DescribeMacro{\DTLremoverow}]%
+%\cs{DTLremoverow}\marg{db name}\marg{row index}
+%\end{definition}
+%where \meta{row index} is the index of the unwanted row. For
+%example:
+%\begin{verbatim}
+%\DTLremoverow{scores}{2}
+%\end{verbatim}
+%will delete the second row in the database labelled ``scores''.
+%There is also a starred version that doesn't check for the
+%existence of the database.
+%
%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:
@@ -3671,11 +3678,13 @@ options>#2=\textsf{#2}|hyperpage}}
%\end{definition}
%This appends a new entry with the given \meta{key} and \meta{value}
%to the current row.
+%(\meta{value} is expanded.)
%
%\begin{definition}[\DescribeMacro{\DTLreplaceentryforrow}]%
%\cs{DTLreplaceentryforrow}\marg{key}\marg{value}
%\end{definition}
-%This replaces the entry for \meta{key} with \meta{value}.
+%This replaces the entry for \meta{key} with \meta{value}.
+%(\meta{value} is expanded.)
%
%\begin{definition}[\DescribeMacro{\DTLremoveentryfromrow}]%
%\cs{DTLremoveentryfromrow}\marg{key}
@@ -4075,6 +4084,9 @@ options>#2=\textsf{#2}|hyperpage}}
%}
%\end{document}
%\end{verbatim}
+%
+%To determine a person's gender when mail merging, see
+%\autoref{sec:person}.
%\end{example}
%
%\subsection{Sorting a Database}
@@ -4395,6 +4407,162 @@ options>#2=\textsf{#2}|hyperpage}}
%a combination of \ics{DTLnewdb}, \ics{DTLnewrow} and
%\ics{DTLnewdbentry} commands.
%
+%\subsection{Deleting or Clearing a Database}\label{sec:deletedb}
+%
+%A database can be cleared or deleted when its contents are no
+%longer required.
+%\begin{definition}[\DescribeMacro{\DTLcleardb}]
+%\cs{DTLcleardb}\marg{db name}
+%\end{definition}
+%Clears the database given by \meta{db name}. The database is emptied
+%but remains defined.
+%
+%\begin{definition}[\DescribeMacro{\DTLdeletedb}]
+%\cs{DTLdeletedb}\marg{db name}
+%\end{definition}
+%Deletes (undefines) the database given by \meta{db name}.
+%
+%\subsection{Advanced Database Commands}
+%
+%This section describes more advanced commands. Further details
+%can be found in \autoref{sec:code:datatool}.
+%
+%\begin{definition}[\DescribeMacro{\DTLgetdatatype}]
+%\cs{DTLgetdatatype}\marg{cs}\marg{db}\marg{key}
+%\end{definition}
+%Gets the data type for the given key \meta{key} for the database
+%given by \meta{db}. The data type is stored in \meta{cs} which
+%must be a command name. The type will be one of:
+%\begin{itemize}
+%\item\DescribeMacro{\DTLunsettype}\cs{DTLunsettype} (not set),
+%\item\DescribeMacro{\DTLstringtype}\cs{DTLstringtype} (string),
+%\item\DescribeMacro{\DTLinttype}\cs{DTLinttype} (integer),
+%\item\DescribeMacro{\DTLrealtype}\cs{DTLrealtype} (real number) or
+%\item\DescribeMacro{\DTLcurrencytype}\cs{DTLcurrenttype} (currency).
+%\end{itemize}
+%
+%\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 (as for \cs{DTLgetdatatype}), \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.
+%
+%\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}.
+%Alternatively, if you want to identify the column by its index
+%rather than its key, use:
+%\begin{definition}[\DescribeMacro{\dtlforcolumnindex}]%
+%\cs{dtlforcolumnindex}\marg{cs}\marg{db}\marg{col index}\marg{body}
+%\end{definition}
+%
+%\begin{definition}[\DescribeMacro{\DTLifdbexists}]
+%\cs{DTLifdbexists}\marg{db name}\marg{true part}\marg{false part}
+%\end{definition}
+%Determines if the database given by \meta{db name} exists.
+%
+%\begin{definition}[\DescribeMacro{\DTLifhaskey}]
+%\cs{DTLifhaskey}\marg{db name}\marg{key}\marg{true part}\marg{false part}
+%\end{definition}
+%This determines if the database given by \meta{db name} has
+%any entries with the key given by \meta{key}. If so, it does
+%\meta{true part} otherwise it does \meta{false part}.
+%
+%Each key has an associated column index. This can be obtained
+%using:
+%\begin{definition}[\DescribeMacro{\DTLgetcolumnindex}]
+%\cs{DTLgetcolumnindex}\marg{cs}\marg{db}\marg{key}
+%\end{definition}
+%where \meta{cs} is a command name, \meta{db} is the database label
+%and \meta{key} is the key. The column index is stored in
+%\meta{cs}.
+%
+%You can also do the reverse and find the key associated with a
+%given column index:
+%\begin{definition}[\DescribeMacro{\DTLgetkeyforcolumn}]
+%\cs{DTLgetkeyforcolumn}\marg{key cs}\marg{db}\marg{column index}
+%\end{definition}
+%The key is stored in \meta{key cs} (which must be a command name).
+%
+%There is also a full expandable way of obtaining the column
+%index, but note that no check is performed to determine
+%if the database exists, or if it contains the given key:
+%\begin{definition}[\DescribeMacro{\dtlcolumnindex}]
+%\cs{dtlcolumnindex}\marg{db name}\marg{key}
+%\end{definition}
+%
+%\begin{definition}[\DescribeMacro{\DTLgetkeydata}]
+%\cs{DTLgetkeydata}\marg{key}\marg{db}\marg{col cs}\marg{type cs}\marg{header cs}
+%\end{definition}
+%Gets data for given key in database \meta{db}: the column index is
+%stored in \meta{col cs} (as \cs{DTLgetcolumnindex}), the type is
+%stored in \meta{type cs} (as \cs{DTLgetdatatype}) and the header
+%is stored in \meta{header cs}.
+%
+%\begin{definition}[\DescribeMacro{\DTLgetvalue}]
+%\cs{DTLgetvalue}\marg{cs}\marg{db}\marg{r}\marg{c}
+%\end{definition}
+%This gets the value for row given by index \meta{r} and column
+%given by \meta{c} for the database \meta{db} and stores it in
+%\meta{cs} which must be a command name. If you want to get the
+%value by key rather than column index you can use
+%\cs{dtlcolumnindex}. For example, the following gets the value
+%for row~3 with key \texttt{Surname} from the database
+%\texttt{data} and stores in \cs{myval}:
+%\begin{verbatim}
+%\DTLgetvalue{\myval}{data}{3}{\dtlcolumnindex{data}{Surname}}
+%\end{verbatim}
+%
+%\begin{definition}[\DescribeMacro{\DTLgetlocation}]
+%\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{definition}[\DescribeMacro{\DTLgetvalueforkey}]
+%\cs{DTLgetvalueforkey}\marg{cmd}\marg{key}\marg{db name}\marg{ref
+% key}\marg{ref value}
+%\end{definition}
+%This (globally) sets \meta{cmd} (a control sequence) to the
+%value of the key specified by \meta{key} in the first row
+%of the database called \meta{db name} which contains the key
+%\meta{ref key} which has the value \meta{value}.
+%
+%Two rows can be swapped using:
+%\begin{definition}[\DescribeMacro{\DTLswaprows}]%
+%\cs{DTLswaprows}\marg{db name}\marg{row1 index}\marg{row2 index}
+%\end{definition}
+%where \meta{row1 index} and \meta{row2 index} are the indices
+%of the rows to be swapped. For example:
+%\begin{verbatim}
+%\DTLswaprows{scores}{3}{5}
+%\end{verbatim}
+%will swap the third and fifth rows.
+%
+%\begin{definition}[\DescribeMacro{\DTLifinlist}]
+%\cs{DTLifinlist}\marg{element}\marg{list}\marg{true part}\marg{false part}
+%\end{definition}
+%If \meta{element} is contained in the comma-separated list given
+%by \meta{list}, then do \meta{true part} otherwise do false
+%part. (Does a one level expansion on \meta{list}, but no
+%expansion on \meta{element}.)
+%
%\section{Pie Charts (\texorpdfstring{\sty{datapie}}{datapie} package)}
%
%The \sty{datapie} package is not loaded by the \sty{datatool} package,
@@ -4404,7 +4572,7 @@ options>#2=\textsf{#2}|hyperpage}}
%may be given the following options:
%\begin{description}
%\item[{\pkgopt[datapie]{color}}] Colour option (default).
-%\item[{\pkgopt[datapie]{monochrome}}] Monochrome option.
+%\item[{\pkgopt[datapie]{gray}}] Grey scale option.
%\item[{\pkgopt[datapie]{rotateinner}}]
%Rotate inner labels so that they are aligned
%with the pie chart radial axis.
@@ -4707,7 +4875,7 @@ options>#2=\textsf{#2}|hyperpage}}
%This command is set to the percentage value of \cs{DTLpievariable}.
%The percentage value is rounded to \meta{n} digits, where \meta{n}
%is the value of the \LaTeX\ counter
-%\counterfmt{DTLpieroundvar}.
+%\desctr{DTLpieroundvar}.
%
%\begin{example}{Changing the Inner and Outer Labels}{ex:pielabels}
%This example uses the database defined in \autoref{ex:piechart}.
@@ -5109,13 +5277,13 @@ options>#2=\textsf{#2}|hyperpage}}
%separated list of labels for each $x$ tick mark. If omitted,
%the labels are the value of the $x$ tick position, rounded
%\meta{n} digits after the decimal point, where \meta{n} is
-%given by the value of the counter \counterfmt{DTLplotroundXvar}.
+%given by the value of the counter \ctr{DTLplotroundXvar}.
%
%\item[\setting{DTLplot}{yticlabels}] The value must be a comma
%separated list of labels for each $y$ tick mark. If omitted,
%the labels are the value of the $y$ tick position, rounded
%\meta{n} digits after the decimal point, where \meta{n} is
-%given by the value of the counter \counterfmt{DTLplotroundYvar}.
+%given by the value of the counter \ctr{DTLplotroundYvar}.
%
%\item[\setting{DTLplot}{xlabel}] The value is the label for
%the $x$ axis. If omitted, the axis has no label.
@@ -5433,21 +5601,21 @@ options>#2=\textsf{#2}|hyperpage}}
%created using \ics{DTLplot}. The value of the counters can be
%changed using \cs{setcounter}.
%
-%\begin{definition}
-%\counterfmt{DTLplotroundXvar}
+%\begin{definition}[\DescribeCounter{DTLplotroundXvar}]
+%\ctrfmt{DTLplotroundXvar}
%\end{definition}
%Unless you specify your own tick labels, the $x$ tick labels will
%be given by the tick points rounded to \meta{n} digits after the
%decimal point, where \meta{n} is the value of the counter
-%\counterfmt{DTLplotroundXvar}.
+%\ctrfmt{DTLplotroundXvar}.
%
-%\begin{definition}
-%\counterfmt{DTLplotroundYvar}
+%\begin{definition}[\DescribeCounter{DTLplotroundYvar}]
+%\ctrfmt{DTLplotroundYvar}
%\end{definition}
%Unless you specify your own tick labels, the $y$ tick labels will
%be given by the tick points rounded to \meta{n} digits after the
%decimal point, where \meta{n} is the value of the counter
-%\counterfmt{DTLplotroundYvar}.
+%\ctrfmt{DTLplotroundYvar}.
%
%\subsubsection{Macros}
%These macros govern the appearance of plots created using
@@ -5674,7 +5842,7 @@ options>#2=\textsf{#2}|hyperpage}}
%used after the legend is plotted. The $x$ and $y$ unit vectors
%are set before \ics{DTLplotatbegintikz} so I don't need to
%worry about the co-ordinates.
-%\item I set the counter \counterfmt{DTLplotroundXvar} to zero
+%\item I set the counter \ctr{DTLplotroundXvar} to zero
%otherwise the $x$ axis would have looked too cluttered.
%\item I have used \ics{DTLminforkeys} and \ics{DTLmaxforkeys} to
%determine the bounds since \ics{DTLplot} won't take the data
@@ -5894,12 +6062,12 @@ options>#2=\textsf{#2}|hyperpage}}
%You must use \cs{setlength} to change this value. The default value
%is 10pt.
%
-%\begin{definition}
-%\counterfmt{DTLbarroundvar}
+%\begin{definition}[\DescribeCounter{DTLbarroundvar}]
+%\ctrfmt{DTLbarroundvar}
%\end{definition}
%The $y$ tick labels are rounded to \meta{n} digits after the
%decimal point, where \meta{n} is given by the value of the
-%counter \counterfmt{DTLbarroundvar}. You must use \cs{setcounter}
+%counter \ctrfmt{DTLbarroundvar}. You must use \cs{setcounter}
%to change this value.
%
%\begin{definition}[\DescribeMacro{\DTLsetbarcolor}]%
@@ -6667,7 +6835,7 @@ options>#2=\textsf{#2}|hyperpage}}
%
%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
+%test the value of the counter \ctr{DTLbibrow} within
%\meta{conditions}. You may also use the boolean commands defined
%by the \sty{ifthen} package, such as \ics{not}.
%
@@ -6891,23 +7059,23 @@ options>#2=\textsf{#2}|hyperpage}}
%}
%\end{verbatim}
%
-%\begin{definition}
-%\counterfmt{DTLmaxauthors}
+%\begin{definition}[\DescribeCounter{DTLmaxauthors}]
+%\ctrfmt{DTLmaxauthors}
%\end{definition}
-%The counter \counterfmt{DTLmaxauthors} is used to determine the
+%The counter \ctrfmt{DTLmaxauthors} is used to determine the
%maximum number of authors to display for a given entry. If the
%entry's author list contains more than that number of authors,
%\cs{etalname} is used, the definition of which is given in
%\autoref{sec:src:bibnames}. The default value of
-%\counterfmt{DTLmaxauthors} is \theDTLmaxauthors.
+%\ctrfmt{DTLmaxauthors} is \theDTLmaxauthors.
%
-%\begin{definition}
-%\counterfmt{DTLmaxeditors}
+%\begin{definition}[\DescribeCounter{DTLmaxeditors}]
+%\ctrfmt{DTLmaxeditors}
%\end{definition}
-%The \counterfmt{DTLmaxeditors} counter is analogous to the
-%\counterfmt{DTLmaxauthors} counter. It is used to determine the
+%The \ctrfmt{DTLmaxeditors} counter is analogous to the
+%\ctrfmt{DTLmaxauthors} counter. It is used to determine the
%maximum number of editor names to display. The default value
-%of \counterfmt{DTLmaxeditors} is \theDTLmaxeditors.
+%of \ctrfmt{DTLmaxeditors} is \theDTLmaxeditors.
%
%\DescribeMacro{\DTLandlast}
%Within a list of author or editor names, \cs{DTLandlast} is
@@ -7116,7 +7284,7 @@ options>#2=\textsf{#2}|hyperpage}}
%is stored in \meta{cmd}, which may then be used in the
%argument of the \env{thebibliography} environment.
%
-%The counter \counterfmt{DTLbibrow} keeps track of the current
+%The counter \desctr{DTLbibrow} keeps track of the current
%bibliography entry. This is reset at the start of each
%\cs{DTLforeachbib} and is incremented if \meta{conditions}
%is met.
@@ -7293,10 +7461,475 @@ options>#2=\textsf{#2}|hyperpage}}
%database using \ics{DTLnewdb} and setting \ics{DTLBIBdbname} to
%the name of the database.
%
+%\section{Referencing People (\sty{person} package)}
+%\label{sec:person}
+%
+%Sometimes when mail-merging, it may be necessary to reference a
+%person by their pronoun which can lead to the cumbersome and
+%impersonal ``he/she'' construct. The \sty{person} package
+%allows you to define a person by their full name, familiar name and
+%gender. You can then use the commands described in
+%\autoref{sec:refperson} to produce the appropriate pronoun.
+%
+%This can also be useful for other types of documents, such as an
+%order of service for a baptism or funeral. Since the
+%document is much the same from one person to the next, documents of
+%this nature are frequently simply copied and a search and replace
+%edit is used to change the relevant text. However this can lead to
+%errors (especially if the previous person's name was Mary!) With
+%the \sty{person} package, you need only change the definition of
+%the person by modifying the arguments of \cs{newperson}.
+%
+%\subsection{Defining and Undefining People}
+%
+%A person is defined (globally) using the command:
+%\begin{definition}[\DescribeMacro{\newperson}]
+%\cs{newperson}\oarg{label}\marg{full name}\marg{familiar name}\marg{gender}
+%\end{definition}
+%The optional argument is a unique label identifying this person,
+%in the event that there is more than one person. If \meta{label}
+%is omitted \texttt{anon} is used. (This is also the case for
+%subsequent commands that take an optional label.)
+%The gender may be any of those given by
+%\begin{definition}[\DescribeMacro{\malelabels}]
+%\cs{malelabels}
+%\end{definition}
+%or
+%\begin{definition}[\DescribeMacro{\femalelabels}]
+%\cs{femalelabels}
+%\end{definition}
+%The default definition of \cs{malelabels} is \texttt{\malelabels}
+%and the default definition of \cs{femalelabels} is
+%\texttt{\femalelabels}. You can add extra identifiers using
+%\begin{definition}[\DescribeMacro{\addmalelabel}]
+%\cs{addmalelabel}\marg{identifier}
+%\end{definition}
+%or
+%\begin{definition}[\DescribeMacro{\addfemalelabel}]
+%\cs{addfemalelabel}\marg{identifier}
+%\end{definition}
+%For example:
+%\begin{verbatim}
+%\addmalelabel{boy}
+%\addfemalelabel{girl}
+%\end{verbatim}
+%
+%The total number of defined people is given by:
+%\begin{definition}[\DescribeMacro{\thepeople}]
+%\cs{thepeople}
+%\end{definition}
+%
+%A person can be undefined using:
+%\begin{definition}[\DescribeMacro{\removeperson}]
+%\cs{removeperson}\oarg{label}
+%\end{definition}
+%where the person is given by \meta{label}.
+%
+%If more than one person has been defined, they can all be
+%removed using:
+%\begin{definition}[\DescribeMacro{\removeallpeople}]
+%\cs{removeallpeople}
+%\end{definition}
+%or you can remove a subset using:
+%\begin{definition}[\DescribeMacro{\removepeople}]
+%\cs{removepeople}\marg{list}
+%\end{definition}
+%where \meta{list} is a comma-separated list of labels.
+%
+%\subsection{Displaying Information}
+%\label{sec:refperson}
+%
+%Once a person has been defined, you can display their name using:
+%\begin{definition}[\DescribeMacro{\personfullname}]
+%\cs{personfullname}\oarg{label}
+%\end{definition}
+%where \meta{label} is the unique label used in the optional
+%argument to \cs{newperson}. The person's familiar name is displayed
+%using:
+%\begin{definition}[\DescribeMacro{\personname}]
+%\cs{personname}\oarg{label}
+%\end{definition}
+%The person's pronoun (``he'' or ``she'') is displayed using:
+%\begin{definition}[\DescribeMacro{\personpronoun}]
+%\cs{personpronoun}\oarg{label}
+%\end{definition}
+%The objective pronoun (``him'' or ``her'') is displayed using:
+%\begin{definition}[\DescribeMacro{\personobjpronoun}]
+%\cs{personobjpronoun}\oarg{label}
+%\end{definition}
+%The possessive adjective (``his'' or ``her'') is displayed using:
+%\begin{definition}[\DescribeMacro{\personpossadj}]
+%\cs{personpossadj}\oarg{label}
+%\end{definition}
+%The possessive pronoun ``his'' or ``hers'' is displayed using:
+%\begin{definition}[\DescribeMacro{\personposspronoun}]
+%\cs{personposspronoun}\oarg{label}
+%\end{definition}
+%The person's relationship to their parent (``son'' or ``daughter'')
+%is displayed using:
+%\begin{definition}[\DescribeMacro{\personchild}]
+%\cs{personchild}\oarg{label}
+%\end{definition}
+%The person's relationship to their child (``mother'' or ``father'')
+%is displayed using:
+%\begin{definition}[\DescribeMacro{\personparent}]
+%\cs{personparent}\oarg{label}
+%\end{definition}
+%The person's relationship to their sibling (``brother'' or
+%``sister'') is displayed using:
+%\begin{definition}[\DescribeMacro{\personsibling}]
+%\cs{personsibling}\oarg{label}
+%\end{definition}
+%
+%If the word occurs at the start of a sentence, you will need one
+%of the following commands, which are as the above, except the
+%first letter is converted to upper case:
+%\begin{definition}[\DescribeMacro{\Personpronoun}]
+%\cs{Personpronoun}\oarg{label}
+%\end{definition}
+%\begin{definition}[\DescribeMacro{\Personobjpronoun}]
+%\cs{Personobjpronoun}\oarg{label}
+%\end{definition}
+%\begin{definition}[\DescribeMacro{\Personpossadj}]
+%\cs{Personpossadj}\oarg{label}
+%\end{definition}
+%\begin{definition}[\DescribeMacro{\Personposspronoun}]
+%\cs{Personposspronoun}\oarg{label}
+%\end{definition}
+%\begin{definition}[\DescribeMacro{\Personchild}]
+%\cs{Personchild}\oarg{label}
+%\end{definition}
+%\begin{definition}[\DescribeMacro{\Personparent}]
+%\cs{Personparent}\oarg{label}
+%\end{definition}
+%\begin{definition}[\DescribeMacro{\Personsibling}]
+%\cs{Personsibling}\oarg{label}
+%\end{definition}
+%
+%\begin{example}{Order of Service (Memorial)}{ex:memorial}
+%This example is for a memorial order of service.
+%
+%\begin{verbatim}
+%\documentclass{article}
+%
+%\usepackage{person}
+%
+%\newperson{Jane Doe}{Jane}{female}
+%
+%\begin{document}
+%\begin{center}
+%\Large
+%In Memory of \personfullname
+%\end{center}
+%
+%We are gathered here to remember our \personsibling\ \personname.
+%\Personpronoun\ will be much missed, and \personpossadj\
+%family are in our prayers.
+%\end{document}
+%\end{verbatim}
+%
+%\newperson{Jane Doe}{Jane}{female}
+%\begin{center}
+%\Large
+%In Memory of \personfullname
+%\end{center}
+%
+%We are gathered here to remember our \personsibling\ \personname.
+%\Personpronoun\ will be much missed, and \personpossadj\
+%family are in our prayers.
+%\removeperson
+%
+%\end{example}
+%
+%If there is more than one person, you will need to use the
+%optional argument \meta{label} to \cs{newperson} to uniquely
+%identify each person. You can then list all of the people's full
+%or familiar names using:
+%\begin{definition}[\DescribeMacro{\peoplefullname}]
+%\cs{peoplefullname}
+%\end{definition}
+%\begin{definition}[\DescribeMacro{\peoplename}]
+%\cs{peoplename}
+%\end{definition}
+%Note that if there is only one person defined, these commands behave
+%the same as \cs{personfullname}\oarg{label} and
+%\cs{personname}[\meta{label}].
+%
+%Similarly for the pronouns:
+%\begin{definition}[\DescribeMacro{\peoplepronoun}]
+%\cs{peoplepronoun}
+%\end{definition}
+%\begin{definition}[\DescribeMacro{\Peoplepronoun}]
+%\cs{Peoplepronoun}
+%\end{definition}
+%\begin{definition}[\DescribeMacro{\peopleobjpronoun}]
+%\cs{peopleobjpronoun}
+%\end{definition}
+%\begin{definition}[\DescribeMacro{\Peopleobjpronoun}]
+%\cs{Peopleobjpronoun}
+%\end{definition}
+%\begin{definition}[\DescribeMacro{\peoplepossadj}]
+%\cs{peoplepossadj}
+%\end{definition}
+%\begin{definition}[\DescribeMacro{\Peoplepossadj}]
+%\cs{Peoplepossadj}
+%\end{definition}
+%\begin{definition}[\DescribeMacro{\peopleposspronoun}]
+%\cs{peopleposspronoun}
+%\end{definition}
+%\begin{definition}[\DescribeMacro{\Peopleposspronoun}]
+%\cs{Peopleposspronoun}
+%\end{definition}
+%where, again, if only one person has been defined, each of these
+%commands is equivalent to
+%\cs{person}\ldots\oarg{label} or
+%\cs{Person}\ldots\oarg{label}. If more than
+%one person has been defined, these commands will display
+%they/them/their/theirs or They/Them/Their/Theirs, as appropriate.
+%
+%Likewise for relationship commands:
+%\begin{definition}[\DescribeMacro{\peoplechild}]
+%\cs{peoplechild}
+%\end{definition}
+%\begin{definition}[\DescribeMacro{\Peoplechild}]
+%\cs{Peoplechild}
+%\end{definition}
+%\begin{definition}[\DescribeMacro{\peopleparent}]
+%\cs{peopleparent}
+%\end{definition}
+%\begin{definition}[\DescribeMacro{\Peopleparent}]
+%\cs{Peopleparent}
+%\end{definition}
+%\begin{definition}[\DescribeMacro{\peoplesibling}]
+%\cs{peoplesibling}
+%\end{definition}
+%\begin{definition}[\DescribeMacro{\Peoplesibling}]
+%\cs{Peoplesibling}
+%\end{definition}
+%
+%\begin{example}{Order of Service (Baptism)}{ex:baptism}
+%In this example two people are defined.
+%\begin{verbatim}
+%\documentclass{article}
+%
+%\usepackage{person}
+%
+%\newperson[john]{John Joseph}{John}{male}
+%\newperson[jane]{Jane Mary}{Jane}{female}
+%
+%\begin{document}
+%\begin{center}
+%\Large
+%Baptism of \peoplefullname.
+%\end{center}
+%
+%Today we welcome \peoplename\ into God's family, may He guide
+%and protect \peopleobjpronoun.
+%\end{document}
+%\end{verbatim}
+%
+%This is produces the following text:
+%
+%\newperson[john]{John Joseph}{John}{male}
+%\newperson[jane]{Jane Mary}{Jane}{female}
+%
+%\begin{center}
+%\Large
+%Baptism of \peoplefullname.
+%\end{center}
+%
+%Today we welcome \peoplename\ into God's family, may He guide
+%and protect \peopleobjpronoun.
+%\removeallpeople
+%\end{example}
+%
+%\begin{example}{Mail Merging Using Appropriate Gender}{ex:personmerge}
+%In this example I have a CSV file called \texttt{students.csv}
+%containing the following:
+%\begin{verbatim}
+%FirstName,Surname,Gender,Parent,Address
+%John,"Smith, Jr",M,Mr and Mrs Smith,1 The Street\\Newtown
+%Jane,Brown,F,Ms Brown,2 The Avenue\\Oldtown
+%Andy,Brown,male,Mr Brown and Miss Sepia,3 The Road\\Newtown
+%Z\"oe,Adams,f,Mr and Mrs Adams,5 The Street\\Newtown
+%Roger,Brady,m,Mrs Brady,6 The Avenue\\Oldtowm
+%Clare,Vernon,female,Mr Vernon,7 The Close\\Anytown
+%\end{verbatim}
+%Suppose I have to write to each student's parents regarding their
+%child. I can load the information using \ics{DTLloaddb} (described
+%in \autoref{sec:loaddb}). I can then iterate through the database
+%and define the student as a person and use the commands defined in
+%the \sty{person} package to display the correct gender related text.
+%I could give each person a unique label based on the row count
+%(\ics{DTLcurrentindex}), but since I don't need to reuse the
+%information, I can use the default "anon" label and undefine the
+%person when no longer required.
+%
+%Note that in the CSV file, the gender label isn't consistent.
+%For some students the gender is identified by a single letter
+%(``m'' or ``f'') and for others the gender is identified by a
+%complete word (``male'' or ``female''). There's also no regard
+%for case. This doesn't matter to \ics{newperson} as all the
+%identifiers used are listed in \ics{malelabels} and
+%\ics{femalelabels}.
+%
+%The following is an example letter sent to all parents:
+%\begin{verbatim}
+%\documentclass{letter}
+%\usepackage{person}
+%
+%% load student information from file "students.csv"
+%\DTLloaddb{students}{students.csv}
+%\begin{document}
+%% Iterate through the student database:
+%\DTLforeach{students}{\FirstName=FirstName,\Surname=Surname,%
+%\Gender=Gender,\Parent=Parent,\Address=Address}{%
+%% Define "anon":
+% \newperson{\FirstName\space\Surname}{\FirstName}{\Gender}%
+%% Do the letter:
+% \begin{letter}{\Parent\\\Address}
+% \opening{Dear \Parent}
+% Your \personchild\ \personname\ has been awarded a
+% place. We look forward to seeing \personobjpronoun\
+% on \personpossadj\ arrival.
+% \closing{Yours Sincerely}
+% \end{letter}
+%% Undefine "anon":
+% \removeperson
+%}
+%\end{document}
+%\end{verbatim}
+%
+%The body of the first letter appears as follows:
+%\newperson{John Smith Jr}{John}{m}
+%\par\vskip\baselineskip
+%
+% Your \personchild\ \personname\ has been awarded a
+% place. We look forward to seeing \personobjpronoun\
+% on \personpossadj\ arrival.
+%
+%\removeperson
+%\par\vskip\baselineskip
+%Whereas the body of the second letter appears as follows:
+%\newperson{Jane Brown}{Jane}{f}
+%\par\vskip\baselineskip
+%
+% Your \personchild\ \personname\ has been awarded a
+% place. We look forward to seeing \personobjpronoun\
+% on \personpossadj\ arrival.
+%
+%\removeperson
+%\end{example}
+%
+%\subsection{Advanced Commands}
+%
+%This section describes additional commands provided by the
+%\sty{person} package. More detail can be found in
+%\autoref{sec:code:person}.
+%
+%\subsubsection{Conditionals}
+%
+%\begin{definition}[\DescribeMacro{\ifpersonexists}]
+%\cs{ifpersonexists}\marg{label}\marg{true part}\marg{false part}
+%\end{definition}
+%Tests if the person identified by \meta{label} has been defined.
+%If true, do \meta{true part} otherwise do \meta{false part}.
+%
+%\begin{definition}[\DescribeMacro{\ifmale}]
+%\cs{ifmale}\marg{label}\marg{true part}\marg{false part}
+%\end{definition}
+%Test if the person identified by \meta{label} is male.
+%If true, do \meta{true part} otherwise do \meta{false part}.
+%
+%\begin{definition}[\DescribeMacro{\iffemale}]
+%\cs{iffemale}\marg{label}\marg{true part}\marg{false part}
+%\end{definition}
+%Test if the person identified by \meta{label} is female.
+%If true, do \meta{true part} otherwise do \meta{false part}.
+%
+%\begin{definition}[\DescribeMacro{\ifallmale}]
+%\cs{ifallmale}\oarg{label list}\marg{true part}\marg{false part}
+%\end{definition}
+%Tests if all the people listed in \meta{label list} are male.
+%If true, do \meta{true part} otherwise do \meta{false part}.
+%If \meta{label list} is omitted, applied to all defined people.
+%\begin{definition}[\DescribeMacro{\ifallfemale}]
+%\cs{ifallfemale}\oarg{label list}\marg{true part}\marg{false part}
+%\end{definition}
+%Likewise to test if all the people tested are female.
+%
+%To determine if a string is an allowed male label:
+%\begin{definition}[\DescribeMacro{\ifmalelabel}]
+%\cs{ifmalelabel}\marg{identifier}\marg{true part}\marg{false part}
+%\end{definition}
+%where \meta{identifier} is the string to be tested. If true, do
+%\meta{true part} otherwise do \meta{false part}.
+%For example:
+%\begin{verbatim}
+%\def\gender{M}
+%\ifmalelabel{\gender}{male}{not male}
+%\end{verbatim}
+%Similarly to for an allowed female label:
+%\begin{definition}[\DescribeMacro{\iffemalelabel}]
+%\cs{iffemalelabel}\marg{identifier}\marg{true part}\marg{false part}
+%\end{definition}
+%For example:
+%\begin{verbatim}
+%\ifmalelabel{\gender}{Male}{%
+% \iffemalelabel{\gender}{Female}%
+% {Undefined Gender}%
+%}
+%\end{verbatim}
+%
+%\subsubsection{Iterating Through Defined People}
+%
+%You can iterate through all defined people using:
+%\begin{definition}[\DescribeMacro{\foreachperson}]
+%\cs{foreachperson}(\meta{name cs},\meta{full name cs},\meta{gender cs},\meta{label cs})\cs{do}\marg{body}
+%\end{definition}
+%At each iteration, \meta{name cs}, \meta{full name cs},
+%\meta{gender cs} and \meta{label cs} are set to the current person's
+%name, full name, gender and label, respectively. (These arguments
+%must all be command names.) Note that the gender is set to
+%the definition of \DescribeMacro{\malename}\cs{malename} or
+%\DescribeMacro{\femalename}\cs{femalename}, as appropriate.\footnote{Predefined names provided by the \sty{person} package are described
+%in \autoref{sec:code:peoplenames}.} Once these
+%commands are set, \meta{body} is applied.
+%
+%If you only want to iterate through a subset of defined people,
+%you can use:
+%\begin{definition}
+%\cs{foreachperson}(\meta{name cs},\meta{full name cs},\meta{gender cs},\meta{label cs})\cs{in}\marg{list}\cs{do}\marg{body}
+%\end{definition}
+%where \meta{list} is a comma-separated list of labels.
+%
+%\subsubsection{Accessing Individual Information}
+%
+%\begin{definition}[\DescribeMacro{\getpersongender}]
+%\cs{getpersongender}\marg{cs}\marg{label}
+%\end{definition}
+%Gets the gender of the person identified by \meta{label} and
+%stores in \meta{cs} (which must be a command name). This
+%sets \meta{cs} to the definition of \ics{malename} or
+%\ics{femalename} as appropriate.
+%
+%\begin{definition}[\DescribeMacro{\getpersonname}]
+%\cs{getpersonname}\marg{cs}\marg{label}
+%\end{definition}
+%Gets the name of the person identified by \meta{label} and
+%stores in \meta{cs} (which must be a command name).
+%
+%\begin{definition}[\DescribeMacro{\getpersonfullname}]
+%\cs{getpersonfullname}\marg{cs}\marg{label}
+%\end{definition}
+%Gets the full name of the person identified by \meta{label} and
+%stores in \meta{cs} (which must be a command name).
+%
% \StopEventually{\clearpage\phantomsection
%\addcontentsline{toc}{section}{\refname}
% \DTLbibliography{docbib}
-%\section{Acknowledgements}
+%\addcontentsline{toc}{section}{Acknowledgements}
+%\section*{Acknowledgements}
%
%Many thanks to Morten~H\o gholm for suggesting a much more
%efficient way of storing the information in databases which
@@ -7305,6 +7938,7 @@ options>#2=\textsf{#2}|hyperpage}}
%
%\phantomsection
%\addcontentsline{toc}{section}{Change History}\PrintChanges
+%\clearpage
%\phantomsection
%\addcontentsline{toc}{section}{Index}\PrintIndex
%}
@@ -7317,10 +7951,11 @@ options>#2=\textsf{#2}|hyperpage}}
%<*datatool.sty>
% \end{macrocode}
%\fi
+%\label{sec:code:datatool}
%\subsection{Package Declaration}
% \begin{macrocode}
\NeedsTeXFormat{LaTeX2e}
-\ProvidesPackage{datatool}[2009/07/13 v2.02 (NLCT)]
+\ProvidesPackage{datatool}[2009/11/15 v2.03 (NLCT)]
% \end{macrocode}
% Load required packages:
% \begin{macrocode}
@@ -9938,9 +10573,11 @@ options>#2=\textsf{#2}|hyperpage}}
% the database name.
%
%\begin{macro}{\DTLnewdb}
+%\begin{definition}
+% \cs{DTLnewdb}\marg{db name}
+%\end{definition}
%\changes{2.0}{2009 February 27}{Changed way database is stored}
-% \cs{DTLnewdb}\marg{name}
-% initialises a database called \meta{name}.
+% Initialises a database called \meta{name}.
% \begin{macrocode}
\newcommand*{\DTLnewdb}[1]{%
% \end{macrocode}
@@ -9977,6 +10614,60 @@ options>#2=\textsf{#2}|hyperpage}}
% \end{macrocode}
%\end{macro}
%
+%\begin{macro}{\DTLcleardb}
+%\begin{definition}
+% \cs{DTLcleardb}\marg{db name}
+%\end{definition}
+% Clears the database. (Makes it empty, but still defined.)
+%\changes{2.03}{2009 November 15}{new}
+% \begin{macrocode}
+\newcommand*{\DTLcleardb}[1]{%
+ \DTLifdbexists{#1}%
+ {%
+ \dtlforeachkey(\@dtl@key,\@dtl@col,\@dtl@type,\@dtl@head)\in{#1}\do
+ {%
+ \expandafter\let\csname dtl@ci@#1@\@dtl@key\endcsname\undefined
+ }%
+ \csname dtldb@#1\endcsname{}%
+ \csname dtlkeys@#1\endcsname{}%
+ \csname dtlrows@#1\endcsname=0\relax
+ \csname dtlcols@#1\endcsname=0\relax
+ }%
+ {%
+ \PackageError{Can't clear database `#1':
+ database doesn't exist}{}{}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLdeletedb}
+%\begin{definition}
+% \cs{DTLdeletedb}\marg{db name}
+%\end{definition}
+% Deletes a database.
+%\changes{2.03}{2009 November 15}{new}
+% \begin{macrocode}
+\newcommand*{\DTLdeletedb}[1]{%
+ \DTLifdbexists{#1}%
+ {%
+ \dtlforeachkey(\@dtl@key,\@dtl@col,\@dtl@type,\@dtl@head)\in{#1}\do
+ {%
+ \expandafter\let\csname dtl@ci@#1@\@dtl@key\endcsname\undefined
+ }%
+ \expandafter\let\csname dtldb@#1\endcsname\undefined
+ \expandafter\let\csname dtlkeys@#1\endcsname\undefined
+ \expandafter\let\csname dtlrows@#1\endcsname\undefined
+ \expandafter\let\csname dtlcols@#1\endcsname\undefined
+ }%
+ {%
+ \PackageError{Can't delete database `#1':
+ database doesn't exist}{}{}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
%\begin{macro}{\DTLrowcount}
%\begin{definition}
% \cs{DTLrowcount}\marg{db name}
@@ -10225,15 +10916,17 @@ options>#2=\textsf{#2}|hyperpage}}
% \end{macrocode}
%\end{macro}
%
-%\begin{macro}{\dtl@columnindex}
+%\begin{macro}{\dtlcolumnindex}
%\begin{definition}
-% \cs{dtl@columnindex}\marg{db}\marg{key}
+% \cs{dtlcolumnindex}\marg{db}\marg{key}
%\end{definition}
% Column index corresponding to \meta{key} in database \meta{db}.
% (No check for existance of database or key.)
%\changes{2.0}{2009 February 27}{new}
+%\changes{2.03}{2009 November 15}{renamed \cs{dtl@columnindex} to
+%\cs{dtlcolumnindex}}
% \begin{macrocode}
-\newcommand*{\dtl@columnindex}[2]{%
+\newcommand*{\dtlcolumnindex}[2]{%
\csname dtl@ci@#1@#2\endcsname
}
% \end{macrocode}
@@ -10423,7 +11116,7 @@ options>#2=\textsf{#2}|hyperpage}}
\newcommand*{\@sdtlgetdatatype}[3]{%
\edef\@dtl@dogetdata{\noexpand\@dtl@getdatatype{\noexpand#1}%
{\expandafter\the\csname dtlkeys@#2\endcsname}%
- {\dtl@columnindex{#2}{#3}}}%
+ {\dtlcolumnindex{#2}{#3}}}%
\@dtl@dogetdata
}
% \end{macrocode}
@@ -10520,7 +11213,7 @@ options>#2=\textsf{#2}|hyperpage}}
% column index.
% \begin{macrocode}
\expandafter\dtlcolumnnum\expandafter
- =\dtl@columnindex{#1}{#2}\relax
+ =\dtlcolumnindex{#1}{#2}\relax
% \end{macrocode}
% Get the properties for this column
% \begin{macrocode}
@@ -10700,7 +11393,7 @@ options>#2=\textsf{#2}|hyperpage}}
% \begin{macrocode}
\newcommand*{\@sDTLsetheader}[3]{%
\expandafter\dtlcolumnnum\expandafter
- =\dtl@columnindex{#1}{#2}\relax
+ =\dtlcolumnindex{#1}{#2}\relax
\@dtl@setheaderforindex{#1}{\dtlcolumnnum}{#3}%
}
% \end{macrocode}
@@ -10751,6 +11444,28 @@ options>#2=\textsf{#2}|hyperpage}}
% \end{macrocode}
%\end{macro}
%
+%\begin{macro}{\dtlexpandnewvalue}
+% Expand new value before adding to database
+% \begin{macrocode}
+\newcommand*{\dtlexpandnewvalue}{%
+ \def\@dtl@setnewvalue##1{\protected@edef\@dtl@tmp{##1}%
+ \expandafter\@dtl@toks\expandafter{\@dtl@tmp}}%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtlnoexpandnewvalue}
+% Don't expand new value before adding to database
+% \begin{macrocode}
+\newcommand*{\dtlnoexpandnewvalue}{%
+ \def\@dtl@setnewvalue##1{\@dtl@toks{##1}}%
+}
+% \end{macrocode}
+% Do this by default:
+% \begin{macrocode}
+\dtlnoexpandnewvalue
+% \end{macrocode}
+%\end{macro}
+%
%\begin{macro}{\DTLnewdbentry}
%\begin{definition}
% \cs{DTLnewdbentry}\marg{db name}\marg{id}\marg{value}.
@@ -10788,7 +11503,7 @@ options>#2=\textsf{#2}|hyperpage}}
% Get the column index
% \begin{macrocode}
\expandafter\dtlcolumnnum\expandafter
- =\dtl@columnindex{#1}{#2}\relax
+ =\dtlcolumnindex{#1}{#2}\relax
% \end{macrocode}
% Get the current row:
% \begin{macrocode}
@@ -10805,8 +11520,10 @@ options>#2=\textsf{#2}|hyperpage}}
\ifx\dtl@entry\dtlnovalue
% \end{macrocode}
% Store the value of this entry in \cs{@dtl@toks}
+%\changes{2.03}{2009 November 15}{value can be expanded before
+% adding to database}%
% \begin{macrocode}
- \@dtl@toks{#3}%
+ \@dtl@setnewvalue{#3}%
% \end{macrocode}
% There are no entries in this row for the given column.
% Add this entry.
@@ -10913,22 +11630,24 @@ options>#2=\textsf{#2}|hyperpage}}
%\begin{definition}
% \cs{@dtl@assigncmd}\meta{cmd}=\meta{id}\cs{@nil}
%\end{definition}
+%\changes{2.03}{2009 November 15}{modified to ignore spaces after
+% commas}
% \begin{macrocode}
-\def\@dtl@assigncmd#1=#2,#3\@@#4{%
+\def\@dtl@assigncmd#1#2=#3,#4\@@#5{%
% \end{macrocode}
-% get entry for ID given by \#2 and store in \#1
+% get entry for ID given by \#3 and store in \#2
% \begin{macrocode}
- \@sDTLifhaskey{#4}{#2}%
+ \@sDTLifhaskey{#5}{#3}%
{%
\edef\@dtl@dogetentry{%
\noexpand\dtlgetentryfromcurrentrow
- {\noexpand#1}{\dtl@columnindex{#4}{#2}}}%
+ {\noexpand#1}{\dtlcolumnindex{#5}{#3}}}%
\@dtl@dogetentry
% \end{macrocode}
% Set to null if required
% \begin{macrocode}
\ifx#1\dtlnovalue
- \@@dtl@setnull{#1}{#2}%
+ \@@dtl@setnull{#1}{#3}%
\fi
% \end{macrocode}
% Make it global
@@ -10937,7 +11656,7 @@ options>#2=\textsf{#2}|hyperpage}}
}%
{%
\PackageError{datatool}{Can't assign \string#1\space: there
- is no key `#2' in data base `#4'}{}%
+ is no key `#3' in data base `#5'}{}%
% \end{macrocode}
% Set to null
% \begin{macrocode}
@@ -10946,13 +11665,13 @@ options>#2=\textsf{#2}|hyperpage}}
% \end{macrocode}
% Recurse?
% \begin{macrocode}
- \def\dtl@tmp{#3}%
+ \def\dtl@tmp{#4}%
\ifx\@nnil\dtl@tmp
\let\@dtl@next\@dtl@assigncmdnoop
\else
\let\@dtl@next\@dtl@assigncmd
\fi
- \@dtl@next#3\@@{#4}%
+ \@dtl@next#4\@@{#5}%
}
% \end{macrocode}
%\end{macro}
@@ -11195,9 +11914,9 @@ options>#2=\textsf{#2}|hyperpage}}
%\begin{macro}{\@dtlgetrow}
%\begin{definition}
%\cs{@dtlgetrow}\marg{data specs}\marg{row idx}
+%\end{definition}
% Gets the row specs from \meta{data specs} for row with index
% \meta{row idx} which must be fully expanded.
-%\end{definition}
% \begin{macrocode}
\newcommand*{\@dtlgetrow}[2]{%
\def\@dtl@getrow##1% before stuff
@@ -11734,7 +12453,7 @@ options>#2=\textsf{#2}|hyperpage}}
\toks@{#4}%
\edef\@dtl@doforcol{\noexpand\dtl@forcolumn{\noexpand#1}%
{\expandafter\the\csname dtldb@#2\endcsname}%
- {\dtl@columnindex{#2}{#3}}{\the\toks@}%
+ {\dtlcolumnindex{#2}{#3}}{\the\toks@}%
}%
\@dtl@doforcol%
}
@@ -12464,7 +13183,7 @@ options>#2=\textsf{#2}|hyperpage}}
% Get column index and store in \cs{dtlcolumnnum}
% \begin{macrocode}
\expandafter\dtlcolumnnum\expandafter
- =\dtl@columnindex{\@dtl@thisdb}{#1}\relax
+ =\dtlcolumnindex{\@dtl@thisdb}{#1}\relax
% \end{macrocode}
% Set \cs{dtlcurrentrow} to the current row
% \begin{macrocode}
@@ -12480,9 +13199,11 @@ options>#2=\textsf{#2}|hyperpage}}
\ifx\dtl@entry\dtlnovalue
% \end{macrocode}
% There are no entries in this row for the given key.
-% Store value in \cs{@dtl@toks} with one level expansion.
+% Expand entry value before storing.
+%\changes{2.03}{2009 November 15}{value expanded before storing}
% \begin{macrocode}
- \expandafter\@dtl@toks\expandafter{#2}%
+ \protected@edef\@dtl@tmp{#2}%
+ \expandafter\@dtl@toks\expandafter{\@dtl@tmp}%
% \end{macrocode}
% Append this entry to the current row.
% \begin{macrocode}
@@ -12689,9 +13410,11 @@ options>#2=\textsf{#2}|hyperpage}}
}%
\@dtl@dosplitrow
% \end{macrocode}
-% Reconstruct row with new entry
+% Reconstruct row with new value (given by \verb|#2|).
+%\changes{2.03}{2009 November 15}{expand replacement entry}
% \begin{macrocode}
- \@dtl@toks{#2}% new value
+ \protected@edef\@dtl@tmp{#2}%
+ \expandafter\@dtl@toks\expandafter{\@dtl@tmp}% new value
\expandafter\@dtl@before\expandafter{\dtl@pre}%
\expandafter\@dtl@after\expandafter{\dtl@post}%
\toks@gconcat@middle@cx
@@ -15042,8 +15765,803 @@ options>#2=\textsf{#2}|hyperpage}}
% \end{macrocode}
%\end{macro}
%
+%\subsection{Saving a database to an external file}
+%
+%\begin{macro}{\@dtl@write}
+% \begin{macrocode}
+\newwrite\@dtl@write
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\DTLsavedb}
+%\begin{definition}
+% \cs{DTLsavedb}\marg{db name}\marg{filename}
+%\end{definition}
+% Save a database as an ASCII data file using the separator
+% and delimiter given by \cs{@dtl@separator} and \cs{@dtl@delimiter}.
+%\changes{2.0}{2009 February 27}{updated to use new database structure}
+% \begin{macrocode}
+\newcommand*{\DTLsavedb}[2]{%
+ \DTLifdbexists{#1}%
+ {%
+% \end{macrocode}
+% Open output file
+%\changes{2.02}{2009 July 13}{Fixed bug that didn't set the filename}
+% \begin{macrocode}
+ \openout\@dtl@write=#2\relax
+% \end{macrocode}
+% Initialise header row
+% \begin{macrocode}
+ \def\@dtl@header{}%
+% \end{macrocode}
+% Construct the header row
+% \begin{macrocode}
+ \dtlforeachkey(\@dtl@key,\@dtl@col,\@dtl@type,\@dtl@head)%
+ \in{#1}\do
+ {%
+ \IfSubStringInString{\@dtl@separator}{\@dtl@key}%
+ {%
+ \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\changes{2.03}{2009 November 15}{Moved outside loop}
+% \begin{macrocode}
+ \protected@write\@dtl@write{}{\@dtl@row}%
+ }%
+% \end{macrocode}
+% Close output file
+% \begin{macrocode}
+ \closeout\@dtl@write
+ }%
+ {%
+ \PackageError{datatool}{Can't save database `#1': no such
+ database}{}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLsavetexdb}
+%\begin{definition}
+% \cs{DTLsavetexdb}\marg{db name}\marg{filename}
+%\end{definition}
+% Save a database as a \LaTeX\ file.
+%\changes{2.0}{2009 February 27}{updated to use new database structure}
+% \begin{macrocode}
+\newcommand*{\DTLsavetexdb}[2]{%
+ \DTLifdbexists{#1}%
+ {%
+% \end{macrocode}
+% Open output file
+% \begin{macrocode}
+ \openout\@dtl@write=#2\relax
+% \end{macrocode}
+% Write new data base definition
+% \begin{macrocode}
+ \protected@write\@dtl@write{}{\string\DTLnewdb{#1}}%
+% \end{macrocode}
+% Iterate through each row
+% \begin{macrocode}
+ \@sDTLforeach{#1}{}%
+ {%
+% \end{macrocode}
+% Start new row
+% \begin{macrocode}
+ \protected@write\@dtl@write{}{\string\DTLnewrow*{#1}}%
+% \end{macrocode}
+% Iterate through each column
+% \begin{macrocode}
+ \DTLforeachkeyinrow{\@dtl@val}%
+ {%
+% \end{macrocode}
+% Is this entry null?
+% \begin{macrocode}
+ \DTLifnull{\@dtl@val}%
+ {\def\@dtl@val{}}%
+ {}%
+% \end{macrocode}
+% Add entry
+% \begin{macrocode}
+ \protected@write\@dtl@write{}{%
+ \string\DTLnewdbentry*{#1}{\dtlkey}{\@dtl@val}}%
+ }%
+ }%
+% \end{macrocode}
+% Save the column headers.
+% \begin{macrocode}
+ \dtlforeachkey(\@dtl@k,\@dtl@c,\@dtl@t,\@dtl@h)\in{#1}\do
+ {%
+ \@onelevel@sanitize\@dtl@h
+ \protected@write\@dtl@write{}{%
+ \string\DTLsetheader*{#1}{\@dtl@k}{\@dtl@h}}%
+ }%
+% \end{macrocode}
+% 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
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtl@entrycr}
+% Keep track of current column in data file
+% \begin{macrocode}
+\newcount\dtl@entrycr
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\ifdtlnoheader}
+% The "noheader" option indicates that the file doesn't have a
+% header row.
+% \begin{macrocode}
+\define@boolkey{loaddb}[dtl]{noheader}[true]{}
+% \end{macrocode}
+%\end{macro}
+% 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}\oarg{options}\marg{db name}\marg{filename}
+%\end{definition}
+% Creates a new database called \meta{db name}, and loads the data
+% in \meta{filename} into it. The separator and delimiter used in
+% the file must match \cs{@dtl@separator} and \cs{@dtl@delimiter}.
+% The optional argument is a comma-separated list.
+%\changes{2.0}{2009 February 27}{removed checks to see if the
+% database exists when adding to it}
+%\changes{2.0}{2009 February 27}{added optional argument}
+% \begin{macrocode}
+\newcommand*{\DTLloaddb}{%
+ \let\@dtl@doreadline\@dtl@readline
+ \@dtlloaddb
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtlloaddb}
+% Loads database using \cs{@dtl@doreadline} to read and trim
+% line from file. (\cs{@dtl@doreadline} must be set before use.)
+% \begin{macrocode}
+\newcommand*{\@dtlloaddb}[3][]{%
+% \end{macrocode}
+% Check if file exists
+% \begin{macrocode}
+ \IfFileExists{#3}{%
+% \end{macrocode}
+% File exists. Locally change catcode of double quote character in
+% case it has been made active.
+% \begin{macrocode}
+ \begingroup
+ \catcode`\"12\relax
+% \end{macrocode}
+% Initialise default options
+% \begin{macrocode}
+ \dtlnoheaderfalse
+% \end{macrocode}
+% Get the options
+% \begin{macrocode}
+ \setkeys{loaddb}{#1}%
+% \end{macrocode}
+% Open the file for reading.
+% \begin{macrocode}
+ \openin\@dtl@read=#3%
+ \dtl@message{Reading `#3'}%
+% \end{macrocode}
+% Create the new database.
+% \begin{macrocode}
+ \DTLnewdb{#2}%
+% \end{macrocode}
+% Check if the file is empty.
+% \begin{macrocode}
+ \ifeof\@dtl@read
+% \end{macrocode}
+% File is empty, so just issue a warning.
+% \begin{macrocode}
+ \PackageWarning{datatool}{File `#3' has no data}%
+ \else
+% \end{macrocode}
+% Does the file have a header row?
+% \begin{macrocode}
+ \ifdtlnoheader
+ \else
+% \end{macrocode}
+% Remove initial blank rows
+% \begin{macrocode}
+ \loop
+% \end{macrocode}
+% Set repeat condition to false
+% \begin{macrocode}
+ \@dtl@conditionfalse
+% \end{macrocode}
+% Do nothing if reached the end of file
+% \begin{macrocode}
+ \ifeof\@dtl@read
+ \else
+% \end{macrocode}
+% Read a line from the file and store in \cs{@dtl@line}
+% \begin{macrocode}
+ \@dtl@doreadline\@dtl@read\@dtl@line
+% \end{macrocode}
+% If this is a blank row, set repeat condition to true
+% \begin{macrocode}
+ \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
+% \end{macrocode}
+% Close the input file
+% \begin{macrocode}
+ \closein\@dtl@read
+% \end{macrocode}
+% Set the headers if required
+% \begin{macrocode}
+ \edef\@dtl@maxcols{\expandafter
+ \number\csname dtlcols@#2\endcsname}%
+ \dtlgforint\dtl@entrycr=1\to\@dtl@maxcols\step1\do
+ {%
+ \@ifundefined{@dtl@inhd@\romannumeral\dtl@entrycr}%
+ {}%
+ {%
+ \expandafter\let\expandafter\@dtl@head
+ \csname @dtl@inhd@\romannumeral\dtl@entrycr\endcsname
+ \@dtl@toks=\expandafter{\@dtl@head}%
+ \edef\@dtl@dosetheader{\noexpand\@dtl@setheaderforindex
+ {#2}{\number\dtl@entrycr}{\the\@dtl@toks}}%
+ \@dtl@dosetheader
+ }%
+ }%
+% \end{macrocode}
+% End current scope
+% \begin{macrocode}
+ \endgroup
+% \end{macrocode}
+% End true part of if file exists
+% \begin{macrocode}
+ }{%
+% \end{macrocode}
+% Requested file not found on TeX's path
+% \begin{macrocode}
+ \PackageError{datatool}{Can't load database `#2' (file `#3'
+ doesn't exist)}{}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\dtl@trim}
+%\begin{definition}
+%\cs{dtl@trim}\marg{line}
+%\end{definition}
+% Trims the trailing space from \meta{line}.
+% \begin{macrocode}
+\newcommand{\dtl@trim}[1]{%
+\def\@dtl@trmstr{}%
+\expandafter\@dtl@starttrim#1\@nil%
+\let#1=\@dtl@trmstr
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@dtl@starttrim}
+% Start trimming
+% \begin{macrocode}
+\long\def\@dtl@starttrim#1#2{%
+\ifx\par#1%
+ \def\@dtl@dotrim{\@dtl@trim{} #2}%
+\else
+ \def\@dtl@dotrim{\@dtl@trim#1#2}%
+\fi
+\@dtl@dotrim%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@dtl@trim}
+% \begin{macrocode}
+\long\def\@dtl@trim#1 \@nil{\long\def\@dtl@trmstr{#1}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLloadrawdb}
+%\begin{definition}
+%\cs{DTLloadrawdb}\marg{db name}\marg{filename}
+%\end{definition}
+% Loads a raw database (substitutes "%" $\to$ "\%",
+% "$" $\to$ "\$", "&" $\to$ "\&", "#" $\to$ "\#",
+% "~" $\to$ "\textasciitilde", "_" $\to$ "\_"
+% and "^" $\to$ "\textasciicircum".) The user can add additional
+% mappings.
+% \begin{macrocode}
+\newcommand*\DTLloadrawdb{%
+ \let\@dtl@doreadline\@dtl@readrawline
+ \@dtlloaddb
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@rawread}
+%\begin{definition}
+% \cs{@dtl@rawread}\meta{number}to\meta{cmd}
+%\end{definition}
+% Reads in a raw line from file given by \meta{number}
+% converts special characters and stores in \meta{cmd}
+% \begin{macrocode}
+\begingroup
+\catcode`\%=\active
+\catcode`$=\active
+\catcode`&=\active
+\catcode`~=\active
+\catcode`_=\active
+\catcode`^=\active
+\catcode`#=\active
+\catcode`?=6\relax
+\catcode`<=1\relax
+\catcode`>=2\relax
+\catcode`\{=\active
+\catcode`\}=\active
+\gdef\@dtl@rawread?1to?2<\relax
+<<\catcode`\%=\active
+\catcode`$=\active
+\catcode`&=\active
+\catcode`~=\active
+\catcode`_=\active
+\catcode`^=\active
+\catcode`#=\active
+\catcode`\{=\active
+\catcode`\}=\active
+\def%<\noexpand\%>\relax
+\def$<\noexpand\$>\relax
+\def&<\&>\relax
+\def#<\#>\relax
+\def~<\noexpand\textasciitilde>\relax
+\def_<\noexpand\_>\relax
+\def^<\noexpand\textasciicircum>\relax
+\@dtl@activatebraces
+\@dtl@doreadraw?1?2>>>
+\gdef\@dtl@doreadraw?1?2<\relax
+\read?1 to \tmp
+\xdef?2<\tmp>\relax
+>
+\endgroup
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@dtl@activatebraces}
+% \cs{@dtl@activatebraces} resets braces for \cs{@dtl@rawread}
+% \begin{macrocode}
+\begingroup
+\catcode`\{=\active
+\catcode`\}=\active
+\catcode`<=1\relax
+\catcode`>=2\relax
+\gdef\@dtl@activatebraces<%
+ \catcode`\{=\active
+ \catcode`\}=\active
+ \def{<\noexpand\{>%
+ \def}<\noexpand\}>%
+>%
+\endgroup
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\DTLrawmap}
+%\begin{definition}
+%\cs{DTLrawmap}\marg{string}\marg{replacement}
+%\end{definition}
+% Additional mappings to perform when reading a raw data file
+% \begin{macrocode}
+\newcommand*{\DTLrawmap}[2]{%
+\expandafter\@dtl@toks\expandafter{\@dtl@rawmappings}%
+\ifx\@dtl@rawmappings\@empty
+ \def\@dtl@rawmappings{{#1}{#2}}%
+\else
+ \def\@dtl@tmp{{#1}{#2}}
+ \protected@edef\@dtl@rawmappings{\the\@dtl@toks,\@dtl@tmp}
+\fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@dtl@rawmappings}
+% List of mappings.
+% \begin{macrocode}
+\newcommand*{\@dtl@rawmappings}{}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\dtl@domappings}
+%\begin{definition}
+% \cs{dtl@domappings}\marg{cmd}
+%\end{definition}
+% Do all mappings in string given by \meta{cmd}.
+% \begin{macrocode}
+\newcommand*{\dtl@domappings}[1]{%
+\@for\@dtl@map:=\@dtl@rawmappings\do{%
+ \expandafter\DTLsubstitute\expandafter#1\@dtl@map
+}}
+% \end{macrocode}
+%\end{macro}
+%
%\subsection{General List Utilities}
%
+%\begin{macro}{\DTLifinlist}
+%\begin{definition}
+%\cs{DTLifinlist}\marg{element}\marg{list}\marg{true part}\marg{false part}
+%\end{definition}
+% If \meta{element} is contained in the comma-separated list given
+% by \meta{list}, then do \meta{true part} otherwise do false
+% part. (Does a one level expansion on \meta{list}, but no
+% expansion on \meta{element}.)
+% \begin{macrocode}
+\newcommand*{\DTLifinlist}[4]{%
+ \def\@dtl@doifinlist##1,#1,##2\end@dtl@doifinlist{%
+ \def\@before{##1}%
+ \def\@after{##2}%
+ }%
+ \expandafter\@dtl@doifinlist\expandafter,#2,#1,\@nil
+ \end@dtl@doifinlist
+ \ifx\@after\@nnil
+% not found
+ #4%
+ \else
+% found
+ #3%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
%\begin{macro}{\dtl@choplast}
%\begin{definition}
% \cs{dtl@choplast}\marg{list}\marg{rest}\marg{last}
@@ -16188,773 +17706,6 @@ options>#2=\textsf{#2}|hyperpage}}
% \end{macrocode}
%\end{macro}
%
-%\subsection{Saving a database to an external file}
-%
-%\begin{macro}{\@dtl@write}
-% \begin{macrocode}
-\newwrite\@dtl@write
-% \end{macrocode}
-%\end{macro}
-%\begin{macro}{\DTLsavedb}
-%\begin{definition}
-% \cs{DTLsavedb}\marg{db name}\marg{filename}
-%\end{definition}
-% Save a database as an ASCII data file using the separator
-% and delimiter given by \cs{@dtl@separator} and \cs{@dtl@delimiter}.
-%\changes{2.0}{2009 February 27}{updated to use new database structure}
-% \begin{macrocode}
-\newcommand*{\DTLsavedb}[2]{%
- \DTLifdbexists{#1}%
- {%
-% \end{macrocode}
-% Open output file
-%\changes{2.02}{2009 July 13}{Fixed bug that didn't set the filename}
-% \begin{macrocode}
- \openout\@dtl@write=#2\relax
-% \end{macrocode}
-% Initialise header row
-% \begin{macrocode}
- \def\@dtl@header{}%
-% \end{macrocode}
-% Construct the header row
-% \begin{macrocode}
- \dtlforeachkey(\@dtl@key,\@dtl@col,\@dtl@type,\@dtl@head)%
- \in{#1}\do
- {%
- \IfSubStringInString{\@dtl@separator}{\@dtl@key}%
- {%
- \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}
-%
-%\begin{macro}{\DTLsavetexdb}
-%\begin{definition}
-% \cs{DTLsavetexdb}\marg{db name}\marg{filename}
-%\end{definition}
-% Save a database as a \LaTeX\ file.
-%\changes{2.0}{2009 February 27}{updated to use new database structure}
-% \begin{macrocode}
-\newcommand*{\DTLsavetexdb}[2]{%
- \DTLifdbexists{#1}%
- {%
-% \end{macrocode}
-% Open output file
-% \begin{macrocode}
- \openout\@dtl@write=#2\relax
-% \end{macrocode}
-% Write new data base definition
-% \begin{macrocode}
- \protected@write\@dtl@write{}{\string\DTLnewdb{#1}}%
-% \end{macrocode}
-% Iterate through each row
-% \begin{macrocode}
- \@sDTLforeach{#1}{}%
- {%
-% \end{macrocode}
-% Start new row
-% \begin{macrocode}
- \protected@write\@dtl@write{}{\string\DTLnewrow*{#1}}%
-% \end{macrocode}
-% Iterate through each column
-% \begin{macrocode}
- \DTLforeachkeyinrow{\@dtl@val}%
- {%
-% \end{macrocode}
-% Is this entry null?
-% \begin{macrocode}
- \DTLifnull{\@dtl@val}%
- {\def\@dtl@val{}}%
- {}%
-% \end{macrocode}
-% Add entry
-% \begin{macrocode}
- \protected@write\@dtl@write{}{%
- \string\DTLnewdbentry*{#1}{\dtlkey}{\@dtl@val}}%
- }%
- }%
-% \end{macrocode}
-% Save the column headers.
-% \begin{macrocode}
- \dtlforeachkey(\@dtl@k,\@dtl@c,\@dtl@t,\@dtl@h)\in{#1}\do
- {%
- \@onelevel@sanitize\@dtl@h
- \protected@write\@dtl@write{}{%
- \string\DTLsetheader*{#1}{\@dtl@k}{\@dtl@h}}%
- }%
-% \end{macrocode}
-% 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
-% \end{macrocode}
-%\end{macro}
-%\begin{macro}{\dtl@entrycr}
-% Keep track of current column in data file
-% \begin{macrocode}
-\newcount\dtl@entrycr
-% \end{macrocode}
-%\end{macro}
-%
-%\begin{macro}{\ifdtlnoheader}
-% The "noheader" option indicates that the file doesn't have a
-% header row.
-% \begin{macrocode}
-\define@boolkey{loaddb}[dtl]{noheader}[true]{}
-% \end{macrocode}
-%\end{macro}
-% 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}\oarg{options}\marg{db name}\marg{filename}
-%\end{definition}
-% Creates a new database called \meta{db name}, and loads the data
-% in \meta{filename} into it. The separator and delimiter used in
-% the file must match \cs{@dtl@separator} and \cs{@dtl@delimiter}.
-% The optional argument is a comma-separated list.
-%\changes{2.0}{2009 February 27}{removed checks to see if the
-% database exists when adding to it}
-%\changes{2.0}{2009 February 27}{added optional argument}
-% \begin{macrocode}
-\newcommand*{\DTLloaddb}{%
- \let\@dtl@doreadline\@dtl@readline
- \@dtlloaddb
-}
-% \end{macrocode}
-%\end{macro}
-%
-%\begin{macro}{\@dtlloaddb}
-% Loads database using \cs{@dtl@doreadline} to read and trim
-% line from file. (\cs{@dtl@doreadline} must be set before use.)
-% \begin{macrocode}
-\newcommand*{\@dtlloaddb}[3][]{%
-% \end{macrocode}
-% Check if file exists
-% \begin{macrocode}
- \IfFileExists{#3}{%
-% \end{macrocode}
-% File exists. Locally change catcode of double quote character in
-% case it has been made active.
-% \begin{macrocode}
- \begingroup
- \catcode`\"12\relax
-% \end{macrocode}
-% Initialise default options
-% \begin{macrocode}
- \dtlnoheaderfalse
-% \end{macrocode}
-% Get the options
-% \begin{macrocode}
- \setkeys{loaddb}{#1}%
-% \end{macrocode}
-% Open the file for reading.
-% \begin{macrocode}
- \openin\@dtl@read=#3%
- \dtl@message{Reading `#3'}%
-% \end{macrocode}
-% Create the new database.
-% \begin{macrocode}
- \DTLnewdb{#2}%
-% \end{macrocode}
-% Check if the file is empty.
-% \begin{macrocode}
- \ifeof\@dtl@read
-% \end{macrocode}
-% File is empty, so just issue a warning.
-% \begin{macrocode}
- \PackageWarning{datatool}{File `#3' has no data}%
- \else
-% \end{macrocode}
-% Does the file have a header row?
-% \begin{macrocode}
- \ifdtlnoheader
- \else
-% \end{macrocode}
-% Remove initial blank rows
-% \begin{macrocode}
- \loop
-% \end{macrocode}
-% Set repeat condition to false
-% \begin{macrocode}
- \@dtl@conditionfalse
-% \end{macrocode}
-% Do nothing if reached the end of file
-% \begin{macrocode}
- \ifeof\@dtl@read
- \else
-% \end{macrocode}
-% Read a line from the file and store in \cs{@dtl@line}
-% \begin{macrocode}
- \@dtl@doreadline\@dtl@read\@dtl@line
-% \end{macrocode}
-% If this is a blank row, set repeat condition to true
-% \begin{macrocode}
- \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
-% \end{macrocode}
-% Close the input file
-% \begin{macrocode}
- \closein\@dtl@read
-% \end{macrocode}
-% Set the headers if required
-% \begin{macrocode}
- \edef\@dtl@maxcols{\expandafter
- \number\csname dtlcols@#2\endcsname}%
- \dtlgforint\dtl@entrycr=1\to\@dtl@maxcols\step1\do
- {%
- \@ifundefined{@dtl@inhd@\romannumeral\dtl@entrycr}%
- {}%
- {%
- \expandafter\let\expandafter\@dtl@head
- \csname @dtl@inhd@\romannumeral\dtl@entrycr\endcsname
- \@dtl@toks=\expandafter{\@dtl@head}%
- \edef\@dtl@dosetheader{\noexpand\@dtl@setheaderforindex
- {#2}{\number\dtl@entrycr}{\the\@dtl@toks}}%
- \@dtl@dosetheader
- }%
- }%
-% \end{macrocode}
-% End current scope
-% \begin{macrocode}
- \endgroup
-% \end{macrocode}
-% End true part of if file exists
-% \begin{macrocode}
- }{%
-% \end{macrocode}
-% Requested file not found on TeX's path
-% \begin{macrocode}
- \PackageError{datatool}{Can't load database `#2' (file `#3'
- doesn't exist)}{}%
- }%
-}
-% \end{macrocode}
-%\end{macro}
-%
-%\begin{macro}{\dtl@trim}
-%\begin{definition}
-%\cs{dtl@trim}\marg{line}
-%\end{definition}
-% Trims the trailing space from \meta{line}.
-% \begin{macrocode}
-\newcommand{\dtl@trim}[1]{%
-\def\@dtl@trmstr{}%
-\expandafter\@dtl@starttrim#1\@nil%
-\let#1=\@dtl@trmstr
-}
-% \end{macrocode}
-%\end{macro}
-%\begin{macro}{\@dtl@starttrim}
-% Start trimming
-% \begin{macrocode}
-\long\def\@dtl@starttrim#1#2{%
-\ifx\par#1%
- \def\@dtl@dotrim{\@dtl@trim{} #2}%
-\else
- \def\@dtl@dotrim{\@dtl@trim#1#2}%
-\fi
-\@dtl@dotrim%
-}
-% \end{macrocode}
-%\end{macro}
-%\begin{macro}{\@dtl@trim}
-% \begin{macrocode}
-\long\def\@dtl@trim#1 \@nil{\long\def\@dtl@trmstr{#1}}
-% \end{macrocode}
-%\end{macro}
-%
-%\begin{macro}{\DTLloadrawdb}
-%\begin{definition}
-%\cs{DTLloadrawdb}\marg{db name}\marg{filename}
-%\end{definition}
-% Loads a raw database (substitutes "%" $\to$ "\%",
-% "$" $\to$ "\$", "&" $\to$ "\&", "#" $\to$ "\#",
-% "~" $\to$ "\textasciitilde", "_" $\to$ "\_"
-% and "^" $\to$ "\textasciicircum".)
-% \begin{macrocode}
-\newcommand*\DTLloadrawdb{%
- \let\@dtl@doreadline\@dtl@readrawline
- \@dtlloaddb
-}
-% \end{macrocode}
-%\end{macro}
-%
-%\begin{macro}{\@dtl@rawread}
-%\begin{definition}
-% \cs{@dtl@rawread}\meta{number}to\meta{cmd}
-%\end{definition}
-% Reads in a raw line from file given by \meta{number}
-% converts special characters and stores in \meta{cmd}
-% \begin{macrocode}
-\begingroup
-\catcode`\%=\active
-\catcode`$=\active
-\catcode`&=\active
-\catcode`~=\active
-\catcode`_=\active
-\catcode`^=\active
-\catcode`#=\active
-\catcode`?=6\relax
-\catcode`<=1\relax
-\catcode`>=2\relax
-\catcode`\{=\active
-\catcode`\}=\active
-\gdef\@dtl@rawread?1to?2<\relax
-<<\catcode`\%=\active
-\catcode`$=\active
-\catcode`&=\active
-\catcode`~=\active
-\catcode`_=\active
-\catcode`^=\active
-\catcode`#=\active
-\catcode`\{=\active
-\catcode`\}=\active
-\def%<\noexpand\%>\relax
-\def$<\noexpand\$>\relax
-\def&<\&>\relax
-\def#<\#>\relax
-\def~<\noexpand\textasciitilde>\relax
-\def_<\noexpand\_>\relax
-\def^<\noexpand\textasciicircum>\relax
-\@dtl@activatebraces
-\@dtl@doreadraw?1?2>>>
-\gdef\@dtl@doreadraw?1?2<\relax
-\read?1 to \tmp
-\xdef?2<\tmp>\relax
->
-\endgroup
-% \end{macrocode}
-%\end{macro}
-%\begin{macro}{\@dtl@activatebraces}
-% \cs{@dtl@activatebraces} resets braces for \cs{@dtl@rawread}
-% \begin{macrocode}
-\begingroup
-\catcode`\{=\active
-\catcode`\}=\active
-\catcode`<=1\relax
-\catcode`>=2\relax
-\gdef\@dtl@activatebraces<%
- \catcode`\{=\active
- \catcode`\}=\active
- \def{<\noexpand\{>%
- \def}<\noexpand\}>%
->%
-\endgroup
-% \end{macrocode}
-%\end{macro}
-%
-%\begin{macro}{\DTLrawmap}
-%\begin{definition}
-%\cs{DTLrawmap}\marg{string}\marg{replacement}
-%\end{definition}
-% Additional mappings to perform when reading a raw data file
-% \begin{macrocode}
-\newcommand*{\DTLrawmap}[2]{%
-\expandafter\@dtl@toks\expandafter{\@dtl@rawmappings}%
-\ifx\@dtl@rawmappings\@empty
- \def\@dtl@rawmappings{{#1}{#2}}%
-\else
- \def\@dtl@tmp{{#1}{#2}}
- \protected@edef\@dtl@rawmappings{\the\@dtl@toks,\@dtl@tmp}
-\fi
-}
-% \end{macrocode}
-%\end{macro}
-%
-%\begin{macro}{\@dtl@rawmappings}
-% List of mappings.
-% \begin{macrocode}
-\newcommand*{\@dtl@rawmappings}{}
-% \end{macrocode}
-%\end{macro}
-%\begin{macro}{\dtl@domappings}
-%\begin{definition}
-% \cs{dtl@domappings}\marg{cmd}
-%\end{definition}
-% Do all mappings in string given by \meta{cmd}.
-% \begin{macrocode}
-\newcommand*{\dtl@domappings}[1]{%
-\@for\@dtl@map:=\@dtl@rawmappings\do{%
- \expandafter\DTLsubstitute\expandafter#1\@dtl@map
-}}
-% \end{macrocode}
-%\end{macro}
-%
%\begin{macro}{\DTLsubstitute}
%\begin{definition}
%\cs{DTLsubstitute}\marg{cmd}\marg{original}\marg{replacement}
@@ -17052,31 +17803,6 @@ options>#2=\textsf{#2}|hyperpage}}
% \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.
@@ -17238,7 +17964,7 @@ options>#2=\textsf{#2}|hyperpage}}
% Declare package:
% \begin{macrocode}
\NeedsTeXFormat{LaTeX2e}
-\ProvidesPackage{datapie}[2007/02/27 v2.0 (NLCT)]
+\ProvidesPackage{datapie}[2009/10/22 v2.01 (NLCT)]
% \end{macrocode}
% Require \sty{xkeyval} package
% \begin{macrocode}
@@ -17365,12 +18091,14 @@ options>#2=\textsf{#2}|hyperpage}}
\def\dtl@outerlabel{}%
% \end{macrocode}
%\end{macro}
-% \counterfmt{DTLpieroundvar} is a counter governing the number of digits
+%\begin{counter}{DTLpieroundvar}
+% \ctrfmt{DTLpieroundvar} is a counter governing the number of digits
% to round to when using \cs{FPround}.
% \begin{macrocode}
\newcounter{DTLpieroundvar}
\setcounter{DTLpieroundvar}{1}
% \end{macrocode}
+%\end{counter}
%
%\begin{macro}{\DTLdisplayinnerlabel}
%\begin{definition}
@@ -17914,7 +18642,7 @@ Try #2-#1 instead of #1-#2}%
% Declare package:
% \begin{macrocode}
\NeedsTeXFormat{LaTeX2e}
-\ProvidesPackage{dataplot}[2009/02/27 v2.0 (NLCT)]
+\ProvidesPackage{dataplot}[2009/10/22 v2.01 (NLCT)]
% \end{macrocode}
% Required packages
% \begin{macrocode}
@@ -18083,18 +18811,22 @@ Try #2-#1 instead of #1-#2}%
\setlength\DTLminminortickgap{5pt}
% \end{macrocode}
%\end{macro}
+%\begin{counter}{DTLplotroundvar}
% Round $x$ tick labels to the number of digits given by
-% the counter \counterfmt{DTLplotroundXvar}.
+% the counter \ctrfmt{DTLplotroundXvar}.
% \begin{macrocode}
\newcounter{DTLplotroundXvar}
\setcounter{DTLplotroundXvar}{2}
% \end{macrocode}
+%\end{counter}
+%\begin{counter}{DTLplotroundYvar}
% Round $y$ tick labels to the number of digits given by
-% the counter \counterfmt{DTLplotroundYvar}.
+% the counter \ctrfmt{DTLplotroundYvar}.
% \begin{macrocode}
\newcounter{DTLplotroundYvar}
\setcounter{DTLplotroundYvar}{2}
% \end{macrocode}
+%\end{counter}
%\begin{macro}{\ifDTLxaxis}
% The conditional \cs {ifDTLxaxis} is used to determine whether or
% not to display the $x$ axis.
@@ -19338,7 +20070,7 @@ east,southeast,south,southwest,west,northwest}[northeast]{%
% Declare package:
% \begin{macrocode}
\NeedsTeXFormat{LaTeX2e}
-\ProvidesPackage{databar}[2009/02/27 v2.0 (NLCT)]
+\ProvidesPackage{databar}[2009/10/22 v2.01 (NLCT)]
% \end{macrocode}
% Require \sty{xkeyval} package
% \begin{macrocode}
@@ -19448,12 +20180,14 @@ east,southeast,south,southwest,west,northwest}[northeast]{%
% \end{macrocode}
%\end{macro}
%
-% \counterfmt{DTLbarroundvar} is a counter governing the number of digits
+%\begin{counter}{DTLbarroundvar}
+% \ctrfmt{DTLbarroundvar} is a counter governing the number of digits
% to round to when using \cs{FPround}.
% \begin{macrocode}
\newcounter{DTLbarroundvar}
\setcounter{DTLbarroundvar}{1}
% \end{macrocode}
+%\end{counter}
%
%\begin{macro}{\DTLbardisplayYticklabel}
%\cs{DTLbardisplayYticklabel} governs how the $y$ tick labels appear.
@@ -20623,7 +21357,7 @@ uppermultibarlabels,groupgap}%
%\subsection{Package Declaration}
% \begin{macrocode}
\NeedsTeXFormat{LaTeX2e}
-\ProvidesPackage{databib}[2009/02/27 v2.0 (NLCT)]
+\ProvidesPackage{databib}[2009/10/22 v2.01 (NLCT)]
% \end{macrocode}
% Load required packages:
% \begin{macrocode}
@@ -20910,20 +21644,24 @@ uppermultibarlabels,groupgap}%
% \end{macrocode}
%\end{macro}
%
-%The counter \counterfmt{DTLbibrow} keeps track of the current
+%\begin{counter}{DTLbibrow}
+%The counter \ctrfmt{DTLbibrow} keeps track of the current
%row in the body of \cs{DTLforeachbibentry}. (You can't rely on
-%\counterfmt{DTLrowi}, \counterfmt{DTLrowii} and
-% \counterfmt{DTLrowiii}, as \cs{DTLforeachbibentry} pass the
+%\ctr{DTLrowi}, \ctr{DTLrowii} and
+% \ctr{DTLrowiii}, as \cs{DTLforeachbibentry} pass the
% conditions to the optional argument of \cs{DTLforeach}, but
-% instead uses \cs{ifthenelse}, which means that \counterfmt{DTLrowi}
+% instead uses \cs{ifthenelse}, which means that \ctr{DTLrowi}
% etc will be incremented, even when the given condition is not met.)
% \begin{macrocode}
\newcounter{DTLbibrow}
% \end{macrocode}
+%\end{counter}
+%\begin{macro}{\theHDTLbibrow}
% Keep \sty{hyperref} happy:
% \begin{macrocode}
\def\theHDTLbibrow{\theHDTLrow.bib.\arabic{DTLbibrow}}%
% \end{macrocode}
+%\end{macro}
%
%\begin{macro}{\DTLbibfield}
%\begin{definition}
@@ -21123,13 +21861,15 @@ uppermultibarlabels,groupgap}%
\newcount\@dtl@authorcount
% \end{macrocode}
%\end{macro}
-% The counter \counterfmt{DTLmaxauthors} indicates the maximum number of
+%\begin{counter}{DTLmaxauthors}
+% The counter \ctrfmt{DTLmaxauthors} indicates the maximum number of
% author names to display, if there are more than that number,
% \cs{etalname} is used.
% \begin{macrocode}
\newcounter{DTLmaxauthors}
\setcounter{DTLmaxauthors}{10}
% \end{macrocode}
+%\end{counter}
%\begin{macro}{\DTLformatauthorlist}
% Format a list of author names (the list is stored in
% \cs{@dtl@key@Author}):
@@ -21181,13 +21921,15 @@ uppermultibarlabels,groupgap}%
}
% \end{macrocode}
%\end{macro}
-% The counter \counterfmt{DTLmaxeditors} indicates the maximum number of
+%\begin{counter}{DTLmaxeditors}
+% The counter \ctrfmt{DTLmaxeditors} indicates the maximum number of
% editor names to display, if there are more than that number,
% \cs{etalname} is used.
% \begin{macrocode}
\newcounter{DTLmaxeditors}
\setcounter{DTLmaxeditors}{10}
% \end{macrocode}
+%\end{counter}
%
%\begin{macro}{\DTLformateditorlist}
% Format a list of editor names (the list is stored in
@@ -24603,5 +25345,1129 @@ EXECUTE {end.bib}
%</databib.bst>
% \end{macrocode}
%\fi
+%\iffalse
+% \begin{macrocode}
+%<*person.sty>
+% \end{macrocode}
+%\fi
+%\section{person.sty}\label{sec:code:person}
+%\subsection{Package Declaration}
+% Package identification:
+% \begin{macrocode}
+\NeedsTeXFormat{LaTeX2e}
+\ProvidesPackage{person}[2009/11/15 v1.01 (NLCT)]
+% \end{macrocode}
+% Requires the \sty{ifthen} package.
+% \begin{macrocode}
+\RequirePackage{ifthen}
+\RequirePackage{datatool}
+% \end{macrocode}
+%\subsection{Defining People}
+%\begin{counter}{people}
+% Keep count of the number of people who have been defined:
+% \begin{macrocode}
+\newcounter{people}
+% \end{macrocode}
+%\end{counter}
+%\begin{counter}{person}
+% Temporary counter
+% \begin{macrocode}
+\newcounter{person}
+% \end{macrocode}
+%\end{counter}
+%\begin{macro}{\@people@list}
+% Keep a list of labels for each person who has been defined:
+% \begin{macrocode}
+\newcommand*{\@people@list}{,}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@get@firstperson}
+% Get the first person's name in \cs{@people@list}, and store in
+% the argument (which must be a control sequence.)
+% \begin{macrocode}
+\newcommand*{\@get@firstperson}[1]{%
+ \expandafter\@@get@firstperson\@people@list,\@nil{#1}}
+ \def\@@get@firstperson,#1,#2\@nil#3{%
+ \def#3{#1}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\malelabels}
+% List of labels that can be used to indicate that a person is
+% male (when defining a person using \cs{newperson}).
+% \begin{macrocode}
+\newcommand*{\malelabels}{male,Male,MALE,M,m}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\addmalelabel}
+% Adds a label to the list of male labels.
+% \begin{macrocode}
+\newcommand*{\addmalelabel}[1]{%
+ \expandafter\@dtl@toksA\expandafter{\malelabels}%
+ \expandafter\@dtl@toksB\expandafter{#1}%
+ \edef\malelabels{\the\@dtl@toksA,\the\@dtl@toksB}%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\addfemalelabel}
+% Adds a label to the list of female labels.
+% \begin{macrocode}
+\newcommand*{\addfemalelabel}[1]{%
+ \expandafter\@dtl@toksA\expandafter{\femalelabels}%
+ \expandafter\@dtl@toksB\expandafter{#1}%
+ \edef\femalelabels{\the\@dtl@toksA,\the\@dtl@toksB}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\femalelabels}
+% List of labels that can be used to indicate that a person is
+% female (when defining a person using \cs{newperson}).
+% \begin{macrocode}
+\newcommand*{\femalelabels}{female,Female,FEMALE,F,f}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\ifmalelabel}
+% Determines if first argument is contained in the list of male
+% labels. (One level expansion is performed on the first object
+% in first argument.)
+% If true does second argument, otherwise does third argument.
+% \begin{macrocode}
+\newcommand{\ifmalelabel}[3]{%
+ \expandafter\DTLifinlist\expandafter{#1}{\malelabels}{#2}{#3}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\iffemalelabel}
+% Determines if first argument is contained in the list of female
+% labels. (One level expansion is performed on the first object
+% in first argument.)
+% If true does second argument, otherwise does third argument.
+% \begin{macrocode}
+\newcommand{\iffemalelabel}[3]{%
+ \expandafter\DTLifinlist\expandafter{#1}{\femalelabels}{#2}{#3}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\newperson}
+% Define a new person. The optional argument specifies a label
+% with which to refer to that person. If omitted, \texttt{anon}
+% is used. If more than one person is defined, the optional
+% argument will be required to specify a unique label. The
+% compulsory arguments are the person's full name, their
+% familiar name and their gender.
+% \begin{macrocode}
+\newcommand*{\newperson}[4][anon]{%
+ \@ifundefined{person@#1@name}%
+ {%
+ \ifmalelabel{#4}%
+ {%
+ \expandafter\gdef\csname person@#1@gender\endcsname{male}%
+ }%
+ {%
+ \iffemalelabel{#4}%
+ {%
+ \expandafter\gdef\csname person@#1@gender\endcsname{female}%
+ }%
+ {%
+ \PackageError{person}{Unknown gender `#4' for person
+ `#1'}{Allowed gender labels are: \malelabels\space or
+ \femalelabels}%
+ \@namedef{person@#1@gender}{other}%
+ }%
+ }%
+ \expandafter
+ \protected@xdef\csname person@#1@fullname\endcsname{#2}%
+ \expandafter
+ \protected@xdef\csname person@#1@name\endcsname{#3}%
+ \protected@xdef\@people@list{\@people@list#1,}%
+ \stepcounter{people}%
+ }%
+ {%
+ \PackageError{person}{Person `#1' has already been defined}{}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\subsection{Remove People}
+%
+%\begin{macro}{\removeperson}
+% Removes person identified by their label from the list.
+% \begin{macrocode}
+\newcommand*{\removeperson}[1][anon]{%
+ \edef\@person@label{#1}%
+ \expandafter\@removeperson\expandafter{\@person@label}%
+}
+% \end{macrocode}
+% The label has to be full expanded for the internal command.
+% \begin{macrocode}
+\newcommand*{\@removeperson}[1]{%
+ \ifpersonexists{#1}%
+ {%
+% \end{macrocode}
+% Remove label from list of people.
+% \begin{macrocode}
+ \def\@remove@person##1,#1,##2\@nil{%
+ \def\@prsn@pre{##1}\def\@prsn@post{##2}}%
+ \expandafter\@remove@person\@people@list\@nil
+ \xdef\@people@list{\@prsn@pre,\@prsn@post}%
+% \end{macrocode}
+% Decrement number of people:
+% \begin{macrocode}
+ \addtocounter{people}{-1}%
+% \end{macrocode}
+% Undefine associated control sequences:
+% \begin{macrocode}
+ \expandafter\global\expandafter
+ \let\csname person@#1@name\endcsname\undefined
+ \expandafter\global\expandafter
+ \let\csname person@#1@fullname\endcsname\undefined
+ \expandafter\global\expandafter
+ \let\csname person@#1@gender\endcsname\undefined
+ }%
+ {%
+ \PackageError{person}{Can't remove person `#1': no such
+ person}{}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\removepeople}
+% Removes the people listed.
+% \begin{macrocode}
+\newcommand*{\removepeople}[1]{%
+ \@for\@thisperson:=#1\do{%
+ \ifx\@thisperson\@empty
+ \else
+ \expandafter\removeperson\expandafter[\@thisperson]%
+ \fi
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\removeallpeople}
+% Removes everyone.
+% \begin{macrocode}
+\newcommand*{\removeallpeople}{%
+ \@for\@thisperson:=\@people@list\do{%
+ \expandafter\global\expandafter
+ \let\csname person@\@thisperson @name\endcsname\undefined
+ \expandafter\global\expandafter
+ \let\csname person@\@thisperson @fullname\endcsname\undefined
+ \expandafter\global\expandafter
+ \let\csname person@\@thisperson @gender\endcsname\undefined
+ }%
+ \setcounter{people}{0}%
+ \gdef\@people@list{,}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\subsection{Conditionals and Loops}
+%\begin{macro}{\ifpersonexists}
+% If person whose label is given by the first argument exists, then
+% do the second argument otherwise do third argument.
+% \begin{macrocode}
+\newcommand{\ifpersonexists}[3]{%
+ \@ifundefined{person@#1@name}{#3}{#2}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\ifmale}
+% If the person given by the label in the first argument is male,
+% do the second argument, otherwise do the third argument.
+% \begin{macrocode}
+\newcommand{\ifmale}[3]{%
+ \ifpersonexists{#1}%
+ {%
+ \edef\@gender{\csname person@\@thisperson @gender\endcsname}%
+ \ifx\@gender\@male@label
+ #2%
+ \else
+ #3%
+ \fi
+ }%
+ {%
+ \PackageError{person}{Person `#1' doesn't exist.}{}%
+ }%
+}
+\def\@male@label{male}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\ifallmale}
+% If all people listed in first argument are male, do the second
+% argument otherwise do the third argument. If the first argument
+% is omitted, all defined people are checked.
+% \begin{macrocode}
+\newcommand{\ifallmale}[3][\@people@list]{%
+ \@for\@thisperson:=#1\do{%
+ \ifpersonexists{\@thisperson}%
+ {%
+ \edef\@gender{\csname person@\@thisperson @gender\endcsname}%
+ \ifx\@gender\@male@label
+ \else
+ \@endfortrue
+ \fi
+ }%
+ {%
+ \PackageError{person}{Person `#1' doesn't exist.}{}%
+ }%
+ }%
+ \if@endfor
+ #3%
+ \else
+ #2%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\iffemale}
+% If the person given by the label in the first argument is female,
+% do the second argument, otherwise do the third argument.
+% \begin{macrocode}
+\newcommand{\iffemale}[3]{%
+ \ifpersonexists{#1}%
+ {%
+ \edef\@gender{\csname person@\@thisperson @gender\endcsname}%
+ \ifx\@gender\@female@label
+ #2%
+ \else
+ #3%
+ \fi
+ }%
+ {%
+ \PackageError{person}{Person `#1' doesn't exist.}{}%
+ }%
+}
+\def\@female@label{female}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\ifallfemale}
+% If all people listed in first argument are female, do the second
+% argument otherwise do the third argument.
+% \begin{macrocode}
+\newcommand{\ifallfemale}[3][\@people@list]{%
+ \@for\@thisperson:=#1\do{%
+ \edef\@gender{\csname person@\@thisperson @gender\endcsname}%
+ \ifx\@gender\@female@label
+ \else
+ \@endfortrue
+ \fi
+ }%
+ \if@endfor
+ #3%
+ \else
+ #2%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\foreachperson}
+%\begin{definition}
+%\cs{foreachperson}(\meta{name cs},\meta{full name cs},\meta{gender cs},\meta{label cs})\cs{in}\marg{list}\cs{do}\marg{body}
+%\end{definition}
+% Iterates through list of people the \cs{in}\marg{list} is optional.
+% If omitted, the list of all defined people is used.
+% \begin{macrocode}
+\def\foreachperson(#1,#2,#3,#4)#5{%
+ \ifx#5\in
+ \def\@do@foreachperson{\@foreachperson(#1,#2,#3,#4)#5}%
+ \else
+ \def\@do@foreachperson{%
+ \@foreachperson(#1,#2,#3,#4)\in\@people@list#5}%
+ \fi
+ \@do@foreachperson
+}
+\long\def\@foreachperson(#1,#2,#3,#4)\in#5\do#6{%
+ \@for#4:=#5\do{%
+ \ifx#4\@empty
+ \else
+ \ifpersonexists{#4}%
+ {%
+ \expandafter
+ \let\expandafter#1\csname person@#4@name\endcsname
+ \expandafter
+ \let\expandafter#2\csname person@#4@fullname\endcsname
+ \expandafter
+ \let\expandafter#3\csname person@#4@gender\endcsname
+ \ifx#3\@male@label
+ \let#3\malename
+ \else
+ \ifx#3\@female@label
+ \let#3\femalename
+ \fi
+ \fi
+ #6%
+ }%
+ {%
+ \PackageError{person}{Person `#4' doesn't exist}{}%
+ }%
+ \fi
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\subsection{Predefined Words}\label{sec:code:peoplenames}
+% These commands should be redefined if
+% you are writing in another language, but note that these
+% are structured according to English grammar.
+%\begin{macro}{\malepronoun}
+% \begin{macrocode}
+\newcommand*{\malepronoun}{he}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\femalepronoun}
+% \begin{macrocode}
+\newcommand*{\femalepronoun}{she}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\pluralpronoun}
+% \begin{macrocode}
+\newcommand*{\pluralpronoun}{they}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\maleobjpronoun}
+% \begin{macrocode}
+\newcommand*{\maleobjpronoun}{him}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\femaleobjpronoun}
+% \begin{macrocode}
+\newcommand*{\femaleobjpronoun}{her}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\pluralobjpronoun}
+% \begin{macrocode}
+\newcommand*{\pluralobjpronoun}{them}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\malepossadj}
+% \begin{macrocode}
+\newcommand*{\malepossadj}{his}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\femalepossadj}
+% \begin{macrocode}
+\newcommand*{\femalepossadj}{her}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\pluralpossadj}
+% \begin{macrocode}
+\newcommand*{\pluralpossadj}{their}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\maleposspronoun}
+% \begin{macrocode}
+\newcommand*{\maleposspronoun}{his}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\femaleposspronoun}
+% \begin{macrocode}
+\newcommand*{\femaleposspronoun}{hers}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\pluralposspronoun}
+% \begin{macrocode}
+\newcommand*{\pluralposspronoun}{theirs}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\malechild}
+% \begin{macrocode}
+\newcommand*{\malechild}{son}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\femalechild}
+% \begin{macrocode}
+\newcommand*{\femalechild}{daughter}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\pluralchild}
+% \begin{macrocode}
+\newcommand*{\pluralchild}{children}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\malechildren}
+% \begin{macrocode}
+\newcommand*{\malechildren}{sons}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\femalechildren}
+% \begin{macrocode}
+\newcommand*{\femalechildren}{daughters}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\maleparent}
+% \begin{macrocode}
+\newcommand*{\maleparent}{father}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\femaleparent}
+% \begin{macrocode}
+\newcommand*{\femaleparent}{mother}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\pluralparent}
+% \begin{macrocode}
+\newcommand*{\pluralparent}{parents}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\malesibling}
+% \begin{macrocode}
+\newcommand*{\malesibling}{brother}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\femalesibling}
+% \begin{macrocode}
+\newcommand*{\femalesibling}{sister}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\pluralsibling}
+% \begin{macrocode}
+\newcommand*{\pluralsibling}{siblings}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\malesiblings}
+% \begin{macrocode}
+\newcommand*{\malesiblings}{brothers}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\femalesiblings}
+% \begin{macrocode}
+\newcommand*{\femalesiblings}{sisters}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\andname}
+% Define \cs{andname} if it hasn't already been defined:
+% \begin{macrocode}
+\providecommand*{\andname}{and}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\malename}
+% \begin{macrocode}
+\newcommand*{\malename}{male}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\femalename}
+% \begin{macrocode}
+\newcommand*{\femalename}{female}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\personsep}
+% Separator to use between people (but not the between the last
+% two).
+% \begin{macrocode}
+\newcommand*{\personsep}{, }
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\personlastsep}
+% Separator to use between last two people.
+% \begin{macrocode}
+\newcommand*{\personlastsep}{\space\andname\space}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\twopeoplesep}
+% Separator to use when list only contains two people.
+% \begin{macrocode}
+\newcommand*{\twopeoplesep}{\space\andname\space}
+% \end{macrocode}
+%\end{macro}
+%
+%\subsection{Displaying Information}
+%\begin{macro}{\personfullname}
+% The person's full name can be displayed using
+% \cs{personfullname}\oarg{label}, where \meta{label} is the
+% unique label used when defining that person. If \meta{label}
+% is omitted, \texttt{anon} is used.
+% \begin{macrocode}
+\newcommand*{\personfullname}[1][anon]{%
+ \@ifundefined{person@#1@fullname}%
+ {%
+ \PackageError{person}{Person `#1' has not been defined}{}%
+ }%
+ {%
+ \csname person@#1@fullname\endcsname
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\peoplefullname}
+% List all defined people's full names. This iterates through all
+% labels in \cs{@people@list}.
+% \begin{macrocode}
+\newcommand*{\peoplefullname}{%
+ \setcounter{person}{1}%
+ \@for\@thisperson:=\@people@list\do{%
+ \ifthenelse{\equal{\@thisperson}{}}%
+ {}%
+ {%
+ \personfullname[\@thisperson]%
+ \stepcounter{person}%
+ \ifnum\c@people=1\relax
+ \else
+ \ifnum\c@person=\c@people
+ \ifnum\c@people=2\relax
+ \twopeoplesep
+ \else
+ \personlastsep
+ \fi
+ \else
+ \ifnum\c@person<\c@people
+ \personsep
+ \fi
+ \fi
+ \fi
+ }%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\personname}
+% As \cs{personfullname}, but for the person's familiar name.
+% \begin{macrocode}
+\newcommand*{\personname}[1][anon]{%
+ \@ifundefined{person@#1@name}%
+ {%
+ \PackageError{person}{Person `#1' has not been defined}{}%
+ }%
+ {%
+ \csname person@#1@name\endcsname
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\peoplename}
+% List all defined people's familiar names. This iterates through all
+% labels in \cs{@people@list}.
+% \begin{macrocode}
+\newcommand*{\peoplename}{%
+ \setcounter{person}{1}%
+ \@for\@thisperson:=\@people@list\do{%
+ \ifthenelse{\equal{\@thisperson}{}}%
+ {}%
+ {%
+ \personname[\@thisperson]%
+ \stepcounter{person}%
+ \ifnum\c@people=1\relax
+ \else
+ \ifnum\c@person=\c@people
+ \ifnum\c@people=2\relax
+ \twopeoplesep
+ \else
+ \personlastsep
+ \fi
+ \else
+ \ifnum\c@person<\c@people
+ \personsep
+ \fi
+ \fi
+ \fi
+ }%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\personpronoun}
+% Display the pronoun (he/she) according to the person's gender.
+% \begin{macrocode}
+\newcommand*{\personpronoun}[1][anon]{%
+ \@ifundefined{person@#1@gender}%
+ {%
+ \PackageError{person}{Person `#1' has not been defined}{}%
+ }%
+ {%
+ \edef\@gender{\csname person@#1@gender\endcsname}%
+ \csname\@gender pronoun\endcsname
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\Personpronoun}
+% As above, but make the first letter uppercase.
+% \begin{macrocode}
+\newcommand*{\Personpronoun}[1][anon]{%
+ \@ifundefined{person@#1@gender}%
+ {%
+ \PackageError{person}{Person `#1' has not been defined}{}%
+ }%
+ {%
+ \edef\@gender{\csname person@#1@gender\endcsname}%
+ \expandafter\expandafter\expandafter
+ \MakeUppercase\csname\@gender pronoun\endcsname
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\peoplepronoun}
+% If there is more than one person, \cs{peoplepronoun} will use
+% \cs{pluralpronoun}, otherwise it will use \cs{personpronoun}.
+% \begin{macrocode}
+\newcommand*{\peoplepronoun}{%
+ \ifnum\c@people>1\relax
+ \pluralpronoun
+ \else
+ \@get@firstperson{\@thisperson}%
+ \personpronoun[\@thisperson]%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\Peoplepronoun}
+% As above, but first letter in upper case
+% \begin{macrocode}
+\newcommand*{\Peoplepronoun}{%
+ \ifnum\c@people>1\relax
+ \expandafter\MakeUppercase\pluralpronoun
+ \else
+ \@get@firstperson{\@thisperson}%
+ \Personpronoun[\@thisperson]%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\personobjpronoun}
+% Display the objective pronoun (him/her) according to the person's
+% gender.
+% \begin{macrocode}
+\newcommand*{\personobjpronoun}[1][anon]{%
+ \@ifundefined{person@#1@gender}%
+ {%
+ \PackageError{person}{Person `#1' has not been defined}{}%
+ }%
+ {%
+ \edef\@gender{\csname person@#1@gender\endcsname}%
+ \csname\@gender objpronoun\endcsname
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\Personobjpronoun}
+% As above, but make the first letter uppercase.
+% \begin{macrocode}
+\newcommand*{\Personobjpronoun}[1][anon]{%
+ \@ifundefined{person@#1@gender}%
+ {%
+ \PackageError{person}{Person `#1' has not been defined}{}%
+ }%
+ {%
+ \edef\@gender{\csname person@#1@gender\endcsname}%
+ \expandafter\expandafter\expandafter
+ \MakeUppercase\csname\@gender objpronoun\endcsname
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\peopleobjpronoun}
+% If there is more than one person, \cs{peopleobjpronoun} will use
+% \cs{pluralobjpronoun}, otherwise it will use \cs{personobjpronoun}.
+% \begin{macrocode}
+\newcommand*{\peopleobjpronoun}{%
+ \ifnum\c@people>1\relax
+ \pluralobjpronoun
+ \else
+ \@get@firstperson{\@thisperson}%
+ \personobjpronoun[\@thisperson]%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\Peopleobjpronoun}
+% As above, but first letter in upper case
+% \begin{macrocode}
+\newcommand*{\Peopleobjpronoun}{%
+ \ifnum\c@people>1\relax
+ \expandafter\MakeUppercase\pluralobjpronoun
+ \else
+ \@get@firstperson{\@thisperson}%
+ \Personobjpronoun[\@thisperson]%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\personpssadj}
+% Display the possessive adjective (his/her) according to the person's
+% gender.
+% \begin{macrocode}
+\newcommand*{\personpossadj}[1][anon]{%
+ \@ifundefined{person@#1@gender}%
+ {%
+ \PackageError{person}{Person `#1' has not been defined}{}%
+ }%
+ {%
+ \edef\@gender{\csname person@#1@gender\endcsname}%
+ \csname\@gender possadj\endcsname
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\Personpossadj}
+% As above, but make the first letter uppercase.
+% \begin{macrocode}
+\newcommand*{\Personpossadj}[1][anon]{%
+ \@ifundefined{person@#1@gender}%
+ {%
+ \PackageError{person}{Person `#1' has not been defined}{}%
+ }%
+ {%
+ \edef\@gender{\csname person@#1@gender\endcsname}%
+ \expandafter\expandafter\expandafter
+ \MakeUppercase\csname\@gender possadj\endcsname
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\peoplepossadj}
+% If there is more than one person, \cs{peoplepossadj} will use
+% \cs{pluralpossadj}, otherwise it will use \cs{personpossadj}.
+% \begin{macrocode}
+\newcommand*{\peoplepossadj}{%
+ \ifnum\c@people>1\relax
+ \pluralpossadj
+ \else
+ \@get@firstperson{\@thisperson}%
+ \personpossadj[\@thisperson]%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\Peoplepossadj}
+% As above, but first letter in upper case
+% \begin{macrocode}
+\newcommand*{\Peoplepossadj}{%
+ \ifnum\c@people>1\relax
+ \expandafter\MakeUppercase\pluralpossadj
+ \else
+ \@get@firstperson{\@thisperson}%
+ \Personpossadj[\@thisperson]%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\personposspronoun}
+% Display possessive pronoun (his/hers) according to the
+% person's gender.
+% \begin{macrocode}
+\newcommand*{\personposspronoun}[1][anon]{%
+ \@ifundefined{person@#1@gender}%
+ {%
+ \PackageError{person}{Person `#1' has not been defined}{}%
+ }%
+ {%
+ \edef\@gender{\csname person@#1@gender\endcsname}%
+ \csname\@gender posspronoun\endcsname
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\Personposspronoun}
+% As above, but make the first letter uppercase.
+% \begin{macrocode}
+\newcommand*{\Personposspronoun}[1][anon]{%
+ \@ifundefined{person@#1@gender}%
+ {%
+ \PackageError{person}{Person `#1' has not been defined}{}%
+ }%
+ {%
+ \edef\@gender{\csname person@#1@gender\endcsname}%
+ \expandafter\expandafter\expandafter
+ \MakeUppercase\csname\@gender posspronoun\endcsname
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\peopleposspronoun}
+% If there is more than one person, \cs{peopleposspronoun} will use
+% \cs{pluralposspronoun}, otherwise it will use \cs{personposspronoun}.
+% \begin{macrocode}
+\newcommand*{\peopleposspronoun}{%
+ \ifnum\c@people>1\relax
+ \pluralposspronoun
+ \else
+ \@get@firstperson{\@thisperson}%
+ \personposspronoun[\@thisperson]%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\Peopleposspronoun}
+% As above, but first letter in upper case
+% \begin{macrocode}
+\newcommand*{\Peopleposspronoun}{%
+ \ifnum\c@people>1\relax
+ \expandafter\MakeUppercase\pluralposspronoun
+ \else
+ \@get@firstperson{\@thisperson}%
+ \Personposspronoun[\@thisperson]%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\personchild}
+% Display this person's relationship to their parent (i.e.\ son
+% or daughter).
+% \begin{macrocode}
+\newcommand*{\personchild}[1][anon]{%
+ \@ifundefined{person@#1@gender}%
+ {%
+ \PackageError{person}{Person `#1' has not been defined}{}%
+ }%
+ {%
+ \edef\@gender{\csname person@#1@gender\endcsname}%
+ \csname\@gender child\endcsname
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\Personchild}
+% As above, but make first letter uppercase.
+% \begin{macrocode}
+\newcommand*{\Personchild}[1][anon]{%
+ \@ifundefined{person@#1@gender}%
+ {%
+ \PackageError{person}{Person `#1' has not been defined}{}%
+ }%
+ {%
+ \edef\@gender{\csname person@#1@gender\endcsname}%
+ \expandafter\expandafter\expandafter\MakeUppercase
+ \csname\@gender child\endcsname
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\peoplechild}
+% If there is more than one person, \cs{peoplechild} will use
+% \cs{malechildren} (if all male), \cs{femalechildren} (if all
+% female) or \cs{pluralchild} (if mixed), otherwise it will use
+% \cs{personchild}.
+% \begin{macrocode}
+\newcommand*{\peoplechild}{%
+ \ifnum\c@people>1\relax
+ \ifallmale
+ {\malechildren}%
+ {\ifallfemale{\femalechildren}{\pluralchild}}%
+ \else
+ \@get@firstperson{\@thisperson}%
+ \personchild[\@thisperson]%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\Peoplechild}
+% As above but first letter is made uppercase.
+% \begin{macrocode}
+\newcommand*{\Peoplechild}{%
+ \ifnum\c@people>1\relax
+ \ifallmale
+ {\expandafter\MakeUppercase\malechildren}%
+ {\ifallfemale
+ {\expandafter\MakeUppercase\femalechildren}
+ {\expandafter\MakeUppercase\pluralchild}}%
+ \else
+ \@get@firstperson{\@thisperson}%
+ \Personchild[\@thisperson]%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\personparent}
+% Display this person's relationship to their child (i.e.\ father
+% or mother).
+% \begin{macrocode}
+\newcommand*{\personparent}[1][anon]{%
+ \@ifundefined{person@#1@gender}%
+ {%
+ \PackageError{person}{Person `#1' has not been defined}{}%
+ }%
+ {%
+ \edef\@gender{\csname person@#1@gender\endcsname}%
+ \csname\@gender parent\endcsname
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\Personparent}
+% As above, but make the first letter uppercase.
+% \begin{macrocode}
+\newcommand*{\Personparent}[1][anon]{%
+ \@ifundefined{person@#1@gender}%
+ {%
+ \PackageError{person}{Person `#1' has not been defined}{}%
+ }%
+ {%
+ \edef\@gender{\csname person@#1@gender\endcsname}%
+ \expandafter\expandafter\expandafter\MakeUppercase
+ \csname\@gender parent\endcsname
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\peopleparent}
+% If there is more than one person, \cs{peopleparent} will use
+% \cs{pluralparent}, otherwise it will use \cs{personparent}.
+% \begin{macrocode}
+\newcommand*{\peopleparent}{%
+ \ifnum\c@people>1\relax
+ \pluralparent
+ \else
+ \@get@firstperson{\@thisperson}%
+ \personparent[\@thisperson]%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\Peopleparent}
+% As above, but make first letter uppercase.
+% \begin{macrocode}
+\newcommand*{\Peopleparent}{%
+ \ifnum\c@people>1\relax
+ \expandafter\MakeUppercase\pluralparent
+ \else
+ \@get@firstperson{\@thisperson}%
+ \Personparent[\@thisperson]%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\personsibling}
+% Display this person's relationship to their siblings (i.e.\
+% brother or sister).
+% \begin{macrocode}
+\newcommand*{\personsibling}[1][anon]{%
+ \@ifundefined{person@#1@gender}%
+ {%
+ \PackageError{person}{Person `#1' has not been defined}{}%
+ }%
+ {%
+ \edef\@gender{\csname person@#1@gender\endcsname}%
+ \csname\@gender sibling\endcsname
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\Personsibling}
+% Display this person's relationship to their siblings (i.e.\
+% brother or sister).
+% \begin{macrocode}
+\newcommand*{\Personsibling}[1][anon]{%
+ \@ifundefined{person@#1@gender}%
+ {%
+ \PackageError{person}{Person `#1' has not been defined}{}%
+ }%
+ {%
+ \edef\@gender{\csname person@#1@gender\endcsname}%
+ \expandafter\expandafter\expandafter\MakeUppercase
+ \csname\@gender sibling\endcsname
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\peoplesibling}
+% If there is more than one person, \cs{peoplesibling} will use
+% \cs{malesiblings} (if all male), \cs{femalesiblings} (if all
+% female) or \cs{pluralsibling} (if mixed), otherwise it will use
+% \cs{personsibling}.
+% \begin{macrocode}
+\newcommand*{\peoplesibling}{%
+ \ifnum\c@people>1\relax
+ \ifallmale
+ {\malesiblings}%
+ {\ifallfemale{\femalesiblings}{\pluralsibling}}%
+ \else
+ \@get@firstperson{\@thisperson}%
+ \personsibling[\@thisperson]%
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\persongender}
+% Displays the given person's gender (\cs{malename} or
+% \cs{femalename}).
+% \begin{macrocode}
+\newcommand*{\persongender}[1]{%
+ \ifpersonmale{#1}{\malename}{\femalename}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\subsection{Extracting Information}
+%
+%\begin{macro}{\getpersongender}
+% Gets person's gender and stores in first argument which must be
+% a control sequence.
+% \begin{macrocode}
+\newcommand*{\getpersongender}[2]{%
+ \ifpersonmale{#2}{\let#1\malename}{\let#1\femalename}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\getpersonname}
+% Gets person's name and stores in first argument which must be
+% a control sequence.
+% \begin{macrocode}
+\newcommand*{\getpersonname}[2]{%
+ \ifpersonexists{#2}%
+ {%
+ \expandafter\let\expandafter#1\csname person@#2@name\endcsname
+ }%
+ {%
+ \PackageError{person}{Person `#2' doesn't exist}{}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\getpersonfullname}
+% Gets person's full name and stores in first argument which must be
+% a control sequence.
+% \begin{macrocode}
+\newcommand*{\getpersonfullname}[2]{%
+ \ifpersonexists{#2}%
+ {%
+ \expandafter
+ \let\expandafter#1\csname person@#2@fullname\endcsname
+ }%
+ {%
+ \PackageError{person}{Person `#2' doesn't exist}{}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%\iffalse
+% \begin{macrocode}
+%</person.sty>
+% \end{macrocode}
+%\fi
%\Finale
\endinput
diff --git a/Master/texmf-dist/source/latex/datatool/datatool.ins b/Master/texmf-dist/source/latex/datatool/datatool.ins
index 8dc5e7e9d71..a3d3bd39125 100644
--- a/Master/texmf-dist/source/latex/datatool/datatool.ins
+++ b/Master/texmf-dist/source/latex/datatool/datatool.ins
@@ -1,4 +1,4 @@
-% datatool.ins generated using makedtx version 0.94b 2009/7/13 10:04
+% datatool.ins generated using makedtx version 0.94b 2009/11/15 15:10
\input docstrip
\preamble
@@ -18,7 +18,7 @@
The Current Maintainer of this work is Nicola Talbot.
- This work consists of the files datatool.dtx and datatool.ins and the derived files datatool.sty, datapie.sty, dataplot.sty, databar.sty, databib.sty, databib.bst.
+ This work consists of the files datatool.dtx and datatool.ins and the derived files datatool.sty, datapie.sty, dataplot.sty, databar.sty, databib.sty, databib.bst, person.sty.
\endpreamble
@@ -35,6 +35,8 @@
\file{databib.sty}{\usepreamble\defaultpreamble
\usepostamble\defaultpostamble\from{datatool.dtx}{databib.sty,package}}
\file{databib.bst}{\nopreamble\usepreamble\defaultpreamble\nopostamble\from{datatool.dtx}{databib.bst}}
+\file{person.sty}{\usepreamble\defaultpreamble
+\usepostamble\defaultpostamble\from{datatool.dtx}{person.sty,package}}
}
\endbatchfile