% \iffalse meta-comment
%<=*COPYRIGHT>
%% Copyright (c) 2009-2025 by Martin Scharrer <martin.scharrer@web.de>
%% ----------------------------------------------------------------------
%% This work may be distributed and/or modified under the
%% conditions of the LaTeX Project Public License, either version 1.3
%% of this license or (at your option) any later version.
%% The latest version of this license is in
%%   http://www.latex-project.org/lppl.txt
%% and version 1.3 or later is part of all distributions of LaTeX
%% version 2005/12/01 or later.
%%
%% This work has the LPPL maintenance status `maintained'.
%%
%% The Current Maintainer of this work is Martin Scharrer.
%%
%% This work consists of the files collcell.dtx and collcell.ins
%% and the derived filebase collcell.sty.
%%
%<=/COPYRIGHT>
% \fi
%
% \iffalse
%<*driver>
\ProvidesFile{collcell.dtx}[%
%<=*DATE>
    2025/02/21
%<=/DATE>
%<=*VERSION>
    v0.6
%<=/VERSION>
    DTX file for collcell]
\documentclass{ydoc}[2011/03/19]
\GetFileInfo{collcell.dtx}
\usepackage[robustcr]{collcell}[\filedate]
\usepackage{tikz-timing}
\lstset{language=[latex]tex,basicstyle=\ttfamily}

\EnableCrossrefs
%\CodelineIndex
\RecordChanges
%\OnlyDescription
\begin{document}
  \DocInput{\jobname.dtx}
  \PrintChanges
  %\newpage\PrintIndex
\end{document}
%</driver>
% \fi
%
% \CheckSum{358}
%
% \CharacterTable
%  {Upper-case    \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
%   Lower-case    \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
%   Digits        \0\1\2\3\4\5\6\7\8\9
%   Exclamation   \!     Double quote  \"     Hash (number) \#
%   Dollar        \$     Percent       \%     Ampersand     \&
%   Acute accent  \'     Left paren    \(     Right paren   \)
%   Asterisk      \*     Plus          \+     Comma         \,
%   Minus         \-     Point         \.     Solidus       \/
%   Colon         \:     Semicolon     \;     Less than     \<
%   Equals        \=     Greater than  \>     Question mark \?
%   Commercial at \@     Left bracket  \[     Backslash     \\
%   Right bracket \]     Circumflex    \^     Underscore    \_
%   Grave accent  \`     Left brace    \{     Vertical bar  \|
%   Right brace   \}     Tilde         \~}
%
%
% \changes{v0.0}{2009/08/13}{Created package}
% \changes{v0.1}{2011/02/04}{First released version}
% \changes{v0.1a}{2011/02/05}{Fixed unwanted spaces. Fixed misspelled macros in example.}
% \changes{v0.5}{2011/02/27}{Fixed several bugs and limitations. (Complete list to be inserted)}
% \changes{v0.6}{2025/02/21}{Add support for \textonly@unskip. Support nesting of environments in cells.}
%
% \DoNotIndex{\newcommand,\newenvironment,\def,\edef,\xdef,\DeclareRobustCommand}
%
% \GetFileInfo{\jobname.dtx}
% \author{Martin Scharrer}
% \email{martin.scharrer@web.de}
% \maketitle
%
% \begin{abstract}
% This package provides macros which collect the cell content of a tabular
% and provide it to a macro as argument. It was inspired by the |\collect@body|
% macro defined by the \pkg{amsmath} or the \pkg{environ} package, which can be used
% to collect the body of an environment. Special care is taken to remove all aligning
% macros inserted by tabular from the cell content. The macros also work in the last
% column of a tabular. They do not support verbatim material inside the cells, except of a
% special almost-verbatim version of \verb+\verb+.
%
% This package is relatively new and might still not work in all possible situations which can arise
% in a tabular. The implementation might change in future versions. Please do not hesitate to contact the
% author about any issue and suggestions.
% \end{abstract}
%
% \section{Usage}
% This package provides the macros \Macro\collectcell and \Macro\endcollectcell
% which are supposed to be used with the |>{ }| and |<{ }| tabular column declarations of
% the \pkg{array} package. This can be done either in the argument of tabular or using
% \Macro\newcolumntype.
%
% The following code defines a `|E|' column which passes the contents of its cell
% to \Macro\usermacro as an argument. The macro can the process the content as usual.
%
% \par\bigskip
% \noindent
% |% Preamble:|\\
% |\usepackage{array}|\\
% |\usepackage{collcell}|\\
% |% Preamble or document:|\\
% |\newcolumntype{E}{>{\collectcell\usermacro}c<{\endcollectcell}}|\\
% ||\\
% |% Document:|\\
% |\begin{tabular}{lE}|\\
% |   A & Example \\ % Same as \usermacro{Example} |\\
% |   B & Text    \\ % Same as \usermacro{Text}    |\\
% |\end{tabular}|\\
% \par\medskip
%
% For example \Macro\usermacro could be \Macro\fbox and wrap the cell content in a frame box.
% More complicated macros are also supported as long they take one argument. This package
% was originally programmed to be used with the \Macro\tikztiming macro of the \pkg{tikz-timing} package.
% This macro takes some complex user input and draws a timing diagram from it
%
% Note that if such a cell contains a tabular environment by itself, the environment must be wrapped
% in braces `|{ }|' to ensure proper operation.
%
% \subsection{Options}
%
% The~\opt*{verb} and~\opt*{noverb} options enable or disable (default) the definition of a special almost-verbatim version of \verb+\verb+.
% At the moment the one defined by the \pkg{tabularx} package is used, which is therefore loaded when this feature is enabled.
% Future versions of \pkg{collcell} might provide this macro in a different way, so the visual result might be different.
% The \pkg{tabularx} should be loaded explicitly if it is used.
% This version of \verb+\verb+ will read the content first normally, i.e. non-verbatim, and then print the included tokens in a verbatim format.
% The content must include a balanced number of |{ }| and must not be end with |\|. Macros inside the content will be followed by a space.
% See the manual of \pkg{tabularx} (page 8 in the version from 1999/01/07) for a more detailed description.
%
% The~\opt*{robustcr} and \opt*{norobustcr} options enable (default) or disable the redefinition of |\\| to a robust version, i.e. this macro
% will be prefixed with eTeX's |\protected| to ensure that it isn't expanded by the underlying |\halign|. If this feature disabled the
% last cell of a tabular must not be empty or only hold empty macros (like |\empty|).
%
% \subsection{Limitations}
%
% \DescribeMacro\ccunskip
% The macro |\unskip| should not be included inside the cell directly, but only inside a |{ }| group or a macro.
% Otherwise it will be taken as part of the internal cell code and ignored. Leading spaces will however be removed.
% This macro can be used as a replacement of |\unskip| inside the cells.
%
% \DescribeMacro\cci
% The content of every cell is expanded by TeX itself until the first non-expandable token (macro, character, \ldots) is found. This happens to check if a |\noalign| follows
% with e.g.\ is used inside |\hrule| and other rule drawing macros. There is nothing what \pkg{collcell} could do about this.
% If this expansion is unwanted the non-expandable token \Macro\cci should be placed at the beginning of the cell. This macro will be ignored (discarded) by \pkg{collcell} and
% will not be provided to the user macro (|cci| = collect cell; ignore).
%
% \clearpage
% \section{Tests and Examples}
%
% \begin{example}
% \caption{Framebox, texttiming, expanded tokens, sub-tabular}
% \begin{examplecode}
%     \makeatletter
%     \newcommand*\Meaning[1]
%        {\def\CODE{#1}\texttt{\expandafter\strip@prefix\meaning\CODE}}%
%     \newcolumntype{F}{>{\collectcell\fbox}l<{\endcollectcell}}%
%     \newcolumntype{M}{>{\collectcell\Meaning}l<{\endcollectcell}}%
%     \newcolumntype{T}{>{\collectcell\texttiming}l<{\endcollectcell}}%
%     \begin{tabular}{@{}F@{}|@{}M@{}|@{}T@{}}
%        A & B                       & HLDZ 2{HZLZ} \\
%        A & \empty\relax Z5D{TEST}Z & Z5D{TEST}Z  \\
%        A & \cci\empty Z5D{TEST}Z & Z5D{TEST}Z  \\
%        {\begin{tabular}{cFc} a & b & c \end{tabular}} &
%         \relax\begin{quote}AA\end{quote}   & $5+5${C} \\
%        A & B   \ccunskip B                 & 3{ttz} \\
%     \end{tabular}%
% \end{examplecode}
% \end{example}
%
% \makeatletter
% \newcommand*\Meaning[1]{\def\CODE{#1}\texttt{\expandafter\strip@prefix\meaning\CODE}}%
% \newcolumntype{M}{>{\collectcell\Meaning}l<{\endcollectcell}}%
% \newcolumntype{F}{>{\collectcell\fbox}l<{\endcollectcell}}%
% \makeatother
%
% \begin{example}
% \caption{Multicolumn, expanded row macro}
% \begin{examplecode}
%     \def\abc{ \empty A & \empty B & \empty C }
%     \begin{tabular}{MMM}
%       \multicolumn{2}{M}{\empty Multi} & \empty single \\
%       \abc \\
%     \end{tabular}
% \end{examplecode}
% \end{example}
%
% \begin{example}
% \caption{Empty cells, missing `\texttt{\textbackslash\textbackslash}' at end}
% \begin{examplecode}
%     \begin{tabular}{|F|F|F|}
%        \\
%        A & \\
%        A & B \\
%        A & B & \\
%        A & B & C \\
%        & \\
%        & B \\
%        & B & \\
%        & B & C \\
%        & & \\
%        & & C \\
%        A & B & C
%     \end{tabular}
% \end{examplecode}
% \end{example}
%
% \StopEventually{}
% \clearpage
%
% \section{Implementation}
%
% \iffalse
%<*collcell.sty>
% \fi
%    \begin{macrocode}
%<!COPYRIGHT>
\ProvidesPackage{collcell}[%
%<!DATE>
%<!VERSION>
%<*DRIVER>
    2099/01/01 develop
%</DRIVER>
    Collect the content of a tabular cell]
