#!/bin/sh
# $Id: dotplot,v 1.84 1994/07/05 16:18:56 schwartz Exp $
USAGE='usage: dotplot 
	[-inv][-ip][-if][-in][-nc][-nb][-nh][-nv][-w#][-h#][-ppi#][-ht#][-vt#]
	[x0 x1 y0 y1]'

optint () {
  expr "$1" : "[^0-9.]*\([-0-9.]*\)" \| "0"
}

while
 case "$1" in
   -inv) INVERTED_NUMBERS="true" INVERTED_FEATURES="true" INVERTED_PLOT="true";;
   -i*p*) INVERTED_PLOT="true";;
   -i*f*) INVERTED_FEATURES="true";;
   -i*n*) INVERTED_NUMBERS="true";;
   -i*) INVERTED_NUMBERS="true" INVERTED_FEATURES="true" INVERTED_PLOT="true";;
   -n*c*) CLIP_FEATURES="false" ;;
   -nh) WANT_HTIC="false" ;;
   -nw) WANT_HTIC="false" ;;
   -nv) WANT_VTIC="false" ;;
   -ht*) HTIC=`optint "$1"` ;;
   -vt*) VTIC=`optint "$1"` ;;
   -nb) BANNER="false" ;;
   -w*) OVERRIDE_WIDTH=`optint "$1"`;;
   -h*) OVERRIDE_HEIGHT=`optint "$1"`;;
   -p*p*i*) OVERRIDE_SCALE=`optint "$1"`;;
   -vsf*) VSCALEFUDGE=`optint "$1"`;;
   -x*) XOFFSET=`optint "$1"` ;;
   -y*) YOFFSET=`optint "$1"` ;;
   -noshowpage) NOSHOWPAGE=1;;
   -landscape) ORIENTATION=1;;
   -portrait) ORIENTATION=2;;
   -*) echo "unknown flag $1" 1>&2 ;;
   *) false ;;
 esac
do shift
done

case $# in 
0|4) ;;
*) echo $USAGE 1>&2 ; exit 1;;
esac

echo "%!"
echo "gsave"
echo "/language_level  /languagelevel where {pop languagelevel} {1} ifelse def"
echo "/picture-xforms where { pop } { /picture-xforms [] def } ifelse"
echo "1023 dict begin"

echo "  /default-options {
    /inverted-dotplot false def /inverted-features false def
    /inverted-numbers false def /clip-features true def
    /banner-line true def /description () def /date (`date`) def
    /current-directory (`pwd|sed -e 's;^/tmp_mnt;;' -e 's;^/auto;;'`) def
    /override-width 0 def /override-height 0 def /override-scale 0 def
    /want-htic true def /want-vtic true def
    /htic-step 0 def /vtic-step 0 def
    /y-scale-fudge 1 def
    /x-offset 0 def /y-offset 0 def
    /page-orientation 0 def
  } def"

echo "  /user-options {
          ${INVERTED_PLOT+/inverted-dotplot $INVERTED_PLOT def} 
          ${INVERTED_FEATURES+/inverted-features $INVERTED_FEATURES def} 
          ${INVERTED_NUMBERS+/inverted-numbers $INVERTED_NUMBERS def} 
          ${CLIP_FEATURES+/clip-features $CLIP_FEATURES def} 
	  ${OVERRIDE_WIDTH+/override-width $OVERRIDE_WIDTH def} 
 	  ${OVERRIDE_HEIGHT+/override-height $OVERRIDE_HEIGHT def} 
 	  ${OVERRIDE_SCALE+/override-scale $OVERRIDE_SCALE def} 
 	  ${WANT_HTIC+/want-htic $WANT_HTIC def} 
 	  ${WANT_VTIC+/want-vtic $WANT_VTIC def} 
 	  ${BANNER+/banner-line $BANNER def} 
 	  ${HTIC+/htic-step $HTIC def} 
 	  ${VSCALEFUDGE+/y-scale-fudge $VSCALEFUDGE def} 
 	  ${VTIC+/vtic-step $VTIC y-scale-fudge mul def} 
 	  ${XOFFSET+/x-offset $XOFFSET inch def} 
 	  ${YOFFSET+/y-offset $YOFFSET inch def} 
  	  ${ORIENTATION+/page-orientation $ORIENTATION def} 
          ${1+/x0 $1 def /x1 $2 def /y0 $3 def /y1 $4 def} 
       } def"

cat <<'@@@EndProlog@@@'
% ------------------------------------------------------------------------
% definitions of various things start here

