% file: psbox.sty by Remko Scharroo, DUT/SSR&T
%
% \psbox is a TeX macro to include Encapsulated PostScript graphic,
% and is based on the epsf macros by Tomas Rokicki and Don Knuth.
%
% The \psbox macro finds the bounding box comment in the PostScript file,
% and scales it to user-defined proportions. Also, you can rotate or
% flip the PostScript inclusion with this macro and not bother about
% changing xsize versus ysize. \psbox pops a single \special macro merged
% into a box or a frame of the appropriate size at the current position in
% your TeX document.
%
% You may like to put a \centering first to have your picture nicely
% centered.
%
% The syntax of \psbox is
%    \psbox[options](boundingbox){filename}
% where both [options] and (boundingbox) are optional.
%
% * {filename} specifies the PS-file to be included.
%
% * (boundingbox) specifies the BoundingBox of the plot. If it is not
%   given, it will be read from the PS-file.
%
% * valid [options] are:
%   xsize=<dimen> : Define the horizontal size of the plot (after rotation).
%                   Default: 0pt (natural size)
%   ysize=<dimen> : Define the vertical size of the plot (after rotation).
%                   Default: 0pt (natural size)
%   size=<dimen>  : (same as xsize=<dimen>)
%   rotate=<rot>  : Rotate the plot, where <rot> can be:
%                   r = right, l = left, u = upside-down, n = none,
%                   h = horizontal flip, v = vertical flip
%                   Default: n
%   <rot>         : You may omit 'rotate='
%   frame=<switch>: Put a frame along the boundary of the plot.
%                   Default: false
%   plot=<switch> : Produce PS output. Default: true
%   verbose=<swch>: Produce verbose output. Default: false
%
% If both xsize=<dimen> and ysize=<dimen> are specified, the plot will
% be scaled to these dimensions in both directions. If one of them
% is not given or is 0, the natural expect ratio of height and width is
% maintained.
% If neither is given or both are 0, the plot will used in it's natural
% size.
% Also, one can specify the xsize or ysize as being a fraction of the
% natural xsize or ysize using the arguments #1 or #2. Here are some
% examples:
%
%   xsize=0pt            : use the natural sizes (default)
%   xsize=\hsize         : scale to full width and keep aspect ratio
%   ysize=\vsize         : scale to full height and keep aspect ratio
%   xsize=#1             : use the natural sizes
%   xsize=0.5#1          : scale to 50% of natural size and keep aspect ratio
%   xsize=#1,ysize=0.8#1 : keep natural horizontal size and shrink vertical
%                          size to 80% of the natural size
%   xsize=\ifnum#1>\hsize\hsize\else#1\fi : smaller of natural and hsize
%
% The default values for the graphics options are set by the \psboxset
% macro:
%
%   \psboxset{xsize=0pt,ysize=0pt,frame=false,plot=true,verbose=false,rotate=n}
%
% You may like to overrule the defaults by calling \psboxset yourself.
% Especially, it may be helpful to put
%
%   \psboxset{plot=false,frame=true}
%
% to create a document without (large) PostScript inclusions, but with
% only a frame (also visible with dvi-previewers) of the appropriate size
% in the appropriate place.
%
% Changes made since creation, 4 June 1993.
% 1993:
% v1.0: 22-Oct: All original rotate stuff removed. Now in one \special.
%               Posibility of defining both xsize and ysize.
% v1.2: 26-Oct: Posibility to keep xsize and change ysize or v.v.
%
\typeout{PSBOX by Remko Scharroo, v1.2}
%
\newread\psfilein    % file to \read
\newif\ifpsfileok    % continue looking for the bounding box?
\newif\ifpsbbfound   % success?
\newdimen\psxsize    % horizontal size after scaling
\newdimen\psysize    % vertical size after scaling
\newdimen\pshsize    % horizontal size before scaling
\newdimen\psvsize    % vertical size before scaling
\newdimen\pstmp      % register for arithmetic manipulation
\newdimen\psrwi      % real width (unit=0.1bp)
\newdimen\psrhi      % real height (unit=0.1bp)
\newdimen\pspoints   % conversion factor
%
\pspoints=1bp        % Adobe points are `big'
%
\def\psbox{\bgroup\@ifnextchar[{\@psboxi}{\@psbox}}
\def\@psboxi[#1]#2{\psboxset{#1}\@psbox{#2}}
\def\psboxset#1{\@psboxset#1,\@nil\ignorespaces}
\def\@psboxset#1,{%
\@@psboxset#1==\@nil
\@ifnextchar\@nil{\@gobble}{\@psboxset}}
\def\@@psboxset#1=#2=#3\@nil{%
\@ifundefined{psbox@#1}%
{\typeout{psbox-parameter `#1' not defined.}}%
{\@nameuse{psbox@#1}{#2}}}%
%
% Define options
\def\psbox@xsize#1{\def\psXsize##1##2{#1}}
\def\psbox@ysize#1{\def\psYsize##1##2{#1}}
\let\psbox@size\psbox@xsize
\def\psbox@r{\def\@rot{r}}
\def\psbox@l{\def\@rot{l}}
\def\psbox@h{\def\@rot{h}}
\def\psbox@u{\def\@rot{u}}
\def\psbox@v{\def\@rot{v}}
\def\psbox@n{\def\@rot{n}}
\def\psbox@rotate#1{\def\@rot{#1}}
%
% Define switches
\newif\ifpsbox@frame@
\newif\ifpsbox@plot@
\newif\ifpsbox@verbose@
\def\psbox@frame#1{\@nameuse{psbox@frame@#1}}
\def\psbox@plot#1{\@nameuse{psbox@plot@#1}}
\def\psbox@verbose#1{\@nameuse{psbox@verbose@#1}}
%
% Define defaults
\psboxset{xsize=0pt,ysize=0pt,frame=false,plot=true,verbose=false,rotate=n}
%
% Define the \psbox macro
%
\def\@psbox#1{\global\def\psllx{72}\global\def\pslly{72}%
   \global\def\psurx{540}\global\def\psury{720}%
   \def\lbracket{(}\def\testit{#1}\ifx\testit\lbracket
   \let\next=\psgetlitbb\else\let\next=\psnormal\fi\next{#1}}%
%
\def\psgetlitbb#1#2 #3 #4 #5)#6{\psgrab #2 #3 #4 #5 .\\%
   \pssetgraph{\@remote#6}\egroup}%
%
\def\psnormal#1{\psgetbb{\@remote#1}\pssetgraph{\@remote#1}\egroup}%
%
\def\psgetbb#1{%
%
% The first thing we need to do is to open the PostScript file, if possible.
%
\openin\psfilein=#1
\ifeof\psfilein\errmessage{I couldn't open #1, will ignore it}\else
%
% Okay, we got it. Now we'll scan lines until we find one that doesn't
% start with %. We're looking for the BoundingBox comment.
%
   {\psfileoktrue \chardef\other=12
    \def\do##1{\catcode`##1=\other}\dospecials \catcode`\ =10
    \loop
       \read\psfilein to \psfileline
       \ifeof\psfilein\psfileokfalse\else
%
% We check to see if the first character is a % sign;
% if not, we stop reading (unless the line was entirely blank);
% if so, we look further and stop only if the line begins with
% `%%BoundingBox:'.
%
          \expandafter\psaux\psfileline:. \\%
       \fi
   \ifpsfileok\repeat
   \ifpsbbfound\else
    \ifpsbox@verbose@\message{No bounding box comment in #1; using defaults}\fi\fi
   }\closein\psfilein\fi}%
%
% Now we have to calculate the scale and offset values to use.
% First we compute the natural sizes.
%
\def\pssetgraph#1{%
  \psvsize=\psury\pspoints
  \advance\psvsize by-\pslly\pspoints
  \pshsize=\psurx\pspoints
  \advance\pshsize by-\psllx\pspoints
%
% If the graph is rotated left or right, exchange \pshsize and \psvsize
%
  \if\@rot r\pstmp=\pshsize\pshsize=\psvsize\psvsize=\pstmp\fi
  \if\@rot l\pstmp=\pshsize\pshsize=\psvsize\psvsize=\pstmp\fi
%
% Scale the plot depending on xsize and ysize.
%
  \psxsize\psXsize\pshsize\psvsize
  \psysize\psYsize\psvsize\pshsize
% \typeout{psxsize=\the\psxsize\space psysize=\the\psysize}
  \ifnum\psxsize=0
    \ifnum\psysize=0
%
% Neither xsize or ysize are given: use natural size
%
      \psxsize=\pshsize \psysize=\psvsize
%
% Only ysize is given: compute xsize
%   We have a sticky problem here:  TeX doesn't do floating point arithmetic!
%   Our goal is to compute x = y*h/v. The following loop does this reasonably
%   fast, with an error of at most about 16 sp (about 1/4000 pt).
% 
    \else\pstmp=\pshsize \divide\pstmp\psvsize
      \psxsize=\psysize \multiply\psxsize\pstmp
      \multiply\pstmp\psvsize \advance\pshsize-\pstmp
      \pstmp=\psysize
      \loop \advance\pshsize\pshsize \divide\pstmp 2
      \ifnum\pstmp>0
        \ifnum\pshsize<\psvsize\else
          \advance\pshsize-\psvsize \advance\psxsize\pstmp \fi
      \repeat
    \fi
  \else
    \ifnum\psysize=0
%
% Only xsize is given: compute ysize (y = x*v/h)
%
      \pstmp=\psvsize \divide\pstmp\pshsize
      \psysize=\psxsize \multiply\psysize\pstmp   
      \multiply\pstmp\pshsize \advance\psvsize-\pstmp
      \pstmp=\psxsize
      \loop \advance\psvsize\psvsize \divide\pstmp 2
      \ifnum\pstmp>0
        \ifnum\psvsize<\pshsize\else
          \advance\psvsize-\pshsize \advance\psysize\pstmp \fi
      \repeat     
    \else
%
% Both xsize and ysize are given: use both !
%
    \fi
  \fi
  \psrwi=10\psxsize \divide\psrwi\pspoints
  \psrhi=10\psysize \divide\psrhi\pspoints
%
% If the graph is rotated left or right, exchange \psrwi and \psrhi
%
  \if\@rot r\pstmp=\psrwi\psrwi=\psrhi\psrhi=\pstmp\fi
  \if\@rot l\pstmp=\psrwi\psrwi=\psrhi\psrhi=\pstmp\fi
%
% Sort out rotation types:
%
  \def\psangle{0}
  \let\mb@b\vss\let\mb@l\hss\let\mb@r\hss\let\mb@t\vss
  \ifpsbox@frame@\let\@psframe\frame\else\let\@psframe\leavevmode\fi
  \if\@rot n\let\mb@b\relax\let\mb@l\relax\fi
  \if\@rot r\let\mb@t\relax\let\mb@l\relax\def\psangle{-90}\fi
  \if\@rot l\let\mb@b\relax\let\mb@r\relax\def\psangle{90}\fi
  \if\@rot u\let\mb@t\relax\let\mb@r\relax\def\psangle{180}\fi
  \if\@rot h\let\mb@b\relax\let\mb@r\relax\psrwi=-\psrwi\fi
  \if\@rot v\let\mb@t\relax\let\mb@l\relax\psrhi=-\psrhi\fi
  \@psframe{\vbox to\psysize{\mb@t\hbox to\psxsize{\mb@l%
    \psbox@spec{psfile=#1
       llx=\psllx\space lly=\pslly\space urx=\psurx\space ury=\psury\space
       rwi=\number\psrwi\space rhi=\number\psrhi\space angle=\psangle}%
    \mb@r}\mb@b}}%
}
% End of \pssetgraph
%
% Finally, do the \special trick
%
\def\psbox@spec#1{%
  \ifpsbox@plot@\special{#1}\ifpsbox@verbose@\typeout{special: #1}\fi%
  \else\ifpsbox@verbose@\typeout{special (suppressed): #1}\fi\fi}
%
% We still need to define the tricky \psaux macro. This requires
% a couple of magic constants for comparison purposes.
%
{\catcode`\%=12 \global\let\pspercent=%\global\def\psbblit{%BoundingBox}}%
%
% So we're ready to check for `%BoundingBox:' and to grab the
% values if they are found.
%
\long\def\psaux#1#2:#3\\{\ifx#1\pspercent
   \def\testit{#2}\ifx\testit\psbblit
      \psgrab #3 . . . \\%
      \psfileokfalse
      \global\psbbfoundtrue
   \fi\else\ifx#1\par\else\psfileokfalse\fi\fi}%
%
% Here we grab the values and stuff them in the appropriate definitions.
%
\def\psgrab #1 #2 #3 #4 #5\\{%
   \global\def\psllx{#1}\ifx\psllx\empty
      \psgrab #2 #3 #4 #5 .\\\else
   \global\def\pslly{#2}%
   \global\def\psurx{#3}\global\def\psury{#4}\fi}%
%
% We default the \@remote macro.
%
\def\@remote{}
\endinput



