diff options
author | Karl Berry <karl@freefriends.org> | 2006-01-11 23:59:07 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2006-01-11 23:59:07 +0000 |
commit | 932f1e9334f5617a090f721262fa30074d5e7374 (patch) | |
tree | 191552bd7389639373d3b65e066ea817327315fb /Master/texmf-dist/source | |
parent | 59aa2576ef260def2b412abb242644e53aa0d071 (diff) |
trunk/Master/texmf-dist/source/latex/xkeyval
git-svn-id: svn://tug.org/texlive/trunk@594 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/source')
-rw-r--r-- | Master/texmf-dist/source/latex/xkeyval/xkeyval.dtx | 5605 |
1 files changed, 5605 insertions, 0 deletions
diff --git a/Master/texmf-dist/source/latex/xkeyval/xkeyval.dtx b/Master/texmf-dist/source/latex/xkeyval/xkeyval.dtx new file mode 100644 index 00000000000..5febf8c8960 --- /dev/null +++ b/Master/texmf-dist/source/latex/xkeyval/xkeyval.dtx @@ -0,0 +1,5605 @@ +% \iffalse meta-comment +% +% xkeyval package by Hendri Adriaens. +% +% Extract package files and examples and create documentation: +% latex xkeyval.dtx +% latex xkeyval.dtx +% bibtex xkeyval +% makeindex -s gglo.ist -o xkeyval.gls xkeyval.glo +% makeindex -s gind.ist -o xkeyval.ind xkeyval.idx +% latex xkeyval.dtx +% latex xkeyval.dtx +% +% To finish the installation you have to move the following +% files into a directory searched by TeX: +% xkeyval.tex +% keyval.tex +% xkvtxhdr.tex +% pst-xkey.tex +% Additional to these files, LaTeX should be able to locate +% the following files: +% xkeyval.sty +% xkvview.sty +% xkvltxp.sty +% pst-xkey.sty +% +%% --------------------------------------- +%% Copyright (C) 2004-2005 Hendri Adriaens +%% --------------------------------------- +%% +%% This work may be distributed and/or modified under the +%% conditions of the LaTeX Project Public License, either version 1.3 +%% of this license or (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 2003/12/01 or later. +%% +%% This work has the LPPL maintenance status "maintained". +%% +%% This Current Maintainer of this work is Hendri Adriaens. +%% +%% This work consists of the file xkeyval.dtx and derived files +%% keyval.tex, xkvtxhdr.tex, xkeyval.sty, xkeyval.tex, xkvview.sty, +%% xkvltxp.sty, pst-xkey.tex, pst-xkey.sty, xkveca.cls, xkvecb.cls, +%% xkvesa.sty, xkvesb.sty, xkvesc.sty, xkvex1.tex, xkvex2.tex, +%% xkvex3.tex and xkvex4.tex. +%% +%% The following files constitute the xkeyval bundle and must be +%% distributed as a whole: readme, xkeyval.pdf, keyval.tex, +%% pst-xkey.sty, pst-xkey.tex, xkeyval.sty, xkeyval.tex, xkvview.sty, +%% xkvltxp.sty, xkvtxhdr.tex, pst-xkey.dtx and xkeyval.dtx. +%% +% \fi +% +% \iffalse +%<*batchfile> +\begingroup +\input docstrip +\keepsilent +\preamble +\endpreamble +\askforoverwritefalse +\generate{ + \file{xkeyval.tex}{\from{xkeyval.dtx}{xkvtex}} + \file{xkeyval.sty}{\from{xkeyval.dtx}{xkvlatex}} + \file{xkvview.sty}{\from{xkeyval.dtx}{xkvview}} + \file{xkvltxp.sty}{\from{xkeyval.dtx}{xkvltxpatch}} + \file{keyval.tex}{\from{xkeyval.dtx}{xkvkeyval}} + \file{xkvtxhdr.tex}{\from{xkeyval.dtx}{xkvheader}} + \file{pst-xkey.tex}{\from{xkeyval.dtx}{pxktex}} + \file{pst-xkey.sty}{\from{xkeyval.dtx}{pxklatex}} + \file{xkvex1.tex}{\from{xkeyval.dtx}{xkvex1}} + \file{xkvex2.tex}{\from{xkeyval.dtx}{xkvex2}} + \file{xkvex3.tex}{\from{xkeyval.dtx}{xkvex3}} + \file{xkvex4.tex}{\from{xkeyval.dtx}{xkvex4}} + \file{xkveca.cls}{\from{xkeyval.dtx}{xkveca}} + \file{xkvecb.cls}{\from{xkeyval.dtx}{xkvecb}} + \file{xkvesa.sty}{\from{xkeyval.dtx}{xkvesa}} + \file{xkvesb.sty}{\from{xkeyval.dtx}{xkvesb}} + \file{xkvesc.sty}{\from{xkeyval.dtx}{xkvesc}} + \file{xkvpream.ble}{\from{xkeyval.dtx}{preamble}} + \file{xkeyval.bib}{\from{xkeyval.dtx}{bib}} +} +\endgroup +%</batchfile> +%<*driver> +\documentclass[a4paper]{ltxdoc} +\input{xkvpream.ble} +\begin{document} +\DocInput{xkeyval.dtx} +\let\Section\section\def\section*#1{\Section*{#1}\addcontentsline{toc}{section}{#1}} +\bibliographystyle{plain} +\bibliography{xkeyval} +\section*{Acknowledgements} +The author is grateful to Josselin Noirel, Till Tantau, Herbert +Vo\ss, Carsten Heinz and Heiko Oberdiek for help and suggestions. Thanks go to +Donald Arseneau for contributing the robust |\@ifnextcharacter| macro and +to Morten H\o gholm for contributing a fast for-loop macro. Special +thanks go to Uwe Kern for his ideas for improving the functionality +of this package, a lot of useful comments on the package and the +documentation and for contributing the |\@selective@sanitize| macro. +\PrintChangesX\PrintIndexX +\end{document} +%</driver> +% \fi +% +% \changes{v1.0}{2004/04/29}{Initial release} +% \changes{v1.2}{2004/05/08}{Change to \cs{DeclareOptionXf}; macro is +% now replaced} +% \changes{v1.3}{2004/05/09}{Revision of documentation} +% \changes{v1.4}{2004/08/24}{Made package \TeX\ compatible} +% \changes{v1.4}{2004/08/24}{Renamed macros to \pf{keyval} names} +% \changes{v1.4}{2004/08/24}{Changed package options} +% \changes{v1.5}{2004/09/27}{Corrected some minor bugs} +% \changes{v1.5}{2004/09/27}{Added \pf{pst-xkey}} +% \changes{v1.5}{2004/09/27}{Revised documentation} +% \changes{v1.5}{2004/09/27}{Added \cs{XKV@for}} +% \changes{v1.6}{2004/10/05}{Changed loading preventions} +% \changes{v1.6}{2004/10/05}{Corrected typos} +% \changes{v1.7}{2004/11/25}{Improved coding} +% \changes{v1.7}{2004/11/25}{Package uses \eTeX\ if available} +% \changes{v1.7}{2004/11/25}{Changed \LaTeX\ patch from \texttt{.tex} +% to \texttt{.sty}} +% \changes{v1.7}{2004/11/25}{Updated license information} +% \changes{v1.7}{2004/11/25}{Added system to control the scope of +% definitions to various macros} +% \changes{v1.8 }{2004/12/13}{Made package robust for catcode changes +% of equality character} +% \changes{v1.8 }{2004/12/13}{Fixed inconsistency of treatment of +% spaces in key and family names, all left untouched now} +% \changes{v1.8c}{2005/01/01}{Simplified and improved some code} +% \changes{v1.8d}{2005/01/02}{Restructured package to indicate general +% tools and their implementation} +% \changes{v1.8d}{2005/01/02}{Renamed \texttt{xkeyval.def} to +% \texttt{xkvtxhdr.tex}} +% \changes{v1.9}{2005/01/16}{Added \cs{delpresetkeys}} +% \changes{v1.9}{2005/01/16}{Added \cs{delsavekeys}} +% \changes{v1.9}{2005/01/16}{Updated license information} +% \changes{v2.0}{2005/01/30}{Made \cs{setkeys} nestable} +% \changes{v2.1}{2005/02/08}{Added `immediate' versions of several +% macros} +% \changes{v2.2}{2005/02/14}{Improved nesting mechanism} +% \changes{v2.2}{2005/02/14}{Added viewer utility} +% \changes{v2.3}{2005/02/22}{Updated viewer utility} +% \changes{v2.3}{2005/02/22}{Added choice keys} +% \changes{v2.3}{2005/02/22}{Increased efficiency of loops} +% \changes{v2.4}{2005/03/31}{Added nesting protection for conditionals} +% \changes{v2.4}{2005/03/31}{Changed \cs{define@boolkey} to have a key +% function} +% \changes{v2.4}{2005/03/31}{Extended boolean keys} +% \changes{v2.4}{2005/03/31}{Extended choice keys} +% \changes{v2.4}{2005/03/31}{Updated \pf{xkvview}} +% \changes{v2.4}{2005/03/31}{Added `default value' column to +% \pf{xkvview} tables} +% \changes{v2.4}{2005/03/31}{Revised documentation and examples} +% \changes{v2.4}{2005/03/31}{Removed command keys} +% \changes{v2.4}{2005/03/31}{Simplified some code} +% \changes{v2.4}{2005/03/31}{Inserted \pf{pst-xkey} in \pf{xkeyval} +% source} +% \changes{v2.5 }{2005/05/07}{Added \cs{define@boolkeys}, +% \cs{define@cmdkey} and \cs{define@cmdkeys}} +% \changes{v2.5 }{2005/05/07}{Restructured documentation} +% \changes{v2.5 }{2005/05/07}{Updated \pf{xkvview}} +% \changes{v2.5 }{2005/05/07}{Solved small bug in \cs{setkeys} which +% allowed other families to take over save key or preset key settings +% if the key was defined in multiple families} +% \changes{v2.5 }{2005/05/07}{Simplified \cs{setkeys} internals} +% \changes{v2.5 }{2005/05/21}{Reimplemented \pf{xkvview} and added +% several options} +% \changes{v2.5 }{2005/05/21}{Added default value examples to docs} +% \changes{v2.5b}{2005/06/20}{Made retrieving document class more robust} +% \changes{v2.5d}{2005/08/12}{Added missing \cs{filename@area} in +% document class retrieval in \texttt{xkeyval.sty}} +% +% \GetFileInfo{xkeyval.sty} +% +% \CheckSum{2963} +% +%\DoNotIndex{\:,\@,\@@,\@backslashchar,\@ehc,\@empty,\@expandtwoargs, +%\@for,\@forloop,\@fornoop,\@fortmp,\@gobble,\@gobbletwo,\@if,\@ifnch, +%\@ifnextchar,\@iforloop,\@ifundefined,\@let@token, +%\@namedef,\@nil,\@nnil,\@sptoken,\@temptokena,\@testopt,\@undefined, +%\@xifnch,\\,\afterassignment,\AtEndOfPackage,\begingroup,\bgroup, +%\catcode,\count@,\csname,\def,\do,\edef,\else,\endcsname,\endgroup, +%\endinput,\errmessage,\escapechar,\eTeXversion,\expandafter,\fi, +%\futurelet,\gdef,\global,\if,\ifcsname,\iffalse,\ifin@,\iftrue,\ifx, +%\in@,\in@@,\in@false,\in@true,\input,\kernel@ifnextchar,\let,\long, +%\lowercase,\m@ne,\meaning,\message,\NeedsTeXFormat,\newif,\newtoks, +%\noexpand,\protect,\ProvidesFile,\ProvidesPackage,\relax,\reserved@a, +%\reserved@b,\reserved@c,\reserved@d,\space,\string,\strip@prefix,\the, +%\toks@,\xdef,\XKV@header,\XKV@inpoxfalse,\XKV@inpoxtrue,\XKV@knffalse, +%\XKV@knftrue,\XKV@plfalse,\XKV@pltrue,\XKV@resa,\XKV@rkvfalse, +%\XKV@rkvtrue,\XKV@stfalse,\XKV@sttrue,\XKV@tempa,\XKV@tempb,\XKV@tempc, +%\XKV@tempd,\XKV@tfam,\XKV@tkey,\XKV@toks,\XKVcatcodes,\XKV@sgtrue, +%\zap@space,\@@cmd,\@@tok,\@i,\@ii,\@iii,\@iv,\=,\XKV@rgtrue,\XKV@rgfalse, +%\z@,\@ne,\m@ne,\count@,\advance,\ifnum,\,,\@M,\XKV@resb,\XKV@sgfalse, +%\newcount,\ttfamily,\textst,\texttt,\ifcase,\begin,\bfseries,\end, +%\hline,\multicolumn,\normalfont,\romannumeral,\emph,\endfirsthead, +%\endfoot,\endhead,\endlastfoot,\textsf,\addto@hook,\RequirePackage, +%\ifcat,\PSTXKeyCatcodes,\@addtofilelist,\XKV@presettrue,\XKV@presetfalse, +%\protected@edef,\closeout,\openout,\label,\newwrite,\protected@write, +%\XKVV@coliitrue,\XKVV@coliiitrue,\XKVV@colivtrue,\XKVV@colvtrue, +%\XKVV@coliifalse,\XKVV@coliiifalse,\XKVV@colivfalse,\XKVV@colvfalse, +%\XKVV@vwkeyfalse,\XKVV@vwkeytrue} +% +% \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 \~} +% +%\title{\vspace*{-1cm}The \pf{xkeyval} package +%\thanks{This package can be downloaded from the CTAN mirrors: +%\texttt{/macros/latex/contrib/xkeyval}. See \texttt{xkeyval.dtx} for +%information on installing \pf{xkeyval} into your \TeX\ or \LaTeX\ +%distribution and for the license of this package.}} +%\author{\mktitledecor Hendri Adriaens\\\url{http://stuwww.uvt.nl/~hendri}} +%\date{\fileversion\ (\filedate)} +%\maketitle +% +%\begin{abstract}\noindent +%This package is an extension of the \pf{keyval} package and offers +%more flexible macros for defining and setting keys. The package +%provides a pointer and a preset system. Furthermore, it supplies +%macros to allow class and package options to contain options of the +%|key=value| form. A \LaTeX\ kernel patch is provided to avoid +%premature expansions of macros in class or package options. A +%specialized system for setting \pf{PSTricks} keys is provided by +%the \pf{pst-xkey} package. +%\end{abstract} +% +%\begin{multicols}{2} +%[\section*{Contents} +%\setlength{\columnseprule}{.4pt} +%\setlength{\columnsep}{18pt}] +%\tableofcontents +%\end{multicols} +% +%\newpage +%\section{Introduction}\label{sec:intro} +%This package is an extension of the \pf{keyval} package by David Carlisle +%\cite{keyval} and offers more flexible and robust macros for defining and +%setting keys. Using keys in macro definition has the advantage that +%the 9 arguments maximum can easily be avoided and that it reduces +%confusion in the syntax of your macro when compared to using a lot +%of (optional) arguments. Compare for instance the following +%possible syntaxes of the macro |\mybox| which might for instance +%use its arguments to draw some box containing text. +%\begin{example} +% \mybox[5pt][20pt]{some text}[red][white][blue] +% \mybox[text=red,background=white,frame=blue,left=5pt,right=20pt]{some text} +%\end{example} +%Notice that, to be able to specify the frame color in the first +%example, the other colors need to be specified as well. This is not +%necessary in the second example and these colors can get preset +%values. The same thing holds for the margins. +% +%The idea is that one first defines a set of keys using the tools +%presented in section~\ref{sec:define} in the document preamble or in a +%package or class. These keys can perform a function with the user +%input. The way to submit user input to these key macros, is by using +%one of the user interfaces described in sections~\ref{sec:setkeys}, +%\ref{sec:pointers} and~\ref{sec:preset}. The main user interface is +%provided by the |\setkeys| command. Using these interfaces, one can +%simplify macro syntax and for instance define the |\mybox| macro +%above as follows. +%\begin{example} +% \define@key{mybox}{left}{\setlength\myleft{#1}} +% \define@key{mybox}{background}{\def\background{#1}} +% % and some other keys +% \def\mybox{\@ifnextchar[\@mybox{\@mybox[]}} +% \def\@mybox[#1]#2{% +% \setkeys{mybox}{#1}% +% % some operations to typeset #2 +% } +%\end{example} +%Notice that the combination of the two definitions |\mybox| and +%|\@mybox| can be replaced by |\newcommand\mybox[2][]{...}| +%when using \LaTeX. +% +%Both keys defined using the \pf{keyval} and \pf{xkeyval} can be set +%by this package. The \pf{xkeyval} macros allow for scanning multiple +%sets (called `families') of keys. This can, for instance, be used to +%create local families for macros and environments which may not +%access keys meant for other macros and environments, while at the +%same time, allowing the use of a single command to (pre)set all of +%the keys from the different families globally. +% +%The package is compatible to plain \TeX\ and redefines several +%\pf{keyval} macros to provide an easy way to switch between using +%\pf{keyval} and \pf{xkeyval}. This might be useful for package +%writers that cannot yet rely on the availability of \pf{xkeyval} in +%a certain distribution. After loading \pf{xkeyval}, loading +%\pf{keyval} is prevented to make sure that the extended macros of +%\pf{xkeyval} will not be redefined. Some internal \pf{keyval} macros +%are supplied in |keyval.tex| to guarantee compatibility to packages +%that use those macros. Section~\ref{sec:issues} provides more +%information about this issue. +% +%The organization of this documentation is as follows. +%Section~\ref{sec:loading} discusses how to load \pf{xkeyval} and +%what the package does when it is loaded. Section~\ref{sec:define} +%will discuss the macros available to define and manage keys. +%Section~\ref{sec:setkeys} will continue with describing the macros +%that can set the keys. Section~\ref{sec:pointers} explains special +%syntax which will allow saving and copying key values. In +%section~\ref{sec:preset}, the preset system will be introduced. +%Section~\ref{sec:catcodes} will explain how \pf{xkeyval} protects +%itself for catcode changes of the comma and the equality sign by +%other packages. The \pf{xkeyval} package also provides commands to +%declare and process class and package options that can take values. +%These will be discussed in section~\ref{sec:options}. +%Section~\ref{sec:macrostructs} provides an overview of structures +%used to create \pf{xkeyval} internal macros used for keys, values, +%presets, etcetera. Sections~\ref{sec:errors} and~\ref{sec:issues} +%discuss feedback that \pf{xkeyval} might give and known issues, +%respectively. Section~\ref{sec:additional} discusses several +%additional packages that come with the \pf{xkeyval} bundle. +%Section~\ref{sec:view} presents a viewer utility which produces +%overviews of defined keys. An extension of the \LaTeXe\ kernel with +%respect to the class and package options system is discussed in +%section~\ref{sec:macrooptions}. This extension provides a way to use +%expandable macros in package options. Section~\ref{sec:pst-xkey} +%presents the \pf{pst-xkey} package, which provides an options system +%based on \pf{xkeyval}, but which is specialized in setting +%\pf{PSTricks} keys. +% +%Throughout this documentation, you will find some examples with a +%short description. More examples can be found in the example files +%that come with this package. See section~\ref{sec:sande} for more +%information. This section also provides the information how to +%generate the full documentation from the source. +% +%\section{Loading \pf{xkeyval}}\label{sec:loading} +%To load the \pf{xkeyval} package,\footnote{The \pf{xkeyval} package +%consists of the files \texttt{xkeyval.tex}, \texttt{xkeyval.sty}, +%\texttt{keyval.tex}, \texttt{xkvtxhdr.tex}.} plain \TeX\ users do +%|\input xkeyval|. \LaTeX\ users do one of the following: +%|\usepackage{xkeyval}| or |\RequirePackage{xkeyval}|. The package +%does not have options. It is mandatory for \LaTeX\ users to load +%\pf{xkeyval} at any point after the |\documentclass| command. +%Loading \pf{xkeyval} from the class which is the document class +%itself is possible. The package will use the \eTeX\ engine when +%available. In particular, |\ifcsname| is used whenever possible to +%avoid filling \TeX's hash tables with useless entries, for instance +%when searching for keys in families. +% +%If \pf{xkeyval} is loaded by |\RequirePackage| or |\usepackage|, the +%package performs two action immediately. These require +%\pf{xkeyval} to be loaded at any point after |\documentclass| or by +%the document class itself. +% +%First, it retrieves the document class of the document at hand and +%stores that (including the class extension) into the following macro. +%\begin{command} +% `\cs{XKV@documentclass}' +%\end{command} +%\DescribeMacro{\XKV@documentclass} +%This macro could, for instance, contain |article.cls| and can be useful +%when using |\ProcessOptionsX*| in a class. See +%page~\pageref{macro:poxstar}. +% +%Secondly, the global options submitted to the |\documentclass| command +%and stored by \LaTeX\ in |\@classoptionslist| +%are copied to the following macro. +%\begin{command} +% `\cs{XKV@classoptionslist}' +%\end{command} +%\DescribeMacro{\XKV@classoptionslist} +%This macro will be used by |\ProcessOptionsX|. Options containing +%an equality sign are deleted from the original list in +%|\@classoptionslist| to avoid packages, which do not use \pf{xkeyval} +%and which are loaded later, running into problems when trying to copy +%global options using \LaTeX's |\ProcessOptions|. +% +%\section{Defining and managing keys}\label{sec:define} +%\changes{v1.4}{2004/08/24}{Added prefix options to macros} +%\changes{v1.7}{2004/11/25}{Removed optional key checking from define macros} +%This section discusses macros to define keys and some tools to manage +%keys. A useful extension to \pf{xkeyval} is the \pf{xkvview} package. +%This packages defines commands to generate overviews of defined keys. +%See section~\ref{sec:view} for more information. +% +%\subsection{Ordinary keys}\label{sec:odefine} +%This section describes how to define ordinary keys. +%\begin{command} +% `\cs{define@key}\oarg{prefix}\marg{family}\marg{key}\oarg{default}\marg{function}' +%\end{command} +%\DescribeMacro{\define@key} +%This defines a macro of the form +%|\|\meta{prefix}|@|\meta{family}|@|\meta{key} with one argument +%holding \meta{function}. The default value for \meta{prefix} is +%|KV|. This is the standard throughout the package to simplify mixing +%\pf{keyval} and \pf{xkeyval} keys. When \meta{key} is used in a +%|\setkeys| command (see section~\ref{sec:setkeys}) containing +%|key=value|, the macro |\|\meta{prefix}|@|\meta{family}|@|\meta{key} +%receives |value| as its argument and will be executed. The argument +%can be accessed by \meta{function} by using |#1| inside the +%function. +%\begin{example} +% \define@key{family}{key}{The input is: #1} +%\end{example} +%\pf{xkeyval} will generate an error when the user omits |=value| for +%a key in the options list of |\setkeys| (see +%section~\ref{sec:setkeys}). To avoid this, the optional argument can +%be used to specify a default value. +%\begin{example} +% \define@key{family}{key}[none]{The input is: #1} +%\end{example} +%This will additionally define a macro +%|\|\meta{prefix}|@|\meta{family}|@|\meta{key}|@default| as a macro +%with no arguments and definition +%|\|\meta{prefix}|@|\meta{family}|@|\meta{key}|{none}| which will be +%used when |=value| is missing for |key| in the options list. So, the +%last example comes down to doing +%\begin{example} +% \def\KV@family@key#1{The input is: #1} +% \def\KV@family@key@default{\KV@family@key{none}} +%\end{example} +% +%When \meta{prefix} is specified and empty, the macros created by +%|\define@key| will have the form |\|\meta{family}|@|\meta{key}. When +%\meta{family} is empty, the resulting form will be +%|\|\meta{prefix}|@|\meta{key}. When both \meta{prefix} and +%\meta{family} are empty, the form is |\|\meta{key}. This combination +%of prefix and family will be called the header. The rules to create +%the header will be applied to all commands taking (optional) prefix +%and family arguments. +% +%The intended use for \meta{family} is to create distinct sets of +%keys. This can be used to avoid a macro setting keys meant for +%another macro only. The optional \meta{prefix} can be used to +%identify keys specifically for your package. Using a package +%specific prefix reduces the probability of multiple packages +%defining the same key macros. This optional argument can also be +%used to set keys of some existing packages which use a system based +%on \pf{keyval}.\footnote{Like \pf{PSTricks}, which uses a system +%originating from \pf{keyval}, but which has been modified to use no +%families and |psset| as prefix.}\label{page:pstricks} +% +%We now define some keys to be used in examples throughout this +%documentation. +%\begin{example} +% \define@key[my]{familya}{keya}[default]{#1} +% \define@key[my]{familya}{keyb}{#1} +% \define@key[my]{familyb}{keyb}{#1} +% \define@key[my]{familya}{keyc}{#1} +%\end{example} +% +%\subsection{Command keys}\label{sec:cdefine} +%Command keys are specialized keys that, before executing any code, +%save the user input to a macro. +%\begin{command} +% `\cs{define@cmdkey}\oarg{prefix}\marg{family}\oarg{mp}\marg{key}\oarg{default}\marg{function}' +%\end{command} +%\DescribeMacro{\define@cmdkey} +%This has the effect of defining a key macro of the form +%|\|\meta{prefix}|@|\meta{family}|@|\meta{key} that, when used, first +%saves the user input to a macro of the form |\|\meta{mp}\meta{key} +%and then executes \meta{function}. \meta{mp} is the macro prefix. If +%\meta{mp} is not specified, the usual combination of \meta{prefix} +%and \meta{family}, together with the extra prefix |cmd|, will be +%used to create the macro prefix, namely +%|\cmd|\meta{prefix}|@|\meta{family}|@|.\footnote{\label{foot:1}Remember +%that some rules are applied when creating the header, the +%combination of \meta{prefix} and \meta{header}. See +%section~\ref{sec:odefine}.} The two keys in the following example +%hence do exactly the same thing.\footnote{Notice however, that the +%first key will be listed as a `command key' by \pf{xkvview} and the +%second as an `ordinary key'. See section~\ref{sec:view}.} +%\begin{example} +% \define@cmdkey{fam}{key}[none]{value: \cmdKV@fam@key} +% \define@key{fam}{key}[none]{\def\cmdKV@fam@key{#1}value: \cmdKV@fam@key} +%\end{example} +%The value |none| is again the default value that will be submitted +%to the key macro when the user didn't supply a value. (See also +%section~\ref{sec:odefine} for more information.) +% +%The following two lines also implement a key with the same key macro. +%\begin{example} +% \define@cmdkey{fam}[my@]{key}[none]{value: \my@key} +% \define@key{fam}{key}[none]{\def\my@key{#1}value: \my@key} +%\end{example} +%Note that the key macro itself in the examples above is still +%|\KV@fam@key|, just as in the previous example. +% +%A lot of packages define keys that only save their value to a macro +%so that it can be used later. Using the macro above, one can save +%some tokens in the package. Some more tokens can be saved by using +%the following macro. +%\begin{command} +% `\cs{define@cmdkeys}\oarg{prefix}\marg{family}\oarg{mp}\marg{keys}\oarg{default}' +%\end{command} +%\DescribeMacro{\define@cmdkeys} +%This repeatedly calls (an internal of) |\define@cmdkey| for all keys +%in the list of \meta{keys}. Note that it is not possible to specify +%a custom key function for the keys created by this command. The only +%function of those keys is to save user input in a macro. The first +%line and the last two lines of the following example create keys +%with the same internal key macro. +%\begin{example} +% \define@cmdkeys{fam}[my@]{keya,keyb}[none] +% \define@key{fam}{keya}[none]{\def\my@keya{#1}} +% \define@key{fam}{keyb}[none]{\def\my@keyb{#1}} +%\end{example} +% +%\subsection{Choice keys}\label{sec:chdefine} +%Choice keys allow only a limited number of different values for user +%input. These keys are defined as follows. +%\begin{command} +% `\cs{define@choicekey}\oarg{pre}\marg{fam}\marg{key}\oarg{bin}\marg{al}\oarg{dft}\marg{func}' +% `\cs{define@choicekey*}\oarg{pre}\marg{fam}\marg{key}\oarg{bin}\marg{al}\oarg{dft}\marg{func}' +%\end{command} +%\DescribeMacros{\define@choicekey,\define@choicekey*} +%The keys work the same as ordinary keys, except that, before +%executing anything, it is verified whether the user input |#1| is +%present in the comma separated list \meta{al}. The starred version +%first converts the input in |#1| and \meta{al} to lowercase before +%performing the check. If the input is not allowed, an error is +%produced and the key macro \meta{func} will not be executed. If the +%input is allowed, the key macro \meta{func} will be executed. \meta{dft} +%is submitted to the key macro when the user didn't supply a value +%for the key. (See also section~\ref{sec:odefine}.) +% +%The optional \meta{bin} should contain either one or two control +%sequences (macros). The first one will be used to store the user +%input used in the input check (hence, in lowercase when the starred +%version was used). The original user input will always be available +%in |#1|. The second (if present) will contain the number of the +%input in the \meta{al} list, starting from 0. The number will be set +%to |-1| if the input was not allowed. The number can, for instance, +%be used in a |\ifcase| statement in \meta{func}. +%\begin{example} +% \define@choicekey*{fam}{align}[\val\nr]{left,center,right}{% +% \ifcase\nr\relax +% \raggedright +% \or +% \centering +% \or +% \raggedleft +% \fi +% } +%\end{example} +%The example above only allows input values |left|, |center| and +%|right|. Notice that we don't need a |\else| case in the key macro +%above as the macro will not be executed when the input was not +%allowed. +% +%\begin{command} +% `\cs{define@choicekey+}\oarg{pre}\marg{fam}\marg{key}\oarg{bin}\marg{al}\oarg{dft}\marg{f1}\marg{f2}' +% `\cs{define@choicekey*+}\oarg{pre}\marg{fam}\marg{key}\oarg{bin}\marg{al}\oarg{dft}\marg{f1}\marg{f2}' +%\end{command} +%\DescribeMacros{\define@choicekey+,\define@choicekey*+} +%These macros operate as their counterparts without the |+|, but +%allow for specifying two key macros. \meta{f1} will be executed when +%the input was correct and \meta{f2} will be executed when the input +%was not allowed. Again, the starred version executes the check after +%converting user input and \meta{al} to lowercase. +%\begin{example} +% \define@choicekey*+{fam}{align}[\val\nr]{left,center,right}{% +% \ifcase\nr\relax +% \raggedright +% \or +% \centering +% \or +% \raggedleft +% \fi +% }{% +% \PackageWarning{mypack}{erroneous input ignored}% +% } +%\end{example} +%The example above defines a key that is similar as the one in the +%previous example, but when input is not allowed, it will not +%generate a standard \pf{xkeyval} warning, but will execute a custom +%function, which, in this case, generates a warning. +% +%\begin{command} +% `\cs{XKV@cc}\oarg{bin}\marg{input}\marg{al}\marg{func}' +% `\cs{XKV@cc*}\oarg{bin}\marg{input}\marg{al}\marg{func}' +% `\cs{XKV@cc+}\oarg{bin}\marg{input}\marg{al}\marg{func1}\marg{func2}' +% `\cs{XKV@cc*+}\oarg{bin}\marg{input}\marg{al}\marg{func1}\marg{func2}' +%\end{command} +%\DescribeMacros{\XKV@cc,\XKV@cc*,\XKV@cc+,\XKV@cc*+} +%Choice keys work by adding (an internal version\footnote{See +%section~\ref{sec:imple} for details of the implementation of choice +%keys.} of) the |\XKV@cc| macro to key macros. This macro has similar +%arguments as the |\define@choicekey| macro and the optional |*| and +%|+| have the same meaning. \meta{input} holds the input that should +%be checked, namely, whether it is (in lowercase if |*| was used) in +%the list \meta{al}. One can use this macro to create custom choice +%keys. See an example below. +%\begin{example} +% \define@key{fam}{key}{% +% I will first check your input, please wait.\\ +% \XKV@cc*+[\val]{#1}{true,false}{% +% The input \val\ was correct, we proceed.\\ +% }{% +% The input \val\ was incorrect and was ignored.\\ +% }% +% I finished the input check. +% } +%\end{example} +%Try to find out why this key cannot be defined with |\define@boolkey| +%which is introduced in the next section. +% +%\subsection{Boolean keys}\label{sec:bdefine} +%\changes{v1.5}{2004/09/27}{Added boolean keys} +%This section describes boolean keys which can be either true or +%false. A boolean key is a special version of a choice key (see +%section~\ref{sec:chdefine}), where \meta{al} takes the value +%|true,false| and comparisons are always done in lowercase mode (so, +%|True| is allowed input). +%\begin{command} +% `\cs{define@boolkey}\oarg{pre}\marg{fam}\oarg{mp}\marg{key}\oarg{default}\marg{func}' +% `\cs{define@boolkey+}\oarg{pre}\marg{fam}\oarg{mp}\marg{key}\oarg{default}\marg{func1}\marg{func2}' +%\end{command} +%\DescribeMacros{\define@boolkey,\define@boolkey+} +%This creates a boolean of the form +%|\if|\meta{pre}|@|\meta{family}|@|\meta{key}\footref{foot:1}\footnote{ +%When you want to use this macro directly, either make sure that +%neither of the input parameters contain characters with a catcode +%different from 11 (hence no \texttt{-} for instance), reset the +%catcode of the offending characters internally to 11 or use +%\texttt{\cs{csname}\dots\cs{endcsname}} to construct macro names, +%(for instance, \texttt{\cs{csname} +%ifpre@some-fam@key\cs{endcsname}}). See for more information +%section~\ref{sec:macrostructs}.} if \meta{mp} is not specified, +%using |\newif|\footnote{The \LaTeX\ of implementation \cs{newif} is +%used because it can be used in the replacement text of a macro, +%whereas the plain \TeX\ \cs{newif} is defined \cs{outer}.} (which +%initiates the conditional to |\iffalse|) and a key macro of the form +%|\|\meta{pre}|@|\meta{family}|@|\meta{key} which first checks the +%validity of the user input. If the input was valid, it uses it to +%set the boolean and afterwards, it executes \meta{func}. If the +%input was invalid, it will not set the boolean and \pf{xkeyval} will +%generate an error. If \meta{mp} is specified, it will create boolean +%of the form |\if|\meta{mp}\meta{key} (compare to command keys in +%section~\ref{sec:cdefine}). The value \meta{default} will be used by +%the key macro when the user didn't submit a value to the key. +%(See also section~\ref{sec:odefine}.) +% +%If the |+| version of the macro is used, one can specify two key +%macros. If user input is valid, the macro will set the boolean and +%executes \meta{func1}. Otherwise, it will not set the boolean and +%execute \meta{func2}. +%\begin{example} +% \define@boolkey{fam}[my@]{frame}{} +% \define@boolkey+{fam}{shadow}{% +% \ifKV@fam@shadow +% \PackageInfo{mypack}{turning shadows on}% +% \else +% \PackageInfo{mypack}{turning shadows off}% +% \fi +% }{% +% \PackageWarning{mypack}{erroneous input ignored}% +% } +%\end{example} +%The first example creates the boolean |\ifmy@frame| and defines +%the key macro |\KV@fam@frame| to only set the boolean (if input is +%correct). The second key informs the user about changed settings or +%produces a warning when input was incorrect. +% +%One can also define multiple boolean keys with a single command. +%\begin{command} +% `\cs{define@boolkeys}\oarg{pre}\marg{fam}\oarg{mp}\marg{keys}\oarg{default}' +%\end{command} +%\DescribeMacro{\define@boolkeys} +%This macro creates a boolean key for every entry in the list +%\meta{keys}. As with the command |\define@cmdkeys|, the individual keys cannot +%have a custom function. The boolean keys created with this command +%are only meant to set the state of the boolean using the user input. +%Concluding, +%\begin{example} +% \define@boolkeys{fam}[my@]{keya,keyb,keyc} +%\end{example} +%is an abbreviation for +%\begin{example} +% \define@boolkey{fam}[my@]{keya}{} +% \define@boolkey{fam}[my@]{keyb}{} +% \define@boolkey{fam}[my@]{keyc}{} +%\end{example} +% +%\subsection{Checking keys}\label{sec:check} +%\changes{v1.7}{2004/11/25}{Changed name of \cs{XKV@ifku}} +%\begin{command} +% `\cs{key@ifundefined}\oarg{prefix}\marg{families}\marg{key}\marg{undefined}\marg{defined}' +%\end{command} +%\DescribeMacro{\key@ifundefined} +%This macro executes \meta{undefined} when \meta{key} is not defined +%in a family listed in \meta{families} using \meta{prefix} (which is +%|KV| by default) and \meta{defined} when it is. If \meta{defined} is +%executed, |\XKV@tfam| holds the first family in the list \meta{families} +%that holds \meta{key}. If \meta{undefined} is executed, |\XKV@tfam| +%contains the last family of the list \meta{families}. +%\begin{example} +% \key@ifundefined[my]{familya,familyb}{keya}{`keya' not defined}{`keya' defined} +%\end{example} +%This example results in |`keya' defined| and |\XKV@tfam| holds |familya|. +% +%\subsection{Disabling keys}\label{sec:disable} +%\changes{v1.7}{2004/11/25}{Added \cs{disable@keys}} +%It is also possible to disable keys after use as to prevent the key +%from being used again. +% +%\begin{command} +% `\cs{disable@keys}\oarg{prefix}\marg{family}\marg{keys}' +%\end{command} +%\DescribeMacro{\disable@keys} +%When you disable a key, the use of this key will produce a warning +%in the log file. Disabling a key that hasn't been defined will result +%in an error message. +%\begin{example} +% \disable@keys[my]{familya}{keya,keyb} +%\end{example} +%This would make |keya| and |keyb| produce a warning when one tries to +%set these keys. +% +%\section{Setting keys}\label{sec:setkeys} +%\subsection{The user interface} +%\changes{v1.4}{2004/08/24}{Added prefix options to macros} +%This section describes the available macros for setting keys. All of +%the macros in this section have an optional argument \meta{prefix} +%which determines part of the form of the keys that the macros will +%be looking for. See section~\ref{sec:define}. This optional argument +%takes the value |KV| by default. +% +%\begin{command} +% `\cs{setkeys}\oarg{prefix}\marg{families}\oarg{na}\marg{keys}' +%\end{command} +%\DescribeMacro{\setkeys} +%This macro sets keys of the form +%|\|\meta{prefix}|@|\meta{family}|@|\meta{key}\footref{foot:1} where \meta{family} is +%an element of the list \meta{families} and |key| is an element of +%the options list \meta{keys} and not of \meta{na}. The latter list +%can be used to specify keys that should be ignored by the macro. If +%a key is defined by more families in the list \meta{families}, the +%first family from the list defining the key will set it. No errors +%are produced when \meta{keys} is empty. If \meta{family} is empty, +%the macro will set keys of the form |\|\meta{prefix}|@|\meta{key}. +%If \meta{prefix} is specified and empty, the macro will set keys of +%the form |\|\meta{family}|@|\meta{key}. If both \meta{prefix} and +%\meta{family} are empty, the macro will set keys of the form +%|\|\meta{key}. +%\begin{example} +% \setkeys[my]{familya,familyb}{keya=test} +% \setkeys[my]{familya,familyb}{keyb=test} +% \setkeys[my]{familyb,familya}{keyb=test} +%\end{example} +%In the example above, line 1 will set |keya| in family |familya|. +%This effectively means that the value |test| will be submitted to the +%key macro |\my@familya@keya|. The next line will set |keyb| in +%|familya|. The last one sets |keyb| in family |familyb|. As the keys +%used here, directly output their value, the above code results in +%typesetting the word |test| three times. +% +%When input is lacking for a key, |\setkeys| will check whether there +%is a default value for that key that can be used instead. If that is +%not the case, an error message will be generated. See also +%section~\ref{sec:define}. +%\begin{example} +% \setkeys[my]{familya}{keya} +% \setkeys[my]{familya}{keyb} +%\end{example} +%The first line of the example above does not generate an error as this +%key has been defined with a default value (see section~\ref{sec:odefine}). +%The second line does generate an error message. See also section~\ref{sec:errors} +%for all possible error messages generated by \pf{xkeyval}. +% +%When you want to use commas or equality signs in the value of a key, +%surround the value by braces, as shown in the example below. +%\begin{example} +% \setkeys[my]{familya}{keya={some=text,other=text}} +%\end{example} +% +%It is possible to nest |\setkeys| commands in other |\setkeys| commands +%or in key definitions. The following, for instance, +%\begin{example} +% \define@key[my]{familyb}{keyc}{#1} +% \setkeys[my]{familyb}{keyc=a\setkeys[my]{familya}{keya=~and b},keyb=~and c} +%\end{example} +%returns |a and b and c|. +% +%\begin{command} +% `\cs{setkeys*}\oarg{prefix}\marg{families}\oarg{na}\marg{keys}' +%\end{command} +%\DescribeMacro{\setkeys*} +%The starred version of |\setkeys| sets keys which it can locate in +%the given families and will not produce errors when it cannot find a +%key. Instead, these keys and their values will be appended to a list +%of remaining keys in the macro |\XKV@rm| after the use of +%|\setkeys*|. Keys listed in \meta{na} will be ignored fully and +%will not be appended to the |\XKV@rm| list. +%\begin{example} +% \setkeys*[my]{familyb}{keya=test} +%\end{example} +%Since |keya| is not defined in |familyb|, the value in the example +%above will be stored in |\XKV@rm| (so |\XKV@rm| expands to +%|keya=test|) for later use and no errors are raised. +% +%\begin{command} +% `\cs{setrmkeys}\oarg{prefix}\marg{families}\oarg{na}' +%\end{command} +%\DescribeMacro{\setrmkeys} +%The macro |\setrmkeys| sets the remaining keys given by the list +%|\XKV@rm| stored previously by a |\setkeys*| (or |\setrmkeys*|) +%command in \meta{families}. \meta{na} again lists keys that should +%be ignored. It will produce an error when a key cannot be located. +%\begin{example} +% \setrmkeys[my]{familya} +%\end{example} +%This submits |keya=test| from the previous +%|\setkeys*| command to |familya|. |keya| will be set. +% +%\begin{command} +% `\cs{setrmkeys*}\oarg{prefix}\marg{families}\oarg{na}' +%\end{command} +%\DescribeMacro{\setrmkeys*} +%The macro |\setrmkeys*| acts as the |\setrmkeys| macro but now, +%as with |\setkeys*|, it ignores keys that it cannot find and puts +%them again on the list stored in |\XKV@rm|. Keys listed in \meta{na} +%will be ignored fully and will not be appended to the list in +%|\XKV@rm|. +%\begin{example} +% \setkeys*[my]{familyb}{keya=test} +% \setrmkeys*[my]{familyb} +% \setrmkeys[my]{familya} +%\end{example} +%In the example above, the second line tries to set |keya| in +%|familyb| again and no errors are generated on failure. The last +%line finally sets |keya|. +% +%The combination of |\setkeys*| and |\setrmkeys| can be used to +%construct complex macros in which, for instance, a part of the keys +%should be set in multiple families and the rest in another family or +%set of families. Instead of splitting the keys or the inputs, the +%user can supply all inputs in a single argument and the two macros +%will perform the splitting and setting of keys for your macro, given +%that the families are well chosen. +% +%\begin{command} +% `\cs{setkeys+}\oarg{prefix}\marg{families}\oarg{na}\marg{keys}' +% `\cs{setkeys*+}\oarg{prefix}\marg{families}\oarg{na}\marg{keys}' +% `\cs{setrmkeys+}\oarg{prefix}\marg{families}\oarg{na}' +% `\cs{setrmkeys*+}\oarg{prefix}\marg{families}\oarg{na}' +%\end{command} +%\changes{v1.4}{2004/08/24}{Added \texttt{+} option to macros} +%\DescribeMacros{\setkeys+,\setkeys*+,\setkeys+,\setkeys*+} +%These macros act as their counterparts without the |+|. However, +%when a key in \meta{keys} is defined by multiple families, this key +%will be set in \emph{all} families in \meta{families}. This can, for +%instance, be used to set keys defined by your own package and by +%another package with the same name but in different families with a +%single command. +%\begin{example} +% \setkeys+[my]{familya,familyb}{keyb=test} +%\end{example} +%The example above sets |keyb| in both families. +% +%\subsection{A few details} +%Several remarks should be made with respect to processing the user +%input. Assuming that |keya| up to |keyd| are properly defined, one +%could do the following. +%\begin{example} +% \setkeys{family}{keya= test a, keyb={test b,c,d}, , keyc=end} +%\end{example} +%From values consisting entirely of a |{ }| group, the outer braces +%will be stripped off internally.\footnote{\pf{xkeyval} actually +%strips off 3 levels of braces: one by using \pf{keyval}'s +%\cs{KV@@sp@def} and two in internal parsings. \pf{keyval} strips off +%only 2 levels: one by using \cs{KV@@sp@def} and one in internal +%parsings. This difference has not yet been shown to cause problems +%for existing packages or new implementations. If this appears to be +%a problem in the future, effort will be done to solve it.} This +%allows the user to `hide' any commas or equality signs that appear +%in the value of a key. This means that when using braces around +%|value|, \pf{xkeyval} will not terminate the |value| when it +%encounters a comma in |value|. For instance, see the value of |keyb| +%in the example above. The same holds for the equality sign. Notice +%further that any spaces around the characters |=| and |,| (in the +%top level group) are removed and that empty entries will silently be +%ignored. This makes the example above equivalent to the example +%below. +%\begin{example} +% \setkeys{family}{keya=test a,keyb={test b,c,d},keyc=end} +%\end{example} +% +%Further, when executing a key macro, the following \pf{xkeyval} +%internals are available. +%\begin{description} +%\item[\cs{XKV@prefix}]\mbox{}\\ +%The prefix, for instance |my|. +%\item[\cs{XKV@fams}]\mbox{}\\ +%The list of families to search, for instance |familya,familyb|. +%\item[\cs{XKV@tfam}]\mbox{}\\ +%The current family, for instance |familya|. +%\item[\cs{XKV@header}]\mbox{}\\ +%The header which is a combination of the prefix and the current +%family, for instance |my@familya@|. +%\item[\cs{XKV@tkey}]\mbox{}\\ +%The current key name, for instance |keya|. +%\item[\cs{XKV@na}]\mbox{}\\ +%The keys that should not be set, for instance |keyc,keyd|. +%\end{description} +%You can use these internals and create, for example, dynamic options +%systems in which user input to |\setkeys| will be used to create new +%keys which can be used in the very same |\setkeys| command. The +%\pf{extract} package \cite{extract} provides an example for this. +% +%\section{Pointers}\label{sec:pointers} +%\changes{v1.4}{2004/08/24}{Added pointer syntax} +%\changes{v1.5}{2004/09/27}{Removed \cs{ifrecordkeyvals}} +%\changes{v1.7}{2004/11/25}{Changed value saving mechanism} +%\changes{v1.7}{2004/11/25}{Changed pointer mechanism} +%The \pf{xkeyval} package provides a pointer mechanism. +%Pointers can be used to copy values of keys. Hence, one can +%reuse the value that has been submitted to a particular key in the +%value of another key. This section will first describe how +%\pf{xkeyval} can be made to save key values. After that, it will +%explain how to use these saved values again. Notice already that the +%commands |\savevalue|, |\gsavevalue| and |\usevalue| can only be used +%in |\setkeys| commands. +% +%\subsection{Saving values}\label{sec:savevalue} +%\DescribeMacro{\savevalue} +%Saving a value for a particular key can be accomplished by using the +%|\savevalue| command with the key name as +%argument. +%\begin{example} +% \setkeys[my]{familya}{\savevalue{keya}=test} +%\end{example} +%This example will set |keya| as we have seen before, but will additionally define +%the macro |\XKV@my@familya@keya@value| to expand to |test|. This +%macro can be used later on by \pf{xkeyval} to replace pointers. In +%general, values of keys will be stored in macros of the form +%|\XKV@|\meta{prefix}|@|\meta{family}|@|\meta{key}|@value|. This implies +%that the pointer system can only be used within the same family (and +%prefix). We will come back to that in section~\ref{sec:usevalue}. +% +%\DescribeMacro{\gsavevalue} +%Using the global version of this command, namely |\gsavevalue|, +%will define the value macro |\XKV@my@family@key@value| globally. +%In other words, the value macro won't survive after a +%|\begingroup|\texttt\dots|\endgroup| construct (for instance, an +%environment), when it has been created in this group using +%|\savevalue| and it will survive afterwards if |\gsavevalue| is +%used. +%\begin{example} +% \setkeys[my]{familya}{\gsavevalue{keya}=test} +%\end{example} +%This example will globally define |\XKV@my@familya@keya@value| to +%expand to |test|. +% +%Actually, in most applications, package authors do not want to require +%users to use the |\savevalue| form when using the pointer system internally. +%To avoid this, the \pf{xkeyval} package also supplies the following commands. +%\begin{command} +% `\cs{savekeys}\oarg{prefix}\marg{family}\marg{keys}' +% `\cs{gsavekeys}\oarg{prefix}\marg{family}\marg{keys}' +%\end{command} +%\DescribeMacros{\savekeys,\gsavekeys} +%The |\savekeys| macro stores a list of keys for which the values +%should always be saved to a macro of the form +%|\XKV@|\meta{prefix}|@|\meta{family}|@save|. This will be used by +%|\setkeys| to check whether a value should be saved or not. The +%global version will define this internal macro globally so that the +%settings can escape groups (and environments). The |\savekeys| macro +%works incrementally. This means that new input will be added to an +%existing list for the family at hand if it is not in yet. +%\begin{example} +% \savekeys[my]{familya}{keya,keyc} +% \savekeys[my]{familya}{keyb,keyc} +%\end{example} +%The first line stores |keya,keyc| to |\XKV@my@familya@save|. The +%next line changes the content of this macro to |keya,keyc,keyb|. +% +%\begin{command} +% `\cs{delsavekeys}\oarg{prefix}\marg{family}\marg{keys}' +% `\cs{gdelsavekeys}\oarg{prefix}\marg{family}\marg{keys}' +% `\cs{unsavekeys}\oarg{prefix}\marg{family}' +% `\cs{gunsavekeys}\oarg{prefix}\marg{family}' +%\end{command} +%\DescribeMacros{\delsavekeys,\gdelsavekeys,\unsavekeys,\gunsavekeys} +%The |\delsavekeys| macro can be used to remove some keys from an +%already defined list of save keys. No errors will be raised when one +%of the keys in the list \meta{keys} was not in the list. The global +%version |\gdelsavekeys| does the same as |\delsavekeys|, but will +%also make the resulting list global. The |\unsavekeys| macro can be +%used to clear the entire list of key names for which the values +%should be saved. The macro will make +%|\XKV@|\meta{prefix}|@|\meta{family}|@save| undefined. +%|\gunsavekeys| is similar to |\unsavekeys| but makes the internal +%macro undefined globally. +%\begin{example} +% \savekeys[my]{familya}{keya,keyb,keyc} +% \delsavekeys[my]{familya}{keyb} +% \unsavekeys[my]{familya} +%\end{example} +%The first line of this example initializes the list to contain +%|keya,keyb,keyc|. The second line removes |keyb| from this list and +%hence |keya,keyc| remains. The last line makes the list undefined and +%hence clears the settings for this family. +% +%\DescribeMacro{\global} +%It is important to notice that the use of the global version +%|\gsavekeys| will only have effect on the definition of the macro +%|\XKV@|\meta{prefix}|@|\meta{family}|@save|. It will not have an +%effect on how the key values will actually be saved by |\setkeys|. +%To achieve that a particular key value will be saved globally (like +%using |\gsavevalue|), use the |\global| specifier in the |\savekeys| +%argument. +%\begin{example} +% \savekeys[my]{familya}{keya,\global{keyc}} +%\end{example} +%This example does the following. The argument |keya,\global{keyc}| +%is saved (locally) to |\XKV@my@familya@save|. When |keyc| is used in +%a |\setkeys| command, the associated value will be saved globally to +%|\XKV@my@familya@keya@value|. When |keya| is used, its value will be +%saved locally. +% +%All macros discussed in this section for altering the list of save keys +%only look at the key name. If that is the same, old content will be +%overwritten with new content, regardless whether |\global| has been +%used in the content. See the example below. +%\begin{example} +% \savekeys[my]{familya}{\global{keyb},keyc} +% \delsavekeys[my]{familya}{keyb} +%\end{example} +%The first line changes the list in |\XKV@my@familya@save| from +%|keya,\global{keyc}| to |keya,keyc,\global{keyb}|. The second line +%changes the list to |keya,keyc|. +% +%\subsection{Using saved values}\label{sec:usevalue} +%\DescribeMacro{\usevalue} +%The syntax of a pointer is |\usevalue{keyname}| and can only be used +%inside |\setkeys| and friends. \pf{xkeyval} will +%replace a pointer by the value that has been saved for the key that +%the pointer is pointing to. If no value has been saved for this key, +%an error will be raised. The following example will demonstrate how +%to use pointers (using the keys defined in +%section~\ref{sec:odefine}). +%\begin{example} +% \setkeys[my]{familya}{\savevalue{keya}=test} +% \setkeys[my]{familya}{keyb=\usevalue{keya}} +%\end{example} +%The value submitted to |keyb| points to |keya|. This has the effect +%that the value recorded for |keya| will replace |\usevalue{keya}| and this +%value (here |test|) will be submitted to the key macro of |keyb|. +% +%Since the saving of values is prefix and family specific, pointers can +%only locate values that have been saved for keys with the same +%prefix and family as the key for which the pointer is used. Hence this +%\begin{example} +% \setkeys[my]{familya}{\savevalue{keya}=test} +% \setkeys[my]{familyb}{keyb=\usevalue{keya}} +%\end{example} +%will never work. An error will be raised in case a key value points +%to a key for which the value cannot be found or has not been stored. +% +%It is possible to nest pointers as the next example shows. +%\begin{example} +% \setkeys[my]{familya}{\savevalue{keya}=test} +% \setkeys[my]{familya}{\savevalue{keyb}=\usevalue{keya}} +% \setkeys[my]{familya}{keyc=\usevalue{keyb}} +%\end{example} +%This works as follows. First \pf{xkeyval} records the value |test| +%in a macro. Then, |keyb| uses that value. Besides that, the value +%submitted to |keyb|, namely |\usevalue{keya}| will be recorded in another +%macro. Finally, |keyc| will use the value recorded previously for +%|keyb|, namely |\usevalue{keya}|. That in turn points to the value saved for +%|keya| and that value will be used. +% +%It is important to stress that the pointer replacement will be done +%before \TeX\ or \LaTeX\ performs the expansion of the key macro and +%its argument (which is the value that has been submitted to the +%key). This allows pointers to be used in almost any application. (The +%exception is grouped material, to which we will come back later.) +%When programming keys (using |\define@key| and friends), you won't +%have to worry about the expansion of the pointers which might be +%submitted to your keys. The value that will be submitted to your key +%macro in the end, will not contain pointers. These have +%already been expanded and been replaced by the saved values. +% +%A word of caution is necessary. You might get into an infinite +%loop if pointers are not applied with care, as the examples below +%show. The first example shows a direct back link. +%\begin{example} +% \setkeys[my]{familya}{\savevalue{keya}=\usevalue{keya}} +%\end{example} +%The second example shows an indirect back link. +%\begin{example} +% \setkeys[my]{familya}{\savevalue{keya}=test} +% \setkeys[my]{familya}{\savevalue{keyb}=\usevalue{keya}} +% \setkeys[my]{familya}{\savevalue{keya}=\usevalue{keyb}} +%\end{example} +%In these cases, an error will be issued and further pointer replacement +%is canceled. +% +%As mentioned already, pointer replacement does not work inside +%grouped material, |{...}|, if this group is not around the entire +%value (since that will be stripped off, see section~\ref{sec:intro}). +%The following, for instance, will not work. +%\begin{example} +% \setkeys[my]{familya}{\savevalue{keya}=test} +% \setkeys[my]{familya}{keyb=\parbox{2cm}{\usevalue{keya}}} +%\end{example} +%The following provides a working alternative for this situation. +%\begin{example} +% \setkeys[my]{familya}{\savevalue{keya}=test} +% \setkeys[my]{familya}{keyb=\begin{minipage}{2cm}\usevalue{keya}\end{minipage}} +%\end{example} +%In case there is no appropriate alternative, we can work around this +%restriction, for instance by using a value macro directly. +%\begin{example} +% \setkeys[my]{familya}{\savevalue{keya}=test} +% \setkeys[my]{familya}{keyb=\parbox{2cm}{\XKV@my@familya@keya@value}} +%\end{example} +%When no value has been saved for |keya|, the macro +%|\XKV@my@familya@keya@value| is undefined. Hence one might want to +%do a preliminary check to be sure that the macro exists. +% +%Pointers can also be used in default values. We finish this section +%with an example which demonstrates this. +%\begin{example} +% \define@key{fam}{keya}{keya: #1} +% \define@key{fam}{keyb}[\usevalue{keya}]{keyb: #1} +% \define@key{fam}{keyc}[\usevalue{keyb}]{keyc: #1} +% \setkeys{fam}{\savevalue{keya}=test} +% \setkeys{fam}{\savevalue{keyb}} +% \setkeys{fam}{keyc} +%\end{example} +%Since user input is lacking in the final two commands, the default +%value defined for those keys will be used. In the first case, the +%default value points to |keya|, which results in the value |test|. +%In the second case, the pointer points to |keyb|, which points to +%|keya| (since its value has been saved now) and hence also in the +%final command, the value |test| will be submitted to the key macro +%of |keyc|. +% +%\section{Presetting keys}\label{sec:preset} +%\changes{v1.5}{2004/09/27}{Added preset system} +%In contrast to the default value system where users are required to +%specify the key without a value to assign it its default value, the +%presetting system does not require this. Keys which are preset will +%be set automatically by |\setkeys| when the user didn't use those +%keys in the |\setkeys| command. When users did use the keys which +%are also preset, |\setkeys| will avoid setting them again. This +%section again uses the key definitions of section~\ref{sec:odefine} +%in examples. +% +%\begin{command} +% `\cs{presetkeys}\oarg{prefix}\marg{family}\marg{head keys}\marg{tail keys}' +% `\cs{gpresetkeys}\oarg{prefix}\marg{family}\marg{head keys}\marg{tail keys}' +%\end{command} +%\DescribeMacros{\presetkeys,\gpresetkeys} +%This macro will save \meta{head keys} to +%|\XKV@|\meta{prefix}|@|\meta{family}|@preseth| and \meta{tail keys} +%to |\XKV@|\meta{prefix}|@|\meta{family}|@presett|. Savings are done +%locally by |\presetkeys| and globally by |\gpresetkeys| (compare +%|\savekeys| and |\gsavekeys|, section~\ref{sec:savevalue}). The +%saved macros will be used by |\setkeys|, when they are defined, +%whenever \meta{family} is used in the \meta{families} argument of +%|\setkeys|. Head keys will be set before setting user keys, tail +%keys will be set afterwards. However, if a key appears in the user +%input, this particular key will not be set by any of the preset +%keys. +% +%The macros work incrementally. This means that new input for a +%particular key replaces already present settings for this key. If no +%settings were present yet, the new input for this key will be +%appended to the end of the existing list. The replacement ignores +%the fact whether a |\savevalue| or an |=| has been specified in the key +%input. We could do the following. +%\begin{example} +% \presetkeys{fam}{keya=red,\savevalue{keyb},keyc}{} +% \presetkeys{fam}{\savevalue{keya},keyb=red,keyd}{} +%\end{example} +%After the first line of the example, the macro |\XKV@KV@fam@preseth| +%will contain |keya=red,\savevalue{keyb},keyc|. After the second line of the +%example, the macro will contain |\savevalue{keya},keyb=red,keyc,keyd|. +%The \meta{tail keys} remain empty throughout the example. +% +%\begin{command} +% `\cs{delpresetkeys}\oarg{prefix}\marg{family}\marg{head keys}\marg{tail keys}' +% `\cs{gdelpresetkeys}\oarg{prefix}\marg{family}\marg{head keys}\marg{tail keys}' +%\end{command} +%\DescribeMacros{\delpresetkeys,\gdelpresetkeys} +%These commands can be used to (globally) delete entries from the +%presets by specifying the key names for which the presets should be +%deleted. Continuing the previous example, we could do the following. +%\begin{example} +% \delpresetkeys{fam}{keya,keyb}{} +%\end{example} +%This redefines the list of head presets |\XKV@KV@fam@preseth| to +%contain |keyc,keyd|. As can be seen from this example, the exact +%use of a key name is irrelevant for successful deletion. +% +%\begin{command} +% `\cs{unpresetkeys}\oarg{prefix}\marg{family}' +% `\cs{gunpresetkeys}\oarg{prefix}\marg{family}' +%\end{command} +%\DescribeMacros{\unpresetkeys,\gunpresetkeys} +%These commands clear the presets for \meta{family} and works just as +%|\unsavekeys|. It makes +%|\XKV@|\meta{prefix}|@|\meta{family}|@preseth| and +%|\XKV@|\meta{prefix}|@|\meta{family}|@presett| undefined. The global +%version will make the macros undefined globally. +% +%Two type of problems in relation to pointers could appear when +%specifying head and tail keys incorrectly. This will be demonstrated +%with two examples. In the first example, we would like to set |keya| +%to |blue| and |keyb| to copy the value of |keya|, also when the user +%has changed the preset value of |keya|. Say that we implement the +%following. +%\begin{example} +% \savekeys[my]{familya}{keya} +% \presetkeys[my]{familya}{keya=blue,keyb=\usevalue{keya}}{} +% \setkeys[my]{familya}{keya=red} +%\end{example} +%This will come down to executing +%\begin{example} +% \savekeys[my]{familya}{keya} +% \setkeys[my]{familya}{keyb=\usevalue{keya},keya=red} +%\end{example} +%since |keya| has been specified by the user. At best, |keyb| will +%copy a probably wrong value of |keya|. In the case that no value for +%|keya| has been saved before, we get an error. We observe that the +%order of keys in the simplified |\setkeys| command is wrong. This +%example shows that the |keyb=\usevalue{keya}| should have been in the +%tail keys, so that it can copy the user input to |keya|. +% +%The following example shows what can go wrong when using presets +%incorrectly and when |\setkeys| contains pointers. +%\begin{example} +% \savekeys[my]{familya}{keya} +% \presetkeys[my]{familya}{}{keya=red} +% \setkeys[my]{familya}{keyb=\usevalue{keya}} +%\end{example} +%This will come down to executing the following. +%\begin{example} +% \savekeys[my]{familya}{keya} +% \setkeys[my]{familya}{keyb=\usevalue{keya},keya=red} +%\end{example} +%This results in exactly the same situation as we have seen in the +%previous example and hence the same conclusion holds. In this case, +%we conclude that the |keya=red| argument should have been specified +%in the head keys of the |\presetkeys| command so that |keyb| can +%copy the value of |keya|. +% +%For most applications, one could use the rule of thumb that preset +%keys containing pointers should go in the tail keys. All other keys +%should go in head keys. There might, however, be applications +%thinkable in which one would like to implement the preset system as +%shown in the two examples above, for instance to easily retrieve +%values used in the last use of a macro or environment. However, make +%sure that keys in that case receive an initialization in order to +%avoid errors of missing values. +% +%For completeness, the working examples are below. +%\begin{example} +% \savekeys[my]{familya}{keya} +% \presetkeys[my]{familya}{keya=blue}{keyb=\usevalue{keya}} +% \setkeys[my]{familya}{keya=red} +% \presetkeys[my]{familya}{keya=red}{} +% \setkeys[my]{familya}{keyb=\usevalue{keya}} +%\end{example} +%Other examples can be found in the example files. See section~\ref{sec:sande}. +% +%\section{Package option processing}\label{sec:options} +%\changes{v1.4}{2004/08/24}{Added prefix options to macros} +%The macros in this section can be used to build \LaTeX\ class or +%package options systems using \pf{xkeyval}. These are comparable to +%the standard \LaTeX\ macros without the trailing |X|. See for more +%information about these \LaTeX\ macros the documentation of the +%source \cite{LaTeXbase} or a \LaTeX\ manual (for instance, the +%\LaTeX\ Companion \cite{companion}). The macros in this section have +%been built using |\define@key| and |\setkeys| and are not +%available to \TeX\ users. +% +%The macros below allow for specifying the \meta{family} (or +%\meta{families}) as an optional +%argument. This could be useful if you want to define global options +%which can be reused later (and set locally by the user) in a macro or +%environment that you define. If no \meta{family} (or +%\meta{families}) is specified, the macro will insert the default +%family name which is the filename of the file that is calling the +%macros. The macros in this section also allow for setting an +%optional prefix. When using the filename as family, uniqueness of +%key macros is already guaranteed. In that case, you can omit the +%optional \meta{prefix}. However, when you use a custom prefix for +%other keys in your package and you want to be able to set all of +%the keys later with a single command, you can use the custom prefix +%also for the class or package options system. +% +%Note that both \oarg{arg} and \larg{arg} denote optional arguments +%to the macros in this section. This syntax is used to identify the +%different optional arguments when they appear next to each other. +% +%\begin{command} +% `\cs{DeclareOptionX}\oarg{prefix}\larg{family}\marg{key}\oarg{default}\marg{function}' +%\end{command} +%\DescribeMacro{\DeclareOptionX} +%Declares an option (i.e., a key, which can also be used later on in +%the package in |\setkeys| and friends). This macro is comparable to the +%standard \LaTeX\ macro |\DeclareOption|, but with this command, the +%user can pass a value to the option as well. Reading that value can +%be done by using |#1| in \meta{function}. This will contain +%\meta{default} when no value has been specified for the key. The +%value of the optional argument \meta{default} is empty by default. +%This implies that when the user does not assign a value to +%\meta{key} and when no default value has been defined, no error will +%be produced. The optional argument \meta{family} can be used to +%specify a custom family for the key. When the argument is not used, +%the macro will insert the default family name. +%\begin{example} +% \newif\iflandscape +% \DeclareOptionX{landscape}{\landscapetrue} +% \DeclareOptionX{parindent}[20pt]{\setlength\parindent{#1}} +%\end{example} +%Assuming that the file containing the example above +%is called |myclass.cls|, the example is equivalent to +%\begin{example} +% \newif\iflandscape +% \define@key{myclass.cls}{landscape}[]{\landscapetrue} +% \define@key{myclass.cls}{parindent}[20pt]{\setlength\parindent{#1}} +%\end{example} +%Notice that an empty default value has been inserted by \pf{xkeyval} +%for the |landscape| option. This allows for the usual \LaTeX\ options +%use like +%\begin{example} +% \documentclass[landscape]{myclass} +%\end{example} +%without raising \texttt{No value specified for key `landscape'} errors. +% +%These examples also show that one can also use |\define@key| (or +%friends, see section~\ref{sec:define}) to define class or package +%options. The macros presented here are supplied for the ease of +%package programmers wanting to convert the options section of their +%package to use \pf{xkeyval}. +% +%\begin{command} +% `\cs{DeclareOptionX*}\marg{function}' +%\end{command} +%\DescribeMacro{\DeclareOptionX*} +%This macro can be used to process any unknown inputs. It is +%comparable to the \LaTeX\ macro |\DeclareOption*|. Use +%|\CurrentOption| within this macro to get the entire input from +%which the key is unknown, for instance |unknownkey=value| or +%|somevalue|. These values (possibly including a key) could for +%example be passed on to another class or package or could be used as +%an extra class or package option specifying for instance a style +%that should be loaded. +%\begin{example} +% \DeclareOptionX*{\PackageWarning{mypackage}{`\CurrentOption' ignored}} +%\end{example} +%The example produces a warning when the user issues an option +%that has not been declared. +% +%\begin{command} +% `\cs{ExecuteOptionsX}\oarg{prefix}\larg{families}\oarg{na}\marg{keys}' +%\end{command} +%\DescribeMacro{\ExecuteOptionsX} +%This macro sets keys created by |\DeclareOptionX| and is basically a +%copy of |\setkeys|. The optional argument \meta{na} specifies keys +%that should be ignored. The optional argument \meta{families} can be +%used to specify a list of families which define \meta{keys}. When +%the argument is not used, the macro will insert the default family +%name. This macro will not use the declaration done by |\DeclareOptionX*| +%when undeclared options appear in its argument. Instead, in this case +%the macro will raise an error. This mimics \LaTeX's |\ExecuteOptions|' +%behavior. +%\begin{example} +% \ExecuteOptionsX{parindent=0pt} +%\end{example} +%This initializes |\parindent| to |0pt|. +% +%\begin{command} +% `\cs{ProcessOptionsX}\oarg{prefix}\larg{families}\oarg{na}' +%\end{command} +%\DescribeMacro{\ProcessOptionsX} +%This macro processes the keys and values passed by the user to the +%class or package. The optional argument \meta{na} can be used to +%specify keys that should be ignored. The optional argument +%\meta{families} can be used to specify the families that have been +%used to define the keys. Note that this macro will not protect +%macros in the user inputs (like |\thepage|) as will be explained in +%section~\ref{sec:macrooptions}. When used in a class file, this macro +%will ignore unknown keys or options. This allows +%the user to use global options in the |\documentclass| command which +%can be copied by packages loaded afterwards. +% +%\begin{command} +% `\cs{ProcessOptionsX*}\oarg{prefix}\larg{families}\oarg{na}' +%\end{command} +%\label{macro:poxstar} +%\DescribeMacro{\ProcessOptionsX*} +%The starred version works like |\ProcessOptionsX| except that it also +%copies user input from the |\documentclass| command. When the user +%specifies an option in the document class which also exists in the +%local family (or families) of the package issuing +%|\ProcessOptionsX*|, the local key will be set as well. In this +%case, |#1| in the |\DeclareOptionX| macro will contain the value +%entered in the |\documentclass| command for this key. First the +%global options from |\documentclass| will set local keys and +%afterwards, the local options, specified with |\usepackage|, +%|\RequirePackage| or |\LoadClass| (or friends), will set local keys, +%which could overwrite the global options again, depending on the way +%the options sections are constructed. This macro reduces to +%|\ProcessOptionsX| only when issued from the class which forms the +%document class for the file at hand to avoid setting the same +%options twice, but not for classes loaded later using for instance +%|\LoadClass|. Global options that do not have a counterpart in local +%families of a package or class will be skipped. +% +%It should be noted that these implementations differ from the +%\LaTeX\ implementations of |\ProcessOptions| and |\ProcessOptions*|. +%The difference is in copying the global options. The \LaTeX\ +%commands always copy global options if possible. As a package author +%doesn't know beforehand which document class will be used and with +%which options, the options declared by the author might show some +%unwanted interactions with the global options. When the class and +%the package share the same option, specifying this option in the +%|\documentclass| command will force the package to use that option +%as well. With |\ProcessOptionsX|, \pf{xkeyval} offers a package +%author to become fully independent of the global options and be sure +%to avoid conflicts with any class. Have a look at the example class, +%style and |.tex| file below and observe the effect of changing to +%|\ProcessOptionsX*| in the style file.\footnote{See +%section~\ref{sec:bdefine} for information about +%\cs{define@boolkey}.} +%\begin{minipage}[t]{.49\linewidth} +%\begin{example} +% % myclass.cls +% \RequirePackage{xkeyval} +% \define@boolkey{myclass.cls}% +% [cls]{bool}{} +% \ProcessOptionsX +% \LoadClass{article +%\end{example} +%\end{minipage} +%\hfill +%\begin{minipage}[t]{.49\linewidth} +%\begin{example} +% % mypack.sty +% \define@boolkey{mypack.sty}% +% [pkg]{bool}{} +% \ProcessOptionsX +%\end{example} +%\end{minipage} +%\begin{example} +% % test.tex +% \documentclass[bool=true]{myclass} +% \usepackage{mypack} +% \begin{document}\parindent0pt +% \ifclsbool class boolean true \else class boolean false\fi\\ +% \ifpkgbool package boolean true \else package boolean false\fi +% \end{document} +%\end{example} +%See section~\ref{sec:sande} for more examples. +% +%The use of |\ProcessOptionsX*| in a class file might be tricky since +%the class could also be used as a basis for another package or class +%using |\LoadClass|. In that case, depending on the options system of +%the document class, the behavior of the class loaded with +%|\LoadClass| could change compared to the situation when it is +%loaded by |\documentclass|. But since it is technically possible to +%create two classes that cooperate, the \pf{xkeyval} package allows +%for the usage of |\ProcessOptionsX*| in class files. Notice that +%using \LaTeX's |\ProcessOptions| or |\ProcessOptions*|, a class file +%cannot copy document class options. +% +%In case you want to verify whether your class is loaded with +%|\documentclass| or |\LoadClass|, you can use the |\XKV@documentclass| +%macro which contains the current document class. +% +%A final remark concerns the use of expandable macros in class or +%package options values. Due to the construction of the \LaTeX\ +%option processing mechanism, this is not possible. However, the +%\pf{xkeyval} bundle includes a patch for the \LaTeX\ kernel which +%solves this problem. See section~\ref{sec:ltxpatch} for more +%information. +% +%\section{List of macro structures}\label{sec:macrostructs} +%This section provides a list of all reserved internal macro structures used +%for key processing. Here |pre| denotes a prefix, |fam| denotes a +%family and |key| denotes a key. These vary per application. The +%other parts in internal macro names are constant. The macros with +%additional |XKV| prefix are protected in the sense that all \pf{xkeyval} +%macros disallow the use of the |XKV| prefix. Package authors +%using \pf{xkeyval} are responsible for protecting the other types of +%internal macros. +% +%\begin{description} +%\item[\cs{pre@fam@key}]\mbox{}\\ +%Key macro. This macro takes one argument. This macro will execute +%the \meta{function} of |\define@key| (and friends) on the value +%submitted to the key macro through |\setkeys|. +%\item[\cs{cmdpre@fam@key}]\indent\\ +%The macro which is used by |\define@cmdkey| to store user input in +%when no custom macro prefix was specified. +%\item[\cs{ifpre@fam@key}, \cs{pre@fam@keytrue}, \cs{pre@fam@keyfalse}]\indent\\ +%The conditional created by |\define@boolkey| with parameters |pre|, +%|fam| and |key| if no custom macro prefix was specified. The +%|true| and |false| macros are used to set the conditional to +%|\iftrue| and |\iffalse| respectively. +%\item[\cs{pre@fam@key@default}]\indent\\ +%Default value macro. This macro expands to |\pre@fam@key{default value}|. +%This macro is defined through |\define@key| and friends. +%\item[\cs{XKV@pre@fam@key@value}]\indent\\ +%This macro is used to store the value that has been submitted +%through |\setkeys| to the key macro (without replacing pointers). +%\item[\cs{XKV@pre@fam@save}]\indent\\ +%Contains the names of the keys that should always be saved when they +%appear in a |\setkeys| command. This macro is defined by +%|\savekeys|. +%\item[\cs{XKV@pre@fam@preseth}]\indent\\ +%Contains the head presets. These will be submitted to |\setkeys| +%before setting user input. Defined by |\presetkeys|. +%\item[\cs{XKV@pre@fam@presett}]\indent\\ +%Contains the tail presets. These will be submitted to |\setkeys| +%after setting user input. Defined by |\presetkeys|. +%\end{description} +% +%An important remark should be made. Most of the macros listed above +%will be constructed by \pf{xkeyval} internally using +%|\csname...\endcsname|. Hence almost any input to the macros defined +%by this package is possible. However, some internal macros might be +%used outside \pf{xkeyval} macros as well, for instance the macros of +%the form |\ifpre@fam@key| and |\cmdpre@fam@key|. To be able to use +%these macros yourself, none of the input parameters should contain +%non-letter characters. If you feel that this is somehow necessary +%anyway, there are several strategies to make things work. +% +%Let us consider as example the following situation (notice the hyphen +%|-| in the family name). +%\begin{example} +% \define@boolkey{some-fam}{myif} +% \setkeys{some-fam}{myif=false} +%\end{example} +%Using these keys in a |\setkeys| command is not a problem at all. +%However, if you want to use the |\ifKV@some-fam@myif| command itself, +%you can do either +%\begin{example} +% \edef\savedhyphencatcode{\the\catcode`\-}% +% \catcode`\-=11\relax +% \def\mymacro{% +% \ifKV@some-fam@myif +% % true case +% \else +% % false case +% \fi} +% \catcode`\-=\savedhyphencatcode +%\end{example} +%or +%\begin{example} +% \def\mymacro{% +% \csname ifKV@some-fam@myif\endcsname +% % true case +% \else +% % false case +% \fi} +%\end{example} +% +%\section{Warnings and errors}\label{sec:errors} +%There are several points where \pf{xkeyval} performs a check and +%could produce a warning or an error. All possible warnings or and +%error messages are listed below with an explanation. Here |pre| +%denotes a prefix, |name| denotes the name of a key, |fam| denotes a +%family, |fams| denotes a list of families and |val| denotes some +%value. These vary per application. Note that messages 1 to 7 could +%result from erroneous key setting through |\setkeys|, |\setrmkeys|, +%|\ExecuteOptionsX| and |\ProcessOptionsX|. +% +%\begin{description} +%\item[\normalfont 1)\, \texttt{value `val' is not allowed}]\hfill(error)\\ +%The value that has been submitted to a key macro is not allowed. +%This error can be generated by either a choice or a boolean key. +%\item[\normalfont 2)\, \texttt{`name' undefined in families `fams'}]\hfill(error)\\ +%The key |name| is not defined in the families in |fams|. Probably +%you mistyped |name|. +%\item[\normalfont 3)\, \texttt{no key specified for value `val'}]\hfill(error)\\ +%\pf{xkeyval} found a value without a key, for instance something +%like |=value|, when setting keys. +%\item[\normalfont 4)\, \texttt{no value recorded for key `name'}]\hfill(error)\\ +%You have used a pointer to a key for which no value has been saved +%previously. +%\item[\normalfont 5)\, \texttt{back linking pointers; pointer replacement canceled}]\hfill(error)\\ +%You were back linking pointers. Further pointer replacements are canceled +%to avoid getting into an infinite loop. See section~\ref{sec:usevalue}. +%\item[\normalfont 6)\, \texttt{no value specified for key `name'}]\hfill(error)\\ +%You have used the key `name' without specifying any value for it +%(namely, |\setkeys{fam}{name}| and the key does not have a default +%value. Notice that |\setkeys{fam}{name=}| submits the empty value to +%the key macro and that this is considered a legal value. +%\item[\normalfont 7)\, \label{mess:2}\texttt{key `name' has been disabled}]\hfill(warning)\\ +%The key that you try to set has been disabled and cannot be used anymore. +%\item[\normalfont 8)\, \texttt{`XKV' prefix is not allowed}]\hfill(error)\\ +%You were trying to use the |XKV| prefix when defining or setting +%keys. This error can be caused by any \pf{xkeyval} macro having an +%optional prefix argument. +%\item[\normalfont 9)\, \texttt{key `name' undefined}]\hfill(error)\\ +%This error message is caused by trying to disable a key that does not +%exist. See section~\ref{sec:disable}. +%\item[\normalfont 10)\, \texttt{no save keys defined for `pre@fam@'}]\hfill(error)\\ +%You are trying to delete or undefine save keys that have not been defined yet. +%See section~\ref{sec:savevalue}. +%\item[\normalfont 11)\, \texttt{no presets defined for `pre@fam@'}]\hfill(error)\\ +%You are trying to delete or undefine presets that have not been defined yet. +%See section~\ref{sec:preset}. +%\item[\normalfont 12)\, \texttt{xkeyval loaded before \cs{documentclass}}]\hfill(error)\\ +%Load \pf{xkeyval} after |\documentclass| (or in the class that is +%the document class). See section~\ref{sec:options}. +%\end{description} +% +%\section{Category codes}\label{sec:catcodes} +%Some packages change the catcode of the equality sign and the comma. +%This is a problem for \pf{keyval} as it then does not recognize +%these characters anymore and cannot parse the input. This problem +%can play up on the background. Consider for instance the following +%example and note that the \pf{graphicx} package is using \pf{keyval} +%and that Turkish \pf{babel} will activate the equality sign for +%shorthand notation. +%\begin{example} +% \documentclass{article} +% \usepackage{graphicx} +% \usepackage[turkish]{babel} +% \begin{document} +% \includegraphics[scale=.5]{rose.eps} +% \end{document} +%\end{example} +%The \pf{babel} package provides syntax to temporarily reset the +%catcode of the equality sign and switch shorthand back on after +%using \pf{keyval} (in the |\includegraphics| command), namely +%|\shorthandoff{=}| and |\shorthandon{=}|. But having to do this +%every time \pf{keyval} is invoked is quite cumbersome. Besides that, +%it might not always be clear to the user what the problem is and +%what the solution. +% +%For these reasons, \pf{xkeyval} performs several actions with user +%input before trying to parse it.\footnote{Notice that temporarily +%resetting catcodes before reading the input to \cs{setkeys} won't +%suffice, as it will not help solving problems when input has been +%read before and has been stored in a token register or a macro.} +%First of all, it performs a check whether the characters |=| and |,| +%appear in the input with unexpected catcodes. If so, the +%|\@selective@sanitize| macro is used to sanitize these characters +%only in the top level. This means that characters inside (a) +%group(s), |{ }|, will not be sanitized. For instance, when using +%Turkish \pf{babel}, it is possible to use |=| shorthand notation +%even in the value of a key, as long as this value is inside a group. +%\begin{example} +% \documentclass{article} +% \usepackage{graphicx} +% \usepackage[turkish]{babel} +% \usepackage{xkeyval} +% \makeatletter +% \define@key{fam}{key}{#1} +% \begin{document} +% \includegraphics[scale=.5]{rose.eps} +% \setkeys{fam}{key={some =text}} +% \end{document} +%\end{example} +%In the example above, the |\includegraphics| command does work. +%Further, the first equality sign in the |\setkeys| command will be +%sanitized, but the second one will be left untouched and will be +%typeset as \pf{babel} shorthand notation. +% +%The commands |\savekeys| and |\disable@keys| are protected against +%catcode changes of the comma. The commands |\setkeys| and +%|\presetkeys| are protected against catcode changes of the comma and +%the equality sign. Note that \LaTeX\ option macros (see +%section~\ref{sec:options}) are not protected as \LaTeX\ does not +%protect them either. +% +%\section{Known issues}\label{sec:issues} +%This package redefines \pf{keyval}'s |\define@key| and |\setkeys|. +%This is risky in general. However, since \pf{xkeyval} extends the +%possibilities of these commands while still allowing for the +%\pf{keyval} syntax and use, there should be no problems for packages +%using these commands after loading \pf{xkeyval}. The package +%prevents \pf{keyval} to be loaded afterwards to avoid these commands +%from being redefined again into the simpler versions. For packages +%using internals of \pf{keyval}, like |\KV@@sp@def|, |\KV@do| and +%|\KV@errx|, these are provided separately in |keyval.tex|. +% +%The advantage of redefining these commands instead of making new +%commands is that it is much easier for package authors to start +%using \pf{xkeyval} instead of \pf{keyval}. Further, it eliminates +%the confusion of having multiple commands doing similar things. +% +%A potential problem lies in other packages that redefine either +%|\define@key| or |\setkeys| or both. Hence particular care has been +%spend to check packages for this. Only one package has been found to +%do this, namely \pf{pst-key}. This package implements a custom +%version of |\setkeys| which is specialized to set \pf{PSTricks} +%\cite{PSTricksWeb,PSTricks} keys of the form |\psset@somekey|. +%\pf{xkeyval} also provides the means to set these kind of keys (see +%page~\pageref{page:pstricks}) and work is going on to convert +%\pf{PSTricks} packages to be using a specialization of \pf{xkeyval} +%instead of \pf{pst-key}. This specialization is available in the +%\pf{pst-xkey} package, which is distributed with the \pf{xkeyval} +%bundle and is described in section~\ref{sec:pst-xkey}. However, since +%a lot of authors are involved and since it requires a change of +%policy, the conversion of \pf{PSTricks} packages might take some +%time. Hence, at the moment of writing, \pf{xkeyval} will conflict +%with \pf{pst-key} and the \pf{PSTricks} packages using \pf{pst-key}, +%which are \pf{pst-circ}, \pf{pst-eucl}, \pf{pst-fr3d}, \pf{pst-geo}, +%\pf{pst-gr3d}, \pf{pst-labo}, \pf{pst-lens}, \pf{pst-ob3d}, +%\pf{pst-optic}, \pf{pst-osci}, \pf{pst-poly}, \pf{pst-stru}, +%\pf{pst-uml} and \pf{pst-vue3d}. +% +%Have a look at the \pf{PSTricks} website \cite{PSTricksWeb} to find +%out if the package that you want to use has been converted already. +%If not, load an already converted package (like \pf{pstricks-add}) +%after loading the old package to make them work. +% +%\section{Additional packages}\label{sec:additional} +%\subsection{\pf{xkvview}}\label{sec:view} +%The \pf{xkeyval} bundle includes a viewer utility, called +%\pf{xkvview},\footnote{The \pf{xkvview} package is contained in the +%file \texttt{xkvview.sty}.} which keeps track of the keys that are +%defined. This utility is intended for package programmers who want +%to have an overview of the keys defined in their package(s). All +%keys defined after loading the package will be recorded in a database. +%It provides the following commands to display (part of) the database. +%\begin{command} +% `\cs{xkvview}\marg{options}' +%\end{command} +%\DescribeMacro{\xkvview} +%When \meta{options} is empty, the entire database will be typeset in +%a table created with the \pf{longtable} package. The columns will, +%respectively, contain the key name, the prefix, the family, the type +%(|ordinary|, |command|, |choice| or |boolean|) and the presence of a +%default value for every key defined after loading \pf{xkvview}. +% +%\DescribeOptions{prefix,family,type,default} +%There are several options to control the output of this command. This +%set of options can be used to set up criteria for the keys that +%should be displayed. If a key does not satisfy one or more of them, +%it won't be included in the table. For instance, the following example +%will display all keys with family |fama|, that do not have a +%default value. Notice that \pf{xkvview} codes `no default value' +%with |[none]|. +%\begin{example} +% \documentclass{article} +% \usepackage{xkvview} +% \makeatletter +% \define@key{fama}{keya}[default]{} +% \define@cmdkey{fama}{keyb}{} +% \define@choicekey{famb}{keyc}{a,b}{} +% \define@boolkey{famb}{keyd}{} +% \makeatother +% \begin{document} +% \xkvview{family=fama,default=[none]} +% \end{document} +%\end{example} +%In the following examples in this section, the same preamble will be +%used, but will not be displayed explicitly in the examples. +% +%\DescribeOption{columns} +%One can select the columns that should be included in the table using +%the |columns| option. The following example includes the columns |prefix| +%and |family| in the table (additional to the key name column). +%\begin{example} +% \xkvview{columns={prefix,family}} +%\end{example} +%The remaining columns are called |type| and |default|. +% +%\DescribeOption{vlabels} +%If you want to refer to an option, |\xkvview| can automatically generate +%labels using the scheme \meta{prefix}|-|\meta{family}|-|\meta{keyname}. +%Here is an example. +%\begin{example} +% \xkvview{vlabels=true} +% Find more information about the keya +% option on page~\pageref{KV-fama-keya}. +%\end{example} +% +%\DescribeOptions{file,wcolsep,weol} +%The package can also write (part of) the database to a file. The +%selection of the information happens in the same way as discussed +%above. When specifying a filename with the option |file|, the body +%of the table that is displayed, will also be written to this file. +%Entries will be separated by |wcolsep| which is |&| by default and +%every row will be concluded by |weol| which is |\\| by default. The +%output in the file can then be used as basis for a custom table, for +%instance in package documentation. The following displays a table in +%the dvi and also writes the body to |out.tex|. +%\begin{example} +% \xkvview{file=out} +%\end{example} +%|out.tex| contains +%\begin{example} +% keya&KV&fama&ordinary&default\\ +% keyb&KV&fama&command&[none]\\ +% keyc&KV&famb&choice&[none]\\ +% keyd&KV&famb&boolean&[none]\\ +%\end{example} +% +%The following example generates a table with entries separated by a +%space and no end-of-line content. +%\begin{example} +% \xkvview{file=out,wcolsep=\space,weol=} +%\end{example} +%Now |out.tex| contains +%\begin{example} +% keya KV fama ordinary default +% keyb KV fama command [none] +% keyc KV famb choice [none] +% keyd KV famb boolean [none] +%\end{example} +% +%\DescribeOption{wlabels} +%When post-processing the table generated in this way, one might want +%to refer to entries again as well. When setting |wlabels| to true, +%the labels with names \meta{prefix}|-|\meta{family}|-|\meta{keyname} +%will be in the output file. The following +%\begin{example} +% \xkvview{file=out,wlabels=true} +%\end{example} +%will result in the following content in |out.tex| +%\begin{example} +% keya&KV&fama&ordinary&default\label{KV-fama-keya}\\ +% keyb&KV&fama&command&[none]\label{KV-fama-keyb}\\ +% keyc&KV&famb&choice&[none]\label{KV-famb-keyc}\\ +% keyd&KV&famb&boolean&[none]\label{KV-famb-keyd}\\ +%\end{example} +% +%\DescribeOption{view} +%Finally, when you only want to generate a file and no output to the +%dvi, set the |view| option to false. +%\begin{example} +% \xkvview{file=out,view=false} +%\end{example} +%This example only generate |out.tex| and does not put a table in the +%dvi. +% +%\subsection{\pf{xkvltxp}}\label{sec:macrooptions} +%The package and class option system of \LaTeX\ contained in the +%kernel performs some expansions while processing options. This +%prevents doing for instance +%\begin{example} +% \documentclass[title=My title,author=\textsc{Me}]{myclass} +%\end{example} +%given that |myclass| uses \pf{xkeyval} and defines the options |title| +%and |author|. +% +%This problem can be overcome by redefining certain kernel commands. +%These redefinitions are contained in the \pf{xkvltxp} +%package.\footnote{The \pf{xkvltxp} package consists of the file +%\texttt{xkvltxp.sty}.} If you want to allow the user of your class +%to be able to specify expandable macros in the package options, the +%user will have to do |\RequirePackage{xkvltxp}| on the first line of +%the \LaTeX\ file. If you want to offer this functionality in a +%package, the user can use the package in the ordinary way with +%|\usepackage{xkvltxp}|. This package then has to be loaded before +%loading the package which will use this functionality. A description +%of the patch can be found in the source code documentation. +% +%The examples below summarize this information. The first example +%shows the case in which we want to allow for macros in the +%|\documentclass| command. +%\begin{example} +% \RequirePackage{xkvltxp} +% \documentclass[title=My title,author=\textsc{Me}]{myclass} +% \begin{document} +% \end{document} +%\end{example} +% +%The second example shows the case in which we want to allow for +%macros in a |\usepackage| command. +%\begin{example} +% \documentclass{article} +% \usepackage{xkvltxp} +% \usepackage[footer=page~\thepage.]{mypack} +% \begin{document} +% \end{document} +%\end{example} +% +%Any package or class using \pf{xkeyval} and \pf{xkvltxp} to process +%options can take options that contain macros in their value without +%expanding them prematurely. However, you can of course not use +%macros in options which are not of the |key=value| form since they +%might in the end be passed on to or copied by a package which is not +%using \pf{xkeyval} to process options, which will then produce +%errors. Options of the |key=value| form will be deleted from +%|\@classoptionslist| (see section~\ref{sec:options}) and form no +%threat for packages loaded later on. Finally, make sure not to pass +%options of the |key=value| form to packages not using \pf{xkeyval} +%to process options since they cannot process them. For examples see +%section~\ref{sec:sande}. +% +%\subsection{\pf{pst-xkey}}\label{sec:pst-xkey} +%The \pf{pst-xkey} package\footnote{The \pf{pst-xkey} package +%consists of the files \texttt{pst-xkey.tex} and +%\texttt{pst-xkey.sty}. To load \pf{pst-xkey} \TeX\ users do +%\cs{input pst-xkey}, \LaTeX\ users do +%\cs{RequirePackage\{pst-xkey\}} or \cs{usepackage\{pst-xkey\}}.} +%implements a specialized version of the options system of +%\pf{xkeyval} designed for \pf{PSTricks} \cite{PSTricksWeb,PSTricks}. +%This system gives additional freedom to \pf{PSTricks} package +%authors since they won't have to worry anymore about potentially +%redefining keys of one of the many other \pf{PSTricks} packages. The +%command |\psset| is redefined to set keys in multiple families. +%Reading the documentation of the \pf{xkeyval} package (especially +%section~\ref{sec:issues}) first is recommended. +% +%Keys defined in the original distribution of \pf{PSTricks} have the +%macro structure |\psset@somekey| (where |psset| is literal). These +%can be (re)defined by +%\begin{example} +% \define@key[psset]{}{somekey}{function} +%\end{example} +%Notice especially that these keys are located in the so-called +%`empty family'. For more information about |\define@key| and friends, +%see section~\ref{sec:define}. +% +%When writing a \pf{PSTricks} package, let's say \pf{pst-new}, you +%should locate keys in a family which contains the name of your +%package. If you only need one family, you should define keys using +%\begin{example} +% \define@key[psset]{pst-new}{somekey}{function} +%\end{example} +%If you want to use multiple families in your package, you can do +%\begin{example} +% \define@key[psset]{pst-new-a}{somekey}{function} +% \define@key[psset]{pst-new-b}{anotherkey}{function} +%\end{example} +% +%\DescribeMacros{\pst@addfams,\pst@famlist} +%It is important that you add all of the families that you use in +%your package to the list in |\pst@famlist|. +%This list of families will be used by |\psset| to scan for keys to +%set user input. You can add your families to the list using +%\begin{command} +% `\cs{pst@addfams}\marg{families}' +%\end{command} +%For instance +%\begin{example} +% \pst@addfams{pst-new} +%\end{example} +%or +%\begin{example} +% \pst@addfams{pst-new-a,pst-new-b} +%\end{example} +% +%Only one command is needed to set \pf{PSTricks} keys. +%\begin{command} +% `\cs{psset}\oarg{families}\marg{keys}' +%\end{command} +%\DescribeMacro{\psset} +%This command will set \meta{keys} in \meta{families} using +%|\setkeys+| (see section~\ref{sec:setkeys}). When \meta{families} is +%not specified, it will set \meta{keys} in all families in +%|\pst@famlist| (which includes the empty family for original +%\pf{PSTricks} keys). +%\begin{example} +% \psset{somekey=red,anotherkey} +% \psset[pst-new-b]{anotherkey=green} +%\end{example} +% +%\section{Examples and documentation}\label{sec:sande} +%To generate the package and example files from the source, find the +%source of this package, the file |xkeyval.dtx|, in your local \TeX\ +%installation or on CTAN and run it with \LaTeX. +%\begin{example} +% latex xkeyval.dtx +%\end{example} +%This will generate the package files (|xkeyval.tex|, |xkeyval.sty|, +%|xkvltxp.sty|, |keyval.tex|, |xkvtxhdr.tex| |xkvview.sty|, +%|pst-xkey.tex| and |pst-xkey.sty|) and the example files. +% +%The file |xkvex1.tex| provides an example for \TeX\ users for the +%macros described in sections~\ref{sec:define}, +%\ref{sec:setkeys}, \ref{sec:pointers} and \ref{sec:preset}. The file +%|xkvex2.tex| provides an example for \LaTeX\ users for the same +%macros. The files |xkvex3.tex|, |xkveca.cls|, |xkvecb.cls|, +%|xkvesa.sty|, |xkvesb.sty| and |xkvesc.sty| together form an example +%for the macros described in section~\ref{sec:options}. The set of +%files |xkvex4.tex|, |xkveca.cls|, |xkvecb.cls|, |xkvesa.sty|, +%|xkvesb.sty| and |xkvesc.sty| provides an example for +%sections~\ref{sec:options} and~\ref{sec:macrooptions}. These files +%also demonstrate the possibilities of interaction between packages +%or classes not using \pf{xkeyval} and packages or classes that do +%use \pf{xkeyval} to set options. +% +%To (re)generate this documentation, perform the following steps. +%\begin{example} +% latex xkeyval.dtx +% latex xkeyval.dtx +% bibtex xkeyval +% makeindex -s gglo.ist -o xkeyval.gls xkeyval.glo +% makeindex -s gind.ist -o xkeyval.ind xkeyval.idx +% latex xkeyval.dtx +% latex xkeyval.dtx +%\end{example} +% +% \StopEventually{} +% +% \section{Implementation}\label{sec:imple} +% \subsection{\texttt{xkeyval.tex}} +% Avoid loading |xkeyval.tex| twice. +% \begin{macrocode} +%<*xkvtex> +\csname XKeyValLoaded\endcsname +\let\XKeyValLoaded\endinput +% \end{macrocode} +% Adjust some catcodes to define internal macros. +% \begin{macrocode} +\edef\XKVcatcodes{% + \catcode`\noexpand\@\the\catcode`\@\relax + \catcode`\noexpand\=\the\catcode`\=\relax + \catcode`\noexpand\,\the\catcode`\,\relax + \catcode`\noexpand\:\the\catcode`\:\relax + \let\noexpand\XKVcatcodes\relax +} +\catcode`\@11\relax +\catcode`\=12\relax +\catcode`\,12\relax +\catcode`\:12\relax +% \end{macrocode} +% Initializations. This package uses a private token to avoid +% conflicts with other packages that use \LaTeX\ scratch token registers +% in key macro definitions (for instance, \pf{graphicx}, keys angle +% and scale). +% \begin{macrocode} +\newtoks\XKV@toks +\newcount\XKV@depth +\newif\ifXKV@st +\newif\ifXKV@sg +\newif\ifXKV@pl +\newif\ifXKV@knf +\newif\ifXKV@rkv +\newif\ifXKV@inpox +\newif\ifXKV@preset +\let\XKV@rm\@empty +% \end{macrocode} +% Load \LaTeX\ primitives if necessary and provide information. +% \begin{macrocode} +\ifx\ProvidesFile\@undefined + \message{2005/08/12 v2.5d key=value parser (HA)} + \input xkvtxhdr +\else + \ProvidesFile{xkeyval.tex}[2005/08/12 v2.5d key=value parser (HA)] + \@addtofilelist{xkeyval.tex} +\fi +% \end{macrocode} +% \begin{macro}{\@firstoftwo} +% \begin{macro}{\@secondoftwo} +% Two utility macros from the |latex.ltx| needed for executing +% |\XKV@ifundefined| in the sequel. +% \begin{macrocode} +\long\def\@firstoftwo#1#2{#1} +\long\def\@secondoftwo#1#2{#2} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \begin{macro}{\XKV@afterfi} +% \begin{macro}{\XKV@afterelsefi} +% Two utility macros to move execution of content of a conditional +% branch after the |\fi|. This avoids nesting conditional structures +% too deep. +% \begin{macrocode} +\long\def\XKV@afterfi#1\fi{\fi#1} +\long\def\XKV@afterelsefi#1\else#2\fi{\fi#1} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \begin{macro}{\XKV@ifundefined} +% \changes{v1.8d}{2005/01/02}{Simplified definition by using \cs{XKV@afterelsefi}} +% \changes{v2.0}{2005/01/30}{Made none \eTeX\ version not leave \cs{relax}} +% \marg{csname}\marg{undefined}\marg{defined}\\ +% Executes \meta{undefined} if the control sequence with name \meta{csname} +% is undefined, else it executes \meta{defined}. This macro uses +% \eTeX\ if possible to avoid filling \TeX's hash when checking +% control sequences like key macros in the rest of the package. +% The use of |\XKV@afterelsefi| is necessary here to avoid \TeX\ picking up the +% second |\fi| as end of the main conditional when |\ifcsname| is +% undefined. For |\XKV@afterelsefi| this |\fi| is hidden in the +% group used to define |\XKV@ifundefined| in branch of the case that +% |\ifcsname| is defined. Notice the following. Both versions of the +% macro leave the tested control sequence undefined. However, the +% first version will execute \meta{undefined} if the control sequence +% is undefined or |\relax|, whereas the second version will only +% execute \meta{undefined} if the control sequence is undefined. This +% is no problem for the applications in this package. +% \begin{macrocode} +\ifx\ifcsname\@undefined\XKV@afterelsefi + \def\XKV@ifundefined#1{% + \begingroup\expandafter\expandafter\expandafter\endgroup + \expandafter\ifx\csname#1\endcsname\relax + \expandafter\@firstoftwo + \else + \expandafter\@secondoftwo + \fi + } +\else + \def\XKV@ifundefined#1{% + \ifcsname#1\endcsname + \expandafter\@secondoftwo + \else + \expandafter\@firstoftwo + \fi + } +\fi +% \end{macrocode} +% \end{macro} +% Check whether \pf{keyval} has been loaded and if not, load +% \pf{keyval} primitives and prevent \pf{keyval} from being loaded +% after \pf{xkeyval}. +% \begin{macrocode} +\XKV@ifundefined{ver@keyval.sty}{ + \input keyval + \expandafter\def\csname ver@keyval.sty\endcsname{1999/03/16} +}{} +% \end{macrocode} +% \begin{macro}{\@ifnextcharacter} +% \changes{v1.4}{2004/08/24}{Added robust next character check} +% \begin{macro}{\@ifncharacter} +% Check the next character independently of its catcode. This will be +% used to safely perform |\@ifnextcharacter+| and +% |\@ifnextcharacter*|. This avoids errors in case any other package +% changes the catcode of these characters.\\ Contributed by Donald +% Arseneau. +% \begin{macrocode} +\long\def\@ifnextcharacter#1#2#3{% + \@ifnextchar\bgroup + {\@ifnextchar{#1}{#2}{#3}}% + {\@ifncharacter{#1}{#2}{#3}}% +} +\long\def\@ifncharacter#1#2#3#4{% + \if\string#1\string#4% + \expandafter\@firstoftwo + \else + \expandafter\@secondoftwo + \fi + {#2}{#3}#4% +} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \begin{macro}{\XKV@for@n} +% \marg{list}\meta{cmd}\marg{function}\\ +% Fast for-loop. \meta{list} is not expanded. Entries of \meta{list} +% will be stored in \meta{cmd} and at every iteration \meta{function} +% is executed.\\ +% Contributed by Morten H\o gholm. +% \begin{macrocode} +\long\def\XKV@for@n#1#2#3{% + \def#2{#1}% + \ifx#2\@empty + \XKV@for@break + \else + \expandafter\XKV@f@r + \fi + #2{#3}#1,\@nil,% +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\XKV@f@r} +% \meta{cmd}\marg{function}\meta{entry}|,|\\ +% Looping macro. +% \begin{macrocode} +\long\def\XKV@f@r#1#2#3,{% + \def#1{#3}% + \ifx#1\@nnil + \expandafter\@gobbletwo + \else + #2\expandafter\XKV@f@r + \fi + #1{#2}% +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\XKV@for@break} +% \meta{text}|\@nil,|\\ +% Macro to stop the for-loop. +% \begin{macrocode} +\long\def\XKV@for@break #1\@nil,{\fi} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\XKV@for@o} +% \meta{listcmd}\meta{cmd}\marg{function}\\ +% \meta{listcmd} is expanded once before starting the loop. +% \begin{macrocode} +\long\def\XKV@for@o#1{\expandafter\XKV@for@n\expandafter{#1}} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\XKV@for@en} +% \marg{list}\meta{cmd}\marg{function}\\ +% As |\XKV@for@n|, but this macro will execute \meta{function} also +% when \meta{list} is empty. This is done to support packages that use the `empty +% family', like \pf{PSTricks}. +% \begin{macrocode} +\long\def\XKV@for@en#1#2#3{\XKV@f@r#2{#3}#1,\@nil,} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\XKV@for@eo} +% \meta{listcmd}\meta{cmd}\marg{function}\\ +% As |\XKV@for@o|, but this macro will execute \meta{function} also +% when \meta{listcmd} is empty. +% \begin{macrocode} +\long\def\XKV@for@eo#1#2#3{% + \def#2{\XKV@f@r#2{#3}}\expandafter#2#1,\@nil,% +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\XKV@whilist} +% \meta{listcmd}\meta{cmd}\meta{if}|\fi|\marg{function}\\ +% \changes{v1.5}{2004/09/27}{Changed behavior} +% \meta{listcmd} is expanded once. Execution of \meta{function} stops when either +% the list has ran out of elements or \meta{if} is not true anymore. +% When using |\iftrue| for \meta{if}, the execution of the macro is the +% same as that of |\XKV@for@o|, but contains an additional check at every +% iteration and is +% hence less efficient than |\XKV@for@o| in that situation. +% \begin{macrocode} +\long\def\XKV@whilist#1#2#3\fi#4{% +% \end{macrocode} +% Check whether the condition is true and start iteration. +% \begin{macrocode} + #3\expandafter\XKV@wh@list#1,\@nil,\@nil\@@#2#3\fi{#4}{}\fi +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\XKV@wh@list} +% \changes{v1.6}{2004/10/05}{Added missing \%} +% \changes{v1.9}{2005/01/16}{Made running command contain last used list entry at exit} +% \changes{v2.4}{2005/03/31}{Avoid using grouping} +% \meta{entry}|,|\meta{text}|\@@|\meta{cmd}\meta{if}|\fi|\marg{function}\marg{previous}\\ +% Performs iteration and checks extra condition. This macro is not +% optimized for the case that the list contains a single element. At +% the end of every iteration, the current \meta{entry} will be stored +% in \meta{previous} for the next iteration. The previous entry is +% necessary when stepping out of the loop. +% \begin{macrocode} +\long\def\XKV@wh@list#1,#2\@@#3#4\fi#5#6{% +% \end{macrocode} +% Define the running \meta{cmd}. +% \begin{macrocode} + \def#3{#1}% +% \end{macrocode} +% If we find the end of the list, stop. +% \begin{macrocode} + \ifx#3\@nnil + \def#3{#6}\expandafter\XKV@wh@l@st + \else +% \end{macrocode} +% If the condition is met, execute \meta{function} and continue. +% Otherwise, define the running command to be the previous entry +% (which inflicted the condition becoming false) and stop. +% \begin{macrocode} + #4% + #5\expandafter\expandafter\expandafter\XKV@wh@list + \else + \def#3{#6}\expandafter\expandafter\expandafter\XKV@wh@l@st + \fi + \fi + #2\@@#3#4\fi{#5}{#1}% +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\XKV@wh@l@st} +% \meta{text}|\@@|\meta{cmd}\meta{if}|\fi|\marg{function}\marg{previous}\\ +% Macro to gobble remaining input. +% \begin{macrocode} +\long\def\XKV@wh@l@st#1\@@#2#3\fi#4#5{} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\XKV@addtomacro@n} +% \meta{macro}\marg{content}\\ +% Adds \meta{content} to \meta{macro} without expanding it. +% \begin{macrocode} +\def\XKV@addtomacro@n#1#2{% + \expandafter\def\expandafter#1\expandafter{#1#2}% +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\XKV@addtomacro@o} +% \meta{macro}\marg{content}\\ +% Adds \meta{content} to \meta{macro} after expanding the first token +% of \meta{content} once. Often used to add the content of a macro +% to another macro. +% \begin{macrocode} +\def\XKV@addtomacro@o#1#2{% + \expandafter\expandafter\expandafter\def + \expandafter\expandafter\expandafter#1\expandafter + \expandafter\expandafter{\expandafter#1#2}% +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\XKV@addtolist@n} +% \meta{cmd}\marg{content}\\ +% \changes{v1.8 }{2004/12/13}{Changed to respect groups} +% \changes{v2.0}{2005/01/30}{Simplified} +% Adds \meta{content} to the list in \meta{cmd} without expanding \meta{content}. +% Notice that it is assumed that \meta{cmd} is not undefined. +% \begin{macrocode} +\def\XKV@addtolist@n#1#2{% + \ifx#1\@empty + \XKV@addtomacro@n#1{#2}% + \else + \XKV@addtomacro@n#1{,#2}% + \fi +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\XKV@addtolist@o} +% \meta{cmd}\marg{content}\\ +% \changes{v2.0}{2005/01/30}{Simplified} +% Adds \meta{content} to the list in \meta{cmd} after expanding the +% first token in \meta{content} once. +% \begin{macrocode} +\def\XKV@addtolist@o#1#2{% + \ifx#1\@empty + \XKV@addtomacro@o#1#2% + \else + \XKV@addtomacro@o#1{\expandafter,#2}% + \fi +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\XKV@addtolist@x} +% \meta{cmd}\marg{content}\\ +% Adds \meta{content} to the list in \meta{cmd} after a full expansion +% of both \meta{cmd} and \meta{content}. +% \begin{macrocode} +\def\XKV@addtolist@x#1#2{\edef#1{#1\ifx#1\@empty\else,\fi#2}} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\@selective@sanitize} +% \begin{macro}{\@s@lective@sanitize} +% \changes{v2.5a}{2005/05/31}{Added missing `\%'} +% \oarg{level}\marg{character string}\marg{cmd}\\ +% Converts selected characters, given by \meta{character string}, +% within the first-level expansion of \meta{cmd} to category code~12, +% leaving all other tokens (including grouping braces) untouched. +% Thus, macros inside \meta{cmd} do not lose their function, as it is +% the case with |\@onelevel@sanitize|. +% The resulting token list is again saved in \meta{cmd}.\\ +% Example: |\def\cs{ ^{\fi}~}| and |\@selective@sanitize{!^}\cs| will +% change the catcode of `|^|' to \emph{other} +% within |\cs|, while |\fi| and `|~|' will remain unchanged. +% As the example shows, unbalanced conditionals are allowed.\\ +% Remarks: \meta{cmd} should not contain the control sequence |\bgroup|; +% however, |\csname| |bgroup\endcsname| and |\egroup| are possible. +% The optional \meta{level} command controls up to which nesting +% level sanitizing takes place inside groups; |0| will only sanitize +% characters in the top level, |1| will also sanitize within the first +% level of braces (but not in the second), etc. +% The default value is |10000|. +% \begin{macrocode} +\def\@selective@sanitize{\@testopt\@s@lective@sanitize\@M} +\def\@s@lective@sanitize[#1]#2#3{% + \begingroup + \count@#1\relax\advance\count@\@ne + \XKV@toks\expandafter{#3}% + \def#3{#2}\@onelevel@sanitize#3% + \edef#3{{#3}{\the\XKV@toks}}% + \expandafter\@s@l@ctive@sanitize\expandafter#3#3% + \expandafter\endgroup\expandafter\def\expandafter#3\expandafter{#3}% +} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \begin{macro}{\@s@l@ctive@sanitize} +% \changes{v1.8 }{2004/12/13}{Bug fixed, added level control} +% \marg{cmd}\marg{sanitized character string}\marg{token list}\\ +% Performs the main work. +% Here, the characters in \meta{sanitized character string} are already +% converted to catcode~12, \meta{token list} is the first-level expansion +% of the original contents of \meta{cmd}. +% The macro basically steps through the \meta{token list}, inspecting +% each single token to decide whether it has to be sanitized or passed +% to the result list. +% Special care has to be taken to detect spaces, grouping characters +% and conditionals (the latter may disturb other expressions). +% However, it is easier and more efficient to look for \TeX{} +% primitives in general -- which are characterized by a |\meaning| +% that starts with a backslash -- than to test whether a token equals +% specifically |\if|, |\else|, |\fi|, etc. +% Note that |\@s@l@ctive@sanitize| is being called recursively if +% \meta{token list} contains grouping braces. +% \begin{macrocode} +\def\@s@l@ctive@sanitize#1#2#3{% + \def\@i{\futurelet\@@tok\@ii}% + \def\@ii{% + \expandafter\@iii\meaning\@@tok\relax + \ifx\@@tok\@s@l@ctive@sanitize + \let\@@cmd\@gobble + \else + \ifx\@@tok\@sptoken + \XKV@toks\expandafter{#1}\edef#1{\the\XKV@toks\space}% + \def\@@cmd{\afterassignment\@i\let\@@tok= }% + \else + \let\@@cmd\@iv + \fi + \fi + \@@cmd + }% + \def\@iii##1##2\relax{\if##1\@backslashchar\let\@@tok\relax\fi}% + \def\@iv##1{% + \toks@\expandafter{#1}\XKV@toks{##1}% + \ifx\@@tok\bgroup + \advance\count@\m@ne + \ifnum\count@>\z@ + \begingroup + \def#1{\expandafter\@s@l@ctive@sanitize + \csname\string#1\endcsname{#2}}% + \expandafter#1\expandafter{\the\XKV@toks}% + \XKV@toks\expandafter\expandafter\expandafter + {\csname\string#1\endcsname}% + \edef#1{\noexpand\XKV@toks{\the\XKV@toks}}% + \expandafter\endgroup#1% + \fi + \edef#1{\the\toks@{\the\XKV@toks}}% + \advance\count@\@ne + \let\@@cmd\@i + \else + \edef#1{\expandafter\string\the\XKV@toks}% + \expandafter\in@\expandafter{#1}{#2}% + \edef#1{\the\toks@\ifin@#1\else + \ifx\@@tok\@sptoken\space\else\the\XKV@toks\fi\fi}% + \edef\@@cmd{\noexpand\@i\ifx\@@tok\@sptoken\the\XKV@toks\fi}% + \fi + \@@cmd + }% + \let#1\@empty\@i#3\@s@l@ctive@sanitize +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\XKV@checksanitizea} +% \marg{content}\meta{cmd}\\ +% Check whether \meta{content}, to be saved to macro \meta{cmd} unexpanded, +% contains the characters |=| or |,| with wrong catcodes. If so, it sanitizes +% them before saving \meta{content} to \meta{cmd}. +% \begin{macrocode} +\def\XKV@checksanitizea#1#2{% + \XKV@ch@cksanitize{#1}#2=% + \ifin@\else\XKV@ch@cksanitize{#1}#2,\fi + \ifin@\@selective@sanitize[0]{,=}#2\fi +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\XKV@checksanitizeb} +% \marg{content}\meta{cmd}\\ +% Similar to |\XKV@checksanitizea|, but only checks commas. +% \begin{macrocode} +\def\XKV@checksanitizeb#1#2{% + \XKV@ch@cksanitize{#1}#2,% + \ifin@\@selective@sanitize[0],#2\fi +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\XKV@ch@cksanitize} +% \changes{v1.8b}{2004/12/22}{Fixed bug for key value \cs{@empty}} +% \marg{character string}\meta{cmd}\meta{token}\\ +% This macro first checks whether at least one \meta{token} is in \meta{character string}. +% If that is the case, it checks whether the character has catcode 12. +% Note that the macro will conclude that the character does not have +% catcode 12 when it is used inside a group |{}|, but that is not a +% problem, as we don't expect \meta{token} (namely |,| or |=|) inside +% a group, unless this group is in a key value. But we won't worry about +% those characters anyway since the relevant user key macro will have to +% process that. Further, it is assumed that all occurrences of \meta{token} +% in \meta{character string} have the same catcode. \meta{cmd} is used +% as a temporary macro and will contain \meta{character string} at the +% end of the macro. +% \begin{macrocode} +\def\XKV@ch@cksanitize#1#2#3{% + \def#2{#1}% + \@onelevel@sanitize#2% +% \end{macrocode} +% Check whether there is at least one |=| present. +% \begin{macrocode} + \@expandtwoargs\in@#3{#2}% + \ifin@ +% \end{macrocode} +% If so, try to find it. If we can't find it, the character(s) has (or +% have) the wrong catcode. In that case sanitizing is necessary. This +% actually occurs, because the input was read by \TeX\ +% before (and for instance stored in a macro or token register). +% \begin{macrocode} + \def#2##1#3##2\@nil{% + \def#2{##2}% + \ifx#2\@empty\else\in@false\fi + }% + #2#1#3\@nil + \fi + \def#2{#1}% +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\XKV@sp@deflist} +% \changes{v1.8a}{2004/12/20}{Modified to respect the empty family} +% \meta{cmd}\marg{token list}\\ +% Defines \meta{cmd} as \meta{token list} after removing spaces surrounding +% elements of the list in \meta{token list}. So, |keya, key b| becomes +% |keya,key b|. This is used to remove spaces from around elements in +% a list. Using |\zap@space| for this job, would also remove the +% spaces inside elements and hence changing key or family names with +% spaces. This method is slower, but does allow for spaces in key and +% family names, just as \pf{keyval} did. We need this algorithm at +% several places to be able to perform |\in@{,key,}{,...,}|, without +% having to worry about spaces in between commas and key names. +% \begin{macrocode} +\def\XKV@sp@deflist#1#2{% + \let#1\@empty + \XKV@for@n{#2}\XKV@resa{% + \expandafter\KV@@sp@def\expandafter\XKV@resa\expandafter{\XKV@resa}% + \XKV@addtomacro@o#1{\expandafter,\XKV@resa}% + }% + \ifx#1\@empty\else + \def\XKV@resa,##1\@nil{\def#1{##1}}% + \expandafter\XKV@resa#1\@nil + \fi +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\XKV@merge} +% \changes{v1.8 }{2004/12/13}{Simplified} +% \meta{list}\marg{new items}\meta{filter}\\ +% This is a merging macro. For a given new item, the old +% items are scanned. If an old item key name matches with a new +% one, the new one will replace the old one. If not, the old one will +% be appended (and might be overwritten in a following loop). If, at +% the end of the old item loop the new item has not been used, it +% will be appended to the end of the list. This macro works irrespective +% of special syntax. The \meta{filter} is used to filter the key name +% from the syntax, eg |\global{key}|. All occurrences of a particulary key +% in the existing list will be overwritten by the new item. This macro +% is used to make |\savekeys| and |\presetkeys| incremental. The +% \meta{filter} is |\XKV@getsg| and |\XKV@getkeyname| respectively. +% \begin{macrocode} +\def\XKV@merge#1#2#3{% + \XKV@checksanitizea{#2}\XKV@tempa +% \end{macrocode} +% Start the loop over the new presets. At every iteration, one new preset +% will be compared with old presets. +% \begin{macrocode} + \XKV@for@o\XKV@tempa\XKV@tempa{% + \XKV@pltrue +% \end{macrocode} +% Retrieve the key name of the new item at hand. +% \begin{macrocode} + #3\XKV@tempa\XKV@tempb +% \end{macrocode} +% Store the (partially updated) old list in a temp macro and empty +% the original macro. +% \begin{macrocode} + \let\XKV@tempc#1% + \let#1\@empty +% \end{macrocode} +% Start a loop over the old list. +% \begin{macrocode} + \XKV@for@o\XKV@tempc\XKV@tempc{% +% \end{macrocode} +% Retrieve the key name of the old key at hand. +% \begin{macrocode} + #3\XKV@tempc\XKV@tempd + \ifx\XKV@tempb\XKV@tempd +% \end{macrocode} +% If the key names are equal, append the new item to the list +% and record that this key should not be added to the end of the +% presets list. +% \begin{macrocode} + \XKV@plfalse + \XKV@addtolist@o#1\XKV@tempa + \else +% \end{macrocode} +% If the key names are not equal, then just append the current item +% to the list. +% \begin{macrocode} + \XKV@addtolist@o#1\XKV@tempc + \fi + }% +% \end{macrocode} +% If, after checking the old item, no old item has been overwritten +% then append the new item to the end of the existing list. +% \begin{macrocode} + \ifXKV@pl\XKV@addtolist@o#1\XKV@tempa\fi + }% +% \end{macrocode} +% If requested, save the new list globally. +% \begin{macrocode} + \ifXKV@st\global\let#1#1\fi +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\XKV@delete} +% \meta{list}\marg{delete}\meta{filter}\\ +% Delete entries \meta{delete} by key name from a \meta{list} of presets +% or save keys using \meta{filter}. For |\delpresetkeys|, +% this is the macro |\XKV@getkeyname| and for |\delsavekeys|, it is +% the macro |\XKV@getsg|. +% \begin{macrocode} +\def\XKV@delete#1#2#3{% +% \end{macrocode} +% Sanitize comma's. +% \begin{macrocode} + \XKV@checksanitizeb{#2}\XKV@tempa +% \end{macrocode} +% Copy the current list and make the original empty. +% \begin{macrocode} + \let\XKV@tempb#1% + \let#1\@empty +% \end{macrocode} +% Run over the current list. +% \begin{macrocode} + \XKV@for@o\XKV@tempb\XKV@tempb{% +% \end{macrocode} +% Get the key name to identify the current entry. +% \begin{macrocode} + #3\XKV@tempb\XKV@tempc +% \end{macrocode} +% If the current key name is in the list, do not add it anymore. +% \begin{macrocode} + \@expandtwoargs\in@{,\XKV@tempc,}{,\XKV@tempa,}% + \ifin@\else\XKV@addtolist@o#1\XKV@tempb\fi + }% +% \end{macrocode} +% Save globally is necessary. +% \begin{macrocode} + \ifXKV@st\global\let#1#1\fi +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\XKV@warn} +% \begin{macro}{\XKV@err} +% \begin{macro}{\KV@err} +% \begin{macro}{\KV@errx} +% Warning and error macros. We redefine the \pf{keyval} error macros +% to use the \pf{xkeyval} ones. This avoids redefining them again when +% we redefine the |\XKV@warn| and |\XKV@err| macros in |xkeyval.sty|. +% \begin{macrocode} +\def\XKV@warn#1{\message{xkeyval warning: #1}} +\def\XKV@err#1{\errmessage{xkeyval error: #1}} +\def\KV@errx{\XKV@err} +\let\KV@err\KV@errx +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \begin{macro}{\XKV@ifstar} +% \begin{macro}{\XKV@ifplus} +% Checks whether the following token is a |*| or |+|. Use +% |\XKV@ifnextchar| to perform the action safely and ignore catcodes. +% \begin{macrocode} +\def\XKV@ifstar#1{\@ifnextcharacter*{\@firstoftwo{#1}}} +\def\XKV@ifplus#1{\@ifnextcharacter+{\@firstoftwo{#1}}} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \begin{macro}{\XKV@makepf} +% \changes{v1.7}{2004/11/25}{Made macro protect internal macros} +% \marg{prefix}\\ +% This macro creates the prefix, like |prefix@| in |\prefix@family@key|. +% First it deletes spaces from the input and checks whether it is empty. +% If not empty, an |@|-sign is added. The use of the |XKV| prefix is +% forbidden to protect internal macros and special macros like saved +% key values. +% \begin{macrocode} +\def\XKV@makepf#1{% + \KV@@sp@def\XKV@prefix{#1}% + \def\XKV@resa{XKV}% + \ifx\XKV@prefix\XKV@resa + \XKV@err{`XKV' prefix is not allowed}% + \let\XKV@prefix\@empty + \else + \edef\XKV@prefix{\ifx\XKV@prefix\@empty\else\XKV@prefix @\fi}% + \fi +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\XKV@makehd} +% \marg{family}\\ +% Creates the header, like |prefix@family@| in |\prefix@family@key|. +% If \meta{family} is empty, the header reduces to |prefix@|. +% \begin{macrocode} +\def\XKV@makehd#1{% + \expandafter\KV@@sp@def\expandafter\XKV@header\expandafter{#1}% + \edef\XKV@header{% + \XKV@prefix\ifx\XKV@header\@empty\else\XKV@header @\fi + }% +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\XKV@srstate} +% \marg{postfix1}\marg{postfix2}\\ +% Macro to save and restore \pf{xkeyval} internals to allow for +% nesting |\setkeys| commands. It executes a for loop over a set of +% \pf{xkeyval} internals and does, for instance, |\let\XKV@na@i\XKV@na| +% to prepare for stepping a level deeper. If \meta{prefix2} is empty, +% we step a level deeper. If \meta{prefix1} is empty, we go a level up. +% The non-empty argument is always |@\romannumeral\XKV@depth|. Notice +% that this also helps to keep changes to boolean settings (for instance +% by |\XKV@cc*+|) local to the execution of that key. +% \begin{macrocode} +\def\XKV@srstate#1#2{% + \ifx\@empty#2\@empty\advance\XKV@depth\@ne\fi + \XKV@for@n{XKV@prefix,XKV@fams,XKV@na,ifXKV@st,ifXKV@pl,ifXKV@knf}% + \XKV@resa{\expandafter\let\csname\XKV@resa#1\expandafter + \endcsname\csname\XKV@resa#2\endcsname + }% + \ifx\@empty#1\@empty\advance\XKV@depth\m@ne\fi +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\XKV@testopta} +% \begin{macro}{\XKV@t@stopta} +% \marg{function}\\ +% Tests for the presence of an optional star or plus and executes +% \meta{function} afterwards. +% \begin{macrocode} +\def\XKV@testopta#1{% + \XKV@ifstar{\XKV@sttrue\XKV@t@stopta{#1}}% + {\XKV@stfalse\XKV@t@stopta{#1}}% +} +\def\XKV@t@stopta#1{\XKV@ifplus{\XKV@pltrue#1}{\XKV@plfalse#1}} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \begin{macro}{\XKV@testoptb} +% \begin{macro}{\XKV@t@stoptb} +% \marg{function}\\ +% First check for an optional prefix. Afterwards, set the \meta{prefix}, set +% the header, remove spaces from the \meta{family} and execute \meta{function}. +% \begin{macrocode} +\def\XKV@testoptb#1{\@testopt{\XKV@t@stoptb#1}{KV}} +\def\XKV@t@stoptb#1[#2]#3{% +% \end{macrocode} +% Set prefix. +% \begin{macrocode} + \XKV@makepf{#2}% +% \end{macrocode} +% Set header. +% \begin{macrocode} + \XKV@makehd{#3}% +% \end{macrocode} +% Save family name for later use. +% \begin{macrocode} + \KV@@sp@def\XKV@tfam{#3}% + #1% +} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \begin{macro}{\XKV@testoptc} +% \begin{macro}{\XKV@t@stoptc} +% \marg{function}\\ +% Test for an optional \meta{prefix}. Then, set the \meta{prefix}, +% sanitize comma's in the list of \meta{families} and remove redundant +% spaces from this list. Finally, check for optional key names that +% should not be set and execute \meta{function}. +% \begin{macrocode} +\def\XKV@testoptc#1{\@testopt{\XKV@t@stoptc#1}{KV}} +\def\XKV@t@stoptc#1[#2]#3{% + \XKV@makepf{#2}% + \XKV@checksanitizeb{#3}\XKV@fams + \expandafter\XKV@sp@deflist\expandafter + \XKV@fams\expandafter{\XKV@fams}% + \@testopt#1{}% +} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \begin{macro}{\XKV@testoptd} +% \begin{macro}{\XKV@t@stoptd} +% \marg{function}\\ +% Use |\XKV@testoptb| first to find \meta{prefix} and the +% \meta{family}. Then check for optional \meta{mp} (`macro prefix'). +% Next eat the \meta{key} name and check for an optional +% \meta{default} value. +% \begin{macrocode} +\def\XKV@testoptd#1#2{% + \XKV@testoptb{% + \edef\XKV@tempa{#2\XKV@header}% + \def\XKV@tempb{\@testopt{\XKV@t@stoptd#1}}% + \expandafter\XKV@tempb\expandafter{\XKV@tempa}% + }% +} +\def\XKV@t@stoptd#1[#2]#3{% +% \end{macrocode} +% |\ifXKV@st| gives the presence of an optional default value. +% \begin{macrocode} + \@ifnextchar[{\XKV@sttrue#1{#2}{#3}}{\XKV@stfalse#1{#2}{#3}[]}% +} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \begin{macro}{\XKV@ifcmd} +% \begin{macro}{\XKV@@ifcmd} +% \marg{tokens}\marg{macro}\marg{cmd}\marg{yes}\marg{no}\\ +% This macro checks whether the \meta{tokens} contains the macro +% specification \meta{macro}. If so, the argument to this macro +% will be saved to \meta{cmd} and \meta{yes} will be executed. +% Otherwise, the content of \meta{tokens} is saved to \meta{cmd} +% and \meta{no} is executed. This macro will, for instance, be used +% to distinguish |key| and |\global{key}| and retrieve |key| in the +% latter case. +% \begin{macrocode} +\def\XKV@ifcmd#1#2#3{% + \def\XKV@@ifcmd##1#2##2##3\@nil##4{% + \def##4{##2}\ifx##4\@nnil + \def##4{##1}\expandafter\@secondoftwo + \else + \expandafter\@firstoftwo + \fi + }% + \XKV@@ifcmd#1#2{\@nil}\@nil#3% +} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \begin{macro}{\XKV@getkeyname} +% \meta{keyvalue}\meta{bin}\\ +% Utility macro to retrieve the key name from \meta{keyvalue} which +% is of the form |key=value|, |\savevalue{key}=value| or +% |\gsavevalue{key}=value|, possibly without |value|. |\ifXKV@rkv| +% will record whether this particular value should be saved. +% |\ifXKV@sg| will record whether this value should be saved globally +% or not. The key name will be stored in \meta{bin}. +% \begin{macrocode} +\def\XKV@getkeyname#1#2{\expandafter\XKV@g@tkeyname#1=\@nil#2} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\XKV@g@tkeyname} +% \meta{key}|=|\meta{value}|\@nil|\meta{bin}\\ +% Use |\XKV@ifcmd| several times to check the syntax of \meta{value}. +% Save \meta{key} to \meta{bin}. +% \begin{macrocode} +\def\XKV@g@tkeyname#1=#2\@nil#3{% + \XKV@ifcmd{#1}\savevalue#3{\XKV@rkvtrue\XKV@sgfalse}{% + \XKV@ifcmd{#1}\gsavevalue#3% + {\XKV@rkvtrue\XKV@sgtrue}{\XKV@rkvfalse\XKV@sgfalse}% + }% +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\XKV@getsg} +% \meta{key}\meta{bin}\\ +% Utility macro to check whether |key| or |\global{key}| has been +% specified in \meta{key}. The key name is saved to \meta{bin} +% \begin{macrocode} +\def\XKV@getsg#1#2{% + \expandafter\XKV@ifcmd\expandafter{#1}\global#2\XKV@sgtrue\XKV@sgfalse +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\XKV@define@default} +% \marg{key}\marg{default}\\ +% Defines the default value macro for \meta{key} and given |\XKV@header|. +% \begin{macrocode} +\def\XKV@define@default#1#2{% + \expandafter\def\csname\XKV@header#1@default\expandafter + \endcsname\expandafter{\csname\XKV@header#1\endcsname{#2}}% +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\define@key} +% \changes{v1.4}{2004/08/24}{Added optional check} +% \oarg{prefix}\marg{family}\\ +% Macro to define a key in a family. Notice the use of the |KV| prefix +% as default prefix. This is done to allow setting both \pf{keyval} and +% \pf{xkeyval} keys with a single command. This top level command first +% checks for an optional \meta{prefix} and the mandatory \meta{family}. +% \begin{macrocode} +\def\define@key{\XKV@testoptb\XKV@define@key} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\XKV@define@key} +% \marg{key}\\ +% Check for an optional default value. If none present, define the +% key macro, else continue to eat the default value. +% \begin{macrocode} +\def\XKV@define@key#1{% + \@ifnextchar[{\XKV@d@fine@k@y{#1}}{% + \expandafter\def\csname\XKV@header#1\endcsname####1% + }% +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\XKV@d@fine@key} +% \marg{key}\oarg{default}\\ +% Defines the key macro and the default value macro. +% \begin{macrocode} +\def\XKV@d@fine@k@y#1[#2]{% + \XKV@define@default{#1}{#2}% + \expandafter\def\csname\XKV@header#1\endcsname##1% +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\define@cmdkey} +% \oarg{prefix}\marg{family}\oarg{mp}\marg{key}\\ +% Define a command key. +% Test for optional \meta{prefix}, mandatory \meta{family}, optional +% \meta{mp} `macro prefix' and mandatory \meta{key} name. +% \begin{macrocode} +\def\define@cmdkey{\XKV@testoptd\XKV@define@cmdkey{cmd}} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\XKV@define@cmdkey} +% \marg{mp}\marg{key}\oarg{default}\marg{function}\\ +% \changes{v2.5c}{2005/07/10}{Avoid initializing control sequence as \cs{relax}} +% Define the default value macro and the key macro. The key macro first +% defines the control sequence formed by the \meta{mp} and \meta{key} +% to expand to the user input and then executes the \meta{function}. +% \begin{macrocode} +\def\XKV@define@cmdkey#1#2[#3]#4{% + \ifXKV@st\XKV@define@default{#2}{#3}\fi + \def\XKV@tempa{\expandafter\def\csname\XKV@header#2\endcsname####1}% + \begingroup\expandafter\endgroup\expandafter\XKV@tempa\expandafter + {\expandafter\def\csname#1#2\endcsname{##1}#4}% +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\define@cmdkeys} +% \oarg{prefix}\marg{family}\oarg{mp}\marg{keys}\\ +% Define multiple command keys. +% \begin{macrocode} +\def\define@cmdkeys{\XKV@testoptd\XKV@define@cmdkeys{cmd}} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\XKV@define@cmdkeys} +% \marg{mp}\marg{keys}\oarg{default}\\ +% Loop over \meta{keys} and define a command key for every entry. +% \begin{macrocode} +\def\XKV@define@cmdkeys#1#2[#3]{% + \XKV@sp@deflist\XKV@tempa{#2}% + \XKV@for@o\XKV@tempa\XKV@tempa{% + \edef\XKV@tempa{\noexpand\XKV@define@cmdkey{#1}{\XKV@tempa}}% + \XKV@tempa[#3]{}% + }% +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\define@choicekey} +% |*+|\oarg{prefix}\marg{family}\\ +% Choice keys. First check optional star, plus and prefix and store the +% family. +% \begin{macrocode} +\def\define@choicekey{\XKV@testopta{\XKV@testoptb\XKV@define@choicekey}} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\XKV@define@choicekey} +% \marg{key}\\ +% Check for optional storage bins for the input and the number of +% the input in the list of allowed inputs. +% \begin{macrocode} +\def\XKV@define@choicekey#1{\@testopt{\XKV@d@fine@choicekey{#1}}{}} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\XKV@d@fine@choicekey} +% \marg{key}\oarg{bin}\marg{allowed}\\ +% Store the storage bin and the list of allowed inputs for later use. +% After that, check for an optional default value. +% \begin{macrocode} +\def\XKV@d@fine@choicekey#1[#2]#3{% + \toks@{#2}% + \XKV@sp@deflist\XKV@tempa{#3}\XKV@toks\expandafter{\XKV@tempa}% + \@ifnextchar[{\XKV@d@fine@ch@icekey{#1}}{\XKV@d@fine@ch@ic@key{#1}}% +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\XKV@d@fine@ch@icekey} +% \marg{key}\oarg{default}\\ +% Define the default value macro if a default value was specified. +% \begin{macrocode} +\def\XKV@d@fine@ch@icekey#1[#2]{% + \XKV@define@default{#1}{#2}% + \XKV@d@fine@ch@ic@key{#1}% +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\XKV@d@fine@ch@ic@key} +% \marg{key}\\ +% Eat correct number of arguments. +% \begin{macrocode} +\def\XKV@d@fine@ch@ic@key#1{% + \ifXKV@pl\XKV@afterelsefi + \expandafter\XKV@d@f@ne@ch@ic@k@y + \else\XKV@afterfi + \expandafter\XKV@d@f@ne@ch@ic@key + \fi + \csname\XKV@header#1\endcsname +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\XKV@d@f@ne@ch@ic@key} +% \meta{key macro}\marg{function}\\ +% Eat one argument and pass it on to the macro that will define the key macro. +% \begin{macrocode} +\def\XKV@d@f@ne@ch@ic@key#1#2{\XKV@d@f@n@@ch@ic@k@y#1{{#2}}} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\XKV@d@f@ne@ch@ic@k@y} +% \meta{key macro}\marg{function1}\marg{function2}\\ +% Eat two arguments and pass these on to the macro that will define the key macro. +% \meta{fucntion1} will be executed on correct input, \meta{function2} +% on incorrect input. +% \begin{macrocode} +\def\XKV@d@f@ne@ch@ic@k@y#1#2#3{\XKV@d@f@n@@ch@ic@k@y#1{{#2}{#3}}} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\XKV@d@f@n@@ch@ic@k@y} +% \meta{key macro}\marg{function}\\ +% Create the key macros. |\XKV@checkchoice| will be used to check the choice +% and execute one of its mandatory arguments. +% \begin{macrocode} +\def\XKV@d@f@n@@ch@ic@k@y#1#2{% + \edef#1##1{% + \ifXKV@st\noexpand\XKV@sttrue\else\noexpand\XKV@stfalse\fi + \ifXKV@pl\noexpand\XKV@pltrue\else\noexpand\XKV@plfalse\fi + \noexpand\XKV@checkchoice[\the\toks@]{##1}{\the\XKV@toks}% + }% + \def\XKV@tempa{\def#1####1}% + \expandafter\XKV@tempa\expandafter{#1{##1}#2}% +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\define@boolkey} +% |+|\oarg{prefix}\marg{family}\oarg{mp}\marg{key}\\ +% Define a boolean key. This macro checks for an optional |+|, an +% optional \meta{prefix}, the mandatory \meta{family}, an optional +% \meta{mp} (`macro prefix') and the mandatory \meta{key} name. +% \begin{macrocode} +\def\define@boolkey{\XKV@t@stopta{\XKV@testoptd\XKV@define@boolkey{}}} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\XKV@define@boolkey} +% \marg{mp}\marg{key}\oarg{default}\\ +% Decide to eat 1 or 2 mandatory arguments for the key macro. Further, +% construct the control sequence for the key macro and the one for the +% if. +% \begin{macrocode} +\def\XKV@define@boolkey#1#2[#3]{% + \ifXKV@pl\XKV@afterelsefi + \expandafter\XKV@d@f@ne@boolkey + \else\XKV@afterfi + \expandafter\XKV@d@fine@boolkey + \fi + \csname\XKV@header#2\endcsname{#2}{#1#2}{#3}% +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\XKV@d@fine@boolkey} +% \changes{v2.5 }{2005/05/07}{Removed \cs{relax}} +% \meta{key macro}\marg{key}\marg{if name}\marg{default}\marg{function}\\ +% Eat one mandatory key function and pass it. Insert `setting the if'. +% \begin{macrocode} +\def\XKV@d@fine@boolkey#1#2#3#4#5{% + \XKV@d@f@ne@b@olkey#1{#2}{#3}{#4}% + {{\csname#3\XKV@resa\endcsname#5}}% +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\XKV@d@f@ne@boolkey} +% \changes{v2.5 }{2005/05/07}{Removed \cs{relax}} +% \meta{key macro}\marg{key}\marg{if name}\marg{default}\marg{func1}\marg{func2}\\ +% Eat two mandatory key functions and pass them. Insert `setting the if'. +% \begin{macrocode} +\def\XKV@d@f@ne@boolkey#1#2#3#4#5#6{% + \XKV@d@f@ne@b@olkey#1{#2}{#3}{#4}% + {{\csname#3\XKV@resa\endcsname#5}{#6}}% +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\XKV@d@f@ne@b@olkey} +% \meta{key macro}\marg{key}\marg{if name}\marg{default}\marg{function}\\ +% Create the if, the default value macro (if a default value was present) +% and the key macro. We use |\XKV@checkchoice| internally to check the +% input and |\XKV@resa| to store the user input and pass it to setting +% the conditional. +% \begin{macrocode} +\def\XKV@d@f@ne@b@olkey#1#2#3#4#5{% + \expandafter\newif\csname if#3\endcsname + \ifXKV@st\XKV@define@default{#2}{#4}\fi + \ifXKV@pl + \def#1##1{\XKV@pltrue\XKV@sttrue + \XKV@checkchoice[\XKV@resa]{##1}{true,false}#5% + }% + \else + \def#1##1{\XKV@plfalse\XKV@sttrue + \XKV@checkchoice[\XKV@resa]{##1}{true,false}#5% + }% + \fi +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\define@boolkeys} +% \oarg{prefix}\marg{family}\oarg{mp}\marg{keys}\\ +% Define multiple boolean keys without user specified key function. +% The key will, of course, still set the if with user input. +% \begin{macrocode} +\def\define@boolkeys{\XKV@plfalse\XKV@testoptd\XKV@define@boolkeys{}} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\XKV@define@boolkeys} +% \marg{mp}\marg{keys}\oarg{default}\\ +% Loop over the list of \meta{keys} and create a boolean key for +% every entry. +% \begin{macrocode} +\def\XKV@define@boolkeys#1#2[#3]{% + \XKV@sp@deflist\XKV@tempa{#2}% + \XKV@for@o\XKV@tempa\XKV@tempa{% + \expandafter\XKV@d@fine@boolkeys\expandafter{\XKV@tempa}{#1}{#3}% + }% +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\XKV@d@fine@boolkeys} +% \marg{key}\marg{mp}\marg{default}\\ +% Use |\XKV@d@f@ne@b@olkey| internally to define the if, the default +% value macro (if present) and the key macro. +% \begin{macrocode} +\def\XKV@d@fine@boolkeys#1#2#3{% + \expandafter\XKV@d@f@ne@b@olkey\csname\XKV@header#1\endcsname + {#1}{#2#1}{#3}{{\csname#2#1\XKV@resa\endcsname}}% +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\XKV@cc} +% This macro is used inside key macros to perform input checks. This +% is the user interface to |\XKV@checkchoice| and we only use the +% latter internally to avoid slow parsings of optional |*| and |+|. +% \begin{macrocode} +\def\XKV@cc{\XKV@testopta{\@testopt\XKV@checkchoice{}}} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\XKV@checkchoice} +% \oarg{bin}\marg{input}\marg{allowed}\\ +% Checks whether \meta{bin} contains at least one control sequence and +% converts \meta{input} and \meta{allowed} to lowercase if requested. +% If \meta{bin} is empty, perform the fast |\in@| check immediately. +% Else, determine whether the bin contains one or two tokens. For the +% first alternative, we can still use the fast |\in@| check. Notice +% that this macro uses settings for |\ifXKV@st| and |\ifXKV@pl|. +% \begin{macrocode} +\def\XKV@checkchoice[#1]#2#3{% + \def\XKV@tempa{#1}% + \ifXKV@st\lowercase{\fi + \ifx\XKV@tempa\@empty + \def\XKV@tempa{\XKV@ch@ckch@ice\@nil{#2}{#3}}% + \else + \def\XKV@tempa{\XKV@ch@ckchoice#1\@nil{#2}{#3}}% + \fi + \ifXKV@st}\fi\XKV@tempa +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\XKV@ch@ckchoice} +% \meta{bin1}\meta{bin2}|\@nil|\marg{input}\marg{allowed}\\ +% Check whether \meta{bin2} is empty. In that case, only the \meta{input} should +% be saved and we can continue with the fast |\in@| check. If not, also +% the number of the input in the \meta{allowed} list should be saved +% and we need to do a slower while type of loop. +% \begin{macrocode} +\def\XKV@ch@ckchoice#1#2\@nil#3#4{% + \def\XKV@tempa{#2}% + \ifx\XKV@tempa\@empty\XKV@afterelsefi + \XKV@ch@ckch@ice#1{#3}{#4}% + \else\XKV@afterfi + \XKV@@ch@ckchoice#1#2{#3}{#4}% + \fi +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\XKV@ch@ckch@ice} +% \meta{bin}\marg{input}\marg{allowed}\\ +% Checks whether \meta{input} is in the list \meta{allowed} and perform +% actions accordingly. +% \begin{macrocode} +\def\XKV@ch@ckch@ice#1#2#3{% + \def\XKV@tempa{#1}% +% \end{macrocode} +% If we have a \meta{bin}, store the input there. +% \begin{macrocode} + \ifx\XKV@tempa\@nnil\let\XKV@tempa\@empty\else + \def\XKV@tempa{\def#1{#2}}% + \fi + \in@{,#2,}{,#3,}% + \ifin@ +% \end{macrocode} +% The \meta{input} is allowed. +% \begin{macrocode} + \ifXKV@pl +% \end{macrocode} +% If we have a |+|, there are two functions. Execute the first. +% \begin{macrocode} + \XKV@addtomacro@n\XKV@tempa\@firstoftwo + \else +% \end{macrocode} +% Else, we have one function; execute it. +% \begin{macrocode} + \XKV@addtomacro@n\XKV@tempa\@firstofone + \fi + \else +% \end{macrocode} +% If we have a |+|, there are two functions. Execute the second. +% \begin{macrocode} + \ifXKV@pl + \XKV@addtomacro@n\XKV@tempa\@secondoftwo + \else +% \end{macrocode} +% Else, raise an error and gobble the one function. +% \begin{macrocode} + \XKV@toks{#2}% + \XKV@err{value `\the\XKV@toks' is not allowed}% + \XKV@addtomacro@n\XKV@tempa\@gobble + \fi + \fi + \XKV@tempa +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\XKV@@ch@ckchoice} +% \meta{bin1}\meta{bin2}\marg{input}\marg{allowed}\\ +% Walk over the \meta{allowed} list and compare each entry with the +% \meta{input}. The input is saved in \meta{bin1}, the number of the +% \meta{input} in the \meta{allowed} list (starting at zero) is saved +% in \meta{bin2}. If the \meta{input} is not allowed, \meta{bin2} will +% be defined to contain |-1|. +% \begin{macrocode} +\def\XKV@@ch@ckchoice#1#2#3#4{% +% \end{macrocode} +% Save the current value of the counter as to avoid disturbing it. +% We don't use a group as that takes a lot of memory and requires some +% more tokens (for global definitions). +% \begin{macrocode} + \edef\XKV@tempa{\the\count@}\count@\z@ +% \end{macrocode} +% The input. +% \begin{macrocode} + \def\XKV@tempb{#3}% +% \end{macrocode} +% Define the while loop. +% \begin{macrocode} + \def\XKV@tempc##1,{% + \def#1{##1}% + \ifx#1\@nnil +% \end{macrocode} +% The \meta{input} was not in \meta{allowed}. Set the number to |-1|. +% \begin{macrocode} + \def#1{#3}\def#2{-1}\count@\XKV@tempa + \ifXKV@pl +% \end{macrocode} +% Execute the macro for the case that input was not allowed. +% \begin{macrocode} + \let\XKV@tempd\@secondoftwo + \else +% \end{macrocode} +% If that function does not exist, raise a generic error and gobble +% the function to be executed on good input. +% \begin{macrocode} + \XKV@toks{#3}% + \XKV@err{value `\the\XKV@toks' is not allowed}% + \let\XKV@tempd\@gobble + \fi + \else + \ifx#1\XKV@tempb +% \end{macrocode} +% We found \meta{input} in \meta{allowed}. +% Save the number of the \meta{input} in the list \meta{allowed}. +% \begin{macrocode} + \edef#2{\the\count@}\count@\XKV@tempa + \ifXKV@pl + \let\XKV@tempd\XKV@@ch@ckch@ice + \else + \let\XKV@tempd\XKV@@ch@ckch@ic@ + \fi + \else +% \end{macrocode} +% Increase counter and check next item in the list \meta{allowed}. +% \begin{macrocode} + \advance\count@\@ne + \let\XKV@tempd\XKV@tempc + \fi + \fi + \XKV@tempd + }% +% \end{macrocode} +% Start the while loop. +% \begin{macrocode} + \XKV@tempc#4,\@nil,% +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\XKV@@ch@ckch@ice} +% \begin{macro}{\XKV@@ch@ckch@ic@} +% \meta{text}|\@nil,|\\ +% Gobble remaining \meta{text} and execute the proper key function. +% \begin{macrocode} +\def\XKV@@ch@ckch@ice#1\@nil,{\@firstoftwo} +\def\XKV@@ch@ckch@ic@#1\@nil,{\@firstofone} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \begin{macro}{\key@ifundefined} +% This macro allows checking if a key is defined in a family from +% a list of families. Check for an optional prefix. +% \begin{macrocode} +\def\key@ifundefined{\@testopt\XKV@key@ifundefined{KV}} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\XKV@key@ifundefined} +% \oarg{prefix}\marg{fams}\\ +% This macro is split in two parts so that |\XKV@p@x| can use only +% the main part of the macro. First we save the prefix and the list +% of families. +% \begin{macrocode} +\def\XKV@key@ifundefined[#1]#2{% + \XKV@makepf{#1}% + \XKV@checksanitizeb{#2}\XKV@fams + \expandafter\XKV@sp@deflist\expandafter + \XKV@fams\expandafter{\XKV@fams}% + \XKV@key@if@ndefined +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\XKV@key@if@ndefined} +% \marg{key}\\ +% Loop over the list of families until we find the key in a family. +% \begin{macrocode} +\def\XKV@key@if@ndefined#1{% + \XKV@knftrue + \KV@@sp@def\XKV@tkey{#1}% +% \end{macrocode} +% Loop over possible families. +% \begin{macrocode} + \XKV@whilist\XKV@fams\XKV@tfam\ifXKV@knf\fi{% +% \end{macrocode} +% Set the header. +% \begin{macrocode} + \XKV@makehd\XKV@tfam +% \end{macrocode} +% Check whether the macro for the key is defined. +% \begin{macrocode} + \XKV@ifundefined{\XKV@header\XKV@tkey}{}{\XKV@knffalse}% + }% +% \end{macrocode} +% Execute one of the final two arguments depending on state of |\XKV@knf|. +% \begin{macrocode} + \ifXKV@knf + \expandafter\@firstoftwo + \else + \expandafter\@secondoftwo + \fi +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\disable@keys} +% \oarg{prefix}\marg{family}\\ +% Macro that make a key produce a warning on use. +% \begin{macrocode} +\def\disable@keys{\XKV@testoptb\XKV@disable@keys} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\XKV@disable@keys} +% \marg{keys}\\ +% Workhorse for |\disable@keys| which redefines a list of key macro +% to produce a warning. +% \begin{macrocode} +\def\XKV@disable@keys#1{% + \XKV@checksanitizeb{#1}\XKV@tempa + \XKV@for@o\XKV@tempa\XKV@tempa{% + \XKV@ifundefined{\XKV@header\XKV@tempa}{% + \XKV@err{key `\XKV@tempa' undefined}% + }{% + \edef\XKV@tempb{% + \noexpand\XKV@warn{key `\XKV@tempa' has been disabled}% + }% + \XKV@ifundefined{\XKV@header\XKV@tempa @default}{% + \edef\XKV@tempc{\noexpand\XKV@define@key{\XKV@tempa}}% + }{% + \edef\XKV@tempc{\noexpand\XKV@define@key{\XKV@tempa}[]}% + }% + \expandafter\XKV@tempc\expandafter{\XKV@tempb}% + }% + }% +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\presetkeys} +% \begin{macro}{\gpresetkeys} +% \changes{v1.7}{2004/11/25}{Made incremental} +% \oarg{prefix}\marg{family}\\ +% This provides the presetting system. The macro works incrementally: +% keys that have been preset before will overwrite the old preset +% values, new ones will be added to the end of the preset list. +% \begin{macrocode} +\def\presetkeys{\XKV@stfalse\XKV@testoptb\XKV@presetkeys} +\def\gpresetkeys{\XKV@sttrue\XKV@testoptb\XKV@presetkeys} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \begin{macro}{\XKV@presetkeys} +% \marg{head presets}\marg{tail presets}\\ +% Execute the merging macro |\XKV@pr@setkeys| for both head and tail +% presets. +% \begin{macrocode} +\def\XKV@presetkeys#1#2{% + \XKV@pr@setkeys{#1}{preseth}% + \XKV@pr@setkeys{#2}{presett}% +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\XKV@pr@setkeys} +% \marg{presets}\marg{postfix}\\ +% Check whether presets have already been defined. If not, define them +% and do not start the merging macro. Otherwise, create the control +% sequence that stores these presets and start merging. +% \begin{macrocode} +\def\XKV@pr@setkeys#1#2{% + \XKV@ifundefined{XKV@\XKV@header#2}{% + \XKV@checksanitizea{#1}\XKV@tempa + \ifXKV@st\expandafter\global\fi\expandafter\def\csname + XKV@\XKV@header#2\expandafter\endcsname\expandafter{\XKV@tempa}% + }{% + \expandafter\XKV@merge\csname XKV@\XKV@header + #2\endcsname{#1}\XKV@getkeyname + }% +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\delpresetkeys} +% \begin{macro}{\gdelpresetkeys} +% \oarg{prefix}\marg{family}\\ +% Macros to remove entries from presets. +% \begin{macrocode} +\def\delpresetkeys{\XKV@stfalse\XKV@testoptb\XKV@delpresetkeys} +\def\gdelpresetkeys{\XKV@sttrue\XKV@testoptb\XKV@delpresetkeys} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \begin{macro}{\XKV@delpresetkeys} +% \marg{head key list}\marg{tail key list}\\ +% Run the main macro for both head and tail presets. +% \begin{macrocode} +\def\XKV@delpresetkeys#1#2{% + \XKV@d@lpresetkeys{#1}{preseth}% + \XKV@d@lpresetkeys{#2}{presett}% +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\XKV@d@lpresetkeys} +% \marg{key list}\marg{postfix}\\ +% Check whether presets have been saved and if so, start deletion +% algorithm. Supply the macro |\XKV@getkeyname| to retrieve key names +% from entries. +% \begin{macrocode} +\def\XKV@d@lpresetkeys#1#2{% + \XKV@ifundefined{XKV@\XKV@header#2}{% + \XKV@err{no presets defined for `\XKV@header'}% + }{% + \expandafter\XKV@delete\csname XKV@\XKV@header + #2\endcsname{#1}\XKV@getkeyname + }% +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\unpresetkeys} +% \begin{macro}{\gunpresetkeys} +% \oarg{prefix}\marg{family}\\ +% Removes presets for a particular family. +% \begin{macrocode} +\def\unpresetkeys{\XKV@stfalse\XKV@testoptb\XKV@unpresetkeys} +\def\gunpresetkeys{\XKV@sttrue\XKV@testoptb\XKV@unpresetkeys} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \begin{macro}{\XKV@unpresetkeys} +% Undefine the preset macros. We make them undefined since this will +% make them appear undefined to both versions of the macro |\XKV@ifundefined|. +% Making the macros |\relax| would work in the case that no \eTeX\ is +% available (hence using |\ifx\csname|), but doesn't work when \eTeX\ +% is used (and using |\ifcsname|). +% \begin{macrocode} +\def\XKV@unpresetkeys{% + \XKV@ifundefined{XKV@\XKV@header preseth}{% + \XKV@err{no presets defined for `\XKV@header'}% + }{% + \ifXKV@st\expandafter\global\fi\expandafter\let + \csname XKV@\XKV@header preseth\endcsname\@undefined + \ifXKV@st\expandafter\global\fi\expandafter\let + \csname XKV@\XKV@header presett\endcsname\@undefined + }% +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\savekeys} +% \begin{macro}{\gsavekeys} +% \oarg{prefix}\marg{family}\\ +% Store a list of keys of a family that should always be saved. The +% macro works incrementally and avoids duplicate entries in the list. +% \begin{macrocode} +\def\savekeys{\XKV@stfalse\XKV@testoptb\XKV@savekeys} +\def\gsavekeys{\XKV@sttrue\XKV@testoptb\XKV@savekeys} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \begin{macro}{\XKV@savekeys} +% \marg{key list}\\ +% Check whether something has been saved before. If not, start merging. +% \begin{macrocode} +\def\XKV@savekeys#1{% + \XKV@ifundefined{XKV@\XKV@header save}{% + \XKV@checksanitizeb{#1}\XKV@tempa + \ifXKV@st\expandafter\global\fi\expandafter\def\csname XKV@% + \XKV@header save\expandafter\endcsname\expandafter{\XKV@tempa}% + }{% + \expandafter\XKV@merge\csname XKV@\XKV@header + save\endcsname{#1}\XKV@getsg + }% +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\delsavekeys} +% \begin{macro}{\gdelsavekeys} +% \oarg{prefix}\marg{family}\\ +% Remove entries from the list of save keys. +% \begin{macrocode} +\def\delsavekeys{\XKV@stfalse\XKV@testoptb\XKV@delsavekeys} +\def\gdelsavekeys{\XKV@sttrue\XKV@testoptb\XKV@delsavekeys} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \begin{macro}{\XKV@delsavekeys} +% \marg{key list}\\ +% Check whether save keys are defined and if yes, start deletion +% algorithm. Use the macro |\XKV@getsg| to retrieve key names from +% entries. +% \begin{macrocode} +\def\XKV@delsavekeys#1{% + \XKV@ifundefined{XKV@\XKV@header save}{% + \XKV@err{no save keys defined for `\XKV@header'}% + }{% + \expandafter\XKV@delete\csname XKV@\XKV@header + save\endcsname{#1}\XKV@getsg + }% +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\unsavekeys} +% \begin{macro}{\gunsavekeys} +% \oarg{prefix}\marg{family}\\ +% Similar to |\unpresetkeys|, but removes the `save keys list' for a +% particular family. +% \begin{macrocode} +\def\unsavekeys{\XKV@stfalse\XKV@testoptb\XKV@unsavekeys} +\def\gunsavekeys{\XKV@sttrue\XKV@testoptb\XKV@unsavekeys} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \begin{macro}{\XKV@unsavekeys} +% Workhorse for |\unsavekeys|. +% \begin{macrocode} +\def\XKV@unsavekeys{% + \XKV@ifundefined{XKV@\XKV@header save}{% + \XKV@err{no save keys defined for `\XKV@header'}% + }{% + \ifXKV@st\expandafter\global\fi\expandafter\let + \csname XKV@\XKV@header save\endcsname\@undefined + }% +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\setkeys} +% |*+|\oarg{prefix}\marg{families}\\ +% Set keys. The starred version does not produce errors, but appends +% keys that cannot be located to the list in |\XKV@rm|. The plus +% version sets keys in all families that are supplied. +% \begin{macrocode} +\def\setkeys{\XKV@testopta{\XKV@testoptc\XKV@setkeys}} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\XKV@setkeys} +% \oarg{na}\marg{key=value list}\\ +% \changes{v1.8a}{2004/12/20}{Solved small bug} +% Workhorse for |\setkeys|. +% \begin{macrocode} +\def\XKV@setkeys[#1]#2{% + \XKV@checksanitizea{#2}\XKV@resb + \let\XKV@naa\@empty +% \end{macrocode} +% Retrieve a list of key names from the user input. +% \begin{macrocode} + \XKV@for@o\XKV@resb\XKV@tempa{% + \expandafter\XKV@g@tkeyname\XKV@tempa=\@nil\XKV@tempa + \XKV@addtolist@x\XKV@naa\XKV@tempa + }% +% \end{macrocode} +% Initialize the remaining keys. +% \begin{macrocode} + \let\XKV@rm\@empty +% \end{macrocode} +% Now scan the list of families for preset keys and set user input keys. +% \begin{macrocode} + \XKV@usepresetkeys{#1}{preseth}% + \expandafter\XKV@s@tkeys\expandafter{\XKV@resb}{#1}% + \XKV@usepresetkeys{#1}{presett}% +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\XKV@usepresetkeys} +% \marg{na}\marg{postfix}\\ +% Loop over the list of families and check them for preset keys. If +% present, set them right away, taking into account the keys which +% are set by the user, available in the |\XKV@naa| list. +% \begin{macrocode} +\def\XKV@usepresetkeys#1#2{% + \XKV@presettrue + \XKV@for@eo\XKV@fams\XKV@tfam{% + \XKV@makehd\XKV@tfam + \XKV@ifundefined{XKV@\XKV@header#2}{}{% + \XKV@toks\expandafter\expandafter\expandafter + {\csname XKV@\XKV@header#2\endcsname}% + \@expandtwoargs\XKV@s@tkeys{\the\XKV@toks}% + {\XKV@naa\ifx\XKV@naa\@empty\else,\fi#1}% + }% + }% + \XKV@presetfalse +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\XKV@s@tkeys} +% \marg{key=value list}\marg{na}\\ +% This macro starts the loop over the |key=value| list. Do not set +% keys in the list \meta{na}. +% \begin{macrocode} +\def\XKV@s@tkeys#1#2{% +% \end{macrocode} +% Define the list of key names which should be ignored. +% \begin{macrocode} + \XKV@sp@deflist\XKV@na{#2}% +% \end{macrocode} +% Loop over the key=value list. +% \begin{macrocode} + \XKV@for@n{#1}\CurrentOption{% +% \end{macrocode} +% Split key and value. +% \begin{macrocode} + \expandafter\XKV@s@tk@ys\CurrentOption==\@nil + }% +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\XKV@s@tk@ys} +% \changes{v1.4}{2004/08/24}{Made macro more efficient} +% \changes{v2.4}{2005/03/31}{Added \cs{global} to make \cs{XKV@rm} +% survive when \cs{setkeys} executed in a group.} +% \meta{key}|=|\meta{value}|=#3\@nil|\\ +% Split key name and value (if present). If |#3| non-empty, there was +% no |=|\meta{value}. +% \begin{macrocode} +\def\XKV@s@tk@ys#1=#2=#3\@nil{% +% \end{macrocode} +% Check for |\savevalue| and |\gsavevalue| and remove spaces from around the key name. +% \begin{macrocode} + \XKV@g@tkeyname#1=\@nil\XKV@tkey + \expandafter\KV@@sp@def\expandafter\XKV@tkey\expandafter{\XKV@tkey}% +% \end{macrocode} +% If the key is empty and a value has been specified, generate an error. +% \begin{macrocode} + \ifx\XKV@tkey\@empty + \XKV@toks{#2}% + \ifcat$\the\XKV@toks$\else + \XKV@err{no key specified for value `\the\XKV@toks'}% + \fi + \else +% \end{macrocode} +% If in the |\XKV@na| list, ignore the key. +% \begin{macrocode} + \@expandtwoargs\in@{,\XKV@tkey,}{,\XKV@na,}% + \ifin@\else + \XKV@knftrue + \KV@@sp@def\XKV@tempa{#2}% + \ifXKV@preset\XKV@s@tk@ys@{#3}\else + \ifXKV@pl +% \end{macrocode} +% If a command with a |+| is used, set keys in all families on the +% list. +% \begin{macrocode} + \XKV@for@eo\XKV@fams\XKV@tfam{% + \XKV@makehd\XKV@tfam + \XKV@s@tk@ys@{#3}% + }% + \else +% \end{macrocode} +% Else, scan the families on the list but stop when the key is found +% or when the list has run out. +% \begin{macrocode} + \XKV@whilist\XKV@fams\XKV@tfam\ifXKV@knf\fi{% + \XKV@makehd\XKV@tfam + \XKV@s@tk@ys@{#3}% + }% + \fi + \fi + \ifXKV@knf + \ifXKV@inpox +% \end{macrocode} +% We are in the options section. Try to use the macro defined by +% |\DeclareOptionX*|. +% \begin{macrocode} + \ifx\XKV@doxs\relax +% \end{macrocode} +% For classes, ignore unknown (possibly global) options. For packages, +% raise the standard \LaTeX\ error. +% \begin{macrocode} + \ifx\@currext\@clsextension\else + \let\CurrentOption\XKV@tkey\@unknownoptionerror + \fi +% \end{macrocode} +% Pass the option through |\DeclareOptionX*|. +% \begin{macrocode} + \else\XKV@doxs\fi + \else +% \end{macrocode} +% If not in the options section, raise an error or add the key to the +% list in |\XKV@rm| when |\setkeys*| has been used. +% \begin{macrocode} + \ifXKV@st + \global\XKV@addtolist@o\XKV@rm\CurrentOption + \else + \XKV@err{`\XKV@tkey' undefined in families `\XKV@fams'}% + \fi + \fi + \else +% \end{macrocode} +% Remove global options set by the document class from |\@unusedoptionlist|. +% Global options set by other packages or classes will be removed by +% |\ProcessOptionsX*|. +% \begin{macrocode} + \ifXKV@inpox\ifx\XKV@testclass\XKV@documentclass + \expandafter\XKV@useoption\expandafter{\CurrentOption}% + \fi\fi + \fi + \fi + \fi +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\XKV@s@tk@ys@} +% \marg{ind}\\ +% This macro coordinates the work of setting a key. \meta{ind} is an +% indicator for the presence of a user submitted value for the key. If +% empty, no value was present. +% \begin{macrocode} +\def\XKV@s@tk@ys@#1{% +% \end{macrocode} +% Check whether the key macro exists. +% \begin{macrocode} + \XKV@ifundefined{\XKV@header\XKV@tkey}{}{% + \XKV@knffalse +% \end{macrocode} +% Check global setting by |\savekeys| to know whether or not to save +% the value of the key at hand. +% \begin{macrocode} + \XKV@ifundefined{XKV@\XKV@header save}{}{% + \expandafter\XKV@testsavekey\csname XKV@\XKV@header + save\endcsname\XKV@tkey + }% +% \end{macrocode} +% Save the value of a key. +% \begin{macrocode} + \ifXKV@rkv + \ifXKV@sg\expandafter\global\fi\expandafter\let + \csname XKV@\XKV@header\XKV@tkey @value\endcsname\XKV@tempa + \fi +% \end{macrocode} +% Replace pointers by saved values. +% \begin{macrocode} + \expandafter\XKV@replacepointers\expandafter{\XKV@tempa}% +% \end{macrocode} +% If no value was present, use the default value macro, if one exists. +% Otherwise, issue an error. +% \begin{macrocode} + \ifx\@empty#1\@empty\XKV@afterelsefi + \XKV@ifundefined{\XKV@header\XKV@tkey @default}{% + \XKV@err{no value specified for key `\XKV@tkey'}% + }{% + \expandafter\expandafter\expandafter\XKV@default + \csname\XKV@header\XKV@tkey @default\endcsname\@nil + }% + \else\XKV@afterfi +% \end{macrocode} +% Save state in case the key executes |\setkeys| or |\XKV@cc|. +% \begin{macrocode} + \XKV@srstate{@\romannumeral\XKV@depth}{}% +% \end{macrocode} +% Execute the key. +% \begin{macrocode} + \csname\XKV@header\XKV@tkey\expandafter + \endcsname\expandafter{\XKV@tempa}\relax +% \end{macrocode} +% Restore the current state. +% \begin{macrocode} + \XKV@srstate{}{@\romannumeral\XKV@depth}% + \fi + }% +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\XKV@testsavekey} +% \meta{save key list}\meta{key name}\\ +% This macro checks whether the key in macro \meta{key name} appears in the +% save list in macro \meta{save key list}. Furthermore, it checks whether or not to +% save the key globally. In other words, that |\global{key}| is in +% the list. +% \begin{macrocode} +\def\XKV@testsavekey#1#2{% + \ifXKV@rkv\else + \XKV@for@o#1\XKV@resa{% + \expandafter\XKV@ifcmd\expandafter{\XKV@resa}\global\XKV@resa{% + \ifx#2\XKV@resa + \XKV@rkvtrue\XKV@sgtrue + \fi + }{% + \ifx#2\XKV@resa + \XKV@rkvtrue\XKV@sgfalse + \fi + }% + }% + \fi +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\XKV@replacepointers} +% \begin{macro}{\XKV@r@placepointers} +% \changes{v1.8d}{2005/01/02}{Added \cs{XKV@afterfi} to avoid capacity +% problems when too many pointers present} +% \changes{v1.9}{2005/01/16}{Added back linking test} +% \changes{v2.0}{2005/01/30}{Simplified} +% \marg{key=value list}\\ +% Replaces all pointers by their saved values. The result is stored in +% |\XKV@tempa|. We feed the replacement and the following tokens again to the +% macro to replace nested pointers. It stops when no pointers are +% found anymore. We keep a list of pointers replaced already for this +% key in |\XKV@resa| so we can check whether we are running in circles. +% \begin{macrocode} +\def\XKV@replacepointers#1{% + \let\XKV@tempa\@empty + \let\XKV@resa\@empty + \XKV@r@placepointers#1\usevalue\@nil +} +\def\XKV@r@placepointers#1\usevalue#2{% + \XKV@addtomacro@n\XKV@tempa{#1}% + \def\XKV@tempb{#2}% + \ifx\XKV@tempb\@nnil\else\XKV@afterfi + \XKV@ifundefined{XKV@\XKV@header#2@value}{% + \XKV@err{no value recorded for key `#2'; ignored}% + \XKV@r@placepointers + }{% + \@expandtwoargs\in@{,#2,}{,\XKV@resa,}% + \ifin@\XKV@afterelsefi + \XKV@err{back linking pointers; pointer replacement canceled}% + \else\XKV@afterfi + \XKV@addtolist@x\XKV@resa{#2}% + \expandafter\expandafter\expandafter\XKV@r@placepointers + \csname XKV@\XKV@header#2@value\endcsname + \fi + }% + \fi +} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \begin{macro}{\XKV@default} +% \changes{v2.0}{2005/01/30}{Repaired adding extra braces when executing default value} +% \meta{token}\meta{tokens}\\ +% This macro checks the |\prefix@fam@key@default| macro. If the macro +% has the form as defined by \pf{keyval} or \pf{xkeyval}, it is +% possible to extract the default value and safe that (if requested) +% and replace pointers. If the form is incorrect, just execute the +% macro and forget about possible pointers. The reason for this check +% is that certain packages (like \pf{fancyvrb}) abuse the `default +% value system' to execute code instead of setting keys by redefining +% default value macros. These macros do not actually contain a +% default value and trying to extract that would not work. +% \begin{macrocode} +\def\XKV@default#1#2\@nil{% +% \end{macrocode} +% Retrieve the first token in the macro. +% \begin{macrocode} + \expandafter\edef\expandafter\XKV@tempa + \expandafter{\expandafter\@gobble\string#1}% +% \end{macrocode} +% Construct the name that we expect on the basis of the \pf{keyval} +% and \pf{xkeyval} syntax of default values. +% \begin{macrocode} + \edef\XKV@tempb{\XKV@header\XKV@tkey}% +% \end{macrocode} +% Sanitize |\XKV@tempb| to reset catcodes for comparison with |\XKV@tempa|. +% \begin{macrocode} + \@onelevel@sanitize\XKV@tempb + \ifx\XKV@tempa\XKV@tempb +% \end{macrocode} +% If it is safe, extract the value. We temporarily redefine the key +% macro to save the default value in a macro. Saving the default value +% itself directly to a macro when defining keys would of course be easier, +% but a lot of packages rely on this system created by \pf{keyval}, so +% we have to support it here. +% \begin{macrocode} + \begingroup + \expandafter\def\csname\XKV@header\XKV@tkey\endcsname##1{% + \gdef\XKV@tempa{##1}% + }% + \csname\XKV@header\XKV@tkey @default\endcsname + \endgroup +% \end{macrocode} +% Save the default value to a value macro if either the key name has +% been entered in a |\savekeys| macro or the starred form has been used. +% \begin{macrocode} + \XKV@ifundefined{XKV@\XKV@header save}{}{% + \expandafter\XKV@testsavekey\csname XKV@\XKV@header + save\endcsname\XKV@tkey + }% + \ifXKV@rkv + \ifXKV@sg\expandafter\global\fi\expandafter\let + \csname XKV@\XKV@header\XKV@tkey @value\endcsname\XKV@tempa + \fi +% \end{macrocode} +% Replace the pointers. +% \begin{macrocode} + \expandafter\XKV@replacepointers\expandafter + {\XKV@tempa}\XKV@afterelsefi +% \end{macrocode} +% Save internal state. +% \begin{macrocode} + \XKV@srstate{@\romannumeral\XKV@depth}{}% +% \end{macrocode} +% Execute the key with the (possibly changed) default value. +% \begin{macrocode} + \expandafter#1\expandafter{\XKV@tempa}\relax +% \end{macrocode} +% Restore internal state. +% \begin{macrocode} + \XKV@srstate{}{@\romannumeral\XKV@depth}% + \else\XKV@afterfi +% \end{macrocode} +% Save internal state. +% \begin{macrocode} + \XKV@srstate{@\romannumeral\XKV@depth}{}% +% \end{macrocode} +% Execute the key with the default value. +% \begin{macrocode} + \csname\XKV@header\XKV@tkey @default\endcsname\relax +% \end{macrocode} +% Restore the state. +% \begin{macrocode} + \XKV@srstate{}{@\romannumeral\XKV@depth}% + \fi +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\setrmkeys} +% |*+|\oarg{prefix}\marg{families}\\ +% Set remaining keys stored in |\XKV@rm|. The starred version creates +% a new list in |\XKV@rm| in case there are still keys that cannot +% be located in the families specified. Care is taken again not to +% expand fragile macros. Use |\XKV@testopa| again to handle optional +% arguments. +% \begin{macrocode} +\def\setrmkeys{\XKV@testopta{\XKV@testoptc\XKV@setrmkeys}} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\XKV@setrmkeys} +% \oarg{na}\\ +% Submits the keys in |\XKV@rm| to |\XKV@setkeys|. +% \begin{macrocode} +\def\XKV@setrmkeys[#1]{% + \def\XKV@tempa{\XKV@setkeys[#1]}% + \expandafter\XKV@tempa\expandafter{\XKV@rm}% +} +% \end{macrocode} +% \end{macro} +% Reset catcodes. +% \begin{macrocode} +\XKVcatcodes +%</xkvtex> +% \end{macrocode} +% \subsection{\texttt{xkeyval.sty}} +% \changes{v1.5}{2004/09/27}{Made macros avoid expansions of options} +% Initialize the package. +% \begin{macrocode} +%<*xkvlatex> +\NeedsTeXFormat{LaTeX2e}[1995/12/01] +\ProvidesPackage{xkeyval} + [2005/08/12 v2.5d package option processing (HA)] +% \end{macrocode} +% Initializations. Load |xkeyval.tex|, adjust some catcodes to define +% internal macros and initialize the |\DeclareOptionX*| working macro. +% \begin{macrocode} +\ifx\XKeyValLoaded\endinput\else\input xkeyval \fi +\edef\XKVcatcodes{% + \catcode`\noexpand\=\the\catcode`\=\relax + \catcode`\noexpand\,\the\catcode`\,\relax + \let\noexpand\XKVcatcodes\relax +} +\catcode`\=12\relax +\catcode`\,12\relax +\let\XKV@doxs\relax +% \end{macrocode} +% \begin{macro}{\XKV@warn} +% \begin{macro}{\XKV@err} +% Warning and error macros. +% \begin{macrocode} +\def\XKV@warn#1{\PackageWarning{xkeyval}{#1}} +\def\XKV@err#1{\PackageError{xkeyval}{#1}\@ehc} +% \end{macrocode} +% \end{macro} +% \end{macro} +% Retrieve the document class from |\@filelist|. This is the first +% filename in the list with a class extension. Use a while loop to +% scan the list and stop when we found the first filename which is +% a class. Also stop in case the list is scanned fully. +% \begin{macrocode} +\XKV@whilist\@filelist\XKV@tempa\ifx\XKV@documentclass\@undefined\fi{% + \filename@parse\XKV@tempa + \ifx\filename@ext\@clsextension + \XKV@ifundefined{opt@\filename@area\filename@base.\filename@ext + }{}{% + \edef\XKV@documentclass{% + \filename@area\filename@base.\filename@ext + }% + }% + \fi +} +% \end{macrocode} +% If we didn't find the document class, raise an error, otherwise +% filter global options. +% \begin{macrocode} +\ifx\XKV@documentclass\@undefined + \XKV@err{xkeyval loaded before \protect\documentclass}% + \let\XKV@documentclass\@empty + \let\XKV@classoptionslist\@empty +\else + \let\XKV@classoptionslist\@classoptionslist +% \end{macrocode} +% \changes{v1.4}{2004/08/24}{Fixed small bug in class option filtering} +% Code to filter |key=value| pairs from |\@classoptionslist| without +% expanding options. +% \begin{macrocode} + \def\XKV@tempa#1{% + \let\@classoptionslist\@empty + \XKV@for@n{#1}\XKV@tempa{% + \expandafter\in@\expandafter=\expandafter{\XKV@tempa}% + \ifin@\else\XKV@addtolist@o\@classoptionslist\XKV@tempa\fi + }% + } + \expandafter\XKV@tempa\expandafter{\@classoptionslist} +\fi +% \end{macrocode} +% \begin{macro}{\XKV@testopte} +% \begin{macro}{\XKV@t@stopte} +% \begin{macro}{\XKV@t@st@pte} +% \changes{v1.9}{2005/01/16}{Added extension to default family} +% \begin{macro}{\XKV@@t@st@pte} +% \marg{function}\\ +% Macros for |\ExecuteOptionsX| and |\ProcessOptionsX| for testing for +% optional arguments and inserting default values. Execute \meta{function} +% after preforming the checks. +% \begin{macrocode} +\def\XKV@testopte#1{% + \XKV@ifstar{\XKV@sttrue\XKV@t@stopte#1}{\XKV@stfalse\XKV@t@stopte#1}% +} +\def\XKV@t@stopte#1{\@testopt{\XKV@t@st@pte#1}{KV}} +\def\XKV@t@st@pte#1[#2]{% + \XKV@makepf{#2}% + \@ifnextchar<{\XKV@@t@st@pte#1}% + {\XKV@@t@st@pte#1<\@currname.\@currext>}% +} +\def\XKV@@t@st@pte#1<#2>{% + \XKV@sp@deflist\XKV@fams{#2}% + \@testopt#1{}% +} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% Macros for class and package writers. These are mainly shortcuts to +% |\define@key| and |\setkeys|. The \LaTeX\ macro |\@fileswith@pti@ns| +% is set to generate an error. This is the case when a class or package +% is loaded in between |\DeclareOptionX| and |\ProcessOptionsX| commands. +% \begin{macro}{\DeclareOptionX} +% |*|\\ +% Declare a package or class option. +% \begin{macrocode} +\def\DeclareOptionX{% + \let\@fileswith@pti@ns\@badrequireerror + \XKV@ifstar\XKV@dox\XKV@d@x +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\XKV@dox} +% This macro defines |\XKV@doxs| to be used for unknown options. +% \begin{macrocode} +\long\def\XKV@dox#1{\XKV@toks{#1}\edef\XKV@doxs{\the\XKV@toks}} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\XKV@d@x} +% \begin{macro}{\XKV@@d@x} +% \changes{v1.9}{2005/01/16}{Added extension to default family} +% \begin{macro}{\XKV@@@d@x} +% \changes{v1.1}{2004/04/30}{Redefined to insert an empty default value +% if none is present} +% Insert default prefix and family name (which is the filename of the +% class or package) and add empty default value if none present. Execute +% |\define@key|. +% \begin{macrocode} +\def\XKV@d@x{\@testopt\XKV@@d@x{KV}} +\def\XKV@@d@x[#1]{% + \@ifnextchar<{\XKV@@@d@x[#1]}{\XKV@@@d@x[#1]<\@currname.\@currext>}% +} +\def\XKV@@@d@x[#1]<#2>#3{\@testopt{\define@key[#1]{#2}{#3}}{}} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \begin{macro}{\ExecuteOptionsX} +% \oarg{prefix}\marg{families}\oarg{na}\marg{key=value list}\\ +% This macro sets keys to specified values and uses |\XKV@setkeys| to do +% the job. Insert default prefix and family name if none provided. Use +% |\XKV@t@stopte| to handle optional arguments and reset |\ifXKV@st| +% and |\ifXKV@pl| first to avoid unexpected behavior when |\setkeys*+| +% (or a friend) has been used before |\ExecuteOptionsX|. +% \begin{macrocode} +\def\ExecuteOptionsX{\XKV@stfalse\XKV@plfalse\XKV@t@stopte\XKV@setkeys} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\ProcessOptionsX} +% \changes{v1.4}{2004/08/24}{Fixed macro for \cs{LoadClass} case} +% |*|\oarg{prefix}\marg{families}\\ +% Processes class or package using \pf{xkeyval}. The starred version +% copies class options submitted by the user as well, given that they +% are defined in the local families which are passed to the macro. Use +% |\XKV@testopte| to handle optional arguments. +% \begin{macrocode} +\def\ProcessOptionsX{\XKV@plfalse\XKV@testopte\XKV@pox} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\XKV@pox} +% \oarg{na}\\ +% Workhorse for |\ProcessOptionsX| and |\ProcessOptionsX*|. +% \begin{macrocode} +\def\XKV@pox[#1]{% + \let\XKV@tempa\@empty +% \end{macrocode} +% Set |\XKV@inpox|: indicates that we are in |\ProcessOptionsX| to +% invoke a special routine in |\XKV@s@tkeys|. +% \begin{macrocode} + \XKV@inpoxtrue +% \end{macrocode} +% Set |\@fileswith@pti@ns| again in case no |\DeclareOptionX| has been +% used. This will be used to identify a call to |\setkeys| from +% |\ProcessOptionsX|. +% \begin{macrocode} + \let\@fileswith@pti@ns\@badrequireerror + \edef\XKV@testclass{\@currname.\@currext}% +% \end{macrocode} +% If \pf{xkeyval} is loaded by the document class, initialize +% |\@unusedoptionlist|. +% \begin{macrocode} + \ifx\XKV@testclass\XKV@documentclass + \let\@unusedoptionlist\XKV@classoptionslist + \XKV@ifundefined{ver@xkvltxp.sty}{}{% + \@onelevel@sanitize\@unusedoptionlist + }% + \else +% \end{macrocode} +% Else, if the starred version is used, copy global options in case +% they are defined in local families. Do not execute this in the +% document class to avoid setting keys twice. +% \begin{macrocode} + \ifXKV@st + \def\XKV@tempb##1,{% + \def\CurrentOption{##1}% + \ifx\CurrentOption\@nnil\else + \XKV@g@tkeyname##1=\@nil\CurrentOption + \XKV@key@if@ndefined{\CurrentOption}{}{% +% \end{macrocode} +% If the option also exists in local families, add it to the list for +% later use and remove it from |\@unusedoptionlist|. +% \begin{macrocode} + \XKV@useoption{##1}% + \XKV@addtolist@n\XKV@tempa{##1}% + }% + \expandafter\XKV@tempb + \fi + }% + \expandafter\XKV@tempb\XKV@classoptionslist,\@nil,% + \fi + \fi +% \end{macrocode} +% Add current package options to the list. +% \begin{macrocode} + \expandafter\XKV@addtolist@o\expandafter + \XKV@tempa\csname opt@\@currname.\@currext\endcsname +% \end{macrocode} +% Set options. We can be certain that global options can be set since +% the definitions of local options have been checked above. Note that +% |\DeclareOptionX*| will not consume global options when +% |\ProcessOptionsX*| is used. +% \begin{macrocode} + \def\XKV@tempb{\XKV@setkeys[#1]}% + \expandafter\XKV@tempb\expandafter{\XKV@tempa}% +% \end{macrocode} +% Reset the macro created by |\DeclareOptionX*| to avoid processing +% future unknown keys using |\XKV@doxs|. +% \begin{macrocode} + \let\XKV@doxs\relax +% \end{macrocode} +% Reset the |\XKV@rm| macro to avoid processing remaining options +% with |\setrmkeys|. +% \begin{macrocode} + \let\XKV@rm\@empty +% \end{macrocode} +% Reset |\ifXKV@inpox|: not in |\ProcessOptionsX| anymore. +% \begin{macrocode} + \XKV@inpoxfalse +% \end{macrocode} +% Reset |\@fileswith@pti@ns| to allow loading of classes or packages +% again. +% \begin{macrocode} + \let\@fileswith@pti@ns\@@fileswith@pti@ns + \AtEndOfPackage{\let\@unprocessedoptions\relax}% +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\XKV@useoption} +% \marg{option}\\ +% Removes an option from |\@unusedoptionlist|. +% \begin{macrocode} +\def\XKV@useoption#1{% + \def\XKV@resa{#1}% + \XKV@ifundefined{ver@xkvltxp.sty}{}{% + \@onelevel@sanitize\XKV@resa + }% + \@expandtwoargs\@removeelement{\XKV@resa}% + {\@unusedoptionlist}\@unusedoptionlist +} +% \end{macrocode} +% \end{macro} +% \changes{v1.3}{2004/05/09}{Moved the options section to the end of +% the package to allow it to use \pf{xkeyval} option macros} +% The options section. Postponed to the end to allow for using +% \pf{xkeyval} options macros. All options are silently ignored. +% \begin{macrocode} +\DeclareOptionX*{% + \PackageWarning{xkeyval}{Unknown option `\CurrentOption'}% +} +\ProcessOptionsX +% \end{macrocode} +% Reset catcodes. +% \begin{macrocode} +\XKVcatcodes +%</xkvlatex> +% \end{macrocode} +% \subsection{\texttt{keyval.tex}} +% \changes{v1.4}{2004/08/24}{Added \pf{keyval} primitives} +% Since the \pf{xkeyval} macros handle input in a very different way +% than \pf{keyval} macros, it is not wise to redefine \pf{keyval} +% primitives (like |\KV@do| and |\KV@split|) used by other packages +% as a back door into |\setkeys|. Instead, we load the original +% primitives here for compatibility to existing packages using (parts +% of) \pf{keyval}. Most of the code is original, but slightly +% adapted to \pf{xkeyval}. See the \pf{keyval} documentation for +% information about the macros below. +% \begin{macrocode} +%<*xkvkeyval> +%% +%% Based on keyval.sty. +%% +\def\XKV@tempa#1{% +\def\KV@@sp@def##1##2{% + \futurelet\XKV@resa\KV@@sp@d##2\@nil\@nil#1\@nil\relax##1}% +\def\KV@@sp@d{% + \ifx\XKV@resa\@sptoken + \expandafter\KV@@sp@b + \else + \expandafter\KV@@sp@b\expandafter#1% + \fi}% +\def\KV@@sp@b#1##1 \@nil{\KV@@sp@c##1}% + } +\XKV@tempa{ } +\def\KV@@sp@c#1\@nil#2\relax#3{\XKV@toks{#1}\edef#3{\the\XKV@toks}} +\def\KV@do#1,{% + \ifx\relax#1\@empty\else + \KV@split#1==\relax + \expandafter\KV@do\fi} +\def\KV@split#1=#2=#3\relax{% + \KV@@sp@def\XKV@tempa{#1}% + \ifx\XKV@tempa\@empty\else + \expandafter\let\expandafter\XKV@tempc + \csname\KV@prefix\XKV@tempa\endcsname + \ifx\XKV@tempc\relax + \XKV@err{`\XKV@tempa' undefined}% + \else + \ifx\@empty#3\@empty + \KV@default + \else + \KV@@sp@def\XKV@tempb{#2}% + \expandafter\XKV@tempc\expandafter{\XKV@tempb}\relax + \fi + \fi + \fi} +\def\KV@default{% + \expandafter\let\expandafter\XKV@tempb + \csname\KV@prefix\XKV@tempa @default\endcsname + \ifx\XKV@tempb\relax + \XKV@err{No value specified for key `\XKV@tempa'}% + \else + \XKV@tempb\relax + \fi} +%</xkvkeyval> +% \end{macrocode} +% \subsection{\texttt{xkvtxhdr.tex}} +% This section generates |xkvtxhdr.tex| which contains some standard +% \LaTeX\ macros taken from |latex.ltx|. This will only be loaded +% when not using |xkeyval.sty|. +% \begin{macrocode} +%<*xkvheader> +%% +%% Taken from latex.ltx. +%% +\message{2005/02/22 v1.1 xkeyval TeX header (HA)} +\def\@nnil{\@nil} +\def\@empty{} +\def\newif#1{% + \count@\escapechar \escapechar\m@ne + \let#1\iffalse + \@if#1\iftrue + \@if#1\iffalse + \escapechar\count@} +\def\@if#1#2{% + \expandafter\def\csname\expandafter\@gobbletwo\string#1% + \expandafter\@gobbletwo\string#2\endcsname + {\let#1#2}} +\long\def\@ifnextchar#1#2#3{% + \let\reserved@d=#1% + \def\reserved@a{#2}% + \def\reserved@b{#3}% + \futurelet\@let@token\@ifnch} +\def\@ifnch{% + \ifx\@let@token\@sptoken + \let\reserved@c\@xifnch + \else + \ifx\@let@token\reserved@d + \let\reserved@c\reserved@a + \else + \let\reserved@c\reserved@b + \fi + \fi + \reserved@c} +\def\:{\let\@sptoken= } \: % this makes \@sptoken a space token +\def\:{\@xifnch} \expandafter\def\: {\futurelet\@let@token\@ifnch} +\let\kernel@ifnextchar\@ifnextchar +\long\def\@testopt#1#2{% + \kernel@ifnextchar[{#1}{#1[{#2}]}} +\long\def\@firstofone#1{#1} +\long\def \@gobble #1{} +\long\def \@gobbletwo #1#2{} +\def\@expandtwoargs#1#2#3{% +\edef\reserved@a{\noexpand#1{#2}{#3}}\reserved@a} +\edef\@backslashchar{\expandafter\@gobble\string\\} +\newif\ifin@ +\def\in@#1#2{% + \def\in@@##1#1##2##3\in@@{% + \ifx\in@##2\in@false\else\in@true\fi}% + \in@@#2#1\in@\in@@} +\def\strip@prefix#1>{} +\def \@onelevel@sanitize #1{% + \edef #1{\expandafter\strip@prefix + \meaning #1}% +} +%</xkvheader> +% \end{macrocode} +% \subsection{\texttt{xkvview.sty}} +% This section provides a small utility for package developers. It +% provides several macros to generate overviews of the keys that are +% defined in a package or a collection of packages. It is possible +% to get an overview for a specific family, but also to get a complete +% overview of all keys that have been defined after loading this +% package. +% \begin{macrocode} +%<*xkvview> +\NeedsTeXFormat{LaTeX2e}[1995/12/01] +\ProvidesPackage{xkvview}% + [2005/07/10 v1.4a viewer utility for xkeyval (HA)] +\RequirePackage{xkeyval} +\RequirePackage{longtable} +\DeclareOptionX*{% + \PackageWarning{xkvview}{Unknown option `\CurrentOption'}% +} +\ProcessOptionsX +% \end{macrocode} +% Initializations. +% \begin{macrocode} +\newif\ifXKVV@vwkey +\newif\ifXKVV@colii +\newif\ifXKVV@coliii +\newif\ifXKVV@coliv +\newif\ifXKVV@colv +\newwrite\XKVV@out +\let\XKVV@db\@empty +% \end{macrocode} +% Setup options and presets. +% \begin{macrocode} +\define@cmdkeys[XKVV]{xkvview}[XKVV@]{% + prefix,family,type,default,file,columns,wcolsep,weol}[\@nil] +\define@boolkeys[XKVV]{xkvview}[XKVV@]{view,vlabels,wlabels}[true] +\presetkeys[XKVV]{xkvview}{prefix,family,type,default,file,% + columns,wcolsep=&,weol=\\,view,vlabels=false,wlabels=false}{} +% \end{macrocode} +% \begin{macro}{\XKVV@tabulate} +% \begin{macro}{\XKVV@t@bulate} +% \marg{key}\marg{type}\marg{default}\\ +% Adds the input information to the main database in |\XKVV@db|. +% \begin{macrocode} +\def\XKVV@tabulate#1#2#3{% + \def\XKV@tempa{#3}% + \@onelevel@sanitize\XKV@tempa + \XKV@addtolist@x\XKVV@db{#1=\expandafter + \XKVV@t@bulate\XKV@prefix=\XKV@tfam=#2=\XKV@tempa}% +} +\def\XKVV@t@bulate#1@{#1} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \begin{macro}{\XKV@define@key} +% \begin{macro}{\XKV@d@fine@k@y} +% \begin{macro}{\XKV@define@cmdkey} +% \changes{v2.5c}{2005/07/10}{Avoid initializing control sequence as \cs{relax}} +% \begin{macro}{\XKV@d@fine@ch@icekey} +% \begin{macro}{\XKV@d@fine@ch@ic@key} +% \begin{macro}{\XKV@d@f@ne@b@olkey} +% Redefine the internals of key defining macros to record information +% in the database. +% \begin{macrocode} +\def\XKV@define@key#1{% + \@ifnextchar[{\XKV@d@fine@k@y{#1}}{% + \XKVV@tabulate{#1}{ordinary}{[none]}% + \expandafter\def\csname\XKV@header#1\endcsname####1% + }% +} +\def\XKV@d@fine@k@y#1[#2]{% + \XKVV@tabulate{#1}{ordinary}{#2}% + \XKV@define@default{#1}{#2}% + \expandafter\def\csname\XKV@header#1\endcsname##1% +} +\def\XKV@define@cmdkey#1#2[#3]#4{% + \ifXKV@st + \XKVV@tabulate{#2}{command}{#3}% + \XKV@define@default{#2}{#3}% + \else + \XKVV@tabulate{#2}{command}{[none]}% + \fi + \def\XKV@tempa{\expandafter\def\csname\XKV@header#2\endcsname####1}% + \begingroup\expandafter\endgroup\expandafter\XKV@tempa\expandafter + {\expandafter\def\csname#1#2\endcsname{##1}#4}% +} +\def\XKV@d@fine@ch@icekey#1[#2]{% + \XKVV@tabulate{#1}{choice}{#2}% + \XKV@define@default{#1}{#2}% + \XKV@d@fine@ch@ic@key{#1}% +} +\def\XKV@d@fine@ch@ic@key#1{% + \XKVV@tabulate{#1}{choice}{[none]}% + \ifXKV@pl\XKV@afterelsefi + \expandafter\XKV@d@f@ne@ch@ic@k@y + \else\XKV@afterfi + \expandafter\XKV@d@f@ne@ch@ic@key + \fi + \csname\XKV@header#1\endcsname +} +\def\XKV@d@f@ne@b@olkey#1#2#3#4#5{% + \expandafter\newif\csname if#3\endcsname + \ifXKV@st + \XKVV@tabulate{#2}{boolean}{#4}% + \XKV@define@default{#2}{#4}% + \else + \XKVV@tabulate{#2}{boolean}{[none]}% + \fi + \ifXKV@pl + \def#1##1{\XKV@pltrue\XKV@sttrue + \XKV@checkchoice[\XKV@resa]{##1}{true,false}#5% + }% + \else + \def#1##1{\XKV@plfalse\XKV@sttrue + \XKV@checkchoice[\XKV@resa]{##1}{true,false}#5% + }% + \fi +} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \begin{macro}{\xkvview} +% \marg{options}\\ +% The main macro. Produces a long table and/or writes to a target file. +% \begin{macrocode} +\def\xkvview#1{% +% \end{macrocode} +% Process all options. +% \begin{macrocode} + \setkeys[XKVV]{xkvview}{#1}% + \ifx\XKVV@default\@nnil\else\@onelevel@sanitize\XKVV@default\fi +% \end{macrocode} +% If no column information, display all columns. +% \begin{macrocode} + \ifx\XKVV@columns\@nnil + \count@5 + \XKVV@coliitrue\XKVV@coliiitrue\XKVV@colivtrue\XKVV@colvtrue + \else +% \end{macrocode} +% Check how much and which columns should be displayed. +% \begin{macrocode} + \count@\@ne + \@expandtwoargs\in@{,prefix,}{,\XKVV@columns,}% + \ifin@\advance\count@\@ne\XKVV@coliitrue\else\XKVV@coliifalse\fi + \@expandtwoargs\in@{,family,}{,\XKVV@columns,}% + \ifin@\advance\count@\@ne\XKVV@coliiitrue\else\XKVV@coliiifalse\fi + \@expandtwoargs\in@{,type,}{,\XKVV@columns,}% + \ifin@\advance\count@\@ne\XKVV@colivtrue\else\XKVV@colivfalse\fi + \@expandtwoargs\in@{,default,}{,\XKVV@columns,}% + \ifin@\advance\count@\@ne\XKVV@colvtrue\else\XKVV@colvfalse\fi + \fi + \ifXKVV@view +% \end{macrocode} +% Construct long table header. +% \begin{macrocode} + \protected@edef\XKV@tempa{\noexpand\begin{longtable}[l]{% + *\the\count@ l}\normalfont Key\ifXKVV@colii&\normalfont Prefix% + \fi\ifXKVV@coliii&\normalfont Family\fi\ifXKVV@coliv&\normalfont + Type\fi\ifXKVV@colv&\normalfont Default\fi\\\noexpand\hline + \noexpand\endfirsthead\noexpand\multicolumn{\the\count@}{l}{% + \normalfont\emph{Continued from previous page}}\\\noexpand\hline + \normalfont Key\ifXKVV@colii&\normalfont Prefix\fi\ifXKVV@coliii + &\normalfont Family\fi\ifXKVV@coliv&\normalfont Type\fi + \ifXKVV@colv&\normalfont Default\fi\\\noexpand\hline\noexpand + \endhead\noexpand\hline\noexpand\multicolumn{\the\count@}{r}{% + \normalfont\emph{Continued on next page}}\\\noexpand\endfoot + \noexpand\hline\noexpand\endlastfoot + }% + \XKV@toks\expandafter{\XKV@tempa}% + \fi +% \end{macrocode} +% Open the target file for writing if a file name has been specified. +% \begin{macrocode} + \ifx\XKVV@file\@nnil\else\immediate\openout\XKVV@out\XKVV@file\fi +% \end{macrocode} +% Parse the entire database to find entries that match the criteria. +% \begin{macrocode} + \XKV@for@o\XKVV@db\XKV@tempa{% + \XKVV@vwkeytrue\expandafter\XKVV@xkvview\XKV@tempa\@nil + }% +% \end{macrocode} +% Finish the long table and typeset it. +% \begin{macrocode} + \ifXKVV@view + \addto@hook\XKV@toks{\end{longtable}}% + \begingroup\ttfamily\the\XKV@toks\endgroup + \fi +% \end{macrocode} +% Close the target file. +% \begin{macrocode} + \ifx\XKVV@file\@nnil\else\immediate\closeout\XKVV@out\fi +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\XKVV@xkvview} +% \meta{key}|=|\meta{prefix}|=|\meta{family}|=|\meta{type}|=|\meta{default}|\@nil|\\ +% Parse a row in the database to get individual column entries. Select +% the requested columns and store the table row in the token or write +% it to the target file. +% \begin{macrocode} +\def\XKVV@xkvview#1=#2=#3=#4=#5\@nil{% +% \end{macrocode} +% Check whether the current entry satisfies all criteria. +% \begin{macrocode} + \ifx\XKVV@prefix\@nnil\else + \def\XKV@tempa{#2}% + \ifx\XKV@tempa\XKVV@prefix\else\XKVV@vwkeyfalse\fi + \fi + \ifx\XKVV@family\@nnil\else + \def\XKV@tempa{#3}% + \ifx\XKV@tempa\XKVV@family\else\XKVV@vwkeyfalse\fi + \fi + \ifx\XKVV@type\@nnil\else + \def\XKV@tempa{#4}% + \ifx\XKV@tempa\XKVV@type\else\XKVV@vwkeyfalse\fi + \fi + \ifx\XKVV@default\@nnil\else + \def\XKV@tempa{#5}% + \ifx\XKV@tempa\XKVV@default\else\XKVV@vwkeyfalse\fi + \fi + \ifXKVV@vwkey +% \end{macrocode} +% If output should go to the dvi, construct the table row and add it +% to the token. +% \begin{macrocode} + \ifXKVV@view + \edef\XKV@tempa{% + #1\ifXKVV@colii\fi\ifXKVV@coliii\fi + \ifXKVV@coliv\fi\ifXKVV@colv\fi + \ifXKVV@vlabels\noexpand\label{#2-#3-#1}\fi + }% + \expandafter\addto@hook\expandafter + \XKV@toks\expandafter{\XKV@tempa\\}% + \fi + \ifx\XKVV@file\@nnil\else +% \end{macrocode} +% When writing, construct the line and write it to file. Notice that +% \pf{xkeyval} removes braces and spaces, so |wcolsep={ }| won't make +% a space between column entries, but |wcolsep=\space| will. +% \begin{macrocode} + \immediate\write\XKVV@out{% + #1\ifXKVV@colii\XKVV@wcolsep#2\fi + \ifXKVV@coliii\XKVV@wcolsep#3\fi + \ifXKVV@coliv\XKVV@wcolsep#4\fi + \ifXKVV@colv\XKVV@wcolsep#5\fi + \ifXKVV@wlabels\string\label{#2-#3-#1}\fi + \expandafter\noexpand\XKVV@weol + }% + \fi + \fi +} +%</xkvview> +% \end{macrocode} +% \end{macro} +% \subsection{\texttt{xkvltxp.sty}}\label{sec:ltxpatch} +% \changes{v1.5}{2004/09/27}{Added \LaTeX\ kernel patch} +% This section redefines some kernel macros as to avoid expansions of +% options at several places to allow for macros in key values in class +% and package options. It uses a temporary token register and some +% careful expansions. Notice that |\@unusedoptionlist| is sanitized +% after creation by \pf{xkeyval} to avoid |\@removeelement| causing +% problems with macros and braces. See for more information about the +% original versions of the macros below the kernel source documentation +% \cite{LaTeXbase}. +% \begin{macrocode} +%<*xkvltxpatch> +%% +%% Based on latex.ltx. +%% +\NeedsTeXFormat{LaTeX2e}[1995/12/01] +\ProvidesPackage{xkvltxp}[2004/12/13 v1.2 LaTeX2e kernel patch (HA)] +\def\@pass@ptions#1#2#3{% + \def\reserved@a{#2}% + \def\reserved@b{\CurrentOption}% + \ifx\reserved@a\reserved@b + \@ifundefined{opt@#3.#1}{\@temptokena\expandafter{#2}}{% + \@temptokena\expandafter\expandafter\expandafter + {\csname opt@#3.#1\endcsname}% + \@temptokena\expandafter\expandafter\expandafter{% + \expandafter\the\expandafter\@temptokena\expandafter,#2}% + }% + \else + \@ifundefined{opt@#3.#1}{\@temptokena{#2}}{% + \@temptokena\expandafter\expandafter\expandafter + {\csname opt@#3.#1\endcsname}% + \@temptokena\expandafter{\the\@temptokena,#2}% + }% + \fi + \expandafter\xdef\csname opt@#3.#1\endcsname{\the\@temptokena}% +} +\def\OptionNotUsed{% + \ifx\@currext\@clsextension + \let\reserved@a\CurrentOption + \@onelevel@sanitize\reserved@a + \xdef\@unusedoptionlist{% + \ifx\@unusedoptionlist\@empty\else\@unusedoptionlist,\fi + \reserved@a}% + \fi +} +\def\@use@ption{% + \let\reserved@a\CurrentOption + \@onelevel@sanitize\reserved@a + \@expandtwoargs\@removeelement\reserved@a + \@unusedoptionlist\@unusedoptionlist + \csname ds@\CurrentOption\endcsname +} +\def\@fileswith@pti@ns#1[#2]#3[#4]{% + \ifx#1\@clsextension + \ifx\@classoptionslist\relax + \@temptokena{#2}% + \xdef\@classoptionslist{\the\@temptokena}% + \def\reserved@a{% + \@onefilewithoptions#3[#2][#4]#1% + \@documentclasshook}% + \else + \def\reserved@a{% + \@onefilewithoptions#3[#2][#4]#1}% + \fi + \else + \@temptokena{#2}% + \def\reserved@b##1,{% + \ifx\@nil##1\relax\else + \ifx\relax##1\relax\else + \noexpand\@onefilewithoptions##1% + [\the\@temptokena][#4]\noexpand\@pkgextension + \fi + \expandafter\reserved@b + \fi}% + \edef\reserved@a{\zap@space#3 \@empty}% + \edef\reserved@a{\expandafter\reserved@b\reserved@a,\@nil,}% + \fi + \reserved@a} +\let\@@fileswith@pti@ns\@fileswith@pti@ns +%</xkvltxpatch> +% \end{macrocode} +% \subsection{\texttt{pst-xkey.tex}} +% Avoid loading |pst-xkey.tex| twice. +% \begin{macrocode} +%<*pxktex> +\csname PSTXKeyLoaded\endcsname +\let\PSTXKeyLoaded\endinput +\edef\PSTXKeyCatcodes{% + \catcode`\noexpand\@\the\catcode`\@\relax + \let\noexpand\PSTXKeyCatcodes\relax +} +\catcode`\@=11\relax +% \end{macrocode} +% Load \pf{xkeyval} when not already done by |pst-xkey.sty| and +% provide information. +% \begin{macrocode} +\ifx\ProvidesFile\@undefined + \message{2005/02/22 v1.5 PSTricks specialization of xkeyval (HA)} + \ifx\XKeyValLoaded\endinput\else\input xkeyval \fi +\else + \ProvidesFile{pst-xkey.tex} + [2005/02/22 v1.5 PSTricks specialization of xkeyval (HA)] + \@addtofilelist{pst-xkey.tex} + \RequirePackage{xkeyval} +\fi +% \end{macrocode} +% \begin{macro}{\pst@famlist} +% Initialize the list of families. +% \begin{macrocode} +\def\pst@famlist{} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\pst@addfams} +% Adds the family to |\pst@famlist| if it was not in yet. +% \begin{macrocode} +\def\pst@addfams#1{% + \XKV@for@n{#1}\XKV@tempa{% + \@expandtwoargs\in@{,\XKV@tempa,}{,\pst@famlist,}% + \ifin@\else\edef\pst@famlist{\pst@famlist,\XKV@tempa}\fi + }% +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\psset} +% \changes{v1.8b}{2004/12/22}{Properly expand \cs{pst@famlist}} +% \begin{macro}{\pss@t} +% Set keys. Uses \pf{xkeyval}'s |\setkeys+|. +% \begin{macrocode} +\def\psset{% + \expandafter\@testopt\expandafter\pss@t\expandafter{\pst@famlist}% +} +\def\pss@t[#1]{\setkeys+[psset]{#1}} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \begin{macro}{\@psset} +% This macro defined by |pstricks.tex| is internally used as a +% shortcut. We have to redefine this as well to avoid problems. +% \begin{macrocode} +\def\@psset#1,\@nil{% + \edef\XKV@tempa{\noexpand\setkeys+[psset]{\pst@famlist}}% + \XKV@tempa{#1}% +} +% \end{macrocode} +% \end{macro} +% Finalize. +% \begin{macrocode} +\PSTXKeyCatcodes +%</pxktex> +% \end{macrocode} +% \subsection{\texttt{pst-xkey.sty}} +% Initialize the package. +% \begin{macrocode} +%<*pxklatex> +\NeedsTeXFormat{LaTeX2e}[1995/12/01] +\ProvidesPackage{pst-xkey} + [2005/02/22 v1.5 package wrapper for pst-xkey.tex (HA)] +% \end{macrocode} +% Load required package. +% \begin{macrocode} +\ifx\PSTXKeyLoaded\endinput\else\input pst-xkey \fi +% \end{macrocode} +% Ignore options. +% \begin{macrocode} +\DeclareOptionX*{% + \PackageWarning{pst-xkey}{Unknown option `\CurrentOption'}% +} +\ProcessOptionsX +%</pxklatex> +% \end{macrocode} +% +% \Finale +% \endinput +% +%<*xkvex1> +\input xkeyval + +\catcode`\@=11 + +%% xkeyval package: TeX example +%% Hendri Adriaens + +\noindent Example 1. This example demonstrates the use of the new +macros for setting keys of the `xkeyval' package. Have a look at the +source for information about this example and to understand the output. + +%% Define keys. +\define@key{fami}{keyi}{key 1: #1 } +\define@key{famii}{keyii}{key 2: #1 } +\define@key{famiii}{keyiii}[test 2]{key 3: #1 } +\define@key{famiv}{keyi}{key 4: #1 } + +%% Set keys from multiple families. +\setkeys{fami,famii,famiii}{keyi=test 1,keyiii} + +%% Multiplely defined keys will be taken from the first family on the +%% list that defines the key. When + is used, all families +%% defining the key will set it. +\setkeys{fami,famiv}{keyi=test 3}\par +\setkeys{famiv,fami}{keyi=test 4}\par +\setkeys+{fami,famiv}{keyi=test 5}\par + +%% Starred form sets keys that it can find in the families specified. +%% Keys that cannot be located will be put onto a list for later use +%% by \setrmkeys. +\setkeys*{famiv}{keyi=test 9,keyii=http://www.test10.com, + keyiii=test 11}\par + +%% Try to set the remaining keys from the previous step. The starred +%% version defines a new list in case there are still keys that cannot +%% be located in the given families. The command below does not do +%% anything since the `keyi' key has already been taken from family +%% `famiv' above. +\setrmkeys*{fami}\par + +%% The normal version will complain (as \setkeys) when it cannot locate +%% a key which was previously submitted to \xsetkeys and hasn't been +%% set yet by previous commands. `xkeyval' commands can also be used to +%% set `keyval' options. +\setrmkeys{famii,famiii}\par + +%% Set keys, excluding some keys. +\setkeys{fami,famii,famiii}[keyi,keyiii]{keyi=test 6,keyii=test +7,keyiii=test 8}\par + +%% Test whether a key is defined in a family from the list. +\key@ifundefined{fami,famii}{keyiii} +{keyiii is not defined in family `fami' or `famii'} +{keyiii is defined in family `fami' or `famii'} + +%% Define some keys and macros. +\define@cmdkey[my]{fama}[my@]{keya}[none]{} +\define@choicekey[my]{fama}{keyb}{a,b,c}[b]{correct input: #1} +\define@boolkey[my]{famb}{keyc}[true]{} +\def\testa{\setkeys[my]{fama}} +\def\testb{\setkeys[my]{famb}} +\def\testset{\setkeys[my]{fama,famb}} + +%% Now \testa can only set keya, \testb can only +%% set keyb and \testset can set both. +\testa{keya} + \my@keya\ +\testa{keyb} +\testb{keyc} + \ifmy@famb@keyc true \else false \fi +\testset{keya=test 11,keyb=c,keyc=false} + \my@keya\space + \ifmy@famb@keyc true \else false \fi + +%% Pointer system + +%% First we (re)define some keys. +\define@key{fam}{keyi}{key 1: #1 } +\define@key{fam}{keyii}{key 2: #1 } +\define@key{fam}{keyiii}[test 2]{key 3: #1 } + +%% Pointers can be used to copy the value of other keys in the same +%% family. This can be done in two ways. The first example shows `on +%% the spot' value saving. +\setkeys{fam}{\savevalue{keyi}=test 12,\savevalue{keyii}=\usevalue{keyi}} +\setkeys{fam}{keyiii=\usevalue{keyii}} + +%% However, you can also predefine the keys to be saved for the entire +%% document with a single command. +\savekeys{fam}{keyi,keyii} +\setkeys{fam}{keyi=test 13,keyii=\usevalue{keyi}} +\setkeys{fam}{keyiii=\usevalue{keyii}} + +%% Pointers can be used in default values as well. Remember that the +%% previous example used \savekeys for keyi and keyii. +\define@key{fam}{keyi}{keyi: #1 } +\define@key{fam}{keyii}[\usevalue{keyi}]{keyii: #1 } +\define@key{fam}{keyiii}[\usevalue{keyii}]{keyiii: #1 } +\setkeys{fam}{keyi=test 14} +\setkeys{fam}{keyii} +\setkeys{fam}{keyiii} + +%% Presetting keys + +%% Simple example of the preset system. +\define@key{fam}{keyi}{keyi: #1 } +\define@key{fam}{keyii}{keyii: #1 } +\presetkeys{fam}{keyi=blue}{keyii=\usevalue{keyi}} +\setkeys{fam}{}\par +\setkeys{fam}{keyi=red}\par +\setkeys{fam}{keyii=red} +\presetkeys{fam}{keyi=red}{}\par +\setkeys{fam}{keyii=\usevalue{keyi}} + +\bye +%</xkvex1> +% +%<*xkvex2> +\documentclass{article} +\usepackage{xkeyval} +\usepackage{xcolor,calc} + +%% Example of setting keyval options using xkeyval +\usepackage{hyperref} +\usepackage{helvet} +\setkeys{Hyp,Hel}{colorlinks,urlcolor=green,scaled=.85} + +\title{\textsf{xkeyval} package\\\normalsize\emph{Example 2}} +\author{Hendri Adriaens} +\setlength{\parindent}{0cm} + +\makeatletter + +\begin{document} +\maketitle + +This example demonstrates the use of the new macros for setting +keys of the \textsf{xkeyval} package. Below each piece of verbatim +code, you can find its output. + +\section{Simple operations} + +Define keys. +\begin{verbatim} +\define@key{fami}{keyi}{key 1: #1\space} +\define@key{famii}{keyii}{key 2: #1\space} +\define@key{famiii}{keyiii}[test 2]{key 3: #1\space} +\define@key{famiv}{keyi}{key 4: #1\space} +\end{verbatim} +\define@key{fami}{keyi}{key 1: #1\space} +\define@key{famii}{keyii}{key 2: #1\space} +\define@key{famiii}{keyiii}[test 2]{key 3: #1\space} +\define@key{famiv}{keyi}{key 4: #1\space} + +Set keys from multiple families. +\begin{verbatim} +\setkeys{fami,famii,famiii}{keyi=test 1,keyiii} +\end{verbatim} +\begin{itemize} +\item[$\Rightarrow$] +\setkeys{fami,famii,famiii}{keyi=test 1,keyiii} +\end{itemize} + +Multiplely defined keys will be taken from the first family on the +list that defines the key. When \verb|+| is used, all families +defining the key will set it. +\begin{verbatim} +\setkeys{fami,famiv}{keyi=test 3} +\setkeys{famiv,fami}{keyi=test 4} +\setkeys+{fami,famiv}{keyi=test 5} +\end{verbatim} +\begin{itemize} +\item[$\Rightarrow$] +\setkeys{fami,famiv}{keyi=test 3}\par +\setkeys{famiv,fami}{keyi=test 4}\par +\setkeys+{fami,famiv}{keyi=test 5} +\end{itemize} + +Starred form sets keys that it can find in the families specified. +Keys that cannot be located will be put onto a list for later use +by \verb+\setrmkeys+. +\begin{verbatim} +\setkeys*{famiv}{keyi=test 9,keyii=\url{http://www.test10.com}, + keyiii=this key has been set on page \thepage} +\end{verbatim} +\begin{itemize} +\item[$\Rightarrow$] +\setkeys*{famiv}{keyi=test 9,keyii=\url{http://www.test10.com}, + keyiii=this key has been set on page \thepage} +\end{itemize} + +Try to set the remaining keys from the previous step. The starred +version defines a new list in case there are still keys that +cannot be located in the given families. The command below does +not do anything since the \verb+keyi+ key has already been taken +from family \verb+famiv+ above. +\begin{verbatim} +\setrmkeys*{fami} +\end{verbatim} +\setrmkeys*{fami}\par + +The normal version will complain (as \verb+\setkeys+) when it +cannot locate a key which was previously submitted to +\verb+\setkeys+ and hasn't been set yet by previous commands. +\textsf{xkeyval} commands can also be used to set \textsf{keyval} +options as is done to the color of the url created with the +\textsf{hyperref} package and the scaling of the font used for +`\textsf{xkeyval}' with the \textsf{helvet} package. (See the +preamble of the example for the code). +\begin{verbatim} +\setrmkeys{famii,famiii} +\end{verbatim} +\begin{itemize} +\item[$\Rightarrow$] +\setrmkeys{famii,famiii} +\end{itemize} + +Set keys, excluding some keys. +\begin{verbatim} +\setkeys{fami,famii,famiii}[keyi,keyiii]{keyi=test 6,keyii=test 7,keyiii=test 8} +\end{verbatim} +\begin{itemize} +\item[$\Rightarrow$] +\setkeys{fami,famii,famiii}[keyi,keyiii]{keyi=test 6,keyii=test 7,keyiii=test 8} +\end{itemize} + +Test whether a key is defined in a family from the list. +\begin{verbatim} +\key@ifundefined{fami,famii}{keyiii} +{keyiii is not defined in family `fami' or `famii'} +{keyiii is defined in family `fami' or `famii'} +\end{verbatim} +\begin{itemize} +\item[$\Rightarrow$] +\key@ifundefined{fami,famii}{keyiii} +{keyiii is not defined in family `fami' or `famii'} +{keyiii is defined in family `fami' or `famii'} +\end{itemize} + +Define some keys and macros. +\begin{verbatim} +\define@cmdkey[my]{fama}[my@]{keya}[none]{} +\define@choicekey[my]{fama}{keyb}{a,b,c}[b]{correct input: #1} +\define@boolkey[my]{famb}{keyc}[true]{} +\def\testa{\setkeys[my]{fama}} +\def\testb{\setkeys[my]{famb}} +\def\testset{\setkeys[my]{fama,famb}} +\end{verbatim} +\define@cmdkey[my]{fama}[my@]{keya}[none]{} +\define@choicekey[my]{fama}{keyb}{a,b,c}[b]{correct input: #1} +\define@boolkey[my]{famb}{keyc}[true]{} +\def\testa{\setkeys[my]{fama}} +\def\testb{\setkeys[my]{famb}} +\def\testset{\setkeys[my]{fama,famb}} +Now \verb+\testa+ can only set \verb+keya+, \verb+\testb+ can only +set \verb+keyb+ and \verb+\testset+ can set both. +\begin{verbatim} +\testa{keya} + \my@keya\ +\testa{keyb} +\testb{keyc} + \ifmy@famb@keyc true \else false \fi +\testset{keya=test 11,keyb=c,keyc=false} + \my@keya\space + \ifmy@famb@keyc true \else false \fi +\end{verbatim} +\begin{itemize} +\item[$\Rightarrow$] +\testa{keya} + \my@keya\ +\testa{keyb} +\testb{keyc} + \ifmy@famb@keyc true \else false \fi +\testset{keya=test 11,keyb=c,keyc=false} + \my@keya\space + \ifmy@famb@keyc true \else false \fi +\end{itemize} + +\section{Pointers and values} + +First we (re)define some keys. +\begin{verbatim} +\define@key{fam}{keyi}{key 1: #1 } +\define@key{fam}{keyii}{key 2: #1 } +\define@key{fam}{keyiii}[test 2]{key 3: #1 } +\end{verbatim} +\define@key{fam}{keyi}{key 1: #1 } +\define@key{fam}{keyii}{key 2: #1 } +\define@key{fam}{keyiii}[test 2]{key 3: #1 } + +Pointers can be used to copy the value of other keys in the same +family. This can be done in two ways. The first example shows `on +the spot' value saving. +\begin{verbatim} +\setkeys{fam}{\savevalue{keyi}=test 12,\savevalue{keyii}=\usevalue{keyi}} +\setkeys{fam}{keyiii=\usevalue{keyii}} +\end{verbatim} +\begin{itemize} +\item[$\Rightarrow$] +\setkeys{fam}{\savevalue{keyi}=test 12,\savevalue{keyii}=\usevalue{keyi}} +\setkeys{fam}{keyiii=\usevalue{keyii}} +\end{itemize} + +However, you can also predefine the keys to be saved for the entire +document with a single command. Note that we force keys to be saved +globally. This is necessary here since the commands in the source of +this document appear in an environment. +\begin{verbatim} +\savekeys{fam}{\global{keyi},\global{keyii}} +\setkeys{fam}{keyi=test 13,keyii=\usevalue{keyi}} +\setkeys{fam}{keyiii=\usevalue{keyii}} +\end{verbatim} +\begin{itemize} +\item[$\Rightarrow$] +\savekeys{fam}{\global{keyi},\global{keyii}} +\setkeys{fam}{keyi=test 13,keyii=\usevalue{keyi}} +\setkeys{fam}{keyiii=\usevalue{keyii}} +\end{itemize} + +Pointers can be used in default values as well. Remember that the +previous example used \verb+\savekeys+ for \verb+keyi+ and \verb+keyii+. +\begin{verbatim} +\define@key{fam}{keyi}{keyi: #1 } +\define@key{fam}{keyii}[\usevalue{keyi}]{keyii: #1 } +\define@key{fam}{keyiii}[\usevalue{keyii}]{keyiii: #1 } +\setkeys{fam}{keyi=test 14} +\setkeys{fam}{keyii} +\setkeys{fam}{keyiii} +\end{verbatim} +\begin{itemize} +\item[$\Rightarrow$] +\define@key{fam}{keyi}{keyi: #1 } +\define@key{fam}{keyii}[\usevalue{keyi}]{keyii: #1 } +\define@key{fam}{keyiii}[\usevalue{keyii}]{keyiii: #1 } +\setkeys{fam}{keyi=test 14} +\setkeys{fam}{keyii} +\setkeys{fam}{keyiii} +\end{itemize} + +\section{Presetting keys} + +Simple example of the preset system. +\begin{verbatim} +\define@key{fam}{keyi}{keyi: #1 } +\define@key{fam}{keyii}{keyii: #1 } +\presetkeys{fam}{keyi=blue}{keyii=\usevalue{keyi}} +\setkeys{fam}{}\par +\setkeys{fam}{keyi=red}\par +\setkeys{fam}{keyii=red} +\presetkeys{fam}{keyi=red}{} +\setkeys{fam}{keyii=\usevalue{keyi}} +\end{verbatim} +\begin{itemize} +\item[$\Rightarrow$] +\define@key{fam}{keyi}{keyi: #1 } +\define@key{fam}{keyii}{keyii: #1 } +\presetkeys{fam}{keyi=blue}{keyii=\usevalue{keyi}} +\setkeys{fam}{}\par +\setkeys{fam}{keyi=red}\par +\setkeys{fam}{keyii=red} +\presetkeys{fam}{keyi=red}{}\par +\setkeys{fam}{keyii=\usevalue{keyi}} +\end{itemize} + +\section{Application of pointers, values and presets} + +\setkeys{Hyp}{urlcolor=black} +More complicated example of the preset +system and pointer system. See for more information about this +example the +\textsf{xkeyval} article on\par +\url{http://stuwww.uvt.nl/~hendri/downloads/xkeyval.html}. +\begin{verbatim} +\newdimen\shadowsize +\define@boolkey{Fbox}{frame}[true]{} +\define@boolkey{Fbox}{shadow}[true]{} +\define@key{Fbox}{framecolor}{\def\Fboxframecolor{#1}} +\define@key{Fbox}{shadowcolor}{\def\Fboxshadowcolor{#1}} +\define@key{Fbox}{framesize}{\setlength\fboxrule{#1}} +\define@key{Fbox}{shadowsize}{\setlength\shadowsize{#1}} +\presetkeys{Fbox}{frame,framecolor=red,framesize=0.5pt}% + {shadow=\usevalue{frame},shadowcolor=\usevalue{framecolor}!40,% + shadowsize=\usevalue{framesize}*4} +\savekeys{Fbox}{frame,framecolor,framesize} +\newcommand*\Fbox[2][]{% + \setkeys{Fbox}{#1}% + {\ifKV@Fbox@frame\else\fboxrule0pt\fi + \ifKV@Fbox@shadow\else\shadowsize0pt\fi + \sbox0{\fcolorbox{\Fboxframecolor}{white}{#2}}% + \hskip\shadowsize + \color{\Fboxshadowcolor}% + \rule[-\dp0]{\wd0}{\ht0+\dp0}% + \llap{\raisebox{\shadowsize}% + {\box0\hskip\shadowsize}}}% +} +\Fbox{demo1} +\Fbox[framecolor=blue]{demo2} +\Fbox[shadow=false]{demo3} +\Fbox[framesize=1pt]{demo4} +\Fbox[frame=false,shadow]{demo5} +\end{verbatim} +\newdimen\shadowsize +\define@boolkey{Fbox}{frame}[true]{} +\define@boolkey{Fbox}{shadow}[true]{} +\define@key{Fbox}{framecolor}% + {\def\Fboxframecolor{#1}} +\define@key{Fbox}{shadowcolor}% + {\def\Fboxshadowcolor{#1}} +\define@key{Fbox}{framesize}% + {\setlength\fboxrule{#1}} +\define@key{Fbox}{shadowsize}% + {\setlength\shadowsize{#1}} +\presetkeys{Fbox}% + {frame,framecolor=red,framesize=0.5pt}% + {shadow=\usevalue{frame}, + shadowcolor=\usevalue{framecolor}!40, + shadowsize=\usevalue{framesize}*4} +\savekeys{Fbox}{frame,framecolor,framesize} +\newcommand*\Fbox[2][]{% + \setkeys{Fbox}{#1}% + {\ifKV@Fbox@frame\else\fboxrule0pt\fi + \ifKV@Fbox@shadow\else\shadowsize0pt\fi + \sbox0{\fcolorbox{\Fboxframecolor}{white}{#2}}% + \hskip\shadowsize + \color{\Fboxshadowcolor}% + \rule[-\dp0]{\wd0}{\ht0+\dp0}% + \llap{\raisebox{\shadowsize}% + {\box0\hskip\shadowsize}}}% +} +\Fbox{demo1} +\Fbox[framecolor=blue]{demo2} +\Fbox[shadow=false]{demo3} +\Fbox[framesize=1pt]{demo4} +\Fbox[frame=false,shadow]{demo5} + +\end{document} +%</xkvex2> +% +%<*xkvex3> +%% keyi will set \keyi in xkveca.cls +%% keyvi will set \keyvi in xkveca.cls and xkvesc.sty will pick +%% it up from \documentclass and redefine it +%% IgnoredGlobal and another=key will be considered as global +%% options to be passed on to packages. Not used anymore. +\documentclass[keyi=test1,keyvi,another=key,IgnoredGlobal,10pt]{xkveca} + +%% keyii will set \keyii in xkvesa.sty +%% keyiv will be passed to xkvesb.sty as unknown option +%% the other input will be passed on to xkvesb as well. +\usepackage[keyii=test2,keyiv=test4,test5]{xkvesa} + +%% keyvii will set \keyvii in xkvesc.sty +\usepackage[keyvii]{xkvesc} + +\title{\textsf{xkeyval} package\\\normalsize\emph{Example 2}} +\author{Hendri Adriaens} +\setlength{\parindent}{0cm} + +\makeatletter +\let\@tempa\@classoptionslist +\let\@tempb\@unusedoptionlist + +\begin{document} +\maketitle + +This example demonstrates the use of the new macros for declaring +class and package options of the \textsf{xkeyval} package. Please +study the files \verb+xkvex2.tex+, \verb+xkveca.cls+, +\verb+xkvecb.cls+, \verb+xkvesa.sty+, \verb+xkvesb.sty+ and +\verb+xkvesc.sty+ carefully to understand the output below.\\ + +Set by \verb+xkveca.cls+: \keyi\par +Set by \verb+xkvesa.sty+, copied from \verb+\documentclass+: \keyia\par +Set by \verb+xkvesa.sty+: \keyii\par +Set by \verb+xkvesb.sty+, passed on from \verb+xkvesa.sty+: \keyiii\par +Set by \verb+xkvesb.sty+, passed on as unknown key from \verb+xkvesa.sty+: \keyiv\par +Set by \verb+xkvesb.sty+, passed on as unknown from \verb+xkvesa.sty+: \keyv\par +Set by the class, copied by \verb+xkvesc.sty+: \keyvi\par +Set by \verb+xkvesc.sty+: \keyvii\par +Set by \verb+xkvecb.cls+, passed on from \verb+xkveca.cls+: \keyviii\\ + +The document class is: \XKV@documentclass\par +Unused global options: \@tempb\\ + +Notice the content of the following macros.\par +\verb+\@classoptionslist+: \@tempa\par +\verb+\XKV@classoptionslist+: \XKV@classoptionslist\\ + +This shows that \verb+key=value+ pairs have been deleted from the +class options list so that subsequent packages which are not using +\textsf{xkeyval} and are scanning this list will not run into +problems.\\ + +\end{document} +%</xkvex3> +% +%<*xkvex4> +%% Load LaTeX kernel macros patch +\RequirePackage{xkvltxp} + +%% keyi will set \keyi in xkveca.cls +%% keyvi will set \keyvi in xkveca.cls and xkvesc.sty will pick +%% it up from \documentclass and redefine it +%% IgnoredGlobal and another=key will be considered as global +%% options to be passed on to packages. Not used anymore. +\documentclass[keyi=test1 on page \thepage,keyvi,another=key,IgnoredGlobal,10pt]{xkveca} + +%% keyii will set \keyii in xkvesa.sty +%% keyiv will be passed to xkvesb.sty as unknown option +%% the other input will be passed on to xkvesb as well. +\usepackage[keyii=test2 on page \thepage,keyiv=test4 on page \thepage,test5]{xkvesa} + +%% keyvii will set \keyvii in xkvesc.sty +\usepackage[keyvii]{xkvesc} + +\title{\textsf{xkeyval} package\\\normalsize\emph{Example 3}} +\author{Hendri Adriaens} +\setlength{\parindent}{0cm} + +\makeatletter +\let\@tempa\@classoptionslist +\let\@tempb\@unusedoptionlist +\let\@tempc\XKV@classoptionslist +\@onelevel@sanitize\@tempc + +\begin{document} +\maketitle + +This example demonstrates the use of the new macros for declaring +class and package options of the \textsf{xkeyval} package. Please +study the files \verb+xkvex2.tex+, \verb+xkveca.cls+, +\verb+xkvecb.cls+, \verb+xkvesa.sty+, \verb+xkvesb.sty+ and +\verb+xkvesc.sty+ carefully to understand the output below.\\ + +Set by \verb+xkveca.cls+: \keyi\par +Set by \verb+xkvesa.sty+, copied from \verb+\documentclass+: \keyia\par +Set by \verb+xkvesa.sty+: \keyii\par +Set by \verb+xkvesb.sty+, passed on from \verb+xkvesa.sty+: \keyiii\par +Set by \verb+xkvesb.sty+, passed on as unknown from \verb+xkvesa.sty+: \keyiv\par +Set by \verb+xkvesb.sty+, passed on as unknown from \verb+xkvesa.sty+: \keyv\par +Set by the class, copied by \verb+xkvesc.sty+: \keyvi\par +Set by \verb+xkvesc.sty+: \keyvii\par +Set by \verb+xkvecb.cls+, passed on from \verb+xkveca.cls+: \keyviii\\ + +The document class is: \XKV@documentclass\par +Unused global options: \texttt{\@tempb}\\ + +Notice the content of the following macros.\par +\verb+\@classoptionslist+: \texttt{\@tempa}\par +\verb+\XKV@classoptionslist+:\par\texttt{\@tempc}\\ + +This shows that \verb+key=value+ pairs have been deleted from the +class options list so that subsequent packages which are not using +\textsf{xkeyval} and are scanning this list will not run into +problems.\\ + +\newpage +This page shows that key values are only expanded when they are +actually used. They are not expanded during option processing.\\ + +\keyi\par +\keyii\par +\keyiv + +\end{document} +%</xkvex4> +% +%<*xkveca> +\ProvidesClass{xkveca} +\usepackage{xkeyval} +\let\keyi\@empty +\let\keyvi\@empty +\DeclareOptionX{keyi}{\def\keyi{#1}} +%% this key has a default value +\DeclareOptionX{keyvi}[{test 6}]{\def\keyvi{#1}} +%% pass option to class xkvesb.cls +\PassOptionsToClass{notitlepage}{xkvecb} +\PassOptionsToClass{keyviii={test 8}}{xkvecb} +%% pass unknown options to article +\DeclareOptionX*{\PassOptionsToClass{\CurrentOption}{article}} +%% process options +\ProcessOptionsX +%% load another class +\LoadClass{xkvecb} +%</xkveca> +% +%<*xkvecb> +\ProvidesClass{xkvecb} +%% pass any unknown option to article +\DeclareOptionX{keyviii}{\def\keyviii{#1}} +\DeclareOptionX*{\PassOptionsToClass{\CurrentOption}{article}} +\ProcessOptionsX* +%% load article +\LoadClass{article} +%</xkvecb> +% +%<*xkvesa> +\ProvidesPackage{xkvesa} +\let\keyia\@empty +\let\keyii\@empty +%% keyi has been used in \documentclass +%% this key uses that information to set another macro +%% to do this, \ProcessOptionsX* is necessary. +%% the value from the \documentclass is copied. +\DeclareOptionX{keyi}{\def\keyia{#1}} +\DeclareOptionX{keyii}{\def\keyii{#1}} +%% pass any unknown keys to xkvesb.sty +\DeclareOptionX*{\PassOptionsToPackage{\CurrentOption}{xkvesb}} +%% pass a specific key=value to xkvesb.sty +\PassOptionsToPackage{keyiii={test 3}}{xkvesb} +%% process options. use the * to pick up options from \documentclass +\ProcessOptionsX* +\RequirePackage{xkvesb} +%</xkvesa> +% +%<*xkvesb> +\ProvidesPackage{xkvesb} +\let\keyiii\@empty +\let\keyiv\@empty +\let\keyv\@empty +%% use multiple families to define options +\DeclareOptionX[xkvesb]<famiii>{keyiii}{\def\keyiii{#1}} +\DeclareOptionX[xkvesb]<famiv>{keyiv}{\def\keyiv{#1}} +%% define \keyv as \CurrentOption +\DeclareOptionX*{\let\keyv\CurrentOption} +%% execute options in multiple families +\ExecuteOptionsX[xkvesb]<famiii>{keyiii={test 3}} +%% process options in multiple families +%% do not set keyiii +\ProcessOptionsX[xkvesb]<famiii,famiv>[keyiii] +%</xkvesb> +% +%<*xkvesc> +\ProvidesPackage{xkvesc} +%% redefine \keyvi when keyvi option is specified in \documentclass +\DeclareOption{keyvi}{\def\keyvi{test 6a}} +%% keyvii is a package specific key +\DeclareOption{keyvii}{\def\keyvii{test 7}} +%% note that this package uses original LaTeX macros for options. +%% this is possible since xkeyval filters key=value pairs from +%% the \documentclass options list. +\ProcessOptions +%</xkvesc> +% +%<*preamble> +\usepackage{url} +\usepackage{xkeyval} +\usepackage{fourier} +\usepackage{xcolor} +\usepackage[multiple]{footmisc} +\usepackage{pst-char} +\usepackage{listings} +\lstnewenvironment{command}{% + \lstset{columns=flexible,frame=single,backgroundcolor=\color{blue!20},% + xleftmargin=\fboxsep,xrightmargin=\fboxsep,escapeinside=`',gobble=1}}{} +\lstnewenvironment{example}{% + \lstset{basicstyle=\footnotesize\ttfamily,columns=flexible,frame=single,% + backgroundcolor=\color{yellow!20},xleftmargin=\fboxsep,% + xrightmargin=\fboxsep,gobble=1}}{} +\def\mktitledecor{% + \rput[tl]{90}(-6.5,-23.56){% + \psline[linewidth=1pt](0,1.5)(\paperheight,1.5)% + \rput[lB](.075\paperheight,.5){\pscharpath[linecolor=blue!50,% + fillcolor=yellow!20,fillstyle=solid,linewidth=.5pt]% + {\Huge\bfseries\sffamily xkeyval}% + }% + \rput[rB](.925\paperheight,.5){\pscharpath[linecolor=blue!50,% + fillcolor=yellow!20,fillstyle=solid,linewidth=.5pt]% + {\Huge\bfseries Documentation}% + }% + \psline[linewidth=1pt](0,0)(\paperheight,0)% + }% +} +\makeatletter +\def\tableofcontents{\@starttoc{toc}} +\def\changes@#1#2#3{\ch@nges #1\@nil{#2}{#3}} +\def\ch@nges v#1.#2#3\@nil#4#5{% + \ifnum#1#2<20\else % Controls displaying changes; 0 displays all. + \protected@edef\@tempa{% + \noexpand\glossary{\textbf{v#1.#2#3}\hfill\emph{(#4)}% + \levelchar + \ifx\saved@macroname\@empty + \space\actualchar\generalname + \else + \expandafter\@gobble\saved@macroname + \actualchar\string\verb\quotechar*% + \verbatimchar\saved@macroname\verbatimchar + \fi + :\levelchar #5}}% + \@tempa + \fi\endgroup\@esphack +} +\renewenvironment{theglossary}{% + \section*{Version history}% + This version history displays recent changes only.\par\bigskip + \GlossaryParms \let\item\@idxitem \ignorespaces +}{}% +\def\eTeX{$\m@th\varepsilon$-\TeX} +\def\DescribeMacros{\leavevmode\@bsphack + \begingroup\MakePrivateLetters\Describe@Macros} +\def\Describe@Macros#1{\endgroup\strut + \marginpar{\raggedleft + \def\@tempa{#1}\count@\z@ + \XKV@for@o\@tempa\@tempa{% + \ifnum\count@>\z@\\\fi\advance\count@\@ne + \MacroFont\expandafter\string\@tempa + \expandafter\SpecialUsageIndex\expandafter{\@tempa}% + }}% + \@esphack\ignorespaces +} +\def\DescribeOption#1{\leavevmode\@bsphack + \marginpar{\raggedleft\PrintDescribeOption{#1}}% + \SpecialOptionIndex{#1}\@esphack\ignorespaces} +\def\PrintDescribeOption#1{\strut\emph{option}\\\MacroFont #1\ } +\def\SpecialOptionIndex#1{\@bsphack + \index{#1\actualchar{\protect\ttfamily#1} + (option)\encapchar usage}% + \index{options:\levelchar#1\actualchar{\protect\ttfamily#1}\encapchar + usage}\@esphack} +\def\DescribeOptions#1{\leavevmode\@bsphack + \marginpar{\raggedleft\strut\emph{options}% + \@for\@tempa:=#1\do{% + \\\strut\MacroFont\@tempa\SpecialOptionIndex\@tempa + }}\@esphack\ignorespaces} +\makeatother +\def\PrintChangesX{% + \begingroup + \let\efill\relax + \PrintChanges + \endgroup +} +\def\PrintIndexX{% + \begingroup + \setcounter{IndexColumns}{2} + \setlength{\columnsep}{18pt}% + \setlength{\columnseprule}{.4pt}% + \PrintIndex + \endgroup +} +\def\larg#1{{\ttfamily\char`\<}\meta{#1}{\ttfamily\char`\>}} +\def\pf#1{\textsf{#1}} +\EnableCrossrefs +\RecordChanges +\CodelineIndex +%</preamble> +% +%<*bib> +@MISC{LaTeXbase, + author = {Johannes Braams and David Carlisle and Alan Jeffrey and Leslie Lamport + and Frank Mittelbach and Chris Rowley and Rainer Sch\"opf}, + title = {The {\LaTeXe} Sources}, + howpublished = {\url{CTAN:/macros/latex/base}}, + year = 2003 +} + +@BOOK{companion, + author = {Frank Mittelbach and Michel Goossens and Johannes Braams and David Carlisle and Chris Rowley}, + title = {The {\LaTeX} {C}ompanion, {S}econd {E}dition}, + year = {2004}, + publisher = {{Addison-Wesley}} +} + +@MISC{keyval, + author = {David Carlisle}, + title = {\pf{keyval} package, v1.13, 1999/03/16}, + howpublished = {\url{CTAN:/macros/latex/required/graphics}} +} + +@MISC{extract, + author = {Hendri Adriaens}, + title = {\pf{extract} package}, + howpublished = {\url{CTAN:/macros/latex/contrib/extract}} +} + +@MISC{PSTricks, + author = {{Timothy Van} {Zandt et al.}}, + title = {\pf{PSTricks} package, v1.04, 2004/06/22}, + howpublished = {\url{CTAN:/graphics/pstricks}} +} + +@MISC{PSTricksWeb, + author = {Herbert Vo\ss}, + title = {\pf{PSTricks} website}, + howpublished = {\url{http://www.pstricks.de}} +} +%</bib> |