% statusdict begin manualfeed true store end
/units-per-inch 72 def
/scalefactor 1 def

/inch { units-per-inch mul } bind def
/point { scalefactor div } bind def

/margin { 0.7 inch } bind def
/edgewidth { 1.25 inch } bind def
/min { 2 copy ge {exch pop} {pop} ifelse } bind def
/max { 2 copy le {exch pop} {pop} ifelse } bind def
/i2s { 20 string cvs } bind def

/Line { % x0 y0 x1 y1 t c -
  unsetpattern 
  setgray 
  point setlinewidth 
  newpath 4 2 roll moveto lineto closepath stroke
  0 setlinewidth
} bind def

/$local 32 dict def

/Rect { % x0 y0 x1 y1 h t c -
  unsetpattern
  setgray
  point setlinewidth
  $local begin
    /h exch def /y1 exch def /x1 exch def /y0 exch def /x0 exch def
    /dx x1 x0 sub def
    /dy y1 y0 sub def
    /dd dx dx mul dy dy mul add sqrt def
    gsave
      x0 y0 translate
      dx 0 ne { dy dx atan } {45} ifelse rotate
        newpath
         0 0 moveto dd 0 rlineto 0 h rlineto dd neg 0 rlineto 0 h neg rlineto
        stroke
    grestore
  end
  0 setlinewidth
} bind def

/Circle { % x y r t c -
  unsetpattern
  setgray
  point setlinewidth
  newpath 0 360 arc closepath stroke
  0 setlinewidth
} bind def

/Frame { % x0 y0 x1 y1 t c - 
  unsetpattern
  setgray point setlinewidth newpath
  % x0 y0 x1 y1	
  1 index 3 index % x0 y0 x1 y1 x1 y0
  1 index 3 index % x0 y0 x1 y1 x1 y0 x1 y1
  7 index 1 index % x0 y0 x1 y1 x1 y0 x1 y1 x0 y1
  1 index 5 index % x0 y0 x1 y1 x1 y0 x1 y1 x0 y1 x0 y0
  moveto lineto lineto lineto closepath stroke
  pop pop pop pop
  0 setlinewidth
} def

% --------------------------------------

% On lots of things we want the top to parameters to
% be ``/dir [[stringlist]] '', but for backwards compatability
% we sometimes have them in the reverse order.  So this checks
% to see of top is an array, and if not assumes things need to
% be reversed.
/parameter-type-kludge { % /dir [[stringlist]]
  dup type
  /arraytype ne { exch } if
} def


% This renders a string in a given font.  Uses global Fontsize.
/show-in-font { % [ str font size sup/sub ]
  aload length 
  2 eq { Fontsize 0 } if  % backwards compatability
  /_script_offset exch def
  /_font_size exch def
  /_font_name exch def
  /_string exch def

  _font_name findfont _font_size scalefont setfont 
  /_script_offset _script_offset _font_size 2 3 div mul mul def
  0 _script_offset rmoveto
   _string show
  0 _script_offset neg rmoveto
} def

% This computes the width of a string in a given font.
/stringwidth-in-font { % [ str font .. ]
   aload length 2 eq { Fontsize 0 } if  % backwards compatability
   pop exch findfont exch scalefont setfont stringwidth pop
} def

% This computes the with of a list of (string * font)s.
/string-width { % [[str font .. ] ...]
  /_sum 0 def
  {stringwidth-in-font _sum add /_sum exch def } forall
  _sum
} def

% General parameters for laying out annotations.
/box_height { 0.2 inch } bind def		% the height of an annotation
/row_gap { box_height dup .3 mul add } bind def	% space between rows of boxes
/H_row_base {_y1} bind def			% starting place for rows
/V_row_base {_x0} bind def
/current_row_base 0 def				% height of nth row above base
/box_adjustment 0 def

% Parts of various shapes
/basic_box_top { current_row_base box_height add } def
/basic_box_bottom { current_row_base } def
/box_top { basic_box_top box_adjustment sub } def
/box_bottom { basic_box_bottom box_adjustment add } def
/text_bottom { box_top row_gap 5 div add } def
/triangle_tip { current_row_base box_height 2 div add } def
/arrow_gap { box_height 3 div } def
/arrow_bottom { current_row_base arrow_gap add } def
/arrow_top { current_row_base arrow_gap dup add add } def


% This draws a horizontal banner in the current row.
/Hbanner { % [[...]]  -
 gsave 
   Black /Fontsize 13 def
   _x0 box_bottom moveto 
   savedmatrix setmatrix 
     Hadjust { show-in-font } forall 
 grestore
} def

