% This is part of the Tcode kernel. Only intended to by input by it. %%%%%%%%%%%%%%%%**** The environment Code ****%%%%%%%%%%%%%%%% %At the begnning we need to put some space (3pt) below the frame line, %but if there is no frame nor background, the space will not be put (see \let\N@abbe@cle\relax below) %and some space above the bottom line at the end: \def\CodeOpen{\NLhrule\no@break\N@abbe@cle\no@break} \def\CodeClose{\no@break\N@abbe@cle\no@break\NLhrule} %Each line will be placed in a box by itself. This makes possible the handling of page breaking in-between by this package. %These macros open and close the \hbox containing each line, and place the 2pt clearance. \def\openfirstline{\hbox\bgroup\kern\CodeLeftInd\setbox0 \hbox to\lineboxwd\bgroup\NLvrule\kern 2pt\strut} \def\openlinebox{\no@break\vskip\CodeBreakglue\applyNLpenalty\vskip-\CodeBreakglue\relax \hbox\bgroup\kern\CodeLeftInd\setbox0 \hbox to\lineboxwd\bgroup\NLvrule\kern 2pt\strut } \def\closelineboxC{\hss\kern 2pt\NLvrule\egroup %Here ends the box with the contents. Now place a box with the bkg color \hbox to0pt{\ApplyBkgColor\vrule width\wd0 height\ht0 depth\dp0\hss}%filling the same space as the contents box \box0\kern\CodeRightInd\egroup %Place the contents box. \egroup closes the line box } \def\closelineboxN{\hss\kern 2pt\NLvrule\egroup \box0\kern\CodeRightInd\egroup} \def\Code{\par \vskip\Codeskipbefore \begingroup\setlineboxwd \let\wordbox\relax %Used in inline mode to prevent hyphenation. Here, not needed. But is available as a hook \offinterlineskip \CodeLineZero %Will consume the ^^M and invoke \CodeAfterFisrtLine } %I'd rather not change the catcode of ^^M for this, so that the user could use a macro %of his own also taking ^^M as delimiter. But TeX does not allow that (which also means the user cannot %have any such macro). \def\CodeLineZero{\SetCatcodesLineZero\CLineZero} \def\SetCatcodesLineZero{%\We do not change %. Hence, its presence in line zero will omit the line after \SpecialCharsInIdent\catcode`\^^M=\active %line zero. But this is useful for writing several lines of definitions } \def\CLineZero#1^^M{#1\CodeAfterLineZero} %Execute what the user has put there. Consumes the ^^M. \def\CodeAfterLineZero{ \ifx\ApplyBkgColor\empty \let\closelinebox\closelineboxN \ifdim\CodeFramewd=0pt \let\N@abbe@cle\relax\fi %If there is no frame nor background, we don't need the clearance. \else \let\closelinebox\closelineboxC \fi \let\break\CBreak \let\nobreak\CNobreak \let\goodbreak\CGoodbreak \SetCodeCatcodes %Those of \ncode, plus ^^M and others \CodeDefineCommands%Hook for the language package \the\CodeHook\CodeOpen% A hook for the user and the top part of the frame \CodeLineCheck %Start parsing the first line } {\catcode`\^^I=13 \gdef\SetCodeCatcodes{ \SetNcodeCatcodes \catcode`\^^M=\active \catcode`\^^I=\active \let^^M\EOLMiddle %This is for ^^M not caught by the normal \@parsecode. \let\^^M\SlashMInCode %This is for \^^M not caught by the normal \@parsecode. \let^^I=\NcodeTab \catcode`\{=\cat@xii \catcode`\}=\cat@xii \let\MaybeSkipSpacesAfterCS\SkipSpacesAfterCS \SetEscapeChars \let\SetEscapeChars\relax %Not worth delaying it to every string. Further, \t, etc. may also be used in comments }} %This is the control seq. performing the last tasks *in* the environment \def\CodeEnd{\CodeClose\endgroup} \def\endCode{\vskip\Codeskipafter}% This will be executed *after* \CodeEnd %Check if we have \end or \endCode right ahead of us \def\IfCodeEnd#1{\ifcsname IfCodeEnd@\string#1\endcsname} \exP\let\csname IfCodeEnd@\string\end\endcsname=\iftrue %or =\relax, \exP\let\csname IfCodeEnd@\string\endCode\endcsname=\iftrue %or =\relax, \let\fi\fi %% This is the first code executed for the first line and for a line following a ^^M or \^^M caught by \@parsecode %% %If we detect the end of the environment we need to perform the closing tasks before Latex %attempts to pass us \endCode, because the latter needs the argument {Code} to be read by \end, %but { and } do not have their usual catcodes inside the environment. We could instead restore these %two catcodes immediately after reading \end. %The c. s. which checks for the end of the environment is \CodeLineCheck \def\CodeLineCheck#1{ \IfCodeEnd#1\exP\CodeEnd \else\openlinebox\exP\CBeginLine\fi #1 } %End of line caught by \@parsecode \def\TcodeReloadC{ \def\splicechar{\SpliceCharTasks{\FormatSpliceChar\\}} %Two hooks for the user \let\SpliceCharTasks\empty \def\SlashMInCode{\splicechar^^M} \TcodeDefineSpecial{^^M}{\closelinebox\CodeLineCheck} \TcodeDefineSpecial{\^^M}{\splicechar\closelinebox\openlinebox\CBeginSplice} \let\CBeginSplice\@parsecode %A hook for the user \def\BeginLineBlanks{\let\parsecode\SkipInitialSpaces\parsecode} \let\CBeginLine\BeginLineBlanks %A hook for the user. This default prints the blanks and then calls \CFirstNoBlank \let\CFirstNoBlank\@parsecode %Another hook } %End of line (i.e., ^^M) or \^^M not caught by \@parsecode because it has entered the argument of a user macro. \def\TcodeReloadD{ \def\EOLMiddle{\egroup\closelinebox\openlinebox\CBeginInTheMiddle} \def\CBeginInTheMiddle{\bgroup\CContinueInTheMiddle} %A hook for the user \let\CContinueInTheMiddle\relax %Another hook } \TcodeReloadC \TcodeReloadD %Another option for \CBeginInTheMiddle is \SkipSpacesInTheMiddle %Space and tab are active in the environment. In the definitions that follow we %need the tab, here, not to be treated like a space. This suffices \catcode`\^^I=12 \def\SkipInitialSpaces#1{ \if\noexpand#1^^I#1\else \if\noexpand#1 #1\else %If is \space, or =any non-primitive % \ifx#1\ \ \else %If is \ . \InitialSpacesFinished#1 \fi\fi \parsecode } \def\InitialSpacesFinished#1{ \ifx#1^^M\def\parsecode{\@parsecode#1} \else\ifx#1^^M\def\parsecode{\@parsecode#1} \else\def\parsecode{\CFirstNoBlank#1} \fi\fi } %Spaces at beginning of line InTheMiddle of something. %The redefinition of itself is local to the group of the line, and will be restored when the line is closed \def\SkipSpacesInTheMiddle#1{ \if\noexpand#1^^I#1\else \if\noexpand#1 #1\else \def\SkipSpacesInTheMiddle{\bgroup\CContinueInTheMiddle #1} \fi\fi \SkipSpacesInTheMiddle } %Two commands for the user. it may be used also for the long inline macros. %Ignore (printing them) blanks until something is found, at which point, execute #1. %1st. If an end of line is reached we discard #1 and proceed normally. \def\CSkipBlanks#1{ \let\CAfterSpaces#1 \let\parsecode\ParseSkipSpaces } \def\ParseSkipSpaces#1{ \if\noexpand#1^^I#1\else \if\noexpand#1 #1\else \SkippedSpacesFinished#1 \fi\fi \parsecode } \def\SkippedSpacesFinished#1{ \ifx#1^^M\def\parsecode{\@parsecode#1} \else\ifx#1^^M\def\parsecode{\@parsecode#1} \else\def\parsecode{\CAfterSpaces#1} \fi\fi } %2nd. Like the previous one, but we let the user handle ^^M and \^^M \def\CSkipBlanksPure#1{ \let\CAfterSpaces#1 \let\parsecode\ParseSkipSpacesPure } \def\ParseSkipSpacesPure#1{ \if\noexpand#1^^I#1\else \if\noexpand#1 #1\else \def\parsecode{\CAfterSpaces#1} \fi\fi \parsecode } \catcode`\^^I=10 %