% Tableau macros -- tabmac.sty, by Glenn Tesler
% Do not further distribute until further notice; it's incomplete now.
%
% loading in LaTeX (<2e):
% \documentstyle[...,tabmac,...]{article}
% or to use arrows through pb-diagram, things must go in this order:
%    \documentstyle[...,pb-diagram,tabmac,...]{article}
% or \documentstyle[...,pb-diagram,lamsarrow,pb-lams,tabmac,...]{article}
%
% loading in LaTeX 2e:
%    \usepackage{tabmac}
% or \usepackage{pb-diagram,lamsarrow,pb-lams,tabmac}
%
% loading in plain TeX:
%    \input tabmac.sty
%
%%%%%%%% DISABLED
%%%%%%% \tableau[options]{row1|row2|...|rowk}       (can use \\ instead of |)
%%%%%%%% \tableau*[options]{row1\\row2\\...\\rowk}
%%%%%%%% rowk may be followed by optional | or \\, so to actually produce
%%%%%%%% a final row with only one entry, terminate with || or \\ \\
%
% \tableau{row1 \cr row2 \cr ... rowk}
% \tableau{row1 \\  row2 \\  ... rowk}
% \tableau[options]{row1 \cr row2 \cr ... rowk}
% \tableau[options]{row1 \\  row2 \\  ... rowk}
% rowk may be followed by optional \\ or \cr, so to actually produce
% a final row with only one entry, terminate with \cr\cr or \\ \\
%
% options:
%       alignment:
%               c: center,  b: bottom,  t: top
%       diagram type:
%		F: Ferrer's diagram	Y: Young diagram	E: empty
%		               F	Y		E
%             dflt cell frame  none     thin frame	no frame
%             null cells       \bullet  thin frame	no content
%             ~ (for skew)     \bullet  no frame	no frame or content
%          a: use arrow font dimension as base instead of \strut
%       cell size in multiples of current font's \strut's dimensions
%              s: small (x1), m: medium (x2 -- default), l: large (x3)
%              p: small partition sized
% can set variable \Tscale for scaling as well.
% If you do this, don't use s,m,l as they will override this setting.
% can use font size declarations -- \tiny, \Large, etc. -- to change
% font size and cell size, too.
%
% rowi has the form
%	c1 & c2 & c3 & ... & cn \cr
%%%%%%       c1,c2,c3,c4,...,cn		DISABLED
% where these are the entries to go on the row.  Can use & instead of ,
%%%%%% in * form, must use &		DISABLED
% If no entry is given, the cell is a frame (Young) or a bullet (Ferrers)
% special entries
%%%%% (only \ forms available with \tableau*)	DISABLED
%  \bullet, %@ = bullet (unframed in Ferrers, framed in Young)
%  \bl        = blank (no frame in either)
%  \sk, %~     = skew cell (use in upper left corner of tableau;
%                      no frame in Young, bullet in Ferrer)
%  \tf, %*     = thick frame
%  \fl        = filled square
%  \fr[options] = frame with these characteristics (use any combination
%		  of letters)
%			t,b,l,r: top, bottom, left, right
%			w:	 thick frame
%  \overlay ... = superimpose ... on this cell (terminate with another
%                 \overlay, or with the end of the tab field)
%  \overlay[??] ... = superimpose ... on this cell with alignment given by
%                      combination of the characters in ??
%                      t, c, b -- top, center, bottom
%                      l, m, r -- left, middle, right
%%%%%%%  \rp[N]	repeat this cell N times horizontally  **** DOESN'T WORK ****
%
% To get a blank row, use the one entry \bl on that row, i.e., |\bl|
% because doing || will yield a one-square row (Young) or one bullet row
% (Ferrers)
%
% The \arrow command from pb-diagram is implemented.
% Use the exact same syntax for \arrow as in diagram.
% Additional parameters which dgo@???? routines may set are two routines
%    \def\tb@getnodesizehead#1#2{...}
%    \def\tb@getnodesizetail#1#2{...}
% which put the width & height of the text at the head or tail nodes
% into number registers #1, #2, in units of scaled points.
%
% Arrow bugs:
%    The tableau dimensions don't correspond to the restricted
%    discrete arrow lengths, so when real small arrow wanted,
%    only a longer one might be available; option ``a'' may help.
%
%    Dashed arrows may not be uniformly dashed.