% These record if anything stuck off the edges of the dotplot.
/Hundershoot false def
/Hovershoot false def

% This adjusts the coordinates so they don't overshoot the plot.
/Hnormalize { % x0 x1 - x0' x1'
  /Hn_x1 exch def
  /Hn_x0 exch def
  Hn_x0 _x0 lt { /Hn_x0 _x0 def /Hundershoot true def } if
  Hn_x1 _x1 gt { /Hn_x1 _x1 def /Hovershoot true def } if
  Hn_x0 Hn_x1
} def

/H_render_label {
   Black savedmatrix setmatrix Hadjust
   { show-in-font } forall
} def

/H_render_other_label {
   Black savedmatrix setmatrix Hotheradjust
   { show-in-font } forall
} def

% This renders a label above the current row.
/Hlabel {
 % x0 x1 /dir [[str font] ...] - x0 x1 /dir
 /Hl_strlist exch def
 /Hl_dir exch def
 /Hl_x1 exch def
 /Hl_x0 exch def
 Hl_x0 Hl_x1 Hnormalize add
   Hl_strlist string-width scalefactor div sub 2 div
   text_bottom moveto
 gsave
   /Fontsize 11 def
   Hl_strlist H_render_label
 grestore
 Hl_x0 Hl_x1 Hl_dir
} def

/Hotherlabel {
 % x0 x1 /dir [[str font] ...] - x0 x1 /dir
 /Hl_strlist exch def
 /Hl_dir exch def
 /Hl_x1 exch def
 /Hl_x0 exch def
 /Fontsize 11 def
 gsave
   Hl_x1 Hl_x0 add 2 div text_bottom moveto
   Hl_strlist H_render_other_label
 grestore
 Hl_x0 Hl_x1 Hl_dir
} def


% Vertical versions of the above.
/Vundershoot false def
/Vovershoot false def

/Vnormalize {
  /Vn_y1 exch def
  /Vn_y0 exch def
  Vn_y0 _y0 lt { /Vn_y0 _y0 def /Vundershoot true def } if
  Vn_y1 _y1 gt { /Vn_y1 _y1 def /Vovershoot true def } if
  Vn_y0 Vn_y1
} def

/Vbanner {
 % strlist -
 gsave 
   Black /Fontsize 13 def
   box_bottom inverted-features {_y1}{_y0} ifelse moveto
   savedmatrix setmatrix 
     Vadjust { show-in-font } forall 
 grestore
} def

/V_render_label {
   Black savedmatrix setmatrix Vadjust 
   { show-in-font } forall 
} def

/V_render_other_label {
   Black savedmatrix setmatrix Votheradjust
   { show-in-font } forall 
} def

/Vlabel {
 % y0 y1 /foo str - y0 y1 /foo
 /Vl_strlist exch def
 /Vl_dir exch def
 /Vl_y1 exch def
 /Vl_y0 exch def
 text_bottom 
 Vl_y0 Vl_y1 Vnormalize add			% (v0+v1
   Vl_strlist string-width scalefactor div 
   inverted-features {add} {sub} ifelse		% +- width)
   2 div 					% /2
 moveto
 gsave 
   /Fontsize 11 def
   Vl_strlist V_render_label
 grestore
 Vl_y0 Vl_y1 Vl_dir
} def

/Votherlabel {
 % y0 y1 /foo str - y0 y1 /foo
 /Vl_strlist exch def
 /Vl_dir exch def
 /Vl_y1 exch def
 /Vl_y0 exch def
 /Fontsize 11 def
 gsave text_bottom Vl_y0 Vl_y1 add 2 div 
        Fontsize 4 div scalefactor div inverted-features {add}{sub} ifelse 
        moveto 
	Vl_strlist dup 
	string-width scalefactor div 0 rmoveto
	V_render_other_label grestore
 Vl_y0 Vl_y1 Vl_dir
} def

% Various shape annotations
/Htriangle { % x0 x1 /dir str
  Hlabel
  % x0 x1 /dir
  /right eq {
    newpath 
    exch dup current_row_base moveto box_top lineto triangle_tip lineto
    closepath
  } {
    newpath
    dup current_row_base moveto box_top lineto triangle_tip lineto
    closepath
  } ifelse
  gsave fill grestore
  gsave Black stroke grestore
} def