%    \end{macrocode}
%
%    \begin{macrocode}
\RequirePackage{array}
\def\collcell@beforeuser{\ignorespaces}
\def\collcell@afteruser{\unskip}

\newif\if@collcell@verb
\newif\if@collcell@robustcr
\@collcell@robustcrtrue
%    \end{macrocode}
%
% \subsection{Options}
%    \begin{macrocode}
\DeclareOption{verb}{\@collcell@verbtrue}
\DeclareOption{noverb}{\@collcell@verbfalse}
\DeclareOption{robustcr}{\@collcell@robustcrtrue}%
\DeclareOption{norobustcr}{\@collcell@robustcrfalse}%
\ProcessOptions\relax
\if@collcell@verb
  \RequirePackage{tabularx}
  \def\collcell@beforeuser{%
    \let\collcell@savedverb\verb
    \let\verb\TX@verb
    \let\TX@vwarn\collcell@vwarn
    \ignorespaces
  }%
  \def\collcell@afteruser{\unskip\let\verb\collcell@savedverb}%
  \def\collcell@vwarn{%
    \PackageWarning{collcell}{\noexpand\verb may be unreliable inside a collected cell}%
  }%
\fi
\if@collcell@robustcr
  \RequirePackage{etoolbox}
  \robustify\@arraycr