%  \skewptn(a1,b1,c1,d1,...|a2,b2,c2,d2,...|...)
%  \skewptn[options](a1,b1,c1,d1,...|a2,b2,c2,d2,...|...)
% for diagrams w/o fillings only:
%	top row: draw a1 cells, leave b1 blank, draw c1 cells,...
%	2nd row: draw a2 cells, leave b2 blank, draw c2 cells,...
%	...
% options are same as for \tableau.  Scaling is determined by \Pscale
% instead of \Tscale, and the options s,m,l,p,a override it.



%
% More to do
%    Add in LaTeX picture mode; put in alternate frames (dashed, oval, circle)
%    from LaTeX picture mode instead of just the thin and bold frames,
%    and use the picture mode \linethickness declaration instead of
%    \tb@fframe,...
%
%
% w/in tableau,   \dimen0=cell size, \dimen1=frame size, \dimen2=strut size
% with option "a", \dimen2 is replaced by value better suited to arrows.
%
% Be very careful that all lines end in %
% so that no spurious spaces are introduced anywhere.

% who knows how @ is defined with all the ways this file could be loaded...
% so save its current catcode and restore it at the end.
\edef\savecatcodeat{\the\catcode`@}
\catcode`\@=11

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%	BEGIN code for \@ifnextchar from LaTeX, so that we can use in TeX too.
%	Altered by changing its name only.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\def\@IFNEXTCHAR#1#2#3{\let\@tempe #1\def\@tempa{#2}\def\@tempb{#3}\futurelet
    \@tempc\@IFNCH}
\def\@IFNCH{\ifx \@tempc \@sptoken \let\@tempd\@xifnch
      \else \ifx \@tempc \@tempe\let\@tempd\@tempa\else\let\@tempd\@tempb\fi
      \fi \@tempd}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%	END code for \@ifnextchar from LaTeX
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\def\tb@ifSpecChars#1#2{#1}
\def\tb@ifNoSpecChars#1#2{#2}

\newcount\tb@rpN

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%	\tableau
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% Determine if * form used
\def\tableau{%
  \bgroup% matched in \tb@tableauD
  \@ifstar{\let\Tif\tb@ifNoSpecChars\tb@tableauB}% *, don't use special chars
          {\let\Tif\tb@ifSpecChars\tb@tableauB}}% no *, use special chars
