% Copyright 2018-2026 by Romano Giannetti
% Copyright 2015-2026 by Stefan Lindner
% Copyright 2013-2026 by Stefan Erhardt
% Copyright 2007-2026 by Massimo Redaelli
%
% This file may be distributed and/or modified
%
% 1. under the LaTeX Project Public License and/or
% 2. under the GNU Public License.
%
% See the files gpl-3.0_license.txt and lppl-1-3c_license.txt for more details.

\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{ctikzmanutils}[2026/02/15 utilities for formatting the circuitikz manual]
\RequirePackage{ifthen}
\RequirePackage{iftex}
\RequirePackage{etoolbox}% easier lwarp support
\RequirePackage{listings}
\RequirePackage{ragged2e}
\RequirePackage{textcomp}
\RequirePackage{booktabs}
\renewcommand{\arraystretch}{1.2}
\RequirePackage{a4wide}	% smaller borders
\RequirePackage{titling}
\RequirePackage{titlesec}
% clear page on section break
\newcommand{\sectionbreak}{\clearpage}
\setcounter{secnumdepth}{4}
\setcounter{tocdepth}{4}
% for some example we need them...
\usetikzlibrary{calc, fit, decorations, decorations.pathmorphing, tikzmark}
\RequirePackage{upgreek}

