%D \module
%D   [       file=t-account,
%D        version=2007.01.15, % last change: 2009.02.06
%D          title=\CONTEXT\ User Module,
%D       subtitle=Miscelaneous,
%D         author=Wolfgang Schuster,
%D           date=\currentdate,
%D      copyright=Wolfgang Schuster,
%D          email=schuster.wolfgang@googlemail.com,
%D        license=Public Domain]

%M \usemodule [account]
%M \loadsetups[t-account.xml]

\writestatus{loading}{Context User Module / Miscelaneous}

\unprotect

\usemodule[floatnumber]

\def\????ac{@@@@ac} % Account

%D This is the second version of my T-Account module. If I want
%D to be true I wrote this module the n-th time but the current
%D version is my second version that has all things implemented
%D that I wanted and is written as a real \CONTEXT\ module and
%D in a simple plain \TEX\ style, although it is sometimes better
%D to try writing things for plain \TEX\ and creating an extended
%D for \CONTEXT\ later, after everything works.

%D The next two count registers save the values for the values
%D from the \tex{debit} and \tex{credit} macros. You can output
%D the values at the end of the account.

\definefloatnumber[creditvalue][\c!command=\accountparameter\c!numbercommand]
\definefloatnumber[debitvalue] [\c!command=\accountparameter\c!numbercommand]

\definefloatnumber[creditsum][\c!command=\accountparameter\c!numbercommand]
\definefloatnumber[debitsum] [\c!command=\accountparameter\c!numbercommand]

%D The following dimens are needed to save the textwidth in the
%D first run with my account parser and feed these values into
%D the account boxes, most of them only needed for the
%D \mono{width=fit} option.

\newdimen\!!debitwidth
\newdimen\!!debitheight
\newdimen\!!creditwidth
\newdimen\!!creditheight
\newdimen\!!accountwidth
\newdimen\!!accountheight
\newdimen\!!debittextwidth
\newdimen\!!debitnumberwidth
\newdimen\!!credittextwidth
\newdimen\!!creditnumberwidth

%D I collect the content from the debit environment in an box and
%D put the content into the main box, after all values are collected.
%D The same happens for the credit environment and his content.

\newbox\debitbox
\newbox\creditbox

%D And the last thing is a private token register to save the account
%D content and use it for both parsing the content and using it afterwards
%D to fill the box with the processed content.

\newtoks\accounttoks

%D This nice thing was taken from \mono{core-rul.tex}.

