% \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 % xkvutils.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-2022 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, xkvutils.tex, 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, xkvutils.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{xkvutils.tex}{\from{xkeyval.dtx}{xkvutils}} \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 % %<*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 Carsten Heinz, Morten H\o gholm, Josselin Noirel, Heiko Oberdiek, Will Robertson, Till Tantau, Herbert Vo\ss and Joseph Wright for help and suggestions. Thanks go to Donald Arseneau for contributing the robust |\@ifnextcharacter| macro, to Morten H\o gholm for contributing a fast for-loop macro and to David Carlisle for modifications to support |\par|. 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} % % \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}} % \changes{v2.5e}{2005/11/25}{Updated docs} % \changes{v2.5g}{2006/12/19}{Altered policy for handling \cs{XKV@rm} % in nested \cs{setkeys*} commands: all unknown keys will be recorded, % not only the once from the outermost \cs{setkeys*}} % \changes{v2.6c}{2014/04/27}{Added support for \cs{par} to support similar % changes in \pf{keyval}} % \changes{v2.6d}{2014/05/09}{Implemented fix conform fix in \pf{keyval}} % \changes{v2.7}{2014/05/25}{Moved several utility macros to \pf{xkvutils}} % % \GetFileInfo{xkeyval.sty} % % \CheckSum{3043} % %\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} %\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*|. This list will also contain keys and values coming from %nested |\setkeys*| commands in the order as they have been %submitted. 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 still using %\pf{pst-key}, which are \pf{pst-ob3d}, \pf{pst-stru} and \pf{pst-uml}. % %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} % Load some basic utilities. % \begin{macrocode} \input xkvutils % \end{macrocode} % Initializations. % \begin{macrocode} \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{2014/12/03 v2.7a key=value parser (HA)} \input xkvtxhdr \else \ProvidesFile{xkeyval.tex}[2014/12/03 v2.7a key=value parser (HA)] \@addtofilelist{xkeyval.tex} \fi % \end{macrocode} % \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} % \changes{v2.5f}{2006/11/18}{Added \texttt{XKV@tkey} and \texttt{XKV@rm} to solve bugs} % \changes{v2.5g}{2006/12/19}{Removed \texttt{XKV@rm} again on user request} % \changes{v2.6b}{2012/10/14}{Added \texttt{CurrentOption} to fix class options not being % removed from \cs{@unusedoptionlist} when \cs{setkeys} is nested in \cs{ProcessOptionsX}} % \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@tkey,XKV@na,% ifXKV@st,ifXKV@pl,ifXKV@knf,CurrentOption}\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} \long\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}}{% \long\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} % \changes{v2.5f}{2006/11/18}{Added reset of \cs{CurrentOption}} % \changes{v2.5g}{2006/12/19}{Avoid reset of \cs{XKV@rm} in nested \cs{setkeys} commands} % Workhorse for |\setkeys|. % \begin{macrocode} \long\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, but only for the outermost level of % |\setkeys|. % \begin{macrocode} \ifnum\XKV@depth=\z@\let\XKV@rm\@empty\fi % \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}% \let\CurrentOption\@empty } % \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} \long\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.} % \changes{v2.5g}{2006/12/19}{Removed \cs{global} again for consistent % approach of \cs{XKV@rm} and to allow groups to keep \cs{XKV@rm} local} % \meta{key}|=|\meta{value}|=#3\@nil|\\ % Split key name and value (if present). If |#3| non-empty, there was % no |=|\meta{value}. % \begin{macrocode} \long\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 \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} % \changes{v2.7a}{2014/12/03}{Removed erroneous \cs{@empty}} % \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} \long\def\XKV@replacepointers#1{% \let\XKV@tempa\@empty \let\XKV@resa\@empty \XKV@r@placepointers#1\usevalue\@nil } \long\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 % % \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} [2022/06/16 v2.9 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} % \changes{v2.8}{2020/11/20}{Removed path from search for options of the documentclass} % 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@base.\filename@ext }{}{\edef\XKV@documentclass{\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|. % \changes{v2.9}{2022/06/16}{Fix for package options with braces} % \begin{macrocode} \def\XKV@useoption#1{% \def\XKV@resa{#1}% \XKV@ifundefined{ver@xkvltxp.sty}{}{% \@onelevel@sanitize\XKV@resa }% \@expandtwoargs\@removeelement{\expandafter\@remove@eq@value\XKV@resa=\@nil}% {\@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 % % \end{macrocode} % \subsection{\texttt{keyval.tex}} % \changes{v1.4}{2004/08/24}{Added \pf{keyval} primitives} % \changes{v2.6 }{2008/08/10}{Added \cs{KV@def} to \texttt{keyval.tex} % as it is used by some packages} % 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{% \long\def\KV@@sp@def##1##2{% \futurelet\XKV@resa\KV@@sp@d##2\@nil\@nil#1\@nil\relax##1}% \long\def\KV@@sp@d{% \ifx\XKV@resa\@sptoken \expandafter\KV@@sp@b \else \expandafter\KV@@sp@b\expandafter#1% \fi}% \long\def\KV@@sp@b#1##1 \@nil{\KV@@sp@c##1}% } \XKV@tempa{ } \long\def\KV@@sp@c#1\@nil#2\relax#3{\XKV@toks{#1}\edef#3{\the\XKV@toks}} \long\def\KV@do#1,{% \ifx\relax#1\@empty\else \KV@split#1==\relax \expandafter\KV@do\fi} \long\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} \def\KV@def#1#2[#3]{% \long\@namedef{KV@#1@#2@default\expandafter}\expandafter {\csname KV@#1@#2\endcsname{#3}}% \long\@namedef{KV@#1@#2}##1} % % \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}% } % % \end{macrocode} % \subsection{\texttt{xkvutils.tex}} % Avoid loading |xkvutils.tex| twice. % \begin{macrocode} %<*xkvutils> \csname XKeyValUtilsLoaded\endcsname \let\XKeyValUtilsLoaded\endinput \edef\XKeyValUtilsCatcodes{% \catcode`\noexpand\@\the\catcode`\@\relax \let\noexpand\XKeyValUtilsCatcodes\relax } \catcode`\@=11\relax % \end{macrocode} % 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 \newtoks\XKV@tempa@toks % \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} % \changes{v2.6 }{2008/08/10}{protecting assignments from \#} % \changes{v2.6a}{2008/08/13}{Use private scratch register} % \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{% \XKV@tempa@toks{#1}\edef#2{\the\XKV@tempa@toks}% \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} % \changes{v2.6 }{2008/08/10}{protecting assignments from \#} % \changes{v2.6a}{2008/08/13}{Use private scratch register} % \meta{cmd}\marg{function}\meta{entry}|,|\\ % Looping macro. % \begin{macrocode} \long\def\XKV@f@r#1#2#3,{% \XKV@tempa@toks{#3}\edef#1{\the\XKV@tempa@toks}% \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} % \changes{v2.6 }{2008/08/10}{protecting assignments from \#} % \changes{v2.6a}{2008/08/13}{Use private scratch register} % \meta{macro}\marg{content}\\ % Adds \meta{content} to \meta{macro} without expanding it. % \begin{macrocode} \long\def\XKV@addtomacro@n#1#2{% \XKV@tempa@toks\expandafter{#1#2}% \edef#1{\the\XKV@tempa@toks}% } % \end{macrocode} % \end{macro} % \begin{macro}{\XKV@addtomacro@o} % \changes{v2.6 }{2008/08/10}{protecting assignments from \#} % \changes{v2.6a}{2008/08/13}{Use private scratch register} % \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\XKV@addtomacro@n\expandafter#1\expandafter{#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 `\%'} % \changes{v2.6 }{2008/08/10}{protecting assignments from \#} % \changes{v2.6a}{2008/08/13}{Use private scratch register} % \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\XKV@tempa@toks\expandafter{#3}% \expandafter\endgroup\expandafter\toks@\expandafter{\the\XKV@tempa@toks}% \edef#3{\the\toks@}% } % \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} \long\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}} % \changes{v2.6 }{2008/08/10}{protecting assignments from \#} % \changes{v2.6a}{2008/08/13}{Use private scratch register} % \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} \long\def\XKV@ch@cksanitize#1#2#3{% \XKV@tempa@toks{#1}\edef#2{\the\XKV@tempa@toks}% \@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} \long\def#2##1#3##2\@nil{% \XKV@tempa@toks{##2}\edef#2{\the\XKV@tempa@toks}% \ifx#2\@empty\else\in@false\fi }% #2#1#3\@nil \fi \XKV@tempa@toks{#1}\edef#2{\the\XKV@tempa@toks}% } % \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} % Finalize. % \begin{macrocode} \XKeyValUtilsCatcodes % % \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}% [2008/08/10 v1.5 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} % \changes{v2.6 }{2008/08/10}{Solved bug occurring with empty prefix} % \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=\ifx\XKV@prefix\@empty\else\expandafter \XKVV@t@bulate\XKV@prefix\fi=\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 } % % \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}[2014/05/25 v1.3 LaTeX2e kernel patch (HA)] % \end{macrocode} % Load utilities needed in this package. % \begin{macrocode} \input xkvutils % \end{macrocode} % Start redefining internal \LaTeX\ macros. % \begin{macrocode} \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 } % \end{macrocode} % \begin{macro}{\@fileswith@pti@ns} % \changes{v1.3}{2014/05/25}{Added code to remove spaces around options} % \begin{macrocode} \def\@fileswith@pti@ns#1[#2]#3[#4]{% \XKV@sp@deflist\XKV@resb{#2}% \ifx#1\@clsextension \ifx\@classoptionslist\relax \let\@classoptionslist\XKV@resb \def\reserved@a{% \@onefilewithoptions#3[#2][#4]#1% \@documentclasshook}% \else \def\reserved@a{% \@onefilewithoptions#3[#2][#4]#1}% \fi \else \def\reserved@b##1,{% \ifx\@nil##1\relax\else \ifx\relax##1\relax\else \noexpand\@onefilewithoptions##1% [\XKV@resb][#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} % \end{macrocode} % \end{macro} % \begin{macrocode} \let\@@fileswith@pti@ns\@fileswith@pti@ns % % \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/11/25 v1.6 PSTricks specialization of xkeyval (HA)} \ifx\XKeyValLoaded\endinput\else\input xkeyval \fi \else \ProvidesFile{pst-xkey.tex} [2005/11/25 v1.6 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}} % \changes{v2.5e}{2005/11/25}{Added \cs{ignorespaces} as in \texttt{pstricks.tex}} % \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]#2{\setkeys+[psset]{#1}{#2}\ignorespaces} % \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 % % \end{macrocode} % \subsection{\texttt{pst-xkey.sty}} % Initialize the package. % \begin{macrocode} %<*pxklatex> \NeedsTeXFormat{LaTeX2e}[1995/12/01] \ProvidesPackage{pst-xkey} [2005/11/25 v1.6 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 % % \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 % % %<*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://www.tug.org/TUGboat/tb25-2/tb81adriaens.pdf}. \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} % % %<*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 3}} \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} % % %<*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 4}} \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} % % %<*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} % % %<*xkvecb> \ProvidesClass{xkvecb} %% pass any unknown option to article \DeclareOptionX{keyviii}{\def\keyviii{#1}} \DeclareOptionX*{\PassOptionsToClass{\CurrentOption}{article}} \ProcessOptionsX* %% load article \LoadClass{article} % % %<*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} % % %<*xkvesb> \ProvidesPackage{xkvesb} \let\keyiii\@empty \let\keyiv\@empty \let\keyv\@empty %% use multiple families to define options \DeclareOptionX[xkvesb]{keyiii}{\def\keyiii{#1}} \DeclareOptionX[xkvesb]{keyiv}{\def\keyiv{#1}} %% define \keyv as \CurrentOption \DeclareOptionX*{\let\keyv\CurrentOption} %% execute options in multiple families \ExecuteOptionsX[xkvesb]{keyiii={test 3}} %% process options in multiple families %% do not set keyiii \ProcessOptionsX[xkvesb][keyiii] % % %<*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 % % %<*preamble> \usepackage{url} \usepackage{xkeyval} \usepackage{fourier} \usepackage{xcolor} \usepackage[multiple]{footmisc} \usepackage{pst-text} \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 \AtBeginDocument{\hypersetup{linkcolor=black, citecolor=black, urlcolor=black}} % % %<*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}, title = {The {\LaTeX} Companion}, edition = 2, note = {With Johannes Braams, David Carlisle, and Chris Rowley}, series = {Tools and Techniques for Computer Typesetting}, publisher = {Addison-Wesley}, address = {Boston, Massachusetts}, year = 2004, pagenums = {1120}, bibliography = {yes}, index = {yes}, isbn = {0-201-36299-6} } @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}} } %