\def\tabstackengineversionnumber{V1.10}
%
% tabstackengine initial release
%
% THIS MATERIAL IS SUBJECT TO THE LaTeX Project Public License
%
% V1.00 -Adopted beta version 0.21 as initial release version 1.0
% V1.10 -Corrected unary/binary problem for left end of tabbed cell content;
%       -Added \TABunaryLeft (\TABbinaryRight) for "   cell{} ";
%        added \TABunaryRight (\TABbinaryLeft) for " {}cell   ";
%        added \TABbinary                      for " {}cell{} ";
%        The default is \TABunaryLeft (V1.00 wrongly equivalent to \TABbinary)
%        This removes need to brace unary negatives at lead of cell.
%       -Corrected bug of trailing \frac, noted in V1.00, by adding a
%        \relax to definition of \@postTAB in \readTABrow.
%
\ProvidesPackage{tabstackengine}
[2014/02/19 (\tabstackengineversionnumber) tabbed stacking]
\RequirePackage[usestackEOL]{stackengine}[2013-10-15]
\RequirePackage{calc}

\newtoggle{@doneTABreads}
\newcounter{TAB@stackindex}
\newcounter{TABcellindex@}
\newlength\maxTAB@width

\newcommand\setstackTAB[1]{%
  \ifstrempty{#1}{\def\TAB@char{ }}{\def\TAB@char{#1}}%
  \expandafter\define@processTABrow\expandafter{\TAB@char}%
}

\newcommand\define@processTABrow[1]{%
    \def\@processTABrow##1#1##2||{%
      \def\@preTAB{##1}%
      \def\@postTAB{##2}%
    }%
}
\setstackTAB{&}

\newcommand\readTABrow[2]{%
  \edef\row@ID{#1}%
  \togglefalse{@doneTABreads}%
  \edef\@postTAB{\unexpanded{#2\relax}\expandonce{\TAB@char}}%
  \setcounter{TABcellindex@}{0}%
  \whileboolexpr{ test {\nottoggle{@doneTABreads}}}{%
    \stepcounter{TABcellindex@}%
    \expandafter\@processTABrow\@postTAB||%
    \global\csedef{TABX\row@ID X\roman{TABcellindex@}}{\expandonce\@preTAB}%
    \setbox0=\hbox{%
      \stack@delim\TABcell{\row@ID}{\theTABcellindex@}\stack@delim}%
    \ifdim\wd0>\maxTAB@width\setlength{\maxTAB@width}{\the\wd0}\fi%
    \expandafter\ifstrempty\expandafter{\@postTAB}{%
      \toggletrue{@doneTABreads}%
    }{}%
  }%
  \expandafter\xdef\csname \row@ID TABcells\endcsname{\arabic{TABcellindex@}}%
  \find@TABstrut{#1}%
}

\newcommand\find@TABstrut[1]{%
  \def\@accumulatedTAB{}%
  \setcounter{TABcellindex@}{0}%
  \expandafter\protected@edef\csname @#1TABtextblob\endcsname{}%
  \whileboolexpr{test {\ifnumless{\theTABcellindex@}{\TABcells{#1}}}}{%
    \stepcounter{TABcellindex@}%
    \protected@edef\@accumulatedTAB{%
      \@accumulatedTAB\TABcell{#1}{\theTABcellindex@}}%
  }%
  \global\csedef{@#1TABtextblob}{\expandonce\@accumulatedTAB}%
}

\def\p@Tstrut#1{\protect\TABstrut{#1}}

\newcommand\TABunaryLeft{%
  \def\TAB@strutLeftA{}%
  \def\TAB@strutRightA{\p@Tstrut{i}}%
  \def\TAB@strutLeftB{}%
  \def\TAB@strutRightB{\p@Tstrut{ii}}%
  \def\TAB@strutLeftC{}%
  \def\TAB@strutRightC{\p@Tstrut{\TAB@prefix}}%
}
\let\TABbinaryRight\TABunaryLeft

\newcommand\TABunaryRight{%
  \def\TAB@strutLeftA{\p@Tstrut{i}}%
  \def\TAB@strutRightA{}%
  \def\TAB@strutLeftB{\p@Tstrut{ii}}%
  \def\TAB@strutRightB{}%
  \def\TAB@strutLeftC{\p@Tstrut{\TAB@prefix}}%
  \def\TAB@strutRightC{}%
}
\let\TABbinaryLeft\TABunaryRight

\newcommand\TABbinary{%
  \def\TAB@strutLeftA{{}}%
  \def\TAB@strutRightA{\p@Tstrut{i}}%
  \def\TAB@strutLeftB{{}}%
  \def\TAB@strutRightB{\p@Tstrut{ii}}%
  \def\TAB@strutLeftC{{}}%
  \def\TAB@strutRightC{\p@Tstrut{\TAB@prefix}}%
}
\TABunaryLeft

\newcommand\TAB@delim[1]{#1}%
\newcommand\TABstackMath{%
  \renewcommand\TAB@delim[1]{\ensuremath{##1}}%
}
\newcommand\TABstackText{%
  \renewcommand\TAB@delim[1]{##1}%
}

\newcommand\TABcell[2]{\TAB@delim{%
  \ignorespaces\csname TABX#1X\romannumeral#2\endcsname\unskip}}

\newcommand\TABcells[1]{\csname #1TABcells\endcsname}

% NOTE THAT THE STRUT IS NOT YET TYPESET, SINCE WE DO NOT YET KNOW
% WHETHER \@#1textblob IS TO BE INVOKED IN MATH MODE OR NOT
\newcommand\TABstrut[1]{\vphantom{\csname @#1TABtextblob\endcsname}}

\newcommand\tabbedShortstack[2][\stackalignment]{%
  \@TAB@stack{#1}{#2}{D}{\Shortstack}}

\newcommand\alignShortstack[1]{%
  \@TAB@stack{}{#1}{A}{\Shortstack}}

\newcommand\tabularShortstack[2]{%
  \@TAB@stack{}{#2}{#1}{\Shortstack}}

\newcommand\tabbedShortunderstack[2][\stackalignment]{%
  \@TAB@stack{#1}{#2}{D}{\Shortunderstack}}

\newcommand\alignShortunderstack[1]{%
  \@TAB@stack{}{#1}{A}{\Shortunderstack}}

\newcommand\tabularShortunderstack[2]{%
  \@TAB@stack{}{#2}{#1}{\Shortunderstack}}

\newcommand\tabbedLongstack[2][\stackalignment]{%
  \@TAB@stack{#1}{#2}{D}{\Longstack}}

\newcommand\alignLongstack[1]{%
  \@TAB@stack{}{#1}{A}{\Longstack}}

\newcommand\tabularLongstack[2]{%
  \@TAB@stack{}{#2}{#1}{\Longstack}}

\newcommand\tabbedLongunderstack[2][\stackalignment]{%
  \@TAB@stack{#1}{#2}{D}{\Longunderstack}}

\newcommand\alignLongunderstack[1]{%
  \@TAB@stack{}{#1}{A}{\Longunderstack}}

\newcommand\tabularLongunderstack[2]{%
  \@TAB@stack{}{#2}{#1}{\Longunderstack}}

\newcommand\tabbedCenterstack[2][\stackalignment]{%
  \@TAB@stack{#1}{#2}{D}{\Centerstack}}

\newcommand\alignCenterstack[1]{%
  \@TAB@stack{}{#1}{A}{\Centerstack}}

\newcommand\tabularCenterstack[2]{%
  \@TAB@stack{}{#2}{#1}{\Centerstack}}

\newcommand\tabbedVectorstack[2][\stackalignment]{%
  \ensureTABstackMath{\@TAB@stack{#1}{#2}{D}{\Vectorstack}}}

\newcommand\alignVectorstack[1]{%
  \ensureTABstackMath{\@TAB@stack{}{#1}{A}{\Vectorstack}}}

\newcommand\tabularVectorstack[2]{%
  \ensureTABstackMath{\@TAB@stack{}{#2}{#1}{\Vectorstack}}}

\newcommand\parenMatrixstack[2][\stackalignment]{%
  \ensureTABstackMath{\left(\@TAB@stack{#1}{#2}{D}{\Vectorstack}\right)}}

\newcommand\braceMatrixstack[2][\stackalignment]{%
  \ensureTABstackMath{\left\{\@TAB@stack{#1}{#2}{D}{\Vectorstack}\right\}}}

\newcommand\bracketMatrixstack[2][\stackalignment]{%
  \ensureTABstackMath{\left[\@TAB@stack{#1}{#2}{D}{\Vectorstack}\right]}}

\newcommand\vertMatrixstack[2][\stackalignment]{%
  \ensureTABstackMath{\left|\@TAB@stack{#1}{#2}{D}{\Vectorstack}\right|}}

\newcommand\@TAB@stack[4]{%
  \setlength{\maxTAB@width}{0pt}%
  \let\sv@stackalignment\stackalignment%
  \edef\stackalignment{#1}%
  \@readMANYrows{#2}%
  \edef\TAB@narg{\narg}%
  \setcounter{TAB@stackindex}{0}%
  \whileboolexpr{test {\ifnumless{\theTAB@stackindex}{\TAB@narg}}}{%
    \stepcounter{TAB@stackindex}%
    \edef\TAB@prefix{\roman{TAB@stackindex}}%
    \protected@edef\TABrow@data{\csname arg\TAB@prefix\endcsname}%
    \def\@tmp{\readTABrow{\TAB@prefix}}%
    \expandafter\@tmp\expandafter{\TABrow@data}%
  }%
%
  \setcounter{TABcellindex@}{0}%
  \whileboolexpr{test {\ifnumless{\theTABcellindex@}{\TABcells{i}}}}{%
    \def\col@stack{%
        \TAB@strutLeftA%
        \TABcell{i}{\theTABcellindex@}%
        \TAB@strutRightA%
}%
    \stepcounter{TABcellindex@}%
    \@getTABalignment{#3}{\theTABcellindex@}%
    \ifboolexpr{%
      test {\ifnumgreater{\theTABcellindex@}{1}}%
    }{\add@TAB@gap{#3}{\theTABcellindex@}}{}%
    \setcounter{TAB@stackindex}{1}%
    \whileboolexpr{test {\ifnumless{\theTAB@stackindex}{\TAB@narg}}}{%
      \stepcounter{TAB@stackindex}%
      \edef\TAB@prefix{\roman{TAB@stackindex}}%
      \protected@edef\col@stack{\col@stack\SEP@char%
        \TAB@strutLeftC%
        \TABcell{\TAB@prefix}{\theTABcellindex@}%
        \TAB@strutRightC%
      }%
    }%
    \iftoggle{fixed@TABwidth}%
      {\makebox[\the\maxTAB@width][\stackalignment]{%
        \expandafter#4\expandafter{\col@stack}}}%
      {\expandafter#4\expandafter{\col@stack}}%
  }%
  \let\stackalignment\sv@stackalignment%
}

\newcommand\tabbedstackon[3][\stackgap]{%
  \@TABstackonunder{#1}{#2}{#3}{D}{\stackon}}

\newcommand\alignstackon[3][\stackgap]{%
  \@TABstackonunder{#1}{#2}{#3}{A}{\stackon}}

\newcommand\tabularstackon[4][\stackgap]{%
  \@TABstackonunder{#1}{#3}{#4}{#2}{\stackon}}

\newcommand\tabbedstackunder[3][\stackgap]{%
  \@TABstackonunder{#1}{#2}{#3}{D}{\stackunder}}

\newcommand\alignstackunder[3][\stackgap]{%
  \@TABstackonunder{#1}{#2}{#3}{A}{\stackunder}}

\newcommand\tabularstackunder[4][\stackgap]{%
  \@TABstackonunder{#1}{#3}{#4}{#2}{\stackunder}}

\newcommand\tabbedstackanchor[3][\stackgap]{%
  \@TABstackonunder{#1}{#2}{#3}{D}{\stackanchor}}

\newcommand\alignstackanchor[3][\stackgap]{%
  \@TABstackonunder{#1}{#2}{#3}{A}{\stackanchor}}

\newcommand\tabularstackanchor[4][\stackgap]{%
  \@TABstackonunder{#1}{#3}{#4}{#2}{\stackanchor}}

\newcommand\@TABstackonunder[5]{%
  \setlength{\maxTAB@width}{0pt}%
  \let\sv@stackalignment\stackalignment%
  \readTABrow{i}{#2}%
  \readTABrow{ii}{#3}%
  \setcounter{TABcellindex@}{0}%
  \whileboolexpr{test {\ifnumless{\theTABcellindex@}{\TABcells{i}}}}{%
    \stepcounter{TABcellindex@}%
    \@getTABalignment{#4}{\theTABcellindex@}%
    \ifboolexpr{%
      test {\ifnumgreater{\theTABcellindex@}{1}}%
    }{\add@TAB@gap{#4}{\theTABcellindex@}}{}%
    \iftoggle{fixed@TABwidth}%
      {\makebox[\the\maxTAB@width][\stackalignment]{%
       #5[#1]{\TAB@strutLeftA\TABcell{i}{\theTABcellindex@}\TAB@strutRightA}%
              {\TAB@strutLeftB\TABcell{ii}{\theTABcellindex@}\TAB@strutRightB}}}%
      {#5[#1]{\TAB@strutLeftA\TABcell{i}{\theTABcellindex@}\TAB@strutRightA}%
              {\TAB@strutLeftB\TABcell{ii}{\theTABcellindex@}\TAB@strutRightB}}%
  }%
  \let\stackalignment\sv@stackalignment%
}

\newcommand\@getTABalignment[2]{%
  \ifstrequal{#1}{D}{}{%                    T, DO NOTHING (USE \stackalignment)
    \ifstrequal{#1}{A}{%
      \ifnumequal{1}{#2}{%
        \def\stackalignment{r}}{%          A, 1st ELEMENT, SET TO r
        \if l\stackalignment%
          \def\stackalignment{r}\else%     A, SWITCH l TO r
          \def\stackalignment{l}\fi}}{%    A, SWITCH r TO l
          \set@tabularcellalignment{#1}{#2}%   tabular, READ #2 location
      }%
  }%
}

\def\tabbed@gap{0pt}
\def\align@gap{1em}
\def\tabular@gap{\tabcolsep}

\newcommand\setstacktabbedgap[1]{\def\tabbed@gap{#1}}
\newcommand\setstackaligngap[1]{\def\align@gap{#1}}
\newcommand\setstacktabulargap[1]{\def\tabular@gap{#1}}

\newcommand\add@TAB@gap[2]{%
  \ifstrequal{#1}{D}{\hspace{\tabbed@gap}}{%
    \ifstrequal{#1}{A}{%
      \if r\stackalignment\hspace{\align@gap}\fi%
    }{%  
      \hspace{\tabular@gap}%
    }%
  }%
}

\newcounter{TABalignmentindex@}

\newcommand\set@tabularcellalignment[2]{%
  \setcounter{TABalignmentindex@}{1}%
  \edef\tabular@settings{#1.}%
  \whileboolexpr{test {\ifnumless{\theTABalignmentindex@}{#2}}}{%
    \stepcounter{TABalignmentindex@}%
    \edef\tabular@settings{\expandafter\@gobble\tabular@settings.}%
  }%
  \expandafter\@getnextTABchar\tabular@settings\\% GET NEXT TAB ALIGNMENT
  \if l\@nextTABchar\edef\stackalignment{l}\else%
    \if r\@nextTABchar\edef\stackalignment{r}\else%
      \if c\@nextTABchar\edef\stackalignment{c}\fi%
    \fi%                                        IGNORE IF NOT l, c, OR r
  \fi%
}

\def\@getnextTABchar#1#2\\{\gdef\@nextTABchar{#1}}


\newtoggle{fixed@TABwidth}
\newcommand\fixTABwidth[1]{%
  \if T#1\toggletrue{fixed@TABwidth}\else\togglefalse{fixed@TABwidth}\fi%
}
\fixTABwidth{F}

\newcommand\ensureTABstackMath[1]{\TABstackMath#1\TABstackText}

\endinput