\def\accountparameter#1%
  {\csname\@@account#1\endcsname}

%D \macros{startACCOUNT,stopACCOUNT}
%D
%D \showsetup{startaccount}

%D My first version used a buffers to store the content between the
%D \tex{startACCOUNT} \unknown\ \tex{stopACCOUNT} pair. This has
%D worked untill I tried to put the environment into a float or to
%D put a few of them side by side in an \mono{combination} environment.
%D A solution for this problems could have been to call the output
%D from my \mono{ACCOUNT} environment by a command like \tex{useACCOUNT}
%D like the \mono{MPgraphics}, but is was not what I wanted and the
%D only solution for this was to use an delimited environment on the
%D one side or collext the text into braces like \tex{ACCOUNT{}} on
%D the other side. The second way would have made it easier to define
%D new macros to for the account with presets with the sideeffect to
%D enclose the content with braces. The first way avoids braces and
%D uses delimitercommands instead, more to write and harder to define
%D wrapper macros (in the way I like) but I prefered this solution
%D as shown below.

\def\startACCOUNT
  {\dodoubleempty\dostartACCOUNT}

\long\def\dostartACCOUNT[#1][#2]#3\stopACCOUNT
  {\bgroup
   \edef\@@account{\????ac#1}%
   \ifsecondargument
     \setupACCOUNT[#1][#2]%
   \fi
   \edef\accountwidth    {\accountparameter\c!width}%
   \edef\accountdistance {\accountparameter\c!distance}%
   \resetfloatnumber[creditsum]%
   \resetfloatnumber[debitsum]%
   \def\creditsum{\getfloatnumber[creditsum]}%
   \def\debitsum {\getfloatnumber[debitsum]}%
   \doifvaluesomething{\accountparameter\c!bodyfont}
     {\expanded{\switchtobodyfont
        [\accountparameter\c!bodyfont]}}%
   \parseACCOUNT{#3}%
   \doifnot\accountwidth\v!fit
     {\global\!!accountwidth\the\dimexpr\accountwidth\relax
      \global\advance\!!accountwidth-\accountdistance
      \global\!!accountwidth0.5\!!accountwidth}%
   #3\removeunwantedspaces
   \checkACCOUNT
   \presetlocalframed[\????ac]%
   \localframed
     [\????ac]
     [\c!background=\accountparameter\c!background,
      \c!backgroundcolor=\accountparameter\c!backgroundcolor,
      \c!backgroundoffset=\accountparameter\c!backgroundoffset,
      \c!backgroundscreen=\accountparameter\c!backgroundscreen,
      \c!frame=\accountparameter\c!frame,
      \c!framecolor=\accountparameter\c!framecolor,
      \c!offset=\accountparameter\c!offset]
   \bgroup
   \setbox\scratchbox\vbox
     {\offinterlineskip
      \doifelsenothing
        {\accountparameter\c!left%
         \accountparameter\c!middle%
         \accountparameter\c!right}
        {\xdef\MPaccountheaderheight{\the\zeropoint}}
        {\setbox\scratchbox\hbox\!!to\dimexpr2\!!accountwidth+\accountdistance\relax
           {\doif{\accountparameter\c!strut}\v!yes\strut
            \rlap{\accountparameter\c!left}\hfil
                  \accountparameter\c!middle\hfil
            \llap{\accountparameter\c!right}}%
            \xdef\MPaccountheaderheight{\the\dimexpr\ht\scratchbox+\dp\scratchbox\relax}%
            \box\scratchbox}
      \doifelse{\accountparameter\c!rule}\v!on
        {\doifsomething{\accountparameter\c!framecolor}
           {\color[\accountparameter\c!framecolor]}
           {\hrule\!!height\accountparameter\c!rulethickness\relax}}
        {\vskip\accountparameter\c!rulethickness\relax}%
      \hbox{\box\debitbox\betweenaccount\box\creditbox}%
      \doifelse{\accountparameter\c!calculate}\v!yes
        {\setbox\scratchbox\vbox
           {\doifelse{\accountparameter\c!rule}\v!on
              {\doifsomething{\accountparameter\c!framecolor}
                 {\color[\accountparameter\c!framecolor]}
                 {\hrule\!!height\accountparameter\c!rulethickness\relax}}
              {\vskip\accountparameter\c!rulethickness\relax}
            \hbox
              {\hbox\!!to\!!accountwidth
                 {\doif{\accountparameter\c!strut}\v!yes\strut%
                  \hfil\debitsum}%
               \spacebetweenaccount
               \hbox\!!to\!!accountwidth
                 {\doif{\accountparameter\c!strut}\v!yes\strut%
                  \hfil\creditsum}}}%
         \xdef\MPaccountfooterheight{\the\dimexpr\ht\scratchbox+\dp\scratchbox\relax}%
         \box\scratchbox}
        {\xdef\MPaccountfooterheight{\the\zeropoint}}}%
   \xdef\MPaccountmaxheight{\the\dimexpr\ht\scratchbox+\dp\scratchbox\relax}%
   \xdef\MPaccountmaxwidth {\the\wd\scratchbox}%
   \box\scratchbox
   \egroup
   \egroup}

\defineoverlay[account][\useMPgraphic{account}]

%D We are not limited to simple rules with \TEX\ primitives.
%D The following \METAPOST\ example graphic shows one way to
%D draw more complicated rules behind the T-Account, you can
%D use thus as an example for your own backgrounds.

\startuseMPgraphic{account}
  AccountNumberGap := 0.5*\MPaccountmaxwidth-\MPaccountwidth ;
  AccountRuleWidth := \the\dimexpr\accountparameter\c!rulethickness\relax ;

  z11 = (0,\MPaccountmaxheight-\MPaccountheaderheight) ;
  z12 = (\MPaccountmaxwidth,\MPaccountmaxheight-\MPaccountheaderheight) ;

  z21 = (\MPaccountwidth-\MPaccountnumberwidth-AccountNumberGap,\MPaccountmaxheight-\MPaccountheaderheight-\MPaccountdebitheight) ;
  z22 = (0.5*\MPaccountmaxwidth,\MPaccountmaxheight-\MPaccountheaderheight-\MPaccountdebitheight) ;
  z23 = (\MPaccountmaxwidth-\MPaccountnumberwidth-AccountNumberGap,\MPaccountmaxheight-\MPaccountheaderheight-\MPaccountcreditheight) ;
  z24 = (\MPaccountmaxwidth,\MPaccountmaxheight-\MPaccountheaderheight-\MPaccountcreditheight) ;

  z31 = (\MPaccountwidth-\MPaccountnumberwidth-AccountNumberGap,\MPaccountfooterheight) ;
  z32 = (0.5*\MPaccountmaxwidth-AccountNumberGap,\MPaccountfooterheight) ;
  z33 = (\MPaccountmaxwidth-\MPaccountnumberwidth-AccountNumberGap,\MPaccountfooterheight) ;
  z34 = (\MPaccountmaxwidth,\MPaccountfooterheight) ;
  
  z41 = (0.5*\MPaccountmaxwidth,\MPaccountmaxheight-\MPaccountheaderheight) ;
  z42 = (0.5*\MPaccountmaxwidth,0) ;
  z43 = whatever[z41,z42]=whatever[z22,z23] ;
  z44 = (0.5*\MPaccountmaxwidth,\MPaccountfooterheight) ;

  z51 = (0,\MPaccountfooterheight) ;
  z52 = (\MPaccountnumberwidth,\MPaccountfooterheight) ;
  z53 = (0.5*\MPaccountmaxwidth-\MPaccountnumberwidth-AccountNumberGap,\MPaccountmaxheight-\MPaccountheaderheight-\MPaccountdebitheight) ;
  z54 = (0.5*\MPaccountmaxwidth-AccountNumberGap,\MPaccountmaxheight-\MPaccountheaderheight-\MPaccountdebitheight) ;
  
  z61 = (\MPaccountwidth-\MPaccountnumberwidth-AccountNumberGap,0) ;
  z62 = (0.5*\MPaccountmaxwidth-AccountNumberGap,0) ;
  z63 = (\MPaccountmaxwidth-\MPaccountnumberwidth-AccountNumberGap,0) ;
  z64 = (\MPaccountmaxwidth,0) ;

  drawoptions (withpen pencircle scaled AccountRuleWidth withcolor \MPcolor{\accountparameter\c!framecolor}) ;
  linecap := butt ; % no round end of the lines

  draw z11--z12 ;
  draw z33--z34 ;

  if \MPaccountfooterheight>0pt:
    draw z61--z62 ;
    draw z63--z64 ;
  fi

  if \MPaccountcreditheight>\MPaccountdebitheight:
    draw z31--z32 ;
    draw z41--z44 ;
    draw z51--z52--z53--z54 ;
  else:
    draw z21--z22--z23--z24 ;
    draw z41--z43 ;
  fi

  setbounds currentpicture to unitsquare xyscaled (\MPaccountmaxwidth,\MPaccountmaxheight) ;
\stopuseMPgraphic

%D \showsetup{startdebits}
%D \showsetup{debit}

\long\def\startDEBITS#1\stopDEBITS
  {\bgroup
   \def\debit{\dosingleempty\dodebit}%
   \def\dodebit[##1]%
     {\def\dododebit####1{\dodododebit[##1]{####1}}%
      \permitspacesbetweengroups
      \dosinglegroupempty\dododebit}%
   \def\dodododebit[##1]##2%
     {\setfloatnumber[debitvalue]{##2}%
      \incrementfloatnumber[debitsum]{\rawfloatnumber[debitvalue]}%
      \hbox\!!to\hsize{\strut##1\hfill\getfloatnumber[debitvalue]}}%
   \global\setbox\debitbox\vtop{\hsize\!!accountwidth#1}%
   \!!debitheight\ht\debitbox
   \advance\!!debitheight\dp\debitbox
   \xdef\MPaccountdebitheight{\the\!!debitheight}%
   \egroup}

%D \showsetup{startcredits}
%D \showsetup{credit}

\long\def\startCREDITS#1\stopCREDITS
  {\bgroup
   \def\credit{\dosingleempty\docredit}%
   \def\docredit[##1]%
     {\def\dodocredit####1{\dododocredit[##1]{####1}}%
      \permitspacesbetweengroups
      \dosinglegroupempty\dodocredit}%
   \def\dododocredit[##1]##2%
     {\setfloatnumber[creditvalue]{##2}%
      \incrementfloatnumber[creditsum]{\rawfloatnumber[creditvalue]}%
      \hbox\!!to\hsize{\strut##1\hfill\getfloatnumber[creditvalue]}}%
   \global\setbox\creditbox\vtop{\hsize\!!accountwidth#1}%
   \!!creditheight\ht\creditbox
   \advance\!!creditheight\dp\creditbox
   \xdef\MPaccountcreditheight{\the\!!creditheight}%
   \egroup}

\long\def\parseACCOUNT#1%
  {\bgroup
   \resetfloatnumber[creditsum]%
   \resetfloatnumber[debitsum]%
   \def\startCREDITS##1\stopCREDITS
     {\def\credit{\dosingleempty\docredit}%
      \def\docredit[####1]%
        {\def\dodocredit########1{\dododocredit[####1]{########1}}%
         \permitspacesbetweengroups
         \dosinglegroupempty\dodocredit}%
      \def\dododocredit[####1]####2%
        {\incrementfloatnumber[creditsum]{####2}%
         \setbox\scratchbox\hbox{####1}\!!dimena\wd\scratchbox
         \compareaccountdimen\!!credittextwidth\!!dimena}%
      ##1\removeunwantedspaces}%
   \def\startDEBITS##1\stopDEBITS
     {\def\debit{\dosingleempty\dodebit}%
      \def\dodebit[####1]%
        {\def\dododebit########1{\dodododebit[####1]{########1}}%
         \permitspacesbetweengroups
         \dosinglegroupempty\dododebit}%
      \def\dodododebit[####1]####2%
        {\incrementfloatnumber[debitsum]{####2}%
         \setbox\scratchbox\hbox{####1}\!!dimena\wd\scratchbox
         \compareaccountdimen\!!debittextwidth\!!dimena}%
      ##1\removeunwantedspaces}%
   #1\removeunwantedspaces
   \compareACCOUNTnumberwidth
   \compareaccountdimen\!!debittextwidth\!!credittextwidth
   \global\!!accountwidth\!!debittextwidth
   \global\advance\!!accountwidth\dimexpr\MPaccountnumberwidth\relax
   \global\advance\!!accountwidth\accountparameter\c!columndistance
   \xdef\MPaccounttextwidth{\the\!!debittextwidth}%
   \xdef\MPaccountwidth    {\the\!!accountwidth}%
   \resetfloatnumber[creditsum]%
   \resetfloatnumber[debitsum]%
   \egroup}

\def\compareACCOUNTnumberwidth
  {\bgroup
   \setbox\plusone\hbox{\getfloatnumber[debitsum]}%
   \setbox\plustwo\hbox{\getfloatnumber[creditsum]}%
   \ifdim\wd\plusone>\wd\plustwo
     \xdef\MPaccountnumberwidth{\the\wd\plusone}%
   \else
     \xdef\MPaccountnumberwidth{\the\wd\plustwo}%
   \fi
   \egroup}

\def\compareaccountdimen#1#2%
  {\ifdim#2>#1\relax
     #1#2
   \fi}

\def\checkACCOUNT
  {\bgroup
   \compareaccountdimen\!!debitheight\!!creditheight
   \xdef\MPaccountheight{\the\!!debitheight}%
   \egroup}

\def\linebetweenaccount
  {\bgroup
   \xdef\MPaccountdistance{\the\dimexpr\accountdistance\relax}%
   \ifdim\accountdistance>\zeropoint\relax
     \!!dimena\accountdistance
   \else
     \!!dimena\linewidth
   \fi
   \advance\!!dimena-\linewidth
   \hskip.5\!!dimena
   \doifsomething{\accountparameter\c!framecolor}
     {\color[\accountparameter\c!framecolor]}%
     {\vrule\!!width\accountparameter\c!rulethickness}%
   \hskip.5\!!dimena\relax
   \egroup}

\def\spacebetweenaccount
  {\xdef\MPaccountdistance{\zeropoint}%
   \hskip\accountdistance}

%D \macros{setupACCOUNT}
%D
%D \showsetup{setupaccount}

\def\setupACCOUNT
  {\dodoubleargument\dosetupACCOUNT}

\def\dosetupACCOUNT[#1][#2]%
  {\getparameters[\????ac#1][#2]%
   \processaction
     [\getvalue{\????ac#1\c!rule}]
     [     \v!on=>\let\betweenaccount\linebetweenaccount,
          \v!off=>\let\betweenaccount\spacebetweenaccount,
      \s!default=>\let\betweenaccount\spacebetweenaccount,
      \s!unknown=>\let\betweenaccount\spacebetweenaccount]}

\def\defineACCOUNT
  {\dodoubleempty\dodefineACCOUNT}

\def\dodefineACCOUNT[#1][#2]%
  {\setupACCOUNT
     [#1]
     [\c!background=,
      \c!backgroundoffset=0pt,
      \c!backgroundscreen=,
      \c!backgroundcolor=,
      \c!bodyfont=,
      \c!calculate=\v!no,
      \c!columndistance=\bodyfontsize,
      \c!distance=\bodyfontsize,
      \c!frame=\v!off,
      \c!framecolor=,
      \c!left=,
      \c!middle=,
      \c!offset=0.25ex,
      \c!right=,
      \c!rule=\v!on,
      \c!rulethickness=\linewidth,
      \c!width=\v!fit,
      \c!strut=\v!yes,
      \c!numbercommand=\integerrounding,
      #2]%
   \processbetween{#1}{\ACCOUNT[#1]}%
   \setvalue{\e!setup#1\e!endsetup}{\dodoubleargument\setupACCOUNT[#1]}}

\def\ACCOUNT[#1]#2%
  {\startACCOUNT[#1]#2\stopACCOUNT}

\defineACCOUNT[TACCOUNT]

\defineACCOUNT[TKONTO]

%D \subject{Example}
%D 
%D \startbuffer
%D \startTACCOUNT[left=S,middle=Retained Earnings,right=H]
%D \startTACCOUNT
%D   \startDEBITS
%D     \debit [Rent Expense]      {2200}
%D     \debit [Salaries Expense]  {1650}
%D     \debit [Interest Expense]  {3950}
%D     \debit [Dividends]         {2000}
%D   \stopDEBITS
%D   \startCREDITS
%D     \credit [Sales Revenue]    {8500}
%D     \credit [Interest Revenue] {1300}
%D   \stopCREDITS
%D \stopTACCOUNT
%D \stopbuffer
%D 
%D A simple example:
%D 
%D \typebuffer
%D 
%D This results in the following output:
%D 
%D \startlinecorrection
%D \getbuffer
%D \stoplinecorrection

\loadmarkfile{t-account}

\protect \endinput