\fi
%    \end{macrocode}
%
% \subsection{Collect cell content}
%    \begin{macrocode}
\let\collect@cell@toks\@temptokena
\newcount\collect@cell@count
%    \end{macrocode}
%
% \begin{macro}{\collectcell}[2]{user macro(s)}{ignored tokens, possible empty}
%    \begin{macrocode}
\newenvironment{collectcell}{}{}
\def\collectcell#1#2\ignorespaces{%
  \begingroup
  \collect@cell@count\z@
  \collect@cell@toks{}%
  \let\collect@cell@spaces\empty
  \def\collect@cell@end{%
    \expandafter\endgroup
    \expandafter\collcell@beforeuser
    \expandafter\ccell@swap\expandafter{\the\collect@cell@toks}{#1}%
    \collcell@afteruser
  }%
  \collect@cell@look#2%
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\ccell@swap}
% Swaps the two arguments. The second one (user macro(s)) is added without braces.
%    \begin{macrocode}
\def\ccell@swap#1#2{#2{#1}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\endcollectcell}
% Holds unique signature which will expand to nothing.
%    \begin{macrocode}
\def\endcollectcell{\@gobble{endcollectcell}}
%    \end{macrocode}
% \end{macro}
%
%
% \begin{macro}{\collect@cell@look}
% Looks ahead to the next token and call the next macro to handle it.
%    \begin{macrocode}
\def\collect@cell@look{%
  \futurelet\collect@cell@lettoken\collect@cell@look@
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\collect@cell@eatspace}
% Eats a following space and call the 'look' macro again.
%    \begin{macrocode}
\@firstofone{\def\collect@cell@eatspace} {\collect@cell@look}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\collect@cell@look@}
% Handles special tokens which should not be read as argument.
% All other are handled by \Macro\collect@cell@arg.
%    \begin{macrocode}
\def\collect@cell@look@{%
  \cc@case
    \@sptoken{%
      \edef\collect@cell@spaces{\collect@cell@spaces\space}%
      \collect@cell@eatspace
    }%
    \bgroup{\collect@cell@group}%
    \default{\collect@cell@arg}%
  \endcc@case
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\collect@cell@group}
% Tests if the previous discovered |begin-group character {| token was a |\bgroup| or a |{|.
% In the first case the command sequence is simply added but in the second case the surrounding
% braces must be added again.
% The use of |\unexpanded| allows |#| in the cells, e.g. for in-cell macro definitions.
%    \begin{macrocode}
\def\collect@cell@group#1{%
  \begingroup
  \edef\@tempa{\unexpanded{#1}}%
  \def\@tempb{\bgroup}%
  \ifx\@tempa\@tempb
    \endgroup
    \collect@cell@addarg{#1}%
  \else
    \endgroup
    \collect@cell@addarg{{#1}}%
  \fi
  \collect@cell@look
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\collect@cell@addarg}
% Adds the given argument to the token list.
%    \begin{macrocode}
\def\collect@cell@addarg#1{%
  \expandafter\expandafter\expandafter\collect@cell@toks
  \expandafter\expandafter\expandafter
  {\expandafter\the\expandafter\collect@cell@toks\collect@cell@spaces#1}%
  \let\collect@cell@spaces\empty
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\collect@cell@addcc}
% This macro is called when another |\collectcell| is found in the preamble
% (at the moment also inside the cell). The argument of it is placed into the
% token register and all following tokens are placed in an own token list which content
% is then added with surrounding braces in the outer token list once the |\endcollectcell|
% is found. TeX scoping mechanism is used for this so only one token register is required.
%    \begin{macrocode}
\def\collect@cell@addcc#1{%
  \collect@cell@addarg{#1}%
  \begingroup
  \collect@cell@toks{}%
  \collect@cell@look
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\collect@cell@checkcsname}
% For support of |\end{tabularx}| without trailing |\\|.
%    \begin{macrocode}
\def\collect@cell@checkcsname#1\endcsname{%
  \begingroup
  \expandafter\ccell@swap\expandafter
    {\expandafter,\@currenvir,endtabular,endtabular*,array,tabularx,}%
    {\in@{,#1,}}%
  \ifin@
    \endgroup
    \expandafter\@firstoftwo
  \else
    \endgroup
    \expandafter\@secondoftwo
  \fi
    {\collect@cell@cr\tabularnewline\csname#1\endcsname}%
    {\collect@cell@addarg{\csname#1\endcsname}\collect@cell@look}%
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\collect@cell@checkend}[1]{The argument of an \string\end~macro}
% Reads the argument of |\end| and checks if it is identical to the current environment (|tabular|, |array|, |tabularx|, ...).
% If so the collecting of token is ended, otherwise the |\end| and its argument are added to the
%    \begin{macrocode}
\def\collect@cell@checkend#1{%
  \begingroup
  \def\@tempa{#1}%
  \ifx\@tempa\@currenvir
    \endgroup
    \expandafter\@firstoftwo
  \else
    \endgroup
    \expandafter\@secondoftwo
  \fi
    {\collect@cell@cr\tabularnewline\end{#1}}%
    {\collect@cell@addarg{\end{#1}}\collect@cell@look}%
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\cc@iftoken}
% Compares the |\collect@cell@lettoken| with the token given as argument.
%    \begin{macrocode}
\def\cc@iftoken#1{%
  \ifx#1\collect@cell@lettoken
    \expandafter\@firstoftwo
  \else
    \expandafter\@secondoftwo
  \fi
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\cc@case}
% Case statement over |\collect@cell@lettoken|.
%    \begin{macrocode}
\def\cc@case{%
  \begingroup
  \let\default= \collect@cell@lettoken
  \cc@@case
}
\def\cc@@case#1{%
  \ifx#1\collect@cell@lettoken
    \expandafter\cc@@truecase
  \else
    \expandafter\cc@@falsecase
  \fi
}
\def\cc@@truecase#1#2\endcc@case{\endgroup#1}
\def\cc@@falsecase#1{\cc@@case}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\collcell@unskip}
% Wrapper around |\unskip| to protect it from the eyes of the token scanner.
% It is protected to avoid trouble if the user wrongly uses it at the beginning of the cell.
% The macro is first defined using |\newcommand| to warn the user about name collisions.
%    \begin{macrocode}
\newcommand*\ccunskip{}
\protected\def\ccunskip{\unskip}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\cci}
% Protected empty macro usable to stop the expansion of tokens at the beginning of the
% cell. It is ignored (gobbled) by the token scanner.
% The macro is first defined using |\newcommand| to warn the user about name collisions.
%    \begin{macrocode}
\newcommand*\cci{}
\protected\def\cci{}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\collect@cell@cr}
% Redefines the table line/row end macro |\cr| so that
% token collection is restarted after the real |\cr| is expanded
% and the end material defined by `<{}` is inserted.
%
% This redefinition must be done around some \emph{dirty tricks}
% otherwise the |\cr| will be wrongly taken as end of the
% row.
%
% Because the redefinition is done just at the end of a cell inside the group
% opened by |collcell| it will only be locally.
%    \begin{macrocode}
\def\collect@cell@cr{%
  \iffalse{\fi
  \let\collcell@realcr\cr
  \def\cr{%
    \collect@cell@look
    \collcell@realcr
  }%
  \iffalse}\fi
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\collect@cell@arg}
% \begin{macro}{\collect@cell@grab}
% \begin{macro}{\l@collect@cell@env@cnt}
% Handles the arguments.
% The first token of the argument is still in the |lettoken| macro which is compared
% against a list of possible end tokens.
% Then either the cell end is handled or the argument is added to the token register
% and the rest of the cell is processed.
%    \begin{macrocode}
\def\collect@cell@arg#1{%
  \cc@case
    \tabularnewline{\ifnum\l@collect@cell@env@cnt=0 %
        \expandafter\collect@cell@cr
      \else
        \expandafter\collect@cell@grab
      \fi
      #1%
    }%
    \begin{\advance\l@collect@cell@env@cnt by 1 %
      \collect@cell@grab\begin}%
    \end{\advance\l@collect@cell@env@cnt by -1 %
      \collect@cell@checkend}%
    \end{\collect@cell@checkend}%
    \csname{\collect@cell@checkcsname}%
    \unskip{%
      \let\collect@cell@spaces\empty
      %\collect@cell@addarg{#1}% do not include the \unskip
      \collect@cell@look%
    }%
    \textonly@unskip{%
      \let\collect@cell@spaces\empty
      \collect@cell@look%
    }%
    \@sharp{%
      \expandafter\collect@cell@addarg\expandafter{#1}%
      \collect@cell@look
    }%
    \collectcell{%
      \advance\collect@cell@count by \@ne
      \collect@cell@addcc%
    }%
    \endcollectcell{%
      \ifnum\collect@cell@count=\z@
        \expandafter\collect@cell@end
      \else
        \expandafter\endgroup
        \expandafter\collect@cell@addarg\expandafter
        {\expandafter{\the\collect@cell@toks}}%
        \advance\collect@cell@count by \m@ne%
        \expandafter\collect@cell@look
      \fi
    }%
    \cci{%
      \collect@cell@look
    }%
    \default{%
      \expandafter\ccell@swap\expandafter
        {\csname endtabular*\endcsname\endtabular\endarray}{\in@{#1}}%
      \ifin@
          \expandafter\@firstoftwo
      \else
          \expandafter\@secondoftwo
      \fi
      {\collect@cell@cr\tabularnewline#1}%
      {%
        \collect@cell@addarg{#1}%
        \collect@cell@look
      }%
    }%
 \endcc@case
}
\long\def\collect@cell@grab#1{%
  \collect@cell@addarg{#1}%
  \collect@cell@look
}
\newcount\l@collect@cell@env@cnt
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \iffalse
%</collcell.sty>
% \fi
%
% \Finale
% \endinput

