%D \module
%D   [       file=m-chart,
%D        version=1998.10.10,
%D          title=\CONTEXT\ Modules,
%D       subtitle=Flow Charts,
%D         author={Hans Hagen \& Ton Otten},
%D           date=\currentdate,
%D      copyright={PRAGMA / Hans Hagen \& Ton Otten}]
%C
%C This module is part of the \CONTEXT\ macro||package and is
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.

% to do: \localpushmacro/\localpopmacro (dohandleflowchart etc)

% will be redone with layers

%D This is an experimental module. Pieces of code will be moved
%D to other modules. More features are possible but will be
%D interfaces later.
%D
%D When finished this module will be documented. The main macro
%D is still a rather big one and there is some redundant and
%D slow code that needs a clean up.

% arrow, dash
% crossing
% \goto -> \normalgoto
% class -> class:name (ref prefix)
% c, automatisch geen overlap zoeken
% eind eerder chart connecties
% relateren aan korps
% check op bestaan naam, bestaan shape
% auto als extern figuur
% subchart
% pijlen
% focus
% ook nog \MPmessage
% areapath -> krappe vlak
% clippath -> gehele vlak
%
% offset  : clip offset
% breedte : breedte cel
% hoogte  : hoogte cel
% dx      : halve afstand in breedte (grid breedte = breedte + 2dx)
% dy      : halve afstand in hoogte (grid hoogte = hoogte + 2dy)
% x       : x offset (clipping)
% y       : y offset (clipping)
% nx      : minimaal aantal cellen horizontaal
% ny      : minimaal aantal cellen vertikaal
%
% shape none en geen equivalent maken
%
% kaderkleur achtergrondkleur
% lijnkleur lijndikte
% focus focuskaderkleur focusachtergrondkleur
% richting
%
% focus koppelen aan kleur

\unprotect

\definesorting [flowchart] [flowcharts] [\v!none] % no access
\setupsorting  [flowchart] [\c!state=\v!stop]     % off by default

\def\@FLOW@{@FLOW@}
\def\@FLOC@{@FLOC@}
\def\@FLOX@{@FLOX@}

\def\@@FLOW{@@FLOW}
\def\@@FLOL{@@FLOL}
\def\@@FLOS{@@FLOS}
\def\@@FLOF{@@FLOF}
\def\@@FLOT{@@FLOT}
\def\@@FLOX{@@FLOX}

\def\@@MPx {@@MPx}
\def\@@MPy {@@MPy}

\def\FLOWbufferprefix{flw-}

\def\processFLOWbuffer#1{\getbuffer[\FLOWbufferprefix#1]}
\def\typeFLOWbuffer   #1{\typebuffer[\FLOWbufferprefix#1]}

