%D \module
%D   [       file=tabl-frm,
%D        version=2017.04.11,
%D          title=\CONTEXT\ Table Macros,
%D       subtitle=Framed Tables,
%D         author=Hans Hagen,
%D           date=\currentdate,
%D      copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
%C
%C This module is part of the \CONTEXT\ macro||package and is
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.

%D For Thomas Schmitz who needed 3000 pages long tables.

\unprotect

\writestatus{loading}{ConTeXt Table Macros / Framed Tables}

\installcorenamespace{framedtable}
\installcorenamespace{framedtablerow}
\installcorenamespace{framedtablecolumn}

\newinteger  \c_tabl_framed_c
\newinteger  \c_tabl_framed_r
\newdimension\d_tabl_framed_h   \def\d_tabl_framed_h_reference{\d_tabl_framed_h}%
\newdimension\d_tabl_framed_d
\newdimension\b_tabl_framed

\initializeboxstack\??framedtable

\defineframed[\??framedtable]
\defineframed[\??framedtablerow][\??framedtable]
\defineframed[\??framedtablecolumn][\??framedtable]

\setupframed
  [\??framedtable]
  [\c!distance=\zeropoint,
   \c!before=,
   \c!after=,
   \c!inbetween=]

\setupframed
  [\??framedtablerow]
  [\c!strut=\v!no,
   \c!offset=\v!overlay]

% \defineframedtable[foo]
% \defineframedtable[bar][foo]

\permanent\tolerant\protected\def\defineframedtable[#1]#*[#2]%
  {\ifarguments\or
     \defineframed[\??framedtable#1][\??framedtable]%
   \or
     \defineframed[\??framedtable#1][\??framedtable#2]%
   \fi}

% \setupframedtable[foo][...]

\permanent\tolerant\protected\def\setupframedtable[#S#1]#*[#S#2]%
  {\ifarguments\or
     \setupframed[\??framedtable][#1]%
   \or
     \ifcsname\??framed:\??framedtable#1\endcsname \else
       \defineframed[\??framedtable#1][\??framedtable]%
     \fi
     \setupframed[\??framedtable#1][#2]%
   \fi}

% \setupframedtable[1][...]
% \setupframedtable[foo][1][...]

\permanent\tolerant\protected\def\setupframedtablerow[#1]#*[#S#2]#*[#S#3]%
  {\ifarguments\or\or
     \ifcsname\??framed:\??framedtablerow:#1\endcsname \else
       \defineframed[\??framedtablerow:#1][\??framedtable]%
     \fi
     \setupframed[\??framedtablerow:#1][#2]%
   \or
     \ifcsname\??framed:\??framedtable#1\endcsname \else
       \defineframed[\??framedtable#1][\??framedtable]%
     \fi
     \ifcsname\??framed:\??framedtablerow#1:#2\endcsname \else
       \defineframed[\??framedtablerow#1:#2][\??framedtable#1]%
     \fi
     \setupframed[\??framedtablerow#1:#2][#3]%
   \fi}

\permanent\tolerant\protected\def\setupframedtablecolumn[#1]#*[#S#2]#*[#S#3]%
  {\ifarguments\or\or
     \ifcsname\??framed:\??framedtablecolumn:#1\endcsname \else
       \defineframed[\??framedtablecolumn:#1][\??framedtable]%
     \fi
     \setupframed[\??framedtablecolumn:#1][#2]%
   \or
     \ifcsname\??framed:\??framedtable#1\endcsname \else
       \defineframed[\??framedtable#1][\??framedtable]%
     \fi
     \ifcsname\??framed:\??framedtablecolumn#1:#2\endcsname \else
       \defineframed[\??framedtablecolumn#1:#2][\??framedtable#1]%
     \fi
     \setupframed[\??framedtablecolumn#1:#2][#3]%
   \fi}

\mutable\lettonothing\currentframedtable

\permanent\tolerant\protected\def\startframedtable[#S#1]#*[#S#2]%
  {\begingroup
   \forgetall
   \ifhastok={#1}%
     \lettonothing\currentframedtable
     \setupframed[\??framedtable][#1]%
   \else
     \cdef\currentframedtable{#1}%
     \setupframed[\??framedtable][#2]%
   \fi
   \cdef\currentframed{\??framedtable\currentframedtable}%
   \pack_framed_initialize
   \c_tabl_framed_r\zerocount
   \d_tabl_framed_d{\framedparameter\c!distance}%
   \framedparameter\c!before}

\permanent\protected\def\stopframedtable
  {\framedparameter\c!after
   \endgroup}

% a two pass variant that deals with the height .. so no catcode changes here

\tolerant\protected\def\pack_framed_start_framed_whatever[#S#1]%
  {\pack_framed_initialize % moved up
   \bgroup
   \setupcurrentframed[#1]% here !
   \pack_framed_process_indeed
   \bgroup
   \ignorespaces}

\newinteger\c_tabl_framed_pass

\permanent\let\stopframedrow\relax

\permanent\protected\def\startframedrow#1\stopframedrow
  {\advanceby\c_tabl_framed_r\plusone
   \startframedrow_one#1\stopframedrow_one
   \startframedrow_two#1\stopframedrow_two}

\tolerant\def\startframedrow_one[#-]%
  {\bgroup
   \c_tabl_framed_pass\plusone
   \c_tabl_framed_c\zerocount
   \d_tabl_framed_h\zeropoint
   \settrialtypesetting}

\protected\def\stopframedrow_one
  {\expanded{\egroup\d_tabl_framed_h\the\d_tabl_framed_h\relax}}

\def\startframedrow_two
  {\bgroup
   \c_tabl_framed_c\zerocount
   \c_tabl_framed_pass\plustwo
   \cdef\currentframed{\the\c_tabl_framed_r}%
   \cdef\currentframed
     {\??framedtablerow\currentframedtable
      \ifcsname\??framedtablerow\currentframedtable:\currentframed\endcsname
        :\currentframed
      \orelse\ifcsname\??framedtablerow\currentframedtable:\v!each\endcsname
        :\v!each
      \fi}%
   \pack_framed_start_framed_whatever}

\protected\def\stopframedrow_two
  {\localcontrolledloop\plusone\c_tabl_framed_c\plusone{\tabl_framed_flush_row_two}%
   \stopframed
   \nointerlineskip
   \vskip\zeroskip\relax
   \framedparameter\c!inbetween}

\protected\def\tabl_framed_flush_row_two
  {\vpack to \d_tabl_framed_h{\flushbox\??framedtable{\the\currentloopiterator}\vfill}%
   \ifzeropt\d_tabl_framed_d\else\kern\d_tabl_framed_d\fi}

\permanent\protected\def\startframedcell
  {\advanceby\c_tabl_framed_c\plusone
   \setbox\b_tabl_framed\hpack\bgroup
  %\bgroup
   \cdef\currentframed{\the\c_tabl_framed_c}%
   \cdef\currentframed
     {\??framedtablecolumn\currentframedtable
      \ifcsname\??framedtablecolumn\currentframedtable:\currentframed\endcsname
        :\currentframed
      \orelse\ifcsname\??framedtablecolumn\currentframedtable:\v!each\endcsname
        :\v!each
      \fi}%
   \ifcase\c_tabl_framed_pass
   \or
     \resetframedparameter\c!background
     \letframedparameter\c!frame\v!off
   \or
     \letframedparameter\c!height\d_tabl_framed_h_reference
   \fi
   \pack_framed_start_framed_whatever}

\permanent\protected\def\stopframedcell
  {\stopframed
  %\egroup
   \ifcase\c_tabl_framed_pass
   \or
     \ifdim\ht\b_tabl_framed>\d_tabl_framed_h
       \d_tabl_framed_h\ht\b_tabl_framed
     \fi
   \else
     \savebox\??framedtable{\the\c_tabl_framed_c}{\box\b_tabl_framed}%
   \fi}

\protect \endinput

\starttext

\setupframedtablecolumn [1] [width=3cm,background=color,backgroundcolor=red]
\setupframedtablecolumn [2] [width=4cm,background=color,backgroundcolor=green,align=normal]
% \setupframedtablerow [each] [background=color,backgroundcolor=blue,strut=no]
% \setupframedtablerow [each] [strut=no,offset=overlay]

\startframedtable[inbetween=\kern-0.4pt,distance=-0.4pt]

\testfeatureonce{10000}{
% \testfeatureonce{10}{
    \startframedrow
        \startframedcell%[backgroundcolor=yellow]
        test
        \stopframedcell
        \startframedcell
        test \par test
        \stopframedcell
    \stopframedrow
}
\stopframedtable

\stoptext