%D \module
%D   [       file=core-pos,
%D        version=1999.08.01,
%D          title=\CONTEXT\ Core Macros,
%D       subtitle=Positioning Support,
%D         author=Hans Hagen,
%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.

% needs a cleanup, things may change

% shorter tags, ..:achtergrond:.. etc in pos actions

% dubbele text- * pos's eruit

% class pos -> als gelijk aan vorige, dan niet niet definieren
% en erven, maw:
%
% 1 -> opslaan
% 2 -> undef, dus == prev
% 3 -> undef, dus == prev
% 4 -> opslaan

\writestatus{loading}{Context Positioning Support}

% todo: topskip als optie voor eerste regel achtergrond
% todo: build pos layers on top of layers
% todo: positionlayer pos van text-1 etc delen

%D Although \TEX\ has a rather powerful channel to the outside
%D world, called \type {\special}, real communication with
%D other programs is complicated by the fact that no positional
%D information is available. Mid 1999, I discussed this with
%D \THANH, the author of \PDFTEX, and after some experiments,
%D \PDFTEX\ was extended with a simple but effective mechanism,
%D that provided positional information. The interesting
%D thought is that, although \TEX\ is frozen, similar
%D functionality could have been achieved with \type
%D {\specials} and an additional \DVI\ postprocessor.
%D
%D Since we want to be as compatible as can be, \CONTEXT\ will
%D support both methods, although the development is primarily
%D driven by the \PDFTEX\ way of doing things. Since the
%D mechanism is basically not limited to one application, for
%D the moment we stick to building the functionality around one
%D \CONTEXT\ special command, but at the same time we keep our
%D eyes open for extensions in other directions.
%D
%D A question that may arise when one reads this module, is to
%D what extend these macros are generic, in the sense that they
%D could be collected in a support module instead of a core
%D module. Since the mechanism described here will closely
%D cooperate with the \METAPOST\ support built in \CONTEXT,
%D which in turn will be tightly integrated with the \CONTEXT\
%D overlay mechanisms, I decided to write a core module instead
%D of a support one. This makes even more sense, when one takes
%D into account that this kind of support depends on special
%D drivers.

\unprotect

%D The first application of positional information was embedded
%D graphics. Since we are interacting with text, it made sense
%D to take the current line height and depth into account too.
%D This is why we have two basic position macros: one for
%D simple positions, and one for boxes.
%D
%D We could have sticked to one special, and actually did so in
%D earlier experiments, but for convenience, as well for
%D clearness, we now have two alternatives. This approach will
%D save us quite some bytes when storing large quantities of
%D positional information. We save as less information as
%D needed, that is, we save no dimensions, in a \METAPOST\
%D friendly way.
%D
%D The three specials involved are:
%D
%D \starttypen
%D \dosetposition          {identifier}
%D \dosetpositionwhd       {identifier} {width} {height} {depth}
%D \dosetpositionplus      {identifier} {width} {height} {depth} {list}
%D \dosetpositionpapersize {width} {height}
%D \stoptypen
%D
%D Either directly, when using \PDFTEX, or by means of a
%D postprocessor, when using \DVI\ output, these end up in the
%D utility file as:
%D
%D \starttypen
%D \pospxy     {identifier} {page} {x} {y}
%D \pospxywhd  {identifier} {page} {x} {y} {w} {h} {d}
%D \pospxylist {identifier} {page} {x} {y} {w} {h} {d} {list}
%D \stoptypen
%D
%D This means that we have to provide both a utility set and
%D reset macro for positions.

\def\POSprefix{POS::}

\def\pxypos    {\pospxy}     % obsolete
\def\pxyposwhd {\pospxywhd}  % obsolete
\def\pxyposplus{\pospxyplus} % obsolete

\def\resetpositions
  {\let\pospxy    \gobblefourarguments
   \let\pospxywhd \gobblesevenarguments
   \let\pospxyplus\gobbleeightarguments}

\def\setpositions
  {\let\pospxy    \setpospxy
   \let\pospxywhd \setpospxywhd
   \let\pospxyplus\setpospxyplus}

% \def\setpospxy#1#2#3#4%
%   {\dosetpositionnm\@@posp{#2}%
%    \dosetpositionpt\@@posx{#3}%
%    \dosetpositionpt\@@posy{#4}%
%   %\setxvalue{\POSprefix#1}{\@@posp,\@@posx,\@@posy}}%
%    \@EA\xdef\csname\POSprefix#1\endcsname{\@@posp,\@@posx,\@@posy}}%
% 
% \def\setpospxywhd#1#2#3#4#5#6#7%
%   {\dosetpositionnm\@@posp{#2}%
%    \dosetpositionpt\@@posx{#3}%
%    \dosetpositionpt\@@posy{#4}%
%    \dosetpositionpt\@@posw{#5}%
%    \dosetpositionpt\@@posh{#6}%
%    \dosetpositionpt\@@posd{#7}%
%   %\setxvalue{\POSprefix#1}{\@@posp,\@@posx,\@@posy,\@@posw,\@@posh,\@@posd}}%
%    \@EA\xdef\csname\POSprefix#1\endcsname{\@@posp,\@@posx,\@@posy,\@@posw,\@@posh,\@@posd}}%
% 
% \def\setpospxyplus#1#2#3#4#5#6#7#8%
%   {\dosetpositionnm\@@posp{#2}%
%    \dosetpositionpt\@@posx{#3}%
%    \dosetpositionpt\@@posy{#4}%
%    \dosetpositionpt\@@posw{#5}%
%    \dosetpositionpt\@@posh{#6}%
%    \dosetpositionpt\@@posd{#7}%
%   %\setxvalue{\POSprefix#1}{\@@posp,\@@posx,\@@posy,\@@posw,\@@posh,\@@posd,#8}}
%    \@EA\xdef\csname\POSprefix#1\endcsname{\@@posp,\@@posx,\@@posy,\@@posw,\@@posh,\@@posd,#8}}

%D This is real tricky! The page anchor is applied to the 
%D page box and therefore flushed first. So, when present, it 
%D is applied to all positions except itself. 

\chardef\positionanchormode=0 % don't relocate page origin 
\chardef\positionanchormode=1 % relocate page origin once 

\def\pageanchor{page:0}

\def\registerpageposition#1% this one is flushed first !
  {\ifpositioning\ifcase\realpageno\or
     \ifdim\printpapierhoogte=\papierhoogte\else
       \ifdim\printpapierbreedte=\papierbreedte\else
         \setbox#1\hbox{\hpos\pageanchor{\box#1}}%
       \fi 
     \fi 
   \fi\fi}

\def\dosetpositionxy#1#2#3% todo: scaled points 
  {\scratchdimen#2\s!sp
   \ifcase\positionanchormode\or
     \advance\scratchdimen-#3\pageanchor
   \fi
   \xdef#1{\@EA\withoutpt\the\scratchdimen}}

\def\setpospxy#1#2#3#4%
  {\dosetpositionnm\@@posp{#2}%
   \dosetpositionxy\@@posx{#3}\MPx
   \dosetpositionxy\@@posy{#4}\MPy
  %\setxvalue{\POSprefix#1}{\@@posp,\@@posx,\@@posy}}%
   \@EA\xdef\csname\POSprefix#1\endcsname{\@@posp,\@@posx,\@@posy}}%

\def\setpospxywhd#1#2#3#4#5#6#7%
  {\dosetpositionnm\@@posp{#2}%
   \dosetpositionxy\@@posx{#3}\MPx
   \dosetpositionxy\@@posy{#4}\MPy
   \dosetpositionpt\@@posw{#5}%
   \dosetpositionpt\@@posh{#6}%
   \dosetpositionpt\@@posd{#7}%
  %\setxvalue{\POSprefix#1}{\@@posp,\@@posx,\@@posy,\@@posw,\@@posh,\@@posd}}%
   \@EA\xdef\csname\POSprefix#1\endcsname{\@@posp,\@@posx,\@@posy,\@@posw,\@@posh,\@@posd}}%

\def\setpospxyplus#1#2#3#4#5#6#7#8%
  {\dosetpositionnm\@@posp{#2}%
   \dosetpositionxy\@@posx{#3}\MPx
   \dosetpositionxy\@@posy{#4}\MPy
   \dosetpositionpt\@@posw{#5}%
   \dosetpositionpt\@@posh{#6}%
   \dosetpositionpt\@@posd{#7}%
  %\setxvalue{\POSprefix#1}{\@@posp,\@@posx,\@@posy,\@@posw,\@@posh,\@@posd,#8}}
   \@EA\xdef\csname\POSprefix#1\endcsname{\@@posp,\@@posx,\@@posy,\@@posw,\@@posh,\@@posd,#8}}

%D We need to initialize.

\resetpositions

%D For postprocessing purposes, we save the number of
%D positions.

\newcounter\currentpositions  % current number of positions
\newcounter\totalnofpositions % total from previous run

\appendtoks
  \savecurrentvalue\totalnofpositions\currentpositions
\to \everybye

%D The next switch can be used to communicate a special
%D situation. Positioning and associated actions can be
%D executed any time. However, in for instance backgrounds
%D they can be collected in a layer, for instance the text
%D layer (especially the hidden text layer). In the case of
%D floats, we run into problems, since the page information is
%D not applicable when the content floats indeed. In such
%D situations one can treat positions and graphics local.

\newif\iflocalpositioning

%D Watch out: sometimes a pagebreak occurs inside a float
%D placement, so there we need to disable local mode.

\appendtoks
  \localpositioningtrue
\to \everyinsidefloat

\appendtoks
  \localpositioningfalse
\to \everypagebody

%D We save positionional information without dimensions, which
%D saves some bytes. The conversion too saves some bytes, but
%D is primarily needed because we want to pass those values to
%D \METAPOST\ too.

\def\dosetpositionpt#1#2%
  {\scratchdimen#2\s!sp
   \xdef#1{\@EA\withoutpt\the\scratchdimen}}

\def\dosetpositionnm#1#2%
  {\xdef#1{\number#2}}

\def\checkpositions
  {\startnointerference
   \protectlabels
   \doutilities{positions}\jobname\empty\relax\relax
   \global\let\checkpositions\relax
   \stopnointerference}

%D Since the positional values are to be fully expandable, we
%D need to preload them as soon as possible, which is why we
%D load the data when we start a text.

\appendtoks \checkpositions \to \everystarttext

%D Positions are either generated at a delayed write time
%D (in \PDFTEX), or derived from the dvi file. The actual
%D method is implemented in a special driver. If needed, the
%D driver can fall back on the following macros.

\def\dolazysaveposition#1#2#3#4% tag page x y
  {\expanded{\writeutilitycommand{\noexpand\pospxy
     {#1}{#2}{#3}{#4}}}}

\def\dolazysavepositionwhd#1#2#3#4#5#6#7% tag page x y w h d
  {\expanded{\writeutilitycommand{\noexpand\pospxywhd
     {#1}{#2}{#3}{#4}{#5}{#6}{#7}}}}

\def\dolazysavepositionplus#1#2#3#4#5#6#7#8% tag page x y w h d list
  {\expanded{\writeutilitycommand{\noexpand\pospxyplus
     {#1}{#2}{#3}{#4}{#5}{#6}{#7}{#8}}}}

\def\dosaveposition#1#2#3#4% tag page x y
  {\expanded{\immediatewriteutilitycommand{\noexpand\pospxy
     {#1}{#2}{#3}{#4}}}}

\def\dosavepositionwhd#1#2#3#4#5#6#7% tag page x y w h d
  {\expanded{\immediatewriteutilitycommand{\noexpand\pospxywhd
     {#1}{#2}{#3}{#4}{#5}{#6}{#7}}}}

\def\dosavepositionplus#1#2#3#4#5#6#7#8% tag page x y w h d list
  {\expanded{\immediatewriteutilitycommand{\noexpand\pospxyplus
     {#1}{#2}{#3}{#4}{#5}{#6}{#7}{#8}}}}

%D \macros
%D   {MPp, MPx, MPy, MPw, MPh, MPd,
%D    MPxy, MPll, MPlr, MPur, MPul, MPpos}
%D
%D Access to the positional information is provided by macros
%D with short names that are clearly meant for \METAPOST.

\def\MPp  {\doMPxyhdwlr\doMPp  }
\def\MPx  {\doMPxyhdwlr\doMPx  }
\def\MPy  {\doMPxyhdwlr\doMPy  }
\def\MPw  {\doMPxyhdwlr\doMPw  }
\def\MPh  {\doMPxyhdwlr\doMPh  }
\def\MPd  {\doMPxyhdwlr\doMPd  }
\def\MPxy {\doMPxyhdwlr\doMPxy }
\def\MPll {\doMPxyhdwlr\doMPll }
\def\MPlr {\doMPxyhdwlr\doMPlr }
\def\MPur {\doMPxyhdwlr\doMPur }
\def\MPul {\doMPxyhdwlr\doMPul }
\def\MPpos{\doMPxyhdwlr\doMPpos}

%D So \type {\MPx{identifier}} returns a position, specified
%D in points. When unknown, \type {0pt} is returned. From the
%D next definitions, we can see that some positions are
%D expressions.

\def\doMPp  #1,#2,#3,#4,#5,#6,#7\relax{#1}
\def\doMPx  #1,#2,#3,#4,#5,#6,#7\relax{#2\s!pt}
\def\doMPy  #1,#2,#3,#4,#5,#6,#7\relax{#3\s!pt}
\def\doMPw  #1,#2,#3,#4,#5,#6,#7\relax{#4\s!pt}
\def\doMPh  #1,#2,#3,#4,#5,#6,#7\relax{#5\s!pt}
\def\doMPd  #1,#2,#3,#4,#5,#6,#7\relax{#6\s!pt}
\def\doMPxy #1,#2,#3,#4,#5,#6,#7\relax{(#2\s!pt,#3\s!pt)}
\def\doMPll #1,#2,#3,#4,#5,#6,#7\relax{(#2\s!pt,#3\s!pt-#6\s!pt)}
\def\doMPlr #1,#2,#3,#4,#5,#6,#7\relax{(#2\s!pt+#4\s!pt,#3\s!pt-#6\s!pt)}
\def\doMPur #1,#2,#3,#4,#5,#6,#7\relax{(#2\s!pt+#4\s!pt,#3\s!pt+#5\s!pt)}
\def\doMPul #1,#2,#3,#4,#5,#6,#7\relax{(#2\s!pt,#3\s!pt+#5\s!pt)}
\def\doMPpos#1,#2,#3,#4,#5,#6,#7\relax{#1,#2\s!pt,#3\s!pt,#4\s!pt,#5\s!pt,#6\s!pt}

%D As said, we will default to zero (dimensions) when a
%D position is unknown.

\def\doMPxyhdwlr#1#2%
  {\ifundefined{\POSprefix#2}%
     #10,0,0,0,0,0,0\relax
   \else
     \@EA\@EA\@EA#1\csname\POSprefix#2\endcsname,0,0,0,0\relax
   \fi}

\beginETEX

\def\doMPxyhdwlr#1#2% evt kan \s!unknown leeg zijn
  {\@EA\@EA\@EA#1\csname\POSprefix
     \ifcsname\POSprefix#2\endcsname#2\else\s!unknown\fi\endcsname
     ,0,0,0,0\relax}

\setvalue{\POSprefix\s!unknown}{0,0,0}

\endETEX

%D \macros
%D  {MPplus, MPrest, MPv, MPvv}
%D
%D Since we will probably keep on extending, we provide a
%D general extension macro. The plus alternative takes an
%D extra argument, denoting what additional parameter to pick
%D up. So, the third extra is fetched with,
%D
%D \starttypen
%D \MPplus{identifier}{3}
%D \stoptypen
%D
%D All extras (comma separated) are fetched with:
%D
%D \starttypen
%D \MPrest{identifier}
%D \stoptypen
%D
%D The extra parameters are not treated.

\def\MPplus  {\MPdoplus\doMPplus}       \let\MPv \MPplus
\def\MPrest#1{\MPdoplus\doMPrest{#1}{}} \let\MPvv\MPrest

\def\MPdoplus#1#2#3#4%
  {\ifundefined{\POSprefix#2}#4\else
     \@EA\@EA\@EA#1\csname\POSprefix#2\endcsname,,,,,,,,,\relax{#3}%
   \fi}

% \beginETEX
%
% \def\MPdoplus#1#2#3#4%
%   {\ifcsname\POSprefix#2\endcsname
%      \@EA\@EA\@EA#1\csname\POSprefix#2\endcsname,,,,,,,,,\relax{#3}%
%    \else
%      #4%
%    \fi}
%
% \endETEX

\def\doMPplus#1,#2,#3,#4,#5,#6,%
  {\dodoMPplus}

\def\dodoMPplus#1,#2,#3,#4,#5,#6,#7,#8\relax#9%
  {\ifcase#9\or#1\or#2\or#3\or#4\or#5\or#6\or#7\else
     \dododoMPplus#8\relax{#9}\fi}

\def\dododoMPplus#1,#2,#3,#4,#5,#6,#7,#8\relax#9%
  {\ifcase#9\or  \or  \or  \or  \or  \or  \or  \or
               #1\or#2\or#3\or#4\or#5\or#6\or#7\fi}

\def\doMPrest#1,#2,#3,#4,#5,#6,#7,,#8\relax#9%
  {#7}

% We can now remap the normal whd onto this.

%D \macros
%D   {MPanchor}
%D
%D For readability we define a few synonyms:

\let\MPanchor\MPpos

%D \macros
%D   {POSp, POSx, POSy, POSh, POSd, POSw}
%D
%D and:

\let\POSp\MPp \let\POSx\MPx \let\POSy\MPy
\let\POSh\MPh \let\POSd\MPd \let\POSw\MPw

\newbox\positionbox \newif\ifpositioning

%D There are two low level positioning macros. Both store the
%D position as well as execute an action associated with that
%D position.

\def\initializenextposition
  {\ifpositioning \else
     \global\positioningtrue
     \dosetpositionpapersize
       {\number\printpapierbreedte}%
       {\number\printpapierhoogte }%
   \fi
   \doglobal\increment\currentpositions}

% \def\setposition#1%
%   {\initializenextposition
%    \dosetposition{#1}%
%    \dopositionaction{#1}}
%
% \def\setpositionbox#1%
%   {\dowithnextbox
%      {\hbox to \nextboxwd
%         {\initializenextposition
%          \def\currentposition{#1}%
%          \dosetpositionwhd \currentposition
%            {\number\nextboxwd}%
%            {\number\nextboxht}%
%            {\number\nextboxdp}%
%          \traceposstring\llap\green{\currentposition>}%
%          \setbox\positionbox\flushnextbox
%          \dopositionaction\currentposition
%          \box\positionbox
%          \hss}}}
%
% \def\setpositionplus#1#2%
%   {\dowithnextbox
%      {\hbox to \nextboxwd
%         {\initializenextposition
%          \def\currentposition{#1}%
%          \dosetpositionplus \currentposition
%            {\number\nextboxwd}%
%            {\number\nextboxht}%
%            {\number\nextboxdp}%
%            {#2}%
%          \traceposstring\rlap\magenta{<\currentposition}%
%          \setbox\positionbox\flushnextbox
%          \dopositionaction\currentposition
%          \box\positionbox
%          \hss}}}

\def\setpositiononly#1%
  {\iftrialtypesetting
      % nothing
   \else
     \initializenextposition
     \def\currentposition{#1}%
     \dosetposition\currentposition
   \fi}

\def\setposition#1%
  {\iftrialtypesetting
      % nothing
   \else
     \initializenextposition
     \def\currentposition{#1}%
     \dosetposition\currentposition
     \traceposstring\llap\green{\currentposition>}%
     \dopositionaction\currentposition
   \fi}

\def\setpositiondata#1#2#3#4%
  {\iftrialtypesetting \else
     \initializenextposition
     \hbox 
       {\def\currentposition{#1}%
        \dosetpositionwhd\currentposition
          {\number#2}%
          {\number#3}%
          {\number#4}%
        \traceposstring\llap\green{\currentposition>}%
        \dopositionaction\currentposition
        \hss}%
   \fi}

\def\setpositionbox#1%
  {\dowithnextbox
     {\iftrialtypesetting
        \flushnextbox
      \else
        \initializenextposition
        \hbox to \nextboxwd
          {\def\currentposition{#1}%
           \dosetpositionwhd\currentposition
             {\number\nextboxwd}%
             {\number\nextboxht}%
             {\number\nextboxdp}%
           \traceposstring\llap\green{\currentposition>}%
           \setbox\positionbox\flushnextbox
           \dopositionaction\currentposition
           \box\positionbox
           \hss}%
      \fi}}

\def\setpositiondataplus#1#2#3#4#5%
  {\iftrialtypesetting \else
     \initializenextposition
     \hbox to \nextboxwd
       {\def\currentposition{#1}%
        \dosetpositionplus\currentposition
          {\number#2}%
          {\number#3}%
          {\number#4}%
          {#5}%
        \traceposstring\rlap\magenta{<\currentposition}%
        \dopositionaction\currentposition
        \hss}%
   \fi}

\def\setpositionplus#1#2%
  {\dowithnextbox
     {\iftrialtypesetting
        \flushnextbox
      \else
        \initializenextposition
        \hbox to \nextboxwd
          {\def\currentposition{#1}%
           \dosetpositionplus\currentposition
             {\number\nextboxwd}%
             {\number\nextboxht}%
             {\number\nextboxdp}%
             {#2}%
           \traceposstring\rlap\magenta{<\currentposition}%
           \setbox\positionbox\flushnextbox
           \dopositionaction\currentposition
           \box\positionbox
           \hss}%
      \fi}}

\let\currentposition\s!unknown

%D A few more low level macros take care of defining and
%D recalling actions. We could save this information in the
%D position containers themselves, this would save hash
%D entries, but at the cost of much more time consuming
%D expansion. Actions are saved globally!

\newtoks\everypositionaction

\let\POSactionprefix\POSprefix

\def\dosetpositionaction#1%
  {\setgvalue{\POSactionprefix#1::}}

%D The lists can become quite long (also because there can
%D be lots of parameters passed on) so we provide a hook
%D to clean up the list afterwards.

\let\cleanuppositionaction\gobbleoneargument

%D The next one will be overloaded later.
%D
%D \starttypen
%D \def\dopositionaction#1% test saves hash entry in etex
%D   {\ifundefined{\POSactionprefix#1::}\else
%D      \ifnum\MPp{#1}>\zerocount % new
%D        \setbox\scratchbox\hbox \bgroup
%D          \traceposstring\clap\red{<#1>}%
%D          \the\everyinsertpositionaction
%D          \the\everypositionaction
%D          \ifcollectMPpositiongraphics
%D            % can save a lot of run time
%D            \pushMPdrawing
%D            \MPshiftdrawingtrue
%D            \resetMPdrawing
%D            \getvalue{\POSactionprefix#1::}%
%D            \ifMPdrawingdone
%D              \getMPdrawing
%D            \fi
%D            \resetMPdrawing
%D            \popMPdrawing
%D          \else
%D            \getvalue{\POSactionprefix#1::}%
%D          \fi
%D          \cleanuppositionaction{#1}%
%D        \egroup
%D        \smashedbox\scratchbox
%D      \else
%D        % shouldn't happen too often
%D        \traceposstring\clap\cyan{<#1>}%
%D      \fi
%D    \fi}
%D \stoptypen 

\def\doifpositionaction#1%
  {\ifundefined{\POSactionprefix#1::}%
     \@EA\gobblefirstargument
   \else
     \@EA\firstofoneargument
   \fi}

\def\doifpositionactionelse#1%
  {\ifundefined{\POSactionprefix#1::}%
     \@EA\secondoftwoarguments
   \else
     \@EA\firstoftwoarguments
   \fi}

%D We can copy a position with:
%D
%D \starttypen
%D \copyposition {to} {from}
%D \stoptypen
%D
%D Again, this is a global action.

\def\copyposition#1#2%
  {\bgroup
   \edef\to  {\POSprefix#1}%
   \edef\from{\POSprefix#2}%
  %\doifdefined\from
  %  {\global\@EA\@EA\@EA\let\@EA\csname\@EA\to\@EA\endcsname\csname\from\endcsname}%
   \ifundefined\from\else
     \global\@EA\@EA\@EA\let\@EA\csname\@EA\to\@EA\endcsname\csname\from\endcsname
   \fi
   \egroup}

%D The fact that handling positions is a two pass operation, is
%D one of the reasons why we need to be able to test for
%D existence, using:
%D
%D \starttypen
%D \doifpositionelse {identifier} {found action} {not found action}
%D \stoptypen

% \def\doifpositionelse#1%
%   {\doifdefinedelse{\POSprefix#1}}

\def\doifpositionelse#1%
  {\ifundefined{\POSprefix#1}%
     \expandafter\secondoftwoarguments
   \else
     \expandafter\firstoftwoarguments
   \fi}

%D We have now arrived at a few macros that would make sense as
%D support macros, but ended up in the core.

%D \macros
%D   {xypos}
%D
%D We have several macros available to save positions. Later
%D we will see applications.
%D
%D \starttabulatie[|l|l||]
%D \NC \type {\xypos} \NC    \NC simple position with no dimensions \NC \NR
%D \NC \type {\hpos}  \NC    \NC position and characteristics of a \type {\hbox}                    \NC \NR
%D \NC \type {\vpos}  \NC    \NC position and characteristics of a \type {\vbox}                    \NC \NR
%D \NC \type {\bpos}  \NC b: \NC begin point in a line \NC \NR
%D \NC \type {\epos}  \NC e: \NC end point in a line \NC \NR
%D \NC \type {\fpos}  \NC f: \NC begin point in a paragraph \NC \NR
%D \NC \type {\tpos}  \NC t: \NC end point in a paragraph \NC \NR
%D \stoptabulatie
%D
%D Each macro takes an identifier as argument, and the \type
%D {\hpos} and \type {\vpos} also expect box content.

% \def\xypos{\initializenextposition\dosetposition}

\let\xypos\setpositiononly

\def\hpos#1{\dontleavehmode\setpositionbox{#1}\hbox}
\def\vpos#1{\setpositionbox{#1}\vbox}

\def\bpos#1{\hpos{b:#1}{\strut}\ignorespaces}
\def\epos#1{\removelastspace\hpos{e:#1}{\strut}}

\def\fpos#1%
  {\setpositionplus{b:#1}\parposcounter\horizontalstrut
   \ignorespaces}

\def\tpos#1%
  {\removelastspace
   \setpositionplus{e:#1}\parposcounter\horizontalstrut}

\def\ffpos#1%
  {\setpositionplus{b:#1}\parposcounter\horizontalstrut\wpos{#1}%
   \ignorespaces}

\def\ttpos#1%
  {\removelastspace
   \setpositionplus{e:#1}\parposcounter\horizontalstrut}

\def\wpos#1%
  {\dontleavehmode\vadjust % may disappear if buried
     {\setbox0\hbox{\raise\strutdp\hbox{\rawwpos{#1}}}%
      \rlap{\smashedbox0}}}

\def\wwpos#1% \hsmashed{\llap{\rawwpos{#1}}}
  {\rlap
     {\setbox0\hbox{\rawwpos{#1}}%
      \smashedbox0}}

\def\rawwpos#1%
  {\hpos{w:#1}
     {\strut
      \hskip-\leftskip
      \hskip\hsize
      \hskip-\rightskip}}

% the next macro disables par positions (in inner boxes) and
% only registers the width

\def\setinnerparpositions
  {\let\fpos\ffpos
   \let\tpos\ttpos
   \let\wpos\wwpos}

% example of usage: (see for application "techniek")
%
% \appendtoks
%   \setinnerparpositions
% \to \everytabulate

%D When we want to calculate more complex backgrounds, we
%D need to know what the current indentation scheme is. At
%D the cost of many positions and memory, we can keep track
%D of them. This mechanism is activated automatically
%D based on information collected in the previous pass.

\newcounter\parposcounter

\newif\ifpositioningpar

\def\efficientdimen#1%
  {\the#1} % \ifdim#1=\zeropoint\string\!!zeropoint\else\the#1\fi}

% we can check for used entries, and if not, then not add one

\def\registerparoptions
  {\ifpositioningpar \ifpositioning \iftrialtypesetting \else
     \ifinpagebody \else \ifmmode \else \ifinformula \else
       \ifprocessingverbatim
         \iflinepar \doregisterparoptions \fi
       \else
         \doregisterparoptions
       \fi
     \fi \fi \fi
   \fi \fi \fi}

\chardef\parposstrut=1 % 0 => no strut data, so fall backs used 

\def\doregisterparoptions
  {\doglobal\increment\parposcounter
   \begingroup
     \leftskip 1\leftskip
     \rightskip1\rightskip
     \setpositiondataplus
       {p:\parposcounter}%         % identifier
       {\zeropoint}%
       {\strutht}%
       {\strutdp}%
       {\efficientdimen\hsize     ,% 1
        \efficientdimen\leftskip  ,% 2
        \efficientdimen\rightskip ,% 3
        \efficientdimen\hangindent,% 4
                   \the\hangafter ,% 5
        \efficientdimen\parindent }% 6
    %\normalhbox{\registerparsymbol}%
     \registerparsymbol
   \endgroup}

\newif\iftracepositions

\def\traceposstring#1#2#3%
  {\iftracepositions\smashedhbox{#1{\infofont#2#3}}\fi}

\def\registerparsymbol
  {\iftracepositions
     \smashedhbox to \zeropoint
       {\hss
        \blue
        \llap{\infofont\number\parposcounter}%
        \scratchdimen\!!onepoint
        \vrule
          \!!width 4\scratchdimen
          \!!height2\scratchdimen
          \!!depth 2\scratchdimen
        \hss}%
   \fi}

\appendtoks \registerparoptions \to \everypar

%D \macros
%D   {doifoverlappingelse}
%D
%D A first application of positional information, is to
%D determine if two boxes do overlap:
%D
%D \starttypen
%D \doifoverlappingelse{point a}{point b}
%D   {action when overlapping}
%D   {action when not overlapping}
%D \stoptypen

% \def\doifoverlappingelse#1#2#3#4%
%   {\relax\ifnum\MPp{#1}=\MPp{#2}\relax
%      \bgroup
%      \donefalse
%      \def\check##1##2%
%        {\ifdone\else
%           \ifdim\dimen1##1<\dimen0 \else \ifdim\dimen1##1>\dimen2 \else
%             \ifdim\dimen1##2<\dimen4 \else \ifdim\dimen1##2>\dimen6 \else
%               \donetrue
%             \fi\fi
%           \fi\fi
%         \fi}%
%      \dimen 0=\MPx{#1}%
%      \dimen 2=\MPx{#1}\advance\dimen 2  \MPw{#1}%
%      \dimen 4=\MPy{#1}\advance\dimen 4 -\MPd{#1}%
%      \dimen 6=\MPy{#1}\advance\dimen 6  \MPh{#1}%
%      \dimen10=\MPx{#2}%
%      \dimen12=\MPx{#2}\advance\dimen12  \MPw{#2}%
%      \dimen14=\MPy{#2}\advance\dimen14 -\MPd{#2}%
%      \dimen16=\MPy{#2}\advance\dimen16  \MPh{#2}%
%     %\message{\the\dimen 0-\the\dimen 2,\the\dimen 4-\the\dimen 6}\wait
%     %\message{\the\dimen10-\the\dimen12,\the\dimen14-\the\dimen16}\wait
%      \check04\check24\check26\check06\ifdone\egroup#3\else\egroup#4\fi
%    \else
%      #4%
%    \fi}

\newdimen\overlappingmargin \overlappingmargin\zeropoint

\def\doifoverlappingelse#1#2%
  {\begingroup
   \donefalse
   \edef\!!stringa{#1}\edef\!!stringb{#2}%
   \ifnum\MPp\!!stringa=\MPp\!!stringb\relax
     \def\check##1##2%
       {\ifdim##1<\!!dimena \else \ifdim##1>\!!dimenb \else
          \ifdim##2<\!!dimenc \else \ifdim##2>\!!dimend \else
            \donetrue
          \fi\fi
        \fi\fi}%
     \!!dimena\MPx\!!stringa
     \!!dimenb\MPx\!!stringa\advance\!!dimenb \MPw\!!stringa
     \!!dimenc\MPy\!!stringa\advance\!!dimenc-\MPd\!!stringa
     \!!dimend\MPy\!!stringa\advance\!!dimend \MPh\!!stringa
     \!!dimene\MPx\!!stringb
     \!!dimenf\MPx\!!stringb\advance\!!dimenf \MPw\!!stringb
     \!!dimeng\MPy\!!stringb\advance\!!dimeng-\MPd\!!stringb
     \!!dimenh\MPy\!!stringb\advance\!!dimenh \MPh\!!stringb
     \ifdim\overlappingmargin=\zeropoint\else
       \advance\!!dimena-\overlappingmargin
       \advance\!!dimenb+\overlappingmargin
       \advance\!!dimenc-\overlappingmargin
       \advance\!!dimend+\overlappingmargin
       \advance\!!dimene-\overlappingmargin
       \advance\!!dimenf+\overlappingmargin
       \advance\!!dimeng-\overlappingmargin
       \advance\!!dimenh+\overlappingmargin
     \fi 
     \check\!!dimene\!!dimeng \ifdone \else
     \check\!!dimene\!!dimenh \ifdone \else
     \check\!!dimenf\!!dimeng \ifdone \else
     \check\!!dimenf\!!dimenh \fi \fi \fi
   \fi
   \ifdone
     \endgroup\expandafter\firstoftwoarguments
   \else
     \endgroup\expandafter\secondoftwoarguments
   \fi}

%D \macros
%D   {doifpositionsonsamepageelse,
%D    doifpositionsonthispageelse}
%D
%D Instead of letting the user handle fuzzy expansion, we
%D provide a simple test on positione being on the same page.
%D
%D \starttypen
%D \doifpositionsonsamepageelse{point a}{point b}
%D   {action when on same page}
%D   {action when not on same page}
%D \doifpositionsonthispageelse{point a}{point b}
%D   {action when on this page}
%D   {action when not on this page}
%D \stoptypen

\def\dodoifpositionsonsamepageelse#1#2#3#4%
  {\bgroup
   \scratchcounter#1\donefalse
   \def\docommando##1%
     {\ifcase\scratchcounter
        \scratchcounter\MPp{##1}\donetrue
      \else
        \ifnum\scratchcounter=\MPp{##1}\relax\else\donefalse\fi
      \fi}%
   \rawprocesscommalist[#2]\docommando
   \ifdone\egroup#3\else\egroup#4\fi}

\def\doifpositionsonsamepageelse%
  {\dodoifpositionsonsamepageelse{0}}

\def\doifpositionsonthispageelse#1#2#3%
  {\dodoifpositionsonsamepageelse\realfolio}

%D Before we come to graphics support, we have to make sure of
%D the reference point on the page. The next macro does so and
%D is hooked into the page building routine.

% in the future, the depth of tail will reflect page depth

\def\textanchor{text:\realfolio}

\def\placepositionanchors % todo : depth pagebox
  {\ifpositioning
     \setbox\scratchbox\vbox to \teksthoogte
       {\topskipcorrection
        \hbox{\strut\dopositionaction\headanchor}%
        \vfill
        \hbox{\strut\dopositionaction\tailanchor}}%
     \dp\scratchbox\zeropoint
     \wd\scratchbox\zetbreedte % not \zeropoint, else wrong text backgrounds
     \hpos\textanchor{\box\scratchbox}%
   \else
     \vskip\teksthoogte
   \fi}

%D The first version of this module implemented head and tail
%D anchors. Currently we stick to just one anchor and derive
%D the head and tail anchors from this one.

\def\headanchor{head:\realfolio} % virtual position
\def\tailanchor{tail:\realfolio} % virtual position

\def\presetpositionanchors% compatibility hack (still needed?)
  {\ifpositioning
     \dopresetpositionanchors
   \fi}

% \def\dopresetpositionanchors
%   {\bgroup
%    \dimen0=\ifdim\topskip>\strutht\topskip\else\strutht\fi
%    \dimen2=\MPy\textanchor
%    \dimen4=\dimen2
%    \advance\dimen2 \MPh\textanchor % space is essential
%    \advance\dimen2 -\dimen0
%    \advance\dimen4 \strutdp
%    \dimen6=\MPx\textanchor
%    \dimen8=\MPw\textanchor
%    \setxvalue{\POSprefix\headanchor}%
%      {\realfolio,\withoutpt{\the\dimen6},\withoutpt{\the\dimen2},%
%       \withoutpt{\the\dimen8},\withoutpt{\the\dimen0},\withoutpt{\the\strutdp}}%
%    \setxvalue{\POSprefix\tailanchor}%
%      {\realfolio,\withoutpt{\the\dimen6},\withoutpt{\the\dimen4},%
%       \withoutpt{\the\dimen8},\withoutpt{\the\strutht},\withoutpt{\the\strutdp}}%
%   %\showanchor\textanchor\showanchor\headanchor\showanchor\tailanchor\wait
%    \egroup}

\def\dopresetpositionanchors
  {\bgroup
   \!!dimena\ifdim\topskip>\strutht\topskip\else\strutht\fi
   \!!dimenb\MPy\textanchor
   \!!dimenc\!!dimenb
   \advance\!!dimenb \MPh\textanchor % space is essential
   \advance\!!dimenb -\!!dimena
   \advance\!!dimenc \strutdp
   \!!dimend\MPx\textanchor
   \!!dimene\MPw\textanchor
   \setxvalue{\POSprefix\headanchor}%
     {\realfolio,\withoutpt{\the\!!dimend},\withoutpt{\the\!!dimenb},%
      \withoutpt{\the\!!dimene},\withoutpt{\the\!!dimena},\withoutpt{\the\strutdp}}%
   \setxvalue{\POSprefix\tailanchor}%
     {\realfolio,\withoutpt{\the\!!dimend},\withoutpt{\the\!!dimenc},%
      \withoutpt{\the\!!dimene},\withoutpt{\the\strutht},\withoutpt{\the\strutdp}}%
  %\showanchor\textanchor\showanchor\headanchor\showanchor\tailanchor\wait
   \egroup}

\def\showanchor#1%
  {\expanded{\writestatus{#1}
     {\MPp{#1}\string|\MPx{#1}\string|\MPy{#1}\string|%
      \MPw{#1}\string|\MPh{#1}\string|\MPd{#1}}}}

%D We set these anchors before and after each page.

\appendtoks \presetpositionanchors \to \beforeeverypage
\appendtoks \presetpositionanchors \to \aftereverypage

%D \macros
%D   {positionoverlay,startpositionoverlay}
%D
%D As long as we're dealing with graphics it makes much sense
%D to use the available overlay mechanism. For this purpose, we
%D define some dedicated overlay extensions.
%D
%D \startbuffer[sample]
%D \defineoverlay [sample] [\positionoverlay{sample}]
%D
%D \startpositionoverlay{sample}
%D   \setMPpositiongraphic{A-1}{connectcenter}{from=A-1,to=A-2}
%D \stoppositionoverlay
%D \stopbuffer
%D
%D \typebuffer[sample]
%D
%D \startbuffer[graphic]
%D \startMPpositiongraphic{connectcenter}
%D   path pa, pb ; pair ca, cb ;
%D   initialize_box(\MPpos{\MPvar{from}}) ; pa := pxy ; ca := cxy ;
%D   initialize_box(\MPpos{\MPvar{to}}) ; pb := pxy ; cb := cxy ;
%D   draw pa withcolor red ;
%D   draw pb withcolor red ;
%D   draw ca -- cb withcolor blue ;
%D   anchor_box(\MPanchor{\MPvar{from}}) ;
%D \stopMPpositiongraphic
%D \stopbuffer
%D
%D We can best demonstrate this in an example, say:
%D
%D \startbuffer[text]
%D \omlijnd
%D   [achtergrond=sample,uitlijnen=midden,breedte=7cm]
%D   {We want to connect \hpos {A-1} {this} word with its
%D    grammatical cousin \hpos {A-2} {that}.}
%D \stopbuffer
%D
%D \typebuffer[text]
%D
%D \startregelcorrectie
%D %\haalbuffer[graphic,sample,text]
%D \stopregelcorrectie
%D
%D The graphic is defined in the following way, using some
%D macros defined in an auxiliary \METAPOST\ module that is
%D preloaded.
%D
%D \typebuffer[graphic]

\def\MPanchoridentifier{mpa} % {mp-anchor}
\def\MPoverlayposprefix{MO::}

% obsolete and wrong anyway 
%
% \long\def\defineMPpositiongraphic#1%
%   {\long\setvalue{\MPoverlayposprefix#1}}

%D The rest of the definitions concerning such overlays may
%D look complicated,

\let\currentpositionoverlay\empty

%D Position actions are automatically executed when a position
%D is set.

% \def\positionoverlay#1%
%   {\ifpositioning
%      \vbox to \overlayheight
%        {\edef\MPanchor##1{\MPpos{#1::\MPanchoridentifier:\realfolio}}%
%         \the\everyinsertpositionaction
%         \copyposition{#1::\MPanchoridentifier}{#1::\MPanchoridentifier:\realfolio}%
%         \hpos
%           {#1::\MPanchoridentifier:\realfolio}
%           {\hbox to \overlaywidth{\dopositionaction{#1::\MPanchoridentifier}\hss}}%
%         \vfill}%
%    \fi}

\let\MPanchornumber\realfolio

% \def\positionoverlay#1%
%   {\ifpositioning
%      \vbox to \overlayheight
%        {\edef\MPanchorid{#1::\MPanchoridentifier:\MPanchornumber}%
%         \edef\MPanchor##1{\MPpos{\MPanchorid}}%
%         \the\everyinsertpositionaction
%         \copyposition{#1::\MPanchoridentifier}{#1::\MPanchoridentifier:\MPanchornumber}%
%         \hpos
%           {#1::\MPanchoridentifier:\MPanchornumber}
%           {\hbox to \overlaywidth{\dopositionaction{#1::\MPanchoridentifier}\hss}}%
%         \vfill}%
%    \fi}

% \def\positionoverlay#1% the test prevents too many redundant positions 
%   {\ifpositioning     % in (not used) text* position layers 
%      \vbox to \overlayheight
%        {\doifpositionactionelse{#1::\MPanchoridentifier}%
%           {\edef\MPanchorid{#1::\MPanchoridentifier:\MPanchornumber}%
%            \edef\MPanchor##1{\MPpos{\MPanchorid}}%
%            \the\everyinsertpositionaction
%            \copyposition{#1::\MPanchoridentifier}{#1::\MPanchoridentifier:\MPanchornumber}%
%            \hpos
%              {#1::\MPanchoridentifier:\MPanchornumber}%
%              {\hbox to \overlaywidth{\dopositionaction{#1::\MPanchoridentifier}\hss}}}%
%           {\hbox to \overlaywidth{\hss}}%
%         \vfill}%
%    \fi}

\def\positionoverlay#1% the test prevents too many redundant positions
  {\ifpositioning     % in (not used) text* position layers
     \vbox to \overlayheight
       {\doifpositionactionelse{#1::\MPanchoridentifier}%
          {\edef\MPanchorid{#1::\MPanchoridentifier:\MPanchornumber}%
           \edef\MPanchor##1{\MPpos{\MPanchorid}}%
           \the\everyinsertpositionaction
           \copyposition{#1::\MPanchoridentifier}{#1::\MPanchoridentifier:\MPanchornumber}%
           \hpos
             {#1::\MPanchoridentifier:\MPanchornumber}%
            % this is ok
            %{\hbox to \overlaywidth{\dopositionaction{#1::\MPanchoridentifier}\hss}}}%
            % but this one prevents cyclic runs due to
            % rounding errors
             {\setbox\scratchbox\hbox to \overlaywidth
                {\dopositionaction{#1::\MPanchoridentifier}\hss}%
              \ht\scratchbox\overlayheight
              \dp\scratchbox\zeropoint
              \box\scratchbox}}%
          {\hbox to \overlaywidth{\hss}}%
        \vfill}%
   \fi}

\def\startpositionoverlay#1%
  {\iftrialtypesetting % we don't want redundant entries in the list
     \@EA\gobbleuntil\@EA\stoppositionoverlay
   \else
     \def\currentpositionoverlay{#1}%
   \fi}

\def\stoppositionoverlay
  {\let\currentpositionoverlay\empty}

\def\resetpositionoverlay#1%
  {\dosetpositionaction{#1::\MPanchoridentifier::}{}}

%D Here the complication has to do with collecting actions
%D for later execution. This collection is especially handy
%D when we want to move actions to a specific layer.
%D Such series of actions are stored in a macro (the one
%D with the funny \type {++}) which is cleaned up after each
%D invocation.

\newtoks\everycleanpositionaction
\newtoks\everyinsertpositionaction

%\def\cleanuppositionaction#1%
%  {\doifdefined{\POSactionprefix#1++}
%     {\the\everycleanpositionaction
%      \setxvalue{\POSactionprefix#1++}{\getvalue{\POSactionprefix#1++}}}}

%\def\cleanuppositionaction#1%
%  {\ifundefined{\POSactionprefix#1++}\else
%     \the\everycleanpositionaction
%     \setxvalue{\POSactionprefix#1++}{\getvalue{\POSactionprefix#1++}}%
%   \fi}

\def\cleanuppositionaction#1% not in trialtypesetting
  {\ifundefined{\POSactionprefix#1++}\else
     \the\everycleanpositionaction
     \iflocalpositioning
       \letgvalue{\POSactionprefix#1++}\empty
     \else
       \setxvalue{\POSactionprefix#1++}{\getvalue{\POSactionprefix#1++}}%
     \fi
   \fi}

\def\handlepositionaction#1\with#2\on#3%
  {\bgroup
   \ifx\currentpositionoverlay\empty
     \edef\!!stringa{#3}% no layer, just pos itself as anchor 
   \else
     \edef\!!stringa{\currentpositionoverlay::\MPanchoridentifier}%
   \fi
   \edef\!!stringc{\POSactionprefix\!!stringa++}%
   \expanded{\dosetpositionaction{\!!stringa}{\noexpand\getvalue{\!!stringc}}}%
   \global\let#1\relax
   \edef\!!stringb{\executeifdefined\!!stringc\empty}%
   \setxvalue\!!stringc{\!!stringb#1#2}%
   \egroup}

%D The indirectness enables us redefine macros for special
%D purposes, like a cleanup.

\def\handlepositionboxes#1#2#3%
  {\handlepositionaction\dohandlepositionboxes\with{#1}{#2}{#3}\on{#2}}

\def\doinsertpositionboxes#1#2#3% pos tag setups
  {\ifnum\MPp{#1}=\realpageno\relax
     % \doifdefined{\MPoverlayposprefix#1}
     %   {\getvalue{\MPoverlayposprefix#1}{#1}{#2}{#3}}%
     \executeifdefined{\MPoverlayposprefix#1}%
       \gobblethreearguments{#1}{#2}{#3}%
   \fi}

\appendtoks
  \let\dohandlepositionboxes\doinsertpositionboxes % was handle ?
\to \everyinsertpositionaction

\def\docleanpositionboxes#1#2#3% pos tag setups
  {\ifnum\MPp{#1}<\realpageno \else
     \noexpand \dohandlepositionboxes{#1}{#2}{#3}% reinsert 
   \fi}

\appendtoks
  \let\dohandlepositionboxes\docleanpositionboxes
\to \everycleanpositionaction

%D A position graphic is a normal (non||reused) \METAPOST\
%D graphic, used immediately, with zero dimensions, so that a
%D sequence of them does not harm.

\newbox\positiongraphicbox

\def\startMPpositiongraphic % id setups
  {\dodoublegroupempty\dostartMPpositiongraphic}

\long\def\dostartMPpositiongraphic#1#2#3\stopMPpositiongraphic
  {\long\setgvalue{MPG:#1}% tag list mpcode
     {\useMPpositiongraphic{#1}{#2}{#3}}}

%\def\prepareMPpositionvariables
%  {\doifundefined{\@@meta self}{\setvalue{\@@meta self}{\currentposition}}%
%   \doifundefined{\@@meta from}{\setvalue{\@@meta from}{\currentposition}}}

\def\prepareMPpositionvariables
  {\ifundefined{\@@meta self}\setvalue{\@@meta self}{\currentposition}\fi
   \ifundefined{\@@meta from}\setvalue{\@@meta from}{\currentposition}\fi}

% \long\def\useMPpositiongraphic#1#2#3%
%   {\bgroup
%    \prepareMPvariables{#2}%
%    \prepareMPpositionvariables
%    \enableincludeMPgraphics
%    \startMPgraphic#3\stopMPgraphic
%    \loadMPgraphic{\MPgraphicfile.\the\currentMPgraphic}{}%
%    \deallocateMPslot\currentMPgraphic
%    \placeMPgraphic
%    \egroup}

\newif\ifcollectMPpositiongraphics \collectMPpositiongraphicstrue

\long\def\useMPpositiongraphic#1#2#3%
  {\bgroup
   \prepareMPvariables{#2}%
   \prepareMPpositionvariables
   \enableincludeMPgraphics
   \ifcollectMPpositiongraphics
     \expanded{\startMPdrawing#3\noexpand\stopMPdrawing}%
     \global\MPdrawingdonetrue
   \else
     \startMPgraphic#3\stopMPgraphic
     \loadMPgraphic{\MPgraphicfile.\the\currentMPgraphic}{}%
     \deallocateMPslot\currentMPgraphic
     \placeMPgraphic
   \fi
   \egroup}

% Now we need a adapted action handler:

% \def\dopositionaction#1% test saves hash entry in etex
%   {\ifundefined{\POSactionprefix#1::}\else
%      \ifnum\MPp{#1}>\zerocount % new
%        \bgroup
%        \traceposstring\clap\red{<#1>}%
%        \the\everyinsertpositionaction
%        \the\everypositionaction
%        \ifcollectMPpositiongraphics
%          % can save a lot of run time
%          \pushMPdrawing
%          \MPshiftdrawingtrue
%          \resetMPdrawing
%          \getvalue{\POSactionprefix#1::}%
%          \ifMPdrawingdone
%            \getMPdrawing
%          \fi
%          \resetMPdrawing
%          \popMPdrawing
%        \else
%          \getvalue{\POSactionprefix#1::}%
%        \fi
%        \cleanuppositionaction{#1}%
%        \egroup
%      \else
%        % shouldn't happen too often
%        \traceposstring\clap\cyan{<#1>}%
%      \fi
%    \fi}

\def\dopositionaction#1% test saves hash entry in etex
  {\ifundefined{\POSactionprefix#1::}\else
     \ifnum\MPp{#1}>\zerocount % new
       \bgroup
       \setbox\scratchbox\hbox
       \bgroup
       \traceposstring\clap\red{<#1>}%
       \the\everyinsertpositionaction
       \the\everypositionaction
       \ifcollectMPpositiongraphics
         % can save a lot of run time
         \pushMPdrawing
         \MPshiftdrawingtrue
         \resetMPdrawing
         \getvalue{\POSactionprefix#1::}%
         \ifMPdrawingdone
           \getMPdrawing
         \fi
         \resetMPdrawing
         \popMPdrawing
       \else
         \getvalue{\POSactionprefix#1::}%
       \fi
       \cleanuppositionaction{#1}%
       \egroup                % smashed is really needed else
       \smashedbox\scratchbox % we get problems with too big
       \egroup                % overlays (s-pre-0x.tex) 
     \else
       % shouldn't happen too often
       \traceposstring\clap\cyan{<#1>}%
     \fi
   \fi}

\def\MPpositiongraphic
  {\dodoublegroupempty\doMPpositiongraphic}

% \def\doMPpositiongraphic#1#2% tag setups
%   {\bgroup
%    \def\@@meta{#1:}%
%    \setupMPvariables[#2]%
%    \prepareMPpositionvariables
%    \MPshiftdrawingtrue
%    \def\doMPpositiongraphic##1##2{\getvalue{MPG:##1}}% temp hack
%    \setbox\positiongraphicbox\hbox
%      {\ignorespaces
%       \executeifdefined{MPM:#1}{\executeifdefined{MPG:#1}\donothing}%
%       \removelastspace}%
%    \smashbox\positiongraphicbox
%    \box\positiongraphicbox
%    \egroup}

\def\doMPpositiongraphic#1#2% tag setups
  {\bgroup
   \def\@@meta{#1:}%
   \setupMPvariables[#2]%
   \prepareMPpositionvariables
   \MPshiftdrawingtrue
   \def\doMPpositiongraphic##1##2%
     {{% new, see (techniek)
       \def\@@meta{##1:}%
       \setupMPvariables[#2,##2]%
       \prepareMPpositionvariables
       % and needed
       \getvalue{MPG:##1}}}% temp hack
   \setbox\positiongraphicbox\hbox
     {\ignorespaces
      \executeifdefined{MPM:#1}{\executeifdefined{MPG:#1}\donothing}%
      \removelastspace}%
   \smashbox\positiongraphicbox
   \box\positiongraphicbox
   \egroup}

\long\def\startMPpositionmethod#1#2\stopMPpositionmethod
  {\long\setgvalue{MPM:#1}{#2}} % todo: var list here

%D Simple one position graphics.

\def\setMPpositiongraphic
  {\dotriplegroupempty\dosetMPpositiongraphic}

\def\dosetMPpositiongraphic#1#2#3% pos tag vars
  {\ifx\currentpositionoverlay\empty
     \dosetpositionaction{#1}{\MPpositiongraphic{#2}{#3}}%
   \else % silly can be one
     \handlepositiongraphics{#1}{#2}{#3}%
   \fi}

\def\handlepositiongraphics#1#2#3% combine with boxes
  {\handlepositionaction\dohandleMPpositiongraphic\with{#1}{#2}{#3}\on{#2}}

\def\doinsertMPpositiongraphic#1#2#3% pos tag setups
  {\ifnum\MPp{#1}=\realpageno\relax % extra saveguard
     \def\currentposition{#1}\MPpositiongraphic{#2}{#3}%
   \fi}

\appendtoks
  \let\dohandleMPpositiongraphic\doinsertMPpositiongraphic
\to \everyinsertpositionaction

\def\docleanMPpositiongraphic#1#2#3% pos tag setups
  {\ifnum\MPp{#1}<\realpageno \else
     \noexpand \dohandleMPpositiongraphic{#1}{#2}{#3}%
   \fi}

\appendtoks
  \let\dohandleMPpositiongraphic\docleanMPpositiongraphic
\to \everycleanpositionaction

%D Graphics that span two positions.

\def\setMPpositiongraphicrange
  {\doquadruplegroupempty\dosetMPpositiongraphicrange}

\def\dosetMPpositiongraphicrange#1#2#3#4% bpos epos tag vars
  {\ifx\currentpositionoverlay\empty
     \dosetpositionaction{#1}{\MPpositiongraphic{#3}{#4}}%
   \else
     \handlepositiongraphicsrange{#1}{#2}{#3}{#4}%
   \fi}

\def\handlepositiongraphicsrange#1#2#3#4%
  {\handlepositionaction\dohandleMPpositiongraphicrange\with{#1}{#2}{#3}{#4}\on{#2}}

% \def\doinsertMPpositiongraphicrange#1#2#3#4% pos pos tag setups
%   {\donefalse
%         \ifnum\MPp{#1}=\realpageno\relax                          \donetrue
%    \else\ifnum\MPp{#2}=\realpageno\relax                          \donetrue
%    \else\ifnum\MPp{#1}<\realpageno\relax\ifnum\MPp{#2}>\realpageno\donetrue
%    \fi\fi\fi\fi \ifdone
%      \def\currentposition{#1}\MPpositiongraphic{#3}{#4}%
%    \fi}

\def\doinsertMPpositiongraphicrange#1#2#3#4% pos pos tag setups
  {\ifnum\MPp{#1}\MPp{#2}>\zerocount
     \iflocalpositioning
       \donetrue
     \else
       \donefalse
       \ifnum\MPp{#1}=\realpageno
         \donetrue
       \else\ifnum\MPp{#2}=\realpageno
         \donetrue
       \else\ifnum\MPp{#1}<\realpageno\relax\ifnum\MPp{#2}>\realpageno
         \donetrue
       \fi\fi\fi\fi
     \fi
     \ifdone
       \def\currentposition{#1}\MPpositiongraphic{#3}{#4}%
     \fi
   \fi}

\appendtoks
  \let\dohandleMPpositiongraphicrange\doinsertMPpositiongraphicrange
\to \everyinsertpositionaction

\def\docleanMPpositiongraphicrange#1#2#3#4% pos tag setups
  {\ifnum\MPp{#2}<\realpageno \else
     \noexpand \dohandleMPpositiongraphicrange{#1}{#2}{#3}{#4}%
   \fi}

\appendtoks
  \let\dohandleMPpositiongraphicrange\docleanMPpositiongraphicrange
\to \everycleanpositionaction

% will be overloaded, and/or code below moved to core-box

\defineoverlay[\v!tekst-2][\positionoverlay{\v!tekst-2}]
\defineoverlay[\v!tekst-1][\positionoverlay{\v!tekst-1}]
\defineoverlay[\v!tekst+1][\positionoverlay{\v!tekst+1}]
\defineoverlay[\v!tekst+2][\positionoverlay{\v!tekst+2}]

%D The auxiliary \METAPOST\ macros are defined by default,
%D by saying:

\appendtoks
  if unknown context_core : input mp-core.mp ; fi ;
\to \MPinitializations

%D Some of these macros are pretty clever but too complicated
%D to be nice. When things are kind of stable I'll clean up
%D this mess.

%D THIS NEEDS A CLEANUP

\setupMPvariables
  [mpos:box]
  [linecolor=blue,
   linewidth=\linewidth,
   fillcolor=lightgray,
   filloffset=\!!zeropoint]

\startMPpositiongraphic{mpos:box}{fillcolor,linecolor,linewidth}
  initialize_box(\MPpos{\MPvar{self}}) ;
  boxfillcolor  := \MPvar{fillcolor} ;
  boxlinecolor  := \MPvar{linecolor} ;
  boxlinewidth  := \MPvar{linewidth} ;
  boxfilloffset := \MPvar{filloffset} ;
  draw_box ;
  anchor_box(\MPanchor{\MPvar{self}}) ;
\stopMPpositiongraphic

\setupMPvariables
  [mpos:area]
  [linecolor=blue,
   linewidth=\linewidth,
   fillcolor=lightgray,
   filloffset=\!!zeropoint]

\startMPpositiongraphic{mpos:area}{fillcolor,linecolor,linewidth}
  initialize_area(\MPpos{b:\MPvar{self}},\MPpos{e:\MPvar{self}}) ;
  boxfillcolor  := \MPvar{fillcolor} ;
  boxlinecolor  := \MPvar{linecolor} ;
  boxlinewidth  := \MPvar{linewidth} ;
  boxfilloffset := \MPvar{filloffset} ;
  draw_area ;
  anchor_area(\MPanchor{b:\MPvar{self}}) ;
\stopMPpositiongraphic

%D This is already cleaned up.

% gridtype = 1 => baseline
% gridtype = 2 => betweenline

\setupMPvariables
  [mpos:par]
  [mp=mpos:par:shape,
   gridtype=0,
   linetype=1,
   filltype=1,
  %snaptops=true, % not that nice: true/false
   gridcolor=red,
   linecolor=blue,
   fillcolor=lightgray,
   filloffset=\!!zeropoint,
   linewidth=\linewidth,
   gridwidth=\linewidth,
   lineradius=.5\bodyfontsize]

\startuseMPgraphic{mpos:par:shape}
  \iftracepositions show_par \else draw_par \fi ;
\stopuseMPgraphic

\startuseMPgraphic{mpos:par:setup}
   boxgridtype   := \MPvar{gridtype} ;
   boxlinetype   := \MPvar{linetype} ;
   boxfilltype   := \MPvar{filltype} ;
   boxgridcolor  := \MPvar{gridcolor} ;
   boxlinecolor  := \MPvar{linecolor} ;
   boxfillcolor  := \MPvar{fillcolor} ;
   boxfilloffset := \MPvar{filloffset} ;
   boxlinewidth  := \MPvar{linewidth} ;
   boxgridwidth  := \MPvar{gridwidth} ;
   boxlineradius := \MPvar{lineradius} ;
  %snap_multi_par_tops := \MPvar{snaptops} ;
\stopuseMPgraphic

\startuseMPgraphic{mpos:par:extra}
  % user stuff, like:
  % snap_multi_par_tops := false ;
\stopuseMPgraphic

% \startMPpositionmethod{mpos:par}
%   \doifpositionelse{w:\MPvar{self}}
%     {\startMPpositiongraphic{mpos:par}%
%          {fillcolor,filloffset,linecolor,gridcolor,linewidth,gridwidth,lineradius}
%        initialize_area_par(\MPpos{b:\MPvar{self}},
%                            \MPpos{e:\MPvar{self}},
%                            \MPpos{w:\MPvar{self}}) ;
%        \includeMPgraphic{mpos:par:setup} ;
%        \includeMPgraphic{mpos:par:extra} ;
%        \includeMPgraphic{\MPvar{mp}} ; % \includeMPgraphic{mpos:par:shape} ;
%        anchor_par(\MPanchor{b:\MPvar{self}}) ;
%      \stopMPpositiongraphic}
%     {\startMPpositiongraphic{mpos:par}%
%          {fillcolor,filloffset,linecolor,gridcolor,linewidth,gridwidth,lineradius}
%        initialize_par(\MPpos{b:\MPvar{self}},
%                       \MPpos{e:\MPvar{self}},
%                       \MPpos{text:\realfolio},
%                       \MPpos{p:\MPparcounter},
%                       \MPvv {p:\MPparcounter}{0,0,0,0,0,0}) ;
%        \includeMPgraphic{mpos:par:setup} ;
%        \includeMPgraphic{mpos:par:extra} ;
%        \includeMPgraphic{\MPvar{mp}} ; % \includeMPgraphic{mpos:par:shape} ;
%        anchor_par(\MPanchor{b:\MPvar{self}}) ;
%      \stopMPpositiongraphic}%
%   \MPpositiongraphic{mpos:par}{}%
% \stopMPpositionmethod

%D Less readable but shorter.

\ifx\MPparcounter\undefined \newcounter\MPparcounter \fi

\def\MPself     {\MPvar{self}}
\def\MPbself    {b:\MPself}
\def\MPeself    {e:\MPself}
\def\MPwself    {w:\MPself}
\def\MPparanchor{p:\MPparcounter}

\def\MPl#1{\MPplus{#1}20}
\def\MPr#1{\MPplus{#1}30}

\startMPpositionmethod{mpos:par} %%%%%%%%%%% will become obsolete 
  \edef\MPparcounter{\MPv\MPbself{1}{0}}%
  \doifpositionelse\MPwself
    {\startMPpositiongraphic{mpos:par}%
         {fillcolor,filloffset,linecolor,gridcolor,linewidth,gridwidth,lineradius}
       initialize_area_par(\MPpos\MPbself,
                           \MPpos\MPeself,
                           \MPpos\MPwself) ;
       \includeMPgraphic{mpos:par:setup} ;
       \includeMPgraphic{mpos:par:extra} ;
       \includeMPgraphic{\MPvar{mp}} ;
       anchor_par(\MPanchor\MPbself) ;
     \stopMPpositiongraphic}
    {\startMPpositiongraphic{mpos:par}%
         {fillcolor,filloffset,linecolor,gridcolor,linewidth,gridwidth,lineradius}
       initialize_par(\MPpos\MPbself,
                      \MPpos\MPeself,
                      \MPpos\textanchor,
                      \MPpos\MPparanchor,
                      \MPvv \MPparanchor{0,0,0,0,0,0}) ;
       \includeMPgraphic{mpos:par:setup} ;
       \includeMPgraphic{mpos:par:extra} ;
       \includeMPgraphic{\MPvar{mp}} ;
       anchor_par(\MPanchor\MPbself) ;
     \stopMPpositiongraphic}%
  \MPpositiongraphic{mpos:par}{}%
\stopMPpositionmethod

%D The next alternative works in columnsets :

\startuseMPgraphic{mpos:par:columnset}
  \iftracepositions show_multi_pars \else draw_multi_pars \fi ;
\stopuseMPgraphic

\startMPpositionmethod{mpos:par:columnset}
  \edef\MPparcounter{\MPv\MPbself{1}{0}}%
  \startMPpositiongraphic{mpos:par}%
    {fillcolor,filloffset,linecolor,gridcolor,%
     linewidth,gridwidth,lineradius}
    \includeMPgraphic{mpos:par:setup} ;
    \includeMPgraphic{mpos:par:extra} ;
    prepare_multi_pars(\MPpos\MPbself,\MPpos\MPeself,\MPpos\MPwself,
      \MPpos\MPparanchor,\MPvv\MPparanchor{0,0,0,0,0,0}) ;
    relocate_multipars(-\MPxy\MPanchorid) ; % inside layerpos
    \includeMPgraphic{\MPvar{mp}} ;
  \stopMPpositiongraphic
  \MPpositiongraphic{mpos:par}{}%
\stopMPpositionmethod

%D \starttypen
%D \setupbackground
%D   [test]
%D   [mp=mpos:par:columnset,
%D    methode=mpos:par:columnset]
%D \stoptypen

%D We need to treat floats in a special way.

\appendtoks
  local_multi_par_area:=\iflocalpositioning true\else false\fi;
\to \MPinitializations

\def\textbackgroundoverlay#1%
  {\iflocalpositioning\v!lokaal\else\v!tekst\fi#1}

\newcounter\localpositionnumber

\def\MPanchornumber
  {\iflocalpositioning\localpositionnumber\else\realfolio\fi}

%D So far for the trickery.

\newcounter\textbackgrounddepth

\appendtoks
  \savecurrentvalue\totalnofparbackgrounds\nofparbackgrounds
\to \everybye

\appendtoks
  \initializeparbackgrounds
\to \everystarttext

\ifx\totalnofparbackgrounds\undefined \newcounter\totalnofparbackgrounds \fi
\ifx\nofparbackgrounds     \undefined \newcounter\nofparbackgrounds      \fi

\def\initializeparbackgrounds
  {\ifcase\totalnofparbackgrounds\else
     \global\positioningtrue
     \global\positioningpartrue
   \fi}

\unexpanded\def\starttextbackground
  {\bgroup
   \increment\textbackgrounddepth
   \dodoubleempty\dostarttextbackground}

\let\dodostarttextbackground\relax
\let\dodostoptextbackground \relax

% \def\currentparbackground{background:0}
% \def\nextparbackground   {background:1}

\def\currentparbackground{pbg:0}
\def\nextparbackground   {pbg:1}

\def\btbanchor{b:\currentparbackground}
\def\etbanchor{e:\currentparbackground}

\def\nextbtbanchor{b:\nextparbackground}
\def\nextetbanchor{e:\nextparbackground}

\def\backgroundvariable#1%
  {\csname\??td\currenttextbackground#1\endcsname}

\def\dostarttextbackground[#1][#2]%
  {\checktextbackgrounds
   \def\currenttextbackground{#1}%
   \doglobal\increment\nofparbackgrounds
  %\edef\currentparbackground{background:\nofparbackgrounds}%
   \edef\currentparbackground{pbg:\nofparbackgrounds}%
   \bgroup
     \increment\nofparbackgrounds
    %\xdef\nextparbackground{background:\nofparbackgrounds}%
     \xdef\nextparbackground{pbg:\nofparbackgrounds}%
   \egroup
   \setuptextbackground[#1][#2]%
   \let\dodostarttextbackground\relax
   \let\dodostoptextbackground \relax
   \doifvalue{\??td#1\c!status}\v!start
     {\dopresettextbackground{#1}}%
   \dodostarttextbackground}

% todo \backgroundvariable\c!variant

\def\dopresettextbackground#1% todo: \backgroundparameter
  {\ExpandFirstAfter\processaction % \EFA niet echt nodig
     [\getvalue{\??td#1\c!plaats}]
     [ \v!tekst=>\let\dodostarttextbackground\dostarttextbackgroundtxt
                 \let\dodostoptextbackground \dostoptextbackgroundtxt,
      \v!alinea=>\let\dodostarttextbackground\dostarttextbackgroundpar
                 \let\dodostoptextbackground \dostoptextbackgroundpar]%
   \ifnum\textbackgrounddepth>\plusone % new
     \let\dodostarttextbackground\dostarttextbackgroundtxt
     \let\dodostoptextbackground \dostoptextbackgroundtxt
   \fi
   \doifelsevalue{\??td#1\c!kader}\v!aan
     {\doifelsevalue{\??td#1\c!hoek}\v!rond
        {\setvalue{\??td#1\c!kader}{2}}
        {\setvalue{\??td#1\c!kader}{1}}}
     {\setvalue{\??td#1\c!kader}{0}}%
   \doifelsevalue{\??td#1\c!achtergrond}\v!kleur
     {\setvalue{\??td#1\c!achtergrond}{1}}
     {\setvalue{\??td#1\c!achtergrond}{0}}%
  %\startpositionoverlay{\v!tekst\getvalue{\??td#1\c!niveau}}%
   \startpositionoverlay{\textbackgroundoverlay{\getvalue{\??td#1\c!niveau}}}%
     \expanded
       {\setMPpositiongraphicrange % moet veel efficienter
          {b:\currentparbackground}%
          {e:\currentparbackground}%
          {\getvalue{\??td#1\c!methode}}%
          {self=\currentparbackground,
           mp=\getvalue{\??td#1\c!mp},
           gridtype=\getvalue{\??td#1\c!variant},
           filltype=\getvalue{\??td#1\c!achtergrond},
           linetype=\getvalue{\??td#1\c!kader},
           gridcolor=\getvalue{\??td#1\c!kaderkleur},
           linecolor=\getvalue{\??td#1\c!kaderkleur},
           fillcolor=\getvalue{\??td#1\c!achtergrondkleur},
           filloffset=\getvalue{\??td#1\c!achtergrondoffset},
           gridwidth=\getvalue{\??td#1\c!lijndikte},
           linewidth=\getvalue{\??td#1\c!lijndikte},
           lineradius=\getvalue{\??td#1\c!straal}}}%
   \stoppositionoverlay}

\def\stoptextbackground
  {\dodostoptextbackground
   \carryoverpar\egroup}

\def\dostarttextbackgroundtxt
  {\ifvmode \leavevmode \fi
   \dostartattributes{\??td\currenttextbackground}\c!letter\c!kleur\empty
   \fpos\currentparbackground\ignorespaces}

\def\dostoptextbackgroundtxt
  {\tpos\currentparbackground
   \dostopattributes}

% keep this simple one, it's used in prikkels and alike
%
% \def\dostarttextbackgroundpar
%   {\endgraf % new
%    \getvalue{\??td\currenttextbackground\c!voor}%
%    \noindent\fpos\currentparbackground\ignorespaces
%    \bgroup
%    \nobreak \vskip-\lineheight \nobreak
%    \doassignsomeskip\getvalue{\??td\currenttextbackground\c!bovenoffset}\to\scratchskip
%    \kern\scratchskip\nobreak
%    \dosetleftskipadaption{\getvalue{\??td\currenttextbackground\c!linkeroffset}}%
%    \advance\leftskip\leftskipadaption
%    \dosetleftskipadaption{\getvalue{\??td\currenttextbackground\c!rechteroffset}}%
%    \advance\rightskip\leftskipadaption
%    \dostartattributes{\??td\currenttextbackground}\c!letter\c!kleur{}%
%    \geenwitruimte
%    \seteffectivehsize
%    \par}
%
% \def\dostoptextbackgroundpar
%   {\par
%    \dostopattributes
%    \doassignsomeskip\getvalue{\??td\currenttextbackground\c!onderoffset}\to\scratchskip
%    \kern\scratchskip\nobreak
%    \nobreak \vskip-\lineheight \nobreak
%    \geenwitruimte
%    \egroup
%    \nobreak \noindent \strut \hfill \kern\zeropoint \tpos\currentparbackground
%    \endgraf % new
%    \getvalue{\??td\currenttextbackground\c!na}}

\def\dostarttextbackgroundpar 
  {\endgraf % new
   \getvalue{\??td\currenttextbackground\c!voor}%
   \doassignsomeskip\getvalue{\??td\currenttextbackground\c!bovenoffset}\to\scratchskip
   \xdef\textbackgroundskip{\the\scratchskip}%
   \noindent
   \ifgridsnapping
     \ifdim\textbackgroundskip>\zeropoint
       \struttedbox{\hbox{\raise\textbackgroundskip\hbox{\fpos\currentparbackground}}}%
     \else
      \fpos\currentparbackground
     \fi
   \else
     \fpos\currentparbackground
   \fi
   \bgroup
   \nobreak \vskip-\lineheight \nobreak
   \doassignsomeskip\getvalue{\??td\currenttextbackground\c!bovenoffset}\to\scratchskip
   \ifgridsnapping \else \ifdim\textbackgroundskip>\zeropoint
     \kern\textbackgroundskip\nobreak
   \fi \fi
   \dosetleftskipadaption{\getvalue{\??td\currenttextbackground\c!linkeroffset}}%
   \advance\leftskip\leftskipadaption
   \dosetleftskipadaption{\getvalue{\??td\currenttextbackground\c!rechteroffset}}%
   \advance\rightskip\leftskipadaption
% new 
\dosetraggedcommand{\getvalue{\??td\currenttextbackground\c!uitlijnen}}%
\raggedcommand
%
   \dostartattributes{\??td\currenttextbackground}\c!letter\c!kleur\empty
   \geenwitruimte
   \seteffectivehsize
   \doinhibitblank %   \blanko[\v!blokkeer]% new
   \par}

\def\dostoptextbackgroundpar
  {\par
   \removelastskip % new
   \dostopattributes
   \doassignsomeskip\getvalue{\??td\currenttextbackground\c!onderoffset}\to\scratchskip
   \ifdim\lastskip>\zeropoint
     \advance\scratchskip-\lastskip
   \fi
   \xdef\textbackgroundskip{\the\scratchskip}%
   \ifgridsnapping \else \ifdim\textbackgroundskip>\zeropoint
     \kern\scratchskip\nobreak
   \fi \fi
   \nobreak \vskip-\lineheight \nobreak
   \geenwitruimte
   \egroup
\bgroup \forgeteverypar % NOT REALLY NEEDED, SAVES HASH/MEM
   \nobreak \noindent \strut \hfill \kern\zeropoint
   \ifgridsnapping % experimental, pascal (todo: topoffset in same way)
     \ifdim\textbackgroundskip>\zeropoint
       \struttedbox{\hbox{\lower\textbackgroundskip\hbox{\tpos\currentparbackground}}}%
     \else
       \tpos\currentparbackground
     \fi
   \else
     \tpos\currentparbackground
   \fi
\egroup
   \endgraf % new
   \getvalue{\??td\currenttextbackground\c!na}}

\let\textparpages \!!zeropoint
\let\textparheight\!!zeropoint
\let\textparwidth \!!zeropoint

\def\calculatetextpardimensions
  {\docalculatetextpardimensions\btbanchor    \etbanchor    \MPparanchor}

\def\calculatenexttextpardimensions
  {\docalculatetextpardimensions\nextbtbanchor\nextetbanchor\relax}

\def\docalculatetextpardimensions#1#2#3%
  {\scratchcounter\MPp#2%\etbanchor
   \advance\scratchcounter-\MPp#1%\btanchor
   \edef\textparpages{\the\scratchcounter}%
   \ifcase\scratchcounter
     % one page
     \scratchdimen         \MPy#1%\btanchor
     \advance\scratchdimen-\MPy#2%\etbanchor
   \else
     % two or more pages
     \scratchdimen         \MPy#1%\btanchor
     \advance\scratchdimen-\MPy#2%\etbanchor
     \advance\scratchdimen-\MPy\textanchor
     \advance\scratchdimen \MPy\textanchor
     \advance\scratchdimen \MPh\textanchor\relax
     \ifcase\scratchcounter>2 \ifnum\scratchcounter<5
       % more pages
       \scratchdimen\teksthoogte
       \advance\scratchcounter \minusone
       \multiply\scratchdimen \scratchcounter
     \else
       % keep'm small
       \scratchdimen5\teksthoogte
     \fi \fi
   \fi
   \edef\textparheight{\the\scratchdimen}%
   \ifcase\scratchcounter
     % one page
     \scratchdimen         \MPx#2%\etbanchor
     \advance\scratchdimen-\MPx#1%\btanchor
   \else
     % two or more pages / maybe also hang
     \ifx#3\relax
       \scratchdimen\zetbreedte % \tekstbreedte
     \else
       \scratchdimen\MPw\MPparanchor
       \advance\scratchdimen-\MPl\MPparanchor
       \advance\scratchdimen-\MPr\MPparanchor
     \fi
   \fi
   \edef\textparwidth{\the\scratchdimen}}

\def\mintextparheight{4\lineheight}

\def\dontsplitnexttextbackground % dangerous but useful
  {\ifdim\pagetotal>\teksthoogte \else
     \ifdim\pagegoal=\maxdimen \else
      \calculatenexttextpardimensions
      % too tricky
      % \scratchdimen=\textparheight
      % \advance\scratchdimen\pagetotal\relax
      % \ifdim\scratchdimen>\pagegoal
      % \pagina
      % \fi
      \ifdim\textparheight>\zeropoint
        \ifdim\textparheight>\mintextparheight\else
          \pagina % option
        \fi
      \fi
    \fi
   \fi}

\def\definetextbackground
  {\dodoubleempty\dodefinetextbackground}

\def\dodefinetextbackground[#1][#2]%
  {\ifsecondargument % why ? 
     \copyparameters[\??td#1][\??td]
       [\c!status,\c!plaats,\c!variant,\c!mp,\c!methode,
        \c!achtergrond,\c!achtergrondkleur,\c!hoek,\c!niveau,
        \c!achtergrondoffset,\c!voor,\c!na,\c!uitlijnen,
        \c!straal,\c!kader,\c!kaderkleur,\c!lijndikte,
        \c!linkeroffset,\c!rechteroffset,\c!bovenoffset,\c!onderoffset]%
     \getparameters[\??td#1][#2]%
     \doifvalue{\??td#1\c!status}\v!start\checktextbackgrounds
     \unexpanded\setvalue{#1}%
       {\groupedcommand{\starttextbackground[#1]}{\stoptextbackground}}%
     \setvalue{\e!start#1}{\starttextbackground[#1]}%
     \setvalue{\e!stop #1}{\stoptextbackground}%
   \fi}

\def\setuptextbackground
  {\dodoubleargument\dosetuptextbackground}

%\def\dosetuptextbackground[#1][#2]%
%  {\ifsecondargument
%     \getparameters[\??td#1][#2]%
%     \def\currenttextbackground{#1}%
%     \doifvalue{\??td#1\c!status}{\v!start}{\checktextbackgrounds}%
%   \else
%     \setuptextbackground[][#1]%
%   \fi}

\def\dosetuptextbackground[#1][#2]%
  {\ifsecondargument
     \doifelsenothing{#1}
       {\dodosetuptextbackground{#2}\empty}
       {\processcommalist[#1]{\dodosetuptextbackground{#2}}}%
   \else
     \dodosetuptextbackground{#1}\empty
   \fi}

\def\dodosetuptextbackground#1#2%
  {\getparameters[\??td#2][#1]%
   \def\currenttextbackground{#2}%
   \doifvalue{\??td#2\c!status}\v!start\checktextbackgrounds}

\let\currenttextbackground\empty

\def\checktextbackgrounds
  {\ifproductionrun
     \enabletextarearegistration
     \enablehiddenbackground
   \fi}

\setuptextbackground
  [\c!mp=mpos:par:columnset,      % buggy: mpos:par:shape
   \c!methode=mpos:par:columnset, %
   \c!status=\v!start,
   \c!plaats=\v!tekst,
   \c!linkeroffset=\!!zeropoint, % 1em,
   \c!rechteroffset=\getvalue{\??td\currenttextbackground\c!linkeroffset},
   \c!bovenoffset=\!!zeropoint,  % \v!middel,
   \c!onderoffset=\getvalue{\??td\currenttextbackground\c!bovenoffset},
   \c!niveau=-1,
   \c!variant=0,
   \c!uitlijnen=,
   \c!achtergrond=\v!kleur,
   \c!achtergrondkleur=lightgray,
   \c!achtergrondoffset=\!!zeropoint,
   \c!hoek=\v!recht,
   \c!straal=.5\bodyfontsize,
   \c!kader=\v!aan,
   \c!kaderkleur=blue,
   \c!lijndikte=\linewidth]

%D As an example we define a grid background:

\definetextbackground
  [\v!grid]
  [\c!status=\v!stop,
   \c!plaats=\v!alinea,
   \c!kader=\v!uit,
   \c!kaderkleur=red,
   \c!achtergrond=,
   \c!variant=1]

\ifx\basegrid\undefined \else \letvalue\v!grid=\basegrid \fi

% lelijk, aanpassen, opties

\setupMPvariables
  [mpos:connect]
  [linecolor=red,
   linewidth=1pt]

\setupMPvariables
  [mpos:encircle]
  [fillcolor=lightgray,
   filloffset=\!!zeropoint,
   linecolor=blue,
   linewidth=1pt]

\startuseMPgraphic{mpos:common:ec}
  path pa ; pair ca ; color lc ; numeric lw ;
  lw := \MPvar{linewidth} ;
  lc := \MPvar{linecolor} ;
  initialize_box(\MPpos{\MPvar{self}}) ;
  pa := pxy ; ca := cxy ; pa := boundingbox pa enlarged 2lw ;
  pa := llcorner pa...lrcorner pa...urcorner pa...ulcorner pa...cycle ;
  drawoptions (withpen pencircle scaled lw withcolor lc) ;
\stopuseMPgraphic

\startMPpositiongraphic{mpos:encircle}{linecolor,fillcolor,linewidth}
  \includeMPgraphic{mpos:common:ec}
  fill pa withcolor \MPvar{fillcolor} ; draw pa ;
  anchor_box(\MPanchor{\MPvar{self}}) ;
\stopMPpositiongraphic

\startMPpositiongraphic{mpos:connect}{linecolor,linewidth}
  path pb, pc ; pair cb, cc ;
  \includeMPgraphic{mpos:common:ec}
  initialize_box(\MPpos{\MPvar{to}}) ;
  pb := pxy ; cb := cxy ; pb := boundingbox pb enlarged 2lw ;
  pb := llcorner pb...lrcorner pb...urcorner pb...ulcorner pb...cycle ;
  pc := ca {up} .. {down} cb ;
  cc := (pc intersection_point pa) ;
  if intersection_found :
    pc := pc cutbefore cc ;
    cc := (pc intersection_point pb) ;
    if intersection_found :
      pc := pc cutafter cc ;
      drawarrow pc ; drawarrow reverse pc ;
    fi ;
  fi ;
  anchor_box(\MPanchor{\MPvar{self}}) ;
\stopMPpositiongraphic

%D \macros
%D   {stackposdown, stackposup, stackposleft,stackposright}
%D
%D A non graphic example of the use of positioning, is to stack
%D text in for instance the margin.
%D
%D \stackposdown \inlinker {some text}The text \type {some text}
%D goes into the left margin, and \stackposdown \inlinker {some
%D more}\type {some more} as well. When they overlap, they
%D will not touch.
%D
%D Here we said \type {\stackposdown \inlinker{some text}}. Instead
%D of \stackposleft \inlinker {one}stacking \stackposleft \inlinker
%D {two}vertically, one can stack horizontally by \stackposleft
%D \inlinker {three}using \type {\stackposleft}.
%D
%D We can go in all four directions, using \type {\stackposdown},
%D \type {\stackposup}, \type {\stackposleft} and \type
%D {\stackposright}.

\def\stackposdistance{.5em}

\newcounter\currentautopos

\def\POSstackprefix{stack:}

\def\dostackposbox#1#2%
  {\dowithnextbox
     {#2{\let\previousautopos\currentautopos
         \doglobal\increment\currentautopos
         \hpos{\POSstackprefix\currentautopos}
           {\doifoverlappingelse{\POSstackprefix\currentautopos}{\POSstackprefix\previousautopos}
              {#1}
              {\flushnextbox}}}}%
     \hbox}

\def\stackposup   {\dostackposbox{\raise\lineheight\flushnextbox}}
\def\stackposdown {\dostackposbox{\lower\lineheight\flushnextbox}}
\def\stackposleft {\dostackposbox{\copy\nextbox\hskip\nextboxwd\hskip\stackposdistance}}
\def\stackposright{\dostackposbox{\hskip\stackposdistance\hskip\nextboxwd\flushnextbox}}

%D \macros
%D   {stackeddown}
%D 
%D However, a better implementation is possible with the
%D following macro. We now have an extra key \type {stack} for
%D margin settings. When set to \type {yes}, this macro comes
%D into action. 

\def\stackeddown 
  {\dowithnextbox
     {\doglobal\increment\currentautopos
      \hpos{\POSstackprefix\currentautopos}
        {\edef\next
           {\nextboxht\the\nextboxht
            \nextboxdp\the\nextboxdp
            \nextboxwd\the\nextboxwd}%
         \let\previousautopos\currentautopos
         \scratchdimen\zeropoint
         \doloop
           {\decrement\previousautopos
            \doifoverlappingelse{\POSstackprefix\currentautopos}{\POSstackprefix\previousautopos}
              {\advance\scratchdimen\MPh{\POSstackprefix\previousautopos}%
               \advance\scratchdimen\MPd{\POSstackprefix\previousautopos}}%
              \exitloop
            \ifnum\previousautopos<\zerocount\exitloop\fi}%
         \ifdim\scratchdimen>\zeropoint
           \setbox\nextbox \hbox % \iftracepositons\ruledhbox\else\hbox\fi
             {\lower\scratchdimen\flushnextbox}%
           \next
         \fi
         \flushnextbox}}}

%D The next hack make sure that margin texts near faulty
%D strutted lines are handled ok.

\newif\ifrepositionmarginbox % \repositionmarginboxtrue

\newcounter\currentmarginpos

% \def\dopositionmarginbox#1%
%   {\bgroup
%    \ifrepositionmarginbox
%      \doglobal\increment\currentmarginpos
%      \setposition{\s!margin:\currentmarginpos}%
%      \scratchdimen=\MPy{\s!margin:\currentmarginpos}%
%      \doglobal\increment\currentmarginpos
%      \advance\scratchdimen by -\MPy{\s!margin:\currentmarginpos}%
%      \advance\scratchdimen by -\strutdp
%      \setbox#1=\hbox
%        {\setposition{\s!margin:\currentmarginpos}\raise\scratchdimen\box#1}%
%      \dp#1=\!!zeropoint
%      \ht#1=\!!zeropoint
%    \fi
%    \vadjust{\box#1}%
%    \egroup}

\def\dopositionmarginbox#1%
  {\bgroup
   \ifrepositionmarginbox
     \doglobal\increment\currentmarginpos
     \setposition{\s!margin:\currentmarginpos}%
     \scratchdimen\MPy{\s!margin:\currentmarginpos}%
     \doglobal\increment\currentmarginpos
     \advance\scratchdimen -\MPy{\s!margin:\currentmarginpos}%
     \advance\scratchdimen -\strutdp
     % new
     \setbox#1\hbox
       {\hskip-\MPx{\s!margin:\currentmarginpos}%
        \hskip\MPx{head:\realfolio}%
        \box#1}%
     % so far
     \setbox#1\hbox
       {\setposition{\s!margin:\currentmarginpos}%
        \raise\scratchdimen\box#1}%
     \dp#1\zeropoint
     \ht#1\zeropoint
   \fi
   \graphicvadjust{\box#1}%
   \egroup}

%D For a right menu, a sequence of calls to \type
%D {right_menu_button} is generated.
%D
%D \starttypen
%D right_menu_button (n, p, s=0/1/2, x, y, w, h, d) ;
%D \stoptypen
%D
%D Here, n is the number of the button, s a status variable,
%D while the rest is positional info. The status variable is
%D 0, 1 or~2: not found, found and found but current page.

% 0=not found 1=found 2=current page

% geen leeg

\newtoks\MPmenutoks

\def\MPmenubuttons#1{\the\MPmenutoks}

\appendtoks \global\MPmenutoks\emptytoks \to \everyshipout

% 0=notfound  1=found  2=currentpage

\def\do@@amposition#1#2#3%
  {\doifelsevalue{\??am#1\c!positie}\v!ja
     {\doglobal\increment\currentamposition
      \doifnumberelse{#2}
        {\docheckrealreferencepage{#2}%
         \global\chardef\currentamrealpage\ifrealreferencepage2\else1\fi}
        {\doifreferencefoundelse{#2}
           {\global\chardef\currentamrealpage\ifrealreferencepage2\else1\fi}
           {\global\chardef\currentamrealpage0}}% % not found
      \expanded
        {\doglobal\noexpand\appendtoks
           #1_menu_button(\currentamposition,\the\currentamrealpage,\noexpand\MPpos{#1:\currentamposition}) ;
         \to \MPmenutoks}%
      \hpos{#1:\currentamposition}{#3}}
     {#3}}

\def\do@@ammenuposition#1%
  {\ifnum\currentamposition>0
     \dowithnextbox{\hpos{menu:#1:\realfolio}{\flushnextbox}}\hbox
   \fi}

%D \macros
%D   {GFC, GTC, GSC}
%D
%D The next macros extend tables and tabulation with
%D backgrounds and position related features. Areas are
%D specified with symbolic names, and symbolic references to
%D the graphics involved. Each table has its own namespace.

\newcounter\noftabpositions
\newtoks   \posXCtoks

\def\tbPOSprefix
  {tbp:\noftabpositions:}

\def\tablepos
  {\scratchtoks\posXCtoks
   \global\posXCtoks\emptytoks
   \the\scratchtoks}

\let\tabulatepos\tablepos

\def\dodododoGSC[#1:#2]%
  {\remappositionframed{#2}{\tbPOSprefix#1}%
   \bpos{\tbPOSprefix#1}%
   \doglobal\appendtoks\@EA\epos\@EA{\tbPOSprefix#1}\to\posXCtoks}

\def\dododoGSC[#1:#2:#3]%
  {\doglobal\appendtoks\dodododoGSC[#1:#2]\to\posXCtoks\NC}

\def\dodoGSC[#1]%
  {\def\docommando##1{\dododoGSC[##1:##1]}%
   \processcommalist[#1]\docommando}

\def\dodododoGFC[#1:#2:#3]%
  {\remappositionframed{#2}{\tbPOSprefix#1}%
   \bpos{\tbPOSprefix#1}}

\def\dododoGFC[#1]%
  {\def\docommando##1{\dodododoGFC[##1:##1]}%
   \processcommalist[#1]\docommando}

\def\dodoGFC[#1]%
  {\doglobal\appendtoks\dododoGFC[#1]\to\posXCtoks\NC}

\def\dododododoGTC[#1:#2]%
  {\epos{\tbPOSprefix#1}}

\def\dodododoGTC[#1]%
  {\def\docommando##1{\dododododoGTC[##1:##1]}%
   \processcommalist[#1]\docommando}

\def\dododoGTC[#1]%
  {\doglobal\appendtoks\dodododoGTC[#1]\to\posXCtoks}

\def\dodoGTC[#1]%
  {\doglobal\appendtoks\dododoGTC[#1]\to\posXCtoks\NC}

\def\dodododoXC[#1#2]%
  {\if#1>\dodoGFC  [#2:#2]\else
   \if#1+\dodoGFC  [#2:#2]\else
   \if#1<\dodoGTC  [#2:#2]\else
   \if#1-\dodoGTC  [#2:#2]\else
   \if#1=\dodoGSC  [#2:#2]\else
         \dodoGSC[#1#2:#1#2]\fi\fi\fi\fi\fi}

\def\dododoXC#1%
  {\dodododoXC[#1]}

\def\dodoXC[#1]%
  {{\let\NC\relax\processcommalist[#1]\dododoXC}}

\def\doGSC[#1]{\iffirstargument\dodoGSC[#1]\else\expandafter\NC\fi}
\def\doGFC[#1]{\iffirstargument\dodoGFC[#1]\else\expandafter\NC\fi}
\def\doGTC[#1]{\iffirstargument\dodoGTC[#1]\else\expandafter\NC\fi}
\def\doXC [#1]{\iffirstargument\dodoXC [#1]\else\expandafter\fi\NC}

\def\tbGSC{\dosingleempty\doGSC}
\def\tbGFC{\dosingleempty\doGFC}
\def\tbGTC{\dosingleempty\doGTC}
\def\tbXC {\dosingleempty\doXC }

%D The amount of code to support tables and tabulation is
%D rather minimalistic.

\let\tabulatepos\tablepos

\def\tabulatenormalpos
  {\hss\tabulatepos\hss}

\def\tabulateequalpos
  {\setbox\scratchbox\hbox{\tabulateEQ}%
   \hbox to \wd\scratchbox{\hss\kern\zeropoint\tabulatepos\hss}%
   \hskip-\wd\scratchbox
   \box\scratchbox}

\def\tabulatenormalcolumn#1% overloaded
  {&\iftabulateequal\tabulateequalpos\else\tabulatenormalpos\fi
   &\global\chardef\tabulatetype#1&}

\def\tabulateequalcolumn#1% overloaded
  {&\tabulateequalpos
   &\global\chardef\tabulatetype#1&}

\appendtoks
  \doglobal\increment\noftabpositions
\to \everytabulate

%D In order to prevent potential clashes with abbreviations,
%D postpone the mapping.

\appendtoks
  \let\GSC\tbGSC \let\GFC\tbGFC \let\GTC\tbGTC \let\XC\tbXC
\to \everytabulate

%D \macros
%D   {definepositionframed}
%D
%D The next example show how to provide backgrounds to table
%D cells. First we define some framed backgrounds.
%D
%D \startbuffer
%D \definepositionframed[x][background=color,backgroundcolor=red]
%D \definepositionframed[y][background=color,backgroundcolor=green]
%D \definepositionframed[z][background=color,backgroundcolor=blue]
%D \stopbuffer
%D
%D \typebuffer
%D
%D % \haalbuffer
%D
%D \startbuffer
%D \starttabulatie[|c|c|c|]
%D \GFC[f:x] this is a small  \NC       table            \NC     in which we \NC \FR
%D \NC       will demonstrate \GFC[g:z] that this        \GTC[g] positioning \NC \MR
%D \GSC[e:y] mechanism also   \GTC[f]   works quite well \NC     in tables   \NC \LR
%D \stoptabulatie
%D \stopbuffer
%D
%D The table itself defines three areas (a, b and~c) using
%D these frames.
%D
%D \typebuffer
%D % \haalbuffer
%D
%D Tables (based on \TABLE) are supported by:

\def\normalTABLEsimplebar {\unskip\!ttRightGlue&\tablepos&}                       % |
\def\normalTABLEcomplexbar{\unskip\!ttRightGlue&\omit\tablepos\!ttAlternateVrule} % \|
\def\normalTABLEquote     {\unskip\!ttRightGlue&\omit\tablepos&}                  % "

\appendtoks
  \doglobal\increment\noftabpositions
\to \everytable

%D Since we don't want nameclashes:

\appendtoks
  \let\GSC\tbGSC \let\GFC\tbGFC \let\GTC\tbGTC \let\XC\tbXC
\to \everytable

%D In the previous example, we could have provided an overlay to
%D the framed definition. A more direct approach is demonstrated
%D below:
%D
%D \startbuffer
%D \def\cw#1{\color[white]{#1}}
%D
%D \startMPpositiongraphic{tableshade}
%D   initialize_area(\MPpos{\MPvar{from}},\MPpos{\MPvar{to}}) ;
%D   color c ; c := \MPvar{color} ;
%D   linear_shade(pxy,0,.4c,.9c) ;
%D   anchor_area(\MPanchor{\MPvar{from}}) ;
%D \stopMPpositiongraphic
%D 
%D \setMPpositiongraphic{b:x}{tableshade}{from=b:x,to=e:x,color=red}
%D \setMPpositiongraphic{b:y}{tableshade}{from=b:y,to=e:y,color=green}
%D \setMPpositiongraphic{b:z}{tableshade}{from=b:z,to=e:z,color=blue}
%D \stopbuffer
%D
%D \typebuffer \haalbuffer
%D 
%D The definition of the table looks about the same as the
%D previous one:
%D
%D \startbuffer
%D \starttabel[|c|c|c|]
%D \GFC[b:z] \cw{this is a small}  \NC       \cw{table}            \NC     in which we      \NC \FR
%D \NC       \cw{will demonstrate} \GFC[c:y] \cw{that this}        \GTC[c] \cw{positioning} \NC \MR
%D \GSC[a:x] \cw{mechanism also}   \GTC[b]   \cw{works quite well} \NC     in tables        \NC \LR
%D \stoptabel
%D \stopbuffer
%D
%D \typebuffer
%D
%D \haalbuffer

% \definepositionframed[w][background=color,backgroundcolor=yellow]
% \definepositionframed[x][background=color,backgroundcolor=red]
% \definepositionframed[y][background=color,backgroundcolor=green]
% \definepositionframed[z][background=color,backgroundcolor=blue]
%
% \starttabulate[|c|c|c|]
% \NC this is a small  \NC table            \NC in which we \NC \FR
% \NC will demonstrate \NC that this        \NC positioning \NC \MR
% \NC mechanism also   \NC works quite well \NC in tables   \NC \LR
% \stoptabulate
%
% \starttabulate[|c|c|c|]
% \GFC[f:x] this is a small      \GTC      table            \NC     in which we \NC \FR
% \NC       will demonstrate     \GFC[g:z] that this        \GTC[g] positioning \NC \MR
% \GSC[e:y] mechanism also       \GTC[f]   works quite well \NC     in tables   \NC \LR
% \stoptabulate
%
% \starttabulate[|c|c|c|]
% \GFC[f:x,d:w] this is a small  \GTC[d]   table            \NC     in which we \NC \FR
% \NC           will demonstrate \GFC[g:z] that this        \GTC[g] positioning \NC \MR
% \GSC[e:y]     mechanism also   \GTC[f]   works quite well \NC     in tables   \NC \LR
% \stoptabulate
%
% \starttabulate[|c|c|c|]
% \XC[+f:x] this is a small  \XC      table            \NC     in which we \NC \FR
% \NC      will demonstrate  \XC[+g:z] that this       \XC[-g] positioning \NC \MR
% \XC[=e:y] mechanism also   \XC[-f]  works quite well \NC     in tables   \NC \LR
% \stoptabulate
%
% \starttabulate[|c|c|c|]
% \XC[+f:x,+d:w] this is a small  \XC[-d]   table            \NC     in which we \NC \FR
% \NC            will demonstrate \XC[+g:z] that this        \XC[-g] positioning \NC \MR
% \XC[=e:y]       mechanism also  \XC[-f]   works quite well \NC     in tables   \NC \LR
% \stoptabulate

% evt                  [b:x]
%
% \definepositionframed[x][background=color,fillcolor=red]
% \definepositionframed[y][background=color,fillcolor=green]
% \definepositionframed[z][background=color,fillcolor=blue]

\def\remappositionframed#1#2% from to
  {\copyposition{b:#1}{b:#2}%
   \copyposition{e:#1}{e:#2}%
   \dosetpositionaction{b:#2}{\dopositionaction{b:#1}}}

\def\definepositionframed
  {\dodoubleargument\dodefinepositionframed}

\def\dodefinepositionframed[#1][#2]%
  {\dosetpositionaction{b:#1}{\dopositionframed[#1][#2]}}

\def\positionframed
  {\dodoubleempty\dopositionframed}

\def\dopositionframed[#1][#2]%
  {\bgroup
   \setbox\scratchbox\hbox
     {\dimen0=\MPx{e:#1}%
      \advance\dimen0 -\MPx{b:#1}%
      \dimen2=\MPy{b:#1}%
      \advance\dimen2 -\MPy{e:#1}%
      \advance\dimen2 \MPd{e:#1}%
      \lower\dimen2\hbox
        {\advance\dimen2 \MPh{b:#1}%
         \framed
           [\c!breedte=\dimen0,\c!hoogte=\dimen2,
            \c!offset=\v!overlay,#2]{}}}%
   \smashedbox\scratchbox
   \egroup}

% \def\sethdistances#1%
%   {\hbox{\lpos{ml:#1}\hpos{mh:#1}{\strut}\rpos{mr:#1}}}
%
% \def\gethdistances#1%
%   {\scratchdimen\MPx{mh:#1}%
%    \advance\scratchdimen -\MPx{ml#1}%
%    \edef\lefthdistance{\the\scratchdimen}%
%    \scratchdimen\MPx{mr:#1}%
%    \advance\scratchdimen -\MPx{mh:#1}%
%    \edef\righthdistance{\the\scratchdimen}}

\protect \endinput