\def\setFLOWname#1#2% funny hack that makes sure that we get
  {\bgroup          % names that are acceptable for METAPOST
   \lccode`0=`a\lccode`1=`b\lccode`2=`c\lccode`3=`d\lccode`4=`e%
   \lccode`5=`f\lccode`6=`g\lccode`7=`h\lccode`8=`i\lccode`9=`j%
   \lccode` =`\_\lccode`-=`\_\lccode`_=`\_%
   \lowercase{\gdef#1{#2}}%
   \egroup}

% een gobble als default is sneller, en dan alleen setten als
% nodig

\def\resetFLOWcell
  {% variables
   \global\let\FLOWname       \empty
   \global\let\FLOWalign      \empty
   \global\let\FLOWshape      \empty
   \global\let\FLOWlocation   \empty
   \global\let\FLOWtext       \empty
   \global\let\FLOWhelp       \empty
   \global\let\FLOWdestination\empty
   \global\let\FLOWoverlay    \empty
   \global\let\FLOWfocus      \empty
   \global\let\tFLOWlabel     \empty
   \global\let\bFLOWlabel     \empty
   \global\let\lFLOWlabel     \empty
   \global\let\rFLOWlabel     \empty
   \global\let\bcFLOWlabel    \empty
   \global\let\tcFLOWlabel    \empty
   \global\let\lcFLOWlabel    \empty
   \global\let\rcFLOWlabel    \empty
   \global\let\tFLOWexit      \empty
   \global\let\bFLOWexit      \empty
   \global\let\lFLOWexit      \empty
   \global\let\rFLOWexit      \empty
   % commands
   \let\name       \doFLOWname
   \let\shape      \doFLOWshape
   \let\destination\doFLOWdestination
   \let\location   \doFLOWlocation
   \let\focus      \doFLOWfocus
   \let\overlay    \doFLOWoverlay
   \let\figure     \doFLOWfigure
   \let\text       \doFLOWtext
   \let\comment    \doFLOWcomment
   \let\label      \doFLOWlabel
   \let\help       \doFLOWhelp
   \let\connection \doFLOWconnection
   \let\exit       \doFLOWexit
   % convenience commands
   \let\locate     \doFLOWlocate
   \let\connect    \doFLOWconnect}

\let\FLOWcell       \s!unknown
\let\FLOWshape      \s!unknown
\let\FLOWdestination\s!unknown
\let\FLOWfocus      \s!unknown
\let\FLOWoverlay    \empty
\let\FLOWtext       \empty

\def\doFLOWname#1%
  {\def\FLOWcell{#1}\setFLOWname\FLOWname{name_#1}\ignorespaces}

\def\doFLOWshape#1%
  {\gdef\FLOWshape{#1}\ignorespaces}

\def\doFLOWdestination#1%
  {\gdef\FLOWdestination{#1}\ignorespaces}

\def\doFLOWlocation#1%
  {\setFLOWlocation#1\end\ignorespaces}

\def\doFLOWfocus#1%
  {\gdef\FLOWfocus{#1}\ignorespaces}

\def\doFLOWoverlay#1%
  {\gdef\FLOWoverlay{#1}\ignorespaces}

\def\doFLOWfigure#1%
  {\defineoverlay
     [\s!dummy]
     [{\externalfigure
         [#1]
         [\c!width=\overlaywidth,
          \c!height=\overlayheight]}]%
   \overlay{\s!dummy}}

\def\doFLOWtext
  {\dosingleempty\dodoFLOWtext}

\def\dodoFLOWtext[#1]%               %  #2%
  {\gdef\FLOWalign{#1}\gdef\FLOWtext}% {#2}}

\def\doFLOWcomment[#1]#2%
  {\ignorespaces\dogobblesingleempty}

\def\doFLOWlabel[#1]#2% wordt dit gebruikt ?
  {\setgvalue{#1FLOWlabel}{#2}\ignorespaces}

\def\doFLOWhelp#1%
  {\gdef\FLOWhelp{#1}\ignorespaces}

\def\doFLOWconnection
  {\dodoubleempty\dodoFLOWconnection}

\def\dodoFLOWconnection[#1][#2]#3%
  {\ignorespaces}

\def\doFLOWconnect%
  {\connection}

\def\doFLOWlocate%
  {\location}

\def\doFLOWexit[#1]#2%
  {\setgvalue{#1FLOWexit}{#2}\ignorespaces}

\def\startFLOWchart
  {\bgroup
   \let\stopFLOWchart\egroup
   \obeylines % lelijk, buffers nog eens fatsoeneren
   \dodoubleempty\dostartFLOWchart}

\def\dostartFLOWchart[#1][#2]%
  {\preparenextFLOWchart{#1}{#2}%
   \dostartbuffer[\FLOWbufferprefix\nofFLOWcharts][startFLOWchart][stopFLOWchart]}

\def\defineFLOWchart%
  {\dodoubleempty\dodefineFLOWchart}

\long\def\dodefineFLOWchart[#1][#2]#3%
  {\preparenextFLOWchart{#1}{#2}%
   \setbuffer[\FLOWbufferprefix\nofFLOWcharts]#3\endbuffer}

\def\preparenextFLOWchart#1#2%
  {\doglobal\increment\nofFLOWcharts
   \flowchart{#1}%
   \setxvalue{\@FLOW@-#1}%
     {\noexpand\dohandleflowchart[\nofFLOWcharts][#2]}}

\def\setupFLOWcharts{\dodoubleargument\getparameters[\@@FLOW]}
\def\setupFLOWlines {\dodoubleargument\getparameters[\@@FLOL]}
\def\setupFLOWshapes{\dodoubleargument\getparameters[\@@FLOS]}
\def\setupFLOWfocus {\dodoubleargument\getparameters[\@@FLOF]}
\def\setupFLOWsets  {\dodoubleargument\getparameters[\@@FLOX]}

\setupFLOWcharts
  [\c!option=,
   \c!bodyfont=,
   \c!dot=,  % private option
   \c!width=12\bodyfontsize,
   \c!height=7\bodyfontsize,
   \c!maxwidth=,
   \c!maxheight=,
   \c!offset=\v!standard, % == auto offset
   \c!dx=2\bodyfontsize,
   \c!dy=2\bodyfontsize,
   \c!nx=0, % 1,
   \c!ny=0, % 1,
   \c!x=1,
   \c!y=1,
   \c!autofocus=,
   \c!focus=,
   \c!background=,      % \v!color,
   \c!backgroundcolor=\s!white,
   \c!rulethickness=\linewidth,
   \c!frame=\v!off,
   \c!framecolor=]

\setupFLOWlines
  [\c!corner=\v!round,
   \c!arrow=\v!yes,
   \c!dash=\v!no,
   \c!radius=.375\bodyfontsize,      % 2.5\c!rulethickness
   \c!color=FLOWlinecolor,
   \c!rulethickness=.15\bodyfontsize,  % 2pt,
   \c!offset=\v!none]

\setupFLOWshapes
  [\c!default=action,
   \c!framecolor=FLOWframecolor,
   \c!background=\v!color,
   \c!backgroundcolor=FLOWbackgroundcolor,
   \c!backgroundscreen=\@@rsscreen,
   \c!rulethickness=.15\bodyfontsize,  % 2pt,
   \c!offset=.5\bodyfontsize]

\setupFLOWfocus
  [\c!framecolor=FLOWfocuscolor,
   \c!background=\@@FLOSbackground,
   \c!backgroundcolor=\@@FLOSbackgroundcolor,
   \c!backgroundscreen=\@@FLOSbackgroundscreen,
   \c!rulethickness=\@@FLOSrulethickness,
   \c!offset=\@@FLOSoffset]

\definecolor [FLOWfocuscolor]      [s=.2]
\definecolor [FLOWlinecolor]       [s=.5]
\definecolor [FLOWframecolor]      [s=.7]
\definecolor [FLOWbackgroundcolor] [s=.9]

\newcounter\includeFLOWx
\newcounter\includeFLOWy

\def\includeFLOWchart%
  {\dodoubleempty\doincludeFLOWchart}

\def\doincludeFLOWchart[#1][#2]%
  {\pushmacro\includeFLOWx
   \pushmacro\includeFLOWy
   \getparameters[FLOWi][x=1,y=1,#2]%
   \increment(\includeFLOWx,0\FLOWix)\decrement\includeFLOWx
   \increment(\includeFLOWy,0\FLOWiy)\decrement\includeFLOWy
   \def\dodoincludeFLOWchart##1%
     {\doifdefined{\@FLOW@-##1}
        {\globalpushmacro\dohandleflowchart % was local
         \gdef\dohandleflowchart[####1][####2]%
           {\globalpopmacro\dohandleflowchart % was local
            \resetFLOWlocation
            \processFLOWbuffer{####1}}%
         \getvalue{\@FLOW@-##1}}}%
   \processcommalist[#1]\dodoincludeFLOWchart
   \popmacro\includeFLOWx
   \popmacro\includeFLOWy}

%\def\setFLOWlocation#1,#2\end%
% {\scratchcounter=0#1\advance\scratchcounter\includeFLOWx
%  \xdef\FLOWlocation{\the\scratchcounter}%
%  \scratchcounter=0#2\advance\scratchcounter\includeFLOWy
%  \xdef\FLOWlocation{\FLOWlocation,\the\scratchcounter}}

\def\resetFLOWlocation%
  {\gdef\lastFLOWx{0}%
   \gdef\lastFLOWy{0}}

\def\dosetFLOWlocation[#1#2]#3#4%
  {\processaction
     [#1#2]
     [         +=>\scratchcounter=#4\advance\scratchcounter+1,
               -=>\scratchcounter=#4\advance\scratchcounter-1,
             +#2=>\scratchcounter=#4\advance\scratchcounter+#2,
             -#2=>\scratchcounter=#4\advance\scratchcounter-#2,
      \s!default=>\scratchcounter=#4,
      \s!unknown=>\scratchcounter=0#1#2]%
   \advance\scratchcounter#3%
   \xdef#4{\the\scratchcounter}}

\def\setFLOWlocation#1,#2\end
  {\dosetFLOWlocation[#1\empty]\includeFLOWx\lastFLOWx
   \dosetFLOWlocation[#2\empty]\includeFLOWy\lastFLOWy
   \xdef\FLOWlocation{\lastFLOWx,\lastFLOWy}}

\def\FLOWshapes
  {node, action, procedure, product, decision, archive,
   loop, wait, subprocedure, singledocument, multidocument,
   sub procedure, single document, multi document, up, down,
   left, right}

\def\FLOWlines
  {up, down, left, right}

\def\FLOWsetconnect#1%
  {\donefalse
   \let\cFLOWfrom\empty
   \let\cFLOWto\empty
   \def\zFLOWfrom{0}%
   \def\zFLOWto{0}%
   \handletokens#1\with\doFLOWsetconnect
   \ifx\cFLOWto\empty\let\cFLOWfrom\empty\fi}

\def\doFLOWsetconnect#1%
  {\ifx     #1p%
     \ifdone\def\zFLOWto{+1}\else\def\zFLOWfrom{+1}\fi
   \else\ifx#1+%
     \ifdone\def\zFLOWto{+1}\else\def\zFLOWfrom{+1}\fi
   \else\ifx#1n%
     \ifdone\def\zFLOWto{-1}\else\def\zFLOWfrom{-1}\fi
   \else\ifx#1-%
     \ifdone\def\zFLOWto{-1}\else\def\zFLOWfrom{-1}\fi
   \else\ifdone
     \edef\cFLOWto{\FLOWconnector#1}%
   \else
     \edef\cFLOWfrom{\FLOWconnector#1}%
     \donetrue
   \fi\fi\fi\fi\fi}

\def\FLOWconnector#1%
  {\if#1bbottom\else\if#1ttop\else\if#1lleft\else\if#1rright\fi\fi\fi\fi}

\newif\ifFLOWscaling \FLOWscalingtrue

\def\@@FLOW@@offset{\@@FLOWoffset}

\def\getFLOWchart
  {\dodoubleempty\dogetFLOWchart}

\def\dogetFLOWchart[#1][#2]%
  {\doifundefinedelse{\@FLOW@-#1}
     {\writestatus{FLOW}{unknown chart #1}%
      \framed
        [\c!width=12\bodyfontsize,\c!height=8\bodyfontsize]
        {\tttf [chart #1]}}
     {\dodogetFLOWchart[#1][#2]}}

\def\dodogetFLOWchart[#1][#2]% to be split a bit more
  {\vbox\bgroup
   \insidefloattrue
   \forgetall
   \dontcomplain
   % \offinterlineskip % we now explicitly use \nointerlineskip later on
   \def\dohandleflowchart[##1][##2]%
     {\def\currentFLOWnumber{##1}%
      \getparameters[\@@FLOW][##2]}%
   \getvalue{\@FLOW@-#1}%
   \getparameters[\@@FLOW][#2]% dubbelop ?
   \doifsomething{\@@FLOWautofocus}
     {\checkFLOWautofocus}%
  %\message{AUTOSHAPE 3: (\@@FLOWx,\@@FLOWy)->(\@@FLOWnx,\@@FLOWny)}\wait
   \global\let\FLOWwidth \@@FLOWnx
   \global\let\FLOWheight\@@FLOWny
   \let\startFLOWcell\startFLOWcellA
   \resetFLOWlocation
   \processFLOWbuffer\currentFLOWnumber
   \ifcase\@@FLOWnx\relax \let\@@FLOWnx\FLOWwidth  \fi
   \ifcase\@@FLOWny\relax \let\@@FLOWny\FLOWheight \fi
   \doifnothing{\@@FLOWmaxwidth\@@FLOWmaxheight}{\FLOWscalingfalse}%
   \ifFLOWscaling
     \doifnothing{\@@FLOWmaxwidth }{\let\@@FLOWmaxwidth \maxdimen}%
     \doifnothing{\@@FLOWmaxheight}{\let\@@FLOWmaxheight\maxdimen}%
     \scratchcounter=\bodyfontpoints
     \doloop  % NOG FONTSWITCH OM EX EN EM TE LATEN WERKEN
       {\ifnum\scratchcounter>1 % NU DIMENSIONS IN TERMS OF BODYFONTSIZE
          \bodyfontsize=\the\scratchcounter pt
          \dimen0=\@@FLOWmaxwidth
          \dimen2=\@@FLOWwidth
          \dimen4=\@@FLOWdx
          \advance\dimen2 2\dimen4
          \dimen2=\@@FLOWnx\dimen2
          \advance\dimen2 2\dimen4
          \ifdim\dimen2>\dimen0
            \advance\scratchcounter \minusone
          \else
            \dimen0=\@@FLOWmaxheight
            \dimen2=\@@FLOWheight
            \dimen4=\@@FLOWdy
            \advance\dimen2 2\dimen4
            \dimen2=\@@FLOWny\dimen2
            \advance\dimen2 2\dimen4
            \ifdim\dimen2>\dimen0
              \advance\scratchcounter \minusone
            \else
              \exitloop
            \fi
          \fi
        \else
          \exitloop
        \fi}%
     \expanded{\switchtobodyfont[\the\scratchcounter pt]}%
     \forgetall
     % \offinterlineskip % needed ?
   \else\ifx\@@FLOWbodyfont\empty\else
     \expanded{\switchtobodyfont[\@@FLOWbodyfont]}% \expanded ?
   \fi\fi
   \global\let\FLOWcells\empty
   \dimen0=\@@FLOWwidth
   \edef\FLOWshapewidth{\the\dimen0}%
   \dimen2=\@@FLOWdx
   \advance\dimen0 2\dimen2
   \edef\FLOWgridwidth{\the\dimen0}%
   \dimen0=\@@FLOWheight
   \edef\FLOWshapeheight{\the\dimen0}%
   \dimen2=\@@FLOWdy
   \advance\dimen0 2\dimen2
   \edef\FLOWgridheight{\the\dimen0}%
   \scratchdimen=\@@FLOSrulethickness
   \edef\@@FLOSrulethickness{\the\scratchdimen}%
   \scratchdimen=\@@FLOFrulethickness
   \edef\@@FLOFrulethickness{\the\scratchdimen}%
   \scratchdimen=\@@FLOLrulethickness
   \edef\@@FLOLrulethickness{\the\scratchdimen}%
   \ifdim\@@FLOLradius<2.5\scratchdimen
     \scratchdimen=2.5\scratchdimen
     \edef\@@FLOLradius{\the\scratchdimen}%
     \ifdim\@@FLOLradius>\@@FLOWdx
       \scratchdimen=\@@FLOWdx
       \edef\@@FLOLradius{\the\scratchdimen}%
     \fi
     \ifdim\@@FLOLradius>\@@FLOWdy
       \scratchdimen=\@@FLOWdy
       \edef\@@FLOLradius{\the\scratchdimen}%
     \fi
   \else
     \scratchdimen=\@@FLOLradius
     \edef\@@FLOLradius{\the\scratchdimen}%
   \fi
   \processaction % magic 2.5
     [\@@FLOWoffset]
     [      \v!none=>\scratchdimen=-2.5\scratchdimen,
         \v!overlay=>\scratchdimen=-2.5\scratchdimen,
        \v!standard=>\scratchdimen=\scratchdimen,
         \s!unknown=>\scratchdimen=\@@FLOWoffset,
         \s!default=>\scratchdimen=-2.5\scratchdimen]%
   \edef\@@FLOW@@offset{\the\scratchdimen}%
   \forgetall
   \offinterlineskip
   \resetMPdrawing
   \doglobal\newcounter\FLOWcomment
   \startMPdrawing
     if unknown context_char : input mp-char.mp ; fi ;
     grid_width             := \FLOWgridwidth ;
     grid_height            := \FLOWgridheight ;
     shape_width            := \FLOWshapewidth ;
     shape_height           := \FLOWshapeheight ;
     connection_line_width  := \@@FLOLrulethickness ;
     connection_smooth_size := \@@FLOLradius ;
     connection_arrow_size  := \@@FLOLradius ;
     connection_dash_size   := \@@FLOLradius ;
%  \stopMPdrawing
%  \def\getFLOWlocationX##1,##2\end%
%    {\ifnum0##1>\FLOWwidth \xdef\FLOWwidth {##1}\fi
%     \ifnum0##2>\FLOWheight\xdef\FLOWheight{##2}\fi}%
%  \long\def\startFLOWcellX##1\stopFLOWcell%
%    {\resetFLOWcell
%     \ignorespaces##1\unskip
%     \expandafter\getFLOWlocationX\FLOWlocation\end
%     \ignorespaces}%
%  \let\startFLOWcell\startFLOWcellX
%  \resetFLOWlocation
%  \processFLOWbuffer\currentFLOWnumber
%  \ifnum\@@FLOWnx\@@FLOWny=11 % listig
%    \let\@@FLOWnx\FLOWwidth
%    \let\@@FLOWny\FLOWheight
%  \fi
%  \startMPdrawing
     begin_chart(0,\FLOWwidth,\FLOWheight);
     reverse_y := true ;
     chart_offset := \@@FLOW@@offset ;
   \stopMPdrawing
   \doifelsenothing\@@FLOWbackgroundcolor
     {\startMPdrawing
      chart_background_color := white ;
      \stopMPdrawing}
     {\startMPdrawing
      chart_background_color := \MPcolor{\@@FLOWbackgroundcolor} ;
      \stopMPdrawing}%
   \doif\@@FLOWoption\v!test
     {\startMPdrawing
        show_con_points := true ;
        show_mid_points := true ;
        show_all_points := true ;
      \stopMPdrawing}%
   \processaction % private
     [\@@FLOWdot]
     [     \v!yes=>\startMPdrawing
                    show_con_points := true ;
                    show_mid_points := true ;
                    show_all_points := true ;
                  \stopMPdrawing,
      \s!unknown=>\startMPdrawing
                    show_\@@FLOWdot_points := true ;
                  \stopMPdrawing]%
   \let\startFLOWcell\startFLOWcellB
   \resetFLOWlocation
   \processFLOWbuffer\currentFLOWnumber
   \let\startFLOWcell\startFLOWcellC
   \resetFLOWlocation
   \processFLOWbuffer\currentFLOWnumber
   \startMPdrawing
     clip_chart(\@@FLOWx,\@@FLOWy,\@@FLOWnx,\@@FLOWny) ;
     end_chart ;
   \stopMPdrawing
   \MPdrawingdonetrue
   \setbox0\hbox
     {\MPstaticgraphictrue
      \MPshiftdrawingfalse
      \getMPdrawing}%
   \def\MPmessage##1%
     {\writestatus{MP charts}{##1}}%
   \def\MPposition##1##2##3%
     {\setvalue{\@@MPx##1}{##2}\setvalue{\@@MPy##1}{##3}}%
   \def\MPclippath##1##2##3##4%
     {\def\clipMPllx{##1bp}\def\clipMPlly{##2bp}%
      \def\clipMPurx{##3bp}\def\clipMPury{##4bp}}%
   \def\MPareapath##1##2##3##4%
     {\def\areaMPllx{##1bp}\def\areaMPlly{##2bp}%
      \def\areaMPurx{##3bp}\def\areaMPury{##4bp}}%
   \getMPdata
   \doglobal\newcounter\FLOWcomment
   \let\startFLOWcell\startFLOWcellD
   \setbox2\vbox to \ht0
     {\forgetall % \offinterlineskip
      \resetFLOWlocation
      \processFLOWbuffer\currentFLOWnumber\vss}%
   \setbox2\hbox
     {\hskip\@@FLOW@@offset\lower\@@FLOW@@offset\box2}%
   \wd2\wd0\ht2\ht0\dp2\dp0
   \let\startFLOWcell\startFLOWcellE
   \setbox4\vbox to \ht0
     {\forgetall % \offinterlineskip
      \resetFLOWlocation
      \processFLOWbuffer\currentFLOWnumber\vss}%
   \setbox4\hbox
     {\hskip\@@FLOW@@offset\lower\@@FLOW@@offset\box4}%
   \wd4\wd0\ht4\ht0\dp4\dp0
   \doifelse\@@FLOWoption\v!test
     {\setbox6\vbox
        {\forgetall
         \vskip\@@FLOW@@offset
         \hskip\@@FLOW@@offset
         \basegrid
           [\c!x=\@@FLOWx,\c!nx=\@@FLOWnx,\c!dx=\withoutpt\FLOWgridwidth,
            \c!y=\@@FLOWy,\c!ny=\@@FLOWny,\c!dy=\withoutpt\FLOWgridheight,
            \c!xstep=1,\c!ystep=1,
            \c!unit=pt,\c!location=\v!middle]}%
      \wd6\wd0\ht6\ht0\dp6\dp0
      \setbox8\vbox
        {\forgetall
         \offinterlineskip
         \vskip\@@FLOW@@offset
         \dostepwiserecurse\@@FLOWy\@@FLOWny\plusone
           {\vbox to \FLOWgridheight
              {\vfill
               \hskip\@@FLOW@@offset
               \hbox
                 {\dostepwiserecurse\@@FLOWx\@@FLOWnx\plusone
                    {\hbox to \FLOWgridwidth
                       {\hfill
                        \framed
                          [\c!framecolor=red,
                           \c!width=\FLOWshapewidth,
                           \c!height=\FLOWshapeheight]
                          {}%
                        \hfill}}}
               \vfill}}}%
      \wd8\wd0\ht8\ht0\dp8\dp0
      \framed
        [\c!offset=\v!overlay,\c!framecolor=green]
        {\hbox{\box4\hskip-\wd0\box0\hskip-\wd2\box2\hskip-\wd6\box6\hskip-\wd8\box8}}}
     {\framed
        [\c!offset=\v!overlay,
         \c!frame=\@@FLOWframe,
         \c!rulethickness=\@@FLOWrulethickness,
         \c!framecolor=\@@FLOWframecolor,
         \c!background=\@@FLOWbackground,
         \c!backgroundcolor=\@@FLOWbackgroundcolor]
        {\hbox{\box4\hskip-\wd0\box0\hskip-\wd2\box2}}}%
  %\message{[\FLOWcells]}\wait
   \egroup}

% Pass A

\long\def\startFLOWcellA#1\stopFLOWcell%
  {\resetFLOWcell
   \ignorespaces#1\unskip
   \expandafter\getFLOWlocationA\FLOWlocation\end
   \ignorespaces}

\def\getFLOWlocationA#1,#2\end
  {\ifnum0#1>\FLOWwidth \xdef\FLOWwidth {#1}\fi
   \ifnum0#2>\FLOWheight\xdef\FLOWheight{#2}\fi}

% Pass B
%
% beware: the - after \@FLOC@ is needed since name can be
% empty and we don't want to redefine \@FLOC@ itself by
% mistake

\long\def\startFLOWcellB#1\stopFLOWcell
  {\resetFLOWcell\ignorespaces#1\unskip
   \setxvalue{\@FLOC@-\FLOWname}{\FLOWlocation}% kost veel cs's
   \ifx\FLOWshape\empty
     \global\let\FLOWshape\@@FLOSdefault
   \fi
   \doifnot\FLOWshape{none} % {\v!none}
     {\ExpandBothAfter\doifinsetelse{\FLOWshape}{\FLOWshapes}
        {\edef\FLOWshapetag{shape_\FLOWshape}% beter \expanded
         \@EA\setFLOWname\@EA\FLOWshapetag\@EA{\FLOWshapetag}}
        {\doifnumberelse\FLOWshape
           {\let\FLOWshapetag\FLOWshape}
           {\let\FLOWshapetag\empty}}%
      \ifx\FLOWshapetag\empty \else
        \ExpandBothAfter\doifinsetelse{\FLOWshape}{\FLOWlines}
          {\chardef\FLOWstate0 }
          {\ExpandBothAfter\doifcommonelse{\FLOWcell,\FLOWfocus}{\@@FLOWfocus}
             {\chardef\FLOWstate1 }
             {\chardef\FLOWstate2 }}%
        \startMPdrawing
          begin_sub_chart ;
          \ifcase\FLOWstate
            shape_line_color := \MPcolor{\@@FLOLcolor} ;
            shape_fill_color := \MPcolor{\@@FLOLcolor} ;
            shape_line_width := \@@FLOLrulethickness ;
          \or
            shape_line_color := \MPcolor{\@@FLOFframecolor} ;
            shape_fill_color := \MPcolor{\@@FLOFbackgroundcolor} ;
            shape_line_width := \@@FLOFrulethickness ;
          \or
            shape_line_color := \MPcolor{\@@FLOSframecolor} ;
            shape_fill_color := \MPcolor{\@@FLOSbackgroundcolor} ;
            shape_line_width := \@@FLOSrulethickness ;
          \fi
         %\ifx\FLOWoverlay\empty
         %  peepshape := false ;
         %\else
         %  peepshape := true ;
         %\fi
          peepshape := \ifx\FLOWoverlay\empty false \else true \fi ;
          new_shape(\FLOWlocation,\FLOWshapetag) ;
          end_sub_chart ;
        \stopMPdrawing
      \fi}%
   \ignorespaces}

% Pass C

\long\def\startFLOWcellC#1\stopFLOWcell%
  {\resetFLOWcell
\pushmacro\lastFLOWx
\pushmacro\lastFLOWy
   \ignorespaces#1\unskip % makes sure that vars are set
\popmacro\lastFLOWy
\popmacro\lastFLOWx
   \let\connection\doFLOWconnectionC
   \ignorespaces#1\unskip}

\def\FLOWorigin{0,0}

\def\doFLOWdisplace[#1,#2,#3]% experiment
  {dsp_x := #1 ; dsp_y := #2 ;}

\def\doFLOWconnectionC
  {\dodoubleempty\dodoFLOWconnectionC}

\def\dodoFLOWconnectionC[#1][#2]#3%
  {\doglobal\increment\FLOWcomment
   \setFLOWname\otherFLOWname{name_#3}%
   \doifdefinedelse{\@FLOC@-\FLOWname}
     {\edef\FLOWfrom{\getvalue{\@FLOC@-\FLOWname}}}
     {\let \FLOWfrom \FLOWorigin}%
   \ifx\FLOWfrom\FLOWorigin \else
     \doifdefinedelse{\@FLOC@-\otherFLOWname}
       {\edef\FLOWto  {\getvalue{\@FLOC@-\otherFLOWname}}}
       {\let \FLOWto   \FLOWorigin}%
     \ifx\FLOWto\FLOWorigin \else
       \FLOWsetconnect{#1}%
       \ifx\cFLOWfrom\empty \else
         \doifelse\@@FLOLcorner\v!round
           {\startMPdrawing smooth     := true  ; \stopMPdrawing}
           {\startMPdrawing smooth     := false ; \stopMPdrawing}%
         \doifelse\@@FLOLdash\v!yes
           {\startMPdrawing dashline   := true  ; \stopMPdrawing}
           {\startMPdrawing dashline   := false ; \stopMPdrawing}%
         \doifelse\@@FLOLarrow\v!yes
           {\startMPdrawing arrowtip   := true  ; \stopMPdrawing}
           {\startMPdrawing arrowtip   := false ; \stopMPdrawing}%
         \doifelse\@@FLOLoffset\v!none
           {\startMPdrawing touchshape := true  ; \stopMPdrawing}
           {\startMPdrawing touchshape := false ; \stopMPdrawing}%
%\doifsomething{#2}
%  {\startMPdrawing
%   \doFLOWdisplace[0#2,0,0]%
%   \stopMPdrawing}%
         \startMPdrawing
\doFLOWdisplace[0#2,0,0]%
           connection_line_color := \MPcolor{\@@FLOLcolor} ;
           connection_line_width := \@@FLOLrulethickness ;
           connect_\cFLOWfrom_\cFLOWto (\FLOWfrom,\zFLOWfrom) (\FLOWto,\zFLOWto) ;
\doFLOWdisplace[0,0,0]%
         \stopMPdrawing
       \fi
     \fi
   \fi
   \ignorespaces}

% Pass D

\long\def\startFLOWcellD#1\stopFLOWcell%
  {\resetFLOWcell
\pushmacro\lastFLOWx
\pushmacro\lastFLOWy
   \ignorespaces#1\unskip % presets vars
\popmacro\lastFLOWy
\popmacro\lastFLOWx
   \let\doprocessFLOWcell\doprocessFLOWcellD
   \expandafter\doprocessFLOWcellD\FLOWlocation\end
   \let\connection\doFLOWconnectionD
   \let\comment\doFLOWcommentD
   \ignorespaces#1\unskip\ignorespaces}

\def\doFLOWconnectionD
  {\dodoubleempty\dodoFLOWconnectionD}

\def\dodoFLOWconnectionD[#1][#2]#3%
  {\doglobal\increment\FLOWcomment
   \ignorespaces}

\def\doFLOWcommentD[#1]#2%
  {\bgroup
   \let\FLOW  \middlebox
   \let\FLOWb \bottombox
   \let\FLOWbl\bottomleftbox
   \let\FLOWbr\bottomrightbox
   \let\FLOWt \topbox
   \let\FLOWtl\topleftbox
   \let\FLOWtr\toprightbox
   \let\FLOWl \leftbox
   \let\FLOWlt\lefttopbox
   \let\FLOWlb\leftbottombox
   \let\FLOWr \rightbox
   \let\FLOWrt\righttopbox
   \let\FLOWrb\rightbottombox
   \let\FLOWc \middlebox
%\ifdefined{FLOW#1}%
   \ifcase0\getvalue{\@@MPx\FLOWcomment}\getvalue{\@@MPy\FLOWcomment}\relax
   \else
     \ifdim\getvalue{\@@MPx\FLOWcomment}\s!bp<\areaMPllx\relax\else
       \ifdim\getvalue{\@@MPx\FLOWcomment}\s!bp>\areaMPurx\relax\else
         \ifdim\getvalue{\@@MPy\FLOWcomment}\s!bp<\areaMPlly\relax\else
           \ifdim\getvalue{\@@MPy\FLOWcomment}\s!bp>\areaMPury\relax\else
             \dimen0=\getvalue{\@@MPx\FLOWcomment}\s!bp
             \advance\dimen0 -\@@FLOW@@offset
             \advance\dimen0 -\clipMPllx
             \dimen2=\clipMPury
             \advance\dimen2 -\@@FLOW@@offset
             \advance\dimen2 -\getvalue{\@@MPy\FLOWcomment}\s!bp
             \setbox0=\hbox{\strut#2}%
             \boxoffset=.5\bodyfontsize
             \setbox0=\hbox
               {\hskip\dimen0\lower\dimen2\getvalue{FLOW#1}{\box0}}%
             \wd0=\zeropoint\ht0=\zeropoint\dp0=\zeropoint
             \box0
           \fi
         \fi
       \fi
     \fi
   \fi
%\fi
   \egroup
   \ignorespaces}

% pass D

\def\dophaseoneFLOWcellX#1#2%
  {\!!counta#1\relax
   \!!countb#2\relax
   \!!countc\@@FLOWx
   \!!countd\@@FLOWy
   \advance\!!countc \@@FLOWnx
   \advance\!!countd \@@FLOWny
   \advance\!!countc \minusone
   \advance\!!countd \minusone
        \ifnum\!!counta<\@@FLOWx\relax  \donefalse
   \else\ifnum\!!counta>\!!countc       \donefalse
   \else\ifnum\!!countb<\@@FLOWy\relax  \donefalse
   \else\ifnum\!!countb>\!!countd       \donefalse
   \else                                \donetrue
   \fi\fi\fi\fi}

\def\dophasetwoFLOWcellX
  {\advance\!!counta -\@@FLOWx
   \advance\!!counta \plusone
   \advance\!!countb -\@@FLOWy
   \advance\!!countb \plusone
   \dimen0=\FLOWgridwidth
   \dimen0=\!!counta\dimen0
   \advance\dimen0 -\FLOWgridwidth
   \dimen4=\FLOWgridwidth
   \advance\dimen4 -\FLOWshapewidth
   \advance\dimen0 .5\dimen4
   \dimen2=\FLOWgridheight
   \dimen2=\!!countb\dimen2
   \dimen4=\FLOWgridheight
   \advance\dimen4 -\FLOWshapeheight
   \advance\dimen2 -.5\dimen4
   \edef\FLOWdx{\the\dimen0}%
   \edef\FLOWdy{\the\dimen2}}

\def\positionFLOWzero% assumes \FLOWdx and \FLOWdy are set
  {\setbox0\hbox{\hskip\FLOWdx\lower\FLOWdy\box0}%
   \smashbox0\box0
   \nointerlineskip} % new, needed since we somehow reset that

\def\doFLOWtlabel#1#2#3%
  {\scratchdimen\ifcase#2 \zeropoint\else\@@FLOWdy\fi
   \setbox0\hbox{\hskip\dimen2\raise\scratchdimen
     \hbox{\raise\dimen4\hbox{#1{\strut#3}}}}%
   \positionFLOWzero}%

\def\doFLOWblabel#1#2#3%
  {\scratchdimen\ifcase#2 \zeropoint\else\@@FLOWdy\fi
   \setbox0\hbox{\hskip\dimen2\raise-\scratchdimen
     \hbox{#1{\strut#3}}}%
   \positionFLOWzero}%

\def\doFLOWllabel#1#2#3%
  {\scratchdimen\ifcase#2 \zeropoint\else\@@FLOWdx\fi
   \setbox0\hbox{\hskip-\scratchdimen\raise\dimen6
     \hbox{#1{\strut#3}}}%
   \positionFLOWzero}%

\def\doFLOWrlabel#1#2#3%
  {\scratchdimen\ifcase#2 \zeropoint\else\@@FLOWdx\fi
   \setbox0\hbox{\hskip\dimen0\hskip\scratchdimen
   \hbox{\raise\dimen6\hbox{#1{\strut#3}}}}%
   \positionFLOWzero}

\def\doprocessFLOWcellD#1,#2\end
  {\dophaseoneFLOWcellX{#1}{#2}%
   \ifdone
     \dophasetwoFLOWcellX
     \doglobal\addtocommalist\FLOWcell\FLOWcells
     \setbox0\hbox
       {\ifx\FLOWalign\empty\else
          \setupframed
            [\c!align=\v!normal,\c!bottom=\vfill,\c!top=\vfill]%
          \@EA\processallactionsinset\@EA
            [\FLOWalign]
            [t=>{\setupframed[\c!bottom=\vfill,\c!top=]},
             b=>{\setupframed[\c!bottom=,\c!top=\vfill]},
             l=>{\setupframed[\c!align=\v!right]},
             r=>{\setupframed[\c!align=\v!left]},
             m=>{\setupframed[\c!align=\v!middle]},
             c=>{\setupframed[\c!align=\v!middle]}]%
        \fi
        \doifelse\FLOWshape{none} % {\v!none}
          {\setupframed[\c!offset=\v!overlay]}
         %{\setupframed[\c!offset=.5\bodyfontsize]}%
          {\setupframed[\c!offset=\@@FLOSoffset]}%
        \framed
          [\c!frame=\v!off,
           \c!width=\FLOWshapewidth,\c!height=\FLOWshapeheight]
          {\FLOWtext}}%
       \showFLOWhelp0
       \ifx\FLOWdestination\empty\else
         \setbox0\hbox
           {\setupinteraction[\c!color=,\c!contrastcolor=]%
            \gotobox{\box0}[\FLOWdestination]}%
       \fi
     \positionFLOWzero
     \dimen0=\FLOWshapewidth \dimen2=.5\dimen0
     \dimen4=\FLOWshapeheight\dimen6=.5\dimen4
     \boxoffset=.5\bodyfontsize
     \doFLOWtlabel   \righttopbox0\tFLOWlabel
     \doFLOWblabel\rightbottombox0\bFLOWlabel
     \doFLOWllabel    \lefttopbox0\lFLOWlabel
     \doFLOWrlabel   \righttopbox0\rFLOWlabel
     \doFLOWtlabel        \topbox0\tcFLOWlabel % for me only
     \doFLOWblabel     \bottombox0\bcFLOWlabel % for me only
     \doFLOWllabel       \leftbox0\lcFLOWlabel % for me only
     \doFLOWrlabel      \rightbox0\rcFLOWlabel % for me only
     \ifnum#1=\@@FLOWx\relax \doFLOWllabel   \leftbox1\lFLOWexit \fi
     \ifnum#1=\!!countc      \doFLOWrlabel  \rightbox1\rFLOWexit \fi
     \ifnum#2=\@@FLOWy\relax \doFLOWtlabel    \topbox1\tFLOWexit \fi
     \ifnum#2=\!!countd      \doFLOWblabel \bottombox1\bFLOWexit \fi
   \fi}

% Pass E

\long\def\startFLOWcellE#1\stopFLOWcell
  {\resetFLOWcell
   \ignorespaces#1\unskip
   \let\doprocessFLOWcell\doprocessFLOWcellE
   \expandafter\doprocessFLOWcell\FLOWlocation\end}

\def\dophaseoneFLOWcellX#1#2%
  {\!!counta#1\relax
   \!!countb#2\relax
   \!!countc\@@FLOWx
   \!!countd\@@FLOWy
   \advance\!!countc \@@FLOWnx
   \advance\!!countd \@@FLOWny
   \advance\!!countc \minusone
   \advance\!!countd \minusone
        \ifnum\!!counta<\@@FLOWx\relax  \donefalse
   \else\ifnum\!!counta>\!!countc       \donefalse
   \else\ifnum\!!countb<\@@FLOWy\relax  \donefalse
   \else\ifnum\!!countb>\!!countd       \donefalse
   \else                                \donetrue
   \fi\fi\fi\fi}

\def\dophasetwoFLOWcellX
  {\advance\!!counta -\@@FLOWx
   \advance\!!counta \plusone
   \advance\!!countb -\@@FLOWy
   \advance\!!countb \plusone
   \dimen0=\FLOWgridwidth
   \dimen0=\!!counta\dimen0
   \advance\dimen0 -\FLOWgridwidth
   \dimen4=\FLOWgridwidth
   \advance\dimen4 -\FLOWshapewidth
   \advance\dimen0 .5\dimen4
   \dimen2=\FLOWgridheight
   \dimen2=\!!countb\dimen2
   \dimen4=\FLOWgridheight
   \advance\dimen4 -\FLOWshapeheight
   \advance\dimen2 -.5\dimen4
   \edef\FLOWdx{\the\dimen0}%
   \edef\FLOWdy{\the\dimen2}}

\def\positionFLOWzero% assumes \FLOWdx and \FLOWdy are set
  {\setbox0\hbox{\hskip\FLOWdx\lower\FLOWdy\box0}%
   \smashbox0\box0
   \nointerlineskip}%

\def\doFLOWtlabel#1#2#3%
  {\scratchdimen\ifcase#2 \zeropoint\else\@@FLOWdy\fi
   \setbox0\hbox{\hskip\dimen2\raise\scratchdimen
     \hbox{\raise\dimen4\hbox{#1{\strut#3}}}}%
   \positionFLOWzero}%

\def\doFLOWblabel#1#2#3%
  {\scratchdimen\ifcase#2 \zeropoint\else\@@FLOWdy\fi
   \setbox0\hbox{\hskip\dimen2\raise-\scratchdimen
     \hbox{#1{\strut#3}}}%
   \positionFLOWzero}%

\def\doFLOWllabel#1#2#3%
  {\scratchdimen\ifcase#2 \zeropoint\else\@@FLOWdx\fi
   \setbox0\hbox{\hskip-\scratchdimen\raise\dimen6
     \hbox{#1{\strut#3}}}%
   \positionFLOWzero}%

\def\doFLOWrlabel#1#2#3%
  {\scratchdimen\ifcase#2 \zeropoint\else\@@FLOWdx\fi
   \setbox0\hbox{\hskip\dimen0\hskip\scratchdimen
   \hbox{\raise\dimen6\hbox{#1{\strut#3}}}}%
   \positionFLOWzero}

\def\doprocessFLOWcellD#1,#2\end
  {\dophaseoneFLOWcellX{#1}{#2}%
   \ifdone
     \dophasetwoFLOWcellX
     \doglobal\addtocommalist\FLOWcell\FLOWcells
     \setbox0\hbox
       {\ifx\FLOWalign\empty\else
          \setupframed
            [\c!align=\v!normal,\c!bottom=\vfill,\c!top=\vfill]%
          \@EA\processallactionsinset\@EA
            [\FLOWalign]
            [t=>{\setupframed[\c!bottom=\vfill,\c!top=]},
             b=>{\setupframed[\c!bottom=,\c!top=\vfill]},
             l=>{\setupframed[\c!align=\v!right]},
             r=>{\setupframed[\c!align=\v!left]},
             m=>{\setupframed[\c!align=\v!middle]},
             c=>{\setupframed[\c!align=\v!middle]}]%
        \fi
        \doifelse\FLOWshape{none} % {\v!none}
          {\setupframed[\c!offset=\v!overlay]}
         %{\setupframed[\c!offset=.5\bodyfontsize]}%
          {\setupframed[\c!offset=\@@FLOSoffset]}%
        \framed
          [\c!frame=\v!off,
           \c!width=\FLOWshapewidth,\c!height=\FLOWshapeheight]
          {\FLOWtext}}%
       \showFLOWhelp0
       \ifx\FLOWdestination\empty\else
         \setbox0\hbox
           {\setupinteraction[\c!color=,\c!contrastcolor=]%
            \gotobox{\box0}[\FLOWdestination]}%
       \fi
     \positionFLOWzero
     \dimen0=\FLOWshapewidth \dimen2=.5\dimen0
     \dimen4=\FLOWshapeheight\dimen6=.5\dimen4
     \boxoffset=.5\bodyfontsize
     \doFLOWtlabel   \righttopbox0\tFLOWlabel
     \doFLOWblabel\rightbottombox0\bFLOWlabel
     \doFLOWllabel    \lefttopbox0\lFLOWlabel
     \doFLOWrlabel   \righttopbox0\rFLOWlabel
     \doFLOWtlabel        \topbox0\tcFLOWlabel % for me only
     \doFLOWblabel     \bottombox0\bcFLOWlabel % for me only
     \doFLOWllabel       \leftbox0\lcFLOWlabel % for me only
     \doFLOWrlabel      \rightbox0\rcFLOWlabel % for me only
     \ifnum#1=\@@FLOWx\relax \doFLOWllabel   \leftbox1\lFLOWexit \fi
     \ifnum#1=\!!countc      \doFLOWrlabel  \rightbox1\rFLOWexit \fi
     \ifnum#2=\@@FLOWy\relax \doFLOWtlabel    \topbox1\tFLOWexit \fi
     \ifnum#2=\!!countd      \doFLOWblabel \bottombox1\bFLOWexit \fi
   \fi}

\def\doprocessFLOWcellE#1,#2\end  % redundant
  {\ifx\FLOWoverlay\empty \else
     \dophaseoneFLOWcellX{#1}{#2}%
     \ifdone
       \dophasetwoFLOWcellX
       \edef\FLOWdx{\the\dimen0}%
       \edef\FLOWdy{\the\dimen2}%
       \setbox0\hbox
         {\framed
            [%\c!frame=\v!off,
             \c!background={\@@FLOWbackground,\FLOWoverlay},
             \c!backgroundcolor=\@@FLOSbackgroundcolor,
             \c!width=\FLOWshapewidth,\c!height=\FLOWshapeheight]
            {}}%
       \positionFLOWzero
     \fi
   \fi}

% Pass F

\def\checkFLOWautofocus
  {\def\@@FLOWminx{100}\let\@@FLOWminy\@@FLOWminx
   \def\@@FLOWmaxx  {0}\let\@@FLOWmaxy\@@FLOWmaxx
   \def\@@FLOWabsx  {0}\let\@@FLOWabsy\@@FLOWabsx
   \let\startFLOWcell\startFLOWcellF
   \resetFLOWlocation
   \processFLOWbuffer\currentFLOWnumber
  %\message{AUTOSHAPE 1: (\@@FLOWminx,\@@FLOWminy)->(\@@FLOWmaxx,\@@FLOWmaxy)}%
   \ifnum\@@FLOWabsx<\@@FLOWmaxx\let\@@FLOWmaxx\@@FLOWabsx\fi
   \ifnum\@@FLOWabsy<\@@FLOWmaxy\let\@@FLOWmaxy\@@FLOWabsy\fi
  %\message{AUTOSHAPE 2: (\@@FLOWminx,\@@FLOWminy)->(\@@FLOWmaxx,\@@FLOWmaxy)}%
   \donetrue
   \ifnum\@@FLOWminx=100 \donefalse\fi
   \ifnum\@@FLOWminy=100 \donefalse\fi
   \ifnum\@@FLOWmaxx=0   \donefalse\fi
   \ifnum\@@FLOWmaxy=0   \donefalse\fi
   \doFLOWcheckF\@@FLOWx\@@FLOWminx\@@FLOWmaxx\@@FLOWnx
   \doFLOWcheckF\@@FLOWy\@@FLOWminy\@@FLOWmaxy\@@FLOWny}

\def\startFLOWcellF#1\stopFLOWcell%
  {\resetFLOWcell
   \ignorespaces#1\unskip
   \expandafter\doFLOWlocationF\FLOWlocation\end}%

\def\doFLOWlocationF#1,#2\end%
  {\ifnum#1>\@@FLOWabsx\def\@@FLOWabsx{#1}\fi
   \ifnum#2>\@@FLOWabsy\def\@@FLOWabsy{#2}\fi
   \ExpandBothAfter\doifinset{\FLOWcell}{\@@FLOWautofocus}
     {\dodoFLOWlocationF{#1}<-\@@FLOWminx
      \dodoFLOWlocationF{#1}>+\@@FLOWmaxx
      \dodoFLOWlocationF{#2}<-\@@FLOWminy
      \dodoFLOWlocationF{#2}>+\@@FLOWmaxy}}

\def\dodoFLOWlocationF#1#2#3#4%
  {\ifnum#1#2#4\relax
     \!!counta=#1\advance\!!counta #31\relax
     \edef#4{\ifnum\!!counta<1 1\else\the\!!counta\fi}%
   \fi}

\def\doFLOWcheckF#1#2#3#4%
  {\ifdone
     \let#1=#2%
     \!!counta=#3%
     \advance\!!counta \plusone\advance\!!counta -#2\relax
     \ifnum\!!counta<1 \!!counta=1 \fi
     \edef#4{\the\!!counta}%
   \else
     \def#1{1}\def#4{0}% no {1}
   \fi}

% \useFLOWchart[name][parent][setting,setting][additional settings]
% \useFLOWchart[name][parent][additional settings]

\let\currentFLOWchart\empty

\def\useFLOWchart
  {\doquadrupleempty\douseFLOWchart}

\def\douseFLOWchart[#1][#2][#3][#4]% name parent sets mainsettings
  {\iffourthargument
     \setvalue{\@FLOW@--#1}[##1]{\setgetFLOWchart[#2][#3][#4,##1]}%
   \else
     \checkparameters[#3]%
     \ifparameters
       \setvalue{\@FLOW@--#1}[##1]{\setgetFLOWchart[#2][][#3,##1]}%
     \else
       \setvalue{\@FLOW@--#1}[##1]{\setgetFLOWchart[#2][#3][##1]}%
     \fi
   \fi}

\def\setgetFLOWchart[#1][#2][#3]%
   {\def\docommando##1{}% cell line focus ?
    \processcommalist[#2]\docommando
    \getFLOWchart[#1][#3]}

\def\doFLOWchart[#1][#2]%
  {\hbox\bgroup\vbox\bgroup % vmode suppresses spaces
\def\currentFLOWchart{#1}%
   \doifundefinedelse{\@FLOW@--#1}
     {\getFLOWchart[#1][#2]}
     {\getvalue{\@FLOW@--#1}[#2]}%
   \egroup\egroup}

\def\FLOWchart%
  {\dodoubleempty\doFLOWchart}

%D A hook into the help system.

\def\showFLOWhelp#1%
  {\doifhelpinfo\FLOWhelp
     {\setbox#1=\hbox
        {\setbox\scratchbox=\hbox{\lower\@@FLOWdy\hbox
           {\helpbutton
              [\c!width=\wd0,\c!color=,\c!height=\@@FLOWdy,\c!frame=\v!no]%
              [\FLOWhelp]}}%
         \smashbox\scratchbox
         \setbox#1=\vbox
           {\forgetall\offinterlineskip\box#1\box\scratchbox}%
         \box#1}}}

%D The next section is dedicated to splitting up charts.

\def\getFLOWsize[#1]%
  {\bgroup\let\dodogetFLOWchart\dogetFLOWsize\FLOWchart[#1]\egroup}

\def\dogetFLOWsize[#1][#2]%
  {\setbox\scratchbox=\vbox
     {\xdef\FLOWmaxwidth {0}%
      \xdef\FLOWmaxheight{0}%
      \def\getFLOWlocation##1,##2\end
        {\ifnum0##1>\FLOWmaxwidth \xdef\FLOWmaxwidth {##1}\fi
         \ifnum0##2>\FLOWmaxheight\xdef\FLOWmaxheight{##2}\fi}%
      \resetFLOWcell
      \long\def\startFLOWcell##1\stopFLOWcell
        {{##1\expandafter\getFLOWlocation\FLOWlocation\end}}%
      \def\dohandleflowchart[##1][##2]%
        {\resetFLOWlocation
         \processFLOWbuffer{##1}}%
      \getvalue{\@FLOW@-#1}}}

\def\setupFLOWsplit%
  {\dodoubleargument\getparameters[\@@FLOT]}

\setupFLOWsplit%
  [\c!nx=3,\c!ny=3,
   \c!dx=1,\c!dy=1,
   \c!command=,
   \c!marking=\v!on,
   \c!before=,\c!after=]

\def\FLOWsplitx {1}
\def\FLOWsplity {1}
\def\FLOWsplitnx{1}
\def\FLOWsplitny{1}

\def\FLOWcharts%
  {\dodoubleempty\doFLOWcharts}

%D While splitting, the following variables are available:
%D
%D \starttyping
%D \FLOWsplitnx \FLOWsplitny \FLOWsplitx \FLOWsplity
%D \stoptyping

\def\doFLOWcharts[#1][#2]%
  {\bgroup
   \getFLOWsize[#1]%
   \dodoFLOWcharts\relax
   \global\let\FLOWsplitnx\FLOWsplitx
   \global\let\FLOWsplitny\FLOWsplity
   \dodoFLOWcharts{\dododoFLOWcharts[#1][#2]}%
   \egroup}

\def\dodoFLOWcharts#1%
  {\def\@@FLOTx{1}%
   \global\let\FLOWsplitx\@@FLOTx
   \doloop
     {\def\@@FLOTy{1}%
      \global\let\FLOWsplity\@@FLOTy
      \doloop
        {\bgroup
         \scratchcounter\FLOWmaxwidth
         \advance\scratchcounter -\@@FLOTx
         \advance\scratchcounter \plusone
         \ifnum\scratchcounter<\@@FLOTnx\edef\@@FLOTnx{\the\scratchcounter}\fi
         \scratchcounter\FLOWmaxheight
         \advance\scratchcounter -\@@FLOTy
         \advance\scratchcounter \plusone
         \ifnum\scratchcounter<\@@FLOTny\edef\@@FLOTny{\the\scratchcounter}\fi
         #1% does something with the float, or not
         \egroup
         \increment(\@@FLOTy,\@@FLOTny)%
         \ifnum\@@FLOTy>\FLOWmaxheight
           \exitloop
         \else
           \doglobal\increment\FLOWsplity
           \decrement(\@@FLOTy,\@@FLOTdy)%
         \fi}%
      \increment(\@@FLOTx,\@@FLOTnx)%
      \ifnum\@@FLOTx>\FLOWmaxwidth
        \exitloop
      \else
        \doglobal\increment\FLOWsplitx
        \decrement(\@@FLOTx,\@@FLOTdx)%
      \fi}}

\def\dododoFLOWcharts[#1][#2]%
  {\bgroup
   \@@FLOTbefore
   \doifnot\@@FLOTmarking\v!on{\let\cuthbox\hbox}%
   \cuthbox
     {\@@FLOTcommand
        {\FLOWchart[#1][#2,
           \c!x=\@@FLOTx,\c!nx=\@@FLOTnx,
           \c!y=\@@FLOTy,\c!ny=\@@FLOTny]}}%
   \@@FLOTafter
   \egroup}

%D An example of splitting is given below:
%D
%D \starttyping
%D \setupFLOWsplit
%D   [nx=5,ny=10,
%D    dx=0,dy=0,
%D    before=,
%D    after=\page]
%D
%D \FLOWcharts[mybigflow]
%D \stoptyping
%D
%D Or, one can say:
%D
%D \starttyping
%D \splitfloat
%D   {\placefigure{What a big flowchart this is!}}
%D   {\FLOWcharts[mybigflow]}
%D \stoptyping

%D \macros
%D   {typeFLOWchart}
%D
%D For documentation purposes the following macro is
%D provided. Watch the use of the first and last line hooks,
%D which is needed because the start and stop commands are
%D not part of the buffer.

\def\typeFLOWchart[#1]%
  {\bgroup
   \def\dohandleflowchart[##1][##2]{\typeFLOWbuffer{##1}}%
   \convertargument\startFLOWchart[#1]\to\firstverbatimfileline
   \convertargument     \stopFLOWchart\to\lastverbatimfileline
   \getvalue{\@FLOW@-#1}
   \egroup}

%D New:
%D
%D \starttyping
%D \setupFLOWcharts[command=\Whow]
%D
%D \startFLOWset[convert-en] % [tag][convert-en]
%D   \subFLOWchart[a][x=1,y=1,nx=3,ny=3]
%D   \subFLOWchart[b][x=1,y=2,nx=3,ny=3]
%D   \subFLOWchart[c][x=2,y=1,nx=3,ny=3]
%D \stopFLOWset
%D
%D \def\Whow#1%
%D   {\ifnum\currentFLOWset=1 \framed{Some Chart}\fi}
%D
%D \FLOWset[convert-en] % [tag]
%D
%D \def\Whow#1%
%D   {\setuphead[state=high]
%D    \startstandardmakeup
%D    \centerbox{#1}
%D    \stopstandardmakeup}
%D
%D \FLOWset[convert-en] % [tag]
%D \stoptyping

\def\startFLOWset
  {\dodoubleempty\dostartFLOWset}

\def\dostartFLOWset[#1][#2]#3\stopFLOWset % tag name data
  {\ifsecondargument
     \long\setvalue{\@FLOX@#1}{\dohandleFLOWset{#1}{#2}{#3}}%
   \else
     \long\setvalue{\@FLOX@#1}{\dohandleFLOWset{#1}{#1}{#3}}%
   \fi}

\long\def\dohandleFLOWset#1#2#3% tag name data
  {\bgroup
   \def\subFLOWchart
     {\dodoubleempty\dosubFLOWchart}%
   \def\dosubFLOWchart[##1][##2]% subtag settings
     {\ifsecondargument
        \dodohandleFLOWset{#1}{##1}{#2}{##2}%
      \else
        \subFLOWchart[][##1]%
      \fi}%
   #3%
   \egroup}

\def\dodohandleFLOWset#1#2#3#4% tag subtag name settings
  {\increment\currentFLOWset
   \bgroup
   \@@FLOXcommand
     {\ifnum\currentFLOWset=1 \pagereference[#1]\fi
      \doifsomething{#2}
        {\setupreferencing[\c!prefix=]%
         \pagereference[#1:#2]% -:#1:#2
         \setupreferencing[\c!prefix=#1:#2]}%
      \FLOWchart[#3][#4]}%
   \egroup}

\def\FLOWset[#1]%
  {\newcounter\currentFLOWset
   \doifdefinedelse{\@FLOX@#1}
     {\getvalue{\@FLOX@#1}}
     {\dodohandleFLOWset{#1}{}{#1}{}}}

\newcounter\currentFLOWset

\setupFLOWsets
  [\c!command=]

%D This will be an option:

% \def\startFLOWchart%
%   {\dodoubleempty\dostartFLOWchart}
%
% \long\def\dostartFLOWchart[#1][#2]#3\stopFLOWchart
%   {\preparenextFLOWchart{#1}{#2}%
%    \long\setgvalue{\FLOWbufferprefix\nofFLOWcharts}{#3}}
%
% \long\def\dodefineFLOWchart[#1][#2]#3%
%   {\preparenextFLOWchart{#1}{#2}%
%    \long\setgvalue{\FLOWbufferprefix\nofFLOWcharts}{#3}}
%
% \def\processFLOWbuffer#1{\getvalue{\FLOWbufferprefix#1}}
% \def\typeFLOWbuffer   #1{[Sorry, no verbatim chart #1 available.]}

%D The XML interface [will be mode protected or separate x-chart file]

\startXMLdefinitions flowchart

\defineXMLargument [flowchartdefinition]
  {\defineFLOWchart[\XMLpar{flowchartdefinition}{identifier}{unknown}]}

\defineXMLpickup [flowcell]
  {\startFLOWcell
   \defineXMLargument[name]{\unspaceafter\name}%
   \defineXMLargument[shape]{\unspaceafter\shape}%
   \defineXMLnestedargument[text]{\text}}
  {\stopFLOWcell}

\defineXMLenvironment [location] % global unspace/store
  {\bgroup\defineXMLpush[x]\defineXMLpush[y]}
  {\XMLunspace{x}\XMLunspace{y}%
   \expanded{\egroup\noexpand\location{\XMLpop{x},\XMLpop{y}}}}

\defineXMLenvironment [connection]
  {\bgroup\defineXMLpush[type]\defineXMLpush[name]}%
  {\XMLunspace{type}\XMLunspace{name}%
   \expanded{\egroup\noexpand\connection[\XMLpop{type}]{\XMLpop{name}}}}

\defineXMLsingular [flowchart]
  {\expanded{\FLOWchart[\XMLpar{flowchart}{identifier}{unknown}]}}

\defineXMLdirective [flowchart] [shapes] \setupFLOWshapes
\defineXMLdirective [flowchart] [lines]  \setupFLOWlines

\stopXMLdefinitions

\protect \endinput
