% Tableau macros -- tabmac.sty, by Glenn Tesler
% Do not further distribute until further notice; it's incomplete now.
%
% \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}
%
% \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 \\ \\
%
% options:
%       alignment:
%               c: center,  b: bottom,  t: top
%       diagram type:
%                          F: Ferrer's diagram            Y: Young diagram
%             dflt cell frame  none                             thin frame
%             null cells       \bullet                          thin frame
%             ~ (for skew)     \bullet                          no frame
%          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,c4,...,cn
% where these are the entries to go on the row.  Can use & instead of ,
% in * form, must use &
% If no entry is given, the cell is a frame (Young) or a bullet (Ferrers)
% special entries (only \ forms available with \tableau*)
%  \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
%  \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
% 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.
%
% 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.

\edef\savecatcodeat{\the\catcode`@}
\catcode`\@=11

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

% 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

\def\tb@tableauB{% add [] if no [options]
  \@ifnextchar[{\tb@tableauC}{\tb@tableauC[]}}

\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\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%
        \begincell\tb@cellarg\endcellno% the actual cell content
        \tbcellF}% draw cell frame
%
    \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#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

\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


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                             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}


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

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                            arrows, if diagram loaded
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\@ifundefined{diagram}{}{
% should \tb@arrowpad should be a multiple of .5?
\def\tb@arrowpad{.5}

% stripped down/altered from \dg@arrow
% Usage: \tb@arrow[USERSIZE]{ARROW_SPECS}LABELS...
\newoptcommand{\tb@arrow}{\@ne}[2]{%
  \endcell% end previous cell contents
   % Keep all arrow geometry parameters local.
   % The \endgroup is in \tb@draw
   \begingroup%
   \let\dg@getnodesize\tb@getnodesize% substitute routine to get nodesize
   % Get optional arrow USERSIZE.
   \dg@USERSIZE=#1\relax%
   \ifnum\dg@USERSIZE<\@ne \dg@USERSIZE=\@ne \fi%
   % Parse arrow specification.
   \dg@parse{#2}%
   \dg@label{\tb@draw{#1}{#2}}}% draw arrow

% substitute alternate routine for getting node sizes
% Usage: \tb@getnodesize{SLIST}{XCOORD}{YCOORD}{\WIDTH}{\HEIGHT}
\def\tb@getnodesize#1#2#3#4#5{\dimen3=\tb@arrowpad\dimen2 #4=\dimen3 #5=\dimen3\relax}
\def\tb@getnodesize#1#2#3#4#5{\ifnum#2=0\ifnum#3=0\tb@getnodesizetail{#4}{#5}\else\tb@getnodesizehead{#4}{#5}\fi\else\tb@getnodesizehead{#4}{#5}\fi}
\def\tb@getnodesizetail#1#2{\dimen3=.5\dimen2 #1=\dimen3 #2=\dimen3}
\def\tb@getnodesizehead#1#2{\dimen3=.5\dimen2 #1=\dimen3 #2=\dimen3}

% like \dg@drawcalc & \dg@draw; do the actual drawing
\def\tb@draw#1#2#3#4{%
  % grid geometry is determined by the tableau grid
        \dg@X=0\dg@Y=0\dg@XGRID=1\dg@YGRID=1\unitlength=.001\dimen0%
        \dg@LBLOFF=\dgLABELOFFSET \divide\dg@LBLOFF\unitlength%
%
        \dg@drawcalc% compute arrow geometry
        \begincell% start tableau cell
        \let\lams@arrow\tb@lams@arrow% substitute routine
  % draw arrow              VVVVV matches endgroup in \dg@draw
        \begin{picture}(0,0)\begingroup\dg@draw{#1}{#2}{#3}{#4}\end{picture}%
        \endcell% end tableau cell
        \endgroup% match \begingroup in \tb@arrow
        \begincell}% start new entry in this cell
}



% \lamssource{V} (= \arrow{...,V}), \lamstarget{V}, \lamstarget{^}
% cause placement of arrow to be ``adjusted'', but then the
% 45 deg. arrows don't go through grid points on the tableau.
%
% So this code from lamsarrow.sty has the adjustment section disabled.
%
% Perhaps \dgo@V should be modified to provide extra padding around cell
% contents to compensate for the removed adjustment.
%
%\def\lams@arrow#1#2{%
\def\tb@lams@arrow#1#2{%
 \lams@firstx\z@\lams@firsty\z@
 \lams@lastx#1\relax\lams@lasty#2\relax
 \lams@center\z@
 %
 % compute direction flags
 \N@false\E@false\H@false\V@false
 \ifdim\lams@lastx>\z@\E@true\fi
 \ifdim\lams@lastx=\z@\V@true\fi
 \ifdim\lams@lasty>\z@\N@true\fi
 \ifdim\lams@lasty=\z@\H@true\fi
 \NESW@false
 \ifN@\ifE@\NESW@true\fi\else\ifE@\else\NESW@true\fi\fi
 %
 % compute shaft char info with help of \lams@slope macro 
 \ifH@\else\ifV@\else
  \lams@slope
  \ifnum\lams@tani>\lams@tanii
   \lams@ht\ten@\p@\lams@wd\ten@\p@
   \multiply\lams@wd\lams@tanii\divide\lams@wd\lams@tani
  \else
   \lams@wd\ten@\p@\lams@ht\ten@\p@
   \divide\lams@ht\lams@tanii\multiply\lams@ht\lams@tani
  \fi
 \fi\fi
%%%%%%%%%%%%%%%%% BEGIN disable
% %
% % adjust arrow placement for source and target style
% \ifH@\else\ifV@\else
%  \ifnum\lams@target=\thr@@
%   \ifN@\advance\lams@lasty-.3\lams@ht
%   \else\advance\lams@lasty.3\lams@ht\fi
%  \fi
%  \ifnum\lams@source=\tw@
%   \ifE@\advance\lams@firstx.3\lams@ht
%   \else\advance\lams@firstx-.3\lams@ht\fi
%  \fi
%  \ifnum\lams@target=12
%   \ifN@\advance\lams@lasty-\lams@ht
%   \else\advance\lams@lasty\lams@ht\fi
%  \fi
% \fi\fi
%%%%%%%%%%%%%%%%% END disable
 %
 % draw arrow, special-casing horizontal and vertical ones
 \ifH@  \lams@harrow
 \else\ifV@ \lams@varrow
 \else \lams@darrow
 \fi\fi
}




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

