  %%
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %%
 %%%%%               boxedeps.tex 
 %%%%% MACROS FOR FIGURE INSERTS OF EPSF NORM  %%%%%
 %%%%%   (EPSF = Encapsulated PostScript File)
  %%
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %%  
 %%%  AUTHOR: Laurent Siebenmann
  %%    lcs@topo.math.u-psud.fr
  %%  
 %%%  VERSIONS: Feb 1991 -- Nov 1995
  %%  Revisions bi-annual approx.
  %%  
 %%%  SOMMAIRE: boxedeps.tex d\'efinit des macro-commandes
  %%    qui permettent d'int\'egrer dans un document TeX des 
  %%    objets graphiques d\'ecrits par fichier de norme EPSF,
  %%    tout en accordant a chacun le statut d'une bo\^ite TeX ayant 
  %%    les bonnes dimensions.  La (seule!) contribution unique 
  %%    de ce fichier est de faire cela d'une fa{\c}con universelle.
  %%    C'est a dire de fa{\c}con \`a pouvoir commod\'ement 
  %%    servir avec tout pilote d'imprimante de norme 
  %%    PostScript --- malgr\'e l'absence d'une norme 
  %%    pour \special. 
  %%  
 %%%% ACTIVATION:
  %%  by a driver-by-driver protocol
  %%  see \SetTexturesEPSFSpecial 
  %%  and its companions below.
  %%  
 %%%% DOCUMENTATION:
  %%  --- see boxedeps.doc
  %%  The complete utility is called BoxedEPSF but for 
  %%  portability the nickname boxedeps is useful. 
  %%
 %%%%  POSTINGS: anonymous ftp 
  %%  ---  ftp matups.math.u-psud.fr [192.54.146.4] 
  %%  is the master copy in 1995.
  %%  ---  ftp.uni-stuttgart.de 
  %%  ---  ftp ftp.TeX.AC.UK
  %%  ---  ftp ftp.SHSU.edu
  %%  Locate the full package on these three 
  %%  "CTAN" servers by using (while connected) the command
  %%        QUOTE SITE INDEX boxedeps

 %%%%  RECENT ADDITIONS: \SetepsfEPSFSpecial simultaneously serves
   %%  dvips, the Y&Y drivers, DirectTeX, CMacTeX, OzTeX>=1.7
   %%  \SetOldOzTeXEPSFSpecial  %% OzTeX 1.42--1.6x 

 
 \chardef\EPSFCatAt\the\catcode`\@
 \catcode`\@=11

 \chardef\C@tColon\the\catcode`\:
 \chardef\C@tSemicolon\the\catcode`\;
 \chardef\C@tQmark\the\catcode`\?
 \chardef\C@tEmark\the\catcode`\!
 \chardef\C@tDqt\the\catcode`\"

 \def\PunctOther@{\catcode`\:=12
   \catcode`\;=12 \catcode`\?=12 \catcode`\!=12 \catcode`\"=12}
 \PunctOther@

 %%%% MESSAGES (separate macro best for Europe)
  %%  
  \def\ms@g{\immediate\write16}

 %%%% Prevent double input
 \let\EX@\expandafter
 
 \ifx\BoxedArtundefined\relax
   \ms@g{}\ms@g{ !!!  Bad news.
     \noexpand\BoxedEPSF or \noexpand\BoxedArt macros already input.}%
   \ms@g{ !!! Hit RETURN to exit, or  c  and RETURN to forge bravely on.}%
   {\endlinechar=-1\gdef\Temp{c}%
   \global\read16 to \temp}%
     \ifx\temp\Temp 
     \else
       \EX@\EX@\EX@\end
     \fi
 \else
    \global\let\BoxedArtundefined\relax
 \fi


 
 %%temporarily suppress Plain's logging of allocations
 \let\wlog@ld\wlog 
 \def\wlog#1{\relax} 

 %% New for TOOLS
 %\newif\ifIN@
 \newdimen\XShift@ \newdimen\YShift@ 
 \newtoks\Realtoks
 
 %%% New for BoxedEPSF
 %
 \newdimen\Wd@ \newdimen\Ht@
 \newdimen\Wd@@ \newdimen\Ht@@
 %
 \newdimen\TT@
 \newdimen\LT@
 \newdimen\BT@
 \newdimen\RT@
 %
 \newdimen\XSlide@ \newdimen\YSlide@ 
 %
 \newdimen\TheScale  %% secretly scale in mils: 1pt= 1mil 
 \newdimen\FigScale  %% secretly scale in mils: 1pt= 1mil 
 %
 \newdimen\ForcedDim@@

 \newtoks\EPSFDirectorytoks@
 \newtoks\EPSFNametoks@
 \newtoks\BdBoxtoks@
 \newtoks\LLXtoks@  %% useful info for Oz
 \newtoks\LLYtoks@  
 \newtoks\URXtoks@  %% useful for epsf.tex syntax
 \newtoks\URYtoks@  

  
 \newif\ifRepeat@
 \newif\ifNotIn@
 \newif\ifForcedDim@
 \newif\ifForceOn@
 \newif\ifForcedHeight@
 \newif\ifPSOrigin
 \newif\ifPCfmt@
 \newif\ifPCfmtOK@


 \newread\EPSFile@ 
 \newwrite \epsf@log
 \def\WrLog@{\immediate\write\epsf@log}

 \gdef\InitLog@{%
   \def\epsf@log@name{epsf.lst}%
   \count255=\time\divide\count255 by 60
   \edef\temp@{\the\count255}%
   \multiply\count255 by -60\relax 
   \advance\count255 by \time
   \immediate\openout\epsf@log \epsf@log@name
   \WrLog@{ \pct@@\space boxedeps.tex log, date 
   \the\day-\the\month-\the\year, 
   time \temp@:\the\count255.}\WrLog@{}%
   \ms@g{}\ms@g{ **** See file \epsf@log@name\space
    for list of EPSFs integrated by boxedeps.tex}%
   \global\let\InitLog@\relax}

 \def\noArtList{\global\let\InitLog@\relax}
 \let\noEPSFList\noArtList
 \def\noArtReports{\global\let\ReportEPSF@\relax}
 \let\noEPSFReports\noArtReports
 
 %%%% WORD-PROCESSING MACROS
  %%
  %%% \IN@0#1@#2@ : Is 1st exp of #1 in 1st exp of #2 ??
   %% Answer in \ifIN@
 \newif\ifIN@\def\IN@{\EX@\INN@\EX@}
  \long\def\INN@0#1@#2@{\long\def\NI@##1#1##2##3\ENDNI@
    {\ifx\m@rker##2\IN@false\else\IN@true\fi}%
     \EX@\NI@#2@@#1\m@rker\ENDNI@}
  \def\m@rker{\m@@rker}

  %%%  \SPLIT@0#1@#2@  :  Split 1st exp of #2 at 1st exp of #1
   %%  \Initialtoks@ , \Terminaltoks@ will contain pieces
  \newtoks\Initialtoks@  \newtoks\Terminaltoks@
  \def\SPLIT@{\EX@\SPLITT@\EX@}
  \def\SPLITT@0#1@#2@{\def\TTILPS@##1#1##2@{%
     \Initialtoks@{##1}\Terminaltoks@{##2}}\EX@\TTILPS@#2@}

 %%%% MACROS TO TRIM  \ForeTrim@0#1@ and \Trim@0#1@  
   %% result appears in \Trimtoks@
   %% LIMITATION: assume no multiple spaces to trim

  \newtoks\Trimtoks@

  %%% \ForeTrim@0#1@ trims initial space of first erpansion of #1
   %% #1 of form \the\toks0 or \mymacro
 \def\ForeTrim@{\EX@\ForeTrim@@\EX@}
 \def\ForePrim@0 #1@{\Trimtoks@{#1}}
 \def\ForeTrim@@0#1@{\IN@0\m@rker. @\m@rker.#1@%
     \ifIN@\ForePrim@0#1@%
     \else\Trimtoks@\EX@{#1}\fi}
   %%\m@rker expands here to \m@@rker since spot initial,
   %% so no confusuion with \m@rker

  %%% \Trim@0#1@ trims init and terminal spaces 
   %% Same syntax.
   %% Warns if internal spaces found.
   %% 
  \def\Trim@0#1@{%
    \ForeTrim@0#1@%
    \IN@0 @\the\Trimtoks@ @%
    \ifIN@ 
      \SPLIT@0 @\the\Trimtoks@ @\Trimtoks@\Initialtoks@
      \IN@0\the\Terminaltoks@ @ @%
      \ifIN@ \else \Trimtoks@{FigNameWithSpace}\fi
    \fi }


  %%%% MATH MACROS (provisional)
    %% use dimen registers for reals; unit 1pt
    %% (numerical dimension arguments OK unless contrary noted)

  %%%% One needs the point token seq (pt with cat 12) USES dimen 0
   \newtoks\pt@ks
   \def\getpt@ks 0.0#1@{\pt@ks{#1}}
   \dimen0=0pt\relax\EX@\getpt@ks\the\dimen0@

   %%% Convert dimen to "decimal multiplier"% USES dimens 0,2
  %\newtoks\Realtoks% the output!
  \def\Real#1{%
    \dimen2=#1%
      \SPLIT@0\the\pt@ks @\the\dimen2@%%  lop off the points
       \Realtoks=\Initialtoks@ %\showthe\Realtoks
            }

   %%% Multiplication 
      % USES dimens 0,2,4,6; preserves args; output \Product
   \newdimen\Product
   \def\Mult#1#2{%
     \dimen4=#1\relax
     \dimen6=#2%
     \Real{\dimen4}%
     \Product=\the\Realtoks\dimen6%
        }

   %%% Inverse 
     % USES dimens 0; preserves arg; output \Inverse
 \newdimen\Inverse
 \newdimen\hmxdim@ \hmxdim@=8192pt%halfmaxdimen
 \def\Invert#1{%
  \Inverse=\hmxdim@
  \dimen0=#1%
  \divide\Inverse \dimen0%
  \multiply\Inverse 8}

 %%% \Rescale#1#2#3  % USES dimens 0,2,4,6
  %%  alters dimen register #1 by ratio #2/#3 
  %%  where #2,#3 can be raw dimensions OR dimen registers
   \def\Rescale#1#2#3{% Adequate accuracy. Can improve. 
              \divide #1 by 100\relax
              \dimen2=#3\divide\dimen2 by 100 \Invert{\dimen2}% 
              \Mult{#1}{#2}%
              \Mult\Product\Inverse 
              #1=\Product}

 %%% \Scale#1 scales dimen register #1 
  %%  by dimen register real \TheScale; USES dimen 0
  \def\Scale#1{\dimen0=\TheScale 
      \divide #1 by  1280 %% 1280*5120*10=1000*2^16 
      \divide \dimen0 by 5120  
      \multiply#1 by \dimen0 
      \divide#1 by 10   %% max size of #1 about 32000/10 pt
     }
 
 %%% SCRUNCHING BOXES AND SHIFTING CONTENTS
  %% TeX has to do this in general
  %% since some drivers do not let 
  %% one do it readily using Postscript

 \newbox\scrunchbox

 %%% \Scrunched#1 puts #1 in an hbox
  %%    then in effect zeros the dimensions of this box
 \def\Scrunched#1{{\setbox\scrunchbox\hbox{#1}%
   \wd\scrunchbox=0pt
   \ht\scrunchbox=0pt
   \dp\scrunchbox=0pt
   \box\scrunchbox}}

  %%% \Shifted@#1 puts #1 in \hbox 
   %% then locates basepoint to bottom left corner
   %% then translates ink only by \XShift@,\YShift@
   %% with Postscript convention
   %% For simplicity use only on scrunched boxes
  %\newdimen\XShift@ 
  %\newdimen\YShift@ 
 \def\Shifted@#1{%
   \vbox {\kern-\YShift@
       \hbox {\kern\XShift@\hbox{#1}\kern-\XShift@}%
           \kern\YShift@}}

  %%% \cBoxedEPSF#1 the main macro
   %%  component macros are explained in order below

 \def\cBoxedEPSF#1{{\leavevmode 
    %% double brace for amstex \allign, \alligned, ...
   \ReadNameAndScale@{#1}%
   \SetEPSFSpec@
   \InitLog@ 
   \ReadEPSFile@ \ReadBdB@x  
   %% Calculations
     \TrimFigDims@ 
     \CalculateFigScale@  
     \ScaleFigDims@
     \SetInkShift@
   \hbox{$\mathsurround=0pt\relax
         \vcenter{\hbox{%
             \FrameSpider{\hskip-.4pt\vrule}%
             \vbox to \Ht@{\offinterlineskip\parindent=\z@%
                \FrameSpider{\vskip-.4pt\hrule}\vfil 
                \hbox to \Wd@{\hfil}%
                \vfil
                \InkShift@{\EPSFSpecial{\EPSFSpec@}{\FigSc@leReal}}%
             \FrameSpider{\hrule\vskip-.4pt}}%
         \FrameSpider{\vrule\hskip-.4pt}}}%
     $\relax}%
    \CleanRegisters@ 
    \ReportEPSF@ 
    }}
 
 \def\tBoxedEPSF#1{\setbox4\hbox{\cBoxedEPSF{#1}}%
     \setbox4\hbox{\raise -\ht4 \hbox{\box4}}%
     \box4
      }

 \def\bBoxedEPSF#1{\setbox4\hbox{\cBoxedEPSF{#1}}%
     \setbox4\hbox{\raise \dp4 \hbox{\box4}}%
     \box4
      }

  \let\BoxedEPSF\cBoxedEPSF% default setting

  %% Some compatibility with BoxedArt.tex
   %
   \let\BoxedArt\BoxedEPSF

  %% Some compatibility with Sweet-teX
   %
  \def\gLinefigure[#1scaled#2]_#3{%
        \BoxedEPSF{#3 scaled #2}}
    
  %% Some compatibility with Rokicki's dvips
   %
  \let\EPSFbox\bBoxedEPSF \let\EPSFfile\bBoxedEPSF
  
  \def\EPSFxsize{\afterassignment\ForceW@\ForcedDim@@}
      \def\ForceW@{\ForcedDim@true\ForcedHeight@false}
  
  \def\EPSFysize{\afterassignment\ForceH@\ForcedDim@@}
      \def\ForceH@{\ForcedDim@true\ForcedHeight@true}

  \def\EmulateRokicki{%
       \let\epsfbox\bBoxedEPSF \let\epsffile\bBoxedEPSF
       \let\epsfxsize\EPSFxsize \let\epsfysize\EPSFysize} 
 
 %%% \ReadNameAndScale@#1
  %
 \def\ReadNameAndScale@#1{\IN@0 scaled@#1@% DOUBLE BARRELED
   \ifIN@\ReadNameAndScale@@0#1@%
   \else \ReadNameAndScale@@0#1 scaled\DefaultMilScale @%
   \fi}
  
 \def\ReadNameAndScale@@0#1scaled#2@{% HELPER MACRO
    \let\OldBackslash@\\%
    \def\\{\OtherB@ckslash}%
    \edef\temp@{#1}%
    \Trim@0\temp@ @%
    \EPSFNametoks@\EX@{\the\Trimtoks@ }%
    \FigScale=#2 pt%
    \let\\\OldBackslash@
    }
 
 \def\SetDefaultEPSFScale#1{%
      \global\def\DefaultMilScale{#1}}

 \SetDefaultEPSFScale{1000}


 %%% \ReadEPSFile@
  %
 \def \SetBogusBbox@{%
     \global\BdBoxtoks@{ BoundingBox:0 0 100 100 }%
     \global\def\BdBoxLine@{ BoundingBox:0 0 100 100 }%
     \ms@g{ !!! Will use placeholder !!!}%
     }

 {\catcode`\%=12\relax\gdef\P@S@{%!}\gdef\pct@@{%%}}
   %% %! min sign of PS file

 %%% Opening and closing
 \def\ReadEPSFile@{%\show\EPSFSpec@%
   \openin\EPSFile@\EPSFSpec@
   \relax  %necessary to prevent precocious expansion of \ifeof
  \ifeof\EPSFile@
   \ms@g{}%
   \ms@g{ !!! EPS FILE \the\EPSFDirectorytoks@
       \the\EPSFNametoks@\space WAS NOT FOUND !!!}%
   \SetBogusBbox@
  \else
   \ReadEPSFile@@
  \fi
  \closein\EPSFile@ 
   }
 
 %% \AdvanceLcnt@ for PC EPSF case only
 \global\let\AdvanceLcnt@\relax %% initialize
 \def\AdvanceLcnt@@{%
   \advance\count255 1 \ifnum \count255>50 \Lcnt@ms@g \fi}
  
 \def\Lcnt@ms@g{\ms@g{}%
  \ms@g{ !!! PC binary EPS preview probably before BoundingBox.}%
  \ms@g{ !!! To accellerate, use utility to move all previews after \pct@@ EOF.}%
  \global\let\AdvanceLcnt@\relax
  \global\let\AdvanceLcnt@@\relax %% in all, one test, one complaint
  }

 %%% Header tests
 \def\ReadEPSFile@@{%
   \begingroup%%
   \chardef\other=12 \chardef\cmt=14 \catcode"0C=9 \catcode"7F=\cmt 
   \def\do##1{\catcode`##1=\other}\dospecials \catcode`\ =10
   \catcode"00=\cmt \catcode`\\=\cmt \catcode`\!=12 \catcode`\:=12 
   %% next to recognize PC-type header
   \global\PCfmt@false%% initialize
   \catcode"C5=\other \catcode"D0=\other \catcode"D3=\other \catcode"C6=\cmt 
   \global\read\EPSFile@ to \HdLine@ 
   \IN@0\P@S@ @\HdLine@ @%
   \ifIN@ %% %! accepted as %!PS so do BdBox search loop!!
     %\message{*********}%
     %\showthe\catcode`\%
     %\showthe\catcode`\!
     %\show\HdLine@
     %\show\P@S@
     \let\temp@\ReadEPSFile@@@
   \else
     \def\temp@@{^^c5^^d0^^d3}%
     \ifx\temp@@\HdLine@  %% sign of PC binary PostScript file header
       \global\PCfmt@true
       \count255=0 %% will be line counter
       \let\AdvanceLcnt@\AdvanceLcnt@@
       \let\temp@\ReadEPSFile@@@
       \ifPCfmtOK@\else %%
         \ms@g{}%
         \ms@g{ !!! PC binary EPS file header encountered. Designated }%
         \ms@g{ !!! driver may not accept this and similar EPS files.}%
         \relax\global\PCfmtOK@true %% just one warning
       \fi
     \else
       \ms@g{}%
       \ms@g{ !!! \the\EPSFNametoks@\space is not PostScript.}%
       \ms@g{ !!! It should begin with the "\P@S@" or PC binary header.}%
       \SetBogusBbox@
     \fi
   \fi
   \temp@
  \endgroup%\relax
  }

 %%% BoundingBox search loop
 \def\ReadEPSFile@@@{\Repeat@true
   \loop   
   \ifeof\EPSFile@\relax\Repeat@false 
     \ms@g{}%
     \ms@g{ !!! BoundingBox NOT FOUND IN %
       \the\EPSFDirectorytoks@\the\EPSFNametoks@\space!!! }%
     \SetBogusBbox@
   \else
     \ReadEPSFile@@@@
   \fi
   \ifRepeat@
   \AdvanceLcnt@ %% is \relax unless PC EPSF; >50 => complaint
   \repeat
   \global\BdBoxtoks@\expandafter{\BdBoxLine@}%
   }

 %%% BoundingBox or HiResBoundingBox
  %% HiRes normally on line following if present at all
 \def\ReadEPSFile@@@@{%
   \global\read\EPSFile@ to \BdBoxLine@
   %\BdBoxtoks@\EX@{\BdBoxLine@}\ms@g{}\ms@g{ *  \the\BdBoxtoks@}%%%%
   \IN@0BoundingBox@\BdBoxLine@ @%
   \ifIN@
     %\ms@g{}\ms@g{ *  SCORE!!}
     \Repeat@false
     \read\EPSFile@ to \temp@
     \IN@0HiResBoundingBox:@\temp@ @%
     \ifIN@
       \global\let\BdBoxLine@\temp@
     \fi
   \fi}

  %%% \ReadBdB@x
   % Rmk For simplicity 0 not used in syntax 
   %  of \ReadBdB@x@,  \ReadBdB@x@@ 
  \def\ReadBdB@x{% PART 0
   \EX@\ReadBdB@x@\the\BdBoxtoks@ @}
  
  \def\ReadBdB@x@#1BoundingBox:#2@{% PART 1
    \ForeTrim@0#2@%
    \IN@0atend@\the\Trimtoks@ @%
       \ifIN@ \Trimtoks@={0 0 100 100 }%
         \ms@g{}%
         \ms@g{ !!! BoundingBox not found in %
         \the\EPSFDirectorytoks@\the\EPSFNametoks@\space !!!}%
         \ms@g{ !!! It must not be at end of EPSF !!!}%
         \ms@g{ !!! Will use placeholder !!!}%
       \fi%% cf \SetBogusBbox@
    \EX@\ReadBdB@x@@\the\Trimtoks@ @%
   }
    
  \def\ReadBdB@x@@#1 #2 #3 #4@{% PART 2
      \Wd@=#3bp\advance\Wd@ by -#1bp%
      \Ht@=#4bp\advance\Ht@ by-#2bp%
       \Wd@@=\Wd@ \Ht@@=\Ht@ %% useful info for Clark
       \LLXtoks@={#1}\LLYtoks@={#2}%% useful for Oz
       \URXtoks@={#3}\URYtoks@={#4}%% useful for epsf.tex
      \ifPSOrigin\XShift@=-#1bp\YShift@=-#2bp\fi 
     }

  %%% \SetEPSFDirectory 
   %
   \def\G@bbl@#1{}
   \bgroup
     \global\edef\OtherB@ckslash{\EX@\G@bbl@\string\\}
   \egroup

  \def\SetEPSFDirectory{%  Part 1
           \bgroup\PunctOther@\relax
           \let\\\OtherB@ckslash
           \SetEPSFDirectory@}

 \def\SetEPSFDirectory@#1{% Part 2
    \edef\temp@{#1}%
    \Trim@0\temp@ @%  result in \Trimtoks@
    \global\toks1\EX@{\the\Trimtoks@ }\relax
    \egroup
    \EPSFDirectorytoks@=\toks1
    }

 \def\SetEPSFSpec@{%
     \bgroup
     \let\\=\OtherB@ckslash
     \global\edef\EPSFSpec@{%
        \the\EPSFDirectorytoks@\the\EPSFNametoks@}%
     \global\edef\EPSFSpec@{\EPSFSpec@}%
     \egroup}

 %%% Is trimming done percentage-wise??
 \newif\ifPCT@ 

 \def\PCTtrueErrTst@{}%
 \def\PCTfalseErrTst@{}%

 %%%% Trimming figure dimensions (source)
   %%
  %%% \TrimSide@ 
   %% #1 is one of \TT@,...,\RT@;  #2 is arg of \TrimTop,...
 \def\TrimSide@#1#2{%
    \IN@0pct@#2@%
    \ifIN@
       \PCT@true\PCTtrueErrTst@
       \SPLIT@0pct@#2@%
       \advance#1 by \the\Initialtoks@ pt
    \else
       \PCTfalseErrTst@
       \advance#1 by #2
    \fi}
 
 \def\TrimTop#1{\TrimSide@{\TT@}{#1}}%
 \def\TrimLeft#1{\TrimSide@{\LT@}{#1}}%
 \def\TrimBottom#1{\TrimSide@{\BT@}{#1}}%
 \def\TrimRight#1{\TrimSide@{\RT@}{#1}}%

 \def\TrimBoundingBox#1{%
   \TrimTop{#1}%
   \TrimLeft{#1}%
   \TrimBottom{#1}%
   \TrimRight{#1}%
       }

 %%% Convert percentage trim to dimension trim on source (if nec)
  %% #1 is percent trim (pt is unit); #2 is source width or height
 \def\PCTtoSideTrimDims@{%
    \ifPCT@
      \Rescale\LT@\Wd@{100pt}%\showthe\LT@
      \Rescale\RT@\Wd@{100pt}%
      \Rescale\TT@\Ht@{100pt}%
      \Rescale\BT@\Ht@{100pt}%
    \fi}

 \def\TrimFigDims@{%
    \PCTtoSideTrimDims@
    \advance\Wd@ by -\LT@ 
    \advance\Wd@ by -\RT@ \RT@=\z@
    \advance\Ht@ by -\TT@ \TT@=\z@
    \advance\Ht@ by -\BT@ 
    }
  

 %%% \CalculateFigScale@
  %
  \def\ForceWidth#1{\ForcedDim@true
       \ForcedDim@@#1\ForcedHeight@false}
  
  \def\ForceHeight#1{\ForcedDim@true
       \ForcedDim@@=#1\ForcedHeight@true}

  \def\ForceOn{\ForceOn@true}
  \def\ForceOff{\ForceOn@false\ForcedDim@false}
  
  \def\CalculateFigScale@{%
            %Have default \FigScale or read \FigScale
     \ifForcedDim@\FigScale=1000pt% %% start afresh
           \ifForcedHeight@
                \Rescale\FigScale\ForcedDim@@\Ht@
           \else
                \Rescale\FigScale\ForcedDim@@\Wd@
           \fi
     \fi
     \Real{\FigScale}%
     \edef\FigSc@leReal{\the\Realtoks}%
     }
   
  \def\ScaleFigDims@{\TheScale=\FigScale
      \ifForcedDim@
           \ifForcedHeight@ \Ht@=\ForcedDim@@  \Scale\Wd@
           \else \Wd@=\ForcedDim@@ \Scale\Ht@
           \fi
      \else \Scale\Wd@\Scale\Ht@        
      \fi
      \ifForceOn@\relax\else\global\ForcedDim@false\fi
      \Scale\LT@\Scale\BT@  %%%\Scale\Wd@\Scale\Ht@
      \Scale\XShift@\Scale\YShift@
      }
      
  %%% \ShowDisplacementBoxes
   %%  shows (prints) corrected scaled and positioned
   %%  bounding boxes; for diagnostics
  %%% \HideDisplacementBoxes makes them invisible again
   %%
 \def\HideDisplacementBoxes{\global\def\FrameSpider##1{\null}}
 \def\ShowDisplacementBoxes{\global\def\FrameSpider##1{##1}}
 \let\HideFigureFrames\HideDisplacementBoxes %% some synonyms
 \let\ShowFigureFrames\ShowDisplacementBoxes
 \ShowDisplacementBoxes
 
  %%% \hSlide#1, \vSlide#1
   %%
 \def\hSlide#1{\advance\XSlide@ by #1}
 \def\vSlide#1{\advance\YSlide@ by #1}
 
  %%% \SetInkShift@, \InkShift@#1
   %%
  \def\SetInkShift@{%
            \advance\XShift@ by -\LT@
            \advance\XShift@ by \XSlide@
            \advance\YShift@ by -\BT@
            \advance\YShift@ by -\YSlide@
             }
   %
  \def\InkShift@#1{\Shifted@{\Scrunched{#1}}}
 
  %%% \CleanRegisters@
   %
  \def\CleanRegisters@{%
      \globaldefs=1\relax
        \XShift@=\z@\YShift@=\z@\XSlide@=\z@\YSlide@=\z@
        \TT@=\z@\LT@=\z@\BT@=\z@\RT@=\z@
      \globaldefs=0
      \global\PCT@false}

 \def\ReportEPSF@{%
  \ms@g{ *** Box composed for the EPS file \the\EPSFNametoks@}%
  \edef\temp@{\the\EPSFDirectorytoks@}%
  \ifx\temp@\LastEPSFDirectory@\else
    \WrLog@{--- change EPSF directory ==> \temp@}%
    \global\let\LastEPSFDirectory@\temp@
  \fi
  \def\temp@{}%
  \ifPCfmt@ \edef\temp@{\space \pct@@\space EPSP binary}%
  \fi
  %\show\temp@
  \WrLog@\EX@{\the\EPSFNametoks@\temp@}%
  }

 \gdef\LastEPSFDirectory@{}%% initialize

 %%% Special syntax for several drivers. The macros 
  %% \SetTexturesEPSFSpecial  %% Textures 
  %% \SetUnixCoopEPSFSpecial %% dvi2ps early unix 
  %% \SetNiponUnixEPSFSpecial %% dvi2ps j-version 
  %% \SetBechtolsheimDVI2PSEPSFSpecial and 
  %% \SetBechtolsheimDVITPSEPSFSpecial %% by S.P.Bechtolsheim
  %% \SetLisEPSFSpecial %% dvi2ps by Tony Lis
  %% \SetepsfEPSFSpecial %% ******* will work for many:
  %% ----- dvips, the Y&Y drivers, DirectTeX, CMacTeX, OzTeX>=1.7
  %% \SetRokickiEPSFSpecial %% dvips by Tom Rokicki
  %% \SetDVIPSoneEPSFSpecial %% DVIPSONE of Y&Y same as
  %% \SetDVIWindowEPSFSpecial %% DVIWindow of Y&Y 
  %% \SetDirectTeXEPSFSpecial %% DirectTeX by Wilfried Ricken
  %% \SetCMacTeXEPSFSpecial %% CMacTeX by Tom Kiffe
  %% \SetOzTeXEPSFSpecial %% OzTeX (>=1.7) by Andrew Trevorrow
  %% -----
  %% \SetOldOzTeXEPSFSpecial %% OzTeX 1.42--1.6x 
  %% \SetPSprintEPSFSpecial %% PSprint by Andrew Trevorrow
  %%  --- also for OzTeX versions <= 1.41 !!
  %% \SetArborEPSFSpecial %% ArborTeX DVILASER/PS
  %% \SetClarkEPSFSpecial %% dvitops by James Clark
  %% \SetBeebeEPSFSpecial %% DVIALW by N. Beebe
  %% \SetNorthlakeEPSFSpecial %% Northlake Software
  %% \SetStandardEPSFSpecial %% Nonexistant: Placebo used
  %%
  %% These many drivers are supported roughly
  %% by (re-)defining the macro \EPSFSpecial#1#2, where
  %% #1 = EPS file pathname (use \\ for the letter backslash)
  %% #2 = scale in mils 
  %% Be wary of using strange characters in pathnames!
 
 %% Textures, Blue Sky Research, Barry Smith
 \def\SetTexturesEPSFSpecial{\PSOriginfalse%\PSOrigintrue
  \gdef\EPSFSpecial##1##2{\relax
    \edef\specialtemp{##2}%
    \SPLIT@0.@\specialtemp.@\relax
    \special{illustration ##1 scaled
                        \the\Initialtoks@}}}
 
  %% Unix : dvi2ps by:  Mark Senn, Stephan  Bechtolsheim,  
   % Bob  Brown, Richard, Furuta, James Schaad, Robert  Wells, 
   % Norm Hutchinson, Neal Holt, Scott Jones, Howard Trickey.
   % Introduced by B. Horn <bkph@ai.mit.edu>
  \def\SetUnixCoopEPSFSpecial{\PSOrigintrue % Please test!
   \gdef\EPSFSpecial##1##2{%
      \dimen4=##2pt% convert real to dimen
      \divide\dimen4 by 1000\relax
      \Real{\dimen4}%dimens 0,2 used here
      \edef\Aux@{\the\Realtoks}%  
      %%convert dimen to real
      \special{psfile=##1\space 
        hscale=\Aux@\space
        vscale=\Aux@}}}

  %% Unix : dvi2ps j-version 1.91j
   % Introduced by Takashi Matsushita matsu@tmuds1.phys.metro-u.ac.jp
   % Takafumi Sakurai, sakurai@math.s.chiba-u.ac.jp
   % Kazuhiro Kazama,  kazama@square.ntt.jp
  \def\SetNiponUnixEPSFSpecial{\PSOriginfalse % Please test!
   \gdef\EPSFSpecial##1##2{%
      \dimen4=##2pt% convert real to dimen
      \divide\dimen4 by 1000\relax
      \Real{\dimen4}%dimens 0,2 used here
      \edef\Aux@{\the\Realtoks}%  
      %%convert dimen to real
      \special{epsfile=##1\space 
        hscale=\Aux@\space
        vscale=\Aux@}}}

  %% Unix : dvi2ps j-version 1.91j
   % Introduced by Takashi Matsushita matsu@tmuds1.phys.metro-u.ac.jp
   % Takafumi Sakurai, sakurai@math.s.chiba-u.ac.jp
   % Kazuhiro Kazama,  kazama@square.ntt.jp
  \def\SetNiponUnixEPSFSpecial{\PSOriginfalse % Please test!
   \gdef\EPSFSpecial##1##2{%
      \dimen4=##2pt% convert real to dimen
      \divide\dimen4 by 1000\relax
      \Real{\dimen4}%dimens 0,2 used here
      \edef\Aux@{\the\Realtoks}%  
      %%convert dimen to real
      {\dimen6=\the\URYtoks@ pt %
      \advance\dimen6 by -\the\LLYtoks@ pt %
      \dimen6=\Aux@\dimen6 
      \Real{\dimen6}% 
      \XShift@=0bp\YShift@=\the\Realtoks bp
      \Shifted@{\special{epsfile=##1\space 
        hscale=\Aux@\space
        vscale=\Aux@}}}}}
%%%      \Shifted@{\special{illustration ##1}}}}}



  %% dvi2ps and dvitps by S.P. Bechtolsheim,
   % Introduced by B. Horn <bkph@ai.mit.edu> and Carl.M.Jones, 
   % testing by R. Evans <Robert@cm.cardiff.ac.uk>
   % and George Denk <denk@mathematik.tu-muenchen.de>
   % Note that a prolog file psfig.pro
   % specific to the driver should be available.
  \def\SetBechtolsheimEPSFSpecial@{%% tool macro only
   \PSOrigintrue
   \special{\DriverTag@ Include0 "psfig.pro"}%
   \gdef\EPSFSpecial##1##2{%
      \dimen4=##2pt %% convert real to dimen
      \divide\dimen4 by 1000\relax
      \Real{\dimen4} %% dimens 0,2 used here
      \edef\Aux@{\the\Realtoks}%% convert dimen to real
      \special{\DriverTag@ Literal "10 10 0 0 10 10 startTexFig
           \the\mag\space 1000 div 
           dup 3.25 neg mul 1 index .25 neg mul translate %% correction line
           \Aux@\space mul dup scale "}%
      \special{\DriverTag@ Include1 "##1"}%
      \special{\DriverTag@ Literal "endTexFig "}%
        }}

  \def\SetBechtolsheimDVITPSEPSFSpecial{\def\DriverTag@{dvitps: }%
      \SetBechtolsheimEPSFSpecial@}

  \def\SetBechtolsheimDVI2PSEPSFSSpecial{\def\DriverTag@{DVI2PS: }%
      \SetBechtolsheimEPSFSpecial@}

  %% dvi2ps by Tony Lis,
   % implantations? ; dates?; availability?
   % Introduced by B. Horn <bkph@ai.mit.edu>
  \def\SetLisEPSFSpecial{\PSOrigintrue 
   \gdef\EPSFSpecial##1##2{%
      \dimen4=##2pt% convert real to dimen
      \divide\dimen4 by 1000\relax
      \Real{\dimen4}% dimens 0,2 used here
      \edef\Aux@{\the\Realtoks}%  
      %%convert dimen to real
      \special{pstext="10 10 0 0 10 10 startTexFig\space
           \the\mag\space 1000 div \Aux@\space mul 
           \the\mag\space 1000 div \Aux@\space mul scale"}%
      \special{psfile=##1}%
      \special{pstext=endTexFig}%
        }}

  %% dvips by Tom Rokicki; free driver in portable C 
   % Introduced by W.D. Neumann <neumann@mps.ohio-state.edu>
  \def\SetRokickiEPSFSpecial{\PSOrigintrue 
   \gdef\EPSFSpecial##1##2{%
      \dimen4=##2pt% convert real to dimen
      \divide\dimen4 by 10\relax
      \Real{\dimen4}% dimens 0,2 used here
      \edef\Aux@{\the\Realtoks}%  
      %%convert dimen to real
      \special{psfile="##1"\space 
        hscale=\Aux@\space
        vscale=\Aux@}}}

  \def\SetInlineRokickiEPSFSpecial{\PSOrigintrue 
   \gdef\EPSFSpecial##1##2{%
      \dimen4=##2pt% convert real to dimen
      \divide\dimen4 by 1000\relax
      \Real{\dimen4}% dimens 0,2 used here
      \edef\Aux@{\the\Realtoks}%  
      %%convert dimen to real
      \special{ps::[begin] 10 10 0 0 10 10 startTexFig\space
           \the\mag\space 1000 div \Aux@\space mul 
           \the\mag\space 1000 div \Aux@\space mul scale}%
      \special{ps: plotfile ##1}%
      \special{ps::[end] endTexFig}%
        }}

  %%% Rokicki's epsf.tex syntax.
   %% Is followed by DirectTeX (W. Ricken)
   %% CMacTeX (Tom Kiffe), Y&Y's drivers, and OzTeX >= 1.7
  \def\SetepsfEPSFSpecial{\PSOriginfalse 
   \gdef\epsfclipstring{}%
   %% make { clip} if you want to clip (non-portably)
   %% down to the PostScript bounding box. (OzTeX refuses this)
   \gdef\EPSFSpecial##1##2{%
      \dimen4=##2pt %% convert mil scale to dimen
      \divide\dimen4 by 100 %% 1000ths to 10ths
      \Real{\dimen4}%% dimens 0,2 used here
      \edef\theScaleholder@{\the\Realtoks}%
      \dimen6=\the\URXtoks@ pt %% not bp!!!!!
      \advance\dimen6 by -\the\LLXtoks@ pt
      %% \dimen6 now (bbox width) * points
      \dimen6=\theScaleholder@\dimen6 \Real{\dimen6}%% dimens 0,2 used here
      \edef\Temp{\the\Realtoks}%
      %% \Temp now holds decimal real no
      %% 10 times desired "real width" (rwi) in bp
      \dimen6=\the\URYtoks@ pt %
      \advance\dimen6 by -\the\LLYtoks@ pt %
      \dimen6=\theScaleholder@\dimen6 \Real{\dimen6}% 
      \special{PSfile=##1\space
        llx=\the\LLXtoks@\space lly=\the\LLYtoks@\space
        urx=\the\URXtoks@\space ury=\the\URYtoks@\space 
        rwi=\Temp\space rhi=\the\Realtoks
        \epsfclipstring}%
        }}
    %% Rmk: Under epsf.tex only multiples of (1/10) bp available widths
    %% but considerably more accuracy available here.

  \let\SetDirectTeXEPSFSpecial=\SetepsfEPSFSpecial
  \let\SetCMacTeXEPSFSpecial=\SetepsfEPSFSpecial
  \let\SetOzTeXEPSFSpecial=\SetepsfEPSFSpecial
 %%% \SetOzTeXEPSFSpecial only for OzTeX in versions 1.7 and later

 %%% Old OzTeX versions (1.42 to 1.6), by Andrew Trevorrow.
 %%% For versions <= 1.41 use \SetPSprintEPSFSpecial below.
 %%  Nota: Version 1.42--1.5 may give
 %%  spurious "offpage" error notices on printing.
 \def\SetOldOzTeXEPSFSpecial{\PSOrigintrue
 \gdef\EPSFSpecial##1##2{%
 \dimen4=##2pt%% convert real to dimen
 \divide\dimen4 by 1000\relax
 \Real{\dimen4}%% dimens 0,2 used here
 \edef\Aux@{\the\Realtoks}%% convert dimen to real
 \special{epsf=\string"##1\string"\space scale=\Aux@}%
 }} 

 %% PSprint, by AndrewTrevorrow for VaX VMS
 %% and OzTeX versions <= 1.41  
  % tested 2-91 by Max Calviani <ISICA@ASTRPD.infn.it>
  \def\SetPSprintEPSFSpecial{\PSOriginfalse % artifice; see below
   \gdef\EPSFSpecial##1##2{%note order
     \special{##1\space 
       ##2 1000 div \the\mag\space 1000 div mul
       ##2 1000 div \the\mag\space 1000 div mul scale
       \the\LLXtoks@\space neg \the\LLYtoks@\space neg translate
       }}}

 %% DVILASER/PS driver originally written by David Fuchs
  % marketed and supported by ArborTeXt  535 W. William St.
  % Suite 300, Ann Arbor, MI 48103, U.S.A
  % (313) 996-3566 (313) 996-3573
  % help@arbortext.com, Andrew Dobrowolski
 \def\SetArborEPSFSpecial{\PSOriginfalse % check!
   \gdef\EPSFSpecial##1##2{%
     \edef\specialthis{##2}%
     \SPLIT@0.@\specialthis.@\relax % suppress decimals (nec!)
     \special{ps: epsfile ##1\space \the\Initialtoks@}}}

 %% dvitops, (c) James Clark <jjc@jclark.uucp>
  % public domain; distributed by UK TeX Archive
  % computers: unix, msdos, vms, primos and vm/cms,
  % introduced by S. Ratz <spqr@uk.ac.southampton.ecs>
 \def\SetClarkEPSFSpecial{\PSOriginfalse % please test!
   \gdef\EPSFSpecial##1##2{%
     \Rescale {\Wd@@}{##2pt}{1000pt}%
     \Rescale {\Ht@@}{##2pt}{1000pt}%
     \special{dvitops: import 
           ##1\space\the\Wd@@\space\the\Ht@@}}}

 %% DVIPSONE, for PC compatibles
  % Y&Y, 106 Indian Hill, Carlisle MA 01741, USA
  % (508) 371-3286
  % (introduced by B. Horn <bkph@ai.mit.edu>)
  \let\SetDVIPSONEEPSFSpecial\SetepsfEPSFSpecial
  \let\SetDVIPSoneEPSFSpecial\SetepsfEPSFSpecial
  \let\SetDVIWindowEPSFSpecial\SetepsfEPSFSpecial

 %% DVIALW by N. Beebe, public domain 
  % DVI Driver Distribution, Center for Scientific Computing,
  % Department of Mathematics, 220 South Physics Building,
  % University of Utah, Salt Lake City, UT 84112, USA
  % (introduced by B. Horn <bkph@ai.mit.edu>)
  % Proposed standard; see TUGboat article 1993.
  \def\SetBeebeEPSFSpecial{%please test!
   \PSOriginfalse% 
   \gdef\EPSFSpecial##1##2{\relax
    \special{language "PS",
      literal "##2 1000 div ##2 1000 div scale",
      position = "bottom left",
      include "##1"}}}
  \let\SetDVIALWEPSFSpecial\SetBeebeEPSFSpecial

 %% Northlake software
  \def\SetNorthlakeEPSFSpecial{\PSOrigintrue
   \gdef\EPSFSpecial##1##2{%
     \edef\specialthis{##2}%
     \SPLIT@0.@\specialthis.@\relax % suppress decimals (nec!)
     \special{insert ##1,magnification=\the\Initialtoks@}}}

 %%% MultiSpecial for Textures PLUS drivers supporting epsf.tex
 %%% syntax of Rokicki (one of many dvips syntaxes)
  %% *experimental* 2-95
  \def\SetEPSFMultiSpecial{\PSOriginfalse
   \csname newwrite\endcsname \EPSFile@@
   \immediate\openout\EPSFile@@ illustration
   \immediate\write\EPSFile@@ {\P@S@}%
   \immediate\write\EPSFile@@ {\pct@@ Remark: Tranquilizer for OzTeX...}%
   \immediate\closeout\EPSFile@@
   \gdef\EPSFSpecial##1##2{%
      \dimen4=##2pt %% convert mil scale to dimen
      \divide\dimen4 by 100 %% 1000ths to 10ths
      \Real{\dimen4}%% dimens 0,2 used here
      \edef\theScaleholder@{\the\Realtoks}%
      \dimen6=\the\URXtoks@ pt %% not bp!!!!!
      \advance\dimen6 by -\the\LLXtoks@ pt
      %% \dimen6 now (bbox width) * points
      \dimen6=\theScaleholder@\dimen6 \Real{\dimen6}%% dimens 0,2 used here
      \edef\Temp{\the\Realtoks}%
      %% \Temp now holds decimal real no
      %% 10 times desired "real width" (rwi) in bp
      \dimen6=\the\URYtoks@ pt %
      \advance\dimen6 by -\the\LLYtoks@ pt %
      \dimen6=\theScaleholder@\dimen6 \Real{\dimen6}% 
      \special{PSfile=##1\space
        llx=\the\LLXtoks@\space lly=\the\LLYtoks@\space
        urx=\the\URXtoks@\space ury=\the\URYtoks@\space 
        rwi=\Temp\space rhi=\the\Realtoks}%
    \edef\specialtemp{##2}%
    \SPLIT@0.@\specialtemp.@\relax
    \special{illustration ##1 scaled \the\Initialtoks@}%
    }}

 \def\SetStandardEPSFSpecial{%
   \gdef\EPSFSpecial##1##2{%
     \ms@g{}
     \ms@g{%
       !!! Sorry! There is still no standard for \noexpand
       \special EPSF integration !!!}%
     \ms@g{%
      --- So you will have to identify your driver using a command}%
     \ms@g{%
      --- of the form \string\Set...EPSFSpecial, in order to get}%
     \ms@g{%
      --- your graphics to print.}%  
     \ms@g{%
      Update your BoxedEPSF and read the documentation.}%
     \ms@g{}
     \gdef\EPSFSpecial####1####2{}
     }}

  \SetStandardEPSFSpecial %% currently gives warning
 
 \let\wlog\wlog@ld %%restore logging 

 \catcode`\:=\C@tColon
 \catcode`\;=\C@tSemicolon
 \catcode`\?=\C@tQmark
 \catcode`\!=\C@tEmark
 \catcode`\"=\C@tDqt

 \catcode`\@=\EPSFCatAt

  \endinput

%%%%%%%%%%%% ASCII Character test
 %
 %       Upper case letters: ABCDEFGHIJKLMNOPQRSTUVWXYZ
 %       Lower case letters: abcdefghijklmnopqrstuvwxyz
 %                                   Digits: 0123456789
 % Square, curly, angle braces, parentheses: [] {} <> ()
 %           Backslash, slash, vertical bar: \ / |
 %                              Punctuation: . ? ! , : ;
 %          Underscore, hyphen, equals sign: _ - =
 %                Quotes--right left double: ' ` "
 %"at", "number" "dollar", "percent", "and": @ # $ % &
 %           "hat", "star", "plus", "tilde": ^ * + ~
 %
 %%%%%%%%%%%%%%%%%%%%%%%%
 %
 % Une seule erreur de transmission peut empoisoner un programme!
 %
 % A single transmission error can poison a whole program.
 %
 %%%%%%%%%%%%%%%%%%%%%%%%
