% hypertext macros for CWEB listings (in addition to cwebmac.tex)
% Used in cwebmac.tex, pdfctwimac.tex, pdfproofmac.tex
% Version 3.0 --- August 2024
\ifx\ifacrohint\undefined\endinput\fi % these are not standalone macros

\ifluatex % LuaTeX is almost like pdfTeX
\protected\def\pdfliteral   {\pdfextension literal}
\protected\def\pdfstartlink {\pdfextension startlink\space}
\protected\def\pdfendlink   {\pdfextension endlink}
\protected\def\pdfoutline   {\pdfextension outline\space}
\protected\def\pdfdest      {\pdfextension dest\space}
\protected\def\pdfcatalog   {\pdfextension catalog}
\edef\pdfhorigin {\pdfvariable horigin}
\edef\pdfvorigin {\pdfvariable vorigin}
\let\pdfpagewidth=\pagewidth
\let\pdfpageheight=\pageheight
\let\pdfoutput=\outputmode
\fi % end of LuaTeX->pdfTeX redirection macros

\def\tocpages{1} % Most programs have one-page Table-of-Contents
\def\startpdf{\def\pagemode{/PageMode /UseOutlines}
  \ifnum\contentspagenumber=0 \advance \pageno by -\tocpages
    \def\pagelabels{/PageLabels << /Nums [ 0 << /S/D/St \tocpages >>
      \the\pageno << /P(Contents) >> ] >>}
  \else \twodigits=\pageno \pageno=\contentspagenumber
    \advance \pageno by \tocpages \advance \twodigits by -\pageno
    \def\pagelabels{/PageLabels << /Nums [ 0 << /S/D/St \the\pageno >>
      \the\twodigits << /S/D/St \contentspagenumber >> ] >>}
  \fi
  \ifpdflua\pdfcatalog{\pagemode\space\pagelabels}
  \else\special{pdf: docview << \pagemode\space\pagelabels >>}\fi}
\ifacrohint\def\digits{\pdflink{\the\countA}\scan}
\else\def\digits{{\the\countA}\scan}\fi
\def\scan#1{\begingroup
  \ifx!#1% exit on exclamation point
  \else\ifx,#1,\space\aftergroup\scan % insert ,\space}\scan ...
  \else\ifx\[#1\aftergroup#1% insert }\[...
  \else\ifx\*#1\aftergroup\lapstar\aftergroup\scan % insert }\lapstar\scan ...
  \else\ifnum`#1>`9#1\aftergroup\scan % insert #1}\scan ...
  \else\ifnum`#1<`0#1\aftergroup\scan % insert #1}\scan ...
  \else
    \afterassignment\digits \aftergroup\countA
    \aftergroup#1% insert }\countA=#1...\digits ...
  \fi\fi\fi\fi\fi \fi
  \endgroup}

% Local variables; there are a few externals like '\toksA' and '\countA'
\newtoks\toksB \newtoks\toksC \newtoks\toksD \newtoks\toksF \newtoks\sanitizer
\newif\iftokprocessed \newif\ifTnum \newif\ifinstr \newif\ifhavenum

\ifacrohint % Common macros for \ifacro and \ifhint to create \pdflink's
\def\pdfnote#1.{\setbox0=\hbox{\toksA={#1.}\toksB={}\maketoks}\the\toksA}
\def\firstsecno#1.{\setbox0=\hbox{\toksA={#1.}\toksB={}%
    \def\makenote{\addtokens\toksB{\the\toksC}\def\makenote{\let\space\empty
      \toksC={}\toksD={}}\makenote}\maketoks}}
