diff options
author | Karl Berry <karl@freefriends.org> | 2007-08-24 18:43:05 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2007-08-24 18:43:05 +0000 |
commit | fe752bd7396fcc8c6fb65128bcd481a5e326e7cd (patch) | |
tree | 216701b87bcd27c641a8a57b4cbd7e2c9dd815ae /Master/texmf-dist/source/latex/datatool/datatool.dtx | |
parent | fabf181c6946e1e5ea931f003df726c9c1c553b8 (diff) |
datatool 1.01 (20aug07)
git-svn-id: svn://tug.org/texlive/trunk@4804 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/source/latex/datatool/datatool.dtx')
-rw-r--r-- | Master/texmf-dist/source/latex/datatool/datatool.dtx | 19616 |
1 files changed, 19616 insertions, 0 deletions
diff --git a/Master/texmf-dist/source/latex/datatool/datatool.dtx b/Master/texmf-dist/source/latex/datatool/datatool.dtx new file mode 100644 index 00000000000..f2afe8ec4b3 --- /dev/null +++ b/Master/texmf-dist/source/latex/datatool/datatool.dtx @@ -0,0 +1,19616 @@ +%\iffalse +% datatool.dtx generated using makedtx version 0.94b (c) Nicola Talbot +% Command line args: +% -macrocode "databib.bst" +% -src "datatool.sty=>datatool.sty" +% -src "datapie.sty=>datapie.sty" +% -src "dataplot.sty=>dataplot.sty" +% -src "databar.sty=>databar.sty" +% -src "databib.sty=>databib.sty" +% -src "databib.bst=>databib.bst" +% -author "Nicola Talbot" +% -dir "source" +% -setambles ".*\.bst=>\nopreamble\usepreamble\defaultpreamble\nopostamble" +% -comment "databib.bst" +% -doc "manual.tex" +% -codetitle "datatool.sty" +% datatool +% Created on 2007/8/19 14:27 +%\fi +%\iffalse +%<*package> +%% \CharacterTable +%% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z +%% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z +%% Digits \0\1\2\3\4\5\6\7\8\9 +%% Exclamation \! Double quote \" Hash (number) \# +%% Dollar \$ Percent \% Ampersand \& +%% Acute accent \' Left paren \( Right paren \) +%% Asterisk \* Plus \+ Comma \, +%% Minus \- Point \. Solidus \/ +%% Colon \: Semicolon \; Less than \< +%% Equals \= Greater than \> Question mark \? +%% Commercial at \@ Left bracket \[ Backslash \\ +%% Right bracket \] Circumflex \^ Underscore \_ +%% Grave accent \` Left brace \{ Vertical bar \| +%% Right brace \} Tilde \~} +%</package> +%\fi +% \iffalse +% Doc-Source file to use with LaTeX2e +% Copyright (C) 2007 Nicola Talbot, all rights reserved. +% \fi +% \iffalse +%<*driver> +\documentclass[a4paper]{ltxdoc} +\usepackage{ifthen} +\usepackage[verbose=false]{datatool} +\usepackage{datapie,databar,databib} +\usepackage{textcomp} +\usepackage{graphicx} +\usepackage{colortbl} +\usepackage[colorlinks, + bookmarks, + hyperindex=false, + pdfauthor={Nicola L.C. Talbot}, + pdftitle={datatool: Databases and data manipulation}, + pdfkeywords={LaTeX,package,database,data,chart,plot}]{hyperref} +\usetikzlibrary{snakes} + + %hyperindex conflicts with doc + %(end up with |usage|hyperpage in indexentry) + %This unfortunately means that the changes section doesn't + %have active links, but at least it will keep makeindex happy. + +\renewcommand{\usage}[1]{\textit{\hyperpage{#1}}} +\renewcommand{\main}[1]{\hyperpage{#1}} +\newcommand{\see}[2]{\emph{see} #1} +\makeatletter +\def\index@prologue{\section*{Index}} + + % commands are too wide for a 3 column index + \def\theindex{\@restonecoltrue\if@twocolumn\@restonecolfalse\fi + \columnseprule \z@ \columnsep 35\p@ + \twocolumn[\index@prologue]% + \IndexParms \let\item\@idxitem \ignorespaces} + \def\endtheindex{\if@restonecol\onecolumn\else\clearpage\fi} +\makeatother +\RecordChanges +\PageIndex +\CheckSum{13202} + +\newcommand*{\sty}[1]{\textsf{#1}} +\newcommand*{\env}[1]{\textsf{#1}} +\newcommand*{\ext}[1]{\texttt{#1}} +\definecolor{defbackground}{rgb}{0.8,1,1} + +\makeatletter +\newcommand*{\setting}[2]{\textsf{#2}\relax +\@for\thiscmd:=#1\do{% +\edef\doindex{\noexpand\index +{\thiscmd\space settings=\noexpand\cs{\thiscmd} settings>#2=\noexpand +\textsf{#2}|hyperpage}}\doindex +}} +\makeatother + +\newcommand*{\counterfmt}[1]{\texttt{#1}\index +{#1 counter=\texttt{#1} counter|hyperpage}} + +\newcommand*{\ics}[1]{\cs{#1}\SpecialMainIndex{#1}} + +\newsavebox\defsbox +\newlength\defwidth +\newenvironment{definition}{% +\setlength{\fboxsep}{4pt}\setlength{\fboxrule}{1.25pt}% +\begin{lrbox}{\defsbox}% +\setlength\defwidth\linewidth +\addtolength\defwidth{-2\fboxrule}% +\addtolength\defwidth{-2\fboxsep}% +\begin{minipage}{\defwidth}\flushleft +}{% +\end{minipage} +\end{lrbox}% +\vskip10pt +\noindent +\fcolorbox{black}{defbackground}{\usebox\defsbox}% +\vskip10pt +} + +\newlength\tmplength +\newcommand{\importantpar}{\relax +\settowidth{\hangindent}{\bfseries\Huge$\bigtriangleup$\space}\relax +\settoheight{\tmplength}{\bfseries\Huge$\bigtriangleup$}\relax +\addtolength{\tmplength}{-0.5\baselineskip}\relax +\hskip-\hangindent +\smash{\raisebox{-\tmplength}{\bfseries +\raisebox{3pt}{\large!}$\!$\makebox[0pt]{\Huge$\bigtriangleup$}\relax +}}\relax +\hskip0.5\hangindent +\hangafter=-2\relax +} + +\newcommand*{\pkgopt}[2][datatool]{\textsf{#2}\index +{#1 package options=\textsf{#1} package options>#2=\textsf{#2}|hyperpage}} + +\newcounter{example} +\newcommand*{\examplename}{example} +\makeatletter +\newenvironment{example}[2]{\refstepcounter{example}\label{#2}% +\par\vskip10pt\noindent +\textbf{\large Example \theexample\ (#1)}% +\addcontentsline{loe}{section}{\protect\numberline{\theexample}#1}% +\nopagebreak\par\vskip10pt\nopagebreak +}% +{\begin{center}\rule{2in}{1pt}\end{center}} + +\newcommand*{\listofexamples}{\section*{List of Examples}% +\@starttoc{loe}} +\makeatother + + %bibliography database +\DTLnewdb{docbib} +\DTLnewrow{docbib} +\DTLnewdbentry{docbib}{CiteKey}{Goossens} +\DTLnewdbentry{docbib}{EntryType}{book} +\DTLnewdbentry{docbib}{Author}{{}{Goossens}{}{Michel},{}{Mittelbach}{}{Frank},{}{Samarin}{}{Alexander}} +\DTLnewdbentry{docbib}{Title}{The \LaTeX\ Companion} +\DTLnewdbentry{docbib}{Publisher}{Addison-Wesley} +\DTLnewdbentry{docbib}{Year}{1994} + + +\begin{document} +\DocInput{datatool.dtx} +\end{document} +%</driver> +%\fi +%\MakeShortVerb{"} +%\DeleteShortVerb{\|} +% +% \title{datatool v 1.01: Databases and data manipulation} +% \author{Nicola L.C. Talbot\\[10pt] +%School of Computing Sciences\\ +%University of East Anglia\\ +%Norwich. Norfolk\\ +%NR4 7TJ. United Kingdom.\\ +%\url{http://theoval.cmp.uea.ac.uk/~nlct/}} +% +% \date{17th August 2007} +% \maketitle +%\tableofcontents +%\listofexamples +%\listoffigures +%\listoftables +% +% \section{Introduction} +% +% \changes{1.0}{2007 July 22}{Initial version} +%The \sty{datatool} bundle consists of the following +%packages: \sty{datatool}, \sty{datapie}, \sty{dataplot}, +%\sty{databar} and \sty{databib}. +% +%The \sty{datatool} package can be used to: +%\begin{itemize} +%\item Create or load databases. +%\item Sort rows of a database (either numerically or alphabetically, +%ascending or descending.) +%\item Perform repetitive operations on each row of a database +%(e.g.\ mail merging.) Conditions may be imposed to exclude rows. +%\item Determine whether an argument is an integer, a real number, +%currency or a string. (Scientific notation is currently not +%supported.) Locale dependent number settings are supported (such +%as a comma as a decimal character and a full stop as a number +%group character.) +%\item Convert locale dependent numbers/currency to the decimal +%format required by the \sty{fp} package, enabling fixed point +%arithmetic to be performed on elements of the database. +%\item Names can be converted to initials. +%\item Strings can be tested to determine if they are all +%upper or lower case. +%\item String comparisons (both case sensitive and case insensitive) +%can be performed. +%\end{itemize} +% +%The \sty{datapie} package can be used to convert a database into +%a pie chart: +%\begin{itemize} +%\item Segments can be separated from the rest of the chart to make +%them stand out. +%\item Colour/grey scale options. +%\item Predefined segment colours can be changed. +%\item Hooks provided to add extra information to the chart +%\end{itemize} +% +%The \sty{databar} package can be used to convert a database into +%a bar chart: +%\begin{itemize} +%\item Colour/grey scale options. +%\item Predefined bar colours can be changed. +%\item Hooks provided to add extra information to the chart +%\end{itemize} +% +%(The \sty{datapie} and \sty{databar} packages do not support the +%creation of 3D charts, and I have no plans to implement them at any +%later date. The use of 3D charts should be discouraged. They may look +%pretty, but the purpose of a chart is to be informative. Three +%dimensional graphics cause distortion, which can result in misleading +%impressions.) +% +%The \sty{dataplot} package can be used to convert a database into +%a two dimensional plot using markers and/or lines. Three dimensional +%plots are currently not supported. +% +%The \sty{databib} package can be used to convert a \BibTeX\ database +%into a \sty{datatool} database. +% +%\section{Data Types} +%\label{sec:datatypes} +% +%The \sty{datatool} package recognises four data types: integers, +%real numbers, currency and strings. +% +%\begin{description} +%\item[Integers] An integer is a sequence of digits, optionally +%groups of three digits may be separated by the number group character. +%The default number group character is a comma (,) but may be +%changed using \cs{DTLsetnumberchars} (see below.) +% +%\item[Real Numbers] A real number is an integer followed by the +%decimal character followed by one or more digits. The decimal +%character is a full stop (.) by default. The number group +%and decimal characters may be changed using +%\DescribeMacro{\DTLsetnumberchars} +%\begin{definition} +%\cs{DTLsetnumberchars}\marg{number group character}\marg{decimal character} +%\end{definition} +%Note that scientific notation is not supported, and the number group +%character may not be used after the decimal character. +% +%\item[Currency] A currency symbol followed by an integer or +%real number is considered to be the currency data type. +%There are two predefined currency symbols, "\$" and \cs{pounds}. +%In addition, if any of the following commands are defined at the +%start of the document, they are also considered to be a currency +%symbol: \cs{texteuro}, \cs{textdollar}, \cs{textstirling}, +%\cs{textyen}, \cs{textwon}, \cs{textcurrency}, \cs{euro} +%and \cs{yen}. Additional currency symbols can be defined using +%\DescribeMacro{\DTLnewcurrencysymbol} +%\begin{definition} +%\cs{DTLnewcurrencysymbol}\marg{symbol} +%\end{definition} +% +%\item[Strings] Anything that doesn't belong to the above three +%types is considered to be a string. +% +%\end{description} +% +%\subsection{Conditionals} +%\label{sec:ifconditions} +% +%The following conditionals are provided by the \sty{datatool} +%package: +% +%\DescribeMacro{\DTLifint} +%\begin{definition} +%\cs{DTLifint}\marg{text}\marg{true part}\marg{false part} +%\end{definition} +%If \meta{text} is an integer then do \meta{true part}, otherwise +%do \meta{false part}. For example +%\begin{verbatim} +%\DTLifint{2536}{integer}{not an integer} +%\end{verbatim} +%produces: +%\DTLifint{2536}{integer}{not an integer}. +% +%The number group character may appear in the number, for example: +%\begin{verbatim} +%\DTLifint{2,536}{integer}{not an integer} +%\end{verbatim} +%produces: +%\DTLifint{2,536}{integer}{not an integer}. +%However, the number group character may only be followed by a group +%of three digits. For example: +%\begin{verbatim} +%\DTLifint{2,5,3,6}{integer}{not an integer} +%\end{verbatim} +%produces: +%\DTLifint{2,5,3,6}{integer}{not an integer}. +%The number group character may be changed. For example: +%\begin{verbatim} +%\DTLsetnumberchars{.}{,}% +%\DTLifint{2,536}{integer}{not an integer} +%\end{verbatim} +%this now produces: +%\DTLsetnumberchars{.}{,}\relax +%\DTLifint{2,536}{integer}{not an integer}, since 2,536 is now +%a real number. +% +%Note that nothing else can be appended or prepended to the +%number. For example: +%\begin{verbatim} +%\DTLsetnumberchars{,}{.}% +%\DTLifint{2,536m}{integer}{not an integer} +%\end{verbatim} +%produces: +%\DTLsetnumberchars{,}{.}\relax +%\DTLifint{2,536m}{integer}{not an integer}. +% +%\DescribeMacro{\DTLifreal} +%\begin{definition} +%\cs{DTLifreal}\marg{text}\marg{true part}\marg{false part} +%\end{definition} +%If \meta{text} is a real number then do \meta{true part}, otherwise +%do \meta{false part}. For example +%\begin{verbatim} +%\DTLifreal{1000.0}{real}{not real} +%\end{verbatim} +%produces: +%\DTLifreal{1000.0}{real}{not real}. +% +%Note that an integer is not a real number: +%\begin{verbatim} +%\DTLifreal{1,000}{real}{not real} +%\end{verbatim} +%produces: +%\DTLifreal{1,000}{real}{not real}. +% +%Whereas +%\begin{verbatim} +%\DTLifreal{1,000.0}{real}{not real} +%\end{verbatim} +%produces: +%\DTLifreal{1,000.0}{real}{not real}. +% +%However +%\begin{verbatim} +%\DTLsetnumberchars{.}{,}% +%\DTLifreal{1,000}{real}{not real} +%\end{verbatim} +%produces: +%\DTLsetnumberchars{.}{,}\relax +%\DTLifreal{1,000}{real}{not real} since the comma is now +%the decimal character. +% +%Currency is not considered to be real: +%\begin{verbatim} +%\DTLsetnumberchars{,}{.}% +%\DTLifreal{\$1.00}{real}{not real} +%\end{verbatim} +%produces: +%\DTLsetnumberchars{,}{.}\relax +%\DTLifreal{\$1.00}{real}{not real}. +% +%\DescribeMacro{\DTLifcurrency} +%\begin{definition} +%\cs{DTLifcurrency}\marg{text}\marg{true part}\marg{false part} +%\end{definition} +%If \meta{text} is currency, then do \meta{true part}, otherwise +%do false part. For example: +%\begin{verbatim} +%\DTLifcurrency{\$5.99}{currency}{not currency} +%\end{verbatim} +%produces: +%\DTLifcurrency{\$5.99}{currency}{not currency}. Similarly: +%\begin{verbatim} +%\DTLifcurrency{\pounds5.99}{currency}{not currency} +%\end{verbatim} +%produces: +%\DTLifcurrency{\pounds5.99}{currency}{not currency}. +%Note, however, that +%\begin{verbatim} +%\DTLifcurrency{US\$5.99}{currency}{not currency} +%\end{verbatim} +%produces: +%\DTLifcurrency{US\$5.99}{currency}{not currency}. If you want +%this to be considered currency, you will have to add the +%sequence "US\$" to the set of currency symbols: +%\begin{verbatim} +%\DTLnewcurrencysymbol{US\$}% +%\DTLifcurrency{US\$5.99}{currency}{not currency} +%\end{verbatim} +%this now produces: +%\DTLnewcurrencysymbol{US\$}\relax +%\DTLifcurrency{US\$5.99}{currency}{not currency}. +% +%This document has used the \sty{textcomp} package which defines +%\cs{texteuro}, so this is also considered to be currency. For +%example: +%\begin{verbatim} +%\DTLifcurrency{\texteuro5.99}{currency}{not currency} +%\end{verbatim} +%produces: +%\DTLifcurrency{\texteuro5.99}{currency}{not currency}. +% +%The preferred method is to display the euro symbol in a sans-serif +%font, but +%\begin{verbatim} +%\DTLifcurrency{\textsf{\texteuro}5.99}{currency}{not currency} +%\end{verbatim} +%will produce: +%\DTLifcurrency{\textsf{\texteuro}5.99}{currency}{not currency}. +% +%It is better to define a new command, for example: +%\begin{verbatim} +%\DeclareRobustCommand*{\euro}{\textsf{\texteuro}} +%\end{verbatim} +%and add that command to the list of currency symbols. In fact, +%in this case, if you define the command \cs{euro} in the +%preamble, it will automatically be added to the list of known +%currency symbols. If however you define \cs{euro} in the document, +%you will have to add it using \ics{DTLnewcurrencysymbol}. For +%example: +%\begin{verbatim} +%\newcommand*{\euro}{\textsf{\texteuro}}% +%\DTLnewcurrencysymbol{\euro}% +%\DTLifcurrency{\euro5.99}{currency}{not currency} +%\end{verbatim} +%produces: +%\DeclareRobustCommand*{\euro}{\textsf{\texteuro}}\relax +%\DTLnewcurrencysymbol{\euro}\relax +%\DTLifcurrency{\euro5.99}{currency}{not currency}. +% +%\DescribeMacro{\DTLifcurrencyunit} +%\begin{definition} +%\cs{DTLifcurrencyunit}\marg{text}\marg{symbol}\marg{true part}\marg{false part} +%\end{definition} +%If \meta{text} is currency, and uses \meta{symbol} as the unit of +%currency, then do \meta{true part} otherwise do \meta{false part}. +%For example: +%\begin{verbatim} +%\DTLifcurrencyunit{\$6.99}{\$}{dollars}{not dollars} +%\end{verbatim} +%produces: +%\DTLifcurrencyunit{\$6.99}{\$}{dollars}{not dollars}. +%Another example: +%\begin{verbatim} +%\def\cost{\euro10.50}% +%\DTLifcurrencyunit{\cost}{\euro}{euros}{not euros} +%\end{verbatim} +%produces: +%\def\cost{\euro10.50}\relax +%\DTLifcurrencyunit{\cost}{\euro}{euros}{not euros}. +% +%\DescribeMacro{\DTLifnumerical} +%\begin{definition} +%\cs{DTLifnumerical}\marg{text}\marg{true part}\marg{false part} +%\end{definition} +%If \meta{text} is numerical (either an integer, real number or +%currency) then do \meta{true part} otherwise do +%\meta{false part}. +%For example: +%\begin{verbatim} +%\DTLifnumerical{1,000.0}{number}{string}. +%\end{verbatim} +%produces: \DTLifnumerical{1,000.0}{number}{string}. +%Whereas +%\begin{verbatim} +%\DTLsetnumberchars{.}{,}% +%\DTLifnumerical{1,000.0}{number}{string}. +%\end{verbatim} +%produces: +%\DTLsetnumberchars{.}{,}\relax +%\DTLifnumerical{1,000.0}{number}{string}. +%Since the number group character is now a full stop, and the +%decimal character is now a comma. (The number group character +%may only appear before the decimal character, not after it.) +% +%Currency is also considered to be numerical: +%\begin{verbatim} +%\DTLsetnumberchars{,}{.}% +%\DTLifnumerical{\$1,000.0}{number}{string}. +%\end{verbatim} +%produces: +%\DTLsetnumberchars{,}{.}\relax +%\DTLifnumerical{\$1,000.0}{number}{string}. +% +%\DescribeMacro{\DTLifstring} +%\begin{definition} +%\cs{DTLifstring}\marg{text}\marg{true part}\marg{false part} +%\end{definition} +%This is the opposite of \cs{DTLifnumerical}. If \meta{text} is +%not numerical, do \meta{true part}, otherwise do \meta{false part}. +% +%\DescribeMacro{\DTLifcasedatatype} +%\begin{definition} +%\cs{DTLifcasedatatype}\marg{text}\marg{string case}\marg{int case}\marg{real case}\marg{currency case} +%\end{definition} +%If \meta{text} is a string do \meta{string case}, if \meta{text} +%is an integer do \meta{int case}, if \meta{text} is a real number +%do \meta{real case}, if \meta{text} is currency do +%\meta{currency case}. For example: +%\begin{verbatim} +%\DTLifcasedatatype{1,000}{string}{integer}{real}{currency} +%\end{verbatim} +%produces: +%\DTLifcasedatatype{1,000}{string}{integer}{real}{currency}. +% +%\DescribeMacro{\DTLifnumeq} +%\begin{definition} +%\cs{DTLifnumeq}\marg{num1}\marg{num2}\marg{true part}\marg{false part} +%\end{definition} +%If \meta{num1} is equal to \meta{num2}, then do \meta{true part}, +%otherwise do \meta{false part}. Note that both \meta{num1} and +%\meta{num2} must be numerical (either integers, real numbers or +%currency.) The currency symbol is ignored when determining +%equality. For example +%\begin{verbatim} +%\DTLifnumeq{\pounds10.50}{10.5}{true}{false} +%\end{verbatim} +%produces: +%\DTLifnumeq{\pounds10.50}{10.5}{true}{false}, since they are +%considered to be numerically equivalent. Likewise: +%\begin{verbatim} +%\DTLifnumeq{\pounds10.50}{\$10.50}{true}{false} +%\end{verbatim} +%produces: +%\DTLifnumeq{\pounds10.50}{\$10.50}{true}{false}. +% +%\DescribeMacro{\DTLifstringeq} +%\begin{definition} +%\cs{DTLifstringeq}\marg{string1}\marg{string2}\marg{true part}\marg{false part} +%\end{definition} +%\DescribeMacro{\DTLifstringeq*} +%\begin{definition} +%\cs{DTLifstringeq*}\marg{string1}\marg{string2}\marg{true part}\marg{false part} +%\end{definition} +%If \meta{string1} and \meta{string2} are the same, then do +%\meta{true part}, otherwise do \meta{false part}. The starred +%version ignores the case, the unstarred version is case +%sensitive. Both +%\meta{string1} and \meta{string2} are considered to be strings, +%so for example: +%\begin{verbatim} +%\DTLifstringeq{10.50}{10.5}{true}{false} +%\end{verbatim} +%produces: +%\DTLifstringeq{10.50}{10.5}{true}{false}. +% +%Note that +%\begin{verbatim} +%\DTLifstringeq{Text}{text}{true}{false} +%\end{verbatim} +%produces: +%\DTLifstringeq{Text}{text}{true}{false}, whereas +%\begin{verbatim} +%\DTLifstringeq*{Text}{text}{true}{false} +%\end{verbatim} +%produces: +%\DTLifstringeq*{Text}{text}{true}{false}, however it should also be +%noted that many commands will be ignored, so: +%\begin{verbatim} +%\DTLifstringeq{\uppercase{t}ext}{text}{true}{false} +%\end{verbatim} +%produces: +%\DTLifstringeq{\uppercase{t}ext}{text}{true}{false}. +% +%Spaces are considered to be equivalent to \cs{space} and "~". For +%example: +%\begin{verbatim} +%\DTLifstringeq{an apple}{an~apple}{true}{false} +%\end{verbatim} +%produces: +%\DTLifstringeq{an apple}{an~apple}{true}{false}. Consecutive spaces +%are treated as the same, for example: +%\begin{verbatim} +%\DTLifstringeq{an apple}{an apple}{true}{false} +%\end{verbatim} +%produces: +%\DTLifstringeq{an apple}{an apple}{true}{false}. +% +%\DescribeMacro{\DTLifeq} +%\begin{definition} +%\cs{DTLifeq}\marg{arg1}\marg{arg2}\marg{true part}\marg{false part} +%\end{definition} +%\DescribeMacro{\DTLifeq*} +%\begin{definition} +%\cs{DTLifeq*}\marg{arg1}\marg{arg2}\marg{true part}\marg{false part} +%\end{definition} +%If both \meta{arg1} and \meta{arg2} are numerical, then this is +%equivalent to \cs{DTLifnumeq}, otherwise it is equivalent to +%\cs{DTLifstringeq} (when using \cs{DTLifeq}) or \cs{DTLifstringeq*} +%(when using \cs{DTLifeq*}). +% +%\DescribeMacro{\DTLifnumlt} +%\begin{definition} +%\cs{DTLifnumlt}\marg{num1}\marg{num2}\marg{true part}\marg{false part} +%\end{definition} +%If \meta{num1} is less than \meta{num2}, then do \meta{true part}, +%otherwise do \meta{false part}. Note that both \meta{num1} and +%\meta{num2} must be numerical (either integers, real numbers or +%currency.) +% +%\DescribeMacro{\DTLifstringlt} +%\begin{definition} +%\cs{DTLifstringlt}\marg{string1}\marg{string2}\marg{true +%part}\marg{false part} +%\end{definition} +%\DescribeMacro{\DTLifstringlt*} +%\begin{definition} +%\cs{DTLifstringlt*}\marg{string1}\marg{string2}\marg{true +%part}\marg{false part} +%\end{definition} +%If \meta{string1} is alphabetically less than \meta{string2}, then do +%\meta{true part}, otherwise do \meta{false part}. The starred +%version ignores the case, the unstarred version is case +%sensitive. +%For example: +%\begin{verbatim} +%\DTLifstringlt{aardvark}{zebra}{less}{not less} +%\end{verbatim} +%produces: +%\DTLifstringlt{aardvark}{zebra}{less}{not less}. +% +%Note that both \meta{string1} and \meta{string2} are considered to be +%strings, so for example: +%\begin{verbatim} +%\DTLifstringlt{2}{10}{less}{not less} +%\end{verbatim} +%produces: +%\DTLifstringlt{2}{10}{less}{not less}, since the string "2" +%comes after the string "10" when arranged alphabetically. +% +%The case sensitive (unstarred) version considers uppercase characters +%to be less than lowercase characters, so +%\begin{verbatim} +%\DTLifstringlt{B}{a}{less}{not less} +%\end{verbatim} +%produces: +%\DTLifstringlt{B}{a}{less}{not less}, whereas +%\begin{verbatim} +%\DTLifstringlt*{B}{a}{less}{not less} +%\end{verbatim} +%produces: +%\DTLifstringlt*{B}{a}{less}{not less}. +% +%\DescribeMacro{\DTLiflt} +%\begin{definition} +%\cs{DTLiflt}\marg{arg1}\marg{arg2}\marg{true part}\marg{false part} +%\end{definition} +%\DescribeMacro{\DTLiflt*} +%\begin{definition} +%\cs{DTLiflt*}\marg{arg1}\marg{arg2}\marg{true part}\marg{false part} +%\end{definition} +%If \meta{arg1} and \meta{arg2} are both numerical, then this +%is equivalent to \cs{DTLifnumlt}, otherwise it is equivalent +%to \cs{DTLstringlt} (when using \cs{DTLiflt}) or +%\cs{DTLstringlt*} (when using \cs{DTLiflt*}). +% +%\DescribeMacro{\DTLifnumgt} +%\begin{definition} +%\cs{DTLifnumgt}\marg{num1}\marg{num2}\marg{true part}\marg{false part} +%\end{definition} +%If \meta{num1} is greater than \meta{num2}, then do \meta{true part}, +%otherwise do \meta{false part}. Note that both \meta{num1} and +%\meta{num2} must be numerical (either integers, real numbers or +%currency.) +% +%\DescribeMacro{\DTLifstringgt} +%\begin{definition} +%\cs{DTLifstringgt}\marg{string1}\marg{string2}\marg{true +%part}\marg{false part} +%\end{definition} +%\DescribeMacro{\DTLifstringgt*} +%\begin{definition} +%\cs{DTLifstringgt*}\marg{string1}\marg{string2}\marg{true +%part}\marg{false part} +%\end{definition} +%If \meta{string1} is alphabetically greater than \meta{string2}, then +%do \meta{true part}, otherwise do \meta{false part}. The +%starred version ignores the case, the unstarred version is +%case sensitive. For example: +%\begin{verbatim} +%\DTLifstringgt{aardvark}{zebra}{greater}{not greater} +%\end{verbatim} +%produces: +%\DTLifstringgt{aardvark}{zebra}{greater}{not greater}. +% +%Note that both \meta{string1} and \meta{string2} are considered to be +%strings, so for example: +%\begin{verbatim} +%\DTLifstringgt{2}{10}{greater}{not greater} +%\end{verbatim} +%produces: +%\DTLifstringgt{2}{10}{greater}{not greater}, since the string "2" +%comes after the string "10" when arranged alphabetically. +% +%As with \cs{DTLifstringlt}, uppercase characters are considered +%to be less than lower case characters when performing a +%case sensitive comparison so: +%\begin{verbatim} +%\DTLifstringgt{B}{a}{greater}{not greater} +%\end{verbatim} +%produces: +%\DTLifstringgt{B}{a}{greater}{not greater}, whereas +%\begin{verbatim} +%\DTLifstringgt*{B}{a}{greater}{not greater} +%\end{verbatim} +%produces: +%\DTLifstringgt*{B}{a}{greater}{not greater}. +% +%\DescribeMacro{\DTLifgt} +%\begin{definition} +%\cs{DTLifgt}\marg{arg1}\marg{arg2}\marg{true part}\marg{false part} +%\end{definition} +%\DescribeMacro{\DTLifgt*} +%\begin{definition} +%\cs{DTLifgt*}\marg{arg1}\marg{arg2}\marg{true part}\marg{false part} +%\end{definition} +%If \meta{arg1} and \meta{arg2} are both numerical, then this +%is equivalent to \cs{DTLifnumgt}, otherwise it is equivalent +%to \cs{DTLstringgt} (when using \cs{DTLifgt}) or +%\cs{DTLstringgt*} (when using \cs{DTLifgt*}). +% +%\DescribeMacro{\DTLifnumclosedbetween} +%\begin{definition} +%\cs{DTLifnumclosedbetween}\marg{num}\marg{min}\marg{max}\marg{true part}\marg{false part} +%\end{definition} +%If \meta{min} $\leq$ \meta{num} $\leq$ \meta{max} then do \meta{true part}, +%otherwise do \meta{false part}. Note that \meta{num}, \meta{min} and +%\meta{max} must be numerical (either integers, real numbers or +%currency.) The currency symbol is ignored when determining +%equality. For example: +%\begin{verbatim} +%\DTLifnumclosedbetween{5.4}{5}{7}{inside}{outside} +%\end{verbatim} +%produces: +%\DTLifnumclosedbetween{5.4}{5}{7}{inside}{outside}. +%Note that the closed range includes end points: +%\begin{verbatim} +%\DTLifnumclosedbetween{5}{5}{7}{inside}{outside} +%\end{verbatim} +%produces: +%\DTLifnumclosedbetween{5}{5}{7}{inside}{outside}. +% +%\DescribeMacro{\DTLifstringclosedbetween} +%\begin{definition} +%\cs{DTLifstringclosedbetween}\marg{string}\marg{min}\marg{max}\marg{true part}\marg{false part} +%\end{definition} +%\DescribeMacro{\DTLifstringclosedbetween*} +%\begin{definition} +%\cs{DTLifstringclosedbetween*}\marg{string}\marg{min}\marg{max}\marg{true part}\marg{false part} +%\end{definition} +%This determines if \meta{string} is between \meta{min} and +%\meta{max} in the alphabetical sense, or is equal to either +%\meta{min} or \meta{max}. The starred version ignores the case, +%the unstarred version is case sensitive. +% +%\DescribeMacro{\DTLifclosedbetween} +%\begin{definition} +%\cs{DTLifclosedbetween}\marg{arg}\marg{min}\marg{max}\marg{true part}\marg{false part} +%\end{definition} +%\DescribeMacro{\DTLifclosedbetween*} +%\begin{definition} +%\cs{DTLifclosedbetween*}\marg{arg}\marg{min}\marg{max}\marg{true part}\marg{false part} +%\end{definition} +%If \meta{arg}, \meta{min} and \meta{max} are numerical, then this is +%equivalent to \cs{DTLifnumclosedbetween}, otherwise it is equivalent to +%\cs{DTLifstringclosedbetween} (when using \cs{DTLifclosedbetween}) +%or +%\cs{DTLifstringclosedbetween*} (when using \cs{DTLifclosedbetween*}). +% +%\DescribeMacro{\DTLifnumopenbetween} +%\begin{definition} +%\cs{DTLifnumopenbetween}\marg{num}\marg{min}\marg{max}\marg{true part}\marg{false part} +%\end{definition} +%If \meta{min} $<$ \meta{num} $<$ \meta{max} then do \meta{true part}, +%otherwise do \meta{false part}. Note that \meta{num}, \meta{min} and +%\meta{max} must be numerical (either integers, real numbers or +%currency.) Again, the currency symbol is ignored when determining +%equality. For example: +%\begin{verbatim} +%\DTLifnumopenbetween{5.4}{5}{7}{inside}{outside} +%\end{verbatim} +%produces: +%\DTLifnumopenbetween{5.4}{5}{7}{inside}{outside}. +%Note that end points are not included. For example: +%\begin{verbatim} +%\DTLifnumopenbetween{5}{5}{7}{inside}{outside} +%\end{verbatim} +%produces: +%\DTLifnumopenbetween{5}{5}{7}{inside}{outside}. +% +%\DescribeMacro{\DTLifstringopenbetween} +%\begin{definition} +%\cs{DTLifstringopenbetween}\marg{string}\marg{min}\marg{max}\marg{true part}\marg{false part} +%\end{definition} +%\DescribeMacro{\DTLifstringopenbetween*} +%\begin{definition} +%\cs{DTLifstringopenbetween*}\marg{string}\marg{min}\marg{max}\marg{true part}\marg{false part} +%\end{definition} +%This determines if \meta{string} is between \meta{min} and +%\meta{max} in the alphabetical sense. +%The starred version ignores the case, +%the unstarred version is case sensitive. +% +%\DescribeMacro{\DTLifopenbetween} +%\begin{definition} +%\cs{DTLifopenbetween}\marg{arg}\marg{min}\marg{max}\marg{true part}\marg{false part} +%\end{definition} +%\DescribeMacro{\DTLifopenbetween*} +%\begin{definition} +%\cs{DTLifopenbetween*}\marg{arg}\marg{min}\marg{max}\marg{true part}\marg{false part} +%\end{definition} +%If \meta{arg}, \meta{min} and \meta{max} are numerical, then this is +%equivalent to \cs{DTLifnumopenbetween}, otherwise it is equivalent to +%\cs{DTLifstringopenbetween} (when using \cs{DTLifopenbetween}) +%\cs{DTLifstringopenbetween*} (when using \cs{DTLifopenbetween*}). +% +%\DescribeMacro{\DTLifFPclosedbetween} +%\begin{definition} +%\cs{DTLifFPclosedbetween}\marg{num}\marg{min}\marg{max}\marg{true part}\marg{false part} +%\end{definition} +%If \meta{min} $\leq$ \meta{num} $\leq$ \meta{max} then do \meta{true part}, +%otherwise do \meta{false part} where \meta{num}, \meta{min} +%and \meta{max} are all in standard fixed point notation (i.e.\ +%no number group separator, no currency symbols and a full stop as +%a decimal point.) +% +%\DescribeMacro{\DTLifFPopenbetween} +%\begin{definition} +%\cs{DTLifFPopenbetween}\marg{num}\marg{min}\marg{max}\marg{true part}\marg{false part} +%\end{definition} +%If \meta{min} $<$ \meta{num} $<$ \meta{max} then do \meta{true part}, +%otherwise do \meta{false part} where \meta{num}, \meta{min} +%and \meta{max} are all in standard fixed point notation (i.e.\ +%no number group separator, no currency symbols and a full stop as +%a decimal point.) +% +%\DescribeMacro{\DTLifAllUpperCase} +%\begin{definition} +%\cs{DTLifAllUpperCase}\marg{string}\marg{true part}\marg{false part} +%\end{definition} +%Tests if \meta{string} is all upper case. For example: +%\begin{verbatim} +%\DTLifAllUpperCase{WORD}{all upper}{not all upper} +%\end{verbatim} +%produces: +%\DTLifAllUpperCase{WORD}{all upper}{not all upper}, +%whereas +%\begin{verbatim} +%\DTLifAllUpperCase{Word}{all upper}{not all upper} +%\end{verbatim} +%produces: +%\DTLifAllUpperCase{Word}{all upper}{not all upper}. +%Note also that: +%\begin{verbatim} +%\DTLifAllUpperCase{\MakeUppercase{word}}{all upper}{not all upper} +%\end{verbatim} +%also produces: +%\DTLifAllUpperCase{\MakeUppercase{word}}{all upper}{not all upper}. +%\cs{MakeTextUppercase} (defined in David Carlisle's \sty{textcase} +%package) and \cs{uppercase} are also detected, otherwise, if +%a command is encountered, the case of the command is considered. +%For example: +%\begin{verbatim} +%\DTLifAllUpperCase{MAN{\OE}UVRE}{all upper}{not all upper} +%\end{verbatim} +%produces: +%\DTLifAllUpperCase{MAN{\OE}UVRE}{all upper}{not all upper}. +% +%\DescribeMacro{\DTLifAllLowerCase} +%\begin{definition} +%\cs{DTLifAllLowerCase}\marg{string}\marg{true part}\marg{false part} +%\end{definition} +%Tests if \meta{string} is all lower case. For example: +%\begin{verbatim} +%\DTLifAllLowerCase{word}{all lower}{not all lower} +%\end{verbatim} +%produces: +%\DTLifAllLowerCase{word}{all lower}{not all lower}, +%whereas +%\begin{verbatim} +%\DTLifAllLowerCase{Word}{all lower}{not all lower} +%\end{verbatim} +%produces: +%\DTLifAllLowerCase{Word}{all lower}{not all lower}. +%Note also that: +%\begin{verbatim} +%\DTLifAllLowerCase{\MakeLowercase{WORD}}{all lower}{not all lower} +%\end{verbatim} +%also produces: +%\DTLifAllLowerCase{\MakeLowercase{WORD}}{all lower}{not all lower}. +%\cs{MakeTextLowercase} (defined in David Carlisle's \sty{textcase} +%package) and \cs{lowercase} are also detected, otherwise, if +%a command is encountered, the case of the command is considered. +%For example: +%\begin{verbatim} +%\DTLifAllLowerCase{man{\oe}uvre}{all lower}{not all lower} +%\end{verbatim} +%produces: +%\DTLifAllLowerCase{man{\oe}uvre}{all lower}{not all lower}. +% +%\DescribeMacro{\DTLifSubString} +%\begin{definition} +%\cs{DTLifSubString}\marg{string}\marg{substring}\marg{true +%part}\marg{false part} +%\end{definition} +%This tests if \meta{substring} is a sub-string of \meta{string}. +%This command performs a case sensitive match. For example: +%\begin{verbatim} +%\DTLifSubString{An apple}{app}{is substring}{isn't substring} +%\end{verbatim} +%produces: +%\DTLifSubString{An apple}{app}{is substring}{isn't substring}. +%Note that spaces are considered to be equivalent to \cs{space} +%or "~", so +%\begin{verbatim} +%\DTLifSubString{An apple}{n~a}{is substring}{isn't substring} +%\end{verbatim} +%produces: +%\DTLifSubString{An apple}{n~a}{is substring}{isn't substring}, +%but other commands are skipped, so +%\begin{verbatim} +%\DTLifSubString{An \uppercase{a}pple}{app}{is substring}{isn't +%substring} +%\end{verbatim} +%produces: +%\DTLifSubString{An \uppercase{a}pple}{app}{is substring}{isn't +%substring}, since the \cs{uppercase} command is ignored. Note also +%that grouping is ignored, so: +%\begin{verbatim} +%\DTLifSubString{An {ap}ple}{app}{is substring}{isn't substring} +%\end{verbatim} +%produces: +%\DTLifSubString{An {ap}ple}{app}{is substring}{isn't substring}. +% +%\cs{DTLifSubString} is case sensitive, so: +%\begin{verbatim} +%\DTLifSubString{An Apple}{app}{is substring}{isn't substring} +%\end{verbatim} +%produces: +%\DTLifSubString{An Apple}{app}{is substring}{isn't substring}. +% +%\DescribeMacro{\DTLifStartsWith} +%\begin{definition} +%\cs{DTLifStartsWith}\marg{string}\marg{substring}\marg{true +%part}\marg{false part} +%\end{definition} +%This is like \cs{DTLifSubString}, except that \meta{substring} must +%occur at the start of \meta{string}. This command performs a case +%sensitive match. For example, +%\begin{verbatim} +%\DTLifStartsWith{An apple}{app}{prefix}{not a prefix} +%\end{verbatim} +%produces: +%\DTLifStartsWith{An apple}{app}{prefix}{not a prefix}. All the +%above remarks for \cs{DTLifSubString} also applies to +%\cs{DTLifStartsWith}. For example: +%\begin{verbatim} +%\DTLifStartsWith{\uppercase{a}n apple}{an~}{prefix}{not a prefix} +%\end{verbatim} +%produces: +%\DTLifStartsWith{\uppercase{a}n apple}{an~}{prefix}{not a prefix}, +%since \cs{uppercase} is ignored, and "~" is considered to be the +%same as a space, whereas +%\begin{verbatim} +%\DTLifStartsWith{An apple}{an~}{prefix}{not a prefix} +%\end{verbatim} +%produces: +%\DTLifStartsWith{An apple}{an~}{prefix}{not a prefix}. +% +%\subsection{\texorpdfstring{\sty{ifthen}}{ifthen} conditionals} +%\label{sec:ifthen} +% +%The commands described in the previous section can not be +%used as the conditional part of the \cs{ifthenelse} or +%\cs{whiledo} commands provided by the \sty{ifthen} package. +%This section describes analogous commands which may only be +%used in the conditional argument of \cs{ifthenelse} and +%\cs{whiledo}. +% +%\DescribeMacro{\DTLisstring} +%\begin{definition} +%\cs{DTLisstring}\marg{text} +%\end{definition} +%Tests if \meta{text} is a string. For example: +%\begin{verbatim} +%\ifthenelse{\DTLisstring{some text}}{string}{not a string} +%\end{verbatim} +%produces: +%\ifthenelse{\DTLisstring{some text}}{string}{not a string}. +% +%\DescribeMacro{\DTLisnumerical} +%\begin{definition} +%\cs{DTLisnumerical}\marg{text} +%\end{definition} +%Tests if \meta{text} is numerical (i.e.\ not a string.) For example: +%\begin{verbatim} +%\ifthenelse{\DTLisnumerical{\$10.95}}{numerical}{not numerical} +%\end{verbatim} +%produces: +%\ifthenelse{\DTLisnumerical{\$10.95}}{numerical}{not numerical}. +% +%Note however that \cs{DTLisnumerical} requires more care than +%\cs{DTLifnumerical} when used with some of the other currency +%symbols. Consider: +%\begin{verbatim} +%\DTLifnumerical{\pounds10.95}{numerical}{not numerical} +%\end{verbatim} +%This produces: +%\DTLifnumerical{\pounds10.95}{numerical}{not numerical}. +%However +%\begin{verbatim} +%\ifthenelse{\DTLisnumerical{\pounds10.95}}{numerical}{not numerical} +%\end{verbatim} +%produces +%\ifthenelse{\DTLisnumerical{\pounds10.95}}{numerical}{not numerical}. +%This is due to the expansion that occurs within \cs{ifthenelse}. +%This can be prevented using \cs{noexpand}, for example: +%\begin{verbatim} +%\ifthenelse{\DTLisnumerical{\noexpand\pounds10.95}}{numerical}{not numerical} +%\end{verbatim} +%produces: +%\ifthenelse{\DTLisnumerical{\noexpand\pounds10.95}}{numerical}{not numerical}. +% +%Likewise: +%\begin{verbatim} +%\def\cost{\pounds10.95}% +%\ifthenelse{\DTLisnumerical{\noexpand\cost}}{numerical}{not numerical} +%\end{verbatim} +%produces +%\def\cost{\pounds10.95}\relax +%\ifthenelse{\DTLisnumerical{\noexpand\cost}}{numerical}{not numerical}. +% +%\DescribeMacro{\DTLiscurrency} +%\begin{definition} +%\cs{DTLiscurrency}\marg{text} +%\end{definition} +%Tests if \meta{text} is currency. For example: +%\begin{verbatim} +%\ifthenelse{\DTLiscurrency{\$10.95}}{currency}{not currency} +%\end{verbatim} +%produces: +%\ifthenelse{\DTLiscurrency{\$10.95}}{currency}{not currency}. +% +%The same warning given above for \cs{DTLisnumerical} also applies +%here. +% +%\DescribeMacro{\DTLiscurrencyunit} +%\begin{definition} +%\cs{DTLiscurrencyunit}\marg{text}\marg{symbol} +%\end{definition} +%Tests if \meta{text} is currency, and uses \meta{symbol} as the unit +%of currency. +%For example: +%\begin{verbatim} +%\ifthenelse{\DTLiscurrencyunit{\$6.99}{\$}}{dollars}{not dollars} +%\end{verbatim} +%produces: +%\ifthenelse{\DTLiscurrencyunit{\$6.99}{\$}}{dollars}{not dollars} +%Another example: +%\begin{verbatim} +%\def\cost{\euro10.50}% +%\ifthenelse{\DTLiscurrencyunit{\noexpand\cost}{\noexpand\euro}}% +%{euros}{not euros} +%\end{verbatim} +%produces: +%\def\cost{\euro10.50}\relax +%\ifthenelse{\DTLiscurrencyunit{\noexpand\cost}{\noexpand\euro}}% +%{euros}{not euros}. Again note the use of \cs{noexpand}. +% +%\DescribeMacro{\DTLisreal} +%\begin{definition} +%\cs{DTLisreal}\marg{text} +%\end{definition} +%Tests if \meta{text} is a fixed point number (again, an integer is +%not considered to be a fixed point number.) For example: +%\begin{verbatim} +%\ifthenelse{\DTLisreal{1.5}}{real}{not real} +%\end{verbatim} +%produces: +%\ifthenelse{\DTLisreal{1.5}}{real}{not real}. +% +%\DescribeMacro{\DTLisint} +%\begin{definition} +%\cs{DTLisint}\marg{text} +%\end{definition} +%Tests if \meta{text} is an integer. For example: +%\begin{verbatim} +%\ifthenelse{\DTLisint{153}}{integer}{not an integer} +%\end{verbatim} +%produces: +%\ifthenelse{\DTLisint{153}}{integer}{not an integer}. +% +%\DescribeMacro{\DTLislt} +%\begin{definition} +%\cs{DTLislt}\marg{arg1}\marg{arg2} +%\end{definition} +%This checks if \meta{arg1} is less than \meta{arg2}. As with +%\cs{DTLiflt}, if \meta{arg1} and \meta{arg2} are numerical, +%a numerical comparison is used, otherwise a case sensitive +%alphabetical comparison is used. (Note that there is no starred +%version of this command, but you can instead use \cs{DTLisilt} +%to ignore the case.) +% +%\DescribeMacro{\DTLisilt} +%\begin{definition} +%\cs{DTLisilt}\marg{arg1}\marg{arg2} +%\end{definition} +%This checks if \meta{arg1} is less than \meta{arg2}. As with +%\cs{DTLiflt*}, if \meta{arg1} and \meta{arg2} are numerical, +%a numerical comparison is used, otherwise a case insensitive +%alphabetical comparison is used. +% +%\DescribeMacro{\DTLisgt} +%\begin{definition} +%\cs{DTLisgt}\marg{arg1}\marg{arg2} +%\end{definition} +%This checks if \meta{arg1} is greater than \meta{arg2}. As with +%\cs{DTLifgt}, if \meta{arg1} and \meta{arg2} are numerical, +%a numerical comparison is used, otherwise a case sensitive +%alphabetical comparison is used. (Note that there is no starred +%version of this command, instead use \cs{DTLisigt} to +%ignore the case.) +% +%\DescribeMacro{\DTLisigt} +%\begin{definition} +%\cs{DTLisigt}\marg{arg1}\marg{arg2} +%\end{definition} +%This checks if \meta{arg1} is greater than \meta{arg2}. As with +%\cs{DTLifgt*}, if \meta{arg1} and \meta{arg2} are numerical, +%a numerical comparison is used, otherwise a case insensitive +%alphabetical comparison is used. +% +%\DescribeMacro{\DTLiseq} +%\begin{definition} +%\cs{DTLiseq}\marg{arg1}\marg{arg2} +%\end{definition} +%This checks if \meta{arg1} is equal to \meta{arg2}. As with +%\cs{DTLifeq}, if \meta{arg1} and \meta{arg2} are numerical, +%a numerical comparison is used, otherwise a case sensitive +%alphabetical comparison is used. (Note that there is no starred +%version of this command, instead use \cs{DTLisieq}.) +% +%\DescribeMacro{\DTLisieq} +%\begin{definition} +%\cs{DTLisieq}\marg{arg1}\marg{arg2} +%\end{definition} +%This checks if \meta{arg1} is equal to \meta{arg2}. As with +%\cs{DTLifeq*}, if \meta{arg1} and \meta{arg2} are numerical, +%a numerical comparison is used, otherwise a case insensitive +%alphabetical comparison is used. +% +%\DescribeMacro{\DTLisclosedbetween} +%\begin{definition} +%\cs{DTLisclosedbetween}\marg{arg}\marg{min}\marg{max} +%\end{definition} +%This checks if \meta{arg} lies between \meta{min} and +%\meta{max} (end points included.) As with +%\cs{DTLifclosedbetween}, if the arguments are numerical, +%a numerical comparison is used, otherwise a case sensitive +%alphabetical comparison is used. (Note that there is no starred +%version of this command, instead use \cs{DTLisiclosedbetween}.) +% +%\DescribeMacro{\DTLisiclosedbetween} +%\begin{definition} +%\cs{DTLisiclosedbetween}\marg{arg}\marg{min}\marg{max} +%\end{definition} +%This checks if \meta{arg} lies between \meta{min} and +%\meta{max} (end points included.) As with +%\cs{DTLifclosedbetween*}, if the arguments are numerical, +%a numerical comparison is used, otherwise a case insensitive +%alphabetical comparison is used. +% +%\DescribeMacro{\DTLisopenbetween} +%\begin{definition} +%\cs{DTLisopenbetween}\marg{arg}\marg{min}\marg{max} +%\end{definition} +%This checks if \meta{arg} lies between \meta{min} and +%\meta{max} (end points excluded.) As with +%\cs{DTLifopenbetween}, if the arguments are numerical, +%a numerical comparison is used, otherwise a case sensitive +%alphabetical comparison is used. (Note that there is no starred +%version of this command, instead use \cs{DTLisiopenbetween}.) +% +%\DescribeMacro{\DTLisiopenbetween} +%\begin{definition} +%\cs{DTLisiopenbetween}\marg{arg}\marg{min}\marg{max} +%\end{definition} +%This checks if \meta{arg} lies between \meta{min} and +%\meta{max} (end points excluded.) As with +%\cs{DTLifopenbetween*}, if the arguments are numerical, +%a numerical comparison is used, otherwise a case insensitive +%alphabetical comparison is used. +% +%\DescribeMacro{\DTLisFPlt} +%\begin{definition} +%\cs{DTLisFPlt}\marg{num1}\marg{num2} +%\end{definition} +%This checks if \meta{num1} is less than \meta{num2}, where both +%numbers are in standard fixed point format (i.e.\ no number group +%separators, no currency and a full stop as a decimal point.) +% +%\DescribeMacro{\DTLisFPlteq} +%\begin{definition} +%\cs{DTLisFPlteq}\marg{num1}\marg{num2} +%\end{definition} +%This checks if \meta{num1} is less than or equal to \meta{num2}, where both +%numbers are in standard fixed point format (i.e.\ no number group +%separators, no currency and a full stop as a decimal point.) +% +%\DescribeMacro{\DTLisFPgt} +%\begin{definition} +%\cs{DTLisFPgt}\marg{num1}\marg{num2} +%\end{definition} +%This checks if \meta{num1} is greater than \meta{num2}, where both +%numbers are in standard fixed point format (i.e.\ no number group +%separators, no currency and a full stop as a decimal point.) +% +%\DescribeMacro{\DTLisFPgteq} +%\begin{definition} +%\cs{DTLisFPgteq}\marg{num1}\marg{num2} +%\end{definition} +%This checks if \meta{num1} is greater than or equal to \meta{num2}, where both +%numbers are in standard fixed point format (i.e.\ no number group +%separators, no currency and a full stop as a decimal point.) +% +%\DescribeMacro{\DTLisFPeq} +%\begin{definition} +%\cs{DTLisFPeq}\marg{num1}\marg{num2} +%\end{definition} +%This checks if \meta{num1} is equal to \meta{num2}, where both +%numbers are in standard fixed point format (i.e.\ no number group +%separators, no currency and a full stop as a decimal point.) +% +%\DescribeMacro{\DTLisFPclosedbetween} +%\begin{definition} +%\cs{DTLisFPclosedbetween}\marg{num}\marg{min}\marg{max} +%\end{definition} +%This checks if \meta{num} lies between \meta{min} and +%\meta{max} (end points included.) All arguments must be +%numbers in standard fixed point format (i.e.\ no number group +%separators, no currency and a full stop as a decimal point.) +% +%\DescribeMacro{\DTLisFPopenbetween} +%\begin{definition} +%\cs{DTLisFPopenbetween}\marg{num}\marg{min}\marg{max} +%\end{definition} +%This checks if \meta{num} lies between \meta{min} and +%\meta{max} (end points excluded.) All arguments must be +%numbers in standard fixed point format (i.e.\ no number group +%separators, no currency and a full stop as a decimal point.) +% +%\DescribeMacro{\DTLisSubString} +%\begin{definition} +%\cs{DTLisSubString}\marg{string}\marg{substring} +%\end{definition} +%This checks if \meta{substring} is contained in \meta{string}. +%The remarks about \cs{DTLifSubString} also apply to +%\cs{DTLisSubString}. This command performs a case sensitive +%match. +% +%\DescribeMacro{\DTLisPrefix} +%\begin{definition} +%\cs{DTLisPrefix}\marg{string}\marg{prefix} +%\end{definition} +%This checks if \meta{string} starts with \meta{prefix}. +%The remarks about \cs{DTLifStartsWith} also apply to +%\cs{DTLisPrefix}. This command performs a case sensitive +%match. +% +%\section{Fixed Point Arithmetic} +%\label{sec:fp} +% +%The \sty{datatool} package uses the \sty{fp} package to perform +%fixed point arithmetic, however all numbers must be converted +%from the locale dependent format into the format required by the +%\sty{fp} package. A numerical value (i.e.\ an integer, a real +%or currency) can be converted into a plain decimal number using +%\DescribeMacro{\DTLconverttodecimal} +%\begin{definition} +%\cs{DTLconverttodecimal}\marg{num}\marg{cmd} +%\end{definition} +%The decimal number will be stored in \meta{cmd} which must be +%a control sequence. For example: +%\begin{verbatim} +%\DTLconverttodecimal{1,563.54}{\mynum} +%\end{verbatim} +%\DTLconverttodecimal{1,563.54}{\mynum}\relax +%will define \cs{mynum} to be \texttt{\mynum}. The command +%can then be used in any of the arithmetic macros provided by the +%\sty{fp} package. There are two commands provided to perform +%the reverse: +%\DescribeMacro{\DTLdecimaltolocale} +%\begin{definition} +%\cs{DTLdecimaltolocale}\marg{number}\marg{cmd} +%\end{definition} +%This converts a plain decimal number \meta{number} (that uses a full +%stop as the decimal character and has no number group characters) +%into a locale dependent format. The resulting number is stored +%in \meta{cmd}, which must be a control sequence. For example: +%\begin{verbatim} +%\DTLdecimaltolocale{6795.3}{\mynum} +%\end{verbatim} +%\DTLdecimaltolocale{6795.3}{\mynum} +%will define \cs{mynum} to be \texttt{\mynum}. +% +%\DescribeMacro{\DTLdecimaltocurrency} +%\begin{definition} +%\cs{DTLdecimaltocurrency}\marg{number}\marg{cmd} +%\end{definition} +%This will convert a plain decimal number \meta{number} into a +%locale dependent currency format. For example: +%\begin{verbatim} +%\DTLdecimaltocurrency{267.5}{\price}\price +%\end{verbatim} +%will produce: +%\DTLdecimaltocurrency{267.5}{\price}\price. +% +%The currency symbol used by \cs{DTLdecimaltocurrency} is +%initially "\$", but will use the currency last encountered. +%So, for example +%\begin{verbatim} +%\DTLifcurrency{\texteuro45.00}{}{}% +%\DTLdecimaltocurrency{267.5}{\price}\price +%\end{verbatim} +%will produce: +%\DTLifcurrency{\texteuro45.00}{}{}\relax +%\DTLdecimaltocurrency{267.5}{\price}\price. This is because +%the last currency symbol to be encountered was \cs{texteuro}. +%You can reset the currency symbol using the command: +%\DescribeMacro{\DTLsetdefaultcurrency} +%\begin{definition} +%\cs{DTLsetdefaultcurrency}\marg{symbol} +%\end{definition} +%For example: +%\begin{verbatim} +%\DTLsetdefaultcurrency{\textyen}% +%\DTLdecimaltocurrency{267.5}{\price}\price +%\end{verbatim} +%will produce: +%\DTLsetdefaultcurrency{\textyen}\relax +%\DTLdecimaltocurrency{267.5}{\price}\price +% +%The \sty{datatool} package provides convenience commands which +%use \cs{DTLconverttodecimal}, and then use the basic macros provided +%by the \sty{fp} package. The resulting value is then converted +%back into the locale format using +%\cs{DTLdecimaltolocale} or \cs{DTLdecimaltocurrency}. +% +%\DescribeMacro{\DTLadd} +%\begin{definition} +%\cs{DTLadd}\marg{cmd}\marg{num1}\marg{num2} +%\end{definition} +%\DescribeMacro{\DTLgadd} +%\begin{definition} +%\cs{DTLgadd}\marg{cmd}\marg{num1}\marg{num2} +%\end{definition} +%This sets the control sequence \meta{cmd} to \meta{num1}+\meta{num2}. +%\cs{DLTadd} sets \meta{cmd} locally, while \cs{DTLgadd} sets +%\meta{cmd} globally. +% +%For example: +%\begin{verbatim} +%\DTLadd{\result}{3,562.65}{412.2}\result +%\end{verbatim} +%will produce: +%\DTLadd{\result}{3,562.65}{412.2}\result. Since +%\cs{DTLconverttodecimal} can also convert currency, you can +%also add prices. For example: +%\begin{verbatim} +%\DTLadd{\result}{\pounds3,562.65}{\pounds452.2}\result +%\end{verbatim} +%produces: +%\DTLadd{\result}{\pounds3,562.65}{\pounds452.2}\result. +% +%Note that \sty{datatool} isn't aware of exchange rates! If you +%use different currency symbols, the last symbol will be used. +%For example +%\begin{verbatim} +%\DTLadd{\result}{\pounds3,562.65}{\euro452.2}\result +%\end{verbatim} +%produces: +%\DTLadd{\result}{\pounds3,562.65}{\euro452.2}\result. +% +%Likewise, if one value is a number and the other is a currency, +%the type of the last value, \meta{num2}, will be used for the +%result. For example: +%\begin{verbatim} +%\DTLadd{\result}{3,562.65}{\$452.2}\result +%\end{verbatim} +%produces: +%\DTLadd{\result}{3,562.65}{\$452.2}\result. +% +%\DescribeMacro{\DTLaddall} +%\begin{definition} +%\cs{DTLaddall}\marg{cmd}\marg{number list} +%\end{definition} +%\DescribeMacro{\DTLgaddall} +%\begin{definition} +%\cs{DTLgaddall}\marg{cmd}\marg{number list} +%\end{definition} +%This sets the control sequence \meta{cmd} to the sum of all +%the numbers in \meta{number list}. +%\cs{DLTaddall} sets \meta{cmd} locally, while \cs{DTLgaddall} sets +%\meta{cmd} globally. Example: +%\begin{verbatim} +%\DTLaddall{\total}{25.1,45.2,35.6}\total +%\end{verbatim} +%produces: +%\DTLaddall{\total}{25.1,45.2,35.6}\total. +%Note that if any of the numbers in \meta{number list} contain +%a comma, you must group the number. Example: +%\begin{verbatim} +%\DTLaddall{\total}{{1,525},{2,340},500}\total +%\end{verbatim} +%produces: +%\DTLaddall{\total}{{1,525},{2,340},500}\total. +% +%\DescribeMacro{\DTLsub} +%\begin{definition} +%\cs{DTLsub}\marg{cmd}\marg{num1}\marg{num2} +%\end{definition} +%\DescribeMacro{\DTLgsub} +%\begin{definition} +%\cs{DTLgsub}\marg{cmd}\marg{num1}\marg{num2} +%\end{definition} +%This sets the control sequence \meta{cmd} to +%\meta{num1}$-$\meta{num2}. +%\cs{DLTsub} sets \meta{cmd} locally, while \cs{DTLgsub} sets +%\meta{cmd} globally. +% +%For example: +%\begin{verbatim} +%\DTLsub{\result}{3,562.65}{412.2}\result +%\end{verbatim} +%will produce: +%\DTLsub{\result}{3,562.65}{412.2}\result. As with \cs{DTLadd}, +%\meta{num1} and \meta{num2} may be currency. +% +%\DescribeMacro{\DTLmul} +%\begin{definition} +%\cs{DTLmul}\marg{cmd}\marg{num1}\marg{num2} +%\end{definition} +%\DescribeMacro{\DTLgmul} +%\begin{definition} +%\cs{DTLgmul}\marg{cmd}\marg{num1}\marg{num2} +%\end{definition} +%This sets the control sequence \meta{cmd} to +%\meta{num1}$\times$\meta{num2}. +%\cs{DLTmul} sets \meta{cmd} locally, while \cs{DTLgmul} sets +%\meta{cmd} globally. +% +%For example: +%\begin{verbatim} +%\DTLmul{\result}{568.95}{2}\result +%\end{verbatim} +%will produce: +%\DTLmul{\result}{568.95}{2}\result. Again, \meta{num1} or +%\meta{num2} may be currency, but unlike \cs{DTLadd} and \cs{DTLsub}, +%currency overrides integer/real. For example: +%\begin{verbatim} +%\DTLmul{\result}{\pounds568.95}{2}\result +%\end{verbatim} +%will produce: +%\DTLmul{\result}{\pounds568.95}{2}\result. Likewise, +%\begin{verbatim} +%\DTLmul{\result}{2}{\pounds568.95}\result +%\end{verbatim} +%will produce: +%\DTLmul{\result}{2}{\pounds568.95}\result. Although it doesn't make +%sense to multiply two currencies, \sty{datatool} will allow +%\begin{verbatim} +%\DTLmul{\result}{\$2}{\pounds568.95}\result +%\end{verbatim} +%which will produce: +%\DTLmul{\result}{\$2}{\pounds568.95}\result. +% +%\DescribeMacro{\DTLdiv} +%\begin{definition} +%\cs{DTLdiv}\marg{cmd}\marg{num1}\marg{num2} +%\end{definition} +%\DescribeMacro{\DTLgdiv} +%\begin{definition} +%\cs{DTLgdiv}\marg{cmd}\marg{num1}\marg{num2} +%\end{definition} +%This sets the control sequence \meta{cmd} to +%\meta{num1}$\div$\meta{num2}. +%\cs{DLTdiv} sets \meta{cmd} locally, while \cs{DTLgdiv} sets +%\meta{cmd} globally. +% +%For example: +%\begin{verbatim} +%\DTLdiv{\result}{501}{2}\result +%\end{verbatim} +%will produce: +%\DTLdiv{\result}{501}{2}\result. Again, \meta{num1} or \meta{num2} +%may be currency, but the resulting type will be not be a currency +%if both \meta{num1} and \meta{num2} use the same currency symbol. +%For example: +%\begin{verbatim} +%\DTLdiv{\result}{\$501}{\$2}\result +%\end{verbatim} +%will produce: +%\DTLdiv{\result}{\$501}{\$2}\result. Whereas +%\begin{verbatim} +%\DTLdiv{\result}{\$501}{2}\result +%\end{verbatim} +%will produce: +%\DTLdiv{\result}{\$501}{2}\result. +% +%\DescribeMacro{\DTLabs} +%\begin{definition} +%\cs{DTLabs}\marg{cmd}\marg{num} +%\end{definition} +%\DescribeMacro{\DTLgabs} +%\begin{definition} +%\cs{DTLgabs}\marg{cmd}\marg{num} +%\end{definition} +%This sets \meta{cmd} to the absolute value of \meta{num}. +%\cs{DLTabs} sets \meta{cmd} locally, while \cs{DTLgabs} sets +%\meta{cmd} globally. Example: +%\begin{verbatim} +%\DTLabs{\result}{-\pounds2.50}\result +%\end{verbatim} +%produces: +%\DTLabs{\result}{-\pounds2.50}\result. +% +%\DescribeMacro{\DTLneg} +%\begin{definition} +%\cs{DTLneg}\marg{cmd}\marg{num} +%\end{definition} +%\DescribeMacro{\DTLgneg} +%\begin{definition} +%\cs{DTLgneg}\marg{cmd}\marg{num} +%\end{definition} +%This sets \meta{cmd} to the negative of \meta{num}. +%\cs{DLTneg} sets \meta{cmd} locally, while \cs{DTLgneg} sets +%\meta{cmd} globally. Example: +%\begin{verbatim} +%\DTLneg{\result}{\pounds2.50}\result +%\end{verbatim} +%produces: +%\DTLneg{\result}{\pounds2.50}\result. +% +%\DescribeMacro{\DTLsqrt} +%\begin{definition} +%\cs{DTLsqrt}\marg{cmd}\marg{num} +%\end{definition} +%\DescribeMacro{\DTLgsqrt} +%\begin{definition} +%\cs{DTLgsqrt}\marg{cmd}\marg{num} +%\end{definition} +%This sets \meta{cmd} to the sqrt root of \meta{num}. +%\cs{DLTsqrt} sets \meta{cmd} locally, while \cs{DTLgsqrt} sets +%\meta{cmd} globally. Example: +%\begin{verbatim} +%\DTLsqrt{\result}{2}\result +%\end{verbatim} +%produces: +%\DTLsqrt{\result}{2}\result. +% +%\DescribeMacro{\DTLmin} +%\begin{definition} +%\cs{DTLmin}\marg{cmd}\marg{num1}\marg{num2} +%\end{definition} +%\DescribeMacro{\DTLgmin} +%\begin{definition} +%\cs{DTLgmin}\marg{cmd}\marg{num1}\marg{num2} +%\end{definition} +%This sets the control sequence \meta{cmd} to the minimum of +%\meta{num1} and \meta{num2}. +%\cs{DLTmin} sets \meta{cmd} locally, while \cs{DTLgmin} sets +%\meta{cmd} globally. For example: +%\begin{verbatim} +%\DTLmin{\result}{256}{32}\result +%\end{verbatim} +%produces: +%\DTLmin{\result}{256}{32}\result. +%Again, \meta{num1} and \meta{num2} may +%be currency. For example: +%\begin{verbatim} +%\DTLmin{\result}{256}{\pounds32}\result +%\end{verbatim} +%produces: +%\DTLmin{\result}{256}{\pounds32}\result, whereas +%\begin{verbatim} +%\DTLmin{\result}{\pounds256}{32}\result +%\end{verbatim} +%produces: +%\DTLmin{\result}{\pounds256}{32}\result. As mentioned above, +%\sty{datatool} doesn't know about exchange rates, so be careful +%about mixing currencies. For example: +%\begin{verbatim} +%\DTLmin{\result}{\pounds5}{\$6}\result +%\end{verbatim} +%produces: +%\DTLmin{\result}{\pounds5}{\$6}\result, which may not necessarily +%be true! +% +%\DescribeMacro{\DTLminall} +%\begin{definition} +%\cs{DTLminall}\marg{cmd}\marg{number list} +%\end{definition} +%\DescribeMacro{\DTLgminall} +%\begin{definition} +%\cs{DTLgminall}\marg{cmd}\marg{number list} +%\end{definition} +%This sets the control sequence \meta{cmd} to the minimum of all +%the numbers in \meta{number list}. +%\cs{DLTminall} sets \meta{cmd} locally, while \cs{DTLgminall} sets +%\meta{cmd} globally. Example: +%\begin{verbatim} +%\DTLminall{\theMin}{25.1,45.2,35.6}\theMin +%\end{verbatim} +%produces: +%\DTLminall{\theMin}{25.1,45.2,35.6}\theMin. +%Note that if any of the numbers in \meta{number list} contain +%a comma, you must group the number. Example: +%\begin{verbatim} +%\DTLminall{\theMin}{{1,525},{2,340},500}\theMin +%\end{verbatim} +%produces: +%\DTLminall{\theMin}{{1,525},{2,340},500}\theMin. +% +%\DescribeMacro{\DTLmax} +%\begin{definition} +%\cs{DTLmax}\marg{cmd}\marg{num1}\marg{num2} +%\end{definition} +%\DescribeMacro{\DTLgmax} +%\begin{definition} +%\cs{DTLgmax}\marg{cmd}\marg{num1}\marg{num2} +%\end{definition} +%This sets the control sequence \meta{cmd} to the maximum of +%\meta{num1} and \meta{num2}. +%\cs{DLTmax} sets \meta{cmd} locally, while \cs{DTLgmax} sets +%\meta{cmd} globally. For example: +%\begin{verbatim} +%\DTLmax{\result}{256}{32}\result +%\end{verbatim} +%produces: +%\DTLmax{\result}{256}{32}\result. +%Again, \meta{num1} and \meta{num2} may +%be currency, but the same warnings for \cs{DTLmin} apply. +% +%\DescribeMacro{\DTLmaxall} +%\begin{definition} +%\cs{DTLmaxall}\marg{cmd}\marg{number list} +%\end{definition} +%\DescribeMacro{\DTLgmaxall} +%\begin{definition} +%\cs{DTLgmaxall}\marg{cmd}\marg{number list} +%\end{definition} +%This sets the control sequence \meta{cmd} to the maximum of all +%the numbers in \meta{number list}. +%\cs{DLTmaxall} sets \meta{cmd} locally, while \cs{DTLgmaxall} sets +%\meta{cmd} globally. Example: +%\begin{verbatim} +%\DTLmaxall{\theMax}{25.1,45.2,35.6}\theMax +%\end{verbatim} +%produces: +%\DTLmaxall{\theMax}{25.1,45.2,35.6}\theMax. +%Note that if any of the numbers in \meta{number list} contain +%a comma, you must group the number. Example: +%\begin{verbatim} +%\DTLmaxall{\theMax}{{1,525},{2,340},500}\theMax +%\end{verbatim} +%produces: +%\DTLmaxall{\theMax}{{1,525},{2,340},500}\theMax. +% +%\DescribeMacro{\DTLmeanforall} +%\begin{definition} +%\cs{DTLmeanforall}\marg{cmd}\marg{number list} +%\end{definition} +%\DescribeMacro{\DTLgmeanall} +%\begin{definition} +%\cs{DTLgmeanforall}\marg{cmd}\marg{number list} +%\end{definition} +%This sets the control sequence \meta{cmd} to the arithmetic mean of all +%the numbers in \meta{number list}. +%\cs{DLTmeanforall} sets \meta{cmd} locally, while \cs{DTLgmeanforall} sets +%\meta{cmd} globally. Example: +%\begin{verbatim} +%\DTLmeanforall{\theMean}{25.1,45.2,35.6}\theMean +%\end{verbatim} +%produces: +%\DTLmeanforall{\theMean}{25.1,45.2,35.6}\theMean. +%Note that if any of the numbers in \meta{number list} contain +%a comma, you must group the number. Example: +%\begin{verbatim} +%\DTLmeanforall{\theMean}{{1,525},{2,340},500}\theMean +%\end{verbatim} +%produces: +%\DTLmeanforall{\theMean}{{1,525},{2,340},500}\theMean. +% +%\DescribeMacro{\DTLvarianceforall} +%\begin{definition} +%\cs{DTLvarianceforall}\marg{cmd}\marg{number list} +%\end{definition} +%\DescribeMacro{\DTLgvarianceforall} +%\begin{definition} +%\cs{DTLgvarianceforall}\marg{cmd}\marg{number list} +%\end{definition} +%This sets the control sequence \meta{cmd} to the variance of all +%the numbers in \meta{number list}. +%\cs{DLTvarianceforall} sets \meta{cmd} locally, while \cs{DTLgvarianceforall} sets +%\meta{cmd} globally. Example: +%\begin{verbatim} +%\DTLvarianceforall{\theVar}{25.1,45.2,35.6}\theVar +%\end{verbatim} +%produces: +%\DTLvarianceforall{\theVar}{25.1,45.2,35.6}\theVar. +%Again note that if any of the numbers in \meta{number list} +%contain a comma, you must group the number. +% +%\DescribeMacro{\DTLsdforall} +%\begin{definition} +%\cs{DTLsdforall}\marg{cmd}\marg{number list} +%\end{definition} +%\DescribeMacro{\DTLgsdforall} +%\begin{definition} +%\cs{DTLgsdforall}\marg{cmd}\marg{number list} +%\end{definition} +%This sets the control sequence \meta{cmd} to the standard deviation of all +%the numbers in \meta{number list}. +%\cs{DLTsdforall} sets \meta{cmd} locally, while \cs{DTLgsdforall} sets +%\meta{cmd} globally. Example: +%\begin{verbatim} +%\DTLsdforall{\theSD}{25.1,45.2,35.6}\theSD +%\end{verbatim} +%produces: +%\DTLsdforall{\theSD}{25.1,45.2,35.6}\theSD. +%Note that if any of the numbers in \meta{number list} contain +%a comma, you must group the number. Example: +%\begin{verbatim} +%\DTLsdforall{\theSD}{{1,525},{2,340},500}\theSD +%\end{verbatim} +%produces: +%\DTLsdforall{\theSD}{{1,525},{2,340},500}\theSD. +% +%\DescribeMacro{\DTLround} +%\begin{definition} +%\cs{DTLround}\marg{cmd}\marg{num}\marg{num digits} +%\end{definition} +%\DescribeMacro{\DTLground} +%\begin{definition} +%\cs{DTLground}\marg{cmd}\marg{num}\marg{num digits} +%\end{definition} +%This sets \meta{cmd} to \meta{num} rounded to \meta{num digits} +%after the decimal character. +%\cs{DLTround} sets \meta{cmd} locally, while \cs{DTLground} sets +%\meta{cmd} globally. +% +%\DescribeMacro{\DTLtrunc} +%\begin{definition} +%\cs{DTLtrunc}\marg{cmd}\marg{num}\marg{num digits} +%\end{definition} +%\DescribeMacro{\DTLgtrunc} +%\begin{definition} +%\cs{DTLgtrunc}\marg{cmd}\marg{num}\marg{num digits} +%\end{definition} +%This sets \meta{cmd} to \meta{num} truncated to \meta{num digits} +%after the decimal character. +%\cs{DLTtrunc} sets \meta{cmd} locally, while \cs{DTLgtrunc} sets +%\meta{cmd} globally. +% +%\DescribeMacro{\DTLclip} +%\begin{definition} +%\cs{DTLclip}\marg{cmd}\marg{num} +%\end{definition} +%\DescribeMacro{\DTLgclip} +%\begin{definition} +%\cs{DTLgclip}\marg{cmd}\marg{num} +%\end{definition} +%This sets \meta{cmd} to \meta{num} with all unnecessary 0's +%removed. +%\cs{DLTclip} sets \meta{cmd} locally, while \cs{DTLgclip} sets +%\meta{cmd} globally. +% +%\section{Strings} +%\label{sec:strings} +% +%Strings are considered to be anything non-numerical. The +%\sty{datatool} package loads the \sty{substr} package, so +%you can use the commands defined in that package to determine +%if one string is contained in another string. In addition, +%the \sty{datatool} provides the following macros: +% +%\DescribeMacro{\DTLsubstitute} +%\begin{definition} +%\cs{DTLsubstitute}\marg{cmd}\marg{original}\marg{replacement} +%\end{definition} +%This replaces the first occurrence of \meta{original} in +%\meta{cmd} with \meta{replacement}. Note that \meta{cmd} must +%be the name of a command. For example: +%\begin{verbatim} +%\def\mystr{abcdce}\DTLsubstitute{\mystr}{c}{z}\mystr +%\end{verbatim} +%produces: +%\def\mystr{abcdce}\DTLsubstitute{\mystr}{c}{z}\mystr. +% +%\DescribeMacro{\DTLsubstituteall} +%\begin{definition} +%\cs{DTLsubstituteall}\marg{cmd}\marg{original}\marg{replacement} +%\end{definition} +%This replaces all occurrences of \meta{original} in +%\meta{cmd} with \meta{replacement}, where again, \meta{cmd} must +%be the name of a command. For example: +%\begin{verbatim} +%\def\mystr{abcdce}\DTLsubstituteall{\mystr}{c}{z}\mystr +%\end{verbatim} +%produces: +%\def\mystr{abcdce}\DTLsubstituteall{\mystr}{c}{z}\mystr. +% +%\DescribeMacro{\DTLsplitstring} +%\begin{definition} +%\cs{DTLsplitstring}\marg{string}\marg{split text}\marg{before +%cmd}\marg{after cmd} +%\end{definition} +%This splits \meta{string} at the first occurrence of \meta{split text} +%and stores the before part in the command \meta{before cmd} and +%the after part in the command \meta{after cmd}. For example: +%\begin{verbatim} +%\DTLsplitstring{abcdce}{c}{\beforepart}{\afterpart}% +%Before part: ``\beforepart''. After part: ``\afterpart'' +%\end{verbatim} +%produces: +%\DTLsplitstring{abcdce}{c}{\beforepart}{\afterpart}\relax +%Before part: ``\beforepart''. After part: ``\afterpart''. +%Note that for \cs{DTLsplitstring}, \meta{string} is not +%expanded, so +%\begin{verbatim} +%\def\mystr{abcdce}% +%\DTLsplitstring{\mystr}{c}{\beforepart}{\afterpart}% +%Before part: ``\beforepart''. After part: ``\afterpart'' +%\end{verbatim} +%produces: +%\def\mystr{abcdce}\relax +%\DTLsplitstring{\mystr}{c}{\beforepart}{\afterpart}% +%Before part: ``\beforepart''. After part: ``\afterpart''. If you +%want the string expanded, you will need to use \cs{expandafter}: +%\begin{verbatim} +%\def\mystr{abcdce}% +%\expandafter\DTLsplitstring\expandafter +%{\mystr}{c}{\beforepart}{\afterpart}% +%Before part: ``\beforepart''. After part: ``\afterpart'' +%\end{verbatim} +%which produces: +%\def\mystr{abcdce}\relax +%\expandafter\DTLsplitstring\expandafter +%{\mystr}{c}{\beforepart}{\afterpart}\relax +%Before part: ``\beforepart''. After part: ``\afterpart''. +% +%\DescribeMacro{\DTLinitials} +%\begin{definition} +%\cs{DTLinitials}\marg{string} +%\end{definition} +%This converts \meta{string} (typically a name) into initials. +%For example: +%\begin{verbatim} +%\DTLinitials{Mary Ann} +%\end{verbatim} +%produces: +%\DTLinitials{Mary Ann} (including the final full stop.) Note that +%\begin{verbatim} +%\DTLinitials{Mary-Ann} +%\end{verbatim} +%produces: +%\DTLinitials{Mary-Ann} (including the final full stop.) +%Be careful if the initial letter has an +%accent. The accented letter needs to be placed in a group, if +%you want the initial to also have an accent, otherwise the +%accent command will be ignored. For example: +%\begin{verbatim} +%\DTLinitials{{\'E}lise Adams} +%\end{verbatim} +%produces: +%\DTLinitials{{\'E}lise Adams}, whereas +%\begin{verbatim} +%\DTLinitials{\'Elise Adams} +%\end{verbatim} +%produces: +%\DTLinitials{\'Elise Adams} In fact, any command which appears +%at the start of the name that is not enclosed in a group will +%be ignored. For example: +%\begin{verbatim} +%\DTLinitials{\MakeUppercase{m}ary ann} +%\end{verbatim} +%produces: +%\DTLinitials{\MakeUppercase{m}ary ann}, whereas +%\begin{verbatim} +%\DTLinitials{{\MakeUppercase{m}}ary ann} +%\end{verbatim} +%produces: +%\DTLinitials{{\MakeUppercase{m}}ary ann}, but note that +%\begin{verbatim} +%\DTLinitials{\MakeUppercase{mary ann}} +%\end{verbatim} +%produces: +%\DTLinitials{\MakeUppercase{mary ann}} +% +%\DescribeMacro{\DTLstoreinitials} +%\begin{definition} +%\cs{DTLstoreinitials}\marg{string}\marg{cmd} +%\end{definition} +%This converts \meta{string} into initials and stores the +%result in \meta{cmd} which must be a command name. The remarks +%about \cs{DTLinitials} also relate to \cs{DTLstoreinitials}. +%For example +%\begin{verbatim} +%\DTLstoreinitials{Marie-{\'E}lise del~Rosario}{\theInitials}\theInitials +%\end{verbatim} +%produces: +%\DTLstoreinitials{Marie-{\'E}lise del~Rosario}{\theInitials}\theInitials +% +%Both the above commands rely on the following to format the +%initials: +%\DescribeMacro{\DTLafterinitials} +%\begin{definition} +%\cs{DTLafterinitials} +%\end{definition} +%This indicates what to do at the end of the initials. This +%simply does a full stop by default. +% +%\DescribeMacro{\DTLbetweeninitials} +%\begin{definition} +%\cs{DTLbetweeninitials} +%\end{definition} +%This indicates what to do between initials. This does a +%full stop by default. +% +%\DescribeMacro{\DTLinitialhyphen} +%\begin{definition} +%\cs{DTLinitialhyphen} +%\end{definition} +%This indicates what to do at a hyphen. This simply does a hyphen +%by default, but can be redefined to do nothing to prevent the +%hyphen appearing in the initials. +% +%\DescribeMacro{\DTLafterinitialbeforehyphen} +%\begin{definition} +%\cs{DTLafterinitialbeforehyphen} +%\end{definition} +%This indicates what to do between an initial and a hyphen. +%This simply does a full stop by default. +% +%For example +%\begin{verbatim} +%\renewcommand*{\DTLafterinitialbeforehyphen}{}% +%\DTLinitials{Marie-{\'E}lise del~Rosario} +%\end{verbatim} +%produces: +%{\renewcommand*{\DTLafterinitialbeforehyphen}{}\relax +%\DTLinitials{Marie-{\'E}lise del~Rosario}} +%whereas +%\begin{verbatim} +%\renewcommand*{\DTLafterinitialbeforehyphen}{}% +%\renewcommand*{\DTLafterinitials}{}% +%\renewcommand*{\DTLbetweeninitials}{}% +%\renewcommand*{\DTLinitialhyphen}{}% +%\DTLinitials{Marie-{\'E}lise del~Rosario} +%\end{verbatim} +%produces: +%{\renewcommand*{\DTLafterinitialbeforehyphen}{}\relax +%\renewcommand*{\DTLafterinitials}{}\relax +%\renewcommand*{\DTLbetweeninitials}{}\relax +%\renewcommand*{\DTLinitialhyphen}{}\relax +%\DTLinitials{Marie-{\'E}lise del~Rosario}} +% +%\section{Databases} +%\label{sec:databases} +% +%The \sty{datatool} package provides a means of creating and +%loading databases. Once a database has been created (or loaded), +%it is possible to iterate through each row of data, to make it +%easier to perform repetitive actions, such as mail merging. +% +%\subsection{Creating a New Database} +%\label{sec:newdb} +% +%\DescribeMacro{\DTLnewdb} +%\begin{definition} +%\cs{DTLnewdb}\marg{db name} +%\end{definition} +%This command creates a new empty database called \meta{db name}. You +%can test if a database is empty using: +%\DescribeMacro{\DTLifdbempty} +%\begin{definition} +%\cs{DTLifdbempty}\marg{db name}\marg{true part}\marg{false part} +%\end{definition} +%If the database called \meta{db name} is empty, do \meta{true part}, +%otherwise do \meta{false part}. +% +%\DescribeMacro{\DTLrowcount} +%\begin{definition} +%\cs{DTLrowcount}\marg{db name} +%\end{definition} +%This command displays the number of rows in the database called +%\meta{db name}. +% +%\DescribeMacro{\DTLnewrow} +%\begin{definition} +%\cs{DTLnewrow}\marg{db name} +%\end{definition} +%This command starts a new row in the database called \meta{db name}. +%This new row becomes the current row when adding new entries. +% +%For example, the following creates an empty database called +%\texttt{mydata}: +%\begin{verbatim} +%\DTLnewdb{mydata} +%\end{verbatim} +%\DTLnewdb{mydata}\relax +%The following tests if the database is empty: +%\begin{verbatim} +%\DTLifdbempty{mydata}{empty}{not empty}! +%\end{verbatim} +%This produces: +%\DTLifdbempty{mydata}{empty}{not empty}! +% +%The following adds an empty row to the database, this is the +%first row of the database: +%\begin{verbatim} +%\DTLnewrow{mydata} +%\end{verbatim} +%\DTLnewrow{mydata}\relax +%Note that even though the only row in the database is currently +%empty, the database is no longer considered to be empty: +%\begin{verbatim} +%\DTLifdbempty{mydata}{empty}{not empty}! +%\end{verbatim} +%This now produces: +%\DTLifdbempty{mydata}{empty}{not empty}! The row count is +%given by +%\begin{verbatim} +%\DTLrowcount{mydata} +%\end{verbatim} +%which produces: +%\DTLrowcount{mydata}. +% +%\DescribeMacro{\DTLnewdbentry} +%\begin{definition} +%\cs{DTLnewdbentry}\marg{db name}\marg{key}\marg{value} +%\end{definition} +%This creates a new entry with the identifier \meta{key} whose value +%is \meta{value} and adds it to the last row of the database +%called \meta{db name}. For example: +%\begin{verbatim} +%\DTLnewdbentry{mydata}{Surname}{Smith} +%\DTLnewdbentry{mydata}{FirstName}{John} +%\end{verbatim} +%Adds an entry with identifier \texttt{Surname} and value +%\texttt{Smith} to the last row of the database named +%\texttt{mydata}, and then adds an entry with identifier +%\texttt{FirstName} and value \texttt{John}. +% +%\importantpar Note that database entries can't contain paragraph +%breaks as many of the macros used by \sty{datatool} are short +%commands. If you do need a paragraph break in an entry, you can +%instead use the command: +%\DescribeMacro{\DTLpar} +%\begin{definition} +%\cs{DTLpar} +%\end{definition} +% +%\DescribeMacro{\DTLaddentryforrow} +%\begin{definition} +%\cs{DTLaddentryforrow}\marg{db name}\marg{assign list}\marg{condition}\marg{key}\marg{value} +%\end{definition} +%This adds the entry with the key given by \meta{key} and value +%given by \meta{value} to the first row in the database +%\meta{db name} which satisfies the condition given by +%\meta{condition}. The \meta{assign list} argument is the same +%as for \cs{DTLforeach} (described in \autoref{sec:dbforeach}) +%and may be used to set the values which are to be tested in +%\meta{condition} (where, again, \meta{condition} is the same +%as for \cs{DTLforeach}). +% +%\subsection{Loading a Database from an External ASCII File} +%\label{sec:loaddb} +% +%Instead of using the commands described in \autoref{sec:newdb} +%to create a new database, you can load a database from an +%external ASCII file using: +%\DescribeMacro{\DTLloaddb} +%\begin{definition} +%\cs{DTLloaddb}\marg{db name}\marg{filename} +%\end{definition} +%This creates a new database called \meta{db name}, and fills +%it with the entries given in the file \meta{filename}. +%The filename must have a header row at the start of the file, +%which provides the \meta{key} when creating a new database entry +%using \ics{DTLnewdbentry}. By default, the entries in the database +%must be separated by a comma, and optionally delimited by the +%double quote character (\verb|"|). The separator can be changed +%to a tab separator using the command: +%\DescribeMacro{\DTLsettabseparator} +%\begin{definition} +%\cs{DTLsettabseparator} +%\end{definition} +%To set the separator to a character other than a tab, you need to use +%\DescribeMacro{\DTLsetseparator} +%\begin{definition} +%\cs{DTLsetseparator}\marg{character} +%\end{definition} +%The delimiter can be changed using +%\DescribeMacro{\DTLsetdelimiter} +%\begin{definition} +%\cs{DTLsetdelimiter}\marg{character} +%\end{definition} +% +%For example, suppose you have a file called \texttt{mydata.csv} +%which contains the following: +%\begin{verbatim} +%FirstName,Surname,Score +%John,"Smith, Jr",68 +%Jane,Brown,75 +%Andy,Brown,42 +%Z\"oe,Adams,52 +%\end{verbatim} +%then +%\begin{verbatim} +%\DTLloaddb{mydata}{mydata.csv} +%\end{verbatim} +%is equivalent to: +%\begin{verbatim} +%\DTLnewdb{mydata} +%\DTLnewrow{mydata}% +%\DTLnewdbentry{mydata}{FirstName}{John}% +%\DTLnewdbentry{mydata}{Surname}{Smith, Jr}% +%\DTLnewdbentry{mydata}{Score}{68}% +%\DTLnewrow{mydata}% +%\DTLnewdbentry{mydata}{FirstName}{Jane}% +%\DTLnewdbentry{mydata}{Surname}{Brown}% +%\DTLnewdbentry{mydata}{Score}{75}% +%\DTLnewrow{mydata}% +%\DTLnewdbentry{mydata}{FirstName}{Andy}% +%\DTLnewdbentry{mydata}{Surname}{Brown}% +%\DTLnewdbentry{mydata}{Score}{42}% +%\DTLnewrow{mydata}% +%\DTLnewdbentry{mydata}{FirstName}{Z\"oe}% +%\DTLnewdbentry{mydata}{Score}{52}% +%\DTLnewdbentry{mydata}{Surname}{Adams}% +%\end{verbatim} +%Note that the entry \texttt{Smith, Jr} had to be delimited in +%\texttt{mydata.csv} using the double quote character since it +%contained a comma which is used as the separator. +% +%The file used in the above example contained a \LaTeX\ command, +%namely \verb|\"|. When using \ics{DTLloaddb} all the special +%characters that appear in the command retain their \LaTeX\ meaning +%when the file is loaded. It is likely however that the data file +%may have been created by another application that is not \TeX-aware, +%such as a spreadsheet application. For example, suppose you +%have a file called, say, \texttt{products.csv} which looks +%like: +%\begin{verbatim} +%Product,Cost +%Fruit & Veg,$1.25 +%Stationary,$0.80 +%\end{verbatim} +%This file contains two of \TeX's special characters, namely +%"&" and \verb|$|. In this case, if you try to load the file +%using \ics{DTLloaddb}, you will encounter errors. Instead you +%can use: +%\DescribeMacro{\DTLloadrawdb} +%\begin{definition} +%\cs{DTLloadrawdb}\marg{db name}\marg{filename} +%\end{definition} +%This is the same as \ics{DTLloaddb} except that it maps nine of +%the ten special characters onto commands which produce that +%symbol. The only character that retains its active state is the +%backslash character, so you will still need to check the file +%for backslash characters. The mappings used are listed in +%\autoref{tab:rawmappings}. So using the file \texttt{products.csv}, +%as described above, +%\begin{verbatim} +%\DTLloadrawdb{mydata}{products.csv} +%\end{verbatim} +%is equivalent to: +%\begin{verbatim} +%\DTLnewdb{mydata} +%\DTLnewrow{mydata}% +%\DTLnewdbentry{mydata}{Product}{Fruit \& Veg}% +%\DTLnewdbentry{mydata}{Cost}{\$1.25}% +%\DTLnewrow{mydata}% +%\DTLnewdbentry{mydata}{Product}{Stationary}% +%\DTLnewdbentry{mydata}{Cost}{\$0.80}% +%\end{verbatim} +% +%\begin{table}[htbp] +%\caption[Special character mappings used by +%\cs{DTLloadrawdb}]{Special character mappings used by +%\cs{DTLloadrawdb} (note that the backslash retains its active state)} +%\label{tab:rawmappings} +%\begin{center} +%\begin{tabular}{ll} +%Character & Mapping\\ +%\verb|%| & \verb|\%|\\ +%\verb|$| & \verb|\$|\\ +%\verb|&| & \verb|\&|\\ +%\verb|#| & \verb|\#|\\ +%\verb|_| & \verb|\_|\\ +%\verb|{| & \verb|\{|\\ +%\verb|}| & \verb|\}|\\ +%\verb|~| & \cs{textasciitilde}\\ +%\verb|^| & \cs{textasciicircum} +%\end{tabular} +%\end{center} +%\end{table} +% +%It may be that there are other characters that require mapping. +%For example, the file \texttt{products.csv} may instead look like:\par +%\vskip\baselineskip +%\begin{ttfamily}\obeylines\setlength{\parindent}{0pt} +%Product,Cost +%Fruit \& Veg,\pounds1.25 +%Stationary,\pounds0.80 +%\end{ttfamily} +%\vskip\baselineskip +%The pound character is not an internationally standard keyboard +%character, and does not generally achieve the desired effect when used +%in a \LaTeX\ document. It will therefore be necessary to convert +%this symbol to an appropriate control sequence. This can be done +%using the command: +%\DescribeMacro{\DTLrawmap} +%\begin{definition} +%\cs{DTLrawmap}\marg{string}\marg{replacement} +%\end{definition} +%For example:\par +%\vskip\baselineskip +%\begin{ttfamily}\obeylines\setlength{\parindent}{0pt} +%\cs{DTLrawmap}\char`\{\pounds\char`\}\char`\{\cs{pounds}\char`\} +%\end{ttfamily} +%\vskip\baselineskip\noindent +%will convert all occurrences\footnote{when it is loaded into the +%\LaTeX\ database, it does not modify the data file!} of +%\texttt{\pounds} with \cs{pounds}. Naturally, the mappings must be +%set \emph{prior} to loading the data with \cs{DTLloadrawdb}. +% +%\importantpar Note that the warning in the previous section about no +%paragraph breaks in an entry also applies to entries loaded from a +%database. If you do need a paragraph break, use \ics{DTLpar} instead +%of \cs{par}, but remember that each row of data in an external data +%file must not have a line break. +% +%\subsection{Iterating Through a Database} +%\label{sec:dbforeach} +% +%Once you have created a database, either loading it from an +%external file, as described in \autoref{sec:loaddb}, or using the +%commands described in \autoref{sec:newdb}, you can then iterate +%through each row of the database and access elements in that row. +% +%\DescribeMacro{\DTLforeach} +%\begin{definition} +%\cs{DTLforeach}\oarg{condition}\marg{db name}\marg{assign list}\marg{text} +%\end{definition} +%\DescribeMacro{\DTLforeach*} +%\begin{definition} +%\cs{DTLforeach*}\oarg{condition}\marg{db name}\marg{assign list}\marg{text} +%\end{definition} +%This will iterate through each row of the database called +%\meta{db name}, applying \meta{text} to each row of the database +%where \meta{condition} is met. The argument \meta{assign list} is a +%comma separated list of \meta{cmd}"="\meta{key} pairs. At the +%start of each row, each command \meta{cmd} in \meta{assign list} +%will be set to the value of the entry given by \meta{key}. +%These commands may then be used in \meta{text}. +% +%\importantpar Note that this assignment is done globally to ensure +%that \cs{DLTforeach} works correctly in a \env{tabular} environment. +%Since you may want to use the same set of commands in a later +%\cs{DTLforeach}, the commands are not checked to determine if they +%already exist. It is therefore important that you check you are not +%using an existing command whose value should not be changed. +% +%The optional argument \meta{condition} is a condition in the +%form allowed by \cs{ifthenelse}. This includes the commands +%provided by the \sty{ifthen} package, as well as the commands +%described in \autoref{sec:ifthen}. The default value of +%\meta{condition} is "\boolean{true}". +% +%The starred version \cs{DTLforeach*} is a read-only version. +%If you want to modify the database using any of the commands +%described in \autoref{sec:editdb}, you must use the unstarred +%version. The starred version is slightly quicker, however the +%difference will probably only be noticeable for very large +%databases. +% +%\begin{example}{Student scores}{ex:scores} +%Suppose you have a data file called \texttt{studentscores.csv} that +%contains the following: +%\begin{verbatim} +%FirstName,Surname,StudentNo,Score +%John,"Smith, Jr",102689,68 +%Jane,Brown,102647,75 +%Andy,Brown,103569,42 +%Z\"oe,Adams,105987,52 +%Roger,Brady,106872,58 +%Clare,Verdon,104356,45 +%\end{verbatim} +%\DTLnewdb{scores}\relax +%\DTLnewrow{scores}\relax +%\DTLnewdbentry{scores}{FirstName}{John}\relax +%\DTLnewdbentry{scores}{Surname}{Smith, Jr}\relax +%\DTLnewdbentry{scores}{StudentNo}{102689}\relax +%\DTLnewdbentry{scores}{Score}{68}\relax +%\DTLnewrow{scores}\relax +%\DTLnewdbentry{scores}{FirstName}{Jane}\relax +%\DTLnewdbentry{scores}{Surname}{Brown}\relax +%\DTLnewdbentry{scores}{StudentNo}{102647}\relax +%\DTLnewdbentry{scores}{Score}{75}\relax +%\DTLnewrow{scores}\relax +%\DTLnewdbentry{scores}{FirstName}{Andy}\relax +%\DTLnewdbentry{scores}{Surname}{Brown}\relax +%\DTLnewdbentry{scores}{StudentNo}{103569}\relax +%\DTLnewdbentry{scores}{Score}{42}\relax +%\DTLnewrow{scores}\relax +%\DTLnewdbentry{scores}{FirstName}{Z\"oe}\relax +%\DTLnewdbentry{scores}{Score}{52}\relax +%\DTLnewdbentry{scores}{StudentNo}{105987}\relax +%\DTLnewdbentry{scores}{Surname}{Adams}\relax +%\DTLnewrow{scores}\relax +%\DTLnewdbentry{scores}{FirstName}{Roger}\relax +%\DTLnewdbentry{scores}{Score}{58}\relax +%\DTLnewdbentry{scores}{StudentNo}{106872}\relax +%\DTLnewdbentry{scores}{Surname}{Brady}\relax +%\DTLnewrow{scores}\relax +%\DTLnewdbentry{scores}{FirstName}{Clare}\relax +%\DTLnewdbentry{scores}{Score}{45}\relax +%\DTLnewdbentry{scores}{StudentNo}{104356}\relax +%\DTLnewdbentry{scores}{Surname}{Verdon}\relax +%and you load the data into a database called "scores" using: +%\begin{verbatim} +%\DTLloaddb{scores}{studentscores.csv} +%\end{verbatim} +%you can then display the database in a table as follows: +%\begin{verbatim} +%\begin{table}[htbp] +%\caption{Student scores} +%\centering +%\begin{tabular}{llr} +%\bfseries First Name & +%\bfseries Surname & +%\bfseries Score (\%)% +%\DTLforeach{scores}{% +%\firstname=FirstName,\surname=Surname,\score=Score}{% +%\\ +%\firstname & \surname & \score} +%\end{tabular} +%\end{table} +%\end{verbatim} +%This produces \autoref{tab:scores}. (Note that since I didn't +%need the student registration number, I didn't bother to +%assign a command to the key "StudentNo".) +% +%\begin{table}[htbp] +%\caption[Student scores (displaying a database in a +%table)]{Student scores}\label{tab:scores} +%\centering +%\begin{tabular}{llr} +%\bfseries First Name & +%\bfseries Surname & +%\bfseries Score (\%)\relax +%\DTLforeach{scores}{\firstname=FirstName,\surname=Surname,\score=Score}{\relax +%\\ +%\firstname & \surname & \score} +%\end{tabular} +%\end{table} +%\end{example} +% +%The macro \ics{DTLforeach} may be nested up to three times. Each +%level uses the corresponding counters: +%\counterfmt{DTLrowi}, +%\counterfmt{DTLrowii} and +%\counterfmt{DTLrowiii} which keep track of +%the current row. +% +%\importantpar Note that these counters are only incremented +%when \meta{condition} is satisfied. These counters are incremented +%using \cs{refstepcounter} before the start of \meta{text}, so they +%may be referenced using \cs{label}, however remember that \cs{label} +%references the last counter to be incremented using +%\cs{refstepcounter} \emph{in the current scope}. The \cs{label} +%should therefore be the first command in \meta{text} to ensure +%that it references the current row counter. +% +%\DescribeMacro{\DTLcurrentindex} +%\begin{definition} +%\cs{DTLcurrentindex} +%\end{definition} +%At the start of each iteration, \cs{DTLcurrentindex} is set +%to the arabic value of the current row counter. +% +%\DescribeMacro{\DTLforeachkeyinrow} +%\begin{definition} +%\cs{DTLforeachkeyinrow}\marg{cmd}\marg{text} +%\end{definition} +%This iterates through each key in the current row, assigns +%\meta{cmd} to the value of that key, and does \meta{text}. +%(\meta{cmd} must be a control sequence.) +% +%\begin{example}{Student Scores---Labelling}{ex:label} +%In the previous example, the student scores, stored in the +%database "scores" were placed in a table. In this example the +%table will be modified slightly to number each student according +%to the row. Suppose I also want to identify which row Jane Brown +%is in, and reference it in the text. The easiest way to do this +%is to construct a label on each row which uniquely identifies +%that student. The label can't simply be constructed from the +%surname, as there are two students with the same surname. In order +%to create a unique label, I can either construct a label from +%both the surname and the first name, or I can use the student's +%registration number, or I can use the student's score, since all +%the scores are unique. The former method will cause a problem since +%one of the names (Z\"oe) contains an accent command. Although +%the registration numbers are all unique, they are not particularly +%memorable, so I shall instead use the scores. +%\begin{verbatim} +%\begin{table}[htbp] +%\caption{Student scores} +%\centering +%\begin{tabular}{cllc} +%\bfseries Row & +%\bfseries First Name & +%\bfseries Surname & +%\bfseries Score (\%)% +%\DTLforeach{scores}{% +%\firstname=FirstName,\surname=Surname,\score=Score}{% +%\label{row:\score}\\\theDTLrowi & +%\firstname & \surname & \score}% +%\end{tabular} +%\end{table} +% +%Jane Brown scored the highest (75\%), her score can be seen on +%row~\ref{row:75}. +%\end{verbatim} +%This produces \autoref{tab:scoreslab} and the following text: +%Jane Brown scored the highest (75\%), her score can be seen on +%row~\ref*{row:75}. +% +%\textbf{Note:} the \cs{label} command is placed before +%"\\" to ensure that it is in the same scope as the command +%"\refstepcounter{DTLrowi}". +% +%\begin{table}[htbp] +%\caption[Student scores (labelling rows)]{Student +%scores}\label{tab:scoreslab} +%\centering +%\begin{tabular}{cllc} +%\bfseries Row & +%\bfseries First Name & +%\bfseries Surname & +%\bfseries Score (\%)\relax +%\DTLforeach{scores}{\firstname=FirstName,\surname=Surname,\score=Score}{\relax +%\label{row:\score}\\\theDTLrowi & +%\firstname & \surname & \score}\relax +%\end{tabular} +%\end{table} +%\end{example} +% +%\DescribeMacro{\DTLsavelastrowcount} +%\begin{definition} +%\cs{DTLsavelastrowcount}\marg{cmd} +%\end{definition} +%This command will store the value of the row counter used in +%the last occurrence of \ics{DTLforeach} in the control sequence +%\meta{cmd}. +% +%\begin{example}{Filtering Rows}{ex:filter} +%As mentioned earlier, the optional argument \meta{condition} of +%\ics{DTLforeach} provides a means to exclude certain rows. +%This example uses the database defined in \autoref{ex:scores}, +%but only displays the information for students whose marks are +%above 60. At the end of the table, \cs{DTLsavelastrowcount} +%is used to store the number of rows in the table. (Note that +%\cs{DTLsavelastrowcount} is outside of \ics{DTLforeach}.) +%\begin{verbatim} +%\begin{table}[htbp] +%\caption{Top student scores} +%\centering +%\begin{tabular}{llr} +%\bfseries First Name & +%\bfseries Surname & +%\bfseries Score (\%)% +%\DTLforeach[\DTLisgt{\score}{60}]{scores}{% +%\firstname=FirstName,\surname=Surname,\score=Score}{% +%\\ +%\firstname & \surname & \score} +%\end{tabular} +% +%\DTLsavelastrowcount{\n}% +%\n\ students scored above 60\%. +%\end{table} +%\end{verbatim} +%This produces \autoref{tab:topscores}. Note that in this example, +%I could have specified the condition as "\score>60" since all +%the scores are integers, however, as it's possible that an entry +%may feasibly have a decimal score I have used \ics{DTLisgt} instead. +% +%\begin{table}[htbp] +%\caption[Top student scores (filtering rows using +%\cs{DTLisgt})]{Top student scores}\label{tab:topscores} +%\centering +%\begin{tabular}{llr} +%\bfseries First Name & +%\bfseries Surname & +%\bfseries Score (\%)\relax +%\DTLforeach[\DTLisgt{\score}{60}]{scores}{\firstname=FirstName,\surname=Surname,\score=Score}{\relax +%\\ +%\firstname & \surname & \score} +%\end{tabular} +% +%\DTLsavelastrowcount{\n}\relax +%\n\ students scored above 60\%. +%\end{table} +% +%Suppose now, I only want to display the scores for students whose +%surname begins with `B'. I can do this as follows: +%\begin{verbatim} +%\begin{table}[htbp] +%\caption{Student scores (B)} +%\centering +%\begin{tabular}{llr} +%\bfseries First Name & +%\bfseries Surname & +%\bfseries Score (\%)% +%\DTLforeach[\DTLisopenbetween{\surname}{B}{C}]{scores}{% +%\firstname=FirstName,\surname=Surname,\score=Score}{% +%\\ +%\firstname & \surname & \score} +%\end{tabular} +%\end{table} +%\end{verbatim} +%This produces \autoref{tab:Bscores}. +% +%\begin{table}[htbp] +%\caption[Student scores (B) --- filtering rows using +%\cs{DTLisopenbetween}]{Student scores (B)}\label{tab:Bscores} +%\centering +%\begin{tabular}{llr} +%\bfseries First Name & +%\bfseries Surname & +%\bfseries Score (\%)\relax +%\DTLforeach[\DTLisopenbetween{\surname}{B}{C}]{scores} +%{\firstname=FirstName,\surname=Surname,\score=Score}{\relax +%\\ +%\firstname & \surname & \score} +%\end{tabular} +%\end{table} +% +%\end{example} +% +%Within the body of \ics{DTLforeach} (i.e.\ within \meta{text}) +%the following conditionals may be used: +%\DescribeMacro{\DTLiffirstrow} +%\begin{definition} +%\cs{DTLiffirstrow}\marg{true part}\marg{false part} +%\end{definition} +%If the current row is the first row, then do \meta{true part}, +%otherwise do \meta{false part}. +% +%\DescribeMacro{\DTLifoddrow} +%\begin{definition} +%\cs{DTLifoddrow}\marg{true part}\marg{false part} +%\end{definition} +%If the current row number is an odd number, then do \meta{true part}, +%otherwise do \meta{false part}. +% +%\begin{example}{Stripy Tables}{ex:stripy} +%This example uses the same database as in the previous examples. +%It requires the \sty{colortbl} package, which provides the +%command \cs{rowcolor}. The command \cs{DTLifoddrow} is used +%to produce a striped table. +%\begin{verbatim} +%\begin{table}[htbp] +%\caption{A stripy table}\label{tab:stripy} +%\centering +%\begin{tabular}{llc} +%\bfseries First Name & +%\bfseries Surname & +%\bfseries Score (\%)% +%\DTLforeach{scores}{% +%\firstname=FirstName,\surname=Surname,\score=Score}{% +%\\\DTLifoddrow{\rowcolor{blue}}{\rowcolor{green}}% +%\firstname & \surname & \score}% +%\end{tabular} +%\end{table} +%\end{verbatim} +%This produces \autoref{tab:stripy}. +% +%\begin{table}[htbp] +%\caption[A stripy table (illustrating the use of +%\cs{DTLifoddrow})]{A stripy table}\label{tab:stripy} +%\centering +%\begin{tabular}{llc} +%\bfseries First Name & +%\bfseries Surname & +%\bfseries Score (\%)\relax +%\DTLforeach{scores}{\firstname=FirstName,\surname=Surname,\score=Score}{\relax +%\\\DTLifoddrow{\rowcolor{blue}}{\rowcolor{green}}\relax +%\firstname & \surname & \score}\relax +%\end{tabular} +%\end{table} +%\end{example} +% +%\begin{example}{Two Database Rows per Tabular Row}{ex:2rows} +%In order to save space, you may want two database rows per +%tabular row, when displaying a database in a \env{tabular} +%environment. This can be accomplished using \ics{DTLifoddrow}. +%For example +%\begin{verbatim} +%\begin{table}[htbp] +%\caption{Two database rows per tabular row} +%\centering +%\begin{tabular}{llcllc} +%\bfseries First Name & +%\bfseries Surname & +%\bfseries Score (\%) & +%\bfseries First Name & +%\bfseries Surname & +%\bfseries Score (\%)% +%\DTLforeach{scores}{\firstname=FirstName,\surname=Surname,\score=Score}{% +%\DTLifoddrow{\\}{&}% +%\firstname & \surname & \score}% +%\end{tabular} +%\end{table} +%\end{verbatim} +%produces \autoref{tab:2rows} +% +%\begin{table}[htbp] +%\caption[Two database rows per tabular row (illustrating the +%use of\newline \cs{DTLifoddrow})]{Two database rows per tabular +%row}\label{tab:2rows} +%\centering +%\begin{tabular}{llcllc} +%\bfseries First Name & +%\bfseries Surname & +%\bfseries Score (\%) & +%\bfseries First Name & +%\bfseries Surname & +%\bfseries Score (\%)\relax +%\DTLforeach{scores}{\firstname=FirstName,\surname=Surname,\score=Score}{\relax +%\DTLifoddrow{\\}{&}\relax +%\firstname & \surname & \score}\relax +%\end{tabular} +%\end{table} +%\end{example} +% +%\begin{example}{Nested \cs{DTLforeach}}{ex:nested} +%In this example I have a CSV file called "index.csv" which +%contains: +%\begin{verbatim} +%File,Temperature,NaCl,pH +%exp25a.csv,25,4.7,0.5 +%exp25b.csv,25,4.8,1.5 +%exp30a.csv,30,5.12,4.5 +%\end{verbatim} +%\DTLnewdb{index}\relax +%\DTLnewrow{index}\relax +%\DTLnewdbentry{index}{File}{exp25a.csv}\relax +%\DTLnewdbentry{index}{Temperature}{25}\relax +%\DTLnewdbentry{index}{NaCl}{4.7}\relax +%\DTLnewdbentry{index}{pH}{0.5}\relax +%\DTLnewrow{index}\relax +%\DTLnewdbentry{index}{File}{exp25b.csv}\relax +%\DTLnewdbentry{index}{Temperature}{25}\relax +%\DTLnewdbentry{index}{NaCl}{4.8}\relax +%\DTLnewdbentry{index}{pH}{1.5}\relax +%\DTLnewrow{index}\relax +%\DTLnewdbentry{index}{File}{exp30a.csv}\relax +%\DTLnewdbentry{index}{Temperature}{30}\relax +%\DTLnewdbentry{index}{NaCl}{5.12}\relax +%\DTLnewdbentry{index}{pH}{4.5}\relax +%The first column of this file contains the name of another +%CSV file which has the results of a time to growth experiment +%performed at the given incubation temperature, salt concentration +%and pH. The file "exp25a.csv" contains the following: +%\begin{verbatim} +%Time,Log Count +%0,3.75 +%23,3.9 +%45,4.0 +%\end{verbatim} +%\DTLnewdb{exp25a.csv}\relax +%\DTLnewrow{exp25a.csv}\relax +%\DTLnewdbentry{exp25a.csv}{Time}{0}\relax +%\DTLnewdbentry{exp25a.csv}{Log Count}{3.75}\relax +%\DTLnewrow{exp25a.csv}\relax +%\DTLnewdbentry{exp25a.csv}{Time}{23}\relax +%\DTLnewdbentry{exp25a.csv}{Log Count}{3.9}\relax +%\DTLnewrow{exp25a.csv}\relax +%\DTLnewdbentry{exp25a.csv}{Time}{45}\relax +%\DTLnewdbentry{exp25a.csv}{Log Count}{4.0}\relax +%The file "exp25b.csv" contains the following: +%\begin{verbatim} +%Time,Log Count +%0,3.6 +%60,3.8 +%120,4.0 +%\end{verbatim} +%\DTLnewdb{exp25b.csv}\relax +%\DTLnewrow{exp25b.csv}\relax +%\DTLnewdbentry{exp25b.csv}{Time}{0}\relax +%\DTLnewdbentry{exp25b.csv}{Log Count}{3.6}\relax +%\DTLnewrow{exp25b.csv}\relax +%\DTLnewdbentry{exp25b.csv}{Time}{60}\relax +%\DTLnewdbentry{exp25b.csv}{Log Count}{3.8}\relax +%\DTLnewrow{exp25b.csv}\relax +%\DTLnewdbentry{exp25b.csv}{Time}{120}\relax +%\DTLnewdbentry{exp25b.csv}{Log Count}{4.0}\relax +%The file "exp30a.csv" contains the following: +%\begin{verbatim} +%Time,Log Count +%0,3.73 +%23,3.67 +%60,4.9 +%\end{verbatim} +%\DTLnewdb{exp30a.csv}\relax +%\DTLnewrow{exp30a.csv}\relax +%\DTLnewdbentry{exp30a.csv}{Time}{0}\relax +%\DTLnewdbentry{exp30a.csv}{Log Count}{3.73}\relax +%\DTLnewrow{exp30a.csv}\relax +%\DTLnewdbentry{exp30a.csv}{Time}{23}\relax +%\DTLnewdbentry{exp30a.csv}{Log Count}{3.67}\relax +%\DTLnewrow{exp30a.csv}\relax +%\DTLnewdbentry{exp30a.csv}{Time}{60}\relax +%\DTLnewdbentry{exp30a.csv}{Log Count}{4.9}\relax +%Suppose I now want to iterate through "index.csv", load the given +%file, and create a table for that data. I can do this using +%nested \ics{DTLforeach} as follows: +%\begin{verbatim} +% % load index data file +%\DTLloaddb{index}{index.csv} +% +% % iterate through index database +%\DTLforeach{index}{\theFile=File,\theTemp=Temperature,% +%\theNaCl=NaCl,\thepH=pH}{% +% % load results file into database of the same name +%\DTLloaddb{\theFile}{\theFile}% +% % Create a table +%\begin{table}[htbp] +%\caption{Temperature = \theTemp, NaCl = \theNaCl, +%pH = \thepH}\label{tab:\theFile} +%\centering +%\begin{tabular}{rl} +%\bfseries Time & \bfseries Log Count +%\DTLforeach{\theFile}{\theTime=Time,\theLogCount=Log Count}{% +%\\\theTime & \theLogCount}% +%\end{tabular} +%\end{table} +%} +%\end{verbatim} +%This creates \autoref{tab:exp25a.csv} to \autoref{tab:exp30a.csv}. +%(Note that each table is given a label that is based on the +%database name, to ensure that it is unique.) +% +%\DTLforeach{index}{\theFile=File,\theTemp=Temperature,\theNaCl +%=NaCl,\thepH=pH}{ +%\begin{table}[htbp] +%\caption[Temperature = \theTemp, NaCl = \theNaCl, +%pH = \thepH\space (illustrating nested +%\cs{DTLforeach})]{Temperature = \theTemp, NaCl = \theNaCl, +%pH = \thepH}\label{tab:\theFile} +%\centering +%\begin{tabular}{rl} +%\bfseries Time & \bfseries Log Count +%\DTLforeach{\theFile}{\theTime=Time,\theLogCount=Log Count}{ +%\\\theTime & \theLogCount}% +%\end{tabular} +%\end{table} +%} +%\end{example} +% +%\subsection{Null Values} +%If a database is created using \cs{DTLnewdb}, \cs{DTLnewrow} +%and \cs{DTLnewdbentry} (rather than loading it from an ASCII +%file), it is possible for some of the entries to have null values +%when a value is not assigned to a given key for a given row. +% +%When you iterate through the database using \cs{DTLforeach} +%(described in \autoref{sec:dbforeach}), +%if an entry is missing for a given row, the associated command given +%in the \meta{values} argument will be set to a null value. This +%value depends on the data type associated with the given key. +% +%\DescribeMacro{\DTLstringnull} +%\begin{definition} +%\cs{DTLstringnull} +%\end{definition} +%This is the null value for a string. +% +%\DescribeMacro{\DTLnumbernull} +%\begin{definition} +%\cs{DTLnumbernull} +%\end{definition} +%This is the null value for a number. +% +%\DescribeMacro{\DTLifnull} +%\begin{definition} +%\cs{DTLifnull}\marg{cmd}\marg{true part}\marg{false part} +%\end{definition} +%This checks if \meta{cmd} is null where \meta{cmd} is a command name, +%if it is, then \meta{true part} +%is done, otherwise \meta{false part} is done. This macro is +%illustrated in \autoref{ex:null} below. +% +%\begin{example}{Null Values}{ex:null} +%Consider the following (which creates a database called "emailDB"): +%\begin{verbatim} +%\DTLnewdb{emailDB} +%\DTLnewrow{emailDB} +%\DTLnewdbentry{emailDB}{Surname}{Jones} +%\DTLnewdbentry{emailDB}{FirstName}{Mary} +%\DTLnewdbentry{emailDB}{Email1}{mj@my.uni.ac.uk} +%\DTLnewdbentry{emailDB}{Email2}{mj@somewhere.com} +%\DTLnewrow{emailDB} +%\DTLnewdbentry{emailDB}{Surname}{Smith} +%\DTLnewdbentry{emailDB}{FirstName}{Adam} +%\DTLnewdbentry{emailDB}{Email1}{as@my.uni.ac.uk} +%\DTLnewdbentry{emailDB}{RegNum}{12345} +%\end{verbatim} +%\DTLnewdb{emailDB}\relax +%\DTLnewrow{emailDB}\relax +%\DTLnewdbentry{emailDB}{Surname}{Jones}\relax +%\DTLnewdbentry{emailDB}{FirstName}{Mary}\relax +%\DTLnewdbentry{emailDB}{Email1}{mj@my.uni.ac.uk}\relax +%\DTLnewdbentry{emailDB}{Email2}{mj@somewhere.com}\relax +%\DTLnewrow{emailDB}\relax +%\DTLnewdbentry{emailDB}{Surname}{Smith}\relax +%\DTLnewdbentry{emailDB}{FirstName}{Adam}\relax +%\DTLnewdbentry{emailDB}{Email1}{as@my.uni.ac.uk}\relax +%\DTLnewdbentry{emailDB}{RegNum}{12345}\relax +%In the above example, the first row of the database contains +%an entry with the key "Email2", but the second row doesn't. +%Whereas the second row contains an entry with the key "RegNum", +%but the first row doesn't. +% +%The following code puts the information in a \env{tabular} +%environment: +%\begin{verbatim} +%\begin{tabular}{lllll} +%\bfseries First Name & +%\bfseries Surname & +%\bfseries Email 1 & +%\bfseries Email 2 & +%\bfseries Reg Num% +%\DTLforeach{emailDB}{\firstname=FirstName,\surname=Surname,% +%\emailI=Email1,\emailII=Email2,\regnum=RegNum}{% +%\\\firstname & \surname & \emailI & \emailII & \regnum}% +%\end{tabular} +%\end{verbatim} +%This produces the following:\par\vskip\baselineskip\noindent +%\begin{tabular}{lllll} +%\bfseries First Name & +%\bfseries Surname & +%\bfseries Email 1 & +%\bfseries Email 2 & +%\bfseries Reg Num\relax +%\DTLforeach{emailDB}{\firstname=FirstName,\surname +%=Surname,\emailI=Email1,\emailII=Email2,\regnum=RegNum}{\relax +%\\\firstname & \surname & \emailI & \emailII & \regnum}\relax +%\end{tabular} +%\par\vskip\baselineskip +%Note that on the first row of data, the registration number appears as +%0, while on the next row, the second email address appears as +%NULL. The \sty{datatool} package has identified the key "RegNum" +%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). +% +%The following code checks each value to determine whether it +%is null using \cs{DTLifnull}. If it is, the text \emph{Missing} +%is inserted, otherwise the value itself is used: +%\begin{verbatim} +%\begin{tabular}{lllll} +%\bfseries First Name & +%\bfseries Surname & +%\bfseries Email 1 & +%\bfseries Email 2 & +%\bfseries Reg Num% +%\DTLforeach{emailDB}{\firstname=FirstName,\surname=Surname,% +%\emailI=Email1,\emailII=Email2,\regnum=RegNum}{% +%\\\DTLifnull{\firstname}{\emph{Missing}}{\firstname} & +%\DTLifnull{\surname}{\emph{Missing}}{\surname} & +%\DTLifnull{\emailI}{\emph{Missing}}{\emailI} & +%\DTLifnull{\emailII}{\emph{Missing}}{\emailII} & +%\DTLifnull{\regnum}{\emph{Missing}}{\regnum}}% +%\end{tabular} +%\end{verbatim} +%This produces the following:\par\vskip\baselineskip\noindent +%\begin{tabular}{lllll} +%\bfseries First Name & +%\bfseries Surname & +%\bfseries Email 1 & +%\bfseries Email 2 & +%\bfseries Reg Num\relax +%\DTLforeach{emailDB}{\firstname=FirstName,\surname +%=Surname,\emailI=Email1,\emailII=Email2,\regnum=RegNum}{\relax +%\\\DTLifnull{\firstname}{\emph{Missing}}{\firstname} & +%\DTLifnull{\surname}{\emph{Missing}}{\surname} & +%\DTLifnull{\emailI}{\emph{Missing}}{\emailI} & +%\DTLifnull{\emailII}{\emph{Missing}}{\emailII} & +%\DTLifnull{\regnum}{\emph{Missing}}{\regnum}}\relax +%\end{tabular} +%\par\vskip\baselineskip\noindent +%If you want to do this, you may find it easier to define a +%convenience command that will display some appropriate text +%if an entry is missing, for example: +%\begin{verbatim} +%\newcommand*{\checkmissing}[1]{\DTLifnull{#1}{---}{#1}} +%\end{verbatim} +%Then instead of typing, say, +%\begin{verbatim} +%\DTLifnull{\regnum}{---}{\regnum} +%\end{verbatim} +%you can instead type: +%\begin{verbatim} +%\checkmissing{\regnum} +%\end{verbatim} +% +%Now suppose that instead of defining the database using \cs{DTLnewdb}, +%\cs{DTLnewrow} and \cs{DTLnewdbentry}, you have a file with the +%contents: +%\begin{ttfamily}\setlength{\parindent}{0pt}\par\vskip\baselineskip +%Surname,FirstName,RegNum,Email1,Email2 +% +%\DTLforeach{emailDB}{\surname=Surname,\firstname=FirstName,\regNo +%=RegNum,\emailI=Email1,\emailII +%=Email2}{\relax +%\surname,\firstname,\DTLifnull{\regNo}{}{\regNo},\emailI,\DTLifnull{\emailII}{}{\emailII}\par +%} +%\end{ttfamily}\par\vskip\baselineskip\noindent +%and you load the data from this file using \cs{DTLloaddb} +%(defined in \autoref{sec:loaddb}). Now the +%database has no null values, but has an empty value for the +%key "RegNum" on the first row of the database, and an empty +%value for the key "Email2" on the second row of the database. +%Now, the following code +%\begin{verbatim} +%\begin{tabular}{lllll} +%\bfseries First Name & +%\bfseries Surname & +%\bfseries Email 1 & +%\bfseries Email 2 & +%\bfseries Reg Number% +%\DTLforeach{emailDB}{\firstname=FirstName,\surname=Surname,% +%\emailI=Email1,\emailII=Email2,\regnum=RegNum}{% +%\\\DTLifnull{\firstname}{\emph{Missing}}{\firstname} & +%\DTLifnull{\surname}{\emph{Missing}}{\surname} & +%\DTLifnull{\emailI}{\emph{Missing}}{\emailI} & +%\DTLifnull{\emailII}{\emph{Missing}}{\emailII} & +%\DTLifnull{\regnum}{\emph{Missing}}{\regnum}}% +%\end{tabular} +%\end{verbatim} +%produces:\par\vskip\baselineskip\noindent +%\begin{tabular}{lllll} +%\bfseries First Name & +%\bfseries Surname & +%\bfseries Email 1 & +%\bfseries Email 2 & +%\bfseries Reg Number\relax +%\DTLforeach{emailDB}{\firstname=FirstName,\surname +%=Surname,\emailI=Email1,\emailII=Email2,\regnum=RegNum}{\relax +%\\\firstname & \surname & \emailI & \DTLifnull{\emailII}{}{\emailII} & \DTLifnull{\regnum}{}{\regnum}}\relax +%\end{tabular} +%\end{example} +% +%\subsection{Editing Database Rows} +%\label{sec:editdb} +% +%In the body of the \ics{DTLforeach} loop, you can use the following +%to edit the current row: +%\DescribeMacro{\DTLappendtorow} +%\begin{definition} +%\cs{DTLappendtorow}\marg{key}\marg{value} +%\end{definition} +%This appends a new entry with the given \meta{key} and \meta{value} +%to the current row. +% +%\DescribeMacro{\DTLreplaceentryforrow} +%\begin{definition} +%\cs{DTLreplaceentryforrow}\marg{key}\marg{value} +%\end{definition} +%This replaces the entry for \meta{key} with \meta{value}. +% +%\DescribeMacro{\DTLremoveentryfromrow} +%\begin{definition} +%\cs{DTLremoveentryfromrow}\marg{key} +%\end{definition} +%This the entry for \meta{key} from the current row. +% +%\DescribeMacro{\DTLremovecurrentrow} +%\begin{definition} +%\cs{DTLremovecurrentrow} +%\end{definition} +%This removes the current row from the database. +% +%\begin{example}{Editing Database Rows}{ex:editdb} +%In this example I have a CSV file called "marks.csv" that contains +%student marks for three assignments: +%\DTLnewdb{marks}\relax +%\DTLnewrow{marks}\relax +%\DTLnewdbentry{marks}{FirstName}{John}\relax +%\DTLnewdbentry{marks}{Surname}{Smith, Jr}\relax +%\DTLnewdbentry{marks}{StudentNo}{102689}\relax +%\DTLnewdbentry{marks}{Assignment 1}{68}\relax +%\DTLnewdbentry{marks}{Assignment 2}{57}\relax +%\DTLnewdbentry{marks}{Assignment 3}{72}\relax +%\DTLnewrow{marks}\relax +%\DTLnewdbentry{marks}{FirstName}{Jane}\relax +%\DTLnewdbentry{marks}{Surname}{Brown}\relax +%\DTLnewdbentry{marks}{StudentNo}{102647}\relax +%\DTLnewdbentry{marks}{Assignment 1}{75}\relax +%\DTLnewdbentry{marks}{Assignment 2}{84}\relax +%\DTLnewdbentry{marks}{Assignment 3}{80}\relax +%\DTLnewrow{marks}\relax +%\DTLnewdbentry{marks}{FirstName}{Andy}\relax +%\DTLnewdbentry{marks}{Surname}{Brown}\relax +%\DTLnewdbentry{marks}{StudentNo}{103569}\relax +%\DTLnewdbentry{marks}{Assignment 1}{42}\relax +%\DTLnewdbentry{marks}{Assignment 2}{52}\relax +%\DTLnewdbentry{marks}{Assignment 3}{54}\relax +%\DTLnewrow{marks}\relax +%\DTLnewdbentry{marks}{FirstName}{Z\"oe}\relax +%\DTLnewdbentry{marks}{Surname}{Adams}\relax +%\DTLnewdbentry{marks}{StudentNo}{105987}\relax +%\DTLnewdbentry{marks}{Assignment 1}{52}\relax +%\DTLnewdbentry{marks}{Assignment 2}{48}\relax +%\DTLnewdbentry{marks}{Assignment 3}{57}\relax +%\DTLnewrow{marks}\relax +%\DTLnewdbentry{marks}{FirstName}{Roger}\relax +%\DTLnewdbentry{marks}{Surname}{Brady}\relax +%\DTLnewdbentry{marks}{StudentNo}{106872}\relax +%\DTLnewdbentry{marks}{Assignment 1}{58}\relax +%\DTLnewdbentry{marks}{Assignment 2}{60}\relax +%\DTLnewdbentry{marks}{Assignment 3}{62}\relax +%\DTLnewrow{marks}\relax +%\DTLnewdbentry{marks}{FirstName}{Clare}\relax +%\DTLnewdbentry{marks}{Surname}{Verdon}\relax +%\DTLnewdbentry{marks}{StudentNo}{104356}\relax +%\DTLnewdbentry{marks}{Assignment 1}{45}\relax +%\DTLnewdbentry{marks}{Assignment 2}{50}\relax +%\DTLnewdbentry{marks}{Assignment 3}{48}\relax +%\begin{ttfamily}\setlength{\parindent}{0pt}\par +%Surname,FirstName,StudentNo,Assignment 1,Assignment 2,Assignment 3 +% +%\DTLforeach{marks}{\surname=Surname,\firstname=FirstName,\regNo +%=StudentNo,\assignI=Assignment 1,\assignII +%=Assignment 2,\assignIII=Assignment 3}{\relax +%\char`\"\surname\char`\",\DTLifstringeq{\firstname}{Zoe}{Z\string\"oe}{\firstname},\regNo,\assignI,\assignII,\assignIII\par +%} +%\end{ttfamily}\par\noindent +%First load this into a database called "marks": +%\begin{verbatim} +%\DTLloaddb{marks}{marks.csv} +%\end{verbatim} +%Suppose now I want to compute the average mark for each +%student, and append this to the database. I can do this as +%follows: +%\begin{verbatim} +%\DTLforeach{marks}{% +%\assignI=Assignment 1,% +%\assignII=Assignment 2,% +%\assignIII=Assignment 3}{% +%\DTLmeanforall{\theMean}{\assignI,\assignII,\assignIII}% +%\DTLappendtorow{Average}{\theMean}} +%\end{verbatim} +%\DTLforeach{marks}{\assignI=Assignment 1,\assignII +%=Assignment 2,\assignIII=Assignment 3}{\relax +%\DTLmeanforall{\theMean}{\assignI,\assignII,\assignIII}% +%\DTLappendtorow{Average}{\theMean}}\relax +%For each row in the "marks" database, I now have an extra key +%called "Average" that contains the average mark over all three +%assignments for a given student. I can now put this data into +%a table: +%\begin{verbatim} +%\begin{table}[htbp] +%\caption{Student marks} +%\centering +%\begin{tabular}{llrrrr} +%\bfseries Surname & \bfseries First Name & +%\bfseries Assign 1 & +%\bfseries Assign 2 & +%\bfseries Assign 3 & +%\bfseries Average Mark% +%\DTLforeach{marks}{\surname=Surname,\firstname=FirstName,\average +%=Average,\assignI=Assignment 1,\assignII=Assignment 2,\assignIII +%=Assignment 3}{\\\surname +%& \firstname & \assignI & \assignII & \assignIII & +%\DTLround{\average}{\average}{2}\average}\relax +%\end{tabular} +%\end{table} +%\end{verbatim} +%This produces \autoref{tab:meanmarks}. +% +%Note that if I only wanted the averages for the table and nothing +%else, I could simply have computed the average in each row of the +%table and displayed it without adding the information to the +%database, however I am going to reuse this information in +%\autoref{ex:multibar}, so adding it to the database means that +%I don't need to recompute the mean. +% +%\begin{table}[htbp] +%\caption[Student marks (with averages)]{Student +%marks}\label{tab:meanmarks} +%\centering +%\begin{tabular}{llrrrr} +%\bfseries Surname & \bfseries First Name & +%\bfseries Assign 1 & +%\bfseries Assign 2 & +%\bfseries Assign 3 & +%\bfseries Average Mark\relax +%\DTLforeach{marks}{\surname=Surname,\firstname=FirstName,\average +%=Average,\assignI=Assignment 1,\assignII=Assignment 2,\assignIII +%=Assignment 3}{\\\surname +%& \firstname & \assignI & \assignII & \assignIII & +%\DTLround{\average}{\average}{2}\average}\relax +%\end{tabular} +%\end{table} +% +%\end{example} +% +%\subsection{Arithmetical Computations on Database Entries} +% +%The commands used in \autoref{sec:fp} can be used on database +%entries. You can, of course, directly use the commands provided +%by the \sty{fp} package if you know that the values are in the +%correct format (i.e.\ no currency symbols, no number group +%separators and a full stop as the decimal point) but if this is +%not the case, then you should use the commands described in +%\autoref{sec:fp}. If you want to use a command provided by the +%\sty{fp} package, that does not have a wrapper function in +%\sty{datatool}, then you will need to convert the value using +%\ics{DTLconverttodecimal}, and convert it back using either +%\ics{DTLdecimaltolocale} or \ics{DTLdecimaltocurrency}. +% +%\begin{example}{Arithmetical Computations}{ex:mean} +%In this example, I am going to produce a table similar to +%\autoref{tab:scores}, except that I want to add an extra row at the +%end which contains the average score. +%\begin{verbatim} +%\begin{table}[htbp] +%\caption{Student scores}\label{tab:mean} +%\centering +%\def\total{0}% +%\begin{tabular}{llr} +%\bfseries First Name & +%\bfseries Surname & +%\bfseries Score (\%)% +%\DTLforeach{scores}{% +%\firstname=FirstName,\surname=Surname,\score=Score}{% +%\\ +%\firstname & \surname & +%\DTLgadd{\total}{\score}{\total}% +%\score +%}\\ +%\multicolumn{2}{l}{\bfseries Average Score} & +%\DTLsavelastrowcount{\n}% +%\DTLdiv{\average}{\total}{\n}% +%\DTLround{\average}{\average}{2}% +%\average +%\end{tabular} +%\end{table} +%\end{verbatim} +%This produces \autoref{tab:mean}. +%\textbf{Notes:} +%\begin{itemize} +%\item I had to use \ics{DTLgadd} rather than \ics{DTLadd} since it +%occurs within a \env{tabular} environment which puts each entry +%in a local scope. +% +%\item I used \ics{DTLsavelastrowcount} to store the number of +%rows produced by \ics{DTLforeach} in the control sequence \cs{n}. +% +%\item I used \ics{DTLround} to round the average score to 2 decimal +%places. +%\end{itemize} +% +%\begin{table}[htbp] +%\caption[Student scores (using arithmetic computations)]{Student +%scores}\label{tab:mean} +%\centering +%\def\total{0}\relax +%\begin{tabular}{llr} +%\bfseries First Name & +%\bfseries Surname & +%\bfseries Score (\%)\relax +%\DTLforeach{scores}{\firstname=FirstName,\surname=Surname,\score=Score}{\relax +%\\ +%\firstname & \surname & +%\DTLgadd{\total}{\score}{\total}\relax +%\score +%}\\ +%\multicolumn{2}{l}{\bfseries Average Score} & +%\DTLsavelastrowcount{\n}\relax +%\DTLdiv{\average}{\total}{\n}\relax +%\DTLround{\average}{\average}{2}\relax +%\average +%\end{tabular} +%\end{table} +%\end{example} +% +%\DescribeMacro{\DTLsumforkeys} +%\begin{definition} +%\cs{DTLsumforkeys}\oarg{condition}\marg{db list}\marg{key list}\marg{cmd} +%\end{definition} +%This command sums all the entries over all the databases listed in +%the comma separated list of database names \meta{db list} for each key in +%\meta{key list} where the condition given by +%\meta{condition} is true. The result is stored in \meta{cmd} +%which must be a control sequence. For example: +%\begin{verbatim} +%\DTLsumforkeys{scores}{Score}{\total} +%\end{verbatim} +%sets \cs{total} to the sum of all the scores in the database +%called "scores". +% +%\DescribeMacro{\DTLmeanforkeys} +%\begin{definition} +%\cs{DTLmeanforkeys}\oarg{condition}\marg{db list}\marg{key list}\marg{cmd} +%\end{definition} +%This command computes the arithmetic mean of all the entries over +%all the databases listed in \meta{db list} for all keys in \meta{key list} where +%the condition +%given by \meta{condition} is true. The result is stored in \meta{cmd} +%which must be a control sequence. For example: +%\begin{verbatim} +%\DTLmeanforkeys{scores}{Score}{\average} +%\end{verbatim} +%sets \cs{average} to the mean of all the scores in the database +%called "scores". +% +%\DescribeMacro{\DTLvarianceforkeys} +%\begin{definition} +%\cs{DTLvarianceforkeys}\oarg{condition}\marg{db list}\marg{key list}\marg{cmd} +%\end{definition} +%This command computes the variance of all the entries over +%all the databases listed in \meta{db list} for all keys in \meta{key list} where +%the condition +%given by \meta{condition} is true. The result is stored in \meta{cmd} +%which must be a control sequence. +% +%\DescribeMacro{\DTLsdforkeys} +%\begin{definition} +%\cs{DTLsdforkeys}\oarg{condition}\marg{db list}\marg{key list}\marg{cmd} +%\end{definition} +%This command computes the standard deviation of all the entries over +%all the databases listed in \meta{db list} for all keys in \meta{key list} where +%the condition +%given by \meta{condition} is true. The result is stored in \meta{cmd} +%which must be a control sequence. +% +%\DescribeMacro{\DTLminforkeys} +%\begin{definition} +%\cs{DTLminforkeys}\oarg{condition}\marg{db list}\marg{key list}\marg{cmd} +%\end{definition} +%This command determines the minimum value over all entries +%for all keys in \meta{key list} over all the databases listed in \meta{db list} +%and stores +%in \meta{cmd}, which must be a control sequence. For example +%\begin{verbatim} +%\DTLminforkeys{scores}{Score}{\theMin} +%\end{verbatim} +%sets \cs{theMin} to the minimum score in the database. +% +%\DescribeMacro{\DTLmaxforkeys} +%\begin{definition} +%\cs{DTLmaxforkeys}\oarg{condition}\marg{db list}\marg{key list}\marg{cmd} +%\end{definition} +%This command determines the maximum value over all entries +%for all keys in \meta{key list} over all the databases listed in \meta{db list} +%and stores +%in \meta{cmd}, which must be a control sequence. For example +%\begin{verbatim} +%\DTLminforkeys{scores}{Score}{\theMax} +%\end{verbatim} +%sets \cs{theMax} to the minimum score in the database. +% +%\DescribeMacro{\DTLcomputebounds} +%\begin{definition} +%\cs{DTLcomputebounds}\marg{condition}\marg{db list}\marg{x key}\marg{y key}\marg{minX cmd}\marg{minY cmd}\marg{maxX cmd}\marg{maxY cmd} +%\end{definition} +%Computes the maximum and minimum $x$ and $y$ values over all +%the databases listed in \meta{db list} where the $x$ value +%is given by \meta{x key} and the $y$ value is given by +%\meta{y key}. The results are stored in \meta{minX cmd}, +%\meta{minY cmd}, \meta{maxX cmd} and \meta{maxY cmd}. +% +%\begin{example}{Mail Merging}{ex:mailmerging} +%This example uses the database given in \autoref{ex:scores} and +%uses \ics{DTLmeanforkeys} to determine the average score. A letter +%is then created for each student to inform them of their score +%and the class average. +% +%\begin{verbatim} +%\documentclass{letter} +% +%\usepackage{datatool} +% +%\begin{document} +% % load database +%\DTLloaddb{scores}{studentscores.csv} +% % compute arithmetic mean for key `Score' +%\DTLmeanforkeys{scores}{Score}{\average} +% % Round the average to 2 decimal places +%\DTLround{\average}{\average}{2} +% % Save the highest score in \maxscore +%\DTLmaxforkeys{scores}{Score}{\maxscore} +% +%\DTLforeach{scores}{\firstname=FirstName,\surname=Surname,% +%\score=Score}{% +%\begin{letter}{} +%\opening{Dear \firstname\ \surname} +% +%\DTLifnumgt{\score}{60}{Congratulations you}{You} achieved a score +%of \score\% which was \DTLifnumgt{\score}{\average}{above}{below} +%the average of \average\%. \DTLifnumeq{\score}{\maxscore}{You +%achieved the highest score}{The top score was \maxscore}. +% +%\closing{Yours Sincerely} +%\end{letter} +%} +%\end{document} +%\end{verbatim} +%\end{example} +% +%\subsection{Sorting a Database} +%\label{sec:sort} +% +%\DescribeMacro{\DTLsort} +%\begin{definition} +%\cs{DTLsort}\oarg{replacement key list}\marg{sort criteria}\marg{db name} +%\end{definition} +%\DescribeMacro{\DTLsort*} +%\begin{definition} +%\cs{DTLsort*}\oarg{replacement key list}\marg{sort criteria}\marg{db name} +%\end{definition} +%This will sort the database called \meta{db name} according to +%the criteria given by \meta{sort criteria}, which must be a +%comma separated list of keys and optionally "="\meta{order}, where +%\meta{order} is either "ascending" or "descending". If the order +%is omitted, "ascending" is assumed. The database keeps track of +%the data type for a given key, and uses this to determine whether +%an alphabetical or numerical sort is required. (String comparisons +%are made using the command \cs{dtlcompare} or \cs{dtlicompare} +%described in \autoref{src:dtlcompare}.) +% +%The optional argument \meta{replacement key list} is a list of +%keys to use if the current key given in \meta{sort criteria} +%is null for a given entry. Null keys are unlikely to occur if +%you have loaded the database from an external ASCII file, but +%may occur if the database is created using \cs{DTLnewdb}, +%\cs{DTLnewrow} and \cs{DTLnewdbentry}. For example: +%\begin{verbatim} +%\DTLsort[Editor,Organization]{Author}{mydata} +%\end{verbatim} +%will sort according to the "Author" key, but if that key is missing +%for a given row of the database, the "Editor" key will be used, +%and if the "Editor" key is missing, it will use the "Organization" +%key. Note that this is not the same as: +%\begin{verbatim} +%\DTLsort{Author,Editor,Organization}{mydata} +%\end{verbatim} +%which will first compare the "Author" keys, but if the author names +%are the same, it will then compare the "Editor" keys, and if the +%editor names are also the same, it will then compare the +%"Organization" keys. +% +%The unstarred version uses a case sensitive comparison for strings, +%whereas the starred version ignores the case when comparing strings. +%Note that the case sensitive comparison orders uppercase characters +%before lowercase characters, so the letter B is considered to be +%lower than the letter a. +% +%\begin{example}{Sorting a Database}{ex:sort} +%This example uses the database called "scores" defined in +%\autoref{ex:scores}. First, I am going to sort the database +%according to the student scores in descending order (highest to +%lowest) and display the database in a table +%\begin{verbatim} +%\begin{table}[htbp] +%\caption{Student scores (sorted by score)} +%\centering +%\DTLsort{Score=descending}{scores}% +%\begin{tabular}{llr} +%\bfseries First Name & +%\bfseries Surname & +%\bfseries Score (\%)% +%\DTLforeach{scores}{% +%\firstname=FirstName,\surname=Surname,\score=Score}{% +%\\ +%\firstname & \surname & \score} +%\end{tabular} +%\end{table} +%\end{verbatim} +%This produces \autoref{tab:sortscores}. +% +%\begin{table}[htbp] +%\caption{Student scores (sorted by score)}\label{tab:sortscores} +%\centering +%\DTLsort{Score=descending}{scores}\relax +%\begin{tabular}{llr} +%\bfseries First Name & +%\bfseries Surname & +%\bfseries Score (\%)\relax +%\DTLforeach{scores}{\firstname=FirstName,\surname=Surname,\score=Score}{\relax +%\\ +%\firstname & \surname & \score} +%\end{tabular} +%\end{table} +% +%Now I am going to sort the database according to +%surname and then first name, and display it in a table. Note that +%since I want to sort in ascending order, I can omit the +%"=ascending" part of the sort criteria. I have also decided to +%reverse the first and second columns, so that the surname is +%in the first column. +%\begin{verbatim} +%\begin{table}[htbp] +%\caption{Student scores (sorted by name)} +%\centering +%\DTLsort{Surname,FirstName}{scores}% +%\begin{tabular}{llr} +%\bfseries Surname & +%\bfseries First Name & +%\bfseries Score (\%)% +%\DTLforeach{scores}{% +%\firstname=FirstName,\surname=Surname,\score=Score}{% +%\\ +%\surname & \firstname & \score} +%\end{tabular} +%\end{table} +%\end{verbatim} +%This produces \autoref{tab:sortname}. +%\begin{table}[htbp] +%\caption{Student scores (sorted by name)}\label{tab:sortname} +%\centering +%\DTLsort{Surname,FirstName}{scores}\relax +%\begin{tabular}{llr} +%\bfseries Surname & +%\bfseries First Name & +%\bfseries Score (\%)\relax +%\DTLforeach{scores}{\firstname=FirstName,\surname=Surname,\score=Score}{\relax +%\\ +%\surname & \firstname & \score} +%\end{tabular} +%\end{table} +% +%Now suppose I add two new students to the database: +%\begin{verbatim} +%\DTLnewrow{scores}% +%\DTLnewdbentry{scores}{Surname}{van der Mere}% +%\DTLnewdbentry{scores}{FirstName}{Henk}% +%\DTLnewdbentry{scores}{Score}{71}% +%\DTLnewrow{scores}% +%\DTLnewdbentry{scores}{Surname}{de la Mere}% +%\DTLnewdbentry{scores}{FirstName}{Jos}% +%\DTLnewdbentry{scores}{Score}{58}% +%\end{verbatim} +%\DTLnewrow{scores} +%\DTLnewdbentry{scores}{Surname}{van der Mere}\relax +%\DTLnewdbentry{scores}{FirstName}{Henk}\relax +%\DTLnewdbentry{scores}{Score}{71}\relax +%\DTLnewrow{scores}\relax +%\DTLnewdbentry{scores}{Surname}{de la Mere}\relax +%\DTLnewdbentry{scores}{FirstName}{Jos}\relax +%\DTLnewdbentry{scores}{Score}{58}\relax +%and again I try sorting the database, and displaying the contents +%as a table: +%\begin{verbatim} +%\begin{table}[htbp] +%\caption{Student scores (case sensitive sort)} +%\centering +%\DTLsort{Surname,FirstName}{scores}% +%\begin{tabular}{llr} +%\bfseries Surname & +%\bfseries First Name & +%\bfseries Score (\%)% +%\DTLforeach{scores}{% +%\firstname=FirstName,\surname=Surname,\score=Score}{% +%\\ +%\surname & \firstname & \score} +%\end{tabular} +%\end{table} +%\end{verbatim} +%This produces \autoref{tab:sortname2}. Notice that the surnames +%aren't correctly ordered. This is because a case-sensitive +%sort was used. Changing \cs{DTLsort} to \cs{DTLsort*} in the +%above code produces \autoref{tab:sortname3}. +% +%\begin{table}[htbp] +%\caption{Student scores (case sensitive sort)}\label{tab:sortname2} +%\centering +%\DTLsort{Surname,FirstName}{scores}\relax +%\begin{tabular}{llr} +%\bfseries Surname & +%\bfseries First Name & +%\bfseries Score (\%)\relax +%\DTLforeach{scores}{\firstname=FirstName,\surname=Surname,\score=Score}{\relax +%\\ +%\surname & \firstname & \score} +%\end{tabular} +%\end{table} +% +%\begin{table}[htbp] +%\caption{Student scores (case ignored when +%sorting)}\label{tab:sortname3} +%\centering +%\DTLsort*{Surname,FirstName}{scores}\relax +%\begin{tabular}{llr} +%\bfseries Surname & +%\bfseries First Name & +%\bfseries Score (\%)\relax +%\DTLforeach{scores}{\firstname=FirstName,\surname=Surname,\score=Score}{\relax +%\\ +%\surname & \firstname & \score} +%\end{tabular} +%\end{table} +% +%\end{example} +% +%\begin{example}{Influencing the sort order}{ex:sortswitchargs} +%Consider the data displayed in \autoref{tab:sortname3}, suppose that +%you want the names ``van der Mere'' and ``de la Mere'' sorted +%according to the actual surname ``Mere'' rather than by the ``von +%part''. There are two ways you can do this: firstly, you could store +%the von part in a separate field, and then sort by surname, then von +%part, then first name, or you could define a command called, say, +%\cs{switchargs}, as follows: +%\begin{verbatim} +%\newcommand*{\switchargs}[2]{#2#1} +%\end{verbatim} +%\newcommand*{\switchargs}[2]{#2#1}\relax +%then store the data as: +%\begin{verbatim} +%FirstName,Surname,StudentNo,Score +%John,"Smith, Jr",102689,68 +%Jane,Brown,102647,75 +%Andy,Brown,103569,42 +%Z\"oe,Adams,105987,52 +%Roger,Brady,106872,58 +%Clare,Verdon,104356,45 +%Henk,\switchargs{Mere}{van der },106789,71 +%Jos,\switchargs{Mere}{de la },104256,58 +%\end{verbatim} +%\DTLnewdb{scores2}\relax +%\DTLnewrow{scores2}\relax +%\DTLnewdbentry{scores2}{FirstName}{John}\relax +%\DTLnewdbentry{scores2}{Surname}{Smith, Jr}\relax +%\DTLnewdbentry{scores2}{StudentNo}{102689}\relax +%\DTLnewdbentry{scores2}{Score}{68}\relax +%\DTLnewrow{scores2}\relax +%\DTLnewdbentry{scores2}{FirstName}{Jane}\relax +%\DTLnewdbentry{scores2}{Surname}{Brown}\relax +%\DTLnewdbentry{scores2}{StudentNo}{102647}\relax +%\DTLnewdbentry{scores2}{Score}{75}\relax +%\DTLnewrow{scores2}\relax +%\DTLnewdbentry{scores2}{FirstName}{Andy}\relax +%\DTLnewdbentry{scores2}{Surname}{Brown}\relax +%\DTLnewdbentry{scores2}{StudentNo}{103569}\relax +%\DTLnewdbentry{scores2}{Score}{42}\relax +%\DTLnewrow{scores2}\relax +%\DTLnewdbentry{scores2}{FirstName}{Z\"oe}\relax +%\DTLnewdbentry{scores2}{Score}{52}\relax +%\DTLnewdbentry{scores2}{StudentNo}{105987}\relax +%\DTLnewdbentry{scores2}{Surname}{Adams}\relax +%\DTLnewrow{scores2}\relax +%\DTLnewdbentry{scores2}{FirstName}{Roger}\relax +%\DTLnewdbentry{scores2}{Score}{58}\relax +%\DTLnewdbentry{scores2}{StudentNo}{106872}\relax +%\DTLnewdbentry{scores2}{Surname}{Brady}\relax +%\DTLnewrow{scores2}\relax +%\DTLnewdbentry{scores2}{FirstName}{Clare}\relax +%\DTLnewdbentry{scores2}{Score}{45}\relax +%\DTLnewdbentry{scores2}{StudentNo}{104356}\relax +%\DTLnewdbentry{scores2}{Surname}{Verdon}\relax +%\DTLnewrow{scores2} +%\DTLnewdbentry{scores2}{Surname}{\switchargs{Mere}{van der }}\relax +%\DTLnewdbentry{scores2}{FirstName}{Henk}\relax +%\DTLnewdbentry{scores2}{Score}{71}\relax +%\DTLnewrow{scores2}\relax +%\DTLnewdbentry{scores2}{Surname}{\switchargs{Mere}{de la }}\relax +%\DTLnewdbentry{scores2}{FirstName}{Jos}\relax +%\DTLnewdbentry{scores2}{Score}{58}\relax +%Now sort the data, and put it in table (this is the same code +%as in the previous example: +%\begin{verbatim} +%\begin{table}[htbp] +%\caption{Student scores (influencing the sort order)} +%\centering +%\DTLsort*{Surname,FirstName}{scores}% +%\begin{tabular}{llr} +%\bfseries Surname & +%\bfseries First Name & +%\bfseries Score (\%)% +%\DTLforeach{scores}{% +%\firstname=FirstName,\surname=Surname,\score=Score}{% +%\\ +%\surname & \firstname & \score} +%\end{tabular} +%\end{table} +%\end{verbatim} +%This produces \autoref{tab:influencesort}. +% +%\begin{table}[htbp] +%\caption{Student scores (influencing the sort order)}\label{tab:influencesort} +%\centering +%\DTLsort*{Surname,FirstName}{scores2}\relax +%\begin{tabular}{llr} +%\bfseries Surname & +%\bfseries First Name & +%\bfseries Score (\%)\relax +%\DTLforeach{scores2}{\firstname=FirstName,\surname=Surname,\score=Score}{\relax +%\\ +%\surname & \firstname & \score} +%\end{tabular} +%\end{table} +% +%\end{example} +% +%\subsection{Saving a Database to an External File} +%\label{sec:savedb} +% +%\DescribeMacro{\DTLsavedb} +%\begin{definition} +%\cs{DTLsavedb}\marg{db name}\marg{filename} +%\end{definition} +%This writes the database called \meta{db name} to a file called +%\meta{filename}. The separator and delimiter characters used +%are as given by \ics{DTLsetseparator} (or \ics{DTLsettabseparator}) +%and \ics{DTLsetdelimiter}. For example: +%\begin{verbatim} +%\DTLsettabdelimiter +%\DTLsavedb{scores}{scores.txt} +%\end{verbatim} +%will create a file called "scores.txt", and save the data in a +%tab separated format. (The delimiters will only be used if a +%given entry contains the separator character.) +% +%\DescribeMacro{\DTLsavetexdb} +%\begin{definition} +%\cs{DTLsavetexdb}\marg{db name}\marg{filename} +%\end{definition} +%This writes the database called \meta{db name} to a \LaTeX\ file +%called \meta{filename}, where the database is stored as +%a combination of \ics{DTLnewdb}, \ics{DTLnewrow} and +%\ics{DTLnewdbentry} commands. +% +%\section{Pie Charts (\texorpdfstring{\sty{datapie}}{datapie} package)} +% +%The \sty{datapie} package is not loaded by the \sty{datatool} package, +%so you need to load \sty{datapie} if you want to use any of the +%commands defined in this section. You will need to have the +%\sty{pgf}/\sty{tikz} packages installed. The \sty{datapie} package +%may be given the following options: +%\begin{description} +%\item[{\pkgopt[datapie]{color}}] Colour option (default.) +%\item[{\pkgopt[datapie]{monochrome}}] Monochrome option. +%\item[{\pkgopt[datapie]{rotateinner}}] +%Rotate inner labels so that they are aligned +%with the pie chart radial axis. +%\item[{\pkgopt[datapie]{norotateinner}}] +%Don't rotate inner labels (default.) +%\item[{\pkgopt[datapie]{rotateouter}}] +%Rotate outer labels so that they are aligned +%with the pie chart radial axis. +%\item[{\pkgopt[datapie]{norotateouter}}] +%Don't rotate outer labels (default.) +%\end{description} +% +%Numerical information contained in a database created by the +%\sty{datatool} package can be converted into a pie chart using +%\DescribeMacro{\DTLpiechart} +%\begin{definition} +%\cs{DTLpiechart}\oarg{condition}\marg{settings list}\marg{db name}\marg{values} +%\end{definition}\noindent +%where \meta{db name} is the name of the database, and +%\meta{condition} has the same form as the optional argument +%to \ics{DTLforeach} described in \autoref{sec:dbforeach}. If +%\meta{condition} is false, that information is omitted from the +%construction of the pie chart. The argument \meta{values} is a +%comma separated list of \meta{cmd}"="\meta{key} pairs, the same +%as that required by the penultimate argument of \ics{DTLforeach}. +%The \meta{settings list} is a comma separated list of +%\meta{setting}=\meta{value} pairs, where \meta{setting} can be any of +%the following: +%\begin{description} +%\item[\setting{DTLpiechart}{variable}] +%This specifies the control sequence to use that +%contains the value used to construct the pie chart. The control +%sequence must be one of the control sequences to appear in +%the assignment list \meta{values}. This setting is required. +% +%\item[\setting{DTLpiechart}{start}] +%This is the starting angle of the first segment. The +%value is 0 by default. +% +%\item[\setting{DTLpiechart}{radius}] +%This is the radius of the pie chart. The default value +%is 2cm. +% +%\item[\setting{DTLpiechart}{innerratio}] +%The distance from the centre of the +%pie chart to the point where the inner labels are placed is given +%by this value multiplied by the ratio. The default value is 0.5. +% +%\item[\setting{DTLpiechart}{outerratio}] +%The distance from the centre of the +%pie chart to the point where the outer labels are placed is given +%by this value multiplied by the ratio. The default value is 1.25. +% +%\item[\setting{DTLpiechart}{cutawayratio}] +%The distance from the centre of the pie chart +%to the point of cutaway segments is given by this value multiplied +%by the ratio. The default value is 0.2. +% +%\item[\setting{DTLpiechart}{inneroffset}] +%This is the absolute distance from the centre +%of the pie chart to the point where the inner labels are placed. +%You should use only one or other of \setting{DTLpiechart}{innerratio} +%and \setting{DTLpiechart}{inneroffset}, not both. If you also want to +%specify the radius, you must use \setting{DTLpiechart}{ratio} +%before \setting{DTLpiechart}{inneroffset}. If omitted, the inner +%offset is obtained from the ratio multiplied by the +%\setting{DTLpiechart}{innerratio} value. +% +%\item[\setting{DTLpiechart}{outeroffset}] +%This is the absolute distance from the centre +%of the pie chart to the point where the outer labels are placed. +%You should use only one or other of \setting{DTLpiechart}{outerratio} +%and \setting{DTLpiechart}{outeroffset}, not both. If you also want to +%specify the radius, you must use \setting{DTLpiechart}{ratio} +%before \setting{DTLpiechart}{outeroffset}. If omitted, the outer +%offset is obtained from the ratio multiplied by the +%\setting{DTLpiechart}{outerratio} value. +% +%\item[\setting{DTLpiechart}{cutawayoffset}] +%This is the absolute distance from the centre of +%the pie chart to the point of the cutaway segments. You should use +%only one or other of \setting{DTLpiechart}{cutawayratio} and +%\setting{DTLpiechart}{cutawayoffset}, not both. If +%you also want to specify the radius, you must use +%\setting{DTLpiechart}{ratio} before +%\setting{DTLpiechart}{cutawayoffset}. If omitted, the cutaway offset +%is obtained from the ratio multiplied by the +%\setting{DTLpiechart}{cutawayratio} value. +% +%\item[\setting{DTLpiechart}{cutaway}] +%This is a list of cutaway segments. This should be +%a comma separated list of individual numbers, or number ranges +%(separated by a dash.) For example "cutaway={1,3}" will separate +%the first and third segments from the rest of the pie chart, offset +%by the value of the \setting{DTLpiechart}{cutawayoffset} setting, +%whereas "cutaway={1-3}" will separate the +%first three segments from the rest of the pie chart. If omitted, +%the pie chart will be whole. +% +%\item[\setting{DTLpiechart}{innerlabel}] +%The value of this is positioned in the middle of each segment at a +%distance of \setting{DTLpiechart}{inneroffset} from the centre +%of the pie chart. The default is the same as the value of +%\setting{DTLpiechart}{variable}. +% +%\item[\setting{DTLpiechart}{outerlabel}] +%The value of this is positioned at a distance of +%\setting{DTLpiechart}{outeroffset} from the centre of the pie chart. +%The default is empty. +% +%\item[\setting{DTLpiechart}{rotateinner}] This is a boolean setting, +%so it can only take the values "true" and "false". If the value is +%omitted "true" is assumed. If true, the inner labels are rotated +%along the spokes of the pie chart, otherwise the inner labels are not +%rotated. There are analogous package options +%\pkgopt[datapie]{rotateinner} and \pkgopt[datapie]{norotateinner}. +% +%\item[\setting{DTLpiechart}{rotateouter}] +%This is a boolean setting, so it can only take +%the values "true" and "false". If the value is omitted "true" is +%assumed. If true, the outer labels are rotated along the spokes of +%the pie chart, otherwise the outer labels are not rotated. +%There are analogous package options +%\pkgopt[datapie]{rotateouter} and \pkgopt[datapie]{norotateouter}. +% +%\end{description} +% +%\begin{example}{A Pie Chart}{ex:piechart} +%This example loads data from a file called "fruit.csv" which contains +%the following: +%\begin{verbatim} +%Name,Quantity +%"Apples",30 +%"Pears",25 +%"Lemons,Limes",40.5 +%"Peaches",34.5 +%"Cherries",20 +%\end{verbatim} +%First load the data: +%\begin{verbatim} +%\DTLloaddb{fruit}{fruit.csv} +%\end{verbatim} +%\DTLnewdb{fruit}\relax +%\DTLnewrow{fruit}\relax +%\DTLnewdbentry{fruit}{Name}{Apples}\relax +%\DTLnewdbentry{fruit}{Quantity}{30}\relax +%\DTLnewrow{fruit}\relax +%\DTLnewdbentry{fruit}{Name}{Pears}\relax +%\DTLnewdbentry{fruit}{Quantity}{25}\relax +%\DTLnewrow{fruit}\relax +%\DTLnewdbentry{fruit}{Name}{Lemons,Limes}\relax +%\DTLnewdbentry{fruit}{Quantity}{40.5}\relax +%\DTLnewrow{fruit}\relax +%\DTLnewdbentry{fruit}{Name}{Peaches}\relax +%\DTLnewdbentry{fruit}{Quantity}{34.5}\relax +%\DTLnewrow{fruit}\relax +%\DTLnewdbentry{fruit}{Name}{Cherries}\relax +%\DTLnewdbentry{fruit}{Quantity}{20}\relax +%Now create a pie chart in a figure: +%\begin{verbatim} +%\begin{figure}[htbp] +%\centering +%\DTLpiechart{variable=\quantity}{fruit}{\name=Name,\quantity=Quantity} +%\caption{A pie chart} +%\end{figure} +%\end{verbatim} +%This creates \autoref{fig:piechart}. +% +%\begin{figure}[htbp] +%\centering +%\DTLpiechart{variable=\quantity}{fruit}{\name=Name,\quantity=Quantity} +%\caption{A pie chart} +%\label{fig:piechart} +%\end{figure} +% +%There are no outer labels by default, but they can be set +%using the \setting{DTLpiechart}{outerlabel} setting. +%The following sets the outer label to the value of the "Name" key: +%\begin{verbatim} +%\begin{figure}[htbp] +%\centering +%\DTLpiechart{variable=\quantity,outerlabel=\name}{fruit}{% +%\name=Name,\quantity=Quantity} +%\caption{A pie chart (outer labels set)} +%\end{figure} +%\end{verbatim} +%This creates \autoref{fig:piechartouter}. +% +%\begin{figure}[htbp] +%\centering +%\DTLpiechart{variable=\quantity,outerlabel=\name}{fruit} +%{\name=Name,\quantity=Quantity} +%\caption{A pie chart (outer labels set)} +%\label{fig:piechartouter} +%\end{figure} +% +%You may prefer the labels to be rotated. The following +%switches on the rotation for the inner and outer labels: +%\begin{verbatim} +%\begin{figure}[htbp] +%\centering +%\DTLpiechart{variable=\quantity,outerlabel=\name,% +%rotateinner,rotateouter}{fruit}{% +%\name=Name,\quantity=Quantity} +%\caption{A pie chart (rotation enabled)} +%\end{figure} +%\end{verbatim} +%This creates \autoref{fig:piechartrot}. +% +%\begin{figure}[htbp] +%\centering +%\DTLpiechart{variable=\quantity,outerlabel=\name +%,rotateinner,rotateouter}{fruit} +%{\name=Name,\quantity=Quantity} +%\caption{A pie chart (rotation enabled)} +%\label{fig:piechartrot} +%\end{figure} +%\end{example} +% +%\begin{example}{Separating Segments from the Pie Chart}{ex:cutaway} +%You may want to separate one or more segments from the pie chart, +%perhaps to emphasize them. You can do this using the +%\setting{DTLpiechart}{cutaway} +%setting. The following separates the first and third segments +%from the pie chart: +%\begin{verbatim} +%\begin{figure}[htbp] +%\centering +%\DTLpiechart{variable=\quantity,outerlabel=\name,% +%cutaway={1,3}}{fruit}{% +%\name=Name,\quantity=Quantity} +%\caption{A pie chart with cutaway segments} +%\end{figure} +%\end{verbatim} +%This produces \autoref{fig:piecutaway}. +% +%\begin{figure}[htbp] +%\centering +%\DTLpiechart{variable=\quantity,outerlabel=\name +%,cutaway={1,3}}{fruit}{\name=Name,\quantity=Quantity} +%\caption{A pie chart with cutaway segments} +%\label{fig:piecutaway} +%\end{figure} +% +%Alternatively I can specify a range of segments. The following +%separates the first two segments: +%\begin{verbatim} +%\begin{figure}[htbp] +%\centering +%\DTLpiechart{variable=\quantity,outerlabel=\name,% +%cutaway={1-2}}{fruit}{% +%\name=Name,\quantity=Quantity} +%\caption{A pie chart with cutaway segments (\texttt{cutaway=\{1-2\}})} +%\end{figure} +%\end{verbatim} +%This produces \autoref{fig:piecutaway2}. +% +%\begin{figure}[htbp] +%\centering +%\DTLpiechart{variable=\quantity,outerlabel=\name +%,cutaway={1-2}}{fruit}{\name=Name,\quantity=Quantity} +%\caption{A pie chart with cutaway segments (\texttt{cutaway=\{1-2\}})} +%\label{fig:piecutaway2} +%\end{figure} +% +%Notice the difference between \autoref{fig:piecutaway2} and +%\autoref{fig:piecutaway3} which was produced using: +%\begin{verbatim} +%\begin{figure}[htbp] +%\centering +%\DTLpiechart{variable=\quantity,outerlabel=\name,% +%cutaway={1,2}}{fruit}{% +%\name=Name,\quantity=Quantity} +%\caption{A pie chart with cutaway segments (\texttt{cutaway=\{1,2\}})} +%\end{figure} +%\end{verbatim} +% +%\begin{figure}[htbp] +%\centering +%\DTLpiechart{variable=\quantity,outerlabel=\name +%,cutaway={1,2}}{fruit}{\name=Name,\quantity=Quantity} +%\caption{A pie chart with cutaway segments (\texttt{cutaway=\{1,2\}})} +%\label{fig:piecutaway3} +%\end{figure} +% +%\end{example} +% +%\subsection{Pie Chart Variables} +% +%\DescribeMacro{\DTLpievariable} +%\begin{definition} +%\cs{DTLpievariable} +%\end{definition} +%This command is set to the variable given by the +%\setting{DTLpiechart}{variable} setting in the \meta{settings list} +%argument of \cs{DTLpiechart}. The \setting{DTLpiechart}{innerlabel} +%is set to \cs{DTLpievariable} by default. +% +%\DescribeMacro{\DTLpiepercent} +%\begin{definition} +%\cs{DTLpiepercent} +%\end{definition} +%This command is set to the percentage value of \cs{DTLpievariable}. +%The percentage value is rounded to \meta{n} digits, where \meta{n} +%is the value of the \LaTeX\ counter +%\counterfmt{DTLpieroundvar}. +% +%\begin{example}{Changing the Inner and Outer Labels}{ex:pielabels} +%This example uses the database defined in \autoref{ex:piechart}. +%The inner label is now set to the percentage value, rather than +%the actual value, and the outer label is set to the name with +%the actual value in parentheses. +%\begin{verbatim} +%\begin{figure}[htbp] +%\centering +%\DTLpiechart{variable=\quantity,% +%innerlabel={\DTLpiepercent\%},% +%outerlabel={\name\ (\DTLpievariable)}}{fruit}{% +%\name=Name,\quantity=Quantity} +%\caption{A pie chart (changing the labels)} +%\end{figure} +%\end{verbatim} +%This produces \autoref{fig:piechartlabels}. +% +%\begin{figure}[htbp] +%\centering +%\DTLpiechart{variable=\quantity,innerlabel={\DTLpiepercent +%\%},outerlabel={\name\ (\DTLpievariable)}}{fruit}{% +%\name=Name,\quantity=Quantity} +%\caption{A pie chart (changing the labels)} +%\label{fig:piechartlabels} +%\end{figure} +%\end{example} +% +%\subsection{Pie Chart Label Formatting} +% +%\DescribeMacro{\DTLdisplayinnerlabel} +%\begin{definition} +%\cs{DTLdisplayinnerlabel}\marg{text} +%\end{definition} +%This governs how the inner label is formatted, where \meta{text} +%is the text of the inner label. The default is to just do \meta{text}. +% +%\DescribeMacro{\DTLdisplayouterlabel} +%\begin{definition} +%\cs{DTLdisplayouterlabel}\marg{text} +%\end{definition} +%This governs how the outer label is formatted, where \meta{text} +%is the text of the outer label. The default is to just do \meta{text}. +% +%\begin{example}{Changing the Inner and Outer Label +%Format}{ex:pielabelformat} +%This example extends \autoref{ex:pielabels}. +%The inner and outer labels are now both typeset in a sans-serif +%font: +%\begin{verbatim} +%\begin{figure}[htbp] +%\centering +%\renewcommand*{\DTLdisplayinnerlabel}[1]{\textsf{#1}} +%\renewcommand*{\DTLdisplayouterlabel}[1]{\textsf{#1}} +%\DTLpiechart{variable=\quantity,% +%innerlabel={\DTLpiepercent\%},% +%outerlabel={\name\ (\DTLpievariable)}}{fruit}{% +%\name=Name,\quantity=Quantity} +%\caption{A pie chart (changing the label format)} +%\end{figure} +%\end{verbatim} +%This produces \autoref{fig:piechartlabelformat}. +% +%\begin{figure}[htbp] +%\centering +%\renewcommand*{\DTLdisplayinnerlabel}[1]{\textsf{#1}} +%\renewcommand*{\DTLdisplayouterlabel}[1]{\textsf{#1}} +%\DTLpiechart{variable=\quantity,innerlabel={\DTLpiepercent +%\%},outerlabel={\name\ (\DTLpievariable)}}{fruit}{% +%\name=Name,\quantity=Quantity} +%\caption{A pie chart (changing the label format)} +%\label{fig:piechartlabelformat} +%\end{figure} +%\end{example} +% +%\subsection{Pie Chart Colours} +% +%The \sty{datapie} package predefines colours for the first +%eight segments of the pie chart. If you require more than +%eight segments, you will need to use +%\DescribeMacro{\DTLsetpiesegmentcolor} +%\begin{definition} +%\cs{DTLsetpiesegmentcolor}\marg{n}\marg{color} +%\end{definition}\noindent +%to set the colours for any additional segments, or you can use +%it to change the default colours. The first argument \meta{n} +%is the segment index (starting from 1), and the second argument +%\meta{color} is a colour specifier as used in commands such as +%\cs{color}. +% +%\DescribeMacro{\DTLdopiesegmentcolor} +%\begin{definition} +%\cs{DTLdopiesegmentcolor}\meta{n} +%\end{definition} +%This sets the current text colour to that of the \meta{n}th +%segment. +% +%\DescribeMacro{\DTLdocurrentpiesegmentcolor} +%\begin{definition} +%\cs{DTLdocurrentpiesegmentcolor} +%\end{definition} +%This sets the current text colour to that of the current pie +%segment. This command may only be used within a pie chart, or +%within the body of \ics{DTLforeach}. +% +%\DescribeMacro{\DTLpieoutlinecolor} +%\begin{definition} +%\cs{DTLpieoutlinecolor} +%\end{definition} +%This sets the outline colour for the pie chart. The default is +%black. +% +%\DescribeMacro{\DTLpieoutlinewidth} +%\begin{definition} +%\cs{DTLpieoutlinewidth} +%\end{definition} +%This is a length that governs the line width of the outline. The +%default value is 0pt, but can be changed using \cs{setlength}. +%The outline is only drawn if \cs{DTLpieoutlinewidth} is greater +%than 0pt. +% +%\begin{example}{Pie Segment Colours}{ex:piecolours} +%This example extends \autoref{ex:pielabelformat}. +%It sets the outline thickness to 2pt, and +%the outer label is now set in the same colour as the fill colour +%of the segment to which it belongs. +%In addition, a legend is created using +%\ics{DTLforeach}. +%\begin{verbatim} +%\begin{figure}[htbp] +%\centering +%\setlength{\DTLpieoutlinewidth}{2pt} +%\renewcommand*{\DTLdisplayinnerlabel}[1]{\textsf{#1}} +%\renewcommand*{\DTLdisplayouterlabel}[1]{% +%\DTLdocurrentpiesegmentcolor +%\textsf{\shortstack{#1}}} +%\DTLpiechart{variable=\quantity,% +%innerlabel={\DTLpiepercent\%},% +%outerlabel={\name\\(\DTLpievariable)}}{fruit}{% +%\name=Name,\quantity=Quantity} +%\begin{tabular}[b]{ll} +%\DTLforeach{fruit}{\name=Name}{\DTLiffirstrow{}{\\}% +%\DTLdocurrentpiesegmentcolor\rule{10pt}{10pt} & +%\name +%} +%\end{tabular} +%\caption{A pie chart (using segment colours and outline)} +%\end{figure} +%\end{verbatim} +%This produces \autoref{fig:piesegcolour}. (The format of the +%outer label has been changed to use \cs{shortstack} to +%prevent the outer labels from taking up so much horizontal +%space. The \setting{DTLpiechart}{outerlabel} setting has also been +%modified to use "\\" after the name to move the percentage value onto +%the next row.) +% +%\begin{figure}[htbp] +%\centering +%\setlength{\DTLpieoutlinewidth}{2pt} +%\renewcommand*{\DTLdisplayinnerlabel}[1]{\textsf{#1}} +%\renewcommand*{\DTLdisplayouterlabel}[1]{\relax +%\DTLdocurrentpiesegmentcolor +%\textsf{\shortstack{#1}}} +%\DTLpiechart{variable=\quantity,innerlabel={\DTLpiepercent +%\%},outerlabel={\name\\(\DTLpievariable)}}{fruit}{% +%\name=Name,\quantity=Quantity} +%\begin{tabular}[b]{ll} +%\DTLforeach{fruit}{\name=Name}{\DTLiffirstrow{}{\\}\relax +%\DTLdocurrentpiesegmentcolor\rule{10pt}{10pt} & +%\name +%} +%\end{tabular} +%\caption{A pie chart (using segment colours and outline)} +%\label{fig:piesegcolour} +%\end{figure} +%\end{example} +% +%\subsection{Adding Extra Commands Before and After the Pie Chart} +% +%The pie charts created using \ics{DTLpiechart} are placed inside +%a \env{tikzpicture} environment (defined by the \sty{tikz} package.) +% +%\DescribeMacro{\DTLpieatbegintikz} +%\begin{definition} +%\cs{DTLpieatbegintikz} +%\end{definition} +%The macro \cs{DTLpieatbegintikz} is called at the start of the +%\env{tikzpicture} environment, allowing you to change the +%\env{tikzpicture} settings. By default \cs{DTLpieatbegintikz} +%does nothing, but you can redefine it to, say, scale the pie +%chart. +% +%\DescribeMacro{\DTLpieatendtikz} +%\begin{definition} +%\cs{DTLpieatendtikz} +%\end{definition} +%The macro \cs{DTLpieatendtikz} is called at the end of the +%\env{tikzpicture} environment, allowing you add additional +%graphics to the pie chart. This does nothing by default. +% +%\begin{example}{Adding Information to the Pie Chart}{ex:piescale} +%This example modifies \autoref{ex:piechart}. It redefines +%\cs{DTLpieatendtikz} to add an annotated arrow. +%\begin{verbatim} +%\begin{figure}[htbp] +%\centering +%\DTLpiechart{variable=\quantity}{fruit}{% +%\name=Name,\quantity=Quantity} +%\caption{An annotated pie chart} +%\end{figure} +%\end{verbatim} +%This produces \autoref{fig:pieannote}. (Note that the centre +%of the pie chart is the origin of the TikZ picture.) +% +%\begin{figure}[htbp] +%\centering +%\renewcommand*{\DTLpieatendtikz}{% +%\draw[<-] (45:1.5cm) -- (40:2.5cm)node[right]{Apples};} +%\DTLpiechart{variable=\quantity}{fruit}{\name=Name,\quantity=Quantity} +%\caption{An annotated pie chart} +%\label{fig:pieannote} +%\end{figure} +%\end{example} +% +%\section{Scatter and Line Plots (\texorpdfstring{\sty{dataplot}}{dataplot} +%package)} +% +%The \sty{dataplot} package provides commands for creating +%scatter or line plots from databases. It uses the pgf/TikZ plot +%handler library to create the plots. See the \sty{pgf} manual for +%more detail on pgf streams and plot handles. The \sty{dataplot} +%package is not loaded by \sty{datatool} so if you want to use +%it you need to load it explicitly using "\usepackage{dataplot}". +% +%\DescribeMacro{\DTLplot} +%\begin{definition} +%\cs{DTLplot}\oarg{condition}\marg{db list}\marg{settings} +%\end{definition} +%This command creates a plot (inside a \env{tikzpicture} environment) +%of all the data given in the databases listed in \meta{db list}, +%which should be a comma separated list of database names. +%The optional argument \meta{condition} is the same as that for +%\ics{DTLforeach}. The \meta{settings} argument is a comma separated +%list of \meta{setting}"="\meta{value} pairs. There are two settings +%that must be specified \setting{DTLplot}{x} and \setting{DTLplot}{y}. +%The other settings are optional. Note that any value that contains +%a comma, must be enclosed in braces. For example +%"colors={red,cyan,blue}". Note where any setting requires +%a number, or list of numbers (such as \setting{DTLplot}{bounds}) +%the number must be supplied in standard decimal notation (i.e.\ +%no currency, no number groups, and a full stop as the decimal +%point.) Available settings are as follows: +%\begin{description} +%\item[\setting{DTLplot}{x}] The database key +%that specifies the $x$ co-ordinates. This setting is required. +% +%\item[\setting{DTLplot}{y}] The database key that specifies +%the $y$ co-ordinates. This setting is required. +% +%\item[\setting{DTLplot}{markcolors}] A comma separated list of colour +%names for the markers. An empty value will use the current colour. +% +%\item[\setting{DTLplot}{linecolors}] A comma separated list of colour +%names for the plot lines. An empty value will use the current colour. +% +%\item[\setting{DTLplot}{colors}] A comma separated list of colour +%names for the lines and markers. +% +%\item[\setting{DTLplot}{marks}] A comma separated list of +%code to generate plot marks. (This should typically be a list +%of \cs{pgfuseplotmark} commands, see the \sty{pgf} manual for +%further details.) You may use \cs{relax} as an element +%of the list to suppress markers for the corresponding plot. +%For example: "marks={\pgfuseplotmark{o},\relax}" will use an +%open circle marker for the first database, and no markers for the +%second database listed in \meta{db list}. +% +%\item[\setting{DTLplot}{lines}] A comma separated list of +%line style settings. (This should typically be a list of +%\cs{pgfsetdash} commands, see the \sty{pgf} manual for +%further details on how to set the line style.) An empty value +%will use the current line style. +%You may use \cs{relax} as an element +%of the list to suppress line for the corresponding plot. +%For example: "lines={\relax,\pgfsetdash{}{0pt}}" +%will have no lines for the first database, and a solid line +%for the second database listed in \meta{db list}. +% +%\item[\setting{DTLplot}{width}] The width of the plot. This must +%be a length. The plot width does not include outer tick marks or +%labels. +% +%\item[\setting{DTLplot}{height}] The height of the plot. This must +%be a length. The plot height does not include outer tick marks +%or labels. +% +%\item[\setting{DTLplot}{style}] This setting governs whether +%to use lines or markers in the plot, and may take one of +%the following values: "both" (lines and markers), +%"lines" (only lines) or "markers" (only markers.) The default is +%"markers". +% +%\item[\setting{DTLplot}{axes}] This setting governs whether +%to display the axes, and may take one of +%the following values: "both", "x", "y" or "none". If no value +%is specified, "both" is assumed. +% +%\item[\setting{DTLplot}{box}] This setting governs whether +%or not to surround the plot in a box. It is a boolean setting, +%taking only the values "true" and "false". If no value is +%specified, "true" is assumed. +% +%\item[\setting{DTLplot}{xtics}] This setting governs whether +%or not to display the $x$ tick marks. It is a boolean setting, +%taking only the values "true" and "false". If no value is +%specified "true" is assumed. If the \setting{DTLplot}{axes} +%setting is set to "both" or "x", this value will automatically +%be set to "true", otherwise it will be set to "false". +% +%\item[\setting{DTLplot}{ytics}] This setting governs whether +%or not to display the $y$ ticks. It is a boolean setting, +%taking only the values "true" and "false". If no value is +%specified "true" is assumed. If the \setting{DTLplot}{axes} +%setting is set to "both" or "y", this value will automatically +%be set to "true", otherwise it will be set to "false". +% +% +%\item[\setting{DTLplot}{xminortics}] This setting governs whether +%or not to display the $x$ minor tick marks. It is a boolean +%setting, taking only the values "true" and "false". If no value is +%specified "true" is assumed. This setting also sets the +%$x$ major tick marks on if the value is "true". +% +%\item[\setting{DTLplot}{yminortics}] This setting governs whether +%or not to display the $y$ minor tick marks. It is a boolean +%setting, taking only the values "true" and "false". If no value is +%specified "true" is assumed. This setting also sets the +%$y$ major tick marks on if the value is "true". +% +%\item[\setting{DTLplot}{xticdir}] This sets the $x$ tick direction, +%and may only take the values "in" or "out". +% +%\item[\setting{DTLplot}{yticdir}] This sets the $y$ tick direction, +%and may only take the values "in" or "out". +% +%\item[\setting{DTLplot}{ticdir}] This sets the $x$ and $y$ tick +%direction, and may only take the values "in" or "out". +% +%\item[\setting{DTLplot}{bounds}] The value must be in the form +%\meta{min x}","\meta{min y}","\meta{max x}","\meta{max y}. This +%sets the graph bounds to the given values. If omitted the +%bounds are computed from the maximum and minimum values of the +%data. For example +%\begin{verbatim} +%\DTLplot{data1,data2}{x=Height,y=Weight,bounds={0,0,10,20}} +%\end{verbatim} +%Note that the \setting{DTLplot}{bounds} setting overrides +%the \setting{DTLplot}{minx}, \setting{DTLplot}{maxx}, +%\setting{DTLplot}{miny} and \setting{DTLplot}{maxy} settings. +% +%\item[\setting{DTLplot}{minx}] The value is the minimum value +%of the $x$ axis. +% +%\item[\setting{DTLplot}{miny}] The value is the minimum value +%of the $y$ axis. +% +%\item[\setting{DTLplot}{maxx}] The value is the maximum value +%of the $x$ axis. +% +%\item[\setting{DTLplot}{maxy}] The value is the maximum value +%of the $y$ axis. +% +%\item[\setting{DTLplot}{xticpoints}] The value must be a comma +%separated list of decimal numbers indicating where to put the +%$x$ tick marks. If omitted, the $x$ tick marks are placed at +%equal intervals along the $x$ axis such that each interval is +%not less than the length given by \ics{DTLmintickgap}. +%This setting overrides \setting{DTLplot}{xticgap}. +% +%\item[\setting{DTLplot}{xticgap}] This value specifies the +%gap between the $x$ tick marks. +% +%\item[\setting{DTLplot}{yticpoints}] The value must be a comma +%separated list of decimal numbers indicating where to put the +%$y$ tick marks. If omitted, the $y$ tick marks are placed at +%equal intervals along the $y$ axis such that each interval is +%not less than the length given by \ics{DTLmintickgap}. +%This setting overrides \setting{DTLplot}{yticgap}. +% +%\item[\setting{DTLplot}{yticgap}] This value specifies the +%gap between the $y$ tick marks. +% +%\item[\setting{DTLplot}{grid}] This is a boolean value that +%specifies whether or not to display the grid. If no value +%is given, "true" is assumed. The minor grid lines are only +%displayed if the minor tick marks are set. +% +%\item[\setting{DTLplot}{xticlabels}] The value must be a comma +%separated list of labels for each $x$ tick mark. If omitted, +%the labels are the value of the $x$ tick position, rounded +%\meta{n} digits after the decimal point, where \meta{n} is +%given by the value of the counter \counterfmt{DTLplotroundXvar}. +% +%\item[\setting{DTLplot}{yticlabels}] The value must be a comma +%separated list of labels for each $y$ tick mark. If omitted, +%the labels are the value of the $y$ tick position, rounded +%\meta{n} digits after the decimal point, where \meta{n} is +%given by the value of the counter \counterfmt{DTLplotroundYvar}. +% +%\item[\setting{DTLplot}{xlabel}] The value is the label for +%the $x$ axis. If omitted, the axis has no label. +% +%\item[\setting{DTLplot}{ylabel}] The value is the label for +%the $y$ axis. If omitted, the axis has no label. +% +%\item[\setting{DTLplot}{legend}] This setting governs whether +%or not to display the legend, and where it should be displayed. +%It may take one of the following values "none" (don't display +%the legend), "north", "northeast", "east", "southeast", "south", +%"southwest", "west" or "northwest". If the value is omitted, +%"northeast" is assumed. +% +%\item[\setting{DTLplot}{legendlabels}] The value must be a comma +%separated list of labels for the legend. If omitted, the database +%names are used. +% +%\end{description} +% +%\begin{example}{A Basic Graph}{ex:basicplot} +%Suppose you have a file called "groupa.csv" that contains the +%following: +%\DTLnewdb{groupa}\relax +%\DTLnewrow{groupa}\relax +%\DTLnewdbentry{groupa}{Height}{1.55}\relax +%\DTLnewdbentry{groupa}{Weight}{45.4}\relax +%\DTLnewrow{groupa}\relax +%\DTLnewdbentry{groupa}{Height}{1.54}\relax +%\DTLnewdbentry{groupa}{Weight}{48.0}\relax +%\DTLnewrow{groupa}\relax +%\DTLnewdbentry{groupa}{Height}{1.56}\relax +%\DTLnewdbentry{groupa}{Weight}{58.0}\relax +%\DTLnewrow{groupa}\relax +%\DTLnewdbentry{groupa}{Height}{1.56}\relax +%\DTLnewdbentry{groupa}{Weight}{50.2}\relax +%\DTLnewrow{groupa}\relax +%\DTLnewdbentry{groupa}{Height}{1.57}\relax +%\DTLnewdbentry{groupa}{Weight}{46.0}\relax +%\DTLnewrow{groupa}\relax +%\DTLnewdbentry{groupa}{Height}{1.58}\relax +%\DTLnewdbentry{groupa}{Weight}{48.3}\relax +%\DTLnewrow{groupa}\relax +%\DTLnewdbentry{groupa}{Height}{1.59}\relax +%\DTLnewdbentry{groupa}{Weight}{56.5}\relax +%\DTLnewrow{groupa}\relax +%\DTLnewdbentry{groupa}{Height}{1.59}\relax +%\DTLnewdbentry{groupa}{Weight}{58.1}\relax +%\DTLnewrow{groupa}\relax +%\DTLnewdbentry{groupa}{Height}{1.60}\relax +%\DTLnewdbentry{groupa}{Weight}{60.9}\relax +%\DTLnewrow{groupa}\relax +%\DTLnewdbentry{groupa}{Height}{1.62}\relax +%\DTLnewdbentry{groupa}{Weight}{56.3}\relax +%\begin{ttfamily}\obeylines\setlength{\parindent}{0pt} +%Height,Weight +%\DTLforeach{groupa}{\x=Height,\y=Weight}{\x,\y +%}\end{ttfamily}\par\noindent +%First load this into a database called "groupa": +%\begin{verbatim} +%\DTLloaddb{groupa}{groupa.csv} +%\end{verbatim} +%The data can now be converted into a scatter plot as follows: +%\begin{verbatim} +%\begin{figure}[htbp] +%\centering +%\DTLplot{groupa}{x=Height,y=Weight} +%\caption{A scatter plot} +%\end{figure} +%\end{verbatim} +%This produces \autoref{fig:basicplot}. +% +%\begin{figure}[htbp] +%\centering +%\DTLplot{groupa}{x=Height,y=Weight} +%\caption{A scatter plot} +%\label{fig:basicplot} +%\end{figure} +% +%Alternatively, you can use the \setting{DTLplot}{style} setting +%to change it into a line plot: +%\begin{verbatim} +%\begin{figure}[htbp] +%\centering +%\DTLplot{groupa}{x=Height,y=Weight,style=lines} +%\caption{A line plot} +%\end{figure} +%\end{verbatim} +%This produces \autoref{fig:basiclineplot}. +% +%\begin{figure}[htbp] +%\centering +%\DTLplot{groupa}{x=Height,y=Weight,style=lines} +%\caption{A line plot} +%\label{fig:basiclineplot} +%\end{figure} +%\end{example} +% +%\begin{example}{Plotting Multiple Data Sets}{ex:2db} +%In this example, I shall use the database called "groupa" defined +%in \autoref{ex:basicplot}, and another database called "groupb" +%which is loaded from the file "groupb.csv" which contains the +%following: +%\DTLnewdb{groupb} +%\DTLnewrow{groupb}\relax +%\DTLnewdbentry{groupb}{Height}{1.54}\relax +%\DTLnewdbentry{groupb}{Weight}{48.4}\relax +%\DTLnewrow{groupb}\relax +%\DTLnewdbentry{groupb}{Height}{1.54}\relax +%\DTLnewdbentry{groupb}{Weight}{42.0}\relax +%\DTLnewrow{groupb}\relax +%\DTLnewdbentry{groupb}{Height}{1.55}\relax +%\DTLnewdbentry{groupb}{Weight}{64.0}\relax +%\DTLnewrow{groupb}\relax +%\DTLnewdbentry{groupb}{Height}{1.56}\relax +%\DTLnewdbentry{groupb}{Weight}{58.2}\relax +%\DTLnewrow{groupb}\relax +%\DTLnewdbentry{groupb}{Height}{1.56}\relax +%\DTLnewdbentry{groupb}{Weight}{49.0}\relax +%\DTLnewrow{groupb}\relax +%\DTLnewdbentry{groupb}{Height}{1.57}\relax +%\DTLnewdbentry{groupb}{Weight}{40.3}\relax +%\DTLnewrow{groupb}\relax +%\DTLnewdbentry{groupb}{Height}{1.58}\relax +%\DTLnewdbentry{groupb}{Weight}{51.5}\relax +%\DTLnewrow{groupb}\relax +%\DTLnewdbentry{groupb}{Height}{1.58}\relax +%\DTLnewdbentry{groupb}{Weight}{63.1}\relax +%\DTLnewrow{groupb}\relax +%\DTLnewdbentry{groupb}{Height}{1.59}\relax +%\DTLnewdbentry{groupb}{Weight}{74.9}\relax +%\DTLnewrow{groupb}\relax +%\DTLnewdbentry{groupb}{Height}{1.59}\relax +%\DTLnewdbentry{groupb}{Weight}{59.3}\relax +%\begin{ttfamily}\obeylines\setlength{\parindent}{0pt} +%Height,Weight +%\DTLforeach{groupb}{\x=Height,\y=Weight}{\x,\y +%}\end{ttfamily}\par\noindent +%First load this into a database called "groupb": +%\begin{verbatim} +%\DTLloaddb{groupb}{groupb.csv} +%\end{verbatim} +%I can now plot both groups in the same graph, but I want a smaller +%graph than \autoref{fig:basicplot} and \autoref{fig:basiclineplot}, +%so I am going to set the plot width and height to 3in: +%\begin{verbatim} +%\begin{figure}[htbp] +%\centering +%\DTLplot{groupa,groupb}{x=Height,y=Weight,width=3in,height=3in} +%\caption{A scatter plot} +%\end{figure} +%\end{verbatim} +%This produces \autoref{fig:2db}. +% +%\begin{figure}[htbp] +%\centering +%\DTLplot{groupa,groupb}{x=Height,y=Weight,width=3in,height=3in} +%\caption[A scatter plot (multiple datasets)]{A scatter plot} +%\label{fig:2db} +%\end{figure} +% +%Now let's add a legend using the \setting{DTLplot}{legend} setting, +%with the legend labels "Group A" and "Group B", +%and set the $x$ tick intervals using \setting{DTLplot}{xticpoints} +%setting. I am also going to set the $x$ axis label to +%"Height (m)" and the $y$ axis label to "Weight (kg)", and place +%a box around the plot. +%\begin{verbatim} +%\begin{figure}[htbp] +%\centering +%\DTLplot{groupa,groupb}{x=Height,y=Weight, +%width=3in,height=3in,legend,legendlabels={Group A,Group B}, +%xlabel={Height (m)},ylabel={Weight (kg)},box, +%xticpoints={1.54,1.55,1.56,1.57,1.58,1.59,1.60,1.61,1.62}} +%\caption{A scatter plot} +%\end{figure} +%\end{verbatim} +%This produces \autoref{fig:legend}. +% +%\begin{figure}[htbp] +%\centering +%\DTLplot{groupa,groupb}{x=Height,y=Weight,legend, +%width=3in,height=3in,legendlabels={Group A,Group B}, +%xlabel={Height (m)},ylabel={Weight (kg)},box, +%xticpoints={1.54,1.55,1.56,1.57,1.58,1.59,1.60,1.61,1.62}} +%\caption[A scatter plot (with a legend)]{A scatter plot} +%\label{fig:legend} +%\end{figure} +%\end{example} +% +%\subsection{Adding Information to the Plot} +% +%The \sty{datatool} package provides two hooks used at the beginning +%and end of the \env{tikzpicture} environment: +%\DescribeMacro{\DTLplotatbegintikz} +%\begin{definition} +%\cs{DTLplotatbegintikz} +%\end{definition}\noindent +%and +%\DescribeMacro{\DTLplotatendtikz} +%\begin{definition} +%\cs{DTLplotatendtikz} +%\end{definition} +%They are both defined to do nothing by default, but can be redefined +%to add commands to the image. The unit vectors are set prior to +%using these hooks, so you can use the same co-ordinates as those +%in the data sets. +% +%\DescribeMacro{\DTLaddtoplotlegend} +%\begin{definition} +%\cs{DTLaddtoplotlegend}\marg{marker}\marg{line style}\marg{text} +%\end{definition} +%This adds a new row to the plot legend where \meta{marker} is +%code to produce the marker, \meta{line style} is code to set +%the line style and \meta{text} is a textual label. You can +%use \cs{relax} to suppress the marker or line. For example: +%\begin{verbatim} +%\DTLaddtoplotlegend{\pgfuseplotmark{x}}{\relax}{Some Data} +%\end{verbatim} +%Note that the legend is plotted before \cs{DTLplotatendtikz}, +%so if you want to add information to the legend you will need +%to do the in \cs{DTLplotatstarttikz}. +% +%\begin{example}{Adding Information to a Plot}{ex:addtoplot} +%Returning to the plots created in \autoref{ex:2db}, suppose +%I now want to annotate the plot, say I want to draw your notice +%to a particular point, say the point (1.58,48.3), then I can +%redefine \cs{DTLplotatendtikz} to draw an annotated arrow to +%that point: +%\begin{verbatim} +%\renewcommand*{\DTLplotatendtikz}{% +%\draw[<-,line width=1pt] (1.58,48.3) -- (1.6,43) +% node[below]{interesting point}; +%} +%\end{verbatim} +%So \autoref{fig:legend} now looks like \autoref{fig:annote}. +%(Obviously, \cs{DTLplotatendtikz} needs to be redefined before +%using \cs{DTLplot}.) +% +%\begin{figure}[htbp] +%\renewcommand*{\DTLplotatendtikz}{% +%\draw[<-,line width=1pt] (1.58,48.3) -- (1.6,43) +% node[below]{interesting point}; +%} +%\centering +%\DTLplot{groupa,groupb}{x=Height,y=Weight,legend, +%width=3in,height=3in,legendlabels={Group A,Group B},box, +%xlabel={Height (m)},ylabel={Weight (kg)}, +%xticpoints={1.54,1.55,1.56,1.57,1.58,1.59,1.60,1.61,1.62}} +%\caption[A scatter plot (using the end plot hook to annotate the +%plot)]{A scatter plot} +% +%\label{fig:annote} +%\end{figure} +%\end{example} +% +%\subsection{Global Plot Settings} +% +%\subsubsection{Lengths} +%This section describes the lengths that govern the appearance of +%the plot created using \ics{DTLplot}. These lengths can be +%changed using \cs{setlength}. +% +%\DescribeMacro{\DTLplotwidth} +%\begin{definition} +%\cs{DTLplotwidth} +%\end{definition} +%This length governs the length of the $x$ axis. Note that the plot +%width does not include any outer tick marks or labels. The default +%value is 4in. +% +%\DescribeMacro{\DTLplotheight} +%\begin{definition} +%\cs{DTLplotheight} +%\end{definition} +%This length governs the length of the $y$ axis. Note that the plot +%height does not include any outer tick marks or labels. The default +%value is 4in +% +%\DescribeMacro{\DTLticklength} +%\begin{definition} +%\cs{DTLticklength} +%\end{definition} +%This governs the length of the tick marks. The default value is +%5pt. +% +%\DescribeMacro{\DTLminorticklength} +%\begin{definition} +%\cs{DTLminorticklength} +%\end{definition} +%This governs the length of the minor tick marks. The default value is +%2pt. +% +%\DescribeMacro{\DTLticklabeloffset} +%\begin{definition} +%\cs{DTLticklabeloffset} +%\end{definition} +%This governs the distance from the axis to the tick labels. The +%default value is 8pt. +% +%\DescribeMacro{\DTLmintickgap} +%\begin{definition} +%\cs{DTLmintickgap} +%\end{definition} +%This is the minimum distance allowed between tick marks. If the +%plot width or height is less than this distance there will only +%be tick marks at either end of the axis. The default value is +%20pt. +% +%\DescribeMacro{\DTLlegendxoffset} +%\begin{definition} +%\cs{DTLlegendxoffset} +%\end{definition} +%This is the horizontal distance from the border of the plot to the +%outer border of the legend. The default value is 10pt. +% +%\DescribeMacro{\DTLlegendyoffset} +%\begin{definition} +%\cs{DTLlegendyoffset} +%\end{definition} +%This is the vertical distance from the border of the plot to the +%outer border of the legend. The default value is 10pt. +% +%\subsubsection{Counters} +%These counters govern the appearance of plots +%created using \ics{DTLplot}. The value of the counters can be +%changed using \cs{setcounter}. +% +%\begin{definition} +%\counterfmt{DTLplotroundXvar} +%\end{definition} +%Unless you specify your own tick labels, the $x$ tick labels will +%be given by the tick points rounded to \meta{n} digits after the +%decimal point, where \meta{n} is the value of the counter +%\counterfmt{DTLplotroundXvar}. +% +%\begin{definition} +%\counterfmt{DTLplotroundYvar} +%\end{definition} +%Unless you specify your own tick labels, the $y$ tick labels will +%be given by the tick points rounded to \meta{n} digits after the +%decimal point, where \meta{n} is the value of the counter +%\counterfmt{DTLplotroundYvar}. +% +%\subsubsection{Macros} +%These macros govern the appearance of plots created using +%\ics{DTLplot}. They can be changed using \cs{renewcommand}. +% +%\DescribeMacro{\DTLplotmarks} +%\begin{definition} +%\cs{DTLplotmarks} +%\end{definition} +%This must be a comma separated list of \sty{pgf} code to create the +%plot marks. \ics{DTLplot} cycles through this list for each +%database listed. The \sty{pgf} package provides convenient commands +%for generating plots using \cs{pgfuseplotmark}. See the \sty{pgf} +%manual for more details. +% +%\DescribeMacro{\DTLplotmarkcolors} +%\begin{definition} +%\cs{DTLplotmarkcolors} +%\end{definition} +%This must be a comma separated list of defined colours to apply to the +%plot marks. \ics{DTLplot} cycles through this list for each database +%listed. If this macro is set to empty, the current colour will +%be used instead. +% +%\DescribeMacro{\DTLplotlines} +%\begin{definition} +%\cs{DTLplotlines} +%\end{definition} +%This must be a comma separated list of \sty{pgf} code to set the +%style of the plot lines. \ics{DTLplot} cycles through this list for +%each database listed. Dash patterns can be set using \cs{pgfsetdash}, +%see the \sty{pgf} manual for more details. If \cs{DTLplotlines} is +%set to empty the current line style will be used instead. +% +%\DescribeMacro{\DTLplotlinecolors} +%\begin{definition} +%\cs{DTLplotlinecolors} +%\end{definition} +%This must be a comma separated list of defined colours to apply to the +%plot lines. \cs{DTLplot} cycles through this list for each database +%listed. If this macro is set to empty, the current colour will +%be used instead. The default is the same as \cs{DTLplotmarkcolors}. +% +%\DescribeMacro{\DTLXAxisStyle} +%\begin{definition} +%\cs{DTLxaxisstyle} +%\end{definition} +%This governs the style of the $x$ axis. It is passed as the optional +%argument to the TikZ \cs{draw} command. By default it is just "-" +%which is a solid line style with no start or end arrows. The $x$ +%axis line starts from the bottom left corner of the plot and extends +%to the bottom right corner of the plot. So if you want the $x$ axis +%to have an arrow head at the right end, you can do: +%\begin{verbatim} +%\renewcommand*{\DTLXAxisStyle}{->} +%\end{verbatim} +% +%\DescribeMacro{\DTLYAxisStyle} +%\begin{definition} +%\cs{DTLyaxisstyle} +%\end{definition} +%This governs the style of the $y$ axis. It is analogous to +%\cs{DTLxaxisstyle} described above. +% +%\DescribeMacro{\DTLmajorgridstyle} +%\begin{definition} +%\cs{DTLmajorgridstyle} +%\end{definition} +%This specifies the format of the major grid lines. +%It may be set to any TikZ setting that you can pass to the +%optional argument of \cs{draw}. The default value is +%"color=gray,-" which indicates a grey solid line. +% +%\DescribeMacro{\DTLminorgridstyle} +%\begin{definition} +%\cs{DTLminorgridstyle} +%\end{definition} +%This specifies the format of the minor grid lines. +%It may be set to any TikZ setting that you can pass to the +%optional argument of \cs{draw}. The default value is +%"color=gray,loosely dotted" which indicates a grey dotted line. +% +%\DescribeMacro{\DTLformatlegend} +%\begin{definition} +%\cs{DTLformatlegend}\marg{legend} +%\end{definition} +%This formats the entire legend, which is passed as the argument. +%The default is to set the legend with +%a white background, a black frame. +% +%\subsection{Adding to a Plot Stream} +%\DescribeMacro{\DTLplotstream} +%\begin{definition} +%\cs{DTLplotstream}\oarg{condition}\marg{db name}\marg{x key}\marg{y key} +%\end{definition} +%This adds points to a stream from the database called \meta{db name} +%where the $x$ co-ordinates are given by the key \meta{x key} +%and the $y$ co-ordinates are given by the key \meta{y key}. +%(\ics{DTLconverttodecimal} is used to convert locale dependent +%values to a standard decimal that is recognised by the +%\sty{pgf} package.) +%The optional argument \meta{condition} is the same as that +%for \ics{DTLforeach}. +% +%\begin{example}{Adding to a Plot Stream}{ex:plotstream} +%Suppose you have a CSV file called "data.csv" containing the +%following: +%\begin{verbatim} +%x,y +%0,0 +%1,1 +%2,0.5 +%1.5,0.3 +%\end{verbatim} +%\DTLnewdb{data}\relax +%\DTLnewrow{data}\relax +%\DTLnewdbentry{data}{x}{0}\relax +%\DTLnewdbentry{data}{y}{0}\relax +%\DTLnewrow{data}\relax +%\DTLnewdbentry{data}{x}{1}\relax +%\DTLnewdbentry{data}{y}{1}\relax +%\DTLnewrow{data}\relax +%\DTLnewdbentry{data}{x}{2}\relax +%\DTLnewdbentry{data}{y}{0.5}\relax +%\DTLnewrow{data}\relax +%\DTLnewdbentry{data}{x}{1.5}\relax +%\DTLnewdbentry{data}{y}{0.3}\relax +%First load the file into a database called "data": +%\begin{verbatim} +%\DTLloaddb{data}{data.csv} +%\end{verbatim} +%Now create a figure containing this data: +%\begin{verbatim} +%\begin{figure}[tbhp] +%\centering +%\begin{tikzpicture} +%\pgfplothandlermark{\pgfuseplotmark{o}} +%\pgfplotstreamstart +%\DTLplotstream{data}{x}{y}% +%\pgfplotstreamend +%\pgfusepath{stroke} +%\end{tikzpicture} +%\caption{Adding to a plot stream} +%\end{figure} +%\end{verbatim} +%This produces \autoref{fig:plotstream}. +% +%\begin{figure}[tbhp] +%\centering +%\begin{tikzpicture} +%\pgfplothandlermark{\pgfuseplotmark{o}} +%\pgfplotstreamstart +%\DTLplotstream{data}{x}{y}% +%\pgfplotstreamend +%\pgfusepath{stroke} +%\end{tikzpicture} +%\caption{Adding to a plot stream} +%\label{fig:plotstream} +%\end{figure} +%\end{example} +% +%\begin{example}{Plotting Multiple Keys in the Same +%Database}{ex:multikey} +%Suppose I have conducted two time to growth experiments. For each +%experiment, I have recorded the log count at set times, and I have +%recorded this information in the same data file called, say, +%"growth.csv" which contains the following: +%\begin{verbatim} +%Time,Experiment 1,Experiment 2 +%0,3.73,3.6 +%23,3.67,3.7 +%60,4.9,3.8 +%\end{verbatim} +%\DTLnewdb{growth}\DTLnewrow{growth}\relax +%\DTLnewdbentry{growth}{Time}{0}\relax +%\DTLnewdbentry{growth}{Experiment 1}{3.73}\relax +%\DTLnewdbentry{growth}{Experiment 2}{3.6}\relax +%\DTLnewrow{growth}\relax +%\DTLnewdbentry{growth}{Time}{23}\relax +%\DTLnewdbentry{growth}{Experiment 1}{3.67}\relax +%\DTLnewdbentry{growth}{Experiment 2}{3.7}\relax +%\DTLnewrow{growth}\relax +%\DTLnewdbentry{growth}{Time}{60}\relax +%\DTLnewdbentry{growth}{Experiment 1}{4.9}\relax +%\DTLnewdbentry{growth}{Experiment 2}{3.8}\relax +%I can load the data into a database using: +%\begin{verbatim} +%\DTLloaddb{growth}{growth.csv} +%\end{verbatim} +%However, I'd like to plot both results on the same graph. Since they +%are contained in the same database, I can't use the method I used +%in \autoref{ex:2db}. Instead I can use a combination of +%\ics{DTLplot} and \ics{DTLplotstream}: +%\begin{verbatim} +%\begin{figure}[tbhp] +%\centering +% % computer bounds +%\DTLminforkeys{growth}{Time}{\minX} +%\DTLminforkeys{growth}{Experiment 1,Experiment 2}{\minY} +%\DTLmaxforkeys{growth}{Time}{\maxX} +%\DTLmaxforkeys{growth}{Experiment 1,Experiment 2}{\maxY} +% % round x tick labels +%\setcounter{DTLplotroundXvar}{0} +% % redefine \DTLplotatbegintikz to plot the data for Experiment 1 +%\renewcommand*{\DTLplotatbegintikz}{% +% % set plot mark +%\pgfplothandlermark{\color{green}\pgfuseplotmark{x}} +% % start plot stream +%\pgfplotstreamstart +% % add data from Experiment 1 to plot stream +%\DTLplotstream{growth}{Time}{Experiment 1}% +% % end plot stream +%\pgfplotstreamend +% % stroke path +%\pgfusepath{stroke} +% % add information to legend (no line is require so use \relax) +%\DTLaddtoplotlegend{\color{green}% +%\pgfuseplotmark{x}}{\relax}{Experiment 1} +%} +% % now plot the data for Experiment 2 +%\DTLplot{growth}{x=Time,y=Experiment 2,legend, +%width=3in,height=3in,bounds={\minX,\minY,\maxX,\maxY}, +%xlabel={Time},ylabel={Log Count}, +%legendlabels={Experiment 2}} +%\caption{Time to growth data} +%\end{figure} +%\end{verbatim} +%This produces \autoref{fig:multikey}. +%Notes: +%\begin{itemize} +%\item I redefined \ics{DTLplotatbegintikz} in order to add +%the new plot to the legend, since \ics{DTLplotatendtikz} is +%used after the legend is plotted. The $x$ and $y$ unit vectors +%are set before \ics{DTLplotatbegintikz} so I don't need to +%worry about the co-ordinates. +%\item I set the counter \counterfmt{DTLplotroundXvar} to zero +%otherwise the $x$ axis would have looked too cluttered. +%\item I have used \ics{DTLminforkeys} and \ics{DTLmaxforkeys} to +%determine the bounds since \ics{DTLplot} won't take the data +%for Experiment 1 into account when computing the bounds. +%\end{itemize} +% +%\begin{figure}[htbp] +%\DTLminforkeys{growth}{Time}{\minX} +%\DTLminforkeys{growth}{Experiment 1,Experiment 2}{\minY} +%\DTLmaxforkeys{growth}{Time}{\maxX} +%\DTLmaxforkeys{growth}{Experiment 1,Experiment 2}{\maxY} +%\setcounter{DTLplotroundXvar}{0} +%\renewcommand*{\DTLplotatbegintikz}{% +%\pgfplothandlermark{\color{green}\pgfuseplotmark{x}} +%\pgfplotstreamstart +%\DTLplotstream{growth}{Time}{Experiment 1}% +%\pgfplotstreamend +%\pgfusepath{stroke} +%\DTLaddtoplotlegend{\color{green}\pgfuseplotmark{x}}{\relax}{Experiment 1} +%} +%\centering +%\DTLplot{growth}{x=Time,y=Experiment 2,legend, +%width=3in,height=3in,bounds={\minX,\minY,\maxX,\maxY}, +%xlabel={Time},ylabel={Log Count}, +%legendlabels={Experiment 2}} +%\caption[Time to growth data (plotting from the same database using +%different keys)]{Time to growth data} +%\label{fig:multikey} +%\end{figure} +%\end{example} +% +%\section{Bar Charts (\texorpdfstring{\sty{databar}}{databar} +%package)} +% +%The \sty{databar} package provides commands for creating bar charts. +%It is not loaded by the \sty{datatool} package, so if you want to +%use it you will need to load it explicitly using +%"\usepackage{databar}". +% +%Bar charts can either be vertical or horizontal, the default is +%vertical. In this section the $x$ axis refers to the horizontal +%axis when plotting a vertical bar chart and to the vertical axis +%when plotting a horizontal bar chart. The $x$ axis units are in +%increments of one bar. The $y$ axis refers to the vertical axis +%when plotting a vertical bar chart and to the horizontal axis when +%plotting a horizontal bar chart. The $y$ axis uses the same +%co-ordinates as the data. The bars may have an upper and lower +%label. In a vertical bar chart, the lower label is placed below +%the $x$ axis and the upper label is placed above the top of the bar. +%In a horizontal bar chart, the lower label is placed to the left of +%the $x$ axis and the upper label is placed to the right of the +%end of the bar. (This is actually a misnomer as it is possible +%for the ``upper'' label to be below the ``lower'' label if a +%bar has a negative value, however the bars are considered to +%be anchored on the $x$ axis, and the other end of the bar is +%considered to be the ``upper'' end, regardless of its +%direction.) +% +%The \sty{databar} package options are as follows: +%\begin{description} +%\item[{\pkgopt[databar]{color}}] Created coloured bar charts +%(default.) +% +%\item[{\pkgopt[databar]{gray}}] Created grey scale bar charts. +% +%\item[{\pkgopt[databar]{vertical}}] Created vertical bar charts +%(default.) +% +%\item[{\pkgopt[databar]{horizontal}}] Created horizontal bar charts. +%\end{description} +% +% +%\DescribeMacro{\DTLbarchart} +%\begin{definition} +%\cs{DTLbarchart}\oarg{condition}\marg{db name}\marg{settings}\marg{values} +%\end{definition} +%\DescribeMacro{\DTLmultibarchart} +%\begin{definition} +%\cs{DTLmultibarchart}\oarg{condition}\marg{db name}\marg{settings}\marg{values} +%\end{definition} +%These commands both create a bar chart from the information in +%the database \meta{db name}, where \meta{condition} is the same +%as the optional argument for \ics{DTLforeach} described in +%\autoref{sec:dbforeach}, and \meta{values} is the same as the +%penultimate argument of \ics{DTLforeach}. The \meta{settings} +%argument is a \meta{setting}"="\meta{value} list of settings. The +%first command, \cs{DLTbarchart}, will draw a bar chart for a +%given column of data in the database, whereas the second command, +%\cs{DTLmultibarchart}, will draw a bar chart that is divided into +%groups of bars where each bar within a group represents data from +%several columns of a given row in the database. +% +%The \setting{DTLbarchart}{variable} setting is +%required for \cs{DTLbarchart} and the +%\setting{DTLmultibarchart}{variables}, the other settings are +%optional (though some may only be used for one of +%\cs{DTLbarchart} and \cs{DLTmultibarchart}), and are as follows: +% +%\begin{description} +%\item[\setting{DTLbarchart}{variable}] +%This specifies the control sequence to use that +%contains the value used to construct the bar chart. The control +%sequence must be one of the control sequences to appear in +%the assignment list \meta{values}. This setting is required +%for \cs{DTLbarchart}, and is unavailable for \cs{DTLmultibarchart}. +% +%\item[\setting{DTLmultibarchart}{variables}] +%This specifies a list of control sequences to use which +%contain the values used to construct the bar chart. Each control +%sequence must be one of the control sequences to appear in +%the assignment list \meta{values}. This setting is required +%for \cs{DTLmultibarchart}, and is unavailable for +%\cs{DTLbarchart}. +% +%\item[\setting{DTLbarchart,DTLmultibarchart}{max}] +%This specifies the maximum value on the $y$ axis. (This should +%be a standard decimal value.) +% +%\item[\setting{DTLbarchart,DTLmultibarchart}{length}] +%This specifies the overall length of the $y$ axis, and must +%be a dimension. +% +%\item[\setting{DTLbarchart,DTLmultibarchart}{maxdepth}] +%This must be a zero or negative number. It specifies the maximum +%depth of the $y$ axis. (This should be a standard decimal value.) +% +%\item[\setting{DTLbarchart,DTLmultibarchart}{axes}] +%This setting specifies which axes to display. This may take one +%of the following values: "both", "x", "y" or "none". +% +%\item[\setting{DTLbarchart,DTLmultibarchart}{barlabel}] +%This setting specifies the lower bar label. When used with +%\cs{DTLmultibarchart} it indicates the group label. +% +%\item[\setting{DTLmultibarchart}{multibarlabels}] +%This setting should contain a comma separated list of labels +%for each bar within a group for \cs{DTLmultibarchart}. This +%setting is not available for \cs{DTLbarchart}. +% +%\item[\setting{DTLbarchart}{upperbarlabel}] +%This setting specifies the upper bar label. This setting +%is not available for \cs{DTLmultibarchart}. +% +%\item[\setting{DTLmultibarchart}{uppermultibarlabels}] +%This setting must be a comma separated list of upper bar +%labels for each bar within a group. This setting is not +%available for \cs{DTLbarchart}. +% +%\item[\setting{DTLbarchart,DTLmultibarchart}{yticpoints}] +%This must be a comma separated list of tick locations for the +%$y$ axis. (These should be standard decimal values.) +%This setting overrides \setting{DTLbarchart}{yticgap}. +% +%\item[\setting{DTLbarchart,DTLmultibarchart}{yticgap}] +%This specifies the gap between the $y$ tick marks. (This should +%be a standard decimal value.) +% +%\item[\setting{DTLbarchart,DTLmultibarchart}{yticlabels}] +%This must be a comma separated list of tick labels for the +%$y$ axis. +% +%\item[\setting{DTLbarchart,DTLmultibarchart}{ylabel}] +%This specifies the label for the $y$ axis. +% +%\item[\setting{DTLmultibarchart}{groupgap}] This specifies +%the gap between groups when using \cs{DTLmultibarchart}. +%This value is given as a multiple of the bar width. The +%default value is 1, which indicates a gap of one bar width. +%This setting is not available for \cs{DTLbarchart}. +% +%\item[\setting{DTLbarchart,DTLmultibarchart}{verticalbars}] +%This is a boolean setting, so it can only take the values +%"true" (do a vertical bar chart) or "false" (do a horizontal +%bar chart.) If the value is omitted, "true" is assumed. +%\end{description} +% +%\begin{example}{A Basic Bar Chart}{ex:barchart} +%Recall \autoref{ex:piechart} defined a database called "fruit". +%This example will be using that database to plot a bar chart. +%The following plots a basic vertical bar chart: +%\begin{verbatim} +%\begin{figure}[htbp] +%\centering +%\DTLbarchart{variable=\theQuantity}{fruit}{\theQuantity=Quantity} +%\caption{A basic bar chart} +%\end{figure} +%\end{verbatim} +%This produces \autoref{fig:barchart}. +% +%\begin{figure}[htbp] +%\centering +%\DTLbarchart{variable=\theQuantity}{fruit}{\theQuantity=Quantity} +%\caption{A basic bar chart} +%\label{fig:barchart} +%\end{figure} +%\end{example} +% +%\subsection{Changing the Appearance of a Bar Chart} +% +%\DescribeMacro{\DTLbarchartlength} +%\begin{definition} +%\cs{DTLbarchartlength} +%\end{definition} +%This specifies the total length of the $y$ axis. You must use +%\cs{setlength} to change this value. The default value is 3in. +% +%\DescribeMacro{\DTLbarwidth} +%\begin{definition} +%\cs{DTLbarwidth} +%\end{definition} +%This specifies the width of each bar. You must use \cs{setlength} +%to change this value. The default value is 1cm. +% +%\DescribeMacro{\DTLbarlabeloffset} +%\begin{definition} +%\cs{DTLbarlabeloffset} +%\end{definition} +%This specifies the distance from the $x$ axis to the lower bar label. +%You must use \cs{setlength} to change this value. The default value +%is 10pt. +% +%\begin{definition} +%\counterfmt{DTLbarroundvar} +%\end{definition} +%The $y$ tick labels are rounded to \meta{n} digits after the +%decimal point, where \meta{n} is given by the value of the +%counter \counterfmt{DTLbarroundvar}. You must use \cs{setcounter} +%to change this value. +% +%\DescribeMacro{\DTLsetbarcolor} +%\begin{definition} +%\cs{DTLsetbarcolor}\marg{n}\marg{color} +%\end{definition} +%This sets the \meta{n}th bar colour to \meta{color}. +%Only the first eight bars have a colour defined by default. If you +%need more than eight bars, you will need to define more bar colours. +% +%\DescribeMacro{\DTLdobarcolor} +%\begin{definition} +%\cs{DTLdobarcolor}\marg{n} +%\end{definition} +%This sets the current colour to the colour of the \meta{n}th bar. +% +%\DescribeMacro{\DTLbaroutlinecolor} +%\begin{definition} +%\cs{DTLbaroutlinecolor} +%\end{definition} +%This macro contains the colour of the bar outlines. This defaults +%to "black". +% +%\DescribeMacro{\DTLbaroutlinewidth} +%\begin{definition} +%\cs{DTLbaroutlinewidth} +%\end{definition} +%This length specifies the line width for the bar outlines. If it +%is 0pt, the outline is not drawn. The default value is 0pt. +% +%\DescribeMacro{\DTLbaratbegintikz} +%\begin{definition} +%\cs{DTLbaratbegintikz} +%\end{definition} +%This specifies any additional commands to add to the start of +%the plot. It defaults to nothing, and is called after the +%unit vectors are set. +% +%\DescribeMacro{\DTLbaratendtikz} +%\begin{definition} +%\cs{DTLbaratendtikz} +%\end{definition} +%This specifies any additional commands to add to the end of +%the plot. It defaults to nothing. +% +%\DescribeMacro{\ifDTLverticalbars} +%\begin{definition} +%\cs{ifDTLverticalbars} +%\end{definition} +%This conditional governs whether the chart uses vertical or +%horizontal bars. +% +%\DescribeMacro{\DTLbarXlabelalign} +%\begin{definition} +%\cs{DTLbarXlabelalign} +%\end{definition} +%This specifies the text alignment of the lower bar labels. This +%defaults to "left,rotate=-90" if you use the \pkgopt[databar]{vertical} +%package option or the \setting{DTLbarchart}{verticalbars} setting, +%and defaults to "right" if you use the \pkgopt[databar]{horizontal} +%package option or the \setting{DTLbarchart}{verticalbars}"=false" +%setting. +% +%\DescribeMacro{\DTLbarYticklabelalign} +%\begin{definition} +%\cs{DTLbarYlabelalign} +%\end{definition} +%This specifies the text alignment of the $y$ axis labels. This +%defaults to "right" for vertical bar charts and "center" for +%horizontal bar charts. +% +%\DescribeMacro{\DTLbardisplayYticklabel} +%\begin{definition} +%\cs{DTLbardisplayYticklabel}\marg{text} +%\end{definition} +%This specifies how to display the $y$ tick label. The argument +%is the tick label. +% +%\DescribeMacro{\DTLdisplaylowerbarlabel} +%\begin{definition} +%\cs{DTLdisplaylowerbarlabel}\marg{text} +%\end{definition} +%This specifies how to display the lower bar label for +%\cs{DTLbarchart} and the lower bar group label for +%\cs{DTLmultibarchart}. The argument is the label. +% +%\DescribeMacro{\DTLdisplaylowermultibarlabel} +%\begin{definition} +%\cs{DTLdisplaylowermultibarlabel}\marg{text} +%\end{definition} +%This specifies how to display the lower bar label for +%\cs{DTLmultibarchart}. The argument is the label. This +%command is ignored by \cs{DTLbarchart}. +% +%\DescribeMacro{\DTLdisplayupperbarlabel} +%\begin{definition} +%\cs{DTLdisplayupperbarlabel}\marg{text} +%\end{definition} +%This specifies how to display the upper bar label for +%\cs{DTLbarchart} and the upper bar group label for +%\cs{DTLmultibarchart}. The argument is the label. +% +%\DescribeMacro{\DTLdisplayuppermultibarlabel} +%\begin{definition} +%\cs{DTLdisplayuppermultibarlabel}\marg{text} +%\end{definition} +%This specifies how to display the upper bar label for +%\cs{DTLmultibarchart}. The argument is the label. This +%command is ignored by \cs{DTLbarchart}. +% +%\begin{example}{An Labelled Bar Chart}{ex:annotebarchart} +%This example extends \autoref{ex:barchart} so that the chart is +%a bit more informative (which is after all the whole point of +%a chart.) This chart now has a label below each bar, as well +%as a label above the bar. The lower label uses the value of the +%"Name" key, and the upper label uses the quantity. I have also +%set the outline width so each bar has a border. +%\begin{verbatim} +%\begin{figure}[htbp] +%\setlength{\DTLbaroutlinewidth}{1pt} +%\centering +%\DTLbarchart{variable=\theQuantity,barlabel=\theName,% +%upperbarlabel=\theQuantity}{fruit}{% +%\theQuantity=Quantity,\theName=Name} +%\caption{A bar chart} +%\end{figure} +%\end{verbatim} +%This produces \autoref{fig:annotebarchart}. +% +%\begin{figure}[htbp] +%\centering +%\setlength{\DTLbaroutlinewidth}{1pt} +%\DTLbarchart{variable=\theQuantity,barlabel=\theName, +%upperbarlabel=\theQuantity}{fruit}{% +%\theQuantity=Quantity,\theName=Name} +%\caption[A bar chart (labelled)]{A bar chart} +%\label{fig:annotebarchart} +%\end{figure} +%\end{example} +% +%\begin{example}{Profit/Loss Bar Chart}{ex:profit} +%Suppose I have a file called "profits.csv" that looks like: +%\DTLnewdb{profits} +%\DTLnewrow{profits} +%\DTLnewdbentry{profits}{Year}{2000}\relax +%\DTLnewdbentry{profits}{Profit}{\protect\pounds2,525}\relax +%\DTLnewrow{profits} +%\DTLnewdbentry{profits}{Year}{2001}\relax +%\DTLnewdbentry{profits}{Profit}{\protect\pounds3,752}\relax +%\DTLnewrow{profits} +%\DTLnewdbentry{profits}{Year}{2002}\relax +%\DTLnewdbentry{profits}{Profit}{-\protect\pounds1,520}\relax +%\DTLnewrow{profits} +%\DTLnewdbentry{profits}{Year}{2003}\relax +%\DTLnewdbentry{profits}{Profit}{\protect\pounds1,270}\relax +%\begin{verbatim} +%Year,Profit +%2000,\pounds2,535 +%2001,\pounds3,752 +%2002,-\pounds1,520 +%2003,\pounds1,270 +%\end{verbatim} +%First I can load this file into a database called "profits": +%\begin{verbatim} +%\DTLloaddb{profits}{profits.csv} +%\end{verbatim} +%Now I can plot the data as a bar chart: +%\begin{verbatim} +%\begin{figure}[htbp] +%\centering +% % Set the width of each bar to 10pt +%\setlength{\DTLbarwidth}{10pt} +% % Set the outline width to 1pt +%\setlength{\DTLbaroutlinewidth}{1pt} +% % Round the $y$ tick labels to integers +%\setcounter{DTLbarroundvar}{0} +% % Adjust the tick label offset +%\setlength{\DTLticklabeloffset}{20pt} +% % Change the y tick label alignment +%\renewcommand*{\DTLbarYticklabelalign}{left} +% % Rotate the y tick labels +%\renewcommand*{\DTLbardisplayYticklabel}[1]{\rotatebox{-45}{#1}} +% % Set the bar colours depending on the value of \theProfit +%\DTLforeach{profits}{\theProfit=Profit}{% +%\ifthenelse{\DTLislt{\theProfit}{0}} +%{\DTLsetbarcolor{\DTLcurrentindex}{red}} +%{\DTLsetbarcolor{\DTLcurrentindex}{blue}}} +% % Do the bar chart +%\DTLbarchart{variable=\theProfit,upperbarlabel=\theYear, +%ylabel={Profit/Loss (\pounds)},verticalbars=false, +%maxdepth=-2000,max=4000}{profits} +%{\theProfit=Profit,\theYear=Year} +%\caption{Profits for 2000--2003} +%\end{figure} +%\end{verbatim} +%This produces \autoref{fig:profits}. Notes: +%\begin{enumerate} +%\item This example uses \cs{rotatebox}, so the \sty{graphics} +%or \sty{graphicx} package is required. +%\item The $y$ tick labels are too wide to fit horizontally +%so they have been rotated to avoid overlapping with their +%neighbour. +%\item Rotating the $y$ tick labels puts them too close to +%the $y$ axis, so \ics{DTLticklabeloffset} is made larger to +%compensate. +%\item Remember not to use \cs{year} as an assignment command +%as this command already exists! +%\item Before the bar chart is created I have iterated through +%the database, setting the bar colour to red or blue +%depending on the value of \cs{theProfit}. +%\end{enumerate} +% +%Both \cs{DTLbarchart} and \cs{DTLmultibarchart} set the following +%macros, which may be used in \cs{DTLbaratbegintikz} and +%\cs{DTLbaratendtikz}: +%\DescribeMacro{\DTLbarchartwidth} +%\begin{definition} +%\cs{DTLbarchartwidth} +%\end{definition} +%This is the overall width of the bar chart. In the case of +%\cs{DTLbarchart} this is just the number of bars. In the case +%of \cs{DTLmultibarchart} it is computed as: +%\begin{displaymath} +%m \times n + (m-1)\times g +%\end{displaymath} +%where $m$ is the number of bar groups (i.e.\ the number of rows +%of data), $n$ is the number of bars within a group (i.e.\ +%the number of commands listed in the +%\setting{DTLmultibarchart}{variables}) setting and $g$ is the +%group gap (as specified by the \setting{DTLmultibarchart}{groupgap} setting.) +% +%\DescribeMacro{\DTLnegextent} +%\begin{definition} +%\cs{DTLnegextent} +%\end{definition} +%This is set to the negative extent of the bar chart. (This value +%may either be zero or negative, and corresponds to the +%\setting{DTLbarchart,DTLmultibarchart}{maxdepth} setting.) +% +%\DescribeMacro{\DTLbarmax} +%\begin{definition} +%\cs{DTLbarmax} +%\end{definition} +%This is set to the maximum extent of the bar chart. (This value +%corresponds to the +%\setting{DTLbarchart,DTLmultibarchart}{max} setting.) +% +%\begin{figure}[htbp] +%\centering +%\setlength{\DTLbarwidth}{10pt} +%\setlength{\DTLbaroutlinewidth}{1pt} +%\setlength{\DTLticklabeloffset}{20pt} +%\setcounter{DTLbarroundvar}{0} +%\renewcommand*{\DTLbarYticklabelalign}{left} +%\renewcommand*{\DTLbardisplayYticklabel}[1]{\rotatebox{-45}{#1}} +%\DTLforeach{profits}{\theProfit=Profit}{\relax +%\ifthenelse{\DTLislt{\theProfit}{0}} +%{\DTLsetbarcolor{\DTLcurrentindex}{red}} +%{\DTLsetbarcolor{\DTLcurrentindex}{blue}}} +%\DTLbarchart{variable=\theProfit,upperbarlabel=\theYear, +%ylabel={Profit/Loss (\pounds)},verticalbars=false, +%maxdepth=-2000,max=4000 +%}{profits} +%{\theProfit=Profit,\theYear=Year} +%\caption[Profits for 2000--2003 (a horizontal bar chart)]{Profits for +%2000--2003} +%\label{fig:profits} +%\end{figure} +% +%\end{example} +% +%\begin{example}{A Multi-Bar Chart}{ex:multibar} +%This example uses the "marks" database described in +%\autoref{ex:editdb}. +%Recall that this database stores student marks for three +%assignments. The keys for the assignment marks are +%\texttt{Assignment 1}, \texttt{Assignment 2} and +%\texttt{Assignment 3}, respectively. I can convert this +%data into a bar chart using the following: +%\begin{verbatim} +%\begin{figure}[htbp] +%\centering +%\DTLmultibarchart{variables={\assignI,\assignII,\assignIII}, +%barwidth=10pt,uppermultibarlabels={\assignI,\assignII,\assignIII}, +%barlabel={\firstname\ \surname}}{marks}{% +%\surname=Surname,\firstname=FirstName,\assignI=Assignment 1,% +%\assignII=Assignment 2,\assignIII=Assignment 3} +%\caption{Student marks} +%\end{figure} +%\end{verbatim} +%This produces \autoref{fig:multibar}. Notes: +%\begin{enumerate} +%\item I used "variables={\assignI,\assignII,\assignIII}" to +%set the variable to use for each bar within a group. This means +%that there will be three bars in each group. +%\item I have set the bar width to 10pt, otherwise the chart +%will be too wide. +%\item I used "uppermultibarlabels={\assignI,\assignII,\assignIII}" +%to set the upper labels for each bar within a group. This +%will print the assignment mark above the relevant bar. +%\item I used "barlabel={\firstname\ \surname}" to place the +%student's name below the group corresponding to that student. +%\end{enumerate} +% +%\begin{figure}[htbp] +%\centering +%\DTLmultibarchart{variables={\assignI,\assignII,\assignIII}, +%barwidth=10pt,uppermultibarlabels={\assignI,\assignII,\assignIII}, +%barlabel={\firstname\ \surname}}{marks} +%{\surname=Surname,\firstname=FirstName,\assignI=Assignment 1,\assignII=Assignment 2,\assignIII=Assignment 3} +%\caption[Student marks (a multi-bar chart)]{Student +%marks}\label{fig:multibar} +%\end{figure} +% +%Recall that \autoref{ex:editdb} computed the average score over +%for each student, and saved it with the key "Average". This +%information can be added to the bar chart. It might also be +%useful to compute the average over all students and add this +%information to the chart. This is done as follows: +%\begin{verbatim} +% \begin{figure}[htbp] +% \centering +% % compute the overall mean +% \DTLmeanforkeys{marks}{Average}{\overallmean} +% % round it to 2 decimal places +% \DTLround{\overallmean}{\overallmean}{2} +% % draw a grey dotted line indicating the overall mean +% % covering the entire width of the bar chart +% \renewcommand*{\DTLbaratendtikz}{% +% \draw[lightgray,loosely dotted] (0,\overallmean) -- +% (\DTLbarchartwidth,\overallmean) +% node[right,black]{Average (\overallmean)};} +% % Set the lower bar labels to draw a brace across the current +% % group, along with the student's name and average score +% \renewcommand*{\DTLdisplaylowerbarlabel}[1]{% +% \tikz[baseline=(current bounding box.center)]{ +% \draw[snake=brace,rotate=-90](0,0) -- (\DTLbargroupwidth,0);} +% \DTLround{\theMean}{\theMean}{2}% +% \shortstack{#1\\(Average: \theMean)}} +% % draw the bar chart +% \DTLmultibarchart{variables={\assignI,\assignII,\assignIII}, +% barwidth=10pt,uppermultibarlabels={\assignI,\assignII,\assignIII}, +% barlabel={\firstname\ \surname}}{marks} +% {\surname=Surname,\firstname=FirstName,\assignI=Assignment 1,% +% \assignII=Assignment 2,\assignIII=Assignment 3,\theMean=Average} +% \caption{Student marks} +% \end{figure} +%\end{verbatim} +%which produces \autoref{fig:multibarmean}. Notes: +%\begin{enumerate} +%\item I've used the TikZ snake library to create a brace, so +%I need to put +%\begin{verbatim} +%\usetikzlibrary{snakes} +%\end{verbatim} +%in the preamble. See the \sty{pgf} manual for more details on +%how to use this library. +% +%\item I used \ics{DTLbargroupwidth} to indicate the width of +%each bar group. +% +%\item I used \ics{DTLbarchartwidth} to indicate the width of the +%entire bar chart +%\end{enumerate} +% +%\begin{figure}[htbp] +%\centering +%\DTLmeanforkeys{marks}{Average}{\overallmean} +%\DTLround{\overallmean}{\overallmean}{2} +%\renewcommand*{\DTLbaratendtikz}{\draw[lightgray,loosely dotted] (0,\overallmean) -- +%(\DTLbarchartwidth,\overallmean) node[right,black]{Average (\overallmean)};} +%\renewcommand*{\DTLdisplaylowerbarlabel}[1]{\relax +%\tikz[baseline=(current bounding box.center)]{ +%\draw[snake=brace,rotate=-90](0,0) -- (\DTLbargroupwidth,0);} +%\DTLround{\theMean}{\theMean}{2}\relax +%\shortstack{#1\\(Average: \theMean)}} +%\DTLmultibarchart{variables={\assignI,\assignII,\assignIII}, +%barwidth=10pt,uppermultibarlabels={\assignI,\assignII,\assignIII}, +%barlabel={\firstname\ \surname}}{marks} +%{\surname=Surname,\firstname=FirstName,\assignI=Assignment 1,\assignII=Assignment 2,\assignIII=Assignment 3,\theMean=Average} +%\caption[Student marks (annotating a bar chart)]{Student marks} +%\label{fig:multibarmean} +%\end{figure} +%\end{example} +% +%\section{Converting a \texorpdfstring{\BibTeX}{BibTeX} database +%into a datatool database +%(\texorpdfstring{\sty{databib}}{databib} package)} +%\label{sec:databib} +% +%The \sty{databib} package provides the means of converting a \BibTeX\ +%database into a \sty{datatool} database. The database can then be +%sorted using \cs{DTLsort}, described in \autoref{sec:sort}. +%For example, you may want to sort the bibliography in +%reverse chronological order. Once you have sorted the bibliography, +%you can display it using \cs{DTLbibliography}, described in +%\autoref{sec:thebib}, or you can iterate through the database +%using \cs{DTLforeachbib}, described in \autoref{sec:foreachbib}. +% +%Note that the \sty{databib} +%package is not automatically loaded by \sty{datatool}, so if +%you want to use it, you must load it using +%"\usepackage{databib}". +% +%\importantpar The purpose of this package is to provide a means for +%authors to format their own bibliography style where there is no +%bibliography style file available that produces the desired results. +%The \cs{DTLsort} macro uses a much less efficient sorting algorithm +%than \BibTeX, and loading the bibliography as a \sty{datatool} +%database is much slower than loading a standard \ext{bbl} file. If +%you have a large database, and you are worried that \LaTeX\ may have +%become stuck, try using the \pkgopt{verbose} option to \sty{datatool} +%or use the command \cs{dtlverbosetrue}. This will print informative +%messages to the console and transcript file, to let you know what's +%going on. +% +%\subsection{\texorpdfstring{\BibTeX}{BibTeX}: An Overview} +%\label{sec:bibtex} +%This document assumes that you have at least some passing +%familiarity with \BibTeX, but here follows a brief refresher. +% +%\BibTeX\ is an external application used in conjunction with \LaTeX. +%When you run \BibTeX, you need to specify the name of the document's +%auxiliary file (without the \ext{aux} extension.) \BibTeX\ then reads +%this file and looks for the commands \cs{bibstyle} (which indicates +%which bibliography style (\ext{bst}) file to load), \cs{bibdata} +%(which indicates which bibliography database (\ext{bib}) files to +%load) and \cs{citation} (produced by \cs{cite} and \cs{nocite}, which +%indicates which entries should be included in the bibliography.) +%\BibTeX\ then creates a file with the extension \ext{bbl} which +%contains the bibliography, formatted according to the layout defined +%in the bibliography style file. +% +%In general, given a document called, say, \texttt{mydoc.tex}, you +%will have to perform the following steps to ensure that the +%bibliography and all citations are up-to-date: +%\begin{enumerate} +%\item +%\begin{verbatim} +%latex mydoc +%\end{verbatim} +%This writes the citation information to the auxiliary file. +%The bibliography currently doesn't exists, so it isn't displayed. +%Citations will appear in the document as ?? since the internal +%cross-references don't exist yet. +% +%\item +%\begin{verbatim} +%bibtex mydoc +%\end{verbatim} +%This reads the auxiliary file, and creates a file with the extension +%\ext{bbl} which typically contains the typeset bibliography. +% +%\item +%\begin{verbatim} +%latex mydoc +%\end{verbatim} +%Now that the \ext{bbl} file exists, the bibliography can be input +%into the document. The internal cross-referencing information for the +%bibliography can now be written to the auxiliary file. +% +%\item +%\begin{verbatim} +%latex mydoc +%\end{verbatim} +%The cross-referencing information can be read from the auxiliary +%file. +%\end{enumerate} +% +%\subsubsection{\texorpdfstring{\BibTeX}{BibTeX} database} +% +%The bibliographic data required by \BibTeX\ must be stored in +%a file with the extension \ext{bib}, where each entry is stored +%in the form:\par\vskip\baselineskip\noindent +%{\obeylines +%\noindent\texttt{@}\meta{entry\_type}\verb|{|\meta{cite\_key}\texttt, +% \meta{field\_name} \texttt{=} \char`\"\meta{value}\char`\"\texttt, +% \mbox{}\vdots +% \meta{field\_name} \texttt{=} \char`\"\meta{value}\char`\" +%\noindent\verb|}| +%} +%\par\vskip\baselineskip\noindent +%Note that curly braces "{" and "}" may be used instead of \verb|"| +%and \verb|"|. +% +%The entry type, given by \meta{entry\_type} above, indicates +%the type of document. This may be one of: "article", "book", +%"booklet", "inbook", "incollection", "inproceedings"\footnote +%{Note that \texttt{conference} is a synonym for \texttt{inproceedings}.}, +%"manual", +%"mastersthesis", "misc", "phdthesis", "proceedings", \linebreak +%"techreport" or "unpublished". +% +%The \meta{cite\_key} above is a unique label identifying this +%entry, and is the label used in the argument of \cs{cite} or +%\cs{nocite}. The available fields depends on the entry type, for +%example, the field "journal" is required for the "article" entry +%type, but is ignored for the "inproceedings" entry type. The standard +%fields are: "address", "author", "booktitle", "chapter", "edition", +%"editor", "howpublished", "institution", "journal", "key", "month", +%"note", "number", "organization", "pages", "publisher", "school", +%"series", "title", "type", "volume" and "year". +% +%Author and editor names must be entered in one of the following +%ways: +%\begin{enumerate} +%\item \meta{First names} \meta{von part} \meta{Surname}, \meta{Jr part} +% +%The \meta{von part} is optional and is identified by the name(s) +%starting with lowercase letters. The final comma followed by +%\meta{Jr part} is also optional. Examples: +%\begin{verbatim} +%author = "Henry James de Vere" +%\end{verbatim} +%In the above, the first names are Henry James, the ``von part'' is +%de and the surname is Vere. There is no ``junior part''. +%\begin{verbatim} +%author = "Mary-Jane Brown, Jr" +%\end{verbatim} +%In the above, the first name is Mary-Jane, there is no von part, +%the surname is Brown and the junior part is Jr. +%\begin{verbatim} +%author = "Peter {Murphy Allen}" +%\end{verbatim} +%In the above, the first name is Peter, and the surname is Murphy +%Allen. Note that in this case, the surname must be grouped, otherwise +%Murphy would be considered part of the forename. +%\begin{verbatim} +%author = "Maria Eliza {\uppercase{d}e La} Cruz" +%\end{verbatim} +%In the above, the first name is Maria Eliza, the von part is +%De La, and the surname is Cruz. In this case, the von part starts +%with an uppercase letter, but specifying +%\begin{verbatim} +%author = "Maria Eliza De La Cruz" +%\end{verbatim} +%would make \BibTeX\ incorrectly classify ``Maria Eliza De La'' as +%the first names, and the von part would be empty. Since \BibTeX\ +%doesn't understand \LaTeX\ commands, using "{\uppercase{d}e La}" +%will trick \BibTeX\ into thinking that it starts with a lower +%case letter. +% +%\item \meta{von part} \meta{Surname}, \meta{Forenames} +% +%Again the \meta{von part} is optional, and is determined by the +%case of the first letter. For example: +%\begin{verbatim} +%author = "de Vere, Henry James" +%\end{verbatim} +%\end{enumerate} +% +%Multiple authors or editors should be separated by the key word +%"and", for example: +%\begin{verbatim} +%author = "Michel Goossens and Frank Mittlebach and Alexander Samarin" +%\end{verbatim} +% +%Below is an example of a book entry: +%\begin{verbatim} +%@book{latexcomp, +% title = "The \LaTeX\ Companion", +% author = "Michel Goossens and Frank Mittlebach and +% Alexander Samarin", +% publisher = "Addison-Wesley", +% year = 1994 +%} +%\end{verbatim} +%Note that numbers may be entered without delimiters, as in "year = 1994". +%There are also some predefined strings, including those for the month +%names. You should always use these strings instead of the actual +%month name, as the way the month name is displayed depends on the +%bibliography style. For example: +%\begin{verbatim} +%@article{Cawley2007b, +%author = "Gavin C. Cawley and Nicola L. C. Talbot", +%title = "Preventing over-fitting in model selection via {B}ayesian +% regularisation of the hyper-parameters", +%journal = "Journal of Machine Learning Research", +%volume = 8, +%pages = "841--861", +%month = APR, +%year = 2007 +%} +%\end{verbatim} +% +%You can concatenate strings using the "#" character, for example: +%\begin{verbatim} +%month = JUL # "~31~--~" # AUG # "~4", +%\end{verbatim} +%Depending on the bibliography style, this may be displayed as: +%July~31~--~August~4, or it may be displayed as: +%Jul~31~--~Aug~4. For further information, see~\cite{Goossens}. +% +%\subsection{Loading a \texorpdfstring{\sty{databib}}{databib} +%database} +%\label{sec:loadbbl} +% +%The \sty{databib} package always requires the \texttt{databib.bst} +%bibliography style file (which is supplied with this bundle.) +%You need to use \cs{cite} or \cs{nocite} as usual. If you want to +%add all entries in the \ext{bib} file to the \sty{datatool} database, +%you can use "\nocite{*}". +% +%\DescribeMacro{\DTLloadbbl} +%\begin{definition} +%\cs{DTLloadbbl}\oarg{bbl name}\marg{db name}\marg{bib list} +%\end{definition} +%This command performs several functions: +% +%\begin{enumerate} +%\item it writes the following line in the auxiliary file: +%\begin{verbatim} +%\bibstyle{databib} +%\end{verbatim} +%which tells \BibTeX\ to use the \texttt{databib.bst} +%\BibTeX\ style file, +% +%\item it writes \cs{bibdata}\marg{bib list} to the +%auxiliary file, which tells \BibTeX\ which \ext{bib} files to use, +% +%\item it creates a \sty{datatool} database called \meta{db name}, +% +%\item it loads the file \meta{bbl name} if it exists. (The value +%defaults to \cs{jobname}".bbl", which is the usual name for +%a \ext{bbl} file.) If the \ext{bbl} file doesn't exist, the +%database \meta{db name} will remain empty. +%\end{enumerate} +% +%You then need to run your document through \LaTeX\ (or PDF\LaTeX) +%and then run \BibTeX\ on the auxiliary file, as described in +%\autoref{sec:bibtex}. This will create a \ext{bbl} file which +%contains all the commands required to add the bibliography information +%to the \sty{datatool} database called \meta{db name}. The next +%time you \LaTeX\ your document, this file will be read, and the +%information will be added to \meta{db name}. +% +%\importantpar Note that +%\cs{DTLloaddb} doesn't generate any text. Once you have loaded +%the data, you can display the bibliography uses +%\cs{DTLbibliography} (described below) or you can iterate +%through it using \cs{DTLforeachbibentry} described in +%\autoref{sec:foreachbib}. +% +%Note that the \texttt{databib.bst} \BibTeX\ style file provides +%the following additional fields: "isbn", "doi", "pubmed", "url" +%and "abstract". +%However these fields are ignored by the three predefined +%\sty{databib} styles ("plain", "abbrv" and "alpha".) If you +%want these fields to be displayed in the bibliography you will +%need to modify the bibliography style (see \autoref{sec:modbibstyle}.) +% +%\subsection{Displaying a \texorpdfstring{\sty{databib}}{databib} +%database} +%\label{sec:thebib} +% +%A \sty{databib} database which has been loaded using +%\cs{DTLloaddb} (described in \autoref{sec:loadbbl}) can be +%displayed using: +%\begin{definition} +%\cs{DTLbibliography}\oarg{conditions}\marg{db name} +%\end{definition}\noindent +%where \meta{db name} is the name of the database. +% +%Within the optional argument \meta{condition}, you may use any of the +%commands that may be used within the optional argument of +%\cs{DTLforeach} \emph{In addition}, you may use the following +%commands: +% +%\DescribeMacro{\DTLbibfieldexists} +%\begin{definition} +%\cs{DTLbibfieldexists}\marg{field label} +%\end{definition} +%This tests whether the field with the given label exists for the +%current entry. +%The field label may be one of: "Address", "Author", +%"BookTitle", "Chapter", "Edition", "Editor", "HowPublished", +%"Institution", "Journal", "Key", "Month", "Note", "Number", +%"Organization", "Pages", "Publisher", "School", "Series", +%"Title", "Type", "Volume", "Year", "ISBN", "DOI", "PubMed", +%"Abstract" or "Url". +% +%For example, suppose you have loaded a \sty{databib} database +%called "mybib" using \cs{DTLloadbbl} (described in +%\autoref{sec:loadbbl}) then the following bibliography will only +%include those entries which have a "Year" field: +%\begin{verbatim} +%\DTLbibliography[\DTLbibfieldexists{Year}]{mybib} +%\end{verbatim} +% +%\DescribeMacro{\DTLbibfieldiseq} +%\begin{definition} +%\cs{DTLbibfieldiseq}\marg{field label}\marg{value} +%\end{definition} +%This tests whether the value of the field given by +%\meta{field label} equals \meta{value}. If the field doesn't +%exist for the current entry, this evaluates to false. +%For example, the following will produce a bibliography which +%only contains entries which have the "Year" field set to 2004: +%\begin{verbatim} +%\DTLbibliography[\DTLbibfieldiseq{Year}{2004}]{mybib} +%\end{verbatim} +% +%\DescribeMacro{\DTLbibfieldcontains} +%\begin{definition} +%\cs{DTLbibfieldcontains}\marg{field label}\marg{sub string} +%\end{definition} +%This tests whether the value of the field given by \meta{field label} +%contains \meta{sub string}. For example, the following will produce +%a bibliography which only contains entries where the author field +%contains the name "Knuth": +%\begin{verbatim} +%\DTLbibliography[\DTLbibfieldcontains{Author}{Knuth}]{mybib} +%\end{verbatim} +% +%\DescribeMacro{\DTLbibfieldislt} +%\begin{definition} +%\cs{DTLbibfieldislt}\marg{field label}\marg{value} +%\end{definition} +%This tests whether the value of the field given by \meta{field label} +%is less than \meta{value}. If the field doesn't exist for the +%current entry, this evaluates to false. +%For example, the following will produce a bibliography which only +%contains entries whose "Year" field is less than 1983: +%\begin{verbatim} +%\DTLbibliography[\DTLbibfieldislt{Year}{1983}]{mybib} +%\end{verbatim} +% +%\DescribeMacro{\DTLbibfieldisle} +%\begin{definition} +%\cs{DTLbibfieldisle}\marg{field label}\marg{value} +%\end{definition} +%This tests whether the value of the field given by \meta{field label} +%is less than or equal to \meta{value}. If the field doesn't exist +%for the current entry, this evaluates to false. +%For example, the following will produce a bibliography which only +%contains entries whose "Year" field is less than or equal to 1983: +%\begin{verbatim} +%\DTLbibliography[\DTLbibfieldisle{Year}{1983}]{mybib} +%\end{verbatim} +% +%\DescribeMacro{\DTLbibfieldisgt} +%\begin{definition} +%\cs{DTLbibfieldisgt}\marg{field label}\marg{value} +%\end{definition} +%This tests whether the value of the field given by \meta{field label} +%is greater than \meta{value}. If the field doesn't exist for the +%current entry, this evaluates to false. +%For example, the following will produce a bibliography which only +%contains entries whose "Year" field is greater than 1983: +%\begin{verbatim} +%\DTLbibliography[\DTLbibfieldisgt{Year}{1983}]{mybib} +%\end{verbatim} +% +%\DescribeMacro{\DTLbibfieldisge} +%\begin{definition} +%\cs{DTLbibfieldisge}\marg{field label}\marg{value} +%\end{definition} +%This tests whether the value of the field given by \meta{field label} +%is greater than or equal to \meta{value}. If the field doesn't exist +%for the current entry, this evaluates to false. +%For example, the following will produce a bibliography which only +%contains entries whose "Year" field is greater than or equal to 1983: +%\begin{verbatim} +%\DTLbibliography[\DTLbibfieldisge{Year}{1983}]{mybib} +%\end{verbatim} +% +%Note that \cs{DTLbibliography} uses \cs{DTLforeachbibentry} +%(described in \autoref{sec:foreachbib}) so you may also use +%test the value of the counter \counterfmt{DTLbibrow} within +%\meta{conditions}. +% +%\begin{example}{Creating a list of publications since a given year}{ex:bibsince2000} +%Suppose my boss has asked me to produce a list of my +%publications in reverse chronological order, but doesn't want any +%publications published prior +%to the year 2000. I have a file called "nlct.bib" which contains +%all my publications which I keep in the directory +%\verb!$HOME/texmf/bibtex/bib/!. I could look through this file, +%work out the labels for all the publications whose year field +%is greater or equal to 2000, and +%create a file with a \cs{nocite} command containing all those labels +%in a comma separated list in reverse chronological order, +%but I really can't be bothered to do that. +%Instead, I can create the following document: +%\begin{verbatim} +%\documentclass{article} +%\usepackage{databib} +%\begin{document} +%\nocite{*} +%\DTLloadbbl{mybib}{nlct} +%\DTLsort{Year=descending,Month=descending}{mybib} +%\DTLbibliography[\DTLbibfieldisge{Year}{2000}]{mybib} +%\end{document} +%\end{verbatim} +%Suppose I save this file as "mypubs.tex", then I need to do: +%\begin{verbatim} +%latex mypubs +%bibtex mypubs +%latex mypubs +%\end{verbatim} +%Notes: +%\begin{enumerate} +%\item "\nocite{*}" is used to add all the citations in the +%bibliography file ("nlct.bib" in this case) to the \sty{databib} +%database. +% +%\item "\DTLloadbbl{mybib}{nlct}" does the following: +%\begin{enumerate} +%\item writes the line +%\begin{verbatim} +%\bibstyle{databib} +%\end{verbatim} +%to the auxiliary file. This tells \BibTeX\ to use "databib.bst" +%(which is supplied with this package.) You therefore shouldn't +%use \cs{bibliographystyle}. +% +%\item writes the line +%\begin{verbatim} +%\bibdata{nlct} +%\end{verbatim} +%to the auxiliary file. This tells \BibTeX\ that the bibliography +%data is stored in the file "nlct.bib". Since I have placed this +%file in \TeX's search path, \BibTeX\ will be able to find it. +% +%\item creates a \sty{datatool} database called "mybib". +% +%\item if the \ext{bbl} file ("mypubs.bbl" in this example) exists, +%it loads this file (which adds the bibliography data to the +%database), otherwise it does nothing further. +% +%\end{enumerate} +% +%\item In my \BibTeX\ database ("nlct.bib" in this example), I +%have remember to use the \BibTeX\ month macros: "jan", "feb" +%etc. This means that the months are stored in the database in +%the form \cs{DTLmonthname}\marg{nn}, where \meta{nn} is a two +%digit number from 01 to 12. \cs{DTLsort} ignores command names +%when it compares strings, which means I can not only sort by +%year, but also by month\footnote{as long as I haven't put anything +%before the month name in the bibliography file, e.g.\ +%\mbox{\texttt{month = "2~" \# apr}} will sort by 2~03, instead of +%03}. +% +%\item Once I have loaded and sorted my database, I can then +%display it using \cs{DTLbibliography}. This uses the style +%given by the \sty{databib} \pkgopt[databib]{style} package option, +%or the \cs{DTLbibliographystyle} command, both of which are +%described in \autoref{sec:bibstyle}. +% +%\item I have filtered the bibliography using the optional +%argument\linebreak "[\DTLbibfieldisge{Year}{2000}]", which checks if the +%year field of the current entry is greater than or equal to +%2000. (Note that if an entry has no year field, the condition +%evaluates to false, and the entry will be omitted from the +%bibliography.) +% +%\item If the bibliography database is large, sorting and creating +%the bibliography may take a while. Using \sty{databib} is much +%slower than using a standard \BibTeX\ style file. +%\end{enumerate} +%\end{example} +% +%\begin{example}{Creating a list of my 10 most recent +%publications}{ex:top10bib} +%Suppose now my boss has asked me to produce a list of my ten most +%recent publications (in reverse chronological order). +%As in the previous example, I have a file called "nlct.bib" +%which contains all my publications. I can create the required +%document as follows: +%\begin{verbatim} +%\documentclass{article} +%\usepackage{databib} +%\begin{document} +%\nocite{*} +%\DTLloadbbl{mybib}{nlct} +%\DTLsort{Year=descending,Month=descending}{mybib} +%\DTLbibliography[\value{DTLbibrow}<11]{mybib} +%\end{document} +%\end{verbatim} +%\end{example} +% +%\subsection{Changing the bibliography style} +%\label{sec:bibstyle} +%The style of the bibliography produced using \cs{DTLbibliography} +%depends on the \pkgopt[databib]{style} +%package option, or can be set using +%\begin{definition} +%\cs{DTLbibliographystyle}\marg{style} +%\end{definition} +%Note that this is \emph{not} the same as \cs{bibliographystyle}, +%as the \sty{databib} package uses its custom \texttt{databib.bst} +%bibliography style file. +% +%Example: +%\begin{verbatim} +%\usepackage[style=plain]{databib} +%\end{verbatim} +%This sets the plain bibliography style. This is, in fact, the +%default style, so it need not be specified. +% +%Available styles are: "plain", "abbrv" and "alpha". These are similar to the +%standard \BibTeX\ styles of the same name, but are by no means +%identical. The most notable difference is that these styles +%do not sort the bibliography. It is up to you to sort the +%bibliography using \cs{DTLsort} (described in \autoref{sec:sort}.) +% +%\subsubsection{Modifying an existing style} +%\label{sec:modbibstyle} +% +%This section describes some of the commands which are used to +%format the bibliography. You can choose whichever predefined +%style best fits your required style, and then modify the commands +%described in this section. A description of the remaining +%commands not listed in this section can be found in +%\autoref{sec:src:bibnames}, \autoref{sec:src:displaybib} +%and \autoref{sec:src:bibstyle}. +% +%\DescribeMacro{\DTLformatauthor} +%\begin{definition} +%\cs{DTLformatauthor}\marg{von part}\marg{surname}\marg{jr part}\marg{forenames} +%\end{definition} +%\DescribeMacro{\DTLformateditor} +%\begin{definition} +%\cs{DTLformateditor}\marg{von part}\marg{surname}\marg{jr part}\marg{forenames} +%\end{definition} +%These commands are used to format an author/editor's name, +%respectively. The list of authors and editors are stored in +%the \sty{databib} database as a comma separated list of +%\marg{von part}\marg{surname}\marg{jr part}\marg{forenames} +%data. This ensures that when you sort on the Author or Editor +%field, the names will be sorted by the first author or editor's +%surname. +% +%Within \cs{DTLformatauthor} and \cs{DTLformateditor}, you may +%use the following commands: +%\DescribeMacro{\DTLformatforenames} +%\begin{definition} +%\cs{DTLformatforenames}\marg{forenames} +%\end{definition} +%This is used by the "plain" style to display the author's +%forenames\footnote{It also checks +%whether \meta{forenames} ends with a full stop using +%\cs{DTLcheckendsperiod} to prevent a sentence ending full stop +%from following an abbreviation full stop}. +% +%\DescribeMacro{\DTLformatabbrvforenames} +%\begin{definition} +%\cs{DTLformatabbrvforenames}\marg{forenames} +%\end{definition} +%This is used by the "abbrv" style to display the author's +%initials (which are determined from \meta{forenames}.) +%Note that if any of the authors has a name starting with an +%accent, the accented letter must be grouped in order for this +%command to work. For example: +%\begin{verbatim} +%author = "{\'E}lise {\"E}awyn Edwards", +%\end{verbatim} +%The initials are formed using \cs{DTLstoreinitials} described +%in \autoref{sec:strings}, so if you want to change the way the +%initials are displayed (e.g.\ put a space between them) you will +%need to redefine the commands used by \cs{DTLstoreinitials} (such +%as \cs{DTLbetweeninitials}.) +% +%\DescribeMacro{\DTLformatsurname} +%\begin{definition} +%\cs{DTLformatsurname}\marg{surname} +%\end{definition} +%This displays its argument by default\footnote{It also checks +%whether the surname ends with a full stop using +%\cs{DTLcheckendsperiod}}. +% +%\DescribeMacro{\DTLformatvon} +%\begin{definition} +%\cs{DTLformatvon}\marg{von part} +%\end{definition} +%If the \meta{von part} is empty, this command does nothing, +%otherwise it displays its argument followed by a +%non-breakable space. +%\DescribeMacro{\DTLformatjr} +%\begin{definition} +%\cs{DTLformatjr}\marg{jr part} +%\end{definition} +%If the \meta{jr part} is empty, this command displays nothing, +%otherwise it displays a comma followed by its argument\footnote +%{again, it also checks \meta{jr part} to determine if it ends +%with a full stop}. +% +%For example, suppose you want the author's surname to appear +%first in small capitals, followed by a comma and the forenames. This +%can be achieved by redefining \cs{DTLformatauthor} as follows: +%\begin{verbatim} +%\renewcommand*{\DTLformatauthor}[4]{% +%\textsc{\DTLformatvon{#1}% +%\DTLformatsurname{#2}\DTLformatjr{#3}}, +%\DTLformatforenames{#4}% +%} +%\end{verbatim} +% +%\begin{definition} +%\counterfmt{DTLmaxauthors} +%\end{definition} +%The counter \counterfmt{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. +% +%\begin{definition} +%\counterfmt{DTLmaxeditors} +%\end{definition} +%The \counterfmt{DTLmaxeditors} counter is analogous to the +%\counterfmt{DTLmaxauthors} counter. It is used to determine the +%maximum number of editor names to display. The default value +%of \counterfmt{DTLmaxeditors} is \theDTLmaxeditors. +% +%\DescribeMacro{\DTLandlast} +%Within a list of author or editor names, \cs{DTLandlast} is +%used between the last two names, otherwise +%\DescribeMacro{\DTLandnotlast}\cs{DTLandnotlast} is used between +%names. +%However, if there are only two author or editor names, +%\DescribeMacro{\DTLtwoand}\cs{DTLtwoand} +%is used instead of \cs{DTLandlast}. +% +%\DescribeMacro{\DTLendbibitem} +%The command \cs{DTLendbibitem} is a hook provided to add +%additional information at the end of each bibliography item. +%This does nothing by default, but if you want to display the +%additional fields provided by the "databib.bst" style file, +%you can redefine \cs{DTLendbibitem} so that it displays a +%particular field, if it is defined. Within this command, you +%may use the commands \cs{DTLbibfield}, \cs{DTLifbibfieldexist} +%and \cs{DTLifanybibfieldexist}, which are described in +%\autoref{sec:foreachbib}. For example, if you have used the +%"abstract" field in any of your entries, you can display the +%abstract as follows: +%\begin{verbatim} +%\renewcommand{\DTLendbibitem}{% +%\DTLifbibfieldexists{Abstract}{\DTLpar\textbf{Abstract} +%\begin{quote}\DTLbibfield{Abstract}\end{quote}}{}} +%\end{verbatim} +%(Note that \cs{DTLpar} needs to be used instead of +%\cs{par}.) +% +%\begin{example}{Compact bibliography}{ex:compactbib} +%Suppose I don't have much space in my document, and I need to +%produce a compact bibliography. Firstly, I can use the +%bibliography style "abbrv", either through the package option: +%\begin{verbatim} +%\usepackage[style=abbrv]{databib} +%\end{verbatim} +%or using: +%\begin{verbatim} +%\DTLbibliographystyle{abbrv} +%\end{verbatim} +%Once I have set the style, I can further modify it thus: +%\begin{verbatim} +%\renewcommand*{\andname}{\&} +%\renewcommand*{\editorname}{ed.} +%\renewcommand*{\editorsname}{eds.} +%\renewcommand*{\pagesname}{pp.} +%\renewcommand*{\pagename}{p.} +%\renewcommand*{\volumename}{vol.} +%\renewcommand*{\numbername}{no.} +%\renewcommand*{\editionname}{ed.} +%\renewcommand*{\techreportname}{T.R.} +%\renewcommand*{\mscthesisname}{MSc thesis} +%\end{verbatim} +%Now I can load\footnote{I can load the bibliography earlier, but +%obviously the bibliography should only be displayed after the +%bibliography styles have been set, otherwise they will have no +%effect} and display the bibliography: +%\begin{verbatim} +% % create a database called mybib from the information given +% % in mybib1.bib and mybib2.bib +% \DTLloadbbl{mybib}{mybib1,mybib2} +% % display the bibliography +% \DTLbibliography{mybib} +%\end{verbatim} +%\end{example} +% +%\begin{example}{Highlighting a given author}{ex:highlightauthor} +%Suppose my boss wants me to produce a list of all my publications +%(which I have stored in the file "nlct.bib", as in +%\autoref{ex:bibsince2000}.) Most of my +%publications have multiple co-authors, but suppose my boss would +%like me to highlight my name so that when he skims through +%the document, he can easily see my name in the list of +%co-authors. I can do this by redefining \cs{DTLformatauthor} +%so that it checks if the given surname matches mine. (This +%assumes that none of the other co-author's share my surname.) +%\begin{verbatim} +%\renewcommand*{\DTLformatauthor}[4]{% +%{\DTLifstringeq{#2}{Talbot}{\bfseries }{}% +%\DTLformatforenames{#4} +%\DTLformatvon{#1}% +%\DTLformatsurname{#2}% +%\DTLformatjr{#3}}} +%\end{verbatim} +%Notes: +%\begin{enumerate} +%\item I have used \cs{DTLifstringeq} (described in +%\autoref{sec:ifconditions}) to perform the string comparison. +%\item If one or more of my co-authors shared the same surname as +%me, I would also have had to check the first name, however there +%is regrettably a lack of consistency in my \ext{bib} file when +%it comes to my forenames. Sometimes my name is given as +%\texttt{Nicola L. C. Talbot}, sometimes the middle initials +%are omitted, \texttt{Nicola Talbot}, or sometimes, just initials +%are used, \texttt{N. L. C. Talbot}. This can cause problems +%when checking the forenames, but as long as the other authors +%who share the same surname as me, don't also share the same +%first initial, I can use \cs{DTLifStartsWith} or \cs{DTLisPrefix}, +%which are described in \autoref{sec:ifconditions} and +%\autoref{sec:ifthen}, respectively. Using the first approach +%I can do: +%\begin{verbatim} +%\renewcommand*{\DTLformatauthor}[4]{% +%{\DTLifstringeq{#2}{Talbot}{\DTLifStartsWith{#4}{N}{\bfseries }{}}{}% +%\DTLformatforenames{#4} +%\DTLformatvon{#1}% +%\DTLformatsurname{#2}% +%\DTLformatjr{#3}}} +%\end{verbatim} +%Using the second approach I can do: +%\begin{verbatim} +%\renewcommand*{\DTLformatauthor}[4]{% +%{\ifthenelse{\DTLiseq{#2}{Talbot}\and +%\DTLisPrefix{#4}{N}}{\bfseries }{}% +%\DTLformatforenames{#4} +%\DTLformatvon{#1}% +%\DTLformatsurname{#2}% +%\DTLformatjr{#3}}} +%\end{verbatim} +% +%\item I have used a group to localise the effect of \cs{bfseries}. +%\end{enumerate} +%\end{example} +% +%\subsection{Iterating through a +%\texorpdfstring{\sty{databib}}{databib} database} +%\label{sec:foreachbib} +% +%\cs{DTLbibliography} (described in \autoref{sec:thebib}) may still +%not meet your needs. For example, you may be required +%to list journal papers and conference proceedings in separate +%sections. In which case, you may find it easier to iterate through +%the bibliography using: +%\DescribeMacro{\DTLforeachbib} +%\begin{definition} +%\cs{DTLforeachbib}\oarg{condition}\marg{db name}\marg{text} +%\end{definition} +%\DescribeMacro{\DTLforeachbib*} +%\begin{definition} +%\cs{DTLforeachbib*}\oarg{condition}\marg{db name}\marg{text} +%\end{definition} +%This iterates through the \sty{databib} database called +%\meta{db name} and does \meta{text} if \meta{condition} is met. +%As with \cs{DTLforeach}, the starred version is read-only. +% +%For each row of the database, the following commands are set: +%\begin{itemize} +%\item \cs{DBIBcitekey} \DescribeMacro{\DBIBcitekey}This is the +%unique label which identifies the current entry (as used in the +%argument of \cs{cite} and \cs{nocite}.) +% +%\item \cs{DBIBentrytype} \DescribeMacro{\DBIBentrytype}This +%is the current entry type, and will be one of: "article", "book", +%"booklet", "inbook", "incollection", "inproceedings", +%"manual", "mastersthesis", "misc", "phdthesis", "proceedings", +%"techreport" or "unpublished". (Note that even if you used the +%entry type "conference" in your \ext{bib} file, its entry type +%will be set to "inproceedings".) +%\end{itemize} +% +%The remaining fields may be accessed using: +%\DescribeMacro{\DTLbibfield} +%\begin{definition} +%\cs{DTLbibfield}\marg{field label} +%\end{definition}\noindent +%where \meta{field label} may be one of: "Address", "Author", +%"BookTitle", "Chapter", "Edition", "Editor", "HowPublished", +%"Institution", "Journal", "Key", "Month", "Note", "Number", +%"Organization", "Pages", "Publisher", "School", "Series", +%"Title", "Type", "Volume", "Year", "ISBN", "DOI", "PubMed", +%"Abstract" or "Url". +% +%You can determine if a field exists for a given entry using +%\DescribeMacro{\DTLifbibfieldexists} +%\begin{definition} +%\cs{DTLifbibfieldexists}\marg{field label}\marg{true part}\marg{false +%part} +%\end{definition} +%If the field given by \meta{field label} exists for the current +%bibliography entry, it does \meta{true part}, otherwise it +%does \meta{false part}. +% +%\DescribeMacro{\DTLifbibanyfieldexists} +%\begin{definition} +%\cs{DTLifanybibfieldexists}\marg{field label list}\marg{true +%part}\marg{false part} +%\end{definition} +%This is similar to \cs{DTLifbibfieldexists} except that the +%first argument is a list of field names. If one or more of +%the fields given in \meta{field label list} exists for the +%current bibliography item, this does \meta{true part}, otherwise +%it does \meta{false part}. +% +%\DescribeMacro{\DTLformatbibentry} +%\begin{definition} +%\cs{DTLformatbibentry} +%\end{definition} +%This formats the bibliography entry for the current row. It +%checks for the existence of the command +%\cs{DTLformat}\meta{entry type}, where \meta{entry type} +%is given by \cs{DBIBentrytype}. These commands are defined +%by the bibliography style. +% +%\DescribeMacro{\DTLcomputewidestbibentry} +%\begin{definition} +%\cs{DTLcomputewidestbibentry}\marg{conditions}\marg{db +%name}\marg{bib label}\marg{cmd} +%\end{definition} +%This computes the widest bibliography entry over all entries +%satisfying \meta{conditions} in the database \meta{db name}, +%where the label is given by \meta{bib label}, and the result +%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 +%bibliography entry. This is reset at the start of each +%\cs{DTLforeachbib} and is incremented if \meta{conditions} +%is met. +% +%Within the optional argument \meta{condition}, you may use any of the +%commands that may be used within the optional argument of +%\cs{DTLbibliography}, described in \autoref{sec:thebib}. +% +%\begin{example}{Separate List of Journals and Conference Papers}{ex:jcbib} +%Suppose now my boss has decided that I need to produce a list +%of all my publications, but they need to be separated so that +%all the journal papers appear in one section, and all the +%conference papers appear in another section. The journal papers +%need to be labelled [J1], [J2] and so on, while the conference +%papers need to be labelled [C1], [C2] and so on. (My boss isn't +%interested in any of my other publications!) Again, all my +%publications are stored in the \BibTeX\ database "nlct.bib". The +%following creates the required document: +%\begin{verbatim} +%\documentclass{article} +%\usepackage{databib} +%\begin{document} +%\nocite{*} +%\DTLloadbbl{mybib}{nlct} +% +%\renewcommand*{\refname}{Journal Papers} +%\DTLcomputewidestbibentry{\equal{\DBIBentrytype}{article}} +%{mybib}{J\theDTLbibrow}{\widest} +% +%\begin{thebibliography}{\widest} +%\DTLforeachbibentry[\equal{\DBIBentrytype}{article}]{mybib}{% +%\bibitem[J\theDTLbibrow]{\DBIBcitekey} \DTLformatbibentry} +%\end{thebibliography} +% +%\renewcommand*{\refname}{Conference Papers} +%\DTLcomputewidestbibentry{\equal{\DBIBentrytype}{inproceedings}} +%{mybib}{C\theDTLbibrow}{\widest} +% +%\begin{thebibliography}{\widest} +%\DTLforeachbibentry[\equal{\DBIBentrytype}{inproceedings}]{mybib}{% +%\bibitem[C\theDTLbibrow]{\DBIBcitekey} \DTLformatbibentry} +%\end{thebibliography} +% +%\end{document} +%\end{verbatim} +%\end{example} +% +% \StopEventually{\clearpage\phantomsection +%\addcontentsline{toc}{section}{\refname} +% \DTLbibliography{docbib} +%\phantomsection +%\addcontentsline{toc}{section}{Change History}\PrintChanges +%\phantomsection +%\addcontentsline{toc}{section}{Index}\PrintIndex +%} +% +% +% +%\section{datatool.sty} +%\iffalse +% \begin{macrocode} +%<*datatool.sty> +% \end{macrocode} +%\fi +%\subsection{Package Declaration} +% \begin{macrocode} +\NeedsTeXFormat{LaTeX2e} +\ProvidesPackage{datatool}[2007/08/17 v1.01 (NLCT)] +% \end{macrocode} +% Load required packages: +% \begin{macrocode} +\RequirePackage{xkeyval} +\RequirePackage{ifthen} +\RequirePackage{xfor} +\RequirePackage{fp} +\RequirePackage{substr} +% \end{macrocode} +% +%\subsection{Package Options} +%\begin{macro}{\@dtl@separator} +% The data separator character (comma by default) is stored in +% \cs{@dtl@separator}. +% This is the separator used in external data files, not in the +% \LaTeX\ code, which always uses a comma separator. +% \begin{macrocode} +\newcommand*{\@dtl@separator}{,} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLsetseparator} +%\begin{definition} +%\cs{DTLsetseparator}\marg{char} +%\end{definition} +% The sets \cs{@dtl@separator}, and constructs the relevent macros +% that require this character to be hardcoded into their definition. +% \begin{macrocode} +\newcommand*{\DTLsetseparator}[1]{% +\renewcommand*{\@dtl@separator}{#1}% +\@dtl@construct@lopoffs +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLsettabseparator} +%\cs{DTLsettabseparator} makes it easier to set a tab separator. +% \begin{macrocode} +\begingroup +\catcode`\ 12 +\gdef\DTLsettabseparator{% + \catcode`\ 12 + \DTLsetseparator{ }% +} +\endgroup +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\@dtl@delimiter} +% The data delimiter character (double quote by default) is stored +% in \cs{@dtl@delimiter}. This is used in external data files, not +% in the \LaTeX\ code. +% \begin{macrocode} +\begingroup +\catcode`\"12\relax +\gdef\@dtl@delimiter{"} +\endgroup +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLsetdelimiter} +%\begin{definition} +%\cs{DTLsetdelimiter}\marg{char} +%\end{definition} +% This sets the delimiter. +% \begin{macrocode} +\newcommand*\DTLsetdelimiter[1]{% +\renewcommand*{\@dtl@delimiter}{#1}% +\@dtl@construct@lopoffs} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\@dtl@construct@lopoff} +%\begin{definition} +%\cs{@dtl@construct@lopoff}\meta{separator char}\meta{delimiter char} +%\end{definition} +% This defines +%\begin{definition} +% \cs{@dtl@lopoff}\meta{first element}\meta{sep}\meta{rest of list}\cs{to}\meta{cmd1}\meta{cmd2} +%\end{definition}\noindent +%for the current separator and delimiter. +% \begin{macrocode} +\edef\@dtl@construct@lopoff#1#2{% +\noexpand\long\noexpand\def\noexpand\@dtl@lopoff#1##1##2\noexpand +\to##3##4{% +\noexpand\ifx#2##1\noexpand\relax +\noexpand\@dtl@qlopoff#1##1##2\noexpand\to##3##4\relax +\noexpand\else +\noexpand\@dtl@lop@ff#1##1##2\noexpand\to##3##4\relax +\noexpand\fi +}} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\@dtl@construct@qlopoff} +%\begin{definition} +% \cs{@dtl@construct@qlopoff}\meta{separator char}\meta{delimiter char} +%\end{definition} +% This constructs \cs{@dtl@qlopoff} to be used +% when the entry is surrounded by the current delimiter value. +% \begin{macrocode} +\edef\@dtl@construct@qlopoff#1#2{% +\noexpand\long\noexpand\def\noexpand\@dtl@qlopoff#1#2##1#2#1##2\noexpand +\to##3##4{% +\noexpand\def##4{##1}\noexpand\def##3{#1##2}% +}} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\@dtl@construct@lop@ff} +%\begin{definition} +% \cs{@dtl@construct@lop@ff}\meta{separator char} +%\end{definition} +% This constructs \cs{@dtl@lop@ff} to be used when +% the entry isn't surrouded by the delimiter. +% \begin{macrocode} +\edef\@dtl@construct@lop@ff#1{% +\noexpand\long\noexpand\def\noexpand\@dtl@lop@ff#1##1#1##2\noexpand +\to##3##4{% +\noexpand\def##4{##1}\noexpand\def##3{#1##2}% +}} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\@dtl@construct@lopoffs} +%\begin{definition} +%\cs{@dtl@construct@lopoffs} +%\end{definition} +% This constructs all the lopoff macros +% using the given separator and delimiter characters. +% \begin{macrocode} +\newcommand{\@dtl@construct@lopoffs}{% +\edef\@dtl@chars{{\@dtl@separator}{\@dtl@delimiter}}% +\expandafter\@dtl@construct@lopoff\@dtl@chars +\expandafter\@dtl@construct@qlopoff\@dtl@chars +\expandafter\@dtl@construct@lop@ff\expandafter{\@dtl@separator}% +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\@dtl@decimal} +% The current decimal character is stored in \cs{@dtl@decimal}. +% \begin{macrocode} +\newcommand*{\@dtl@decimal}{.} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\@dtl@numbergroupchar} +% The current number group character is stored in +% \cs{@dtl@numbergroupchar}. +% \begin{macrocode} +\newcommand*{\@dtl@numbergroupchar}{,} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLsetnumberchars} +%\begin{definition} +%\cs{DTLsetnumberchars}\marg{number group char}\marg{decimal char} +%\end{definition} +% This sets the decimal character and number group +% characters. +% \begin{macrocode} +\newcommand*{\DTLsetnumberchars}[2]{% +\renewcommand*{\@dtl@numbergroupchar}{#1}% +\renewcommand*{\@dtl@decimal}{#2}% +\@dtl@construct@getnums +\@dtl@construct@stripnumgrpchar{#1}} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\@dtl@construct@getintfrac} +%\begin{definition} +%\cs{@dtl@construct@getintfrac}\marg{char} +%\end{definition} +% This constructs the macros for extracting integer and +% fractional parts from a real number using the decimal character +% \meta{char}. +% +%\begin{definition} +% \cs{DTLconverttodecimal}\marg{num}\marg{cmd} +%\end{definition} +% \cs{DTLconverttodecimal} will convert locale dependent \meta{num} +% a decimal number in a form that can be used in the +% macros defined in the \sty{fp} package. The resulting +% number is stored in \meta{cmd}. This command has to be redefined +% whenever the decimal and number group characters are changed +% as they form part of the command definitions. +% \begin{macrocode} +\edef\@dtl@construct@getintfrac#1{% +\noexpand\def\noexpand\@dtl@getintfrac##1#1##2\noexpand\relax{% +\noexpand\@dtl@get@intpart{##1}% +\noexpand\def\noexpand\@dtl@fracpart{##2}% +\noexpand\ifx\noexpand\@empty\noexpand\@dtl@fracpart + \noexpand\def\noexpand\@dtl@fracpart{0}% +\noexpand\else + \noexpand\@dtl@getfracpart##2\noexpand\relax + \noexpand\@dtl@choptrailingzeroes{\noexpand\@dtl@fracpart}% +\noexpand\fi +}% +\noexpand\def\noexpand\@dtl@getfracpart##1#1\noexpand\relax{% +\noexpand\def\noexpand\@dtl@fracpart{##1}% +}% +\noexpand\def\noexpand\DTLconverttodecimal##1##2{% +\noexpand\dtl@ifsingle{##1}% +{\noexpand\expandafter\noexpand\toks@\noexpand\expandafter{##1}% +\noexpand\edef\noexpand\@dtl@tmp{\noexpand\the\noexpand\toks@}}% +{\noexpand\def\noexpand\@dtl@tmp{##1}}% + \noexpand\@dtl@standardize@currency\noexpand\@dtl@tmp + \noexpand\ifx\noexpand\@dtl@org@currency\noexpand\@empty + \noexpand\else + \noexpand\let\noexpand\@dtl@currency\noexpand\@dtl@org@currency + \noexpand\fi +\noexpand\expandafter +\noexpand\@dtl@getintfrac\noexpand\@dtl@tmp#1\noexpand\relax +\noexpand\edef##2{\noexpand\@dtl@intpart.\noexpand\@dtl@fracpart}}% +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\@dtl@construct@getnums} +% The following calls the above with the relevant +% decimal character: +% \begin{macrocode} +\newcommand*{\@dtl@construct@getnums}{% +\expandafter\@dtl@construct@getintfrac\expandafter{\@dtl@decimal}} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\@dtl@get@intpart} +% The following gets the integer part (adjusting for +% repeating +/- signs if necessary.) +% Sets \cs{@dtl@intpart}. +% \begin{macrocode} +\newcommand*{\@dtl@get@intpart}[1]{% +\@dtl@tmpcount=1\relax +\def\@dtl@intpart{#1}% +\ifx\@dtl@intpart\@empty + \def\@dtl@intpart{0}% +\else + \def\@dtl@intpart{}% + \@dtl@get@int@part#1.\relax% +\fi +\ifnum\@dtl@tmpcount<0\relax + \edef\@dtl@intpart{-\@dtl@intpart}% +\fi +\@dtl@strip@numgrpchar{\@dtl@intpart}% +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\@dtl@get@int@part} +% \begin{macrocode} +\def\@dtl@get@int@part#1#2\relax{% +\def\@dtl@argi{#1}% +\def\@dtl@argii{#2}% +\ifx\protect#1\relax% + \let\@dtl@get@nextintpart=\@dtl@get@int@part +\else + \expandafter\ifx\@dtl@argi\$% + \let\@dtl@get@nextintpart=\@dtl@get@int@part + \else + \ifx-#1% + \multiply\@dtl@tmpcount by -1\relax + \let\@dtl@get@nextintpart=\@dtl@get@int@part + \else + \if\@dtl@argi+% + \let\@dtl@get@nextintpart=\@dtl@get@int@part + \else + \def\@dtl@intpart{#1}% + \ifx.\@dtl@argii + \let\@dtl@get@nextintpart=\@gobble + \else + \let\@dtl@get@nextintpart=\@dtl@get@next@intpart + \fi + \fi + \fi + \fi +\fi +\@dtl@get@nextintpart#2\relax +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\@dtl@get@next@intpart} +% \begin{macrocode} +\def\@dtl@get@next@intpart#1.\relax{% +\edef\@dtl@intpart{\@dtl@intpart#1}% +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\@dtl@choptrailingzeroes} +%\begin{definition} +% \cs{@dtl@choptrailingzeroes}\marg{cmd} +%\end{definition} +% Chops trailing zeroes from number given by \meta{cmd}. +% \begin{macrocode} +\newcommand*{\@dtl@choptrailingzeroes}[1]{% +\def\@dtl@tmpcpz{}% +\expandafter\@dtl@chop@trailingzeroes#1\@nil% +\let#1=\@dtl@tmpcpz +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\@dtl@chop@trailingzeroes} +% Trailing zeroes are chopped using a recursive algorithm. +% \cs{@dtl@tmpcpz} needs to be set before using this. (The chopped +% number is put in this control sequence.) +% \begin{macrocode} +\def\@dtl@chop@trailingzeroes#1#2\@nil{% +\FPifeq{#2}{0}% + \edef\@dtl@tmpcpz{\@dtl@tmpcpz#1}% + \let\@dtl@chopzeroesnext=\@dtl@gobbletonil +\else + \edef\@dtl@tmpcpz{\@dtl@tmpcpz#1}% + \let\@dtl@chopzeroesnext=\@dtl@chop@trailingzeroes +\fi +\@dtl@chopzeroesnext#2\@nil +} +% \end{macrocode} +%\end{macro} +% No-op macro to end recursion: +%\begin{macro}{\@dtl@gobbletonil} +% \begin{macrocode} +\def\@dtl@gobbletonil#1\@nil{} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\dtl@truncatedecimal} +%\begin{definition} +%\cs{dtl@truncatedecimal}\meta{cmd} +%\end{definition} +%Truncates decimal given by \meta{cmd} to an integer (assumes the +% number is in decimal format with full stop as decimal point.) +% \begin{macrocode} +\newcommand*{\dtl@truncatedecimal}[1]{% +\expandafter\@dtl@truncatedecimal#1.\@nil#1} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\@dtl@truncatedecimal} +% \begin{macrocode} +\def\@dtl@truncatedecimal#1.#2\@nil#3{% +\def#3{#1}} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\@dtl@strip@numgrpchar} +%\begin{definition} +% \cs{@dtl@strip@numgrpchar}\marg{cmd} +%\end{definition} +% Strip the number group character from the number given by +% \meta{cmd}. +% \begin{macrocode} +\newcommand*{\@dtl@strip@numgrpchar}[1]{% +\def\@dtl@stripped{}% +\edef\@dtl@do@stripnumgrpchar{% +\noexpand\@@dtl@strip@numgrpchar#1\@dtl@numbergroupchar +\noexpand\relax}% +\@dtl@do@stripnumgrpchar +\let#1=\@dtl@stripped +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\@dtl@construct@stripnumgrpchar} +% The following macro constructs \cs{@@dtl@strip@numgrpchar}. +% \begin{macrocode} +\edef\@dtl@construct@stripnumgrpchar#1{% +\noexpand\def\noexpand\@@dtl@strip@numgrpchar##1#1##2\noexpand\relax{% +\noexpand\expandafter\noexpand\toks@\noexpand\expandafter +{\noexpand\@dtl@stripped}% +\noexpand\edef\noexpand\@dtl@stripped{\noexpand\the\noexpand\toks@ +##1}% +\noexpand\def\noexpand\@dtl@tmp{##2}% +\noexpand\ifx\noexpand\@dtl@tmp\noexpand\@empty + \noexpand\let\noexpand\@dtl@next=\noexpand\relax +\noexpand\else + \noexpand\let\noexpand\@dtl@next=\noexpand\@@dtl@strip@numgrpchar +\noexpand\fi +\noexpand\@dtl@next##2\noexpand\relax +}% +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLdecimaltolocale} +%\begin{definition} +% \cs{DTLdecimaltolocale}\marg{number}\marg{cmd} +%\end{definition} +% Define command to convert a decimal number into the locale +% dependent format. Stores result in \meta{cmd} which must be +% a control sequence. +% \begin{macrocode} +\newcommand*{\DTLdecimaltolocale}[2]{% +\edef\@dtl@tmpdtl{#1}% +\expandafter\@dtl@decimaltolocale\@dtl@tmpdtl.\relax +\FPifeq{\@dtl@fracpart}{0}% + \edef#2{\@dtl@intpart}% +\else + \edef#2{\@dtl@intpart\@dtl@decimal\@dtl@fracpart}% +\fi +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\@dtl@decimaltolocale} +% Convert the integer part (store in \cs{@dtl@intpart}) +% \begin{macrocode} +\def\@dtl@decimaltolocale#1.#2\relax{% +\@dtl@decimaltolocaleint{#1}% +\def\@dtl@fracpart{#2}% +\ifx\@dtl@fracpart\@empty + \def\@dtl@fracpart{0}% +\else + \@dtl@decimaltolocalefrac#2\relax +\fi +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\@dtl@decimaltolocaleint} +% \begin{macrocode} +\def\@dtl@decimaltolocaleint#1{% +\@dtl@tmpcount=0\relax +\@dtl@countdigits#1.\relax +\@dtl@numgrpsepcount=\@dtl@tmpcount\relax +\divide\@dtl@numgrpsepcount by 3\relax +\multiply\@dtl@numgrpsepcount by 3\relax +\advance\@dtl@numgrpsepcount by -\@dtl@tmpcount\relax +\ifnum\@dtl@numgrpsepcount<0\relax + \advance\@dtl@numgrpsepcount by 3\relax +\fi +\def\@dtl@intpart{}% +\@dtl@decimal@to@localeint#1.\relax +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\@dtl@countdigits} +% Counts the number of digits until "#2" is a full stop. +% (increments \cs{@dtl@tmpcount}.) +% \begin{macrocode} +\def\@dtl@countdigits#1#2\relax{% +\advance\@dtl@tmpcount by 1\relax +\ifx.#2\relax + \let\@dtl@countnext=\@gobble +\else + \let\@dtl@countnext=\@dtl@countdigits +\fi +\@dtl@countnext#2\relax +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\@dtl@decimal@to@localeint} +% \begin{macrocode} +\def\@dtl@decimal@to@localeint#1#2\relax{% +\advance\@dtl@numgrpsepcount by 1\relax +\ifx.#2\relax + \edef\@dtl@intpart{\@dtl@intpart#1}% + \let\@dtl@localeintnext=\@gobble +\else + \ifnum\@dtl@numgrpsepcount=3\relax + \edef\@dtl@intpart{\@dtl@intpart#1\@dtl@numbergroupchar}% + \@dtl@numgrpsepcount=0\relax + \else + \ifnum\@dtl@numgrpsepcount>3\relax + \@dtl@numgrpsepcount=0\relax + \fi + \edef\@dtl@intpart{\@dtl@intpart#1}% + \fi + \let\@dtl@localeintnext=\@dtl@decimal@to@localeint +\fi +\@dtl@localeintnext#2\relax +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\@dtl@decimaltolocalefrac} +% Convert the fractional part (store in \cs{@dtl@fracpart}) +% \begin{macrocode} +% \end{macrocode} +\def\@dtl@decimaltolocalefrac#1.\relax{% +\def\@dtl@fracpart{#1}% +\@dtl@choptrailingzeroes{\@dtl@fracpart}% +} +%\end{macro} +% +%\begin{macro}{\DTLdecimaltocurrency} +%\begin{definition} +% \cs{DTLdecimaltocurrency}\marg{number}\marg{cmd} +%\end{definition} +% This converts a decimal number into the locale +% dependent currency format. Stores result in \meta{cmd} which must be +% a control sequence. +% \begin{macrocode} +\newcommand*{\DTLdecimaltocurrency}[2]{% +\edef\@dtl@tmpdtl{#1}% +\expandafter\@dtl@decimaltolocale\@dtl@tmpdtl.\relax +\dtl@truncatedecimal\@dtl@tmpdtl +\@dtl@tmpcount=\@dtl@tmpdtl\relax +\expandafter\@dtl@toks\expandafter{\@dtl@currency}% +\FPifeq{\@dtl@fracpart}{0}% + \ifnum\@dtl@tmpcount<0\relax + \@dtl@tmpcount = -\@dtl@tmpcount\relax + \edef#2{-\the\@dtl@toks\the\@dtl@tmpcount\@dtl@decimal00}% + \else + \edef#2{\the\@dtl@toks\@dtl@intpart\@dtl@decimal00}% + \fi +\else + \ifnum\@dtl@tmpcount<0\relax + \@dtl@tmpcount = -\@dtl@tmpcount\relax + \ifnum\@dtl@fracpart<10\relax + \edef#2{-\the\@dtl@toks\number\@dtl@tmpcount + \@dtl@decimal\@dtl@fracpart0}% + \else + \edef#2{-\the\@dtl@toks\number\@dtl@tmpcount + \@dtl@decimal\@dtl@fracpart}% + \fi + \else + \ifnum\@dtl@fracpart<10\relax + \edef#2{\the\@dtl@toks\@dtl@intpart\@dtl@decimal\@dtl@fracpart0}% + \else + \edef#2{\the\@dtl@toks\@dtl@intpart\@dtl@decimal\@dtl@fracpart}% + \fi + \fi +\fi +} +% \end{macrocode} +%\end{macro} +% +% Set the defaults: +% \begin{macrocode} +\@dtl@construct@lopoffs +\@dtl@construct@getnums +\expandafter\@dtl@construct@stripnumgrpchar\expandafter +{\@dtl@numbergroupchar} +% \end{macrocode} +% Define key for package option \pkgopt{separator}. +% \begin{macrocode} +\define@key{datatool.sty}{separator}{% +\DTLsetseparator{#1}} +% \end{macrocode} +% Define key for package option \pkgopt{delimiter}. +% \begin{macrocode} +\define@key{datatool.sty}{delimiter}{% +\DTLsetdelimiter{#1}} +% \end{macrocode} +% Define key for package option \pkgopt{verbose}. (This also +% switches the \sty{fp} messages on/off) +% \begin{macrocode} +\define@boolkey{datatool.sty}[dtl]{verbose}[true]{% +\ifdtlverbose \FPmessagestrue\else \FPmessagesfalse\fi} +% \end{macrocode} +%\begin{macro}{\dtl@message} +%\begin{definition} +%\cs{dtl@message}\marg{message string} +%\end{definition} +% Displays message only if the verbose option is set. +% \begin{macrocode} +\newcommand*{\dtl@message}[1]{% +\ifdtlverbose\typeout{#1}\fi} +% \end{macrocode} +%\end{macro} +% Process package options: +% \begin{macrocode} +\ProcessOptionsX +% \end{macrocode} +% +%\begin{macro}{\DTLpar} +% Many of the commands used by this package are short commands. +% This means that you can't use \cs{par} +% in the data. To get around this, define the robust command +% \cs{DTLpar} to use instead. +% \begin{macrocode} +\DeclareRobustCommand\DTLpar{\@par} +% \end{macrocode} +%\end{macro} +% +% \subsection{Determining Data Types} +% The control sequence \cs{@dtl@checknumerical} checks the data +% type of its argument, and sets \cs{@dtl@datatype} to 0 if +% the argument is a string, 1 if the argument is an integer +% or 2 if the argument is a real number. First define +% \cs{@dtl@datatype}: +%\begin{macro}{\@dtl@datatype} +% \begin{macrocode} +\newcount\@dtl@datatype +% \end{macrocode} +%\end{macro} +%\begin{macro}{\@dtl@tmpcount} +% Define temporary count register +% \begin{macrocode} +\newcount\@dtl@tmpcount +% \end{macrocode} +%\end{macro} +%\begin{macro}{\dtl@tmplength} +% Define temporary length register: +% \begin{macrocode} +\newlength\dtl@tmplength +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\@dtl@numgrpsepcount} +% Define count register to count the digits between the number +% group separators. +% \begin{macrocode} +\newcount\@dtl@numgrpsepcount +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\@dtl@checknumerical} +%\begin{definition} +%\cs{@dtl@checknumerical}\marg{arg} +%\end{definition} +% Checks if \meta{arg} is numerical +% (includes decimal numbers, but not scientific notation.) +% Sets \cs{@dtl@datatype}, as described above. +% \begin{macrocode} +\newcommand{\@dtl@checknumerical}[1]{% +\@dtl@numgrpsepfalse +\def\@dtl@tmp{#1}% +\ifx\@empty#1\@empty + \@dtl@datatype=0\relax +\else + \dtl@ifsingle{#1}% + {\expandafter\toks@\expandafter{#1}% + \edef\@dtl@tmp{\the\toks@}}% + {\def\@dtl@tmp{#1}}% + \@dtl@tmpcount=0\relax + \@dtl@datatype=0\relax + \@dtl@numgrpsepcount=2\relax + \@dtl@standardize@currency\@dtl@tmp + \ifx\@dtl@org@currency\@empty + \else + \let\@dtl@currency\@dtl@org@currency + \fi + \expandafter\@dtl@checknumericalstart\@dtl@tmp\@nil\@nil +\fi +\ifnum\@dtl@numgrpsepcount>-1\relax + \if@dtl@numgrpsep + \ifnum\@dtl@numgrpsepcount=3\relax + \else + \@dtl@datatype=0\relax + \fi + \fi +\fi +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\@dtl@checknumericalstart} +% Check first character for checknumerical process to see if +% it's a plus or minus sign. +% \begin{macrocode} +\def\@dtl@checknumericalstart#1#2\@nil\@nil{% +\ifx#1\protect + \@dtl@checknumericalstart#2\@nil\@nil\relax +\else + \ifx-#1\relax + \def\@dtl@tmp{#2}% + \ifx\@empty\@dtl@tmp + \@dtl@datatype=0\relax + \else + \ifnum\@dtl@datatype=0\relax + \@dtl@datatype=1\relax + \fi + \@dtl@checknumericalstart#2\@nil\@nil\relax + \fi + \else + \ifx+#1\relax + \def\@dtl@tmp{#2}% + \ifx\@empty\@dtl@tmp + \@dtl@datatype=0\relax + \else + \ifnum\@dtl@datatype=0\relax + \@dtl@datatype=1\relax + \fi + \@dtl@checknumericalstart#2\@nil\@nil\relax + \fi + \else + \def\@dtl@tmp{#1}% + \ifx#1\$\relax + \@dtl@datatype=3\relax + \@dtl@checknumericalstart#2\@nil\@nil\relax + \else + \ifx\@empty\@dtl@tmp + \@dtl@datatype=0\relax + \else + \ifnum\@dtl@datatype=0\relax + \@dtl@datatype=1\relax + \fi + \@dtl@checknumericalloop#1#2\@nil\@nil\relax + \fi + \fi + \fi + \fi +\fi +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\if@dtl@numgrpsep} +% The conditional \cs{if@dtl@numgrpsep} is set the first time +% \cs{@dtl@checknumericalloop} encounters the number group +% separator. +% \begin{macrocode} +\newif\if@dtl@numgrpsep +% \end{macrocode} +%\end{macro} +%\begin{macro}{\@dtl@ifDigitOrDecimalSep} +% Check if argument is either a digit or the decimal separator. +%\changes{1.01}{2007 Aug 17}{new} +% \begin{macrocode} +\newcommand*{\@dtl@ifDigitOrDecimalSep}[3]{% +\ifx0#1\relax + #2% +\else + \ifx1#1\relax + #2% + \else + \ifx2#1\relax + #2% + \else + \ifx3#1\relax + #2% + \else + \ifx4#1\relax + #2% + \else + \ifx5#1\relax + #2% + \else + \ifx6#1\relax + #2% + \else + \ifx7#1\relax + #2% + \else + \ifx8#1\relax + #2% + \else + \ifx9#1\relax + #2% + \else + \expandafter\ifx\@dtl@decimal#1\relax + #2% + \else + #3% + \fi + \fi + \fi + \fi + \fi + \fi + \fi + \fi + \fi + \fi +\fi +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\@dtl@checknumericalloop} +% Check numerical loop. This iterates through each character +% until \cs{@nil} is reached, or invalid character found. +% Increments \cs{@dtl@tmpcount} each time it encounters a +% decimal character.\changes{1.01}{2007 Aug 17}{fixed bug caused +% by commands occuring within text being tested} +% \begin{macrocode} +\def\@dtl@checknumericalloop#1#2\@nil{% +\def\@dtl@tmp{#1}% +\ifx\@nnil\@dtl@tmp\relax + \let\@dtl@chcknumnext=\@dtl@checknumericalnoop% +\else + \@dtl@ifDigitOrDecimalSep{#1}{% + \let\@dtl@chcknumnext=\@dtl@checknumericalloop% + \expandafter\ifx\@dtl@decimal#1\relax + \if@dtl@numgrpsep + \ifnum\@dtl@numgrpsepcount=3\relax + \@dtl@numgrpsepcount=-1\relax + \else + \@dtl@datatype=0\relax + \let\@dtl@chcknumnext=\@dtl@checknumericalnoop + \fi + \else + \@dtl@numgrpsepcount=-1\relax + \fi + \else + \ifnum\@dtl@numgrpsepcount=-1\relax + \else + \advance\@dtl@numgrpsepcount by 1\relax + \fi + \fi +}{% +\ifx\@dtl@numbergroupchar\@dtl@tmp\relax + \@dtl@numgrpseptrue + \ifnum\@dtl@numgrpsepcount<3\relax + \@dtl@datatype=0\relax + \let\@dtl@chcknumnext=\@dtl@checknumericalnoop + \else + \@dtl@numgrpsepcount=0\relax + \fi +\else + \@dtl@datatype=0\relax + \let\@dtl@chcknumnext=\@dtl@checknumericalnoop +\fi +}% + \ifx\@dtl@decimal\@dtl@tmp\relax + \ifnum\@dtl@datatype<3\relax + \@dtl@datatype=2\relax + \fi + \advance\@dtl@tmpcount by 1\relax + \ifnum\@dtl@tmpcount>1\relax + \@dtl@datatype=0\relax + \let\@dtl@chcknumnext=\@dtl@checknumericalnoop% + \fi + \fi +\fi +\@dtl@chcknumnext#2\@nil +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\@dtl@checknumericalnoop} +% End loop +% \begin{macrocode} +\def\@dtl@checknumericalnoop#1\@nil#2{} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLifnumerical} +%\begin{definition} +%\cs{DTLifnumerical}\marg{arg}\marg{true part}\marg{false part} +%\end{definition} +% Tests the first argument, if +% its numerical do second argument, otherwise do third argument. +% \begin{macrocode} +\newcommand{\DTLifnumerical}[3]{% +\@dtl@checknumerical{#1}% +\ifnum\@dtl@datatype=0\relax#3\else#2\fi +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLifreal} +%\begin{definition} +%\cs{DTLifreal}\marg{arg}\marg{true part}\marg{false part} +%\end{definition} +% Tests the first argument, if +% it's a real number (not an integer) do second argument, +% otherwise do third argument. +% \begin{macrocode} +\newcommand{\DTLifreal}[3]{% +\@dtl@checknumerical{#1}% +\ifnum\@dtl@datatype=2\relax #2\else #3\fi +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLifint} +%\begin{definition} +%\cs{DTLifint}\marg{arg}\marg{true part}\marg{false part} +%\end{definition} +% Tests the first argument, if +% it's an integer do second argument, +% otherwise do third argument. +% \begin{macrocode} +\newcommand{\DTLifint}[3]{% +\@dtl@checknumerical{#1}% +\ifnum\@dtl@datatype=1\relax #2\else #3\fi +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLifstring} +%\begin{definition} +%\cs{DTLifstring}\marg{arg}\marg{true part}\marg{false part} +%\end{definition} +% Tests the first argument, if +% it's a string do second argument, +% otherwise do third argument. +% \begin{macrocode} +\newcommand{\DTLifstring}[3]{% +\@dtl@checknumerical{#1}% +\ifnum\@dtl@datatype=0\relax #2\else #3\fi +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLifcurrency} +%\begin{definition} +%\cs{DTLifcurrency}\marg{arg}\marg{true part}\marg{false part} +%\end{definition} +% Tests the first argument, if +% it starts with the currency symbol do second argument, +% otherwise do third argument. +% \begin{macrocode} +\newcommand{\DTLifcurrency}[3]{% +\@dtl@checknumerical{#1}% +\ifnum\@dtl@datatype=3\relax #2\else #3\fi +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLifcurrencyunit} +%\begin{definition} +%\cs{DTLifcurrencyunit}\marg{arg}\marg{symbol}\marg{true +% part}\marg{false part} +%\end{definition} +% This tests if \meta{arg} is currency, and uses the currency unit +% \meta{symbol}. If true do third argument, otherwise +% do fourth argument. +% \begin{macrocode} +\newcommand*{\DTLifcurrencyunit}[4]{% +\@dtl@checknumerical{#1}% +\ifnum\@dtl@datatype=3\relax + \ifthenelse{\equal{\@dtl@org@currency}{#2}}{#3}{#4}% +\else + #4% +\fi +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLifcasedatatype} +%\begin{definition} +%\cs{DTLifcasedatatype}\marg{arg}\marg{string case}\marg{int +%case}\marg{real case}\marg{currency case} +%\end{definition} +% If \meta{arg} is a string, do \meta{string case}, if \meta{arg} +% is an integer do \meta{int case}, if \meta{arg} is a real number, +% do \meta{real case}, if \meta{arg} is currency, do \meta{curreny +%case}. +% \begin{macrocode} +\newcommand{\DTLifcasedatatype}[5]{% +\@dtl@checknumerical{#1}% +\ifcase\@dtl@datatype + #2% string +\or + #3% integer +\or + #4% number +\or + #5% currency +\fi +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\dtl@testbothnumerical} +%\begin{definition} +%\cs{dtl@testbothnumerical}\marg{arg1}\marg{arg2} +%\end{definition} +% Tests if both arguments are numerical. This sets +% the conditional \cs{if@dtl@condition}. +% \begin{macrocode} +\newcommand*{\dtl@testbothnumerical}[2]{% +\dtl@ifsingle{#1}{% + \edef\@dtl@tmp{#1}}{% + \def\@dtl@tmp{#1}}% +\expandafter\@dtl@checknumerical\expandafter{\@dtl@tmp}% +\edef\@dtl@firsttype{\number\@dtl@datatype}% +\dtl@ifsingle{#2}{% + \edef\@dtl@tmp{#2}}{% + \def\@dtl@tmp{#2}}% +\expandafter\@dtl@checknumerical\expandafter{\@dtl@tmp}% +\multiply\@dtl@datatype by \@dtl@firsttype\relax +\ifnum\@dtl@datatype>0\relax + \@dtl@conditiontrue +\else + \@dtl@conditionfalse +\fi +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLifnumlt} +%\begin{definition} +%\cs{DTLifnumlt}\marg{num1}\marg{num2}\marg{true part}\marg{false part} +%\end{definition} +% Determines if \marg{num1} $<$ \marg{num2}. Both numbers +% need to have the decimal separator changed to a dot +% to ensure that it works with \cs{FPiflt} +% \begin{macrocode} +\newcommand*{\DTLifnumlt}[4]{% + \DTLconverttodecimal{#1}{\@dtl@numi}% + \DTLconverttodecimal{#2}{\@dtl@numii}% + \FPiflt{\@dtl@numi}{\@dtl@numii}% + #3% + \else + #4% + \fi +} +% \end{macrocode} +%\end{macro} +% +%\label{src:dtlcompare} +%\begin{macro}{\dtlcompare} +%\begin{definition} +%\cs{dtlcompare}\marg{count}\marg{string1}\marg{string2} +%\end{definition} +% Compares \meta{string1} and \meta{string2}, and stores the +% result in the count register \meta{count}. The result may be +% one of: +%\par\vskip\baselineskip\noindent +%\begin{tabular}{rl} +%-1 & if \meta{string1} is considered to be less than +%\meta{string2}\\ +%0 & if \meta{string1} is considered to be the same as +%\meta{string2}\\ +%1 & if \meta{string1} is considered to be greater than +%\meta{string2} +%\end{tabular} +%\par\vskip\baselineskip\noindent +%Note that for the purposes of string comparisons, commands within +%\meta{string1} and \meta{string2} are ignored, except for +%\cs{space} and "~", which are both treated as a space (character +%code 32.) The following +%examples assume that the count register \cs{mycount} has been +%defined as follows: +%\begin{verbatim} +%\newcount\mycount +%\end{verbatim} +%\newcount\mycount\par\noindent +%\textbf{Examples:} +%\begin{enumerate} +%\item +%\begin{verbatim} +%\dtlcompare{\mycount}{Z\"oe}{Zoe}\number\mycount +%\end{verbatim} +%produces: +%\dtlcompare{\mycount}{Z\"oe}{Zoe}\number\mycount, since the accent +%command is ignored. +% +%\item +%\begin{verbatim} +%\dtlcompare{\mycount}{foo}{Foo}\number\mycount +%\end{verbatim} +%produces: +%\dtlcompare{\mycount}{foo}{Foo}\number\mycount, since the comparison +%is case sensitive, however, note the following example: +%\item +%\begin{verbatim} +%\dtlcompare{\mycount}{foo}{\uppercase{f}oo}\number\mycount +%\end{verbatim} +%which produces: +%\dtlcompare{\mycount}{foo}{\uppercase{f}oo}\number\mycount, since +%the \cs{uppercase} command is ignored. +% +%\item You can ``trick'' \cs{dtlcompare} using a command which doesn't +%output any text. Suppose you have defined the following command: +%\begin{verbatim} +%\newcommand*{\noopsort}[1]{} +%\end{verbatim} +%\providecommand*{\noopsort}[1]{} +%then "\noopsort{a}foo" produces the text: \noopsort{a}foo, however +%the following +%\begin{verbatim} +%\dtlcompare{\mycount}{\noopsort{a}foo}{bar}\number\mycount +%\end{verbatim} +%produces: +%\dtlcompare{\mycount}{\noopsort{a}foo}{bar}\number\mycount, +%since the command \cs{noopsort} is disregarded when the comparison +%is made, so \cs{dtlcompare} just compares "{a}foo" with "bar", and +%since "a" is less than "b", the first string is considered to be less +%than the second string. +% +%\item Note that this also means that: +%\begin{verbatim} +%\def\mystr{abc}% +%\dtlcompare{\mycount}{\mystr}{abc}\number\mycount +%\end{verbatim} +%produces: +%\def\mystr{abc}\relax +%\dtlcompare{\mycount}{\mystr}{abc}\number\mycount, since the command +%\cs{mystr} is disregarded, which means that \cs{dtlcompare} is +%comparing an empty string with the string "abc". +% +%\item Spaces count in the comparison: +%\begin{verbatim} +%\dtlcompare{\mycount}{ab cd}{abcd}\number\mycount +%\end{verbatim} +%produces: +%\dtlcompare{\mycount}{ab cd}{abcd}\number\mycount, +%but sequential spaces are treated as a single space: +%\begin{verbatim} +%\dtlcompare{\mycount}{ab cd}{ab cd}\number\mycount +%\end{verbatim} +%produces: +%\dtlcompare{\mycount}{ab cd}{ab cd}\number\mycount. +% +%\item As usual, spaces following command names are ignored, so +%\begin{verbatim} +%\dtlcompare{\mycount}{ab\relax cd}{ab cd}\number\mycount +%\end{verbatim} +%produces: +%\dtlcompare{\mycount}{ab\relax cd}{ab cd}\number\mycount. +% +%\item "~" and \cs{space} are considered to be the same as a +% space: +%\begin{verbatim} +%\dtlcompare{\mycount}{ab cd}{ab~cd}\number\mycount +%\end{verbatim} +%produces: +%\dtlcompare{\mycount}{ab cd}{ab~cd}\number\mycount. +%\end{enumerate} +%\changes{1.01}{2007 Aug 17}{replaces \cs{compare} (no +% longer using compare.tex)} +% \begin{macrocode} +\newcommand*{\dtlcompare}[3]{% +\dtl@subnobrsp{#2}{\@dtl@argA}% +\dtl@subnobrsp{#3}{\@dtl@argB}% +\ifx\@dtl@argA\@empty + \ifx\@dtl@argB\@empty + #1=0\relax + \else + #1=-1\relax + \fi +\else + \ifx\@dtl@argB\@empty + #1=1\relax + \else + \DTLsubstituteall{\@dtl@argA}{ }{\space }% + \DTLsubstituteall{\@dtl@argB}{ }{\space }% + \expandafter\dtl@getfirst\@dtl@argA\end + \let\dtl@firstA=\dtl@first + \let\dtl@restA=\dtl@rest + \expandafter\dtl@getfirst\@dtl@argB\end + \let\dtl@firstB=\dtl@first + \let\dtl@restB=\dtl@rest + \expandafter\dtl@ifsingle\expandafter{\dtl@firstA}{% + \expandafter\dtl@ifsingle\expandafter{\dtl@firstB}{% + \expandafter\dtl@setcharcode\expandafter{\dtl@firstA}{\dtl@codeA}% + \expandafter\dtl@setcharcode\expandafter{\dtl@firstB}{\dtl@codeB}% + \ifnum\dtl@codeA=-1\relax + \ifnum\dtl@codeB=-1\relax + \protected@edef\dtl@donext{% + \noexpand\dtlcompare{\noexpand#1}{\dtl@restA}{\dtl@restB}}% + \dtl@donext + \else + \protected@edef\dtl@donext{% + \noexpand\dtlcompare + {\noexpand#1}{\dtl@restA}{\dtl@firstB\dtl@restB}}% + \dtl@donext + \fi + \else + \ifnum\dtl@codeB=-1\relax + \protected@edef\dtl@donext{% + \noexpand\dtlcompare + {\noexpand#1}{\dtl@firstA\dtl@restA}{\dtl@restB}}% + \dtl@donext + \else + \ifnum\dtl@codeA<\dtl@codeB + #1=-1\relax + \else + \ifnum\dtl@codeA>\dtl@codeB + #1=1\relax + \else + \ifx\dtl@restA\@empty + \ifx\dtl@restB\@empty + #1=0\relax + \else + #1=-1\relax + \fi + \else + \ifx\restB\@empty + #1=1\relax + \else + \protected@edef\dtl@donext{% + \noexpand\dtlcompare + {\noexpand#1}{\dtl@restA}{\dtl@restB}}% + \dtl@donext + \fi + \fi + \fi + \fi + \fi + \fi + }{% + \protected@edef\dtl@donext{% + \noexpand\dtlcompare + {\noexpand#1}{\dtl@firstA\dtl@restA}{\dtl@firstB\dtl@restB}}% + \dtl@donext + }}{% + \protected@edef\dtl@donext{% + \noexpand\dtlcompare + {\noexpand#1}{\dtl@firstA\dtl@restA}{\dtl@firstB\dtl@restB}}% + \dtl@donext + }% + \fi +\fi +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\dtl@getfirst} +% Gets the first object, and stores in \cs{dtl@first}. The remainder +% is stored in \cs{dtl@rest}. +% \begin{macrocode} +\def\dtl@getfirst#1#2\end{% +\def\dtl@first{#1}% +\ifx\dtl@first\@empty + \def\dtl@rest{#2}% +\else + \dtl@ifsingle{#1}{\def\dtl@rest{#2}}{\dtl@getfirst#1#2\end}% +\fi +} +% \end{macrocode} +%\end{macro} +% Count registers to store character codes: +% \begin{macrocode} +\newcount\dtl@codeA +\newcount\dtl@codeB +% \end{macrocode} +%\begin{macro}{\dtl@setcharcode} +%\begin{definition} +%\cs{dtl@setcharcode}\marg{c}\marg{count register} +%\end{definition} +% Sets \meta{count register} to the character code of \meta{c}, or to +% -1 if \meta{c} is a control sequence, unless \meta{c} is either +% \cs{space} or |~| in which case it sets \meta{count register} +% to the character code of the space character. +% \begin{macrocode} +\newcommand*{\dtl@setcharcode}[2]{% +\def\@dtl@tmp{#1}% +\ifx\@dtl@tmp\@empty + #2=-1\relax +\else + \ifx#1\space\relax + #2=`\ \relax + \else + \ifx#1~\relax + #2=`\ \relax + \else + \ifcat\noexpand#1\relax% + #2=-1\relax + \else + #2=`#1\relax + \fi + \fi + \fi +\fi +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\dtl@setlccharcode} +%\begin{definition} +%\cs{dtl@setlccharcode}\marg{c}\marg{count register} +%\end{definition} +% As \cs{dtl@setlccharcode} except it sets \meta{count register} +% to the lower case character code of \meta{c}, unless \meta{c} +% is a control sequence, in which case it does the same as +% \cs{dtl@setcharcode}. +% \begin{macrocode} +\newcommand*{\dtl@setlccharcode}[2]{% +\def\@dtl@tmp{#1}% +\ifx\@dtl@tmp\@empty + #2=-1\relax +\else + \ifx#1\space\relax + #2=`\ \relax + \else + \ifx#1~\relax + #2=`\ \relax + \else + \ifcat\noexpand#1\relax% + #2=-1\relax + \else + #2=\lccode`#1\relax + \fi + \fi + \fi +\fi +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\dtlicompare} +%\begin{definition} +%\cs{dtlicompare}\marg{count}\marg{string1}\marg{string2} +%\end{definition} +% As \cs{dtlcompare} but ignores case. +%\changes{1.01}{2007 Aug 17}{new} +% \begin{macrocode} +\newcommand*{\dtlicompare}[3]{% +\dtl@subnobrsp{#2}{\@dtl@argA}% +\dtl@subnobrsp{#3}{\@dtl@argB}% +\ifx\@dtl@argA\@empty + \ifx\@dtl@argB\@empty + #1=0\relax + \else + #1=-1\relax + \fi +\else + \ifx\@dtl@argB\@empty + #1=1\relax + \else + \DTLsubstituteall{\@dtl@argA}{ }{\space }% + \DTLsubstituteall{\@dtl@argB}{ }{\space }% + \expandafter\dtl@getfirst\@dtl@argA\end + \let\dtl@firstA=\dtl@first + \let\dtl@restA=\dtl@rest + \expandafter\dtl@getfirst\@dtl@argB\end + \let\dtl@firstB=\dtl@first + \let\dtl@restB=\dtl@rest + \expandafter\dtl@ifsingle\expandafter{\dtl@firstA}{% + \expandafter\dtl@ifsingle\expandafter{\dtl@firstB}{% + \expandafter\dtl@setlccharcode\expandafter{\dtl@firstA}{\dtl@codeA}% + \expandafter\dtl@setlccharcode\expandafter{\dtl@firstB}{\dtl@codeB}% + \ifnum\dtl@codeA=-1\relax + \ifnum\dtl@codeB=-1\relax + \protected@edef\dtl@donext{% + \noexpand\dtlicompare{\noexpand#1}{\dtl@restA}{\dtl@restB}}% + \dtl@donext + \else + \protected@edef\dtl@donext{% + \noexpand\dtlicompare + {\noexpand#1}{\dtl@restA}{\dtl@firstB\dtl@restB}}% + \dtl@donext + \fi + \else + \ifnum\dtl@codeB=-1\relax + \protected@edef\dtl@donext{% + \noexpand\dtlicompare + {\noexpand#1}{\dtl@firstA\dtl@restA}{\dtl@restB}}% + \dtl@donext + \else + \ifnum\dtl@codeA<\dtl@codeB + #1=-1\relax + \else + \ifnum\dtl@codeA>\dtl@codeB + #1=1\relax + \else + \ifx\dtl@restA\@empty + \ifx\dtl@restB\@empty + #1=0\relax + \else + #1=-1\relax + \fi + \else + \ifx\restB\@empty + #1=1\relax + \else + \protected@edef\dtl@donext{% + \noexpand\dtlicompare + {\noexpand#1}{\dtl@restA}{\dtl@restB}}% + \dtl@donext + \fi + \fi + \fi + \fi + \fi + \fi + }{% + \protected@edef\dtl@donext{% + \noexpand\dtlicompare + {\noexpand#1}{\dtl@firstA\dtl@restA}{\dtl@firstB\dtl@restB}}% + \dtl@donext + }}{% + \protected@edef\dtl@donext{% + \noexpand\dtlicompare + {\noexpand#1}{\dtl@firstA\dtl@restA}{\dtl@firstB\dtl@restB}}% + \dtl@donext + }% + \fi +\fi +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLifstringlt} +%\begin{definition} +%\cs{DTLifstringlt}\marg{string1}\marg{string2}\marg{true part}\marg{false part} +%\end{definition} +% String comparison (Starred version ignores case) +%\changes{1.01}{2007 Aug 17}{added starred version} +% \begin{macrocode} +\newcommand*{\DTLifstringlt}{\@ifstar\@sDTLifstringlt\@DTLifstringlt} +% \end{macrocode} +% Unstarred version +% \begin{macrocode} +\newcommand*{\@DTLifstringlt}[4]{% +\protected@edef\@dtl@tmpcmp{% + \noexpand\dtlcompare{\noexpand\@dtl@tmpcount}{#1}{#2}}% +\@dtl@tmpcmp +\ifnum\@dtl@tmpcount<0\relax + #3% +\else + #4% +\fi +} +% \end{macrocode} +% Starred version +% \begin{macrocode} +\newcommand*{\@sDTLifstringlt}[4]{% +\protected@edef\@dtl@tmpcmp{% + \noexpand\dtlicompare{\noexpand\@dtl@tmpcount}{#1}{#2}}% +\@dtl@tmpcmp +\ifnum\@dtl@tmpcount<0\relax + #3% +\else + #4% +\fi +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLiflt} +%\begin{definition} +%\cs{DTLiflt}\marg{arg1}\marg{arg2}\marg{true part}\marg{false part} +%\end{definition} +% Does \cs{DTLifnumlt} if both \meta{arg1} and \meta{arg2} are +% numerical, otherwise do \cs{DTLifstringlt} (unstarred version) +% or \cs{DTLifstringlt*} (starred version). +%\changes{1.01}{2007 Aug 17}{added starred version} +% \begin{macrocode} +\newcommand*{\DTLiflt}{\@ifstar\@sDTLiflt\@DTLiflt} +% \end{macrocode} +% Unstarred version +% \begin{macrocode} +\newcommand*{\@DTLiflt}[4]{% +\dtl@testbothnumerical{#1}{#2}% +\if@dtl@condition + \DTLifnumlt{#1}{#2}{#3}{#4}% +\else + \@DTLifstringlt{#1}{#2}{#3}{#4}% +\fi +} +% \end{macrocode} +% Starred version +% \begin{macrocode} +\newcommand*{\@sDTLiflt}[4]{% +\dtl@testbothnumerical{#1}{#2}% +\if@dtl@condition + \DTLifnumlt{#1}{#2}{#3}{#4}% +\else + \@sDTLifstringlt{#1}{#2}{#3}{#4}% +\fi +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLifnumgt} +%\begin{definition} +%\cs{DTLifnumgt}\marg{num1}\marg{num2}\marg{true part}\marg{false part} +%\end{definition} +% Determines if \marg{num1} $>$ \marg{num2}. Both numbers +% need to have the decimal separator changed to a dot +% to ensure that it works with \cs{FPifgt} +% \begin{macrocode} +\newcommand*{\DTLifnumgt}[4]{% + \DTLconverttodecimal{#1}{\@dtl@numi}% + \DTLconverttodecimal{#2}{\@dtl@numii}% + \FPifgt{\@dtl@numi}{\@dtl@numii}% + #3% + \else + #4% + \fi +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLifstringgt} +%\begin{definition} +%\cs{DTLifstringgt}\marg{string1}\marg{string2}\marg{true part}\marg{false part} +%\end{definition} +% String comparison (starred version ignores case) +%\changes{1.01}{2007 Aug 17}{added starred version} +% \begin{macrocode} +\newcommand*{\DTLifstringgt}{\@ifstar\@sDTLifstringgt\@DTLifstringgt} +% \end{macrocode} +% Unstarred version +% \begin{macrocode} +\newcommand*{\@DTLifstringgt}[4]{% +\protected@edef\@dtl@tmpcmp{% + \noexpand\dtlcompare{\noexpand\@dtl@tmpcount}{#1}{#2}}% +\@dtl@tmpcmp +\ifnum\@dtl@tmpcount>0\relax + #3% +\else + #4% +\fi +} +% \end{macrocode} +% Starred version +% \begin{macrocode} +\newcommand*{\@sDTLifstringgt}[4]{% +\protected@edef\@dtl@tmpcmp{% + \noexpand\dtlicompare{\noexpand\@dtl@tmpcount}{#1}{#2}}% +\@dtl@tmpcmp +\ifnum\@dtl@tmpcount>0\relax + #3% +\else + #4% +\fi +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLifgt} +%\begin{definition} +%\cs{DTLifgt}\marg{arg1}\marg{arg2}\marg{true part}\marg{false part} +%\end{definition} +% Does \cs{DTLifnumgt} if both \meta{arg1} and \meta{arg2} are +% numerical, otherwise do \cs{DTLifstringgt} or \cs{DTLifstringgt*}. +%\changes{1.01}{2007 Aug 17}{added starred version} +% \begin{macrocode} +\newcommand*{\DTLifgt}{\@ifstar\@sDTLifgt\@DTLifgt} +% \end{macrocode} +% Unstarred version +% \begin{macrocode} +\newcommand*{\@DTLifgt}[4]{% +\dtl@testbothnumerical{#1}{#2}% +\if@dtl@condition + \DTLifnumgt{#1}{#2}{#3}{#4}% +\else + \@DTLifstringgt{#1}{#2}{#3}{#4}% +\fi +} +% \end{macrocode} +% Starred version +% \begin{macrocode} +\newcommand*{\@sDTLifgt}[4]{% +\dtl@testbothnumerical{#1}{#2}% +\if@dtl@condition + \DTLifnumgt{#1}{#2}{#3}{#4}% +\else + \@sDTLifstringgt{#1}{#2}{#3}{#4}% +\fi +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLifnumeq} +%\begin{definition} +%\cs{DTLifnumeq}\marg{num1}\marg{num2}\marg{true part}\marg{false part} +%\end{definition} +% Determines if \marg{num1} = \marg{num2}. Both numbers +% need to have the decimal separator changed to a dot +% to ensure that it works with \cs{FPifeq} +% \begin{macrocode} +\newcommand*{\DTLifnumeq}[4]{% + \DTLconverttodecimal{#1}{\@dtl@numi}% + \DTLconverttodecimal{#2}{\@dtl@numii}% + \FPifeq{\@dtl@numi}{\@dtl@numii}% + #3% + \else + #4% + \fi +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLifstringeq} +%\begin{definition} +%\cs{DTLifstringeq}\marg{string1}\marg{string2}\marg{true part}\marg{false part} +%\end{definition} +% String comparison (starred version ignores case) +%\changes{1.01}{2007 Aug 17}{added starred version} +% \begin{macrocode} +\newcommand*{\DTLifstringeq}{\@ifstar\@sDTLifstringeq\@DTLifstringeq} +% \end{macrocode} +% Unstarred version +% \begin{macrocode} +\newcommand*{\@DTLifstringeq}[4]{% +\protected@edef\@dtl@tmpcmp{% + \noexpand\dtlcompare{\noexpand\@dtl@tmpcount}{#1}{#2}}% +\@dtl@tmpcmp +\ifnum\@dtl@tmpcount=0\relax + #3% +\else + #4% +\fi +} +% \end{macrocode} +% Starred version +% \begin{macrocode} +\newcommand*{\@sDTLifstringeq}[4]{% +\protected@edef\@dtl@tmpcmp{% + \noexpand\dtlicompare{\noexpand\@dtl@tmpcount}{#1}{#2}}% +\@dtl@tmpcmp +\ifnum\@dtl@tmpcount=0\relax + #3% +\else + #4% +\fi +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLifeq} +%\begin{definition} +%\cs{DTLifeq}\marg{arg1}\marg{arg2}\marg{true part}\marg{false part} +%\end{definition} +% Does \cs{DTLifnumeq} if both \meta{arg1} and \meta{arg2} are +% numerical, otherwise do \cs{DTLifstringeq} or \cs{DTLifstringeq*}. +%\changes{1.01}{2007 Aug 17}{added starred version} +% \begin{macrocode} +\newcommand*{\DTLifeq}{\@ifstar\@sDTLifeq\@DTLifeq} +% \end{macrocode} +% Unstarred version +% \begin{macrocode} +\newcommand*{\@DTLifeq}[4]{% +\dtl@testbothnumerical{#1}{#2}% +\if@dtl@condition + \DTLifnumeq{#1}{#2}{#3}{#4}% +\else + \@DTLifstringeq{#1}{#2}{#3}{#4}% +\fi +} +% \end{macrocode} +% Starred version +% \begin{macrocode} +\newcommand*{\@sDTLifeq}[4]{% +\dtl@testbothnumerical{#1}{#2}% +\if@dtl@condition + \DTLifnumeq{#1}{#2}{#3}{#4}% +\else + \@sDTLifstringeq{#1}{#2}{#3}{#4}% +\fi +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLifSubString} +%\begin{definition} +%\cs{DTLifSubString}\marg{string}\marg{sub string}\marg{true +%part}\marg{false part} +%\end{definition} +% If \meta{sub string} is contained in \meta{string} does +%\meta{true part}, otherwise does \meta{false part}. +%\changes{1.01}{2007 Aug 17}{new} +% \begin{macrocode} +\newcommand*{\DTLifSubString}[4]{% +\protected@edef\@dtl@tmp{\noexpand\dtl@testifsubstring +{#1}{#2}}% +\@dtl@tmp +\if@dtl@condition + #3% +\else + #4% +\fi +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\dtl@testifsubstring} +% \begin{macrocode} +\newcommand*{\dtl@testifsubstring}[2]{% +\dtl@subnobrsp{#1}{\@dtl@argA}% +\dtl@subnobrsp{#2}{\@dtl@argB}% +\ifx\@dtl@argB\@empty + \@dtl@conditiontrue +\else + \ifx\@dtl@argA\@empty + \@dtl@conditionfalse + \else + \dtl@teststartswith{#1}{#2}% + \if@dtl@condition + \else + \DTLsubstituteall{\@dtl@argA}{ }{\space }% + \expandafter\dtl@getfirst\@dtl@argA\end + \expandafter\dtl@ifsingle\expandafter{\dtl@first}{% + \expandafter\dtl@testifsubstring\expandafter{\dtl@rest}{#2}% + }{% + \protected@edef\@dtl@donext{\noexpand\dtl@testifsubstring + {\dtl@first\dtl@rest}{\@dtl@argB}}% + \@dtl@donext + }% + \fi + \fi +\fi +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLifStartsWith} +%\begin{definition} +%\cs{DTLifStartsWith}\marg{string}\marg{substring}\marg{true +%part}\marg{false part} +%\end{definition} +%If \meta{string} starts with \meta{substring}, this does +%\meta{true part}, otherwise it does \meta{false part}. +%\changes{1.01}{2007 Aug 17}{new} +% \begin{macrocode} +\newcommand*{\DTLifStartsWith}[4]{% +\@dtl@conditionfalse +\protected@edef\@dtl@tmp{\noexpand\dtl@teststartswith{#1}{#2}}% +\@dtl@tmp +\if@dtl@condition + #3% +\else + #4% +\fi +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\dtl@teststartswith} +%\begin{definition} +%\cs{dtl@teststartswith}\marg{string}\marg{prefix} +%\end{definition} +% Tests if \meta{string} starts with \meta{prefix}. This sets +% \cs{if@dtl@condition}. +% \begin{macrocode} +\newcommand*{\dtl@teststartswith}[2]{% +\dtl@subnobrsp{#1}{\@dtl@argA}% +\dtl@subnobrsp{#2}{\@dtl@argB}% +\ifx\@dtl@argA\@empty + \ifx\@dtl@argB\@empty + \@dtl@conditiontrue + \else + \@dtl@conditionfalse + \fi +\else + \ifx\@dtl@argB\@empty + \@dtl@conditiontrue + \else + \DTLsubstituteall{\@dtl@argA}{ }{\space }% + \DTLsubstituteall{\@dtl@argB}{ }{\space }% + \expandafter\dtl@getfirst\@dtl@argA\end + \let\dtl@firstA=\dtl@first + \let\dtl@restA=\dtl@rest + \expandafter\dtl@getfirst\@dtl@argB\end + \let\dtl@firstB=\dtl@first + \let\dtl@restB=\dtl@rest + \expandafter\dtl@ifsingle\expandafter{\dtl@firstA}{% + \expandafter\dtl@ifsingle\expandafter{\dtl@firstB}{% + \expandafter\dtl@setcharcode\expandafter{\dtl@firstA}{\dtl@codeA}% + \expandafter\dtl@setcharcode\expandafter{\dtl@firstB}{\dtl@codeB}% + \ifnum\dtl@codeA=-1\relax + \ifnum\dtl@codeB=-1\relax + \protected@edef\dtl@donext{% + \noexpand\dtl@teststartswith{\dtl@restA}{\dtl@restB}}% + \dtl@donext + \else + \protected@edef\dtl@donext{% + \noexpand\dtl@teststartswith + {\dtl@restA}{\dtl@firstB\dtl@restB}}% + \dtl@donext + \fi + \else + \ifnum\dtl@codeB=-1\relax + \protected@edef\dtl@donext{% + \noexpand\dtl@teststartswith + {\dtl@firstA\dtl@restA}{\dtl@restB}}% + \dtl@donext + \else + \ifnum\dtl@codeA=\dtl@codeB + \protected@edef\dtl@donext{% + \noexpand\dtl@teststartswith{\dtl@restA}{\dtl@restB}}% + \dtl@donext + \else + \@dtl@conditionfalse + \fi + \fi + \fi + }{% + \protected@edef\dtl@donext{% + \noexpand\dtl@teststartswith + {\dtl@firstA\dtl@restA}{\dtl@firstB\dtl@restB}}% + \dtl@donext + }}{% + \protected@edef\dtl@donext{% + \noexpand\dtl@teststartswith + {\dtl@firstA\dtl@restA}{\dtl@firstB\dtl@restB}}% + }% + \fi +\fi +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLifnumclosedbetween} +%\begin{definition} +%\cs{DTLifnumclosedbetween}\marg{num}\marg{min}\marg{max}\marg{true part}\marg{false part} +%\end{definition} +% Determines if \meta{min} $\leq$ \meta{num} $\leq$ \meta{max}. +% \begin{macrocode} +\newcommand*{\DTLifnumclosedbetween}[5]{% +\DTLconverttodecimal{#1}{\@dtl@numi}% +\DTLconverttodecimal{#2}{\@dtl@numii}% +\DTLconverttodecimal{#3}{\@dtl@numiii}% +\DTLifFPclosedbetween{\@dtl@numi}{\@dtl@numii}{\@dtl@numiii}{#4}{#5}% +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLifstringclosedbetween} +%\begin{definition} +%\cs{DTLifstringclosedbetween}\marg{string}\marg{min}\marg{max}\marg{true part}\marg{false part} +%\end{definition} +% String comparison (starred version ignores case) +%\changes{1.01}{2007 Aug 17}{added starred version} +% \begin{macrocode} +\newcommand*{\DTLifstringclosedbetween}{% +\@ifstar\@sDTLifstringclosedbetween\@DTLifstringclosedbetween} +% \end{macrocode} +% Unstarred version +% \begin{macrocode} +\newcommand*{\@DTLifstringclosedbetween}[5]{% +\protected@edef\@dtl@tmpcmp{% + \noexpand\dtlcompare{\noexpand\@dtl@tmpcount}{#1}{#2}}% +\@dtl@tmpcmp +\let\@dtl@dovalue\relax +\ifnum\@dtl@tmpcount<0\relax + \def\@dtl@dovalue{#5}% +\fi +\ifx\@dtl@dovalue\relax + \protected@edef\@dtl@tmpcmp{% + \noexpand\dtlcompare{\noexpand\@dtl@tmpcount}{#1}{#3}}% + \@dtl@tmpcmp + \ifnum\@dtl@tmpcount>0\relax + \def\@dtl@dovalue{#5}% + \else + \def\@dtl@dovalue{#4}% + \fi +\fi +\@dtl@dovalue +} +% \end{macrocode} +% Starred version +% \begin{macrocode} +\newcommand*{\@sDTLifstringclosedbetween}[5]{% +\protected@edef\@dtl@tmpcmp{% + \noexpand\dtlicompare{\noexpand\@dtl@tmpcount}{#1}{#2}}% +\@dtl@tmpcmp +\let\@dtl@dovalue\relax +\ifnum\@dtl@tmpcount<0\relax + \def\@dtl@dovalue{#5}% +\fi +\ifx\@dtl@dovalue\relax + \protected@edef\@dtl@tmpcmp{% + \noexpand\dtlicompare{\noexpand\@dtl@tmpcount}{#1}{#3}}% + \@dtl@tmpcmp + \ifnum\@dtl@tmpcount>0\relax + \def\@dtl@dovalue{#5}% + \else + \def\@dtl@dovalue{#4}% + \fi +\fi +\@dtl@dovalue +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLifclosedbetween} +%\begin{definition} +%\cs{DTLifclosedbetween}\marg{arg}\marg{min}\marg{max}\marg{true part}\marg{false part} +%\end{definition} +% Does \cs{DTLifnumclosedbetween} if \marg{arg}, \meta{min} and \meta{max} are +% numerical, otherwise do \cs{DTLifstringclosedbetween} +% or \cs{DTLifstringclosedbetween*}. +%\changes{1.01}{2007 Aug 17}{added starred version} +% \begin{macrocode} +\newcommand*{\DTLifclosedbetween}{% +\@ifstar\@sDTLifclosedbetween\@DTLifclosedbetween} +% \end{macrocode} +% Unstarred version +% \begin{macrocode} +\newcommand*{\@DTLifclosedbetween}[5]{% +\dtl@testbothnumerical{#2}{#3}% +\if@dtl@condition + \dtl@ifsingle{#1}{% + \edef\@dtl@tmp{#1}}{% + \def\@dtl@tmp{#1}}% + \expandafter\@dtl@checknumerical\expandafter{\@dtl@tmp}% + \ifnum\@dtl@datatype>0\relax + \DTLifnumclosedbetween{#1}{#2}{#3}{#4}{#5}% + \else + \@DTLifstringclosedbetween{#1}{#2}{#3}{#4}{#5}% + \fi +\else + \@DTLifstringclosedbetween{#1}{#2}{#3}{#4}{#5}% +\fi +} +% \end{macrocode} +% Starred version +% \begin{macrocode} +\newcommand*{\@sDTLifclosedbetween}[5]{% +\dtl@testbothnumerical{#2}{#3}% +\if@dtl@condition + \dtl@ifsingle{#1}{% + \edef\@dtl@tmp{#1}}{% + \def\@dtl@tmp{#1}}% + \expandafter\@dtl@checknumerical\expandafter{\@dtl@tmp}% + \ifnum\@dtl@datatype>0\relax + \DTLifnumclosedbetween{#1}{#2}{#3}{#4}{#5}% + \else + \@sDTLifstringclosedbetween{#1}{#2}{#3}{#4}{#5}% + \fi +\else + \@sDTLifstringclosedbetween{#1}{#2}{#3}{#4}{#5}% +\fi +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLifnumopenbetween} +%\begin{definition} +%\cs{DTLifnumopenbetween}\marg{num}\marg{min}\marg{max}\marg{true part}\marg{false part} +%\end{definition} +% Determines if \meta{min} $<$ \meta{num} $<$ \meta{max}. +% \begin{macrocode} +\newcommand*{\DTLifnumopenbetween}[5]{% +\DTLconverttodecimal{#1}{\@dtl@numi}% +\DTLconverttodecimal{#2}{\@dtl@numii}% +\DTLconverttodecimal{#3}{\@dtl@numiii}% +\DTLifFPopenbetween{\@dtl@numi}{\@dtl@numii}{\@dtl@numiii}{#4}{#5}% +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLifstringopenbetween} +%\begin{definition} +%\cs{DTLifstringopenbetween}\marg{string}\marg{min}\marg{max}\marg{true part}\marg{false part} +%\end{definition} +% String comparison (starred version ignores case) +%\changes{1.01}{2007 Aug 17}{added starred version} +% \begin{macrocode} +\newcommand*{\DTLifstringopenbetween}{% +\@ifstar\@sDTLifstringopenbetween\@DTLifstringopenbetween} +% \end{macrocode} +% Unstarred version: +% \begin{macrocode} +\newcommand*{\@DTLifstringopenbetween}[5]{% +\protected@edef\@dtl@tmpcmp{% + \noexpand\dtlcompare{\noexpand\@dtl@tmpcount}{#1}{#2}}% +\@dtl@tmpcmp +\let\@dtl@dovalue\relax +\ifnum\@dtl@tmpcount>0\relax +\else + \def\@dtl@dovalue{#5}% +\fi +\ifx\@dtl@dovalue\relax + \protected@edef\@dtl@tmpcmp{% + \noexpand\dtlcompare{\noexpand\@dtl@tmpcount}{#1}{#3}}% + \@dtl@tmpcmp + \ifnum\@dtl@tmpcount<0\relax + \def\@dtl@dovalue{#4}% + \else + \def\@dtl@dovalue{#5}% + \fi +\fi +\@dtl@dovalue +} +% \end{macrocode} +% Starred version +% \begin{macrocode} +\newcommand*{\@sDTLifstringopenbetween}[5]{% +\protected@edef\@dtl@tmpcmp{% + \noexpand\dtlicompare{\noexpand\@dtl@tmpcount}{#1}{#2}}% +\@dtl@tmpcmp +\let\@dtl@dovalue\relax +\ifnum\@dtl@tmpcount>0\relax +\else + \def\@dtl@dovalue{#5}% +\fi +\ifx\@dtl@dovalue\relax + \protected@edef\@dtl@tmpcmp{% + \noexpand\dtlicompare{\noexpand\@dtl@tmpcount}{#1}{#3}}% + \@dtl@tmpcmp + \ifnum\@dtl@tmpcount<0\relax + \def\@dtl@dovalue{#4}% + \else + \def\@dtl@dovalue{#5}% + \fi +\fi +\@dtl@dovalue +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLifopenbetween} +%\begin{definition} +%\cs{DTLifopenbetween}\marg{arg}\marg{min}\marg{max}\marg{true part}\marg{false part} +%\end{definition} +% Does \cs{DTLifnumopenbetween} if \marg{arg}, \meta{min} and \meta{max} are +% numerical, otherwise do \cs{DTLifstringopenbetween} +% or \cs{DTLifstringopenbetween*}. +%\changes{1.01}{2007 Aug 17}{added starred version} +% \begin{macrocode} +\newcommand*{\DTLifopenbetween}{% +\@ifstar\@sDTLifopenbetween\@DTLifopenbetween} +% \end{macrocode} +% Unstarred version +% \begin{macrocode} +\newcommand*{\@DTLifopenbetween}[5]{% +\dtl@testbothnumerical{#2}{#3}% +\if@dtl@condition + \dtl@ifsingle{#1}{% + \edef\@dtl@tmp{#1}}{% + \def\@dtl@tmp{#1}}% + \expandafter\@dtl@checknumerical\expandafter{\@dtl@tmp}% + \ifnum\@dtl@datatype>0\relax + \DTLifnumopenbetween{#1}{#2}{#3}{#4}{#5}% + \else + \@DTLifstringopenbetween{#1}{#2}{#3}{#4}{#5}% + \fi +\else + \@DTLifstringopenbetween{#1}{#2}{#3}{#4}{#5}% +\fi +} +% \end{macrocode} +% Starred version +% \begin{macrocode} +\newcommand*{\@sDTLifopenbetween}[5]{% +\dtl@testbothnumerical{#2}{#3}% +\if@dtl@condition + \dtl@ifsingle{#1}{% + \edef\@dtl@tmp{#1}}{% + \def\@dtl@tmp{#1}}% + \expandafter\@dtl@checknumerical\expandafter{\@dtl@tmp}% + \ifnum\@dtl@datatype>0\relax + \DTLifnumopenbetween{#1}{#2}{#3}{#4}{#5}% + \else + \@sDTLifstringopenbetween{#1}{#2}{#3}{#4}{#5}% + \fi +\else + \@sDTLifstringopenbetween{#1}{#2}{#3}{#4}{#5}% +\fi +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLifFPopenbetween} +%\begin{definition} +%\cs{DTLifFPopenbetween}\marg{num}\marg{min}\marg{max}\marg{true part}\marg{false part} +%\end{definition} +% Determines if \meta{min} $<$ \meta{num} $<$ \meta{max} where +% all arguments are in standard fixed point notation. +% \begin{macrocode} +\newcommand*{\DTLifFPopenbetween}[5]{% + \let\@dtl@dovalue\relax + \FPifgt{#1}{#2}% + \else + \def\@dtl@dovalue{#5}% + \fi + \FPiflt{#1}{#3}% + \ifx\@dtl@dovalue\relax + \def\@dtl@dovalue{#4}% + \fi + \else + \def\@dtl@dovalue{#5}% + \fi +\@dtl@dovalue +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLifFPclosedbetween} +%\begin{definition} +%\cs{DTLifFPclosedbetween}\marg{num}\marg{min}\marg{max}\marg{true part}\marg{false part} +%\end{definition} +% Determines if \meta{min} $\leq$ \meta{num} $\leq$ \meta{max}. +% \begin{macrocode} +\newcommand*{\DTLifFPclosedbetween}[5]{% + \let\@dtl@dovalue\relax + \FPifgt{#1}{#3}% + \def\@dtl@dovalue{#5}% + \fi + \FPiflt{#1}{#2}% + \ifx\@dtl@dovalue\relax + \def\@dtl@dovalue{#5}% + \fi + \else + \def\@dtl@dovalue{#4}% + \fi +\@dtl@dovalue +} +% \end{macrocode} +%\end{macro} +% +% The following conditionals are only meant to be used within +% \cs{DTLforeach} as they depend on the counter +% \texttt{DTLrow}\meta{n}. +% +%\begin{macro}{\DTLiffirstrow} +%\begin{definition} +%\cs{DTLiffirstrow}\marg{true part}\marg{false part} +%\end{definition} +% Test if the current row is the first row. (This takes +% \meta{condition}, the optional argument of \cs{DTLforeach}, +% into account.) +% \begin{macrocode} +\newcommand{\DTLiffirstrow}[2]{% +\ifnum\dtlforeachlevel=0\relax + \PackageError{datatool}{\string\DTLiffirstrow\space can only + be used inside \string\DTLforeach}{}% +\else +\expandafter\ifnum\csname c@DTLrow\romannumeral +\dtlforeachlevel\endcsname +=1\relax#1\else#2\fi +\fi} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLiflastrow} +%\begin{definition} +%\cs{DTLiflastrow}\marg{true part}\marg{false part} +%\end{definition} +% Checks if the current row is the last row of the database. +% It doesn't take the condition (the optional argument of +% \cs{DTLforeach}) into account, so its possible it may never +% do \meta{true part}, as the last row of the database may not +% meet the condition. It is therefore not very useful and is +% confusing since it behaves differently to \cs{DTLiffirstrow} +% which does take the condition into account, so I have removed +% its description from the main part of the manual. If you need +% to use the optional argument of \cs{DTLforeach}, you will first +% have to iterate through the database to count up the number +% of rows which meet the condition, and then do another pass, +% checking if the current row has reached that number. +% This command requires at least v1.02 of the \sty{xfor} package. +%\changes{1.01}{2007 Aug 17}{fixed bug} +% \begin{macrocode} +\newcommand{\DTLiflastrow}[2]{% +\ifnum\dtlforeachlevel=0\relax + \PackageError{datatool}{\string\DTLiflastrow\space can only + be used inside \string\DTLforeach}{}% +\else +\ifx\@dtl@nextrow\@nnil +#1\else #2\fi +\fi +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLifoddrow} +%\begin{definition} +%\cs{DTLifoddrow}\marg{true part}\marg{false part} +%\end{definition} +% Determines whether the current row is odd (takes the optional +% argument of \cs{DTLforeach} into account.) +% \begin{macrocode} +\newcommand{\DTLifoddrow}[2]{% +\ifnum\dtlforeachlevel=0\relax + \PackageError{datatool}{\string\DTLifoddrow\space can only + be used inside \string\DTLforeach}{}% +\else +\expandafter\ifodd\csname c@DTLrow\romannumeral +\dtlforeachlevel\endcsname +#1\else #2\fi +\fi +} +% \end{macrocode} +%\end{macro} +% +% \subsection{ifthen Conditionals} +% The following commands provide conditionals \cs{DTLis}\ldots\ +% which can be used in \cs{ifthenelse}. First need to define +% a new conditional: +%\begin{macro}{\if@dtl@condition} +% \begin{macrocode} +\newif\if@dtl@condition +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\dtl@testlt} +% Command to test if first argument is less than second argument. +% If either argument is a string, a case sensitive string comparison +% is used instead. +% This sets \cs{if@dtl@condition}. +% \begin{macrocode} +\newcommand*{\dtl@testlt}[2]{% +\DTLiflt{#1}{#2}{\@dtl@conditiontrue}{\@dtl@conditionfalse}} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLislt} +% Provide conditional command for use in \cs{ifthenelse} +% \begin{macrocode} +\newcommand*{\DTLislt}[2]{% +\TE@throw\noexpand\dtl@testlt{#1}{#2}\noexpand\if@dtl@condition} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\dtl@testiclt} +% Command to test if first argument is less than second argument. +% If either argument is a string, a case insensitive string comparison +% is used instead. +% This sets \cs{if@dtl@condition}. +% \begin{macrocode} +\newcommand*{\dtl@testiclt}[2]{% +\@sDTLiflt{#1}{#2}{\@dtl@conditiontrue}{\@dtl@conditionfalse}} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLisilt} +% Provide conditional command for use in \cs{ifthenelse} +%\changes{1.01}{2007 Aug 17}{new} +% \begin{macrocode} +\newcommand*{\DTLisilt}[2]{% +\TE@throw\noexpand\dtl@testiclt{#1}{#2}\noexpand\if@dtl@condition} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\dtl@testgt} +% Command to test if first number is greater than second number. +% This sets \cs{if@dtl@condition}. +% \begin{macrocode} +\newcommand*{\dtl@testgt}[2]{% +\DTLifgt{#1}{#2}{\@dtl@conditiontrue}{\@dtl@conditionfalse}} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLisgt} +% Provide conditional command for use in \cs{ifthenelse} +% \begin{macrocode} +\newcommand*{\DTLisgt}[2]{% +\TE@throw\noexpand\dtl@testgt{#1}{#2}\noexpand\if@dtl@condition} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\dtl@testicgt} +% Command to test if first number is greater than second number +% (ignores case). +% This sets \cs{if@dtl@condition}. +% \begin{macrocode} +\newcommand*{\dtl@testicgt}[2]{% +\@sDTLifgt{#1}{#2}{\@dtl@conditiontrue}{\@dtl@conditionfalse}} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLisigt} +% Provide conditional command for use in \cs{ifthenelse} +%\changes{1.01}{2007 Aug 17}{new} +% \begin{macrocode} +\newcommand*{\DTLisigt}[2]{% +\TE@throw\noexpand\dtl@testicgt{#1}{#2}\noexpand\if@dtl@condition} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\dtl@testeq} +% Command to test if first number is equal to the second number. +% This sets \cs{if@dtl@condition}. +% \begin{macrocode} +\newcommand*{\dtl@testeq}[2]{% +\DTLifeq{#1}{#2}{\@dtl@conditiontrue}{\@dtl@conditionfalse}} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLiseq} +% Provide conditional command for use in \cs{ifthenelse} +% \begin{macrocode} +\newcommand*{\DTLiseq}[2]{% +\TE@throw\noexpand\dtl@testeq{#1}{#2}\noexpand\if@dtl@condition} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\dtl@testiceq} +% Command to test if first number is equal to the second number +% (ignores case). +% This sets \cs{if@dtl@condition}. +% \begin{macrocode} +\newcommand*{\dtl@testiceq}[2]{% +\@sDTLifeq{#1}{#2}{\@dtl@conditiontrue}{\@dtl@conditionfalse}} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLisieq} +% Provide conditional command for use in \cs{ifthenelse} +%\changes{1.01}{2007 Aug 17}{new} +% \begin{macrocode} +\newcommand*{\DTLisieq}[2]{% +\TE@throw\noexpand\dtl@testiceq{#1}{#2}\noexpand\if@dtl@condition} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLisSubString} +% Tests if second argument is contained in first argument. +%\changes{1.01}{2007 Aug 17}{new} +% \begin{macrocode} +\newcommand*{\DTLisSubString}[2]{% +\TE@throw\noexpand\dtl@testifsubstring{#1}{#2}% +\noexpand\if@dtl@condition} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLisPrefix} +% Tests if first argument starts with second argument. +%\changes{1.01}{2007 Aug 17}{new} +% \begin{macrocode} +\newcommand*{\DTLisPrefix}[2]{% +\TE@throw\noexpand\dtl@teststartswith{#1}{#2}% +\noexpand\if@dtl@condition} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\dtl@testclosedbetween} +% Command to test if first value lies between second and third +% values. (End points included, case sensitive.) +% This sets \cs{if@dtl@condition}. +% \begin{macrocode} +\newcommand*{\dtl@testclosedbetween}[3]{% +\DTLifclosedbetween{#1}{#2}{#3}{\@dtl@conditiontrue}{\@dtl@conditionfalse}} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLisclosedbetween} +% Provide conditional command for use in \cs{ifthenelse} +% \begin{macrocode} +\newcommand*{\DTLisclosedbetween}[3]{% +\TE@throw\noexpand\dtl@testclosedbetween{#1}{#2}{#3}% +\noexpand\if@dtl@condition} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\dtl@testiclosedbetween} +% Command to test if first value lies between second and third +% values. (End points included, case ignored.) +% This sets \cs{if@dtl@condition}. +% \begin{macrocode} +\newcommand*{\dtl@testiclosedbetween}[3]{% +\@sDTLifclosedbetween{#1}{#2}{#3}{\@dtl@conditiontrue}{\@dtl@conditionfalse}} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLisiclosedbetween} +% Provide conditional command for use in \cs{ifthenelse} +%\changes{1.01}{2007 Aug 17}{new} +% \begin{macrocode} +\newcommand*{\DTLisiclosedbetween}[3]{% +\TE@throw\noexpand\dtl@testiclosedbetween{#1}{#2}{#3}% +\noexpand\if@dtl@condition} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\dtl@testopenbetween} +% Command to test if first value lies between second and third +% values. (End points excluded, case sensitive.) +% This sets \cs{if@dtl@condition}. +% \begin{macrocode} +\newcommand*{\dtl@testopenbetween}[3]{% +\DTLifopenbetween{#1}{#2}{#3}{\@dtl@conditiontrue +}{\@dtl@conditionfalse}} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLisopenbetween} +% Provide conditional command for use in \cs{ifthenelse} +% \begin{macrocode} +\newcommand*{\DTLisopenbetween}[3]{% +\TE@throw\noexpand\dtl@testopenbetween{#1}{#2}{#3}% +\noexpand\if@dtl@condition} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\dtl@testiopenbetween} +% Command to test if first value lies between second and third +% values. (End points excluded, case ignored.) +% This sets \cs{if@dtl@condition}. +% \begin{macrocode} +\newcommand*{\dtl@testiopenbetween}[3]{% +\@sDTLifopenbetween{#1}{#2}{#3}{\@dtl@conditiontrue +}{\@dtl@conditionfalse}} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLisiopenbetween} +% Provide conditional command for use in \cs{ifthenelse} +%\changes{1.01}{2007 Aug 17}{new} +% \begin{macrocode} +\newcommand*{\DTLisiopenbetween}[3]{% +\TE@throw\noexpand\dtl@testiopenbetween{#1}{#2}{#3}% +\noexpand\if@dtl@condition} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\dtl@testclosedbetween} +% Command to test if first number lies between second and third +% numbers. (End points included, all arguments are fixed point +% numbers in standard format.) This sets \cs{if@dtl@condition}. +% \begin{macrocode} +\newcommand*{\dtl@testFPclosedbetween}[3]{% +\DTLifFPclosedbetween{#1}{#2}{#3}% +{\@dtl@conditiontrue}{\@dtl@conditionfalse}} +% \end{macrocode} +%\end{macro} +% Provide conditional command for use in \cs{ifthenelse} +%\begin{macro}{\DTLisFPclosedbetween} +% \begin{macrocode} +\newcommand*{\DTLisFPclosedbetween}[3]{% +\TE@throw\noexpand\dtl@testFPclosedbetween{#1}{#2}{#3}% +\noexpand\if@dtl@condition} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\dtl@testopenbetween} +% Command to test if first number lies between second and third +% numbers. (End points excluded, all arguments are fixed point +% numbers in standard format.) This sets \cs{if@dtl@condition}. +% \begin{macrocode} +\newcommand*{\dtl@testFPopenbetween}[3]{% +\DTLifFPopenbetween{#1}{#2}{#3}{\@dtl@conditiontrue}{\@dtl@conditionfalse}} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLisFPopenbetween} +% Provide conditional command for use in \cs{ifthenelse} +% \begin{macrocode} +\newcommand*{\DTLisFPopenbetween}[3]{% +\TE@throw\noexpand\dtl@testFPopenbetween{#1}{#2}{#3}% +\noexpand\if@dtl@condition} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\dtl@testFPislt} +% Command to test if first number is less than second +% number where both numbers are in standard format. +% This sets \cs{if@dtl@condition}. +% \begin{macrocode} +\newcommand*{\dtl@testFPislt}[2]{% +\FPiflt{#1}{#2}\@dtl@conditiontrue\else\@dtl@conditionfalse\fi} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLisFPlt} +% Provide conditional command for use in \cs{ifthenelse} +% \begin{macrocode} +\newcommand*{\DTLisFPlt}[2]{% +\TE@throw\noexpand\dtl@testFPislt{#1}{#2}% +\noexpand\if@dtl@condition} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\dtl@testFPisgt} +% Command to test if first number is greater than second +% number where both numbers are in standard format. +% This sets \cs{if@dtl@condition}. +% \begin{macrocode} +\newcommand*{\dtl@testFPisgt}[2]{% +\FPifgt{#1}{#2}\@dtl@conditiontrue\else\@dtl@conditionfalse\fi} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLisFPgt} +% Provide conditional command for use in \cs{ifthenelse} +% \begin{macrocode} +\newcommand*{\DTLisFPgt}[2]{% +\TE@throw\noexpand\dtl@testFPisgt{#1}{#2}% +\noexpand\if@dtl@condition} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\dtl@testFPiseq} +% Command to test if two numbers are equal, where both numbers +% are in standard decimal format +% \begin{macrocode} +\newcommand*{\dtl@testFPiseq}[2]{% +\FPifeq{#1}{#2}\@dtl@conditiontrue\else\@dtl@conditionfalse\fi} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLisFPeq} +% Provide conditional command for use in \cs{ifthenelse} +% \begin{macrocode} +\newcommand*{\DTLisFPeq}[2]{% +\TE@throw\noexpand\dtl@testFPiseq{#1}{#2}% +\noexpand\if@dtl@condition} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\dtl@testFPislteq} +% Command to test if first number is less than or equal to second +% number where both numbers are in standard format. +% This sets \cs{if@dtl@condition}. +% \begin{macrocode} +\newcommand*{\dtl@testFPislteq}[2]{% +\FPiflt{#1}{#2}\@dtl@conditiontrue\else\@dtl@conditionfalse\fi +\if@dtl@condition +\else + \dtl@testFPiseq{#1}{#2}% +\fi +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLisFPlteq} +% Provide conditional command for use in \cs{ifthenelse} +% \begin{macrocode} +\newcommand*{\DTLisFPlteq}[2]{% +\TE@throw\noexpand\dtl@testFPislteq{#1}{#2}% +\noexpand\if@dtl@condition} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\dtl@testFPisgteq} +% Command to test if first number is greater than or equal to second +% number where both numbers are in standard format. +% This sets \cs{if@dtl@condition}. +% \begin{macrocode} +\newcommand*{\dtl@testFPisgteq}[2]{% +\FPifgt{#1}{#2}\@dtl@conditiontrue\else\@dtl@conditionfalse\fi +\if@dtl@condition +\else + \dtl@testFPiseq{#1}{#2}% +\fi +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLisFPgteq} +% Provide conditional command for use in \cs{ifthenelse} +% \begin{macrocode} +\newcommand*{\DTLisFPgteq}[2]{% +\TE@throw\noexpand\dtl@testFPisgteq{#1}{#2}% +\noexpand\if@dtl@condition} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\dtl@teststring} +% Command to test if argument is a string. This sets +% \cs{if@dtl@condition} +% \begin{macrocode} +\newcommand*{\dtl@teststring}[1]{% +\DTLifstring{#1}{\@dtl@conditiontrue}{\@dtl@conditionfalse}} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLisstring} +% Provide conditional command for use in \cs{ifthenelse} +% \begin{macrocode} +\newcommand*{\DTLisstring}[1]{% +\TE@throw\noexpand\dtl@teststring{#1}\noexpand\if@dtl@condition} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\dtl@testnumerical} +% Command to test if argument is a numerical. This sets +% \cs{if@dtl@condition} +% \begin{macrocode} +\newcommand*{\dtl@testnumerical}[1]{% +\DTLifnumerical{#1}{\@dtl@conditiontrue}{\@dtl@conditionfalse}% +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLisnumerical} +% Provide conditional command for use in \cs{ifthenelse} +% \begin{macrocode} +\newcommand*{\DTLisnumerical}[1]{% +\TE@throw\noexpand\dtl@testnumerical{#1}\noexpand\if@dtl@condition} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\dtl@testint} +% Command to test if argument is an integer. This sets +% \cs{if@dtl@condition} +% \begin{macrocode} +\newcommand*{\dtl@testint}[1]{% +\DTLifint{#1}{\@dtl@conditiontrue}{\@dtl@conditionfalse}} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLisint} +% Provide conditional command for use in \cs{ifthenelse} +% \begin{macrocode} +\newcommand*{\DTLisint}[1]{% +\TE@throw\noexpand\dtl@testint{#1}\noexpand\if@dtl@condition} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\dtl@testreal} +% Command to test if argument is a real. This sets +% \cs{if@dtl@condition} +% \begin{macrocode} +\newcommand*{\dtl@testreal}[1]{% +\DTLifreal{#1}{\@dtl@conditiontrue}{\@dtl@conditionfalse}} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLisreal} +% Provide conditional command for use in \cs{ifthenelse} +% \begin{macrocode} +\newcommand*{\DTLisreal}[1]{% +\TE@throw\noexpand\dtl@testreal{#1}\noexpand\if@dtl@condition} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\dtl@testcurrency} +% Command to test if argument is a currency. This sets +% \cs{if@dtl@condition} +% \begin{macrocode} +\newcommand*{\dtl@testcurrency}[1]{% +\DTLifcurrency{#1}{\@dtl@conditiontrue}{\@dtl@conditionfalse}} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLiscurrency} +% Provide conditional command for use in \cs{ifthenelse} +% \begin{macrocode} +\newcommand*{\DTLiscurrency}[1]{% +\TE@throw\noexpand\dtl@testcurrency{#1}\noexpand\if@dtl@condition} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\dtl@testcurrencyunit} +% Command to test if argument is a currency with given unit. This sets +% \cs{if@dtl@condition} +% \begin{macrocode} +\newcommand*{\dtl@testcurrencyunit}[2]{% +\DTLifcurrencyunit{#1}{#2}{\@dtl@conditiontrue}{\@dtl@conditionfalse}} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLiscurrencyunit} +% Provide conditional command for use in \cs{ifthenelse} +% \begin{macrocode} +\newcommand*{\DTLiscurrencyunit}[2]{% +\TE@throw\noexpand\dtl@testcurrencyunit{#1}{#2}% +\noexpand\if@dtl@condition} +% \end{macrocode} +%\end{macro} +% +% \subsection{Defining New Databases} +% A database is stored internally as a list of lists, where each list +% is a row of data. The data is stored as a comma separated list of +% \marg{id}\marg{value} pairs, where \meta{id} is an +% identifier +% and \meta{value} is the value. +% +%\begin{macro}{\DTLnewdb} +% \cs{DTLnewdb}\marg{name} +% initialises a database called \meta{name}. The keys associated +% with this database are stored in \cs{dtlkeys@}\meta{name} +% A new count register \cs{dtlrows@}\meta{db name} is created. +% This stores the total number of rows in the data base. +% \begin{macrocode} +\newcommand*{\DTLnewdb}[1]{% +\DTLifdbexists{#1}{% +\PackageError{datatool}{Database `#1' already exists}{}}{% +\dtl@message{Creating database `#1'}% +\expandafter\gdef\csname dtldb@#1\endcsname{}% +\expandafter\gdef\csname dtlkeys@#1\endcsname{}% +\expandafter\global\expandafter\newcount\csname dtlrows@#1\endcsname}} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLrowcount} +%\begin{definition} +% \cs{DTLrowcount}\marg{db name} +%\end{definition} +% The number of rows in the database called \meta{db name}. +% \begin{macrocode} +\newcommand*{\DTLrowcount}[1]{% +\expandafter\number\csname dtlrows@#1\endcsname} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLifdbempty} +%\begin{definition} +% \cs{DTLifempty}\marg{name}\marg{true part}\marg{false part} +%\end{definition} +% Check if named database is empty (i.e.\ no rows have been added.) +% \begin{macrocode} +\newcommand{\DTLifdbempty}[3]{% +\DTLifdbexists{#1}{% +\expandafter\ifx\csname dtldb@#1\endcsname\@empty + #2% +\else + #3% +\fi}{% +\PackageError{Database `#1' doesn't exist}{}{}}} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLnewrow} +%\begin{definition} +% \cs{DTLnewrow}\marg{db name} +%\end{definition} +% Add a new row to named database. +% \begin{macrocode} +\newcommand*{\DTLnewrow}[1]{% +\DTLifdbempty{#1}{% + \expandafter\gdef\csname dtldb@#1\endcsname{{}}% + \expandafter\global\expandafter\advance + \csname dtlrows@#1\endcsname by 1\relax + \dtl@message{New row added to database `#1'}% +}{% + \expandafter\let\expandafter\@dtl@olddb\csname dtldb@#1\endcsname% + \expandafter\toks@\expandafter{\@dtl@olddb,{}}% + \expandafter\xdef\csname dtldb@#1\endcsname{\the\toks@}% + \expandafter\global\expandafter\advance + \csname dtlrows@#1\endcsname by 1\relax + \dtl@message{New row added to database `#1'}% +}} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLnewdbentry} +%\begin{definition} +% \cs{DTLnewdbentry}\marg{db name}\marg{id}\marg{value}. +%\end{definition} +% Adds an entry to the last row (adds new row if database is empty.) +% +% When a new entry is added, the control sequence +% \cs{@dtl@idtype@}\meta{db name}\texttt{@}\meta{id} is checked. +% This keeps track of the type of all the entries with the given ID +% for the given database. If this control +% sequence doesn't exist, a new one is created, and set to the +% relevant type: 0 (string), 1 (int) or 2 (real). If it exists, +% then it is set as follows: if has a value of 0 (string), it +% remains unchanged. If it has another value, then it is set to +% 2 (real) if it was either 1 or 2 and \meta{value} is 2, it is +% set to 1 if \meta{value} is 1, otherwise it remains unchanged. +% \begin{macrocode} +\newcommand{\DTLnewdbentry}[3]{% +% \end{macrocode} +% Set \cs{@dtl@dbvalue} to the value of this entry. +% \begin{macrocode} +\@dtl@toks{#3}% +\edef\@dtl@dbvalue{\the\@dtl@toks}% +% \end{macrocode} +% Set \cs{@dtl@dbid} to the entry ID. This uses \cs{edef} to allow +% for the ID to be stored in a control sequence. +% \begin{macrocode} +\edef\@dtl@dbid{#2}% +% \end{macrocode} +% Set up the correct entry format: +% \begin{macrocode} +\edef\@dtl@dbentry{{\@dtl@dbid}{\the\@dtl@toks}}% +% \end{macrocode} +% If database is empty, add new row. +% \begin{macrocode} +\DTLifdbempty{#1}{\DTLnewrow{#1}}{}% +% \end{macrocode} +% Add the entry to the last row of the database: +% Split the database into the last row +% (\cs{@dtl@dblastrow}), and everything except the last row +% (\cs{@dtl@dbrest}.) +% \begin{macrocode} +\expandafter\dtl@choplast\expandafter{% +\csname dtldb@#1\endcsname}{\@dtl@dbrest}{\@dtl@dblastrow}% +% \end{macrocode} +% Check if the last row already contains an entry with this ID. +% If so, generate an error, otherwise append this entry to the +% row, and reconstruct database list. +% \begin{macrocode} +\dtl@ifrowcontains{#2}{\@dtl@dblastrow}{% +\PackageError{datatool}{Can't add entry with ID `#2' to current +row of database `#1'}{There is already an entry with this ID on +the current row}}{% +% \end{macrocode} +% Append entry to last row +% \begin{macrocode} +\expandafter\@dtl@toks\expandafter{\@dtl@dbentry}% +\ifthenelse{\equal{}{\@dtl@dblastrow}}{% + \edef\@dtl@dblastrow{\the\@dtl@toks}% +}{% + \expandafter\toks@\expandafter{\@dtl@dblastrow}% + \edef\@dtl@dblastrow{\the\toks@,\the\@dtl@toks}% +}% +% \end{macrocode} +% Reconstruct list. +% \begin{macrocode} +\expandafter\@dtl@toks\expandafter{\@dtl@dblastrow}% +\ifthenelse{\equal{}{\@dtl@dbrest}}{% + \expandafter\long\expandafter\xdef\csname dtldb@#1\endcsname{% + {\the\@dtl@toks}}% +}{% + \expandafter\toks@\expandafter{\@dtl@dbrest}% + \expandafter\long\expandafter\xdef\csname dtldb@#1\endcsname{% + \the\toks@,{\the\@dtl@toks}}% +}% +% \end{macrocode} +% Set the keys +% \begin{macrocode} +\@dtl@setidtype{#1}{#2}{#3}% +\expandafter\@dtl@setkeys\expandafter{#2}{#1}% +}% +\dtl@message{Added #2\space -> #3\space to database `#1'}% +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\@dtl@setidtype} +%\begin{definition} +% \cs{@dtl@setidtype}\marg{db name}\marg{id}\marg{value} +%\end{definition} +% Set the type for \meta{id} according to \meta{value}. +% If \meta{value} is empty, leave \cs{@dtl@idtype}\meta{id} +% unchanged (if defined) or define as empty if not defined. +%\changes{1.01}{2007 Aug 17}{Added currency check} +%\changes{1.01}{2007 Aug 17}{Fixed bug when setting +% \cs{@dtl@tmpcount}} +% \begin{macrocode} +\newcommand{\@dtl@setidtype}[3]{% +% \end{macrocode} +% Check the data type of this value. +% \begin{macrocode} +\@dtl@checknumerical{#3}% +% \end{macrocode} +% Store value if \cs{@dtl@value} to make it easier to test if it +% is empty. +% \begin{macrocode} +\def\@dtl@value{#3}% +% \end{macrocode} +% Determine if this key already has a data type assigned to it. +% \begin{macrocode} +\@ifundefined{@dtl@idtype@#1@#2}{% +% \end{macrocode} +% This key doesn't have an associated data type, so set it to +% this value's data type, unless the value is empty. +% \begin{macrocode} +\ifx\@dtl@value\@empty + \expandafter\gdef\csname @dtl@idtype@#1@#2\endcsname{}% +\else + \expandafter\xdef\csname @dtl@idtype@#1@#2\endcsname{% + \the\@dtl@datatype}% +\fi +}{% +% \end{macrocode} +% This key already has an associated data type, but may need updating. +% \begin{macrocode} +\ifx\@dtl@value\@empty +% \end{macrocode} +% The value is empty, so do nothing. +% \begin{macrocode} +\else + \expandafter\ifx\csname @dtl@idtype@#1@#2\endcsname\@empty +% \end{macrocode} +% The data type is currently unset (all previous values for this +% key were empty) so set the data type for this key to the data type +% of the given value. +% \begin{macrocode} + \expandafter\xdef\csname @dtl@idtype@#1@#2\endcsname{% + \the\@dtl@datatype}% + \else +% \end{macrocode} +% Store the data type currently associated with this key in +% \cs{@dtl@tmpcount}. +% \begin{macrocode} + \expandafter\@dtl@tmpcount\expandafter= + \csname @dtl@idtype@#1@#2\endcsname\relax +% \end{macrocode} +% Determine whether to update the data type associated with this key. +% \begin{macrocode} + \ifcase\@dtl@tmpcount +% \end{macrocode} +% The current data type is a string, so leave as it is +% (string overrides all the other types.) +% \begin{macrocode} + \or +% \end{macrocode} +% The current data type is an int, so set the data type of the given +% value (all other data types override int.) +% \begin{macrocode} + \expandafter\xdef\csname @dtl@idtype@#1@#2\endcsname{% + \the\@dtl@datatype}% + \or +% \end{macrocode} +% The current data type is a real, set to real unless the given value +% is a string or currency (real overrides int, but not string or +% currency.) +% \begin{macrocode} + \ifnum\@dtl@datatype=0\relax + \expandafter\gdef\csname @dtl@idtype@#1@#2\endcsname{0}% + \else + \ifnum\@dtl@datatype=3\relax + \expandafter\gdef\csname @dtl@idtype@#1@#2\endcsname{3}% + \else + \expandafter\gdef\csname @dtl@idtype@#1@#2\endcsname{2}% + \fi + \fi + \or +% \end{macrocode} +% The current data type is currency, so set to currency unless +% the given value is a string (currency overrides real and int, +% but not string.) +% \begin{macrocode} + \ifnum\@dtl@datatype=0\relax + \expandafter\gdef\csname @dtl@idtype@#1@#2\endcsname{0}% + \else + \expandafter\gdef\csname @dtl@idtype@#1@#2\endcsname{3}% + \fi + \fi + \fi +\fi +}% +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\@dtl@setkeys} +%\begin{definition} +%\cs{@dtl@setkeys}\marg{key}\marg{db name} +%\end{definition} +% Adds \marg{key} to \cs{dtlkeys@}\meta{db name} if not already +% in it. +% \begin{macrocode} +\newcommand*{\@dtl@setkeys}[2]{% +\edef\@dtl@tmp{\csname dtlkeys@#2\endcsname}% +\expandafter\@dtl@toks\expandafter{\@dtl@tmp}% +\expandafter\ifx\csname dtlkeys@#2\endcsname\@empty + \expandafter\gdef\csname dtlkeys@#2\endcsname{#1}% +\else + \@for\dtl@key:=\@dtl@tmp\do{% + \ifthenelse{\equal{\dtl@key}{#1}}{\@endfortrue}{}% + }% + \if@endfor + \else + \expandafter\xdef\csname dtlkeys@#2\endcsname{\the\@dtl@toks,#1}% + \fi +\fi +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\@dtl@getidtype} +%\begin{definition} +% \cs{@dtl@getidtype}\marg{db name}\marg{id} +%\end{definition} +% Gets the data type for \meta{id} in given database. +% \begin{macrocode} +\newcommand*{\@dtl@getidtype}[2]{% +\csname @dtl@idtype@#1@#2\endcsname} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLifdbexists} +%\begin{definition} +%\cs{DTLifdbexists}\marg{db name}\marg{true part}\marg{false part} +%\end{definition} +% Checks if a data base with the given name exists. +% \begin{macrocode} +\newcommand{\DTLifdbexists}[3]{% +\@ifundefined{dtldb@#1}{#3}{#2}} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\dtl@ifrowcontains} +%\begin{definition} +% \cs{dtl@ifrowcontains}\meta{id}\meta{cmd}\meta{true part}\meta{false +%part} +%\end{definition} +% Checks to see if the row given by \meta{cmd} contains an +% entry with ID given by \meta{id}. If true, do \meta{true part}, +% otherwise do \meta{false part}. +% \begin{macrocode} +\newcommand{\dtl@ifrowcontains}[4]{% +\@for\@dtl@element:=#2\do{% +\dtl@getentryid{\@dtl@element}{\@dtl@entryid}% +\ifthenelse{\equal{#1}{\@dtl@entryid}}{\@endfortrue}{}% +}% +\if@endfor #3\else #4\fi +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\dtl@getentryid} +%\begin{definition} +% \cs{dtl@getentryid}\meta{entry cmd}\meta{id cmd} +%\end{definition} +% Gets the ID for an entry given by \meta{entry cmd}, and stores in +% in \meta{id cmd}. +% \begin{macrocode} +\newcommand*{\dtl@getentryid}[2]{\expandafter\@dtl@getentryid#1#2} +\long\def\@dtl@getentryid#1#2#3{\def#3{#1}} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\dtl@getentryvalue} +%\begin{definition} +% \cs{dtl@getentryvalue}\meta{entry cmd}\meta{cmd} +%\end{definition} +% Stores the entry value in \meta{cmd} for +% entry given by \meta{entry cmd}. +% \begin{macrocode} +\newcommand*{\dtl@getentryvalue}[2]{% +\expandafter\@dtl@getentryvalue#1#2} +\long\def\@dtl@getentryvalue#1#2#3{\gdef#3{#2}} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\dtlforeachlevel} +%\cs{DTLforeach} can only be nested up to three levels. +% \cs{dtlforeachlevel} keeps track of the current level. +% \begin{macrocode} +\global\newcount\dtlforeachlevel +% \end{macrocode} +%\end{macro} +% +% The counter DTLrow\meta{n} keeps track of each row of data during +% the \meta{n} nested \cs{DTLforeach}. It is only incremented in the +% conditions (given by the optional argument) are met. +% \begin{macrocode} +\newcounter{DTLrowi} +\newcounter{DTLrowii} +\newcounter{DTLrowiii} +% \end{macrocode} +% Keep \sty{hyperref} happy +% \begin{macrocode} +\newcounter{DTLrow} +\def\theHDTLrow{\arabic{DTLrow}} +\def\theHDTLrowi{\theHDTLrow.\arabic{DTLrowi}} +\def\theHDTLrowii{\theHDTLrowi.\arabic{DTLrowii}} +\def\theHDTLrowiii{\theHDTLrowii.\arabic{DTLrowiii}} +% \end{macrocode} +% +%\begin{macro}{\DTLsaverowcount} +%\begin{definition} +%\cs{DTLsavelastrowcount}\marg{cmd} +%\end{definition} +% Stores the maximum row count for the last \cs{DTLforeach}. +% \begin{macrocode} +\newcommand*{\DTLsavelastrowcount}[1]{% +\ifnum\dtlforeachlevel>2\relax + \def#1{0}% +\else + \ifnum\dtlforeachlevel<0\relax + \def#1{0}% + \else + \@dtl@tmpcount=\dtlforeachlevel + \advance\@dtl@tmpcount by 1\relax + \edef#1{\expandafter\number + \csname c@DTLrow\romannumeral\@dtl@tmpcount\endcsname}% + \fi +\fi} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLforeach} +%\begin{definition} +% \cs{DTLforeach}\oarg{conditions}\marg{db name}\marg{values}\marg{text} +%\end{definition} +% For each row of data in the database given by \meta{db name}, +% do \meta{text}, if the specified conditions are satisfied. +% The argument \marg{values} is a comma separated list of +% \meta{cmd}\texttt{=}\meta{key} pairs. At the start of each row, +% each of the commands in this list are set to the value of the +% entry with the corresponding key \meta{key}. +% (\cs{gdef} is used to ensure \cs{DTLforeach} works in a tabular +% environment.) The database may be edited in the unstarred +% version, in the starred version the database is read only. +%\changes{1.01}{2007 Aug 17}{added starred version} +% \begin{macrocode} +\newcommand*{\DTLforeach}{\@ifstar\@sDTLforeach\@DTLforeach} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\@DTLforeach} +% \cs{@DTLforeach} is the unstarred version of \cs{DTLforeach}. +% The database is reconstructed to allow for rows to be edited. +% \begin{macrocode} +\newcommand{\@DTLforeach}[4][\boolean{true}]{% +% \end{macrocode} +% Check database exists +% \begin{macrocode} +\DTLifdbexists{#2}{% +% \end{macrocode} +% Keep \sty{hyperref} happy +% \begin{macrocode} +\refstepcounter{DTLrow}% +\global\c@DTLrow=\c@DTLrow +% \end{macrocode} +% Store database name +% \begin{macrocode} +\gdef\@dtl@dbname{#2}% +% \end{macrocode} +% Increment level and check not exceeded 3 +% \begin{macrocode} +\global\advance\dtlforeachlevel by 1\relax +\ifnum\dtlforeachlevel>3\relax + \PackageError{datatool}{\string\DTLforeach\space nested too +deeply}{}% +\else +% \end{macrocode} +% Set level dependent information (needs to be global to ensure +% it works in the \env{tabular} environment.) Row counter: +% \begin{macrocode} + \expandafter\global + \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname = 0\relax +% \end{macrocode} +% Construct updated database: +% \begin{macrocode} + \expandafter\global\expandafter\let + \csname @dtl@foreachrows@\romannumeral\dtlforeachlevel\endcsname + =\@empty +% \end{macrocode} +% Database name: +% \begin{macrocode} + \expandafter\global\expandafter\let + \csname @dtl@dbname@\romannumeral\dtlforeachlevel\endcsname + =\@dtl@dbname +% \end{macrocode} +% Iterate through each row +% \begin{macrocode} + \expandafter\let\expandafter\@dtl@db\csname dtldb@#2\endcsname% + \@for\@dtl@currentrow:=\@dtl@db\do{% +% \end{macrocode} +% Set current row macro for this level +% \begin{macrocode} + \expandafter\global\expandafter + \let\csname @dtl@thiscurrentrow@\romannumeral\dtlforeachlevel + \endcsname=\@dtl@currentrow +% \end{macrocode} +% Globally assign next element (note that there is no check to +% determine if the next element will be skipped.) +%\changes{1.01}{2007 Aug 17}{set \cs{@dtl@nextrow}} +% \begin{macrocode} + \global\let\@dtl@nextrow\@xfor@nextelement +% \end{macrocode} +% Assign commands to the required entries +% \begin{macrocode} + \ifx\relax#3\relax + \else + \@dtl@assign{#3}% + \fi +% \end{macrocode} +% Do the main body of text if condition is satisfied +% \begin{macrocode} + \ifthenelse{#1}{% + \refstepcounter{DTLrow\romannumeral\dtlforeachlevel}% + \expandafter\edef\expandafter\DTLcurrentindex\expandafter + {\arabic{DTLrow\romannumeral\dtlforeachlevel}}% + #4% + }{}% +% \end{macrocode} +% Reconstruct database +% \begin{macrocode} + \expandafter\let\expandafter\@dtl@thiscurrentrow + \csname @dtl@thiscurrentrow@\romannumeral\dtlforeachlevel\endcsname +% \end{macrocode} +% Don't add this row if it is now empty +% \begin{macrocode} + \ifx\@dtl@thiscurrentrow\@empty + \else + \expandafter\@dtl@toks\expandafter{\@dtl@thiscurrentrow}% + \expandafter + \ifx + \csname @dtl@foreachrows@\romannumeral\dtlforeachlevel\endcsname + \@empty + \expandafter + \xdef\csname @dtl@foreachrows@\romannumeral\dtlforeachlevel\endcsname{% + {\the\@dtl@toks}}% + \else + \expandafter\let\expandafter\@dtl@foreachrows\expandafter + =\csname @dtl@foreachrows@\romannumeral\dtlforeachlevel\endcsname + \expandafter\toks@\expandafter{\@dtl@foreachrows}% + \expandafter + \xdef\csname @dtl@foreachrows@\romannumeral\dtlforeachlevel\endcsname{% + \the\toks@,{\the\@dtl@toks}}% + \fi + \fi +\@endforfalse +}% +\expandafter\let\expandafter\@dtl@foreachrows\expandafter + =\csname @dtl@foreachrows@\romannumeral\dtlforeachlevel\endcsname +\expandafter\global + \expandafter\let\csname dtldb@#2\endcsname=\@dtl@foreachrows +\fi +\global\advance\dtlforeachlevel by -1\relax +}{% +\PackageError{datatool}{Database `#2' doesn't exist}{}}% +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\@sDTLforeach} +% \cs{@sDTLforeach} is the starred version of \cs{DTLforeach}. +% The database rows can't be edited. +% \begin{macrocode} +\newcommand{\@sDTLforeach}[4][\boolean{true}]{% +% \end{macrocode} +% Check database exists +% \begin{macrocode} +\DTLifdbexists{#2}{% +% \end{macrocode} +% Keep \sty{hyperref} happy +% \begin{macrocode} +\refstepcounter{DTLrow}% +\global\c@DTLrow=\c@DTLrow +% \end{macrocode} +% Store database name +% \begin{macrocode} +\gdef\@dtl@dbname{#2}% +% \end{macrocode} +% Increment level and check not exceeded 3 +% \begin{macrocode} +\global\advance\dtlforeachlevel by 1\relax +\ifnum\dtlforeachlevel>3\relax + \PackageError{datatool}{\string\DTLforeach\space nested too +deeply}{}% +\else +% \end{macrocode} +% Set level dependent information (needs to be global to ensure +% it works in the \env{tabular} environment.) Row counter: +% \begin{macrocode} + \expandafter\global + \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname = 0\relax +% \end{macrocode} +% Set database name to \cs{@nnil} to indicate that this is read only: +% \begin{macrocode} + \expandafter\global\expandafter\let + \csname @dtl@dbname@\romannumeral\dtlforeachlevel\endcsname + =\@nnil +% \end{macrocode} +% Iterate through each row +% \begin{macrocode} + \expandafter\let\expandafter\@dtl@db\csname dtldb@#2\endcsname% + \@for\@dtl@currentrow:=\@dtl@db\do{% +% \end{macrocode} +% Set current row macro for this level +% \begin{macrocode} + \expandafter\global\expandafter + \let\csname @dtl@thiscurrentrow@\romannumeral\dtlforeachlevel + \endcsname=\@dtl@currentrow +% \end{macrocode} +% Globally assign next element (note that there is no check to +% determine if the next element will be skipped.) +%\changes{1.01}{2007 Aug 17}{set \cs{@dtl@nextrow}} +% \begin{macrocode} + \global\let\@dtl@nextrow\@xfor@nextelement +% \end{macrocode} +% Assign commands to the required entries +% \begin{macrocode} + \ifx\relax#3\relax + \else + \@dtl@assign{#3}% + \fi +% \end{macrocode} +% Do the main body of text if condition is satisfied +% \begin{macrocode} + \ifthenelse{#1}{% + \refstepcounter{DTLrow\romannumeral\dtlforeachlevel}% + \expandafter\edef\expandafter\DTLcurrentindex\expandafter + {\arabic{DTLrow\romannumeral\dtlforeachlevel}}% + #4% + }{}% +% \end{macrocode} +% \begin{macrocode} +\@endforfalse +}% +\fi +\global\advance\dtlforeachlevel by -1\relax +}{% +\PackageError{datatool}{Database `#2' doesn't exist}{}}% +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLappendtorow} +%\begin{definition} +%\cs{DTLappendtorow}\marg{key}\marg{value} +%\end{definition} +% Appends entry to current row. (The current row is given by +% \cs{@dtl@thiscurrentrow@}\meta{n} where \meta{n} is roman +% numeral value of \cs{dtlforeachlevel}. +% \begin{macrocode} +\newcommand*{\DTLappendtorow}[2]{% +\ifnum\dtlforeachlevel=0\relax + \PackageError{datatool}{\string\DTLappendtorow\space can only + be used inside \string\DTLforeach}{}% +\else +% \end{macrocode} +% Set \cs{@dtl@thisdb} to the current database name: +% \begin{macrocode} + \expandafter\let\expandafter\@dtl@thisdb + \csname @dtl@dbname@\romannumeral\dtlforeachlevel\endcsname +% \end{macrocode} +% Check this isn't in \cs{DTLforeach*} +% \begin{macrocode} + \ifx\@dtl@thisdb\@nnil + \PackageError{datatool}{\string\DTLappendtorow\space can't + be used inside \string\DTLforeach*}{The starred version of + \string\DTLforeach\space is read only}% + \else +% \end{macrocode} +% Set \cs{@dtl@dbvalue} to the value of this entry +% \begin{macrocode} + \expandafter\@dtl@toks\expandafter{#2}% + \edef\@dtl@dbvalue{\the\@dtl@toks}% +% \end{macrocode} +% Set \cs{@dtl@dbid} to the entry ID. This uses \cs{edef} to allow +% for the ID to be stored in a control sequence. +% \begin{macrocode} + \edef\@dtl@dbid{#1}% +% \end{macrocode} +% Set up the correct entry format: +% \begin{macrocode} + \edef\@dtl@dbentry{{\@dtl@dbid}{\the\@dtl@toks}}% +% \end{macrocode} +% Set \cs{@dtl@thisrow} to the current row. +% \begin{macrocode} + \expandafter\let\expandafter\@dtl@thisrow + \csname @dtl@thiscurrentrow@\romannumeral\dtlforeachlevel\endcsname +% \end{macrocode} +% Check if there is already an entry with this key +% \begin{macrocode} + \dtl@ifrowcontains{#1}{\@dtl@thisrow}{% + \PackageError{datatool}{Can't add entry with ID `#1' to current + row of database `\@dtl@thisdb'}{There is already an entry with + this ID on the current row}}{% +% \end{macrocode} +% Append entry to last row +% \begin{macrocode} + \expandafter\@dtl@toks\expandafter{\@dtl@dbentry}% + \ifx\@dtl@thisrow\@empty + \expandafter + \xdef\csname @dtl@thiscurrentrow@\romannumeral\dtlforeachlevel\endcsname{% + \the\@dtl@toks}% + \else + \expandafter\toks@\expandafter{\@dtl@thisrow}% + \expandafter + \xdef\csname @dtl@thiscurrentrow@\romannumeral\dtlforeachlevel\endcsname{% + \the\toks@,\the\@dtl@toks}% + \fi + } +% \end{macrocode} +% Update key list +% \begin{macrocode} + \@dtl@setidtype{\@dtl@thisdb}{#1}{#2}% + \expandafter\@dtl@setkeys\expandafter{#1}{\@dtl@thisdb}% +% \end{macrocode} +% end the \cs{ifx} and \cs{ifnum} +% \begin{macrocode} + \fi +\fi +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLremoveentryfromrow} +%\begin{definition} +%\cs{DTLremoveentryfromrow}\marg{key} +%\end{definition} +% Removes entry given by \meta{key} from current row. +% (The current row is given by +% \cs{@dtl@thiscurrentrow@}\meta{n} where \meta{n} is roman +% numeral value of \cs{dtlforeachlevel}. +% \begin{macrocode} +\newcommand*{\DTLremoveentryfromrow}[1]{% +\ifnum\dtlforeachlevel=0\relax + \PackageError{datatool}{\string\DTLremoveentryfromrow\space can only + be used inside \string\DTLforeach}{}% +\else +% \end{macrocode} +% Set \cs{@dtl@thisdb} to the current database name: +% \begin{macrocode} + \expandafter\let\expandafter\@dtl@thisdb + \csname @dtl@dbname@\romannumeral\dtlforeachlevel\endcsname +% \end{macrocode} +% Check this isn't in \cs{DTLforeach*} +% \begin{macrocode} + \ifx\@dtl@thisdb\@nnil + \PackageError{datatool}{\string\DTLremoveentryfromrow\space can't + be used inside \string\DTLforeach*}{The starred version of + \string\DTLforeach\space is read only}% + \else +% \end{macrocode} +% Set \cs{@dtl@thisrow} to the current row. +% \begin{macrocode} + \expandafter\let\expandafter\@dtl@thisrow + \csname @dtl@thiscurrentrow@\romannumeral\dtlforeachlevel\endcsname +% \end{macrocode} +% Check row contains an entry with this key +% \begin{macrocode} + \dtl@ifrowcontains{#1}{\@dtl@thisrow}{% +% \end{macrocode} +% Split row list +% \begin{macrocode} + \let\@dtl@pre=\@empty + \@for\dtl@thisentry:=\@dtl@thisrow\do{% + \dtl@getentryid\dtl@thisentry\@dtl@id + \ifthenelse{\equal{\@dtl@id}{#1}}{% + }{% + \expandafter\@dtl@toks\expandafter{\dtl@thisentry}% + \ifx\@dtl@pre\@empty + \edef\@dtl@pre{{\the\@dtl@toks}}% + \else + \expandafter\toks@\expandafter{\@dtl@pre}% + \edef\@dtl@pre{\the\toks@,{\the\@dtl@toks}}% + \fi + } + }% + \expandafter\let + \csname @dtl@thiscurrentrow@\romannumeral\dtlforeachlevel\endcsname + =\@dtl@pre + }{% + \PackageError{datatool}{Can't remove entry given by key `#1' + from current row in database `\@dtl@thisdb', no such entry}{}% + }% + \fi +\fi +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLreplaceentryforrow} +%\begin{definition} +%\cs{DTLreplaceentryforrow}\marg{key}\marg{value} +%\end{definition} +% Replaces entry given by \meta{key} in current row with +% \meta{value}. +% (The current row is given by +% \cs{@dtl@thiscurrentrow@}\meta{n} where \meta{n} is roman +% numeral value of \cs{dtlforeachlevel}. +% \begin{macrocode} +\newcommand*{\DTLreplaceentryforrow}[2]{% +\ifnum\dtlforeachlevel=0\relax + \PackageError{datatool}{\string\DTLreplaceentryforrow\space can only + be used inside \string\DTLforeach}{}% +\else +% \end{macrocode} +% Set \cs{@dtl@thisdb} to the current database name: +% \begin{macrocode} + \expandafter\let\expandafter\@dtl@thisdb + \csname @dtl@dbname@\romannumeral\dtlforeachlevel\endcsname +% \end{macrocode} +% Check this isn't in \cs{DTLforeach*} +% \begin{macrocode} + \ifx\@dtl@thisdb\@nnil + \PackageError{datatool}{\string\DTLreplaceentryforrow\space can't + be used inside \string\DTLforeach*}{The starred version of + \string\DTLforeach\space is read only}% + \else +% \end{macrocode} +% Set \cs{@dtl@dbvalue} to the value of this entry +% \begin{macrocode} + \expandafter\@dtl@toks\expandafter{#2}% + \edef\@dtl@dbvalue{\the\@dtl@toks}% +% \end{macrocode} +% Set \cs{@dtl@dbid} to the entry ID. This uses \cs{edef} to allow +% for the ID to be stored in a control sequence. +% \begin{macrocode} + \edef\@dtl@dbid{#1}% +% \end{macrocode} +% Set up the correct entry format: +% \begin{macrocode} + \edef\dtl@newentry{{\@dtl@dbid}{\the\@dtl@toks}}% +% \end{macrocode} +% Set \cs{@dtl@thisrow} to the current row. +% \begin{macrocode} + \expandafter\let\expandafter\@dtl@thisrow + \csname @dtl@thiscurrentrow@\romannumeral\dtlforeachlevel\endcsname +% \end{macrocode} +% Check row contains an entry with this key +% \begin{macrocode} + \dtl@ifrowcontains{#1}{\@dtl@thisrow}{% +% \end{macrocode} +% Split row list +% \begin{macrocode} + \let\@dtl@pre=\@empty + \@for\dtl@thisentry:=\@dtl@thisrow\do{% + \dtl@getentryid\dtl@thisentry\@dtl@id + \ifthenelse{\equal{\@dtl@id}{#1}}{% + \expandafter\@dtl@toks\expandafter{\dtl@newentry}% + }{% + \expandafter\@dtl@toks\expandafter{\dtl@thisentry}% + } + \ifx\@dtl@pre\@empty + \edef\@dtl@pre{{\the\@dtl@toks}}% + \else + \expandafter\toks@\expandafter{\@dtl@pre}% + \edef\@dtl@pre{\the\toks@,{\the\@dtl@toks}}% + \fi + }% + \expandafter\let + \csname @dtl@thiscurrentrow@\romannumeral\dtlforeachlevel\endcsname + =\@dtl@pre + }{% + \PackageError{datatool}{Can't remove entry given by key `#1' + from current row in database `\@dtl@thisdb', no such entry}{}% + }% + \fi +\fi +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLremovecurrentrow} +%\begin{definition} +%\cs{DTLremovecurrentrow} +%\end{definition} +% Removes current row. This just sets the current row to empty +%\changes{1.01}{2007 Aug 17}{fix bug caused by missing \cs{fi} +% and unrequired argument} +% \begin{macrocode} +\newcommand*{\DTLremovecurrentrow}{% +\ifnum\dtlforeachlevel=0\relax + \PackageError{datatool}{\string\DTLremovecurrentrow\space can only + be used inside \string\DTLforeach}{}% +\else +% \end{macrocode} +% Check this isn't in \cs{DTLforeach*} +% \begin{macrocode} + \expandafter\ifx + \csname @dtl@dbname@\romannumeral\dtlforeachlevel\endcsname\@nnil + \PackageError{datatool}{\string\DTLremovecurrentrow\space can't + be used inside \string\DTLforeach*}{The starred version of + \string\DTLforeach\space is read only}% + \else +% \end{macrocode} +% Set current row to empty. +% \begin{macrocode} + \expandafter\let + \csname @dtl@thiscurrentrow@\romannumeral\dtlforeachlevel\endcsname + =\@empty + \fi +\fi +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLforeachkeyinrow} +%\begin{definition} +%\cs{DTLforeachkeyinrow}\marg{cmd}\marg{text} +%\end{definition} +% Iterates through each key in the current row of \cs{DTLforeach}, +% and does \meta{text}. +% \begin{macrocode} +\newcommand*{\DTLforeachkeyinrow}[2]{% +\ifnum\dtlforeachlevel=0\relax + \PackageError{datatool}{\string\DTLforeachkeyinrow\space can only + be used inside \string\DTLforeach}{}% +\else +% \end{macrocode} +% Set \cs{@dtl@thisrow} to the current row. +% \begin{macrocode} + \expandafter\let\expandafter\@dtl@thisrow + \csname @dtl@thiscurrentrow@\romannumeral\dtlforeachlevel\endcsname +% \end{macrocode} +% Iterate through the row +% \begin{macrocode} + \@for\dtl@thisentry:=\@dtl@thisrow\do{% + \dtl@getentryvalue\dtl@thisentry{#1}% + #2% + }% +\fi +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLaddentryforrow} +%\begin{definition} +%\cs{DTLaddentryforrow}\marg{db name}\marg{assign list}\marg{condition}\marg{key}\marg{value} +%\end{definition} +% Adds the entry with key given by \meta{key} and value given by +% \meta{value} to the first row in the database \meta{db name} +% which satisfies the condition given by \meta{condition}. The +% \meta{assign list} is the same as for \cs{DTLforeach} and may +% be used to set the values which are to be tested in \meta{condition}. +% \begin{macrocode} +\newcommand{\DTLaddentryforrow}[5]{% +\gdef\@dtl@dbname{#1}% +\DTLifdbexists{#1}{% +% \end{macrocode} +% Set \cs{@dtl@dbvalue} to the value of this entry +% \begin{macrocode} + \expandafter\@dtl@toks\expandafter{#5}% + \edef\@dtl@dbvalue{\the\@dtl@toks}% +% \end{macrocode} +% Set \cs{@dtl@dbid} to the entry ID. This uses \cs{edef} to allow +% for the ID to be stored in a control sequence. +% \begin{macrocode} + \edef\@dtl@dbid{#4}% +% \end{macrocode} +% Set up the correct entry format: +% \begin{macrocode} + \edef\@dtl@dbentry{{\@dtl@dbid}{\the\@dtl@toks}}% +% \end{macrocode} +% Store the database in \cs{@dtl@db} +% \begin{macrocode} + \expandafter + \let\expandafter\@dtl@db\csname dtldb@\@dtl@dbname\endcsname% + \let\@dtl@prerow=\@empty +% \end{macrocode} +% Iterate through each row of the database +% \begin{macrocode} + \@for\@dtl@currentrow:=\@dtl@db\do{% + \@dtl@assign{#2}% + \ifthenelse{#3}{% + \expandafter\@dtl@toks\expandafter{\@dtl@dbentry}% + \ifx\@dtl@currentrow\@empty + \edef\@dtl@currentrow{{\the\@dtl@toks}}% + \else + \expandafter\toks@\expandafter{\@dtl@currentrow}% + \edef\@dtl@currentrow{\the\toks@,{\the\@dtl@toks}}% + \fi + \@endfortrue + }{% + }% + \expandafter\@dtl@toks\expandafter{\@dtl@currentrow}% + \ifx\@dtl@prerow\@empty + \edef\@dtl@prerow{{\the\@dtl@toks}}% + \else + \expandafter\toks@\expandafter{\@dtl@prerow}% + \edef\@dtl@prerow{\the\toks@,{\the\@dtl@toks}}% + \fi +}% +\if@endfor + \expandafter\@dtl@toks\expandafter{\@forremainder}% + \expandafter\toks@\expandafter{\@dtl@prerow}% + \edef\@dtl@prerow{\the\toks@,{\the\@dtl@toks}}% + \expandafter\global\expandafter + \let\csname dtldb@\@dtl@dbname\endcsname=\@dtl@prerow +\else + \PackageError{datatool}{Unable to add `#5' for key `#4' - condition + not met for any row in database `#1'}{}% +\fi +\@endforfalse +}{% +\PackageError{datatool}{Database `#1' doesn't exist}{}}% +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\@dtl@assign} +%\begin{definition} +%\cs{@dtl@assign}\oarg{row}\marg{values} +%\end{definition} +% Assigns each command in +% \meta{values} (see above) to the value of the corresponding +% ID for the row given by \meta{row} (which defaults to +% \cs{@dtl@currentrow} if absent.) +% \begin{macrocode} +\newcommand*{\@dtl@assign}[2][\@dtl@currentrow]{% +\@dtl@assigncmd#2,\relax\@@{#1}% +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\@dtl@assigncmd} +%\begin{definition} +% \cs{\@dtl@assigncmd}\meta{cmd}=\meta{id}\cs{@nil} +%\end{definition} +% Assign \meta{cmd} to value given by \meta{id} +% \begin{macrocode} +\def\@dtl@assigncmd#1=#2,#3\@@#4{% +\@for\@dtl@entry:=#4\do{% +\dtl@getentryid\@dtl@entry\@dtl@id +\ifthenelse{\equal{\@dtl@id}{#2}}{% +\dtl@getentryvalue\@dtl@entry#1% +\@endfortrue}{}% +}% +\if@endfor +\else + \@dtl@setnull{#1}{#2}% +\fi +\@endforfalse +\ifx\relax#3% + \let\@dtl@next=\@dtl@assigncmdnoop +\else + \let\@dtl@next=\@dtl@assigncmd +\fi +\@dtl@next#3\@@{#4}% +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\@dtl@assigncmdnoop} +% End loop +% \begin{macrocode} +\def\@dtl@assigncmdnoop#1\@@#2{} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\@dtl@setnull} +%\cs{@dtl@setnull}\marg{cmd}\marg{id} sets \meta{cmd} to either +% \cs{DTLstringnull} or \cs{DTLnumbernull} depending on the data +% type for \meta{id}. (Database +% name should be stored in \cs{@dtl@dbname} prior to use. +% \begin{macrocode} +\newcommand*{\@dtl@setnull}[2]{% +\@ifundefined{@dtl@idtype@\@dtl@dbname @#2}{% +\global\let#1=\DTLstringnull}{% +\edef\@dtl@tmp{0\@dtl@getidtype{\@dtl@dbname}{#2}}% +\expandafter\ifnum\@dtl@tmp=0\relax + \global\let#1=\DTLstringnull +\else + \global\let#1=\DTLnumbernull +\fi +}} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLstringnull} +% String null value: +% \begin{macrocode} +\newcommand*{\DTLstringnull}{NULL} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLnumbernull} +% Number null value: +% \begin{macrocode} +\newcommand*{\DTLnumbernull}{0} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLifnull} +%\begin{definition} +%\cs{DTLifnull}\marg{value}\marg{true part}\marg{false part} +%\end{definition} +% Checks if \meta{value} is null (either \cs{DTLstringnull} or +% \cs{DTLnumbernull}) if true, does \meta{true part} otherwise +% does \meta{false part}. +% \begin{macrocode} +\newcommand*{\DTLifnull}[3]{% +\ifx\DTLstringnull#1\relax + #2% +\else + \ifx\DTLnumbernull#1\relax + #2% + \else + #3% + \fi +\fi} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\dtl@gathervalues} +%\begin{definition} +%\cs{dtl@gathervalues}\oarg{label}\marg{db name}\marg{row} +%\end{definition} +% Stores each element of \meta{row} in \meta{db name} into +% the command \cs{@dtl@}\meta{label}\texttt{@}\meta{key}, +% where \meta{key} is the +% key for that element, and \meta{label} defaults to "key". +% \begin{macrocode} +\newcommand{\dtl@gathervalues}[3][key]{% +\expandafter\let\expandafter\@dtl@tmp\expandafter + =\csname dtlkeys@#2\endcsname% +\def\@dtl@list{}% +\@for\dtl@key:=\@dtl@tmp\do{% + \expandafter\@dtl@setnull\expandafter{% + \csname @dtl@#1@\dtl@key\endcsname}{\dtl@key}% + \@for\dtl@thiselement:=#3\do{% + \dtl@getentryid\dtl@thiselement\@dtl@id + \ifthenelse{\equal{\@dtl@id}{\dtl@key}}{% + \dtl@getentryvalue\dtl@thiselement\@dtl@value% + \expandafter\toks@\expandafter{\@dtl@value}% + \expandafter\edef\csname @dtl@#1@\dtl@key\endcsname{% + \the\toks@}% + \@endfortrue}{}% + }% +\@endforfalse +}% +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLsumforkeys} +%\begin{definition} +%\cs{DTLsumforkeys}\oarg{condition}\marg{db list}\marg{key list}\marg{cmd} +%\end{definition} +% Sums all entries for key \meta{key} over all databases listed +% in \meta{db list}, +% and stores in \meta{cmd}, which must be a control sequence. +% The optional argument \meta{condition} is the same as that +% for \cs{DTLforeach}. +% \begin{macrocode} +\newcommand*{\DTLsumforkeys}[4][\boolean{true}\and +\DTLisnumerical{\DTLthisval}]{% +\def#4{0}% +\@for\@dtl@dbname:=#2\do{% + \DTLifdbexists{\@dtl@dbname}{% + \expandafter + \let\expandafter\@dtl@db\csname dtldb@\@dtl@dbname\endcsname% + \@for\@dtl@currentrow:=\@dtl@db\do{% + \dtl@gathervalues{\@dtl@dbname}{\@dtl@currentrow}% + \@for\@dtl@key:=#3\do{% + \protected@edef\DTLthisval{% + \csname @dtl@key@\@dtl@key\endcsname}% + \ifthenelse{#1}{\DTLadd{#4}{#4}{\DTLthisval}}{}% + }}% + }{\PackageError{datatool}{Database `\@dtl@dbname' doesn't exist}{}% + }% +}% +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLmeanforkeys} +%\begin{definition} +%\cs{DTLmeanforkeys}\oarg{condition}\marg{db list}\marg{key list}\marg{cmd} +%\end{definition} +% Computes the arithmetic mean of all entries for each key in +% \meta{key list} over all databases in \meta{db list}, +% and stores in \meta{cmd}, which must be a control sequence. +% The optional argument \meta{condition} is the same as that +% for \cs{DTLforeach}. +% \begin{macrocode} +\newcommand*{\DTLmeanforkeys}[4][\boolean{true}\and +\DTLisnumerical{\DTLthisval}]{% +\def#4{0}% +\def\dtl@n{0}% +\@for\@dtl@dbname:=#2\do{% +\DTLifdbexists{\@dtl@dbname}{% + \expandafter + \let\expandafter\@dtl@db\csname dtldb@\@dtl@dbname\endcsname% + \@for\@dtl@currentrow:=\@dtl@db\do{% + \dtl@gathervalues{\@dtl@dbname}{\@dtl@currentrow}% + \@for\@dtl@key:=#3\do{% + \protected@edef\DTLthisval{% + \csname @dtl@key@\@dtl@key\endcsname}% + \ifthenelse{#1}{% + \DTLadd{#4}{#4}{\DTLthisval}% + \DTLadd{\dtl@n}{\dtl@n}{1}% + }{}% + }}% +}{\PackageError{datatool}{Database `\@dtl@dbname' doesn't exist}{}}}% +\ifnum\dtl@n=0\relax + \PackageError{datatool}{Can't compute mean, no data!}{}% +\else + \DTLdiv{#4}{#4}{\dtl@n}% +\fi +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLvarianceforkeys} +%\begin{definition} +%\cs{DTLvarianceforkeys}\oarg{condition}\marg{db list}\marg{key list}\marg{cmd} +%\end{definition} +% Computes the variance of all entries for each key in +% \meta{key list} over all databases in \meta{db list}, +% and stores in \meta{cmd}, which must be a control sequence. +% The optional argument \meta{condition} is the same as that +% for \cs{DTLforeach}. +% \begin{macrocode} +\newcommand*{\DTLvarianceforkeys}[4][\boolean{true}\and +\DTLisnumerical{\DTLthisval}]{% +\DTLmeanforkeys[#1]{#2}{#3}{\dtl@mean}% +\def#4{0}% +\@for\@dtl@dbname:=#2\do{% + \DTLifdbexists{\@dtl@dbname}{% + \expandafter + \let\expandafter\@dtl@db\csname dtldb@\@dtl@dbname\endcsname + \@for\@dtl@currentrow:=\@dtl@db\do{% + \dtl@gathervalues{\@dtl@dbname}{\@dtl@currentrow}% + \@for\@dtl@key:=#3\do{% + \protected@edef\DTLthisval{% + \csname @dtl@key@\@dtl@key\endcsname}% + \ifthenelse{#1}{% + \DTLsub{\dtl@diff}{\DTLthisval}{\dtl@mean}% + \DTLmul{\dtl@diff}{\dtl@diff}{\dtl@diff}% + \DTLadd{#4}{#4}{\dtl@diff}% + }{}% + }}% + }{\PackageError{datatool}{Database `\@dtl@dbname' doesn't exist}{}% + }% +}% +\ifnum\dtl@n=0\relax + \PackageError{datatool}{Can't compute variance, no data!}{}% +\else + \DTLdiv{#4}{#4}{\dtl@n}% +\fi +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLsdforkeys} +%\begin{definition} +%\cs{DTLsdforkeys}\oarg{condition}\marg{db list}\marg{key list}\marg{cmd} +%\end{definition} +% Computes the standard deviation of all entries for each key in +% \meta{key list} over all databases in \meta{db list}, +% and stores in \meta{cmd}, which must be a control sequence. +% The optional argument \meta{condition} is the same as that +% for \cs{DTLforeach}. +% \begin{macrocode} +\newcommand*{\DTLsdforkeys}[4][\boolean{true}\and +\DTLisnumerical{\DTLthisval}]{% +\DTLvarianceforkeys[#1]{#2}{#3}{#4}% +\DTLsqrt{#4}{#4}% +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLminforkeys} +%\begin{definition} +%\cs{DTLminforkeys}\oarg{condition}\marg{db list}\marg{key list}\marg{cmd} +%\end{definition} +% Determines the minimum over all entries for each key in +% \meta{key list} over all databases in \meta{db list}, +% and stores in \meta{cmd}, which must be a control sequence. +% The optional argument \meta{condition} is the same as that +% for \cs{DTLforeach}. +% \begin{macrocode} +\newcommand*{\DTLminforkeys}[4][\boolean{true}\and +\DTLisnumerical{\DTLthisval}]{% +\def#4{}% +\@for\@dtl@dbname:=#2\do{% +\DTLifdbexists{\@dtl@dbname}{% + \expandafter + \let\expandafter\@dtl@db\csname dtldb@\@dtl@dbname\endcsname% + \@for\@dtl@currentrow:=\@dtl@db\do{% + \dtl@gathervalues{\@dtl@dbname}{\@dtl@currentrow}% + \@for\@dtl@key:=#3\do{% + \protected@edef\DTLthisval{% + \csname @dtl@key@\@dtl@key\endcsname}% + \ifthenelse{#1}{% + \ifx#4\@empty + \let#4=\DTLthisval + \else + \DTLmin{#4}{#4}{\DTLthisval}% + \fi + }{}% +}}% + }{\PackageError{datatool}{Database `\@dtl@dbname' doesn't exist}{}% + }% +}} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLmaxforkeys} +%\begin{definition} +%\cs{DTLmaxforkeys}\oarg{condition}\marg{db list}\marg{key list}\marg{cmd} +%\end{definition} +% Determines the maximum over all entries for each key in +% \meta{key list} over all databases in \meta{db list}, +% and stores in \meta{cmd}, which must be a control sequence. +% The optional argument \meta{condition} is the same as that +% for \cs{DTLforeach}. +% \begin{macrocode} +\newcommand*{\DTLmaxforkeys}[4][\boolean{true}\and +\DTLisnumerical{\DTLthisval}]{% +\def#4{}% +\@for\@dtl@dbname:=#2\do{% +\DTLifdbexists{\@dtl@dbname}{% + \expandafter + \let\expandafter\@dtl@db\csname dtldb@\@dtl@dbname\endcsname% + \@for\@dtl@currentrow:=\@dtl@db\do{% + \dtl@gathervalues{\@dtl@dbname}{\@dtl@currentrow}% + \@for\@dtl@key:=#3\do{% + \protected@edef\DTLthisval{% + \csname @dtl@key@\@dtl@key\endcsname}% + \ifthenelse{#1}{% + \ifx#4\@empty + \let#4=\DTLthisval + \else + \DTLmax{#4}{#4}{\DTLthisval}% + \fi + }{}% +}}% + }{\PackageError{datatool}{Database `\@dtl@dbname' doesn't exist}{}% + }% +}} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLcomputebounds} +%\begin{definition} +%\cs{DTLcomputebounds}\oarg{condition}\marg{db list}\marg{x key}\marg{y key}\marg{minX cmd}\marg{minY cmd}\marg{maxX cmd}\marg{maxY cmd} +%\end{definition} +% Computes the maximum and minimum $x$ and $y$ values over all +% the databases listed in \meta{db list} where the $x$ value +% is given by \meta{x key} and the $y$ value is given by +% \meta{y key}. The results are stored in \meta{minX cmd}, +% \meta{minY cmd}, \meta{maxX cmd} and \meta{maxY cmd} in +% standard decimal format. +% \begin{macrocode} +\newcommand*{\DTLcomputebounds}[8][\boolean{true}]{% +\let#5=\relax +\let#6=\relax +\let#7=\relax +\let#8=\relax +\@for\dtl@thisdb:=#2\do{% + \@sDTLforeach[#1]{\dtl@thisdb}{\DTLthisX=#3,\DTLthisY=#4}{% + \DTLconverttodecimal{\DTLthisX}{\dtl@decx}% + \DTLconverttodecimal{\DTLthisY}{\dtl@decy}% + \ifx#5\relax + \let#5=\dtl@decx + \let#6=\dtl@decy + \let#7=\dtl@decx + \let#8=\dtl@decy + \else + \FPmin{#5}{#5}{\dtl@decx}% + \FPmin{#6}{#6}{\dtl@decy}% + \FPmax{#7}{#7}{\dtl@decx}% + \FPmax{#8}{#8}{\dtl@decy}% + \fi + }% +}% +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLgetvalueforkey} +%\begin{definition} +%\cs{DTLgetvalueforkey}\marg{cmd}\marg{key}\marg{db name}\marg{ref +% key}\marg{ref value} +%\end{definition} +% This (globally) sets \meta{cmd} (a control sequence) to the +% value of the key specified by \meta{key} in the first row +% of the database called \meta{db name} which contains the key +% \meta{ref key} which has the value \meta{value}. +%\changes{1.01}{2007 Aug 17}{new} +% \begin{macrocode} +\newcommand*{\DTLgetvalueforkey}[5]{% +{% +\global\let#1=\DTLstringnull +\@sDTLforeach{#3}{\dtl@valueA=#2,\dtl@refvalue=#4}{% +\DTLifnull{\dtl@refvalue}{}{% +\ifthenelse{\equal{\dtl@refvalue}{#5}}{% +\global\let#1=\dtl@valueA +\@endfortrue +}{}}}% +}} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLgetrowforkey} +%\begin{definition} +%\cs{DTLgetrowforkey}\marg{cmd}\marg{db name}\marg{ref +% key}\marg{ref value} +%\end{definition} +% This (globally) sets \meta{cmd} (a control sequence) to the +% first row +% of the database called \meta{db name} which contains the key +% \meta{ref key} which has the value \meta{value}. +%\changes{1.01}{2007 Aug 17}{new} +% \begin{macrocode} +\newcommand*{\DTLgetrowforkey}[4]{% +{% +\global\let#1=\@empty +\@sDTLforeach{#2}{\dtl@refvalue=#3}{% +\DTLifnull{\dtl@refvalue}{}{% +\ifthenelse{\equal{\dtl@refvalue}{#4}}{% +\expandafter\global\expandafter\let\expandafter#1 + \csname @dtl@thiscurrentrow@\romannumeral\dtlforeachlevel\endcsname +\@endfortrue +}{}}}% +}} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLsort} +%\begin{definition} +% \cs{DTLsort}\oarg{replacement keys}\marg{sort criteria}\marg{db name} +%\end{definition} +% Sorts database \meta{db name} according to \marg{sort criteria}, +% which must be a comma separated list of keys, and optionally +% \texttt{=}\meta{order}, where \meta{order} is either +% "ascending" or "descending". The optional argument is a list of +% keys to uses if the given key has a null value. The starred +% version uses a case insensitive string comparison. +%\changes{1.01}{2007 Aug 17}{added optional argument} +%\changes{1.01}{2007 Aug 17}{added starred version} +% \begin{macrocode} +\newcommand*{\DTLsort}{\@ifstar\@sDTLsort\@DTLsort} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\@DTLsort} +% Unstarred (case sensitive) version. +% \begin{macrocode} +\newcommand*{\@DTLsort}[3][]{% +\edef\@dtl@replacementkeys{#1}% +\edef\@dtl@sortorder{#2}% +\edef\@dtl@dbname{#3}% +\let\@dtl@comparecs=\dtlcompare +\expandafter\let\expandafter\@dtl@list\csname dtldb@#3\endcsname +\dtl@sortlist{\@dtl@list}{\@dtl@sortcriteria}% +\expandafter\global\expandafter + \let\csname dtldb@#3\endcsname=\@dtl@list} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\@sDTLsort} +% Starred (case insensitive) version. +% \begin{macrocode} +\newcommand*{\@sDTLsort}[3][]{% +\edef\@dtl@replacementkeys{#1}% +\edef\@dtl@sortorder{#2}% +\edef\@dtl@dbname{#3}% +\let\@dtl@comparecs=\dtlicompare +\expandafter\let\expandafter\@dtl@list\csname dtldb@#3\endcsname +\dtl@sortlist{\@dtl@list}{\@dtl@sortcriteria}% +\expandafter\global\expandafter + \let\csname dtldb@#3\endcsname=\@dtl@list} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\@dtl@sortcriteria} +%\begin{definition} +% \cs{@dtl@sortcriteria}\marg{a}\marg{b} +%\end{definition} +% Sort criteria. \cs{@dtl@dbname} and +% \cs{@dtl@sortorder} must be set before use. +% \begin{macrocode} +\newcommand{\@dtl@sortcriteria}[2]{% +\@for\@dtl@level:=\@dtl@sortorder\do{% + \expandafter\@dtl@getsortdirection\@dtl@level=\relax% + \@ifundefined{@dtl@idtype@\@dtl@dbname @\@dtl@key}{% + \ifx\@dtl@replacementkeys\@empty + \PackageError{datatool}{Unknown key `\@dtl@key' for database + `\@dtl@dbname'}{}% + \else + \dtl@gathervalues[keya]{\@dtl@dbname}{#1}% + \dtl@gathervalues[keyb]{\@dtl@dbname}{#2}% + \@ifundefined{@dtl@keya@\@dtl@key}{% + \@dtl@setnull{\@dtl@tmpa}{\@dtl@key}% + }{% + \expandafter\let\expandafter\@dtl@tmpa\expandafter + =\csname @dtl@keya@\@dtl@key\endcsname}% + \@ifundefined{@dtl@keyb@\@dtl@key}{% + \@dtl@setnull{\@dtl@tmpb}{\@dtl@key}% + }{% + \expandafter\let\expandafter\@dtl@tmpb\expandafter + =\csname @dtl@keyb@\@dtl@key\endcsname}% + \let\@dtl@keya=\@dtl@key + \let\@dtl@keyb=\@dtl@key + \DTLifnull{\@dtl@tmpa}{% + % find first non null key in list of replacement keys + \@for\@dtl@keya:=\@dtl@replacementkeys\do{% + \@ifundefined{@dtl@keya@\@dtl@keya}{}{% + \expandafter\let\expandafter\@dtl@tmpa\expandafter + =\csname @dtl@keya@\@dtl@keya\endcsname + \DTLifnull{\@dtl@tmpa}{}{\@endfortrue}}% + }% + \if@endfor \else\let\@dtl@keya=\@dtl@key \fi + \@endforfalse + }{}% + \DTLifnull{\@dtl@tmpb}{% + % find first non null key in list of replacement keys + \@for\@dtl@keyb:=\@dtl@replacementkeys\do{% + \@ifundefined{@dtl@keyb@\@dtl@keyb}{}{% + \expandafter\let\expandafter\@dtl@tmpb\expandafter + =\csname @dtl@keyb@\@dtl@keyb\endcsname + \DTLifnull{\@dtl@tmpb}{}{\@endfortrue}}% + }% + \if@endfor \else\let\@dtl@keyb=\@dtl@key \fi + \@endforfalse + }{}% + \@ifundefined{@dtl@idtype@\@dtl@dbname @\@dtl@keya}{% + \@ifundefined{@dtl@idtype@\@dtl@dbname @\@dtl@keyb}{% + \dtl@sortresult=0\relax}{\dtl@sortresult=-1\relax}% + }{% + \@ifundefined{@dtl@idtype@\@dtl@dbname @\@dtl@keyb}{% + \dtl@sortresult=1\relax}{% + \dtl@compare@{\@dtl@keya}{\@dtl@keyb}{#1}{#2}% + }% + }% + \fi + }{% + \ifx\@dtl@replacementkeys\@empty + \dtl@compare{\@dtl@key}{#1}{#2}% + \else + \dtl@gathervalues[keya]{\@dtl@dbname}{#1}% + \dtl@gathervalues[keyb]{\@dtl@dbname}{#2}% + \@ifundefined{@dtl@keya@\@dtl@key}{% + \@dtl@setnull{\@dtl@tmpa}{\@dtl@key}% + }{% + \expandafter\let\expandafter\@dtl@tmpa\expandafter + =\csname @dtl@keya@\@dtl@key\endcsname}% + \@ifundefined{@dtl@keyb@\@dtl@key}{% + \@dtl@setnull{\@dtl@tmpb}{\@dtl@key}% + }{% + \expandafter\let\expandafter\@dtl@tmpb\expandafter + =\csname @dtl@keyb@\@dtl@key\endcsname}% + \let\@dtl@keya=\@dtl@key + \let\@dtl@keyb=\@dtl@key + \DTLifnull{\@dtl@tmpa}{% + % find first non null key in list of replacement keys + \@for\@dtl@keya:=\@dtl@replacementkeys\do{% + \@ifundefined{@dtl@keya@\@dtl@keya}{}{% + \expandafter\let\expandafter\@dtl@tmpa\expandafter + =\csname @dtl@keya@\@dtl@keya\endcsname + \DTLifnull{\@dtl@tmpa}{}{\@endfortrue}}% + }% + \if@endfor \else\let\@dtl@keya=\@dtl@key \fi + \@endforfalse + }{}% + \DTLifnull{\@dtl@tmpb}{% + % find first non null key in list of replacement keys + \@for\@dtl@keyb:=\@dtl@replacementkeys\do{% + \@ifundefined{@dtl@keyb@\@dtl@keyb}{}{% + \expandafter\let\expandafter\@dtl@tmpb\expandafter + =\csname @dtl@keyb@\@dtl@keyb\endcsname + \DTLifnull{\@dtl@tmpb}{}{\@endfortrue}}% + }% + \if@endfor \else\let\@dtl@keyb=\@dtl@key \fi + \@endforfalse + }{}% + \dtl@compare@{\@dtl@keya}{\@dtl@keyb}{#1}{#2}% + \fi + \multiply\dtl@sortresult by \@dtl@sortdirection\relax + \ifnum\dtl@sortresult=0\relax + \else + \@endfortrue + \fi + }% +}% +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\@dtl@getsortdirection} +% Get the direction from either \meta{key} or +% \meta{key}=\meta{direction}. Sets \cs{@dtl@sortdirection} to +% either -1 (ascending) or 1 (descending). +% \begin{macrocode} +\def\@dtl@getsortdirection#1=#2\relax{% +\def\@dtl@key{#1}% +\def\@dtl@sortdirection{#2}% +\ifx\@dtl@sortdirection\@empty + \def\@dtl@sortdirection{-1}% +\else + \@dtl@get@sortdirection#2% + \ifthenelse{\equal{\@dtl@sortdirection}{ascending}}{% + \def\@dtl@sortdirection{-1}}{% + \ifthenelse{\equal{\@dtl@sortdirection}{descending}}{% + \def\@dtl@sortdirection{1}}{% + \PackageError{datatool}{Invalid sort direction + `\@dtl@sortdirection'}{% + The sort direction can only be one of `ascending' or + `descending'}\def\@dtl@sortdirection{-1}}}% +\fi +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\@dtl@get@sortdirection} +% Get direction +% \begin{macrocode} +\def\@dtl@get@sortdirection#1={\def\@dtl@sortdirection{#1}} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\dtl@compare} +%\begin{definition} +%\cs{dtl@compare}\marg{key}\marg{a}\marg{b} +%\end{definition} +% Compares \meta{a} and \meta{b} according to \meta{key} of +% database given by \cs{@dtl@dbname}. Sets \cs{dtl@sortresult}. +% \cs{@dtl@comparecs} must be set to the required comparison macro. +% \begin{macrocode} +\newtoks\@dtl@toksA\newtoks\@dtl@toksB +\newcommand{\dtl@compare}[3]{% +\dtl@gathervalues{\@dtl@dbname}{#2}% +\expandafter\let\expandafter\@dtl@tmp\expandafter + =\csname @dtl@key@#1\endcsname +\expandafter\@dtl@toksA\expandafter{\@dtl@tmp}% +\edef\@dtl@a{\the\@dtl@toksA}% +\dtl@gathervalues{\@dtl@dbname}{#3}% +\expandafter\let\expandafter\@dtl@tmp\expandafter + =\csname @dtl@key@#1\endcsname +\expandafter\@dtl@toksB\expandafter{\@dtl@tmp}% +\edef\@dtl@b{\the\@dtl@toksB}% +\expandafter\@dtl@datatype\expandafter= + \csname @dtl@idtype@\@dtl@dbname @#1\endcsname\relax +\ifnum\@dtl@datatype=0\relax + \edef\@dtl@tmpcmp{% + \noexpand\@dtl@comparecs{\noexpand\dtl@sortresult}% + {\the\@dtl@toksA}{\the\@dtl@toksB}}% + \@dtl@tmpcmp +\else + \DTLifnumlt{\@dtl@a}{\@dtl@b}{\dtl@sortresult=-1\relax}{% + \DTLifnumgt{\@dtl@a}{\@dtl@b}{\dtl@sortresult=1\relax}{% + \dtl@sortresult=0\relax}}% +\fi +\ifdtlverbose +\@onelevel@sanitize\@dtl@a +\@onelevel@sanitize\@dtl@b +\fi +\dtl@message{`\@dtl@a' <=> `\@dtl@b' = \number\dtl@sortresult}% +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\dtl@compare@} +%\begin{definition} +%\cs{dtl@compare@}\marg{keya}\marg{keyb}\marg{a}\marg{b} +%\end{definition} +% Compare \meta{a} and \meta{b} according to \meta{keya} +% and \meta{keyb} of +% database given by \cs{@dtl@dbname}. Sets \cs{dtl@sortresult}. +% \cs{@dtl@comparecs} must be set. +% \begin{macrocode} +\newcommand{\dtl@compare@}[4]{% +\dtl@gathervalues{\@dtl@dbname}{#3}% +\expandafter\let\expandafter\@dtl@tmp\expandafter + =\csname @dtl@key@#1\endcsname +\expandafter\@dtl@toksA\expandafter{\@dtl@tmp}% +\edef\@dtl@a{\the\@dtl@toksA}% +\dtl@gathervalues{\@dtl@dbname}{#4}% +\expandafter\let\expandafter\@dtl@tmp\expandafter + =\csname @dtl@key@#2\endcsname +\expandafter\@dtl@toksB\expandafter{\@dtl@tmp}% +\edef\@dtl@b{\the\@dtl@toksB}% +\expandafter\@dtl@tmpcount\expandafter= + \csname @dtl@idtype@\@dtl@dbname @#1\endcsname\relax +\expandafter\@dtl@datatype\expandafter= + \csname @dtl@idtype@\@dtl@dbname @#2\endcsname\relax +\multiply\@dtl@datatype by \@dtl@tmpcount\relax +\ifnum\@dtl@datatype=0\relax + \edef\@dtl@tmpcmp{% + \noexpand\@dtl@comparecs{\noexpand\dtl@sortresult}% + {\the\@dtl@toksA}{\the\@dtl@toksB}}% + \@dtl@tmpcmp +\else + \DTLifnumlt{\@dtl@a}{\@dtl@b}{\dtl@sortresult=-1\relax}{% + \DTLifnumgt{\@dtl@a}{\@dtl@b}{\dtl@sortresult=1\relax}{% + \dtl@sortresult=0\relax}}% +\fi +\ifdtlverbose +\@onelevel@sanitize\@dtl@a +\@onelevel@sanitize\@dtl@b +\fi +\dtl@message{`\@dtl@a' <=> `\@dtl@b' = \number\dtl@sortresult}% +} +% \end{macrocode} +%\end{macro} +% +%\subsection{General List Utilities} +% +%\begin{macro}{\dtl@choplast} +%\begin{definition} +% \cs{dtl@choplast}\marg{list}\marg{rest}\marg{last} +%\end{definition} +% Chops the last element off a comma separated list, putting the +% last element in the control sequence \meta{last} and putting +% the rest in the control sequence \meta{rest}. The control +% sequence \meta{list} is unchanged. If the list is empty, both +% \meta{last} and \meta{rest} will be empty. +% \begin{macrocode} +\newcommand*{\dtl@choplast}[3]{% +% \end{macrocode} +% Set \meta{rest} to empty: +% \begin{macrocode} +\let#2\@empty +% \end{macrocode} +% Set \meta{last} to empty: +% \begin{macrocode} +\let#3\@empty +% \end{macrocode} +% Iterate through \meta{list}: +% \begin{macrocode} +\@for\@dtl@element:=#1\do{% +\ifx#3\@empty +% \end{macrocode} +% First iteration, don't set \meta{rest}. +% \begin{macrocode} +\else + \ifx#2\@empty +% \end{macrocode} +% Second iteration, set \meta{rest} to \meta{last} (which is +% currently set to the previous value: +% \begin{macrocode} + \expandafter\toks@\expandafter{#3}% + \edef#2{{\the\toks@}}% + \else +% \end{macrocode} +% Subsequent iterations, set \meta{rest} to \meta{rest},\meta{last} +% (\meta{last} is currently set to the previous value): +% \begin{macrocode} + \expandafter\toks@\expandafter{#3}% + \expandafter\@dtl@toks\expandafter{#2}% + \edef#2{\the\@dtl@toks,{\the\toks@}}% + \fi +\fi +% \end{macrocode} +% Now set \meta{last} to current element. +% \begin{macrocode} +\let#3=\@dtl@element% +}% +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\dtl@chopfirst} +%\begin{definition} +% \cs{dtl@chopfirst}\marg{list}\marg{first}\marg{rest} +%\end{definition} +% Chops first element off \meta{list} and store in \meta{first}. +% The remainder of the list is stored in \meta{rest}. (\meta{list} +% remains unchanged.) +% \begin{macrocode} +\newcommand*{\dtl@chopfirst}[3]{% +\let#2=\@empty +\let#3=\@empty +\@for\@dtl@element:=#1\do{% + \let#2=\@dtl@element + \@endfortrue +}% +\if@endfor + \let#3=\@forremainder +\fi +\@endforfalse +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\dtl@sortlist} +%\begin{definition} +% \cs{dtl@sortlist}\marg{list}\marg{criteria cmd} +%\end{definition} +% Performs an insertion sort on \meta{list}, where \meta{criteria cmd} +% is a macro which takes two arguments \meta{a} and \meta{b}. +% \meta{criteria cmd} must set the count register \cs{dtl@sortresult} +% to either -1 (\meta{a} less than \meta{b}), 0 (\meta{a} is +% equal to \meta{b}) or 1 (\meta{a} is greater than \meta{b}.) +% \begin{macrocode} +\newcommand{\dtl@sortlist}[2]{% +\def\@dtl@sortedlist{}% +\@for\@dtl@currentrow:=#1\do{% +\expandafter\dtl@insertinto\expandafter + {\@dtl@currentrow}{\@dtl@sortedlist}{#2}% +\@endforfalse}% +\let#1=\@dtl@sortedlist +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\dtl@insertinto} +%\begin{definition} +% \cs{dtl@insertinto}\marg{element}\marg{sorted-list}\marg{criteria cmd} +%\end{definition} +% Inserts \meta{element} into the sorted list \meta{sorted-list} +% according to the criteria given by \meta{criteria cmd} (see above.) +% \begin{macrocode} +\newtoks\@dtl@toks +\newcommand{\dtl@insertinto}[3]{% +\def\@dtl@newsortedlist{}% +\@dtl@insertdonefalse +\@for\dtl@srtelement:=#2\do{% +\if@dtl@insertdone + \expandafter\toks@\expandafter{\dtl@srtelement}% + \edef\@dtl@newstuff{{\the\toks@}}% +\else + \expandafter#3\expandafter{\dtl@srtelement}{#1}% + \ifnum\dtl@sortresult<0\relax + \expandafter\toks@\expandafter{\dtl@srtelement}% + \@dtl@toks{#1}% + \edef\@dtl@newstuff{{\the\@dtl@toks},{\the\toks@}}% + \@dtl@insertdonetrue + \else + \expandafter\toks@\expandafter{\dtl@srtelement}% + \edef\@dtl@newstuff{{\the\toks@}}% + \fi +\fi +\ifx\@dtl@newsortedlist\@empty + \expandafter\toks@\expandafter{\@dtl@newstuff}% + \edef\@dtl@newsortedlist{\the\toks@}% +\else + \expandafter\toks@\expandafter{\@dtl@newsortedlist}% + \expandafter\@dtl@toks\expandafter{\@dtl@newstuff}% + \edef\@dtl@newsortedlist{\the\toks@,\the\@dtl@toks}% +\fi +\@endforfalse +}% + \ifx\@dtl@newsortedlist\@empty + \@dtl@toks{#1}% + \edef\@dtl@newsortedlist{{\the\@dtl@toks}}% + \else + \if@dtl@insertdone + \else + \expandafter\toks@\expandafter{\@dtl@newsortedlist}% + \@dtl@toks{#1}% + \edef\@dtl@newsortedlist{\the\toks@,{\the\@dtl@toks}}% + \fi + \fi +\global\let#2=\@dtl@newsortedlist +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\if@dtl@insertdone} +% Define conditional to indicate whether the new entry has +% been inserted into the sorted list. +% \begin{macrocode} +\newif\if@dtl@insertdone +% \end{macrocode} +%\end{macro} +%\begin{macro}{\dtl@sortresult} +% Define \cs{dtl@sortresult} to be set by comparision macro. +% \begin{macrocode} +\newcount\dtl@sortresult +% \end{macrocode} +%\end{macro} +% +% \subsection{Floating Point Arithmetic} +% The commands defined in this section all use the equivalent +% commands provided by the \sty{fp} package, but first convert +% the decimal number into the required format. +% +%\begin{macro}{\DTLadd} +%\begin{definition} +% \cs{DTLadd}\marg{cmd}\marg{num1}\marg{num2} +%\end{definition} +% Sets \meta{cmd} = \meta{num1} + \meta{num2} +% \begin{macrocode} +\newcommand*{\DTLadd}[3]{% +\DTLconverttodecimal{#2}{\@dtl@numi}% +\DTLconverttodecimal{#3}{\@dtl@numii}% +\FPadd{\@dtl@tmp}{\@dtl@numi}{\@dtl@numii}% +\ifx\@dtl@replaced\@empty + \DTLdecimaltolocale{\@dtl@tmp}{#1}% +\else + \DTLdecimaltocurrency{\@dtl@tmp}{#1}% +\fi +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLgadd} +% Global version +% \begin{macrocode} +\newcommand*{\DTLgadd}[3]{% +\DTLadd{\@dtl@tmpii}{#2}{#3}% +\global\let#1=\@dtl@tmpii +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLaddall} +%\begin{definition} +%\cs{DTLaddall}\marg{cmd}\marg{num list} +%\end{definition} +% Sums all the values in \meta{num list} and stores in +% \meta{cmd} which must be a control sequence. +%\changes{1.01}{2007 Aug 17}{removed extraneous space} +% \begin{macrocode} +\newcommand*{\DTLaddall}[2]{% +\def\@dtl@sum{0}% +\@for\dtl@thisval:=#2\do{% + \DTLconverttodecimal{\dtl@thisval}{\@dtl@num}% + \FPadd{\@dtl@sum}{\@dtl@sum}{\@dtl@num}% +}% +\ifx\@dtl@replaced\@empty + \DTLdecimaltolocale{\@dtl@sum}{#1}% +\else + \DTLdecimaltocurrency{\@dtl@sum}{#1}% +\fi +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLgaddall} +%\begin{definition} +%\cs{DTLgaddall}\marg{cmd}\marg{num list} +%\end{definition} +% Global version +% \begin{macrocode} +\newcommand*{\DTLgaddall}[2]{% +\DTLaddall{\@dtl@tmpi}{#2}% +\global\let#1=\@dtl@tmpi +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLsub} +%\begin{definition} +% \cs{DTLsub}\marg{cmd}\marg{num1}\marg{num2} +%\end{definition} +% Sets \meta{cmd} = \meta{num1} - \meta{num2} +% \begin{macrocode} +\newcommand*{\DTLsub}[3]{% +\DTLconverttodecimal{#2}{\@dtl@numi}% +\DTLconverttodecimal{#3}{\@dtl@numii}% +\FPsub{\@dtl@tmp}{\@dtl@numi}{\@dtl@numii}% +\ifx\@dtl@replaced\@empty + \DTLdecimaltolocale{\@dtl@tmp}{#1}% +\else + \DTLdecimaltocurrency{\@dtl@tmp}{#1}% +\fi +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLgsub} +% Global version +% \begin{macrocode} +\newcommand*{\DTLgsub}[3]{% +\DTLsub{\@dtl@tmpii}{#2}{#3}% +\global\let#1=\@dtl@tmpii +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLmul} +%\begin{definition} +% \cs{DTLmul}\marg{cmd}\marg{num1}\marg{num2} +%\end{definition} +% Sets \meta{cmd} = \meta{num1} $\times$ \meta{num2} +% \begin{macrocode} +\newcommand*{\DTLmul}[3]{% +\let\@dtl@thisreplaced=\@empty +\DTLconverttodecimal{#2}{\@dtl@numi}% +\ifx\@dtl@replaced\@empty +\else + \let\@dtl@thisreplaced=\@dtl@replaced +\fi +\DTLconverttodecimal{#3}{\@dtl@numii}% +\ifx\@dtl@replaced\@empty +\else + \let\@dtl@thisreplaced=\@dtl@replaced +\fi +\FPmul{\@dtl@tmp}{\@dtl@numi}{\@dtl@numii}% +\ifx\@dtl@thisreplaced\@empty + \DTLdecimaltolocale{\@dtl@tmp}{#1}% +\else + \DTLdecimaltocurrency{\@dtl@tmp}{#1}% +\fi +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLgmul} +% Global version +% \begin{macrocode} +\newcommand*{\DTLgmul}[3]{% +\DTLmul{\@dtl@tmpii}{#2}{#3}% +\global\let#1=\@dtl@tmpii +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLdiv} +%\begin{definition} +% \cs{DTLdiv}\marg{cmd}\marg{num1}\marg{num2} +%\end{definition} +% Sets \meta{cmd} = \meta{num1} / \meta{num2} +% \begin{macrocode} +\newcommand*{\DTLdiv}[3]{% +\let\@dtl@thisreplaced=\@empty +\DTLconverttodecimal{#2}{\@dtl@numi}% +\ifx\@dtl@replaced\@empty +\else + \let\@dtl@thisreplaced=\@dtl@replaced +\fi +\DTLconverttodecimal{#3}{\@dtl@numii}% +\FPdiv{\@dtl@tmp}{\@dtl@numi}{\@dtl@numii}% +\ifx\@dtl@thisreplaced\@empty + \DTLdecimaltolocale{\@dtl@tmp}{#1}% +\else + \ifx\@dtl@thisreplaced\@dtl@replaced + \DTLdecimaltolocale{\@dtl@tmp}{#1}% + \else + \DTLdecimaltocurrency{\@dtl@tmp}{#1}% + \fi +\fi +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLgdiv} +% Global version +% \begin{macrocode} +\newcommand*{\DTLgdiv}[3]{% +\DTLdiv{\@dtl@tmpii}{#2}{#3}% +\global\let#1=\@dtl@tmpii +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLabs} +%\begin{definition} +% \cs{DTLabs}\marg{cmd}\marg{num} +%\end{definition} +% Sets \meta{cmd} = abs(\meta{num}) +% \begin{macrocode} +\newcommand*{\DTLabs}[2]{% +\DTLconverttodecimal{#2}{\@dtl@numi}% +\FPabs{\@dtl@tmp}{\@dtl@numi}% +\ifx\@dtl@replaced\@empty + \DTLdecimaltolocale{\@dtl@tmp}{#1}% +\else + \DTLdecimaltocurrency{\@dtl@tmp}{#1}% +\fi +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLgabs} +% Global version +% \begin{macrocode} +\newcommand*{\DTLgabs}[2]{% +\DTLabs{\@dtl@tmpii}{#2}% +\global\let#1=\@dtl@tmpii +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLneg} +%\begin{definition} +% \cs{DTLneg}\marg{cmd}\marg{num} +%\end{definition} +% Sets \meta{cmd} = -\meta{num} +% \begin{macrocode} +\newcommand*{\DTLneg}[2]{% +\DTLconverttodecimal{#2}{\@dtl@numi}% +\FPneg{\@dtl@tmp}{\@dtl@numi}% +\ifx\@dtl@replaced\@empty + \DTLdecimaltolocale{\@dtl@tmp}{#1}% +\else + \DTLdecimaltocurrency{\@dtl@tmp}{#1}% +\fi +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLgneg} +% Global version +% \begin{macrocode} +\newcommand*{\DTLgneg}[2]{% +\DTLneg{\@dtl@tmpii}{#2}% +\global\let#1=\@dtl@tmpii +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLsqrt} +%\begin{definition} +% \cs{DTLsqrt}\marg{cmd}\marg{num} +%\end{definition} +% Sets \meta{cmd} = sqrt(\meta{num}) +% \begin{macrocode} +\newcommand*{\DTLsqrt}[2]{% +\DTLconverttodecimal{#2}{\@dtl@numi}% +\FProot{\@dtl@tmpi}{\@dtl@numi}{2}% +\ifx\@dtl@replaced\@empty + \DTLdecimaltolocale{\@dtl@tmpi}{#1}% +\else + \DTLdecimaltocurrency{\@dtl@tmpi}{#1}% +\fi +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLgsqrt} +% Global version +% \begin{macrocode} +\newcommand*{\DTLgsqrt}[2]{% +\DTLsqrt{\@dtl@tmpii}{#2}% +\global\let#1=\@dtl@tmpii +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLmin} +%\begin{definition} +% \cs{DTLmin}\marg{cmd}\marg{num1}\marg{num2} +%\end{definition} +% Sets \meta{cmd} = min(\meta{num1}, \meta{num2}) +% \begin{macrocode} +\newcommand*{\DTLmin}[3]{% +\DTLconverttodecimal{#2}{\@dtl@numi}% +\DTLconverttodecimal{#3}{\@dtl@numii}% +\FPiflt{\@dtl@numi}{\@dtl@numii}% + \dtl@ifsingle{#2}{% + \let#1=#2}{% + \def#1{#2}}% +\else + \dtl@ifsingle{#3}{% + \let#1=#3}{% + \def#1{#3}}% +\fi +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLgmin} +% Global version +% \begin{macrocode} +\newcommand*{\DTLgmin}[3]{% +\DTLmin{\@dtl@tmpii}{#2}{#3}% +\global\let#1=\@dtl@tmpii +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLminall} +%\begin{definition} +%\cs{DTLminall}\marg{cmd}\marg{num list} +%\end{definition} +% Finds the minimum value in \meta{num list} and stores in +% \meta{cmd} which must be a control sequence. +%\changes{1.01}{2007 Aug 17}{removed extraneous space} +% \begin{macrocode} +\newcommand*{\DTLminall}[2]{% +\let\@dtl@min=\@empty +\@for\dtl@thisval:=#2\do{% + \DTLconverttodecimal{\dtl@thisval}{\@dtl@num}% + \ifx\@dtl@min\@empty + \let\@dtl@min=\@dtl@num + \else + \FPmin{\@dtl@min}{\@dtl@min}{\@dtl@num}% + \fi +}% +\ifx\@dtl@replaced\@empty + \DTLdecimaltolocale{\@dtl@min}{#1}% +\else + \DTLdecimaltocurrency{\@dtl@min}{#1}% +\fi +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLgminall} +%\begin{definition} +%\cs{DTLgminall}\marg{cmd}\marg{num list} +%\end{definition} +% Global version +% \begin{macrocode} +\newcommand*{\DTLgminall}[2]{% +\DTLminall{\@dtl@tmpi}{#2}% +\global\let#1=\@dtl@tmpi +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLmax} +%\begin{definition} +% \cs{DTLmax}\marg{cmd}\marg{num1}\marg{num2} +%\end{definition} +% Sets \meta{cmd} = max(\meta{num1}, \meta{num2}) +% \begin{macrocode} +\newcommand*{\DTLmax}[3]{% +\DTLconverttodecimal{#2}{\@dtl@numi}% +\DTLconverttodecimal{#3}{\@dtl@numii}% +\FPmax{\@dtl@tmp}{\@dtl@numi}{\@dtl@numii}% +\FPifgt{\@dtl@numi}{\@dtl@numii}% + \dtl@ifsingle{#2}{% + \let#1=#2}{% + \def#1{#2}}% +\else + \dtl@ifsingle{#3}{% + \let#1=#3}{% + \def#1{#3}}% +\fi +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLgmax} +% Global version +% \begin{macrocode} +\newcommand*{\DTLgmax}[3]{% +\DTLmax{\@dtl@tmpii}{#2}{#3}% +\global\let#1=\@dtl@tmpii +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLmaxall} +%\begin{definition} +%\cs{DTLmaxall}\marg{cmd}\marg{num list} +%\end{definition} +% Finds the maximum value in \meta{num list} and stores in +% \meta{cmd} which must be a control sequence. +%\changes{1.01}{2007 Aug 17}{removed extraneous space} +% \begin{macrocode} +\newcommand*{\DTLmaxall}[2]{% +\let\@dtl@max=\@empty +\@for\dtl@thisval:=#2\do{% + \DTLconverttodecimal{\dtl@thisval}{\@dtl@num}% + \ifx\@dtl@max\@empty + \let\@dtl@max\@dtl@num + \else + \FPmax{\@dtl@max}{\@dtl@max}{\@dtl@num}% + \fi +}% +\ifx\@dtl@replaced\@empty + \DTLdecimaltolocale{\@dtl@max}{#1}% +\else + \DTLdecimaltocurrency{\@dtl@max}{#1}% +\fi +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLgmaxall} +%\begin{definition} +%\cs{DTLgmaxall}\marg{cmd}\marg{num list} +%\end{definition} +% Global version +% \begin{macrocode} +\newcommand*{\DTLgmaxall}[2]{% +\DTLmaxall{\@dtl@tmpi}{#2}% +\global\let#1=\@dtl@tmpi +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLmeanforall} +%\begin{definition} +%\cs{DTLmeanforall}\marg{cmd}\marg{num list} +%\end{definition} +% Computes the arithmetic mean of all the values in \meta{num list} +% and stores in \meta{cmd} which must be a control sequence. +%\changes{1.01}{2007 Aug 17}{removed extraneous space} +% \begin{macrocode} +\newcommand*{\DTLmeanforall}[2]{% +\def\@dtl@mean{0}% +\def\@dtl@n{0}% +\@for\dtl@thisval:=#2\do{% + \DTLconverttodecimal{\dtl@thisval}{\@dtl@num}% + \FPadd{\@dtl@mean}{\@dtl@mean}{\@dtl@num}% + \FPadd{\@dtl@n}{\@dtl@n}{1}% +}% +\FPdiv{\@dtl@mean}{\@dtl@mean}{\@dtl@n}% +\ifx\@dtl@replaced\@empty + \DTLdecimaltolocale{\@dtl@mean}{#1}% +\else + \DTLdecimaltocurrency{\@dtl@mean}{#1}% +\fi +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLgmeanforall} +%\begin{definition} +%\cs{DTLgmeanforall}\marg{cmd}\marg{num list} +%\end{definition} +% Global version +% \begin{macrocode} +\newcommand*{\DTLgmeanforall}[2]{% +\DTLmeanforall{\@dtl@tmpi}{#2}% +\global\let#1=\@dtl@tmpi +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLvarianceforall} +%\begin{definition} +%\cs{DTLvarianceforall}\marg{cmd}\marg{num list} +%\end{definition} +% Computes the variance of all the values in \meta{num list} +% and stores in \meta{cmd} which must be a control sequence. +%\changes{1.01}{2007 Aug 17}{fixed bug} +%\changes{1.01}{2007 Aug 17}{removed extraneous space} +% \begin{macrocode} +\newcommand*{\DTLvarianceforall}[2]{% +\def\@dtl@mean{0}% +\def\@dtl@n{0}% +\let\@dtl@decvals=\@empty +\@for\dtl@thisval:=#2\do{% + \DTLconverttodecimal{\dtl@thisval}{\@dtl@num}% + \ifx\@dtl@decvals\@empty + \let\@dtl@decvals=\@dtl@num + \else + \expandafter\toks@\expandafter{\@dtl@decvals}% + \edef\@dtl@decvals{\the\toks@,\@dtl@num}% + \fi + \FPadd{\@dtl@mean}{\@dtl@mean}{\@dtl@num}% + \FPadd{\@dtl@n}{\@dtl@n}{1}% +}% +\FPdiv{\@dtl@mean}{\@dtl@mean}{\@dtl@n}% +\def\@dtl@var{0}% +\@for\@dtl@num:=\@dtl@decvals\do{% + \FPsub{\@dtl@diff}{\@dtl@num}{\@dtl@mean}% + \FPmul{\@dtl@diff}{\@dtl@diff}{\@dtl@diff}% + \FPadd{\@dtl@var}{\@dtl@var}{\@dtl@diff}% +}% +\FPdiv{\@dtl@var}{\@dtl@var}{\@dtl@n}% +\ifx\@dtl@replaced\@empty + \DTLdecimaltolocale{\@dtl@var}{#1}% +\else + \DTLdecimaltocurrency{\@dtl@var}{#1}% +\fi +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLgvarianceforall} +%\begin{definition} +%\cs{DTLgvarianceforall}\marg{cmd}\marg{num list} +%\end{definition} +% Global version +% \begin{macrocode} +\newcommand*{\DTLgvarianceforall}[2]{% +\DTLvarianceforall{\@dtl@tmpi}{#2}% +\global\let#1=\@dtl@tmpi +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLsdforall} +%\begin{definition} +%\cs{DTLsdforall}\marg{cmd}\marg{num list} +%\end{definition} +% Computes the standard deviation of all the values in \meta{num list} +% and stores in \meta{cmd} which must be a control sequence. +%\changes{1.01}{2007 Aug 17}{fixed bug} +%\changes{1.01}{2007 Aug 17}{removed extraneous space} +% \begin{macrocode} +\newcommand*{\DTLsdforall}[2]{% +\def\@dtl@mean{0}% +\def\@dtl@n{0}% +\let\@dtl@decvals=\@empty +\@for\dtl@thisval:=#2\do{% + \DTLconverttodecimal{\dtl@thisval}{\@dtl@num}% + \ifx\@dtl@decvals\@empty + \let\@dtl@decvals=\@dtl@num + \else + \expandafter\toks@\expandafter{\@dtl@decvals}% + \edef\@dtl@decvals{\the\toks@,\@dtl@num}% + \fi + \FPadd{\@dtl@mean}{\@dtl@mean}{\@dtl@num}% + \FPadd{\@dtl@n}{\@dtl@n}{1}% +}% +\FPdiv{\@dtl@mean}{\@dtl@mean}{\@dtl@n}% +\def\@dtl@sd{0}% +\@for\@dtl@num:=\@dtl@decvals\do{% + \FPsub{\@dtl@diff}{\@dtl@num}{\@dtl@mean}% + \FPmul{\@dtl@diff}{\@dtl@diff}{\@dtl@diff}% + \FPadd{\@dtl@sd}{\@dtl@sd}{\@dtl@diff}% +}% +\FPdiv{\@dtl@sd}{\@dtl@sd}{\@dtl@n}% +\FProot{\@dtl@sd}{\@dtl@sd}{2}% +\ifx\@dtl@replaced\@empty + \DTLdecimaltolocale{\@dtl@sd}{#1}% +\else + \DTLdecimaltocurrency{\@dtl@sd}{#1}% +\fi +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLgsdforall} +%\begin{definition} +%\cs{DTLgsdforall}\marg{cmd}\marg{num list} +%\end{definition} +% Global version +% \begin{macrocode} +\newcommand*{\DTLgsdforall}[2]{% +\DTLsdforall{\@dtl@tmpi}{#2}% +\global\let#1=\@dtl@tmpi +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLround} +%\begin{definition} +% \cs{DTLround}\marg{cmd}\marg{num}\marg{num digits} +%\end{definition} +% Sets \meta{cmd} to \meta{num} rounded to \meta{num digits} +% digits after the decimal character. +% \begin{macrocode} +\newcommand*{\DTLround}[3]{% +\DTLconverttodecimal{#2}{\@dtl@numi}% +\FPround{\@dtl@tmp}{\@dtl@numi}{#3}% +\ifx\@dtl@replaced\@empty + \DTLdecimaltolocale{\@dtl@tmp}{#1}% +\else + \DTLdecimaltocurrency{\@dtl@tmp}{#1}% +\fi +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLground} +% Global version +% \begin{macrocode} +\newcommand*{\DTLground}[3]{% +\DTLround{\@dtl@tmpii}{#2}{#3}% +\global\let#1=\@dtl@tmpii +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLtrunc} +%\begin{definition} +% \cs{DTLtrunc}\marg{cmd}\marg{num}\marg{num digits} +%\end{definition} +% Sets \meta{cmd} to \meta{num} truncated to \meta{num digits} +% digits after the decimal character. +% \begin{macrocode} +\newcommand*{\DTLtrunc}[3]{% +\DTLconverttodecimal{#2}{\@dtl@numi}% +\FPtrunc{\@dtl@tmp}{\@dtl@numi}{#3}% +\ifx\@dtl@replaced\@empty + \DTLdecimaltolocale{\@dtl@tmp}{#1}% +\else + \DTLdecimaltocurrency{\@dtl@tmp}{#1}% +\fi +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLgtrunc} +% Global version +% \begin{macrocode} +\newcommand*{\DTLgtrunc}[3]{% +\DTLtrunc{\@dtl@tmpii}{#2}{#3}% +\global\let#1=\@dtl@tmpii +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLclip} +%\begin{definition} +% \cs{DTLclip}\marg{cmd}\marg{num} +%\end{definition} +% Sets \meta{cmd} to \meta{num} with all unnecessary 0's removed. +% \begin{macrocode} +\newcommand*{\DTLclip}[2]{% +\DTLconverttodecimal{#2}{\@dtl@numi}% +\FPclip{\@dtl@tmp}{\@dtl@numi}% +\ifx\@dtl@replaced\@empty + \DTLdecimaltolocale{\@dtl@tmp}{#1}% +\else + \DTLdecimaltocurrency{\@dtl@tmp}{#1}% +\fi +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLgclip} +% Global version +% \begin{macrocode} +\newcommand*{\DTLgclip}[3]{% +\DTLclip{\@dtl@tmpii}{#2}% +\global\let#1=\@dtl@tmpii +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLinitials} +%\subsection{String Macros} +%\begin{definition} +%\cs{DTLinitials}\marg{string} +%\end{definition} +% Convert a string into initials. +% (Any "~" character found is first converted into a space.) +%\changes{1.01}{2007 Aug 17}{now works with unbreakable space symbol} +%\changes{1.01}{2007 Aug 17}{now uses \cs{DTLinitialhyphen}} +% \begin{macrocode} +\newcommand*\DTLinitials[1]{% +\def\dtl@initialscmd{}% +\dtl@subnobrsp{#1}{\dtl@string}% +\DTLsubstituteall{\dtl@string}{~}{ }% +\DTLsubstituteall{\dtl@string}{\ }{ }% +\DTLsubstituteall{\dtl@string}{\space}{ }% +\expandafter\dtl@initials\dtl@string{} \@nil% +\dtl@initialscmd}% +% \end{macrocode} +%\end{macro} +% The following substitutes "\protect \nobreakspace {}" with +% a space. (Note that in this case the space following +% "\nobreakspace" forms part of the command.) +% \begin{macrocode} +\edef\dtl@construct@subnobrsp{% +\noexpand\def\noexpand\@dtl@subnobrsp##1\noexpand\protect +\expandafter\noexpand\csname nobreakspace \endcsname ##2{% +\noexpand\toks@{##1}% +\noexpand\expandafter\noexpand\@dtl@toks\noexpand\expandafter{% +\noexpand\@dtl@string}% +\noexpand\edef\noexpand\@dtl@string{\noexpand\the\noexpand\@dtl@toks +\noexpand\the\noexpand\toks@}% +\noexpand\def\noexpand\@dtl@tmp{##2}% +\noexpand\ifx\noexpand\@dtl@tmp\noexpand\@nnil + \noexpand\let\noexpand\@dtl@subnobrspnext=\noexpand\relax +\noexpand\else + \noexpand\toks@{ }% + \noexpand\expandafter\noexpand\@dtl@toks\noexpand\expandafter{% + \noexpand\@dtl@string}% + \noexpand\edef\noexpand\@dtl@string{\noexpand\the\noexpand\@dtl@toks + \noexpand\the\noexpand\toks@}% + \noexpand\let\noexpand\@dtl@subnobrspnext=\noexpand\@dtl@subnobrsp +\noexpand\fi +\noexpand\@dtl@subnobrspnext +}% +\noexpand\def\noexpand\dtl@subnobrsp##1##2{% +\noexpand\def\noexpand\@dtl@string{}% +\noexpand\@dtl@subnobrsp ##1\noexpand\protect\expandafter\noexpand +\csname nobreakspace \endcsname \noexpand\@nil +\noexpand\let##2=\noexpand\@dtl@string +}} +\dtl@construct@subnobrsp +% \end{macrocode} +% +%\begin{macro}{\DTLstoreinitials} +%\begin{definition} +%\cs{DTLstoreinitials}\marg{string}\marg{cmd} +%\end{definition} +% Convert a string into initials and store in \meta{cmd}. +% (Any "~" character found is first converted into a space.) +%\changes{1.01}{2007 Aug 17}{now works with unbreakable space symbol} +%\changes{1.01}{2007 Aug 17}{now uses \cs{DTLinitialhyphen}} +% \begin{macrocode} +\newcommand*{\DTLstoreinitials}[2]{% +\def\dtl@initialscmd{}% +\dtl@subnobrsp{#1}{\dtl@string}% +\DTLsubstituteall{\dtl@string}{~}{ }% +\DTLsubstituteall{\dtl@string}{\ }{ }% +\DTLsubstituteall{\dtl@string}{\space}{ }% +\expandafter\dtl@initials\dtl@string{} \@nil +\let#2=\dtl@initialscmd +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\dtl@initials} +% \begin{macrocode} +\def\dtl@initials#1#2 #3{% +\dtl@ifsingle{#1}{% +\ifcat\noexpand#1\relax\relax + \def\@dtl@donextinitials{\@dtl@initials#2 {#3}}% +\else + \def\@dtl@donextinitials{\@dtl@initials#1#2 {#3}}% +\fi +}{% + \def\@dtl@donextinitials{\@dtl@initials{#1}#2 {#3}}% +}% +\@dtl@donextinitials +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\@dtl@initials} +% \begin{macrocode} +\def\@dtl@initials#1#2 #3{% +\dtl@initialshyphen#2-{}\dtl@endhyp +\expandafter\@dtl@toks\expandafter{\dtl@initialscmd}% +\toks@{#1}% +\ifx\dtl@inithyphen\@empty +\else + \edef\dtl@initialscmd{\the\@dtl@toks\the\toks@}% + \expandafter\@dtl@toks\expandafter{\dtl@initialscmd}% + \expandafter\toks@\expandafter{\dtl@inithyphen}% +\fi +\def\dtl@tmp{#3}% +\ifx\@nnil\dtl@tmp + \edef\dtl@initialscmd{\the\@dtl@toks\the\toks@\DTLafterinitials}% + \let\dtl@initialsnext=\@gobble +\else + \edef\dtl@initialscmd{\the\@dtl@toks\the\toks@\DTLbetweeninitials}% + \let\dtl@initialsnext=\dtl@initials +\fi +\dtl@initialsnext{#3}} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\dtl@initialshyphen} +% \begin{macrocode} +\def\dtl@initialshyphen#1-#2#3\dtl@endhyp{% +\def\dtl@inithyphen{#2}% +\ifx\dtl@inithyphen\@empty +\else + \edef\dtl@inithyphen{% + \DTLafterinitialbeforehyphen\DTLinitialhyphen#2}% +\fi +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLafterinitials} +% Defines what to do after the final initial. +% \begin{macrocode} +\newcommand*{\DTLafterinitials}{.} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLbetweeninitials} +% Defines what to do between initials. +% \begin{macrocode} +\newcommand*{\DTLbetweeninitials}{.} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLafterinitialbeforehyphen} +% Defines what to do before a hyphen. +% \begin{macrocode} +\newcommand*{\DTLafterinitialbeforehyphen}{.} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLinitialhyphen} +%Defines what to do at the hyphen +%\changes{1.01}{2007 Aug 17}{new} +% \begin{macrocode} +\newcommand*{\DTLinitialhyphen}{-} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLifAllUpperCase} +%\begin{definition} +%\cs{DTLifAllUpperCase}\marg{string}\marg{true part}\marg{false part} +%\end{definition} +% If \meta{string} only contains uppercase characters do \meta{true +%part}, otherwise do \meta{false part}. +% \begin{macrocode} +\newcommand*{\DTLifAllUpperCase}[3]{% +\protected@edef\dtl@tuc{#1}% +\expandafter\dtl@testifuppercase\dtl@tuc\@nil\relax +\if@dtl@condition#2\else#3\fi +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\dtl@testifalluppercase} +% \begin{macrocode} +\def\dtl@testifuppercase#1#2{% +\def\dtl@argi{#1}% +\def\dtl@argii{#2}% +\def\dtl@tc@rest{}% +\ifx\dtl@argi\@nnil + \let\dtl@testifuppernext=\@nnil +\else + \ifx#1\protect + \let\dtl@testifuppernext=\dtl@testifuppercase + \else + \ifx\uppercase#1\relax + \@dtl@conditiontrue + \def\dtl@tc@rest{}% + \let\dtl@testifuppernext=\relax + \else + \edef\dtl@tc@arg{\string#1}% + \expandafter\dtl@test@ifuppercase\dtl@tc@arg\end + \ifx\dtl@argii\@nnil + \let\dtl@testifuppernext=\@dtl@gobbletonil + \fi + \fi + \fi +\fi +\ifx\dtl@testifuppernext\relax + \edef\dtl@dotestifuppernext{% + \noexpand\dtl@testifuppercase}% +\else + \ifx\dtl@testifuppernext\@nnil + \edef\dtl@dotestifuppernext{#2}% + \else + \expandafter\toks@\expandafter{\dtl@tc@rest}% + \@dtl@toks{#2}% + \edef\dtl@dotestifuppernext{% + \noexpand\dtl@testifuppernext\the\toks@\the\@dtl@toks}% + \fi +\fi +\dtl@dotestifuppernext +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\dtl@test@ifalluppercase} +% \begin{macrocode} +\def\dtl@test@ifuppercase#1#2\end{% +\def\dtl@tc@rest{#2}% +\IfSubStringInString{\string\MakeUppercase}{#1#2}{% + \@dtl@conditiontrue + \def\dtl@tc@rest{}% + \let\dtl@testifuppernext=\relax +}{% + \IfSubStringInString{\string\MakeTextUppercase}{#1#2}{% + \@dtl@conditiontrue + \def\dtl@tc@rest{}% + \let\dtl@testifuppernext=\relax + }{% + \edef\dtl@uccode{\the\uccode`#1}% + \edef\dtl@code{\number`#1}% + \ifnum\dtl@code=\dtl@uccode\relax + \@dtl@conditiontrue + \let\dtl@testifuppernext=\dtl@testifuppercase + \else + \ifnum\dtl@uccode=0\relax + \@dtl@conditiontrue + \let\dtl@testifuppernext=\dtl@testifuppercase + \else + \@dtl@conditionfalse + \let\dtl@testifuppernext=\@dtl@gobbletonil + \fi + \fi +}}} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLifAllLowerCase} +%\begin{definition} +%\cs{DTLifAllLowerCase}\marg{string}\marg{true part}\marg{false part} +%\end{definition} +% If \meta{string} only contains lowercase characters do \meta{true +%part}, otherwise do \meta{false part}. +% \begin{macrocode} +\newcommand*{\DTLifAllLowerCase}[3]{% +\protected@edef\dtl@tlc{#1}% +\expandafter\dtl@testiflowercase\dtl@tlc\@nil\relax +\if@dtl@condition#2\else#3\fi +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\dtl@testifalllowercase} +% \begin{macrocode} +\def\dtl@testiflowercase#1#2{% +\def\dtl@argi{#1}% +\def\dtl@argii{#2}% +\ifx\dtl@argi\@nnil + \let\dtl@testiflowernext=\@nnil +\else + \ifx#1\protect + \let\dtl@testiflowernext=\dtl@testiflowercase + \else + \ifx\lowercase#1\relax + \@dtl@conditiontrue + \def\dtl@tc@rest{}% + \let\dtl@testiflowernext=\relax + \else + \edef\dtl@tc@arg{\string#1}% + \expandafter\dtl@test@iflowercase\dtl@tc@arg\end + \ifx\dtl@argii\@nnil + \let\dtl@testiflowernext=\@dtl@gobbletonil + \fi + \fi + \fi +\fi +\ifx\dtl@testiflowernext\relax + \edef\dtl@dotestiflowernext{% + \noexpand\dtl@testiflowercase}% +\else + \ifx\dtl@testiflowernext\@nnil + \edef\dtl@dotestiflowernext{#2}% + \else + \expandafter\toks@\expandafter{\dtl@tc@rest}% + \@dtl@toks{#2}% + \edef\dtl@dotestiflowernext{% + \noexpand\dtl@testiflowernext\the\toks@\the\@dtl@toks}% + \fi +\fi +\dtl@dotestiflowernext +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\dtl@test@ifalllowercase} +% \begin{macrocode} +\def\dtl@test@iflowercase#1#2\end{% +\def\dtl@tc@rest{#2}% +\IfSubStringInString{\string\MakeLowercase}{#1#2}{% + \@dtl@conditiontrue + \def\dtl@tc@rest{}% + \let\dtl@testiflowernext=\relax +}{% + \IfSubStringInString{\string\MakeTextLowercase}{#1#2}{% + \@dtl@conditiontrue + \def\dtl@tc@rest{}% + \let\dtl@testiflowernext=\relax + }{% + \edef\dtl@lccode{\the\lccode`#1}% + \edef\dtl@code{\number`#1}% + \ifnum\dtl@code=\dtl@lccode\relax + \@dtl@conditiontrue + \let\dtl@testiflowernext=\dtl@testiflowercase + \else + \ifnum\dtl@lccode=0\relax + \@dtl@conditiontrue + \let\dtl@testiflowernext=\dtl@testiflowercase + \else + \@dtl@conditionfalse + \let\dtl@testiflowernext=\@dtl@gobbletonil + \fi + \fi +}}} +% \end{macrocode} +%\end{macro} +% +%\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}. +% \begin{macrocode} +\newcommand*{\DTLsavedb}[2]{% +\DTLifdbexists{#1}{% +\openout\@dtl@write=#2% +\edef\@dtl@keys{\csname dtlkeys@#1\endcsname}% +\def\@dtl@header{}% +\@for\@dtl@key:=\@dtl@keys\do{% +\expandafter\@dtl@toks\expandafter{\@dtl@header}% +\ifx\@dtl@header\@empty + \IfSubStringInString{\@dtl@separator}{\@dtl@key}{% + \protected@edef\@dtl@header{% + \@dtl@delimiter\@dtl@key\@dtl@delimiter}% + }{% + \protected@edef\@dtl@header{\@dtl@key}% + }% +\else + \IfSubStringInString{\@dtl@separator}{\@dtl@key}{% + \protected@edef\@dtl@header{\the\@dtl@toks\@dtl@separator + \@dtl@delimiter\@dtl@key\@dtl@delimiter}% + }{% + \protected@edef\@dtl@header{\the\@dtl@toks\@dtl@separator + \@dtl@key}% + }% +\fi +}% +\protected@write\@dtl@write{}{\@dtl@header}% +\expandafter\let\expandafter\@dtl@db\csname dtldb@#1\endcsname% +\@for\@dtl@currentrow:=\@dtl@db\do{% +\dtl@gathervalues{#1}{\@dtl@currentrow}% +\def\@dtl@outputrow{}% +\@for\@dtl@key:=\@dtl@keys\do{% +\protected@edef\@dtl@element{\csname @dtl@key@\@dtl@key\endcsname}% +\expandafter\@dtl@toks\expandafter{\@dtl@outputrow}% +\ifx\@dtl@outputrow\@empty + \IfSubStringInString{\@dtl@separator}{\@dtl@element}{% + \protected@edef\@dtl@outputrow{% + \@dtl@delimiter\@dtl@element\@dtl@delimiter}% + }{% + \protected@edef\@dtl@outputrow{\@dtl@element}% + }% +\else + \IfSubStringInString{\@dtl@separator}{\@dtl@element}{% + \protected@edef\@dtl@outputrow{\the\@dtl@toks\@dtl@separator + \@dtl@delimiter\@dtl@element\@dtl@delimiter}% + }{% + \protected@edef\@dtl@outputrow{\the\@dtl@toks\@dtl@separator + \@dtl@element}% + }% +\fi +}% +\protected@write\@dtl@write{}{\@dtl@outputrow}% +}% +\closeout\@dtl@write +}{% +\PackageError{datatool}{Database `#1' doesn't exist}{}% +}} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLsavetexdb} +%\begin{definition} +% \cs{DTLsavetexdb}\marg{db name}\marg{filename} +%\end{definition} +% Save a database as a \LaTeX\ file. +% \begin{macrocode} +\newcommand*{\DTLsavetexdb}[2]{% +\DTLifdbexists{#1}{% +\def\@dtl@dbname{#1}% +\openout\@dtl@write=#2% +\edef\@dtl@keys{\csname dtlkeys@#1\endcsname}% +\protected@write\@dtl@write{}{\string\DTLnewdb{#1}}% +\expandafter\let\expandafter\@dtl@db\csname dtldb@#1\endcsname% +\@for\@dtl@currentrow:=\@dtl@db\do{% +\dtl@gathervalues{#1}{\@dtl@currentrow}% +\protected@write\@dtl@write{}{\string\DTLnewrow{#1}}% +\@for\@dtl@key:=\@dtl@keys\do{% +\expandafter\DTLifnull\csname @dtl@key@\@dtl@key\endcsname +{}{% +\protected@edef\@dtl@element{\csname @dtl@key@\@dtl@key\endcsname}% +\protected@write\@dtl@write{}{\string\DTLnewdbentry + {#1}{\@dtl@key}{\@dtl@element}}% +}% +}% +}% +\closeout\@dtl@write +}{% +\PackageError{datatool}{Database `#1' doesn't exist}{}% +}} +% \end{macrocode} +%\end{macro} +% +%\subsection{Loading a database from an external file} +% +%\begin{macro}{\@dtl@read} +% \begin{macrocode} +\newread\@dtl@read +% \end{macrocode} +%\end{macro} +%\begin{macro}{\dtl@entrycr} +% Keep track of current column in data file +% \begin{macrocode} +\newcount\dtl@entrycr +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLloaddb} +%\begin{definition} +% \cs{DTLloaddb}\marg{db name}\marg{filename} +%\end{definition} +% Creates a new database called \meta{db name}, and load the data in +% \meta{filename} into it. The separator and delimiter used in +% the file must match \cs{@dtl@separator} and \cs{@dtl@delimiter}. +% \begin{macrocode} +\gdef\DTLloaddb#1#2{% +\IfFileExists{#2}{% +\begingroup +\catcode`\"12\relax +\openin\@dtl@read=#2% +\dtl@message{Reading `#2'}% +\DTLnewdb{#1}% +\ifeof\@dtl@read +\else + \loop + \@dtl@conditionfalse + \ifeof\@dtl@read + \else + \read\@dtl@read to \@dtl@line + \dtl@trim\@dtl@line + \if\@dtl@line\par + \@dtl@conditiontrue + \fi + \fi + \if@dtl@condition + \repeat + \ifeof\@dtl@read + \else + \protected@edef\@dtl@lin@{\@dtl@separator\@dtl@line\@dtl@separator}% + \@dtl@tmpcount=0\relax + \whiledo{\not\equal{\@dtl@lin@}{\@dtl@separator}}{% + \expandafter\@dtl@lopoff\@dtl@lin@\to\@dtl@lin@\@dtl@key + \advance\@dtl@tmpcount by 1\relax + \expandafter\@dtl@toks\expandafter{\@dtl@key}% + \expandafter + \edef\csname @dtl@inky@\romannumeral\@dtl@tmpcount\endcsname{% + \the\@dtl@toks}% + }% + \ifeof\@dtl@read + \else + \@dtl@conditiontrue + \loop + \read\@dtl@read to \@dtl@line + \dtl@trim\@dtl@line + \ifthenelse{\equal{\@dtl@line}{}}{}% + {% + \DTLnewrow{#1}% + \expandafter\@dtl@toks\expandafter{\@dtl@line}% + \edef\@dtl@lin@{\@dtl@separator\the\@dtl@toks + \@dtl@separator}% + \dtl@entrycr=0\relax + \whiledo{\not\equal{\@dtl@lin@}{\@dtl@separator}}{% + \expandafter\@dtl@lopoff\@dtl@lin@\to + \@dtl@lin@\@dtl@thisentry + \advance\dtl@entrycr by 1\relax + \edef\@dtl@thiskey{% + \csname @dtl@inky@\romannumeral\dtl@entrycr\endcsname}% + \expandafter\@dtl@toks\expandafter{\@dtl@thisentry}% + \edef\@do@dtlnewentry{\noexpand\DTLnewdbentry + {#1}{\@dtl@thiskey}{\the\@dtl@toks}}% + \@do@dtlnewentry + }% + }% + \ifeof\@dtl@read \@dtl@conditionfalse\fi + \if@dtl@condition + \repeat + \fi + \fi +\fi +\closein\@dtl@read +\endgroup +}{% +\PackageError{datatool}{Can't load database `#1' (file `#2' +doesn't exist)}{}% +}} +% \end{macrocode} +%\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} +\gdef\DTLloadrawdb#1#2{% +\IfFileExists{#2}{% +\openin\@dtl@read=#2% +\dtl@message{Reading `#2'}% +\DTLnewdb{#1}% +\ifeof\@dtl@read +\else + \loop + \@dtl@conditionfalse + \ifeof\@dtl@read + \else + \@dtl@rawread\@dtl@read to\@dtl@line + \dtl@trim\@dtl@line + \if\@dtl@line\par + \@dtl@conditiontrue + \fi + \fi + \if@dtl@condition + \repeat + \ifeof\@dtl@read + \else + \dtl@domappings\@dtl@line + \protected@edef\@dtl@lin@{\@dtl@separator\@dtl@line\@dtl@separator}% + \@dtl@tmpcount=0\relax + \whiledo{\not\equal{\@dtl@lin@}{\@dtl@separator}}{% + \expandafter\@dtl@lopoff\@dtl@lin@\to\@dtl@lin@\@dtl@key + \advance\@dtl@tmpcount by 1\relax + \expandafter\@dtl@toks\expandafter{\@dtl@key}% + \expandafter + \edef\csname @dtl@inky@\romannumeral\@dtl@tmpcount\endcsname{% + \the\@dtl@toks}% + }% + \ifeof\@dtl@read + \else + \@dtl@conditiontrue + \loop + \@dtl@rawread\@dtl@read to\@dtl@line + \dtl@trim\@dtl@line + \ifthenelse{\equal{\@dtl@line}{}}{}% + {% + \DTLnewrow{#1}% + \dtl@domappings\@dtl@line + \expandafter\@dtl@toks\expandafter{\@dtl@line}% + \edef\@dtl@lin@{\@dtl@separator\the\@dtl@toks + \@dtl@separator}% + \dtl@entrycr=0\relax + \whiledo{\not\equal{\@dtl@lin@}{\@dtl@separator}}{% + \expandafter\@dtl@lopoff\@dtl@lin@\to + \@dtl@lin@\@dtl@thisentry + \advance\dtl@entrycr by 1\relax + \edef\@dtl@thiskey{% + \csname @dtl@inky@\romannumeral\dtl@entrycr\endcsname}% + \expandafter\@dtl@toks\expandafter{\@dtl@thisentry}% + \edef\@do@dtlnewentry{\noexpand\DTLnewdbentry + {#1}{\@dtl@thiskey}{\the\@dtl@toks}}% + \@do@dtlnewentry + }% + }% + \ifeof\@dtl@read \@dtl@conditionfalse\fi + \if@dtl@condition + \repeat + \fi + \fi +\fi +\closein\@dtl@read +}{% +\PackageError{datatool}{Can't load database `#1' (file `#2' +doesn't exist)}{}% +}} +% \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} +%\end{definition} +% Substitutes first occurence of \meta{original} with +% \marg{replacement} within the string given by \meta{cmd} +% \begin{macrocode} +\newcommand{\DTLsubstitute}[3]{% +\expandafter\DTLsplitstring\expandafter + {#1}{#2}{\@dtl@beforepart}{\@dtl@afterpart}% +\ifx\@dtl@replaced\@empty +\else + \def#1{}% + \expandafter\@dtl@toks\expandafter{\@dtl@beforepart}% + \expandafter\toks@\expandafter{#1}% + \protected@edef#1{\the\toks@\the\@dtl@toks#3}% + \expandafter\@dtl@toks\expandafter{\@dtl@afterpart}% + \expandafter\toks@\expandafter{#1}% + \edef#1{\the\toks@\the\@dtl@toks}% +\fi +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLsplitstring} +%\begin{definition} +%\cs{DTLsplitstring}\marg{string}\marg{split text}\marg{before +%cmd}\marg{after cmd} +%\end{definition} +% Splits string at \meta{split text} stores the pre split text +% in \meta{before cmd} and the post split text in \meta{after cmd}. +%\changes{1.01}{2007 Aug 17}{new} +% \begin{macrocode} +\newcommand*{\DTLsplitstring}[4]{% +\def\dtl@splitstr##1#2##2\@nil{% +\def#3{##1}% +\def#4{##2}% +\ifx#4\@empty + \let\@dtl@replaced=\@empty +\else + \def\@dtl@replaced{#2}% + \dtl@split@str##2\@nil +\fi +}% +\def\dtl@split@str##1#2\@nil{% +\def#4{##1}}% +\dtl@splitstr#1#2\@nil +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLsubstituteall} +%\begin{definition} +%\cs{DTLsubstituteall}\marg{cmd}\marg{original}\marg{replacement} +%\end{definition} +% Substitutes all occurences of \meta{original} with +% \marg{replacement} within the string given by \meta{cmd} +%\changes{1.01}{2007 Aug 17}{fixed bug caused when certain commands +% occur in the string} +% \begin{macrocode} +\newcommand{\DTLsubstituteall}[3]{% +\def\@dtl@splitsubstr{}% +\let\@dtl@afterpart=#1\relax +\@dtl@dosubstitute{#2}{#3}% +\expandafter\toks@\expandafter{\@dtl@splitsubstr}% +\expandafter\@dtl@toks\expandafter{\@dtl@afterpart}% +\edef#1{\the\toks@\the\@dtl@toks}% +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\@dtl@dosubstitute} +% Recursive substitution macro. +% \begin{macrocode} +\def\@dtl@dosubstitute#1#2{% +\expandafter\DTLsplitstring\expandafter + {\@dtl@afterpart}{#1}{\@dtl@beforepart}{\@dtl@afterpart}% +\expandafter\toks@\expandafter{\@dtl@splitsubstr}% +\expandafter\@dtl@toks\expandafter{\@dtl@beforepart}% +\edef\@dtl@splitsubstr{\the\toks@\the\@dtl@toks}% +\ifx\@dtl@replaced\@empty + \let\@dtl@dosubstnext=\@dtl@dosubstitutenoop +\else + \expandafter\toks@\expandafter{\@dtl@splitsubstr}% + \@dtl@toks{#2}% + \edef\@dtl@splitsubstr{\the\toks@\the\@dtl@toks}% + \let\@dtl@dosubstnext=\@dtl@dosubstitute +\fi +\@dtl@dosubstnext{#1}{#2}% +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\@dtl@dosubstitutenoop} +% Terminates recursive substitution macro. +% \begin{macrocode} +\def\@dtl@dosubstitutenoop#1#2{} +% \end{macrocode} +%\end{macro} +% +%\subsection{Currencies} +%\begin{macro}{\@dtl@currencies} +% \cs{@dtl@currencies} stores all known currencies. +% \begin{macrocode} +\newcommand*{\@dtl@currencies}{\$,\pounds} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLnewcurrencysymbol} +%\begin{definition} +% \cs{DTLaddcurrency}\marg{symbol} +%\end{definition} +% Adds \meta{symbol} to the list of known currencies +% \begin{macrocode} +\newcommand*{\DTLnewcurrencysymbol}[1]{% +\expandafter\toks@\expandafter{\@dtl@currencies}% +\@dtl@toks{#1}% +\edef\@dtl@currencies{\the\@dtl@toks,\the\toks@}% +} +% \end{macrocode} +%\end{macro} +% If any of the following currency commands have been defined, +% add them to the list: +% \begin{macrocode} +\AtBeginDocument{% +\@ifundefined{texteuro}{}{\DTLnewcurrencysymbol{\texteuro}}% +\@ifundefined{textdollar}{}{\DTLnewcurrencysymbol{\textdollar}}% +\@ifundefined{textstirling}{}{\DTLnewcurrencysymbol{\textstirling}}% +\@ifundefined{textyen}{}{\DTLnewcurrencysymbol{\textyen}}% +\@ifundefined{textwon}{}{\DTLnewcurrencysymbol{\textwon}}% +\@ifundefined{textcurrency}{}{\DTLnewcurrencysymbol{\textcurrency}}% +\@ifundefined{euro}{}{\DTLnewcurrencysymbol{\euro}}% +\@ifundefined{yen}{}{\DTLnewcurrencysymbol{\yen}}% +} +% \end{macrocode} +%\begin{macro}{\@dtl@standardize@currency} +%\begin{definition} +%\cs{@dtl@standardize@currency}\marg{cmd} +%\end{definition} +% Substitutes the first currency symbol found in \meta{cmd} +% with "\$". This is used when testing text to determine +% if it is currency. The original currency symbol is stored +% in \cs{@dtl@org@currency}, so that it can be replaced later. +% If no currency symbol is found, \cs{@dtl@org@currency} will +% be empty. +% \begin{macrocode} +\newcommand{\@dtl@standardize@currency}[1]{% +\def\@dtl@org@currency{}% +\@for\@dtl@thiscurrency:=\@dtl@currencies\do{% + \expandafter\toks@\expandafter{\@dtl@thiscurrency}% + \edef\@dtl@dosubs{\noexpand\DTLsubstitute{\noexpand#1}% + {\the\toks@}{\noexpand\$}}% + \@dtl@dosubs + \ifx\@dtl@replaced\@empty + \else + \let\@dtl@org@currency=\@dtl@replaced + \@endfortrue + \fi +}% +\@endforfalse} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\@dtl@currency} +%\cs{@dtl@currency} is set by \cs{DTLlocaltodecimal} and +%\cs{@dtl@checknumerical}. It is used by \cs{DTLdecimaltocurrency}. +% Set to "\$" by default. +% \begin{macrocode} +\newcommand*{\@dtl@currency}{\$} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLsetdefaultcurrency} +%\cs{DTLsetdefaultcurrency}\marg{symbol} sets the default currency. +% \begin{macrocode} +\newcommand*{\DTLsetdefaultcurrency}[1]{% +\renewcommand*{\@dtl@currency}{#1}} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\dtl@ifsingle} +%\begin{definition} +%\cs{dtl@ifsingle}\marg{arg}\marg{true part}\marg{false part} +%\end{definition} +% If there is only one object in \meta{arg} (without expansion) +% do \meta{true part}, otherwise do false part. +% \begin{macrocode} +\newcommand{\dtl@ifsingle}[3]{% +\def\@dtl@arg{#1}% +\ifx\@dtl@arg\@empty + #3% +\else + \@dtl@ifsingle#1\@nil{#2}{#3}% +\fi +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\@dtl@ifsingle} +% \begin{macrocode} +\def\@dtl@ifsingle#1#2\@nil#3#4{% +\def\dtl@sg@arg{#2}% +\ifx\dtl@sg@arg\@empty + #3% +\else + #4% +\fi +} +% \end{macrocode} +%\end{macro} +% +%\subsection{Debugging commands} +% These commands are provided to assist debugging +%\begin{macro}{\dtlshowdb} +%\begin{definition} +%\cs{dtlshowdb}\marg{db name} +%\end{definition} +% Shows the database. +% \begin{macrocode} +\newcommand*{\dtlshowdb}[1]{% +\expandafter\show\csname dtldb@#1\endcsname} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\dtlshowdbkeys} +%\begin{definition} +%\cs{dtlshowdbkeys}\marg{db name} +%\end{definition} +% Shows the key list for the named database. +% \begin{macrocode} +\newcommand*{\dtlshowdbkeys}[1]{% +\expandafter\show\csname dtlkeys@#1\endcsname} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\dtlshowtype} +%\begin{definition} +%\cs{dtlshowtype}\marg{db name}\marg{key} +%\end{definition} +% Show the data type for given key in the named database. +% This should be an integer from 0 to 3. +% \begin{macrocode} +\newcommand*{\dtlshowtype}[2]{% +\expandafter\show\csname @dtl@idtype@#1@#2\endcsname} +% \end{macrocode} +%\end{macro} +%\iffalse +% \begin{macrocode} +%</datatool.sty> +% \end{macrocode} +%\fi +%\iffalse +% \begin{macrocode} +%<*datapie.sty> +% \end{macrocode} +%\fi +%\section{datapie.sty} +% Declare package: +% \begin{macrocode} +\NeedsTeXFormat{LaTeX2e} +\ProvidesPackage{datapie}[2007/08/17 v1.01 (NLCT)] +% \end{macrocode} +% Require \sty{xkeyval} package +% \begin{macrocode} +\RequirePackage{xkeyval} +% \end{macrocode} +%\begin{macro}{\ifDTLcolorpiechart} +% The conditional \cs{ifDTLcolorpiechart} is to determine +% whether to use colour or grey scale. +% \begin{macrocode} +\newif\ifDTLcolorpiechart +\DTLcolorpiecharttrue +% \end{macrocode} +%\end{macro} +% Package options to change the conditional: +% \begin{macrocode} +\DeclareOption{color}{\DTLcolorpiecharttrue} +\DeclareOption{gray}{\DTLcolorpiechartfalse} +% \end{macrocode} +%\begin{macro}{\ifDTLrotateinner} +% Define boolean keys to govern label rotations. +% \begin{macrocode} +\define@boolkey{datapie}[DTL]{rotateinner}[true]{} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\ifDTLrotateouter} +% \begin{macrocode} +\define@boolkey{datapie}[DTL]{rotateouter}[true]{} +% \end{macrocode} +%\end{macro} +% Set defaults: +% \begin{macrocode} +\DTLrotateinnerfalse +\DTLrotateouterfalse +% \end{macrocode} +% Package options to change \cs{DTLrotateinner} +% \begin{macrocode} +\DeclareOption{rotateinner}{\DTLrotateinnertrue} +\DeclareOption{norotateinner}{\DTLrotateinnerfalse} +% \end{macrocode} +% Package options to change \cs{DTLrotateouter} +% \begin{macrocode} +\DeclareOption{rotateouter}{\DTLrotateoutertrue} +\DeclareOption{norotateouter}{\DTLrotateouterfalse} +% \end{macrocode} +% Process options: +% \begin{macrocode} +\ProcessOptions +% \end{macrocode} +% Required packages: +% \begin{macrocode} +\RequirePackage{datatool} +\RequirePackage{tikz} +% \end{macrocode} +% Define some variables that govern the appearance of the pie +% chart. +% +%\begin{macro}{\DTLradius} +% The radius of the pie chart is given by \cs{DTLradius}. +% \begin{macrocode} +\newlength\DTLradius +\DTLradius=2cm +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLinnerratio} +% The inner label offset ratio is given by \cs{DTLinnerratio} +% \begin{macrocode} +\newcommand*{\DTLinnerratio}{0.5} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLouterratio} +% The outer label offset ratio is given by \cs{DTLouterratio}. +% \begin{macrocode} +\newcommand*{\DTLouterratio}{1.25} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLcutawayratio} +% The cutaway offset ratio is given by \cs{DTLcutawayratio}. +% \begin{macrocode} +\newcommand*\DTLcutawayratio{0.2} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLstartangle} +% The angle of the first segment is given by \cs{DTLstartangle}. +% \begin{macrocode} +\newcommand*{\DTLstartangle}{0} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\dtl@inneroffset} +% \begin{macrocode} +\newlength\dtl@inneroffset +\dtl@inneroffset=\DTLinnerratio\DTLradius +% \end{macrocode} +%\end{macro} +%\begin{macro}{\dtl@outeroffset} +% \begin{macrocode} +\newlength\dtl@outeroffset +\dtl@outeroffset=\DTLouterratio\DTLradius +% \end{macrocode} +%\end{macro} +%\begin{macro}{\dtl@cutawayoffset} +% \begin{macrocode} +\newlength\dtl@cutawayoffset +\dtl@cutawayoffset=\DTLcutawayratio\DTLradius +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\dtl@piecutaways} +% \cs{dtl@piecutaways} is a comma separated list of segments that +% need to be cut away from the pie chart. +% \begin{macrocode} +\newcommand*{\dtl@piecutaways}{} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\dtl@innerlabel} +% \cs{dtl@innerlabel} specifies the label to appear inside +% the segment. By default this is the variable used to create +% the pie chart. +% \begin{macrocode} +\def\dtl@innerlabel{\DTLpievariable}% +% \end{macrocode} +%\end{macro} +%\begin{macro}{\dtl@outerlabel} +% \begin{macrocode} +\def\dtl@outerlabel{}% +% \end{macrocode} +%\end{macro} +% \counterfmt{DTLpieroundvar} is a counter governing the number of digits +% to round to when using \cs{FPround}. +% \begin{macrocode} +\newcounter{DTLpieroundvar} +\setcounter{DTLpieroundvar}{1} +% \end{macrocode} +% +%\begin{macro}{\DTLdisplayinnerlabel} +%\begin{definition} +%\cs{DTLdisplayinnerlabel}\marg{label} +%\end{definition} +% This is used to format the inner label. This just does the +% label by default. +% \begin{macrocode} +\newcommand*{\DTLdisplayinnerlabel}[1]{#1} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLdisplayouterlabel} +%\begin{definition} +%\cs{DTLdisplayouterlabel}\marg{label} +%\end{definition} +% This is used to format the outer label. This just does the +% label by default. +% \begin{macrocode} +\newcommand*{\DTLdisplayouterlabel}[1]{#1} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLpiepercent} +%\cs{DTLpiepercent} +% returns the percentage value of the current segment. +% \begin{macrocode} +\newcommand*{\DTLpiepercent}{% +\ifnum\dtlforeachlevel=0\relax + \PackageError{datapie}{Can't use + \string\DTLpiepercent\space outside + \string\DTLpiechart}{}% +\else + \csname dtl@piepercent@\romannumeral\@dtl@seg\endcsname +\fi} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLpieatbegintikz} +% \cs{DTLpieatbegintikz} specifies any commands +% to apply at the start of the \env{tikzpicture} environment. +% By default it does nothing. +% \begin{macrocode} +\newcommand*{\DTLpieatbegintikz}{} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLpieatendtikz} +% \cs{DTLpieatendtikz} specifies any commands +% to apply at the end of the \env{tikzpicture} environment. +% By default it does nothing. +% \begin{macrocode} +\newcommand*{\DTLpieatendtikz}{} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLsetpiesegmentcolor} +%\begin{definition} +% \cs{DTLsetpiesegmentcolor}\marg{n}\marg{color} +%\end{definition} +% Assign colour name \meta{color} to the \meta{n}th segment. +% \begin{macrocode} +\newcommand*{\DTLsetpiesegmentcolor}[2]{% +\expandafter\def\csname dtlpie@segcol\romannumeral#1\endcsname{#2}% +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLgetpiesegmentcolor} +%\begin{definition} +%\cs{DTLgetpiesegmentcolor}\marg{n} +%\end{definition} +% Get the colour specification for segment \meta{n} +% \begin{macrocode} +\newcommand*{\DTLgetpiesegmentcolor}[1]{% +\csname dtlpie@segcol\romannumeral#1\endcsname} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLdopiesegmentcolor} +%\begin{definition} +%\cs{DTLdopiesegmentcolor}\marg{n} +%\end{definition} +% Set the colour to that for segment \meta{n} +% \begin{macrocode} +\newcommand*{\DTLdopiesegmentcolor}[1]{% +\expandafter\color\expandafter +{\csname dtlpie@segcol\romannumeral#1\endcsname}} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLdocurrentpiesegmentcolor} +%\cs{DTLdocurrentpiesegmentcolor} +% sets the colour to that of the current segment. +% \begin{macrocode} +\newcommand*{\DTLdocurrentpiesegmentcolor}{% +\ifnum\dtlforeachlevel=0\relax + \PackageError{datapie}{Can't use + \string\DTLdocurrentpiesegmentcolor\space outside + \string\DTLpiechart}{}% +\else + \expandafter\DTLdopiesegmentcolor\expandafter{% + \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname}% +\fi} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLpieoutlinecolor} +%\cs{DTLpieoutlinecolor} specifies what colour to draw the +% outline. +% \begin{macrocode} +\newcommand*{\DTLpieoutlinecolor}{black} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLpieoutlinewidth} +%\cs{DTLpieoutlinewidth} specifies the line width of the outline: +% Outline is only drawn if the linewidth is greater than 0pt. +% \begin{macrocode} +\newlength\DTLpieoutlinewidth +\DTLpieoutlinewidth=0pt +% \end{macrocode} +%\end{macro} +% +% Set the default colours. If there are more than eight segments, +% more colours will need to be defined. +% \begin{macrocode} +\ifDTLcolorpiechart + \DTLsetpiesegmentcolor{1}{red} + \DTLsetpiesegmentcolor{2}{green} + \DTLsetpiesegmentcolor{3}{blue} + \DTLsetpiesegmentcolor{4}{yellow} + \DTLsetpiesegmentcolor{5}{magenta} + \DTLsetpiesegmentcolor{6}{cyan} + \DTLsetpiesegmentcolor{7}{orange} + \DTLsetpiesegmentcolor{8}{white} +\else + \DTLsetpiesegmentcolor{1}{black!15} + \DTLsetpiesegmentcolor{2}{black!25} + \DTLsetpiesegmentcolor{3}{black!35} + \DTLsetpiesegmentcolor{4}{black!45} + \DTLsetpiesegmentcolor{5}{black!55} + \DTLsetpiesegmentcolor{6}{black!65} + \DTLsetpiesegmentcolor{7}{black!75} + \DTLsetpiesegmentcolor{8}{black!85} +\fi +% \end{macrocode} +% Define keys for \cs{DTLpiechart} optional argument. +% Set the starting angle of the first segment. +% \begin{macrocode} +\define@key{datapie}{start}{\def\DTLstartangle{#1}} +% \end{macrocode} +% Set the radius of the pie chart (must be set prior to +% inneroffset and outeroffset keys.) +% \begin{macrocode} +\define@key{datapie}{radius}{\DTLradius=#1\relax +\dtl@inneroffset=\DTLinnerratio\DTLradius +\dtl@outeroffset=\DTLouterratio\DTLradius +\dtl@cutawayoffset=\DTLcutawayratio\DTLradius} +% \end{macrocode} +% Set the inner ratio. +% \begin{macrocode} +\define@key{datapie}{innerratio}{% +\def\DTLinnerratio{#1}% +\dtl@inneroffset=\DTLinnerratio\DTLradius} +% \end{macrocode} +% Set the outer ratio +% \begin{macrocode} +\define@key{datapie}{outerratio}{% +\def\DTLouterratio{#1}% +\dtl@outeroffset=\DTLouterratio\DTLradius} +% \end{macrocode} +% The cutaway offset ratio +% \begin{macrocode} +\define@key{datapie}{cutawayratio}{% +\def\DTLcutawayratio{#1}% +\dtl@cutawayoffset=\DTLcutawayratio\DTLradius} +% \end{macrocode} +% Set the inner offset as an absolute value (not dependent +% on the radius.) +% \begin{macrocode} +\define@key{datapie}{inneroffset}{% +\dtl@inneroffset=#1} +% \end{macrocode} +% Set the outer offset as an absolute value (not dependent +% on the radius.) +% \begin{macrocode} +\define@key{datapie}{outeroffset}{% +\dtl@outeroffset=#1} +% \end{macrocode} +% Set the cutaway offset as an absolute value (not dependent +% on the radius.) +% \begin{macrocode} +\define@key{datapie}{cutawayoffset}{% +\dtl@cutawayoffset=#1} +% \end{macrocode} +% List of cut away segments. +% \begin{macrocode} +\define@key{datapie}{cutaway}{% +\renewcommand*{\dtl@piecutaways}{#1}} +% \end{macrocode} +% Variable used to create the pie chart. (Must be a control +% sequence.) +% \begin{macrocode} +\define@key{datapie}{variable}{% +\def\DTLpievariable{#1}} +% \end{macrocode} +% Inner label +% \begin{macrocode} +\define@key{datapie}{innerlabel}{% +\def\dtl@innerlabel{#1}} +% \end{macrocode} +% Outer label +% \begin{macrocode} +\define@key{datapie}{outerlabel}{% +\def\dtl@outerlabel{#1}} +% \end{macrocode} +% +%\begin{macro}{\DTLpiechart} +%\begin{definition} +% \cs{DTLpiechart}\oarg{conditions}\marg{option list}\marg{db name}\marg{assign list} +%\end{definition} +% Make a pie chart from data given in data base \meta{db name}, +% where \meta{assign list} is a comma-separated list of +% \meta{cmd}\texttt{=}\meta{key} pairs. \meta{option list} must +% include \texttt{variable}\texttt{=}\meta{cmd}, where \meta{cmd} +% is included in \meta{assign list}. The optional argument +% \meta{conditions} is the same as that for \cs{DTLforeach}. +% \begin{macrocode} +\newcommand*{\DTLpiechart}[4][\boolean{true}]{% +{\let\DTLpievariable=\relax +\setkeys{datapie}{#2}% +\ifx\DTLpievariable\relax + \PackageError{datapie}{\string\DTLpiechart\space missing variable}{}% +\else +% \end{macrocode} +% Compute the total. +%\changes{1.01}{2007 Aug 17}{uses \cs{@sDTLforeach} instead of +%\cs{DTLforeach}} +% \begin{macrocode} +\def\dtl@total{0}% +\@sDTLforeach[#1]{#3}{#4}{% +\let\dtl@oldtotal=\dtl@total +\expandafter\DTLconverttodecimal\expandafter + {\DTLpievariable}{\dtl@variable}% +\FPadd{\dtl@total}{\dtl@variable}{\dtl@total}% +}% +% \end{macrocode} +% Compute the angles +% \begin{macrocode} +\expandafter\DTLconverttodecimal\expandafter + {\DTLstartangle}{\@dtl@start}% +\@sDTLforeach[#1]{#3}{#4}{% +\expandafter\DTLconverttodecimal\expandafter + {\DTLpievariable}{\dtl@variable}% +\dtl@computeangles{% +\csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname}{% +\dtl@variable}% +\expandafter\@dtl@seg\expandafter= +\csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname% +\FPmul{\dtl@tmp}{\dtl@variable}{100}% +\let\dtl@old=\dtl@tmp +\FPdiv{\dtl@tmp}{\dtl@old}{\dtl@total}% +\expandafter\FPround +\csname dtl@piepercent@\romannumeral\@dtl@seg\endcsname\dtl@tmp +\c@DTLpieroundvar +}% +% \end{macrocode} +% Compute the offsets for each cut away segment +% \begin{macrocode} +\@for\dtl@row:=\dtl@piecutaways\do{% +\expandafter\@dtl@set@off\dtl@row-\relax +}% +% \end{macrocode} +% Set the starting angle +% \begin{macrocode} +\let\dtl@start=\DTLstartangle +% \end{macrocode} +% Do the pie chart +% \begin{macrocode} +\begin{tikzpicture} +\DTLpieatbegintikz +\@sDTLforeach[#1]{#3}{#4}{% +% \end{macrocode} +% Store the segment number in \cs{@dtl@seg} +% \begin{macrocode} +\expandafter\@dtl@seg\expandafter= +\csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname% +% \end{macrocode} +% Set the start angle. +% \begin{macrocode} +\edef\dtl@start{\csname dtl@sang@\romannumeral\@dtl@seg\endcsname}% +% \end{macrocode} +% Set the extent +% \begin{macrocode} +\edef\dtl@extent{\csname dtl@angle@\romannumeral\@dtl@seg\endcsname}% +% \end{macrocode} +% Compute the end angle +% \begin{macrocode} +\FPadd{\dtl@endangle}{\dtl@start}{\dtl@extent}% +% \end{macrocode} +% Compute the shift. +% \begin{macrocode} +\edef\dtl@angle{\csname dtl@cut@angle@\romannumeral\@dtl@seg\endcsname}% +\let\dtl@old=\dtl@angle +\dtl@truncatedecimal\dtl@angle +\ifnum\dtl@angle>180 + \FPsub{\dtl@angle}{\dtl@old}{360}% + \dtl@truncatedecimal\dtl@angle +\fi +\edef\dtl@cutlen{% +\csname dtl@cut@len@\romannumeral\@dtl@seg\endcsname} +\edef\@dtl@shift{(\dtl@angle:\dtl@cutlen)}% +% \end{macrocode} +% Compute the mid way angle. +% \begin{macrocode} +\FPmul{\dtl@angle}{\dtl@extent}{0.5}% +\FPadd{\dtl@midangle}{\dtl@angle}{\dtl@start}% +% \end{macrocode} +% Draw the segment. +% \begin{macrocode} +\begin{scope}[shift={\@dtl@shift}]% +\dtl@truncatedecimal\dtl@start +\dtl@truncatedecimal\dtl@endangle +\fill[color=\DTLgetpiesegmentcolor\@dtl@seg] (0,0) -- +(\dtl@start:\DTLradius) +arc (\dtl@start:\dtl@endangle:\DTLradius) -- cycle; +% \end{macrocode} +% Draw the outline if required: +% \begin{macrocode} +\ifdim\DTLpieoutlinewidth>0pt\relax +\draw[color=\DTLpieoutlinecolor,line width=\DTLpieoutlinewidth] +(0,0) -- (\dtl@start:\DTLradius) +arc (\dtl@start:\dtl@endangle:\DTLradius) -- cycle; +\fi +% \end{macrocode} +% Convert decimal to an integer +% \begin{macrocode} +\dtl@truncatedecimal\dtl@midangle +% \end{macrocode} +% Determine whether to rotate inner labels +% \begin{macrocode} +\ifDTLrotateinner +% \end{macrocode} +% If the mid way angle is between 90 and 270, the text will look +% upside-down, so adjust accordingly. +% \begin{macrocode} +\ifthenelse{\(\dtl@midangle > 90 \and \dtl@midangle < 270\) +\TE@or \dtl@midangle < -90}{% + \FPsub{\dtl@labelangle}{\dtl@midangle}{180}% + \dtl@truncatedecimal\dtl@labelangle + \edef\dtl@innernodeopt{anchor=east,rotate=\dtl@labelangle}% +}{% + \edef\dtl@innernodeopt{anchor=west,rotate=\dtl@midangle}% +}% +% \end{macrocode} +% Don't rotate inner labels +% \begin{macrocode} +\else + \edef\dtl@innernodeopt{anchor=center}% +\fi +% \end{macrocode} +% Determine whether to rotate outer labels +% \begin{macrocode} +\ifDTLrotateouter +% \end{macrocode} +% If the mid way angle is between 90 and 270, the text will look +% upside-down, so adjust accordingly. +% \begin{macrocode} +\ifthenelse{\(\dtl@midangle > 90 \and \dtl@midangle < 270\) +\TE@or \dtl@midangle < -90}{% + \FPsub{\dtl@labelangle}{\dtl@midangle}{180}% + \dtl@truncatedecimal\dtl@labelangle + \edef\dtl@outernodeopt{anchor=east,rotate=\dtl@labelangle}% +}{% + \edef\dtl@outernodeopt{anchor=west,rotate=\dtl@midangle}% +}% +% \end{macrocode} +% Don't rotate outer labels +% \begin{macrocode} +\else + \ifthenelse{\(\dtl@midangle<45\and\dtl@midangle>-45\) + \TE@or \dtl@midangle=45 + \TE@or \dtl@midangle>315}{% + % east quadrant + \edef\dtl@outernodeopt{anchor=west}% + }{% + \ifthenelse{\(\dtl@midangle<135\and\dtl@midangle>45\) + \TE@or \dtl@midangle=135}{% + % north quadrant + \edef\dtl@outernodeopt{anchor=south}% + }{% + \ifthenelse{\(\dtl@midangle<225\and\dtl@midangle>135\) + \TE@or \dtl@midangle=225 + \TE@or \dtl@midangle=-135 + \TE@or \dtl@midangle<-135}{% + % west quadrant + \edef\dtl@outernodeopt{anchor=east}% + }{% + \edef\dtl@outernodeopt{anchor=north}% + }% + } + } +\fi +% \end{macrocode} +% Draw inner and outer labels +% \begin{macrocode} +\edef\@dtl@dolabel{% +\noexpand\draw (\dtl@midangle:\the\dtl@inneroffset) +node[\dtl@innernodeopt]{% +\noexpand\DTLdisplayinnerlabel{\noexpand\dtl@innerlabel}};}% +\@dtl@dolabel +\edef\@dtl@dolabel{% +\noexpand\draw (\dtl@midangle:\the\dtl@outeroffset) +node[\dtl@outernodeopt]{% +\noexpand\DTLdisplayouterlabel{\noexpand\dtl@outerlabel}};}% +\@dtl@dolabel +\end{scope} +}% +\DTLpieatendtikz +\end{tikzpicture} +\fi +}} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\dtl@computeangles} +%\begin{definition} +%\cs{dtl@computeangles}\marg{n}\marg{variable} +%\end{definition} +% Compute the angles for segment \meta{n}. This sets +% \cs{dtl@sang@}\meta{n} (start angle), +% \cs{dtl@angle@}\meta{n} (extent angle), +% \cs{dtl@cut@angle@}\meta{n} (cut away angle) and +% \cs{dtl@cut@len@}\meta{n} (cut away length). +% \begin{macrocode} +\newcommand*{\dtl@computeangles}[2]{% +\FPifgt{\@dtl@start}{180}% +% if startangle > 180 + \let\dtl@old=\@dtl@start +% startangle = startangle - 360 + \FPsub{\@dtl@start}{\dtl@old}{360}% +\fi +\FPiflt{\@dtl@start}{-180}% +% if startangle < -180 + \let\dtl@old=\@dtl@start +% startangle = startangle + 360 + \FPadd{\@dtl@start}{\dtl@old}{360}% +\fi +\expandafter\edef\csname dtl@sang@\romannumeral#1\endcsname{% +\@dtl@start}% +\FPmul{\dtl@angle}{360}{#2}% +\let\dtl@old=\dtl@angle +\FPdiv{\dtl@angle}{\dtl@old}{\dtl@total}% +\expandafter\let\csname dtl@angle@\romannumeral#1\endcsname=\dtl@angle +\let\dtl@old=\@dtl@start +\FPadd{\@dtl@start}{\dtl@old}{\dtl@angle}% +\expandafter\def\csname dtl@cut@angle@\romannumeral#1\endcsname{0}% +\expandafter\def\csname dtl@cut@len@\romannumeral#1\endcsname{0cm}% +} +% \end{macrocode} +%\end{macro} +% +% Set the offset angles. +%\begin{macro}{\@dtl@set@off} +% \begin{macrocode} +\def\@dtl@set@off#1-#2\relax{% +\ifthenelse{\equal{#2}{}}{% +\@@dtl@set@off{#1}}{% +\@@dtl@set@offr#1-#2\relax}% +} +% \end{macrocode} +%\end{macro} +% Set offset for individual segment: +%\begin{macro}{\@@dtl@set@off} +% \begin{macrocode} +\newcommand*{\@@dtl@set@off}[1]{% +\edef\dtl@old{\csname dtl@angle@\romannumeral#1\endcsname}% +\FPmul{\dtl@angle}{\dtl@old}{0.5}% +\let\dtl@old=\dtl@angle +\edef\dtl@sang{\csname dtl@sang@\romannumeral#1\endcsname}% +\FPadd{\dtl@angle}{\dtl@old}{\dtl@sang}% +\expandafter\edef\csname dtl@cut@angle@\romannumeral#1\endcsname{% +\dtl@angle}% +\expandafter\edef\csname dtl@cut@len@\romannumeral#1\endcsname{% + \the\dtl@cutawayoffset} +} +% \end{macrocode} +%\end{macro} +% Define count register to keep track of segments +%\begin{macro}{\@dtl@seg} +% \begin{macrocode} +\newcount\@dtl@seg +% \end{macrocode} +%\end{macro} +%\begin{macro}{\@@dtl@setoffr} +% Set offset for a range of segments +% \begin{macrocode} +\def\@@dtl@set@offr#1-#2-\relax{% +\ifnum#1>#2\relax + \PackageError{datapie}{Segment ranges must go in ascending order}{% +Try #2-#1 instead of #1-#2}% +\else + \def\dtl@angle{0}% + \@dtl@seg=#1\relax + \whiledo{\not\(\@dtl@seg > #2\)}{% + \let\dtl@old=\dtl@angle + \edef\dtl@segang{\csname dtl@angle@\romannumeral\@dtl@seg\endcsname}% + \FPadd{\dtl@angle}{\dtl@old}{\dtl@segang}% + \advance\@dtl@seg by 1\relax + }% + \let\dtl@old=\dtl@angle + \FPmul{\dtl@angle}{\dtl@old}{0.5}% + \edef\dtl@sang{\csname dtl@sang@\romannumeral#1\endcsname}% + \let\dtl@old=\dtl@angle + \FPadd{\dtl@angle}{\dtl@old}{\dtl@sang}% + \@dtl@seg=#1\relax + \whiledo{\not\(\@dtl@seg > #2\)}{% + \expandafter + \let\csname dtl@cut@angle@\romannumeral\@dtl@seg\endcsname + =\dtl@angle + \expandafter + \edef\csname dtl@cut@len@\romannumeral\@dtl@seg\endcsname{% + \the\dtl@cutawayoffset} + \advance\@dtl@seg by 1\relax + }% +\fi +} +% \end{macrocode} +%\end{macro} +%\iffalse +% \begin{macrocode} +%</datapie.sty> +% \end{macrocode} +%\fi +%\iffalse +% \begin{macrocode} +%<*dataplot.sty> +% \end{macrocode} +%\fi +%\section{dataplot.sty} +% Declare package: +% \begin{macrocode} +\NeedsTeXFormat{LaTeX2e} +\ProvidesPackage{dataplot}[2007/08/17 v1.01 (NLCT)] +% \end{macrocode} +% Required packages +% \begin{macrocode} +\RequirePackage{xkeyval} +\RequirePackage{tikz} +\RequirePackage{datatool} +% \end{macrocode} +% Load TikZ plot libraries +% \begin{macrocode} +\usetikzlibrary{plotmarks} +\usetikzlibrary{plothandlers} +% \end{macrocode} +% +%\begin{macro}{\DTLplotstream} +%\begin{definition} +%\cs{DTLplotstream}\oarg{condition}\marg{db name}\marg{x key}\marg{y key} +%\end{definition} +% Add points to a stream from the database called \meta{db name} +% where the $x$ co-ordinates are given by the key \meta{x key} +% and the $y$ co-ordinates are given by the key \meta{y key}. +% The optional argument \meta{condition} is the same as that +% for \cs{DTLforeach} +%\changes{1.01}{2007 Aug 17}{uses \cs{@sDTLforeach} instead of +%\cs{DTLforeach}} +% \begin{macrocode} +\newcommand*{\DTLplotstream}[4][\boolean{true}]{% +\@sDTLforeach[#1]{#2}{\dtl@x=#3,\dtl@y=#4}{% +\DTLconverttodecimal{\dtl@x}{\dtl@decx}% +\DTLconverttodecimal{\dtl@y}{\dtl@decy}% +\pgfplotstreampoint{\pgfpointxy{\dtl@decx}{\dtl@decy}}}} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLplotmarks} +%\cs{DTLplotmarks} contains a list of plot marks used by +%\cs{DTLplot}. +% \begin{macrocode} +\newcommand*{\DTLplotmarks}{% +\pgfuseplotmark{o},% +\pgfuseplotmark{x},% +\pgfuseplotmark{+},% +\pgfuseplotmark{square},% +\pgfuseplotmark{triangle},% +\pgfuseplotmark{diamond},% +\pgfuseplotmark{pentagon},% +\pgfuseplotmark{asterisk},% +\pgfuseplotmark{star}} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLplotmarkcolors} +%\cs{DTLplotmarkcolors} contains a list of the plot mark colours. +% \begin{macrocode} +\newcommand*{\DTLplotmarkcolors}{% +red,% +green,% +blue,% +yellow,% +magenta,% +cyan,% +orange,% +black,% +gray} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLplotlines} +%\cs{DTLplotlines} contains a list of dash patterns used by +%\cs{DLTplot}. +% \begin{macrocode} +\newcommand*{\DTLplotlines}{% +\pgfsetdash{}{{0pt}},% solid line +\pgfsetdash{{10pt}{5pt}}{0pt},% +\pgfsetdash{{5pt}{5pt}}{0pt},% +\pgfsetdash{{1pt}{5pt}}{0pt},% +\pgfsetdash{{5pt}{5pt}{1pt}{5pt}}{0pt},% +\pgfsetdash{{1pt}{3pt}}{0pt},% +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLplotlinecolors} +%\cs{DTLplotlinecolors} contains a list of the plot line colours. +% \begin{macrocode} +\newcommand*{\DTLplotlinecolors}{% +red,% +green,% +blue,% +yellow,% +magenta,% +cyan,% +orange,% +black,% +gray} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLplotwidth} +% The default total plot width is stored in the length +% \cs{dtlplotwidth} +% \begin{macrocode} +\newlength\DTLplotwidth +\setlength\DTLplotwidth{4in} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLplotheight} +% The default total plot height is stored in the length +% \cs{dtlplotheight} +% \begin{macrocode} +\newlength\DTLplotheight +\setlength\DTLplotheight{4in} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLticklength} +% The length of the tick marks is given by \cs{DTLticklength} +% \begin{macrocode} +\newlength\DTLticklength +\setlength\DTLticklength{5pt} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLminorticklength} +% The length of the minor tick marks is given by +% \cs{DTLminorticklength}. +% \begin{macrocode} +\newlength\DTLminorticklength +\setlength\DTLminorticklength{2pt} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLticklabeloffset} +% The offset from the axis to the tick label is given by +% \cs{DTLticklabeloffset}. +% \begin{macrocode} +\newlength\DTLticklabeloffset +\setlength\DTLticklabeloffset{8pt} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\dtl@xticlabelheight} +% \cs{dtl@xticlabelheight} is used to store the height of +% the $x$ tick labels. +% \begin{macrocode} +\newlength\dtl@xticlabelheight +% \end{macrocode} +%\end{macro} +%\begin{macro}{\dtl@yticlabelwidth} +% \cs{dtl@yticlabelwidth} is used to store the width of +% the $y$ tick labels. +% \begin{macrocode} +\newlength\dtl@yticlabelwidth +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLmintickgap} +% \cs{DTLmintickgap} stores the suggested minimum distance between +% tick marks where the gap is not specified. +% \begin{macrocode} +\newlength\DTLmintickgap +\setlength\DTLmintickgap{20pt} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLminminortickgap} +% The suggested minimum distance between minor tick marks where the +% gap is not specified is given by \cs{DTLminminortickgap}. +% \begin{macrocode} +\newlength\DTLminminortickgap +\setlength\DTLminminortickgap{5pt} +% \end{macrocode} +%\end{macro} +% Round $x$ tick labels to the number of digits given by +% the counter \counterfmt{DTLplotroundXvar}. +% \begin{macrocode} +\newcounter{DTLplotroundXvar} +\setcounter{DTLplotroundXvar}{2} +% \end{macrocode} +% Round $y$ tick labels to the number of digits given by +% the counter \counterfmt{DTLplotroundYvar}. +% \begin{macrocode} +\newcounter{DTLplotroundYvar} +\setcounter{DTLplotroundYvar}{2} +% \end{macrocode} +%\begin{macro}{\ifDTLxaxis} +% The conditional \cs {ifDTLxaxis} is used to determine whether or +% not to display the $x$ axis. +% \begin{macrocode} +\newif\ifDTLxaxis +\DTLxaxistrue +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLXAxisStyle} +% The style of the $x$ axis is given by \cs{DTLXAxisStyle}. This +% is just a solid line by default. +% \begin{macrocode} +\newcommand*{\DTLXAxisStyle}{-} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\ifDTLyaxis} +% The conditional \cs{ifDTLyaxis} is used to determine whether or +% not to display the $y$ axis +% \begin{macrocode} +\newif\ifDTLyaxis +\DTLyaxistrue +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLYAxisStyle} +% The style of the $y$ axis is given by \cs{DTLYAxisStyle}. This +% is just a solid line by default. +% \begin{macrocode} +\newcommand*{\DTLYAxisStyle}{-} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLmajorgridstyle} +% The style of the major grid lines is given by +% \cs{DTLmajorgridstyle}. +% \begin{macrocode} +\newcommand*{\DTLmajorgridstyle}{color=gray,-} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLminorgridstyle} +% The style of the minor grid lines is given by +% \cs{DTLminorgridstyle}. +% \begin{macrocode} +\newcommand*{\DTLminorgridstyle}{color=gray,loosely dotted} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\ifDTLxticsin} +% The conditional \cs{ifDTLxticsin} is used to determine whether +% the $x$ tics should point in or out. +% \begin{macrocode} +\newif\ifDTLxticsin +\DTLxticsintrue +% \end{macrocode} +%\end{macro} +%\begin{macro}{\ifDTLyticsin} +% The conditional \cs{ifDTLyticsin} is used to determine whether +% the $y$ tics should point in or out. +% \begin{macrocode} +\newif\ifDTLyticsin +\DTLyticsintrue +% \end{macrocode} +%\end{macro} +%\begin{macro}{\dtl@legendsetting} +% The legend setting is stored in the count register +% \cs{dtl@legendsetting}. +% \begin{macrocode} +\newcount\dtl@legendsetting +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLlegendxoffset} +% The gap between the border of plot and legend is given by the +% lengths \cs{DTLlegendxoffset} and \cs{DTLlegendyoffset} +% \begin{macrocode} +\newlength\DTLlegendxoffset +\setlength\DTLlegendxoffset{10pt} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLlegendyoffset} +% \begin{macrocode} +\newlength\DTLlegendyoffset +\setlength\DTLlegendyoffset{10pt} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLformatlegend} +%\begin{definition} +%\cs{DTLformatlegend}\marg{legend} +%\end{definition} +% This formats the legend. +% \begin{macrocode} +\newcommand*{\DTLformatlegend}[1]{% +\setlength{\fboxrule}{1.1pt}% +\fcolorbox{black}{white}{#1}} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\ifDTLshowmarkers} +% The conditional \cs{ifDTLshowmarkers} is used to specify +% whether or not to use markers. +% \begin{macrocode} +\newif\ifDTLshowmarkers +\DTLshowmarkerstrue +% \end{macrocode} +%\end{macro} +%\begin{macro}{\ifDTLshowlines} +% The conditional \cs{ifDTLshowlines} is used to specify +% whether or not to use lines. +% \begin{macrocode} +\newif\ifDTLshowlines +\DTLshowlinesfalse +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLplotatbegintikz} +% \cs{DTLplotatbegintikz} is a hook to insert stuff at the +% start of the \env{tikzpicture} +% environment (after the unit vectors have been set). +% \begin{macrocode} +\newcommand*{\DTLplotatbegintikz}{} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLplotatendtikz} +% \cs{DTLplotatendtikz} is a hook to insert stuff at the end +% of the \env{tikzpicture} environment. +% \begin{macrocode} +\newcommand*{\DTLplotatendtikz}{} +% \end{macrocode} +%\end{macro} +% +% Plot settings. The database key for the $x$ value is +% given by the "x" setting: +% \begin{macrocode} +\define@key{dataplot}{x}{% +\def\dtl@xkey{#1}} +% \end{macrocode} +% The database key for the $y$ value is given by the "y" setting: +% \begin{macrocode} +\define@key{dataplot}{y}{% +\def\dtl@ykey{#1}} +% \end{macrocode} +% The list of plot mark colours is given by the "markcolors" setting. +% (This should be a comma separated list of colour names.) +% \begin{macrocode} +\define@key{dataplot}{markcolors}{% +\def\DTLplotmarkcolors{#1}} +% \end{macrocode} +% The list of plot line colours is given by the "linecolors" setting. +% (This should be a comma separated list of colour names.) +% \begin{macrocode} +\define@key{dataplot}{linecolors}{% +\def\DTLplotlinecolors{#1}} +% \end{macrocode} +% The list of plot mark and line colours is given by the "colors" +% setting. (This should be a comma separated list of colour names.) +% \begin{macrocode} +\define@key{dataplot}{colors}{% +\def\DTLplotmarkcolors{#1}% +\def\DTLplotlinecolors{#1}} +% \end{macrocode} +% The list of plot marks is given by the "marks" setting. (This +% should be a comma separated list of code that generates +% pgf plot marks.) +% \begin{macrocode} +\define@key{dataplot}{marks}{% +\def\DTLplotmarks{#1}} +% \end{macrocode} +% The list of plot line styles is given by the "lines" setting. (This +% should be a comma separated list of code that sets the line +% style.) An empty set will create solid lines. +% \begin{macrocode} +\define@key{dataplot}{lines}{% +\def\DTLplotlines{#1}} +% \end{macrocode} +% The total width of the plot is given by the "width" setting. +% \begin{macrocode} +\define@key{dataplot}{width}{% +\setlength\DTLplotwidth{#1}} +% \end{macrocode} +% The total height of the plot is given by the "height" setting. +% \begin{macrocode} +\define@key{dataplot}{height}{% +\setlength\DTLplotheight{#1}} +% \end{macrocode} +% Determine whether to show lines, markers or both +% \begin{macrocode} +\define@choicekey{dataplot}{style}[\val\nr]{both,lines,markers}{% +\ifcase\nr\relax + \DTLshowlinestrue + \DTLshowmarkerstrue +\or + \DTLshowlinestrue + \DTLshowmarkersfalse +\or + \DTLshowmarkerstrue + \DTLshowlinesfalse +\fi} +% \end{macrocode} +% Determine whether or not to display the axes +% \begin{macrocode} +\define@choicekey{dataplot}{axes}[\val\nr]{both,x,y,none}[both]{% +\ifcase\nr\relax + % both + \DTLxaxistrue + \DTLxticstrue + \DTLyaxistrue + \DTLyticstrue +\or % x + \DTLxaxistrue + \DTLxticstrue + \DTLyaxisfalse + \DTLyticsfalse +\or % y + \DTLxaxisfalse + \DTLxticsfalse + \DTLyaxistrue + \DTLyticstrue +\or % none + \DTLxaxisfalse + \DTLxticsfalse + \DTLyaxisfalse + \DTLyticsfalse +\fi +} +% \end{macrocode} +%\begin{macro}{\ifDTLbox} +% Enclose plot in a box +% \begin{macrocode} +\define@boolkey{dataplot}[DTL]{box}[true]{} +\DTLboxfalse +% \end{macrocode} +%\end{macro} +%\begin{macro}{\ifDTLxticstrue} +% Condition to determine whether to show the $x$ tick marks +% \begin{macrocode} +\define@boolkey{dataplot}[DTL]{xtics}[true]{} +\DTLxticstrue +% \end{macrocode} +%\end{macro} +%\begin{macro}{\ifDTLyticstrue} +% Condition to determine whether to show the $y$ tick marks +% \begin{macrocode} +\define@boolkey{dataplot}[DTL]{ytics}[true]{} +\DTLyticstrue +% \end{macrocode} +%\end{macro} +%\begin{macro}{\ifDTLxminortics} +% Condition to determine whether to show the $x$ minor tick marks +% \begin{macrocode} +\define@boolkey{dataplot}[DTL]{xminortics}[true]{% +\ifDTLxminortics \DTLxticstrue\fi} +\DTLxminorticsfalse +% \end{macrocode} +%\end{macro} +%\begin{macro}{\ifDTLyminortics} +% Condition to determine whether to show the $y$ minor tick marks +% \begin{macrocode} +\define@boolkey{dataplot}[DTL]{yminortics}[true]{% +\ifDTLyminortics \DTLyticstrue\fi} +\DTLyminorticsfalse +% \end{macrocode} +%\end{macro} +%\begin{macro}{\ifDTLgrid} +% Determine whether to draw the grid +% \begin{macrocode} +\define@boolkey{dataplot}[DTL]{grid}[true]{} +% \end{macrocode} +%\end{macro} +% Determine whether the $x$ tick marks should point +% in or out: +% \begin{macrocode} +\define@choicekey{dataplot}{xticdir}[\val\nr]{in,out}{% +\ifcase\nr\relax + \DTLxticsintrue +\or + \DTLxticsinfalse +\fi +} +% \end{macrocode} +% Determine whether the $y$ tick marks should point +% in or out: +% \begin{macrocode} +\define@choicekey{dataplot}{yticdir}[\val\nr]{in,out}{% +\ifcase\nr\relax + \DTLyticsintrue +\or + \DTLyticsinfalse +\fi +} +% \end{macrocode} +% Determine whether the $x$ and $y$ tick marks should point +% in or out; +% \begin{macrocode} +\define@choicekey{dataplot}{ticdir}[\val\nr]{in,out}{% +\ifcase\nr\relax + \DTLxticsintrue + \DTLyticsintrue +\or + \DTLxticsinfalse + \DTLyticsinfalse +\fi +} +% \end{macrocode} +% Set the bounds of the graph (value must be in the form +% \meta{min x}","\meta{min y}","\meta{max x}","\meta{max y} +% (bounds overrides minx, miny, maxx and maxy settings.) +% \begin{macrocode} +\define@key{dataplot}{bounds}{% +\def\dtl@bounds{#1}} +\let\dtl@bounds=\relax +% \end{macrocode} +% Set only the lower $x$ bound +% \begin{macrocode} +\define@key{dataplot}{minx}{% +\def\dtl@minx{#1}} +\let\dtl@minx=\relax +% \end{macrocode} +% Set only the upper $x$ bound: +% \begin{macrocode} +\define@key{dataplot}{maxx}{% +\def\dtl@maxx{#1}} +\let\dtl@maxx=\relax +% \end{macrocode} +% Set only the lower $y$ bound: +% \begin{macrocode} +\define@key{dataplot}{miny}{% +\def\dtl@miny{#1}} +\let\dtl@miny=\relax +% \end{macrocode} +% Set only the upper $y$ bound: +% \begin{macrocode} +\define@key{dataplot}{maxy}{% +\def\dtl@maxy{#1}} +\let\dtl@maxy=\relax +% \end{macrocode} +% Define list of points for $x$ ticks. (Must be a comma separated +% list of decimal numbers.) +% \begin{macrocode} +\define@key{dataplot}{xticpoints}{% +\def\dtl@xticlist{#1}\DTLxticstrue\DTLxaxistrue} +\let\dtl@xticlist=\relax +% \end{macrocode} +% Define list of points for $y$ ticks. (Must be a comma separated +% list of decimal numbers.) +% \begin{macrocode} +\define@key{dataplot}{yticpoints}{% +\def\dtl@yticlist{#1}\DTLyticstrue\DTLyaxistrue} +\let\dtl@yticlist=\relax +% \end{macrocode} +% Define a the gap between $x$ tick marks (xticpoints overrides +% xticgap) +% \begin{macrocode} +\define@key{dataplot}{xticgap}{\def\dtl@xticgap{#1}% +\DTLxticstrue\DTLxaxistrue} +\let\dtl@xticgap=\relax +% \end{macrocode} +% Define a the gap between $y$ tick marks (yticpoints overrides +% yticgap) +% \begin{macrocode} +\define@key{dataplot}{yticgap}{\def\dtl@yticgap{#1}% +\DTLyticstrue\DTLyaxistrue} +\let\dtl@yticgap=\relax +% \end{macrocode} +% Define comma separated list of labels for $x$ ticks. +% \begin{macrocode} +\define@key{dataplot}{xticlabels}{% +\def\dtl@xticlabels{#1}\DTLxticstrue\DTLxaxistrue} +\let\dtl@xticlabels=\relax +% \end{macrocode} +% Define comma separated list of labels for $y$ ticks. +% \begin{macrocode} +\define@key{dataplot}{yticlabels}{% +\def\dtl@yticlabels{#1}\DTLyticstrue\DTLyaxistrue} +\let\dtl@yticlabels=\relax +% \end{macrocode} +% Define $x$ axis label +% \begin{macrocode} +\define@key{dataplot}{xlabel}{% +\def\dtl@xlabel{#1}} +\let\dtl@xlabel=\relax +% \end{macrocode} +% Define $y$ axis label +% \begin{macrocode} +\define@key{dataplot}{ylabel}{% +\def\dtl@ylabel{#1}} +\let\dtl@ylabel=\relax +% \end{macrocode} +% The legend setting may be one of: "none" (don't show it), +% "north", "northeast", "east", "southeast", "south", "southwest", +% "west", or "northwest". These set the count register +% \cs{dtl@legendsetting}. +% \begin{macrocode} +\define@choicekey{dataplot}{legend}[\val\nr]{none,north,northeast,% +east,southeast,south,southwest,west,northwest}[northeast]{% +\dtl@legendsetting=\nr\relax +} +% \end{macrocode} +% Legend labels (comma separated list). If omitted, the database +% name is used. +% \begin{macrocode} +\define@key{dataplot}{legendlabels}{\def\dtl@legendlabels{#1}} +% \end{macrocode} +% +%\begin{macro}{\DTLplot} +%\begin{definition} +%\cs{DTLplot}\oarg{condition}\marg{db list}\marg{settings} +%\end{definition} +% Creates a plot (inside a \env{tikzpicture} environment) of all +% the data given in the databases listed in \meta{db list}. +% \begin{macrocode} +\newcommand*{\DTLplot}[3][\boolean{true}]{{% +\let\dtl@xkey=\relax +\let\dtl@ykey=\relax +\let\dtl@legendlabels=\relax +\setkeys{dataplot}{#3}% +\let\dtl@plotmarklist=\DTLplotmarks +\let\dtl@plotlinelist=\DTLplotlines +\let\dtl@plotmarkcolorlist=\DTLplotmarkcolors +\let\dtl@plotlinecolorlist=\DTLplotlinecolors +\def\dtl@legend{}% +\ifx\dtl@legendlabels\relax + \edef\dtl@legendlabels{#2}% +\fi +\ifx\dtl@xkey\relax + \PackageError{dataplot}{Missing x setting for + \string\DTLplot}{}% +\else + \ifx\dtl@ykey\relax + \PackageError{dataplot}{Missing y setting for + \string\DTLplot}{}% + \else +% \end{macrocode} +% If user didn't specified bounds, +% compute the maximum and minimum $x$ and $y$ values over +% all the databases listed. +% \begin{macrocode} + \ifx\dtl@bounds\relax + \DTLcomputebounds[#1]{#2}{\dtl@xkey}{\dtl@ykey} + {\DTLminX}{\DTLminY}{\DTLmaxX}{\DTLmaxY}% + \ifx\dtl@minx\relax + \else + \let\DTLminX=\dtl@minx + \fi + \ifx\dtl@maxx\relax + \else + \let\DTLmaxX=\dtl@maxx + \fi + \ifx\dtl@miny\relax + \else + \let\DTLminY=\dtl@miny + \fi + \ifx\dtl@maxy\relax + \else + \let\DTLmaxY=\dtl@maxy + \fi +% \end{macrocode} +% Otherwise extract information from \cs{dtl@bounds} +% \begin{macrocode} + \else + \expandafter\dtl@getbounds\dtl@bounds\@nil + \fi +% \end{macrocode} +% Determine scaling factors. +% \begin{macrocode} + \@dtl@tmpcount=\DTLplotwidth + \FPsub{\dtl@dx}{\DTLmaxX}{\DTLminX}% + \FPdiv{\dtl@unit@x}{\number\@dtl@tmpcount}{\dtl@dx}% + \@dtl@tmpcount=\DTLplotheight + \FPsub{\dtl@dy}{\DTLmaxY}{\DTLminY}% + \FPdiv{\dtl@unit@y}{\number\@dtl@tmpcount}{\dtl@dy}% +% \end{macrocode} +% If x tics specified, construct a list of x tic points if not +% already specified. +% \begin{macrocode} + \ifDTLxtics + \ifx\dtl@xticlist\relax + \ifx\dtl@xticgap\relax + \dtl@constructticklist\DTLminX\DTLmaxX + \dtl@unit@x\dtl@xticlist + \else + \DTLifFPopenbetween{0}{\DTLminX}{\DTLmaxX}{% + \dtl@constructticklistwithgapz + \DTLminX\DTLmaxX\dtl@xticlist\dtl@xticgap}{% + \dtl@constructticklistwithgap + \DTLminX\DTLmaxX\dtl@xticlist\dtl@xticgap}% + \fi + \fi +% \end{macrocode} +% Construct a list of $x$ minor tick points if required +% \begin{macrocode} + \let\dtl@xminorticlist\@empty + \ifDTLxminortics + \let\dtl@prevtick=\relax + \@for\dtl@nexttick:=\dtl@xticlist\do{% + \ifx\dtl@prevtick\relax + \else + \dtl@constructminorticklist + \dtl@prevtick\dtl@nexttick\dtl@unit@x\dtl@xminorticlist + \fi + \let\dtl@prevtick=\dtl@nexttick + }% + \fi +% \end{macrocode} +% Determine the height of the $x$ tick labels. +% \begin{macrocode} + \ifx\dtl@xticlabels\relax + \settoheight{\dtl@xticlabelheight}{\dtl@xticlist}% + \else + \settoheight{\dtl@xticlabelheight}{\dtl@xticlabels}% + \fi + \else + \setlength{\dtl@xticlabelheight}{0pt}% + \fi +% \end{macrocode} +% If y tics specified, construct a list of y tic points if not +% already specified. +% \begin{macrocode} + \setlength{\dtl@yticlabelwidth}{0pt}% + \ifDTLytics + \ifx\dtl@yticlist\relax + \ifx\dtl@yticgap\relax + \dtl@constructticklist\DTLminY\DTLmaxY + \dtl@unit@y\dtl@yticlist + \else + \DTLifFPopenbetween{0}{\DTLminY}{\DTLmaxY}{% + \dtl@constructticklistwithgapz + \DTLminY\DTLmaxY\dtl@yticlist\dtl@yticgap}{% + \dtl@constructticklistwithgap + \DTLminY\DTLmaxY\dtl@yticlist\dtl@yticgap}% + \fi + \fi +% \end{macrocode} +% Construct a list of $y$ minor tick points if required +% \begin{macrocode} + \let\dtl@yminorticlist\@empty + \ifDTLyminortics + \let\dtl@prevtick=\relax + \@for\dtl@nexttick:=\dtl@yticlist\do{% + \ifx\dtl@prevtick\relax + \else + \dtl@constructminorticklist + \dtl@prevtick\dtl@nexttick\dtl@unit@y\dtl@yminorticlist + \fi + \let\dtl@prevtick=\dtl@nexttick + }% + \fi +% \end{macrocode} +% Determine the width of the $y$ tick labels. +% \begin{macrocode} + \ifx\dtl@ylabel\relax + \else + \ifx\dtl@yticlabels\relax + \@for\dtl@thislabel:=\dtl@yticlist\do{% + \FPround{\dtl@thislabel}{\dtl@thislabel} + {\c@DTLplotroundYvar}% + \settowidth{\dtl@tmplength}{\dtl@thislabel}% + \ifdim\dtl@tmplength>\dtl@yticlabelwidth + \setlength{\dtl@yticlabelwidth}{\dtl@tmplength}% + \fi + }% + \else + \@for\dtl@thislabel:=\dtl@yticlabels\do{% + \settowidth{\dtl@tmplength}{\dtl@thislabel}% + \ifdim\dtl@tmplength>\dtl@yticlabelwidth + \setlength{\dtl@yticlabelwidth}{\dtl@tmplength}% + \fi + }% + \fi + \fi +% \end{macrocode} +% Start the picture. +% \begin{macrocode} + \begin{tikzpicture} +% \end{macrocode} +% Set the $x$ and $y$ unit vectors. +% \begin{macrocode} + \pgfsetxvec{\pgfpoint{\dtl@unit@x sp}{0pt}}% + \pgfsetyvec{\pgfpoint{0pt}{\dtl@unit@y sp}}% +% \end{macrocode} +% Add any extra information the user requires +% \begin{macrocode} + \DTLplotatbegintikz +% \end{macrocode} +% Determine whether to put a box around the plot +% \begin{macrocode} + \ifDTLbox + \draw (\DTLminX,\DTLminY) -- (\DTLmaxX,\DTLminY) -- + (\DTLmaxX,\DTLmaxY) -- (\DTLminX,\DTLmaxY) -- + cycle; + \else +% \end{macrocode} +% Plot $x$ axis if required. +% \begin{macrocode} + \ifDTLxaxis + \expandafter\draw\expandafter[\DTLXAxisStyle] + (\DTLminX,\DTLminY) -- (\DTLmaxX,\DTLminY); + \fi +% \end{macrocode} +% Plot $y$ axis if required. +% \begin{macrocode} + \ifDTLyaxis + \expandafter\draw\expandafter[\DTLYAxisStyle] + (\DTLminX,\DTLminY) -- (\DTLminX,\DTLmaxY); + \fi + \fi +% \end{macrocode} +% Plot grid if required +% \begin{macrocode} + \ifDTLgrid + \ifDTLxminortics + \@for\dtl@thistick:=\dtl@xminorticlist\do{% + \expandafter\draw\expandafter[\DTLminorgridstyle] + (\dtl@thistick,\DTLminY) -- (\dtl@thistick,\DTLmaxY); + }% + \fi + \ifDTLyminortics + \@for\dtl@thistick:=\dtl@yminorticlist\do{% + \expandafter\draw\expandafter[\DTLminorgridstyle] + (\DTLminX,\dtl@thistick) -- (\DTLmaxX,\dtl@thistick); + }% + \fi + \@for\dtl@thistick:=\dtl@xticlist\do{% + \expandafter\draw\expandafter[\DTLmajorgridstyle] + (\dtl@thistick,\DTLminY) -- (\dtl@thistick,\DTLmaxY); + }% + \@for\dtl@thistick:=\dtl@yticlist\do{% + \expandafter\draw\expandafter[\DTLmajorgridstyle] + (\DTLminX,\dtl@thistick) -- (\DTLmaxX,\dtl@thistick); + }% + \fi +% \end{macrocode} +% Plot $x$ tics if required. +% \begin{macrocode} + \ifDTLxtics + \addtolength\dtl@xticlabelheight{\DTLticklabeloffset}% + \@for\dtl@thistick:=\dtl@xticlist\do{% + \pgfpathmoveto{\pgfpointxy{\dtl@thistick}{\DTLminY}} + \ifDTLxticsin + \pgfpathlineto{ + \pgfpointadd{\pgfpointxy{\dtl@thistick}{\DTLminY}} + {\pgfpoint{0pt}{\DTLticklength}}} + \else + \pgfpathlineto{ + \pgfpointadd{\pgfpointxy{\dtl@thistick}{\DTLminY}} + {\pgfpoint{0pt}{-\DTLticklength}}} + \fi + \ifDTLbox + \pgfpathmoveto{\pgfpointxy{\dtl@thistick}{\DTLmaxY}} + \ifDTLxticsin + \pgfpathlineto{ + \pgfpointadd{\pgfpointxy{\dtl@thistick}{\DTLmaxY}} + {\pgfpoint{0pt}{-\DTLticklength}}} + \else + \pgfpathlineto{ + \pgfpointadd{\pgfpointxy{\dtl@thistick}{\DTLmaxY}} + {\pgfpoint{0pt}{\DTLticklength}}} + \fi + \fi + \pgfusepath{stroke}% +% \end{macrocode} +% Plot the tick labels +% \begin{macrocode} + \ifx\dtl@xticlabels\relax + \FPround{\dtl@thislabel}{\dtl@thistick} + {\c@DTLplotroundXvar}% + \else + \dtl@chopfirst\dtl@xticlabels\dtl@thislabel\dtl@rest + \let\dtl@xticlabels=\dtl@rest + \fi + \pgftext[base,center,at={\pgfpointadd + {\pgfpointxy{\dtl@thistick}{\DTLminY}} + {\pgfpoint{0pt}{-\dtl@xticlabelheight}}}] + {\dtl@thislabel} + }% + \fi +% \end{macrocode} +% Plot $x$ label if required. +% \begin{macrocode} + \ifx\dtl@xlabel\relax + \else + \addtolength{\dtl@xticlabelheight}{\baselineskip}% + \setlength{\dtl@tmplength}{0.5\DTLplotwidth} + \pgftext[base,center,at={\pgfpointadd + {\pgfpointxy{\DTLminX}{\DTLminY}}% + {\pgfpoint{\dtl@tmplength}{-\dtl@xticlabelheight}}}]{% + \dtl@xlabel} + \fi +% \end{macrocode} +% Plot the $x$ minor ticks if required +% \begin{macrocode} + \ifDTLxminortics + \@for\dtl@thistick:=\dtl@xminorticlist\do{% + \pgfpathmoveto{\pgfpointxy{\dtl@thistick}{\DTLminY}} + \ifDTLxticsin + \pgfpathlineto{ + \pgfpointadd{\pgfpointxy{\dtl@thistick}{\DTLminY}} + {\pgfpoint{0pt}{\DTLminorticklength}}} + \else + \pgfpathlineto{ + \pgfpointadd{\pgfpointxy{\dtl@thistick}{\DTLminY}} + {\pgfpoint{0pt}{-\DTLminorticklength}}} + \fi + \ifDTLbox + \pgfpathmoveto{\pgfpointxy{\dtl@thistick}{\DTLmaxY}} + \ifDTLxticsin + \pgfpathlineto{ + \pgfpointadd{\pgfpointxy{\dtl@thistick}{\DTLmaxY}} + {\pgfpoint{0pt}{-\DTLminorticklength}}} + \else + \pgfpathlineto{ + \pgfpointadd{\pgfpointxy{\dtl@thistick}{\DTLmaxY}} + {\pgfpoint{0pt}{\DTLminorticklength}}} + \fi + \fi + }% + \fi +% \end{macrocode} +% Plot $y$ tics if required. +% \begin{macrocode} + \ifDTLytics + \@for\dtl@thistick:=\dtl@yticlist\do{% + \pgfpathmoveto{\pgfpointxy{\DTLminX}{\dtl@thistick}} + \ifDTLyticsin + \pgfpathlineto{ + \pgfpointadd{\pgfpointxy{\DTLminX}{\dtl@thistick}} + {\pgfpoint{\DTLticklength}{0pt}}} + \else + \pgfpathlineto{ + \pgfpointadd{\pgfpointxy{\DTLminX}{\dtl@thistick}} + {\pgfpoint{-\DTLticklength}{0pt}}} + \fi + \ifDTLbox + \pgfpathmoveto{\pgfpointxy{\DTLmaxX}{\dtl@thistick}} + \ifDTLyticsin + \pgfpathlineto{ + \pgfpointadd{\pgfpointxy{\DTLmaxX}{\dtl@thistick}} + {\pgfpoint{-\DTLticklength}{0pt}}} + \else + \pgfpathlineto{ + \pgfpointadd{\pgfpointxy{\DTLmaxX}{\dtl@thistick}} + {\pgfpoint{\DTLticklength}{0pt}}} + \fi + \fi + \pgfusepath{stroke} +% \end{macrocode} +% Plot the $y$ tick labels if required +% \begin{macrocode} + \ifx\dtl@yticlabels\relax + \FPround{\dtl@thislabel}{\dtl@thistick} + {\c@DTLplotroundYvar}% + \else + \dtl@chopfirst\dtl@yticlabels\dtl@thislabel\dtl@rest + \let\dtl@yticlabels=\dtl@rest + \fi + \pgftext[right,at={\pgfpointadd + {\pgfpointxy{\DTLminX}{\dtl@thistick}} + {\pgfpoint{-\DTLticklabeloffset}{0pt}}}] + {\dtl@thislabel} + }% + \fi +% \end{macrocode} +% Plot $y$ label if required. +% \begin{macrocode} + \ifx\dtl@ylabel\relax + \else + \addtolength{\dtl@yticlabelwidth}{\baselineskip}% + \setlength{\dtl@tmplength}{0.5\DTLplotheight} + \pgftext[bottom,center,at={\pgfpointadd + {\pgfpointxy{\DTLminX}{\DTLminY}}% + {\pgfpoint{-\dtl@yticlabelwidth}{\dtl@tmplength}}}, + rotate=90]{% + \dtl@ylabel} + \fi +% \end{macrocode} +% Plot the $y$ minor ticks if required +% \begin{macrocode} + \ifDTLyminortics + \@for\dtl@thistick:=\dtl@yminorticlist\do{% + \pgfpathmoveto{\pgfpointxy{\DTLminX}{\dtl@thistick}} + \ifDTLyticsin + \pgfpathlineto{ + \pgfpointadd{\pgfpointxy{\DTLminX}{\dtl@thistick}} + {\pgfpoint{\DTLminorticklength}{0pt}}} + \else + \pgfpathlineto{ + \pgfpointadd{\pgfpointxy{\DTLminX}{\dtl@thistick}} + {\pgfpoint{-\DTLminorticklength}{0pt}}} + \fi + \ifDTLbox + \pgfpathmoveto{\pgfpointxy{\DTLmaxX}{\dtl@thistick}} + \ifDTLyticsin + \pgfpathlineto{ + \pgfpointadd{\pgfpointxy{\DTLmaxX}{\dtl@thistick}} + {\pgfpoint{-\DTLminorticklength}{0pt}}} + \else + \pgfpathlineto{ + \pgfpointadd{\pgfpointxy{\DTLmaxX}{\dtl@thistick}} + {\pgfpoint{\DTLminorticklength}{0pt}}} + \fi + \fi + \pgfusepath{stroke} + }% + \fi +% \end{macrocode} +% Iterate through each database +% \begin{macrocode} + \@for\dtl@thisdb:=#2\do{% +% \end{macrocode} +% Get the current plot mark colour. +% \begin{macrocode} + \ifx\dtl@plotmarkcolorlist\@empty + \let\dtl@plotmarkcolorlist=\DTLplotmarkcolors + \fi + \dtl@chopfirst\dtl@plotmarkcolorlist\dtl@thisplotmarkcolor + \dtl@remainder + \let\dtl@plotmarkcolorlist=\dtl@remainder +% \end{macrocode} +% Get the current plot mark, and store in \cs{dtl@mark} +% \begin{macrocode} + \ifDTLshowmarkers + \ifx\dtl@plotmarklist\@empty + \let\dtl@plotmarklist=\DTLplotmarks + \fi + \dtl@chopfirst\dtl@plotmarklist\dtl@thisplotmark + \dtl@remainder + \let\dtl@plotmarklist=\dtl@remainder + \ifx\dtl@thisplotmark\relax + \let\dtl@mark=\relax + \else + \expandafter\toks@\expandafter{\dtl@thisplotmark}% + \ifx\dtl@thisplotmarkcolor\@empty + \edef\dtl@mark{\the\toks@}% + \else + \edef\dtl@mark{% + \noexpand\color{\dtl@thisplotmarkcolor}% + \the\toks@}% + \fi + \fi + \else + \let\dtl@mark=\relax + \fi +% \end{macrocode} +% Get the current plot line colour. +% \begin{macrocode} + \ifx\dtl@plotlinecolorlist\@empty + \let\dtl@plotlinecolorlist=\DTLplotlinecolors + \fi + \dtl@chopfirst\dtl@plotlinecolorlist\dtl@thisplotlinecolor + \dtl@remainder + \let\dtl@plotlinecolorlist=\dtl@remainder +% \end{macrocode} +% Get the current line style, and store in \cs{dtl@linestyle} +% \begin{macrocode} + \ifDTLshowlines + \ifx\dtl@plotlinelist\@empty + \let\dtl@plotlinelist=\DTLplotlines + \fi + \dtl@chopfirst\dtl@plotlinelist\dtl@thisplotline + \dtl@remainder + \let\dtl@plotlinelist=\dtl@remainder + \expandafter\ifx\dtl@thisplotline\relax + \let\dtl@linestyle=\relax + \else + \expandafter\toks@\expandafter{\dtl@thisplotline}% + \ifx\dtl@thisplotlinecolor\@empty + \edef\dtl@linestyle{\the\toks@}% + \else + \edef\dtl@linestyle{% + \noexpand\color{\dtl@thisplotlinecolor}% + \the\toks@}% + \fi + \fi + \else + \let\dtl@linestyle=\relax + \fi +% \end{macrocode} +% Append this plot setting to the legend. +% \begin{macrocode} + \ifnum\dtl@legendsetting>0\relax + \dtl@chopfirst\dtl@legendlabels\dtl@thislabel\dtl@rest + \let\dtl@legendlabels=\dtl@rest + \expandafter\toks@\expandafter{\dtl@mark}% + \expandafter\@dtl@toks\expandafter{\dtl@linestyle}% + \edef\dtl@addtolegend{\noexpand\DTLaddtoplotlegend + {\the\toks@}{\the\@dtl@toks}{\dtl@thislabel}}% + \dtl@addtolegend + \fi +% \end{macrocode} +% Store stream in \cs{dtl@stream} +% \begin{macrocode} + \def\dtl@stream{\pgfplotstreamstart}% +% \end{macrocode} +% Only plot points that lie inside bounds. +%\changes{1.01}{2007 Aug 17}{uses \cs{@sDTLforeach} instead of +%\cs{DTLforeach}} +% \begin{macrocode} + \@sDTLforeach[#1]{\dtl@thisdb}{\dtl@x=\dtl@xkey,% + \dtl@y=\dtl@ykey}{% + \DTLconverttodecimal{\dtl@x}{\dtl@decx}% + \DTLconverttodecimal{\dtl@y}{\dtl@decy}% + \ifthenelse{% + \DTLisclosedbetween{\dtl@x}{\DTLminX}{\DTLmaxX}% + \and + \DTLisclosedbetween{\dtl@y}{\DTLminY}{\DTLmaxY}% + }{% + \expandafter\toks@\expandafter{\dtl@stream}% + \edef\dtl@stream{\the\toks@ + \noexpand\pgfplotstreampoint + {\noexpand\pgfpointxy{\dtl@decx}{\dtl@decy}}}% + }{}% + }% + \expandafter\toks@\expandafter{\dtl@stream}% + \edef\dtl@stream{\the\toks@\noexpand\pgfplotstreamend}% +% \end{macrocode} +% End plot stream and draw path. +% \begin{macrocode} + \ifx\dtl@linestyle\relax + \else + \begin{scope} + \dtl@linestyle + \pgfplothandlerlineto + \dtl@stream + \pgfusepath{stroke} + \end{scope} + \fi + \ifx\dtl@mark\relax + \else + \begin{scope} + \pgfplothandlermark{\dtl@mark}% + \dtl@stream + \pgfusepath{stroke} + \end{scope} + \fi + }% +% \end{macrocode} +% Plot legend if required. +% \begin{macrocode} + \ifcase\dtl@legendsetting + % none + \or % north + \pgftext[top,center,at={\pgfpointadd + {\pgfpointxy{\DTLminX}{\DTLmaxY}} + {\pgfpoint{0.5\DTLplotwidth}{-\DTLlegendyoffset}}}] + {\DTLformatlegend + {\begin{tabular}{cl}\dtl@legend\end{tabular}}} + \or % north east + \pgftext[top,right,at={\pgfpointadd + {\pgfpointxy{\DTLmaxX}{\DTLmaxY}} + {\pgfpoint{-\DTLlegendxoffset}{-\DTLlegendyoffset}}}] + {\DTLformatlegend + {\begin{tabular}{cl}\dtl@legend\end{tabular}}} + \or % east + \pgftext[center,right,at={\pgfpointadd + {\pgfpointxy{\DTLmaxX}{\DTLminY}} + {\pgfpoint{-\DTLlegendxoffset}{0.5\DTLplotheight}}}] + {\DTLformatlegend + {\begin{tabular}{cl}\dtl@legend\end{tabular}}} + \or % south east + \pgftext[bottom,right,at={\pgfpointadd + {\pgfpointxy{\DTLmaxX}{\DTLminY}} + {\pgfpoint{-\DTLlegendxoffset}{\DTLlegendyoffset}}}] + {\DTLformatlegend + {\begin{tabular}{cl}\dtl@legend\end{tabular}}} + \or % south + \pgftext[center,bottom,at={\pgfpointadd + {\pgfpointxy{\DTLminX}{\DTLminY}} + {\pgfpoint{0.5\DTLplotwidth}{\DTLlegendyoffset}}}] + {\DTLformatlegend + {\begin{tabular}{cl}\dtl@legend\end{tabular}}} + \or % south west + \pgftext[bottom,left,at={\pgfpointadd + {\pgfpointxy{\DTLminX}{\DTLminY}} + {\pgfpoint{\DTLlegendxoffset}{\DTLlegendyoffset}}}] + {\DTLformatlegend + {\begin{tabular}{cl}\dtl@legend\end{tabular}}} + \or % west + \pgftext[center,left,at={\pgfpointadd + {\pgfpointxy{\DTLminX}{\DTLminY}} + {\pgfpoint{\DTLlegendxoffset}{0.5\DTLplotheight}}}] + {\DTLformatlegend + {\begin{tabular}{cl}\dtl@legend\end{tabular}}} + \or % north west + \pgftext[top,left,at={\pgfpointadd + {\pgfpointxy{\DTLminX}{\DTLmaxY}} + {\pgfpoint{\DTLlegendxoffset}{-\DTLlegendyoffset}}}] + {\DTLformatlegend + {\begin{tabular}{cl}\dtl@legend\end{tabular}}} + \fi + \DTLplotatendtikz + \end{tikzpicture} + \fi + \fi +\fi +}} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\dtl@getbounds} +% Extract bounds: +% \begin{macrocode} +\def\dtl@getbounds#1,#2,#3,#4\@nil{% +\def\DTLminX{#1}% +\def\DTLminY{#2}% +\def\DTLmaxX{#3}% +\def\DTLmaxY{#4}% +\FPifgt{\DTLminX}{\DTLmaxX} + \PackageError{dataplot}{Min X > Max X in bounds #1,#2,#3,#4}{% + The bounds must be specified as minX,minY,maxX,maxY}% +\fi +\FPifgt{\DTLminY}{\DTLmaxY} + \PackageError{dataplot}{Min Y > Max Y in bounds #1,#2,#3,#4}{% + The bounds must be specified as minX,minY,maxX,maxY}% +\fi +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\dtl@constructticklist} +%\begin{definition} +%\cs{dtl@constructticklist}\marg{min}\marg{max}\marg{scale factor}\marg{list} +%\end{definition} +% Constructs a list of tick points between \meta{min} and \meta{max} +% and store in \meta{list} (a control sequence.) +% \begin{macrocode} +\newcommand*{\dtl@constructticklist}[4]{% +\DTLifFPopenbetween{0}{#1}{#2}{% + \FPsub{\@dtl@width}{0}{#1}% + \FPmul{\@dtl@width}{\@dtl@width}{#3}% + \FPdiv{\@dtl@neggap}{\@dtl@width}{10}% + \setlength\dtl@tmplength{\@dtl@neggap sp}% + \ifdim\dtl@tmplength<\DTLmintickgap + \FPdiv{\@dtl@neggap}{\@dtl@width}{4}% + \setlength\dtl@tmplength{\@dtl@neggap sp}% + \ifdim\dtl@tmplength<\DTLmintickgap + \FPdiv{\@dtl@neggap}{\@dtl@width}{2}% + \setlength\dtl@tmplength{\@dtl@neggap sp}% + \ifdim\dtl@tmplength<\DTLmintickgap + \let\@dtl@neggap=\@dtl@width + \fi + \fi + \fi + \FPmul{\@dtl@width}{#2}{#3}% + \FPdiv{\@dtl@posgap}{\@dtl@width}{10}% + \setlength\dtl@tmplength{\@dtl@posgap sp}% + \ifdim\dtl@tmplength<\DTLmintickgap + \FPdiv{\@dtl@posgap}{\@dtl@width}{4}% + \setlength\dtl@tmplength{\@dtl@posgap sp}% + \ifdim\dtl@tmplength<\DTLmintickgap + \FPdiv{\@dtl@posgap}{\@dtl@width}{2}% + \setlength\dtl@tmplength{\@dtl@posgap sp}% + \ifdim\dtl@tmplength<\DTLmintickgap + \let\@dtl@posgap=\@dtl@width + \fi + \fi + \fi + \FPmax{\@dtl@gap}{\@dtl@neggap}{\@dtl@posgap}% + \FPdiv{\@dtl@gap}{\@dtl@gap}{#3}% + \dtl@constructticklistwithgapz{#1}{#2}{#4}{\@dtl@gap}% +}{% + \FPsub{\@dtl@width}{#2}{#1}% + \FPmul{\@dtl@width}{\@dtl@width}{#3}% + \FPdiv{\@dtl@gap}{\@dtl@width}{10}% + \setlength\dtl@tmplength{\@dtl@gap sp}% + \ifdim\dtl@tmplength<\DTLmintickgap + \FPdiv{\@dtl@gap}{\@dtl@width}{4}% + \setlength\dtl@tmplength{\@dtl@gap sp}% + \ifdim\dtl@tmplength<\DTLmintickgap + \FPdiv{\@dtl@gap}{\@dtl@width}{2}% + \setlength\dtl@tmplength{\@dtl@gap sp}% + \ifdim\dtl@tmplength<\DTLmintickgap + \let\@dtl@gap=\@dtl@width + \fi + \fi + \fi + \FPdiv{\@dtl@gap}{\@dtl@gap}{#3}% + \dtl@constructticklistwithgap{#1}{#2}{#4}{\@dtl@gap}% +}% +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\dtl@constructticklistwithgap} +%\begin{definition} +%\cs{dtl@constructticklistwithgap}\marg{min}\marg{max}\marg{list}\marg{gap} +%\end{definition} +% Constructs a list of tick points between \meta{min} and \meta{max} +% and store in \meta{list} (a control sequence) using the gap given +% by \meta{gap} where the gap is given in user co-ordinates. +% \begin{macrocode} +\newcommand*{\dtl@constructticklistwithgap}[4]{% +\edef\@dtl@thistick{#1}% +\edef#3{#1}% +\FPadd{\@dtl@thistick}{\@dtl@thistick}{#4}% +\whiledo{\DTLisFPopenbetween{\@dtl@thistick}{#1}{#2}}{% + \expandafter\toks@\expandafter{\@dtl@thistick}% + \edef#3{#3,\the\toks@}% + \FPadd{\@dtl@thistick}{\@dtl@thistick}{#4}% +}% +\expandafter\toks@\expandafter{#2}% +\edef#3{#3,\the\toks@}% +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\dtl@constructticklistwithgapz} +%\begin{definition} +%\cs{dtl@constructticklistwithgapz}\marg{min}\marg{max}\marg{list}\marg{gap} +%\end{definition} +% Constructs a list of tick points between \meta{min} and \meta{max} +% and store in \meta{list} (a control sequence) using the gap given +% by \meta{gap} where the tick list straddles zero. +% \begin{macrocode} +\newcommand*{\dtl@constructticklistwithgapz}[4]{% +\edef\@dtl@thistick{0}% +\edef#3{0}% +\FPadd{\@dtl@thistick}{\@dtl@thistick}{#4}% +\whiledo{\DTLisFPopenbetween{\@dtl@thistick}{0}{#2}}{% + \expandafter\toks@\expandafter{\@dtl@thistick}% + \edef#3{#3,\the\toks@}% + \FPadd{\@dtl@thistick}{\@dtl@thistick}{#4}% +}% +\expandafter\toks@\expandafter{#2}% +\edef#3{#3,\the\toks@}% +\FPifeq{#1}{0}% +\else +\edef\@dtl@thistick{0}% + \FPsub{\@dtl@thistick}{\@dtl@thistick}{#4}% + \whiledo{\DTLisFPopenbetween{\@dtl@thistick}{#1}{0}}{% + \expandafter\toks@\expandafter{\@dtl@thistick}% + \edef#3{\the\toks@,#3}% + \FPsub{\@dtl@thistick}{\@dtl@thistick}{#4}% + }% + \expandafter\toks@\expandafter{#1}% + \edef#3{\the\toks@,#3}% +\fi +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\dtl@constructminorticklist} +%\begin{definition} +%\cs{dtl@constructminorticklist}\marg{min}\marg{max}\marg{scale factor}\marg{list} +%\end{definition} +% Constructs a list of minor tick points between \meta{min} and \meta{max} +% and append to \meta{list} (a control sequence.) +% \begin{macrocode} +\newcommand*{\dtl@constructminorticklist}[4]{% + \FPsub{\@dtl@width}{#2}{#1}% + \FPmul{\@dtl@width}{\@dtl@width}{#3}% + \FPdiv{\@dtl@gap}{\@dtl@width}{10}% + \setlength\dtl@tmplength{\@dtl@gap sp}% + \ifdim\dtl@tmplength<\DTLminminortickgap + \FPdiv{\@dtl@gap}{\@dtl@width}{4}% + \setlength\dtl@tmplength{\@dtl@gap sp}% + \ifdim\dtl@tmplength<\DTLminminortickgap + \FPdiv{\@dtl@gap}{\@dtl@width}{2}% + \setlength\dtl@tmplength{\@dtl@gap sp}% + \ifdim\dtl@tmplength<\DTLminminortickgap + \let\@dtl@gap=\@dtl@width + \fi + \fi + \fi + \FPdiv{\@dtl@gap}{\@dtl@gap}{#3}% + \dtl@constructticklistwithgapex{#1}{#2}{\dtl@tmp}{\@dtl@gap}% + \ifx#4\@empty + \let#4=\dtl@tmp + \else + \expandafter\toks@\expandafter{#4}% + \edef#4{#4,\dtl@tmp}% + \fi +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\dtl@constructticklistwithgapex} +%\begin{definition} +%\cs{dtl@constructticklistwithgapex}\marg{min}\marg{max}\marg{list}\marg{gap} +%\end{definition} +% Constructs a list of tick points between \meta{min} and \meta{max} +% and store in \meta{list} (a control sequence) using the gap given +% by \meta{gap} where the gap is given in user co-ordinates. +% The end points are excluded from the list. +% \begin{macrocode} +\newcommand*{\dtl@constructticklistwithgapex}[4]{% +\edef\@dtl@thistick{#1}% +\let#3=\@empty +\FPadd{\@dtl@thistick}{\@dtl@thistick}{#4}% +\whiledo{\DTLisFPopenbetween{\@dtl@thistick}{#1}{#2}}{% + \expandafter\toks@\expandafter{\@dtl@thistick}% + \ifx#3\@empty + \edef#3{\the\toks@}% + \else + \edef#3{#3,\the\toks@}% + \fi + \FPadd{\@dtl@thistick}{\@dtl@thistick}{#4}% +}% +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLaddtoplotlegend} +%\begin{definition} +%\cs{DTLaddtoplotlegend}\marg{marker}\marg{line style}\marg{label} +%\end{definition} +% Adds entry to legend. +% \begin{macrocode} +\newcommand*{\DTLaddtoplotlegend}[3]{% +\def\dtl@legendline{}% +\ifx\relax#2\relax +\else + \toks@{#2% + \pgfpathmoveto{\pgfpoint{-10pt}{0pt}}% + \pgfpathlineto{\pgfpoint{10pt}{0pt}}% + \pgfusepath{stroke}}% + \edef\dtl@legendline{\the\toks@}% +\fi +\ifx\relax#1\relax +\else + \toks@{#1}% + \expandafter\@dtl@toks\expandafter{\dtl@legendline}% + \edef\dtl@legendline{\the\@dtl@toks\the\toks@}% +\fi +\expandafter\toks@\expandafter{\dtl@legendline}% +\ifx\dtl@legend\@empty + \edef\dtl@legend{\noexpand\tikz\the\toks@; \noexpand& #3}% +\else + \expandafter\@dtl@toks\expandafter{\dtl@legend}% + \edef\dtl@legend{\the\@dtl@toks\noexpand\\% + \noexpand\tikz\the\toks@; \noexpand& #3}% +\fi +} +% \end{macrocode} +%\end{macro} +%\iffalse +% \begin{macrocode} +%</dataplot.sty> +% \end{macrocode} +%\fi +%\iffalse +% \begin{macrocode} +%<*databar.sty> +% \end{macrocode} +%\fi +%\section{databar.sty} +% Declare package: +% \begin{macrocode} +\NeedsTeXFormat{LaTeX2e} +\ProvidesPackage{databar}[2007/08/17 v1.01 (NLCT)] +% \end{macrocode} +% Require \sty{xkeyval} package +% \begin{macrocode} +\RequirePackage{xkeyval} +% \end{macrocode} +% Require \sty{dataplot} package +% \begin{macrocode} +\RequirePackage{dataplot} +% \end{macrocode} +%\begin{macro}{\ifDTLcolorbarchart} +% The conditional \cs{ifDTLcolorbarchart} is used to determine +% whether to use colour or grey scale. +% \begin{macrocode} +\newif\ifDTLcolorbarchart +\DTLcolorbarcharttrue +% \end{macrocode} +%\end{macro} +% Package options to change the conditional: +% \begin{macrocode} +\DeclareOption{color}{\DTLcolorbarcharttrue} +\DeclareOption{gray}{\DTLcolorbarchartfalse} +% \end{macrocode} +%\cs{DTLbarXlabelalign} specifies the alignment +% for the $x$ axis labels. +% \begin{macrocode} +\newcommand*{\DTLbarXlabelalign}{left,rotate=-90} +% \end{macrocode} +%\cs{DTLbarYticklabelalign} specifies the alignment +% for the $x$ axis labels. +% \begin{macrocode} +\newcommand*{\DTLbarYticklabelalign}{right} +% \end{macrocode} +%\begin{macro}{\ifDTLverticalbars} +% Define boolean keys to govern bar chart orientation. +% \begin{macrocode} +\define@boolkey{databar}[DTL]{verticalbars}[true]{% +\ifDTLverticalbars + \def\DTLbarXlabelalign{left,rotate=-90}% + \def\DTLbarYticklabelalign{right} +\else + \def\DTLbarXlabelalign{right}% + \def\DTLbarYticklabelalign{center} +\fi} +% \end{macrocode} +%\end{macro} +% Set defaults: +% \begin{macrocode} +\DTLverticalbarstrue +% \end{macrocode} +% Package options to change \cs{ifDTLverticalbars} +% \begin{macrocode} +\DeclareOption{vertical}{\DTLverticalbarstrue + \def\DTLbarXlabelalign{left,rotate=-90}% + \def\DTLbarYticklabelalign{right} +} +\DeclareOption{horizontal}{\DTLverticalbarsfalse + \def\DTLbarXlabelalign{right}% + \def\DTLbarYticklabelalign{center} +} +% \end{macrocode} +% Process options: +% \begin{macrocode} +\ProcessOptions +% \end{macrocode} +% Required packages: +% \begin{macrocode} +\RequirePackage{datatool} +\RequirePackage{tikz} +% \end{macrocode} +% Define some variables that govern the appearance of the bar +% chart. +% +%\begin{macro}{\DTLbarchartlength} +% The total height of the bar chart is given by \cs{DTLbarchartheight} +% \begin{macrocode} +\newlength\DTLbarchartlength +\DTLbarchartlength=3in +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLbarwidth} +% The width of each bar is given by \cs{DTLbarwidth}. +% \begin{macrocode} +\newlength\DTLbarwidth +\DTLbarwidth=1cm +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLbarlabeloffset} +% The offset from the $x$ axis to the bar label if given by +% \cs{DTLbarlabeloffset}. +% \begin{macrocode} +\newlength\DTLbarlabeloffset +\setlength\DTLbarlabeloffset{10pt} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLBarXAxisStyle} +% The style of the $x$ axis is given by \cs{DTLBarXAxisStyle} +% \begin{macrocode} +\newcommand*{\DTLBarXAxisStyle}{-} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLBarYAxisStyle} +% The style of the $y$ axis is given by \cs{DTLBarYAxisStyle}. +% \begin{macrocode} +\newcommand*{\DTLBarYAxisStyle}{-} +% \end{macrocode} +%\end{macro} +% +% \counterfmt{DTLbarroundvar} is a counter governing the number of digits +% to round to when using \cs{FPround}. +% \begin{macrocode} +\newcounter{DTLbarroundvar} +\setcounter{DTLbarroundvar}{1} +% \end{macrocode} +% +%\begin{macro}{\DTLbardisplayYticklabel} +%\cs{DTLbardisplayYticklabel} governs how the $y$ tick labels appear. +% \begin{macrocode} +\newcommand*{\DTLbardisplayYticklabel}[1]{#1} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLdisplaylowerbarlabel} +%\cs{DTLdisplaylowerbarlabel} governs how the lower bar labels appear. +% \begin{macrocode} +\newcommand*{\DTLdisplaylowerbarlabel}[1]{#1} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLdisplaylowermultibarlabel} +%\cs{DTLdisplaylowermultibarlabel} governs how the lower multi bar labels appear. +% \begin{macrocode} +\newcommand*{\DTLdisplaylowermultibarlabel}[1]{#1} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLdisplayupperbarlabel} +%\cs{DTLdisplayupperbarlabel} governs how the upper bar labels +% appear. +% \begin{macrocode} +\newcommand*{\DTLdisplayupperbarlabel}[1]{#1} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLdisplayuppermultibarlabel} +%\cs{DTLdisplayuppermultibarlabel} governs how the upper multi bar +% labels appear. +% \begin{macrocode} +\newcommand*{\DTLdisplayuppermultibarlabel}[1]{#1} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLbaratbegintikz} +% \cs{DTLbaratbegintikz} specifies any commands +% to apply at the start of the \env{tikzpicture} environment. +% By default it does nothing. +% \begin{macrocode} +\newcommand*{\DTLbaratbegintikz}{} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLbaratendtikz} +% \cs{DTLbaratendtikz} specifies any commands +% to apply at the end of the \env{tikzpicture} environment. +% By default it does nothing. +% \begin{macrocode} +\newcommand*{\DTLbaratendtikz}{} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\ifDTLbarxaxis} +% The conditional \cs{ifDTLbarxaxis} is used to determine +% whether or not to display the $x$ axis +% \begin{macrocode} +\newif\ifDTLbarxaxis +% \end{macrocode} +%\end{macro} +%\begin{macro}{\ifDTLbaryaxis} +% The conditional \cs{ifDTLbaryaxis} is used to determine +% whether or not to display the $y$ axis. +% \begin{macrocode} +\newif\ifDTLbaryaxis +% \end{macrocode} +%\end{macro} +%\begin{macro}{\ifDTLbarytics} +% The conditional \cs{ifDTLbarytics} to determine whether +% or not to display the $y$ tick marks. +% \begin{macrocode} +\newif\ifDTLbarytics +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\@dtl@barcount} +% The count register \cs{@dtl@barcount} is used to store +% the current bar index. +% \begin{macrocode} +\newcount\@dtl@barcount +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLsetbarcolor} +%\begin{definition} +% \cs{DTLsetbarcolor}\marg{n}\marg{color} +%\end{definition} +% Assigns colour name \meta{color} to the \meta{n}th bar. +% \begin{macrocode} +\newcommand*{\DTLsetbarcolor}[2]{% +\expandafter\def\csname dtlbar@segcol\romannumeral#1\endcsname{#2}% +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLgetbarcolor} +%\begin{definition} +%\cs{DTLgetbarcolor}\marg{n} +%\end{definition} +% Gets the colour specification for the \meta{n}th bar. +% \begin{macrocode} +\newcommand*{\DTLgetbarcolor}[1]{% +\csname dtlbar@segcol\romannumeral#1\endcsname} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLdobarcolor} +%\begin{definition} +%\cs{DTLdobarcolor}\marg{n} +%\end{definition} +% Sets the colour to that for the \meta{n}th bar. +% \begin{macrocode} +\newcommand*{\DTLdobarcolor}[1]{% +\expandafter\color\expandafter +{\csname dtlbar@segcol\romannumeral#1\endcsname}} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLdocurrentbarcolor} +%\cs{DTLdocurrentbarcolor} +% sets the colour to that of the current bar. +% \begin{macrocode} +\newcommand*{\DTLdocurrentbarcolor}{% +\ifnum\dtlforeachlevel=0\relax + \PackageError{databar}{Can't use + \string\DTLdocurrentbarcolor\space outside + \string\DTLbarchart}{}% +\else + \expandafter\DTLdobarcolor\expandafter{% + \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname}% +\fi} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLbaroutlinecolor} +%\cs{DTLbaroutlinecolor} specifies what colour to draw the +% outline. +% \begin{macrocode} +\newcommand*{\DTLbaroutlinecolor}{black} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLbaroutlinewidth} +%\cs{DTLbaroutlinewidth} specifies the line width of the outline: +% Outline is only drawn if the linewidth is greater than 0pt. +% \begin{macrocode} +\newlength\DTLbaroutlinewidth +\DTLbaroutlinewidth=0pt +% \end{macrocode} +%\end{macro} +% +% Set the default colours. If there are more than eight bars, +% more colours will need to be defined. +% \begin{macrocode} +\ifDTLcolorbarchart + \DTLsetbarcolor{1}{red} + \DTLsetbarcolor{2}{green} + \DTLsetbarcolor{3}{blue} + \DTLsetbarcolor{4}{yellow} + \DTLsetbarcolor{5}{magenta} + \DTLsetbarcolor{6}{cyan} + \DTLsetbarcolor{7}{orange} + \DTLsetbarcolor{8}{white} +\else + \DTLsetbarcolor{1}{black!15} + \DTLsetbarcolor{2}{black!25} + \DTLsetbarcolor{3}{black!35} + \DTLsetbarcolor{4}{black!45} + \DTLsetbarcolor{5}{black!55} + \DTLsetbarcolor{6}{black!65} + \DTLsetbarcolor{7}{black!75} + \DTLsetbarcolor{8}{black!85} +\fi +% \end{macrocode} +% +% Define keys for \cs{DTLbarchart} optional argument. +% Set the maximum value of the $y$ axis. +% \begin{macrocode} +\define@key{databar}{max}{\def\DTLbarmax{#1}} +% \end{macrocode} +% Set the total length of the bar chart +% \begin{macrocode} +\define@key{databar}{length}{\DTLbarchartlength=#1\relax +} +% \end{macrocode} +% Set the maximum depth (negative extent) +% \begin{macrocode} +\define@key{databar}{maxdepth}{% +\ifnum#1>0\relax + \PackageError{databar}{depth must be zero or negative}{}% +\else + \def\DTLnegextent{#1}% +\fi} +% \end{macrocode} +% Determine which axes should be shown +% \begin{macrocode} +\define@choicekey{databar}{axes}[\var\nr]{both,x,y,none}{% +\ifcase\nr\relax + % both + \DTLbarxaxistrue + \DTLbaryaxistrue + \DTLbaryticstrue +\or + % x only + \DTLbarxaxistrue + \DTLbaryaxisfalse + \DTLbaryticsfalse +\or + % y only + \DTLbarxaxisfalse + \DTLbaryaxistrue + \DTLbaryticstrue +\or + % neither + \DTLbarxaxisfalse + \DTLbaryaxisfalse + \DTLbaryticsfalse +\fi +} +% \end{macrocode} +% Variable used to create the bar chart. (Must be a control +% sequence.) +% \begin{macrocode} +\define@key{databar}{variable}{% +\def\DTLbarvariable{#1}} +% \end{macrocode} +% Variables used to create the multi bar chart. (Must be a +% comma separated list of control sequences.) +% \begin{macrocode} +\define@key{databar}{variables}{% +\def\dtlbar@variables{#1}} +% \end{macrocode} +% Bar width +% \begin{macrocode} +\define@key{databar}{barwidth}{\setlength{\DTLbarwidth}{#1}} +% \end{macrocode} +% Lower bar labels +% \begin{macrocode} +\define@key{databar}{barlabel}{% +\def\dtl@barlabel{#1}} +\def\dtl@barlabel{} +% \end{macrocode} +% Lower bar labels for multi-bar charts +% \begin{macrocode} +\define@key{databar}{multibarlabels}{% +\def\dtl@multibarlabels{#1}} +\def\dtl@multibarlabels{} +% \end{macrocode} +% Gap between groups in multi-bar charts (This should be in $x$ units +% where 1 $x$ unit is the width of a bar.) +% \begin{macrocode} +\define@key{databar}{groupgap}{\def\dtlbar@groupgap{#1}} +\def\dtlbar@groupgap{1} +% \end{macrocode} +% Upper bar labels +% \begin{macrocode} +\define@key{databar}{upperbarlabel}{% +\def\dtl@upperbarlabel{#1}} +\def\dtl@upperbarlabel{} +% \end{macrocode} +% Upper bar labels for multi-bar charts +% \begin{macrocode} +\define@key{databar}{uppermultibarlabels}{% +\def\dtl@uppermultibarlabels{#1}} +\def\dtl@uppermultibarlabels{} +% \end{macrocode} +% Define list of points for $y$ tics. (Must be a comma separated list +% of decimal numbers.) +% \begin{macrocode} +\define@key{databar}{yticpoints}{% +\def\dtlbar@yticlist{#1}\DTLbaryticstrue\DTLbaryaxistrue} +\let\dtlbar@yticlist=\relax +% \end{macrocode} +% Set the $y$ tick gap: +% \begin{macrocode} +\define@key{databar}{yticgap}{% +\def\dtlbar@yticgap{#1}\DTLbaryticstrue\DTLbaryaxistrue} +\let\dtlbar@yticgap=\relax +% \end{macrocode} +% Define list of labels for $y$ tics. +% \begin{macrocode} +\define@key{databar}{yticlabels}{% +\def\dtlbar@yticlabels{#1}\DTLbaryticstrue\DTLbaryaxistrue} +\let\dtlbar@yticlabels=\relax +% \end{macrocode} +% Define $y$ axis label. +% \begin{macrocode} +\define@key{databar}{ylabel}{% +\def\dtlbar@ylabel{#1}} +\let\dtlbar@ylabel=\relax +% \end{macrocode} +% +%\begin{macro}{\DTLbarchart} +%\begin{definition} +% \cs{DTLbarchart}\oarg{conditions}\marg{option list}\marg{db name}\marg{assign list} +%\end{definition} +% Make a bar chart from data given in data base \meta{db name}, +% where \meta{assign list} is a comma-separated list of +% \meta{cmd}\texttt{=}\meta{key} pairs. \meta{option list} must +% include \texttt{variable}\texttt{=}\meta{cmd}, where \meta{cmd} +% is included in \meta{assign list}. The optional argument +% \meta{conditions} is the same as that for \cs{DTLforeach}. +% \begin{macrocode} +\newcommand*{\DTLbarchart}[4][\boolean{true}]{% +{\let\DTLbarvariable=\relax +\let\DTLbarmax=\relax +\let\DTLnegextent=\relax +\disable@keys{databar}{variables,multibarlabels,% +uppermultibarlabels,groupgap}% +\setkeys{databar}{#2}% +\ifx\DTLbarvariable\relax + \PackageError{databar}{\string\DTLbarchart\space missing variable}{}% +\else +% \end{macrocode} +% Compute the maximum bar height, unless \cs{DTLbarmax} has been +% set. +%\changes{1.01}{2007 Aug 17}{uses \cs{@sDTLforeach} instead of +%\cs{DTLforeach}} +% \begin{macrocode} + \ifx\DTLbarmax\relax + \@sDTLforeach[#1]{#3}{#4}{% + \expandafter\DTLconverttodecimal\expandafter + {\DTLbarvariable}{\dtl@barvar}% + \ifx\DTLbarmax\relax + \let\DTLbarmax=\dtl@barvar + \else + \let\dtl@old=\DTLbarmax + \FPmax{\DTLbarmax}{\dtl@old}{\dtl@barvar}% + \fi + }% + \ifx\dtlbar@yticgap\relax + \else + \let\dtl@thistick=\dtlbar@yticgap% + \whiledo{\DTLisFPopenbetween{\dtl@thistick}{0}{\DTLbarmax}}{% + \FPadd{\dtl@thistick}{\dtl@thistick}{\dtlbar@yticgap}% + }% + \let\DTLbarmax=\dtl@thistick + \fi + \fi +% \end{macrocode} +% Compute the bar depth, unless \cs{DTLnegextent} has been +% set. +% \begin{macrocode} + \ifx\DTLnegextent\relax + \def\DTLnegextent{0}% + \@sDTLforeach[#1]{#3}{#4}{% + \expandafter\DTLconverttodecimal\expandafter + {\DTLbarvariable}{\dtl@barvar}% + \let\dtl@old=\DTLnegextent + \DTLmin{\DTLnegextent}{\dtl@old}{\dtl@barvar}% + }% + \ifx\dtlbar@yticgap\relax + \else + \ifthenelse{\DTLisFPlt{\DTLnegextent}{0}}{% + \edef\dtl@thistick{0}% + \whiledo{\DTLisFPclosedbetween{\dtl@thistick}{\DTLnegextent}{0}}{% + \FPsub{\dtl@thistick}{\dtl@thistick}{\dtlbar@yticgap}% + }% + \let\DTLnegextent=\dtl@thistick + }{}% + \fi + \fi +% \end{macrocode} +% Determine scaling factor +% \begin{macrocode} + \@dtl@tmpcount=\DTLbarchartlength + \FPsub{\dtl@extent}{\DTLbarmax}{\DTLnegextent}% + \FPdiv{\dtl@unit}{\number\@dtl@tmpcount}{\dtl@extent}% +% \end{macrocode} +% Construct $y$ tick list if required +% \begin{macrocode} + \setlength{\dtl@yticlabelwidth}{0pt}% + \ifDTLbarytics + \ifx\dtlbar@yticlist\relax + \ifx\dtlbar@yticgap\relax + \dtl@constructticklist\DTLnegextent\DTLbarmax + \dtl@unit\dtlbar@yticlist + \else + \dtl@constructticklistwithgapz + \DTLnegextent\DTLbarmax\dtlbar@yticlist\dtlbar@yticgap + \fi + \fi + \ifx\dtlbar@ylabel\relax + \else + \ifx\dtlbar@yticlabels\relax + \@for\dtl@thislabel:=\dtlbar@yticlist\do{% + \FPround{\dtl@thislabel}{\dtl@thislabel} + {\c@DTLbarroundvar}% + \ifDTLverticalbars + \settowidth{\dtl@tmplength}{% + \DTLbardisplayYticklabel{\dtl@thislabel}}% + \else + \settoheight{\dtl@tmplength}{% + \DTLbardisplayYticklabel{\dtl@thislabel}}% + \edef\@dtl@h{\the\dtl@tmplength}% + \settodepth{\dtl@tmplength}{% + \DTLbardisplayYticklabel{\dtl@thislabel}}% + \addtolength{\dtl@tmplength}{\@dtl@h}% + \addtolength{\dtl@tmplength}{\baselineskip}% + \fi + \ifdim\dtl@tmplength>\dtl@yticlabelwidth + \setlength{\dtl@yticlabelwidth}{\dtl@tmplength}% + \fi + }% + \else + \@for\dtl@thislabel:=\dtlbar@yticlabels\do{% + \ifDTLverticalbars + \settowidth{\dtl@tmplength}{% + \DTLbardisplayYticklabel{\dtl@thislabel}}% + \else + \settoheight{\dtl@tmplength}{% + \DTLbardisplayYticklabel{\dtl@thislabel}}% + \edef\@dtl@h{\the\dtl@tmplength}% + \settodepth{\dtl@tmplength}{% + \DTLbardisplayYticklabel{\dtl@thislabel}}% + \addtolength{\dtl@tmplength}{\@dtl@h}% + \addtolength{\dtl@tmplength}{\baselineskip}% + \fi + \ifdim\dtl@tmplength>\dtl@yticlabelwidth + \setlength{\dtl@yticlabelwidth}{\dtl@tmplength}% + \fi + }% + \fi + \fi + \fi +% \end{macrocode} +% Store the width of the bar chart in \cs{DTLbarchartwidth} +% \begin{macrocode} +\edef\DTLbarchartwidth{\expandafter\number\csname dtlrows@#3\endcsname} +% \end{macrocode} +% Do the bar chart +% \begin{macrocode} +\begin{tikzpicture} +% \end{macrocode} +% Set unit vectors +% \begin{macrocode} +\ifDTLverticalbars + \pgfsetyvec{\pgfpoint{0pt}{\dtl@unit sp}}% + \pgfsetxvec{\pgfpoint{\DTLbarwidth}{0pt}}% +\else + \pgfsetxvec{\pgfpoint{\dtl@unit sp}{0pt}}% + \pgfsetyvec{\pgfpoint{0pt}{\DTLbarwidth}}% +\fi +% \end{macrocode} +% Begin hook +% \begin{macrocode} +\DTLbaratbegintikz +% \end{macrocode} +% Initialise +% \begin{macrocode} +\def\@dtl@start{0}% +% \end{macrocode} +% Iterate through data +% \begin{macrocode} +\@sDTLforeach[#1]{#3}{#4}{% +% \end{macrocode} +% Store the bar number in \cs{@dtl@bar} +% \begin{macrocode} +\expandafter\let\expandafter\@dtl@bar + \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname% +% \end{macrocode} +% Convert variable to decimal +% \begin{macrocode} +\expandafter\DTLconverttodecimal\expandafter + {\DTLbarvariable}{\dtl@variable}% +% \end{macrocode} +% Draw bars +% \begin{macrocode} +\begin{scope} + \DTLdocurrentbarcolor + \ifDTLverticalbars + \fill (\@dtl@start,0) -- (\@dtl@start,\dtl@variable) + -- (\@dtl@bar,\dtl@variable) -- (\@dtl@bar,0) -- cycle; + \else + \fill (0,\@dtl@start) -- (\dtl@variable,\@dtl@start) + -- (\dtl@variable,\@dtl@bar) -- (0,\@dtl@bar) -- cycle; + \fi +\end{scope} +% \end{macrocode} +% Draw outline +% \begin{macrocode} +\begin{scope} +\ifdim\DTLbaroutlinewidth>0pt + \expandafter\color\expandafter{\DTLbaroutlinecolor} + \ifDTLverticalbars + \draw (\@dtl@start,0) -- (\@dtl@start,\dtl@variable) + -- (\@dtl@bar,\dtl@variable) -- (\@dtl@bar,0) -- cycle; + \else + \draw (0,\@dtl@start) -- (\dtl@variable,\@dtl@start) + -- (\dtl@variable,\@dtl@bar) -- (0,\@dtl@bar) -- cycle; + \fi +\fi +\end{scope} +% \end{macrocode} +% Draw lower $x$ labels +% \begin{macrocode} +\ifDTLverticalbars + \edef\dtl@textopt{% + at={\noexpand\pgfpointadd + {\noexpand\pgfpointxy{\@dtl@start.5}{0}} + {\noexpand\pgfpoint{0pt}{-\noexpand\DTLbarlabeloffset}}}, + \DTLbarXlabelalign + }% +\else + \edef\dtl@textopt{% + at={\noexpand\pgfpointadd + {\noexpand\pgfpointxy{0}{\@dtl@start.5}} + {\noexpand\pgfpoint{-\noexpand\DTLbarlabeloffset}{0pt}}}, + \DTLbarXlabelalign + }% +\fi + \expandafter\pgftext\expandafter[\dtl@textopt]{% + \DTLdisplaylowerbarlabel{\dtl@barlabel}} +% \end{macrocode} +% Draw upper $x$ labels +% \begin{macrocode} +\ifDTLverticalbars + \expandafter\DTLifnumlt\expandafter{\DTLbarvariable}{0} + { + \edef\dtl@textopt{% + at={\noexpand\pgfpointadd + {\noexpand\pgfpointxy{\@dtl@start.5}{\dtl@variable}} + {\noexpand\pgfpoint{0pt}{-\noexpand\DTLbarlabeloffset}}} + }% + }{% + \edef\dtl@textopt{% + at={\noexpand\pgfpointadd + {\noexpand\pgfpointxy{\@dtl@start.5}{\dtl@variable}} + {\noexpand\pgfpoint{0pt}{\noexpand\DTLbarlabeloffset}}} + }% + } +\else + \expandafter\DTLifnumlt\expandafter{\DTLbarvariable}{0} + { + \edef\dtl@textopt{right, + at={\noexpand\pgfpointadd + {\noexpand\pgfpointxy{\dtl@variable}{\@dtl@start.5}} + {\noexpand\pgfpoint{-\noexpand\DTLbarlabeloffset}{0pt}}} + }% + }{% + \edef\dtl@textopt{left, + at={\noexpand\pgfpointadd + {\noexpand\pgfpointxy{\dtl@variable}{\@dtl@start.5}} + {\noexpand\pgfpoint{\noexpand\DTLbarlabeloffset}{0pt}}} + }% + } +\fi + \expandafter\pgftext\expandafter[\dtl@textopt]{% + \DTLdisplayupperbarlabel{\dtl@upperbarlabel}} +% \end{macrocode} +% End of loop +% \begin{macrocode} + \edef\@dtl@start{\number\@dtl@bar}% +} +% \end{macrocode} +% Draw $x$ axis +% \begin{macrocode} +\ifDTLbarxaxis + \ifDTLverticalbars + \expandafter\draw\expandafter[\DTLBarXAxisStyle] + (0,0) -- (\DTLbarchartwidth,0); + \else + \expandafter\draw\expandafter[\DTLBarXAxisStyle] + (0,0) -- (0,\DTLbarchartwidth); + \fi +\fi +% \end{macrocode} +% Draw $y$ axis +% \begin{macrocode} +\ifDTLbaryaxis + \ifDTLverticalbars + \expandafter\draw\expandafter[\DTLBarYAxisStyle] + (0,\DTLnegextent) -- (0,\DTLbarmax); + \else + \expandafter\draw\expandafter[\DTLBarYAxisStyle] + (\DTLnegextent,0) -- (\DTLbarmax,0); + \fi +\fi +% \end{macrocode} +% Plot $y$ tick marks if required +% \begin{macrocode} +\ifx\dtlbar@yticlist\relax +\else + \@for\dtl@thistick:=\dtlbar@yticlist\do{% + \ifDTLverticalbars + \pgfpathmoveto{\pgfpointxy{0}{\dtl@thistick}} + \pgfpathlineto{ + \pgfpointadd{\pgfpointxy{0}{\dtl@thistick}} + {\pgfpoint{-\DTLticklength}{0pt}}} + \else + \pgfpathmoveto{\pgfpointxy{\dtl@thistick}{0}} + \pgfpathlineto{ + \pgfpointadd{\pgfpointxy{\dtl@thistick}{0}} + {\pgfpoint{0pt}{-\DTLticklength}}} + \fi + \pgfusepath{stroke} + \ifx\dtlbar@yticlabels\relax + \FPround{\dtl@thislabel}{\dtl@thistick} + {\c@DTLbarroundvar}% + \else + \dtl@chopfirst\dtlbar@yticlabels\dtl@thislabel\dtl@rest + \let\dtlbar@yticlabels=\dtl@rest + \fi + \ifDTLverticalbars + \edef\dtl@textopt{\DTLbarYticklabelalign,% + at={\noexpand\pgfpointadd + {\noexpand\pgfpointxy{0}{\dtl@thistick}} + {\noexpand\pgfpoint{-\noexpand\DTLticklabeloffset}{0pt}}, + }}% + \else + \edef\dtl@textopt{\DTLbarYticklabelalign, + at={\noexpand\pgfpointadd + {\noexpand\pgfpointxy{\dtl@thistick}{0}} + {\noexpand\pgfpoint{0pt}{-\noexpand\DTLticklabeloffset}} + }}% + \fi + \expandafter\pgftext\expandafter[\dtl@textopt]{% + \DTLbardisplayYticklabel{\dtl@thislabel}} + }% +\fi +% \end{macrocode} +% Plot the $y$ label if required +% \begin{macrocode} +\ifx\dtlbar@ylabel\relax +\else + \addtolength{\dtl@yticlabelwidth}{\baselineskip}% + \setlength{\dtl@tmplength}{0.5\DTLbarchartlength} + \ifDTLverticalbars + \pgftext[bottom,center,at={\pgfpointadd + {\pgfpointxy{0}{\DTLnegextent}}% + {\pgfpoint{-\dtl@yticlabelwidth}{\dtl@tmplength}}}, + rotate=90]{% + \dtlbar@ylabel} + \else + \pgftext[bottom,center,at={\pgfpointadd + {\pgfpointxy{\DTLnegextent}{0}}% + {\pgfpoint{\dtl@tmplength}{-\dtl@yticlabelwidth}}}]{% + \dtlbar@ylabel} + \fi +\fi +% \end{macrocode} +% Finish bar chart +% \begin{macrocode} +\DTLbaratendtikz +\end{tikzpicture} +\fi +}} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLmultibarchart} +%\begin{definition} +% \cs{DTLmultibarchart}\oarg{conditions}\marg{option list}\marg{db name}\marg{assign list} +%\end{definition} +% Make a multi-bar chart from data given in data base \meta{db name}, +% where \meta{assign list} is a comma-separated list of +% \meta{cmd}\texttt{=}\meta{key} pairs. \meta{option list} must +% include the \texttt{variables} key which must be a comma separated +% list of commands, where each command +% is included in \meta{assign list}. The optional argument +% \meta{conditions} is the same as that for \cs{DTLforeach}. +% \begin{macrocode} +\newcommand*{\DTLmultibarchart}[4][\boolean{true}]{% +{\let\dtlbar@variables=\relax +\let\DTLbarmax=\relax +\let\DTLnegextent=\relax +\disable@keys{databar}{variable,upperbarlabel}% +\setkeys{databar}{#2}% +\ifx\dtlbar@variables\relax + \PackageError{databar}{\string\DTLmultibarchart\space missing variables setting}{}% +\else +% \end{macrocode} +% Compute the maximum bar height, unless \cs{DTLbarmax} has been +% set. +%\changes{1.01}{2007 Aug 17}{uses \cs{@sDTLforeach} instead of +%\cs{DTLforeach}} +% \begin{macrocode} + \ifx\DTLbarmax\relax + \@sDTLforeach[#1]{#3}{#4}{% + \@for\DTLbarvariable:=\dtlbar@variables\do{% + \expandafter\DTLconverttodecimal\expandafter + {\DTLbarvariable}{\dtl@barvar}% + \ifx\DTLbarmax\relax + \let\DTLbarmax=\dtl@barvar + \else + \let\dtl@old=\DTLbarmax + \FPmax{\DTLbarmax}{\dtl@old}{\dtl@barvar}% + \fi + }% + }% + \ifx\dtlbar@yticgap\relax + \else + \let\dtl@thistick=\dtlbar@yticgap% + \whiledo{\DTLisFPopenbetween{\dtl@thistick}{0}{\DTLbarmax}}{% + \FPadd{\dtl@thistick}{\dtl@thistick}{\dtlbar@yticgap}% + }% + \let\DTLbarmax=\dtl@thistick + \fi + \fi +% \end{macrocode} +% Compute the bar depth, unless \cs{DTLnegextent} has been +% set. +% \begin{macrocode} + \ifx\DTLnegextent\relax + \def\DTLnegextent{0}% + \@sDTLforeach[#1]{#3}{#4}{% + \@for\DTLbarvariable:=\dtlbar@variables\do{% + \expandafter\DTLconverttodecimal\expandafter + {\DTLbarvariable}{\dtl@barvar}% + \let\dtl@old=\DTLnegextent + \DTLmin{\DTLnegextent}{\dtl@old}{\dtl@barvar}% + }% + }% + \ifx\dtlbar@yticgap\relax + \else + \ifthenelse{\DTLisFPlt{\DTLnegextent}{0}}{% + \edef\dtl@thistick{0}% + \whiledo{\DTLisFPclosedbetween{\dtl@thistick}{\DTLnegextent}{0}}{% + \FPsub{\dtl@thistick}{\dtl@thistick}{\dtlbar@yticgap}% + }% + \let\DTLnegextent=\dtl@thistick + }{}% + \fi + \fi +% \end{macrocode} +% Determine scaling factor +% \begin{macrocode} + \@dtl@tmpcount=\DTLbarchartlength + \FPsub{\dtl@extent}{\DTLbarmax}{\DTLnegextent}% + \FPdiv{\dtl@unit}{\number\@dtl@tmpcount}{\dtl@extent}% +% \end{macrocode} +% Construct $y$ tick list if required +% \begin{macrocode} + \setlength{\dtl@yticlabelwidth}{0pt}% + \ifDTLbarytics + \ifx\dtlbar@yticlist\relax + \ifx\dtlbar@yticgap\relax + \dtl@constructticklist\DTLnegextent\DTLbarmax + \dtl@unit\dtlbar@yticlist + \else + \dtl@constructticklistwithgapz + \DTLnegextent\DTLbarmax\dtlbar@yticlist\dtlbar@yticgap + \fi + \fi + \ifx\dtlbar@ylabel\relax + \else + \ifx\dtlbar@yticlabels\relax + \@for\dtl@thislabel:=\dtlbar@yticlist\do{% + \FPround{\dtl@thislabel}{\dtl@thislabel} + {\c@DTLbarroundvar}% + \ifDTLverticalbars + \settowidth{\dtl@tmplength}{% + \DTLbardisplayYticklabel{\dtl@thislabel}}% + \else + \settoheight{\dtl@tmplength}{% + \DTLbardisplayYticklabel{\dtl@thislabel}}% + \edef\@dtl@h{\the\dtl@tmplength}% + \settodepth{\dtl@tmplength}{% + \DTLbardisplayYticklabel{\dtl@thislabel}}% + \addtolength{\dtl@tmplength}{\@dtl@h}% + \addtolength{\dtl@tmplength}{\baselineskip}% + \fi + \ifdim\dtl@tmplength>\dtl@yticlabelwidth + \setlength{\dtl@yticlabelwidth}{\dtl@tmplength}% + \fi + }% + \else + \@for\dtl@thislabel:=\dtlbar@yticlabels\do{% + \ifDTLverticalbars + \settowidth{\dtl@tmplength}{% + \DTLbardisplayYticklabel{\dtl@thislabel}}% + \else + \settoheight{\dtl@tmplength}{% + \DTLbardisplayYticklabel{\dtl@thislabel}}% + \edef\@dtl@h{\the\dtl@tmplength}% + \settodepth{\dtl@tmplength}{% + \DTLbardisplayYticklabel{\dtl@thislabel}}% + \addtolength{\dtl@tmplength}{\@dtl@h}% + \addtolength{\dtl@tmplength}{\baselineskip}% + \fi + \ifdim\dtl@tmplength>\dtl@yticlabelwidth + \setlength{\dtl@yticlabelwidth}{\dtl@tmplength}% + \fi + }% + \fi + \fi + \fi +% \end{macrocode} +% Calculate the offset for the lower label and number of labels +% \begin{macrocode} +\dtl@xticlabelheight=0pt\relax +\@dtl@tmpcount=0\relax +\@for\dtl@thislabel:=\dtl@multibarlabels\do{% + \advance\@dtl@tmpcount by 1\relax + \settoheight{\dtl@tmplength}{\tikz\expandafter\pgftext\expandafter + [\DTLbarXlabelalign]{\DTLdisplaylowerbarlabel{\dtl@thislabel}};}% + \edef\@dtl@h{\the\dtl@tmplength}% + \settodepth{\dtl@tmplength}{\tikz\expandafter\pgftext\expandafter + [\DTLbarXlabelalign]{\DTLdisplaylowerbarlabel{\dtl@thislabel}};}% + \addtolength{\dtl@tmplength}{\@dtl@h}% + \addtolength{\dtl@tmplength}{\baselineskip}% + \ifdim\dtl@tmplength>\dtl@xticlabelheight + \setlength{\dtl@xticlabelheight}{\dtl@tmplength}% + \fi +} +% \end{macrocode} +% Calculate number of bars per group +% \begin{macrocode} +\@dtl@tmpcount=0\relax +\@for\dtl@this:=\dtlbar@variables\do{% + \advance\@dtl@tmpcount by 1\relax +}% +\edef\DTLbargroupwidth{\number\@dtl@tmpcount}% +% \end{macrocode} +% Compute the total width of the bar chart (in terms of +% the $x$ unit vector.) +% \begin{macrocode} +\edef\dtl@n{\expandafter\number\csname dtlrows@#3\endcsname} +\FPmul{\dtl@tmpi}{\dtl@n}{\DTLbargroupwidth} +\FPsub{\dtl@tmpii}{\dtl@n}{1}% +\FPmul{\dtl@tmpii}{\dtl@tmpii}{\dtlbar@groupgap}% +\FPadd{\DTLbarchartwidth}{\dtl@tmpi}{\dtl@tmpii} +% \end{macrocode} +% Do the bar chart +% \begin{macrocode} +\begin{tikzpicture} +% \end{macrocode} +% Set unit vectors +% \begin{macrocode} +\ifDTLverticalbars + \pgfsetyvec{\pgfpoint{0pt}{\dtl@unit sp}}% + \pgfsetxvec{\pgfpoint{\DTLbarwidth}{0pt}}% +\else + \pgfsetxvec{\pgfpoint{\dtl@unit sp}{0pt}}% + \pgfsetyvec{\pgfpoint{0pt}{\DTLbarwidth}}% +\fi +% \end{macrocode} +% Begin hook +% \begin{macrocode} +\DTLbaratbegintikz +% \end{macrocode} +% Initialise +% \begin{macrocode} +\def\@dtl@start{0}% +% \end{macrocode} +% Iterate through data +% \begin{macrocode} +\@sDTLforeach[#1]{#3}{#4}{% +% \end{macrocode} +% Store the bar number in \cs{@dtl@bar} +% \begin{macrocode} +\@dtl@barcount = 1\relax +% \end{macrocode} +% Set the multibar label lists +% \begin{macrocode} +\let\dtl@multibar@labels=\dtl@multibarlabels +\let\dtl@uppermultibar@labels=\dtl@uppermultibarlabels +% \end{macrocode} +% Compute mid point over group +% \begin{macrocode} +\FPmul{\dtl@multimidpt}{\DTLbargroupwidth}{0.5}% +\FPadd{\dtl@multimidpt}{\dtl@multimidpt}{\@dtl@start}% +% \end{macrocode} +% Iterate through each variable +% \begin{macrocode} +\@for\DTLbarvariable:=\dtlbar@variables\do{% +% \end{macrocode} +% Set end point +% \begin{macrocode} +\FPadd{\@dtl@endpt}{\@dtl@start}{1}% +% \end{macrocode} +% Convert variable to decimal +% \begin{macrocode} +\expandafter\DTLconverttodecimal\expandafter + {\DTLbarvariable}{\dtl@variable}% +% \end{macrocode} +% Get the current lower label: +% \begin{macrocode} +\dtl@chopfirst\dtl@multibar@labels\dtl@thisbarlabel\dtl@rest +\let\dtl@multibar@labels=\dtl@rest +% \end{macrocode} +% Get the current upper label: +% \begin{macrocode} +\dtl@chopfirst\dtl@uppermultibar@labels\dtl@thisupperbarlabel\dtl@rest +\let\dtl@uppermultibar@labels=\dtl@rest +% \end{macrocode} +% Draw bars +% \begin{macrocode} +\begin{scope} + \expandafter\color\expandafter{\DTLgetbarcolor{\@dtl@barcount}}% + \ifDTLverticalbars + \fill (\@dtl@start,0) -- (\@dtl@start,\dtl@variable) + -- (\@dtl@endpt,\dtl@variable) -- (\@dtl@endpt,0) -- cycle; + \else + \fill (0,\@dtl@start) -- (\dtl@variable,\@dtl@start) + -- (\dtl@variable,\@dtl@endpt) -- (0,\@dtl@endpt) -- cycle; + \fi +\end{scope} +% \end{macrocode} +% Draw outline +% \begin{macrocode} +\begin{scope} +\ifdim\DTLbaroutlinewidth>0pt + \expandafter\color\expandafter{\DTLbaroutlinecolor} + \ifDTLverticalbars + \draw (\@dtl@start,0) -- (\@dtl@start,\dtl@variable) + -- (\@dtl@endpt,\dtl@variable) -- (\@dtl@endpt,0) -- cycle; + \else + \draw (0,\@dtl@start) -- (\dtl@variable,\@dtl@start) + -- (\dtl@variable,\@dtl@endpt) -- (0,\@dtl@endpt) -- cycle; + \fi +\fi +\end{scope} +% \end{macrocode} +% Calculate mid point +% \begin{macrocode} +\FPadd{\@dtl@midpt}{\@dtl@start}{0.5}% +% \end{macrocode} +% Draw lower $x$ labels +% \begin{macrocode} +\ifDTLverticalbars + \edef\dtl@textopt{% + at={\noexpand\pgfpointadd + {\noexpand\pgfpointxy{\@dtl@midpt}{0}} + {\noexpand\pgfpoint{0pt}{-\noexpand\DTLbarlabeloffset}}}, + \DTLbarXlabelalign + }% +\else + \edef\dtl@textopt{% + at={\noexpand\pgfpointadd + {\noexpand\pgfpointxy{0}{\@dtl@midpt}} + {\noexpand\pgfpoint{-\noexpand\DTLbarlabeloffset}{0pt}}}, + \DTLbarXlabelalign + }% +\fi + \expandafter\pgftext\expandafter[\dtl@textopt]{% + \DTLdisplaylowermultibarlabel{\dtl@thisbarlabel}} +% \end{macrocode} +% Draw upper $x$ labels +% \begin{macrocode} +\ifDTLverticalbars + \expandafter\DTLifnumlt\expandafter{\DTLbarvariable}{0} + { + \edef\dtl@textopt{% + at={\noexpand\pgfpointadd + {\noexpand\pgfpointxy{\@dtl@midpt}{\dtl@variable}} + {\noexpand\pgfpoint{0pt}{-\noexpand\DTLbarlabeloffset}}} + }% + }{% + \edef\dtl@textopt{% + at={\noexpand\pgfpointadd + {\noexpand\pgfpointxy{\@dtl@midpt}{\dtl@variable}} + {\noexpand\pgfpoint{0pt}{\noexpand\DTLbarlabeloffset}}} + }% + } +\else + \expandafter\DTLifnumlt\expandafter{\DTLbarvariable}{0} + { + \edef\dtl@textopt{right, + at={\noexpand\pgfpointadd + {\noexpand\pgfpointxy{\dtl@variable}{\@dtl@midpt}} + {\noexpand\pgfpoint{-\noexpand\DTLbarlabeloffset}{0pt}}} + }% + }{% + \edef\dtl@textopt{left, + at={\noexpand\pgfpointadd + {\noexpand\pgfpointxy{\dtl@variable}{\@dtl@midpt}} + {\noexpand\pgfpoint{\noexpand\DTLbarlabeloffset}{0pt}}} + }% + } +\fi + \expandafter\pgftext\expandafter[\dtl@textopt]{% + \DTLdisplayuppermultibarlabel{\dtl@thisupperbarlabel}} +% \end{macrocode} +% End of loop increment loop variables +% \begin{macrocode} + \FPadd{\@dtl@start}{\@dtl@start}{1}% + \advance\@dtl@barcount by 1\relax +}% +% Draw lower group $x$ labels +% \begin{macrocode} +\setlength{\dtl@tmplength}{\DTLbarlabeloffset}% +\addtolength{\dtl@tmplength}{\dtl@xticlabelheight}% +\ifDTLverticalbars + \edef\dtl@textopt{% + at={\noexpand\pgfpointadd + {\noexpand\pgfpointxy{\dtl@multimidpt}{0}} + {\noexpand\pgfpoint{0pt}{-\noexpand\dtl@tmplength}}}, + \DTLbarXlabelalign + }% +\else + \edef\dtl@textopt{% + at={\noexpand\pgfpointadd + {\noexpand\pgfpointxy{0}{\dtl@multimidpt}} + {\noexpand\pgfpoint{-\noexpand\dtl@tmplength}{0pt}}}, + \DTLbarXlabelalign + }% +\fi + \expandafter\pgftext\expandafter[\dtl@textopt]{% + \DTLdisplaylowerbarlabel{\dtl@barlabel}} +% \end{macrocode} +% Increment starting position by \cs{dtlbar@groupgap} +% \begin{macrocode} + \FPadd{\@dtl@start}{\@dtl@start}{\dtlbar@groupgap}% +} +% \end{macrocode} +% Draw $x$ axis +% \begin{macrocode} +\ifDTLbarxaxis + \ifDTLverticalbars + \expandafter\draw\expandafter[\DTLBarXAxisStyle] + (0,0) -- (\DTLbarchartwidth,0); + \else + \expandafter\draw\expandafter[\DTLBarXAxisStyle] + (0,0) -- (0,\DTLbarchartwidth); + \fi +\fi +% \end{macrocode} +% Draw $y$ axis +% \begin{macrocode} +\ifDTLbaryaxis + \ifDTLverticalbars + \expandafter\draw\expandafter[\DTLBarYAxisStyle] + (0,\DTLnegextent) -- (0,\DTLbarmax); + \else + \expandafter\draw\expandafter[\DTLBarYAxisStyle] + (\DTLnegextent,0) -- (\DTLbarmax,0); + \fi +\fi +% \end{macrocode} +% Plot $y$ tick marks if required +% \begin{macrocode} +\ifx\dtlbar@yticlist\relax +\else + \@for\dtl@thistick:=\dtlbar@yticlist\do{% + \ifDTLverticalbars + \pgfpathmoveto{\pgfpointxy{0}{\dtl@thistick}} + \pgfpathlineto{ + \pgfpointadd{\pgfpointxy{0}{\dtl@thistick}} + {\pgfpoint{-\DTLticklength}{0pt}}} + \else + \pgfpathmoveto{\pgfpointxy{\dtl@thistick}{0}} + \pgfpathlineto{ + \pgfpointadd{\pgfpointxy{\dtl@thistick}{0}} + {\pgfpoint{0pt}{-\DTLticklength}}} + \fi + \pgfusepath{stroke} + \ifx\dtlbar@yticlabels\relax + \FPround{\dtl@thislabel}{\dtl@thistick} + {\c@DTLbarroundvar}% + \else + \dtl@chopfirst\dtlbar@yticlabels\dtl@thislabel\dtl@rest + \let\dtlbar@yticlabels=\dtl@rest + \fi + \ifDTLverticalbars + \edef\dtl@textopt{\DTLbarYticklabelalign,% + at={\noexpand\pgfpointadd + {\noexpand\pgfpointxy{0}{\dtl@thistick}} + {\noexpand\pgfpoint{-\noexpand\DTLticklabeloffset}{0pt}}, + }}% + \else + \edef\dtl@textopt{\DTLbarYticklabelalign, + at={\noexpand\pgfpointadd + {\noexpand\pgfpointxy{\dtl@thistick}{0}} + {\noexpand\pgfpoint{0pt}{-\noexpand\DTLticklabeloffset}} + }}% + \fi + \expandafter\pgftext\expandafter[\dtl@textopt]{% + \DTLbardisplayYticklabel{\dtl@thislabel}} + }% +\fi +% \end{macrocode} +% Plot the $y$ label if required +% \begin{macrocode} +\ifx\dtlbar@ylabel\relax +\else + \addtolength{\dtl@yticlabelwidth}{\baselineskip}% + \setlength{\dtl@tmplength}{0.5\DTLbarchartlength} + \ifDTLverticalbars + \pgftext[bottom,center,at={\pgfpointadd + {\pgfpointxy{0}{\DTLnegextent}}% + {\pgfpoint{-\dtl@yticlabelwidth}{\dtl@tmplength}}}, + rotate=90]{% + \dtlbar@ylabel} + \else + \pgftext[bottom,center,at={\pgfpointadd + {\pgfpointxy{\DTLnegextent}{0}}% + {\pgfpoint{\dtl@tmplength}{-\dtl@yticlabelwidth}}}]{% + \dtlbar@ylabel} + \fi +\fi +% \end{macrocode} +% Finish bar chart +% \begin{macrocode} +\DTLbaratendtikz +\end{tikzpicture} +\fi +}} +% \end{macrocode} +%\end{macro} +%\iffalse +% \begin{macrocode} +%</databar.sty> +% \end{macrocode} +%\fi +%\iffalse +% \begin{macrocode} +%<*databib.sty> +% \end{macrocode} +%\fi +%\section{databib.sty} +%\label{sec:src:databib} +%\subsection{Package Declaration} +% \begin{macrocode} +\NeedsTeXFormat{LaTeX2e} +\ProvidesPackage{databib}[2007/08/17 v1.0 (NLCT)] +% \end{macrocode} +% Load required packages: +% \begin{macrocode} +\RequirePackage{datatool} +% \end{macrocode} +%\subsection{Package Options} +%\begin{macro}{\dtlbib@style} +%The default bib style is stored in \cs{dtlbib@style}. +% \begin{macrocode} +\newcommand*{\dtlbib@style}{plain} +% \end{macrocode} +%\end{macro} +% The \pkgopt[databib]{style} package option sets \cs{dtlbib@style}. +% \begin{macrocode} +\define@choicekey{databib.sty}{style}{plain,abbrv,alpha}{% +\def\dtlbib@style{#1}} +% \end{macrocode} +% Process package options: +% \begin{macrocode} +\ProcessOptionsX +% \end{macrocode} +%\subsection{Loading BBL file} +%\begin{macro}{\DTLloadbbl} +%\begin{definition} +%\cs{DTLloadbib}\oarg{bbl file}\marg{db name}\marg{bib list} +%\end{definition} +% \begin{macrocode} +\newcommand*{\DTLloadbbl}[3][\jobname.bbl]{% +\bibliographystyle{databib}% +\if@filesw + \immediate\write\@auxout{\string\bibdata{#3}}% +\fi +\DTLnewdb{#2}% +\edef\DTLBIBdbname{#2}% +\@input@{#1}} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLnewbibrow} +% \cs{DTLnewbibrow} adds a new row to the bibliography database. +% (\cs{DTLBIBdbname} must be set prior to use to the name +% of the \sty{datatool} database.) +% \begin{macrocode} +\newcommand*{\DTLnewbibrow}{\DTLnewrow{\DTLBIBdbname}} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLnewbibitem} +%\begin{definition} +%\cs{DTLnewbibitem}\marg{key}\marg{value} +%\end{definition} +% Adds a new database entry with the given key and value. +% \begin{macrocode} +\newcommand*{\DTLnewbibitem}[2]{% +\DTLnewdbentry{\DTLBIBdbname}{#1}{#2}} +% \end{macrocode} +%\end{macro} +%\subsection{Predefined text} +%\label{sec:src:bibnames} +%\begin{macro}{\andname} +% \begin{macrocode} +\providecommand*{\andname}{and} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\ofname} +% \begin{macrocode} +\providecommand*{\ofname}{of} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\inname} +% \begin{macrocode} +\providecommand*{\inname}{in} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\etalname} +% \begin{macrocode} +\providecommand*{\etalname}{et al.} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\editorname} +% \begin{macrocode} +\providecommand*{\editorname}{editor} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\editorsname} +% \begin{macrocode} +\providecommand*{\editorsname}{editors} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\volumename} +% \begin{macrocode} +\providecommand*{\volumename}{volume} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\numbername} +% \begin{macrocode} +\providecommand*{\numbername}{number} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\pagesname} +% \begin{macrocode} +\providecommand*{\pagesname}{pages} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\pagename} +% \begin{macrocode} +\providecommand*{\pagename}{page} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\editionname} +% \begin{macrocode} +\providecommand*{\editionname}{edition} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\techreportname} +% \begin{macrocode} +\providecommand*{\techreportname}{Technical report} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\mscthesisname} +% \begin{macrocode} +\providecommand*{\mscthesisname}{Master's thesis} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\phdthesisname} +% \begin{macrocode} +\providecommand*{\phdthesisname}{PhD thesis} +% \end{macrocode} +%\end{macro} +% +% +%\subsection{Displaying the bibliography} +%\label{sec:src:displaybib} +%\begin{definition} +%\cs{DTLbibliography}\marg{bib dbname} +%\end{definition} +% Displays the bibliography for the database \meta{bib dbname} +% which must have previously been loaded using +% \cs{DTLloadbbl}. +%\begin{macro}{\DTLbibliography} +% \begin{macrocode} +\newcommand*{\DTLbibliography}[2][\boolean{true}]{% +\begin{DTLthebibliography}[#1]{#2}% +\DTLforeachbibentry[#1]{#2}{% +\DTLbibitem \DTLformatbibentry \DTLendbibitem +}% +\end{DTLthebibliography}% +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLformatbibentry} +%\begin{definition} +%\cs{DTLformatbibentry} +%\end{definition} +% Formats the current bib entry. +% \begin{macrocode} +\newcommand*{\DTLformatbibentry}{% +\@ifundefined{DTLformat\DBIBentrytype}{% +\PackageError{databib}{Don't know how to format bibliography entries +of type `\DBIBentrytype'}{}}{% +\dtl@message{[\DBIBcitekey]}% +\DTLstartsentencefalse\DTLmidsentencefalse\DTLperiodfalse +\csname DTLformat\DBIBentrytype\endcsname}% +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLendbibitem} +% Hook to add extra information at the end of a bibliography item. +% This does nothing by default. +% \begin{macrocode} +\newcommand*{\DTLendbibitem}{} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLwidest} +%Define a length to store the widest bib entry label +% \begin{macrocode} +\newlength\dtl@widest +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLcomputewidestbibentry} +%\begin{definition} +%\cs{DTLcomputewidestbibentry}\marg{conditions}\marg{db +%name}\marg{bib label}\marg{cmd} +%\end{definition} +%Computes the widest bibliography entry over all entries satisfying +%\meta{condition} for the database called \meta{db name}, where +% the bibliography label is formated according to \meta{bib label} and +% stores the result in \meta{cmd} which must be a command name. +% \begin{macrocode} +\newcommand*{\DTLcomputewidestbibentry}[4]{% +\dtl@widest=0pt\relax +\let#4=\@empty +\DTLforeachbibentry[#1]{#2}{% +\settowidth{\dtl@tmplength}{#3}% +\ifdim\dtl@tmplength>\dtl@widest\relax + \dtl@widest=\dtl@tmplength + \protected@edef#4{#3}% +\fi +}% +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLforeachbibentry} +%\begin{definition} +%\cs{DTLforeachbibentry}\oarg{condition}\marg{db name}\marg{text} +%\end{definition} +%\begin{definition} +%\cs{DTLforeachbibentry*}\oarg{condition}\marg{db name}\marg{text} +%\end{definition} +% Iterates through the database called \meta{db name} and does +% \meta{text} if \meta{condition} is met. As with +% \cs{DTLforeach}, the starred version is read only. +% \begin{macrocode} +\newcommand*{\DTLforeachbibentry}{% +\@ifstar\@DTLforeachbibentry\@DTLforeachbibentry} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\@DTLforeachbibentry} +% Unstarred version +% \begin{macrocode} +\newcommand*{\@DTLforeachbibentry}[3][\boolean{true}]{% +\edef\DBIBname{#2}\setcounter{DTLbibrow}{0}% +\@DTLforeach{#2}{\DBIBcitekey=CiteKey,\DBIBentrytype +=EntryType}{\dtl@gathervalues{#2}{\@dtl@currentrow}% +\ifthenelse{#1}{\refstepcounter{DTLbibrow}#3}{}}} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\@sDTLforeachbibentry} +% Starred version +% \begin{macrocode} +\newcommand*{\@sDTLforeachbibentry}[3][\boolean{true}]{% +\edef\DBIBname{#2}\setcounter{DTLbibrow}{0}% +\@sDTLforeach{#2}{\DBIBcitekey=CiteKey,\DBIBentrytype +=EntryType}{\dtl@gathervalues{#2}{\@dtl@currentrow}% +\ifthenelse{#1}{\refstepcounter{DTLbibrow}#3}{}}} +% \end{macrocode} +%\end{macro} +% +%The counter \counterfmt{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 +% conditions to the optional argument of \cs{DTLforeach}, but +% instead uses \cs{ifthenelse}, which means that \counterfmt{DTLrowi} +% etc will be incremented, even when the given condition is not met.) +% \begin{macrocode} +\newcounter{DTLbibrow} +% \end{macrocode} +% Keep \sty{hyperref} happy: +% \begin{macrocode} +\def\theHDTLbibrow{\theHDTLrow.bib.\arabic{DTLbibrow}}% +% \end{macrocode} +% +%\begin{macro}{\DTLbibfield} +%\begin{definition} +%\cs{DTLbibfield}\marg{field name} +%\end{definition} +% Gets the value assigned to the field \meta{field name} for +% the current row of \cs{DTLforeachbibentry}. (Doesn't check if +% the field exists, or if it is being used within +% \cs{DTLforeachbibentry}.) +% \begin{macrocode} +\newcommand*{\DTLbibfield}[1]{\csname @dtl@key@#1\endcsname} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLifbibfieldexists} +%\begin{definition} +%\cs{DTLifbibfieldexists}\marg{field name}\marg{true part}\marg{false +%part} +%\end{definition} +%Determines whether the given field name exists for the current +% row of \cs{DTLforeachbibentry}. +% \begin{macrocode} +\newcommand*{\DTLifbibfieldexists}[3]{% +\@ifundefined{@dtl@key@#1}{#3}{% +\expandafter\DTLifnull\csname @dtl@key@#1\endcsname +{#3}{#2}}} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLifanybibfieldexists} +%\begin{definition} +%\cs{DTLifanybibfieldexists}\marg{list of field name}\marg{true part}\marg{false +%part} +%\end{definition} +% Determines whether any of the listed fields exist for the current +% row of \cs{DTLforeachbibentry}. +% \begin{macrocode} +\newcommand*{\DTLifanybibfieldexists}[3]{% +\@for\dtl@thisfield:=#1\do{% +\@ifundefined{@dtl@key@\dtl@thisfield}{}{% +\expandafter\DTLifnull\csname @dtl@key@\dtl@thisfield\endcsname +{}{% +\@endfortrue}}}% +\if@endfor + #2% +\else + #3% +\fi +\@endforfalse +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\ifDTLperiod} +% The conditional \cs{ifDTLperiod} is used to keep track of any +% abbreviations ending with a period, this is to ensure that +% abbreviations aren't followed by a full stop if they already +% have a full stop terminating the abbreviation. +% \begin{macrocode} +\newif\ifDTLperiod +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLcheckendsperiod} +%\begin{definition} +%\cs{DTLcheckendperiod}\marg{string} +%\end{definition} +% Checks if \meta{string} ends with a full stop. This sets +% \cs{ifDTLperiod}. +% \begin{macrocode} +\newcommand*{\DTLcheckendsperiod}[1]{% +\dtl@checkendsperiod#1\@nil\relax} +% \end{macrocode} +% \begin{macrocode} +\def\dtl@checkendsperiod#1#2{% +\def\@dtl@argi{#1}\def\@dtl@argii{#2}% +\def\@dtl@period{.}% +\ifx\@dtl@argi\@nnil + \global\DTLperiodfalse + \let\@dtl@donext=\relax +\else + \ifx\@dtl@argii\@nnil + \ifx\@dtl@argi\@dtl@period + \global\DTLperiodtrue + \else + \global\DTLperiodfalse + \fi + \let\@dtl@donext=\@gobble + \else + \let\@dtl@donext=\dtl@checkendsperiod + \fi +\fi +\@dtl@donext{#2}% +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLcheckbibfieldendsperiod} +%\begin{definition} +%\cs{DTLcheckbibfieldendperiod}\marg{label} +%\end{definition} +% Checks if the bib field \meta{label} ends with a full stop. +% This sets \cs{ifDTLperiod}. +% \begin{macrocode} +\newcommand*{\DTLcheckbibfieldendsperiod}[1]{% +\protected@edef\@dtl@tmp{\DTLbibfield{#1}}% +\expandafter\DTLcheckendsperiod\expandafter{\@dtl@tmp}} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\ifDTLmidsentence} +%\begin{definition} +%\cs{ifDTLmidsentence} +%\end{definition} +% Determine whether we are in the middle +% of a sentence. +% \begin{macrocode} +\newif\ifDTLmidsentence +% \end{macrocode} +%\end{macro} +%\begin{macro}{\ifDTLstartsentence} +%\begin{definition} +%\cs{ifDTLstartsentence} +%\end{definition} +% Determine whether we are at the start +% of a sentence. +% \begin{macrocode} +\newif\ifDTLstartsentence +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLaddperiod} +%\begin{definition} +%\cs{DTLaddperiod} +%\end{definition} +%Adds a full stop and sets \cs{DTLmidsentencefalse}, +%\cs{DTLstartsentencetrue} and +%\cs{DTLperiodfalse}. +% \begin{macrocode} +\newcommand*{\DTLaddperiod}{\DTLmidsentencefalse\DTLperiodfalse +\DTLstartsentencetrue +\ifDTLperiod\else.\fi} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLaddcomma} +%\begin{definition} +%\cs{DTLaddcomma} +%\end{definition} +%Adds a comma and sets \cs{DTLmidsentencetrue}, \cs{DTLperiodfalse} +%and \cs{DTLstartsentencefalse} +% \begin{macrocode} +\newcommand*{\DTLaddcomma}{, \DTLmidsentencetrue +\DTLperiodfalse\DTLstartsentencefalse} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLstartsentencespace} +%Adds a space if at the start of the sentence, otherwise does +% nothing. (The space between sentences is added this way, rather +% than in \cs{DTLaddperiod} otherwise spurious extra space can +% occur at the end of the bib item. The spacefactor needs to be +% set manually, because there's stuff in the way of the previous +% sentence's full stop and this space which confuses the inter +% sentence spacing (and, of course, the previous sentence could +% have ended with a capital letter.) +% \begin{macrocode} +\newcommand*{\DTLstartsentencespace}{% +\ifDTLstartsentence\spacefactor=\sfcode`\.\relax\space +\fi\DTLstartsentencefalse} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLtwoand} +% In a list of only two author (or editor) names, the text between the +% two names is given by \cs{DTLtwoand}: +% \begin{macrocode} +\newcommand*{\DTLtwoand}{\ \andname\ } +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLandlast} +% In a list of author (or editor) names, the text between the +% penultimate and last name is given by \cs{DTLandlast}: +% \begin{macrocode} +\newcommand*{\DTLandlast}{, \andname\ } +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLandnotlast} +% In a list of author (or editor) names, the text between the +% names (except the penultimate and last name) is given by +% \cs{DTLandnotlast}: +% \begin{macrocode} +\newcommand*{\DTLandnotlast}{, } +% \end{macrocode} +%\end{macro} +%\begin{macro}{\dtl@authorcount} +% Define a count register to keep track of the number of authors: +% \begin{macrocode} +\newcount\@dtl@authorcount +% \end{macrocode} +%\end{macro} +% The counter \counterfmt{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} +%\begin{macro}{\DTLformatauthorlist} +% Format a list of author names (the list is stored in +% \cs{@dtl@key@Author}): +% \begin{macrocode} +\newcommand*{\DTLformatauthorlist}{% +\DTLifbibfieldexists{Author}{% +\DTLstartsentencespace +\@dtl@authorcount=0\relax +\@for\@dtl@author:=\@dtl@key@Author\do{% +\advance\@dtl@authorcount by 1\relax}% +\@dtl@tmpcount=0\relax +\ifnum\@dtl@authorcount>\c@DTLmaxauthors +{% + \@for\@dtl@author:=\@dtl@key@Author\do{% + \advance\@dtl@tmpcount by 1\relax + \ifnum\@dtl@tmpcount=1\relax + \expandafter\DTLformatauthor\@dtl@author + \else + \ifnum\@dtl@tmpcount>\c@DTLmaxauthors + \DTLandnotlast \etalname + \expandafter\DTLcheckendsperiod\expandafter{\etalname}% + \@endfortrue + \else + \DTLandnotlast \expandafter\DTLformatauthor\@dtl@author + \fi + \fi + }% +}% +\else + \@for\@dtl@author:=\@dtl@key@Author\do{% + \advance\@dtl@tmpcount by 1\relax + \ifnum\@dtl@tmpcount=1\relax + \expandafter\DTLformatauthor\@dtl@author + \else + \ifnum\@dtl@tmpcount=\@dtl@authorcount + \ifnum\@dtl@authorcount=2\relax + \DTLtwoand + \else + \DTLandlast + \fi + \expandafter\DTLformatauthor\@dtl@author + \else + \DTLandnotlast \expandafter\DTLformatauthor\@dtl@author + \fi + \fi + }% +\fi +}{}% +} +% \end{macrocode} +%\end{macro} +% The counter \counterfmt{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} +% +%\begin{macro}{\DTLformateditorlist} +% Format a list of editor names (the list is stored in +% \cs{@dtl@key@Editor}): +% \begin{macrocode} +\newcommand*{\DTLformateditorlist}{% +\DTLifbibfieldexists{Editor}{% +\DTLstartsentencespace +\@dtl@authorcount=0\relax +\@for\@dtl@author:=\@dtl@key@Editor\do{% +\advance\@dtl@authorcount by 1\relax}% +\@dtl@tmpcount=0\relax +\ifnum\@dtl@authorcount>\c@DTLmaxeditors +{% + \@for\@dtl@author:=\@dtl@key@Editor\do{% + \advance\@dtl@tmpcount by 1\relax + \ifnum\@dtl@tmpcount=1\relax + \expandafter\DTLformateditor\@dtl@author + \else + \ifnum\@dtl@tmpcount>\c@DTLmaxeditors + \DTLandnotlast \etalname + \expandafter\DTLcheckendsperiod\expandafter{\etalname}% + \@endfortrue + \else + \DTLandnotlast \expandafter\DTLformateditor\@dtl@author + \fi + \fi + }% +}% +\else +\@for\@dtl@author:=\@dtl@key@Editor\do{% + \advance\@dtl@tmpcount by 1\relax + \ifnum\@dtl@tmpcount=1\relax + \expandafter\DTLformateditor\@dtl@author + \else + \ifnum\@dtl@tmpcount=\@dtl@authorcount + \ifnum\@dtl@authorcount=2\relax + \DTLtwoand + \else + \DTLandlast + \fi + \expandafter\DTLformateditor\@dtl@author + \else + \DTLandnotlast \expandafter\DTLformateditor\@dtl@author + \fi + \fi + }% +\fi +, +\ifnum\@dtl@authorcount=1\relax + \editorname + \expandafter\DTLcheckendsperiod\expandafter{\editorname}% +\else + \editorsname + \expandafter\DTLcheckendsperiod\expandafter{\editorsname}% +\fi +}{}% +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLformatsurnameonly} +%\begin{definition} +%\cs{DTLformatsurnameonly}\marg{von part}\marg{surname}\marg{jr +%part}\marg{forenames} +%\end{definition} +% This is used when only the surname should be displayed. (The +% final argument, \meta{forenames}, is ignored.) +% \begin{macrocode} +\newcommand*{\DTLformatsurnameonly}[4]{% +\DTLstartsentencespace +\def\@dtl@tmp{#1}% +\ifx\@dtl@tmp\@empty\else#1~\fi +#2% +\def\@dtl@tmp{#3}% +\ifx\@dtl@tmp\@empty + \DTLcheckendsperiod{#2}% +\else + , #3% + \DTLcheckendsperiod{#3}% +\fi +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLformatforenames} +%\begin{definition} +%\cs{DTLformatforenames}\marg{forenames} +%\end{definition} +% The format of an author/editor's forenames. If the forenames +% occur at the start of sentence, a new sentence space is added. +% The argument is checked to determine whether it ends with a +% full stop (sometimes the forenames may include initials.) +% \begin{macrocode} +\newcommand*{\DTLformatforenames}[1]{% +\DTLstartsentencespace +#1% +\DTLcheckendsperiod{#1}} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLformatabbrvforenames} +%\begin{definition} +%\cs{DTLformatabbrvforenames}\marg{forenames} +%\end{definition} +% The format of an author/editor's abbreviated forenames. The initials +% may or may not end in a full stop depending on the commands +% governing the format of \cs{DTLstoreinitials}, so the initials +% need to be check using \cs{DTLcheckendsperiod}. +% \begin{macrocode} +\newcommand*{\DTLformatabbrvforenames}[1]{% +\DTLstartsentencespace +\DTLstoreinitials{#1}{\@dtl@tmp}\@dtl@tmp +\expandafter\DTLcheckendsperiod\expandafter{\@dtl@tmp}} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLformatvon} +%\begin{definition} +%\cs{DTLformatvon}\marg{von part} +%\end{definition} +% The format of the ``von'' part. This does nothing if the argument +% is empty, otherwise it does the argument followed by a +% non-breakable space. +% \begin{macrocode} +\newcommand*{\DTLformatvon}[1]{% +\DTLstartsentencespace +\def\@dtl@tmp{#1}% +\ifx\@dtl@tmp\@empty +\else + #1~% +\fi +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLformatsurname} +%\begin{definition} +%\cs{DTLformatsurname}\marg{surname} +%\end{definition} +% The format of an author/editor's surname. +% \begin{macrocode} +\newcommand*{\DTLformatsurname}[1]{% +\DTLstartsentencespace +#1\DTLcheckendsperiod{#1}} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLformatjr} +%\begin{definition} +%\cs{DTLformatjr}\marg{jr part} +%\end{definition} +% The format of the ``jr'' part. This does nothing if the +% argument is empty. +% \begin{macrocode} +\newcommand*{\DTLformatjr}[1]{% +\DTLstartsentencespace +\def\@dtl@tmp{#1}% +\ifx\@dtl@tmp\@empty +\else + , #1\DTLcheckendsperiod{#1}% +\fi +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLformatcrossrefeditor} +% Format cross reference editors: +% \begin{macrocode} +\newcommand*{\DTLformatcrossrefeditor}{% +\DTLifbibfieldexists{Editor}{% +\DTLstartsentencespace +\@dtl@authorcount=0\relax +\@for\@dtl@author:=\@dtl@key@Editor\do{% +\advance\@dtl@authorcount by 1\relax}% +{\@dtl@tmpcount=0\relax +\@for\@dtl@author:=\@dtl@key@Editor\do{% +\ifnum\@dtl@authorcount=1\relax + \expandafter\DTLformatsurnameonly\@dtl@author +\else + \advance\@dtl@tmpcount by 1\relax + \ifnum\@dtl@tmpcount=1\relax + \expandafter\DTLformatsurnameonly\@dtl@author + \else + \ifnum\@dtl@authorcount=2\relax + \ \andname\ \expandafter\DTLformatsurnameonly\@dtl@author + \else + \ \etalname + \expandafter\DTLcheckendsperiod\expandafter{\etalname} + \fi + \@endfortrue + \fi +\fi +}}% +}{}% +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLformatvolnumpages} +% Format volume, number and pages (of an article). +% \begin{macrocode} +\newcommand*{\DTLformatvolnumpages}{% +\DTLifbibfieldexists{Volume}{% +\DTLstartsentencespace +\DTLbibfield{Volume}\DTLperiodfalse}{}% +\DTLifbibfieldexists{Number}{% +\DTLstartsentencespace +(\DTLbibfield{Number})\DTLperiodfalse}{}% +\DTLifbibfieldexists{Pages}{% +\DTLifanybibfieldexists{Volume,Number}{:}{% +\DTLstartsentencespace +\protected@edef\@dtl@pages{0\DTLbibfield{Pages}}% +\DTLifnumerical{\@dtl@pages}{\pagename}{\pagesname}~}% +\DTLbibfield{Pages}\DTLperiodfalse}{}% +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLformatbvolume} +% Format book volume. +% \begin{macrocode} +\newcommand*{\DTLformatbvolume}{% +\DTLifbibfieldexists{Volume}{% +\ifDTLmidsentence + \volumename +\else + \DTLstartsentencespace + \expandafter\MakeUppercase\volumename +\fi +~\DTLbibfield{Volume}% +\DTLifbibfieldexists{Series}{\ \ofname\ +{\em\DTLbibfield{Series}}\DTLcheckbibfieldendsperiod{Series}}{% +\DTLcheckbibfieldendsperiod{Volume}}% +}{}} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLformatchapterpages} +% Format chapter and pages: +% \begin{macrocode} +\newcommand*{\DTLformatchapterpages}{% +\DTLifbibfieldexists{Chapter}{% +\DTLifbibfieldexists{Type}{% +\DTLstartsentencespace +\DTLbibfield{Type}}{% +\DTLstartsentencespace +\chaptername}~\DTLbibfield{Chapter}% +\DTLifbibfieldexists{Pages}{\DTLaddcomma}{% +\DTLcheckbibfieldendsperiod{Chapter}}}{}% +\DTLstartsentencespace +\DTLformatpages} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLformatpages} +% Format pages: +% \begin{macrocode} +\newcommand*{\DTLformatpages}{% +\DTLifbibfieldexists{Pages}{% +\DTLstartsentencespace +\protected@edef\@dtl@pages{0\DTLbibfield{Pages}}% +\DTLifnumerical{\@dtl@pages}{\pagename}{\pagesname}~% +\DTLbibfield{Pages}\DTLcheckbibfieldendsperiod{Pages}}{}% +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLformatnumberseries} +% Format number and series (of book) +% \begin{macrocode} +\newcommand*{\DTLformatnumberseries}{% +\DTLifbibfieldexists{Volume}{}{% +\DTLifbibfieldexists{Number}{% +\ifDTLmidsentence + \numbername +\else + \DTLstartsentencespace + \expandafter\MakeUppercase\numbername +\fi~\DTLbibfield{Number}% +\DTLifbibfieldexists{Series}{\ \inname\ \DTLbibfield{Series}% +\DTLcheckbibfieldendsperiod{Series}}{% +\DTLcheckbibfieldendsperiod{Number}}% +}{% +\DTLifbibfieldexists{Series}{% +\DTLstartsentencespace +\DTLbibfield{Series}% +\DTLcheckbibfieldendsperiod{Series}}{}}% +}% +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLformatbookcrossref} +% Format a book cross reference. +% \begin{macrocode} +\newcommand*{\DTLformatbookcrossref}{% +\DTLifbibfieldexists{Volume}{% +\ifDTLmidsentence + \volumename +\else + \DTLstartsentencespace + \expandafter\MakeUppercase\volumename +\fi +~\DTLbibfield{Volume}\ \ofname\ +}{% +\ifDTLmidsentence + \inname +\else + \DTLstartsentencespace + \expandafter\MakeUppercase\inname +\fi\ }% +\DTLifbibfieldexists{Editor}{\DTLformatcrossrefeditor}{% +\DTLifbibfieldexists{Key}{% +\DTLbibfield{Key}}{% +\DTLifbibfieldexists{Series}{% +{\em\DTLbibfield{Series}}}{}% +}% +}% +\edef\@dtl@tmp{\DTLbibfield{CrossRef}}% +~\cite{\@dtl@tmp}% +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLformatincollproccrossref} +% Format `incollections' cross reference. +% \begin{macrocode} +\newcommand*{\DTLformatincollproccrossref}{% +\DTLifbibfieldexists{Editor}{% +\ifDTLmidsentence + \inname +\else + \DTLstartsentencespace + \expandafter\MakeUppercase\inname +\fi\ +\DTLformatcrossrefeditor +}{% +\DTLifbibfieldexists{Key}{% +\ifDTLmidsentence + \inname +\else + \DTLstartsentencespace + \expandafter\MakeUppercase\inname +\fi\ \DTLbibfield{Key}% +}{% +\DTLifbibfieldexists{BookTitle}{% +\ifDTLmidsentence + \inname +\else + \DTLstartsentencespace + \expandafter\MakeUppercase\inname +\fi\ {\em\DTLbibfield{BookTitle}}}{}% +}}% +\edef\@dtl@tmp{\DTLbibfield{CrossRef}}% +~\cite{\@dtl@tmp}% +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLformatinedbooktitle} +%Format editor and booktitle: +% \begin{macrocode} +\newcommand*{\DTLformatinedbooktitle}{% +\DTLifbibfieldexists{BookTitle}{% +\ifDTLmidsentence + \inname +\else + \DTLstartsentencespace + \expandafter\MakeUppercase\inname +\fi\ +\DTLifbibfieldexists{Editor}{% +\DTLformateditorlist\DTLaddcomma {\em\DTLbibfield{BookTitle}}% +\DTLcheckbibfieldendsperiod{BookTitle}% +}{{\em\DTLbibfield{BookTitle}}% +\DTLcheckbibfieldendsperiod{BookTitle}% +}}{}} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLformatdate} +%Format date. +% \begin{macrocode} +\newcommand*{\DTLformatdate}{% +\DTLifbibfieldexists{Year}{% +\DTLifbibfieldexists{Month}{% +\protected@edef\@dtl@tmp{\DTLbibfield{Month}}% +\ifDTLmidsentence + \@dtl@tmp +\else + \DTLstartsentencespace + \expandafter\MakeUppercase\@dtl@tmp +\fi\ +\DTLmidsentencefalse}{}% +\DTLstartsentencespace +\DTLbibfield{Year}}{% +\DTLifbibfieldexists{Month}{% +\protected@edef\@dtl@tmp{\DTLbibfield{Month}}% +\ifDTLmidsentence + \@dtl@tmp +\else + \DTLstartsentencespace + \expandafter\MakeUppercase\@dtl@tmp +\fi +\DTLcheckbibfieldendsperiod{Month}% +}{}}} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLformatarticlecrossref} +% Format article cross reference. +% \begin{macrocode} +\newcommand*{\DTLformatarticlecrossref}{% +\DTLifbibfieldexists{Key}{% +\ifDTLmidsentence + \inname +\else + \DTLstartsentencespace + \expandafter\MakeUppercase\inname +\fi +\ {\em\DTLbibfield{Key}}}{% +\DTLifbibfieldexists{Journal}{% +\ifDTLmidsentence + \inname +\else + \DTLstartsentencespace + \expandafter\MakeUppercase\inname +\fi +\ {\em\DTLbibfield{Journal}}}{}}% +\edef\@dtl@tmp{\DTLbibfield{CrossRef}}% +~\cite{\@dtl@tmp}% +} +% \end{macrocode} +%\end{macro} +% +%\subsubsection{ifthen conditionals} +% The conditionals defined in this section may be used in the +% optional argument of \cs{DTLforeachbib}. They may also be +% used in the first argument of \cs{ifthenelse}, but only if the +% command occurs within the body of \cs{DTLforeachbib}. +% +%\begin{macro}{\DTLbibfieldexists} +%\begin{definition} +%\cs{DTLbibfieldexists}\marg{field label} +%\end{definition} +% Checks if named bib field exists for current entry +% \begin{macrocode} +\newcommand*{\DTLbibfieldexists}[1]{% +\TE@throw\noexpand\dtl@testbibfieldexists{#1}% +\noexpand\if@dtl@condition} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\dtl@testbibfieldexists} +% \begin{macrocode} +\newcommand*{\dtl@testbibfieldexists}[1]{% +\DTLifbibfieldexists{#1}{\@dtl@conditiontrue}{\@dtl@conditionfalse}} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLbibfieldiseq} +%\begin{definition} +%\cs{DTLbibfieldiseq}\marg{field label}\marg{value} +%\end{definition} +% Checks if the value of the bib field given by \meta{field label} +% is equal to \meta{value}. (Uses \cs{dtlcompare} to determine if +% the values are equal. If the bib field doesn't exist, the +% condition is false.) +% \begin{macrocode} +\newcommand*{\DTLbibfieldiseq}[2]{% +\TE@throw\noexpand\dtl@testbibfieldiseq{#1}{#2}% +\noexpand\if@dtl@condition} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\dtl@testbibfieldiseq} +% \begin{macrocode} +\newcommand*{\dtl@testbibfieldiseq}[2]{% +\DTLifbibfieldexists{#1}{% +\expandafter\let\expandafter\@dtl@tmp\expandafter + =\csname @dtl@key@#1\endcsname +\expandafter\toks@\expandafter{\@dtl@tmp}% +\@dtl@toks{#2}% +\edef\@dtl@docompare{\noexpand\dtlcompare{\noexpand\@dtl@tmpcount}% +{\the\toks@}{\the\@dtl@toks}}% +\@dtl@docompare +\ifnum\@dtl@tmpcount=0\relax + \@dtl@conditiontrue +\else + \@dtl@conditionfalse +\fi +}{% +\@dtl@conditionfalse}% +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLbibfieldislt} +%\begin{definition} +%\cs{DTLbibfieldislt}\marg{field label}\marg{value} +%\end{definition} +% Checks if the value of the bib field given by \meta{field label} +% is less than \meta{value}. (If the bib field doesn't exist, the +% condition is false.) +% \begin{macrocode} +\newcommand*{\DTLbibfieldislt}[2]{% +\TE@throw\noexpand\dtl@testbibfieldislt{#1}{#2}% +\noexpand\if@dtl@condition} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\dtl@testbibfieldislt} +% \begin{macrocode} +\newcommand*{\dtl@testbibfieldislt}[2]{% +\DTLifbibfieldexists{#1}{% +\expandafter\let\expandafter\@dtl@tmp\expandafter + =\csname @dtl@key@#1\endcsname +\expandafter\toks@\expandafter{\@dtl@tmp}% +\@dtl@toks{#2}% +\edef\@dtl@docompare{\noexpand\dtlcompare{\noexpand\@dtl@tmpcount}% +{\the\toks@}{\the\@dtl@toks}}% +\@dtl@docompare +\ifnum\@dtl@tmpcount=-1\relax + \@dtl@conditiontrue +\else + \@dtl@conditionfalse +\fi +}{% +\@dtl@conditionfalse}% +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLbibfieldisle} +%\begin{definition} +%\cs{DTLbibfieldisle}\marg{field label}\marg{value} +%\end{definition} +% Checks if the value of the bib field given by \meta{field label} +% is less than or equal to \meta{value}. +% (If the bib field doesn't exist, the +% condition is false.) +% \begin{macrocode} +\newcommand*{\DTLbibfieldisle}[2]{% +\TE@throw\noexpand\dtl@testbibfieldisle{#1}{#2}% +\noexpand\if@dtl@condition} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\dtl@testbibfieldisle} +% \begin{macrocode} +\newcommand*{\dtl@testbibfieldisle}[2]{% +\DTLifbibfieldexists{#1}{% +\expandafter\let\expandafter\@dtl@tmp\expandafter + =\csname @dtl@key@#1\endcsname +\expandafter\toks@\expandafter{\@dtl@tmp}% +\@dtl@toks{#2}% +\edef\@dtl@docompare{\noexpand\dtlcompare{\noexpand\@dtl@tmpcount}% +{\the\toks@}{\the\@dtl@toks}}% +\@dtl@docompare +\ifnum\@dtl@tmpcount<1\relax + \@dtl@conditiontrue +\else + \@dtl@conditionfalse +\fi +}{% +\@dtl@conditionfalse}% +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLbibfieldisgt} +%\begin{definition} +%\cs{DTLbibfieldisgt}\marg{field label}\marg{value} +%\end{definition} +% Checks if the value of the bib field given by \meta{field label} +% is greater than \meta{value}. (If the bib field doesn't exist, the +% condition is false.) +% \begin{macrocode} +\newcommand*{\DTLbibfieldisgt}[2]{% +\TE@throw\noexpand\dtl@testbibfieldisgt{#1}{#2}% +\noexpand\if@dtl@condition} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\dtl@testbibfieldisgt} +% \begin{macrocode} +\newcommand*{\dtl@testbibfieldisgt}[2]{% +\DTLifbibfieldexists{#1}{% +\expandafter\let\expandafter\@dtl@tmp\expandafter + =\csname @dtl@key@#1\endcsname +\expandafter\toks@\expandafter{\@dtl@tmp}% +\@dtl@toks{#2}% +\edef\@dtl@docompare{\noexpand\dtlcompare{\noexpand\@dtl@tmpcount}% +{\the\toks@}{\the\@dtl@toks}}% +\@dtl@docompare +\ifnum\@dtl@tmpcount=1\relax + \@dtl@conditiontrue +\else + \@dtl@conditionfalse +\fi +}{% +\@dtl@conditionfalse}% +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLbibfieldisge} +%\begin{definition} +%\cs{DTLbibfieldisge}\marg{field label}\marg{value} +%\end{definition} +% Checks if the value of the bib field given by \meta{field label} +% is less than or equal to \meta{value}. +% (If the bib field doesn't exist, the +% condition is false.) +% \begin{macrocode} +\newcommand*{\DTLbibfieldisge}[2]{% +\TE@throw\noexpand\dtl@testbibfieldisge{#1}{#2}% +\noexpand\if@dtl@condition} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\dtl@testbibfieldisge} +% \begin{macrocode} +\newcommand*{\dtl@testbibfieldisge}[2]{% +\DTLifbibfieldexists{#1}{% +\expandafter\let\expandafter\@dtl@tmp\expandafter + =\csname @dtl@key@#1\endcsname +\expandafter\toks@\expandafter{\@dtl@tmp}% +\@dtl@toks{#2}% +\edef\@dtl@docompare{\noexpand\dtlcompare{\noexpand\@dtl@tmpcount}% +{\the\toks@}{\the\@dtl@toks}}% +\@dtl@docompare +\ifnum\@dtl@tmpcount>-1\relax + \@dtl@conditiontrue +\else + \@dtl@conditionfalse +\fi +}{% +\@dtl@conditionfalse}% +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLbibfieldcontains} +%\begin{definition} +%\cs{DTLbibfieldcontains}\marg{field label}\marg{sub string} +%\end{definition} +% Checks if the value of the bib field given by \meta{field label} +% contains \meta{sub string}. +% (If the bib field doesn't exist, the +% condition is false.) +% \begin{macrocode} +\newcommand*{\DTLbibfieldcontains}[2]{% +\TE@throw\noexpand\dtl@testbibfieldcontains{#1}{#2}% +\noexpand\if@dtl@condition} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\dtl@testbibfieldcontains} +% \begin{macrocode} +\newcommand*{\dtl@testbibfieldcontains}[2]{% +\DTLifbibfieldexists{#1}{% +\expandafter\let\expandafter\@dtl@tmp\expandafter + =\csname @dtl@key@#1\endcsname +\expandafter\dtl@testifsubstring\expandafter{\@dtl@tmp}{#2}% +}{\@dtl@conditionfalse}} +% \end{macrocode} +%\end{macro} +% +%\subsection{Bibliography Style Macros} +%\label{sec:src:bibstyle} +% The macros defined in this section should be redefined by +% bibliography styles. +% +%\begin{environment}{DTLthebibliography} +% How to format the entire bibliography: +% \begin{macrocode} +\newenvironment{DTLthebibliography}[2][\boolean{true}]{% +\@dtl@tmpcount=0\relax +\@sDTLforeach[#1]{#2}{}{\advance\@dtl@tmpcount by 1\relax}% +\begin{thebibliography}{\number\@dtl@tmpcount} +}{\end{thebibliography}} +% \end{macrocode} +%\end{environment} +%\begin{macro}{\DTLmonthname} +% The monthname style. The argument must be a number from~1 +% to~12. By default, uses \cs{dtl@monthname}. +% \begin{macrocode} +\newcommand*{\DTLmonthname}[1]{% +\dtl@monthname{#1}} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\dtl@monthname} +% Full month names: +% \begin{macrocode} +\newcommand*{\dtl@monthname}[1]{% +\ifcase#1% +\or January% +\or February% +\or March% +\or April% +\or May% +\or June% +\or July% +\or August% +\or September% +\or October% +\or November% +\or December% +\fi} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\dtl@abbrvmonthname} +% Abbreviated months: +% \begin{macrocode} +\newcommand*{\dtl@abbrvmonthname}[1]{% +\ifcase#1% +\or Jan.% +\or Feb.% +\or Mar.% +\or Apr.% +\or May% +\or June% +\or July% +\or Aug.% +\or Sept.% +\or Oct.% +\or Nov.% +\or Dec.% +\fi} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLbibitem} +% Define how to start a new bibitem: +% \begin{macrocode} +\newcommand*{\DTLbibitem}{\bibitem{\DBIBcitekey}} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLformatauthor} +%\begin{definition} +%\cs{DTLformatauthor}\marg{von part}\marg{surname}\marg{junior +%part}\marg{forenames} +%\end{definition} +% The format of an author's name. +% \begin{macrocode} +\newcommand*{\DTLformatauthor}[4]{% +\DTLformatforenames{#4} +\DTLformatvon{#1}% +\DTLformatsurname{#2}% +\DTLformatjr{#3}} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLformateditor} +% The format of an editor's name. +% \begin{macrocode} +\newcommand*{\DTLformateditor}[4]{% +\DTLformatforenames{#4} +\DTLformatvon{#1}% +\DTLformatsurname{#2}% +\DTLformatjr{#3}} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLformatedition} +% The format of an edition: +% \begin{macrocode} +\newcommand*{\DTLformatedition}[1]{#1 \editionname} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLformatarticle} +% The format of an article: +% \begin{macrocode} +\newcommand{\DTLformatarticle}{} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLformatbook} +% The format of a book: +% \begin{macrocode} +\newcommand{\DTLformatbook}{} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLformatbooklet} +% The format of a booklet: +% \begin{macrocode} +\newcommand{\DTLformatbooklet}{} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLformatinbook} +% The format of an ``inbook'' type: +% \begin{macrocode} +\newcommand{\DTLformatinbook}{} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLformatincollection} +% The format of an ``incollection'' type: +% \begin{macrocode} +\newcommand{\DTLformatincollection}{} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLformatinproceedings} +% The format of an ``inproceedings'' type: +% \begin{macrocode} +\newcommand{\DTLformatinproceedings}{} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLformatmanual} +% The format of a manual: +% \begin{macrocode} +\newcommand{\DTLformatmanual}{} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLformatmastersthesis} +% The format of a master's thesis: +% \begin{macrocode} +\newcommand{\DTLformatmastersthesis}{} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLformatmisc} +% The format of a miscellaneous entry: +% \begin{macrocode} +\newcommand{\DTLformatmisc}{} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLformatphdthesis} +% The format of a Ph.D. thesis: +% \begin{macrocode} +\newcommand{\DTLformatphdthesis}{} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLformatproceedings} +% The format of a proceedings: +% \begin{macrocode} +\newcommand{\DTLformatproceedings}{} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLformattechreport} +% The format of a technical report: +% \begin{macrocode} +\newcommand{\DTLformattechreport}{} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLformatunpublished} +% The format of an unpublished work: +% \begin{macrocode} +\newcommand{\DTLformatunpublished}{} +% \end{macrocode} +%\end{macro} +% +% Predefined names (these correspond to the standard \BibTeX\ +% predefined strings of the same name without the leading +% \cs{DTL}): +%\begin{macro}{\DTLacmcs} +% \begin{macrocode} +\newcommand*{\DTLacmcs}{ACM Computing Surveys} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLacta} +% \begin{macrocode} +\newcommand*{\DTLacta}{Acta Informatica} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLcacm} +% \begin{macrocode} +\newcommand*{\DTLcacm}{Communications of the ACM} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLibmjrd} +% \begin{macrocode} +\newcommand*{\DTLibmjrd}{IBM Journal of Research and Development} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLibmsj} +% \begin{macrocode} +\newcommand*{\DTLibmsj}{IBM Systems Journal} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLieeese} +% \begin{macrocode} +\newcommand*{\DTLieeese}{IEEE Transactions on Software Engineering} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLieeetc} +% \begin{macrocode} +\newcommand*{\DTLieeetc}{IEEE Transactions on Computers} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLieeetcad} +% \begin{macrocode} +\newcommand*{\DTLieeetcad}{IEEE Transactions on Computer-Aided Design +of Integrated Circuits} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLipl} +% \begin{macrocode} +\newcommand*{\DTLipl}{Information Processing Letters} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLjacm} +% \begin{macrocode} +\newcommand*{\DTLjacm}{Journal of the ACM} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLjcss} +% \begin{macrocode} +\newcommand*{\DTLjcss}{Journal of Computer and System Sciences} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLscp} +% \begin{macrocode} +\newcommand*{\DTLscp}{Science of Computer Programming} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLsicomp} +% \begin{macrocode} +\newcommand*{\DTLsicomp}{SIAM Journal on Computing} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLtocs} +% \begin{macrocode} +\newcommand*{\DTLtocs}{ACM Transactions on Computer Systems} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLtods} +% \begin{macrocode} +\newcommand*{\DTLtods}{ACM Transactions on Database Systems} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLtog} +% \begin{macrocode} +\newcommand*{\DTLtog}{ACM Transactions on Graphics} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLtoms} +% \begin{macrocode} +\newcommand*{\DTLtoms}{ACM Transactions on Mathematical Software} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLtoois} +% \begin{macrocode} +\newcommand*{\DTLtoois}{ACM Transactions on Office Information +Systems} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLtoplas} +% \begin{macrocode} +\newcommand*{\DTLtoplas}{ACM Transactions on Programming Languages +and Systems} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLtcs} +% \begin{macrocode} +\newcommand*{\DTLtcs}{Theoretical Computer Science} +% \end{macrocode} +%\end{macro} +% +%\subsection{Bibliography Styles} +% Each bibliography style is set by the command +% \cs{dtlbst@}\meta{style}, where \meta{style} is the name +% of the bibliography style. +% +%\begin{macro}{\dtlbst@plain} +% The `plain' style: +% \begin{macrocode} +\newcommand{\dtlbst@plain}{% +% \end{macrocode} +% Set how to format the entire bibliography: +% \begin{macrocode} +\renewenvironment{DTLthebibliography}[2][\boolean{true}]{% +\@dtl@tmpcount=0\relax +\@sDTLforeach[##1]{##2}{}{\advance\@dtl@tmpcount by 1\relax}% +\begin{thebibliography}{\number\@dtl@tmpcount}% +}{\end{thebibliography}}% +% \end{macrocode} +% Set how to start the bibliography entry: +% \begin{macrocode} +\renewcommand*{\DTLbibitem}{\bibitem{\DBIBcitekey}}% +% \end{macrocode} +% Sets the author name format. +% \begin{macrocode} +\renewcommand*{\DTLformatauthor}[4]{% +\DTLformatforenames{##4} +\DTLformatvon{##1}% +\DTLformatsurname{##2}% +\DTLformatjr{##3}} +% \end{macrocode} +% Sets the editor name format. +% \begin{macrocode} +\renewcommand*{\DTLformateditor}[4]{% +\DTLformatforenames{##4} +\DTLformatvon{##1}% +\DTLformatsurname{##2}% +\DTLformatjr{##3}} +% \end{macrocode} +% Sets the edition format. +% \begin{macrocode} +\renewcommand*{\DTLformatedition}[1]{##1 \editionname}% +% \end{macrocode} +% Sets the monthname format. +% \begin{macrocode} +\let\DTLmonthname\dtl@monthname +% \end{macrocode} +% Sets other predefined names: +% \begin{macrocode} +\renewcommand*{\DTLacmcs}{ACM Computing Surveys} +\renewcommand*{\DTLacta}{Acta Informatica} +\renewcommand*{\DTLcacm}{Communications of the ACM} +\renewcommand*{\DTLibmjrd}{IBM Journal of Research and Development} +\renewcommand*{\DTLibmsj}{IBM Systems Journal} +\renewcommand*{\DTLieeese}{IEEE Transactions on Software Engineering} +\renewcommand*{\DTLieeetc}{IEEE Transactions on Computers} +\renewcommand*{\DTLieeetcad}{IEEE Transactions on Computer-Aided Design +of Integrated Circuits} +\renewcommand*{\DTLipl}{Information Processing Letters} +\renewcommand*{\DTLjacm}{Journal of the ACM} +\renewcommand*{\DTLjcss}{Journal of Computer and System Sciences} +\renewcommand*{\DTLscp}{Science of Computer Programming} +\renewcommand*{\DTLsicomp}{SIAM Journal on Computing} +\renewcommand*{\DTLtocs}{ACM Transactions on Computer Systems} +\renewcommand*{\DTLtods}{ACM Transactions on Database Systems} +\renewcommand*{\DTLtog}{ACM Transactions on Graphics} +\renewcommand*{\DTLtoms}{ACM Transactions on Mathematical Software} +\renewcommand*{\DTLtoois}{ACM Transactions on Office Information +Systems} +\renewcommand*{\DTLtoplas}{ACM Transactions on Programming Languages +and Systems} +\renewcommand*{\DTLtcs}{Theoretical Computer Science} +% \end{macrocode} +% The format of an article. +% \begin{macrocode} +\renewcommand*{\DTLformatarticle}{% +\DTLformatauthorlist +\DTLifbibfieldexists{Author}{\DTLaddperiod}{}% +\DTLifbibfieldexists{Title}{% +\DTLstartsentencespace\DTLbibfield{Title}% +\DTLcheckbibfieldendsperiod{Title}% +\DTLaddperiod}{}% +\DTLifbibfieldexists{CrossRef}{% +% cross ref field +\DTLformatarticlecrossref +\DTLifbibfieldexists{Pages}{\DTLaddcomma}{}% +\DTLformatpages +\DTLaddperiod +}{% no cross ref field +\DTLifbibfieldexists{Journal}{\DTLstartsentencespace +{\em\DTLbibfield{Journal}}% +\DTLcheckbibfieldendsperiod{Journal}% +\DTLifanybibfieldexists{Number,Volume,Pages,Month,Year}{% +\DTLaddcomma}{\DTLaddperiod}}{}% +\DTLformatvolnumpages +\DTLifanybibfieldexists{Volume,Number,Pages}{% +\DTLifanybibfieldexists{Year,Month}{\DTLaddcomma}{% +\DTLaddperiod}% +\DTLmidsentencefalse}{}% +\DTLformatdate +\DTLifanybibfieldexists{Year,Month}{\DTLaddperiod}{}% +}% +\DTLifbibfieldexists{Note}{\DTLstartsentencespace\DTLbibfield{Note}% +\DTLcheckbibfieldendsperiod{Note}% +\DTLaddperiod}{}% +} +% \end{macrocode} +% The format of a book. +% \begin{macrocode} +\renewcommand*{\DTLformatbook}{% +\DTLifbibfieldexists{Author}{% +\DTLformatauthorlist\DTLaddperiod +}{\DTLformateditorlist\DTLifbibfieldexists{Editor}{% +\DTLaddperiod}{}}% +\DTLifbibfieldexists{Title}{\DTLstartsentencespace +{\em\DTLbibfield{Title}}% +\DTLcheckbibfieldendsperiod{Title}}{}% +\DTLifbibfieldexists{CrossRef}{% +% cross ref field +\DTLifbibfieldexists{Title}{\DTLaddperiod}{}% +\DTLformatbookcrossref +\DTLifanybibfieldexists{Edition,Month,Year}{\DTLaddcomma +}{\DTLaddperiod}% +}{% no cross ref field +\DTLifbibfieldexists{Title}{% +\DTLifbibfieldexists{Volume}{\DTLaddcomma}{\DTLaddperiod}}{}% +\DTLformatbvolume +\DTLformatnumberseries +\DTLifanybibfieldexists{Number,Series,Volume}{\DTLaddperiod}{}% +\DTLifbibfieldexists{Publisher}{\DTLstartsentencespace +\DTLbibfield{Publisher}% +\DTLcheckbibfieldendsperiod{Publisher}% +\DTLifbibfieldexists{Address}{\DTLaddcomma}{% +\DTLifanybibfieldexists{Month,Year}{\DTLaddcomma +}{\DTLaddperiod}% +}}{}% +\DTLifbibfieldexists{Address}{\DTLstartsentencespace +\DTLbibfield{Address}% +\DTLcheckbibfieldendsperiod{Address}% +\DTLifanybibfieldexists{Month,Year}{\DTLaddcomma}{\DTLaddperiod}}{}% +}% +\DTLifbibfieldexists{Edition}{% +\protected@edef\@dtl@tmp{\DTLformatedition{\DTLbibfield{Edition}}}% +\ifDTLmidsentence + \@dtl@tmp +\else + \DTLstartsentencespace\expandafter\MakeUppercase\@dtl@tmp +\fi +\expandafter\DTLcheckendsperiod\expandafter{\@dtl@tmp}% +\DTLifanybibfieldexists{Month,Year}{\DTLaddcomma}{\DTLaddperiod}% +}{}% +\DTLformatdate +\DTLifanybibfieldexists{Year,Month}{\DTLaddperiod}{}% +\DTLifbibfieldexists{Note}{\DTLstartsentencespace +\DTLbibfield{Note}% +\DTLcheckbibfieldendsperiod{Note}% +\DTLaddperiod}{}% +}% +% \end{macrocode} +% The format of a booklet. +% \begin{macrocode} +\renewcommand*{\DTLformatbooklet}{% +\DTLifbibfieldexists{Author}{% +\DTLformatauthorlist\DTLaddperiod}{}% +\DTLifbibfieldexists{Title}{\DTLstartsentencespace +\DTLbibfield{Title}% +\DTLcheckbibfieldendsperiod{Title}% +\DTLaddperiod}{}% +\DTLifbibfieldexists{HowPublished}{% +\DTLstartsentencespace\DTLbibfield{HowPublished}% +\DTLcheckbibfieldendsperiod{HowPublished}% +\DTLifanybibfieldexists{Address,Month,Year}{\DTLaddcomma +}{\DTLaddperiod}}{}% +\DTLifbibfieldexists{Address}{\DTLstartsentencespace +\DTLbibfield{Address}% +\DTLcheckbibfieldendsperiod{Address}% +\DTLifanybibfieldexists{Month,Year}{\DTLaddcomma}{\DTLaddperiod}}{}% +\DTLformatdate +\DTLifanybibfieldexists{Year,Month}{\DTLaddperiod}{}% +\DTLifbibfieldexists{Note}{\DTLstartsentencespace\DTLbibfield{Note}% +\DTLcheckbibfieldendsperiod{Note}% +\DTLaddperiod}{}% +}% +% \end{macrocode} +% The format of an `inbook' entry. +% \begin{macrocode} +\renewcommand*{\DTLformatinbook}{% +\DTLifbibfieldexists{Author}{% +\DTLformatauthorlist\DTLaddperiod}{% +\DTLifbibfieldexists{Editor}{\DTLformateditorlist\DTLaddperiod}{}}% +\DTLifbibfieldexists{Title}{% +\DTLstartsentencespace +{\em\DTLbibfield{Title}}% +\DTLcheckbibfieldendsperiod{Title}% +}{}% +\DTLifbibfieldexists{CrossRef}{% +% Cross ref entry +\DTLifbibfieldexists{Title}{% +\DTLifbibfieldexists{Chapter}{\DTLaddcomma}{\DTLaddperiod}}{}% +\DTLformatchapterpages +\DTLifanybibfieldexists{Chapter,Pages}{\DTLaddperiod}{}% +\DTLformatbookcrossref +}{% no cross ref +\DTLifbibfieldexists{Title}{% +\DTLifanybibfieldexists{Chapter,Volume}{\DTLaddcomma +}{\DTLaddperiod}}{}% +\DTLformatbvolume +\DTLifanybibfieldexists{Volume,Series}{% +\DTLifanybibfieldexists{Chapter,Pages}{% +\DTLaddcomma}{\DTLaddperiod}}{}% +\DTLformatchapterpages +\DTLifanybibfieldexists{Chapter,Pages}{\DTLaddperiod}{}% +\DTLifbibfieldexists{Publisher}{% +\DTLstartsentencespace +\DTLbibfield{Publisher}% +\DTLcheckbibfieldendsperiod{Publisher}% +\DTLifbibfieldexists{Address}{\DTLaddcomma}{}}{}% +\DTLifbibfieldexists{Address}{% +\DTLstartsentencespace +\DTLbibfield{Address}% +\DTLcheckbibfieldendsperiod{Address}}{}% +}% +\DTLifanybibfieldexists{Edition,Month,Year}{\DTLaddcomma +}{\DTLaddperiod}% +\DTLifbibfieldexists{Edition}{% +\protected@edef\@dtl@tmp{\DTLformatedition{\DTLbibfield{Edition}}}% +\ifDTLmidsentence + \@dtl@tmp +\else + \DTLstartsentencespace + \expandafter\MakeUppercase\@dtl@tmp +\fi +\expandafter\DTLcheckendsperiod\expandafter{\@dtl@tmp}% +\DTLifanybibfieldexists{Month,Year}{\DTLaddcomma +}{\DTLaddperiod}% +}{}% +\DTLformatdate +\DTLifanybibfieldexists{Month,Year}{\DTLaddperiod}{}% +\DTLifbibfieldexists{Note}{% +\DTLstartsentencespace +\DTLbibfield{Note}% +\DTLcheckbibfieldendsperiod{Note}% +\DTLaddperiod}{}% +}% +% \end{macrocode} +% The format of an `incollection' entry. +% \begin{macrocode} +\renewcommand*{\DTLformatincollection}{% +\DTLifbibfieldexists{Author}{\DTLformatauthorlist\DTLaddperiod}{}% +\DTLifbibfieldexists{Title}{% +\DTLstartsentencespace +\DTLbibfield{Title}% +\DTLcheckbibfieldendsperiod{Title}% +\DTLaddperiod}{}% +\DTLifbibfieldexists{CrossRef}{% +% cross ref entry +\DTLformatincollproccrossref +\DTLifanybibfieldexists{Chapter,Pages}{\DTLaddcomma}{}% +\DTLformatchapterpages\DTLaddperiod +}{% no cross ref entry +\DTLformatinedbooktitle +\DTLifbibfieldexists{BookTitle}{% +\DTLifanybibfieldexists{Volume,Series,Chapter,Pages,Number}{% +\DTLaddcomma}{\DTLaddperiod}}{}% +\DTLformatbvolume +\DTLifbibfieldexists{Volume}{% +\DTLifanybibfieldexists{Number,Series,Chapter,Pages}{% +\DTLaddcomma}{\DTLaddperiod}}{}% +\DTLformatnumberseries +\DTLifanybibfieldexists{Number,Series}{% +\DTLifanybibfieldexists{Chapter,Pages}{\DTLaddcomma +}{\DTLaddperiod}}{}% +\DTLformatchapterpages +\DTLifanybibfieldexists{Chapter,Pages}{\DTLaddperiod}{}% +\DTLifbibfieldexists{Publisher}{% +\DTLstartsentencespace +\DTLbibfield{Publisher}% +\DTLcheckbibfieldendsperiod{Publisher}% +\DTLifanybibfieldexists{Address,Edition,Month,Year}{% +\DTLaddcomma}{\DTLaddperiod}}{}% +\DTLifbibfieldexists{Address}{% +\DTLstartsentencespace +\DTLbibfield{Address}% +\DTLcheckbibfieldendsperiod{Address}% +\DTLifanybibfieldexists{Edition,Month,Year}{% +\DTLaddcomma}{\DTLaddperiod}}{}% +\DTLifbibfieldexists{Edition}{% +\protected@edef\@dtl@tmp{\DTLformatedition{\DTLbibfield{Edition}}}% +\ifDTLmidsentence + \@dtl@tmp +\else + \DTLstartsentencespace + \expandafter\MakeUppercase\@dtl@tmp +\fi +\expandafter\DTLcheckendsperiod\expandafter{\@dtl@tmp}% +\DTLifanybibfieldexists{Month,Year}{\DTLaddcomma +}{\DTLaddperiod}% +}{}% +\DTLformatdate +\DTLifanybibfieldexists{Month,Year}{\DTLaddperiod}{}% +}% +\DTLifbibfieldexists{Note}{% +\DTLstartsentencespace +\DTLbibfield{Note}% +\DTLcheckbibfieldendsperiod{Note}% +\DTLaddperiod}{}% +}% +% \end{macrocode} +% The format of an `inproceedings' entry. +% \begin{macrocode} +\renewcommand*{\DTLformatinproceedings}{% +\DTLifbibfieldexists{Author}{\DTLformatauthorlist +\DTLaddperiod}{}% +\DTLifbibfieldexists{Title}{% +\DTLstartsentencespace +\DTLbibfield{Title}% +\DTLcheckbibfieldendsperiod{Title}% +\DTLaddperiod}{}% +\DTLifbibfieldexists{CrossRef}{% +% cross ref entry +\DTLformatincollproccrossref +\DTLifbibfieldexists{Pages}{\DTLaddcomma}{% +\DTLaddperiod}% +\DTLformatpages +\DTLifbibfieldexists{Pages}{\DTLaddperiod}{}% +}{% no cross ref +\DTLformatinedbooktitle +\DTLifbibfieldexists{BookTitle}{% +\DTLifanybibfieldexists{Volume,Series,Pages,Number,Address,% +Month,Year}{% +\DTLaddcomma}{\DTLaddperiod}}{}% +\DTLformatbvolume +\DTLifbibfieldexists{Volume}{% +\DTLifanybibfieldexists{Number,Series,Pages,Address,Month,Year}{% +\DTLaddcomma}{\DTLaddperiod}}{}% +\DTLformatnumberseries +\DTLifanybibfieldexists{Number,Series}{% +\DTLifanybibfieldexists{Pages,Address,Month,Year}{% +\DTLaddcomma}{\DTLaddperiod}}{}% +\DTLformatpages +\DTLifbibfieldexists{Pages}{% +\DTLifanybibfieldexists{Address,Month,Year}{% +\DTLaddcomma}{\DTLaddperiod}}{}% +\DTLifbibfieldexists{Address}{% +\DTLstartsentencespace +\DTLbibfield{Address}% +\DTLcheckbibfieldendsperiod{Address}% +\DTLifanybibfieldexists{Month,Year}{\DTLaddcomma}{% +\DTLaddperiod}% +\DTLformatdate +\DTLifanybibfieldexists{Month,Year}{\DTLaddperiod}{}% +\DTLifbibfieldexists{Organization}{% +\DTLstartsentencespace +\DTLbibfield{Organization}% +\DTLcheckbibfieldendsperiod{Organization}% +\DTLifbibfieldexists{Publisher}{\DTLaddcomma}{% +\DTLaddperiod}}{}% +\DTLifbibfieldexists{Publisher}{% +\DTLstartsentencespace +\DTLbibfield{Publisher}% +\DTLcheckbibfieldendsperiod{Publisher}% +\DTLaddperiod}{}% +}{% +\DTLifanybibfieldexists{Publisher,Organization}{% +\DTLaddperiod}{}% +\DTLifbibfieldexists{Organization}{% +\DTLstartsentencespace +\DTLbibfield{Organization}% +\DTLcheckbibfieldendsperiod{Organization}% +\DTLifanybibfieldexists{Publisher,Month,Year}{% +\DTLaddcomma}{}}{}% +\DTLifbibfieldexists{Publisher}{% +\DTLstartsentencespace +\DTLbibfield{Publisher}% +\DTLcheckbibfieldendsperiod{Publisher}% +\DTLifanybibfieldexists{Month,Year}{\DTLaddcomma}{% +\DTLaddperiod}}{}% +\DTLformatdate +\DTLifanybibfieldexists{Month,Year}{\DTLaddperiod}{}% +}% +}% +\DTLifbibfieldexists{Note}{% +\DTLstartsentencespace +\DTLbibfield{Note}% +\DTLcheckbibfieldendsperiod{Note}% +\DTLaddperiod}{}% +}% +% \end{macrocode} +% The format of a manual. +% \begin{macrocode} +\renewcommand*{\DTLformatmanual}{% +\DTLifbibfieldexists{Author}{\DTLformatauthorlist +\DTLaddperiod}{% +\DTLifbibfieldexists{Organization}{% +\DTLstartsentencespace +\DTLbibfield{Organization}% +\DTLcheckbibfieldendsperiod{Organization}% +\DTLifbibfieldexists{Address}{\DTLaddcomma \DTLbibfield{Address}% +\DTLcheckbibfieldendsperiod{Address}% +}{}% +\DTLaddperiod}{}% +}% +\DTLifbibfieldexists{Title}{% +\DTLstartsentencespace +{\em\DTLbibfield{Title}}% +\DTLcheckbibfieldendsperiod{Title}% +\DTLifbibfieldexists{Author}{% +\DTLifanybibfieldexists{Organization,Address}{% +\DTLaddperiod}{\DTLaddcomma}}{% +\DTLifanybibfieldexists{Organization,Address,Edition,Month,Year}{% +\DTLaddcomma}{\DTLaddperiod}}}{}% +\DTLifbibfieldexists{Author}{% +\DTLifbibfieldexists{Organization}{% +\DTLstartsentencespace +\DTLbibfield{Organization}% +\DTLcheckbibfieldendsperiod{Organization}% +\DTLifanybibfieldexists{Address,Edition,Month,Year}{% +\DTLaddcomma}{\DTLaddperiod}}{}% +\DTLifbibfieldexists{Address}{% +\DTLstartsentencespace +\DTLbibfield{Address}% +\DTLcheckbibfieldendsperiod{Address}% +\DTLifanybibfieldexists{Edition,Month,Year}{% +\DTLaddcomma}{\DTLaddperiod}}{}% +}{% +\DTLifbibfieldexists{Organization}{}{% +\DTLifbibfieldexists{Address}{% +\DTLstartsentencespace +\DTLbibfield{Address}% +\DTLcheckbibfieldendsperiod{Address}% +\DTLifanybibfieldexists{Edition,Month,Year}{\DTLaddcomma}{% +\DTLaddperiod}}{}}% +}% +\DTLifbibfieldexists{Edition}{% +\protected@edef\@dtl@tmp{\DTLformatedition{\DTLbibfield{Edition}}}% +\ifDTLmidsentence + \@dtl@tmp +\else + \DTLstartsentencespace + \expandafter\MakeUppercase\@dtl@tmp +\fi +\expandafter\DTLcheckendsperiod\expandafter{\@dtl@tmp}% +\DTLifanybibfieldexists{Month,Year}{\DTLaddcomma}{% +\DTLaddperiod}}{}% +\DTLformatdate +\DTLifanybibfieldexists{Month,Year}{\DTLaddperiod}{}% +\DTLifbibfieldexists{Note}{% +\DTLstartsentencespace +\DTLbibfield{Note}% +\DTLcheckbibfieldendsperiod{Note}% +\DTLaddperiod}{}% +}% +% \end{macrocode} +% The format of a master's thesis. +% \begin{macrocode} +\renewcommand*{\DTLformatmastersthesis}{% +\DTLifbibfieldexists{Author}{\DTLformatauthorlist\DTLaddperiod}{}% +\DTLifbibfieldexists{Title}{% +\DTLstartsentencespace +\DTLbibfield{Title}% +\DTLcheckbibfieldendsperiod{Title}% +\DTLaddperiod}{}% +\DTLifbibfieldexists{Type}{% +\DTLstartsentencespace +\DTLbibfield{Type}% +\DTLcheckbibfieldendsperiod{Type}% +\DTLifanybibfieldexists{School,Address,Month,Year}{% +\DTLaddcomma}{\DTLaddperiod}}{}% +\DTLifbibfieldexists{School}{% +\DTLstartsentencespace +\DTLbibfield{School}% +\DTLcheckbibfieldendsperiod{School}% +\DTLifanybibfieldexists{Address,Month,Year}{% +\DTLaddcomma}{\DTLaddperiod}}{}% +\DTLifbibfieldexists{Address}{% +\DTLstartsentencespace +\DTLbibfield{Address}% +\DTLcheckbibfieldendsperiod{Address}% +\DTLifanybibfieldexists{Month,Year}{% +\DTLaddcomma}{\DTLaddperiod}}{}% +\DTLformatdate +\DTLifanybibfieldexists{Month,Year}{\DTLaddperiod}{}% +\DTLifbibfieldexists{Note}{% +\DTLstartsentencespace +\DTLbibfield{Note}% +\DTLcheckbibfieldendsperiod{Note}% +\DTLaddperiod}{}% +}% +% \end{macrocode} +% The format of a miscellaneous entry. +% \begin{macrocode} +\renewcommand*{\DTLformatmisc}{% +\DTLifbibfieldexists{Author}{\DTLformatauthorlist\DTLaddperiod}{}% +\DTLifbibfieldexists{Title}{% +\DTLstartsentencespace +\DTLbibfield{Title}% +\DTLcheckbibfieldendsperiod{Title}% +\DTLifbibfieldexists{HowPublished}{\DTLaddperiod}{% +\DTLifanybibfieldexists{Month,Year}{\DTLaddcomma}{% +\DTLaddperiod}% +}% +\DTLmidsentencefalse}{}% +\DTLifbibfieldexists{HowPublished}{% +\DTLstartsentencespace +\DTLbibfield{HowPublished}% +\DTLcheckbibfieldendsperiod{HowPublished}% +\DTLifanybibfieldexists{Month,Year}{\DTLaddcomma}{% +\DTLaddperiod}}{}% +\DTLformatdate +\DTLifanybibfieldexists{Month,Year}{\DTLaddperiod}{}% +\DTLifbibfieldexists{Note}{% +\DTLstartsentencespace +\DTLbibfield{Note}% +\DTLcheckbibfieldendsperiod{Note}% +\DTLaddperiod}{}% +}% +% \end{macrocode} +% The format of a PhD thesis. +% \begin{macrocode} +\renewcommand*{\DTLformatphdthesis}{% +\DTLifbibfieldexists{Author}{\DTLformatauthorlist\DTLaddperiod}{}% +\DTLifbibfieldexists{Title}{% +\DTLstartsentencespace +{\em\DTLbibfield{Title}}% +\DTLcheckbibfieldendsperiod{Title}% +\DTLaddperiod}{}% +\DTLifbibfieldexists{Type}{% +\DTLstartsentencespace +\DTLbibfield{Type}% +\DTLcheckbibfieldendsperiod{Type}% +\DTLifanybibfieldexists{School,Address,Month,Year}{% +\DTLaddcomma}{\DTLaddperiod}}{}% +\DTLifbibfieldexists{School}{% +\DTLstartsentencespace +\DTLbibfield{School}% +\DTLcheckbibfieldendsperiod{School}% +\DTLifanybibfieldexists{Address,Month,Year}{% +\DTLaddcomma}{\DTLaddperiod}}{}% +\DTLifbibfieldexists{Address}{% +\DTLstartsentencespace +\DTLbibfield{Address}% +\DTLcheckbibfieldendsperiod{Address}% +\DTLifanybibfieldexists{Month,Year}{% +\DTLaddcomma}{\DTLaddperiod}}{}% +\DTLformatdate +\DTLifanybibfieldexists{Month,Year}{\DTLaddperiod}{}% +\DTLifbibfieldexists{Note}{% +\DTLstartsentencespace +\DTLbibfield{Note}% +\DTLcheckbibfieldendsperiod{Note}% +\DTLaddperiod}{}% +}% +% \end{macrocode} +% The format of a proceedings. +% \begin{macrocode} +\renewcommand*{\DTLformatproceedings}{% +\DTLifbibfieldexists{Editor}{% +\DTLformateditorlist\DTLaddperiod}{% +\DTLifbibfieldexists{Organization}{% +\DTLstartsentencespace +\DTLbibfield{Organization}% +\DTLcheckbibfieldendsperiod{Organization}% +\DTLaddperiod}{}}% +\DTLifbibfieldexists{Title}{% +\DTLstartsentencespace +{\em\DTLbibfield{Title}}% +\DTLcheckbibfieldendsperiod{Title}% +\DTLifanybibfieldexists{Volume,Number,Address,Editor,Publisher,% +Month,Year}{\DTLaddcomma}{\DTLaddperiod}% +}{}% +\DTLformatbvolume +\DTLifbibfieldexists{Volume}{% +\DTLifanybibfieldexists{Number,Address,Editor,Publisher,% +Month,Year}{\DTLaddcomma}{\DTLaddperiod}}{}% +\DTLformatnumberseries +\DTLifbibfieldexists{Number}{% +\DTLifanybibfieldexists{Address,Editor,Publisher,% +Month,Year}{\DTLaddcomma}{\DTLaddperiod}}{}% +\DTLifbibfieldexists{Address}{% +\DTLstartsentencespace +\DTLbibfield{Address}% +\DTLcheckbibfieldendsperiod{Address}% +\DTLifanybibfieldexists{Month,Year}{\DTLaddcomma}{\DTLaddperiod}% +\DTLformatdate +\DTLifanybibfieldexists{Month,Year}{\DTLaddperiod}{}% +\DTLifbibfieldexists{Editor}{\DTLifbibfieldexists{Organization}{% +\DTLstartsentencespace +\DTLbibfield{Organization}% +\DTLcheckbibfieldendsperiod{Organization}% +\DTLifbibfieldexists{Publisher}{% +\DTLaddcomma}{\DTLaddperiod}}{}}{}% +\DTLifbibfieldexists{Publisher}{% +\DTLstartsentencespace +\DTLbibfield{Publisher}% +\DTLcheckbibfieldendsperiod{Publisher}% +\DTLaddperiod +}{}% +}{% no address +\DTLifbibfieldexists{Editor}{% +\DTLifbibfieldexists{Organization}{% +\DTLstartsentencespace +\DTLbibfield{Organization}% +\DTLcheckbibfieldendsperiod{Organization}% +\DTLifanybibfieldexists{Publisher,Month,Year}{% +\DTLaddcomma}{\DTLaddperiod}}{}% +}{}% +\DTLifbibfieldexists{Publisher}{% +\DTLstartsentencespace +\DTLbibfield{Publisher}% +\DTLcheckbibfieldendsperiod{Publisher}% +\DTLifanybibfieldexists{Month,Year}{\DTLaddcomma}{\DTLaddperiod}}{}% +\DTLformatdate +\DTLifanybibfieldexists{Month,Year}{\DTLaddperiod}{}% +}% +\DTLifbibfieldexists{Note}{% +\DTLstartsentencespace +\DTLbibfield{Note}% +\DTLcheckbibfieldendsperiod{Note}% +\DTLaddperiod}{}% +}% +% \end{macrocode} +% The format of a technical report. +% \begin{macrocode} +\renewcommand*{\DTLformattechreport}{% +\DTLifbibfieldexists{Author}{\DTLformatauthorlist\DTLaddperiod}{}% +\DTLifbibfieldexists{Title}{% +\DTLstartsentencespace +\DTLbibfield{Title}% +\DTLcheckbibfieldendsperiod{Title}% +\DTLaddperiod}{}% +\DTLifbibfieldexists{Type}{% +\DTLstartsentencespace +\DTLbibfield{Type}% +\DTLcheckbibfieldendsperiod{Type}% +\DTLifbibfieldexists{Number}{~}{}}{}% +\DTLifbibfieldexists{Number}{% +\DTLstartsentencespace +\DTLbibfield{Number}% +\DTLcheckbibfieldendsperiod{Number}% +}{}% +\DTLifanybibfieldexists{Type,Number}{% +\DTLifanybibfieldexists{Institution,Address,Month,Year}{\DTLaddcomma +}{\DTLaddperiod}}{}% +\DTLifbibfieldexists{Institution}{% +\DTLstartsentencespace +\DTLbibfield{Institution}% +\DTLcheckbibfieldendsperiod{Institution}% +\DTLifanybibfieldexists{Address,Month,Year}{\DTLaddcomma +}{\DTLaddperiod}}{}% +\DTLifbibfieldexists{Address}{% +\DTLstartsentencespace +\DTLbibfield{Address}% +\DTLcheckbibfieldendsperiod{Address}% +\DTLifanybibfieldexists{Month,Year}{\DTLaddcomma +}{\DTLaddperiod}}{}% +\DTLformatdate +\DTLifanybibfieldexists{Month,Year}{\DTLaddperiod}{}% +\DTLifbibfieldexists{Note}{% +\DTLstartsentencespace +\DTLbibfield{Note}% +\DTLcheckbibfieldendsperiod{Note}% +\DTLaddperiod}{}% +}% +% \end{macrocode} +% The format of an unpublished work. +% \begin{macrocode} +\renewcommand*{\DTLformatunpublished}{% +\DTLifbibfieldexists{Author}{\DTLformatauthorlist\DTLaddperiod}{}% +\DTLifbibfieldexists{Title}{% +\DTLstartsentencespace +\DTLbibfield{Title}% +\DTLcheckbibfieldendsperiod{Title}% +\DTLaddperiod}{}% +\DTLifbibfieldexists{Note}{% +\DTLstartsentencespace +\DTLbibfield{Note}% +\DTLcheckbibfieldendsperiod{Note}% +\DTLifanybibfieldexists{Month,Year}{\DTLaddcomma}{\DTLaddperiod}}{}% +\DTLformatdate +\DTLifanybibfieldexists{Month,Year}{\DTLaddperiod}{}% +}% +% \end{macrocode} +% End of `plain' style. +% \begin{macrocode} +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\dtlbst@abbrv} +% Define `abbrv' style. This is similar to `plain' except that +% some of the values are abbreviated +% \begin{macrocode} +\newcommand{\dtlbst@abbrv}{% +% \end{macrocode} +% Base this style on `plain': +% \begin{macrocode} +\dtlbst@plain +% \end{macrocode} +% Sets the author name format. +% \begin{macrocode} +\renewcommand*{\DTLformatauthor}[4]{% +\DTLformatabbrvforenames{##4} +\DTLformatvon{##1}% +\DTLformatsurname{##2}% +\DTLformatjr{##3}} +% \end{macrocode} +% Sets the editor name format. +% \begin{macrocode} +\renewcommand*{\DTLformateditor}[4]{% +\DTLformatabbrvforenames{##4} +\DTLformatvon{##1}% +\DTLformatsurname{##2}% +\DTLformatjr{##3}} +% \end{macrocode} +% Sets the monthname format. +% \begin{macrocode} +\let\DTLmonthname\dtl@abbrvmonthname +% \end{macrocode} +% Sets other predefined names: +% \begin{macrocode} +\renewcommand*{\DTLacmcs}{ACM Comput.\ Surv.} +\renewcommand*{\DTLacta}{Acta Inf.} +\renewcommand*{\DTLcacm}{Commun.\ ACM} +\renewcommand*{\DTLibmjrd}{IBM J.\ Res.\ Dev.} +\renewcommand*{\DTLibmsj}{IBM Syst.~J.} +\renewcommand*{\DTLieeese}{IEEE Trans. Softw.\ Eng.} +\renewcommand*{\DTLieeetc}{IEEE Trans.\ Comput.} +\renewcommand*{\DTLieeetcad}{IEEE Trans.\ Comput.-Aided Design +Integrated Circuits} +\renewcommand*{\DTLipl}{Inf.\ Process.\ Lett.} +\renewcommand*{\DTLjacm}{J.~ACM} +\renewcommand*{\DTLjcss}{J.~Comput.\ Syst.\ Sci.} +\renewcommand*{\DTLscp}{Sci.\ Comput.\ Programming} +\renewcommand*{\DTLsicomp}{SIAM J.~Comput.} +\renewcommand*{\DTLtocs}{ACM Trans.\ Comput.\ Syst.} +\renewcommand*{\DTLtods}{ACM Trans.\ Database Syst.} +\renewcommand*{\DTLtog}{ACM Trans.\ Gr.} +\renewcommand*{\DTLtoms}{ACM Trans.\ Math. Softw.} +\renewcommand*{\DTLtoois}{ACM Trans. Office Inf.\ Syst.} +\renewcommand*{\DTLtoplas}{ACM Trans.\ Prog. Lang.\ Syst.} +\renewcommand*{\DTLtcs}{Theoretical Comput.\ Sci.} +% \end{macrocode} +% End of `abbrv' style. +% \begin{macrocode} +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\dtlbst@alpha} +% Define `alpha' style. This is similar to `plain' except that +% the labels are strings rather than numerical. +% \begin{macrocode} +\newcommand{\dtlbst@alpha}{% +% \end{macrocode} +% Base this style on `plain': +% \begin{macrocode} +\dtlbst@plain +% \end{macrocode} +% Set how to format the entire bibliography: +% \begin{macrocode} +\renewenvironment{DTLthebibliography}[2][\boolean{true}]{% +\dtl@createalphabiblabels{##1}{##2}% +\begin{thebibliography}{\@dtl@widestlabel}% +}{\end{thebibliography}}% +% \end{macrocode} +% Set how to start the bibliography entry: +% \begin{macrocode} +\renewcommand*{\DTLbibitem}{% +\expandafter\bibitem\expandafter + [\csname dtl@biblabel@\DBIBcitekey\endcsname]{\DBIBcitekey}}% +% \end{macrocode} +% \begin{macrocode} +% \end{macrocode} +% End of `alpha' style. +% \begin{macrocode} +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{dtl@createalphabiblabels} +%\begin{definition} +%\cs{dtl@createalphabiblabels}\marg{condition}\marg{db name} +%\end{definition} +% Constructs the alpha style bib labels for the given database. +% (Labels are stored in the control sequence +%\cs{dtl@biblabel@}\meta{citekey}.) This also sets +% \cs{@dtl@widestlabel} to the widest label. +% \begin{macrocode} +\newcommand*{\dtl@createalphabiblabels}[2]{% +\dtl@message{Creating bib labels}% +\begingroup +\gdef\@dtl@widestlabel{}% +\dtl@widest=0pt\relax +\DTLforeachbibentry[#1]{#2}{% +\dtl@message{\DBIBcitekey}% +\DTLifbibfieldexists{Author}{% + \dtl@listgetalphalabel{\@dtl@thislabel}{\@dtl@key@Author}% +}{% +\DTLifbibfieldexists{Editor}{% + \dtl@listgetalphalabel{\@dtl@thislabel}{\@dtl@key@Editor}% + }{% + \DTLifbibfieldexists{Key}{% + \expandafter\dtl@get@firstthree\expandafter + {\@dtl@key@Key}{\@dtl@thislabel}% + }{% + \DTLifbibfieldexists{Organization}{% + \expandafter\dtl@get@firstthree\expandafter + {\@dtl@key@Organization}{\@dtl@thislabel}% + }{% + \expandafter\dtl@get@firstthree\expandafter + {\DBIBentrytype}{\@dtl@thislabel}% + }% + }}}% +\DTLifbibfieldexists{Year}{}{\DTLifbibfieldexists{CrossRef}{% +\DTLgetvalueforkey{\@dtl@key@Year}{Year}{#2}{CiteKey}{% +\@dtl@key@CrossRef}}{}}% +\DTLifbibfieldexists{Year}{% +\expandafter\dtl@get@yearsuffix\expandafter{\@dtl@key@Year}% +\expandafter\toks@\expandafter{\@dtl@thislabel}% +\expandafter\@dtl@toks\expandafter{\@dtl@year}% +\edef\@dtl@thislabel{\the\toks@\the\@dtl@toks}% +}{}% +\let\@dtl@s@thislabel=\@dtl@thislabel +\@onelevel@sanitize\@dtl@s@thislabel +\@ifundefined{c@biblabel@\@dtl@s@thislabel}{% +\newcounter{biblabel@\@dtl@s@thislabel}% +\setcounter{biblabel@\@dtl@s@thislabel}{1}% +\expandafter\edef\csname @dtl@bibfirst@\@dtl@s@thislabel\endcsname{% +\DBIBcitekey}% +\expandafter\global +\expandafter\let\csname dtl@biblabel@\DBIBcitekey\endcsname= + \@dtl@thislabel +}{% +\expandafter\ifnum\csname c@biblabel@\@dtl@s@thislabel\endcsname=1\relax + \expandafter\let\expandafter\@dtl@tmp + \csname @dtl@bibfirst@\@dtl@s@thislabel\endcsname + \expandafter\protected@xdef\csname dtl@biblabel@\@dtl@tmp\endcsname{% + \@dtl@thislabel a}% +\fi +\stepcounter{biblabel@\@dtl@s@thislabel}% +\expandafter\protected@xdef\csname dtl@biblabel@\DBIBcitekey\endcsname{% + \@dtl@thislabel\alph{biblabel@\@dtl@s@thislabel}}% +}% +\settowidth{\dtl@tmplength}{% + \csname dtl@biblabel@\DBIBcitekey\endcsname}% +\ifdim\dtl@tmplength>\dtl@widest + \dtl@widest=\dtl@tmplength + \expandafter\global\expandafter\let\expandafter\@dtl@widestlabel + \expandafter=\csname dtl@biblabel@\DBIBcitekey\endcsname +\fi +}% +\endgroup +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\dtl@listgetalphalabel} +% Determine the alpha style label from a list of authors/editors +% (the first argument must be a control sequence (in which the +% label is stored), the second argument must be the list of names.) +% \begin{macrocode} +\newcommand*{\dtl@listgetalphalabel}[2]{% +\@dtl@authorcount=0\relax +\@for\@dtl@author:=#2\do{% +\advance\@dtl@authorcount by 1\relax}% +\ifnum\@dtl@authorcount=1\relax + \expandafter\dtl@getsinglealphalabel#2{#1}\relax +\else + {% + \xdef#1{}% + \@dtl@tmpcount=0\relax + \def\DTLafterinitials{}\def\DTLbetweeninitials{}% + \def\DTLafterinitialbeforehyphen{}\def\DTLinitialhyphen{}% + \@for\@dtl@author:=#2\do{% + \expandafter\dtl@getauthorinitial\@dtl@author + \expandafter\toks@\expandafter{\@dtl@tmp}% + \expandafter\@dtl@toks\expandafter{#1}% + \xdef#1{\the\@dtl@toks\the\toks@}% + \advance\@dtl@tmpcount by 1\relax + \ifnum\@dtl@tmpcount>2\relax\@endfortrue\fi + }}% +\fi +} +% \end{macrocode} +%\end{macro} +% Get author's initial (stores in \cs{@dtl@tmp}): +% \begin{macrocode} +\newcommand*{\dtl@getauthorinitial}[4]{% +\def\@dtl@vonpart{#1}% +\ifx\@dtl@vonpart\@empty + \DTLstoreinitials{#2}{\@dtl@tmp}% +\else + \DTLstoreinitials{#1 #2}{\@dtl@tmp}% +\fi} +% \end{macrocode} +% Get label for single author (last argument is control sequence +% in which to store the label): +% \begin{macrocode} +\newcommand*{\dtl@getsinglealphalabel}[5]{% +\def\@dtl@vonpart{#1}% +\ifx\@dtl@vonpart\@empty + \DTLifSubString{#2}{-}{% + {\def\DTLafterinitials{}\def\DTLbetweeninitials{}% + \def\DTLafterinitialbeforehyphen{}% + \def\DTLinitialhyphen{}% + \DTLstoreinitials{#2}{\@dtl@tmp}\global\let#5=\@dtl@tmp}% + }{% + \dtl@getfirstthree{#5}#2{}{}{}{}\@nil + } +\else + {\def\DTLafterinitials{}\def\DTLbetweeninitials{}% + \def\DTLafterinitialbeforehyphen{}% + \def\DTLinitialhyphen{}% + \DTLstoreinitials{#1 #2}{\@dtl@tmp}\global\let#5=\@dtl@tmp}% +\fi +} +% \end{macrocode} +%Get first three letters from the given string: +% \begin{macrocode} +\def\dtl@getfirstthree#1#2#3#4#5\@nil{% + \def#1{#2#3#4}% +} +\newcommand*{\dtl@get@firstthree}[2]{% +\dtl@getfirstthree#2#1{}{}{}{}{}\@nil} +% \end{macrocode} +%Get year suffix: +% \begin{macrocode} +\newcommand*{\dtl@get@yearsuffix}[1]{% +\dtl@getyearsuffix#1\@nil\relax\relax} + +\def\dtl@getyearsuffix#1#2#3{% +\def\@dtl@argi{#1}\def\@dtl@argii{#2}% +\def\@dtl@argiii{#3}% +\ifx\@dtl@argi\@nnil + \def\@dtl@year{}% + \let\@dtl@donext=\relax +\else + \ifx\@dtl@argii\@nnil + \dtl@ifsingle{#1}{% + \def\@dtl@year{#1}% + \let\@dtl@donext=\relax + }{% + \def\@dtl@donext{\dtl@getyearsuffix#1#2#3}% + }% + \else + \ifx\@dtl@argiii\@nnil + \dtl@ifsingle{#1}{% + \dtl@ifsingle{#2}{% + \def\@dtl@year{#1#2}% + \let\@dtl@donext=\relax + }{% + \def\@dtl@donext{\dtl@getyearsuffix#2#3}% + }% + }{% + \def\@dtl@donext{\dtl@getyearsuffix#2#3}% + }% + \else + \def\@dtl@donext{\dtl@getyearsuffix{#2}{#3}}% + \fi + \fi +\fi +\@dtl@donext +} +% \end{macrocode} +% +%\begin{macro}{\DTLbibliographystyle} +%\begin{definition} +%\cs{DTLbibliographystyle}\marg{style} +%\end{definition} +% Sets the bibliography style. +% \begin{macrocode} +\newcommand*{\DTLbibliographystyle}[1]{% +\@ifundefined{dtlbst@#1}{\PackageError{databib}{Unknown +bibliography style `#1'}{}}{\csname dtlbst@#1\endcsname}} +% \end{macrocode} +%\end{macro} +%Set the default bibliography style: +% \begin{macrocode} +\DTLbibliographystyle{\dtlbib@style} +% \end{macrocode} +%\iffalse +% \begin{macrocode} +%</databib.sty> +% \end{macrocode} +%\fi +%\iffalse +% \begin{macrocode} +%<*databib.bst> +% \end{macrocode} +%\fi +%\iffalse +% \begin{macrocode} +% \begin{macrocode} +% Bibliography style `databib' +% This style is provided for use with the databib package. + +ENTRY + { address + author + booktitle + chapter + edition + editor + howpublished + institution + journal + key + month + note + number + organization + pages + publisher + school + series + title + type + volume + year + isbn + doi + pubmed + url + abstract + } + {} + { label } + +INTEGERS { output.state before.all mid.sentence after.sentence after.block } + +FUNCTION {init.state.consts} +{ #0 'before.all := + #1 'mid.sentence := + #2 'after.sentence := + #3 'after.block := +} + +STRINGS { s t } + +FUNCTION {output.nonnull} +{ 's := +% output.state mid.sentence = +% { "%" * write$ +% newline$ +% } +% { output.state after.block = +% { add.period$ write$ +% newline$ +% } + %{ + output.state before.all = + { + "%" * write$ + newline$ + } + { newline$ + %add.period$ " " * write$ + } + if$ +% } + % if$ + % mid.sentence 'output.state := + % } + %if$ + s +} + +FUNCTION {output} +{ duplicate$ empty$ + 'pop$ + 'output.nonnull + if$ +} + +FUNCTION {output.check} +{ 't := + duplicate$ empty$ + { pop$ "empty " t * " in " * cite$ * warning$ } + { + output.nonnull + } + if$ +} + +FUNCTION {output.bibitem} +{ "\DTLnewbibrow" write$ + newline$ + "\DTLnewbibitem {CiteKey}{" write$ + cite$ write$ + "}%" write$ + newline$ + "" + before.all 'output.state := +} + +FUNCTION {fin.entry} +{ "%" * + write$ + newline$ +} + +FUNCTION {new.block} +{ output.state before.all = + 'skip$ + { after.block 'output.state := } + if$ +} + +FUNCTION {new.sentence} +{ output.state after.block = + 'skip$ + { output.state before.all = + 'skip$ + { after.sentence 'output.state := } + if$ + } + if$ +} + +FUNCTION {not} +{ { #0 } + { #1 } + if$ +} + +FUNCTION {and} +{ 'skip$ + { pop$ #0 } + if$ +} + +FUNCTION {or} +{ { pop$ #1 } + 'skip$ + if$ +} + +FUNCTION {new.block.checka} +{ empty$ + 'skip$ + 'new.block + if$ +} + +FUNCTION {new.block.checkb} +{ empty$ + swap$ empty$ + and + 'skip$ + 'new.block + if$ +} + +FUNCTION {new.sentence.checka} +{ empty$ + 'skip$ + 'new.sentence + if$ +} + +FUNCTION {new.sentence.checkb} +{ empty$ + swap$ empty$ + and + 'skip$ + 'new.sentence + if$ +} + +FUNCTION {field.or.null} +{ duplicate$ empty$ + { pop$ "" } + 'skip$ + if$ +} + +FUNCTION {emphasize} +{ duplicate$ empty$ + { pop$ "" } + { "{\em " swap$ * "}" * } + if$ +} + +FUNCTION {group} +{ duplicate$ empty$ + { pop$ "" } + { "{" swap$ * "}" * } + if$ +} + +INTEGERS { nameptr namesleft numnames } + +FUNCTION {format.names} +{ + 's := + #1 'nameptr := + s num.names$ 'numnames := + numnames 'namesleft := + { namesleft #0 > } + { + %s nameptr "{vv,}{ll,}{jj,}{ff}" format.name$ 't := + "{" * + s nameptr "{vv}" format.name$ 't := + t * "}" * + "{" * + s nameptr "{ll}" format.name$ 't := + t * "}{" * + s nameptr "{jj}" format.name$ 't := + t * "}" * + "{" * + s nameptr "{ff}" format.name$ 't := + t * "}" * + s nameptr "" format.name$ 't := + namesleft #1 > + { "," * } + { } + if$ + nameptr #1 > + { + t * + } + 't + if$ + nameptr #1 + 'nameptr := + namesleft #1 - 'namesleft := + } + while$ + "}" * +} + +FUNCTION {format.authors} +{ + author empty$ + { "" } + { author + "\DTLnewbibitem {Author}{" write$ + format.names } + if$ +} + +FUNCTION {format.editors} +{ editor empty$ + { "" } + { editor + "\DTLnewbibitem {Editor}{" write$ + format.names + } + if$ +} + +FUNCTION {format.title} +{ title empty$ + { "" } + { + "\DTLnewbibitem {Title}" + title "t" change.case$ group * + } + if$ +} + +FUNCTION {format.howpublished} +{ howpublished empty$ + { "" } + { + howpublished + "\DTLnewbibitem {HowPublished}" swap$ group * + } + if$ +} + +FUNCTION {format.organization} +{ organization empty$ + { "" } + { + organization + "\DTLnewbibitem {Organization}" swap$ group * + } + if$ +} + +FUNCTION {format.institution} +{ institution empty$ + { "" } + { + institution + "\DTLnewbibitem {Institution}" swap$ group * + } + if$ +} + +FUNCTION {format.key} +{ key empty$ + { "" } + { + key + "\DTLnewbibitem {Key}" swap$ group * + } + if$ +} + +FUNCTION {format.note} +{ note empty$ + { "" } + { + note + "\DTLnewbibitem {Note}" swap$ group * + } + if$ +} + +FUNCTION {format.isbn} +{ isbn empty$ + { "" } + { + isbn + "\DTLnewbibitem {ISBN}" swap$ group * + } + if$ +} + +FUNCTION {format.doi} +{ doi empty$ + { "" } + { + doi + "\DTLnewbibitem {DOI}" swap$ group * + } + if$ +} + +FUNCTION {format.pubmed} +{ pubmed empty$ + { "" } + { + pubmed + "\DTLnewbibitem {PubMed}" swap$ group * + } + if$ +} + +FUNCTION {format.abstract} +{ abstract empty$ + { "" } + { + abstract + "\DTLnewbibitem {Abstract}" swap$ group * + } + if$ +} + +FUNCTION {format.url} +{ url empty$ + { "" } + { + url + "\DTLnewbibitem {Url}" swap$ group * + } + if$ +} + +FUNCTION {format.address} +{ address empty$ + { "" } + { + address + "\DTLnewbibitem {Address}" swap$ group * + } + if$ +} + +FUNCTION {format.school} +{ school empty$ + { "" } + { + school + "\DTLnewbibitem {School}" swap$ group * + } + if$ +} + +FUNCTION {format.publisher} +{ publisher empty$ + { "" } + { + publisher + "\DTLnewbibitem {Publisher}" swap$ group * + } + if$ +} + +FUNCTION {n.dashify} +{ 't := + "" + { t empty$ not } + { t #1 #1 substring$ "-" = + { t #1 #2 substring$ "--" = not + { "--" * + t #2 global.max$ substring$ 't := + } + { { t #1 #1 substring$ "-" = } + { "-" * + t #2 global.max$ substring$ 't := + } + while$ + } + if$ + } + { t #1 #1 substring$ * + t #2 global.max$ substring$ 't := + } + if$ + } + while$ +} + +FUNCTION {format.date} +{ year empty$ + { month empty$ + { "" } + { "there's a month but no year in " cite$ * warning$ + "\DTLnewbibitem {Month}" * + month group + } + if$ + } + { month empty$ + { } + { "\DTLnewbibitem {Month}{" * month * "}" * } + if$ + "\DTLnewbibitem {Year}{" * year * "}" + } + if$ +} + +FUNCTION {format.btitle} +{ title + "\DTLnewbibitem {Title}{" swap$ * + "}" * +} + +FUNCTION {tie.or.space.connect} +{ duplicate$ text.length$ #3 < + { "~" } + { " " } + if$ + swap$ * * +} + +FUNCTION {either.or.check} +{ empty$ + 'pop$ + { "can't use both " swap$ * " fields in " * cite$ * warning$ } + if$ +} + +FUNCTION {format.bvolume} +{ volume empty$ + { "" } + { + "\DTLnewbibitem {Volume}{" volume * "}" * + series empty$ + 'skip$ + { + "\DTLnewbibitem {Series}" * series group * + } + if$ + "volume and number" number either.or.check + } + if$ +} + +FUNCTION {format.number.series} +{ volume empty$ + { number empty$ + { + %series field.or.null group + series empty$ + { "" } + { "\DTLnewbibitem {Series}" * series group } + if$ + } + { + "\DTLnewbibitem {Number}" number group * + series empty$ + { "there's a number but no series in " cite$ * warning$ } + { "\DTLnewbibitem {Series}{" * series * "}" * } + if$ + } + if$ + } + { "" } + if$ +} + +FUNCTION {format.edition} +{ edition empty$ + { "" } + { + "\DTLnewbibitem {Edition}" + edition "l" change.case$ group * + } + if$ +} + +INTEGERS { multiresult } + +FUNCTION {multi.page.check} +{ 't := + #0 'multiresult := + { multiresult not + t empty$ not + and + } + { t #1 #1 substring$ + duplicate$ "-" = + swap$ duplicate$ "," = + swap$ "+" = + or or + { #1 'multiresult := } + { t #2 global.max$ substring$ 't := } + if$ + } + while$ + multiresult +} + +FUNCTION {format.pages} +{ pages empty$ + { "" } + { pages multi.page.check + { "\DTLnewbibitem {Pages}" pages n.dashify + group * } + { "\DTLnewbibitem {Pages}" pages + group *} + if$ + } + if$ +} + +FUNCTION {format.vol.num.pages} +{ + volume empty$ + { "" } + { + "\DTLnewbibitem {Volume}{" volume * "}" * + } + if$ + number empty$ + 'skip$ + { "\DTLnewbibitem {Number}{" number * "}\relax " * * + volume empty$ + { "there's a number but no volume in " cite$ * warning$ } + 'skip$ + if$ + } + if$ + pages empty$ + 'skip$ + { duplicate$ empty$ + { pop$ format.pages } + { "\DTLnewbibitem {Pages}" * pages n.dashify group * } + if$ + } + if$ +} + +FUNCTION {format.chapter.pages} +{ chapter empty$ + 'format.pages + { type empty$ + { "\DTLnewbibitem {Type}{chapter}" } + { "\DTLnewbibitem {Type}" type "l" change.case$ group *} + if$ + "\DTLnewbibitem {Chapter}{" * chapter * "}" * + pages empty$ + 'skip$ + { format.pages * } + if$ + } + if$ +} + +FUNCTION {format.in.ed.booktitle} +{ booktitle empty$ + { "" } + { + "\DTLnewbibitem {BookTitle}" booktitle group * + editor empty$ + {} + { + "\DTLnewbibitem {Editor}{" * + editor format.names * + } + if$ + } + if$ +} + +FUNCTION {empty.misc.check} +{ author empty$ title empty$ howpublished empty$ + month empty$ year empty$ note empty$ + and and and and and + { "all relevant fields are empty in " cite$ * warning$ } + 'skip$ + if$ +} + +FUNCTION {format.thesis.type} +{ type empty$ + 'skip$ + { pop$ + type "t" change.case$ + "\DTLnewbibitem {Type}" swap$ group * + } + if$ +} + +FUNCTION {format.tr.number} +{ + type empty$ + { "\techreportname " } + 'type + if$ + number empty$ + { "t" change.case$ "\DTLnewbibitem {Type}" swap$ group *} + { "\DTLnewbibitem {Type}" swap$ group * + "\DTLnewbibitem {Number}" * + number group * } + if$ +} + +FUNCTION {format.article.crossref} +{ key empty$ + { journal empty$ + { "need key or journal for " cite$ * " to crossref " * crossref * + warning$ + "" + } + { + "\DTLnewbibitem {Journal}" journal group * + } + if$ + } + { + "" + } + if$ + "\DTLnewbibitem {CrossRef}{" * crossref * "}" * +} + +FUNCTION {format.crossref.editor} +{ format.editors +% editor #1 "{vv~}{ll}" format.name$ +% editor num.names$ duplicate$ +% #2 > +% { pop$ " et~al." * } +% { #2 < +% 'skip$ +% { editor #2 "{ff }{vv }{ll}{ jj}" format.name$ "others" = +% { " et~al." * } +% { " and " * editor #2 "{vv~}{ll}" format.name$ * } +% if$ +% } +% if$ +% } +% if$ +} + +FUNCTION {format.book.crossref} +{ volume empty$ + { "empty volume in " cite$ * "'s crossref of " * crossref * warning$ + } + { + "\DTLnewbibitem {Volume}" + volume group * + } + if$ + editor empty$ + editor field.or.null author field.or.null = + or + { key empty$ + { series empty$ + { "need editor, key, or series for " cite$ * " to crossref " * + crossref * warning$ + "" * + } + { + "\DTLnewbibitem {Series}{" * series * + "}" * + } + if$ + } + { "" + } + if$ + } + { + format.crossref.editor * + } + if$ + "\DTLnewbibitem {CrossRef}{" * crossref * "}" * +} + +FUNCTION {format.incoll.inproc.crossref} +{ editor empty$ + editor field.or.null author field.or.null = + or + { key empty$ + { booktitle empty$ + { "need editor, key, or booktitle for " cite$ * " to crossref " * + crossref * warning$ + "" + } + { "\DTLnewbibitem {BookTitle}{" booktitle * "}" * } + if$ + } + { "" } + if$ + } + { + "\DTLnewbibitem {Editor}{" * + editor format.names + } + if$ + "\DTLnewbibitem {CrossRef}{" * crossref * "}" * +} + +FUNCTION {article} +{ output.bibitem + "\DTLnewbibitem {EntryType}{article}%" write$ + newline$ + format.authors "author" + output.check + format.title "title" output.check + new.block + crossref missing$ + { + "\DTLnewbibitem {Journal}" * + journal group "journal" output.check + format.vol.num.pages output + format.date "year" output.check + } + { format.article.crossref output.nonnull + format.pages output + } + if$ + new.block + format.key output + format.note output + format.isbn output + format.doi output + format.pubmed output + format.url output + format.abstract output + fin.entry +} + +FUNCTION {book} +{ output.bibitem + "\DTLnewbibitem {EntryType}{book}%" write$ + newline$ + author empty$ + { format.editors "author and editor" output.check } + { format.authors output.nonnull + crossref missing$ + { "author and editor" editor either.or.check + } + 'skip$ + if$ + } + if$ + new.block + format.btitle "title" output.check + crossref missing$ + { format.bvolume output + new.block + format.number.series output + %new.sentence + format.publisher "publisher" output.check + format.address output + } + { new.block + format.book.crossref output.nonnull + } + if$ + format.edition output + format.date "year" output.check + new.block + format.key output + format.note output + format.isbn output + format.doi output + format.pubmed output + format.url output + format.abstract output + fin.entry +} + +FUNCTION {booklet} +{ output.bibitem + "\DTLnewbibitem {EntryType}{booklet}%" write$ + newline$ + format.authors output + new.block + format.title "title" output.check + howpublished address new.block.checkb + format.howpublished output + format.address output + format.date output + new.block + format.key output + format.note output + format.isbn output + format.doi output + format.pubmed output + format.url output + format.abstract output + fin.entry +} + +FUNCTION {inbook} +{ output.bibitem + "\DTLnewbibitem {EntryType}{inbook}%" write$ + newline$ + author empty$ + { format.editors "author and editor" output.check } + { format.authors output.nonnull + crossref missing$ + { "author and editor" editor either.or.check } + 'skip$ + if$ + } + if$ + new.block + format.btitle "title" output.check + crossref missing$ + { format.bvolume output + format.chapter.pages "chapter and pages" output.check + new.block + format.number.series output + new.sentence + format.publisher "publisher" output.check + format.address output + } + { format.chapter.pages "chapter and pages" output.check + new.block + format.book.crossref output.nonnull + } + if$ + format.edition output + format.date "year" output.check + new.block + format.key output + format.note output + format.isbn output + format.doi output + format.pubmed output + format.url output + format.abstract output + fin.entry +} + +FUNCTION {incollection} +{ output.bibitem + "\DTLnewbibitem {EntryType}{incollection}%" write$ + newline$ + format.authors "author" output.check + format.title "title" output.check + crossref missing$ + { format.in.ed.booktitle "booktitle" output.check + format.bvolume output + format.number.series output + format.chapter.pages output + new.sentence + format.publisher "publisher" output.check + format.address output + format.edition output + format.date "year" output.check + } + { format.incoll.inproc.crossref output.nonnull + format.chapter.pages output + } + if$ + format.key output + format.note output + format.isbn output + format.doi output + format.pubmed output + format.url output + format.abstract output + fin.entry +} + +FUNCTION {inproceedings} +{ output.bibitem + "\DTLnewbibitem {EntryType}{inproceedings}%" write$ + newline$ + format.authors "author" output.check + format.title "title" output.check + crossref missing$ + { format.in.ed.booktitle "booktitle" output.check + format.bvolume output + format.number.series output + format.pages output + address empty$ + { %organization publisher new.sentence.checkb + format.organization write$ + format.publisher output + } + { format.address write$ + new.sentence + format.organization output + format.publisher output + } + if$ + format.date "year" output.check + } + { + format.incoll.inproc.crossref output.nonnull + format.pages output + } + if$ + format.key output + format.note output + format.isbn output + format.doi output + format.pubmed output + format.url output + format.abstract output + fin.entry +} + +FUNCTION {conference} { inproceedings } + +FUNCTION {manual} +{ output.bibitem + "\DTLnewbibitem {EntryType}{manual}%" write$ + newline$ + author empty$ + { organization empty$ + 'skip$ + { format.organization output + format.address output + } + if$ + } + { format.authors output } + if$ + new.block + format.btitle "title" output.check + author empty$ + { organization empty$ + { address new.block.checka + address output + } + 'skip$ + if$ + } + { %organization address new.block.checkb + format.organization output + format.address output + } + if$ + format.edition output + format.date output + new.block + format.key output + format.note output + format.isbn output + format.doi output + format.pubmed output + format.url output + format.abstract output + fin.entry +} + +FUNCTION {mastersthesis} +{ output.bibitem + "\DTLnewbibitem {EntryType}{mastersthesis}%" write$ + newline$ + format.authors "author" output.check + new.block + format.title "title" output.check + new.block + "\DTLnewbibitem {Type}{\mscthesisname }" + format.thesis.type output.nonnull + format.school "school" output.check + format.address output + format.date "year" output.check + new.block + format.key output + format.note output + format.isbn output + format.doi output + format.pubmed output + format.url output + format.abstract output + fin.entry +} + +FUNCTION {misc} +{ output.bibitem + "\DTLnewbibitem {EntryType}{misc}%" write$ + newline$ + format.authors output + title howpublished new.block.checkb + format.title output + %howpublished new.block.checka + format.howpublished output + format.date output + new.block + format.key output + format.note output + format.isbn output + format.doi output + format.pubmed output + format.url output + format.abstract output + fin.entry + empty.misc.check +} + +FUNCTION {phdthesis} +{ output.bibitem + "\DTLnewbibitem {EntryType}{phdthesis}%" write$ + newline$ + format.authors "author" output.check + new.block + format.btitle "title" output.check + new.block + "\DTLnewbibitem {Type}{\phdthesisname }" + format.thesis.type output.nonnull + format.school "school" output.check + format.address output + format.date "year" output.check + new.block + format.key output + format.note output + format.isbn output + format.doi output + format.pubmed output + format.url output + format.abstract output + fin.entry +} + +FUNCTION {proceedings} +{ output.bibitem + "\DTLnewbibitem {EntryType}{proceedings}%" write$ + newline$ + editor empty$ + { format.organization output } + { format.editors output.nonnull } + if$ + new.block + format.btitle "title" output.check + format.bvolume output + format.number.series output + address empty$ + { editor empty$ + { publisher new.sentence.checka } + { organization publisher new.sentence.checkb + format.organization output + } + if$ + format.publisher output + format.date "year" output.check + } + { format.address output + format.date "year" output.check + new.sentence + editor empty$ + 'skip$ + { format.organization output } + if$ + format.publisher output + } + if$ + new.block + format.key output + format.note output + format.isbn output + format.doi output + format.pubmed output + format.url output + format.abstract output + fin.entry +} + +FUNCTION {techreport} +{ output.bibitem + "\DTLnewbibitem {EntryType}{techreport}%" write$ + newline$ + format.authors "author" output.check + new.block + format.title "title" output.check + new.block + format.tr.number output.nonnull + format.institution "institution" output.check + format.address output + format.date "year" output.check + new.block + format.key output + format.note output + format.isbn output + format.doi output + format.pubmed output + format.url output + format.abstract output + fin.entry +} + +FUNCTION {unpublished} +{ output.bibitem + "\DTLnewbibitem {EntryType}{unpublished}%" write$ + newline$ + format.authors "author" output.check + new.block + format.title "title" output.check + new.block + format.key output + format.note output + format.isbn output + format.doi output + format.pubmed output + format.url output + format.abstract output + format.date output + fin.entry +} + +FUNCTION {default.type} { misc } + +MACRO {jan} {"\DTLmonthname{01}"} + +MACRO {feb} {"\DTLmonthname{02}"} + +MACRO {mar} {"\DTLmonthname{03}"} + +MACRO {apr} {"\DTLmonthname{04}"} + +MACRO {may} {"\DTLmonthname{05}"} + +MACRO {jun} {"\DTLmonthname{06}"} + +MACRO {jul} {"\DTLmonthname{07}"} + +MACRO {aug} {"\DTLmonthname{08}"} + +MACRO {sep} {"\DTLmonthname{09}"} + +MACRO {oct} {"\DTLmonthname{10}"} + +MACRO {nov} {"\DTLmonthname{11}"} + +MACRO {dec} {"\DTLmonthname{12}"} + +MACRO {acmcs} {"\DTLacmcs "} + +MACRO {acta} {"\DTLacta "} + +MACRO {cacm} {"\DTLcacm "} + +MACRO {ibmjrd} {"\DTLibmjrd "} + +MACRO {ibmsj} {"\DTLibmsj "} + +MACRO {ieeese} {"\DTLieeese "} + +MACRO {ieeetc} {"\DTLieeetc "} + +MACRO {ieeetcad} {"\DTLieeetcad "} + +MACRO {ipl} {"\DTLipl "} + +MACRO {jacm} {"\DTLjacm "} + +MACRO {jcss} {"\DTLjcss "} + +MACRO {scp} {"\DTLscp "} + +MACRO {sicomp} {"\DTLsicomp "} + +MACRO {tocs} {"\DTLtocs "} + +MACRO {tods} {"\DTLtods "} + +MACRO {tog} {"\DTLtog "} + +MACRO {toms} {"\DTLtoms "} + +MACRO {toois} {"\DTLtoois "} + +MACRO {toplas} {"\DTLtoplas "} + +MACRO {tcs} {"\DTLtcs "} + +READ + +STRINGS { longest.label } + +INTEGERS { number.label longest.label.width } + +FUNCTION {initialize.longest.label} +{ "" 'longest.label := + #1 'number.label := + #0 'longest.label.width := +} + +FUNCTION {longest.label.pass} +{ number.label int.to.str$ 'label := + number.label #1 + 'number.label := + label width$ longest.label.width > + { label 'longest.label := + label width$ 'longest.label.width := + } + 'skip$ + if$ +} + +EXECUTE {initialize.longest.label} + +ITERATE {longest.label.pass} + +FUNCTION {begin.bib} +{ preamble$ empty$ + 'skip$ + { preamble$ write$ newline$ } + if$ +} + +EXECUTE {begin.bib} + +EXECUTE {init.state.consts} + +ITERATE {call.type$} + +FUNCTION {end.bib} +{ +} + +EXECUTE {end.bib} +% \end{macrocode} +% \end{macrocode} +%\fi +%\iffalse +% \begin{macrocode} +%</databib.bst> +% \end{macrocode} +%\fi +%\Finale +\endinput |