/Vtriangle { 
  % y0 y1 /dir str
  Vlabel
  /right eq {
    newpath 
    exch dup 
    current_row_base exch moveto box_top exch lineto triangle_tip exch lineto
    closepath
  } {
    newpath 
    dup 
    current_row_base exch moveto box_top exch lineto triangle_tip exch lineto
    closepath
  } ifelse
  gsave fill grestore
  gsave Black stroke grestore
} def

/Harrow { % x0 x1 /dir str
  Hotherlabel
  gsave
    Black
    % x0 x1 /dir
    /right eq { 1 index box_bottom translate }
	      { 0 index box_bottom translate -1 1 scale } ifelse
    /_arrowhead_len { 1 16 div inch } def  
    exch sub /_arrowbody_len exch def

%%    _arrowbody_len _arrowhead_len ge {
      newpath
        _arrowbody_len triangle_tip moveto
        _arrowhead_len neg box_height 6 div rlineto
        0 box_height 3 div neg rlineto
      closepath fill
%%    } if
    0 triangle_tip moveto _arrowbody_len triangle_tip lineto stroke    
  grestore
} def

/Hthickarrow { % x0 x1 dir str
  Hlabel
  /right eq {
    newpath
    exch
    dup arrow_bottom moveto arrow_top lineto 
    dup 
      box_height sub dup dup
	arrow_top lineto 
	box_top lineto
	exch
      triangle_tip lineto
    dup
      box_bottom lineto
      arrow_bottom lineto
    closepath
  } {
    newpath
    dup arrow_bottom moveto arrow_top lineto
    dup 
      box_height add dup dup
   	arrow_top lineto 
	box_top lineto
	exch
      triangle_tip lineto
    dup
      box_bottom lineto
      arrow_bottom lineto
    closepath
  } ifelse
  gsave fill grestore
  gsave Black stroke grestore
} def

/Varrow { % y0 y1 /dir str 
  Votherlabel
  gsave
    Black
    % y0 y1
    /right eq { box_bottom 2 index translate }
	      { box_bottom 1 index translate 1 -1 scale } ifelse
    /_arrowhead_len { 1 16 div inch } def  
    exch sub /_arrowbody_len exch def

%%    _arrowbody_len _arrowhead_len ge {
      newpath
        triangle_tip _arrowbody_len moveto
        box_height 6 div _arrowhead_len neg rlineto
        box_height 3 div neg 0 rlineto
      closepath fill
%%    } if
    triangle_tip 0 moveto triangle_tip _arrowbody_len lineto stroke    
  grestore
} def

/Vthickarrow { % y0 y1 /dir str
  Vlabel
  /right eq {
    newpath
    exch % y1 y0
    dup 
      arrow_bottom exch moveto	% a_b y0 moveto
      arrow_top exch lineto   	% a_t y0 lineto
    dup 
      box_height sub dup dup  	% y1 y1-b_h y1-b_h y1-b_h 
	arrow_top exch lineto 	% a_t (y1-b_h) lineto
	box_top exch lineto	% b_t (y1-b_h) lineto
	exch                  	% y1-b_h y1
      triangle_tip exch lineto 	% d_t y1 lineto
    dup                       	% y1-b_h y1-b_h 
      box_bottom exch lineto  	% b_b y1-b_h lineto
      arrow_bottom exch lineto	% a_b y1-b_h lineto
    closepath
  } {
    newpath
    dup 
      arrow_bottom exch moveto	% a_b y0 moveto
      arrow_top exch lineto   	% a_t y0 lineto
    dup 
      box_height add dup dup  	% y1 y1-b_h y1-b_h y1-b_h 
	arrow_top exch lineto 	% a_t (y1-b_h) lineto
	box_top exch lineto	% b_t (y1-b_h) lineto
	exch                  	% y1-b_h y1
      triangle_tip exch lineto 	% d_t y1 lineto
    dup                       	% y1-b_h y1-b_h 
      box_bottom exch lineto  	% b_b y1-b_h lineto
      arrow_bottom exch lineto	% a_b y1-b_h lineto
    closepath
  } ifelse
  gsave fill grestore
  gsave Black stroke grestore
} def

/Hvoid { % x0 x1 str
  /foo exch Hlabel pop
  pop pop
} def

/Vvoid { % x0 x1 str
  /foo exch Vlabel pop
  pop pop
} def

/Hbox { % x0 x1 str
  /foo exch Hlabel pop
  % x0 x1
  newpath
  exch 
  dup current_row_base moveto box_top lineto 
  dup box_top lineto current_row_base lineto
  closepath
  gsave fill grestore
  gsave Black stroke grestore
} def

