%%%
%%%  File: mfpic.tex
%%%  Version:  0.25
%%%
%%%  Principal Author:  Thomas Leathrum
%%%  Assistants:  Bryan Green, Geoffrey Tobin
%%%

% preliminary version of macros
% save catcode, as Michael Downes of AMS recommends.
\chardef\oldatcatcode=\catcode`@
\catcode`@=11 % letter
\def\@wout{\immediate\write16\relax}
\@wout {}
\@wout
 {mfpic version 0.25 - 19:20 GMT +10:00 Wed 13 Oct 93}
\@wout
 {fixes for TFM, LaTeX (picture), fractions, catcode, sharp.}
\@wout
 {tests for bad label options, mf char codes out of range (0 - 255).}
\@wout
 {localised short-range declarations.}
\@wout {}
% test whether mfpic is used in LaTeX.
\newif\if@inlatex
% idea from _The TeXbook_ (1986), p. 384:
% \@mfundefined must remain undefined.
\ifx\picture\@mfundefined
 \@inlatexfalse
 \@wout {MFPIC: not in latex}
\else
 \@inlatextrue
 \@wout {MFPIC: in latex}
\fi
\@wout {}
% local declarations
\wlog {MFPIC: local declarations}
\newwrite\@outx
\newbox\@labeledgraph
\newdimen\@graphwd
\newcount\@code
% dimension parameters
\wlog {}
\wlog {MFPIC: dimension parameters}
\newdimen\mfpicunit
\newdimen\pointsize
\newdimen\shadespace
\newdimen\headlen
\newdimen\axisheadlen
\newdimen\hashlen
\newdimen\dashlen
\newdimen\dashspace
% default dimension settings
\mfpicunit=1pt
\pointsize=2pt
\shadespace=1pt
\headlen=3pt
\axisheadlen=5pt
\hashlen=4pt
\dashlen=4pt
\dashspace=4pt
% standard setting macros
\def\darkershade{%
 \multiply\shadespace by 5
 \divide\shadespace by 6}
\def\lightershade{%
 \multiply\shadespace by 6
 \divide\shadespace by 5}
\def\dashlineset{%
 \dashlen=4pt
 \dashspace=4pt}
\def\dotlineset{%
 \dashlen=1pt
 \dashspace=2pt}
