From 2b1511b76524ed6e4b906094ee4a63aacf7d68e5 Mon Sep 17 00:00:00 2001 From: Karl Berry Date: Mon, 16 Nov 2009 01:44:59 +0000 Subject: datalog 2.03 (15nov09) git-svn-id: svn://tug.org/texlive/trunk@16023 c570f23f-e606-0410-a88d-b1316a301751 --- Master/texmf-dist/bibtex/bst/datatool/databib.bst | 7 +- Master/texmf-dist/doc/latex/datatool/CHANGES | 25 + Master/texmf-dist/doc/latex/datatool/README | 216 +- Master/texmf-dist/doc/latex/datatool/datatool.pdf | Bin 1456219 -> 1850660 bytes .../texmf-dist/source/latex/datatool/datatool.dtx | 13302 +++++++++++-------- .../texmf-dist/source/latex/datatool/datatool.ins | 6 +- Master/texmf-dist/tex/latex/datatool/databar.sty | 9 +- Master/texmf-dist/tex/latex/datatool/databib.sty | 9 +- Master/texmf-dist/tex/latex/datatool/datapie.sty | 9 +- Master/texmf-dist/tex/latex/datatool/dataplot.sty | 9 +- Master/texmf-dist/tex/latex/datatool/datatool.sty | 1449 +- Master/texmf-dist/tex/latex/datatool/person.sty | 638 + 12 files changed, 9145 insertions(+), 6534 deletions(-) create mode 100644 Master/texmf-dist/tex/latex/datatool/person.sty diff --git a/Master/texmf-dist/bibtex/bst/datatool/databib.bst b/Master/texmf-dist/bibtex/bst/datatool/databib.bst index 7999f9f6c08..3f779b2f863 100644 --- a/Master/texmf-dist/bibtex/bst/datatool/databib.bst +++ b/Master/texmf-dist/bibtex/bst/datatool/databib.bst @@ -21,8 +21,13 @@ %% %% The Current Maintainer of this work is Nicola Talbot. %% -%% This work consists of the files datatool.dtx and datatool.ins and the derived files datatool.sty, datapie.sty, dataplot.sty, databar.sty, databib.sty, databib.bst. +%% This work consists of the files datatool.dtx and datatool.ins and the derived files datatool.sty, datapie.sty, dataplot.sty, databar.sty, databib.sty, databib.bst, person.sty. %% +%% load student information from file "students.csv" +%% Iterate through the student database: +%% Define "anon": +%% Do the letter: +%% Undefine "anon": ENTRY { address diff --git a/Master/texmf-dist/doc/latex/datatool/CHANGES b/Master/texmf-dist/doc/latex/datatool/CHANGES index 397e19c756b..bee8676f0e6 100644 --- a/Master/texmf-dist/doc/latex/datatool/CHANGES +++ b/Master/texmf-dist/doc/latex/datatool/CHANGES @@ -1,3 +1,28 @@ +v2.03 (2009/11/15): + * Added facility to clear or delete a database. + + * Fixed bug in \DTLsavedb that prints duplicate information to file. + + * \DTLreplaceentryforrow expands the replacement value + + * \DTLappendtorow expands the new value + + * \DTLnewdbentry : user can choose between expanding or not + expanding value before adding to database. + + * Renamed \dtl@columnindex to \dtlcolumnindex so that it can be + used in the document. + + * Spaces may now occur after commas (but not before) in the + assignment part of \DTLforeach + + * Fixed missing backslashes in example in manual (pounds->\pounds) + + * Fixed type in datapie documentation: non-colour option is + "gray" not "monochrome". + + * Added package "person.sty" + v2.02 (2009/07/13): * fixed bug caused by undefined \@dtlifhaskey (should be \@DTLifhaskey) diff --git a/Master/texmf-dist/doc/latex/datatool/README b/Master/texmf-dist/doc/latex/datatool/README index 7ae2effb4ae..0a6d97f88d4 100644 --- a/Master/texmf-dist/doc/latex/datatool/README +++ b/Master/texmf-dist/doc/latex/datatool/README @@ -1,105 +1,111 @@ -LaTeX Bundle : datatool v2.02 (datatool.sty, datapie.sty, dataplot.sty, databar.sty, databib.sty) - -Last Modified : 13th July 2009 - -Author : Nicola Talbot - -datatool.sty: - - Databases can be created using LaTeX commands or loaded - from external ASCII files, such as comma or tab separated - variable files. - - Databases can be sorted numerically or alphabetically - (descending or ascending.) - - Repetitive operations can be performed on each row of - data in a database (such as mail merging.) Conditions - can be imposed to exclude rows. - - Commands are provided to determine if an argument is - an integer, a real number, currency or a string. - (Scientific notation is currently not supported.) - - Locale dependent number settings are supported - (such as a comma as a decimal character and full stop as - a number group character.) - - Commands are provided to convert between locale dependent - numbers/currency and the standard decimal format required - by the fp package enabling fixed point arithmetic to be - performed on elements of the database. - - Strings can be tested to determine if they are all upper - or all lower case. - - Names can be converted to initials using \DTLinitials. - -datapie.sty: - - A database defined by datatool.sty can be converted into a - pie chart. - - Segments can be separated from the rest of the chart to make - them stand out. - - Colour/grey scale options. - - Predefined segment colours can be changed. - - Hooks provided to annotate chart. - -dataplot.sty: - - A database defined by datatool.sty may be plotted as a 2D - scatter or line plot - - Settings provided to govern the appearance of the chart. - (e.g. show/hide axes, legend, grid, major/minor tick marks.) - - Hooks provided to add extra information to the plot - -databar.sty: - - A database defined by datatool.sty can be converted into a - bar chart. - - Colour/grey scale options. - - Predefined bar colours can be changed. - - Horizontal or vertical formats provided. - - Hooks provided to annotate chart. - -databib.sty: - - Provides commands to convert a BibTeX database into a datatool - database. - -*The datatool bundle replaces the csvtools bundle which is now obsolete.* - -REQUIRED PACKAGES: - -The datatool.sty package requires the following packages/files: - -xkeyval -ifthen -xfor -fp -substr -etex - -The datapie.sty, dataplot.sty and databar.sty packages -additionally require the tikz/pgf bundle. - -*Remember to refresh TeX's database* - -The package and documentation source code is also supplied as a -dtx and ins file located in texmf/source. - -This material is subject to the LaTeX Project Public License. -See http://www.ctan.org/tex-archive/help/Catalogue/licenses.lppl.html for the details of that license. - -http://theoval.cmp.uea.ac.uk/~nlct/ - +LaTeX Bundle : datatool v2.03 (datatool.sty, datapie.sty, dataplot.sty, databar.sty, databib.sty) + +Last Modified : 15 November 2009 + +Author : Nicola Talbot + +datatool.sty: + + Databases can be created using LaTeX commands or loaded + from external ASCII files, such as comma or tab separated + variable files. + + Databases can be sorted numerically or alphabetically + (descending or ascending.) + + Repetitive operations can be performed on each row of + data in a database (such as mail merging.) Conditions + can be imposed to exclude rows. + + Commands are provided to determine if an argument is + an integer, a real number, currency or a string. + (Scientific notation is currently not supported.) + + Locale dependent number settings are supported + (such as a comma as a decimal character and full stop as + a number group character.) + + Commands are provided to convert between locale dependent + numbers/currency and the standard decimal format required + by the fp package enabling fixed point arithmetic to be + performed on elements of the database. + + Strings can be tested to determine if they are all upper + or all lower case. + + Names can be converted to initials using \DTLinitials. + +datapie.sty: + + A database defined by datatool.sty can be converted into a + pie chart. + + Segments can be separated from the rest of the chart to make + them stand out. + + Colour/grey scale options. + + Predefined segment colours can be changed. + + Hooks provided to annotate chart. + +dataplot.sty: + + A database defined by datatool.sty may be plotted as a 2D + scatter or line plot + + Settings provided to govern the appearance of the chart. + (e.g. show/hide axes, legend, grid, major/minor tick marks.) + + Hooks provided to add extra information to the plot + +databar.sty: + + A database defined by datatool.sty can be converted into a + bar chart. + + Colour/grey scale options. + + Predefined bar colours can be changed. + + Horizontal or vertical formats provided. + + Hooks provided to annotate chart. + +databib.sty: + + Provides commands to convert a BibTeX database into a datatool + database. + +person.sty: + + Provides commands to display a person's name and pronoun in an + order of service style document to provide consistency, or in mail + merging to eliminate the cumbersome use of ``he/she'' etc. + +*The datatool bundle replaces the csvtools bundle which is now obsolete.* + +REQUIRED PACKAGES: + +The datatool.sty package requires the following packages/files: + +xkeyval +ifthen +xfor +fp +substr +etex + +The datapie.sty, dataplot.sty and databar.sty packages +additionally require the tikz/pgf bundle. + +*Remember to refresh TeX's database* + +The package and documentation source code is also supplied as a +dtx and ins file located in texmf/source. + +This material is subject to the LaTeX Project Public License. +See http://www.ctan.org/tex-archive/help/Catalogue/licenses.lppl.html for the details of that license. + +http://theoval.cmp.uea.ac.uk/~nlct/ + diff --git a/Master/texmf-dist/doc/latex/datatool/datatool.pdf b/Master/texmf-dist/doc/latex/datatool/datatool.pdf index 8cdcba6b253..61220a750bb 100644 Binary files a/Master/texmf-dist/doc/latex/datatool/datatool.pdf and b/Master/texmf-dist/doc/latex/datatool/datatool.pdf differ diff --git a/Master/texmf-dist/source/latex/datatool/datatool.dtx b/Master/texmf-dist/source/latex/datatool/datatool.dtx index 8db14f657ed..fcae77779b6 100644 --- a/Master/texmf-dist/source/latex/datatool/datatool.dtx +++ b/Master/texmf-dist/source/latex/datatool/datatool.dtx @@ -2,20 +2,21 @@ % datatool.dtx generated using makedtx version 0.94b (c) Nicola Talbot % Command line args: % -macrocode "databib.bst" -% -src "datatool.sty\Z=>datatool.sty" -% -src "datapie.sty\Z=>datapie.sty" -% -src "dataplot.sty\Z=>dataplot.sty" -% -src "databar.sty\Z=>databar.sty" -% -src "databib.sty\Z=>databib.sty" -% -src "databib.bst\Z=>databib.bst" +% -src "datatool\.sty\Z=>datatool.sty" +% -src "datapie\.sty\Z=>datapie.sty" +% -src "dataplot\.sty\Z=>dataplot.sty" +% -src "databar\.sty\Z=>databar.sty" +% -src "databib\.sty\Z=>databib.sty" +% -src "databib\.bst\Z=>databib.bst" +% -src "person\.sty\Z=>person.sty" % -author "Nicola Talbot" % -dir "source" % -setambles ".*\.bst=>\nopreamble\usepreamble\defaultpreamble\nopostamble" % -comment "databib.bst" -% -doc "manual.tex" +% -doc "datatool-manual.tex" % -codetitle "datatool.sty" % datatool -% Created on 2009/7/13 10:04 +% Created on 2009/11/15 15:10 %\fi %\iffalse %<*package> @@ -43,15 +44,17 @@ % \iffalse %<*driver> \documentclass[a4paper]{ltxdoc} +\usepackage{dox} \usepackage{ifthen} \usepackage[verbose=false]{datatool} -\usepackage{datapie,databar,databib} +\usepackage{datapie,databar,databib,person} \usepackage{textcomp} \usepackage{graphicx} \usepackage{colortbl} \usepackage{cmap} \usepackage[T1]{fontenc} \usepackage[utf8]{inputenc} +\usepackage{caption} \usepackage[colorlinks, bookmarks, hyperindex=false, @@ -80,7 +83,7 @@ \makeatother \RecordChanges \PageIndex -\CheckSum{15418} +\CheckSum{16375} \newcommand*{\sty}[1]{\textsf{#1}} \newcommand*{\env}[1]{\textsf{#1}} @@ -96,11 +99,6 @@ }} \makeatother -\newcommand*{\counterfmt}[1]{\texttt{#1}\index -{#1 counter=\texttt{#1} counter|hyperpage}} - -\newcommand*{\ics}[1]{\cs{#1}\SpecialMainIndex{#1}} - \newsavebox\defsbox \newlength\defwidth \newenvironment{definition}[1][]{% @@ -118,6 +116,8 @@ \noindent \defarg\fcolorbox{black}{defbackground}{\usebox\defsbox}% \vskip10pt +\noindent +\ignorespacesafterend } \newlength\tmplength @@ -133,6 +133,14 @@ \hangafter=-2\relax } +\doxitem{Counter}{counter}{counters} + +\newcommand*{\ctrfmt}[1]{\texttt{#1}} +\newcommand*{\ctr}[1]{\ctrfmt{#1}\SpecialMainCounterIndex{#1}} +\newcommand*{\desctr}[1]{\ctrfmt{#1}\DescribeCounter{#1}} + +\newcommand*{\ics}[1]{\cs{#1}\SpecialMainIndex{#1}} + \newcommand*{\pkgopt}[2][datatool]{\textsf{#2}\index {#1 package options=\textsf{#1} package options>#2=\textsf{#2}|hyperpage}} @@ -173,7 +181,7 @@ options>#2=\textsf{#2}|hyperpage}} %\MakeShortVerb{"} %\DeleteShortVerb{\|} % -% \title{datatool v 2.02: Databases and data manipulation} +% \title{datatool v 2.03: Databases and data manipulation} % \author{Nicola L.C. Talbot\\[10pt] %School of Computing Sciences\\ %University of East Anglia\\ @@ -181,11 +189,16 @@ options>#2=\textsf{#2}|hyperpage}} %NR4 7TJ. United Kingdom.\\ %\url{http://theoval.cmp.uea.ac.uk/~nlct/}} % -% \date{13th July 2009} +% \date{15th November 2009} % \maketitle +% +%\pdfbookmark[1]{Contents}{contents} %\tableofcontents +%\pdfbookmark[1]{List of Examples}{examples} %\listofexamples +%\pdfbookmark[1]{List of Figures}{figures} %\listoffigures +%\pdfbookmark[1]{List of Tables}{tables} %\listoftables % % \section{Introduction} @@ -1930,6 +1943,12 @@ options>#2=\textsf{#2}|hyperpage}} %This command displays the number of rows in the database called %\meta{db name}. % +%\begin{definition}[\DescribeMacro{\DTLcolumncount}]% +%\cs{DTLcolumncount}\marg{db name} +%\end{definition} +%This command displays the number of columns (or keys) in the +%database called \meta{db name}. +% %\begin{definition}[\DescribeMacro{\DTLnewrow}]% %\cs{DTLnewrow}\marg{db name} %\end{definition} @@ -1967,7 +1986,11 @@ options>#2=\textsf{#2}|hyperpage}} %\DTLrowcount{mydata} %\end{verbatim} %which produces: -%\DTLrowcount{mydata}. +%\DTLrowcount{mydata}. The column count is given by +%\begin{verbatim} +%\DTLcolumncount{mydata} +%\end{verbatim} +%which produces: \DTLcolumncount{mydata}. % %\begin{definition}[\DescribeMacro{\DTLnewdbentry}]% %\cs{DTLnewdbentry}\marg{db name}\marg{key}\marg{value} @@ -1986,6 +2009,17 @@ options>#2=\textsf{#2}|hyperpage}} %key should not contain any fragile commands. It is generally %best to only use non-active characters in the key. % +%The value isn't expanded by default, but you can change this +%using the declaration: +%\begin{definition}[\DescribeMacro{\dtlexpandnewvalue}] +%\cs{dtlexpandnewvalue} +%\end{definition} +%This can be localised by placing it in a group, or you can +%switch back using: +%\begin{definition}[\DescribeMacro{\dtlnoexpandnewvalue}] +%\cs{dtlnoexpandnewvalue} +%\end{definition} +% %\importantpar Note that database entries can't contain paragraph %breaks as many of the macros used by \sty{datatool} are short %commands. If you do need a paragraph break in an entry, you can @@ -2016,6 +2050,8 @@ options>#2=\textsf{#2}|hyperpage}} %{\DTLiseq{\firstname}{John}\and\DTLiseq{\surname}{Smith}}% %{Score}{75} %\end{verbatim} +%Note that unlike \cs{DTLnewdbentry}, the value is always expanded +%when adding an entry using \cs{DTLaddentryforrow}. % %\begin{definition}[\DescribeMacro{\DTLsetheader}]% %\cs{DTLsetheader}\marg{db}\marg{key}\marg{header} @@ -2177,7 +2213,7 @@ options>#2=\textsf{#2}|hyperpage}} %\cs{DTLloadrawdb}]{Special character mappings used by %\cs{DTLloadrawdb} (note that the backslash retains its active state)} %\label{tab:rawmappings} -%\begin{center} +%\centering %\begin{tabular}{cl} %Character & Mapping\\ %\verb|%| & \verb|\%|\\ @@ -2190,7 +2226,6 @@ options>#2=\textsf{#2}|hyperpage}} %\verb|~| & \cs{textasciitilde}\\ %\verb|^| & \cs{textasciicircum} %\end{tabular} -%\end{center} %\end{table} % %It may be that there are other characters that require mapping. @@ -2204,7 +2239,7 @@ options>#2=\textsf{#2}|hyperpage}} %\vskip\baselineskip %The pound character is not an internationally standard keyboard %character, and does not generally achieve the desired effect when used -%in a \LaTeX\ document. It will therefore be necessary to convert +%in a \LaTeX\ document. It may therefore be necessary to convert %this symbol to an appropriate control sequence. This can be done %using the command: %\begin{definition}[\DescribeMacro{\DTLrawmap}]% @@ -2249,8 +2284,8 @@ options>#2=\textsf{#2}|hyperpage}} %\end{definition} %This is like \cs{DTLdisplaydb} except that it uses the %\env{longtable} environment instead of the \env{tabular} -%environment. Note that if you use this command, you must load -%\sty{longtable}, as it is not loaded by \sty{datatool}. +%environment. Note that if you use this command, you must load the +%\sty{longtable} package, as it is not loaded by \sty{datatool}. %The optional argument \meta{options} is a comma-separated list %of key=value pairs. The following keys are available: %\begin{description} @@ -2337,7 +2372,6 @@ options>#2=\textsf{#2}|hyperpage}} %\begin{verbatim} %\begin{table}[htbp] %\caption{Time to Growth Data} -%\vspace{\baselineskip} %\centering %\DTLdisplaydb{t2g} %\end{table} @@ -2346,7 +2380,6 @@ options>#2=\textsf{#2}|hyperpage}} %\begin{table}[htbp] %\caption{Time to Growth Data} %\label{tab:t2g} -%\vspace{\baselineskip} %\centering %\DTLdisplaydb{t2g} %\end{table} @@ -2524,8 +2557,8 @@ options>#2=\textsf{#2}|hyperpage}} %\DTLsetheader{balance}{Balance}{Balance (\pounds)}\relax %The data can be loaded using: %\begin{verbatim} -%\DTLloaddb[headers={Description,In (\pounds),Out (pounds),Balance -%(pounds)}]{balance}{balance.csv} +%\DTLloaddb[headers={Description,In (\pounds),Out (\pounds),Balance +%(\pounds)}]{balance}{balance.csv} %\end{verbatim} % %Suppose I want negative numbers to be displayed in red. I can do @@ -2535,7 +2568,6 @@ options>#2=\textsf{#2}|hyperpage}} %\begin{table}[htbp] %\caption{Balance Sheet} %\renewcommand*{\dtlrealformat}[1]{\DTLiflt{#1}{0}{\color{red}}{}#1} -%\vspace{\baselineskip} %\centering %\DTLdisplaydb{balance} %\end{table} @@ -2545,7 +2577,6 @@ options>#2=\textsf{#2}|hyperpage}} %\caption{Balance Sheet} %\label{tab:balance} %\renewcommand*{\dtlrealformat}[1]{\DTLiflt{#1}{0}{\color{red}}{}#1} -%\vspace{\baselineskip} %\centering %\DTLdisplaydb{balance} %\end{table} @@ -2676,9 +2707,9 @@ options>#2=\textsf{#2}|hyperpage}} % %The macro \ics{DTLforeach} may be nested up to three times. Each %level uses the corresponding counters: -%\counterfmt{DTLrowi}, -%\counterfmt{DTLrowii} and -%\counterfmt{DTLrowiii} which keep track of +%\desctr{DTLrowi}, +%\desctr{DTLrowii} and +%\desctr{DTLrowiii} which keep track of %the current row. % %\importantpar Note that these counters are only incremented when @@ -2738,33 +2769,6 @@ options>#2=\textsf{#2}|hyperpage}} %the column have mixed types, it may not correspond to the type %of the current entry. % -%\begin{definition}[\DescribeMacro{\dtlforeachkey}]% -%\cs{dtlforeachkey}(\meta{key cs},\meta{col cs},\meta{type -%cs},\meta{header cs})\cs{in}\marg{db}\cs{do}\marg{body} -%\end{definition} -%This iterates through all the keys in the database given by -%\meta{db}. In each iteration, \meta{key cs} is set to the key, -%\meta{col cs} is set to the column index, \meta{type cs} is -%set to the data type, \meta{header cs} is set to the header -%for that column, and then \meta{body} is done. Note that -%\meta{key cs}, \meta{col cs}, \meta{type cs} and \meta{header cs} -%must all be control sequences. No check is performed to determine -%if that control sequence already exists, and the control -%sequences are defined globally (since it's likely that -%\cs{dtlforeachkey} may be used within a \env{tabular} -%environment), so you need to make sure you don't override an -%existing command of the same name. The data type may have the -%following values: 0 (string), 1 (integer), 2 (real number), 3 -%(currency) or it will be empty if the column has no entries. -% -%\begin{definition}[\DescribeMacro{\dtlforcolumn}]% -%\cs{dtlforcolumn}\marg{cs}\marg{db}\marg{key}\marg{body} -%\end{definition} -%This iterates through the column given by \meta{key} in the -%database given by \meta{db} and applies \meta{body}. In each -%iteration, \meta{cs} (which must be a control sequence) is set to -%the current element in the column and may be used in \meta{body}. -% %\begin{definition}[\DescribeMacro{\dtlbreak}]% %\cs{dtlbreak} %\end{definition} @@ -2927,7 +2931,7 @@ options>#2=\textsf{#2}|hyperpage}} % %\begin{example}{Breaking Out of a Loop}{ex:dtlbreak} %Suppose I only want to display the first three rows of a database. -%I could do:\footnote{Recall that \counterfmt{DTLrowi} is incremented +%I could do:\footnote{Recall that \ctr{DTLrowi} is incremented %after the condition is tested, so it will be out by 1 when the %condition is tested which is why \texttt{<3} is used instead of %\texttt{<4}.} @@ -2946,7 +2950,6 @@ options>#2=\textsf{#2}|hyperpage}} %\begin{table}[htbp] %\caption{First Three Rows} %\centering -%\vskip\baselineskip %\begin{tabular}{llr} %\bfseries First Name & \bfseries Surname & \bfseries Score (\%)% %\DTLforeach*{scores}% @@ -2963,7 +2966,7 @@ options>#2=\textsf{#2}|hyperpage}} %finished until the third row is completed. (Recall that %\cs{DTLcurrentindex} must be used before the first instance of %\verb|\\| or \verb|&|.) Alternatively, you can use -%\counterfmt{DTLrowi} instead: +%\ctr{DTLrowi} instead: %\begin{verbatim} %\DTLforeach{scores}% %{\firstname=FirstName,\surname=Surname,\score=Score}{% @@ -2976,7 +2979,6 @@ options>#2=\textsf{#2}|hyperpage}} %\caption{First Three Rows} %\label{tab:dtlbreak}% %\centering -%\vskip\baselineskip %\begin{tabular}{llr} %\bfseries First Name & \bfseries Surname & \bfseries Score (\%)\relax %\DTLforeach*{scores}% @@ -3077,7 +3079,6 @@ options>#2=\textsf{#2}|hyperpage}} %\begin{verbatim} %\begin{table}[htbp] %\caption{Student Scores (Iterating Through Keys)} -%\vskip\baselineskip %\centering %\begin{tabular}{llll} %\bfseries First Name & \bfseries Surname & @@ -3093,7 +3094,6 @@ options>#2=\textsf{#2}|hyperpage}} %\begin{table}[htbp] %\caption{Student Scores (Iterating Through Keys)} %\label{tab:foreachkey} -%\vskip\baselineskip %\centering %\begin{tabular}{llll} %\bfseries First Name & \bfseries Surname & @@ -3120,7 +3120,6 @@ options>#2=\textsf{#2}|hyperpage}} %\begin{verbatim} % \begin{table}[htbp] % \caption{Student Scores} -% \vskip\baselineskip % \centering % % Work out the column alignments. % \def\colalign{}% @@ -3145,7 +3144,6 @@ options>#2=\textsf{#2}|hyperpage}} %\caption{Student Scores (Using \cs{dtlforeachkey} and %\cs{DTLforeachkeyinrow})} %\label{tab:foreachkey2} -%\vskip\baselineskip %\centering %\def\colalign{}% %\dtlforeachkey(\theKey,\theCol,\theType,\theHead)\in{scores}\do @@ -3211,7 +3209,6 @@ options>#2=\textsf{#2}|hyperpage}} %\begin{verbatim} %\begin{table}[htbp] %\caption{Student Scores (Filtering Out a Column)} -%\vskip\baselineskip %\centering %\def\colalign{}% %\dtlforeachkey(\theKey,\theCol,\theType,\theHead)\in{scores}\do @@ -3233,7 +3230,6 @@ options>#2=\textsf{#2}|hyperpage}} %\begin{table}[htbp] %\caption{Student Scores (Filtering Out a Column)} %\label{tab:foreachkey3} -%\vskip\baselineskip %\centering %\def\colalign{}% %\dtlforeachkey(\theKey,\theCol,\theType,\theHead)\in{scores}\do @@ -3437,7 +3433,6 @@ options>#2=\textsf{#2}|hyperpage}} %\begin{verbatim} %\begin{table}[htbp] %\caption{Club Membership} -%\vskip\baselineskip %\centering %\begin{tabular}{lll} %\bfseries First Name & \bfseries Surname & \bfseries Status @@ -3453,7 +3448,6 @@ options>#2=\textsf{#2}|hyperpage}} %\begin{table}[htbp] %\caption{Club Membership} %\label{tab:dyn} -%\vskip\baselineskip %\centering %\begin{tabular}{lll} %\bfseries First Name & \bfseries Surname & \bfseries Status @@ -3559,9 +3553,9 @@ options>#2=\textsf{#2}|hyperpage}} %for this database as a numerical key, since all elements in the %database with that key are numerical, whereas it has %identified the key "Email2" as a string, since there is at least -%one element in this database with that key that is a string. -%Null numerical values are set to \cs{DTLnumbernull} (0), -%and null strings are set to \cs{DTLstringnull} (NULL). +%one element in this database with that key that is a string. Null +%numerical values are set to \cs{DTLnumbernull} (\DTLnumbernull), and +%null strings are set to \cs{DTLstringnull} (\DTLstringnull). % %The following code checks each value to determine whether it %is null using \cs{DTLifnull}. If it is, the text \emph{Missing} @@ -3663,6 +3657,19 @@ options>#2=\textsf{#2}|hyperpage}} %\subsection{Editing Database Rows} %\label{sec:editdb} % +%A row can be removed from a data base using: +%\begin{definition}[\DescribeMacro{\DTLremoverow}]% +%\cs{DTLremoverow}\marg{db name}\marg{row index} +%\end{definition} +%where \meta{row index} is the index of the unwanted row. For +%example: +%\begin{verbatim} +%\DTLremoverow{scores}{2} +%\end{verbatim} +%will delete the second row in the database labelled ``scores''. +%There is also a starred version that doesn't check for the +%existence of the database. +% %In the body of the \ics{DTLforeach} loop,\footnote{Only the %unstarred version of \cs{DTLforeach}; the starred version is %read-only.}\ you can use the following to edit the current row: @@ -3671,11 +3678,13 @@ options>#2=\textsf{#2}|hyperpage}} %\end{definition} %This appends a new entry with the given \meta{key} and \meta{value} %to the current row. +%(\meta{value} is expanded.) % %\begin{definition}[\DescribeMacro{\DTLreplaceentryforrow}]% %\cs{DTLreplaceentryforrow}\marg{key}\marg{value} %\end{definition} -%This replaces the entry for \meta{key} with \meta{value}. +%This replaces the entry for \meta{key} with \meta{value}. +%(\meta{value} is expanded.) % %\begin{definition}[\DescribeMacro{\DTLremoveentryfromrow}]% %\cs{DTLremoveentryfromrow}\marg{key} @@ -4075,6 +4084,9 @@ options>#2=\textsf{#2}|hyperpage}} %} %\end{document} %\end{verbatim} +% +%To determine a person's gender when mail merging, see +%\autoref{sec:person}. %\end{example} % %\subsection{Sorting a Database} @@ -4395,6 +4407,162 @@ options>#2=\textsf{#2}|hyperpage}} %a combination of \ics{DTLnewdb}, \ics{DTLnewrow} and %\ics{DTLnewdbentry} commands. % +%\subsection{Deleting or Clearing a Database}\label{sec:deletedb} +% +%A database can be cleared or deleted when its contents are no +%longer required. +%\begin{definition}[\DescribeMacro{\DTLcleardb}] +%\cs{DTLcleardb}\marg{db name} +%\end{definition} +%Clears the database given by \meta{db name}. The database is emptied +%but remains defined. +% +%\begin{definition}[\DescribeMacro{\DTLdeletedb}] +%\cs{DTLdeletedb}\marg{db name} +%\end{definition} +%Deletes (undefines) the database given by \meta{db name}. +% +%\subsection{Advanced Database Commands} +% +%This section describes more advanced commands. Further details +%can be found in \autoref{sec:code:datatool}. +% +%\begin{definition}[\DescribeMacro{\DTLgetdatatype}] +%\cs{DTLgetdatatype}\marg{cs}\marg{db}\marg{key} +%\end{definition} +%Gets the data type for the given key \meta{key} for the database +%given by \meta{db}. The data type is stored in \meta{cs} which +%must be a command name. The type will be one of: +%\begin{itemize} +%\item\DescribeMacro{\DTLunsettype}\cs{DTLunsettype} (not set), +%\item\DescribeMacro{\DTLstringtype}\cs{DTLstringtype} (string), +%\item\DescribeMacro{\DTLinttype}\cs{DTLinttype} (integer), +%\item\DescribeMacro{\DTLrealtype}\cs{DTLrealtype} (real number) or +%\item\DescribeMacro{\DTLcurrencytype}\cs{DTLcurrenttype} (currency). +%\end{itemize} +% +%\begin{definition}[\DescribeMacro{\dtlforeachkey}]% +%\cs{dtlforeachkey}(\meta{key cs},\meta{col cs},\meta{type +%cs},\meta{header cs})\cs{in}\marg{db}\cs{do}\marg{body} +%\end{definition} +%This iterates through all the keys in the database given by +%\meta{db}. In each iteration, \meta{key cs} is set to the key, +%\meta{col cs} is set to the column index, \meta{type cs} is set to +%the data type (as for \cs{DTLgetdatatype}), \meta{header cs} is set +%to the header for that column, and then \meta{body} is done. Note +%that \meta{key cs}, \meta{col cs}, \meta{type cs} and \meta{header +%cs} must all be control sequences. No check is performed to +%determine if that control sequence already exists, and the control +%sequences are defined globally (since it's likely that +%\cs{dtlforeachkey} may be used within a \env{tabular} environment), +%so you need to make sure you don't override an existing command of +%the same name. +% +%\begin{definition}[\DescribeMacro{\dtlforcolumn}]% +%\cs{dtlforcolumn}\marg{cs}\marg{db}\marg{key}\marg{body} +%\end{definition} +%This iterates through the column given by \meta{key} in the +%database given by \meta{db} and applies \meta{body}. In each +%iteration, \meta{cs} (which must be a control sequence) is set to +%the current element in the column and may be used in \meta{body}. +%Alternatively, if you want to identify the column by its index +%rather than its key, use: +%\begin{definition}[\DescribeMacro{\dtlforcolumnindex}]% +%\cs{dtlforcolumnindex}\marg{cs}\marg{db}\marg{col index}\marg{body} +%\end{definition} +% +%\begin{definition}[\DescribeMacro{\DTLifdbexists}] +%\cs{DTLifdbexists}\marg{db name}\marg{true part}\marg{false part} +%\end{definition} +%Determines if the database given by \meta{db name} exists. +% +%\begin{definition}[\DescribeMacro{\DTLifhaskey}] +%\cs{DTLifhaskey}\marg{db name}\marg{key}\marg{true part}\marg{false part} +%\end{definition} +%This determines if the database given by \meta{db name} has +%any entries with the key given by \meta{key}. If so, it does +%\meta{true part} otherwise it does \meta{false part}. +% +%Each key has an associated column index. This can be obtained +%using: +%\begin{definition}[\DescribeMacro{\DTLgetcolumnindex}] +%\cs{DTLgetcolumnindex}\marg{cs}\marg{db}\marg{key} +%\end{definition} +%where \meta{cs} is a command name, \meta{db} is the database label +%and \meta{key} is the key. The column index is stored in +%\meta{cs}. +% +%You can also do the reverse and find the key associated with a +%given column index: +%\begin{definition}[\DescribeMacro{\DTLgetkeyforcolumn}] +%\cs{DTLgetkeyforcolumn}\marg{key cs}\marg{db}\marg{column index} +%\end{definition} +%The key is stored in \meta{key cs} (which must be a command name). +% +%There is also a full expandable way of obtaining the column +%index, but note that no check is performed to determine +%if the database exists, or if it contains the given key: +%\begin{definition}[\DescribeMacro{\dtlcolumnindex}] +%\cs{dtlcolumnindex}\marg{db name}\marg{key} +%\end{definition} +% +%\begin{definition}[\DescribeMacro{\DTLgetkeydata}] +%\cs{DTLgetkeydata}\marg{key}\marg{db}\marg{col cs}\marg{type cs}\marg{header cs} +%\end{definition} +%Gets data for given key in database \meta{db}: the column index is +%stored in \meta{col cs} (as \cs{DTLgetcolumnindex}), the type is +%stored in \meta{type cs} (as \cs{DTLgetdatatype}) and the header +%is stored in \meta{header cs}. +% +%\begin{definition}[\DescribeMacro{\DTLgetvalue}] +%\cs{DTLgetvalue}\marg{cs}\marg{db}\marg{r}\marg{c} +%\end{definition} +%This gets the value for row given by index \meta{r} and column +%given by \meta{c} for the database \meta{db} and stores it in +%\meta{cs} which must be a command name. If you want to get the +%value by key rather than column index you can use +%\cs{dtlcolumnindex}. For example, the following gets the value +%for row~3 with key \texttt{Surname} from the database +%\texttt{data} and stores in \cs{myval}: +%\begin{verbatim} +%\DTLgetvalue{\myval}{data}{3}{\dtlcolumnindex{data}{Surname}} +%\end{verbatim} +% +%\begin{definition}[\DescribeMacro{\DTLgetlocation}] +%\cs{DTLgetlocation}\marg{row cs}\marg{column cs}\marg{database}% +%\marg{value} +%\end{definition} +%Assigns \meta{row cs} and \meta{column cs} to the indices of the +%first entry in \meta{database} that matches \meta{value}. +% +%\begin{definition}[\DescribeMacro{\DTLgetvalueforkey}] +%\cs{DTLgetvalueforkey}\marg{cmd}\marg{key}\marg{db name}\marg{ref +% key}\marg{ref value} +%\end{definition} +%This (globally) sets \meta{cmd} (a control sequence) to the +%value of the key specified by \meta{key} in the first row +%of the database called \meta{db name} which contains the key +%\meta{ref key} which has the value \meta{value}. +% +%Two rows can be swapped using: +%\begin{definition}[\DescribeMacro{\DTLswaprows}]% +%\cs{DTLswaprows}\marg{db name}\marg{row1 index}\marg{row2 index} +%\end{definition} +%where \meta{row1 index} and \meta{row2 index} are the indices +%of the rows to be swapped. For example: +%\begin{verbatim} +%\DTLswaprows{scores}{3}{5} +%\end{verbatim} +%will swap the third and fifth rows. +% +%\begin{definition}[\DescribeMacro{\DTLifinlist}] +%\cs{DTLifinlist}\marg{element}\marg{list}\marg{true part}\marg{false part} +%\end{definition} +%If \meta{element} is contained in the comma-separated list given +%by \meta{list}, then do \meta{true part} otherwise do false +%part. (Does a one level expansion on \meta{list}, but no +%expansion on \meta{element}.) +% %\section{Pie Charts (\texorpdfstring{\sty{datapie}}{datapie} package)} % %The \sty{datapie} package is not loaded by the \sty{datatool} package, @@ -4404,7 +4572,7 @@ options>#2=\textsf{#2}|hyperpage}} %may be given the following options: %\begin{description} %\item[{\pkgopt[datapie]{color}}] Colour option (default). -%\item[{\pkgopt[datapie]{monochrome}}] Monochrome option. +%\item[{\pkgopt[datapie]{gray}}] Grey scale option. %\item[{\pkgopt[datapie]{rotateinner}}] %Rotate inner labels so that they are aligned %with the pie chart radial axis. @@ -4707,7 +4875,7 @@ options>#2=\textsf{#2}|hyperpage}} %This command is set to the percentage value of \cs{DTLpievariable}. %The percentage value is rounded to \meta{n} digits, where \meta{n} %is the value of the \LaTeX\ counter -%\counterfmt{DTLpieroundvar}. +%\desctr{DTLpieroundvar}. % %\begin{example}{Changing the Inner and Outer Labels}{ex:pielabels} %This example uses the database defined in \autoref{ex:piechart}. @@ -5109,13 +5277,13 @@ options>#2=\textsf{#2}|hyperpage}} %separated list of labels for each $x$ tick mark. If omitted, %the labels are the value of the $x$ tick position, rounded %\meta{n} digits after the decimal point, where \meta{n} is -%given by the value of the counter \counterfmt{DTLplotroundXvar}. +%given by the value of the counter \ctr{DTLplotroundXvar}. % %\item[\setting{DTLplot}{yticlabels}] The value must be a comma %separated list of labels for each $y$ tick mark. If omitted, %the labels are the value of the $y$ tick position, rounded %\meta{n} digits after the decimal point, where \meta{n} is -%given by the value of the counter \counterfmt{DTLplotroundYvar}. +%given by the value of the counter \ctr{DTLplotroundYvar}. % %\item[\setting{DTLplot}{xlabel}] The value is the label for %the $x$ axis. If omitted, the axis has no label. @@ -5433,21 +5601,21 @@ options>#2=\textsf{#2}|hyperpage}} %created using \ics{DTLplot}. The value of the counters can be %changed using \cs{setcounter}. % -%\begin{definition} -%\counterfmt{DTLplotroundXvar} +%\begin{definition}[\DescribeCounter{DTLplotroundXvar}] +%\ctrfmt{DTLplotroundXvar} %\end{definition} %Unless you specify your own tick labels, the $x$ tick labels will %be given by the tick points rounded to \meta{n} digits after the %decimal point, where \meta{n} is the value of the counter -%\counterfmt{DTLplotroundXvar}. +%\ctrfmt{DTLplotroundXvar}. % -%\begin{definition} -%\counterfmt{DTLplotroundYvar} +%\begin{definition}[\DescribeCounter{DTLplotroundYvar}] +%\ctrfmt{DTLplotroundYvar} %\end{definition} %Unless you specify your own tick labels, the $y$ tick labels will %be given by the tick points rounded to \meta{n} digits after the %decimal point, where \meta{n} is the value of the counter -%\counterfmt{DTLplotroundYvar}. +%\ctrfmt{DTLplotroundYvar}. % %\subsubsection{Macros} %These macros govern the appearance of plots created using @@ -5674,7 +5842,7 @@ options>#2=\textsf{#2}|hyperpage}} %used after the legend is plotted. The $x$ and $y$ unit vectors %are set before \ics{DTLplotatbegintikz} so I don't need to %worry about the co-ordinates. -%\item I set the counter \counterfmt{DTLplotroundXvar} to zero +%\item I set the counter \ctr{DTLplotroundXvar} to zero %otherwise the $x$ axis would have looked too cluttered. %\item I have used \ics{DTLminforkeys} and \ics{DTLmaxforkeys} to %determine the bounds since \ics{DTLplot} won't take the data @@ -5894,12 +6062,12 @@ options>#2=\textsf{#2}|hyperpage}} %You must use \cs{setlength} to change this value. The default value %is 10pt. % -%\begin{definition} -%\counterfmt{DTLbarroundvar} +%\begin{definition}[\DescribeCounter{DTLbarroundvar}] +%\ctrfmt{DTLbarroundvar} %\end{definition} %The $y$ tick labels are rounded to \meta{n} digits after the %decimal point, where \meta{n} is given by the value of the -%counter \counterfmt{DTLbarroundvar}. You must use \cs{setcounter} +%counter \ctrfmt{DTLbarroundvar}. You must use \cs{setcounter} %to change this value. % %\begin{definition}[\DescribeMacro{\DTLsetbarcolor}]% @@ -6667,7 +6835,7 @@ options>#2=\textsf{#2}|hyperpage}} % %Note that \cs{DTLbibliography} uses \cs{DTLforeachbibentry} %(described in \autoref{sec:foreachbib}) so you may also use -%test the value of the counter \counterfmt{DTLbibrow} within +%test the value of the counter \ctr{DTLbibrow} within %\meta{conditions}. You may also use the boolean commands defined %by the \sty{ifthen} package, such as \ics{not}. % @@ -6891,23 +7059,23 @@ options>#2=\textsf{#2}|hyperpage}} %} %\end{verbatim} % -%\begin{definition} -%\counterfmt{DTLmaxauthors} +%\begin{definition}[\DescribeCounter{DTLmaxauthors}] +%\ctrfmt{DTLmaxauthors} %\end{definition} -%The counter \counterfmt{DTLmaxauthors} is used to determine the +%The counter \ctrfmt{DTLmaxauthors} is used to determine the %maximum number of authors to display for a given entry. If the %entry's author list contains more than that number of authors, %\cs{etalname} is used, the definition of which is given in %\autoref{sec:src:bibnames}. The default value of -%\counterfmt{DTLmaxauthors} is \theDTLmaxauthors. +%\ctrfmt{DTLmaxauthors} is \theDTLmaxauthors. % -%\begin{definition} -%\counterfmt{DTLmaxeditors} +%\begin{definition}[\DescribeCounter{DTLmaxeditors}] +%\ctrfmt{DTLmaxeditors} %\end{definition} -%The \counterfmt{DTLmaxeditors} counter is analogous to the -%\counterfmt{DTLmaxauthors} counter. It is used to determine the +%The \ctrfmt{DTLmaxeditors} counter is analogous to the +%\ctrfmt{DTLmaxauthors} counter. It is used to determine the %maximum number of editor names to display. The default value -%of \counterfmt{DTLmaxeditors} is \theDTLmaxeditors. +%of \ctrfmt{DTLmaxeditors} is \theDTLmaxeditors. % %\DescribeMacro{\DTLandlast} %Within a list of author or editor names, \cs{DTLandlast} is @@ -7116,7 +7284,7 @@ options>#2=\textsf{#2}|hyperpage}} %is stored in \meta{cmd}, which may then be used in the %argument of the \env{thebibliography} environment. % -%The counter \counterfmt{DTLbibrow} keeps track of the current +%The counter \desctr{DTLbibrow} keeps track of the current %bibliography entry. This is reset at the start of each %\cs{DTLforeachbib} and is incremented if \meta{conditions} %is met. @@ -7293,138 +7461,605 @@ options>#2=\textsf{#2}|hyperpage}} %database using \ics{DTLnewdb} and setting \ics{DTLBIBdbname} to %the name of the database. % -% \StopEventually{\clearpage\phantomsection -%\addcontentsline{toc}{section}{\refname} -% \DTLbibliography{docbib} -%\section{Acknowledgements} -% -%Many thanks to Morten~H\o gholm for suggesting a much more -%efficient way of storing the information in databases which -%has significantly improved the time it takes to \LaTeX\ documents -%containing large databases. +%\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} % -%\phantomsection -%\addcontentsline{toc}{section}{Change History}\PrintChanges -%\phantomsection -%\addcontentsline{toc}{section}{Index}\PrintIndex -%} +%The total number of defined people is given by: +%\begin{definition}[\DescribeMacro{\thepeople}] +%\cs{thepeople} +%\end{definition} % +%A person can be undefined using: +%\begin{definition}[\DescribeMacro{\removeperson}] +%\cs{removeperson}\oarg{label} +%\end{definition} +%where the person is given by \meta{label}. % +%If more than one person has been defined, they can all be +%removed using: +%\begin{definition}[\DescribeMacro{\removeallpeople}] +%\cs{removeallpeople} +%\end{definition} +%or you can remove a subset using: +%\begin{definition}[\DescribeMacro{\removepeople}] +%\cs{removepeople}\marg{list} +%\end{definition} +%where \meta{list} is a comma-separated list of labels. % -%\section{datatool.sty} -%\iffalse -% \begin{macrocode} -%<*datatool.sty> -% \end{macrocode} -%\fi -%\subsection{Package Declaration} -% \begin{macrocode} -\NeedsTeXFormat{LaTeX2e} -\ProvidesPackage{datatool}[2009/07/13 v2.02 (NLCT)] -% \end{macrocode} -% Load required packages: -% \begin{macrocode} -\RequirePackage{xkeyval} -\RequirePackage{ifthen} -\RequirePackage{xfor} -\RequirePackage{fp} -\RequirePackage{substr} -% \end{macrocode} -%\changes{2.0}{2009 February 27}{added etex as a required package} -% \begin{macrocode} -\RequirePackage{etex} -% \end{macrocode} +%\subsection{Displaying Information} +%\label{sec:refperson} % -%\subsection{Package Options} -%\begin{macro}{\@dtl@separator} -% The data separator character (comma by default) is stored in -% \cs{@dtl@separator}. -% This is the separator used in external data files, not in the -% \LaTeX\ code, which always uses a comma separator. -% \begin{macrocode} -\newcommand*{\@dtl@separator}{,} -% \end{macrocode} -%\end{macro} -%\begin{macro}{\DTLsetseparator} -%\begin{definition} -%\cs{DTLsetseparator}\marg{char} +%Once a person has been defined, you can display their name using: +%\begin{definition}[\DescribeMacro{\personfullname}] +%\cs{personfullname}\oarg{label} %\end{definition} -% The sets \cs{@dtl@separator}, and constructs the relevent macros -% that require this character to be hardcoded into their definition. -% \begin{macrocode} -\newcommand*{\DTLsetseparator}[1]{% -\renewcommand*{\@dtl@separator}{#1}% -\@dtl@construct@lopoffs -} -% \end{macrocode} -%\end{macro} -%\begin{macro}{\DTLsettabseparator} -%\cs{DTLsettabseparator} makes it easier to set a tab separator. -% \begin{macrocode} -\begingroup -\catcode`\ 12 -\gdef\DTLsettabseparator{% - \catcode`\ 12 - \DTLsetseparator{ }% -} -\endgroup -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@dtl@delimiter} -% The data delimiter character (double quote by default) is stored -% in \cs{@dtl@delimiter}. This is used in external data files, not -% in the \LaTeX\ code. -% \begin{macrocode} -\begingroup -\catcode`\"12\relax -\gdef\@dtl@delimiter{"} -\endgroup -% \end{macrocode} -%\end{macro} -%\begin{macro}{\DTLsetdelimiter} -%\begin{definition} -%\cs{DTLsetdelimiter}\marg{char} +%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} -% This sets the delimiter. -% \begin{macrocode} -\newcommand*\DTLsetdelimiter[1]{% -\renewcommand*{\@dtl@delimiter}{#1}% -\@dtl@construct@lopoffs} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@dtl@construct@lopoff} -%\begin{definition} -%\cs{@dtl@construct@lopoff}\meta{separator char}\meta{delimiter char} +%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} -% This defines -%\begin{definition} -% \cs{@dtl@lopoff}\meta{first element}\meta{sep}\meta{rest of list}\cs{to}\meta{cmd1}\meta{cmd2} -%\end{definition}\noindent -%for the current separator and delimiter. -% \begin{macrocode} -\edef\@dtl@construct@lopoff#1#2{% -\noexpand\long\noexpand\def\noexpand\@dtl@lopoff#1##1##2\noexpand -\to##3##4{% -\noexpand\ifx#2##1\noexpand\relax -\noexpand\@dtl@qlopoff#1##1##2\noexpand\to##3##4\relax -\noexpand\else -\noexpand\@dtl@lop@ff#1##1##2\noexpand\to##3##4\relax -\noexpand\fi -}} -% \end{macrocode} -%\end{macro} % -%\begin{macro}{\@dtl@construct@qlopoff} -%\begin{definition} -% \cs{@dtl@construct@qlopoff}\meta{separator char}\meta{delimiter char} +%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} -% 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 +%\begin{definition}[\DescribeMacro{\Personobjpronoun}] +%\cs{Personobjpronoun}\oarg{label} +%\end{definition} +%\begin{definition}[\DescribeMacro{\Personpossadj}] +%\cs{Personpossadj}\oarg{label} +%\end{definition} +%\begin{definition}[\DescribeMacro{\Personposspronoun}] +%\cs{Personposspronoun}\oarg{label} +%\end{definition} +%\begin{definition}[\DescribeMacro{\Personchild}] +%\cs{Personchild}\oarg{label} +%\end{definition} +%\begin{definition}[\DescribeMacro{\Personparent}] +%\cs{Personparent}\oarg{label} +%\end{definition} +%\begin{definition}[\DescribeMacro{\Personsibling}] +%\cs{Personsibling}\oarg{label} +%\end{definition} +% +%\begin{example}{Order of Service (Memorial)}{ex:memorial} +%This example is for a memorial order of service. +% +%\begin{verbatim} +%\documentclass{article} +% +%\usepackage{person} +% +%\newperson{Jane Doe}{Jane}{female} +% +%\begin{document} +%\begin{center} +%\Large +%In Memory of \personfullname +%\end{center} +% +%We are gathered here to remember our \personsibling\ \personname. +%\Personpronoun\ will be much missed, and \personpossadj\ +%family are in our prayers. +%\end{document} +%\end{verbatim} +% +%\newperson{Jane Doe}{Jane}{female} +%\begin{center} +%\Large +%In Memory of \personfullname +%\end{center} +% +%We are gathered here to remember our \personsibling\ \personname. +%\Personpronoun\ will be much missed, and \personpossadj\ +%family are in our prayers. +%\removeperson +% +%\end{example} +% +%If there is more than one person, you will need to use the +%optional argument \meta{label} to \cs{newperson} to uniquely +%identify each person. You can then list all of the people's full +%or familiar names using: +%\begin{definition}[\DescribeMacro{\peoplefullname}] +%\cs{peoplefullname} +%\end{definition} +%\begin{definition}[\DescribeMacro{\peoplename}] +%\cs{peoplename} +%\end{definition} +%Note that if there is only one person defined, these commands behave +%the same as \cs{personfullname}\oarg{label} and +%\cs{personname}[\meta{label}]. +% +%Similarly for the pronouns: +%\begin{definition}[\DescribeMacro{\peoplepronoun}] +%\cs{peoplepronoun} +%\end{definition} +%\begin{definition}[\DescribeMacro{\Peoplepronoun}] +%\cs{Peoplepronoun} +%\end{definition} +%\begin{definition}[\DescribeMacro{\peopleobjpronoun}] +%\cs{peopleobjpronoun} +%\end{definition} +%\begin{definition}[\DescribeMacro{\Peopleobjpronoun}] +%\cs{Peopleobjpronoun} +%\end{definition} +%\begin{definition}[\DescribeMacro{\peoplepossadj}] +%\cs{peoplepossadj} +%\end{definition} +%\begin{definition}[\DescribeMacro{\Peoplepossadj}] +%\cs{Peoplepossadj} +%\end{definition} +%\begin{definition}[\DescribeMacro{\peopleposspronoun}] +%\cs{peopleposspronoun} +%\end{definition} +%\begin{definition}[\DescribeMacro{\Peopleposspronoun}] +%\cs{Peopleposspronoun} +%\end{definition} +%where, again, if only one person has been defined, each of these +%commands is equivalent to +%\cs{person}\ldots\oarg{label} or +%\cs{Person}\ldots\oarg{label}. If more than +%one person has been defined, these commands will display +%they/them/their/theirs or They/Them/Their/Theirs, as appropriate. +% +%Likewise for relationship commands: +%\begin{definition}[\DescribeMacro{\peoplechild}] +%\cs{peoplechild} +%\end{definition} +%\begin{definition}[\DescribeMacro{\Peoplechild}] +%\cs{Peoplechild} +%\end{definition} +%\begin{definition}[\DescribeMacro{\peopleparent}] +%\cs{peopleparent} +%\end{definition} +%\begin{definition}[\DescribeMacro{\Peopleparent}] +%\cs{Peopleparent} +%\end{definition} +%\begin{definition}[\DescribeMacro{\peoplesibling}] +%\cs{peoplesibling} +%\end{definition} +%\begin{definition}[\DescribeMacro{\Peoplesibling}] +%\cs{Peoplesibling} +%\end{definition} +% +%\begin{example}{Order of Service (Baptism)}{ex:baptism} +%In this example two people are defined. +%\begin{verbatim} +%\documentclass{article} +% +%\usepackage{person} +% +%\newperson[john]{John Joseph}{John}{male} +%\newperson[jane]{Jane Mary}{Jane}{female} +% +%\begin{document} +%\begin{center} +%\Large +%Baptism of \peoplefullname. +%\end{center} +% +%Today we welcome \peoplename\ into God's family, may He guide +%and protect \peopleobjpronoun. +%\end{document} +%\end{verbatim} +% +%This is produces the following text: +% +%\newperson[john]{John Joseph}{John}{male} +%\newperson[jane]{Jane Mary}{Jane}{female} +% +%\begin{center} +%\Large +%Baptism of \peoplefullname. +%\end{center} +% +%Today we welcome \peoplename\ into God's family, may He guide +%and protect \peopleobjpronoun. +%\removeallpeople +%\end{example} +% +%\begin{example}{Mail Merging Using Appropriate Gender}{ex:personmerge} +%In this example I have a CSV file called \texttt{students.csv} +%containing the following: +%\begin{verbatim} +%FirstName,Surname,Gender,Parent,Address +%John,"Smith, Jr",M,Mr and Mrs Smith,1 The Street\\Newtown +%Jane,Brown,F,Ms Brown,2 The Avenue\\Oldtown +%Andy,Brown,male,Mr Brown and Miss Sepia,3 The Road\\Newtown +%Z\"oe,Adams,f,Mr and Mrs Adams,5 The Street\\Newtown +%Roger,Brady,m,Mrs Brady,6 The Avenue\\Oldtowm +%Clare,Vernon,female,Mr Vernon,7 The Close\\Anytown +%\end{verbatim} +%Suppose I have to write to each student's parents regarding their +%child. I can load the information using \ics{DTLloaddb} (described +%in \autoref{sec:loaddb}). I can then iterate through the database +%and define the student as a person and use the commands defined in +%the \sty{person} package to display the correct gender related text. +%I could give each person a unique label based on the row count +%(\ics{DTLcurrentindex}), but since I don't need to reuse the +%information, I can use the default "anon" label and undefine the +%person when no longer required. +% +%Note that in the CSV file, the gender label isn't consistent. +%For some students the gender is identified by a single letter +%(``m'' or ``f'') and for others the gender is identified by a +%complete word (``male'' or ``female''). There's also no regard +%for case. This doesn't matter to \ics{newperson} as all the +%identifiers used are listed in \ics{malelabels} and +%\ics{femalelabels}. +% +%The following is an example letter sent to all parents: +%\begin{verbatim} +%\documentclass{letter} +%\usepackage{person} +% +%% load student information from file "students.csv" +%\DTLloaddb{students}{students.csv} +%\begin{document} +%% Iterate through the student database: +%\DTLforeach{students}{\FirstName=FirstName,\Surname=Surname,% +%\Gender=Gender,\Parent=Parent,\Address=Address}{% +%% Define "anon": +% \newperson{\FirstName\space\Surname}{\FirstName}{\Gender}% +%% Do the letter: +% \begin{letter}{\Parent\\\Address} +% \opening{Dear \Parent} +% Your \personchild\ \personname\ has been awarded a +% place. We look forward to seeing \personobjpronoun\ +% on \personpossadj\ arrival. +% \closing{Yours Sincerely} +% \end{letter} +%% Undefine "anon": +% \removeperson +%} +%\end{document} +%\end{verbatim} +% +%The body of the first letter appears as follows: +%\newperson{John Smith Jr}{John}{m} +%\par\vskip\baselineskip +% +% Your \personchild\ \personname\ has been awarded a +% place. We look forward to seeing \personobjpronoun\ +% on \personpossadj\ arrival. +% +%\removeperson +%\par\vskip\baselineskip +%Whereas the body of the second letter appears as follows: +%\newperson{Jane Brown}{Jane}{f} +%\par\vskip\baselineskip +% +% Your \personchild\ \personname\ has been awarded a +% place. We look forward to seeing \personobjpronoun\ +% on \personpossadj\ arrival. +% +%\removeperson +%\end{example} +% +%\subsection{Advanced Commands} +% +%This section describes additional commands provided by the +%\sty{person} package. More detail can be found in +%\autoref{sec:code:person}. +% +%\subsubsection{Conditionals} +% +%\begin{definition}[\DescribeMacro{\ifpersonexists}] +%\cs{ifpersonexists}\marg{label}\marg{true part}\marg{false part} +%\end{definition} +%Tests if the person identified by \meta{label} has been defined. +%If true, do \meta{true part} otherwise do \meta{false part}. +% +%\begin{definition}[\DescribeMacro{\ifmale}] +%\cs{ifmale}\marg{label}\marg{true part}\marg{false part} +%\end{definition} +%Test if the person identified by \meta{label} is male. +%If true, do \meta{true part} otherwise do \meta{false part}. +% +%\begin{definition}[\DescribeMacro{\iffemale}] +%\cs{iffemale}\marg{label}\marg{true part}\marg{false part} +%\end{definition} +%Test if the person identified by \meta{label} is female. +%If true, do \meta{true part} otherwise do \meta{false part}. +% +%\begin{definition}[\DescribeMacro{\ifallmale}] +%\cs{ifallmale}\oarg{label list}\marg{true part}\marg{false part} +%\end{definition} +%Tests if all the people listed in \meta{label list} are male. +%If true, do \meta{true part} otherwise do \meta{false part}. +%If \meta{label list} is omitted, applied to all defined people. +%\begin{definition}[\DescribeMacro{\ifallfemale}] +%\cs{ifallfemale}\oarg{label list}\marg{true part}\marg{false part} +%\end{definition} +%Likewise to test if all the people tested are female. +% +%To determine if a string is an allowed male label: +%\begin{definition}[\DescribeMacro{\ifmalelabel}] +%\cs{ifmalelabel}\marg{identifier}\marg{true part}\marg{false part} +%\end{definition} +%where \meta{identifier} is the string to be tested. If true, do +%\meta{true part} otherwise do \meta{false part}. +%For example: +%\begin{verbatim} +%\def\gender{M} +%\ifmalelabel{\gender}{male}{not male} +%\end{verbatim} +%Similarly to for an allowed female label: +%\begin{definition}[\DescribeMacro{\iffemalelabel}] +%\cs{iffemalelabel}\marg{identifier}\marg{true part}\marg{false part} +%\end{definition} +%For example: +%\begin{verbatim} +%\ifmalelabel{\gender}{Male}{% +% \iffemalelabel{\gender}{Female}% +% {Undefined Gender}% +%} +%\end{verbatim} +% +%\subsubsection{Iterating Through Defined People} +% +%You can iterate through all defined people using: +%\begin{definition}[\DescribeMacro{\foreachperson}] +%\cs{foreachperson}(\meta{name cs},\meta{full name cs},\meta{gender cs},\meta{label cs})\cs{do}\marg{body} +%\end{definition} +%At each iteration, \meta{name cs}, \meta{full name cs}, +%\meta{gender cs} and \meta{label cs} are set to the current person's +%name, full name, gender and label, respectively. (These arguments +%must all be command names.) Note that the gender is set to +%the definition of \DescribeMacro{\malename}\cs{malename} or +%\DescribeMacro{\femalename}\cs{femalename}, as appropriate.\footnote{Predefined names provided by the \sty{person} package are described +%in \autoref{sec:code:peoplenames}.} Once these +%commands are set, \meta{body} is applied. +% +%If you only want to iterate through a subset of defined people, +%you can use: +%\begin{definition} +%\cs{foreachperson}(\meta{name cs},\meta{full name cs},\meta{gender cs},\meta{label cs})\cs{in}\marg{list}\cs{do}\marg{body} +%\end{definition} +%where \meta{list} is a comma-separated list of labels. +% +%\subsubsection{Accessing Individual Information} +% +%\begin{definition}[\DescribeMacro{\getpersongender}] +%\cs{getpersongender}\marg{cs}\marg{label} +%\end{definition} +%Gets the gender of the person identified by \meta{label} and +%stores in \meta{cs} (which must be a command name). This +%sets \meta{cs} to the definition of \ics{malename} or +%\ics{femalename} as appropriate. +% +%\begin{definition}[\DescribeMacro{\getpersonname}] +%\cs{getpersonname}\marg{cs}\marg{label} +%\end{definition} +%Gets the name of the person identified by \meta{label} and +%stores in \meta{cs} (which must be a command name). +% +%\begin{definition}[\DescribeMacro{\getpersonfullname}] +%\cs{getpersonfullname}\marg{cs}\marg{label} +%\end{definition} +%Gets the full name of the person identified by \meta{label} and +%stores in \meta{cs} (which must be a command name). +% +% \StopEventually{\clearpage\phantomsection +%\addcontentsline{toc}{section}{\refname} +% \DTLbibliography{docbib} +%\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 +% \begin{macrocode} +%<*datatool.sty> +% \end{macrocode} +%\fi +%\label{sec:code:datatool} +%\subsection{Package Declaration} +% \begin{macrocode} +\NeedsTeXFormat{LaTeX2e} +\ProvidesPackage{datatool}[2009/11/15 v2.03 (NLCT)] +% \end{macrocode} +% Load required packages: +% \begin{macrocode} +\RequirePackage{xkeyval} +\RequirePackage{ifthen} +\RequirePackage{xfor} +\RequirePackage{fp} +\RequirePackage{substr} +% \end{macrocode} +%\changes{2.0}{2009 February 27}{added etex as a required package} +% \begin{macrocode} +\RequirePackage{etex} +% \end{macrocode} +% +%\subsection{Package Options} +%\begin{macro}{\@dtl@separator} +% The data separator character (comma by default) is stored in +% \cs{@dtl@separator}. +% This is the separator used in external data files, not in the +% \LaTeX\ code, which always uses a comma separator. +% \begin{macrocode} +\newcommand*{\@dtl@separator}{,} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLsetseparator} +%\begin{definition} +%\cs{DTLsetseparator}\marg{char} +%\end{definition} +% The sets \cs{@dtl@separator}, and constructs the relevent macros +% that require this character to be hardcoded into their definition. +% \begin{macrocode} +\newcommand*{\DTLsetseparator}[1]{% +\renewcommand*{\@dtl@separator}{#1}% +\@dtl@construct@lopoffs +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLsettabseparator} +%\cs{DTLsettabseparator} makes it easier to set a tab separator. +% \begin{macrocode} +\begingroup +\catcode`\ 12 +\gdef\DTLsettabseparator{% + \catcode`\ 12 + \DTLsetseparator{ }% +} +\endgroup +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\@dtl@delimiter} +% The data delimiter character (double quote by default) is stored +% in \cs{@dtl@delimiter}. This is used in external data files, not +% in the \LaTeX\ code. +% \begin{macrocode} +\begingroup +\catcode`\"12\relax +\gdef\@dtl@delimiter{"} +\endgroup +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLsetdelimiter} +%\begin{definition} +%\cs{DTLsetdelimiter}\marg{char} +%\end{definition} +% This sets the delimiter. +% \begin{macrocode} +\newcommand*\DTLsetdelimiter[1]{% +\renewcommand*{\@dtl@delimiter}{#1}% +\@dtl@construct@lopoffs} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\@dtl@construct@lopoff} +%\begin{definition} +%\cs{@dtl@construct@lopoff}\meta{separator char}\meta{delimiter char} +%\end{definition} +% This defines +%\begin{definition} +% \cs{@dtl@lopoff}\meta{first element}\meta{sep}\meta{rest of list}\cs{to}\meta{cmd1}\meta{cmd2} +%\end{definition}\noindent +%for the current separator and delimiter. +% \begin{macrocode} +\edef\@dtl@construct@lopoff#1#2{% +\noexpand\long\noexpand\def\noexpand\@dtl@lopoff#1##1##2\noexpand +\to##3##4{% +\noexpand\ifx#2##1\noexpand\relax +\noexpand\@dtl@qlopoff#1##1##2\noexpand\to##3##4\relax +\noexpand\else +\noexpand\@dtl@lop@ff#1##1##2\noexpand\to##3##4\relax +\noexpand\fi +}} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\@dtl@construct@qlopoff} +%\begin{definition} +% \cs{@dtl@construct@qlopoff}\meta{separator char}\meta{delimiter char} +%\end{definition} +% This constructs \cs{@dtl@qlopoff} to be used +% when the entry is surrounded by the current delimiter value. +% \begin{macrocode} +\edef\@dtl@construct@qlopoff#1#2{% +\noexpand\long\noexpand\def\noexpand\@dtl@qlopoff#1#2##1#2#1##2\noexpand \to##3##4{% \noexpand\def##4{##1}\noexpand\def##3{#1##2}% }} @@ -9938,9 +10573,11 @@ options>#2=\textsf{#2}|hyperpage}} % the database name. % %\begin{macro}{\DTLnewdb} +%\begin{definition} +% \cs{DTLnewdb}\marg{db name} +%\end{definition} %\changes{2.0}{2009 February 27}{Changed way database is stored} -% \cs{DTLnewdb}\marg{name} -% initialises a database called \meta{name}. +% Initialises a database called \meta{name}. % \begin{macrocode} \newcommand*{\DTLnewdb}[1]{% % \end{macrocode} @@ -9977,17 +10614,71 @@ options>#2=\textsf{#2}|hyperpage}} % \end{macrocode} %\end{macro} % -%\begin{macro}{\DTLrowcount} +%\begin{macro}{\DTLcleardb} %\begin{definition} -% \cs{DTLrowcount}\marg{db name} +% \cs{DTLcleardb}\marg{db name} %\end{definition} -% The number of rows in the database called \meta{db name}. -% (Doesn't check if database exists.) +% Clears the database. (Makes it empty, but still defined.) +%\changes{2.03}{2009 November 15}{new} % \begin{macrocode} -\newcommand*{\DTLrowcount}[1]{% -\expandafter\number\csname dtlrows@#1\endcsname} -% \end{macrocode} -%\end{macro} +\newcommand*{\DTLcleardb}[1]{% + \DTLifdbexists{#1}% + {% + \dtlforeachkey(\@dtl@key,\@dtl@col,\@dtl@type,\@dtl@head)\in{#1}\do + {% + \expandafter\let\csname dtl@ci@#1@\@dtl@key\endcsname\undefined + }% + \csname dtldb@#1\endcsname{}% + \csname dtlkeys@#1\endcsname{}% + \csname dtlrows@#1\endcsname=0\relax + \csname dtlcols@#1\endcsname=0\relax + }% + {% + \PackageError{Can't clear database `#1': + database doesn't exist}{}{}% + }% +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLdeletedb} +%\begin{definition} +% \cs{DTLdeletedb}\marg{db name} +%\end{definition} +% Deletes a database. +%\changes{2.03}{2009 November 15}{new} +% \begin{macrocode} +\newcommand*{\DTLdeletedb}[1]{% + \DTLifdbexists{#1}% + {% + \dtlforeachkey(\@dtl@key,\@dtl@col,\@dtl@type,\@dtl@head)\in{#1}\do + {% + \expandafter\let\csname dtl@ci@#1@\@dtl@key\endcsname\undefined + }% + \expandafter\let\csname dtldb@#1\endcsname\undefined + \expandafter\let\csname dtlkeys@#1\endcsname\undefined + \expandafter\let\csname dtlrows@#1\endcsname\undefined + \expandafter\let\csname dtlcols@#1\endcsname\undefined + }% + {% + \PackageError{Can't delete database `#1': + database doesn't exist}{}{}% + }% +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLrowcount} +%\begin{definition} +% \cs{DTLrowcount}\marg{db name} +%\end{definition} +% The number of rows in the database called \meta{db name}. +% (Doesn't check if database exists.) +% \begin{macrocode} +\newcommand*{\DTLrowcount}[1]{% +\expandafter\number\csname dtlrows@#1\endcsname} +% \end{macrocode} +%\end{macro} % %\begin{macro}{\DTLcolumncount} %\begin{definition} @@ -10225,15 +10916,17 @@ options>#2=\textsf{#2}|hyperpage}} % \end{macrocode} %\end{macro} % -%\begin{macro}{\dtl@columnindex} +%\begin{macro}{\dtlcolumnindex} %\begin{definition} -% \cs{dtl@columnindex}\marg{db}\marg{key} +% \cs{dtlcolumnindex}\marg{db}\marg{key} %\end{definition} % Column index corresponding to \meta{key} in database \meta{db}. % (No check for existance of database or key.) %\changes{2.0}{2009 February 27}{new} +%\changes{2.03}{2009 November 15}{renamed \cs{dtl@columnindex} to +%\cs{dtlcolumnindex}} % \begin{macrocode} -\newcommand*{\dtl@columnindex}[2]{% +\newcommand*{\dtlcolumnindex}[2]{% \csname dtl@ci@#1@#2\endcsname } % \end{macrocode} @@ -10423,7 +11116,7 @@ options>#2=\textsf{#2}|hyperpage}} \newcommand*{\@sdtlgetdatatype}[3]{% \edef\@dtl@dogetdata{\noexpand\@dtl@getdatatype{\noexpand#1}% {\expandafter\the\csname dtlkeys@#2\endcsname}% - {\dtl@columnindex{#2}{#3}}}% + {\dtlcolumnindex{#2}{#3}}}% \@dtl@dogetdata } % \end{macrocode} @@ -10520,7 +11213,7 @@ options>#2=\textsf{#2}|hyperpage}} % column index. % \begin{macrocode} \expandafter\dtlcolumnnum\expandafter - =\dtl@columnindex{#1}{#2}\relax + =\dtlcolumnindex{#1}{#2}\relax % \end{macrocode} % Get the properties for this column % \begin{macrocode} @@ -10700,7 +11393,7 @@ options>#2=\textsf{#2}|hyperpage}} % \begin{macrocode} \newcommand*{\@sDTLsetheader}[3]{% \expandafter\dtlcolumnnum\expandafter - =\dtl@columnindex{#1}{#2}\relax + =\dtlcolumnindex{#1}{#2}\relax \@dtl@setheaderforindex{#1}{\dtlcolumnnum}{#3}% } % \end{macrocode} @@ -10751,6 +11444,28 @@ options>#2=\textsf{#2}|hyperpage}} % \end{macrocode} %\end{macro} % +%\begin{macro}{\dtlexpandnewvalue} +% Expand new value before adding to database +% \begin{macrocode} +\newcommand*{\dtlexpandnewvalue}{% + \def\@dtl@setnewvalue##1{\protected@edef\@dtl@tmp{##1}% + \expandafter\@dtl@toks\expandafter{\@dtl@tmp}}% +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\dtlnoexpandnewvalue} +% Don't expand new value before adding to database +% \begin{macrocode} +\newcommand*{\dtlnoexpandnewvalue}{% + \def\@dtl@setnewvalue##1{\@dtl@toks{##1}}% +} +% \end{macrocode} +% Do this by default: +% \begin{macrocode} +\dtlnoexpandnewvalue +% \end{macrocode} +%\end{macro} +% %\begin{macro}{\DTLnewdbentry} %\begin{definition} % \cs{DTLnewdbentry}\marg{db name}\marg{id}\marg{value}. @@ -10788,7 +11503,7 @@ options>#2=\textsf{#2}|hyperpage}} % Get the column index % \begin{macrocode} \expandafter\dtlcolumnnum\expandafter - =\dtl@columnindex{#1}{#2}\relax + =\dtlcolumnindex{#1}{#2}\relax % \end{macrocode} % Get the current row: % \begin{macrocode} @@ -10805,8 +11520,10 @@ options>#2=\textsf{#2}|hyperpage}} \ifx\dtl@entry\dtlnovalue % \end{macrocode} % Store the value of this entry in \cs{@dtl@toks} +%\changes{2.03}{2009 November 15}{value can be expanded before +% adding to database}% % \begin{macrocode} - \@dtl@toks{#3}% + \@dtl@setnewvalue{#3}% % \end{macrocode} % There are no entries in this row for the given column. % Add this entry. @@ -10913,22 +11630,24 @@ options>#2=\textsf{#2}|hyperpage}} %\begin{definition} % \cs{@dtl@assigncmd}\meta{cmd}=\meta{id}\cs{@nil} %\end{definition} +%\changes{2.03}{2009 November 15}{modified to ignore spaces after +% commas} % \begin{macrocode} -\def\@dtl@assigncmd#1=#2,#3\@@#4{% +\def\@dtl@assigncmd#1#2=#3,#4\@@#5{% % \end{macrocode} -% get entry for ID given by \#2 and store in \#1 +% get entry for ID given by \#3 and store in \#2 % \begin{macrocode} - \@sDTLifhaskey{#4}{#2}% + \@sDTLifhaskey{#5}{#3}% {% \edef\@dtl@dogetentry{% \noexpand\dtlgetentryfromcurrentrow - {\noexpand#1}{\dtl@columnindex{#4}{#2}}}% + {\noexpand#1}{\dtlcolumnindex{#5}{#3}}}% \@dtl@dogetentry % \end{macrocode} % Set to null if required % \begin{macrocode} \ifx#1\dtlnovalue - \@@dtl@setnull{#1}{#2}% + \@@dtl@setnull{#1}{#3}% \fi % \end{macrocode} % Make it global @@ -10937,7 +11656,7 @@ options>#2=\textsf{#2}|hyperpage}} }% {% \PackageError{datatool}{Can't assign \string#1\space: there - is no key `#2' in data base `#4'}{}% + is no key `#3' in data base `#5'}{}% % \end{macrocode} % Set to null % \begin{macrocode} @@ -10946,13 +11665,13 @@ options>#2=\textsf{#2}|hyperpage}} % \end{macrocode} % Recurse? % \begin{macrocode} - \def\dtl@tmp{#3}% + \def\dtl@tmp{#4}% \ifx\@nnil\dtl@tmp \let\@dtl@next\@dtl@assigncmdnoop \else \let\@dtl@next\@dtl@assigncmd \fi - \@dtl@next#3\@@{#4}% + \@dtl@next#4\@@{#5}% } % \end{macrocode} %\end{macro} @@ -11195,9 +11914,9 @@ options>#2=\textsf{#2}|hyperpage}} %\begin{macro}{\@dtlgetrow} %\begin{definition} %\cs{@dtlgetrow}\marg{data specs}\marg{row idx} +%\end{definition} % Gets the row specs from \meta{data specs} for row with index % \meta{row idx} which must be fully expanded. -%\end{definition} % \begin{macrocode} \newcommand*{\@dtlgetrow}[2]{% \def\@dtl@getrow##1% before stuff @@ -11734,7 +12453,7 @@ options>#2=\textsf{#2}|hyperpage}} \toks@{#4}% \edef\@dtl@doforcol{\noexpand\dtl@forcolumn{\noexpand#1}% {\expandafter\the\csname dtldb@#2\endcsname}% - {\dtl@columnindex{#2}{#3}}{\the\toks@}% + {\dtlcolumnindex{#2}{#3}}{\the\toks@}% }% \@dtl@doforcol% } @@ -12464,7 +13183,7 @@ options>#2=\textsf{#2}|hyperpage}} % Get column index and store in \cs{dtlcolumnnum} % \begin{macrocode} \expandafter\dtlcolumnnum\expandafter - =\dtl@columnindex{\@dtl@thisdb}{#1}\relax + =\dtlcolumnindex{\@dtl@thisdb}{#1}\relax % \end{macrocode} % Set \cs{dtlcurrentrow} to the current row % \begin{macrocode} @@ -12480,9 +13199,11 @@ options>#2=\textsf{#2}|hyperpage}} \ifx\dtl@entry\dtlnovalue % \end{macrocode} % There are no entries in this row for the given key. -% Store value in \cs{@dtl@toks} with one level expansion. +% Expand entry value before storing. +%\changes{2.03}{2009 November 15}{value expanded before storing} % \begin{macrocode} - \expandafter\@dtl@toks\expandafter{#2}% + \protected@edef\@dtl@tmp{#2}% + \expandafter\@dtl@toks\expandafter{\@dtl@tmp}% % \end{macrocode} % Append this entry to the current row. % \begin{macrocode} @@ -12689,9 +13410,11 @@ options>#2=\textsf{#2}|hyperpage}} }% \@dtl@dosplitrow % \end{macrocode} -% Reconstruct row with new entry +% Reconstruct row with new value (given by \verb|#2|). +%\changes{2.03}{2009 November 15}{expand replacement entry} % \begin{macrocode} - \@dtl@toks{#2}% new value + \protected@edef\@dtl@tmp{#2}% + \expandafter\@dtl@toks\expandafter{\@dtl@tmp}% new value \expandafter\@dtl@before\expandafter{\dtl@pre}% \expandafter\@dtl@after\expandafter{\dtl@post}% \toks@gconcat@middle@cx @@ -15042,5129 +15765,4751 @@ options>#2=\textsf{#2}|hyperpage}} % \end{macrocode} %\end{macro} % -%\subsection{General List Utilities} +%\subsection{Saving a database to an external file} % -%\begin{macro}{\dtl@choplast} +%\begin{macro}{\@dtl@write} +% \begin{macrocode} +\newwrite\@dtl@write +% \end{macrocode} +%\end{macro} +%\begin{macro}{\DTLsavedb} %\begin{definition} -% \cs{dtl@choplast}\marg{list}\marg{rest}\marg{last} +% \cs{DTLsavedb}\marg{db name}\marg{filename} %\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. +% Save a database as an ASCII data file using the separator +% and delimiter given by \cs{@dtl@separator} and \cs{@dtl@delimiter}. +%\changes{2.0}{2009 February 27}{updated to use new database structure} % \begin{macrocode} -\newcommand*{\dtl@choplast}[3]{% +\newcommand*{\DTLsavedb}[2]{% + \DTLifdbexists{#1}% + {% % \end{macrocode} -% Set \meta{rest} to empty: +% Open output file +%\changes{2.02}{2009 July 13}{Fixed bug that didn't set the filename} % \begin{macrocode} -\let#2\@empty + \openout\@dtl@write=#2\relax % \end{macrocode} -% Set \meta{last} to empty: +% Initialise header row % \begin{macrocode} -\let#3\@empty + \def\@dtl@header{}% % \end{macrocode} -% Iterate through \meta{list}: +% Construct the header row % \begin{macrocode} -\@for\@dtl@element:=#1\do{% -\ifx#3\@empty + \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} -% First iteration, don't set \meta{rest}. +% Print header % \begin{macrocode} -\else - \ifx#2\@empty + \protected@write\@dtl@write{}{\@dtl@header}% % \end{macrocode} -% Second iteration, set \meta{rest} to \meta{last} (which is -% currently set to the previous value: +% Iterate through each row % \begin{macrocode} - \expandafter\toks@\expandafter{#3}% - \edef#2{{\the\toks@}}% - \else + \@sDTLforeach{#1}{}% + {% % \end{macrocode} -% Subsequent iterations, set \meta{rest} to \meta{rest},\meta{last} -% (\meta{last} is currently set to the previous value): +% Initialise row % \begin{macrocode} - \expandafter\toks@\expandafter{#3}% - \expandafter\@dtl@toks\expandafter{#2}% - \edef#2{\the\@dtl@toks,{\the\toks@}}% - \fi -\fi + \def\@dtl@row{}% % \end{macrocode} -% Now set \meta{last} to current element. +% Iterate through each key % \begin{macrocode} -\let#3=\@dtl@element% -}% -} + \DTLforeachkeyinrow{\@dtl@val}% + {% + \IfSubStringInString{\@dtl@separator}{\@dtl@val}% + {% + \ifx\@dtl@row\@empty + \protected@edef\@dtl@row{% + \@dtl@delimiter\@dtl@val\@dtl@delimiter}% + \else + \toks@=\expandafter{\@dtl@row}% + \protected@edef\@dtl@row{\the\toks@\@dtl@separator + \@dtl@delimiter\@dtl@val\@dtl@delimiter}% + \fi + }% + {% + \ifx\@dtl@row\@empty + \protected@edef\@dtl@row{\@dtl@val}% + \else + \toks@=\expandafter{\@dtl@row}% + \protected@edef\@dtl@row{\the\toks@\@dtl@separator + \@dtl@val}% + \fi + }% + }% % \end{macrocode} -%\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.) +% Print row\changes{2.03}{2009 November 15}{Moved outside loop} % \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 -} + \protected@write\@dtl@write{}{\@dtl@row}% + }% % \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}.) +% Close output file % \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 + \closeout\@dtl@write + }% + {% + \PackageError{datatool}{Can't save database `#1': no such + database}{}% + }% } % \end{macrocode} %\end{macro} % -%\begin{macro}{\dtl@insertinto} +%\begin{macro}{\DTLsavetexdb} %\begin{definition} -% \cs{dtl@insertinto}\marg{element}\marg{sorted-list}\marg{criteria cmd} +% \cs{DTLsavetexdb}\marg{db name}\marg{filename} %\end{definition} -% Inserts \meta{element} into the sorted list \meta{sorted-list} -% according to the criteria given by \meta{criteria cmd} (see above.) +% Save a database as a \LaTeX\ file. +%\changes{2.0}{2009 February 27}{updated to use new database structure} % \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 -}% - \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 -} +\newcommand*{\DTLsavetexdb}[2]{% + \DTLifdbexists{#1}% + {% % \end{macrocode} -%\end{macro} -%\begin{macro}{\if@dtl@insertdone} -% Define conditional to indicate whether the new entry has -% been inserted into the sorted list. +% Open output file % \begin{macrocode} -\newif\if@dtl@insertdone + \openout\@dtl@write=#2\relax % \end{macrocode} -%\end{macro} -%\begin{macro}{\dtl@sortresult} -% Define \cs{dtl@sortresult} to be set by comparision macro. +% Write new data base definition % \begin{macrocode} -\newcount\dtl@sortresult + \protected@write\@dtl@write{}{\string\DTLnewdb{#1}}% % \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} +% Iterate through each row % \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}% -} + \@sDTLforeach{#1}{}% + {% % \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} +% Start new row % \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}% + \protected@write\@dtl@write{}{\string\DTLnewrow*{#1}}% +% \end{macrocode} +% Iterate through each column +% \begin{macrocode} + \DTLforeachkeyinrow{\@dtl@val}% + {% +% \end{macrocode} +% Is this entry null? +% \begin{macrocode} + \DTLifnull{\@dtl@val}% + {\def\@dtl@val{}}% + {}% +% \end{macrocode} +% Add entry +% \begin{macrocode} + \protected@write\@dtl@write{}{% + \string\DTLnewdbentry*{#1}{\dtlkey}{\@dtl@val}}% + }% + }% +% \end{macrocode} +% Save the column headers. +% \begin{macrocode} + \dtlforeachkey(\@dtl@k,\@dtl@c,\@dtl@t,\@dtl@h)\in{#1}\do + {% + \@onelevel@sanitize\@dtl@h + \protected@write\@dtl@write{}{% + \string\DTLsetheader*{#1}{\@dtl@k}{\@dtl@h}}% + }% +% \end{macrocode} +% Close output file +% \begin{macrocode} + \closeout\@dtl@write + }% + {% + \PackageError{datatool}{Can't save database `#1': no such + database}{}% + }% } % \end{macrocode} %\end{macro} % -% \subsection{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. +%\subsection{Loading a database from an external file} % -%\begin{macro}{\DTLadd} -%\begin{definition} -% \cs{DTLadd}\marg{cmd}\marg{num1}\marg{num2} -%\end{definition} -% Sets \meta{cmd} = \meta{num1} + \meta{num2} % \begin{macrocode} -\newcommand*{\DTLadd}[3]{% -\DTLconverttodecimal{#2}{\@dtl@numi}% -\DTLconverttodecimal{#3}{\@dtl@numii}% -\FPadd{\@dtl@tmp}{\@dtl@numi}{\@dtl@numii}% -\ifx\@dtl@replaced\@empty - \DTLdecimaltolocale{\@dtl@tmp}{#1}% -\else - \DTLdecimaltocurrency{\@dtl@tmp}{#1}% -\fi -} +\newcommand{\@longempty}{} +% \end{macrocode} +%\begin{macro}{\@dtl@read} +% \begin{macrocode} +\newread\@dtl@read % \end{macrocode} %\end{macro} -%\begin{macro}{\DTLgadd} -% Global version +%\begin{macro}{\dtl@entrycr} +% Keep track of current column in data file % \begin{macrocode} -\newcommand*{\DTLgadd}[3]{% -\DTLadd{\@dtl@tmpii}{#2}{#3}% -\global\let#1=\@dtl@tmpii -} +\newcount\dtl@entrycr % \end{macrocode} %\end{macro} % -%\begin{macro}{\DTLaddall} -%\begin{definition} -%\cs{DTLaddall}\marg{cmd}\marg{num list} -%\end{definition} -% Sums all the values in \meta{num list} and stores in -% \meta{cmd} which must be a control sequence. -%\changes{1.01}{2007 Aug 17}{removed extraneous space} +%\begin{macro}{\ifdtlnoheader} +% The "noheader" option indicates that the file doesn't have a +% header row. % \begin{macrocode} -\newcommand*{\DTLaddall}[2]{% -\def\@dtl@sum{0}% -\@for\dtl@thisval:=#2\do{% - \DTLconverttodecimal{\dtl@thisval}{\@dtl@num}% - \FPadd{\@dtl@sum}{\@dtl@sum}{\@dtl@num}% -}% -\ifx\@dtl@replaced\@empty - \DTLdecimaltolocale{\@dtl@sum}{#1}% -\else - \DTLdecimaltocurrency{\@dtl@sum}{#1}% -\fi -} +\define@boolkey{loaddb}[dtl]{noheader}[true]{} % \end{macrocode} %\end{macro} -%\begin{macro}{\DTLgaddall} -%\begin{definition} -%\cs{DTLgaddall}\marg{cmd}\marg{num list} -%\end{definition} -% Global version +% 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} -\newcommand*{\DTLgaddall}[2]{% -\DTLaddall{\@dtl@tmpi}{#2}% -\global\let#1=\@dtl@tmpi +\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} -%\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 "headers" option specifies the list of headers in the +% same order as the columns in the data file. % \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 +\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} -%\begin{macro}{\DTLgsub} -% Global version +% +%\begin{macro}{\dtldefaultkey} +% Default key to use if none specified (column index will be +% appended). % \begin{macrocode} -\newcommand*{\DTLgsub}[3]{% -\DTLsub{\@dtl@tmpii}{#2}{#3}% -\global\let#1=\@dtl@tmpii -} +\newcommand*{\dtldefaultkey}{Column} % \end{macrocode} %\end{macro} % -%\begin{macro}{\DTLmul} +%\begin{macro}{\@dtl@readline} %\begin{definition} -% \cs{DTLmul}\marg{cmd}\marg{num1}\marg{num2} +%\cs{@dtl@readline}\marg{file reg}\marg{cs} %\end{definition} -% Sets \meta{cmd} = \meta{num1} $\times$ \meta{num2} +% Reads line from \meta{file reg}, trims end of line character +% and stores in \meta{cs}. % \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 -} +\newcommand*{\@dtl@readline}[2]{% +% Read a line from "#1" and store in "#2" +% \begin{macrocode} + \read#1 to #2% % \end{macrocode} -%\end{macro} -%\begin{macro}{\DTLgmul} -% Global version +% Trim the end of line character % \begin{macrocode} -\newcommand*{\DTLgmul}[3]{% -\DTLmul{\@dtl@tmpii}{#2}{#3}% -\global\let#1=\@dtl@tmpii + \dtl@trim#2% } % \end{macrocode} %\end{macro} % -%\begin{macro}{\DTLdiv} +%\begin{macro}{\@dtl@readrawline} %\begin{definition} -% \cs{DTLdiv}\marg{cmd}\marg{num1}\marg{num2} +%\cs{@dtl@readrawline}\marg{file register}\marg{cs} %\end{definition} -% Sets \meta{cmd} = \meta{num1} / \meta{num2} +% Reads line from \meta{file register}, trims end of line character, +% applies mappings and stores in \meta{cs}. % \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*{\@dtl@readrawline}[2]{% +% Read a line from "#1" and store in "#2" +% \begin{macrocode} + \@dtl@rawread#1 to #2% % \end{macrocode} -%\end{macro} -%\begin{macro}{\DTLgdiv} -% Global version +% Trim the end of line character % \begin{macrocode} -\newcommand*{\DTLgdiv}[3]{% -\DTLdiv{\@dtl@tmpii}{#2}{#3}% -\global\let#1=\@dtl@tmpii + \dtl@trim#2% +% \end{macrocode} +% Apply mappings +% \begin{macrocode} + \dtl@domappings\@dtl@line } % \end{macrocode} %\end{macro} -% -%\begin{macro}{\DTLabs} + +%\begin{macro}{\DTLloaddb} %\begin{definition} -% \cs{DTLabs}\marg{cmd}\marg{num} +% \cs{DTLloaddb}\oarg{options}\marg{db name}\marg{filename} %\end{definition} -% Sets \meta{cmd} = abs(\meta{num}) +% 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*{\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 +\newcommand*{\DTLloaddb}{% + \let\@dtl@doreadline\@dtl@readline + \@dtlloaddb } % \end{macrocode} %\end{macro} -%\begin{macro}{\DTLgabs} -% Global version +% +%\begin{macro}{\@dtlloaddb} +% Loads database using \cs{@dtl@doreadline} to read and trim +% line from file. (\cs{@dtl@doreadline} must be set before use.) % \begin{macrocode} -\newcommand*{\DTLgabs}[2]{% -\DTLabs{\@dtl@tmpii}{#2}% -\global\let#1=\@dtl@tmpii -} +\newcommand*{\@dtlloaddb}[3][]{% % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\DTLneg} -%\begin{definition} -% \cs{DTLneg}\marg{cmd}\marg{num} -%\end{definition} -% Sets \meta{cmd} = -\meta{num} +% Check if file exists % \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 -} + \IfFileExists{#3}{% % \end{macrocode} -%\end{macro} -%\begin{macro}{\DTLgneg} -% Global version +% File exists. Locally change catcode of double quote character in +% case it has been made active. % \begin{macrocode} -\newcommand*{\DTLgneg}[2]{% -\DTLneg{\@dtl@tmpii}{#2}% -\global\let#1=\@dtl@tmpii -} + \begingroup + \catcode`\"12\relax % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\DTLsqrt} -%\begin{definition} -% \cs{DTLsqrt}\marg{cmd}\marg{num} -%\end{definition} -% Sets \meta{cmd} = sqrt(\meta{num}) +% Initialise default options % \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 -} + \dtlnoheaderfalse % \end{macrocode} -%\end{macro} -%\begin{macro}{\DTLgsqrt} -% Global version +% Get the options % \begin{macrocode} -\newcommand*{\DTLgsqrt}[2]{% -\DTLsqrt{\@dtl@tmpii}{#2}% -\global\let#1=\@dtl@tmpii -} + \setkeys{loaddb}{#1}% % \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}) +% Open the file for reading. % \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 -} + \openin\@dtl@read=#3% + \dtl@message{Reading `#3'}% % \end{macrocode} -%\end{macro} -%\begin{macro}{\DTLgmin} -% Global version +% Create the new database. % \begin{macrocode} -\newcommand*{\DTLgmin}[3]{% -\DTLmin{\@dtl@tmpii}{#2}{#3}% -\global\let#1=\@dtl@tmpii -} + \DTLnewdb{#2}% % \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} +% Check if the file is empty. % \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 -} + \ifeof\@dtl@read % \end{macrocode} -%\end{macro} -%\begin{macro}{\DTLgminall} -%\begin{definition} -%\cs{DTLgminall}\marg{cmd}\marg{num list} -%\end{definition} -% Global version +% File is empty, so just issue a warning. % \begin{macrocode} -\newcommand*{\DTLgminall}[2]{% -\DTLminall{\@dtl@tmpi}{#2}% -\global\let#1=\@dtl@tmpi -} + \PackageWarning{datatool}{File `#3' has no data}% + \else % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\DTLmax} -%\begin{definition} -% \cs{DTLmax}\marg{cmd}\marg{num1}\marg{num2} -%\end{definition} -% Sets \meta{cmd} = max(\meta{num1}, \meta{num2}) +% Does the file have a header row? % \begin{macrocode} -\newcommand*{\DTLmax}[3]{% -\DTLconverttodecimal{#2}{\@dtl@numi}% -\DTLconverttodecimal{#3}{\@dtl@numii}% -\FPmax{\@dtl@tmp}{\@dtl@numi}{\@dtl@numii}% -\FPifgt{\@dtl@numi}{\@dtl@numii}% - \dtl@ifsingle{#2}{% - \let#1=#2}{% - \def#1{#2}}% -\else - \dtl@ifsingle{#3}{% - \let#1=#3}{% - \def#1{#3}}% -\fi -} + \ifdtlnoheader + \else % \end{macrocode} -%\end{macro} -%\begin{macro}{\DTLgmax} -% Global version +% Remove initial blank rows % \begin{macrocode} -\newcommand*{\DTLgmax}[3]{% -\DTLmax{\@dtl@tmpii}{#2}{#3}% -\global\let#1=\@dtl@tmpii -} + \loop % \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} +% Set repeat condition to false % \begin{macrocode} -\newcommand*{\DTLmaxall}[2]{% -\let\@dtl@max=\@empty -\@for\dtl@thisval:=#2\do{% - \DTLconverttodecimal{\dtl@thisval}{\@dtl@num}% - \ifx\@dtl@max\@empty - \let\@dtl@max\@dtl@num - \else - \FPmax{\@dtl@max}{\@dtl@max}{\@dtl@num}% - \fi -}% -\ifx\@dtl@replaced\@empty - \DTLdecimaltolocale{\@dtl@max}{#1}% -\else - \DTLdecimaltocurrency{\@dtl@max}{#1}% -\fi -} + \@dtl@conditionfalse % \end{macrocode} -%\end{macro} -%\begin{macro}{\DTLgmaxall} -%\begin{definition} -%\cs{DTLgmaxall}\marg{cmd}\marg{num list} -%\end{definition} -% Global version -% \begin{macrocode} -\newcommand*{\DTLgmaxall}[2]{% -\DTLmaxall{\@dtl@tmpi}{#2}% -\global\let#1=\@dtl@tmpi -} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\DTLmeanforall} -%\begin{definition} -%\cs{DTLmeanforall}\marg{cmd}\marg{num list} -%\end{definition} -% Computes the arithmetic mean of all the values in \meta{num list} -% and stores in \meta{cmd} which must be a control sequence. -%\changes{1.01}{2007 Aug 17}{removed extraneous space} +% Do nothing if reached the end of file % \begin{macrocode} -\newcommand*{\DTLmeanforall}[2]{% -\def\@dtl@mean{0}% -\def\@dtl@n{0}% -\@for\dtl@thisval:=#2\do{% - \DTLconverttodecimal{\dtl@thisval}{\@dtl@num}% - \FPadd{\@dtl@mean}{\@dtl@mean}{\@dtl@num}% - \FPadd{\@dtl@n}{\@dtl@n}{1}% -}% -\FPdiv{\@dtl@mean}{\@dtl@mean}{\@dtl@n}% -\ifx\@dtl@replaced\@empty - \DTLdecimaltolocale{\@dtl@mean}{#1}% -\else - \DTLdecimaltocurrency{\@dtl@mean}{#1}% -\fi -} + \ifeof\@dtl@read + \else % \end{macrocode} -%\end{macro} -%\begin{macro}{\DTLgmeanforall} -%\begin{definition} -%\cs{DTLgmeanforall}\marg{cmd}\marg{num list} -%\end{definition} -% Global version +% Read a line from the file and store in \cs{@dtl@line} % \begin{macrocode} -\newcommand*{\DTLgmeanforall}[2]{% -\DTLmeanforall{\@dtl@tmpi}{#2}% -\global\let#1=\@dtl@tmpi -} + \@dtl@doreadline\@dtl@read\@dtl@line % \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} +% If this is a blank row, set repeat condition to true % \begin{macrocode} -\newcommand*{\DTLvarianceforall}[2]{% -\def\@dtl@mean{0}% -\def\@dtl@n{0}% -\let\@dtl@decvals=\@empty -\@for\dtl@thisval:=#2\do{% - \DTLconverttodecimal{\dtl@thisval}{\@dtl@num}% - \ifx\@dtl@decvals\@empty - \let\@dtl@decvals=\@dtl@num - \else - \expandafter\toks@\expandafter{\@dtl@decvals}% - \edef\@dtl@decvals{\the\toks@,\@dtl@num}% - \fi - \FPadd{\@dtl@mean}{\@dtl@mean}{\@dtl@num}% - \FPadd{\@dtl@n}{\@dtl@n}{1}% -}% -\FPdiv{\@dtl@mean}{\@dtl@mean}{\@dtl@n}% -\def\@dtl@var{0}% -\@for\@dtl@num:=\@dtl@decvals\do{% - \FPsub{\@dtl@diff}{\@dtl@num}{\@dtl@mean}% - \FPmul{\@dtl@diff}{\@dtl@diff}{\@dtl@diff}% - \FPadd{\@dtl@var}{\@dtl@var}{\@dtl@diff}% -}% -\FPdiv{\@dtl@var}{\@dtl@var}{\@dtl@n}% -\ifx\@dtl@replaced\@empty - \DTLdecimaltolocale{\@dtl@var}{#1}% -\else - \DTLdecimaltocurrency{\@dtl@var}{#1}% -\fi -} + \ifx\@dtl@line\@longempty + \@dtl@conditiontrue + \fi + \fi % \end{macrocode} -%\end{macro} -%\begin{macro}{\DTLgvarianceforall} -%\begin{definition} -%\cs{DTLgvarianceforall}\marg{cmd}\marg{num list} -%\end{definition} -% Global version +% Repeat loop if necessary % \begin{macrocode} -\newcommand*{\DTLgvarianceforall}[2]{% -\DTLvarianceforall{\@dtl@tmpi}{#2}% -\global\let#1=\@dtl@tmpi -} + \if@dtl@condition + \repeat % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\DTLsdforall} -%\begin{definition} -%\cs{DTLsdforall}\marg{cmd}\marg{num list} -%\end{definition} -% Computes the standard deviation of all the values in \meta{num list} -% and stores in \meta{cmd} which must be a control sequence. -%\changes{1.01}{2007 Aug 17}{fixed bug} -%\changes{1.01}{2007 Aug 17}{removed extraneous space} +% Parse the header row. Store the row as +% \meta{sep}\meta{row}\meta{sep} in \cs{@dtl@lin@}. % \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 -} + \protected@edef\@dtl@lin@{% + \@dtl@separator\@dtl@line\@dtl@separator}% % \end{macrocode} -%\end{macro} -%\begin{macro}{\DTLgsdforall} -%\begin{definition} -%\cs{DTLgsdforall}\marg{cmd}\marg{num list} -%\end{definition} -% Global version +% Keep track of columns: % \begin{macrocode} -\newcommand*{\DTLgsdforall}[2]{% -\DTLsdforall{\@dtl@tmpi}{#2}% -\global\let#1=\@dtl@tmpi -} + \dtl@entrycr=0\relax % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\DTLround} -%\begin{definition} -% \cs{DTLround}\marg{cmd}\marg{num}\marg{num digits} -%\end{definition} -% Sets \meta{cmd} to \meta{num} rounded to \meta{num digits} -% digits after the decimal character. +% 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} -\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 -} + \loop % \end{macrocode} -%\end{macro} -%\begin{macro}{\DTLground} -% Global version +% Lopoff the first element and store in \cs{@dtl@key} % \begin{macrocode} -\newcommand*{\DTLground}[3]{% -\DTLround{\@dtl@tmpii}{#2}{#3}% -\global\let#1=\@dtl@tmpii -} + \expandafter\@dtl@lopoff\@dtl@lin@\to\@dtl@lin@\@dtl@key % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\DTLtrunc} -%\begin{definition} -% \cs{DTLtrunc}\marg{cmd}\marg{num}\marg{num digits} -%\end{definition} -% Sets \meta{cmd} to \meta{num} truncated to \meta{num digits} -% digits after the decimal character. +% Increment column count. % \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 -} + \advance\dtl@entrycr by 1\relax % \end{macrocode} -%\end{macro} -%\begin{macro}{\DTLgtrunc} -% Global version +% Store key in \cs{@dtl@toks} % \begin{macrocode} -\newcommand*{\DTLgtrunc}[3]{% -\DTLtrunc{\@dtl@tmpii}{#2}{#3}% -\global\let#1=\@dtl@tmpii -} + \expandafter\@dtl@toks\expandafter{\@dtl@key}% % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\DTLclip} -%\begin{definition} -% \cs{DTLclip}\marg{cmd}\marg{num} -%\end{definition} -% Sets \meta{cmd} to \meta{num} with all unnecessary 0's removed. +% 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*{\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 -} + \@ifundefined{@dtl@inky@\romannumeral\dtl@entrycr}% + {% + \expandafter + \edef\csname @dtl@inky@\romannumeral + \dtl@entrycr\endcsname{\the\@dtl@toks}% + }% + {% % \end{macrocode} -%\end{macro} -%\begin{macro}{\DTLgclip} -% Global version +% 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*{\DTLgclip}[3]{% -\DTLclip{\@dtl@tmpii}{#2}% -\global\let#1=\@dtl@tmpii -} + \@ifundefined{@dtl@inhd@\romannumeral\dtl@entrycr}% + {% + \expandafter + \edef\csname @dtl@inhd@\romannumeral + \dtl@entrycr\endcsname{\the\@dtl@toks}% + }% + {}% + }% % \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}} +% Check if the loop should be repeated % \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}% + \ifx\@dtl@lin@\@dtl@separator + \@dtl@conditionfalse + \else + \@dtl@conditiontrue + \fi % \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.) +% Repeat loop if necessary. % \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 + \if@dtl@condition + \repeat % \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}} +% End if no header % \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 -} + \fi % \end{macrocode} -%\end{macro} -%\begin{macro}{\dtl@initials} +% 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} -\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 -} + \ifeof\@dtl@read + \ifdtlnoheader + \PackageWarning{datatool}{No data in `#3'}% + \else + \PackageWarning{datatool}{Only header row found in `#3'}% + \fi + \else % \end{macrocode} -%\end{macro} -%\begin{macro}{\@dtl@initials} +% Iterate through the rest of the file. First set the repeat +% condition to true: % \begin{macrocode} -\def\@dtl@initials#1#2 #3{% -\dtl@initialshyphen#2-{}\dtl@endhyp -\expandafter\@dtl@toks\expandafter{\dtl@initialscmd}% -\toks@{#1}% -\ifx\dtl@inithyphen\@empty -\else - \edef\dtl@initialscmd{\the\@dtl@toks\the\toks@}% - \expandafter\@dtl@toks\expandafter{\dtl@initialscmd}% - \expandafter\toks@\expandafter{\dtl@inithyphen}% -\fi -\def\dtl@tmp{#3}% -\ifx\@nnil\dtl@tmp - \edef\dtl@initialscmd{\the\@dtl@toks\the\toks@\DTLafterinitials}% - \let\dtl@initialsnext=\@gobble -\else - \edef\dtl@initialscmd{\the\@dtl@toks\the\toks@\DTLbetweeninitials}% - \let\dtl@initialsnext=\dtl@initials -\fi -\dtl@initialsnext{#3}} + \@dtl@conditiontrue + \loop % \end{macrocode} -%\end{macro} -%\begin{macro}{\dtl@initialshyphen} +% Read in a line % \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 -} + \@dtl@doreadline\@dtl@read\@dtl@line % \end{macrocode} -%\end{macro} -%\begin{macro}{\DTLafterinitials} -% Defines what to do after the final initial. +% Check if the line is empty. +%\changes{2.0}{2009 February 27}{changed \cs{ifthenelse} to +%\cs{ifx} to improve efficiency} % \begin{macrocode} -\newcommand*{\DTLafterinitials}{.} + \ifx\@dtl@line\@longempty % \end{macrocode} -%\end{macro} -%\begin{macro}{\DTLbetweeninitials} -% Defines what to do between initials. +% Do nothing if the row is empty. % \begin{macrocode} -\newcommand*{\DTLbetweeninitials}{.} + \else % \end{macrocode} -%\end{macro} -%\begin{macro}{\DTLafterinitialbeforehyphen} -% Defines what to do before a hyphen. +% Add a new row to the database. (Don't need to check if the +% database exists, since it's just been created.) % \begin{macrocode} -\newcommand*{\DTLafterinitialbeforehyphen}{.} + \@sDTLnewrow{#2}% % \end{macrocode} -%\end{macro} -%\begin{macro}{\DTLinitialhyphen} -%Defines what to do at the hyphen -%\changes{1.01}{2007 Aug 17}{new} +% Store the row as \meta{sep}\meta{row}\meta{sep} to make the +% lopping off easier % \begin{macrocode} -\newcommand*{\DTLinitialhyphen}{-} + \expandafter\@dtl@toks\expandafter{\@dtl@line}% + \edef\@dtl@lin@{\@dtl@separator\the\@dtl@toks + \@dtl@separator}% % \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}. +% Reset the column counter. % \begin{macrocode} -\newcommand*{\DTLifAllUpperCase}[3]{% -\protected@edef\dtl@tuc{#1}% -\expandafter\dtl@testifuppercase\dtl@tuc\@nil\relax -\if@dtl@condition#2\else#3\fi -} + \dtl@entrycr=0\relax % \end{macrocode} -%\end{macro} -%\begin{macro}{\dtl@testifalluppercase} +%\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} -\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} +% Initialise repeat condition % \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 -}}} + \@dtl@conditiontrue % \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}. +% Iterate through the list % \begin{macrocode} -\newcommand*{\DTLifAllLowerCase}[3]{% -\protected@edef\dtl@tlc{#1}% -\expandafter\dtl@testiflowercase\dtl@tlc\@nil\relax -\if@dtl@condition#2\else#3\fi -} + \loop % \end{macrocode} -%\end{macro} -%\begin{macro}{\dtl@testifalllowercase} +% lop off first element and store in \cs{@dtl@thisentry} % \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 -} + \expandafter\@dtl@lopoff\@dtl@lin@\to + \@dtl@lin@\@dtl@thisentry % \end{macrocode} -%\end{macro} -%\begin{macro}{\dtl@test@ifalllowercase} +% Increment the column count. % \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 -}}} + \advance\dtl@entrycr by 1\relax % \end{macrocode} -%\end{macro} -% -%\subsection{Saving a database to an external file} -% -%\begin{macro}{\@dtl@write} +% Get the key for this column and store in \cs{@dtl@thiskey}. +% Use default value if not defined. % \begin{macrocode} -\newwrite\@dtl@write + \@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} -%\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} +% Store this entry in \cs{@dtl@toks} % \begin{macrocode} -\newcommand*{\DTLsavedb}[2]{% - \DTLifdbexists{#1}% - {% + \expandafter\@dtl@toks\expandafter{\@dtl@thisentry}% % \end{macrocode} -% Open output file -%\changes{2.02}{2009 July 13}{Fixed bug that didn't set the filename} +% Add this entry to the database % \begin{macrocode} - \openout\@dtl@write=#2\relax + \edef\@do@dtlnewentry{\noexpand\@sDTLnewdbentry + {#2}{\@dtl@thiskey}{\the\@dtl@toks}}% + \@do@dtlnewentry % \end{macrocode} -% Initialise header row +% Check if loop should be terminated % \begin{macrocode} - \def\@dtl@header{}% + \ifx\@dtl@lin@\@dtl@separator + \@dtl@conditionfalse + \fi % \end{macrocode} -% Construct the header row +% Repeat loop if necessary % \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 - }% - }% + \if@dtl@condition + \repeat + }% % \end{macrocode} -% Print header +% End of parsing this row % \begin{macrocode} - \protected@write\@dtl@write{}{\@dtl@header}% + \fi % \end{macrocode} -% Iterate through each row +% If the end of file has been reached, set the repeat condition +% to false. % \begin{macrocode} - \@sDTLforeach{#1}{}% - {% + \ifeof\@dtl@read \@dtl@conditionfalse\fi % \end{macrocode} -% Initialise row +% Repeat if necessary % \begin{macrocode} - \def\@dtl@row{}% + \if@dtl@condition + \repeat + \fi % \end{macrocode} -% Iterate through each key +% End of first \cs{ifeof} % \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 - }% + \fi % \end{macrocode} -% Print row +% Close the input file % \begin{macrocode} - \protected@write\@dtl@write{}{\@dtl@row}% - }% - }% + \closein\@dtl@read % \end{macrocode} -% Close output file +% Set the headers if required % \begin{macrocode} - \closeout\@dtl@write - }% - {% - \PackageError{datatool}{Can't save database `#1': no such - database}{}% - }% -} + \edef\@dtl@maxcols{\expandafter + \number\csname dtlcols@#2\endcsname}% + \dtlgforint\dtl@entrycr=1\to\@dtl@maxcols\step1\do + {% + \@ifundefined{@dtl@inhd@\romannumeral\dtl@entrycr}% + {}% + {% + \expandafter\let\expandafter\@dtl@head + \csname @dtl@inhd@\romannumeral\dtl@entrycr\endcsname + \@dtl@toks=\expandafter{\@dtl@head}% + \edef\@dtl@dosetheader{\noexpand\@dtl@setheaderforindex + {#2}{\number\dtl@entrycr}{\the\@dtl@toks}}% + \@dtl@dosetheader + }% + }% % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\DTLsavetexdb} -%\begin{definition} -% \cs{DTLsavetexdb}\marg{db name}\marg{filename} -%\end{definition} -% Save a database as a \LaTeX\ file. -%\changes{2.0}{2009 February 27}{updated to use new database structure} -% \begin{macrocode} -\newcommand*{\DTLsavetexdb}[2]{% - \DTLifdbexists{#1}% - {% -% \end{macrocode} -% Open output file -% \begin{macrocode} - \openout\@dtl@write=#2\relax -% \end{macrocode} -% Write new data base definition -% \begin{macrocode} - \protected@write\@dtl@write{}{\string\DTLnewdb{#1}}% -% \end{macrocode} -% Iterate through each row -% \begin{macrocode} - \@sDTLforeach{#1}{}% - {% -% \end{macrocode} -% Start new row -% \begin{macrocode} - \protected@write\@dtl@write{}{\string\DTLnewrow*{#1}}% -% \end{macrocode} -% Iterate through each column -% \begin{macrocode} - \DTLforeachkeyinrow{\@dtl@val}% - {% -% \end{macrocode} -% Is this entry null? -% \begin{macrocode} - \DTLifnull{\@dtl@val}% - {\def\@dtl@val{}}% - {}% -% \end{macrocode} -% Add entry +% End current scope % \begin{macrocode} - \protected@write\@dtl@write{}{% - \string\DTLnewdbentry*{#1}{\dtlkey}{\@dtl@val}}% - }% - }% + \endgroup % \end{macrocode} -% Save the column headers. +% End true part of if file exists % \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 +% Requested file not found on TeX's path % \begin{macrocode} - \closeout\@dtl@write - }% - {% - \PackageError{datatool}{Can't save database `#1': no such - database}{}% + \PackageError{datatool}{Can't load database `#2' (file `#3' + doesn't exist)}{}% }% } % \end{macrocode} %\end{macro} % -%\subsection{Loading a database from an external file} -% -% \begin{macrocode} -\newcommand{\@longempty}{} -% \end{macrocode} -%\begin{macro}{\@dtl@read} +%\begin{macro}{\dtl@trim} +%\begin{definition} +%\cs{dtl@trim}\marg{line} +%\end{definition} +% Trims the trailing space from \meta{line}. % \begin{macrocode} -\newread\@dtl@read +\newcommand{\dtl@trim}[1]{% +\def\@dtl@trmstr{}% +\expandafter\@dtl@starttrim#1\@nil% +\let#1=\@dtl@trmstr +} % \end{macrocode} %\end{macro} -%\begin{macro}{\dtl@entrycr} -% Keep track of current column in data file +%\begin{macro}{\@dtl@starttrim} +% Start trimming % \begin{macrocode} -\newcount\dtl@entrycr +\long\def\@dtl@starttrim#1#2{% +\ifx\par#1% + \def\@dtl@dotrim{\@dtl@trim{} #2}% +\else + \def\@dtl@dotrim{\@dtl@trim#1#2}% +\fi +\@dtl@dotrim% +} % \end{macrocode} %\end{macro} -% -%\begin{macro}{\ifdtlnoheader} -% The "noheader" option indicates that the file doesn't have a -% header row. +%\begin{macro}{\@dtl@trim} % \begin{macrocode} -\define@boolkey{loaddb}[dtl]{noheader}[true]{} +\long\def\@dtl@trim#1 \@nil{\long\def\@dtl@trmstr{#1}} % \end{macrocode} %\end{macro} -% The "keys" option specifies the list of keys in the same order -% as the columns in the data file. -% Each key is stored in \cs{@dtl@inky@}\meta{n} where \meta{n} is the -% roman numeral representation of the current column. -% \begin{macrocode} -\define@key{loaddb}{keys}{% - \dtl@entrycr=0\relax - \@for\@dtl@key:=#1\do - {% - \advance\dtl@entrycr by 1\relax - \expandafter - \edef\csname @dtl@inky@\romannumeral\dtl@entrycr\endcsname{% - \@dtl@key}% - }% -} -% \end{macrocode} -% The "headers" option specifies the list of headers in the -% same order as the columns in the data file. -% \begin{macrocode} -\define@key{loaddb}{headers}{% - \dtl@entrycr=0\relax - \@for\@dtl@head:=#1\do - {% - \advance\dtl@entrycr by 1\relax - \toks@=\expandafter{\@dtl@head}% - \expandafter - \edef\csname @dtl@inhd@\romannumeral\dtl@entrycr\endcsname{% - \the\toks@}% - }% -} -% \end{macrocode} % -%\begin{macro}{\dtldefaultkey} -% Default key to use if none specified (column index will be -% appended). +%\begin{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*{\dtldefaultkey}{Column} +\newcommand*\DTLloadrawdb{% + \let\@dtl@doreadline\@dtl@readrawline + \@dtlloaddb +} % \end{macrocode} %\end{macro} % -%\begin{macro}{\@dtl@readline} +%\begin{macro}{\@dtl@rawread} %\begin{definition} -%\cs{@dtl@readline}\marg{file reg}\marg{cs} +% \cs{@dtl@rawread}\meta{number}to\meta{cmd} %\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" +% Reads in a raw line from file given by \meta{number} +% converts special characters and stores in \meta{cmd} % \begin{macrocode} - \read#1 to #2% +\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} -% Trim the end of line character +%\end{macro} +%\begin{macro}{\@dtl@activatebraces} +% \cs{@dtl@activatebraces} resets braces for \cs{@dtl@rawread} % \begin{macrocode} - \dtl@trim#2% -} +\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}{\@dtl@readrawline} +%\begin{macro}{\DTLrawmap} %\begin{definition} -%\cs{@dtl@readrawline}\marg{file register}\marg{cs} +%\cs{DTLrawmap}\marg{string}\marg{replacement} %\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 +% Additional mappings to perform when reading a raw data file % \begin{macrocode} - \dtl@trim#2% +\newcommand*{\DTLrawmap}[2]{% +\expandafter\@dtl@toks\expandafter{\@dtl@rawmappings}% +\ifx\@dtl@rawmappings\@empty + \def\@dtl@rawmappings{{#1}{#2}}% +\else + \def\@dtl@tmp{{#1}{#2}} + \protected@edef\@dtl@rawmappings{\the\@dtl@toks,\@dtl@tmp} +\fi +} % \end{macrocode} -% Apply mappings +%\end{macro} +% +%\begin{macro}{\@dtl@rawmappings} +% List of mappings. % \begin{macrocode} - \dtl@domappings\@dtl@line -} +\newcommand*{\@dtl@rawmappings}{} % \end{macrocode} %\end{macro} - -%\begin{macro}{\DTLloaddb} +%\begin{macro}{\dtl@domappings} %\begin{definition} -% \cs{DTLloaddb}\oarg{options}\marg{db name}\marg{filename} +% \cs{dtl@domappings}\marg{cmd} %\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} +% Do all mappings in string given by \meta{cmd}. % \begin{macrocode} -\newcommand*{\DTLloaddb}{% - \let\@dtl@doreadline\@dtl@readline - \@dtlloaddb -} +\newcommand*{\dtl@domappings}[1]{% +\@for\@dtl@map:=\@dtl@rawmappings\do{% + \expandafter\DTLsubstitute\expandafter#1\@dtl@map +}} % \end{macrocode} %\end{macro} % -%\begin{macro}{\@dtlloaddb} -% Loads database using \cs{@dtl@doreadline} to read and trim -% line from file. (\cs{@dtl@doreadline} must be set before use.) -% \begin{macrocode} -\newcommand*{\@dtlloaddb}[3][]{% -% \end{macrocode} -% Check if file exists -% \begin{macrocode} - \IfFileExists{#3}{% -% \end{macrocode} -% File exists. Locally change catcode of double quote character in -% case it has been made active. +%\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} - \begingroup - \catcode`\"12\relax +\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} -% Initialise default options +%\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} - \dtlnoheaderfalse +\newcommand*{\dtl@choplast}[3]{% % \end{macrocode} -% Get the options +% Set \meta{rest} to empty: % \begin{macrocode} - \setkeys{loaddb}{#1}% +\let#2\@empty % \end{macrocode} -% Open the file for reading. +% Set \meta{last} to empty: % \begin{macrocode} - \openin\@dtl@read=#3% - \dtl@message{Reading `#3'}% +\let#3\@empty % \end{macrocode} -% Create the new database. +% Iterate through \meta{list}: % \begin{macrocode} - \DTLnewdb{#2}% +\@for\@dtl@element:=#1\do{% +\ifx#3\@empty % \end{macrocode} -% Check if the file is empty. +% First iteration, don't set \meta{rest}. % \begin{macrocode} - \ifeof\@dtl@read +\else + \ifx#2\@empty % \end{macrocode} -% File is empty, so just issue a warning. +% Second iteration, set \meta{rest} to \meta{last} (which is +% currently set to the previous value: % \begin{macrocode} - \PackageWarning{datatool}{File `#3' has no data}% - \else + \expandafter\toks@\expandafter{#3}% + \edef#2{{\the\toks@}}% + \else % \end{macrocode} -% Does the file have a header row? +% Subsequent iterations, set \meta{rest} to \meta{rest},\meta{last} +% (\meta{last} is currently set to the previous value): % \begin{macrocode} - \ifdtlnoheader - \else + \expandafter\toks@\expandafter{#3}% + \expandafter\@dtl@toks\expandafter{#2}% + \edef#2{\the\@dtl@toks,{\the\toks@}}% + \fi +\fi % \end{macrocode} -% Remove initial blank rows +% Now set \meta{last} to current element. % \begin{macrocode} - \loop +\let#3=\@dtl@element% +}% +} % \end{macrocode} -% Set repeat condition to false +%\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} - \@dtl@conditionfalse +\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} -% Do nothing if reached the end of file +%\end{macro} +% +%\begin{macro}{\dtl@sortlist} +%\begin{definition} +% \cs{dtl@sortlist}\marg{list}\marg{criteria cmd} +%\end{definition} +% Performs an insertion sort on \meta{list}, where \meta{criteria cmd} +% is a macro which takes two arguments \meta{a} and \meta{b}. +% \meta{criteria cmd} must set the count register \cs{dtl@sortresult} +% to either -1 (\meta{a} less than \meta{b}), 0 (\meta{a} is +% equal to \meta{b}) or 1 (\meta{a} is greater than \meta{b}.) % \begin{macrocode} - \ifeof\@dtl@read - \else +\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} -% Read a line from the file and store in \cs{@dtl@line} +%\end{macro} +% +%\begin{macro}{\dtl@insertinto} +%\begin{definition} +% \cs{dtl@insertinto}\marg{element}\marg{sorted-list}\marg{criteria cmd} +%\end{definition} +% Inserts \meta{element} into the sorted list \meta{sorted-list} +% according to the criteria given by \meta{criteria cmd} (see above.) % \begin{macrocode} - \@dtl@doreadline\@dtl@read\@dtl@line +\newcommand{\dtl@insertinto}[3]{% +\def\@dtl@newsortedlist{}% +\@dtl@insertdonefalse +\@for\dtl@srtelement:=#2\do{% +\if@dtl@insertdone + \expandafter\toks@\expandafter{\dtl@srtelement}% + \edef\@dtl@newstuff{{\the\toks@}}% +\else + \expandafter#3\expandafter{\dtl@srtelement}{#1}% + \ifnum\dtl@sortresult<0\relax + \expandafter\toks@\expandafter{\dtl@srtelement}% + \@dtl@toks{#1}% + \edef\@dtl@newstuff{{\the\@dtl@toks},{\the\toks@}}% + \@dtl@insertdonetrue + \else + \expandafter\toks@\expandafter{\dtl@srtelement}% + \edef\@dtl@newstuff{{\the\toks@}}% + \fi +\fi +\ifx\@dtl@newsortedlist\@empty + \expandafter\toks@\expandafter{\@dtl@newstuff}% + \edef\@dtl@newsortedlist{\the\toks@}% +\else + \expandafter\toks@\expandafter{\@dtl@newsortedlist}% + \expandafter\@dtl@toks\expandafter{\@dtl@newstuff}% + \edef\@dtl@newsortedlist{\the\toks@,\the\@dtl@toks}% +\fi +\@endforfalse +}% + \ifx\@dtl@newsortedlist\@empty + \@dtl@toks{#1}% + \edef\@dtl@newsortedlist{{\the\@dtl@toks}}% + \else + \if@dtl@insertdone + \else + \expandafter\toks@\expandafter{\@dtl@newsortedlist}% + \@dtl@toks{#1}% + \edef\@dtl@newsortedlist{\the\toks@,{\the\@dtl@toks}}% + \fi + \fi +\global\let#2=\@dtl@newsortedlist +} % \end{macrocode} -% If this is a blank row, set repeat condition to true +%\end{macro} +%\begin{macro}{\if@dtl@insertdone} +% Define conditional to indicate whether the new entry has +% been inserted into the sorted list. % \begin{macrocode} - \ifx\@dtl@line\@longempty - \@dtl@conditiontrue - \fi - \fi +\newif\if@dtl@insertdone % \end{macrocode} -% Repeat loop if necessary +%\end{macro} +%\begin{macro}{\dtl@sortresult} +% Define \cs{dtl@sortresult} to be set by comparision macro. % \begin{macrocode} - \if@dtl@condition - \repeat +\newcount\dtl@sortresult % \end{macrocode} -% Parse the header row. Store the row as -% \meta{sep}\meta{row}\meta{sep} in \cs{@dtl@lin@}. +%\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} - \protected@edef\@dtl@lin@{% - \@dtl@separator\@dtl@line\@dtl@separator}% +\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} -% Keep track of columns: +%\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} - \dtl@entrycr=0\relax +\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} -% 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} +% +% \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} - \loop +\newcommand*{\DTLadd}[3]{% +\DTLconverttodecimal{#2}{\@dtl@numi}% +\DTLconverttodecimal{#3}{\@dtl@numii}% +\FPadd{\@dtl@tmp}{\@dtl@numi}{\@dtl@numii}% +\ifx\@dtl@replaced\@empty + \DTLdecimaltolocale{\@dtl@tmp}{#1}% +\else + \DTLdecimaltocurrency{\@dtl@tmp}{#1}% +\fi +} % \end{macrocode} -% Lopoff the first element and store in \cs{@dtl@key} +%\end{macro} +%\begin{macro}{\DTLgadd} +% Global version % \begin{macrocode} - \expandafter\@dtl@lopoff\@dtl@lin@\to\@dtl@lin@\@dtl@key +\newcommand*{\DTLgadd}[3]{% +\DTLadd{\@dtl@tmpii}{#2}{#3}% +\global\let#1=\@dtl@tmpii +} % \end{macrocode} -% Increment column count. +%\end{macro} +% +%\begin{macro}{\DTLaddall} +%\begin{definition} +%\cs{DTLaddall}\marg{cmd}\marg{num list} +%\end{definition} +% Sums all the values in \meta{num list} and stores in +% \meta{cmd} which must be a control sequence. +%\changes{1.01}{2007 Aug 17}{removed extraneous space} % \begin{macrocode} - \advance\dtl@entrycr by 1\relax +\newcommand*{\DTLaddall}[2]{% +\def\@dtl@sum{0}% +\@for\dtl@thisval:=#2\do{% + \DTLconverttodecimal{\dtl@thisval}{\@dtl@num}% + \FPadd{\@dtl@sum}{\@dtl@sum}{\@dtl@num}% +}% +\ifx\@dtl@replaced\@empty + \DTLdecimaltolocale{\@dtl@sum}{#1}% +\else + \DTLdecimaltocurrency{\@dtl@sum}{#1}% +\fi +} % \end{macrocode} -% Store key in \cs{@dtl@toks} +%\end{macro} +%\begin{macro}{\DTLgaddall} +%\begin{definition} +%\cs{DTLgaddall}\marg{cmd}\marg{num list} +%\end{definition} +% Global version % \begin{macrocode} - \expandafter\@dtl@toks\expandafter{\@dtl@key}% +\newcommand*{\DTLgaddall}[2]{% +\DTLaddall{\@dtl@tmpi}{#2}% +\global\let#1=\@dtl@tmpi +} % \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} +% +%\begin{macro}{\DTLsub} +%\begin{definition} +% \cs{DTLsub}\marg{cmd}\marg{num1}\marg{num2} +%\end{definition} +% Sets \meta{cmd} = \meta{num1} - \meta{num2} % \begin{macrocode} - \@ifundefined{@dtl@inky@\romannumeral\dtl@entrycr}% - {% - \expandafter - \edef\csname @dtl@inky@\romannumeral - \dtl@entrycr\endcsname{\the\@dtl@toks}% - }% - {% +\newcommand*{\DTLsub}[3]{% +\DTLconverttodecimal{#2}{\@dtl@numi}% +\DTLconverttodecimal{#3}{\@dtl@numii}% +\FPsub{\@dtl@tmp}{\@dtl@numi}{\@dtl@numii}% +\ifx\@dtl@replaced\@empty + \DTLdecimaltolocale{\@dtl@tmp}{#1}% +\else + \DTLdecimaltocurrency{\@dtl@tmp}{#1}% +\fi +} % \end{macrocode} -% 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}{\DTLgsub} +% Global version % \begin{macrocode} - \@ifundefined{@dtl@inhd@\romannumeral\dtl@entrycr}% - {% - \expandafter - \edef\csname @dtl@inhd@\romannumeral - \dtl@entrycr\endcsname{\the\@dtl@toks}% - }% - {}% - }% +\newcommand*{\DTLgsub}[3]{% +\DTLsub{\@dtl@tmpii}{#2}{#3}% +\global\let#1=\@dtl@tmpii +} % \end{macrocode} -% Check if the loop should be repeated +%\end{macro} +% +%\begin{macro}{\DTLmul} +%\begin{definition} +% \cs{DTLmul}\marg{cmd}\marg{num1}\marg{num2} +%\end{definition} +% Sets \meta{cmd} = \meta{num1} $\times$ \meta{num2} % \begin{macrocode} - \ifx\@dtl@lin@\@dtl@separator - \@dtl@conditionfalse - \else - \@dtl@conditiontrue - \fi +\newcommand*{\DTLmul}[3]{% +\let\@dtl@thisreplaced=\@empty +\DTLconverttodecimal{#2}{\@dtl@numi}% +\ifx\@dtl@replaced\@empty +\else + \let\@dtl@thisreplaced=\@dtl@replaced +\fi +\DTLconverttodecimal{#3}{\@dtl@numii}% +\ifx\@dtl@replaced\@empty +\else + \let\@dtl@thisreplaced=\@dtl@replaced +\fi +\FPmul{\@dtl@tmp}{\@dtl@numi}{\@dtl@numii}% +\ifx\@dtl@thisreplaced\@empty + \DTLdecimaltolocale{\@dtl@tmp}{#1}% +\else + \DTLdecimaltocurrency{\@dtl@tmp}{#1}% +\fi +} % \end{macrocode} -% Repeat loop if necessary. +%\end{macro} +%\begin{macro}{\DTLgmul} +% Global version % \begin{macrocode} - \if@dtl@condition - \repeat +\newcommand*{\DTLgmul}[3]{% +\DTLmul{\@dtl@tmpii}{#2}{#3}% +\global\let#1=\@dtl@tmpii +} % \end{macrocode} -% End if no header +%\end{macro} +% +%\begin{macro}{\DTLdiv} +%\begin{definition} +% \cs{DTLdiv}\marg{cmd}\marg{num1}\marg{num2} +%\end{definition} +% Sets \meta{cmd} = \meta{num1} / \meta{num2} % \begin{macrocode} - \fi +\newcommand*{\DTLdiv}[3]{% +\let\@dtl@thisreplaced=\@empty +\DTLconverttodecimal{#2}{\@dtl@numi}% +\ifx\@dtl@replaced\@empty +\else + \let\@dtl@thisreplaced=\@dtl@replaced +\fi +\DTLconverttodecimal{#3}{\@dtl@numii}% +\FPdiv{\@dtl@tmp}{\@dtl@numi}{\@dtl@numii}% +\ifx\@dtl@thisreplaced\@empty + \DTLdecimaltolocale{\@dtl@tmp}{#1}% +\else + \ifx\@dtl@thisreplaced\@dtl@replaced + \DTLdecimaltolocale{\@dtl@tmp}{#1}% + \else + \DTLdecimaltocurrency{\@dtl@tmp}{#1}% + \fi +\fi +} % \end{macrocode} -% 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}{\DTLgdiv} +% Global version % \begin{macrocode} - \ifeof\@dtl@read - \ifdtlnoheader - \PackageWarning{datatool}{No data in `#3'}% - \else - \PackageWarning{datatool}{Only header row found in `#3'}% - \fi - \else +\newcommand*{\DTLgdiv}[3]{% +\DTLdiv{\@dtl@tmpii}{#2}{#3}% +\global\let#1=\@dtl@tmpii +} % \end{macrocode} -% Iterate through the rest of the file. First set the repeat -% condition to true: +%\end{macro} +% +%\begin{macro}{\DTLabs} +%\begin{definition} +% \cs{DTLabs}\marg{cmd}\marg{num} +%\end{definition} +% Sets \meta{cmd} = abs(\meta{num}) % \begin{macrocode} - \@dtl@conditiontrue - \loop +\newcommand*{\DTLabs}[2]{% +\DTLconverttodecimal{#2}{\@dtl@numi}% +\FPabs{\@dtl@tmp}{\@dtl@numi}% +\ifx\@dtl@replaced\@empty + \DTLdecimaltolocale{\@dtl@tmp}{#1}% +\else + \DTLdecimaltocurrency{\@dtl@tmp}{#1}% +\fi +} % \end{macrocode} -% Read in a line +%\end{macro} +%\begin{macro}{\DTLgabs} +% Global version % \begin{macrocode} - \@dtl@doreadline\@dtl@read\@dtl@line +\newcommand*{\DTLgabs}[2]{% +\DTLabs{\@dtl@tmpii}{#2}% +\global\let#1=\@dtl@tmpii +} % \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}{\DTLneg} +%\begin{definition} +% \cs{DTLneg}\marg{cmd}\marg{num} +%\end{definition} +% Sets \meta{cmd} = -\meta{num} % \begin{macrocode} - \ifx\@dtl@line\@longempty +\newcommand*{\DTLneg}[2]{% +\DTLconverttodecimal{#2}{\@dtl@numi}% +\FPneg{\@dtl@tmp}{\@dtl@numi}% +\ifx\@dtl@replaced\@empty + \DTLdecimaltolocale{\@dtl@tmp}{#1}% +\else + \DTLdecimaltocurrency{\@dtl@tmp}{#1}% +\fi +} % \end{macrocode} -% Do nothing if the row is empty. +%\end{macro} +%\begin{macro}{\DTLgneg} +% Global version % \begin{macrocode} - \else +\newcommand*{\DTLgneg}[2]{% +\DTLneg{\@dtl@tmpii}{#2}% +\global\let#1=\@dtl@tmpii +} % \end{macrocode} -% Add a new row to the database. (Don't need to check if the -% database exists, since it's just been created.) -% \begin{macrocode} - \@sDTLnewrow{#2}% -% \end{macrocode} -% Store the row as \meta{sep}\meta{row}\meta{sep} to make the -% lopping off easier -% \begin{macrocode} - \expandafter\@dtl@toks\expandafter{\@dtl@line}% - \edef\@dtl@lin@{\@dtl@separator\the\@dtl@toks - \@dtl@separator}% -% \end{macrocode} -% Reset the column counter. -% \begin{macrocode} - \dtl@entrycr=0\relax -% \end{macrocode} -%\changes{2.0}{2009 February 27}{changed \cs{whiledo} to \cs{loop} -% to improve efficiency} -% Iterate through each element in the row. Needs to be grouped -% since we're already inside a loop. -% \begin{macrocode} - {% -% \end{macrocode} -% Initialise repeat condition -% \begin{macrocode} - \@dtl@conditiontrue -% \end{macrocode} -% Iterate through the list -% \begin{macrocode} - \loop -% \end{macrocode} -% lop off first element and store in \cs{@dtl@thisentry} -% \begin{macrocode} - \expandafter\@dtl@lopoff\@dtl@lin@\to - \@dtl@lin@\@dtl@thisentry -% \end{macrocode} -% Increment the column count. -% \begin{macrocode} - \advance\dtl@entrycr by 1\relax -% \end{macrocode} -% Get the key for this column and store in \cs{@dtl@thiskey}. -% Use default value if not defined. -% \begin{macrocode} - \@ifundefined{@dtl@inky@\romannumeral\dtl@entrycr}% - {% - \edef\@dtl@thiskey{\dtldefaultkey - \number\dtl@entrycr}% - \expandafter\let - \csname @dtl@inky@\romannumeral - \dtl@entrycr\endcsname\@dtl@thiskey - }% - {% - \edef\@dtl@thiskey{% - \csname @dtl@inky@\romannumeral - \dtl@entrycr\endcsname}% - }% -% \end{macrocode} -% Store this entry in \cs{@dtl@toks} -% \begin{macrocode} - \expandafter\@dtl@toks\expandafter{\@dtl@thisentry}% -% \end{macrocode} -% Add this entry to the database -% \begin{macrocode} - \edef\@do@dtlnewentry{\noexpand\@sDTLnewdbentry - {#2}{\@dtl@thiskey}{\the\@dtl@toks}}% - \@do@dtlnewentry -% \end{macrocode} -% Check if loop should be terminated -% \begin{macrocode} - \ifx\@dtl@lin@\@dtl@separator - \@dtl@conditionfalse - \fi -% \end{macrocode} -% Repeat loop if necessary -% \begin{macrocode} - \if@dtl@condition - \repeat - }% -% \end{macrocode} -% End of parsing this row -% \begin{macrocode} - \fi -% \end{macrocode} -% If the end of file has been reached, set the repeat condition -% to false. -% \begin{macrocode} - \ifeof\@dtl@read \@dtl@conditionfalse\fi -% \end{macrocode} -% Repeat if necessary -% \begin{macrocode} - \if@dtl@condition - \repeat - \fi -% \end{macrocode} -% End of first \cs{ifeof} -% \begin{macrocode} - \fi -% \end{macrocode} -% Close the input file +%\end{macro} +% +%\begin{macro}{\DTLsqrt} +%\begin{definition} +% \cs{DTLsqrt}\marg{cmd}\marg{num} +%\end{definition} +% Sets \meta{cmd} = sqrt(\meta{num}) % \begin{macrocode} - \closein\@dtl@read +\newcommand*{\DTLsqrt}[2]{% +\DTLconverttodecimal{#2}{\@dtl@numi}% +\FProot{\@dtl@tmpi}{\@dtl@numi}{2}% +\ifx\@dtl@replaced\@empty + \DTLdecimaltolocale{\@dtl@tmpi}{#1}% +\else + \DTLdecimaltocurrency{\@dtl@tmpi}{#1}% +\fi +} % \end{macrocode} -% Set the headers if required +%\end{macro} +%\begin{macro}{\DTLgsqrt} +% Global version % \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 - }% - }% +\newcommand*{\DTLgsqrt}[2]{% +\DTLsqrt{\@dtl@tmpii}{#2}% +\global\let#1=\@dtl@tmpii +} % \end{macrocode} -% End current scope +%\end{macro} +% +%\begin{macro}{\DTLmin} +%\begin{definition} +% \cs{DTLmin}\marg{cmd}\marg{num1}\marg{num2} +%\end{definition} +% Sets \meta{cmd} = min(\meta{num1}, \meta{num2}) % \begin{macrocode} - \endgroup +\newcommand*{\DTLmin}[3]{% +\DTLconverttodecimal{#2}{\@dtl@numi}% +\DTLconverttodecimal{#3}{\@dtl@numii}% +\FPiflt{\@dtl@numi}{\@dtl@numii}% + \dtl@ifsingle{#2}{% + \let#1=#2}{% + \def#1{#2}}% +\else + \dtl@ifsingle{#3}{% + \let#1=#3}{% + \def#1{#3}}% +\fi +} % \end{macrocode} -% End true part of if file exists +%\end{macro} +%\begin{macro}{\DTLgmin} +% Global version % \begin{macrocode} - }{% +\newcommand*{\DTLgmin}[3]{% +\DTLmin{\@dtl@tmpii}{#2}{#3}% +\global\let#1=\@dtl@tmpii +} % \end{macrocode} -% Requested file not found on TeX's path +%\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} - \PackageError{datatool}{Can't load database `#2' (file `#3' - doesn't exist)}{}% - }% +\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}{\dtl@trim} +%\begin{macro}{\DTLgminall} %\begin{definition} -%\cs{dtl@trim}\marg{line} +%\cs{DTLgminall}\marg{cmd}\marg{num list} %\end{definition} -% Trims the trailing space from \meta{line}. +% Global version % \begin{macrocode} -\newcommand{\dtl@trim}[1]{% -\def\@dtl@trmstr{}% -\expandafter\@dtl@starttrim#1\@nil% -\let#1=\@dtl@trmstr +\newcommand*{\DTLgminall}[2]{% +\DTLminall{\@dtl@tmpi}{#2}% +\global\let#1=\@dtl@tmpi } % \end{macrocode} %\end{macro} -%\begin{macro}{\@dtl@starttrim} -% Start trimming +% +%\begin{macro}{\DTLmax} +%\begin{definition} +% \cs{DTLmax}\marg{cmd}\marg{num1}\marg{num2} +%\end{definition} +% Sets \meta{cmd} = max(\meta{num1}, \meta{num2}) % \begin{macrocode} -\long\def\@dtl@starttrim#1#2{% -\ifx\par#1% - \def\@dtl@dotrim{\@dtl@trim{} #2}% +\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 - \def\@dtl@dotrim{\@dtl@trim#1#2}% + \dtl@ifsingle{#3}{% + \let#1=#3}{% + \def#1{#3}}% \fi -\@dtl@dotrim% } % \end{macrocode} %\end{macro} -%\begin{macro}{\@dtl@trim} +%\begin{macro}{\DTLgmax} +% Global version % \begin{macrocode} -\long\def\@dtl@trim#1 \@nil{\long\def\@dtl@trmstr{#1}} +\newcommand*{\DTLgmax}[3]{% +\DTLmax{\@dtl@tmpii}{#2}{#3}% +\global\let#1=\@dtl@tmpii +} % \end{macrocode} %\end{macro} % -%\begin{macro}{\DTLloadrawdb} +%\begin{macro}{\DTLmaxall} %\begin{definition} -%\cs{DTLloadrawdb}\marg{db name}\marg{filename} +%\cs{DTLmaxall}\marg{cmd}\marg{num list} %\end{definition} -% Loads a raw database (substitutes "%" $\to$ "\%", -% "$" $\to$ "\$", "&" $\to$ "\&", "#" $\to$ "\#", -% "~" $\to$ "\textasciitilde", "_" $\to$ "\_" -% and "^" $\to$ "\textasciicircum".) +% 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*\DTLloadrawdb{% - \let\@dtl@doreadline\@dtl@readrawline - \@dtlloaddb +\newcommand*{\DTLmaxall}[2]{% +\let\@dtl@max=\@empty +\@for\dtl@thisval:=#2\do{% + \DTLconverttodecimal{\dtl@thisval}{\@dtl@num}% + \ifx\@dtl@max\@empty + \let\@dtl@max\@dtl@num + \else + \FPmax{\@dtl@max}{\@dtl@max}{\@dtl@num}% + \fi +}% +\ifx\@dtl@replaced\@empty + \DTLdecimaltolocale{\@dtl@max}{#1}% +\else + \DTLdecimaltocurrency{\@dtl@max}{#1}% +\fi } % \end{macrocode} %\end{macro} -% -%\begin{macro}{\@dtl@rawread} +%\begin{macro}{\DTLgmaxall} %\begin{definition} -% \cs{@dtl@rawread}\meta{number}to\meta{cmd} +%\cs{DTLgmaxall}\marg{cmd}\marg{num list} %\end{definition} -% Reads in a raw line from file given by \meta{number} -% converts special characters and stores in \meta{cmd} -% \begin{macrocode} -\begingroup -\catcode`\%=\active -\catcode`$=\active -\catcode`&=\active -\catcode`~=\active -\catcode`_=\active -\catcode`^=\active -\catcode`#=\active -\catcode`?=6\relax -\catcode`<=1\relax -\catcode`>=2\relax -\catcode`\{=\active -\catcode`\}=\active -\gdef\@dtl@rawread?1to?2<\relax -<<\catcode`\%=\active -\catcode`$=\active -\catcode`&=\active -\catcode`~=\active -\catcode`_=\active -\catcode`^=\active -\catcode`#=\active -\catcode`\{=\active -\catcode`\}=\active -\def%<\noexpand\%>\relax -\def$<\noexpand\$>\relax -\def&<\&>\relax -\def#<\#>\relax -\def~<\noexpand\textasciitilde>\relax -\def_<\noexpand\_>\relax -\def^<\noexpand\textasciicircum>\relax -\@dtl@activatebraces -\@dtl@doreadraw?1?2>>> -\gdef\@dtl@doreadraw?1?2<\relax -\read?1 to \tmp -\xdef?2<\tmp>\relax -> -\endgroup -% \end{macrocode} -%\end{macro} -%\begin{macro}{\@dtl@activatebraces} -% \cs{@dtl@activatebraces} resets braces for \cs{@dtl@rawread} +% Global version % \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 +\newcommand*{\DTLgmaxall}[2]{% +\DTLmaxall{\@dtl@tmpi}{#2}% +\global\let#1=\@dtl@tmpi +} % \end{macrocode} %\end{macro} % -%\begin{macro}{\DTLrawmap} +%\begin{macro}{\DTLmeanforall} %\begin{definition} -%\cs{DTLrawmap}\marg{string}\marg{replacement} +%\cs{DTLmeanforall}\marg{cmd}\marg{num list} %\end{definition} -% Additional mappings to perform when reading a raw data file +% 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*{\DTLrawmap}[2]{% -\expandafter\@dtl@toks\expandafter{\@dtl@rawmappings}% -\ifx\@dtl@rawmappings\@empty - \def\@dtl@rawmappings{{#1}{#2}}% +\newcommand*{\DTLmeanforall}[2]{% +\def\@dtl@mean{0}% +\def\@dtl@n{0}% +\@for\dtl@thisval:=#2\do{% + \DTLconverttodecimal{\dtl@thisval}{\@dtl@num}% + \FPadd{\@dtl@mean}{\@dtl@mean}{\@dtl@num}% + \FPadd{\@dtl@n}{\@dtl@n}{1}% +}% +\FPdiv{\@dtl@mean}{\@dtl@mean}{\@dtl@n}% +\ifx\@dtl@replaced\@empty + \DTLdecimaltolocale{\@dtl@mean}{#1}% \else - \def\@dtl@tmp{{#1}{#2}} - \protected@edef\@dtl@rawmappings{\the\@dtl@toks,\@dtl@tmp} + \DTLdecimaltocurrency{\@dtl@mean}{#1}% \fi } % \end{macrocode} %\end{macro} -% -%\begin{macro}{\@dtl@rawmappings} -% List of mappings. -% \begin{macrocode} -\newcommand*{\@dtl@rawmappings}{} -% \end{macrocode} -%\end{macro} -%\begin{macro}{\dtl@domappings} +%\begin{macro}{\DTLgmeanforall} %\begin{definition} -% \cs{dtl@domappings}\marg{cmd} +%\cs{DTLgmeanforall}\marg{cmd}\marg{num list} %\end{definition} -% Do all mappings in string given by \meta{cmd}. +% Global version % \begin{macrocode} -\newcommand*{\dtl@domappings}[1]{% -\@for\@dtl@map:=\@dtl@rawmappings\do{% - \expandafter\DTLsubstitute\expandafter#1\@dtl@map -}} +\newcommand*{\DTLgmeanforall}[2]{% +\DTLmeanforall{\@dtl@tmpi}{#2}% +\global\let#1=\@dtl@tmpi +} % \end{macrocode} %\end{macro} % -%\begin{macro}{\DTLsubstitute} +%\begin{macro}{\DTLvarianceforall} %\begin{definition} -%\cs{DTLsubstitute}\marg{cmd}\marg{original}\marg{replacement} +%\cs{DTLvarianceforall}\marg{cmd}\marg{num list} %\end{definition} -% Substitutes first occurence of \meta{original} with -% \marg{replacement} within the string given by \meta{cmd} +% 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{\DTLsubstitute}[3]{% -\expandafter\DTLsplitstring\expandafter - {#1}{#2}{\@dtl@beforepart}{\@dtl@afterpart}% +\newcommand*{\DTLvarianceforall}[2]{% +\def\@dtl@mean{0}% +\def\@dtl@n{0}% +\let\@dtl@decvals=\@empty +\@for\dtl@thisval:=#2\do{% + \DTLconverttodecimal{\dtl@thisval}{\@dtl@num}% + \ifx\@dtl@decvals\@empty + \let\@dtl@decvals=\@dtl@num + \else + \expandafter\toks@\expandafter{\@dtl@decvals}% + \edef\@dtl@decvals{\the\toks@,\@dtl@num}% + \fi + \FPadd{\@dtl@mean}{\@dtl@mean}{\@dtl@num}% + \FPadd{\@dtl@n}{\@dtl@n}{1}% +}% +\FPdiv{\@dtl@mean}{\@dtl@mean}{\@dtl@n}% +\def\@dtl@var{0}% +\@for\@dtl@num:=\@dtl@decvals\do{% + \FPsub{\@dtl@diff}{\@dtl@num}{\@dtl@mean}% + \FPmul{\@dtl@diff}{\@dtl@diff}{\@dtl@diff}% + \FPadd{\@dtl@var}{\@dtl@var}{\@dtl@diff}% +}% +\FPdiv{\@dtl@var}{\@dtl@var}{\@dtl@n}% \ifx\@dtl@replaced\@empty + \DTLdecimaltolocale{\@dtl@var}{#1}% \else - \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}% + \DTLdecimaltocurrency{\@dtl@var}{#1}% \fi } % \end{macrocode} %\end{macro} -%\begin{macro}{\DTLsplitstring} +%\begin{macro}{\DTLgvarianceforall} %\begin{definition} -%\cs{DTLsplitstring}\marg{string}\marg{split text}\marg{before -%cmd}\marg{after cmd} +%\cs{DTLgvarianceforall}\marg{cmd}\marg{num list} %\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} +% Global version % \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*{\DTLgvarianceforall}[2]{% +\DTLvarianceforall{\@dtl@tmpi}{#2}% +\global\let#1=\@dtl@tmpi } % \end{macrocode} %\end{macro} % -%\begin{macro}{\DTLsubstituteall} +%\begin{macro}{\DTLsdforall} %\begin{definition} -%\cs{DTLsubstituteall}\marg{cmd}\marg{original}\marg{replacement} +%\cs{DTLsdforall}\marg{cmd}\marg{num list} %\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} +% 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{\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}% +\newcommand*{\DTLsdforall}[2]{% +\def\@dtl@mean{0}% +\def\@dtl@n{0}% +\let\@dtl@decvals=\@empty +\@for\dtl@thisval:=#2\do{% + \DTLconverttodecimal{\dtl@thisval}{\@dtl@num}% + \ifx\@dtl@decvals\@empty + \let\@dtl@decvals=\@dtl@num + \else + \expandafter\toks@\expandafter{\@dtl@decvals}% + \edef\@dtl@decvals{\the\toks@,\@dtl@num}% + \fi + \FPadd{\@dtl@mean}{\@dtl@mean}{\@dtl@num}% + \FPadd{\@dtl@n}{\@dtl@n}{1}% +}% +\FPdiv{\@dtl@mean}{\@dtl@mean}{\@dtl@n}% +\def\@dtl@sd{0}% +\@for\@dtl@num:=\@dtl@decvals\do{% + \FPsub{\@dtl@diff}{\@dtl@num}{\@dtl@mean}% + \FPmul{\@dtl@diff}{\@dtl@diff}{\@dtl@diff}% + \FPadd{\@dtl@sd}{\@dtl@sd}{\@dtl@diff}% +}% +\FPdiv{\@dtl@sd}{\@dtl@sd}{\@dtl@n}% +\FProot{\@dtl@sd}{\@dtl@sd}{2}% +\ifx\@dtl@replaced\@empty + \DTLdecimaltolocale{\@dtl@sd}{#1}% +\else + \DTLdecimaltocurrency{\@dtl@sd}{#1}% +\fi } % \end{macrocode} %\end{macro} -%\begin{macro}{\@dtl@dosubstitute} -% Recursive substitution macro. +%\begin{macro}{\DTLgsdforall} +%\begin{definition} +%\cs{DTLgsdforall}\marg{cmd}\marg{num list} +%\end{definition} +% Global version % \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}% +\newcommand*{\DTLgsdforall}[2]{% +\DTLsdforall{\@dtl@tmpi}{#2}% +\global\let#1=\@dtl@tmpi +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\DTLround} +%\begin{definition} +% \cs{DTLround}\marg{cmd}\marg{num}\marg{num digits} +%\end{definition} +% Sets \meta{cmd} to \meta{num} rounded to \meta{num digits} +% digits after the decimal character. +% \begin{macrocode} +\newcommand*{\DTLround}[3]{% +\DTLconverttodecimal{#2}{\@dtl@numi}% +\FPround{\@dtl@tmp}{\@dtl@numi}{#3}% \ifx\@dtl@replaced\@empty - \let\@dtl@dosubstnext=\@dtl@dosubstitutenoop + \DTLdecimaltolocale{\@dtl@tmp}{#1}% \else - \expandafter\toks@\expandafter{\@dtl@splitsubstr}% - \@dtl@toks{#2}% - \edef\@dtl@splitsubstr{\the\toks@\the\@dtl@toks}% - \let\@dtl@dosubstnext=\@dtl@dosubstitute + \DTLdecimaltocurrency{\@dtl@tmp}{#1}% \fi -\@dtl@dosubstnext{#1}{#2}% } % \end{macrocode} %\end{macro} -%\begin{macro}{\@dtl@dosubstitutenoop} -% Terminates recursive substitution macro. +%\begin{macro}{\DTLground} +% Global version % \begin{macrocode} -\def\@dtl@dosubstitutenoop#1#2{} +\newcommand*{\DTLground}[3]{% +\DTLround{\@dtl@tmpii}{#2}{#3}% +\global\let#1=\@dtl@tmpii +} % \end{macrocode} %\end{macro} % -%\begin{macro}{\DTLifinlist} -%\cs{DTLifinlist}\marg{element}\marg{list}\marg{true part}\marg{false part} -% If \meta{element} is contained in the comma-separated list given -% by \meta{list}, then do \meta{true part} otherwise do false -% part. (Does a one level expansion on \meta{list}) +%\begin{macro}{\DTLtrunc} +%\begin{definition} +% \cs{DTLtrunc}\marg{cmd}\marg{num}\marg{num digits} +%\end{definition} +% Sets \meta{cmd} to \meta{num} truncated to \meta{num digits} +% digits after the decimal character. % \begin{macrocode} -\newcommand*{\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 +\newcommand*{\DTLtrunc}[3]{% +\DTLconverttodecimal{#2}{\@dtl@numi}% +\FPtrunc{\@dtl@tmp}{\@dtl@numi}{#3}% +\ifx\@dtl@replaced\@empty + \DTLdecimaltolocale{\@dtl@tmp}{#1}% +\else + \DTLdecimaltocurrency{\@dtl@tmp}{#1}% +\fi } % \end{macrocode} %\end{macro} -% -% -%\subsection{Currencies} -%\begin{macro}{\@dtl@currencies} -% \cs{@dtl@currencies} stores all known currencies. +%\begin{macro}{\DTLgtrunc} +% Global version % \begin{macrocode} -\newcommand*{\@dtl@currencies}{\$,\pounds} +\newcommand*{\DTLgtrunc}[3]{% +\DTLtrunc{\@dtl@tmpii}{#2}{#3}% +\global\let#1=\@dtl@tmpii +} % \end{macrocode} %\end{macro} -%\begin{macro}{\DTLnewcurrencysymbol} +% +%\begin{macro}{\DTLclip} %\begin{definition} -% \cs{DTLaddcurrency}\marg{symbol} +% \cs{DTLclip}\marg{cmd}\marg{num} %\end{definition} -% Adds \meta{symbol} to the list of known currencies +% Sets \meta{cmd} to \meta{num} with all unnecessary 0's removed. % \begin{macrocode} -\newcommand*{\DTLnewcurrencysymbol}[1]{% -\expandafter\toks@\expandafter{\@dtl@currencies}% -\@dtl@toks{#1}% -\edef\@dtl@currencies{\the\@dtl@toks,\the\toks@}% +\newcommand*{\DTLclip}[2]{% +\DTLconverttodecimal{#2}{\@dtl@numi}% +\FPclip{\@dtl@tmp}{\@dtl@numi}% +\ifx\@dtl@replaced\@empty + \DTLdecimaltolocale{\@dtl@tmp}{#1}% +\else + \DTLdecimaltocurrency{\@dtl@tmp}{#1}% +\fi } % \end{macrocode} %\end{macro} -% If any of the following currency commands have been defined, -% add them to the list: +%\begin{macro}{\DTLgclip} +% Global version % \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*{\DTLgclip}[3]{% +\DTLclip{\@dtl@tmpii}{#2}% +\global\let#1=\@dtl@tmpii } % \end{macrocode} -%\begin{macro}{\@dtl@standardize@currency} -%\begin{definition} -%\cs{@dtl@standardize@currency}\marg{cmd} -%\end{definition} -% Substitutes the first currency symbol found in \meta{cmd} -% with "\$". This is used when testing text to determine -% if it is currency. The original currency symbol is stored -% in \cs{@dtl@org@currency}, so that it can be replaced later. -% If no currency symbol is found, \cs{@dtl@org@currency} will -% be empty. -% \begin{macrocode} -\newcommand{\@dtl@standardize@currency}[1]{% -\def\@dtl@org@currency{}% -\@for\@dtl@thiscurrency:=\@dtl@currencies\do{% - \expandafter\toks@\expandafter{\@dtl@thiscurrency}% - \edef\@dtl@dosubs{\noexpand\DTLsubstitute{\noexpand#1}% - {\the\toks@}{\noexpand\$}}% - \@dtl@dosubs - \ifx\@dtl@replaced\@empty - \else - \let\@dtl@org@currency=\@dtl@replaced - \@endfortrue - \fi -}% -\@endforfalse} -% \end{macrocode} %\end{macro} % -%\begin{macro}{\@dtl@currency} -%\cs{@dtl@currency} is set by \cs{DTLlocaltodecimal} and -%\cs{@dtl@checknumerical}. It is used by \cs{DTLdecimaltocurrency}. -% Set to "\$" by default. +%\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}} % \begin{macrocode} -\newcommand*{\@dtl@currency}{\$} +\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} -%\begin{macro}{\DTLsetdefaultcurrency} -%\cs{DTLsetdefaultcurrency}\marg{symbol} sets the default currency. +% The following substitutes "\protect \nobreakspace {}" with +% a space. (Note that in this case the space following +% "\nobreakspace" forms part of the command.) % \begin{macrocode} -\newcommand*{\DTLsetdefaultcurrency}[1]{% -\renewcommand*{\@dtl@currency}{#1}} +\edef\dtl@construct@subnobrsp{% +\noexpand\def\noexpand\@dtl@subnobrsp##1\noexpand\protect +\expandafter\noexpand\csname nobreakspace \endcsname ##2{% +\noexpand\toks@{##1}% +\noexpand\expandafter\noexpand\@dtl@toks\noexpand\expandafter{% +\noexpand\@dtl@string}% +\noexpand\edef\noexpand\@dtl@string{\noexpand\the\noexpand\@dtl@toks +\noexpand\the\noexpand\toks@}% +\noexpand\def\noexpand\@dtl@tmp{##2}% +\noexpand\ifx\noexpand\@dtl@tmp\noexpand\@nnil + \noexpand\let\noexpand\@dtl@subnobrspnext=\noexpand\relax +\noexpand\else + \noexpand\toks@{ }% + \noexpand\expandafter\noexpand\@dtl@toks\noexpand\expandafter{% + \noexpand\@dtl@string}% + \noexpand\edef\noexpand\@dtl@string{\noexpand\the\noexpand\@dtl@toks + \noexpand\the\noexpand\toks@}% + \noexpand\let\noexpand\@dtl@subnobrspnext=\noexpand\@dtl@subnobrsp +\noexpand\fi +\noexpand\@dtl@subnobrspnext +}% +\noexpand\def\noexpand\dtl@subnobrsp##1##2{% +\noexpand\def\noexpand\@dtl@string{}% +\noexpand\@dtl@subnobrsp ##1\noexpand\protect\expandafter\noexpand +\csname nobreakspace \endcsname \noexpand\@nil +\noexpand\let##2=\noexpand\@dtl@string +}} +\dtl@construct@subnobrsp % \end{macrocode} -%\end{macro} % -%\begin{macro}{\dtl@ifsingle} +%\begin{macro}{\DTLstoreinitials} %\begin{definition} -%\cs{dtl@ifsingle}\marg{arg}\marg{true part}\marg{false part} +%\cs{DTLstoreinitials}\marg{string}\marg{cmd} %\end{definition} -% If there is only one object in \meta{arg} (without expansion) -% do \meta{true part}, otherwise do false part. +% 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{\dtl@ifsingle}[3]{% -\def\@dtl@arg{#1}% -\ifx\@dtl@arg\@empty - #3% -\else - \@dtl@ifsingle#1\@nil{#2}{#3}% -\fi +\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@ifsingle} +%\begin{macro}{\dtl@initials} % \begin{macrocode} -\def\@dtl@ifsingle#1#2\@nil#3#4{% -\def\dtl@sg@arg{#2}% -\ifx\dtl@sg@arg\@empty - #3% +\def\dtl@initials#1#2 #3{% +\dtl@ifsingle{#1}{% +\ifcat\noexpand#1\relax\relax + \def\@dtl@donextinitials{\@dtl@initials#2 {#3}}% \else - #4% + \def\@dtl@donextinitials{\@dtl@initials#1#2 {#3}}% \fi +}{% + \def\@dtl@donextinitials{\@dtl@initials{#1}#2 {#3}}% +}% +\@dtl@donextinitials } % \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}{\@dtl@initials} % \begin{macrocode} -\newcommand*{\dtlshowdb}[1]{% -\expandafter\showthe\csname dtldb@#1\endcsname} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\dtlshowdbkeys} -%\begin{definition} -%\cs{dtlshowdbkeys}\marg{db name} -%\end{definition} -% Shows the key list for the named database. -%\changes{2.0}{2009 February 27}{updated to use new database structure} -% \begin{macrocode} -\newcommand*{\dtlshowdbkeys}[1]{% -\expandafter\showthe\csname dtlkeys@#1\endcsname} +\def\@dtl@initials#1#2 #3{% +\dtl@initialshyphen#2-{}\dtl@endhyp +\expandafter\@dtl@toks\expandafter{\dtl@initialscmd}% +\toks@{#1}% +\ifx\dtl@inithyphen\@empty +\else + \edef\dtl@initialscmd{\the\@dtl@toks\the\toks@}% + \expandafter\@dtl@toks\expandafter{\dtl@initialscmd}% + \expandafter\toks@\expandafter{\dtl@inithyphen}% +\fi +\def\dtl@tmp{#3}% +\ifx\@nnil\dtl@tmp + \edef\dtl@initialscmd{\the\@dtl@toks\the\toks@\DTLafterinitials}% + \let\dtl@initialsnext=\@gobble +\else + \edef\dtl@initialscmd{\the\@dtl@toks\the\toks@\DTLbetweeninitials}% + \let\dtl@initialsnext=\dtl@initials +\fi +\dtl@initialsnext{#3}} % \end{macrocode} %\end{macro} -% -%\begin{macro}{\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} +%\begin{macro}{\dtl@initialshyphen} % \begin{macrocode} -\newcommand*{\dtlshowtype}[2]{% - \DTLgetdatatype{\@dtl@type}{#1}{#2}\show\@dtl@type +\def\dtl@initialshyphen#1-#2#3\dtl@endhyp{% +\def\dtl@inithyphen{#2}% +\ifx\dtl@inithyphen\@empty +\else + \edef\dtl@inithyphen{% + \DTLafterinitialbeforehyphen\DTLinitialhyphen#2}% +\fi } % \end{macrocode} %\end{macro} -%\iffalse -% \begin{macrocode} -% -% \end{macrocode} -%\fi -%\iffalse -% \begin{macrocode} -%<*datapie.sty> -% \end{macrocode} -%\fi -%\section{datapie.sty} -% Declare package: -% \begin{macrocode} -\NeedsTeXFormat{LaTeX2e} -\ProvidesPackage{datapie}[2007/02/27 v2.0 (NLCT)] -% \end{macrocode} -% Require \sty{xkeyval} package -% \begin{macrocode} -\RequirePackage{xkeyval} -% \end{macrocode} -%\begin{macro}{\ifDTLcolorpiechart} -% The conditional \cs{ifDTLcolorpiechart} is to determine -% whether to use colour or grey scale. -% \begin{macrocode} -\newif\ifDTLcolorpiechart -\DTLcolorpiecharttrue -% \end{macrocode} -%\end{macro} -% Package options to change the conditional: -% \begin{macrocode} -\DeclareOption{color}{\DTLcolorpiecharttrue} -\DeclareOption{gray}{\DTLcolorpiechartfalse} -% \end{macrocode} -%\begin{macro}{\ifDTLrotateinner} -% Define boolean keys to govern label rotations. -% \begin{macrocode} -\define@boolkey{datapie}[DTL]{rotateinner}[true]{} -% \end{macrocode} -%\end{macro} -%\begin{macro}{\ifDTLrotateouter} -% \begin{macrocode} -\define@boolkey{datapie}[DTL]{rotateouter}[true]{} -% \end{macrocode} -%\end{macro} -% Set defaults: -% \begin{macrocode} -\DTLrotateinnerfalse -\DTLrotateouterfalse -% \end{macrocode} -% Package options to change \cs{DTLrotateinner} -% \begin{macrocode} -\DeclareOption{rotateinner}{\DTLrotateinnertrue} -\DeclareOption{norotateinner}{\DTLrotateinnerfalse} -% \end{macrocode} -% Package options to change \cs{DTLrotateouter} -% \begin{macrocode} -\DeclareOption{rotateouter}{\DTLrotateoutertrue} -\DeclareOption{norotateouter}{\DTLrotateouterfalse} -% \end{macrocode} -% Process options: -% \begin{macrocode} -\ProcessOptions -% \end{macrocode} -% Required packages: -% \begin{macrocode} -\RequirePackage{datatool} -\RequirePackage{tikz} -% \end{macrocode} -% Define some variables that govern the appearance of the pie -% chart. -% -%\begin{macro}{\DTLradius} -% The radius of the pie chart is given by \cs{DTLradius}. +%\begin{macro}{\DTLafterinitials} +% Defines what to do after the final initial. % \begin{macrocode} -\newlength\DTLradius -\DTLradius=2cm +\newcommand*{\DTLafterinitials}{.} % \end{macrocode} %\end{macro} -%\begin{macro}{\DTLinnerratio} -% The inner label offset ratio is given by \cs{DTLinnerratio} +%\begin{macro}{\DTLbetweeninitials} +% Defines what to do between initials. % \begin{macrocode} -\newcommand*{\DTLinnerratio}{0.5} +\newcommand*{\DTLbetweeninitials}{.} % \end{macrocode} %\end{macro} -%\begin{macro}{\DTLouterratio} -% The outer label offset ratio is given by \cs{DTLouterratio}. +%\begin{macro}{\DTLafterinitialbeforehyphen} +% Defines what to do before a hyphen. % \begin{macrocode} -\newcommand*{\DTLouterratio}{1.25} +\newcommand*{\DTLafterinitialbeforehyphen}{.} % \end{macrocode} %\end{macro} -%\begin{macro}{\DTLcutawayratio} -% The cutaway offset ratio is given by \cs{DTLcutawayratio}. +%\begin{macro}{\DTLinitialhyphen} +%Defines what to do at the hyphen +%\changes{1.01}{2007 Aug 17}{new} % \begin{macrocode} -\newcommand*\DTLcutawayratio{0.2} +\newcommand*{\DTLinitialhyphen}{-} % \end{macrocode} %\end{macro} -%\begin{macro}{\DTLstartangle} -% The angle of the first segment is given by \cs{DTLstartangle}. +% +%\begin{macro}{\DTLifAllUpperCase} +%\begin{definition} +%\cs{DTLifAllUpperCase}\marg{string}\marg{true part}\marg{false part} +%\end{definition} +% If \meta{string} only contains uppercase characters do \meta{true +%part}, otherwise do \meta{false part}. % \begin{macrocode} -\newcommand*{\DTLstartangle}{0} +\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@inneroffset} +%\begin{macro}{\dtl@testifalluppercase} % \begin{macrocode} -\newlength\dtl@inneroffset -\dtl@inneroffset=\DTLinnerratio\DTLradius +\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@outeroffset} +%\begin{macro}{\dtl@test@ifalluppercase} % \begin{macrocode} -\newlength\dtl@outeroffset -\dtl@outeroffset=\DTLouterratio\DTLradius +\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}{\dtl@cutawayoffset} +%\begin{macro}{\DTLifAllLowerCase} +%\begin{definition} +%\cs{DTLifAllLowerCase}\marg{string}\marg{true part}\marg{false part} +%\end{definition} +% If \meta{string} only contains lowercase characters do \meta{true +%part}, otherwise do \meta{false part}. % \begin{macrocode} -\newlength\dtl@cutawayoffset -\dtl@cutawayoffset=\DTLcutawayratio\DTLradius +\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@piecutaways} -% \cs{dtl@piecutaways} is a comma separated list of segments that -% need to be cut away from the pie chart. +%\begin{macro}{\dtl@testifalllowercase} % \begin{macrocode} -\newcommand*{\dtl@piecutaways}{} -% \end{macrocode} -%\end{macro} -%\begin{macro}{\dtl@innerlabel} -% \cs{dtl@innerlabel} specifies the label to appear inside -% the segment. By default this is the variable used to create -% the pie chart. -% \begin{macrocode} -\def\dtl@innerlabel{\DTLpievariable}% +\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@outerlabel} +%\begin{macro}{\dtl@test@ifalllowercase} % \begin{macrocode} -\def\dtl@outerlabel{}% +\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} -% \counterfmt{DTLpieroundvar} is a counter governing the number of digits -% to round to when using \cs{FPround}. +% +%\begin{macro}{\DTLsubstitute} +%\begin{definition} +%\cs{DTLsubstitute}\marg{cmd}\marg{original}\marg{replacement} +%\end{definition} +% Substitutes first occurence of \meta{original} with +% \marg{replacement} within the string given by \meta{cmd} % \begin{macrocode} -\newcounter{DTLpieroundvar} -\setcounter{DTLpieroundvar}{1} +\newcommand{\DTLsubstitute}[3]{% +\expandafter\DTLsplitstring\expandafter + {#1}{#2}{\@dtl@beforepart}{\@dtl@afterpart}% +\ifx\@dtl@replaced\@empty +\else + \def#1{}% + \expandafter\@dtl@toks\expandafter{\@dtl@beforepart}% + \expandafter\toks@\expandafter{#1}% + \protected@edef#1{\the\toks@\the\@dtl@toks#3}% + \expandafter\@dtl@toks\expandafter{\@dtl@afterpart}% + \expandafter\toks@\expandafter{#1}% + \edef#1{\the\toks@\the\@dtl@toks}% +\fi +} % \end{macrocode} -% -%\begin{macro}{\DTLdisplayinnerlabel} +%\end{macro} +%\begin{macro}{\DTLsplitstring} %\begin{definition} -%\cs{DTLdisplayinnerlabel}\marg{label} +%\cs{DTLsplitstring}\marg{string}\marg{split text}\marg{before +%cmd}\marg{after cmd} %\end{definition} -% This is used to format the inner label. This just does the -% label by default. +% 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*{\DTLdisplayinnerlabel}[1]{#1} +\newcommand*{\DTLsplitstring}[4]{% +\def\dtl@splitstr##1#2##2\@nil{% +\def#3{##1}% +\def#4{##2}% +\ifx#4\@empty + \let\@dtl@replaced=\@empty +\else + \def\@dtl@replaced{#2}% + \dtl@split@str##2\@nil +\fi +}% +\def\dtl@split@str##1#2\@nil{% +\def#4{##1}}% +\dtl@splitstr#1#2\@nil +} % \end{macrocode} %\end{macro} % -%\begin{macro}{\DTLdisplayouterlabel} +%\begin{macro}{\DTLsubstituteall} %\begin{definition} -%\cs{DTLdisplayouterlabel}\marg{label} +%\cs{DTLsubstituteall}\marg{cmd}\marg{original}\marg{replacement} %\end{definition} -% This is used to format the outer label. This just does the -% label by default. +% Substitutes all occurences of \meta{original} with +% \marg{replacement} within the string given by \meta{cmd} +%\changes{1.01}{2007 Aug 17}{fixed bug caused when certain commands +% occur in the string} % \begin{macrocode} -\newcommand*{\DTLdisplayouterlabel}[1]{#1} +\newcommand{\DTLsubstituteall}[3]{% +\def\@dtl@splitsubstr{}% +\let\@dtl@afterpart=#1\relax +\@dtl@dosubstitute{#2}{#3}% +\expandafter\toks@\expandafter{\@dtl@splitsubstr}% +\expandafter\@dtl@toks\expandafter{\@dtl@afterpart}% +\edef#1{\the\toks@\the\@dtl@toks}% +} % \end{macrocode} %\end{macro} -% -%\begin{macro}{\DTLpiepercent} -%\cs{DTLpiepercent} -% returns the percentage value of the current segment. +%\begin{macro}{\@dtl@dosubstitute} +% Recursive substitution macro. % \begin{macrocode} -\newcommand*{\DTLpiepercent}{% -\ifnum\dtlforeachlevel=0\relax - \PackageError{datapie}{Can't use - \string\DTLpiepercent\space outside - \string\DTLpiechart}{}% +\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 - \csname dtl@piepercent@\romannumeral\@dtl@seg\endcsname -\fi} + \expandafter\toks@\expandafter{\@dtl@splitsubstr}% + \@dtl@toks{#2}% + \edef\@dtl@splitsubstr{\the\toks@\the\@dtl@toks}% + \let\@dtl@dosubstnext=\@dtl@dosubstitute +\fi +\@dtl@dosubstnext{#1}{#2}% +} % \end{macrocode} %\end{macro} -% -%\begin{macro}{\DTLpieatbegintikz} -% \cs{DTLpieatbegintikz} specifies any commands -% to apply at the start of the \env{tikzpicture} environment. -% By default it does nothing. +%\begin{macro}{\@dtl@dosubstitutenoop} +% Terminates recursive substitution macro. % \begin{macrocode} -\newcommand*{\DTLpieatbegintikz}{} +\def\@dtl@dosubstitutenoop#1#2{} % \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. +%\subsection{Currencies} +%\begin{macro}{\@dtl@currencies} +% \cs{@dtl@currencies} stores all known currencies. % \begin{macrocode} -\newcommand*{\DTLpieatendtikz}{} +\newcommand*{\@dtl@currencies}{\$,\pounds} % \end{macrocode} %\end{macro} -% -%\begin{macro}{\DTLsetpiesegmentcolor} +%\begin{macro}{\DTLnewcurrencysymbol} %\begin{definition} -% \cs{DTLsetpiesegmentcolor}\marg{n}\marg{color} +% \cs{DTLaddcurrency}\marg{symbol} %\end{definition} -% Assign colour name \meta{color} to the \meta{n}th segment. +% Adds \meta{symbol} to the list of known currencies % \begin{macrocode} -\newcommand*{\DTLsetpiesegmentcolor}[2]{% -\expandafter\def\csname dtlpie@segcol\romannumeral#1\endcsname{#2}% +\newcommand*{\DTLnewcurrencysymbol}[1]{% +\expandafter\toks@\expandafter{\@dtl@currencies}% +\@dtl@toks{#1}% +\edef\@dtl@currencies{\the\@dtl@toks,\the\toks@}% } % \end{macrocode} %\end{macro} -% -%\begin{macro}{\DTLgetpiesegmentcolor} +% 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{DTLgetpiesegmentcolor}\marg{n} +%\cs{@dtl@standardize@currency}\marg{cmd} %\end{definition} -% Get the colour specification for segment \meta{n} +% 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*{\DTLgetpiesegmentcolor}[1]{% -\csname dtlpie@segcol\romannumeral#1\endcsname} +\newcommand{\@dtl@standardize@currency}[1]{% +\def\@dtl@org@currency{}% +\@for\@dtl@thiscurrency:=\@dtl@currencies\do{% + \expandafter\toks@\expandafter{\@dtl@thiscurrency}% + \edef\@dtl@dosubs{\noexpand\DTLsubstitute{\noexpand#1}% + {\the\toks@}{\noexpand\$}}% + \@dtl@dosubs + \ifx\@dtl@replaced\@empty + \else + \let\@dtl@org@currency=\@dtl@replaced + \@endfortrue + \fi +}% +\@endforfalse} % \end{macrocode} %\end{macro} % -%\begin{macro}{\DTLdopiesegmentcolor} -%\begin{definition} -%\cs{DTLdopiesegmentcolor}\marg{n} -%\end{definition} -% Set the colour to that for segment \meta{n} +%\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*{\DTLdopiesegmentcolor}[1]{% -\expandafter\color\expandafter -{\csname dtlpie@segcol\romannumeral#1\endcsname}} +\newcommand*{\@dtl@currency}{\$} % \end{macrocode} %\end{macro} -%\begin{macro}{\DTLdocurrentpiesegmentcolor} -%\cs{DTLdocurrentpiesegmentcolor} -% sets the colour to that of the current segment. +%\begin{macro}{\DTLsetdefaultcurrency} +%\cs{DTLsetdefaultcurrency}\marg{symbol} sets the default currency. % \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} +\newcommand*{\DTLsetdefaultcurrency}[1]{% +\renewcommand*{\@dtl@currency}{#1}} % \end{macrocode} %\end{macro} % -%\begin{macro}{\DTLpieoutlinecolor} -%\cs{DTLpieoutlinecolor} specifies what colour to draw the -% outline. +%\begin{macro}{\dtl@ifsingle} +%\begin{definition} +%\cs{dtl@ifsingle}\marg{arg}\marg{true part}\marg{false part} +%\end{definition} +% If there is only one object in \meta{arg} (without expansion) +% do \meta{true part}, otherwise do false part. % \begin{macrocode} -\newcommand*{\DTLpieoutlinecolor}{black} +\newcommand{\dtl@ifsingle}[3]{% +\def\@dtl@arg{#1}% +\ifx\@dtl@arg\@empty + #3% +\else + \@dtl@ifsingle#1\@nil{#2}{#3}% +\fi +} % \end{macrocode} %\end{macro} -% -%\begin{macro}{\DTLpieoutlinewidth} -%\cs{DTLpieoutlinewidth} specifies the line width of the outline: -% Outline is only drawn if the linewidth is greater than 0pt. +%\begin{macro}{\@dtl@ifsingle} % \begin{macrocode} -\newlength\DTLpieoutlinewidth -\DTLpieoutlinewidth=0pt +\def\@dtl@ifsingle#1#2\@nil#3#4{% +\def\dtl@sg@arg{#2}% +\ifx\dtl@sg@arg\@empty + #3% +\else + #4% +\fi +} % \end{macrocode} %\end{macro} % -% Set the default colours. If there are more than eight segments, -% more colours will need to be defined. +%\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{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 +\newcommand*{\dtlshowdb}[1]{% +\expandafter\showthe\csname dtldb@#1\endcsname} % \end{macrocode} -% Define keys for \cs{DTLpiechart} optional argument. -% Set the starting angle of the first segment. +%\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} % \begin{macrocode} -\define@key{datapie}{start}{\def\DTLstartangle{#1}} +\newcommand*{\dtlshowdbkeys}[1]{% +\expandafter\showthe\csname dtlkeys@#1\endcsname} % \end{macrocode} -% Set the radius of the pie chart (must be set prior to -% inneroffset and outeroffset keys.) +%\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} % \begin{macrocode} -\define@key{datapie}{radius}{\DTLradius=#1\relax -\dtl@inneroffset=\DTLinnerratio\DTLradius -\dtl@outeroffset=\DTLouterratio\DTLradius -\dtl@cutawayoffset=\DTLcutawayratio\DTLradius} +\newcommand*{\dtlshowtype}[2]{% + \DTLgetdatatype{\@dtl@type}{#1}{#2}\show\@dtl@type +} % \end{macrocode} -% Set the inner ratio. +%\end{macro} +%\iffalse % \begin{macrocode} -\define@key{datapie}{innerratio}{% -\def\DTLinnerratio{#1}% -\dtl@inneroffset=\DTLinnerratio\DTLradius} +% % \end{macrocode} -% Set the outer ratio +%\fi +%\iffalse % \begin{macrocode} -\define@key{datapie}{outerratio}{% -\def\DTLouterratio{#1}% -\dtl@outeroffset=\DTLouterratio\DTLradius} +%<*datapie.sty> % \end{macrocode} -% The cutaway offset ratio +%\fi +%\section{datapie.sty} +% Declare package: % \begin{macrocode} -\define@key{datapie}{cutawayratio}{% -\def\DTLcutawayratio{#1}% -\dtl@cutawayoffset=\DTLcutawayratio\DTLradius} +\NeedsTeXFormat{LaTeX2e} +\ProvidesPackage{datapie}[2009/10/22 v2.01 (NLCT)] % \end{macrocode} -% Set the inner offset as an absolute value (not dependent -% on the radius.) +% Require \sty{xkeyval} package % \begin{macrocode} -\define@key{datapie}{inneroffset}{% -\dtl@inneroffset=#1} +\RequirePackage{xkeyval} % \end{macrocode} -% Set the outer offset as an absolute value (not dependent -% on the radius.) +%\begin{macro}{\ifDTLcolorpiechart} +% The conditional \cs{ifDTLcolorpiechart} is to determine +% whether to use colour or grey scale. % \begin{macrocode} -\define@key{datapie}{outeroffset}{% -\dtl@outeroffset=#1} +\newif\ifDTLcolorpiechart +\DTLcolorpiecharttrue % \end{macrocode} -% Set the cutaway offset as an absolute value (not dependent -% on the radius.) +%\end{macro} +% Package options to change the conditional: % \begin{macrocode} -\define@key{datapie}{cutawayoffset}{% -\dtl@cutawayoffset=#1} +\DeclareOption{color}{\DTLcolorpiecharttrue} +\DeclareOption{gray}{\DTLcolorpiechartfalse} % \end{macrocode} -% List of cut away segments. +%\begin{macro}{\ifDTLrotateinner} +% Define boolean keys to govern label rotations. % \begin{macrocode} -\define@key{datapie}{cutaway}{% -\renewcommand*{\dtl@piecutaways}{#1}} +\define@boolkey{datapie}[DTL]{rotateinner}[true]{} % \end{macrocode} -% Variable used to create the pie chart. (Must be a control -% sequence.) +%\end{macro} +%\begin{macro}{\ifDTLrotateouter} % \begin{macrocode} -\define@key{datapie}{variable}{% -\def\DTLpievariable{#1}} +\define@boolkey{datapie}[DTL]{rotateouter}[true]{} % \end{macrocode} -% Inner label +%\end{macro} +% Set defaults: % \begin{macrocode} -\define@key{datapie}{innerlabel}{% -\def\dtl@innerlabel{#1}} +\DTLrotateinnerfalse +\DTLrotateouterfalse % \end{macrocode} -% Outer label +% Package options to change \cs{DTLrotateinner} % \begin{macrocode} -\define@key{datapie}{outerlabel}{% -\def\dtl@outerlabel{#1}} +\DeclareOption{rotateinner}{\DTLrotateinnertrue} +\DeclareOption{norotateinner}{\DTLrotateinnerfalse} % \end{macrocode} -% -%\begin{macro}{\DTLpiechart} -%\begin{definition} -% \cs{DTLpiechart}\oarg{conditions}\marg{option list}\marg{db name}\marg{assign list} -%\end{definition} -% Make a pie chart from data given in data base \meta{db name}, -% where \meta{assign list} is a comma-separated list of -% \meta{cmd}\texttt{=}\meta{key} pairs. \meta{option list} must -% include \texttt{variable}\texttt{=}\meta{cmd}, where \meta{cmd} -% is included in \meta{assign list}. The optional argument -% \meta{conditions} is the same as that for \cs{DTLforeach}. +% Package options to change \cs{DTLrotateouter} % \begin{macrocode} -\newcommand*{\DTLpiechart}[4][\boolean{true}]{% -{\let\DTLpievariable=\relax -\setkeys{datapie}{#2}% -\ifx\DTLpievariable\relax - \PackageError{datapie}{\string\DTLpiechart\space missing variable}{}% -\else +\DeclareOption{rotateouter}{\DTLrotateoutertrue} +\DeclareOption{norotateouter}{\DTLrotateouterfalse} % \end{macrocode} -% Compute the total. -%\changes{1.01}{2007 Aug 17}{uses \cs{@sDTLforeach} instead of -%\cs{DTLforeach}} +% Process options: % \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}% -}% +\ProcessOptions % \end{macrocode} -% Compute the angles +% Required packages: % \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 -}% +\RequirePackage{datatool} +\RequirePackage{tikz} % \end{macrocode} -% Compute the offsets for each cut away segment +% Define some variables that govern the appearance of the pie +% chart. +% +%\begin{macro}{\DTLradius} +% The radius of the pie chart is given by \cs{DTLradius}. % \begin{macrocode} -\@for\dtl@row:=\dtl@piecutaways\do{% -\expandafter\@dtl@set@off\dtl@row-\relax -}% +\newlength\DTLradius +\DTLradius=2cm % \end{macrocode} -% Set the starting angle +%\end{macro} +%\begin{macro}{\DTLinnerratio} +% The inner label offset ratio is given by \cs{DTLinnerratio} % \begin{macrocode} -\let\dtl@start=\DTLstartangle +\newcommand*{\DTLinnerratio}{0.5} % \end{macrocode} -% Do the pie chart +%\end{macro} +%\begin{macro}{\DTLouterratio} +% The outer label offset ratio is given by \cs{DTLouterratio}. % \begin{macrocode} -\begin{tikzpicture} -\DTLpieatbegintikz -\@sDTLforeach[#1]{#3}{#4}{% +\newcommand*{\DTLouterratio}{1.25} % \end{macrocode} -% Store the segment number in \cs{@dtl@seg} +%\end{macro} +%\begin{macro}{\DTLcutawayratio} +% The cutaway offset ratio is given by \cs{DTLcutawayratio}. % \begin{macrocode} -\expandafter\@dtl@seg\expandafter= -\csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname% +\newcommand*\DTLcutawayratio{0.2} % \end{macrocode} -% Set the start angle. +%\end{macro} +%\begin{macro}{\DTLstartangle} +% The angle of the first segment is given by \cs{DTLstartangle}. % \begin{macrocode} -\edef\dtl@start{\csname dtl@sang@\romannumeral\@dtl@seg\endcsname}% +\newcommand*{\DTLstartangle}{0} % \end{macrocode} -% Set the extent +%\end{macro} +%\begin{macro}{\dtl@inneroffset} % \begin{macrocode} -\edef\dtl@extent{\csname dtl@angle@\romannumeral\@dtl@seg\endcsname}% +\newlength\dtl@inneroffset +\dtl@inneroffset=\DTLinnerratio\DTLradius % \end{macrocode} -% Compute the end angle +%\end{macro} +%\begin{macro}{\dtl@outeroffset} % \begin{macrocode} -\FPadd{\dtl@endangle}{\dtl@start}{\dtl@extent}% +\newlength\dtl@outeroffset +\dtl@outeroffset=\DTLouterratio\DTLradius % \end{macrocode} -% Compute the shift. +%\end{macro} +%\begin{macro}{\dtl@cutawayoffset} % \begin{macrocode} -\edef\dtl@angle{\csname dtl@cut@angle@\romannumeral\@dtl@seg\endcsname}% -\let\dtl@old=\dtl@angle -\dtl@truncatedecimal\dtl@angle -\ifnum\dtl@angle>180 - \FPsub{\dtl@angle}{\dtl@old}{360}% - \dtl@truncatedecimal\dtl@angle -\fi -\edef\dtl@cutlen{% -\csname dtl@cut@len@\romannumeral\@dtl@seg\endcsname} -\edef\@dtl@shift{(\dtl@angle:\dtl@cutlen)}% +\newlength\dtl@cutawayoffset +\dtl@cutawayoffset=\DTLcutawayratio\DTLradius % \end{macrocode} -% Compute the mid way angle. +%\end{macro} +% +%\begin{macro}{\dtl@piecutaways} +% \cs{dtl@piecutaways} is a comma separated list of segments that +% need to be cut away from the pie chart. % \begin{macrocode} -\FPmul{\dtl@angle}{\dtl@extent}{0.5}% -\FPadd{\dtl@midangle}{\dtl@angle}{\dtl@start}% +\newcommand*{\dtl@piecutaways}{} % \end{macrocode} -% Draw the segment. +%\end{macro} +%\begin{macro}{\dtl@innerlabel} +% \cs{dtl@innerlabel} specifies the label to appear inside +% the segment. By default this is the variable used to create +% the pie chart. % \begin{macrocode} -\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@innerlabel{\DTLpievariable}% % \end{macrocode} -% Draw the outline if required: +%\end{macro} +%\begin{macro}{\dtl@outerlabel} % \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 +\def\dtl@outerlabel{}% % \end{macrocode} -% Convert decimal to an integer +%\end{macro} +%\begin{counter}{DTLpieroundvar} +% \ctrfmt{DTLpieroundvar} is a counter governing the number of digits +% to round to when using \cs{FPround}. % \begin{macrocode} -\dtl@truncatedecimal\dtl@midangle +\newcounter{DTLpieroundvar} +\setcounter{DTLpieroundvar}{1} % \end{macrocode} -% Determine whether to rotate inner labels +%\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} -\ifDTLrotateinner +\newcommand*{\DTLdisplayinnerlabel}[1]{#1} % \end{macrocode} -% If the mid way angle is between 90 and 270, the text will look -% upside-down, so adjust accordingly. +%\end{macro} +% +%\begin{macro}{\DTLdisplayouterlabel} +%\begin{definition} +%\cs{DTLdisplayouterlabel}\marg{label} +%\end{definition} +% This is used to format the outer label. This just does the +% label by default. % \begin{macrocode} -\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}% -}% +\newcommand*{\DTLdisplayouterlabel}[1]{#1} % \end{macrocode} -% Don't rotate inner labels +%\end{macro} +% +%\begin{macro}{\DTLpiepercent} +%\cs{DTLpiepercent} +% returns the percentage value of the current segment. % \begin{macrocode} +\newcommand*{\DTLpiepercent}{% +\ifnum\dtlforeachlevel=0\relax + \PackageError{datapie}{Can't use + \string\DTLpiepercent\space outside + \string\DTLpiechart}{}% \else - \edef\dtl@innernodeopt{anchor=center}% -\fi -% \end{macrocode} -% Determine whether to rotate outer labels -% \begin{macrocode} -\ifDTLrotateouter -% \end{macrocode} -% If the mid way angle is between 90 and 270, the text will look -% upside-down, so adjust accordingly. -% \begin{macrocode} -\ifthenelse{\(\dtl@midangle > 90 \and \dtl@midangle < 270\) -\TE@or \dtl@midangle < -90}{% - \FPsub{\dtl@labelangle}{\dtl@midangle}{180}% - \dtl@truncatedecimal\dtl@labelangle - \edef\dtl@outernodeopt{anchor=east,rotate=\dtl@labelangle}% -}{% - \edef\dtl@outernodeopt{anchor=west,rotate=\dtl@midangle}% -}% + \csname dtl@piepercent@\romannumeral\@dtl@seg\endcsname +\fi} % \end{macrocode} -% Don't rotate outer labels +%\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} -\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 +\newcommand*{\DTLpieatbegintikz}{} % \end{macrocode} -% Draw inner and outer labels +%\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} -\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 -}} +\newcommand*{\DTLpieatendtikz}{} % \end{macrocode} %\end{macro} % -%\begin{macro}{\dtl@computeangles} +%\begin{macro}{\DTLsetpiesegmentcolor} %\begin{definition} -%\cs{dtl@computeangles}\marg{n}\marg{variable} +% \cs{DTLsetpiesegmentcolor}\marg{n}\marg{color} %\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). +% Assign colour name \meta{color} to the \meta{n}th segment. % \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}% +\newcommand*{\DTLsetpiesegmentcolor}[2]{% +\expandafter\def\csname dtlpie@segcol\romannumeral#1\endcsname{#2}% } % \end{macrocode} %\end{macro} % -% Set the offset angles. -%\begin{macro}{\@dtl@set@off} +%\begin{macro}{\DTLgetpiesegmentcolor} +%\begin{definition} +%\cs{DTLgetpiesegmentcolor}\marg{n} +%\end{definition} +% Get the colour specification for segment \meta{n} % \begin{macrocode} -\def\@dtl@set@off#1-#2\relax{% -\ifthenelse{\equal{#2}{}}{% -\@@dtl@set@off{#1}}{% -\@@dtl@set@offr#1-#2\relax}% -} +\newcommand*{\DTLgetpiesegmentcolor}[1]{% +\csname dtlpie@segcol\romannumeral#1\endcsname} % \end{macrocode} %\end{macro} -% Set offset for individual segment: -%\begin{macro}{\@@dtl@set@off} +% +%\begin{macro}{\DTLdopiesegmentcolor} +%\begin{definition} +%\cs{DTLdopiesegmentcolor}\marg{n} +%\end{definition} +% Set the colour to that for segment \meta{n} % \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} -} +\newcommand*{\DTLdopiesegmentcolor}[1]{% +\expandafter\color\expandafter +{\csname dtlpie@segcol\romannumeral#1\endcsname}} % \end{macrocode} %\end{macro} -% Define count register to keep track of segments -%\begin{macro}{\@dtl@seg} +%\begin{macro}{\DTLdocurrentpiesegmentcolor} +%\cs{DTLdocurrentpiesegmentcolor} +% sets the colour to that of the current segment. % \begin{macrocode} -\newcount\@dtl@seg +\newcommand*{\DTLdocurrentpiesegmentcolor}{% +\ifnum\dtlforeachlevel=0\relax + \PackageError{datapie}{Can't use + \string\DTLdocurrentpiesegmentcolor\space outside + \string\DTLpiechart}{}% +\else + \expandafter\DTLdopiesegmentcolor\expandafter{% + \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname}% +\fi} % \end{macrocode} %\end{macro} -%\begin{macro}{\@@dtl@setoffr} -% Set offset for a range of segments +% +%\begin{macro}{\DTLpieoutlinecolor} +%\cs{DTLpieoutlinecolor} specifies what colour to draw the +% outline. % \begin{macrocode} -\def\@@dtl@set@offr#1-#2-\relax{% -\ifnum#1>#2\relax - \PackageError{datapie}{Segment ranges must go in ascending order}{% -Try #2-#1 instead of #1-#2}% -\else - \def\dtl@angle{0}% - \@dtl@seg=#1\relax - \whiledo{\not\(\@dtl@seg > #2\)}{% - \let\dtl@old=\dtl@angle - \edef\dtl@segang{\csname dtl@angle@\romannumeral\@dtl@seg\endcsname}% - \FPadd{\dtl@angle}{\dtl@old}{\dtl@segang}% - \advance\@dtl@seg by 1\relax - }% - \let\dtl@old=\dtl@angle - \FPmul{\dtl@angle}{\dtl@old}{0.5}% - \edef\dtl@sang{\csname dtl@sang@\romannumeral#1\endcsname}% - \let\dtl@old=\dtl@angle - \FPadd{\dtl@angle}{\dtl@old}{\dtl@sang}% - \@dtl@seg=#1\relax - \whiledo{\not\(\@dtl@seg > #2\)}{% - \expandafter - \let\csname dtl@cut@angle@\romannumeral\@dtl@seg\endcsname - =\dtl@angle - \expandafter - \edef\csname dtl@cut@len@\romannumeral\@dtl@seg\endcsname{% - \the\dtl@cutawayoffset} - \advance\@dtl@seg by 1\relax - }% -\fi -} +\newcommand*{\DTLpieoutlinecolor}{black} % \end{macrocode} %\end{macro} -%\iffalse +% +%\begin{macro}{\DTLpieoutlinewidth} +%\cs{DTLpieoutlinewidth} specifies the line width of the outline: +% Outline is only drawn if the linewidth is greater than 0pt. % \begin{macrocode} -% +\newlength\DTLpieoutlinewidth +\DTLpieoutlinewidth=0pt % \end{macrocode} -%\fi -%\iffalse +%\end{macro} +% +% Set the default colours. If there are more than eight segments, +% more colours will need to be defined. % \begin{macrocode} -%<*dataplot.sty> +\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} -%\fi -%\section{dataplot.sty} -% Declare package: +% Define keys for \cs{DTLpiechart} optional argument. +% Set the starting angle of the first segment. % \begin{macrocode} -\NeedsTeXFormat{LaTeX2e} -\ProvidesPackage{dataplot}[2009/02/27 v2.0 (NLCT)] +\define@key{datapie}{start}{\def\DTLstartangle{#1}} % \end{macrocode} -% Required packages +% Set the radius of the pie chart (must be set prior to +% inneroffset and outeroffset keys.) % \begin{macrocode} -\RequirePackage{xkeyval} -\RequirePackage{tikz} -\RequirePackage{datatool} +\define@key{datapie}{radius}{\DTLradius=#1\relax +\dtl@inneroffset=\DTLinnerratio\DTLradius +\dtl@outeroffset=\DTLouterratio\DTLradius +\dtl@cutawayoffset=\DTLcutawayratio\DTLradius} % \end{macrocode} -% Load TikZ plot libraries +% Set the inner ratio. % \begin{macrocode} -\usetikzlibrary{plotmarks} -\usetikzlibrary{plothandlers} +\define@key{datapie}{innerratio}{% +\def\DTLinnerratio{#1}% +\dtl@inneroffset=\DTLinnerratio\DTLradius} % \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}} +% Set the outer ratio % \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}}}} +\define@key{datapie}{outerratio}{% +\def\DTLouterratio{#1}% +\dtl@outeroffset=\DTLouterratio\DTLradius} % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\DTLplotmarks} -%\cs{DTLplotmarks} contains a list of plot marks used by -%\cs{DTLplot}. +% The cutaway offset ratio % \begin{macrocode} -\newcommand*{\DTLplotmarks}{% - \pgfuseplotmark{o},% - \pgfuseplotmark{x},% - \pgfuseplotmark{+},% - \pgfuseplotmark{square},% - \pgfuseplotmark{triangle},% - \pgfuseplotmark{diamond},% - \pgfuseplotmark{pentagon},% - \pgfuseplotmark{asterisk},% - \pgfuseplotmark{star}% -} +\define@key{datapie}{cutawayratio}{% +\def\DTLcutawayratio{#1}% +\dtl@cutawayoffset=\DTLcutawayratio\DTLradius} % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\DTLplotmarkcolors} -%\cs{DTLplotmarkcolors} contains a list of the plot mark colours. +% Set the inner offset as an absolute value (not dependent +% on the radius.) % \begin{macrocode} -\newcommand*{\DTLplotmarkcolors}{% - red,% - green,% - blue,% - yellow,% - magenta,% - cyan,% - orange,% - black,% - gray} +\define@key{datapie}{inneroffset}{% +\dtl@inneroffset=#1} % \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} +% Set the outer offset as an absolute value (not dependent +% on the radius.) % \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},% -} +\define@key{datapie}{outeroffset}{% +\dtl@outeroffset=#1} % \end{macrocode} -%\end{macro} -%\begin{macro}{\DTLplotlinecolors} -%\cs{DTLplotlinecolors} contains a list of the plot line colours. +% Set the cutaway offset as an absolute value (not dependent +% on the radius.) % \begin{macrocode} -\newcommand*{\DTLplotlinecolors}{% - red,% - green,% - blue,% - yellow,% - magenta,% - cyan,% - orange,% - black,% - gray} +\define@key{datapie}{cutawayoffset}{% +\dtl@cutawayoffset=#1} % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\DTLplotwidth} -% The default total plot width is stored in the length -% \cs{dtlplotwidth} +% List of cut away segments. % \begin{macrocode} -\newlength\DTLplotwidth -\setlength\DTLplotwidth{4in} +\define@key{datapie}{cutaway}{% +\renewcommand*{\dtl@piecutaways}{#1}} % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\DTLplotheight} -% The default total plot height is stored in the length -% \cs{dtlplotheight} +% Variable used to create the pie chart. (Must be a control +% sequence.) % \begin{macrocode} -\newlength\DTLplotheight -\setlength\DTLplotheight{4in} +\define@key{datapie}{variable}{% +\def\DTLpievariable{#1}} % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\DTLticklength} -% The length of the tick marks is given by \cs{DTLticklength} +% Inner label % \begin{macrocode} -\newlength\DTLticklength -\setlength\DTLticklength{5pt} +\define@key{datapie}{innerlabel}{% +\def\dtl@innerlabel{#1}} % \end{macrocode} -%\end{macro} -%\begin{macro}{\DTLminorticklength} -% The length of the minor tick marks is given by -% \cs{DTLminorticklength}. +% Outer label % \begin{macrocode} -\newlength\DTLminorticklength -\setlength\DTLminorticklength{2pt} +\define@key{datapie}{outerlabel}{% +\def\dtl@outerlabel{#1}} % \end{macrocode} -%\end{macro} -%\begin{macro}{\DTLticklabeloffset} -% The offset from the axis to the tick label is given by -% \cs{DTLticklabeloffset}. -% \begin{macrocode} -\newlength\DTLticklabeloffset -\setlength\DTLticklabeloffset{8pt} -% \end{macrocode} -%\end{macro} -%\begin{macro}{\dtl@xticlabelheight} -% \cs{dtl@xticlabelheight} is used to store the height of -% the $x$ tick labels. -% \begin{macrocode} -\newlength\dtl@xticlabelheight -% \end{macrocode} -%\end{macro} -%\begin{macro}{\dtl@yticlabelwidth} -% \cs{dtl@yticlabelwidth} is used to store the width of -% the $y$ tick labels. +% +%\begin{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} -\newlength\dtl@yticlabelwidth +\newcommand*{\DTLpiechart}[4][\boolean{true}]{% +{\let\DTLpievariable=\relax +\setkeys{datapie}{#2}% +\ifx\DTLpievariable\relax + \PackageError{datapie}{\string\DTLpiechart\space missing variable}{}% +\else % \end{macrocode} -%\end{macro} -%\begin{macro}{\DTLmintickgap} -% \cs{DTLmintickgap} stores the suggested minimum distance between -% tick marks where the gap is not specified. +% Compute the total. +%\changes{1.01}{2007 Aug 17}{uses \cs{@sDTLforeach} instead of +%\cs{DTLforeach}} % \begin{macrocode} -\newlength\DTLmintickgap -\setlength\DTLmintickgap{20pt} +\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} -%\end{macro} -%\begin{macro}{\DTLminminortickgap} -% The suggested minimum distance between minor tick marks where the -% gap is not specified is given by \cs{DTLminminortickgap}. +% Compute the angles % \begin{macrocode} -\newlength\DTLminminortickgap -\setlength\DTLminminortickgap{5pt} +\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} -%\end{macro} -% Round $x$ tick labels to the number of digits given by -% the counter \counterfmt{DTLplotroundXvar}. +% Compute the offsets for each cut away segment % \begin{macrocode} -\newcounter{DTLplotroundXvar} -\setcounter{DTLplotroundXvar}{2} +\@for\dtl@row:=\dtl@piecutaways\do{% +\expandafter\@dtl@set@off\dtl@row-\relax +}% % \end{macrocode} -% Round $y$ tick labels to the number of digits given by -% the counter \counterfmt{DTLplotroundYvar}. +% Set the starting angle % \begin{macrocode} -\newcounter{DTLplotroundYvar} -\setcounter{DTLplotroundYvar}{2} +\let\dtl@start=\DTLstartangle % \end{macrocode} -%\begin{macro}{\ifDTLxaxis} -% The conditional \cs {ifDTLxaxis} is used to determine whether or -% not to display the $x$ axis. +% Do the pie chart % \begin{macrocode} -\newif\ifDTLxaxis -\DTLxaxistrue +\begin{tikzpicture} +\DTLpieatbegintikz +\@sDTLforeach[#1]{#3}{#4}{% % \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. +% Store the segment number in \cs{@dtl@seg} % \begin{macrocode} -\newcommand*{\DTLXAxisStyle}{-} +\expandafter\@dtl@seg\expandafter= +\csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname% % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\ifDTLyaxis} -% The conditional \cs{ifDTLyaxis} is used to determine whether or -% not to display the $y$ axis +% Set the start angle. % \begin{macrocode} -\newif\ifDTLyaxis -\DTLyaxistrue +\edef\dtl@start{\csname dtl@sang@\romannumeral\@dtl@seg\endcsname}% % \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. +% Set the extent % \begin{macrocode} -\newcommand*{\DTLYAxisStyle}{-} +\edef\dtl@extent{\csname dtl@angle@\romannumeral\@dtl@seg\endcsname}% % \end{macrocode} -%\end{macro} -%\begin{macro}{\DTLmajorgridstyle} -% The style of the major grid lines is given by -% \cs{DTLmajorgridstyle}. +% Compute the end angle % \begin{macrocode} -\newcommand*{\DTLmajorgridstyle}{color=gray,-} +\FPadd{\dtl@endangle}{\dtl@start}{\dtl@extent}% % \end{macrocode} -%\end{macro} -%\begin{macro}{\DTLminorgridstyle} -% The style of the minor grid lines is given by -% \cs{DTLminorgridstyle}. +% Compute the shift. % \begin{macrocode} -\newcommand*{\DTLminorgridstyle}{color=gray,loosely dotted} +\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} -%\end{macro} -% -%\begin{macro}{\ifDTLxticsin} -% The conditional \cs{ifDTLxticsin} is used to determine whether -% the $x$ tics should point in or out. +% Compute the mid way angle. % \begin{macrocode} -\newif\ifDTLxticsin -\DTLxticsintrue +\FPmul{\dtl@angle}{\dtl@extent}{0.5}% +\FPadd{\dtl@midangle}{\dtl@angle}{\dtl@start}% % \end{macrocode} -%\end{macro} -%\begin{macro}{\ifDTLyticsin} -% The conditional \cs{ifDTLyticsin} is used to determine whether -% the $y$ tics should point in or out. +% Draw the segment. % \begin{macrocode} -\newif\ifDTLyticsin -\DTLyticsintrue +\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} -%\end{macro} -%\begin{macro}{\dtl@legendsetting} -% The legend setting is stored in the count register -% \cs{dtl@legendsetting}. +% Draw the outline if required: % \begin{macrocode} -\newcount\dtl@legendsetting +\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} -%\end{macro} -%\begin{macro}{\DTLlegendxoffset} -% The gap between the border of plot and legend is given by the -% lengths \cs{DTLlegendxoffset} and \cs{DTLlegendyoffset} +% Convert decimal to an integer % \begin{macrocode} -\newlength\DTLlegendxoffset -\setlength\DTLlegendxoffset{10pt} +\dtl@truncatedecimal\dtl@midangle % \end{macrocode} -%\end{macro} -%\begin{macro}{\DTLlegendyoffset} +% Determine whether to rotate inner labels % \begin{macrocode} -\newlength\DTLlegendyoffset -\setlength\DTLlegendyoffset{10pt} +\ifDTLrotateinner % \end{macrocode} -%\end{macro} -%\begin{macro}{\DTLformatlegend} -%\begin{definition} -%\cs{DTLformatlegend}\marg{legend} -%\end{definition} -% This formats the legend. +% If the mid way angle is between 90 and 270, the text will look +% upside-down, so adjust accordingly. % \begin{macrocode} -\newcommand*{\DTLformatlegend}[1]{% -\setlength{\fboxrule}{1.1pt}% -\fcolorbox{black}{white}{#1}} +\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} -%\end{macro} -%\begin{macro}{\ifDTLshowmarkers} -% The conditional \cs{ifDTLshowmarkers} is used to specify -% whether or not to use markers. +% Don't rotate inner labels % \begin{macrocode} -\newif\ifDTLshowmarkers -\DTLshowmarkerstrue +\else + \edef\dtl@innernodeopt{anchor=center}% +\fi % \end{macrocode} -%\end{macro} -%\begin{macro}{\ifDTLshowlines} -% The conditional \cs{ifDTLshowlines} is used to specify -% whether or not to use lines. +% Determine whether to rotate outer labels % \begin{macrocode} -\newif\ifDTLshowlines -\DTLshowlinesfalse +\ifDTLrotateouter % \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). +% If the mid way angle is between 90 and 270, the text will look +% upside-down, so adjust accordingly. % \begin{macrocode} -\newcommand*{\DTLplotatbegintikz}{} +\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} -%\end{macro} -%\begin{macro}{\DTLplotatendtikz} -% \cs{DTLplotatendtikz} is a hook to insert stuff at the end -% of the \env{tikzpicture} environment. +% Don't rotate outer labels % \begin{macrocode} -\newcommand*{\DTLplotatendtikz}{} -% \end{macrocode} -%\end{macro} -% -% Plot settings. The database key for the $x$ value is -% given by the "x" setting: -% \begin{macrocode} -\define@key{dataplot}{x}{% -\def\dtl@xkey{#1}} +\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} -% The database key for the $y$ value is given by the "y" setting: +% Draw inner and outer labels % \begin{macrocode} -\define@key{dataplot}{y}{% -\def\dtl@ykey{#1}} +\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} -% 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}{\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} -\define@key{dataplot}{markcolors}{% -\def\DTLplotmarkcolors{#1}} +\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} -% The list of plot line colours is given by the "linecolors" setting. -% (This should be a comma separated list of colour names.) +%\end{macro} +% +% Set the offset angles. +%\begin{macro}{\@dtl@set@off} % \begin{macrocode} -\define@key{dataplot}{linecolors}{% -\def\DTLplotlinecolors{#1}} +\def\@dtl@set@off#1-#2\relax{% +\ifthenelse{\equal{#2}{}}{% +\@@dtl@set@off{#1}}{% +\@@dtl@set@offr#1-#2\relax}% +} % \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} +% Set offset for individual segment: +%\begin{macro}{\@@dtl@set@off} % \begin{macrocode} -\define@key{dataplot}{colors}{% -\def\DTLplotmarkcolors{#1}% -\def\DTLplotlinecolors{#1}} +\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} -% 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} +% Define count register to keep track of segments +%\begin{macro}{\@dtl@seg} % \begin{macrocode} -\define@key{dataplot}{marks}{% -\def\DTLplotmarks{#1}} +\newcount\@dtl@seg % \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}{\@@dtl@setoffr} +% Set offset for a range of segments % \begin{macrocode} -\define@key{dataplot}{lines}{% -\def\DTLplotlines{#1}} +\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} -% The total width of the plot is given by the "width" setting. +%\end{macro} +%\iffalse % \begin{macrocode} -\define@key{dataplot}{width}{% -\setlength\DTLplotwidth{#1}} +% % \end{macrocode} -% The total height of the plot is given by the "height" setting. +%\fi +%\iffalse % \begin{macrocode} -\define@key{dataplot}{height}{% -\setlength\DTLplotheight{#1}} +%<*dataplot.sty> % \end{macrocode} -% Determine whether to show lines, markers or both +%\fi +%\section{dataplot.sty} +% Declare package: % \begin{macrocode} -\define@choicekey{dataplot}{style}[\val\nr]{both,lines,markers}{% -\ifcase\nr\relax - \DTLshowlinestrue - \DTLshowmarkerstrue -\or - \DTLshowlinestrue - \DTLshowmarkersfalse -\or - \DTLshowmarkerstrue - \DTLshowlinesfalse -\fi} +\NeedsTeXFormat{LaTeX2e} +\ProvidesPackage{dataplot}[2009/10/22 v2.01 (NLCT)] % \end{macrocode} -% Determine whether or not to display the axes +% Required packages % \begin{macrocode} -\define@choicekey{dataplot}{axes}[\val\nr]{both,x,y,none}[both]{% -\ifcase\nr\relax - % both - \DTLxaxistrue - \DTLxticstrue - \DTLyaxistrue - \DTLyticstrue -\or % x - \DTLxaxistrue - \DTLxticstrue - \DTLyaxisfalse - \DTLyticsfalse -\or % y - \DTLxaxisfalse - \DTLxticsfalse - \DTLyaxistrue - \DTLyticstrue -\or % none - \DTLxaxisfalse - \DTLxticsfalse - \DTLyaxisfalse - \DTLyticsfalse -\fi -} +\RequirePackage{xkeyval} +\RequirePackage{tikz} +\RequirePackage{datatool} % \end{macrocode} -%\begin{macro}{\ifDTLbox} -% Enclose plot in a box +% Load TikZ plot libraries % \begin{macrocode} -\define@boolkey{dataplot}[DTL]{box}[true]{} -\DTLboxfalse +\usetikzlibrary{plotmarks} +\usetikzlibrary{plothandlers} % \end{macrocode} -%\end{macro} -%\begin{macro}{\ifDTLxticstrue} -% Condition to determine whether to show the $x$ tick marks +% +%\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} -\define@boolkey{dataplot}[DTL]{xtics}[true]{} -\DTLxticstrue +\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}{\ifDTLyticstrue} -% Condition to determine whether to show the $y$ tick marks -% \begin{macrocode} -\define@boolkey{dataplot}[DTL]{ytics}[true]{} -\DTLyticstrue +% +%\begin{macro}{\DTLplotmarks} +%\cs{DTLplotmarks} contains a list of plot marks used by +%\cs{DTLplot}. +% \begin{macrocode} +\newcommand*{\DTLplotmarks}{% + \pgfuseplotmark{o},% + \pgfuseplotmark{x},% + \pgfuseplotmark{+},% + \pgfuseplotmark{square},% + \pgfuseplotmark{triangle},% + \pgfuseplotmark{diamond},% + \pgfuseplotmark{pentagon},% + \pgfuseplotmark{asterisk},% + \pgfuseplotmark{star}% +} % \end{macrocode} %\end{macro} -%\begin{macro}{\ifDTLxminortics} -% Condition to determine whether to show the $x$ minor tick marks +% +%\begin{macro}{\DTLplotmarkcolors} +%\cs{DTLplotmarkcolors} contains a list of the plot mark colours. % \begin{macrocode} -\define@boolkey{dataplot}[DTL]{xminortics}[true]{% -\ifDTLxminortics \DTLxticstrue\fi} -\DTLxminorticsfalse +\newcommand*{\DTLplotmarkcolors}{% + red,% + green,% + blue,% + yellow,% + magenta,% + cyan,% + orange,% + black,% + gray} % \end{macrocode} %\end{macro} -%\begin{macro}{\ifDTLyminortics} -% Condition to determine whether to show the $y$ minor tick marks +%\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} -\define@boolkey{dataplot}[DTL]{yminortics}[true]{% -\ifDTLyminortics \DTLyticstrue\fi} -\DTLyminorticsfalse +\newcommand*{\DTLplotlines}{% + \pgfsetdash{}{0pt},% solid line + \pgfsetdash{{10pt}{5pt}}{0pt},% + \pgfsetdash{{5pt}{5pt}}{0pt},% + \pgfsetdash{{1pt}{5pt}}{0pt},% + \pgfsetdash{{5pt}{5pt}{1pt}{5pt}}{0pt},% + \pgfsetdash{{1pt}{3pt}}{0pt},% +} % \end{macrocode} %\end{macro} -%\begin{macro}{\ifDTLgrid} -% Determine whether to draw the grid +%\begin{macro}{\DTLplotlinecolors} +%\cs{DTLplotlinecolors} contains a list of the plot line colours. % \begin{macrocode} -\define@boolkey{dataplot}[DTL]{grid}[true]{} +\newcommand*{\DTLplotlinecolors}{% + red,% + green,% + blue,% + yellow,% + magenta,% + cyan,% + orange,% + black,% + gray} % \end{macrocode} %\end{macro} -% Determine whether the $x$ tick marks should point -% in or out: +% +%\begin{macro}{\DTLplotwidth} +% The default total plot width is stored in the length +% \cs{dtlplotwidth} % \begin{macrocode} -\define@choicekey{dataplot}{xticdir}[\val\nr]{in,out}{% -\ifcase\nr\relax - \DTLxticsintrue -\or - \DTLxticsinfalse -\fi -} +\newlength\DTLplotwidth +\setlength\DTLplotwidth{4in} % \end{macrocode} -% Determine whether the $y$ tick marks should point -% in or out: +%\end{macro} +% +%\begin{macro}{\DTLplotheight} +% The default total plot height is stored in the length +% \cs{dtlplotheight} % \begin{macrocode} -\define@choicekey{dataplot}{yticdir}[\val\nr]{in,out}{% -\ifcase\nr\relax - \DTLyticsintrue -\or - \DTLyticsinfalse -\fi -} +\newlength\DTLplotheight +\setlength\DTLplotheight{4in} % \end{macrocode} -% Determine whether the $x$ and $y$ tick marks should point -% in or out; +%\end{macro} +% +%\begin{macro}{\DTLticklength} +% The length of the tick marks is given by \cs{DTLticklength} % \begin{macrocode} -\define@choicekey{dataplot}{ticdir}[\val\nr]{in,out}{% -\ifcase\nr\relax - \DTLxticsintrue - \DTLyticsintrue -\or - \DTLxticsinfalse - \DTLyticsinfalse -\fi -} +\newlength\DTLticklength +\setlength\DTLticklength{5pt} % \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.) +%\end{macro} +%\begin{macro}{\DTLminorticklength} +% The length of the minor tick marks is given by +% \cs{DTLminorticklength}. % \begin{macrocode} -\define@key{dataplot}{bounds}{% -\def\dtl@bounds{#1}} -\let\dtl@bounds=\relax +\newlength\DTLminorticklength +\setlength\DTLminorticklength{2pt} % \end{macrocode} -% Set only the lower $x$ bound +%\end{macro} +%\begin{macro}{\DTLticklabeloffset} +% The offset from the axis to the tick label is given by +% \cs{DTLticklabeloffset}. % \begin{macrocode} -\define@key{dataplot}{minx}{% -\def\dtl@minx{#1}} -\let\dtl@minx=\relax +\newlength\DTLticklabeloffset +\setlength\DTLticklabeloffset{8pt} % \end{macrocode} -% Set only the upper $x$ bound: +%\end{macro} +%\begin{macro}{\dtl@xticlabelheight} +% \cs{dtl@xticlabelheight} is used to store the height of +% the $x$ tick labels. % \begin{macrocode} -\define@key{dataplot}{maxx}{% -\def\dtl@maxx{#1}} -\let\dtl@maxx=\relax +\newlength\dtl@xticlabelheight % \end{macrocode} -% Set only the lower $y$ bound: +%\end{macro} +%\begin{macro}{\dtl@yticlabelwidth} +% \cs{dtl@yticlabelwidth} is used to store the width of +% the $y$ tick labels. % \begin{macrocode} -\define@key{dataplot}{miny}{% -\def\dtl@miny{#1}} -\let\dtl@miny=\relax +\newlength\dtl@yticlabelwidth % \end{macrocode} -% Set only the upper $y$ bound: +%\end{macro} +%\begin{macro}{\DTLmintickgap} +% \cs{DTLmintickgap} stores the suggested minimum distance between +% tick marks where the gap is not specified. % \begin{macrocode} -\define@key{dataplot}{maxy}{% -\def\dtl@maxy{#1}} -\let\dtl@maxy=\relax +\newlength\DTLmintickgap +\setlength\DTLmintickgap{20pt} % \end{macrocode} -% Define list of points for $x$ ticks. (Must be a comma separated -% list of decimal numbers.) +%\end{macro} +%\begin{macro}{\DTLminminortickgap} +% The suggested minimum distance between minor tick marks where the +% gap is not specified is given by \cs{DTLminminortickgap}. % \begin{macrocode} -\define@key{dataplot}{xticpoints}{% -\def\dtl@xticlist{#1}\DTLxticstrue\DTLxaxistrue} -\let\dtl@xticlist=\relax +\newlength\DTLminminortickgap +\setlength\DTLminminortickgap{5pt} % \end{macrocode} -% Define list of points for $y$ ticks. (Must be a comma separated -% list of decimal numbers.) +%\end{macro} +%\begin{counter}{DTLplotroundvar} +% Round $x$ tick labels to the number of digits given by +% the counter \ctrfmt{DTLplotroundXvar}. % \begin{macrocode} -\define@key{dataplot}{yticpoints}{% -\def\dtl@yticlist{#1}\DTLyticstrue\DTLyaxistrue} -\let\dtl@yticlist=\relax +\newcounter{DTLplotroundXvar} +\setcounter{DTLplotroundXvar}{2} % \end{macrocode} -% Define a the gap between $x$ tick marks (xticpoints overrides -% xticgap) +%\end{counter} +%\begin{counter}{DTLplotroundYvar} +% Round $y$ tick labels to the number of digits given by +% the counter \ctrfmt{DTLplotroundYvar}. % \begin{macrocode} -\define@key{dataplot}{xticgap}{\def\dtl@xticgap{#1}% -\DTLxticstrue\DTLxaxistrue} -\let\dtl@xticgap=\relax +\newcounter{DTLplotroundYvar} +\setcounter{DTLplotroundYvar}{2} % \end{macrocode} -% Define a the gap between $y$ tick marks (yticpoints overrides -% yticgap) +%\end{counter} +%\begin{macro}{\ifDTLxaxis} +% The conditional \cs {ifDTLxaxis} is used to determine whether or +% not to display the $x$ axis. % \begin{macrocode} -\define@key{dataplot}{yticgap}{\def\dtl@yticgap{#1}% -\DTLyticstrue\DTLyaxistrue} -\let\dtl@yticgap=\relax +\newif\ifDTLxaxis +\DTLxaxistrue % \end{macrocode} -% Define comma separated list of labels for $x$ ticks. +%\end{macro} +%\begin{macro}{\DTLXAxisStyle} +% The style of the $x$ axis is given by \cs{DTLXAxisStyle}. This +% is just a solid line by default. % \begin{macrocode} -\define@key{dataplot}{xticlabels}{% -\def\dtl@xticlabels{#1}\DTLxticstrue\DTLxaxistrue} -\let\dtl@xticlabels=\relax +\newcommand*{\DTLXAxisStyle}{-} % \end{macrocode} -% Define comma separated list of labels for $y$ ticks. +%\end{macro} +% +%\begin{macro}{\ifDTLyaxis} +% The conditional \cs{ifDTLyaxis} is used to determine whether or +% not to display the $y$ axis % \begin{macrocode} -\define@key{dataplot}{yticlabels}{% -\def\dtl@yticlabels{#1}\DTLyticstrue\DTLyaxistrue} -\let\dtl@yticlabels=\relax +\newif\ifDTLyaxis +\DTLyaxistrue % \end{macrocode} -% Define $x$ axis label +%\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} -\define@key{dataplot}{xlabel}{% -\def\dtl@xlabel{#1}} -\let\dtl@xlabel=\relax +\newcommand*{\DTLYAxisStyle}{-} % \end{macrocode} -% Define $y$ axis label +%\end{macro} +%\begin{macro}{\DTLmajorgridstyle} +% The style of the major grid lines is given by +% \cs{DTLmajorgridstyle}. % \begin{macrocode} -\define@key{dataplot}{ylabel}{% -\def\dtl@ylabel{#1}} -\let\dtl@ylabel=\relax +\newcommand*{\DTLmajorgridstyle}{color=gray,-} % \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}. +%\end{macro} +%\begin{macro}{\DTLminorgridstyle} +% The style of the minor grid lines is given by +% \cs{DTLminorgridstyle}. % \begin{macrocode} -\define@choicekey{dataplot}{legend}[\val\nr]{none,north,northeast,% -east,southeast,south,southwest,west,northwest}[northeast]{% -\dtl@legendsetting=\nr\relax -} -% \end{macrocode} -% Legend labels (comma separated list). If omitted, the database -% name is used. -% \begin{macrocode} -\define@key{dataplot}{legendlabels}{\def\dtl@legendlabels{#1}} +\newcommand*{\DTLminorgridstyle}{color=gray,loosely dotted} % \end{macrocode} +%\end{macro} % -%\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{macro}{\ifDTLxticsin} +% The conditional \cs{ifDTLxticsin} is used to determine whether +% the $x$ tics should point in or out. % \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 +\newif\ifDTLxticsin +\DTLxticsintrue % \end{macrocode} -% If user didn't specified bounds, -% compute the maximum and minimum $x$ and $y$ values over -% all the databases listed. +%\end{macro} +%\begin{macro}{\ifDTLyticsin} +% The conditional \cs{ifDTLyticsin} is used to determine whether +% the $y$ tics should point in or out. % \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 +\newif\ifDTLyticsin +\DTLyticsintrue % \end{macrocode} -% Otherwise extract information from \cs{dtl@bounds} +%\end{macro} +%\begin{macro}{\dtl@legendsetting} +% The legend setting is stored in the count register +% \cs{dtl@legendsetting}. % \begin{macrocode} - \else - \expandafter\dtl@getbounds\dtl@bounds\@nil - \fi +\newcount\dtl@legendsetting % \end{macrocode} -% Determine scaling factors. +%\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} - \@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}% +\newlength\DTLlegendxoffset +\setlength\DTLlegendxoffset{10pt} % \end{macrocode} -% If x tics specified, construct a list of x tic points if not -% already specified. +%\end{macro} +%\begin{macro}{\DTLlegendyoffset} % \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 +\newlength\DTLlegendyoffset +\setlength\DTLlegendyoffset{10pt} % \end{macrocode} -% Construct a list of $x$ minor tick points if required +%\end{macro} +%\begin{macro}{\DTLformatlegend} +%\begin{definition} +%\cs{DTLformatlegend}\marg{legend} +%\end{definition} +% This formats the legend. % \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 +\newcommand*{\DTLformatlegend}[1]{% +\setlength{\fboxrule}{1.1pt}% +\fcolorbox{black}{white}{#1}} % \end{macrocode} -% Determine the height of the $x$ tick labels. +%\end{macro} +%\begin{macro}{\ifDTLshowmarkers} +% The conditional \cs{ifDTLshowmarkers} is used to specify +% whether or not to use markers. % \begin{macrocode} - \ifx\dtl@xticlabels\relax - \settoheight{\dtl@xticlabelheight}{\dtl@xticlist}% - \else - \settoheight{\dtl@xticlabelheight}{\dtl@xticlabels}% - \fi - \else - \setlength{\dtl@xticlabelheight}{0pt}% - \fi +\newif\ifDTLshowmarkers +\DTLshowmarkerstrue % \end{macrocode} -% If y tics specified, construct a list of y tic points if not -% already specified. +%\end{macro} +%\begin{macro}{\ifDTLshowlines} +% The conditional \cs{ifDTLshowlines} is used to specify +% whether or not to use lines. % \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 +\newif\ifDTLshowlines +\DTLshowlinesfalse % \end{macrocode} -% Construct a list of $y$ minor tick points if required +%\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} - \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 +\newcommand*{\DTLplotatbegintikz}{} % \end{macrocode} -% Determine the width of the $y$ tick labels. +%\end{macro} +%\begin{macro}{\DTLplotatendtikz} +% \cs{DTLplotatendtikz} is a hook to insert stuff at the end +% of the \env{tikzpicture} environment. % \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 +\newcommand*{\DTLplotatendtikz}{} % \end{macrocode} -% Start the picture. +%\end{macro} +% +% Plot settings. The database key for the $x$ value is +% given by the "x" setting: % \begin{macrocode} - \begin{tikzpicture} +\define@key{dataplot}{x}{% +\def\dtl@xkey{#1}} % \end{macrocode} -% Set the $x$ and $y$ unit vectors. +% The database key for the $y$ value is given by the "y" setting: % \begin{macrocode} - \pgfsetxvec{\pgfpoint{\dtl@unit@x sp}{0pt}}% - \pgfsetyvec{\pgfpoint{0pt}{\dtl@unit@y sp}}% +\define@key{dataplot}{y}{% +\def\dtl@ykey{#1}} % \end{macrocode} -% Add any extra information the user requires +% The list of plot mark colours is given by the "markcolors" setting. +% (This should be a comma separated list of colour names.) % \begin{macrocode} - \DTLplotatbegintikz +\define@key{dataplot}{markcolors}{% +\def\DTLplotmarkcolors{#1}} % \end{macrocode} -% Determine whether to put a box around the plot +% The list of plot line colours is given by the "linecolors" setting. +% (This should be a comma separated list of colour names.) % \begin{macrocode} - \ifDTLbox - \draw (\DTLminX,\DTLminY) -- (\DTLmaxX,\DTLminY) -- - (\DTLmaxX,\DTLmaxY) -- (\DTLminX,\DTLmaxY) -- - cycle; - \else +\define@key{dataplot}{linecolors}{% +\def\DTLplotlinecolors{#1}} % \end{macrocode} -% Plot $x$ axis if required. +% 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} - \ifDTLxaxis - \expandafter\draw\expandafter[\DTLXAxisStyle] - (\DTLminX,\DTLminY) -- (\DTLmaxX,\DTLminY); - \fi +\define@key{dataplot}{colors}{% +\def\DTLplotmarkcolors{#1}% +\def\DTLplotlinecolors{#1}} % \end{macrocode} -% Plot $y$ axis if required. +% 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} - \ifDTLyaxis - \expandafter\draw\expandafter[\DTLYAxisStyle] - (\DTLminX,\DTLminY) -- (\DTLminX,\DTLmaxY); - \fi - \fi +\define@key{dataplot}{marks}{% +\def\DTLplotmarks{#1}} % \end{macrocode} -% Plot grid if required +% 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} - \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 +\define@key{dataplot}{lines}{% +\def\DTLplotlines{#1}} % \end{macrocode} -% Plot $x$ tics if required. +% The total width of the plot is given by the "width" setting. % \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}% +\define@key{dataplot}{width}{% +\setlength\DTLplotwidth{#1}} % \end{macrocode} -% Plot the tick labels +% The total height of the plot is given by the "height" setting. % \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 +\define@key{dataplot}{height}{% +\setlength\DTLplotheight{#1}} % \end{macrocode} -% Plot $x$ label if required. +% Determine whether to show lines, markers or both % \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 +\define@choicekey{dataplot}{style}[\val\nr]{both,lines,markers}{% +\ifcase\nr\relax + \DTLshowlinestrue + \DTLshowmarkerstrue +\or + \DTLshowlinestrue + \DTLshowmarkersfalse +\or + \DTLshowmarkerstrue + \DTLshowlinesfalse +\fi} % \end{macrocode} -% Plot the $x$ minor ticks if required +% Determine whether or not to display the axes % \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 +\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} -% Plot $y$ tics if required. +%\begin{macro}{\ifDTLbox} +% Enclose plot in a box % \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} +\define@boolkey{dataplot}[DTL]{box}[true]{} +\DTLboxfalse % \end{macrocode} -% Plot the $y$ tick labels if required +%\end{macro} +%\begin{macro}{\ifDTLxticstrue} +% Condition to determine whether to show the $x$ tick marks % \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 +\define@boolkey{dataplot}[DTL]{xtics}[true]{} +\DTLxticstrue % \end{macrocode} -% Plot $y$ label if required. +%\end{macro} +%\begin{macro}{\ifDTLyticstrue} +% Condition to determine whether to show the $y$ tick marks % \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 +\define@boolkey{dataplot}[DTL]{ytics}[true]{} +\DTLyticstrue % \end{macrocode} -% Plot the $y$ minor ticks if required +%\end{macro} +%\begin{macro}{\ifDTLxminortics} +% Condition to determine whether to show the $x$ minor tick marks % \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 +\define@boolkey{dataplot}[DTL]{xminortics}[true]{% +\ifDTLxminortics \DTLxticstrue\fi} +\DTLxminorticsfalse % \end{macrocode} -% Iterate through each database +%\end{macro} +%\begin{macro}{\ifDTLyminortics} +% Condition to determine whether to show the $y$ minor tick marks % \begin{macrocode} - \@for\dtl@thisdb:=#2\do{% +\define@boolkey{dataplot}[DTL]{yminortics}[true]{% +\ifDTLyminortics \DTLyticstrue\fi} +\DTLyminorticsfalse % \end{macrocode} -% Get the current plot mark colour. +%\end{macro} +%\begin{macro}{\ifDTLgrid} +% Determine whether to draw the grid % \begin{macrocode} - \ifx\dtl@plotmarkcolorlist\@empty - \let\dtl@plotmarkcolorlist=\DTLplotmarkcolors - \fi - \dtl@chopfirst\dtl@plotmarkcolorlist\dtl@thisplotmarkcolor - \dtl@remainder - \let\dtl@plotmarkcolorlist=\dtl@remainder +\define@boolkey{dataplot}[DTL]{grid}[true]{} % \end{macrocode} -% Get the current plot mark, and store in \cs{dtl@mark} +%\end{macro} +% Determine whether the $x$ tick marks should point +% in or out: % \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 +\define@choicekey{dataplot}{xticdir}[\val\nr]{in,out}{% +\ifcase\nr\relax + \DTLxticsintrue +\or + \DTLxticsinfalse +\fi +} % \end{macrocode} -% Get the current plot line colour. +% Determine whether the $y$ tick marks should point +% in or out: % \begin{macrocode} - \ifx\dtl@plotlinecolorlist\@empty - \let\dtl@plotlinecolorlist=\DTLplotlinecolors - \fi - \dtl@chopfirst\dtl@plotlinecolorlist\dtl@thisplotlinecolor - \dtl@remainder - \let\dtl@plotlinecolorlist=\dtl@remainder +\define@choicekey{dataplot}{yticdir}[\val\nr]{in,out}{% +\ifcase\nr\relax + \DTLyticsintrue +\or + \DTLyticsinfalse +\fi +} % \end{macrocode} -% Get the current line style, and store in \cs{dtl@linestyle} +% Determine whether the $x$ and $y$ tick marks should point +% in or out; % \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 +\define@choicekey{dataplot}{ticdir}[\val\nr]{in,out}{% +\ifcase\nr\relax + \DTLxticsintrue + \DTLyticsintrue +\or + \DTLxticsinfalse + \DTLyticsinfalse +\fi +} % \end{macrocode} -% Append this plot setting to the legend. +% 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} - \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 +\define@key{dataplot}{bounds}{% +\def\dtl@bounds{#1}} +\let\dtl@bounds=\relax % \end{macrocode} -% Store stream in \cs{dtl@stream} +% Set only the lower $x$ bound % \begin{macrocode} - \def\dtl@stream{\pgfplotstreamstart}% +\define@key{dataplot}{minx}{% +\def\dtl@minx{#1}} +\let\dtl@minx=\relax % \end{macrocode} -% Only plot points that lie inside bounds. -%\changes{1.01}{2007 Aug 17}{uses \cs{@sDTLforeach} instead of -%\cs{DTLforeach}} +% Set only the upper $x$ bound: % \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}% +\define@key{dataplot}{maxx}{% +\def\dtl@maxx{#1}} +\let\dtl@maxx=\relax % \end{macrocode} -% End plot stream and draw path. +% Set only the lower $y$ bound: % \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 - }% +\define@key{dataplot}{miny}{% +\def\dtl@miny{#1}} +\let\dtl@miny=\relax % \end{macrocode} -% Plot legend if required. +% Set only the upper $y$ bound: % \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 -}} +\define@key{dataplot}{maxy}{% +\def\dtl@maxy{#1}} +\let\dtl@maxy=\relax % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\dtl@getbounds} -% Extract bounds: +% Define list of points for $x$ ticks. (Must be a comma separated +% list of decimal numbers.) % \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 -} +\define@key{dataplot}{xticpoints}{% +\def\dtl@xticlist{#1}\DTLxticstrue\DTLxaxistrue} +\let\dtl@xticlist=\relax % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\dtl@constructticklist} -%\begin{definition} -%\cs{dtl@constructticklist}\marg{min}\marg{max}\marg{scale factor}\marg{list} -%\end{definition} -% Constructs a list of tick points between \meta{min} and \meta{max} -% and store in \meta{list} (a control sequence.) -% \begin{macrocode} -\newcommand*{\dtl@constructticklist}[4]{% -\DTLifFPopenbetween{0}{#1}{#2}{% - \FPsub{\@dtl@width}{0}{#1}% - \FPmul{\@dtl@width}{\@dtl@width}{#3}% - \FPdiv{\@dtl@neggap}{\@dtl@width}{10}% - \setlength\dtl@tmplength{\@dtl@neggap sp}% - \ifdim\dtl@tmplength<\DTLmintickgap - \FPdiv{\@dtl@neggap}{\@dtl@width}{4}% - \setlength\dtl@tmplength{\@dtl@neggap sp}% - \ifdim\dtl@tmplength<\DTLmintickgap - \FPdiv{\@dtl@neggap}{\@dtl@width}{2}% - \setlength\dtl@tmplength{\@dtl@neggap sp}% - \ifdim\dtl@tmplength<\DTLmintickgap - \let\@dtl@neggap=\@dtl@width - \fi - \fi - \fi - \FPmul{\@dtl@width}{#2}{#3}% - \FPdiv{\@dtl@posgap}{\@dtl@width}{10}% - \setlength\dtl@tmplength{\@dtl@posgap sp}% - \ifdim\dtl@tmplength<\DTLmintickgap - \FPdiv{\@dtl@posgap}{\@dtl@width}{4}% - \setlength\dtl@tmplength{\@dtl@posgap sp}% - \ifdim\dtl@tmplength<\DTLmintickgap - \FPdiv{\@dtl@posgap}{\@dtl@width}{2}% - \setlength\dtl@tmplength{\@dtl@posgap sp}% - \ifdim\dtl@tmplength<\DTLmintickgap - \let\@dtl@posgap=\@dtl@width - \fi - \fi - \fi - \FPmax{\@dtl@gap}{\@dtl@neggap}{\@dtl@posgap}% - \FPdiv{\@dtl@gap}{\@dtl@gap}{#3}% - \dtl@constructticklistwithgapz{#1}{#2}{#4}{\@dtl@gap}% -}{% - \FPsub{\@dtl@width}{#2}{#1}% - \FPmul{\@dtl@width}{\@dtl@width}{#3}% - \FPdiv{\@dtl@gap}{\@dtl@width}{10}% - \setlength\dtl@tmplength{\@dtl@gap sp}% - \ifdim\dtl@tmplength<\DTLmintickgap - \FPdiv{\@dtl@gap}{\@dtl@width}{4}% - \setlength\dtl@tmplength{\@dtl@gap sp}% - \ifdim\dtl@tmplength<\DTLmintickgap - \FPdiv{\@dtl@gap}{\@dtl@width}{2}% - \setlength\dtl@tmplength{\@dtl@gap sp}% - \ifdim\dtl@tmplength<\DTLmintickgap - \let\@dtl@gap=\@dtl@width - \fi - \fi - \fi - \FPdiv{\@dtl@gap}{\@dtl@gap}{#3}% - \dtl@constructticklistwithgap{#1}{#2}{#4}{\@dtl@gap}% -}% -} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\dtl@constructticklistwithgap} -%\begin{definition} -%\cs{dtl@constructticklistwithgap}\marg{min}\marg{max}\marg{list}\marg{gap} -%\end{definition} -% Constructs a list of tick points between \meta{min} and \meta{max} -% and store in \meta{list} (a control sequence) using the gap given -% by \meta{gap} where the gap is given in user co-ordinates. +% Define list of points for $y$ ticks. (Must be a comma separated +% list of decimal numbers.) % \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@}% -} +\define@key{dataplot}{yticpoints}{% +\def\dtl@yticlist{#1}\DTLyticstrue\DTLyaxistrue} +\let\dtl@yticlist=\relax % \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. +% Define a the gap between $x$ tick marks (xticpoints overrides +% xticgap) % \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 -} +\define@key{dataplot}{xticgap}{\def\dtl@xticgap{#1}% +\DTLxticstrue\DTLxaxistrue} +\let\dtl@xticgap=\relax % \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.) +% Define a the gap between $y$ tick marks (yticpoints overrides +% yticgap) % \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 -} +\define@key{dataplot}{yticgap}{\def\dtl@yticgap{#1}% +\DTLyticstrue\DTLyaxistrue} +\let\dtl@yticgap=\relax % \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. +% Define comma separated list of labels for $x$ ticks. % \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}% -}% -} +\define@key{dataplot}{xticlabels}{% +\def\dtl@xticlabels{#1}\DTLxticstrue\DTLxaxistrue} +\let\dtl@xticlabels=\relax % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\DTLaddtoplotlegend} -%\begin{definition} -%\cs{DTLaddtoplotlegend}\marg{marker}\marg{line style}\marg{label} -%\end{definition} -% Adds entry to legend. +% Define comma separated list of labels for $y$ ticks. % \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 -} +\define@key{dataplot}{yticlabels}{% +\def\dtl@yticlabels{#1}\DTLyticstrue\DTLyaxistrue} +\let\dtl@yticlabels=\relax % \end{macrocode} -%\end{macro} -%\iffalse +% Define $x$ axis label % \begin{macrocode} -% +\define@key{dataplot}{xlabel}{% +\def\dtl@xlabel{#1}} +\let\dtl@xlabel=\relax % \end{macrocode} -%\fi -%\iffalse +% Define $y$ axis label % \begin{macrocode} -%<*databar.sty> +\define@key{dataplot}{ylabel}{% +\def\dtl@ylabel{#1}} +\let\dtl@ylabel=\relax % \end{macrocode} -%\fi -%\section{databar.sty} -% Declare package: +% 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} -\NeedsTeXFormat{LaTeX2e} -\ProvidesPackage{databar}[2009/02/27 v2.0 (NLCT)] +\define@choicekey{dataplot}{legend}[\val\nr]{none,north,northeast,% +east,southeast,south,southwest,west,northwest}[northeast]{% +\dtl@legendsetting=\nr\relax +} % \end{macrocode} -% Require \sty{xkeyval} package +% Legend labels (comma separated list). If omitted, the database +% name is used. % \begin{macrocode} -\RequirePackage{xkeyval} +\define@key{dataplot}{legendlabels}{\def\dtl@legendlabels{#1}} % \end{macrocode} -% Require \sty{dataplot} package +% +%\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} -\RequirePackage{dataplot} +\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} -%\begin{macro}{\ifDTLcolorbarchart} -% The conditional \cs{ifDTLcolorbarchart} is used to determine -% whether to use colour or grey scale. +% If user didn't specified bounds, +% compute the maximum and minimum $x$ and $y$ values over +% all the databases listed. % \begin{macrocode} -\newif\ifDTLcolorbarchart -\DTLcolorbarcharttrue + \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} -%\end{macro} -% Package options to change the conditional: +% Otherwise extract information from \cs{dtl@bounds} % \begin{macrocode} -\DeclareOption{color}{\DTLcolorbarcharttrue} -\DeclareOption{gray}{\DTLcolorbarchartfalse} + \else + \expandafter\dtl@getbounds\dtl@bounds\@nil + \fi % \end{macrocode} -%\cs{DTLbarXlabelalign} specifies the alignment -% for the $x$ axis labels. +% Determine scaling factors. % \begin{macrocode} -\newcommand*{\DTLbarXlabelalign}{left,rotate=-90} + \@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} -%\cs{DTLbarYticklabelalign} specifies the alignment -% for the $x$ axis labels. +% If x tics specified, construct a list of x tic points if not +% already specified. % \begin{macrocode} -\newcommand*{\DTLbarYticklabelalign}{right} + \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} -%\begin{macro}{\ifDTLverticalbars} -% Define boolean keys to govern bar chart orientation. +% Construct a list of $x$ minor tick points if required % \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} + \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} -%\end{macro} -% Set defaults: +% Determine the height of the $x$ tick labels. % \begin{macrocode} -\DTLverticalbarstrue + \ifx\dtl@xticlabels\relax + \settoheight{\dtl@xticlabelheight}{\dtl@xticlist}% + \else + \settoheight{\dtl@xticlabelheight}{\dtl@xticlabels}% + \fi + \else + \setlength{\dtl@xticlabelheight}{0pt}% + \fi % \end{macrocode} -% Package options to change \cs{ifDTLverticalbars} +% If y tics specified, construct a list of y tic points if not +% already specified. % \begin{macrocode} -\DeclareOption{vertical}{\DTLverticalbarstrue - \def\DTLbarXlabelalign{left,rotate=-90}% - \def\DTLbarYticklabelalign{right} -} -\DeclareOption{horizontal}{\DTLverticalbarsfalse - \def\DTLbarXlabelalign{right}% - \def\DTLbarYticklabelalign{center} -} + \setlength{\dtl@yticlabelwidth}{0pt}% + \ifDTLytics + \ifx\dtl@yticlist\relax + \ifx\dtl@yticgap\relax + \dtl@constructticklist\DTLminY\DTLmaxY + \dtl@unit@y\dtl@yticlist + \else + \DTLifFPopenbetween{0}{\DTLminY}{\DTLmaxY}{% + \dtl@constructticklistwithgapz + \DTLminY\DTLmaxY\dtl@yticlist\dtl@yticgap}{% + \dtl@constructticklistwithgap + \DTLminY\DTLmaxY\dtl@yticlist\dtl@yticgap}% + \fi + \fi % \end{macrocode} -% Process options: +% Construct a list of $y$ minor tick points if required % \begin{macrocode} -\ProcessOptions + \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} -% Required packages: +% Determine the width of the $y$ tick labels. % \begin{macrocode} -\RequirePackage{datatool} -\RequirePackage{tikz} + \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} -% 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} +% Start the picture. % \begin{macrocode} -\newlength\DTLbarchartlength -\DTLbarchartlength=3in + \begin{tikzpicture} % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\DTLbarwidth} -% The width of each bar is given by \cs{DTLbarwidth}. +% Set the $x$ and $y$ unit vectors. % \begin{macrocode} -\newlength\DTLbarwidth -\DTLbarwidth=1cm + \pgfsetxvec{\pgfpoint{\dtl@unit@x sp}{0pt}}% + \pgfsetyvec{\pgfpoint{0pt}{\dtl@unit@y sp}}% % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\DTLbarlabeloffset} -% The offset from the $x$ axis to the bar label if given by -% \cs{DTLbarlabeloffset}. +% Add any extra information the user requires % \begin{macrocode} -\newlength\DTLbarlabeloffset -\setlength\DTLbarlabeloffset{10pt} + \DTLplotatbegintikz % \end{macrocode} -%\end{macro} -%\begin{macro}{\DTLBarXAxisStyle} -% The style of the $x$ axis is given by \cs{DTLBarXAxisStyle} +% Determine whether to put a box around the plot % \begin{macrocode} -\newcommand*{\DTLBarXAxisStyle}{-} + \ifDTLbox + \draw (\DTLminX,\DTLminY) -- (\DTLmaxX,\DTLminY) -- + (\DTLmaxX,\DTLmaxY) -- (\DTLminX,\DTLmaxY) -- + cycle; + \else % \end{macrocode} -%\end{macro} -%\begin{macro}{\DTLBarYAxisStyle} -% The style of the $y$ axis is given by \cs{DTLBarYAxisStyle}. +% Plot $x$ axis if required. % \begin{macrocode} -\newcommand*{\DTLBarYAxisStyle}{-} + \ifDTLxaxis + \expandafter\draw\expandafter[\DTLXAxisStyle] + (\DTLminX,\DTLminY) -- (\DTLmaxX,\DTLminY); + \fi % \end{macrocode} -%\end{macro} -% -% \counterfmt{DTLbarroundvar} is a counter governing the number of digits -% to round to when using \cs{FPround}. +% Plot $y$ axis if required. % \begin{macrocode} -\newcounter{DTLbarroundvar} -\setcounter{DTLbarroundvar}{1} + \ifDTLyaxis + \expandafter\draw\expandafter[\DTLYAxisStyle] + (\DTLminX,\DTLminY) -- (\DTLminX,\DTLmaxY); + \fi + \fi % \end{macrocode} -% -%\begin{macro}{\DTLbardisplayYticklabel} -%\cs{DTLbardisplayYticklabel} governs how the $y$ tick labels appear. +% Plot grid if required % \begin{macrocode} -\newcommand*{\DTLbardisplayYticklabel}[1]{#1} -% \end{macrocode} -%\end{macro} -%\begin{macro}{\DTLdisplaylowerbarlabel} -%\cs{DTLdisplaylowerbarlabel} governs how the lower bar labels appear. -% \begin{macrocode} -\newcommand*{\DTLdisplaylowerbarlabel}[1]{#1} + \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} -%\end{macro} -%\begin{macro}{\DTLdisplaylowermultibarlabel} -%\cs{DTLdisplaylowermultibarlabel} governs how the lower multi bar labels appear. +% Plot $x$ tics if required. % \begin{macrocode} -\newcommand*{\DTLdisplaylowermultibarlabel}[1]{#1} + \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} -%\end{macro} -%\begin{macro}{\DTLdisplayupperbarlabel} -%\cs{DTLdisplayupperbarlabel} governs how the upper bar labels -% appear. +% Plot the tick labels % \begin{macrocode} -\newcommand*{\DTLdisplayupperbarlabel}[1]{#1} + \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} -%\end{macro} -%\begin{macro}{\DTLdisplayuppermultibarlabel} -%\cs{DTLdisplayuppermultibarlabel} governs how the upper multi bar -% labels appear. +% Plot $x$ label if required. % \begin{macrocode} -\newcommand*{\DTLdisplayuppermultibarlabel}[1]{#1} + \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} -%\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. +% Plot the $x$ minor ticks if required % \begin{macrocode} -\newcommand*{\DTLbaratbegintikz}{} + \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} -%\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. +% Plot $y$ tics if required. % \begin{macrocode} -\newcommand*{\DTLbaratendtikz}{} + \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} -%\end{macro} -% -%\begin{macro}{\ifDTLbarxaxis} -% The conditional \cs{ifDTLbarxaxis} is used to determine -% whether or not to display the $x$ axis +% Plot the $y$ tick labels if required % \begin{macrocode} -\newif\ifDTLbarxaxis + \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} -%\end{macro} -%\begin{macro}{\ifDTLbaryaxis} -% The conditional \cs{ifDTLbaryaxis} is used to determine -% whether or not to display the $y$ axis. +% Plot $y$ label if required. % \begin{macrocode} -\newif\ifDTLbaryaxis + \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} -%\end{macro} -%\begin{macro}{\ifDTLbarytics} -% The conditional \cs{ifDTLbarytics} to determine whether -% or not to display the $y$ tick marks. +% Plot the $y$ minor ticks if required % \begin{macrocode} -\newif\ifDTLbarytics + \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} -%\end{macro} -% -%\begin{macro}{\@dtl@barcount} -% The count register \cs{@dtl@barcount} is used to store -% the current bar index. +% Iterate through each database % \begin{macrocode} -\newcount\@dtl@barcount + \@for\dtl@thisdb:=#2\do{% % \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. +% Get the current plot mark colour. % \begin{macrocode} -\newcommand*{\DTLsetbarcolor}[2]{% -\expandafter\def\csname dtlbar@segcol\romannumeral#1\endcsname{#2}% -} + \ifx\dtl@plotmarkcolorlist\@empty + \let\dtl@plotmarkcolorlist=\DTLplotmarkcolors + \fi + \dtl@chopfirst\dtl@plotmarkcolorlist\dtl@thisplotmarkcolor + \dtl@remainder + \let\dtl@plotmarkcolorlist=\dtl@remainder % \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. +% Get the current plot mark, and store in \cs{dtl@mark} % \begin{macrocode} -\newcommand*{\DTLgetbarcolor}[1]{% -\csname dtlbar@segcol\romannumeral#1\endcsname} + \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{macro} -% -%\begin{macro}{\DTLdobarcolor} -%\begin{definition} -%\cs{DTLdobarcolor}\marg{n} -%\end{definition} -% Sets the colour to that for the \meta{n}th bar. +% Get the current plot line colour. % \begin{macrocode} -\newcommand*{\DTLdobarcolor}[1]{% -\expandafter\color\expandafter -{\csname dtlbar@segcol\romannumeral#1\endcsname}} + \ifx\dtl@plotlinecolorlist\@empty + \let\dtl@plotlinecolorlist=\DTLplotlinecolors + \fi + \dtl@chopfirst\dtl@plotlinecolorlist\dtl@thisplotlinecolor + \dtl@remainder + \let\dtl@plotlinecolorlist=\dtl@remainder % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\DTLdocurrentbarcolor} -%\cs{DTLdocurrentbarcolor} -% sets the colour to that of the current bar. +% Get the current line style, and store in \cs{dtl@linestyle} % \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} + \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} -%\end{macro} -% -%\begin{macro}{\DTLbaroutlinecolor} -%\cs{DTLbaroutlinecolor} specifies what colour to draw the -% outline. +% Append this plot setting to the legend. % \begin{macrocode} -\newcommand*{\DTLbaroutlinecolor}{black} + \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} -%\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. +% Store stream in \cs{dtl@stream} % \begin{macrocode} -\newlength\DTLbaroutlinewidth -\DTLbaroutlinewidth=0pt + \def\dtl@stream{\pgfplotstreamstart}% % \end{macrocode} -%\end{macro} -% -% Set the default colours. If there are more than eight bars, -% more colours will need to be defined. +% Only plot points that lie inside bounds. +%\changes{1.01}{2007 Aug 17}{uses \cs{@sDTLforeach} instead of +%\cs{DTLforeach}} % \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 + \@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} -%\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}% +% End plot stream and draw path. % \begin{macrocode} -\newcommand*{\DTLeverybarhook}{} + \ifx\dtl@linestyle\relax + \else + \begin{scope} + \dtl@linestyle + \pgfplothandlerlineto + \dtl@stream + \pgfusepath{stroke} + \end{scope} + \fi + \ifx\dtl@mark\relax + \else + \begin{scope} + \pgfplothandlermark{\dtl@mark}% + \dtl@stream + \pgfusepath{stroke} + \end{scope} + \fi + }% +% \end{macrocode} +% Plot legend if required. +% \begin{macrocode} + \ifcase\dtl@legendsetting + % none + \or % north + \pgftext[top,center,at={\pgfpointadd + {\pgfpointxy{\DTLminX}{\DTLmaxY}} + {\pgfpoint{0.5\DTLplotwidth}{-\DTLlegendyoffset}}}] + {\DTLformatlegend + {\begin{tabular}{cl}\dtl@legend\end{tabular}}} + \or % north east + \pgftext[top,right,at={\pgfpointadd + {\pgfpointxy{\DTLmaxX}{\DTLmaxY}} + {\pgfpoint{-\DTLlegendxoffset}{-\DTLlegendyoffset}}}] + {\DTLformatlegend + {\begin{tabular}{cl}\dtl@legend\end{tabular}}} + \or % east + \pgftext[center,right,at={\pgfpointadd + {\pgfpointxy{\DTLmaxX}{\DTLminY}} + {\pgfpoint{-\DTLlegendxoffset}{0.5\DTLplotheight}}}] + {\DTLformatlegend + {\begin{tabular}{cl}\dtl@legend\end{tabular}}} + \or % south east + \pgftext[bottom,right,at={\pgfpointadd + {\pgfpointxy{\DTLmaxX}{\DTLminY}} + {\pgfpoint{-\DTLlegendxoffset}{\DTLlegendyoffset}}}] + {\DTLformatlegend + {\begin{tabular}{cl}\dtl@legend\end{tabular}}} + \or % south + \pgftext[center,bottom,at={\pgfpointadd + {\pgfpointxy{\DTLminX}{\DTLminY}} + {\pgfpoint{0.5\DTLplotwidth}{\DTLlegendyoffset}}}] + {\DTLformatlegend + {\begin{tabular}{cl}\dtl@legend\end{tabular}}} + \or % south west + \pgftext[bottom,left,at={\pgfpointadd + {\pgfpointxy{\DTLminX}{\DTLminY}} + {\pgfpoint{\DTLlegendxoffset}{\DTLlegendyoffset}}}] + {\DTLformatlegend + {\begin{tabular}{cl}\dtl@legend\end{tabular}}} + \or % west + \pgftext[center,left,at={\pgfpointadd + {\pgfpointxy{\DTLminX}{\DTLminY}} + {\pgfpoint{\DTLlegendxoffset}{0.5\DTLplotheight}}}] + {\DTLformatlegend + {\begin{tabular}{cl}\dtl@legend\end{tabular}}} + \or % north west + \pgftext[top,left,at={\pgfpointadd + {\pgfpointxy{\DTLminX}{\DTLmaxY}} + {\pgfpoint{\DTLlegendxoffset}{-\DTLlegendyoffset}}}] + {\DTLformatlegend + {\begin{tabular}{cl}\dtl@legend\end{tabular}}} + \fi + \DTLplotatendtikz + \end{tikzpicture} + \fi + \fi +\fi +}} % \end{macrocode} %\end{macro} % -% Define keys for \cs{DTLbarchart} optional argument. -% Set the maximum value of the $y$ axis. +%\begin{macro}{\dtl@getbounds} +% Extract bounds: % \begin{macrocode} -\define@key{databar}{max}{\def\DTLbarmax{#1}} +\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} -% Set the total length of the bar chart +%\end{macro} +% +%\begin{macro}{\dtl@constructticklist} +%\begin{definition} +%\cs{dtl@constructticklist}\marg{min}\marg{max}\marg{scale factor}\marg{list} +%\end{definition} +% Constructs a list of tick points between \meta{min} and \meta{max} +% and store in \meta{list} (a control sequence.) % \begin{macrocode} -\define@key{databar}{length}{\DTLbarchartlength=#1\relax +\newcommand*{\dtl@constructticklist}[4]{% +\DTLifFPopenbetween{0}{#1}{#2}{% + \FPsub{\@dtl@width}{0}{#1}% + \FPmul{\@dtl@width}{\@dtl@width}{#3}% + \FPdiv{\@dtl@neggap}{\@dtl@width}{10}% + \setlength\dtl@tmplength{\@dtl@neggap sp}% + \ifdim\dtl@tmplength<\DTLmintickgap + \FPdiv{\@dtl@neggap}{\@dtl@width}{4}% + \setlength\dtl@tmplength{\@dtl@neggap sp}% + \ifdim\dtl@tmplength<\DTLmintickgap + \FPdiv{\@dtl@neggap}{\@dtl@width}{2}% + \setlength\dtl@tmplength{\@dtl@neggap sp}% + \ifdim\dtl@tmplength<\DTLmintickgap + \let\@dtl@neggap=\@dtl@width + \fi + \fi + \fi + \FPmul{\@dtl@width}{#2}{#3}% + \FPdiv{\@dtl@posgap}{\@dtl@width}{10}% + \setlength\dtl@tmplength{\@dtl@posgap sp}% + \ifdim\dtl@tmplength<\DTLmintickgap + \FPdiv{\@dtl@posgap}{\@dtl@width}{4}% + \setlength\dtl@tmplength{\@dtl@posgap sp}% + \ifdim\dtl@tmplength<\DTLmintickgap + \FPdiv{\@dtl@posgap}{\@dtl@width}{2}% + \setlength\dtl@tmplength{\@dtl@posgap sp}% + \ifdim\dtl@tmplength<\DTLmintickgap + \let\@dtl@posgap=\@dtl@width + \fi + \fi + \fi + \FPmax{\@dtl@gap}{\@dtl@neggap}{\@dtl@posgap}% + \FPdiv{\@dtl@gap}{\@dtl@gap}{#3}% + \dtl@constructticklistwithgapz{#1}{#2}{#4}{\@dtl@gap}% +}{% + \FPsub{\@dtl@width}{#2}{#1}% + \FPmul{\@dtl@width}{\@dtl@width}{#3}% + \FPdiv{\@dtl@gap}{\@dtl@width}{10}% + \setlength\dtl@tmplength{\@dtl@gap sp}% + \ifdim\dtl@tmplength<\DTLmintickgap + \FPdiv{\@dtl@gap}{\@dtl@width}{4}% + \setlength\dtl@tmplength{\@dtl@gap sp}% + \ifdim\dtl@tmplength<\DTLmintickgap + \FPdiv{\@dtl@gap}{\@dtl@width}{2}% + \setlength\dtl@tmplength{\@dtl@gap sp}% + \ifdim\dtl@tmplength<\DTLmintickgap + \let\@dtl@gap=\@dtl@width + \fi + \fi + \fi + \FPdiv{\@dtl@gap}{\@dtl@gap}{#3}% + \dtl@constructticklistwithgap{#1}{#2}{#4}{\@dtl@gap}% +}% } % \end{macrocode} -% Set the maximum depth (negative extent) +%\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} -\define@key{databar}{maxdepth}{% -\ifnum#1>0\relax - \PackageError{databar}{depth must be zero or negative}{}% -\else - \def\DTLnegextent{#1}% -\fi} +\newcommand*{\dtl@constructticklistwithgap}[4]{% +\edef\@dtl@thistick{#1}% +\edef#3{#1}% +\FPadd{\@dtl@thistick}{\@dtl@thistick}{#4}% +\whiledo{\DTLisFPopenbetween{\@dtl@thistick}{#1}{#2}}{% + \expandafter\toks@\expandafter{\@dtl@thistick}% + \edef#3{#3,\the\toks@}% + \FPadd{\@dtl@thistick}{\@dtl@thistick}{#4}% +}% +\expandafter\toks@\expandafter{#2}% +\edef#3{#3,\the\toks@}% +} % \end{macrocode} -% Determine which axes should be shown +%\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} -\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 +\newcommand*{\dtl@constructticklistwithgapz}[4]{% +\edef\@dtl@thistick{0}% +\edef#3{0}% +\FPadd{\@dtl@thistick}{\@dtl@thistick}{#4}% +\whiledo{\DTLisFPopenbetween{\@dtl@thistick}{0}{#2}}{% + \expandafter\toks@\expandafter{\@dtl@thistick}% + \edef#3{#3,\the\toks@}% + \FPadd{\@dtl@thistick}{\@dtl@thistick}{#4}% +}% +\expandafter\toks@\expandafter{#2}% +\edef#3{#3,\the\toks@}% +\FPifeq{#1}{0}% +\else +\edef\@dtl@thistick{0}% + \FPsub{\@dtl@thistick}{\@dtl@thistick}{#4}% + \whiledo{\DTLisFPopenbetween{\@dtl@thistick}{#1}{0}}{% + \expandafter\toks@\expandafter{\@dtl@thistick}% + \edef#3{\the\toks@,#3}% + \FPsub{\@dtl@thistick}{\@dtl@thistick}{#4}% + }% + \expandafter\toks@\expandafter{#1}% + \edef#3{\the\toks@,#3}% \fi } % \end{macrocode} -% Variable used to create the bar chart. (Must be a control -% sequence.) +%\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} -\define@key{databar}{variable}{% -\def\DTLbarvariable{#1}} +\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} -% Variables used to create the multi bar chart. (Must be a -% comma separated list of control sequences.) +%\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} -\define@key{databar}{variables}{% -\def\dtlbar@variables{#1}} +\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} -% Bar width +%\end{macro} +% +%\begin{macro}{\DTLaddtoplotlegend} +%\begin{definition} +%\cs{DTLaddtoplotlegend}\marg{marker}\marg{line style}\marg{label} +%\end{definition} +% Adds entry to legend. % \begin{macrocode} -\define@key{databar}{barwidth}{\setlength{\DTLbarwidth}{#1}} +\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} -% Lower bar labels +%\end{macro} +%\iffalse % \begin{macrocode} -\define@key{databar}{barlabel}{% -\def\dtl@barlabel{#1}} -\def\dtl@barlabel{} +% % \end{macrocode} -% Lower bar labels for multi-bar charts +%\fi +%\iffalse % \begin{macrocode} -\define@key{databar}{multibarlabels}{% -\def\dtl@multibarlabels{#1}} -\def\dtl@multibarlabels{} +%<*databar.sty> % \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.) +%\fi +%\section{databar.sty} +% Declare package: % \begin{macrocode} -\define@key{databar}{groupgap}{\def\dtlbar@groupgap{#1}} -\def\dtlbar@groupgap{1} +\NeedsTeXFormat{LaTeX2e} +\ProvidesPackage{databar}[2009/10/22 v2.01 (NLCT)] % \end{macrocode} -% Upper bar labels +% Require \sty{xkeyval} package % \begin{macrocode} -\define@key{databar}{upperbarlabel}{% -\def\dtl@upperbarlabel{#1}} -\def\dtl@upperbarlabel{} +\RequirePackage{xkeyval} % \end{macrocode} -% Upper bar labels for multi-bar charts +% Require \sty{dataplot} package % \begin{macrocode} -\define@key{databar}{uppermultibarlabels}{% -\def\dtl@uppermultibarlabels{#1}} -\def\dtl@uppermultibarlabels{} +\RequirePackage{dataplot} % \end{macrocode} -% Define list of points for $y$ tics. (Must be a comma separated list -% of decimal numbers.) +%\begin{macro}{\ifDTLcolorbarchart} +% The conditional \cs{ifDTLcolorbarchart} is used to determine +% whether to use colour or grey scale. % \begin{macrocode} -\define@key{databar}{yticpoints}{% -\def\dtlbar@yticlist{#1}\DTLbaryticstrue\DTLbaryaxistrue} -\let\dtlbar@yticlist=\relax +\newif\ifDTLcolorbarchart +\DTLcolorbarcharttrue % \end{macrocode} -% Set the $y$ tick gap: +%\end{macro} +% Package options to change the conditional: % \begin{macrocode} -\define@key{databar}{yticgap}{% -\def\dtlbar@yticgap{#1}\DTLbaryticstrue\DTLbaryaxistrue} -\let\dtlbar@yticgap=\relax +\DeclareOption{color}{\DTLcolorbarcharttrue} +\DeclareOption{gray}{\DTLcolorbarchartfalse} % \end{macrocode} -% Define list of labels for $y$ tics. +%\cs{DTLbarXlabelalign} specifies the alignment +% for the $x$ axis labels. % \begin{macrocode} -\define@key{databar}{yticlabels}{% -\def\dtlbar@yticlabels{#1}\DTLbaryticstrue\DTLbaryaxistrue} -\let\dtlbar@yticlabels=\relax +\newcommand*{\DTLbarXlabelalign}{left,rotate=-90} % \end{macrocode} -% Define $y$ axis label. +%\cs{DTLbarYticklabelalign} specifies the alignment +% for the $x$ axis labels. % \begin{macrocode} -\define@key{databar}{ylabel}{% -\def\dtlbar@ylabel{#1}} -\let\dtlbar@ylabel=\relax +\newcommand*{\DTLbarYticklabelalign}{right} % \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{macro}{\ifDTLverticalbars} +% Define boolean keys to govern bar chart orientation. % \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}% +\define@boolkey{databar}[DTL]{verticalbars}[true]{% +\ifDTLverticalbars + \def\DTLbarXlabelalign{left,rotate=-90}% + \def\DTLbarYticklabelalign{right} \else + \def\DTLbarXlabelalign{right}% + \def\DTLbarYticklabelalign{center} +\fi} % \end{macrocode} -% Compute the maximum bar height, unless \cs{DTLbarmax} has been -% set. -%\changes{1.01}{2007 Aug 17}{uses \cs{@sDTLforeach} instead of -%\cs{DTLforeach}} +%\end{macro} +% Set defaults: % \begin{macrocode} - \ifx\DTLbarmax\relax - \@sDTLforeach[#1]{#3}{#4}{% - \expandafter\DTLconverttodecimal\expandafter - {\DTLbarvariable}{\dtl@barvar}% - \ifx\DTLbarmax\relax - \let\DTLbarmax=\dtl@barvar - \else - \let\dtl@old=\DTLbarmax - \FPmax{\DTLbarmax}{\dtl@old}{\dtl@barvar}% - \fi - }% - \ifx\dtlbar@yticgap\relax - \else - \let\dtl@thistick=\dtlbar@yticgap% - \whiledo{\DTLisFPopenbetween{\dtl@thistick}{0}{\DTLbarmax}}{% - \FPadd{\dtl@thistick}{\dtl@thistick}{\dtlbar@yticgap}% - }% - \let\DTLbarmax=\dtl@thistick - \fi - \fi +\DTLverticalbarstrue % \end{macrocode} -% Compute the bar depth, unless \cs{DTLnegextent} has been -% set. +% Package options to change \cs{ifDTLverticalbars} % \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 +\DeclareOption{vertical}{\DTLverticalbarstrue + \def\DTLbarXlabelalign{left,rotate=-90}% + \def\DTLbarYticklabelalign{right} +} +\DeclareOption{horizontal}{\DTLverticalbarsfalse + \def\DTLbarXlabelalign{right}% + \def\DTLbarYticklabelalign{center} +} % \end{macrocode} -% Determine scaling factor +% Process options: % \begin{macrocode} - \@dtl@tmpcount=\DTLbarchartlength - \FPsub{\dtl@extent}{\DTLbarmax}{\DTLnegextent}% - \FPdiv{\dtl@unit}{\number\@dtl@tmpcount}{\dtl@extent}% +\ProcessOptions % \end{macrocode} -% Construct $y$ tick list if required +% Required packages: % \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 +\RequirePackage{datatool} +\RequirePackage{tikz} % \end{macrocode} -% Store the width of the bar chart in \cs{DTLbarchartwidth} +% 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} -\edef\DTLbarchartwidth{\expandafter\number\csname dtlrows@#3\endcsname} +\newlength\DTLbarchartlength +\DTLbarchartlength=3in % \end{macrocode} -% Do the bar chart +%\end{macro} +% +%\begin{macro}{\DTLbarwidth} +% The width of each bar is given by \cs{DTLbarwidth}. % \begin{macrocode} -\begin{tikzpicture} +\newlength\DTLbarwidth +\DTLbarwidth=1cm % \end{macrocode} -% Set unit vectors +%\end{macro} +% +%\begin{macro}{\DTLbarlabeloffset} +% The offset from the $x$ axis to the bar label if given by +% \cs{DTLbarlabeloffset}. % \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 +\newlength\DTLbarlabeloffset +\setlength\DTLbarlabeloffset{10pt} % \end{macrocode} -% Begin hook +%\end{macro} +%\begin{macro}{\DTLBarXAxisStyle} +% The style of the $x$ axis is given by \cs{DTLBarXAxisStyle} % \begin{macrocode} -\DTLbaratbegintikz +\newcommand*{\DTLBarXAxisStyle}{-} % \end{macrocode} -% Initialise +%\end{macro} +%\begin{macro}{\DTLBarYAxisStyle} +% The style of the $y$ axis is given by \cs{DTLBarYAxisStyle}. % \begin{macrocode} -\def\@dtl@start{0}% +\newcommand*{\DTLBarYAxisStyle}{-} % \end{macrocode} -% Iterate through data +%\end{macro} +% +%\begin{counter}{DTLbarroundvar} +% \ctrfmt{DTLbarroundvar} is a counter governing the number of digits +% to round to when using \cs{FPround}. % \begin{macrocode} -\@sDTLforeach[#1]{#3}{#4}{% +\newcounter{DTLbarroundvar} +\setcounter{DTLbarroundvar}{1} % \end{macrocode} -% Store the bar number in \cs{@dtl@bar} -% \begin{macrocode} -\expandafter\let\expandafter\@dtl@bar - \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname% +%\end{counter} +% +%\begin{macro}{\DTLbardisplayYticklabel} +%\cs{DTLbardisplayYticklabel} governs how the $y$ tick labels appear. +% \begin{macrocode} +\newcommand*{\DTLbardisplayYticklabel}[1]{#1} % \end{macrocode} -% Convert variable to decimal +%\end{macro} +%\begin{macro}{\DTLdisplaylowerbarlabel} +%\cs{DTLdisplaylowerbarlabel} governs how the lower bar labels appear. % \begin{macrocode} -\expandafter\DTLconverttodecimal\expandafter - {\DTLbarvariable}{\dtl@variable}% +\newcommand*{\DTLdisplaylowerbarlabel}[1]{#1} % \end{macrocode} -% Draw bars +%\end{macro} +%\begin{macro}{\DTLdisplaylowermultibarlabel} +%\cs{DTLdisplaylowermultibarlabel} governs how the lower multi bar labels appear. % \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} +\newcommand*{\DTLdisplaylowermultibarlabel}[1]{#1} % \end{macrocode} -% Draw outline +%\end{macro} +%\begin{macro}{\DTLdisplayupperbarlabel} +%\cs{DTLdisplayupperbarlabel} governs how the upper bar labels +% appear. % \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} +\newcommand*{\DTLdisplayupperbarlabel}[1]{#1} % \end{macrocode} -% Draw lower $x$ labels +%\end{macro} +%\begin{macro}{\DTLdisplayuppermultibarlabel} +%\cs{DTLdisplayuppermultibarlabel} governs how the upper multi bar +% labels appear. % \begin{macrocode} -\ifDTLverticalbars - \edef\dtl@textopt{% - at={\noexpand\pgfpointadd - {\noexpand\pgfpointxy{\@dtl@start.5}{0}} - {\noexpand\pgfpoint{0pt}{-\noexpand\DTLbarlabeloffset}}}, - \DTLbarXlabelalign - }% +\newcommand*{\DTLdisplayuppermultibarlabel}[1]{#1} % \end{macrocode} -% Set \cs{DTLstartpt} to the starting point. +%\end{macro} +% +%\begin{macro}{\DTLbaratbegintikz} +% \cs{DTLbaratbegintikz} specifies any commands +% to apply at the start of the \env{tikzpicture} environment. +% By default it does nothing. % \begin{macrocode} - \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 - }% +\newcommand*{\DTLbaratbegintikz}{} % \end{macrocode} -% Set \cs{DTLstartpt} to the starting point. +%\end{macro} +% +%\begin{macro}{\DTLbaratendtikz} +% \cs{DTLbaratendtikz} specifies any commands +% to apply at the end of the \env{tikzpicture} environment. +% By default it does nothing. % \begin{macrocode} - \edef\DTLstartpt{\noexpand\pgfpointxy{0}{\@dtl@start.5}}% -\fi - \expandafter\pgftext\expandafter[\dtl@textopt]{% - \DTLdisplaylowerbarlabel{\dtl@barlabel}} +\newcommand*{\DTLbaratendtikz}{} % \end{macrocode} -% Draw upper $x$ labels +%\end{macro} +% +%\begin{macro}{\ifDTLbarxaxis} +% The conditional \cs{ifDTLbarxaxis} is used to determine +% whether or not to display the $x$ axis % \begin{macrocode} -\ifDTLverticalbars +\newif\ifDTLbarxaxis % \end{macrocode} -% Vertical bars +%\end{macro} +%\begin{macro}{\ifDTLbaryaxis} +% The conditional \cs{ifDTLbaryaxis} is used to determine +% whether or not to display the $y$ axis. % \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}}} - }% - } +\newif\ifDTLbaryaxis % \end{macrocode} -% Set \cs{DTLendpt} to the end point. +%\end{macro} +%\begin{macro}{\ifDTLbarytics} +% The conditional \cs{ifDTLbarytics} to determine whether +% or not to display the $y$ tick marks. % \begin{macrocode} - \edef\DTLendpt{\noexpand\pgfpointxy{\@dtl@start.5}{\dtl@variable}}% -\else +\newif\ifDTLbarytics % \end{macrocode} -% Horizontal bars +%\end{macro} +% +%\begin{macro}{\@dtl@barcount} +% The count register \cs{@dtl@barcount} is used to store +% the current bar index. % \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}}} - }% - } +\newcount\@dtl@barcount % \end{macrocode} -% Set \cs{DTLendpt} to the end point. +%\end{macro} +% +%\begin{macro}{\DTLsetbarcolor} +%\begin{definition} +% \cs{DTLsetbarcolor}\marg{n}\marg{color} +%\end{definition} +% Assigns colour name \meta{color} to the \meta{n}th bar. % \begin{macrocode} - \edef\DTLendpt{\noexpand\pgfpointxy{\dtl@variable}{\@dtl@start.5}}% -\fi - \expandafter\pgftext\expandafter[\dtl@textopt]{% - \DTLdisplayupperbarlabel{\dtl@upperbarlabel}} +\newcommand*{\DTLsetbarcolor}[2]{% +\expandafter\def\csname dtlbar@segcol\romannumeral#1\endcsname{#2}% +} % \end{macrocode} -% Set the mid point +%\end{macro} +% +%\begin{macro}{\DTLgetbarcolor} +%\begin{definition} +%\cs{DTLgetbarcolor}\marg{n} +%\end{definition} +% Gets the colour specification for the \meta{n}th bar. % \begin{macrocode} -\def\DTLmidpt{\pgfpointlineattime{0.5}{\DTLstartpt}{\DTLendpt}}% +\newcommand*{\DTLgetbarcolor}[1]{% +\csname dtlbar@segcol\romannumeral#1\endcsname} % \end{macrocode} -% Do every bar hook -%\changes{2.0}{2009 February 27}{added \cs{DTLeverybarhook}}% +%\end{macro} +% +%\begin{macro}{\DTLdobarcolor} +%\begin{definition} +%\cs{DTLdobarcolor}\marg{n} +%\end{definition} +% Sets the colour to that for the \meta{n}th bar. % \begin{macrocode} - \DTLeverybarhook +\newcommand*{\DTLdobarcolor}[1]{% +\expandafter\color\expandafter +{\csname dtlbar@segcol\romannumeral#1\endcsname}} % \end{macrocode} -% End of loop +%\end{macro} +% +%\begin{macro}{\DTLdocurrentbarcolor} +%\cs{DTLdocurrentbarcolor} +% sets the colour to that of the current bar. % \begin{macrocode} - \edef\@dtl@start{\number\@dtl@bar}% -} +\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} -% Draw $x$ axis +%\end{macro} +% +%\begin{macro}{\DTLbaroutlinecolor} +%\cs{DTLbaroutlinecolor} specifies what colour to draw the +% outline. % \begin{macrocode} -\ifDTLbarxaxis - \ifDTLverticalbars - \expandafter\draw\expandafter[\DTLBarXAxisStyle] - (0,0) -- (\DTLbarchartwidth,0); - \else - \expandafter\draw\expandafter[\DTLBarXAxisStyle] - (0,0) -- (0,\DTLbarchartwidth); - \fi -\fi +\newcommand*{\DTLbaroutlinecolor}{black} % \end{macrocode} -% Draw $y$ axis +%\end{macro} +% +%\begin{macro}{\DTLbaroutlinewidth} +%\cs{DTLbaroutlinewidth} specifies the line width of the outline: +% Outline is only drawn if the linewidth is greater than 0pt. % \begin{macrocode} -\ifDTLbaryaxis - \ifDTLverticalbars - \expandafter\draw\expandafter[\DTLBarYAxisStyle] - (0,\DTLnegextent) -- (0,\DTLbarmax); - \else - \expandafter\draw\expandafter[\DTLBarYAxisStyle] - (\DTLnegextent,0) -- (\DTLbarmax,0); - \fi -\fi +\newlength\DTLbaroutlinewidth +\DTLbaroutlinewidth=0pt % \end{macrocode} -% Plot $y$ tick marks if required +%\end{macro} +% +% Set the default colours. If there are more than eight bars, +% more colours will need to be defined. % \begin{macrocode} -\ifx\dtlbar@yticlist\relax +\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 - \@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}} - }% + \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} -% Plot the $y$ label if required +%\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} -\ifx\dtlbar@ylabel\relax +\newcommand*{\DTLeverybarhook}{} +% \end{macrocode} +%\end{macro} +% +% Define keys for \cs{DTLbarchart} optional argument. +% Set the maximum value of the $y$ axis. +% \begin{macrocode} +\define@key{databar}{max}{\def\DTLbarmax{#1}} +% \end{macrocode} +% Set the total length of the bar chart +% \begin{macrocode} +\define@key{databar}{length}{\DTLbarchartlength=#1\relax +} +% \end{macrocode} +% Set the maximum depth (negative extent) +% \begin{macrocode} +\define@key{databar}{maxdepth}{% +\ifnum#1>0\relax + \PackageError{databar}{depth must be zero or negative}{}% \else - \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 + \def\DTLnegextent{#1}% +\fi} % \end{macrocode} -% Finish bar chart +% Determine which axes should be shown % \begin{macrocode} -\DTLbaratendtikz -\end{tikzpicture} +\define@choicekey{databar}{axes}[\var\nr]{both,x,y,none}{% +\ifcase\nr\relax + % both + \DTLbarxaxistrue + \DTLbaryaxistrue + \DTLbaryticstrue +\or + % x only + \DTLbarxaxistrue + \DTLbaryaxisfalse + \DTLbaryticsfalse +\or + % y only + \DTLbarxaxisfalse + \DTLbaryaxistrue + \DTLbaryticstrue +\or + % neither + \DTLbarxaxisfalse + \DTLbaryaxisfalse + \DTLbaryticsfalse \fi -}} +} +% \end{macrocode} +% Variable used to create the bar chart. (Must be a control +% sequence.) +% \begin{macrocode} +\define@key{databar}{variable}{% +\def\DTLbarvariable{#1}} +% \end{macrocode} +% Variables used to create the multi bar chart. (Must be a +% comma separated list of control sequences.) +% \begin{macrocode} +\define@key{databar}{variables}{% +\def\dtlbar@variables{#1}} +% \end{macrocode} +% Bar width +% \begin{macrocode} +\define@key{databar}{barwidth}{\setlength{\DTLbarwidth}{#1}} +% \end{macrocode} +% Lower bar labels +% \begin{macrocode} +\define@key{databar}{barlabel}{% +\def\dtl@barlabel{#1}} +\def\dtl@barlabel{} +% \end{macrocode} +% Lower bar labels for multi-bar charts +% \begin{macrocode} +\define@key{databar}{multibarlabels}{% +\def\dtl@multibarlabels{#1}} +\def\dtl@multibarlabels{} +% \end{macrocode} +% Gap between groups in multi-bar charts (This should be in $x$ units +% where 1 $x$ unit is the width of a bar.) +% \begin{macrocode} +\define@key{databar}{groupgap}{\def\dtlbar@groupgap{#1}} +\def\dtlbar@groupgap{1} +% \end{macrocode} +% Upper bar labels +% \begin{macrocode} +\define@key{databar}{upperbarlabel}{% +\def\dtl@upperbarlabel{#1}} +\def\dtl@upperbarlabel{} +% \end{macrocode} +% Upper bar labels for multi-bar charts +% \begin{macrocode} +\define@key{databar}{uppermultibarlabels}{% +\def\dtl@uppermultibarlabels{#1}} +\def\dtl@uppermultibarlabels{} +% \end{macrocode} +% Define list of points for $y$ tics. (Must be a comma separated list +% of decimal numbers.) +% \begin{macrocode} +\define@key{databar}{yticpoints}{% +\def\dtlbar@yticlist{#1}\DTLbaryticstrue\DTLbaryaxistrue} +\let\dtlbar@yticlist=\relax +% \end{macrocode} +% Set the $y$ tick gap: +% \begin{macrocode} +\define@key{databar}{yticgap}{% +\def\dtlbar@yticgap{#1}\DTLbaryticstrue\DTLbaryaxistrue} +\let\dtlbar@yticgap=\relax +% \end{macrocode} +% Define list of labels for $y$ tics. +% \begin{macrocode} +\define@key{databar}{yticlabels}{% +\def\dtlbar@yticlabels{#1}\DTLbaryticstrue\DTLbaryaxistrue} +\let\dtlbar@yticlabels=\relax +% \end{macrocode} +% Define $y$ axis label. +% \begin{macrocode} +\define@key{databar}{ylabel}{% +\def\dtlbar@ylabel{#1}} +\let\dtlbar@ylabel=\relax % \end{macrocode} -%\end{macro} % -%\begin{macro}{\DTLmultibarchart} +%\begin{macro}{\DTLbarchart} %\begin{definition} -% \cs{DTLmultibarchart}\oarg{conditions}\marg{option list}\marg{db name}\marg{assign list} +% \cs{DTLbarchart}\oarg{conditions}\marg{option list}\marg{db name}\marg{assign list} %\end{definition} -% Make a multi-bar chart from data given in data base \meta{db name}, +% 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 the \texttt{variables} key which must be a comma separated -% list of commands, where each command +% 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*{\DTLmultibarchart}[4][\boolean{true}]{% -{\let\dtlbar@variables=\relax +\newcommand*{\DTLbarchart}[4][\boolean{true}]{% +{\let\DTLbarvariable=\relax \let\DTLbarmax=\relax \let\DTLnegextent=\relax -\disable@keys{databar}{variable,upperbarlabel}% +\disable@keys{databar}{variables,multibarlabels,% +uppermultibarlabels,groupgap}% \setkeys{databar}{#2}% -\ifx\dtlbar@variables\relax - \PackageError{databar}{\string\DTLmultibarchart\space missing variables setting}{}% +\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 @@ -20174,16 +20519,14 @@ uppermultibarlabels,groupgap}% % \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 - }% + \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 @@ -20201,12 +20544,10 @@ uppermultibarlabels,groupgap}% \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}% - }% + \expandafter\DTLconverttodecimal\expandafter + {\DTLbarvariable}{\dtl@barvar}% + \let\dtl@old=\DTLnegextent + \DTLmin{\DTLnegextent}{\dtl@old}{\dtl@barvar}% }% \ifx\dtlbar@yticgap\relax \else @@ -20283,44 +20624,13 @@ uppermultibarlabels,groupgap}% \fi \fi % \end{macrocode} -% Calculate the offset for the lower label and number of labels +% Store the width of the bar chart in \cs{DTLbarchartwidth} % \begin{macrocode} -\dtl@xticlabelheight=0pt\relax -\@dtl@tmpcount=0\relax -\@for\dtl@thislabel:=\dtl@multibarlabels\do{% - \advance\@dtl@tmpcount by 1\relax - \settoheight{\dtl@tmplength}{\tikz\expandafter\pgftext\expandafter - [\DTLbarXlabelalign]{\DTLdisplaylowerbarlabel{\dtl@thislabel}};}% - \edef\@dtl@h{\the\dtl@tmplength}% - \settodepth{\dtl@tmplength}{\tikz\expandafter\pgftext\expandafter - [\DTLbarXlabelalign]{\DTLdisplaylowerbarlabel{\dtl@thislabel}};}% - \addtolength{\dtl@tmplength}{\@dtl@h}% - \addtolength{\dtl@tmplength}{\baselineskip}% - \ifdim\dtl@tmplength>\dtl@xticlabelheight - \setlength{\dtl@xticlabelheight}{\dtl@tmplength}% - \fi -} +\edef\DTLbarchartwidth{\expandafter\number\csname dtlrows@#3\endcsname} % \end{macrocode} -% Calculate number of bars per group +% Do the bar chart % \begin{macrocode} -\@dtl@tmpcount=0\relax -\@for\dtl@this:=\dtlbar@variables\do{% - \advance\@dtl@tmpcount by 1\relax -}% -\edef\DTLbargroupwidth{\number\@dtl@tmpcount}% -% \end{macrocode} -% Compute the total width of the bar chart (in terms of -% the $x$ unit vector.) -% \begin{macrocode} -\edef\dtl@n{\expandafter\number\csname dtlrows@#3\endcsname} -\FPmul{\dtl@tmpi}{\dtl@n}{\DTLbargroupwidth} -\FPsub{\dtl@tmpii}{\dtl@n}{1}% -\FPmul{\dtl@tmpii}{\dtl@tmpii}{\dtlbar@groupgap}% -\FPadd{\DTLbarchartwidth}{\dtl@tmpi}{\dtl@tmpii} -% \end{macrocode} -% Do the bar chart -% \begin{macrocode} -\begin{tikzpicture} +\begin{tikzpicture} % \end{macrocode} % Set unit vectors % \begin{macrocode} @@ -20346,51 +20656,24 @@ uppermultibarlabels,groupgap}% % \end{macrocode} % Store the bar number in \cs{@dtl@bar} % \begin{macrocode} -\@dtl@barcount = 1\relax -% \end{macrocode} -% Set the multibar label lists -% \begin{macrocode} -\let\dtl@multibar@labels=\dtl@multibarlabels -\let\dtl@uppermultibar@labels=\dtl@uppermultibarlabels -% \end{macrocode} -% Compute mid point over group -% \begin{macrocode} -\FPmul{\dtl@multimidpt}{\DTLbargroupwidth}{0.5}% -\FPadd{\dtl@multimidpt}{\dtl@multimidpt}{\@dtl@start}% -% \end{macrocode} -% Iterate through each variable -% \begin{macrocode} -\@for\DTLbarvariable:=\dtlbar@variables\do{% -% \end{macrocode} -% Set end point -% \begin{macrocode} -\FPadd{\@dtl@endpt}{\@dtl@start}{1}% +\expandafter\let\expandafter\@dtl@bar + \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname% % \end{macrocode} % Convert variable to decimal % \begin{macrocode} \expandafter\DTLconverttodecimal\expandafter {\DTLbarvariable}{\dtl@variable}% % \end{macrocode} -% Get the current lower label: -% \begin{macrocode} -\dtl@chopfirst\dtl@multibar@labels\dtl@thisbarlabel\dtl@rest -\let\dtl@multibar@labels=\dtl@rest -% \end{macrocode} -% Get the current upper label: -% \begin{macrocode} -\dtl@chopfirst\dtl@uppermultibar@labels\dtl@thisupperbarlabel\dtl@rest -\let\dtl@uppermultibar@labels=\dtl@rest -% \end{macrocode} % Draw bars % \begin{macrocode} \begin{scope} - \expandafter\color\expandafter{\DTLgetbarcolor{\@dtl@barcount}}% + \DTLdocurrentbarcolor \ifDTLverticalbars \fill (\@dtl@start,0) -- (\@dtl@start,\dtl@variable) - -- (\@dtl@endpt,\dtl@variable) -- (\@dtl@endpt,0) -- cycle; + -- (\@dtl@bar,\dtl@variable) -- (\@dtl@bar,0) -- cycle; \else \fill (0,\@dtl@start) -- (\dtl@variable,\@dtl@start) - -- (\dtl@variable,\@dtl@endpt) -- (0,\@dtl@endpt) -- cycle; + -- (\dtl@variable,\@dtl@bar) -- (0,\@dtl@bar) -- cycle; \fi \end{scope} % \end{macrocode} @@ -20401,77 +20684,91 @@ uppermultibarlabels,groupgap}% \expandafter\color\expandafter{\DTLbaroutlinecolor} \ifDTLverticalbars \draw (\@dtl@start,0) -- (\@dtl@start,\dtl@variable) - -- (\@dtl@endpt,\dtl@variable) -- (\@dtl@endpt,0) -- cycle; + -- (\@dtl@bar,\dtl@variable) -- (\@dtl@bar,0) -- cycle; \else \draw (0,\@dtl@start) -- (\dtl@variable,\@dtl@start) - -- (\dtl@variable,\@dtl@endpt) -- (0,\@dtl@endpt) -- cycle; + -- (\dtl@variable,\@dtl@bar) -- (0,\@dtl@bar) -- cycle; \fi \fi \end{scope} % \end{macrocode} -% Calculate mid point -% \begin{macrocode} -\FPadd{\@dtl@midpt}{\@dtl@start}{0.5}% -% \end{macrocode} % Draw lower $x$ labels % \begin{macrocode} \ifDTLverticalbars \edef\dtl@textopt{% at={\noexpand\pgfpointadd - {\noexpand\pgfpointxy{\@dtl@midpt}{0}} + {\noexpand\pgfpointxy{\@dtl@start.5}{0}} {\noexpand\pgfpoint{0pt}{-\noexpand\DTLbarlabeloffset}}}, \DTLbarXlabelalign }% - \edef\DTLstartpt{\noexpand\pgfpointxy{\@dtl@midpt}{0}}% +% \end{macrocode} +% Set \cs{DTLstartpt} to the starting point. +% \begin{macrocode} + \edef\DTLstartpt{\noexpand\pgfpointxy{\@dtl@start.5}{0}}% \else \edef\dtl@textopt{% at={\noexpand\pgfpointadd - {\noexpand\pgfpointxy{0}{\@dtl@midpt}} + {\noexpand\pgfpointxy{0}{\@dtl@start.5}} {\noexpand\pgfpoint{-\noexpand\DTLbarlabeloffset}{0pt}}}, \DTLbarXlabelalign }% - \edef\DTLstartpt{\noexpand\pgfpointxy{0}{\@dtl@midpt}}% +% \end{macrocode} +% Set \cs{DTLstartpt} to the starting point. +% \begin{macrocode} + \edef\DTLstartpt{\noexpand\pgfpointxy{0}{\@dtl@start.5}}% \fi \expandafter\pgftext\expandafter[\dtl@textopt]{% - \DTLdisplaylowermultibarlabel{\dtl@thisbarlabel}} + \DTLdisplaylowerbarlabel{\dtl@barlabel}} % \end{macrocode} % Draw upper $x$ labels % \begin{macrocode} \ifDTLverticalbars +% \end{macrocode} +% Vertical bars +% \begin{macrocode} \expandafter\DTLifnumlt\expandafter{\DTLbarvariable}{0} { \edef\dtl@textopt{% at={\noexpand\pgfpointadd - {\noexpand\pgfpointxy{\@dtl@midpt}{\dtl@variable}} + {\noexpand\pgfpointxy{\@dtl@start.5}{\dtl@variable}} {\noexpand\pgfpoint{0pt}{-\noexpand\DTLbarlabeloffset}}} }% }{% \edef\dtl@textopt{% at={\noexpand\pgfpointadd - {\noexpand\pgfpointxy{\@dtl@midpt}{\dtl@variable}} + {\noexpand\pgfpointxy{\@dtl@start.5}{\dtl@variable}} {\noexpand\pgfpoint{0pt}{\noexpand\DTLbarlabeloffset}}} }% } - \edef\DTLendpt{\noexpand\pgfpointxy{\@dtl@midpt}{\dtl@variable}}% +% \end{macrocode} +% Set \cs{DTLendpt} to the end point. +% \begin{macrocode} + \edef\DTLendpt{\noexpand\pgfpointxy{\@dtl@start.5}{\dtl@variable}}% \else +% \end{macrocode} +% Horizontal bars +% \begin{macrocode} \expandafter\DTLifnumlt\expandafter{\DTLbarvariable}{0} { \edef\dtl@textopt{right, at={\noexpand\pgfpointadd - {\noexpand\pgfpointxy{\dtl@variable}{\@dtl@midpt}} + {\noexpand\pgfpointxy{\dtl@variable}{\@dtl@start.5}} {\noexpand\pgfpoint{-\noexpand\DTLbarlabeloffset}{0pt}}} }% }{% \edef\dtl@textopt{left, at={\noexpand\pgfpointadd - {\noexpand\pgfpointxy{\dtl@variable}{\@dtl@midpt}} + {\noexpand\pgfpointxy{\dtl@variable}{\@dtl@start.5}} {\noexpand\pgfpoint{\noexpand\DTLbarlabeloffset}{0pt}}} }% } - \edef\DTLendpt{\noexpand\pgfpointxy{\dtl@variable}{\@dtl@midpt}}% +% \end{macrocode} +% Set \cs{DTLendpt} to the end point. +% \begin{macrocode} + \edef\DTLendpt{\noexpand\pgfpointxy{\dtl@variable}{\@dtl@start.5}}% \fi \expandafter\pgftext\expandafter[\dtl@textopt]{% - \DTLdisplayuppermultibarlabel{\dtl@thisupperbarlabel}} + \DTLdisplayupperbarlabel{\dtl@upperbarlabel}} % \end{macrocode} % Set the mid point % \begin{macrocode} @@ -20480,38 +20777,11 @@ uppermultibarlabels,groupgap}% % Do every bar hook %\changes{2.0}{2009 February 27}{added \cs{DTLeverybarhook}}% % \begin{macrocode} -\DTLeverybarhook -% \end{macrocode} -% End of loop increment loop variables -% \begin{macrocode} - \FPadd{\@dtl@start}{\@dtl@start}{1}% - \advance\@dtl@barcount by 1\relax -}% -% Draw lower group $x$ labels -% \begin{macrocode} -\setlength{\dtl@tmplength}{\DTLbarlabeloffset}% -\addtolength{\dtl@tmplength}{\dtl@xticlabelheight}% -\ifDTLverticalbars - \edef\dtl@textopt{% - at={\noexpand\pgfpointadd - {\noexpand\pgfpointxy{\dtl@multimidpt}{0}} - {\noexpand\pgfpoint{0pt}{-\noexpand\dtl@tmplength}}}, - \DTLbarXlabelalign - }% -\else - \edef\dtl@textopt{% - at={\noexpand\pgfpointadd - {\noexpand\pgfpointxy{0}{\dtl@multimidpt}} - {\noexpand\pgfpoint{-\noexpand\dtl@tmplength}{0pt}}}, - \DTLbarXlabelalign - }% -\fi - \expandafter\pgftext\expandafter[\dtl@textopt]{% - \DTLdisplaylowerbarlabel{\dtl@barlabel}} + \DTLeverybarhook % \end{macrocode} -% Increment starting position by \cs{dtlbar@groupgap} +% End of loop % \begin{macrocode} - \FPadd{\@dtl@start}{\@dtl@start}{\dtlbar@groupgap}% + \edef\@dtl@start{\number\@dtl@bar}% } % \end{macrocode} % Draw $x$ axis @@ -20608,1648 +20878,2120 @@ uppermultibarlabels,groupgap}% }} % \end{macrocode} %\end{macro} -%\iffalse -% \begin{macrocode} -% -% \end{macrocode} -%\fi -%\iffalse -% \begin{macrocode} -%<*databib.sty> -% \end{macrocode} -%\fi -%\section{databib.sty} -%\label{sec:src:databib} -%\subsection{Package Declaration} -% \begin{macrocode} -\NeedsTeXFormat{LaTeX2e} -\ProvidesPackage{databib}[2009/02/27 v2.0 (NLCT)] -% \end{macrocode} -% Load required packages: +% +%\begin{macro}{\DTLmultibarchart} +%\begin{definition} +% \cs{DTLmultibarchart}\oarg{conditions}\marg{option list}\marg{db name}\marg{assign list} +%\end{definition} +% Make a multi-bar chart from data given in data base \meta{db name}, +% where \meta{assign list} is a comma-separated list of +% \meta{cmd}\texttt{=}\meta{key} pairs. \meta{option list} must +% include the \texttt{variables} key which must be a comma separated +% list of commands, where each command +% is included in \meta{assign list}. The optional argument +% \meta{conditions} is the same as that for \cs{DTLforeach}. % \begin{macrocode} -\RequirePackage{datatool} +\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} -%\subsection{Package Options} -%\begin{macro}{\dtlbib@style} -%The default bib style is stored in \cs{dtlbib@style}. +% 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*{\dtlbib@style}{plain} + \ifx\DTLbarmax\relax + \@sDTLforeach[#1]{#3}{#4}{% + \@for\DTLbarvariable:=\dtlbar@variables\do{% + \expandafter\DTLconverttodecimal\expandafter + {\DTLbarvariable}{\dtl@barvar}% + \ifx\DTLbarmax\relax + \let\DTLbarmax=\dtl@barvar + \else + \let\dtl@old=\DTLbarmax + \FPmax{\DTLbarmax}{\dtl@old}{\dtl@barvar}% + \fi + }% + }% + \ifx\dtlbar@yticgap\relax + \else + \let\dtl@thistick=\dtlbar@yticgap% + \whiledo{\DTLisFPopenbetween{\dtl@thistick}{0}{\DTLbarmax}}{% + \FPadd{\dtl@thistick}{\dtl@thistick}{\dtlbar@yticgap}% + }% + \let\DTLbarmax=\dtl@thistick + \fi + \fi % \end{macrocode} -%\end{macro} -% The \pkgopt[databib]{style} package option sets \cs{dtlbib@style}. +% Compute the bar depth, unless \cs{DTLnegextent} has been +% set. % \begin{macrocode} -\define@choicekey{databib.sty}{style}{plain,abbrv,alpha}{% -\def\dtlbib@style{#1}} + \ifx\DTLnegextent\relax + \def\DTLnegextent{0}% + \@sDTLforeach[#1]{#3}{#4}{% + \@for\DTLbarvariable:=\dtlbar@variables\do{% + \expandafter\DTLconverttodecimal\expandafter + {\DTLbarvariable}{\dtl@barvar}% + \let\dtl@old=\DTLnegextent + \DTLmin{\DTLnegextent}{\dtl@old}{\dtl@barvar}% + }% + }% + \ifx\dtlbar@yticgap\relax + \else + \ifthenelse{\DTLisFPlt{\DTLnegextent}{0}}{% + \edef\dtl@thistick{0}% + \whiledo{\DTLisFPclosedbetween{\dtl@thistick}{\DTLnegextent}{0}}{% + \FPsub{\dtl@thistick}{\dtl@thistick}{\dtlbar@yticgap}% + }% + \let\DTLnegextent=\dtl@thistick + }{}% + \fi + \fi % \end{macrocode} -% Process package options: +% Determine scaling factor % \begin{macrocode} -\ProcessOptionsX + \@dtl@tmpcount=\DTLbarchartlength + \FPsub{\dtl@extent}{\DTLbarmax}{\DTLnegextent}% + \FPdiv{\dtl@unit}{\number\@dtl@tmpcount}{\dtl@extent}% % \end{macrocode} -%\subsection{Loading BBL file} -%\begin{macro}{\DTLloadbbl} -%\begin{definition} -%\cs{DTLloadbib}\oarg{bbl file}\marg{db name}\marg{bib list} -%\end{definition} +% Construct $y$ tick list if required % \begin{macrocode} -\newcommand*{\DTLloadbbl}[3][\jobname.bbl]{% -\bibliographystyle{databib}% -\if@filesw - \immediate\write\@auxout{\string\bibdata{#3}}% -\fi -\DTLnewdb{#2}% -\edef\DTLBIBdbname{#2}% -\@input@{#1}} -% \end{macrocode} -%\end{macro} -%\begin{macro}{\DTLnewbibrow} -% \cs{DTLnewbibrow} adds a new row to the bibliography database. -% (\cs{DTLBIBdbname} must be set prior to use to the name -% of the \sty{datatool} database which must exist. Any check -% to determine its existence should be performed when -% \cs{DTLBIBdbname} is set.) -%\changes{1.03}{2009 January 27}{removed check if database exists} -% \begin{macrocode} -\newcommand*{\DTLnewbibrow}{\@DTLnewrow{\DTLBIBdbname}} -% \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{macrocode} -\newcommand*{\DTLnewbibitem}[2]{% - \@DTLnewdbentry{\DTLBIBdbname}{#1}{#2}} + \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} -%\end{macro} -%\subsection{Predefined text} -%\label{sec:src:bibnames} -%\begin{macro}{\andname} +% Calculate the offset for the lower label and number of labels % \begin{macrocode} -\providecommand*{\andname}{and} +\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} -%\end{macro} -%\begin{macro}{\ofname} +% Calculate number of bars per group % \begin{macrocode} -\providecommand*{\ofname}{of} +\@dtl@tmpcount=0\relax +\@for\dtl@this:=\dtlbar@variables\do{% + \advance\@dtl@tmpcount by 1\relax +}% +\edef\DTLbargroupwidth{\number\@dtl@tmpcount}% % \end{macrocode} -%\end{macro} -%\begin{macro}{\inname} +% Compute the total width of the bar chart (in terms of +% the $x$ unit vector.) % \begin{macrocode} -\providecommand*{\inname}{in} +\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} -%\end{macro} -%\begin{macro}{\etalname} +% Do the bar chart % \begin{macrocode} -\providecommand*{\etalname}{et al.} +\begin{tikzpicture} % \end{macrocode} -%\end{macro} -%\begin{macro}{\editorname} +% Set unit vectors % \begin{macrocode} -\providecommand*{\editorname}{editor} +\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}{\editorsname} +% Begin hook % \begin{macrocode} -\providecommand*{\editorsname}{editors} +\DTLbaratbegintikz % \end{macrocode} -%\end{macro} -%\begin{macro}{\volumename} +% Initialise % \begin{macrocode} -\providecommand*{\volumename}{volume} +\def\@dtl@start{0}% % \end{macrocode} -%\end{macro} -%\begin{macro}{\numbername} +% Iterate through data % \begin{macrocode} -\providecommand*{\numbername}{number} +\@sDTLforeach[#1]{#3}{#4}{% % \end{macrocode} -%\end{macro} -%\begin{macro}{\pagesname} +% Store the bar number in \cs{@dtl@bar} % \begin{macrocode} -\providecommand*{\pagesname}{pages} +\@dtl@barcount = 1\relax % \end{macrocode} -%\end{macro} -%\begin{macro}{\pagename} +% Set the multibar label lists % \begin{macrocode} -\providecommand*{\pagename}{page} +\let\dtl@multibar@labels=\dtl@multibarlabels +\let\dtl@uppermultibar@labels=\dtl@uppermultibarlabels % \end{macrocode} -%\end{macro} -%\begin{macro}{\editionname} +% Compute mid point over group % \begin{macrocode} -\providecommand*{\editionname}{edition} +\FPmul{\dtl@multimidpt}{\DTLbargroupwidth}{0.5}% +\FPadd{\dtl@multimidpt}{\dtl@multimidpt}{\@dtl@start}% % \end{macrocode} -%\end{macro} -%\begin{macro}{\techreportname} +% Iterate through each variable % \begin{macrocode} -\providecommand*{\techreportname}{Technical report} +\@for\DTLbarvariable:=\dtlbar@variables\do{% % \end{macrocode} -%\end{macro} -%\begin{macro}{\mscthesisname} +% Set end point % \begin{macrocode} -\providecommand*{\mscthesisname}{Master's thesis} +\FPadd{\@dtl@endpt}{\@dtl@start}{1}% % \end{macrocode} -%\end{macro} -%\begin{macro}{\phdthesisname} +% Convert variable to decimal % \begin{macrocode} -\providecommand*{\phdthesisname}{PhD thesis} +\expandafter\DTLconverttodecimal\expandafter + {\DTLbarvariable}{\dtl@variable}% % \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} +% Get the current lower label: % \begin{macrocode} -\newcommand*{\DTLbibliography}[2][\boolean{true}]{% - \begin{DTLthebibliography}[#1]{#2}% - \DTLforeachbibentry[#1]{#2}{% - \DTLbibitem \DTLformatbibentry \DTLendbibitem - }% - \end{DTLthebibliography}% -} +\dtl@chopfirst\dtl@multibar@labels\dtl@thisbarlabel\dtl@rest +\let\dtl@multibar@labels=\dtl@rest % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\DTLformatbibentry} -%\begin{definition} -%\cs{DTLformatbibentry} -%\end{definition} -% Formats the current bib entry. +% Get the current upper label: % \begin{macrocode} -\newcommand*{\DTLformatbibentry}{% +\dtl@chopfirst\dtl@uppermultibar@labels\dtl@thisupperbarlabel\dtl@rest +\let\dtl@uppermultibar@labels=\dtl@rest % \end{macrocode} -% Check format for this type is defined. +% Draw bars % \begin{macrocode} - \@ifundefined{DTLformat\DBIBentrytype}% - {% - \PackageError{databib}{Don't know how to format bibliography - entries of type `\DBIBentrytype'}{}% - }% - {% +\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} -% Print information to terminal and log file if in verbose mode. +% Draw outline % \begin{macrocode} - \dtl@message{[\DBIBcitekey]}% +\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} -% Initialise +% Calculate mid point % \begin{macrocode} - \DTLstartsentencefalse\DTLmidsentencefalse\DTLperiodfalse +\FPadd{\@dtl@midpt}{\@dtl@start}{0.5}% % \end{macrocode} -% Format this entry +% Draw lower $x$ labels % \begin{macrocode} - \csname DTLformat\DBIBentrytype\endcsname +\ifDTLverticalbars + \edef\dtl@textopt{% + at={\noexpand\pgfpointadd + {\noexpand\pgfpointxy{\@dtl@midpt}{0}} + {\noexpand\pgfpoint{0pt}{-\noexpand\DTLbarlabeloffset}}}, + \DTLbarXlabelalign }% -} -% \end{macrocode} -%\end{macro} -%\begin{macro}{\DTLendbibitem} -% Hook to add extra information at the end of a bibliography item. -% This does nothing by default. + \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} +% Draw upper $x$ labels % \begin{macrocode} -\newcommand*{\DTLendbibitem}{} +\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}} % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\DTLwidest} -%Define a length to store the widest bib entry label +% Set the mid point % \begin{macrocode} -\newlength\dtl@widest +\def\DTLmidpt{\pgfpointlineattime{0.5}{\DTLstartpt}{\DTLendpt}}% % \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. +% Do every bar hook +%\changes{2.0}{2009 February 27}{added \cs{DTLeverybarhook}}% % \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 -}% -} +\DTLeverybarhook % \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. +% End of loop increment loop variables % \begin{macrocode} -\newcommand*{\DTLforeachbibentry}{% -\@ifstar\@DTLforeachbibentry\@DTLforeachbibentry} + \FPadd{\@dtl@start}{\@dtl@start}{1}% + \advance\@dtl@barcount by 1\relax +}% +% Draw lower group $x$ labels +% \begin{macrocode} +\setlength{\dtl@tmplength}{\DTLbarlabeloffset}% +\addtolength{\dtl@tmplength}{\dtl@xticlabelheight}% +\ifDTLverticalbars + \edef\dtl@textopt{% + at={\noexpand\pgfpointadd + {\noexpand\pgfpointxy{\dtl@multimidpt}{0}} + {\noexpand\pgfpoint{0pt}{-\noexpand\dtl@tmplength}}}, + \DTLbarXlabelalign + }% +\else + \edef\dtl@textopt{% + at={\noexpand\pgfpointadd + {\noexpand\pgfpointxy{0}{\dtl@multimidpt}} + {\noexpand\pgfpoint{-\noexpand\dtl@tmplength}{0pt}}}, + \DTLbarXlabelalign + }% +\fi + \expandafter\pgftext\expandafter[\dtl@textopt]{% + \DTLdisplaylowerbarlabel{\dtl@barlabel}} % \end{macrocode} -%\end{macro} -%\begin{macro}{\@DTLforeachbibentry} -% Unstarred version +% Increment starting position by \cs{dtlbar@groupgap} % \begin{macrocode} -\newcommand*{\@DTLforeachbibentry}[3][\boolean{true}]{% + \FPadd{\@dtl@start}{\@dtl@start}{\dtlbar@groupgap}% +} % \end{macrocode} -% Store database name. +% Draw $x$ axis % \begin{macrocode} - \edef\DBIBname{#2}% +\ifDTLbarxaxis + \ifDTLverticalbars + \expandafter\draw\expandafter[\DTLBarXAxisStyle] + (0,0) -- (\DTLbarchartwidth,0); + \else + \expandafter\draw\expandafter[\DTLBarXAxisStyle] + (0,0) -- (0,\DTLbarchartwidth); + \fi +\fi % \end{macrocode} -% Reset row counter. +% Draw $y$ axis % \begin{macrocode} - \setcounter{DTLbibrow}{0}% +\ifDTLbaryaxis + \ifDTLverticalbars + \expandafter\draw\expandafter[\DTLBarYAxisStyle] + (0,\DTLnegextent) -- (0,\DTLbarmax); + \else + \expandafter\draw\expandafter[\DTLBarYAxisStyle] + (\DTLnegextent,0) -- (\DTLbarmax,0); + \fi +\fi % \end{macrocode} -% Iterate through the database. +% Plot $y$ tick marks if required % \begin{macrocode} - \@DTLforeach{#2}{\DBIBcitekey=CiteKey,\DBIBentrytype=EntryType}% - {% - \dtl@gathervalues{#2}{\dtlcurrentrow}% - \ifthenelse{#1}{\refstepcounter{DTLbibrow}#3}{}% +\ifx\dtlbar@yticlist\relax +\else + \@for\dtl@thistick:=\dtlbar@yticlist\do{% + \ifDTLverticalbars + \pgfpathmoveto{\pgfpointxy{0}{\dtl@thistick}} + \pgfpathlineto{ + \pgfpointadd{\pgfpointxy{0}{\dtl@thistick}} + {\pgfpoint{-\DTLticklength}{0pt}}} + \else + \pgfpathmoveto{\pgfpointxy{\dtl@thistick}{0}} + \pgfpathlineto{ + \pgfpointadd{\pgfpointxy{\dtl@thistick}{0}} + {\pgfpoint{0pt}{-\DTLticklength}}} + \fi + \pgfusepath{stroke} + \ifx\dtlbar@yticlabels\relax + \FPround{\dtl@thislabel}{\dtl@thistick} + {\c@DTLbarroundvar}% + \else + \dtl@chopfirst\dtlbar@yticlabels\dtl@thislabel\dtl@rest + \let\dtlbar@yticlabels=\dtl@rest + \fi + \ifDTLverticalbars + \edef\dtl@textopt{\DTLbarYticklabelalign,% + at={\noexpand\pgfpointadd + {\noexpand\pgfpointxy{0}{\dtl@thistick}} + {\noexpand\pgfpoint{-\noexpand\DTLticklabeloffset}{0pt}}, + }}% + \else + \edef\dtl@textopt{\DTLbarYticklabelalign, + at={\noexpand\pgfpointadd + {\noexpand\pgfpointxy{\dtl@thistick}{0}} + {\noexpand\pgfpoint{0pt}{-\noexpand\DTLticklabeloffset}} + }}% + \fi + \expandafter\pgftext\expandafter[\dtl@textopt]{% + \DTLbardisplayYticklabel{\dtl@thislabel}} }% -} +\fi % \end{macrocode} -%\end{macro} -%\begin{macro}{\@sDTLforeachbibentry} -% Starred version +% Plot the $y$ label if required % \begin{macrocode} -\newcommand*{\@sDTLforeachbibentry}[3][\boolean{true}]{% +\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} -% Store database name. +% Finish bar chart % \begin{macrocode} - \edef\DBIBname{#2}% +\DTLbaratendtikz +\end{tikzpicture} +\fi +}} % \end{macrocode} -% Reset row counter. +%\end{macro} +%\iffalse % \begin{macrocode} - \setcounter{DTLbibrow}{0}% +% % \end{macrocode} -% Iterate through the database (read only). +%\fi +%\iffalse % \begin{macrocode} - \@sDTLforeach{#2}{\DBIBcitekey=CiteKey,\DBIBentrytype=EntryType}% - {% - \dtl@gathervalues{#2}{\dtlcurrentrow}% - \ifthenelse{#1}{\refstepcounter{DTLbibrow}#3}{}% - }% -} +%<*databib.sty> % \end{macrocode} -%\end{macro} -% -%The counter \counterfmt{DTLbibrow} keeps track of the current -%row in the body of \cs{DTLforeachbibentry}. (You can't rely on -%\counterfmt{DTLrowi}, \counterfmt{DTLrowii} and -% \counterfmt{DTLrowiii}, as \cs{DTLforeachbibentry} pass the -% conditions to the optional argument of \cs{DTLforeach}, but -% instead uses \cs{ifthenelse}, which means that \counterfmt{DTLrowi} -% etc will be incremented, even when the given condition is not met.) +%\fi +%\section{databib.sty} +%\label{sec:src:databib} +%\subsection{Package Declaration} % \begin{macrocode} -\newcounter{DTLbibrow} +\NeedsTeXFormat{LaTeX2e} +\ProvidesPackage{databib}[2009/10/22 v2.01 (NLCT)] % \end{macrocode} -% Keep \sty{hyperref} happy: +% Load required packages: % \begin{macrocode} -\def\theHDTLbibrow{\theHDTLrow.bib.\arabic{DTLbibrow}}% +\RequirePackage{datatool} % \end{macrocode} -% -%\begin{macro}{\DTLbibfield} -%\begin{definition} -%\cs{DTLbibfield}\marg{field name} -%\end{definition} -% Gets the value assigned to the field \meta{field name} for -% the current row of \cs{DTLforeachbibentry}. (Doesn't check if -% the field exists, or if it is being used within -% \cs{DTLforeachbibentry}.) +%\subsection{Package Options} +%\begin{macro}{\dtlbib@style} +%The default bib style is stored in \cs{dtlbib@style}. % \begin{macrocode} -\newcommand*{\DTLbibfield}[1]{\csname @dtl@key@#1\endcsname} +\newcommand*{\dtlbib@style}{plain} % \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}. +% The \pkgopt[databib]{style} package option sets \cs{dtlbib@style}. % \begin{macrocode} -\newcommand*{\DTLifbibfieldexists}[3]{% -\@ifundefined{@dtl@key@#1}{#3}{% -\expandafter\DTLifnull\csname @dtl@key@#1\endcsname -{#3}{#2}}} +\define@choicekey{databib.sty}{style}{plain,abbrv,alpha}{% +\def\dtlbib@style{#1}} % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\DTLifanybibfieldexists} +% Process package options: +% \begin{macrocode} +\ProcessOptionsX +% \end{macrocode} +%\subsection{Loading BBL file} +%\begin{macro}{\DTLloadbbl} %\begin{definition} -%\cs{DTLifanybibfieldexists}\marg{list of field name}\marg{true part}\marg{false -%part} +%\cs{DTLloadbib}\oarg{bbl file}\marg{db name}\marg{bib list} %\end{definition} -% Determines whether any of the listed fields exist for the current -% row of \cs{DTLforeachbibentry}. % \begin{macrocode} -\newcommand*{\DTLifanybibfieldexists}[3]{% -\@for\dtl@thisfield:=#1\do{% -\@ifundefined{@dtl@key@\dtl@thisfield}{}{% -\expandafter\DTLifnull\csname @dtl@key@\dtl@thisfield\endcsname -{}{% -\@endfortrue}}}% -\if@endfor - #2% -\else - #3% +\newcommand*{\DTLloadbbl}[3][\jobname.bbl]{% +\bibliographystyle{databib}% +\if@filesw + \immediate\write\@auxout{\string\bibdata{#3}}% \fi -\@endforfalse -} +\DTLnewdb{#2}% +\edef\DTLBIBdbname{#2}% +\@input@{#1}} % \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}{\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} -\newif\ifDTLperiod +\newcommand*{\DTLnewbibrow}{\@DTLnewrow{\DTLBIBdbname}} % \end{macrocode} %\end{macro} -%\begin{macro}{\DTLcheckendsperiod} +%\begin{macro}{\DTLnewbibitem} %\begin{definition} -%\cs{DTLcheckendperiod}\marg{string} +%\cs{DTLnewbibitem}\marg{key}\marg{value} %\end{definition} -% Checks if \meta{string} ends with a full stop. This sets -% \cs{ifDTLperiod}. +% Adds a new database entry with the given key and value. +%\changes{1.03}{2009 January 27}{removed check if database exists} % \begin{macrocode} -\newcommand*{\DTLcheckendsperiod}[1]{% -\dtl@checkendsperiod#1\@nil\relax} +\newcommand*{\DTLnewbibitem}[2]{% + \@DTLnewdbentry{\DTLBIBdbname}{#1}{#2}} % \end{macrocode} +%\end{macro} +%\subsection{Predefined text} +%\label{sec:src:bibnames} +%\begin{macro}{\andname} % \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}% -} +\providecommand*{\andname}{and} % \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}{\ofname} % \begin{macrocode} -\newcommand*{\DTLcheckbibfieldendsperiod}[1]{% -\protected@edef\@dtl@tmp{\DTLbibfield{#1}}% -\expandafter\DTLcheckendsperiod\expandafter{\@dtl@tmp}} +\providecommand*{\ofname}{of} % \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}{\inname} % \begin{macrocode} -\newif\ifDTLmidsentence +\providecommand*{\inname}{in} % \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}{\etalname} % \begin{macrocode} -\newif\ifDTLstartsentence +\providecommand*{\etalname}{et al.} % \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}{\editorname} % \begin{macrocode} -\newcommand*{\DTLaddperiod}{\DTLmidsentencefalse\DTLperiodfalse -\DTLstartsentencetrue -\ifDTLperiod\else.\fi} +\providecommand*{\editorname}{editor} % \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}{\editorsname} % \begin{macrocode} -\newcommand*{\DTLaddcomma}{, \DTLmidsentencetrue -\DTLperiodfalse\DTLstartsentencefalse} +\providecommand*{\editorsname}{editors} % \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}{\volumename} % \begin{macrocode} -\newcommand*{\DTLstartsentencespace}{% -\ifDTLstartsentence\spacefactor=\sfcode`\.\relax\space -\fi\DTLstartsentencefalse} -% \end{macrocode} +\providecommand*{\volumename}{volume} +% \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}{\numbername} % \begin{macrocode} -\newcommand*{\DTLtwoand}{\ \andname\ } +\providecommand*{\numbername}{number} % \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}{\pagesname} % \begin{macrocode} -\newcommand*{\DTLandlast}{, \andname\ } +\providecommand*{\pagesname}{pages} % \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}{\pagename} % \begin{macrocode} -\newcommand*{\DTLandnotlast}{, } +\providecommand*{\pagename}{page} % \end{macrocode} %\end{macro} -%\begin{macro}{\dtl@authorcount} -% Define a count register to keep track of the number of authors: +%\begin{macro}{\editionname} % \begin{macrocode} -\newcount\@dtl@authorcount +\providecommand*{\editionname}{edition} % \end{macrocode} %\end{macro} -% The counter \counterfmt{DTLmaxauthors} indicates the maximum number of -% author names to display, if there are more than that number, -% \cs{etalname} is used. +%\begin{macro}{\techreportname} % \begin{macrocode} -\newcounter{DTLmaxauthors} -\setcounter{DTLmaxauthors}{10} +\providecommand*{\techreportname}{Technical report} % \end{macrocode} -%\begin{macro}{\DTLformatauthorlist} -% Format a list of author names (the list is stored in -% \cs{@dtl@key@Author}): +%\end{macro} +%\begin{macro}{\mscthesisname} % \begin{macrocode} -\newcommand*{\DTLformatauthorlist}{% -\DTLifbibfieldexists{Author}{% -\DTLstartsentencespace -\@dtl@authorcount=0\relax -\@for\@dtl@author:=\@dtl@key@Author\do{% -\advance\@dtl@authorcount by 1\relax}% -\@dtl@tmpcount=0\relax -\ifnum\@dtl@authorcount>\c@DTLmaxauthors -{% - \@for\@dtl@author:=\@dtl@key@Author\do{% - \advance\@dtl@tmpcount by 1\relax - \ifnum\@dtl@tmpcount=1\relax - \expandafter\DTLformatauthor\@dtl@author - \else - \ifnum\@dtl@tmpcount>\c@DTLmaxauthors - \DTLandnotlast \etalname - \expandafter\DTLcheckendsperiod\expandafter{\etalname}% - \@endfortrue - \else - \DTLandnotlast \expandafter\DTLformatauthor\@dtl@author - \fi - \fi - }% -}% -\else - \@for\@dtl@author:=\@dtl@key@Author\do{% - \advance\@dtl@tmpcount by 1\relax - \ifnum\@dtl@tmpcount=1\relax - \expandafter\DTLformatauthor\@dtl@author - \else - \ifnum\@dtl@tmpcount=\@dtl@authorcount - \ifnum\@dtl@authorcount=2\relax - \DTLtwoand - \else - \DTLandlast - \fi - \expandafter\DTLformatauthor\@dtl@author - \else - \DTLandnotlast \expandafter\DTLformatauthor\@dtl@author - \fi - \fi - }% -\fi -}{}% -} +\providecommand*{\mscthesisname}{Master's thesis} % \end{macrocode} %\end{macro} -% The counter \counterfmt{DTLmaxeditors} indicates the maximum number of -% editor names to display, if there are more than that number, -% \cs{etalname} is used. +%\begin{macro}{\phdthesisname} % \begin{macrocode} -\newcounter{DTLmaxeditors} -\setcounter{DTLmaxeditors}{10} +\providecommand*{\phdthesisname}{PhD thesis} % \end{macrocode} +%\end{macro} % -%\begin{macro}{\DTLformateditorlist} -% Format a list of editor names (the list is stored in -% \cs{@dtl@key@Editor}): +% +%\subsection{Displaying the bibliography} +%\label{sec:src:displaybib} +%\begin{definition} +%\cs{DTLbibliography}\marg{bib dbname} +%\end{definition} +% Displays the bibliography for the database \meta{bib dbname} +% which must have previously been loaded using +% \cs{DTLloadbbl}. +%\begin{macro}{\DTLbibliography} % \begin{macrocode} -\newcommand*{\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 +\newcommand*{\DTLbibliography}[2][\boolean{true}]{% + \begin{DTLthebibliography}[#1]{#2}% + \DTLforeachbibentry[#1]{#2}{% + \DTLbibitem \DTLformatbibentry \DTLendbibitem }% -\fi -, -\ifnum\@dtl@authorcount=1\relax - \editorname - \expandafter\DTLcheckendsperiod\expandafter{\editorname}% -\else - \editorsname - \expandafter\DTLcheckendsperiod\expandafter{\editorsname}% -\fi -}{}% + \end{DTLthebibliography}% } % \end{macrocode} %\end{macro} -%\begin{macro}{\DTLformatsurnameonly} +% +%\begin{macro}{\DTLformatbibentry} %\begin{definition} -%\cs{DTLformatsurnameonly}\marg{von part}\marg{surname}\marg{jr -%part}\marg{forenames} +%\cs{DTLformatbibentry} %\end{definition} -% This is used when only the surname should be displayed. (The -% final argument, \meta{forenames}, is ignored.) +% Formats the current bib entry. % \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*{\DTLformatbibentry}{% +% \end{macrocode} +% Check format for this type is defined. +% \begin{macrocode} + \@ifundefined{DTLformat\DBIBentrytype}% + {% + \PackageError{databib}{Don't know how to format bibliography + entries of type `\DBIBentrytype'}{}% + }% + {% +% \end{macrocode} +% Print information to terminal and log file if in verbose mode. +% \begin{macrocode} + \dtl@message{[\DBIBcitekey]}% +% \end{macrocode} +% Initialise +% \begin{macrocode} + \DTLstartsentencefalse\DTLmidsentencefalse\DTLperiodfalse +% \end{macrocode} +% Format this entry +% \begin{macrocode} + \csname DTLformat\DBIBentrytype\endcsname + }% } % \end{macrocode} %\end{macro} -% -%\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}{\DTLendbibitem} +% Hook to add extra information at the end of a bibliography item. +% This does nothing by default. % \begin{macrocode} -\newcommand*{\DTLformatforenames}[1]{% -\DTLstartsentencespace -#1% -\DTLcheckendsperiod{#1}} +\newcommand*{\DTLendbibitem}{} % \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}{\DTLwidest} +%Define a length to store the widest bib entry label % \begin{macrocode} -\newcommand*{\DTLformatabbrvforenames}[1]{% -\DTLstartsentencespace -\DTLstoreinitials{#1}{\@dtl@tmp}\@dtl@tmp -\expandafter\DTLcheckendsperiod\expandafter{\@dtl@tmp}} +\newlength\dtl@widest % \end{macrocode} %\end{macro} % -%\begin{macro}{\DTLformatvon} +%\begin{macro}{\DTLcomputewidestbibentry} %\begin{definition} -%\cs{DTLformatvon}\marg{von part} +%\cs{DTLcomputewidestbibentry}\marg{conditions}\marg{db +%name}\marg{bib label}\marg{cmd} %\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. +%Computes the widest bibliography entry over all entries satisfying +%\meta{condition} for the database called \meta{db name}, where +% the bibliography label is formated according to \meta{bib label} and +% stores the result in \meta{cmd} which must be a command name. % \begin{macrocode} -\newcommand*{\DTLformatvon}[1]{% -\DTLstartsentencespace -\def\@dtl@tmp{#1}% -\ifx\@dtl@tmp\@empty -\else - #1~% +\newcommand*{\DTLcomputewidestbibentry}[4]{% +\dtl@widest=0pt\relax +\let#4=\@empty +\DTLforeachbibentry[#1]{#2}{% +\settowidth{\dtl@tmplength}{#3}% +\ifdim\dtl@tmplength>\dtl@widest\relax + \dtl@widest=\dtl@tmplength + \protected@edef#4{#3}% \fi +}% } % \end{macrocode} %\end{macro} % -%\begin{macro}{\DTLformatsurname} +%\begin{macro}{\DTLforeachbibentry} %\begin{definition} -%\cs{DTLformatsurname}\marg{surname} +%\cs{DTLforeachbibentry}\oarg{condition}\marg{db name}\marg{text} %\end{definition} -% The format of an author/editor's surname. +%\begin{definition} +%\cs{DTLforeachbibentry*}\oarg{condition}\marg{db name}\marg{text} +%\end{definition} +% Iterates through the database called \meta{db name} and does +% \meta{text} if \meta{condition} is met. As with +% \cs{DTLforeach}, the starred version is read only. % \begin{macrocode} -\newcommand*{\DTLformatsurname}[1]{% -\DTLstartsentencespace -#1\DTLcheckendsperiod{#1}} +\newcommand*{\DTLforeachbibentry}{% +\@ifstar\@DTLforeachbibentry\@DTLforeachbibentry} % \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{macro}{\@DTLforeachbibentry} +% Unstarred version % \begin{macrocode} -\newcommand*{\DTLformatjr}[1]{% -\DTLstartsentencespace -\def\@dtl@tmp{#1}% -\ifx\@dtl@tmp\@empty -\else - , #1\DTLcheckendsperiod{#1}% -\fi +\newcommand*{\@DTLforeachbibentry}[3][\boolean{true}]{% +% \end{macrocode} +% Store database name. +% \begin{macrocode} + \edef\DBIBname{#2}% +% \end{macrocode} +% Reset row counter. +% \begin{macrocode} + \setcounter{DTLbibrow}{0}% +% \end{macrocode} +% Iterate through the database. +% \begin{macrocode} + \@DTLforeach{#2}{\DBIBcitekey=CiteKey,\DBIBentrytype=EntryType}% + {% + \dtl@gathervalues{#2}{\dtlcurrentrow}% + \ifthenelse{#1}{\refstepcounter{DTLbibrow}#3}{}% + }% } % \end{macrocode} %\end{macro} -% -%\begin{macro}{\DTLformatcrossrefeditor} -% Format cross reference editors: +%\begin{macro}{\@sDTLforeachbibentry} +% Starred version % \begin{macrocode} -\newcommand*{\DTLformatcrossrefeditor}{% -\DTLifbibfieldexists{Editor}{% -\DTLstartsentencespace -\@dtl@authorcount=0\relax -\@for\@dtl@author:=\@dtl@key@Editor\do{% -\advance\@dtl@authorcount by 1\relax}% -{\@dtl@tmpcount=0\relax -\@for\@dtl@author:=\@dtl@key@Editor\do{% -\ifnum\@dtl@authorcount=1\relax - \expandafter\DTLformatsurnameonly\@dtl@author -\else - \advance\@dtl@tmpcount by 1\relax - \ifnum\@dtl@tmpcount=1\relax - \expandafter\DTLformatsurnameonly\@dtl@author - \else - \ifnum\@dtl@authorcount=2\relax - \ \andname\ \expandafter\DTLformatsurnameonly\@dtl@author - \else - \ \etalname - \expandafter\DTLcheckendsperiod\expandafter{\etalname} - \fi - \@endfortrue - \fi -\fi -}}% -}{}% +\newcommand*{\@sDTLforeachbibentry}[3][\boolean{true}]{% +% \end{macrocode} +% Store database name. +% \begin{macrocode} + \edef\DBIBname{#2}% +% \end{macrocode} +% Reset row counter. +% \begin{macrocode} + \setcounter{DTLbibrow}{0}% +% \end{macrocode} +% Iterate through the database (read only). +% \begin{macrocode} + \@sDTLforeach{#2}{\DBIBcitekey=CiteKey,\DBIBentrytype=EntryType}% + {% + \dtl@gathervalues{#2}{\dtlcurrentrow}% + \ifthenelse{#1}{\refstepcounter{DTLbibrow}#3}{}% + }% } % \end{macrocode} %\end{macro} % -%\begin{macro}{\DTLformatvolnumpages} -% Format volume, number and pages (of an article). +%\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} -\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}{}% -} +\newcounter{DTLbibrow} +% \end{macrocode} +%\end{counter} +%\begin{macro}{\theHDTLbibrow} +% Keep \sty{hyperref} happy: +% \begin{macrocode} +\def\theHDTLbibrow{\theHDTLrow.bib.\arabic{DTLbibrow}}% % \end{macrocode} %\end{macro} % -%\begin{macro}{\DTLformatbvolume} -% Format book volume. +%\begin{macro}{\DTLbibfield} +%\begin{definition} +%\cs{DTLbibfield}\marg{field name} +%\end{definition} +% Gets the value assigned to the field \meta{field name} for +% the current row of \cs{DTLforeachbibentry}. (Doesn't check if +% the field exists, or if it is being used within +% \cs{DTLforeachbibentry}.) % \begin{macrocode} -\newcommand*{\DTLformatbvolume}{% -\DTLifbibfieldexists{Volume}{% -\ifDTLmidsentence - \volumename -\else - \DTLstartsentencespace - \expandafter\MakeUppercase\volumename -\fi -~\DTLbibfield{Volume}% -\DTLifbibfieldexists{Series}{\ \ofname\ -{\em\DTLbibfield{Series}}\DTLcheckbibfieldendsperiod{Series}}{% -\DTLcheckbibfieldendsperiod{Volume}}% -}{}} +\newcommand*{\DTLbibfield}[1]{\csname @dtl@key@#1\endcsname} % \end{macrocode} %\end{macro} % -%\begin{macro}{\DTLformatchapterpages} -% Format chapter and pages: +%\begin{macro}{\DTLifbibfieldexists} +%\begin{definition} +%\cs{DTLifbibfieldexists}\marg{field name}\marg{true part}\marg{false +%part} +%\end{definition} +%Determines whether the given field name exists for the current +% row of \cs{DTLforeachbibentry}. % \begin{macrocode} -\newcommand*{\DTLformatchapterpages}{% -\DTLifbibfieldexists{Chapter}{% -\DTLifbibfieldexists{Type}{% -\DTLstartsentencespace -\DTLbibfield{Type}}{% -\DTLstartsentencespace -\chaptername}~\DTLbibfield{Chapter}% -\DTLifbibfieldexists{Pages}{\DTLaddcomma}{% -\DTLcheckbibfieldendsperiod{Chapter}}}{}% -\DTLstartsentencespace -\DTLformatpages} +\newcommand*{\DTLifbibfieldexists}[3]{% +\@ifundefined{@dtl@key@#1}{#3}{% +\expandafter\DTLifnull\csname @dtl@key@#1\endcsname +{#3}{#2}}} % \end{macrocode} %\end{macro} % -%\begin{macro}{\DTLformatpages} -% Format pages: +%\begin{macro}{\DTLifanybibfieldexists} +%\begin{definition} +%\cs{DTLifanybibfieldexists}\marg{list of field name}\marg{true part}\marg{false +%part} +%\end{definition} +% Determines whether any of the listed fields exist for the current +% row of \cs{DTLforeachbibentry}. % \begin{macrocode} -\newcommand*{\DTLformatpages}{% -\DTLifbibfieldexists{Pages}{% -\DTLstartsentencespace -\protected@edef\@dtl@pages{0\DTLbibfield{Pages}}% -\DTLifnumerical{\@dtl@pages}{\pagename}{\pagesname}~% -\DTLbibfield{Pages}\DTLcheckbibfieldendsperiod{Pages}}{}% +\newcommand*{\DTLifanybibfieldexists}[3]{% +\@for\dtl@thisfield:=#1\do{% +\@ifundefined{@dtl@key@\dtl@thisfield}{}{% +\expandafter\DTLifnull\csname @dtl@key@\dtl@thisfield\endcsname +{}{% +\@endfortrue}}}% +\if@endfor + #2% +\else + #3% +\fi +\@endforfalse } % \end{macrocode} %\end{macro} % -%\begin{macro}{\DTLformatnumberseries} -% Format number and series (of book) +%\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} -\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}}{}}% -}% -} +\newif\ifDTLperiod % \end{macrocode} %\end{macro} -%\begin{macro}{\DTLformatbookcrossref} -% Format a book cross reference. +%\begin{macro}{\DTLcheckendsperiod} +%\begin{definition} +%\cs{DTLcheckendperiod}\marg{string} +%\end{definition} +% Checks if \meta{string} ends with a full stop. This sets +% \cs{ifDTLperiod}. % \begin{macrocode} -\newcommand*{\DTLformatbookcrossref}{% -\DTLifbibfieldexists{Volume}{% -\ifDTLmidsentence - \volumename +\newcommand*{\DTLcheckendsperiod}[1]{% +\dtl@checkendsperiod#1\@nil\relax} +% \end{macrocode} +% \begin{macrocode} +\def\dtl@checkendsperiod#1#2{% +\def\@dtl@argi{#1}\def\@dtl@argii{#2}% +\def\@dtl@period{.}% +\ifx\@dtl@argi\@nnil + \global\DTLperiodfalse + \let\@dtl@donext=\relax \else - \DTLstartsentencespace - \expandafter\MakeUppercase\volumename + \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 -~\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}% +\@dtl@donext{#2}% } % \end{macrocode} %\end{macro} -%\begin{macro}{\DTLformatincollproccrossref} -% Format `incollections' cross reference. +%\begin{macro}{\DTLcheckbibfieldendsperiod} +%\begin{definition} +%\cs{DTLcheckbibfieldendperiod}\marg{label} +%\end{definition} +% Checks if the bib field \meta{label} ends with a full stop. +% This sets \cs{ifDTLperiod}. % \begin{macrocode} -\newcommand*{\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}% -} +\newcommand*{\DTLcheckbibfieldendsperiod}[1]{% +\protected@edef\@dtl@tmp{\DTLbibfield{#1}}% +\expandafter\DTLcheckendsperiod\expandafter{\@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{macro}{\ifDTLmidsentence} +%\begin{definition} +%\cs{ifDTLmidsentence} +%\end{definition} +% Determine whether we are in the middle +% of a sentence. % \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}% -}{}}} +\newif\ifDTLmidsentence % \end{macrocode} %\end{macro} -%\begin{macro}{\DTLformatarticlecrossref} -% Format article cross reference. +%\begin{macro}{\ifDTLstartsentence} +%\begin{definition} +%\cs{ifDTLstartsentence} +%\end{definition} +% Determine whether we are at the start +% of a sentence. % \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}% -} +\newif\ifDTLstartsentence % \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{macro}{\DTLaddperiod} %\begin{definition} -%\cs{DTLbibfieldexists}\marg{field label} +%\cs{DTLaddperiod} %\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} +%Adds a full stop and sets \cs{DTLmidsentencefalse}, +%\cs{DTLstartsentencetrue} and +%\cs{DTLperiodfalse}. % \begin{macrocode} -\newcommand*{\dtl@testbibfieldexists}[1]{% -\DTLifbibfieldexists{#1}{\@dtl@conditiontrue}{\@dtl@conditionfalse}} +\newcommand*{\DTLaddperiod}{\DTLmidsentencefalse\DTLperiodfalse +\DTLstartsentencetrue +\ifDTLperiod\else.\fi} % \end{macrocode} %\end{macro} % -%\begin{macro}{\DTLbibfieldiseq} +%\begin{macro}{\DTLaddcomma} %\begin{definition} -%\cs{DTLbibfieldiseq}\marg{field label}\marg{value} +%\cs{DTLaddcomma} %\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.) +%Adds a comma and sets \cs{DTLmidsentencetrue}, \cs{DTLperiodfalse} +%and \cs{DTLstartsentencefalse} % \begin{macrocode} -\newcommand*{\DTLbibfieldiseq}[2]{% -\TE@throw\noexpand\dtl@testbibfieldiseq{#1}{#2}% -\noexpand\if@dtl@condition} +\newcommand*{\DTLaddcomma}{, \DTLmidsentencetrue +\DTLperiodfalse\DTLstartsentencefalse} % \end{macrocode} %\end{macro} -%\begin{macro}{\dtl@testbibfieldiseq} +% +%\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*{\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} +\newcommand*{\DTLstartsentencespace}{% +\ifDTLstartsentence\spacefactor=\sfcode`\.\relax\space +\fi\DTLstartsentencefalse} +% \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{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*{\DTLbibfieldislt}[2]{% -\TE@throw\noexpand\dtl@testbibfieldislt{#1}{#2}% -\noexpand\if@dtl@condition} +\newcommand*{\DTLtwoand}{\ \andname\ } % \end{macrocode} %\end{macro} -%\begin{macro}{\dtl@testbibfieldislt} +%\begin{macro}{\DTLandlast} +% In a list of author (or editor) names, the text between the +% penultimate and last name is given by \cs{DTLandlast}: % \begin{macrocode} -\newcommand*{\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}% -} +\newcommand*{\DTLandlast}{, \andname\ } % \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{macro}{\DTLandnotlast} +% In a list of author (or editor) names, the text between the +% names (except the penultimate and last name) is given by +% \cs{DTLandnotlast}: % \begin{macrocode} -\newcommand*{\DTLbibfieldisle}[2]{% -\TE@throw\noexpand\dtl@testbibfieldisle{#1}{#2}% -\noexpand\if@dtl@condition} +\newcommand*{\DTLandnotlast}{, } % \end{macrocode} %\end{macro} -%\begin{macro}{\dtl@testbibfieldisle} +%\begin{macro}{\dtl@authorcount} +% Define a count register to keep track of the number of authors: % \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}% -} +\newcount\@dtl@authorcount % \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{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} -\newcommand*{\DTLbibfieldisgt}[2]{% -\TE@throw\noexpand\dtl@testbibfieldisgt{#1}{#2}% -\noexpand\if@dtl@condition} +\newcounter{DTLmaxauthors} +\setcounter{DTLmaxauthors}{10} % \end{macrocode} -%\end{macro} -%\begin{macro}{\dtl@testbibfieldisgt} +%\end{counter} +%\begin{macro}{\DTLformatauthorlist} +% Format a list of author names (the list is stored in +% \cs{@dtl@key@Author}): % \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 +\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 -}{% -\@dtl@conditionfalse}% +}{}% } % \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{macrocode} +\newcounter{DTLmaxeditors} +\setcounter{DTLmaxeditors}{10} +% \end{macrocode} +%\end{counter} % -%\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{macro}{\DTLformateditorlist} +% Format a list of editor names (the list is stored in +% \cs{@dtl@key@Editor}): % \begin{macrocode} -\newcommand*{\DTLbibfieldisge}[2]{% -\TE@throw\noexpand\dtl@testbibfieldisge{#1}{#2}% -\noexpand\if@dtl@condition} +\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@testbibfieldisge} +%\begin{macro}{\DTLformatsurnameonly} +%\begin{definition} +%\cs{DTLformatsurnameonly}\marg{von part}\marg{surname}\marg{jr +%part}\marg{forenames} +%\end{definition} +% This is used when only the surname should be displayed. (The +% final argument, \meta{forenames}, is ignored.) % \begin{macrocode} -\newcommand*{\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 +\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 - \@dtl@conditionfalse + , #3% + \DTLcheckendsperiod{#3}% \fi -}{% -\@dtl@conditionfalse}% } % \end{macrocode} %\end{macro} % -%\begin{macro}{\DTLbibfieldcontains} +%\begin{macro}{\DTLformatforenames} %\begin{definition} -%\cs{DTLbibfieldcontains}\marg{field label}\marg{sub string} +%\cs{DTLformatforenames}\marg{forenames} %\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.) +% The format of an author/editor's forenames. If the forenames +% occur at the start of sentence, a new sentence space is added. +% The argument is checked to determine whether it ends with a +% full stop (sometimes the forenames may include initials.) % \begin{macrocode} -\newcommand*{\DTLbibfieldcontains}[2]{% -\TE@throw\noexpand\dtl@testbibfieldcontains{#1}{#2}% -\noexpand\if@dtl@condition} +\newcommand*{\DTLformatforenames}[1]{% +\DTLstartsentencespace +#1% +\DTLcheckendsperiod{#1}} % \end{macrocode} %\end{macro} -%\begin{macro}{\dtl@testbibfieldcontains} +% +%\begin{macro}{\DTLformatabbrvforenames} +%\begin{definition} +%\cs{DTLformatabbrvforenames}\marg{forenames} +%\end{definition} +% The format of an author/editor's abbreviated forenames. The initials +% may or may not end in a full stop depending on the commands +% governing the format of \cs{DTLstoreinitials}, so the initials +% need to be check using \cs{DTLcheckendsperiod}. % \begin{macrocode} -\newcommand*{\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}} +\newcommand*{\DTLformatabbrvforenames}[1]{% +\DTLstartsentencespace +\DTLstoreinitials{#1}{\@dtl@tmp}\@dtl@tmp +\expandafter\DTLcheckendsperiod\expandafter{\@dtl@tmp}} % \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{macro}{\DTLformatvon} +%\begin{definition} +%\cs{DTLformatvon}\marg{von part} +%\end{definition} +% The format of the ``von'' part. This does nothing if the argument +% is empty, otherwise it does the argument followed by a +% non-breakable space. +% \begin{macrocode} +\newcommand*{\DTLformatvon}[1]{% +\DTLstartsentencespace +\def\@dtl@tmp{#1}% +\ifx\@dtl@tmp\@empty +\else + #1~% +\fi +} +% \end{macrocode} +%\end{macro} % -%\begin{environment}{DTLthebibliography} -% How to format the entire bibliography: +%\begin{macro}{\DTLformatsurname} +%\begin{definition} +%\cs{DTLformatsurname}\marg{surname} +%\end{definition} +% The format of an author/editor's surname. % \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}} +\newcommand*{\DTLformatsurname}[1]{% +\DTLstartsentencespace +#1\DTLcheckendsperiod{#1}} % \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}. +%\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*{\DTLmonthname}[1]{% -\dtl@monthname{#1}} +\newcommand*{\DTLformatjr}[1]{% +\DTLstartsentencespace +\def\@dtl@tmp{#1}% +\ifx\@dtl@tmp\@empty +\else + , #1\DTLcheckendsperiod{#1}% +\fi +} % \end{macrocode} %\end{macro} -%\begin{macro}{\dtl@monthname} -% Full month names: +% +%\begin{macro}{\DTLformatcrossrefeditor} +% Format cross reference editors: % \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} +\newcommand*{\DTLformatcrossrefeditor}{% +\DTLifbibfieldexists{Editor}{% +\DTLstartsentencespace +\@dtl@authorcount=0\relax +\@for\@dtl@author:=\@dtl@key@Editor\do{% +\advance\@dtl@authorcount by 1\relax}% +{\@dtl@tmpcount=0\relax +\@for\@dtl@author:=\@dtl@key@Editor\do{% +\ifnum\@dtl@authorcount=1\relax + \expandafter\DTLformatsurnameonly\@dtl@author +\else + \advance\@dtl@tmpcount by 1\relax + \ifnum\@dtl@tmpcount=1\relax + \expandafter\DTLformatsurnameonly\@dtl@author + \else + \ifnum\@dtl@authorcount=2\relax + \ \andname\ \expandafter\DTLformatsurnameonly\@dtl@author + \else + \ \etalname + \expandafter\DTLcheckendsperiod\expandafter{\etalname} + \fi + \@endfortrue + \fi +\fi +}}% +}{}% +} % \end{macrocode} %\end{macro} % -%\begin{macro}{\DTLbibitem} -% Define how to start a new bibitem: +%\begin{macro}{\DTLformatvolnumpages} +% Format volume, number and pages (of an article). % \begin{macrocode} -\newcommand*{\DTLbibitem}{\bibitem{\DBIBcitekey}} +\newcommand*{\DTLformatvolnumpages}{% +\DTLifbibfieldexists{Volume}{% +\DTLstartsentencespace +\DTLbibfield{Volume}\DTLperiodfalse}{}% +\DTLifbibfieldexists{Number}{% +\DTLstartsentencespace +(\DTLbibfield{Number})\DTLperiodfalse}{}% +\DTLifbibfieldexists{Pages}{% +\DTLifanybibfieldexists{Volume,Number}{:}{% +\DTLstartsentencespace +\protected@edef\@dtl@pages{0\DTLbibfield{Pages}}% +\DTLifnumerical{\@dtl@pages}{\pagename}{\pagesname}~}% +\DTLbibfield{Pages}\DTLperiodfalse}{}% +} % \end{macrocode} %\end{macro} % -%\begin{macro}{\DTLmbibitem} -% As \cs{DTLbibitem} but for \cs{DTLmbibliography} +%\begin{macro}{\DTLformatbvolume} +% Format book volume. % \begin{macrocode} -\newcommand*{\DTLmbibitem}[1]{\bibitem{#1@\DBIBcitekey}} +\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}{\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{macro}{\DTLformatchapterpages} +% Format chapter and pages: % \begin{macrocode} -\newcommand*{\DTLformatauthor}[4]{% -\DTLformatforenames{#4} -\DTLformatvon{#1}% -\DTLformatsurname{#2}% -\DTLformatjr{#3}} +\newcommand*{\DTLformatchapterpages}{% +\DTLifbibfieldexists{Chapter}{% +\DTLifbibfieldexists{Type}{% +\DTLstartsentencespace +\DTLbibfield{Type}}{% +\DTLstartsentencespace +\chaptername}~\DTLbibfield{Chapter}% +\DTLifbibfieldexists{Pages}{\DTLaddcomma}{% +\DTLcheckbibfieldendsperiod{Chapter}}}{}% +\DTLstartsentencespace +\DTLformatpages} % \end{macrocode} %\end{macro} % -%\begin{macro}{\DTLformateditor} -% The format of an editor's name. +%\begin{macro}{\DTLformatpages} +% Format pages: % \begin{macrocode} -\newcommand*{\DTLformateditor}[4]{% -\DTLformatforenames{#4} -\DTLformatvon{#1}% -\DTLformatsurname{#2}% -\DTLformatjr{#3}} +\newcommand*{\DTLformatpages}{% +\DTLifbibfieldexists{Pages}{% +\DTLstartsentencespace +\protected@edef\@dtl@pages{0\DTLbibfield{Pages}}% +\DTLifnumerical{\@dtl@pages}{\pagename}{\pagesname}~% +\DTLbibfield{Pages}\DTLcheckbibfieldendsperiod{Pages}}{}% +} % \end{macrocode} %\end{macro} % -%\begin{macro}{\DTLformatedition} -% The format of an edition: +%\begin{macro}{\DTLformatnumberseries} +% Format number and series (of book) % \begin{macrocode} -\newcommand*{\DTLformatedition}[1]{#1 \editionname} +\newcommand*{\DTLformatnumberseries}{% +\DTLifbibfieldexists{Volume}{}{% +\DTLifbibfieldexists{Number}{% +\ifDTLmidsentence + \numbername +\else + \DTLstartsentencespace + \expandafter\MakeUppercase\numbername +\fi~\DTLbibfield{Number}% +\DTLifbibfieldexists{Series}{\ \inname\ \DTLbibfield{Series}% +\DTLcheckbibfieldendsperiod{Series}}{% +\DTLcheckbibfieldendsperiod{Number}}% +}{% +\DTLifbibfieldexists{Series}{% +\DTLstartsentencespace +\DTLbibfield{Series}% +\DTLcheckbibfieldendsperiod{Series}}{}}% +}% +} % \end{macrocode} %\end{macro} -% -%\begin{macro}{\DTLformatarticle} -% The format of an article: +%\begin{macro}{\DTLformatbookcrossref} +% Format a book cross reference. % \begin{macrocode} -\newcommand{\DTLformatarticle}{} +\newcommand*{\DTLformatbookcrossref}{% +\DTLifbibfieldexists{Volume}{% +\ifDTLmidsentence + \volumename +\else + \DTLstartsentencespace + \expandafter\MakeUppercase\volumename +\fi +~\DTLbibfield{Volume}\ \ofname\ +}{% +\ifDTLmidsentence + \inname +\else + \DTLstartsentencespace + \expandafter\MakeUppercase\inname +\fi\ }% +\DTLifbibfieldexists{Editor}{\DTLformatcrossrefeditor}{% +\DTLifbibfieldexists{Key}{% +\DTLbibfield{Key}}{% +\DTLifbibfieldexists{Series}{% +{\em\DTLbibfield{Series}}}{}% +}% +}% +\edef\@dtl@tmp{\DTLbibfield{CrossRef}}% +~\cite{\@dtl@tmp}% +} % \end{macrocode} %\end{macro} -% -%\begin{macro}{\DTLformatbook} -% The format of a book: +%\begin{macro}{\DTLformatincollproccrossref} +% Format `incollections' cross reference. % \begin{macrocode} -\newcommand{\DTLformatbook}{} +\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}{\DTLformatbooklet} -% The format of a booklet: +%\begin{macro}{\DTLformatinedbooktitle} +%Format editor and booktitle: % \begin{macrocode} -\newcommand{\DTLformatbooklet}{} +\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}{\DTLformatinbook} -% The format of an ``inbook'' type: +%\begin{macro}{\DTLformatdate} +%Format date. % \begin{macrocode} -\newcommand{\DTLformatinbook}{} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\DTLformatincollection} -% The format of an ``incollection'' type: -% \begin{macrocode} -\newcommand{\DTLformatincollection}{} +\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}{\DTLformatinproceedings} -% The format of an ``inproceedings'' type: +%\begin{macro}{\DTLformatarticlecrossref} +% Format article cross reference. % \begin{macrocode} -\newcommand{\DTLformatinproceedings}{} +\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}{\DTLformatmanual} -% The format of a manual: -% \begin{macrocode} -\newcommand{\DTLformatmanual}{} -% \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}{\DTLformatmastersthesis} -% The format of a master's thesis: +%\begin{macro}{\DTLbibfieldexists} +%\begin{definition} +%\cs{DTLbibfieldexists}\marg{field label} +%\end{definition} +% Checks if named bib field exists for current entry % \begin{macrocode} -\newcommand{\DTLformatmastersthesis}{} +\newcommand*{\DTLbibfieldexists}[1]{% +\TE@throw\noexpand\dtl@testbibfieldexists{#1}% +\noexpand\if@dtl@condition} % \end{macrocode} %\end{macro} -% -%\begin{macro}{\DTLformatmisc} -% The format of a miscellaneous entry: +%\begin{macro}{\dtl@testbibfieldexists} % \begin{macrocode} -\newcommand{\DTLformatmisc}{} +\newcommand*{\dtl@testbibfieldexists}[1]{% +\DTLifbibfieldexists{#1}{\@dtl@conditiontrue}{\@dtl@conditionfalse}} % \end{macrocode} %\end{macro} % -%\begin{macro}{\DTLformatphdthesis} -% The format of a Ph.D. thesis: +%\begin{macro}{\DTLbibfieldiseq} +%\begin{definition} +%\cs{DTLbibfieldiseq}\marg{field label}\marg{value} +%\end{definition} +% Checks if the value of the bib field given by \meta{field label} +% is equal to \meta{value}. (Uses \cs{dtlcompare} to determine if +% the values are equal. If the bib field doesn't exist, the +% condition is false.) % \begin{macrocode} -\newcommand{\DTLformatphdthesis}{} +\newcommand*{\DTLbibfieldiseq}[2]{% +\TE@throw\noexpand\dtl@testbibfieldiseq{#1}{#2}% +\noexpand\if@dtl@condition} % \end{macrocode} %\end{macro} -% -%\begin{macro}{\DTLformatproceedings} -% The format of a proceedings: +%\begin{macro}{\dtl@testbibfieldiseq} % \begin{macrocode} -\newcommand{\DTLformatproceedings}{} +\newcommand*{\dtl@testbibfieldiseq}[2]{% +\DTLifbibfieldexists{#1}{% +\expandafter\let\expandafter\@dtl@tmp\expandafter + =\csname @dtl@key@#1\endcsname +\expandafter\toks@\expandafter{\@dtl@tmp}% +\@dtl@toks{#2}% +\edef\@dtl@docompare{\noexpand\dtlcompare{\noexpand\@dtl@tmpcount}% +{\the\toks@}{\the\@dtl@toks}}% +\@dtl@docompare +\ifnum\@dtl@tmpcount=0\relax + \@dtl@conditiontrue +\else + \@dtl@conditionfalse +\fi +}{% +\@dtl@conditionfalse}% +} % \end{macrocode} %\end{macro} % -%\begin{macro}{\DTLformattechreport} -% The format of a technical report: +%\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{\DTLformattechreport}{} +\newcommand*{\DTLbibfieldislt}[2]{% +\TE@throw\noexpand\dtl@testbibfieldislt{#1}{#2}% +\noexpand\if@dtl@condition} % \end{macrocode} %\end{macro} -% -%\begin{macro}{\DTLformatunpublished} -% The format of an unpublished work: +%\begin{macro}{\dtl@testbibfieldislt} % \begin{macrocode} -\newcommand{\DTLformatunpublished}{} +\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} % -% Predefined names (these correspond to the standard \BibTeX\ -% predefined strings of the same name without the leading -% \cs{DTL}): -%\begin{macro}{\DTLacmcs} +%\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*{\DTLacmcs}{ACM Computing Surveys} +\newcommand*{\DTLbibfieldisle}[2]{% +\TE@throw\noexpand\dtl@testbibfieldisle{#1}{#2}% +\noexpand\if@dtl@condition} % \end{macrocode} %\end{macro} -% -%\begin{macro}{\DTLacta} +%\begin{macro}{\dtl@testbibfieldisle} % \begin{macrocode} -\newcommand*{\DTLacta}{Acta Informatica} +\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}{\DTLcacm} +%\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*{\DTLcacm}{Communications of the ACM} +\newcommand*{\DTLbibfieldisgt}[2]{% +\TE@throw\noexpand\dtl@testbibfieldisgt{#1}{#2}% +\noexpand\if@dtl@condition} % \end{macrocode} %\end{macro} -% -%\begin{macro}{\DTLibmjrd} +%\begin{macro}{\dtl@testbibfieldisgt} % \begin{macrocode} -\newcommand*{\DTLibmjrd}{IBM Journal of Research and Development} +\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}{\DTLibmsj} +%\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*{\DTLibmsj}{IBM Systems Journal} +\newcommand*{\DTLbibfieldisge}[2]{% +\TE@throw\noexpand\dtl@testbibfieldisge{#1}{#2}% +\noexpand\if@dtl@condition} % \end{macrocode} %\end{macro} -% -%\begin{macro}{\DTLieeese} +%\begin{macro}{\dtl@testbibfieldisge} % \begin{macrocode} -\newcommand*{\DTLieeese}{IEEE Transactions on Software Engineering} +\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}{\DTLieeetc} +%\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*{\DTLieeetc}{IEEE Transactions on Computers} +\newcommand*{\DTLbibfieldcontains}[2]{% +\TE@throw\noexpand\dtl@testbibfieldcontains{#1}{#2}% +\noexpand\if@dtl@condition} % \end{macrocode} %\end{macro} -% -%\begin{macro}{\DTLieeetcad} +%\begin{macro}{\dtl@testbibfieldcontains} % \begin{macrocode} -\newcommand*{\DTLieeetcad}{IEEE Transactions on Computer-Aided Design -of Integrated Circuits} +\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}{\DTLipl} +%\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} -\newcommand*{\DTLipl}{Information Processing Letters} +\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}{\DTLjacm} +%\begin{macro}{\dtl@monthname} +% Full month names: % \begin{macrocode} -\newcommand*{\DTLjacm}{Journal of the ACM} +\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}{\DTLjcss} +%\begin{macro}{\DTLbibitem} +% Define how to start a new bibitem: % \begin{macrocode} -\newcommand*{\DTLjcss}{Journal of Computer and System Sciences} +\newcommand*{\DTLbibitem}{\bibitem{\DBIBcitekey}} % \end{macrocode} %\end{macro} % -%\begin{macro}{\DTLscp} +%\begin{macro}{\DTLmbibitem} +% As \cs{DTLbibitem} but for \cs{DTLmbibliography} % \begin{macrocode} -\newcommand*{\DTLscp}{Science of Computer Programming} +\newcommand*{\DTLmbibitem}[1]{\bibitem{#1@\DBIBcitekey}} % \end{macrocode} %\end{macro} % -%\begin{macro}{\DTLsicomp} +%\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*{\DTLsicomp}{SIAM Journal on Computing} +\newcommand*{\DTLformatauthor}[4]{% +\DTLformatforenames{#4} +\DTLformatvon{#1}% +\DTLformatsurname{#2}% +\DTLformatjr{#3}} % \end{macrocode} %\end{macro} % -%\begin{macro}{\DTLtocs} +%\begin{macro}{\DTLformateditor} +% The format of an editor's name. % \begin{macrocode} -\newcommand*{\DTLtocs}{ACM Transactions on Computer Systems} +\newcommand*{\DTLformateditor}[4]{% +\DTLformatforenames{#4} +\DTLformatvon{#1}% +\DTLformatsurname{#2}% +\DTLformatjr{#3}} % \end{macrocode} %\end{macro} % -%\begin{macro}{\DTLtods} +%\begin{macro}{\DTLformatedition} +% The format of an edition: % \begin{macrocode} -\newcommand*{\DTLtods}{ACM Transactions on Database Systems} +\newcommand*{\DTLformatedition}[1]{#1 \editionname} % \end{macrocode} %\end{macro} % -%\begin{macro}{\DTLtog} +%\begin{macro}{\DTLformatarticle} +% The format of an article: % \begin{macrocode} -\newcommand*{\DTLtog}{ACM Transactions on Graphics} +\newcommand{\DTLformatarticle}{} % \end{macrocode} %\end{macro} % -%\begin{macro}{\DTLtoms} +%\begin{macro}{\DTLformatbook} +% The format of a book: % \begin{macrocode} -\newcommand*{\DTLtoms}{ACM Transactions on Mathematical Software} +\newcommand{\DTLformatbook}{} % \end{macrocode} %\end{macro} % -%\begin{macro}{\DTLtoois} +%\begin{macro}{\DTLformatbooklet} +% The format of a booklet: % \begin{macrocode} -\newcommand*{\DTLtoois}{ACM Transactions on Office Information -Systems} +\newcommand{\DTLformatbooklet}{} % \end{macrocode} %\end{macro} % -%\begin{macro}{\DTLtoplas} +%\begin{macro}{\DTLformatinbook} +% The format of an ``inbook'' type: % \begin{macrocode} -\newcommand*{\DTLtoplas}{ACM Transactions on Programming Languages -and Systems} +\newcommand{\DTLformatinbook}{} % \end{macrocode} %\end{macro} % -%\begin{macro}{\DTLtcs} +%\begin{macro}{\DTLformatincollection} +% The format of an ``incollection'' type: % \begin{macrocode} -\newcommand*{\DTLtcs}{Theoretical Computer Science} +\newcommand{\DTLformatincollection}{} % \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}{\DTLformatinproceedings} +% The format of an ``inproceedings'' type: +% \begin{macrocode} +\newcommand{\DTLformatinproceedings}{} +% \end{macrocode} +%\end{macro} % -%\begin{macro}{\dtlbst@plain} -% The `plain' style: +%\begin{macro}{\DTLformatmanual} +% The format of a manual: % \begin{macrocode} -\newcommand{\dtlbst@plain}{% +\newcommand{\DTLformatmanual}{} % \end{macrocode} -% Set how to format the entire bibliography: +%\end{macro} +% +%\begin{macro}{\DTLformatmastersthesis} +% The format of a master's thesis: % \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}}% +\newcommand{\DTLformatmastersthesis}{} % \end{macrocode} -% Set how to start the bibliography entry: +%\end{macro} +% +%\begin{macro}{\DTLformatmisc} +% The format of a miscellaneous entry: % \begin{macrocode} -\renewcommand*{\DTLbibitem}{\bibitem{\DBIBcitekey}}% -\renewcommand*{\DTLmbibitem}[1]{\bibitem{##1@\DBIBcitekey}}% +\newcommand{\DTLformatmisc}{} % \end{macrocode} -% Sets the author name format. +%\end{macro} +% +%\begin{macro}{\DTLformatphdthesis} +% The format of a Ph.D. thesis: % \begin{macrocode} -\renewcommand*{\DTLformatauthor}[4]{% -\DTLformatforenames{##4} -\DTLformatvon{##1}% -\DTLformatsurname{##2}% -\DTLformatjr{##3}} +\newcommand{\DTLformatphdthesis}{} % \end{macrocode} -% Sets the editor name format. +%\end{macro} +% +%\begin{macro}{\DTLformatproceedings} +% The format of a proceedings: % \begin{macrocode} -\renewcommand*{\DTLformateditor}[4]{% -\DTLformatforenames{##4} -\DTLformatvon{##1}% -\DTLformatsurname{##2}% -\DTLformatjr{##3}} +\newcommand{\DTLformatproceedings}{} % \end{macrocode} -% Sets the edition format. +%\end{macro} +% +%\begin{macro}{\DTLformattechreport} +% The format of a technical report: % \begin{macrocode} -\renewcommand*{\DTLformatedition}[1]{##1 \editionname}% +\newcommand{\DTLformattechreport}{} % \end{macrocode} -% Sets the monthname format. +%\end{macro} +% +%\begin{macro}{\DTLformatunpublished} +% The format of an unpublished work: % \begin{macrocode} -\let\DTLmonthname\dtl@monthname +\newcommand{\DTLformatunpublished}{} % \end{macrocode} -% Sets other predefined names: +%\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} -\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} +\newcommand*{\DTLacmcs}{ACM Computing Surveys} % \end{macrocode} -% The format of an article. +%\end{macro} +% +%\begin{macro}{\DTLacta} % \begin{macrocode} -\renewcommand*{\DTLformatarticle}{% +\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}{% @@ -24603,5 +25345,1129 @@ EXECUTE {end.bib} % % \end{macrocode} %\fi +%\iffalse +% \begin{macrocode} +%<*person.sty> +% \end{macrocode} +%\fi +%\section{person.sty}\label{sec:code:person} +%\subsection{Package Declaration} +% Package identification: +% \begin{macrocode} +\NeedsTeXFormat{LaTeX2e} +\ProvidesPackage{person}[2009/11/15 v1.01 (NLCT)] +% \end{macrocode} +% Requires the \sty{ifthen} package. +% \begin{macrocode} +\RequirePackage{ifthen} +\RequirePackage{datatool} +% \end{macrocode} +%\subsection{Defining People} +%\begin{counter}{people} +% Keep count of the number of people who have been defined: +% \begin{macrocode} +\newcounter{people} +% \end{macrocode} +%\end{counter} +%\begin{counter}{person} +% Temporary counter +% \begin{macrocode} +\newcounter{person} +% \end{macrocode} +%\end{counter} +%\begin{macro}{\@people@list} +% Keep a list of labels for each person who has been defined: +% \begin{macrocode} +\newcommand*{\@people@list}{,} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\@get@firstperson} +% Get the first person's name in \cs{@people@list}, and store in +% the argument (which must be a control sequence.) +% \begin{macrocode} +\newcommand*{\@get@firstperson}[1]{% + \expandafter\@@get@firstperson\@people@list,\@nil{#1}} + \def\@@get@firstperson,#1,#2\@nil#3{% + \def#3{#1}% +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\malelabels} +% List of labels that can be used to indicate that a person is +% male (when defining a person using \cs{newperson}). +% \begin{macrocode} +\newcommand*{\malelabels}{male,Male,MALE,M,m} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\addmalelabel} +% Adds a label to the list of male labels. +% \begin{macrocode} +\newcommand*{\addmalelabel}[1]{% + \expandafter\@dtl@toksA\expandafter{\malelabels}% + \expandafter\@dtl@toksB\expandafter{#1}% + \edef\malelabels{\the\@dtl@toksA,\the\@dtl@toksB}% +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\addfemalelabel} +% Adds a label to the list of female labels. +% \begin{macrocode} +\newcommand*{\addfemalelabel}[1]{% + \expandafter\@dtl@toksA\expandafter{\femalelabels}% + \expandafter\@dtl@toksB\expandafter{#1}% + \edef\femalelabels{\the\@dtl@toksA,\the\@dtl@toksB}% +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\femalelabels} +% List of labels that can be used to indicate that a person is +% female (when defining a person using \cs{newperson}). +% \begin{macrocode} +\newcommand*{\femalelabels}{female,Female,FEMALE,F,f} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\ifmalelabel} +% Determines if first argument is contained in the list of male +% labels. (One level expansion is performed on the first object +% in first argument.) +% If true does second argument, otherwise does third argument. +% \begin{macrocode} +\newcommand{\ifmalelabel}[3]{% + \expandafter\DTLifinlist\expandafter{#1}{\malelabels}{#2}{#3}% +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\iffemalelabel} +% Determines if first argument is contained in the list of female +% labels. (One level expansion is performed on the first object +% in first argument.) +% If true does second argument, otherwise does third argument. +% \begin{macrocode} +\newcommand{\iffemalelabel}[3]{% + \expandafter\DTLifinlist\expandafter{#1}{\femalelabels}{#2}{#3}% +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\newperson} +% Define a new person. The optional argument specifies a label +% with which to refer to that person. If omitted, \texttt{anon} +% is used. If more than one person is defined, the optional +% argument will be required to specify a unique label. The +% compulsory arguments are the person's full name, their +% familiar name and their gender. +% \begin{macrocode} +\newcommand*{\newperson}[4][anon]{% + \@ifundefined{person@#1@name}% + {% + \ifmalelabel{#4}% + {% + \expandafter\gdef\csname person@#1@gender\endcsname{male}% + }% + {% + \iffemalelabel{#4}% + {% + \expandafter\gdef\csname person@#1@gender\endcsname{female}% + }% + {% + \PackageError{person}{Unknown gender `#4' for person + `#1'}{Allowed gender labels are: \malelabels\space or + \femalelabels}% + \@namedef{person@#1@gender}{other}% + }% + }% + \expandafter + \protected@xdef\csname person@#1@fullname\endcsname{#2}% + \expandafter + \protected@xdef\csname person@#1@name\endcsname{#3}% + \protected@xdef\@people@list{\@people@list#1,}% + \stepcounter{people}% + }% + {% + \PackageError{person}{Person `#1' has already been defined}{}% + }% +} +% \end{macrocode} +%\end{macro} +% +%\subsection{Remove People} +% +%\begin{macro}{\removeperson} +% Removes person identified by their label from the list. +% \begin{macrocode} +\newcommand*{\removeperson}[1][anon]{% + \edef\@person@label{#1}% + \expandafter\@removeperson\expandafter{\@person@label}% +} +% \end{macrocode} +% The label has to be full expanded for the internal command. +% \begin{macrocode} +\newcommand*{\@removeperson}[1]{% + \ifpersonexists{#1}% + {% +% \end{macrocode} +% Remove label from list of people. +% \begin{macrocode} + \def\@remove@person##1,#1,##2\@nil{% + \def\@prsn@pre{##1}\def\@prsn@post{##2}}% + \expandafter\@remove@person\@people@list\@nil + \xdef\@people@list{\@prsn@pre,\@prsn@post}% +% \end{macrocode} +% Decrement number of people: +% \begin{macrocode} + \addtocounter{people}{-1}% +% \end{macrocode} +% Undefine associated control sequences: +% \begin{macrocode} + \expandafter\global\expandafter + \let\csname person@#1@name\endcsname\undefined + \expandafter\global\expandafter + \let\csname person@#1@fullname\endcsname\undefined + \expandafter\global\expandafter + \let\csname person@#1@gender\endcsname\undefined + }% + {% + \PackageError{person}{Can't remove person `#1': no such + person}{}% + }% +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\removepeople} +% Removes the people listed. +% \begin{macrocode} +\newcommand*{\removepeople}[1]{% + \@for\@thisperson:=#1\do{% + \ifx\@thisperson\@empty + \else + \expandafter\removeperson\expandafter[\@thisperson]% + \fi + }% +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\removeallpeople} +% Removes everyone. +% \begin{macrocode} +\newcommand*{\removeallpeople}{% + \@for\@thisperson:=\@people@list\do{% + \expandafter\global\expandafter + \let\csname person@\@thisperson @name\endcsname\undefined + \expandafter\global\expandafter + \let\csname person@\@thisperson @fullname\endcsname\undefined + \expandafter\global\expandafter + \let\csname person@\@thisperson @gender\endcsname\undefined + }% + \setcounter{people}{0}% + \gdef\@people@list{,}% +} +% \end{macrocode} +%\end{macro} +% +%\subsection{Conditionals and Loops} +%\begin{macro}{\ifpersonexists} +% If person whose label is given by the first argument exists, then +% do the second argument otherwise do third argument. +% \begin{macrocode} +\newcommand{\ifpersonexists}[3]{% + \@ifundefined{person@#1@name}{#3}{#2}% +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\ifmale} +% If the person given by the label in the first argument is male, +% do the second argument, otherwise do the third argument. +% \begin{macrocode} +\newcommand{\ifmale}[3]{% + \ifpersonexists{#1}% + {% + \edef\@gender{\csname person@\@thisperson @gender\endcsname}% + \ifx\@gender\@male@label + #2% + \else + #3% + \fi + }% + {% + \PackageError{person}{Person `#1' doesn't exist.}{}% + }% +} +\def\@male@label{male} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\ifallmale} +% If all people listed in first argument are male, do the second +% argument otherwise do the third argument. If the first argument +% is omitted, all defined people are checked. +% \begin{macrocode} +\newcommand{\ifallmale}[3][\@people@list]{% + \@for\@thisperson:=#1\do{% + \ifpersonexists{\@thisperson}% + {% + \edef\@gender{\csname person@\@thisperson @gender\endcsname}% + \ifx\@gender\@male@label + \else + \@endfortrue + \fi + }% + {% + \PackageError{person}{Person `#1' doesn't exist.}{}% + }% + }% + \if@endfor + #3% + \else + #2% + \fi +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\iffemale} +% If the person given by the label in the first argument is female, +% do the second argument, otherwise do the third argument. +% \begin{macrocode} +\newcommand{\iffemale}[3]{% + \ifpersonexists{#1}% + {% + \edef\@gender{\csname person@\@thisperson @gender\endcsname}% + \ifx\@gender\@female@label + #2% + \else + #3% + \fi + }% + {% + \PackageError{person}{Person `#1' doesn't exist.}{}% + }% +} +\def\@female@label{female} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\ifallfemale} +% If all people listed in first argument are female, do the second +% argument otherwise do the third argument. +% \begin{macrocode} +\newcommand{\ifallfemale}[3][\@people@list]{% + \@for\@thisperson:=#1\do{% + \edef\@gender{\csname person@\@thisperson @gender\endcsname}% + \ifx\@gender\@female@label + \else + \@endfortrue + \fi + }% + \if@endfor + #3% + \else + #2% + \fi +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\foreachperson} +%\begin{definition} +%\cs{foreachperson}(\meta{name cs},\meta{full name cs},\meta{gender cs},\meta{label cs})\cs{in}\marg{list}\cs{do}\marg{body} +%\end{definition} +% Iterates through list of people the \cs{in}\marg{list} is optional. +% If omitted, the list of all defined people is used. +% \begin{macrocode} +\def\foreachperson(#1,#2,#3,#4)#5{% + \ifx#5\in + \def\@do@foreachperson{\@foreachperson(#1,#2,#3,#4)#5}% + \else + \def\@do@foreachperson{% + \@foreachperson(#1,#2,#3,#4)\in\@people@list#5}% + \fi + \@do@foreachperson +} +\long\def\@foreachperson(#1,#2,#3,#4)\in#5\do#6{% + \@for#4:=#5\do{% + \ifx#4\@empty + \else + \ifpersonexists{#4}% + {% + \expandafter + \let\expandafter#1\csname person@#4@name\endcsname + \expandafter + \let\expandafter#2\csname person@#4@fullname\endcsname + \expandafter + \let\expandafter#3\csname person@#4@gender\endcsname + \ifx#3\@male@label + \let#3\malename + \else + \ifx#3\@female@label + \let#3\femalename + \fi + \fi + #6% + }% + {% + \PackageError{person}{Person `#4' doesn't exist}{}% + }% + \fi + }% +} +% \end{macrocode} +%\end{macro} +% +%\subsection{Predefined Words}\label{sec:code:peoplenames} +% These commands should be redefined if +% you are writing in another language, but note that these +% are structured according to English grammar. +%\begin{macro}{\malepronoun} +% \begin{macrocode} +\newcommand*{\malepronoun}{he} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\femalepronoun} +% \begin{macrocode} +\newcommand*{\femalepronoun}{she} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\pluralpronoun} +% \begin{macrocode} +\newcommand*{\pluralpronoun}{they} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\maleobjpronoun} +% \begin{macrocode} +\newcommand*{\maleobjpronoun}{him} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\femaleobjpronoun} +% \begin{macrocode} +\newcommand*{\femaleobjpronoun}{her} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\pluralobjpronoun} +% \begin{macrocode} +\newcommand*{\pluralobjpronoun}{them} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\malepossadj} +% \begin{macrocode} +\newcommand*{\malepossadj}{his} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\femalepossadj} +% \begin{macrocode} +\newcommand*{\femalepossadj}{her} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\pluralpossadj} +% \begin{macrocode} +\newcommand*{\pluralpossadj}{their} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\maleposspronoun} +% \begin{macrocode} +\newcommand*{\maleposspronoun}{his} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\femaleposspronoun} +% \begin{macrocode} +\newcommand*{\femaleposspronoun}{hers} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\pluralposspronoun} +% \begin{macrocode} +\newcommand*{\pluralposspronoun}{theirs} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\malechild} +% \begin{macrocode} +\newcommand*{\malechild}{son} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\femalechild} +% \begin{macrocode} +\newcommand*{\femalechild}{daughter} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\pluralchild} +% \begin{macrocode} +\newcommand*{\pluralchild}{children} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\malechildren} +% \begin{macrocode} +\newcommand*{\malechildren}{sons} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\femalechildren} +% \begin{macrocode} +\newcommand*{\femalechildren}{daughters} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\maleparent} +% \begin{macrocode} +\newcommand*{\maleparent}{father} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\femaleparent} +% \begin{macrocode} +\newcommand*{\femaleparent}{mother} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\pluralparent} +% \begin{macrocode} +\newcommand*{\pluralparent}{parents} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\malesibling} +% \begin{macrocode} +\newcommand*{\malesibling}{brother} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\femalesibling} +% \begin{macrocode} +\newcommand*{\femalesibling}{sister} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\pluralsibling} +% \begin{macrocode} +\newcommand*{\pluralsibling}{siblings} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\malesiblings} +% \begin{macrocode} +\newcommand*{\malesiblings}{brothers} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\femalesiblings} +% \begin{macrocode} +\newcommand*{\femalesiblings}{sisters} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\andname} +% Define \cs{andname} if it hasn't already been defined: +% \begin{macrocode} +\providecommand*{\andname}{and} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\malename} +% \begin{macrocode} +\newcommand*{\malename}{male} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\femalename} +% \begin{macrocode} +\newcommand*{\femalename}{female} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\personsep} +% Separator to use between people (but not the between the last +% two). +% \begin{macrocode} +\newcommand*{\personsep}{, } +% \end{macrocode} +%\end{macro} +%\begin{macro}{\personlastsep} +% Separator to use between last two people. +% \begin{macrocode} +\newcommand*{\personlastsep}{\space\andname\space} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\twopeoplesep} +% Separator to use when list only contains two people. +% \begin{macrocode} +\newcommand*{\twopeoplesep}{\space\andname\space} +% \end{macrocode} +%\end{macro} +% +%\subsection{Displaying Information} +%\begin{macro}{\personfullname} +% The person's full name can be displayed using +% \cs{personfullname}\oarg{label}, where \meta{label} is the +% unique label used when defining that person. If \meta{label} +% is omitted, \texttt{anon} is used. +% \begin{macrocode} +\newcommand*{\personfullname}[1][anon]{% + \@ifundefined{person@#1@fullname}% + {% + \PackageError{person}{Person `#1' has not been defined}{}% + }% + {% + \csname person@#1@fullname\endcsname + }% +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\peoplefullname} +% List all defined people's full names. This iterates through all +% labels in \cs{@people@list}. +% \begin{macrocode} +\newcommand*{\peoplefullname}{% + \setcounter{person}{1}% + \@for\@thisperson:=\@people@list\do{% + \ifthenelse{\equal{\@thisperson}{}}% + {}% + {% + \personfullname[\@thisperson]% + \stepcounter{person}% + \ifnum\c@people=1\relax + \else + \ifnum\c@person=\c@people + \ifnum\c@people=2\relax + \twopeoplesep + \else + \personlastsep + \fi + \else + \ifnum\c@person<\c@people + \personsep + \fi + \fi + \fi + }% + }% +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\personname} +% As \cs{personfullname}, but for the person's familiar name. +% \begin{macrocode} +\newcommand*{\personname}[1][anon]{% + \@ifundefined{person@#1@name}% + {% + \PackageError{person}{Person `#1' has not been defined}{}% + }% + {% + \csname person@#1@name\endcsname + }% +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\peoplename} +% List all defined people's familiar names. This iterates through all +% labels in \cs{@people@list}. +% \begin{macrocode} +\newcommand*{\peoplename}{% + \setcounter{person}{1}% + \@for\@thisperson:=\@people@list\do{% + \ifthenelse{\equal{\@thisperson}{}}% + {}% + {% + \personname[\@thisperson]% + \stepcounter{person}% + \ifnum\c@people=1\relax + \else + \ifnum\c@person=\c@people + \ifnum\c@people=2\relax + \twopeoplesep + \else + \personlastsep + \fi + \else + \ifnum\c@person<\c@people + \personsep + \fi + \fi + \fi + }% + }% +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\personpronoun} +% Display the pronoun (he/she) according to the person's gender. +% \begin{macrocode} +\newcommand*{\personpronoun}[1][anon]{% + \@ifundefined{person@#1@gender}% + {% + \PackageError{person}{Person `#1' has not been defined}{}% + }% + {% + \edef\@gender{\csname person@#1@gender\endcsname}% + \csname\@gender pronoun\endcsname + }% +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\Personpronoun} +% As above, but make the first letter uppercase. +% \begin{macrocode} +\newcommand*{\Personpronoun}[1][anon]{% + \@ifundefined{person@#1@gender}% + {% + \PackageError{person}{Person `#1' has not been defined}{}% + }% + {% + \edef\@gender{\csname person@#1@gender\endcsname}% + \expandafter\expandafter\expandafter + \MakeUppercase\csname\@gender pronoun\endcsname + }% +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\peoplepronoun} +% If there is more than one person, \cs{peoplepronoun} will use +% \cs{pluralpronoun}, otherwise it will use \cs{personpronoun}. +% \begin{macrocode} +\newcommand*{\peoplepronoun}{% + \ifnum\c@people>1\relax + \pluralpronoun + \else + \@get@firstperson{\@thisperson}% + \personpronoun[\@thisperson]% + \fi +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\Peoplepronoun} +% As above, but first letter in upper case +% \begin{macrocode} +\newcommand*{\Peoplepronoun}{% + \ifnum\c@people>1\relax + \expandafter\MakeUppercase\pluralpronoun + \else + \@get@firstperson{\@thisperson}% + \Personpronoun[\@thisperson]% + \fi +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\personobjpronoun} +% Display the objective pronoun (him/her) according to the person's +% gender. +% \begin{macrocode} +\newcommand*{\personobjpronoun}[1][anon]{% + \@ifundefined{person@#1@gender}% + {% + \PackageError{person}{Person `#1' has not been defined}{}% + }% + {% + \edef\@gender{\csname person@#1@gender\endcsname}% + \csname\@gender objpronoun\endcsname + }% +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\Personobjpronoun} +% As above, but make the first letter uppercase. +% \begin{macrocode} +\newcommand*{\Personobjpronoun}[1][anon]{% + \@ifundefined{person@#1@gender}% + {% + \PackageError{person}{Person `#1' has not been defined}{}% + }% + {% + \edef\@gender{\csname person@#1@gender\endcsname}% + \expandafter\expandafter\expandafter + \MakeUppercase\csname\@gender objpronoun\endcsname + }% +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\peopleobjpronoun} +% If there is more than one person, \cs{peopleobjpronoun} will use +% \cs{pluralobjpronoun}, otherwise it will use \cs{personobjpronoun}. +% \begin{macrocode} +\newcommand*{\peopleobjpronoun}{% + \ifnum\c@people>1\relax + \pluralobjpronoun + \else + \@get@firstperson{\@thisperson}% + \personobjpronoun[\@thisperson]% + \fi +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\Peopleobjpronoun} +% As above, but first letter in upper case +% \begin{macrocode} +\newcommand*{\Peopleobjpronoun}{% + \ifnum\c@people>1\relax + \expandafter\MakeUppercase\pluralobjpronoun + \else + \@get@firstperson{\@thisperson}% + \Personobjpronoun[\@thisperson]% + \fi +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\personpssadj} +% Display the possessive adjective (his/her) according to the person's +% gender. +% \begin{macrocode} +\newcommand*{\personpossadj}[1][anon]{% + \@ifundefined{person@#1@gender}% + {% + \PackageError{person}{Person `#1' has not been defined}{}% + }% + {% + \edef\@gender{\csname person@#1@gender\endcsname}% + \csname\@gender possadj\endcsname + }% +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\Personpossadj} +% As above, but make the first letter uppercase. +% \begin{macrocode} +\newcommand*{\Personpossadj}[1][anon]{% + \@ifundefined{person@#1@gender}% + {% + \PackageError{person}{Person `#1' has not been defined}{}% + }% + {% + \edef\@gender{\csname person@#1@gender\endcsname}% + \expandafter\expandafter\expandafter + \MakeUppercase\csname\@gender possadj\endcsname + }% +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\peoplepossadj} +% If there is more than one person, \cs{peoplepossadj} will use +% \cs{pluralpossadj}, otherwise it will use \cs{personpossadj}. +% \begin{macrocode} +\newcommand*{\peoplepossadj}{% + \ifnum\c@people>1\relax + \pluralpossadj + \else + \@get@firstperson{\@thisperson}% + \personpossadj[\@thisperson]% + \fi +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\Peoplepossadj} +% As above, but first letter in upper case +% \begin{macrocode} +\newcommand*{\Peoplepossadj}{% + \ifnum\c@people>1\relax + \expandafter\MakeUppercase\pluralpossadj + \else + \@get@firstperson{\@thisperson}% + \Personpossadj[\@thisperson]% + \fi +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\personposspronoun} +% Display possessive pronoun (his/hers) according to the +% person's gender. +% \begin{macrocode} +\newcommand*{\personposspronoun}[1][anon]{% + \@ifundefined{person@#1@gender}% + {% + \PackageError{person}{Person `#1' has not been defined}{}% + }% + {% + \edef\@gender{\csname person@#1@gender\endcsname}% + \csname\@gender posspronoun\endcsname + }% +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\Personposspronoun} +% As above, but make the first letter uppercase. +% \begin{macrocode} +\newcommand*{\Personposspronoun}[1][anon]{% + \@ifundefined{person@#1@gender}% + {% + \PackageError{person}{Person `#1' has not been defined}{}% + }% + {% + \edef\@gender{\csname person@#1@gender\endcsname}% + \expandafter\expandafter\expandafter + \MakeUppercase\csname\@gender posspronoun\endcsname + }% +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\peopleposspronoun} +% If there is more than one person, \cs{peopleposspronoun} will use +% \cs{pluralposspronoun}, otherwise it will use \cs{personposspronoun}. +% \begin{macrocode} +\newcommand*{\peopleposspronoun}{% + \ifnum\c@people>1\relax + \pluralposspronoun + \else + \@get@firstperson{\@thisperson}% + \personposspronoun[\@thisperson]% + \fi +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\Peopleposspronoun} +% As above, but first letter in upper case +% \begin{macrocode} +\newcommand*{\Peopleposspronoun}{% + \ifnum\c@people>1\relax + \expandafter\MakeUppercase\pluralposspronoun + \else + \@get@firstperson{\@thisperson}% + \Personposspronoun[\@thisperson]% + \fi +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\personchild} +% Display this person's relationship to their parent (i.e.\ son +% or daughter). +% \begin{macrocode} +\newcommand*{\personchild}[1][anon]{% + \@ifundefined{person@#1@gender}% + {% + \PackageError{person}{Person `#1' has not been defined}{}% + }% + {% + \edef\@gender{\csname person@#1@gender\endcsname}% + \csname\@gender child\endcsname + }% +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\Personchild} +% As above, but make first letter uppercase. +% \begin{macrocode} +\newcommand*{\Personchild}[1][anon]{% + \@ifundefined{person@#1@gender}% + {% + \PackageError{person}{Person `#1' has not been defined}{}% + }% + {% + \edef\@gender{\csname person@#1@gender\endcsname}% + \expandafter\expandafter\expandafter\MakeUppercase + \csname\@gender child\endcsname + }% +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\peoplechild} +% If there is more than one person, \cs{peoplechild} will use +% \cs{malechildren} (if all male), \cs{femalechildren} (if all +% female) or \cs{pluralchild} (if mixed), otherwise it will use +% \cs{personchild}. +% \begin{macrocode} +\newcommand*{\peoplechild}{% + \ifnum\c@people>1\relax + \ifallmale + {\malechildren}% + {\ifallfemale{\femalechildren}{\pluralchild}}% + \else + \@get@firstperson{\@thisperson}% + \personchild[\@thisperson]% + \fi +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\Peoplechild} +% As above but first letter is made uppercase. +% \begin{macrocode} +\newcommand*{\Peoplechild}{% + \ifnum\c@people>1\relax + \ifallmale + {\expandafter\MakeUppercase\malechildren}% + {\ifallfemale + {\expandafter\MakeUppercase\femalechildren} + {\expandafter\MakeUppercase\pluralchild}}% + \else + \@get@firstperson{\@thisperson}% + \Personchild[\@thisperson]% + \fi +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\personparent} +% Display this person's relationship to their child (i.e.\ father +% or mother). +% \begin{macrocode} +\newcommand*{\personparent}[1][anon]{% + \@ifundefined{person@#1@gender}% + {% + \PackageError{person}{Person `#1' has not been defined}{}% + }% + {% + \edef\@gender{\csname person@#1@gender\endcsname}% + \csname\@gender parent\endcsname + }% +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\Personparent} +% As above, but make the first letter uppercase. +% \begin{macrocode} +\newcommand*{\Personparent}[1][anon]{% + \@ifundefined{person@#1@gender}% + {% + \PackageError{person}{Person `#1' has not been defined}{}% + }% + {% + \edef\@gender{\csname person@#1@gender\endcsname}% + \expandafter\expandafter\expandafter\MakeUppercase + \csname\@gender parent\endcsname + }% +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\peopleparent} +% If there is more than one person, \cs{peopleparent} will use +% \cs{pluralparent}, otherwise it will use \cs{personparent}. +% \begin{macrocode} +\newcommand*{\peopleparent}{% + \ifnum\c@people>1\relax + \pluralparent + \else + \@get@firstperson{\@thisperson}% + \personparent[\@thisperson]% + \fi +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\Peopleparent} +% As above, but make first letter uppercase. +% \begin{macrocode} +\newcommand*{\Peopleparent}{% + \ifnum\c@people>1\relax + \expandafter\MakeUppercase\pluralparent + \else + \@get@firstperson{\@thisperson}% + \Personparent[\@thisperson]% + \fi +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\personsibling} +% Display this person's relationship to their siblings (i.e.\ +% brother or sister). +% \begin{macrocode} +\newcommand*{\personsibling}[1][anon]{% + \@ifundefined{person@#1@gender}% + {% + \PackageError{person}{Person `#1' has not been defined}{}% + }% + {% + \edef\@gender{\csname person@#1@gender\endcsname}% + \csname\@gender sibling\endcsname + }% +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\Personsibling} +% Display this person's relationship to their siblings (i.e.\ +% brother or sister). +% \begin{macrocode} +\newcommand*{\Personsibling}[1][anon]{% + \@ifundefined{person@#1@gender}% + {% + \PackageError{person}{Person `#1' has not been defined}{}% + }% + {% + \edef\@gender{\csname person@#1@gender\endcsname}% + \expandafter\expandafter\expandafter\MakeUppercase + \csname\@gender sibling\endcsname + }% +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\peoplesibling} +% If there is more than one person, \cs{peoplesibling} will use +% \cs{malesiblings} (if all male), \cs{femalesiblings} (if all +% female) or \cs{pluralsibling} (if mixed), otherwise it will use +% \cs{personsibling}. +% \begin{macrocode} +\newcommand*{\peoplesibling}{% + \ifnum\c@people>1\relax + \ifallmale + {\malesiblings}% + {\ifallfemale{\femalesiblings}{\pluralsibling}}% + \else + \@get@firstperson{\@thisperson}% + \personsibling[\@thisperson]% + \fi +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\persongender} +% Displays the given person's gender (\cs{malename} or +% \cs{femalename}). +% \begin{macrocode} +\newcommand*{\persongender}[1]{% + \ifpersonmale{#1}{\malename}{\femalename}% +} +% \end{macrocode} +%\end{macro} +% +%\subsection{Extracting Information} +% +%\begin{macro}{\getpersongender} +% Gets person's gender and stores in first argument which must be +% a control sequence. +% \begin{macrocode} +\newcommand*{\getpersongender}[2]{% + \ifpersonmale{#2}{\let#1\malename}{\let#1\femalename}% +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\getpersonname} +% Gets person's name and stores in first argument which must be +% a control sequence. +% \begin{macrocode} +\newcommand*{\getpersonname}[2]{% + \ifpersonexists{#2}% + {% + \expandafter\let\expandafter#1\csname person@#2@name\endcsname + }% + {% + \PackageError{person}{Person `#2' doesn't exist}{}% + }% +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\getpersonfullname} +% Gets person's full name and stores in first argument which must be +% a control sequence. +% \begin{macrocode} +\newcommand*{\getpersonfullname}[2]{% + \ifpersonexists{#2}% + {% + \expandafter + \let\expandafter#1\csname person@#2@fullname\endcsname + }% + {% + \PackageError{person}{Person `#2' doesn't exist}{}% + }% +} +% \end{macrocode} +%\end{macro} +%\iffalse +% \begin{macrocode} +% +% \end{macrocode} +%\fi %\Finale \endinput diff --git a/Master/texmf-dist/source/latex/datatool/datatool.ins b/Master/texmf-dist/source/latex/datatool/datatool.ins index 8dc5e7e9d71..a3d3bd39125 100644 --- a/Master/texmf-dist/source/latex/datatool/datatool.ins +++ b/Master/texmf-dist/source/latex/datatool/datatool.ins @@ -1,4 +1,4 @@ -% datatool.ins generated using makedtx version 0.94b 2009/7/13 10:04 +% datatool.ins generated using makedtx version 0.94b 2009/11/15 15:10 \input docstrip \preamble @@ -18,7 +18,7 @@ The Current Maintainer of this work is Nicola Talbot. - This work consists of the files datatool.dtx and datatool.ins and the derived files datatool.sty, datapie.sty, dataplot.sty, databar.sty, databib.sty, databib.bst. + This work consists of the files datatool.dtx and datatool.ins and the derived files datatool.sty, datapie.sty, dataplot.sty, databar.sty, databib.sty, databib.bst, person.sty. \endpreamble @@ -35,6 +35,8 @@ \file{databib.sty}{\usepreamble\defaultpreamble \usepostamble\defaultpostamble\from{datatool.dtx}{databib.sty,package}} \file{databib.bst}{\nopreamble\usepreamble\defaultpreamble\nopostamble\from{datatool.dtx}{databib.bst}} +\file{person.sty}{\usepreamble\defaultpreamble +\usepostamble\defaultpostamble\from{datatool.dtx}{person.sty,package}} } \endbatchfile diff --git a/Master/texmf-dist/tex/latex/datatool/databar.sty b/Master/texmf-dist/tex/latex/datatool/databar.sty index ecf8ce763bf..a381960c486 100644 --- a/Master/texmf-dist/tex/latex/datatool/databar.sty +++ b/Master/texmf-dist/tex/latex/datatool/databar.sty @@ -21,7 +21,7 @@ %% %% The Current Maintainer of this work is Nicola Talbot. %% -%% This work consists of the files datatool.dtx and datatool.ins and the derived files datatool.sty, datapie.sty, dataplot.sty, databar.sty, databib.sty, databib.bst. +%% This work consists of the files datatool.dtx and datatool.ins and the derived files datatool.sty, datapie.sty, dataplot.sty, databar.sty, databib.sty, databib.bst, person.sty. %% %% \CharacterTable %% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z @@ -38,8 +38,13 @@ %% Right bracket \] Circumflex \^ Underscore \_ %% Grave accent \` Left brace \{ Vertical bar \| %% Right brace \} Tilde \~} +%% load student information from file "students.csv" +%% Iterate through the student database: +%% Define "anon": +%% Do the letter: +%% Undefine "anon": \NeedsTeXFormat{LaTeX2e} -\ProvidesPackage{databar}[2009/02/27 v2.0 (NLCT)] +\ProvidesPackage{databar}[2009/10/22 v2.01 (NLCT)] \RequirePackage{xkeyval} \RequirePackage{dataplot} \newif\ifDTLcolorbarchart diff --git a/Master/texmf-dist/tex/latex/datatool/databib.sty b/Master/texmf-dist/tex/latex/datatool/databib.sty index 44160a138d9..4e45c052256 100644 --- a/Master/texmf-dist/tex/latex/datatool/databib.sty +++ b/Master/texmf-dist/tex/latex/datatool/databib.sty @@ -21,7 +21,7 @@ %% %% The Current Maintainer of this work is Nicola Talbot. %% -%% This work consists of the files datatool.dtx and datatool.ins and the derived files datatool.sty, datapie.sty, dataplot.sty, databar.sty, databib.sty, databib.bst. +%% This work consists of the files datatool.dtx and datatool.ins and the derived files datatool.sty, datapie.sty, dataplot.sty, databar.sty, databib.sty, databib.bst, person.sty. %% %% \CharacterTable %% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z @@ -38,8 +38,13 @@ %% Right bracket \] Circumflex \^ Underscore \_ %% Grave accent \` Left brace \{ Vertical bar \| %% Right brace \} Tilde \~} +%% load student information from file "students.csv" +%% Iterate through the student database: +%% Define "anon": +%% Do the letter: +%% Undefine "anon": \NeedsTeXFormat{LaTeX2e} -\ProvidesPackage{databib}[2009/02/27 v2.0 (NLCT)] +\ProvidesPackage{databib}[2009/10/22 v2.01 (NLCT)] \RequirePackage{datatool} \newcommand*{\dtlbib@style}{plain} \define@choicekey{databib.sty}{style}{plain,abbrv,alpha}{% diff --git a/Master/texmf-dist/tex/latex/datatool/datapie.sty b/Master/texmf-dist/tex/latex/datatool/datapie.sty index f1af8129159..62916f4638d 100644 --- a/Master/texmf-dist/tex/latex/datatool/datapie.sty +++ b/Master/texmf-dist/tex/latex/datatool/datapie.sty @@ -21,7 +21,7 @@ %% %% The Current Maintainer of this work is Nicola Talbot. %% -%% This work consists of the files datatool.dtx and datatool.ins and the derived files datatool.sty, datapie.sty, dataplot.sty, databar.sty, databib.sty, databib.bst. +%% This work consists of the files datatool.dtx and datatool.ins and the derived files datatool.sty, datapie.sty, dataplot.sty, databar.sty, databib.sty, databib.bst, person.sty. %% %% \CharacterTable %% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z @@ -38,8 +38,13 @@ %% Right bracket \] Circumflex \^ Underscore \_ %% Grave accent \` Left brace \{ Vertical bar \| %% Right brace \} Tilde \~} +%% load student information from file "students.csv" +%% Iterate through the student database: +%% Define "anon": +%% Do the letter: +%% Undefine "anon": \NeedsTeXFormat{LaTeX2e} -\ProvidesPackage{datapie}[2007/02/27 v2.0 (NLCT)] +\ProvidesPackage{datapie}[2009/10/22 v2.01 (NLCT)] \RequirePackage{xkeyval} \newif\ifDTLcolorpiechart \DTLcolorpiecharttrue diff --git a/Master/texmf-dist/tex/latex/datatool/dataplot.sty b/Master/texmf-dist/tex/latex/datatool/dataplot.sty index 48500c6843c..3d67f7823de 100644 --- a/Master/texmf-dist/tex/latex/datatool/dataplot.sty +++ b/Master/texmf-dist/tex/latex/datatool/dataplot.sty @@ -21,7 +21,7 @@ %% %% The Current Maintainer of this work is Nicola Talbot. %% -%% This work consists of the files datatool.dtx and datatool.ins and the derived files datatool.sty, datapie.sty, dataplot.sty, databar.sty, databib.sty, databib.bst. +%% This work consists of the files datatool.dtx and datatool.ins and the derived files datatool.sty, datapie.sty, dataplot.sty, databar.sty, databib.sty, databib.bst, person.sty. %% %% \CharacterTable %% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z @@ -38,8 +38,13 @@ %% Right bracket \] Circumflex \^ Underscore \_ %% Grave accent \` Left brace \{ Vertical bar \| %% Right brace \} Tilde \~} +%% load student information from file "students.csv" +%% Iterate through the student database: +%% Define "anon": +%% Do the letter: +%% Undefine "anon": \NeedsTeXFormat{LaTeX2e} -\ProvidesPackage{dataplot}[2009/02/27 v2.0 (NLCT)] +\ProvidesPackage{dataplot}[2009/10/22 v2.01 (NLCT)] \RequirePackage{xkeyval} \RequirePackage{tikz} \RequirePackage{datatool} diff --git a/Master/texmf-dist/tex/latex/datatool/datatool.sty b/Master/texmf-dist/tex/latex/datatool/datatool.sty index 1d630179591..8306dba927c 100644 --- a/Master/texmf-dist/tex/latex/datatool/datatool.sty +++ b/Master/texmf-dist/tex/latex/datatool/datatool.sty @@ -21,7 +21,7 @@ %% %% The Current Maintainer of this work is Nicola Talbot. %% -%% This work consists of the files datatool.dtx and datatool.ins and the derived files datatool.sty, datapie.sty, dataplot.sty, databar.sty, databib.sty, databib.bst. +%% This work consists of the files datatool.dtx and datatool.ins and the derived files datatool.sty, datapie.sty, dataplot.sty, databar.sty, databib.sty, databib.bst, person.sty. %% %% \CharacterTable %% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z @@ -38,8 +38,13 @@ %% Right bracket \] Circumflex \^ Underscore \_ %% Grave accent \` Left brace \{ Vertical bar \| %% Right brace \} Tilde \~} +%% load student information from file "students.csv" +%% Iterate through the student database: +%% Define "anon": +%% Do the letter: +%% Undefine "anon": \NeedsTeXFormat{LaTeX2e} -\ProvidesPackage{datatool}[2009/07/13 v2.02 (NLCT)] +\ProvidesPackage{datatool}[2009/11/15 v2.03 (NLCT)] \RequirePackage{xkeyval} \RequirePackage{ifthen} \RequirePackage{xfor} @@ -1370,6 +1375,40 @@ \expandafter\newcount\csname dtlcols@#1\endcsname }% } +\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}{}{}% + }% +} +\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}{}{}% + }% +} \newcommand*{\DTLrowcount}[1]{% \expandafter\number\csname dtlrows@#1\endcsname} \newcommand*{\DTLcolumncount}[1]{% @@ -1451,7 +1490,7 @@ \newcommand*{\@sdtl@getcolumnindex}[3]{% \expandafter\let\expandafter#1\csname dtl@ci@#2@#3\endcsname } -\newcommand*{\dtl@columnindex}[2]{% +\newcommand*{\dtlcolumnindex}[2]{% \csname dtl@ci@#1@#2\endcsname } \newcommand*{\DTLgetkeyforcolumn}{% @@ -1529,7 +1568,7 @@ \newcommand*{\@sdtlgetdatatype}[3]{% \edef\@dtl@dogetdata{\noexpand\@dtl@getdatatype{\noexpand#1}% {\expandafter\the\csname dtlkeys@#2\endcsname}% - {\dtl@columnindex{#2}{#3}}}% + {\dtlcolumnindex{#2}{#3}}}% \@dtl@dogetdata } \newcommand*{\@dtl@getdatatype}[3]{% @@ -1571,7 +1610,7 @@ \@sDTLifhaskey{#1}{#2}% {% \expandafter\dtlcolumnnum\expandafter - =\dtl@columnindex{#1}{#2}\relax + =\dtlcolumnindex{#1}{#2}\relax \edef\@dtl@dogetprops{\noexpand\@dtl@getprops {\noexpand\@dtl@key}{\noexpand\@dtl@type}% {\noexpand\@dtl@colhead}{\noexpand\@dtl@before}% @@ -1667,7 +1706,7 @@ } \newcommand*{\@sDTLsetheader}[3]{% \expandafter\dtlcolumnnum\expandafter - =\dtl@columnindex{#1}{#2}\relax + =\dtlcolumnindex{#1}{#2}\relax \@dtl@setheaderforindex{#1}{\dtlcolumnnum}{#3}% } \newcommand*{\@dtl@setheaderforindex}[3]{% @@ -1696,6 +1735,14 @@ }% {\@dtl@after}% } +\newcommand*{\dtlexpandnewvalue}{% + \def\@dtl@setnewvalue##1{\protected@edef\@dtl@tmp{##1}% + \expandafter\@dtl@toks\expandafter{\@dtl@tmp}}% +} +\newcommand*{\dtlnoexpandnewvalue}{% + \def\@dtl@setnewvalue##1{\@dtl@toks{##1}}% +} +\dtlnoexpandnewvalue \newcommand{\DTLnewdbentry}{% \@ifstar\@sDTLnewdbentry\@DTLnewdbentry } @@ -1708,7 +1755,7 @@ \newcommand*{\@sDTLnewdbentry}[3]{% \@dtl@updatekeys{#1}{#2}{#3}% \expandafter\dtlcolumnnum\expandafter - =\dtl@columnindex{#1}{#2}\relax + =\dtlcolumnindex{#1}{#2}\relax \edef\dtl@dogetrow{\noexpand\dtlgetrow{#1}% {\number\csname dtlrows@#1\endcsname}}% \dtl@dogetrow @@ -1717,7 +1764,7 @@ }% \dtl@dogetentry \ifx\dtl@entry\dtlnovalue - \@dtl@toks{#3}% + \@dtl@setnewvalue{#3}% \toks@gconcat@middle@cx{dtldb@#1}% {\dtlbeforerow}% {% @@ -1748,30 +1795,30 @@ \newcommand*{\@dtl@assign}[2]{% \@dtl@assigncmd#1,\@nil\@@{#2}% } -\def\@dtl@assigncmd#1=#2,#3\@@#4{% - \@sDTLifhaskey{#4}{#2}% +\def\@dtl@assigncmd#1#2=#3,#4\@@#5{% + \@sDTLifhaskey{#5}{#3}% {% \edef\@dtl@dogetentry{% \noexpand\dtlgetentryfromcurrentrow - {\noexpand#1}{\dtl@columnindex{#4}{#2}}}% + {\noexpand#1}{\dtlcolumnindex{#5}{#3}}}% \@dtl@dogetentry \ifx#1\dtlnovalue - \@@dtl@setnull{#1}{#2}% + \@@dtl@setnull{#1}{#3}% \fi \global\let#1=#1\relax }% {% \PackageError{datatool}{Can't assign \string#1\space: there - is no key `#2' in data base `#4'}{}% + is no key `#3' in data base `#5'}{}% \global\let#1\DTLstringnull }% - \def\dtl@tmp{#3}% + \def\dtl@tmp{#4}% \ifx\@nnil\dtl@tmp \let\@dtl@next\@dtl@assigncmdnoop \else \let\@dtl@next\@dtl@assigncmd \fi - \@dtl@next#3\@@{#4}% + \@dtl@next#4\@@{#5}% } \def\@dtl@assigncmdnoop#1\@@#2{} \newcommand*{\@dtl@setnull}[2]{% @@ -2097,7 +2144,7 @@ \toks@{#4}% \edef\@dtl@doforcol{\noexpand\dtl@forcolumn{\noexpand#1}% {\expandafter\the\csname dtldb@#2\endcsname}% - {\dtl@columnindex{#2}{#3}}{\the\toks@}% + {\dtlcolumnindex{#2}{#3}}{\the\toks@}% }% \@dtl@doforcol% } @@ -2463,7 +2510,7 @@ \csname dtl@row\romannumeral\dtlforeachlevel\endcsname\relax \@dtl@updatekeys{\@dtl@thisdb}{#1}{#2}% \expandafter\dtlcolumnnum\expandafter - =\dtl@columnindex{\@dtl@thisdb}{#1}\relax + =\dtlcolumnindex{\@dtl@thisdb}{#1}\relax \dtlcurrentrow = \csname @dtl@cur\romannumeral\dtlforeachlevel\endcsname \edef\dtl@dogetentry{\noexpand\dtlgetentryfromcurrentrow @@ -2471,7 +2518,8 @@ }% \dtl@dogetentry \ifx\dtl@entry\dtlnovalue - \expandafter\@dtl@toks\expandafter{#2}% + \protected@edef\@dtl@tmp{#2}% + \expandafter\@dtl@toks\expandafter{\@dtl@tmp}% \toks@gput@right@cx{@dtl@cur\romannumeral\dtlforeachlevel}% {% \noexpand\db@col@id@w \number\dtlcolumnnum @@ -2584,7 +2632,8 @@ {\noexpand\dtl@post}% }% \@dtl@dosplitrow - \@dtl@toks{#2}% new value + \protected@edef\@dtl@tmp{#2}% + \expandafter\@dtl@toks\expandafter{\@dtl@tmp}% new value \expandafter\@dtl@before\expandafter{\dtl@pre}% \expandafter\@dtl@after\expandafter{\dtl@post}% \toks@gconcat@middle@cx @@ -3573,174 +3622,534 @@ \dtl@message{`\@dtl@a' <=> `\@dtl@b' = \number\dtl@sortresult}% \fi } -\newcommand*{\dtl@choplast}[3]{% -\let#2\@empty -\let#3\@empty -\@for\@dtl@element:=#1\do{% -\ifx#3\@empty -\else - \ifx#2\@empty - \expandafter\toks@\expandafter{#3}% - \edef#2{{\the\toks@}}% - \else - \expandafter\toks@\expandafter{#3}% - \expandafter\@dtl@toks\expandafter{#2}% - \edef#2{\the\@dtl@toks,{\the\toks@}}% - \fi -\fi -\let#3=\@dtl@element% -}% -} -\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 +\newwrite\@dtl@write +\newcommand*{\DTLsavedb}[2]{% + \DTLifdbexists{#1}% + {% + \openout\@dtl@write=#2\relax + \def\@dtl@header{}% + \dtlforeachkey(\@dtl@key,\@dtl@col,\@dtl@type,\@dtl@head)% + \in{#1}\do + {% + \IfSubStringInString{\@dtl@separator}{\@dtl@key}% + {% + \ifx\@dtl@header\@empty + \protected@edef\@dtl@header{% + \@dtl@delimiter\@dtl@key\@dtl@delimiter}% + \else + \toks@=\expandafter{\@dtl@header}% + \protected@edef\@dtl@header{% + \the\toks@\@dtl@separator + \@dtl@delimiter\@dtl@key\@dtl@delimiter}% + \fi + }% + {% + \ifx\@dtl@header\@empty + \protected@edef\@dtl@header{\@dtl@key}% + \else + \toks@=\expandafter{\@dtl@header}% + \protected@edef\@dtl@header{\the\toks@ + \@dtl@separator\@dtl@key}% + \fi + }% + }% + \protected@write\@dtl@write{}{\@dtl@header}% + \@sDTLforeach{#1}{}% + {% + \def\@dtl@row{}% + \DTLforeachkeyinrow{\@dtl@val}% + {% + \IfSubStringInString{\@dtl@separator}{\@dtl@val}% + {% + \ifx\@dtl@row\@empty + \protected@edef\@dtl@row{% + \@dtl@delimiter\@dtl@val\@dtl@delimiter}% + \else + \toks@=\expandafter{\@dtl@row}% + \protected@edef\@dtl@row{\the\toks@\@dtl@separator + \@dtl@delimiter\@dtl@val\@dtl@delimiter}% + \fi + }% + {% + \ifx\@dtl@row\@empty + \protected@edef\@dtl@row{\@dtl@val}% + \else + \toks@=\expandafter{\@dtl@row}% + \protected@edef\@dtl@row{\the\toks@\@dtl@separator + \@dtl@val}% + \fi + }% + }% + \protected@write\@dtl@write{}{\@dtl@row}% + }% + \closeout\@dtl@write + }% + {% + \PackageError{datatool}{Can't save database `#1': no such + database}{}% + }% } -\newcommand{\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 +\newcommand*{\DTLsavetexdb}[2]{% + \DTLifdbexists{#1}% + {% + \openout\@dtl@write=#2\relax + \protected@write\@dtl@write{}{\string\DTLnewdb{#1}}% + \@sDTLforeach{#1}{}% + {% + \protected@write\@dtl@write{}{\string\DTLnewrow*{#1}}% + \DTLforeachkeyinrow{\@dtl@val}% + {% + \DTLifnull{\@dtl@val}% + {\def\@dtl@val{}}% + {}% + \protected@write\@dtl@write{}{% + \string\DTLnewdbentry*{#1}{\dtlkey}{\@dtl@val}}% + }% + }% + \dtlforeachkey(\@dtl@k,\@dtl@c,\@dtl@t,\@dtl@h)\in{#1}\do + {% + \@onelevel@sanitize\@dtl@h + \protected@write\@dtl@write{}{% + \string\DTLsetheader*{#1}{\@dtl@k}{\@dtl@h}}% + }% + \closeout\@dtl@write + }% + {% + \PackageError{datatool}{Can't save database `#1': no such + database}{}% + }% } -\newcommand{\dtl@insertinto}[3]{% -\def\@dtl@newsortedlist{}% -\@dtl@insertdonefalse -\@for\dtl@srtelement:=#2\do{% -\if@dtl@insertdone - \expandafter\toks@\expandafter{\dtl@srtelement}% - \edef\@dtl@newstuff{{\the\toks@}}% -\else - \expandafter#3\expandafter{\dtl@srtelement}{#1}% - \ifnum\dtl@sortresult<0\relax - \expandafter\toks@\expandafter{\dtl@srtelement}% - \@dtl@toks{#1}% - \edef\@dtl@newstuff{{\the\@dtl@toks},{\the\toks@}}% - \@dtl@insertdonetrue - \else - \expandafter\toks@\expandafter{\dtl@srtelement}% - \edef\@dtl@newstuff{{\the\toks@}}% - \fi -\fi -\ifx\@dtl@newsortedlist\@empty - \expandafter\toks@\expandafter{\@dtl@newstuff}% - \edef\@dtl@newsortedlist{\the\toks@}% -\else - \expandafter\toks@\expandafter{\@dtl@newsortedlist}% - \expandafter\@dtl@toks\expandafter{\@dtl@newstuff}% - \edef\@dtl@newsortedlist{\the\toks@,\the\@dtl@toks}% -\fi -\@endforfalse -}% - \ifx\@dtl@newsortedlist\@empty - \@dtl@toks{#1}% - \edef\@dtl@newsortedlist{{\the\@dtl@toks}}% - \else - \if@dtl@insertdone - \else - \expandafter\toks@\expandafter{\@dtl@newsortedlist}% - \@dtl@toks{#1}% - \edef\@dtl@newsortedlist{\the\toks@,{\the\@dtl@toks}}% - \fi - \fi -\global\let#2=\@dtl@newsortedlist +\newcommand{\@longempty}{} +\newread\@dtl@read +\newcount\dtl@entrycr +\define@boolkey{loaddb}[dtl]{noheader}[true]{} +\define@key{loaddb}{keys}{% + \dtl@entrycr=0\relax + \@for\@dtl@key:=#1\do + {% + \advance\dtl@entrycr by 1\relax + \expandafter + \edef\csname @dtl@inky@\romannumeral\dtl@entrycr\endcsname{% + \@dtl@key}% + }% } -\newif\if@dtl@insertdone -\newcount\dtl@sortresult -\newcommand{\toks@gput@right@cx}[2]{% - \def\@toks@name{#1}% - \edef\@dtl@stuff{#2}% - \global\csname\@toks@name\endcsname\expandafter - \expandafter\expandafter{\expandafter\the - \csname\expandafter\@toks@name\expandafter\endcsname\@dtl@stuff}% +\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{\toks@gconcat@middle@cx}[4]{% - \def\@toks@name{#1}% - \edef\@dtl@stuff{#3}% - \global\csname\@toks@name\endcsname\expandafter\expandafter - \expandafter\expandafter\expandafter - \expandafter\expandafter{\expandafter\expandafter\expandafter - \the\expandafter\expandafter\expandafter#2% - \expandafter\@dtl@stuff\the#4}% +\newcommand*{\dtldefaultkey}{Column} +\newcommand*{\@dtl@readline}[2]{% + \read#1 to #2% + \dtl@trim#2% } -\newcommand*{\DTLadd}[3]{% -\DTLconverttodecimal{#2}{\@dtl@numi}% -\DTLconverttodecimal{#3}{\@dtl@numii}% -\FPadd{\@dtl@tmp}{\@dtl@numi}{\@dtl@numii}% -\ifx\@dtl@replaced\@empty - \DTLdecimaltolocale{\@dtl@tmp}{#1}% -\else - \DTLdecimaltocurrency{\@dtl@tmp}{#1}% -\fi +\newcommand*{\@dtl@readrawline}[2]{% + \@dtl@rawread#1 to #2% + \dtl@trim#2% + \dtl@domappings\@dtl@line } -\newcommand*{\DTLgadd}[3]{% -\DTLadd{\@dtl@tmpii}{#2}{#3}% -\global\let#1=\@dtl@tmpii + +\newcommand*{\DTLloaddb}{% + \let\@dtl@doreadline\@dtl@readline + \@dtlloaddb } -\newcommand*{\DTLaddall}[2]{% -\def\@dtl@sum{0}% -\@for\dtl@thisval:=#2\do{% - \DTLconverttodecimal{\dtl@thisval}{\@dtl@num}% - \FPadd{\@dtl@sum}{\@dtl@sum}{\@dtl@num}% -}% -\ifx\@dtl@replaced\@empty - \DTLdecimaltolocale{\@dtl@sum}{#1}% -\else - \DTLdecimaltocurrency{\@dtl@sum}{#1}% -\fi +\newcommand*{\@dtlloaddb}[3][]{% + \IfFileExists{#3}{% + \begingroup + \catcode`\"12\relax + \dtlnoheaderfalse + \setkeys{loaddb}{#1}% + \openin\@dtl@read=#3% + \dtl@message{Reading `#3'}% + \DTLnewdb{#2}% + \ifeof\@dtl@read + \PackageWarning{datatool}{File `#3' has no data}% + \else + \ifdtlnoheader + \else + \loop + \@dtl@conditionfalse + \ifeof\@dtl@read + \else + \@dtl@doreadline\@dtl@read\@dtl@line + \ifx\@dtl@line\@longempty + \@dtl@conditiontrue + \fi + \fi + \if@dtl@condition + \repeat + \protected@edef\@dtl@lin@{% + \@dtl@separator\@dtl@line\@dtl@separator}% + \dtl@entrycr=0\relax + \loop + \expandafter\@dtl@lopoff\@dtl@lin@\to\@dtl@lin@\@dtl@key + \advance\dtl@entrycr by 1\relax + \expandafter\@dtl@toks\expandafter{\@dtl@key}% + \@ifundefined{@dtl@inky@\romannumeral\dtl@entrycr}% + {% + \expandafter + \edef\csname @dtl@inky@\romannumeral + \dtl@entrycr\endcsname{\the\@dtl@toks}% + }% + {% + \@ifundefined{@dtl@inhd@\romannumeral\dtl@entrycr}% + {% + \expandafter + \edef\csname @dtl@inhd@\romannumeral + \dtl@entrycr\endcsname{\the\@dtl@toks}% + }% + {}% + }% + \ifx\@dtl@lin@\@dtl@separator + \@dtl@conditionfalse + \else + \@dtl@conditiontrue + \fi + \if@dtl@condition + \repeat + \fi + \ifeof\@dtl@read + \ifdtlnoheader + \PackageWarning{datatool}{No data in `#3'}% + \else + \PackageWarning{datatool}{Only header row found in `#3'}% + \fi + \else + \@dtl@conditiontrue + \loop + \@dtl@doreadline\@dtl@read\@dtl@line + \ifx\@dtl@line\@longempty + \else + \@sDTLnewrow{#2}% + \expandafter\@dtl@toks\expandafter{\@dtl@line}% + \edef\@dtl@lin@{\@dtl@separator\the\@dtl@toks + \@dtl@separator}% + \dtl@entrycr=0\relax + {% + \@dtl@conditiontrue + \loop + \expandafter\@dtl@lopoff\@dtl@lin@\to + \@dtl@lin@\@dtl@thisentry + \advance\dtl@entrycr by 1\relax + \@ifundefined{@dtl@inky@\romannumeral\dtl@entrycr}% + {% + \edef\@dtl@thiskey{\dtldefaultkey + \number\dtl@entrycr}% + \expandafter\let + \csname @dtl@inky@\romannumeral + \dtl@entrycr\endcsname\@dtl@thiskey + }% + {% + \edef\@dtl@thiskey{% + \csname @dtl@inky@\romannumeral + \dtl@entrycr\endcsname}% + }% + \expandafter\@dtl@toks\expandafter{\@dtl@thisentry}% + \edef\@do@dtlnewentry{\noexpand\@sDTLnewdbentry + {#2}{\@dtl@thiskey}{\the\@dtl@toks}}% + \@do@dtlnewentry + \ifx\@dtl@lin@\@dtl@separator + \@dtl@conditionfalse + \fi + \if@dtl@condition + \repeat + }% + \fi + \ifeof\@dtl@read \@dtl@conditionfalse\fi + \if@dtl@condition + \repeat + \fi + \fi + \closein\@dtl@read + \edef\@dtl@maxcols{\expandafter + \number\csname dtlcols@#2\endcsname}% + \dtlgforint\dtl@entrycr=1\to\@dtl@maxcols\step1\do + {% + \@ifundefined{@dtl@inhd@\romannumeral\dtl@entrycr}% + {}% + {% + \expandafter\let\expandafter\@dtl@head + \csname @dtl@inhd@\romannumeral\dtl@entrycr\endcsname + \@dtl@toks=\expandafter{\@dtl@head}% + \edef\@dtl@dosetheader{\noexpand\@dtl@setheaderforindex + {#2}{\number\dtl@entrycr}{\the\@dtl@toks}}% + \@dtl@dosetheader + }% + }% + \endgroup + }{% + \PackageError{datatool}{Can't load database `#2' (file `#3' + doesn't exist)}{}% + }% } -\newcommand*{\DTLgaddall}[2]{% -\DTLaddall{\@dtl@tmpi}{#2}% -\global\let#1=\@dtl@tmpi +\newcommand{\dtl@trim}[1]{% +\def\@dtl@trmstr{}% +\expandafter\@dtl@starttrim#1\@nil% +\let#1=\@dtl@trmstr } -\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}% +\long\def\@dtl@starttrim#1#2{% +\ifx\par#1% + \def\@dtl@dotrim{\@dtl@trim{} #2}% \else - \DTLdecimaltocurrency{\@dtl@tmp}{#1}% + \def\@dtl@dotrim{\@dtl@trim#1#2}% \fi +\@dtl@dotrim% } -\newcommand*{\DTLgsub}[3]{% -\DTLsub{\@dtl@tmpii}{#2}{#3}% -\global\let#1=\@dtl@tmpii +\long\def\@dtl@trim#1 \@nil{\long\def\@dtl@trmstr{#1}} +\newcommand*\DTLloadrawdb{% + \let\@dtl@doreadline\@dtl@readrawline + \@dtlloaddb } -\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}% +\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 +\begingroup +\catcode`\{=\active +\catcode`\}=\active +\catcode`<=1\relax +\catcode`>=2\relax +\gdef\@dtl@activatebraces<% + \catcode`\{=\active + \catcode`\}=\active + \def{<\noexpand\{>% + \def}<\noexpand\}>% +>% +\endgroup +\newcommand*{\DTLrawmap}[2]{% +\expandafter\@dtl@toks\expandafter{\@dtl@rawmappings}% +\ifx\@dtl@rawmappings\@empty + \def\@dtl@rawmappings{{#1}{#2}}% \else - \DTLdecimaltocurrency{\@dtl@tmp}{#1}% + \def\@dtl@tmp{{#1}{#2}} + \protected@edef\@dtl@rawmappings{\the\@dtl@toks,\@dtl@tmp} \fi } -\newcommand*{\DTLgmul}[3]{% -\DTLmul{\@dtl@tmpii}{#2}{#3}% -\global\let#1=\@dtl@tmpii +\newcommand*{\@dtl@rawmappings}{} +\newcommand*{\dtl@domappings}[1]{% +\@for\@dtl@map:=\@dtl@rawmappings\do{% + \expandafter\DTLsubstitute\expandafter#1\@dtl@map +}} +\newcommand*{\DTLifinlist}[4]{% + \def\@dtl@doifinlist##1,#1,##2\end@dtl@doifinlist{% + \def\@before{##1}% + \def\@after{##2}% + }% + \expandafter\@dtl@doifinlist\expandafter,#2,#1,\@nil + \end@dtl@doifinlist + \ifx\@after\@nnil + #4% + \else + #3% + \fi } -\newcommand*{\DTLdiv}[3]{% -\let\@dtl@thisreplaced=\@empty -\DTLconverttodecimal{#2}{\@dtl@numi}% +\newcommand*{\dtl@choplast}[3]{% +\let#2\@empty +\let#3\@empty +\@for\@dtl@element:=#1\do{% +\ifx#3\@empty +\else + \ifx#2\@empty + \expandafter\toks@\expandafter{#3}% + \edef#2{{\the\toks@}}% + \else + \expandafter\toks@\expandafter{#3}% + \expandafter\@dtl@toks\expandafter{#2}% + \edef#2{\the\@dtl@toks,{\the\toks@}}% + \fi +\fi +\let#3=\@dtl@element% +}% +} +\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 +} +\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 +} +\newcommand{\dtl@insertinto}[3]{% +\def\@dtl@newsortedlist{}% +\@dtl@insertdonefalse +\@for\dtl@srtelement:=#2\do{% +\if@dtl@insertdone + \expandafter\toks@\expandafter{\dtl@srtelement}% + \edef\@dtl@newstuff{{\the\toks@}}% +\else + \expandafter#3\expandafter{\dtl@srtelement}{#1}% + \ifnum\dtl@sortresult<0\relax + \expandafter\toks@\expandafter{\dtl@srtelement}% + \@dtl@toks{#1}% + \edef\@dtl@newstuff{{\the\@dtl@toks},{\the\toks@}}% + \@dtl@insertdonetrue + \else + \expandafter\toks@\expandafter{\dtl@srtelement}% + \edef\@dtl@newstuff{{\the\toks@}}% + \fi +\fi +\ifx\@dtl@newsortedlist\@empty + \expandafter\toks@\expandafter{\@dtl@newstuff}% + \edef\@dtl@newsortedlist{\the\toks@}% +\else + \expandafter\toks@\expandafter{\@dtl@newsortedlist}% + \expandafter\@dtl@toks\expandafter{\@dtl@newstuff}% + \edef\@dtl@newsortedlist{\the\toks@,\the\@dtl@toks}% +\fi +\@endforfalse +}% + \ifx\@dtl@newsortedlist\@empty + \@dtl@toks{#1}% + \edef\@dtl@newsortedlist{{\the\@dtl@toks}}% + \else + \if@dtl@insertdone + \else + \expandafter\toks@\expandafter{\@dtl@newsortedlist}% + \@dtl@toks{#1}% + \edef\@dtl@newsortedlist{\the\toks@,{\the\@dtl@toks}}% + \fi + \fi +\global\let#2=\@dtl@newsortedlist +} +\newif\if@dtl@insertdone +\newcount\dtl@sortresult +\newcommand{\toks@gput@right@cx}[2]{% + \def\@toks@name{#1}% + \edef\@dtl@stuff{#2}% + \global\csname\@toks@name\endcsname\expandafter + \expandafter\expandafter{\expandafter\the + \csname\expandafter\@toks@name\expandafter\endcsname\@dtl@stuff}% +} +\newcommand{\toks@gconcat@middle@cx}[4]{% + \def\@toks@name{#1}% + \edef\@dtl@stuff{#3}% + \global\csname\@toks@name\endcsname\expandafter\expandafter + \expandafter\expandafter\expandafter + \expandafter\expandafter{\expandafter\expandafter\expandafter + \the\expandafter\expandafter\expandafter#2% + \expandafter\@dtl@stuff\the#4}% +} +\newcommand*{\DTLadd}[3]{% +\DTLconverttodecimal{#2}{\@dtl@numi}% +\DTLconverttodecimal{#3}{\@dtl@numii}% +\FPadd{\@dtl@tmp}{\@dtl@numi}{\@dtl@numii}% +\ifx\@dtl@replaced\@empty + \DTLdecimaltolocale{\@dtl@tmp}{#1}% +\else + \DTLdecimaltocurrency{\@dtl@tmp}{#1}% +\fi +} +\newcommand*{\DTLgadd}[3]{% +\DTLadd{\@dtl@tmpii}{#2}{#3}% +\global\let#1=\@dtl@tmpii +} +\newcommand*{\DTLaddall}[2]{% +\def\@dtl@sum{0}% +\@for\dtl@thisval:=#2\do{% + \DTLconverttodecimal{\dtl@thisval}{\@dtl@num}% + \FPadd{\@dtl@sum}{\@dtl@sum}{\@dtl@num}% +}% +\ifx\@dtl@replaced\@empty + \DTLdecimaltolocale{\@dtl@sum}{#1}% +\else + \DTLdecimaltocurrency{\@dtl@sum}{#1}% +\fi +} +\newcommand*{\DTLgaddall}[2]{% +\DTLaddall{\@dtl@tmpi}{#2}% +\global\let#1=\@dtl@tmpi +} +\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 +} +\newcommand*{\DTLgsub}[3]{% +\DTLsub{\@dtl@tmpii}{#2}{#3}% +\global\let#1=\@dtl@tmpii +} +\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 +} +\newcommand*{\DTLgmul}[3]{% +\DTLmul{\@dtl@tmpii}{#2}{#3}% +\global\let#1=\@dtl@tmpii +} +\newcommand*{\DTLdiv}[3]{% +\let\@dtl@thisreplaced=\@empty +\DTLconverttodecimal{#2}{\@dtl@numi}% \ifx\@dtl@replaced\@empty \else \let\@dtl@thisreplaced=\@dtl@replaced @@ -4048,532 +4457,185 @@ \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 -} -\def\@dtl@initials#1#2 #3{% -\dtl@initialshyphen#2-{}\dtl@endhyp -\expandafter\@dtl@toks\expandafter{\dtl@initialscmd}% -\toks@{#1}% -\ifx\dtl@inithyphen\@empty -\else - \edef\dtl@initialscmd{\the\@dtl@toks\the\toks@}% - \expandafter\@dtl@toks\expandafter{\dtl@initialscmd}% - \expandafter\toks@\expandafter{\dtl@inithyphen}% -\fi -\def\dtl@tmp{#3}% -\ifx\@nnil\dtl@tmp - \edef\dtl@initialscmd{\the\@dtl@toks\the\toks@\DTLafterinitials}% - \let\dtl@initialsnext=\@gobble -\else - \edef\dtl@initialscmd{\the\@dtl@toks\the\toks@\DTLbetweeninitials}% - \let\dtl@initialsnext=\dtl@initials -\fi -\dtl@initialsnext{#3}} -\def\dtl@initialshyphen#1-#2#3\dtl@endhyp{% -\def\dtl@inithyphen{#2}% -\ifx\dtl@inithyphen\@empty -\else - \edef\dtl@inithyphen{% - \DTLafterinitialbeforehyphen\DTLinitialhyphen#2}% -\fi -} -\newcommand*{\DTLafterinitials}{.} -\newcommand*{\DTLbetweeninitials}{.} -\newcommand*{\DTLafterinitialbeforehyphen}{.} -\newcommand*{\DTLinitialhyphen}{-} -\newcommand*{\DTLifAllUpperCase}[3]{% -\protected@edef\dtl@tuc{#1}% -\expandafter\dtl@testifuppercase\dtl@tuc\@nil\relax -\if@dtl@condition#2\else#3\fi -} -\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 -} -\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*{\DTLifAllLowerCase}[3]{% -\protected@edef\dtl@tlc{#1}% -\expandafter\dtl@testiflowercase\dtl@tlc\@nil\relax -\if@dtl@condition#2\else#3\fi -} -\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 -} -\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 -}}} -\newwrite\@dtl@write -\newcommand*{\DTLsavedb}[2]{% - \DTLifdbexists{#1}% - {% - \openout\@dtl@write=#2\relax - \def\@dtl@header{}% - \dtlforeachkey(\@dtl@key,\@dtl@col,\@dtl@type,\@dtl@head)% - \in{#1}\do - {% - \IfSubStringInString{\@dtl@separator}{\@dtl@key}% - {% - \ifx\@dtl@header\@empty - \protected@edef\@dtl@header{% - \@dtl@delimiter\@dtl@key\@dtl@delimiter}% - \else - \toks@=\expandafter{\@dtl@header}% - \protected@edef\@dtl@header{% - \the\toks@\@dtl@separator - \@dtl@delimiter\@dtl@key\@dtl@delimiter}% - \fi - }% - {% - \ifx\@dtl@header\@empty - \protected@edef\@dtl@header{\@dtl@key}% - \else - \toks@=\expandafter{\@dtl@header}% - \protected@edef\@dtl@header{\the\toks@ - \@dtl@separator\@dtl@key}% - \fi - }% - }% - \protected@write\@dtl@write{}{\@dtl@header}% - \@sDTLforeach{#1}{}% - {% - \def\@dtl@row{}% - \DTLforeachkeyinrow{\@dtl@val}% - {% - \IfSubStringInString{\@dtl@separator}{\@dtl@val}% - {% - \ifx\@dtl@row\@empty - \protected@edef\@dtl@row{% - \@dtl@delimiter\@dtl@val\@dtl@delimiter}% - \else - \toks@=\expandafter{\@dtl@row}% - \protected@edef\@dtl@row{\the\toks@\@dtl@separator - \@dtl@delimiter\@dtl@val\@dtl@delimiter}% - \fi - }% - {% - \ifx\@dtl@row\@empty - \protected@edef\@dtl@row{\@dtl@val}% - \else - \toks@=\expandafter{\@dtl@row}% - \protected@edef\@dtl@row{\the\toks@\@dtl@separator - \@dtl@val}% - \fi - }% - \protected@write\@dtl@write{}{\@dtl@row}% - }% - }% - \closeout\@dtl@write - }% - {% - \PackageError{datatool}{Can't save database `#1': no such - database}{}% - }% -} -\newcommand*{\DTLsavetexdb}[2]{% - \DTLifdbexists{#1}% - {% - \openout\@dtl@write=#2\relax - \protected@write\@dtl@write{}{\string\DTLnewdb{#1}}% - \@sDTLforeach{#1}{}% - {% - \protected@write\@dtl@write{}{\string\DTLnewrow*{#1}}% - \DTLforeachkeyinrow{\@dtl@val}% - {% - \DTLifnull{\@dtl@val}% - {\def\@dtl@val{}}% - {}% - \protected@write\@dtl@write{}{% - \string\DTLnewdbentry*{#1}{\dtlkey}{\@dtl@val}}% - }% - }% - \dtlforeachkey(\@dtl@k,\@dtl@c,\@dtl@t,\@dtl@h)\in{#1}\do - {% - \@onelevel@sanitize\@dtl@h - \protected@write\@dtl@write{}{% - \string\DTLsetheader*{#1}{\@dtl@k}{\@dtl@h}}% - }% - \closeout\@dtl@write - }% - {% - \PackageError{datatool}{Can't save database `#1': no such - database}{}% - }% -} -\newcommand{\@longempty}{} -\newread\@dtl@read -\newcount\dtl@entrycr -\define@boolkey{loaddb}[dtl]{noheader}[true]{} -\define@key{loaddb}{keys}{% - \dtl@entrycr=0\relax - \@for\@dtl@key:=#1\do - {% - \advance\dtl@entrycr by 1\relax - \expandafter - \edef\csname @dtl@inky@\romannumeral\dtl@entrycr\endcsname{% - \@dtl@key}% - }% -} -\define@key{loaddb}{headers}{% - \dtl@entrycr=0\relax - \@for\@dtl@head:=#1\do - {% - \advance\dtl@entrycr by 1\relax - \toks@=\expandafter{\@dtl@head}% - \expandafter - \edef\csname @dtl@inhd@\romannumeral\dtl@entrycr\endcsname{% - \the\toks@}% - }% -} -\newcommand*{\dtldefaultkey}{Column} -\newcommand*{\@dtl@readline}[2]{% - \read#1 to #2% - \dtl@trim#2% -} -\newcommand*{\@dtl@readrawline}[2]{% - \@dtl@rawread#1 to #2% - \dtl@trim#2% - \dtl@domappings\@dtl@line -} - -\newcommand*{\DTLloaddb}{% - \let\@dtl@doreadline\@dtl@readline - \@dtlloaddb -} -\newcommand*{\@dtlloaddb}[3][]{% - \IfFileExists{#3}{% - \begingroup - \catcode`\"12\relax - \dtlnoheaderfalse - \setkeys{loaddb}{#1}% - \openin\@dtl@read=#3% - \dtl@message{Reading `#3'}% - \DTLnewdb{#2}% - \ifeof\@dtl@read - \PackageWarning{datatool}{File `#3' has no data}% - \else - \ifdtlnoheader - \else - \loop - \@dtl@conditionfalse - \ifeof\@dtl@read - \else - \@dtl@doreadline\@dtl@read\@dtl@line - \ifx\@dtl@line\@longempty - \@dtl@conditiontrue - \fi - \fi - \if@dtl@condition - \repeat - \protected@edef\@dtl@lin@{% - \@dtl@separator\@dtl@line\@dtl@separator}% - \dtl@entrycr=0\relax - \loop - \expandafter\@dtl@lopoff\@dtl@lin@\to\@dtl@lin@\@dtl@key - \advance\dtl@entrycr by 1\relax - \expandafter\@dtl@toks\expandafter{\@dtl@key}% - \@ifundefined{@dtl@inky@\romannumeral\dtl@entrycr}% - {% - \expandafter - \edef\csname @dtl@inky@\romannumeral - \dtl@entrycr\endcsname{\the\@dtl@toks}% - }% - {% - \@ifundefined{@dtl@inhd@\romannumeral\dtl@entrycr}% - {% - \expandafter - \edef\csname @dtl@inhd@\romannumeral - \dtl@entrycr\endcsname{\the\@dtl@toks}% - }% - {}% - }% - \ifx\@dtl@lin@\@dtl@separator - \@dtl@conditionfalse - \else - \@dtl@conditiontrue - \fi - \if@dtl@condition - \repeat - \fi - \ifeof\@dtl@read - \ifdtlnoheader - \PackageWarning{datatool}{No data in `#3'}% - \else - \PackageWarning{datatool}{Only header row found in `#3'}% - \fi - \else - \@dtl@conditiontrue - \loop - \@dtl@doreadline\@dtl@read\@dtl@line - \ifx\@dtl@line\@longempty - \else - \@sDTLnewrow{#2}% - \expandafter\@dtl@toks\expandafter{\@dtl@line}% - \edef\@dtl@lin@{\@dtl@separator\the\@dtl@toks - \@dtl@separator}% - \dtl@entrycr=0\relax - {% - \@dtl@conditiontrue - \loop - \expandafter\@dtl@lopoff\@dtl@lin@\to - \@dtl@lin@\@dtl@thisentry - \advance\dtl@entrycr by 1\relax - \@ifundefined{@dtl@inky@\romannumeral\dtl@entrycr}% - {% - \edef\@dtl@thiskey{\dtldefaultkey - \number\dtl@entrycr}% - \expandafter\let - \csname @dtl@inky@\romannumeral - \dtl@entrycr\endcsname\@dtl@thiskey - }% - {% - \edef\@dtl@thiskey{% - \csname @dtl@inky@\romannumeral - \dtl@entrycr\endcsname}% - }% - \expandafter\@dtl@toks\expandafter{\@dtl@thisentry}% - \edef\@do@dtlnewentry{\noexpand\@sDTLnewdbentry - {#2}{\@dtl@thiskey}{\the\@dtl@toks}}% - \@do@dtlnewentry - \ifx\@dtl@lin@\@dtl@separator - \@dtl@conditionfalse - \fi - \if@dtl@condition - \repeat - }% - \fi - \ifeof\@dtl@read \@dtl@conditionfalse\fi - \if@dtl@condition - \repeat - \fi - \fi - \closein\@dtl@read - \edef\@dtl@maxcols{\expandafter - \number\csname dtlcols@#2\endcsname}% - \dtlgforint\dtl@entrycr=1\to\@dtl@maxcols\step1\do - {% - \@ifundefined{@dtl@inhd@\romannumeral\dtl@entrycr}% - {}% - {% - \expandafter\let\expandafter\@dtl@head - \csname @dtl@inhd@\romannumeral\dtl@entrycr\endcsname - \@dtl@toks=\expandafter{\@dtl@head}% - \edef\@dtl@dosetheader{\noexpand\@dtl@setheaderforindex - {#2}{\number\dtl@entrycr}{\the\@dtl@toks}}% - \@dtl@dosetheader - }% - }% - \endgroup - }{% - \PackageError{datatool}{Can't load database `#2' (file `#3' - doesn't exist)}{}% - }% + \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 } -\newcommand{\dtl@trim}[1]{% -\def\@dtl@trmstr{}% -\expandafter\@dtl@starttrim#1\@nil% -\let#1=\@dtl@trmstr +\def\@dtl@initials#1#2 #3{% +\dtl@initialshyphen#2-{}\dtl@endhyp +\expandafter\@dtl@toks\expandafter{\dtl@initialscmd}% +\toks@{#1}% +\ifx\dtl@inithyphen\@empty +\else + \edef\dtl@initialscmd{\the\@dtl@toks\the\toks@}% + \expandafter\@dtl@toks\expandafter{\dtl@initialscmd}% + \expandafter\toks@\expandafter{\dtl@inithyphen}% +\fi +\def\dtl@tmp{#3}% +\ifx\@nnil\dtl@tmp + \edef\dtl@initialscmd{\the\@dtl@toks\the\toks@\DTLafterinitials}% + \let\dtl@initialsnext=\@gobble +\else + \edef\dtl@initialscmd{\the\@dtl@toks\the\toks@\DTLbetweeninitials}% + \let\dtl@initialsnext=\dtl@initials +\fi +\dtl@initialsnext{#3}} +\def\dtl@initialshyphen#1-#2#3\dtl@endhyp{% +\def\dtl@inithyphen{#2}% +\ifx\dtl@inithyphen\@empty +\else + \edef\dtl@inithyphen{% + \DTLafterinitialbeforehyphen\DTLinitialhyphen#2}% +\fi } -\long\def\@dtl@starttrim#1#2{% -\ifx\par#1% - \def\@dtl@dotrim{\@dtl@trim{} #2}% +\newcommand*{\DTLafterinitials}{.} +\newcommand*{\DTLbetweeninitials}{.} +\newcommand*{\DTLafterinitialbeforehyphen}{.} +\newcommand*{\DTLinitialhyphen}{-} +\newcommand*{\DTLifAllUpperCase}[3]{% +\protected@edef\dtl@tuc{#1}% +\expandafter\dtl@testifuppercase\dtl@tuc\@nil\relax +\if@dtl@condition#2\else#3\fi +} +\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 - \def\@dtl@dotrim{\@dtl@trim#1#2}% + \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 -\@dtl@dotrim% +\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 } -\long\def\@dtl@trim#1 \@nil{\long\def\@dtl@trmstr{#1}} -\newcommand*\DTLloadrawdb{% - \let\@dtl@doreadline\@dtl@readrawline - \@dtlloaddb +\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*{\DTLifAllLowerCase}[3]{% +\protected@edef\dtl@tlc{#1}% +\expandafter\dtl@testiflowercase\dtl@tlc\@nil\relax +\if@dtl@condition#2\else#3\fi } -\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 -\begingroup -\catcode`\{=\active -\catcode`\}=\active -\catcode`<=1\relax -\catcode`>=2\relax -\gdef\@dtl@activatebraces<% - \catcode`\{=\active - \catcode`\}=\active - \def{<\noexpand\{>% - \def}<\noexpand\}>% ->% -\endgroup -\newcommand*{\DTLrawmap}[2]{% -\expandafter\@dtl@toks\expandafter{\@dtl@rawmappings}% -\ifx\@dtl@rawmappings\@empty - \def\@dtl@rawmappings{{#1}{#2}}% +\def\dtl@testiflowercase#1#2{% +\def\dtl@argi{#1}% +\def\dtl@argii{#2}% +\ifx\dtl@argi\@nnil + \let\dtl@testiflowernext=\@nnil \else - \def\@dtl@tmp{{#1}{#2}} - \protected@edef\@dtl@rawmappings{\the\@dtl@toks,\@dtl@tmp} + \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*{\@dtl@rawmappings}{} -\newcommand*{\dtl@domappings}[1]{% -\@for\@dtl@map:=\@dtl@rawmappings\do{% - \expandafter\DTLsubstitute\expandafter#1\@dtl@map -}} +\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{\DTLsubstitute}[3]{% \expandafter\DTLsplitstring\expandafter {#1}{#2}{\@dtl@beforepart}{\@dtl@afterpart}% @@ -4628,19 +4690,6 @@ \@dtl@dosubstnext{#1}{#2}% } \def\@dtl@dosubstitutenoop#1#2{} -\newcommand*{\DTLifinlist}[4]{% - \def\@dtl@doifinlist##1,#1,##2\end@dtl@doifinlist{% - \def\@before{##1}% - \def\@after{##2}% - }% - \expandafter\@dtl@doifinlist\expandafter,#2,#1,\@nil - \end@dtl@doifinlist - \ifx\@after\@nnil - #4% - \else - #3% - \fi -} \newcommand*{\@dtl@currencies}{\$,\pounds} \newcommand*{\DTLnewcurrencysymbol}[1]{% \expandafter\toks@\expandafter{\@dtl@currencies}% diff --git a/Master/texmf-dist/tex/latex/datatool/person.sty b/Master/texmf-dist/tex/latex/datatool/person.sty new file mode 100644 index 00000000000..3a6ea1b6d27 --- /dev/null +++ b/Master/texmf-dist/tex/latex/datatool/person.sty @@ -0,0 +1,638 @@ +%% +%% This is file `person.sty', +%% generated with the docstrip utility. +%% +%% The original source files were: +%% +%% datatool.dtx (with options: `person.sty,package') +%% +%% datatool.dtx +%% Copyright 2009 Nicola Talbot +%% +%% This work may be distributed and/or modified under the +%% conditions of the LaTeX Project Public License, either version 1.3 +%% of this license of (at your option) any later version. +%% The latest version of this license is in +%% http://www.latex-project.org/lppl.txt +%% and version 1.3 or later is part of all distributions of LaTeX +%% version 2005/12/01 or later. +%% +%% This work has the LPPL maintenance status `maintained'. +%% +%% 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. +%% +%% \CharacterTable +%% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z +%% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z +%% Digits \0\1\2\3\4\5\6\7\8\9 +%% Exclamation \! Double quote \" Hash (number) \# +%% Dollar \$ Percent \% Ampersand \& +%% Acute accent \' Left paren \( Right paren \) +%% Asterisk \* Plus \+ Comma \, +%% Minus \- Point \. Solidus \/ +%% Colon \: Semicolon \; Less than \< +%% Equals \= Greater than \> Question mark \? +%% Commercial at \@ Left bracket \[ Backslash \\ +%% Right bracket \] Circumflex \^ Underscore \_ +%% Grave accent \` Left brace \{ Vertical bar \| +%% Right brace \} Tilde \~} +%% load student information from file "students.csv" +%% Iterate through the student database: +%% Define "anon": +%% Do the letter: +%% Undefine "anon": +\NeedsTeXFormat{LaTeX2e} +\ProvidesPackage{person}[2009/11/15 v1.01 (NLCT)] +\RequirePackage{ifthen} +\RequirePackage{datatool} +\newcounter{people} +\newcounter{person} +\newcommand*{\@people@list}{,} +\newcommand*{\@get@firstperson}[1]{% + \expandafter\@@get@firstperson\@people@list,\@nil{#1}} + \def\@@get@firstperson,#1,#2\@nil#3{% + \def#3{#1}% +} +\newcommand*{\malelabels}{male,Male,MALE,M,m} +\newcommand*{\addmalelabel}[1]{% + \expandafter\@dtl@toksA\expandafter{\malelabels}% + \expandafter\@dtl@toksB\expandafter{#1}% + \edef\malelabels{\the\@dtl@toksA,\the\@dtl@toksB}% +} +\newcommand*{\addfemalelabel}[1]{% + \expandafter\@dtl@toksA\expandafter{\femalelabels}% + \expandafter\@dtl@toksB\expandafter{#1}% + \edef\femalelabels{\the\@dtl@toksA,\the\@dtl@toksB}% +} +\newcommand*{\femalelabels}{female,Female,FEMALE,F,f} +\newcommand{\ifmalelabel}[3]{% + \expandafter\DTLifinlist\expandafter{#1}{\malelabels}{#2}{#3}% +} +\newcommand{\iffemalelabel}[3]{% + \expandafter\DTLifinlist\expandafter{#1}{\femalelabels}{#2}{#3}% +} +\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}{}% + }% +} +\newcommand*{\removeperson}[1][anon]{% + \edef\@person@label{#1}% + \expandafter\@removeperson\expandafter{\@person@label}% +} +\newcommand*{\@removeperson}[1]{% + \ifpersonexists{#1}% + {% + \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}% + \addtocounter{people}{-1}% + \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}{}% + }% +} +\newcommand*{\removepeople}[1]{% + \@for\@thisperson:=#1\do{% + \ifx\@thisperson\@empty + \else + \expandafter\removeperson\expandafter[\@thisperson]% + \fi + }% +} +\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{,}% +} +\newcommand{\ifpersonexists}[3]{% + \@ifundefined{person@#1@name}{#3}{#2}% +} +\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} +\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 +} +\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} +\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 +} +\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 + }% +} +\newcommand*{\malepronoun}{he} +\newcommand*{\femalepronoun}{she} +\newcommand*{\pluralpronoun}{they} +\newcommand*{\maleobjpronoun}{him} +\newcommand*{\femaleobjpronoun}{her} +\newcommand*{\pluralobjpronoun}{them} +\newcommand*{\malepossadj}{his} +\newcommand*{\femalepossadj}{her} +\newcommand*{\pluralpossadj}{their} +\newcommand*{\maleposspronoun}{his} +\newcommand*{\femaleposspronoun}{hers} +\newcommand*{\pluralposspronoun}{theirs} +\newcommand*{\malechild}{son} +\newcommand*{\femalechild}{daughter} +\newcommand*{\pluralchild}{children} +\newcommand*{\malechildren}{sons} +\newcommand*{\femalechildren}{daughters} +\newcommand*{\maleparent}{father} +\newcommand*{\femaleparent}{mother} +\newcommand*{\pluralparent}{parents} +\newcommand*{\malesibling}{brother} +\newcommand*{\femalesibling}{sister} +\newcommand*{\pluralsibling}{siblings} +\newcommand*{\malesiblings}{brothers} +\newcommand*{\femalesiblings}{sisters} +\providecommand*{\andname}{and} +\newcommand*{\malename}{male} +\newcommand*{\femalename}{female} +\newcommand*{\personsep}{, } +\newcommand*{\personlastsep}{\space\andname\space} +\newcommand*{\twopeoplesep}{\space\andname\space} +\newcommand*{\personfullname}[1][anon]{% + \@ifundefined{person@#1@fullname}% + {% + \PackageError{person}{Person `#1' has not been defined}{}% + }% + {% + \csname person@#1@fullname\endcsname + }% +} +\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 + }% + }% +} +\newcommand*{\personname}[1][anon]{% + \@ifundefined{person@#1@name}% + {% + \PackageError{person}{Person `#1' has not been defined}{}% + }% + {% + \csname person@#1@name\endcsname + }% +} +\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 + }% + }% +} +\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 + }% +} +\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 + }% +} +\newcommand*{\peoplepronoun}{% + \ifnum\c@people>1\relax + \pluralpronoun + \else + \@get@firstperson{\@thisperson}% + \personpronoun[\@thisperson]% + \fi +} +\newcommand*{\Peoplepronoun}{% + \ifnum\c@people>1\relax + \expandafter\MakeUppercase\pluralpronoun + \else + \@get@firstperson{\@thisperson}% + \Personpronoun[\@thisperson]% + \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 + }% +} +\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 + }% +} +\newcommand*{\peopleobjpronoun}{% + \ifnum\c@people>1\relax + \pluralobjpronoun + \else + \@get@firstperson{\@thisperson}% + \personobjpronoun[\@thisperson]% + \fi +} +\newcommand*{\Peopleobjpronoun}{% + \ifnum\c@people>1\relax + \expandafter\MakeUppercase\pluralobjpronoun + \else + \@get@firstperson{\@thisperson}% + \Personobjpronoun[\@thisperson]% + \fi +} +\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 + }% +} +\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 + }% +} +\newcommand*{\peoplepossadj}{% + \ifnum\c@people>1\relax + \pluralpossadj + \else + \@get@firstperson{\@thisperson}% + \personpossadj[\@thisperson]% + \fi +} +\newcommand*{\Peoplepossadj}{% + \ifnum\c@people>1\relax + \expandafter\MakeUppercase\pluralpossadj + \else + \@get@firstperson{\@thisperson}% + \Personpossadj[\@thisperson]% + \fi +} +\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 + }% +} +\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 + }% +} +\newcommand*{\peopleposspronoun}{% + \ifnum\c@people>1\relax + \pluralposspronoun + \else + \@get@firstperson{\@thisperson}% + \personposspronoun[\@thisperson]% + \fi +} +\newcommand*{\Peopleposspronoun}{% + \ifnum\c@people>1\relax + \expandafter\MakeUppercase\pluralposspronoun + \else + \@get@firstperson{\@thisperson}% + \Personposspronoun[\@thisperson]% + \fi +} +\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 + }% +} +\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 + }% +} +\newcommand*{\peoplechild}{% + \ifnum\c@people>1\relax + \ifallmale + {\malechildren}% + {\ifallfemale{\femalechildren}{\pluralchild}}% + \else + \@get@firstperson{\@thisperson}% + \personchild[\@thisperson]% + \fi +} +\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 +} +\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 + }% +} +\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 + }% +} +\newcommand*{\peopleparent}{% + \ifnum\c@people>1\relax + \pluralparent + \else + \@get@firstperson{\@thisperson}% + \personparent[\@thisperson]% + \fi +} +\newcommand*{\Peopleparent}{% + \ifnum\c@people>1\relax + \expandafter\MakeUppercase\pluralparent + \else + \@get@firstperson{\@thisperson}% + \Personparent[\@thisperson]% + \fi +} +\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 + }% +} +\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 + }% +} +\newcommand*{\peoplesibling}{% + \ifnum\c@people>1\relax + \ifallmale + {\malesiblings}% + {\ifallfemale{\femalesiblings}{\pluralsibling}}% + \else + \@get@firstperson{\@thisperson}% + \personsibling[\@thisperson]% + \fi +} +\newcommand*{\persongender}[1]{% + \ifpersonmale{#1}{\malename}{\femalename}% +} +\newcommand*{\getpersongender}[2]{% + \ifpersonmale{#2}{\let#1\malename}{\let#1\femalename}% +} +\newcommand*{\getpersonname}[2]{% + \ifpersonexists{#2}% + {% + \expandafter\let\expandafter#1\csname person@#2@name\endcsname + }% + {% + \PackageError{person}{Person `#2' doesn't exist}{}% + }% +} +\newcommand*{\getpersonfullname}[2]{% + \ifpersonexists{#2}% + {% + \expandafter + \let\expandafter#1\csname person@#2@fullname\endcsname + }% + {% + \PackageError{person}{Person `#2' doesn't exist}{}% + }% +} +\endinput +%% +%% End of file `person.sty'. -- cgit v1.2.3