%--------------------------------------------
%
% Package pgfplots
%
% Provides a user-friendly interface to create function plots (normal
% plots, semi-logplots and double-logplots).
%
% It is based on Till Tantau's PGF package.
%
% Copyright 2007/2008/2019 by Christian Feuersänger.
%
% This program is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with this program.  If not, see <http://www.gnu.org/licenses/>.
%
%--------------------------------------------

% This file provides an interface to the
% pgfmanual.prettyprint.code.tex thing -- it allows to
%  *generate pdf crossrefs inside of codeexamples automatically*
% without any user input.
%
% Thus, you write
% \begin{codeexample}[]
% \begin{tikzpicture}[options]
% \end{tikzpicture}
% \end{codeexample}
% and pdf cross references to the definitions of 'tikzpicture'
% and any options will be generated automatically.
%
% Furthermore, pdf cross references will be generated for everything
% within vertical bars, |....|.
%
%
%
%
%
% The only necessary thing is that \pgfmanualpdflabel has been called
% for every (fully qualified) key, control sequence, environment or
% whatever.

\newif\ifpgfmanualpdfwarnings
\pgfmanualpdfwarningstrue

\newif\ifpgfmanualshowlabels

\pgfkeys{%
    /codeexample/prettyprint/cs arguments/pgfkeys/.initial=1,
    /codeexample/prettyprint/cs/pgfkeys/.code 2 args={\pgfmanualpdfref{#1}{#1}\{\pgfmanualprettyprintpgfkeys{#2}\pgfmanualclosebrace},
    %
    /codeexample/prettyprint/autolinks/.style={%
        /codeexample/prettyprint/key name/.code={\pgfmanualpdfref{##1}{##1}},
        /codeexample/prettyprint/key name with handler/.code 2 args={\pgfmanualpdfref{##1}{##1}/\pgfmanualpdfref{/handlers/##2}{##2}},
        /codeexample/prettyprint/key value display only/.code={\pgfmanualprettyprintcode{##1}},
        /codeexample/prettyprint/cs/.code={\pgfmanualpdfref{##1}{##1}},
        /codeexample/prettyprint/cs with args/.code 2 args={\pgfmanualpdfref{##1}{##1}\{\pgfmanualprettyprintcode{##2}\pgfmanualclosebrace},
        /codeexample/prettyprint/cs arguments/pgfkeys/.initial=1,
        /codeexample/prettyprint/cs/pgfkeys/.code 2 args={\pgfmanualpdfref{##1}{##1}\{\pgfmanualprettyprintpgfkeys{##2}\pgfmanualclosebrace},
        /codeexample/prettyprint/cs arguments/begin/.initial=1,
        /codeexample/prettyprint/cs/begin/.code 2 args={##1\{\pgfmanualpdfref{##2}{##2}\pgfmanualclosebrace},
        /codeexample/prettyprint/cs arguments/end/.initial=1,
        /codeexample/prettyprint/cs/end/.code 2 args={##1\{\pgfmanualpdfref{##2}{##2}\pgfmanualclosebrace},
        /codeexample/prettyprint/word/.code={\begingroup\pgfkeyssetvalue{/pdflinks/search key prefixes in}{}\pgfmanualpdfref{##1}{##1}\endgroup},
        /codeexample/prettyprint/point/.code={##1},%
        /codeexample/prettyprint/point with cs/.code 2 args={(\pgfmanualpdfref{##1}{##1}:##2},%
    },%
    /codeexample/prettyprint/autolinks,
}%

\pgfkeys{
    %
    % Enables or disables the parsing of codeexamples.
    /pdflinks/codeexample links/.is if=pgfmanualprettyenabled,
    /pdflinks/codeexample links/.default=true,
    %
    % How to render a hyperlink
    /pdflinks/render hyperlink/.code=#1,
    %
    % whenever an unqualified key is found, the following key prefix
    % list is tried to find a match.
    /pdflinks/search key prefixes in/.initial={/tikz/,/pgf/},
    %
    % Enables or disables warnings for failed auto links:
    /pdflinks/warnings/.is if=pgfmanualpdfwarnings,
    /pdflinks/warnings/.default=true,
    %
    % Shows the autogenerated labels. This is useful to check if the
    % 'search key prefixes in' worked as it ought to.
    /pdflinks/show labels/.is if=pgfmanualshowlabels,
    /pdflinks/show labels/.default=true,
    /pdflinks/show labels=false,
    % will be invoked with '#1' set to the generated label.
    /pdflinks/show labels code/.code={
        \hbox to 0pt{%
            \vbox to 0pt{\hsize=0pt
                \vskip-\baselineskip
                \hbox to \hsize{%
                    \hss
                    {\footnotesize\ttfamily\textcolor{red}{#1}}%
                    \hss
                }%
                \vss
            }%
            \vbox to 0pt{\hsize=0pt
                \vss
                \hbox to \hsize{%
                    \hss
                    {\footnotesize\ttfamily\textcolor{red}{$\vert$}}%
                    \hss
                }%
            }%
            \vsize=0pt
        }%
    },
    %
    % the link prefix written to the pdf file:
    /pdflinks/internal link prefix/.initial=pgf,
}

\begingroup
    \catcode`\_=12
    \gdef\pgfmanualpdf@underscore{_}%
    \catcode`\ =13\relax\gdef\pgfmanualpdf@install@active@space{\def {\space}}%
\endgroup

\gdef\pgfmanualpdf@installreplacements{%
    \def\marg##1{{##1}}%
    \def\oarg##1{[##1]}%
    \def\meta##1{meta(##1)}%
    \def\x{x}%
    \def\textbackslash{back/}%
    \def\\{\textbackslash}%
    \def\space{:}%
    \edef\ {\space}%
    \edef\SPACE{\` \relax}%
    \ifnum\the\catcode`\ =13 %
        \pgfmanualpdf@install@active@space
    \fi
    \edef\#{}%
    \def\printanat{@}%
    \def\protect{}%
    \def\textasciicircum{o}%
        \def\_{\pgfmanualpdf@underscore}%
    \expandafter\edef\pgfmanual@verb@activebar{\pgfmanual@verb@bar}%
}%

% Defines a new pdf cross ref label for use with \pgfmanualpdfref.
%
% Usage:
%     \pgfmanualpdflabel{<label>}{<text>}
% #1: the label.
% The text #2 will be shown in the resulting pdf (if it is not empty).
%
% There is also support for catcode changes if <label> contains
% something which shouldn't be written as-is into .aux files:
%     \pgfmanualpdflabel[\catcode`\|=12 ]{|-}{}
% -> this will write
% \begingroup \catcode `\|=12
%     <code to deal with the label |-  >
% \endgroup
% into the .aux file.
%
\def\pgfmanualpdflabel{\pgfutil@ifnextchar[{\pgfmanualpdflabel@opt}{\pgfmanualpdflabel@opt[]}}%
\def\pgfmanualpdflabel@opt[#1]#2#3{%
    \begingroup
    %
    \def\pgfmanualpdf@catcode{#1}%
    \pgfmanualpdf@catcode
    %
    \pgfmanualpdflabel@generate{#2}{#3}%
    %
    % this is pgfplots-specific: pgfplots supports generic styles which
    % contain '\x' where '\x' iterates through 'x,y,z'.
    \pgfutil@in@\x{#2}%
    \ifpgfutil@in@
        \def\x{y}%
        \pgfmanualpdflabel@generate{#2}{#3}%
        \def\x{z}%
        \pgfmanualpdflabel@generate{#2}{#3}%
    \fi
    \endgroup
}%
\def\pgfmanualpdflabel@generate#1#2{%
    \pgfmanual@handlespeciallabeltokens@in{#1}%
    %
    \def\pgfmanualpdflabel@generateone{0}%
    \pgfutil@ifundefined{pgfd@lbl@\pgfmanualpdflabel@@}{%
        % ok, no such label is known.
        \def\pgfmanualpdflabel@generateone{1}%
    }{%
        \if\csname pgfd@lbl@\pgfmanualpdflabel@@\endcsname a% "a"ux
            % ah, it is "just" known from a previous run, but there is
            % no code in the pdf! Write it!
            \def\pgfmanualpdflabel@generateone{1}%
        \else
            % ok, we already wrote one before. Skip.
        \fi
    }%
    \if\pgfmanualpdflabel@generateone1%
        \ifpgfmanualshowlabels
            \pgfkeysvalueof{/pdflinks/show labels code/.@cmd}{\pgfmanualpdflabel@@}\pgfeov
        \fi
        %
        \if@filesw
        \ifx\pgfmanualpdf@catcode\pgfutil@empty
        \else
            \toks0=\expandafter{\pgfmanualpdf@catcode}%
            \immediate\write\@auxout{%
                \noexpand\begingroup
                \the\toks0
            }%
        \fi
        \immediate\write\@auxout{%
            \noexpand\expandafter\noexpand\gdef
            \noexpand\csname pgfd@lbl@\pgfmanualpdflabel@@\noexpand\endcsname{a}% a = known in "a"ux file
        }%
        \ifx\pgfmanualpdf@catcode\pgfutil@empty
        \else
            \immediate\write\@auxout{\noexpand\endgroup}%
        \fi
        \fi
        \expandafter\gdef\csname pgfd@lbl@\pgfmanualpdflabel@@\endcsname{w}% 1. remember the label AND remember that we "w"rote it into the pdf.
        \edef\pgfmanualpdflabel@@{\pgfkeysvalueof{/pdflinks/internal link prefix}.\pgfmanualpdflabel@@}%
        \ifvmode%
          \expandafter\hypertarget\expandafter{\pgfmanualpdflabel@@}{#2}%
        \else%
          {\setbox0=\hbox{\raise1em\hbox{\expandafter\hypertarget\expandafter{\pgfmanualpdflabel@@}{}}}\ht0=0pt\box0}#2%
        \fi%
    \else
        #2%
    \fi
}%

% A pdf reference to label `#1' with (TeX) text `#2'.
% @see also \verbpdfref.
\def\pgfmanualpdfref#1#2{%
    \begingroup
    \pgfmanual@handlespeciallabeltokens@in{#1}%
    %
    \ifcsname pgfd@lbl@\pgfmanualpdflabel@@\endcsname
    \else
        \global\let\pgfmanual@glob=\pgfmanualpdflabel@@
        \def\pgfmanual@tempa{\foreach \prefix in }%
        \pgfkeysgetvalue{/pdflinks/search key prefixes in}\pgfmanual@tempb
        \expandafter\pgfmanual@tempa\expandafter{\pgfmanual@tempb}{%
            \edef\pgfmanualpdflabel@@{\prefix\pgfmanualpdflabel@@}%
            \expandafter\pgfmanual@handlespeciallabeltokens@in\expandafter{\pgfmanualpdflabel@@}%
            \ifcsname pgfd@lbl@\pgfmanualpdflabel@@\endcsname
                \xdef\pgfmanual@glob{\pgfmanualpdflabel@@}%
                \breakforeach
            \fi
        }%
        \let\pgfmanualpdflabel@@=\pgfmanual@glob
        \ifcsname pgfd@lbl@\pgfmanualpdflabel@@\endcsname
        \else
            \ifpgfmanualpdfwarnings
                \begingroup
                    \toks0={#1}%
                    \pgfmanual@warning{pgfmanualpdfref{\the\toks0 }: target label does not exist.}%
                \endgroup
            \fi
            #2%
            \let\pgfmanualpdflabel@@=\pgfutil@empty
        \fi
    \fi
    \ifx\pgfmanualpdflabel@@\pgfutil@empty
    \else
        \expandafter\pgfmanualpdfref@\expandafter{\pgfmanualpdflabel@@}{#2}%
    \fi
    \endgroup
}%
\def\pgfmanualpdfref@#1#2{%
    \pgfkeysgetvalue{/pdflinks/internal link prefix}\pgfmanual@temp
    \expandafter\hyperlink\expandafter{\pgfmanual@temp.#1}{\pgfkeysvalueof{/pdflinks/render hyperlink/.@cmd}{#2}\pgfeov}%
    \ifpgfmanualshowlabels
        \pgfkeysvalueof{/pdflinks/show labels code/.@cmd}{#1}\pgfeov
    \fi
}%

% Handles special tokens in a pdf label which should be treated with
% care.
%
% For example, backslashes might produce problems.
% This occurs quite frequently with automatically generated hyperrefs
% inside of codeexamples where \pgfmanualpdfref will be invoked -
% there, we get the catcode 12 backslashes.
% Check for them!
%
% #1: a token list which shall be used either as cross ref or as
% label.
%
% On output, the macro \pgfmanualpdflabel@@ will be '\edef'ed to the
% new, possibly modified value.
\def\pgfmanual@handlespeciallabeltokens@in#1{%
    \begingroup
    \pgfmanualpdf@installreplacements
    \expandafter\pgfutil@in@\pgfmanual@pretty@backslash{#1}%
    \ifpgfutil@in@
        % assume the backslash is the first char and substitute it:
        \pgfmanualpdfref@substitute@backslash#1\relax
    \else
        \edef\pgfmanualpdflabel@@{#1}%
    \fi
    \def\pgfmanual@tmp{\pgfutilstrreplace{ }{\space}}%
    \expandafter\pgfmanual@tmp\expandafter{\pgfmanualpdflabel@@}%
    \edef\pgfmanualpdflabel@@{\pgfretval}%
    \pgfmath@smuggleone\pgfmanualpdflabel@@
    \endgroup
}%

\expandafter\def\expandafter\pgfmanualpdfref@substitute@backslash\expandafter#\expandafter1\pgfmanual@pretty@backslash#2\relax{%
    \edef\pgfmanualpdflabel@@{#1\textbackslash #2}%
}%

% Typesets '#1' in red,\texttt like every declaration. It will also
% generate a pdf cross ref anchor for #1.
%
% WARNING: this changes catcodes! In case this is not acceptable in
% your context, you will need to generate a \pgfmanualpdflabel
% manually.
%
% \declareandlabel{\controlsequence}  can be used as |\controlsequence|
\def\declareandlabel{%
    \begingroup
    \pgfmanual@verb@preparecatcodes@
    \def\pgfmanualprettyprinterhandlecollectedargs##1{%
        \pgfmanualpdflabel##1{\texttt{\declare##1}}% mark: '##1' contains already braces.
        \endgroup
    }%
    \pgfmanualprettyprintercollectargcount1{\relax}%
}

%
% \verbpdfref{\controlsequence more stuff}
% is the same as writing |\controlsequence more stuff|, but the
% *complete* argument is supposed to be one label.
%
% The difference to \pgfmanualpdfref{...}{} is that the argument is
% supposed to be verbatim text.
\def\verbpdfref{%
    \begingroup
    \pgfmanual@verb@preparecatcodes@
    \def\pgfmanualprettyprinterhandlecollectedargs##1{%
        \pgfmanualpdfref##1{\texttt{##1}}% mark: '##1' contains already braces.
        \endgroup
    }%
    \pgfmanualprettyprintercollectargcount1{\relax}%
}

% Prepare active vertical bars, |....| for auto-pretty cross
% referencing.
%
% Example:
%  |\pgfkeys| -> will generate a hyperref!
{
    \catcode`\|=12
    \gdef\pgfmanual@verb@bar{|}%
%    \gdef\pgfmanual@verb@collect#1|{%
%        % this command will also handle control sequences.
%        \texttt{\pgfmanualprettyprintpgfkeys{#1}}%
%        \endgroup
%    }%
    \catcode`\|=13
    \gdef\pgfmanual@verb@activebar{|}%
}
\def\pgfmanual@verb{%
    \begingroup
    \pgfmanual@verb@preparecatcodes@
    \toksdef\t@pgfmanual@verb=0
    \t@pgfmanual@verb={}%
    \pgfmanual@verb@collect
}
% this version of \pgfmanual@verb@collect is less efficient than the
% one uncommented above. BUT: it can auto-detect the case when
% |...| has been provided somewhere where I can't change catcodes!
% The other one would simply fail to compile.
\def\pgfmanual@verb@collect#1{%
    \def\pgfmanual@temp{#1}%
    \ifx\pgfmanual@temp\pgfmanual@verb@bar
        % ok, finish:
        \edef\pgfmanual@verb@collect@next{%
            % this command will also handle control sequences.
            \noexpand\endgroup
            \noexpand\texttt{\noexpand\pgfmanualprettyprintpgfkeys{\the\t@pgfmanual@verb}}%
        }%
    \else
        \ifx\pgfmanual@temp\pgfmanual@verb@activebar
            % ohoh... that should not happen! It means someone invoked
            % |...| within an argument; I couldn't change catcodes.
            % Ok, resort to a simple fallback solution.
            % FIXME : I have just realized that THIS DOESN'T PRESERVE SPACES
            \edef\pgfmanual@verb@collect@next{%
                \noexpand\endgroup
                \noexpand\texttt{\the\t@pgfmanual@verb}%
            }%
        \else
            \t@pgfmanual@verb=\expandafter{\the\t@pgfmanual@verb #1}%
            \let\pgfmanual@verb@collect@next=\pgfmanual@verb@collect
        \fi
    \fi
    \pgfmanual@verb@collect@next
}%

\AtBeginDocument{%
    \ifpgfmanualprettyenabled
        \catcode`\|=13
        \expandafter\let\pgfmanual@verb@activebar=\pgfmanual@verb
    \fi
}%

\def\pgfmanual@verb@preparecatcodes@{%
    \let\do\@makeother%
    \dospecials%
    \catcode`\%=12 % THATS IMPORTANT! Do *not* handle comments!
    % these catcodes are expected by the pretty printer...
    %\catcode`\^^M=13
    \catcode`\ =13
    \catcode`\^^I=13
    \expandafter\def\pgfmanual@pretty@activespace{\space}%
    \expandafter\def\pgfmanual@pretty@activetab{\space\space\space\space}%
}%
\endinput
% vi: ts=4 sw=4