/Vbox {
  /foo exch Vlabel pop
  % x0 x1
  newpath
  exch 
  dup current_row_base exch moveto box_top exch lineto 
  dup box_top exch lineto current_row_base exch lineto
  closepath
  gsave fill grestore
  gsave Black stroke grestore
} def

/Harrowbox {
  Hlabel
  /right eq {
    newpath
    /Harrowbox_1 exch def
    /Harrowbox_0 exch def
    Harrowbox_0 dup box_bottom moveto box_top lineto 
    Harrowbox_1 dup 
      box_height 4 div sub Harrowbox_0 max
      dup 
	box_top lineto 
	exch triangle_tip lineto
      box_bottom lineto
    closepath
  } {
    newpath
    /Harrowbox_0 exch def
    /Harrowbox_1 exch def
    Harrowbox_0 dup box_bottom moveto box_top lineto
    Harrowbox_1 dup 
      box_height 4 div add Harrowbox_0 min
      dup
	box_top lineto
	exch triangle_tip lineto
      box_bottom lineto
    closepath
  } ifelse
  gsave fill grestore
  gsave 0 setlinewidth Black stroke grestore
} def

/Varrowbox { % y0 y1 /dir str
  Vlabel
  /right eq {
    newpath
    /Varrowbox_1 exch def
    /Varrowbox_0 exch def
    Varrowbox_0 dup 
      box_bottom exch moveto
      box_top exch lineto   	
    Varrowbox_1 dup 
      box_height 4 div sub Varrowbox_0 max dup box_top exch lineto exch
      triangle_tip exch lineto 	
      box_bottom exch lineto  	
    closepath
  } {
    newpath
    /Varrowbox_0 exch def
    /Varrowbox_1 exch def
    Varrowbox_0 dup 
      box_bottom exch moveto	
      box_top exch lineto   	
    Varrowbox_1 dup 
      box_height 4 div add Varrowbox_0 min dup box_top exch lineto exch
      triangle_tip exch lineto 	
      box_bottom exch lineto  	
    closepath
  } ifelse
  gsave fill grestore
  gsave 0 setlinewidth Black stroke grestore
} def


%  Mode switching commands.  Horizontal puts you in horizontal
%  mode, ready to lay out the horizontal annotations.  Similarly
%  for vertical.

/setrow { box_height row_gap add mul /current_row_base exch def } def
/setsize { 1.0 exch sub box_height mul 2 div /box_adjustment exch def } def

/setup-bars { % ishorizontal --
  __landscape xor not {
    /Bars { <CCCCCCCCCCCCCCCC> 8 1 dpi 16 div setpattern } def
    /Bars0 { <CCCCCCCCCCCCCCCC> 8 1 dpi 16 div setpattern } def
    /Bars1 { <FFFF0000FFFF0000> 8 1 dpi 16 div setpattern } def
    /Bars2 { <8142241818244281> 8 1 dpi 16 div setpattern } def
  } { 
    /Bars { <FFFF0000FFFF0000> 8 1 dpi 16 div setpattern } def
    /Bars0 { <FFFF0000FFFF0000> 8 1 dpi 16 div setpattern } def
    /Bars1 { <CCCCCCCCCCCCCCCC> 8 1 dpi 16 div setpattern } def
    /Bars2 { <8142241818244281> 8 1 dpi 16 div setpattern } def
  } ifelse
} def

/horizontal { 
  main
  initclip
  bordermatrix setmatrix
  0 H_row_base translate
  /horizontalmatrix matrix currentmatrix def

  clip-features {
	_x0 -1 inch moveto 
	_x0 4 inch lineto 
	_x1 4 inch lineto 
	_x1 -1 inch lineto closepath clip
  } if

  /Arrow { parameter-type-kludge Harrow } def
  /ArrowBox { parameter-type-kludge Harrowbox 1 setsize } def
  /Triangle { parameter-type-kludge Htriangle } def
  /ThickArrow { parameter-type-kludge Hthickarrow } def
  /Banner { Hbanner } def
  /Box { Hbox } def
  /Void { Hvoid } def
  true setup-bars
  0 setrow
} def

