% This file is only intended to be input by Tcode_Ccode.tex

%At beginning of line, we let Tcode parse the initial spaces. After that it issues \CFirstNoBlank, that
% gets as #1 the first non-white (and non-^^M) of the line. We check if it is #. We allow #<spaces>define,
% for example, and intercept include and embed to properly format the <header_name> that may follow.

\let\PPLineHook\relax %A hook for the user

\if*\TcodeLang*
  \def\dohash@Code@C{\PPLineHook{\FormatPPDirective\#}\let\parsecode\ParseInBetweenSpaces}
\else
  \def\dohash@Code@C{\PPLineHook{\FormatCPPDirective\#}\let\parsecode\ParseInBetweenSpaces}
\fi

\def\CFirstNoBlank#1{
  \if\noexpand#1##\dohash@Code@C
  \else\def\parsecode{\@parsecode#1}
  \fi
  \parsecode
}
\def\ParseInBetweenSpaces#1{
  \ifcat\noexpand#1a%This is virtually always the branch taken
    \WordToPrint={#1}\let\parsecode\ParsePPDirective
  \else
    \InBetweenNoLetter#1%If #1 is not a space, restores control to \@parsecode
  \fi
  \parsecode
}
%Space and tab are active in the environment
{\catcode`\^^I=12 %Otherwise, it is treated, here, like a space
%When this macro is expanded \parsecode is \ParseInBetweenSpaces
\gdef\temp#1{
  \if\noexpand#1^^I#1\else
  \if\noexpand#1 #1\else
    \def\parsecode{\@parsecode#1}
  \fi\fi
}}
\let\InBetweenNoLetter\temp

\def\ParsePPDirective#1{
  \ifcat\noexpand#1a
  \WordToPrint=\exP{\the\WordToPrint#1}% append it to WordToPrint
  \else\PPDirectiveFinished#1
  \fi
  \parsecode
}
\def\PPDirectiveFinished#1{\def\parsecode{\@parsecode #1}\PrintPPDirective\WordToPrint={}}

\def\PrintPPDirective{
   {\ifcsname Format\TcodeLang @##\the\WordToPrint\endcsname \csname Format\TcodeLang @##\the\WordToPrint\exP\endcsname
   \else\exP\FormatOtherWords\fi
   {\the\WordToPrint}}
   \csname PPDirective@\the\WordToPrint\endcsname %Execute something for this directive in case something has been defined
}

\def\PPDirective@include{\catcode`\<=\active \let\HandlePPFile\HandleFileInclude}
\def\PPDirective@embed{\catcode`\<=\active \let\HandlePPFile\HandleFileEmbed}
%Modify \PreprintLongHook for the next word. If no word follows, the end of the box will restore it
\def\PPDirective@define@{\let\PrePrint@Saved\PrePrintLongHook \let\PrePrintLongHook\PrePrintMakeMacro}%
\def\PPDirective@undef@{\let\PrePrint@Saved\PrePrintLongHook \let\PrePrintLongHook\PrePrintUnDefine}%

%A hook that causes the next word to be classified as Macro. Then restores \PrePrintLongHook
\def\PrePrintMakeMacro{
  \MakeWord{\the\WordToPrint}{Macro}% Now make it "global". \closelinebox restores itself
  \edef\closelinebox{\expandonce\closelinebox\noexpand\MakeWord{\the\WordToPrint}{Macro}}
  \def\FormatToApply{\csname Format\TcodeLang Macro\endcsname}% Update FormatToApply for this particular instance
  \let\PrePrintLongHook\PrePrint@Saved
  \PrePrintLongHook
}
%The same, for undefinig it
\def\PrePrintUnDefine{
  \KillWord{\the\WordToPrint}% Now make it "global"
  \edef\closelinebox{\expandonce\closelinebox\noexpand\KillWord{\the\WordToPrint}}%\closelinebox restores itself
  \let\FormatToApply\relaxorundef
  \let\PrePrintLongHook\PrePrint@Saved
  \PrePrintLongHook
}

\def\HandlePPDefine{
  \let\PPDirective@define\PPDirective@define@
  \let\PPDirective@undef\PPDirective@undef@
}
\def\NoHandlePPDefine{
  \let\PPDirective@define\undefined
  \let\PPDirective@undef\undefined
}
\let\HandleCPPdefine\HandlePPDefine
\let\NoHandleCPPdefine\NoHandlePPDefine

\HandlePPDefine %The default

\def\ParseIncludedString#1>{\HandlePPFile{#1}\catcode`\<=12 \@parsecode}


%Save the definitions for double inclusion

\let\CFirstNoBlank@langC\CFirstNoBlank
\let\ParseInBetweenSpaces@langC\ParseInBetweenSpaces
\let\InBetweenNoLetter@langC\InBetweenNoLetter
\let\ParsePPDirective@langC\ParsePPDirective
\let\PPDirectiveFinished@langC\PPDirectiveFinished
\let\PrintPPDirective@langC\PrintPPDirective
\let\PrePrintMakeMacro@langC\PrePrintMakeMacro
\let\PrePrintUnDefine@langC\PrePrintUnDefine
\let\ParseIncludedString@langC\ParseIncludedString
\let\HandlePPDefine@langC\HandlePPDefine
\let\NoHandlePPDefine@langC\NoHandlePPDefine
  
\def\TcodeCcode@Reload@PP{
  \let\CFirstNoBlank\CFirstNoBlank@langC
  \let\ParseInBetweenSpaces\ParseInBetweenSpaces@langC
  \let\InBetweenNoLetter\InBetweenNoLetter@langC
  \let\ParsePPDirective\ParsePPDirective@langC
  \let\PPDirectiveFinished\PPDirectiveFinished@langC
  \let\PrintPPDirective\PrintPPDirective@langC
  \let\PrePrintMakeMacro\PrePrintMakeMacro@langC
  \let\PrePrintUnDefine\PrePrintUnDefine@langC
  \let\ParseIncludedString\ParseIncludedString@langC
  \let\HandlePPDefine\HandlePPDefine@langC
  \let\NoHandlePPDefine\NoHandlePPDefine@langC
  \let\HandleCPPdefine\HandlePPDefine
  \let\NoHandleCPPdefine\NoHandlePPDefine
}