diff options
author | Karl Berry <karl@freefriends.org> | 2014-06-27 00:38:59 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2014-06-27 00:38:59 +0000 |
commit | 81231e60a62c9f46b647f59881e9165f01e4c9e2 (patch) | |
tree | f03c83af5253780c3225086d61d779e2a7742af4 /Master/texmf-dist/source/latex/xkeyval/xkeyval.dtx | |
parent | bf6d61e576dd9107b5e449872ce0ea965df5e673 (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.dtx | 1264 |
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} |