/vertical { 
  main
  initclip
  bordermatrix setmatrix
  inverted-features {
	  _x0 _y0 translate 1 -1 scale 0 height neg translate
	  _x0 neg _y0 neg translate } if
  
  V_row_base 0 translate -1 1 scale
  /verticalmatrix matrix currentmatrix def

  clip-features {
  	4 inch _y0 moveto 
  	4 inch _y1 lineto 
  	-1 inch _y1 lineto 
  	-1 inch _y0 lineto closepath clip
  } if

  /ArrowBox { parameter-type-kludge Varrowbox 1 setsize } def
  /Arrow { parameter-type-kludge Varrow } def
  /Triangle { parameter-type-kludge Vtriangle } def
  /ThickArrow { parameter-type-kludge Vthickarrow } def
  /Banner { Vbanner } def
  /Box { Vbox } def
  /Void { Vvoid } def
  false setup-bars
  0 setrow
} def

% Switch to data plotting mode.
/plotdata {
  main
  bordermatrix setmatrix
  inverted-dotplot {
	  _x0 _y0 translate 1 -1 scale 0 height neg translate
	  _x0 neg _y0 neg translate } if
  report-plot-once
  clip-to-selection
} def

/do-report-plot { 
	/picture-xforms	
		picture-xforms aload length  % m1 m2 ... mi i
		matrix currentmatrix matrix defaultmatrix
		matrix invertmatrix matrix concatmatrix 
		dup /my-xform exch def
		exch 1 add array astore 
	store
	(xform )print my-xform ==
	_x1 _y1 my-xform transform _x0 _y0 my-xform transform 
        (bbox )print % x0 y0 x1 y1
	exch i2s print ( )print i2s print ( )print 
	exch i2s print ( )print i2s print (\n)print
} def

/report-plot-once { 
	do-report-plot
	/do-report-plot {} def
} def

%  Utility variables
/Fontsize 11 def
/Null [[() /Courier]] def  % empty label
/Black { unsetpattern 0 setgray } def
/White { unsetpattern 1 setgray } def
/Gray  { unsetpattern 0.5 setgray } def
/LightGray  { unsetpattern 0.9 setgray } def
/DarkGray  { unsetpattern 0.5 setgray } def

%
% dpi, bitison, setpattern are adapted from code in the
% Postscript Tutorial and Cookbook, copr Adobe, 1985.
%
/resmatrix matrix def
/dpi 
  72 0 resmatrix defaultmatrix dtransform /yres exch def /xres exch def
  xres dup mul yres dup mul add sqrt
def

/bitison {
  /ybit exch def /xbit exch def
  bstring ybit bwidth mul xbit 8 idiv add get
  1 7 xbit 8 mod sub bitshift and 0 ne
} def

/setpattern {
   /freq exch def /bwidth exch def /bpside exch def /bstring exch def
   /onbits 0 def /offbits 0 def
   freq 0
     {/y exch def /x exch def
      /xindex x 1 add 2 div
         bpside mul cvi def
      /yindex y 1 add 2 div
         bpside mul cvi def
      xindex yindex bitison
        {/onbits onbits 1 add def 1}
        {/offbits offbits 1 add def
         0}
        ifelse
      }  setscreen
   {} settransfer
   offbits offbits onbits add div
     setgray
} def

% Put back default pattern function.
/unsetpattern { 
  language_level 1 eq 
    { saved_screen_freq saved_screen_angle {saved_screen_proc} setscreen } 
    { saved_screen_proc sethalftone }
  ifelse
} def

% Clip to the box around the plot.
/clip-to-selection { 
  initclip newpath _x0 _y0 moveto 0 height rlineto 
  width 0 rlineto 0 height neg rlineto closepath clip
} def

% -------------------------------------------------------------------------
% entry point here