%
% Example definitions using `enverb`
%
\RequirePackage{enverb,varwidth}
\newcommand*\ctikz@ex@lstopts{} % collect options meant for lstlisting
\newcommand*\ctikz@ex@codeOutside{} % collect code to execute after the env
\newdimen\ctikz@ex@width % width available to the code
\newsavebox\ctikz@ex@box % temporary box register
% handle the 'store' key.
% #1: the name of the storage
% saves the contents currently in \enverbBody to the named storage.
\newcommand*\ctikz@ex@dostore[1]
  {%
    \@ifundefined{ctikz@ex@storage@#1}%
      {\global\expandafter\let\csname ctikz@ex@storage@#1\endcsname\@empty}%
      {}%
    \expandafter\gappto\csname ctikz@ex@storage@#1\expandafter\endcsname
      \expandafter{\enverbBody}%
  }
% handle the 'restore' key.
% #1: the name of the storage
% prepends \enverbBody with the contents of the named storage.
\newcommand*\ctikz@ex@dorestore[1]
  {%
    \@ifundefined{ctikz@ex@storage@#1}
      {\PackageError{ctikz}{Unknown storage #1}{}}%
      {%
        \epreto\enverbBody
          {%
            \unexpanded\expandafter\expandafter\expandafter
              {\csname ctikz@ex@storage@#1\endcsname}%
          }%
      }%
  }
\ekvdefinekeys{ctikz/examples}
  {
    % pos=<t|b|l>
    %   where to output the results
    %     t: on top of the code
    %     b: below the code
    %     l: left of the code
     choice-store pos       = \ctikz@ex@pos{t,b,l}
    ,initial      pos       = l
    % hsep=<dimen>
    %   how much separation to put between the results and the code for pos=l
    ,dimen        hsep      = \ctikz@ex@hsep
    ,initial      hsep      = 1.5\columnsep
    % vsep=<dimen>
    %   how much separation to put between the results and the code for pos=t/b
    ,dimen        vsep      = \ctikz@ex@vsep
    ,initial      vsep      = \bigskipamount
    % aboveskip=<dimen>
    %   how much space to put above the environment
    ,dimen        aboveskip = \ctikz@ex@aboveskip
    ,initial      aboveskip = \medskipamount
    % belowskip=<dimen>
    %   how much space to put below the environment
    ,dimen        belowskip = \ctikz@ex@belowskip
    ,initial      belowskip = \medskipamount
    % width=<dimen> (late evaluation)
    %   the width of the results box for box=varwidth/minipage, if this is 0pt
    %   the default values will be
    %     pos=l: 0.5\linewidth
    %     pos=t/b: \linewidth
    ,store        width     = \ctikz@ex@reswd
    ,initial      width     = 0pt
    % box=<hbox|varwidth|minipage|default>
    %   the type of box put around the results box (not visually but how to
    %   determine the width)
    %     hbox: simply use a \hbox (so natural width, no \par, no vertical
    %       material)
    %     varwidth: Use a `varwidth` environment around it
    %     minipage: Use a `minipage` environment around it
    %     default: the used boxing mechanism depends on pos:
    %       pos=l: hbox
    %       pos=t/b: minipage
    ,choice-store box       = \ctikz@ex@boxtype
      {hbox=h, varwidth=v, minipage=m, default=d}
    ,initial      box       = default
    % varwidth=[<t|true|f|false>]
    %   backwards compatibility, sets box=varwidth without a value or with
    %   true/t, sets box=default with false/f.
    ,nmeta        varwidth  = box=varwidth
    ,choice       varwidth  =
      {
        true=\ekvmorekv{box=varwidth}, t=\ekvmorekv{box=varwidth},
        false=\ekvmorekv{box=default}, f=\ekvmorekv{box=default}
      }
    % only code=[<true|false>]
    %   true/-NoValue-: there'll be no results box
    %   false: revert the setting
    ,boolTF       only code = \ctikz@ex@onlycodeTF
    % exec outside=[<true|false>]
    %   true/-NoValue-: the code will be executed outside the environment (using
    %     the generic env/<env>/after hook).
    %   false: revert this setting
    %   This will also call 'only code' with the same value!
    ,boolTF       exec outside = \ctikz@ex@execOutsideTF
    ,also meta    exec outside = {only code={#1}}
    ,also nmeta   exec outside = only code
    % store=<name>
    %   if used the code will be stored in a named storage for later use (see
    %   'restore'). Multiple environments using the same storage name will
    %   result in the code being appended to the existing stored code in this
    %   storage.
    ,dataT        store     = \ctikz@ex@store
    % restore=<name>
    %   restore the code of the named storage, meaning it'll be prepended to the
    %   code of this environment for the results box (but not for the listing!)
    ,dataT        restore   = \ctikz@ex@restore
    % clear storage=<name>
    %   forget the contents of the named storage (handled on the spot, so a key
    %   combination `store=foo, clear storage=foo` would first clear `foo` and
    %   then store the environment contents into `foo` after the environment was
    %   processed.
    ,code         clear storage =
      \global\expandafter\let\csname  ctikz@ex@storage@#1\endcsname\ctikz@undef
    % dollar=[<true|false>]
    %   Whether to fix the dollar category code while code is executed. We set
    %   the boolean globally but if used it's turned to false again in the
    %   after-block. Will only take effect during lwarp's HTML creation.
    ,gboolTF      dollar    = \ctikz@ex@dollarTF
    % collect unknown keys for lstlisting
    ,unknown      code      = \appto\ctikz@ex@lstopts{,#1={#2}}
    ,unknown      noval     = \appto\ctikz@ex@lstopts{,#1}
  }
% wrap enverbExecute to handle 'dollar=true'
\newcommand*\ctikz@ex@execute
  {%
    \ctikz@ex@dollarTF{\pushdollarcat}{}%
    \enverbExecute
    \ctikz@ex@dollarTF{\popdollarcat}{}%
  }
% handle the boxing inside the results box
% #1: default box type if 'box=default'
% This will call \ctikz@ex@fbox with the argument based on the current
% box-setting.
\newcommand*\ctikz@ex@handleboxtype[1] % #1 = default case
  {%
    \if\ctikz@ex@boxtype d%
      \def\ctikz@ex@boxtype{#1}%
    \fi
    \if\ctikz@ex@boxtype h%
      \ctikz@ex@fbox{\ctikz@ex@execute}%
    \else\if\ctikz@ex@boxtype v%
      \ctikz@ex@fbox
        {\begin{varwidth}{\dimeval\ctikz@ex@reswd}\ctikz@ex@execute\end{varwidth}}%
    \else\if\ctikz@ex@boxtype m%
      \ctikz@ex@fbox
        {\begin{minipage}{\dimeval\ctikz@ex@reswd}\ctikz@ex@execute\end{minipage}}%
    \else
      \PackageError{ctikz}{Unknown example box type \ctikz@ex@boxtype}{}%
    \fi\fi\fi
  }
% print the result of the collected code
% Control will first be given to \ctikz@ex@handleboxtype which will call
% \ctikz@ex@fbox eventually. But first we need to set a suitable default width
% for 'width=0pt' (or anything that evaluates to 0pt inside \dimexpr).
\newcommand*\ctikz@ex@printresult
  {%
    \if\ctikz@ex@pos l%
      \ifdim\dimeval\ctikz@ex@reswd=\z@
        \def\ctikz@ex@reswd{.5\linewidth}%
      \fi
      \ctikz@ex@handleboxtype{h}%
    \else
      \ifdim\dimeval\ctikz@ex@reswd=\z@
        \def\ctikz@ex@reswd{\linewidth}%
      \fi
      \ctikz@ex@handleboxtype{m}%
    \fi
  }
% output a vcentered framed box for the results
% additionally the output (together with the framed box) will be in the box
% register \ctikz@ex@box
% #1: the contents to box up (should be \enverbExecute nested in a suitable box
%     construct based on the 'box' key).
\newcommand*\ctikz@ex@fbox[1]
  {%
    \sbox\ctikz@ex@box
      {%
        % fboxsep=6pt, fboxrule=0.8pt -> 13.6pt less for linewidth
        \advance\linewidth-13.6pt
        \ctikz@ex@restore\ctikz@ex@dorestore
        \ignorespaces#1\unskip
      }%
    \sbox\ctikz@ex@box
      {%
        \fboxsep=6pt
        \fboxrule=0.8pt
        \rlap{\fcolorbox{cyan}{white}{\phantom{\usebox\ctikz@ex@box}}}%
        \kern\fboxrule
        \kern\fboxsep
        \usebox\ctikz@ex@box
      }%
    $\vcenter{\copy\ctikz@ex@box}$% vcenter matches minipage [c]
  }
% output a vcentered code listing if pos=l, otherwise output a code listing
\newcommand*\ctikz@ex@printcode
  {%
    \ctikz@ex@onlycodeTF{\@firstofone}%
      {%
        \if\ctikz@ex@pos l% only box up the code if necessary
          \expandafter\@secondoftwo
        \fi
        \@secondoftwo{\parbox[c]{\ctikz@ex@width}}%
      }%
      {%
        \ExpandArgs{ne}\enverbListing{lstlisting}%
          {[%
             style=expl-code
            ,aboveskip=6pt% we don't want skips but need to compensate listings
            ,belowskip=0pt%
            \unexpanded\expandafter{\ctikz@ex@lstopts}%
          ]}%
      }%
  }
% \begin{ctikzExample}[<settings>]
% the front level environment. <settings> can be any keys as described inside
% \ekvdefinekeys{ctikz/examples}. The following paragraph will be indented if
% there's a blank line between \end{ctikzExample} and the first line of the
% paragraph (as with lists in LaTeX).
\newenvironment{ctikzExample}
  {\enverb{key-set=ctikz/examples, oarg-not-enverb, more-ignore=0}}
  {%
    \par
    \vskip\ctikz@ex@aboveskip
    \noindent
    \ctikz@ex@width=\linewidth
    \ctikz@ex@onlycodeTF
      {}%
      {%
        \if\ctikz@ex@pos b
        \else
          \ctikz@ex@printresult
          \if\ctikz@ex@pos t
            \par
            \vskip\ctikz@ex@vsep
            \noindent
          \else
            \hfill
            \advance\ctikz@ex@width-\wd\ctikz@ex@box
            \advance\ctikz@ex@width-\ctikz@ex@hsep
          \fi
        \fi
      }%
    \ctikz@ex@printcode
    \ctikz@ex@onlycodeTF
      {}%
      {%
        \if\ctikz@ex@pos b
          \par
          \vskip\ctikz@ex@vsep
          \noindent
          \ctikz@ex@printresult
        \fi
      }%
    \par
    \vskip\ctikz@ex@belowskip
    \ctikz@ex@store\ctikz@ex@dostore
    \ctikz@ex@execOutsideTF
      {\global\let\ctikz@ex@codeOutside\enverbBody}%
      {}%
    \@endparenv
  }
% handling of the 'exec outside' key. If there are contents inside
% \ctikz@ex@codeOutside the key was used and we should rerun an \enverbExecute
% (which only works on \enverbBody contents, so we restore those outside of the
% environment).
\AddToHook{env/ctikzExample/after}
  {%
    \ifx\ctikz@ex@codeOutside\@empty
    \else
      \let\enverbBody\ctikz@ex@codeOutside
      \global\let\ctikz@ex@codeOutside\@empty
      \ctikz@ex@execute
    \fi
    \ctikz@ex@dollarTF{\global\let\ctikz@ex@dollarTF\@secondoftwo}{}%
  }
%
% --- Style for the code part  ---
% cyan block, no numbers
%
\lstdefinestyle{expl-code}{
  language=[LaTeX]TeX,
  basicstyle=\small\ttfamily,
  columns=fullflexible,
  keepspaces=true,
  breaklines=true,
  showstringspaces=false,
  tabsize=3,
  numbers=none,
  frame=single, % using none make framesep=0 which is ugly
  framerule=0pt,% no frame but keep separation
  framesep=4pt,
  backgroundcolor=\color{cyan!10},
  xleftmargin=0.5em,
  aboveskip=\bigskipamount,
  belowskip=\bigskipamount,
}
\lstset{style=expl-code}

% in lwarp's warpingprint-false case we need to temporarily change the category
% code of $ to be mathshift again. These macros will do that in that case
% (they're redefined in `ctikz-lwarp-late.tex`).
\newcommand*\pushdollarcat{}
\newcommand*\popdollarcat{}

\newcommand{\email}[1]{\href{mailto:#1}{#1}}
\long\def\comment#1{}

\RequirePackage{framed}
\RequirePackage{xtab}
\RequirePackage{hyperref}
\hypersetup{
    pdftitle={CircuiTikZ \pgfcircversion\ - manual}, % title
    pdfauthor={Massimo Redaelli, Stefan Lindner, Stefan Erhardt, Romano Giannetti}, % authors
    pdfsubject={CircuiTikZ manual},   % subject of the document
    pdfkeywords={},   % list of keywords
    colorlinks=true,  % false: boxed links; true: colored links
    linkcolor=blue,   % color of internal links
    citecolor=blue,   % color of links to bibliography
    filecolor=blue,   % color of file links
    urlcolor=blue     % color of external links
}

% There are a lot of boxes in the document; let's try to give TeX
% a bit of leverage... do not use parindent (which looks strange between examples)
% and add stretch between paragraph, to avoid a lot of sections and subsections
% starting at the end of the page.
\parindent=0pt
\parskip=4pt plus 6pt minus 2pt
%
% names
%
\def\TikZ{Ti\emph{k}Z}
\def\Circuitikz{Circui\TikZ}
\def\ConTeXt{Con\TeX t}
%
% Start of special macros for component descriptions
%
% draw the shape without affecting anything
\newcommand{\drawphantomshape}[1] {%
    {\tikz [overlay, color=blue] \path (0,0) node[#1]{};}
}
%% New circuit description macros
\newcommand{\twopartbox}[2]{%
    \leavevmode\null\par\noindent\fbox{\parbox[c]{0.32\linewidth}{#1}\hfill
    \parbox[c]{0.66\linewidth}{\RaggedRight\hbadness=9500 #2}\par\noindent}%
}
% filling color for filled-enabled component
\colorlet{fillcol}{cyan!30!white}
% find the class for the element. Thanks to Symbol 1
% https://tex.stackexchange.com/a/501389/38080
\def\checkclass#1{%
    \csname pgf@sh@ma@#1\endcsname
    \ifdefined\ctikzclass
        Class: \texttt{\ctikzclass}.%
    \else
        No class.%
    \fi
}
% description of a node component:
% optional star for fillable
% optional: scale of the component in the entry
% mandatory  shape name, description, node text:
% optional between (): anchor specification list
% optional between []: internal nodes specification list
\NewDocumentCommand{\circuitdesc}{s O{1} m m m d() d[]}
{
    \twopartbox{%
        \begin{circuitikz}[]
            \IfBooleanTF{#1}{%
                \draw (0,0) node[#3,scale=#2, fill=fillcol](N){#5};
                }{
                % if it's non-fillable, red should not go through
                \draw (0,0) node[#3,scale=#2,
                % fill=red
                ](N){#5};
            }
            \IfValueT{#6}{%
                \foreach \n/\a/\d in {#6} \path(N.\n) \showcoord(\n)<\a:\d>;
            }
            \IfValueT{#7}{%
                \foreach \n/\a/\d in {#7} \path(N-\n) \showcoordb(N-\n)<\a:\d>;
            }
        \end{circuitikz}%
        }{\sloppy
        {#4, type: node\IfBooleanT{#1}{, fillable}%
        } (\texttt{node[\detokenize{#3}]\IfValueT{#7}{(N)}\{\detokenize{#5}\}}). \index{#3}%
        \checkclass{N}%
    }%
}
% description of a path-style bipole component:
% optional: main name, if different from above
% mandatory component name
% optional between <>: shapename, if note "nodeshape"
% mandatory description, comma separated alias
% optional between (): anchor specification list
% optional between []: internal nodes specification list
%                                    1 2 3 4   5 6 7   8
\NewDocumentCommand{\circuitdescbip}{s o m d<> m m d() d[]}
{%
    \index{#3}%
    \foreach \i in {#6} {\index{\i|seealso{#3}} }%
    \twopartbox{%
        \begin{circuitikz}
        \IfBooleanTF{#1}{%
            \draw (0,0) to[#3, name=B, fill=fillcol] (2,0);
            }{
            % if it's non-fillable, red should not go through
            \draw (0,0) to[#3, name=B,
            %fill=red
            ] (2,0);
        }
        \IfValueT{#7}{%
                \foreach \n/\a/\d in {#7} \path(B.\n) \showcoord(\n)<\a:\d>;
            }
            \IfValueT{#8}{%
                \foreach \n/\a/\d in {#8} \path(B-\n) \showcoordb(B-\n)<\a:\d>;
            }
        \end{circuitikz}%
        }{\sloppy
        \texttt{\textbf{#3}}: #5, \texttt{type: path-style\IfBooleanT{#1}{, fillable}%
            \IfValueT{#8}{, \texttt{name=B}}%
            \IfValueTF{#4}{, nodename: #4.}{%
            \IfValueTF{#2}{, nodename: #2shape.%\drawphantomshape{#2shape}%
            }{, nodename: #3shape.%\drawphantomshape{#3shape}%
        }}%
        }
        \ifthenelse{\equal{#6}{}}{ }{ Aliases: \texttt{#6}. }\checkclass{B}%
    }%
}
% command to add the content to the index
\NewDocumentCommand{\IndexKey}{O{#2} m}{%
    \index{\detokenize{#1}|textit}\texttt{#2}%
}

%new environment for grouping descriptions
\newenvironment{groupdesc}{\medskip\begingroup}{\endgroup\par\medskip\par\noindent}

% command to show anchors: (name)<angle>
% usage in path: \path (anchor) \coord(anchor)<60>
\makeatletter % we use the internal circuitikz base length
\def\showcoord(#1)<#2:#3>{%
    node[circle, red, draw, inner sep=1pt,pin={%
        [red, inner sep=0.5pt, font=\small,
        pin distance=#3\pgf@circ@Rlen, pin edge={red, }%
    ]#2:#1}](#1){}}
\def\showcoordb(#1)<#2:#3>{%
    node[circle, blue, draw, inner sep=1pt,pin={%
        [blue, inner sep=0.5pt, font=\small,
        pin distance=#3\pgf@circ@Rlen, pin edge={blue, }%
    ]#2:#1}](#1){}}
    \def\showcoordwc[#1](#2)<#3:#4>{%
    node[circle, #1, draw, inner sep=1pt,pin={%
        [#1, inner sep=0.5pt, font=\small,
        pin distance=#4\pgf@circ@Rlen, pin edge={#1, }%
    ]#3:#2}](#2){}}
\makeatother
% show anchors of a node component:
% optional: options of the circuitikz environment
% mandatory  node spec, node text
% optional between (): anchor specification list
\NewDocumentCommand{\showanchors}{O{} m m d()}
{
        \begin{circuitikz}[#1]
                \draw (0,0) node[#2](N){#3};
            \IfValueT{#4}{%
                \foreach \n/\a/\d in {#4} \path(N.\n) \showcoord(\n)<\a:\d>;
            }
        \end{circuitikz}%
}


\newcommand{\geolrcoord}[2][]{\showanchors[#1]{#2}{text}(north/90/0.4, north east/45/0.4, east/0/0.4,
    south east/-45/0.4,
    south/-90/0.4, south west/-135/0.4, west/180/0.4, north west/135/0.4,
    left/160/0.4, right/30/0.4, center/-120/0.3
    )
}

\newcommand{\geocoord}[2][]{\showanchors[#1]{#2}{text}(north/90/0.4, north east/45/0.4, east/0/0.4,
    south east/-45/0.4,
    south/-90/0.4, south west/-135/0.4, west/180/0.4, north west/135/0.4,
    center/-120/0.3
    )
}
