supp-mps.mkii / last modification: 2020-01-30 14:15
%D \module
%D   [       file=supp-mps,
%D        version=1997.07.05,
%D          title=\CONTEXT\ Support Macros,
%D       subtitle=\METAPOST\ Inclusion,
%D         author=Hans Hagen,
%D           date=\currentdate,
%D      copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
%C
%C This module is part of the \CONTEXT\ macro||package and is
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.

%D Forget about generic modules \unknown\ ...

\ifx \undefined \contextversion \endinput \fi

%D \METAPOST\ is John Hobbys alternative for \METAFONT\ and
%D produces superior \POSTSCRIPT\ code. In this module we
%D integrate \METAPOST\ support int \CONTEXT.  We offer two
%D tracks:
%D
%D \startitemize
%D \item generating \METAPOST\ code, running this program from
%D      within \TEX\ using \type{\write18}, and importing the
%D      result
%D \item generating \METAPOST\ code, processing the code
%D      afterward, and importing the result in a second pass
%D \stopitemize
%D
%D The first approach uses a non standard \TEX\ feature,
%D implemented in Web2c. I'm not going to discuss the pros and
%D cons of running programs from within others, but all
%D arguments against this can be overcome by implementing a
%D \TEX\ worthy primitive:
%D
%D \starttyping
%D \excuteMetaPost filename
%D \stoptyping
%D
%D Ok then, let's start:

\writestatus{loading}{ConTeXt Support Macros / MetaPost Inclusion}

\unprotect

\def\@@MPG{@MPG@}

%D First we define a handy constant:

\bgroup \catcode`\%=\@@other \xdef\letterpercent{\string%} \egroup

% todo : sort out ^^M, \par and ; mess

%D \macros
%D   {everyMPgraphic}
%D
%D Because some graphics interact with \TEX\ (i.e.\ \CONTEXT), we
%D provide a hook for additional actions: \type {\everyMPgraphic}.

\newtoks\everyMPgraphic \everyMPgraphic{\everyMPgraphic\emptytoks}

%D \macros
%D   {startMPgraphic}
%D
%D From within \TEX\ one can execute \METAPOST\ code by putting
%D it between the two commands
%D
%D \starttyping
%D \startMPgraphic
%D \stopMPgraphic
%D \stoptyping
%D
%D This is implemented as:

\let\stopMPgraphic\relax

\long\def\startMPgraphic#1\stopMPgraphic
  {\startwritingMPgraphic
   \writecheckedMPgraphic{#1}% % potential speedup: pass #1 as macro
   \stopwritingMPgraphic}

%D \macros
%D   {startMPrun}
%D
%D If we just want to run \METAPOST\ code, that is, not to
%D explictly generate a figure in terms of \type{beginfig} and
%D \type{endfig}, we can use:
%D
%D \starttyping
%D \startMPgraphic
%D \stopMPgraphic
%D \stoptyping
%D
%D \starttyping
%D \startMPrun
%D \stopMPrun
%D \stoptyping
%D
%D The next booleans are for internal purposes only.

% some day a bit more more clear:
%
% run directly/run afterwards/run external defined
% insert directly/insert whenever
% use object/don't use objects

\newif\ifMPgraphics \MPgraphicstrue
\newif\ifMPrun      \MPrunfalse
\newif\ifMPwrapper  \MPwrappertrue

\let\stopMPrun\relax

\ifCONTEXT

  \long\def\dostartMPrun#1#2\stopMPrun
    {\bgroup
     \MPruntrue
     \doifsomething{#1}{\def\MPgraphicfile{#1}}%
     \startwritingMPgraphic
     \writecheckedMPgraphic{#2}%
     \stopwritingMPgraphic
     \egroup}

  \def\startMPrun
    {\dosinglegroupempty\dostartMPrun}

\else

  \long\def\startMPrun#1\stopMPrun
    {\MPruntrue
     \startwritingMPgraphic
     \writecheckedMPgraphic{#1}%
     \stopwritingMPgraphic
     \MPrunfalse}

\fi

%D \macros
%D   {startwritingMPgraphic,
%D    writeMPgraphic,
%D    stopwritingMPgraphic}
%D
%D If the writing process is divided into more steps, one can
%D use the components of this macro directly.
%D
%D \starttyping
%D \startwritingMPgraphic
%D ...
%D \writeMPgraphic{...}
%D ...
%D \writeMPgraphic{...}
%D ...
%D \stopwritingMPgraphic
%D \stoptyping

%D \macros
%D   {ifrunMPgraphics,ifrunMPTEXgraphics,ifinsertMPgraphics}
%D
%D These macros look a bit more complicated that one would
%D expect at first sight. This is due to the two ways of
%D processing these graphics, mentioned in a previous
%D paragraph. Which method is used, the direct or indirect
%D one, depends on a boolean.

\newif\ifrunMPgraphics     \runMPgraphicsfalse
\newif\ifrunMPTEXgraphics  \runMPTEXgraphicsfalse
\newif\ifinsertMPgraphics  \insertMPgraphicstrue

%D If set to true, one can do with a single pass, else one must
%D process the \METAPOST\ file \type{mpgraph} between two
%D succesive \TEX\ runs.

\ifx\MPgraphicfile\undefined

\def\MPgraphicfile{mp\ifMPrun run\else graph\fi}
\def\MPruntimefile{mprun}

\fi

%D \macros
%D   {MPgraphic}
%D
%D When we run \METAPOST\ from within \TEX, each graphic is
%D processed at once, which means that we reuse this file many
%D times. When however the execution is delayed, all graphics
%D are saved in a separate figure. The current graphic is
%D characterized bij a \COUNTER. This counter is available
%D in \type{\MPgraphic}.

\newcount\nofMPgraphics
\newcount\currentMPgraphic

\def\MPgraphic{0}

% %D \macros
% %D   {ifreuseMPgraphics}
% %D
% %D If one want to reuse grapics, one can save much redundant
% %D run time by setting the next switch to true.
%
% \newif\ifreuseMPgraphics \reuseMPgraphicstrue

%D The three macros responsible for writing the graphic
%D implement both schemes.

%D \macros
%D   {MPinclusions, startMPinclusions, MPinitializations}
%D
%D One can include for instance common input commands by
%D passing them to \type{\MPinclusions}:
%D
%D \starttyping
%D \startMPinclusions
%D    input mp-mine ;
%D \stopMPinclusions
%D \stoptyping
%D
%D \starttyping
%D \MPinclusions{input mp-mine}
%D \stoptyping
%D
%D These commands reset their content each time. You can append
%D code as follows:
%D
%D \starttyping
%D \startMPinclusions[+]
%D    input mp-mine ;
%D \stopMPinclusions
%D \stoptyping
%D
%D The token register \type {\MPinitializations} is expanded
%D before all other inclusions, the extensions are expanded
%D only once per run.

%D The next hack prevents too long lines:

\long\def\runtimeobeyMPlines
  {\catcode35=11\relax % goodie
   \ifx\rawcharacter\undefined
     \let\obeyedline\space
   \else
     \obeylines
     \ifx\outputnewlinechar\undefined
       \edef\obeyedline{\rawcharacter{\endlinechar}}%
     \else
       \let\obeyedline\outputnewlinechar
     \fi
   \fi}

\long\def\obeyMPlines % anyhow, we end up with ^^M's in the input
  {\obeylines
   \let\obeyedline\relax} % delay expansion

\ifx\everydump\undefined
    % maybe we're not using context
\else
    \appendtoks
        \let\obeyMPlines\runtimeobeyMPlines
    \to \everydump
\fi

%D We use two distinguished token registers:

\newtoks \MPextensions      % once per run (can be multiple graphics)
\newtoks \MPinitializations % each graphic

\let\stopMPextensions     \relax % so that we can use it in \expanded
\let\stopMPinitializations\relax % so that we can use it in \expanded
\let\stopMPinclusions     \relax % so that we can use it in \expanded

\def\startMPextensions % no text checking done here !
  {\begingroup
   \obeyMPlines
   \dostartMPextensions}

\def\dostartMPextensions#1\stopMPextensions
  {\endgroup
   \MPextensions\expandafter{\the\MPextensions#1}}

\def\startMPinitializations % no text checking done here !
  {\begingroup
   \obeyMPlines
   \dostartMPinitializations}

\def\dostartMPinitializations#1\stopMPinitializations
  {\endgroup
   \MPinitializations\expandafter{\the\MPinitializations#1}}

\def\startMPinclusions
  {\begingroup
   \dosingleempty\dostartMPinclusions}

\long\def\dostartMPinclusions
  {\obeyMPlines
   \dodostartMPinclusions}

\long\def\dodostartMPinclusions[#1]#2\stopMPinclusions % document wide
  {\endgroup
   \doifelse{#1}{+}
     {\@EA\long\@EA\def\@EA\theMPinclusions\@EA
        {\theMPinclusions
         \writeMPgraphic{#2}}}
     {\long\def\theMPinclusions
        {% \expanded !
%          \@EA\expanded\@EA{\@EA\writeMPgraphic\@EA{\the\MPextensions;}}% new
         \writeMPgraphic{#2}}}}

\def\MPinclusions
  {\dosingleempty\doMPinclusions}

\long\def\doMPinclusions[#1]#2%
  {\startMPinclusions[#1]#2\stopMPinclusions}

\def\theMPextensions
  {\@EA\expanded\@EA{\@EA\writeMPgraphic\@EA{\the\MPextensions;}}}

\def\theMPinitializations
  {\@EA\expanded\@EA{\@EA\writeMPgraphic\@EA{\the\MPinitializations;}}}

\startMPinclusions \stopMPinclusions

%D \macros
%D   {iflongMPlines}
%D
%D When grabbing a graphic deifnition, newlines are turned
%D into spaces. By default we split the graphic definition
%D at the colon, but long lines are still possible by
%D setting the next boolean to true.

\newwrite\MPwrite
\newwrite\MPstaticwrite

\newif\iflongMPlines \longMPlinestrue % we now have \obeyMPlines

\ifx \overlaywidth     \undefined \def \overlaywidth     {4cm} \fi
\ifx \overlayheight    \undefined \def \overlayheight    {3cm} \fi
\ifx \overlaylinewidth \undefined \def \overlaylinewidth {0pt} \fi

\def\presetMPdefinitions
  {\edef\overlaywidth     {\overlaywidth    \space}%
   \edef\overlayheight    {\overlayheight   \space}%
   \edef\overlaylinewidth {\overlaylinewidth\space}%
   \edef\currentwidth     {\the\hsize       \space}%
   \edef\currentheight    {\the\vsize       \space}}

%D The \type {;} aware method (the \type {\else} branch) also
%D takes care of \type {btex}||\type {etex}, \type
%D {verbatimtex}||\type {etex}. The space after \type {tex}
%D is essential, since it protects \type {text}.

\newif\ifMPTEXgraphic

\let\bufferedMPgraphicsline\empty

\appendtoks
  \globallet\bufferedMPgraphicsline\empty
\to \everyMPgraphic

\chardef\MPgraphicsscanmode\plustwo % 0=no scanning, 1=simple scanning, 2=less simple, 3=even less

% the next fails with \chardef\MPgraphicsscanmode\plusone
%
% \startMPextensions
% 	gp_num_points_with_tex := 3 ;
% \stopMPextensions

\def\writeMPgraphic % no big #1 passing here
  {\iflongMPlines
     \ifMPTEXgraphic
       \ifcase\MPgraphicsscanmode
         \let\next\writeMPgraphiclongR
       \else
         \let\next\writeMPgraphiclongT
       \fi
     \else
       \let\next\writeMPgraphiclongN
     \fi
   \else
     \ifMPTEXgraphic
       \ifcase\MPgraphicsscanmode
         \let\next\writeMPgraphicshortN % we could \let \writeMPgraphicshortR\writeMPgraphicshortN
       \else
         \let\next\writeMPgraphicshortT
       \fi
     \else
       \let\next\writeMPgraphicshortN
     \fi
   \fi
   \next}

\appendtoks \obeyMPlines \to \everyMPgraphic % more efficient than in each following grouped write

\long\def\writeMPgraphiclongR#1% fast, no scanning
  {\bgroup
   \let\par\space
   \immediate\write\MPwrite{#1}%
   \egroup}

\long\def\writeMPgraphiclongT#1%
  {\bgroup
   \let\par\space
   \longMPflushT#1\empty\par\relax\par
   \egroup}

\long\def\writeMPgraphicshortT#1%
  {\bgroup
   \let\par\space
   \shortMPflushT#1\empty;\relax;%
   \egroup}

\long\def\longMPflushT#1#2\par
  {\ifx#1\relax \else
     \dowriteMPgraphicline#1#2tex \relax etex\MPend
     \expandafter\longMPflushT
   \fi}

\long\def\shortMPflushT#1#2;%
  {\ifx#1\relax \else
     \dowriteMPgraphicline#1#2tex \relax etex\MPend
     \expandafter\shortMPflushT
   \fi}

\long\def\writeMPgraphiclongN#1%
  {\bgroup
   \let\par\space
   \longMPflushN#1\empty\par\relax\par
   \egroup}

\long\def\writeMPgraphicshortN#1%
  {\bgroup
   \let\par\space
   \shortMPflushN#1\empty;\relax;%
   \egroup}

\long\def\longMPflushN#1#2\par
  {\ifx#1\relax \else
     \nowriteMPgraphicline#1#2\MPend
     \expandafter\longMPflushN
   \fi}

\long\def\shortMPflushN#1#2;%
  {\ifx#1\relax \else
     \nowriteMPgraphicline#1#2\MPend
     \expandafter\shortMPflushN
   \fi}

\def\dowriteMPgraphicline{\futurelet\next\dodowriteMPgraphicline}
\def\nowriteMPgraphicline{\futurelet\next\nonowriteMPgraphicline}

%D Will move (check if next is needed):

\long\def\nonowriteMPgraphicline#1\MPend
  {\ifx\next\empty\else\ifx\next\relax\else
     \bgroup
     \let\par\space
     \iflongMPlines
      %\immediate\write\MPwrite{#1;}% oeps, ; invalid
       \immediate\write\MPwrite{#1}%
     \else
       \long\edef\ascii{#1}%
       \expandafter\flushMPgraphicline\ascii\empty;\relax;%
     \fi
     \egroup
   \fi\fi}

%D A first version:
%D
%D \starttyping
%D \long\def\dodowriteMPgraphicline#1tex #2#3etex#4\MPend%
%D   {\ifx\next\empty\else\ifx\next\relax\else
%D      \bgroup
%D      \let\par=\space
%D      \ifx#2\relax
%D        \immediate\write\MPwrite{#1;}%
%D       \egroup
%D     \else
%D       \global\MPTEXgraphictrue
%D        \convertargument#2#3\to\ascii
%D        \immediate\write\MPwrite{#1tex \ascii etex}%
%D        \egroup
%D        \dowriteMPgraphicline#4tex \relax etex\MPend
%D      \fi
%D    \fi\fi}
%D \stoptyping

%D The next alternative also handles inclusions well.

\newtoks \everyMPTEXgraphic

\newif\ifforceMPTEXgraphic

%D Before we supported the graph module, we had:
%D
%D \starttyping
%D \convertargument        etex\to\MPasciiB
%D \convertargument     textext\to\MPasciiC % geen "text"
%D \convertargument graphictext\to\MPasciiD % geen "text"
%D
%D \long\def\checkMPTEXgraphic#1%
%D   {\ifforceMPTEXgraphic
%D      \global\MPTEXgraphictrue
%D    \else
%D      \expandafter\convertargument#1\to\MPasciia
%D      \doifstringinstringelse\MPasciiB\MPasciia{\global\MPTEXgraphictrue}
%D     {\doifstringinstringelse\MPasciiC\MPasciia{\global\MPTEXgraphictrue}
%D     {\doifstringinstringelse\MPasciiD\MPasciia{\global\MPTEXgraphictrue}
%D                                               {\global\MPTEXgraphicfalse}}}%
%D    \fi}
%D \stoptyping
%D
%D The next alternative permits extensions in other modules
%D without the need to know the details of testing.

\newtoks\MPTEXgraphicchecks

\long\def\writecheckedMPgraphic#1%
  {\ifforceMPTEXgraphic
     \global\MPTEXgraphictrue
   \else
     \global\MPTEXgraphicfalse
     \edef\ascii{#1}\convertcommand\ascii\to\MPascii
     \the\MPTEXgraphicchecks\relax % \relax is end condition!
   \fi
   \flushMPTEXgraphic % verbatimtex etc
   \writeMPgraphic{#1}} % potential optimization: pass \ascii

%D We could have used a kind of array approach using a
%D counter appended to \type {MPascii}, but this is an
%D as efficient alternative. (The uglyness comes from
%D expanding after the string \type {#1}).

\let\MPTEXchecklist\empty

\def\forceMPTEXcheck#1%
  {\addtocommalist{#1}\MPTEXchecklist
   \expanded{\convertargument#1\noexpand\to
     \@EA\noexpand\csname MPascii#1\endcsname}%
   \@EA\appendtoks
     \@EA\doifincsnameelse\csname MPascii#1\endcsname\MPascii
       {\global\MPTEXgraphictrue\gobbleuntil\relax}\donothing
   \to \MPTEXgraphicchecks}

\forceMPTEXcheck{etex}
\forceMPTEXcheck{textext}
\forceMPTEXcheck{graphictext}

%D \starttyping
%D \forceMPTEXgraphictrue
%D
%D \forceMPTEXcheck{lintext}
%D \forceMPTEXcheck{logtext}
%D
%D \startMPcode
%D draw hlintext.lft(0, 20,  5, 20cm, "@3e") ;
%D draw vlogtext.bot(0, 10,  9, 10cm, "@3e") ;
%D \stopMPcode
%D \stoptyping

%D A goodie for Mojca (the gnuplot wizzard):
%D
%D \starttyping
%D \startMPcode
%D draw fullcircle scaled 4cm ;
%D draw \textext{$\sqrt{\frac{3}{2}^3}$} ;
%D \stopMPcode
%D \stoptyping

\long\def\textext#1{\normalunexpanded{textext("#1")}} % or \detokenize

\def\flushMPTEXgraphic
  {\ifMPTEXgraphic
     \immediate\write\MPwrite{verbatimtex \the\everyMPTEXgraphic\space etex;}%
   \fi}

\long\def\flushMPgraphicline#1#2;%
  {\ifx#1\relax \else
     \immediate\write\MPwrite{#1#2;}%
     \expandafter\flushMPgraphicline
   \fi}

% the next one fails on btex \vbox {\hbox .. leading to \vbox \hbox
%
% \long\def\dodowriteMPgraphicline#1tex #2#3etex#4\MPend
%   {\ifx\next\empty\else\ifx\next\relax\else
%      \bgroup
%      \let\par\space
%      \ifx#2\relax
%        \iflongMPlines
%          \immediate\write\MPwrite{#1;}%
%        \else
%          \edef\ascii{#1}%
%          \expandafter\flushMPgraphicline\ascii\empty;\relax;%
%        \fi
%        \egroup
%      \else
%        \convertargument#2#3\to\ascii
%        \immediate\write\MPwrite{#1tex \ascii etex}%
%        \egroup
%        \dowriteMPgraphicline#4tex \relax etex\MPend
%      \fi
%    \fi\fi}
%
% so we need a two step approach

% \long\def\dodowriteMPgraphicline#1tex %
%   {\doifnextcharelse\relax
%      {\nododowriteMPgraphicline{#1}}
%      {\redodowriteMPgraphicline{#1}}}
%
% better and faster

% \long\def\dodowriteMPgraphicline#1tex #2%
%   {\ifx#2\relax
%      \expandafter\nododowriteMPgraphicline
%    \else
%      \expandafter\redodowriteMPgraphicline
%    \fi{#1} #2}
%
% \long\def\redodowriteMPgraphicline#1#2etex#3\MPend
%   {\ifx\next\empty\else\ifx\next\relax\else
%      \bgroup
%      \let\par\space
%      \convertargument#2\to\ascii
%      \immediate\write\MPwrite{#1tex \ascii etex}%
%      \egroup
%      \dowriteMPgraphicline#3tex \relax etex\MPend
%    \fi\fi}
%
% \long\def\nododowriteMPgraphicline#1#2\MPend
%   {\ifx\next\empty\else\ifx\next\relax\else
%      \bgroup
%      \let\par\space
%      \iflongMPlines
%        \immediate\write\MPwrite{#1;}%
%      \else
%        \long\edef\ascii{#1}%
%        \expandafter\flushMPgraphicline\ascii\empty;\relax;%
%      \fi
%      \egroup
%    \fi\fi}

% extra scanning

\long\def\dodowriteMPgraphicline#1tex #2% kind of ok
  {\ifx#2\relax
     \expandafter\nododowriteMPgraphicline
   \else
     \ifcase\MPgraphicsscanmode
       % can't happen
     \or
       \@EAEAEA\redodowriteMPgraphicline
     \or
       \doifinstringelse{b$}       {#1$}{\@EAEAEA\redodowriteMPgraphicline}%
      {\doifinstringelse{verbatim$}{#1$}{\@EAEAEA\redodowriteMPgraphicline}%
                                        {\@EAEAEA\dododowriteMPgraphicline}}%
     \else
       \doifinstringelse      { b$}{#1$}{\@EAEAEA\redodowriteMPgraphicline}%
      {\doifinstringelse      {(b$}{#1$}{\@EAEAEA\redodowriteMPgraphicline}%
      {\doifinstringelse      {=b$}{#1$}{\@EAEAEA\redodowriteMPgraphicline}%
      {\doifinstringelse{verbatim$}{#1$}{\@EAEAEA\redodowriteMPgraphicline}%
                                        {\@EAEAEA\dododowriteMPgraphicline}}}}%
     \fi
   \fi{#1} #2}

\def\dododowriteMPgraphicline#1#2\MPend
  {\doifsomething{#1}{\xdef\bufferedMPgraphicsline{\bufferedMPgraphicsline#1tex }}%
   \dowriteMPgraphicline#2tex \relax etex\MPend}

\long\def\redodowriteMPgraphicline#1#2etex#3\MPend
  {\ifx\next\empty
   \else\ifx\next\relax
   \else
     \bgroup
     \let\par\space
     \convertargument#2\to\ascii
     \immediate\write\MPwrite{\bufferedMPgraphicsline#1tex \ascii etex}%
     \globallet\bufferedMPgraphicsline\empty
     \egroup
     \dowriteMPgraphicline#3tex \relax etex\MPend
   \fi\fi}

\long\def\nododowriteMPgraphicline#1#2\MPend
  {\ifx\next\empty
   \else\ifx\next\relax
   \else
     \bgroup
     \let\par\space
     \iflongMPlines
       \immediate\write\MPwrite{\bufferedMPgraphicsline#1;}%
       \globallet\bufferedMPgraphicsline\empty
     \else
       \long\edef\ascii{\bufferedMPgraphicsline#1}%
       \expandafter\flushMPgraphicline\ascii\empty;\relax;%
     \fi
     \egroup
   \fi\fi}

%D This stripper is suboptimal in the sense that more
%D \type{;}'s are output than feasible. Anyhow, \METAPOST\
%D can handle this and users may consider it being a sort
%D of error prevention bonus.

\ifx\blabelgroup\undefined

  \let\blabelgroup\bgroup
  \let\elabelgroup\egroup

\fi

\newconditional\firstMPgraphic \settrue\firstMPgraphic

\appendtoks
  \let \# \letterhash
  \let \_ \letterunderscore
  \let \& \letterampersand
  \let \{ \letteropenbrace
  \let \} \letterclosebrace
\to \everyMPgraphic

%D Not the best place but we need to make sure that no funny
%D active characters creep in. Some day we will move this code.

\ifx\disablediscretionaries\undefined
  \let\disablediscretionaries\relax
\fi

\appendtoks
  \disablediscretionaries
\to \everyMPgraphic

\def\writeMPgraph
  {\immediate\write\MPwrite{mpgraph:=\the\currentMPgraphic;}}

\def\startwritingMPgraphic
  {\blabelgroup
   \global\advance\nofMPgraphics \plusone
   \ifMPrun \else
     \allocateMPslot\currentMPgraphic
   \fi
   \enableincludeMPgraphics
   \xdef\MPgraphic{\the\currentMPgraphic}%
   \the\everyMPgraphic
   \presetMPdefinitions % moved to here from \writeMPgraphic
   \ifrunMPgraphics
     \openMPgraphicfile1{runtime}%
     % no reset here !
     \theMPextensions
     \theMPinclusions
   \else
     \openMPgraphicfile0{collected}%
     % reset here ! global added (due to adding \blabelgroup)
     \theMPextensions
     \theMPinclusions
     \global\let\theMPextensions\relax
     \global\let\theMPinclusions\relax
   \fi
   \theMPinitializations % always
   \ifMPrun
   \else
     \ifMPwrapper
       \immediate\write\MPwrite{let mprunend = end ;}%
       \immediate\write\MPwrite{beginfig(\the\currentMPgraphic);}%
     \fi
   \fi
   \globallet\flushMPgraphics\closeMPgraphicfiles % \dodostopwritingMPgraphic
   \globallet\stopwritingMPgraphic\dostopwritingMPgraphic}

\let\MPgraphicfiles\empty

\let\MPinputtranslation\empty

\def\openMPgraphicfile#1#2% #1=alwaysopen #2=message
  {\@EA\ifx\csname\@@MPG\@@MPG\MPgraphicfile\endcsname\relax
     \donetrue
     % \@EA\newwrite\csname\@@MPG\@@MPG\MPgraphicfile\endcsname
     % for the sake of plain usage
     \@EA\@EA\csname newwrite\endcsname\csname\@@MPG\@@MPG\MPgraphicfile\endcsname
     \doglobal\addtocommalist\MPgraphicfile\MPgraphicfiles
   \else
     \ifcase#1\relax\donefalse\else\donetrue\fi
   \fi
   \@EA\let\@EA\MPwrite\csname\@@MPG\@@MPG\MPgraphicfile\endcsname
   \ifdone
     \immediate\openout\MPwrite\MPgraphicfile.mp\relax
     \ifx\MPinputtranslation\empty\else
       \immediate\write\MPwrite{\MPinputtranslation}%
       \immediate\write\MPwrite{verbatimtex \MPinputtranslation etex ;}%
     \fi
     \immediate\write\MPwrite{\letterpercent\space #2 graphics of job "\jobname"}%
     \writeMPgraph
     \setMPrandomseed
   \fi}

\def\dostopwritingMPgraphic
  {\ifMPrun \else
     \ifMPwrapper
       \immediate\write\MPwrite{endfig;}%
       \immediate\write\MPwrite{let end=mprunend;}%
     \fi
   \fi
   \ifrunMPgraphics
     \dodostopwritingMPgraphic
   \fi
   \elabelgroup}

\def\dodostopwritingMPgraphic
  {\ifnum\currentMPgraphic>\zerocount
     \donetrue
   \else\ifMPrun
     \donetrue
   \else
     \donefalse
   \fi\fi
   \ifdone
     \finishwritingMPgraphics
     \runMPgraphic\MPgraphicfile
   \fi
   \globallet\flushMPgraphics\relax}

\def\finishwritingMPgraphics
  {\ifMPwrapper\immediate\write\MPwrite{end.}\fi
   \immediate\closeout\MPwrite}

\def\closeMPgraphicfiles
  {\ifrunMPgraphics \else \ifx\MPgraphicsfiles\empty\else
     \def\docommand##1%
       {\message{[flush and process ##1.mp afterwards]}%
        \@EA\let\@EA\MPwrite\csname\@@MPG\@@MPG##1\endcsname
        \finishwritingMPgraphics}%
     \processcommacommand[\MPgraphicfiles]\docommand
   \fi \fi}

\let\stopwritingMPgraphic\relax
\let\flushMPgraphics     \relax

%D By default each graphic gets its own slot (number). Later
%D on we will define a recycle bin.

\def  \allocateMPslot#1{\global\advance#1\plusone}
\def\deallocateMPslot#1{}

%D \macros
%D   {translateMPinput}
%D
%D For my polish friends:
%D
%D \starttyping
%D % translate=il2-pl
%D
%D \translateMPinput{il2-pl}
%D
%D \startMPenvironment[global]
%D   \setupbodyfont[plr]
%D \stopMPenvironment
%D
%D \TeX: ± ¶
%D
%D \startMPcode
%D draw btex MetaPost: ± ¶ etex scaled 5 ;
%D \stopMPcode
%D \stoptyping

\def\translateMPinput#1%
% {\xdef\MPinputtranslation{\letterpercent -translate-file=#1\space}} % at some point
% {\xdef\MPinputtranslation{\letterpercent --8bit}}                   % some time later
  {\globallet\MPinputtranslation\empty}                               % the new mpost is 8 bit clean

%D \macros
%D   {setMPrandomseed}
%D
%D Did you notice the random seed initialization? This is
%D needed because \METAPOST\ has a rather poor initialization,
%D which in some implementations depends on the time in
%D minutes. So, in quick successive runs, random is not that
%D random.

\newif\ifsetMPrandomseed \setMPrandomseedtrue % false by default

\def\setMPrandomseed
  {\ifsetMPrandomseed \ifx\getrandomnumber\undefined \else
     \getrandomnumber\localMPseed\zerocount{4095}%
     \writeMPgraphic{randomseed:=\localMPseed;}%
   \fi\fi}

%D This feature has become optional. Thanks to Fabrice Popineau,
%D \METAPOST\ can now do a far better job!

%D \macros
%D   {flushMPgraphics}
%D
%D When we use the indirect method, all graphics are saved in
%D one file. This means that we cannot close this file after
%D every \type{\stopMPgraphic}. Therefore we need to say:
%D
%D \starttyping
%D \flushMPgraphics
%D \stoptyping
%D
%D else the file is closed without writing the \METAPOST\ end
%D command. One will notice this fast enough when in indirect
%D mode. When using the direct mode this command is not
%D implicitly needed, but ommiting it makes files less
%D portable.

%D \macros
%D   {loadcurrentMPgraphic,
%D    placeMPgraphic}
%D
%D Once defined, we can call for this graphic by saying:
%D
%D \starttyping
%D \loadcurrentMPgraphic{setups}
%D \placeMPgraphic
%D \stoptyping
%D
%D This two stage insert permits some intermediate manipulations
%D of the graphic, which temporary saved in:

\newbox\MPgraphicbox

\def\doloadcurrentMPgraphic#1%
  {\loadMPgraphic{\MPgraphicfile.\the\currentMPgraphic}{#1}%
   \deallocateMPslot\currentMPgraphic} % added

\ifCONTEXT
  \def\loadcurrentMPgraphic{\dosinglegroupempty\doloadcurrentMPgraphic}
\else
  \let\loadcurrentMPgraphic\doloadcurrentMPgraphic
\fi

\def\loadMPgraphic#1#2%
  {\setbox\MPgraphicbox\hbox{\ifinsertMPgraphics\insertMPfile{#1}{#2}\fi}}

\def\MPllx{0}
\def\MPlly{0}

% \def\placeMPgraphic%
%  {\ifMPshiftdrawing
%     \hbox{\hskip\MPllx\onebasepoint\raise\MPlly\onebasepoint\box\MPgraphicbox}%
%   \else
%     \box\MPgraphicbox
%   \fi}
%
% experimental:

\def\placeMPgraphic
  {\ifMPshiftdrawing
     \edef\next
       {\wd\MPgraphicbox\the\wd\MPgraphicbox
        \ht\MPgraphicbox\the\ht\MPgraphicbox
        \dp\MPgraphicbox\the\dp\MPgraphicbox}%
     \setbox\MPgraphicbox\hbox
       {\hskip\MPllx\onebasepoint\raise\MPlly\onebasepoint\box\MPgraphicbox}%
     \next
   \fi
   \box\MPgraphicbox}

%D \macros
%D   {startreusableMPgraphic, reuseMPgraphic, useMPbox}
%D
%D One can use the next macro for defining graphics that are
%D to be reused. When the next switch is set, graphics are
%D cached.

\newif\ifuseMPbox  \useMPboxtrue

%D We assume that one can set objects:
%D
%D \starttyping
%D \def\douseMPbox#1%
%D   {\setobject{MP}{#1}\vbox
%D      {\forgetall
%D       \loadMPgraphic{\MPgraphicfile.\the\currentMPgraphic}{}%
%D       \deallocateMPslot\currentMPgraphic
%D       \placeMPgraphic}%
%D    \setgvalue{#1}{\getobject{MP}{#1}}}
%D \stoptyping
%D
%D More safe is to use a number for \type {{MP}{#1}} which permits
%D redefinition. We also saves the boundingbox. This helps positioning
%D reused graphics in layers.

\newcount\MPobjectcounter

\ifx\getobject\undefined \def\setobject#1#2{\setbox\scratchbox} \fi % makes dep check happy
\ifx\getobject\undefined \def\getobject#1#2{\box   \scratchbox} \fi % makes dep check happy

\def\douseMPbox#1%
  {\global\advance\MPobjectcounter\plusone
   \setobject{MP}{\number\MPobjectcounter}\vbox
     {\forgetall
      \loadMPgraphic{\MPgraphicfile.\the\currentMPgraphic}{}%
      \deallocateMPslot\currentMPgraphic
      \placeMPgraphic}%
   \setxvalue{#1}%
     {\noexpand\dodouseMPbox{\number\MPobjectcounter}{\MPllx}{\MPlly}{\MPurx}{\MPury}}}

\def\dodouseMPbox#1#2#3#4#5% space delimiting would save some tokens
  {\xdef\MPllx{#2}%          but it's not worth the effort and looks
   \xdef\MPlly{#3}%          ugly as well
   \xdef\MPurx{#4}%
   \xdef\MPury{#5}%
   \getobject{MP}{#1}}

\def\nouseMPbox#1%
  {\setxvalue{#1}%
     {\noexpand\forgetall
      \noexpand\loadMPgraphic{\MPgraphicfile.\the\currentMPgraphic}{}%
      \noexpand\deallocateMPslot{\currentMPgraphic}%
      \noexpand\placeMPgraphic}}

\ifCONTEXT \else \let\douseMPbox\nouseMPbox          \fi
\ifCONTEXT \else \let\doifobjectssupportedelse\relax \fi

\long\def\handlereusableMPgraphic#1#2%
  {\blabelgroup
   \enableincludeMPgraphics
   \startMPgraphic#2\stopMPgraphic
   \doifobjectssupportedelse\donothing\useMPboxfalse
   \ifuseMPbox
     \expandafter \douseMPbox
   \else
     \expandafter \nouseMPbox
   \fi {\@@MPG#1}%
   \getvalue{\@@MPG#1}%
   \elabelgroup}

% \long\def\startreusableMPgraphic#1#2\stopreusableMPgraphic
%   {\ifundefined{\@@MPG#1}%
%      \long\setgvalue{\@@MPG#1}{\handlereusableMPgraphic{#1}{#2}}%
%    \fi}

\long\def\dostartreusableMPgraphic#1#2\stopreusableMPgraphic
  {\blabelgroup
   \long\setgvalue{\@@MPG#1}{\handlereusableMPgraphic{#1}{#2}}%
   \elabelgroup}

\def\reuseMPgraphic#1%
  {\blabelgroup
   \getvalue{\@@MPG#1}%
   \elabelgroup}

\let\stopreusableMPgraphic \relax % so that we can use it in \expanded

%D \macros
%D   {startuseMPgraphic,useMPgraphic}
%D
%D The every||time||it's||used original one is defined below.
%D This one makes sense when the graphic uses random numbers.
%D
%D We can run (process graphic) without including them at that
%D particular place. Therefore we explicitly disable
%D inclusions (resulting in an dummy figure) when we are in MP
%D run mode (see mfun-004 for an example, we process an
%D example buffer which produced graphics).

\long\def\handleuseMPgraphic#1#2%
  {\bgroup
   \enableincludeMPgraphics
   \startMPgraphic#2\stopMPgraphic
   \ifMPrun \else
     \loadMPgraphic{\MPgraphicfile.\the\currentMPgraphic}{}%
     \placeMPgraphic
   \fi
   \deallocateMPslot\currentMPgraphic
   \egroup}

\long\def\startuseMPgraphic
  {\blabelgroup
   \obeyMPlines
   \dostartuseMPgraphic}

\long\def\dostartuseMPgraphic#1#2\stopuseMPgraphic
  {\long\setgvalue{\@@MPG#1}{\handleuseMPgraphic{#1}{#2}}%
   \elabelgroup}

\long\def\startusableMPgraphic
  {\blabelgroup
   \obeyMPlines
   \dostartusableMPgraphic}

\long\def\dostartusableMPgraphic#1#2\stopusableMPgraphic
  {\long\setgvalue{\@@MPG#1}{\handleuseMPgraphic{#1}{#2}}%
   \elabelgroup}

\let\useMPgraphic\reuseMPgraphic

\let\stopuseMPgraphic    \relax % so that we can use it in \expanded
\let\stopusableMPgraphic \relax % so that we can use it in \expanded

%D \macros
%D   {doifMPgraphicelse}
%D
%D For (mainly internal) purposes we provide a test macro.

% \def\doifMPgraphicelse#1%
%   {\doifdefinedelse{\@@MPG#1}}

\def\doifMPgraphicelse#1%
  {\blabelgroup
   \doifdefinedelse{\@@MPG#1}%
     {\elabelgroup\firstoftwoarguments}
     {\elabelgroup\secondoftwoarguments}}

%D \macros
%D   {includeMPgraphic}
%D
%D In a graphic one can call up another (predefined one)
%D like:
%D
%D \starttyping
%D \startuseMPgraphic{a}
%D   fill fullcircle scaled 100 ;
%D \stopuseMPgraphic
%D
%D \startuseMPgraphic{b}
%D   \includeMPgraphic{a}
%D   fill fullsquare rotated 45 scaled 50 withcolor red ;
%D \stopuseMPgraphic
%D
%D \useMPgraphic{b}
%D \stoptyping

\def\includeMPgraphic#1%
  {\executeifdefined{\@@MPG#1};} % ; if not found

\def\enableincludeMPgraphics
  {\let\handleuseMPgraphic     \secondoftwoarguments
   \let\handlereusableMPgraphic\secondoftwoarguments}

%D We didn't yet define the macro responsible for processing
%D the graphic from within \TEX.

\def\runMPgraphic#1%
  {\ifrunMPgraphics
     \executeMETAPOST{#1}%
   \else
     % \message{[flush and process \MPgraphicfile.mp afterwards]}%
   \fi}

%D \macros
%D   {useMETAFUNformat}
%D
%D For faster running, one can generate a format, saying
%D
%D \starttyping
%D mpost -ini context
%D \stoptyping
%D
%D (The resulting \type {mem} file should be moved to the
%D right location. Watch out for misatching \type {progname}
%D directives, since they can clutter memory.

\newif\ifuseMETAFUNformat

%D \macros
%D   {executeMetaPost, executeMETAPOST, executesystemcommand}
%D
%D With \type{\executeMETAPOST} being defined as:

\ifx\undefined\executeMETAPOST
  \def\executeMETAPOST#1{\executesystemcommand{\executeMetaPost{#1}}}
\fi

%D There are two system dependant definitions:

\ifx\undefined\executesystemcommand
  \def\executesystemcommand#1{\immediate\write18{#1}}
\fi

\ifx\TEXEXECcommand \undefined \def\TEXEXECcommand{texmfstart texexec} \fi

\ifx\undefined\executeMetaPost

  \ifx\undefined\interactionmode \chardef\interactionmode=255 \fi

  \def\MPOSTbatchswitch   {-interaction=batchmode}   % was -int, but newer mpost does not support partial flags
  \def\MPOSTnonstopswitch {-interaction=nonstopmode} % was -int, but newer mpost does not support partial flags
  \def\MPOSTformatswitch  {-progname=metafun -mem=}
  \def\MPOSTdriver        {dvips}

  \def\executeMPOST#1% direct call
    {mpost
      \ifcase\interactionmode\MPOSTbatchswitch\or\MPOSTnonstopswitch\fi
      \space\ifuseMETAFUNformat \MPOSTformatswitch metafun \fi #1}

  \def\executeMPTEX#1% slower, due to nested texexec call
    {\TEXEXECcommand\space
       --batch \ifcase\interactionmode --logfile='mptex.log' \fi
       --output=\MPOSTdriver\space
       \ifuseMETAFUNformat --mpformat=metafun \fi --mptex --nomp --once #1}

  \def\executeMetaPost
    {\ifrunMPTEXgraphics
       \ifMPTEXgraphic
         \@EAEAEA\executeMPTEX
       \else
         \@EAEAEA\executeMPOST
       \fi
     \else
       \@EA\executeMPOST
     \fi}

\fi

%D The batchmode and nonstopmode (introduced in 2003 for
%D Patrick Gundlach) switches may differ per binary and are
%D supported by \TEXEXEC.

%D \macros
%D   {insertMPfile}
%D
%D One can define this command in advance or redefine it after
%D loading this module. The same goes for the forward
%D reference to the figure loading macro:

\ifx\undefined\insertMPfile

  \def\insertMPfile#1#2%
    {\ifx\undefined\externalfigure
       \message{[insert file #1 here]}%
     \else
       \externalfigure
         [#1]
         [\c!type=\c!mps,\c!object=\v!no,
          \c!symbol=\v!yes,\c!reset=\v!yes,
          \c!maxwidth=,\c!maxheight=,
          \c!frame=\v!off,\c!background=,
          #2]%
     \fi}

\fi

%D This macro takes {\em two} arguments, the second one can be
%D used to pass info to the inclusion macro. Some examples
%D of its use can be found in the modules \type{supp-tpi} and
%D \type{prag-log}.

%D This module can be used in \PLAIN\ \TEX too. When using
%D \DVIPS, just try to process:
%D
%D \starttyping
%D \input supp-mps
%D
%D \runMPgraphicstrue
%D
%D \def\insertMPfile#1#2%
%D   {\special{psfile=#1}}
%D
%D \startuseMPgraphic{1}
%D   prologues := 1;
%D   draw (0,0) withpen pencircle scaled 100;
%D \stopuseMPgraphic
%D
%D \useMPgraphic{1}
%D \stoptyping
%D
%D Don't forget to enable \type{\write18}. When does not say
%D \type{\runMPgraphicstrue}, the \METAPOST\ scratch file
%D must be closed by saying
%D
%D \starttyping
%D \flushMPgraphics
%D \stoptyping
%D
%D When using the indirect method, one has to process the file
%D \type{mpgraph.mp} between two successive \TEX\ runs.
%D
%D \METAPOST\ needs the public domain \DVI\ to \POSTSCRIPT\
%D converter \DVIPS. This symbiosis originates in the need to
%D include the fonts (glyphs) that \METAPOST\ uses in the
%D \POSTSCRIPT\ file. Driver independancy was one of my
%D prerequisites for using \METAPOST, so I decided to build
%D this kind of support myself. Personally I consider driver
%D dependancy a drawback for the dissemination of such a
%D package. The second part of this module more or less
%D decouples \METAPOST\ and \DVIPS.
%D
%D The macros hereafter are copied from the module
%D \type{m-metapost}. After writing module \type{supp-pdf} I
%D added this method to the module named and after a while
%D decided to hook it into module \type{spec-yy}. Therefore
%D they made it into a support module, but in a slightly
%D different way.

%D \macros
%D   {includeMPfonts, ifincludeMPfonts}
%D
%D The method we use is both robust and simple: one can do
%D with calling the next macro with the filename as argument:
%D
%D \starttyping
%D \includeMPfonts{filename}
%D \stoptyping
%D
%D We can turn of this mechanism with:
%D
%D \starttyping
%D \includeMPfontsfalse
%D \stoptyping
%D
%D {\em Currently this method fails for situations where the
%D font definition is not on one line, which is he case when
%D unkerned fonts are used along with long lines. One solution
%D for this is to increase the value of \type {max_print_line}
%D in \type {texmf.cnf}.}}

\newif\ifincludeMPfonts \includeMPfontstrue

\def\includeMPfonts#1%
  {\ifincludeMPfonts
     \bgroup
     \message{[MP fonts #1]}%
     %\uncatcodespecials
     \endlinechar\minusone
     \setMPspecials
     \obeyMPspecials
     \setbox\scratchbox\hbox
       {\hskip-\maxdimen
        \doprocessfile\scratchread{#1}\handleMPfont}%
     \smashbox\scratchbox
     \box\scratchbox
     \egroup
   \fi}

\def\UseMetaPostGraphic      {\includeMPfonts}      % upward compatible
\def\DontUseMetaPostGraphics {\includeMPfontsfalse} % upward compatible

%D The characters are collected in a box and moved as far as
%D possible into the left margin. The resulting box has no
%D dimensions and can be prepended (appended) to the special
%D that handles the inclusion. The characters are in the file
%D but made invisible.
%D
%D In \CONTEXT\ font handling is intergrated in the figure
%D inclusion macros. A decent plain \TEX\ alternative is:
%D
%D \starttyping
%D \def\includeMPgraphic#1%
%D   {\hbox\bgroup
%D    \includeMPfonts{#1}%
%D    \dogetEPSboundingbox{#1}{\dimen2}{\dimen4}{\dimen6}{\dimen8}%
%D    \advance\dimen6 by -\dimen2
%D    \advance\dimen8 by -\dimen4
%D    \vbox to \dimen8
%D      {\forgetall
%D       \vfill
%D       \hsize\dimen6
%D       \special
%D         {PSfile="#1"\space
%D          llx=\EPSllx\space
%D          lly=\EPSlly\space
%D          urx=\EPSurx\space
%D          ury=\EPSury\space}}%
%D    \egroup}
%D \stoptyping
%D
%D This macro needs \type {supp-eps.tex} and provided no
%D scaling. For \LATEX\ users the next one will do:
%D
%D \starttyping
%D \def\includeMPgraphic#1#%
%D   {\hbox\bgroup
%D    \def\includeMPgraphics##1%
%D      {\includeMPfonts{##1}%
%D       \includegraphics[typetype=mps,#1]{##1}%  or whatever type they use
%D       \egroup}%
%D    \includeMPgraphics}
%D \stoptyping

%D We scan the graphics file for the \type{fshow} operator,
%D that is, lines that start with \type{(}. If found it
%D interprets the line, which looks like:
%D
%D \starttyping
%D (string ... string) font size fshow
%D \stoptyping
%D
%D Font definitions specified in the preamble are simply
%D ignored. Only lines starting with \type{(} are interpreted.

\def\dohandleMPfont#1#2\relax
  {\if#1(\expandafter\includeMPcharacters\fileline\relax\fi}

\def\handleMPfont
  {\expandafter\dohandleMPfont\fileline\relax}

%D Before we start scanning for data, we first change some
%D \CATCODES. The first set of macro's is copied from module
%D \type{supp-pdf}. This scheme is a bit overdone for this
%D module, but using the same macros saves us some memory.

\def\octalMPcharacter#1#2#3%
  {\char'#1#2#3\relax}

\bgroup
\catcode`\|=\@@comment
\catcode`\%=\@@active
\catcode`\[=\@@active
\catcode`\]=\@@active
\catcode`\{=\@@active
\catcode`\}=\@@active
\catcode`B=\@@begingroup
\catcode`E=\@@endgroup
\gdef\keepMPspecials|
  B\let%\letterpercent|
   \def[B\noexpand[E|
   \def]B\noexpand]E|
   \def{B\noexpand{E|
   \def}B\noexpand}EE
\gdef\ignoreMPspecials|
  B\let%\letterpercent|
   \def[BE|
   \def]BE|
   \def{BE|
   \def}BEE
\gdef\obeyMPspecials|
  B\def%B\char 37\relax E|
   \def[B\char 91\relax E|
   \def]B\char 93\relax E|
   \def{B\char123\relax E|
   \def}B\char125\relax EE
\gdef\setMPspecials|
  B\setnaturalcatcodes
   \catcode`\\=\@@escape
   \catcode`\%=\@@active
   \catcode`\[=\@@active
   \catcode`\]=\@@active
   \catcode`\{=\@@active
   \catcode`\}=\@@active
   \lccode`\-=0 | latex sets this to `\-
   \lccode`\%=`\% | otherwise it's seen as a number
   \def\(B\char40\relax     E|
   \def\)B\char41\relax     E|
   \def\\B\char92\relax     E|
   \def\0B\octalMPcharacter0E|
   \def\1B\octalMPcharacter1E|
   \def\2B\octalMPcharacter2E|
   \def\3B\octalMPcharacter3E|
   \def\4B\octalMPcharacter4E|
   \def\5B\octalMPcharacter5E|
   \def\6B\octalMPcharacter6E|
   \def\7B\octalMPcharacter7E|
   \def\8B\octalMPcharacter8E|
   \def\9B\octalMPcharacter9EE
\egroup

%D The lines starting with \type{(} are interpreted and
%D handled by
%D
%D \starttyping
%D \def\includeMPcharacters(#1) #2 #3 #4\relax%
%D   {\font\temp=#2 at #3bp\temp#1}
%D \stoptyping
%D
%D While processing some \TUG~98 proceedings, I also had to
%D deal with:
%D
%D \starttyping
%D /nfont {10 div dup scale 10} def
%D (T) ANTTB 7.13086 nfont fshow
%D \stoptyping
%D
%D which comes to rounding sizes. This is something
%D experimental. (The macro in supp-pdf.tex is more
%D advanced.)

\def\PSnfont{nfont}

\def\includeMPcharacters(#1) #2 #3 #4#5#6#7#8#9\relax
  {\edef\temp{#4#5#6#7#8}%
   \ifx\temp\PSnfont % round font size (to pt)
     \scratchdimen#3\onepoint
     \ifdim\scratchdimen<\onepoint
       \def\size{1pt}%
     \else
       \advance\scratchdimen .5\onepoint
       \def\size##1.##2\relax{\def\size{##1pt}}%
       \expandafter\size\the\scratchdimen\relax
     \fi
   \else
     \edef\size{#3bp}%
   \fi
   \font\temp=#2 at \size
   \temp\if#1 \char32\else#1\fi}

%D This method is both robust and reasonable fast. The only
%D disadvantage is that when not embedded properly in the
%D graphics inclusion macros, one has to load all graphics by
%D hand.

%D Now let's see if things work all right and show the example
%D files that are part of the \METAPOST\ distribution:
%D
%D \setupexternalfigures[directory={../sample}]
%D \startlinecorrection
%D \setupalign[middle]
%D \leavevmode
%D \startcombination[3*3]
%D   {\externalfigure[mp-exa-1][frame=on,width=.2\hsize]} {}
%D   {\externalfigure[mp-exa-2][frame=on,width=.2\hsize]} {}
%D   {\externalfigure[mp-exa-3][frame=on,width=.2\hsize]} {}
%D   {\externalfigure[mp-exa-4][frame=on,width=.2\hsize]} {}
%D   {\externalfigure[mp-exa-5][frame=on,width=.2\hsize]} {}
%D   {\externalfigure[mp-exa-6][frame=on,width=.2\hsize]} {}
%D   {\externalfigure[mp-exa-7][frame=on,width=.2\hsize]} {}
%D   {\externalfigure[mp-exa-8][frame=on,width=.2\hsize]} {}
%D   {\externalfigure[mp-exa-9][frame=on,width=.2\hsize]} {}
%D \stopcombination
%D \stoplinecorrection
%D
%D Here we used calls like:
%D
%D \starttyping
%D \externalfigure[mp-exa-1][methode-mps,frame=on,width=.2\hsize]
%D \stoptyping

%D \macros
%D   {convertMPcolors,
%D    ifconvertMPcolors,ifreduceMPcolors,ifforceMPcolors}
%D
%D When I told the editors that I wanted to use colored
%D \METAPOST\ graphics in the color issue of the \MAPS, I was
%D asked to use the \cap{CMYK} colorspace instead of \cap{RGB}
%D one. However, \METAPOST\ only supports \cap{RGB} colors. I
%D decided to write a utility to convert the \type
%D {setrgbcolor} operators into \type {setcmykcolor} ones, and
%D some experiments showed me that I could best let \TEX\ do it
%D itself. Here it is:
%D
%D There are two booleans that control the conversion process.
%D These are false by default.

\newif\ifconvertMPcolors
\newif\ifreduceMPcolors
\newif\ifforcegrayMPcolors

%D The main macro is called as:
%D
%D \starttyping
%D \convertMPcolors{filename}
%D \stoptyping
%D
%D When active, this macro returns a message saying if indeed
%D conversion took place. The old file is overwritten! This
%D saves time in a succesive passes and can't harm, simply
%D because MP can generate them anew.

\def\convertMPcolorpath{}
\def\convertMPcolorfile{metacmyk.tmp}

\def\convertMPcolors#1% todo: open on local path, no copy
  {\bgroup
   \ifforcegrayMPcolors
     \donetrue
   \else\ifconvertMPcolors
     \donetrue
   \else
     \donefalse
   \fi\fi
   \ifdone
     \message{[MP color conversion #1}%
     \endlinechar\minusone
     \uncatcodespecials
     \donefalse
     \immediate\openout\scratchwrite\convertMPcolorpath\convertMPcolorfile\relax
     \doprocessfile\scratchread{#1}\handleMPcolor
     \immediate\closeout\scratchwrite
     \ifdone
       \immediate\openout\scratchwrite\convertMPcolorpath#1\relax
       \doprocessfile\scratchread{\convertMPcolorpath \convertMPcolorfile}\handleMPcopy
       \immediate\closeout\scratchwrite
       \message{done]}%
     \else
       \message{not needed]}%
     \fi
     \immediate\openout\scratchwrite\convertMPcolorpath\convertMPcolorfile
     \immediate\closeout\scratchwrite
   \fi
   \egroup}

%D The process is rather simple: read a line, look for the
%D \type {setrgbcolor} operator, recalculate the components and
%D check for gray reduction or black removal, write the result
%D to a temporary file, and go on. Afterwards, the file is
%D copied back. We don't have to reduce to gray scales;
%D \METAPOST\ already takes care of that.

%D The next macro is needed for forced conversion. This macro
%D is copied from \type{colo-ini}, just in case one uses this
%D module outside \CONTEXT.

\ifx\@@cl@@s         \undefined \def\@@cl@@s{0} \fi

\ifx\convertRGBtoGRAY\undefined

\def\convertRGBtoGRAY#1#2#3%
  {\scratchdimen#1\onepoint
   \scratchdimen300\scratchdimen
   \scratchcounter\scratchdimen
   \scratchdimen#2\onepoint
   \scratchdimen590\scratchdimen
   \advance\scratchcounter \scratchdimen
   \scratchdimen#3\onepoint
   \scratchdimen110\scratchdimen
   \advance\scratchcounter \scratchdimen
   \advance\scratchcounter \!!medcard
   \divide\scratchcounter \!!maxcard
   \edef\@@cl@@s{\realcolorvalue\scratchcounter}}

\fi

%D BTW, this code is quite old, and not as complete as the
%D \PDF\ converter, which also handles spot colors and so.

\def\handleMPcolor
  {\expandafter\dohandleMPcolor\fileline setrgbcolor*\\}

\def\dohandleMPcolor#1setrgbcolor#2#3\\%
  {\if#2*%
     \immediate\write\scratchwrite{#1}%
   \else
     \dodohandleMPcolor#1setrgbcolor#2#3\\%
   \fi}

\def\dodohandleMPcolor#1 #2 #3setrgbcolor#4setrgbcolor*\\% old and maybe broke
  {\bgroup
   \ifdim#1pt=.123pt
     \immediate\write\scratchwrite{#1 #2 #3 setrgbcolor}%
   \else
     \ifforcegrayMPcolors
       \convertRGBtoGRAY{#1}{#2}{#3}%
       \immediate\write\scratchwrite
         {\@@cl@@s \space setgray #4}%
     \else
       \dimen0=\onepoint \advance\dimen0 -#1\points
       \dimen2=\onepoint \advance\dimen2 -#2\points
       \dimen4=\onepoint \advance\dimen4 -#3\points
       \ifreduceMPcolors
         \dimen6\dimen0
         \ifdim\dimen2<\dimen6 \dimen6\dimen2 \fi
         \ifdim\dimen4<\dimen6 \dimen6\dimen4 \fi
         \advance\dimen0 -\dimen6
         \advance\dimen2 -\dimen6
         \advance\dimen4 -\dimen6
       \else
         \dimen6\zeropoint
       \fi
       \immediate\write\scratchwrite
         {\withoutpt\the\dimen0 \space
          \withoutpt\the\dimen2 \space
          \withoutpt\the\dimen4 \space
          \withoutpt\the\dimen6 \space setcmykcolor #4}%
     \fi
   \fi
   \egroup
   \donetrue} % needed for message

\def\handleMPcopy
  {\immediate\write\scratchwrite{\fileline}}

%D The next examples show the color conversion macros in
%D action. These examples also demonstrate in||text \METAPOST\
%D handling. As we will see, the conversion is hooked into the
%D \CONTEXT\ color mechanism.
%D
%D By setting both \type{rgb} and \type{cmyk} to off, we force
%D conversion to gray scales using:
%D
%D \placeformula[-]
%D   \startformula
%D   G = .30r + .59g + .11b
%D   \stopformula
%D
%D By using buffers, we keep the \ASCII\ layout clean:
%D
%D \startbuffer
%D \startbuffer[rgb]
%D   \setupcolors[rgb=ja,cmyk=nee,reduction=no,conversion=no]
%D   \useMPgraphic{hans}
%D \stopbuffer
%D
%D \startbuffer[cmyk]
%D   \setupcolors[rgb=nee,cmyk=ja,reduction=no,conversion=no]
%D   \useMPgraphic{hans}
%D \stopbuffer
%D
%D \startbuffer[cmy]
%D   \setupcolors[rgb=nee,cmyk=ja,reduction=yes,conversion=no]
%D   \useMPgraphic{hans}
%D \stopbuffer
%D
%D \startbuffer[gray]
%D   \setupcolors[rgb=nee,cmyk=nee,reduction=no,conversion=no]
%D   \useMPgraphic{hans}
%D \stopbuffer
%D \stopbuffer
%D
%D \typebuffer
%D \getbuffer
%D
%D The graphic is rather simple and is generated each time
%D it's called:
%D
%D \global\runMPgraphicstrue
%D
%D \startbuffer
%D \startbuffer[graphic]
%D   \startuseMPgraphic{hans}
%D     width  :=\the\textwidth/5;
%D     height := width/4;
%D     fill fullcircle
%D       xscaled width
%D       yscaled height
%D       withcolor (\RedGreenBlue);
%D   \stopuseMPgraphic
%D \stopbuffer
%D \stopbuffer
%D
%D \typebuffer
%D \getbuffer
%D
%D Next we combine the four alternative interpretations in a
%D combination:
%D
%D \startbuffer
%D \startbuffer[result]
%D   \startcombination[4]
%D     {\getbuffer[rgb]}  {\tfxx original}
%D     {\getbuffer[cmyk]} {\ttxx\string\convertMPcolorstrue}
%D     {\getbuffer[cmy]}  {\ttxx\string\reduceMPcolorstrue}
%D     {\getbuffer[gray]} {\ttxx\string\forcegrayMPcolorstrue}
%D   \stopcombination
%D \stopbuffer
%D \stopbuffer
%D
%D \typebuffer
%D \getbuffer
%D
%D Finally we call the buffers, using different setting:
%D
%D \startbuffer
%D \placefigure
%D   {\METAPOST\ color conversions}
%D   {\def\RedGreenBlue{.1,.4,.6}\getbuffer[graphic]\getbuffer[result]\vskip6pt
%D    \def\RedGreenBlue{.1,.6,.4}\getbuffer[graphic]\getbuffer[result]\vskip6pt
%D    \def\RedGreenBlue{.4,.1,.6}\getbuffer[graphic]\getbuffer[result]\vskip6pt
%D    \def\RedGreenBlue{.4,.6,.1}\getbuffer[graphic]\getbuffer[result]\vskip6pt
%D    \def\RedGreenBlue{.6,.1,.4}\getbuffer[graphic]\getbuffer[result]\vskip6pt
%D    \def\RedGreenBlue{.6,.4,.1}\getbuffer[graphic]\getbuffer[result]}
%D \stopbuffer
%D
%D \typebuffer
%D \getbuffer
%D
%D By the way, when the \POSTSCRIPT\ file resulting from
%D this input is converted into \PDF\ and viewed in Acrobat
%D Reader, one can quite different colors from those
%D displayed in \GHOSTSCRIPT, which view equals the
%D \POSTSCRIPT\ originals.

%D \macros
%D   {experimental}
%D
%D Some experimental macros:
%D
%D \starttyping
%D \startMPdrawing
%D \stopMPdrawing
%D \pushMPdrawing
%D \popMPdrawing
%D \resetMPdrawing
%D \ifMPdrawingdone
%D \getMPdrawing
%D \MPdivten[number]
%D \stoptyping
%D
%D These macros are used in \PPCHTEX.

\let\MPdrawingdata\empty

\newif\ifMPdrawingdone  \MPdrawingdonefalse
\newif\ifMPshiftdrawing \MPshiftdrawingfalse

\def\resetMPdrawing
  {\globallet\MPdrawingdata\empty
   \global\MPdrawingdonefalse}

% why global push/pop here?

\def\pushMPdrawing
  {\globalpushmacro\MPdrawingdata
   \globallet\MPdrawingdata\empty}

\def\popMPdrawing
  {\globalpopmacro\MPdrawingdata}

\def\getMPdrawing
  {\ifMPdrawingdone
     \expandafter\startMPgraphic\MPdrawingdata\stopMPgraphic
     \loadcurrentMPgraphic{}%
     \deallocateMPslot\currentMPgraphic
     \placeMPgraphic
   \fi}

\def\startMPdrawing
  {\dosingleempty\dostartMPdrawing}

\long\def\dostartMPdrawing[#1]#2\stopMPdrawing
  {\relax
   \bgroup
   \enableincludeMPgraphics
   \presetMPdefinitions % in case #2 has measures
   \doifelse{#1}{-}{\convertargument#2\to\asciia}{\long\def\asciia{#2}}%
   \long\xdef\MPdrawingdata{\MPdrawingdata\asciia}%
   \egroup}

\let\stopMPdrawing\relax

\def\MPdivten[#1]%
  {\@EA\@EA\@EA\doMPdivten\@EA\@EA\@EA[\@EA#1]}

\def\doMPdivten[#1]%
  {\ifnum#1> 9999 \dodoMPdivtenB#1\else
   \ifnum#1>  999 \dodoMPdivtenC#1\else
   \ifnum#1>   99 \dodoMPdivtenD#1\else
   \ifnum#1>    9 \dodoMPdivtenE#1\else
   \ifnum#1>    0 \dodoMPdivtenF#1\else
   \ifnum#1<-9999 \dodoMPdivtenA#1\else
   \ifnum#1< -999 \dodoMPdivtenB#1\else
   \ifnum#1<  -99 \dodoMPdivtenC#1\else
   \ifnum#1<   -9 \dodoMPdivtenD#1\else
   \ifnum#1<    0 \dodoMPdivtenE#1\else
                0 \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi}

\def\dodoMPdivtenA#1#2#3#4#5#6{#1#2#3#4#5.#6}
\def\dodoMPdivtenB  #1#2#3#4#5{#1#2#3#4.#5}
\def\dodoMPdivtenC    #1#2#3#4{#1#2#3.#4}
\def\dodoMPdivtenD      #1#2#3{#1#2.#3}
\def\dodoMPdivtenE        #1#2{#1.#2}
\def\dodoMPdivtenF          #1{.#1}

% if we assume etex ... \def\MPdivten[#1]{\withoutpt\the\dimexpr#1pt/10\relax}

%D \macros
%D   {startMPclip,grabMPclippath}
%D
%D We can use \METAPOST\ to calculate arbitrary clipping
%D paths. Such a path is defined by (for instance):
%D
%D \starttyping
%D \startMPclip{window}
%D    clip currentpicture to fullcircle xscaled \width yscaled \height ;
%D \stopMPclip
%D \stoptyping
%D
%D Such a path can be extracted (processed) by:
%D
%D \starttyping
%D \grabMPclippath{window}{method}{width}{height}{default path}
%D \stoptyping
%D
%D Currently only method 1 makes sense; it produces \PDF\
%D code. This macro only makes sense when hooked into a
%D special routine.

\let\MPclippath\empty

\long\def\startMPclip#1#2\stopMPclip
  {\blabelgroup
   \long\setgvalue{MPC:#1}{\startMPgraphic#2\stopMPgraphic\dograbMPclippath}%
   \elabelgroup}

\let\stopMPclip\relax

\def\grabMPclippath#1#2#3#4#5%
  {\blabelgroup
   \edef\width {#3\space}\let\overlaywidth \width
   \edef\height{#4\space}\let\overlayheight\height
   \doifdefinedelse{MPC:#1}
     {\getvalue{MPC:#1}%
      \setxvalue{MPC:#1}{\noexpand\xdef\noexpand\MPclippath{\MPclippath}}}%
     {\xdef\MPclippath{#5}}%
   \ifcase#2\else % method 1 :
     \doglobal\stripcharacter urveto\from\MPclippath\to\MPclippath
     \doglobal\stripcharacter  oveto\from\MPclippath\to\MPclippath
     \doglobal\stripcharacter  ineto\from\MPclippath\to\MPclippath
   \fi
   \elabelgroup}

%D We pose some restrictions to the \METAPOST\ code and pickup
%D the clip path from the file.
%D
%D We turn the slash into a comment. The \type {\hbox} grabs spaces
%D and the \type {%} triggers the grabber. Next we filter the
%D clipping path, or actually, the first path.

% \bgroup
% \catcode`\%=\@@active
% \catcode`\/=\@@comment
% \gdef\dograbMPclippath/
%   {\setbox\scratchbox=\hbox\bgroup/
%    \catcode`\%=\@@active
%    \obeylines\let\obeyedline\space
%    \def\do##1newpath##2closepath##3\od/
%      {\xdef\MPclippath{##2}\endinput}/
%    \def%##1%%EOF/
%      {\do##1newpathclosepath\od\endinput}/
%    \readfile{\MPgraphicfile.\the\currentMPgraphic}{}{}/
%    \deallocateMPslot\currentMPgraphic / new
%    \egroup}
% \egroup

\bgroup
\catcode`\%=\@@active
\catcode`\/=\@@comment
\gdef\dograbMPclippath/
  {\setbox\scratchbox=\hbox\bgroup/
   \catcode`\%=\@@active
   \obeylines\let\obeyedline\space
   \def\do##1q n##2p W##3\od/
     {\xdef\MPclippath{##2}\endinput}/
   \def%##1%%EOF/
     {\do##1q np W\od\endinput}/
   \readfile{\MPgraphicfile.\the\currentMPgraphic}{}{}/
   \ifx\MPclippath\empty
     \def\do##1newpath##2closepath##3\od/
       {\xdef\MPclippath{##2}\endinput}/
     \def%##1%%EOF/
       {\do##1newpathclosepath\od\endinput}/
     \readfile{\MPgraphicfile.\the\currentMPgraphic}{}{}/
   \fi
   \deallocateMPslot\currentMPgraphic / new
   \egroup}
\egroup

%D \macros
%D   {recycleMPslots}
%D
%D When coding and embedding many \METAPOST\ figures in a
%D document, one can save quite some disk space by using
%D \PDFTEX\ and setting the next switch:

\newif\ifrecycleMPslots \recycleMPslotstrue

%D When a graphic takes space in the text flow, we can run
%D into deadlock typesetting. In the first pass, the graphic
%D is not available, but in the second pass it is. The
%D placeholder that was put there in the first pass in now
%D replace by the real graphic and as a result the document
%D shrinks or grows and pages are removed or added. This in
%D turn can trigger generation of other graphics, like those
%D in the background. Graphics start swapping place and again
%D page breaks change. You can imagine the mess we en dup
%D with.
%D
%D This is why we provide was to use a dedicate range if
%D numbers for fixed graphcs. Such graphics will not en dup
%D in the text flow (at least their dimensions don't
%D contribute to the main vertical list, and thereby they
%D cannot interfere. We use a rather safe maximum of 4000
%D graphics here and 8000 in \type {meta-ini}.

\newcount \maxnofMPgraphics  \maxnofMPgraphics = 4000 % 8000
\newcount \minnofMPgraphics  \minnofMPgraphics =    1

\newif    \ifMPstaticgraphic \MPstaticgraphicfalse % determines slot allocation

\def\locateMPslot#1% slightly faster on one slot, much faster on multiple slots
  {\ifundefined{\number#1MP}% no \ifcsname
     \letgvalueempty{\number#1MP}%
     \expandafter\gobbletwoarguments
   \else
     \global\advance#1\plusone
   \fi
   \locateMPslot#1}

\def\allocateMPslot#1%
  {\ifrunMPgraphics
     \ifx\pdfliteral\undefined
       \recycleMPslotsfalse % quite certainly not pdftex
     \else\ifcase\pdfoutput
       \recycleMPslotsfalse % dvi mode or not pdftex (we need to handle dvipdfmx)
     \fi\fi
   \else
     \recycleMPslotsfalse
   \fi
   \ifrecycleMPslots
   % \doloop % slow but used seldom
   %   {\doifundefined{\recurselevel MP}
   %      {\letgvalueempty{\recurselevel MP}%
   %       \global#1\recurselevel
   %       \exitloop}}%
     \global#1\plusone
     \locateMPslot#1%
   % \message{[MP slot + \number#1]%
   \else\ifMPstaticgraphic % beware not the same as static graphics
     \global#1\maxnofMPgraphics
     \global\advance\maxnofMPgraphics \minusone
   \else
     \global#1\minnofMPgraphics
     \global\advance\minnofMPgraphics \plusone
   \fi\fi
   \ifnum\minnofMPgraphics<\maxnofMPgraphics \else
     \writestatus\m!systems{increase \string\maxnofMPgraphics}%
   \fi}

\def\deallocateMPslot#1%
  {\ifrunMPgraphics
     \ifcase\pdfoutput \recycleMPslotsfalse \fi
   \else
     \recycleMPslotsfalse
   \fi
   \ifrecycleMPslots
    \global\letbeundefined{\number#1MP}%
    %\message{[MP slot - \number#1]}%
   \fi}

%D Experimental and overloaded later, since we need to be
%D more clever due to \METAPOST's limit of 4~open files.

\def\MPdatafile
  {mp-\the\currentMPgraphic.mpd}

\def\getMPdata
  {\input \MPdatafile\relax}

%D \macros
%D   {MPtoks, MPbox}
%D
%D For convenience, we provide some scratch registers:

\ifx\undefined\MPtoks \newtoks\MPtoks \fi
\ifx\undefined\MPbox  \newbox \MPbox  \fi

%D \macros
%D   {startMPcode}
%D
%D We can save some typing with:
%D
%D \starttyping
%D \startMPcode whatever \stopMPcode
%D \stoptyping
%D
%D this automatically places the graphic

\long\def\startMPcode
  {\begingroup
   \obeyMPlines
   \dostartMPcode}

\long\def\dostartMPcode#1\stopMPcode
  {\startuseMPgraphic{@@}#1\stopuseMPgraphic
   \useMPgraphic{@@}%
   \endgroup}

\let\stopMPcode\relax

%D \macros
%D   {startstaticMPgraphic}
%D
%D Dedicated to Aditya Mahajan. See meta-ini for usage.

% \long\def\startstaticMPgraphic#1#2\stopstaticMPgraphic
%   {\bgroup
%    \MPstaticgraphictrue
%    \setMPrandomseedfalse
%    \def\MPgraphicfile{#1}% no \jobname here
%    \let\allocateMPslot  \gobbleoneargument
%    \let\deallocateMPslot\gobbleoneargument
%    \let\runMPgraphic    \gobbleoneargument
%    \MPextensions\emptytoks
%    \MPinitializations\emptytoks
%    \runMPgraphicstrue
%    \MPwrapperfalse
%    \enableincludeMPgraphics
%    \def\sometxt##1{\string\sometxt{##1}}%
%    \currentMPgraphic\plusone  % hack, else no close
%    \startMPgraphic#2\stopMPgraphic
%    \executeMPgraphicfile
%    \egroup}

% different version, less messy hooked into the rest

\long\def\startstaticMPgraphic#1#2\stopstaticMPgraphic
  {\blabelgroup
   \def\MPgraphicfile{#1}% no \jobname here
   \let\MPwrite\MPstaticwrite
   \immediate\openout\MPwrite=\MPgraphicfile.mp
   \setMPrandomseedfalse
   \enableincludeMPgraphics
   \def\sometxt##1{\string\sometxt{##1}}%
   \the\everyMPgraphic
   \presetMPdefinitions
   \theMPinclusions % brrr
   \writeMPgraphic{\letterpercent mpenvironment: \the\everyMPTEXgraphic}%
   \writeMPgraphic{beginfig(1);}%
   \writeMPgraphic{#2}%
   \writeMPgraphic{endfig; end.}%
   \immediate\closeout\MPwrite
   \executeMPgraphicfile
   \elabelgroup}

% this will go to meta-ini

\def\delaysystemcommand
  {\ifx\installprogram\undefined
     \expandafter\executesystemcommand
   \else
     \expandafter\installprogram
   \fi}

\def\MPgraphicfilerunner
  {texmfstart --ifchanged=\MPgraphicfile.mp texexec --mpstatic \MPgraphicfile.mp}

\ifx\doifmode\undefined
  \def\executeMPgraphicfile
    {\ifrunMPgraphics\@EA\executesystemcommand\else\@EA\delaysystemcommand\fi{\MPgraphicfilerunner}}
\else
  \def\executeMPgraphicfile{\doifmode{*\v!first}
    {\ifrunMPgraphics\@EA\executesystemcommand\else\@EA\delaysystemcommand\fi{\MPgraphicfilerunner}}}
\fi

%D Special for \XETEX\ (problem with newlines). This will go
%D away once the version supporting \type {--8bit} is
%D widespread.

\ifnum\texengine=\xetexengine
    \let\obeyMPlines\relax
    \longMPlinesfalse % alas
\fi

\protect \endinput