%%%
%%%  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