%	\tb@tableauB%
%}
%
\def\tb@tableauB{%
  \@IFNEXTCHAR[{\tb@tableauC}{\tb@tableauC[]}}     % add [] if no [options]

\def\tb@tableauC[#1]{\hbox\bgroup%
    \let\\=\cr% end line
    \def\bl{\global\let\tbcellF\tb@cellNF}%
    \def\tf{\global\let\tbcellF\tb@cellH}% highlighted cell
%
%   \dimen0=cell size, \dimen1=frame size, \dimen2=strut size
    \dimen2=\ht\strutbox \advance\dimen2 by\dp\strutbox%
    \ifx\baselinestretch\undefined\relax%
    \else%
% want \dimen2 = \dimen2 / \baselinestretch, but can't do that if
% \baselinestretch has a decimal, so fake it to 2 decimal places.
       \dimen0=100sp \dimen0=\baselinestretch\dimen0%
       \dimen2=100\dimen2 \divide\dimen2 by\dimen0%
    \fi%
%
    \let\tpos\tb@vcenter% default position
    \tb@initYoung% default tableau type
    \tb@options#1\eoo% parse options
%
    \let\arrow\tb@arrow%
%
    \dimen0=\Tscale\dimen2%
    \dimen1=\dimen0 \advance\dimen1 by \tb@fframe%
%
    \lineskip=0pt\baselineskip=0pt% line spacing will be from \vbox to \dimen0
%
    % \mkcell{#1} --  format individual cell:
    %   set cellF to default frame.
    %   supply argument for cell if none given
    %   format argument in sized box, then superimpose cell frame.
    \def\tb@nothing{}%
    \def\endcellno{$\rss\egroup\bss\egroup}% end cell w/o overlap
    \def\endcell{\endcellno\kern-\dimen0}% end cell & prepare to overlap it
    \def\begincell{\vbox to\dimen0\bgroup\vss\hbox to\dimen0\bgroup\hss$}%
%    \def\overlay{\endcell\begincell}%
    \let\overlay\tb@overlay%
    \let\fl\tb@fl%
    \let\fr\tb@fr%
%%%    \let\rp\tb@rp%
    \let\lss\hss\let\rss\hss\let\tss\vss\let\bss\vss% cell alignment
    \def\mkcell##1{% format individual cell
        \let\tbcellF\tb@cellD% default cell frame
        \def\tb@cellarg{##1}% store cell contents
        % provide default contents if cell empty
        \ifx\tb@cellarg\tb@nothing\let\tb@cellarg\tb@cellE\fi%
%
%%%      \tb@rpN=0
%%%      \loop%	% repeat cell contents 1 or rpN times, where rpN may be set
%%%		% by the argument to mkcell
	        \begincell\tb@cellarg\endcellno% the actual cell content
	        \tbcellF% draw cell frame
%%%      \ifnum\tb@rpN>1\advance\tb@rpN by-1%
%%%%	\span\omit%
%%%      \repeat%
    }%
%
    \let\savecellF\tbcellF% save global value of cellF in case of nested tableau
     \Tif{\catcode`,=4\catcode`|=\active}{}\tb@tableauD}%




\let\tb@savetableauD\tableauD% save any current definition
{% set up characters which will be interpreted as command characters
% when the definition of \tableauD is read in
    \catcode`|=\active \catcode`*=\active \catcode`~=\active%
    \catcode`@=\active% command characters
\gdef\tableauD#1{%
  \Tif{% make all the command characters active in math mode when #1 parsed
    \mathcode`|="8000 \mathcode`*="8000%
    \mathcode`~="8000 \mathcode`@="8000%
    \def@{\bullet}%
    \let|\cr% end line
    \let*\tf% highlighted cell
    \let~\sk% skew cell
  }{}%
  \tpos{\tabskip=0pt\halign{&\mkcell{##}\cr#1\crcr}}%
  \global\let\tbcellF\savecellF% restore global value
  \egroup% match \hbox\bgroup at start of \tableauC
  \egroup}% match \bgroup at start of \tableau
}
\let\tb@tableauD\tableauD% rename the command
\let\tableauD\tb@savetableauD% restore old command with this name
\let\tb@savetableauD\undefined

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                      Parse options in \tableau[options]
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% pick out one option at a time until \eoo reached.
\def\tb@options#1{\ifx#1\eoo\relax\else\tb@option#1\expandafter\tb@options\fi}

% dispatch handler for each option
\def\tb@option#1{%
  \if#1t\let\tpos\tb@vtop\fi%        t = align at top
  \if#1c\let\tpos\tb@vcenter\fi%     c = align at center
  \if#1b\let\tpos\vbox\fi%           b = align at bottom
  \if#1F\tb@initFerrers\fi%          F = Ferrers diagram
  \if#1Y\tb@initYoung\fi%            Y = Young diagram
  \if#1E\tb@initEmpty\fi%	     E = empty diagram
  \if#1s\tb@initSmall\fi%            s = small boxes
  \if#1m\tb@initMedium\fi%           m = medium boxes
  \if#1l\tb@initLarge\fi%            l = large boxes
  \if#1p\tb@initPartition\fi%        p = small partition sized boxes
  \if#1a\tb@initArrow\fi%            a = use arrow font as base dimension
}

% alternate to \vcenter which starts math mode if necessary
\def\tb@vcenter#1{\ifmmode\vcenter{#1}\else$\vcenter{#1}$\fi}

% alternate to \vtop; the array produced by \halign has as its baseline
% the lower border of the first row of the tableau, so move down by this
% amount, and move up \ht\strutbox to align the top border with the
% top of the text on this line.
\def\tb@vtop#1{\hbox{\raise\ht\strutbox\hbox{\lower\dimen0\vtop{#1}}}}

\def\tb@initPartition{\def\Tscale{.3}}
\def\tb@initSmall{\def\Tscale{1}}
\def\tb@initMedium{\def\Tscale{2}}
\def\tb@initLarge{\def\Tscale{3}}

% diagram has dimens hardcoded.  Arrow is .625em
\def\tb@initArrow{\dimen2=1.25em}


\def\tb@initYoung{%
  \def\tb@cellE{}%				% empty cell stays empty
  \let\tb@cellD\tb@cellN%			% default frame is normal frame
  \def\sk{\global\let\tbcellF\tb@cellNF}}%	% skew cells are empty
\def\tb@initFerrers{%
  \def\tb@cellE{\bullet}%			% empty cell gets bullet
  \let\tb@cellD\tb@cellNF%			% default frame is no frame
  \def\sk{\bullet}}%				% skew cell gets bullet
\def\tb@initEmpty{%
  \def\tb@cellE{}%				% empty cell stays empty
  \let\tb@cellD\tb@cellNF%			% default frame is no frame
  \def\sk{\global\let\tbcellF\tb@cellNF}}%	% skew cells are empty

\tb@initMedium% default scale


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%               draw square frame with edges of given thickness
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% initial refrence pt = upper right corner of cell
\def\tb@sframe#1{%
  \vbox to0pt{%            Embed frame in a box of no vert or hor extent
    \vss%                            pull box above reference point
    \hbox to0pt{%
      \hss%                          pull box left of reference point
      \vbox to\dimen1{%              Actual width of frame
        \hrule depth #1 height0pt% draw top edge of frame
        \vss%                     begin vcenter sides
        \hbox to\dimen1{%           horiz box with side edges just inside
          \vrule width #1 height\dimen1% left edge
          \hss%                     stretch center
          \vrule width #1%         right edge
          }%
        \vss%                     end vcenter sides
        \hrule height #1 depth 0in% bottom edge
        }%
      \kern-\tb@hframe%           horiz alignment off by half line width
      }%
    \kern-\tb@hframe}}%           vert alignment off by half line width
% alignment off by \dimen1-\dimen0=2\tb@hframe



% should this be combined with picture modes' linethickness?
% \tb@fframe = width of ordinary divider line
% \tb@hframe = \tb@fframe/2
% \tb@bframe = width of bold divider line;
%     ought to have \tb@bframe >= \tb@fframe
\def\tb@hframe{.2pt}\def\tb@fframe{.4pt}\def\tb@bframe{2pt}
\def\tb@cellH{\tb@sframe{\tb@bframe}}       % bold frame
\def\tb@cellNF{}                            % no frame
\def\tb@cellN{\tb@sframe{\tb@fframe}}       % normal frame
\let\tbcellF\tb@cellN                       % default is normal

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%               draw fragments of square frame with edges
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% initial refrence pt = upper right corner of cell
\def\tb@Fsframe{%
  \vbox to0pt{%            Embed frame in a box of no vert or hor extent
    \vss%                            pull box above reference point
    \hbox to0pt{%
      \hss%                          pull box left of reference point
      \vbox to\dimen1{%              Actual width of frame
        \fr@iftop{\hrule depth \fr@width height0pt}{\vskip \fr@width}% draw top edge of frame
        \vss%                     begin vcenter sides
        \hbox to\dimen1{%           horiz box with side edges just inside
	  \fr@ifleft{\vrule width \fr@width height\dimen1}{\hskip \fr@width}% left edge
          \hss%                     stretch center
          \fr@ifright{\vrule width \fr@width height\dimen1}{\hskip \fr@width}% right edge
          }%
        \vss%                     end vcenter sides
        \fr@ifbottom{\hrule height \fr@width depth 0in}{\vskip\fr@width}% bottom edge
        }%
      \kern-\tb@hframe%           horiz alignment off by half line width
      }%
    \kern-\tb@hframe}}%           vert alignment off by half line width
% alignment off by \dimen1-\dimen0=2\tb@hframe

\def\tb@fr{\@IFNEXTCHAR[{\tb@fra}{\global\let\tbcellF\tb@cellN}}
\def\tb@fra[#1]{%
	\global\let\fr@iftop\tb@IFNO%			% set defaults
	\global\let\fr@ifbottom\tb@IFNO%
	\global\let\fr@ifleft\tb@IFNO%
	\global\let\fr@ifright\tb@IFNO%
	\global\let\fr@width\tb@fframe%
	\global\let\tbcellF\tb@Fsframe%
%
	\froptions#1\eoo% parse options
}
% pick out one option at a time until \eoo reached
\def\froptions#1{\ifx#1\eoo\relax\else\froption#1\expandafter\froptions\fi}
% dispatch handler for each option
\def\froption#1{
	\if#1t\global\let\fr@iftop\tb@IFYES\fi%	% t = draw top of cell
	\if#1b\global\let\fr@ifbottom\tb@IFYES\fi%	% b = draw bottom of cell
	\if#1l\global\let\fr@ifleft\tb@IFYES\fi%	% l = draw left of cell
	\if#1r\global\let\fr@ifright\tb@IFYES\fi%	% r = draw right of cell
	\if#1w\global\let\fr@width\tb@bframe\fi%	% w = bold
}
\def\tb@IFYES#1#2{#1}
\def\tb@IFNO#1#2{#2}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                             overlay cell contents
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\def\tb@rpad{1pt}
\def\tb@lpad{1pt}
\def\tb@tpad{1.8pt}
\def\tb@bpad{1.8pt}

\def\tb@overlay{\endcell\@IFNEXTCHAR[{\tb@overlaya}{\begincell}}
%\def\tb@overlay{\endcell\@IFNEXTCHAR[{\begincell}{\begincell}}
\def\tb@overlaya[#1]{\vbox to\dimen0\bgroup%
  \tb@overlayoptions#1\eoo%
  \tss\hbox to\dimen0\bgroup\lss$}
% pick out one option at a time until \eoo reached.
\def\tb@overlayoptions#1{\ifx#1\eoo\relax\else\tb@overlayoption#1\expandafter\tb@overlayoptions\fi}

% dispatch handler for each option
\def\tb@overlayoption#1{
  \if#1t\def\tss{\vskip\tb@tpad}\let\bss\vss\fi% t = align at top
  \if#1c\let\tss\vss\let\bss\vss\fi%             c = align at center
  \if#1b\def\bss{\vskip\tb@bpad}\let\tss\vss\fi% b = align at bottom
  \if#1l\def\lss{\hskip\tb@lpad}\let\rss\hss\fi% l = align at left
  \if#1m\let\lss\hss\let\rss\hss\fi%             m = align at middle
  \if#1r\def\rss{\hskip\tb@rpad}\let\lss\hss\fi% r = align at right
}

\def\tb@fl{\endcell\begincell\vrule depth 0pt width \dimen0 height \dimen0 \endcell\begincell}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%		repeat a cell
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% don't process the argument on more than one repetition
%%%%%\def\tb@rp[#1]{{\ifnum\tb@rpN=0\global\tb@rpN=#1\fi}}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%  \skewptn(a1,b1,c1,d1,...|a2,b2,c2,d2,...|...)
%  \skewptn[options](a1,b1,c1,d1,...|a2,b2,c2,d2,...|...)
% for diagrams w/o fillings only:
%	top row: draw a1 cells, leave b1 blank, draw c1 cells,...
%	2nd row: draw a2 cells, leave b2 blank, draw c2 cells,...
%	...
% options are same as for \tableau.  Scaling is determined by \Pscale
% instead of \Tscale, and the options s,m,l,p,a override it.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\def\tbgobble#1{}
\def\Pscale{1}

\def\skewptn{%
  \@IFNEXTCHAR[{\tb@ptnC}{\tb@ptnC[]}}     % add [] if no [options]

\def\tb@ptnC[#1](#2){%
	{%
    \let\Tscale\Pscale% default scaling
    \let\\=\cr% end line
%
   \def\tb@initYoung{%
	\def\tb@cell{\hskip\dimen0\tb@cellN}%
	\def\tb@kernA{\kern.5\dimen0}%
	\def\tb@kernB{\kern-.5\dimen0}%
   }%
   \def\tb@initFerrers{%
	\def\tb@cell{\hbox to\dimen0{\hss$\bullet$\hss}}%
	\def\tb@kernA{}%
	\def\tb@kernB{}%
   }%
%
%   \dimen0=cell size, \dimen1=frame size, \dimen2=strut size
    \dimen2=\ht\strutbox \advance\dimen2 by\dp\strutbox%
    \ifx\baselinestretch\undefined\relax%
    \else%
% want \dimen2 = \dimen2 / \baselinestretch, but can't do that if
% \baselinestretch has a decimal, so fake it to 2 decimal places.
       \dimen0=100sp \dimen0=\baselinestretch\dimen0%
       \dimen2=100\dimen2 \divide\dimen2 by\dimen0%
    \fi%
%
    \let\tpos\tb@vcenter% default position
    \tb@initYoung% default ptn type
    \tb@options#1\eoo% parse options (cell size, alignment, Ferrers/Young)
%
    \dimen0=\Tscale\dimen2%
    \dimen1=\dimen0 \advance\dimen1 by \tb@fframe%
    \lineskip=0pt\baselineskip=0pt% line spacing will be from \vbox to \dimen0
%
    \tpos{\skewptnDnewline#2|)}%
	}%
}%


\def\skewptnDnewline#1|{\vbox to\dimen0\bgroup\vss\tb@kernA\hbox\bgroup\skewptnEon#1,|}
\def\skewptnDendline|{\egroup\tb@kernB\vss\egroup\@IFNEXTCHAR{)}{\tbgobble}{\skewptnDnewline}}
\def\skewptnEon#1,{%
	\tb@rpN=#1%
	\ifnum#1>0
	        \loop%
%        	\hskip\dimen0\tb@cellN% draw cell frame
%		\hbox to\dimen0{\hss$\tb@cellE$\hss}\tb@cellD%
		\tb@cell%
%		
	        \ifnum\tb@rpN>1\advance\tb@rpN by-1%
        	\repeat%
	\fi%
	\@IFNEXTCHAR{|}{\skewptnDendline}{\skewptnEoff}}
\def\skewptnEoff#1,{\hskip #1\dimen0%
	\@IFNEXTCHAR{|}{\skewptnDendline}{\skewptnEon}}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\catcode`\@=\savecatcodeat
\let\savecatcodeat\undefined
