summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/source/latex/xkeyval/xkeyval.dtx
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2014-06-27 00:38:59 +0000
committerKarl Berry <karl@freefriends.org>2014-06-27 00:38:59 +0000
commit81231e60a62c9f46b647f59881e9165f01e4c9e2 (patch)
treef03c83af5253780c3225086d61d779e2a7742af4 /Master/texmf-dist/source/latex/xkeyval/xkeyval.dtx
parentbf6d61e576dd9107b5e449872ce0ea965df5e673 (diff)
xkeyval
git-svn-id: svn://tug.org/texlive/trunk@34442 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/source/latex/xkeyval/xkeyval.dtx')
-rw-r--r--Master/texmf-dist/source/latex/xkeyval/xkeyval.dtx1264
1 files changed, 652 insertions, 612 deletions
diff --git a/Master/texmf-dist/source/latex/xkeyval/xkeyval.dtx b/Master/texmf-dist/source/latex/xkeyval/xkeyval.dtx
index 07ce2c46f7d..b8bb4ed4e25 100644
--- a/Master/texmf-dist/source/latex/xkeyval/xkeyval.dtx
+++ b/Master/texmf-dist/source/latex/xkeyval/xkeyval.dtx
@@ -17,6 +17,7 @@
% keyval.tex
% xkvtxhdr.tex
% pst-xkey.tex
+% xkvutils.tex
% Additional to these files, LaTeX should be able to locate
% the following files:
% xkeyval.sty
@@ -42,14 +43,14 @@
%%
%% This work consists of the file xkeyval.dtx and derived files
%% keyval.tex, xkvtxhdr.tex, xkeyval.sty, xkeyval.tex, xkvview.sty,
-%% xkvltxp.sty, pst-xkey.tex, pst-xkey.sty, xkveca.cls, xkvecb.cls,
-%% xkvesa.sty, xkvesb.sty, xkvesc.sty, xkvex1.tex, xkvex2.tex,
-%% xkvex3.tex and xkvex4.tex.
+%% 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, pst-xkey.dtx and xkeyval.dtx.
+%% xkvltxp.sty, xkvtxhdr.tex, xkvutils.tex, pst-xkey.dtx and xkeyval.dtx.
%%
% \fi
%
@@ -68,6 +69,7 @@
\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}}
@@ -182,10 +184,11 @@ macro. \PrintChangesX\PrintIndexX
% \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{3025}
+% \CheckSum{3047}
%
%\DoNotIndex{\:,\@,\@@,\@backslashchar,\@ehc,\@empty,\@expandtwoargs,
%\@for,\@forloop,\@fornoop,\@fortmp,\@gobble,\@gobbletwo,\@if,\@ifnch,
@@ -2038,13 +2041,12 @@ macro. \PrintChangesX\PrintIndexX
\catcode`\,12\relax
\catcode`\:12\relax
% \end{macrocode}
-% Initializations. This package uses a private token to avoid
-% conflicts with other packages that use \LaTeX\ scratch token registers
-% in key macro definitions (for instance, \pf{graphicx}, keys angle
-% and scale).
+% Load some basic utilities.
+% \begin{macrocode}
+\input xkvutils
+% \end{macrocode}
+% Initializations.
% \begin{macrocode}
-\newtoks\XKV@toks
-\newtoks\XKV@tempa@toks
\newcount\XKV@depth
\newif\ifXKV@st
\newif\ifXKV@sg
@@ -2058,606 +2060,13 @@ macro. \PrintChangesX\PrintIndexX
% Load \LaTeX\ primitives if necessary and provide information.
% \begin{macrocode}
\ifx\ProvidesFile\@undefined
- \message{2014/05/09 v2.6d key=value parser (HA)}
+ \message{2014/05/25 v2.7 key=value parser (HA)}
\input xkvtxhdr
\else
- \ProvidesFile{xkeyval.tex}[2014/05/09 v2.6d key=value parser (HA)]
+ \ProvidesFile{xkeyval.tex}[2014/05/25 v2.7 key=value parser (HA)]
\@addtofilelist{xkeyval.tex}
\fi
% \end{macrocode}
-% \begin{macro}{\@firstoftwo}
-% \begin{macro}{\@secondoftwo}
-% Two utility macros from the |latex.ltx| needed for executing
-% |\XKV@ifundefined| in the sequel.
-% \begin{macrocode}
-\long\def\@firstoftwo#1#2{#1}
-\long\def\@secondoftwo#1#2{#2}
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-% \begin{macro}{\XKV@afterfi}
-% \begin{macro}{\XKV@afterelsefi}
-% Two utility macros to move execution of content of a conditional
-% branch after the |\fi|. This avoids nesting conditional structures
-% too deep.
-% \begin{macrocode}
-\long\def\XKV@afterfi#1\fi{\fi#1}
-\long\def\XKV@afterelsefi#1\else#2\fi{\fi#1}
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-% \begin{macro}{\XKV@ifundefined}
-% \changes{v1.8d}{2005/01/02}{Simplified definition by using \cs{XKV@afterelsefi}}
-% \changes{v2.0}{2005/01/30}{Made none \eTeX\ version not leave \cs{relax}}
-% \marg{csname}\marg{undefined}\marg{defined}\\
-% Executes \meta{undefined} if the control sequence with name \meta{csname}
-% is undefined, else it executes \meta{defined}. This macro uses
-% \eTeX\ if possible to avoid filling \TeX's hash when checking
-% control sequences like key macros in the rest of the package.
-% The use of |\XKV@afterelsefi| is necessary here to avoid \TeX\ picking up the
-% second |\fi| as end of the main conditional when |\ifcsname| is
-% undefined. For |\XKV@afterelsefi| this |\fi| is hidden in the
-% group used to define |\XKV@ifundefined| in branch of the case that
-% |\ifcsname| is defined. Notice the following. Both versions of the
-% macro leave the tested control sequence undefined. However, the
-% first version will execute \meta{undefined} if the control sequence
-% is undefined or |\relax|, whereas the second version will only
-% execute \meta{undefined} if the control sequence is undefined. This
-% is no problem for the applications in this package.
-% \begin{macrocode}
-\ifx\ifcsname\@undefined\XKV@afterelsefi
- \def\XKV@ifundefined#1{%
- \begingroup\expandafter\expandafter\expandafter\endgroup
- \expandafter\ifx\csname#1\endcsname\relax
- \expandafter\@firstoftwo
- \else
- \expandafter\@secondoftwo
- \fi
- }
-\else
- \def\XKV@ifundefined#1{%
- \ifcsname#1\endcsname
- \expandafter\@secondoftwo
- \else
- \expandafter\@firstoftwo
- \fi
- }
-\fi
-% \end{macrocode}
-% \end{macro}
-% Check whether \pf{keyval} has been loaded and if not, load
-% \pf{keyval} primitives and prevent \pf{keyval} from being loaded
-% after \pf{xkeyval}.
-% \begin{macrocode}
-\XKV@ifundefined{ver@keyval.sty}{
- \input keyval
- \expandafter\def\csname ver@keyval.sty\endcsname{1999/03/16}
-}{}
-% \end{macrocode}
-% \begin{macro}{\@ifnextcharacter}
-% \changes{v1.4}{2004/08/24}{Added robust next character check}
-% \begin{macro}{\@ifncharacter}
-% Check the next character independently of its catcode. This will be
-% used to safely perform |\@ifnextcharacter+| and
-% |\@ifnextcharacter*|. This avoids errors in case any other package
-% changes the catcode of these characters.\\ Contributed by Donald
-% Arseneau.
-% \begin{macrocode}
-\long\def\@ifnextcharacter#1#2#3{%
- \@ifnextchar\bgroup
- {\@ifnextchar{#1}{#2}{#3}}%
- {\@ifncharacter{#1}{#2}{#3}}%
-}
-\long\def\@ifncharacter#1#2#3#4{%
- \if\string#1\string#4%
- \expandafter\@firstoftwo
- \else
- \expandafter\@secondoftwo
- \fi
- {#2}{#3}#4%
-}
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-% \begin{macro}{\XKV@for@n}
-% \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}
% \begin{macro}{\XKV@warn}
% \begin{macro}{\XKV@err}
% \begin{macro}{\KV@err}
@@ -4031,7 +3440,7 @@ macro. \PrintChangesX\PrintIndexX
%<*xkvlatex>
\NeedsTeXFormat{LaTeX2e}[1995/12/01]
\ProvidesPackage{xkeyval}
- [2014/05/09 v2.6d package option processing (HA)]
+ [2014/05/25 v2.7 package option processing (HA)]
% \end{macrocode}
% Initializations. Load |xkeyval.tex|, adjust some catcodes to define
% internal macros and initialize the |\DeclareOptionX*| working macro.
@@ -4427,6 +3836,624 @@ macro. \PrintChangesX\PrintIndexX
}
%</xkvheader>
% \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
+%</xkvutils>
+% \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
@@ -4700,7 +4727,14 @@ macro. \PrintChangesX\PrintIndexX
%% Based on latex.ltx.
%%
\NeedsTeXFormat{LaTeX2e}[1995/12/01]
-\ProvidesPackage{xkvltxp}[2004/12/13 v1.2 LaTeX2e kernel patch (HA)]
+\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}%
@@ -4736,11 +4770,15 @@ macro. \PrintChangesX\PrintIndexX
\@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
- \@temptokena{#2}%
- \xdef\@classoptionslist{\the\@temptokena}%
+ \let\@classoptionslist\XKV@resb
\def\reserved@a{%
\@onefilewithoptions#3[#2][#4]#1%
\@documentclasshook}%
@@ -4749,12 +4787,11 @@ macro. \PrintChangesX\PrintIndexX
\@onefilewithoptions#3[#2][#4]#1}%
\fi
\else
- \@temptokena{#2}%
\def\reserved@b##1,{%
\ifx\@nil##1\relax\else
\ifx\relax##1\relax\else
\noexpand\@onefilewithoptions##1%
- [\the\@temptokena][#4]\noexpand\@pkgextension
+ [\XKV@resb][#4]\noexpand\@pkgextension
\fi
\expandafter\reserved@b
\fi}%
@@ -4762,6 +4799,9 @@ macro. \PrintChangesX\PrintIndexX
\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
%</xkvltxpatch>
% \end{macrocode}