From d5ef93ccfdd8ddb5ee3d5a41434e0aec04df8fa0 Mon Sep 17 00:00:00 2001 From: Karl Berry Date: Mon, 23 Jul 2012 21:55:18 +0000 Subject: datatool 2.10 (23jul12) git-svn-id: svn://tug.org/texlive/trunk@27115 c570f23f-e606-0410-a88d-b1316a301751 --- .../texmf-dist/source/latex/datatool/datatool.dtx | 39173 ++++++++----------- .../texmf-dist/source/latex/datatool/datatool.ins | 25 +- 2 files changed, 16384 insertions(+), 22814 deletions(-) (limited to 'Master/texmf-dist/source') diff --git a/Master/texmf-dist/source/latex/datatool/datatool.dtx b/Master/texmf-dist/source/latex/datatool/datatool.dtx index fcae77779b6..48dbc515cb4 100644 --- a/Master/texmf-dist/source/latex/datatool/datatool.dtx +++ b/Master/texmf-dist/source/latex/datatool/datatool.dtx @@ -1,22 +1,22 @@ %\iffalse % datatool.dtx generated using makedtx version 0.94b (c) Nicola Talbot % Command line args: -% -macrocode "databib.bst" -% -src "datatool\.sty\Z=>datatool.sty" -% -src "datapie\.sty\Z=>datapie.sty" -% -src "dataplot\.sty\Z=>dataplot.sty" -% -src "databar\.sty\Z=>databar.sty" -% -src "databib\.sty\Z=>databib.sty" -% -src "databib\.bst\Z=>databib.bst" -% -src "person\.sty\Z=>person.sty" -% -author "Nicola Talbot" -% -dir "source" -% -setambles ".*\.bst=>\nopreamble\usepreamble\defaultpreamble\nopostamble" -% -comment "databib.bst" +% -macrocode "databib\.bst" +% -src "datatool-base.sty\Z=>datatool-base.sty" +% -src "datatool-fp.sty\Z=>datatool-fp.sty" +% -src "datatool-pgfmath.sty\Z=>datatool-pgfmath.sty" +% -src "datatool.sty\Z=>datatool.sty" +% -src "databib.sty\Z=>databib.sty" +% -src "databar.sty\Z=>databar.sty" +% -src "datapie.sty\Z=>datapie.sty" +% -src "dataplot.sty\Z=>dataplot.sty" +% -src "person.sty\Z=>person.sty" +% -src "databib.bst\Z=>databib.bst" % -doc "datatool-manual.tex" -% -codetitle "datatool.sty" +% -author "Nicola Talbot" +% -codetitle "" % datatool -% Created on 2009/11/15 15:10 +% Created on 2012/7/19 16:34 %\fi %\iffalse %<*package> @@ -39,139 +39,35 @@ %\fi % \iffalse % Doc-Source file to use with LaTeX2e -% Copyright (C) 2009 Nicola Talbot, all rights reserved. +% Copyright (C) 2012 Nicola Talbot, all rights reserved. % \fi % \iffalse %<*driver> -\documentclass[a4paper]{ltxdoc} -\usepackage{dox} -\usepackage{ifthen} -\usepackage[verbose=false]{datatool} -\usepackage{datapie,databar,databib,person} -\usepackage{textcomp} -\usepackage{graphicx} -\usepackage{colortbl} -\usepackage{cmap} -\usepackage[T1]{fontenc} +\documentclass[report]{nlctdoc} + +\iffalse +datatool-manual.tex is a stub file used by makedtx to create +datatool.dtx +\fi + +\usepackage{datatool} \usepackage[utf8]{inputenc} -\usepackage{caption} +\usepackage[T1]{fontenc} \usepackage[colorlinks, bookmarks, hyperindex=false, - pdfauthor={Nicola L.C. Talbot}, + 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. +\doxitem{Counter}{counter}{counters} +\doxitem{Option}{option}{package options} -\renewcommand{\usage}[1]{\textit{\hyperpage{#1}}} -\renewcommand{\main}[1]{\hyperpage{#1}} -\newcommand{\see}[2]{\emph{see} #1} -\makeatletter -\def\index@prologue{\section*{Index}} +\CheckSum{16856} - % 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{16375} - -\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 - -\newsavebox\defsbox -\newlength\defwidth -\newenvironment{definition}[1][]{% -\def\defarg{#1}% -\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 -\defarg\fcolorbox{black}{defbackground}{\usebox\defsbox}% -\vskip10pt -\noindent -\ignorespacesafterend -} - -\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 -} - -\doxitem{Counter}{counter}{counters} - -\newcommand*{\ctrfmt}[1]{\texttt{#1}} -\newcommand*{\ctr}[1]{\ctrfmt{#1}\SpecialMainCounterIndex{#1}} -\newcommand*{\desctr}[1]{\ctrfmt{#1}\DescribeCounter{#1}} - -\newcommand*{\ics}[1]{\cs{#1}\SpecialMainIndex{#1}} - -\newcommand*{\pkgopt}[2][datatool]{\textsf{#2}\index -{#1 package options=\textsf{#1} package options>#2=\textsf{#2}|hyperpage}} - -\newcommand*{\cmdopt}[2]{\textsf{#2}\index{#1 options=\cs{#1} -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} - +\setcounter{IndexColumns}{2} \begin{document} \DocInput{datatool.dtx} @@ -179,26294 +75,19961 @@ options>#2=\textsf{#2}|hyperpage}} % %\fi %\MakeShortVerb{"} -%\DeleteShortVerb{\|} % -% \title{datatool v 2.03: Databases and data manipulation} -% \author{Nicola L.C. Talbot\\[10pt] +%\title{Documented Code for datatool v2.10} +%\author{Nicola L. C. Talbot\\[10pt] %School of Computing Sciences\\ %University of East Anglia\\ %Norwich. Norfolk\\ -%NR4 7TJ. United Kingdom.\\ +%NR4 7TJ. United Kingdom\\ %\url{http://theoval.cmp.uea.ac.uk/~nlct/}} % -% \date{15th November 2009} -% \maketitle +%\date{2012-07-18} +%\maketitle +% +%\pagenumbering{roman} % -%\pdfbookmark[1]{Contents}{contents} +%This is the documented code for the \styfmt{datatool} bundle. See +%\url{datatool-user.pdf} for the main user manual. +% +%\clearpage +%\pdfbookmark[0]{Contents}{contents} %\tableofcontents -%\pdfbookmark[1]{List of Examples}{examples} -%\listofexamples -%\pdfbookmark[1]{List of Figures}{figures} -%\listoffigures -%\pdfbookmark[1]{List of Tables}{tables} -%\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{pgf} manual provides a more in-depth -%discussion on the matter.) -% -%The \sty{dataplot} package can be used to convert a database into -%a two dimensional plot using markers and/or lines. Three dimensional -%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 -%\begin{definition}[\DescribeMacro{\DTLsetnumberchars}]% -%\cs{DTLsetnumberchars}\marg{number group character}\marg{decimal character} -%\end{definition} -%Note that scientific notation is not supported, and the number group -%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 -%\begin{definition}[\DescribeMacro{\DTLnewcurrencysymbol}]% -%\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: -%\begin{definition}[\DescribeMacro{\DTLifint}]% -%\cs{DTLifint}\marg{text}\marg{true part}\marg{false part} -%\end{definition} -%If \meta{text} is an integer then do \meta{true part}, otherwise -%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. +%\pagenumbering{arabic} % -%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}. +%\StopEventually{% +% \clearpage\phantomsection +% \addcontentsline{toc}{chapter}{Index}\PrintIndex +% \clearpage\phantomsection +% \addcontentsline{toc}{chapter}{History}\PrintChanges +%} % -%\begin{definition}[\DescribeMacro{\DTLifreal}]% -%\cs{DTLifreal}\marg{text}\marg{true part}\marg{false part} -%\end{definition} -%If \meta{text} is a real number then do \meta{true part}, otherwise -%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}. +%\iffalse +% \begin{macrocode} +%<*datatool-base.sty> +% \end{macrocode} +%\fi +%\chapter{datatool-base.sty} +%\label{sec:code:datatool-base} +% This package provides all the basic commands needed by various +% packages in the \styfmt{datatool} bundle. % -%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. +% \begin{macrocode} +\NeedsTeXFormat{LaTeX2e} +\ProvidesPackage{datatool-base}[2012/07/18 v2.10 (NLCT)] +% \end{macrocode} +% Required packages: +% \begin{macrocode} +\RequirePackage{etoolbox} +\RequirePackage{amsmath} +\RequirePackage{xkeyval} +\RequirePackage{xfor} +\RequirePackage{ifthen} +% \end{macrocode} +% Version of \isty{substr} required that fixes +% \cs{su@IfSubStringInString} +% \begin{macrocode} +\RequirePackage{substr}[2009/10/20] +% \end{macrocode} % -%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}. +%\section{Package Options} % -%\begin{definition}[\DescribeMacro{\DTLifcurrency}]% -%\cs{DTLifcurrency}\marg{text}\marg{true part}\marg{false part} -%\end{definition} -%If \meta{text} is currency, then do \meta{true part}, otherwise -%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}. +%\begin{option}{verbose} +% Define key for package option \pkgopt{verbose}. (This also +% switches the \sty{fp} messages on/off if \sty{datatool-fp} used.) +% This boolean may already have been defined if \sty{datatool} has +% been loaded. +% \begin{macrocode} +\ifundef{\ifdtlverbose} +{ + \define@boolkey{datatool-base.sty}[dtl]{verbose}[true]{} +}% +{} +% \end{macrocode} +%\end{option} +%\begin{option}{math} +% Determine whether to use \sty{fp} or \sty{pgfmath} for the +% arithmetic commands. The default is to use \sty{fp}. +% \begin{macrocode} +\define@choicekey{datatool-base.sty}{math}[\val\nr]{fp,pgfmath}{% + \renewcommand*\@dtl@mathprocessor{#1}% +} +% \end{macrocode} +%\end{option} +%\begin{macro}{\@dtl@mathprocessor} +% \begin{macrocode} +\providecommand*{\@dtl@mathprocessor}{fp} +% \end{macrocode} +%\end{macro} % -%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}. +% Process options: +% \begin{macrocode} +\ProcessOptionsX +% \end{macrocode} % -%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}. +% Load package dealing with numerical processes: +% \begin{macrocode} +\RequirePackage{datatool-\@dtl@mathprocessor} +% \end{macrocode} % -%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}. +%\section{Utilities} % -%\begin{definition}[\DescribeMacro{\DTLifcurrencyunit}]% -%\cs{DTLifcurrencyunit}\marg{text}\marg{symbol}\marg{true part}\marg{false part} +%\begin{macro}{\dtl@message} +%\begin{definition} +%\cs{dtl@message}\marg{message string} %\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}. +% Displays message only if the verbose option is set. +% \begin{macrocode} +\newcommand*{\dtl@message}[1]{% + \ifdtlverbose\typeout{#1}\fi +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\@dtl@toks} +% \begin{macrocode} +\newtoks\@dtl@toks +% \end{macrocode} +%\end{macro} % -%\begin{definition}[\DescribeMacro{\DTLifnumerical}]% -%\cs{DTLifnumerical}\marg{text}\marg{true part}\marg{false part} +%\begin{macro}{\@dtl@tmpcount} +% Define temporary count register +% \begin{macrocode} +\newcount\@dtl@tmpcount +% \end{macrocode} +%\end{macro} +%\begin{macro}{\dtl@tmplength} +% Define temporary length register: +% \begin{macrocode} +\newlength\dtl@tmplength +% \end{macrocode} +%\end{macro} +%\begin{macro}{\dtl@ifsingle} +%\begin{definition} +%\cs{dtl@ifsingle}\marg{arg}\marg{true part}\marg{false part} %\end{definition} -%If \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.) +% If there is only one object in \meta{arg} (without expansion) +% do \meta{true part}, otherwise do false part. +% \begin{macrocode} +\newcommand{\dtl@ifsingle}[3]{% + \def\@dtl@arg{#1}% + \ifdefempty{\@dtl@arg}% + {% + #3% + }% + {% + \@dtl@ifsingle#1\@nil{#2}{#3}% + }% +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\@dtl@ifsingle} +% \begin{macrocode} +\def\@dtl@ifsingle#1#2\@nil#3#4{% + \def\dtl@sg@arg{#2}% + \ifdefempty{\dtl@sg@arg}% + {% + #3% + }% + {% + #4% + }% +} +% \end{macrocode} +%\end{macro} % -%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}. +%\begin{macro}{\long@collect@body} +% Need long versions of \isty{amsmath}'s \cs{collect@body}. These macros are +% adapted from the macros defined by \sty{amsmath}. +% \begin{macrocode} +\long\def\long@collect@body#1{% + \@envbody{\@xp#1\@xp{\the\@envbody}}% + \edef\process@envbody{\the\@envbody\@nx\end{\@currenvir}}% + \@envbody\@emptytoks \def\begin@stack{b}% + \begingroup + \@xp\let\csname\@currenvir\endcsname\long@collect@@body + \edef\process@envbody{\@xp\@nx\csname\@currenvir\endcsname}% + \process@envbody +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\long@addto@envbody} +%\changes{2.10}{2012-07-18}{new} +% Adapted from \isty{amsmath}'s \cs{addto@envbody} +% \begin{macrocode} +\long\def\long@addto@envbody#1{% + \toks@{#1}% + \edef\@dtl@tmp{\the\@envbody\the\toks@}% + \global\@envbody\@xp{\@dtl@tmp}% +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\long@collect@@body} +%\changes{2.10}{2012-07-18}{new} +% Adapted from \isty{amsmath}'s \cs{collect@body} +% \begin{macrocode} +\long\def\long@collect@@body#1\end#2{% + \protected@edef\begin@stack{% + \long@push@begins#1\begin\end \@xp\@gobble\begin@stack + }% + \ifx\@empty\begin@stack + \endgroup + \@checkend{#2}% + \long@addto@envbody{#1}% + \else + \long@addto@envbody{#1\end{#2}}% + \fi + \process@envbody +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\long@push@begins} +%\changes{2.10}{2012-07-16}{new} +%Adapted from \isty{amsmath}'s \cs{push@begins} +% \begin{macrocode} +\long\def\long@push@begins#1\begin#2{% + \ifx\end#2\else b\@xp\long@push@begins\fi +} +% \end{macrocode} +%\end{macro} % -%\begin{definition}[\DescribeMacro{\DTLifstring}]% -%\cs{DTLifstring}\marg{text}\marg{true part}\marg{false part} -%\end{definition} -%This is the opposite of \cs{DTLifnumerical}. If \meta{text} is -%not numerical, do \meta{true part}, otherwise do \meta{false part}. +%\subsection{General List Utilities} % -%\begin{definition}[\DescribeMacro{\DTLifcasedatatype}]% -%\cs{DTLifcasedatatype}\marg{text}\marg{string case}\marg{int case}\marg{real case}\marg{currency case} +%\begin{macro}{\DTLifinlist} +%\begin{definition} +%\cs{DTLifinlist}\marg{element}\marg{list}\marg{true part}\marg{false part} %\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}. +% If \meta{element} is contained in the comma-separated list given +% by \meta{list}, then do \meta{true part} otherwise do false +% part. (Does a one level expansion on \meta{list}, but no +% expansion on \meta{element}.) +% \begin{macrocode} +\newcommand*{\DTLifinlist}[4]{% + \def\@dtl@doifinlist##1,#1,##2\end@dtl@doifinlist{% + \def\@before{##1}% + \def\@after{##2}% + }% + \expandafter\@dtl@doifinlist\expandafter,#2,#1,\@nil + \end@dtl@doifinlist + \ifx\@after\@nnil +% not found + #4% + \else +% found + #3% + \fi +} +% \end{macrocode} +%\end{macro} % -%\begin{definition}[\DescribeMacro{\DTLifnumeq}]% -%\cs{DTLifnumeq}\marg{num1}\marg{num2}\marg{true part}\marg{false part} -%\end{definition} -%If \meta{num1} is equal to \meta{num2}, then do \meta{true part}, -%otherwise do \meta{false part}. Note that both \meta{num1} and -%\meta{num2} must be numerical (either integers, real numbers or -%currency). The currency symbol is ignored when determining -%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}. +%\begin{macro}{\DTLnumitemsinlist} +%\cs{DTLnumitemsinlist}\marg{list}\marg{cmd} +%\end{macro} +% Counts number of non-empty elements in list and stores result in control +% sequence \meta{cmd}. +% \begin{macrocode} +\newcommand*{\DTLnumitemsinlist}[2]{% + \@dtl@tmpcount=0\relax + \@for\@dtl@element:=#1\do{% + \ifdefempty{\@dtl@element}% + {}% + {\advance\@dtl@tmpcount by 1\relax}% + }% + \edef#2{\number\@dtl@tmpcount}% +} +% \end{macrocode} % -%\begin{definition}[\DescribeMacro{\DTLifstringeq}]% -%\cs{DTLifstringeq}\marg{string1}\marg{string2}\marg{true part}\marg{false part} -%\end{definition} -%\begin{definition}[\DescribeMacro{\DTLifstringeq*}]% -%\cs{DTLifstringeq*}\marg{string1}\marg{string2}\marg{true part}\marg{false part} +%\begin{macro}{\dtl@choplast} +%\begin{definition} +% \cs{dtl@choplast}\marg{list}\marg{rest}\marg{last} %\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}. +% Chops the last element off a comma separated list, putting the +% last element in the control sequence \meta{last} and putting +% the rest in the control sequence \meta{rest}. The control +% sequence \meta{list} is unchanged. If the list is empty, both +% \meta{last} and \meta{rest} will be empty. +% \begin{macrocode} +\newcommand*{\dtl@choplast}[3]{% +% \end{macrocode} +% Set \meta{rest} to empty: +% \begin{macrocode} + \let#2\@empty +% \end{macrocode} +% Set \meta{last} to empty: +% \begin{macrocode} + \let#3\@empty +% \end{macrocode} +% Iterate through \meta{list}: +% \begin{macrocode} + \@for\@dtl@element:=#1\do{% + \ifdefempty{#3}% + {% +% \end{macrocode} +% First iteration, don't set \meta{rest}. +% \begin{macrocode} + }% + {% + \ifdefempty{#2}% + {% +% \end{macrocode} +% Second iteration, set \meta{rest} to \meta{last} (which is +% currently set to the previous value: +% \begin{macrocode} + \expandafter\toks@\expandafter{#3}% + \edef#2{{\the\toks@}}% + }% + {% +% \end{macrocode} +% Subsequent iterations, set \meta{rest} to \meta{rest},\meta{last} +% (\meta{last} is currently set to the previous value): +% \begin{macrocode} + \expandafter\toks@\expandafter{#3}% + \expandafter\@dtl@toks\expandafter{#2}% + \edef#2{\the\@dtl@toks,{\the\toks@}}% + }% + }% +% \end{macrocode} +% Now set \meta{last} to current element. +% \begin{macrocode} + \let#3=\@dtl@element% + }% +} +% \end{macrocode} +%\end{macro} % -%\begin{definition}[\DescribeMacro{\DTLifeq}]% -%\cs{DTLifeq}\marg{arg1}\marg{arg2}\marg{true part}\marg{false part} -%\end{definition} -%\begin{definition}[\DescribeMacro{\DTLifeq*}]% -%\cs{DTLifeq*}\marg{arg1}\marg{arg2}\marg{true part}\marg{false part} +%\begin{macro}{\dtl@chopfirst} +%\begin{definition} +% \cs{dtl@chopfirst}\marg{list}\marg{first}\marg{rest} %\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*}). +% 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{definition}[\DescribeMacro{\DTLifnumlt}]% -%\cs{DTLifnumlt}\marg{num1}\marg{num2}\marg{true part}\marg{false part} +%\begin{macro}{\dtl@sortlist} +%\begin{definition} +% \cs{dtl@sortlist}\marg{list}\marg{criteria cmd} %\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). +% 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{definition}[\DescribeMacro{\DTLifstringlt}]% -%\cs{DTLifstringlt}\marg{string1}\marg{string2}\marg{true -%part}\marg{false part} -%\end{definition} -%\begin{definition}[\DescribeMacro{\DTLifstringlt*}]% -%\cs{DTLifstringlt*}\marg{string1}\marg{string2}\marg{true -%part}\marg{false part} +%\begin{macro}{\dtl@insertinto} +%\begin{definition} +% \cs{dtl@insertinto}\marg{element}\marg{sorted-list}\marg{criteria cmd} %\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}. +% Inserts \meta{element} into the sorted list \meta{sorted-list} +% according to the criteria given by \meta{criteria cmd} (see above.) +% \begin{macrocode} +\newcommand{\dtl@insertinto}[3]{% + \def\@dtl@newsortedlist{}% + \@dtl@insertdonefalse + \@for\dtl@srtelement:=#2\do{% + \if@dtl@insertdone + \expandafter\toks@\expandafter{\dtl@srtelement}% + \edef\@dtl@newstuff{{\the\toks@}}% + \else + \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 + \ifdefempty{\@dtl@newsortedlist}% + {% + \expandafter\toks@\expandafter{\@dtl@newstuff}% + \edef\@dtl@newsortedlist{\the\toks@}% + }% + {% + \expandafter\toks@\expandafter{\@dtl@newsortedlist}% + \expandafter\@dtl@toks\expandafter{\@dtl@newstuff}% + \edef\@dtl@newsortedlist{\the\toks@,\the\@dtl@toks}% + }% + \@endforfalse + }% + \ifdefempty{\@dtl@newsortedlist}% + {% + \@dtl@toks{#1}% + \edef\@dtl@newsortedlist{{\the\@dtl@toks}}% + }% + {% + \if@dtl@insertdone + \else + \expandafter\toks@\expandafter{\@dtl@newsortedlist}% + \@dtl@toks{#1}% + \edef\@dtl@newsortedlist{\the\toks@,{\the\@dtl@toks}}% + \fi + }% + \global\let#2=\@dtl@newsortedlist +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\if@dtl@insertdone} +% Define conditional to indicate whether the new entry has +% been inserted into the sorted list. +% \begin{macrocode} +\newif\if@dtl@insertdone +% \end{macrocode} +%\end{macro} +%\begin{macro}{\dtl@sortresult} +% Define \cs{dtl@sortresult} to be set by comparison macro. +% \begin{macrocode} +\newcount\dtl@sortresult +% \end{macrocode} +%\end{macro} % -%\begin{definition}[\DescribeMacro{\DTLiflt}]% -%\cs{DTLiflt}\marg{arg1}\marg{arg2}\marg{true part}\marg{false part} -%\end{definition} -%\begin{definition}[\DescribeMacro{\DTLiflt*}]% -%\cs{DTLiflt*}\marg{arg1}\marg{arg2}\marg{true part}\marg{false part} +% \subsection{General Token Utilities} +%\begin{macro}{\toks@gput@right@cx} +%\begin{definition} +%\cs{toks@gput@right@cx}\marg{toks name}\marg{stuff} %\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*}). -% -%\begin{definition}[\DescribeMacro{\DTLifnumgt}]% -%\cs{DTLifnumgt}\marg{num1}\marg{num2}\marg{true part}\marg{false part} +% Globally appends stuff to token register \cs{}\meta{toks name} +% \begin{macrocode} +\newcommand{\toks@gput@right@cx}[2]{% + \def\@toks@name{#1}% + \edef\@dtl@stuff{#2}% + \global\csname\@toks@name\endcsname\expandafter + \expandafter\expandafter{\expandafter\the + \csname\expandafter\@toks@name\expandafter\endcsname\@dtl@stuff}% +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\toks@gconcat@middle@cx} +%\begin{definition} +%\cs{toks@gconcat@middle@cx}\marg{toks name}\marg{before toks}\marg{stuff}\marg{after toks} %\end{definition} -%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). +% Globally sets token register \cs{}\meta{toks name} to +% the contents of \meta{before toks} concatenated with +% \meta{stuff} (expanded) and the contents of \meta{after toks} +% \begin{macrocode} +\newcommand{\toks@gconcat@middle@cx}[4]{% + \def\@toks@name{#1}% + \edef\@dtl@stuff{#3}% + \global\csname\@toks@name\endcsname\expandafter\expandafter + \expandafter\expandafter\expandafter + \expandafter\expandafter{\expandafter\expandafter\expandafter + \the\expandafter\expandafter\expandafter#2% + \expandafter\@dtl@stuff\the#4}% +} +% \end{macrocode} +%\end{macro} % -%\begin{definition}[\DescribeMacro{\DTLifstringgt}]% -%\cs{DTLifstringgt}\marg{string1}\marg{string2}\marg{true -%part}\marg{false part} -%\end{definition} -%\begin{definition}[\DescribeMacro{\DTLifstringgt*}]% -%\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}. +%\section{Locale Dependent Information} % -%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. +%\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} % -%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}. +%\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{definition}[\DescribeMacro{\DTLifgt}]% -%\cs{DTLifgt}\marg{arg1}\marg{arg2}\marg{true part}\marg{false part} -%\end{definition} -%\begin{definition}[\DescribeMacro{\DTLifgt*}]% -%\cs{DTLifgt*}\marg{arg1}\marg{arg2}\marg{true part}\marg{false part} +%\begin{macro}{\DTLsetnumberchars} +%\begin{definition} +%\cs{DTLsetnumberchars}\marg{number group char}\marg{decimal char} %\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*}). +% 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{definition}[\DescribeMacro{\DTLifnumclosedbetween}]% -%\cs{DTLifnumclosedbetween}\marg{num}\marg{min}\marg{max}\marg{true part}\marg{false part} +%\begin{macro}{\@dtl@construct@getintfrac} +%\begin{definition} +%\cs{@dtl@construct@getintfrac}\marg{char} %\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}. +% This constructs the macros for extracting integer and +% fractional parts from a real number using the decimal character +% \meta{char}. % -%\begin{definition}[\DescribeMacro{\DTLifstringclosedbetween}]% -%\cs{DTLifstringclosedbetween}\marg{string}\marg{min}\marg{max}\marg{true part}\marg{false part} -%\end{definition} -%\begin{definition}[\DescribeMacro{\DTLifstringclosedbetween*}]% -%\cs{DTLifstringclosedbetween*}\marg{string}\marg{min}\marg{max}\marg{true part}\marg{false part} +%\begin{definition}[\DescribeMacro{\DTLconverttodecimal}] +% \cs{DTLconverttodecimal}\marg{num}\marg{cmd} %\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. -% -%\begin{definition}[\DescribeMacro{\DTLifclosedbetween}]% -%\cs{DTLifclosedbetween}\marg{arg}\marg{min}\marg{max}\marg{true part}\marg{false part} -%\end{definition} -%\begin{definition}[\DescribeMacro{\DTLifclosedbetween*}]% -%\cs{DTLifclosedbetween*}\marg{arg}\marg{min}\marg{max}\marg{true part}\marg{false part} -%\end{definition} -%If \meta{arg}, \meta{min} and \meta{max} are numerical, then this is -%equivalent to \cs{DTLifnumclosedbetween}, otherwise it is equivalent to -%\cs{DTLifstringclosedbetween} (when using \cs{DTLifclosedbetween}) -%or -%\cs{DTLifstringclosedbetween*} (when using \cs{DTLifclosedbetween*}). -% -%\begin{definition}[\DescribeMacro{\DTLifnumopenbetween}]% -%\cs{DTLifnumopenbetween}\marg{num}\marg{min}\marg{max}\marg{true part}\marg{false part} -%\end{definition} -%If \meta{min} $<$ \meta{num} $<$ \meta{max} then do \meta{true part}, -%otherwise do \meta{false part}. Note that \meta{num}, \meta{min} and -%\meta{max} must be numerical (either integers, real numbers or -%currency). Again, the currency symbol is ignored when determining -%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}. +% \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\ifdefempty{\noexpand\@dtl@org@currency}% + {% + }% + {% + \noexpand\let\noexpand\@dtl@currency\noexpand\@dtl@org@currency + }% + \noexpand\expandafter + \noexpand\@dtl@getintfrac\noexpand\@dtl@tmp#1\noexpand\relax + \noexpand\edef##2{\noexpand\@dtl@intpart.\noexpand\@dtl@fracpart}% + }% +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\@dtl@construct@getnums} +% The following calls the above with the relevant +% decimal character: +% \begin{macrocode} +\newcommand*{\@dtl@construct@getnums}{% + \expandafter\@dtl@construct@getintfrac\expandafter{\@dtl@decimal}% +} +% \end{macrocode} +%\end{macro} % -%\begin{definition}[\DescribeMacro{\DTLifstringopenbetween}]% -%\cs{DTLifstringopenbetween}\marg{string}\marg{min}\marg{max}\marg{true part}\marg{false part} -%\end{definition} -%\begin{definition}[\DescribeMacro{\DTLifstringopenbetween*}]% -%\cs{DTLifstringopenbetween*}\marg{string}\marg{min}\marg{max}\marg{true part}\marg{false part} -%\end{definition} -%This determines if \meta{string} is between \meta{min} and -%\meta{max} in the alphabetical sense. -%The starred version ignores the case, -%the unstarred version is case sensitive. +%\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{definition}[\DescribeMacro{\DTLifopenbetween}]% -%\cs{DTLifopenbetween}\marg{arg}\marg{min}\marg{max}\marg{true part}\marg{false part} -%\end{definition} -%\begin{definition}[\DescribeMacro{\DTLifopenbetween*}]% -%\cs{DTLifopenbetween*}\marg{arg}\marg{min}\marg{max}\marg{true part}\marg{false part} +%\begin{macro}{\@dtl@choptrailingzeroes} +%\begin{definition} +% \cs{@dtl@choptrailingzeroes}\marg{cmd} %\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*}). +% 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{definition}[\DescribeMacro{\DTLifFPclosedbetween}]% -%\cs{DTLifFPclosedbetween}\marg{num}\marg{min}\marg{max}\marg{true part}\marg{false part} -%\end{definition} -%If \meta{min} $\leq$ \meta{num} $\leq$ \meta{max} then do \meta{true part}, -%otherwise do \meta{false part} where \meta{num}, \meta{min} -%and \meta{max} are all in standard fixed point notation (i.e.\ -%no number group separator, no currency symbols and a full stop as -%a decimal point). +%\begin{macro}{\@dtl@chop@trailingzeroes} +% Trailing zeroes are chopped using a recursive algorithm. +% \cs{@dtl@tmpcpz} needs to be set before using this. (The chopped +% number is put in this control sequence.) +% \begin{macrocode} +\def\@dtl@chop@trailingzeroes#1#2\@nil{% + \dtlifnumeq{#2}{0}% + {% + \edef\@dtl@tmpcpz{\@dtl@tmpcpz#1}% + \let\@dtl@chopzeroesnext=\@dtl@gobbletonil + }% + {% + \edef\@dtl@tmpcpz{\@dtl@tmpcpz#1}% + \let\@dtl@chopzeroesnext=\@dtl@chop@trailingzeroes + }% + \@dtl@chopzeroesnext#2\@nil +} +% \end{macrocode} +%\end{macro} +% No-op macro to end recursion: +%\begin{macro}{\@dtl@gobbletonil} +% \begin{macrocode} +\def\@dtl@gobbletonil#1\@nil{} +% \end{macrocode} +%\end{macro} % -%\begin{definition}[\DescribeMacro{\DTLifFPopenbetween}]% -%\cs{DTLifFPopenbetween}\marg{num}\marg{min}\marg{max}\marg{true part}\marg{false part} +%\begin{macro}{\dtl@truncatedecimal} +%\begin{definition} +%\cs{dtl@truncatedecimal}\meta{cmd} %\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). +%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{definition}[\DescribeMacro{\DTLifAllUpperCase}]% -%\cs{DTLifAllUpperCase}\marg{string}\marg{true part}\marg{false part} +%\begin{macro}{\@dtl@strip@numgrpchar} +%\begin{definition} +% \cs{@dtl@strip@numgrpchar}\marg{cmd} %\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}. +% 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{definition}[\DescribeMacro{\DTLifAllLowerCase}]% -%\cs{DTLifAllLowerCase}\marg{string}\marg{true part}\marg{false part} -%\end{definition} -%Tests if \meta{string} is all lower case. For example: -%\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}. +%\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{definition}[\DescribeMacro{\DTLifSubString}]% -%\cs{DTLifSubString}\marg{string}\marg{substring}\marg{true -%part}\marg{false part} +%\begin{macro}{\DTLdecimaltolocale} +%\begin{definition} +% \cs{DTLdecimaltolocale}\marg{number}\marg{cmd} %\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}. +% Define command to convert a decimal number into the locale +% dependent format. Stores result in \meta{cmd} which must be +% a control sequence. +% \begin{macrocode} +\newcommand*{\DTLdecimaltolocale}[2]{% + \edef\@dtl@tmpdtl{#1}% + \expandafter\@dtl@decimaltolocale\@dtl@tmpdtl.\relax + \dtlifnumeq{\@dtl@fracpart}{0}% + {% + \edef#2{\@dtl@intpart}% + }% + {% + \edef#2{\@dtl@intpart\@dtl@decimal\@dtl@fracpart}% + }% +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\@dtl@decimaltolocale} +% Convert the integer part (store in \cs{@dtl@intpart}) +% \begin{macrocode} +\def\@dtl@decimaltolocale#1.#2\relax{% + \@dtl@decimaltolocaleint{#1}% + \def\@dtl@fracpart{#2}% + \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} % -%\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}. +%\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{definition}[\DescribeMacro{\DTLifStartsWith}]% -%\cs{DTLifStartsWith}\marg{string}\marg{substring}\marg{true -%part}\marg{false part} +%\begin{macro}{\DTLdecimaltocurrency} +%\begin{definition} +% \cs{DTLdecimaltocurrency}\marg{number}\marg{cmd} %\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}. These may be used with the boolean operations -%\cs{not}, \cs{and} and \cs{or} provided by the \sty{ifthen} package. -%See the \sty{ifthen} documentation for further details. +% This converts a decimal number into the locale +% dependent currency format. Stores result in \meta{cmd} which must be +% a control sequence. +% \begin{macrocode} +\newcommand*{\DTLdecimaltocurrency}[2]{% + \edef\@dtl@tmpdtl{#1}% + \expandafter\@dtl@decimaltolocale\@dtl@tmpdtl.\relax + \dtl@truncatedecimal\@dtl@tmpdtl + \@dtl@tmpcount=\@dtl@tmpdtl\relax + \expandafter\@dtl@toks\expandafter{\@dtl@currency}% + \dtlifnumeq{\@dtl@fracpart}{0}% + {% + \ifnum\@dtl@tmpcount<0\relax + \@dtl@tmpcount = -\@dtl@tmpcount\relax + \edef#2{-\the\@dtl@toks\the\@dtl@tmpcount\@dtl@decimal00}% + \else + \edef#2{\the\@dtl@toks\@dtl@intpart\@dtl@decimal00}% + \fi + }% + {% + \ifnum\@dtl@tmpcount<0\relax + \@dtl@tmpcount = -\@dtl@tmpcount\relax + \ifnum\@dtl@fracpart<10\relax + \edef#2{% + -\the\@dtl@toks\number\@dtl@tmpcount + \@dtl@decimal\@dtl@fracpart0% + }% + \else + \edef#2{% + -\the\@dtl@toks\number\@dtl@tmpcount + \@dtl@decimal\@dtl@fracpart + }% + \fi + \else + \ifnum\@dtl@fracpart<10\relax + \edef#2{\the\@dtl@toks\@dtl@intpart\@dtl@decimal\@dtl@fracpart0}% + \else + \edef#2{\the\@dtl@toks\@dtl@intpart\@dtl@decimal\@dtl@fracpart}% + \fi + \fi + }% +} +% \end{macrocode} +%\end{macro} % -%\begin{definition}[\DescribeMacro{\DTLisstring}]% -%\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}. +% Set the defaults: +% \begin{macrocode} +\@dtl@construct@getnums +\expandafter\@dtl@construct@stripnumgrpchar\expandafter + {\@dtl@numbergroupchar} +% \end{macrocode} % -%\begin{definition}[\DescribeMacro{\DTLisnumerical}]% -%\cs{DTLisnumerical}\marg{text} +%\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} -%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}. -% -%\begin{definition}[\DescribeMacro{\DTLiscurrency}]% -%\cs{DTLiscurrency}\marg{text} +% 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} -%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. +% Substitutes the first currency symbol found in \meta{cmd} +% with "\$". This is used when testing text to determine +% if it is currency. The original currency symbol is stored +% in \cs{@dtl@org@currency}, so that it can be replaced later. +% If no currency symbol is found, \cs{@dtl@org@currency} will +% be empty. +% \begin{macrocode} +\newcommand{\@dtl@standardize@currency}[1]{% + \def\@dtl@org@currency{}% + \@for\@dtl@thiscurrency:=\@dtl@currencies\do{% + \expandafter\toks@\expandafter{\@dtl@thiscurrency}% + \edef\@dtl@dosubs{\noexpand\DTLsubstitute{\noexpand#1}% + {\the\toks@}{\noexpand\$}}% + \@dtl@dosubs + \ifdefempty{\@dtl@replaced}% + {% + }% + {% + \let\@dtl@org@currency=\@dtl@replaced + \@endfortrue + }% + }% + \@endforfalse +} +% \end{macrocode} +%\end{macro} % -%\begin{definition}[\DescribeMacro{\DTLiscurrencyunit}]% -%\cs{DTLiscurrencyunit}\marg{text}\marg{symbol} -%\end{definition} -%Tests if \meta{text} is currency and that currency uses \meta{symbol} as the unit -%of currency. -%For example: -%\begin{verbatim} -%\ifthenelse{\DTLiscurrencyunit{\$6.99}{\$}}{dollars}{not dollars} -%\end{verbatim} -%produces: -%\ifthenelse{\DTLiscurrencyunit{\$6.99}{\$}}{dollars}{not dollars}. -%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}. +%\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{definition}[\DescribeMacro{\DTLisreal}]% -%\cs{DTLisreal}\marg{text} -%\end{definition} -%Tests if \meta{text} is a fixed point number (again, an integer is -%not considered to be a fixed point number). For example: -%\begin{verbatim} -%\ifthenelse{\DTLisreal{1.5}}{real}{not real} -%\end{verbatim} -%produces: -%\ifthenelse{\DTLisreal{1.5}}{real}{not real}. +% \section{Floating Point Arithmetic} +% The commands defined in this section all use the equivalent +% commands provided by the \sty{fp} or \sty{pgfmath} packages, but +% first convert the decimal number into the required format. % -%\begin{definition}[\DescribeMacro{\DTLisint}]% -%\cs{DTLisint}\marg{text} +%\begin{macro}{\DTLadd} +%\begin{definition} +% \cs{DTLadd}\marg{cmd}\marg{num1}\marg{num2} %\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}. -% -%\begin{definition}[\DescribeMacro{\DTLislt}]% -%\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.) -% -%\begin{definition}[\DescribeMacro{\DTLisilt}]% -%\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. -% -%\begin{definition}[\DescribeMacro{\DTLisgt}]% -%\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.) -% -%\begin{definition}[\DescribeMacro{\DTLisigt}]% -%\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. -% -%\begin{definition}[\DescribeMacro{\DTLiseq}]% -%\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}.) -% -%\begin{definition}[\DescribeMacro{\DTLisieq}]% -%\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. +% Sets \meta{cmd} = \meta{num1} + \meta{num2} +% \begin{macrocode} +\newcommand*{\DTLadd}[3]{% + \DTLconverttodecimal{#2}{\@dtl@numi}% + \DTLconverttodecimal{#3}{\@dtl@numii}% + \dtladd{\@dtl@tmp}{\@dtl@numi}{\@dtl@numii}% + \ifdefempty{\@dtl@replaced}% + {% + \DTLdecimaltolocale{\@dtl@tmp}{#1}% + }% + {% + \DTLdecimaltocurrency{\@dtl@tmp}{#1}% + }% +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLgadd} +% Global version +% \begin{macrocode} +\newcommand*{\DTLgadd}[3]{% + \DTLadd{\@dtl@tmpii}{#2}{#3}% + \global\let#1=\@dtl@tmpii +} +% \end{macrocode} +%\end{macro} % -%\begin{definition}[\DescribeMacro{\DTLisclosedbetween}]% -%\cs{DTLisclosedbetween}\marg{arg}\marg{min}\marg{max} -%\end{definition} -%This checks if \meta{arg} lies between \meta{min} and -%\meta{max} (end points included). As with -%\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}.) -% -%\begin{definition}[\DescribeMacro{\DTLisiclosedbetween}]% -%\cs{DTLisiclosedbetween}\marg{arg}\marg{min}\marg{max} -%\end{definition} -%This checks if \meta{arg} lies between \meta{min} and -%\meta{max} (end points included). As with -%\cs{DTLifclosedbetween*}, if the arguments are numerical, -%a numerical comparison is used, otherwise a case insensitive -%alphabetical comparison is used. -% -%\begin{definition}[\DescribeMacro{\DTLisopenbetween}]% -%\cs{DTLisopenbetween}\marg{arg}\marg{min}\marg{max} -%\end{definition} -%This checks if \meta{arg} lies between \meta{min} and -%\meta{max} (end points excluded). As with -%\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}.) -% -%\begin{definition}[\DescribeMacro{\DTLisiopenbetween}]% -%\cs{DTLisiopenbetween}\marg{arg}\marg{min}\marg{max} -%\end{definition} -%This checks if \meta{arg} lies between \meta{min} and -%\meta{max} (end points excluded). As with -%\cs{DTLifopenbetween*}, if the arguments are numerical, -%a numerical comparison is used, otherwise a case insensitive -%alphabetical comparison is used. -% -%\begin{definition}[\DescribeMacro{\DTLisFPlt}]% -%\cs{DTLisFPlt}\marg{num1}\marg{num2} -%\end{definition} -%This checks if \meta{num1} is less than \meta{num2}, where both -%numbers are in standard fixed point format (i.e.\ no number group -%separators, no currency and a full stop as a decimal point). -% -%\begin{definition}[\DescribeMacro{\DTLisFPlteq}]% -%\cs{DTLisFPlteq}\marg{num1}\marg{num2} -%\end{definition} -%This checks if \meta{num1} is less than or equal to \meta{num2}, where both -%numbers are in standard fixed point format (i.e.\ no number group -%separators, no currency and a full stop as a decimal point). -% -%\begin{definition}[\DescribeMacro{\DTLisFPgt}]% -%\cs{DTLisFPgt}\marg{num1}\marg{num2} -%\end{definition} -%This checks if \meta{num1} is greater than \meta{num2}, where both -%numbers are in standard fixed point format (i.e.\ no number group -%separators, no currency and a full stop as a decimal point). -% -%\begin{definition}[\DescribeMacro{\DTLisFPgteq}]% -%\cs{DTLisFPgteq}\marg{num1}\marg{num2} -%\end{definition} -%This checks if \meta{num1} is greater than or equal to \meta{num2}, where both -%numbers are in standard fixed point format (i.e.\ no number group -%separators, no currency and a full stop as a decimal point). -% -%\begin{definition}[\DescribeMacro{\DTLisFPeq}]% -%\cs{DTLisFPeq}\marg{num1}\marg{num2} -%\end{definition} -%This checks if \meta{num1} is equal to \meta{num2}, where both -%numbers are in standard fixed point format (i.e.\ no number group -%separators, no currency and a full stop as a decimal point). -% -%\begin{definition}[\DescribeMacro{\DTLisFPclosedbetween}]% -%\cs{DTLisFPclosedbetween}\marg{num}\marg{min}\marg{max} -%\end{definition} -%This checks if \meta{num} lies between \meta{min} and -%\meta{max} (end points included). All arguments must be -%numbers in standard fixed point format (i.e.\ no number group -%separators, no currency and a full stop as a decimal point). -% -%\begin{definition}[\DescribeMacro{\DTLisFPopenbetween}]% -%\cs{DTLisFPopenbetween}\marg{num}\marg{min}\marg{max} -%\end{definition} -%This checks if \meta{num} lies between \meta{min} and -%\meta{max} (end points excluded). All arguments must be -%numbers in standard fixed point format (i.e.\ no number group -%separators, no currency and a full stop as a decimal point). -% -%\begin{definition}[\DescribeMacro{\DTLisSubString}]% -%\cs{DTLisSubString}\marg{string}\marg{substring} +%\begin{macro}{\DTLaddall} +%\begin{definition} +%\cs{DTLaddall}\marg{cmd}\marg{num list} %\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. -% -%\begin{definition}[\DescribeMacro{\DTLisPrefix}]% -%\cs{DTLisPrefix}\marg{string}\marg{prefix} +% Sums all the values in \meta{num list} and stores in +% \meta{cmd} which must be a control sequence. +%\changes{1.01}{2007 Aug 17}{removed extraneous space} +% \begin{macrocode} +\newcommand*{\DTLaddall}[2]{% + \def\@dtl@sum{0}% + \@for\dtl@thisval:=#2\do{% + \expandafter\DTLconverttodecimal\expandafter{\dtl@thisval}{\@dtl@num}% + \dtladd{\@dtl@sum}{\@dtl@sum}{\@dtl@num}% + }% + \ifdefempty{\@dtl@replaced}% + {% + \DTLdecimaltolocale{\@dtl@sum}{#1}% + }% + {% + \DTLdecimaltocurrency{\@dtl@sum}{#1}% + }% +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLgaddall} +%\begin{definition} +%\cs{DTLgaddall}\marg{cmd}\marg{num list} %\end{definition} -%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} +% Global version +% \begin{macrocode} +\newcommand*{\DTLgaddall}[2]{% + \DTLaddall{\@dtl@tmpi}{#2}% + \global\let#1=\@dtl@tmpi +} +% \end{macrocode} +%\end{macro} % -%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 -%\begin{definition}[\DescribeMacro{\DTLconverttodecimal}]% -%\cs{DTLconverttodecimal}\marg{num}\marg{cmd} +%\begin{macro}{\DTLsub} +%\begin{definition} +% \cs{DTLsub}\marg{cmd}\marg{num1}\marg{num2} %\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 \cs{mynum} -%can then be used in any of the arithmetic macros provided by the -%\sty{fp} package. There are two commands provided to perform -%the reverse: -%\begin{definition}[\DescribeMacro{\DTLdecimaltolocale}]% -%\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}. +% Sets \meta{cmd} = \meta{num1} - \meta{num2} +% \begin{macrocode} +\newcommand*{\DTLsub}[3]{% + \DTLconverttodecimal{#2}{\@dtl@numi}% + \DTLconverttodecimal{#3}{\@dtl@numii}% + \dtlsub{\@dtl@tmp}{\@dtl@numi}{\@dtl@numii}% + \ifdefempty{\@dtl@replaced}% + {% + \DTLdecimaltolocale{\@dtl@tmp}{#1}% + }% + {% + \DTLdecimaltocurrency{\@dtl@tmp}{#1}% + }% +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLgsub} +% Global version +% \begin{macrocode} +\newcommand*{\DTLgsub}[3]{% + \DTLsub{\@dtl@tmpii}{#2}{#3}% + \global\let#1=\@dtl@tmpii +} +% \end{macrocode} +%\end{macro} % -%\begin{definition}[\DescribeMacro{\DTLdecimaltocurrency}]% -%\cs{DTLdecimaltocurrency}\marg{number}\marg{cmd} +%\begin{macro}{\DTLmul} +%\begin{definition} +% \cs{DTLmul}\marg{cmd}\marg{num1}\marg{num2} %\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: -%\begin{definition}[\DescribeMacro{\DTLsetdefaultcurrency}]% -%\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}. -% +% Sets \meta{cmd} = \meta{num1} $\times$ \meta{num2} +% \begin{macrocode} +\newcommand*{\DTLmul}[3]{% + \let\@dtl@thisreplaced=\@empty + \DTLconverttodecimal{#2}{\@dtl@numi}% + \ifdefempty{\@dtl@replaced}% + {% + }% + {% + \let\@dtl@thisreplaced=\@dtl@replaced + }% + \DTLconverttodecimal{#3}{\@dtl@numii}% + \ifdefempty{\@dtl@replaced}% + {% + }% + {% + \let\@dtl@thisreplaced=\@dtl@replaced + }% + \dtlmul{\@dtl@tmp}{\@dtl@numi}{\@dtl@numii}% + \ifdefempty{\@dtl@thisreplaced}% + {% + \DTLdecimaltolocale{\@dtl@tmp}{#1}% + }% + {% + \DTLdecimaltocurrency{\@dtl@tmp}{#1}% + }% +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLgmul} +% Global version +% \begin{macrocode} +\newcommand*{\DTLgmul}[3]{% + \DTLmul{\@dtl@tmpii}{#2}{#3}% + \global\let#1=\@dtl@tmpii +} +% \end{macrocode} +%\end{macro} % -%\begin{definition}[\DescribeMacro{\DTLadd}]% -%\cs{DTLadd}\marg{cmd}\marg{num1}\marg{num2} -%\end{definition} -%\begin{definition}[\DescribeMacro{\DTLgadd}]% -%\cs{DTLgadd}\marg{cmd}\marg{num1}\marg{num2} +%\begin{macro}{\DTLdiv} +%\begin{definition} +% \cs{DTLdiv}\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 convert currency to a real -%number, you can also add prices. For example: -%\begin{verbatim} -%\DTLadd{\result}{\pounds3,562.65}{\pounds452.2}\result -%\end{verbatim} -%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. +% Sets \meta{cmd} = \meta{num1} / \meta{num2} +% \begin{macrocode} +\newcommand*{\DTLdiv}[3]{% + \let\@dtl@thisreplaced=\@empty + \DTLconverttodecimal{#2}{\@dtl@numi}% + \ifdefempty{\@dtl@replaced}% + {% + }% + {% + \let\@dtl@thisreplaced=\@dtl@replaced + }% + \DTLconverttodecimal{#3}{\@dtl@numii}% + \dtldiv{\@dtl@tmp}{\@dtl@numi}{\@dtl@numii}% + \ifdefempty{\@dtl@thisreplaced}% + {% + \DTLdecimaltolocale{\@dtl@tmp}{#1}% + }% + {% + \ifdefequal{\@dtl@thisreplaced}{\@dtl@replaced}% + {% + \DTLdecimaltolocale{\@dtl@tmp}{#1}% + }% + {% + \DTLdecimaltocurrency{\@dtl@tmp}{#1}% + }% + }% +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLgdiv} +% Global version +% \begin{macrocode} +\newcommand*{\DTLgdiv}[3]{% + \DTLdiv{\@dtl@tmpii}{#2}{#3}% + \global\let#1=\@dtl@tmpii +} +% \end{macrocode} +%\end{macro} % -%\begin{definition}[\DescribeMacro{\DTLaddall}]% -%\cs{DTLaddall}\marg{cmd}\marg{number list} -%\end{definition} -%\begin{definition}[\DescribeMacro{\DTLgaddall}]% -%\cs{DTLgaddall}\marg{cmd}\marg{number list} +%\begin{macro}{\DTLabs} +%\begin{definition} +% \cs{DTLabs}\marg{cmd}\marg{num} %\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. +% Sets \meta{cmd} = abs(\meta{num}) +% \begin{macrocode} +\newcommand*{\DTLabs}[2]{% + \DTLconverttodecimal{#2}{\@dtl@numi}% + \dtlabs{\@dtl@tmp}{\@dtl@numi}% + \ifdefempty{\@dtl@replaced}% + {% + \DTLdecimaltolocale{\@dtl@tmp}{#1}% + }% + {% + \DTLdecimaltocurrency{\@dtl@tmp}{#1}% + }% +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLgabs} +% Global version +% \begin{macrocode} +\newcommand*{\DTLgabs}[2]{% + \DTLabs{\@dtl@tmpii}{#2}% + \global\let#1=\@dtl@tmpii +} +% \end{macrocode} +%\end{macro} % -%\begin{definition}[\DescribeMacro{\DTLsub}]% -%\cs{DTLsub}\marg{cmd}\marg{num1}\marg{num2} -%\end{definition} -%\begin{definition}[\DescribeMacro{\DTLgsub}]% -%\cs{DTLgsub}\marg{cmd}\marg{num1}\marg{num2} +%\begin{macro}{\DTLneg} +%\begin{definition} +% \cs{DTLneg}\marg{cmd}\marg{num} %\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. +% Sets \meta{cmd} = -\meta{num} +% \begin{macrocode} +\newcommand*{\DTLneg}[2]{% + \DTLconverttodecimal{#2}{\@dtl@numi}% + \dtlneg{\@dtl@tmp}{\@dtl@numi}% + \ifdefempty{\@dtl@replaced}% + {% + \DTLdecimaltolocale{\@dtl@tmp}{#1}% + }% + {% + \DTLdecimaltocurrency{\@dtl@tmp}{#1}% + }% +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLgneg} +% Global version +% \begin{macrocode} +\newcommand*{\DTLgneg}[2]{% + \DTLneg{\@dtl@tmpii}{#2}% + \global\let#1=\@dtl@tmpii +} +% \end{macrocode} +%\end{macro} % -%\begin{definition}[\DescribeMacro{\DTLmul}]% -%\cs{DTLmul}\marg{cmd}\marg{num1}\marg{num2} -%\end{definition} -%\begin{definition}[\DescribeMacro{\DTLgmul}]% -%\cs{DTLgmul}\marg{cmd}\marg{num1}\marg{num2} +%\begin{macro}{\DTLsqrt} +%\begin{definition} +% \cs{DTLsqrt}\marg{cmd}\marg{num} %\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. +% Sets \meta{cmd} = sqrt(\meta{num}) +% \begin{macrocode} +\newcommand*{\DTLsqrt}[2]{% + \DTLconverttodecimal{#2}{\@dtl@numi}% + \dtlroot{\@dtl@tmpi}{\@dtl@numi}{2}% + \ifdefempty{\@dtl@replaced}% + {% + \DTLdecimaltolocale{\@dtl@tmpi}{#1}% + }% + {% + \DTLdecimaltocurrency{\@dtl@tmpi}{#1}% + }% +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLgsqrt} +% Global version +% \begin{macrocode} +\newcommand*{\DTLgsqrt}[2]{% +\DTLsqrt{\@dtl@tmpii}{#2}% +\global\let#1=\@dtl@tmpii +} +% \end{macrocode} +%\end{macro} % -%\begin{definition}[\DescribeMacro{\DTLdiv}]% -%\cs{DTLdiv}\marg{cmd}\marg{num1}\marg{num2} -%\end{definition} -%\begin{definition}[\DescribeMacro{\DTLgdiv}]% -%\cs{DTLgdiv}\marg{cmd}\marg{num1}\marg{num2} +%\begin{macro}{\DTLmin} +%\begin{definition} +% \cs{DTLmin}\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. +% Sets \meta{cmd} = min(\meta{num1}, \meta{num2}) +% \begin{macrocode} +\newcommand*{\DTLmin}[3]{% + \DTLconverttodecimal{#2}{\@dtl@numi}% + \DTLconverttodecimal{#3}{\@dtl@numii}% + \dtlifnumlt{\@dtl@numi}{\@dtl@numii}% + {% + \dtl@ifsingle{#2}% + {\let#1=#2}% + {\def#1{#2}}% + }% + {% + \dtl@ifsingle{#3}% + {\let#1=#3}% + {\def#1{#3}}% + }% +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLgmin} +% Global version +% \begin{macrocode} +\newcommand*{\DTLgmin}[3]{% + \DTLmin{\@dtl@tmpii}{#2}{#3}% + \global\let#1=\@dtl@tmpii +} +% \end{macrocode} +%\end{macro} % -%\begin{definition}[\DescribeMacro{\DTLabs}]% -%\cs{DTLabs}\marg{cmd}\marg{num} +%\begin{macro}{\DTLminall} +%\begin{definition} +%\cs{DTLminall}\marg{cmd}\marg{num list} %\end{definition} -%\begin{definition}[\DescribeMacro{\DTLgabs}]% -%\cs{DTLgabs}\marg{cmd}\marg{num} +% Finds the minimum value in \meta{num list} and stores in +% \meta{cmd} which must be a control sequence. +%\changes{1.01}{2007 Aug 17}{removed extraneous space} +% \begin{macrocode} +\newcommand*{\DTLminall}[2]{% + \let\@dtl@min=\@empty + \@for\dtl@thisval:=#2\do{% + \expandafter\DTLconverttodecimal\expandafter{\dtl@thisval}{\@dtl@num}% + \ifdefempty{\@dtl@min}% + {% + \let\@dtl@min=\@dtl@num + }% + {% + \dtlmin{\@dtl@min}{\@dtl@min}{\@dtl@num}% + }% + }% + \ifdefempty{\@dtl@replaced}% + {% + \DTLdecimaltolocale{\@dtl@min}{#1}% + }% + {% + \DTLdecimaltocurrency{\@dtl@min}{#1}% + }% +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLgminall} +%\begin{definition} +%\cs{DTLgminall}\marg{cmd}\marg{num list} %\end{definition} -%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. +% Global version +% \begin{macrocode} +\newcommand*{\DTLgminall}[2]{% + \DTLminall{\@dtl@tmpi}{#2}% + \global\let#1=\@dtl@tmpi +} +% \end{macrocode} +%\end{macro} % -%\begin{definition}[\DescribeMacro{\DTLneg}]% -%\cs{DTLneg}\marg{cmd}\marg{num} -%\end{definition} -%\begin{definition}[\DescribeMacro{\DTLgneg}]% -%\cs{DTLgneg}\marg{cmd}\marg{num} +%\begin{macro}{\DTLmax} +%\begin{definition} +% \cs{DTLmax}\marg{cmd}\marg{num1}\marg{num2} %\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. +% Sets \meta{cmd} = max(\meta{num1}, \meta{num2}) +% \begin{macrocode} +\newcommand*{\DTLmax}[3]{% + \DTLconverttodecimal{#2}{\@dtl@numi}% + \DTLconverttodecimal{#3}{\@dtl@numii}% + \dtlmax{\@dtl@tmp}{\@dtl@numi}{\@dtl@numii}% + \dtlifnumgt{\@dtl@numi}{\@dtl@numii}% + {% + \dtl@ifsingle{#2}% + {\let#1=#2}% + {\def#1{#2}}% + }% + {% + \dtl@ifsingle{#3}% + {\let#1=#3}% + {\def#1{#3}}% + }% +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLgmax} +% Global version +% \begin{macrocode} +\newcommand*{\DTLgmax}[3]{% + \DTLmax{\@dtl@tmpii}{#2}{#3}% + \global\let#1=\@dtl@tmpii +} +% \end{macrocode} +%\end{macro} % -%\begin{definition}[\DescribeMacro{\DTLsqrt}]% -%\cs{DTLsqrt}\marg{cmd}\marg{num} +%\begin{macro}{\DTLmaxall} +%\begin{definition} +%\cs{DTLmaxall}\marg{cmd}\marg{num list} %\end{definition} -%\begin{definition}[\DescribeMacro{\DTLgsqrt}]% -%\cs{DTLgsqrt}\marg{cmd}\marg{num} +% Finds the maximum value in \meta{num list} and stores in +% \meta{cmd} which must be a control sequence. +%\changes{1.01}{2007 Aug 17}{removed extraneous space} +% \begin{macrocode} +\newcommand*{\DTLmaxall}[2]{% + \let\@dtl@max=\@empty + \@for\dtl@thisval:=#2\do{% + \expandafter\DTLconverttodecimal\expandafter{\dtl@thisval}{\@dtl@num}% + \ifdefempty{\@dtl@max}% + {% + \let\@dtl@max\@dtl@num + }% + {% + \dtlmax{\@dtl@max}{\@dtl@max}{\@dtl@num}% + }% + }% + \ifdefempty{\@dtl@replaced}% + {% + \DTLdecimaltolocale{\@dtl@max}{#1}% + }% + {% + \DTLdecimaltocurrency{\@dtl@max}{#1}% + }% +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLgmaxall} +%\begin{definition} +%\cs{DTLgmaxall}\marg{cmd}\marg{num list} %\end{definition} -%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. +% Global version +% \begin{macrocode} +\newcommand*{\DTLgmaxall}[2]{% +\DTLmaxall{\@dtl@tmpi}{#2}% +\global\let#1=\@dtl@tmpi +} +% \end{macrocode} +%\end{macro} % -%\begin{definition}[\DescribeMacro{\DTLmin}]% -%\cs{DTLmin}\marg{cmd}\marg{num1}\marg{num2} -%\end{definition} -%\begin{definition}[\DescribeMacro{\DTLgmin}]% -%\cs{DTLgmin}\marg{cmd}\marg{num1}\marg{num2} +%\begin{macro}{\DTLmeanforall} +%\begin{definition} +%\cs{DTLmeanforall}\marg{cmd}\marg{num list} %\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! -% -%\begin{definition}[\DescribeMacro{\DTLminall}]% -%\cs{DTLminall}\marg{cmd}\marg{number list} -%\end{definition} -%\begin{definition}[\DescribeMacro{\DTLgminall}]% -%\cs{DTLgminall}\marg{cmd}\marg{number list} -%\end{definition} -%This sets the control sequence \meta{cmd} to the minimum of all -%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. -% -%\begin{definition}[\DescribeMacro{\DTLmax}]% -%\cs{DTLmax}\marg{cmd}\marg{num1}\marg{num2} -%\end{definition} -%\begin{definition}[\DescribeMacro{\DTLgmax}]% -%\cs{DTLgmax}\marg{cmd}\marg{num1}\marg{num2} -%\end{definition} -%This sets the control sequence \meta{cmd} to the maximum of -%\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. -% -%\begin{definition}[\DescribeMacro{\DTLmaxall}]% -%\cs{DTLmaxall}\marg{cmd}\marg{number list} -%\end{definition} -%\begin{definition}[\DescribeMacro{\DTLgmaxall}]% -%\cs{DTLgmaxall}\marg{cmd}\marg{number list} -%\end{definition} -%This sets the control sequence \meta{cmd} to the maximum of all -%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. -% -%\begin{definition}[\DescribeMacro{\DTLmeanforall}]% -%\cs{DTLmeanforall}\marg{cmd}\marg{number list} -%\end{definition} -%\begin{definition}[\DescribeMacro{\DTLgmeanall}]% -%\cs{DTLgmeanforall}\marg{cmd}\marg{number list} -%\end{definition} -%This sets the control sequence \meta{cmd} to the arithmetic mean of all -%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. -% -%\begin{definition}[\DescribeMacro{\DTLvarianceforall}]% -%\cs{DTLvarianceforall}\marg{cmd}\marg{number list} -%\end{definition} -%\begin{definition}[\DescribeMacro{\DTLgvarianceforall}]% -%\cs{DTLgvarianceforall}\marg{cmd}\marg{number list} +% Computes the arithmetic mean of all the values in \meta{num list} +% and stores in \meta{cmd} which must be a control sequence. +%\changes{1.01}{2007 Aug 17}{removed extraneous space} +% \begin{macrocode} +\newcommand*{\DTLmeanforall}[2]{% + \def\@dtl@mean{0}% + \def\@dtl@n{0}% + \@for\dtl@thisval:=#2\do{% + \expandafter\DTLconverttodecimal\expandafter{\dtl@thisval}{\@dtl@num}% + \dtladd{\@dtl@mean}{\@dtl@mean}{\@dtl@num}% + \dtladd{\@dtl@n}{\@dtl@n}{1}% + }% + \dtldiv{\@dtl@mean}{\@dtl@mean}{\@dtl@n}% + \ifdefempty{\@dtl@replaced}% + {% + \DTLdecimaltolocale{\@dtl@mean}{#1}% + }% + {% + \DTLdecimaltocurrency{\@dtl@mean}{#1}% + }% +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLgmeanforall} +%\begin{definition} +%\cs{DTLgmeanforall}\marg{cmd}\marg{num list} %\end{definition} -%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. +% Global version +% \begin{macrocode} +\newcommand*{\DTLgmeanforall}[2]{% + \DTLmeanforall{\@dtl@tmpi}{#2}% + \global\let#1=\@dtl@tmpi +} +% \end{macrocode} +%\end{macro} % -%\begin{definition}[\DescribeMacro{\DTLsdforall}]% -%\cs{DTLsdforall}\marg{cmd}\marg{number list} +%\begin{macro}{\DTLvarianceforall} +%\begin{definition} +%\cs{DTLvarianceforall}\marg{cmd}\marg{num list} %\end{definition} -%\begin{definition}[\DescribeMacro{\DTLgsdforall}]% -%\cs{DTLgsdforall}\marg{cmd}\marg{number list} +% Computes the variance of all the values in \meta{num list} +% and stores in \meta{cmd} which must be a control sequence. +%\changes{1.01}{2007 Aug 17}{fixed bug} +%\changes{1.01}{2007 Aug 17}{removed extraneous space} +% \begin{macrocode} +\newcommand*{\DTLvarianceforall}[2]{% + \def\@dtl@mean{0}% + \def\@dtl@n{0}% + \let\@dtl@decvals=\@empty + \@for\dtl@thisval:=#2\do{% + \expandafter\DTLconverttodecimal\expandafter{\dtl@thisval}{\@dtl@num}% + \ifdefempty{\@dtl@decvals}% + {% + \let\@dtl@decvals=\@dtl@num + }% + {% + \expandafter\toks@\expandafter{\@dtl@decvals}% + \edef\@dtl@decvals{\the\toks@,\@dtl@num}% + }% + \dtladd{\@dtl@mean}{\@dtl@mean}{\@dtl@num}% + \dtladd{\@dtl@n}{\@dtl@n}{1}% + }% + \dtldiv{\@dtl@mean}{\@dtl@mean}{\@dtl@n}% + \def\@dtl@var{0}% + \@for\@dtl@num:=\@dtl@decvals\do{% + \dtlsub{\@dtl@diff}{\@dtl@num}{\@dtl@mean}% + \dtlmul{\@dtl@diff}{\@dtl@diff}{\@dtl@diff}% + \dtladd{\@dtl@var}{\@dtl@var}{\@dtl@diff}% + }% + \dtldiv{\@dtl@var}{\@dtl@var}{\@dtl@n}% + \ifdefempty{\@dtl@replaced}% + {% + \DTLdecimaltolocale{\@dtl@var}{#1}% + }% + {% + \DTLdecimaltocurrency{\@dtl@var}{#1}% + }% +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLgvarianceforall} +%\begin{definition} +%\cs{DTLgvarianceforall}\marg{cmd}\marg{num list} %\end{definition} -%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. +% Global version +% \begin{macrocode} +\newcommand*{\DTLgvarianceforall}[2]{% + \DTLvarianceforall{\@dtl@tmpi}{#2}% + \global\let#1=\@dtl@tmpi +} +% \end{macrocode} +%\end{macro} % -%\begin{definition}[\DescribeMacro{\DTLround}]% -%\cs{DTLround}\marg{cmd}\marg{num}\marg{num digits} +%\begin{macro}{\DTLsdforall} +%\begin{definition} +%\cs{DTLsdforall}\marg{cmd}\marg{num list} %\end{definition} -%\begin{definition}[\DescribeMacro{\DTLground}]% -%\cs{DTLground}\marg{cmd}\marg{num}\marg{num digits} +% Computes the standard deviation of all the values in \meta{num list} +% and stores in \meta{cmd} which must be a control sequence. +%\changes{1.01}{2007 Aug 17}{fixed bug} +%\changes{1.01}{2007 Aug 17}{removed extraneous space} +% \begin{macrocode} +\newcommand*{\DTLsdforall}[2]{% + \def\@dtl@mean{0}% + \def\@dtl@n{0}% + \let\@dtl@decvals=\@empty + \@for\dtl@thisval:=#2\do{% + \expandafter\DTLconverttodecimal\expandafter{\dtl@thisval}{\@dtl@num}% + \ifdefempty{\@dtl@decvals}% + {% + \let\@dtl@decvals=\@dtl@num + }% + {% + \expandafter\toks@\expandafter{\@dtl@decvals}% + \edef\@dtl@decvals{\the\toks@,\@dtl@num}% + }% + \dtladd{\@dtl@mean}{\@dtl@mean}{\@dtl@num}% + \dtladd{\@dtl@n}{\@dtl@n}{1}% + }% + \dtldiv{\@dtl@mean}{\@dtl@mean}{\@dtl@n}% + \def\@dtl@sd{0}% + \@for\@dtl@num:=\@dtl@decvals\do{% + \dtlsub{\@dtl@diff}{\@dtl@num}{\@dtl@mean}% + \dtlmul{\@dtl@diff}{\@dtl@diff}{\@dtl@diff}% + \dtladd{\@dtl@sd}{\@dtl@sd}{\@dtl@diff}% + }% + \dtldiv{\@dtl@sd}{\@dtl@sd}{\@dtl@n}% + \dtlroot{\@dtl@sd}{\@dtl@sd}{2}% + \ifdefempty{\@dtl@replaced}% + {% + \DTLdecimaltolocale{\@dtl@sd}{#1}% + }% + {% + \DTLdecimaltocurrency{\@dtl@sd}{#1}% + }% +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLgsdforall} +%\begin{definition} +%\cs{DTLgsdforall}\marg{cmd}\marg{num list} %\end{definition} -%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. Example: -%\begin{verbatim} -%\DTLround{\result}{3.135276}{2}\result -%\end{verbatim} -%produces: \DTLround{\result}{3.135276}{2}\result. +% Global version +% \begin{macrocode} +\newcommand*{\DTLgsdforall}[2]{% + \DTLsdforall{\@dtl@tmpi}{#2}% + \global\let#1=\@dtl@tmpi +} +% \end{macrocode} +%\end{macro} % -%\begin{definition}[\DescribeMacro{\DTLtrunc}]% -%\cs{DTLtrunc}\marg{cmd}\marg{num}\marg{num digits} -%\end{definition} -%\begin{definition}[\DescribeMacro{\DTLgtrunc}]% -%\cs{DTLgtrunc}\marg{cmd}\marg{num}\marg{num digits} +%\begin{macro}{\DTLround} +%\begin{definition} +% \cs{DTLround}\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. Example: -%\begin{verbatim} -%\DTLtrunc{\result}{3.135276}{2}\result -%\end{verbatim} -%produces: \DTLtrunc{\result}{3.135276}{2}\result. +% Sets \meta{cmd} to \meta{num} rounded to \meta{num digits} +% digits after the decimal character. +% \begin{macrocode} +\newcommand*{\DTLround}[3]{% + \DTLconverttodecimal{#2}{\@dtl@numi}% + \dtlround{\@dtl@tmp}{\@dtl@numi}{#3}% + \ifdefempty{\@dtl@replaced}% + {% + \DTLdecimaltolocale{\@dtl@tmp}{#1}% + }% + {% + \DTLdecimaltocurrency{\@dtl@tmp}{#1}% + }% +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLground} +% Global version +% \begin{macrocode} +\newcommand*{\DTLground}[3]{% + \DTLround{\@dtl@tmpii}{#2}{#3}% + \global\let#1=\@dtl@tmpii +} +% \end{macrocode} +%\end{macro} % -%\begin{definition}[\DescribeMacro{\DTLclip}]% -%\cs{DTLclip}\marg{cmd}\marg{num} -%\end{definition} -%\begin{definition}[\DescribeMacro{\DTLgclip}]% -%\cs{DTLgclip}\marg{cmd}\marg{num} +%\begin{macro}{\DTLtrunc} +%\begin{definition} +% \cs{DTLtrunc}\marg{cmd}\marg{num}\marg{num digits} %\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: +% Sets \meta{cmd} to \meta{num} truncated to \meta{num digits} +% digits after the decimal character. +% \begin{macrocode} +\newcommand*{\DTLtrunc}[3]{% + \DTLconverttodecimal{#2}{\@dtl@numi}% + \dtltrunc{\@dtl@tmp}{\@dtl@numi}{#3}% + \ifdefempty{\@dtl@replaced}% + {% + \DTLdecimaltolocale{\@dtl@tmp}{#1}% + }% + {% + \DTLdecimaltocurrency{\@dtl@tmp}{#1}% + }% +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLgtrunc} +% Global version +% \begin{macrocode} +\newcommand*{\DTLgtrunc}[3]{% + \DTLtrunc{\@dtl@tmpii}{#2}{#3}% + \global\let#1=\@dtl@tmpii +} +% \end{macrocode} +%\end{macro} % -%\begin{definition}[\DescribeMacro{\DTLsubstitute}]% -%\cs{DTLsubstitute}\marg{cmd}\marg{original}\marg{replacement} +%\begin{macro}{\DTLclip} +%\begin{definition} +% \cs{DTLclip}\marg{cmd}\marg{num} %\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. +% Sets \meta{cmd} to \meta{num} with all unnecessary 0's removed. +% \begin{macrocode} +\newcommand*{\DTLclip}[2]{% + \DTLconverttodecimal{#2}{\@dtl@numi}% + \dtlclip{\@dtl@tmp}{\@dtl@numi}% + \ifdefempty{\@dtl@replaced}% + {% + \DTLdecimaltolocale{\@dtl@tmp}{#1}% + }% + {% + \DTLdecimaltocurrency{\@dtl@tmp}{#1}% + }% +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLgclip} +% Global version +% \begin{macrocode} +\newcommand*{\DTLgclip}[3]{% + \DTLclip{\@dtl@tmpii}{#2}% + \global\let#1=\@dtl@tmpii +} +% \end{macrocode} +%\end{macro} % -%\begin{definition}[\DescribeMacro{\DTLsubstituteall}]% -%\cs{DTLsubstituteall}\marg{cmd}\marg{original}\marg{replacement} +%\section{String Macros} +%\begin{macro}{\DTLinitials} +%\begin{definition} +%\cs{DTLinitials}\marg{string} %\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. +% Convert a string into initials. +% (Any "~" character found is first converted into a space.) +%\changes{1.01}{2007 Aug 17}{now works with unbreakable space symbol} +%\changes{1.01}{2007 Aug 17}{now uses \cs{DTLinitialhyphen}} +% \begin{macrocode} +\newcommand*\DTLinitials[1]{% + \def\dtl@initialscmd{}% + \dtl@subnobrsp{#1}{\dtl@string}% + \DTLsubstituteall{\dtl@string}{~}{ }% + \DTLsubstituteall{\dtl@string}{\ }{ }% + \DTLsubstituteall{\dtl@string}{\space}{ }% + \expandafter\dtl@initials\dtl@string{} \@nil% + \dtl@initialscmd +}% +% \end{macrocode} +%\end{macro} +% The following substitutes "\protect \nobreakspace {}" with +% a space. (Note that in this case the space following +% "\nobreakspace" forms part of the command.) +% \begin{macrocode} +\edef\dtl@construct@subnobrsp{% +% \end{macrocode} +% Define \ics{@dtl@subnobrsp} +% \begin{macrocode} + \noexpand\def\noexpand\@dtl@subnobrsp##1\noexpand\protect + \expandafter\noexpand\csname nobreakspace \endcsname ##2{% + \noexpand\toks@{##1}% + \noexpand\expandafter\noexpand\@dtl@toks\noexpand\expandafter{% + \noexpand\@dtl@string}% + \noexpand\edef\noexpand\@dtl@string{\noexpand\the\noexpand\@dtl@toks + \noexpand\the\noexpand\toks@}% + \noexpand\def\noexpand\@dtl@tmp{##2}% + \noexpand\ifx\noexpand\@dtl@tmp\noexpand\@nnil + \noexpand\let\noexpand\@dtl@subnobrspnext=\noexpand\relax + \noexpand\else + \noexpand\toks@{ }% + \noexpand\expandafter\noexpand\@dtl@toks\noexpand\expandafter{% + \noexpand\@dtl@string}% + \noexpand\edef\noexpand\@dtl@string{\noexpand\the\noexpand\@dtl@toks + \noexpand\the\noexpand\toks@}% + \noexpand\let\noexpand\@dtl@subnobrspnext=\noexpand\@dtl@subnobrsp + \noexpand\fi + \noexpand\@dtl@subnobrspnext + }% +% \end{macrocode} +% Define \ics{dtl@subnobrsp} +% \begin{macrocode} + \noexpand\def\noexpand\dtl@subnobrsp##1##2{% + \noexpand\def\noexpand\@dtl@string{}% + \noexpand\@dtl@subnobrsp ##1\noexpand\protect\expandafter\noexpand + \csname nobreakspace \endcsname \noexpand\@nil + \noexpand\let##2=\noexpand\@dtl@string + }% +} +\dtl@construct@subnobrsp +% \end{macrocode} % -%\begin{definition}[\DescribeMacro{\DTLsplitstring}]% -%\cs{DTLsplitstring}\marg{string}\marg{split text}\marg{before -%cmd}\marg{after cmd} +%\begin{macro}{\DTLstoreinitials} +%\begin{definition} +%\cs{DTLstoreinitials}\marg{string}\marg{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''. -% -%\begin{definition}[\DescribeMacro{\DTLinitials}]% -%\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}} +% Convert a string into initials and store in \meta{cmd}. +% (Any "~" character found is first converted into a space.) +%\changes{1.01}{2007 Aug 17}{now works with unbreakable space symbol} +%\changes{1.01}{2007 Aug 17}{now uses \cs{DTLinitialhyphen}} +% \begin{macrocode} +\newcommand*{\DTLstoreinitials}[2]{% + \def\dtl@initialscmd{}% + \dtl@subnobrsp{#1}{\dtl@string}% + \DTLsubstituteall{\dtl@string}{~}{ }% + \DTLsubstituteall{\dtl@string}{\ }{ }% + \DTLsubstituteall{\dtl@string}{\space}{ }% + \expandafter\dtl@initials\dtl@string{} \@nil + \let#2=\dtl@initialscmd +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\dtl@initials} +% \begin{macrocode} +\def\dtl@initials#1#2 #3{% + \dtl@ifsingle{#1}% + {% + \ifcat\noexpand#1\relax\relax + \def\@dtl@donextinitials{\@dtl@initials#2 {#3}}% + \else + \def\@dtl@donextinitials{\@dtl@initials#1#2 {#3}}% + \fi + }% + {% + \def\@dtl@donextinitials{\@dtl@initials{#1}#2 {#3}}% + }% + \@dtl@donextinitials +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\@dtl@initials} +% \begin{macrocode} +\def\@dtl@initials#1#2 #3{% + \dtl@initialshyphen#2-{}\dtl@endhyp + \expandafter\@dtl@toks\expandafter{\dtl@initialscmd}% + \toks@{#1}% + \ifdefempty{\dtl@inithyphen}% + {% + }% + {% + \edef\dtl@initialscmd{\the\@dtl@toks\the\toks@}% + \expandafter\@dtl@toks\expandafter{\dtl@initialscmd}% + \expandafter\toks@\expandafter{\dtl@inithyphen}% + }% + \def\dtl@tmp{#3}% + \ifx\@nnil\dtl@tmp + \edef\dtl@initialscmd{\the\@dtl@toks\the\toks@\DTLafterinitials}% + \let\dtl@initialsnext=\@gobble + \else + \edef\dtl@initialscmd{\the\@dtl@toks\the\toks@\DTLbetweeninitials}% + \let\dtl@initialsnext=\dtl@initials + \fi + \dtl@initialsnext{#3}% +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\dtl@initialshyphen} +% \begin{macrocode} +\def\dtl@initialshyphen#1-#2#3\dtl@endhyp{% + \def\dtl@inithyphen{#2}% + \ifdefempty{\dtl@inithyphen}% + {% + }% + {% + \edef\dtl@inithyphen{% + \DTLafterinitialbeforehyphen\DTLinitialhyphen#2}% + }% +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLafterinitials} +% Defines what to do after the final initial. +% \begin{macrocode} +\newcommand*{\DTLafterinitials}{.} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLbetweeninitials} +% Defines what to do between initials. +% \begin{macrocode} +\newcommand*{\DTLbetweeninitials}{.} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLafterinitialbeforehyphen} +% Defines what to do before a hyphen. +% \begin{macrocode} +\newcommand*{\DTLafterinitialbeforehyphen}{.} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLinitialhyphen} +%Defines what to do at the hyphen +%\changes{1.01}{2007 Aug 17}{new} +% \begin{macrocode} +\newcommand*{\DTLinitialhyphen}{-} +% \end{macrocode} +%\end{macro} % -%\begin{definition}[\DescribeMacro{\DTLstoreinitials}]% -%\cs{DTLstoreinitials}\marg{string}\marg{cmd} +%\begin{macro}{\DTLifAllUpperCase} +%\begin{definition} +%\cs{DTLifAllUpperCase}\marg{string}\marg{true part}\marg{false part} %\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: -%\begin{definition}[\DescribeMacro{\DTLafterinitials}]% -%\cs{DTLafterinitials} +% 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} -%This indicates what to do at the end of the initials. This -%simply does a full stop by default. +% If \meta{string} only contains lowercase characters do \meta{true +%part}, otherwise do \meta{false part}. +% \begin{macrocode} +\newcommand*{\DTLifAllLowerCase}[3]{% + \protected@edef\dtl@tlc{#1}% + \expandafter\dtl@testiflowercase\dtl@tlc\@nil\relax + \if@dtl@condition#2\else#3\fi +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\dtl@testifalllowercase} +% \begin{macrocode} +\def\dtl@testiflowercase#1#2{% + \def\dtl@argi{#1}% + \def\dtl@argii{#2}% + \ifx\dtl@argi\@nnil + \let\dtl@testiflowernext=\@nnil + \else + \ifx#1\protect + \let\dtl@testiflowernext=\dtl@testiflowercase + \else + \ifx\lowercase#1\relax + \@dtl@conditiontrue + \def\dtl@tc@rest{}% + \let\dtl@testiflowernext=\relax + \else + \edef\dtl@tc@arg{\string#1}% + \expandafter\dtl@test@iflowercase\dtl@tc@arg\end + \ifx\dtl@argii\@nnil + \let\dtl@testiflowernext=\@dtl@gobbletonil + \fi + \fi + \fi + \fi + \ifx\dtl@testiflowernext\relax + \edef\dtl@dotestiflowernext{% + \noexpand\dtl@testiflowercase}% + \else + \ifx\dtl@testiflowernext\@nnil + \edef\dtl@dotestiflowernext{#2}% + \else + \expandafter\toks@\expandafter{\dtl@tc@rest}% + \@dtl@toks{#2}% + \edef\dtl@dotestiflowernext{% + \noexpand\dtl@testiflowernext\the\toks@\the\@dtl@toks}% + \fi + \fi + \dtl@dotestiflowernext +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\dtl@test@ifalllowercase} +% \begin{macrocode} +\def\dtl@test@iflowercase#1#2\end{% + \def\dtl@tc@rest{#2}% + \IfSubStringInString{\string\MakeLowercase}{#1#2}% + {% + \@dtl@conditiontrue + \def\dtl@tc@rest{}% + \let\dtl@testiflowernext=\relax + }% + {% + \IfSubStringInString{\string\MakeTextLowercase}{#1#2}% + {% + \@dtl@conditiontrue + \def\dtl@tc@rest{}% + \let\dtl@testiflowernext=\relax + }% + {% + \edef\dtl@lccode{\the\lccode`#1}% + \edef\dtl@code{\number`#1}% + \ifnum\dtl@code=\dtl@lccode\relax + \@dtl@conditiontrue + \let\dtl@testiflowernext=\dtl@testiflowercase + \else + \ifnum\dtl@lccode=0\relax + \@dtl@conditiontrue + \let\dtl@testiflowernext=\dtl@testiflowercase + \else + \@dtl@conditionfalse + \let\dtl@testiflowernext=\@dtl@gobbletonil + \fi + \fi + }% + }% +} +% \end{macrocode} +%\end{macro} % -%\begin{definition}[\DescribeMacro{\DTLbetweeninitials}]% -%\cs{DTLbetweeninitials} +%\begin{macro}{\DTLsubstitute} +%\begin{definition} +%\cs{DTLsubstitute}\marg{cmd}\marg{original}\marg{replacement} %\end{definition} -%This indicates what to do between initials. This does a -%full stop by default. -% -%\begin{definition}[\DescribeMacro{\DTLinitialhyphen}]% -%\cs{DTLinitialhyphen} +% Substitutes first occurrence of \meta{original} with +% \marg{replacement} within the string given by \meta{cmd} +% \begin{macrocode} +\newcommand{\DTLsubstitute}[3]{% + \expandafter\DTLsplitstring\expandafter + {#1}{#2}{\@dtl@beforepart}{\@dtl@afterpart}% + \ifdefempty{\@dtl@replaced}% + {% + }% + {% + \def#1{}% + \expandafter\@dtl@toks\expandafter{\@dtl@beforepart}% + \expandafter\toks@\expandafter{#1}% + \protected@edef#1{\the\toks@\the\@dtl@toks#3}% + \expandafter\@dtl@toks\expandafter{\@dtl@afterpart}% + \expandafter\toks@\expandafter{#1}% + \edef#1{\the\toks@\the\@dtl@toks}% + }% +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLsplitstring} +%\begin{definition} +%\cs{DTLsplitstring}\marg{string}\marg{split text}\marg{before +%cmd}\marg{after cmd} %\end{definition} -%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. +% Splits string at \meta{split text} stores the pre split text +% in \meta{before cmd} and the post split text in \meta{after cmd}. +%\changes{1.01}{2007 Aug 17}{new} +% \begin{macrocode} +\newcommand*{\DTLsplitstring}[4]{% + \def\dtl@splitstr##1#2##2\@nil{% + \def#3{##1}% + \def#4{##2}% + \ifdefempty{#4}% + {% + \let\@dtl@replaced=\@empty + }% + {% + \def\@dtl@replaced{#2}% + \dtl@split@str##2\@nil + }% + }% + \def\dtl@split@str##1#2\@nil{% + \def#4{##1}}% + \dtl@splitstr#1#2\@nil +} +% \end{macrocode} +%\end{macro} % -%\begin{definition}[\DescribeMacro{\DTLafterinitialbeforehyphen}]% -%\cs{DTLafterinitialbeforehyphen} +%\begin{macro}{\DTLsubstituteall} +%\begin{definition} +%\cs{DTLsubstituteall}\marg{cmd}\marg{original}\marg{replacement} %\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. -% -%\importantpar Whilst \TeX\ is an excellent typesetting language, -%it is not designed as a database management system, and -%attempting to use it as such is like trying to fasten a screw -%with a knife instead of a screwdriver: it can be done, but requires -%great care and is more time consuming. Version 2.0 of the -%\sty{datatool} package uses a completely different method of storing -%the data to previous versions.\footnote{Thanks to Morten H\o gholm -%for the suggestion.} As a result, the code is much more efficient, -%however, large databases and complex operations will still slow the -%time taken to process your document. Therefore, if you can, it is -%better to do the complex operations using whatever system created -%the data in the first place. -% -%\subsection{Creating a New Database} -%\label{sec:newdb} -% -%\begin{definition}[\DescribeMacro{\DTLnewdb}]% -%\cs{DTLnewdb}\marg{db name} -%\end{definition} -%This command creates a new empty database called \meta{db name}. You -%can test if a database is empty using: -%\begin{definition}[\DescribeMacro{\DTLifdbempty}]% -%\cs{DTLifdbempty}\marg{db name}\marg{true part}\marg{false part} -%\end{definition} -%If the database called \meta{db name} is empty, do \meta{true part}, -%otherwise do \meta{false part}. -% -%\begin{definition}[\DescribeMacro{\DTLrowcount}]% -%\cs{DTLrowcount}\marg{db name} -%\end{definition} -%This command displays the number of rows in the database called -%\meta{db name}. -% -%\begin{definition}[\DescribeMacro{\DTLcolumncount}]% -%\cs{DTLcolumncount}\marg{db name} -%\end{definition} -%This command displays the number of columns (or keys) in the -%database called \meta{db name}. -% -%\begin{definition}[\DescribeMacro{\DTLnewrow}]% -%\cs{DTLnewrow}\marg{db name} -%\end{definition} -%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}. The column count is given by -%\begin{verbatim} -%\DTLcolumncount{mydata} -%\end{verbatim} -%which produces: \DTLcolumncount{mydata}. +% Substitutes all occurrences of \meta{original} with +% \marg{replacement} within the string given by \meta{cmd} +%\changes{1.01}{2007 Aug 17}{fixed bug caused when certain commands +% occur in the string} +%\changes{2.10}{2012-07-18}{added \cs{long}} +% \begin{macrocode} +\newcommand{\DTLsubstituteall}[3]{% + \def\@dtl@splitsubstr{}% + \let\@dtl@afterpart=#1\relax + \@dtl@dosubstitute{#2}{#3}% + \expandafter\toks@\expandafter{\@dtl@splitsubstr}% + \expandafter\@dtl@toks\expandafter{\@dtl@afterpart}% + \long\edef#1{\the\toks@\the\@dtl@toks}% +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\@dtl@dosubstitute} +% Recursive substitution macro. +% \begin{macrocode} +\def\@dtl@dosubstitute#1#2{% + \expandafter\DTLsplitstring\expandafter + {\@dtl@afterpart}{#1}{\@dtl@beforepart}{\@dtl@afterpart}% + \expandafter\toks@\expandafter{\@dtl@splitsubstr}% + \expandafter\@dtl@toks\expandafter{\@dtl@beforepart}% + \edef\@dtl@splitsubstr{\the\toks@\the\@dtl@toks}% + \ifdefempty{\@dtl@replaced}% + {% + \let\@dtl@dosubstnext=\@dtl@dosubstitutenoop + }% + {% + \expandafter\toks@\expandafter{\@dtl@splitsubstr}% + \@dtl@toks{#2}% + \edef\@dtl@splitsubstr{\the\toks@\the\@dtl@toks}% + \let\@dtl@dosubstnext=\@dtl@dosubstitute + }% + \@dtl@dosubstnext{#1}{#2}% +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\@dtl@dosubstitutenoop} +% Terminates recursive substitution macro. +% \begin{macrocode} +\def\@dtl@dosubstitutenoop#1#2{} +% \end{macrocode} +%\end{macro} % -%\begin{definition}[\DescribeMacro{\DTLnewdbentry}]% -%\cs{DTLnewdbentry}\marg{db name}\marg{key}\marg{value} -%\end{definition} -%This creates a new entry with the identifier \meta{key} whose value -%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}. Note that the -%key should not contain any fragile commands. It is generally -%best to only use non-active characters in the key. +%\section{Conditionals} % -%The value isn't expanded by default, but you can change this -%using the declaration: -%\begin{definition}[\DescribeMacro{\dtlexpandnewvalue}] -%\cs{dtlexpandnewvalue} -%\end{definition} -%This can be localised by placing it in a group, or you can -%switch back using: -%\begin{definition}[\DescribeMacro{\dtlnoexpandnewvalue}] -%\cs{dtlnoexpandnewvalue} -%\end{definition} +%\begin{macro}{\if@dtl@condition} +% \begin{macrocode} +\newif\if@dtl@condition +% \end{macrocode} +%\end{macro} % -%\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: -%\begin{definition}[\DescribeMacro{\DTLpar}]% -%\cs{DTLpar} +% \subsection{Determining Data Types} +% The control sequence \cs{@dtl@checknumerical} checks the data +% type of its argument, and sets \cs{@dtl@datatype} to 0 if +% the argument is a string, 1 if the argument is an integer +% or 2 if the argument is a real number. First define +% \cs{@dtl@datatype}: +%\begin{macro}{\@dtl@datatype} +% \begin{macrocode} +\newcount\@dtl@datatype +% \end{macrocode} +%\end{macro} +%\begin{macro}{\@dtl@checknumerical} +%\begin{definition} +%\cs{@dtl@checknumerical}\marg{arg} %\end{definition} +% Checks if \meta{arg} is numerical +% (includes decimal numbers, but not scientific notation.) +% Sets \cs{@dtl@datatype}, as described above. +% \begin{macrocode} +\newcommand{\@dtl@checknumerical}[1]{% + \@dtl@numgrpsepfalse + \def\@dtl@tmp{#1}% + \ifstrempty{#1}% + {% + \@dtl@datatype=0\relax + }% + {% + \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 + \ifdefempty{\@dtl@org@currency}% + {% + }% + {% + \let\@dtl@currency\@dtl@org@currency + }% + \expandafter\@dtl@checknumericalstart\@dtl@tmp\@nil\@nil + }% + \ifnum\@dtl@numgrpsepcount>-1\relax + \if@dtl@numgrpsep + \ifnum\@dtl@numgrpsepcount=3\relax + \else + \@dtl@datatype=0\relax + \fi + \fi + \fi +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\@dtl@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\relax + \@dtl@checknumericalstart#2\@nil\@nil\relax +\else + \ifx-#1\relax + \def\@dtl@tmp{#2}% + \ifdefempty{\@dtl@tmp}% + {% + \@dtl@datatype=0\relax + }% + {% + \ifnum\@dtl@datatype=0\relax + \@dtl@datatype=1\relax + \fi + \@dtl@checknumericalstart#2\@nil\@nil\relax + }% + \else + \ifx+#1\relax + \def\@dtl@tmp{#2}% + \ifdefempty{\@dtl@tmp}% + {% + \@dtl@datatype=0\relax + }% + {% + \ifnum\@dtl@datatype=0\relax + \@dtl@datatype=1\relax + \fi + \@dtl@checknumericalstart#2\@nil\@nil\relax + }% + \else + \def\@dtl@tmp{#1}% + \ifx#1\$\relax + \@dtl@datatype=3\relax + \@dtl@checknumericalstart#2\@nil\@nil\relax + \else + \ifdefempty{\@dtl@tmp}% + {% + \@dtl@datatype=0\relax + }% + {% + \ifnum\@dtl@datatype=0\relax + \@dtl@datatype=1\relax + \fi + \@dtl@checknumericalloop#1#2\@nil\@nil\relax + }% + \fi + \fi + \fi +\fi +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\if@dtl@numgrpsep} +% The conditional \cs{if@dtl@numgrpsep} is set the first time +% \cs{@dtl@checknumericalloop} encounters the number group +% separator. +% \begin{macrocode} +\newif\if@dtl@numgrpsep +% \end{macrocode} +%\end{macro} +%\begin{macro}{\@dtl@ifDigitOrDecimalSep} +% Check if argument is either a digit or the decimal separator. +% Rewrite provided by Bruno Le Floch. +%\changes{1.01}{2007 Aug 17}{new} +%\changes{2.10}{2012-07-18}{Rewritten} +% \begin{macrocode} +\newcommand*{\@dtl@ifDigitOrDecimalSep}[3]{% + \ifnum 9<1\noexpand#1\relax + #2% + \else + \expandafter\ifx\@dtl@decimal#1\relax + #2% + \else + #3% + \fi + \fi +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\@dtl@checknumericalloop} +% Check numerical loop. This iterates through each character +% until \cs{@nil} is reached, or invalid character found. +% Increments \cs{@dtl@tmpcount} each time it encounters a +% decimal character.\changes{1.01}{2007 Aug 17}{fixed bug caused +% by commands occuring within text being tested} +% \begin{macrocode} +\def\@dtl@checknumericalloop#1#2\@nil{% +\def\@dtl@tmp{#1}% +\ifx\@nnil\@dtl@tmp\relax + \let\@dtl@chcknumnext=\@dtl@checknumericalnoop% +\else + \@dtl@ifDigitOrDecimalSep{#1}{% + \let\@dtl@chcknumnext=\@dtl@checknumericalloop% + \expandafter\ifx\@dtl@decimal#1\relax + \if@dtl@numgrpsep + \ifnum\@dtl@numgrpsepcount=3\relax + \@dtl@numgrpsepcount=-1\relax + \else + \@dtl@datatype=0\relax + \let\@dtl@chcknumnext=\@dtl@checknumericalnoop + \fi + \else + \@dtl@numgrpsepcount=-1\relax + \fi + \else + \ifnum\@dtl@numgrpsepcount=-1\relax + \else + \advance\@dtl@numgrpsepcount by 1\relax + \fi + \fi +}{% +\ifx\@dtl@numbergroupchar\@dtl@tmp\relax + \@dtl@numgrpseptrue + \ifnum\@dtl@numgrpsepcount<3\relax + \@dtl@datatype=0\relax + \let\@dtl@chcknumnext=\@dtl@checknumericalnoop + \else + \@dtl@numgrpsepcount=0\relax + \fi +\else + \@dtl@datatype=0\relax + \let\@dtl@chcknumnext=\@dtl@checknumericalnoop +\fi +}% + \ifx\@dtl@decimal\@dtl@tmp\relax + \ifnum\@dtl@datatype<3\relax + \@dtl@datatype=2\relax + \fi + \advance\@dtl@tmpcount by 1\relax + \ifnum\@dtl@tmpcount>1\relax + \@dtl@datatype=0\relax + \let\@dtl@chcknumnext=\@dtl@checknumericalnoop% + \fi + \fi +\fi +\@dtl@chcknumnext#2\@nil +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\@dtl@checknumericalnoop} +% End loop +% \begin{macrocode} +\def\@dtl@checknumericalnoop#1\@nil#2{} +% \end{macrocode} +%\end{macro} % -%For example: -%\begin{verbatim} -%\DTLnewdbentry{mydata}{Description}{First paragraph.\DTLpar -%Second paragraph.} -%\end{verbatim} -% -%\begin{definition}[\DescribeMacro{\DTLaddentryforrow}]% -%\cs{DTLaddentryforrow}\marg{db}\marg{assign list}\marg{condition}\marg{key}\marg{value} -%\end{definition} -%This adds the entry with the key given by \meta{key} and value -%given by \meta{value} to the first row in the database -%\meta{db} 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}). For example: -%\begin{verbatim} -%\DTLaddentryforrow{mydata}{\firstname=FirstName,\surname=Surname}% -%{\DTLiseq{\firstname}{John}\and\DTLiseq{\surname}{Smith}}% -%{Score}{75} -%\end{verbatim} -%Note that unlike \cs{DTLnewdbentry}, the value is always expanded -%when adding an entry using \cs{DTLaddentryforrow}. -% -%\begin{definition}[\DescribeMacro{\DTLsetheader}]% -%\cs{DTLsetheader}\marg{db}\marg{key}\marg{header} +%\begin{macro}{\DTLifnumerical} +%\begin{definition} +%\cs{DTLifnumerical}\marg{arg}\marg{true part}\marg{false part} %\end{definition} -%This assigns a header for a given key in the database named -%\meta{db}. This is used by \cs{DTLdisplaydb} and -%\cs{DTLdisplaylongdb} in the header row (see -%\autoref{sec:displaydb}). If you don't assign -%a header, the header will be given by the key. -%For example: -%\begin{verbatim} -%\DTLsetheader{mydata}{Price}{Price (\$)} -%\end{verbatim} -% -%\subsection{Loading a Database from an External ASCII File} -%\label{sec:loaddb} -% -%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: -%\begin{definition}[\DescribeMacro{\DTLloaddb}]% -%\cs{DTLloaddb}\oarg{options}\marg{db name}\marg{filename} -%\end{definition} -%This creates a new database called \meta{db name}, and fills -%it with the entries given in the file \meta{filename}. -%The filename may have a header row at the start of the file, -%which provides the \meta{key} when creating a new database entry -%using \ics{DTLnewdbentry}. The optional argument \meta{options} -%is a key=value list of options. Available options are: -%\begin{description} -%\item[\cmdopt{DTLloaddb}{noheader}] This is a boolean value and -%indicates if the file does not contain a header. If no value is -%supplied, "true" is assumed (i.e.\ the file doesn't contain a header -%row). If this option is omitted, it is assumed that the file -%contains a header row. -% -%\item[\cmdopt{DTLloaddb}{keys}] This is a comma-separated list of -%keys to use, where the keys are listed in the same order as the -%columns. If the file has a header, these keys will override the -%values given in the header row. If the file has no header row and no -%keys are supplied in \meta{options}, then the keys will be given by -%\cs{dtldefaultkey}\meta{n}, where \meta{n} is the column number and -%\DescribeMacro{\dtldefaultkey}\cs{dtldefaultkey} defaults to -%``\dtldefaultkey''. Note that the list of keys must be delimited by -%braces since they contain commas. For example: -%\begin{verbatim} -%\DTLloaddb[noheader,keys={Temperature,Time,T2G}]{data}{data.csv} -%\end{verbatim} -% -%\item[\cmdopt{DTLloaddb}{headers}] This is a comma-separated list of -%headers. If not supplied, the header will be the same as that given -%in the header row, or the key if there is no header row. Note that -%the list of headers must be delimited by braces since they contain -%commas. For example: -%\begin{verbatim} -%\DTLloaddb[noheader,keys={Temperature,Time,T2G},% -%headers={\shortstack{Incubation\\Temperature},% -%\shortstack{Incubation\\Time},% -%\shortstack{Time to\\Growth}}]{data}{data.csv} -%\end{verbatim} -%\end{description} +% 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} % -%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: -%\begin{definition}[\DescribeMacro{\DTLsettabseparator}]% -%\cs{DTLsettabseparator} -%\end{definition} -%To set the separator to a character other than a tab, you need to use -%\begin{definition}[\DescribeMacro{\DTLsetseparator}]% -%\cs{DTLsetseparator}\marg{character} -%\end{definition} -%The delimiter can be changed using -%\begin{definition}[\DescribeMacro{\DTLsetdelimiter}]% -%\cs{DTLsetdelimiter}\marg{character} +%\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} % -%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: -%\begin{definition}[\DescribeMacro{\DTLloadrawdb}]% -%\cs{DTLloadrawdb}\oarg{options}\marg{db name}\marg{filename} -%\end{definition} -%This is the same as \ics{DTLloaddb} except that it maps nine of -%the ten special characters onto commands which produce that -%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} -%\centering -%\begin{tabular}{cl} -%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{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 may therefore be necessary to convert -%this symbol to an appropriate control sequence. This can be done -%using the command: -%\begin{definition}[\DescribeMacro{\DTLrawmap}]% -%\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 replace all occurrences\footnote{when it is loaded into the -%\LaTeX\ database, it does not modify the data file!}\ of -%\texttt{\pounds} with \cs{pounds}. Naturally, the mappings must be -%set \emph{prior} to loading the data with \cs{DTLloadrawdb}. -% -%\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{Displaying the Contents of a Database} -%\label{sec:displaydb} -% -%Once you have created a database, either loading it from an -%external file, as described in \autoref{sec:loaddb}, or using the -%commands described in \autoref{sec:newdb}, you can display the -%entire database in a \env{tabular} or \env{longtable} -%environment. -% -%\begin{definition}[\DescribeMacro{\DTLdisplaydb}]% -%\cs{DTLdisplaydb}\marg{db} -%\end{definition} -%This displays the database given by \meta{db} in a \env{tabular} -%environment. The first row displays the headers for the database -%in bold, the subsequent rows display the values for each key -%in each row of the database. -% -%\begin{definition}[\DescribeMacro{\DTLdisplaylongdb}]% -%\cs{DTLdisplaylongdb}\oarg{options}\marg{db} -%\end{definition} -%This is like \cs{DTLdisplaydb} except that it uses the -%\env{longtable} environment instead of the \env{tabular} -%environment. Note that if you use this command, you must load the -%\sty{longtable} package, as it is not loaded by \sty{datatool}. -%The optional argument \meta{options} is a comma-separated list -%of key=value pairs. The following keys are available: -%\begin{description} -%\item[caption] The caption for the \env{longtable}. -% -%\item[contcaption] The continuation caption. -% -%\item[shortcaption] The caption to be used in the list of figures. -% -%\item[label] The label for this table. -% -%\item[foot] The \env{longtable}'s foot. -% -%\item[lastfoot] The foot for the last page of the \env{longtable}. -%\end{description} -%For example, suppose I have a database called "iris", then I can -%display the contents in a \env{longtable} using: -%\begin{verbatim} -%\DTLdisplaylongdb[% -%caption={Iris Data},% -%label={tab:iris},% -%contcaption={Iris Data (continued)},% -%foot={\em Continued overleaf},% -%lastfoot={}% -%]{iris} -%\end{verbatim} -%I can then reference the table using \verb|\ref{tab:iris}|. -% -%See the \sty{longtable} documentation for details on how to -%change the \env{longtable} settings, such as how to change the -%table so that it is left aligned instead of centred on the page. -% -%Note that if you want more control over the way the data is -%displayed, for example, you want to filter rows or columns, you will -%need to use \cs{DTLforeach}, described in \autoref{sec:dbforeach}. -% -%\begin{example}{Displaying the Contents of a Database}{ex:displaydb} -%Suppose I have a file called \texttt{t2g.csv} that contains the -%following: -%\begin{verbatim} -%40,120,40 -%40,90,60 -%35,180,20 -%55,190,40 -%\end{verbatim} -%This represents time to growth data, where the first column -%is the incubation temperature, the second column is the incubation -%time and the third column is the time to growth. This file has no -%header row, so when it is loaded, the \cmdopt{DTLloaddb}{noheaders} -%option is required. Note that \cs{DTLdisplaydb} only puts the data -%in a \env{tabular} environment, so \cs{DTLdisplaydb} needs to be -%put in a \env{table} environment with a caption to make it a float. -% -%First load the data base, setting the keys and headers: -%\begin{verbatim} -%\DTLloaddb[noheader,% -%keys={Temperature,Time,T2G},% -%headers={\shortstack{Incubation\\Temperature},% -%\shortstack{Incubation\\Time},\shortstack{Time to\\Growth}}% -%]{t2g}{t2g.csv} -%\end{verbatim} -%\DTLnewdb{t2g}\relax -%\DTLnewrow*{t2g}\relax -%\DTLnewdbentry*{t2g}{Temperature}{40}\relax -%\DTLnewdbentry*{t2g}{Time}{120}\relax -%\DTLnewdbentry*{t2g}{T2G}{40}\relax -%\DTLnewrow*{t2g}\relax -%\DTLnewdbentry*{t2g}{Temperature}{40}\relax -%\DTLnewdbentry*{t2g}{Time}{90}\relax -%\DTLnewdbentry*{t2g}{T2G}{60}\relax -%\DTLnewrow*{t2g}\relax -%\DTLnewdbentry*{t2g}{Temperature}{35}\relax -%\DTLnewdbentry*{t2g}{Time}{180}\relax -%\DTLnewdbentry*{t2g}{T2G}{20}\relax -%\DTLnewrow*{t2g}\relax -%\DTLnewdbentry*{t2g}{Temperature}{55}\relax -%\DTLnewdbentry*{t2g}{Time}{190}\relax -%\DTLnewdbentry*{t2g}{T2G}{40}\relax -%\DTLsetheader*{t2g}{Temperature}{\shortstack{Incubation\\Temperature}}\relax -%\DTLsetheader*{t2g}{Time}{\shortstack {Incubation\\Time}}\relax -%\DTLsetheader*{t2g}{T2G}{\shortstack {Time to\\Growth}}\relax -% -%Now display the data in a table: -%\begin{verbatim} -%\begin{table}[htbp] -%\caption{Time to Growth Data} -%\centering -%\DTLdisplaydb{t2g} -%\end{table} -%\end{verbatim} -%The result is shown in \autoref{tab:t2g}. -%\begin{table}[htbp] -%\caption{Time to Growth Data} -%\label{tab:t2g} -%\centering -%\DTLdisplaydb{t2g} -%\end{table} -%\end{example} -% -%Each column in the database has an associated data type which -%indicates what type of data is in that column. This may be one -%of: string, integer, real number or currency. If a column contains -%more than one type, the data type is determined as follows: -%\begin{itemize} -%\item If the column contains at least one string, then the column -%data type is string. -% -%\item If the column doesn't contain a string, but contains at least -%one currency, then the column data type is currency. -% -%\item If the column contains only real numbers and integers, the -%column data type is real number. -% -%\item The column data type is integer if the column only -%contains integers. -%\end{itemize} -%The column data type is updated whenever a new entry is added -%to the database. Note that the column data type is not adjusted -%when an entry is removed from the database. -% -%The column alignments used by \cs{DTLdisplaydb} are given by: -%\begin{definition}[\DescribeMacro{\dtlstringalign}]% -%\cs{dtlstringalign} -%\end{definition}\noindent -%The string alignment defaults to \texttt{l} (left aligned). -% -%\begin{definition}[\DescribeMacro{\dtlintalign}]% -%\cs{dtlintalign} -%\end{definition}\noindent -%The integer alignment defaults to \texttt{r} (right aligned). -% -%\begin{definition}[\DescribeMacro{\dtlrealalign}]% -%\cs{dtlrealalign} -%\end{definition}\noindent -%The alignment for real numbers defaults to \texttt{r} (right -%aligned). -% -%\begin{definition}[\DescribeMacro{\dtlcurrencyalign}]% -%\cs{dtlcurrencyalign} -%\end{definition}\noindent -%The currency alignment defaults to \texttt{r} (right aligned). -% -%You can redefine these to change the column alignments. For -%example, if you want columns containing strings to have the -%alignment "p{2in}", then you can redefine \cs{dtlstringalign} as -%follows: -%\begin{verbatim} -%\renewcommand{\dtlstringalign}{p{2in}} -%\end{verbatim} -% -%\importantpar You can't use \sty{siunitx}'s "S" column alignment -%with either \cs{DTLdisplaydb} or \cs{DTLdisplaylongdb}. Instead, you -%will need to use \cs{DTLforeach}. The \sty{siunitx} documentation -%provides an example. -% -%In addition to the \cs{dtl}\meta{type}"align" commands above, you -%can also modify the \env{tabular} column styles by redefining -%\DescribeMacro{\dtlbeforecols}\cs{dtlbeforecols}, -%\DescribeMacro{\dtlbetweencols}\cs{dtlbetweencols} and -%\DescribeMacro{\dtlaftercols}\cs{dtlaftercols}. For example, to -%place a vertical line before the start of the first column and -%after the last column, do: -%\begin{verbatim} -%\renewcommand{\dtlbeforecols}{|} -%\renewcommand{\dtlaftercols}{|} -%\end{verbatim} -%If you additionally want vertical lines between columns, do: -%\begin{verbatim} -%\renewcommand{\dtlbetweencols}{|} -%\end{verbatim} -% -%Limited modifications can be made to the way the data is displayed -%with \cs{DTLdisplaydb} and \cs{DTLdisplaylongdb}. -%The commands controlling the formatting are described below. -%If a more complicated layout is required, you will need to use -%\cs{DTLforeach} described in \autoref{sec:dbforeach}. -% -%\begin{definition}[\DescribeMacro{\dtlheaderformat}]% -%\cs{dtlheaderformat}\marg{header} -%\end{definition} -%This indicates how to format a column header, where the header is -%given by \meta{header}. This defaults to -%\cs{null}\cs{hfil}\cs{textbf}\marg{header}\cs{hfil}\cs{null}. -% -%\begin{definition}[\DescribeMacro{\dtlstringformat}]% -%\cs{dtlstringformat}\marg{text} +%\begin{macro}{\DTLifint} +%\begin{definition} +%\cs{DTLifint}\marg{arg}\marg{true part}\marg{false part} %\end{definition} -%This specifies how to format each entry in the columns that contain -%strings. This defaults to just displaying \meta{text}. +% 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{definition}[\DescribeMacro{\dtlintformat}]% -%\cs{dtlintformat}\marg{text} +%\begin{macro}{\DTLifstring} +%\begin{definition} +%\cs{DTLifstring}\marg{arg}\marg{true part}\marg{false part} %\end{definition} -%This specifies how to format each entry in the columns that contain -%only integers. This defaults to just displaying \meta{text}. +% 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{definition}[\DescribeMacro{\dtlrealformat}]% -%\cs{dtlrealformat}\marg{text} +%\begin{macro}{\DTLifcurrency} +%\begin{definition} +%\cs{DTLifcurrency}\marg{arg}\marg{true part}\marg{false part} %\end{definition} -%This specifies how to format each entry in the columns that contain -%only real numbers or a mixture of real numbers and integers. This -%defaults to just displaying \meta{text}. +% 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{definition}[\DescribeMacro{\dtlcurrencyformat}]% -%\cs{dtlcurrencyformat}\marg{text} +%\begin{macro}{\DTLifcurrencyunit} +%\begin{definition} +%\cs{DTLifcurrencyunit}\marg{arg}\marg{symbol}\marg{true +% part}\marg{false part} %\end{definition} -%This specifies how to format each entry in the columns that contain -%only currency or currency mixed with real numbers and/or integers. -%This defaults to just displaying \meta{text}. +% 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{definition}[\DescribeMacro{\dtldisplaystarttab}]% -%\cs{dtldisplaystarttab} +%\begin{macro}{\DTLifcasedatatype} +%\begin{definition} +%\cs{DTLifcasedatatype}\marg{arg}\marg{string case}\marg{int +%case}\marg{real case}\marg{currency case} %\end{definition} -%This is a hook to add something at the beginning of the -%\env{tabular} environment. This defaults to nothing. +% 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{definition}[\DescribeMacro{\dtldisplayendtab}]% -%\cs{dtldisplayendtab} +%\begin{macro}{\dtl@testbothnumerical} +%\begin{definition} +%\cs{dtl@testbothnumerical}\marg{arg1}\marg{arg2} %\end{definition} -%This is a hook to add something at the end of the -%\env{tabular} environment. This defaults to nothing. +% 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{definition}[\DescribeMacro{\dtldisplayafterhead}]% -%\cs{dtldisplayafterhead} +%\begin{macro}{\DTLifnumlt} +%\begin{definition} +%\cs{DTLifnumlt}\marg{num1}\marg{num2}\marg{true part}\marg{false part} %\end{definition} -%This is a hook to add something after the header row, before -%the first row of data. This defaults to nothing. +% Determines if \marg{num1} $<$ \marg{num2}. Both numbers +% need to have the decimal separator changed to a dot +% to ensure that it works with \cs{dtlifnumlt} +%\changes{2.10}{2012-07-18}{changed \cs{FPiflt} to \cs{dtlifnumlt}} +% \begin{macrocode} +\newcommand*{\DTLifnumlt}[4]{% + \DTLconverttodecimal{#1}{\@dtl@numi}% + \DTLconverttodecimal{#2}{\@dtl@numii}% + \dtlifnumlt{\@dtl@numi}{\@dtl@numii}% + {% + #3% + }% + {% + #4% + }% +} +% \end{macrocode} +%\end{macro} % -%\begin{definition}[\DescribeMacro{\dtldisplaystartrow}]% -%\cs{dtldisplaystartrow} +%\label{src:dtlcompare} +%\begin{macro}{\dtlcompare} +%\begin{definition} +%\cs{dtlcompare}\marg{count}\marg{string1}\marg{string2} %\end{definition} -%This is a hook to add something at the start of each row, but -%not including the header row or the first row of data. This -%defaults to nothing. -% -%\begin{example}{Balance Sheet}{ex:balance} -%Suppose you have a file called "balance.csv" that contains -%the following: +% 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} -%Description,In,Out,Balance -%Travel expenses,,230,-230 -%Conference fees,,400,-630 -%Grant,700,,70 -%Train fare,,70,0 +%\newcount\mycount %\end{verbatim} -%\DTLnewdb{balance}\relax -%\DTLnewrow{balance}\relax -%\DTLnewdbentry{balance}{Description}{Travel expenses}\relax -%\DTLnewdbentry{balance}{In}{}\relax -%\DTLnewdbentry{balance}{Out}{230.00}\relax -%\DTLnewdbentry{balance}{Balance}{-230.00}\relax -%\DTLnewrow{balance}\relax -%\DTLnewdbentry{balance}{Description}{Conference fees}\relax -%\DTLnewdbentry{balance}{In}{}\relax -%\DTLnewdbentry{balance}{Out}{400.00}\relax -%\DTLnewdbentry{balance}{Balance}{-630.00}\relax -%\DTLnewrow{balance}\relax -%\DTLnewdbentry{balance}{Description}{Grant}\relax -%\DTLnewdbentry{balance}{In}{700.00}\relax -%\DTLnewdbentry{balance}{Out}{}\relax -%\DTLnewdbentry{balance}{Balance}{70.00}\relax -%\DTLnewrow{balance}\relax -%\DTLnewdbentry{balance}{Description}{Train Fare}\relax -%\DTLnewdbentry{balance}{In}{}\relax -%\DTLnewdbentry{balance}{Out}{70.00}\relax -%\DTLnewdbentry{balance}{Balance}{0.00}\relax -%\DTLsetheader{balance}{In}{In (\pounds)}\relax -%\DTLsetheader{balance}{Out}{Out (\pounds)}\relax -%\DTLsetheader{balance}{Balance}{Balance (\pounds)}\relax -%The data can be loaded using: +%\newcount\mycount\par\noindent +%\textbf{Examples:} +%\begin{enumerate} +%\item %\begin{verbatim} -%\DTLloaddb[headers={Description,In (\pounds),Out (\pounds),Balance -%(\pounds)}]{balance}{balance.csv} +%\dtlcompare{\mycount}{Z\"oe}{Zoe}\number\mycount %\end{verbatim} +%produces: +%\dtlcompare{\mycount}{Z\"oe}{Zoe}\number\mycount, since the accent +%command is ignored. % -%Suppose I want negative numbers to be displayed in red. I can do -%this by redefining \cs{dtlrealformat} to check if the entry -%is negative. For example: -%\begin{verbatim} -%\begin{table}[htbp] -%\caption{Balance Sheet} -%\renewcommand*{\dtlrealformat}[1]{\DTLiflt{#1}{0}{\color{red}}{}#1} -%\centering -%\DTLdisplaydb{balance} -%\end{table} -%\end{verbatim} -%This produces \autoref{tab:balance}. -%\begin{table}[htbp] -%\caption{Balance Sheet} -%\label{tab:balance} -%\renewcommand*{\dtlrealformat}[1]{\DTLiflt{#1}{0}{\color{red}}{}#1} -%\centering -%\DTLdisplaydb{balance} -%\end{table} -%\end{example} -% -%\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. -% -%\begin{definition}[\DescribeMacro{\DTLforeach}]% -%\cs{DTLforeach}\oarg{condition}\marg{db name}\marg{assign list}\marg{text} -%\end{definition} -%\begin{definition}[\DescribeMacro{\DTLforeach*}]% -%\cs{DTLforeach*}\oarg{condition}\marg{db name}\marg{assign list}\marg{text} -%\end{definition} -%This will iterate through each row of the database called -%\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 (such as \cs{not}, \cs{and}, -%\cs{or}), as well as the commands -%described in \autoref{sec:ifthen}. The default value of -%\meta{condition} is "\boolean{true}". -% -%The starred version \cs{DTLforeach*} is a read-only version. -%If you want to modify the database using any of the commands -%described in \autoref{sec:editdb}, you must use the unstarred -%version. The starred version is faster. -% -%\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: +%\item %\begin{verbatim} -%\DTLloaddb{scores}{studentscores.csv} +%\dtlcompare{\mycount}{foo}{Foo}\number\mycount %\end{verbatim} -%you can then display the database in a table as follows: +%produces: +%\dtlcompare{\mycount}{foo}{Foo}\number\mycount, since the comparison +%is case sensitive, however, note the following example: +%\item %\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} +%\dtlcompare{\mycount}{foo}{\uppercase{f}oo}\number\mycount %\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: -%\desctr{DTLrowi}, -%\desctr{DTLrowii} and -%\desctr{DTLrowiii} which keep track of -%the current row. -% -%\importantpar Note that these counters are only incremented when -%\meta{condition} is satisfied, therefore they will not have the -%correct value in \meta{condition}. These counters are incremented -%using \cs{refstepcounter} before the start of \meta{text}, so they -%may be referenced using \cs{label}, however remember that \cs{label} -%references the last counter to be incremented using -%\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. -% -%\begin{definition}[\DescribeMacro{\DTLcurrentindex}]% -%\cs{DTLcurrentindex} -%\end{definition} -%At the start of each iteration in \cs{DTLforeach}, -%\cs{DTLcurrentindex} is set to the arabic value of the current row -%counter. Note that this is only set after the condition is tested, -%so it should only be used in the body of \cs{DTLforeach} not in -%the condition. It is also only set locally, so if you use it in -%a tabular environment, it can only be used before the first instance -%of \verb|\\| or \verb|&| in the current iteration. -% -%Within the body of \ics{DTLforeach} (i.e.\ within \meta{text}) -%the following conditionals may be used: -%\begin{definition}[\DescribeMacro{\DTLiffirstrow}]% -%\cs{DTLiffirstrow}\marg{true part}\marg{false part} -%\end{definition} -%If the current row is the first row, then do \meta{true part}, -%otherwise do \meta{false part}. -% -%\begin{definition}[\DescribeMacro{\DTLifoddrow}]% -%\cs{DTLifoddrow}\marg{true part}\marg{false part} -%\end{definition} -%If the current row number is an odd number, then do \meta{true part}, -%otherwise do \meta{false part}. -% -%\begin{definition}[\DescribeMacro{\DTLsavelastrowcount}]% -%\cs{DTLsavelastrowcount}\marg{cmd} -%\end{definition} -%This command will store the value of the row counter used in -%the last occurrence of \ics{DTLforeach} in the control sequence -%\meta{cmd}. +%which produces: +%\dtlcompare{\mycount}{foo}{\uppercase{f}oo}\number\mycount, since +%the \cs{uppercase} command is ignored. % -%\begin{definition}[\DescribeMacro{\DTLforeachkeyinrow}]% -%\cs{DTLforeachkeyinrow}\marg{cmd}\marg{text} -%\end{definition} -%This iterates through each key in the current row, (globally) assigns -%\meta{cmd} to the value of that key, and does \meta{text} -%(\meta{cmd} must be a control sequence and may be used in -%\meta{text}). This command may only be used in the body of -%\cs{DTLforeach}. At each iteration, \cs{DTLforeachkeyinrow} sets -%\cs{dtlkey} to the current key, \cs{dtlcol} to the current column -%index, \cs{dtltype} to the data type for the current column, -%and \cs{dtlheader} to the header for the current column. Note that -%\cs{dtltype} corresponds to the column type but if the entries in -%the column have mixed types, it may not correspond to the type -%of the current entry. -% -%\begin{definition}[\DescribeMacro{\dtlbreak}]% -%\cs{dtlbreak} -%\end{definition} -%You can break out of most of the loops provided by \sty{datatool} -%using \cs{dtlbreak}. Note, however, that it doesn't break the loop -%until the end of the current iteration. There is no provision for -%a "next" or "continue" style command. -% -%Additional loop commands provided by \sty{datatool} are -%described in \autoref{sec:code:loops}. -% -%\begin{example}{Student Scores---Labelling}{ex:label} -%In the previous example, the student scores, stored in the -%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. +%\item You can ``trick'' \cs{dtlcompare} using a command which doesn't +%output any text. Suppose you have defined the following command: %\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}. +%\newcommand*{\noopsort}[1]{} %\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}. -% -%Notes: -%\begin{itemize} -%\item the \cs{label} command is placed before -%"\\" to ensure that it is in the same scope as the command -%"\refstepcounter{DTLrowi}". -% -%\item To avoid unwanted spaces the end of line characters are -%commented out with the percent (\texttt{\%}) symbol. -%\end{itemize} -% -%\begin{table}[htbp] -%\caption[Student scores (labelling rows)]{Student -%scores}\label{tab:scoreslab} -%\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} -% -%\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}.) +%\providecommand*{\noopsort}[1]{} +%then "\noopsort{a}foo" produces the text: \noopsort{a}foo, however +%the following %\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} +%\dtlcompare{\mycount}{\noopsort{a}foo}{bar}\number\mycount %\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} +%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. % -%Suppose now, I only want to display the scores for students whose -%surname begins with `B'. I can do this as follows: +%\item Note that this also means that: %\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} +%\def\mystr{abc}% +%\dtlcompare{\mycount}{\mystr}{abc}\number\mycount %\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} +%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". % -%\begin{example}{Breaking Out of a Loop}{ex:dtlbreak} -%Suppose I only want to display the first three rows of a database. -%I could do:\footnote{Recall that \ctr{DTLrowi} is incremented -%after the condition is tested, so it will be out by 1 when the -%condition is tested which is why \texttt{<3} is used instead of -%\texttt{<4}.} +%\item Spaces count in the comparison: %\begin{verbatim} -%\DTLforeach*[\value{DTLrowi}<3]{scores}% -%{\firstname=FirstName,\surname=Surname,\score=Score}{% -%\\\firstname & \surname & \score -%} +%\dtlcompare{\mycount}{ab cd}{abcd}\number\mycount %\end{verbatim} -%However, this isn't very efficient, as it still has to iterate -%through the entire database, checking if the condition is met. If -%the database has over 100 entries, this will slow the time taken -%to create the table. It would therefore be much more efficient -%to break out of the loop when row count exceeds 3: +%produces: +%\dtlcompare{\mycount}{ab cd}{abcd}\number\mycount, +%but sequential spaces are treated as a single space: %\begin{verbatim} -%\begin{table}[htbp] -%\caption{First Three Rows} -%\centering -%\begin{tabular}{llr} -%\bfseries First Name & \bfseries Surname & \bfseries Score (\%)% -%\DTLforeach*{scores}% -%{\firstname=FirstName,\surname=Surname,\score=Score}{% -%\ifthenelse{\DTLcurrentindex=3}{\dtlbreak}{}% -%\\\firstname & \surname & \score -%}% -%\end{tabular} -%\end{table} +%\dtlcompare{\mycount}{ab cd}{ab cd}\number\mycount %\end{verbatim} -%This produces \autoref{tab:dtlbreak}. Note that the loop is not -%broken until the end of the current iteration, so even though -%\cs{dtlbreak} occurs at the start of the third row, the loop isn't -%finished until the third row is completed. (Recall that -%\cs{DTLcurrentindex} must be used before the first instance of -%\verb|\\| or \verb|&|.) Alternatively, you can use -%\ctr{DTLrowi} instead: +%produces: +%\dtlcompare{\mycount}{ab cd}{ab cd}\number\mycount. +% +%\item As usual, spaces following command names are ignored, so %\begin{verbatim} -%\DTLforeach{scores}% -%{\firstname=FirstName,\surname=Surname,\score=Score}{% -%\\\firstname & \surname & \score -%\ifthenelse{\value{DTLrowi}=3}{\dtlbreak}{}% -%}% +%\dtlcompare{\mycount}{ab\relax cd}{ab cd}\number\mycount %\end{verbatim} +%produces: +%\dtlcompare{\mycount}{ab\relax cd}{ab cd}\number\mycount. % -%\begin{table}[htbp] -%\caption{First Three Rows} -%\label{tab:dtlbreak}% -%\centering -%\begin{tabular}{llr} -%\bfseries First Name & \bfseries Surname & \bfseries Score (\%)\relax -%\DTLforeach*{scores}% -%{\firstname=FirstName,\surname=Surname,\score=Score}{% -%\ifthenelse{\DTLcurrentindex=3}{\dtlbreak}{}\relax -%\\\firstname & \surname & \score -%}% -%\end{tabular} -%\end{table} -%\end{example} -% -%\begin{example}{Stripy Tables}{ex:stripy} -%This example uses the same database as in the previous examples. -%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}{Iterating Through Keys in a Row}{ex:foreachkey} -%Suppose you have lots of columns in your database, and you -%want to display them all without having to set a variable for -%each column. You can leave the assignment list in \cs{DTLforeach} -%blank, and iterate through the keys using \cs{DTLforeachkeyinrow}. -%For example: -%\begin{verbatim} -%\begin{table}[htbp] -%\caption{Student Scores (Iterating Through Keys)} -%\centering -%\begin{tabular}{llll} -%\bfseries First Name & \bfseries Surname & -%\bfseries Registration No. & -%\bfseries Score (\%)% -%\DTLforeach*{scores}{}{% -%\\\gdef\doamp{\gdef\doamp{&}}% -%\DTLforeachkeyinrow{\thisValue}{\doamp\thisValue}}% -%\end{tabular} -%\end{table} -%\end{verbatim} -%This produces \autoref{tab:foreachkey}. -%\begin{table}[htbp] -%\caption{Student Scores (Iterating Through Keys)} -%\label{tab:foreachkey} -%\centering -%\begin{tabular}{llll} -%\bfseries First Name & \bfseries Surname & -%\bfseries Registration No. & -%\bfseries Score (\%)\relax -%\DTLforeach*{scores}{}{% -%\\\gdef\doamp{\gdef\doamp{&}}\relax -%\DTLforeachkeyinrow{\thisValue}{\doamp\thisValue}}\relax -%\end{tabular} -%\end{table} -% -%Note that the "&" must be between columns, so I have defined -%a command called \cs{doamp} that on first use redefines -%itself to do "&". So, for each row, at the start of -%the key iteration, \cs{doamp} does nothing, and on subsequent -%iterations it does "&". This ensures that the correct number of -%"&"s are used. Since each cell in the \env{tabular} environment -%is scoped, \cs{gdef} is needed instead of \cs{def}. -% -%In the above, I needed to know how many columns are in the -%database, and the order that the headings should appear. If you -%are unsure, you can use \cs{dtlforeachkey} to determine the -%number of columns and to display the header row. For example: -%\begin{verbatim} -% \begin{table}[htbp] -% \caption{Student Scores} -% \centering -% % Work out the column alignments. -% \def\colalign{}% -% \dtlforeachkey(\theKey,\theCol,\theType,\theHead)\in{scores}\do -% {\edef\colalign{\colalign l}}% -% % Begin the tabular environment. -% \edef\dobegintabular{\noexpand\begin{tabular}{\colalign}}% -% \dobegintabular -% % Do the header row. -% \gdef\doamp{\gdef\doamp{&}}% -% \dtlforeachkey(\theKey,\theCol,\theType,\theHead)\in{scores}\do -% {\doamp\bfseries \theHead}% -% % Iterate through the data. -% \DTLforeach*{scores}{}{% -% \\\gdef\doamp{\gdef\doamp{&}}% -% \DTLforeachkeyinrow{\thisValue}{\doamp\thisValue}}% -% \end{tabular} -% \end{table} -%\end{verbatim} -% -%\begin{table}[htbp] -%\caption{Student Scores (Using \cs{dtlforeachkey} and -%\cs{DTLforeachkeyinrow})} -%\label{tab:foreachkey2} -%\centering -%\def\colalign{}% -%\dtlforeachkey(\theKey,\theCol,\theType,\theHead)\in{scores}\do -%{\edef\colalign{\colalign l}}% -%\edef\dobegintabular{\noexpand\begin{tabular}{\colalign}}\relax -%\dobegintabular -%\gdef\doamp{\gdef\doamp{&}}\relax -%\dtlforeachkey(\theKey,\theCol,\theType,\theHead)\in{scores}\do -%{\doamp\bfseries \theHead}\relax -%\DTLforeach*{scores}{}{% -%\\\gdef\doamp{\gdef\doamp{&}}\relax -%\DTLforeachkeyinrow{\thisValue}{\doamp\thisValue}}\relax -%\end{tabular} -%\end{table} -% -%Notes: -%\begin{itemize} -%\item In order to determine the column alignment for the -%\env{tabular} environment, I first define \cs{colalign} to -%nothing, and then I iterate through the keys appending -%\texttt{l} to \cs{colalign}. Since \cs{colalign} only contains -%alphabetical characters, I can just use \cs{edef} for this. I -%could modify this to check the data type and, say, use \texttt{l} -%(left alignment) for columns containing strings and \texttt{c} -%(centred) for the other columns: -%\begin{verbatim} -%\dtlforeachkey(\theKey,\theCol,\theType,\theHead)\in{scores}\do -%{\ifnum\theType=0\relax -% \edef\colalign{\colalign l}% column contains strings -% \else -% \edef\colalign{\colalign c}% column contains numerical values -% \fi -%}% -%\end{verbatim} -% -%\item To ensure \cs{colalign} gets correct expanded when passed -%to the \env{tabular} environment I temporarily define -%\cs{dobegintabular} to the code required to start the -%\env{tabular} environment: -%\begin{verbatim} -%\edef\dobegintabular{\noexpand\begin{tabular}{\colalign}}% -%\end{verbatim} -%This sets \cs{dobegintabular} to \verb|\begin{tabular}{llll}|. -%After defining \cs{dobegintabular}, I then need to use it. -% -%\item As before, I use \cs{doamp} to put the ampersands between -%columns. -% -%\item Recall that I can set the headers using \cs{DTLsetheader} -%or using the \cmdopt{DTLloaddb}{headers} key when loading the data -%from an external file. For example: -%\begin{verbatim} -%\DTLsetheaders{scores}{FirstName}{First Name} -%\DTLsetheaders{scores}{Score}{Score (\%)} -%\end{verbatim} -%\end{itemize} -% -%Recall that \cs{DTLforeachkeyinrow} sets \cs{dtlkey} to the -%current key. This can be used to filter out columns. Alternatively, -%if you know the column index, you can test \cs{dtlcol} instead. -%The following code modifies the above example so that it filters -%out the column whose key is \texttt{StudentNo}: -%\begin{verbatim} -%\begin{table}[htbp] -%\caption{Student Scores (Filtering Out a Column)} -%\centering -%\def\colalign{}% -%\dtlforeachkey(\theKey,\theCol,\theType,\theHead)\in{scores}\do -%{\DTLifeq{\theKey}{StudentNo}{}{\edef\colalign{\colalign l}}}% -%\edef\dobegintabular{\noexpand\begin{tabular}{\colalign}}% -%\dobegintabular -%\gdef\doamp{\gdef\doamp{&}}% -%\dtlforeachkey(\theKey,\theCol,\theType,\theHead)\in{scores}\do -%{\DTLifeq{\theKey}{StudentNo}{}{\doamp\bfseries \theHead}}% -%\DTLforeach*{scores}{}{% -%\\\gdef\doamp{\gdef\doamp{&}}% -%\DTLforeachkeyinrow{\thisValue}{% -% \DTLifeq{\dtlkey}{StudentNo}{}{\doamp\thisValue}}}% -%\end{tabular} -%\end{table} -%\end{verbatim} -%The result is shown in \autoref{tab:foreachkey3}. -% -%\begin{table}[htbp] -%\caption{Student Scores (Filtering Out a Column)} -%\label{tab:foreachkey3} -%\centering -%\def\colalign{}% -%\dtlforeachkey(\theKey,\theCol,\theType,\theHead)\in{scores}\do -%{\DTLifeq{\theKey}{StudentNo}{}{\edef\colalign{\colalign l}}}% -%\edef\dobegintabular{\noexpand\begin{tabular}{\colalign}}\relax -%\dobegintabular -%\gdef\doamp{\gdef\doamp{&}}\relax -%\dtlforeachkey(\theKey,\theCol,\theType,\theHead)\in{scores}\do -%{\DTLifeq{\theKey}{StudentNo}{}{\doamp\bfseries \theHead}}\relax -%\DTLforeach*{scores}{}{% -%\\\gdef\doamp{\gdef\doamp{&}}\relax -%\DTLforeachkeyinrow{\thisValue}{\relax -%\DTLifeq{\dtlkey}{StudentNo}{}{\doamp\thisValue}}}\relax -%\end{tabular} -%\end{table} -%\end{example} -% -%\begin{example}{Nested \cs{DTLforeach}}{ex:nested} -%In this example I have a CSV file called "index.csv" which -%contains: -%\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} -% -%\begin{example}{Dynamically Allocating Field Name}{ex:dyn} -%(This example was suggested by Bill~Hobbs.) Suppose you have a -%directory containing members of multiple clubs. The CSV file -%(say, \texttt{clubs.csv}) may look something like: -%\begin{verbatim} -%First Name,Surname,Rockin,Single -%John,"Smith, Jr",member, -%Jane,Brown,,friend -%Andy,Brown,friend,member -%Z\"oe,Adams,member,member -%Roger,Brady,friend,friend -%Clare,Verdon,member, -%\end{verbatim} -%\DTLnewdb{clubs}\relax -%\DTLnewrow{clubs}\relax -%\DTLnewdbentry{clubs}{First Name}{John}\relax -%\DTLnewdbentry{clubs}{Surname}{Smith, Jr}\relax -%\DTLnewdbentry{clubs}{Rockin}{member}\relax -%\DTLnewdbentry{clubs}{Single}{}\relax -%\DTLnewrow{clubs}\relax -%\DTLnewdbentry{clubs}{First Name}{Jane}\relax -%\DTLnewdbentry{clubs}{Surname}{Brown}\relax -%\DTLnewdbentry{clubs}{Rockin}{}\relax -%\DTLnewdbentry{clubs}{Single}{friend}\relax -%\DTLnewrow{clubs}\relax -%\DTLnewdbentry{clubs}{First Name}{Andy}\relax -%\DTLnewdbentry{clubs}{Surname}{Brown}\relax -%\DTLnewdbentry{clubs}{Rockin}{friend}\relax -%\DTLnewdbentry{clubs}{Single}{member}\relax -%\DTLnewrow{clubs}\relax -%\DTLnewdbentry{clubs}{First Name}{Z\"oe}\relax -%\DTLnewdbentry{clubs}{Surname}{Adams}\relax -%\DTLnewdbentry{clubs}{Rockin}{member}\relax -%\DTLnewdbentry{clubs}{Single}{member}\relax -%\DTLnewrow{clubs}\relax -%\DTLnewdbentry{clubs}{First Name}{Roger}\relax -%\DTLnewdbentry{clubs}{Surname}{Brady}\relax -%\DTLnewdbentry{clubs}{Rockin}{friend}\relax -%\DTLnewdbentry{clubs}{Single}{friend}\relax -%\DTLnewrow{clubs}\relax -%\DTLnewdbentry{clubs}{First Name}{Clare}\relax -%\DTLnewdbentry{clubs}{Surname}{Verdon}\relax -%\DTLnewdbentry{clubs}{Rockin}{member}\relax -%\DTLnewdbentry{clubs}{Single}{}\relax -%(Blank entries indicate that the person is not a member of that -%club.) The data can be loaded as follows: -%\begin{verbatim} -%\DTLloaddb{clubs}{clubs.csv} -%\end{verbatim} -%Suppose at the beginning of your document you have specified -%which club you are interested in ("Rockin" or "Single") and -%store it in \cs{DIdent}: -%\begin{verbatim} -%\newcommand{\DIdent}{Rockin} -%\end{verbatim} -%\newcommand{\DIdent}{Rockin}\relax -%You can now display the members for this particular club as -%follows: -%\begin{verbatim} -%\begin{table}[htbp] -%\caption{Club Membership} -%\centering -%\begin{tabular}{lll} -%\bfseries First Name & \bfseries Surname & \bfseries Status -%\DTLforeach*[\not\DTLiseq{\status}{}]{clubs} -%{\firstname=First Name,\surname=Surname,\status=\DIdent}{% -%\\\firstname & \surname & \status -%}% -%\end{tabular} -%\end{table} -%\end{verbatim} -%The result is shown in \autoref{tab:dyn}. -% -%\begin{table}[htbp] -%\caption{Club Membership} -%\label{tab:dyn} -%\centering -%\begin{tabular}{lll} -%\bfseries First Name & \bfseries Surname & \bfseries Status -%\DTLforeach*[\not\DTLiseq{\status}{}]{clubs} -%{\firstname=First Name,\surname=Surname,\status=\DIdent}{\relax -%\\\firstname & \surname & \status -%}\relax -%\end{tabular} -%\end{table} -%\end{example} -% -%\subsection{Null Values} -%If a database is created using \cs{DTLnewdb}, \cs{DTLnewrow} -%and \cs{DTLnewdbentry} (rather than loading it from an ASCII -%file), it is possible for some of the entries to have null values -%when a value is not assigned to a given key for a given row. -%(Note that a null value is not the same as an empty value.) -% -%When you iterate through the database using \cs{DTLforeach} -%(described in \autoref{sec:dbforeach}), -%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. -% -%\begin{definition}[\DescribeMacro{\DTLstringnull}]% -%\cs{DTLstringnull} -%\end{definition} -%This is the null value for a string. -% -%\begin{definition}[\DescribeMacro{\DTLnumbernull}]% -%\cs{DTLnumbernull} -%\end{definition} -%This is the null value for a number. -% -%\begin{definition}[\DescribeMacro{\DTLifnull}]% -%\cs{DTLifnull}\marg{cmd}\marg{true part}\marg{false part} -%\end{definition} -%This checks if \meta{cmd} is null where \meta{cmd} is a command name, -%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} (\DTLnumbernull), and -%null strings are set to \cs{DTLstringnull} (\DTLstringnull). -% -%The following code checks each value to determine whether it -%is null using \cs{DTLifnull}. If it is, the text \emph{Missing} -%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} -% -%A row can be removed from a data base using: -%\begin{definition}[\DescribeMacro{\DTLremoverow}]% -%\cs{DTLremoverow}\marg{db name}\marg{row index} -%\end{definition} -%where \meta{row index} is the index of the unwanted row. For -%example: +%\item "~" and \cs{space} are considered to be the same as a +% space: %\begin{verbatim} -%\DTLremoverow{scores}{2} +%\dtlcompare{\mycount}{ab cd}{ab~cd}\number\mycount %\end{verbatim} -%will delete the second row in the database labelled ``scores''. -%There is also a starred version that doesn't check for the -%existence of the database. -% -%In the body of the \ics{DTLforeach} loop,\footnote{Only the -%unstarred version of \cs{DTLforeach}; the starred version is -%read-only.}\ you can use the following to edit the current row: -%\begin{definition}[\DescribeMacro{\DTLappendtorow}]% -%\cs{DTLappendtorow}\marg{key}\marg{value} +%produces: +%\dtlcompare{\mycount}{ab cd}{ab~cd}\number\mycount. +%\end{enumerate} +%\changes{1.01}{2007 Aug 17}{replaces \cs{compare} (no +% longer using compare.tex)} +% \begin{macrocode} +\newcommand*{\dtlcompare}[3]{% + \dtl@subnobrsp{#2}{\@dtl@argA}% + \dtl@subnobrsp{#3}{\@dtl@argB}% + \ifdefempty{\@dtl@argA}% + {% + \ifdefempty{\@dtl@argB}% + {% + #1=0\relax + }% + {% + #1=-1\relax + }% + }% + {% + \ifdefempty{\@dtl@argB}% + {% + #1=1\relax + }% + {% + \DTLsubstituteall{\@dtl@argA}{ }{\space }% + \DTLsubstituteall{\@dtl@argB}{ }{\space }% + \expandafter\dtl@getfirst\@dtl@argA\end + \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 + \ifdefempty{\dtl@restA}% + {% + \ifdefempty{\dtl@restB}% + {% + #1=0\relax + }% + {% + #1=-1\relax + }% + }% + {% + \ifdefempty{\restB}% + {% + #1=1\relax + }% + {% + \protected@edef\dtl@donext{% + \noexpand\dtlcompare + {\noexpand#1}{\dtl@restA}{\dtl@restB}}% + \dtl@donext + }% + }% + \fi + \fi + \fi + \fi + }{% + \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 + }% + }% + }% +} +% \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}% + \ifdefempty{\dtl@first}% + {% + \def\dtl@rest{#2}% + }% + {% + \dtl@ifsingle{#1}{\def\dtl@rest{#2}}{\dtl@getfirst#1#2\end}% + }% +} +% \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} -%This appends a new entry with the given \meta{key} and \meta{value} -%to the current row. -%(\meta{value} is expanded.) +% Sets \meta{count register} to the character code of \meta{c}, or to +% -1 if \meta{c} is a control sequence, unless \meta{c} is either +% \cs{space} or |~| in which case it sets \meta{count register} +% to the character code of the space character. +% \begin{macrocode} +\newcommand*{\dtl@setcharcode}[2]{% + \ifstrempty{#1}% + {% + #2=-1\relax + }% + {% + \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 + }% +} +% \end{macrocode} +%\end{macro} % -%\begin{definition}[\DescribeMacro{\DTLreplaceentryforrow}]% -%\cs{DTLreplaceentryforrow}\marg{key}\marg{value} +%\begin{macro}{\dtl@setlccharcode} +%\begin{definition} +%\cs{dtl@setlccharcode}\marg{c}\marg{count register} %\end{definition} -%This replaces the entry for \meta{key} with \meta{value}. -%(\meta{value} is expanded.) -% -%\begin{definition}[\DescribeMacro{\DTLremoveentryfromrow}]% -%\cs{DTLremoveentryfromrow}\marg{key} +% As \cs{dtl@setlccharcode} except it sets \meta{count register} +% to the lower case character code of \meta{c}, unless \meta{c} +% is a control sequence, in which case it does the same as +% \cs{dtl@setcharcode}. +% \begin{macrocode} +\newcommand*{\dtl@setlccharcode}[2]{% + \ifstrempty{#1}% + {% + #2=-1\relax + }% + {% + \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 + }% +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\dtlicompare} +%\begin{definition} +%\cs{dtlicompare}\marg{count}\marg{string1}\marg{string2} %\end{definition} -%This removes the entry for \meta{key} from the current row. +% As \cs{dtlcompare} but ignores case. +%\changes{1.01}{2007 Aug 17}{new} +% \begin{macrocode} +\newcommand*{\dtlicompare}[3]{% + \dtl@subnobrsp{#2}{\@dtl@argA}% + \dtl@subnobrsp{#3}{\@dtl@argB}% + \ifdefempty{\@dtl@argA}% + {% + \ifdefempty{\@dtl@argB}% + {% + #1=0\relax + }% + {% + #1=-1\relax + }% + }% + {% + \ifdefempty{\@dtl@argB}% + {% + #1=1\relax + }% + {% + \DTLsubstituteall{\@dtl@argA}{ }{\space }% + \DTLsubstituteall{\@dtl@argB}{ }{\space }% + \expandafter\dtl@getfirst\@dtl@argA\end + \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 + \ifdefempty{\dtl@restA}% + {% + \ifdefempty{\dtl@restB}% + {% + #1=0\relax + }% + {% + #1=-1\relax + }% + }% + {% + \ifdefempty{\restB}% + {% + #1=1\relax + }% + {% + \protected@edef\dtl@donext{% + \noexpand\dtlicompare + {\noexpand#1}{\dtl@restA}{\dtl@restB}}% + \dtl@donext + }% + }% + \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 + }% + }% + }% +} +% \end{macrocode} +%\end{macro} % -%\begin{definition}[\DescribeMacro{\DTLremovecurrentrow}]% -%\cs{DTLremovecurrentrow} +%\begin{macro}{\DTLifstringlt} +%\begin{definition} +%\cs{DTLifstringlt}\marg{string1}\marg{string2}\marg{true part}\marg{false part} %\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}{llcccc} -%\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}{llcccc} -%\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} -% -%\begin{definition}[\DescribeMacro{\DTLsumforkeys}]% -%\cs{DTLsumforkeys}\oarg{condition}\oarg{assign list}\marg{db list}\marg{key list}\marg{cmd} -%\end{definition} -%This command sums all the entries over all the databases listed in -%the comma separated list of database names \meta{db list} for each -%key in \meta{key list} where the condition given by \meta{condition} -%is true. The second optional argument \meta{assign list} is the same -%as the assignment list used by \ics{DTLforeach}, so that you can use -%the information in \meta{condition}. The result is stored in -%\meta{cmd} which must be a control sequence. For example: -%\begin{verbatim} -%\DTLsumforkeys{scores}{Score}{\total} -%\end{verbatim} -%sets \cs{total} to the sum of all the scores in the database -%called "scores". -% -%\begin{definition}[\DescribeMacro{\DTLsumcolumn}]% -%\cs{DTLsumcolumn}\marg{db}\marg{key}\marg{cmd} -%\end{definition} -%This is a faster version of \cs{DTLsumforkeys} that only sums -%the entries in a single column (specified by \meta{key}) for -%a single database (specified by \meta{db}) and doesn't provide any -%filtering. The result is stored in \meta{cmd} which must be -%a control sequence. -% -%\begin{definition}[\DescribeMacro{\DTLmeanforkeys}]% -%\cs{DTLmeanforkeys}\oarg{condition}\oarg{assign list}\marg{db list}\marg{key list}\marg{cmd} -%\end{definition} -%This command computes the arithmetic mean of all the entries over -%all the databases listed in \meta{db list} for all keys in \meta{key -%list} where the condition given by \meta{condition} is true. The -%second optional argument \meta{assign list} is the same as the -%assignment list used by \ics{DTLforeach}, so that you can use the -%information in \meta{condition}. The result is stored in \meta{cmd} -%which must be a control sequence. For example: -%\begin{verbatim} -%\DTLmeanforkeys{scores}{Score}{\average} -%\end{verbatim} -%sets \cs{average} to the mean of all the scores in the database -%called "scores". -% -%\begin{definition}[\DescribeMacro{\DTLmeanforcolumn}]% -%\cs{DTLmeanforcolumn}\marg{db}\marg{key}\marg{cmd} -%\end{definition} -%This is a faster version of \cs{DTLmeanforkeys} that only computes -%the mean for a single column (specified by \meta{key}) for -%a single database (specified by \meta{db}) and doesn't provide any -%filtering. The result is stored in \meta{cmd} which must be -%a control sequence. -% -%\begin{definition}[\DescribeMacro{\DTLvarianceforkeys}]% -%\cs{DTLvarianceforkeys}\oarg{condition}\oarg{assign list}\marg{db list}\marg{key list}\marg{cmd} -%\end{definition} -%This command computes the variance of all the entries over all the -%databases listed in \meta{db list} for all keys in \meta{key list} -%where the condition given by \meta{condition} is true. The second -%optional argument \meta{assign list} is the same as the assignment -%list used by \ics{DTLforeach}, so that you can use the information -%in \meta{condition}. The result is stored in \meta{cmd} which must -%be a control sequence. -% -%\begin{definition}[\DescribeMacro{\DTLvarianceforcolumn}]% -%\cs{DTLvarianceforcolumn}\marg{db}\marg{key}\marg{cmd} +% 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} -%This is a faster version of \cs{DTLvarianceforkeys} that only -%computes the variance for a single column (specified by \meta{key}) -%for a single database (specified by \meta{db}) and doesn't provide -%any filtering. The result is stored in \meta{cmd} which must be a -%control sequence. +% 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{definition}[\DescribeMacro{\DTLsdforkeys}]% -%\cs{DTLsdforkeys}\oarg{condition}\oarg{assign list}\marg{db list}\marg{key list}\marg{cmd} +%\begin{macro}{\DTLifnumgt} +%\begin{definition} +%\cs{DTLifnumgt}\marg{num1}\marg{num2}\marg{true part}\marg{false part} %\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 -%second optional argument \meta{assign list} is the same as the -%assignment list used by \ics{DTLforeach}, so that you can use the -%information in \meta{condition}. The result is stored in \meta{cmd} -%which must be a control sequence. +% Determines if \marg{num1} $>$ \marg{num2}. Both numbers +% need to have the decimal separator changed to a dot +% to ensure that it works with \cs{dtlifnumgt} +%\changes{2.10}{2012-07-18}{changed \cs{FPifgt} to \cs{dtlifnumgt}} +% \begin{macrocode} +\newcommand*{\DTLifnumgt}[4]{% + \DTLconverttodecimal{#1}{\@dtl@numi}% + \DTLconverttodecimal{#2}{\@dtl@numii}% + \dtlifnumgt{\@dtl@numi}{\@dtl@numii}% + {% + #3% + }% + {% + #4% + }% +} +% \end{macrocode} +%\end{macro} % -%\begin{definition}[\DescribeMacro{\DTLsdforcolumn}]% -%\cs{DTLsdforcolumn}\marg{db}\marg{key}\marg{cmd} +%\begin{macro}{\DTLifstringgt} +%\begin{definition} +%\cs{DTLifstringgt}\marg{string1}\marg{string2}\marg{true part}\marg{false part} %\end{definition} -%This is a faster version of \cs{DTLsdforkeys} that only computes the -%standard deviation for a single column (specified by \meta{key}) for -%a single database (specified by \meta{db}) and doesn't provide any -%filtering. The result is stored in \meta{cmd} which must be a -%control sequence. -% -%\begin{definition}[\DescribeMacro{\DTLminforkeys}]% -%\cs{DTLminforkeys}\oarg{condition}\oarg{assign list}\marg{db list}\marg{key list}\marg{cmd} +% 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} -%This command determines the minimum value over all entries for all -%keys in \meta{key list} over all the databases listed in \meta{db -%list} where \meta{condition} is true. The second optional argument -%\meta{assign list} is the same as the assignment list used by -%\ics{DTLforeach}, so that you can use the information in -%\meta{condition}. The result is stored in \meta{cmd}, which must be -%a control sequence. For example -%\begin{verbatim} -%\DTLminforkeys{scores}{Score}{\theMin} -%\end{verbatim} -%sets \cs{theMin} to the minimum score in the database. +% 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{definition}[\DescribeMacro{\DTLminforcolumn}]% -%\cs{DTLminforcolumn}\marg{db}\marg{key}\marg{cmd} +%\begin{macro}{\DTLifnumeq} +%\begin{definition} +%\cs{DTLifnumeq}\marg{num1}\marg{num2}\marg{true part}\marg{false part} %\end{definition} -%This is a faster version of \cs{DTLminforkeys} that only computes -%the minimum for a single column (specified by \meta{key}) for -%a single database (specified by \meta{db}) and doesn't provide any -%filtering. The result is stored in \meta{cmd} which must be -%a control sequence. +% Determines if \marg{num1} = \marg{num2}. Both numbers +% need to have the decimal separator changed to a dot +% to ensure that it works with \cs{dtlifnumeq} +%\changes{2.10}{2012-07-18}{changed \cs{FPifeq} to \cs{dtlifnumeq}} +% \begin{macrocode} +\newcommand*{\DTLifnumeq}[4]{% + \DTLconverttodecimal{#1}{\@dtl@numi}% + \DTLconverttodecimal{#2}{\@dtl@numii}% + \dtlifnumeq{\@dtl@numi}{\@dtl@numii}% + {% + #3% + }% + {% + #4% + }% +} +% \end{macrocode} +%\end{macro} % -%\begin{definition}[\DescribeMacro{\DTLmaxforkeys}]% -%\cs{DTLmaxforkeys}\oarg{condition}\oarg{assign list}\marg{db list}\marg{key list}\marg{cmd} +%\begin{macro}{\DTLifstringeq} +%\begin{definition} +%\cs{DTLifstringeq}\marg{string1}\marg{string2}\marg{true part}\marg{false part} %\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} where \meta{condition} is true. The second optional argument -%\meta{assign list} is the same as the assignment list used by -%\ics{DTLforeach}, so that you can use the information in -%\meta{condition}. The result is stored in \meta{cmd}, which must be -%a control sequence. For example -%\begin{verbatim} -%\DTLminforkeys{scores}{Score}{\theMax} -%\end{verbatim} -%sets \cs{theMax} to the minimum score in the database. -% -%\begin{definition}[\DescribeMacro{\DTLmaxforcolumn}]% -%\cs{DTLmaxforcolumn}\marg{db}\marg{key}\marg{cmd} +% 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} -%This is a faster version of \cs{DTLmaxforkeys} that only computes -%the maximum for a single column (specified by \meta{key}) for -%a single database (specified by \meta{db}) and doesn't provide any -%filtering. The result is stored in \meta{cmd} which must be -%a control sequence. +% 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{definition}[\DescribeMacro{\DTLcomputebounds}]% -%\cs{DTLcomputebounds}\marg{db list}\marg{x key}\marg{y key}\marg{minX cmd}\marg{minY cmd}\marg{maxX cmd}\marg{maxY cmd} +%\begin{macro}{\DTLifSubString} +%\begin{definition} +%\cs{DTLifSubString}\marg{string}\marg{sub string}\marg{true +%part}\marg{false part} %\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} -% -%To determine a person's gender when mail merging, see -%\autoref{sec:person}. -%\end{example} -% -%\subsection{Sorting a Database} -%\label{sec:sort} -% -%\begin{definition}[\DescribeMacro{\DTLsort}]% -%\cs{DTLsort}\oarg{replacement key list}\marg{sort criteria}\marg{db name} -%\end{definition} -%\begin{definition}[\DescribeMacro{\DTLsort*}]% -%\cs{DTLsort*}\oarg{replacement key list}\marg{sort criteria}\marg{db name} -%\end{definition} -%This will sort the database called \meta{db name} according to -%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} -% -%\begin{definition}[\DescribeMacro{\DTLsavedb}]% -%\cs{DTLsavedb}\marg{db name}\marg{filename} -%\end{definition} -%This writes the database called \meta{db name} to a file called -%\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 will save the data in a -%tab separated format. (The delimiters will only be used if a -%given entry contains the separator character.) -% -%\begin{definition}[\DescribeMacro{\DTLsavetexdb}]% -%\cs{DTLsavetexdb}\marg{db name}\marg{filename} -%\end{definition} -%This writes the database called \meta{db name} to a \LaTeX\ file -%called \meta{filename}, where the database is stored as -%a combination of \ics{DTLnewdb}, \ics{DTLnewrow} and -%\ics{DTLnewdbentry} commands. -% -%\subsection{Deleting or Clearing a Database}\label{sec:deletedb} -% -%A database can be cleared or deleted when its contents are no -%longer required. -%\begin{definition}[\DescribeMacro{\DTLcleardb}] -%\cs{DTLcleardb}\marg{db name} -%\end{definition} -%Clears the database given by \meta{db name}. The database is emptied -%but remains defined. -% -%\begin{definition}[\DescribeMacro{\DTLdeletedb}] -%\cs{DTLdeletedb}\marg{db name} -%\end{definition} -%Deletes (undefines) the database given by \meta{db name}. -% -%\subsection{Advanced Database Commands} -% -%This section describes more advanced commands. Further details -%can be found in \autoref{sec:code:datatool}. -% -%\begin{definition}[\DescribeMacro{\DTLgetdatatype}] -%\cs{DTLgetdatatype}\marg{cs}\marg{db}\marg{key} -%\end{definition} -%Gets the data type for the given key \meta{key} for the database -%given by \meta{db}. The data type is stored in \meta{cs} which -%must be a command name. The type will be one of: -%\begin{itemize} -%\item\DescribeMacro{\DTLunsettype}\cs{DTLunsettype} (not set), -%\item\DescribeMacro{\DTLstringtype}\cs{DTLstringtype} (string), -%\item\DescribeMacro{\DTLinttype}\cs{DTLinttype} (integer), -%\item\DescribeMacro{\DTLrealtype}\cs{DTLrealtype} (real number) or -%\item\DescribeMacro{\DTLcurrencytype}\cs{DTLcurrenttype} (currency). -%\end{itemize} -% -%\begin{definition}[\DescribeMacro{\dtlforeachkey}]% -%\cs{dtlforeachkey}(\meta{key cs},\meta{col cs},\meta{type -%cs},\meta{header cs})\cs{in}\marg{db}\cs{do}\marg{body} -%\end{definition} -%This iterates through all the keys in the database given by -%\meta{db}. In each iteration, \meta{key cs} is set to the key, -%\meta{col cs} is set to the column index, \meta{type cs} is set to -%the data type (as for \cs{DTLgetdatatype}), \meta{header cs} is set -%to the header for that column, and then \meta{body} is done. Note -%that \meta{key cs}, \meta{col cs}, \meta{type cs} and \meta{header -%cs} must all be control sequences. No check is performed to -%determine if that control sequence already exists, and the control -%sequences are defined globally (since it's likely that -%\cs{dtlforeachkey} may be used within a \env{tabular} environment), -%so you need to make sure you don't override an existing command of -%the same name. -% -%\begin{definition}[\DescribeMacro{\dtlforcolumn}]% -%\cs{dtlforcolumn}\marg{cs}\marg{db}\marg{key}\marg{body} -%\end{definition} -%This iterates through the column given by \meta{key} in the -%database given by \meta{db} and applies \meta{body}. In each -%iteration, \meta{cs} (which must be a control sequence) is set to -%the current element in the column and may be used in \meta{body}. -%Alternatively, if you want to identify the column by its index -%rather than its key, use: -%\begin{definition}[\DescribeMacro{\dtlforcolumnindex}]% -%\cs{dtlforcolumnindex}\marg{cs}\marg{db}\marg{col index}\marg{body} -%\end{definition} -% -%\begin{definition}[\DescribeMacro{\DTLifdbexists}] -%\cs{DTLifdbexists}\marg{db name}\marg{true part}\marg{false part} -%\end{definition} -%Determines if the database given by \meta{db name} exists. -% -%\begin{definition}[\DescribeMacro{\DTLifhaskey}] -%\cs{DTLifhaskey}\marg{db name}\marg{key}\marg{true part}\marg{false part} -%\end{definition} -%This determines if the database given by \meta{db name} has -%any entries with the key given by \meta{key}. If so, it does -%\meta{true part} otherwise it does \meta{false part}. +% 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}% + \ifdefempty{\@dtl@argB}% + {% + \@dtl@conditiontrue + }% + {% + \ifdefempty{\@dtl@argA}% + {% + \@dtl@conditionfalse + }% + {% + \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 + }% + }% +} +% \end{macrocode} +%\end{macro} % -%Each key has an associated column index. This can be obtained -%using: -%\begin{definition}[\DescribeMacro{\DTLgetcolumnindex}] -%\cs{DTLgetcolumnindex}\marg{cs}\marg{db}\marg{key} +%\begin{macro}{\DTLifStartsWith} +%\begin{definition} +%\cs{DTLifStartsWith}\marg{string}\marg{substring}\marg{true +%part}\marg{false part} %\end{definition} -%where \meta{cs} is a command name, \meta{db} is the database label -%and \meta{key} is the key. The column index is stored in -%\meta{cs}. +%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} % -%You can also do the reverse and find the key associated with a -%given column index: -%\begin{definition}[\DescribeMacro{\DTLgetkeyforcolumn}] -%\cs{DTLgetkeyforcolumn}\marg{key cs}\marg{db}\marg{column index} +%\begin{macro}{\dtl@teststartswith} +%\begin{definition} +%\cs{dtl@teststartswith}\marg{string}\marg{prefix} %\end{definition} -%The key is stored in \meta{key cs} (which must be a command name). +% 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}% + \ifdefempty{\@dtl@argA}% + {% + \ifdefempty{\@dtl@argB}% + {% + \@dtl@conditiontrue + }% + {% + \@dtl@conditionfalse + }% + }% + {% + \ifdefempty{\@dtl@argB}% + {% + \@dtl@conditiontrue + }% + {% + \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}}% + }% + }% + }% +} +% \end{macrocode} +%\end{macro} % -%There is also a full expandable way of obtaining the column -%index, but note that no check is performed to determine -%if the database exists, or if it contains the given key: -%\begin{definition}[\DescribeMacro{\dtlcolumnindex}] -%\cs{dtlcolumnindex}\marg{db name}\marg{key} +%\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{definition}[\DescribeMacro{\DTLgetkeydata}] -%\cs{DTLgetkeydata}\marg{key}\marg{db}\marg{col cs}\marg{type cs}\marg{header cs} +%\begin{macro}{\DTLifstringclosedbetween} +%\begin{definition} +%\cs{DTLifstringclosedbetween}\marg{string}\marg{min}\marg{max}\marg{true part}\marg{false part} %\end{definition} -%Gets data for given key in database \meta{db}: the column index is -%stored in \meta{col cs} (as \cs{DTLgetcolumnindex}), the type is -%stored in \meta{type cs} (as \cs{DTLgetdatatype}) and the header -%is stored in \meta{header cs}. -% -%\begin{definition}[\DescribeMacro{\DTLgetvalue}] -%\cs{DTLgetvalue}\marg{cs}\marg{db}\marg{r}\marg{c} +% 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} -%This gets the value for row given by index \meta{r} and column -%given by \meta{c} for the database \meta{db} and stores it in -%\meta{cs} which must be a command name. If you want to get the -%value by key rather than column index you can use -%\cs{dtlcolumnindex}. For example, the following gets the value -%for row~3 with key \texttt{Surname} from the database -%\texttt{data} and stores in \cs{myval}: -%\begin{verbatim} -%\DTLgetvalue{\myval}{data}{3}{\dtlcolumnindex{data}{Surname}} -%\end{verbatim} +% 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{definition}[\DescribeMacro{\DTLgetlocation}] -%\cs{DTLgetlocation}\marg{row cs}\marg{column cs}\marg{database}% -%\marg{value} +%\begin{macro}{\DTLifnumopenbetween} +%\begin{definition} +%\cs{DTLifnumopenbetween}\marg{num}\marg{min}\marg{max}\marg{true part}\marg{false part} %\end{definition} -%Assigns \meta{row cs} and \meta{column cs} to the indices of the -%first entry in \meta{database} that matches \meta{value}. +% 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{definition}[\DescribeMacro{\DTLgetvalueforkey}] -%\cs{DTLgetvalueforkey}\marg{cmd}\marg{key}\marg{db name}\marg{ref -% key}\marg{ref value} +%\begin{macro}{\DTLifstringopenbetween} +%\begin{definition} +%\cs{DTLifstringopenbetween}\marg{string}\marg{min}\marg{max}\marg{true part}\marg{false part} %\end{definition} -%This (globally) sets \meta{cmd} (a control sequence) to the -%value of the key specified by \meta{key} in the first row -%of the database called \meta{db name} which contains the key -%\meta{ref key} which has the value \meta{value}. -% -%Two rows can be swapped using: -%\begin{definition}[\DescribeMacro{\DTLswaprows}]% -%\cs{DTLswaprows}\marg{db name}\marg{row1 index}\marg{row2 index} -%\end{definition} -%where \meta{row1 index} and \meta{row2 index} are the indices -%of the rows to be swapped. For example: -%\begin{verbatim} -%\DTLswaprows{scores}{3}{5} -%\end{verbatim} -%will swap the third and fifth rows. -% -%\begin{definition}[\DescribeMacro{\DTLifinlist}] -%\cs{DTLifinlist}\marg{element}\marg{list}\marg{true part}\marg{false part} +% 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} -%If \meta{element} is contained in the comma-separated list given -%by \meta{list}, then do \meta{true part} otherwise do false -%part. (Does a one level expansion on \meta{list}, but no -%expansion on \meta{element}.) -% -%\section{Pie Charts (\texorpdfstring{\sty{datapie}}{datapie} package)} -% -%The \sty{datapie} package is not loaded by the \sty{datatool} package, -%so you need to explicitly load \sty{datapie} if you want to use any of the -%commands defined in this section. You will also need to have the -%\sty{pgf}/\sty{tikz} packages installed. The \sty{datapie} package -%may be given the following options: -%\begin{description} -%\item[{\pkgopt[datapie]{color}}] Colour option (default). -%\item[{\pkgopt[datapie]{gray}}] Grey scale 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 -%\begin{definition}[\DescribeMacro{\DTLpiechart}]% -%\cs{DTLpiechart}\oarg{condition}\marg{settings list}\marg{db name}\marg{values} -%\end{definition}\noindent -%where \meta{db name} is the name of the database, and -%\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} +% 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{definition}[\DescribeMacro{\DTLpievariable}]% -%\cs{DTLpievariable} +%\begin{macro}{\DTLifFPopenbetween} +%\begin{definition} +%\cs{DTLifFPopenbetween}\marg{num}\marg{min}\marg{max}\marg{true part}\marg{false part} %\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. +% Determines if \meta{min} $<$ \meta{num} $<$ \meta{max} where +% all arguments are in standard fixed point notation. +% (Command name maintained for backward compatibility.) +% \begin{macrocode} +\let\DTLifFPopenbetween\dtlifnumopenbetween +% \end{macrocode} +%\end{macro} % -%\begin{definition}[\DescribeMacro{\DTLpiepercent}]% -%\cs{DTLpiepercent} +%\begin{macro}{\DTLifFPclosedbetween} +%\begin{definition} +%\cs{DTLifFPclosedbetween}\marg{num}\marg{min}\marg{max}\marg{true part}\marg{false part} %\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 -%\desctr{DTLpieroundvar}. +% Determines if \meta{min} $\leq$ \meta{num} $\leq$ \meta{max}. +% (Command name maintained for backward compatibility.) +% \begin{macrocode} +\let\DTLifFPclosedbetween\dtlifnumclosedbetween +% \end{macrocode} +%\end{macro} % -%\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{ifthen Conditionals} +% The following commands provide conditionals \cs{DTLis}\ldots\ +% which can be used in \cs{ifthenelse}. % -%\subsection{Pie Chart Label Formatting} +%\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{definition}[\DescribeMacro{\DTLdisplayinnerlabel}]% -%\cs{DTLdisplayinnerlabel}\marg{text} -%\end{definition} -%This governs how the inner label is formatted, where \meta{text} -%is the text of the inner label. The default is to just do \meta{text}. +%\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{definition}[\DescribeMacro{\DTLdisplayouterlabel}]% -%\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{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{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 or if you want to change the default colours, you -%will need to use -%\begin{definition}[\DescribeMacro{\DTLsetpiesegmentcolor}]% -%\cs{DTLsetpiesegmentcolor}\marg{n}\marg{color} -%\end{definition}\noindent -%The first argument \meta{n} is the segment index (starting from 1), -%and the second argument \meta{color} is a colour specifier as used -%in commands such as \cs{color}. -% -%It is a good idea to set the colours so that each segment colour -%is somehow relevant to whatever the segment represents. For -%example, in the previous examples of pie charts depicting fruit, -%some of default colours were inappropriate. Whilst red is -%appropriate for apples and green is appropriate for pears, blue -%doesn't really correspond to lemons or limes. -% -%\begin{definition}[\DescribeMacro{\DTLdopiesegmentcolor}]% -%\cs{DTLdopiesegmentcolor}\meta{n} -%\end{definition} -%This sets the current text colour to that of the \meta{n}th -%segment. -% -%\begin{definition}[\DescribeMacro{\DTLdocurrentpiesegmentcolor}]% -%\cs{DTLdocurrentpiesegmentcolor} -%\end{definition} -%This sets the current text colour to that of the current pie -%segment. This command may only be used within a pie chart, or -%within the body of \ics{DTLforeach}. +%\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{definition}[\DescribeMacro{\DTLpieoutlinecolor}]% -%\cs{DTLpieoutlinecolor} -%\end{definition} -%This sets the outline colour for the pie chart. The default is -%black. +%\begin{macro}{\dtl@testgt} +% Command to test if first argument is greater than second argument. +% This sets \cs{if@dtl@condition}. +% \begin{macrocode} +\newcommand*{\dtl@testgt}[2]{% + \DTLifgt{#1}{#2}{\@dtl@conditiontrue}{\@dtl@conditionfalse}% +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLisgt} +% Provide conditional command for use in \cs{ifthenelse} +% \begin{macrocode} +\newcommand*{\DTLisgt}[2]{% + \TE@throw\noexpand\dtl@testgt{#1}{#2}\noexpand\if@dtl@condition +} +% \end{macrocode} +%\end{macro} % -%\begin{definition}[\DescribeMacro{\DTLpieoutlinewidth}]% -%\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{macro}{\dtl@testicgt} +% Command to test if first argument is greater than second argument +% (ignores case). +% This sets \cs{if@dtl@condition}. +% \begin{macrocode} +\newcommand*{\dtl@testicgt}[2]{% + \@sDTLifgt{#1}{#2}{\@dtl@conditiontrue}{\@dtl@conditionfalse}% +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLisigt} +% Provide conditional command for use in \cs{ifthenelse} +%\changes{1.01}{2007 Aug 17}{new} +% \begin{macrocode} +\newcommand*{\DTLisigt}[2]{% + \TE@throw\noexpand\dtl@testicgt{#1}{#2}\noexpand\if@dtl@condition +} +% \end{macrocode} +%\end{macro} % -%\begin{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. The third segment (lemons and -%limes) is set to yellow and the fourth segment (peaches) is set -%to pink. In addition, a legend is created using \ics{DTLforeach}. -%\begin{verbatim} -%\begin{figure}[htbp] -%\centering -%\setlength{\DTLpieoutlinewidth}{2pt} -%\DTLsetpiesegmentcolor{3}{yellow} -%\DTLsetpiesegmentcolor{4}{pink} -%\renewcommand*{\DTLdisplayinnerlabel}[1]{\textsf{#1}} -%\renewcommand*{\DTLdisplayouterlabel}[1]{% -%\DTLdocurrentpiesegmentcolor -%\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} -%\DTLsetpiesegmentcolor{3}{yellow} -%\DTLsetpiesegmentcolor{4}{pink} -%\renewcommand*{\DTLdisplayinnerlabel}[1]{\textsf{#1}} -%\renewcommand*{\DTLdisplayouterlabel}[1]{\relax -%\DTLdocurrentpiesegmentcolor -%\textsf{\shortstack{#1}}} -%\DTLpiechart{variable=\quantity,innerlabel={\DTLpiepercent -%\%},outerlabel={\name\\(\DTLpievariable)}}{fruit}{\name=Name,\quantity=Quantity} -%\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} +%\begin{macro}{\dtl@testeq} +% Command to test if first argument is equal to the second argument. +% This sets \cs{if@dtl@condition}. +% \begin{macrocode} +\newcommand*{\dtl@testeq}[2]{% + \DTLifeq{#1}{#2}{\@dtl@conditiontrue}{\@dtl@conditionfalse}% +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLiseq} +% Provide conditional command for use in \cs{ifthenelse} +% \begin{macrocode} +\newcommand*{\DTLiseq}[2]{% + \TE@throw\noexpand\dtl@testeq{#1}{#2}\noexpand\if@dtl@condition +} +% \end{macrocode} +%\end{macro} % -%\subsection{Adding Extra Commands Before and After the Pie Chart} +%\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} % -%The pie charts created using \ics{DTLpiechart} are placed inside -%a \env{tikzpicture} environment (defined by the \sty{tikz} package). +%\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{definition}[\DescribeMacro{\DTLpieatbegintikz}]% -%\cs{DTLpieatbegintikz} -%\end{definition} -%The macro \cs{DTLpieatbegintikz} is called at the start of the -%\env{tikzpicture} environment, allowing you to change the -%\env{tikzpicture} settings. By default \cs{DTLpieatbegintikz} -%does nothing, but you can redefine it to, say, scale the pie -%chart (but be careful not to distort the chart). +%\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{definition}[\DescribeMacro{\DTLpieatendtikz}]% -%\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{macro}{\dtl@testnumclosedbetween} +% Command to test if first number lies between second and third +% numbers. (End points included, all arguments are fixed point +% numbers in standard format.) This sets \cs{if@dtl@condition}. +% \begin{macrocode} +\newcommand*{\dtl@testnumclosedbetween}[3]{% + \DTLifnumclosedbetween{#1}{#2}{#3}% + {\@dtl@conditiontrue}{\@dtl@conditionfalse}% +} +% \end{macrocode} +%\end{macro} % -%\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 -%\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} -%\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}". -% -% -%\begin{definition}[\DescribeMacro{\DTLplot}]% -%\cs{DTLplot}\oarg{condition}\marg{db list}\marg{settings} -%\end{definition} -%This command creates a plot (inside a \env{tikzpicture} environment) -%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 \ctr{DTLplotroundXvar}. -% -%\item[\setting{DTLplot}{yticlabels}] The value must be a comma -%separated list of labels for each $y$ tick mark. If omitted, -%the labels are the value of the $y$ tick position, rounded -%\meta{n} digits after the decimal point, where \meta{n} is -%given by the value of the counter \ctr{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: -%\begin{definition}[\DescribeMacro{\DTLplotatbegintikz}]% -%\cs{DTLplotatbegintikz} -%\end{definition}\noindent -%and -%\begin{definition}[\DescribeMacro{\DTLplotatendtikz}]% -%\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. -% -%\begin{definition}[\DescribeMacro{\DTLaddtoplotlegend}]% -%\cs{DTLaddtoplotlegend}\marg{marker}\marg{line style}\marg{text} -%\end{definition} -%This adds a new row to the plot legend where \meta{marker} is -%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} +% Provide conditional command for use in \cs{ifthenelse} +%\begin{macro}{\DTLisnumclosedbetween} +% \begin{macrocode} +\newcommand*{\DTLisnumclosedbetween}[3]{% + \TE@throw\noexpand\dtl@testnumclosedbetween{#1}{#2}{#3}% + \noexpand\if@dtl@condition +} +% \end{macrocode} +%\end{macro} % -%\label{fig:annote} -%\end{figure} -%\end{example} +%\begin{macro}{\dtl@testnumopenbetween} +% Command to test if first number lies between second and third +% numbers. (End points excluded, all arguments are fixed point +% numbers in standard format.) This sets \cs{if@dtl@condition}. +% \begin{macrocode} +\newcommand*{\dtl@testnumopenbetween}[3]{% + \DTLifnumopenbetween{#1}{#2}{#3}% + {\@dtl@conditiontrue}{\@dtl@conditionfalse}% +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLisnumopenbetween} +% Provide conditional command for use in \cs{ifthenelse} +% \begin{macrocode} +\newcommand*{\DTLisnumopenbetween}[3]{% + \TE@throw\noexpand\dtl@testnumopenbetween{#1}{#2}{#3}% + \noexpand\if@dtl@condition +} +% \end{macrocode} +%\end{macro} % -%\subsection{Global Plot Settings} +%\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} % -%\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}. +%\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{definition}[\DescribeMacro{\DTLplotwidth}]% -%\cs{DTLplotwidth} -%\end{definition} -%This length governs the length of the $x$ axis. Note that the plot -%width does not include any outer tick marks or labels. The default -%value is 4in. +%\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{definition}[\DescribeMacro{\DTLplotheight}]% -%\cs{DTLplotheight} -%\end{definition} -%This length governs the length of the $y$ axis. Note that the plot -%height does not include any outer tick marks or labels. The default -%value is 4in +%\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{definition}[\DescribeMacro{\DTLticklength}]% -%\cs{DTLticklength} -%\end{definition} -%This governs the length of the tick marks. The default value is -%5pt. +%\begin{macro}{\DTLisFPclosedbetween} +% Keep old command name for backwards compatibility: +% \begin{macrocode} +\let\DTLisFPclosedbetween\DTLisnumclosedbetween +% \end{macrocode} +%\end{macro} % -%\begin{definition}[\DescribeMacro{\DTLminorticklength}]% -%\cs{DTLminorticklength} -%\end{definition} -%This governs the length of the minor tick marks. The default value is -%2pt. +%\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{definition}[\DescribeMacro{\DTLticklabeloffset}]% -%\cs{DTLticklabeloffset} -%\end{definition} -%This governs the distance from the axis to the tick labels. The -%default value is 8pt. +%\begin{macro}{\dtl@testFPislt} +% Command to test if first number is less than second +% number where both numbers are in standard format. +% This sets \cs{if@dtl@condition}. +% \begin{macrocode} +\newcommand*{\dtl@testFPislt}[2]{% + \dtlifnumlt{#1}{#2}% + {% + \@dtl@conditiontrue + }% + {% + \@dtl@conditionfalse + }% +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLisFPlt} +% Provide conditional command for use in \cs{ifthenelse} +% \begin{macrocode} +\newcommand*{\DTLisFPlt}[2]{% + \TE@throw\noexpand\dtl@testFPislt{#1}{#2}% + \noexpand\if@dtl@condition +} +% \end{macrocode} +%\end{macro} % -%\begin{definition}[\DescribeMacro{\DTLmintickgap}]% -%\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. +%\begin{macro}{\dtl@testFPisgt} +% Command to test if first number is greater than second +% number where both numbers are in standard format. +% This sets \cs{if@dtl@condition}. +% \begin{macrocode} +\newcommand*{\dtl@testFPisgt}[2]{% + \dtlifnumgt{#1}{#2}% + {% + \@dtl@conditiontrue + }% + {% + \@dtl@conditionfalse + }% +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLisFPgt} +% Provide conditional command for use in \cs{ifthenelse} +% \begin{macrocode} +\newcommand*{\DTLisFPgt}[2]{% + \TE@throw\noexpand\dtl@testFPisgt{#1}{#2}% + \noexpand\if@dtl@condition +} +% \end{macrocode} +%\end{macro} % -%\begin{definition}[\DescribeMacro{\DTLlegendxoffset}]% -%\cs{DTLlegendxoffset} -%\end{definition} -%This is the horizontal distance from the border of the plot to the -%outer border of the legend. The default value is 10pt. +%\begin{macro}{\dtl@testFPiseq} +% Command to test if two numbers are equal, where both numbers +% are in standard decimal format +% \begin{macrocode} +\newcommand*{\dtl@testFPiseq}[2]{% + \dtlifnumeq{#1}{#2}% + {% + \@dtl@conditiontrue + }% + {% + \@dtl@conditionfalse + }% +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLisFPeq} +% Provide conditional command for use in \cs{ifthenelse} +% \begin{macrocode} +\newcommand*{\DTLisFPeq}[2]{% + \TE@throw\noexpand\dtl@testFPiseq{#1}{#2}% + \noexpand\if@dtl@condition +} +% \end{macrocode} +%\end{macro} % -%\begin{definition}[\DescribeMacro{\DTLlegendyoffset}]% -%\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. +%\begin{macro}{\dtl@testFPislteq} +% Command to test if first number is less than or equal to second +% number where both numbers are in standard format. +% This sets \cs{if@dtl@condition}. +% \begin{macrocode} +\newcommand*{\dtl@testFPislteq}[2]{% + \dtlifnumlt{#1}{#2}% + {% + \@dtl@conditiontrue + }% + {% + \@dtl@conditionfalse + }% + \if@dtl@condition + \else + \dtl@testFPiseq{#1}{#2}% + \fi +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLisFPlteq} +% Provide conditional command for use in \cs{ifthenelse} +% \begin{macrocode} +\newcommand*{\DTLisFPlteq}[2]{% + \TE@throw\noexpand\dtl@testFPislteq{#1}{#2}% + \noexpand\if@dtl@condition +} +% \end{macrocode} +%\end{macro} % -%\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{macro}{\dtl@testFPisgteq} +% Command to test if first number is greater than or equal to second +% number where both numbers are in standard format. +% This sets \cs{if@dtl@condition}. +% \begin{macrocode} +\newcommand*{\dtl@testFPisgteq}[2]{% + \dtlifnumgt{#1}{#2}% + {% + \@dtl@conditiontrue + }% + {% + \@dtl@conditionfalse + }% + \if@dtl@condition + \else + \dtl@testFPiseq{#1}{#2}% + \fi +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLisFPgteq} +% Provide conditional command for use in \cs{ifthenelse} +% \begin{macrocode} +\newcommand*{\DTLisFPgteq}[2]{% + \TE@throw\noexpand\dtl@testFPisgteq{#1}{#2}% + \noexpand\if@dtl@condition} +% \end{macrocode} +%\end{macro} % -%\begin{definition}[\DescribeCounter{DTLplotroundXvar}] -%\ctrfmt{DTLplotroundXvar} -%\end{definition} -%Unless you specify your own tick labels, the $x$ tick labels will -%be given by the tick points rounded to \meta{n} digits after the -%decimal point, where \meta{n} is the value of the counter -%\ctrfmt{DTLplotroundXvar}. +%\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{definition}[\DescribeCounter{DTLplotroundYvar}] -%\ctrfmt{DTLplotroundYvar} -%\end{definition} -%Unless you specify your own tick labels, the $y$ tick labels will -%be given by the tick points rounded to \meta{n} digits after the -%decimal point, where \meta{n} is the value of the counter -%\ctrfmt{DTLplotroundYvar}. -% -%\subsubsection{Macros} -%These macros govern the appearance of plots created using -%\ics{DTLplot}. They can be changed using \cs{renewcommand}. +%\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{definition}[\DescribeMacro{\DTLplotmarks}]% -%\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. +%\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{definition}[\DescribeMacro{\DTLplotmarkcolors}]% -%\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. +%\begin{macro}{\dtl@testreal} +% Command to test if argument is a real. This sets +% \cs{if@dtl@condition} +% \begin{macrocode} +\newcommand*{\dtl@testreal}[1]{% + \DTLifreal{#1}{\@dtl@conditiontrue}{\@dtl@conditionfalse}} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLisreal} +% Provide conditional command for use in \cs{ifthenelse} +% \begin{macrocode} +\newcommand*{\DTLisreal}[1]{% + \TE@throw\noexpand\dtl@testreal{#1}\noexpand\if@dtl@condition} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\dtl@testcurrency} +% Command to test if argument is a currency. This sets +% \cs{if@dtl@condition} +% \begin{macrocode} +\newcommand*{\dtl@testcurrency}[1]{% + \DTLifcurrency{#1}{\@dtl@conditiontrue}{\@dtl@conditionfalse}} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLiscurrency} +% Provide conditional command for use in \cs{ifthenelse} +% \begin{macrocode} +\newcommand*{\DTLiscurrency}[1]{% + \TE@throw\noexpand\dtl@testcurrency{#1}\noexpand\if@dtl@condition} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\dtl@testcurrencyunit} +% Command to test if argument is a currency with given unit. This sets +% \cs{if@dtl@condition} +% \begin{macrocode} +\newcommand*{\dtl@testcurrencyunit}[2]{% + \DTLifcurrencyunit{#1}{#2}{\@dtl@conditiontrue}{\@dtl@conditionfalse}} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLiscurrencyunit} +% Provide conditional command for use in \cs{ifthenelse} +% \begin{macrocode} +\newcommand*{\DTLiscurrencyunit}[2]{% + \TE@throw\noexpand\dtl@testcurrencyunit{#1}{#2}% + \noexpand\if@dtl@condition +} +% \end{macrocode} +%\end{macro} +% +%\section{Loops} +%\begin{macro}{\dtlbreak} +% Break out of loop at the end of current iteration. +% \begin{macrocode} +\newcommand*{\dtlbreak}{% + \PackageError{datatool}{Can't break out of anything}{}% +} +% \end{macrocode} +%\end{macro} % -%\begin{definition}[\DescribeMacro{\DTLplotlines}]% -%\cs{DTLplotlines} +%\begin{macro}{\dtlforint} +%\begin{definition} +%\cs{dtlforint}\meta{ct}=\meta{start}\cs{to}\meta{end}\cs{step}% +%\meta{inc}\cs{do}\marg{body} %\end{definition} -%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. +% \meta{ct} is a count register, \meta{start}, \meta{end} and +% \meta{inc} are integers. +% Group if nested or use \cs{dtlgforint}. +% An infinite loop may result if \meta{inc}$=0$ and +% \meta{start} $\le$ \meta{end} and \cs{dtlbreak} isn't used. +% \begin{macrocode} +\long\def\dtlforint#1=#2\to#3\step#4\do#5{% +% \end{macrocode} +% Make a copy of old version of break function +% \begin{macrocode} + \let\@dtl@orgbreak\dtlbreak + \def\@dtl@endloophook{}% +% \end{macrocode} +% Setup break function for the loop (sets \meta{ct} to \meta{end} +% at the end of the current iteration). +% \begin{macrocode} + \def\dtlbreak{\def\@dtl@endloophook{#1=#3}}% +% \end{macrocode} +% Initialise \meta{ct} +% \begin{macrocode} + #1=#2\relax +% \end{macrocode} +% Check if the steps are positive or negative. +% \begin{macrocode} + \ifnum#4<0\relax +% \end{macrocode} +% Counting down +% \begin{macrocode} + \whiledo{\(#1>#3\)\TE@or\(#1=#3\)}% + {% + #5% + \@dtl@endloophook + \advance#1 by #4\relax + }% + \else +% \end{macrocode} +% Counting up +% \begin{macrocode} + \whiledo{\(#1<#3\)\TE@or\(#1=#3\)}% + {% + #5% + \@dtl@endloophook + \advance#1 by #4\relax + }% + \fi +% \end{macrocode} +% Restore break function. +% \begin{macrocode} + \let\dtlbreak\@dtl@orgbreak +} +% \end{macrocode} +%\end{macro} % -%\begin{definition}[\DescribeMacro{\DTLplotlinecolors}]% -%\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}. +%\begin{macro}{\@dtl@foreach@level} +% Count register to keep track of global nested loops. +% \begin{macrocode} +\newcount\@dtl@foreach@level +% \end{macrocode} +%\end{macro} % -%\begin{definition}[\DescribeMacro{\DTLXAxisStyle}]% -%\cs{DTLXAxisStyle} +%\begin{macro}{\dtlgforint} +%\begin{definition} +%\cs{dtlgforint}\meta{ct}=\meta{start}\cs{to}\meta{end}\cs{step}% +%\meta{inc}\cs{do}\marg{body} %\end{definition} -%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} +% \meta{ct} is a count register, \meta{start}, \meta{end} and +% \meta{inc} are integers. +% An infinite loop may result if \meta{inc}=0 and \meta{start} $\le$ +% \meta{end} and \cs{dtlbreak} isn't used. +% \begin{macrocode} +\long\def\dtlgforint#1=#2\to#3\step#4\do#5{% +% \end{macrocode} +% Initialise +% \begin{macrocode} + \global#1=#2\relax +% \end{macrocode} +% Increment level counter to allow for nested loops +% \begin{macrocode} + \global\advance\@dtl@foreach@level by 1\relax +% \end{macrocode} +% Set up end loop hook +% \begin{macrocode} + \expandafter\global\expandafter + \let\csname @dtl@endhook@\the\@dtl@foreach@level\endcsname + \relax +% \end{macrocode} +% Set up the break function: +% Copy current definition +% \begin{macrocode} + \expandafter\global\expandafter + \let\csname @dtl@break@\the\@dtl@foreach@level\endcsname + \dtlbreak +% \end{macrocode} +% Set up definition for this level (sets to at the end +% of the current iteration). +% \begin{macrocode} + \gdef\dtlbreak{\expandafter + \gdef\csname @dtl@endhook@\the\@dtl@foreach@level\endcsname{% + #1=#3}}% +% \end{macrocode} +% check the direction +% \begin{macrocode} + \ifnum#4<0\relax +% \end{macrocode} +% Counting down +% \begin{macrocode} + \whiledo{\(#1>#3\)\TE@or\(#1=#3\)}% + {% + #5% + \csname @dtl@endhook@\the\@dtl@foreach@level\endcsname + \global\advance#1 by #4\relax + }% + \else +% \end{macrocode} +% Counting up (or 0 increments) +% \begin{macrocode} + \whiledo{\(#1<#3\)\TE@or\(#1=#3\)}% + {% + #5% + \csname @dtl@endhook@\the\@dtl@foreach@level\endcsname + \global\advance#1 by #4\relax + }% + \fi +% \end{macrocode} +% Restore break function +% \begin{macrocode} + \expandafter\global\expandafter\let\expandafter\dtlbreak + \csname @dtl@break@\the\@dtl@foreach@level\endcsname +% \end{macrocode} +% Decrement level counter +% \begin{macrocode} + \global\advance\@dtl@foreach@level by -1\relax +} +% \end{macrocode} +%\end{macro} % -%\begin{definition}[\DescribeMacro{\DTLYAxisStyle}]% -%\cs{DTLYAxisStyle} -%\end{definition} -%This governs the style of the $y$ axis. It is analogous to -%\cs{DTLXAxisStyle} described above. +%\begin{environment}{dtlenvgforint} +% Environment form (contents are gathered, so verbatim can't be +% used): +% \begin{macrocode} +\newenvironment{dtlenvgforint}[1]% +{% + \def\@dtlenvgforint@arg{#1}% + \long@collect@body\@do@dtlenvgforint +}% +{} +\newcommand{\@do@dtlenvgforint}[1]{% + \expandafter\dtlgforint\@dtlenvgforint@arg\do{#1}% +} +% \end{macrocode} +%\end{environment} +%\iffalse +% \begin{macrocode} +% +% \end{macrocode} +%\fi +%\iffalse +% \begin{macrocode} +%<*datatool-fp.sty> +% \end{macrocode} +%\fi +%\chapter{datatool-fp.sty}\label{sec:code:datatool-fp} +% Definitions of fixed-point commands that use the \sty{fp} package. +% \begin{macrocode} +\NeedsTeXFormat{LaTeX2e} +\ProvidesPackage{datatool-fp}[2012/07/18 v2.10 (NLCT)] +% \end{macrocode} +% Required packages: +% \begin{macrocode} +\RequirePackage{xkeyval} +\RequirePackage{fp} +\RequirePackage{datatool-base} +% \end{macrocode} +%\begin{option}{verbose} +% Switch \sty{fp} messages on or off +% \begin{macrocode} +\define@choicekey{datatool-fp}{verbose}[\val\nr]{true,false}[true]{% + \ifcase\nr\relax + \FPmessagestrue + \or + \FPmessagesfalse + \fi +} +\let\ifFPmessages\ifdtlverbose +% \end{macrocode} +%\end{option} % -%\begin{definition}[\DescribeMacro{\DTLmajorgridstyle}]% -%\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. +% Process package options: +% \begin{macrocode} +\ProcessOptionsX +% \end{macrocode} % -%\begin{definition}[\DescribeMacro{\DTLminorgridstyle}]% -%\cs{DTLminorgridstyle} +% Define commands that are needed before loading +% \sty{datatool-base}: +% \begin{macrocode} +\providecommand*{\@dtl@mathprocessor}{fp} +% \end{macrocode} +%\begin{macro}{\dtlifnumeq} +%\begin{definition} +%\cs{dtlifnumeq}\marg{num1}\marg{num2}\marg{true part}\marg{false +%part} %\end{definition} -%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. +% Does \meta{true part} if \meta{num1}=\meta{num2}, otherwise does +% \meta{false part}. The numbers must use a full stop as the decimal +% character and no number group separator. +% \begin{macrocode} +\newcommand*{\dtlifnumeq}[4]{% + \FPifeq{#1}{#2}% + #3% + \else + #4% + \fi +} +% \end{macrocode} +%\end{macro} % -%\begin{definition}[\DescribeMacro{\DTLformatlegend}]% -%\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. +% If \pkgopt{verbose} option set, switch on \pkgopt{verbose} for +% \sty{datatool-base} as well: +% \begin{macrocode} +\let\ifdtlverbose\ifFPmessages +% \end{macrocode} % -%\subsection{Adding to a Plot Stream} +%\section{Comparison Commands} % -%\begin{definition}[\DescribeMacro{\DTLplotstream}]% -%\cs{DTLplotstream}\oarg{condition}\marg{db name}\marg{x key}\marg{y key} +%\begin{macro}{\dtlifnumlt} +%\begin{definition} +%\cs{dtlifnumlt}\marg{num1}\marg{num2}\marg{true part}\marg{false +%part} %\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 \ctr{DTLplotroundXvar} to zero -%otherwise the $x$ axis would have looked too cluttered. -%\item I have used \ics{DTLminforkeys} and \ics{DTLmaxforkeys} to -%determine the bounds since \ics{DTLplot} won't take the data -%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}". You must also have the \sty{pgf} package -%installed. -% -%Bar charts can either be vertical or horizontal, the default is -%vertical. In this section the $x$ axis refers to the horizontal -%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} -% -% -% -%\begin{definition}[\DescribeMacro{\DTLbarchart}]% -%\cs{DTLbarchart}\oarg{condition}\marg{db name}\marg{settings}\marg{values} -%\end{definition} -%\begin{definition}[\DescribeMacro{\DTLmultibarchart}]% -%\cs{DTLmultibarchart}\oarg{condition}\marg{db name}\marg{settings}\marg{values} -%\end{definition} -%These commands both create a bar chart from the information in -%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} -% +% Does \meta{true part} if \meta{num1} \textless \meta{num2}, otherwise does +% \meta{false part}. The numbers must use a full stop as the decimal +% character and no number group separator. +% \begin{macrocode} +\newcommand*{\dtlifnumlt}[4]{% + \FPiflt{#1}{#2}% + #3% + \else + #4% + \fi +} +% \end{macrocode} +%\end{macro} % -%\begin{definition}[\DescribeMacro{\DTLbarchartlength}]% -%\cs{DTLbarchartlength} +%\begin{macro}{\dtlifnumgt} +%\begin{definition} +%\cs{dtlifnumgt}\marg{num1}\marg{num2}\marg{true part}\marg{false +%part} %\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. +% Does \meta{true part} if \meta{num1} \textgreater \meta{num2}, otherwise does +% \meta{false part}. The numbers must use a full stop as the decimal +% character and no number group separator. +% \begin{macrocode} +\newcommand*{\dtlifnumgt}[4]{% + \FPifgt{#1}{#2}% + #3% + \else + #4% + \fi +} +% \end{macrocode} +%\end{macro} % -%\begin{definition}[\DescribeMacro{\DTLbarwidth}]% -%\cs{DTLbarwidth} +%\begin{macro}{\dtlifnumopenbetween} +%\begin{definition} +%\cs{dtlifnumopenbetween}\marg{num}\marg{min}\marg{max}\marg{true part}\marg{false part} %\end{definition} -%This specifies the width of each bar. You must use \cs{setlength} -%to change this value. The default value is 1cm. +% Determines if \meta{min} $<$ \meta{num} $<$ \meta{max} where +% all arguments are in standard fixed point notation. +% \begin{macrocode} +\newcommand*{\dtlifnumopenbetween}[5]{% + \let\@dtl@dovalue\relax + \dtlifnumgt{#1}{#2}% + {}% + {% + \def\@dtl@dovalue{#5}% + }% + \dtlifnumlt{#1}{#3}% + {% + \ifx\@dtl@dovalue\relax + \def\@dtl@dovalue{#4}% + \fi + }% + {% + \def\@dtl@dovalue{#5}% + }% + \@dtl@dovalue +} +% \end{macrocode} +%\end{macro} % -%\begin{definition}[\DescribeMacro{\DTLbarlabeloffset}]% -%\cs{DTLbarlabeloffset} +%\begin{macro}{\dtlifnumclosedbetween} +%\begin{definition} +%\cs{dtlifnumclosedbetween}\marg{num}\marg{min}\marg{max}\marg{true part}\marg{false part} %\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. +% Determines if \meta{min} $\leq$ \meta{num} $\leq$ \meta{max} where +% all arguments are in standard fixed point notation. +% \begin{macrocode} +\newcommand*{\dtlifnumclosedbetween}[5]{% + \let\@dtl@dovalue\relax + \dtlifnumgt{#1}{#2}% + {}% + {% + \dtlifnumeq{#1}{#2}% + {% + \def\@dtl@dovalue{#4}% + }% + {% + \def\@dtl@dovalue{#5}% + }% + }% + \dtlifnumlt{#1}{#3}% + {% + \ifx\@dtl@dovalue\relax + \def\@dtl@dovalue{#4}% + \fi + }% + {% + \dtlifnumeq{#1}{#3}% + {% + \def\@dtl@dovalue{#4}% + }% + {% + \def\@dtl@dovalue{#5}% + }% + }% + \@dtl@dovalue +} +% \end{macrocode} +%\end{macro} % -%\begin{definition}[\DescribeCounter{DTLbarroundvar}] -%\ctrfmt{DTLbarroundvar} -%\end{definition} -%The $y$ tick labels are rounded to \meta{n} digits after the -%decimal point, where \meta{n} is given by the value of the -%counter \ctrfmt{DTLbarroundvar}. You must use \cs{setcounter} -%to change this value. +%\section{Functions} % -%\begin{definition}[\DescribeMacro{\DTLsetbarcolor}]% -%\cs{DTLsetbarcolor}\marg{n}\marg{color} -%\end{definition} -%This sets the \meta{n}th bar colour to \meta{color}. -%Only the first eight bars have a colour defined by default. If you -%need more than eight bars, you will need to define more bar colours. -%It is recommended that you set the colour of each bar to -%correspond with whatever the bar represents. +%\begin{macro}{\dtladd} +% Adds two numbers using fp. +% \begin{macrocode} +\newcommand*{\dtladd}[3]{% + \FPadd{#1}{#2}{#3}% +} +% \end{macrocode} +%\end{macro} % -%\begin{definition}[\DescribeMacro{\DTLdobarcolor}]% -%\cs{DTLdobarcolor}\marg{n} -%\end{definition} -%This sets the current colour to the colour of the \meta{n}th bar. +%\begin{macro}{\dtlsub} +% Subtracts two numbers using fp. +% \begin{macrocode} +\newcommand*{\dtlsub}[3]{% + \FPsub{#1}{#2}{#3}% +} +% \end{macrocode} +%\end{macro} % -%\begin{definition}[\DescribeMacro{\DTLbaroutlinecolor}]% -%\cs{DTLbaroutlinecolor} -%\end{definition} -%This macro contains the colour of the bar outlines. This defaults -%to "black". +%\begin{macro}{\dtlmul} +% Multiplies two numbers using fp. +% \begin{macrocode} +\newcommand*{\dtlmul}[3]{% + \FPmul{#1}{#2}{#3}% +} +% \end{macrocode} +%\end{macro} % -%\begin{definition}[\DescribeMacro{\DTLbaroutlinewidth}]% -%\cs{DTLbaroutlinewidth} -%\end{definition} -%This length specifies the line width for the bar outlines. If it -%is 0pt, the outline is not drawn. The default value is 0pt. +%\begin{macro}{\dtldiv} +% Divides two numbers using fp. +% \begin{macrocode} +\newcommand*{\dtldiv}[3]{% + \FPdiv{#1}{#2}{#3}% +} +% \end{macrocode} +%\end{macro} % +%\begin{macro}{\dtlroot} +% Square root using fp. +% \begin{macrocode} +\newcommand*{\dtlroot}[2]{% + \FProot{#1}{#2}% +} +% \end{macrocode} +%\end{macro} % -%\begin{definition}[\DescribeMacro{\DTLbaratbegintikz}]% -%\cs{DTLbaratbegintikz} -%\end{definition} -%This specifies any additional commands to add to the start of -%the plot. It defaults to nothing, and is called after the -%unit vectors are set. +%\begin{macro}{\dtlround} +% Rounds using fp. +% \begin{macrocode} +\newcommand*{\dtlround}[3]{% + \FPround{#1}{#2}{#3}% +} +% \end{macrocode} +%\end{macro} % -%\begin{definition}[\DescribeMacro{\DTLbaratendtikz}]% -%\cs{DTLbaratendtikz} -%\end{definition} -%This specifies any additional commands to add to the end of -%the plot. It defaults to nothing. +%\begin{macro}{\dtltrunc} +% Truncates using fp. +% (Third argument is the number of digits.) +% \begin{macrocode} +\newcommand*{\dtltrunc}[3]{% + \FPtrunc{#1}{#2}{#3}% +} +% \end{macrocode} +%\end{macro} % -%\begin{definition}[\DescribeMacro{\DTLeverybarhook}]% -%\cs{DTLeverybarhook} -%\end{definition} -%The specifies code to apply at every bar. Within the definition -%of \cs{DTLeverybarhook} you can use the commands -%\DescribeMacro{\DTLstartpt}\cs{DTLstartpt} (the start -%of the bar), \DescribeMacro{\DTLmidpt}\cs{DTLmidpt} -%(the mid point of the bar) and -%\DescribeMacro{\DTLendpt}\cs{DTLendpt} (the end of the bar). For -%example (using the earlier "fruit" database): -%\begin{verbatim} -%\renewcommand*{\DTLeverybarhook}{% -%\pgftext[at=\DTLmidpt]{\insertName\space(\insertValue)}% -%} -%\DTLbarchart{variable=\insertValue,axes=both, -%ylabel=Quantity,max=50,verticalbars=false -%}% -%{fruit}{\insertValue=Value,\insertName=Name} -%\end{verbatim} -%This puts the name followed by the quantity in brackets in the -%middle of the bar. +%\begin{macro}{\dtlclip} +% \begin{macrocode} +\newcommand*{\dtlclip}[2]{% + \FPclip{#1}{#2}% +} +% \end{macrocode} +%\end{macro} % -%\begin{definition}[\DescribeMacro{\ifDTLverticalbars}]% -%\cs{ifDTLverticalbars} -%\end{definition} -%This conditional governs whether the chart uses vertical or -%horizontal bars. +%\begin{macro}{\dtlmin} +% Minimum of two numbers using fp. +% \begin{macrocode} +\newcommand*{\dtlmin}[3]{% + \FPmin{#1}{#2}{#3}% +} +% \end{macrocode} +%\end{macro} % -%\begin{definition}[\DescribeMacro{\DTLbarXlabelalign}]% -%\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. +%\begin{macro}{\dtlmax} +% Maximum of two numbers using fp. +% \begin{macrocode} +\newcommand*{\dtlmax}[3]{% + \FPmax{#1}{#2}{#3}% +} +% \end{macrocode} +%\end{macro} % -%\begin{definition}[\DescribeMacro{\DTLbarYticklabelalign}]% -%\cs{DTLbarYlabelalign} -%\end{definition} -%This specifies the text alignment of the $y$ axis labels. This -%defaults to "right" for vertical bar charts and "center" for -%horizontal bar charts. +%\begin{macro}{\dtlabs} +% Absolute value using fp. +% \begin{macrocode} +\newcommand*{\dtlabs}[2]{% + \FPabs{#1}{#2}% +} +% \end{macrocode} +%\end{macro} % -%\begin{definition}[\DescribeMacro{\DTLbardisplayYticklabel}]% -%\cs{DTLbardisplayYticklabel}\marg{text} +%\begin{macro}{\dtlneg} +% Negative of a value using fp. +% \begin{macrocode} +\newcommand*{\dtlneg}[2]{% + \FPneg{#1}{#2}% +} +% \end{macrocode} +%\end{macro} +% +%\iffalse +% \begin{macrocode} +% +% \end{macrocode} +%\fi +%\iffalse +% \begin{macrocode} +%<*datatool-pgfmath.sty> +% \end{macrocode} +%\fi +%\chapter{datatool-pgfmath.sty}\label{sec:code:datatool-pgfmath} +% Definitions of fixed-point commands that use the \sty{pgfmath} package. +% \begin{macrocode} +\NeedsTeXFormat{LaTeX2e} +\ProvidesPackage{datatool-pgfmath}[2012/07/18 v2.10 (NLCT)] +% \end{macrocode} +% Required packages: +% \begin{macrocode} +\RequirePackage{xkeyval} +\RequirePackage{pgfrcs,pgfkeys,pgfmath} +% \end{macrocode} +% +% Process package options: +% \begin{macrocode} +\ProcessOptionsX +% \end{macrocode} +% +% Define commands that are needed before loading +% \sty{datatool-base}: +% \begin{macrocode} +\providecommand*{\@dtl@mathprocessor}{pgfmath} +% \end{macrocode} +%\begin{macro}{\dtlifnumeq} +%\begin{definition} +%\cs{dtlifnumeq}\marg{num1}\marg{num2}\marg{true part}\marg{false +%part} %\end{definition} -%This specifies how to display the $y$ tick label. The argument -%is the tick label. +% Does \meta{true part} if \meta{num1}=\meta{num2}, otherwise does +% \meta{false part}. The numbers must use a full stop as the decimal +% character and no number group separator. +% \begin{macrocode} +\newcommand*{\dtlifnumeq}[4]{% + \pgfmathifthenelse{#1==#2}{"#3"}{"#4"}% + \pgfmathresult +} +% \end{macrocode} +%\end{macro} +% +% Load base package: +% \begin{macrocode} +\RequirePackage{datatool-base} +% \end{macrocode} % -%\begin{definition}[\DescribeMacro{\DTLdisplaylowerbarlabel}]% -%\cs{DTLdisplaylowerbarlabel}\marg{text} +%\section{Comparison Commands} +%\begin{macro}{\dtlifnumlt} +%\begin{definition} +%\cs{dtlifnumlt}\marg{num1}\marg{num2}\marg{true part}\marg{false +%part} %\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. +% Does \meta{true part} if \meta{num1} \textless \meta{num2}, otherwise does +% \meta{false part}. The numbers must use a full stop as the decimal +% character and no number group separator. +% \begin{macrocode} +\newcommand*{\dtlifnumlt}[4]{% + \pgfmathifthenelse{#1 < #2}{"#3"}{"#4"}% + \pgfmathresult +} +% \end{macrocode} +%\end{macro} % -%\begin{definition}[\DescribeMacro{\DTLdisplaylowermultibarlabel}]% -%\cs{DTLdisplaylowermultibarlabel}\marg{text} +%\begin{macro}{\dtlifnumgt} +%\begin{definition} +%\cs{dtlifnumgt}\marg{num1}\marg{num2}\marg{true part}\marg{false +%part} %\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}. +% Does \meta{true part} if \meta{num1} \textgreater \meta{num2}, otherwise does +% \meta{false part}. The numbers must use a full stop as the decimal +% character and no number group separator. +% \begin{macrocode} +\newcommand*{\dtlifnumgt}[4]{% + \pgfmathifthenelse{#1 > #2}{"#3"}{"#4"}% + \pgfmathresult +} +% \end{macrocode} +%\end{macro} % -%\begin{definition}[\DescribeMacro{\DTLdisplayupperbarlabel}]% -%\cs{DTLdisplayupperbarlabel}\marg{text} +%\begin{macro}{\dtlifnumopenbetween} +%\begin{definition} +%\cs{dtlifnumopenbetween}\marg{num}\marg{min}\marg{max}\marg{true part}\marg{false part} %\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. +% Determines if \meta{min} $<$ \meta{num} $<$ \meta{max} where +% all numerical arguments are in standard fixed point notation. +% \begin{macrocode} +\newcommand*{\dtlifnumopenbetween}[5]{% + \pgfmathifthenelse{(#2 < #1) && (#1 < #3)}{"#4"}{"#5"}% + \pgfmathresult +} +% \end{macrocode} +%\end{macro} % -%\begin{definition}[\DescribeMacro{\DTLdisplayuppermultibarlabel}]% -%\cs{DTLdisplayuppermultibarlabel}\marg{text} +%\begin{macro}{\dtlifnumclosedbetween} +%\begin{definition} +%\cs{dtlifnumclosedbetween}\marg{num}\marg{min}\marg{max}\marg{true part}\marg{false part} %\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}. +% Determines if \meta{min} $\leq$ \meta{num} $\leq$ \meta{max} where +% all numerical arguments are in standard fixed point notation. +% \begin{macrocode} +\newcommand*{\dtlifnumclosedbetween}[5]{% + \pgfmathifthenelse{(#2 <= #1) && (#1 <= #3)}{"#4"}{"#5"}% + \pgfmathresult +} +% \end{macrocode} +%\end{macro} % -%\begin{example}{A Labelled Bar Chart}{ex:annotebarchart} -%This example extends \autoref{ex:barchart} so that the chart is -%a bit more informative (which is after all the whole point of -%a chart). This chart now has a label below each bar, as well -%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} +%\section{Functions} +%\begin{macro}{\dtladd} +% Adds two numbers using PGF math engine. +% \begin{macrocode} +\newcommand*{\dtladd}[3]{% + \pgfmathadd{#2}{#3}% + \let#1\pgfmathresult +} +% \end{macrocode} +%\end{macro} % -%Both \cs{DTLbarchart} and \cs{DTLmultibarchart} set the following -%macros, which may be used in \cs{DTLbaratbegintikz} and -%\cs{DTLbaratendtikz}: -%\begin{definition}[\DescribeMacro{\DTLbarchartwidth}]% -%\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). -% -%\begin{definition}[\DescribeMacro{\DTLnegextent}]% -%\cs{DTLnegextent} -%\end{definition} -%This is set to the negative extent of the bar chart. (This value -%may either be zero or negative, and corresponds to the -%\setting{DTLbarchart,DTLmultibarchart}{maxdepth} setting.) -% -%\begin{definition}[\DescribeMacro{\DTLbarmax}]% -%\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{macro}{\dtlsub} +% Subtracts two numbers using PGF math engine. +% \begin{macrocode} +\newcommand*{\dtlsub}[3]{% + \pgfmathsubtract{#2}{#3}% + \let#1\pgfmathresult +} +% \end{macrocode} +%\end{macro} % -%\begin{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. +%\begin{macro}{\dtlmul} +% Multiplies two numbers using PGF math engine. +% \begin{macrocode} +\newcommand*{\dtlmul}[3]{% + \pgfmathmultiply{#2}{#3}% + \let#1\pgfmathresult +} +% \end{macrocode} +%\end{macro} % -%\item I used \ics{DTLbargroupwidth} to indicate the width of -%each bar group. +%\begin{macro}{\dtldiv} +% Divides two numbers using PGF math engine. +% \begin{macrocode} +\newcommand*{\dtldiv}[3]{% + \pgfmathdivide{#2}{#3}% + \let#1\pgfmathresult +} +% \end{macrocode} +%\end{macro} % -%\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 \texorpdfstring{\sty{datatool}}{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} +%\begin{macro}{\dtlroot} +% Square root using PGF math engine. +% \begin{macrocode} +\newcommand*{\dtlroot}[2]{% + \pgfmathsqrt{#2}% + \let#1\pgfmathresult +} +% \end{macrocode} +%\end{macro} % -%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}. +%\begin{macro}{\dtlround} +% Rounds using PGF math engine. +% \begin{macrocode} +\newcommand*{\dtlround}[3]{% + \pgfmathparse{10^#3}% + \let\dtl@tmpshift\pgfmathresult + \pgfmathparse{round(#2 * \dtl@tmpshift) / \dtl@tmpshift}% + \let#1\pgfmathresult +} +% \end{macrocode} +%\end{macro} % -%\subsection{Loading a \texorpdfstring{\sty{databib}}{databib} -%database} -%\label{sec:loadbbl} +%\begin{macro}{\dtltrunc} +% Truncates using PGF math engine. +% (Third argument is the number of digits.) +% \begin{macrocode} +\newcommand*{\dtltrunc}[3]{% + \pgfmathparse{10^#3}% + \let\dtl@tmpshift\pgfmathresult + \pgfmathparse{floor(#2 * \dtl@tmpshift) / \dtl@tmpshift}% + \let#1\pgfmathresult +} +% \end{macrocode} +%\end{macro} % -%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{*}". +%\begin{macro}{\dtlclip} +% There isn't a clip in pgfmath as it seems to automatically clip. +% \begin{macrocode} +\newcommand*{\dtlclip}[2]{% + \edef#1{#2}% +} +% \end{macrocode} +%\end{macro} % -%\begin{definition}[\DescribeMacro{\DTLloadbbl}]% -%\cs{DTLloadbbl}\oarg{bbl name}\marg{db name}\marg{bib list} -%\end{definition} -%This command performs several functions: +%\begin{macro}{\dtlmin} +% Minimum of two numbers using PGF math engine. +% \begin{macrocode} +\newcommand*{\dtlmin}[3]{% + \pgfmathmin{#2}{#3}% + \let#1\pgfmathresult +} +% \end{macrocode} +%\end{macro} % -%\begin{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, +%\begin{macro}{\dtlmax} +% Maximum of two numbers using PGF math engine. +% \begin{macrocode} +\newcommand*{\dtlmax}[3]{% + \pgfmathmax{#2}{#3}% + \let#1\pgfmathresult +} +% \end{macrocode} +%\end{macro} % -%\item it writes \cs{bibdata}\marg{bib list} to the -%auxiliary file, which tells \BibTeX\ which \ext{bib} files to use, +%\begin{macro}{\dtlabs} +% Absolute value using PGF math engine. +% \begin{macrocode} +\newcommand*{\dtlabs}[2]{% + \pgfmathabs{#2}% + \let#1\pgfmathresult +} +% \end{macrocode} +%\end{macro} % -%\item it creates a \sty{datatool} database called \meta{db name}, +%\begin{macro}{\dtlneg} +% Negative of a value using PGF math engine. +% \begin{macrocode} +\newcommand*{\dtlneg}[2]{% + \pgfmathmul{-1}{#2}% + \let#1\pgfmathresult +} +% \end{macrocode} +%\end{macro} % -%\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} +%\iffalse +% \begin{macrocode} +% +% \end{macrocode} +%\fi +%\iffalse +% \begin{macrocode} +%<*datatool.sty> +% \end{macrocode} +%\fi +%\chapter{datatool.sty} +%\label{sec:code:datatool} +%\section{Package Declaration} +% \begin{macrocode} +\NeedsTeXFormat{LaTeX2e} +\ProvidesPackage{datatool}[2012/07/18 v2.10 (NLCT)] +% \end{macrocode} +% Load required packages: +% \begin{macrocode} +\RequirePackage{xkeyval} +\RequirePackage{ifthen} +\RequirePackage{xfor} +\RequirePackage{substr} +% \end{macrocode} +%\changes{2.0}{2009 February 27}{added etex as a required package} +% \begin{macrocode} +\RequirePackage{etex} +% \end{macrocode} % -%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{DTLloadbbl} doesn't generate any text. Once you have loaded -%the data, you can display the bibliography uses -%\cs{DTLbibliography} (described below) or you can iterate -%through it using \cs{DTLforeachbibentry} described in -%\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{DTLloadbbl} (described in \autoref{sec:loadbbl}) can be -%displayed using: -%\begin{definition}[\DescribeMacro{\DTLbibliography}] -%\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: -% -%\begin{definition}[\DescribeMacro{\DTLbibfieldexists}]% -%\cs{DTLbibfieldexists}\marg{field label} +%\section{Package Options} +%\begin{macro}{\@dtl@separator} +% The data separator character (comma by default) is stored in +% \cs{@dtl@separator}. +% This is the separator used in external data files, not in the +% \LaTeX\ code, which always uses a comma separator. +% \begin{macrocode} +\newcommand*{\@dtl@separator}{,} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLsetseparator} +%\begin{definition} +%\cs{DTLsetseparator}\marg{char} %\end{definition} -%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} +% 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. +%\changes{2.10}{2012-07-18}{changed tab character to +%\texttt{\textasciicircum\textasciicircum I}} +% \begin{macrocode} +\begingroup +\catcode`\^^I12 +\gdef\DTLsettabseparator{% + \catcode`\^^I12 + \DTLsetseparator{^^I}% +} +\endgroup +% \end{macrocode} +%\end{macro} % -%\begin{definition}[\DescribeMacro{\DTLbibfieldiseq}]% -%\cs{DTLbibfieldiseq}\marg{field label}\marg{value} +%\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 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} +% This sets the delimiter. +% \begin{macrocode} +\newcommand*\DTLsetdelimiter[1]{% + \renewcommand*{\@dtl@delimiter}{#1}% + \@dtl@construct@lopoffs +} +% \end{macrocode} +%\end{macro} % -%\begin{definition}[\DescribeMacro{\DTLbibfieldcontains}]% -%\cs{DTLbibfieldcontains}\marg{field label}\marg{sub string} +%\begin{macro}{\@dtl@construct@lopoff} +%\begin{definition} +%\cs{@dtl@construct@lopoff}\meta{separator char}\meta{delimiter char} %\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} -% -%\begin{definition}[\DescribeMacro{\DTLbibfieldislt}]% -%\cs{DTLbibfieldislt}\marg{field label}\marg{value} +% This defines +%\begin{definition} +% \cs{@dtl@lopoff}\meta{first element}\meta{sep}\meta{rest of list}\cs{to}\meta{cmd1}\meta{cmd2} %\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} +%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{definition}[\DescribeMacro{\DTLbibfieldisle}]% -%\cs{DTLbibfieldisle}\marg{field label}\marg{value} +%\begin{macro}{\@dtl@construct@qlopoff} +%\begin{definition} +% \cs{@dtl@construct@qlopoff}\meta{separator char}\meta{delimiter char} %\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} -% -%\begin{definition}[\DescribeMacro{\DTLbibfieldisgt}]% -%\cs{DTLbibfieldisgt}\marg{field label}\marg{value} +% This constructs \cs{@dtl@qlopoff} to be used +% when the entry is surrounded by the current delimiter value. +% \begin{macrocode} +\edef\@dtl@construct@qlopoff#1#2{% + \noexpand\long + \noexpand\def\noexpand\@dtl@qlopoff#1#2##1#2#1##2\noexpand\to##3##4{% + \noexpand\def##4{##1}% +% \end{macrocode} +% Replace any escaped delimiters +%\changes{2.10}{2012-07-18}{Added code to replace escaped delimiters} +% \begin{macrocode} + \noexpand\DTLsubstituteall{##4}{#2#2}{#2}% + \noexpand\edef\noexpand\@dtl@dosubs{% + \noexpand\noexpand\noexpand\DTLsubstituteall{\noexpand\noexpand##4}% + {\noexpand\expandafter\noexpand\noexpand\noexpand\csname#2\noexpand\endcsname#2}% + {\noexpand\expandafter\noexpand\noexpand\noexpand\csname#2\noexpand\endcsname}% + }% + \noexpand\@dtl@dosubs + \noexpand\def##3{#1##2}% + }% +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\@dtl@construct@lop@ff} +%\begin{definition} +% \cs{@dtl@construct@lop@ff}\meta{separator char} %\end{definition} -%This 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} +% 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{definition}[\DescribeMacro{\DTLbibfieldisge}]% -%\cs{DTLbibfieldisge}\marg{field label}\marg{value} +%\begin{macro}{\@dtl@construct@lopoffs} +%\begin{definition} +%\cs{@dtl@construct@lopoffs} %\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} +% 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} % -%Note that \cs{DTLbibliography} uses \cs{DTLforeachbibentry} -%(described in \autoref{sec:foreachbib}) so you may also use -%test the value of the counter \ctr{DTLbibrow} within -%\meta{conditions}. You may also use the boolean commands defined -%by the \sty{ifthen} package, such as \ics{not}. -% -%\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. +%\begin{option}{separator} +% Define separator used in external data files. +% \begin{macrocode} +\define@key{datatool.sty}{separator}{% + \DTLsetseparator{#1}% +} +% \end{macrocode} +%\end{option} % -%\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}. +%\begin{option}{delimiter} +% Define delimiter used in external data files. +% \begin{macrocode} +\define@key{datatool.sty}{delimiter}{% + \DTLsetdelimiter{#1}% +} +% \end{macrocode} +%\end{option} % -%\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. +%\begin{option}{verbose} +% \begin{macrocode} +\define@boolkey{datatool.sty}[dtl]{verbose}[true]{} +% \end{macrocode} +%\end{option} % -%\item creates a \sty{datatool} database called "mybib". +%\begin{option}{math} +% Determine whether to use \sty{fp} or \sty{pgfmath} for the +% arithmetic commands. The default is to use \sty{fp}. +% \begin{macrocode} +\define@choicekey{datatool.sty}{math}[\val\nr]{fp,pgfmath}{% + \renewcommand*\@dtl@mathprocessor{#1}% +} +\newcommand*{\@dtl@mathprocessor}{fp} +% \end{macrocode} +%\end{option} % -%\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. +% Process package options: +% \begin{macrocode} +\ProcessOptionsX +% \end{macrocode} % -%\end{enumerate} -% -%\item In my \BibTeX\ database ("nlct.bib" in this example), I -%have remembered to use the \BibTeX\ month macros: "jan", "feb" -%etc. This means that the months are stored in the database in -%the form \cs{DTLmonthname}\marg{nn}, where \meta{nn} is a two -%digit number from 01 to 12. \cs{DTLsort} ignores command names -%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}[\DescribeMacro{\DTLbibliographystyle}]% -%\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}. -% -%\begin{definition}[\DescribeMacro{\DTLformatauthor}]% -%\cs{DTLformatauthor}\marg{von part}\marg{surname}\marg{jr part}\marg{forenames} -%\end{definition} -%\begin{definition}[\DescribeMacro{\DTLformateditor}]% -%\cs{DTLformateditor}\marg{von part}\marg{surname}\marg{jr part}\marg{forenames} -%\end{definition} -%These commands are used to format an author/editor's name, -%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: -%\begin{definition}[\DescribeMacro{\DTLformatforenames}]% -%\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}. -% -%\begin{definition}[\DescribeMacro{\DTLformatabbrvforenames}]% -%\cs{DTLformatabbrvforenames}\marg{forenames} -%\end{definition} -%This is used by the "abbrv" style to display the author's -%initials (which are determined from \meta{forenames}). -%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}). -% -%\begin{definition}[\DescribeMacro{\DTLformatsurname}]% -%\cs{DTLformatsurname}\marg{surname} -%\end{definition} -%This displays its argument by default\footnote{It also checks -%whether the surname ends with a full stop using -%\cs{DTLcheckendsperiod}}. +% Set the defaults: +% \begin{macrocode} +\@dtl@construct@lopoffs +% \end{macrocode} % -%\begin{definition}[\DescribeMacro{\DTLformatvon}]% -%\cs{DTLformatvon}\marg{von part} -%\end{definition} -%If the \meta{von part} is empty, this command does nothing, -%otherwise it displays its argument followed by a -%non-breakable space. -%\begin{definition}[\DescribeMacro{\DTLformatjr}]% -%\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}. +% Load base package: +% \begin{macrocode} +\RequirePackage{datatool-base} +% \end{macrocode} % -%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{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} % -%\begin{definition}[\DescribeCounter{DTLmaxauthors}] -%\ctrfmt{DTLmaxauthors} -%\end{definition} -%The counter \ctrfmt{DTLmaxauthors} is used to determine the -%maximum number of authors to display for a given entry. If the -%entry's author list contains more than that number of authors, -%\cs{etalname} is used, the definition of which is given in -%\autoref{sec:src:bibnames}. The default value of -%\ctrfmt{DTLmaxauthors} is \theDTLmaxauthors. -% -%\begin{definition}[\DescribeCounter{DTLmaxeditors}] -%\ctrfmt{DTLmaxeditors} -%\end{definition} -%The \ctrfmt{DTLmaxeditors} counter is analogous to the -%\ctrfmt{DTLmaxauthors} counter. It is used to determine the -%maximum number of editor names to display. The default value -%of \ctrfmt{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}.) +% \section{Defining New Databases} +% As from v2.0, the internal structure of the database has changed +% to make it more efficient.\footnote{Thanks to Morten H\o gholm +% for the suggestion.} The database is now stored in a token +% register instead of a macro. Each row is represented as:\par +%\verb|\db@row@elt@w|% +%\verb|\db@row@id@w| \meta{row idx}\verb|\db@row@id@end@|% +%\meta{column data}% +%\verb|\db@row@id@w| \meta{row idx}\verb|\db@row@id@end@|% +%\verb|\db@row@elt@end@|\par +% where \meta{row idx} is the row index and \meta{column data} is +% the data for each column in the row. Each column for a given +% row is stored as:\par +%\verb|\db@col@id@w| \meta{column idx}\verb|\db@col@id@end@|% +%\verb|\db@col@elt@w| \meta{value}\verb|\db@col@elt@end@|% +%\verb|\db@col@id@w| \meta{column idx}\verb|\db@col@id@end@|\par +% where \meta{column idx} is the column index and \meta{value} +% is the entry for the given column and row. % -%\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} +% Each row only has an associated index, but columns have +% a unique identifying key as well as an associated index. Columns +% also have an associated data type which may be: 0 (column +% contains strings), 1 (column contains integers), 2 (column +% contains real numbers), 3 (column contains currency) or +% \meta{empty} (column contains no data). Since the key sometimes +% has to be expanded, a header is also available in the event +% that the user wants to use \cs{DTLdisplaydb} or +% \cs{DTLdisplaylongdb} and requires a column header that would +% cause problems if used as a key. The general column +% information is stored in a token register where each column +% has information stored in the form:\par +%\verb|\db@plist@elt@w|% +%\verb|\db@col@id@w| \meta{index}\verb|\db@col@id@end@|% +%\verb|\db@key@id@w| \meta{key}\verb|\db@key@id@end@|% +%\verb|\db@type@id@w| \meta{type}\verb|\db@type@id@end@|% +%\verb|\db@header@id@w| \meta{type}\verb|\db@header@id@end@|% +%\verb|\db@col@id@w| \meta{index}\verb|\db@col@id@end@|% +%\verb|\db@plist@elt@end@| % -%\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: -%\begin{definition}[\DescribeMacro{\DTLforeachbib}]% -%\cs{DTLforeachbib}\oarg{condition}\marg{db name}\marg{text} -%\end{definition} -%\begin{definition}[\DescribeMacro{\DTLforeachbib*}]% -%\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: -%\begin{definition}[\DescribeMacro{\DTLbibfield}]% -%\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 -%\begin{definition}[\DescribeMacro{\DTLifbibfieldexists}]% -%\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}. +% The column name (\meta{key}) is mapped to the column index +% using \cs{dtl@ci@}\meta{db}"@"\meta{key} where \meta{db} is +% the database name. % -%\begin{definition}[\DescribeMacro{\DTLifbibanyfieldexists}]% -%\cs{DTLifanybibfieldexists}\marg{field label list}\marg{true -%part}\marg{false part} +%\begin{macro}{\DTLnewdb} +%\begin{definition} +% \cs{DTLnewdb}\marg{db name} %\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}. +%\changes{2.0}{2009 February 27}{Changed way database is stored} +% Initialises a database called \meta{name}. +% \begin{macrocode} +\newcommand*{\DTLnewdb}[1]{% +% \end{macrocode} +% Check if there is already a database with this name. +% \begin{macrocode} + \DTLifdbexists{#1}% + {% + \PackageError{datatool}{Database `#1' already exists}{}% + }% + {% +% \end{macrocode} +% Define new database. Add information message if in verbose +% mode. +% \begin{macrocode} + \dtl@message{Creating database `#1'}% +% \end{macrocode} +% Define token register used to store the contents of the database. +% \begin{macrocode} + \expandafter\newtoks\csname dtldb@#1\endcsname +% \end{macrocode} +% Define token register used to store the column header information. +% \begin{macrocode} + \expandafter\newtoks\csname dtlkeys@#1\endcsname{}% +% \end{macrocode} +% Define count register used to store the row count. +% \begin{macrocode} + \expandafter\newcount\csname dtlrows@#1\endcsname +% \end{macrocode} +% Define count register used to store the column count. +% \begin{macrocode} + \expandafter\newcount\csname dtlcols@#1\endcsname + }% +} +% \end{macrocode} +%\end{macro} % -%\begin{definition}[\DescribeMacro{\DTLformatbibentry}]% -%\cs{DTLformatbibentry} +%\begin{macro}{\DTLcleardb} +%\begin{definition} +% \cs{DTLcleardb}\marg{db name} %\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. +% Clears the database. (Makes it empty, but still defined.) +%\changes{2.03}{2009 November 15}{new} +% \begin{macrocode} +\newcommand*{\DTLcleardb}[1]{% + \DTLifdbexists{#1}% + {% + \dtlforeachkey(\@dtl@key,\@dtl@col,\@dtl@type,\@dtl@head)\in{#1}\do + {% + \expandafter\let\csname dtl@ci@#1@\@dtl@key\endcsname\undefined + }% + \csname dtldb@#1\endcsname{}% + \csname dtlkeys@#1\endcsname{}% + \csname dtlrows@#1\endcsname=0\relax + \csname dtlcols@#1\endcsname=0\relax + }% + {% + \PackageError{Can't clear database `#1': + database doesn't exist}{}{}% + }% +} +% \end{macrocode} +%\end{macro} % -%\begin{definition}[\DescribeMacro{\DTLcomputewidestbibentry}]% -%\cs{DTLcomputewidestbibentry}\marg{conditions}\marg{db -%name}\marg{bib label}\marg{cmd} +%\begin{macro}{\DTLdeletedb} +%\begin{definition} +% \cs{DTLdeletedb}\marg{db name} %\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 \desctr{DTLbibrow} keeps track of the current -%bibliography entry. This is reset at the start of each -%\cs{DTLforeachbib} and is incremented if \meta{conditions} -%is met. -% -%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} -% -%\subsection{Multiple Bibliographies} -%\label{sec:multibib} -% -%It is possible to have more than one bibliography in a document, -%but it then becomes necessary to have a separate auxiliary file -%for each bibliography, and each auxiliary file must then be -%passed to \BibTeX. In order to do this, you need to use -%\begin{definition}[\DescribeMacro{\DTLmultibibs}]% -%\cs{DTLmultibibs}\marg{name list} -%\end{definition} -%where \meta{name list} is a comma separated list of names, -%\meta{name}. For each \meta{name}, this command creates an -%auxiliary file called \meta{name}".aux" (note that this -%command may only be used in the preamble). -% -%When you want to cite an entry for a given bibliography named -%in \cs{DTLmultibibs}, you must use: -%\begin{definition}[\DescribeMacro{\DTLcite}]% -%\cs{DTLcite}\oarg{text}\marg{mbib}\marg{cite key list} -%\end{definition}\noindent -%This is analogous to \cs{cite}\oarg{text}\marg{cite key list}, -%but writes the \cs{citation} command to \meta{mbib}".aux" instead -%of to the document's main auxiliary file. It also ensures that -%the cross-referencing labels are based on \meta{mbib}, to allow -%you to have the same reference in more than one bibliography -%without incurring a ``multiply defined'' warning message. Note -%that you can still use \cs{cite} to add citation information to -%the main auxiliary file. -% -%If you want to add an entry to the bibliography without producing -%any text, you can use -%\begin{definition}[\DescribeMacro{\DTLnocite}] -%\cs{DTLnocite}\marg{mbib}\marg{cite key list} -%\end{definition}\noindent -%which is analogous to \cs{nocite}\marg{cite key list}, where -%again the citation information is written to \meta{mbib}".aux" -%instead of the document's main auxiliary file. -% -%Note that for both \cs{DTLcite} and \cs{DTLnocite} the -%\meta{mbib} part must be one of the names listed in -%\cs{DTLmultibibs}. -% -%\begin{definition}[\DescribeMacro{\DTLloadmbbl}]% -%\cs{DTLloadmbbl}\marg{mbib}\marg{db name}\marg{bib list} -%\end{definition} -%This is analogous to \cs{DTLloadbbl}\marg{db name}\marg{bib list} -%described in \autoref{sec:loadbbl}. (Again \meta{mbib} must be -%one of the names listed in \cs{DTLmultibibs}.) This creates -%a new \sty{datatool} database called \meta{db name} and loads the -%bibliography information from \meta{mbib}".bbl" (if it exists). -% -%\begin{definition}[\DescribeMacro{\DTLmbibliography}]% -%\cs{DTLmbibliography}\oarg{condition}\marg{mbib}\marg{db name} -%\end{definition} -%This is analogous to \cs{DTLbibliography}\oarg{condition}\marg{db name}, -%but is required when displaying a bibliography in which elements have -%been cited using \cs{DTLcite} and \cs{DTLnocite}. -% -%\begin{example}{Multiple Bibliographies}{ex:multibib} -%Suppose I need to create a document which contains a section listing -%all my publications, but I also need to have separate sections -%covering each of my research topics, with a mini-bibliography -%at the end of each section. As in the earlier examples, all my -%publications are stored in the file "nlct.bib" which is somewhere -%on \TeX's path. Note that there will be some duplication as the -%references in the mini-bibliographies will also appear in the -%main bibliography at the end of the document, but using -%\cs{DTLcite} and \cs{DTLmbibliography} ensures that all the -%cross-referencing labels (and hyperlinks if they are enabled) -%are unique. -%\begin{verbatim} -%\documentclass{article} -%\usepackage{databib} -%\DTLmultibibs{kernel,food} -%\begin{document} -%\section{Kernel methods} -%In this section I'm going to describe some research work into -%kernel methods, and in the process I'm going to cite some related -%papers \DTLcite{kernel}{Cawley2007a,Cawley2006a}. -% -%\DTLloadmbbl{kernel}{kernelDB}{nlct} -%\DTLmbibliography{kernel}{kernelDB} -% -%\section{Food research} -% -%In this section I'm going to describe some research work -%in the area of food safety, and in the process, I'm going -%to cite some related papers \DTLcite{food}{Peck1999,Barker1999a} -% -%\DTLloadmbbl{food}{foodDB}{nlct} -%\DTLmbibliography{food}{foodDB} -% -%\cite{*} -%\renewcommand{\refname}{Complete List of Publications} -%\DTLloadbbl{fullDB}{nlct} -%\DTLbibliography{fullDB} -%\end{document} -%\end{verbatim} -%Notes: -%\begin{enumerate} -%\item This will create the files "kernel.aux" and "food.aux". -%These will have to be passed to \BibTeX, in addition to the -%documents main auxiliary file. So, if my document is called -%"researchwork.tex", then I need to do: -%\begin{verbatim} -%latex researchwork -%bibtex researchwork -%bibtex kernel -%bibtex food -%latex researchwork -%latex researchwork -%\end{verbatim} -% -%\item "\cite{*}" is used to add all the entries in the bib file -%to the main bibliography database. As before, \cs{DTLloadbbl} -%and \cs{DTLbibliography} are used to load and display the main -%bibliography. -%\end{enumerate} -%\end{example} -% -%\importantpar Don't try to directly input the ".bbl" file using -%\cs{input} (or \cs{include}) instead of using \cs{DTLloadbbl} -%or \cs{DTLloadmbbl} as these commands store the name of the required -%database and initialise the database before loading the -%\texttt{.bbl} file. Similarly, don't just copy the contents of -%the ".bbl" file into your document without first defining the -%database using \ics{DTLnewdb} and setting \ics{DTLBIBdbname} to -%the name of the database. -% -%\section{Referencing People (\sty{person} package)} -%\label{sec:person} -% -%Sometimes when mail-merging, it may be necessary to reference a -%person by their pronoun which can lead to the cumbersome and -%impersonal ``he/she'' construct. The \sty{person} package -%allows you to define a person by their full name, familiar name and -%gender. You can then use the commands described in -%\autoref{sec:refperson} to produce the appropriate pronoun. -% -%This can also be useful for other types of documents, such as an -%order of service for a baptism or funeral. Since the -%document is much the same from one person to the next, documents of -%this nature are frequently simply copied and a search and replace -%edit is used to change the relevant text. However this can lead to -%errors (especially if the previous person's name was Mary!) With -%the \sty{person} package, you need only change the definition of -%the person by modifying the arguments of \cs{newperson}. -% -%\subsection{Defining and Undefining People} -% -%A person is defined (globally) using the command: -%\begin{definition}[\DescribeMacro{\newperson}] -%\cs{newperson}\oarg{label}\marg{full name}\marg{familiar name}\marg{gender} -%\end{definition} -%The optional argument is a unique label identifying this person, -%in the event that there is more than one person. If \meta{label} -%is omitted \texttt{anon} is used. (This is also the case for -%subsequent commands that take an optional label.) -%The gender may be any of those given by -%\begin{definition}[\DescribeMacro{\malelabels}] -%\cs{malelabels} -%\end{definition} -%or -%\begin{definition}[\DescribeMacro{\femalelabels}] -%\cs{femalelabels} -%\end{definition} -%The default definition of \cs{malelabels} is \texttt{\malelabels} -%and the default definition of \cs{femalelabels} is -%\texttt{\femalelabels}. You can add extra identifiers using -%\begin{definition}[\DescribeMacro{\addmalelabel}] -%\cs{addmalelabel}\marg{identifier} -%\end{definition} -%or -%\begin{definition}[\DescribeMacro{\addfemalelabel}] -%\cs{addfemalelabel}\marg{identifier} -%\end{definition} -%For example: -%\begin{verbatim} -%\addmalelabel{boy} -%\addfemalelabel{girl} -%\end{verbatim} +% Deletes a database. +%\changes{2.03}{2009 November 15}{new} +% \begin{macrocode} +\newcommand*{\DTLdeletedb}[1]{% + \DTLifdbexists{#1}% + {% + \dtlforeachkey(\@dtl@key,\@dtl@col,\@dtl@type,\@dtl@head)\in{#1}\do + {% + \expandafter\let\csname dtl@ci@#1@\@dtl@key\endcsname\undefined + }% + \expandafter\let\csname dtldb@#1\endcsname\undefined + \expandafter\let\csname dtlkeys@#1\endcsname\undefined + \expandafter\let\csname dtlrows@#1\endcsname\undefined + \expandafter\let\csname dtlcols@#1\endcsname\undefined + }% + {% + \PackageError{Can't delete database `#1': + database doesn't exist}{}{}% + }% +} +% \end{macrocode} +%\end{macro} % -%The total number of defined people is given by: -%\begin{definition}[\DescribeMacro{\thepeople}] -%\cs{thepeople} +%\begin{macro}{\DTLrowcount} +%\begin{definition} +% \cs{DTLrowcount}\marg{db name} %\end{definition} +% The number of rows in the database called \meta{db name}. +% (Doesn't check if database exists.) +% \begin{macrocode} +\newcommand*{\DTLrowcount}[1]{% + \expandafter\number\csname dtlrows@#1\endcsname +} +% \end{macrocode} +%\end{macro} % -%A person can be undefined using: -%\begin{definition}[\DescribeMacro{\removeperson}] -%\cs{removeperson}\oarg{label} +%\begin{macro}{\DTLcolumncount} +%\begin{definition} +% \cs{DTLcolumncount}\marg{db name} %\end{definition} -%where the person is given by \meta{label}. +% The number of columns in the database called \meta{db name}. +% (Doesn't check if database exists.) +%\changes{2.0}{2009 February 27}{new}% +% \begin{macrocode} +\newcommand*{\DTLcolumncount}[1]{% + \expandafter\number\csname dtlcols@#1\endcsname +} +% \end{macrocode} +%\end{macro} % -%If more than one person has been defined, they can all be -%removed using: -%\begin{definition}[\DescribeMacro{\removeallpeople}] -%\cs{removeallpeople} +%\begin{macro}{\DTLifdbempty} +%\begin{definition} +% \cs{DTLifdbempty}\marg{name}\marg{true part}\marg{false part} %\end{definition} -%or you can remove a subset using: -%\begin{definition}[\DescribeMacro{\removepeople}] -%\cs{removepeople}\marg{list} +% Check if named database is empty (i.e.\ no rows have been added). +% \begin{macrocode} +\newcommand{\DTLifdbempty}[3]{% + \DTLifdbexists{#1}% + {\@DTLifdbempty{#1}{#2}{#3}}% + {\PackageError{Can't check if database `#1' is empty: + database doesn't exist}{}{}}% +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\@DTLifdbempty} +%\begin{definition} +% \cs{@sDTLifdbempty}\marg{name}\marg{true part}\marg{false part} %\end{definition} -%where \meta{list} is a comma-separated list of labels. +% Check if named existing database is empty. (No check performed +% to determine if the database exists.) +%\changes{2.0}{2009 February 27}{new} +% \begin{macrocode} +\newcommand{\@DTLifdbempty}[3]{% + \expandafter\ifnum\csname dtlrows@#1\endcsname=0\relax + #2% + \else + #3% + \fi +} +% \end{macrocode} +%\end{macro} % -%\subsection{Displaying Information} -%\label{sec:refperson} -% -%Once a person has been defined, you can display their name using: -%\begin{definition}[\DescribeMacro{\personfullname}] -%\cs{personfullname}\oarg{label} -%\end{definition} -%where \meta{label} is the unique label used in the optional -%argument to \cs{newperson}. The person's familiar name is displayed -%using: -%\begin{definition}[\DescribeMacro{\personname}] -%\cs{personname}\oarg{label} -%\end{definition} -%The person's pronoun (``he'' or ``she'') is displayed using: -%\begin{definition}[\DescribeMacro{\personpronoun}] -%\cs{personpronoun}\oarg{label} -%\end{definition} -%The objective pronoun (``him'' or ``her'') is displayed using: -%\begin{definition}[\DescribeMacro{\personobjpronoun}] -%\cs{personobjpronoun}\oarg{label} -%\end{definition} -%The possessive adjective (``his'' or ``her'') is displayed using: -%\begin{definition}[\DescribeMacro{\personpossadj}] -%\cs{personpossadj}\oarg{label} -%\end{definition} -%The possessive pronoun ``his'' or ``hers'' is displayed using: -%\begin{definition}[\DescribeMacro{\personposspronoun}] -%\cs{personposspronoun}\oarg{label} -%\end{definition} -%The person's relationship to their parent (``son'' or ``daughter'') -%is displayed using: -%\begin{definition}[\DescribeMacro{\personchild}] -%\cs{personchild}\oarg{label} -%\end{definition} -%The person's relationship to their child (``mother'' or ``father'') -%is displayed using: -%\begin{definition}[\DescribeMacro{\personparent}] -%\cs{personparent}\oarg{label} -%\end{definition} -%The person's relationship to their sibling (``brother'' or -%``sister'') is displayed using: -%\begin{definition}[\DescribeMacro{\personsibling}] -%\cs{personsibling}\oarg{label} -%\end{definition} -% -%If the word occurs at the start of a sentence, you will need one -%of the following commands, which are as the above, except the -%first letter is converted to upper case: -%\begin{definition}[\DescribeMacro{\Personpronoun}] -%\cs{Personpronoun}\oarg{label} -%\end{definition} -%\begin{definition}[\DescribeMacro{\Personobjpronoun}] -%\cs{Personobjpronoun}\oarg{label} -%\end{definition} -%\begin{definition}[\DescribeMacro{\Personpossadj}] -%\cs{Personpossadj}\oarg{label} -%\end{definition} -%\begin{definition}[\DescribeMacro{\Personposspronoun}] -%\cs{Personposspronoun}\oarg{label} -%\end{definition} -%\begin{definition}[\DescribeMacro{\Personchild}] -%\cs{Personchild}\oarg{label} -%\end{definition} -%\begin{definition}[\DescribeMacro{\Personparent}] -%\cs{Personparent}\oarg{label} -%\end{definition} -%\begin{definition}[\DescribeMacro{\Personsibling}] -%\cs{Personsibling}\oarg{label} -%\end{definition} -% -%\begin{example}{Order of Service (Memorial)}{ex:memorial} -%This example is for a memorial order of service. -% -%\begin{verbatim} -%\documentclass{article} -% -%\usepackage{person} -% -%\newperson{Jane Doe}{Jane}{female} -% -%\begin{document} -%\begin{center} -%\Large -%In Memory of \personfullname -%\end{center} -% -%We are gathered here to remember our \personsibling\ \personname. -%\Personpronoun\ will be much missed, and \personpossadj\ -%family are in our prayers. -%\end{document} -%\end{verbatim} -% -%\newperson{Jane Doe}{Jane}{female} -%\begin{center} -%\Large -%In Memory of \personfullname -%\end{center} -% -%We are gathered here to remember our \personsibling\ \personname. -%\Personpronoun\ will be much missed, and \personpossadj\ -%family are in our prayers. -%\removeperson -% -%\end{example} -% -%If there is more than one person, you will need to use the -%optional argument \meta{label} to \cs{newperson} to uniquely -%identify each person. You can then list all of the people's full -%or familiar names using: -%\begin{definition}[\DescribeMacro{\peoplefullname}] -%\cs{peoplefullname} -%\end{definition} -%\begin{definition}[\DescribeMacro{\peoplename}] -%\cs{peoplename} -%\end{definition} -%Note that if there is only one person defined, these commands behave -%the same as \cs{personfullname}\oarg{label} and -%\cs{personname}[\meta{label}]. -% -%Similarly for the pronouns: -%\begin{definition}[\DescribeMacro{\peoplepronoun}] -%\cs{peoplepronoun} -%\end{definition} -%\begin{definition}[\DescribeMacro{\Peoplepronoun}] -%\cs{Peoplepronoun} -%\end{definition} -%\begin{definition}[\DescribeMacro{\peopleobjpronoun}] -%\cs{peopleobjpronoun} -%\end{definition} -%\begin{definition}[\DescribeMacro{\Peopleobjpronoun}] -%\cs{Peopleobjpronoun} -%\end{definition} -%\begin{definition}[\DescribeMacro{\peoplepossadj}] -%\cs{peoplepossadj} -%\end{definition} -%\begin{definition}[\DescribeMacro{\Peoplepossadj}] -%\cs{Peoplepossadj} -%\end{definition} -%\begin{definition}[\DescribeMacro{\peopleposspronoun}] -%\cs{peopleposspronoun} -%\end{definition} -%\begin{definition}[\DescribeMacro{\Peopleposspronoun}] -%\cs{Peopleposspronoun} -%\end{definition} -%where, again, if only one person has been defined, each of these -%commands is equivalent to -%\cs{person}\ldots\oarg{label} or -%\cs{Person}\ldots\oarg{label}. If more than -%one person has been defined, these commands will display -%they/them/their/theirs or They/Them/Their/Theirs, as appropriate. -% -%Likewise for relationship commands: -%\begin{definition}[\DescribeMacro{\peoplechild}] -%\cs{peoplechild} -%\end{definition} -%\begin{definition}[\DescribeMacro{\Peoplechild}] -%\cs{Peoplechild} -%\end{definition} -%\begin{definition}[\DescribeMacro{\peopleparent}] -%\cs{peopleparent} -%\end{definition} -%\begin{definition}[\DescribeMacro{\Peopleparent}] -%\cs{Peopleparent} -%\end{definition} -%\begin{definition}[\DescribeMacro{\peoplesibling}] -%\cs{peoplesibling} -%\end{definition} -%\begin{definition}[\DescribeMacro{\Peoplesibling}] -%\cs{Peoplesibling} -%\end{definition} -% -%\begin{example}{Order of Service (Baptism)}{ex:baptism} -%In this example two people are defined. -%\begin{verbatim} -%\documentclass{article} -% -%\usepackage{person} -% -%\newperson[john]{John Joseph}{John}{male} -%\newperson[jane]{Jane Mary}{Jane}{female} -% -%\begin{document} -%\begin{center} -%\Large -%Baptism of \peoplefullname. -%\end{center} -% -%Today we welcome \peoplename\ into God's family, may He guide -%and protect \peopleobjpronoun. -%\end{document} -%\end{verbatim} -% -%This is produces the following text: -% -%\newperson[john]{John Joseph}{John}{male} -%\newperson[jane]{Jane Mary}{Jane}{female} -% -%\begin{center} -%\Large -%Baptism of \peoplefullname. -%\end{center} -% -%Today we welcome \peoplename\ into God's family, may He guide -%and protect \peopleobjpronoun. -%\removeallpeople -%\end{example} -% -%\begin{example}{Mail Merging Using Appropriate Gender}{ex:personmerge} -%In this example I have a CSV file called \texttt{students.csv} -%containing the following: -%\begin{verbatim} -%FirstName,Surname,Gender,Parent,Address -%John,"Smith, Jr",M,Mr and Mrs Smith,1 The Street\\Newtown -%Jane,Brown,F,Ms Brown,2 The Avenue\\Oldtown -%Andy,Brown,male,Mr Brown and Miss Sepia,3 The Road\\Newtown -%Z\"oe,Adams,f,Mr and Mrs Adams,5 The Street\\Newtown -%Roger,Brady,m,Mrs Brady,6 The Avenue\\Oldtowm -%Clare,Vernon,female,Mr Vernon,7 The Close\\Anytown -%\end{verbatim} -%Suppose I have to write to each student's parents regarding their -%child. I can load the information using \ics{DTLloaddb} (described -%in \autoref{sec:loaddb}). I can then iterate through the database -%and define the student as a person and use the commands defined in -%the \sty{person} package to display the correct gender related text. -%I could give each person a unique label based on the row count -%(\ics{DTLcurrentindex}), but since I don't need to reuse the -%information, I can use the default "anon" label and undefine the -%person when no longer required. -% -%Note that in the CSV file, the gender label isn't consistent. -%For some students the gender is identified by a single letter -%(``m'' or ``f'') and for others the gender is identified by a -%complete word (``male'' or ``female''). There's also no regard -%for case. This doesn't matter to \ics{newperson} as all the -%identifiers used are listed in \ics{malelabels} and -%\ics{femalelabels}. -% -%The following is an example letter sent to all parents: -%\begin{verbatim} -%\documentclass{letter} -%\usepackage{person} -% -%% load student information from file "students.csv" -%\DTLloaddb{students}{students.csv} -%\begin{document} -%% Iterate through the student database: -%\DTLforeach{students}{\FirstName=FirstName,\Surname=Surname,% -%\Gender=Gender,\Parent=Parent,\Address=Address}{% -%% Define "anon": -% \newperson{\FirstName\space\Surname}{\FirstName}{\Gender}% -%% Do the letter: -% \begin{letter}{\Parent\\\Address} -% \opening{Dear \Parent} -% Your \personchild\ \personname\ has been awarded a -% place. We look forward to seeing \personobjpronoun\ -% on \personpossadj\ arrival. -% \closing{Yours Sincerely} -% \end{letter} -%% Undefine "anon": -% \removeperson -%} -%\end{document} -%\end{verbatim} -% -%The body of the first letter appears as follows: -%\newperson{John Smith Jr}{John}{m} -%\par\vskip\baselineskip -% -% Your \personchild\ \personname\ has been awarded a -% place. We look forward to seeing \personobjpronoun\ -% on \personpossadj\ arrival. -% -%\removeperson -%\par\vskip\baselineskip -%Whereas the body of the second letter appears as follows: -%\newperson{Jane Brown}{Jane}{f} -%\par\vskip\baselineskip -% -% Your \personchild\ \personname\ has been awarded a -% place. We look forward to seeing \personobjpronoun\ -% on \personpossadj\ arrival. -% -%\removeperson -%\end{example} -% -%\subsection{Advanced Commands} -% -%This section describes additional commands provided by the -%\sty{person} package. More detail can be found in -%\autoref{sec:code:person}. -% -%\subsubsection{Conditionals} -% -%\begin{definition}[\DescribeMacro{\ifpersonexists}] -%\cs{ifpersonexists}\marg{label}\marg{true part}\marg{false part} -%\end{definition} -%Tests if the person identified by \meta{label} has been defined. -%If true, do \meta{true part} otherwise do \meta{false part}. -% -%\begin{definition}[\DescribeMacro{\ifmale}] -%\cs{ifmale}\marg{label}\marg{true part}\marg{false part} -%\end{definition} -%Test if the person identified by \meta{label} is male. -%If true, do \meta{true part} otherwise do \meta{false part}. -% -%\begin{definition}[\DescribeMacro{\iffemale}] -%\cs{iffemale}\marg{label}\marg{true part}\marg{false part} -%\end{definition} -%Test if the person identified by \meta{label} is female. -%If true, do \meta{true part} otherwise do \meta{false part}. -% -%\begin{definition}[\DescribeMacro{\ifallmale}] -%\cs{ifallmale}\oarg{label list}\marg{true part}\marg{false part} -%\end{definition} -%Tests if all the people listed in \meta{label list} are male. -%If true, do \meta{true part} otherwise do \meta{false part}. -%If \meta{label list} is omitted, applied to all defined people. -%\begin{definition}[\DescribeMacro{\ifallfemale}] -%\cs{ifallfemale}\oarg{label list}\marg{true part}\marg{false part} -%\end{definition} -%Likewise to test if all the people tested are female. -% -%To determine if a string is an allowed male label: -%\begin{definition}[\DescribeMacro{\ifmalelabel}] -%\cs{ifmalelabel}\marg{identifier}\marg{true part}\marg{false part} -%\end{definition} -%where \meta{identifier} is the string to be tested. If true, do -%\meta{true part} otherwise do \meta{false part}. -%For example: -%\begin{verbatim} -%\def\gender{M} -%\ifmalelabel{\gender}{male}{not male} -%\end{verbatim} -%Similarly to for an allowed female label: -%\begin{definition}[\DescribeMacro{\iffemalelabel}] -%\cs{iffemalelabel}\marg{identifier}\marg{true part}\marg{false part} -%\end{definition} -%For example: -%\begin{verbatim} -%\ifmalelabel{\gender}{Male}{% -% \iffemalelabel{\gender}{Female}% -% {Undefined Gender}% -%} -%\end{verbatim} -% -%\subsubsection{Iterating Through Defined People} -% -%You can iterate through all defined people using: -%\begin{definition}[\DescribeMacro{\foreachperson}] -%\cs{foreachperson}(\meta{name cs},\meta{full name cs},\meta{gender cs},\meta{label cs})\cs{do}\marg{body} -%\end{definition} -%At each iteration, \meta{name cs}, \meta{full name cs}, -%\meta{gender cs} and \meta{label cs} are set to the current person's -%name, full name, gender and label, respectively. (These arguments -%must all be command names.) Note that the gender is set to -%the definition of \DescribeMacro{\malename}\cs{malename} or -%\DescribeMacro{\femalename}\cs{femalename}, as appropriate.\footnote{Predefined names provided by the \sty{person} package are described -%in \autoref{sec:code:peoplenames}.} Once these -%commands are set, \meta{body} is applied. -% -%If you only want to iterate through a subset of defined people, -%you can use: +%\begin{macro}{\DTLnewrow} %\begin{definition} -%\cs{foreachperson}(\meta{name cs},\meta{full name cs},\meta{gender cs},\meta{label cs})\cs{in}\marg{list}\cs{do}\marg{body} -%\end{definition} -%where \meta{list} is a comma-separated list of labels. -% -%\subsubsection{Accessing Individual Information} -% -%\begin{definition}[\DescribeMacro{\getpersongender}] -%\cs{getpersongender}\marg{cs}\marg{label} +% \cs{DTLnewrow}\marg{db name} %\end{definition} -%Gets the gender of the person identified by \meta{label} and -%stores in \meta{cs} (which must be a command name). This -%sets \meta{cs} to the definition of \ics{malename} or -%\ics{femalename} as appropriate. +% Add a new row to named database. The starred version doesn't +% check for the existence of the database. +% \begin{macrocode} +\newcommand*{\DTLnewrow}{% + \@ifstar\@sDTLnewrow\@DTLnewrow +} +% \end{macrocode} +%\end{macro} % -%\begin{definition}[\DescribeMacro{\getpersonname}] -%\cs{getpersonname}\marg{cs}\marg{label} +%\begin{macro}{\@DTLnewrow} +%\begin{definition} +% \cs{@DTLnewrow}\marg{db name} %\end{definition} -%Gets the name of the person identified by \meta{label} and -%stores in \meta{cs} (which must be a command name). +% Add a new row to named database. (Checks for the existance +% of the database.) +% \begin{macrocode} +\newcommand*{\@DTLnewrow}[1]{% +\DTLifdbexists{#1}% + {\@sDTLnewrow{#1}}% + {\PackageErrors{datatool}{Can't add new row to database `#1': + database doesn't exist}{}}% +} +% \end{macrocode} +%\end{macro} % -%\begin{definition}[\DescribeMacro{\getpersonfullname}] -%\cs{getpersonfullname}\marg{cs}\marg{label} +%\begin{macro}{\@sDTLnewrow} +%\begin{definition} +% \cs{@DTLnewrow}\marg{db name} %\end{definition} -%Gets the full name of the person identified by \meta{label} and -%stores in \meta{cs} (which must be a command name). -% -% \StopEventually{\clearpage\phantomsection -%\addcontentsline{toc}{section}{\refname} -% \DTLbibliography{docbib} -%\addcontentsline{toc}{section}{Acknowledgements} -%\section*{Acknowledgements} -% -%Many thanks to Morten~H\o gholm for suggesting a much more -%efficient way of storing the information in databases which -%has significantly improved the time it takes to \LaTeX\ documents -%containing large databases. -% -%\phantomsection -%\addcontentsline{toc}{section}{Change History}\PrintChanges -%\clearpage -%\phantomsection -%\addcontentsline{toc}{section}{Index}\PrintIndex -%} -% -% -% -%\section{datatool.sty} -%\iffalse +% Add a new row to named existing database. (No check performed +% to determine if the database exists.) +%\changes{2.0}{2009 February 27}{new} % \begin{macrocode} -%<*datatool.sty> +\newcommand*{\@sDTLnewrow}[1]{% % \end{macrocode} -%\fi -%\label{sec:code:datatool} -%\subsection{Package Declaration} +% Increment row count. % \begin{macrocode} -\NeedsTeXFormat{LaTeX2e} -\ProvidesPackage{datatool}[2009/11/15 v2.03 (NLCT)] + \global\advance\csname dtlrows@#1\endcsname by 1\relax % \end{macrocode} -% Load required packages: +% Append an empty row to the database % \begin{macrocode} -\RequirePackage{xkeyval} -\RequirePackage{ifthen} -\RequirePackage{xfor} -\RequirePackage{fp} -\RequirePackage{substr} + \toks@gput@right@cx{dtldb@#1}{% + \noexpand\db@row@elt@w% + \noexpand\db@row@id@w \number\csname dtlrows@#1\endcsname + \noexpand\db@row@id@end@% + \noexpand\db@row@id@w \number\csname dtlrows@#1\endcsname + \noexpand\db@row@id@end@% + \noexpand\db@row@elt@end@% + }% % \end{macrocode} -%\changes{2.0}{2009 February 27}{added etex as a required package} +% Display message on terminal and log file if in verbose mode. % \begin{macrocode} -\RequirePackage{etex} + \dtl@message{New row added to database `#1'}% +} % \end{macrocode} +%\end{macro} % -%\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{macro}{\dtlcolumnnum} +% Count register to keep track of column index. +%\changes{2.0}{2009 February 27}{new} % \begin{macrocode} -\newcommand*{\@dtl@separator}{,} +\newcount\dtlcolumnnum % \end{macrocode} %\end{macro} -%\begin{macro}{\DTLsetseparator} +%\begin{macro}{\dtlrownum} +% Count register to keep track of row index. +%\changes{2.0}{2009 February 27}{new} +% \begin{macrocode} +\newcount\dtlrownum +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLifhaskey} %\begin{definition} -%\cs{DTLsetseparator}\marg{char} +%\cs{DTLifhaskey}\meta{db name}\meta{key}\meta{true part}\meta{false +% part} %\end{definition} -% The sets \cs{@dtl@separator}, and constructs the relevent macros -% that require this character to be hardcoded into their definition. +% Checks if the named database \meta{db name} has a column with label +% \meta{key}. If column exists, do \meta{true part} otherwise +% do \meta{false part}. The starred version doesn't check if +% the named database exists. +%\changes{2.0}{2009 February 27}{new} % \begin{macrocode} -\newcommand*{\DTLsetseparator}[1]{% -\renewcommand*{\@dtl@separator}{#1}% -\@dtl@construct@lopoffs -} +\newcommand*{\DTLifhaskey}{\@ifstar\@sDTLifhaskey\@DTLifhaskey} % \end{macrocode} %\end{macro} -%\begin{macro}{\DTLsettabseparator} -%\cs{DTLsettabseparator} makes it easier to set a tab separator. +% +%\begin{macro}{\@DTLifhaskey} +% Unstarred version of \cs{DTLifhaskey} % \begin{macrocode} -\begingroup -\catcode`\ 12 -\gdef\DTLsettabseparator{% - \catcode`\ 12 - \DTLsetseparator{ }% +\newcommand{\@DTLifhaskey}[4]{% + \DTLifdbexists{#1}% + {% + \@sDTLifhaskey{#1}{#2}{#3}{#4}% + }% + {% + \PackageError{datatool}{Database `#1' doesn't exist}{}% + }% } -\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{macro}{\@sDTLifhaskey} +% Starred version of \cs{DTLifhaskey} % \begin{macrocode} -\begingroup -\catcode`\"12\relax -\gdef\@dtl@delimiter{"} -\endgroup +\newcommand{\@sDTLifhaskey}[4]{% + \@ifundefined{dtl@ci@#1@#2}% + {% % \end{macrocode} -%\end{macro} -%\begin{macro}{\DTLsetdelimiter} -%\begin{definition} -%\cs{DTLsetdelimiter}\marg{char} -%\end{definition} -% This sets the delimiter. +% Key not defined % \begin{macrocode} -\newcommand*\DTLsetdelimiter[1]{% -\renewcommand*{\@dtl@delimiter}{#1}% -\@dtl@construct@lopoffs} + #4% + }% + {% % \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. +% Key defined % \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 -}} + #3% + }% +} % \end{macrocode} %\end{macro} % -%\begin{macro}{\@dtl@construct@qlopoff} +%\begin{macro}{\DTLgetcolumnindex} %\begin{definition} -% \cs{@dtl@construct@qlopoff}\meta{separator char}\meta{delimiter char} +%\cs{DTLgetcolumnindex}\marg{cs}\marg{db}\marg{key} %\end{definition} -% This constructs \cs{@dtl@qlopoff} to be used -% when the entry is surrounded by the current delimiter value. +% Gets index for column with label \meta{key} from database +% \meta{db} and stores in \meta{cs} which must be a control +% sequence. +% Unstarred version checks if database and key exist, unstarred +% version doesn't perform any checks. +%\changes{2.0}{2009 February 27}{new} % \begin{macrocode} -\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}% -}} +\newcommand*{\DTLgetcolumnindex}{% + \@ifstar\@sdtl@getcolumnindex\@dtl@getcolumnindex +} % \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{macro}{\@dtl@getcolumnindex} +% Unstarred version of \cs{DTLgetcolumnindex} +%\changes{2.0}{2009 February 27}{new} % \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}% -}} +\newcommand*{\@dtl@getcolumnindex}[3]{% % \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. +% Check if database exists. % \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}% -} + \DTLifdbexists{#2}% + {% % \end{macrocode} -%\end{macro} -%\begin{macro}{\@dtl@decimal} -% The current decimal character is stored in \cs{@dtl@decimal}. +% Database exists. Now check if key exists. % \begin{macrocode} -\newcommand*{\@dtl@decimal}{.} + \@sDTLifhaskey{#2}{#3}% + {% % \end{macrocode} -%\end{macro} -%\begin{macro}{\@dtl@numbergroupchar} -% The current number group character is stored in -% \cs{@dtl@numbergroupchar}. +% Key exists so go ahead and get column index. % \begin{macrocode} -\newcommand*{\@dtl@numbergroupchar}{,} + \@sdtl@getcolumnindex{#1}{#2}{#3}% + }% + {% +% \end{macrocode} +% Key doesn't exists in named database. +% \begin{macrocode} + \PackageError{datatool}{Database `#2' doesn't contain + key `#3'}{}% + }% + }% + {% +% \end{macrocode} +% Named database doesn't exist. +% \begin{macrocode} + \PackageError{datatool}{Database `#2' doesn't exist}{}% + }% +} % \end{macrocode} %\end{macro} % -%\begin{macro}{\DTLsetnumberchars} -%\begin{definition} -%\cs{DTLsetnumberchars}\marg{number group char}\marg{decimal char} -%\end{definition} -% This sets the decimal character and number group -% characters. +%\begin{macro}{\@dtl@getcolumnindex} +% Starred version of \cs{DTLgetcolumnindex}. +%\changes{2.0}{2009 February 27}{new} % \begin{macrocode} -\newcommand*{\DTLsetnumberchars}[2]{% -\renewcommand*{\@dtl@numbergroupchar}{#1}% -\renewcommand*{\@dtl@decimal}{#2}% -\@dtl@construct@getnums -\@dtl@construct@stripnumgrpchar{#1}} +\newcommand*{\@sdtl@getcolumnindex}[3]{% + \expandafter\let\expandafter#1\csname dtl@ci@#2@#3\endcsname +} % \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{macro}{\dtlcolumnindex} %\begin{definition} -% \cs{DTLconverttodecimal}\marg{num}\marg{cmd} +% \cs{dtlcolumnindex}\marg{db}\marg{key} %\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. +% Column index corresponding to \meta{key} in database \meta{db}. +% (No check for existance of database or key.) +%\changes{2.0}{2009 February 27}{new} +%\changes{2.03}{2009 November 15}{renamed \cs{dtl@columnindex} to +%\cs{dtlcolumnindex}} % \begin{macrocode} -\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}}% +\newcommand*{\dtlcolumnindex}[2]{% + \csname dtl@ci@#1@#2\endcsname } % \end{macrocode} %\end{macro} -%\begin{macro}{\@dtl@construct@getnums} -% The following calls the above with the relevant -% decimal character: +% +%\begin{macro}{\DTLgetkeyforcolumn} +%\begin{definition} +%\cs{DTLgetkeyforcolumn}\marg{key cs}\marg{db}\marg{column index} +%\end{definition} +% Gets the key associated with the given column index and stores +% in \meta{key cs}. Unstarred version doesn't perform checks. % \begin{macrocode} -\newcommand*{\@dtl@construct@getnums}{% -\expandafter\@dtl@construct@getintfrac\expandafter{\@dtl@decimal}} +\newcommand*{\DTLgetkeyforcolumn}{% + \@ifstar\@sdtlgetkeyforcolumn\@dtlgetkeyforcolumn} % \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{macro}{\@dtlgetkeyforcolumn} % \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}% -} +\newcommand*{\@dtlgetkeyforcolumn}[3]{% + \DTLifdbexists{#2}% + {% % \end{macrocode} -%\end{macro} -%\begin{macro}{\@dtl@get@int@part} +% Check if index is in range. % \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 + \ifnum#3<1\relax + \PackageError{datatool}{Invalid column index \number#3}{% + Column indices start at 1}% \else - \if\@dtl@argi+% - \let\@dtl@get@nextintpart=\@dtl@get@int@part + \expandafter\ifnum\csname dtlcols@#2\endcsname<#3\relax + \PackageError{datatool}{Index \number#3\space out of + range for database `#2'}{Database `#2' only has + \expandafter\number\csname dtlcols@#2\endcsname\space + columns}% \else - \def\@dtl@intpart{#1}% - \ifx.\@dtl@argii - \let\@dtl@get@nextintpart=\@gobble - \else - \let\@dtl@get@nextintpart=\@dtl@get@next@intpart - \fi + \@sdtlgetkeyforcolumn{#1}{#2}{#3}% \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}% + }% + {% + \PackageError{datatool}{Database `#2' doesn't exists}{}% + }% } % \end{macrocode} %\end{macro} % -%\begin{macro}{\@dtl@choptrailingzeroes} +%\begin{macro}{\@sdtlgetkeyforcolumn} %\begin{definition} -% \cs{@dtl@choptrailingzeroes}\marg{cmd} +%\cs{@sdtlgetkeyforcolumn}\marg{key cs}\marg{db}\marg{column index} %\end{definition} -% Chops trailing zeroes from number given by \meta{cmd}. +% Gets the key associated with the given column index and stores +% in \meta{key cs} % \begin{macrocode} -\newcommand*{\@dtl@choptrailingzeroes}[1]{% -\def\@dtl@tmpcpz{}% -\expandafter\@dtl@chop@trailingzeroes#1\@nil% -\let#1=\@dtl@tmpcpz +\newcommand*{\@sdtlgetkeyforcolumn}[3]{% + \edef\@dtl@dogetkeyforcolumn{\noexpand\@dtl@getkeyforcolumn + {\noexpand#1}{#2}{\number#3}}% + \@dtl@dogetkeyforcolumn } % \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{macro}{\@dtl@getkeyforcolumn} +% Column index must be fully expanded before use. +%\changes{2.10}{2012-07-18}{fixed bug} % \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 +\newcommand*{\@dtl@getkeyforcolumn}[3]{% + \def\@dtl@get@keyforcolumn##1% before stuff + \db@plist@elt@w% start of block + \db@col@id@w #3\db@col@id@end@% index + \db@key@id@w ##2\db@key@id@end@% key + \db@type@id@w ##3\db@type@id@end@% data type + \db@header@id@w ##4\db@header@id@end@% header + \db@col@id@w #3\db@col@id@end@% index + \db@plist@elt@end@% end of block + ##5\q@nil{\def#1{##2}}% + \edef\@dtl@tmp{\expandafter\the\csname dtlkeys@#2\endcsname}% + \expandafter\@dtl@get@keyforcolumn\@dtl@tmp + \db@plist@elt@w% start of block + \db@col@id@w #3\db@col@id@end@ %index + \db@key@id@w \@nil\db@key@id@end@% key + \db@type@id@w \db@type@id@end@% data type + \db@header@id@w \db@header@id@end@% header + \db@col@id@w #3\db@col@id@end@% index + \db@plist@elt@end@% end of block + \q@nil } % \end{macrocode} %\end{macro} -% No-op macro to end recursion: -%\begin{macro}{\@dtl@gobbletonil} +% +% Define some commands to indicate the various data types a database +% may contain. +%\begin{macro}{\DTLunsettype} +% Unknown data type. (All entries in the column are blank so the +% type can't be determined.) +%\changes{2.0}{2009 February 27}{new} % \begin{macrocode} -\def\@dtl@gobbletonil#1\@nil{} +\def\DTLunsettype{} % \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{macro}{\DTLstringtype} +% Data type representing strings. +%\changes{2.0}{2009 February 27}{new} % \begin{macrocode} -\newcommand*{\dtl@truncatedecimal}[1]{% -\expandafter\@dtl@truncatedecimal#1.\@nil#1} +\def\DTLstringtype{0} % \end{macrocode} %\end{macro} -%\begin{macro}{\@dtl@truncatedecimal} +%\begin{macro}{\DTLinttype} +% Data type representing integers. +%\changes{2.0}{2009 February 27}{new} % \begin{macrocode} -\def\@dtl@truncatedecimal#1.#2\@nil#3{% -\def#3{#1}} +\def\DTLinttype{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{macro}{\DTLrealtype} +% Data type representing real numbers. +%\changes{2.0}{2009 February 27}{new} % \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 -} +\def\DTLrealtype{2} % \end{macrocode} %\end{macro} -% -%\begin{macro}{\@dtl@construct@stripnumgrpchar} -% The following macro constructs \cs{@@dtl@strip@numgrpchar}. +%\begin{macro}{\DTLcurrencytype} +% Data type representing currency. +%\changes{2.0}{2009 February 27}{new} % \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 -}% -} +\def\DTLcurrencytype{3} % \end{macrocode} %\end{macro} % -%\begin{macro}{\DTLdecimaltolocale} +%\begin{macro}{\DTLgetdatatype} %\begin{definition} -% \cs{DTLdecimaltolocale}\marg{number}\marg{cmd} +%\cs{DTLgetdatatype}\marg{cs}\marg{db}\marg{key} %\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. +% Gets data type associated with column labelled \meta{key} in +% database \meta{db} and stores in \meta{cs}. Type may be: +% \meta{empty} (unset), 0 (string), 1 (int), +% 2 (real), 3 (currency). Unstarred version checks if the database +% and key exist, starred version doesn't. +%\changes{2.0}{2009 February 27}{new} % \begin{macrocode} -\newcommand*{\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 +\newcommand*{\DTLgetdatatype}{% + \@ifstar\@sdtlgetdatatype\@dtlgetdatatype } % \end{macrocode} %\end{macro} -%\begin{macro}{\@dtl@decimaltolocale} -% Convert the integer part (store in \cs{@dtl@intpart}) +% +%\begin{macro}{\@dtlgetdatatype} +% Unstarred version of \cs{DTLgetdatatype}. +%\changes{2.0}{2009 February 27}{new} % \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 -} +\newcommand*{\@dtlgetdatatype}[3]{% % \end{macrocode} -%\end{macro} -%\begin{macro}{\@dtl@decimaltolocaleint} +% Check if database exists. % \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 -} + \DTLifdbexists{#2}% + {% % \end{macrocode} -%\end{macro} -%\begin{macro}{\@dtl@countdigits} -% Counts the number of digits until "#2" is a full stop. -% (increments \cs{@dtl@tmpcount}.) +% Check if key exists in this database. % \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 -} + \@sDTLifhaskey{#2}{#3}% + {% % \end{macrocode} -%\end{macro} -%\begin{macro}{\@dtl@decimal@to@localeint} +% Get data type for this database and key. % \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 + \@sdtlgetdatatype{#1}{#2}{#3}% + }% + {% +% \end{macrocode} +% Key doesn't exist in this database. +% \begin{macrocode} + \PackageError{datatool}{Key `#3' undefined in database `#2'}{}% + }% + }% + {% +% \end{macrocode} +% Database doesn't exist. +% \begin{macrocode} + \PackageError{datatool}{Database `#2' doesn't exist}{}% + }% } % \end{macrocode} %\end{macro} % -%\begin{macro}{\@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}% +%\begin{macro}{\@sdtlgetdatatype} +% Starred version of \cs{DTLgetdatatype}. This ensures that +% the key is fully expanded before begin passed to +% \cs{@dtl@getdatatype}. +%\changes{2.0}{2009 February 27}{new} +% \begin{macrocode} +\newcommand*{\@sdtlgetdatatype}[3]{% + \edef\@dtl@dogetdata{\noexpand\@dtl@getdatatype{\noexpand#1}% + {\expandafter\the\csname dtlkeys@#2\endcsname}% + {\dtlcolumnindex{#2}{#3}}}% + \@dtl@dogetdata } +% \end{macrocode} %\end{macro} % -%\begin{macro}{\DTLdecimaltocurrency} +%\begin{macro}{\@dtl@getdatatype} %\begin{definition} -% \cs{DTLdecimaltocurrency}\marg{number}\marg{cmd} +%\cs{@dtl@getdatatype}\marg{cs}\marg{data specs}\marg{column index} %\end{definition} -% This converts a decimal number into the locale -% dependent currency format. Stores result in \meta{cmd} which must be -% a control sequence. +% Column index must be expanded. +%\changes{2.0}{2009 February 27}{new} % \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 +\newcommand*{\@dtl@getdatatype}[3]{% + \def\@dtl@get@keydata##1% stuff before + \db@plist@elt@w% start of key block + \db@col@id@w #3\db@col@id@end@% column index + \db@key@id@w ##2\db@key@id@end@% key id + \db@type@id@w ##3\db@type@id@end@% data type + \db@header@id@w ##4\db@header@id@end@% header + \db@col@id@w #3\db@col@id@end@% column index + \db@plist@elt@end@% end of key block + ##5% stuff afterwards + \q@nil{\def#1{##3}}% + \@dtl@get@keydata#2\q@nil } % \end{macrocode} %\end{macro} % -% Set the defaults: +%\begin{macro}{\@dtl@getprops} +%\begin{definition} +%\cs{@dtl@getprops}\marg{key cs}\marg{type cs}\marg{header toks}\marg{before toks}\marg{after toks}\marg{data specs}\marg{column index} +%\end{definition} +% Column index must be expanded. +%\changes{2.0}{2009 February 27}{new} % \begin{macrocode} -\@dtl@construct@lopoffs -\@dtl@construct@getnums -\expandafter\@dtl@construct@stripnumgrpchar\expandafter -{\@dtl@numbergroupchar} +\newcommand*{\@dtl@getprops}[7]{% + \def\@dtl@get@keydata##1% stuff before + \db@plist@elt@w% start of key block + \db@col@id@w #7\db@col@id@end@% column index + \db@key@id@w ##2\db@key@id@end@% key id + \db@type@id@w ##3\db@type@id@end@% data type + \db@header@id@w ##4\db@header@id@end@% header + \db@col@id@w #7\db@col@id@end@% column index + \db@plist@elt@end@% end of key block + ##5% stuff afterwards + \q@nil{% + \def#1{##2}% key + \def#2{##3}% data type + #3={##4}% header + #4={##1}% before stuff + #5={##5}% after stuff + }% + \@dtl@get@keydata#6\q@nil +} % \end{macrocode} -% Define key for package option \pkgopt{separator}. +%\end{macro} +% +%\begin{macro}{\@dtl@before} +%\changes{2.0}{2009 February 27}{new} % \begin{macrocode} -\define@key{datatool.sty}{separator}{% -\DTLsetseparator{#1}} +\newtoks\@dtl@before % \end{macrocode} -% Define key for package option \pkgopt{delimiter}. +%\end{macro} +%\begin{macro}{\@dtl@after} +%\changes{2.0}{2009 February 27}{new} % \begin{macrocode} -\define@key{datatool.sty}{delimiter}{% -\DTLsetdelimiter{#1}} +\newtoks\@dtl@after % \end{macrocode} -% Define key for package option \pkgopt{verbose}. (This also -% switches the \sty{fp} messages on/off) +%\end{macro} +%\begin{macro}{\@dtl@colhead} +%\changes{2.0}{2009 February 27}{new} % \begin{macrocode} -\define@boolkey{datatool.sty}[dtl]{verbose}[true]{% -\ifdtlverbose \FPmessagestrue\else \FPmessagesfalse\fi} +\newtoks\@dtl@colhead % \end{macrocode} -%\begin{macro}{\dtl@message} +%\end{macro} +% +%\begin{macro}{\@dtl@updatekeys} %\begin{definition} -%\cs{dtl@message}\marg{message string} +%\cs{@dtl@updatekeys}\marg{db}\marg{key}\marg{value} %\end{definition} -% Displays message only if the verbose option is set. +% Adds key to database's key list if it doesn't exist. +% The value is used to update the data type associated with that key. +% Key must be fully expanded. Doesn't check if database exists. +%\changes{2.0}{2009 February 27}{new} % \begin{macrocode} -\newcommand*{\dtl@message}[1]{% -\ifdtlverbose\typeout{#1}\fi} +\newcommand*{\@dtl@updatekeys}[3]{% % \end{macrocode} -%\end{macro} -% Process package options: +% Check if key already exists % \begin{macrocode} -\ProcessOptionsX + \@sDTLifhaskey{#1}{#2}% + {% % \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. +% Key exists, may need to update data type. First get the +% column index. % \begin{macrocode} -\DeclareRobustCommand\DTLpar{\@par} + \expandafter\dtlcolumnnum\expandafter + =\dtlcolumnindex{#1}{#2}\relax % \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} +% Get the properties for this column % \begin{macrocode} -\newcount\@dtl@datatype + \edef\@dtl@dogetprops{\noexpand\@dtl@getprops + {\noexpand\@dtl@key}{\noexpand\@dtl@type}% + {\noexpand\@dtl@colhead}{\noexpand\@dtl@before}% + {\noexpand\@dtl@after}{\the\csname dtlkeys@#1\endcsname}% + {\number\dtlcolumnnum}} + \@dtl@dogetprops % \end{macrocode} -%\end{macro} -%\begin{macro}{\@dtl@tmpcount} -% Define temporary count register +% Is the value empty? % \begin{macrocode} -\newcount\@dtl@tmpcount + \ifstrempty{#3}% + {% % \end{macrocode} -%\end{macro} -%\begin{macro}{\dtl@tmplength} -% Define temporary length register: +% Leave data type as it is % \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. +% Make a copy of current data type % \begin{macrocode} -\newcount\@dtl@numgrpsepcount + \let\@dtl@oldtype\@dtl@type % \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. +% Check the data type for this entry (stored in \cs{@dtl@datatype}) % \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 -} + \@dtl@checknumerical{#3}% % \end{macrocode} -%\end{macro} -%\begin{macro}{\@dtl@checknumericalstart} -% Check first character for checknumerical process to see if -% it's a plus or minus sign. +% If this column currently has no data type assigned to it +% then use the new type. % \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 + \ifdefempty{\@dtl@type}% + {% + \edef\@dtl@type{\number\@dtl@datatype}% + }% + {% +% \end{macrocode} +% This column already has an associated data type but it may +% need updating. +% \begin{macrocode} + \ifcase\@dtl@datatype % string +% \end{macrocode} +% String overrides all other types +% \begin{macrocode} + \def\@dtl@type{0}% + \or % int +% \end{macrocode} +% All other types override int, so leave it as it is +% \begin{macrocode} + \or % real +% \end{macrocode} +% Real overrides int, but not currency or string +% \begin{macrocode} + \ifnum\@dtl@type=1\relax + \def\@dtl@type{2}% + \fi + \or % currency +% \end{macrocode} +% Currency overrides int and real but not string +% \begin{macrocode} + \ifnum\@dtl@type>0\relax + \def\@dtl@type{3}% \fi - \@dtl@checknumericalloop#1#2\@nil\@nil\relax \fi + }% +% \end{macrocode} +% Has the data type been updated? +% \begin{macrocode} + \ifx\@dtl@oldtype\@dtl@type +% \end{macrocode} +% No change needed +% \begin{macrocode} + \else +% \end{macrocode} +% Update required +% \begin{macrocode} + \toks@gconcat@middle@cx{dtlkeys@#1}% + {\@dtl@before}% + {% + \noexpand\db@plist@elt@w% start of key block + \noexpand\db@col@id@w \the\dtlcolumnnum + \noexpand\db@col@id@end@% column index + \noexpand\db@key@id@w #2\noexpand\db@key@id@end@% key id + \noexpand\db@type@id@w \@dtl@type + \noexpand\db@type@id@end@% data type + \noexpand\db@header@id@w \the\@dtl@colhead + \noexpand\db@header@id@end@% header + \noexpand\db@col@id@w \the\dtlcolumnnum + \noexpand\db@col@id@end@% column index + \noexpand\db@plist@elt@end@% end of key block + }% + {\@dtl@after}% \fi - \fi - \fi -\fi -} + }% + }% + {% % \end{macrocode} -%\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. +% Key doesn't exist. Increment column count. % \begin{macrocode} -\newif\if@dtl@numgrpsep + \expandafter\global\expandafter\advance + \csname dtlcols@#1\endcsname by 1\relax + \dtlcolumnnum=\csname dtlcols@#1\endcsname\relax % \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} +% Set column index for this key % \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 -} + \expandafter\xdef\csname dtl@ci@#1@#2\endcsname{% + \number\dtlcolumnnum}% % \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} +% Get data type for this entry (stored in \cs{@dtl@datatype}) % \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 -} + \ifstrempty{#2}% + {% + \edef\@dtl@type{}% don't know data type yet + }% + {% + \@dtl@checknumerical{#3}% + \edef\@dtl@type{\number\@dtl@datatype}% + }% % \end{macrocode} -%\end{macro} -%\begin{macro}{\@dtl@checknumericalnoop} -% End loop +% Append to property list % \begin{macrocode} -\def\@dtl@checknumericalnoop#1\@nil#2{} + \toks@gput@right@cx{dtlkeys@#1}% + {% + \noexpand\db@plist@elt@w + \noexpand\db@col@id@w \the\dtlcolumnnum + \noexpand\db@col@id@end@ + \noexpand\db@key@id@w #2\noexpand\db@key@id@end@ + \noexpand\db@type@id@w \@dtl@type + \noexpand\db@type@id@end@ + \noexpand\db@header@id@w #2\noexpand\db@header@id@end@ + \noexpand\db@col@id@w \the\dtlcolumnnum + \noexpand\db@col@id@end@ + \noexpand\db@plist@elt@end@ + }% + }% +} % \end{macrocode} %\end{macro} % -%\begin{macro}{\DTLifnumerical} +%\begin{macro}{\DTLsetheader} %\begin{definition} -%\cs{DTLifnumerical}\marg{arg}\marg{true part}\marg{false part} +%\cs{DTLsetheader}\marg{db}\marg{key}\marg{header} %\end{definition} -% Tests the first argument, if -% its numerical do second argument, otherwise do third argument. +% Sets header for column given by \meta{key} in database \meta{db}. +% Starred version doesn't check for existance of database or key. % \begin{macrocode} -\newcommand{\DTLifnumerical}[3]{% -\@dtl@checknumerical{#1}% -\ifnum\@dtl@datatype=0\relax#3\else#2\fi -} +\newcommand*{\DTLsetheader}{\@ifstar\@sDTLsetheader\@DTLsetheader} % \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{macro}{\@DTLsetheader} +% Unstarred version % \begin{macrocode} -\newcommand{\DTLifreal}[3]{% -\@dtl@checknumerical{#1}% -\ifnum\@dtl@datatype=2\relax #2\else #3\fi -} +\newcommand*{\@DTLsetheader}[3]{% % \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. +% Check if database exists % \begin{macrocode} -\newcommand{\DTLifint}[3]{% -\@dtl@checknumerical{#1}% -\ifnum\@dtl@datatype=1\relax #2\else #3\fi + \DTLifdbexists{#1}% + {% +% \end{macrocode} +% Check if key exists. +% \begin{macrocode} + \@sDTLifhaskey{#1}{#2}% + {% + \@sDTLsetheader{#1}{#2}{#3}% + }% + {% + \PackageError{datatool}{Database `#1' doesn't contain key + `#2'}{}% + }% + }% + {% + \PackageError{datatool}{Database `#1' doesn't exist}{}% + }% } % \end{macrocode} %\end{macro} % -%\begin{macro}{\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{macro}{\@sDTLsetheader} +% Starred version % \begin{macrocode} -\newcommand{\DTLifstring}[3]{% -\@dtl@checknumerical{#1}% -\ifnum\@dtl@datatype=0\relax #2\else #3\fi +\newcommand*{\@sDTLsetheader}[3]{% + \expandafter\dtlcolumnnum\expandafter + =\dtlcolumnindex{#1}{#2}\relax + \@dtl@setheaderforindex{#1}{\dtlcolumnnum}{#3}% } % \end{macrocode} %\end{macro} % -%\begin{macro}{\DTLifcurrency} +%\begin{macro}{\@dtl@setheaderforindex} %\begin{definition} -%\cs{DTLifcurrency}\marg{arg}\marg{true part}\marg{false part} +%\cs{@dtl@setheaderforindex}\marg{db}\marg{column index}\marg{header} %\end{definition} -% Tests the first argument, if -% it starts with the currency symbol do second argument, -% otherwise do third argument. +% Sets the header for column given by \meta{column index} in +% database \meta{db}. The header must be expanded. % \begin{macrocode} -\newcommand{\DTLifcurrency}[3]{% -\@dtl@checknumerical{#1}% -\ifnum\@dtl@datatype=3\relax #2\else #3\fi +\newcommand*{\@dtl@setheaderforindex}[3]{% +% \end{macrocode} +% Get the properties for this column +% \begin{macrocode} + \edef\@dtl@dogetprops{\noexpand\@dtl@getprops + {\noexpand\@dtl@key}{\noexpand\@dtl@type}% + {\noexpand\@dtl@colhead}{\noexpand\@dtl@before}% + {\noexpand\@dtl@after}{\the\csname dtlkeys@#1\endcsname}% + {\number#2}} + \@dtl@dogetprops +% \end{macrocode} +% Store the header in \cs{@dtl@toks} +% \begin{macrocode} + \@dtl@colhead={#3}% +% \end{macrocode} +% Reconstruct property list +% \begin{macrocode} + \edef\@dtl@colnum{\number#2}\relax + \toks@gconcat@middle@cx{dtlkeys@#1}% + {\@dtl@before}% + {% + \noexpand\db@plist@elt@w% start of block + \noexpand\db@col@id@w \@dtl@colnum + \noexpand\db@col@id@end@% index + \noexpand\db@key@id@w \@dtl@key\noexpand\db@key@id@end@% key + \noexpand\db@type@id@w \@dtl@type + \noexpand\db@type@id@end@% data type + \noexpand\db@header@id@w \the\@dtl@colhead + \noexpand\db@header@id@end@% header + \noexpand\db@col@id@w \@dtl@colnum + \noexpand\db@col@id@end@% index + \noexpand\db@plist@elt@end@% end of block + }% + {\@dtl@after}% } % \end{macrocode} %\end{macro} % -%\begin{macro}{\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{macro}{\dtlexpandnewvalue} +% Expand new value before adding to database % \begin{macrocode} -\newcommand*{\DTLifcurrencyunit}[4]{% -\@dtl@checknumerical{#1}% -\ifnum\@dtl@datatype=3\relax - \ifthenelse{\equal{\@dtl@org@currency}{#2}}{#3}{#4}% -\else - #4% -\fi +\newcommand*{\dtlexpandnewvalue}{% + \def\@dtl@setnewvalue##1{\protected@edef\@dtl@tmp{##1}% + \expandafter\@dtl@toks\expandafter{\@dtl@tmp}}% } % \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{macro}{\dtlnoexpandnewvalue} +% Don't expand new value before adding to database % \begin{macrocode} -\newcommand{\DTLifcasedatatype}[5]{% -\@dtl@checknumerical{#1}% -\ifcase\@dtl@datatype - #2% string -\or - #3% integer -\or - #4% number -\or - #5% currency -\fi +\newcommand*{\dtlnoexpandnewvalue}{% + \def\@dtl@setnewvalue##1{\@dtl@toks{##1}}% } % \end{macrocode} +% Do this by default: +% \begin{macrocode} +\dtlnoexpandnewvalue +% \end{macrocode} %\end{macro} % -%\begin{macro}{\dtl@testbothnumerical} +%\begin{macro}{\DTLnewdbentry} %\begin{definition} -%\cs{dtl@testbothnumerical}\marg{arg1}\marg{arg2} +% \cs{DTLnewdbentry}\marg{db name}\marg{id}\marg{value}. %\end{definition} -% Tests if both arguments are numerical. This sets -% the conditional \cs{if@dtl@condition}. +% Adds an entry to the last row (adds new row if database is empty) +% and updates general column information if necessary. The +% starred version doesn't check if the database exists. % \begin{macrocode} -\newcommand*{\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 +\newcommand{\DTLnewdbentry}{% + \@ifstar\@sDTLnewdbentry\@DTLnewdbentry } % \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{macro}{\@DTLnewdbentry} +% Unstarred version of \cs{DTLnewdbentry}. % \begin{macrocode} -\newcommand*{\DTLifnumlt}[4]{% - \DTLconverttodecimal{#1}{\@dtl@numi}% - \DTLconverttodecimal{#2}{\@dtl@numii}% - \FPiflt{\@dtl@numi}{\@dtl@numii}% - #3% - \else - #4% - \fi +\newcommand{\@DTLnewdbentry}[3]{% + \DTLifdbexists{#1}% + {\@sDTLnewdbentry{#1}{#2}{#3}}% + {\PackageError{datatool}{Can't add new entry to database `#1': + database doesn't exist}{}}% } % \end{macrocode} %\end{macro} -% -%\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{macro}{\@sDTLnewdbentry} +% Starred version of \cs{DTLnewdbentry} (doesn't check if the database exists). % \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 +\newcommand*{\@sDTLnewdbentry}[3]{% +% \end{macrocode} +% Update key list +% \begin{macrocode} + \@dtl@updatekeys{#1}{#2}{#3}% +% \end{macrocode} +% Get the column index +% \begin{macrocode} + \expandafter\dtlcolumnnum\expandafter + =\dtlcolumnindex{#1}{#2}\relax +% \end{macrocode} +% Get the current row: +% \begin{macrocode} + \edef\dtl@dogetrow{\noexpand\dtlgetrow{#1}% + {\number\csname dtlrows@#1\endcsname}}% + \dtl@dogetrow +% \end{macrocode} +% Check if this row already has an entry for the given column. +% \begin{macrocode} + \edef\dtl@dogetentry{\noexpand\dtlgetentryfromcurrentrow + {\noexpand\dtl@entry}{\number\dtlcolumnnum}% + }% + \dtl@dogetentry + \ifx\dtl@entry\dtlnovalue +% \end{macrocode} +% Store the value of this entry in \cs{@dtl@toks} +%\changes{2.03}{2009 November 15}{value can be expanded before +% adding to database}% +% \begin{macrocode} + \@dtl@setnewvalue{#3}% +% \end{macrocode} +% There are no entries in this row for the given column. +% Add this entry. +% \begin{macrocode} + \toks@gconcat@middle@cx{dtldb@#1}% + {\dtlbeforerow}% + {% +% \end{macrocode} +% Start of this row: +% \begin{macrocode} + \noexpand\db@row@elt@w% +% \end{macrocode} +% Row ID: +% \begin{macrocode} + \noexpand\db@row@id@w \number\csname dtlrows@#1\endcsname + \noexpand\db@row@id@end@% +% \end{macrocode} +% Current row so far +% \begin{macrocode} + \the\dtlcurrentrow +% \end{macrocode} +% New column: +% Column ID +% \begin{macrocode} + \noexpand\db@col@id@w \number\dtlcolumnnum + \noexpand\db@col@id@end@% +% \end{macrocode} +% Value: +% \begin{macrocode} + \noexpand\db@col@elt@w \the\@dtl@toks + \noexpand\db@col@elt@end@% +% \end{macrocode} +% Column ID: +% \begin{macrocode} + \noexpand\db@col@id@w \number\dtlcolumnnum + \noexpand\db@col@id@end@% +% \end{macrocode} +% Row ID: +% \begin{macrocode} + \noexpand\db@row@id@w \number\csname dtlrows@#1\endcsname + \noexpand\db@row@id@end@% +% \end{macrocode} +% End of this row +% \begin{macrocode} + \noexpand\db@row@elt@end@% }% - \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}. +% Rest (this should be empty) % \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 -} + {\dtlafterrow}% % \end{macrocode} -%\end{macro} -% Count registers to store character codes: +% Print information message if in verbose mode. % \begin{macrocode} -\newcount\dtl@codeA -\newcount\dtl@codeB + \dtl@message{Added #2\space -> #3\space to database `#1'}% + \else % \end{macrocode} -%\begin{macro}{\dtl@setcharcode} +% There's already an entry for the given column in this row +% \begin{macrocode} + \PackageError{datatool}{Can't add entry with ID `#2' to + current row of database `#1'}{There is already an entry with + this ID in the current row}% + \fi +} +% \end{macrocode} +%\end{macro} +% +%\changes{2.0}{2009 February 27}{removed \cs{@dtl@setidtype}} +%\changes{2.0}{2009 February 27}{removed \cs{@dtl@setkeys}} +%\changes{2.0}{2009 February 27}{removed \cs{@dtl@getidtype}} +% +%\begin{macro}{\DTLifdbexists} %\begin{definition} -%\cs{dtl@setcharcode}\marg{c}\marg{count register} +%\cs{DTLifdbexists}\marg{db name}\marg{true part}\marg{false part} %\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. +% Checks if a data base with the given name exists. % \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 -} +\newcommand{\DTLifdbexists}[3]{% + \@ifundefined{dtldb@#1}{#3}{#2}} % \end{macrocode} %\end{macro} % -%\begin{macro}{\dtl@setlccharcode} +%\changes{2.0}{2009 February 27}{removed \cs{@dtl@ifrowcontains}} +%\changes{2.0}{2009 February 27}{removed \cs{dtl@getentryvalue}} +%\changes{2.0}{2009 February 27}{removed \cs{dtl@getentryid}} +% +%\section{Accessing Data} +% +%\begin{macro}{\DTLassign} %\begin{definition} -%\cs{dtl@setlccharcode}\marg{c}\marg{count register} +%\cs{DTLassign}\marg{db}\marg{row idx}\marg{assign list} %\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}. +% Assigns values given in \meta{assign list} for row \meta{row idx} in database +% \meta{db}. (Where \meta{assign list} is in the same form as in +% \cs{DTLforeach}) +%\changes{2.10}{2012-07-18}{new} % \begin{macrocode} -\newcommand*{\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 +\newcommand*{\DTLassign}[3]{% +% \end{macrocode} +% Grouped in the event that \cs{dtlcurrentrow} is already in use. +% (Assignments in \cs{@dtl@assign} are global.) +% \begin{macrocode} + {% + \dtlgetrow{#1}{#2}% + \@dtl@assign{#3}{#1}% + }% } % \end{macrocode} %\end{macro} -%\begin{macro}{\dtlicompare} +% +%\begin{macro}{\@dtl@assign} %\begin{definition} -%\cs{dtlicompare}\marg{count}\marg{string1}\marg{string2} +%\cs{@dtl@assign}\marg{list}\marg{db} %\end{definition} -% As \cs{dtlcompare} but ignores case. -%\changes{1.01}{2007 Aug 17}{new} +% Assigns commands according to the given keys. +% The current row must be stored in \cs{dtlcurrentrow}. +%\changes{2.0}{2009 February 27}{updated to use new database +% structure} % \begin{macrocode} -\newcommand*{\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 +\newcommand*{\@dtl@assign}[2]{% + \@dtl@assigncmd#1,\@nil\@@{#2}% } % \end{macrocode} %\end{macro} % -%\begin{macro}{\DTLifstringlt} +%\begin{macro}{\@dtl@assigncmd} %\begin{definition} -%\cs{DTLifstringlt}\marg{string1}\marg{string2}\marg{true part}\marg{false part} +% \cs{@dtl@assigncmd}\meta{cmd}=\meta{id}\cs{@nil} %\end{definition} -% String comparison (Starred version ignores case) -%\changes{1.01}{2007 Aug 17}{added starred version} +%\changes{2.03}{2009 November 15}{modified to ignore spaces after +% commas} % \begin{macrocode} -\newcommand*{\DTLifstringlt}{\@ifstar\@sDTLifstringlt\@DTLifstringlt} +\def\@dtl@assigncmd#1#2=#3,#4\@@#5{% % \end{macrocode} -% Unstarred version +% get entry for ID given by \#3 and store in \#2 % \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 -} + \@sDTLifhaskey{#5}{#3}% + {% + \edef\@dtl@dogetentry{% + \noexpand\dtlgetentryfromcurrentrow + {\noexpand#1}{\dtlcolumnindex{#5}{#3}}}% + \@dtl@dogetentry % \end{macrocode} -% Starred version +% Set to null if required % \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 -} + \ifx#1\dtlnovalue + \@@dtl@setnull{#1}{#3}% + \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} +% Make it global % \begin{macrocode} -\newcommand*{\DTLiflt}{\@ifstar\@sDTLiflt\@DTLiflt} + \global\let#1=#1\relax + }% + {% + \PackageError{datatool}{Can't assign \string#1\space: there + is no key `#3' in data base `#5'}{}% % \end{macrocode} -% Unstarred version +% Set to null % \begin{macrocode} -\newcommand*{\@DTLiflt}[4]{% -\dtl@testbothnumerical{#1}{#2}% -\if@dtl@condition - \DTLifnumlt{#1}{#2}{#3}{#4}% -\else - \@DTLifstringlt{#1}{#2}{#3}{#4}% -\fi -} + \global\let#1\DTLstringnull + }% % \end{macrocode} -% Starred version +% Recurse? % \begin{macrocode} -\newcommand*{\@sDTLiflt}[4]{% -\dtl@testbothnumerical{#1}{#2}% -\if@dtl@condition - \DTLifnumlt{#1}{#2}{#3}{#4}% -\else - \@sDTLifstringlt{#1}{#2}{#3}{#4}% -\fi + \def\dtl@tmp{#4}% + \ifx\@nnil\dtl@tmp + \let\@dtl@next\@dtl@assigncmdnoop + \else + \let\@dtl@next\@dtl@assigncmd + \fi + \@dtl@next#4\@@{#5}% } % \end{macrocode} %\end{macro} -% -%\begin{macro}{\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{macro}{\@dtl@assigncmdnoop} +% End loop % \begin{macrocode} -\newcommand*{\DTLifnumgt}[4]{% - \DTLconverttodecimal{#1}{\@dtl@numi}% - \DTLconverttodecimal{#2}{\@dtl@numii}% - \FPifgt{\@dtl@numi}{\@dtl@numii}% - #3% - \else - #4% - \fi -} +\def\@dtl@assigncmdnoop#1\@@#2{} % \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{macro}{\@dtl@setnull} +%\cs{@dtl@setnull}\marg{cmd}\marg{id} sets \meta{cmd} to either +% \cs{DTLstringnull} or \cs{DTLnumbernull} depending on the data +% type for \meta{id}. (Database +% name should be stored in \cs{@dtl@dbname} prior to use.) +%\changes{2.0}{2009 February 27}{modified to use new database +% structure} % \begin{macrocode} -\newcommand*{\DTLifstringgt}{\@ifstar\@sDTLifstringgt\@DTLifstringgt} +\newcommand*{\@dtl@setnull}[2]{% % \end{macrocode} -% Unstarred version +% Check if database given by \cs{@dtl@dbname} has the required key. % \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 -} + \@sDTLifhaskey{\@dtl@dbname}{#2}% + {% % \end{macrocode} -% Starred version +% Set to null % \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 + \@@dtl@setnull{#1}{#2}% + }% + {% +% \end{macrocode} +% Key not defined in database \cs{@dtl@dbname}. +% \begin{macrocode} + \global\let#1=\DTLstringnull + }% } % \end{macrocode} %\end{macro} -% -%\begin{macro}{\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{macro}{\@@dtl@setnull} +% As above, but doesn't check if key exists % \begin{macrocode} -\newcommand*{\DTLifgt}{\@ifstar\@sDTLifgt\@DTLifgt} +\newcommand*{\@@dtl@setnull}[2]{% % \end{macrocode} -% Unstarred version +% Get the data type associated with this key and store in +% \cs{@dtl@type}. % \begin{macrocode} -\newcommand*{\@DTLifgt}[4]{% -\dtl@testbothnumerical{#1}{#2}% -\if@dtl@condition - \DTLifnumgt{#1}{#2}{#3}{#4}% -\else - \@DTLifstringgt{#1}{#2}{#3}{#4}% -\fi -} + \@sdtlgetdatatype{\@dtl@type}{\@dtl@dbname}{#2}% % \end{macrocode} -% Starred version +% Check data type. % \begin{macrocode} -\newcommand*{\@sDTLifgt}[4]{% -\dtl@testbothnumerical{#1}{#2}% -\if@dtl@condition - \DTLifnumgt{#1}{#2}{#3}{#4}% -\else - \@sDTLifstringgt{#1}{#2}{#3}{#4}% -\fi -} + \ifnum0\@dtl@type=0\relax % \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} +% Data type is \meta{empty} or 0, so set to string null. % \begin{macrocode} -\newcommand*{\DTLifnumeq}[4]{% - \DTLconverttodecimal{#1}{\@dtl@numi}% - \DTLconverttodecimal{#2}{\@dtl@numii}% - \FPifeq{\@dtl@numi}{\@dtl@numii}% - #3% + \global\let#1=\DTLstringnull \else - #4% +% \end{macrocode} +% Data type is numerical, so set to number null. +% \begin{macrocode} + \global\let#1=\DTLnumbernull \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{macro}{\DTLstringnull} +% String null value: % \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 -} +\newcommand*{\DTLstringnull}{NULL} % \end{macrocode} -% Starred version +%\end{macro} +%\begin{macro}{\DTLnumbernull} +% Number null value: % \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 -} +\newcommand*{\DTLnumbernull}{0} % \end{macrocode} %\end{macro} -% -%\begin{macro}{\DTLifeq} +%\begin{macro}{\DTLifnull} %\begin{definition} -%\cs{DTLifeq}\marg{arg1}\marg{arg2}\marg{true part}\marg{false part} +%\cs{DTLifnull}\marg{value}\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} +% 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*{\DTLifeq}{\@ifstar\@sDTLifeq\@DTLifeq} +\newcommand*{\DTLifnull}[3]{% + \ifx\DTLstringnull#1\relax + #2% + \else + \ifx\DTLnumbernull#1\relax + #2% + \else + #3% + \fi + \fi +} % \end{macrocode} -% Unstarred version +%\end{macro} +% +%\begin{macro}{\@dtlnovalue} % \begin{macrocode} -\newcommand*{\@DTLifeq}[4]{% -\dtl@testbothnumerical{#1}{#2}% -\if@dtl@condition - \DTLifnumeq{#1}{#2}{#3}{#4}% -\else - \@DTLifstringeq{#1}{#2}{#3}{#4}% -\fi -} +\def\@dtlnovalue{Undefined Value} % \end{macrocode} -% Starred version +%\end{macro} +%\begin{macro}{\dtlnovalue} % \begin{macrocode} -\newcommand*{\@sDTLifeq}[4]{% -\dtl@testbothnumerical{#1}{#2}% -\if@dtl@condition - \DTLifnumeq{#1}{#2}{#3}{#4}% -\else - \@sDTLifstringeq{#1}{#2}{#3}{#4}% -\fi -} +\def\dtlnovalue{\@dtlnovalue} % \end{macrocode} %\end{macro} % -%\begin{macro}{\DTLifSubString} +%\begin{macro}{\DTLgetkeydata} %\begin{definition} -%\cs{DTLifSubString}\marg{string}\marg{sub string}\marg{true -%part}\marg{false part} +%\cs{DTLgetkeydata}\marg{key}\marg{db}\marg{col cs}\marg{type cs}\marg{header cs} %\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} +% Gets data for given key in database \meta{db}: the column index is +% stored in \meta{col cs} and data type is stored in \meta{type cs}. +% The unstarred version checks for the existance of the database +% and key, the starred version doesn't. % \begin{macrocode} -\newcommand*{\DTLifSubString}[4]{% -\protected@edef\@dtl@tmp{\noexpand\dtl@testifsubstring -{#1}{#2}}% -\@dtl@tmp -\if@dtl@condition - #3% -\else - #4% -\fi +\newcommand*{\DTLgetkeydata}{% + \@ifstar\@sdtlgetkeydata\@dtlgetkeydata } % \end{macrocode} %\end{macro} -%\begin{macro}{\dtl@testifsubstring} +% +%\begin{macro}{\@dtlgetkeydata} +% Unstarred version of \cs{DTLgetkeydata} % \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 +\newcommand*{\@dtlgetkeydata}[5]{% +% \end{macrocode} +% Check if the database exists. +% \begin{macrocode} + \DTLifdbexists{#2}% + {% +% \end{macrocode} +% Check if the given key exists in the database. +% \begin{macrocode} + \@sDTLifhaskey{#2}{#1}% + {% +% \end{macrocode} +% Get the data. +% \begin{macrocode} + \@sdtlgetkeydata{#1}{#2}{#3}{#4}{#5}% + }% + {% +% \end{macrocode} +% Key not defined in the given database. +% \begin{macrocode} + \PackageError{datatool}{Key `#1' not defined in database + `#2'}{}% + }% + }% + {% +% \end{macrocode} +% Database not defined. +% \begin{macrocode} + \PackageError{datatool}{Database `#2' doesn't exist}{}% + }% } % \end{macrocode} %\end{macro} % -%\begin{macro}{\DTLifStartsWith} +%\begin{macro}{\@sdtlgetkeydata} +%\cs{@sdtlgetkeydata}\marg{key}\marg{db}\marg{col cs}\marg{type cs}\marg{header cs} +% Starred verison of \cs{DTLgetkeydata}. +% \begin{macrocode} +\newcommand*{\@sdtlgetkeydata}[5]{% + \@sdtl@getcolumnindex{#3}{#2}{#1}% + \edef\@dtl@dogetkeydata{\noexpand\@dtl@getprops + {\noexpand\@dtl@key}{\noexpand#4}{\noexpand\@dtl@colhead}% + {\noexpand\@dtl@before}{\noexpand\@dtl@after}% + {\expandafter\the\csname dtlkeys@#2\endcsname}% + {#3}}% + \@dtl@dogetkeydata + \edef#5{\the\@dtl@toks}% +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\dtl@gathervalues} %\begin{definition} -%\cs{DTLifStartsWith}\marg{string}\marg{substring}\marg{true -%part}\marg{false part} +%\cs{dtl@gathervalues}\oarg{label}\marg{db name}\marg{row toks} %\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} +% Stores each element of \meta{row} in \meta{db name} into +% the command \cs{@dtl@}\meta{label}\texttt{@}\meta{key}, +% where \meta{key} is the +% key for that element, and \meta{label} defaults to "key". +%\changes{2.0}{2009 February 27}{updated to use new database structure} % \begin{macrocode} -\newcommand*{\DTLifStartsWith}[4]{% -\@dtl@conditionfalse -\protected@edef\@dtl@tmp{\noexpand\dtl@teststartswith{#1}{#2}}% -\@dtl@tmp -\if@dtl@condition - #3% -\else - #4% -\fi +\newcommand{\dtl@gathervalues}[3][key]{% + \dtlforeachkey(\@dtl@key,\@dtl@col,\@dtl@type,\@dtl@head)\in{#2}\do + {% + \dtlgetentryfromrow{\@dtl@tmp}{\@dtl@col}{\dtlcurrentrow}% + \ifx\@dtl@tmp\dtlnovalue + \@dtl@setnull{\@dtl@tmp}{\@dtl@key}% + \fi + \expandafter\let\csname @dtl@#1@\@dtl@key\endcsname\@dtl@tmp + }% } % \end{macrocode} %\end{macro} % -%\begin{macro}{\dtl@teststartswith} +%\begin{macro}{\dtlcurrentrow} +% Define token register to store current row. +% \begin{macrocode} +\newtoks\dtlcurrentrow +% \end{macrocode} +%\end{macro} +%\begin{macro}{\dtlbeforerow} +% Define token register to store everything before the current row. +% \begin{macrocode} +\newtoks\dtlbeforerow +% \end{macrocode} +%\end{macro} +%\begin{macro}{\dtlafterrow} +% Define token register to store everything after the current row. +% \begin{macrocode} +\newtoks\dtlafterrow +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\dtlgetrow} %\begin{definition} -%\cs{dtl@teststartswith}\marg{string}\marg{prefix} +%\cs{dtlgetrow}\marg{db}\marg{row idx} %\end{definition} -% Tests if \meta{string} starts with \meta{prefix}. This sets -% \cs{if@dtl@condition}. +% Gets row with index \meta{row idx} from database named \meta{db} +% and stores the row in \cs{dtlcurrentrow}, the preceding rows in +% \cs{dtlbeforerow} and the following rows in \cs{dtlafterrow}. +% The row index, \meta{row idx}, is stored in \cs{dtlrownum} +% and the database name, \meta{db}, is stored in \cs{dtldbname}. +% This assumes that the given row exists. % \begin{macrocode} -\newcommand*{\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 +\newcommand*{\dtlgetrow}[2]{% + \dtlrownum=#2\relax + \edef\dtldbname{#1}% + \expandafter\toks@\expandafter=\csname dtldb@#1\endcsname + \edef\@dtl@dogetrow{\noexpand\@dtlgetrow{\the\toks@}{\number#2}}% + \@dtl@dogetrow } % \end{macrocode} %\end{macro} % -%\begin{macro}{\DTLifnumclosedbetween} +%\begin{macro}{\@dtlgetrow} %\begin{definition} -%\cs{DTLifnumclosedbetween}\marg{num}\marg{min}\marg{max}\marg{true part}\marg{false part} +%\cs{@dtlgetrow}\marg{data specs}\marg{row idx} %\end{definition} -% Determines if \meta{min} $\leq$ \meta{num} $\leq$ \meta{max}. +% Gets the row specs from \meta{data specs} for row with index +% \meta{row idx} which must be fully expanded. % \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}% +\newcommand*{\@dtlgetrow}[2]{% + \def\@dtl@getrow##1% before stuff + \db@row@elt@w% start of the row + \db@row@id@w #2\db@row@id@end@% row id + ##2% + \db@row@id@w #2\db@row@id@end@% row id + \db@row@elt@end@% end of the row + ##3% after stuff + \q@nil{\dtlbeforerow={##1}\dtlcurrentrow={##2}\dtlafterrow={##3}}% + \@dtl@getrow#1\q@nil } % \end{macrocode} %\end{macro} % -%\begin{macro}{\DTLifstringclosedbetween} +%\begin{macro}{\dtlrecombine} %\begin{definition} -%\cs{DTLifstringclosedbetween}\marg{string}\marg{min}\marg{max}\marg{true part}\marg{false part} +%\cs{dtlrecombine} %\end{definition} -% String comparison (starred version ignores case) -%\changes{1.01}{2007 Aug 17}{added starred version} +% Recombines database contents from \cs{dtlbeforerow}, +% \cs{dtlcurrentrow} and \cs{dtlafterrow} % \begin{macrocode} -\newcommand*{\DTLifstringclosedbetween}{% -\@ifstar\@sDTLifstringclosedbetween\@DTLifstringclosedbetween} +\newcommand*{\dtlrecombine}{% + \toks@gconcat@middle@cx{dtldb@\dtldbname}% + {\dtlbeforerow}% + {% % \end{macrocode} -% Unstarred version +% Start of row tag % \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 -} + \noexpand\db@row@elt@w % \end{macrocode} -% Starred version +% Row number % \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 + \noexpand\db@row@id@w + \number\dtlrownum + \noexpand\db@row@id@end@ +% \end{macrocode} +% Current row specs: +% \begin{macrocode} + \the\dtlcurrentrow +% \end{macrocode} +% Row number +% \begin{macrocode} + \noexpand\db@row@id@w + \number\dtlrownum + \noexpand\db@row@id@end@ +% \end{macrocode} +% End of row tag +% \begin{macrocode} + \noexpand\db@row@elt@end@ + }% + {\dtlafterrow}% } % \end{macrocode} %\end{macro} -% -%\begin{macro}{\DTLifclosedbetween} +% +%\begin{macro}{\dtlrecombineomitcurrent} %\begin{definition} -%\cs{DTLifclosedbetween}\marg{arg}\marg{min}\marg{max}\marg{true part}\marg{false part} +%\cs{dtlrecombineomitcurrent} %\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} +%Like \cs{dtlrecombine} but omits \cs{dtlcurrentrow} +%\changes{2.10}{2012-07-18}{new} % \begin{macrocode} -\newcommand*{\DTLifclosedbetween}{% -\@ifstar\@sDTLifclosedbetween\@DTLifclosedbetween} +\newcommand{\dtlrecombineomitcurrent}{% % \end{macrocode} -% Unstarred version +% Decrement row indices in \cs{dtlafterrow}: % \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 -} + \dtl@decrementrows{\dtlafterrow}{\dtlrownum} % \end{macrocode} -% Starred version +% Reconstruct database contents by concatenating +% \cs{dtlbeforerow} and \cs{dtlafterrow} % \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 + \csname dtldb@\dtldbname\endcsname=\dtlbeforerow + \toks@gput@right@cx{dtldb@\dtldbname}{\the\dtlafterrow}% + \dtl@message{Removed row \number\dtlrownum\space in database + `\dtldbname'}% } % \end{macrocode} %\end{macro} % -%\begin{macro}{\DTLifnumopenbetween} +%\begin{macro}{\dtlsplitrow} %\begin{definition} -%\cs{DTLifnumopenbetween}\marg{num}\marg{min}\marg{max}\marg{true part}\marg{false part} +%\cs{dtlsplitrow}\marg{row specs}\marg{col num}\marg{before +% cs}\marg{after cs} %\end{definition} -% Determines if \meta{min} $<$ \meta{num} $<$ \meta{max}. +% Splits the row around the entry given by \meta{col num}. The +% entries before the split are stored in \meta{before cs} and the +% entries after the split are stored in \meta{after cs}. +% \meta{row specs} and \meta{col num} need to be expanded before use. % \begin{macrocode} -\newcommand*{\DTLifnumopenbetween}[5]{% -\DTLconverttodecimal{#1}{\@dtl@numi}% -\DTLconverttodecimal{#2}{\@dtl@numii}% -\DTLconverttodecimal{#3}{\@dtl@numiii}% -\DTLifFPopenbetween{\@dtl@numi}{\@dtl@numii}{\@dtl@numiii}{#4}{#5}% +\newcommand*{\dtlsplitrow}[4]{% + \def\@dtlsplitrow##1%before stuff + \db@col@id@w #2\db@col@id@end@% column id + ##2% unwanted stuff + \db@col@id@w #2\db@col@id@end@% column id + ##3% after stuff + \q@nil{\def#3{##1}\def#4{##3}}% + \@dtlsplitrow#1\q@nil } % \end{macrocode} %\end{macro} % -%\begin{macro}{\DTLifstringopenbetween} +%\begin{macro}{\dtlreplaceentryincurrentrow} %\begin{definition} -%\cs{DTLifstringopenbetween}\marg{string}\marg{min}\marg{max}\marg{true part}\marg{false part} +%\cs{dtlreplaceentryincurrentrow}\marg{new value}\marg{col num} %\end{definition} -% String comparison (starred version ignores case) -%\changes{1.01}{2007 Aug 17}{added starred version} +% Replaces entry for column \meta{col num} in \cs{dtlcurrentrow} +% with \meta{new value} +%\changes{2.10}{2012-07-18}{new} % \begin{macrocode} -\newcommand*{\DTLifstringopenbetween}{% -\@ifstar\@sDTLifstringopenbetween\@DTLifstringopenbetween} +\newcommand*{\dtlreplaceentryincurrentrow}[2]{% % \end{macrocode} -% Unstarred version: +% Split row % \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 -} + \edef\@dtl@do@splitrow{\noexpand\dtlsplitrow + {\the\dtlcurrentrow}% + {\number#2}% + {\noexpand\@dtl@before@cs}% + {\noexpand\@dtl@after@cs}}% + \@dtl@do@splitrow % \end{macrocode} -% Starred version +% Recombine with new value % \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 -} + \toks@{#1}% + \edef\@dtl@stuff{% + \expandonce\@dtl@before@cs % \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 column index specs: % \begin{macrocode} -\newcommand*{\DTLifopenbetween}{% -\@ifstar\@sDTLifopenbetween\@DTLifopenbetween} + \noexpand\db@col@id@w \number#2\noexpand + \noexpand\db@col@id@end@% column id % \end{macrocode} -% Unstarred version +% New entry: % \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 -} + \noexpand\db@col@elt@w + \the\toks@ + \noexpand\db@col@elt@end@ % \end{macrocode} -% Starred version +% End column index specs: % \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 + \noexpand\db@col@id@w \number#2\noexpand + \noexpand\db@col@id@end@% column id + \expandonce\@dtl@after@cs + }% +% \end{macrocode} +% Store in \cs{dtlcurrentrow} +% \begin{macrocode} + \expandafter\dtlcurrentrow\expandafter{\@dtl@stuff}% +% \end{macrocode} +% Update column specs +% \begin{macrocode} + \@sdtlgetkeyforcolumn{\@dtl@key}{\dtldbname}{#2}% + \@dtl@updatekeys{\dtldbname}{\@dtl@key}{#1}% + \dtl@message{Updated \@dtl@key\space -> #1\space in database + `\dtldbname'}% } % \end{macrocode} %\end{macro} % -%\begin{macro}{\DTLifFPopenbetween} +%\begin{macro}{\dtlremoveentryincurrentrow} %\begin{definition} -%\cs{DTLifFPopenbetween}\marg{num}\marg{min}\marg{max}\marg{true part}\marg{false part} +%\cs{dtlremoveentryincurrentrow}\marg{col idx} %\end{definition} -% Determines if \meta{min} $<$ \meta{num} $<$ \meta{max} where -% all arguments are in standard fixed point notation. +% Removes entry for column \meta{col idx} from \cs{dtlcurrentrow}. +%\changes{2.10}{2012-07-18}{new} % \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 +\newcommand*{\dtlremoveentryincurrentrow}[1]{% +% \end{macrocode} +% Split row +% \begin{macrocode} + \edef\@dtl@do@splitrow{\noexpand\dtlsplitrow + {\the\dtlcurrentrow}% + {\number#1}% + {\noexpand\@dtl@before@cs}% + {\noexpand\@dtl@after@cs}}% + \@dtl@do@splitrow +% \end{macrocode} +% Combine row without given column: +% \begin{macrocode} + \edef\@dtl@stuff{% + \expandonce\@dtl@before@cs + \expandonce\@dtl@after@cs + }% +% \end{macrocode} +% Store in \cs{dtlcurrentrow} +% \begin{macrocode} + \expandafter\dtlcurrentrow\expandafter{\@dtl@stuff}% + \dtl@message{Removed entry from column \number#1\space\space in database + `\dtldbname'}% } % \end{macrocode} %\end{macro} % -%\begin{macro}{\DTLifFPclosedbetween} +%\begin{macro}{\dtlswapentriesincurrentrow} %\begin{definition} -%\cs{DTLifFPclosedbetween}\marg{num}\marg{min}\marg{max}\marg{true part}\marg{false part} +%\cs{dtlswapentriesincurrentrow}\marg{col1 +%num}\marg{col2 num} %\end{definition} -% Determines if \meta{min} $\leq$ \meta{num} $\leq$ \meta{max}. +% Swaps columns \meta{col1 num} and \meta{col2 num} in \cs{dtlcurrentrow} +%\changes{2.10}{2012-07-18}{new} % \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 +\newcommand*{\dtlswapentriesincurrentrow}[2]{% + \dtlgetentryfromcurrentrow{\@dtl@entryI}{#1}% + \dtlgetentryfromcurrentrow{\@dtl@entryII}{#2}% + \expandafter\dtlreplaceentryincurrentrow\expandafter + {\@dtl@entryII}{#1}% + \expandafter\dtlreplaceentryincurrentrow\expandafter + {\@dtl@entryI}{#2}% } % \end{macrocode} %\end{macro} % -% 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{macro}{\dtlgetentryfromcurrentrow} %\begin{definition} -%\cs{DTLiffirstrow}\marg{true part}\marg{false part} +%\cs{dtlgetentryfromcurrentrow}\marg{cs}\marg{col num} %\end{definition} -% Test if the current row is the first row. (This takes -% \meta{condition}, the optional argument of \cs{DTLforeach}, -% into account, so it may not correspond to row~1 of the -% database.) Can only be used in \cs{DTLforeachrow}. -%\changes{2.0}{2009 February 27}{modified to have different -% definition depending on location} +% Gets value for column \meta{col num} from \cs{dtlcurrentrow} +% and stores in \meta{cs}. If not found, \meta{cs} is set to +% \cs{dtlnovalue}. +%\changes{2.0}{2009 February 27}{new} % \begin{macrocode} -\newcommand{\DTLiffirstrow}[2]{% - \PackageError{datatool}{\string\DTLiffirstrow\space can only - be used inside \string\DTLforeach}{}% +\newcommand*{\dtlgetentryfromcurrentrow}[2]{% + \dtlgetentryfromrow{#1}{#2}{\dtlcurrentrow}% } % \end{macrocode} %\end{macro} % -%\begin{macro}{\DTLiflastrow} +%\begin{macro}{\dtlgetentryfromrow} %\begin{definition} -%\cs{DTLiflastrow}\marg{true part}\marg{false part} +%\cs{dtlgetentryfromrow}\marg{cs}\marg{col num}\marg{row toks} %\end{definition} -% Checks if the current row is the last row of the database. -% It doesn't take the condition (the optional argument of -% \cs{DTLforeach}) into account, so its possible it may never -% do \meta{true part}, as the last row of the database may not -% meet the condition. It is therefore not very useful and is -% confusing since it behaves differently to \cs{DTLiffirstrow} -% which does take the condition into account, so I have removed -% its description from the main part of the manual. If you need -% to use the optional argument of \cs{DTLforeach}, you will first -% have to iterate through the database to count up the number -% of rows which meet the condition, and then do another pass, -% checking if the current row has reached that number. -%\changes{1.01}{2007 Aug 17}{fixed bug} -%\changes{2.0}{2009 February 27}{modified to have different -% definition depending on location} % \begin{macrocode} -\newcommand{\DTLiflastrow}[2]{% - \PackageError{datatool}{\string\DTLiflastrow\space can only - be used inside \string\DTLforeach}{}% +\newcommand*{\dtlgetentryfromrow}[3]{% + \edef\@dtl@do@getentry{\noexpand\dtl@getentryfromrow + {\noexpand#1}{\number#2}{\the#3}}% + \@dtl@do@getentry } % \end{macrocode} %\end{macro} % -%\begin{macro}{\DTLifoddrow} +%\begin{macro}{\dtl@getentryfromrow} %\begin{definition} -%\cs{DTLifoddrow}\marg{true part}\marg{false part} +%\cs{dtl@getentryfromrow}\marg{cs}\marg{col num}\marg{row specs} %\end{definition} -% Determines whether the current row is odd (takes the optional -% argument of \cs{DTLforeach} into account.) -%\changes{2.0}{2009 February 27}{modified to have different -% definition depending on location} % \begin{macrocode} -\newcommand{\DTLifoddrow}[2]{% - \PackageError{datatool}{\string\DTLifoddrow\space can only - be used inside \string\DTLforeach}{}% +\newcommand*{\dtl@getentryfromrow}[3]{% + \def\dtl@dogetentry##1% before stuff + \db@col@id@w #2\db@col@id@end@% Column id + \db@col@elt@w ##2\db@col@elt@end@% Value + \db@col@id@w #2\db@col@id@end@% Column id + ##3% Remaining stuff + \q@nil{\def#1{##2}}% + \dtl@dogetentry#3% + \db@col@id@w #2\db@col@id@end@% + \db@col@elt@w \@dtlnovalue\db@col@elt@end@% + \db@col@id@w #2\db@col@id@end@% + \q@nil } % \end{macrocode} %\end{macro} % -% \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{macro}{\dtlappendentrytocurrentrow} +%\begin{definition} +%\cs{dtlappendentrytocurrentrow}\marg{key}\marg{value} +%\end{definition} +% Appends entry to \cs{dtlcurrentrow} +%\changes{2.10}{2012-07-18}{new} % \begin{macrocode} -\newif\if@dtl@condition +\newcommand*{\dtlappendentrytocurrentrow}[2]{% % \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}. +% Update information about this column (adding new column if +% necessary) % \begin{macrocode} -\newcommand*{\dtl@testlt}[2]{% -\DTLiflt{#1}{#2}{\@dtl@conditiontrue}{\@dtl@conditionfalse}} + \@dtl@updatekeys{\dtldbname}{#1}{#2}% % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\DTLislt} -% Provide conditional command for use in \cs{ifthenelse} +% Get column index and store in \cs{dtlcolumnnum} % \begin{macrocode} -\newcommand*{\DTLislt}[2]{% -\TE@throw\noexpand\dtl@testlt{#1}{#2}\noexpand\if@dtl@condition} + \expandafter\dtlcolumnnum\expandafter + =\dtlcolumnindex{\dtldbname}{#1}\relax % \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}. +% Does this row already have an entry with this key? % \begin{macrocode} -\newcommand*{\dtl@testiclt}[2]{% -\@sDTLiflt{#1}{#2}{\@dtl@conditiontrue}{\@dtl@conditionfalse}} + \edef\dtl@dogetentry{\noexpand\dtlgetentryfromcurrentrow + {\noexpand\dtl@entry}{\number\dtlcolumnnum}% + }% + \dtl@dogetentry + \ifx\dtl@entry\dtlnovalue % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\DTLisilt} -% Provide conditional command for use in \cs{ifthenelse} -%\changes{1.01}{2007 Aug 17}{new} +% There are no entries in this row for the given key. +% Expand entry value before storing. % \begin{macrocode} -\newcommand*{\DTLisilt}[2]{% -\TE@throw\noexpand\dtl@testiclt{#1}{#2}\noexpand\if@dtl@condition} + \protected@edef\@dtl@tmp{#2}% + \expandafter\@dtl@toks\expandafter{\@dtl@tmp}% % \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}. +% Append this entry to the current row. % \begin{macrocode} -\newcommand*{\dtl@testgt}[2]{% -\DTLifgt{#1}{#2}{\@dtl@conditiontrue}{\@dtl@conditionfalse}} + \toks@gput@right@cx{dtlcurrentrow}% + {% % \end{macrocode} -%\end{macro} -%\begin{macro}{\DTLisgt} -% Provide conditional command for use in \cs{ifthenelse} +% Begin column index specs: % \begin{macrocode} -\newcommand*{\DTLisgt}[2]{% -\TE@throw\noexpand\dtl@testgt{#1}{#2}\noexpand\if@dtl@condition} + \noexpand\db@col@id@w + \number\dtlcolumnnum + \noexpand\db@col@id@end@ % \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}. +% New entry: % \begin{macrocode} -\newcommand*{\dtl@testicgt}[2]{% -\@sDTLifgt{#1}{#2}{\@dtl@conditiontrue}{\@dtl@conditionfalse}} + \noexpand\db@col@elt@w + \the\@dtl@toks + \noexpand\db@col@elt@end@ % \end{macrocode} -%\end{macro} -%\begin{macro}{\DTLisigt} -% Provide conditional command for use in \cs{ifthenelse} -%\changes{1.01}{2007 Aug 17}{new} +% End column index specs: % \begin{macrocode} -\newcommand*{\DTLisigt}[2]{% -\TE@throw\noexpand\dtl@testicgt{#1}{#2}\noexpand\if@dtl@condition} + \noexpand\db@col@id@w + \number\dtlcolumnnum + \noexpand\db@col@id@end@ + }% % \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}. +% Print information to terminal and log file if in verbose mode. % \begin{macrocode} -\newcommand*{\dtl@testeq}[2]{% -\DTLifeq{#1}{#2}{\@dtl@conditiontrue}{\@dtl@conditionfalse}} + \dtl@message{Appended #1\space -> #2\space to database + `\dtldbname'}% + \else % \end{macrocode} -%\end{macro} -%\begin{macro}{\DTLiseq} -% Provide conditional command for use in \cs{ifthenelse} +% There is already an entry in this row for the given key % \begin{macrocode} -\newcommand*{\DTLiseq}[2]{% -\TE@throw\noexpand\dtl@testeq{#1}{#2}\noexpand\if@dtl@condition} + \PackageError{datatool}{Can't append entry to row: + there is already an entry for key `#1' in this row}{}% + \fi +} % \end{macrocode} %\end{macro} % -%\begin{macro}{\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{macro}{\DTLgetvalue} +%\begin{definition} +%\cs{DTLgetvalue}\marg{cs}\marg{db}\marg{r}\marg{c} +%\end{definition} +% Gets the element in row \meta{r}, column \meta{c} from database +% \meta{db} and stores in \meta{cs}. % \begin{macrocode} -\newcommand*{\DTLisieq}[2]{% -\TE@throw\noexpand\dtl@testiceq{#1}{#2}\noexpand\if@dtl@condition} +\newcommand*{\DTLgetvalue}[4]{% + \edef\dtl@dogetvalue{\noexpand\dtl@getvalue{\noexpand#1}{#2}% + {\number#3}{\number#4}}% + \dtl@dogetvalue +} % \end{macrocode} %\end{macro} % -%\begin{macro}{\DTLisSubString} -% Tests if second argument is contained in first argument. -%\changes{1.01}{2007 Aug 17}{new} +%\begin{macro}{\dtl@getvalue} % \begin{macrocode} -\newcommand*{\DTLisSubString}[2]{% -\TE@throw\noexpand\dtl@testifsubstring{#1}{#2}% -\noexpand\if@dtl@condition} +\newcommand*{\dtl@getvalue}[4]{% + \def\@dtl@getvalue ##1% stuff before row + \db@row@id@w #3\db@row@id@end@% row id + ##2% stuff in row before column + \db@col@id@w #4\db@col@id@end@% column id + \db@col@elt@w ##3\db@col@elt@end@% value + ##4% stuff after value + \q@nil{\def#1{##3}}% + \toks@=\csname dtldb@#2\endcsname + \expandafter\@dtl@getvalue\the\toks@% contents of data base + \db@row@id@w #3\db@row@id@end@% + \db@col@id@w #4\db@col@id@end@% + \db@col@elt@w \@dtlnovalue\db@col@elt@end@% undefined value + \q@nil + \ifx#1\dtlnovalue + \PackageError{datatool}{There is no element at (row=#3, + column=#4) in database `#2'}{}% + \fi +} % \end{macrocode} %\end{macro} % -%\begin{macro}{\DTLisPrefix} -% Tests if first argument starts with second argument. -%\changes{1.01}{2007 Aug 17}{new} +%\begin{macro}{\DTLgetlocation} +%\begin{definition} +%\cs{DTLgetlocation}\marg{row cs}\marg{column cs}\marg{database}% +%\marg{value} +%\end{definition} +% Assigns \meta{row cs} and \meta{column cs} to the indices of the +% first entry in \meta{database} that matches \meta{value}. % \begin{macrocode} -\newcommand*{\DTLisPrefix}[2]{% -\TE@throw\noexpand\dtl@teststartswith{#1}{#2}% -\noexpand\if@dtl@condition} +\newcommand*{\DTLgetlocation}[4]{% + \def\@dtl@getlocation##1% stuff before value + \db@col@elt@w #4\db@col@elt@end@% value + \db@col@id@w ##2\db@col@id@end@% column id + ##3% stuff after this column + \db@row@id@w ##4\db@row@id@end@% row id + ##5% stuff after row + \q@nil{\def#1{##4}\def#2{##2}}% + \toks@=\csname dtldb@#3\endcsname + \expandafter\@dtl@getlocation\the\toks@% contents of data base + \db@col@elt@w #4\db@col@elt@end@% value + \db@col@id@w \@dtlnovalue\db@col@id@end@% undefined column id + \db@row@id@w \@dtlnovalue\db@row@id@end@% undefined row id + \q@nil + \ifx#1\dtlnovalue + \PackageError{datatool}{There is no element `#4' in + database `#3'}{}% + \fi +} % \end{macrocode} %\end{macro} + +%\section{Iterating Through Databases} +%\label{sec:code:loops} % -%\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{macro}{\@dtlforeachrow} +%\begin{definition} +%\cs{@dtlforeachrow}(\meta{idx cs},\meta{row cs})\cs{in}\marg{db}% +%\cs{do}\marg{body} +%\end{definition} +% Iterates through each row in database. Assigns the current row +% index to \meta{idx cs} and the row specs to \meta{row cs} % \begin{macrocode} -\newcommand*{\DTLisclosedbetween}[3]{% -\TE@throw\noexpand\dtl@testclosedbetween{#1}{#2}{#3}% -\noexpand\if@dtl@condition} +\long\def\@dtlforeachrow(#1,#2)\in#3\do#4{% + \edef\dtl@tmp{\expandafter\the\csname dtldb@#3\endcsname}% + \expandafter\@dtl@foreachrow\dtl@tmp + \db@row@elt@w% + \db@row@id@w \@nil\db@row@id@end@% + \db@row@id@w \@nil\db@row@id@end@% + \db@row@elt@end@% + \@@{#1}{#2}{#4}\q@nil +} % \end{macrocode} %\end{macro} % -%\begin{macro}{\dtl@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{macro}{\@dtl@foreachrow} % \begin{macrocode} -\newcommand*{\dtl@testiclosedbetween}[3]{% -\@sDTLifclosedbetween{#1}{#2}{#3}{\@dtl@conditiontrue}{\@dtl@conditionfalse}} +\long\def\@dtl@foreachrow\db@row@elt@w% +\db@row@id@w #1\db@row@id@end@% +#2\db@row@id@w #3\db@row@id@end@% +\db@row@elt@end@#4\@@#5#6#7\q@nil{% % \end{macrocode} -%\end{macro} -%\begin{macro}{\DTLisiclosedbetween} -% Provide conditional command for use in \cs{ifthenelse} -%\changes{1.01}{2007 Aug 17}{new} +% Define control sequence given by "#5" % \begin{macrocode} -\newcommand*{\DTLisiclosedbetween}[3]{% -\TE@throw\noexpand\dtl@testiclosedbetween{#1}{#2}{#3}% -\noexpand\if@dtl@condition} + \gdef#5{#1}% % \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}. +% Hide the loop body in a macro % \begin{macrocode} -\newcommand*{\dtl@testopenbetween}[3]{% -\DTLifopenbetween{#1}{#2}{#3}{\@dtl@conditiontrue -}{\@dtl@conditionfalse}} + \gdef\@dtl@loopbody{#7}% % \end{macrocode} -%\end{macro} -%\begin{macro}{\DTLisopenbetween} -% Provide conditional command for use in \cs{ifthenelse} +% Increment level counter to allow for nested loops % \begin{macrocode} -\newcommand*{\DTLisopenbetween}[3]{% -\TE@throw\noexpand\dtl@testopenbetween{#1}{#2}{#3}% -\noexpand\if@dtl@condition} + \global\advance\@dtl@foreach@level by 1\relax % \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}. +% Check if we have reached the end of the loop % \begin{macrocode} -\newcommand*{\dtl@testiopenbetween}[3]{% -\@sDTLifopenbetween{#1}{#2}{#3}{\@dtl@conditiontrue -}{\@dtl@conditionfalse}} + \ifx#5\@nnil + \expandafter\global\expandafter + \let\csname @dtl@foreachnext\the\@dtl@foreach@level\endcsname + =\@dtl@foreachnoop + \else + \gdef#6{#2}% % \end{macrocode} -%\end{macro} -%\begin{macro}{\DTLisiopenbetween} -% Provide conditional command for use in \cs{ifthenelse} -%\changes{1.01}{2007 Aug 17}{new} +% Set up the break function: +% Make a copy of current break function % \begin{macrocode} -\newcommand*{\DTLisiopenbetween}[3]{% -\TE@throw\noexpand\dtl@testiopenbetween{#1}{#2}{#3}% -\noexpand\if@dtl@condition} + \expandafter\let + \csname @dtl@break@\the\@dtl@foreach@level\endcsname + \dtlbreak % \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}. +% Setup break function for this level % \begin{macrocode} -\newcommand*{\dtl@testFPclosedbetween}[3]{% -\DTLifFPclosedbetween{#1}{#2}{#3}% -{\@dtl@conditiontrue}{\@dtl@conditionfalse}} + \gdef\dtlbreak{\expandafter\global\expandafter + \let\csname @dtl@foreachnext\the\@dtl@foreach@level\endcsname + =\@dtl@foreachnoop}% % \end{macrocode} -%\end{macro} -% Provide conditional command for use in \cs{ifthenelse} -%\begin{macro}{\DTLisFPclosedbetween} +% Initialise % \begin{macrocode} -\newcommand*{\DTLisFPclosedbetween}[3]{% -\TE@throw\noexpand\dtl@testFPclosedbetween{#1}{#2}{#3}% -\noexpand\if@dtl@condition} + \expandafter\global\expandafter + \let\csname @dtl@foreachnext\the\@dtl@foreach@level\endcsname + =\@dtl@foreachrow % \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}. +% Do body of loop % \begin{macrocode} -\newcommand*{\dtl@testFPopenbetween}[3]{% -\DTLifFPopenbetween{#1}{#2}{#3}{\@dtl@conditiontrue}{\@dtl@conditionfalse}} + \@dtl@loopbody % \end{macrocode} -%\end{macro} -%\begin{macro}{\DTLisFPopenbetween} -% Provide conditional command for use in \cs{ifthenelse} +% Restore break function % \begin{macrocode} -\newcommand*{\DTLisFPopenbetween}[3]{% -\TE@throw\noexpand\dtl@testFPopenbetween{#1}{#2}{#3}% -\noexpand\if@dtl@condition} + \expandafter\let\expandafter\dtlbreak + \csname @dtl@break@\the\@dtl@foreach@level\endcsname + \fi % \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}. +% Set up what to do next. % \begin{macrocode} -\newcommand*{\dtl@testFPislt}[2]{% -\FPiflt{#1}{#2}\@dtl@conditiontrue\else\@dtl@conditionfalse\fi} + \expandafter\let\expandafter\@dtl@foreachnext + \csname @dtl@foreachnext\the\@dtl@foreach@level\endcsname % \end{macrocode} -%\end{macro} -%\begin{macro}{\DTLisFPlt} -% Provide conditional command for use in \cs{ifthenelse} +% Decrement level counter. % \begin{macrocode} -\newcommand*{\DTLisFPlt}[2]{% -\TE@throw\noexpand\dtl@testFPislt{#1}{#2}% -\noexpand\if@dtl@condition} + \global\advance\@dtl@foreach@level by -1\relax % \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}. +% Repeat loop if necessary. % \begin{macrocode} -\newcommand*{\dtl@testFPisgt}[2]{% -\FPifgt{#1}{#2}\@dtl@conditiontrue\else\@dtl@conditionfalse\fi} + \@dtl@foreachnext#4\@@{#5}{#6}{#7}\q@nil +} % \end{macrocode} %\end{macro} -%\begin{macro}{\DTLisFPgt} -% Provide conditional command for use in \cs{ifthenelse} +% +%\begin{macro}{\@dtl@foreachnoop} % \begin{macrocode} -\newcommand*{\DTLisFPgt}[2]{% -\TE@throw\noexpand\dtl@testFPisgt{#1}{#2}% -\noexpand\if@dtl@condition} +\long\def\@dtl@foreachnoop#1\@@#2\q@nil{} % \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{macro}{\dtlforeachkey} +%\begin{definition} +%\cs{dtlforeachkey}(\meta{key cs},\meta{col cs},\meta{type cs},\meta{header cs})% +%\cs{in}\marg{db}\cs{do}\marg{body} +%\end{definition} +% Iterates through all the keys in database \meta{db}. In each +% iteration, \meta{key cs} stores the key, \meta{col cs} stores the +% column index and \meta{type cs} stores the data type. % \begin{macrocode} -\newcommand*{\dtl@testFPiseq}[2]{% -\FPifeq{#1}{#2}\@dtl@conditiontrue\else\@dtl@conditionfalse\fi} +\long\def\dtlforeachkey(#1,#2,#3,#4)\in#5\do#6{% + \gdef\@dtl@loopbody{#6}% + \edef\@dtl@keys{\expandafter\the\csname dtlkeys@#5\endcsname}% + \expandafter\@dtl@foreachkey\@dtl@keys + \db@plist@elt@w% + \db@col@id@w -1\db@col@id@end@% + \db@key@id@w \db@key@id@end@% + \db@type@id@w \db@type@id@end@% + \db@header@id@w \db@header@id@end@% + \db@col@id@w -1\db@col@id@end@% + \db@plist@elt@end@% + \@@{\@dtl@updatefkcs{#1}{#2}{#3}{#4}}\q@nil +} % \end{macrocode} %\end{macro} -%\begin{macro}{\DTLisFPeq} -% Provide conditional command for use in \cs{ifthenelse} +% +%\begin{macro}{\@dtl@updatefkcs} % \begin{macrocode} -\newcommand*{\DTLisFPeq}[2]{% -\TE@throw\noexpand\dtl@testFPiseq{#1}{#2}% -\noexpand\if@dtl@condition} +\newcommand*{\@dtl@updatefkcs}[8]{% + \gdef#1{#5}% + \gdef#2{#6}% + \gdef#3{#7}% + \gdef#4{#8}% +} % \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{macro}{\@dtl@foreachkey} +% Sets everything globally in case it occurs in a tabular environment +% Loop body needs to be stored in \cs{@dtl@loopbody}. +% "#7" indicates an update macro. % \begin{macrocode} -\newcommand*{\dtl@testFPislteq}[2]{% -\FPiflt{#1}{#2}\@dtl@conditiontrue\else\@dtl@conditionfalse\fi -\if@dtl@condition -\else - \dtl@testFPiseq{#1}{#2}% -\fi -} +\long\def\@dtl@foreachkey\db@plist@elt@w% +\db@col@id@w #1\db@col@id@end@% +\db@key@id@w #2\db@key@id@end@% +\db@type@id@w #3\db@type@id@end@% +\db@header@id@w #4\db@header@id@end@% +\db@col@id@w #5\db@col@id@end@% +\db@plist@elt@end@#6\@@#7\q@nil{% + \ifnum#1=-1\relax % \end{macrocode} -%\end{macro} -%\begin{macro}{\DTLisFPlteq} -% Provide conditional command for use in \cs{ifthenelse} +% Terminate loop % \begin{macrocode} -\newcommand*{\DTLisFPlteq}[2]{% -\TE@throw\noexpand\dtl@testFPislteq{#1}{#2}% -\noexpand\if@dtl@condition} + \let\@dtl@foreachnext\@dtl@foreachnoop + \else % \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}. +% Set up loop variables % \begin{macrocode} -\newcommand*{\dtl@testFPisgteq}[2]{% -\FPifgt{#1}{#2}\@dtl@conditiontrue\else\@dtl@conditionfalse\fi -\if@dtl@condition -\else - \dtl@testFPiseq{#1}{#2}% -\fi -} + #7{#2}{#1}{#3}{#4}% % \end{macrocode} -%\end{macro} -%\begin{macro}{\DTLisFPgteq} -% Provide conditional command for use in \cs{ifthenelse} +% Increment level counter to allow for nested loops % \begin{macrocode} -\newcommand*{\DTLisFPgteq}[2]{% -\TE@throw\noexpand\dtl@testFPisgteq{#1}{#2}% -\noexpand\if@dtl@condition} + \global\advance\@dtl@foreach@level by 1\relax % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\dtl@teststring} -% Command to test if argument is a string. This sets -% \cs{if@dtl@condition} +% Set up the break function % \begin{macrocode} -\newcommand*{\dtl@teststring}[1]{% -\DTLifstring{#1}{\@dtl@conditiontrue}{\@dtl@conditionfalse}} + \expandafter\let + \csname @dtl@break@\the\@dtl@foreach@level\endcsname + \dtlbreak + \gdef\dtlbreak{\expandafter\global\expandafter + \let\csname @dtl@foreachnext\the\@dtl@foreach@level\endcsname + =\@dtl@foreachnoop}% % \end{macrocode} -%\end{macro} -%\begin{macro}{\DTLisstring} -% Provide conditional command for use in \cs{ifthenelse} +% Initialise % \begin{macrocode} -\newcommand*{\DTLisstring}[1]{% -\TE@throw\noexpand\dtl@teststring{#1}\noexpand\if@dtl@condition} + \expandafter\global\expandafter + \let\csname @dtl@foreachnext\the\@dtl@foreach@level\endcsname + =\@dtl@foreachkey % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\dtl@testnumerical} -% Command to test if argument is a numerical. This sets -% \cs{if@dtl@condition} +% Do body of loop % \begin{macrocode} -\newcommand*{\dtl@testnumerical}[1]{% -\DTLifnumerical{#1}{\@dtl@conditiontrue}{\@dtl@conditionfalse}% -} + \@dtl@loopbody % \end{macrocode} -%\end{macro} -%\begin{macro}{\DTLisnumerical} -% Provide conditional command for use in \cs{ifthenelse} +% Set up what to do next % \begin{macrocode} -\newcommand*{\DTLisnumerical}[1]{% -\TE@throw\noexpand\dtl@testnumerical{#1}\noexpand\if@dtl@condition} + \expandafter\let\expandafter\@dtl@foreachnext + \csname @dtl@foreachnext\the\@dtl@foreach@level\endcsname % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\dtl@testint} -% Command to test if argument is an integer. This sets -% \cs{if@dtl@condition} +% Restore break function % \begin{macrocode} -\newcommand*{\dtl@testint}[1]{% -\DTLifint{#1}{\@dtl@conditiontrue}{\@dtl@conditionfalse}} + \expandafter\let\expandafter\dtlbreak + \csname @dtl@break@\the\@dtl@foreach@level\endcsname % \end{macrocode} -%\end{macro} -%\begin{macro}{\DTLisint} -% Provide conditional command for use in \cs{ifthenelse} +% Decrement level counter % \begin{macrocode} -\newcommand*{\DTLisint}[1]{% -\TE@throw\noexpand\dtl@testint{#1}\noexpand\if@dtl@condition} + \global\advance\@dtl@foreach@level by -1\relax + \fi % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\dtl@testreal} -% Command to test if argument is a real. This sets -% \cs{if@dtl@condition} +% Recurse if necessary % \begin{macrocode} -\newcommand*{\dtl@testreal}[1]{% -\DTLifreal{#1}{\@dtl@conditiontrue}{\@dtl@conditionfalse}} + \@dtl@foreachnext#6\@@{#7}\q@nil +} % \end{macrocode} %\end{macro} -%\begin{macro}{\DTLisreal} -% Provide conditional command for use in \cs{ifthenelse} +% +%\begin{macro}{\dtlforcolumn} +%\begin{definition} +%\cs{dtlforcolumn}\marg{cs}\marg{db}\marg{key}\marg{body} +%\end{definition} +% Iterates through column given by \meta{key} in database \meta{db}. +% \meta{cs} is assign to the element of the column in the +% current iteration. Starred version doesn't check if data base +% exists % \begin{macrocode} -\newcommand*{\DTLisreal}[1]{% -\TE@throw\noexpand\dtl@testreal{#1}\noexpand\if@dtl@condition} +\newcommand*{\dtlforcolumn}{\@ifstar\@sdtlforcolumn\@dtlforcolumn} % \end{macrocode} %\end{macro} -% -%\begin{macro}{\dtl@testcurrency} -% Command to test if argument is a currency. This sets -% \cs{if@dtl@condition} +% +%\begin{macro}{\@dtlforcolumn} % \begin{macrocode} -\newcommand*{\dtl@testcurrency}[1]{% -\DTLifcurrency{#1}{\@dtl@conditiontrue}{\@dtl@conditionfalse}} +\newcommand{\@dtlforcolumn}[4]{% % \end{macrocode} -%\end{macro} -%\begin{macro}{\DTLiscurrency} -% Provide conditional command for use in \cs{ifthenelse} +% Check if data base exists % \begin{macrocode} -\newcommand*{\DTLiscurrency}[1]{% -\TE@throw\noexpand\dtl@testcurrency{#1}\noexpand\if@dtl@condition} + \DTLifdbexists{#2}% + {% + \@DTLifhaskey{#2}{#3}% + {% + \@sdtlforcolumn{#1}{#2}{#3}{#4}% + }% % \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} +% key not in data base % \begin{macrocode} -\newcommand*{\dtl@testcurrencyunit}[2]{% -\DTLifcurrencyunit{#1}{#2}{\@dtl@conditiontrue}{\@dtl@conditionfalse}} + {% + \PackageError{datatool}{Database `#2' doesn't contain + key `#3'}{}% + }% + }% +% + {% + \PackageError{datatool}{Database `#2' doesn't exist}{}% + }% +} % \end{macrocode} %\end{macro} -%\begin{macro}{\DTLiscurrencyunit} -% Provide conditional command for use in \cs{ifthenelse} +% +%\begin{macro}{\@sdtlforcolumn} % \begin{macrocode} -\newcommand*{\DTLiscurrencyunit}[2]{% -\TE@throw\noexpand\dtl@testcurrencyunit{#1}{#2}% -\noexpand\if@dtl@condition} -% \end{macrocode} +\newcommand{\@sdtlforcolumn}[4]{% + \toks@{#4}% + \edef\@dtl@doforcol{\noexpand\dtl@forcolumn{\noexpand#1}% + {\expandafter\the\csname dtldb@#2\endcsname}% + {\dtlcolumnindex{#2}{#3}}{\the\toks@}% + }% + \@dtl@doforcol% +} +% end{macrocode} %\end{macro} -% -% \subsection{Defining New Databases} -% As from v2.0, the internal structure of the database has changed -% to make it more efficient.\footnote{Thanks to Morten H\o gholm -% for the suggestion.} The database is now stored in a token -% register instead of a macro. Each row is represented as:\par -%\verb|\db@row@elt@w|% -%\verb|\db@row@id@w| \meta{row idx}\verb|\db@row@id@end@|% -%\meta{column data}% -%\verb|\db@row@id@w| \meta{row idx}\verb|\db@row@id@end@|% -%\verb|\db@row@elt@end@|\par -% where \meta{row idx} is the row index and \meta{column data} is -% the data for each column in the row. Each column for a given -% row is stored as:\par -%\verb|\db@col@id@w| \meta{column idx}\verb|\db@col@id@end@|% -%\verb|\db@col@elt@w| \meta{value}\verb|\db@col@elt@end@|% -%\verb|\db@col@id@w| \meta{column idx}\verb|\db@col@id@end@|\par -% where \meta{column idx} is the column index and \meta{value} -% is the entry for the given column and row. -% -% Each row only has an associated index, but columns have -% a unique identifying key as well as an associated index. Columns -% also have an associated data type which may be: 0 (column -% contains strings), 1 (column contains integers), 2 (column -% contains real numbers), 3 (column contains currency) or -% \meta{empty} (column contains no data). Since the key sometimes -% has to be expanded, a header is also available in the event -% that the user wants to use \cs{DTLdisplaydb} or -% \cs{DTLdisplaylongdb} and requires a column header that would -% cause problems if used as a key. The general column -% information is stored in a token register where each column -% has information stored in the form:\par -%\verb|\db@plist@elt@w|% -%\verb|\db@col@id@w| \meta{index}\verb|\db@col@id@end@|% -%\verb|\db@key@id@w| \meta{key}\verb|\db@key@id@end@|% -%\verb|\db@type@id@w| \meta{type}\verb|\db@type@id@end@|% -%\verb|\db@header@id@w| \meta{type}\verb|\db@header@id@end@|% -%\verb|\db@col@id@w| \meta{index}\verb|\db@col@id@end@|% -%\verb|\db@plist@elt@end@| -% -% The column name (\meta{key}) is mapped to the column index -% using \cs{dtl@ci@}\meta{db}"@"\meta{key} where \meta{db} is -% the database name. % -%\begin{macro}{\DTLnewdb} +%\begin{macro}{\dtlforcolumnidx} %\begin{definition} -% \cs{DTLnewdb}\marg{db name} +%\cs{dtlforcolumnidx}\marg{cs}\marg{db}\marg{col num}\marg{body} %\end{definition} -%\changes{2.0}{2009 February 27}{Changed way database is stored} -% Initialises a database called \meta{name}. +% Iterates through the column with index in database . +% Starred version doesn't check if database exists. +%\changes{2.0}{2009 February 27}{new} +% \begin{macrocode} +\newcommand*{\dtlforcolumnidx}{% + \@ifstar\@sdtlforcolumnidx\@dtlforcolumnidx +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\@dtlforcolumnidx} % \begin{macrocode} -\newcommand*{\DTLnewdb}[1]{% +\newcommand{\@dtlforcolumnidx}[4]{% + \DTLifdbexists{#2}% + {% + \expandafter\ifnum\csname dtlcols@#2\endcsname<#3\relax + \PackageError{datatool}{Column index \number#3\space out of + bounds for database `#2'}{Database `#2' only has + \expandafter\number\csname dtlcols@#2\endcsname\space + columns}% + \else + \ifnum#3<1\relax + \PackageError{datatool}{Column index \number#3\space out of + bounds for database `#2'}{Indices start from 1}% + \else + \@sdtlforcolumnidx{#1}{#2}{#3}{#4}% + \fi + \fi + }% % \end{macrocode} -% Check if there is already a database with this name. +% data base doesn't exist % \begin{macrocode} - \DTLifdbexists{#1}% {% - \PackageError{datatool}{Database `#1' already exists}{}% + \PackageError{datatool}{Database `#2' doesn't exist}{}% }% - {% +} % \end{macrocode} -% Define new database. Add information message if in verbose -% mode. +%\end{macro} +% +%\begin{macro}{\@sdtlforcolumnidx} % \begin{macrocode} - \dtl@message{Creating database `#1'}% +\newcommand{\@sdtlforcolumnidx}[4]{% + \toks@{#4}% + \edef\@dtl@doforcol{\noexpand\dtl@forcolumn{\noexpand#1}% + {\expandafter\the\csname dtldb@#2\endcsname}% + {\number#3}{\the\toks@}% + }% + \@dtl@doforcol +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\dtl@forcolumn} +%\begin{definition} +%\cs{dtl@forcolumn}\marg{cs}\marg{db specs}\marg{col num}\marg{body} +%\end{definition} +% \meta{col num} needs to be fully expanded +% \begin{macrocode} +\newcommand{\dtl@forcolumn}[4]{% % \end{macrocode} -% Define token register used to store the contents of the database. +% make a copy of break function % \begin{macrocode} - \expandafter\newtoks\csname dtldb@#1\endcsname + \let\@dtl@oldbreak\dtlbreak % \end{macrocode} -% Define token register used to store the column header information. +% set up break function % \begin{macrocode} - \expandafter\newtoks\csname dtlkeys@#1\endcsname{}% + \def\dtlbreak{\let\@dtl@forcolnext=\@dtl@forcolnoop}% % \end{macrocode} -% Define count register used to store the row count. +% define loop macro for this column % \begin{macrocode} - \expandafter\newcount\csname dtlrows@#1\endcsname + \def\@dtl@forcolumn##1% before stuff + \db@col@id@w #3\db@col@id@end@% column index + \db@col@elt@w ##2\db@col@elt@end@% entry + \db@col@id@w #3\db@col@id@end@% column index + ##3% after stuff + \q@nil{% + \def#1{##2}% assign value to % \end{macrocode} -% Define count register used to store the column count. +% check if end of loop % \begin{macrocode} - \expandafter\newcount\csname dtlcols@#1\endcsname - }% -} + \ifx#1\@nnil + \let\@dtl@forcolnext=\@dtl@forcolnoop + \else % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\DTLcleardb} -%\begin{definition} -% \cs{DTLcleardb}\marg{db name} -%\end{definition} -% Clears the database. (Makes it empty, but still defined.) -%\changes{2.03}{2009 November 15}{new} +% do body of loop % \begin{macrocode} -\newcommand*{\DTLcleardb}[1]{% - \DTLifdbexists{#1}% - {% - \dtlforeachkey(\@dtl@key,\@dtl@col,\@dtl@type,\@dtl@head)\in{#1}\do - {% - \expandafter\let\csname dtl@ci@#1@\@dtl@key\endcsname\undefined + #4% + \let\@dtl@forcolnext=\@dtl@forcolumn + \fi +% \end{macrocode} +% repeat if necessary +% \begin{macrocode} + \@dtl@forcolnext##3\q@nil }% - \csname dtldb@#1\endcsname{}% - \csname dtlkeys@#1\endcsname{}% - \csname dtlrows@#1\endcsname=0\relax - \csname dtlcols@#1\endcsname=0\relax - }% - {% - \PackageError{Can't clear database `#1': - database doesn't exist}{}{}% - }% +% \end{macrocode} +% do loop +% \begin{macrocode} + \@dtl@forcolumn#2% + \db@col@id@w #3\db@col@id@end@% + \db@col@elt@w \@nil\db@col@elt@end@% + \db@col@id@w #3\db@col@id@end@\q@nil +% \end{macrocode} +% restore break function +% \begin{macrocode} + \let\dtlbreak\@dtl@oldbreak } % \end{macrocode} %\end{macro} -% -%\begin{macro}{\DTLdeletedb} -%\begin{definition} -% \cs{DTLdeletedb}\marg{db name} -%\end{definition} -% Deletes a database. -%\changes{2.03}{2009 November 15}{new} +%\begin{macro}{\@dtl@forcolnoop} % \begin{macrocode} -\newcommand*{\DTLdeletedb}[1]{% - \DTLifdbexists{#1}% - {% - \dtlforeachkey(\@dtl@key,\@dtl@col,\@dtl@type,\@dtl@head)\in{#1}\do - {% - \expandafter\let\csname dtl@ci@#1@\@dtl@key\endcsname\undefined - }% - \expandafter\let\csname dtldb@#1\endcsname\undefined - \expandafter\let\csname dtlkeys@#1\endcsname\undefined - \expandafter\let\csname dtlrows@#1\endcsname\undefined - \expandafter\let\csname dtlcols@#1\endcsname\undefined - }% - {% - \PackageError{Can't delete database `#1': - database doesn't exist}{}{}% - }% -} +\def\@dtl@forcolnoop#1\q@nil{} % \end{macrocode} %\end{macro} -% -%\begin{macro}{\DTLrowcount} -%\begin{definition} -% \cs{DTLrowcount}\marg{db name} -%\end{definition} -% The number of rows in the database called \meta{db name}. -% (Doesn't check if database exists.) + +%\begin{macro}{\dtlforeachlevel} +%\cs{DTLforeach} can only be nested up to three levels. +% \cs{dtlforeachlevel} keeps track of the current level. % \begin{macrocode} -\newcommand*{\DTLrowcount}[1]{% -\expandafter\number\csname dtlrows@#1\endcsname} +\newcount\dtlforeachlevel % \end{macrocode} %\end{macro} % -%\begin{macro}{\DTLcolumncount} -%\begin{definition} -% \cs{DTLcolumncount}\marg{db name} -%\end{definition} -% The number of columns in the database called \meta{db name}. -% (Doesn't check if database exists.) -%\changes{2.0}{2009 February 27}{new}% +% 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} -\newcommand*{\DTLcolumncount}[1]{% -\expandafter\number\csname dtlcols@#1\endcsname} +\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} -%\end{macro} % -%\begin{macro}{\DTLifdbempty} -%\begin{definition} -% \cs{DTLifdbempty}\marg{name}\marg{true part}\marg{false part} -%\end{definition} -% Check if named database is empty (i.e.\ no rows have been added). % \begin{macrocode} -\newcommand{\DTLifdbempty}[3]{% - \DTLifdbexists{#1}% - {\@DTLifdbempty{#1}{#2}{#3}}% - {\PackageError{Can't check if database `#1' is empty: - database doesn't exist}{}{}}% -} +\newcount\dtl@rowi +\newcount\dtl@rowii +\newcount\dtl@rowiii % \end{macrocode} -%\end{macro} -%\begin{macro}{\@DTLifdbempty} +% +% \begin{macrocode} +\newtoks\@dtl@curi +\newtoks\@dtl@previ +\newtoks\@dtl@nexti +\newtoks\@dtl@curii +\newtoks\@dtl@previi +\newtoks\@dtl@nextii +\newtoks\@dtl@curiii +\newtoks\@dtl@previii +\newtoks\@dtl@nextiii +% \end{macrocode} +% +%\begin{macro}{\DTLsaverowcount} %\begin{definition} -% \cs{@sDTLifdbempty}\marg{name}\marg{true part}\marg{false part} +%\cs{DTLsavelastrowcount}\marg{cmd} %\end{definition} -% Check if named existing database is empty. (No check performed -% to determine if the database exists.) -%\changes{2.0}{2009 February 27}{new} +% Stores the maximum row count for the last \cs{DTLforeach}. % \begin{macrocode} -\newcommand{\@DTLifdbempty}[3]{% - \expandafter\ifnum\csname dtlrows@#1\endcsname=0\relax - #2% +\newcommand*{\DTLsavelastrowcount}[1]{% +\ifnum\dtlforeachlevel>2\relax + \def#1{0}% +\else + \ifnum\dtlforeachlevel<0\relax + \def#1{0}% \else - #3% + \@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}{\DTLnewrow} -%\begin{definition} -% \cs{DTLnewrow}\marg{db name} -%\end{definition} -% Add a new row to named database. The starred version doesn't -% check for the existence of the database. +%\begin{environment}{DTLenvforeach} +% Environment form of \cs{DTLforeach} (contents are gathered, so +% verbatim can't be used). % \begin{macrocode} -\newcommand*{\DTLnewrow}{% - \@ifstar\@sDTLnewrow\@DTLnewrow +\newenvironment{DTLenvforeach}[3][\boolean{true}]% +{% + \def\@dtlenvforeach@args{[#1]{#2}{#3}}% + \long@collect@body\@do@dtlenvforeach +}% +{} +\newcommand{\@do@dtlenvforeach}[1]{% + \expandafter\@DTLforeach\@dtlenvforeach@args{#1}% } % \end{macrocode} -%\end{macro} +%\end{environment} % -%\begin{macro}{\@DTLnewrow} -%\begin{definition} -% \cs{@DTLnewrow}\marg{db name} -%\end{definition} -% Add a new row to named database. (Checks for the existance -% of the database.) +%\begin{environment}{DTLenvforeach*} +% Environment form of \cs{DTLforeach*} (contents are gathered, so +% verbatim can't be used). % \begin{macrocode} -\newcommand*{\@DTLnewrow}[1]{% -\DTLifdbexists{#1}% - {\@sDTLnewrow{#1}}% - {\PackageErrors{datatool}{Can't add new row to database `#1': - database doesn't exist}{}}% +\newenvironment{DTLenvforeach*}[3][\boolean{true}]% +{% + \def\s@dtlenvforeach@args{[#1]{#2}{#3}}% + \long@collect@body\@do@sdtlenvforeach +}% +{} +\newcommand{\@do@sdtlenvforeach}[1]{% + \expandafter\@sDTLforeach\s@dtlenvforeach@args{#1}% } % \end{macrocode} -%\end{macro} +%\end{environment} % -%\begin{macro}{\@sDTLnewrow} +%\begin{macro}{\DTLforeach} %\begin{definition} -% \cs{@DTLnewrow}\marg{db name} +% \cs{DTLforeach}\oarg{conditions}\marg{db name}\marg{values}\marg{text} %\end{definition} -% Add a new row to named existing database. (No check performed -% to determine if the database exists.) -%\changes{2.0}{2009 February 27}{new} -% \begin{macrocode} -\newcommand*{\@sDTLnewrow}[1]{% -% \end{macrocode} -% Increment row count. +% 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} - \global\advance\csname dtlrows@#1\endcsname by 1\relax +\newcommand*{\DTLforeach}{\@ifstar\@sDTLforeach\@DTLforeach} % \end{macrocode} -% Append an empty row to the database +%\end{macro} +% +%\begin{macro}{\@DTLforeach} +% \cs{@DTLforeach} is the unstarred version of \cs{DTLforeach}. +% The database is reconstructed to allow for rows to be edited. +% Use the starred version for faster access. +%\changes{2.0}{2009 February 27}{updated to use new database structure} % \begin{macrocode} - \toks@gput@right@cx{dtldb@#1}{% - \noexpand\db@row@elt@w% - \noexpand\db@row@id@w \number\csname dtlrows@#1\endcsname - \noexpand\db@row@id@end@% - \noexpand\db@row@id@w \number\csname dtlrows@#1\endcsname - \noexpand\db@row@id@end@% - \noexpand\db@row@elt@end@% - }% +\newcommand{\@DTLforeach}[4][\boolean{true}]{% % \end{macrocode} -% Display message on terminal and log file if in verbose mode. +% Check database exists % \begin{macrocode} - \dtl@message{New row added to database `#1'}% -} + \DTLifdbexists{#2}% + {% % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\dtlcolumnnum} -% Count register to keep track of column index. -%\changes{2.0}{2009 February 27}{new} +% Keep \sty{hyperref} happy % \begin{macrocode} -\newcount\dtlcolumnnum + \refstepcounter{DTLrow}% % \end{macrocode} -%\end{macro} -%\begin{macro}{\dtlrownum} -% Count register to keep track of row index. -%\changes{2.0}{2009 February 27}{new} +% Make it global (so that it works in tabular environment) % \begin{macrocode} -\newcount\dtlrownum + \global\c@DTLrow=\c@DTLrow\relax % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\DTLifhaskey} -%\begin{definition} -%\cs{DTLifhaskey}\meta{db name}\meta{key}\meta{true part}\meta{false -% part} -%\end{definition} -% Checks if the named database \meta{db name} has a column with label -% \meta{key}. If column exists, do \meta{true part} otherwise -% do \meta{false part}. The starred version doesn't check if -% the named database exists. -%\changes{2.0}{2009 February 27}{new} +% Store database name % \begin{macrocode} -\newcommand*{\DTLifhaskey}{\@ifstar\@sDTLifhaskey\@DTLifhaskey} + \gdef\@dtl@dbname{#2}% % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@DTLifhaskey} -% Unstarred version of \cs{DTLifhaskey} +% Increment level and check not exceeded 3 % \begin{macrocode} -\newcommand{\@DTLifhaskey}[4]{% - \DTLifdbexists{#1}% - {% - \@sDTLifhaskey{#1}{#2}{#3}{#4}% - }% - {% - \PackageError{datatool}{Database `#1' doesn't exist}{}% - }% -} + \global\advance\dtlforeachlevel by 1\relax + \ifnum\dtlforeachlevel>3\relax + \PackageError{datatool}{\string\DTLforeach\space nested too + deeply}{Only 3 levels are allowed}% + \else + \@DTLifdbempty{#2}% % \end{macrocode} -%\end{macro} -%\begin{macro}{\@sDTLifhaskey} -% Starred version of \cs{DTLifhaskey} +% Do nothing if database is empty % \begin{macrocode} -\newcommand{\@sDTLifhaskey}[4]{% - \@ifundefined{dtl@ci@#1@#2}% - {% + {}% + {% % \end{macrocode} -% Key not defined +% Set level dependent information (needs to be global to ensure +% it works in the \env{tabular} environment). Row counter: % \begin{macrocode} - #4% - }% - {% + \expandafter\global + \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname + = 0\relax % \end{macrocode} -% Key defined +% Store previous value of \cs{DTLiffirstrow} % \begin{macrocode} - #3% - }% -} + \expandafter\global\expandafter\let% + \csname @dtl@iffirstrow\the\dtlforeachlevel\endcsname + \DTLiffirstrow % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\DTLgetcolumnindex} -%\begin{definition} -%\cs{DTLgetcolumnindex}\marg{cs}\marg{db}\marg{key} -%\end{definition} -% Gets index for column with label \meta{key} from database -% \meta{db} and stores in \meta{cs} which must be a control -% sequence. -% Unstarred version checks if database and key exist, unstarred -% version doesn't perform any checks. -%\changes{2.0}{2009 February 27}{new} +% Define current \cs{DTLiffirstrow} % \begin{macrocode} -\newcommand*{\DTLgetcolumnindex}{% - \@ifstar\@sdtl@getcolumnindex\@dtl@getcolumnindex -} + \gdef\DTLiffirstrow##1##2{% + \expandafter\ifnum + \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname + =1\relax + ##1% + \else + ##2% + \fi}% % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@dtl@getcolumnindex} -% Unstarred version of \cs{DTLgetcolumnindex} -%\changes{2.0}{2009 February 27}{new} +% Store previous value of \cs{DTLiflastrow} % \begin{macrocode} -\newcommand*{\@dtl@getcolumnindex}[3]{% + \expandafter\global\expandafter\let% + \csname @dtl@iflastrow\the\dtlforeachlevel\endcsname + \DTLiflastrow % \end{macrocode} -% Check if database exists. +% Define current \cs{DTLiflastrow} % \begin{macrocode} - \DTLifdbexists{#2}% - {% + \gdef\DTLiflastrow##1##2{% + \expandafter\ifnum + \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname + =\csname dtlcols@#2\endcsname\relax + ##1% + \else + ##2% + \fi}% % \end{macrocode} -% Database exists. Now check if key exists. +% Store previous value of \cs{DTLifoddrow} % \begin{macrocode} - \@sDTLifhaskey{#2}{#3}% - {% + \expandafter\global\expandafter\let% + \csname @dtl@ifoddrow\the\dtlforeachlevel\endcsname + \DTLifoddrow % \end{macrocode} -% Key exists so go ahead and get column index. +% Define current \cs{DTLifoddrow} % \begin{macrocode} - \@sdtl@getcolumnindex{#1}{#2}{#3}% - }% - {% + \gdef\DTLifoddrow##1##2{% + \expandafter\ifodd + \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname + ##1% + \else + ##2% + \fi}% % \end{macrocode} -% Key doesn't exists in named database. +% Store data base name for current level % \begin{macrocode} - \PackageError{datatool}{Database `#2' doesn't contain - key `#3'}{}% - }% - }% - {% + \expandafter\global\expandafter\let + \csname @dtl@dbname@\romannumeral\dtlforeachlevel\endcsname + =\@dtl@dbname % \end{macrocode} -% Named database doesn't exist. +% Mark it as not read only % \begin{macrocode} - \PackageError{datatool}{Database `#2' doesn't exist}{}% - }% -} + \expandafter\global\expandafter\let + \csname @dtl@ro@\romannumeral\dtlforeachlevel\endcsname + = 0\relax % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@dtl@getcolumnindex} -% Starred version of \cs{DTLgetcolumnindex}. -%\changes{2.0}{2009 February 27}{new} +% Loop through each row. +% Loop counter given by \cs{dtl@row}\meta{level} % \begin{macrocode} -\newcommand*{\@sdtl@getcolumnindex}[3]{% - \expandafter\let\expandafter#1\csname dtl@ci@#2@#3\endcsname -} + \dtlgforint + \csname dtl@row\romannumeral\dtlforeachlevel\endcsname + =1\to\csname dtlrows@#2\endcsname\step1\do + {% % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\dtlcolumnindex} -%\begin{definition} -% \cs{dtlcolumnindex}\marg{db}\marg{key} -%\end{definition} -% Column index corresponding to \meta{key} in database \meta{db}. -% (No check for existance of database or key.) -%\changes{2.0}{2009 February 27}{new} -%\changes{2.03}{2009 November 15}{renamed \cs{dtl@columnindex} to -%\cs{dtlcolumnindex}} +% Get current row from the data base % \begin{macrocode} -\newcommand*{\dtlcolumnindex}[2]{% - \csname dtl@ci@#1@#2\endcsname -} + \@dtl@tmpcount= + \csname dtl@row\romannumeral\dtlforeachlevel\endcsname + \edef\dtl@dogetrow{\noexpand\dtlgetrow{#2}% + {\number\@dtl@tmpcount}}% + \dtl@dogetrow % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\DTLgetkeyforcolumn} -%\begin{definition} -%\cs{DTLgetkeyforcolumn}\marg{key cs}\marg{db}\marg{column index} -%\end{definition} -% Gets the key associated with the given column index and stores -% in \meta{key cs}. Unstarred version doesn't perform checks. +% Store the current row for this level % \begin{macrocode} -\newcommand*{\DTLgetkeyforcolumn}{% - \@ifstar\@sdtlgetkeyforcolumn\@dtlgetkeyforcolumn} + \expandafter\global + \csname @dtl@cur\romannumeral\dtlforeachlevel\endcsname + = \dtlcurrentrow % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@dtlgetkeyforcolumn} +% Store the previous rows for this level % \begin{macrocode} -\newcommand*{\@dtlgetkeyforcolumn}[3]{% - \DTLifdbexists{#2}% - {% + \expandafter\global + \csname @dtl@prev\romannumeral\dtlforeachlevel\endcsname + = \dtlbeforerow % \end{macrocode} -% Check if index is in range. +% Store the subsequent rows for this level % \begin{macrocode} - \ifnum#3<1\relax - \PackageError{datatool}{Invalid column index \number#3}{% - Column indices start at 1}% - \else - \expandafter\ifnum\csname dtlcols@#2\endcsname<#3\relax - \PackageError{datatool}{Index \number#3\space out of - range for database `#2'}{Database `#2' only has - \expandafter\number\csname dtlcols@#2\endcsname\space - columns}% - \else - \@sdtlgetkeyforcolumn{#1}{#2}{#3}% - \fi - \fi - }% - {% - \PackageError{datatool}{Database `#2' doesn't exists}{}% - }% -} + \expandafter\global + \csname @dtl@next\romannumeral\dtlforeachlevel\endcsname + = \dtlafterrow % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@sdtlgetkeyforcolumn} -%\begin{definition} -%\cs{@sdtlgetkeyforcolumn}\marg{key cs}\marg{db}\marg{column index} -%\end{definition} -% Gets the key associated with the given column index and stores -% in \meta{key cs} +% Assign commands to the required entries % \begin{macrocode} -\newcommand*{\@sdtlgetkeyforcolumn}[3]{% - \edef\@dtl@dogetkeyforcolumn{\noexpand\@dtl@getkeyforcolumn - {\noexpand#1}{#2}{\number#3}}% - \@dtl@dogetkeyforcolumn -} + \ifx\relax#3\relax + \else + \@dtl@assign{#3}{#2}% + \fi % \end{macrocode} -%\end{macro} -%\begin{macro}{\@dtl@getkeyforcolumn} -% Column index must be fully expanded before use. +% Do the main body of text if condition is satisfied % \begin{macrocode} -\newcommand*{\@dtl@getkeyforcolumn}[3]{% - \def\@dtl@get@keyforcolumn##1% before stuff - \db@plist@elt@w% start of block - \db@col@id@w #3\db@col@id@end@% index - \db@key@id@w ##2\db@key@id@end@% key - \db@type@id@w ##3\db@type@id@end@% data type - \db@header@id@w ##4\db@header@id@end@% header - \db@col@id@w #3\db@col@id@end@% index - \db@plist@elt@end@% end of block - ##5\q@nil{\def#1{##2}}% - \edef\@dtl@tmp{\expandafter\the\csname dtldb@#2\endcsname}% - \expandafter\@dtl@getkeyforcolumn\@dtl@tmp - \db@plist@elt@w% start of block - \db@col@id@w #3\db@col@id@end@ index - \db@key@id@w \@nil\db@key@id@end@% key - \db@type@id@w \db@type@id@end@% data type - \db@header@id@w \db@header@id@end@% header - \db@col@id@w #3\db@col@id@end@% index - \db@plist@elt@end@% end of block - \q@nil -} + \ifthenelse{#1}% + {% % \end{macrocode} -%\end{macro} -% -% Define some commands to indicate the various data types a database -% may contain. -%\begin{macro}{\DTLunsettype} -% Unknown data type. (All entries in the column are blank so the -% type can't be determined.) -%\changes{2.0}{2009 February 27}{new} +% Increment user row counter % \begin{macrocode} -\def\DTLunsettype{} + \refstepcounter{DTLrow\romannumeral\dtlforeachlevel}% + \expandafter\edef\expandafter\DTLcurrentindex% + \expandafter{% + \arabic{DTLrow\romannumeral\dtlforeachlevel}}% + #4% % \end{macrocode} -%\end{macro} -%\begin{macro}{\DTLstringtype} -% Data type representing strings. -%\changes{2.0}{2009 February 27}{new} +% Has this row been marked for deletion? % \begin{macrocode} -\def\DTLstringtype{0} + \edef\@dtl@tmp{\expandafter\the + \csname @dtl@cur\romannumeral + \dtlforeachlevel\endcsname}% + \ifx\@dtl@tmp\@nnil % \end{macrocode} -%\end{macro} -%\begin{macro}{\DTLinttype} -% Data type representing integers. -%\changes{2.0}{2009 February 27}{new} +% Row needs to be deleted +% Decrement row indices for rows with a higher index than this one % \begin{macrocode} -\def\DTLinttype{1} + \expandafter\dtl@decrementrows\expandafter + {\csname @dtl@prev\romannumeral + \dtlforeachlevel\endcsname + }{\csname dtl@row\romannumeral + \dtlforeachlevel\endcsname}% + \expandafter\dtl@decrementrows\expandafter + {\csname @dtl@next\romannumeral + \dtlforeachlevel\endcsname + }{\csname dtl@row\romannumeral + \dtlforeachlevel\endcsname}% % \end{macrocode} -%\end{macro} -%\begin{macro}{\DTLrealtype} -% Data type representing real numbers. -%\changes{2.0}{2009 February 27}{new} +% Reconstruct data base without this row % \begin{macrocode} -\def\DTLrealtype{2} + \edef\@dtl@tmp{% + \expandafter\the + \csname @dtl@prev\romannumeral + \dtlforeachlevel\endcsname + \expandafter\the + \csname @dtl@next\romannumeral + \dtlforeachlevel\endcsname + }% + \expandafter\global\expandafter + \csname dtldb@#2\endcsname\expandafter{\@dtl@tmp}% % \end{macrocode} -%\end{macro} -%\begin{macro}{\DTLcurrencytype} -% Data type representing currency. -%\changes{2.0}{2009 February 27}{new} +% Decrement the row count for this database: % \begin{macrocode} -\def\DTLcurrencytype{3} + \expandafter\global\expandafter + \advance\csname dtlrows@#2\endcsname by -1\relax % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\DTLgetdatatype} -%\begin{definition} -%\cs{DTLgetdatatype}\marg{cs}\marg{db}\marg{key} -%\end{definition} -% Gets data type associated with column labelled \meta{key} in -% database \meta{db} and stores in \meta{cs}. Type may be: -% \meta{empty} (unset), 0 (string), 1 (int), -% 2 (real), 3 (currency). Unstarred version checks if the database -% and key exist, starred version doesn't. -%\changes{2.0}{2009 February 27}{new} +% Decrement the counter for this loop % \begin{macrocode} -\newcommand*{\DTLgetdatatype}{% - \@ifstar\@sdtlgetdatatype\@dtlgetdatatype -} + \expandafter\global\expandafter + \advance\csname dtl@row\romannumeral + \dtlforeachlevel\endcsname by -1\relax + \else % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@dtlgetdatatype} -% Unstarred version of \cs{DTLgetdatatype}. -%\changes{2.0}{2009 February 27}{new} +% Reconstruct data base % \begin{macrocode} -\newcommand*{\@dtlgetdatatype}[3]{% + \@dtl@before=\csname @dtl@prev\romannumeral + \dtlforeachlevel\endcsname + \@dtl@after=\csname @dtl@next\romannumeral + \dtlforeachlevel\endcsname + \toks@gconcat@middle@cx{dtldb@#2}% + {\@dtl@before}% + {% % \end{macrocode} -% Check if database exists. +% This row % \begin{macrocode} - \DTLifdbexists{#2}% - {% + \noexpand\db@row@elt@w% + \noexpand\db@row@id@w \expandafter\number + \csname dtl@row\romannumeral + \dtlforeachlevel\endcsname + \noexpand\db@row@id@end@% + \expandafter\the + \csname @dtl@cur\romannumeral + \dtlforeachlevel\endcsname + \noexpand\db@row@id@w \expandafter\number + \csname dtl@row\romannumeral + \dtlforeachlevel\endcsname + \noexpand\db@row@id@end@% + \noexpand\db@row@elt@end@% + }% + {\@dtl@after}% + \fi + }% % \end{macrocode} -% Check if key exists in this database. +% Condition not met so ignore % \begin{macrocode} - \@sDTLifhaskey{#2}{#3}% - {% + {}% + }% % \end{macrocode} -% Get data type for this database and key. +% Restore previous value of \cs{DTLiffirstrow} % \begin{macrocode} - \@sdtlgetdatatype{#1}{#2}{#3}% - }% - {% + \expandafter\global\expandafter\let\expandafter\DTLiffirstrow + \csname @dtl@iffirstrow\the\dtlforeachlevel\endcsname % \end{macrocode} -% Key doesn't exist in this database. +% Restore previous value of \cs{DTLiflastrow} % \begin{macrocode} - \PackageError{datatool}{Key `#3' undefined in database `#2'}{}% - }% + \expandafter\global\expandafter\let\expandafter\DTLiflastrow + \csname @dtl@iflastrow\the\dtlforeachlevel\endcsname +% \end{macrocode} +% Restore previous value of \cs{DTLifoddrow} +% \begin{macrocode} + \expandafter\global\expandafter\let\expandafter\DTLifoddrow + \csname @dtl@ifoddrow\the\dtlforeachlevel\endcsname + }% + \fi +% \end{macrocode} +% Decrement level +% \begin{macrocode} + \global\advance\dtlforeachlevel by -1\relax }% - {% % \end{macrocode} -% Database doesn't exist. +% else part (data base doesn't exist): % \begin{macrocode} + {% \PackageError{datatool}{Database `#2' doesn't exist}{}% }% } % \end{macrocode} %\end{macro} % -%\begin{macro}{\@sdtlgetdatatype} -% Starred version of \cs{DTLgetdatatype}. This ensures that -% the key is fully expanded before begin passed to -% \cs{@dtl@getdatatype}. -%\changes{2.0}{2009 February 27}{new} +%\begin{macro}{\@sDTLforeach} +% \cs{@sDTLforeach} is the starred version of \cs{DTLforeach}. +% The database rows can't be edited. +%\changes{2.0}{2009 February 27}{updated to use new database structure} % \begin{macrocode} -\newcommand*{\@sdtlgetdatatype}[3]{% - \edef\@dtl@dogetdata{\noexpand\@dtl@getdatatype{\noexpand#1}% - {\expandafter\the\csname dtlkeys@#2\endcsname}% - {\dtlcolumnindex{#2}{#3}}}% - \@dtl@dogetdata -} +\newcommand{\@sDTLforeach}[4][\boolean{true}]{% % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@dtl@getdatatype} -%\begin{definition} -%\cs{@dtl@getdatatype}\marg{cs}\marg{data specs}\marg{column index} -%\end{definition} -% Column index must be expanded. -%\changes{2.0}{2009 February 27}{new} +% Check database exists % \begin{macrocode} -\newcommand*{\@dtl@getdatatype}[3]{% - \def\@dtl@get@keydata##1% stuff before - \db@plist@elt@w% start of key block - \db@col@id@w #3\db@col@id@end@% column index - \db@key@id@w ##2\db@key@id@end@% key id - \db@type@id@w ##3\db@type@id@end@% data type - \db@header@id@w ##4\db@header@id@end@% header - \db@col@id@w #3\db@col@id@end@% column index - \db@plist@elt@end@% end of key block - ##5% stuff afterwards - \q@nil{\def#1{##3}}% - \@dtl@get@keydata#2\q@nil -} + \DTLifdbexists{#2}% + {% % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@dtl@getprops} -%\begin{definition} -%\cs{@dtl@getprops}\marg{key cs}\marg{type cs}\marg{header toks}\marg{before toks}\marg{after toks}\marg{data specs}\marg{column index} -%\end{definition} -% Column index must be expanded. -%\changes{2.0}{2009 February 27}{new} +% Keep \sty{hyperref} happy % \begin{macrocode} -\newcommand*{\@dtl@getprops}[7]{% - \def\@dtl@get@keydata##1% stuff before - \db@plist@elt@w% start of key block - \db@col@id@w #7\db@col@id@end@% column index - \db@key@id@w ##2\db@key@id@end@% key id - \db@type@id@w ##3\db@type@id@end@% data type - \db@header@id@w ##4\db@header@id@end@% header - \db@col@id@w #7\db@col@id@end@% column index - \db@plist@elt@end@% end of key block - ##5% stuff afterwards - \q@nil{% - \def#1{##2}% key - \def#2{##3}% data type - #3={##4}% header - #4={##1}% before stuff - #5={##5}% after stuff - }% - \@dtl@get@keydata#6\q@nil -} + \refstepcounter{DTLrow}% % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@dtl@before} -%\changes{2.0}{2009 February 27}{new} +% Make it global (so that it works in tabular environment) % \begin{macrocode} -\newtoks\@dtl@before + \global\c@DTLrow=\c@DTLrow % \end{macrocode} -%\end{macro} -%\begin{macro}{\@dtl@after} -%\changes{2.0}{2009 February 27}{new} +% Increment level and check not exceeded 3 % \begin{macrocode} -\newtoks\@dtl@after + \global\advance\dtlforeachlevel by 1\relax + \ifnum\dtlforeachlevel>3\relax + \PackageError{datatool}{\string\DTLforeach\space nested too + deeply}{Only 3 levels are allowed}% + \else + \@DTLifdbempty{#2}% % \end{macrocode} -%\end{macro} -%\begin{macro}{\@dtl@colhead} -%\changes{2.0}{2009 February 27}{new} +% Do nothing if database is empty % \begin{macrocode} -\newtoks\@dtl@colhead + {}% + {% % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@dtl@updatekeys} -%\begin{definition} -%\cs{@dtl@updatekeys}\marg{db}\marg{key}\marg{value} -%\end{definition} -% Adds key to database's key list if it doesn't exist. -% The value is used to update the data type associated with that key. -% Key must be fully expanded. Doesn't check if database exists. -%\changes{2.0}{2009 February 27}{new} +% Set level dependent information (needs to be global to ensure +% it works in the \env{tabular} environment). Row counter: % \begin{macrocode} -\newcommand*{\@dtl@updatekeys}[3]{% + \expandafter\global + \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname + = 0\relax % \end{macrocode} -% Check if key already exists +% Store previous value of \cs{DTLiffirstrow} % \begin{macrocode} - \@sDTLifhaskey{#1}{#2}% - {% + \expandafter\global\expandafter\let% + \csname @dtl@iffirstrow\the\dtlforeachlevel\endcsname + \DTLiffirstrow % \end{macrocode} -% Key exists, may need to update data type. First get the -% column index. +% Define current \cs{DTLiffirstrow} % \begin{macrocode} - \expandafter\dtlcolumnnum\expandafter - =\dtlcolumnindex{#1}{#2}\relax + \gdef\DTLiffirstrow##1##2{% + \expandafter\ifnum + \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname + =1\relax + ##1% + \else + ##2% + \fi}% % \end{macrocode} -% Get the properties for this column +% Store previous value of \cs{DTLiflastrow} % \begin{macrocode} - \edef\@dtl@dogetprops{\noexpand\@dtl@getprops - {\noexpand\@dtl@key}{\noexpand\@dtl@type}% - {\noexpand\@dtl@colhead}{\noexpand\@dtl@before}% - {\noexpand\@dtl@after}{\the\csname dtlkeys@#1\endcsname}% - {\number\dtlcolumnnum}} - \@dtl@dogetprops + \expandafter\global\expandafter\let% + \csname @dtl@iflastrow\the\dtlforeachlevel\endcsname + \DTLiflastrow % \end{macrocode} -% Is the value empty? +% Define current \cs{DTLiflastrow} % \begin{macrocode} - \def\@dtl@tmp{#3}% - \ifx\@dtl@tmp\@empty + \gdef\DTLiflastrow##1##2{% + \expandafter\ifnum + \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname + =\csname dtlcols@#2\endcsname\relax + ##1% + \else + ##2% + \fi}% % \end{macrocode} -% Leave data type as it is +% Store previous value of \cs{DTLifoddrow} % \begin{macrocode} - \else + \expandafter\global\expandafter\let% + \csname @dtl@ifoddrow\the\dtlforeachlevel\endcsname + \DTLifoddrow % \end{macrocode} -% Make a copy of current data type +% Define current \cs{DTLifoddrow} % \begin{macrocode} - \let\@dtl@oldtype\@dtl@type + \gdef\DTLifoddrow##1##2{% + \expandafter\ifodd + \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname + ##1% + \else + ##2% + \fi}% % \end{macrocode} -% Check the data type for this entry (stored in \cs{@dtl@datatype}) +% Store data base name for current level % \begin{macrocode} - \@dtl@checknumerical{#3}% + \expandafter\gdef\csname @dtl@dbname@\romannumeral + \dtlforeachlevel\endcsname{#2}% % \end{macrocode} -% If this column currently has no data type assigned to it -% then use the new type. +% Mark it as read only % \begin{macrocode} - \ifx\@dtl@type\@empty - \edef\@dtl@type{\number\@dtl@datatype}% - \else + \expandafter\global\expandafter\let + \csname @dtl@ro@\romannumeral\dtlforeachlevel\endcsname + = 1\relax % \end{macrocode} -% This column already has an associated data type but it may -% need updating. +% Iterate through each row. % \begin{macrocode} - \ifcase\@dtl@datatype % string + \@dtlforeachrow(\dtl@thisidx,\dtl@thisrow)\in{#2}\do% + {% % \end{macrocode} -% String overrides all other types +% Assign row number (not sure if this is needed here) % \begin{macrocode} - \def\@dtl@type{0}% - \or % int + \csname dtl@row\romannumeral\dtlforeachlevel\endcsname + = \dtl@thisidx\relax % \end{macrocode} -% All other types override int, so leave it as it is +% Store the current row specs for this level % \begin{macrocode} - \or % real + \expandafter\global + \csname @dtl@cur\romannumeral\dtlforeachlevel\endcsname + = \expandafter{\dtl@thisrow}% % \end{macrocode} -% Real overrides int, but not currency or string +% Assign commands to the required entries % \begin{macrocode} - \ifnum\@dtl@type=1\relax - \def\@dtl@type{2}% - \fi - \or % currency + \ifx\relax#3\relax + \else % \end{macrocode} -% Currency overrides int and real but not string +% Need to set \cs{dtlcurrentrow} for \cs{@dtl@assign} % \begin{macrocode} - \ifnum\@dtl@type>0\relax - \def\@dtl@type{3}% + \dtlcurrentrow=\expandafter{\dtl@thisrow}% + \@dtl@assign{#3}{#2}% \fi - \fi - \fi % \end{macrocode} -% Has the data type been updated? +% Do the main body of text if condition is satisfied % \begin{macrocode} - \ifx\@dtl@oldtype\@dtl@type + \ifthenelse{#1}% + {% % \end{macrocode} -% No change needed +% Increment user row counter % \begin{macrocode} - \else + \refstepcounter{DTLrow\romannumeral\dtlforeachlevel}% + \expandafter\edef\expandafter\DTLcurrentindex% + \expandafter{% + \arabic{DTLrow\romannumeral\dtlforeachlevel}}% + #4% + }% % \end{macrocode} -% Update required +% Condition not met so ignore % \begin{macrocode} - \toks@gconcat@middle@cx{dtlkeys@#1}% - {\@dtl@before}% - {% - \noexpand\db@plist@elt@w% start of key block - \noexpand\db@col@id@w \the\dtlcolumnnum - \noexpand\db@col@id@end@% column index - \noexpand\db@key@id@w #2\noexpand\db@key@id@end@% key id - \noexpand\db@type@id@w \@dtl@type - \noexpand\db@type@id@end@% data type - \noexpand\db@header@id@w \the\@dtl@colhead - \noexpand\db@header@id@end@% header - \noexpand\db@col@id@w \the\dtlcolumnnum - \noexpand\db@col@id@end@% column index - \noexpand\db@plist@elt@end@% end of key block - }% - {\@dtl@after}% - \fi - \fi - }% - {% + {}% + }% % \end{macrocode} -% Key doesn't exist. Increment column count. +% Restore previous value of \cs{DTLiffirstrow} % \begin{macrocode} - \expandafter\global\expandafter\advance - \csname dtlcols@#1\endcsname by 1\relax - \dtlcolumnnum=\csname dtlcols@#1\endcsname\relax + \expandafter\global\expandafter\let\expandafter\DTLiffirstrow + \csname @dtl@iffirstrow\the\dtlforeachlevel\endcsname % \end{macrocode} -% Set column index for this key +% Restore previous value of \cs{DTLiflastrow} % \begin{macrocode} - \expandafter\xdef\csname dtl@ci@#1@#2\endcsname{% - \number\dtlcolumnnum}% + \expandafter\global\expandafter\let\expandafter\DTLiflastrow + \csname @dtl@iflastrow\the\dtlforeachlevel\endcsname % \end{macrocode} -% Get data type for this entry (stored in \cs{@dtl@datatype}) +% Restore previous value of \cs{DTLifoddrow} % \begin{macrocode} - \def\@dtl@tmp{#3}% - \ifx\@dtl@tmp\@empty - \edef\@dtl@type{}% don't know data type yet - \else - \@dtl@checknumerical{#3}% - \edef\@dtl@type{\number\@dtl@datatype}% + \expandafter\global\expandafter\let\expandafter\DTLifoddrow + \csname @dtl@ifoddrow\the\dtlforeachlevel\endcsname + }% \fi % \end{macrocode} -% Append to property list +% Decrement level % \begin{macrocode} - \toks@gput@right@cx{dtlkeys@#1}% - {% - \noexpand\db@plist@elt@w - \noexpand\db@col@id@w \the\dtlcolumnnum - \noexpand\db@col@id@end@ - \noexpand\db@key@id@w #2\noexpand\db@key@id@end@ - \noexpand\db@type@id@w \@dtl@type - \noexpand\db@type@id@end@ - \noexpand\db@header@id@w #2\noexpand\db@header@id@end@ - \noexpand\db@col@id@w \the\dtlcolumnnum - \noexpand\db@col@id@end@ - \noexpand\db@plist@elt@end@ - }% + \global\advance\dtlforeachlevel by -1\relax + }% +% \end{macrocode} +% else part (data base doesn't exist): +% \begin{macrocode} + {% + \PackageError{datatool}{Database `#2' doesn't exist}{}% }% } % \end{macrocode} %\end{macro} % -%\begin{macro}{\DTLsetheader} +%\begin{macro}{\@dtlifreadonly} %\begin{definition} -%\cs{DTLsetheader}\marg{db}\marg{key}\marg{header} +%\cs{@dtlifreadonly}\marg{true part}\marg{false part} %\end{definition} -% Sets header for column given by \meta{key} in database \meta{db}. -% Starred version doesn't check for existance of database or key. +% Checks if current loop level is read only +%\changes{2.0}{2009 February 27}{new} % \begin{macrocode} -\newcommand*{\DTLsetheader}{\@ifstar\@sDTLsetheader\@DTLsetheader} +\newcommand*{\@dtlifreadonly}[2]{% + \expandafter\ifx + \csname @dtl@ro@\romannumeral\dtlforeachlevel\endcsname1\relax % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@DTLsetheader} -% Unstarred version -% \begin{macrocode} -\newcommand*{\@DTLsetheader}[3]{% -% \end{macrocode} -% Check if database exists -% \begin{macrocode} - \DTLifdbexists{#1}% - {% -% \end{macrocode} -% Check if key exists. +% Read only % \begin{macrocode} - \@sDTLifhaskey{#1}{#2}% - {% - \@sDTLsetheader{#1}{#2}{#3}% - }% - {% - \PackageError{datatool}{Database `#1' doesn't contain key - `#2'}{}% - }% - }% - {% - \PackageError{datatool}{Database `#1' doesn't exist}{}% - }% -} + #1% + \else % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@sDTLsetheader} -% Starred version +% Not read only % \begin{macrocode} -\newcommand*{\@sDTLsetheader}[3]{% - \expandafter\dtlcolumnnum\expandafter - =\dtlcolumnindex{#1}{#2}\relax - \@dtl@setheaderforindex{#1}{\dtlcolumnnum}{#3}% + #2% + \fi } % \end{macrocode} %\end{macro} % -%\begin{macro}{\@dtl@setheaderforindex} +%\begin{macro}{\DTLappendtorow} %\begin{definition} -%\cs{@dtl@setheaderforindex}\marg{db}\marg{column index}\marg{header} +%\cs{DTLappendtorow}\marg{key}\marg{value} %\end{definition} -% Sets the header for column given by \meta{column index} in -% database \meta{db}. The header must be expanded. -% \begin{macrocode} -\newcommand*{\@dtl@setheaderforindex}[3]{% -% \end{macrocode} -% Get the properties for this column +% Appends entry to current row. (The current row is given by +% \cs{@dtl@cur}\meta{n} where \meta{n} is roman +% numeral value of \cs{dtlforeachlevel}. +% One level expansion is applied to \meta{value}. +%\changes{2.0}{2009 February 27}{updated to use new database structure} % \begin{macrocode} - \edef\@dtl@dogetprops{\noexpand\@dtl@getprops - {\noexpand\@dtl@key}{\noexpand\@dtl@type}% - {\noexpand\@dtl@colhead}{\noexpand\@dtl@before}% - {\noexpand\@dtl@after}{\the\csname dtlkeys@#1\endcsname}% - {\number#2}} - \@dtl@dogetprops +\newcommand*{\DTLappendtorow}[2]{% + \ifnum\dtlforeachlevel=0\relax + \PackageError{datatool}{\string\DTLappendrow\space can only be + used inside \string\DTLforeach}{}% + \else % \end{macrocode} -% Store the header in \cs{@dtl@toks} +% Set \cs{@dtl@thisdb} to the current database name: % \begin{macrocode} - \@dtl@colhead={#3}% + \expandafter\let\expandafter\@dtl@thisdb + \csname @dtl@dbname@\romannumeral\dtlforeachlevel\endcsname % \end{macrocode} -% Reconstruct property list +% Check this isn't in \cs{DTLforeach*} % \begin{macrocode} - \edef\@dtl@colnum{\number#2}\relax - \toks@gconcat@middle@cx{dtlkeys@#1}% - {\@dtl@before}% - {% - \noexpand\db@plist@elt@w% start of block - \noexpand\db@col@id@w \@dtl@colnum - \noexpand\db@col@id@end@% index - \noexpand\db@key@id@w \@dtl@key\noexpand\db@key@id@end@% key - \noexpand\db@type@id@w \@dtl@type - \noexpand\db@type@id@end@% data type - \noexpand\db@header@id@w \the\@dtl@colhead - \noexpand\db@header@id@end@% header - \noexpand\db@col@id@w \@dtl@colnum - \noexpand\db@col@id@end@% index - \noexpand\db@plist@elt@end@% end of block - }% - {\@dtl@after}% -} + \@dtlifreadonly + {% + \PackageError{datatool}{\string\DTLappendtorow\space can't + be used inside \DTLforeach*}{The starred version of + \string\DTLforeach\space is read only}% + }% + {% % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\dtlexpandnewvalue} -% Expand new value before adding to database +% Store current row number in \cs{dtlrownum} % \begin{macrocode} -\newcommand*{\dtlexpandnewvalue}{% - \def\@dtl@setnewvalue##1{\protected@edef\@dtl@tmp{##1}% - \expandafter\@dtl@toks\expandafter{\@dtl@tmp}}% -} + \dtlrownum= + \csname dtl@row\romannumeral\dtlforeachlevel\endcsname\relax % \end{macrocode} -%\end{macro} -%\begin{macro}{\dtlnoexpandnewvalue} -% Don't expand new value before adding to database +% Update information about this column (adding new column if +% necessary) % \begin{macrocode} -\newcommand*{\dtlnoexpandnewvalue}{% - \def\@dtl@setnewvalue##1{\@dtl@toks{##1}}% -} + \@dtl@updatekeys{\@dtl@thisdb}{#1}{#2}% % \end{macrocode} -% Do this by default: +% Get column index and store in \cs{dtlcolumnnum} % \begin{macrocode} -\dtlnoexpandnewvalue + \expandafter\dtlcolumnnum\expandafter + =\dtlcolumnindex{\@dtl@thisdb}{#1}\relax % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\DTLnewdbentry} -%\begin{definition} -% \cs{DTLnewdbentry}\marg{db name}\marg{id}\marg{value}. -%\end{definition} -% Adds an entry to the last row (adds new row if database is empty) -% and updates general column information if necessary. The -% starred version doesn't check if the database exists. +% Set \cs{dtlcurrentrow} to the current row % \begin{macrocode} -\newcommand{\DTLnewdbentry}{% - \@ifstar\@sDTLnewdbentry\@DTLnewdbentry -} + \dtlcurrentrow = + \csname @dtl@cur\romannumeral\dtlforeachlevel\endcsname % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@DTLnewdbentry} -% Unstarred version of \cs{DTLnewdbentry}. +% Does this row already have an entry with this key? % \begin{macrocode} -\newcommand{\@DTLnewdbentry}[3]{% - \DTLifdbexists{#1}% - {\@sDTLnewdbentry{#1}{#2}{#3}}% - {\PackageError{datatool}{Can't add new entry to database `#1': - database doesn't exist}{}}% -} + \edef\dtl@dogetentry{\noexpand\dtlgetentryfromcurrentrow + {\noexpand\dtl@entry}{\number\dtlcolumnnum}% + }% + \dtl@dogetentry + \ifx\dtl@entry\dtlnovalue % \end{macrocode} -%\end{macro} -%\begin{macro}{\@sDTLnewdbentry} -% Starred version of \cs{DTLnewdbentry} (doesn't check if the database exists). +% There are no entries in this row for the given key. +% Expand entry value before storing. +%\changes{2.03}{2009 November 15}{value expanded before storing} % \begin{macrocode} -\newcommand*{\@sDTLnewdbentry}[3]{% + \protected@edef\@dtl@tmp{#2}% + \expandafter\@dtl@toks\expandafter{\@dtl@tmp}% % \end{macrocode} -% Update key list +% Append this entry to the current row. % \begin{macrocode} - \@dtl@updatekeys{#1}{#2}{#3}% + \toks@gput@right@cx{@dtl@cur\romannumeral\dtlforeachlevel}% + {% + \noexpand\db@col@id@w \number\dtlcolumnnum + \noexpand\db@col@id@end@ + \noexpand\db@col@elt@w \the\@dtl@toks + \noexpand\db@col@elt@end@ + \noexpand\db@col@id@w \number\dtlcolumnnum + \noexpand\db@col@id@end@ + }% % \end{macrocode} -% Get the column index +% Print information to terminal and log file if in verbose mode. % \begin{macrocode} - \expandafter\dtlcolumnnum\expandafter - =\dtlcolumnindex{#1}{#2}\relax + \dtl@message{Appended #1\space -> #2\space to database + `\@dtl@thisdb'}% + \else % \end{macrocode} -% Get the current row: +% There is already an entry in this row for the given key % \begin{macrocode} - \edef\dtl@dogetrow{\noexpand\dtlgetrow{#1}% - {\number\csname dtlrows@#1\endcsname}}% - \dtl@dogetrow + \PackageError{datatool}{Can't append entry to row: + there is already an entry for key `#1' in this row}{}% + \fi + }% + \fi +} % \end{macrocode} -% Check if this row already has an entry for the given column. +%\end{macro} +% +%\begin{macro}{\DTLremoveentryfromrow} +%\begin{definition} +%\cs{DTLremoveentryfromrow}\marg{key} +%\end{definition} +% Removes entry given by \meta{key} from current row. +% (The current row is given by +% \cs{@dtl@cur}\meta{n} where \meta{n} is roman +% numeral value of \cs{dtlforeachlevel}. +%\changes{2.0}{2009 February 27}{updated to use new database structure} % \begin{macrocode} - \edef\dtl@dogetentry{\noexpand\dtlgetentryfromcurrentrow - {\noexpand\dtl@entry}{\number\dtlcolumnnum}% - }% - \dtl@dogetentry - \ifx\dtl@entry\dtlnovalue +\newcommand*{\DTLremoveentryfromrow}[1]{% + \ifnum\dtlforeachlevel=0\relax + \PackageError{datatool}{\string\DTLremoventryfromrow\space + can only be used inside \string\DTLforeach}{}% + \else % \end{macrocode} -% Store the value of this entry in \cs{@dtl@toks} -%\changes{2.03}{2009 November 15}{value can be expanded before -% adding to database}% +% Set \cs{@dtl@thisdb} to the current database name: % \begin{macrocode} - \@dtl@setnewvalue{#3}% + \expandafter\let\expandafter\@dtl@thisdb + \csname @dtl@dbname@\romannumeral\dtlforeachlevel\endcsname % \end{macrocode} -% There are no entries in this row for the given column. -% Add this entry. +% Check this isn't in \cs{DTLforeach*} % \begin{macrocode} - \toks@gconcat@middle@cx{dtldb@#1}% - {\dtlbeforerow}% + \@dtlifreadonly + {% + \PackageError{datatool}{\string\DTLremoveentryfromrow\space + can't be used inside \string\DTLforeach*}{The starred + version of \string\DTLforeach\space is read only}% + }% {% % \end{macrocode} -% Start of this row: +% Store current row number in \cs{dtlrownum} % \begin{macrocode} - \noexpand\db@row@elt@w% + \dtlrownum= + \csname dtl@row\romannumeral\dtlforeachlevel\endcsname\relax % \end{macrocode} -% Row ID: +% Is there a column corresponding to this key? % \begin{macrocode} - \noexpand\db@row@id@w \number\csname dtlrows@#1\endcsname - \noexpand\db@row@id@end@% + \@DTLifhaskey{\@dtl@thisdb}{#1}% + {% % \end{macrocode} -% Current row so far +% There exists a column for this key, so get the index: % \begin{macrocode} - \the\dtlcurrentrow + \@dtl@getcolumnindex{\thiscol}{\@dtl@thisdb}{#1}\relax + \dtlcolumnnum=\thiscol\relax % \end{macrocode} -% New column: -% Column ID +% Set \cs{dtlcurrentrow} to the current row % \begin{macrocode} - \noexpand\db@col@id@w \number\dtlcolumnnum - \noexpand\db@col@id@end@% + \dtlcurrentrow = + \csname @dtl@cur\romannumeral\dtlforeachlevel\endcsname % \end{macrocode} -% Value: +% Does this row have an entry with this key? % \begin{macrocode} - \noexpand\db@col@elt@w \the\@dtl@toks - \noexpand\db@col@elt@end@% + \edef\dtl@dogetentry{\noexpand\dtlgetentryfromcurrentrow + {\noexpand\dtl@entry}{\number\dtlcolumnnum}% + }% + \dtl@dogetentry + \ifx\dtl@entry\dtlnovalue % \end{macrocode} -% Column ID: +% This row doesn't contain an entry with this key % \begin{macrocode} - \noexpand\db@col@id@w \number\dtlcolumnnum - \noexpand\db@col@id@end@% + \PackageError{datatool}{Can't remove entry given by `#1' + from current row in database `\@dtl@thisdb': no such + entry}{The current row doesn't contain an entry for + key `#1'}% + \else % \end{macrocode} -% Row ID: +% Split the current row around the unwanted entry % \begin{macrocode} - \noexpand\db@row@id@w \number\csname dtlrows@#1\endcsname - \noexpand\db@row@id@end@% + \edef\@dtl@dosplitrow{% + \noexpand\dtlsplitrow{\the\dtlcurrentrow}% + {\number\dtlcolumnnum}{\noexpand\dtl@pre}% + {\noexpand\dtl@post}% + }% + \@dtl@dosplitrow % \end{macrocode} -% End of this row +% Reconstruct row without unwanted entry % \begin{macrocode} - \noexpand\db@row@elt@end@% + \expandafter\@dtl@toks\expandafter{\dtl@pre}% + \expandafter\toks@\expandafter{\dtl@post}% + \edef\@dtl@tmp{\the\@dtl@toks \the\toks@}% + \dtlcurrentrow=\expandafter{\@dtl@tmp}% + \expandafter\global + \csname @dtl@cur\romannumeral\dtlforeachlevel\endcsname + = \dtlcurrentrow + \dtl@message{Removed entry given by #1\space from current + row of database `\@dtl@thisdb'}% + \fi + }% + {% + \PackageError{datatool}{Can't remove entry given by + `#1' - no such key exists}{}% + }% }% -% \end{macrocode} -% Rest (this should be empty) -% \begin{macrocode} - {\dtlafterrow}% -% \end{macrocode} -% Print information message if in verbose mode. -% \begin{macrocode} - \dtl@message{Added #2\space -> #3\space to database `#1'}% - \else -% \end{macrocode} -% There's already an entry for the given column in this row -% \begin{macrocode} - \PackageError{datatool}{Can't add entry with ID `#2' to - current row of database `#1'}{There is already an entry with - this ID in the current row}% \fi } % \end{macrocode} %\end{macro} % -%\changes{2.0}{2009 February 27}{removed \cs{@dtl@setidtype}} -%\changes{2.0}{2009 February 27}{removed \cs{@dtl@setkeys}} -%\changes{2.0}{2009 February 27}{removed \cs{@dtl@getidtype}} -% -%\begin{macro}{\DTLifdbexists} +%\begin{macro}{\DTLreplaceentryforrow} %\begin{definition} -%\cs{DTLifdbexists}\marg{db name}\marg{true part}\marg{false part} +%\cs{DTLreplaceentryforrow}\marg{key}\marg{value} %\end{definition} -% Checks if a data base with the given name exists. +% Replaces entry given by \meta{key} in current row with +% \meta{value}. +% (The current row is given by the token register +% \cs{@dtl@cur}\meta{n} where \meta{n} is roman +% numeral value of \cs{dtlforeachlevel}. +%\changes{2.0}{2009 February 27}{updated to use new database structure} % \begin{macrocode} -\newcommand{\DTLifdbexists}[3]{% - \@ifundefined{dtldb@#1}{#3}{#2}} +\newcommand*{\DTLreplaceentryforrow}[2]{% + \ifnum\dtlforeachlevel=0\relax + \PackageError{datatool}{\string\DTLreplaceentryforrow\space + can only be used inside \string\DTLforeach}{}% + \else % \end{macrocode} -%\end{macro} -% -%\changes{2.0}{2009 February 27}{removed \cs{@dtl@ifrowcontains}} -%\changes{2.0}{2009 February 27}{removed \cs{dtl@getentryvalue}} -%\changes{2.0}{2009 February 27}{removed \cs{dtl@getentryid}} -% -%\subsection{Accessing Data} -% -%\begin{macro}{\@dtl@assign} -%\begin{definition} -%\cs{@dtl@assign}\marg{list}\marg{db} -%\end{definition} -% Assigns commands according to the given keys. -% The current row must be stored in \cs{dtlcurrentrow}. -%\changes{2.0}{2009 February 27}{updated to use new database -% structure} +% Set \cs{@dtl@thisdb} to the current database name: % \begin{macrocode} -\newcommand*{\@dtl@assign}[2]{% - \@dtl@assigncmd#1,\@nil\@@{#2}% -} + \expandafter\let\expandafter\@dtl@thisdb + \csname @dtl@dbname@\romannumeral\dtlforeachlevel\endcsname % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@dtl@assigncmd} -%\begin{definition} -% \cs{@dtl@assigncmd}\meta{cmd}=\meta{id}\cs{@nil} -%\end{definition} -%\changes{2.03}{2009 November 15}{modified to ignore spaces after -% commas} +% Check this isn't in \cs{DTLforeach*} % \begin{macrocode} -\def\@dtl@assigncmd#1#2=#3,#4\@@#5{% + \@dtlifreadonly + {% + \PackageError{datatool}{\string\DTLreplaceentryforrow\space + can't be used inside \string\DTLforeach*}{The starred version + of \string\DTLforeach\space is read only}% + }% + {% % \end{macrocode} -% get entry for ID given by \#3 and store in \#2 +% Store current row number in \cs{dtlrownum} % \begin{macrocode} - \@sDTLifhaskey{#5}{#3}% - {% - \edef\@dtl@dogetentry{% - \noexpand\dtlgetentryfromcurrentrow - {\noexpand#1}{\dtlcolumnindex{#5}{#3}}}% - \@dtl@dogetentry + \dtlrownum= + \csname dtl@row\romannumeral\dtlforeachlevel\endcsname\relax % \end{macrocode} -% Set to null if required +% Is there a column corresponding to this key? % \begin{macrocode} - \ifx#1\dtlnovalue - \@@dtl@setnull{#1}{#3}% - \fi + \@DTLifhaskey{\@dtl@thisdb}{#1}% + {% % \end{macrocode} -% Make it global +% There exists a column for this key, so get the index: % \begin{macrocode} - \global\let#1=#1\relax - }% - {% - \PackageError{datatool}{Can't assign \string#1\space: there - is no key `#3' in data base `#5'}{}% + \@dtl@getcolumnindex{\thiscol}{\@dtl@thisdb}{#1}\relax + \dtlcolumnnum=\thiscol\relax % \end{macrocode} -% Set to null +% Set \cs{dtlcurrentrow} to the current row % \begin{macrocode} - \global\let#1\DTLstringnull - }% + \dtlcurrentrow = + \csname @dtl@cur\romannumeral\dtlforeachlevel\endcsname % \end{macrocode} -% Recurse? +% Does this row have an entry with this key? % \begin{macrocode} - \def\dtl@tmp{#4}% - \ifx\@nnil\dtl@tmp - \let\@dtl@next\@dtl@assigncmdnoop - \else - \let\@dtl@next\@dtl@assigncmd - \fi - \@dtl@next#4\@@{#5}% -} + \edef\dtl@dogetentry{\noexpand\dtlgetentryfromcurrentrow + {\noexpand\dtl@entry}{\number\dtlcolumnnum}% + }% + \dtl@dogetentry + \ifx\dtl@entry\dtlnovalue % \end{macrocode} -%\end{macro} -%\begin{macro}{\@dtl@assigncmdnoop} -% End loop +% This row doesn't contain an entry with this key % \begin{macrocode} -\def\@dtl@assigncmdnoop#1\@@#2{} + \PackageError{datatool}{Can't replace entry given by `#1' + from current row in database `\@dtl@thisdb': no such + entry}{The current row doesn't contain an entry for + key `#1'}% + \else % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@dtl@setnull} -%\cs{@dtl@setnull}\marg{cmd}\marg{id} sets \meta{cmd} to either -% \cs{DTLstringnull} or \cs{DTLnumbernull} depending on the data -% type for \meta{id}. (Database -% name should be stored in \cs{@dtl@dbname} prior to use.) -%\changes{2.0}{2009 February 27}{modified to use new database -% structure} +% Split the current row around the requested entry % \begin{macrocode} -\newcommand*{\@dtl@setnull}[2]{% + \edef\@dtl@dosplitrow{% + \noexpand\dtlsplitrow{\the\dtlcurrentrow}% + {\number\dtlcolumnnum}{\noexpand\dtl@pre}% + {\noexpand\dtl@post}% + }% + \@dtl@dosplitrow % \end{macrocode} -% Check if database given by \cs{@dtl@dbname} has the required key. +% Reconstruct row with new value (given by \verb|#2|). +%\changes{2.03}{2009 November 15}{expand replacement entry} % \begin{macrocode} - \@sDTLifhaskey{\@dtl@dbname}{#2}% - {% + \protected@edef\@dtl@tmp{#2}% + \expandafter\@dtl@toks\expandafter{\@dtl@tmp}% new value + \expandafter\@dtl@before\expandafter{\dtl@pre}% + \expandafter\@dtl@after\expandafter{\dtl@post}% + \toks@gconcat@middle@cx + {@dtl@cur\romannumeral\dtlforeachlevel}% + {\@dtl@before}% + {% + \noexpand\db@col@id@w \number\dtlcolumnnum + \noexpand\db@col@id@end@% + \noexpand\db@col@elt@w \the\@dtl@toks + \noexpand\db@col@elt@end@% + \noexpand\db@col@id@w \number\dtlcolumnnum + \noexpand\db@col@id@end@% + }% + {\@dtl@after}% % \end{macrocode} -% Set to null +% Print information to terminal and log file if in verbose mode. % \begin{macrocode} - \@@dtl@setnull{#1}{#2}% - }% - {% + \dtl@message{Updated #1\space -> #2\space in database + `\@dtl@thisdb'}% + \fi + }% + {% % \end{macrocode} -% Key not defined in database \cs{@dtl@dbname}. +% There doesn't exist a column for this key. % \begin{macrocode} - \global\let#1=\DTLstringnull - }% + \PackageError{datatool}{Can't replace key `#1' - no such + key in database `\@dtl@thisdb'}{}% + }% + }% + \fi } % \end{macrocode} %\end{macro} % -%\begin{macro}{\@@dtl@setnull} -% As above, but doesn't check if key exists +%\begin{macro}{\DTLremovecurrentrow} +%\begin{definition} +%\cs{DTLremovecurrentrow} +%\end{definition} +% Removes current row. This just sets the current row to empty +%\changes{1.01}{2007 Aug 17}{fix bug caused by missing \cs{fi} +% and unrequired argument} +%\changes{2.0}{2009 February 27}{updated to use new database structure} % \begin{macrocode} -\newcommand*{\@@dtl@setnull}[2]{% +\newcommand*{\DTLremovecurrentrow}{% + \ifnum\dtlforeachlevel=0\relax + \PackageError{datatool}{\string\DTLremovecurrentrow\space can + only be used inside \string\DTLforeach}{}% + \else % \end{macrocode} -% Get the data type associated with this key and store in -% \cs{@dtl@type}. +% Set \cs{@dtl@thisdb} to the current database name: % \begin{macrocode} - \@sdtlgetdatatype{\@dtl@type}{\@dtl@dbname}{#2}% + \expandafter\let\expandafter\@dtl@thisdb + \csname @dtl@dbname@\romannumeral\dtlforeachlevel\endcsname % \end{macrocode} -% Check data type. -% \begin{macrocode} - \ifnum0\@dtl@type=0\relax -% \end{macrocode} -% Data type is \meta{empty} or 0, so set to string null. +% Check this isn't in \cs{DTLforeach*} % \begin{macrocode} - \global\let#1=\DTLstringnull - \else + \@dtlifreadonly + {% + \PackageError{datatool}{\string\DTLreplaceentryforrow\space + can't be used inside \string\DTLforeach*}{The starred version + of \string\DTLforeach\space is read only}% + }% + {% % \end{macrocode} -% Data type is numerical, so set to number null. +% Set the current row to \cs{@nil} (\cs{DTLforeach} needs to check +% for this) % \begin{macrocode} - \global\let#1=\DTLnumbernull + \expandafter\global + \csname @dtl@cur\romannumeral\dtlforeachlevel\endcsname + ={\@nil}% + }% \fi } % \end{macrocode} %\end{macro} % -%\begin{macro}{\DTLstringnull} -% String null value: +%\begin{macro}{\DTLaddentryforrow} +%\begin{definition} +%\cs{DTLaddentryforrow}\marg{db name}\marg{assign list}\marg{condition}\marg{key}\marg{value} +%\end{definition} +% Adds the entry with key given by \meta{key} and value given by +% \meta{value} to the first row in the database \meta{db name} +% which satisfies the condition given by \meta{condition}. The +% \meta{assign list} is the same as for \cs{DTLforeach} and may +% be used to set the values which are to be tested in \meta{condition}. +%\changes{2.0}{2009 February 27}{updated to use new database structure} % \begin{macrocode} -\newcommand*{\DTLstringnull}{NULL} +\newcommand{\DTLaddentryforrow}[5]{% % \end{macrocode} -%\end{macro} -%\begin{macro}{\DTLnumbernull} -% Number null value: +% Iterate through the data base until condition is met % \begin{macrocode} -\newcommand*{\DTLnumbernull}{0} + \DTLifdbexists{#1}% + { + \def\@dtl@notdone{\PackageError{datatool}{Unable to add entry + given by key `#4': condition not met for any row in database + `#1'}{}}% % \end{macrocode} -%\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}. +% Iterate through each row % \begin{macrocode} -\newcommand*{\DTLifnull}[3]{% - \ifx\DTLstringnull#1\relax - #2% - \else - \ifx\DTLnumbernull#1\relax - #2% - \else - #3% - \fi - \fi -} + \DTLforeach[#3]{#1}{#2}% + {% % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@dtlnovalue} +% add entry to this row % \begin{macrocode} -\def\@dtlnovalue{Undefined Value} + \DTLappendtorow{#4}{#5}% % \end{macrocode} -%\end{macro} -%\begin{macro}{\dtlnovalue} +% disable error message % \begin{macrocode} -\def\dtlnovalue{\@dtlnovalue} + \let\@dtl@notdone\relax % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\DTLgetkeydata} -%\begin{definition} -%\cs{DTLgetkeydata}\marg{key}\marg{db}\marg{col cs}\marg{type cs}\marg{header cs} -%\end{definition} -% Gets data for given key in database \meta{db}: the column index is -% stored in \meta{col cs} and data type is stored in \meta{type cs}. -% The unstarred version checks for the existance of the database -% and key, the starred version doesn't. +% break out of loop % \begin{macrocode} -\newcommand*{\DTLgetkeydata}{% - \@ifstar\@sdtlgetkeydata\@dtlgetkeydata + \dtlbreak + }% + \@dtl@notdone + }% + {% + \PackageError{datatool}{Unable to add entry given by key `#4': + database `#1' doesn't exist}{}% + }% } % \end{macrocode} %\end{macro} % -%\begin{macro}{\@dtlgetkeydata} -% Unstarred version of \cs{DTLgetkeydata} -% \begin{macrocode} -\newcommand*{\@dtlgetkeydata}[5]{% -% \end{macrocode} -% Check if the database exists. +%\begin{macro}{\DTLforeachkeyinrow} +%\begin{definition} +%\cs{DTLforeachkeyinrow}\marg{cmd}\marg{text} +%\end{definition} +% Iterates through each key in the current row of \cs{DTLforeach}, +% and does \meta{text}. +%\changes{2.0}{2009 February 27}{updated to use new database structure} % \begin{macrocode} - \DTLifdbexists{#2}% - {% +\newcommand*{\DTLforeachkeyinrow}[2]{% + \ifnum\dtlforeachlevel=0\relax + \PackageError{datatool}{\string\DTLforeachkeyinrow\space can only + be used inside \string\DTLforeach}{}% + \else % \end{macrocode} -% Check if the given key exists in the database. +% Set \cs{@dtl@thisdb} to the current database name: % \begin{macrocode} - \@sDTLifhaskey{#2}{#1}% - {% + \expandafter\let\expandafter\@dtl@thisdb + \csname @dtl@dbname@\romannumeral\dtlforeachlevel\endcsname % \end{macrocode} -% Get the data. +% Iterate through key list % \begin{macrocode} - \@sdtlgetkeydata{#1}{#2}{#3}{#4}{#5}% - }% - {% + \dtlforeachkey(\dtlkey,\dtlcol,\dtltype,\dtlheader)\in + \@dtl@thisdb\do{% % \end{macrocode} -% Key not defined in the given database. +% store row in \cs{dtlcurrentrow} +% (This may get nested so need to do it here instead of +% outside this loop in case +% \meta{text} changes it.) % \begin{macrocode} - \PackageError{datatool}{Key `#1' not defined in database - `#2'}{}% - }% - }% - {% + \dtlcurrentrow = + \csname @dtl@cur\romannumeral\dtlforeachlevel\endcsname % \end{macrocode} -% Database not defined. +% Get the value for this key and store in "#1" % \begin{macrocode} - \PackageError{datatool}{Database `#2' doesn't exist}{}% - }% -} + \edef\dtl@dogetentry{\noexpand\dtlgetentryfromcurrentrow + {\noexpand#1}{\dtlcol}}% + \dtl@dogetentry % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@sdtlgetkeydata} -%\cs{@sdtlgetkeydata}\marg{key}\marg{db}\marg{col cs}\marg{type cs}\marg{header cs} -% Starred verison of \cs{DTLgetkeydata}. +% Check if null % \begin{macrocode} -\newcommand*{\@sdtlgetkeydata}[5]{% - \@sdtl@getcolumnindex{#3}{#2}{#1}% - \edef\@dtl@dogetkeydata{\noexpand\@dtl@getprops - {\noexpand\@dtl@key}{\noexpand#4}{\noexpand\@dtl@colhead}% - {\noexpand\@dtl@before}{\noexpand\@dtl@after}% - {\expandafter\the\csname dtlkeys@#2\endcsname}% - {#3}}% - \@dtl@dogetkeydata - \edef#5{\the\@dtl@toks}% -} + \ifx#1\dtlnovalue + \ifnum0\dtltype=0\relax % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\dtl@gathervalues} -%\begin{definition} -%\cs{dtl@gathervalues}\oarg{label}\marg{db name}\marg{row toks} -%\end{definition} -% Stores each element of \meta{row} in \meta{db name} into -% the command \cs{@dtl@}\meta{label}\texttt{@}\meta{key}, -% where \meta{key} is the -% key for that element, and \meta{label} defaults to "key". -%\changes{2.0}{2009 February 27}{updated to use new database structure} +% Data type is \meta{empty} or 0, so set to string null. % \begin{macrocode} -\newcommand{\dtl@gathervalues}[3][key]{% - \dtlforeachkey(\@dtl@key,\@dtl@col,\@dtl@type,\@dtl@head)\in{#2}\do - {% - \dtlgetentryfromrow{\@dtl@tmp}{\@dtl@col}{\dtlcurrentrow}% - \ifx\@dtl@tmp\dtlnovalue - \@dtl@setnull{\@dtl@tmp}{\@dtl@key}% - \fi - \expandafter\let\csname @dtl@#1@\@dtl@key\endcsname\@dtl@tmp - }% -} + \let#1=\DTLstringnull + \else % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\dtlcurrentrow} -% Define token register to store current row. +% Data type is numerical, so set to number null. % \begin{macrocode} -\newtoks\dtlcurrentrow + \let#1=\DTLnumbernull + \fi + \fi % \end{macrocode} -%\end{macro} -%\begin{macro}{\dtlbeforerow} -% Define token register to store everything before the current row. +% Make "#1" global in case this is in a tabular environment (or +% something similar) % \begin{macrocode} -\newtoks\dtlbeforerow + \global\let#1#1% % \end{macrocode} -%\end{macro} -%\begin{macro}{\dtlafterrow} -% Define token register to store everything after the current row. +% Store loop body so that any scoping commands (such as "&") don't +% cause a problem for \cs{ifx} % \begin{macrocode} -\newtoks\dtlafterrow + \def\@dtl@loop@body{#2}% + \@dtl@loop@body + }% + \fi +} % \end{macrocode} %\end{macro} % -%\begin{macro}{\dtlgetrow} +%\section{DTLforeach Conditionals} +% The following conditionals are only meant to be used within +% \cs{DTLforeach} as they depend on the counter +% \texttt{DTLrow}\meta{n}. +% +%\begin{macro}{\DTLiffirstrow} %\begin{definition} -%\cs{dtlgetrow}\marg{db}\marg{row idx} +%\cs{DTLiffirstrow}\marg{true part}\marg{false part} %\end{definition} -% Gets row with index \meta{row idx} from database named \meta{db} -% and stores the row in \cs{dtlcurrentrow}, the preceding rows in -% \cs{dtlbeforerow} and the following rows in \cs{dtlafterrow}. -% This assumes that the given row exists. +% Test if the current row is the first row. (This takes +% \meta{condition}, the optional argument of \cs{DTLforeach}, +% into account, so it may not correspond to row~1 of the +% database.) Can only be used in \cs{DTLforeachrow}. +%\changes{2.0}{2009 February 27}{modified to have different +% definition depending on location} % \begin{macrocode} -\newcommand*{\dtlgetrow}[2]{% - \expandafter\toks@\expandafter=\csname dtldb@#1\endcsname - \edef\@dtl@dogetrow{\noexpand\@dtlgetrow{\the\toks@}{\number#2}}% - \@dtl@dogetrow +\newcommand{\DTLiffirstrow}[2]{% + \PackageError{datatool}{\string\DTLiffirstrow\space can only + be used inside \string\DTLforeach}{}% } % \end{macrocode} %\end{macro} % -%\begin{macro}{\@dtlgetrow} +%\begin{macro}{\DTLiflastrow} %\begin{definition} -%\cs{@dtlgetrow}\marg{data specs}\marg{row idx} +%\cs{DTLiflastrow}\marg{true part}\marg{false part} %\end{definition} -% Gets the row specs from \meta{data specs} for row with index -% \meta{row idx} which must be fully expanded. -% \begin{macrocode} -\newcommand*{\@dtlgetrow}[2]{% - \def\@dtl@getrow##1% before stuff - \db@row@elt@w% start of the row - \db@row@id@w #2\db@row@id@end@% row id - ##2% - \db@row@id@w #2\db@row@id@end@% row id - \db@row@elt@end@% end of the row - ##3% after stuff - \q@nil{\dtlbeforerow={##1}\dtlcurrentrow={##2}\dtlafterrow={##3}}% - \@dtl@getrow#1\q@nil +% Checks if the current row is the last row of the database. +% It doesn't take the condition (the optional argument of +% \cs{DTLforeach}) into account, so its possible it may never +% do \meta{true part}, as the last row of the database may not +% meet the condition. It is therefore not very useful and is +% confusing since it behaves differently to \cs{DTLiffirstrow} +% which does take the condition into account, so I have removed +% its description from the main part of the manual. If you need +% to use the optional argument of \cs{DTLforeach}, you will first +% have to iterate through the database to count up the number +% of rows which meet the condition, and then do another pass, +% checking if the current row has reached that number. +%\changes{1.01}{2007 Aug 17}{fixed bug} +%\changes{2.0}{2009 February 27}{modified to have different +% definition depending on location} +% \begin{macrocode} +\newcommand{\DTLiflastrow}[2]{% + \PackageError{datatool}{\string\DTLiflastrow\space can only + be used inside \string\DTLforeach}{}% } % \end{macrocode} %\end{macro} % -%\begin{macro}{\dtlgetentryfromcurrentrow} +%\begin{macro}{\DTLifoddrow} %\begin{definition} -%\cs{dtlgetentryfromcurrentrow}\marg{cs}\marg{col num} +%\cs{DTLifoddrow}\marg{true part}\marg{false part} %\end{definition} -% Gets value for column \meta{col num} from \cs{dtlcurrentrow} -% and stores in \meta{cs}. If not found, \meta{cs} is set to -% \cs{dtlnovalue}. -%\changes{2.0}{2009 February 27}{new} +% Determines whether the current row is odd (takes the optional +% argument of \cs{DTLforeach} into account.) +%\changes{2.0}{2009 February 27}{modified to have different +% definition depending on location} % \begin{macrocode} -\newcommand*{\dtlgetentryfromcurrentrow}[2]{% - \dtlgetentryfromrow{#1}{#2}{\dtlcurrentrow}% +\newcommand{\DTLifoddrow}[2]{% + \PackageError{datatool}{\string\DTLifoddrow\space can only + be used inside \string\DTLforeach}{}% } % \end{macrocode} %\end{macro} % -%\begin{macro}{\dtlgetentryfromrow} -%\begin{definition} -%\cs{dtlgetentryfromrow}\marg{cs}\marg{col num}\marg{row toks} -%\end{definition} +%\section{Displaying Database} +% This section defines commands to display the entire database +% in a \env{tabular} or \env{longtable} environment. +% +%\begin{macro}{\dtlbetweencols} +% This specifies what to put between the column alignment +% specifiers. +%\changes{2.0}{2009 February 27}{new} % \begin{macrocode} -\newcommand*{\dtlgetentryfromrow}[3]{% - \edef\@dtl@do@getentry{\noexpand\dtl@getentryfromrow - {\noexpand#1}{\number#2}{\the#3}}% - \@dtl@do@getentry -} +\newcommand*{\dtlbetweencols}{} % \end{macrocode} %\end{macro} -% -%\begin{macro}{\dtl@getentryfromrow} -%\begin{definition} -%\cs{dtl@getentryfromrow}\marg{cs}\marg{col num}\marg{row specs} -%\end{definition} +%\begin{macro}{\dtlbeforecols} +% This specifies what to put before the first column alignment +% specifier. +%\changes{2.0}{2009 February 27}{new} % \begin{macrocode} -\newcommand*{\dtl@getentryfromrow}[3]{% - \def\dtl@dogetentry##1% before stuff - \db@col@id@w #2\db@col@id@end@% Column id - \db@col@elt@w ##2\db@col@elt@end@% Value - \db@col@id@w #2\db@col@id@end@% Column id - ##3% Remaining stuff - \q@nil{\def#1{##2}}% - \dtl@dogetentry#3% - \db@col@id@w #2\db@col@id@end@% - \db@col@elt@w \@dtlnovalue\db@col@elt@end@% - \db@col@id@w #2\db@col@id@end@% - \q@nil -} +\newcommand*{\dtlbeforecols}{} % \end{macrocode} %\end{macro} -% -%\begin{macro}{\DTLgetvalue} -%\begin{definition} -%\cs{DTLgetvalue}\marg{cs}\marg{db}\marg{r}\marg{c} -%\end{definition} -% Gets the element in row \meta{r}, column \meta{c} from database -% \meta{db} and stores in \meta{cs}. +%\begin{macro}{\dtlaftercols} +% This specifies what to put after the last column alignment +% specifier. +%\changes{2.0}{2009 February 27}{new} % \begin{macrocode} -\newcommand*{\DTLgetvalue}[4]{% - \edef\dtl@dogetvalue{\noexpand\dtl@getvalue{\noexpand#1}{#2}% - {\number#3}{\number#4}}% - \dtl@dogetvalue -} +\newcommand*{\dtlaftercols}{} % \end{macrocode} %\end{macro} % -%\begin{macro}{\dtl@getvalue} +%\begin{macro}{\dtlstringalign} +% Alignment character for columns containing strings % \begin{macrocode} -\newcommand*{\dtl@getvalue}[4]{% - \def\@dtl@getvalue ##1% stuff before row - \db@row@id@w #3\db@row@id@end@% row id - ##2% stuff in row before column - \db@col@id@w #4\db@col@id@end@% column id - \db@col@elt@w ##3\db@col@elt@end@% value - ##4% stuff after value - \q@nil{\def#1{##3}}% - \toks@=\csname dtldb@#2\endcsname - \expandafter\@dtl@getvalue\the\toks@% contents of data base - \db@row@id@w #3\db@row@id@end@% - \db@col@id@w #4\db@col@id@end@% - \db@col@elt@w \@dtlnovalue\db@col@elt@end@% undefined value - \q@nil - \ifx#1\dtlnovalue - \PackageError{datatool}{There is no element at (row=#3, - column=#4) in database `#2'}{}% - \fi -} +\newcommand*{\dtlstringalign}{l} % \end{macrocode} %\end{macro} -% -%\begin{macro}{\DTLgetlocation} -%\begin{definition} -%\cs{DTLgetlocation}\marg{row cs}\marg{column cs}\marg{database}% -%\marg{value} -%\end{definition} -% Assigns \meta{row cs} and \meta{column cs} to the indices of the -% first entry in \meta{database} that matches \meta{value}. +%\begin{macro}{\dtlintalign} +% Alignment character for columns containing integers % \begin{macrocode} -\newcommand*{\DTLgetlocation}[4]{% - \def\@dtl@getlocation##1% stuff before value - \db@col@elt@w #4\db@col@elt@end@% value - \db@col@id@w ##2\db@col@id@end@% column id - ##3% stuff after this column - \db@row@id@w ##4\db@row@id@end@% row id - ##5% stuff after row - \q@nil{\def#1{##4}\def#2{##2}}% - \toks@=\csname dtldb@#3\endcsname - \expandafter\@dtl@getlocation\the\toks@% contents of data base - \db@col@elt@w #4\db@col@elt@end@% value - \db@col@id@w \@dtlnovalue\db@col@id@end@% undefined column id - \db@row@id@w \@dtlnovalue\db@row@id@end@% undefined row id - \q@nil - \ifx#1\dtlnovalue - \PackageError{datatool}{There is no element `#4' in - database `#3'}{}% - \fi -} +\newcommand*{\dtlintalign}{r} % \end{macrocode} %\end{macro} - -%\subsection{Iterating Through Databases} -%\label{sec:code:loops} -% -%\begin{macro}{\dtlbreak} -% Break out of loop at the end of current iteration. +%\begin{macro}{\dtlrealalign} +% Alignment character for columns containing real numbers % \begin{macrocode} -\newcommand*{\dtlbreak}{% - \PackageError{datatool}{Can't break out of anything}{}% -} +\newcommand*{\dtlrealalign}{r} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\dtlcurrencyalign} +% Alignment character for columns containing currency numbers +% \begin{macrocode} +\newcommand*{\dtlcurrencyalign}{r} % \end{macrocode} %\end{macro} % -%\begin{macro}{\dtlforint} +%\begin{macro}{\dtladdalign} %\begin{definition} -%\cs{dtlforint}\meta{ct}=\meta{start}\cs{to}\meta{end}\cs{step}% -%\meta{inc}\cs{do}\marg{body} +%\cs{dtladdalign}\marg{cs}\marg{type}\marg{col num}\marg{max cols} %\end{definition} -% \meta{ct} is a count register, \meta{start}, \meta{end} and -% \meta{inc} are integers. -% Group if nested or use \cs{dtlgforint}. -% An infinite loop may result if \meta{inc}$=0$ and -% \meta{start} $\le$ \meta{end} and \cs{dtlbreak} isn't used. -% \begin{macrocode} -\long\def\dtlforint#1=#2\to#3\step#4\do#5{% -% \end{macrocode} -% Make a copy of old version of break function +% Adds tabular column alignment character to \meta{cs} for column +% \meta{col num} which contains data type \meta{type}. +%\changes{2.0}{2009 February 27}{new} % \begin{macrocode} - \let\@dtl@orgbreak\dtlbreak - \def\@dtl@endloophook{}% +\newcommand*{\dtladdalign}[4]{% + \ifnum#3=1\relax + \protected@edef#1{\dtlbeforecols}% + \else + \protected@edef#1{#1\dtlbetweencols}% + \fi + \ifstrempty{#2}% + {% + \protected@edef#1{#1c}% + }% + {% + \ifcase#2\relax % \end{macrocode} -% Setup break function for the loop (sets \meta{ct} to \meta{end} -% at the end of the current iteration). +% string % \begin{macrocode} - \def\dtlbreak{\def\@dtl@endloophook{#1=#3}}% + \protected@edef#1{#1\dtlstringalign}% + \or % \end{macrocode} -% Initialise \meta{ct} +% integer % \begin{macrocode} - #1=#2\relax + \protected@edef#1{#1\dtlintalign}% + \or % \end{macrocode} -% Check if the steps are positive or negative. +% real number % \begin{macrocode} - \ifnum#4<0\relax + \protected@edef#1{#1\dtlrealalign}% + \or % \end{macrocode} -% Counting down +% currency % \begin{macrocode} - \whiledo{\(#1>#3\)\TE@or\(#1=#3\)}% - {% - #5% - \@dtl@endloophook - \advance#1 by #4\relax - }% - \else + \protected@edef#1{#1\dtlcurrencyalign}% + \else % \end{macrocode} -% Counting up +% Unknown type % \begin{macrocode} - \whiledo{\(#1<#3\)\TE@or\(#1=#3\)}% - {% - #5% - \@dtl@endloophook - \advance#1 by #4\relax - }% + \protected@edef#1{#1c}% + \PackageError{datatool}{Unknown data type `#2'}{}% + \fi + }% + \ifnum#3=#4\relax + \protected@edef#1{#1\dtlaftercols}% \fi -% \end{macrocode} -% Restore break function. -% \begin{macrocode} - \let\dtlbreak\@dtl@orgbreak } % \end{macrocode} %\end{macro} % -%\begin{macro}{\@dtl@foreach@level} -% Count register to keep track of global nested loops. +%\begin{macro}{\dtlheaderformat} +%\begin{definition} +%\cs{dtlheaderformat}\marg{text} +%\end{definition} +% Specifies how to format the column title. +%\changes{2.0}{2009 February 27}{new} % \begin{macrocode} -\newcount\@dtl@foreach@level +\newcommand*{\dtlheaderformat}[1]{\null\hfil\textbf{#1}\hfil\null} % \end{macrocode} %\end{macro} % -%\begin{macro}{\dtlgforint} +%\begin{macro}{\dtlstringformat} %\begin{definition} -%\cs{dtlgforint}\meta{ct}=\meta{start}\cs{to}\meta{end}\cs{step}% -%\meta{inc}\cs{do}\marg{body} +%\cs{dtlstringformat}\marg{text} %\end{definition} -% \meta{ct} is a count register, \meta{start}, \meta{end} and -% \meta{inc} are integers. -% An infinite loop may result if \meta{inc}=0 and \meta{start} $\le$ -% \meta{end} and \cs{dtlbreak} isn't used. +% Specifies how to format entries in columns with string data type. +%\changes{2.0}{2009 February 27}{new} % \begin{macrocode} -\long\def\dtlgforint#1=#2\to#3\step#4\do#5{% +\newcommand*{\dtlstringformat}[1]{#1} % \end{macrocode} -% Initialise +%\end{macro} +%\begin{macro}{\dtlintformat} +%\begin{definition} +%\cs{dtlintformat}\marg{text} +%\end{definition} +% Specifies how to format entries in columns with integer data type. +%\changes{2.0}{2009 February 27}{new} % \begin{macrocode} - \global#1=#2\relax +\newcommand*{\dtlintformat}[1]{#1} % \end{macrocode} -% Increment level counter to allow for nested loops +%\end{macro} +%\begin{macro}{\dtlrealformat} +%\begin{definition} +%\cs{dtlrealformat}\marg{text} +%\end{definition} +% Specifies how to format entries in columns with real data type. +%\changes{2.0}{2009 February 27}{new} % \begin{macrocode} - \global\advance\@dtl@foreach@level by 1\relax +\newcommand*{\dtlrealformat}[1]{#1} % \end{macrocode} -% Set up end loop hook +%\end{macro} +%\begin{macro}{\dtlcurrencyformat} +%\begin{definition} +%\cs{dtlcurrencyformat}\marg{text} +%\end{definition} +% Specifies how to format entries in columns with currency data type. +%\changes{2.0}{2009 February 27}{new} % \begin{macrocode} - \expandafter\global\expandafter - \let\csname @dtl@endhook@\the\@dtl@foreach@level\endcsname - \relax +\newcommand*{\dtlcurrencyformat}[1]{#1} % \end{macrocode} -% Set up the break function: -% Copy current definition +%\end{macro} +% +%\begin{macro}{\dtldisplaystarttab} +% Indicates what to do just after "\begin{tabular}"\marg{column specs} +% (e.g.\ \cs{hline}). +%\changes{2.0}{2009 February 27}{new} % \begin{macrocode} - \expandafter\global\expandafter - \let\csname @dtl@break@\the\@dtl@foreach@level\endcsname - \dtlbreak +\newcommand*{\dtldisplaystarttab}{} % \end{macrocode} -% Set up definition for this level (sets to at the end -% of the current iteration). +%\end{macro} +% +%\begin{macro}{\dtldisplayendtab} +% Indicates what to do just before "\end{tabular}". +%\changes{2.0}{2009 February 27}{new} % \begin{macrocode} - \gdef\dtlbreak{\expandafter - \gdef\csname @dtl@endhook@\the\@dtl@foreach@level\endcsname{% - #1=#3}}% +\newcommand*{\dtldisplayendtab}{} % \end{macrocode} -% check the direction +%\end{macro} +% +%\begin{macro}{\dtldisplayafterhead} +% Indicates what to do after the header row, before the first row +% of data. +%\changes{2.0}{2009 February 27}{new} % \begin{macrocode} - \ifnum#4<0\relax +\newcommand*{\dtldisplayafterhead}{} % \end{macrocode} -% Counting down +%\end{macro} +% +%\begin{macro}{\dtldisplaystartrow} +% Indicates what to do at the start of each row (not including +% the header row or the first row of data). +%\changes{2.0}{2009 February 27}{new} % \begin{macrocode} - \whiledo{\(#1>#3\)\TE@or\(#1=#3\)}% - {% - #5% - \csname @dtl@endhook@\the\@dtl@foreach@level\endcsname - \global\advance#1 by #4\relax - }% - \else +\newcommand*{\dtldisplaystartrow}{} % \end{macrocode} -% Counting up (or 0 increments) +%\end{macro} + +%\begin{macro}{\DTLdisplaydb} +%\begin{definition} +%\cs{DTLdisplaydb}\oarg{omit list}\marg{db} +%\end{definition} +% Displays the database \meta{db} in a tabular environment. +%\changes{2.0}{2009 February 27}{new} +%\changes{2.10}{2012-07-18}{added optional arg} % \begin{macrocode} - \whiledo{\(#1<#3\)\TE@or\(#1=#3\)}% - {% - #5% - \csname @dtl@endhook@\the\@dtl@foreach@level\endcsname - \global\advance#1 by #4\relax - }% - \fi +\newcommand*{\DTLdisplaydb}[2][]{% % \end{macrocode} -% Restore break function +% Initialise: +% only want "&" between columns % \begin{macrocode} - \expandafter\global\expandafter\let\expandafter\dtlbreak - \csname @dtl@break@\the\@dtl@foreach@level\endcsname + \def\@dtl@doamp{\gdef\@dtl@doamp{&}} + \def\@dtl@resetdoamp{\gdef\@dtl@doamp{\gdef\@dtl@doamp{&}}} % \end{macrocode} -% Decrement level counter +% Store maximum number of columns % \begin{macrocode} - \global\advance\@dtl@foreach@level by -1\relax -} + \edef\@dtl@maxcols{\expandafter\number + \csname dtlcols@#2\endcsname}% % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@dtlforeachrow} -%\begin{definition} -%\cs{@dtlforeachrow}(\meta{idx cs},\meta{row cs})\cs{in}\marg{db}% -%\cs{do}\marg{body} -%\end{definition} -% Iterates through each row in database. Assigns the current row -% index to \meta{idx cs} and the row specs to \meta{row cs} +% Subtract number of omitted columns % \begin{macrocode} -\long\def\@dtlforeachrow(#1,#2)\in#3\do#4{% - \edef\dtl@tmp{\expandafter\the\csname dtldb@#3\endcsname}% - \expandafter\@dtl@foreachrow\dtl@tmp - \db@row@elt@w% - \db@row@id@w \@nil\db@row@id@end@% - \db@row@id@w \@nil\db@row@id@end@% - \db@row@elt@end@% - \@@{#1}{#2}{#4}\q@nil -} + \DTLnumitemsinlist{#1}{\@dtl@tmp}% + \dtlsub{\@dtl@maxcols}{\@dtl@maxcols}{\@dtl@tmp}% + \dtlclip{\@dtl@maxcols}{\@dtl@maxcols}% % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@dtl@foreachrow} +% Argument for tabular environment % \begin{macrocode} -\long\def\@dtl@foreachrow\db@row@elt@w% -\db@row@id@w #1\db@row@id@end@% -#2\db@row@id@w #3\db@row@id@end@% -\db@row@elt@end@#4\@@#5#6#7\q@nil{% + \def\@dtl@tabargs{}% + \dtlforeachkey(\@dtl@key,\@dtl@idx,\@dtl@type,\@dtl@head)% + \in{#2}\do + {% + \expandafter\DTLifinlist\expandafter{\@dtl@key}{#1}% + {}% + {% + \dtladdalign\@dtl@tabargs\@dtl@type\@dtl@idx\@dtl@maxcols + } + }% % \end{macrocode} -% Define control sequence given by "#5" +% Begin tabular environment % \begin{macrocode} - \gdef#5{#1}% + \edef\@dtl@dobegintab{\noexpand\begin{tabular}{\@dtl@tabargs}}% + \@dtl@dobegintab % \end{macrocode} -% Hide the loop body in a macro +% Do start hook % \begin{macrocode} - \gdef\@dtl@loopbody{#7}% + \dtldisplaystarttab % \end{macrocode} -% Increment level counter to allow for nested loops +% Reset \cs{@dtl@doamp} so it doesn't do an ampersand at the +% start of the first column. % \begin{macrocode} - \global\advance\@dtl@foreach@level by 1\relax + \@dtl@resetdoamp % \end{macrocode} -% Check if we have reached the end of the loop +% Do the header row. % \begin{macrocode} - \ifx#5\@nnil - \expandafter\global\expandafter - \let\csname @dtl@foreachnext\the\@dtl@foreach@level\endcsname - =\@dtl@foreachnoop - \else - \gdef#6{#2}% + \dtlforeachkey(\@dtl@key,\@dtl@idx,\@dtl@type,\@dtl@head)% + \in{#2}\do + {% + \expandafter\DTLifinlist\expandafter{\@dtl@key}{#1}% + {}% + {% + \@dtl@doamp + \dtlheaderformat{\@dtl@head}% + }% + }% + \\% % \end{macrocode} -% Set up the break function: -% Make a copy of current break function +% Do the after header hook % \begin{macrocode} - \expandafter\let - \csname @dtl@break@\the\@dtl@foreach@level\endcsname - \dtlbreak + \dtldisplayafterhead % \end{macrocode} -% Setup break function for this level +% Reset \cs{@dtl@doamp} so it doesn't do an ampersand at the +% start of the first column. % \begin{macrocode} - \gdef\dtlbreak{\expandafter\global\expandafter - \let\csname @dtl@foreachnext\the\@dtl@foreach@level\endcsname - =\@dtl@foreachnoop}% + \@dtl@resetdoamp % \end{macrocode} -% Initialise +% Iterate through each row of the database % \begin{macrocode} - \expandafter\global\expandafter - \let\csname @dtl@foreachnext\the\@dtl@foreach@level\endcsname - =\@dtl@foreachrow + \@sDTLforeach{#2}{}{% % \end{macrocode} -% Do body of loop +% Do the start row hook if not the first row % \begin{macrocode} - \@dtl@loopbody + \DTLiffirstrow{}{\\\dtldisplaystartrow}% % \end{macrocode} -% Restore break function +% Reset \cs{@dtl@doamp} so it doesn't do an ampersand at the +% start of the first column. % \begin{macrocode} - \expandafter\let\expandafter\dtlbreak - \csname @dtl@break@\the\@dtl@foreach@level\endcsname - \fi + \@dtl@resetdoamp % \end{macrocode} -% Set up what to do next. +% Iterate through each column. % \begin{macrocode} - \expandafter\let\expandafter\@dtl@foreachnext - \csname @dtl@foreachnext\the\@dtl@foreach@level\endcsname + \DTLforeachkeyinrow{\@dtl@val}% + {% + \expandafter\DTLifinlist\expandafter{\dtlkey}{#1}% + {}% + {% % \end{macrocode} -% Decrement level counter. +% Need to make value global as it needs to be used after the +% ampersand. % \begin{macrocode} - \global\advance\@dtl@foreach@level by -1\relax + \global\let\@dtl@val\@dtl@val + \@dtl@doamp % \end{macrocode} -% Repeat loop if necessary. +% \cs{DTLforeachkeyinrow} sets \cs{dtltype} to the data type +% for the current key. This can be used to determine which +% format to use for this entry. % \begin{macrocode} - \@dtl@foreachnext#4\@@{#5}{#6}{#7}\q@nil + \@dtl@datatype=0\dtltype\relax + \ifcase\@dtl@datatype + \dtlstringformat\@dtl@val + \or + \dtlintformat\@dtl@val + \or + \dtlrealformat\@dtl@val + \or + \dtlcurrencyformat\@dtl@val + \else + \@dtl@val + \fi + }% + }% + }% + \dtldisplayendtab + \end{tabular}% } % \end{macrocode} %\end{macro} % -%\begin{macro}{\@dtl@foreachnoop} -% \begin{macrocode} -\long\def\@dtl@foreachnoop#1\@@#2\q@nil{} -% \end{macrocode} -%\end{macro} +% Define keys to use in the optional argument of +% \cs{DTLdisplaylongdb}. % -%\begin{macro}{\dtlforeachkey} -%\begin{definition} -%\cs{dtlforeachkey}(\meta{key cs},\meta{col cs},\meta{type cs},\meta{header cs})% -%\cs{in}\marg{db}\cs{do}\marg{body} -%\end{definition} -% Iterates through all the keys in database \meta{db}. In each -% iteration, \meta{key cs} stores the key, \meta{col cs} stores the -% column index and \meta{type cs} stores the data type. +% The caption key sets the caption for the longtable. % \begin{macrocode} -\long\def\dtlforeachkey(#1,#2,#3,#4)\in#5\do#6{% - \gdef\@dtl@loopbody{#6}% - \edef\@dtl@keys{\expandafter\the\csname dtlkeys@#5\endcsname}% - \expandafter\@dtl@foreachkey\@dtl@keys - \db@plist@elt@w% - \db@col@id@w -1\db@col@id@end@% - \db@key@id@w \db@key@id@end@% - \db@type@id@w \db@type@id@end@% - \db@header@id@w \db@header@id@end@% - \db@col@id@w -1\db@col@id@end@% - \db@plist@elt@end@% - \@@{\@dtl@updatefkcs{#1}{#2}{#3}{#4}}\q@nil -} +\define@key{displaylong}{caption}{\def\@dtl@cap{#1}} +% \end{macrocode} +% The contcaption key sets the continuation caption for the +% longtable. +% \begin{macrocode} +\define@key{displaylong}{contcaption}{\def\@dtl@contcap{#1}} +% \end{macrocode} +% The shortcaption key sets the lof caption for the longtable. +% \begin{macrocode} +\define@key{displaylong}{shortcaption}{\def\@dtl@shortcap{#1}} +% \end{macrocode} +% The label key sets the label for the longtable. +% \begin{macrocode} +\define@key{displaylong}{label}{\def\@dtl@label{#1}} +% \end{macrocode} +% The foot key sets the longtable foot +% \begin{macrocode} +\define@key{displaylong}{foot}{\def\@dtl@foot{#1}} +% \end{macrocode} +% The lastfoot key sets the longtable last foot +% \begin{macrocode} +\define@key{displaylong}{lastfoot}{\def\@dtl@lastfoot{#1}} +% \end{macrocode} +% List of omitted columns +% \begin{macrocode} +\define@key{displaylong}{omit}{\def\@dtl@omitlist{#1}} % \end{macrocode} -%\end{macro} % -%\begin{macro}{\@dtl@updatefkcs} +%\begin{macro}{\@dtl@resetdostartrow} +% Resets start row hook so that it skips the first row. % \begin{macrocode} -\newcommand*{\@dtl@updatefkcs}[8]{% - \gdef#1{#5}% - \gdef#2{#6}% - \gdef#3{#7}% - \gdef#4{#8}% +\newcommand*{\@dtl@resetdostartrow}{% + \gdef\@dtl@dostartrow{% + \gdef\@dtl@dostartrow{\\\dtldisplaystartrow}}% } % \end{macrocode} %\end{macro} % -%\begin{macro}{\@dtl@foreachkey} -% Sets everything globally in case it occurs in a tabular environment -% Loop body needs to be stored in \cs{@dtl@loopbody}. -% "#7" indicates an update macro. +%\begin{macro}{\DTLdisplaylongdb} +%\begin{definition} +%\cs{DTLdisplaylongdb}\oarg{options}\marg{db} +%\end{definition} +% Displays the database \meta{db} in a longtable environment. +% (User needs to load \sty{longtable}). +%\changes{2.0}{2009 February 27}{new} +%\changes{2.10}{2012-07-18}{added omit option} % \begin{macrocode} -\long\def\@dtl@foreachkey\db@plist@elt@w% -\db@col@id@w #1\db@col@id@end@% -\db@key@id@w #2\db@key@id@end@% -\db@type@id@w #3\db@type@id@end@% -\db@header@id@w #4\db@header@id@end@% -\db@col@id@w #5\db@col@id@end@% -\db@plist@elt@end@#6\@@#7\q@nil{% - \ifnum#1=-1\relax +\newcommand*{\DTLdisplaylongdb}[2][]{% % \end{macrocode} -% Terminate loop +% Initialise. % \begin{macrocode} - \let\@dtl@foreachnext\@dtl@foreachnoop - \else + \def\@dtl@cap{\@nil}% + \def\@dtl@contcap{\@nil}% + \def\@dtl@label{\@nil}% + \def\@dtl@shortcap{\@dtl@cap}% + \def\@dtl@foot{\@nil}% + \def\@dtl@lastfoot{\@nil}% + \def\@dtl@omitlist{}% % \end{macrocode} -% Set up loop variables +% Set the options % \begin{macrocode} - #7{#2}{#1}{#3}{#4}% + \setkeys{displaylong}{#1}% % \end{macrocode} -% Increment level counter to allow for nested loops +% Only want "&" between columns % \begin{macrocode} - \global\advance\@dtl@foreach@level by 1\relax + \def\@dtl@doamp{\gdef\@dtl@doamp{&}} + \def\@dtl@resetdoamp{\gdef\@dtl@doamp{\gdef\@dtl@doamp{&}}} + \@dtl@resetdostartrow % \end{macrocode} -% Set up the break function +% Store maximum number of columns % \begin{macrocode} - \expandafter\let - \csname @dtl@break@\the\@dtl@foreach@level\endcsname - \dtlbreak - \gdef\dtlbreak{\expandafter\global\expandafter - \let\csname @dtl@foreachnext\the\@dtl@foreach@level\endcsname - =\@dtl@foreachnoop}% + \edef\@dtl@maxcols{\expandafter\number + \csname dtlcols@#2\endcsname}% % \end{macrocode} -% Initialise +% Subtract number of omitted columns % \begin{macrocode} - \expandafter\global\expandafter - \let\csname @dtl@foreachnext\the\@dtl@foreach@level\endcsname - =\@dtl@foreachkey + \DTLnumitemsinlist{\@dtl@omitlist}{\@dtl@tmp}% + \dtlsub{\@dtl@maxcols}{\@dtl@maxcols}{\@dtl@tmp}% + \dtlclip{\@dtl@maxcols}{\@dtl@maxcols}% % \end{macrocode} -% Do body of loop +% Argument for \env{longtable} environment % \begin{macrocode} - \@dtl@loopbody + \def\@dtl@tabargs{}% + \dtlforeachkey(\@dtl@key,\@dtl@idx,\@dtl@type,\@dtl@head)% + \in{#2}\do + {% + \expandafter\DTLifinlist\expandafter{\@dtl@key}{\@dtl@omitlist}% + {}% + {% + \dtladdalign\@dtl@tabargs\@dtl@type\@dtl@idx\@dtl@maxcols + }% + }% % \end{macrocode} -% Set up what to do next +% Start the \env{longtable} environment. % \begin{macrocode} - \expandafter\let\expandafter\@dtl@foreachnext - \csname @dtl@foreachnext\the\@dtl@foreach@level\endcsname + \edef\@dtl@dobegintab{\noexpand\begin{longtable}{\@dtl@tabargs}}% + \@dtl@dobegintab % \end{macrocode} -% Restore break function +% Do start hook. % \begin{macrocode} - \expandafter\let\expandafter\dtlbreak - \csname @dtl@break@\the\@dtl@foreach@level\endcsname + \dtldisplaystarttab % \end{macrocode} -% Decrement level counter +% Is a foot required? % \begin{macrocode} - \global\advance\@dtl@foreach@level by -1\relax + \ifx\@dtl@foot\@nnil + \else + \@dtl@foot\endfoot \fi % \end{macrocode} -% Recurse if necessary +% Is a last foot required? % \begin{macrocode} - \@dtl@foreachnext#6\@@{#7}\q@nil -} + \ifx\@dtl@lastfoot\@nnil + \else + \@dtl@lastfoot\endlastfoot + \fi % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\dtlforcolumn} -%\begin{definition} -%\cs{dtlforcolumn}\marg{cs}\marg{db}\marg{key}\marg{body} -%\end{definition} -% Iterates through column given by \meta{key} in database \meta{db}. -% \meta{cs} is assign to the element of the column in the -% current iteration. Starred version doesn't check if data base -% exists +% Is a caption required? % \begin{macrocode} -\newcommand*{\dtlforcolumn}{\@ifstar\@sdtlforcolumn\@dtlforcolumn} + \ifx\@dtl@cap\@nnil % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@dtlforcolumn} +% No caption required, just do header row. % \begin{macrocode} -\newcommand{\@dtlforcolumn}[4]{% + \@dtl@resetdoamp + \dtlforeachkey(\@dtl@key,\@dtl@idx,\@dtl@type,\@dtl@head)% + \in{#2}\do + {% + \expandafter\DTLifinlist\expandafter{\@dtl@key}{\@dtl@omitlist}% + {}% + {% + \@dtl@doamp{\dtlheaderformat{\@dtl@head}}% + }% + }% + \@dtl@resetdoamp + \@dtl@resetdostartrow + \endhead\dtldisplayafterhead + \else % \end{macrocode} -% Check if data base exists +% Caption is required % \begin{macrocode} - \DTLifdbexists{#2}% - {% - \@DTLifhaskey{#2}{#3}% + \caption[\@dtl@shortcap]{\@dtl@cap}% +% \end{macrocode} +% Is a label required? +% \begin{macrocode} + \ifx\@dtl@label\@nnil + \else + \label{\@dtl@label}% + \fi + \\% +% \end{macrocode} +% Do header row. +% \begin{macrocode} + \@dtl@resetdoamp + \dtlforeachkey(\@dtl@key,\@dtl@idx,\@dtl@type,\@dtl@head)% + \in{#2}\do {% - \@sdtlforcolumn{#1}{#2}{#3}{#4}% + \expandafter\DTLifinlist\expandafter{\@dtl@key}{\@dtl@omitlist}% + {}% + {% + \@dtl@doamp{\dtlheaderformat{\@dtl@head}}% + }% }% + \@dtl@resetdoamp + \@dtl@resetdostartrow + \endfirsthead % \end{macrocode} -% key not in data base +% Is a continuation caption required? +% \begin{macrocode} + \ifx\@dtl@contcap\@nnil + \caption{\@dtl@cap}% + \else + \caption{\@dtl@contcap}% + \fi + \\% +% \end{macrocode} +% Do header row. +% \begin{macrocode} + \@dtl@resetdoamp + \dtlforeachkey(\@dtl@key,\@dtl@idx,\@dtl@type,\@dtl@head)% + \in{#2}\do + {% + \expandafter\DTLifinlist\expandafter{\@dtl@key}{\@dtl@omitlist}% + {}% + {% + \@dtl@doamp{\dtlheaderformat{\@dtl@head}}% + }% + }% + \@dtl@resetdoamp + \@dtl@resetdostartrow + \endhead\dtldisplayafterhead + \fi +% \end{macrocode} +% Iterate through each row of the database +% \begin{macrocode} + \@sDTLforeach{#2}{}{% + \@dtl@dostartrow + \@dtl@resetdoamp +% \end{macrocode} +% Iterate through each column % \begin{macrocode} + \DTLforeachkeyinrow{\@dtl@val}% {% - \PackageError{datatool}{Database `#2' doesn't contain - key `#3'}{}% + \global\let\@dtl@val\@dtl@val + \expandafter\DTLifinlist\expandafter{\dtlkey}{\@dtl@omitlist}% + {}% + {% + \@dtl@doamp +% \end{macrocode} +% \cs{DTLforeachkeyinrow} sets \cs{dtltype} to the data type +% for the current key. This can be used to determine which +% format to use for this entry. +% \begin{macrocode} + \@dtl@datatype=0\dtltype\relax + \ifcase\@dtl@datatype + \dtlstringformat\@dtl@val + \or + \dtlintformat\@dtl@val + \or + \dtlrealformat\@dtl@val + \or + \dtlcurrencyformat\@dtl@val + \fi + }% }% }% -% - {% - \PackageError{datatool}{Database `#2' doesn't exist}{}% - }% + \dtldisplayendtab + \end{longtable}% } % \end{macrocode} %\end{macro} % -%\begin{macro}{\@sdtlforcolumn} +% +%\section{Editing Databases} +% +%\begin{macro}{\dtlswaprows} +%\begin{definition} +%\cs{dtlswaprows}\marg{db}\marg{row1 idx}\marg{row2 idx} +%\end{definition} +% Swaps the rows with indices \meta{row1 idx} and \meta{row2 idx} +% in the database \meta{db}. +% (Doesn't check if data base exists or if indices are out of +% bounds.) % \begin{macrocode} -\newcommand{\@sdtlforcolumn}[4]{% - \toks@{#4}% - \edef\@dtl@doforcol{\noexpand\dtl@forcolumn{\noexpand#1}% - {\expandafter\the\csname dtldb@#2\endcsname}% - {\dtlcolumnindex{#2}{#3}}{\the\toks@}% - }% - \@dtl@doforcol% -} -% end{macrocode} -%\end{macro} -% -%\begin{macro}{\dtlforcolumnidx} -%\begin{definition} -%\cs{dtlforcolumnidx}\marg{cs}\marg{db}\marg{col num}\marg{body} -%\end{definition} -% Iterates through the column with index in database . -% Starred version doesn't check if database exists. -%\changes{2.0}{2009 February 27}{new} -% \begin{macrocode} -\newcommand*{\dtlforcolumnidx}{% - \@ifstar\@sdtlforcolumnidx\@dtlforcolumnidx -} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@dtlforcolumnidx} -% \begin{macrocode} -\newcommand{\@dtlforcolumnidx}[4]{% - \DTLifdbexists{#2}% - {% - \expandafter\ifnum\csname dtlcols@#2\endcsname<#3\relax - \PackageError{datatool}{Column index \number#3\space out of - bounds for database `#2'}{Database `#2' only has - \expandafter\number\csname dtlcols@#2\endcsname\space - columns}% - \else - \ifnum#3<1\relax - \PackageError{datatool}{Column index \number#3\space out of - bounds for database `#2'}{Indices start from 1}% - \else - \@sdtlforcolumnidx{#1}{#2}{#3}{#4}% - \fi - \fi - }% -% \end{macrocode} -% data base doesn't exist -% \begin{macrocode} - {% - \PackageError{datatool}{Database `#2' doesn't exist}{}% - }% -} +\newcommand*{\dtlswaprows}[3]{% + \ifnum#2=#3\relax % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@sdtlforcolumnidx} -% \begin{macrocode} -\newcommand{\@sdtlforcolumnidx}[4]{% - \toks@{#4}% - \edef\@dtl@doforcol{\noexpand\dtl@forcolumn{\noexpand#1}% - {\expandafter\the\csname dtldb@#2\endcsname}% - {\number#3}{\the\toks@}% - }% - \@dtl@doforcol -} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\dtl@forcolumn} -%\begin{definition} -%\cs{dtl@forcolumn}\marg{cs}\marg{db specs}\marg{col num}\marg{body} -%\end{definition} -% \meta{col num} needs to be fully expanded +% Attempt to swap row with itself: do nothing. % \begin{macrocode} -\newcommand{\dtl@forcolumn}[4]{% + \else % \end{macrocode} -% make a copy of break function +% Let row A be the row with the lower index and row B be the +% row with ther higher index. % \begin{macrocode} - \let\@dtl@oldbreak\dtlbreak + \ifnum#2<#3\relax + \edef\@dtl@rowAidx{\number#2}% + \edef\@dtl@rowBidx{\number#3}% + \else + \edef\@dtl@rowAidx{\number#3}% + \edef\@dtl@rowBidx{\number#2}% + \fi % \end{macrocode} -% set up break function +% Split the database around row A. % \begin{macrocode} - \def\dtlbreak{\let\@dtl@forcolnext=\@dtl@forcolnoop}% + \edef\@dtl@dosplit{\noexpand\dtlgetrow{#1}{\@dtl@rowAidx}}% + \@dtl@dosplit % \end{macrocode} -% define loop macro for this column +% Store first part of database in \cs{@dtl@firstpart}. % \begin{macrocode} - \def\@dtl@forcolumn##1% before stuff - \db@col@id@w #3\db@col@id@end@% column index - \db@col@elt@w ##2\db@col@elt@end@% entry - \db@col@id@w #3\db@col@id@end@% column index - ##3% after stuff - \q@nil{% - \def#1{##2}% assign value to + \expandafter\def\expandafter\@dtl@firstpart\expandafter + {\the\dtlbeforerow}% % \end{macrocode} -% check if end of loop +% Store row A in \cs{@dtl@toksA}. % \begin{macrocode} - \ifx#1\@nnil - \let\@dtl@forcolnext=\@dtl@forcolnoop - \else + \@dtl@toksA=\dtlcurrentrow % \end{macrocode} -% do body of loop +% Split the second part (everything after row A). % \begin{macrocode} - #4% - \let\@dtl@forcolnext=\@dtl@forcolumn - \fi + \edef\@dtl@dosplit{\noexpand\@dtlgetrow + {\the\dtlafterrow}{\@dtl@rowBidx}}% + \@dtl@dosplit % \end{macrocode} -% repeat if necessary +% Store the mid part (everything between row A and row B) % \begin{macrocode} - \@dtl@forcolnext##3\q@nil - }% + \expandafter\def\expandafter\@dtl@secondpart\expandafter + {\the\dtlbeforerow}% % \end{macrocode} -% do loop +% Store row B in \cs{@dtl@toksB}. % \begin{macrocode} - \@dtl@forcolumn#2% - \db@col@id@w #3\db@col@id@end@% - \db@col@elt@w \@nil\db@col@elt@end@% - \db@col@id@w #3\db@col@id@end@\q@nil + \@dtl@toksB=\dtlcurrentrow % \end{macrocode} -% restore break function +% Store the last part (everything after row B). % \begin{macrocode} - \let\dtlbreak\@dtl@oldbreak -} + \expandafter\def\expandafter\@dtl@thirdpart\expandafter + {\the\dtlafterrow}% % \end{macrocode} -%\end{macro} -%\begin{macro}{\@dtl@forcolnoop} +% Reconstruct database: store first part in \cs{toks@} % \begin{macrocode} -\def\@dtl@forcolnoop#1\q@nil{} + \toks@=\expandafter{\@dtl@firstpart}% % \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. +% Store mid part in \cs{dtl@toks} % \begin{macrocode} -\newcount\dtlforeachlevel + \@dtl@toks=\expandafter{\@dtl@secondpart}% % \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. +% Format data for first part, row B and mid part. % \begin{macrocode} -\newcounter{DTLrowi} -\newcounter{DTLrowii} -\newcounter{DTLrowiii} + \edef\@dtl@tmp{\the\toks@ + \noexpand\db@row@elt@w% + \noexpand\db@row@id@w \@dtl@rowAidx\noexpand\db@row@id@end@% + \the\@dtl@toksB + \noexpand\db@row@id@w \@dtl@rowAidx\noexpand\db@row@id@end@% + \noexpand\db@row@elt@end@% + \the\@dtl@toks}% % \end{macrocode} -% Keep \sty{hyperref} happy +% Store data so far in \cs{toks@}. % \begin{macrocode} -\newcounter{DTLrow} -\def\theHDTLrow{\arabic{DTLrow}} -\def\theHDTLrowi{\theHDTLrow.\arabic{DTLrowi}} -\def\theHDTLrowii{\theHDTLrowi.\arabic{DTLrowii}} -\def\theHDTLrowiii{\theHDTLrowii.\arabic{DTLrowiii}} + \toks@=\expandafter{\@dtl@tmp}% % \end{macrocode} -% +% Store last part in \cs{dtl@toks}. % \begin{macrocode} -\newcount\dtl@rowi -\newcount\dtl@rowii -\newcount\dtl@rowiii + \@dtl@toks=\expandafter{\@dtl@thirdpart}% % \end{macrocode} -% +% Format row A and end part. % \begin{macrocode} -\newtoks\@dtl@curi -\newtoks\@dtl@previ -\newtoks\@dtl@nexti -\newtoks\@dtl@curii -\newtoks\@dtl@previi -\newtoks\@dtl@nextii -\newtoks\@dtl@curiii -\newtoks\@dtl@previii -\newtoks\@dtl@nextiii + \edef\@dtl@tmp{\the\toks@ + \noexpand\db@row@elt@w% + \noexpand\db@row@id@w \@dtl@rowBidx\noexpand\db@row@id@end@% + \the\@dtl@toksA + \noexpand\db@row@id@w \@dtl@rowBidx\noexpand\db@row@id@end@% + \noexpand\db@row@elt@end@% + \the\@dtl@toks}% % \end{macrocode} -% -%\begin{macro}{\DTLsaverowcount} -%\begin{definition} -%\cs{DTLsavelastrowcount}\marg{cmd} -%\end{definition} -% Stores the maximum row count for the last \cs{DTLforeach}. +% Update the database % \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}% + \expandafter\global\csname dtldb@#1\endcsname=\expandafter + {\@dtl@tmp}% \fi -\fi} +} % \end{macrocode} %\end{macro} % -%\begin{macro}{\DTLforeach} +%\begin{macro}{\dtl@decrementrows} %\begin{definition} -% \cs{DTLforeach}\oarg{conditions}\marg{db name}\marg{values}\marg{text} +%\cs{dtl@decrementrows}\marg{toks}\marg{n} %\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} +% decrement by 1 all rows in \meta{toks} with row index above +% \meta{n} +%\changes{2.0}{2009 February 27}{new} % \begin{macrocode} -\newcommand*{\DTLforeach}{\@ifstar\@sDTLforeach\@DTLforeach} +\newcommand*{\dtl@decrementrows}[2]{% + \def\@dtl@newlist{}% + \edef\@dtl@min{\number#2}% + \expandafter\@dtl@decrementrows\the#1% + \db@row@elt@w% + \db@row@id@w \@nil\db@row@id@end@% + \db@row@id@w \@nil\db@row@id@end@% + \db@row@elt@end@% + \@nil + #1=\expandafter{\@dtl@newlist}% +} % \end{macrocode} %\end{macro} % -%\begin{macro}{\@DTLforeach} -% \cs{@DTLforeach} is the unstarred version of \cs{DTLforeach}. -% The database is reconstructed to allow for rows to be edited. -% Use the starred version for faster access. -%\changes{2.0}{2009 February 27}{updated to use new database structure} +%\begin{macro}{\@dtl@decrementrows} +%\changes{2.0}{2009 February 27}{new} % \begin{macrocode} -\newcommand{\@DTLforeach}[4][\boolean{true}]{% -% \end{macrocode} -% Check database exists -% \begin{macrocode} - \DTLifdbexists{#2}% - {% +\def\@dtl@decrementrows\db@row@elt@w\db@row@id@w #1\db@row@id@end@% +#2\db@row@id@w #3\db@row@id@end@\db@row@elt@end@#4\@nil{% + \def\@dtl@thisrow{#1}% + \ifx\@dtl@thisrow\@nnil + \let\@dtl@donextdec=\@dtl@gobbletonil + \else + \ifnum\@dtl@thisrow>\@dtl@min + \@dtl@tmpcount=\@dtl@thisrow\relax + \advance\@dtl@tmpcount by -1\relax + \toks@{#2}% + \@dtl@toks=\expandafter{\@dtl@newlist}% + \edef\@dtl@newlist{\the\@dtl@toks + \noexpand\db@row@elt@w% row header + \noexpand\db@row@id@w \number\@dtl@tmpcount + \noexpand\db@row@id@end@% row id + \the\toks@ % row contents + \noexpand\db@row@id@w \number\@dtl@tmpcount + \noexpand\db@row@id@end@% row id + \noexpand\db@row@elt@end@% row end + }% + \else + \toks@{#2}% + \@dtl@toks=\expandafter{\@dtl@newlist}% + \edef\@dtl@newlist{\the\@dtl@toks + \noexpand\db@row@elt@w% row header + \noexpand\db@row@id@w #1% + \noexpand\db@row@id@end@% row id + \the\toks@ % row contents + \noexpand\db@row@id@w #3% + \noexpand\db@row@id@end@% row id + \noexpand\db@row@elt@end@% row end + }% + \fi + \let\@dtl@donextdec=\@dtl@decrementrows + \fi + \@dtl@donextdec#4\@nil +} % \end{macrocode} -% Keep \sty{hyperref} happy +%\end{macro} +% +%\begin{macro}{\DTLremoverow} +%\begin{definition} +%\cs{DTLremoverow}\marg{db}\marg{row index} +%\end{definition} +% Remove row with given index from database named \meta{db}. +%\changes{2.0}{2009 February 27}{new} % \begin{macrocode} - \refstepcounter{DTLrow}% +\newcommand*{\DTLremoverow}[2]{% % \end{macrocode} -% Make it global (so that it works in tabular environment) +% Check database exists % \begin{macrocode} - \global\c@DTLrow=\c@DTLrow\relax + \DTLifdbexists{#1}% + {% % \end{macrocode} -% Store database name +% Check index if index is out of bounds % \begin{macrocode} - \gdef\@dtl@dbname{#2}% + \ifnum#2>0\relax % \end{macrocode} -% Increment level and check not exceeded 3 +% Check if data base has at least \meta{row index} rows % \begin{macrocode} - \global\advance\dtlforeachlevel by 1\relax - \ifnum\dtlforeachlevel>3\relax - \PackageError{datatool}{\string\DTLforeach\space nested too - deeply}{Only 3 levels are allowed}% + \expandafter\ifnum\csname dtlrows@#1\endcsname<#2\relax + \expandafter\ifnum\csname dtlrows@#1\endcsname=1\relax + \PackageError{datatool}{Can't remove row `\number#2' from + database `#1': no such row}{Database `#1' only has + 1 row}% + \else + \PackageError{datatool}{Can't remove row `\number#2' from + database `#1': no such row}{Database `#1' only has + \expandafter\number\csname dtlrows@#1\endcsname\space + rows}% + \fi + \else + \@DTLremoverow{#1}{#2}% + \fi \else - \@DTLifdbempty{#2}% + \PackageError{datatool}{Can't remove row \number#2: index + out of bounds}{Row indices start at 1}% + \fi + }% + {% + \PackageError{datatool}{Can't remove row: database `#1' doesn't + exist}{}% + }% +} % \end{macrocode} -% Do nothing if database is empty +%\end{macro} +% +%\begin{macro}{\@DTLremoverow} +%\begin{definition} +%\cs{@DTLremoverow}\marg{db}\marg{row index} +%\end{definition} +% Doesn't perform any checks for the existence of the database +% or if the index is in range. +%\changes{2.0}{2009 February 27}{new} % \begin{macrocode} - {}% - {% +\newcommand*{\@DTLremoverow}[2]{% % \end{macrocode} -% Set level dependent information (needs to be global to ensure -% it works in the \env{tabular} environment). Row counter: +% Get row from data base % \begin{macrocode} - \expandafter\global - \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname - = 0\relax + \edef\dtl@dogetrow{\noexpand\dtlgetrow{#1}{\number#2}}% + \dtl@dogetrow % \end{macrocode} -% Store previous value of \cs{DTLiffirstrow} +% Update the row indices % \begin{macrocode} - \expandafter\global\expandafter\let% - \csname @dtl@iffirstrow\the\dtlforeachlevel\endcsname - \DTLiffirstrow + \expandafter\dtl@decrementrows\expandafter + {\dtlbeforerow}{#2}% + \expandafter\dtl@decrementrows\expandafter + {\dtlafterrow}{#2}% % \end{macrocode} -% Define current \cs{DTLiffirstrow} +% Reconstruct database % \begin{macrocode} - \gdef\DTLiffirstrow##1##2{% - \expandafter\ifnum - \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname - =1\relax - ##1% - \else - ##2% - \fi}% + \edef\dtl@tmp{\the\dtlbeforerow \the\dtlafterrow}% + \expandafter\global\csname dtldb@#1\endcsname + =\expandafter{\dtl@tmp}% % \end{macrocode} -% Store previous value of \cs{DTLiflastrow} +% decrement row counter % \begin{macrocode} - \expandafter\global\expandafter\let% - \csname @dtl@iflastrow\the\dtlforeachlevel\endcsname - \DTLiflastrow + \expandafter\global\expandafter\advance + \csname dtlrows@#1\endcsname by -1\relax +} % \end{macrocode} -% Define current \cs{DTLiflastrow} +%\end{macro} +% +%\section{Database Functions} +% +%\begin{macro}{\DTLsumforkeys} +%\begin{definition} +%\cs{DTLsumforkeys}\oarg{condition}\oarg{assign list}\marg{db list}\marg{key list}\marg{cmd} +%\end{definition} +% Sums all entries for key \meta{key} over all databases listed +% in \meta{db list}, +% and stores in \meta{cmd}, which must be a control sequence. +% The first argument \meta{condition} is the same as that +% for \cs{DTLforeach}. The second optional argument provides +% an assignment list to pass to \cs{DTLforeach} in case extra +% information is need by \meta{condition}. +%\changes{2.0}{2009 February 27}{added second optional argument} % \begin{macrocode} - \gdef\DTLiflastrow##1##2{% - \expandafter\ifnum - \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname - =\csname dtlcols@#2\endcsname\relax - ##1% - \else - ##2% - \fi}% +\newcommand*{\DTLsumforkeys}[1][\boolean{true}\and + \DTLisnumerical{\DTLthisval}]{% + \def\@dtl@cond{#1}% + \@dtlsumforkeys +} % \end{macrocode} -% Store previous value of \cs{DTLifoddrow} +%\end{macro} +% +%\begin{macro}{\@dtlsumforkeys} % \begin{macrocode} - \expandafter\global\expandafter\let% - \csname @dtl@ifoddrow\the\dtlforeachlevel\endcsname - \DTLifoddrow +\newcommand*{\@dtlsumforkeys}[4][]{% + \def#4{0}% % \end{macrocode} -% Define current \cs{DTLifoddrow} +% Iterate over all the listed data bases % \begin{macrocode} - \gdef\DTLifoddrow##1##2{% - \expandafter\ifodd - \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname - ##1% - \else - ##2% - \fi}% + \@for\@dtl@dbname:=#2\do{% % \end{macrocode} -% Store data base name for current level +% Iterate through this database (using read only version) % \begin{macrocode} - \expandafter\global\expandafter\let - \csname @dtl@dbname@\romannumeral\dtlforeachlevel\endcsname - =\@dtl@dbname + \@sDTLforeach{\@dtl@dbname}% + {#1}% assignment list + {% % \end{macrocode} -% Mark it as not read only +% Iterate through key list. % \begin{macrocode} - \expandafter\global\expandafter\let - \csname @dtl@ro@\romannumeral\dtlforeachlevel\endcsname - = 0\relax + \@for\@dtl@key:=#3\do{% + \@sdtl@getcolumnindex{\@dtl@col}{\@dtl@dbname}{\@dtl@key}% + \dtlcurrentrow=\expandafter{\dtl@thisrow}% + \dtlgetentryfromrow{\DTLthisval}{\@dtl@col}{\dtlcurrentrow}% + \expandafter\ifthenelse\expandafter{\@dtl@cond}% + {\DTLadd{#4}{#4}{\DTLthisval}}{}% + }% + }% + }% +} % \end{macrocode} -% Loop through each row. -% Loop counter given by \cs{dtl@row@}\meta{level} +%\end{macro} +% +%\begin{macro}{\DTLsumcolumn} +%\begin{definition} +%\cs{DTLsumcolumn}\marg{db}\marg{key}\marg{cmd} +%\end{definition} +% Quicker version of \cs{DTLsumforkeys} that just sums over +% one column (specified by \meta{key}) for a single database +% (specified by \meta{db}) and stores the result in \meta{cmd}. +%\changes{2.0}{2009 February 27}{new} % \begin{macrocode} - \dtlgforint - \csname dtl@row\romannumeral\dtlforeachlevel\endcsname - =1\to\csname dtlrows@#2\endcsname\step1\do - {% +\newcommand*{\DTLsumcolumn}[3]{% + \def#3{0}% % \end{macrocode} -% Get current row from the data base +% Check data base exists % \begin{macrocode} - \@dtl@tmpcount= - \csname dtl@row\romannumeral\dtlforeachlevel\endcsname - \edef\dtl@dogetrow{\noexpand\dtlgetrow{#2}% - {\number\@dtl@tmpcount}}% - \dtl@dogetrow + \DTLifdbexists{#1}% + {% % \end{macrocode} -% Store the current row for this level +% Check column exists % \begin{macrocode} - \expandafter\global - \csname @dtl@cur\romannumeral\dtlforeachlevel\endcsname - = \dtlcurrentrow + \@sDTLifhaskey{#1}{#2}% + {% + \@sdtlforcolumn{\DTLthisval}{#1}{#2}% + {% + \DTLadd{#3}{#3}{\DTLthisval}% + }% + }% % \end{macrocode} -% Store the previous rows for this level +% key not defined for this data base % \begin{macrocode} - \expandafter\global - \csname @dtl@prev\romannumeral\dtlforeachlevel\endcsname - = \dtlbeforerow -% \end{macrocode} -% Store the subsequent rows for this level -% \begin{macrocode} - \expandafter\global - \csname @dtl@next\romannumeral\dtlforeachlevel\endcsname - = \dtlafterrow -% \end{macrocode} -% Assign commands to the required entries -% \begin{macrocode} - \ifx\relax#3\relax - \else - \@dtl@assign{#3}{#2}% - \fi -% \end{macrocode} -% Do the main body of text if condition is satisfied -% \begin{macrocode} - \ifthenelse{#1}% - {% -% \end{macrocode} -% Increment user row counter -% \begin{macrocode} - \refstepcounter{DTLrow\romannumeral\dtlforeachlevel}% - \expandafter\edef\expandafter\DTLcurrentindex% - \expandafter{% - \arabic{DTLrow\romannumeral\dtlforeachlevel}}% - #4% + {% + \PackageError{datatool}{Key `#2' doesn't + exist in database `#1'}{}% + }% + }% % \end{macrocode} -% Has this row been marked for deletion? +% data base doesn't exist % \begin{macrocode} - \edef\@dtl@tmp{\expandafter\the - \csname @dtl@cur\romannumeral - \dtlforeachlevel\endcsname}% - \ifx\@dtl@tmp\@nnil + {% + \PackageError{datatool}{Data base `#1' doesn't + exist}{}% + }% +} % \end{macrocode} -% Row needs to be deleted -% Decrement row indices for rows with a higher index than this one +%\end{macro} +% +%\begin{macro}{\DTLmeanforkeys} +%\begin{definition} +%\cs{DTLmeanforkeys}\oarg{condition}\oarg{assign list}\marg{db list}\marg{key list}\marg{cmd} +%\end{definition} +% Computes the arithmetic mean of all entries for each key in +% \meta{key list} over all databases in \meta{db list}, +% and stores in \meta{cmd}, which must be a control sequence. +% The first argument \meta{condition} is the same as that +% for \cs{DTLforeach}. The second optional argument allows an +% assignment list to be passed to \cs{DTLforeach}. +%\changes{2.0}{2009 February 27}{added second optional argument} % \begin{macrocode} - \expandafter\dtl@decrementrows\expandafter - {\csname @dtl@prev\romannumeral - \dtlforeachlevel\endcsname - }{\csname dtl@row\romannumeral - \dtlforeachlevel\endcsname}% - \expandafter\dtl@decrementrows\expandafter - {\csname @dtl@next\romannumeral - \dtlforeachlevel\endcsname - }{\csname dtl@row\romannumeral - \dtlforeachlevel\endcsname}% +\newcommand*{\DTLmeanforkeys}[1][\boolean{true}\and + \DTLisnumerical{\DTLthisval}]{% + \def\@dtl@cond{#1}% + \@dtlmeanforkeys +} % \end{macrocode} -% Reconstruct data base without this row +%\end{macro} +% +%\begin{macro}{\@dtl@elements} +% Count register to keep track of number of elements % \begin{macrocode} - \edef\@dtl@tmp{% - \expandafter\the - \csname @dtl@prev\romannumeral - \dtlforeachlevel\endcsname - \expandafter\the - \csname @dtl@next\romannumeral - \dtlforeachlevel\endcsname - }% - \expandafter\global\expandafter - \csname dtldb@#2\endcsname\expandafter{\@dtl@tmp}% +\newcount\@dtl@elements % \end{macrocode} -% Decrement the row count for this database: +%\end{macro} +% +%\begin{macro}{\@dtlmeanforkeys} % \begin{macrocode} - \expandafter\global\expandafter - \advance\csname dtlrows@#2\endcsname by -1\relax +\newcommand*{\@dtlmeanforkeys}[4][]{% + \def#4{0}% + \@dtl@elements=0\relax % \end{macrocode} -% Decrement the counter for this loop +% Iterate over all the listed data bases % \begin{macrocode} - \expandafter\global\expandafter - \advance\csname dtl@row\romannumeral - \dtlforeachlevel\endcsname by -1\relax - \else + \@for\@dtl@dbname:=#2\do{% % \end{macrocode} -% Reconstruct data base +% Iterate through this database (using read only version) % \begin{macrocode} - \@dtl@before=\csname @dtl@prev\romannumeral - \dtlforeachlevel\endcsname - \@dtl@after=\csname @dtl@next\romannumeral - \dtlforeachlevel\endcsname - \toks@gconcat@middle@cx{dtldb@#2}% - {\@dtl@before}% - {% + \@sDTLforeach{\@dtl@dbname}% + {#1}% assignment list + {% % \end{macrocode} -% This row +% Iterate through key list. % \begin{macrocode} - \noexpand\db@row@elt@w% - \noexpand\db@row@id@w \expandafter\number - \csname dtl@row\romannumeral - \dtlforeachlevel\endcsname - \noexpand\db@row@id@end@% - \expandafter\the - \csname @dtl@cur\romannumeral - \dtlforeachlevel\endcsname - \noexpand\db@row@id@w \expandafter\number - \csname dtl@row\romannumeral - \dtlforeachlevel\endcsname - \noexpand\db@row@id@end@% - \noexpand\db@row@elt@end@% - }% - {\@dtl@after}% - \fi - }% + \@for\@dtl@key:=#3\do{% + \@sdtl@getcolumnindex{\@dtl@col}{\@dtl@dbname}{\@dtl@key}% + \dtlcurrentrow=\expandafter{\dtl@thisrow}% + \dtlgetentryfromrow{\DTLthisval}{\@dtl@col}{\dtlcurrentrow}% + \expandafter\ifthenelse\expandafter{\@dtl@cond}% + {% + \DTLadd{#4}{#4}{\DTLthisval}% + \advance\@dtl@elements by 1\relax + }{}% + }% + }% + }% % \end{macrocode} -% Condition not met so ignore +% Divide total by number of elements summed. % \begin{macrocode} - {}% - }% + \ifnum\@dtl@elements=0\relax +% \PackageError{datatool}{Unable to evaluate mean: no data}{}% + \else + \edef\@dtl@n{\number\@dtl@elements}% + \DTLdiv{#4}{#4}{\@dtl@n}% + \fi +} % \end{macrocode} -% Restore previous value of \cs{DTLiffirstrow} +%\end{macro} +% +%\begin{macro}{\DTLmeanforcolumn} +%\begin{definition} +%\cs{DTLmeanforcolumn}\marg{db}\marg{key}\marg{cmd} +%\end{definition} +% Quicker version of \cs{DTLmeanforkeys} that just computes the +% mean over one column (specified by \meta{key}) for a single +% database (specified by \meta{db}) and stores the result in +% \meta{cmd}. +%\changes{2.0}{2009 February 27}{new} % \begin{macrocode} - \expandafter\global\expandafter\let\expandafter\DTLiffirstrow - \csname @dtl@iffirstrow\the\dtlforeachlevel\endcsname +\newcommand*{\DTLmeanforcolumn}[3]{% + \def#3{0}% + \@dtl@elements=0\relax % \end{macrocode} -% Restore previous value of \cs{DTLiflastrow} +% Check data base exists % \begin{macrocode} - \expandafter\global\expandafter\let\expandafter\DTLiflastrow - \csname @dtl@iflastrow\the\dtlforeachlevel\endcsname + \DTLifdbexists{#1}% + {% % \end{macrocode} -% Restore previous value of \cs{DTLifoddrow} +% Check column exists % \begin{macrocode} - \expandafter\global\expandafter\let\expandafter\DTLifoddrow - \csname @dtl@ifoddrow\the\dtlforeachlevel\endcsname - }% - \fi + \@sDTLifhaskey{#1}{#2}% + {% + \@sdtlforcolumn{\DTLthisval}{#1}{#2}% + {% + \DTLadd{#3}{#3}{\DTLthisval}% + \advance\@dtl@elements by 1\relax + }% + \ifnum\@dtl@elements=0\relax + \PackageError{datatool}{Can't compute mean for + column `#2' in database `#1': no data}{}% + \else + \edef\@dtl@n{\number\@dtl@elements}% + \DTLdiv{#3}{#3}{\@dtl@n}% + \fi + }% % \end{macrocode} -% Decrement level +% key not defined for this data base % \begin{macrocode} - \global\advance\dtlforeachlevel by -1\relax + {% + \PackageError{datatool}{Key `#2' doesn't + exist in database `#1'}{}% + }% }% % \end{macrocode} -% else part (data base doesn't exist): +% data base doesn't exist % \begin{macrocode} {% - \PackageError{datatool}{Database `#2' doesn't exist}{}% + \PackageError{datatool}{Data base `#1' doesn't + exist}{}% }% } % \end{macrocode} %\end{macro} % -%\begin{macro}{\@sDTLforeach} -% \cs{@sDTLforeach} is the starred version of \cs{DTLforeach}. -% The database rows can't be edited. -%\changes{2.0}{2009 February 27}{updated to use new database structure} +%\begin{macro}{\DTLvarianceforkeys} +%\begin{definition} +%\cs{DTLvarianceforkeys}\oarg{condition}\oarg{assign list}\marg{db list}\marg{key list}\marg{cmd} +%\end{definition} +% Computes the variance of all entries for each key in +% \meta{key list} over all databases in \meta{db list}, +% and stores in \meta{cmd}, which must be a control sequence. +% The first optional argument \meta{condition} is the same as that +% for \cs{DTLforeach}. The second optional argument is an assignment +% list to pass to \cs{DTLforeach} in case it is required for the +% condition. +%\changes{2.0}{2009 February 27}{added second optional argument} % \begin{macrocode} -\newcommand{\@sDTLforeach}[4][\boolean{true}]{% +\newcommand*{\DTLvarianceforkeys}[1][\boolean{true}\and + \DTLisnumerical{\DTLthisval}]{% + \def\@dtl@cond{#1}% + \@dtlvarianceforkeys +} % \end{macrocode} -% Check database exists +%\end{macro} +% +%\begin{macro}{\@dtlmeanforkeys} % \begin{macrocode} - \DTLifdbexists{#2}% - {% +\newcommand*{\@dtlvarianceforkeys}[4][]{% + \@dtlmeanforkeys[#1]{#2}{#3}{\dtl@mean}% + \def#4{0}% + \@dtl@elements=0\relax % \end{macrocode} -% Keep \sty{hyperref} happy +% Iterate over all the listed data bases % \begin{macrocode} - \refstepcounter{DTLrow}% + \@for\@dtl@dbname:=#2\do{% % \end{macrocode} -% Make it global (so that it works in tabular environment) +% Iterate through this database (using read only version) % \begin{macrocode} - \global\c@DTLrow=\c@DTLrow + \@sDTLforeach{\@dtl@dbname}% + {#1}% assignment list + {% % \end{macrocode} -% Increment level and check not exceeded 3 +% Iterate through key list. % \begin{macrocode} - \global\advance\dtlforeachlevel by 1\relax - \ifnum\dtlforeachlevel>3\relax - \PackageError{datatool}{\string\DTLforeach\space nested too - deeply}{Only 3 levels are allowed}% - \else - \@DTLifdbempty{#2}% -% \end{macrocode} -% Do nothing if database is empty -% \begin{macrocode} - {}% - {% -% \end{macrocode} -% Set level dependent information (needs to be global to ensure -% it works in the \env{tabular} environment). Row counter: -% \begin{macrocode} - \expandafter\global - \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname - = 0\relax -% \end{macrocode} -% Store previous value of \cs{DTLiffirstrow} -% \begin{macrocode} - \expandafter\global\expandafter\let% - \csname @dtl@iffirstrow\the\dtlforeachlevel\endcsname - \DTLiffirstrow -% \end{macrocode} -% Define current \cs{DTLiffirstrow} -% \begin{macrocode} - \gdef\DTLiffirstrow##1##2{% - \expandafter\ifnum - \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname - =1\relax - ##1% - \else - ##2% - \fi}% -% \end{macrocode} -% Store previous value of \cs{DTLiflastrow} -% \begin{macrocode} - \expandafter\global\expandafter\let% - \csname @dtl@iflastrow\the\dtlforeachlevel\endcsname - \DTLiflastrow -% \end{macrocode} -% Define current \cs{DTLiflastrow} -% \begin{macrocode} - \gdef\DTLiflastrow##1##2{% - \expandafter\ifnum - \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname - =\csname dtlcols@#2\endcsname\relax - ##1% - \else - ##2% - \fi}% -% \end{macrocode} -% Store previous value of \cs{DTLifoddrow} -% \begin{macrocode} - \expandafter\global\expandafter\let% - \csname @dtl@ifoddrow\the\dtlforeachlevel\endcsname - \DTLifoddrow -% \end{macrocode} -% Define current \cs{DTLifoddrow} -% \begin{macrocode} - \gdef\DTLifoddrow##1##2{% - \expandafter\ifodd - \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname - ##1% - \else - ##2% - \fi}% -% \end{macrocode} -% Store data base name for current level -% \begin{macrocode} - \expandafter\gdef\csname @dtl@dbname@\romannumeral - \dtlforeachlevel\endcsname{#2}% -% \end{macrocode} -% Mark it as read only -% \begin{macrocode} - \expandafter\global\expandafter\let - \csname @dtl@ro@\romannumeral\dtlforeachlevel\endcsname - = 1\relax -% \end{macrocode} -% Iterate through each row. -% \begin{macrocode} - \@dtlforeachrow(\dtl@thisidx,\dtl@thisrow)\in{#2}\do% + \@for\@dtl@key:=#3\do{% + \@sdtl@getcolumnindex{\@dtl@col}{\@dtl@dbname}{\@dtl@key}% + \dtlcurrentrow=\expandafter{\dtl@thisrow}% + \dtlgetentryfromrow{\DTLthisval}{\@dtl@col}{\dtlcurrentrow}% + \expandafter\ifthenelse\expandafter{\@dtl@cond}% {% % \end{macrocode} -% Assign row number (not sure if this is needed here) -% \begin{macrocode} - \csname dtl@row\romannumeral\dtlforeachlevel\endcsname - = \dtl@thisidx\relax -% \end{macrocode} -% Store the current row specs for this level -% \begin{macrocode} - \expandafter\global - \csname @dtl@cur\romannumeral\dtlforeachlevel\endcsname - = \expandafter{\dtl@thisrow}% -% \end{macrocode} -% Assign commands to the required entries -% \begin{macrocode} - \ifx\relax#3\relax - \else -% \end{macrocode} -% Need to set \cs{dtlcurrentrow} for \cs{@dtl@assign} -% \begin{macrocode} - \dtlcurrentrow=\expandafter{\dtl@thisrow}% - \@dtl@assign{#3}{#2}% - \fi -% \end{macrocode} -% Do the main body of text if condition is satisfied +% compute $(x_i - \mu)^2$ % \begin{macrocode} - \ifthenelse{#1}% - {% + \DTLsub{\dtl@diff}{\DTLthisval}{\dtl@mean}% + \DTLmul{\dtl@diff}{\dtl@diff}{\dtl@diff}% + \DTLadd{#4}{#4}{\dtl@diff}% + \advance\@dtl@elements by 1\relax + }{}% + }% + }% + }% % \end{macrocode} -% Increment user row counter +% Divide by number of elements. % \begin{macrocode} - \refstepcounter{DTLrow\romannumeral\dtlforeachlevel}% - \expandafter\edef\expandafter\DTLcurrentindex% - \expandafter{% - \arabic{DTLrow\romannumeral\dtlforeachlevel}}% - #4% - }% + \ifnum\@dtl@elements=0\relax + \PackageError{datatool}{Unable to evaluate variance: no data}{}% + \else + \edef\@dtl@n{\number\@dtl@elements}% + \DTLdiv{#4}{#4}{\@dtl@n}% + \fi +} % \end{macrocode} -% Condition not met so ignore +%\end{macro} +% +%\begin{macro}{\DTLvarianceforcolumn} +%\begin{definition} +%\cs{DTLvarianceforcolumn}\marg{db}\marg{key}\marg{cmd} +%\end{definition} +% Quicker version of \cs{DTLvarianceforkeys} that just computes the +% variance over one column (specified by \meta{key}) for a single +% database (specified by \meta{db}) and stores the result in +% \meta{cmd}. +%\changes{2.0}{2009 February 27}{new} % \begin{macrocode} - {}% - }% +\newcommand*{\DTLvarianceforcolumn}[3]{% + \DTLmeanforcolumn{#1}{#2}{\dtl@mean}% + \def#3{0}% + \@dtl@elements=0\relax % \end{macrocode} -% Restore previous value of \cs{DTLiffirstrow} +% Check data base exists % \begin{macrocode} - \expandafter\global\expandafter\let\expandafter\DTLiffirstrow - \csname @dtl@iffirstrow\the\dtlforeachlevel\endcsname + \DTLifdbexists{#1}% + {% % \end{macrocode} -% Restore previous value of \cs{DTLiflastrow} +% Check column exists % \begin{macrocode} - \expandafter\global\expandafter\let\expandafter\DTLiflastrow - \csname @dtl@iflastrow\the\dtlforeachlevel\endcsname + \@sDTLifhaskey{#1}{#2}% + {% + \@sdtlforcolumn{\DTLthisval}{#1}{#2}% + {% % \end{macrocode} -% Restore previous value of \cs{DTLifoddrow} +% compute $(x_i - \mu)^2$ % \begin{macrocode} - \expandafter\global\expandafter\let\expandafter\DTLifoddrow - \csname @dtl@ifoddrow\the\dtlforeachlevel\endcsname - }% - \fi + \DTLsub{\dtl@diff}{\DTLthisval}{\dtl@mean}% + \DTLmul{\dtl@diff}{\dtl@diff}{\dtl@diff}% + \DTLadd{#3}{#3}{\dtl@diff}% + \advance\@dtl@elements by 1\relax + }% + \ifnum\@dtl@elements=0\relax + \PackageError{datatool}{Can't compute variance for + column `#2' in database `#1': no data}{}% + \else + \edef\@dtl@n{\number\@dtl@elements}% + \DTLdiv{#3}{#3}{\@dtl@n}% + \fi + }% % \end{macrocode} -% Decrement level +% key not defined for this data base % \begin{macrocode} - \global\advance\dtlforeachlevel by -1\relax + {% + \PackageError{datatool}{Key `#2' doesn't + exist in database `#1'}{}% + }% }% % \end{macrocode} -% else part (data base doesn't exist): +% data base doesn't exist % \begin{macrocode} {% - \PackageError{datatool}{Database `#2' doesn't exist}{}% + \PackageError{datatool}{Data base `#1' doesn't + exist}{}% }% } % \end{macrocode} %\end{macro} % -%\begin{macro}{\@dtlifreadonly} +% +%\begin{macro}{\DTLsdforkeys} %\begin{definition} -%\cs{@dtlifreadonly}\marg{true part}\marg{false part} +%\cs{DTLsdforkeys}\oarg{condition}\oarg{assign list}\marg{db list}\marg{key list}\marg{cmd} %\end{definition} -% Checks if current loop level is read only -%\changes{2.0}{2009 February 27}{new} +% Computes the standard deviation of all entries for each key in +% \meta{key list} over all databases in \meta{db list}, +% and stores in \meta{cmd}, which must be a control sequence. +% The first optional argument \meta{condition} is the same as that +% for \cs{DTLforeach}. The second optional argument is an +% assignment list for \cs{DTLforeach} in case it is needed for +% the condition. +%\changes{2.0}{2009 February 27}{added second optional argument} % \begin{macrocode} -\newcommand*{\@dtlifreadonly}[2]{% - \expandafter\ifx - \csname @dtl@ro@\romannumeral\dtlforeachlevel\endcsname1\relax +\newcommand*{\DTLsdforkeys}[1][\boolean{true}\and +\DTLisnumerical{\DTLthisval}]{% + \def\@dtl@cond{#1}% + \@dtlsdforkeys +} % \end{macrocode} -% Read only +%\end{macro} +%\begin{macro}{\@dtlsdforkeys} % \begin{macrocode} - #1% - \else +\newcommand*{\@dtlsdforkeys}[4][]{% + \@dtlvarianceforkeys[#1]{#2}{#3}{#4}% + \DTLsqrt{#4}{#4}% +} % \end{macrocode} -% Not read only +%\end{macro} +% +%\begin{macro}{\DTLsdforcolumn} +%\begin{definition} +%\cs{DTLsdforcolumn}\marg{db}\marg{key}\marg{cmd} +%\end{definition} +% Quicker version of \cs{DTLsdforkeys} that just computes the +% standard deviation over one column (specified by \meta{key}) for +% a single database (specified by \meta{db}) and stores the result +% in \meta{cmd}. +%\changes{2.0}{2009 February 27}{new} % \begin{macrocode} - #2% - \fi +\newcommand*{\DTLsdforcolumn}[3]{% + \DTLvarianceforcolumn{#1}{#2}{#3}% + \DTLsqrt{#3}{#3}% } % \end{macrocode} %\end{macro} % -%\begin{macro}{\DTLappendtorow} +%\begin{macro}{\DTLminforkeys} %\begin{definition} -%\cs{DTLappendtorow}\marg{key}\marg{value} +%\cs{DTLminforkeys}\oarg{condition}\oarg{assign list}\marg{db list}\marg{key list}\marg{cmd} %\end{definition} -% Appends entry to current row. (The current row is given by -% \cs{@dtl@cur}\meta{n} where \meta{n} is roman -% numeral value of \cs{dtlforeachlevel}. -% One level expansion is applied to \meta{value}. -%\changes{2.0}{2009 February 27}{updated to use new database structure} +% Determines the minimum over all entries for each key in +% \meta{key list} over all databases in \meta{db list}, +% and stores in \meta{cmd}, which must be a control sequence. +% The first optional argument \meta{condition} is the same as that +% for \cs{DTLforeach}. The second optional argument is an +% assignment list for \cs{DTLforeach} in the event that extra +% information is need for the condition. +%\changes{2.0}{2009 February 27}{added second optional argument} % \begin{macrocode} -\newcommand*{\DTLappendtorow}[2]{% - \ifnum\dtlforeachlevel=0\relax - \PackageError{datatool}{\string\DTLappendrow\space can only be - used inside \string\DTLforeach}{}% - \else +\newcommand*{\DTLminforkeys}[1][\boolean{true}\and + \DTLisnumerical{\DTLthisval}]{% + \def\@dtl@cond{#1}% + \@dtlminforkeys +} % \end{macrocode} -% Set \cs{@dtl@thisdb} to the current database name: +%\end{macro} +% +%\begin{macro}{\@dtlminforkeys} % \begin{macrocode} - \expandafter\let\expandafter\@dtl@thisdb - \csname @dtl@dbname@\romannumeral\dtlforeachlevel\endcsname +\newcommand*{\@dtlminforkeys}[4][]{% + \def#4{}% % \end{macrocode} -% Check this isn't in \cs{DTLforeach*} +% Iterate over all the listed data bases % \begin{macrocode} - \@dtlifreadonly + \@for\@dtl@dbname:=#2\do{% +% \end{macrocode} +% Iterate through this database (using read only version) +% \begin{macrocode} + \@sDTLforeach{\@dtl@dbname}% + {#1}% assignment list {% - \PackageError{datatool}{\string\DTLappendtorow\space can't - be used inside \DTLforeach*}{The starred version of - \string\DTLforeach\space is read only}% +% \end{macrocode} +% Iterate through key list. +% \begin{macrocode} + \@for\@dtl@key:=#3\do{% + \@sdtl@getcolumnindex{\@dtl@col}{\@dtl@dbname}{\@dtl@key}% + \dtlcurrentrow=\expandafter{\dtl@thisrow}% + \dtlgetentryfromrow{\DTLthisval}{\@dtl@col}{\dtlcurrentrow}% + \expandafter\ifthenelse\expandafter{\@dtl@cond}% + {% + \ifstrempty{#4}% + {% + \let#4\DTLthisval + }% + {% + \DTLmin{#4}{#4}{\DTLthisval}% + }% + }{}% + }% }% - {% + }% +} % \end{macrocode} -% Store current row number in \cs{dtlrownum} +%\end{macro} +% +%\begin{macro}{\DTLminforcolumn} +%\begin{definition} +%\cs{DTLminforcolumn}\marg{db}\marg{key}\marg{cmd} +%\end{definition} +% Quicker version of \cs{DTLminforkeys} that just finds the +% minimum value in one column (specified by \meta{key}) for a +% single database (specified by \meta{db}) and stores the result +% in \meta{cmd}. +%\changes{2.0}{2009 February 27}{new} % \begin{macrocode} - \dtlrownum= - \csname dtl@row\romannumeral\dtlforeachlevel\endcsname\relax +\newcommand*{\DTLminforcolumn}[3]{% + \def#3{}% % \end{macrocode} -% Update information about this column (adding new column if -% necessary) +% Check data base exists % \begin{macrocode} - \@dtl@updatekeys{\@dtl@thisdb}{#1}{#2}% + \DTLifdbexists{#1}% + {% % \end{macrocode} -% Get column index and store in \cs{dtlcolumnnum} +% Check column exists % \begin{macrocode} - \expandafter\dtlcolumnnum\expandafter - =\dtlcolumnindex{\@dtl@thisdb}{#1}\relax + \@sDTLifhaskey{#1}{#2}% + {% + \@sdtlforcolumn{\DTLthisval}{#1}{#2}% + {% + \ifdefempty{#3}% + {% + \let#3\DTLthisval + }% + {% + \DTLmin{#3}{#3}{\DTLthisval}% + }% + }% + }% % \end{macrocode} -% Set \cs{dtlcurrentrow} to the current row +% key not defined for this data base % \begin{macrocode} - \dtlcurrentrow = - \csname @dtl@cur\romannumeral\dtlforeachlevel\endcsname + {% + \PackageError{datatool}{Key `#2' doesn't + exist in database `#1'}{}% + }% + }% % \end{macrocode} -% Does this row already have an entry with this key? +% data base doesn't exist % \begin{macrocode} - \edef\dtl@dogetentry{\noexpand\dtlgetentryfromcurrentrow - {\noexpand\dtl@entry}{\number\dtlcolumnnum}% - }% - \dtl@dogetentry - \ifx\dtl@entry\dtlnovalue + {% + \PackageError{datatool}{Data base `#1' doesn't + exist}{}% + }% +} % \end{macrocode} -% There are no entries in this row for the given key. -% Expand entry value before storing. -%\changes{2.03}{2009 November 15}{value expanded before storing} +%\end{macro} +% +% +%\begin{macro}{\DTLmaxforkeys} +%\begin{definition} +%\cs{DTLmaxforkeys}\oarg{condition}\oarg{assign list}\marg{db list}\marg{key list}\marg{cmd} +%\end{definition} +% Determines the maximum over all entries for each key in +% \meta{key list} over all databases in \meta{db list}, +% and stores in \meta{cmd}, which must be a control sequence. +% The first optional argument \meta{condition} is the same as that +% for \cs{DTLforeach}. The second optional argument is an +% assignment list to pass to \cs{DTLforeach} in the event that +% extra information is required in the condition. +%\changes{2.0}{2009 February 27}{added second optional argument} % \begin{macrocode} - \protected@edef\@dtl@tmp{#2}% - \expandafter\@dtl@toks\expandafter{\@dtl@tmp}% +\newcommand*{\DTLmaxforkeys}[1][\boolean{true}\and + \DTLisnumerical{\DTLthisval}]{% + \def\@dtl@cond{#1}% + \@dtlmaxforkeys +} % \end{macrocode} -% Append this entry to the current row. +%\end{macro} +% +%\begin{macro}{\@dtlmaxforkeys} % \begin{macrocode} - \toks@gput@right@cx{@dtl@cur\romannumeral\dtlforeachlevel}% - {% - \noexpand\db@col@id@w \number\dtlcolumnnum - \noexpand\db@col@id@end@ - \noexpand\db@col@elt@w \the\@dtl@toks - \noexpand\db@col@elt@end@ - \noexpand\db@col@id@w \number\dtlcolumnnum - \noexpand\db@col@id@end@ - }% +\newcommand*{\@dtlmaxforkeys}[4][]{% + \def#4{}% % \end{macrocode} -% Print information to terminal and log file if in verbose mode. +% Iterate over all the listed data bases % \begin{macrocode} - \dtl@message{Appended #1\space -> #2\space to database - `\@dtl@thisdb'}% - \else + \@for\@dtl@dbname:=#2\do{% % \end{macrocode} -% There is already an entry in this row for the given key +% Iterate through this database (using read only version) % \begin{macrocode} - \PackageError{datatool}{Can't append entry to row: - there is already an entry for key `#1' in this row}{}% - \fi + \@sDTLforeach{\@dtl@dbname}% + {#1}% assignment list + {% +% \end{macrocode} +% Iterate through key list. +% \begin{macrocode} + \@for\@dtl@key:=#3\do{% + \@sdtl@getcolumnindex{\@dtl@col}{\@dtl@dbname}{\@dtl@key}% + \dtlcurrentrow=\expandafter{\dtl@thisrow}% + \dtlgetentryfromrow{\DTLthisval}{\@dtl@col}{\dtlcurrentrow}% + \expandafter\ifthenelse\expandafter{\@dtl@cond}% + {% + \ifdefempty{#4}% + {% + \let#4\DTLthisval + }% + {% + \DTLmax{#4}{#4}{\DTLthisval}% + }% + }{}% + }% }% - \fi + }% } % \end{macrocode} %\end{macro} % -%\begin{macro}{\DTLremoveentryfromrow} +%\begin{macro}{\DTLmaxforcolumn} %\begin{definition} -%\cs{DTLremoveentryfromrow}\marg{key} +%\cs{DTLmaxforcolumn}\marg{db}\marg{key}\marg{cmd} %\end{definition} -% Removes entry given by \meta{key} from current row. -% (The current row is given by -% \cs{@dtl@cur}\meta{n} where \meta{n} is roman -% numeral value of \cs{dtlforeachlevel}. -%\changes{2.0}{2009 February 27}{updated to use new database structure} +% Quicker version of \cs{DTLmaxforkeys} that just finds the +% maximum value in one column (specified by \meta{key}) for a +% single database (specified by \meta{db}) and stores the result +% in \meta{cmd}. +%\changes{2.0}{2009 February 27}{new} % \begin{macrocode} -\newcommand*{\DTLremoveentryfromrow}[1]{% - \ifnum\dtlforeachlevel=0\relax - \PackageError{datatool}{\string\DTLremoventryfromrow\space - can only be used inside \string\DTLforeach}{}% - \else +\newcommand*{\DTLmaxforcolumn}[3]{% + \def#3{}% % \end{macrocode} -% Set \cs{@dtl@thisdb} to the current database name: +% Check data base exists % \begin{macrocode} - \expandafter\let\expandafter\@dtl@thisdb - \csname @dtl@dbname@\romannumeral\dtlforeachlevel\endcsname + \DTLifdbexists{#1}% + {% % \end{macrocode} -% Check this isn't in \cs{DTLforeach*} +% Check column exists % \begin{macrocode} - \@dtlifreadonly - {% - \PackageError{datatool}{\string\DTLremoveentryfromrow\space - can't be used inside \string\DTLforeach*}{The starred - version of \string\DTLforeach\space is read only}% - }% - {% + \@sDTLifhaskey{#1}{#2}% + {% + \@sdtlforcolumn{\DTLthisval}{#1}{#2}% + {% + \ifdefempty{#3}% + {% + \let#3\DTLthisval + }% + {% + \DTLmax{#3}{#3}{\DTLthisval}% + }% + }% + }% % \end{macrocode} -% Store current row number in \cs{dtlrownum} +% key not defined for this data base % \begin{macrocode} - \dtlrownum= - \csname dtl@row\romannumeral\dtlforeachlevel\endcsname\relax + {% + \PackageError{datatool}{Key `#2' doesn't + exist in database `#1'}{}% + }% + }% % \end{macrocode} -% Is there a column corresponding to this key? +% data base doesn't exist % \begin{macrocode} - \@DTLifhaskey{\@dtl@thisdb}{#1}% - {% + {% + \PackageError{datatool}{Data base `#1' doesn't + exist}{}% + }% +} % \end{macrocode} -% There exists a column for this key, so get the index: -% \begin{macrocode} - \@dtl@getcolumnindex{\thiscol}{\@dtl@thisdb}{#1}\relax - \dtlcolumnnum=\thiscol\relax +%\end{macro} +% +%\begin{macro}{\DTLcomputebounds} +%\begin{definition} +%\cs{DTLcomputebounds}\oarg{condition}\marg{db list}\marg{x key}\marg{y key}\marg{minX cmd}\marg{minY cmd}\marg{maxX cmd}\marg{maxY cmd} +%\end{definition} +% Computes the maximum and minimum $x$ and $y$ values over all +% the databases listed in \meta{db list} where the $x$ value +% is given by \meta{x key} and the $y$ value is given by +% \meta{y key}. The results are stored in \meta{minX cmd}, +% \meta{minY cmd}, \meta{maxX cmd} and \meta{maxY cmd} in +% standard decimal format. +% \begin{macrocode} +\newcommand*{\DTLcomputebounds}[8][\boolean{true}]{% +\let#5=\relax +\let#6=\relax +\let#7=\relax +\let#8=\relax +\@for\dtl@thisdb:=#2\do{% + \@sDTLforeach[#1]{\dtl@thisdb}{\DTLthisX=#3,\DTLthisY=#4}{% + \expandafter\DTLconverttodecimal\expandafter{\DTLthisX}{\dtl@decx}% + \expandafter\DTLconverttodecimal\expandafter{\DTLthisY}{\dtl@decy}% + \ifx#5\relax + \let#5=\dtl@decx + \let#6=\dtl@decy + \let#7=\dtl@decx + \let#8=\dtl@decy + \else + \dtlmin{#5}{#5}{\dtl@decx}% + \dtlmin{#6}{#6}{\dtl@decy}% + \dtlmax{#7}{#7}{\dtl@decx}% + \dtlmax{#8}{#8}{\dtl@decy}% + \fi + }% +}% +} % \end{macrocode} -% Set \cs{dtlcurrentrow} to the current row +%\end{macro} +% +%\begin{macro}{\DTLgetvalueforkey} +%\begin{definition} +%\cs{DTLgetvalueforkey}\marg{cmd}\marg{key}\marg{db name}\marg{ref +% key}\marg{ref value} +%\end{definition} +% This (globally) sets \meta{cmd} (a control sequence) to the +% value of the key specified by \meta{key} in the first row +% of the database called \meta{db name} which contains the key +% \meta{ref key} which has the value \meta{value}. +%\changes{1.01}{2007 Aug 17}{new} +%\changes{2.0}{2009 February 27}{updated to use new database +% structure} % \begin{macrocode} - \dtlcurrentrow = - \csname @dtl@cur\romannumeral\dtlforeachlevel\endcsname +\newcommand*{\DTLgetvalueforkey}[5]{% % \end{macrocode} -% Does this row have an entry with this key? +% Get row containing referenced (key,value) pair % \begin{macrocode} - \edef\dtl@dogetentry{\noexpand\dtlgetentryfromcurrentrow - {\noexpand\dtl@entry}{\number\dtlcolumnnum}% - }% - \dtl@dogetentry - \ifx\dtl@entry\dtlnovalue + \DTLgetrowforkey{\@dtl@row}{#3}{#4}{#5}% % \end{macrocode} -% This row doesn't contain an entry with this key +% Get column number for \meta{key} % \begin{macrocode} - \PackageError{datatool}{Can't remove entry given by `#1' - from current row in database `\@dtl@thisdb': no such - entry}{The current row doesn't contain an entry for - key `#1'}% - \else + \@sdtl@getcolumnindex{\@dtl@col}{#3}{#2}% % \end{macrocode} -% Split the current row around the unwanted entry +% Get value for given column % \begin{macrocode} - \edef\@dtl@dosplitrow{% - \noexpand\dtlsplitrow{\the\dtlcurrentrow}% - {\number\dtlcolumnnum}{\noexpand\dtl@pre}% - {\noexpand\dtl@post}% - }% - \@dtl@dosplitrow + {% + \dtlcurrentrow=\expandafter{\@dtl@row}% + \edef\@dtl@dogetval{\noexpand\dtlgetentryfromcurrentrow + {\noexpand\@dtl@val}{\@dtl@col}}% + \@dtl@dogetval + \global\let#1=\@dtl@val + }% +} % \end{macrocode} -% Reconstruct row without unwanted entry +%\end{macro} +% +%\begin{macro}{\DTLgetrowforkey} +%\begin{definition} +%\cs{DTLgetrowforkey}\marg{cmd}\marg{db name}\marg{ref +% key}\marg{ref value} +%\end{definition} +% This (globally) sets \meta{cmd} (a control sequence) to the +% first row +% of the database called \meta{db name} which contains the key +% \meta{ref key} that has the value \meta{value}. +%\changes{1.01}{2007 Aug 17}{new} +%\changes{2.0}{2009 February 27}{update to use new database +% structure} % \begin{macrocode} - \expandafter\@dtl@toks\expandafter{\dtl@pre}% - \expandafter\toks@\expandafter{\dtl@post}% - \edef\@dtl@tmp{\the\@dtl@toks \the\toks@}% - \dtlcurrentrow=\expandafter{\@dtl@tmp}% - \expandafter\global - \csname @dtl@cur\romannumeral\dtlforeachlevel\endcsname - = \dtlcurrentrow - \dtl@message{Removed entry given by #1\space from current - row of database `\@dtl@thisdb'}% - \fi - }% +\newcommand*{\DTLgetrowforkey}[4]{% + \global\let#1=\@empty + \@sDTLforeach{#2}{\dtl@refvalue=#3}{% + \DTLifnull{\dtl@refvalue}% + {}% + {% + \ifthenelse{\equal{\dtl@refvalue}{#4}}% {% - \PackageError{datatool}{Can't remove entry given by - `#1' - no such key exists}{}% + \xdef#1{\the\dtlcurrentrow}% + \dtlbreak }% + {}% }% - \fi + }% } % \end{macrocode} %\end{macro} % -%\begin{macro}{\DTLreplaceentryforrow} +%\section{Sorting Databases} +% +%\begin{macro}{\@dtl@list} +% Token register to store data when sorting. +%\changes{2.0}{2009 February 27}{new} +% \begin{macrocode} +\newtoks\@dtl@list +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLsort} %\begin{definition} -%\cs{DTLreplaceentryforrow}\marg{key}\marg{value} +% \cs{DTLsort}\oarg{replacement keys}\marg{sort criteria}\marg{db name} %\end{definition} -% Replaces entry given by \meta{key} in current row with -% \meta{value}. -% (The current row is given by the token register -% \cs{@dtl@cur}\meta{n} where \meta{n} is roman -% numeral value of \cs{dtlforeachlevel}. -%\changes{2.0}{2009 February 27}{updated to use new database structure} +% Sorts database \meta{db name} according to \marg{sort criteria}, +% which must be a comma separated list of keys, and optionally +% \texttt{=}\meta{order}, where \meta{order} is either +% "ascending" or "descending". The optional argument is a list of +% keys to uses if the given key has a null value. The starred +% version uses a case insensitive string comparison. +%\changes{1.01}{2007 Aug 17}{added optional argument} +%\changes{1.01}{2007 Aug 17}{added starred version} +%\changes{2.0}{2009 February 27}{updated to use new data structure} % \begin{macrocode} -\newcommand*{\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: +\newcommand*{\DTLsort}{\@ifstar\@sDTLsort\@DTLsort} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\@DTLsort} +% Unstarred (case sensitive) version. % \begin{macrocode} - \expandafter\let\expandafter\@dtl@thisdb - \csname @dtl@dbname@\romannumeral\dtlforeachlevel\endcsname +\newcommand{\@DTLsort}[3][]{% % \end{macrocode} -% Check this isn't in \cs{DTLforeach*} +% Check the database exists % \begin{macrocode} - \@dtlifreadonly - {% - \PackageError{datatool}{\string\DTLreplaceentryforrow\space - can't be used inside \string\DTLforeach*}{The starred version - of \string\DTLforeach\space is read only}% - }% - {% + \DTLifdbexists{#3}% + {% % \end{macrocode} -% Store current row number in \cs{dtlrownum} +% Store replacement keys in \cs{@dtl@replacementkeys}. % \begin{macrocode} - \dtlrownum= - \csname dtl@row\romannumeral\dtlforeachlevel\endcsname\relax + \edef\@dtl@replacementkeys{#1}% % \end{macrocode} -% Is there a column corresponding to this key? +% Store sort order in \cs{@dtl@sortorder}. % \begin{macrocode} - \@DTLifhaskey{\@dtl@thisdb}{#1}% - {% + \edef\@dtl@sortorder{#2}% % \end{macrocode} -% There exists a column for this key, so get the index: +% Set \cs{@dtl@comparecs} to the required string comparison +% function. (Using case sensitive comparison macro \cs{dtlcompare}.) % \begin{macrocode} - \@dtl@getcolumnindex{\thiscol}{\@dtl@thisdb}{#1}\relax - \dtlcolumnnum=\thiscol\relax + \let\@dtl@comparecs=\dtlcompare % \end{macrocode} -% Set \cs{dtlcurrentrow} to the current row +% Sort the database. % \begin{macrocode} - \dtlcurrentrow = - \csname @dtl@cur\romannumeral\dtlforeachlevel\endcsname + \dtl@sortdata{#3}% + }% + {% + \PackageError{datatool}{Database `#3' doesn't exist}{}% + }% +} % \end{macrocode} -% Does this row have an entry with this key? +%\end{macro} +% +%\begin{macro}{\@sDTLsort} +% Starred (case insensitive) version. % \begin{macrocode} - \edef\dtl@dogetentry{\noexpand\dtlgetentryfromcurrentrow - {\noexpand\dtl@entry}{\number\dtlcolumnnum}% - }% - \dtl@dogetentry - \ifx\dtl@entry\dtlnovalue +\newcommand{\@sDTLsort}[3][]{% % \end{macrocode} -% This row doesn't contain an entry with this key +% Check the database exists % \begin{macrocode} - \PackageError{datatool}{Can't replace entry given by `#1' - from current row in database `\@dtl@thisdb': no such - entry}{The current row doesn't contain an entry for - key `#1'}% - \else + \DTLifdbexists{#3}% + {% % \end{macrocode} -% Split the current row around the requested entry +% Store replacement keys in \cs{@dtl@replacementkeys}. % \begin{macrocode} - \edef\@dtl@dosplitrow{% - \noexpand\dtlsplitrow{\the\dtlcurrentrow}% - {\number\dtlcolumnnum}{\noexpand\dtl@pre}% - {\noexpand\dtl@post}% - }% - \@dtl@dosplitrow + \edef\@dtl@replacementkeys{#1}% % \end{macrocode} -% Reconstruct row with new value (given by \verb|#2|). -%\changes{2.03}{2009 November 15}{expand replacement entry} +% Store sort order in \cs{@dtl@sortorder}. % \begin{macrocode} - \protected@edef\@dtl@tmp{#2}% - \expandafter\@dtl@toks\expandafter{\@dtl@tmp}% new value - \expandafter\@dtl@before\expandafter{\dtl@pre}% - \expandafter\@dtl@after\expandafter{\dtl@post}% - \toks@gconcat@middle@cx - {@dtl@cur\romannumeral\dtlforeachlevel}% - {\@dtl@before}% - {% - \noexpand\db@col@id@w \number\dtlcolumnnum - \noexpand\db@col@id@end@% - \noexpand\db@col@elt@w \the\@dtl@toks - \noexpand\db@col@elt@end@% - \noexpand\db@col@id@w \number\dtlcolumnnum - \noexpand\db@col@id@end@% - }% - {\@dtl@after}% + \edef\@dtl@sortorder{#2}% % \end{macrocode} -% Print information to terminal and log file if in verbose mode. +% Set \cs{@dtl@comparecs} to the required string comparison +% function. (Using case insensitive comparison macro +% \cs{dtlicompare}.) % \begin{macrocode} - \dtl@message{Updated #1\space -> #2\space in database - `\@dtl@thisdb'}% - \fi - }% - {% + \let\@dtl@comparecs=\dtlicompare % \end{macrocode} -% There doesn't exist a column for this key. +% Sort the database. % \begin{macrocode} - \PackageError{datatool}{Can't replace key `#1' - no such - key in database `\@dtl@thisdb'}{}% - }% - }% - \fi + \dtl@sortdata{#3}% + }% + {% + \PackageError{datatool}{Database `#3' doesn't exist}{}% + }% } % \end{macrocode} %\end{macro} % -%\begin{macro}{\DTLremovecurrentrow} -%\begin{definition} -%\cs{DTLremovecurrentrow} -%\end{definition} -% Removes current row. This just sets the current row to empty -%\changes{1.01}{2007 Aug 17}{fix bug caused by missing \cs{fi} -% and unrequired argument} -%\changes{2.0}{2009 February 27}{updated to use new database structure} -% \begin{macrocode} -\newcommand*{\DTLremovecurrentrow}{% - \ifnum\dtlforeachlevel=0\relax - \PackageError{datatool}{\string\DTLremovecurrentrow\space can - only be used inside \string\DTLforeach}{}% - \else -% \end{macrocode} -% Set \cs{@dtl@thisdb} to the current database name: -% \begin{macrocode} - \expandafter\let\expandafter\@dtl@thisdb - \csname @dtl@dbname@\romannumeral\dtlforeachlevel\endcsname -% \end{macrocode} -% Check this isn't in \cs{DTLforeach*} +%\begin{macro}{\@dtl@rowa} +% Token register to store first row when sorting. % \begin{macrocode} - \@dtlifreadonly - {% - \PackageError{datatool}{\string\DTLreplaceentryforrow\space - can't be used inside \string\DTLforeach*}{The starred version - of \string\DTLforeach\space is read only}% - }% - {% +\newtoks\@dtl@rowa % \end{macrocode} -% Set the current row to \cs{@nil} (\cs{DTLforeach} needs to check -% for this) +%\end{macro} +%\begin{macro}{\@dtl@rowb} +% Token register to store comparison row when sorting. % \begin{macrocode} - \expandafter\global - \csname @dtl@cur\romannumeral\dtlforeachlevel\endcsname - ={\@nil}% - }% - \fi -} +\newtoks\@dtl@rowb % \end{macrocode} %\end{macro} % -%\begin{macro}{\DTLaddentryforrow} +%\begin{macro}{\dtl@sortdata} %\begin{definition} -%\cs{DTLaddentryforrow}\marg{db name}\marg{assign list}\marg{condition}\marg{key}\marg{value} +%\cs{dtl@sortdata}\marg{db} %\end{definition} -% Adds the entry with key given by \meta{key} and value given by -% \meta{value} to the first row in the database \meta{db name} -% which satisfies the condition given by \meta{condition}. The -% \meta{assign list} is the same as for \cs{DTLforeach} and may -% be used to set the values which are to be tested in \meta{condition}. -%\changes{2.0}{2009 February 27}{updated to use new database structure} -% \begin{macrocode} -\newcommand{\DTLaddentryforrow}[5]{% -% \end{macrocode} -% Iterate through the data base until condition is met +% Sorts the data in named database using an insertion sort +% algorithm. +% \cs{@dtl@replacementkeys}, \cs{@dtl@sortorder} and +% \cs{@dtl@comparecs} must be set prior to use. +%\changes{2.0}{2009 February 27}{new} % \begin{macrocode} - \DTLifdbexists{#1}% - { - \def\@dtl@notdone{\PackageError{datatool}{Unable to add entry - given by key `#4': condition not met for any row in database - `#1'}{}}% +\newcommand*{\dtl@sortdata}[1]{% % \end{macrocode} -% Iterate through each row +% Initialise macro containing sorted data. % \begin{macrocode} - \DTLforeach[#3]{#1}{#2}% - {% + \def\@dtl@sortedlist{}% % \end{macrocode} -% add entry to this row +% Store database name. % \begin{macrocode} - \DTLappendtorow{#4}{#5}% + \edef\@dtl@dbname{#1}% % \end{macrocode} -% disable error message +% Iterate through each row and insert into sorted list. % \begin{macrocode} - \let\@dtl@notdone\relax + \@dtlforeachrow(\@dtl@rowAnum,\@dtl@rowAcontents)\in{#1}\do{% + \@dtl@rowa=\expandafter{\@dtl@rowAcontents}% % \end{macrocode} -% break out of loop +% Create a temporary list % \begin{macrocode} - \dtlbreak - }% - \@dtl@notdone - }% - {% - \PackageError{datatool}{Unable to add entry given by key `#4': - database `#1' doesn't exist}{}% - }% -} + \def\@dtl@newlist{}% % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\DTLforeachkeyinrow} -%\begin{definition} -%\cs{DTLforeachkeyinrow}\marg{cmd}\marg{text} -%\end{definition} -% Iterates through each key in the current row of \cs{DTLforeach}, -% and does \meta{text}. -%\changes{2.0}{2009 February 27}{updated to use new database structure} +% Initialise the insertion for this iteration. Insertion hasn't +% been done yet. % \begin{macrocode} -\newcommand*{\DTLforeachkeyinrow}[2]{% - \ifnum\dtlforeachlevel=0\relax - \PackageError{datatool}{\string\DTLforeachkeyinrow\space can only - be used inside \string\DTLforeach}{}% - \else + \@dtl@insertdonefalse % \end{macrocode} -% Set \cs{@dtl@thisdb} to the current database name: +% Initialise row index to 0 % \begin{macrocode} - \expandafter\let\expandafter\@dtl@thisdb - \csname @dtl@dbname@\romannumeral\dtlforeachlevel\endcsname + \dtlrownum=0\relax % \end{macrocode} -% Iterate through key list +% Iterate through sorted list. % \begin{macrocode} - \dtlforeachkey(\dtlkey,\dtlcol,\dtltype,\dtlheader)\in - \@dtl@thisdb\do{% + \expandafter\@dtl@foreachrow\@dtl@sortedlist + \db@row@elt@w% + \db@row@id@w \@nil\db@row@id@end@% + \db@row@id@w \@nil\db@row@id@end@% + \db@row@elt@end@% + \@@{\@dtl@rowBnum}{\@dtl@rowBcontents}{% % \end{macrocode} -% store row in \cs{dtlcurrentrow} -% (This may get nested so need to do it here instead of -% outside this loop in case -% \meta{text} changes it.) +% Store row B in a token register % \begin{macrocode} - \dtlcurrentrow = - \csname @dtl@cur\romannumeral\dtlforeachlevel\endcsname + \@dtl@rowb=\expandafter{\@dtl@rowBcontents}% % \end{macrocode} -% Get the value for this key and store in "#1" +% Get current row number of sorted list % \begin{macrocode} - \edef\dtl@dogetentry{\noexpand\dtlgetentryfromcurrentrow - {\noexpand#1}{\dtlcol}}% - \dtl@dogetentry + \dtlrownum=\@dtl@rowBnum % \end{macrocode} -% Check if null +% Has the insertion been done? % \begin{macrocode} - \ifx#1\dtlnovalue - \ifnum0\dtltype=0\relax + \if@dtl@insertdone % \end{macrocode} -% Data type is \meta{empty} or 0, so set to string null. +% New element has already been inserted, so just increment the row +% number to compensate for the inserted row. % \begin{macrocode} - \let#1=\DTLstringnull - \else + \advance\dtlrownum by 1\relax + \else % \end{macrocode} -% Data type is numerical, so set to number null. +% Insertion hasn't been done yet. +% Compare row A and row B. % \begin{macrocode} - \let#1=\DTLnumbernull - \fi - \fi + \@dtl@sortcriteria{\@dtl@rowa}{\@dtl@rowb}% % \end{macrocode} -% Make "#1" global in case this is in a tabular environment (or -% something similar) +% If \cs{dtl@sortresult} is negative insert A before B. % \begin{macrocode} - \global\let#1#1% + \ifnum\dtl@sortresult<0\relax % \end{macrocode} -% Store loop body so that any scoping commands (such as "&") don't -% cause a problem for \cs{ifx} +% Insert row A into new list. First store \cs{@dtl@newlist} in +% \cs{toks@}. % \begin{macrocode} - \def\@dtl@loop@body{#2}% - \@dtl@loop@body - }% - \fi -} + \toks@=\expandafter{\@dtl@newlist}% % \end{macrocode} -%\end{macro} -% -%\subsection{Displaying Database} -% This section defines commands to display the entire database -% in a \env{tabular} or \env{longtable} environment. -% -%\begin{macro}{\dtlbetweencols} -% This specifies what to put between the column alignment -% specifiers. -%\changes{2.0}{2009 February 27}{new} +% Update \cs{@dtl@newlist} to be the old value followed by +% row A. % \begin{macrocode} -\newcommand*{\dtlbetweencols}{} + \edef\@dtl@newlist{% % \end{macrocode} -%\end{macro} -%\begin{macro}{\dtlbeforecols} -% This specifies what to put before the first column alignment -% specifier. -%\changes{2.0}{2009 February 27}{new} +% Old value: % \begin{macrocode} -\newcommand*{\dtlbeforecols}{} + \the\toks@ % \end{macrocode} -%\end{macro} -%\begin{macro}{\dtlaftercols} -% This specifies what to put after the last column alignment -% specifier. -%\changes{2.0}{2009 February 27}{new} +% Format row A % \begin{macrocode} -\newcommand*{\dtlaftercols}{} + \noexpand\db@row@elt@w% + \noexpand\db@row@id@w \number\dtlrownum + \noexpand\db@row@id@end@% + \the\@dtl@rowa + \noexpand\db@row@id@w \number\dtlrownum + \noexpand\db@row@id@end@% + \noexpand\db@row@elt@end@% + }% % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\dtlstringalign} -% Alignment character for columns containing strings +% Increment row number to compensate for inserted row. % \begin{macrocode} -\newcommand*{\dtlstringalign}{l} + \advance\dtlrownum by 1\relax % \end{macrocode} -%\end{macro} -%\begin{macro}{\dtlintalign} -% Alignment character for columns containing integers +% Mark insertion done. % \begin{macrocode} -\newcommand*{\dtlintalign}{r} + \@dtl@insertdonetrue + \fi + \fi % \end{macrocode} -%\end{macro} -%\begin{macro}{\dtlrealalign} -% Alignment character for columns containing real numbers +% Insert row B % \begin{macrocode} -\newcommand*{\dtlrealalign}{r} + \toks@=\expandafter{\@dtl@newlist}% + \edef\@dtl@newlist{\the\toks@ % \end{macrocode} -%\end{macro} -%\begin{macro}{\dtlcurrencyalign} -% Alignment character for columns containing currency numbers +% row B % \begin{macrocode} -\newcommand*{\dtlcurrencyalign}{r} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\dtladdalign} -%\begin{definition} -%\cs{dtladdalign}\marg{cs}\marg{type}\marg{col num}\marg{max cols} -%\end{definition} -% Adds tabular column alignment character to \meta{cs} for column -% \meta{col num} which contains data type \meta{type}. -%\changes{2.0}{2009 February 27}{new} -% \begin{macrocode} -\newcommand*{\dtladdalign}[4]{% - \ifnum#3=1\relax - \protected@edef#1{\dtlbeforecols}% - \else - \protected@edef#1{#1\dtlbetweencols}% - \fi - \ifx\@empty#2\@empty - \protected@edef#1{#1c}% - \else - \ifcase#2\relax + \noexpand\db@row@elt@w% + \noexpand\db@row@id@w \number\dtlrownum + \noexpand\db@row@id@end@% + \the\@dtl@rowb + \noexpand\db@row@id@w \number\dtlrownum + \noexpand\db@row@id@end@% + \noexpand\db@row@elt@end@% + }% % \end{macrocode} -% string +% Repeat loop. % \begin{macrocode} - \protected@edef#1{#1\dtlstringalign}% - \or + }\q@nil % \end{macrocode} -% integer +% If row A hasn't been inserted, do so now. % \begin{macrocode} - \protected@edef#1{#1\dtlintalign}% - \or + \if@dtl@insertdone + \else % \end{macrocode} -% real number +% \cs{dtlrownum} contains the index of the last row in new list, +% So increment it to get the new index for row A. % \begin{macrocode} - \protected@edef#1{#1\dtlrealalign}% - \or + \advance\dtlrownum by 1\relax % \end{macrocode} -% currency +% Insert row A. % \begin{macrocode} - \protected@edef#1{#1\dtlcurrencyalign}% - \else + \toks@=\expandafter{\@dtl@newlist}% + \edef\@dtl@newlist{\the\toks@ % \end{macrocode} -% Unknown type +% row A % \begin{macrocode} - \protected@edef#1{#1c}% - \PackageError{datatool}{Unknown data type `#2'}{}% + \noexpand\db@row@elt@w% + \noexpand\db@row@id@w \number\dtlrownum + \noexpand\db@row@id@end@% + \the\@dtl@rowa + \noexpand\db@row@id@w \number\dtlrownum + \noexpand\db@row@id@end@% + \noexpand\db@row@elt@end@% + }% \fi - \fi - \ifnum#3=#4\relax - \protected@edef#1{#1\dtlaftercols}% - \fi -} % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\dtlheaderformat} -%\begin{definition} -%\cs{dtlheaderformat}\marg{text} -%\end{definition} -% Specifies how to format the column title. -%\changes{2.0}{2009 February 27}{new} +% Set sorted list to new list. % \begin{macrocode} -\newcommand*{\dtlheaderformat}[1]{\null\hfil\textbf{#1}\hfil\null} + \let\@dtl@sortedlist=\@dtl@newlist + }% % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\dtlstringformat} -%\begin{definition} -%\cs{dtlstringformat}\marg{text} -%\end{definition} -% Specifies how to format entries in columns with string data type. -%\changes{2.0}{2009 February 27}{new} +% Update database. % \begin{macrocode} -\newcommand*{\dtlstringformat}[1]{#1} + \expandafter\global\csname dtldb@#1\endcsname=\expandafter + {\@dtl@sortedlist}% +} % \end{macrocode} %\end{macro} -%\begin{macro}{\dtlintformat} +% +%\begin{macro}{\@dtl@sortcriteria} %\begin{definition} -%\cs{dtlintformat}\marg{text} +% \cs{@dtl@sortcriteria}\marg{row a toks}\marg{row b toks} %\end{definition} -% Specifies how to format entries in columns with integer data type. -%\changes{2.0}{2009 February 27}{new} +% \cs{@dtl@dbname} and \cs{@dtl@sortorder} must be set before use +% \cs{@dtl@sortorder} is a comma separated list of either just keys +% or \meta{key}=\meta{direction}. +% (Check keys are valid before use.) +%\changes{2.0}{2009 February 27}{updated to take account of new +% database structure} % \begin{macrocode} -\newcommand*{\dtlintformat}[1]{#1} +\newcommand{\@dtl@sortcriteria}[2]{% % \end{macrocode} -%\end{macro} -%\begin{macro}{\dtlrealformat} -%\begin{definition} -%\cs{dtlrealformat}\marg{text} -%\end{definition} -% Specifies how to format entries in columns with real data type. -%\changes{2.0}{2009 February 27}{new} +% Iterate through the sort order. % \begin{macrocode} -\newcommand*{\dtlrealformat}[1]{#1} + \@for\@dtl@level:=\@dtl@sortorder\do{% % \end{macrocode} -%\end{macro} -%\begin{macro}{\dtlcurrencyformat} -%\begin{definition} -%\cs{dtlcurrencyformat}\marg{text} -%\end{definition} -% Specifies how to format entries in columns with currency data type. -%\changes{2.0}{2009 February 27}{new} +% Set \cs{@dtl@sortdirection} to $-1$ (ascending) or $+1$ +% (descending). Key is stored in \cs{@dtl@key}. % \begin{macrocode} -\newcommand*{\dtlcurrencyformat}[1]{#1} + \expandafter\@dtl@getsortdirection\@dtl@level=\relax % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\dtldisplaystarttab} -% Indicates what to do just after "\begin{tabular}"\marg{column specs} -% (e.g.\ \cs{hline}). -%\changes{2.0}{2009 February 27}{new} +% Initially comparing on the same key % \begin{macrocode} -\newcommand*{\dtldisplaystarttab}{} + \let\@dtl@keya=\@dtl@key + \let\@dtl@keyb=\@dtl@key % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\dtldisplayendtab} -% Indicates what to do just before "\end{tabular}". -%\changes{2.0}{2009 February 27}{new} +% Get values corresponding to key from both rows. +% First get column index corresponding to key. % \begin{macrocode} -\newcommand*{\dtldisplayendtab}{} + \@sdtl@getcolumnindex{\@dtl@col}{\@dtl@dbname}{\@dtl@key}% % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\dtldisplayafterhead} -% Indicates what to do after the header row, before the first row -% of data. -%\changes{2.0}{2009 February 27}{new} +% Get entry for this column from row A and store in \cs{@dtl@a}. % \begin{macrocode} -\newcommand*{\dtldisplayafterhead}{} + \dtlgetentryfromrow{\@dtl@a}{\@dtl@col}{#1}% % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\dtldisplaystartrow} -% Indicates what to do at the start of each row (not including -% the header row or the first row of data). -%\changes{2.0}{2009 February 27}{new} +% Get entry for this column from row B and store in \cs{@dtl@b}. % \begin{macrocode} -\newcommand*{\dtldisplaystartrow}{} + \dtlgetentryfromrow{\@dtl@b}{\@dtl@col}{#2}% % \end{macrocode} -%\end{macro} - -%\begin{macro}{\DTLdisplaydb} -%\begin{definition} -%\cs{DTLdisplaydb}\marg{db} -%\end{definition} -% Displays the database \meta{db} in a tabular environment. -%\changes{2.0}{2009 February 27}{new} +% Has value from row A been defined? % \begin{macrocode} -\newcommand*{\DTLdisplaydb}[1]{% + \ifx\@dtl@a\dtlnovalue % \end{macrocode} -% Initialise: -% only want "&" between columns +% Value hasn't been defined so set to null % \begin{macrocode} - \def\@dtl@doamp{\gdef\@dtl@doamp{&}} - \def\@dtl@resetdoamp{\gdef\@dtl@doamp{\gdef\@dtl@doamp{&}}} + \@dtl@setnull{\@dtl@a}{\@dtl@key}% + \fi % \end{macrocode} -% Store maximum number of columns +% Has value from row B been defined? % \begin{macrocode} - \edef\@dtl@maxcols{\expandafter\number - \csname dtlcols@#1\endcsname}% + \ifx\@dtl@b\dtlnovalue % \end{macrocode} -% Argument for tabular environment +% Value hasn't been defined so set to null % \begin{macrocode} - \def\@dtl@tabargs{}% - \dtlforeachkey(\@dtl@key,\@dtl@idx,\@dtl@type,\@dtl@head)% - \in{#1}\do - {% - \dtladdalign\@dtl@tabargs\@dtl@type\@dtl@idx\@dtl@maxcols - }% + \@dtl@setnull{\@dtl@b}{\@dtl@key}% + \fi % \end{macrocode} -% Begin tabular environment +% Check if value for row A is null. % \begin{macrocode} - \edef\@dtl@dobegintab{\noexpand\begin{tabular}{\@dtl@tabargs}}% - \@dtl@dobegintab + \DTLifnull{\@dtl@a}% + {% % \end{macrocode} -% Do start hook +% Value for row A is null, so find the first non null key in list of +% replacement keys. % \begin{macrocode} - \dtldisplaystarttab + \@for\@dtl@keya:=\@dtl@replacementkeys\do{% % \end{macrocode} -% Reset \cs{@dtl@doamp} so it doesn't do an ampersand at the -% start of the first column. +% Get column corresponding to this key. % \begin{macrocode} - \@dtl@resetdoamp + \@sdtl@getcolumnindex{\@dtl@col}{\@dtl@dbname}{\@dtl@keya}% + \dtlgetentryfromrow{\@dtl@a}{\@dtl@col}{#1}% % \end{macrocode} -% Do the header row. +% Has value for row A been defined? % \begin{macrocode} - \dtlforeachkey(\@dtl@key,\@dtl@idx,\@dtl@type,\@dtl@head)% - \in{#1}\do - {% - \@dtl@doamp - \dtlheaderformat{\@dtl@head}% - }% - \\% + \ifx\@dtl@a\dtlnovalue % \end{macrocode} -% Do the after header hook +% Value for row A hasn't been defined so set to null % \begin{macrocode} - \dtldisplayafterhead + \@dtl@setnull{\@dtl@a}{\@dtl@key}% + \fi % \end{macrocode} -% Reset \cs{@dtl@doamp} so it doesn't do an ampersand at the -% start of the first column. +% Is value for row A null? If not null end the loop. % \begin{macrocode} - \@dtl@resetdoamp + \DTLifnull{\@dtl@a}{}{\@endfortrue}% + }% % \end{macrocode} -% Iterate through each row of the database +% No non-null value found. % \begin{macrocode} - \DTLforeach*{#1}{}{% + \ifx\@dtl@keya\@nnil + \let\@dtl@keya\@dtl@key + \@dtl@setnull{\@dtl@a}{\@dtl@key}% + \fi + }% + {}% % \end{macrocode} -% Do the start row hook if not the first row +% Check if value for row B is null. % \begin{macrocode} - \DTLiffirstrow{}{\\\dtldisplaystartrow}% + \DTLifnull{\@dtl@b}% + {% % \end{macrocode} -% Reset \cs{@dtl@doamp} so it doesn't do an ampersand at the -% start of the first column. +% Value for row B is null, so find the first non null key in list of +% replacement keys. % \begin{macrocode} - \@dtl@resetdoamp + \@for\@dtl@keyb:=\@dtl@replacementkeys\do{% % \end{macrocode} -% Iterate through each column. +% Get column corresponding to this key. % \begin{macrocode} - \DTLforeachkeyinrow{\@dtl@val}% - {% + \@sdtl@getcolumnindex{\@dtl@col}{\@dtl@dbname}{\@dtl@keyb}% + \dtlgetentryfromrow{\@dtl@b}{\@dtl@col}{#2}% % \end{macrocode} -% Need to make value global as it needs to be used after the -% ampersand. +% Has value for row B been defined? % \begin{macrocode} - \global\let\@dtl@val\@dtl@val - \@dtl@doamp + \ifx\@dtl@b\dtlnovalue % \end{macrocode} -% \cs{DTLforeachkeyinrow} sets \cs{dtltype} to the data type -% for the current key. This can be used to determine which -% format to use for this entry. +% Value for row B hasn't been defined so set to null. % \begin{macrocode} - \@dtl@datatype=0\dtltype\relax - \ifcase\@dtl@datatype - \dtlstringformat\@dtl@val - \or - \dtlintformat\@dtl@val - \or - \dtlrealformat\@dtl@val - \or - \dtlcurrencyformat\@dtl@val - \else - \@dtl@val - \fi - }% - }% - \dtldisplayendtab - \end{tabular}% -} + \@dtl@setnull{\@dtl@b}{\@dtl@key}% + \fi % \end{macrocode} -%\end{macro} -% -% Define keys to use in the optional argument of -% \cs{DTLdisplaylongdb}. -% -% The caption key sets the caption for the longtable. +% Is value for row B null? If not null end the loop. % \begin{macrocode} -\define@key{displaylong}{caption}{\def\@dtl@cap{#1}} + \DTLifnull{\@dtl@b}{}{\@endfortrue}% + }% % \end{macrocode} -% The contcaption key sets the continuation caption for the -% longtable. +% No non-null value found. % \begin{macrocode} -\define@key{displaylong}{contcaption}{\def\@dtl@contcap{#1}} + \ifx\@dtl@keyb\@nnil + \let\@dtl@keyb\@dtl@key + \@dtl@setnull{\@dtl@b}{\@dtl@key}% + \fi + }% + {}% % \end{macrocode} -% The shortcaption key sets the lof caption for the longtable. +% Compare rows A and B. First store the values for row A and B +% in token registers so that they can be passed to +% \cs{dtl@compare@}. % \begin{macrocode} -\define@key{displaylong}{shortcaption}{\def\@dtl@shortcap{#1}} + \@dtl@toksA=\expandafter{\@dtl@a}% + \@dtl@toksB=\expandafter{\@dtl@b}% % \end{macrocode} -% The label key sets the label for the longtable. +% Do comparison. % \begin{macrocode} -\define@key{displaylong}{label}{\def\@dtl@label{#1}} + \edef\@dtl@docompare{\noexpand\dtl@compare@ + {\@dtl@keya}{\@dtl@keyb}% + {\noexpand\@dtl@toksA}{\noexpand\@dtl@toksB}}% + \@dtl@docompare % \end{macrocode} -% The foot key sets the longtable foot +% Repeat if the two values are considered identical and there +% are further sorting options. % \begin{macrocode} -\define@key{displaylong}{foot}{\def\@dtl@foot{#1}} + \ifnum\dtl@sortresult=0\relax % \end{macrocode} -% The lastfoot key sets the longtable last foot +% Reset switch to prevent breaking out of outer loop. % \begin{macrocode} -\define@key{displaylong}{lastfoot}{\def\@dtl@lastfoot{#1}} + \@endforfalse + \else % \end{macrocode} -% -%\begin{macro}{\@dtl@resetdostartrow} -% Resets start row hook so that it skips the first row. +% Break out of loop. % \begin{macrocode} -\newcommand*{\@dtl@resetdostartrow}{% - \gdef\@dtl@dostartrow{% - \gdef\@dtl@dostartrow{\\\dtldisplaystartrow}}% + \@endfortrue + \fi + }% +% \end{macrocode} +% Apply sort direction +%\changes{2.01}{2009 March 27}{fixed sort direction} +% \begin{macrocode} + \multiply\dtl@sortresult by -\@dtl@sortdirection\relax } % \end{macrocode} %\end{macro} % -%\begin{macro}{\DTLdisplaylongdb} -%\begin{definition} -%\cs{DTLdisplaylongdb}\oarg{options}\marg{db} -%\end{definition} -% Displays the database \meta{db} in a longtable environment. -% (User needs to load \sty{longtable}). -%\changes{2.0}{2009 February 27}{new} +%\begin{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} -\newcommand*{\DTLdisplaylongdb}[2][]{% +\def\@dtl@getsortdirection#1=#2\relax{% % \end{macrocode} -% Initialise. +% Store key in \cs{@dtl@key}. % \begin{macrocode} - \def\@dtl@cap{\@nil}% - \def\@dtl@contcap{\@nil}% - \def\@dtl@label{\@nil}% - \def\@dtl@shortcap{\@dtl@cap}% - \def\@dtl@foot{\@nil}% - \def\@dtl@lastfoot{\@nil}% + \def\@dtl@key{#1}% % \end{macrocode} -% Set the options +% Store sort direction. This will be empty if no direction was +% specified. % \begin{macrocode} - \setkeys{displaylong}{#1}% + \def\@dtl@sortdirection{#2}% % \end{macrocode} -% Only want "&" between columns +% Check if a direction was specified. % \begin{macrocode} - \def\@dtl@doamp{\gdef\@dtl@doamp{&}} - \def\@dtl@resetdoamp{\gdef\@dtl@doamp{\gdef\@dtl@doamp{&}}} - \@dtl@resetdostartrow + \ifdefempty{\@dtl@sortdirection}% + {% % \end{macrocode} -% Store maximum number of columns +% No direction specified so assume ascending. % \begin{macrocode} - \edef\@dtl@maxcols{\expandafter\number - \csname dtlcols@#2\endcsname}% + \def\@dtl@sortdirection{-1}% + }% + {% % \end{macrocode} -% Argument for \env{longtable} environment +% Get the sort direction from the second argument (needs terminating +% equal sign removed) and store in \cs{@dtl@sortdirection}. % \begin{macrocode} - \def\@dtl@tabargs{}% - \dtlforeachkey(\@dtl@key,\@dtl@idx,\@dtl@type,\@dtl@head)% - \in{#2}\do - {% - \dtladdalign\@dtl@tabargs\@dtl@type\@dtl@idx\@dtl@maxcols - }% + \@dtl@get@sortdirection#2% % \end{macrocode} -% Start the \env{longtable} environment. +% Determine the direction. +% \changes{2.0}{2009 February 27}{modified to use \cs{ifx} instead +% of \cs{ifthenelse}} % \begin{macrocode} - \edef\@dtl@dobegintab{\noexpand\begin{longtable}{\@dtl@tabargs}}% - \@dtl@dobegintab + \def\@dtl@dir{ascending}% + \ifx\@dtl@sortdirection\@dtl@dir % \end{macrocode} -% Do start hook. +% Ascending % \begin{macrocode} - \dtldisplaystarttab + \def\@dtl@sortdirection{-1}% + \else % \end{macrocode} -% Is a foot required? +% Check if descending. % \begin{macrocode} - \ifx\@dtl@foot\@nnil - \else - \@dtl@foot\endfoot - \fi + \def\@dtl@dir{descending}% + \ifx\@dtl@sortdirection\@dtl@dir % \end{macrocode} -% Is a last foot required? +% Descending % \begin{macrocode} - \ifx\@dtl@lastfoot\@nnil - \else - \@dtl@lastfoot\endlastfoot - \fi + \def\@dtl@sortdirection{1}% + \else % \end{macrocode} -% Is a caption required? +% Direction not valid. Generate error message. % \begin{macrocode} - \ifx\@dtl@cap\@nnil + \PackageError{datatool}{Invalid sort direction + `\@dtl@sortdirection'}{The sort direction can only be + one of `ascending' or `descending'}% % \end{macrocode} -% No caption required, just do header row. +% Assume ascending. % \begin{macrocode} - \@dtl@resetdoamp - \dtlforeachkey(\@dtl@key,\@dtl@idx,\@dtl@type,\@dtl@head)% - \in{#2}\do - {\@dtl@doamp{\dtlheaderformat{\@dtl@head}}}% - \@dtl@resetdoamp - \@dtl@resetdostartrow - \endhead\dtldisplayafterhead - \else + \def\@dtl@sortdirection{-1} + \fi + \fi + }% +} % \end{macrocode} -% Caption is required +%\end{macro} +%\begin{macro}{\@dtl@get@sortdirection} +% Get direction (trims trailing = sign) % \begin{macrocode} - \caption[\@dtl@shortcap]{\@dtl@cap}% +\def\@dtl@get@sortdirection#1={\def\@dtl@sortdirection{#1}} % \end{macrocode} -% Is a label required? +%\end{macro} +% +%\begin{macro}{\@dtl@toksA} % \begin{macrocode} - \ifx\@dtl@label\@nnil - \else - \label{\@dtl@label}% - \fi - \\% +\newtoks\@dtl@toksA % \end{macrocode} -% Do header row. +%\end{macro} +%\begin{macro}{\@dtl@toksB} +% \begin{macrocode} +\newtoks\@dtl@toksB +% \end{macrocode} +%\end{macro} +%\begin{macro}{\dtl@compare} +%\begin{definition} +%\cs{dtl@compare}\marg{key}\marg{a toks}\marg{b toks} +%\end{definition} +% Compares two values according to \meta{key} of database given by +% \cs{@dtl@dbname}. Sets \cs{dtl@sortresult}. \cs{@dtl@comparecs} +% must be set to the required comparison macro. +%\changes{2.0}{2009 February 27}{no longer used} % \begin{macrocode} - \@dtl@resetdoamp - \dtlforeachkey(\@dtl@key,\@dtl@idx,\@dtl@type,\@dtl@head)% - \in{#2}\do - {\@dtl@doamp{\dtlheaderformat{\@dtl@head}}}% - \@dtl@resetdoamp - \@dtl@resetdostartrow - \endfirsthead +\newcommand{\dtl@compare}[3]{% + \dtl@compare@{#1}{#1}{#2}{#3}% +} % \end{macrocode} -% Is a continuation caption required? +%\end{macro} +% +%\begin{macro}{\dtl@compare@} +%\begin{definition} +% \cs{dtl@compare@}\marg{keyA}\marg{keyB}\marg{A toks}\marg{B toks} +%\end{definition} +% Compare \meta{A} and \meta{B} according \meta{keyA} and +% \meta{keyB} for database given by \cs{@dtl@dbname}. Sets +% \cs{dtl@sortresult}. +% \cs{@dtl@comparecs} must be set before use. +%\changes{2.0}{2009 February 27}{updated to use new database +% structure} % \begin{macrocode} - \ifx\@dtl@contcap\@nnil - \caption{\@dtl@cap}% - \else - \caption{\@dtl@contcap}% - \fi - \\% +\newcommand{\dtl@compare@}[4]{% % \end{macrocode} -% Do header row. +% Get the data type for first key and store in \cs{@dtl@typeA}. % \begin{macrocode} - \@dtl@resetdoamp - \dtlforeachkey(\@dtl@key,\@dtl@idx,\@dtl@type,\@dtl@head)% - \in{#2}\do - {\@dtl@doamp{\dtlheaderformat{\@dtl@head}}}% - \@dtl@resetdoamp - \@dtl@resetdostartrow - \endhead\dtldisplayafterhead + \DTLgetdatatype{\@dtl@typeA}{\@dtl@dbname}{#1}% +% \end{macrocode} +% Is it unset? If so, assume string +% \begin{macrocode} + \ifx\@dtl@typeA\DTLunsettype + \let\@dtl@typeA\DTLstringtype \fi % \end{macrocode} -% Iterate through each row of the database +% Get the data type for the second key and store in \cs{@dtl@typeB} % \begin{macrocode} - \DTLforeach*{#2}{}{% - \@dtl@dostartrow - \@dtl@resetdoamp + \DTLgetdatatype{\@dtl@typeB}{\@dtl@dbname}{#2}% % \end{macrocode} -% Iterate through each column +% Is it unset? If so, assume string % \begin{macrocode} - \DTLforeachkeyinrow{\@dtl@val}% - {% - \global\let\@dtl@val\@dtl@val - \@dtl@doamp + \ifx\@dtl@typeB\DTLunsettype + \let\@dtl@typeB\DTLstringtype + \fi % \end{macrocode} -% \cs{DTLforeachkeyinrow} sets \cs{dtltype} to the data type -% for the current key. This can be used to determine which -% format to use for this entry. +% Multiply the two values together % \begin{macrocode} - \@dtl@datatype=0\dtltype\relax - \ifcase\@dtl@datatype - \dtlstringformat\@dtl@val - \or - \dtlintformat\@dtl@val - \or - \dtlrealformat\@dtl@val - \or - \dtlcurrencyformat\@dtl@val - \fi - }% - }% - \dtldisplayendtab - \end{longtable}% -} + \@dtl@tmpcount=\@dtl@typeA\relax + \multiply\@dtl@tmpcount by \@dtl@typeB\relax % \end{macrocode} -%\end{macro} -% -% -%\subsection{Editing Databases} -% -%\begin{macro}{\dtlswaprows} -%\begin{definition} -%\cs{dtlswaprows}\marg{db}\marg{row1 idx}\marg{row2 idx} -%\end{definition} -% Swaps the rows with indices \meta{row1 idx} and \meta{row2 idx} -% in the database \meta{db}. -% (Doesn't check if data base exists of if indices are out of -% bounds.) +% If either type is 0 (a string) then the product will also be +% 0 (string) otherwise it will be one of the numerical types. % \begin{macrocode} -\newcommand*{\dtlswaprows}[3]{% - \ifnum#2=#3\relax + \ifnum\@dtl@tmpcount=0\relax % \end{macrocode} -% Attempt to swap row with itself: do nothing. +% A string, so use comparison function % \begin{macrocode} + \edef\@dtl@tmpcmp{% + \noexpand\@dtl@comparecs{\noexpand\dtl@sortresult}% + {\the#3}{\the#4}% + }% + \@dtl@tmpcmp + \ifdtlverbose + \edef\@dtl@a{\the#3}% + \edef\@dtl@b{\the#4}% + \fi \else % \end{macrocode} -% Let row A be the row with the lower index and row B be the -% row with ther higher index. +% Store the first value % \begin{macrocode} - \ifnum#2<#3\relax - \edef\@dtl@rowAidx{\number#2}% - \edef\@dtl@rowBidx{\number#3}% - \else - \edef\@dtl@rowAidx{\number#3}% - \edef\@dtl@rowBidx{\number#2}% - \fi + \edef\@dtl@a{\the#3}% % \end{macrocode} -% Split the database around row A. +% Store the second value % \begin{macrocode} - \edef\@dtl@dosplit{\noexpand\dtlgetrow{#1}{\@dtl@rowAidx}}% - \@dtl@dosplit + \edef\@dtl@b{\the#4}% % \end{macrocode} -% Store first part of database in \cs{@dtl@firstpart}. +% Compare % \begin{macrocode} - \expandafter\def\expandafter\@dtl@firstpart\expandafter - {\the\dtlbeforerow}% + \DTLifnumlt{\@dtl@a}{\@dtl@b}% + {% % \end{macrocode} -% Store row A in \cs{@dtl@toksA}. +% $A < B$ % \begin{macrocode} - \@dtl@toksA=\dtlcurrentrow + \dtl@sortresult=-1\relax + }% + {% + \DTLifnumgt{\@dtl@a}{\@dtl@b}% + {% % \end{macrocode} -% Split the second part (everything after row A). +% $A > B$ % \begin{macrocode} - \edef\@dtl@dosplit{\noexpand\@dtlgetrow - {\the\dtlafterrow}{\@dtl@rowBidx}}% - \@dtl@dosplit + \dtl@sortresult=1\relax + }% + {% % \end{macrocode} -% Store the mid part (everything between row A and row B) +% $A = B$ % \begin{macrocode} - \expandafter\def\expandafter\@dtl@secondpart\expandafter - {\the\dtlbeforerow}% + \dtl@sortresult=0\relax + }% + }% + \fi % \end{macrocode} -% Store row B in \cs{@dtl@toksB}. +% Write comparison result to terminal/log if verbose mode. % \begin{macrocode} - \@dtl@toksB=\dtlcurrentrow + \ifdtlverbose + \@onelevel@sanitize\@dtl@a + \@onelevel@sanitize\@dtl@b + \dtl@message{`\@dtl@a' <=> `\@dtl@b' = \number\dtl@sortresult}% + \fi +} % \end{macrocode} -% Store the last part (everything after row B). +%\end{macro} +% +%\section{Saving a database to an external file} +% +%\begin{macro}{\@dtl@write} % \begin{macrocode} - \expandafter\def\expandafter\@dtl@thirdpart\expandafter - {\the\dtlafterrow}% +\newwrite\@dtl@write % \end{macrocode} -% Reconstruct database: store first part in \cs{toks@} +%\end{macro} +%\begin{macro}{\DTLsavedb} +%\begin{definition} +% \cs{DTLsavedb}\marg{db name}\marg{filename} +%\end{definition} +% Save a database as an ASCII data file using the separator +% and delimiter given by \cs{@dtl@separator} and \cs{@dtl@delimiter}. +%\changes{2.0}{2009 February 27}{updated to use new database structure} % \begin{macrocode} - \toks@=\expandafter{\@dtl@firstpart}% +\newcommand*{\DTLsavedb}[2]{% + \DTLifdbexists{#1}% + {% % \end{macrocode} -% Store mid part in \cs{dtl@toks} +% Open output file +%\changes{2.02}{2009 July 13}{Fixed bug that didn't set the filename} % \begin{macrocode} - \@dtl@toks=\expandafter{\@dtl@secondpart}% + \openout\@dtl@write=#2\relax % \end{macrocode} -% Format data for first part, row B and mid part. +% Initialise header row % \begin{macrocode} - \edef\@dtl@tmp{\the\toks@ - \noexpand\db@row@elt@w% - \noexpand\db@row@id@w \@dtl@rowAidx\noexpand\db@row@id@end@% - \the\@dtl@toksB - \noexpand\db@row@id@w \@dtl@rowAidx\noexpand\db@row@id@end@% - \noexpand\db@row@elt@end@% - \the\@dtl@toks}% + \def\@dtl@header{}% % \end{macrocode} -% Store data so far in \cs{toks@}. +% Construct the header row % \begin{macrocode} - \toks@=\expandafter{\@dtl@tmp}% + \dtlforeachkey(\@dtl@key,\@dtl@col,\@dtl@type,\@dtl@head)% + \in{#1}\do + {% + \IfSubStringInString{\@dtl@separator}{\@dtl@key}% + {% + \ifdefempty{\@dtl@header}% + {% + \protected@edef\@dtl@header{% + \@dtl@delimiter\@dtl@key\@dtl@delimiter}% + }% + {% + \toks@=\expandafter{\@dtl@header}% + \protected@edef\@dtl@header{% + \the\toks@\@dtl@separator + \@dtl@delimiter\@dtl@key\@dtl@delimiter}% + }% + }% + {% + \ifdefempty{\@dtl@header}% + {% + \protected@edef\@dtl@header{\@dtl@key}% + }% + {% + \toks@=\expandafter{\@dtl@header}% + \protected@edef\@dtl@header{\the\toks@ + \@dtl@separator\@dtl@key}% + }% + }% + }% % \end{macrocode} -% Store last part in \cs{dtl@toks}. +% Print header % \begin{macrocode} - \@dtl@toks=\expandafter{\@dtl@thirdpart}% + \protected@write\@dtl@write{}{\@dtl@header}% % \end{macrocode} -% Format row A and end part. +% Iterate through each row % \begin{macrocode} - \edef\@dtl@tmp{\the\toks@ - \noexpand\db@row@elt@w% - \noexpand\db@row@id@w \@dtl@rowBidx\noexpand\db@row@id@end@% - \the\@dtl@toksA - \noexpand\db@row@id@w \@dtl@rowBidx\noexpand\db@row@id@end@% - \noexpand\db@row@elt@end@% - \the\@dtl@toks}% + \@sDTLforeach{#1}{}% + {% % \end{macrocode} -% Update the database +% Initialise row % \begin{macrocode} - \expandafter\global\csname dtldb@#1\endcsname=\expandafter - {\@dtl@tmp}% - \fi + \def\@dtl@row{}% +% \end{macrocode} +% Iterate through each key +% \begin{macrocode} + \DTLforeachkeyinrow{\@dtl@val}% + {% + \IfSubStringInString{\@dtl@separator}{\@dtl@val}% + {% + \ifdefempty{\@dtl@row}% + {% + \protected@edef\@dtl@row{% + \@dtl@delimiter\@dtl@val\@dtl@delimiter}% + }% + {% + \toks@=\expandafter{\@dtl@row}% + \protected@edef\@dtl@row{\the\toks@\@dtl@separator + \@dtl@delimiter\@dtl@val\@dtl@delimiter}% + }% + }% + {% + \ifdefempty{\@dtl@row}% + {% + \protected@edef\@dtl@row{\@dtl@val}% + }% + {% + \toks@=\expandafter{\@dtl@row}% + \protected@edef\@dtl@row{\the\toks@\@dtl@separator + \@dtl@val}% + }% + }% + }% +% \end{macrocode} +% Print row\changes{2.03}{2009 November 15}{Moved outside loop} +% \begin{macrocode} + \protected@write\@dtl@write{}{\@dtl@row}% + }% +% \end{macrocode} +% Close output file +% \begin{macrocode} + \closeout\@dtl@write + }% + {% + \PackageError{datatool}{Can't save database `#1': no such + database}{}% + }% } % \end{macrocode} %\end{macro} % -%\begin{macro}{\dtl@decrementrows} +%\begin{macro}{\DTLsavetexdb} %\begin{definition} -%\cs{dtl@decrementrows}\marg{toks}\marg{n} +% \cs{DTLsavetexdb}\marg{db name}\marg{filename} %\end{definition} -% decrement by 1 all rows in \meta{toks} with row index above -% \meta{n} -%\changes{2.0}{2009 February 27}{new} +% Save a database as a \LaTeX\ file. +%\changes{2.0}{2009 February 27}{updated to use new database structure} % \begin{macrocode} -\newcommand*{\dtl@decrementrows}[2]{% - \def\@dtl@newlist{}% - \edef\@dtl@min{\number#2}% - \expandafter\@dtl@decrementrows\the#1% - \db@row@elt@w% - \db@row@id@w \@nil\db@row@id@end@% - \db@row@id@w \@nil\db@row@id@end@% - \db@row@elt@end@% - \@nil - #1=\expandafter{\@dtl@newlist}% -} +\newcommand*{\DTLsavetexdb}[2]{% + \DTLifdbexists{#1}% + {% % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@dtl@decrementrows} -%\changes{2.0}{2009 February 27}{new} +% Open output file % \begin{macrocode} -\def\@dtl@decrementrows\db@row@elt@w\db@row@id@w #1\db@row@id@end@% -#2\db@row@id@w #3\db@row@id@end@\db@row@elt@end@#4\@nil{% - \def\@dtl@thisrow{#1}% - \ifx\@dtl@thisrow\@nnil - \let\@dtl@donextdec=\@dtl@gobbletonil - \else - \ifnum\@dtl@thisrow>\@dtl@min - \@dtl@tmpcount=\@dtl@thisrow\relax - \advance\@dtl@tmpcount by -1\relax - \toks@{#2}% - \@dtl@toks=\expandafter{\@dtl@newlist}% - \edef\@dtl@newlist{\the\@dtl@toks - \noexpand\db@row@elt@w% row header - \noexpand\db@row@id@w \number\@dtl@tmpcount - \noexpand\db@row@id@end@% row id - \the\toks@ % row contents - \noexpand\db@row@id@w \number\@dtl@tmpcount - \noexpand\db@row@id@end@% row id - \noexpand\db@row@elt@end@% row end - }% - \else - \toks@{#2}% - \@dtl@toks=\expandafter{\@dtl@newlist}% - \edef\@dtl@newlist{\the\@dtl@toks - \noexpand\db@row@elt@w% row header - \noexpand\db@row@id@w #1% - \noexpand\db@row@id@end@% row id - \the\toks@ % row contents - \noexpand\db@row@id@w #3% - \noexpand\db@row@id@end@% row id - \noexpand\db@row@elt@end@% row end - }% - \fi - \let\@dtl@donextdec=\@dtl@decrementrows - \fi - \@dtl@donextdec#4\@nil -} + \openout\@dtl@write=#2\relax % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\DTLremoverow} -%\begin{definition} -%\cs{DTLremoverow}\marg{db}\marg{row index} -%\end{definition} -% Remove row with given index from database named \meta{db}. -%\changes{2.0}{2009 February 27}{new} +% Write new data base definition % \begin{macrocode} -\newcommand*{\DTLremoverow}[2]{% + \protected@write\@dtl@write{}{\string\DTLnewdb{#1}}% % \end{macrocode} -% Check database exists +% Iterate through each row % \begin{macrocode} - \DTLifdbexists{#1}% - {% + \@sDTLforeach{#1}{}% + {% % \end{macrocode} -% Check index if index is out of bounds +% Start new row % \begin{macrocode} - \ifnum#2>0\relax + \protected@write\@dtl@write{}{\string\DTLnewrow*{#1}}% % \end{macrocode} -% Check if data base has at least \meta{row index} rows +% Iterate through each column % \begin{macrocode} - \expandafter\ifnum\csname dtlrows@#1\endcsname<#2\relax - \expandafter\ifnum\csname dtlrows@#1\endcsname=1\relax - \PackageError{datatool}{Can't remove row `\number#2' from - database `#1': no such row}{Database `#1' only has - 1 row}% - \else - \PackageError{datatool}{Can't remove row `\number#2' from - database `#1': no such row}{Database `#1' only has - \expandafter\number\csname dtlrows@#1\endcsname\space - rows}% - \fi - \else - \@DTLremoverow{#1}{#2}% - \fi - \else - \PackageError{datatool}{Can't remove row \number#2: index - out of bounds}{Row indices start at 1}% - \fi + \DTLforeachkeyinrow{\@dtl@val}% + {% +% \end{macrocode} +% Is this entry null? +% \begin{macrocode} + \DTLifnull{\@dtl@val}% + {\def\@dtl@val{}}% + {}% +% \end{macrocode} +% Add entry +% \begin{macrocode} + \protected@write\@dtl@write{}{% + \string\DTLnewdbentry*{#1}{\dtlkey}{\@dtl@val}}% + }% + }% +% \end{macrocode} +% Save the column headers. +% \begin{macrocode} + \dtlforeachkey(\@dtl@k,\@dtl@c,\@dtl@t,\@dtl@h)\in{#1}\do + {% + \@onelevel@sanitize\@dtl@h + \protected@write\@dtl@write{}{% + \string\DTLsetheader*{#1}{\@dtl@k}{\@dtl@h}}% + }% +% \end{macrocode} +% Close output file +% \begin{macrocode} + \closeout\@dtl@write }% {% - \PackageError{datatool}{Can't remove row: database `#1' doesn't - exist}{}% + \PackageError{datatool}{Can't save database `#1': no such + database}{}% }% } % \end{macrocode} %\end{macro} % -%\begin{macro}{\@DTLremoverow} -%\begin{definition} -%\cs{@DTLremoverow}\marg{db}\marg{row index} -%\end{definition} -% Doesn't perform any checks for the existance of the database -% or if the index is in range. -%\changes{2.0}{2009 February 27}{new} +%\section{Loading a database from an external file} +% +%\begin{macro}{\@dtl@read} % \begin{macrocode} -\newcommand*{\@DTLremoverow}[2]{% +\newread\@dtl@read % \end{macrocode} -% Get row from data base +%\end{macro} +%\begin{macro}{\dtl@entrycr} +% Keep track of current column in data file % \begin{macrocode} - \edef\dtl@dogetrow{\noexpand\dtlgetrow{#1}{\number#2}}% - \dtl@dogetrow +\newcount\dtl@entrycr % \end{macrocode} -% Update the row indices +%\end{macro} +% +%\begin{macro}{\ifdtlnoheader} +% The "noheader" option indicates that the file doesn't have a +% header row. % \begin{macrocode} - \expandafter\dtl@decrementrows\expandafter - {\dtlbeforerow}{#2}% - \expandafter\dtl@decrementrows\expandafter - {\dtlafterrow}{#2}% +\define@boolkey{loaddb}[dtl]{noheader}[true]{} % \end{macrocode} -% Reconstruct database +%\end{macro} +% The "keys" option specifies the list of keys in the same order +% as the columns in the data file. +% Each key is stored in \cs{@dtl@inky@}\meta{n} where \meta{n} is the +% roman numeral representation of the current column. % \begin{macrocode} - \edef\dtl@tmp{\the\dtlbeforerow \the\dtlafterrow}% - \expandafter\global\csname dtldb@#1\endcsname - =\expandafter{\dtl@tmp}% +\define@key{loaddb}{keys}{% + \dtl@entrycr=0\relax + \@for\@dtl@key:=#1\do + {% + \advance\dtl@entrycr by 1\relax + \expandafter + \edef\csname @dtl@inky@\romannumeral\dtl@entrycr\endcsname{% + \@dtl@key}% + }% +} % \end{macrocode} -% decrement row counter +% The "headers" option specifies the list of headers in the +% same order as the columns in the data file. % \begin{macrocode} - \expandafter\global\expandafter\advance - \csname dtlrows@#1\endcsname by -1\relax +\define@key{loaddb}{headers}{% + \dtl@entrycr=0\relax + \@for\@dtl@head:=#1\do + {% + \advance\dtl@entrycr by 1\relax + \toks@=\expandafter{\@dtl@head}% + \expandafter + \edef\csname @dtl@inhd@\romannumeral\dtl@entrycr\endcsname{% + \the\toks@}% + }% } % \end{macrocode} -%\end{macro} % -%\subsection{Database Functions} -% -%\begin{macro}{\DTLsumforkeys} -%\begin{definition} -%\cs{DTLsumforkeys}\oarg{condition}\oarg{assign list}\marg{db list}\marg{key list}\marg{cmd} -%\end{definition} -% Sums all entries for key \meta{key} over all databases listed -% in \meta{db list}, -% and stores in \meta{cmd}, which must be a control sequence. -% The first argument \meta{condition} is the same as that -% for \cs{DTLforeach}. The second optional argument provides -% an assignment list to pass to \cs{DTLforeach} in case extra -% information is need by \meta{condition}. -%\changes{2.0}{2009 February 27}{added second optional argument} +% The following is supplied in a patch by Bruno Le Floch: +%\changes{2.10}{2012-07-18}{added omitlines key} % \begin{macrocode} -\newcommand*{\DTLsumforkeys}[1][\boolean{true}\and - \DTLisnumerical{\DTLthisval}]{% - \def\@dtl@cond{#1}% - \@dtlsumforkeys -} +\newcount{\dtl@omitlines} +\define@key{loaddb}{omitlines}{\dtl@omitlines=#1\relax} % \end{macrocode} -%\end{macro} % -%\begin{macro}{\@dtlsumforkeys} +%\begin{macro}{\dtldefaultkey} +% Default key to use if none specified (column index will be +% appended). % \begin{macrocode} -\newcommand*{\@dtlsumforkeys}[4][]{% - \def#4{0}% +\newcommand*{\dtldefaultkey}{Column} % \end{macrocode} -% Iterate over all the listed data bases +%\end{macro} +% +%\begin{macro}{\@dtl@readline} +%\begin{definition} +%\cs{@dtl@readline}\marg{file reg}\marg{cs} +%\end{definition} +% Reads line from \meta{file reg}, trims end of line character +% and stores in \meta{cs}. % \begin{macrocode} - \@for\@dtl@dbname:=#2\do{% -% \end{macrocode} -% Iterate through this database (using read only version) +\newcommand*{\@dtl@readline}[2]{% +% Read a line from "#1" and store in "#2" % \begin{macrocode} - \@sDTLforeach{\@dtl@dbname}% - {#1}% assignment list - {% + \read#1 to #2% % \end{macrocode} -% Iterate through key list. +% Trim the end of line character % \begin{macrocode} - \@for\@dtl@key:=#3\do{% - \@sdtl@getcolumnindex{\@dtl@col}{\@dtl@dbname}{\@dtl@key}% - \dtlcurrentrow=\expandafter{\dtl@thisrow}% - \dtlgetentryfromrow{\DTLthisval}{\@dtl@col}{\dtlcurrentrow}% - \expandafter\ifthenelse\expandafter{\@dtl@cond}% - {\DTLadd{#4}{#4}{\DTLthisval}}{}% - }% - }% + \ifdefempty{#2}% + {% }% + {% + \dtl@trim#2% + } } % \end{macrocode} %\end{macro} % -%\begin{macro}{\DTLsumcolumn} +%\begin{macro}{\@dtl@readrawline} %\begin{definition} -%\cs{DTLsumcolumn}\marg{db}\marg{key}\marg{cmd} +%\cs{@dtl@readrawline}\marg{file register}\marg{cs} %\end{definition} -% Quicker version of \cs{DTLsumforkeys} that just sums over -% one column (specified by \meta{key}) for a single database -% (specified by \meta{db}) and stores the result in \meta{cmd}. -%\changes{2.0}{2009 February 27}{new} +% Reads line from \meta{file register}, trims end of line character, +% applies mappings and stores in \meta{cs}. % \begin{macrocode} -\newcommand*{\DTLsumcolumn}[3]{% - \def#3{0}% +\newcommand*{\@dtl@readrawline}[2]{% +% Read a line from "#1" and store in "#2" +% \begin{macrocode} + \@dtl@rawread#1 to #2% % \end{macrocode} -% Check data base exists +% Trim the end of line character % \begin{macrocode} - \DTLifdbexists{#1}% - {% + \dtl@trim#2% % \end{macrocode} -% Check column exists +% Apply mappings % \begin{macrocode} - \@sDTLifhaskey{#1}{#2}% - {% - \@sdtlforcolumn{\DTLthisval}{#1}{#2}% - {% - \DTLadd{#3}{#3}{\DTLthisval}% - }% - }% -% \end{macrocode} -% key not defined for this data base -% \begin{macrocode} - {% - \PackageError{datatool}{Key `#2' doesn't - exist in database `#1'}{}% - }% - }% -% \end{macrocode} -% data base doesn't exist -% \begin{macrocode} - {% - \PackageError{datatool}{Data base `#1' doesn't - exist}{}% - }% + \dtl@domappings\@dtl@line } % \end{macrocode} %\end{macro} % -%\begin{macro}{\DTLmeanforkeys} +%\begin{macro}{\DTLloaddb} %\begin{definition} -%\cs{DTLmeanforkeys}\oarg{condition}\oarg{assign list}\marg{db list}\marg{key list}\marg{cmd} +% \cs{DTLloaddb}\oarg{options}\marg{db name}\marg{filename} %\end{definition} -% Computes the arithmetic mean of all entries for each key in -% \meta{key list} over all databases in \meta{db list}, -% and stores in \meta{cmd}, which must be a control sequence. -% The first argument \meta{condition} is the same as that -% for \cs{DTLforeach}. The second optional argument allows an -% assignment list to be passed to \cs{DTLforeach}. -%\changes{2.0}{2009 February 27}{added second optional argument} +% Creates a new database called \meta{db name}, and loads the data +% in \meta{filename} into it. The separator and delimiter used in +% the file must match \cs{@dtl@separator} and \cs{@dtl@delimiter}. +% The optional argument is a comma-separated list. +%\changes{2.0}{2009 February 27}{removed checks to see if the +% database exists when adding to it} +%\changes{2.0}{2009 February 27}{added optional argument} % \begin{macrocode} -\newcommand*{\DTLmeanforkeys}[1][\boolean{true}\and - \DTLisnumerical{\DTLthisval}]{% - \def\@dtl@cond{#1}% - \@dtlmeanforkeys +\newcommand*{\DTLloaddb}{% + \let\@dtl@doreadline\@dtl@readline + \@dtlloaddb } % \end{macrocode} %\end{macro} % -%\begin{macro}{\@dtl@elements} -% Count register to keep track of number of elements +%\begin{macro}{\@dtlloaddb} +% Loads database using \cs{@dtl@doreadline} to read and trim +% line from file. (\cs{@dtl@doreadline} must be set before use.) % \begin{macrocode} -\newcount\@dtl@elements +\newcommand*{\@dtlloaddb}[3][]{% % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@dtlmeanforkeys} +% Check if file exists % \begin{macrocode} -\newcommand*{\@dtlmeanforkeys}[4][]{% - \def#4{0}% - \@dtl@elements=0\relax + \IfFileExists{#3}{% % \end{macrocode} -% Iterate over all the listed data bases +% File exists. Locally change catcode of double quote character in +% case it has been made active. % \begin{macrocode} - \@for\@dtl@dbname:=#2\do{% + \begingroup + \catcode`\"12\relax % \end{macrocode} -% Iterate through this database (using read only version) +% Initialise default options % \begin{macrocode} - \@sDTLforeach{\@dtl@dbname}% - {#1}% assignment list - {% + \dtlnoheaderfalse % \end{macrocode} -% Iterate through key list. +% Get the options % \begin{macrocode} - \@for\@dtl@key:=#3\do{% - \@sdtl@getcolumnindex{\@dtl@col}{\@dtl@dbname}{\@dtl@key}% - \dtlcurrentrow=\expandafter{\dtl@thisrow}% - \dtlgetentryfromrow{\DTLthisval}{\@dtl@col}{\dtlcurrentrow}% - \expandafter\ifthenelse\expandafter{\@dtl@cond}% - {% - \DTLadd{#4}{#4}{\DTLthisval}% - \advance\@dtl@elements by 1\relax - }{}% - }% - }% - }% + \setkeys{loaddb}{#1}% % \end{macrocode} -% Divide total by number of elements summed. +% Open the file for reading. % \begin{macrocode} - \ifnum\@dtl@elements=0\relax - \PackageError{datatool}{Unable to evaluate mean: no data}{}% - \else - \edef\@dtl@n{\number\@dtl@elements}% - \DTLdiv{#4}{#4}{\@dtl@n}% - \fi -} + \openin\@dtl@read=#3% + \dtl@message{Reading `#3'}% % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\DTLmeanforcolumn} -%\begin{definition} -%\cs{DTLmeanforcolumn}\marg{db}\marg{key}\marg{cmd} -%\end{definition} -% Quicker version of \cs{DTLmeanforkeys} that just computes the -% mean over one column (specified by \meta{key}) for a single -% database (specified by \meta{db}) and stores the result in -% \meta{cmd}. -%\changes{2.0}{2009 February 27}{new} +% The following supplied in patch by Bruno Le~Floch: +%\changes{2.10}{2012-07-18}{added code to skip lines} % \begin{macrocode} -\newcommand*{\DTLmeanforcolumn}[3]{% - \def#3{0}% - \@dtl@elements=0\relax + \loop + \ifnum \dtl@omitlines > \z@ + \advance\dtl@omitlines by \m@ne + \read\@dtl@read to \@dtl@line + \repeat % \end{macrocode} -% Check data base exists +% Create the new database. % \begin{macrocode} - \DTLifdbexists{#1}% - {% + \DTLnewdb{#2}% % \end{macrocode} -% Check column exists +% Check if the file is empty. % \begin{macrocode} - \@sDTLifhaskey{#1}{#2}% - {% - \@sdtlforcolumn{\DTLthisval}{#1}{#2}% - {% - \DTLadd{#3}{#3}{\DTLthisval}% - \advance\@dtl@elements by 1\relax - }% - \ifnum\@dtl@elements=0\relax - \PackageError{datatool}{Can't compute mean for - column `#2' in database `#1': no data}{}% - \else - \edef\@dtl@n{\number\@dtl@elements}% - \DTLdiv{#3}{#3}{\@dtl@n}% - \fi - }% + \ifeof\@dtl@read % \end{macrocode} -% key not defined for this data base +% File is empty, so just issue a warning. % \begin{macrocode} - {% - \PackageError{datatool}{Key `#2' doesn't - exist in database `#1'}{}% - }% - }% + \PackageWarning{datatool}{File `#3' has no data}% + \else % \end{macrocode} -% data base doesn't exist +% Does the file have a header row? % \begin{macrocode} - {% - \PackageError{datatool}{Data base `#1' doesn't - exist}{}% - }% -} + \ifdtlnoheader + \else % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\DTLvarianceforkeys} -%\begin{definition} -%\cs{DTLvarianceforkeys}\oarg{condition}\oarg{assign list}\marg{db list}\marg{key list}\marg{cmd} -%\end{definition} -% Computes the variance of all entries for each key in -% \meta{key list} over all databases in \meta{db list}, -% and stores in \meta{cmd}, which must be a control sequence. -% The first optional argument \meta{condition} is the same as that -% for \cs{DTLforeach}. The second optional argument is an assignment -% list to pass to \cs{DTLforeach} in case it is required for the -% condition. -%\changes{2.0}{2009 February 27}{added second optional argument} +% Remove initial blank rows % \begin{macrocode} -\newcommand*{\DTLvarianceforkeys}[1][\boolean{true}\and - \DTLisnumerical{\DTLthisval}]{% - \def\@dtl@cond{#1}% - \@dtlvarianceforkeys -} + \loop % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@dtlmeanforkeys} +% Set repeat condition to false % \begin{macrocode} -\newcommand*{\@dtlvarianceforkeys}[4][]{% - \@dtlmeanforkeys[#1]{#2}{#3}{\dtl@mean}% - \def#4{0}% - \@dtl@elements=0\relax + \@dtl@conditionfalse % \end{macrocode} -% Iterate over all the listed data bases +% Do nothing if reached the end of file % \begin{macrocode} - \@for\@dtl@dbname:=#2\do{% + \ifeof\@dtl@read + \else % \end{macrocode} -% Iterate through this database (using read only version) +% Read a line from the file and store in \cs{@dtl@line} % \begin{macrocode} - \@sDTLforeach{\@dtl@dbname}% - {#1}% assignment list - {% + \@dtl@doreadline\@dtl@read\@dtl@line % \end{macrocode} -% Iterate through key list. +% If this is a blank row, set repeat condition to true % \begin{macrocode} - \@for\@dtl@key:=#3\do{% - \@sdtl@getcolumnindex{\@dtl@col}{\@dtl@dbname}{\@dtl@key}% - \dtlcurrentrow=\expandafter{\dtl@thisrow}% - \dtlgetentryfromrow{\DTLthisval}{\@dtl@col}{\dtlcurrentrow}% - \expandafter\ifthenelse\expandafter{\@dtl@cond}% - {% + \ifdefempty{\@dtl@line}% + {% + \@dtl@conditiontrue + }% + {% + }% + \fi % \end{macrocode} -% compute $(x_i - \mu)^2$ +% Repeat loop if necessary % \begin{macrocode} - \DTLsub{\dtl@diff}{\DTLthisval}{\dtl@mean}% - \DTLmul{\dtl@diff}{\dtl@diff}{\dtl@diff}% - \DTLadd{#4}{#4}{\dtl@diff}% - \advance\@dtl@elements by 1\relax - }{}% - }% - }% - }% + \if@dtl@condition + \repeat % \end{macrocode} -% Divide by number of elements. +% Parse the header row. Store the row as +% \meta{sep}\meta{row}\meta{sep} in \cs{@dtl@lin@}. % \begin{macrocode} - \ifnum\@dtl@elements=0\relax - \PackageError{datatool}{Unable to evaluate variance: no data}{}% - \else - \edef\@dtl@n{\number\@dtl@elements}% - \DTLdiv{#4}{#4}{\@dtl@n}% - \fi -} + \protected@edef\@dtl@lin@{% + \@dtl@separator\@dtl@line\@dtl@separator}% % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\DTLvarianceforcolumn} -%\begin{definition} -%\cs{DTLvarianceforcolumn}\marg{db}\marg{key}\marg{cmd} -%\end{definition} -% Quicker version of \cs{DTLvarianceforkeys} that just computes the -% variance over one column (specified by \meta{key}) for a single -% database (specified by \meta{db}) and stores the result in -% \meta{cmd}. -%\changes{2.0}{2009 February 27}{new} +% Keep track of columns: % \begin{macrocode} -\newcommand*{\DTLvarianceforcolumn}[3]{% - \DTLmeanforcolumn{#1}{#2}{\dtl@mean}% - \def#3{0}% - \@dtl@elements=0\relax + \dtl@entrycr=0\relax % \end{macrocode} -% Check data base exists +% Keep lopping off elements until the end of the row is reached. +% (That is, until \cs{@dtl@lin@} is \cs{@dtl@separator}.) +%\changes{2.0}{2009 February 27}{changed \cs{whiledo} to +% \cs{loop} to improve efficiency}% % \begin{macrocode} - \DTLifdbexists{#1}% - {% + \loop % \end{macrocode} -% Check column exists +% Lopoff the first element and store in \cs{@dtl@key} % \begin{macrocode} - \@sDTLifhaskey{#1}{#2}% - {% - \@sdtlforcolumn{\DTLthisval}{#1}{#2}% - {% + \expandafter\@dtl@lopoff\@dtl@lin@\to\@dtl@lin@\@dtl@key % \end{macrocode} -% compute $(x_i - \mu)^2$ +% Increment column count. % \begin{macrocode} - \DTLsub{\dtl@diff}{\DTLthisval}{\dtl@mean}% - \DTLmul{\dtl@diff}{\dtl@diff}{\dtl@diff}% - \DTLadd{#3}{#3}{\dtl@diff}% - \advance\@dtl@elements by 1\relax - }% - \ifnum\@dtl@elements=0\relax - \PackageError{datatool}{Can't compute variance for - column `#2' in database `#1': no data}{}% - \else - \edef\@dtl@n{\number\@dtl@elements}% - \DTLdiv{#3}{#3}{\@dtl@n}% - \fi - }% + \advance\dtl@entrycr by 1\relax % \end{macrocode} -% key not defined for this data base +% If missing a key, add generic one: +%\changes{2.10}{2012-07-18}{add generic header if missing} % \begin{macrocode} - {% - \PackageError{datatool}{Key `#2' doesn't - exist in database `#1'}{}% - }% - }% + \ifdefempty{\@dtl@key}% + {% + \edef\@dtl@key{\dtldefaultkey\number\dtl@entrycr}% + }% + {}% % \end{macrocode} -% data base doesn't exist +% Store key in \cs{@dtl@toks} % \begin{macrocode} - {% - \PackageError{datatool}{Data base `#1' doesn't - exist}{}% - }% -} + \expandafter\@dtl@toks\expandafter{\@dtl@key}% % \end{macrocode} -%\end{macro} -% -% -%\begin{macro}{\DTLsdforkeys} -%\begin{definition} -%\cs{DTLsdforkeys}\oarg{condition}\oarg{assign list}\marg{db list}\marg{key list}\marg{cmd} -%\end{definition} -% Computes the standard deviation of all entries for each key in -% \meta{key list} over all databases in \meta{db list}, -% and stores in \meta{cmd}, which must be a control sequence. -% The first optional argument \meta{condition} is the same as that -% for \cs{DTLforeach}. The second optional argument is an -% assignment list for \cs{DTLforeach} in case it is needed for -% the condition. -%\changes{2.0}{2009 February 27}{added second optional argument} +% Store the key in \cs{@dtl@inky@}\meta{n} where \meta{n} is the +% roman numeral representation of the current column, unless +% already defined. % \begin{macrocode} -\newcommand*{\DTLsdforkeys}[1][\boolean{true}\and -\DTLisnumerical{\DTLthisval}]{% - \def\@dtl@cond{#1}% - \@dtlsdforkeys -} + \@ifundefined{@dtl@inky@\romannumeral\dtl@entrycr}% + {% + \expandafter + \edef\csname @dtl@inky@\romannumeral + \dtl@entrycr\endcsname{\the\@dtl@toks}% + }% + {% % \end{macrocode} -%\end{macro} -%\begin{macro}{\@dtlsdforkeys} +% If key has been specified in "#1", then use the header found in the +% file, unless a header has also been specified in "#1" % \begin{macrocode} -\newcommand*{\@dtlsdforkeys}[4][]{% - \@dtlvarianceforkeys[#1]{#2}{#3}{#4}% - \DTLsqrt{#4}{#4}% -} + \@ifundefined{@dtl@inhd@\romannumeral\dtl@entrycr}% + {% + \expandafter + \edef\csname @dtl@inhd@\romannumeral + \dtl@entrycr\endcsname{\the\@dtl@toks}% + }% + {}% + }% % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\DTLsdforcolumn} -%\begin{definition} -%\cs{DTLsdforcolumn}\marg{db}\marg{key}\marg{cmd} -%\end{definition} -% Quicker version of \cs{DTLsdforkeys} that just computes the -% standard deviation over one column (specified by \meta{key}) for -% a single database (specified by \meta{db}) and stores the result -% in \meta{cmd}. -%\changes{2.0}{2009 February 27}{new} +% Check if the loop should be repeated % \begin{macrocode} -\newcommand*{\DTLsdforcolumn}[3]{% - \DTLvarianceforcolumn{#1}{#2}{#3}% - \DTLsqrt{#3}{#3}% -} + \ifx\@dtl@lin@\@dtl@separator + \@dtl@conditionfalse + \else + \@dtl@conditiontrue + \fi % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\DTLminforkeys} -%\begin{definition} -%\cs{DTLminforkeys}\oarg{condition}\oarg{assign list}\marg{db list}\marg{key list}\marg{cmd} -%\end{definition} -% Determines the minimum over all entries for each key in -% \meta{key list} over all databases in \meta{db list}, -% and stores in \meta{cmd}, which must be a control sequence. -% The first optional argument \meta{condition} is the same as that -% for \cs{DTLforeach}. The second optional argument is an -% assignment list for \cs{DTLforeach} in the event that extra -% information is need for the condition. -%\changes{2.0}{2009 February 27}{added second optional argument} +% Repeat loop if necessary. % \begin{macrocode} -\newcommand*{\DTLminforkeys}[1][\boolean{true}\and - \DTLisnumerical{\DTLthisval}]{% - \def\@dtl@cond{#1}% - \@dtlminforkeys -} + \if@dtl@condition + \repeat % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@dtlminforkeys} +% End if no header % \begin{macrocode} -\newcommand*{\@dtlminforkeys}[4][]{% - \def#4{}% + \fi % \end{macrocode} -% Iterate over all the listed data bases +% Now for the rest of the data. If the end of file has been +% reached, then only the header row is available or file is empty. % \begin{macrocode} - \@for\@dtl@dbname:=#2\do{% + \ifeof\@dtl@read + \ifdtlnoheader + \PackageWarning{datatool}{No data in `#3'}% + \else + \PackageWarning{datatool}{Only header row found in `#3'}% + \fi + \else % \end{macrocode} -% Iterate through this database (using read only version) +% Iterate through the rest of the file. First set the repeat +% condition to true: % \begin{macrocode} - \@sDTLforeach{\@dtl@dbname}% - {#1}% assignment list - {% + \@dtl@conditiontrue + \loop % \end{macrocode} -% Iterate through key list. +% Read in a line % \begin{macrocode} - \@for\@dtl@key:=#3\do{% - \@sdtl@getcolumnindex{\@dtl@col}{\@dtl@dbname}{\@dtl@key}% - \dtlcurrentrow=\expandafter{\dtl@thisrow}% - \dtlgetentryfromrow{\DTLthisval}{\@dtl@col}{\dtlcurrentrow}% - \expandafter\ifthenelse\expandafter{\@dtl@cond}% - {% - \ifx#4\@empty - \let#4\DTLthisval - \else - \DTLmin{#4}{#4}{\DTLthisval}% - \fi - }{}% - }% - }% - }% -} + \@dtl@doreadline\@dtl@read\@dtl@line % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\DTLminforcolumn} -%\begin{definition} -%\cs{DTLminforcolumn}\marg{db}\marg{key}\marg{cmd} -%\end{definition} -% Quicker version of \cs{DTLminforkeys} that just finds the -% minimum value in one column (specified by \meta{key}) for a -% single database (specified by \meta{db}) and stores the result -% in \meta{cmd}. -%\changes{2.0}{2009 February 27}{new} +% Check if the line is empty. +%\changes{2.0}{2009 February 27}{changed \cs{ifthenelse} to +%\cs{ifx} to improve efficiency} +%\changes{2.10}{2012-07-16}{changed \cs{ifx} to \cs{ifdefempty}} % \begin{macrocode} -\newcommand*{\DTLminforcolumn}[3]{% - \def#3{}% + \ifdefempty{\@dtl@line}% + {% % \end{macrocode} -% Check data base exists +% Do nothing if the row is empty. % \begin{macrocode} - \DTLifdbexists{#1}% - {% + }% + {% % \end{macrocode} -% Check column exists +% Add a new row to the database. (Don't need to check if the +% database exists, since it's just been created.) % \begin{macrocode} - \@sDTLifhaskey{#1}{#2}% - {% - \@sdtlforcolumn{\DTLthisval}{#1}{#2}% - {% - \ifx#3\@empty - \let#3\DTLthisval - \else - \DTLmin{#3}{#3}{\DTLthisval}% - \fi - }% - }% + \@sDTLnewrow{#2}% % \end{macrocode} -% key not defined for this data base +% Store the row as \meta{sep}\meta{row}\meta{sep} to make the +% lopping off easier % \begin{macrocode} - {% - \PackageError{datatool}{Key `#2' doesn't - exist in database `#1'}{}% - }% - }% + \expandafter\@dtl@toks\expandafter{\@dtl@line}% + \edef\@dtl@lin@{\@dtl@separator\the\@dtl@toks + \@dtl@separator}% % \end{macrocode} -% data base doesn't exist +% Reset the column counter. % \begin{macrocode} - {% - \PackageError{datatool}{Data base `#1' doesn't - exist}{}% - }% -} + \dtl@entrycr=0\relax % \end{macrocode} -%\end{macro} -% -% -%\begin{macro}{\DTLmaxforkeys} -%\begin{definition} -%\cs{DTLmaxforkeys}\oarg{condition}\oarg{assign list}\marg{db list}\marg{key list}\marg{cmd} -%\end{definition} -% Determines the maximum over all entries for each key in -% \meta{key list} over all databases in \meta{db list}, -% and stores in \meta{cmd}, which must be a control sequence. -% The first optional argument \meta{condition} is the same as that -% for \cs{DTLforeach}. The second optional argument is an -% assignment list to pass to \cs{DTLforeach} in the event that -% extra information is required in the condition. -%\changes{2.0}{2009 February 27}{added second optional argument} +%\changes{2.0}{2009 February 27}{changed \cs{whiledo} to \cs{loop} +% to improve efficiency} +% Iterate through each element in the row. Needs to be grouped +% since we're already inside a loop. % \begin{macrocode} -\newcommand*{\DTLmaxforkeys}[1][\boolean{true}\and - \DTLisnumerical{\DTLthisval}]{% - \def\@dtl@cond{#1}% - \@dtlmaxforkeys -} + {% % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@dtlmaxforkeys} +% Initialise repeat condition % \begin{macrocode} -\newcommand*{\@dtlmaxforkeys}[4][]{% - \def#4{}% + \@dtl@conditiontrue % \end{macrocode} -% Iterate over all the listed data bases +% Iterate through the list % \begin{macrocode} - \@for\@dtl@dbname:=#2\do{% + \loop % \end{macrocode} -% Iterate through this database (using read only version) +% lop off first element and store in \cs{@dtl@thisentry} % \begin{macrocode} - \@sDTLforeach{\@dtl@dbname}% - {#1}% assignment list - {% + \expandafter\@dtl@lopoff\@dtl@lin@\to + \@dtl@lin@\@dtl@thisentry % \end{macrocode} -% Iterate through key list. +% Increment the column count. % \begin{macrocode} - \@for\@dtl@key:=#3\do{% - \@sdtl@getcolumnindex{\@dtl@col}{\@dtl@dbname}{\@dtl@key}% - \dtlcurrentrow=\expandafter{\dtl@thisrow}% - \dtlgetentryfromrow{\DTLthisval}{\@dtl@col}{\dtlcurrentrow}% - \expandafter\ifthenelse\expandafter{\@dtl@cond}% - {% - \ifx#4\@empty - \let#4\DTLthisval - \else - \DTLmax{#4}{#4}{\DTLthisval}% - \fi - }{}% - }% - }% - }% -} + \advance\dtl@entrycr by 1\relax % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\DTLmaxforcolumn} -%\begin{definition} -%\cs{DTLmaxforcolumn}\marg{db}\marg{key}\marg{cmd} -%\end{definition} -% Quicker version of \cs{DTLmaxforkeys} that just finds the -% maximum value in one column (specified by \meta{key}) for a -% single database (specified by \meta{db}) and stores the result -% in \meta{cmd}. -%\changes{2.0}{2009 February 27}{new} +% Get the key for this column and store in \cs{@dtl@thiskey}. +% Use default value if not defined. % \begin{macrocode} -\newcommand*{\DTLmaxforcolumn}[3]{% - \def#3{}% + \@ifundefined{@dtl@inky@\romannumeral\dtl@entrycr}% + {% + \edef\@dtl@thiskey{\dtldefaultkey + \number\dtl@entrycr}% + \expandafter\let + \csname @dtl@inky@\romannumeral + \dtl@entrycr\endcsname\@dtl@thiskey + }% + {% + \edef\@dtl@thiskey{% + \csname @dtl@inky@\romannumeral + \dtl@entrycr\endcsname}% + }% % \end{macrocode} -% Check data base exists +% Store this entry in \cs{@dtl@toks} % \begin{macrocode} - \DTLifdbexists{#1}% - {% + \expandafter\@dtl@toks\expandafter{\@dtl@thisentry}% % \end{macrocode} -% Check column exists +% Add this entry to the database % \begin{macrocode} - \@sDTLifhaskey{#1}{#2}% + \edef\@do@dtlnewentry{\noexpand\@sDTLnewdbentry + {#2}{\@dtl@thiskey}{\the\@dtl@toks}}% + \@do@dtlnewentry +% \end{macrocode} +% Check if loop should be terminated +% \begin{macrocode} + \ifx\@dtl@lin@\@dtl@separator + \@dtl@conditionfalse + \fi +% \end{macrocode} +% Repeat loop if necessary +% \begin{macrocode} + \if@dtl@condition + \repeat + }% +% \end{macrocode} +% End of parsing this row +% \begin{macrocode} + }% +% \end{macrocode} +% If the end of file has been reached, set the repeat condition +% to false. +% \begin{macrocode} + \ifeof\@dtl@read \@dtl@conditionfalse\fi +% \end{macrocode} +% Repeat if necessary +% \begin{macrocode} + \if@dtl@condition + \repeat + \fi +% \end{macrocode} +% End of first \cs{ifeof} +% \begin{macrocode} + \fi +% \end{macrocode} +% Close the input file +% \begin{macrocode} + \closein\@dtl@read +% \end{macrocode} +% Set the headers if required +% \begin{macrocode} + \edef\@dtl@maxcols{\expandafter + \number\csname dtlcols@#2\endcsname}% + \dtlgforint\dtl@entrycr=1\to\@dtl@maxcols\step1\do {% - \@sdtlforcolumn{\DTLthisval}{#1}{#2}% + \@ifundefined{@dtl@inhd@\romannumeral\dtl@entrycr}% + {}% {% - \ifx#3\@empty - \let#3\DTLthisval - \else - \DTLmax{#3}{#3}{\DTLthisval}% - \fi + \expandafter\let\expandafter\@dtl@head + \csname @dtl@inhd@\romannumeral\dtl@entrycr\endcsname + \@dtl@toks=\expandafter{\@dtl@head}% + \edef\@dtl@dosetheader{\noexpand\@dtl@setheaderforindex + {#2}{\number\dtl@entrycr}{\the\@dtl@toks}}% + \@dtl@dosetheader }% }% % \end{macrocode} -% key not defined for this data base +% End current scope % \begin{macrocode} - {% - \PackageError{datatool}{Key `#2' doesn't - exist in database `#1'}{}% - }% - }% + \endgroup % \end{macrocode} -% data base doesn't exist +% End true part of if file exists % \begin{macrocode} - {% - \PackageError{datatool}{Data base `#1' doesn't - exist}{}% - }% -} + }{% % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\DTLcomputebounds} -%\begin{definition} -%\cs{DTLcomputebounds}\oarg{condition}\marg{db list}\marg{x key}\marg{y key}\marg{minX cmd}\marg{minY cmd}\marg{maxX cmd}\marg{maxY cmd} -%\end{definition} -% Computes the maximum and minimum $x$ and $y$ values over all -% the databases listed in \meta{db list} where the $x$ value -% is given by \meta{x key} and the $y$ value is given by -% \meta{y key}. The results are stored in \meta{minX cmd}, -% \meta{minY cmd}, \meta{maxX cmd} and \meta{maxY cmd} in -% standard decimal format. +% Requested file not found on TeX's path % \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 + \PackageError{datatool}{Can't load database `#2' (file `#3' + doesn't exist)}{}% }% -}% } % \end{macrocode} %\end{macro} % -%\begin{macro}{\DTLgetvalueforkey} +%\begin{macro}{\dtl@trim} %\begin{definition} -%\cs{DTLgetvalueforkey}\marg{cmd}\marg{key}\marg{db name}\marg{ref -% key}\marg{ref value} +%\cs{dtl@trim}\marg{line} %\end{definition} -% This (globally) sets \meta{cmd} (a control sequence) to the -% value of the key specified by \meta{key} in the first row -% of the database called \meta{db name} which contains the key -% \meta{ref key} which has the value \meta{value}. -%\changes{1.01}{2007 Aug 17}{new} -%\changes{2.0}{2009 February 27}{updated to use new database -% structure} -% \begin{macrocode} -\newcommand*{\DTLgetvalueforkey}[5]{% -% \end{macrocode} -% Get row containing referenced (key,value) pair +% Trims the trailing space from \meta{line}. % \begin{macrocode} - \DTLgetrowforkey{\@dtl@row}{#3}{#4}{#5}% +\newcommand{\dtl@trim}[1]{% + \def\@dtl@trmstr{}% + \expandafter\@dtl@starttrim#1\@nil + \let#1=\@dtl@trmstr +} % \end{macrocode} -% Get column number for \meta{key} +%\end{macro} +%\begin{macro}{\@dtl@starttrim} +% Start trimming +%\changes{2.10}{2012-07-18}{added check in the event there's no +%trailing space} % \begin{macrocode} - \@sdtl@getcolumnindex{\@dtl@col}{#3}{#2}% +\long\def\@dtl@starttrim#1#2{% + \def\@dtl@tmpB{#2}% + \ifx\par#1% + \def\@dtl@dotrim{\@dtl@trim{} #2}% + \else + \ifx\@dtl@tmpB\@nnil + \def\@dtl@dotrim{}% + \def\@dtl@trmstr{#1}% + \else + \def\@dtl@dotrim{\@dtl@trim#1#2}% + \fi + \fi + \@dtl@dotrim +} % \end{macrocode} -% Get value for given column +%\end{macro} +%\begin{macro}{\@dtl@trim} % \begin{macrocode} - {% - \dtlcurrentrow=\expandafter{\@dtl@row}% - \edef\@dtl@dogetval{\noexpand\dtlgetentryfromcurrentrow - {\noexpand\@dtl@val}{\@dtl@col}}% - \@dtl@dogetval - \global\let#1=\@dtl@val - }% -} +\long\def\@dtl@trim#1 \@nil{\long\def\@dtl@trmstr{#1}} % \end{macrocode} %\end{macro} % -%\begin{macro}{\DTLgetrowforkey} +%\begin{macro}{\DTLloadrawdb} %\begin{definition} -%\cs{DTLgetrowforkey}\marg{cmd}\marg{db name}\marg{ref -% key}\marg{ref value} +%\cs{DTLloadrawdb}\marg{db name}\marg{filename} %\end{definition} -% This (globally) sets \meta{cmd} (a control sequence) to the -% first row -% of the database called \meta{db name} which contains the key -% \meta{ref key} that has the value \meta{value}. -%\changes{1.01}{2007 Aug 17}{new} -%\changes{2.0}{2009 February 27}{update to use new database -% structure} +% Loads a raw database (substitutes "%" $\to$ "\%", +% "$" $\to$ "\$", "&" $\to$ "\&", "#" $\to$ "\#", +% "~" $\to$ "\textasciitilde", "_" $\to$ "\_" +% and "^" $\to$ "\textasciicircum".) The user can add additional +% mappings. % \begin{macrocode} -\newcommand*{\DTLgetrowforkey}[4]{% - \global\let#1=\@empty - \@sDTLforeach{#2}{\dtl@refvalue=#3}{% - \DTLifnull{\dtl@refvalue}% - {}% - {% - \ifthenelse{\equal{\dtl@refvalue}{#4}}% - {% - \xdef#1{\the\dtlcurrentrow}% - \dtlbreak - }% - {}% - }% - }% +\newcommand*\DTLloadrawdb{% + \let\@dtl@doreadline\@dtl@readrawline + \@dtlloaddb } % \end{macrocode} %\end{macro} % -%\begin{macro}{\dtlsplitrow} +%\begin{macro}{\@dtl@rawread} %\begin{definition} -%\cs{dtlsplitrow}\marg{row specs}\marg{col num}\marg{before -% cs}\marg{after cs} +% \cs{@dtl@rawread}\meta{number}to\meta{cmd} %\end{definition} -% Splits the row around the entry given by \meta{col num}. The -% entries before the split are stored in \meta{before cs} and the -% entries after the split are stored in \meta{after cs}. -% \meta{row specs} and \meta{col num} need to be expanded before use. +% Reads in a raw line from file given by \meta{number} +% converts special characters and stores in \meta{cmd} % \begin{macrocode} -\newcommand*{\dtlsplitrow}[4]{% - \def\@dtlsplitrow##1%before stuff - \db@col@id@w #2\db@col@id@end@% column id - ##2% unwanted stuff - \db@col@id@w #2\db@col@id@end@% column id - ##3% after stuff - \q@nil{\def#3{##1}\def#4{##3}}% - \@dtlsplitrow#1\q@nil -} +\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} -% -%\subsection{Sorting Databases} -% -%\begin{macro}{\@dtl@list} -% Token register to store data when sorting. -%\changes{2.0}{2009 February 27}{new} +%\begin{macro}{\@dtl@activatebraces} +% \cs{@dtl@activatebraces} resets braces for \cs{@dtl@rawread} % \begin{macrocode} -\newtoks\@dtl@list +\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}{\DTLsort} +%\begin{macro}{\DTLrawmap} %\begin{definition} -% \cs{DTLsort}\oarg{replacement keys}\marg{sort criteria}\marg{db name} +%\cs{DTLrawmap}\marg{string}\marg{replacement} %\end{definition} -% Sorts database \meta{db name} according to \marg{sort criteria}, -% which must be a comma separated list of keys, and optionally -% \texttt{=}\meta{order}, where \meta{order} is either -% "ascending" or "descending". The optional argument is a list of -% keys to uses if the given key has a null value. The starred -% version uses a case insensitive string comparison. -%\changes{1.01}{2007 Aug 17}{added optional argument} -%\changes{1.01}{2007 Aug 17}{added starred version} -%\changes{2.0}{2009 February 27}{updated to use new data structure} -% \begin{macrocode} -\newcommand*{\DTLsort}{\@ifstar\@sDTLsort\@DTLsort} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@DTLsort} -% Unstarred (case sensitive) version. -% \begin{macrocode} -\newcommand{\@DTLsort}[3][]{% -% \end{macrocode} -% Check the database exists +% Additional mappings to perform when reading a raw data file % \begin{macrocode} - \DTLifdbexists{#3}% +\newcommand*{\DTLrawmap}[2]{% + \expandafter\@dtl@toks\expandafter{\@dtl@rawmappings}% + \ifdefempty{\@dtl@rawmappings}% {% -% \end{macrocode} -% Store replacement keys in \cs{@dtl@replacementkeys}. -% \begin{macrocode} - \edef\@dtl@replacementkeys{#1}% -% \end{macrocode} -% Store sort order in \cs{@dtl@sortorder}. -% \begin{macrocode} - \edef\@dtl@sortorder{#2}% -% \end{macrocode} -% Set \cs{@dtl@comparecs} to the required string comparison -% function. (Using case sensitive comparison macro \cs{dtlcompare}.) -% \begin{macrocode} - \let\@dtl@comparecs=\dtlcompare -% \end{macrocode} -% Sort the database. -% \begin{macrocode} - \dtl@sortdata{#3}% + \def\@dtl@rawmappings{{#1}{#2}}% }% {% - \PackageError{datatool}{Database `#3' doesn't exist}{}% + \def\@dtl@tmp{{#1}{#2}} + \protected@edef\@dtl@rawmappings{\the\@dtl@toks,\@dtl@tmp} }% } % \end{macrocode} %\end{macro} % -%\begin{macro}{\@sDTLsort} -% Starred (case insensitive) version. -% \begin{macrocode} -\newcommand{\@sDTLsort}[3][]{% -% \end{macrocode} -% Check the database exists -% \begin{macrocode} - \DTLifdbexists{#3}% - {% -% \end{macrocode} -% Store replacement keys in \cs{@dtl@replacementkeys}. -% \begin{macrocode} - \edef\@dtl@replacementkeys{#1}% -% \end{macrocode} -% Store sort order in \cs{@dtl@sortorder}. -% \begin{macrocode} - \edef\@dtl@sortorder{#2}% -% \end{macrocode} -% Set \cs{@dtl@comparecs} to the required string comparison -% function. (Using case insensitive comparison macro -% \cs{dtlicompare}.) +%\begin{macro}{\@dtl@rawmappings} +% List of mappings. % \begin{macrocode} - \let\@dtl@comparecs=\dtlicompare +\newcommand*{\@dtl@rawmappings}{} % \end{macrocode} -% Sort the database. +%\end{macro} +%\begin{macro}{\dtl@domappings} +%\begin{definition} +% \cs{dtl@domappings}\marg{cmd} +%\end{definition} +% Do all mappings in string given by \meta{cmd}. +%\changes{2.10}{2012-07-18}{replaced \cs{DTLsubstitute} with +%\cs{DTLsubstituteall}} % \begin{macrocode} - \dtl@sortdata{#3}% - }% - {% - \PackageError{datatool}{Database `#3' doesn't exist}{}% +\newcommand*{\dtl@domappings}[1]{% + \@for\@dtl@map:=\@dtl@rawmappings\do{% + \expandafter\DTLsubstituteall\expandafter#1\@dtl@map }% } % \end{macrocode} %\end{macro} % -%\begin{macro}{\@dtl@rowa} -% Token register to store first row when sorting. +%\section{Debugging commands} +% These commands are provided to assist debugging +%\begin{macro}{\dtlshowdb} +%\begin{definition} +%\cs{dtlshowdb}\marg{db name} +%\end{definition} +% Shows the database. +%\changes{2.0}{2009 February 27}{updated to use new database structure} % \begin{macrocode} -\newtoks\@dtl@rowa +\newcommand*{\dtlshowdb}[1]{% + \expandafter\showthe\csname dtldb@#1\endcsname +} % \end{macrocode} %\end{macro} -%\begin{macro}{\@dtl@rowb} -% Token register to store comparison row when sorting. +% +%\begin{macro}{\dtlshowdbkeys} +%\begin{definition} +%\cs{dtlshowdbkeys}\marg{db name} +%\end{definition} +% Shows the key list for the named database. +%\changes{2.0}{2009 February 27}{updated to use new database structure} % \begin{macrocode} -\newtoks\@dtl@rowb +\newcommand*{\dtlshowdbkeys}[1]{% + \expandafter\showthe\csname dtlkeys@#1\endcsname +} % \end{macrocode} %\end{macro} % -%\begin{macro}{\dtl@sortdata} +%\begin{macro}{\dtlshowtype} %\begin{definition} -%\cs{dtl@sortdata}\marg{db} +%\cs{dtlshowtype}\marg{db name}\marg{key} %\end{definition} -% Sorts the data in named database using an insertion sort -% algorithm. -% \cs{@dtl@replacementkeys}, \cs{@dtl@sortorder} and -% \cs{@dtl@comparecs} must be set prior to use. -%\changes{2.0}{2009 February 27}{new} +% Show the data type for given key in the named database. +% This should be an integer from 0 to 3. +%\changes{2.0}{2009 February 27}{updated to use new database structure} % \begin{macrocode} -\newcommand*{\dtl@sortdata}[1]{% +\newcommand*{\dtlshowtype}[2]{% + \DTLgetdatatype{\@dtl@type}{#1}{#2}\show\@dtl@type +} % \end{macrocode} -% Initialise macro containing sorted data. +%\end{macro} +%\iffalse % \begin{macrocode} - \def\@dtl@sortedlist{}% +% % \end{macrocode} -% Store database name. +%\fi +%\iffalse % \begin{macrocode} - \edef\@dtl@dbname{#1}% +%<*databib.sty> % \end{macrocode} -% Iterate through each row and insert into sorted list. +%\fi +%\chapter{databib.sty} +%\label{sec:src:databib} +%\section{Package Declaration} % \begin{macrocode} - \@dtlforeachrow(\@dtl@rowAnum,\@dtl@rowAcontents)\in{#1}\do{% - \@dtl@rowa=\expandafter{\@dtl@rowAcontents}% +\NeedsTeXFormat{LaTeX2e} +\ProvidesPackage{databib}[2012/07/18 v2.10 (NLCT)] % \end{macrocode} -% Create a temporary list +% Load required packages: % \begin{macrocode} - \def\@dtl@newlist{}% +\RequirePackage{datatool} % \end{macrocode} -% Initialise the insertion for this iteration. Insertion hasn't -% been done yet. +%\section{Package Options} +%\begin{macro}{\dtlbib@style} +%The default bib style is stored in \cs{dtlbib@style}. % \begin{macrocode} - \@dtl@insertdonefalse +\newcommand*{\dtlbib@style}{plain} % \end{macrocode} -% Initialise row index to 0 +%\end{macro} +% The \pkgopt[databib]{style} package option sets \cs{dtlbib@style}. % \begin{macrocode} - \dtlrownum=0\relax +\define@choicekey{databib.sty}{style}{plain,abbrv,alpha}{% +\def\dtlbib@style{#1}} % \end{macrocode} -% Iterate through sorted list. +% Process package options: % \begin{macrocode} - \expandafter\@dtl@foreachrow\@dtl@sortedlist - \db@row@elt@w% - \db@row@id@w \@nil\db@row@id@end@% - \db@row@id@w \@nil\db@row@id@end@% - \db@row@elt@end@% - \@@{\@dtl@rowBnum}{\@dtl@rowBcontents}{% +\ProcessOptionsX % \end{macrocode} -% Store row B in a token register +%\section{Loading BBL file} +%\begin{macro}{\DTLloadbbl} +%\begin{definition} +%\cs{DTLloadbib}\oarg{bbl file}\marg{db name}\marg{bib list} +%\end{definition} % \begin{macrocode} - \@dtl@rowb=\expandafter{\@dtl@rowBcontents}% +\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} -% Get current row number of sorted list +%\end{macro} +%\begin{macro}{\DTLnewbibrow} +% \cs{DTLnewbibrow} adds a new row to the bibliography database. +% (\cs{DTLBIBdbname} must be set prior to use to the name +% of the \sty{datatool} database which must exist. Any check +% to determine its existence should be performed when +% \cs{DTLBIBdbname} is set.) +%\changes{1.03}{2009 January 27}{removed check if database exists} % \begin{macrocode} - \dtlrownum=\@dtl@rowBnum -% \end{macrocode} -% Has the insertion been done? -% \begin{macrocode} - \if@dtl@insertdone -% \end{macrocode} -% New element has already been inserted, so just increment the row -% number to compensate for the inserted row. -% \begin{macrocode} - \advance\dtlrownum by 1\relax - \else +\newcommand*{\DTLnewbibrow}{\@DTLnewrow{\DTLBIBdbname}} % \end{macrocode} -% Insertion hasn't been done yet. -% Compare row A and row B. +%\end{macro} +%\begin{macro}{\DTLnewbibitem} +%\begin{definition} +%\cs{DTLnewbibitem}\marg{key}\marg{value} +%\end{definition} +% Adds a new database entry with the given key and value. +%\changes{1.03}{2009 January 27}{removed check if database exists} % \begin{macrocode} - \@dtl@sortcriteria{\@dtl@rowa}{\@dtl@rowb}% +\newcommand*{\DTLnewbibitem}[2]{% + \@DTLnewdbentry{\DTLBIBdbname}{#1}{#2}} % \end{macrocode} -% If \cs{dtl@sortresult} is negative insert A before B. +%\end{macro} +%\section{Predefined text} +%\label{sec:src:bibnames} +%\begin{macro}{\andname} % \begin{macrocode} - \ifnum\dtl@sortresult<0\relax +\providecommand*{\andname}{and} % \end{macrocode} -% Insert row A into new list. First store \cs{@dtl@newlist} in -% \cs{toks@}. +%\end{macro} +%\begin{macro}{\ofname} % \begin{macrocode} - \toks@=\expandafter{\@dtl@newlist}% +\providecommand*{\ofname}{of} % \end{macrocode} -% Update \cs{@dtl@newlist} to be the old value followed by -% row A. +%\end{macro} +%\begin{macro}{\inname} % \begin{macrocode} - \edef\@dtl@newlist{% +\providecommand*{\inname}{in} % \end{macrocode} -% Old value: +%\end{macro} +%\begin{macro}{\etalname} % \begin{macrocode} - \the\toks@ +\providecommand*{\etalname}{et al.} % \end{macrocode} -% Format row A +%\end{macro} +%\begin{macro}{\editorname} % \begin{macrocode} - \noexpand\db@row@elt@w% - \noexpand\db@row@id@w \number\dtlrownum - \noexpand\db@row@id@end@% - \the\@dtl@rowa - \noexpand\db@row@id@w \number\dtlrownum - \noexpand\db@row@id@end@% - \noexpand\db@row@elt@end@% - }% +\providecommand*{\editorname}{editor} % \end{macrocode} -% Increment row number to compensate for inserted row. +%\end{macro} +%\begin{macro}{\editorsname} % \begin{macrocode} - \advance\dtlrownum by 1\relax +\providecommand*{\editorsname}{editors} % \end{macrocode} -% Mark insertion done. +%\end{macro} +%\begin{macro}{\volumename} % \begin{macrocode} - \@dtl@insertdonetrue - \fi - \fi +\providecommand*{\volumename}{volume} % \end{macrocode} -% Insert row B +%\end{macro} +%\begin{macro}{\numbername} % \begin{macrocode} - \toks@=\expandafter{\@dtl@newlist}% - \edef\@dtl@newlist{\the\toks@ +\providecommand*{\numbername}{number} % \end{macrocode} -% row B +%\end{macro} +%\begin{macro}{\pagesname} % \begin{macrocode} - \noexpand\db@row@elt@w% - \noexpand\db@row@id@w \number\dtlrownum - \noexpand\db@row@id@end@% - \the\@dtl@rowb - \noexpand\db@row@id@w \number\dtlrownum - \noexpand\db@row@id@end@% - \noexpand\db@row@elt@end@% - }% +\providecommand*{\pagesname}{pages} % \end{macrocode} -% Repeat loop. +%\end{macro} +%\begin{macro}{\pagename} % \begin{macrocode} - }\q@nil +\providecommand*{\pagename}{page} % \end{macrocode} -% If row A hasn't been inserted, do so now. +%\end{macro} +%\begin{macro}{\editionname} % \begin{macrocode} - \if@dtl@insertdone - \else +\providecommand*{\editionname}{edition} % \end{macrocode} -% \cs{dtlrownum} contains the index of the last row in new list, -% So increment it to get the new index for row A. +%\end{macro} +%\begin{macro}{\techreportname} % \begin{macrocode} - \advance\dtlrownum by 1\relax +\providecommand*{\techreportname}{Technical report} % \end{macrocode} -% Insert row A. +%\end{macro} +%\begin{macro}{\mscthesisname} % \begin{macrocode} - \toks@=\expandafter{\@dtl@newlist}% - \edef\@dtl@newlist{\the\toks@ +\providecommand*{\mscthesisname}{Master's thesis} % \end{macrocode} -% row A +%\end{macro} +%\begin{macro}{\phdthesisname} % \begin{macrocode} - \noexpand\db@row@elt@w% - \noexpand\db@row@id@w \number\dtlrownum - \noexpand\db@row@id@end@% - \the\@dtl@rowa - \noexpand\db@row@id@w \number\dtlrownum - \noexpand\db@row@id@end@% - \noexpand\db@row@elt@end@% - }% - \fi +\providecommand*{\phdthesisname}{PhD thesis} % \end{macrocode} -% Set sorted list to new list. +%\end{macro} +% +% +%\section{Displaying the bibliography} +%\label{sec:src:displaybib} +%\begin{definition} +%\cs{DTLbibliography}\marg{bib dbname} +%\end{definition} +% Displays the bibliography for the database \meta{bib dbname} +% which must have previously been loaded using +% \cs{DTLloadbbl}. +%\begin{macro}{\DTLbibliography} % \begin{macrocode} - \let\@dtl@sortedlist=\@dtl@newlist +\newcommand*{\DTLbibliography}[2][\boolean{true}]{% + \begin{DTLthebibliography}[#1]{#2}% + \DTLforeachbibentry[#1]{#2}{% + \DTLbibitem \DTLformatbibentry \DTLendbibitem }% -% \end{macrocode} -% Update database. -% \begin{macrocode} - \expandafter\global\csname dtldb@#1\endcsname=\expandafter - {\@dtl@sortedlist}% + \end{DTLthebibliography}% } % \end{macrocode} %\end{macro} % -%\begin{macro}{\@dtl@sortcriteria} +%\begin{macro}{\DTLformatbibentry} %\begin{definition} -% \cs{@dtl@sortcriteria}\marg{row a toks}\marg{row b toks} +%\cs{DTLformatbibentry} %\end{definition} -% \cs{@dtl@dbname} and \cs{@dtl@sortorder} must be set before use -% \cs{@dtl@sortorder} is a comma separated list of either just keys -% or \meta{key}=\meta{direction}. -% (Check keys are valid before use.) -%\changes{2.0}{2009 February 27}{updated to take account of new -% database structure} +% Formats the current bib entry. % \begin{macrocode} -\newcommand{\@dtl@sortcriteria}[2]{% +\newcommand*{\DTLformatbibentry}{% % \end{macrocode} -% Iterate through the sort order. +% Check format for this type is defined. % \begin{macrocode} - \@for\@dtl@level:=\@dtl@sortorder\do{% + \@ifundefined{DTLformat\DBIBentrytype}% + {% + \PackageError{databib}{Don't know how to format bibliography + entries of type `\DBIBentrytype'}{}% + }% + {% % \end{macrocode} -% Set \cs{@dtl@sortdirection} to $-1$ (ascending) or $+1$ -% (descending). Key is stored in \cs{@dtl@key}. +% Print information to terminal and log file if in verbose mode. % \begin{macrocode} - \expandafter\@dtl@getsortdirection\@dtl@level=\relax + \dtl@message{[\DBIBcitekey]}% % \end{macrocode} -% Initially comparing on the same key +% Initialise % \begin{macrocode} - \let\@dtl@keya=\@dtl@key - \let\@dtl@keyb=\@dtl@key + \DTLstartsentencefalse\DTLmidsentencefalse\DTLperiodfalse % \end{macrocode} -% Get values corresponding to key from both rows. -% First get column index corresponding to key. +% Format this entry % \begin{macrocode} - \@sdtl@getcolumnindex{\@dtl@col}{\@dtl@dbname}{\@dtl@key}% + \csname DTLformat\DBIBentrytype\endcsname + }% +} % \end{macrocode} -% Get entry for this column from row A and store in \cs{@dtl@a}. +%\end{macro} +%\begin{macro}{\DTLendbibitem} +% Hook to add extra information at the end of a bibliography item. +% This does nothing by default. % \begin{macrocode} - \dtlgetentryfromrow{\@dtl@a}{\@dtl@col}{#1}% +\newcommand*{\DTLendbibitem}{} % \end{macrocode} -% Get entry for this column from row B and store in \cs{@dtl@b}. +%\end{macro} +% +%\begin{macro}{\DTLwidest} +%Define a length to store the widest bib entry label % \begin{macrocode} - \dtlgetentryfromrow{\@dtl@b}{\@dtl@col}{#2}% +\newlength\dtl@widest % \end{macrocode} -% Has value from row A been defined? +%\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} - \ifx\@dtl@a\dtlnovalue +\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} -% Value hasn't been defined so set to null +%\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} - \@dtl@setnull{\@dtl@a}{\@dtl@key}% - \fi +\newcommand*{\DTLforeachbibentry}{% +\@ifstar\@DTLforeachbibentry\@DTLforeachbibentry} % \end{macrocode} -% Has value from row B been defined? +%\end{macro} +%\begin{macro}{\@DTLforeachbibentry} +% Unstarred version % \begin{macrocode} - \ifx\@dtl@b\dtlnovalue +\newcommand*{\@DTLforeachbibentry}[3][\boolean{true}]{% % \end{macrocode} -% Value hasn't been defined so set to null +% Store database name. % \begin{macrocode} - \@dtl@setnull{\@dtl@b}{\@dtl@key}% - \fi + \edef\DBIBname{#2}% % \end{macrocode} -% Check if value for row A is null. +% Reset row counter. % \begin{macrocode} - \DTLifnull{\@dtl@a}% - {% -% \end{macrocode} -% Value for row A is null, so find the first non null key in list of -% replacement keys. -% \begin{macrocode} - \@for\@dtl@keya:=\@dtl@replacementkeys\do{% -% \end{macrocode} -% Get column corresponding to this key. -% \begin{macrocode} - \@sdtl@getcolumnindex{\@dtl@col}{\@dtl@dbname}{\@dtl@keya}% - \dtlgetentryfromrow{\@dtl@a}{\@dtl@col}{#1}% -% \end{macrocode} -% Has value for row A been defined? -% \begin{macrocode} - \ifx\@dtl@a\dtlnovalue -% \end{macrocode} -% Value for row A hasn't been defined so set to null -% \begin{macrocode} - \@dtl@setnull{\@dtl@a}{\@dtl@key}% - \fi + \setcounter{DTLbibrow}{0}% % \end{macrocode} -% Is value for row A null? If not null end the loop. +% Iterate through the database. % \begin{macrocode} - \DTLifnull{\@dtl@a}{}{\@endfortrue}% - }% + \@DTLforeach{#2}{\DBIBcitekey=CiteKey,\DBIBentrytype=EntryType}% + {% + \dtl@gathervalues{#2}{\dtlcurrentrow}% + \ifthenelse{#1}{\refstepcounter{DTLbibrow}#3}{}% + }% +} % \end{macrocode} -% No non-null value found. +%\end{macro} +%\begin{macro}{\@sDTLforeachbibentry} +% Starred version % \begin{macrocode} - \ifx\@dtl@keya\@nnil - \let\@dtl@keya\@dtl@key - \@dtl@setnull{\@dtl@a}{\@dtl@key}% - \fi - }% - {}% +\newcommand*{\@sDTLforeachbibentry}[3][\boolean{true}]{% % \end{macrocode} -% Check if value for row B is null. +% Store database name. % \begin{macrocode} - \DTLifnull{\@dtl@b}% - {% + \edef\DBIBname{#2}% % \end{macrocode} -% Value for row B is null, so find the first non null key in list of -% replacement keys. +% Reset row counter. % \begin{macrocode} - \@for\@dtl@keyb:=\@dtl@replacementkeys\do{% + \setcounter{DTLbibrow}{0}% % \end{macrocode} -% Get column corresponding to this key. +% Iterate through the database (read only). % \begin{macrocode} - \@sdtl@getcolumnindex{\@dtl@col}{\@dtl@dbname}{\@dtl@keyb}% - \dtlgetentryfromrow{\@dtl@b}{\@dtl@col}{#2}% + \@sDTLforeach{#2}{\DBIBcitekey=CiteKey,\DBIBentrytype=EntryType}% + {% + \dtl@gathervalues{#2}{\dtlcurrentrow}% + \ifthenelse{#1}{\refstepcounter{DTLbibrow}#3}{}% + }% +} % \end{macrocode} -% Has value for row B been defined? +%\end{macro} +% +%\begin{counter}{DTLbibrow} +%The counter \ctrfmt{DTLbibrow} keeps track of the current +%row in the body of \cs{DTLforeachbibentry}. (You can't rely on +%\ctr{DTLrowi}, \ctr{DTLrowii} and +% \ctr{DTLrowiii}, as \cs{DTLforeachbibentry} pass the +% conditions to the optional argument of \cs{DTLforeach}, but +% instead uses \cs{ifthenelse}, which means that \ctr{DTLrowi} +% etc will be incremented, even when the given condition is not met.) % \begin{macrocode} - \ifx\@dtl@b\dtlnovalue +\newcounter{DTLbibrow} % \end{macrocode} -% Value for row B hasn't been defined so set to null. +%\end{counter} +%\begin{macro}{\theHDTLbibrow} +% Keep \sty{hyperref} happy: % \begin{macrocode} - \@dtl@setnull{\@dtl@b}{\@dtl@key}% - \fi +\def\theHDTLbibrow{\theHDTLrow.bib.\arabic{DTLbibrow}}% % \end{macrocode} -% Is value for row B null? If not null end the loop. +%\end{macro} +% +%\begin{macro}{\DTLbibfield} +%\begin{definition} +%\cs{DTLbibfield}\marg{field name} +%\end{definition} +% Gets the value assigned to the field \meta{field name} for +% the current row of \cs{DTLforeachbibentry}. (Doesn't check if +% the field exists, or if it is being used within +% \cs{DTLforeachbibentry}.) % \begin{macrocode} - \DTLifnull{\@dtl@b}{}{\@endfortrue}% - }% +\newcommand*{\DTLbibfield}[1]{\csname @dtl@key@#1\endcsname} % \end{macrocode} -% No non-null value found. +%\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} - \ifx\@dtl@keyb\@nnil - \let\@dtl@keyb\@dtl@key - \@dtl@setnull{\@dtl@b}{\@dtl@key}% - \fi - }% - {}% +\newcommand*{\DTLifbibfieldexists}[3]{% +\@ifundefined{@dtl@key@#1}{#3}{% +\expandafter\DTLifnull\csname @dtl@key@#1\endcsname +{#3}{#2}}} % \end{macrocode} -% Compare rows A and B. First store the values for row A and B -% in token registers so that they can be passed to -% \cs{dtl@compare@}. +%\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} - \@dtl@toksA=\expandafter{\@dtl@a}% - \@dtl@toksB=\expandafter{\@dtl@b}% +\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} -% Do comparison. +%\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} - \edef\@dtl@docompare{\noexpand\dtl@compare@ - {\@dtl@keya}{\@dtl@keyb}% - {\noexpand\@dtl@toksA}{\noexpand\@dtl@toksB}}% - \@dtl@docompare +\newif\ifDTLperiod % \end{macrocode} -% Repeat if the two values are considered identical and there -% are further sorting options. +%\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} - \ifnum\dtl@sortresult=0\relax +\newcommand*{\DTLcheckendsperiod}[1]{% +\dtl@checkendsperiod#1\@nil\relax} % \end{macrocode} -% Reset switch to prevent breaking out of outer loop. % \begin{macrocode} - \@endforfalse +\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 -% \end{macrocode} -% Break out of loop. -% \begin{macrocode} - \@endfortrue + \global\DTLperiodfalse \fi - }% + \let\@dtl@donext=\@gobble + \else + \let\@dtl@donext=\dtl@checkendsperiod + \fi +\fi +\@dtl@donext{#2}% +} % \end{macrocode} -% Apply sort direction -%\changes{2.01}{2009 March 27}{fixed sort direction} +%\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} - \multiply\dtl@sortresult by -\@dtl@sortdirection\relax -} +\newcommand*{\DTLcheckbibfieldendsperiod}[1]{% +\protected@edef\@dtl@tmp{\DTLbibfield{#1}}% +\expandafter\DTLcheckendsperiod\expandafter{\@dtl@tmp}} % \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{macro}{\ifDTLmidsentence} +%\begin{definition} +%\cs{ifDTLmidsentence} +%\end{definition} +% Determine whether we are in the middle +% of a sentence. % \begin{macrocode} -\def\@dtl@getsortdirection#1=#2\relax{% +\newif\ifDTLmidsentence % \end{macrocode} -% Store key in \cs{@dtl@key}. +%\end{macro} +%\begin{macro}{\ifDTLstartsentence} +%\begin{definition} +%\cs{ifDTLstartsentence} +%\end{definition} +% Determine whether we are at the start +% of a sentence. % \begin{macrocode} - \def\@dtl@key{#1}% +\newif\ifDTLstartsentence % \end{macrocode} -% Store sort direction. This will be empty if no direction was -% specified. +%\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} - \def\@dtl@sortdirection{#2}% +\newcommand*{\DTLaddperiod}{\DTLmidsentencefalse\DTLperiodfalse +\DTLstartsentencetrue +\ifDTLperiod\else.\fi} % \end{macrocode} -% Check if a direction was specified. +%\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} - \ifx\@dtl@sortdirection\@empty +\newcommand*{\DTLaddcomma}{, \DTLmidsentencetrue +\DTLperiodfalse\DTLstartsentencefalse} % \end{macrocode} -% No direction specified so assume ascending. -% \begin{macrocode} - \def\@dtl@sortdirection{-1}% - \else +%\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} -% Get the sort direction from the second argument (needs terminating -% equal sign removed) and store in \cs{@dtl@sortdirection}. +%\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} - \@dtl@get@sortdirection#2% +\newcommand*{\DTLandlast}{, \andname\ } % \end{macrocode} -% Determine the direction. -% \changes{2.0}{2009 February 27}{modified to use \cs{ifx} instead -% of \cs{ifthenelse}} +%\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} - \def\@dtl@dir{ascending}% - \ifx\@dtl@sortdirection\@dtl@dir +\newcommand*{\DTLandnotlast}{, } % \end{macrocode} -% Ascending +%\end{macro} +%\begin{macro}{\dtl@authorcount} +% Define a count register to keep track of the number of authors: % \begin{macrocode} - \def\@dtl@sortdirection{-1}% - \else +\newcount\@dtl@authorcount % \end{macrocode} -% Check if descending. +%\end{macro} +%\begin{counter}{DTLmaxauthors} +% The counter \ctrfmt{DTLmaxauthors} indicates the maximum number of +% author names to display, if there are more than that number, +% \cs{etalname} is used. % \begin{macrocode} - \def\@dtl@dir{descending}% - \ifx\@dtl@sortdirection\@dtl@dir +\newcounter{DTLmaxauthors} +\setcounter{DTLmaxauthors}{10} % \end{macrocode} -% Descending +%\end{counter} +%\begin{macro}{\DTLformatauthorlist} +% Format a list of author names (the list is stored in +% \cs{@dtl@key@Author}): % \begin{macrocode} - \def\@dtl@sortdirection{1}% +\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} -% Direction not valid. Generate error message. +%\end{macro} +%\begin{counter}{DTLmaxeditors} +% The counter \ctrfmt{DTLmaxeditors} indicates the maximum number of +% editor names to display, if there are more than that number, +% \cs{etalname} is used. % \begin{macrocode} - \PackageError{datatool}{Invalid sort direction - `\@dtl@sortdirection'}{The sort direction can only be - one of `ascending' or `descending'}% +\newcounter{DTLmaxeditors} +\setcounter{DTLmaxeditors}{10} % \end{macrocode} -% Assume ascending. +%\end{counter} +% +%\begin{macro}{\DTLformateditorlist} +% Format a list of editor names (the list is stored in +% \cs{@dtl@key@Editor}): % \begin{macrocode} - \def\@dtl@sortdirection{-1} +\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}{\@dtl@get@sortdirection} -% Get direction (trims trailing = sign) +%\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} -\def\@dtl@get@sortdirection#1={\def\@dtl@sortdirection{#1}} +\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}{\@dtl@toksA} +%\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} -\newtoks\@dtl@toksA +\newcommand*{\DTLformatforenames}[1]{% +\DTLstartsentencespace +#1% +\DTLcheckendsperiod{#1}} % \end{macrocode} %\end{macro} -%\begin{macro}{\@dtl@toksB} -% \begin{macrocode} -\newtoks\@dtl@toksB -% \end{macrocode} -%\end{macro} -%\begin{macro}{\@dtl@toks} +% +%\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} -\newtoks\@dtl@toks +\newcommand*{\DTLformatabbrvforenames}[1]{% +\DTLstartsentencespace +\DTLstoreinitials{#1}{\@dtl@tmp}\@dtl@tmp +\expandafter\DTLcheckendsperiod\expandafter{\@dtl@tmp}} % \end{macrocode} %\end{macro} % -%\begin{macro}{\dtl@compare} +%\begin{macro}{\DTLformatvon} %\begin{definition} -%\cs{dtl@compare}\marg{key}\marg{a toks}\marg{b toks} +%\cs{DTLformatvon}\marg{von part} %\end{definition} -% Compares two values according to \meta{key} of database given by -% \cs{@dtl@dbname}. Sets \cs{dtl@sortresult}. \cs{@dtl@comparecs} -% must be set to the required comparison macro. -%\changes{2.0}{2009 February 27}{no longer used} +% 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{\dtl@compare}[3]{% - \dtl@compare@{#1}{#1}{#2}{#3}% +\newcommand*{\DTLformatvon}[1]{% +\DTLstartsentencespace +\def\@dtl@tmp{#1}% +\ifx\@dtl@tmp\@empty +\else + #1~% +\fi } % \end{macrocode} %\end{macro} % -%\begin{macro}{\dtl@compare@} +%\begin{macro}{\DTLformatsurname} %\begin{definition} -% \cs{dtl@compare@}\marg{keyA}\marg{keyB}\marg{A toks}\marg{B toks} +%\cs{DTLformatsurname}\marg{surname} %\end{definition} -% Compare \meta{A} and \meta{B} according \meta{keyA} and -% \meta{keyB} for database given by \cs{@dtl@dbname}. Sets -% \cs{dtl@sortresult}. -% \cs{@dtl@comparecs} must be set before use. -%\changes{2.0}{2009 February 27}{updated to use new database -% structure} -% \begin{macrocode} -\newcommand{\dtl@compare@}[4]{% -% \end{macrocode} -% Get the data type for first key and store in \cs{@dtl@typeA}. -% \begin{macrocode} - \DTLgetdatatype{\@dtl@typeA}{\@dtl@dbname}{#1}% -% \end{macrocode} -% Is it unset? If so, assume string -% \begin{macrocode} - \ifx\@dtl@typeA\DTLunsettype - \let\@dtl@typeA\DTLstringtype - \fi -% \end{macrocode} -% Get the data type for the second key and store in \cs{@dtl@typeB} -% \begin{macrocode} - \DTLgetdatatype{\@dtl@typeB}{\@dtl@dbname}{#2}% -% \end{macrocode} -% Is it unset? If so, assume string -% \begin{macrocode} - \ifx\@dtl@typeB\DTLunsettype - \let\@dtl@typeB\DTLstringtype - \fi -% \end{macrocode} -% Multiply the two values together +% The format of an author/editor's surname. % \begin{macrocode} - \@dtl@tmpcount=\@dtl@typeA\relax - \multiply\@dtl@tmpcount by \@dtl@typeB\relax +\newcommand*{\DTLformatsurname}[1]{% +\DTLstartsentencespace +#1\DTLcheckendsperiod{#1}} % \end{macrocode} -% If either type is 0 (a string) then the product will also be -% 0 (string) otherwise it will be one of the numerical types. +%\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} - \ifnum\@dtl@tmpcount=0\relax +\newcommand*{\DTLformatjr}[1]{% +\DTLstartsentencespace +\def\@dtl@tmp{#1}% +\ifx\@dtl@tmp\@empty +\else + , #1\DTLcheckendsperiod{#1}% +\fi +} % \end{macrocode} -% A string, so use comparison function +%\end{macro} +% +%\begin{macro}{\DTLformatcrossrefeditor} +% Format cross reference editors: % \begin{macrocode} - \edef\@dtl@tmpcmp{% - \noexpand\@dtl@comparecs{\noexpand\dtl@sortresult}% - {\the#3}{\the#4}% - }% - \@dtl@tmpcmp - \ifdtlverbose - \edef\@dtl@a{\the#3}% - \edef\@dtl@b{\the#4}% - \fi +\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 -% \end{macrocode} -% Store the first value -% \begin{macrocode} - \edef\@dtl@a{\the#3}% -% \end{macrocode} -% Store the second value -% \begin{macrocode} - \edef\@dtl@b{\the#4}% -% \end{macrocode} -% Compare -% \begin{macrocode} - \DTLifnumlt{\@dtl@a}{\@dtl@b}% - {% -% \end{macrocode} -% $A < B$ -% \begin{macrocode} - \dtl@sortresult=-1\relax - }% - {% - \DTLifnumgt{\@dtl@a}{\@dtl@b}% - {% -% \end{macrocode} -% $A > B$ -% \begin{macrocode} - \dtl@sortresult=1\relax - }% - {% -% \end{macrocode} -% $A = B$ -% \begin{macrocode} - \dtl@sortresult=0\relax - }% - }% + \ifnum\@dtl@authorcount=2\relax + \ \andname\ \expandafter\DTLformatsurnameonly\@dtl@author + \else + \ \etalname + \expandafter\DTLcheckendsperiod\expandafter{\etalname} + \fi + \@endfortrue \fi +\fi +}}% +}{}% +} % \end{macrocode} -% Write comparison result to terminal/log if verbose mode. +%\end{macro} +% +%\begin{macro}{\DTLformatvolnumpages} +% Format volume, number and pages (of an article). % \begin{macrocode} - \ifdtlverbose - \@onelevel@sanitize\@dtl@a - \@onelevel@sanitize\@dtl@b - \dtl@message{`\@dtl@a' <=> `\@dtl@b' = \number\dtl@sortresult}% - \fi +\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} % -%\subsection{Saving a database to an external file} -% -%\begin{macro}{\@dtl@write} +%\begin{macro}{\DTLformatbvolume} +% Format book volume. % \begin{macrocode} -\newwrite\@dtl@write +\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}{\DTLsavedb} -%\begin{definition} -% \cs{DTLsavedb}\marg{db name}\marg{filename} -%\end{definition} -% Save a database as an ASCII data file using the separator -% and delimiter given by \cs{@dtl@separator} and \cs{@dtl@delimiter}. -%\changes{2.0}{2009 February 27}{updated to use new database structure} +% +%\begin{macro}{\DTLformatchapterpages} +% Format chapter and pages: % \begin{macrocode} -\newcommand*{\DTLsavedb}[2]{% - \DTLifdbexists{#1}% - {% +\newcommand*{\DTLformatchapterpages}{% +\DTLifbibfieldexists{Chapter}{% +\DTLifbibfieldexists{Type}{% +\DTLstartsentencespace +\DTLbibfield{Type}}{% +\DTLstartsentencespace +\chaptername}~\DTLbibfield{Chapter}% +\DTLifbibfieldexists{Pages}{\DTLaddcomma}{% +\DTLcheckbibfieldendsperiod{Chapter}}}{}% +\DTLstartsentencespace +\DTLformatpages} % \end{macrocode} -% Open output file -%\changes{2.02}{2009 July 13}{Fixed bug that didn't set the filename} +%\end{macro} +% +%\begin{macro}{\DTLformatpages} +% Format pages: % \begin{macrocode} - \openout\@dtl@write=#2\relax +\newcommand*{\DTLformatpages}{% +\DTLifbibfieldexists{Pages}{% +\DTLstartsentencespace +\protected@edef\@dtl@pages{0\DTLbibfield{Pages}}% +\DTLifnumerical{\@dtl@pages}{\pagename}{\pagesname}~% +\DTLbibfield{Pages}\DTLcheckbibfieldendsperiod{Pages}}{}% +} % \end{macrocode} -% Initialise header row +%\end{macro} +% +%\begin{macro}{\DTLformatnumberseries} +% Format number and series (of book) % \begin{macrocode} - \def\@dtl@header{}% +\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} -% Construct the header row +%\end{macro} +%\begin{macro}{\DTLformatbookcrossref} +% Format a book cross reference. % \begin{macrocode} - \dtlforeachkey(\@dtl@key,\@dtl@col,\@dtl@type,\@dtl@head)% - \in{#1}\do - {% - \IfSubStringInString{\@dtl@separator}{\@dtl@key}% - {% - \ifx\@dtl@header\@empty - \protected@edef\@dtl@header{% - \@dtl@delimiter\@dtl@key\@dtl@delimiter}% - \else - \toks@=\expandafter{\@dtl@header}% - \protected@edef\@dtl@header{% - \the\toks@\@dtl@separator - \@dtl@delimiter\@dtl@key\@dtl@delimiter}% - \fi - }% - {% - \ifx\@dtl@header\@empty - \protected@edef\@dtl@header{\@dtl@key}% - \else - \toks@=\expandafter{\@dtl@header}% - \protected@edef\@dtl@header{\the\toks@ - \@dtl@separator\@dtl@key}% - \fi - }% - }% -% \end{macrocode} -% Print header -% \begin{macrocode} - \protected@write\@dtl@write{}{\@dtl@header}% -% \end{macrocode} -% Iterate through each row -% \begin{macrocode} - \@sDTLforeach{#1}{}% - {% +\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} -% Initialise row +%\end{macro} +%\begin{macro}{\DTLformatincollproccrossref} +% Format `incollections' cross reference. % \begin{macrocode} - \def\@dtl@row{}% +\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} -% Iterate through each key +%\end{macro} +% +%\begin{macro}{\DTLformatinedbooktitle} +%Format editor and booktitle: % \begin{macrocode} - \DTLforeachkeyinrow{\@dtl@val}% - {% - \IfSubStringInString{\@dtl@separator}{\@dtl@val}% - {% - \ifx\@dtl@row\@empty - \protected@edef\@dtl@row{% - \@dtl@delimiter\@dtl@val\@dtl@delimiter}% - \else - \toks@=\expandafter{\@dtl@row}% - \protected@edef\@dtl@row{\the\toks@\@dtl@separator - \@dtl@delimiter\@dtl@val\@dtl@delimiter}% - \fi - }% - {% - \ifx\@dtl@row\@empty - \protected@edef\@dtl@row{\@dtl@val}% - \else - \toks@=\expandafter{\@dtl@row}% - \protected@edef\@dtl@row{\the\toks@\@dtl@separator - \@dtl@val}% - \fi - }% - }% +\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} -% Print row\changes{2.03}{2009 November 15}{Moved outside loop} +%\end{macro} +% +%\begin{macro}{\DTLformatdate} +%Format date. % \begin{macrocode} - \protected@write\@dtl@write{}{\@dtl@row}% - }% +\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} -% Close output file +%\end{macro} +%\begin{macro}{\DTLformatarticlecrossref} +% Format article cross reference. % \begin{macrocode} - \closeout\@dtl@write - }% - {% - \PackageError{datatool}{Can't save database `#1': no such - database}{}% - }% +\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} % -%\begin{macro}{\DTLsavetexdb} +%\subsection{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{DTLsavetexdb}\marg{db name}\marg{filename} +%\cs{DTLbibfieldexists}\marg{field label} %\end{definition} -% Save a database as a \LaTeX\ file. -%\changes{2.0}{2009 February 27}{updated to use new database structure} -% \begin{macrocode} -\newcommand*{\DTLsavetexdb}[2]{% - \DTLifdbexists{#1}% - {% -% \end{macrocode} -% Open output file +% Checks if named bib field exists for current entry % \begin{macrocode} - \openout\@dtl@write=#2\relax +\newcommand*{\DTLbibfieldexists}[1]{% +\TE@throw\noexpand\dtl@testbibfieldexists{#1}% +\noexpand\if@dtl@condition} % \end{macrocode} -% Write new data base definition +%\end{macro} +%\begin{macro}{\dtl@testbibfieldexists} % \begin{macrocode} - \protected@write\@dtl@write{}{\string\DTLnewdb{#1}}% +\newcommand*{\dtl@testbibfieldexists}[1]{% +\DTLifbibfieldexists{#1}{\@dtl@conditiontrue}{\@dtl@conditionfalse}} % \end{macrocode} -% Iterate through each row +%\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} - \@sDTLforeach{#1}{}% - {% +\newcommand*{\DTLbibfieldiseq}[2]{% +\TE@throw\noexpand\dtl@testbibfieldiseq{#1}{#2}% +\noexpand\if@dtl@condition} % \end{macrocode} -% Start new row +%\end{macro} +%\begin{macro}{\dtl@testbibfieldiseq} % \begin{macrocode} - \protected@write\@dtl@write{}{\string\DTLnewrow*{#1}}% +\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} -% Iterate through each column +%\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} - \DTLforeachkeyinrow{\@dtl@val}% - {% +\newcommand*{\DTLbibfieldislt}[2]{% +\TE@throw\noexpand\dtl@testbibfieldislt{#1}{#2}% +\noexpand\if@dtl@condition} % \end{macrocode} -% Is this entry null? +%\end{macro} +%\begin{macro}{\dtl@testbibfieldislt} % \begin{macrocode} - \DTLifnull{\@dtl@val}% - {\def\@dtl@val{}}% - {}% -% \end{macrocode} -% Add entry -% \begin{macrocode} - \protected@write\@dtl@write{}{% - \string\DTLnewdbentry*{#1}{\dtlkey}{\@dtl@val}}% - }% - }% -% \end{macrocode} -% Save the column headers. -% \begin{macrocode} - \dtlforeachkey(\@dtl@k,\@dtl@c,\@dtl@t,\@dtl@h)\in{#1}\do - {% - \@onelevel@sanitize\@dtl@h - \protected@write\@dtl@write{}{% - \string\DTLsetheader*{#1}{\@dtl@k}{\@dtl@h}}% - }% -% \end{macrocode} -% Close output file -% \begin{macrocode} - \closeout\@dtl@write - }% - {% - \PackageError{datatool}{Can't save database `#1': no such - database}{}% - }% +\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} % -%\subsection{Loading a database from an external file} -% -% \begin{macrocode} -\newcommand{\@longempty}{} -% \end{macrocode} -%\begin{macro}{\@dtl@read} +%\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} -\newread\@dtl@read +\newcommand*{\DTLbibfieldisle}[2]{% +\TE@throw\noexpand\dtl@testbibfieldisle{#1}{#2}% +\noexpand\if@dtl@condition} % \end{macrocode} %\end{macro} -%\begin{macro}{\dtl@entrycr} -% Keep track of current column in data file +%\begin{macro}{\dtl@testbibfieldisle} % \begin{macrocode} -\newcount\dtl@entrycr +\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}{\ifdtlnoheader} -% The "noheader" option indicates that the file doesn't have a -% header row. +%\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} -\define@boolkey{loaddb}[dtl]{noheader}[true]{} +\newcommand*{\DTLbibfieldisgt}[2]{% +\TE@throw\noexpand\dtl@testbibfieldisgt{#1}{#2}% +\noexpand\if@dtl@condition} % \end{macrocode} %\end{macro} -% The "keys" option specifies the list of keys in the same order -% as the columns in the data file. -% Each key is stored in \cs{@dtl@inky@}\meta{n} where \meta{n} is the -% roman numeral representation of the current column. -% \begin{macrocode} -\define@key{loaddb}{keys}{% - \dtl@entrycr=0\relax - \@for\@dtl@key:=#1\do - {% - \advance\dtl@entrycr by 1\relax - \expandafter - \edef\csname @dtl@inky@\romannumeral\dtl@entrycr\endcsname{% - \@dtl@key}% - }% -} -% \end{macrocode} -% The "headers" option specifies the list of headers in the -% same order as the columns in the data file. +%\begin{macro}{\dtl@testbibfieldisgt} % \begin{macrocode} -\define@key{loaddb}{headers}{% - \dtl@entrycr=0\relax - \@for\@dtl@head:=#1\do - {% - \advance\dtl@entrycr by 1\relax - \toks@=\expandafter{\@dtl@head}% - \expandafter - \edef\csname @dtl@inhd@\romannumeral\dtl@entrycr\endcsname{% - \the\toks@}% - }% +\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} -% -%\begin{macro}{\dtldefaultkey} -% Default key to use if none specified (column index will be -% appended). -% \begin{macrocode} -\newcommand*{\dtldefaultkey}{Column} -% \end{macrocode} %\end{macro} % -%\begin{macro}{\@dtl@readline} +%\begin{macro}{\DTLbibfieldisge} %\begin{definition} -%\cs{@dtl@readline}\marg{file reg}\marg{cs} +%\cs{DTLbibfieldisge}\marg{field label}\marg{value} %\end{definition} -% Reads line from \meta{file reg}, trims end of line character -% and stores in \meta{cs}. -% \begin{macrocode} -\newcommand*{\@dtl@readline}[2]{% -% Read a line from "#1" and store in "#2" +% 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} - \read#1 to #2% +\newcommand*{\DTLbibfieldisge}[2]{% +\TE@throw\noexpand\dtl@testbibfieldisge{#1}{#2}% +\noexpand\if@dtl@condition} % \end{macrocode} -% Trim the end of line character +%\end{macro} +%\begin{macro}{\dtl@testbibfieldisge} % \begin{macrocode} - \dtl@trim#2% +\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}{\@dtl@readrawline} +%\begin{macro}{\DTLbibfieldcontains} %\begin{definition} -%\cs{@dtl@readrawline}\marg{file register}\marg{cs} +%\cs{DTLbibfieldcontains}\marg{field label}\marg{sub string} %\end{definition} -% Reads line from \meta{file register}, trims end of line character, -% applies mappings and stores in \meta{cs}. -% \begin{macrocode} -\newcommand*{\@dtl@readrawline}[2]{% -% Read a line from "#1" and store in "#2" -% \begin{macrocode} - \@dtl@rawread#1 to #2% -% \end{macrocode} -% Trim the end of line character -% \begin{macrocode} - \dtl@trim#2% -% \end{macrocode} -% Apply mappings +% 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} - \dtl@domappings\@dtl@line -} +\newcommand*{\DTLbibfieldcontains}[2]{% +\TE@throw\noexpand\dtl@testbibfieldcontains{#1}{#2}% +\noexpand\if@dtl@condition} % \end{macrocode} %\end{macro} - -%\begin{macro}{\DTLloaddb} -%\begin{definition} -% \cs{DTLloaddb}\oarg{options}\marg{db name}\marg{filename} -%\end{definition} -% Creates a new database called \meta{db name}, and loads the data -% in \meta{filename} into it. The separator and delimiter used in -% the file must match \cs{@dtl@separator} and \cs{@dtl@delimiter}. -% The optional argument is a comma-separated list. -%\changes{2.0}{2009 February 27}{removed checks to see if the -% database exists when adding to it} -%\changes{2.0}{2009 February 27}{added optional argument} +%\begin{macro}{\dtl@testbibfieldcontains} % \begin{macrocode} -\newcommand*{\DTLloaddb}{% - \let\@dtl@doreadline\@dtl@readline - \@dtlloaddb -} +\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} % -%\begin{macro}{\@dtlloaddb} -% Loads database using \cs{@dtl@doreadline} to read and trim -% line from file. (\cs{@dtl@doreadline} must be set before use.) +%\section{Bibliography Style Macros} +%\label{sec:src:bibstyle} +% The macros defined in this section should be redefined by +% bibliography styles. +% +%\begin{environment}{DTLthebibliography} +% How to format the entire bibliography: % \begin{macrocode} -\newcommand*{\@dtlloaddb}[3][]{% +\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} -% Check if file exists +%\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} - \IfFileExists{#3}{% +\newcommand*{\DTLmonthname}[1]{% +\dtl@monthname{#1}} % \end{macrocode} -% File exists. Locally change catcode of double quote character in -% case it has been made active. +%\end{macro} +%\begin{macro}{\dtl@monthname} +% Full month names: % \begin{macrocode} - \begingroup - \catcode`\"12\relax +\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} -% Initialise default options +%\end{macro} +%\begin{macro}{\dtl@abbrvmonthname} +% Abbreviated months: % \begin{macrocode} - \dtlnoheaderfalse +\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} -% Get the options +%\end{macro} +% +%\begin{macro}{\DTLbibitem} +% Define how to start a new bibitem: % \begin{macrocode} - \setkeys{loaddb}{#1}% +\newcommand*{\DTLbibitem}{\bibitem{\DBIBcitekey}} % \end{macrocode} -% Open the file for reading. +%\end{macro} +% +%\begin{macro}{\DTLmbibitem} +% As \cs{DTLbibitem} but for \cs{DTLmbibliography} % \begin{macrocode} - \openin\@dtl@read=#3% - \dtl@message{Reading `#3'}% +\newcommand*{\DTLmbibitem}[1]{\bibitem{#1@\DBIBcitekey}} % \end{macrocode} -% Create the new database. +%\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} - \DTLnewdb{#2}% +\newcommand*{\DTLformatauthor}[4]{% +\DTLformatforenames{#4} +\DTLformatvon{#1}% +\DTLformatsurname{#2}% +\DTLformatjr{#3}} % \end{macrocode} -% Check if the file is empty. +%\end{macro} +% +%\begin{macro}{\DTLformateditor} +% The format of an editor's name. % \begin{macrocode} - \ifeof\@dtl@read +\newcommand*{\DTLformateditor}[4]{% +\DTLformatforenames{#4} +\DTLformatvon{#1}% +\DTLformatsurname{#2}% +\DTLformatjr{#3}} % \end{macrocode} -% File is empty, so just issue a warning. +%\end{macro} +% +%\begin{macro}{\DTLformatedition} +% The format of an edition: % \begin{macrocode} - \PackageWarning{datatool}{File `#3' has no data}% - \else +\newcommand*{\DTLformatedition}[1]{#1 \editionname} % \end{macrocode} -% Does the file have a header row? +%\end{macro} +% +%\begin{macro}{\DTLformatarticle} +% The format of an article: % \begin{macrocode} - \ifdtlnoheader - \else +\newcommand{\DTLformatarticle}{} % \end{macrocode} -% Remove initial blank rows +%\end{macro} +% +%\begin{macro}{\DTLformatbook} +% The format of a book: % \begin{macrocode} - \loop +\newcommand{\DTLformatbook}{} % \end{macrocode} -% Set repeat condition to false +%\end{macro} +% +%\begin{macro}{\DTLformatbooklet} +% The format of a booklet: % \begin{macrocode} - \@dtl@conditionfalse +\newcommand{\DTLformatbooklet}{} % \end{macrocode} -% Do nothing if reached the end of file +%\end{macro} +% +%\begin{macro}{\DTLformatinbook} +% The format of an ``inbook'' type: % \begin{macrocode} - \ifeof\@dtl@read - \else +\newcommand{\DTLformatinbook}{} % \end{macrocode} -% Read a line from the file and store in \cs{@dtl@line} +%\end{macro} +% +%\begin{macro}{\DTLformatincollection} +% The format of an ``incollection'' type: % \begin{macrocode} - \@dtl@doreadline\@dtl@read\@dtl@line +\newcommand{\DTLformatincollection}{} % \end{macrocode} -% If this is a blank row, set repeat condition to true +%\end{macro} +% +%\begin{macro}{\DTLformatinproceedings} +% The format of an ``inproceedings'' type: % \begin{macrocode} - \ifx\@dtl@line\@longempty - \@dtl@conditiontrue - \fi - \fi +\newcommand{\DTLformatinproceedings}{} % \end{macrocode} -% Repeat loop if necessary +%\end{macro} +% +%\begin{macro}{\DTLformatmanual} +% The format of a manual: % \begin{macrocode} - \if@dtl@condition - \repeat +\newcommand{\DTLformatmanual}{} % \end{macrocode} -% Parse the header row. Store the row as -% \meta{sep}\meta{row}\meta{sep} in \cs{@dtl@lin@}. +%\end{macro} +% +%\begin{macro}{\DTLformatmastersthesis} +% The format of a master's thesis: % \begin{macrocode} - \protected@edef\@dtl@lin@{% - \@dtl@separator\@dtl@line\@dtl@separator}% +\newcommand{\DTLformatmastersthesis}{} % \end{macrocode} -% Keep track of columns: +%\end{macro} +% +%\begin{macro}{\DTLformatmisc} +% The format of a miscellaneous entry: % \begin{macrocode} - \dtl@entrycr=0\relax +\newcommand{\DTLformatmisc}{} % \end{macrocode} -% Keep lopping off elements until the end of the row is reached. -% (That is, until \cs{@dtl@lin@} is \cs{@dtl@separator}.) -%\changes{2.0}{2009 February 27}{changed \cs{whiledo} to -% \cs{loop} to improve efficiency}% +%\end{macro} +% +%\begin{macro}{\DTLformatphdthesis} +% The format of a Ph.D. thesis: % \begin{macrocode} - \loop +\newcommand{\DTLformatphdthesis}{} % \end{macrocode} -% Lopoff the first element and store in \cs{@dtl@key} +%\end{macro} +% +%\begin{macro}{\DTLformatproceedings} +% The format of a proceedings: % \begin{macrocode} - \expandafter\@dtl@lopoff\@dtl@lin@\to\@dtl@lin@\@dtl@key +\newcommand{\DTLformatproceedings}{} % \end{macrocode} -% Increment column count. +%\end{macro} +% +%\begin{macro}{\DTLformattechreport} +% The format of a technical report: % \begin{macrocode} - \advance\dtl@entrycr by 1\relax +\newcommand{\DTLformattechreport}{} % \end{macrocode} -% Store key in \cs{@dtl@toks} +%\end{macro} +% +%\begin{macro}{\DTLformatunpublished} +% The format of an unpublished work: % \begin{macrocode} - \expandafter\@dtl@toks\expandafter{\@dtl@key}% +\newcommand{\DTLformatunpublished}{} % \end{macrocode} -% Store the key in \cs{@dtl@inky@}\meta{n} where \meta{n} is the -% roman numeral representation of the current column, unless -% already defined. +%\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} - \@ifundefined{@dtl@inky@\romannumeral\dtl@entrycr}% - {% - \expandafter - \edef\csname @dtl@inky@\romannumeral - \dtl@entrycr\endcsname{\the\@dtl@toks}% - }% - {% +\newcommand*{\DTLacmcs}{ACM Computing Surveys} % \end{macrocode} -% If key has been specified in "#1", then use the header found in the -% file, unless a header has also been specified in "#1" +%\end{macro} +% +%\begin{macro}{\DTLacta} % \begin{macrocode} - \@ifundefined{@dtl@inhd@\romannumeral\dtl@entrycr}% - {% - \expandafter - \edef\csname @dtl@inhd@\romannumeral - \dtl@entrycr\endcsname{\the\@dtl@toks}% - }% - {}% - }% +\newcommand*{\DTLacta}{Acta Informatica} % \end{macrocode} -% Check if the loop should be repeated +%\end{macro} +% +%\begin{macro}{\DTLcacm} % \begin{macrocode} - \ifx\@dtl@lin@\@dtl@separator - \@dtl@conditionfalse - \else - \@dtl@conditiontrue - \fi +\newcommand*{\DTLcacm}{Communications of the ACM} % \end{macrocode} -% Repeat loop if necessary. +%\end{macro} +% +%\begin{macro}{\DTLibmjrd} % \begin{macrocode} - \if@dtl@condition - \repeat +\newcommand*{\DTLibmjrd}{IBM Journal of Research and Development} % \end{macrocode} -% End if no header +%\end{macro} +% +%\begin{macro}{\DTLibmsj} % \begin{macrocode} - \fi +\newcommand*{\DTLibmsj}{IBM Systems Journal} % \end{macrocode} -% Now for the rest of the data. If the end of file has been -% reached, then only the header row is available or file is empty. +%\end{macro} +% +%\begin{macro}{\DTLieeese} % \begin{macrocode} - \ifeof\@dtl@read - \ifdtlnoheader - \PackageWarning{datatool}{No data in `#3'}% - \else - \PackageWarning{datatool}{Only header row found in `#3'}% - \fi - \else -% \end{macrocode} -% Iterate through the rest of the file. First set the repeat -% condition to true: -% \begin{macrocode} - \@dtl@conditiontrue - \loop -% \end{macrocode} -% Read in a line -% \begin{macrocode} - \@dtl@doreadline\@dtl@read\@dtl@line +\newcommand*{\DTLieeese}{IEEE Transactions on Software Engineering} % \end{macrocode} -% Check if the line is empty. -%\changes{2.0}{2009 February 27}{changed \cs{ifthenelse} to -%\cs{ifx} to improve efficiency} +%\end{macro} +% +%\begin{macro}{\DTLieeetc} % \begin{macrocode} - \ifx\@dtl@line\@longempty +\newcommand*{\DTLieeetc}{IEEE Transactions on Computers} % \end{macrocode} -% Do nothing if the row is empty. +%\end{macro} +% +%\begin{macro}{\DTLieeetcad} % \begin{macrocode} - \else +\newcommand*{\DTLieeetcad}{IEEE Transactions on Computer-Aided Design +of Integrated Circuits} % \end{macrocode} -% Add a new row to the database. (Don't need to check if the -% database exists, since it's just been created.) +%\end{macro} +% +%\begin{macro}{\DTLipl} % \begin{macrocode} - \@sDTLnewrow{#2}% +\newcommand*{\DTLipl}{Information Processing Letters} % \end{macrocode} -% Store the row as \meta{sep}\meta{row}\meta{sep} to make the -% lopping off easier +%\end{macro} +% +%\begin{macro}{\DTLjacm} % \begin{macrocode} - \expandafter\@dtl@toks\expandafter{\@dtl@line}% - \edef\@dtl@lin@{\@dtl@separator\the\@dtl@toks - \@dtl@separator}% +\newcommand*{\DTLjacm}{Journal of the ACM} % \end{macrocode} -% Reset the column counter. +%\end{macro} +% +%\begin{macro}{\DTLjcss} % \begin{macrocode} - \dtl@entrycr=0\relax +\newcommand*{\DTLjcss}{Journal of Computer and System Sciences} % \end{macrocode} -%\changes{2.0}{2009 February 27}{changed \cs{whiledo} to \cs{loop} -% to improve efficiency} -% Iterate through each element in the row. Needs to be grouped -% since we're already inside a loop. +%\end{macro} +% +%\begin{macro}{\DTLscp} % \begin{macrocode} - {% +\newcommand*{\DTLscp}{Science of Computer Programming} % \end{macrocode} -% Initialise repeat condition +%\end{macro} +% +%\begin{macro}{\DTLsicomp} % \begin{macrocode} - \@dtl@conditiontrue +\newcommand*{\DTLsicomp}{SIAM Journal on Computing} % \end{macrocode} -% Iterate through the list +%\end{macro} +% +%\begin{macro}{\DTLtocs} % \begin{macrocode} - \loop +\newcommand*{\DTLtocs}{ACM Transactions on Computer Systems} % \end{macrocode} -% lop off first element and store in \cs{@dtl@thisentry} +%\end{macro} +% +%\begin{macro}{\DTLtods} % \begin{macrocode} - \expandafter\@dtl@lopoff\@dtl@lin@\to - \@dtl@lin@\@dtl@thisentry +\newcommand*{\DTLtods}{ACM Transactions on Database Systems} % \end{macrocode} -% Increment the column count. +%\end{macro} +% +%\begin{macro}{\DTLtog} % \begin{macrocode} - \advance\dtl@entrycr by 1\relax +\newcommand*{\DTLtog}{ACM Transactions on Graphics} % \end{macrocode} -% Get the key for this column and store in \cs{@dtl@thiskey}. -% Use default value if not defined. +%\end{macro} +% +%\begin{macro}{\DTLtoms} % \begin{macrocode} - \@ifundefined{@dtl@inky@\romannumeral\dtl@entrycr}% - {% - \edef\@dtl@thiskey{\dtldefaultkey - \number\dtl@entrycr}% - \expandafter\let - \csname @dtl@inky@\romannumeral - \dtl@entrycr\endcsname\@dtl@thiskey - }% - {% - \edef\@dtl@thiskey{% - \csname @dtl@inky@\romannumeral - \dtl@entrycr\endcsname}% - }% +\newcommand*{\DTLtoms}{ACM Transactions on Mathematical Software} % \end{macrocode} -% Store this entry in \cs{@dtl@toks} +%\end{macro} +% +%\begin{macro}{\DTLtoois} % \begin{macrocode} - \expandafter\@dtl@toks\expandafter{\@dtl@thisentry}% +\newcommand*{\DTLtoois}{ACM Transactions on Office Information +Systems} % \end{macrocode} -% Add this entry to the database +%\end{macro} +% +%\begin{macro}{\DTLtoplas} % \begin{macrocode} - \edef\@do@dtlnewentry{\noexpand\@sDTLnewdbentry - {#2}{\@dtl@thiskey}{\the\@dtl@toks}}% - \@do@dtlnewentry +\newcommand*{\DTLtoplas}{ACM Transactions on Programming Languages +and Systems} % \end{macrocode} -% Check if loop should be terminated +%\end{macro} +% +%\begin{macro}{\DTLtcs} % \begin{macrocode} - \ifx\@dtl@lin@\@dtl@separator - \@dtl@conditionfalse - \fi +\newcommand*{\DTLtcs}{Theoretical Computer Science} % \end{macrocode} -% Repeat loop if necessary +%\end{macro} +% +%\section{Bibliography Styles} +% Each bibliography style is set by the command +% \cs{dtlbst@}\meta{style}, where \meta{style} is the name +% of the bibliography style. +% +%\begin{macro}{\dtlbst@plain} +% The `plain' style: % \begin{macrocode} - \if@dtl@condition - \repeat - }% +\newcommand{\dtlbst@plain}{% % \end{macrocode} -% End of parsing this row +% Set how to format the entire bibliography: % \begin{macrocode} - \fi +\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} -% If the end of file has been reached, set the repeat condition -% to false. +% Set how to start the bibliography entry: % \begin{macrocode} - \ifeof\@dtl@read \@dtl@conditionfalse\fi +\renewcommand*{\DTLbibitem}{\bibitem{\DBIBcitekey}}% +\renewcommand*{\DTLmbibitem}[1]{\bibitem{##1@\DBIBcitekey}}% % \end{macrocode} -% Repeat if necessary +% Sets the author name format. % \begin{macrocode} - \if@dtl@condition - \repeat - \fi +\renewcommand*{\DTLformatauthor}[4]{% +\DTLformatforenames{##4} +\DTLformatvon{##1}% +\DTLformatsurname{##2}% +\DTLformatjr{##3}} % \end{macrocode} -% End of first \cs{ifeof} +% Sets the editor name format. % \begin{macrocode} - \fi +\renewcommand*{\DTLformateditor}[4]{% +\DTLformatforenames{##4} +\DTLformatvon{##1}% +\DTLformatsurname{##2}% +\DTLformatjr{##3}} % \end{macrocode} -% Close the input file +% Sets the edition format. % \begin{macrocode} - \closein\@dtl@read +\renewcommand*{\DTLformatedition}[1]{##1 \editionname}% % \end{macrocode} -% Set the headers if required +% Sets the monthname format. % \begin{macrocode} - \edef\@dtl@maxcols{\expandafter - \number\csname dtlcols@#2\endcsname}% - \dtlgforint\dtl@entrycr=1\to\@dtl@maxcols\step1\do - {% - \@ifundefined{@dtl@inhd@\romannumeral\dtl@entrycr}% - {}% - {% - \expandafter\let\expandafter\@dtl@head - \csname @dtl@inhd@\romannumeral\dtl@entrycr\endcsname - \@dtl@toks=\expandafter{\@dtl@head}% - \edef\@dtl@dosetheader{\noexpand\@dtl@setheaderforindex - {#2}{\number\dtl@entrycr}{\the\@dtl@toks}}% - \@dtl@dosetheader - }% - }% +\let\DTLmonthname\dtl@monthname % \end{macrocode} -% End current scope +% Sets other predefined names: % \begin{macrocode} - \endgroup +\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} -% End true part of if file exists +% 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} -% Requested file not found on TeX's path +% The format of a book. % \begin{macrocode} - \PackageError{datatool}{Can't load database `#2' (file `#3' - doesn't exist)}{}% - }% -} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\dtl@trim} -%\begin{definition} -%\cs{dtl@trim}\marg{line} -%\end{definition} -% Trims the trailing space from \meta{line}. -% \begin{macrocode} -\newcommand{\dtl@trim}[1]{% -\def\@dtl@trmstr{}% -\expandafter\@dtl@starttrim#1\@nil% -\let#1=\@dtl@trmstr -} -% \end{macrocode} -%\end{macro} -%\begin{macro}{\@dtl@starttrim} -% Start trimming -% \begin{macrocode} -\long\def\@dtl@starttrim#1#2{% -\ifx\par#1% - \def\@dtl@dotrim{\@dtl@trim{} #2}% +\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 - \def\@dtl@dotrim{\@dtl@trim#1#2}% + \DTLstartsentencespace\expandafter\MakeUppercase\@dtl@tmp \fi -\@dtl@dotrim% -} -% \end{macrocode} -%\end{macro} -%\begin{macro}{\@dtl@trim} -% \begin{macrocode} -\long\def\@dtl@trim#1 \@nil{\long\def\@dtl@trmstr{#1}} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\DTLloadrawdb} -%\begin{definition} -%\cs{DTLloadrawdb}\marg{db name}\marg{filename} -%\end{definition} -% Loads a raw database (substitutes "%" $\to$ "\%", -% "$" $\to$ "\$", "&" $\to$ "\&", "#" $\to$ "\#", -% "~" $\to$ "\textasciitilde", "_" $\to$ "\_" -% and "^" $\to$ "\textasciicircum".) The user can add additional -% mappings. -% \begin{macrocode} -\newcommand*\DTLloadrawdb{% - \let\@dtl@doreadline\@dtl@readrawline - \@dtlloaddb -} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@dtl@rawread} -%\begin{definition} -% \cs{@dtl@rawread}\meta{number}to\meta{cmd} -%\end{definition} -% Reads in a raw line from file given by \meta{number} -% converts special characters and stores in \meta{cmd} -% \begin{macrocode} -\begingroup -\catcode`\%=\active -\catcode`$=\active -\catcode`&=\active -\catcode`~=\active -\catcode`_=\active -\catcode`^=\active -\catcode`#=\active -\catcode`?=6\relax -\catcode`<=1\relax -\catcode`>=2\relax -\catcode`\{=\active -\catcode`\}=\active -\gdef\@dtl@rawread?1to?2<\relax -<<\catcode`\%=\active -\catcode`$=\active -\catcode`&=\active -\catcode`~=\active -\catcode`_=\active -\catcode`^=\active -\catcode`#=\active -\catcode`\{=\active -\catcode`\}=\active -\def%<\noexpand\%>\relax -\def$<\noexpand\$>\relax -\def&<\&>\relax -\def#<\#>\relax -\def~<\noexpand\textasciitilde>\relax -\def_<\noexpand\_>\relax -\def^<\noexpand\textasciicircum>\relax -\@dtl@activatebraces -\@dtl@doreadraw?1?2>>> -\gdef\@dtl@doreadraw?1?2<\relax -\read?1 to \tmp -\xdef?2<\tmp>\relax -> -\endgroup +\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} -%\end{macro} -%\begin{macro}{\@dtl@activatebraces} -% \cs{@dtl@activatebraces} resets braces for \cs{@dtl@rawread} +% The format of a booklet. % \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 +\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} -%\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 +% The format of an `inbook' entry. % \begin{macrocode} -\newcommand*{\DTLrawmap}[2]{% -\expandafter\@dtl@toks\expandafter{\@dtl@rawmappings}% -\ifx\@dtl@rawmappings\@empty - \def\@dtl@rawmappings{{#1}{#2}}% +\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 - \def\@dtl@tmp{{#1}{#2}} - \protected@edef\@dtl@rawmappings{\the\@dtl@toks,\@dtl@tmp} + \DTLstartsentencespace + \expandafter\MakeUppercase\@dtl@tmp \fi -} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@dtl@rawmappings} -% List of mappings. -% \begin{macrocode} -\newcommand*{\@dtl@rawmappings}{} +\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} -%\end{macro} -%\begin{macro}{\dtl@domappings} -%\begin{definition} -% \cs{dtl@domappings}\marg{cmd} -%\end{definition} -% Do all mappings in string given by \meta{cmd}. -% \begin{macrocode} -\newcommand*{\dtl@domappings}[1]{% -\@for\@dtl@map:=\@dtl@rawmappings\do{% - \expandafter\DTLsubstitute\expandafter#1\@dtl@map -}} -% \end{macrocode} -%\end{macro} -% -%\subsection{General List Utilities} -% -%\begin{macro}{\DTLifinlist} -%\begin{definition} -%\cs{DTLifinlist}\marg{element}\marg{list}\marg{true part}\marg{false part} -%\end{definition} -% If \meta{element} is contained in the comma-separated list given -% by \meta{list}, then do \meta{true part} otherwise do false -% part. (Does a one level expansion on \meta{list}, but no -% expansion on \meta{element}.) -% \begin{macrocode} -\newcommand*{\DTLifinlist}[4]{% - \def\@dtl@doifinlist##1,#1,##2\end@dtl@doifinlist{% - \def\@before{##1}% - \def\@after{##2}% - }% - \expandafter\@dtl@doifinlist\expandafter,#2,#1,\@nil - \end@dtl@doifinlist - \ifx\@after\@nnil -% not found - #4% - \else -% found - #3% - \fi -} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\dtl@choplast} -%\begin{definition} -% \cs{dtl@choplast}\marg{list}\marg{rest}\marg{last} -%\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}. +% 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 - \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 + \DTLstartsentencespace + \expandafter\MakeUppercase\@dtl@tmp \fi -% \end{macrocode} -% Now set \meta{last} to current element. -% \begin{macrocode} -\let#3=\@dtl@element% +\expandafter\DTLcheckendsperiod\expandafter{\@dtl@tmp}% +\DTLifanybibfieldexists{Month,Year}{\DTLaddcomma +}{\DTLaddperiod}% +}{}% +\DTLformatdate +\DTLifanybibfieldexists{Month,Year}{\DTLaddperiod}{}% }% -} -% \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 +\DTLifbibfieldexists{Note}{% +\DTLstartsentencespace +\DTLbibfield{Note}% +\DTLcheckbibfieldendsperiod{Note}% +\DTLaddperiod}{}% }% -\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}.) +% The format of an `inproceedings' entry. % \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 -} +\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} -%\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.) +% The format of a manual. % \begin{macrocode} -\newcommand{\dtl@insertinto}[3]{% -\def\@dtl@newsortedlist{}% -\@dtl@insertdonefalse -\@for\dtl@srtelement:=#2\do{% -\if@dtl@insertdone - \expandafter\toks@\expandafter{\dtl@srtelement}% - \edef\@dtl@newstuff{{\the\toks@}}% -\else - \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 +\renewcommand*{\DTLformatmanual}{% +\DTLifbibfieldexists{Author}{\DTLformatauthorlist +\DTLaddperiod}{% +\DTLifbibfieldexists{Organization}{% +\DTLstartsentencespace +\DTLbibfield{Organization}% +\DTLcheckbibfieldendsperiod{Organization}% +\DTLifbibfieldexists{Address}{\DTLaddcomma \DTLbibfield{Address}% +\DTLcheckbibfieldendsperiod{Address}% +}{}% +\DTLaddperiod}{}% }% - \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{General Token Utilities} -%\begin{macro}{\toks@gput@right@cx} -%\begin{definition} -%\cs{toks@gput@right@cx}\marg{toks name}\marg{stuff} -%\end{definition} -% Globally appends stuff to token register \cs{}\meta{toks name} -% \begin{macrocode} -\newcommand{\toks@gput@right@cx}[2]{% - \def\@toks@name{#1}% - \edef\@dtl@stuff{#2}% - \global\csname\@toks@name\endcsname\expandafter - \expandafter\expandafter{\expandafter\the - \csname\expandafter\@toks@name\expandafter\endcsname\@dtl@stuff}% -} -% \end{macrocode} -%\end{macro} -%\begin{macro}{\toks@gconcat@middle@cx} -%\begin{definition} -%\cs{toks@gconcat@middle@cx}\marg{toks name}\marg{before toks}\marg{stuff}\marg{after toks} -%\end{definition} -% Globally sets token register \cs{}\meta{toks name} to -% the contents of \meta{before toks} concatenated with -% \meta{stuff} (expanded) and the contents of \meta{after toks} -% \begin{macrocode} -\newcommand{\toks@gconcat@middle@cx}[4]{% - \def\@toks@name{#1}% - \edef\@dtl@stuff{#3}% - \global\csname\@toks@name\endcsname\expandafter\expandafter - \expandafter\expandafter\expandafter - \expandafter\expandafter{\expandafter\expandafter\expandafter - \the\expandafter\expandafter\expandafter#2% - \expandafter\@dtl@stuff\the#4}% -} -% \end{macrocode} -%\end{macro} -% -% \subsection{Floating Point Arithmetic} -% The commands defined in this section all use the equivalent -% commands provided by the \sty{fp} package, but first convert -% 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}% +\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 - \DTLdecimaltocurrency{\@dtl@tmp}{#1}% + \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} -%\end{macro} -%\begin{macro}{\DTLgadd} -% Global version +% The format of a master's thesis. % \begin{macrocode} -\newcommand*{\DTLgadd}[3]{% -\DTLadd{\@dtl@tmpii}{#2}{#3}% -\global\let#1=\@dtl@tmpii -} +\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} -%\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} +% The format of a miscellaneous entry. % \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}% +\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}{}% }% -\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 +% The format of a PhD thesis. % \begin{macrocode} -\newcommand*{\DTLgaddall}[2]{% -\DTLaddall{\@dtl@tmpi}{#2}% -\global\let#1=\@dtl@tmpi -} +\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} -%\end{macro} -% -%\begin{macro}{\DTLsub} -%\begin{definition} -% \cs{DTLsub}\marg{cmd}\marg{num1}\marg{num2} -%\end{definition} -% Sets \meta{cmd} = \meta{num1} - \meta{num2} +% The format of a proceedings. % \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 -} +\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} -%\end{macro} -%\begin{macro}{\DTLgsub} -% Global version +% The format of a technical report. % \begin{macrocode} -\newcommand*{\DTLgsub}[3]{% -\DTLsub{\@dtl@tmpii}{#2}{#3}% -\global\let#1=\@dtl@tmpii -} +\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} -%\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} +% The format of an unpublished work. % \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 -} +\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{macro} -%\begin{macro}{\DTLgmul} -% Global version +% End of `plain' style. % \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{macro}{\dtlbst@abbrv} +% Define `abbrv' style. This is similar to `plain' except that +% some of the values are abbreviated % \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 -} +\newcommand{\dtlbst@abbrv}{% % \end{macrocode} -%\end{macro} -%\begin{macro}{\DTLgdiv} -% Global version +% Base this style on `plain': % \begin{macrocode} -\newcommand*{\DTLgdiv}[3]{% -\DTLdiv{\@dtl@tmpii}{#2}{#3}% -\global\let#1=\@dtl@tmpii -} +\dtlbst@plain % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\DTLabs} -%\begin{definition} -% \cs{DTLabs}\marg{cmd}\marg{num} -%\end{definition} -% Sets \meta{cmd} = abs(\meta{num}) +% Sets the author name format. % \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 -} +\renewcommand*{\DTLformatauthor}[4]{% +\DTLformatabbrvforenames{##4} +\DTLformatvon{##1}% +\DTLformatsurname{##2}% +\DTLformatjr{##3}} % \end{macrocode} -%\end{macro} -%\begin{macro}{\DTLgabs} -% Global version +% Sets the editor name format. % \begin{macrocode} -\newcommand*{\DTLgabs}[2]{% -\DTLabs{\@dtl@tmpii}{#2}% -\global\let#1=\@dtl@tmpii -} +\renewcommand*{\DTLformateditor}[4]{% +\DTLformatabbrvforenames{##4} +\DTLformatvon{##1}% +\DTLformatsurname{##2}% +\DTLformatjr{##3}} % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\DTLneg} -%\begin{definition} -% \cs{DTLneg}\marg{cmd}\marg{num} -%\end{definition} -% Sets \meta{cmd} = -\meta{num} +% Sets the monthname format. % \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 -} +\let\DTLmonthname\dtl@abbrvmonthname % \end{macrocode} -%\end{macro} -%\begin{macro}{\DTLgneg} -% Global version +% 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} -\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{macro}{\dtlbst@alpha} +% Define `alpha' style. This is similar to `plain' except that +% the labels are strings rather than numerical. % \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 -} +\newcommand{\dtlbst@alpha}{% % \end{macrocode} -%\end{macro} -%\begin{macro}{\DTLgsqrt} -% Global version +% Base this style on `plain': % \begin{macrocode} -\newcommand*{\DTLgsqrt}[2]{% -\DTLsqrt{\@dtl@tmpii}{#2}% -\global\let#1=\@dtl@tmpii -} +\dtlbst@plain % \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}) +% Set how to format the entire bibliography: % \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 -} +\renewenvironment{DTLthebibliography}[2][\boolean{true}]{% +\dtl@createalphabiblabels{##1}{##2}% +\begin{thebibliography}{\@dtl@widestlabel}% +}{\end{thebibliography}}% % \end{macrocode} -%\end{macro} -%\begin{macro}{\DTLgmin} -% Global version +% Set how to start the bibliography entry: % \begin{macrocode} -\newcommand*{\DTLgmin}[3]{% -\DTLmin{\@dtl@tmpii}{#2}{#3}% -\global\let#1=\@dtl@tmpii -} +\renewcommand*{\DTLbibitem}{% +\expandafter\bibitem\expandafter + [\csname dtl@biblabel@\DBIBcitekey\endcsname]{\DBIBcitekey}}% +\renewcommand*{\DTLmbibitem}[1]{% +\expandafter\bibitem\expandafter + [\csname dtl@biblabel@\DBIBcitekey\endcsname]{##1@\DBIBcitekey}}% % \end{macrocode} -%\end{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 +% End of `alpha' style. % \begin{macrocode} -\newcommand*{\DTLgminall}[2]{% -\DTLminall{\@dtl@tmpi}{#2}% -\global\let#1=\@dtl@tmpi } % \end{macrocode} %\end{macro} % -%\begin{macro}{\DTLmax} +%\begin{macro}{dtl@createalphabiblabels} %\begin{definition} -% \cs{DTLmax}\marg{cmd}\marg{num1}\marg{num2} +%\cs{dtl@createalphabiblabels}\marg{condition}\marg{db name} %\end{definition} -% Sets \meta{cmd} = max(\meta{num1}, \meta{num2}) +% 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*{\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}}% +\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 -} -% \end{macrocode} -%\end{macro} -%\begin{macro}{\DTLgmax} -% Global version -% \begin{macrocode} -\newcommand*{\DTLgmax}[3]{% -\DTLmax{\@dtl@tmpii}{#2}{#3}% -\global\let#1=\@dtl@tmpii +\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}{\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{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*{\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}% +\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 - \DTLdecimaltocurrency{\@dtl@max}{#1}% + {% + \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} -%\begin{macro}{\DTLgmaxall} -%\begin{definition} -%\cs{DTLgmaxall}\marg{cmd}\marg{num list} -%\end{definition} -% Global version +% Get author's initial (stores in \cs{@dtl@tmp}): % \begin{macrocode} -\newcommand*{\DTLgmaxall}[2]{% -\DTLmaxall{\@dtl@tmpi}{#2}% -\global\let#1=\@dtl@tmpi -} +\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} -%\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} +% Get label for single author (last argument is control sequence +% in which to store the label): % \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}% +\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 - \DTLdecimaltocurrency{\@dtl@mean}{#1}% + {\def\DTLafterinitials{}\def\DTLbetweeninitials{}% + \def\DTLafterinitialbeforehyphen{}% + \def\DTLinitialhyphen{}% + \DTLstoreinitials{#1 #2}{\@dtl@tmp}\global\let#5=\@dtl@tmp}% \fi } % \end{macrocode} -%\end{macro} -%\begin{macro}{\DTLgmeanforall} -%\begin{definition} -%\cs{DTLgmeanforall}\marg{cmd}\marg{num list} -%\end{definition} -% Global version +%Get first three letters from the given string: % \begin{macrocode} -\newcommand*{\DTLgmeanforall}[2]{% -\DTLmeanforall{\@dtl@tmpi}{#2}% -\global\let#1=\@dtl@tmpi +\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} -%\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} +%Get year suffix: % \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 +\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 - \expandafter\toks@\expandafter{\@dtl@decvals}% - \edef\@dtl@decvals{\the\toks@,\@dtl@num}% + \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 - \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 +\@dtl@donext } % \end{macrocode} -%\end{macro} -%\begin{macro}{\DTLgvarianceforall} +% +%\begin{macro}{\DTLbibliographystyle} %\begin{definition} -%\cs{DTLgvarianceforall}\marg{cmd}\marg{num list} +%\cs{DTLbibliographystyle}\marg{style} %\end{definition} -% Global version +% Sets the bibliography style. % \begin{macrocode} -\newcommand*{\DTLgvarianceforall}[2]{% -\DTLvarianceforall{\@dtl@tmpi}{#2}% -\global\let#1=\@dtl@tmpi -} +\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} % -%\begin{macro}{\DTLsdforall} +%\section{Multiple Bibliographies} +% In order to have multiple bibliographies, there needs to be +% an aux file for each bibliography. The main bibliography is in +% \cs{jobname}.aux, but need to provide a means of creating +% additional aux files. +%\begin{macro}{\DTLmultibibs} %\begin{definition} -%\cs{DTLsdforall}\marg{cmd}\marg{num list} +%\cs{DTLmultibibs}\marg{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} +%\changes{1.01}{2007/08/22}{new} +% This creates an auxiliary file for each name in \meta{list}. +% For example, "\DTLmultibibs{foo,bar}" will create the files +% "foo.aux" and "bar.aux". % \begin{macrocode} -\newcommand*{\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 -} +\newcommand*{\DTLmultibibs}[1]{% +\@for\@dtl@af:=#1\do{% +\@ifundefined{dtl@aux@\@dtl@af}{% +\expandafter\newwrite\csname dtl@aux@\@dtl@af\endcsname +\expandafter\immediate +\expandafter\openout\csname dtl@aux@\@dtl@af\endcsname=\@dtl@af.aux +\expandafter\def\csname b@\@dtl@af @*\endcsname{}% +}{% +\PackageError{databib}{Can't create auxiliary file `\@dtl@af.aux', +\expandafter\string\csname dtl@aux@\@dtl@af\endcsname\space +already exists}{}}}} % \end{macrocode} -%\end{macro} -%\begin{macro}{\DTLgsdforall} -%\begin{definition} -%\cs{DTLgsdforall}\marg{cmd}\marg{num list} -%\end{definition} -% Global version +% Can only be used in the preamble: % \begin{macrocode} -\newcommand*{\DTLgsdforall}[2]{% -\DTLsdforall{\@dtl@tmpi}{#2}% -\global\let#1=\@dtl@tmpi -} +\@onlypreamble{\DTLmultibibs} % \end{macrocode} %\end{macro} -% -%\begin{macro}{\DTLround} +%\begin{macro}{\DTLcite} %\begin{definition} -% \cs{DTLround}\marg{cmd}\marg{num}\marg{num digits} +%\cs{DTLcite}\oarg{text}\marg{mbib}\marg{labels} %\end{definition} -% Sets \meta{cmd} to \meta{num} rounded to \meta{num digits} -% digits after the decimal character. +% This is similar to \cs{cite}\oarg{text}\marg{labels}, except +% 1) the cite information is written to the auxiliary file +% associated with the multi-bib \meta{mbib} (which must be named +% in \cs{DTLmultibibs}) and 2) the cross referencing label is +% constructed from \meta{mbib} and \meta{label} to allow for +% the same citation to appear in multiple bibliographies. % \begin{macrocode} -\newcommand*{\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 -} +\newcommand*{\DTLcite}{\@ifnextchar[{\@tempswatrue \dtl@citex +}{\@tempswafalse \dtl@citex[]}} % \end{macrocode} %\end{macro} -%\begin{macro}{\DTLground} -% Global version +%\begin{macro}{\dtl@citex} % \begin{macrocode} -\newcommand*{\DTLground}[3]{% -\DTLround{\@dtl@tmpii}{#2}{#3}% -\global\let#1=\@dtl@tmpii +\def\dtl@citex[#1]#2#3{% +\leavevmode\let\@citea\@empty +\@cite{\@for\@citeb:=#3\do{\@citea + \def\@citea{,\penalty \@m \ }% + \edef\@citeb{\expandafter\@firstofone\@citeb\@empty}% + \if@filesw + \@ifundefined{dtl@aux@#2}{% + \PackageError{databib}{multibib `#2' not defined}{% + You need to define `#2' in \string\DTLmutlibibs}% + }{% + \expandafter\immediate + \expandafter\write\csname dtl@aux@#2\endcsname{% + \string\citation{\@citeb}}% + }% + \fi + \@ifundefined{b@#2@\@citeb}{% + \hbox{\reset@font\bfseries ?}% + \G@refundefinedtrue + \@latex@warning{Citation `\@citeb ' on page \thepage \space + undefined}% + }{% + \@cite@ofmt{\csname b@#2@\@citeb \endcsname }% + }% +}}{#1}% } % \end{macrocode} %\end{macro} -% -%\begin{macro}{\DTLtrunc} +%\begin{macro}{\DTLnocite} %\begin{definition} -% \cs{DTLtrunc}\marg{cmd}\marg{num}\marg{num digits} +%\cs{DTLnocite}\marg{mbib}\marg{key list} %\end{definition} -% Sets \meta{cmd} to \meta{num} truncated to \meta{num digits} -% digits after the decimal character. +% As \cs{nocite} but uses the aux file associated with \meta{mbib} +% which must have been defined using \cs{DTLmultibibs}. % \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 +\newcommand*{\DTLnocite}[2]{% +\@ifundefined{dtl@aux@#1}{% + \PackageError{databib}{multibib `#1' not defined}{% + You need to define `#1' in \string\DTLmutlibibs}% +}{% + \@bsphack + \ifx\@onlypreamble\document + \@for\@citeb:=#2\do{% + \edef\@citeb{\expandafter\@firstofone\@citeb}% + \if@filesw + \expandafter\immediate + \expandafter\write\csname dtl@aux@#1\endcsname{% + \string\citation{\@citeb}}% + \fi + \@ifundefined{b@#1@\@citeb}{% + \G@refundefinedtrue + \@latex@warning{Citation `\@citeb ' undefined}}{}% + }% + \else + \@latex@error{Cannot be used in preamble}\@eha + \fi + \@esphack +}% } % \end{macrocode} %\end{macro} -%\begin{macro}{\DTLgtrunc} -% Global version +% +%\begin{macro}{\DTLloadmbbl} +%\begin{definition} +%\cs{DTLloadmbib}\marg{mbib}\marg{db name}\marg{bib list} +%\end{definition} % \begin{macrocode} -\newcommand*{\DTLgtrunc}[3]{% -\DTLtrunc{\@dtl@tmpii}{#2}{#3}% -\global\let#1=\@dtl@tmpii +\newcommand*{\DTLloadmbbl}[3]{% +\@ifundefined{dtl@aux@#1}{% + \PackageError{databib}{multibib `#1' not defined}{% + You need to define `#1' in \string\DTLmutlibibs}% +}{% + \if@filesw + \expandafter\immediate\expandafter + \write\csname dtl@aux@#1\endcsname{\string\bibstyle{databib}}% + \expandafter\immediate\expandafter + \write\csname dtl@aux@#1\endcsname{\string\bibdata{#3}}% + \fi + \DTLnewdb{#2}% + \edef\DTLBIBdbname{#2}% + \@input@{#1.bbl}% +}% } % \end{macrocode} %\end{macro} -% -%\begin{macro}{\DTLclip} %\begin{definition} -% \cs{DTLclip}\marg{cmd}\marg{num} +%\cs{DTLmbibliography}\oarg{condition}\marg{mbib name}\marg{bib dbname} %\end{definition} -% Sets \meta{cmd} to \meta{num} with all unnecessary 0's removed. +% Displays the bibliography for the database \meta{bib dbname} +% which must have previously been loaded using +% \cs{DTLloadmbbl}, where \meta{mbib name} must be listed +% in \cs{DTLmultibibs}. +%\begin{macro}{\DTLmbibliography} % \begin{macrocode} -\newcommand*{\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 +\newcommand*{\DTLmbibliography}[3][\boolean{true}]{% +\begin{DTLthebibliography}[#1]{#3}% +\DTLforeachbibentry[#1]{#3}{% +\DTLmbibitem{#2} \DTLformatbibentry \DTLendbibitem +}% +\end{DTLthebibliography}% } % \end{macrocode} %\end{macro} -%\begin{macro}{\DTLgclip} -% Global version +%\iffalse % \begin{macrocode} -\newcommand*{\DTLgclip}[3]{% -\DTLclip{\@dtl@tmpii}{#2}% -\global\let#1=\@dtl@tmpii -} +% % \end{macrocode} -%\end{macro} -% -%\subsection{String Macros} -%\begin{macro}{\DTLinitials} -%\begin{definition} -%\cs{DTLinitials}\marg{string} -%\end{definition} -% Convert a string into initials. -% (Any "~" character found is first converted into a space.) -%\changes{1.01}{2007 Aug 17}{now works with unbreakable space symbol} -%\changes{1.01}{2007 Aug 17}{now uses \cs{DTLinitialhyphen}} +%\fi +%\iffalse % \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}% +%<*databar.sty> % \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.) +%\fi +%\chapter{databar.sty} +% Declare package: % \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 +\NeedsTeXFormat{LaTeX2e} +\ProvidesPackage{databar}[2012/07/18 v2.10 (NLCT)] % \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}} +% Require \sty{xkeyval} package % \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 -} +\RequirePackage{xkeyval} % \end{macrocode} -%\end{macro} -%\begin{macro}{\dtl@initials} +% Require \sty{dataplot} package % \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 -} +\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} -%\begin{macro}{\@dtl@initials} +% Package options to change the conditional: % \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 +\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 - \edef\dtl@initialscmd{\the\@dtl@toks\the\toks@\DTLbetweeninitials}% - \let\dtl@initialsnext=\dtl@initials -\fi -\dtl@initialsnext{#3}} + \def\DTLbarXlabelalign{right}% + \def\DTLbarYticklabelalign{center} +\fi} % \end{macrocode} %\end{macro} -%\begin{macro}{\dtl@initialshyphen} +% Set defaults: % \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 +\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}{\DTLafterinitials} -% Defines what to do after the final initial. +% +%\begin{macro}{\DTLbarwidth} +% The width of each bar is given by \cs{DTLbarwidth}. % \begin{macrocode} -\newcommand*{\DTLafterinitials}{.} +\newlength\DTLbarwidth +\DTLbarwidth=1cm % \end{macrocode} %\end{macro} -%\begin{macro}{\DTLbetweeninitials} -% Defines what to do between initials. +% +%\begin{macro}{\DTLbarlabeloffset} +% The offset from the $x$ axis to the bar label if given by +% \cs{DTLbarlabeloffset}. % \begin{macrocode} -\newcommand*{\DTLbetweeninitials}{.} +\newlength\DTLbarlabeloffset +\setlength\DTLbarlabeloffset{10pt} % \end{macrocode} %\end{macro} -%\begin{macro}{\DTLafterinitialbeforehyphen} -% Defines what to do before a hyphen. +%\begin{macro}{\DTLBarXAxisStyle} +% The style of the $x$ axis is given by \cs{DTLBarXAxisStyle} % \begin{macrocode} -\newcommand*{\DTLafterinitialbeforehyphen}{.} +\newcommand*{\DTLBarXAxisStyle}{-} % \end{macrocode} %\end{macro} -%\begin{macro}{\DTLinitialhyphen} -%Defines what to do at the hyphen -%\changes{1.01}{2007 Aug 17}{new} +%\begin{macro}{\DTLBarYAxisStyle} +% The style of the $y$ axis is given by \cs{DTLBarYAxisStyle}. % \begin{macrocode} -\newcommand*{\DTLinitialhyphen}{-} +\newcommand*{\DTLBarYAxisStyle}{-} % \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{counter}{DTLbarroundvar} +% \ctrfmt{DTLbarroundvar} is a counter governing the number of digits +% to round to when using \cs{FPround}. % \begin{macrocode} -\newcommand*{\DTLifAllUpperCase}[3]{% -\protected@edef\dtl@tuc{#1}% -\expandafter\dtl@testifuppercase\dtl@tuc\@nil\relax -\if@dtl@condition#2\else#3\fi -} +\newcounter{DTLbarroundvar} +\setcounter{DTLbarroundvar}{1} % \end{macrocode} -%\end{macro} -%\begin{macro}{\dtl@testifalluppercase} +%\end{counter} +% +%\begin{macro}{\DTLbardisplayYticklabel} +%\cs{DTLbardisplayYticklabel} governs how the $y$ tick labels appear. % \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 -} +\newcommand*{\DTLbardisplayYticklabel}[1]{#1} % \end{macrocode} %\end{macro} -%\begin{macro}{\dtl@test@ifalluppercase} +%\begin{macro}{\DTLdisplaylowerbarlabel} +%\cs{DTLdisplaylowerbarlabel} governs how the lower bar labels appear. % \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 -}}} +\newcommand*{\DTLdisplaylowerbarlabel}[1]{#1} % \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{macro}{\DTLdisplaylowermultibarlabel} +%\cs{DTLdisplaylowermultibarlabel} governs how the lower multi bar labels appear. % \begin{macrocode} -\newcommand*{\DTLifAllLowerCase}[3]{% -\protected@edef\dtl@tlc{#1}% -\expandafter\dtl@testiflowercase\dtl@tlc\@nil\relax -\if@dtl@condition#2\else#3\fi -} +\newcommand*{\DTLdisplaylowermultibarlabel}[1]{#1} % \end{macrocode} %\end{macro} -%\begin{macro}{\dtl@testifalllowercase} +%\begin{macro}{\DTLdisplayupperbarlabel} +%\cs{DTLdisplayupperbarlabel} governs how the upper bar labels +% appear. % \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 -} +\newcommand*{\DTLdisplayupperbarlabel}[1]{#1} % \end{macrocode} %\end{macro} -%\begin{macro}{\dtl@test@ifalllowercase} +%\begin{macro}{\DTLdisplayuppermultibarlabel} +%\cs{DTLdisplayuppermultibarlabel} governs how the upper multi bar +% labels appear. % \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 -}}} +\newcommand*{\DTLdisplayuppermultibarlabel}[1]{#1} % \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{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{\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 -} +\newcommand*{\DTLbaratbegintikz}{} % \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{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*{\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 -} +\newcommand*{\DTLbaratendtikz}{} % \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{macro}{\ifDTLbarxaxis} +% The conditional \cs{ifDTLbarxaxis} is used to determine +% whether or not to display the $x$ axis % \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}% -} +\newif\ifDTLbarxaxis % \end{macrocode} %\end{macro} -%\begin{macro}{\@dtl@dosubstitute} -% Recursive substitution macro. +%\begin{macro}{\ifDTLbaryaxis} +% The conditional \cs{ifDTLbaryaxis} is used to determine +% whether or not to display the $y$ axis. % \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}% -} +\newif\ifDTLbaryaxis % \end{macrocode} %\end{macro} -%\begin{macro}{\@dtl@dosubstitutenoop} -% Terminates recursive substitution macro. +%\begin{macro}{\ifDTLbarytics} +% The conditional \cs{ifDTLbarytics} to determine whether +% or not to display the $y$ tick marks. % \begin{macrocode} -\def\@dtl@dosubstitutenoop#1#2{} +\newif\ifDTLbarytics % \end{macrocode} %\end{macro} % -%\subsection{Currencies} -%\begin{macro}{\@dtl@currencies} -% \cs{@dtl@currencies} stores all known currencies. +%\begin{macro}{\@dtl@barcount} +% The count register \cs{@dtl@barcount} is used to store +% the current bar index. % \begin{macrocode} -\newcommand*{\@dtl@currencies}{\$,\pounds} +\newcount\@dtl@barcount % \end{macrocode} %\end{macro} -%\begin{macro}{\DTLnewcurrencysymbol} +% +%\begin{macro}{\DTLsetbarcolor} %\begin{definition} -% \cs{DTLaddcurrency}\marg{symbol} +% \cs{DTLsetbarcolor}\marg{n}\marg{color} %\end{definition} -% Adds \meta{symbol} to the list of known currencies +% Assigns colour name \meta{color} to the \meta{n}th bar. % \begin{macrocode} -\newcommand*{\DTLnewcurrencysymbol}[1]{% -\expandafter\toks@\expandafter{\@dtl@currencies}% -\@dtl@toks{#1}% -\edef\@dtl@currencies{\the\@dtl@toks,\the\toks@}% +\newcommand*{\DTLsetbarcolor}[2]{% +\expandafter\def\csname dtlbar@segcol\romannumeral#1\endcsname{#2}% } % \end{macrocode} %\end{macro} -% If any of the following currency commands have been defined, -% add them to the list: +% +%\begin{macro}{\DTLgetbarcolor} +%\begin{definition} +%\cs{DTLgetbarcolor}\marg{n} +%\end{definition} +% Gets the colour specification for the \meta{n}th bar. % \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}}% -} +\newcommand*{\DTLgetbarcolor}[1]{% +\csname dtlbar@segcol\romannumeral#1\endcsname} % \end{macrocode} -%\begin{macro}{\@dtl@standardize@currency} +%\end{macro} +% +%\begin{macro}{\DTLdobarcolor} %\begin{definition} -%\cs{@dtl@standardize@currency}\marg{cmd} +%\cs{DTLdobarcolor}\marg{n} %\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. +% Sets the colour to that for the \meta{n}th bar. % \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} +\newcommand*{\DTLdobarcolor}[1]{% +\expandafter\color\expandafter +{\csname dtlbar@segcol\romannumeral#1\endcsname}} % \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{macro}{\DTLdocurrentbarcolor} +%\cs{DTLdocurrentbarcolor} +% sets the colour to that of the current bar. % \begin{macrocode} -\newcommand*{\@dtl@currency}{\$} +\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}{\DTLsetdefaultcurrency} -%\cs{DTLsetdefaultcurrency}\marg{symbol} sets the default currency. +% +%\begin{macro}{\DTLbaroutlinecolor} +%\cs{DTLbaroutlinecolor} specifies what colour to draw the +% outline. % \begin{macrocode} -\newcommand*{\DTLsetdefaultcurrency}[1]{% -\renewcommand*{\@dtl@currency}{#1}} +\newcommand*{\DTLbaroutlinecolor}{black} % \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{macro}{\DTLbaroutlinewidth} +%\cs{DTLbaroutlinewidth} specifies the line width of the outline: +% Outline is only drawn if the linewidth is greater than 0pt. % \begin{macrocode} -\newcommand{\dtl@ifsingle}[3]{% -\def\@dtl@arg{#1}% -\ifx\@dtl@arg\@empty - #3% -\else - \@dtl@ifsingle#1\@nil{#2}{#3}% -\fi -} +\newlength\DTLbaroutlinewidth +\DTLbaroutlinewidth=0pt % \end{macrocode} %\end{macro} -%\begin{macro}{\@dtl@ifsingle} +% +% Set the default colours. If there are more than eight bars, +% more colours will need to be defined. % \begin{macrocode} -\def\@dtl@ifsingle#1#2\@nil#3#4{% -\def\dtl@sg@arg{#2}% -\ifx\dtl@sg@arg\@empty - #3% +\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 - #4% + \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} -%\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. -%\changes{2.0}{2009 February 27}{updated to use new database structure} +%\begin{macro}{\DTLeverybarhook} +% Code to apply at every bar. The start point of the bar +% can be accessed via \cs{DTLstartpt}, the mid point of the bar +% can be accessed via \cs{DTLmidpt} and the end point of the +% bar can be accessed via \cs{DTLendpt} +%\changes{2.0}{2009 February 27}{new}% % \begin{macrocode} -\newcommand*{\dtlshowdb}[1]{% -\expandafter\showthe\csname dtldb@#1\endcsname} +\newcommand*{\DTLeverybarhook}{} % \end{macrocode} %\end{macro} % -%\begin{macro}{\dtlshowdbkeys} -%\begin{definition} -%\cs{dtlshowdbkeys}\marg{db name} -%\end{definition} -% Shows the key list for the named database. -%\changes{2.0}{2009 February 27}{updated to use new database structure} +% Define keys for \cs{DTLbarchart} optional argument. +% Set the maximum value of the $y$ axis. % \begin{macrocode} -\newcommand*{\dtlshowdbkeys}[1]{% -\expandafter\showthe\csname dtlkeys@#1\endcsname} +\define@key{databar}{max}{\def\DTLbarmax{#1}} % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\dtlshowtype} -%\begin{definition} -%\cs{dtlshowtype}\marg{db name}\marg{key} -%\end{definition} -% Show the data type for given key in the named database. -% This should be an integer from 0 to 3. -%\changes{2.0}{2009 February 27}{updated to use new database structure} +% Set the total length of the bar chart % \begin{macrocode} -\newcommand*{\dtlshowtype}[2]{% - \DTLgetdatatype{\@dtl@type}{#1}{#2}\show\@dtl@type +\define@key{databar}{length}{\DTLbarchartlength=#1\relax } % \end{macrocode} -%\end{macro} -%\iffalse +% 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} -%\fi -%\iffalse +% Determine which axes should be shown % \begin{macrocode} -%<*datapie.sty> +\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} -%\fi -%\section{datapie.sty} -% Declare package: +% Variable used to create the bar chart. (Must be a control +% sequence.) % \begin{macrocode} -\NeedsTeXFormat{LaTeX2e} -\ProvidesPackage{datapie}[2009/10/22 v2.01 (NLCT)] +\define@key{databar}{variable}{% + \def\DTLbarvariable{#1}% +} % \end{macrocode} -% Require \sty{xkeyval} package +% Variables used to create the multi bar chart. (Must be a +% comma separated list of control sequences.) % \begin{macrocode} -\RequirePackage{xkeyval} +\define@key{databar}{variables}{% + \def\dtlbar@variables{#1}% +} % \end{macrocode} -%\begin{macro}{\ifDTLcolorpiechart} -% The conditional \cs{ifDTLcolorpiechart} is to determine -% whether to use colour or grey scale. +% Bar width % \begin{macrocode} -\newif\ifDTLcolorpiechart -\DTLcolorpiecharttrue +\define@key{databar}{barwidth}{\setlength{\DTLbarwidth}{#1}} % \end{macrocode} -%\end{macro} -% Package options to change the conditional: +% Lower bar labels % \begin{macrocode} -\DeclareOption{color}{\DTLcolorpiecharttrue} -\DeclareOption{gray}{\DTLcolorpiechartfalse} +\define@key{databar}{barlabel}{% +\def\dtl@barlabel{#1}} +\def\dtl@barlabel{} % \end{macrocode} -%\begin{macro}{\ifDTLrotateinner} -% Define boolean keys to govern label rotations. +% Lower bar labels for multi-bar charts % \begin{macrocode} -\define@boolkey{datapie}[DTL]{rotateinner}[true]{} +\define@key{databar}{multibarlabels}{% +\def\dtl@multibarlabels{#1}} +\def\dtl@multibarlabels{} % \end{macrocode} -%\end{macro} -%\begin{macro}{\ifDTLrotateouter} +% 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@boolkey{datapie}[DTL]{rotateouter}[true]{} +\define@key{databar}{groupgap}{\def\dtlbar@groupgap{#1}} +\def\dtlbar@groupgap{1} % \end{macrocode} -%\end{macro} -% Set defaults: +% Upper bar labels % \begin{macrocode} -\DTLrotateinnerfalse -\DTLrotateouterfalse +\define@key{databar}{upperbarlabel}{% +\def\dtl@upperbarlabel{#1}} +\def\dtl@upperbarlabel{} % \end{macrocode} -% Package options to change \cs{DTLrotateinner} +% Upper bar labels for multi-bar charts % \begin{macrocode} -\DeclareOption{rotateinner}{\DTLrotateinnertrue} -\DeclareOption{norotateinner}{\DTLrotateinnerfalse} +\define@key{databar}{uppermultibarlabels}{% +\def\dtl@uppermultibarlabels{#1}} +\def\dtl@uppermultibarlabels{} % \end{macrocode} -% Package options to change \cs{DTLrotateouter} +% Define list of points for $y$ tics. (Must be a comma separated list +% of decimal numbers.) % \begin{macrocode} -\DeclareOption{rotateouter}{\DTLrotateoutertrue} -\DeclareOption{norotateouter}{\DTLrotateouterfalse} +\define@key{databar}{yticpoints}{% +\def\dtlbar@yticlist{#1}\DTLbaryticstrue\DTLbaryaxistrue} +\let\dtlbar@yticlist=\relax % \end{macrocode} -% Process options: +% Set the $y$ tick gap: % \begin{macrocode} -\ProcessOptions +\define@key{databar}{yticgap}{% +\def\dtlbar@yticgap{#1}\DTLbaryticstrue\DTLbaryaxistrue} +\let\dtlbar@yticgap=\relax % \end{macrocode} -% Required packages: +% Define list of labels for $y$ tics. % \begin{macrocode} -\RequirePackage{datatool} -\RequirePackage{tikz} +\define@key{databar}{yticlabels}{% +\def\dtlbar@yticlabels{#1}\DTLbaryticstrue\DTLbaryaxistrue} +\let\dtlbar@yticlabels=\relax % \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}. +% Define $y$ axis label. % \begin{macrocode} -\newlength\DTLradius -\DTLradius=2cm +\define@key{databar}{ylabel}{% +\def\dtlbar@ylabel{#1}} +\let\dtlbar@ylabel=\relax % \end{macrocode} -%\end{macro} -%\begin{macro}{\DTLinnerratio} -% The inner label offset ratio is given by \cs{DTLinnerratio} +% +%\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*{\DTLinnerratio}{0.5} +\newcommand*{\DTLbarchart}[4][\boolean{true}]{% +{% + \undef\DTLbarvariable + \undef\DTLbarmax + \undef\DTLnegextent + \disable@keys{databar}{variables,multibarlabels,% + uppermultibarlabels,groupgap}% + \setkeys{databar}{#2}% + \ifundef{\DTLbarvariable}% + {% + \PackageError{databar}% + {\string\DTLbarchart\space missing variable}% + {You haven't use the "variable" key}% + }% + {% % \end{macrocode} -%\end{macro} -%\begin{macro}{\DTLouterratio} -% The outer label offset ratio is given by \cs{DTLouterratio}. +% 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} -\newcommand*{\DTLouterratio}{1.25} + \ifundef{\DTLbarmax}% + {% + \@sDTLforeach[#1]{#3}{#4}{% + \expandafter\DTLconverttodecimal\expandafter + {\DTLbarvariable}{\dtl@barvar}% + \ifundef{\DTLbarmax}% + {% + \let\DTLbarmax=\dtl@barvar + }% + {% + \let\dtl@old=\DTLbarmax + \dtlmax{\DTLbarmax}{\dtl@old}{\dtl@barvar}% + }% + }% + \ifx\dtlbar@yticgap\relax + \else + \let\dtl@thistick=\dtlbar@yticgap + \whiledo{\DTLisFPopenbetween{\dtl@thistick}{0}{\DTLbarmax}}% + {% + \dtladd{\dtl@thistick}{\dtl@thistick}{\dtlbar@yticgap}% + }% + \let\DTLbarmax=\dtl@thistick + \fi + }% + {}% % \end{macrocode} -%\end{macro} -%\begin{macro}{\DTLcutawayratio} -% The cutaway offset ratio is given by \cs{DTLcutawayratio}. +% Compute the bar depth, unless \cs{DTLnegextent} has been +% set. % \begin{macrocode} -\newcommand*\DTLcutawayratio{0.2} + \ifundef{\DTLnegextent}% + {% + \def\DTLnegextent{0}% + \@sDTLforeach[#1]{#3}{#4}{% + \expandafter\DTLconverttodecimal\expandafter + {\DTLbarvariable}{\dtl@barvar}% + \let\dtl@old=\DTLnegextent + \DTLmin{\DTLnegextent}{\dtl@old}{\dtl@barvar}% + }% + \ifx\dtlbar@yticgap\relax + \else + \ifthenelse{\DTLisFPlt{\DTLnegextent}{0}}% + {% + \edef\dtl@thistick{0}% + \whiledo{\DTLisFPclosedbetween{\dtl@thistick}{\DTLnegextent}{0}}{% + \dtlsub{\dtl@thistick}{\dtl@thistick}{\dtlbar@yticgap}% + }% + \let\DTLnegextent=\dtl@thistick + }{}% + \fi + }% + {}% % \end{macrocode} -%\end{macro} -%\begin{macro}{\DTLstartangle} -% The angle of the first segment is given by \cs{DTLstartangle}. +% Determine scaling factor % \begin{macrocode} -\newcommand*{\DTLstartangle}{0} + \@dtl@tmpcount=\DTLbarchartlength + \dtlsub{\dtl@extent}{\DTLbarmax}{\DTLnegextent}% + \dtldiv{\dtl@unit}{\number\@dtl@tmpcount}{\dtl@extent}% % \end{macrocode} -%\end{macro} -%\begin{macro}{\dtl@inneroffset} +% Construct $y$ tick list if required % \begin{macrocode} -\newlength\dtl@inneroffset -\dtl@inneroffset=\DTLinnerratio\DTLradius + \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{% + \dtlround{\dtl@thislabel}{\dtl@thislabel} + {\c@DTLbarroundvar}% + \ifDTLverticalbars + \settowidth{\dtl@tmplength}{% + \DTLbardisplayYticklabel{\dtl@thislabel}}% + \else + \settoheight{\dtl@tmplength}{% + \DTLbardisplayYticklabel{\dtl@thislabel}}% + \edef\@dtl@h{\the\dtl@tmplength}% + \settodepth{\dtl@tmplength}{% + \DTLbardisplayYticklabel{\dtl@thislabel}}% + \addtolength{\dtl@tmplength}{\@dtl@h}% + \addtolength{\dtl@tmplength}{\baselineskip}% + \fi + \ifdim\dtl@tmplength>\dtl@yticlabelwidth + \setlength{\dtl@yticlabelwidth}{\dtl@tmplength}% + \fi + }% + \else + \@for\dtl@thislabel:=\dtlbar@yticlabels\do{% + \ifDTLverticalbars + \settowidth{\dtl@tmplength}{% + \DTLbardisplayYticklabel{\dtl@thislabel}}% + \else + \settoheight{\dtl@tmplength}{% + \DTLbardisplayYticklabel{\dtl@thislabel}}% + \edef\@dtl@h{\the\dtl@tmplength}% + \settodepth{\dtl@tmplength}{% + \DTLbardisplayYticklabel{\dtl@thislabel}}% + \addtolength{\dtl@tmplength}{\@dtl@h}% + \addtolength{\dtl@tmplength}{\baselineskip}% + \fi + \ifdim\dtl@tmplength>\dtl@yticlabelwidth + \setlength{\dtl@yticlabelwidth}{\dtl@tmplength}% + \fi + }% + \fi + \fi + \fi % \end{macrocode} -%\end{macro} -%\begin{macro}{\dtl@outeroffset} +% Store the width of the bar chart in \cs{DTLbarchartwidth} % \begin{macrocode} -\newlength\dtl@outeroffset -\dtl@outeroffset=\DTLouterratio\DTLradius + \edef\DTLbarchartwidth{\expandafter\number\csname dtlrows@#3\endcsname} % \end{macrocode} -%\end{macro} -%\begin{macro}{\dtl@cutawayoffset} +% Do the bar chart % \begin{macrocode} -\newlength\dtl@cutawayoffset -\dtl@cutawayoffset=\DTLcutawayratio\DTLradius + \begin{tikzpicture} % \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. +% Set unit vectors % \begin{macrocode} -\newcommand*{\dtl@piecutaways}{} + \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} -%\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 hook % \begin{macrocode} -\def\dtl@innerlabel{\DTLpievariable}% + \DTLbaratbegintikz % \end{macrocode} -%\end{macro} -%\begin{macro}{\dtl@outerlabel} +% Initialise % \begin{macrocode} -\def\dtl@outerlabel{}% + \def\@dtl@start{0}% % \end{macrocode} -%\end{macro} -%\begin{counter}{DTLpieroundvar} -% \ctrfmt{DTLpieroundvar} is a counter governing the number of digits -% to round to when using \cs{FPround}. +% Iterate through data % \begin{macrocode} -\newcounter{DTLpieroundvar} -\setcounter{DTLpieroundvar}{1} + \@sDTLforeach[#1]{#3}{#4}{% % \end{macrocode} -%\end{counter} -% -%\begin{macro}{\DTLdisplayinnerlabel} -%\begin{definition} -%\cs{DTLdisplayinnerlabel}\marg{label} -%\end{definition} -% This is used to format the inner label. This just does the -% label by default. +% Store the bar number in \cs{@dtl@bar} % \begin{macrocode} -\newcommand*{\DTLdisplayinnerlabel}[1]{#1} + \expandafter\let\expandafter\@dtl@bar + \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname% % \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. +% Convert variable to decimal % \begin{macrocode} -\newcommand*{\DTLdisplayouterlabel}[1]{#1} + \expandafter\DTLconverttodecimal\expandafter + {\DTLbarvariable}{\dtl@variable}% % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\DTLpiepercent} -%\cs{DTLpiepercent} -% returns the percentage value of the current segment. +% Draw bars % \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} + \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} -%\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. +% Draw outline % \begin{macrocode} -\newcommand*{\DTLpieatbegintikz}{} + \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} -%\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. +% Draw lower $x$ labels % \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} + \ifDTLverticalbars + \edef\dtl@textopt{% + at={\noexpand\pgfpointadd + {\noexpand\pgfpointxy{\@dtl@start.5}{0}} + {\noexpand\pgfpoint{0pt}{-\noexpand\DTLbarlabeloffset}}}, + \DTLbarXlabelalign + }% % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\DTLpieoutlinecolor} -%\cs{DTLpieoutlinecolor} specifies what colour to draw the -% outline. +% Set \cs{DTLstartpt} to the starting point. % \begin{macrocode} -\newcommand*{\DTLpieoutlinecolor}{black} + \edef\DTLstartpt{\noexpand\pgfpointxy{\@dtl@start.5}{0}}% + \else + \edef\dtl@textopt{% + at={\noexpand\pgfpointadd + {\noexpand\pgfpointxy{0}{\@dtl@start.5}} + {\noexpand\pgfpoint{-\noexpand\DTLbarlabeloffset}{0pt}}}, + \DTLbarXlabelalign + }% % \end{macrocode} -%\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. +% Set \cs{DTLstartpt} to the starting point. % \begin{macrocode} -\newlength\DTLpieoutlinewidth -\DTLpieoutlinewidth=0pt + \edef\DTLstartpt{\noexpand\pgfpointxy{0}{\@dtl@start.5}}% + \fi + \expandafter\pgftext\expandafter[\dtl@textopt]{% + \DTLdisplaylowerbarlabel{\dtl@barlabel}} % \end{macrocode} -%\end{macro} -% -% Set the default colours. If there are more than eight segments, -% more colours will need to be defined. +% Draw upper $x$ labels % \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 + \ifDTLverticalbars % \end{macrocode} -% Define keys for \cs{DTLpiechart} optional argument. -% Set the starting angle of the first segment. +% Vertical bars % \begin{macrocode} -\define@key{datapie}{start}{\def\DTLstartangle{#1}} + \expandafter\DTLifnumlt\expandafter{\DTLbarvariable}{0}% + { + \edef\dtl@textopt{% + at={\noexpand\pgfpointadd + {\noexpand\pgfpointxy{\@dtl@start.5}{\dtl@variable}} + {\noexpand\pgfpoint{0pt}{-\noexpand\DTLbarlabeloffset}}} + }% + }{% + \edef\dtl@textopt{% + at={\noexpand\pgfpointadd + {\noexpand\pgfpointxy{\@dtl@start.5}{\dtl@variable}} + {\noexpand\pgfpoint{0pt}{\noexpand\DTLbarlabeloffset}}} + }% + } % \end{macrocode} -% Set the radius of the pie chart (must be set prior to -% inneroffset and outeroffset keys.) +% Set \cs{DTLendpt} to the end point. % \begin{macrocode} -\define@key{datapie}{radius}{\DTLradius=#1\relax -\dtl@inneroffset=\DTLinnerratio\DTLradius -\dtl@outeroffset=\DTLouterratio\DTLradius -\dtl@cutawayoffset=\DTLcutawayratio\DTLradius} + \edef\DTLendpt{\noexpand\pgfpointxy{\@dtl@start.5}{\dtl@variable}}% + \else % \end{macrocode} -% Set the inner ratio. +% Horizontal bars % \begin{macrocode} -\define@key{datapie}{innerratio}{% -\def\DTLinnerratio{#1}% -\dtl@inneroffset=\DTLinnerratio\DTLradius} + \expandafter\DTLifnumlt\expandafter{\DTLbarvariable}{0}% + { + \edef\dtl@textopt{right, + at={\noexpand\pgfpointadd + {\noexpand\pgfpointxy{\dtl@variable}{\@dtl@start.5}} + {\noexpand\pgfpoint{-\noexpand\DTLbarlabeloffset}{0pt}}} + }% + }{% + \edef\dtl@textopt{left, + at={\noexpand\pgfpointadd + {\noexpand\pgfpointxy{\dtl@variable}{\@dtl@start.5}} + {\noexpand\pgfpoint{\noexpand\DTLbarlabeloffset}{0pt}}} + }% + } % \end{macrocode} -% Set the outer ratio +% Set \cs{DTLendpt} to the end point. % \begin{macrocode} -\define@key{datapie}{outerratio}{% -\def\DTLouterratio{#1}% -\dtl@outeroffset=\DTLouterratio\DTLradius} + \edef\DTLendpt{\noexpand\pgfpointxy{\dtl@variable}{\@dtl@start.5}}% + \fi + \expandafter\pgftext\expandafter[\dtl@textopt]{% + \DTLdisplayupperbarlabel{\dtl@upperbarlabel}} % \end{macrocode} -% The cutaway offset ratio +% Set the mid point % \begin{macrocode} -\define@key{datapie}{cutawayratio}{% -\def\DTLcutawayratio{#1}% -\dtl@cutawayoffset=\DTLcutawayratio\DTLradius} + \def\DTLmidpt{\pgfpointlineattime{0.5}{\DTLstartpt}{\DTLendpt}}% % \end{macrocode} -% Set the inner offset as an absolute value (not dependent -% on the radius.) +% Do every bar hook +%\changes{2.0}{2009 February 27}{added \cs{DTLeverybarhook}}% % \begin{macrocode} -\define@key{datapie}{inneroffset}{% -\dtl@inneroffset=#1} + \DTLeverybarhook % \end{macrocode} -% Set the outer offset as an absolute value (not dependent -% on the radius.) +% End of loop % \begin{macrocode} -\define@key{datapie}{outeroffset}{% -\dtl@outeroffset=#1} + \edef\@dtl@start{\number\@dtl@bar}% + }% % \end{macrocode} -% Set the cutaway offset as an absolute value (not dependent -% on the radius.) +% Draw $x$ axis % \begin{macrocode} -\define@key{datapie}{cutawayoffset}{% -\dtl@cutawayoffset=#1} + \ifDTLbarxaxis + \ifDTLverticalbars + \expandafter\draw\expandafter[\DTLBarXAxisStyle] + (0,0) -- (\DTLbarchartwidth,0); + \else + \expandafter\draw\expandafter[\DTLBarXAxisStyle] + (0,0) -- (0,\DTLbarchartwidth); + \fi + \fi % \end{macrocode} -% List of cut away segments. +% Draw $y$ axis % \begin{macrocode} -\define@key{datapie}{cutaway}{% -\renewcommand*{\dtl@piecutaways}{#1}} + \ifDTLbaryaxis + \ifDTLverticalbars + \expandafter\draw\expandafter[\DTLBarYAxisStyle] + (0,\DTLnegextent) -- (0,\DTLbarmax); + \else + \expandafter\draw\expandafter[\DTLBarYAxisStyle] + (\DTLnegextent,0) -- (\DTLbarmax,0); + \fi + \fi % \end{macrocode} -% Variable used to create the pie chart. (Must be a control -% sequence.) +% Plot $y$ tick marks if required % \begin{macrocode} -\define@key{datapie}{variable}{% -\def\DTLpievariable{#1}} + \ifx\dtlbar@yticlist\relax + \else + \@for\dtl@thistick:=\dtlbar@yticlist\do{% + \ifDTLverticalbars + \pgfpathmoveto{\pgfpointxy{0}{\dtl@thistick}} + \pgfpathlineto{ + \pgfpointadd{\pgfpointxy{0}{\dtl@thistick}} + {\pgfpoint{-\DTLticklength}{0pt}}} + \else + \pgfpathmoveto{\pgfpointxy{\dtl@thistick}{0}} + \pgfpathlineto{ + \pgfpointadd{\pgfpointxy{\dtl@thistick}{0}} + {\pgfpoint{0pt}{-\DTLticklength}}} + \fi + \pgfusepath{stroke} + \ifx\dtlbar@yticlabels\relax + \dtlround{\dtl@thislabel}{\dtl@thistick} + {\c@DTLbarroundvar}% + \else + \dtl@chopfirst\dtlbar@yticlabels\dtl@thislabel\dtl@rest + \let\dtlbar@yticlabels=\dtl@rest + \fi + \ifDTLverticalbars + \edef\dtl@textopt{\DTLbarYticklabelalign,% + at={\noexpand\pgfpointadd + {\noexpand\pgfpointxy{0}{\dtl@thistick}} + {\noexpand\pgfpoint{-\noexpand\DTLticklabeloffset}{0pt}}, + }}% + \else + \edef\dtl@textopt{\DTLbarYticklabelalign, + at={\noexpand\pgfpointadd + {\noexpand\pgfpointxy{\dtl@thistick}{0}} + {\noexpand\pgfpoint{0pt}{-\noexpand\DTLticklabeloffset}} + }}% + \fi + \expandafter\pgftext\expandafter[\dtl@textopt]{% + \DTLbardisplayYticklabel{\dtl@thislabel}} + }% + \fi % \end{macrocode} -% Inner label +% Plot the $y$ label if required % \begin{macrocode} -\define@key{datapie}{innerlabel}{% -\def\dtl@innerlabel{#1}} + \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} -% Outer label +% Finish bar chart % \begin{macrocode} -\define@key{datapie}{outerlabel}{% -\def\dtl@outerlabel{#1}} + \DTLbaratendtikz + \end{tikzpicture} + }% +}% +} % \end{macrocode} +%\end{macro} % -%\begin{macro}{\DTLpiechart} +%\begin{macro}{\DTLmultibarchart} %\begin{definition} -% \cs{DTLpiechart}\oarg{conditions}\marg{option list}\marg{db name}\marg{assign list} +% \cs{DTLmultibarchart}\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}, +% 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 \texttt{variable}\texttt{=}\meta{cmd}, where \meta{cmd} +% 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*{\DTLpiechart}[4][\boolean{true}]{% -{\let\DTLpievariable=\relax -\setkeys{datapie}{#2}% -\ifx\DTLpievariable\relax - \PackageError{datapie}{\string\DTLpiechart\space missing variable}{}% +\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 total. +% 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} -\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}% -}% + \ifx\DTLbarmax\relax + \@sDTLforeach[#1]{#3}{#4}{% + \@for\DTLbarvariable:=\dtlbar@variables\do{% + \expandafter\DTLconverttodecimal\expandafter + {\DTLbarvariable}{\dtl@barvar}% + \ifx\DTLbarmax\relax + \let\DTLbarmax=\dtl@barvar + \else + \let\dtl@old=\DTLbarmax + \dtlmax{\DTLbarmax}{\dtl@old}{\dtl@barvar}% + \fi + }% + }% + \ifx\dtlbar@yticgap\relax + \else + \let\dtl@thistick=\dtlbar@yticgap% + \whiledo{\DTLisFPopenbetween{\dtl@thistick}{0}{\DTLbarmax}}{% + \dtladd{\dtl@thistick}{\dtl@thistick}{\dtlbar@yticgap}% + }% + \let\DTLbarmax=\dtl@thistick + \fi + \fi % \end{macrocode} -% Compute the 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 +% Compute the bar depth, unless \cs{DTLnegextent} has been +% set. % \begin{macrocode} -\@for\dtl@row:=\dtl@piecutaways\do{% -\expandafter\@dtl@set@off\dtl@row-\relax -}% + \ifx\DTLnegextent\relax + \def\DTLnegextent{0}% + \@sDTLforeach[#1]{#3}{#4}{% + \@for\DTLbarvariable:=\dtlbar@variables\do{% + \expandafter\DTLconverttodecimal\expandafter + {\DTLbarvariable}{\dtl@barvar}% + \let\dtl@old=\DTLnegextent + \DTLmin{\DTLnegextent}{\dtl@old}{\dtl@barvar}% + }% + }% + \ifx\dtlbar@yticgap\relax + \else + \ifthenelse{\DTLisFPlt{\DTLnegextent}{0}}{% + \edef\dtl@thistick{0}% + \whiledo{\DTLisFPclosedbetween{\dtl@thistick}{\DTLnegextent}{0}}{% + \dtlsub{\dtl@thistick}{\dtl@thistick}{\dtlbar@yticgap}% + }% + \let\DTLnegextent=\dtl@thistick + }{}% + \fi + \fi % \end{macrocode} -% Set the starting angle +% Determine scaling factor % \begin{macrocode} -\let\dtl@start=\DTLstartangle + \@dtl@tmpcount=\DTLbarchartlength + \dtlsub{\dtl@extent}{\DTLbarmax}{\DTLnegextent}% + \dtldiv{\dtl@unit}{\number\@dtl@tmpcount}{\dtl@extent}% % \end{macrocode} -% Do the pie chart +% Construct $y$ tick list if required % \begin{macrocode} -\begin{tikzpicture} -\DTLpieatbegintikz -\@sDTLforeach[#1]{#3}{#4}{% + \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{% + \dtlround{\dtl@thislabel}{\dtl@thislabel} + {\c@DTLbarroundvar}% + \ifDTLverticalbars + \settowidth{\dtl@tmplength}{% + \DTLbardisplayYticklabel{\dtl@thislabel}}% + \else + \settoheight{\dtl@tmplength}{% + \DTLbardisplayYticklabel{\dtl@thislabel}}% + \edef\@dtl@h{\the\dtl@tmplength}% + \settodepth{\dtl@tmplength}{% + \DTLbardisplayYticklabel{\dtl@thislabel}}% + \addtolength{\dtl@tmplength}{\@dtl@h}% + \addtolength{\dtl@tmplength}{\baselineskip}% + \fi + \ifdim\dtl@tmplength>\dtl@yticlabelwidth + \setlength{\dtl@yticlabelwidth}{\dtl@tmplength}% + \fi + }% + \else + \@for\dtl@thislabel:=\dtlbar@yticlabels\do{% + \ifDTLverticalbars + \settowidth{\dtl@tmplength}{% + \DTLbardisplayYticklabel{\dtl@thislabel}}% + \else + \settoheight{\dtl@tmplength}{% + \DTLbardisplayYticklabel{\dtl@thislabel}}% + \edef\@dtl@h{\the\dtl@tmplength}% + \settodepth{\dtl@tmplength}{% + \DTLbardisplayYticklabel{\dtl@thislabel}}% + \addtolength{\dtl@tmplength}{\@dtl@h}% + \addtolength{\dtl@tmplength}{\baselineskip}% + \fi + \ifdim\dtl@tmplength>\dtl@yticlabelwidth + \setlength{\dtl@yticlabelwidth}{\dtl@tmplength}% + \fi + }% + \fi + \fi + \fi % \end{macrocode} -% Store the segment number in \cs{@dtl@seg} +% Calculate the offset for the lower label and number of labels % \begin{macrocode} -\expandafter\@dtl@seg\expandafter= -\csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname% +\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} -% Set the start angle. +% Calculate number of bars per group % \begin{macrocode} -\edef\dtl@start{\csname dtl@sang@\romannumeral\@dtl@seg\endcsname}% +\@dtl@tmpcount=0\relax +\@for\dtl@this:=\dtlbar@variables\do{% + \advance\@dtl@tmpcount by 1\relax +}% +\edef\DTLbargroupwidth{\number\@dtl@tmpcount}% % \end{macrocode} -% Set the extent +% Compute the total width of the bar chart (in terms of +% the $x$ unit vector.) % \begin{macrocode} -\edef\dtl@extent{\csname dtl@angle@\romannumeral\@dtl@seg\endcsname}% +\edef\dtl@n{\expandafter\number\csname dtlrows@#3\endcsname} +\dtlmul{\dtl@tmpi}{\dtl@n}{\DTLbargroupwidth} +\dtlsub{\dtl@tmpii}{\dtl@n}{1}% +\dtlmul{\dtl@tmpii}{\dtl@tmpii}{\dtlbar@groupgap}% +\dtladd{\DTLbarchartwidth}{\dtl@tmpi}{\dtl@tmpii} % \end{macrocode} -% Compute the end angle +% Do the bar chart % \begin{macrocode} -\FPadd{\dtl@endangle}{\dtl@start}{\dtl@extent}% +\begin{tikzpicture} % \end{macrocode} -% Compute the shift. +% Set unit vectors % \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 +\ifDTLverticalbars + \pgfsetyvec{\pgfpoint{0pt}{\dtl@unit sp}}% + \pgfsetxvec{\pgfpoint{\DTLbarwidth}{0pt}}% +\else + \pgfsetxvec{\pgfpoint{\dtl@unit sp}{0pt}}% + \pgfsetyvec{\pgfpoint{0pt}{\DTLbarwidth}}% \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 hook % \begin{macrocode} -\FPmul{\dtl@angle}{\dtl@extent}{0.5}% -\FPadd{\dtl@midangle}{\dtl@angle}{\dtl@start}% +\DTLbaratbegintikz % \end{macrocode} -% Draw the segment. +% Initialise % \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; +\def\@dtl@start{0}% % \end{macrocode} -% Draw the outline if required: +% Iterate through data % \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 +\@sDTLforeach[#1]{#3}{#4}{% % \end{macrocode} -% Convert decimal to an integer +% Store the bar number in \cs{@dtl@bar} % \begin{macrocode} -\dtl@truncatedecimal\dtl@midangle +\@dtl@barcount = 1\relax % \end{macrocode} -% Determine whether to rotate inner labels +% Set the multibar label lists % \begin{macrocode} -\ifDTLrotateinner +\let\dtl@multibar@labels=\dtl@multibarlabels +\let\dtl@uppermultibar@labels=\dtl@uppermultibarlabels % \end{macrocode} -% If the mid way angle is between 90 and 270, the text will look -% upside-down, so adjust accordingly. +% Compute mid point over group % \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}% -}% +\dtlmul{\dtl@multimidpt}{\DTLbargroupwidth}{0.5}% +\dtladd{\dtl@multimidpt}{\dtl@multimidpt}{\@dtl@start}% % \end{macrocode} -% Don't rotate inner labels +% Iterate through each variable % \begin{macrocode} -\else - \edef\dtl@innernodeopt{anchor=center}% -\fi +\@for\DTLbarvariable:=\dtlbar@variables\do{% % \end{macrocode} -% Determine whether to rotate outer labels +% Set end point % \begin{macrocode} -\ifDTLrotateouter +\dtladd{\@dtl@endpt}{\@dtl@start}{1}% % \end{macrocode} -% If the mid way angle is between 90 and 270, the text will look -% upside-down, so adjust accordingly. +% Convert variable to decimal % \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}% -}% +\expandafter\DTLconverttodecimal\expandafter + {\DTLbarvariable}{\dtl@variable}% % \end{macrocode} -% Don't rotate outer labels +% Get the current lower label: % \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 +\dtl@chopfirst\dtl@multibar@labels\dtl@thisbarlabel\dtl@rest +\let\dtl@multibar@labels=\dtl@rest % \end{macrocode} -% Draw inner and outer labels +% Get the current upper label: % \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 -}} +\dtl@chopfirst\dtl@uppermultibar@labels\dtl@thisupperbarlabel\dtl@rest +\let\dtl@uppermultibar@labels=\dtl@rest % \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). +% Draw bars % \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}% -} +\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} -%\end{macro} -% -% Set the offset angles. -%\begin{macro}{\@dtl@set@off} +% Draw outline % \begin{macrocode} -\def\@dtl@set@off#1-#2\relax{% -\ifthenelse{\equal{#2}{}}{% -\@@dtl@set@off{#1}}{% -\@@dtl@set@offr#1-#2\relax}% -} +\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} -%\end{macro} -% Set offset for individual segment: -%\begin{macro}{\@@dtl@set@off} +% Calculate mid point % \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} -} +\dtladd{\@dtl@midpt}{\@dtl@start}{0.5}% % \end{macrocode} -%\end{macro} -% Define count register to keep track of segments -%\begin{macro}{\@dtl@seg} +% Draw lower $x$ labels % \begin{macrocode} -\newcount\@dtl@seg +\ifDTLverticalbars + \edef\dtl@textopt{% + at={\noexpand\pgfpointadd + {\noexpand\pgfpointxy{\@dtl@midpt}{0}} + {\noexpand\pgfpoint{0pt}{-\noexpand\DTLbarlabeloffset}}}, + \DTLbarXlabelalign + }% + \edef\DTLstartpt{\noexpand\pgfpointxy{\@dtl@midpt}{0}}% +\else + \edef\dtl@textopt{% + at={\noexpand\pgfpointadd + {\noexpand\pgfpointxy{0}{\@dtl@midpt}} + {\noexpand\pgfpoint{-\noexpand\DTLbarlabeloffset}{0pt}}}, + \DTLbarXlabelalign + }% + \edef\DTLstartpt{\noexpand\pgfpointxy{0}{\@dtl@midpt}}% +\fi + \expandafter\pgftext\expandafter[\dtl@textopt]{% + \DTLdisplaylowermultibarlabel{\dtl@thisbarlabel}} % \end{macrocode} -%\end{macro} -%\begin{macro}{\@@dtl@setoffr} -% Set offset for a range of segments +% Draw upper $x$ labels % \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}% +\ifDTLverticalbars + \expandafter\DTLifnumlt\expandafter{\DTLbarvariable}{0} + { + \edef\dtl@textopt{% + at={\noexpand\pgfpointadd + {\noexpand\pgfpointxy{\@dtl@midpt}{\dtl@variable}} + {\noexpand\pgfpoint{0pt}{-\noexpand\DTLbarlabeloffset}}} + }% + }{% + \edef\dtl@textopt{% + at={\noexpand\pgfpointadd + {\noexpand\pgfpointxy{\@dtl@midpt}{\dtl@variable}} + {\noexpand\pgfpoint{0pt}{\noexpand\DTLbarlabeloffset}}} + }% + } + \edef\DTLendpt{\noexpand\pgfpointxy{\@dtl@midpt}{\dtl@variable}}% \else - \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 - }% + \expandafter\DTLifnumlt\expandafter{\DTLbarvariable}{0} + { + \edef\dtl@textopt{right, + at={\noexpand\pgfpointadd + {\noexpand\pgfpointxy{\dtl@variable}{\@dtl@midpt}} + {\noexpand\pgfpoint{-\noexpand\DTLbarlabeloffset}{0pt}}} + }% + }{% + \edef\dtl@textopt{left, + at={\noexpand\pgfpointadd + {\noexpand\pgfpointxy{\dtl@variable}{\@dtl@midpt}} + {\noexpand\pgfpoint{\noexpand\DTLbarlabeloffset}{0pt}}} + }% + } + \edef\DTLendpt{\noexpand\pgfpointxy{\dtl@variable}{\@dtl@midpt}}% \fi -} + \expandafter\pgftext\expandafter[\dtl@textopt]{% + \DTLdisplayuppermultibarlabel{\dtl@thisupperbarlabel}} % \end{macrocode} -%\end{macro} -%\iffalse +% Set the mid point % \begin{macrocode} -% +\def\DTLmidpt{\pgfpointlineattime{0.5}{\DTLstartpt}{\DTLendpt}}% % \end{macrocode} -%\fi -%\iffalse +% Do every bar hook +%\changes{2.0}{2009 February 27}{added \cs{DTLeverybarhook}}% % \begin{macrocode} -%<*dataplot.sty> +\DTLeverybarhook % \end{macrocode} -%\fi -%\section{dataplot.sty} -% Declare package: +% End of loop increment loop variables % \begin{macrocode} -\NeedsTeXFormat{LaTeX2e} -\ProvidesPackage{dataplot}[2009/10/22 v2.01 (NLCT)] -% \end{macrocode} -% Required packages + \dtladd{\@dtl@start}{\@dtl@start}{1}% + \advance\@dtl@barcount by 1\relax +}% +% Draw lower group $x$ labels % \begin{macrocode} -\RequirePackage{xkeyval} -\RequirePackage{tikz} -\RequirePackage{datatool} +\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} -% Load TikZ plot libraries +% Increment starting position by \cs{dtlbar@groupgap} % \begin{macrocode} -\usetikzlibrary{plotmarks} -\usetikzlibrary{plothandlers} + \dtladd{\@dtl@start}{\@dtl@start}{\dtlbar@groupgap}% +} % \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}} +% Draw $x$ axis % \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}. +\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} -\newcommand*{\DTLplotmarks}{% - \pgfuseplotmark{o},% - \pgfuseplotmark{x},% - \pgfuseplotmark{+},% - \pgfuseplotmark{square},% - \pgfuseplotmark{triangle},% - \pgfuseplotmark{diamond},% - \pgfuseplotmark{pentagon},% - \pgfuseplotmark{asterisk},% - \pgfuseplotmark{star}% -} +\ifDTLbaryaxis + \ifDTLverticalbars + \expandafter\draw\expandafter[\DTLBarYAxisStyle] + (0,\DTLnegextent) -- (0,\DTLbarmax); + \else + \expandafter\draw\expandafter[\DTLBarYAxisStyle] + (\DTLnegextent,0) -- (\DTLbarmax,0); + \fi +\fi % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\DTLplotmarkcolors} -%\cs{DTLplotmarkcolors} contains a list of the plot mark colours. +% Plot $y$ tick marks if required % \begin{macrocode} -\newcommand*{\DTLplotmarkcolors}{% - red,% - green,% - blue,% - yellow,% - magenta,% - cyan,% - orange,% - black,% - gray} +\ifx\dtlbar@yticlist\relax +\else + \@for\dtl@thistick:=\dtlbar@yticlist\do{% + \ifDTLverticalbars + \pgfpathmoveto{\pgfpointxy{0}{\dtl@thistick}} + \pgfpathlineto{ + \pgfpointadd{\pgfpointxy{0}{\dtl@thistick}} + {\pgfpoint{-\DTLticklength}{0pt}}} + \else + \pgfpathmoveto{\pgfpointxy{\dtl@thistick}{0}} + \pgfpathlineto{ + \pgfpointadd{\pgfpointxy{\dtl@thistick}{0}} + {\pgfpoint{0pt}{-\DTLticklength}}} + \fi + \pgfusepath{stroke} + \ifx\dtlbar@yticlabels\relax + \dtlround{\dtl@thislabel}{\dtl@thistick} + {\c@DTLbarroundvar}% + \else + \dtl@chopfirst\dtlbar@yticlabels\dtl@thislabel\dtl@rest + \let\dtlbar@yticlabels=\dtl@rest + \fi + \ifDTLverticalbars + \edef\dtl@textopt{\DTLbarYticklabelalign,% + at={\noexpand\pgfpointadd + {\noexpand\pgfpointxy{0}{\dtl@thistick}} + {\noexpand\pgfpoint{-\noexpand\DTLticklabeloffset}{0pt}}, + }}% + \else + \edef\dtl@textopt{\DTLbarYticklabelalign, + at={\noexpand\pgfpointadd + {\noexpand\pgfpointxy{\dtl@thistick}{0}} + {\noexpand\pgfpoint{0pt}{-\noexpand\DTLticklabeloffset}} + }}% + \fi + \expandafter\pgftext\expandafter[\dtl@textopt]{% + \DTLbardisplayYticklabel{\dtl@thislabel}} + }% +\fi % \end{macrocode} -%\end{macro} -%\begin{macro}{\DTLplotlines} -%\cs{DTLplotlines} contains a list of dash patterns used by -%\cs{DLTplot}. -%\changes{1.03}{2009 January 27}{fixed error in solid line setting} +% Plot the $y$ label if required % \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},% -} +\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} -%\end{macro} -%\begin{macro}{\DTLplotlinecolors} -%\cs{DTLplotlinecolors} contains a list of the plot line colours. +% Finish bar chart % \begin{macrocode} -\newcommand*{\DTLplotlinecolors}{% - red,% - green,% - blue,% - yellow,% - magenta,% - cyan,% - orange,% - black,% - gray} +\DTLbaratendtikz +\end{tikzpicture} +\fi +}} % \end{macrocode} %\end{macro} -% -%\begin{macro}{\DTLplotwidth} -% The default total plot width is stored in the length -% \cs{dtlplotwidth} +%\iffalse % \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} +%\fi +%\iffalse % \begin{macrocode} -\newlength\DTLplotheight -\setlength\DTLplotheight{4in} +%<*datapie.sty> % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\DTLticklength} -% The length of the tick marks is given by \cs{DTLticklength} +%\fi +%\chapter{datapie.sty} +% Declare package: % \begin{macrocode} -\newlength\DTLticklength -\setlength\DTLticklength{5pt} +\NeedsTeXFormat{LaTeX2e} +\ProvidesPackage{datapie}[2012/07/18 v2.10 (NLCT)] % \end{macrocode} -%\end{macro} -%\begin{macro}{\DTLminorticklength} -% The length of the minor tick marks is given by -% \cs{DTLminorticklength}. +% Require \sty{xkeyval} package % \begin{macrocode} -\newlength\DTLminorticklength -\setlength\DTLminorticklength{2pt} +\RequirePackage{xkeyval} % \end{macrocode} -%\end{macro} -%\begin{macro}{\DTLticklabeloffset} -% The offset from the axis to the tick label is given by -% \cs{DTLticklabeloffset}. +%\begin{macro}{\ifDTLcolorpiechart} +% The conditional \cs{ifDTLcolorpiechart} is to determine +% whether to use colour or grey scale. % \begin{macrocode} -\newlength\DTLticklabeloffset -\setlength\DTLticklabeloffset{8pt} +\newif\ifDTLcolorpiechart +\DTLcolorpiecharttrue % \end{macrocode} %\end{macro} -%\begin{macro}{\dtl@xticlabelheight} -% \cs{dtl@xticlabelheight} is used to store the height of -% the $x$ tick labels. +% Package options to change the conditional: % \begin{macrocode} -\newlength\dtl@xticlabelheight +\DeclareOption{color}{\DTLcolorpiecharttrue} +\DeclareOption{gray}{\DTLcolorpiechartfalse} % \end{macrocode} -%\end{macro} -%\begin{macro}{\dtl@yticlabelwidth} -% \cs{dtl@yticlabelwidth} is used to store the width of -% the $y$ tick labels. +%\begin{macro}{\ifDTLrotateinner} +% Define boolean keys to govern label rotations. % \begin{macrocode} -\newlength\dtl@yticlabelwidth +\define@boolkey{datapie}[DTL]{rotateinner}[true]{} % \end{macrocode} %\end{macro} -%\begin{macro}{\DTLmintickgap} -% \cs{DTLmintickgap} stores the suggested minimum distance between -% tick marks where the gap is not specified. +%\begin{macro}{\ifDTLrotateouter} % \begin{macrocode} -\newlength\DTLmintickgap -\setlength\DTLmintickgap{20pt} +\define@boolkey{datapie}[DTL]{rotateouter}[true]{} % \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}. +% Set defaults: % \begin{macrocode} -\newlength\DTLminminortickgap -\setlength\DTLminminortickgap{5pt} +\DTLrotateinnerfalse +\DTLrotateouterfalse % \end{macrocode} -%\end{macro} -%\begin{counter}{DTLplotroundvar} -% Round $x$ tick labels to the number of digits given by -% the counter \ctrfmt{DTLplotroundXvar}. +% Package options to change \cs{DTLrotateinner} % \begin{macrocode} -\newcounter{DTLplotroundXvar} -\setcounter{DTLplotroundXvar}{2} +\DeclareOption{rotateinner}{\DTLrotateinnertrue} +\DeclareOption{norotateinner}{\DTLrotateinnerfalse} % \end{macrocode} -%\end{counter} -%\begin{counter}{DTLplotroundYvar} -% Round $y$ tick labels to the number of digits given by -% the counter \ctrfmt{DTLplotroundYvar}. +% Package options to change \cs{DTLrotateouter} % \begin{macrocode} -\newcounter{DTLplotroundYvar} -\setcounter{DTLplotroundYvar}{2} +\DeclareOption{rotateouter}{\DTLrotateoutertrue} +\DeclareOption{norotateouter}{\DTLrotateouterfalse} % \end{macrocode} -%\end{counter} -%\begin{macro}{\ifDTLxaxis} -% The conditional \cs {ifDTLxaxis} is used to determine whether or -% not to display the $x$ axis. +% Process options: % \begin{macrocode} -\newif\ifDTLxaxis -\DTLxaxistrue +\ProcessOptions % \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. +% Required packages: % \begin{macrocode} -\newcommand*{\DTLXAxisStyle}{-} +\RequirePackage{datatool} +\RequirePackage{tikz} % \end{macrocode} -%\end{macro} +% Define some variables that govern the appearance of the pie +% chart. % -%\begin{macro}{\ifDTLyaxis} -% The conditional \cs{ifDTLyaxis} is used to determine whether or -% not to display the $y$ axis +%\begin{macro}{\DTLradius} +% The radius of the pie chart is given by \cs{DTLradius}. % \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}{-} +\newlength\DTLradius +\DTLradius=2cm % \end{macrocode} %\end{macro} -%\begin{macro}{\DTLmajorgridstyle} -% The style of the major grid lines is given by -% \cs{DTLmajorgridstyle}. +%\begin{macro}{\DTLinnerratio} +% The inner label offset ratio is given by \cs{DTLinnerratio} % \begin{macrocode} -\newcommand*{\DTLmajorgridstyle}{color=gray,-} +\newcommand*{\DTLinnerratio}{0.5} % \end{macrocode} %\end{macro} -%\begin{macro}{\DTLminorgridstyle} -% The style of the minor grid lines is given by -% \cs{DTLminorgridstyle}. +%\begin{macro}{\DTLouterratio} +% The outer label offset ratio is given by \cs{DTLouterratio}. % \begin{macrocode} -\newcommand*{\DTLminorgridstyle}{color=gray,loosely dotted} +\newcommand*{\DTLouterratio}{1.25} % \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{macro}{\DTLcutawayratio} +% The cutaway offset ratio is given by \cs{DTLcutawayratio}. % \begin{macrocode} -\newif\ifDTLxticsin -\DTLxticsintrue +\newcommand*\DTLcutawayratio{0.2} % \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{macro}{\DTLstartangle} +% The angle of the first segment is given by \cs{DTLstartangle}. % \begin{macrocode} -\newif\ifDTLyticsin -\DTLyticsintrue +\newcommand*{\DTLstartangle}{0} % \end{macrocode} %\end{macro} -%\begin{macro}{\dtl@legendsetting} -% The legend setting is stored in the count register -% \cs{dtl@legendsetting}. +%\begin{macro}{\dtl@inneroffset} % \begin{macrocode} -\newcount\dtl@legendsetting +\newlength\dtl@inneroffset +\dtl@inneroffset=\DTLinnerratio\DTLradius % \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{macro}{\dtl@outeroffset} % \begin{macrocode} -\newlength\DTLlegendxoffset -\setlength\DTLlegendxoffset{10pt} +\newlength\dtl@outeroffset +\dtl@outeroffset=\DTLouterratio\DTLradius % \end{macrocode} %\end{macro} -%\begin{macro}{\DTLlegendyoffset} +%\begin{macro}{\dtl@cutawayoffset} % \begin{macrocode} -\newlength\DTLlegendyoffset -\setlength\DTLlegendyoffset{10pt} +\newlength\dtl@cutawayoffset +\dtl@cutawayoffset=\DTLcutawayratio\DTLradius % \end{macrocode} %\end{macro} -%\begin{macro}{\DTLformatlegend} -%\begin{definition} -%\cs{DTLformatlegend}\marg{legend} -%\end{definition} -% This formats the legend. +% +%\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*{\DTLformatlegend}[1]{% -\setlength{\fboxrule}{1.1pt}% -\fcolorbox{black}{white}{#1}} +\newcommand*{\dtl@piecutaways}{} % \end{macrocode} %\end{macro} -%\begin{macro}{\ifDTLshowmarkers} -% The conditional \cs{ifDTLshowmarkers} is used to specify -% whether or not to use markers. +%\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} -\newif\ifDTLshowmarkers -\DTLshowmarkerstrue +\def\dtl@innerlabel{\DTLpievariable}% % \end{macrocode} %\end{macro} -%\begin{macro}{\ifDTLshowlines} -% The conditional \cs{ifDTLshowlines} is used to specify -% whether or not to use lines. +%\begin{macro}{\dtl@outerlabel} % \begin{macrocode} -\newif\ifDTLshowlines -\DTLshowlinesfalse +\def\dtl@outerlabel{}% % \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{counter}{DTLpieroundvar} +% \ctrfmt{DTLpieroundvar} is a counter governing the number of digits +% to round to when using \cs{FPround}. % \begin{macrocode} -\newcommand*{\DTLplotatbegintikz}{} +\newcounter{DTLpieroundvar} +\setcounter{DTLpieroundvar}{1} % \end{macrocode} -%\end{macro} -%\begin{macro}{\DTLplotatendtikz} -% \cs{DTLplotatendtikz} is a hook to insert stuff at the end -% of the \env{tikzpicture} environment. +%\end{counter} +% +%\begin{macro}{\DTLdisplayinnerlabel} +%\begin{definition} +%\cs{DTLdisplayinnerlabel}\marg{label} +%\end{definition} +% This is used to format the inner label. This just does the +% label by default. % \begin{macrocode} -\newcommand*{\DTLplotatendtikz}{} +\newcommand*{\DTLdisplayinnerlabel}[1]{#1} % \end{macrocode} %\end{macro} % -% Plot settings. The database key for the $x$ value is -% given by the "x" setting: +%\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} -\define@key{dataplot}{x}{% -\def\dtl@xkey{#1}} +\newcommand*{\DTLdisplayouterlabel}[1]{#1} % \end{macrocode} -% The database key for the $y$ value is given by the "y" setting: +%\end{macro} +% +%\begin{macro}{\DTLpiepercent} +%\cs{DTLpiepercent} +% returns the percentage value of the current segment. % \begin{macrocode} -\define@key{dataplot}{y}{% -\def\dtl@ykey{#1}} +\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} -% The list of plot mark colours is given by the "markcolors" setting. -% (This should be a comma separated list of colour names.) +%\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} -\define@key{dataplot}{markcolors}{% -\def\DTLplotmarkcolors{#1}} +\newcommand*{\DTLpieatbegintikz}{} % \end{macrocode} -% The list of plot line colours is given by the "linecolors" setting. -% (This should be a comma separated list of colour names.) +%\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} -\define@key{dataplot}{linecolors}{% -\def\DTLplotlinecolors{#1}} +\newcommand*{\DTLpieatendtikz}{} % \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.) +%\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} -\define@key{dataplot}{colors}{% -\def\DTLplotmarkcolors{#1}% -\def\DTLplotlinecolors{#1}} +\newcommand*{\DTLsetpiesegmentcolor}[2]{% +\expandafter\def\csname dtlpie@segcol\romannumeral#1\endcsname{#2}% +} % \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.) +%\end{macro} +% +%\begin{macro}{\DTLgetpiesegmentcolor} +%\begin{definition} +%\cs{DTLgetpiesegmentcolor}\marg{n} +%\end{definition} +% Get the colour specification for segment \meta{n} % \begin{macrocode} -\define@key{dataplot}{marks}{% -\def\DTLplotmarks{#1}} +\newcommand*{\DTLgetpiesegmentcolor}[1]{% +\csname dtlpie@segcol\romannumeral#1\endcsname} % \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. +%\end{macro} +% +%\begin{macro}{\DTLdopiesegmentcolor} +%\begin{definition} +%\cs{DTLdopiesegmentcolor}\marg{n} +%\end{definition} +% Set the colour to that for segment \meta{n} % \begin{macrocode} -\define@key{dataplot}{lines}{% -\def\DTLplotlines{#1}} +\newcommand*{\DTLdopiesegmentcolor}[1]{% +\expandafter\color\expandafter +{\csname dtlpie@segcol\romannumeral#1\endcsname}} % \end{macrocode} -% The total width of the plot is given by the "width" setting. +%\end{macro} +%\begin{macro}{\DTLdocurrentpiesegmentcolor} +%\cs{DTLdocurrentpiesegmentcolor} +% sets the colour to that of the current segment. % \begin{macrocode} -\define@key{dataplot}{width}{% -\setlength\DTLplotwidth{#1}} +\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} -% The total height of the plot is given by the "height" setting. +%\end{macro} +% +%\begin{macro}{\DTLpieoutlinecolor} +%\cs{DTLpieoutlinecolor} specifies what colour to draw the +% outline. % \begin{macrocode} -\define@key{dataplot}{height}{% -\setlength\DTLplotheight{#1}} +\newcommand*{\DTLpieoutlinecolor}{black} % \end{macrocode} -% Determine whether to show lines, markers or both +%\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} -\define@choicekey{dataplot}{style}[\val\nr]{both,lines,markers}{% -\ifcase\nr\relax - \DTLshowlinestrue - \DTLshowmarkerstrue -\or - \DTLshowlinestrue - \DTLshowmarkersfalse -\or - \DTLshowmarkerstrue - \DTLshowlinesfalse -\fi} +\newlength\DTLpieoutlinewidth +\DTLpieoutlinewidth=0pt % \end{macrocode} -% Determine whether or not to display the axes +%\end{macro} +% +% Set the default colours. If there are more than eight segments, +% more colours will need to be defined. % \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 +\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} -%\begin{macro}{\ifDTLbox} -% Enclose plot in a box +% Define keys for \cs{DTLpiechart} optional argument. +% Set the starting angle of the first segment. % \begin{macrocode} -\define@boolkey{dataplot}[DTL]{box}[true]{} -\DTLboxfalse +\define@key{datapie}{start}{\def\DTLstartangle{#1}} % \end{macrocode} -%\end{macro} -%\begin{macro}{\ifDTLxticstrue} -% Condition to determine whether to show the $x$ tick marks +% Set the radius of the pie chart (must be set prior to +% inneroffset and outeroffset keys.) % \begin{macrocode} -\define@boolkey{dataplot}[DTL]{xtics}[true]{} -\DTLxticstrue +\define@key{datapie}{radius}{\DTLradius=#1\relax +\dtl@inneroffset=\DTLinnerratio\DTLradius +\dtl@outeroffset=\DTLouterratio\DTLradius +\dtl@cutawayoffset=\DTLcutawayratio\DTLradius} % \end{macrocode} -%\end{macro} -%\begin{macro}{\ifDTLyticstrue} -% Condition to determine whether to show the $y$ tick marks +% Set the inner ratio. % \begin{macrocode} -\define@boolkey{dataplot}[DTL]{ytics}[true]{} -\DTLyticstrue +\define@key{datapie}{innerratio}{% +\def\DTLinnerratio{#1}% +\dtl@inneroffset=\DTLinnerratio\DTLradius} % \end{macrocode} -%\end{macro} -%\begin{macro}{\ifDTLxminortics} -% Condition to determine whether to show the $x$ minor tick marks +% Set the outer ratio % \begin{macrocode} -\define@boolkey{dataplot}[DTL]{xminortics}[true]{% -\ifDTLxminortics \DTLxticstrue\fi} -\DTLxminorticsfalse +\define@key{datapie}{outerratio}{% +\def\DTLouterratio{#1}% +\dtl@outeroffset=\DTLouterratio\DTLradius} % \end{macrocode} -%\end{macro} -%\begin{macro}{\ifDTLyminortics} -% Condition to determine whether to show the $y$ minor tick marks +% The cutaway offset ratio % \begin{macrocode} -\define@boolkey{dataplot}[DTL]{yminortics}[true]{% -\ifDTLyminortics \DTLyticstrue\fi} -\DTLyminorticsfalse +\define@key{datapie}{cutawayratio}{% +\def\DTLcutawayratio{#1}% +\dtl@cutawayoffset=\DTLcutawayratio\DTLradius} % \end{macrocode} -%\end{macro} -%\begin{macro}{\ifDTLgrid} -% Determine whether to draw the grid +% Set the inner offset as an absolute value (not dependent +% on the radius.) % \begin{macrocode} -\define@boolkey{dataplot}[DTL]{grid}[true]{} +\define@key{datapie}{inneroffset}{% +\dtl@inneroffset=#1} % \end{macrocode} -%\end{macro} -% Determine whether the $x$ tick marks should point -% in or out: +% Set the outer offset as an absolute value (not dependent +% on the radius.) % \begin{macrocode} -\define@choicekey{dataplot}{xticdir}[\val\nr]{in,out}{% -\ifcase\nr\relax - \DTLxticsintrue -\or - \DTLxticsinfalse -\fi -} +\define@key{datapie}{outeroffset}{% +\dtl@outeroffset=#1} % \end{macrocode} -% Determine whether the $y$ tick marks should point -% in or out: +% Set the cutaway offset as an absolute value (not dependent +% on the radius.) % \begin{macrocode} -\define@choicekey{dataplot}{yticdir}[\val\nr]{in,out}{% -\ifcase\nr\relax - \DTLyticsintrue -\or - \DTLyticsinfalse -\fi -} +\define@key{datapie}{cutawayoffset}{% +\dtl@cutawayoffset=#1} % \end{macrocode} -% Determine whether the $x$ and $y$ tick marks should point -% in or out; +% List of cut away segments. % \begin{macrocode} -\define@choicekey{dataplot}{ticdir}[\val\nr]{in,out}{% -\ifcase\nr\relax - \DTLxticsintrue - \DTLyticsintrue -\or - \DTLxticsinfalse - \DTLyticsinfalse -\fi -} +\define@key{datapie}{cutaway}{% +\renewcommand*{\dtl@piecutaways}{#1}} % \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.) +% Variable used to create the pie chart. (Must be a control +% sequence.) % \begin{macrocode} -\define@key{dataplot}{bounds}{% -\def\dtl@bounds{#1}} -\let\dtl@bounds=\relax +\define@key{datapie}{variable}{% +\def\DTLpievariable{#1}} % \end{macrocode} -% Set only the lower $x$ bound +% Inner label % \begin{macrocode} -\define@key{dataplot}{minx}{% -\def\dtl@minx{#1}} -\let\dtl@minx=\relax +\define@key{datapie}{innerlabel}{% +\def\dtl@innerlabel{#1}} % \end{macrocode} -% Set only the upper $x$ bound: +% Outer label % \begin{macrocode} -\define@key{dataplot}{maxx}{% -\def\dtl@maxx{#1}} -\let\dtl@maxx=\relax +\define@key{datapie}{outerlabel}{% +\def\dtl@outerlabel{#1}} % \end{macrocode} -% Set only the lower $y$ bound: +% +%\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} -\define@key{dataplot}{miny}{% -\def\dtl@miny{#1}} -\let\dtl@miny=\relax +\newcommand*{\DTLpiechart}[4][\boolean{true}]{% +{\let\DTLpievariable=\relax +\setkeys{datapie}{#2}% +\ifx\DTLpievariable\relax + \PackageError{datapie}{\string\DTLpiechart\space missing variable}{}% +\else % \end{macrocode} -% Set only the upper $y$ bound: +% Compute the total. +%\changes{1.01}{2007 Aug 17}{uses \cs{@sDTLforeach} instead of +%\cs{DTLforeach}} % \begin{macrocode} -\define@key{dataplot}{maxy}{% -\def\dtl@maxy{#1}} -\let\dtl@maxy=\relax +\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} -% Define list of points for $x$ ticks. (Must be a comma separated -% list of decimal numbers.) +% Compute the angles % \begin{macrocode} -\define@key{dataplot}{xticpoints}{% -\def\dtl@xticlist{#1}\DTLxticstrue\DTLxaxistrue} -\let\dtl@xticlist=\relax +\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} -% Define list of points for $y$ ticks. (Must be a comma separated -% list of decimal numbers.) +% Compute the offsets for each cut away segment % \begin{macrocode} -\define@key{dataplot}{yticpoints}{% -\def\dtl@yticlist{#1}\DTLyticstrue\DTLyaxistrue} -\let\dtl@yticlist=\relax +\@for\dtl@row:=\dtl@piecutaways\do{% +\expandafter\@dtl@set@off\dtl@row-\relax +}% % \end{macrocode} -% Define a the gap between $x$ tick marks (xticpoints overrides -% xticgap) +% Set the starting angle % \begin{macrocode} -\define@key{dataplot}{xticgap}{\def\dtl@xticgap{#1}% -\DTLxticstrue\DTLxaxistrue} -\let\dtl@xticgap=\relax +\let\dtl@start=\DTLstartangle % \end{macrocode} -% Define a the gap between $y$ tick marks (yticpoints overrides -% yticgap) +% Do the pie chart % \begin{macrocode} -\define@key{dataplot}{yticgap}{\def\dtl@yticgap{#1}% -\DTLyticstrue\DTLyaxistrue} -\let\dtl@yticgap=\relax +\begin{tikzpicture} +\DTLpieatbegintikz +\@sDTLforeach[#1]{#3}{#4}{% % \end{macrocode} -% Define comma separated list of labels for $x$ ticks. +% Store the segment number in \cs{@dtl@seg} % \begin{macrocode} -\define@key{dataplot}{xticlabels}{% -\def\dtl@xticlabels{#1}\DTLxticstrue\DTLxaxistrue} -\let\dtl@xticlabels=\relax +\expandafter\@dtl@seg\expandafter= +\csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname% % \end{macrocode} -% Define comma separated list of labels for $y$ ticks. +% Set the start angle. % \begin{macrocode} -\define@key{dataplot}{yticlabels}{% -\def\dtl@yticlabels{#1}\DTLyticstrue\DTLyaxistrue} -\let\dtl@yticlabels=\relax +\edef\dtl@start{\csname dtl@sang@\romannumeral\@dtl@seg\endcsname}% % \end{macrocode} -% Define $x$ axis label +% Set the extent % \begin{macrocode} -\define@key{dataplot}{xlabel}{% -\def\dtl@xlabel{#1}} -\let\dtl@xlabel=\relax +\edef\dtl@extent{\csname dtl@angle@\romannumeral\@dtl@seg\endcsname}% % \end{macrocode} -% Define $y$ axis label +% Compute the end angle % \begin{macrocode} -\define@key{dataplot}{ylabel}{% -\def\dtl@ylabel{#1}} -\let\dtl@ylabel=\relax +\FPadd{\dtl@endangle}{\dtl@start}{\dtl@extent}% % \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}. +% Compute the shift. % \begin{macrocode} -\define@choicekey{dataplot}{legend}[\val\nr]{none,north,northeast,% -east,southeast,south,southwest,west,northwest}[northeast]{% -\dtl@legendsetting=\nr\relax -} +\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} -% Legend labels (comma separated list). If omitted, the database -% name is used. +% Compute the mid way angle. % \begin{macrocode} -\define@key{dataplot}{legendlabels}{\def\dtl@legendlabels{#1}} +\FPmul{\dtl@angle}{\dtl@extent}{0.5}% +\FPadd{\dtl@midangle}{\dtl@angle}{\dtl@start}% % \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}. +% Draw the segment. % \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 +\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} -% If user didn't specified bounds, -% compute the maximum and minimum $x$ and $y$ values over -% all the databases listed. +% Draw the outline if required: % \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 +\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} -% Otherwise extract information from \cs{dtl@bounds} +% Convert decimal to an integer % \begin{macrocode} - \else - \expandafter\dtl@getbounds\dtl@bounds\@nil - \fi +\dtl@truncatedecimal\dtl@midangle % \end{macrocode} -% Determine scaling factors. +% Determine whether to rotate inner labels % \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}% +\ifDTLrotateinner % \end{macrocode} -% If x tics specified, construct a list of x tic points if not -% already specified. +% If the mid way angle is between 90 and 270, the text will look +% upside-down, so adjust accordingly. % \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 +\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} -% Construct a list of $x$ minor tick points if required +% Don't rotate inner labels % \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 +\else + \edef\dtl@innernodeopt{anchor=center}% +\fi % \end{macrocode} -% Determine the height of the $x$ tick labels. +% Determine whether to rotate outer 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 +\ifDTLrotateouter % \end{macrocode} -% If y tics specified, construct a list of y tic points if not -% already specified. +% If the mid way angle is between 90 and 270, the text will look +% upside-down, so adjust accordingly. % \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 +\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} -% Construct a list of $y$ minor tick points if required +% Don't rotate outer labels % \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 +\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} -% Determine the width of the $y$ tick labels. +% Draw inner and outer 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} +\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} -% Set the $x$ and $y$ unit vectors. +%\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} - \pgfsetxvec{\pgfpoint{\dtl@unit@x sp}{0pt}}% - \pgfsetyvec{\pgfpoint{0pt}{\dtl@unit@y sp}}% +\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} -% Add any extra information the user requires +%\end{macro} +% +% Set the offset angles. +%\begin{macro}{\@dtl@set@off} % \begin{macrocode} - \DTLplotatbegintikz +\def\@dtl@set@off#1-#2\relax{% +\ifthenelse{\equal{#2}{}}{% +\@@dtl@set@off{#1}}{% +\@@dtl@set@offr#1-#2\relax}% +} % \end{macrocode} -% Determine whether to put a box around the plot +%\end{macro} +% Set offset for individual segment: +%\begin{macro}{\@@dtl@set@off} % \begin{macrocode} - \ifDTLbox - \draw (\DTLminX,\DTLminY) -- (\DTLmaxX,\DTLminY) -- - (\DTLmaxX,\DTLmaxY) -- (\DTLminX,\DTLmaxY) -- - cycle; - \else +\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} -% Plot $x$ axis if required. +%\end{macro} +% Define count register to keep track of segments +%\begin{macro}{\@dtl@seg} % \begin{macrocode} - \ifDTLxaxis - \expandafter\draw\expandafter[\DTLXAxisStyle] - (\DTLminX,\DTLminY) -- (\DTLmaxX,\DTLminY); - \fi +\newcount\@dtl@seg % \end{macrocode} -% Plot $y$ axis if required. +%\end{macro} +%\begin{macro}{\@@dtl@setoffr} +% Set offset for a range of segments % \begin{macrocode} - \ifDTLyaxis - \expandafter\draw\expandafter[\DTLYAxisStyle] - (\DTLminX,\DTLminY) -- (\DTLminX,\DTLmaxY); - \fi - \fi +\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} -% Plot grid if required +%\end{macro} +%\iffalse % \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. +%\fi +%\iffalse % \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}% +%<*dataplot.sty> % \end{macrocode} -% Plot the tick labels +%\fi +%\chapter{dataplot.sty} +% Declare package: % \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 +\NeedsTeXFormat{LaTeX2e} +\ProvidesPackage{dataplot}[2012/07/18 v2.10 (NLCT)] % \end{macrocode} -% Plot $x$ label if required. +% Required packages % \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 +\RequirePackage{xkeyval} +\RequirePackage{tikz} +\RequirePackage{datatool} % \end{macrocode} -% Plot the $x$ minor ticks if required +% Load TikZ plot libraries % \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 +\usetikzlibrary{plotmarks} +\usetikzlibrary{plothandlers} % \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{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} - \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 +\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} -% Plot $y$ label if required. +%\end{macro} +% +%\begin{macro}{\DTLplotmarks} +%\cs{DTLplotmarks} contains a list of plot marks used by +%\cs{DTLplot}. % \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 +\newcommand*{\DTLplotmarks}{% + \pgfuseplotmark{o},% + \pgfuseplotmark{x},% + \pgfuseplotmark{+},% + \pgfuseplotmark{square},% + \pgfuseplotmark{triangle},% + \pgfuseplotmark{diamond},% + \pgfuseplotmark{pentagon},% + \pgfuseplotmark{asterisk},% + \pgfuseplotmark{star}% +} % \end{macrocode} -% Plot the $y$ minor ticks if required +%\end{macro} +% +%\begin{macro}{\DTLplotmarkcolors} +%\cs{DTLplotmarkcolors} contains a list of the plot mark colours. % \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 +\newcommand*{\DTLplotmarkcolors}{% + red,% + green,% + blue,% + yellow,% + magenta,% + cyan,% + orange,% + black,% + gray} % \end{macrocode} -% Iterate through each database +%\end{macro} +%\begin{macro}{\DTLplotlines} +%\cs{DTLplotlines} contains a list of dash patterns used by +%\cs{DLTplot}. +%\changes{1.03}{2009 January 27}{fixed error in solid line setting} % \begin{macrocode} - \@for\dtl@thisdb:=#2\do{% +\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} -% Get the current plot mark colour. +%\end{macro} +%\begin{macro}{\DTLplotlinecolors} +%\cs{DTLplotlinecolors} contains a list of the plot line colours. % \begin{macrocode} - \ifx\dtl@plotmarkcolorlist\@empty - \let\dtl@plotmarkcolorlist=\DTLplotmarkcolors - \fi - \dtl@chopfirst\dtl@plotmarkcolorlist\dtl@thisplotmarkcolor - \dtl@remainder - \let\dtl@plotmarkcolorlist=\dtl@remainder +\newcommand*{\DTLplotlinecolors}{% + red,% + green,% + blue,% + yellow,% + magenta,% + cyan,% + orange,% + black,% + gray} % \end{macrocode} -% Get the current plot mark, and store in \cs{dtl@mark} +%\end{macro} +% +%\begin{macro}{\DTLplotwidth} +% The default total plot width is stored in the length +% \cs{dtlplotwidth} % \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 +\newlength\DTLplotwidth +\setlength\DTLplotwidth{4in} % \end{macrocode} -% Get the current plot line colour. +%\end{macro} +% +%\begin{macro}{\DTLplotheight} +% The default total plot height is stored in the length +% \cs{dtlplotheight} % \begin{macrocode} - \ifx\dtl@plotlinecolorlist\@empty - \let\dtl@plotlinecolorlist=\DTLplotlinecolors - \fi - \dtl@chopfirst\dtl@plotlinecolorlist\dtl@thisplotlinecolor - \dtl@remainder - \let\dtl@plotlinecolorlist=\dtl@remainder +\newlength\DTLplotheight +\setlength\DTLplotheight{4in} % \end{macrocode} -% Get the current line style, and store in \cs{dtl@linestyle} +%\end{macro} +% +%\begin{macro}{\DTLticklength} +% The length of the tick marks is given by \cs{DTLticklength} % \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 +\newlength\DTLticklength +\setlength\DTLticklength{5pt} % \end{macrocode} -% Append this plot setting to the legend. +%\end{macro} +%\begin{macro}{\DTLminorticklength} +% The length of the minor tick marks is given by +% \cs{DTLminorticklength}. % \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 +\newlength\DTLminorticklength +\setlength\DTLminorticklength{2pt} % \end{macrocode} -% Store stream in \cs{dtl@stream} +%\end{macro} +%\begin{macro}{\DTLticklabeloffset} +% The offset from the axis to the tick label is given by +% \cs{DTLticklabeloffset}. % \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}} +\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} - \@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}% +\newlength\dtl@xticlabelheight % \end{macrocode} -% End plot stream and draw path. +%\end{macro} +%\begin{macro}{\dtl@yticlabelwidth} +% \cs{dtl@yticlabelwidth} is used to store the width of +% the $y$ tick labels. % \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 - }% +\newlength\dtl@yticlabelwidth % \end{macrocode} -% Plot legend if required. +%\end{macro} +%\begin{macro}{\DTLmintickgap} +% \cs{DTLmintickgap} stores the suggested minimum distance between +% tick marks where the gap is not specified. % \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 -}} +\newlength\DTLmintickgap +\setlength\DTLmintickgap{20pt} % \end{macrocode} %\end{macro} -% -%\begin{macro}{\dtl@getbounds} -% Extract bounds: +%\begin{macro}{\DTLminminortickgap} +% The suggested minimum distance between minor tick marks where the +% gap is not specified is given by \cs{DTLminminortickgap}. % \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 -} +\newlength\DTLminminortickgap +\setlength\DTLminminortickgap{5pt} % \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{counter}{DTLplotroundvar} +% Round $x$ tick labels to the number of digits given by +% the counter \ctrfmt{DTLplotroundXvar}. % \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}% -}% -} +\newcounter{DTLplotroundXvar} +\setcounter{DTLplotroundXvar}{2} +% \end{macrocode} +%\end{counter} +%\begin{counter}{DTLplotroundYvar} +% Round $y$ tick labels to the number of digits given by +% the counter \ctrfmt{DTLplotroundYvar}. +% \begin{macrocode} +\newcounter{DTLplotroundYvar} +\setcounter{DTLplotroundYvar}{2} +% \end{macrocode} +%\end{counter} +%\begin{macro}{\ifDTLxaxis} +% The conditional \cs {ifDTLxaxis} is used to determine whether or +% not to display the $x$ axis. +% \begin{macrocode} +\newif\ifDTLxaxis +\DTLxaxistrue % \end{macrocode} %\end{macro} -% -%\begin{macro}{\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{macro}{\DTLXAxisStyle} +% The style of the $x$ axis is given by \cs{DTLXAxisStyle}. This +% is just a solid line by default. % \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@}% -} +\newcommand*{\DTLXAxisStyle}{-} % \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{macro}{\ifDTLyaxis} +% The conditional \cs{ifDTLyaxis} is used to determine whether or +% not to display the $y$ axis % \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 -} +\newif\ifDTLyaxis +\DTLyaxistrue % \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{macro}{\DTLYAxisStyle} +% The style of the $y$ axis is given by \cs{DTLYAxisStyle}. This +% is just a solid line by default. % \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 -} +\newcommand*{\DTLYAxisStyle}{-} % \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{macro}{\DTLmajorgridstyle} +% The style of the major grid lines is given by +% \cs{DTLmajorgridstyle}. % \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}% -}% -} +\newcommand*{\DTLmajorgridstyle}{color=gray,-} % \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{macro}{\DTLminorgridstyle} +% The style of the minor grid lines is given by +% \cs{DTLminorgridstyle}. % \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 -} +\newcommand*{\DTLminorgridstyle}{color=gray,loosely dotted} % \end{macrocode} %\end{macro} -%\iffalse +% +%\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} -%\fi -%\iffalse +%\end{macro} +%\begin{macro}{\ifDTLyticsin} +% The conditional \cs{ifDTLyticsin} is used to determine whether +% the $y$ tics should point in or out. % \begin{macrocode} -%<*databar.sty> +\newif\ifDTLyticsin +\DTLyticsintrue % \end{macrocode} -%\fi -%\section{databar.sty} -% Declare package: +%\end{macro} +%\begin{macro}{\dtl@legendsetting} +% The legend setting is stored in the count register +% \cs{dtl@legendsetting}. % \begin{macrocode} -\NeedsTeXFormat{LaTeX2e} -\ProvidesPackage{databar}[2009/10/22 v2.01 (NLCT)] +\newcount\dtl@legendsetting % \end{macrocode} -% Require \sty{xkeyval} package +%\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} -\RequirePackage{xkeyval} +\newlength\DTLlegendxoffset +\setlength\DTLlegendxoffset{10pt} % \end{macrocode} -% Require \sty{dataplot} package +%\end{macro} +%\begin{macro}{\DTLlegendyoffset} % \begin{macrocode} -\RequirePackage{dataplot} +\newlength\DTLlegendyoffset +\setlength\DTLlegendyoffset{10pt} % \end{macrocode} -%\begin{macro}{\ifDTLcolorbarchart} -% The conditional \cs{ifDTLcolorbarchart} is used to determine -% whether to use colour or grey scale. +%\end{macro} +%\begin{macro}{\DTLformatlegend} +%\begin{definition} +%\cs{DTLformatlegend}\marg{legend} +%\end{definition} +% This formats the legend. % \begin{macrocode} -\newif\ifDTLcolorbarchart -\DTLcolorbarcharttrue +\newcommand*{\DTLformatlegend}[1]{% +\setlength{\fboxrule}{1.1pt}% +\fcolorbox{black}{white}{#1}} % \end{macrocode} %\end{macro} -% Package options to change the conditional: +%\begin{macro}{\ifDTLshowmarkers} +% The conditional \cs{ifDTLshowmarkers} is used to specify +% whether or not to use markers. % \begin{macrocode} -\DeclareOption{color}{\DTLcolorbarcharttrue} -\DeclareOption{gray}{\DTLcolorbarchartfalse} +\newif\ifDTLshowmarkers +\DTLshowmarkerstrue % \end{macrocode} -%\cs{DTLbarXlabelalign} specifies the alignment -% for the $x$ axis labels. +%\end{macro} +%\begin{macro}{\ifDTLshowlines} +% The conditional \cs{ifDTLshowlines} is used to specify +% whether or not to use lines. % \begin{macrocode} -\newcommand*{\DTLbarXlabelalign}{left,rotate=-90} +\newif\ifDTLshowlines +\DTLshowlinesfalse % \end{macrocode} -%\cs{DTLbarYticklabelalign} specifies the alignment -% for the $x$ axis labels. +%\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*{\DTLbarYticklabelalign}{right} +\newcommand*{\DTLplotatbegintikz}{} % \end{macrocode} -%\begin{macro}{\ifDTLverticalbars} -% Define boolean keys to govern bar chart orientation. +%\end{macro} +%\begin{macro}{\DTLplotatendtikz} +% \cs{DTLplotatendtikz} is a hook to insert stuff at the end +% of the \env{tikzpicture} environment. % \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} +\newcommand*{\DTLplotatendtikz}{} % \end{macrocode} %\end{macro} -% Set defaults: +% +% Plot settings. The database key for the $x$ value is +% given by the "x" setting: % \begin{macrocode} -\DTLverticalbarstrue +\define@key{dataplot}{x}{% +\def\dtl@xkey{#1}} % \end{macrocode} -% Package options to change \cs{ifDTLverticalbars} +% The database key for the $y$ value is given by the "y" setting: % \begin{macrocode} -\DeclareOption{vertical}{\DTLverticalbarstrue - \def\DTLbarXlabelalign{left,rotate=-90}% - \def\DTLbarYticklabelalign{right} -} -\DeclareOption{horizontal}{\DTLverticalbarsfalse - \def\DTLbarXlabelalign{right}% - \def\DTLbarYticklabelalign{center} -} +\define@key{dataplot}{y}{% +\def\dtl@ykey{#1}} % \end{macrocode} -% Process options: +% The list of plot mark colours is given by the "markcolors" setting. +% (This should be a comma separated list of colour names.) % \begin{macrocode} -\ProcessOptions +\define@key{dataplot}{markcolors}{% +\def\DTLplotmarkcolors{#1}} % \end{macrocode} -% Required packages: +% The list of plot line colours is given by the "linecolors" setting. +% (This should be a comma separated list of colour names.) % \begin{macrocode} -\RequirePackage{datatool} -\RequirePackage{tikz} +\define@key{dataplot}{linecolors}{% +\def\DTLplotlinecolors{#1}} % \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} +% 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} -\newlength\DTLbarchartlength -\DTLbarchartlength=3in +\define@key{dataplot}{colors}{% +\def\DTLplotmarkcolors{#1}% +\def\DTLplotlinecolors{#1}} % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\DTLbarwidth} -% The width of each bar is given by \cs{DTLbarwidth}. +% 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} -\newlength\DTLbarwidth -\DTLbarwidth=1cm +\define@key{dataplot}{marks}{% +\def\DTLplotmarks{#1}} % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\DTLbarlabeloffset} -% The offset from the $x$ axis to the bar label if given by -% \cs{DTLbarlabeloffset}. +% 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} -\newlength\DTLbarlabeloffset -\setlength\DTLbarlabeloffset{10pt} +\define@key{dataplot}{lines}{% +\def\DTLplotlines{#1}} % \end{macrocode} -%\end{macro} -%\begin{macro}{\DTLBarXAxisStyle} -% The style of the $x$ axis is given by \cs{DTLBarXAxisStyle} +% The total width of the plot is given by the "width" setting. % \begin{macrocode} -\newcommand*{\DTLBarXAxisStyle}{-} +\define@key{dataplot}{width}{% +\setlength\DTLplotwidth{#1}} % \end{macrocode} -%\end{macro} -%\begin{macro}{\DTLBarYAxisStyle} -% The style of the $y$ axis is given by \cs{DTLBarYAxisStyle}. +% The total height of the plot is given by the "height" setting. % \begin{macrocode} -\newcommand*{\DTLBarYAxisStyle}{-} +\define@key{dataplot}{height}{% +\setlength\DTLplotheight{#1}} % \end{macrocode} -%\end{macro} -% -%\begin{counter}{DTLbarroundvar} -% \ctrfmt{DTLbarroundvar} is a counter governing the number of digits -% to round to when using \cs{FPround}. +% Determine whether to show lines, markers or both % \begin{macrocode} -\newcounter{DTLbarroundvar} -\setcounter{DTLbarroundvar}{1} +\define@choicekey{dataplot}{style}[\val\nr]{both,lines,markers}{% +\ifcase\nr\relax + \DTLshowlinestrue + \DTLshowmarkerstrue +\or + \DTLshowlinestrue + \DTLshowmarkersfalse +\or + \DTLshowmarkerstrue + \DTLshowlinesfalse +\fi} % \end{macrocode} -%\end{counter} -% -%\begin{macro}{\DTLbardisplayYticklabel} -%\cs{DTLbardisplayYticklabel} governs how the $y$ tick labels appear. +% Determine whether or not to display the axes % \begin{macrocode} -\newcommand*{\DTLbardisplayYticklabel}[1]{#1} +\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} -%\end{macro} -%\begin{macro}{\DTLdisplaylowerbarlabel} -%\cs{DTLdisplaylowerbarlabel} governs how the lower bar labels appear. +%\begin{macro}{\ifDTLbox} +% Enclose plot in a box % \begin{macrocode} -\newcommand*{\DTLdisplaylowerbarlabel}[1]{#1} +\define@boolkey{dataplot}[DTL]{box}[true]{} +\DTLboxfalse % \end{macrocode} %\end{macro} -%\begin{macro}{\DTLdisplaylowermultibarlabel} -%\cs{DTLdisplaylowermultibarlabel} governs how the lower multi bar labels appear. +%\begin{macro}{\ifDTLxticstrue} +% Condition to determine whether to show the $x$ tick marks % \begin{macrocode} -\newcommand*{\DTLdisplaylowermultibarlabel}[1]{#1} +\define@boolkey{dataplot}[DTL]{xtics}[true]{} +\DTLxticstrue % \end{macrocode} %\end{macro} -%\begin{macro}{\DTLdisplayupperbarlabel} -%\cs{DTLdisplayupperbarlabel} governs how the upper bar labels -% appear. +%\begin{macro}{\ifDTLyticstrue} +% Condition to determine whether to show the $y$ tick marks % \begin{macrocode} -\newcommand*{\DTLdisplayupperbarlabel}[1]{#1} +\define@boolkey{dataplot}[DTL]{ytics}[true]{} +\DTLyticstrue % \end{macrocode} %\end{macro} -%\begin{macro}{\DTLdisplayuppermultibarlabel} -%\cs{DTLdisplayuppermultibarlabel} governs how the upper multi bar -% labels appear. +%\begin{macro}{\ifDTLxminortics} +% Condition to determine whether to show the $x$ minor tick marks % \begin{macrocode} -\newcommand*{\DTLdisplayuppermultibarlabel}[1]{#1} +\define@boolkey{dataplot}[DTL]{xminortics}[true]{% +\ifDTLxminortics \DTLxticstrue\fi} +\DTLxminorticsfalse % \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{macro}{\ifDTLyminortics} +% Condition to determine whether to show the $y$ minor tick marks % \begin{macrocode} -\newcommand*{\DTLbaratbegintikz}{} +\define@boolkey{dataplot}[DTL]{yminortics}[true]{% +\ifDTLyminortics \DTLyticstrue\fi} +\DTLyminorticsfalse % \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{macro}{\ifDTLgrid} +% Determine whether to draw the grid % \begin{macrocode} -\newcommand*{\DTLbaratendtikz}{} +\define@boolkey{dataplot}[DTL]{grid}[true]{} % \end{macrocode} %\end{macro} -% -%\begin{macro}{\ifDTLbarxaxis} -% The conditional \cs{ifDTLbarxaxis} is used to determine -% whether or not to display the $x$ axis +% Determine whether the $x$ tick marks should point +% in or out: % \begin{macrocode} -\newif\ifDTLbarxaxis +\define@choicekey{dataplot}{xticdir}[\val\nr]{in,out}{% +\ifcase\nr\relax + \DTLxticsintrue +\or + \DTLxticsinfalse +\fi +} % \end{macrocode} -%\end{macro} -%\begin{macro}{\ifDTLbaryaxis} -% The conditional \cs{ifDTLbaryaxis} is used to determine -% whether or not to display the $y$ axis. +% Determine whether the $y$ tick marks should point +% in or out: % \begin{macrocode} -\newif\ifDTLbaryaxis +\define@choicekey{dataplot}{yticdir}[\val\nr]{in,out}{% +\ifcase\nr\relax + \DTLyticsintrue +\or + \DTLyticsinfalse +\fi +} % \end{macrocode} -%\end{macro} -%\begin{macro}{\ifDTLbarytics} -% The conditional \cs{ifDTLbarytics} to determine whether -% or not to display the $y$ tick marks. +% Determine whether the $x$ and $y$ tick marks should point +% in or out; % \begin{macrocode} -\newif\ifDTLbarytics +\define@choicekey{dataplot}{ticdir}[\val\nr]{in,out}{% +\ifcase\nr\relax + \DTLxticsintrue + \DTLyticsintrue +\or + \DTLxticsinfalse + \DTLyticsinfalse +\fi +} % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@dtl@barcount} -% The count register \cs{@dtl@barcount} is used to store -% the current bar index. +% 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} -\newcount\@dtl@barcount +\define@key{dataplot}{bounds}{% +\def\dtl@bounds{#1}} +\let\dtl@bounds=\relax % \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. +% Set only the lower $x$ bound % \begin{macrocode} -\newcommand*{\DTLsetbarcolor}[2]{% -\expandafter\def\csname dtlbar@segcol\romannumeral#1\endcsname{#2}% -} +\define@key{dataplot}{minx}{% +\def\dtl@minx{#1}} +\let\dtl@minx=\relax % \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. +% Set only the upper $x$ bound: % \begin{macrocode} -\newcommand*{\DTLgetbarcolor}[1]{% -\csname dtlbar@segcol\romannumeral#1\endcsname} +\define@key{dataplot}{maxx}{% +\def\dtl@maxx{#1}} +\let\dtl@maxx=\relax % \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. +% Set only the lower $y$ bound: % \begin{macrocode} -\newcommand*{\DTLdobarcolor}[1]{% -\expandafter\color\expandafter -{\csname dtlbar@segcol\romannumeral#1\endcsname}} +\define@key{dataplot}{miny}{% +\def\dtl@miny{#1}} +\let\dtl@miny=\relax % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\DTLdocurrentbarcolor} -%\cs{DTLdocurrentbarcolor} -% sets the colour to that of the current bar. +% Set only the upper $y$ bound: % \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} +\define@key{dataplot}{maxy}{% +\def\dtl@maxy{#1}} +\let\dtl@maxy=\relax % \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. +% Define list of points for $x$ ticks. (Must be a comma separated +% list of decimal numbers.) % \begin{macrocode} -\newlength\DTLbaroutlinewidth -\DTLbaroutlinewidth=0pt +\define@key{dataplot}{xticpoints}{% +\def\dtl@xticlist{#1}\DTLxticstrue\DTLxaxistrue} +\let\dtl@xticlist=\relax % \end{macrocode} -%\end{macro} -% -% Set the default colours. If there are more than eight bars, -% more colours will need to be defined. +% Define list of points for $y$ ticks. (Must be a comma separated +% list of decimal numbers.) % \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 +\define@key{dataplot}{yticpoints}{% +\def\dtl@yticlist{#1}\DTLyticstrue\DTLyaxistrue} +\let\dtl@yticlist=\relax % \end{macrocode} -%\begin{macro}{\DTLeverybarhook} -% Code to apply at every bar. The start point of the bar -% can be accessed via \cs{DTLstartpt}, the mid point of the bar -% can be accessed via \cs{DTLmidpt} and the end point of the -% bar can be accessed via \cs{DTLendpt} -%\changes{2.0}{2009 February 27}{new}% +% Define a the gap between $x$ tick marks (xticpoints overrides +% xticgap) % \begin{macrocode} -\newcommand*{\DTLeverybarhook}{} +\define@key{dataplot}{xticgap}{\def\dtl@xticgap{#1}% +\DTLxticstrue\DTLxaxistrue} +\let\dtl@xticgap=\relax % \end{macrocode} -%\end{macro} -% -% Define keys for \cs{DTLbarchart} optional argument. -% Set the maximum value of the $y$ axis. +% Define a the gap between $y$ tick marks (yticpoints overrides +% yticgap) % \begin{macrocode} -\define@key{databar}{max}{\def\DTLbarmax{#1}} +\define@key{dataplot}{yticgap}{\def\dtl@yticgap{#1}% +\DTLyticstrue\DTLyaxistrue} +\let\dtl@yticgap=\relax % \end{macrocode} -% Set the total length of the bar chart +% Define comma separated list of labels for $x$ ticks. % \begin{macrocode} -\define@key{databar}{length}{\DTLbarchartlength=#1\relax -} +\define@key{dataplot}{xticlabels}{% +\def\dtl@xticlabels{#1}\DTLxticstrue\DTLxaxistrue} +\let\dtl@xticlabels=\relax % \end{macrocode} -% Set the maximum depth (negative extent) +% Define comma separated list of labels for $y$ ticks. % \begin{macrocode} -\define@key{databar}{maxdepth}{% -\ifnum#1>0\relax - \PackageError{databar}{depth must be zero or negative}{}% -\else - \def\DTLnegextent{#1}% -\fi} +\define@key{dataplot}{yticlabels}{% +\def\dtl@yticlabels{#1}\DTLyticstrue\DTLyaxistrue} +\let\dtl@yticlabels=\relax % \end{macrocode} -% Determine which axes should be shown +% Define $x$ axis label % \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 -} +\define@key{dataplot}{xlabel}{% +\def\dtl@xlabel{#1}} +\let\dtl@xlabel=\relax % \end{macrocode} -% Variable used to create the bar chart. (Must be a control -% sequence.) +% Define $y$ axis label % \begin{macrocode} -\define@key{databar}{variable}{% -\def\DTLbarvariable{#1}} +\define@key{dataplot}{ylabel}{% +\def\dtl@ylabel{#1}} +\let\dtl@ylabel=\relax % \end{macrocode} -% Variables used to create the multi bar chart. (Must be a -% comma separated list of control sequences.) +% 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@key{databar}{variables}{% -\def\dtlbar@variables{#1}} +\define@choicekey{dataplot}{legend}[\val\nr]{none,north,northeast,% +east,southeast,south,southwest,west,northwest}[northeast]{% +\dtl@legendsetting=\nr\relax +} % \end{macrocode} -% Bar width +% Legend labels (comma separated list). If omitted, the database +% name is used. % \begin{macrocode} -\define@key{databar}{barwidth}{\setlength{\DTLbarwidth}{#1}} +\define@key{dataplot}{legendlabels}{\def\dtl@legendlabels{#1}} % \end{macrocode} -% Lower bar labels +% +%\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} -\define@key{databar}{barlabel}{% -\def\dtl@barlabel{#1}} -\def\dtl@barlabel{} +\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} -% Lower bar labels for multi-bar charts +% If user didn't specified bounds, +% compute the maximum and minimum $x$ and $y$ values over +% all the databases listed. % \begin{macrocode} -\define@key{databar}{multibarlabels}{% -\def\dtl@multibarlabels{#1}} -\def\dtl@multibarlabels{} + \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} -% Gap between groups in multi-bar charts (This should be in $x$ units -% where 1 $x$ unit is the width of a bar.) +% Otherwise extract information from \cs{dtl@bounds} % \begin{macrocode} -\define@key{databar}{groupgap}{\def\dtlbar@groupgap{#1}} -\def\dtlbar@groupgap{1} + \else + \expandafter\dtl@getbounds\dtl@bounds\@nil + \fi % \end{macrocode} -% Upper bar labels +% Determine scaling factors. % \begin{macrocode} -\define@key{databar}{upperbarlabel}{% -\def\dtl@upperbarlabel{#1}} -\def\dtl@upperbarlabel{} + \@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} -% Upper bar labels for multi-bar charts +% If x tics specified, construct a list of x tic points if not +% already specified. % \begin{macrocode} -\define@key{databar}{uppermultibarlabels}{% -\def\dtl@uppermultibarlabels{#1}} -\def\dtl@uppermultibarlabels{} + \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} -% Define list of points for $y$ tics. (Must be a comma separated list -% of decimal numbers.) +% Construct a list of $x$ minor tick points if required % \begin{macrocode} -\define@key{databar}{yticpoints}{% -\def\dtlbar@yticlist{#1}\DTLbaryticstrue\DTLbaryaxistrue} -\let\dtlbar@yticlist=\relax + \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} -% Set the $y$ tick gap: +% Determine the height of the $x$ tick labels. % \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}{You haven't use the "variable" key}% -\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}% + \ifx\dtl@xticlabels\relax + \settoheight{\dtl@xticlabelheight}{\dtl@xticlist}% + \else + \settoheight{\dtl@xticlabelheight}{\dtl@xticlabels}% \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}% + \else + \setlength{\dtl@xticlabelheight}{0pt}% + \fi % \end{macrocode} -% Construct $y$ tick list if required +% If y tics specified, construct a list of y tic points if not +% already specified. % \begin{macrocode} \setlength{\dtl@yticlabelwidth}{0pt}% - \ifDTLbarytics - \ifx\dtlbar@yticlist\relax - \ifx\dtlbar@yticgap\relax - \dtl@constructticklist\DTLnegextent\DTLbarmax - \dtl@unit\dtlbar@yticlist + \ifDTLytics + \ifx\dtl@yticlist\relax + \ifx\dtl@yticgap\relax + \dtl@constructticklist\DTLminY\DTLmaxY + \dtl@unit@y\dtl@yticlist \else - \dtl@constructticklistwithgapz - \DTLnegextent\DTLbarmax\dtlbar@yticlist\dtlbar@yticgap + \DTLifFPopenbetween{0}{\DTLminY}{\DTLmaxY}{% + \dtl@constructticklistwithgapz + \DTLminY\DTLmaxY\dtl@yticlist\dtl@yticgap}{% + \dtl@constructticklistwithgap + \DTLminY\DTLmaxY\dtl@yticlist\dtl@yticgap}% \fi \fi - \ifx\dtlbar@ylabel\relax +% \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\dtlbar@yticlabels\relax - \@for\dtl@thislabel:=\dtlbar@yticlist\do{% + \ifx\dtl@yticlabels\relax + \@for\dtl@thislabel:=\dtl@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 + {\c@DTLplotroundYvar}% + \settowidth{\dtl@tmplength}{\dtl@thislabel}% \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 + \@for\dtl@thislabel:=\dtl@yticlabels\do{% + \settowidth{\dtl@tmplength}{\dtl@thislabel}% \ifdim\dtl@tmplength>\dtl@yticlabelwidth \setlength{\dtl@yticlabelwidth}{\dtl@tmplength}% \fi }% \fi \fi - \fi % \end{macrocode} -% Store the width of the bar chart in \cs{DTLbarchartwidth} +% Start the picture. % \begin{macrocode} -\edef\DTLbarchartwidth{\expandafter\number\csname dtlrows@#3\endcsname} + \begin{tikzpicture} % \end{macrocode} -% Do the bar chart +% Set the $x$ and $y$ unit vectors. % \begin{macrocode} -\begin{tikzpicture} + \pgfsetxvec{\pgfpoint{\dtl@unit@x sp}{0pt}}% + \pgfsetyvec{\pgfpoint{0pt}{\dtl@unit@y sp}}% % \end{macrocode} -% Set unit vectors +% Add any extra information the user requires % \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 + \DTLplotatbegintikz % \end{macrocode} -% Begin hook +% Determine whether to put a box around the plot % \begin{macrocode} -\DTLbaratbegintikz + \ifDTLbox + \draw (\DTLminX,\DTLminY) -- (\DTLmaxX,\DTLminY) -- + (\DTLmaxX,\DTLmaxY) -- (\DTLminX,\DTLmaxY) -- + cycle; + \else % \end{macrocode} -% Initialise +% Plot $x$ axis if required. % \begin{macrocode} -\def\@dtl@start{0}% + \ifDTLxaxis + \expandafter\draw\expandafter[\DTLXAxisStyle] + (\DTLminX,\DTLminY) -- (\DTLmaxX,\DTLminY); + \fi % \end{macrocode} -% Iterate through data +% Plot $y$ axis if required. % \begin{macrocode} -\@sDTLforeach[#1]{#3}{#4}{% + \ifDTLyaxis + \expandafter\draw\expandafter[\DTLYAxisStyle] + (\DTLminX,\DTLminY) -- (\DTLminX,\DTLmaxY); + \fi + \fi % \end{macrocode} -% Store the bar number in \cs{@dtl@bar} +% Plot grid if required % \begin{macrocode} -\expandafter\let\expandafter\@dtl@bar - \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname% + \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} -% Convert variable to decimal +% Plot $x$ tics if required. % \begin{macrocode} -\expandafter\DTLconverttodecimal\expandafter - {\DTLbarvariable}{\dtl@variable}% + \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} -% Draw bars +% Plot the tick labels % \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 - }% + \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} -% Set \cs{DTLstartpt} to the starting point. +% Plot $x$ label if required. % \begin{macrocode} - \edef\DTLstartpt{\noexpand\pgfpointxy{\@dtl@start.5}{0}}% -\else - \edef\dtl@textopt{% - at={\noexpand\pgfpointadd - {\noexpand\pgfpointxy{0}{\@dtl@start.5}} - {\noexpand\pgfpoint{-\noexpand\DTLbarlabeloffset}{0pt}}}, - \DTLbarXlabelalign - }% + \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} -% Set \cs{DTLstartpt} to the starting point. +% Plot the $x$ minor ticks if required % \begin{macrocode} - \edef\DTLstartpt{\noexpand\pgfpointxy{0}{\@dtl@start.5}}% -\fi - \expandafter\pgftext\expandafter[\dtl@textopt]{% - \DTLdisplaylowerbarlabel{\dtl@barlabel}} + \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} -% Draw upper $x$ labels +% Plot $y$ tics if required. % \begin{macrocode} -\ifDTLverticalbars + \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} -% Vertical bars +% Plot the $y$ tick labels if required % \begin{macrocode} - \expandafter\DTLifnumlt\expandafter{\DTLbarvariable}{0} - { - \edef\dtl@textopt{% - at={\noexpand\pgfpointadd - {\noexpand\pgfpointxy{\@dtl@start.5}{\dtl@variable}} - {\noexpand\pgfpoint{0pt}{-\noexpand\DTLbarlabeloffset}}} - }% - }{% - \edef\dtl@textopt{% - at={\noexpand\pgfpointadd - {\noexpand\pgfpointxy{\@dtl@start.5}{\dtl@variable}} - {\noexpand\pgfpoint{0pt}{\noexpand\DTLbarlabeloffset}}} - }% - } + \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} -% Set \cs{DTLendpt} to the end point. +% Plot $y$ label if required. % \begin{macrocode} - \edef\DTLendpt{\noexpand\pgfpointxy{\@dtl@start.5}{\dtl@variable}}% -\else + \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} -% Horizontal bars +% Plot the $y$ minor ticks if required % \begin{macrocode} - \expandafter\DTLifnumlt\expandafter{\DTLbarvariable}{0} - { - \edef\dtl@textopt{right, - at={\noexpand\pgfpointadd - {\noexpand\pgfpointxy{\dtl@variable}{\@dtl@start.5}} - {\noexpand\pgfpoint{-\noexpand\DTLbarlabeloffset}{0pt}}} - }% - }{% - \edef\dtl@textopt{left, - at={\noexpand\pgfpointadd - {\noexpand\pgfpointxy{\dtl@variable}{\@dtl@start.5}} - {\noexpand\pgfpoint{\noexpand\DTLbarlabeloffset}{0pt}}} - }% - } + \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} -% Set \cs{DTLendpt} to the end point. +% Iterate through each database % \begin{macrocode} - \edef\DTLendpt{\noexpand\pgfpointxy{\dtl@variable}{\@dtl@start.5}}% -\fi - \expandafter\pgftext\expandafter[\dtl@textopt]{% - \DTLdisplayupperbarlabel{\dtl@upperbarlabel}} + \@for\dtl@thisdb:=#2\do{% % \end{macrocode} -% Set the mid point +% Get the current plot mark colour. % \begin{macrocode} -\def\DTLmidpt{\pgfpointlineattime{0.5}{\DTLstartpt}{\DTLendpt}}% + \ifx\dtl@plotmarkcolorlist\@empty + \let\dtl@plotmarkcolorlist=\DTLplotmarkcolors + \fi + \dtl@chopfirst\dtl@plotmarkcolorlist\dtl@thisplotmarkcolor + \dtl@remainder + \let\dtl@plotmarkcolorlist=\dtl@remainder % \end{macrocode} -% Do every bar hook -%\changes{2.0}{2009 February 27}{added \cs{DTLeverybarhook}}% +% Get the current plot mark, and store in \cs{dtl@mark} % \begin{macrocode} - \DTLeverybarhook + \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} -% End of loop +% Get the current plot line colour. % \begin{macrocode} - \edef\@dtl@start{\number\@dtl@bar}% -} + \ifx\dtl@plotlinecolorlist\@empty + \let\dtl@plotlinecolorlist=\DTLplotlinecolors + \fi + \dtl@chopfirst\dtl@plotlinecolorlist\dtl@thisplotlinecolor + \dtl@remainder + \let\dtl@plotlinecolorlist=\dtl@remainder % \end{macrocode} -% Draw $x$ axis +% Get the current line style, and store in \cs{dtl@linestyle} % \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 + \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} -\ifDTLbaryaxis - \ifDTLverticalbars - \expandafter\draw\expandafter[\DTLBarYAxisStyle] - (0,\DTLnegextent) -- (0,\DTLbarmax); - \else - \expandafter\draw\expandafter[\DTLBarYAxisStyle] - (\DTLnegextent,0) -- (\DTLbarmax,0); - \fi -\fi + \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} -% Plot $y$ tick marks if required +% Store stream in \cs{dtl@stream} % \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 + \def\dtl@stream{\pgfplotstreamstart}% % \end{macrocode} -% Plot the $y$ label if required +% Only plot points that lie inside bounds. +%\changes{1.01}{2007 Aug 17}{uses \cs{@sDTLforeach} instead of +%\cs{DTLforeach}} % \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} + \@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} -% Finish bar chart +%\end{macro} +% +%\begin{macro}{\dtl@getbounds} +% Extract bounds: % \begin{macrocode} -\DTLbaratendtikz -\end{tikzpicture} +\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}{\DTLmultibarchart} +%\begin{macro}{\dtl@constructticklist} %\begin{definition} -% \cs{DTLmultibarchart}\oarg{conditions}\marg{option list}\marg{db name}\marg{assign list} +%\cs{dtl@constructticklist}\marg{min}\marg{max}\marg{scale factor}\marg{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}} +% Constructs a list of tick points between \meta{min} and \meta{max} +% and store in \meta{list} (a control sequence.) % \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 +\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 -% \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 - }{}% + \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 -% \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}% + \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} -% Calculate number of bars per group +%\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} -\@dtl@tmpcount=0\relax -\@for\dtl@this:=\dtlbar@variables\do{% - \advance\@dtl@tmpcount by 1\relax +\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}% }% -\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} +\expandafter\toks@\expandafter{#2}% +\edef#3{#3,\the\toks@}% +} % \end{macrocode} -% Set unit vectors +%\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} -\ifDTLverticalbars - \pgfsetyvec{\pgfpoint{0pt}{\dtl@unit sp}}% - \pgfsetxvec{\pgfpoint{\DTLbarwidth}{0pt}}% +\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 - \pgfsetxvec{\pgfpoint{\dtl@unit sp}{0pt}}% - \pgfsetyvec{\pgfpoint{0pt}{\DTLbarwidth}}% +\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} -% 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 +%\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} -\let\dtl@multibar@labels=\dtl@multibarlabels -\let\dtl@uppermultibar@labels=\dtl@uppermultibarlabels -% \end{macrocode} -% Compute mid point over group +\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} -\FPmul{\dtl@multimidpt}{\DTLbargroupwidth}{0.5}% -\FPadd{\dtl@multimidpt}{\dtl@multimidpt}{\@dtl@start}% +\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} -% Iterate through each variable +%\end{macro} +% +%\begin{macro}{\DTLaddtoplotlegend} +%\begin{definition} +%\cs{DTLaddtoplotlegend}\marg{marker}\marg{line style}\marg{label} +%\end{definition} +% Adds entry to legend. % \begin{macrocode} -\@for\DTLbarvariable:=\dtlbar@variables\do{% +\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} -% Set end point +%\end{macro} +%\iffalse % \begin{macrocode} -\FPadd{\@dtl@endpt}{\@dtl@start}{1}% +% % \end{macrocode} -% Convert variable to decimal +%\fi +%\iffalse % \begin{macrocode} -\expandafter\DTLconverttodecimal\expandafter - {\DTLbarvariable}{\dtl@variable}% +%<*person.sty> % \end{macrocode} -% Get the current lower label: +%\fi +%\chapter{person.sty}\label{sec:code:person} +%\section{Package Declaration} +% Package identification: % \begin{macrocode} -\dtl@chopfirst\dtl@multibar@labels\dtl@thisbarlabel\dtl@rest -\let\dtl@multibar@labels=\dtl@rest +\NeedsTeXFormat{LaTeX2e} +\ProvidesPackage{person}[2012/07/18 v2.10 (NLCT)] % \end{macrocode} -% Get the current upper label: +% Requires the \sty{ifthen} package. % \begin{macrocode} -\dtl@chopfirst\dtl@uppermultibar@labels\dtl@thisupperbarlabel\dtl@rest -\let\dtl@uppermultibar@labels=\dtl@rest +\RequirePackage{ifthen} +\RequirePackage{datatool} % \end{macrocode} -% Draw bars +%\section{Defining People} +%\begin{counter}{people} +% Keep count of the number of people who have been defined: % \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} +\newcounter{people} % \end{macrocode} -% Draw outline +%\end{counter} +%\begin{counter}{person} +% Temporary counter % \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} +\newcounter{person} % \end{macrocode} -% Calculate mid point +%\end{counter} +%\begin{macro}{\@people@list} +% Keep a list of labels for each person who has been defined: % \begin{macrocode} -\FPadd{\@dtl@midpt}{\@dtl@start}{0.5}% +\newcommand*{\@people@list}{,} % \end{macrocode} -% Draw lower $x$ labels +%\end{macro} +%\begin{macro}{\@get@firstperson} +% Get the first person's name in \cs{@people@list}, and store in +% the argument (which must be a control sequence.) % \begin{macrocode} -\ifDTLverticalbars - \edef\dtl@textopt{% - at={\noexpand\pgfpointadd - {\noexpand\pgfpointxy{\@dtl@midpt}{0}} - {\noexpand\pgfpoint{0pt}{-\noexpand\DTLbarlabeloffset}}}, - \DTLbarXlabelalign - }% - \edef\DTLstartpt{\noexpand\pgfpointxy{\@dtl@midpt}{0}}% -\else - \edef\dtl@textopt{% - at={\noexpand\pgfpointadd - {\noexpand\pgfpointxy{0}{\@dtl@midpt}} - {\noexpand\pgfpoint{-\noexpand\DTLbarlabeloffset}{0pt}}}, - \DTLbarXlabelalign - }% - \edef\DTLstartpt{\noexpand\pgfpointxy{0}{\@dtl@midpt}}% -\fi - \expandafter\pgftext\expandafter[\dtl@textopt]{% - \DTLdisplaylowermultibarlabel{\dtl@thisbarlabel}} +\newcommand*{\@get@firstperson}[1]{% + \expandafter\@@get@firstperson\@people@list,\@nil{#1}} + \def\@@get@firstperson,#1,#2\@nil#3{% + \def#3{#1}% +} % \end{macrocode} -% Draw upper $x$ labels +%\end{macro} +% +%\begin{macro}{\malelabels} +% List of labels that can be used to indicate that a person is +% male (when defining a person using \cs{newperson}). % \begin{macrocode} -\ifDTLverticalbars - \expandafter\DTLifnumlt\expandafter{\DTLbarvariable}{0} - { - \edef\dtl@textopt{% - at={\noexpand\pgfpointadd - {\noexpand\pgfpointxy{\@dtl@midpt}{\dtl@variable}} - {\noexpand\pgfpoint{0pt}{-\noexpand\DTLbarlabeloffset}}} - }% - }{% - \edef\dtl@textopt{% - at={\noexpand\pgfpointadd - {\noexpand\pgfpointxy{\@dtl@midpt}{\dtl@variable}} - {\noexpand\pgfpoint{0pt}{\noexpand\DTLbarlabeloffset}}} - }% - } - \edef\DTLendpt{\noexpand\pgfpointxy{\@dtl@midpt}{\dtl@variable}}% -\else - \expandafter\DTLifnumlt\expandafter{\DTLbarvariable}{0} - { - \edef\dtl@textopt{right, - at={\noexpand\pgfpointadd - {\noexpand\pgfpointxy{\dtl@variable}{\@dtl@midpt}} - {\noexpand\pgfpoint{-\noexpand\DTLbarlabeloffset}{0pt}}} - }% - }{% - \edef\dtl@textopt{left, - at={\noexpand\pgfpointadd - {\noexpand\pgfpointxy{\dtl@variable}{\@dtl@midpt}} - {\noexpand\pgfpoint{\noexpand\DTLbarlabeloffset}{0pt}}} - }% - } - \edef\DTLendpt{\noexpand\pgfpointxy{\dtl@variable}{\@dtl@midpt}}% -\fi - \expandafter\pgftext\expandafter[\dtl@textopt]{% - \DTLdisplayuppermultibarlabel{\dtl@thisupperbarlabel}} +\newcommand*{\malelabels}{male,Male,MALE,M,m} % \end{macrocode} -% Set the mid point +%\end{macro} +%\begin{macro}{\addmalelabel} +% Adds a label to the list of male labels. % \begin{macrocode} -\def\DTLmidpt{\pgfpointlineattime{0.5}{\DTLstartpt}{\DTLendpt}}% +\newcommand*{\addmalelabel}[1]{% + \expandafter\@dtl@toksA\expandafter{\malelabels}% + \expandafter\@dtl@toksB\expandafter{#1}% + \edef\malelabels{\the\@dtl@toksA,\the\@dtl@toksB}% +} % \end{macrocode} -% Do every bar hook -%\changes{2.0}{2009 February 27}{added \cs{DTLeverybarhook}}% +%\end{macro} +%\begin{macro}{\addfemalelabel} +% Adds a label to the list of female labels. % \begin{macrocode} -\DTLeverybarhook +\newcommand*{\addfemalelabel}[1]{% + \expandafter\@dtl@toksA\expandafter{\femalelabels}% + \expandafter\@dtl@toksB\expandafter{#1}% + \edef\femalelabels{\the\@dtl@toksA,\the\@dtl@toksB}% +} % \end{macrocode} -% End of loop increment loop variables +%\end{macro} +% +%\begin{macro}{\femalelabels} +% List of labels that can be used to indicate that a person is +% female (when defining a person using \cs{newperson}). % \begin{macrocode} - \FPadd{\@dtl@start}{\@dtl@start}{1}% - \advance\@dtl@barcount by 1\relax -}% -% Draw lower group $x$ labels +\newcommand*{\femalelabels}{female,Female,FEMALE,F,f} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\ifmalelabel} +% Determines if first argument is contained in the list of male +% labels. (One level expansion is performed on the first object +% in first argument.) +% If true does second argument, otherwise does third argument. % \begin{macrocode} -\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}% +\newcommand{\ifmalelabel}[3]{% + \expandafter\DTLifinlist\expandafter{#1}{\malelabels}{#2}{#3}% } % \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 +%\end{macro} +% +%\begin{macro}{\iffemalelabel} +% Determines if first argument is contained in the list of female +% labels. (One level expansion is performed on the first object +% in first argument.) +% If true does second argument, otherwise does third argument. % \begin{macrocode} -\ifDTLbaryaxis - \ifDTLverticalbars - \expandafter\draw\expandafter[\DTLBarYAxisStyle] - (0,\DTLnegextent) -- (0,\DTLbarmax); - \else - \expandafter\draw\expandafter[\DTLBarYAxisStyle] - (\DTLnegextent,0) -- (\DTLbarmax,0); - \fi -\fi +\newcommand{\iffemalelabel}[3]{% + \expandafter\DTLifinlist\expandafter{#1}{\femalelabels}{#2}{#3}% +} % \end{macrocode} -% Plot $y$ tick marks if required +%\end{macro} +% +%\begin{macro}{\newperson} +% Define a new person. The optional argument specifies a label +% with which to refer to that person. If omitted, \texttt{anon} +% is used. If more than one person is defined, the optional +% argument will be required to specify a unique label. The +% compulsory arguments are the person's full name, their +% familiar name and their gender. % \begin{macrocode} -\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}} +\newcommand*{\newperson}[4][anon]{% + \@ifundefined{person@#1@name}% + {% + \ifmalelabel{#4}% + {% + \expandafter\gdef\csname person@#1@gender\endcsname{male}% + }% + {% + \iffemalelabel{#4}% + {% + \expandafter\gdef\csname person@#1@gender\endcsname{female}% + }% + {% + \PackageError{person}{Unknown gender `#4' for person + `#1'}{Allowed gender labels are: \malelabels\space or + \femalelabels}% + \@namedef{person@#1@gender}{other}% + }% + }% + \expandafter + \protected@xdef\csname person@#1@fullname\endcsname{#2}% + \expandafter + \protected@xdef\csname person@#1@name\endcsname{#3}% + \protected@xdef\@people@list{\@people@list#1,}% + \stepcounter{people}% }% -\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 -}} + {% + \PackageError{person}{Person `#1' has already been defined}{}% + }% +} % \end{macrocode} %\end{macro} -%\iffalse +% +%\section{Remove People} +% +%\begin{macro}{\removeperson} +% Removes person identified by their label from the list. % \begin{macrocode} -% +\newcommand*{\removeperson}[1][anon]{% + \edef\@person@label{#1}% + \expandafter\@removeperson\expandafter{\@person@label}% +} % \end{macrocode} -%\fi -%\iffalse +% The label has to be full expanded for the internal command. % \begin{macrocode} -%<*databib.sty> +\newcommand*{\@removeperson}[1]{% + \ifpersonexists{#1}% + {% % \end{macrocode} -%\fi -%\section{databib.sty} -%\label{sec:src:databib} -%\subsection{Package Declaration} +% Remove label from list of people. % \begin{macrocode} -\NeedsTeXFormat{LaTeX2e} -\ProvidesPackage{databib}[2009/10/22 v2.01 (NLCT)] + \def\@remove@person##1,#1,##2\@nil{% + \def\@prsn@pre{##1}\def\@prsn@post{##2}}% + \expandafter\@remove@person\@people@list\@nil + \xdef\@people@list{\@prsn@pre,\@prsn@post}% % \end{macrocode} -% Load required packages: +% Decrement number of people: % \begin{macrocode} -\RequirePackage{datatool} + \addtocounter{people}{-1}% % \end{macrocode} -%\subsection{Package Options} -%\begin{macro}{\dtlbib@style} -%The default bib style is stored in \cs{dtlbib@style}. +% Undefine associated control sequences: % \begin{macrocode} -\newcommand*{\dtlbib@style}{plain} + \expandafter\global\expandafter + \let\csname person@#1@name\endcsname\undefined + \expandafter\global\expandafter + \let\csname person@#1@fullname\endcsname\undefined + \expandafter\global\expandafter + \let\csname person@#1@gender\endcsname\undefined + }% + {% + \PackageError{person}{Can't remove person `#1': no such + person}{}% + }% +} % \end{macrocode} %\end{macro} -% The \pkgopt[databib]{style} package option sets \cs{dtlbib@style}. +%\begin{macro}{\removepeople} +% Removes the people listed. % \begin{macrocode} -\define@choicekey{databib.sty}{style}{plain,abbrv,alpha}{% -\def\dtlbib@style{#1}} +\newcommand*{\removepeople}[1]{% + \@for\@thisperson:=#1\do{% + \ifx\@thisperson\@empty + \else + \expandafter\removeperson\expandafter[\@thisperson]% + \fi + }% +} % \end{macrocode} -% Process package options: +%\end{macro} +%\begin{macro}{\removeallpeople} +% Removes everyone. % \begin{macrocode} -\ProcessOptionsX +\newcommand*{\removeallpeople}{% + \@for\@thisperson:=\@people@list\do{% + \expandafter\global\expandafter + \let\csname person@\@thisperson @name\endcsname\undefined + \expandafter\global\expandafter + \let\csname person@\@thisperson @fullname\endcsname\undefined + \expandafter\global\expandafter + \let\csname person@\@thisperson @gender\endcsname\undefined + }% + \setcounter{people}{0}% + \gdef\@people@list{,}% +} % \end{macrocode} -%\subsection{Loading BBL file} -%\begin{macro}{\DTLloadbbl} -%\begin{definition} -%\cs{DTLloadbib}\oarg{bbl file}\marg{db name}\marg{bib list} -%\end{definition} +%\end{macro} +% +%\section{Conditionals and Loops} +%\begin{macro}{\ifpersonexists} +% If person whose label is given by the first argument exists, then +% do the second argument otherwise do third argument. % \begin{macrocode} -\newcommand*{\DTLloadbbl}[3][\jobname.bbl]{% -\bibliographystyle{databib}% -\if@filesw - \immediate\write\@auxout{\string\bibdata{#3}}% -\fi -\DTLnewdb{#2}% -\edef\DTLBIBdbname{#2}% -\@input@{#1}} +\newcommand{\ifpersonexists}[3]{% + \@ifundefined{person@#1@name}{#3}{#2}% +} % \end{macrocode} %\end{macro} -%\begin{macro}{\DTLnewbibrow} -% \cs{DTLnewbibrow} adds a new row to the bibliography database. -% (\cs{DTLBIBdbname} must be set prior to use to the name -% of the \sty{datatool} database which must exist. Any check -% to determine its existence should be performed when -% \cs{DTLBIBdbname} is set.) -%\changes{1.03}{2009 January 27}{removed check if database exists} +% +%\begin{macro}{\ifmale} +% If the person given by the label in the first argument is male, +% do the second argument, otherwise do the third argument. % \begin{macrocode} -\newcommand*{\DTLnewbibrow}{\@DTLnewrow{\DTLBIBdbname}} +\newcommand{\ifmale}[3]{% + \ifpersonexists{#1}% + {% + \edef\@gender{\csname person@\@thisperson @gender\endcsname}% + \ifx\@gender\@male@label + #2% + \else + #3% + \fi + }% + {% + \PackageError{person}{Person `#1' doesn't exist.}{}% + }% +} +\def\@male@label{male} % \end{macrocode} %\end{macro} -%\begin{macro}{\DTLnewbibitem} -%\begin{definition} -%\cs{DTLnewbibitem}\marg{key}\marg{value} -%\end{definition} -% Adds a new database entry with the given key and value. -%\changes{1.03}{2009 January 27}{removed check if database exists} +% +%\begin{macro}{\ifallmale} +% If all people listed in first argument are male, do the second +% argument otherwise do the third argument. If the first argument +% is omitted, all defined people are checked. % \begin{macrocode} -\newcommand*{\DTLnewbibitem}[2]{% - \@DTLnewdbentry{\DTLBIBdbname}{#1}{#2}} +\newcommand{\ifallmale}[3][\@people@list]{% + \@for\@thisperson:=#1\do{% + \ifpersonexists{\@thisperson}% + {% + \edef\@gender{\csname person@\@thisperson @gender\endcsname}% + \ifx\@gender\@male@label + \else + \@endfortrue + \fi + }% + {% + \PackageError{person}{Person `#1' doesn't exist.}{}% + }% + }% + \if@endfor + #3% + \else + #2% + \fi +} % \end{macrocode} %\end{macro} -%\subsection{Predefined text} -%\label{sec:src:bibnames} -%\begin{macro}{\andname} +% +%\begin{macro}{\iffemale} +% If the person given by the label in the first argument is female, +% do the second argument, otherwise do the third argument. % \begin{macrocode} -\providecommand*{\andname}{and} +\newcommand{\iffemale}[3]{% + \ifpersonexists{#1}% + {% + \edef\@gender{\csname person@\@thisperson @gender\endcsname}% + \ifx\@gender\@female@label + #2% + \else + #3% + \fi + }% + {% + \PackageError{person}{Person `#1' doesn't exist.}{}% + }% +} +\def\@female@label{female} % \end{macrocode} %\end{macro} -%\begin{macro}{\ofname} +% +%\begin{macro}{\ifallfemale} +% If all people listed in first argument are female, do the second +% argument otherwise do the third argument. % \begin{macrocode} -\providecommand*{\ofname}{of} +\newcommand{\ifallfemale}[3][\@people@list]{% + \@for\@thisperson:=#1\do{% + \edef\@gender{\csname person@\@thisperson @gender\endcsname}% + \ifx\@gender\@female@label + \else + \@endfortrue + \fi + }% + \if@endfor + #3% + \else + #2% + \fi +} % \end{macrocode} %\end{macro} -%\begin{macro}{\inname} +% +%\begin{macro}{\foreachperson} +%\begin{definition} +%\cs{foreachperson}(\meta{name cs},\meta{full name cs},\meta{gender cs},\meta{label cs})\cs{in}\marg{list}\cs{do}\marg{body} +%\end{definition} +% Iterates through list of people the \cs{in}\marg{list} is optional. +% If omitted, the list of all defined people is used. % \begin{macrocode} -\providecommand*{\inname}{in} +\def\foreachperson(#1,#2,#3,#4)#5{% + \ifx#5\in + \def\@do@foreachperson{\@foreachperson(#1,#2,#3,#4)#5}% + \else + \def\@do@foreachperson{% + \@foreachperson(#1,#2,#3,#4)\in\@people@list#5}% + \fi + \@do@foreachperson +} +\long\def\@foreachperson(#1,#2,#3,#4)\in#5\do#6{% + \@for#4:=#5\do{% + \ifx#4\@empty + \else + \ifpersonexists{#4}% + {% + \expandafter + \let\expandafter#1\csname person@#4@name\endcsname + \expandafter + \let\expandafter#2\csname person@#4@fullname\endcsname + \expandafter + \let\expandafter#3\csname person@#4@gender\endcsname + \ifx#3\@male@label + \let#3\malename + \else + \ifx#3\@female@label + \let#3\femalename + \fi + \fi + #6% + }% + {% + \PackageError{person}{Person `#4' doesn't exist}{}% + }% + \fi + }% +} % \end{macrocode} %\end{macro} -%\begin{macro}{\etalname} +% +%\section{Predefined Words}\label{sec:code:peoplenames} +% These commands should be redefined if +% you are writing in another language, but note that these +% are structured according to English grammar. +%\begin{macro}{\malepronoun} % \begin{macrocode} -\providecommand*{\etalname}{et al.} +\newcommand*{\malepronoun}{he} % \end{macrocode} %\end{macro} -%\begin{macro}{\editorname} +%\begin{macro}{\femalepronoun} % \begin{macrocode} -\providecommand*{\editorname}{editor} +\newcommand*{\femalepronoun}{she} % \end{macrocode} %\end{macro} -%\begin{macro}{\editorsname} +%\begin{macro}{\pluralpronoun} % \begin{macrocode} -\providecommand*{\editorsname}{editors} +\newcommand*{\pluralpronoun}{they} % \end{macrocode} %\end{macro} -%\begin{macro}{\volumename} +%\begin{macro}{\maleobjpronoun} % \begin{macrocode} -\providecommand*{\volumename}{volume} +\newcommand*{\maleobjpronoun}{him} % \end{macrocode} %\end{macro} -%\begin{macro}{\numbername} +%\begin{macro}{\femaleobjpronoun} % \begin{macrocode} -\providecommand*{\numbername}{number} +\newcommand*{\femaleobjpronoun}{her} % \end{macrocode} %\end{macro} -%\begin{macro}{\pagesname} +%\begin{macro}{\pluralobjpronoun} % \begin{macrocode} -\providecommand*{\pagesname}{pages} +\newcommand*{\pluralobjpronoun}{them} % \end{macrocode} %\end{macro} -%\begin{macro}{\pagename} +%\begin{macro}{\malepossadj} % \begin{macrocode} -\providecommand*{\pagename}{page} +\newcommand*{\malepossadj}{his} % \end{macrocode} %\end{macro} -%\begin{macro}{\editionname} +%\begin{macro}{\femalepossadj} % \begin{macrocode} -\providecommand*{\editionname}{edition} +\newcommand*{\femalepossadj}{her} % \end{macrocode} %\end{macro} -%\begin{macro}{\techreportname} +%\begin{macro}{\pluralpossadj} % \begin{macrocode} -\providecommand*{\techreportname}{Technical report} +\newcommand*{\pluralpossadj}{their} % \end{macrocode} %\end{macro} -%\begin{macro}{\mscthesisname} +%\begin{macro}{\maleposspronoun} % \begin{macrocode} -\providecommand*{\mscthesisname}{Master's thesis} +\newcommand*{\maleposspronoun}{his} % \end{macrocode} %\end{macro} -%\begin{macro}{\phdthesisname} +%\begin{macro}{\femaleposspronoun} % \begin{macrocode} -\providecommand*{\phdthesisname}{PhD thesis} +\newcommand*{\femaleposspronoun}{hers} % \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{macro}{\pluralposspronoun} % \begin{macrocode} -\newcommand*{\DTLbibliography}[2][\boolean{true}]{% - \begin{DTLthebibliography}[#1]{#2}% - \DTLforeachbibentry[#1]{#2}{% - \DTLbibitem \DTLformatbibentry \DTLendbibitem - }% - \end{DTLthebibliography}% -} +\newcommand*{\pluralposspronoun}{theirs} % \end{macrocode} %\end{macro} -% -%\begin{macro}{\DTLformatbibentry} -%\begin{definition} -%\cs{DTLformatbibentry} -%\end{definition} -% Formats the current bib entry. +%\begin{macro}{\malechild} % \begin{macrocode} -\newcommand*{\DTLformatbibentry}{% +\newcommand*{\malechild}{son} % \end{macrocode} -% Check format for this type is defined. +%\end{macro} +%\begin{macro}{\femalechild} % \begin{macrocode} - \@ifundefined{DTLformat\DBIBentrytype}% - {% - \PackageError{databib}{Don't know how to format bibliography - entries of type `\DBIBentrytype'}{}% - }% - {% +\newcommand*{\femalechild}{daughter} % \end{macrocode} -% Print information to terminal and log file if in verbose mode. +%\end{macro} +%\begin{macro}{\pluralchild} % \begin{macrocode} - \dtl@message{[\DBIBcitekey]}% +\newcommand*{\pluralchild}{children} % \end{macrocode} -% Initialise +%\end{macro} +%\begin{macro}{\malechildren} % \begin{macrocode} - \DTLstartsentencefalse\DTLmidsentencefalse\DTLperiodfalse +\newcommand*{\malechildren}{sons} % \end{macrocode} -% Format this entry +%\end{macro} +%\begin{macro}{\femalechildren} % \begin{macrocode} - \csname DTLformat\DBIBentrytype\endcsname - }% -} +\newcommand*{\femalechildren}{daughters} % \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{macro}{\maleparent} % \begin{macrocode} -\newcommand*{\DTLendbibitem}{} +\newcommand*{\maleparent}{father} % \end{macrocode} %\end{macro} -% -%\begin{macro}{\DTLwidest} -%Define a length to store the widest bib entry label +%\begin{macro}{\femaleparent} % \begin{macrocode} -\newlength\dtl@widest +\newcommand*{\femaleparent}{mother} % \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{macro}{\pluralparent} % \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 -}% -} +\newcommand*{\pluralparent}{parents} % \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{macro}{\malesibling} % \begin{macrocode} -\newcommand*{\DTLforeachbibentry}{% -\@ifstar\@DTLforeachbibentry\@DTLforeachbibentry} +\newcommand*{\malesibling}{brother} % \end{macrocode} %\end{macro} -%\begin{macro}{\@DTLforeachbibentry} -% Unstarred version -% \begin{macrocode} -\newcommand*{\@DTLforeachbibentry}[3][\boolean{true}]{% -% \end{macrocode} -% Store database name. +%\begin{macro}{\femalesibling} % \begin{macrocode} - \edef\DBIBname{#2}% +\newcommand*{\femalesibling}{sister} % \end{macrocode} -% Reset row counter. +%\end{macro} +%\begin{macro}{\pluralsibling} % \begin{macrocode} - \setcounter{DTLbibrow}{0}% +\newcommand*{\pluralsibling}{siblings} % \end{macrocode} -% Iterate through the database. +%\end{macro} +%\begin{macro}{\malesiblings} % \begin{macrocode} - \@DTLforeach{#2}{\DBIBcitekey=CiteKey,\DBIBentrytype=EntryType}% - {% - \dtl@gathervalues{#2}{\dtlcurrentrow}% - \ifthenelse{#1}{\refstepcounter{DTLbibrow}#3}{}% - }% -} +\newcommand*{\malesiblings}{brothers} % \end{macrocode} %\end{macro} -%\begin{macro}{\@sDTLforeachbibentry} -% Starred version +%\begin{macro}{\femalesiblings} % \begin{macrocode} -\newcommand*{\@sDTLforeachbibentry}[3][\boolean{true}]{% +\newcommand*{\femalesiblings}{sisters} % \end{macrocode} -% Store database name. +%\end{macro} +% +%\begin{macro}{\andname} +% Define \cs{andname} if it hasn't already been defined: % \begin{macrocode} - \edef\DBIBname{#2}% +\providecommand*{\andname}{and} % \end{macrocode} -% Reset row counter. +%\end{macro} +%\begin{macro}{\malename} % \begin{macrocode} - \setcounter{DTLbibrow}{0}% +\newcommand*{\malename}{male} % \end{macrocode} -% Iterate through the database (read only). +%\end{macro} +%\begin{macro}{\femalename} % \begin{macrocode} - \@sDTLforeach{#2}{\DBIBcitekey=CiteKey,\DBIBentrytype=EntryType}% - {% - \dtl@gathervalues{#2}{\dtlcurrentrow}% - \ifthenelse{#1}{\refstepcounter{DTLbibrow}#3}{}% - }% -} +\newcommand*{\femalename}{female} % \end{macrocode} %\end{macro} % -%\begin{counter}{DTLbibrow} -%The counter \ctrfmt{DTLbibrow} keeps track of the current -%row in the body of \cs{DTLforeachbibentry}. (You can't rely on -%\ctr{DTLrowi}, \ctr{DTLrowii} and -% \ctr{DTLrowiii}, as \cs{DTLforeachbibentry} pass the -% conditions to the optional argument of \cs{DTLforeach}, but -% instead uses \cs{ifthenelse}, which means that \ctr{DTLrowi} -% etc will be incremented, even when the given condition is not met.) +%\begin{macro}{\personsep} +% Separator to use between people (but not the between the last +% two). % \begin{macrocode} -\newcounter{DTLbibrow} +\newcommand*{\personsep}{, } % \end{macrocode} -%\end{counter} -%\begin{macro}{\theHDTLbibrow} -% Keep \sty{hyperref} happy: +%\end{macro} +%\begin{macro}{\personlastsep} +% Separator to use between last two people. % \begin{macrocode} -\def\theHDTLbibrow{\theHDTLrow.bib.\arabic{DTLbibrow}}% +\newcommand*{\personlastsep}{\space\andname\space} % \end{macrocode} %\end{macro} -% -%\begin{macro}{\DTLbibfield} -%\begin{definition} -%\cs{DTLbibfield}\marg{field name} -%\end{definition} -% Gets the value assigned to the field \meta{field name} for -% the current row of \cs{DTLforeachbibentry}. (Doesn't check if -% the field exists, or if it is being used within -% \cs{DTLforeachbibentry}.) +%\begin{macro}{\twopeoplesep} +% Separator to use when list only contains two people. % \begin{macrocode} -\newcommand*{\DTLbibfield}[1]{\csname @dtl@key@#1\endcsname} +\newcommand*{\twopeoplesep}{\space\andname\space} % \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}. +%\section{Displaying Information} +%\begin{macro}{\personfullname} +% The person's full name can be displayed using +% \cs{personfullname}\oarg{label}, where \meta{label} is the +% unique label used when defining that person. If \meta{label} +% is omitted, \texttt{anon} is used. % \begin{macrocode} -\newcommand*{\DTLifbibfieldexists}[3]{% -\@ifundefined{@dtl@key@#1}{#3}{% -\expandafter\DTLifnull\csname @dtl@key@#1\endcsname -{#3}{#2}}} +\newcommand*{\personfullname}[1][anon]{% + \@ifundefined{person@#1@fullname}% + {% + \PackageError{person}{Person `#1' has not been defined}{}% + }% + {% + \csname person@#1@fullname\endcsname + }% +} % \end{macrocode} %\end{macro} % -%\begin{macro}{\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{macro}{\peoplefullname} +% List all defined people's full names. This iterates through all +% labels in \cs{@people@list}. % \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 +\newcommand*{\peoplefullname}{% + \setcounter{person}{1}% + \@for\@thisperson:=\@people@list\do{% + \ifthenelse{\equal{\@thisperson}{}}% + {}% + {% + \personfullname[\@thisperson]% + \stepcounter{person}% + \ifnum\c@people=1\relax + \else + \ifnum\c@person=\c@people + \ifnum\c@people=2\relax + \twopeoplesep + \else + \personlastsep + \fi + \else + \ifnum\c@person<\c@people + \personsep + \fi + \fi + \fi + }% + }% } % \end{macrocode} %\end{macro} % -%\begin{macro}{\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{macro}{\personname} +% As \cs{personfullname}, but for the person's familiar name. % \begin{macrocode} -\newif\ifDTLperiod +\newcommand*{\personname}[1][anon]{% + \@ifundefined{person@#1@name}% + {% + \PackageError{person}{Person `#1' has not been defined}{}% + }% + {% + \csname person@#1@name\endcsname + }% +} % \end{macrocode} %\end{macro} -%\begin{macro}{\DTLcheckendsperiod} -%\begin{definition} -%\cs{DTLcheckendperiod}\marg{string} -%\end{definition} -% Checks if \meta{string} ends with a full stop. This sets -% \cs{ifDTLperiod}. +% +%\begin{macro}{\peoplename} +% List all defined people's familiar names. This iterates through all +% labels in \cs{@people@list}. % \begin{macrocode} -\newcommand*{\DTLcheckendsperiod}[1]{% -\dtl@checkendsperiod#1\@nil\relax} +\newcommand*{\peoplename}{% + \setcounter{person}{1}% + \@for\@thisperson:=\@people@list\do{% + \ifthenelse{\equal{\@thisperson}{}}% + {}% + {% + \personname[\@thisperson]% + \stepcounter{person}% + \ifnum\c@people=1\relax + \else + \ifnum\c@person=\c@people + \ifnum\c@people=2\relax + \twopeoplesep + \else + \personlastsep + \fi + \else + \ifnum\c@person<\c@people + \personsep + \fi + \fi + \fi + }% + }% +} % \end{macrocode} +%\end{macro} +% +%\begin{macro}{\personpronoun} +% Display the pronoun (he/she) according to the person's gender. % \begin{macrocode} -\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}% +\newcommand*{\personpronoun}[1][anon]{% + \@ifundefined{person@#1@gender}% + {% + \PackageError{person}{Person `#1' has not been defined}{}% + }% + {% + \edef\@gender{\csname person@#1@gender\endcsname}% + \csname\@gender pronoun\endcsname + }% } % \end{macrocode} %\end{macro} -%\begin{macro}{\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{macro}{\Personpronoun} +% As above, but make the first letter uppercase. % \begin{macrocode} -\newcommand*{\DTLcheckbibfieldendsperiod}[1]{% -\protected@edef\@dtl@tmp{\DTLbibfield{#1}}% -\expandafter\DTLcheckendsperiod\expandafter{\@dtl@tmp}} +\newcommand*{\Personpronoun}[1][anon]{% + \@ifundefined{person@#1@gender}% + {% + \PackageError{person}{Person `#1' has not been defined}{}% + }% + {% + \edef\@gender{\csname person@#1@gender\endcsname}% + \expandafter\expandafter\expandafter + \MakeUppercase\csname\@gender pronoun\endcsname + }% +} % \end{macrocode} %\end{macro} % -%\begin{macro}{\ifDTLmidsentence} -%\begin{definition} -%\cs{ifDTLmidsentence} -%\end{definition} -% Determine whether we are in the middle -% of a sentence. +%\begin{macro}{\peoplepronoun} +% If there is more than one person, \cs{peoplepronoun} will use +% \cs{pluralpronoun}, otherwise it will use \cs{personpronoun}. % \begin{macrocode} -\newif\ifDTLmidsentence +\newcommand*{\peoplepronoun}{% + \ifnum\c@people>1\relax + \pluralpronoun + \else + \@get@firstperson{\@thisperson}% + \personpronoun[\@thisperson]% + \fi +} % \end{macrocode} %\end{macro} -%\begin{macro}{\ifDTLstartsentence} -%\begin{definition} -%\cs{ifDTLstartsentence} -%\end{definition} -% Determine whether we are at the start -% of a sentence. +% +%\begin{macro}{\Peoplepronoun} +% As above, but first letter in upper case % \begin{macrocode} -\newif\ifDTLstartsentence +\newcommand*{\Peoplepronoun}{% + \ifnum\c@people>1\relax + \expandafter\MakeUppercase\pluralpronoun + \else + \@get@firstperson{\@thisperson}% + \Personpronoun[\@thisperson]% + \fi +} % \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{macro}{\personobjpronoun} +% Display the objective pronoun (him/her) according to the person's +% gender. % \begin{macrocode} -\newcommand*{\DTLaddperiod}{\DTLmidsentencefalse\DTLperiodfalse -\DTLstartsentencetrue -\ifDTLperiod\else.\fi} +\newcommand*{\personobjpronoun}[1][anon]{% + \@ifundefined{person@#1@gender}% + {% + \PackageError{person}{Person `#1' has not been defined}{}% + }% + {% + \edef\@gender{\csname person@#1@gender\endcsname}% + \csname\@gender objpronoun\endcsname + }% +} % \end{macrocode} %\end{macro} -% -%\begin{macro}{\DTLaddcomma} -%\begin{definition} -%\cs{DTLaddcomma} -%\end{definition} -%Adds a comma and sets \cs{DTLmidsentencetrue}, \cs{DTLperiodfalse} -%and \cs{DTLstartsentencefalse} +%\begin{macro}{\Personobjpronoun} +% As above, but make the first letter uppercase. % \begin{macrocode} -\newcommand*{\DTLaddcomma}{, \DTLmidsentencetrue -\DTLperiodfalse\DTLstartsentencefalse} +\newcommand*{\Personobjpronoun}[1][anon]{% + \@ifundefined{person@#1@gender}% + {% + \PackageError{person}{Person `#1' has not been defined}{}% + }% + {% + \edef\@gender{\csname person@#1@gender\endcsname}% + \expandafter\expandafter\expandafter + \MakeUppercase\csname\@gender objpronoun\endcsname + }% +} % \end{macrocode} %\end{macro} -% -%\begin{macro}{\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{macro}{\peopleobjpronoun} +% If there is more than one person, \cs{peopleobjpronoun} will use +% \cs{pluralobjpronoun}, otherwise it will use \cs{personobjpronoun}. % \begin{macrocode} -\newcommand*{\DTLstartsentencespace}{% -\ifDTLstartsentence\spacefactor=\sfcode`\.\relax\space -\fi\DTLstartsentencefalse} -% \end{macrocode} +\newcommand*{\peopleobjpronoun}{% + \ifnum\c@people>1\relax + \pluralobjpronoun + \else + \@get@firstperson{\@thisperson}% + \personobjpronoun[\@thisperson]% + \fi +} +% \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{macro}{\Peopleobjpronoun} +% As above, but first letter in upper case % \begin{macrocode} -\newcommand*{\DTLtwoand}{\ \andname\ } +\newcommand*{\Peopleobjpronoun}{% + \ifnum\c@people>1\relax + \expandafter\MakeUppercase\pluralobjpronoun + \else + \@get@firstperson{\@thisperson}% + \Personobjpronoun[\@thisperson]% + \fi +} % \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{macro}{\personpssadj} +% Display the possessive adjective (his/her) according to the person's +% gender. % \begin{macrocode} -\newcommand*{\DTLandlast}{, \andname\ } +\newcommand*{\personpossadj}[1][anon]{% + \@ifundefined{person@#1@gender}% + {% + \PackageError{person}{Person `#1' has not been defined}{}% + }% + {% + \edef\@gender{\csname person@#1@gender\endcsname}% + \csname\@gender possadj\endcsname + }% +} % \end{macrocode} %\end{macro} -%\begin{macro}{\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{macro}{\Personpossadj} +% As above, but make the first letter uppercase. % \begin{macrocode} -\newcommand*{\DTLandnotlast}{, } +\newcommand*{\Personpossadj}[1][anon]{% + \@ifundefined{person@#1@gender}% + {% + \PackageError{person}{Person `#1' has not been defined}{}% + }% + {% + \edef\@gender{\csname person@#1@gender\endcsname}% + \expandafter\expandafter\expandafter + \MakeUppercase\csname\@gender possadj\endcsname + }% +} % \end{macrocode} %\end{macro} -%\begin{macro}{\dtl@authorcount} -% Define a count register to keep track of the number of authors: +%\begin{macro}{\peoplepossadj} +% If there is more than one person, \cs{peoplepossadj} will use +% \cs{pluralpossadj}, otherwise it will use \cs{personpossadj}. % \begin{macrocode} -\newcount\@dtl@authorcount +\newcommand*{\peoplepossadj}{% + \ifnum\c@people>1\relax + \pluralpossadj + \else + \@get@firstperson{\@thisperson}% + \personpossadj[\@thisperson]% + \fi +} % \end{macrocode} %\end{macro} -%\begin{counter}{DTLmaxauthors} -% The counter \ctrfmt{DTLmaxauthors} indicates the maximum number of -% author names to display, if there are more than that number, -% \cs{etalname} is used. +%\begin{macro}{\Peoplepossadj} +% As above, but first letter in upper case % \begin{macrocode} -\newcounter{DTLmaxauthors} -\setcounter{DTLmaxauthors}{10} +\newcommand*{\Peoplepossadj}{% + \ifnum\c@people>1\relax + \expandafter\MakeUppercase\pluralpossadj + \else + \@get@firstperson{\@thisperson}% + \Personpossadj[\@thisperson]% + \fi +} % \end{macrocode} -%\end{counter} -%\begin{macro}{\DTLformatauthorlist} -% Format a list of author names (the list is stored in -% \cs{@dtl@key@Author}): +%\end{macro} +% +%\begin{macro}{\personposspronoun} +% Display possessive pronoun (his/hers) according to the +% person's gender. % \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 +\newcommand*{\personposspronoun}[1][anon]{% + \@ifundefined{person@#1@gender}% + {% + \PackageError{person}{Person `#1' has not been defined}{}% }% -}% -\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 + {% + \edef\@gender{\csname person@#1@gender\endcsname}% + \csname\@gender posspronoun\endcsname }% -\fi -}{}% } % \end{macrocode} %\end{macro} -%\begin{counter}{DTLmaxeditors} -% The counter \ctrfmt{DTLmaxeditors} indicates the maximum number of -% editor names to display, if there are more than that number, -% \cs{etalname} is used. +%\begin{macro}{\Personposspronoun} +% As above, but make the first letter uppercase. % \begin{macrocode} -\newcounter{DTLmaxeditors} -\setcounter{DTLmaxeditors}{10} +\newcommand*{\Personposspronoun}[1][anon]{% + \@ifundefined{person@#1@gender}% + {% + \PackageError{person}{Person `#1' has not been defined}{}% + }% + {% + \edef\@gender{\csname person@#1@gender\endcsname}% + \expandafter\expandafter\expandafter + \MakeUppercase\csname\@gender posspronoun\endcsname + }% +} % \end{macrocode} -%\end{counter} -% -%\begin{macro}{\DTLformateditorlist} -% Format a list of editor names (the list is stored in -% \cs{@dtl@key@Editor}): +%\end{macro} +%\begin{macro}{\peopleposspronoun} +% If there is more than one person, \cs{peopleposspronoun} will use +% \cs{pluralposspronoun}, otherwise it will use \cs{personposspronoun}. % \begin{macrocode} -\newcommand*{\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 +\newcommand*{\peopleposspronoun}{% + \ifnum\c@people>1\relax + \pluralposspronoun \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 + \@get@firstperson{\@thisperson}% + \personposspronoun[\@thisperson]% \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{macro}{\Peopleposspronoun} +% As above, but first letter in upper case % \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 +\newcommand*{\Peopleposspronoun}{% + \ifnum\c@people>1\relax + \expandafter\MakeUppercase\pluralposspronoun + \else + \@get@firstperson{\@thisperson}% + \Personposspronoun[\@thisperson]% + \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{macro}{\personchild} +% Display this person's relationship to their parent (i.e.\ son +% or daughter). % \begin{macrocode} -\newcommand*{\DTLformatforenames}[1]{% -\DTLstartsentencespace -#1% -\DTLcheckendsperiod{#1}} +\newcommand*{\personchild}[1][anon]{% + \@ifundefined{person@#1@gender}% + {% + \PackageError{person}{Person `#1' has not been defined}{}% + }% + {% + \edef\@gender{\csname person@#1@gender\endcsname}% + \csname\@gender child\endcsname + }% +} % \end{macrocode} %\end{macro} % -%\begin{macro}{\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{macro}{\Personchild} +% As above, but make first letter uppercase. % \begin{macrocode} -\newcommand*{\DTLformatabbrvforenames}[1]{% -\DTLstartsentencespace -\DTLstoreinitials{#1}{\@dtl@tmp}\@dtl@tmp -\expandafter\DTLcheckendsperiod\expandafter{\@dtl@tmp}} +\newcommand*{\Personchild}[1][anon]{% + \@ifundefined{person@#1@gender}% + {% + \PackageError{person}{Person `#1' has not been defined}{}% + }% + {% + \edef\@gender{\csname person@#1@gender\endcsname}% + \expandafter\expandafter\expandafter\MakeUppercase + \csname\@gender child\endcsname + }% +} % \end{macrocode} %\end{macro} % -%\begin{macro}{\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{macro}{\peoplechild} +% If there is more than one person, \cs{peoplechild} will use +% \cs{malechildren} (if all male), \cs{femalechildren} (if all +% female) or \cs{pluralchild} (if mixed), otherwise it will use +% \cs{personchild}. % \begin{macrocode} -\newcommand*{\DTLformatvon}[1]{% -\DTLstartsentencespace -\def\@dtl@tmp{#1}% -\ifx\@dtl@tmp\@empty -\else - #1~% -\fi +\newcommand*{\peoplechild}{% + \ifnum\c@people>1\relax + \ifallmale + {\malechildren}% + {\ifallfemale{\femalechildren}{\pluralchild}}% + \else + \@get@firstperson{\@thisperson}% + \personchild[\@thisperson]% + \fi } % \end{macrocode} %\end{macro} % -%\begin{macro}{\DTLformatsurname} -%\begin{definition} -%\cs{DTLformatsurname}\marg{surname} -%\end{definition} -% The format of an author/editor's surname. +%\begin{macro}{\Peoplechild} +% As above but first letter is made uppercase. % \begin{macrocode} -\newcommand*{\DTLformatsurname}[1]{% -\DTLstartsentencespace -#1\DTLcheckendsperiod{#1}} +\newcommand*{\Peoplechild}{% + \ifnum\c@people>1\relax + \ifallmale + {\expandafter\MakeUppercase\malechildren}% + {\ifallfemale + {\expandafter\MakeUppercase\femalechildren} + {\expandafter\MakeUppercase\pluralchild}}% + \else + \@get@firstperson{\@thisperson}% + \Personchild[\@thisperson]% + \fi +} % \end{macrocode} %\end{macro} % -%\begin{macro}{\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 +%\begin{macro}{\personparent} +% Display this person's relationship to their child (i.e.\ father +% or mother). +% \begin{macrocode} +\newcommand*{\personparent}[1][anon]{% + \@ifundefined{person@#1@gender}% + {% + \PackageError{person}{Person `#1' has not been defined}{}% + }% + {% + \edef\@gender{\csname person@#1@gender\endcsname}% + \csname\@gender parent\endcsname + }% } % \end{macrocode} %\end{macro} % -%\begin{macro}{\DTLformatcrossrefeditor} -% Format cross reference editors: +%\begin{macro}{\Personparent} +% As above, but make the first letter uppercase. % \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 +\newcommand*{\Personparent}[1][anon]{% + \@ifundefined{person@#1@gender}% + {% + \PackageError{person}{Person `#1' has not been defined}{}% + }% + {% + \edef\@gender{\csname person@#1@gender\endcsname}% + \expandafter\expandafter\expandafter\MakeUppercase + \csname\@gender parent\endcsname + }% +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\peopleparent} +% If there is more than one person, \cs{peopleparent} will use +% \cs{pluralparent}, otherwise it will use \cs{personparent}. +% \begin{macrocode} +\newcommand*{\peopleparent}{% + \ifnum\c@people>1\relax + \pluralparent \else - \ifnum\@dtl@authorcount=2\relax - \ \andname\ \expandafter\DTLformatsurnameonly\@dtl@author - \else - \ \etalname - \expandafter\DTLcheckendsperiod\expandafter{\etalname} - \fi - \@endfortrue + \@get@firstperson{\@thisperson}% + \personparent[\@thisperson]% \fi -\fi -}}% -}{}% } % \end{macrocode} %\end{macro} % -%\begin{macro}{\DTLformatvolnumpages} -% Format volume, number and pages (of an article). +%\begin{macro}{\Peopleparent} +% As above, but make first letter uppercase. % \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}{}% +\newcommand*{\Peopleparent}{% + \ifnum\c@people>1\relax + \expandafter\MakeUppercase\pluralparent + \else + \@get@firstperson{\@thisperson}% + \Personparent[\@thisperson]% + \fi } % \end{macrocode} %\end{macro} % -%\begin{macro}{\DTLformatbvolume} -% Format book volume. +%\begin{macro}{\personsibling} +% Display this person's relationship to their siblings (i.e.\ +% brother or sister). % \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}}% -}{}} +\newcommand*{\personsibling}[1][anon]{% + \@ifundefined{person@#1@gender}% + {% + \PackageError{person}{Person `#1' has not been defined}{}% + }% + {% + \edef\@gender{\csname person@#1@gender\endcsname}% + \csname\@gender sibling\endcsname + }% +} % \end{macrocode} %\end{macro} % -%\begin{macro}{\DTLformatchapterpages} -% Format chapter and pages: +%\begin{macro}{\Personsibling} +% Display this person's relationship to their siblings (i.e.\ +% brother or sister). % \begin{macrocode} -\newcommand*{\DTLformatchapterpages}{% -\DTLifbibfieldexists{Chapter}{% -\DTLifbibfieldexists{Type}{% -\DTLstartsentencespace -\DTLbibfield{Type}}{% -\DTLstartsentencespace -\chaptername}~\DTLbibfield{Chapter}% -\DTLifbibfieldexists{Pages}{\DTLaddcomma}{% -\DTLcheckbibfieldendsperiod{Chapter}}}{}% -\DTLstartsentencespace -\DTLformatpages} +\newcommand*{\Personsibling}[1][anon]{% + \@ifundefined{person@#1@gender}% + {% + \PackageError{person}{Person `#1' has not been defined}{}% + }% + {% + \edef\@gender{\csname person@#1@gender\endcsname}% + \expandafter\expandafter\expandafter\MakeUppercase + \csname\@gender sibling\endcsname + }% +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\peoplesibling} +% If there is more than one person, \cs{peoplesibling} will use +% \cs{malesiblings} (if all male), \cs{femalesiblings} (if all +% female) or \cs{pluralsibling} (if mixed), otherwise it will use +% \cs{personsibling}. +% \begin{macrocode} +\newcommand*{\peoplesibling}{% + \ifnum\c@people>1\relax + \ifallmale + {\malesiblings}% + {\ifallfemale{\femalesiblings}{\pluralsibling}}% + \else + \@get@firstperson{\@thisperson}% + \personsibling[\@thisperson]% + \fi +} % \end{macrocode} %\end{macro} % -%\begin{macro}{\DTLformatpages} -% Format pages: +%\begin{macro}{\persongender} +% Displays the given person's gender (\cs{malename} or +% \cs{femalename}). % \begin{macrocode} -\newcommand*{\DTLformatpages}{% -\DTLifbibfieldexists{Pages}{% -\DTLstartsentencespace -\protected@edef\@dtl@pages{0\DTLbibfield{Pages}}% -\DTLifnumerical{\@dtl@pages}{\pagename}{\pagesname}~% -\DTLbibfield{Pages}\DTLcheckbibfieldendsperiod{Pages}}{}% +\newcommand*{\persongender}[1]{% + \ifpersonmale{#1}{\malename}{\femalename}% } % \end{macrocode} %\end{macro} % -%\begin{macro}{\DTLformatnumberseries} -% Format number and series (of book) +%\section{Extracting Information} +% +%\begin{macro}{\getpersongender} +% Gets person's gender and stores in first argument which must be +% a control sequence. % \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}}{}}% -}% +\newcommand*{\getpersongender}[2]{% + \ifpersonmale{#2}{\let#1\malename}{\let#1\femalename}% } % \end{macrocode} %\end{macro} -%\begin{macro}{\DTLformatbookcrossref} -% Format a book cross reference. +% +%\begin{macro}{\getpersonname} +% Gets person's name and stores in first argument which must be +% a control sequence. % \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}% +\newcommand*{\getpersonname}[2]{% + \ifpersonexists{#2}% + {% + \expandafter\let\expandafter#1\csname person@#2@name\endcsname + }% + {% + \PackageError{person}{Person `#2' doesn't exist}{}% + }% } % \end{macrocode} %\end{macro} -%\begin{macro}{\DTLformatincollproccrossref} -% Format `incollections' cross reference. +% +%\begin{macro}{\getpersonfullname} +% Gets person's full name and stores in first argument which must be +% a control sequence. % \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}% +\newcommand*{\getpersonfullname}[2]{% + \ifpersonexists{#2}% + {% + \expandafter + \let\expandafter#1\csname person@#2@fullname\endcsname + }% + {% + \PackageError{person}{Person `#2' doesn't exist}{}% + }% } % \end{macrocode} %\end{macro} -% -%\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} +%\iffalse % \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.) +%\fi +%\iffalse % \begin{macrocode} -\newcommand*{\DTLbibfieldiseq}[2]{% -\TE@throw\noexpand\dtl@testbibfieldiseq{#1}{#2}% -\noexpand\if@dtl@condition} +%<*databib.bst> % \end{macrocode} -%\end{macro} -%\begin{macro}{\dtl@testbibfieldiseq} +%\fi % \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}% +ENTRY + { address + author + booktitle + chapter + edition + editor + howpublished + institution + journal + key + month + note + number + organization + pages + publisher + school + series + title + type + volume + year + isbn + doi + pubmed + url + abstract + file + eprints + } + {} + { label } + +INTEGERS { output.state before.all mid.sentence after.sentence after.block } + +FUNCTION {init.state.consts} +{ #0 'before.all := + #1 'mid.sentence := + #2 'after.sentence := + #3 'after.block := } -% \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}% + +STRINGS { s t } + +FUNCTION {output.nonnull} +{ 's := + output.state before.all = + { + "%" * write$ + newline$ + } + { newline$ + %add.period$ " " * write$ + } + if$ + % if$ + % mid.sentence 'output.state := + % } + %if$ + s } -% \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}{\DTLmbibitem} -% As \cs{DTLbibitem} but for \cs{DTLmbibliography} -% \begin{macrocode} -\newcommand*{\DTLmbibitem}[1]{\bibitem{#1@\DBIBcitekey}} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\DTLformatauthor} -%\begin{definition} -%\cs{DTLformatauthor}\marg{von part}\marg{surname}\marg{junior -%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}}% -\renewcommand*{\DTLmbibitem}[1]{\bibitem{##1@\DBIBcitekey}}% -% \end{macrocode} -% Sets the author name format. -% \begin{macrocode} -\renewcommand*{\DTLformatauthor}[4]{% -\DTLformatforenames{##4} -\DTLformatvon{##1}% -\DTLformatsurname{##2}% -\DTLformatjr{##3}} -% \end{macrocode} -% Sets the editor name format. -% \begin{macrocode} -\renewcommand*{\DTLformateditor}[4]{% -\DTLformatforenames{##4} -\DTLformatvon{##1}% -\DTLformatsurname{##2}% -\DTLformatjr{##3}} -% \end{macrocode} -% Sets the edition format. -% \begin{macrocode} -\renewcommand*{\DTLformatedition}[1]{##1 \editionname}% -% \end{macrocode} -% Sets the monthname format. -% \begin{macrocode} -\let\DTLmonthname\dtl@monthname -% \end{macrocode} -% Sets other predefined names: -% \begin{macrocode} -\renewcommand*{\DTLacmcs}{ACM Computing Surveys} -\renewcommand*{\DTLacta}{Acta Informatica} -\renewcommand*{\DTLcacm}{Communications of the ACM} -\renewcommand*{\DTLibmjrd}{IBM Journal of Research and Development} -\renewcommand*{\DTLibmsj}{IBM Systems Journal} -\renewcommand*{\DTLieeese}{IEEE Transactions on Software Engineering} -\renewcommand*{\DTLieeetc}{IEEE Transactions on Computers} -\renewcommand*{\DTLieeetcad}{IEEE Transactions on Computer-Aided Design -of Integrated Circuits} -\renewcommand*{\DTLipl}{Information Processing Letters} -\renewcommand*{\DTLjacm}{Journal of the ACM} -\renewcommand*{\DTLjcss}{Journal of Computer and System Sciences} -\renewcommand*{\DTLscp}{Science of Computer Programming} -\renewcommand*{\DTLsicomp}{SIAM Journal on Computing} -\renewcommand*{\DTLtocs}{ACM Transactions on Computer Systems} -\renewcommand*{\DTLtods}{ACM Transactions on Database Systems} -\renewcommand*{\DTLtog}{ACM Transactions on Graphics} -\renewcommand*{\DTLtoms}{ACM Transactions on Mathematical Software} -\renewcommand*{\DTLtoois}{ACM Transactions on Office Information -Systems} -\renewcommand*{\DTLtoplas}{ACM Transactions on Programming Languages -and Systems} -\renewcommand*{\DTLtcs}{Theoretical Computer Science} -% \end{macrocode} -% The format of an article. -% \begin{macrocode} -\renewcommand*{\DTLformatarticle}{% -\DTLformatauthorlist -\DTLifbibfieldexists{Author}{\DTLaddperiod}{}% -\DTLifbibfieldexists{Title}{% -\DTLstartsentencespace\DTLbibfield{Title}% -\DTLcheckbibfieldendsperiod{Title}% -\DTLaddperiod}{}% -\DTLifbibfieldexists{CrossRef}{% -% cross ref field -\DTLformatarticlecrossref -\DTLifbibfieldexists{Pages}{\DTLaddcomma}{}% -\DTLformatpages -\DTLaddperiod -}{% no cross ref field -\DTLifbibfieldexists{Journal}{\DTLstartsentencespace -{\em\DTLbibfield{Journal}}% -\DTLcheckbibfieldendsperiod{Journal}% -\DTLifanybibfieldexists{Number,Volume,Pages,Month,Year}{% -\DTLaddcomma}{\DTLaddperiod}}{}% -\DTLformatvolnumpages -\DTLifanybibfieldexists{Volume,Number,Pages}{% -\DTLifanybibfieldexists{Year,Month}{\DTLaddcomma}{% -\DTLaddperiod}% -\DTLmidsentencefalse}{}% -\DTLformatdate -\DTLifanybibfieldexists{Year,Month}{\DTLaddperiod}{}% -}% -\DTLifbibfieldexists{Note}{\DTLstartsentencespace\DTLbibfield{Note}% -\DTLcheckbibfieldendsperiod{Note}% -\DTLaddperiod}{}% -} -% \end{macrocode} -% The format of a book. -% \begin{macrocode} -\renewcommand*{\DTLformatbook}{% -\DTLifbibfieldexists{Author}{% -\DTLformatauthorlist\DTLaddperiod -}{\DTLformateditorlist\DTLifbibfieldexists{Editor}{% -\DTLaddperiod}{}}% -\DTLifbibfieldexists{Title}{\DTLstartsentencespace -{\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}}% -\renewcommand*{\DTLmbibitem}[1]{% -\expandafter\bibitem\expandafter - [\csname dtl@biblabel@\DBIBcitekey\endcsname]{##1@\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} -% -%\subsection{Multiple Bibliographies} -% In order to have multiple bibliographies, there needs to be -% an aux file for each bibliography. The main bibliography is in -% \cs{jobname}.aux, but need to provide a means of creating -% additional aux files. -%\begin{macro}{\DTLmultibibs} -%\begin{definition} -%\cs{DTLmultibibs}\marg{list} -%\end{definition} -%\changes{1.01}{2007/08/22}{new} -% This creates an auxiliary file for each name in \meta{list}. -% For example, "\DTLmultibibs{foo,bar}" will create the files -% "foo.aux" and "bar.aux". -% \begin{macrocode} -\newcommand*{\DTLmultibibs}[1]{% -\@for\@dtl@af:=#1\do{% -\@ifundefined{dtl@aux@\@dtl@af}{% -\expandafter\newwrite\csname dtl@aux@\@dtl@af\endcsname -\expandafter\immediate -\expandafter\openout\csname dtl@aux@\@dtl@af\endcsname=\@dtl@af.aux -\expandafter\def\csname b@\@dtl@af @*\endcsname{}% -}{% -\PackageError{databib}{Can't create auxiliary file `\@dtl@af.aux', -\expandafter\string\csname dtl@aux@\@dtl@af\endcsname\space -already exists}{}}}} -% \end{macrocode} -% Can only be used in the preamble: -% \begin{macrocode} -\@onlypreamble{\DTLmultibibs} -% \end{macrocode} -%\end{macro} -%\begin{macro}{\DTLcite} -%\begin{definition} -%\cs{DTLcite}\oarg{text}\marg{mbib}\marg{labels} -%\end{definition} -% This is similar to \cs{cite}\oarg{text}\marg{labels}, except -% 1) the cite information is written to the auxiliary file -% associated with the multi-bib \meta{mbib} (which must be named -% in \cs{DTLmultibibs}) and 2) the cross referencing label is -% constructed from \meta{mbib} and \meta{label} to allow for -% the same citation to appear in multiple bibliographies. -% \begin{macrocode} -\newcommand*{\DTLcite}{\@ifnextchar[{\@tempswatrue \dtl@citex -}{\@tempswafalse \dtl@citex[]}} -% \end{macrocode} -%\end{macro} -%\begin{macro}{\dtl@citex} -% \begin{macrocode} -\def\dtl@citex[#1]#2#3{% -\leavevmode\let\@citea\@empty -\@cite{\@for\@citeb:=#3\do{\@citea - \def\@citea{,\penalty \@m \ }% - \edef\@citeb{\expandafter\@firstofone\@citeb\@empty}% - \if@filesw - \@ifundefined{dtl@aux@#2}{% - \PackageError{databib}{multibib `#2' not defined}{% - You need to define `#2' in \string\DTLmutlibibs}% - }{% - \expandafter\immediate - \expandafter\write\csname dtl@aux@#2\endcsname{% - \string\citation{\@citeb}}% - }% - \fi - \@ifundefined{b@#2@\@citeb}{% - \hbox{\reset@font\bfseries ?}% - \G@refundefinedtrue - \@latex@warning{Citation `\@citeb ' on page \thepage \space - undefined}% - }{% - \@cite@ofmt{\csname b@#2@\@citeb \endcsname }% - }% -}}{#1}% -} -% \end{macrocode} -%\end{macro} -%\begin{macro}{\DTLnocite} -%\begin{definition} -%\cs{DTLnocite}\marg{mbib}\marg{key list} -%\end{definition} -% As \cs{nocite} but uses the aux file associated with \meta{mbib} -% which must have been defined using \cs{DTLmultibibs}. -% \begin{macrocode} -\newcommand*{\DTLnocite}[2]{% -\@ifundefined{dtl@aux@#1}{% - \PackageError{databib}{multibib `#1' not defined}{% - You need to define `#1' in \string\DTLmutlibibs}% -}{% - \@bsphack - \ifx\@onlypreamble\document - \@for\@citeb:=#2\do{% - \edef\@citeb{\expandafter\@firstofone\@citeb}% - \if@filesw - \expandafter\immediate - \expandafter\write\csname dtl@aux@#1\endcsname{% - \string\citation{\@citeb}}% - \fi - \@ifundefined{b@#1@\@citeb}{% - \G@refundefinedtrue - \@latex@warning{Citation `\@citeb ' undefined}}{}% - }% - \else - \@latex@error{Cannot be used in preamble}\@eha - \fi - \@esphack -}% -} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\DTLloadmbbl} -%\begin{definition} -%\cs{DTLloadmbib}\marg{mbib}\marg{db name}\marg{bib list} -%\end{definition} -% \begin{macrocode} -\newcommand*{\DTLloadmbbl}[3]{% -\@ifundefined{dtl@aux@#1}{% - \PackageError{databib}{multibib `#1' not defined}{% - You need to define `#1' in \string\DTLmutlibibs}% -}{% - \if@filesw - \expandafter\immediate\expandafter - \write\csname dtl@aux@#1\endcsname{\string\bibstyle{databib}}% - \expandafter\immediate\expandafter - \write\csname dtl@aux@#1\endcsname{\string\bibdata{#3}}% - \fi - \DTLnewdb{#2}% - \edef\DTLBIBdbname{#2}% - \@input@{#1.bbl}% -}% -} -% \end{macrocode} -%\end{macro} -%\begin{definition} -%\cs{DTLmbibliography}\oarg{condition}\marg{mbib name}\marg{bib dbname} -%\end{definition} -% Displays the bibliography for the database \meta{bib dbname} -% which must have previously been loaded using -% \cs{DTLloadmbbl}, where \meta{mbib name} must be listed -% in \cs{DTLmultibibs}. -%\begin{macro}{\DTLmbibliography} -% \begin{macrocode} -\newcommand*{\DTLmbibliography}[3][\boolean{true}]{% -\begin{DTLthebibliography}[#1]{#3}% -\DTLforeachbibentry[#1]{#3}{% -\DTLmbibitem{#2} \DTLformatbibentry \DTLendbibitem -}% -\end{DTLthebibliography}% -} -% \end{macrocode} -%\end{macro} -%\iffalse -% \begin{macrocode} -% -% \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. -% v1.01 (2007/08/22) - added "file" field - -ENTRY - { address - author - booktitle - chapter - edition - editor - howpublished - institution - journal - key - month - note - number - organization - pages - publisher - school - series - title - type - volume - year - isbn - doi - pubmed - url - abstract - file - } - {} - { 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.file} -{ file empty$ - { "" } - { - file - "\DTLnewbibitem {File}" 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 - format.file output - fin.entry -} - -FUNCTION {book} -{ output.bibitem - "\DTLnewbibitem {EntryType}{book}%" write$ - newline$ - author empty$ - { format.editors "author and editor" output.check } - { format.authors output.nonnull - crossref missing$ - { "author and editor" editor either.or.check - } - 'skip$ - if$ - } - if$ - new.block - format.btitle "title" output.check - crossref missing$ - { format.bvolume output - new.block - format.number.series output - %new.sentence - format.publisher "publisher" output.check - format.address output - } - { new.block - format.book.crossref output.nonnull - } - if$ - format.edition output - format.date "year" output.check - new.block - format.key output - format.note output - format.isbn output - format.doi output - format.pubmed output - format.url output - format.abstract output - format.file output - fin.entry -} - -FUNCTION {booklet} -{ output.bibitem - "\DTLnewbibitem {EntryType}{booklet}%" write$ - newline$ - format.authors output - new.block - format.title "title" output.check - howpublished address new.block.checkb - format.howpublished output - format.address output - format.date output - new.block - format.key output - format.note output - format.isbn output - format.doi output - format.pubmed output - format.url output - format.abstract output - format.file output - fin.entry -} - -FUNCTION {inbook} -{ output.bibitem - "\DTLnewbibitem {EntryType}{inbook}%" write$ - newline$ - author empty$ - { format.editors "author and editor" output.check } - { format.authors output.nonnull - crossref missing$ - { "author and editor" editor either.or.check } - 'skip$ - if$ - } - if$ - new.block - format.btitle "title" output.check - crossref missing$ - { format.bvolume output - format.chapter.pages "chapter and pages" output.check - new.block - format.number.series output - new.sentence - format.publisher "publisher" output.check - format.address output - } - { format.chapter.pages "chapter and pages" output.check - new.block - format.book.crossref output.nonnull - } - if$ - format.edition output - format.date "year" output.check - new.block - format.key output - format.note output - format.isbn output - format.doi output - format.pubmed output - format.url output - format.abstract output - format.file output - fin.entry -} - -FUNCTION {incollection} -{ output.bibitem - "\DTLnewbibitem {EntryType}{incollection}%" write$ - newline$ - format.authors "author" output.check - format.title "title" output.check - crossref missing$ - { format.in.ed.booktitle "booktitle" output.check - format.bvolume output - format.number.series output - format.chapter.pages output - new.sentence - format.publisher "publisher" output.check - format.address output - format.edition output - format.date "year" output.check - } - { format.incoll.inproc.crossref output.nonnull - format.chapter.pages output - } - if$ - format.key output - format.note output - format.isbn output - format.doi output - format.pubmed output - format.url output - format.abstract output - format.file output - fin.entry -} - -FUNCTION {inproceedings} -{ output.bibitem - "\DTLnewbibitem {EntryType}{inproceedings}%" write$ - newline$ - format.authors "author" output.check - format.title "title" output.check - crossref missing$ - { format.in.ed.booktitle "booktitle" output.check - format.bvolume output - format.number.series output - format.pages output - address empty$ - { %organization publisher new.sentence.checkb - format.organization write$ - format.publisher output - } - { format.address write$ - new.sentence - format.organization output - format.publisher output - } - if$ - format.date "year" output.check - } - { - format.incoll.inproc.crossref output.nonnull - format.pages output - } - if$ - format.key output - format.note output - format.isbn output - format.doi output - format.pubmed output - format.url output - format.abstract output - format.file output - fin.entry -} - -FUNCTION {conference} { inproceedings } - -FUNCTION {manual} -{ output.bibitem - "\DTLnewbibitem {EntryType}{manual}%" write$ - newline$ - author empty$ - { organization empty$ - 'skip$ - { format.organization output - format.address output - } - if$ - } - { format.authors output } - if$ - new.block - format.btitle "title" output.check - author empty$ - { organization empty$ - { address new.block.checka - address output - } - 'skip$ - if$ - } - { %organization address new.block.checkb - format.organization output - format.address output - } - if$ - format.edition output - format.date output - new.block - format.key output - format.note output - format.isbn output - format.doi output - format.pubmed output - format.url output - format.abstract output - format.file output - fin.entry -} - -FUNCTION {mastersthesis} -{ output.bibitem - "\DTLnewbibitem {EntryType}{mastersthesis}%" write$ - newline$ - format.authors "author" output.check - new.block - format.title "title" output.check - new.block - "\DTLnewbibitem {Type}{\mscthesisname }" - format.thesis.type output.nonnull - format.school "school" output.check - format.address output - format.date "year" output.check - new.block - format.key output - format.note output - format.isbn output - format.doi output - format.pubmed output - format.url output - format.abstract output - format.file output - fin.entry + +FUNCTION {output} +{ duplicate$ empty$ + 'pop$ + 'output.nonnull + if$ } -FUNCTION {misc} -{ output.bibitem - "\DTLnewbibitem {EntryType}{misc}%" write$ - newline$ - format.authors output - title howpublished new.block.checkb - format.title output - %howpublished new.block.checka - format.howpublished output - format.date output - new.block - format.key output - format.note output - format.isbn output - format.doi output - format.pubmed output - format.url output - format.abstract output - format.file output - fin.entry - empty.misc.check +FUNCTION {output.check} +{ 't := + duplicate$ empty$ + { pop$ "empty " t * " in " * cite$ * warning$ } + { + output.nonnull + } + if$ } -FUNCTION {phdthesis} -{ output.bibitem - "\DTLnewbibitem {EntryType}{phdthesis}%" write$ +FUNCTION {output.bibitem} +{ "\DTLnewbibrow" write$ newline$ - format.authors "author" output.check - new.block - format.btitle "title" output.check - new.block - "\DTLnewbibitem {Type}{\phdthesisname }" - format.thesis.type output.nonnull - format.school "school" output.check - format.address output - format.date "year" output.check - new.block - format.key output - format.note output - format.isbn output - format.doi output - format.pubmed output - format.url output - format.abstract output - format.file output - fin.entry + "\DTLnewbibitem {CiteKey}{" write$ + cite$ write$ + "}%" write$ + newline$ + "" + before.all 'output.state := } -FUNCTION {proceedings} -{ output.bibitem - "\DTLnewbibitem {EntryType}{proceedings}%" write$ +FUNCTION {fin.entry} +{ "%" * + write$ newline$ - editor empty$ - { format.organization output } - { format.editors output.nonnull } +} + +FUNCTION {new.block} +{ output.state before.all = + 'skip$ + { after.block 'output.state := } 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 } +} + +FUNCTION {new.sentence} +{ output.state after.block = + 'skip$ + { output.state before.all = +'skip$ +{ after.sentence 'output.state := } if$ - format.publisher output } if$ - new.block - format.key output - format.note output - format.isbn output - format.doi output - format.pubmed output - format.url output - format.abstract output - format.file output - fin.entry } -FUNCTION {techreport} -{ output.bibitem - "\DTLnewbibitem {EntryType}{techreport}%" write$ - newline$ - format.authors "author" output.check - new.block - format.title "title" output.check - new.block - format.tr.number output.nonnull - format.institution "institution" output.check - format.address output - format.date "year" output.check - new.block - format.key output - format.note output - format.isbn output - format.doi output - format.pubmed output - format.url output - format.abstract output - format.file output - fin.entry +FUNCTION {not} +{ { #0 } + { #1 } + if$ } -FUNCTION {unpublished} -{ output.bibitem - "\DTLnewbibitem {EntryType}{unpublished}%" write$ - newline$ - format.authors "author" output.check - new.block - format.title "title" output.check - new.block - format.key output - format.note output - format.isbn output - format.doi output - format.pubmed output - format.url output - format.abstract output - format.file output - format.date output - fin.entry +FUNCTION {and} +{ 'skip$ + { pop$ #0 } + if$ } -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 +FUNCTION {or} +{ { pop$ #1 } + 'skip$ + if$ +} -STRINGS { longest.label } +FUNCTION {new.block.checka} +{ empty$ + 'skip$ + 'new.block + if$ +} -INTEGERS { number.label longest.label.width } +FUNCTION {new.block.checkb} +{ empty$ + swap$ empty$ + and + 'skip$ + 'new.block + if$ +} -FUNCTION {initialize.longest.label} -{ "" 'longest.label := - #1 'number.label := - #0 'longest.label.width := +FUNCTION {new.sentence.checka} +{ empty$ + 'skip$ + 'new.sentence + if$ } -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 := - } +FUNCTION {new.sentence.checkb} +{ empty$ + swap$ empty$ + and 'skip$ + 'new.sentence if$ } -EXECUTE {initialize.longest.label} - -ITERATE {longest.label.pass} - -FUNCTION {begin.bib} -{ preamble$ empty$ +FUNCTION {field.or.null} +{ duplicate$ empty$ + { pop$ "" } 'skip$ - { preamble$ write$ newline$ } if$ } -EXECUTE {begin.bib} +FUNCTION {emphasize} +{ duplicate$ empty$ + { pop$ "" } + { "{\em " swap$ * "}" * } + if$ +} -EXECUTE {init.state.consts} +FUNCTION {group} +{ duplicate$ empty$ + { pop$ "" } + { "{" swap$ * "}" * } + if$ +} -ITERATE {call.type$} +INTEGERS { nameptr namesleft numnames } -FUNCTION {end.bib} +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 * } - -EXECUTE {end.bib} -% \end{macrocode} -% \end{macrocode} -%\fi -%\iffalse -% \begin{macrocode} -% -% \end{macrocode} -%\fi -%\iffalse -% \begin{macrocode} -%<*person.sty> -% \end{macrocode} -%\fi -%\section{person.sty}\label{sec:code:person} -%\subsection{Package Declaration} -% Package identification: -% \begin{macrocode} -\NeedsTeXFormat{LaTeX2e} -\ProvidesPackage{person}[2009/11/15 v1.01 (NLCT)] -% \end{macrocode} -% Requires the \sty{ifthen} package. -% \begin{macrocode} -\RequirePackage{ifthen} -\RequirePackage{datatool} -% \end{macrocode} -%\subsection{Defining People} -%\begin{counter}{people} -% Keep count of the number of people who have been defined: -% \begin{macrocode} -\newcounter{people} -% \end{macrocode} -%\end{counter} -%\begin{counter}{person} -% Temporary counter -% \begin{macrocode} -\newcounter{person} -% \end{macrocode} -%\end{counter} -%\begin{macro}{\@people@list} -% Keep a list of labels for each person who has been defined: -% \begin{macrocode} -\newcommand*{\@people@list}{,} -% \end{macrocode} -%\end{macro} -%\begin{macro}{\@get@firstperson} -% Get the first person's name in \cs{@people@list}, and store in -% the argument (which must be a control sequence.) -% \begin{macrocode} -\newcommand*{\@get@firstperson}[1]{% - \expandafter\@@get@firstperson\@people@list,\@nil{#1}} - \def\@@get@firstperson,#1,#2\@nil#3{% - \def#3{#1}% +'t + if$ + nameptr #1 + 'nameptr := + namesleft #1 - 'namesleft := + } + while$ + "}" * } -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\malelabels} -% List of labels that can be used to indicate that a person is -% male (when defining a person using \cs{newperson}). -% \begin{macrocode} -\newcommand*{\malelabels}{male,Male,MALE,M,m} -% \end{macrocode} -%\end{macro} -%\begin{macro}{\addmalelabel} -% Adds a label to the list of male labels. -% \begin{macrocode} -\newcommand*{\addmalelabel}[1]{% - \expandafter\@dtl@toksA\expandafter{\malelabels}% - \expandafter\@dtl@toksB\expandafter{#1}% - \edef\malelabels{\the\@dtl@toksA,\the\@dtl@toksB}% + +FUNCTION {format.authors} +{ + author empty$ + { "" } + { author + "\DTLnewbibitem {Author}{" write$ + format.names } + if$ } -% \end{macrocode} -%\end{macro} -%\begin{macro}{\addfemalelabel} -% Adds a label to the list of female labels. -% \begin{macrocode} -\newcommand*{\addfemalelabel}[1]{% - \expandafter\@dtl@toksA\expandafter{\femalelabels}% - \expandafter\@dtl@toksB\expandafter{#1}% - \edef\femalelabels{\the\@dtl@toksA,\the\@dtl@toksB}% + +FUNCTION {format.editors} +{ editor empty$ + { "" } + { editor + "\DTLnewbibitem {Editor}{" write$ + format.names + } + if$ } -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\femalelabels} -% List of labels that can be used to indicate that a person is -% female (when defining a person using \cs{newperson}). -% \begin{macrocode} -\newcommand*{\femalelabels}{female,Female,FEMALE,F,f} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\ifmalelabel} -% Determines if first argument is contained in the list of male -% labels. (One level expansion is performed on the first object -% in first argument.) -% If true does second argument, otherwise does third argument. -% \begin{macrocode} -\newcommand{\ifmalelabel}[3]{% - \expandafter\DTLifinlist\expandafter{#1}{\malelabels}{#2}{#3}% + +FUNCTION {format.title} +{ title empty$ + { "" } + { + "\DTLnewbibitem {Title}" + title "t" change.case$ group * + } + if$ } -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\iffemalelabel} -% Determines if first argument is contained in the list of female -% labels. (One level expansion is performed on the first object -% in first argument.) -% If true does second argument, otherwise does third argument. -% \begin{macrocode} -\newcommand{\iffemalelabel}[3]{% - \expandafter\DTLifinlist\expandafter{#1}{\femalelabels}{#2}{#3}% + +FUNCTION {format.howpublished} +{ howpublished empty$ + { "" } + { + howpublished + "\DTLnewbibitem {HowPublished}" swap$ group * + } + if$ } -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\newperson} -% Define a new person. The optional argument specifies a label -% with which to refer to that person. If omitted, \texttt{anon} -% is used. If more than one person is defined, the optional -% argument will be required to specify a unique label. The -% compulsory arguments are the person's full name, their -% familiar name and their gender. -% \begin{macrocode} -\newcommand*{\newperson}[4][anon]{% - \@ifundefined{person@#1@name}% - {% - \ifmalelabel{#4}% - {% - \expandafter\gdef\csname person@#1@gender\endcsname{male}% - }% - {% - \iffemalelabel{#4}% - {% - \expandafter\gdef\csname person@#1@gender\endcsname{female}% - }% - {% - \PackageError{person}{Unknown gender `#4' for person - `#1'}{Allowed gender labels are: \malelabels\space or - \femalelabels}% - \@namedef{person@#1@gender}{other}% - }% - }% - \expandafter - \protected@xdef\csname person@#1@fullname\endcsname{#2}% - \expandafter - \protected@xdef\csname person@#1@name\endcsname{#3}% - \protected@xdef\@people@list{\@people@list#1,}% - \stepcounter{people}% - }% - {% - \PackageError{person}{Person `#1' has already been defined}{}% - }% + +FUNCTION {format.organization} +{ organization empty$ + { "" } + { + organization + "\DTLnewbibitem {Organization}" swap$ group * + } + if$ } -% \end{macrocode} -%\end{macro} -% -%\subsection{Remove People} -% -%\begin{macro}{\removeperson} -% Removes person identified by their label from the list. -% \begin{macrocode} -\newcommand*{\removeperson}[1][anon]{% - \edef\@person@label{#1}% - \expandafter\@removeperson\expandafter{\@person@label}% + +FUNCTION {format.institution} +{ institution empty$ + { "" } + { + institution + "\DTLnewbibitem {Institution}" swap$ group * + } + if$ } -% \end{macrocode} -% The label has to be full expanded for the internal command. -% \begin{macrocode} -\newcommand*{\@removeperson}[1]{% - \ifpersonexists{#1}% - {% -% \end{macrocode} -% Remove label from list of people. -% \begin{macrocode} - \def\@remove@person##1,#1,##2\@nil{% - \def\@prsn@pre{##1}\def\@prsn@post{##2}}% - \expandafter\@remove@person\@people@list\@nil - \xdef\@people@list{\@prsn@pre,\@prsn@post}% -% \end{macrocode} -% Decrement number of people: -% \begin{macrocode} - \addtocounter{people}{-1}% -% \end{macrocode} -% Undefine associated control sequences: -% \begin{macrocode} - \expandafter\global\expandafter - \let\csname person@#1@name\endcsname\undefined - \expandafter\global\expandafter - \let\csname person@#1@fullname\endcsname\undefined - \expandafter\global\expandafter - \let\csname person@#1@gender\endcsname\undefined - }% - {% - \PackageError{person}{Can't remove person `#1': no such - person}{}% - }% + +FUNCTION {format.key} +{ key empty$ + { "" } + { + key + "\DTLnewbibitem {Key}" swap$ group * + } + if$ } -% \end{macrocode} -%\end{macro} -%\begin{macro}{\removepeople} -% Removes the people listed. -% \begin{macrocode} -\newcommand*{\removepeople}[1]{% - \@for\@thisperson:=#1\do{% - \ifx\@thisperson\@empty - \else - \expandafter\removeperson\expandafter[\@thisperson]% - \fi - }% + +FUNCTION {format.note} +{ note empty$ + { "" } + { + note + "\DTLnewbibitem {Note}" swap$ group * + } + if$ } -% \end{macrocode} -%\end{macro} -%\begin{macro}{\removeallpeople} -% Removes everyone. -% \begin{macrocode} -\newcommand*{\removeallpeople}{% - \@for\@thisperson:=\@people@list\do{% - \expandafter\global\expandafter - \let\csname person@\@thisperson @name\endcsname\undefined - \expandafter\global\expandafter - \let\csname person@\@thisperson @fullname\endcsname\undefined - \expandafter\global\expandafter - \let\csname person@\@thisperson @gender\endcsname\undefined - }% - \setcounter{people}{0}% - \gdef\@people@list{,}% + +FUNCTION {format.isbn} +{ isbn empty$ + { "" } + { + isbn + "\DTLnewbibitem {ISBN}" swap$ group * + } + if$ } -% \end{macrocode} -%\end{macro} -% -%\subsection{Conditionals and Loops} -%\begin{macro}{\ifpersonexists} -% If person whose label is given by the first argument exists, then -% do the second argument otherwise do third argument. -% \begin{macrocode} -\newcommand{\ifpersonexists}[3]{% - \@ifundefined{person@#1@name}{#3}{#2}% + +FUNCTION {format.doi} +{ doi empty$ + { "" } + { + doi + "\DTLnewbibitem {DOI}" swap$ group * + } + if$ } -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\ifmale} -% If the person given by the label in the first argument is male, -% do the second argument, otherwise do the third argument. -% \begin{macrocode} -\newcommand{\ifmale}[3]{% - \ifpersonexists{#1}% - {% - \edef\@gender{\csname person@\@thisperson @gender\endcsname}% - \ifx\@gender\@male@label - #2% - \else - #3% - \fi - }% - {% - \PackageError{person}{Person `#1' doesn't exist.}{}% - }% + +FUNCTION {format.pubmed} +{ pubmed empty$ + { "" } + { + pubmed + "\DTLnewbibitem {PubMed}" swap$ group * + } + if$ } -\def\@male@label{male} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\ifallmale} -% If all people listed in first argument are male, do the second -% argument otherwise do the third argument. If the first argument -% is omitted, all defined people are checked. -% \begin{macrocode} -\newcommand{\ifallmale}[3][\@people@list]{% - \@for\@thisperson:=#1\do{% - \ifpersonexists{\@thisperson}% - {% - \edef\@gender{\csname person@\@thisperson @gender\endcsname}% - \ifx\@gender\@male@label - \else - \@endfortrue - \fi - }% - {% - \PackageError{person}{Person `#1' doesn't exist.}{}% - }% - }% - \if@endfor - #3% - \else - #2% - \fi + +FUNCTION {format.abstract} +{ abstract empty$ + { "" } + { + abstract + "\DTLnewbibitem {Abstract}" swap$ group * + } + if$ } -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\iffemale} -% If the person given by the label in the first argument is female, -% do the second argument, otherwise do the third argument. -% \begin{macrocode} -\newcommand{\iffemale}[3]{% - \ifpersonexists{#1}% - {% - \edef\@gender{\csname person@\@thisperson @gender\endcsname}% - \ifx\@gender\@female@label - #2% - \else - #3% - \fi - }% - {% - \PackageError{person}{Person `#1' doesn't exist.}{}% - }% + +FUNCTION {format.url} +{ url empty$ + { "" } + { + url + "\DTLnewbibitem {Url}" swap$ group * + } + if$ } -\def\@female@label{female} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\ifallfemale} -% If all people listed in first argument are female, do the second -% argument otherwise do the third argument. -% \begin{macrocode} -\newcommand{\ifallfemale}[3][\@people@list]{% - \@for\@thisperson:=#1\do{% - \edef\@gender{\csname person@\@thisperson @gender\endcsname}% - \ifx\@gender\@female@label - \else - \@endfortrue - \fi - }% - \if@endfor - #3% - \else - #2% - \fi + +FUNCTION {format.file} +{ file empty$ + { "" } + { + file + "\DTLnewbibitem {File}" swap$ group * + } + if$ +} + +FUNCTION {format.eprints} +{ eprints empty$ + { "" } + { + eprints + "\DTLnewbibitem {Eprints}" swap$ group * + } + if$ } -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\foreachperson} -%\begin{definition} -%\cs{foreachperson}(\meta{name cs},\meta{full name cs},\meta{gender cs},\meta{label cs})\cs{in}\marg{list}\cs{do}\marg{body} -%\end{definition} -% Iterates through list of people the \cs{in}\marg{list} is optional. -% If omitted, the list of all defined people is used. -% \begin{macrocode} -\def\foreachperson(#1,#2,#3,#4)#5{% - \ifx#5\in - \def\@do@foreachperson{\@foreachperson(#1,#2,#3,#4)#5}% - \else - \def\@do@foreachperson{% - \@foreachperson(#1,#2,#3,#4)\in\@people@list#5}% - \fi - \@do@foreachperson + +FUNCTION {format.address} +{ address empty$ + { "" } + { + address + "\DTLnewbibitem {Address}" swap$ group * + } + if$ } -\long\def\@foreachperson(#1,#2,#3,#4)\in#5\do#6{% - \@for#4:=#5\do{% - \ifx#4\@empty - \else - \ifpersonexists{#4}% - {% - \expandafter - \let\expandafter#1\csname person@#4@name\endcsname - \expandafter - \let\expandafter#2\csname person@#4@fullname\endcsname - \expandafter - \let\expandafter#3\csname person@#4@gender\endcsname - \ifx#3\@male@label - \let#3\malename - \else - \ifx#3\@female@label - \let#3\femalename - \fi - \fi - #6% - }% - {% - \PackageError{person}{Person `#4' doesn't exist}{}% - }% - \fi - }% + +FUNCTION {format.school} +{ school empty$ + { "" } + { + school + "\DTLnewbibitem {School}" swap$ group * + } + if$ } -% \end{macrocode} -%\end{macro} -% -%\subsection{Predefined Words}\label{sec:code:peoplenames} -% These commands should be redefined if -% you are writing in another language, but note that these -% are structured according to English grammar. -%\begin{macro}{\malepronoun} -% \begin{macrocode} -\newcommand*{\malepronoun}{he} -% \end{macrocode} -%\end{macro} -%\begin{macro}{\femalepronoun} -% \begin{macrocode} -\newcommand*{\femalepronoun}{she} -% \end{macrocode} -%\end{macro} -%\begin{macro}{\pluralpronoun} -% \begin{macrocode} -\newcommand*{\pluralpronoun}{they} -% \end{macrocode} -%\end{macro} -%\begin{macro}{\maleobjpronoun} -% \begin{macrocode} -\newcommand*{\maleobjpronoun}{him} -% \end{macrocode} -%\end{macro} -%\begin{macro}{\femaleobjpronoun} -% \begin{macrocode} -\newcommand*{\femaleobjpronoun}{her} -% \end{macrocode} -%\end{macro} -%\begin{macro}{\pluralobjpronoun} -% \begin{macrocode} -\newcommand*{\pluralobjpronoun}{them} -% \end{macrocode} -%\end{macro} -%\begin{macro}{\malepossadj} -% \begin{macrocode} -\newcommand*{\malepossadj}{his} -% \end{macrocode} -%\end{macro} -%\begin{macro}{\femalepossadj} -% \begin{macrocode} -\newcommand*{\femalepossadj}{her} -% \end{macrocode} -%\end{macro} -%\begin{macro}{\pluralpossadj} -% \begin{macrocode} -\newcommand*{\pluralpossadj}{their} -% \end{macrocode} -%\end{macro} -%\begin{macro}{\maleposspronoun} -% \begin{macrocode} -\newcommand*{\maleposspronoun}{his} -% \end{macrocode} -%\end{macro} -%\begin{macro}{\femaleposspronoun} -% \begin{macrocode} -\newcommand*{\femaleposspronoun}{hers} -% \end{macrocode} -%\end{macro} -%\begin{macro}{\pluralposspronoun} -% \begin{macrocode} -\newcommand*{\pluralposspronoun}{theirs} -% \end{macrocode} -%\end{macro} -%\begin{macro}{\malechild} -% \begin{macrocode} -\newcommand*{\malechild}{son} -% \end{macrocode} -%\end{macro} -%\begin{macro}{\femalechild} -% \begin{macrocode} -\newcommand*{\femalechild}{daughter} -% \end{macrocode} -%\end{macro} -%\begin{macro}{\pluralchild} -% \begin{macrocode} -\newcommand*{\pluralchild}{children} -% \end{macrocode} -%\end{macro} -%\begin{macro}{\malechildren} -% \begin{macrocode} -\newcommand*{\malechildren}{sons} -% \end{macrocode} -%\end{macro} -%\begin{macro}{\femalechildren} -% \begin{macrocode} -\newcommand*{\femalechildren}{daughters} -% \end{macrocode} -%\end{macro} -%\begin{macro}{\maleparent} -% \begin{macrocode} -\newcommand*{\maleparent}{father} -% \end{macrocode} -%\end{macro} -%\begin{macro}{\femaleparent} -% \begin{macrocode} -\newcommand*{\femaleparent}{mother} -% \end{macrocode} -%\end{macro} -%\begin{macro}{\pluralparent} -% \begin{macrocode} -\newcommand*{\pluralparent}{parents} -% \end{macrocode} -%\end{macro} -%\begin{macro}{\malesibling} -% \begin{macrocode} -\newcommand*{\malesibling}{brother} -% \end{macrocode} -%\end{macro} -%\begin{macro}{\femalesibling} -% \begin{macrocode} -\newcommand*{\femalesibling}{sister} -% \end{macrocode} -%\end{macro} -%\begin{macro}{\pluralsibling} -% \begin{macrocode} -\newcommand*{\pluralsibling}{siblings} -% \end{macrocode} -%\end{macro} -%\begin{macro}{\malesiblings} -% \begin{macrocode} -\newcommand*{\malesiblings}{brothers} -% \end{macrocode} -%\end{macro} -%\begin{macro}{\femalesiblings} -% \begin{macrocode} -\newcommand*{\femalesiblings}{sisters} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\andname} -% Define \cs{andname} if it hasn't already been defined: -% \begin{macrocode} -\providecommand*{\andname}{and} -% \end{macrocode} -%\end{macro} -%\begin{macro}{\malename} -% \begin{macrocode} -\newcommand*{\malename}{male} -% \end{macrocode} -%\end{macro} -%\begin{macro}{\femalename} -% \begin{macrocode} -\newcommand*{\femalename}{female} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\personsep} -% Separator to use between people (but not the between the last -% two). -% \begin{macrocode} -\newcommand*{\personsep}{, } -% \end{macrocode} -%\end{macro} -%\begin{macro}{\personlastsep} -% Separator to use between last two people. -% \begin{macrocode} -\newcommand*{\personlastsep}{\space\andname\space} -% \end{macrocode} -%\end{macro} -%\begin{macro}{\twopeoplesep} -% Separator to use when list only contains two people. -% \begin{macrocode} -\newcommand*{\twopeoplesep}{\space\andname\space} -% \end{macrocode} -%\end{macro} -% -%\subsection{Displaying Information} -%\begin{macro}{\personfullname} -% The person's full name can be displayed using -% \cs{personfullname}\oarg{label}, where \meta{label} is the -% unique label used when defining that person. If \meta{label} -% is omitted, \texttt{anon} is used. -% \begin{macrocode} -\newcommand*{\personfullname}[1][anon]{% - \@ifundefined{person@#1@fullname}% - {% - \PackageError{person}{Person `#1' has not been defined}{}% - }% - {% - \csname person@#1@fullname\endcsname - }% + +FUNCTION {format.publisher} +{ publisher empty$ + { "" } + { + publisher + "\DTLnewbibitem {Publisher}" swap$ group * + } + if$ } -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\peoplefullname} -% List all defined people's full names. This iterates through all -% labels in \cs{@people@list}. -% \begin{macrocode} -\newcommand*{\peoplefullname}{% - \setcounter{person}{1}% - \@for\@thisperson:=\@people@list\do{% - \ifthenelse{\equal{\@thisperson}{}}% - {}% - {% - \personfullname[\@thisperson]% - \stepcounter{person}% - \ifnum\c@people=1\relax - \else - \ifnum\c@person=\c@people - \ifnum\c@people=2\relax - \twopeoplesep - \else - \personlastsep - \fi - \else - \ifnum\c@person<\c@people - \personsep - \fi - \fi - \fi - }% - }% + +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 := } -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\personname} -% As \cs{personfullname}, but for the person's familiar name. -% \begin{macrocode} -\newcommand*{\personname}[1][anon]{% - \@ifundefined{person@#1@name}% - {% - \PackageError{person}{Person `#1' has not been defined}{}% - }% - {% - \csname person@#1@name\endcsname - }% + while$ + } + if$ } -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\peoplename} -% List all defined people's familiar names. This iterates through all -% labels in \cs{@people@list}. -% \begin{macrocode} -\newcommand*{\peoplename}{% - \setcounter{person}{1}% - \@for\@thisperson:=\@people@list\do{% - \ifthenelse{\equal{\@thisperson}{}}% - {}% - {% - \personname[\@thisperson]% - \stepcounter{person}% - \ifnum\c@people=1\relax - \else - \ifnum\c@person=\c@people - \ifnum\c@people=2\relax - \twopeoplesep - \else - \personlastsep - \fi - \else - \ifnum\c@person<\c@people - \personsep - \fi - \fi - \fi - }% - }% +{ 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$ } -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\personpronoun} -% Display the pronoun (he/she) according to the person's gender. -% \begin{macrocode} -\newcommand*{\personpronoun}[1][anon]{% - \@ifundefined{person@#1@gender}% - {% - \PackageError{person}{Person `#1' has not been defined}{}% - }% - {% - \edef\@gender{\csname person@#1@gender\endcsname}% - \csname\@gender pronoun\endcsname - }% + +FUNCTION {format.thesis.type} +{ type empty$ + 'skip$ + { pop$ + type "t" change.case$ + "\DTLnewbibitem {Type}" swap$ group * + } + if$ } -% \end{macrocode} -%\end{macro} -%\begin{macro}{\Personpronoun} -% As above, but make the first letter uppercase. -% \begin{macrocode} -\newcommand*{\Personpronoun}[1][anon]{% - \@ifundefined{person@#1@gender}% - {% - \PackageError{person}{Person `#1' has not been defined}{}% - }% - {% - \edef\@gender{\csname person@#1@gender\endcsname}% - \expandafter\expandafter\expandafter - \MakeUppercase\csname\@gender pronoun\endcsname - }% + +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$ } -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\peoplepronoun} -% If there is more than one person, \cs{peoplepronoun} will use -% \cs{pluralpronoun}, otherwise it will use \cs{personpronoun}. -% \begin{macrocode} -\newcommand*{\peoplepronoun}{% - \ifnum\c@people>1\relax - \pluralpronoun - \else - \@get@firstperson{\@thisperson}% - \personpronoun[\@thisperson]% - \fi + +FUNCTION {format.article.crossref} +{ key empty$ + { journal empty$ +{ "need key or journal for " cite$ * " to crossref " * crossref * + warning$ + "" } -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\Peoplepronoun} -% As above, but first letter in upper case -% \begin{macrocode} -\newcommand*{\Peoplepronoun}{% - \ifnum\c@people>1\relax - \expandafter\MakeUppercase\pluralpronoun - \else - \@get@firstperson{\@thisperson}% - \Personpronoun[\@thisperson]% - \fi +{ + "\DTLnewbibitem {Journal}" journal group * + } + if$ + } + { + "" + } + if$ + "\DTLnewbibitem {CrossRef}{" * crossref * "}" * } -% \end{macrocode} -%\end{macro} -%\begin{macro}{\personobjpronoun} -% Display the objective pronoun (him/her) according to the person's -% gender. -% \begin{macrocode} -\newcommand*{\personobjpronoun}[1][anon]{% - \@ifundefined{person@#1@gender}% - {% - \PackageError{person}{Person `#1' has not been defined}{}% - }% - {% - \edef\@gender{\csname person@#1@gender\endcsname}% - \csname\@gender objpronoun\endcsname - }% + +FUNCTION {format.crossref.editor} +{ format.editors } -% \end{macrocode} -%\end{macro} -%\begin{macro}{\Personobjpronoun} -% As above, but make the first letter uppercase. -% \begin{macrocode} -\newcommand*{\Personobjpronoun}[1][anon]{% - \@ifundefined{person@#1@gender}% - {% - \PackageError{person}{Person `#1' has not been defined}{}% - }% - {% - \edef\@gender{\csname person@#1@gender\endcsname}% - \expandafter\expandafter\expandafter - \MakeUppercase\csname\@gender objpronoun\endcsname - }% + +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$ } -% \end{macrocode} -%\end{macro} -%\begin{macro}{\peopleobjpronoun} -% If there is more than one person, \cs{peopleobjpronoun} will use -% \cs{pluralobjpronoun}, otherwise it will use \cs{personobjpronoun}. -% \begin{macrocode} -\newcommand*{\peopleobjpronoun}{% - \ifnum\c@people>1\relax - \pluralobjpronoun - \else - \@get@firstperson{\@thisperson}% - \personobjpronoun[\@thisperson]% - \fi +{ "" + } + if$ + } + { + format.crossref.editor * + } + if$ + "\DTLnewbibitem {CrossRef}{" * crossref * "}" * } -% \end{macrocode} -%\end{macro} -%\begin{macro}{\Peopleobjpronoun} -% As above, but first letter in upper case -% \begin{macrocode} -\newcommand*{\Peopleobjpronoun}{% - \ifnum\c@people>1\relax - \expandafter\MakeUppercase\pluralobjpronoun - \else - \@get@firstperson{\@thisperson}% - \Personobjpronoun[\@thisperson]% - \fi + +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$ } -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\personpssadj} -% Display the possessive adjective (his/her) according to the person's -% gender. -% \begin{macrocode} -\newcommand*{\personpossadj}[1][anon]{% - \@ifundefined{person@#1@gender}% - {% - \PackageError{person}{Person `#1' has not been defined}{}% - }% - {% - \edef\@gender{\csname person@#1@gender\endcsname}% - \csname\@gender possadj\endcsname - }% +{ "" } + if$ + } + { + "\DTLnewbibitem {Editor}{" * + editor format.names + } + if$ + "\DTLnewbibitem {CrossRef}{" * crossref * "}" * } -% \end{macrocode} -%\end{macro} -%\begin{macro}{\Personpossadj} -% As above, but make the first letter uppercase. -% \begin{macrocode} -\newcommand*{\Personpossadj}[1][anon]{% - \@ifundefined{person@#1@gender}% - {% - \PackageError{person}{Person `#1' has not been defined}{}% - }% - {% - \edef\@gender{\csname person@#1@gender\endcsname}% - \expandafter\expandafter\expandafter - \MakeUppercase\csname\@gender possadj\endcsname - }% + +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 + format.file output + fin.entry } -% \end{macrocode} -%\end{macro} -%\begin{macro}{\peoplepossadj} -% If there is more than one person, \cs{peoplepossadj} will use -% \cs{pluralpossadj}, otherwise it will use \cs{personpossadj}. -% \begin{macrocode} -\newcommand*{\peoplepossadj}{% - \ifnum\c@people>1\relax - \pluralpossadj - \else - \@get@firstperson{\@thisperson}% - \personpossadj[\@thisperson]% - \fi + +FUNCTION {book} +{ output.bibitem + "\DTLnewbibitem {EntryType}{book}%" write$ + newline$ + author empty$ + { format.editors "author and editor" output.check } + { format.authors output.nonnull + crossref missing$ +{ "author and editor" editor either.or.check + } +'skip$ + if$ + } + if$ + new.block + format.btitle "title" output.check + crossref missing$ + { format.bvolume output + new.block + format.number.series output + %new.sentence + format.publisher "publisher" output.check + format.address output + } + { new.block + format.book.crossref output.nonnull + } + if$ + format.edition output + format.date "year" output.check + new.block + format.key output + format.note output + format.isbn output + format.doi output + format.pubmed output + format.url output + format.abstract output + format.file output + fin.entry } -% \end{macrocode} -%\end{macro} -%\begin{macro}{\Peoplepossadj} -% As above, but first letter in upper case -% \begin{macrocode} -\newcommand*{\Peoplepossadj}{% - \ifnum\c@people>1\relax - \expandafter\MakeUppercase\pluralpossadj - \else - \@get@firstperson{\@thisperson}% - \Personpossadj[\@thisperson]% - \fi + +FUNCTION {booklet} +{ output.bibitem + "\DTLnewbibitem {EntryType}{booklet}%" write$ + newline$ + format.authors output + new.block + format.title "title" output.check + howpublished address new.block.checkb + format.howpublished output + format.address output + format.date output + new.block + format.key output + format.note output + format.isbn output + format.doi output + format.pubmed output + format.url output + format.abstract output + format.file output + fin.entry } -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\personposspronoun} -% Display possessive pronoun (his/hers) according to the -% person's gender. -% \begin{macrocode} -\newcommand*{\personposspronoun}[1][anon]{% - \@ifundefined{person@#1@gender}% - {% - \PackageError{person}{Person `#1' has not been defined}{}% - }% - {% - \edef\@gender{\csname person@#1@gender\endcsname}% - \csname\@gender posspronoun\endcsname - }% + +FUNCTION {inbook} +{ output.bibitem + "\DTLnewbibitem {EntryType}{inbook}%" write$ + newline$ + author empty$ + { format.editors "author and editor" output.check } + { format.authors output.nonnull + crossref missing$ +{ "author and editor" editor either.or.check } +'skip$ + if$ + } + if$ + new.block + format.btitle "title" output.check + crossref missing$ + { format.bvolume output + format.chapter.pages "chapter and pages" output.check + new.block + format.number.series output + new.sentence + format.publisher "publisher" output.check + format.address output + } + { format.chapter.pages "chapter and pages" output.check + new.block + format.book.crossref output.nonnull + } + if$ + format.edition output + format.date "year" output.check + new.block + format.key output + format.note output + format.isbn output + format.doi output + format.pubmed output + format.url output + format.abstract output + format.file output + fin.entry } -% \end{macrocode} -%\end{macro} -%\begin{macro}{\Personposspronoun} -% As above, but make the first letter uppercase. -% \begin{macrocode} -\newcommand*{\Personposspronoun}[1][anon]{% - \@ifundefined{person@#1@gender}% - {% - \PackageError{person}{Person `#1' has not been defined}{}% - }% - {% - \edef\@gender{\csname person@#1@gender\endcsname}% - \expandafter\expandafter\expandafter - \MakeUppercase\csname\@gender posspronoun\endcsname - }% + +FUNCTION {incollection} +{ output.bibitem + "\DTLnewbibitem {EntryType}{incollection}%" write$ + newline$ + format.authors "author" output.check + format.title "title" output.check + crossref missing$ + { format.in.ed.booktitle "booktitle" output.check + format.bvolume output + format.number.series output + format.chapter.pages output + new.sentence + format.publisher "publisher" output.check + format.address output + format.edition output + format.date "year" output.check + } + { format.incoll.inproc.crossref output.nonnull + format.chapter.pages output + } + if$ + format.key output + format.note output + format.isbn output + format.doi output + format.pubmed output + format.url output + format.abstract output + format.file output + fin.entry } -% \end{macrocode} -%\end{macro} -%\begin{macro}{\peopleposspronoun} -% If there is more than one person, \cs{peopleposspronoun} will use -% \cs{pluralposspronoun}, otherwise it will use \cs{personposspronoun}. -% \begin{macrocode} -\newcommand*{\peopleposspronoun}{% - \ifnum\c@people>1\relax - \pluralposspronoun - \else - \@get@firstperson{\@thisperson}% - \personposspronoun[\@thisperson]% - \fi + +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 } -% \end{macrocode} -%\end{macro} -%\begin{macro}{\Peopleposspronoun} -% As above, but first letter in upper case -% \begin{macrocode} -\newcommand*{\Peopleposspronoun}{% - \ifnum\c@people>1\relax - \expandafter\MakeUppercase\pluralposspronoun - \else - \@get@firstperson{\@thisperson}% - \Personposspronoun[\@thisperson]% - \fi +{ format.address write$ + new.sentence + format.organization output + format.publisher output } -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\personchild} -% Display this person's relationship to their parent (i.e.\ son -% or daughter). -% \begin{macrocode} -\newcommand*{\personchild}[1][anon]{% - \@ifundefined{person@#1@gender}% - {% - \PackageError{person}{Person `#1' has not been defined}{}% - }% - {% - \edef\@gender{\csname person@#1@gender\endcsname}% - \csname\@gender child\endcsname - }% + if$ + format.date "year" output.check + } + { + format.incoll.inproc.crossref output.nonnull + format.pages output + } + if$ + format.key output + format.note output + format.isbn output + format.doi output + format.pubmed output + format.url output + format.abstract output + format.file output + fin.entry } -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\Personchild} -% As above, but make first letter uppercase. -% \begin{macrocode} -\newcommand*{\Personchild}[1][anon]{% - \@ifundefined{person@#1@gender}% - {% - \PackageError{person}{Person `#1' has not been defined}{}% - }% - {% - \edef\@gender{\csname person@#1@gender\endcsname}% - \expandafter\expandafter\expandafter\MakeUppercase - \csname\@gender child\endcsname - }% + +FUNCTION {conference} { inproceedings } + +FUNCTION {manual} +{ output.bibitem + "\DTLnewbibitem {EntryType}{manual}%" write$ + newline$ + author empty$ + { organization empty$ +'skip$ +{ format.organization output + format.address output } -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\peoplechild} -% If there is more than one person, \cs{peoplechild} will use -% \cs{malechildren} (if all male), \cs{femalechildren} (if all -% female) or \cs{pluralchild} (if mixed), otherwise it will use -% \cs{personchild}. -% \begin{macrocode} -\newcommand*{\peoplechild}{% - \ifnum\c@people>1\relax - \ifallmale - {\malechildren}% - {\ifallfemale{\femalechildren}{\pluralchild}}% - \else - \@get@firstperson{\@thisperson}% - \personchild[\@thisperson]% - \fi + if$ + } + { format.authors output } + if$ + new.block + format.btitle "title" output.check + author empty$ + { organization empty$ +{ address new.block.checka + address output } -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\Peoplechild} -% As above but first letter is made uppercase. -% \begin{macrocode} -\newcommand*{\Peoplechild}{% - \ifnum\c@people>1\relax - \ifallmale - {\expandafter\MakeUppercase\malechildren}% - {\ifallfemale - {\expandafter\MakeUppercase\femalechildren} - {\expandafter\MakeUppercase\pluralchild}}% - \else - \@get@firstperson{\@thisperson}% - \Personchild[\@thisperson]% - \fi +'skip$ + if$ + } + { %organization address new.block.checkb + format.organization output + format.address output + } + if$ + format.edition output + format.date output + new.block + format.key output + format.note output + format.isbn output + format.doi output + format.pubmed output + format.url output + format.abstract output + format.file output + fin.entry } -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\personparent} -% Display this person's relationship to their child (i.e.\ father -% or mother). -% \begin{macrocode} -\newcommand*{\personparent}[1][anon]{% - \@ifundefined{person@#1@gender}% - {% - \PackageError{person}{Person `#1' has not been defined}{}% - }% - {% - \edef\@gender{\csname person@#1@gender\endcsname}% - \csname\@gender parent\endcsname - }% + +FUNCTION {mastersthesis} +{ output.bibitem + "\DTLnewbibitem {EntryType}{mastersthesis}%" write$ + newline$ + format.authors "author" output.check + new.block + format.title "title" output.check + new.block + "\DTLnewbibitem {Type}{\mscthesisname }" + format.thesis.type output.nonnull + format.school "school" output.check + format.address output + format.date "year" output.check + new.block + format.key output + format.note output + format.isbn output + format.doi output + format.pubmed output + format.url output + format.abstract output + format.file output + fin.entry } -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\Personparent} -% As above, but make the first letter uppercase. -% \begin{macrocode} -\newcommand*{\Personparent}[1][anon]{% - \@ifundefined{person@#1@gender}% - {% - \PackageError{person}{Person `#1' has not been defined}{}% - }% - {% - \edef\@gender{\csname person@#1@gender\endcsname}% - \expandafter\expandafter\expandafter\MakeUppercase - \csname\@gender parent\endcsname - }% + +FUNCTION {misc} +{ output.bibitem + "\DTLnewbibitem {EntryType}{misc}%" write$ + newline$ + format.authors output + title howpublished new.block.checkb + format.title output + %howpublished new.block.checka + format.howpublished output + format.date output + new.block + format.key output + format.note output + format.isbn output + format.doi output + format.pubmed output + format.url output + format.abstract output + format.file output + fin.entry + empty.misc.check } -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\peopleparent} -% If there is more than one person, \cs{peopleparent} will use -% \cs{pluralparent}, otherwise it will use \cs{personparent}. -% \begin{macrocode} -\newcommand*{\peopleparent}{% - \ifnum\c@people>1\relax - \pluralparent - \else - \@get@firstperson{\@thisperson}% - \personparent[\@thisperson]% - \fi + +FUNCTION {phdthesis} +{ output.bibitem + "\DTLnewbibitem {EntryType}{phdthesis}%" write$ + newline$ + format.authors "author" output.check + new.block + format.btitle "title" output.check + new.block + "\DTLnewbibitem {Type}{\phdthesisname }" + format.thesis.type output.nonnull + format.school "school" output.check + format.address output + format.date "year" output.check + new.block + format.key output + format.note output + format.isbn output + format.doi output + format.pubmed output + format.url output + format.abstract output + format.file output + fin.entry } -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\Peopleparent} -% As above, but make first letter uppercase. -% \begin{macrocode} -\newcommand*{\Peopleparent}{% - \ifnum\c@people>1\relax - \expandafter\MakeUppercase\pluralparent - \else - \@get@firstperson{\@thisperson}% - \Personparent[\@thisperson]% - \fi + +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 } -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\personsibling} -% Display this person's relationship to their siblings (i.e.\ -% brother or sister). -% \begin{macrocode} -\newcommand*{\personsibling}[1][anon]{% - \@ifundefined{person@#1@gender}% - {% - \PackageError{person}{Person `#1' has not been defined}{}% - }% - {% - \edef\@gender{\csname person@#1@gender\endcsname}% - \csname\@gender sibling\endcsname - }% + if$ + format.publisher output + format.date "year" output.check + } + { format.address output + format.date "year" output.check + new.sentence + editor empty$ +'skip$ +{ format.organization output } + if$ + format.publisher output + } + if$ + new.block + format.key output + format.note output + format.isbn output + format.doi output + format.pubmed output + format.url output + format.abstract output + format.file output + fin.entry } -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\Personsibling} -% Display this person's relationship to their siblings (i.e.\ -% brother or sister). -% \begin{macrocode} -\newcommand*{\Personsibling}[1][anon]{% - \@ifundefined{person@#1@gender}% - {% - \PackageError{person}{Person `#1' has not been defined}{}% - }% - {% - \edef\@gender{\csname person@#1@gender\endcsname}% - \expandafter\expandafter\expandafter\MakeUppercase - \csname\@gender sibling\endcsname - }% + +FUNCTION {techreport} +{ output.bibitem + "\DTLnewbibitem {EntryType}{techreport}%" write$ + newline$ + format.authors "author" output.check + new.block + format.title "title" output.check + new.block + format.tr.number output.nonnull + format.institution "institution" output.check + format.address output + format.date "year" output.check + new.block + format.key output + format.note output + format.isbn output + format.doi output + format.pubmed output + format.url output + format.abstract output + format.file output + fin.entry } -% \end{macrocode} -%\end{macro} -%\begin{macro}{\peoplesibling} -% If there is more than one person, \cs{peoplesibling} will use -% \cs{malesiblings} (if all male), \cs{femalesiblings} (if all -% female) or \cs{pluralsibling} (if mixed), otherwise it will use -% \cs{personsibling}. -% \begin{macrocode} -\newcommand*{\peoplesibling}{% - \ifnum\c@people>1\relax - \ifallmale - {\malesiblings}% - {\ifallfemale{\femalesiblings}{\pluralsibling}}% - \else - \@get@firstperson{\@thisperson}% - \personsibling[\@thisperson]% - \fi + +FUNCTION {unpublished} +{ output.bibitem + "\DTLnewbibitem {EntryType}{unpublished}%" write$ + newline$ + format.authors "author" output.check + new.block + format.title "title" output.check + new.block + format.key output + format.note output + format.isbn output + format.doi output + format.pubmed output + format.url output + format.abstract output + format.file output + format.date output + fin.entry } -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\persongender} -% Displays the given person's gender (\cs{malename} or -% \cs{femalename}). -% \begin{macrocode} -\newcommand*{\persongender}[1]{% - \ifpersonmale{#1}{\malename}{\femalename}% + +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 := } -% \end{macrocode} -%\end{macro} -% -%\subsection{Extracting Information} -% -%\begin{macro}{\getpersongender} -% Gets person's gender and stores in first argument which must be -% a control sequence. -% \begin{macrocode} -\newcommand*{\getpersongender}[2]{% - \ifpersonmale{#2}{\let#1\malename}{\let#1\femalename}% + +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$ } -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\getpersonname} -% Gets person's name and stores in first argument which must be -% a control sequence. -% \begin{macrocode} -\newcommand*{\getpersonname}[2]{% - \ifpersonexists{#2}% - {% - \expandafter\let\expandafter#1\csname person@#2@name\endcsname - }% - {% - \PackageError{person}{Person `#2' doesn't exist}{}% - }% + +EXECUTE {initialize.longest.label} + +ITERATE {longest.label.pass} + +FUNCTION {begin.bib} +{ preamble$ empty$ + 'skip$ + { preamble$ write$ newline$ } + if$ } -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\getpersonfullname} -% Gets person's full name and stores in first argument which must be -% a control sequence. -% \begin{macrocode} -\newcommand*{\getpersonfullname}[2]{% - \ifpersonexists{#2}% - {% - \expandafter - \let\expandafter#1\csname person@#2@fullname\endcsname - }% - {% - \PackageError{person}{Person `#2' doesn't exist}{}% - }% + +EXECUTE {begin.bib} + +EXECUTE {init.state.consts} + +ITERATE {call.type$} + +FUNCTION {end.bib} +{ } + +EXECUTE {end.bib} % \end{macrocode} -%\end{macro} %\iffalse % \begin{macrocode} -% +% % \end{macrocode} %\fi %\Finale diff --git a/Master/texmf-dist/source/latex/datatool/datatool.ins b/Master/texmf-dist/source/latex/datatool/datatool.ins index a3d3bd39125..ace8870e0cc 100644 --- a/Master/texmf-dist/source/latex/datatool/datatool.ins +++ b/Master/texmf-dist/source/latex/datatool/datatool.ins @@ -1,10 +1,10 @@ -% datatool.ins generated using makedtx version 0.94b 2009/11/15 15:10 +% datatool.ins generated using makedtx version 0.94b 2012/7/19 16:34 \input docstrip \preamble datatool.dtx - Copyright 2009 Nicola Talbot + Copyright 2012 Nicola Talbot This work may be distributed and/or modified under the conditions of the LaTeX Project Public License, either version 1.3 @@ -18,25 +18,32 @@ The Current Maintainer of this work is Nicola Talbot. - This work consists of the files datatool.dtx and datatool.ins and the derived files datatool.sty, datapie.sty, dataplot.sty, databar.sty, databib.sty, databib.bst, person.sty. + This work consists of the files datatool.dtx and datatool.ins and the derived files datatool-base.sty, datatool-fp.sty, datatool-pgfmath.sty, datatool.sty, databib.sty, databar.sty, datapie.sty, dataplot.sty, person.sty, databib.bst. \endpreamble \askforoverwritefalse -\generate{\file{datatool.sty}{\usepreamble\defaultpreamble +\generate{\file{datatool-base.sty}{\usepreamble\defaultpreamble +\usepostamble\defaultpostamble\from{datatool.dtx}{datatool-base.sty,package}} +\file{datatool-fp.sty}{\usepreamble\defaultpreamble +\usepostamble\defaultpostamble\from{datatool.dtx}{datatool-fp.sty,package}} +\file{datatool-pgfmath.sty}{\usepreamble\defaultpreamble +\usepostamble\defaultpostamble\from{datatool.dtx}{datatool-pgfmath.sty,package}} +\file{datatool.sty}{\usepreamble\defaultpreamble \usepostamble\defaultpostamble\from{datatool.dtx}{datatool.sty,package}} +\file{databib.sty}{\usepreamble\defaultpreamble +\usepostamble\defaultpostamble\from{datatool.dtx}{databib.sty,package}} +\file{databar.sty}{\usepreamble\defaultpreamble +\usepostamble\defaultpostamble\from{datatool.dtx}{databar.sty,package}} \file{datapie.sty}{\usepreamble\defaultpreamble \usepostamble\defaultpostamble\from{datatool.dtx}{datapie.sty,package}} \file{dataplot.sty}{\usepreamble\defaultpreamble \usepostamble\defaultpostamble\from{datatool.dtx}{dataplot.sty,package}} -\file{databar.sty}{\usepreamble\defaultpreamble -\usepostamble\defaultpostamble\from{datatool.dtx}{databar.sty,package}} -\file{databib.sty}{\usepreamble\defaultpreamble -\usepostamble\defaultpostamble\from{datatool.dtx}{databib.sty,package}} -\file{databib.bst}{\nopreamble\usepreamble\defaultpreamble\nopostamble\from{datatool.dtx}{databib.bst}} \file{person.sty}{\usepreamble\defaultpreamble \usepostamble\defaultpostamble\from{datatool.dtx}{person.sty,package}} +\file{databib.bst}{\usepreamble\defaultpreamble +\usepostamble\defaultpostamble\from{datatool.dtx}{databib.bst,package}} } \endbatchfile -- cgit v1.2.3