/main { _main /_main {} def } def  % do main just once
/_main { __main } def
/__main {
  user-options
  /_x0 x0 def /_y0 y0 def /_x1 x1 def /_y1 y1 def
  (plot )print
  x0 i2s print ( )print
  y0 i2s print ( )print
  x1 i2s print ( )print
  y1 i2s print (\n)print

  % -- savedmatrix is the initial coordinate system
  %    we use it to render text
  /savedmatrix matrix currentmatrix def

  currentscreen 
    /saved_screen_proc exch def 
    /saved_screen_angle exch def 
    /saved_screen_freq exch def

  /Times-Roman findfont Fontsize scalefont setfont 

  /width _x1 _x0 sub def /height _y1 _y0 sub def

  % Decide on landscape or portrait mode based on width/height.
  page-orientation 0 eq {
    width height ge 
      { /page-orientation 1 def } 
      { /page-orientation 2 def } 
    ifelse
  } if

  clippath pathbbox
  /_page_y1 exch def
  /_page_x1 exch def
  /_page_y0 exch def
  /_page_x0 exch def

  /_page_dy _page_y1 _page_y0 sub def
  /_page_dx _page_x1 _page_x0 sub def

  page-orientation 1 eq {
    % Landscape mode
    /__landscape true def
    _page_dx 0 translate 90 rotate
    /pagewidth  _page_dy edgewidth sub margin 2 mul sub def 
    /pageheight _page_dx edgewidth sub margin 2 mul sub def 
    /Hadjust { 90 rotate } def
    /Hotheradjust { 180 rotate 0 Fontsize 4 div neg rmoveto } def
    /Vadjust { 180 rotate } def
    /Votheradjust { 90 rotate } def
    /HP { gsave savedmatrix setmatrix 90 rotate show grestore } def
  } {
    % Portrait mode
    /__landscape false def
    /pagewidth  _page_dx edgewidth sub margin 2 mul sub def 
    /pageheight _page_dy edgewidth sub margin 2 mul sub def 
    /Hadjust { 0 rotate } def
    /Vadjust { 90 rotate } def
    /Hotheradjust { 90 rotate 0 Fontsize 4 div neg rmoveto } def
    /Votheradjust { 0 rotate } def
    /HP { gsave savedmatrix setmatrix show grestore } def
  } ifelse

  % Offset to avoid margins and such
  %edgewidth margin add dup neg translate
  margin dup edgewidth add exch translate
  (margin )print 
  margin edgewidth add i2s print ( )print margin i2s print (\n)print

  % Offset for page location
  x-offset y-offset translate
  (offset )print x-offset i2s print ( )print y-offset i2s print (\n)print

  % Print title
  banner-line {
    0 pageheight moveto edgewidth dup neg exch rmoveto 
       current-directory show
    0 pageheight moveto edgewidth dup neg exch rmoveto 0 Fontsize neg rmoveto
       description show (   ) show date show 
  } if

  % Scale to dot-plot sizes
  /tmpwidth override-width 0 ne {override-width} {width} ifelse def
  /tmpheight override-height 0 ne {override-height} {height} ifelse def
  /scalefactor 
    override-scale 0 ne 
	{72 override-scale div} 
	{pagewidth tmpwidth div pageheight tmpheight div min}
    ifelse 
  def
  scalefactor dup scale
  (scale )print scalefactor =

  /units-per-inch 72 scalefactor div def

  % Move origin to upper left of selected region
  _x0 neg _y0 neg translate

  % -- bordermatrix is erect, but scaled to fit the data
  %    we use it to render horizontal annotations and tickmarks
  /bordermatrix matrix currentmatrix def

  % Draw box for axis
  _x0 _y0 _x1 _y1 1 72 div 0 Frame

  % Draw ticks
  /ticklen { 1 16 div inch } def
  /basicticstep { % x - x'
	  % log round 1 sub 10 exch exp cvi 
	  log 1 sub truncate 10 exch exp
	  1 max cvi
  } def

  /xtic { % x y -
	  2 copy	% x y x y
	  ticklen sub cvi % x y x y'
	  0 0 Line
  } def

  /ytic { % y x -
	  2 copy	% y x y x
	  ticklen add cvi	% y x y x'
	  4 -1 roll	% x y x' y
	  0 0 Line 
  } def

  /xlabel { % x y
	  2 copy moveto				% x y 
	  1 index cvi i2s 
	    stringwidth pop 
	    2 div scalefactor div neg	% x y -xlen
	  ticklen -3 mul 				% x y -xlen -3ylen
	  rmoveto					% x y
	  pop cvi i2s 
	  HP	
  } def

  /ylabel { % y x
	  exch 2 copy moveto			% x y
	  ticklen 0 rmoveto exch			% y x
	  pop y-scale-fudge div cvi i2s 
	  0 Fontsize 4 div scalefactor div inverted-dotplot not { neg } if
	  rmoveto
	  HP
  } def

  /x-tic-step {
    htic-step 0 eq { width basicticstep } { htic-step } ifelse
  } def

  /y-tic-step {
    vtic-step 0 eq { height basicticstep } { vtic-step } ifelse
  } def

  /xstep x-tic-step cvi def
  /ystep y-tic-step cvi def
  /xstart _x0 dup xstep mod sub xstep add def
  /ystart _y0 dup ystep mod sub ystep add def
  /xend _x1 dup xstep mod sub xstep sub def
  /yend _y1 dup ystep mod sub ystep sub def

  /goodxtic { % x - isgood
	  dup 
	  _x0 sub abs xstep 10 div gt exch	% b x
	  _x1 sub abs xstep 10 div gt 	% b b
	  and				% b
  } def

  /goodxlabel { % x - isgood
	  dup _x0 sub abs xstep 10 div gt exch	% b x
	  dup _x1 sub abs xstep 10 div gt exch	% b b x

	  dup 					% b b x x
		  _x1 sub abs 			% b b x d
		  exch				% b b d x
		  dup cvi i2s stringwidth pop scalefactor div	
						  % b b d x s
		  3 -1 roll			% b b x s d
		  lt 				% b b x b
		  exch				% b b b x
	  dup xstep 5 mul mod 0 eq exch		% b b b b x
	  pop
	  and and	and 				% b
  } def

  /goodytic { % y - isgood
	  dup 
	  _y0 sub abs ystep 10 div gt exch	% b x
	  _y1 sub abs ystep 10 div gt 	% b b
	  and				% b
  } def

  /goodylabel { % y - isgood
	% 2 was 10 below
	  dup _y0 sub abs ystep 2 div gt exch	% b x
	  dup _y1 sub abs ystep 2 div gt exch	% b b
	  ystep 5 mul mod 0 eq	
	  and and
  } def

  want-htic {
    bordermatrix setmatrix % X-tics made in border matrix
    _x0 _y0 2 copy xtic xlabel
    _x1 _y0 2 copy xtic xlabel
    htic-step 0 eq {
      xstart xstep _x1 { 
	  dup
	  dup goodxtic { _y0 xtic } { pop } ifelse 
	  dup goodxlabel { _y0 xlabel } { pop } ifelse
      } for
    } {
      xstart xstep xend {
          dup _y0 xtic _y0 xlabel
      } for
    } ifelse
  } if

  want-vtic {
    bordermatrix setmatrix % Y-tics need new matrix
    inverted-numbers {
          _x0 _y0 translate 1 -1 scale 0 height neg translate
          _x0 neg _y0 neg translate } if
    _y0 _x1 2 copy ytic ylabel
    _y1 _x1 2 copy ytic ylabel
    vtic-step 0 eq {
      ystart ystep _y1 { 
	  dup
	  dup goodytic { _x1 ytic } { pop } ifelse
	  dup goodylabel { _x1 ylabel } { pop } ifelse
      } for
    } {
      ystart ystep yend {
	  dup _x1 ytic _x1 ylabel
      } for
    } ifelse
  } if

  bordermatrix setmatrix
} def