\def\addtokens#1#2{\edef\addtoks{\noexpand#1={\the#1#2}}\addtoks}
\def\poptoks#1#2|ENDTOKS|{\let\first=#1\toksD={#1}\toksA={#2}%
  \ifcat\noexpand\first0\countB=`#1\else\countB=0\fi}
\def\maketoks{\expandafter\poptoks\the\toksA|ENDTOKS|%
  \let\next=\maketoks % continue processing by default
  \ifnum\countB>`9 \countB=0 \fi
  \ifnum\countB<`0
    \ifhavenum\makenote\fi
    \ifx\first.\let\next=\maketoksdone % fullstop
    \else \addtokens\toksB{\the\toksD} \ifx\first,\addtokens\toksB{\space}\fi
    \fi
  \else \addtokens\toksC{\the\toksD}\global\havenumtrue
  \fi
  \next
}
\def\makenote{\addtokens\toksB
    {\noexpand\pdflink{\the\toksC}}\toksC={}\global\havenumfalse}
\def\maketoksdone{\edef\st{\global\noexpand\toksA={\the\toksB}}\st}
\fi % End of common pdf/hint macros

\ifacro % The following are general pdf macros
\def\thewidth{\the\wd0 \space}
\def\theheight{\the\ht\strutbox\space}
\def\thedepth{\the\dp\strutbox\space}
\ifpdflua
  \ifx\pdfannotlink\undefined\let\pdfannotlink\pdfstartlink\fi% for pdfTeX 0.14
  \def\pdflink#1{\hbox{\pdfannotlink height \theheight depth \thedepth
    attr{/Border [0 0 0]} goto num #1 \Blue #1\Black\pdfendlink}} % changed 3.69
\else\def\pdflink#1{\setbox0=\hbox{\special{pdf: bc [ \pdflinkcolor ]}{#1}%
    \special{pdf: ec}}\special{pdf: ann width \thewidth height \theheight
      depth \thedepth << /Type /Annot /Subtype /Link /Border [0 0 0]
      /A << /S /GoTo /D (\romannumeral#1) >> >>}\box0\relax}
\fi
\def\sanitizecommand#1#2{\addtokens\sanitizer
       {\noexpand\dosanitizecommand\noexpand#1{#2}}}
\def\dosanitizecommand#1#2{\ifx\nxt#1\addF{#2}\fi}

\catcode`\[=1 \catcode`\]=2 \catcode`\{=12 \catcode`\}=12
  \def\lbchar[{] \def\rbchar[}]
\catcode`\[=12 \catcode`\]=12 \catcode`\{=1 \catcode`\}=2
\catcode`\~=12 \def\tildechar{~} \catcode`\~=13
\catcode`\|=0 |catcode`|\=12 |def|bschar{\} |catcode`|\=0 \catcode`\|=12
\def\makeoutlinetoks{\toksF={}\Tnumfalse
  \afterassignment\makeolproctok\let\nxt= }
\def\makeolnexttok{\afterassignment\makeolproctok\let\nxt= }
\def\makeolgobbletok{\afterassignment\makeolnexttok\let\nxt= }
\def\addF#1{\addtokens\toksF{#1}\tokprocessedtrue}
% now comes a routine to "sanitize" section names, for pdf outlines
\def\makeolproctok{\tokprocessedfalse
  \let\next\makeolnexttok % default
  \ifx\nxt\outlinedone\let\next\outlinedone
  \else\ifx{\nxt \else\ifx}\nxt \Tnumfalse \instrfalse % skip braces
  \else\ifx$\nxt % or a $ sign
  \else\ifx^\nxt \addF^\else\ifx_\nxt \addF_% sanitize ^ and _
  \else\ifx\nxt\spacechar \addF\space
  \else\if\noexpand\nxt\relax % we have a control sequence; is it one we know?
    \ifx\nxt~\addF\space
    \else\ifx\nxt\onespace\addF\space
    \else\the\sanitizer
      \iftokprocessed\else\makeolproctokctli
      \iftokprocessed\else\makeolproctokctlii
      \iftokprocessed\else\makeolproctokctliii % if not recognised, skip it
      \fi\fi\fi
    \fi\fi
  \else  % we don't have a control sequence, it's an ordinary char
    \ifx/\nxt \addF{\string\/}% quote chars special to PDF with backslash
    \else\ifx(\nxt \addF{\string\(}\else\ifx)\nxt \addF{\string\)}%
    \else\ifx[\nxt \addF{\string\[}\else\ifx]\nxt \addF{\string\]}%
    \else\expandafter\makeolproctokchar\meaning\nxt
    \fi\fi\fi\fi\fi
  \fi\fi\fi\fi\fi \fi\fi\fi
  \next
}
\def\makeolproctokchar#1 #2 #3{\addF{#3}}
\def\makeolproctokctli{%
  \ifx\nxt\CEE\addF{C}\let\next\makeolgobbletok % \CEE/
  \else\ifx\nxt\UNIX\addF{UNIX}\let\next\makeolgobbletok % \UNIX/
  \else\ifx\nxt\TEX\addF{TeX}\let\next\makeolgobbletok % \TEX/
  \else\ifx\nxt\TeX\addF{TeX}\else\ifx\nxt\LaTeX\addF{LaTeX}%
  \else\ifx\nxt\CPLUSPLUS\addF{C++}\let\next\makeolgobbletok % \CPLUSPLUS/
  \else\ifx\nxt\Cee\addF{C}%
  \else\ifx\nxt\PB \let\next\makeolgobbletok \tokprocessedtrue % \PB{...}
  \else\ifx\nxt\.\tokprocessedtrue\instrtrue % \.{...}
      % skip \|
  \else\ifx\nxt\\\ifinstr\addF{\bschar\bschar}\else\tokprocessedtrue\fi
  \else\ifx\nxt\&\ifinstr\addF&\else\tokprocessedtrue\fi
  \else\ifx\nxt\~\ifTnum\addF{0}\else\addF\tildechar\fi % 077->\T{\~77}
  \else\ifx\nxt\_\ifTnum\addF{E}\else\addF_\fi % 0.1E5->\T{0.1\_5}
  \else\ifx\nxt\^\ifTnum\addF{0x}\else\addF^\fi % 0x77 -> \T{\^77}
  \else\ifx\nxt\\\\\ifTnum\addF{0b}\else\addF\\\fi % 0b10111 -> \T{\\10111}
  \else\ifx\nxt\$\ifTnum\tokprocessedtrue\else\addF$\fi %$% \T{77\$L}
  \else\ifx\nxt\{\addF\lbchar\else\ifx\nxt\}\addF\rbchar
  \else\ifx\nxt\ \addF\space\else\ifx\nxt\#\addF{\string\#}%
  \else\ifx\nxt\PP\addF{++}\else\ifx\nxt\MM\addF{--}%
  \fi\fi\fi\fi\fi \fi\fi\fi\fi\fi
  \fi\fi\fi\fi\fi \fi\fi\fi\fi\fi
  \fi\fi
}
\def\makeolproctokctlii{%
  \ifx\nxt\MG\addF{->}\else\ifx\nxt\GG\addF{>>}%
  \else\ifx\nxt\LL\addF{<<}\else\ifx\nxt\NULL\addF{NULL}%
  \else\ifx\nxt\AND\addF&\else\ifx\nxt\OR\addF|%
  \else\ifx\nxt\XOR\addF^\else\ifx\nxt\CM\addF\tildechar
  \else\ifx\nxt\MOD\addF{\string\%}\else\ifx\nxt\DC\addF{::}%
  \else\ifx\nxt\PA\addF{.*}\else\ifx\nxt\MGA\addF{->*}%
  \else\ifx\nxt\this\addF{this}\else\ifx\nxt\?\addF?%
  \else\ifx\nxt\E\addF{==}\else\ifx\nxt\G\addF{>=}%
  \else\ifx\nxt\I\addF{!=}\else\ifx\nxt\K\addF{=}%
  \else\ifx\nxt\l\addF{l}\else\ifx\nxt\L\addF{L}%
  \else\ifx\nxt\o\addF{o}\else\ifx\nxt\O\addF{O}%
  \else\ifx\nxt\R\addF!%
  \else\ifx\nxt\T \Tnumtrue \let\next\makeolgobbletok
    \tokprocessedtrue % \T{number}
  \else\ifx\nxt\AM\addF&\else\ifx\nxt\%\addF{\string\%}%
  \fi\fi\fi\fi\fi \fi\fi\fi\fi\fi
  \fi\fi\fi\fi\fi \fi\fi\fi\fi\fi
  \fi\fi\fi\fi\fi \fi
}
\def\makeolproctokctliii{%
  \ifx\nxt\V\addF{||}\else\ifx\nxt\W\addF{&&}\else\ifx\nxt\Z\addF{<=}%
  \else\ifx\nxt\*\addF*\else\ifx\nxt\Xand\addF{\space and\space}%
  \else\ifx\nxt\Xandxeq\addF{\space and_eq\space}%
  \else\ifx\nxt\Xbitand\addF{\space bitand\space}%
  \else\ifx\nxt\Xbitor\addF{\space bitor\space}%
  \else\ifx\nxt\Xcompl\addF{\space compl\space}%
  \else\ifx\nxt\Xnot\addF{\space not\space}%
  \else\ifx\nxt\Xnotxeq\addF{\space not_eq\space}%
  \else\ifx\nxt\Xor\addF{\space or\space}%
  \else\ifx\nxt\Xorxeq\addF{\space or_eq\space}%
  \else\ifx\nxt\Xxor\addF{\space xor\space}%
  \else\ifx\nxt\Xxorxeq\addF{\space xor_eq\space}%
  \fi\fi\fi\fi\fi \fi\fi\fi\fi\fi
  \fi\fi\fi\fi\fi
}
\def\outlinedone{\edef\outlinest{\global\noexpand\toksE={\the\toksF}}%
  \outlinest\let\outlinedone=\relax\outlinedone}
\fi % End of pdf macros

\ifhint
% The following top level macros use HINT primitives to implement:
% \HINThome to mark the position of the home page
% \HINTlabel to attach a label to the top of a section
% \HINTlink to link a section number to the section label
% \HINTcontents to produce an 'outline' item
\def\HINThome{\HINTdest name {HINT.home}%
  \HINToutline goto name {HINT.home} depth 1 {Table of Contents}}
\def\HINTlabel{{\let\*=\empty\HINTdest num \secstar top}}
\def\HINTlink#1{\HINTstartlink goto num #1 {#1}\HINTendlink}
\def\HINTcontents#1#2#3{\HINToutline goto num #3 depth #2 {#1}}
\let\pdflink=\HINTlink
\fi % End of HINT macros
