% \iffalse % ------------------------------------------------------------------- % % Copyright 2002--2006, Daniel H. Luecking % % Mfpic may be distributed and/or modified under the conditions of the % LaTeX Project Public License, either version 1.3b of this license or (at % your option) any later version. The latest version of this license is in % % and version 1.3b or later is part of all distributions of LaTeX version % 2003/12/01 or later. % % Mfpic has maintenance status "author-maintained". The Current Maintainer % is Daniel H. Luecking. There are several Base Interpreters: plain TeX, LaTeX, % plain Metafont and plain MetaPost. % %<*driver> \ProvidesFile{mfpic.dtx} % %\ProvidesPackage{mfpic} %<*sty> [2006/05/26 v0.9. Macros for drawing with Metafont/MetaPost.]% % %<*driver> \documentclass[draft]{ltxdoc} \addtolength{\textwidth}{.5878pt} \def\mytt{\upshape\mdseries\ttfamily} \renewcommand\marg[1]{{\mytt\{#1\}}} \renewcommand\oarg[1]{{\mytt [#1]}} \renewcommand\parg[1]{{\mytt (#1)}} \renewcommand \arg[1]{{\mytt \##1}} \renewcommand\#{\char`\#\relax} \renewcommand{\meta}[1]{{$\langle$\rmfamily\itshape#1\/$\rangle$}} \DeclareRobustCommand\cs[1]{{\mytt\char`\\#1}} \def\prog#1{{\mdseries\scshape #1}} \def\grafbase{\prog{grafbase}} \def\Grafbase{\prog{Grafbase}} \def\mfpic{\prog{mfpic}} \def\Mfpic{\prog{Mfpic}} \def\MF{\prog{meta\-font}} \def\MP{\prog{meta\-post}} \def\CMF{\prog{Meta\-font}} \def\CMP{\prog{Meta\-post}} \def\opt#1{{\sffamily\upshape#1}} \def\mfc#1{{\mytt#1}} \let\env\mfc \let\file\mfc \let\gbc \mfc \catcode`\_=12 \renewcommand\{{\char`\{} \renewcommand\}{\char`\}} \renewcommand\|{${}\mathrel{|}{}$} \makeatletter \newcommand\bsl{{\mytt\@backslashchar}} % Stupid lists! \def\@listi{\leftmargin\leftmargini \parsep \z@ \@plus\p@ \@minus\z@ \topsep 4\p@ \@plus\p@ \@minus2\p@ \itemsep\parsep} \let\@listI\@listi \@listi \renewcommand\labelitemi{\normalfont\bfseries \textendash} \renewcommand\labelitemii{\textasteriskcentered} \renewcommand\labelitemiii{\textperiodcentered} \leftmargini\parindent % Stupid index! \def\usage#1{\textrm{#1}} \def\index@prologue{\section*{Index}\markboth{Index}{Index}% Numbers refer to the page where the corresponding entry is described. } \def\IndexParms{% \parindent \z@ \columnsep 15pt \parskip 0pt plus 1pt \rightskip 5pt plus2em \mathsurround \z@ \parfillskip-5pt \small % less hanging: \def\@idxitem{\par\hangindent 20pt}% \def\subitem{\@idxitem\hspace*{15pt}}% \def\subsubitem{\@idxitem\hspace*{25pt}}% \def\indexspace{\par\vspace{10pt plus 2pt minus 3pt}}} \makeatother \def\pdfTeX{\textrm{pdf\kern.04em\TeX}} \def\pdfLaTeX{\textrm{pdf\kern.06em\LaTeX}} \def\ConTeXt{\textrm{Con\kern-.16em\TeX\kern-0.06em t}} \def\PiCTeX{\textrm{P\kern-.13em\lower.3ex\hbox{I}C\TeX}} \title{The \mfpic{} package\thanks{This file has version number \fileversion, last revised \filedate. The code described here was developed by several people, notably Thomas Leathrum, Geoffrey Tobin and Dan Luecking. Dan wrote this documentation.}} \author{Dan Luecking} \date{\filedate} \DisableCrossrefs \CodelineIndex \AlsoImplementation \begin{document} \DeleteShortVerb{\|} \DocInput{mfpic.dtx} \end{document} % %\fi % \CheckSum{4902} % \CharacterTable % {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z % Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z % Digits \0\1\2\3\4\5\6\7\8\9 % Exclamation \! Double quote \" Hash (number) \# % Dollar \$ Percent \% Ampersand \& % Acute accent \' Left paren \( Right paren \) % Asterisk \* Plus \+ Comma \, % Minus \- Point \. Solidus \/ % Colon \: Semicolon \; Less than \< % Equals \= Greater than \> Question mark \? % Commercial at \@ Left bracket \[ Backslash \\ % Right bracket \] Circumflex \^ Underscore \_ % Grave accent \` Left brace \{ Vertical bar \| % Right brace \} Tilde \~} % % \GetFileInfo{mfpic.dtx} % \maketitle % % \begin{abstract} % An environment, \env{mfpic}, is defined, within which commands can be % used for drawing pictures, especially of mathematical objects and % functions. These commands actually write code to an external file to be % processed through \MF{} or \MP{} (depending on package options) to % produce the picture. The picture is then included on a second pass % through \TeX. % % This file documents the source code. See \file{mfpman.pdf} or % \file{mfpman.tex} for the user documentation. % \end{abstract} % % \StopEventually{\PrintIndex} % \tableofcontents % % % \section{Introductory setup}\label{intro} % % \Mfpic{} is designed to work with plain \TeX, \LaTeX, \pdfTeX, and % \pdfLaTeX. I consistently use it with eplain and AMS\LaTeX{} % without problems. Users have reported succesfully using it with \AmSTeX. % It has \emph{not} been successfully used with \ConTeXt. % % \subsection{Versions numbers, category codes, etc.}\label{category} % % Almost all the various category code settings we do were prompted by % an \mfpic{} user who had sent a bug report and had to send along his % modified version of \file{mfpic.tex}. It had been modified so that % \cs{message}\,s and \cs{write}\,s would do the right thing in latex % files where various punctuation were made active (e.g., with % \file{french.sty}). % % We keep track of version numbers here. We store the version and date % in macros and later we write this version information to the % output file, The \cs{mfpicversion} is 100 times the numeric part of the % version. The output file can compare this number with the corresponding % value in \file{grafbase} and detect installations where there is a % mismatch. % \begin{macrocode} %<*tex> \ifx\mfpfileversion\UndEfInEd\else\expandafter\endinput\fi% {% \catcode\lq\.12 \catcode\lq\/12% \gdef\mfpfileversion{0.9}% \gdef\mfpfiledate{2006/05/26}% \gdef\mfpicversion{90}% }% % \end{macrocode} % % A bug in older versions of some support files is triggered by the macro % \cs{+}, which is an \cs{outer} macro in plain \TeX. Here we save the % current definition and then give it a nonouter meaning. % \begin{macrocode} \let\mfpsaveplus\+% \let\+\tabalign% % \end{macrocode} % % We now get rid of unusually catcoded punctuation, space and EOL. % We save all the current category codes in the macro \cs{mfp@restoreALL} % and restore them at the end by executing this command. % We assume that letters, numbers, `\texttt\bsl', `\texttt\{', `\texttt\}', % `\texttt\#' and `\texttt\%' have the usual categories. However, styles % (e.g., \prog{french}) that make punctuation active foul up \cs{write}\,s % of MF/MP code. This can still occur in user-generated \cs{write}\,s, so % maybe some of this code should be added in \cs{mfpic} or \cs{mfsrc} % command, too. % \begin{macrocode} {% \catcode61\space12\relax% 61=equal sign \catcode32=10\relax% 32=space \catcode13=5 % 13=EOL \catcode96=12 % 96=left quote \catcode`\@=11 \gdef\MFPsavecodes{% \edef\mfp@restoreNLchar{\newlinechar\number\newlinechar\relax}% \edef\mfp@restoreELchar{\endlinechar\number\endlinechar\relax}% \edef\mfp@restoreSP{\catcode32=\number\catcode32\relax}% \edef\mfp@restoreEOL{\catcode13=\number\catcode13\relax}% \edef\mfp@restoreALL{\mfp@restorecode{=}\mfp@restorecode{@}% \mfp@restorecode{$}\mfp@restorecode{:}\mfp@restorecode{;}% \mfp@restorecode{.}\mfp@restorecode{,}\mfp@restorecode{!}% \mfp@restorecode{?}\mfp@restorecode{(}\mfp@restorecode{)}% \mfp@restorecode{[}\mfp@restorecode{]}\mfp@restorecode{<}% \mfp@restorecode{>}\mfp@restorecode{*}\mfp@restorecode{/}% \mfp@restorecode{+}\mfp@restorecode{-}\mfp@restorecode{"}% \mfp@restorecode{'}\mfp@restorecode{_}\mfp@restorecode{`}% \mfp@restoreEOL\mfp@restoreSP\catcode10=\number\catcode10 \mfp@restoreNLchar\mfp@restoreELchar}}% \gdef\mfp@restorecode#1{\catcode`\string#1=\number\catcode`#1\relax}% \ifx\@makeother\UndEfInEd \gdef\@makeother#1{\catcode`#1=12\relax}\fi \gdef\MFPsanitize{\endlinechar13 \newlinechar10 \catcode10=12 \catcode13=5 \catcode`\$=3 \catcode`\ =10 \@makeother\:\@makeother\;\@makeother\.\@makeother\,% \@makeother\!\@makeother\?\@makeother\(\@makeother\)% \@makeother\[\@makeother\]\@makeother\>\@makeother\<% \@makeother\/\@makeother\*\@makeother\+\@makeother\-% \@makeother\'\@makeother\"\@makeother\_\@makeother\`% \@makeother\=\@makeother\@}% }% \MFPsavecodes\MFPsanitize \catcode`@11 \chardef\mfp@ctrlJ 10 \chardef\mfp@ctrlM 13 % \end{macrocode} % % \cs{MFPsavecodes} saves a bunch of things that must have (mostly) % normal settings \cs{mfp@restoreALL} will be invoked at the end of the % file to restore all the values. % % \cs{MFPsanitize} sets (almost) everything to normal. It can be used to % redo these settings inside some other macro, should that ever become % necessary. Characters 10 and 13 are \verb|^^J| and \verb|^^M|, % control-J and control-M. % % \subsection{Debugging and messages}\label{debug} % % \DescribeMacro{\mfpicdebug} % To turn on debugging before option processing, the user must make sure % \cs{mfpicdebug} is defined. \cs{mfp@DBlog} writes it contents to the % log file only if debugging is on. % \DescribeMacro{\ifmfpicdebug}\cs{ifmfpicdebug} is normally set to true % if the user loads \mfpic{} with the \opt{debug} option, or sets it % directly with \cs{mfpicdebugtrue} after loading. % \begin{macrocode} \newif\ifmfpicdebug \ifx\mfpicdebug\UndEfInEd \mfpicdebugfalse \else \mfpicdebugtrue \fi \def\mfp@DBlog#1{% \ifmfpicdebug{\let\@msgbreak\mfp@errbrk\wlog{Mfpic debug: #1}}\fi}% % \end{macrocode} % % We need to write various kinds of messages to the screen and log file. % \cs{mfp@msg} is only used in the definition of the others and to write a % blank line. We always use the second, which identifies the source of the % message, or the third, which adds the word `warning'. The fourth is for % errors and provides for help if a user presses `\texttt h' in response % to the message. The bit with the spaces is to get a hanging indentation % with text properly aligned on screen. The basic \cs{mfp@msg} defines % \cs{@nl} to place the \cs{newlinechar}, for multiline messages. We % also define \cs{@nl} in \cs{mfp@write} for new lines in writing to a % file. We do not define it at all at the outer level. % \begin{macrocode} \def\mfp@msg#1{% {\newlinechar\mfp@ctrlJ\def\@nl{^^J}\immediate\write16{#1}}}% \def\mfp@spaces{\space\space\space\space\space\space}% \def\mfp@msgbrk{^^J\mfp@spaces\space}% \def\mfp@errbrk{\mfp@msgbrk\mfp@spaces}% \def\mfp@warnbrk{\mfp@errbrk\space\space}% \def\Mfpic@msg#1{{\let\@msgbreak\mfp@msgbrk\mfp@msg{Mfpic: #1}}}% \def\Mfpic@warn#1{% {\let\@msgbreak\mfp@warnbrk\mfp@msg{\@nl Mfpic warning: #1}}}% \def\mfp@errmsg#1#2{{\newlinechar\mfp@ctrlJ\let\@msgbreak\mfp@errbrk \errhelp{#2}\errmessage{Mfpic error: #1}}}% % \end{macrocode} % % In \TeX{} 3.x we can identify the line being processed when a message is % issued. We do not support \TeX{} 2.x. The command \cs{mfp@lineno} is % for information written into the output file. % \begin{macrocode} \def\mfp@lineno{line \number\inputlineno\space in the TeX source}% % \end{macrocode} % % \subsection{Detecting the format}\label{format} % % To detect its environment, \mfpic{} needs to test whether certain % commands are defined. We usually use the positive version % \cs{mfp@ifdefined}. The \cs{@xp} in it is used to `expand away' the rest % of a conditional. \cs{@XP} does this from two levels deep in a % conditional. Since our check uses \cs{@firstoftwo} and % \cs{@secondoftwo}, we cannot use it to check \emph{their} existence (but % we could use other means). % % \cs{mfp@ifundefined} checks its argument to see if it is defined. % If so, it gobbles all code up to \cs{mfp@enddef}. Otherwise that code is % executed. This avoids reading code prematurely (category code changes). % % We also copy \LaTeX's \cs{@ifundefined} since we have at least five % places where we need to supply the name without a backslash. % \begin{macrocode} \let\@xp\expandafter \def\@XP{\@xp\@xp\@xp}% \long\def\@firstoftwo#1#2{#1}% \long\def\@secondoftwo#1#2{#2}% \def\mfp@ifdefined#1{% \ifx#1\UndEfInEd \@xp\@secondoftwo \else\ifx#1\relax \@XP\@secondoftwo \else \@XP\@firstoftwo \fi\fi}% \mfp@ifdefined\@empty{}{\def\@empty{}}% \mfp@ifdefined\@gobble{}{\def\@gobble#1{}}% \mfp@ifdefined\@firstofone{}{\long\def\@firstofone#1{#1}}% \mfp@ifdefined\on@line{}% {\def\on@line{ on input line \number\inputlineno}}% \let\mfp@enddef\@empty \long\def\mfp@gobbledef#1\mfp@enddef{}% \def\mfp@ifundefined#1{\mfp@ifdefined#1\mfp@gobbledef\@empty}% \mfp@ifundefined\@ifundefined \def\@ifundefined#1{% \@xp\ifx\csname #1\endcsname\relax \@xp\@firstoftwo \else \@xp\@secondoftwo \fi}% \mfp@enddef % \end{macrocode} % % The following might be useful in patching things or adding to % \cs{mfp@additions}. % \begin{macrocode} \mfp@ifdefined\g@addto@macro{}{% \long\def\g@addto@macro#1#2{% \begingroup \toks@\@xp{#1#2}% \xdef#1{\the\toks@}% \endgroup}}% \mfp@ifdefined\g@prependto@macro{}{% \long\def\g@prependto@macro#1#2{% \begingroup \toks@{#2}\toks2\@xp{#1}% \xdef#1{\the\toks@\the\toks2}% \endgroup}}% % \end{macrocode} % % We test for LaTeX. We assume plain\TeX{}, or something compatible, % except in a few places where LaTeX{} does thing differently. \Mfpic{} % didn't work in \ConTeXt{} the last few times I tried. % % Here we see if \cs{documentstyle} is defined, and then make sure % we are not in \AmSTeX{}. Probably there is a better command to test, % and perhaps we should just test whether the functionality required is % present, but I'm not really sure how best to do either of those. % \begin{macrocode} \newif\ifmfp@latex \mfp@latexfalse \mfp@ifdefined\documentstyle {\def\mfp@tempa{AmS-TeX}% \ifx \fmtname\mfp@tempa \mfp@DBlog{AmS-TeX detected.}% \else \mfp@DBlog{LaTeX detected.}\mfp@latextrue \fi}% {\mfp@DBlog{Neither LaTeX nor AmS-TeX detected.}}% % \end{macrocode} % % We are in \LaTeXe{}, as opposed to \LaTeX2.09, if \cs{documentclass} % is defined. The \file{mfpic.sty} now assumes \LaTeXe{}. It might still % be possible to use \LaTeX{}2.09 with \cs{input mfpic}, but I don't % care enough to test it. % \begin{macrocode} \newif\ifmfp@latexe \mfp@latexefalse \mfp@ifdefined\documentclass {\mfp@latexetrue \mfp@DBlog{LaTeX2e detected.}}% {\mfp@DBlog{Not LaTeX2e.}}% % \end{macrocode} % % We now test \cs{pdfoutput} to see if pdf support is needed. % \begin{macrocode} \newif\ifmfp@pdf \mfp@pdffalse \mfp@ifdefined\pdfoutput {\mfp@DBlog{PdfTeX detected...}% \ifnum\pdfoutput<1 \mfp@DBlog{...with dvi output.}% \else \mfp@pdftrue \mfp@DBlog{...with PDF output.}% \fi}% {\mfp@DBlog{Not pdfTeX.}}% % \end{macrocode} % % \subsection{Blank line and spacing hacks}\label{spacing} % % In order for commands to always read their arguments correctly, % we need EOLs to have their normal category codes, but then a % blank line will end a paragraph, and we would like blank lines to be % ignored inside an \env{mfpic} environment. Therefore we turn off % \cs{par} inside that environment, and then need(?) to turn it back on % inside \cs{tlabel} and \cs{tcaption}. \cs{@@par} (in \LaTeX) and % \cs{endgraf} (in plain \TeX) should equal the primitive \cs{par}. % \begin{macrocode} \ifmfp@latex \else \let\@@par\endgraf \fi \def\mfp@restorepar{\let\par\@@par}% % \end{macrocode} % % Some \mfpic{} commands end with \cs{ignorespaces}. For some others a % better choice is the \LaTeX{} strategy of conditionally ignoring spaces. % \begin{macrocode} \mfp@ifdefined\@namedef{}% {\def\@namedef#1{\@xp\def\csname #1\endcsname}}% \mfp@ifdefined\@namelet{}% {\def\@namelet#1{\@xp\let\csname #1\endcsname}}% \mfp@ifdefined\@nameuse{}% {\def\@nameuse#1{\csname #1\endcsname}}% \mfp@ifundefined\@bsphack \@nameuse{newskip}\@savsk \@nameuse{newcount}\@savsf \def\@bsphack{\relax \ifhmode \@savsk\lastskip \@savsf\spacefactor \fi}% \def\@esphack{\relax \ifhmode \spacefactor\@savsf \ifdim\@savsk>\z@ \ignorespaces \fi\fi}% \mfp@enddef % \end{macrocode} % % \subsection{Warning if commands are already defined} % % We sometimes (either by accident or by choice) redefine things defined % in some formats. For the accidental redefinitions we want to be told, % and since we cannot assume \LaTeX{} with its \cs{newcommand}, we define % a simple check and print a warning when it happens. % \begin{macrocode} \mfp@DBlog{Defining test for previous definitions of macros.}% \def\mfp@testdef#1{% \ifx#1\UndEfInEd \else\ifx#1\relax \Mfpic@warn{\string#1 was previouly defined to be \string\relax.}% \else \Mfpic@warn{\string#1 is already defined.}% \fi\fi}% % \end{macrocode} % % Is the proposed definer of new definitions itself not new? Well, % we'd like a warning, but go ahead and define it anyway. All % \cs{newdef} does is check whether the macro being defined is already % defined, raise a warning (but \emph{not} an error) and define it % anyway. We do something similar with \cs{let}. % \begin{macrocode} \mfp@testdef\newdef \def\newdef#1{\mfp@testdef#1\def#1}% \newdef\newlet#1{\mfp@testdef#1\let#1}% % \end{macrocode} % % \subsection{Error messages and warnings} % % If one tries to switch on \MP{} support after the output file has been % set up, we issue this error message. % \begin{macrocode} \newdef\mfp@useMP@error{% \mfp@errmsg {Command \mfp@b usemetapost too late}% {It is too late to select the metapost option.^^J% It must be selected before the \opengraphsfile command.^^J% If you proceed, the metafont option will be assumed.}}% % \end{macrocode} % % This one is for macros that need an output file to write to, but are % called before one has been opened. % \begin{macrocode} \def\mfp@nooutput@error#1{% \mfp@errmsg {No output file has been opened}% {You have tried to used a command, #1, that requires an output^^J% file to be opened with the \opengraphsfile command, which^^J% was either not issued or was not successful.}}% % \end{macrocode} % % Some options and commands require the \opt{metapost} option be in % effect. We define an error message for the case where it is not in % effect. % \begin{macrocode} \newdef\mfp@noMP@error#1{% \mfp@errmsg {Metafont does not support #1, use MetaPost}% {Metafont doesn't support #1. Perhaps you forgot to turn on^^J% MetaPost support by using the metapost option or issuing the^^J% command \usemetapost. For now, I will ignore it.}}% % \end{macrocode} % % This next is like \cs{mfp@useMP@error}, but it is not so specific. % It is for other options that also need to be issued before % \cs{opengraphsfile}. % \begin{macrocode} \def\mfp@afteropen@error#1{% \mfp@errmsg{Improper use of command \string#1\on@line}% {You must issue the command #1 prior to \opengraphsfile. It will be ignored now.}}% % \end{macrocode} % % \cs{mfp@end} is defined to be an error message, but that is for % debugging purposes. It's actual use is to mark the end when we need to % process a list of tokens. The code should simply detect and remove it, % and it should never be expanded, so seeing the error message indicates % a coding error by me, or incorrect syntax by a user. % \begin{macrocode} \newdef\mfp@end{% \mfp@errmsg {Unexpected token \string\mfp@end}% {If you get this message but did not misuse the command^^J% \mfp@end, it could mean you have unbalanced braces.}}% % \end{macrocode} % % The next two are error messages for missing or empty data files. % \begin{macrocode} \newdef\mfp@nofile@error#1{% \mfp@errmsg{No data file: #1}% {The data file you tried to plot was not found.}}% \newdef\mfp@nodata@error#1{% \mfp@errmsg{Empty data file: #1}% {The data file contained only empty lines and comments.}}% % \end{macrocode} % % This message is issued when the \cs{tlabeljustify} command (see % section~\ref{labelsettings}) is issued with an invalid parameter. % \begin{macrocode} \newdef\mfp@justify@error{% \mfp@errmsg{Invalid justification parameter for text label}% {The optional argument for an mfpic text label must be^^J% one of B, b, c or t, followed by^^J one of l, r or c, optionally followed by an angle.}}% % \end{macrocode} % % This is the default meaning assigned to \cs{@nountil} at the % beginning of \cs{mfploop}. Use of \cs{mfpuntil} cancels the % warning, which is otherwise issued by \cs{mfpendloop}. % \begin{macrocode} \newdef\mfp@untilwarn{% \Mfpic@warn{\mfp@b mfploop without \string\mfpuntil!}}% % \end{macrocode} % % % \section{Configuring \mfpic{} behavior}\label{configuring} % % \subsection{Options}\label{options} % % \DescribeMacro{\ifmfpmpost} % I have decided to make this a user-level macro so that a user can % write code that behaves one way for \MP{} and another for \MF. However % the commands to change the setting are private. % % Our switch to turn \MP{} support on or off needs to be global, so it % can't be a normal \cs{newif}. % \begin{macrocode} \newlet\ifmfpmpost\iffalse \newdef\mfp@mposttrue {\global\let\ifmfpmpost\iftrue}% \newdef\mfp@mpostfalse{\global\let\ifmfpmpost\iffalse}% \newdef\mfp@ifmpost{% \ifmfpmpost\@xp\@firstoftwo\else\@xp\@secondoftwo\fi}% % \end{macrocode} % % \DescribeMacro{\usemetafont} % We make user-level commands for switching to the appropriate drawing % program. This is necessary for plain\TeX, but also used internally by % \mfpic. \CMF{} is the default. This command needs to not only clear the % boolean \cs{ifmfpmpost}, but also restore the default graphics inclusion % commands. Actually, it doesn't \emph{need} to unless \cs{usemetapost} % was previously issued to change the default. This would normally not % happen unless the user wanted to close the current graph file and open a % new one for \MF. For similar reasons, we clear the \opt{mplabels} % option. % % \MP{} support requires macros for including EPS graphics. What works % best depends on the format, so we delay the definition of % \cs{usemetapost} until the \LaTeX{} options section. % % Since \cs{mfpicllx} and \cs{mfpiclly} are globally defined by graphic % inclusion, we reset then to 0, in case \opt{metafont} and \opt{metapost} % options are mixed in one file. % \begin{macrocode} \newdef\usemetafont{\mfp@mpostfalse \nomplabels \def\preparemfpicgraphic##1{}% \def\setmfpicgraphic##1{\mfp@graphfont\char\mfp@count}% \def\getmfpicoffset##1{\gdef\mfpicllx{0}\gdef\mfpiclly{0}}}% % \end{macrocode} % % Some options need an open \file{.mf} or \file{.mp} file before they % can do anything. This means the \cs{opengraphsfile} command must have % been issued but not \cs{closegraphsfile}. Since those commands define and % undefine \cs{mfp@filename}, we use that as our test. % \begin{macrocode} \newdef\mfp@ifopengraphsfile{\mfp@ifdefined\mfp@filename}% % \end{macrocode} % % \DescribeMacro{\setmfvariable} % A useful abbreviation for a common requirement: declaring and setting % a \MF{} variable. I have decided to change it to a user-level macro for % power users. % \DescribeMacro{\setmpvariable}\cs{setmpvariable} is another name for it. % It takes three arguments: the type of variable, the variable itself, and % its value. Example:\\ % \indent \cs{setmfvariable}\marg{numeric}\marg{shadewd}\marg{.7pt}.\\ % Since it \mfc{save}\,s the variable, it must not have a suffix. This is % not a big problem since mostly it is for internal use. We document % that fact for power users and advise ordinary users on the naming of % \MF{} variables. % % We have abbreviations for the most common internal uses. For example % \SpecialUsageIndex{\setmfboolean}\cs{setmfboolean} is the equivalent of % \cs{setmfvariable} with type \mfc{boolean}. A similar statement is true % For \SpecialUsageIndex{\setmfnumeric}\cs{setmfnumeric}, % \SpecialUsageIndex{\setmfpair}\cs{setmfpair}, and % \SpecialUsageIndex{\setmfcolor}\cs{setmfcolor}. % % \DescribeMacro{\globalsetmfvariable} % This is like \cs{setmfvariable}, except it doesn't perform a % \mfc{save} and so the variable is globally defined. Also, % suffixed variables are permitted (but not numeric suffixes). % \begin{macrocode} \newdef\setmfvariable#1#2#3{% \mfp@ifopengraphsfile{\mfcmd{setvariable (#1) (#2) #3}}% {\mfp@nooutput@error\setmfvariable}}% \newlet\setmpvariable\setmfvariable \newdef\setmfboolean {\setmfvariable{boolean}}% \newdef\setmfnumeric {\setmfvariable{numeric}}% \newdef\setmfpair {\setmfvariable{pair}}% \newdef\setmfcolor {\setmfvariable{color}}% \newdef\globalsetmfvariable#1#2#3{% \mfp@ifopengraphsfile{\mfcmd{gsetvariable (#1) (#2) #3}}% {\mfp@nooutput@error\globalsetmfvariable}}% \newlet\globalsetvariable\globalsetmfvariable % \end{macrocode} % % The command \cs{setmfvariable} arranges for the value of % that variable to be localized to each figure if set inside one, but % it is global otherwise. We have to be careful that \TeX{} and \MF{} % stay in synchrony, as they have different understandings as to what is % global and what is not. So we define a switch that will be set at the % start of an \env{mfpic} environment to test if a command is issued % inside one. The command \cs{mfp@local} tests this switch and makes the % following assignment global if it fails. Then we have two shortcuts for % the more commonly occuring cases. % % We also define here \texttt{true}, \texttt{false} and \texttt{color} as % macros. These are strings we need to write to the output frequently. % \begin{macrocode} \newlet\ifin@mfpicenv\iffalse \newdef\mfp@local{\relax\ifin@mfpicenv\else\global\fi}% \newdef\mfp@let{\mfp@local\let}% \newdef\mfp@def{\mfp@local\def}% \newdef\mfp@T{true}% \newdef\mfp@F{false}% \newdef\mfp@C{color}% % \end{macrocode} % % \DescribeMacro{\usecenteredcaptions} % This (\opt{centeredcaptions}) is the simplest option. Other options % follow a similar pattern: a user-level command \cs{usecenteredcaptions} % is defined for turning it on and another % \DescribeMacro{\nocenteredcaptions}\cs{nocenteredcaptions} is defined % for turning it off. Selection of centered captions can be turned on or % off at will throughout a document. % \begin{macrocode} \newdef\usecenteredcaptions{\mfp@let\ifmfp@centcapt\iftrue}% \newdef\nocenteredcaptions {\mfp@let\ifmfp@centcapt\iffalse}% \nocenteredcaptions % \end{macrocode} % % \DescribeMacro{\useraggedcaptions} % Here we define the settings for justified and ragged captions. % Justified captions are the default. Ragged cptions are normally % raggedright, but are ragged on both sides if \opt{centeredcaptions} is % in effect. \DescribeMacro{\noraggedcaptions}For justified captions, % lines are justified on both sides, except the last is centered under % \opt{centeredcaptions}. % \begin{macrocode} \newdef\useraggedcaptions{\mfp@let\mfp@capsettings\mfp@raggedcap}% \newdef\noraggedcaptions{\mfp@let\mfp@capsettings\mfp@justifiedcap}% \newdef\mfp@raggedcap{% \ifmfp@latex \ifmfp@centcapt \centering \else \raggedright \fi \else \rightskip 0pt plus 1fil \ifmfp@centcapt \leftskip 0pt plus 1fil \parfillskip 0pt plus 1fil\relax \fi \def\\{\unskip\hbox{}\penalty-\@M\ignorespaces}% \fi}% \def\mfp@justifiedcap{% \ifmfp@centcapt \leftskip 0pt plus 0.5fil \rightskip 0pt plus -0.5fil \parfillskip 0pt plus 1fil\relax \fi \def\\{\unskip\hbox{}\hfil\penalty-\@M\ignorespaces}}% \noraggedcaptions % \end{macrocode} % % This common code is repeated almost verbatim four times, so we define % the following abbreviation. The first two arguments are the commands % to turn the option on and off. The third and fourth are the \MF{} and % \TeX{} booleans to switch. In all cases, the default for the option is % \emph{off}, so we issue the second command after it is defined. % % Since the output file has not been opened while \mfpic{} is loading, the % \MF{} boolean is not set, but the \cs{opengraphsfile} code will check % the \TeX{} boolean and write the appropriate \MF{} code. % \begin{macrocode} \newdef\mfp@makeoption#1#2#3#4{% \newdef#1{\mfp@let#4\iftrue \mfp@ifopengraphsfile{\setmfboolean{#3}\mfp@T}{}}% \newdef#2{\mfp@let#4\iffalse \mfp@ifopengraphsfile{\setmfboolean{#3}\mfp@F}{}}% #2}% % \end{macrocode} % % \DescribeMacro{\clipmfpic} % The \opt{clip} option shows only what's inside the rectangle given in % the \cs{mfpic} command. It can be turned on or off for each figure % independently. \DescribeMacro{\noclipmfpic}The default is the old % behavior: no clipping. % \begin{macrocode} \mfp@makeoption\clipmfpic\noclipmfpic{clipall}\ifmfp@clip % \end{macrocode} % % \DescribeMacro{\usetruebbox} % The \opt{truebbox} option lets \MP{} set the true bounding box (which % may differ from the numbers defined through \cs{mfpic}). % \DescribeMacro{\notruebbox}The default is the old behavior, \cs{notruebbox}. % % We don't need to be too careful with the scope of these option % commands. As currently written, \TeX{} never needs to know the setting % except to pass the information on to \cs{opengraphsfile} if the option % is set before then. However, we treat it like most other settings, % turning on or off an appropriate \TeX{} boolean, in case it ever becomes % necessary to know the setting. It is local to any \env{mfpic}, global % otherwise. The default is to have \opt{truebbox} turned off. % \begin{macrocode} \mfp@makeoption\usetruebbox\notruebbox{truebbox}\ifmfp@truebbox % \end{macrocode} % % \DescribeMacro{\usemplabels} % An option to let \MP{} create labels, \opt{mplabels} mostly just % switches between two versions of \cs{tlabel} so no \MP{} booleans % are set and so synchronization of scope is not an issue. % \DescribeMacro{\nomplabels}The default is the old behavior: labels are % placed by \TeX. The actual setting is delayed until \cs{opengraphsfile} % so the order of these commands and \cs{usemetapost} is not significant % (before \cs{opengraphsfile}). % % Because of the frequent need to check this setting, we define % \cs{@ifmplabels} to execute one of two alternatives based on it. % When writing \TeX{} code to the file we need to make sure \texttt\# % is not doubled. We do this by issuing \cs{mp@mksharpother} before % reading the argument that will be written. % \begin{macrocode} \newdef\usemplabels{\mfp@let\ifmfp@mplabels\iftrue \mfp@ifopengraphsfile {\mfp@ifmpost{}% {\mfp@noMP@error{mplabels}\global\let\ifmfp@mplabels\iffalse}}{}}% \newdef\nomplabels{\mfp@let\ifmfp@mplabels\iffalse}% \newdef\@ifmplabels{% \ifmfp@mplabels\@xp\@firstoftwo\else\@xp\@secondoftwo\fi}% \nomplabels \newdef\mp@mksharpother{\@ifmplabels{\@makeother\#}{}}% % \end{macrocode} % % \DescribeMacro{\overlaylabels} % The option \opt{overlaylabels} instructs \MP{} to defer adding labels % until the end of the picture. That means they don't get clipped or % covered up by any drawing elements. \DescribeMacro{\nooverlaylabels}The % default is the old behavior, \cs{nooverlaylabels}. Neither of these % commands affect \MF, but they write to the output file anyway if issued % after \cs{opengraphsfile}. % \begin{macrocode} \mfp@makeoption% \overlaylabels\nooverlaylabels{overlaylabels}\ifmfp@overlabels % \end{macrocode} % % \DescribeMacro{\clearsymbols} % The option \opt{clearsymbols} causes the symbols drawn by % \cs{plotsymbol} and \cs{plotnodes} to have their interiors erased before % being drawn. \DescribeMacro{\noclearsymbols}The default is the old % behavior: \cs{noclearsymbols}. % \begin{macrocode} \mfp@makeoption% \clearsymbols\noclearsymbols{clearsymbols}\ifmfp@clearsym % \end{macrocode} % % \DescribeMacro{\stopshipping} % This is to turn off character shipping for duration of innermost % enclosing \MF{} group (eg, \env{mfpic} environment). As far as I know % it has never been tested with \MP. (It hasn't been tested recently even % in \MF.) The \MF{} code prevents the figure from being added to the font, % the \TeX{} switch \cs{ifmfp@noship} is checked before \cs{endmfpic} % attempts to add the (nonexistent) figure to the document. % \DescribeMacro{\resumeshipping}\cs{resumeshipping} restores character % shipping. % % \DescribeMacro{\noship}\cs{noship} is the older name for % \cs{stopshipping}. Its name indicated that it was intended for use in % one picture. This is not actually an option (that is, there is no % corresponding \cs{DeclareOption} in \LaTeX), but it is coded the same. % \begin{macrocode} \mfp@makeoption\stopshipping\resumeshipping{noship}\ifmfp@noship \newlet\noship\stopshipping % \end{macrocode} % % \DescribeMacro{\mfpreadlog} % This sets the boolean governing the option to examine the \MF{} or % \MP{} log file for certain information. % \begin{macrocode} \newlet\ifmfp@readlog\iffalse \newdef\mfpreadlog{% \mfp@ifopengraphsfile {\mfp@afteropen@error\mfpreadlog}{\global\let\ifmfp@readlog\iftrue}}% % \end{macrocode} % % \subsection{Graphic inclusion}\label{graphic} % % \DescribeMacro{\mfpicllx} % The code to include a figure has been divided into three parts. Under % \opt{metapost} we need to both include the figure and save the % \DescribeMacro{\mfpiclly} bounding box coordinates of the lower left % corner. Here we initialize the macros that hold these coordinates. % \begin{macrocode} \newdef\mfpicllx{0}% \newdef\mfpiclly{0}% % \end{macrocode} % % \DescribeMacro{\preparemfpicgraphic} % Most EPS inclusion macros make the bounding box information available, % and so after the inclusion command we just save it in the above two % macros. However, \LaTeX's \cs{includegraphics} does not, so we have to % issue a command before the inclusion to force it to become available. % That command is \cs{preparemfpicgraphic}. Usually it does nothing, % but in the \LaTeXe{} case it locally redefines one of the graphics % packages internal macros. % % \DescribeMacro{\setmfpicgraphic} % This command includes the graphic. The \mfpic{} default (for the % \opt{metafont} option) is set by running \cs{usemetafont}. % % \DescribeMacro{\getmfpicoffset} % This one saves the lower left corner in the macros \cs{mfpicllx} and % \cs{mfpiclly}. In the case described above, that is accomplished by % the redefined internal command, so this command does nothing. % % The command \cs{@setmfpicgraphic} is a wrapper around the inclusion % code. It takes the name of the graphic file and passes it along to the % above three commands. Those three commands can be redefined by the % user for special circumstances. The user is then responsible to make % sure \cs{mfpicllx} and \cs{mfpiclly} are properly set when necessary. % Redefining one may necessitate redefining one or both of the others. % % The definition of these three is delayed to the option processing % section, except under the \MF{} default: \cs{usemetafont} defines them. % % We actually define two alternative versions of \cs{@setmfpicgraphic}. % The normal one is as described above, and a `nofile' alternative for % when the graphic file somehow doesn't exist. Then we just print the % filename. % \begin{macrocode} \newdef\normal@setmfpgraphic#1{% \preparemfpicgraphic{#1}\setmfpicgraphic{#1}\getmfpicoffset{#1}}% \newdef\nofile@setmfpgraphic#1{% {\edef\mfp@tempa{#1}% \vbox to 0pt{\vss \rlap{\kern2pt \mfpdraftfont \mfp@sanitized\mfp@tempa}\kern 2pt}}}% \mfp@ifdefined\strip@prefix{}{\def\strip@prefix#1>{}}% \newdef\mfp@sanitized{\@xp\strip@prefix\meaning} \newlet\@setmfpicgraphic\normal@setmfpgraphic \usemetafont % \end{macrocode} % % \DescribeMacro{\setfilename} % The user can also change \cs{setfilename} to modify the assumed % filenames of the graphics output by \MP. The default is the output % file's basename (\arg1) with the picture number as the extension. % \begin{macrocode} \newdef\setfilename#1#2{#1.#2}% % \end{macrocode} % % The \opt{draft}, \opt{final} and \opt{nowrite} options override % \mfpic's attempts to automatically detect whether the pictures should % be included. They also work under the \opt{metafont} option, but are % less important then (even unnecessary). % % \DescribeMacro{\mfpicdraft} % The \opt{draft} option (\cs{mfpicdraft} command) causes the pictures % created by \mfpic{} to be omitted. % % \DescribeMacro{\mfpicnowrite} % The \opt{nowrite} option (\cs{mfpicnowrite} command) turns off creation % of the output \file{.mp} file. It is intended to help speed things up % after all figures are completed, so it permits the insertion of pictures. % % \DescribeMacro{\mfpicfinal} % The \opt{final} option (\cs{mfpicfinal} command) can be used to % override a global draft option. It forces \mfpic{} to attempt to % insert the pictures. Under the \opt{metapost} option, missing figures % may cause serious slow-downs as a large number of directories may be % searched. % % Each of these sets the user level if-command % \SpecialUsageIndex{\ifmfpicdraft}\cs{ifmfpicdraft}, which is retained % for backward compatibility. These settings are global since they are % intended to be set for the whole document. The four commands % \cs{mfp@\{draft\|final\}\{true\|false\}} are used to communicate with % the \cs{opengraphsfile} command, in case the user-level commands occur % before then. % \begin{macrocode} \newif\ifmfpicdraft \newlet\ifmfp@draft\iffalse \newlet\ifmfp@final\iffalse \newlet\ifmfp@nowrite\iffalse \newdef\mfpicdraft{% \mfp@ifopengraphsfile{\global\mfpicdrafttrue}% {\global\let\ifmfp@draft\iftrue}}% \newdef\mfpicfinal{% \mfp@ifopengraphsfile{\global\mfpicdraftfalse}% {\global\let\ifmfp@final\iftrue}}% \newdef\mfpicnowrite{% \mfp@ifopengraphsfile{\mfp@afteropen@error\mfpicnowrite}% {\global\let\ifmfp@nowrite\iftrue}}% % % \end{macrocode} % % \subsection{\LaTeX{} options and \MP{} graphics inclusion}\label{latex} % % Code dependent on \LaTeXe. Mostly this is the option processing % facilities. The declaration of options is in the file % \file{mfpic.sty}, which will input \file{mfpic.tex}. % \begin{macrocode} %<*sty> \DeclareOption{draft}{\mfpicdraft}% \DeclareOption{final}{% \mfpicfinal\PassOptionsToPackage{final}{graphics}}% \DeclareOption{nowrite}{\mfpicnowrite}% \DeclareOption{metapost}{\mfp@mposttrue}% \DeclareOption{metafont}{\usemetafont}% \DeclareOption{centeredcaptions}{\usecenteredcaptions}% \DeclareOption{justifiedcaptions}{\noraggedcaptions}% \DeclareOption{raggedcaptions}{\useraggedcaptions}% \DeclareOption{clip}{\clipmfpic}% \DeclareOption{truebbox}{\usetruebbox}% \DeclareOption{mplabels}{\usemplabels}% \DeclareOption{overlaylabels}{\overlaylabels}% \DeclareOption{clearsymbols}{\clearsymbols}% \DeclareOption{debug}{\mfpicdebugtrue}% \DeclareOption{mfpreadlog}{\mfp@readlogtrue}% \DeclareOption*{% \@ifpackageloaded{graphics}% {\Mfpic@warn{Unrecognized option \CurrentOption.}}% {\Mfpic@msg{Passing option \CurrentOption\space to % graphics package.}% \PassOptionsToPackage{\CurrentOption}{graphics}}}% \newcommand*\mfpdraftfont{\normalfont\ttfamily}% % \end{macrocode} % % Now we define one of three versions of \cs{@usemetapost}. This command % will be issued by the user level command \cs{usemetapost}, and consists % of the format dependent code. The one here is, of course, for \LaTeX{} % and will be in \file{mfpic.sty}. % % Unlike all the other EPS inclusion macros, \cs{includegraphics} does % not make the bounding box coordinates available: \cs{Gin@llx} and the % others are defined, but are local to a group surrounding the internals % of \cs{includegraphics}. We locally modify one graphics package internal % macro to globally save the information we need. Here we save the % original definition and define our replacement. For this, we definitely % need to make sure the \prog{graphics} package is loaded. % \begin{macrocode} \def\@usemetapost{% \mfp@ifdefined\includegraphics{}{\RequirePackage{graphics}}% \let\mfp@save@parse@bb\Gread@parse@bb \newdef\mfp@parse@bb##1 ##2 ##3 ##4 ##5\\{% \mfp@save@parse@bb##1 ##2 ##3 ##4 ##5\\% \xdef\mfpicllx{\Gin@llx}\xdef\mfpiclly{\Gin@lly}}% % \end{macrocode} % The \prog{graphics} package makes decisions about graphic files based on % the files' extensions. Since we don't want to force our users to rename % all the graphics output by \MP, we add code to \cs{preparemfpicgraphic} % to force \cs{includegraphics} to treat the current extension (some % number) as if it were `{\tt eps}' or `{\tt mps}' according to the % context. We also use this command to substitute the above BoundingBox % parsing code for the \prog{graphics} package version. % \begin{macrocode} \ifmfp@pdf \gdef\mfp@Gtype{mps}% \else \gdef\mfp@Gtype{eps}% \fi \gdef\preparemfpicgraphic##1{% \@namedef{Gin@rule@.\number\mfp@count}####1{{\mfp@Gtype}% {.\number\mfp@count}{####1}}% \let\Gread@parse@bb\mfp@parse@bb}% \global\let\setmfpicgraphic\includegraphics \gdef\getmfpicoffset##1{}}% % % \end{macrocode} % % \DescribeMacro{\usemetapost} % The user level command \cs{usemetapost} starts with a few actions common % to all formats, then calls \cs{@usemetapost} which is defined % differently for different formats. % \begin{macrocode} %<*tex> \newdef\usemetapost{% \mfp@ifopengraphsfile{\mfp@mpostfalse\mfp@useMP@error}% {\mfp@mposttrue \@usemetapost}}% % \end{macrocode} % % Under \LaTeX, if \file{mfpic.cfg} exists, it will be input at this % point. Then, we \cs{ProcessOptions}, using the star-form because it allows % package options to take precedence over global options. Thus \mfpic's % \opt{final} option can counteract the \mfpic-specific side effects of a % global \opt{draft} option. % \begin{macrocode} \ifmfp@latexe \InputIfFileExists{mfpic.cfg}{}{}% \ProcessOptions*\relax % \end{macrocode} % % \cs{ProcessOptions} doesn't allow \cs{RequirePackage}\marg{graphics}, % so the above and the following were not simply put inside % \cs{DeclareOption}\marg{metapost}. The \cs{AtEndDocument} command will % close the output file if the user forgot. % \begin{macrocode} \mfp@ifmpost{\usemetapost}{}% \AtEndDocument{\mfp@closegraphsfile}% % \end{macrocode} % % Now those cases outside \LaTeXe{} that we try to support. % \begin{macrocode} \else \mfp@msg{}\Mfpic@msg{\mfpfiledate\space v\mfpfileversion.\@nl}% % \end{macrocode} % % The definition of \cs{@usemetapost} in plain \TeX{} depends on the % setting of \cs{ifmfp@pdf}. However both cases are so similar that we % define a helper macro \cs{mfp@useMP} that just needs to have the names % of three commands and one file fed to it. % \begin{macrocode} \newdef\mfp@useMP#1#2#3#4{% \mfp@ifdefined#1{}{\input #2\relax}% \global\let\setmfpicgraphic\mfp@includeMPS \gdef\getmfpicoffset##1{\xdef\mfpicllx{#3}\xdef\mfpiclly{#4}}}% % \end{macrocode} % % Under \pdfTeX{}, the graphics inclusion command is \cs{convertMPtoPDF}, % defined in \file{supp-pdf.tex}. This command parses the file's PS % contents to PDF code, and leaves the bounding box info in macros % \cs{MPllx} and \cs{MPlly}. % \begin{macrocode} \ifmfp@pdf \newdef\mfp@includeMPS#1{\convertMPtoPDF{#1}{1}{1}}% \newdef\@usemetapost{% \mfp@useMP\convertMPtoPDF{supp-pdf}\MPllx\MPlly}% % \end{macrocode} % % Under plain\TeX, eplain (still need to test this after recent eplain % changes), \AmSTeX, or \LaTeX2.09, the graphics inclusion command is % \cs{epsfbox}, defined in \file{epsf.tex}. This command writes a % \cs{special} for \prog{dvips} (and other DVI driver programs), and % leaves the bounding box info in macros \cs{epsfllx} and \cs{epsflly}. % \begin{macrocode} \else \newdef\mfp@includeMPS#1{\epsfbox{#1}}% \newdef\@usemetapost{\mfp@useMP\epsfbox{epsf}\epsfllx\epsflly}% \fi \fi % \end{macrocode} % % % \section{Optional parameter handling}\label{optional} % % We borrow \LaTeX's \cs{@ifnextchar}. The first argument is the token % being checked. It doesn't have to be a character and we sometimes use % \cs{@ifnextchar} to check whether a certain command follows. % The next argument is the code to run if that character is present, the % last is code to use if the character is not present. % \begin{macrocode} \mfp@DBlog{Handlers for optional parameters.}% \mfp@ifundefined\@ifnextchar \long\def\@ifnextchar#1#2#3{% \let\reserved@d#1% \def\reserved@a{#2}% \def\reserved@b{#3}% \futurelet\@let@token\@ifnch}% \def\@ifnch{% \ifx\@let@token\@sptoken \let\reserved@c\@xifnch \else \ifx\@let@token\reserved@d \let\reserved@c\reserved@a \else \let\reserved@c\reserved@b \fi \fi \reserved@c}% {% \def\:{\global\let\@sptoken= }\: % this makes \@sptoken a space token \def\:{\@xifnch}\@xp\gdef\: {\futurelet\@let@token\@ifnch}% }% \mfp@enddef % \end{macrocode} % % The following save us some typing whenever we need to check if some % token follows, and then remove it if it does. That's what % \cs{mfp@iftoken} does, being just a generalized form of \LaTeX{}'s % \cs{@ifstar}. All our star-form commands differ only in what parameter % is passed to some other command. Thus \cs{mfp@ifstar} passes either % \arg{2} or \arg{3} to command \arg{1}. % % The \cs{mfp@ifend} is for use in processing lists, which all end with % the token \cs{mfp@end}. \cs{mfp@ifendorcomma} is useful for processing % comma-separated lists. If \cs{mfp@end} follows, it is removed and \arg1 % is executed. Otherwise, if a comma follows, it is removed and \arg2 is % executed. When neither follows, nothing is removed and \arg3 is % executed. Normally, this last is the main command being applied to each % element of the list. % \begin{macrocode} \def\mfp@iftoken#1#2{\@ifnextchar#1{\@firstoftwo{#2}}}% \def\mfp@ifstar#1#2#3{\mfp@iftoken*{#1{#2}}{#1{#3}}}% \def\mfp@ifend{\mfp@iftoken\mfp@end}% \def\mfp@ifendorcomma#1#2#3{\mfp@ifend{#1}{\mfp@iftoken,{#2}{#3}}}% % \end{macrocode} % % I've taken to making an empty optional argument the default for a lot % of commands. I wanted to make it possible to have the same result for % empty brackets (i.e., \texttt{[\,]}) as for omitted brackets. % \cs{mfp@ifempty} helps check for emptyness. It uses a simple \cs{if} so % that \arg{1} will be expanded. I use a non-active \texttt\textasciitilde % (so it won't expand) to test for emptiness because, even if % a tilde should accidentally occur in a user's \arg1, it will most % likely be the usual active version which expands to something else. % % The shorthand \cs{mfp@ifexist} executes some code if \arg1 is not % empty, otherwise it does nothing. And \cs{mfp@emptysub} expands to % \arg1 if it isn't empty, otherwise \arg2. % % The \cs{@ifmtarg} macro is borrowed from \file{ifmtarg.sty}. % It is used when a space should count as empty, but expansion isn't % needed. It would be nice to have one that counts both as empty, but % that seems impossible (or impossibly hard). % \begin{macrocode} {% \catcode`Q3 \catcode`\~12 \gdef\mfp@ifempty#1{\if~#1~\@xp\@firstoftwo\else\@xp\@secondoftwo\fi}% \gdef\mfp@ifexist#1{\if~#1~\@xp\@gobble\else\@xp\@firstofone\fi}% \gdef\mfp@emptysub#1#2{\if~#1~#2\else#1\fi}% \long\gdef\@ifmtarg#1{\@xifmtarg#1QQ\@secondoftwo\@firstoftwo\@nil}% \long\gdef\@xifmtarg#1#2Q#3#4#5\@nil{#4}% }% % \end{macrocode} % % These are the two most common methods to parse optional arguments. In % \cs{mfp@defaultopt}, if an optional argument is present, we use % \cs{mfp@ifemptyopt} to see if it is empty and substitute a default % (\arg{2}) if it is. Argument \arg{1} is the command to run % on the resulting argument after this check. It needn't be a single % command token, but can (and often will) be a series of commands, or a % command with additional arguments. % % \cs{mfp@nullopt} is a convenient abbreviation for a common case: the % default option is empty. We could define it in terms of % \cs{mfp@defaultopt}, but then we'd have the redundant step of checking % for an empty optional argument, only to replace it by an empty argument. % That might not make a significant difference, but it just feels wrong. % % Both commands turn the delimited argument, if present, into an ordinary % one. This extra step permits us to avoid many bracket pairs in later % code. % \begin{macrocode} \newdef\mfp@defaultopt#1#2{% \@ifnextchar[{\mfp@ifemptyopt{#1}{#2}}{#1{#2}}}% \newdef\mfp@ifemptyopt#1#2[#3]{\mfp@ifempty{#3}{#1{#2}}{#1{#3}}}% \newdef\mfp@nullopt#1{\@ifnextchar[{\mfp@getopt{#1}}{#1{}}}% \newdef\mfp@getopt#1[#2]{#1{#2}}% % \end{macrocode} % % Why do we bother to check for an empty optional argument? Because % quite a few \mfpic{} commands stuff several parameters into a % single optional argument. All but the last are processed as undelimited % arguments and the last one as delimited by the right bracket. If only % the last parameter is missing, TeX{} takes that as an empty argument and % we can proceed gracefully (substituting a default). However, if more % than that are missing, \TeX{} takes the closing bracket as the % \emph{undelimited} argument and produces pretty inscrutable error % mesages. This decision to add extra information in one optional argument % was, in retrospect, a bad one. It was made for backward compatibility % and (originally) to minimize the changes in existing commands. % Unfortunately we are stuck with it for at least the near future. % % Another reason is that multiple optional arguments generally mean that % the to specify a later one, all the previous ones need to be specified. % But with the above code, the user can always use an empty bracket pair % to indicate the default, minimizing the extra typing. % % % \section{Writing to the \file{.mf} or \file{.mp} file}\label{writing} % % \subsection{Preserving linebreaks}\label{linebreaks} % % Some macros (the ones we call list macros) can take quite long % arguments, especially if they are automatically generated by some % program. While the output file need not ever be looked at, there can be % a problem with lines too long for the \MF{} executable's line buffer. % Plus, for debugging, we might want to examine the file \mfpic{} writes. % We therefore try to get at least the list macros to preserve linebreaks % on output. % % We make use of the \TeX{} property that expandable commands are expanded % inside \cs{write} commands, but unexpandable commands and characters are % written verbatim (almost). If this were the only consideration, nothing % would need to be done. But characters with catagory code 5 (end-of-line) % are converted to spaces upon reading, so we have to change the category % of the \cs{endlinechar}, or we have change the \cs{endlinechar} to a % character of a different category. We do the former, because the line a % macro starts on will already have the end-of-line character added, but % it will not yet have been tokenized, so its category can be changed. We % need a category that \TeX{} will not \emph{ignore}, but that % nevertheless has no (or minimal) side effects if encountered in a \TeX{} % file. We therefore make it active, but \cs{let} it equal to \cs{relax}. % This makes the end-line-character unexpandable since \cs{relax} is not % expandable. % \begin{macrocode} \mfp@DBlog{Direct output to Metafont/Post file.}% {% \catcode\mfp@ctrlM\active% \gdef\@activectrlM{^^M}% \gdef\mfp@obeylines{\catcode\mfp@ctrlM\active\let^^M\relax}% }% % \end{macrocode} % % The choice \cs{relax} seems to be actually a slightly better choice % than \cs{endgraf} (which we used to use, and which equals the % unexpandable primative \cs{par}) because \cs{relax} is permitted before % the opening brace in the syntax of \meta{general text} (for token % variable assignments, \cs{write}, \cs{message}, and the like). % % The character assigned to \cs{endlinechar} is added to the end of all % lines read in by \TeX. The character assigned to \cs{newlinechar} % will produce a newline when it occurs in a \cs{write}. Our % \cs{mfp@keeplines} ensures these are the same and makes the above % changes in category. This will fail in the following case: % \cs{endlinechar} is not \verb$^^M$ and the data starts on the same line % as the command that issued \cs{mfp@keeplines}. But then the output will % lack only that first linebreak. % \begin{macrocode} \newdef\mfp@keeplines{\newlinechar\mfp@ctrlM \endlinechar\newlinechar \mfp@obeylines}% % \end{macrocode} % % We want our file writes to issue \cs{mfp@keeplines} before the text is % read (and category codes assigned). Also we often want to add a few % items to the argument (figure macros append a semi-colon, list macros % surround with parentheses), so we isolate the common starting code in % \cs{mfp@write}, and then invoke the appropriate continuation command. % % \DescribeMacro{\mfsrc} % This one is the most basic, merely writing its contents. For figure % macros, we ultimately call % \DescribeMacro{\mfcmd}\cs{mfcmd}, which appends a semicolon, % terminating any pending \MF{} command. For macros which take a comma % separated list of values as their arguments, we call % \DescribeMacro{\mflist}\cs{mflist} which surrounds the list in % parentheses and appends a semicolon % % The ending code is in \cs{mfp@src}. The \cs{begingroup} in % \cs{mfp@write} matches the \cs{endgroup} in \cs{mfp@src}. The group % isolates the changes to EOLs. We also define \cs{@nl} to expand to an % active control-M so that it can be used for line breaks in cases where % it is inconvenient to make EOLs active (in the replacement text of % \cs{opengraphsfile} and \cs{@mfpic}, for example). % \begin{macrocode} \newdef\mfsrc {\mfp@write\mfp@src\mfsrc}% \newdef\mfcmd {\mfp@write\mfp@cmd}% \newdef\mflist{\mfp@write\mfp@wlist}% \newdef\mfp@write{\begingroup\mfp@keeplines \let\@nl\@activectrlM}% % \end{macrocode} % % The macro \cs{mfp@src} does the job of writing to files. The output % stream \cs{mfp@out} is declared later. The other two commands invoke % \cs{mfp@src} on a slightly modified argument. The first argument to % \cs{mfp@src} is the command that called it (for the error message), the % second is the code to write. % \begin{macrocode} \newdef\mfp@src#1#2{% \mfp@ifopengraphsfile{\immediate\write\mfp@out{#2}}% {\mfp@nooutput@error{#1}}\endgroup}% \newdef\mfp@cmd#1{\mfp@src\mfcmd{#1;}}% \newdef\mfp@wlist#1{\mfp@src\mflist{(#1);}}% % \end{macrocode} % % \subsection{Initializing the output file}\label{output} % % Category 12 characters percent, sharp and backslash signs for the % \file{.mf} file. The command \cs{mfp@d} is used to write a line of % dashes above and below each figure to make them stand out when debugging % the file. % \begin{macrocode} \edef\mfp@p{\@xp\@gobble\string\%}% percent (%) \edef\mfp@s{\@xp\@gobble\string\#}% sharp (#) \edef\mfp@b{\@xp\@gobble\string\\}% backslash (\) \newdef\mfp@d{--------------}% % \end{macrocode} % % The current date and time stamp will be written to the \file{.mf} file. % We calculate it here and store the result in these macros. The commands % \cs{normalyear} and \cs{normalmonth} are part of \ConTeXt, where they % have been equated to the primitive commands \cs{year} and \cs{month} % (which are then redefined). % \begin{macrocode} \mfp@ifdefined\two@digits{}% {\def\two@digits#1{\ifnum#1<10 0\fi\number#1}}% {% \mfp@ifdefined\normalmonth {\let\month\normalmonth\let\year\normalyear}{}% \count@\time \divide\count@ by 60 \xdef\mfp@now{\number\year/\two@digits\month/\two@digits\day \space at \two@digits\count@:}% \multiply\count@ by -60 \advance\count@\time \xdef\mfp@now{\mfp@now\two@digits\count@}% }% % \end{macrocode} % % These registers are allocated: % \begin{itemize} % \item \cs{mfp@out} Write stream for the \file{.mf} or \file{.mp} file. % \item \cs{mfp@graph} Read stream used to test existence of files and % for reading datafiles. % \item \cs{mfp@count} Number for next \env{mfpic} environment. % \item \cs{mfp@linetype} Number indexing current line style in % multi-curve data plots. % \item \cs{mfp@sequence} Counter incremented with every datapoint written % from a file to implement the feature that a list of numeric data % can be plotted against its sequence position. % \item \cs{mfp@toks} Temporary token register. % \item \cs{mfp@verbtex} A temporary token list used by \cs{mfpverbtex}. % \item \cs{mfp@commonverbatimtex} Tokens written at the start of every % output file inside a \mfc{verbatimtex} group. % \item \cs{ifmfp@switch} Not exactly a register, but a temporary % switch for passing information from one macro to another. % \end{itemize} % \begin{macrocode} \mfp@DBlog{Declarations used with data and graphs files.}% \newwrite\mfp@out \newread\mfp@graph \newlet\mfp@data\mfp@graph \newcount\mfp@count \newcount\mfp@linetype \newcount\mfp@sequence \newtoks\mfp@toks \newtoks\mfp@verbtex \newtoks\mfp@commonverbatimtex \newif\ifmfp@switch % \end{macrocode} % % We store most of the \mfc{verbatimtex} block that \mfpic{} relies on in % the token register \cs{mfp@commonverbatimtex}. We do that because it % relies on a couple of catcode changes and we want to be in a situation % where we have that under control. Each line will end with an active % ctrl-M, which is transformed by \cs{mfsrc} into a newline. % % The \cs{mpxshipout} is to cover all three cases of the output of % `\texttt{mpto -tex}'. In public versions of \MP{} prior to 0.9 there was % no such command in that output file. In 0.9 and 0.901 that command is % defined at the start of the file, prior to any verbatimtex, but it is % buggy. This code overwrites it and fixes the bugs. In later versions a % good definition is used, but it appears only just before the first % \mfc{btex} and so will overwrite my definition. Thus all cases are % served. % \begin{macrocode} \begingroup \mfp@keeplines\@makeother\#% \@makeother\%\global\mfp@commonverbatimtex {\gdef\mpxshipout{\afterassignment\middlempxshipout\setbox0=\hbox}% \gdef\middlempxshipout{\aftergroup\finishmpxshipout}% \gdef\finishmpxshipout{\dimen1=\ht0 \dimen2=\dp0 \dimen0=\dimen1 \advance\dimen0\dimen2 \setbox0=\hbox{\hbox{\box0 \ifnum\dimen0>0 \vrule width1sp height\dimen1 depth\dimen2 \else \vrule width1sp height1sp depth0sp\relax \fi}}% \ht0=0pt \dp0=0pt \shipout\hbox{\box0}}% \def\MFPtext#1{\vbox{\def\\{\cr}\MFPcfont\everylabel \halign{##\hfil\cr#1\crcr}}}% }\endgroup % \end{macrocode} % % We store the first several lines that will be written to the output % file in a few internal macros, so that changing them will be easier. % % The first two lines of the output file are comments identifying the % file, the \mfpic{} version, the tex source file, and the timestamp. % These are stored in \cs{mfp@versioninfo}. We also let \grafbase{} know % the \mfpic{} version creating the file. This could catch version % mismatches. But since older \grafbase{} didn't test this, some % mismatches will be missed. % % After that (\cs{mfp@init@outfile}) we set the \mfc{mode}, the \mfc{mag} % (both ignored by \MP), and arrange for \grafbase{} macros to be loaded. % \begin{macrocode} \newdef\mfp@versioninfo{% \mfp@p\space\mfp@filename.m\mfp@ifmpost{p}{f}, generated by Mfpic, v\mfpfileversion\space\mfpfiledate,\@nl \mfp@p\space from TeX source "\jobname" on \mfp@now\@nl numeric mfpicversion; mfpicversion:=\mfpicversion;\@nl}% \newdef\mfp@init@outfile{% if unknown mode: mode = localfont; fi\@nl if unknown mag: mag = \number\mag/1000; fi\@nl if unknown grafbase: input grafbase; fi\@nl\@nl}% % \end{macrocode} % Then a comparison of the version of this file, stored in % \cs{mfpicversion} with the version stored in the \grafbase{} variable % \mfc{grafbaseversion}. This should catch a mismatch caused by an old % \grafbase{} with a current \mfpic. % \begin{macrocode} \newdef\mfp@versioncheck{% if unknown grafbaseversion: grafbaseversion = 0; fi\@nl if grafbaseversion <> mfpicversion :\@nl GBmsg "Bad mfpic installation: mfpic and grafbase % versions do not match.";\@nl fi\@nl}% % \end{macrocode} % % This opens the output file and prints a reminder to the user to run % \MF{} or \MP{}. % \begin{macrocode} \newdef\mfp@openfile{% \ifmfp@nowrite \else \mfp@msg{}% \Mfpic@msg{Initializing \mfp@filename\mfp@ext.}% \immediate\openout\mfp@out=\mfp@filename\mfp@ext\relax \Mfpic@msg{Don't forget to process \mfp@filename\mfp@ext!}% \Mfpic@msg{Apply \mfp@progname\space to \mfp@filename\mfp@ext% \mfp@ifmpost{}{, then gftopk to the resulting gf file}.}% \Mfpic@msg{Then reprocess this file "\jobname".\@nl}% \fi}% % \end{macrocode} % % A little bit of \LaTeX{} for checking file existence. % \begin{macrocode} \mfp@ifundefined\IfFileExists \def\IfFileExists#1{\openin\mfp@graph=#1\relax \ifeof\mfp@graph \@xp\@secondoftwo \else \immediate\closein\mfp@graph \@xp\@firstoftwo \fi}% \def\InputIfFileExists#1#2{\IfFileExists{#1}{#2\input #1\relax}}% \mfp@enddef % \end{macrocode} % % The following is the code involved in opening the output file and % checking for the existence of already created figures. % \cs{mfp@checkoutput} checks if the output file of \MP{} or \MF{} exists. % The first argument is the extension of that output file (\file{tfm} for % \MF{}, the starting value of the figure counter for \MP{}). We use the % existence of that output as a signal that there are graphics to be % included. % % Based on the file existence, we set the values of the draft switch, and % issue a message. Any other actions needed are passed as \arg2 (it % exists) and \arg3 (it doesn't). These are nonempty only under the % \opt{metafont} option: we load the font only if the \file{.tfm} exists, % otherwise we use a the \texttt{dummy} font. % % We do not try to load a nonexistent font because that might trigger some % \prog{maketfm} script which could be disastrous at this point, when the % \file{.mf} file is in an uncertain state. % \begin{macrocode} \newdef\mfp@checkoutput#1#2#3{% \IfFileExists{\setfilename\mfp@filename{#1}}% {\global\mfpicdraftfalse #2}% {\global\mfpicdrafttrue #3\mfp@msg{}% \Mfpic@msg{No file \setfilename\mfp@filename{#1}.}% }}% \newdef\mfp@checkMPoutput{\mfp@checkoutput{\number\mfp@count}{}{}}% \newdef\mfp@checkMFoutput{\mfp@checkoutput{tfm}% {\global\font\mfp@graphfont\mfp@filename\relax}% {\global\let\mfp@graphfont\mfp@dummy}}% % \end{macrocode} % % For \opt{metapost} the output file needs to load some color macros, and % write some setup for text labels (even if \cs{nomplabels}, because % \cs{usemplabels could be turned on later}). \MF{} now can also handle % the definitions in \file{dvipsnam.mp} but it seems a waste to load all % those definitions just to get more names for grayscales (even given % that \MF{} can find that file). % \begin{macrocode} \newdef\mfp@MPextras{\mfp@toks\@xp{\every@tlabel}% \mfsrc{% if unknown Apricot: input dvipsnam.mp; fi\@nl verbatimtex\@nl \ifmfp@verbtex \the\mfp@verbtex\@nl \fi \the\mfp@commonverbatimtex\@nl \def\noexpand\everylabel{\the\mfp@toks}\@nl etex;\@nl}% \global\mfp@verbtexfalse \global\mfp@verbtex{}% % \end{macrocode} % Finally, we process the \MP{}-specific options as they are currently % known. The \cs{usemplabels} was delayed until now so that the order of % it and \cs{usemetapost} before now would not matter. % \begin{macrocode} \@ifmplabels\usemplabels{}% \ifmfp@truebbox \usetruebbox \fi \ifmfp@overlabels \overlaylabels \fi}% % \end{macrocode} % % \DescribeMacro{\opengraphsfile} % This is the main command to set up the output file. % The name of the output file is its only parameter, and it appends % the extension \file{.mf} or \file{.mp} depending on the whether option % \opt{metafont} or \opt{metapost} was chosen. % \begin{macrocode} \mfp@DBlog{Macros to open and close graphs files.}% \newdef\opengraphsfile#1{\@bsphack % \end{macrocode} % A command can determine if it occurs after \cs{opengraphsfile} but % before \cs{closegraphsfile} by testing whether \cs{mfp@filename} is % defined. We also save the name of the processing program (\MF{} or \MP) % and the file extension (\file{.mf} of \file{.mp}) in macros for use in % messages. % \begin{macrocode} \def\mfp@tempa{#1}% \mfp@ifopengraphsfile% {\Mfpic@warn {\@nl An attempt has been made to open a graph file, \mfp@sanitized\mfp@tempa\@msgbreak while another, \mfp@filename, is still open. \@msgbreak Closing \mfp@filename.}\mfp@closegraphsfile}% {}% \xdef\mfp@filename{\mfp@sanitized\mfp@tempa} \xdef\mfp@progname{meta\mfp@ifmpost{pos}{fon}t}% \xdef\mfp@ext{.m\mfp@ifmpost{p}{f}}% % \end{macrocode} % % These commands test for the existence of the graphics (\file{.tfm} file % or first EPS file) and provisionally set \cs{ifmfpicdraft} based on the % result. Then the \file{.mf} or \file{.mp} file is opened, and the % automatic settings of \cs{ifmfpicdraft}, etc., are overridden if the % user has explicitly chosen the \opt{draft} or \opt{final} option. The % \opt{nowrite} option merely disables the \cs{mfp@src} command, called % by all the commands that write to the file. % \begin{macrocode} \mfp@ifmpost\mfp@checkMPoutput\mfp@checkMFoutput \mfp@openfile \ifmfp@draft \global\mfpicdrafttrue \fi \ifmfp@final \global\mfpicdraftfalse \fi \ifmfp@nowrite \gdef\mfp@src##1##2{\endgroup}\fi % \end{macrocode} % % Now we set up the header and preamble of the output file, writing % version info, initializations, version checking code and extra code % for \MP{}, if required. % % Finally, we process options as they are currently known. These were % delayed until now because they might require a write to the output file. % Finally, we read the \prog{meta*o*t} log file, if the option to do that % is in effect. % \begin{macrocode} \mfsrc{\mfp@versioninfo\mfp@init@outfile\mfp@versioncheck}% \mfp@ifmpost\mfp@MPextras{}% \ifmfp@clip \clipmfpic \fi \ifmfp@clearsym \clearsymbols \fi \ifmfp@noship \stopshipping \fi \ifmfp@readlog \mfp@readlogfile \fi \@esphack}% % \end{macrocode} % % \DescribeMacro{\closegraphsfile} % This command finishes off the output file and undefines \cs{mfp@filename}. % We define an error message free version \cs{mfp@closegraphsfile} for % internal use. We unconditionally undefine \cs{mfp@filename} just in % case. % \begin{macrocode} \newdef\closegraphsfile{% \mfp@ifopengraphsfile{}{\mfp@nooutput@error\closegraphsfile}% \mfp@closegraphsfile}% \newdef\mfp@closegraphsfile{% \mfp@ifopengraphsfile {\ifmfp@nowrite \else \mfsrc{\@nl end.}\immediate\closeout\mfp@out \fi \global\let\mfp@filename\UndEfInEd}{}}% % \end{macrocode} % % \subsection{Information from \MF: reading its log file} % % \DescribeMacro{\assignmfvalue}\SpecialUsageIndex{\globalassignmfvalue} % This macro was suggested by Werner Lemberg, who also supplied working % code. I have made modifications, so I am to blame if it has bugs. It % writes code to the \file{.mf} file that causes \MF{} to write % information to its \file{.log} file. If the option \opt{mfpreadlog} has % been set, that log file will be examined for that information. The % result, for example, of % \begin{verbatim} % \setmfvariable{numeric}{s}{10} % \assignmfvalue\foo{s+2} % \end{verbatim} % is that \cs{foo} will be a macro that expands to `\texttt{12}' (during % the \TeX{} run following the \MF{} pass). Under \opt{mplabels} a label % containing \cs{foo} will only be correct in the \file{.mp} file after % the second \MP{} pass, and so a third \TeX{} run may be required to % insert the correct figure. To implement localization, the code causes % the internal command \cs{mfpic-\meta{N}-foo} to be defined to the value, % where \meta{N} is the number of the current figure. The \cs{foo} is then % defined to the value of that internal command. Outside any \env{mfpic} % environment, the internal command is \cs{mfpic--foo}. If the \file{.log} % file doesn't exist or doesn't yet contain the information, \cs{foo} is % defined to `???'. % % While \cs{mfpicvalue} is merely a signal and doesn't need a % definition, we give it a useful definition for debugging: its own name. % It could be accidentally redefined by a user, but that will be harmless; % the debugging is mainly for me. % % It is possible to put \cs{global} in front of \cs{assignmfvalue} and % its macro will be defined globally in the \TeX{} run, but I could find % no way to make it global in the \file{.mp} file under \opt{mplabels}. % Thus, I've created a \cs{globalassignmfvalue}. % % \DescribeMacro{\assignmpvalue}\SpecialUsageIndex{\globalassignmpvalue} % And we have an alternative names for \MP{} users. % \begin{macrocode} \edef\mfpicvalue{\string\mfpicvalue}% \newdef\mfp@cmdname{% mfpic-\ifin@mfpicenv\number\mfp@count\fi-\@xp\@gobble\string}% \newdef\assignmfvalue{\mfp@assign\@empty}% \newdef\globalassignmfvalue{\mfp@assign\global}% \newdef\mfp@assign#1#2#3{% #1\edef#2{% \@ifundefined{\mfp@cmdname#2}{???}{\@nameuse{\mfp@cmdname#2}}}% \@ifundefined{\mfp@cmdname#2}% {\mfp@msg{}\Mfpic@msg{No value for \string#2 in mfpic figure \number\mfp@count.\@nl}}% {}% \mfsrc{\@ifmplabels{\@nl verbatimtex #1\def\string#2{#2} etex;\@nl}{}% message "\string\mfpicvalue";\@nl message "\mfp@cmdname#2";\@nl show #3;\@nl message "";}}% \newlet\assignmpvalue\assignmfvalue \newlet\globalassignmpvalue\globalassignmfvalue % \end{macrocode} % % The following code is what really makes \cs{assignmfvalue} work. It is % similar to code in the \prog{metatex} package, adapted by Werner Lemberg % and then modified by me. It steps through the \mfpic{} output file looking % for this signal: a line containing only `\verb$\mfpicvalue$'. It then % reads the next line, creates a macro name from it, and assigns to that % macro the value it reads on the next line. This is repeated to the end % of the file. % \begin{macrocode} \newdef\strip@gtgt>> #1\mfp@end{#1}% \newdef\mfp@readlogfile{% \openin\mfp@data=\mfp@filename.log\relax \ifeof\mfp@data \Mfpic@msg{No file \mfp@filename.log.}% \else {% \mfp@resetwhitespace \endlinechar -1 \catcode`\>12 \def\@mfpicvalue{\mfpicvalue}% \message{< Mfpic: Reading \mfp@filename.log}% \mfp@readloglines \message{>}% }% \fi \closein\mfp@data}% \newdef\mfp@readloglines{% \read\mfp@data to \mfp@tempa \ifeof\mfp@data \else \ifx\mfp@tempa\@mfpicvalue \read\mfp@data to \mfp@tempa \read\mfp@data to \mfp@tempb \@XP\xdef\@nameuse\mfp@tempa{\@xp\strip@gtgt\mfp@tempb\mfp@end}% \fi \@xp\mfp@readloglines \fi}% % \end{macrocode} % % % \section{\Mfpic{} dimensions}\label{dimensions} % % A number of packages, especially figure drawing packages, allocate a % great many dimension registers. The most familiar example is \PiCTeX{} % which is at least partially responsible for most ``No room for a new % \cs{dimen}'' error messages. \Mfpic{} also needs many dimension % values, but some are set by macros that simply write the value to the % \file{.mf} file and do not use any registers. A few are stored in % \TeX{} registers, but most are stored using a trick with font % dimensions. % \begin{macrocode} \mfp@DBlog{Using dummy font's dimensions, to spare TeX registers.}% % \end{macrocode} % % While most fonts have relatively few font dimensions (twenty-two is a % common number), it turns out that if one loads a font and immediately % assigns a value to \cs{fontdimen}~$n$, Then \TeX{} acts as if the font % has \cs{fontdimen}\,s 0 through $n$ available. They can be assigned % dimension values just like \TeX{} dimension registers. % % Virtually all \TeX{} systems have a \file{dummy.tfm}, which contains % no characters (it is used for syntax checking by some packages and % classes). Since this trick will only work if we are the first to % load the font (the \AmSTeX{} document style \file{amsppt.sty} loads % the dummy font), we use another trick, which is to load it scaled to % some unlikely value, which \TeX{} treats as a new font. % \begin{macrocode} \font\mfp@dummy=dummy scaled 1042 \fontdimen100\mfp@dummy0pt % \end{macrocode} % % Some versions of \file{dummy.tfm} have values already assigned to font % dimensions 0 through 22. It would probably not hurt to use those, but % we'll be cautious and use only font dimensions 23 and up, making 78 % available. % % We use an auxiliary count register to keep track of new font dimens. % \begin{macrocode} \newcount\mfp@fdc \mfp@fdc22 % \end{macrocode} % % We define a macros that mimics the behavior of \cs{newdimen}, for % allocating font dimension numbers. It increments \cs{mfp@fdc} and % defines its argument \arg{1} to expand to a reference to the % \cs{fontdimen} with that number. The syntax it produces is valid as % the left side of a dimension assignment and also as a dimension % that may follow a real factor and \cs{the}. For example, later we say % \cs{newfdim}\cs{pointsize} and give it the value \texttt{2pt}. Then % \verb$\the\pointsize$ prints this value and % \verb$\pointsize = 0.5\pointsize$ is a valid assignment. % \begin{macrocode} \newdef\newfdim#1{% \global\advance\mfp@fdc1 \xdef#1{\fontdimen\number\mfp@fdc\mfp@dummy}% \wlog{\string#1=\fontdimen\number\mfp@fdc\mfp@dummy}}% % \end{macrocode} % \TeX{} will not accept font dimensions in its syntax for the dimension % arithmetic commands \cs{advance}, \cs{multiply} and \cs{divide}. In the % rare cases where we need to do this we assign the value to a temporary % register and calculate with it. % % We allocate a couple of boxes. At the end of an \mfpic{} % environment, \cs{@wholegraph} is loaded with the picture (possibly % null) as it exists then. Inside the environment, when text labels are % processed, \cs{@textbox} holds this text temporarily so it can be % measured, moved about, etc. We also define abbreviations for the % frequent commands that specify the dimensions of \cs{@textbox} % \begin{macrocode} \mfp@DBlog{A box register for whole labeled graph, % and a temporary one.}% \newbox\@wholegraph \newbox\@textbox \newdef\tb@ht{\ht\@textbox}% \newdef\tb@dp{\dp\@textbox}% \newdef\tb@wd{\wd\@textbox}% % \end{macrocode} % % When labels are processed, they are accumulated in the box % \cs{@alltlabels}. We allocate it, and four \cs{newfdim}\,s for the % location of three of the sides (We don't need the fourth). The box % \cs{@backtext} holds `background text', that is, text accumulated % between \cs{startbacktext} and \cs{stopbacktext}. % \begin{macrocode} \newbox\@alltlabels \newbox\@backtext \newfdim\@tlabelstop \newfdim\@tlabelsbot \newfdim\@tlabelsleft % \end{macrocode} % % The following fontdims record the dimensions of the box containing the % picture. We need to adjust them when the text labels are added to the % picture, because \TeX{} doesn't do it automatically. For example, % kerning left outside the picture will not change the picture box's % reference point. % \begin{macrocode} \mfp@DBlog{Internal dimension parameters for graph dimensions...}% \newfdim\@graphright \newfdim\@graphleft \newfdim\@graphtop \newfdim\@graphbot \mfp@DBlog{...and dimension parameters for tlabel positioning.}% \newfdim\tb@raise \newfdim\tb@moveright \newfdim\tb@totalht % \end{macrocode} % % The following are for label adjustments. The first two are used to % implement the feature that all labels can be simultaneously shifted an % equal amount. The third is for the feature that the label can be a % certain distance separated from the point where it is placed. And the % last establishes the distance between a label and a path surrounding it. % \begin{macrocode} \newfdim\tlabel@hadj \newfdim\tlabel@vadj \newfdim\tlabel@sep \newfdim\tlpath@sep \tlabel@hadj0pt \tlabel@vadj0pt \tlabel@sep0pt \tlpath@sep0pt % \end{macrocode} % % It can be argued that dimensions not needed by \TeX{} should be stored % in the output file rather than allocating (font) dimensions. These are % everything below from \cs{pointsize} through \cs{symbolspace}, % inclusive. This would make synchrony between \TeX{} and \MF{} easier % to maintain. Those that are needed by \TeX{} are then few enough to be % regular \cs{dimen} registers, making them automatically local to each % \env{mfpic} environment. Unfortunately, changing to such a scheme could % break some past \mfpic{} files. It would also require recoding every % command that now writes one of these dimensions to the output. % % The following are default parameters for various graphics commands that % take an optional argument for the size of something. % \begin{itemize} % \item\cs{mfpicunit}\SpecialUsageIndex{mfpicunit}, the unit of length in % a picture. \cs{@mfpicunit} is used internally. % \item\cs{pointsize}\SpecialUsageIndex{pointsize}, the diameter of a % \cs{point}. % \item\cs{shadespace}\SpecialUsageIndex{shadespace}, the spacing of dots % in \cs{shade}. % \item\cs{polkadotspace}\SpecialUsageIndex{polkadotspace}, the spacing of % polkadots. % \item\cs{hatchspace}\SpecialUsageIndex{hatchspace}, the spacing of hatch % lines. % \item\cs{headlen}\SpecialUsageIndex{headlen}, the size of arrowheads % (except on axes). % \item\cs{axisheadlen}\SpecialUsageIndex{axisheadlen}, the size of the % arrowhead for $x$- and $y$-axes. % \item\cs{sideheadlen}\SpecialUsageIndex{sideheadlen}, the size of the % arrowhead for border axes. % \item\cs{hashlen}\SpecialUsageIndex{hashlen}, the length of tic marks on % axes. % \item\cs{dashlen}\SpecialUsageIndex{dashlen}, the length of dashes in % \cs{dashed}. % \item\cs{dashspace}\SpecialUsageIndex{dashspace}, the space between such % dashes. % \item\cs{dotsize}\SpecialUsageIndex{dotsize}, the size of dots for % \cs{dotted}. % \item\cs{griddotsize}\SpecialUsageIndex{griddotsize}, the size of dots % for \cs{grid} and \cs{plrgridpoints}. % \item\cs{dotspace}\SpecialUsageIndex{dotspace}, the space between such % dots. % \item\cs{symbolspace}\SpecialUsageIndex{symbolspace}, the space between % symbols used in a \cs{plot} command. % \end{itemize} % We allocate them, and then initialize them. % \begin{macrocode} \mfp@DBlog{User level dimension parameters, with default settings.}% \newfdim\mfpicunit \newfdim\@mfpicunit % internal version \newfdim\pointsize \newfdim\shadespace \newfdim\polkadotspace \newfdim\hatchspace \newfdim\headlen \newfdim\axisheadlen \newfdim\sideheadlen \newfdim\hashlen \newfdim\dashlen \newfdim\dashspace \newfdim\dotsize \newfdim\griddotsize \newfdim\dotspace \newfdim\symbolspace \mfpicunit1pt \pointsize2pt \shadespace1pt \polkadotspace10pt \hatchspace3pt \headlen3pt \axisheadlen5pt \sideheadlen0pt \hashlen4pt \dashlen4pt \dashspace4pt \dotsize0.5pt \griddotsize0.5pt \dotspace3pt \symbolspace5pt % \end{macrocode} % % Font dimensions are global, and so not restricted to an \env{mfpic} % environment even when assigned inside one. This would require the % user to restore a value every time one picture needed a different % value from the rest. To avoid requiring this, the following macro is % used to save all values of these dimensions at the start of a picture, % and to restore the saved values at the end. Some internal dimensions % (all the \cs{@graph...}, \cs{@tlabels...} and \cs{tb@...}) don't need % saving since they are reset with each picture. % \begin{macrocode} \newdef\save@mfpicdimens{% \edef\restore@mfpicdimens{% \mfpicunit \the\mfpicunit \pointsize \the\pointsize \shadespace \the\shadespace \polkadotspace \the\polkadotspace \hatchspace \the\hatchspace \headlen \the\headlen \axisheadlen \the\axisheadlen \sideheadlen \the\sideheadlen \hashlen \the\hashlen \dashlen \the\dashlen \dashspace \the\dashspace \dotsize \the\dotsize \griddotsize \the\griddotsize \dotspace \the\dotspace \symbolspace \the\symbolspace \tlabel@hadj \the\tlabel@hadj \tlabel@vadj \the\tlabel@vadj \tlabel@sep \the\tlabel@sep \tlpath@sep \the\tlpath@sep}}% % \end{macrocode} % % Here are the few dimension registers we do allocate: % \SpecialUsageIndex{\mfpframesep}\cs{mfpframesep}, and % \SpecialUsageIndex{\mfpframethickness}\cs{mfpframethickness} % govern frames. % \SpecialUsageIndex{\mfpicheight}\cs{mfpicheight} and % \SpecialUsageIndex{\mfpicwidth}\cs{mfpicwidth} are set % after each picture to that picture's size. A \cs{vskip} of % \SpecialUsageIndex{\mfpiccaptionskip}\cs{mfpiccaptionskip} is placed % between figure and caption by \cs{tcaption}. We also allocate a % frequently used scratch register % \begin{macrocode} \newdimen\mfp@scratch \newdimen\mfpframesep \newdimen\mfpframethickness \newdimen\mfpicheight \newdimen\mfpicwidth \newskip\mfpiccaptionskip \mfpframethickness0.4pt \mfpframesep2pt \mfpiccaptionskip\medskipamount % \end{macrocode} % % % \section{Helper macros}\label{helper} % % \DescribeMacro{\mfpicnumber} % We make a user-level macro for setting the number of the next graph. % The original purpose of this is so that the font file could have % characters in the positions of printable characters. Then creating a % composite figure is as easy as changing fonts: \marg{\cs{pic} ABABAAB}. % The motivation came from a discussion on \texttt{comp.text.tex} started % by someone who wanted to input a sequence of 0's and 1's and get a % sequence of black and white squares. For \MP{} users it is not very % important. % \begin{macrocode} \def\mfpicnumber#1{\global\mfp@count#1\relax}% % \end{macrocode} % % \DescribeMacro{\mfpaddto} % When placing text at intervals on an axis, we need to automatically % calculate coordinates to feed to the \cs{tlabel} command. The % following is a utility macro to add two real numbers. It is currently % used only in the \cs{axislabels} command, so it needn't be globally % defined, but it might be handy in the future. % \begin{itemize} % \item[] \arg{1} is a \emph{macro} that expands to some number. % \item[] \arg{2} is a number to add to it. % \end{itemize} % The result is stored again in \arg{1}, overwriting the old value. % % \DescribeMacro{\mfpmultiply} % This is the multiplicative version, with the same syntax and behavior. % It is not used anywhere yet. % \begin{macrocode} \newdef\mfpaddto#1#2{\mfp@scratch#1pt \advance\mfp@scratch#2pt \edef#1{\strip@pt\mfp@scratch}}% \newdef\mfpmultiply#1#2{\mfp@scratch#1pt \mfp@scratch#2\mfp@scratch \edef#1{\strip@pt\mfp@scratch}}% \mfp@ifundefined\strip@pt \begingroup \lccode`\/`\p \lccode`\?`\t \lowercase{% \endgroup \def\rem@pt#1.#2/?}{#1\ifnum#2>\z@.#2\fi}% \def\strip@pt{\@xp\rem@pt\the}% \mfp@enddef % \end{macrocode} % % \DescribeMacro{\pointdef} % A point defining macro, suggested by a user. % \begin{itemize} % \item[] \arg{1} is a symbolic name for a point, only letters. % \item[] \arg{2} and \arg{3} are the coordinates. % \item[] Usage: \cs{pointdef}\marg{A}\parg{2,5} makes \cs{A} expand % to \texttt{(2,5)}, \cs{Ax} to \texttt{2}, and \cs{Ay} to % \texttt{5}. % \end{itemize} % \begin{macrocode} \newdef\pointdef#1(#2,#3){% \@ifundefined{#1} {}{\Mfpic@warn{\mfp@b#1 already defined.}}% \@ifundefined{#1x}{}{\Mfpic@warn{\mfp@b#1x already defined.}}% \@ifundefined{#1y}{}{\Mfpic@warn{\mfp@b#1y already defined.}}% \@namedef{#1}{(#2,#3)}\@namedef{#1x}{#2}\@namedef{#1y}{#3}}% % \end{macrocode} % % \DescribeMacro{\setmfarray} % This enables the simultaneous definition of \MF{} (or \MP) variables % such as \mfc{A1}, \mfc{A2}, etc., by writing % \cs{setmfarray}\marg{\meta{type}}\marg{\meta{name}}\marg{\meta{list}}, % the \meta{name} being any \MF{} variable without a suffix, the list being % a comma separated list of items of the appropriate \meta{type}. % For example, \cs{setmfarray}\marg{pair} would require a list of % pairs. % % \SpecialUsageIndex{\numericarray} % As with \cs{setmfvariable}, we provide a few abbreviations. % \cs{numericarray} is for arrays of numeric variables, % \SpecialUsageIndex{\pairarray} \cs{pairarray} for arrays of pair % variables and \SpecialUsageIndex{\colorarray}\cs{colorarray} is for % arrays of color variables. Finally, to set arrays globally, there is % \SpecialUsageIndex{\globalsetmfarray}\cs{globalsetmfarray}. % \begin{macrocode} \newdef\setmfarray#1#2{\mfsrc{setarray (#1) (#2)}\mfp@writedata}% \newlet\setmparray\setmfarray \newdef\pairarray{\setmfarray{pair}}% \newdef\numericarray{\setmfarray{numeric}}% \newdef\colorarray{\setmfarray{color}}% \newdef\globalsetmfarray#1#2{\mfsrc{gsetarray (#1) (#2)}\mfp@writedata}% % \end{macrocode} % % Shade adjustment macros. % \DescribeMacro{\lightershade}\cs{lightershade} % just multiplies \cs{shadespace} by $1.2$. While % \DescribeMacro{\darkershade}\cs{darkershade} divides by $1.2$ % (actually, multiplies by $1/1.2$) % \begin{macrocode} \newdef\lightershade{\shadespace1.2\shadespace}% \newdef\darkershade{\shadespace.83333\shadespace}% % \end{macrocode} % % \DescribeMacro{\dashlineset} % The following arrange for contrastive dashed lines. \cs{dashlineset} % just resets the default parameters that the \cs{dashed} macro uses, % \DescribeMacro{\dotlineset} % \cs{dotlineset} sets these parameters so that \cs{dashed} produces % something almost dotted. % \begin{macrocode} \newdef\dashlineset{\dashlen4pt \dashspace4pt }% \newdef\dotlineset{\dashlen1pt \dashspace2pt }% % \end{macrocode} % % \DescribeMacro{\pointfilltrue} % With the commands \cs{pointfilltrue} or \cs{pointfillfalse} the user % can specify points drawn with the \cs{point} command to be either % filled in or \DescribeMacro{\pointfillfalse}not. % \begin{macrocode} \let\ifpointfill\iftrue \newdef\pointfilltrue{\mfp@let\ifpointfill\iftrue}% \newdef\pointfillfalse{\mfp@let\ifpointfill\iffalse}% % \end{macrocode} % % \CMF{} has very flexible looping capabilities. Before version 0.8 there % was no \mfpic{} interface because it seemed that \cs{mfsrc} was the % simplest way to access this capability. Anything else would have to % be either a clone of \cs{mfsrc} or limit the possibilities. However, I % now believe it might be a good thing to have a structured way to perform % repetitive actions at the \MF{} level. % % As of version 0.9, \mfpic{} will allow loops outside \env{mfpic} % environments. It seems like a reasonable thing to be allowed to do. % Fortunately, the macro names are already unique. % % \DescribeMacro{\mfpfor} % This is the simplest: it writes the word \mfc{for} plus the contents of % its only mandatory argument, followed by a colon. The loop is ended by % \DescribeMacro{\endmfpfor}\cs{endmfpfor} which merely writes the text % \mfc{endfor}. % \begin{macrocode} \newdef\mfpfor#1{\begingroup\mfsrc{for #1:}}% \newdef\endmfpfor{\mfsrc{endfor}\endgroup}% % \end{macrocode} % % \DescribeMacro{\mfploop} % This starts a loop with \mfc{forever}. The user is expected to provide % an escape condition with \DescribeMacro{\mfpuntil}\cs{mfpuntil}, which % can be placed anywhere among the commands contained in the % \env{mfploop} environment. \DescribeMacro{\endmfploop}\cs{endmfploop} % is a clone of \cs{mfpfor} except for the warning. Grouping keeps % the warning from being turned off if \cs{mfpuntil} occurs in a nested % loop. % \begin{macrocode} \newdef\mfploop{% \begingroup\mfsrc{forever:}\let\@nountil\mfp@untilwarn}% \newdef\mfpuntil#1{\mfcmd{exitif #1}\let\@nountil\@empty}% \newdef\endmfploop{\@nountil\endmfpfor}% % \end{macrocode} % % \DescribeMacro{\mfpwhile} % This emulates a while-loop, the condition being given in the mandatory % argument. It has the same behavior, and writes almost the same code as % \cs{mfploop} with an immediate \cs{mfpuntil} using the negative of the % condition. The closing, \DescribeMacro{\endmfpwhile}\cs{endmfpwhile}, % is again the same as \cs{endmfpfor}. % \begin{macrocode} \newdef\mfpwhile#1{\begingroup\mfcmd{forever: exitif not(#1)}}% \newlet\endmfpwhile\endmfpfor % \end{macrocode} % % \DescribeMacro{\plr} % A little utility to convert a list of pairs into another list of % pairs, where the given list are assumed to be polar coordinates and the % results are their Cartesian counterparts. This is guaranteed to work as % expected only in macros with a list argument, or for a single pair. % \DescribeMacro{\midpoint} % And one to calculate the midpoint, given two points separated by a comma. % Can be used in graphics macros where a point is required. % \begin{macrocode} \newdef\plr#1{map (polar) (#1)}% \newdef\midpoint#1{(0.5[#1])}% % \end{macrocode} % % % \section{Macros to implement prefix commands}\label{prefix} % % Some \mfpic{} macros, like \cs{circle} create a path. When used without % a prefix, they also draw the path. At the \MF{} level, every figure % macro is syntactically a path expression. Other macros are prefix macros % and operate on a figure macro that follows. Every prefix accepts a path % expression as input and has a path as its return value, so a combination % prefix + path expression is again a path expression. % % Prefixes may also have side effects, such as adding some ink to the % current picture. Such prefixes are called \emph{rendering} macros. % % Rendering macros normally return the same path as their argument, but % there are macros that modify the path. Some apply a linear transform, % some close an open path, some return a subpath. These we call % \emph{modification} macros. % % This scheme is quite simple, but unfortunately too simple. To avoid % having to explicitly type a rendering prefix every time, a figure % macro needs to know if a rendering prefix has occured, so prefix macros % need to pass information to the figure macro (and to later prefixes). % % Moreover, \MF{} abhors an `isolated expression', so the first prefix % has to write something with a different syntax, and pass the info that % it has already done so on to later prefixes, who need to test that % info. Thus, every prefix macro needs to know if it is the first or a % later one. They test this \cs{if} command and also set it to false. The % figure macros, which are last in the chain, close by resetting it true. % \begin{macrocode} \mfp@DBlog{Tests to control multiple prefix commands.}% \newif\if@mfpstart\@mfpstarttrue % \end{macrocode} % % If a prefix is a rendering prefix, it writes its rendering code and sets % the following switch to false, letting the figure macro know it needn't % invoke the default rendering. Figure macros close by resetting it true. % Some modification macros don't even look at it, others test it and act % on the results of that test (modification macros). % \begin{macrocode} \newif\if@mfprend\@mfprendtrue % \end{macrocode} % % The following macro is always (and only) invoked by the first prefix % macro (or the figure macro, if there are no prefixes). It writes the % code that prevents an isolated expression. It stores the following path % expression in the variable \gbc{curpath}. Thus every combination of % prefixes followed by a figure macro is syntactically a \MF{} variable % assignment command. % \begin{macrocode} \newdef\mfp@storepath{\mfsrc{\@nl store (curpath)}}% % \end{macrocode} % % Every prefix and figure macro has to invoke \cs{mfp@first}, since each % is potentially the first in the sequence. If \cs{@mfpstart} is true, it % writes the storing command, sets \cs{@mfpstartfalse}, and says that % rendering is needed. (The rendering macros immediately cancel that % switch.) % \begin{macrocode} \newdef\mfp@first{\relax \if@mfpstart \mfp@storepath \@mfprendtrue \@mfpstartfalse\fi}% % \end{macrocode} % % Every rendering macro invokes this next command. After the first-stage % code it writes its rendering command (via \cs{mfsrc}) and passes on the % info that rendering is no longer required of the figure macro. % \begin{macrocode} \newdef\mfp@rendmac{\mfp@first \@mfprendfalse \mfsrc}% % \end{macrocode} % % The \emph{figure} macros proceed as follows: (i)~they invoke the % \cs{mfp@first} code, then (ii)~write a rendering macro if necessary % (\cs{mfp@autorend}), (iii)~then make \cs{@mfpstarttrue} (for the next % figure) and write \MF{} code that defines the path. The \cs{mfp@modmac} % macros do only the first two, then write their modification code, % counting on the following figure macro to do (iii). The idea is that % [modifier + figure] should act the same as if the path it defines were % encoded as a single figure command. % \begin{macrocode} \newdef\mfp@modmac{\mfp@first\mfp@autorend\mfsrc}% \newdef\mfp@autorend{\if@mfprend\@xp\mfp@render\fi}% % \end{macrocode} % % Only axis and arrow commands (plus \cs{reverse}) use \cs{mfp@addmac}. % As the name suggests, something is added onto an existing figure. That % is, it is designed to ignore the rendering state and not invoke implicit % rendering. If no explicit rendering occurs, the figure macro that % follows invokes a rendering. For arrows, this causes the arrowhead to be % drawn on top of the drawing of the shaft. % % It would seem \cs{reverse} doesn't fit this name, but it also needs to % be transparent to the rendering state so that it will work in % combination with arrows. % % \cs{mfp@addmac} simply invokes the common first-stage code and writes % its \MF{} code. % \begin{macrocode} \newdef\mfp@addmac{\mfp@first \mfsrc}% % \end{macrocode} % % The \cs{mfp@addmac} and \cs{mfp@modmac} macros differ when there are no % preceeding rendering macros. In that case it is as if \cs{draw} (or % more generally \cs{mfp@render}) precedes the \cs{mfp@modmac} macro. That % drawing happens \emph{in addition to} any rendering macros that follow. % This implicitly added \cs{draw} is not present for \cs{mfp@addmac} % macros; it is added by the following figure macro. The effect of this is % the \cs{mfp@addmac} macros perform their additions on top of an already % rendered figure. % % \DescribeMacro{\setrender} % As mentioned above, when a figure macro is invoked without a rendering % prefix, it will invoke some default. That default is stored in a macro % and can be changed for special effects. Initially we define it as % \cs{draw} (with empty optional argument) to draw solid paths in the % default color, but we provide a command for the user to change it. % \begin{macrocode} \newdef\mfp@render{\draw[]}% \newdef\setrender#1{\mfp@def\mfp@render{#1}}% % \end{macrocode} % % A figure macro will invoke the common first-stage code and the rendering % check. It also resets the \cs{@mfpstart} switch. Because a figure macro % completes an assignment command in \MF, it writes its code with % \cs{mfcmd}, which places a semicolon at the end. We define the first % part (all but the writing) as a separate command because there are a few % cases where we need to delay that writing. % \begin{macrocode} \newdef\mfp@figmacbase{\mfp@first \mfp@autorend \@mfpstarttrue}% \newdef\mfp@figmac{\mfp@figmacbase\mfcmd}% % \end{macrocode} % % The list macros take as their last argument a list of $(x,y)$ pairs (or % occasionally a list of numbers). That list can either be typed directly % into the \TeX{} source file (inside braces, separated by commas) or be % present in an external datafile. Either way, the data is written as a % list within an enclosing pair of parentheses. Since these are all % figure macros, \cs{mfp@listmac} starts out just like \cs{mfp@figmac}, % but it writes only part of its arguments, the last one (the data list) % being handled by \cs{mfp@writedata}. % % \cs{mfp@writedata} looks ahead to see if the token \cs{datafile} % follows, if it does \cs{mfp@writefile} is invoked, which gobbles % the \cs{datafile} token and processes the filename that should follow it. % Otherwise, \cs{mflist} is invoked to write the list in braces % that should follow. % % \cs{mfp@writedata} is also used by non-figure macros such as the axis % marks macros, plus \cs{piechart} and \cs{barchart}. % \begin{macrocode} \newdef\mfp@listmac#1{\mfp@figmacbase\mfsrc{#1}\mfp@writedata}% \newdef\mfp@writedata{\mfp@iftoken\datafile{\mfp@writefile}{\mflist}}% \newdef\mfp@writefile{% \mfp@ifopengraphsfile {\mfp@processfile{\mfp@rwdata}}{\mfp@nooutput@error\datafile}}% % \end{macrocode} % % \DescribeMacro{\mftitle} % This is mainly for debugging the example files. \cs{mfp@title} takes % two arguments: the command that called it (for the error message of % \cs{mfp@src}), and some \TeX{} code. That code is written into the string % argument of the \grafbase{} command \gbc{mftitle} and ends up in the % \MF{} \file{.log} file and as a comment in the GF file. \cs{mftitle} % merely calls \cs{mfp@title}, while \DescribeMacro{\tmtitle}\cs{tmtitle} % also writes the argument to the \TeX{} \file{.log} file and typesets it % in the document. % % We write the argument as a token list because that is the the easiest % verbatim-like way to do it. % \begin{macrocode} \newdef\mftitle#1{\@bsphack\mfp@title\mftitle{#1}\@esphack}% \newdef\tmtitle#1{\mfp@title\tmtitle{#1}\wlog{\the\mfp@toks}{#1}}% \newdef\mfp@title#1#2{\mfp@toks{#2}% \mfp@write\mfp@src#1{mftitle "\the\mfp@toks";}}% % \end{macrocode} % % % \section{Macros for getting data from files}\label{rwdata} % % The following command contains the common code to open a data file for % reading. The second parameter is the filename, the first is what to do % if it exists and is nonempty. We first try to \cs{openin} the file and % issue an error message if that fails. Then we skip any initial blank % lines and comments and complain if that takes us to the end of the % file. Otherwise we execute the command specified. Afterwards, since % each \cs{plotdata} command in a given \env{mfpic} environment % starts with the linetype at which the previous one ended, we allow the % value of \cs{mfp@linetype} to survive this group but not any enclosing % group. % \begin{macrocode} \newdef\mfp@processfile#1#2{% \openin\mfp@data=#2\relax \ifeof\mfp@data \mfp@nofile@error{#2}% \else \mfp@DBlog{Opening file #2 for data.}% {% \mfp@resetwhitespace \mfp@setcomment \mfp@skipblanklines \ifeof\mfp@data \mfp@nodata@error{#2}% \else \message{< Mfpic: Reading #2}% #1% \message{>}% \fi \@xp }\@xp\mfp@linetype\number\mfp@linetype\relax \mfp@DBlog{Closing file #2.}% \fi \closein\mfp@data}% % \end{macrocode} % % When reading files it is important that white space in the files % always have the same meaning for \TeX{}. This utility resets spaces, % tabs and EOLs to the standard categories. % \begin{macrocode} \newdef\mfp@resetwhitespace{\mfp@restorepar \endlinechar`\^^M \catcode`\^^M5 \catcode`\ 10 \catcode`\^^I10 }% % \end{macrocode} % % \cs{mfp@skipcomments} % does what it says, skipping comments in a data file. It reads a % line from a previously opened file (input stream \cs{mfp@data}) and % compares it to \cs{@empty}. It calls itself when they are equal (a % comment line, a blank line would put a \cs{par} token in \cs{mfp@data}). % When this macro finishes, \cs{mfp@temp} contains either \cs{par} (blank % line or EOF) or real data. % \begin{macrocode} \newdef\mfp@skipcomments{\read\mfp@data to \mfp@temp \ifx\mfp@temp\@empty \@xp\mfp@skipcomments\fi}% % \end{macrocode} % % \cs{mfp@skipblanklines} % first skips comments. After that \cs{mfp@temp} can contain \cs{par}, % indicating either EOF or a blank line, or something else. In the first % case (EOF) the macro terminates, in the second case (blank) it calls % itself again, in the other case (something else) it also terminates, % having presumably found real data. % % When this is called, a file should already be open using the handle % \cs{mfp@data}. % \begin{macrocode} \newdef\mfp@skipblanklines{\mfp@skipcomments \ifeof\mfp@data \else\ifx\mfp@temp\mfp@par \@XP\mfp@skipblanklines \fi\fi}% % \end{macrocode} % % The following two commands, \cs{mfp@rwdata} and \cs{mfp@rwdataloop} % perform the work of writing the file (read stream \cs{mfp@data} opened % by \cs{mfp@processfile}). % % The figure counter \cs{mfp@count} is reused (this should all be inside % a group) to keep track of how many lines of the data file have been % written to one line of the output. The token \cs{sequence} in a % \cs{using} specification will expand to the value of the counter % \cs{mfp@sequence}. % % When \cs{mfp@rwdata} is called, a non-blank line has been read to the % macro \cs{mfp@temp}, to which we now add a space. The macro % \cs{mfp@buffer} is what will be written to the output file as soon as it % is long enough. We initialize it by defining it to be an open % parenthesis followed by the result of applying \cs{parse@data} to the % contents of \cs{mfp@temp}. Then we call \cs{mfp@rwdataloop}, which does % the remaining reading and all the writing. % \begin{macrocode} \newdef\mfp@nextdatum{\@xp\parse@data\mfp@temp\mfp@end}% \newdef\mfp@rwdata{\mfp@count1 \mfp@sequence1 \def\sequence{\number\mfp@sequence}% \edef\mfp@temp{\mfp@temp\space}% \edef\mfp@buffer{(\mfp@nextdatum}\mfp@rwdataloop}% % \end{macrocode} % % At this point, the buffer has been started with the first datum, so we % read another line. If that is blank, we write the buffer (and the closing % parenthesis and a semicolon) and terminate the loop. Otherwise we have % read another datum and then we: % \begin{enumerate} % \item increment the sequence counter, % \item add a comma to the buffer, % \item test whether the buffer is `full', and if so, write the buffer % to the output and clear it, then % \item add the datum to the buffer. % \end{enumerate} % The buffer is `full' when \cs{mfp@count} (the number of data in the % buffer) exceeds \cs{mfp@dataperline}. % % \cs{mfp@rwdataloop} loops by calling itself at the end. Whenever % \cs{mfp@temp} is empty (comment line read), (1)--(4) are skipped and % another line read. % \begin{macrocode} \newdef\mfp@rwdataloop{% \read\mfp@data to \mfp@temp \ifx\mfp@temp\mfp@par \mfcmd{\mfp@buffer)}% \else \ifx\mfp@temp\@empty \else \edef\mfp@temp{\mfp@temp\space}% \advance\mfp@sequence1 \edef\mfp@buffer{\mfp@buffer\mfp@join}% \ifnum\mfp@count<\mfpdataperline\relax \advance\mfp@count1 \else \mfsrc{\mfp@buffer}\mfp@count1 \def\mfp@buffer{}% \fi \edef\mfp@buffer{\mfp@buffer\mfp@nextdatum}% \fi \@xp\mfp@rwdataloop \fi}% % \end{macrocode} % % % \section{Various \CMF{} Settings.}\label{MFsettings} % % \DescribeMacro{\penwd} % Macros that write changes in default \grafbase{} variables now use the % construct ``\gbc{save x; x; x := ;}'' (via a call to % \cs{setmfvariable}). This makes changes local if inside a given \env{mfpic} % environment, global if outside. An exception is \gbc{penwd} which, as an % internal variable uses `\gbc{interim}' instead (via the \grafbase{} % command \gbc{resizedrawpen}). % % \SpecialUsageIndex{\drawpen} % \cs{drawpen} was the original command used to set the pen diameter % (prior to version 0.2.13). At some point it was replaced by % \SpecialUsageIndex{\pen}\cs{pen}. However \cs{penwd} seems to be more % consistent with other commands (e.g., \cs{shadewd}), and we keep all three. % \begin{macrocode} \newdef\pen#1{\mfcmd{\@nl resizedrawpen (#1)}}% \newlet\penwd\pen \newlet\drawpen\pen % \end{macrocode} % % \DescribeMacro{\shadewd} % The \cs{shade} macro works in \MF{} by adding many copies of the small % picture \gbc{shadedot} to the figure, in \MP{} the parameters % \gbc{shadewd} and \cs{shadespace} are simply used to calculate a level % of gray and a color fill is used. % % \DescribeMacro{\polkadotwd} % However, both \MF{} and \MP{} handle polkadots the same. The only % difference is \MF's need for fitting to a pixel grid. But that is % handled in \grafbase. % \begin{macrocode} \newdef\shadewd#1{\setmfnumeric{shadewd}{#1}}% \newdef\polkadotwd#1{\setmfnumeric{polkadotwd}{#1}}% % \end{macrocode} % % \DescribeMacro{\hatchwd} % The thickness of lines in the hatching fill is set by \cs{hatchwd}. % \begin{macrocode} \newdef\hatchwd#1{\setmfnumeric{hatchwd}{#1}% \setmfvariable{pen}{hatchpen}{pencircle scaled hatchwd}}% % \end{macrocode} % % \DescribeMacro{\dashpattern} % A dash pattern consists (internal to \MF) of an array of lengths. The % \grafbase{} command \gbc{dashpat} accepts a name, and a sequence of % numbers representing the sizes of dashes and spaces, and builds this % array. It differs from \cs{numericarray} in that a little additional % checking is done (at the \grafbase{} level). % \begin{macrocode} \newdef\dashpattern#1{\mfsrc{save #1; dashpat (#1)}\mfp@writedata}% % \end{macrocode} % % \DescribeMacro{\settension} % This sets the default tension for any command (for example, \cs{curve}) % that takes an optional argument that contains a tension value. This % includes also \cs{function}, \cs{plrfcn}, \cs{fcncurve}, \cs{datafile}, % \cs{plotdata}. It also sets the default tension for \cs{sclosed} and % \cs{bclosed}. The value should be at least $3/4$. % \begin{macrocode} \newdef\settension#1{\setmfnumeric{default_tension}{#1}}% % \end{macrocode} % % % \section{Settings for text label placement in figures}\label{labelsettings} % % \cs{tlabel}\,s are `justified' by placing a particular point of the % text at the location specified. The \cs{tlabel} command accepts an % optional argument containing two letters. There are 4 possibilities % for the first and three for the second. It turns out to be easier to % process these if we have a command that converts these to numbers, and % then \cs{ifcase} can be used. There is a third part of the optional % argument usable only in \MP{}: a number indicating degrees of rotation. % % \DescribeMacro{\tlabeljustify} % The multi-part definition of \cs{tlabeljustify} is to guard % against confusing error messages if some part of this optional argument % is empty. The code assumes that if there are only 2, 1 or no parts, then % later parts should be left unchanged. The rotation part is empty by % default (rather than 0), because some commands will emit a warning if % a nonempty rotation exists without \opt{mplabels}. % % The result of \cs{tlabeljustify} is that \cs{tl@vpos} is set equal to % $-1$ if the first letter is (default) \texttt{B} (for Baseline), and % 0--2 if it is \texttt{b} (bottom), \texttt{c} (center) or \texttt{t} % (top). Similarly, \cs{tl@hpos} is set equal to $-1$ if the second % letter is (default) \texttt{l} (for left), and 0 or 1 if it is % \texttt{c} (center) or \texttt{r} (right). Making the defaults % negative means they must be handled by the \cs{else} portion of any % \cs{ifcase}. % % The rotation part is just saved in \cs{tl@rot}. This is true even % without \opt{mplabels}, in case it is turned on later. It is ignored by % \cs{tlabel} without \opt{mplabels}, but a warning is issued here anyway. % \begin{macrocode} \newcount\tl@vpos \newcount\tl@hpos \newdef\mfp@tlh@l{-1}% \newdef\mfp@tlh@c{0}% \newdef\mfp@tlh@r{1}% \newdef\mfp@tlv@B{-1}% \newdef\mfp@tlv@b{0}% \newdef\mfp@tlv@c{1}% \newdef\mfp@tlv@t{2}% \newdef\tl@rot{}\tl@vpos-1 \tl@hpos-1 \newdef\tlabeljustify#1{\mfp@ifexist{#1}{\mfp@justify#1\mfp@end}}% \newdef\mfp@justify#1#2\mfp@end{\mfp@local\mfp@vconv{#1}% \mfp@ifexist{#2}{\mfp@@justify#2\mfp@end}}% \newdef\mfp@@justify#1#2\mfp@end{\mfp@local\mfp@hconv{#1}% \mfp@local\edef\tl@rot{#2}% \@ifmplabels{}% {\mfp@ifexist{#2}% {\Mfpic@warn{Rotation of labels is not supported without the mplabels\@msgbreak option. Rotation setting\on@line\space may be ignored.}}% }}% \newdef\mfp@vconv#1{% \@ifundefined{mfp@tlv@#1}% {\tl@vpos-1 \mfp@justify@error}% {\tl@vpos\@nameuse{mfp@tlv@#1}\relax}}% \newdef\mfp@hconv#1{% \@ifundefined{mfp@tlh@#1}% {\tl@hpos-1 \mfp@justify@error}% {\tl@hpos\@nameuse{mfp@tlh@#1}\relax}}% % \end{macrocode} % % \DescribeMacro{\tlpathjustify} % This acts just like \cs{tlabeljustify} from the user's point of view. % Since it is only for users, and not used internally, it merely defines % three macros that are passed to \cs{tlabeljustify} when no justification % parameter is present for a \cs{tlabel}-path command. % \begin{macrocode} \newdef\tlpathjustify#1{% \mfp@ifexist{#1}{\tlp@justify#1\mfp@end}}% \newdef\tlp@justify#1#2\mfp@end{\mfp@def\tlpath@v{#1}% \mfp@ifexist{#2}{\tlp@@justify#2\mfp@end}}% \newdef\tlp@@justify#1#2\mfp@end{% \mfp@def\tlpath@h{#1}\mfp@def\tlpath@r{#2}}% \tlpathjustify{cc}% % \end{macrocode} % % \DescribeMacro{\tlpointsep} % This takes an absolute length as its argument and sets parameters that % determine by how much a tlabel is separated from the point it is placed % at. This is in case something is drawn at that point, such as a dot or % a hash mark on an axis. % % \DescribeMacro{\tlpathsep} % This takes an absolute length and sets parameters that determine by how % much a path created by one of the \cs{tlabel\meta{path}} macros is % separated from the label it surrounds. % % \DescribeMacro{\tlabelsep} % This simply issues both the above commands. This is for compatibility % with \mfpic{} versions 0.7 or earlier, where both these separations were % determined by the same parameters. % % \DescribeMacro{\tlabeloffset} % \cs{tlabeloffset}, on the other hand, takes two arguments: dimensions, % representing offsets of labels from their point of placement. This is % mainly so that, if labels seem to be off, they can all be shifted with % one command. % % Both these values are written to the \MF{} file for the sake of the % commands that draw rectangles or ovals around labels. % \begin{macrocode} \newdef\tlpointsep#1{\mfp@local\tlabel@sep#1\relax \setmfnumeric{label_sep}{\the\tlabel@sep}}% \newdef\tlpathsep#1{\mfp@local\tlpath@sep#1\relax \setmfnumeric{labelpath_sep}{\the\tlpath@sep}}% \newdef\tlabelsep#1{\tlpointsep{#1}\tlpathsep{#1}}% \newdef\tlabeloffset#1#2{% \mfp@local\tlabel@hadj#1\relax \mfp@local\tlabel@vadj#2\relax \setmfpair{label_adjust}% {(\the\tlabel@hadj,\the\tlabel@vadj)}}% % \end{macrocode} % % \DescribeMacro{\everytlabel} % Every line of a multiline label is written inside a group, so % adjustments to baselineskip and other things are difficult or % impossible. Therefore, \cs{everytlabel} is provided to define code to be % inserted before the label code, outside these groups. The messing around % with the token register \cs{mfp@toks} is so one can put definitions in % the code without having to double \arg{} characters. % % The command \cs{extra@endtlabel} is called at the end of every % \cs{tlabel}. Normally it does nothing, but the \cs{tlabels} command % defines it to repeat the start of a loop. % \begin{macrocode} \newdef\everytlabel{\afterassignment\mfp@everytlabel\mfp@toks}% \newdef\mfp@everytlabel{\mfp@local\edef\every@tlabel{\the\mfp@toks}% \mfp@ifmpost {\mfp@ifopengraphsfile {\mfcmd{verbatimtex\@nl \def\noexpand\everylabel{\the\mfp@toks} etex}}% {}}% {}}% \newdef\every@tlabel{}% \newdef\extra@endtlabel{}% % \end{macrocode} % % Without \opt{mplabels} it is impossible to use \MP{} variables in % a text label placement parameter. I have occasionally found it useful % to have a \TeX{} version of the numeric variable \gbc{pi}. % \begin{macrocode} \newdef\pinumber{3.14159}% % \end{macrocode} % % % \section{Other settings}\label{othersettings} % % \DescribeMacro{\headshape} % This sets the arrowhead shape. The parameters are: the ratio of width % to length, the tension (see \file{grafbase.dtx}) and a boolean % (\gbc{true} or \gbc{false}) to say whether the the head is filled, or % only the barbs are drawn. It would be more consistent with other % commands to have one \TeX{} parameter with commas separating the % components, but this is legacy code. % \begin{macrocode} \newdef\headshape#1#2#3{\mfcmd{\@nl headshape (#1, #2, #3)}}% % \end{macrocode} % % There are up to 4 optional arguments to any given \cs{arrow} command, % and these can take any one of 6 special indicators ({\mytt b}, {\mytt c}, % {\mytt f}, {\mytt l}, {\mytt r} or {\mytt s}). Here we define macros % to handle these options. Each macro is fed a \emph{value}. For example, % the indicator {\mytt b} must be followed by a length, and that length is % the argument of \cs{mfp@arr@b}. % \begin{macrocode} \newdef\mfp@arr@b#1{\edef\mfp@hlocate{#1}}% \newdef\mfp@arr@c#1{\edef\mfp@hcolour{#1}}% \newdef\mfp@arr@l#1{\edef\mfp@hlength{#1}}% \newdef\mfp@arr@r#1{\edef\mfp@hrotate{#1}}% \newlet\mfp@arr@f\mfp@arr@b \newlet\mfp@arr@s\mfp@arr@l % \end{macrocode} % % The \cs{arc} and \cs{circle} commands take an optional argument that % indicates how the arc or circle is defined (and therefore the format of % the non-optional argument). These are passed to different \grafbase{} % commands whose names start with \gbc{arc} or \gbc{circle}. The commands % below store the rest of that name. The switch is set true by the % \cs{arc} command and false by \cs{circle}. % \begin{macrocode} \newdef\mfp@arc@s{pps}% \newdef\mfp@arc@t{ppp}% \newdef\mfp@arc@p{\ifmfp@switch plr\fi}% \newdef\mfp@arc@a{\ifmfp@switch alt\fi}% \newdef\mfp@arc@c{cp\ifmfp@switch s\fi}% \newdef\mfp@arc@r{pp (\mfp@T)}% \newdef\mfp@arc@q{pp (\mfp@F)}% % \end{macrocode} % % \DescribeMacro{\mfpdefinecolor} % \prog{Mfpic} supports color under \MP{} by writing all color % definitions to the output \file{.mp} file. In order to support a % \LaTeX-like color syntax, all the color models allowed by the color % package correspond to a \grafbase{} function that returns a \MP{} % color value. For example, \gbc{cmyk(.3,.3,0,.7)} returns \gbc{(0,0,.3)}, % a very dark blue. This can be set by % \cs{mfpdefinecolor}\marg{vdblue}\marg{cmyk}\marg{.3,.3,0,.7}. % % Several commands are provided to set certain special colors. Currently % we have the following commands, setting the color of the same name as % the command (except \cs{backgroundcolor} which sets a color named % \gbc{background}): % \cs{drawcolor}\SpecialUsageIndex{\drawcolor},\\ % \cs{fillcolor}\SpecialUsageIndex{\fillcolor}, % \cs{hatchcolor}\SpecialUsageIndex{\hatchcolor}, % \cs{headcolor}\SpecialUsageIndex{\headcolor}, % \cs{pointcolor}\SpecialUsageIndex{\pointcolor}, % \cs{tlabelcolor}\SpecialUsageIndex{\tlabelcolor}, and\\ % \cs{backgroundcolor}\SpecialUsageIndex{\backgroundcolor}. % % These commands support the \LaTeX-like syntax:\\ % \indent\cs{fillcolor}\oarg{\meta{model}}\marg{\meta{parameters}}.\\ % The code for \cs{backgroundcolor} has to be spelled out since the % command name has the string `\texttt{color}', but the color does not. % \begin{macrocode} \newdef\mfpdefinecolor#1#2#3{\setmfcolor{#1}{#2(#3)}}% \newdef\mfp@defclr#1#2#3{\setmfcolor{#1}{\mfp@ifempty{#2}{#3}{#2(#3)}}}% \newdef\mfp@newcolorcmd#1{% \@namedef{#1\mfp@C}{\mfp@nullopt{\mfp@defclr{#1\mfp@C}}}}% \mfp@newcolorcmd{draw}\mfp@newcolorcmd{fill}\mfp@newcolorcmd{tlabel}% \mfp@newcolorcmd{hatch}\mfp@newcolorcmd{head}\mfp@newcolorcmd{point}% \def\backgroundcolor{\mfp@nullopt{\mfp@defclr{background}}}% % \end{macrocode} % % When \cs{plotdata} is used to draw several graphs from one file, each % sequence of non-blank lines corresponds to a different curve with a % different style of rendering. The user has the option to cycle through % different dashing patterns, different colors, or different symbols. % % Internally, \cs{plotdata} issues the command \cs{mfp@setstyle} (which % can be defined to be any rendering macro), followed by a path defining % command such as \cs{curve} or \cs{polyline}, followed by a command % that reads the data and writes it in a suitable format. The following % commands essentially allow the user to select the rendering macro. % They start by resetting \cs{mfp@linetype}, the count register that keeps % track of how many curves have been drawn, then they define % \cs{mfp@setstyle}. % % \DescribeMacro{\dashedlines} % \cs{dashedlines} uses the rendering prefix \cs{gendashed} with 6 % different dashing patterns \gbc{dashtype0} through \gbc{dashtype5}. % These are actually selected in \MF{} through the command % \gbc{getdashpat}. This takes care of cycling back to % \gbc{dashtype0} when the number of available dash patterns is exceeded. % Dashed lines is the default. % \begin{macrocode} \newdef\dashedlines{\mfp@local\mfp@linetype0 \mfp@def\mfp@setstyle{\gendashed{getdashpat \number\mfp@linetype}}}% \dashedlines % \end{macrocode} % % \DescribeMacro{\coloredlines} % This uses \cs{draw} with an optional color parameter set to % \gbc{colortype0} through (by default) \gbc{colortype7}. These are color % variables defined by \grafbase{}. It also issues a warning if \MF{} is % being used. As with \cs{dashedlines}, a \MP{} command \gbc{getcolor} % selects these colors. % \begin{macrocode} \newdef\coloredlines{% \mfp@ifmpost {\mfp@local\mfp@linetype0 \mfp@def\mfp@setstyle{\draw[getcolor \number\mfp@linetype]}}% {\Mfpic@warn{You can't use \mfp@b coloredlines in Metafont.\@msgbreak Using \dashedlines instead}% \dashedlines}}% % \end{macrocode} % % \DescribeMacro{\pointedlines} % This makes a sort of dotted line, except the dots are actually different % symbols. It uses the rendering macro \cs{plot} with a parameter cycling % through 9 different symbols. % \begin{macrocode} \newdef\pointedlines{\mfp@local\mfp@linetype0 \mfp@def\mfp@setstyle{\plot{getsymbol \number\mfp@linetype}}}% % \end{macrocode} % % \DescribeMacro{\datapointsonly} % \cs{datapointsonly} uses symbols like \cs{pointedlines}, but places % them only at the data points from the file. It uses the rendering macro % \cs{plotnodes} with a parameter cycling through the same 9 symbols. % \begin{macrocode} \newdef\datapointsonly{\mfp@local\mfp@linetype0 \mfp@def\mfp@setstyle{\relax \plotnodes{getsymbol \number\mfp@linetype}}}% % \end{macrocode} % % \DescribeMacro{\reconfigureplot} % This command allows the user to set the dashes, colors and symbols used % by the \cs{plotdata} command. The first argument is the plotting method % to be changed (\texttt{dashes}, \texttt{colors}, or \texttt{symbols}) % and the second argument is a comma separated list of appropriate type % variables for \cs{plotdata} to cycle through. For example, % \cs{reconfigureplot}\marg{dashes} takes a list of dashing patterns % (previously defined by the \cs{dashpattern} command) separated by % commas. It writes a command instructing \MF{} to redefine the arrays % \mfc{dashtype0}, \mfc{dashtype1}, etc., used with \cs{gendashed} when % \cs{dashedlines} is in effect. The number of patterns is counted by \MF, % which also handles the mod-ing operation now. % % \cs{reconfigureplot}\marg{colors} takes a list of colors (expressions or % color names previously defined) separated by commas. It redefines % \gbc{colortype0}, etc., used with \cs{plotdata} when \cs{coloredlines} % is in effect. % % \cs{reconfigureplot}\marg{symbols} takes a list of symbols (\MF{} path % expressions, one of the symbols available to \cs{plotsymbol}, or path % names defined by \cs{store}) separated by commas. It redefines % \gbc{pointtype0}, etc., used by \cs{plotdata} when \cs{pointedlines} or % \cs{datapointsonly} is in effect. % % \DescribeMacro{\defaultplot} % This restores \mfpic's predefined defaults for dash patterns, colors and % symbols in \cs{plotdata}. The one argument is one of the words % \texttt{dashes}, \texttt{colors}, or \texttt{symbols}, indicating which % plotting method is to be restored. % \begin{macrocode} \newdef\reconfigureplot#1{\mfsrc{setdata#1}\mfp@writedata}% \newdef\defaultplot#1{\mfcmd{default#1}}% % \end{macrocode} % % \DescribeMacro{\mfplinetype} % The user-level command \cs{mfplinetype} allows the user to set the % starting value of \cs{mfp@linetype}. The default is to start at $0$. % \DescribeMacro{\mfplinestyle}\cs{mfplinestyle} is an alias for this % same command. The names `linestyle' and `linetype' come from % an analogous system of changing rendering in \prog{gnuplot}. (The % reason for two names is that \prog{gnuplot} documentation was not % consistent in its terminology.) % \begin{macrocode} \newdef\mfplinetype#1{\mfp@local\mfp@linetype#1\relax}% \newlet\mfplinestyle\mfplinetype \mfplinetype{0}% % \end{macrocode} % % \prog{Mfpic} has 6 possible axes, the $x$- and $y$-axes pass through the % origin, $(0,0)$, the four border axes are at the edges of the graph % space, possibly offset from it by some amount. These four commands hold % the amount of that offset in graph units, the default being 0. % \begin{macrocode} \newdef\mfp@lshift{0}\newdef\mfp@bshift{0}% \newdef\mfp@rshift{0}\newdef\mfp@tshift{0}% % \end{macrocode} % % \DescribeMacro{\axismargin} % The main user-level command for setting the above offsets is % \cs{axismargin}. Its first argument is one of the letters l, b, r, or t % to select the axis and the second is the offset in graph units. A % positive offset represents an inward shift, which is why we call them % \emph{margins}. % \DescribeMacro{\setaxismargins} % The arguments of \cs{setaxismargins} are four offsets for the axes (in % the above order, which is anticlockwise, starting with the left). % \DescribeMacro{\setallaxismargins} % \cs{setallaxismargins} takes one offset and applies it to all axes. % % The values are passed on to \MF{} in the variables \gbc{laxis}, % \gbc{baxis}, \gbc{raxis}, and \gbc{taxis}. They are also needed by the % \cs{axislabels} command so they are saved in macros. % \begin{macrocode} \newdef\axismargin#1#2{\setmfnumeric{#1axis}{#2}% \mfp@local\@namedef{mfp@#1shift}{#2}}% \newdef\setaxismargins#1#2#3#4{\axismargin l{#1}\axismargin b{#2}% \axismargin r{#3}\axismargin t{#4}}% \newdef\setallaxismargins#1{\setaxismargins{#1}{#1}{#1}{#1}}% % \end{macrocode} % % The following converts axis letters to a numeric, making conditionals for % axes simpler to code (\cs{ifcase} versus six nested \cs{if}\,s). % Plus we get to define the error message only once. The first argument % of \cs{mfp@getaxis} is the letter and the third argument is the calling % command (for the error message). We allow the letter to be instead a word, % using only the first letter and discarding the rest (\arg2). % \begin{macrocode} \def\mfp@axis@x{0}% \def\mfp@axis@y{1}% \def\mfp@axis@l{2}% \def\mfp@axis@b{3}% \def\mfp@axis@r{4}% \def\mfp@axis@t{5}% \def\mfp@getaxis#1#2\mfp@end#3{% \@ifundefined{mfp@axis@#1}% {\mfp@errmsg {Invalid axis letter "#1"}% {The command #3 requires an axis to be designated by one of^^J% the following letters: x, y, l, b, r, or t. If you proceed, ^^J% x will be assumed.}\def\mfp@axisnum{0}\def\mfp@axisletter{x}}% {\edef\mfp@axisnum{\@nameuse{mfp@axis@#1}}\def\mfp@axisletter{#1}}% \edef\mfp@defheadlen{% \the\ifnum\mfp@axisnum>1 \sideheadlen\else \axisheadlen\fi}}% % \end{macrocode} % % The tick marks (or hash marks) on the axes can be in three possible % positions: centered on the axes, on one side, or on the other side. % The default for the $x$- and $y$-axes is centered, for the border axes it % is inside. % \DescribeMacro{\setaxismarks}For changing this we provide the % \cs{setaxismarks} command, whose first argument is the axis letter, and % whose second argument is one of the words \texttt{inside}, % \texttt{outside}, \texttt{centered}, \texttt{ontop}, \texttt{onbottom}, % \texttt{onleft}, or \texttt{onright}. % % \DescribeMacro{\setxmarks} % \cs{setxmarks} takes one argument and sets the position for the $x$ axis % only, while % \DescribeMacro{\setymarks}\cs{setymarks} does the same for the $y$ axis. % For the border axes we provide % \DescribeMacro{\setbordermarks}\cs{setbordermarks}, which takes four % arguments: the positions for the left, bottom, right and top axis (in % that order). The abbreviation % \DescribeMacro{\setallbordermarks}\cs{setallbordermarks} takes one % argument and sets the position for all border axis marks to that. % \begin{macrocode} \newdef\setaxismarks#1#2{\setmfnumeric{#1tick}{#2}}% \newdef\setxmarks#1{\setaxismarks x{#1}}% \newdef\setymarks#1{\setaxismarks y{#1}}% \newdef\setbordermarks#1#2#3#4{\setaxismarks l{#1}\setaxismarks b{#2}% \setaxismarks r{#3}\setaxismarks t{#4}}% \newdef\setallbordermarks#1{\setbordermarks{#1}{#1}{#1}{#1}}% % \end{macrocode} % % The \cs{datafile} and \cs{plotdata} commands originally just created % polygonal paths, but users requested the ability to draw smooth ones. % Originally only the commands below (\cs{smoothdata} and % \cs{unsmoothdata}) were written to do this. Later, these file % manipulation commands were given optional arguments to achieve the same % effect, so now the commands below just set the defaults for the optional % parameter, storing them in the macros \cs{mfp@smoothness} and % \cs{mfp@tension}. The latter can be used to adjust the tension of the % \MF{} path if smoothness is `\texttt{s}'. % % \DescribeMacro{\smoothdata} % This takes an option tension argument. It defines \cs{mfp@smoothness} to % be `\texttt{s}' and \cs{mfp@tension} to be the optional argument. % Default tension is empty rather than 1 so we can implement a scheme to % change the actual default used. % \DescribeMacro{\unsmoothdata}\cs{unsmoothdata} defines % \cs{mfp@smoothness} to be `\texttt{p}' and \cs{mfp@tension} to be % empty. The latter might not be necessary. % \begin{macrocode} \newdef\mfp@smdata#1{\mfp@def\mfp@smoothness{#1}% \mfp@nullopt{\mfp@def\mfp@tension}}% \newdef\smoothdata{\mfp@smdata{s}}% \newdef\unsmoothdata{\mfp@smdata{p}\@empty}% \unsmoothdata% default % \end{macrocode} % % \DescribeMacro{\using} % The command \cs{using} is named after a keyword in \prog{gnuplot}. It % controls which datum is plotted against which by \cs{plotdata} and % \cs{datafile}. % % \DescribeMacro{\usingpairdefault}\cs{usingpairdefault} sets the default, % which is to read the first two space separated words on a line as the % $x$ and $y$ coordinate of a point. To allow that there might be more % data on a line, it is also assumed that the second word is followed by a % space and the rest of the line is read as a third parameter that is not % used. In case there are only two words, \mfpic{} will always add a space % on the end and then the third parameter will be empty. % % \DescribeMacro{\usingnumericdefault} % For the occasional command that needs numeric data, % \cs{usingnumericdefault} sets \cs{using} so that the first % space-separated word on a line is selected and the remainder of the line % discarded. % % The \cs{parse@data} command reads its argument as delimited % parameters, and the \cs{using} command tells what those delimiters are. % For example, in the first part of % \cs{using}\marg{\#1 \#2 \#3}\marg{(\#1,\#2)}, we are telling % \cs{parse@data} that everything on a line up to the first space is the % first parameter, and everything up to the second space is the second % parameter and the rest of the line is the third parameter. In the second % part we are telling it that what we write to the output is a pair in % parentheses with the first two parameters separated by a comma. This % example is the default as we see here in \cs{usingpairdefault}. This % command can be issued by a user to return to that default. The user can % also issue \cs{usingnumericdefault} to write the first word as a single % numeric for commands like \cs{piechart}. % % \DescribeMacro{\mfpdataperline} % \cs{mfpdataperline} is a user level macro that controls the maximum % number of points that will be written to a single line in the output. % \begin{macrocode} \newdef\using#1#2{\mfp@def\parse@data#1\mfp@end{#2}}% \newdef\usingpairdefault{\using{##1 ##2 ##3}{(##1,##2)}}% \newdef\usingnumericdefault{\using{##1 ##2}{##1}}% \usingpairdefault \newdef\mfpdataperline{5}% % \end{macrocode} % % The following macros are used internally by \cs{datafile} and % \cs{plotdata}. A blank line is read as \cs{par} (not the primitive % \cs{par}, but the literal token \cs{par}, so it tests as equal to % \cs{mfp@par}. Early versions of \cs{plotdata} wrote a literal \MF{} path % expression to the output file and \cs{mfp@join} created the \mfc{--} % between points. Now we write one of the \grafbase{} list-to-path % commands followed by a comma separated list of points, so \cs{mfp@join} % has morphed into a comma. % \begin{macrocode} \newdef\mfp@par{\par}\newdef\mfp@join{,}% % \end{macrocode} % % \DescribeMacro{\mfpdatacomment} % The user can change the comment character for data files with % something like \cs{mfpdatacomment}\marg{\cs{\#}}. This also changes the % percent character to category `other'. We can also use the percent sign % as part of the numeric data by placing % \DescribeMacro{\makepercentother}\cs{makepercentother} before the % \cs{using} command to turn `\texttt\%' into an ordinary character. % \DescribeMacro{\makepercentcomment}\cs{makepercentcomment} returns it to % its usual role as a comment. Every file reading command issues % \cs{mfp@setcomment} before reading. The count register % \cs{mfp@commentchar} holds the ASCII code of the current comment % character, the default being the percent sign. % \begin{macrocode} \newcount\mfp@commentchar \mfp@commentchar`\%% \newdef\makepercentother{\@makeother\%}% \newdef\makepercentcomment{\catcode`\%14 }% \newdef\mfpdatacomment#1{\mfp@local\mfp@commentchar`#1}% \newdef\mfp@setcomment{\makepercentother\catcode\mfp@commentchar14 }% % \end{macrocode} % % \DescribeMacro{\fdef} % The following is for defining functions to be used in \cs{function} % through \cs{plrregion}. The first argument is the name of the function, % the second is its variable, the last is the \MF{} code. Obviously its % use requires a knowledge of the \MF{} language. The function produced is % a \mfc{vardef}, and can contain almost arbitrary \MF{} code, but must % end with an expression. Normally it must be a numerical expression, to % be use in \cs{function}, or a pair expression so it can be used alone in % the last argument of \cs{parafcn}. % % We apply \c