% direct output to Metafont file
% only valid b/w \open- and \close- graphsfile.
\def\mfcmd#1{%
 \immediate\write\@outx{#1}}
% pen size setting
\def\@pickup{%
 \mfcmd{pickup pencircle scaled penwd;}}
\def\pen#1{%
 \mfcmd{interim penwd:=#1;}
 \@pickup}
% arrowhead shape setting
\def\headshape#1#2{%
 \mfcmd{interim hdwdr:=#1;
        interim hdten:=#2;}}
% open and close file
\def\opengraphsfile#1%
{%
 \@code33 % first graphic is `!'
 \immediate\openout\@outx=#1.mf
 \batchmode
 \font\@graph=#1
 \errorstopmode
 \immediate\write16 {}
 \ifx\@graph\nullfont
   \font\@graph=dummy
   \immediate\write16
     {MFPIC: ** Graphic's TFM file #1.tfm not found. **}
   \immediate\write16
     {MFPIC: ** Process #1.mf! Then reprocess this file. **}
   \immediate\write16
     {MFPIC: `Missing character' messages will log the graphic characters.}
 \else
   \immediate\write16
     {MFPIC: Graphic's TFM file found.}
   \immediate\write16
     {MFPIC: Nevertheless, if PK font's changed, reprocess #1.mf.}
   \immediate\write16
     {MFPIC: If TFM's changed, reprocess #1.mf, and then this TeX file.}
 \fi
 \immediate\write16 {}
 \mfcmd{mag:=\number\mag/1000;}
 \mfcmd{input graphbase.mf;}
 % set global defaults
 \mfcmd{mfpicenv;}
 \headshape{1}{1}
 \pen{0.5 pt}%
}% -- end \opengraphsfile
\def\closegraphsfile
{%
 \mfcmd{}
 \mfcmd{endmfpicenv;}
 \mfcmd{end.}
 \immediate\closeout\@outx
}% -- end \closegraphsfile
% a useful macro not in plain TeX.
\def\mf@gobble#1{}
% for output of #  (c/o Donald Arseneau).
\def\mf@s{\expandafter\mf@gobble\string\#}
% beginning mfpicture environment
\def\@mfpicture#1#2#3#4#5#6{%
 % dimension conversion: ##1 is a dimen.
 \def\@xconv##1{%
   \global\advance ##1 by -#3 \mfpicunit
   \global ##1 = #1 ##1}
 \def\@yconv##1{%
   \global\advance ##1 by -#5 \mfpicunit
   \global ##1 = -#2 ##1}
 % set up TeX
 \global\font\@tcurr=\fontname\font
 \relax
 \bgroup
 \nullfont
 \global\@graphwd = #4 \mfpicunit
 \@xconv\@graphwd
 \global\setbox\@labeledgraph=\vtop
   {\hbox{\@graph\char\@code}}
 % set up Metafont file
 \mfcmd{}
 \mfcmd{unitlen:=\the\mfpicunit\mf@s;}
 \mfcmd{xscale:=#1*unitlen; yscale:=#2*unitlen;
   xneg:=#3; xpos:=#4;
   yneg:=#5; ypos:=#6;}
 \mfcmd{beginchar (\the\@code,
   (xpos-xneg)*xscale,
   (ypos-yneg)*yscale,
   0);}
 \mfcmd{setztr;}
 \@pickup
 % metafont drawing macros
 % points, lines, and arrows
 \def\point##1{%
   \mfcmd{pointd(##1, \the\pointsize);}}
 \def\line##1{%
   \mfcmd{line(##1);}}
 \def\arrow##1{%
   \mfcmd{arrow(##1, \the\headlen);}}
 \def\dottedline##1{%
   \mfcmd{dottedline(##1, \the\dashlen,
     \the\dashspace);}}
 \def\dottedarrow##1{%
   \mfcmd{dottedarrow(##1, \the\dashlen,
     \the\dashspace, \the\headlen);}}
 % axes and axis marks
 \def\axes
   {\mfcmd{axes(\the\axisheadlen);}}
 \def\xmarks##1{%
   \mfcmd{xmarks(\the\hashlen, ##1);}}
 \def\ymarks##1{%
   \mfcmd{ymarks(\the\hashlen, ##1);}}
 % polygons
 \def\rect##1{%
   \mfcmd{rect(##1);}}
 \def\dottedrect##1{%
   \mfcmd{dottedrect(##1,
     \the\dashlen, \the\dashspace);}}
 \def\block##1{%
   \mfcmd{block(##1);}}
 \def\rectshade##1{%
   \mfcmd{rectshade(\the\shadespace, ##1);}}
 \def\polygon##1{%
   \mfcmd{curve(false, true, ##1);}}
 \def\polyshade##1{%
   \mfcmd{cycleshade(\the\shadespace,
     false, ##1);}}
 \def\polyfill##1{%
   \mfcmd{cycleshade(0, false, ##1);}}
 % circles and ellipses
 \def\circle##1{%
   \mfcmd{circle(##1);}}
 \def\ellipse##1{%
   \mfcmd{ellipse(##1, 0);}}
 \def\rotatedellipse##1{%
   \mfcmd{ellipse(##1);}}
 \def\circshade##1{%
   \mfcmd{circshade(\the\shadespace, ##1);}}
 \def\ellshade##1{%
   \mfcmd{ellshade(\the\shadespace, ##1, 0);}}
 \def\rotatedellshade##1{%
   \mfcmd{ellshade(\the\shadespace, ##1);}}
 \def\cdisk##1{%
   \mfcmd{circshade(0, ##1);}}
 \def\edisk##1{%
   \mfcmd{ellshade(0, ##1, 0);}}
 \def\rotatededisk##1{%
   \mfcmd{ellshade(0, ##1);}}
 % circular arcs
 \def\arc##1{%
   \mfcmd{arc(##1);}}
 \def\arcarrow##1{%
   \mfcmd{arcarrow(\the\headlen, ##1);}}
 \def\arcshade##1{%
   \mfcmd{arcshade(\the\shadespace, ##1);}}
 \def\arcfill##1{%
   \mfcmd{arcshade(0, ##1);}}
 % polar coordinates
 \def\linedir##1{%
   \mfcmd{linedir(##1);}}
 \def\arrowdir##1{%
   \mfcmd{arrowdir(\the\headlen, ##1);}}
 \def\arcth##1{%
   \mfcmd{arcth(##1);}}
 \def\arctharrow##1{%
   \mfcmd{arctharrow(\the\headlen, ##1);}}
 \def\wedgeshade##1{%
   \mfcmd{wedgeshade(\the\shadespace, ##1);}}
 \def\wedgefill##1{%
   \mfcmd{wedgeshade(0, ##1);}}
 % curves
 \def\curve##1{%
   \mfcmd{curve(true, false, ##1);}}
 \def\polyline##1{%
   \mfcmd{curve(false, false, ##1);}}
 \let\polycurve=\polyline
 \def\curvedarrow##1{%
   \mfcmd{curvedarrow(true,
     \the\headlen, ##1);}}
 \def\polyarrow##1{%
   \mfcmd{curvedarrow(false,
     \the\headlen, ##1);}}
 % cyclic curves
 \def\cyclic##1{%
   \mfcmd{curve(true, true, ##1);}}
 \def\cycleshade##1{%
   \mfcmd{cycleshade(\the\shadespace,
     true, ##1);}}
 \def\cyclefill##1{%
   \mfcmd{cycleshade(0, true, ##1);}}
 % functions
 \def\function##1{%
   \mfcmd{function(true, ##1);}}
 \def\polyfunction##1{%
   \mfcmd{function(false, ##1);}}
 \def\parafcn##1{%
   \mfcmd{parafcn(true, ##1);}}
 \def\polyparafcn##1{%
   \mfcmd{parafcn(false, ##1);}}
 \def\shadefcn##1##2##3{%
   \mfcmd{shadefcn(\the\shadespace, ##1)
     (##2) (##3);}}
 % labels
 \def\@mflabel[##1##2]##3##4##5{%
   % compute width of graph with label
   % and reset size if necessary
   {% local env. for \@btemp.
     \chardef\@btemp=255\relax
     \setbox\@btemp=\hbox{\@tcurr##5}
     {% local env. for \@xtemp.
       \dimendef\@xtemp=0\relax
       \@xtemp = ##3 \mfpicunit
       \@xconv\@xtemp
       \advance\@xtemp by\wd\@btemp
       \ifdim\@xtemp>\@graphwd
         \global\@graphwd=\@xtemp\fi
     }% end local env.
     % set label onto picture
     \global\setbox\@labeledgraph=
     \vtop{\unvbox\@labeledgraph
       \vbox to 0 pt{%
         \if##1t\relax\else
         \if##1c\kern-0.5\ht\@btemp\else
         \if##1b\kern-\ht\@btemp\else
           \immediate\write16 {}
           \immediate\write16
             {MFPIC: label: vertical option `##1' unknown, will treat as `b'}
           \immediate\write16 {}
           \kern-\ht\@btemp
         \fi\fi\fi
         {% local env. for \@ytemp.
           \dimendef\@ytemp=0\relax
           \@ytemp = ##4 \mfpicunit
           \@yconv\@ytemp
           \kern\@ytemp
         }% end local env.
         \hbox{%
           \if##2l\relax\else
           \if##2c\kern-0.5\wd\@btemp\else
           \if##2r\kern-\wd\@btemp\else
             \immediate\write16 {}
             \immediate\write16
               {MFPIC: label: horizontal option `##2' unknown, will treat as `l'}
             \immediate\write16 {}
           \fi\fi\fi
           {% local env. for \@xtemp.
             \dimendef\@xtemp=0\relax
             \@xtemp = ##3 \mfpicunit
             \@xconv\@xtemp
             \kern\@xtemp
           }% end local env.
           \box\@btemp}% -- end \hbox
         \vss}% -- end \vbox
       \nointerlineskip}% -- end \vtop
   }% end local env.
 }% -- end \@mflabel
 \def\@labeldefault{\@mflabel[bl]}
 \def\@dolabel{%
   \if[\@nchr\expandafter\@mflabel
   \else\expandafter\@labeldefault\fi}
 \def\mflabel{\futurelet\@nchr\@dolabel}
 % captions
 % \@docaption is called by \endmfpicture
 \def\@docaption{}
 \def\mfcaption##1{%
   % redefine to set caption
   \def\@docaption{%
     % allow forced line breaks
     \def\\{%
       \global\font\@curr=\fontname\font
       \relax\egroup \hbox\bgroup\@curr}
     % compute adjustments to center
     \chardef\@btemp=255\relax
     \setbox\@btemp=\vbox
       {\hbox{\@tcurr##1}}
     \ifdim\wd\@btemp>\@graphwd
     \global\@graphwd=\wd\@btemp\fi
     % set caption onto picture
     \global\setbox\@labeledgraph=\vbox
     {\unvbox\@labeledgraph
       \medskip\hbox
       {\noindent
         \dimendef\@centerskip=0\relax
         \@centerskip=\@graphwd
         \advance\@centerskip -\wd\@btemp
         \divide\@centerskip by 2\relax
         \kern\@centerskip
         \box\@btemp
       }% -- end \hbox
       \vss
     }% -- end \vbox
   }% -- end \@docaption
 }% -- end \mfcaption
 % backward compatibility:
 \let\label=\mflabel
 \let\caption=\mfcaption
 % end of object macros
}% -- end \@mfpicture
% setting up optional arguments
\def\@piciii#1#2#3#4{%
 \@mfpicture{\@param}{\@param}%
   {#1}{#2}{#3}{#4}}
\def\@picii[#1]#2#3#4#5{%
 \@mfpicture{\@param}{#1}%
   {#2}{#3}{#4}{#5}}
\def\@pici{%
 \if[\@nchr\expandafter\@picii
 \else\expandafter\@piciii\fi}
\def\mfpicture [#1]{%
 {% local env. for \@outrange.
   \def\@outrange {%
     \immediate\write16 {}
     \immediate\write16
       {MFPIC: ** Sorry, mfpic makes characters between 0 and 255, inclusive;}
     \immediate\write16
       {MFPIC: ** if you want more, then I suggest you start another graphics font;}
     \immediate\write16
       {MFPIC: * in the meantime mfpic will use the dummy font for new graphics.}
     \immediate\write16 {}
     \font\@graph=dummy\relax
   }% -- end \@outrange
   \ifx \@code <  0 \@outrange \else
   \ifx \@code > 255 \@outrange \fi\fi
 }% end local env.
 \def\@param{#1}%
 \futurelet\@nchr\@pici
}% -- end \mfpicture
% ending mfpicture environment:
\def\endmfpicture{%
 \mfcmd{endchar;}
 \@docaption\egroup
 \hbox to\@graphwd{%
   \box\@labeledgraph\hss}
 \global\advance\@code1
}% -- end \endmfpicture
%
% Abbreviations:
\let\mfpic=\mfpicture
\let\endmfpic=\endmfpicture
%
\if@inlatex
 \relax
\else % NOT in LaTeX.
 % backward compatibility:
 \let\picture=\mfpicture
 \let\endpicture=\endmfpicture
\fi
% restore catcode.
\catcode`@=\oldatcatcode
%
% end mfpic.tex