% ------------------------------------------------------------------------
% Tag file abbreviations

/Left /left def
/Right /right def
/Sub -1 def
/Sup 1 def
/Plain 0 def

% extra kludges

/extra-labels { plotdata initclip  /Fontsize 8 def } def

/right-label { % y str
  _x1 0.2 inch add 
  3 2 roll % str x y
  moveto
  ticklen 0 rmoveto
  0 Fontsize 4 div scalefactor div inverted-dotplot not { neg } if rmoveto
  gsave
    savedmatrix setmatrix Hadjust show-in-font
  grestore
} def

/bottom-label { % x str
  _y0 0.25 inch sub 
  3 -1 roll exch % str x y
  moveto
  ticklen 0 rmoveto
  0 Fontsize 4 div scalefactor div inverted-dotplot not { neg } if rmoveto
  gsave
    savedmatrix setmatrix Hadjust show-in-font
  grestore
} def

/bottom-label-rotated { % x str
  _y0 0.25 inch sub 
  3 -1 roll exch % str x y
  moveto
  ticklen 0 rmoveto
  0 Fontsize 4 div scalefactor div inverted-dotplot not { neg } if rmoveto
  gsave   
    savedmatrix setmatrix Hadjust 90 rotate show-in-font
  grestore
} def

/bottom-label-reverse-rotated { % x str
  _y0 0.25 inch sub 
  3 -1 roll exch % str x y
  moveto
  ticklen 0 rmoveto
  0 Fontsize 4 div scalefactor div inverted-dotplot not { neg } if rmoveto
  gsave   
    savedmatrix setmatrix Hadjust -90 rotate show-in-font
  grestore
} def

% ------------------------------------------------------------------------
% Plot data...
default-options
@@@EndProlog@@@
# set file options
# main
# plotdata
# ... lines
# tag definitions
# horizontal
# ... stuff
# vertical
# ... stuff
cat
echo "end grestore"
case "$NOSHOWPAGE" in
'') echo "showpage"
esac
exit 0
