summaryrefslogtreecommitdiff
path: root/graphics/pgf/contrib/circuitikz/tex/pgfcircutils.tex
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2021-06-16 03:01:15 +0000
committerNorbert Preining <norbert@preining.info>2021-06-16 03:01:15 +0000
commit2c0c7988beae1efa245bfb9fec0a25d41d88047d (patch)
treeeb29ed898d242ae356a592081c53f11dbd751870 /graphics/pgf/contrib/circuitikz/tex/pgfcircutils.tex
parent2faf2507ca4d1d6d153f4c2b4c4c78479d459f06 (diff)
CTAN sync 202106160301
Diffstat (limited to 'graphics/pgf/contrib/circuitikz/tex/pgfcircutils.tex')
-rw-r--r--graphics/pgf/contrib/circuitikz/tex/pgfcircutils.tex257
1 files changed, 257 insertions, 0 deletions
diff --git a/graphics/pgf/contrib/circuitikz/tex/pgfcircutils.tex b/graphics/pgf/contrib/circuitikz/tex/pgfcircutils.tex
index ac87e08304..86732077b0 100644
--- a/graphics/pgf/contrib/circuitikz/tex/pgfcircutils.tex
+++ b/graphics/pgf/contrib/circuitikz/tex/pgfcircutils.tex
@@ -120,4 +120,261 @@
}
\long\def\ctikzsubcircuitactivate#1{\csname #1@setanchors\endcsname}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Basic utility macros
+%%
+%% Functions provided here are:
+%% \pgf@circ@ifempty{<argument>}{<true>}{<false>}
+%% Tests whether <argument> is completely empty.
+%% \pgf@circ@ifblank{<argument>}{<true>}{<false>}
+%% Tests whether <argument> is either empty or only contains spaces.
+%% \pgf@circ@trimspaces@do{<argument>}{<next>}
+%% Trims at most one space from either end of <argument> and forwards the
+%% result to <next> as <next>{<trimmed argument>}
+
+% these two are pretty standard code
+\long\def\pgf@circ@ifempty#1%
+ {%
+ \if\relax\detokenize{#1}\relax
+ \expandafter\pgfutil@firstoftwo
+ \else
+ \expandafter\pgfutil@secondoftwo
+ \fi
+ }
+\long\def\pgf@circ@ifblank#1%
+ {%
+ \if\relax\detokenize\expandafter{\pgfutil@gobble#1.}\relax
+ \expandafter\pgfutil@firstoftwo
+ \else
+ \expandafter\pgfutil@secondoftwo
+ \fi
+ }
+
+% \pgfutil@trimspaces needs two expansions. The first expansion we'll do during
+% the definition.
+\def\pgf@circ@trimspaces@do#1%
+ {%
+ \def\pgf@circ@trimspaces@do##1%
+ {\expandafter\pgf@circ@trimspaces@do@\expandafter{#1}}%
+ }
+\expandafter\pgf@circ@trimspaces@do\expandafter{\pgfutil@trimspaces{#1}}
+\def\pgf@circ@trimspaces@do@#1#2{#2{#1}}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% list handling
+%%
+%% Contribution by Jonathan P. Spratte (blame him!)
+%%
+%% The list implementation here has a few limitations. Those are:
+%% 1. not long, so no \par in the lists (but many used functions in pgfutil
+%% aren't long as well)
+%% 2. list elements can't contain a Q with category code 3 (but the used
+%% function \pgfutil@trimspaces doesn't support them as well, and this
+%% should be a very rare token anyway)
+%% 3. list elements can't contain the token \pgf@circ@set@list as that is used
+%% as the end marker
+%% 4. currently these lists are meant for numeric data (hence only
+%% \pgf@circ@if@num@in@list is provided as a test), as a result there is
+%% another limitation for the data here. If the list element contains no
+%% hyphen '-', the element will be stored without further processing
+%% 'as-is' (well, after trimming spaces). If there is a hyphen we assume
+%% well-behaved input data and will interpret this as a num-range without
+%% further tests.
+%%
+%% Functions provided here are:
+%% \pgf@circ@set@list<macro>{<csv-list>}
+%% Parses the <csv-list> and stores the result inside <macro> (local
+%% assignment). If a num-range given as <start - stop> (with or without
+%% spaces) is found it will be expanded to <start>,<start+1>,...,<stop>.
+%% \pgf@circ@if@num@in@list<macro>{<value>}{<true>}{<false>}
+%% Checks whether <value> (numeric value, evaluated once with \numexpr) is
+%% found inside the list stored in <macro>. There are two special cases: If
+%% <macro> is undefined <false> is executed. If the list contains only one
+%% element and that is `all' <true> is executed.
+
+% set the catcode of our marker
+\chardef\pgf@circ@temp=\the\catcode`\Q
+\catcode`\Q=3
+
+% lists will have the structure
+% <marker><element 1><marker>...<element n><marker>
+% As marker we use a Q with category 3. Under the assumption that no list
+% element does ever contain that token we can set the elements without braces,
+% allowing us to use \pgfutil@in@ to search for elements (see above). The other
+% token that isn't allowed to show up in the list is \pgf@circ@set@list, that we
+% use as another marker during parsing.
+% The other big restriction in this implementation is that lists can't contain a
+% \par (but \pgfutil@in@ doesn't support that anyway so there is not much
+% sense in supporting it here)
+\pgfutil@protected\def\pgf@circ@set@list#1#2%
+ {%
+ % clear the error flag
+ \let\pgf@circ@error@marker\pgf@circ@undefined
+ % set the list
+ \edef#1%
+ {Q\pgf@circ@set@list@sanitize#2,\pgf@circ@set@list,\pgf@circ@set@list}%
+ % there was an error, throw the error message, recovery was already done by
+ % ignoring the offending elements.
+ \ifx\pgf@circ@error@marker\relax
+ \begingroup
+ \newlinechar`\^^J
+ \pgfutil@packageerror{circuitikz}
+ {%
+ Unallowed marker found in list^^J%
+ \pgfutil@unexpanded{#2}.^^J%
+ Offending elements were ignored.%
+ }
+ {Lists can't contain a Q with category code 3}%
+ \endgroup
+ \fi
+ }
+% just a utility for the <marker> test
+\def\pgf@circ@set@list@gobbletomarker#1Q{}
+% quick way to check whether list parsing is done by gobbling up to a marker, in
+% this case the marker is \pgf@circ@set@list
+\def\pgf@circ@set@list@sanitize@checkend#1\pgf@circ@set@list{}
+% will only be called after the last element is handled, will gobble the
+% remainder of the current sanitizing step
+\def\pgf@circ@set@list@sanitize@end\pgf@circ@set@list#1\pgf@circ@set@list{}
+% grabs the next list element, checks whether we're done, and if not sanitizes
+% it (meaning stripping spaces from either end and placing the <marker>).
+\def\pgf@circ@set@list@sanitize#1,%
+ {%
+ \pgf@circ@set@list@sanitize@checkend
+ #1\pgf@circ@set@list@sanitize@end\pgf@circ@set@list
+ \pgf@circ@set@list@sanitize@a{#1}%
+ }
+% testing whether a list element contains the used <marker> expandably, if it
+% does set the flag, else continue sanitizing.
+\def\pgf@circ@set@list@sanitize@a#1%
+ {%
+ \expandafter\pgf@circ@ifempty\expandafter
+ % if this is empty no marker was found
+ {\pgf@circ@set@list@gobbletomarker#1Q}
+ {%
+ \pgf@circ@ifblank{#1}
+ {}% ignore blank entries
+ {\pgf@circ@trimspaces@do{#1}\pgf@circ@set@list@sanitize@b}%
+ }
+ {%
+ % panic, there was a marker found in a list element. We'll recover by
+ % ignoring the current element after setting a flag. When we do
+ % \csname ...\endcsname on an undefined macro name TeX will let that
+ % macro to relax and we exploit this to expandable set a flag and
+ % gobbling the result.
+ \expandafter\pgfutil@gobble\csname pgf@circ@error@marker\endcsname
+ }%
+ % get the next element
+ \pgf@circ@set@list@sanitize
+ }
+% we'll protect any element from further expanding using \unexpanded and place
+% the marker after the element, and ignore empty/blank elements
+\def\pgf@circ@set@list@sanitize@b#1%
+ {%
+ \expandafter\pgf@circ@ifempty\expandafter
+ % if this is empty no hyphen is found
+ {\pgf@circ@gobbletohyphen#1-}
+ {\pgfutil@unexpanded{#1}Q}
+ {\pgf@circ@set@list@parse@range{#1}}%
+ }
+\def\pgf@circ@gobbletohyphen#1-{}
+\def\pgf@circ@set@list@parse@range#1{\pgf@circ@set@list@parse@range@a#1Q}
+\def\pgf@circ@set@list@parse@range@a#1-#2Q%
+ {%
+ \expandafter\pgf@circ@set@list@parse@range@b
+ \the\numexpr#1\expandafter Q\the\numexpr#2Q%
+ }
+\def\pgf@circ@set@list@parse@range@b#1Q#2Q%
+ {%
+ \ifnum#1<#2
+ % expand to the range from #1 to #2 (inclusive)
+ \pgf@circ@set@list@range{#1}{#2}%
+ \else
+ \ifnum#2<#1
+ % if #2 is smaller than #1 just swap the order
+ \pgf@circ@set@list@range{#2}{#1}%
+ \else
+ % last case, they are equal, so just put the result here
+ #1Q%
+ \fi
+ \fi
+ }
+\def\pgf@circ@set@list@parse@range@norange#1Q#2{\pgfutil@unexpanded{#2}Q}
+\def\pgf@circ@set@list@range#1#2%
+ {%
+ #1Q%
+ \ifnum#1<#2
+ \expandafter\pgfutil@secondoftwo
+ \fi
+ \pgfutil@gobble
+ {\expandafter\pgf@circ@set@list@range\expandafter{\the\numexpr#1+1}{#2}}%
+ }
+
+% flag for special value
+\def\pgf@circ@all@flag{QallQ}
+\pgfutil@protected\def\pgf@circ@if@num@in@list#1#2%
+ {%
+ % test whether the list macro is defined, if it isn't result is false
+ \pgfutil@ifx\pgf@circ@undefined#1%
+ {\pgfutil@secondoftwo}
+ {%
+ % test whether the list macro is just the special value 'all', if so
+ % true, else search (and start that by evaluating a numexpr)
+ \pgfutil@ifx\pgf@circ@all@flag#1%
+ {\pgfutil@firstoftwo}
+ {%
+ \expandafter\pgf@circ@if@num@in@list@a\expandafter
+ {\the\numexpr#2}%
+ #1%
+ }%
+ }%
+ }
+% next step is expanding the list macro
+\pgfutil@protected\def\pgf@circ@if@num@in@list@a#1#2%
+ {\expandafter\pgf@circ@if@num@in@list@b\expandafter{#2}{#1}}
+% now use \pgfutil@in@ to check whether there is the searched list element
+\pgfutil@protected\def\pgf@circ@if@num@in@list@b#1#2%
+ {%
+ \begingroup
+ % put the <marker> around the number to make sure only full matches are
+ % found. \pgfutil@in@ will set \ifpgfutil@in@ to true if it finds a match
+ \pgfutil@in@{Q#2Q}{#1}%
+ \expandafter
+ \endgroup
+ \ifpgfutil@in@
+ \expandafter\pgfutil@firstoftwo
+ \else
+ \expandafter\pgfutil@secondoftwo
+ \fi
+ }
+
+% reset the catcode of Q
+\catcode`\Q=\pgf@circ@temp
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% temporary fix for old TikZ versions (remove me)
+%%
+%% All blame to Romano Giannetti for this code!
+%%
+%% This tries to be smart and provide \pgfutil@unexpanded and \pgfutil@ifx if
+%% PGF doesn't provide them.
+
+\ifx\pgfutil@unexpanded\pgf@circ@undefined
+ \ifpgfutil@format@is@context
+ \let\pgfutil@unexpanded\normalunexpanded
+ \else
+ \let\pgfutil@unexpanded\unexpanded
+ \fi
+\fi
+
+\ifx\pgfutil@ifx\pgf@circ@undefined
+ \long\def\pgfutil@ifx#1#2{%
+ \ifx#1#2%
+ \expandafter\pgfutil@firstoftwo
+ \else
+ \expandafter\pgfutil@secondoftwo
+ \fi}
+\fi
+
\endinput