view glib/ps.c @ 0:5242703e91d3 tip

Initial checkin for AIM92 aimR8.2 (last updated May 1997).
author tomwalters
date Fri, 20 May 2011 15:19:45 +0100
parents
children
line wrap: on
line source
/*
  Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989
  ===========================================================================
  Permission to use, copy, modify, and distribute this software without fee 
  is hereby granted for research purposes, provided that this copyright 
  notice appears in all copies and in all supporting documentation, and that 
  the software is not redistributed for any fee (except for a nominal shipping 
  charge). Anyone wanting to incorporate all or part of this software in a
  commercial product must obtain a license from the Medical Research Council.
  The MRC makes no representations about the suitability of this 
  software for any purpose.  It is provided "as is" without express or implied 
  warranty.

  THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
  ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE
  A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY 
  DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 
  AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/

/*
  ps.c
  ====
  primitive PostScript interface ala windows.h interface.
  Copyright (c), 1989  The Medical Research Council, Applied Psychology Unit.
  Author  : John Holdsworth   22nd March, 1989.
            Michael Akeroyd   Summer 1994.

  Edited  : Roy P 27-11-92: commented out two if statements with this->hidden
            in them to force hiddenline.
            Also added '(void)' at start of line after second of the lines
	    commented out to make it symmetric with similar lines.

          : MAA. Summer 1994. rebuild. Notes:
          (1) don't print windows bigger than 800 pixels wide; they aren't scaled 
              properly. 
          (2) all windows get drawn in the centre of the page.
          (3) because of the 'fill's in drawing the data, the tick-marks can
              get blanked out. To avoid this, the whole frame+marks are drawn
              twice, at the begining (to get the coorect clipppath) and at the 
              end
          : MAA. Autumn 1994. rebuilt to avoid note (3).

*/


#include <stdio.h>
#if defined(THINK_C) || defined(NeXT)
#include <stdlib.h>
#else
#include <malloc.h>
#endif
#include "windows.h"
#include "grey.h"
#include "options.h"   /* MAA: 23-4-1994: required for isON() */
#include "string.h"    /* MAA: Summer 1994: required for atof() */
#ifndef NeXT
/* extern int fprintf() ;       */      /* mha 8/4/97:  sgi stops here */
#endif

static char *sccs_id = "@(#)ps.c	1.31     J. Holdsworth (MRC-APU)  7/7/93  Revised MAA 1994" ;


/* resolution parameters for line width */
#define POINTS_PER_INCH 72     /* standard definition of "points" */
#define PIXELS_PER_INCH 300    /* laserwriterII */
#define PIXELS_PER_POINT ( ( double ) PIXELS_PER_INCH / POINTS_PER_INCH )


/* limitation on graphics path lengths */
#define MAX_PATH 350 


typedef struct {
 windowEntries *entries ; /* pointers to method routines below */
 char *xptr ;             /* general pointer to postscript device */
 int (*sender)(), (*closer)() ;       /* function to transmit postscript */
 int (*storer)(), (*recaller)(), (*reader)(), (*writer)(), (*pauser)() ; /* functions which may be used */
 int x, y, width, height, pixels, hidden, page ; /* window paramaters */
 enum { False, True } drawn, showpage ; /* if drawn and if clear not used and
			                 window can be included in document */
 struct _lookup *lookup ; /* state structure for dithering routines in grey.c*/
 } *psWindowObject ;
 
static windowsClass psClass ;



/* MAA: lots of new options */
extern *rotateaxesstr;
extern char *xstartstr, *ystartstr, *xendstr, *yendstr;
extern char *xnewtitlestr, *ynewtitlestr;
extern char *portraitstr, *landscapestr;
extern char *fontnamestr, *fontsizestr, *titlesizestr;
extern char *xticksstr, *yticksstr, *outsidestr;
extern char *axistopstr, *axisbottomstr, *axisleftstr, *axisrightstr;
extern char *xmajorticksstr, *xminorticksstr;
extern char *ymajorticksstr, *yminorticksstr;
extern char *axislinewidthstr, *figurelinewidthstr; 
extern char *boxstr;
static double temp_xmin;
static double temp_xmax;
static double temp_ymin;
static double temp_ymax;


/*-----------------------------------------------------------------------*/


WindowObject newPostScriptWindow( xptr, default_x, default_y, default_width, default_height, pixels, sender, closer, storer, recaller, reader, writer, pauser, pshidden )
     char *xptr ;
     int default_x, default_y, default_width, default_height, pixels ;
     int (*sender)(), (*closer)() ;
     int (*storer)(), (*recaller)(), (*reader)(), (*writer)(), (*pauser)() ;
     int pshidden;            /* =0 if off, =1 if on */
{
  psWindowObject this = ( psWindowObject ) malloc( sizeof ( *this ) ) ;
  char psfontstr[30];
  char **ptr ;

  if( psClass.super == (windowsClass *) 0 )
    (void) initPostScriptClass( &psClass ) ;
  this->entries = &psClass.entries ;
  this->xptr     = xptr ;
  this->sender   = sender ;
  this->storer   = storer ;
  this->recaller = recaller ;
  this->reader   = reader ;
  this->writer   = writer ;
  this->pauser   = pauser ;
  this->closer   = closer ;
  this->x       = default_x ;
  this->y       = default_y ;
  this->width   = default_width ;
  this->height  = default_height ;
  this->hidden  = pshidden ;
  this->pixels  = abs( pixels ) ;
  this->lookup  = 0 ;
  this->drawn   = False ;

  (void) this->sender( this->xptr, "%%!PS-Adobe-2.0 EPSF-1.2\n");
  (void) this->sender( this->xptr, "%%%%Title: Windows postscript file\n");
  (void) this->sender( this->xptr, "%%%%Creator: %s\n", sccs_id);
  (void) this->sender( this->xptr, "%%%%BoundingBox: %d %d %d %d\n", this->x, this->y, this->x+this->width, this->y+this->height);
  (void) this->sender( this->xptr, "%%%%Pages: (atend)\n", this->y);
/*  (void) this->sender( this->xptr, "%%%%DocumentFonts: Times-Roman\n");*/
  (void) this->sender( this->xptr, "%%%%EndComments\n") ;
  
  if ( this->hidden == 0 ) {
    (void) this->sender( this->xptr, "\n%%/fill workaround: no hidden lines. MAA. 22-1-1993\n" );
    (void) this->sender( this->xptr, "/fill {} def\n\n" );}
  else ;

  /* Fonts. The only allowed ones are Times-Roman, Helvetica and Courier,
   * because they are the only three you get in the Adobe Red Book, and
   * so are presumably the onyl three you get in all printers.*/
  if      (!strcmp(fontnamestr, "Times")) {strcpy(psfontstr, "Times-Roman");}
  else if (!strcmp(fontnamestr, "times")) {strcpy(psfontstr, "Times-Roman");}
  else if (!strcmp(fontnamestr, "Roman")) {strcpy(psfontstr, "Times-Roman");}
  else if (!strcmp(fontnamestr, "roman")) {strcpy(psfontstr, "Times-Roman");}
  else if (!strcmp(fontnamestr, "times-roman")) {strcpy(psfontstr, "Times-Roman");}
  else if (!strcmp(fontnamestr, "Times-Roman")) {strcpy(psfontstr, "Times-Roman");}
  else if (!strcmp(fontnamestr, "timesroman")) {strcpy(psfontstr, "Times-Roman");}
  else if (!strcmp(fontnamestr, "RimesRoman")) {strcpy(psfontstr, "Times-Roman");}
  else if (!strcmp(fontnamestr, "TimesBold")) {strcpy(psfontstr, "Times-Bold");}
  else if (!strcmp(fontnamestr, "timesbold")) {strcpy(psfontstr, "Times-Bold");}
  else if (!strcmp(fontnamestr, "timesbold")) {strcpy(psfontstr, "Times-Bold");}
  else if (!strcmp(fontnamestr, "times-bold")) {strcpy(psfontstr, "Times-Bold");}
  else if (!strcmp(fontnamestr, "Times-Bold")) {strcpy(psfontstr, "Times-Bold");}
						
  else if (!strcmp(fontnamestr, "Helvetica")) {strcpy(psfontstr, "Helvetica");}
  else if (!strcmp(fontnamestr, "helvetica")) {strcpy(psfontstr, "Helvetica");}
  else if (!strcmp(fontnamestr, "Hel")) {strcpy(psfontstr, "Helvetica");}
  else if (!strcmp(fontnamestr, "hel")) {strcpy(psfontstr, "Helvetica");}
  else if (!strcmp(fontnamestr, "HelveticaBold")) {strcpy(psfontstr, "Helvetica-Bold");}
  else if (!strcmp(fontnamestr, "Helveticabold")) {strcpy(psfontstr, "Helvetica-Bold");}
  else if (!strcmp(fontnamestr, "helveticabold")) {strcpy(psfontstr, "Helvetica-Bold");}
  else if (!strcmp(fontnamestr, "Helvetica-Bold")) {strcpy(psfontstr, "Helvetica-Bold");}
  else if (!strcmp(fontnamestr, "helvetica-bold")) {strcpy(psfontstr, "Helvetica-Bold");}
  else if (!strcmp(fontnamestr, "helbold")) {strcpy(psfontstr, "Helvetica-Bold");}
  else if (!strcmp(fontnamestr, "HelBold")) {strcpy(psfontstr, "Helvetica-Bold");}

  else if (!strcmp(fontnamestr, "Courier")) {strcpy(psfontstr, "Courier");}
  else if (!strcmp(fontnamestr, "courier")) {strcpy(psfontstr, "Courier");}
  else if (!strcmp(fontnamestr, "Cou")) {strcpy(psfontstr, "Courier");}
  else if (!strcmp(fontnamestr, "cou")) {strcpy(psfontstr, "Courier");}
  else if (!strcmp(fontnamestr, "Courier-Bold")) {strcpy(psfontstr, "Courier-Bold");}
  else if (!strcmp(fontnamestr, "courier-bold")) {strcpy(psfontstr, "Courier-Bold");}
  else if (!strcmp(fontnamestr, "courierbold")) {strcpy(psfontstr, "Courier-Bold");}
  else if (!strcmp(fontnamestr, "CourierBold")) {strcpy(psfontstr, "Courier-Bold");}
  else if (!strcmp(fontnamestr, "CouBold")) {strcpy(psfontstr, "Courier-Bold");}
  else if (!strcmp(fontnamestr, "coubold")) {strcpy(psfontstr, "Courier-Bold");}
  
  else {
    fprintf(stderr, "WARNING: Unknown font %s. (allowed time, helvetica or courier.)\n", fontnamestr);
    fprintf(stderr, "WARNING: Stopping here; no Postscript generated\n");
    exit(-1);}


  /* copy postscript code for axes into output file */
  (void) this->sender( this->xptr, "%%! simple postscript axes\n");
  (void) this->sender( this->xptr, "%% v1.10 John Holdsworth (5/31/91).\n");
  (void) this->sender( this->xptr, "%% Revised M Akeroyd (Summer, Autumn 1994)\n");
  (void) this->sender( this->xptr, "\n");
  (void) this->sender( this->xptr, "  /midprint { %% str x y midprint -\n");
  (void) this->sender( this->xptr, "    moveto\n");
  (void) this->sender( this->xptr, "    dup\n");
  (void) this->sender( this->xptr, "    stringwidth pop 2 div neg 0 rmoveto\n");
  (void) this->sender( this->xptr, "    show\n");
  (void) this->sender( this->xptr, "  } def\n");
  (void) this->sender( this->xptr, "\n");
  (void) this->sender( this->xptr, "  /leftprint { %% str x y leftprint -\n");
  (void) this->sender( this->xptr, "    moveto\n");
  (void) this->sender( this->xptr, "    dup\n");   
  (void) this->sender( this->xptr, "    stringwidth pop neg fontsize 0.4 mul neg rmoveto\n");
  (void) this->sender( this->xptr, "    show\n");  
  (void) this->sender( this->xptr, "  } def\n");
  (void) this->sender( this->xptr, "\n");
  (void) this->sender( this->xptr, "  /ticks { %% min max <float> <float> ticker -\n");
  (void) this->sender( this->xptr, "    /ticker  exch def %% procedure to draw ticks\n");
  (void) this->sender( this->xptr, "    /fmax exch cvr def %% relative spacing of max ticks (0.5x, etc)\n");
  (void) this->sender( this->xptr, "    /fmin exch cvr def %% relative spacing of min ticks (0.5x, etc)\n");
  (void) this->sender( this->xptr, "    /max exch cvr def %% axis maximum\n");
  (void) this->sender( this->xptr, "    /min exch cvr def %% axis minimum\n");
  (void) this->sender( this->xptr, "    /maxsubticks 50 def\n");
  (void) this->sender( this->xptr, "    max min ne {\n");
  (void) this->sender( this->xptr, "	%% calculate order of magnitude\n");
  (void) this->sender( this->xptr, "	/delta max min sub log ceiling 1 sub 10 exch exp def\n");
  (void) this->sender( this->xptr, "	%% do ticks\n");
  (void) this->sender( this->xptr, "	min delta div ceiling delta mul\n");
  (void) this->sender( this->xptr, "	delta fmax mul\n");
  (void) this->sender( this->xptr, "	max delta div floor   delta mul\n");
  (void) this->sender( this->xptr, "	{\n");
  (void) this->sender( this->xptr, "		min sub max min sub div 1.333333 exch ticker\n");
  (void) this->sender( this->xptr, "	}\n");
  (void) this->sender( this->xptr, "	for\n");
  (void) this->sender( this->xptr, "	%% do sub ticks (but only if fmin != 0)\n");
  (void) this->sender( this->xptr, "	fmin 0 ne {");
  (void) this->sender( this->xptr, "      max min sub delta div dup\n");
  (void) this->sender( this->xptr, "	  10 mul maxsubticks lt {.1} {5 mul maxsubticks lt {.2} {.5} ifelse } ifelse\n");
  (void) this->sender( this->xptr, "	  delta mul /delta exch def\n");
  (void) this->sender( this->xptr, "	  min delta div ceiling delta mul\n");
  (void) this->sender( this->xptr, "	  delta fmin mul \n");
  (void) this->sender( this->xptr, "	  max delta div floor   delta mul\n");
  (void) this->sender( this->xptr, "	  {\n");
  /* MAA: This used to be 0.25; I've changed it (0.25 * 1.33), so its in real points.*/
  (void) this->sender( this->xptr, "		  min sub max min sub div 0.666666 exch ticker\n");
  (void) this->sender( this->xptr, "	  }\n");
  (void) this->sender( this->xptr, "	  for\n");
  (void) this->sender( this->xptr, "      } if\n");
  (void) this->sender( this->xptr, "    } if\n");
  (void) this->sender( this->xptr, "  } def\n");
  (void) this->sender( this->xptr, "\n");
  (void) this->sender( this->xptr, "/Axes { %% title xmin xmax xtitle ymin ymax ytitle Axes -\n");
  (void) this->sender( this->xptr, "/AxesDict 50 dict def\n");
  (void) this->sender( this->xptr, "AxesDict begin\n");
  (void) this->sender( this->xptr, "  /ytitle exch def\n");
  (void) this->sender( this->xptr, "  /ymax   exch def\n");
  (void) this->sender( this->xptr, "  /ymin   exch def\n");
  (void) this->sender( this->xptr, "  /xtitle exch def\n");
  (void) this->sender( this->xptr, "  /xmax   exch def\n");
  (void) this->sender( this->xptr, "  /xmin   exch def\n");
  (void) this->sender( this->xptr, "  /title  exch def\n");
  (void) this->sender( this->xptr, "  newpath clippath pathbbox /height exch def\n");
  (void) this->sender( this->xptr, "			    /width  exch def\n");
  (void) this->sender( this->xptr, "			    pop pop\n");
  (void) this->sender( this->xptr, "  /tagsize  0.05 height mul neg def\n");
  if (isOFF(xticksstr))
    (void) this->sender( this->xptr, "  /xtagsize tagsize 1.33 mul def\n");
  else
    (void) this->sender( this->xptr, "  /xtagsize %s neg 1.33 mul def\n", xticksstr);
  if (isOFF(yticksstr))
    (void) this->sender( this->xptr, "  /ytagsize tagsize 1.33 mul def\n");
  else
    (void) this->sender( this->xptr, "  /ytagsize %s neg 1.33 mul def\n", yticksstr);
  if (isOFF(fontsizestr))
    (void) this->sender( this->xptr, "  /fontsize 0.05 height mul def\n");
  else {
    /* note 1.333 multiplier: required to get rid of the 0.75 later on */
    (void) this->sender( this->xptr, "  /fontsize %s 1.333 mul def\n", fontsizestr);}
  (void) this->sender( this->xptr, "  /space    0.10 height mul def\n");
  (void) this->sender( this->xptr, "  /%s findfont fontsize scalefont setfont\n", psfontstr);
  /* MAA: What do these 0.75/0.75 do? Quite a lot: they seem to be a screen -> paper multiplu constant*/
  (void) this->sender( this->xptr, "  width 0.20 mul  0.15 height mul  translate  0.75 0.75 scale\n");
  (void) this->sender( this->xptr, "  gsave\n");
  (void) this->sender( this->xptr, "  gsave\n");
  (void) this->sender( this->xptr, "  %s setlinewidth\n", axislinewidthstr);
  /* MAA: I do  not knwo why this (2,2) translation is here, but it seems to get in the way */
  /*  (void) this->sender( this->xptr, "  currentlinewidth 2 div neg dup translate\n");*/
  (void) this->sender( this->xptr, "  newpath\n");
  if (isOFF(titlesizestr))
    (void) this->sender( this->xptr, "  title  width 2 div    height  tagsize  1.75 mul sub midprint\n");
  else {
    (void) this->sender( this->xptr, "  gsave\n");
    /* note 1.333 multiplier: required to get rid of the 0.75 later on */
    (void) this->sender( this->xptr, "  /%s findfont %s 1.333 mul scalefont  setfont\n", psfontstr, titlesizestr);
    (void) this->sender( this->xptr, "  title  width 2 div    height  tagsize  1.75 mul sub midprint\n");}
  if (isON(axisbottomstr)){
    (void) this->sender( this->xptr, "  xmin   0              xtagsize fontsize sub midprint\n");
    (void) this->sender( this->xptr, "  xmax   width          xtagsize fontsize sub midprint\n");
    (void) this->sender( this->xptr, "  xmin cvr 0 lt  \n");
    (void) this->sender( this->xptr, "    {xmax cvr 0 ge \n");
    (void) this->sender( this->xptr, "       {(0) width xmin cvr neg xmin cvr neg xmax cvr add div mul xtagsize 1.0 mul fontsize sub midprint \n");
    (void) this->sender( this->xptr, "        /xtitleconstant 2.0 def} \n");
    (void) this->sender( this->xptr, "       {/xtitleconstant 1.0 def} \n");
    (void) this->sender( this->xptr, "       ifelse}\n");
    (void) this->sender( this->xptr, "    {/xtitleconstant 1.0 def} \n");
    (void) this->sender( this->xptr, "    ifelse\n");
    (void) this->sender( this->xptr, "  xtitle width 2 div    xtagsize xtitleconstant mul fontsize sub midprint\n");
  }
  if (isON(axisleftstr)) {
    (void) this->sender( this->xptr, "  ymin   ytagsize  2.0 mul  0                    leftprint\n");
    (void) this->sender( this->xptr, "  ymax   ytagsize  2.0 mul  height               leftprint\n");
    (void) this->sender( this->xptr, "  ymin cvr 0 lt { \n");
    (void) this->sender( this->xptr, "    ymax cvr 0 ge {\n");
    (void) this->sender( this->xptr, "       (0) ytagsize  2.0 mul  height ymin cvr neg ymin cvr neg ymax cvr add div mul leftprint} \n");
    (void) this->sender( this->xptr, "       if}\n");
    (void) this->sender( this->xptr, "    if\n");}
  (void) this->sender( this->xptr, "  90 rotate\n");
  (void) this->sender( this->xptr, "  ytitle height 2 div   space   1.75 mul             midprint\n");
  (void) this->sender( this->xptr, "  grestore\n"); 
  (void) this->sender( this->xptr, "  grestore\n");
  (void) this->sender( this->xptr, "end } def\n");
  
  
  
  /* MAA: New procedure AxesBox, which draws the box ... This is actually a revised workaround
   * for the 'borderframe' problem. */
  (void) this->sender( this->xptr, "\n\n" ) ;  
  (void) this->sender( this->xptr, "/AxesBox { %% xmin xmax ymin ymax AxesBox -\n");
  (void) this->sender( this->xptr, "/AxesBoxDict 50 dict def\n");
  (void) this->sender( this->xptr, "AxesBoxDict begin\n");
  (void) this->sender( this->xptr, "  /ymax   exch def\n");
  (void) this->sender( this->xptr, "  /ymin   exch def\n");
  (void) this->sender( this->xptr, "  /xmax   exch def\n");
  (void) this->sender( this->xptr, "  /xmin   exch def\n");
  (void) this->sender( this->xptr, "  newpath clippath pathbbox /height exch def\n");
  (void) this->sender( this->xptr, "			    /width  exch def\n");
  (void) this->sender( this->xptr, "			    pop pop\n");
  (void) this->sender( this->xptr, "  /tagsize  0.05 height mul neg def\n");
  if (isOFF(xticksstr))
    (void) this->sender( this->xptr, "  /xtagsize tagsize def\n");
  else
    (void) this->sender( this->xptr, "  /xtagsize %s neg def\n", xticksstr);
  if (isOFF(yticksstr))
    (void) this->sender( this->xptr, "  /ytagsize tagsize def\n");
  else
    (void) this->sender( this->xptr, "  /ytagsize %s neg def\n", yticksstr);
  (void) this->sender( this->xptr, "  /space    0.10 height mul def\n");
  (void) this->sender( this->xptr, "  width 0.20 mul  0.15 height mul  translate  0.75 0.75 scale\n");
  (void) this->sender( this->xptr, "  gsave\n");
  (void) this->sender( this->xptr, "  %s setlinewidth\n", axislinewidthstr);
  (void) this->sender( this->xptr, "  newpath\n");
  if (isON(outsidestr)){
    (void) this->sender( this->xptr, "  /toptagsize xtagsize neg def\n");
    (void) this->sender( this->xptr, "  /bottomtagsize xtagsize def\n");
    (void) this->sender( this->xptr, "  /lefttagsize ytagsize def\n");
    (void) this->sender( this->xptr, "  /righttagsize ytagsize neg def\n");}
  else{
    (void) this->sender( this->xptr, "  /toptagsize xtagsize def\n");
    (void) this->sender( this->xptr, "  /bottomtagsize xtagsize neg def\n");
    (void) this->sender( this->xptr, "  /lefttagsize ytagsize neg def\n");
    (void) this->sender( this->xptr, "  /righttagsize ytagsize def\n");}
  if (isON(axisbottomstr)){
    (void) this->sender( this->xptr, "  0     bottomtagsize  moveto  0     0  lineto stroke\n");
    (void) this->sender( this->xptr, "  width bottomtagsize  moveto  width 0  lineto stroke\n");}
  if (isON(axistopstr)){
    (void) this->sender( this->xptr, "  0     height moveto 0   toptagsize rmoveto  0      height lineto stroke\n");
    (void) this->sender( this->xptr, "  width height moveto 0   toptagsize rmoveto  width  height lineto stroke\n");}
  if (isON(axisleftstr)){
    (void) this->sender( this->xptr, "  0     0      moveto lefttagsize  0 rmoveto  0      0      lineto stroke\n");
    (void) this->sender( this->xptr, "  0     height moveto lefttagsize  0 rmoveto  0      height lineto stroke\n");}
  if (isON(axisrightstr)){
    (void) this->sender( this->xptr, "  width 0      moveto righttagsize 0 rmoveto  width  0      lineto stroke\n");
    (void) this->sender( this->xptr, "  width height moveto righttagsize 0 rmoveto  width  height lineto stroke\n");}
  if (isON(axisbottomstr))
    (void) this->sender( this->xptr, "  xmin xmax %s %s {width  mul      0 moveto bottomtagsize mul 0 exch rlineto stroke} ticks\n", xminorticksstr, xmajorticksstr);
  if (isON(axistopstr))
    (void) this->sender( this->xptr, "  xmin xmax %s %s {width  mul height moveto toptagsize mul 0 exch rlineto stroke} ticks\n", xminorticksstr, xmajorticksstr);
  if (isON(axisleftstr))
    (void) this->sender( this->xptr, "  ymin ymax %s %s {height mul     0 exch moveto lefttagsize  mul 0      rlineto stroke} ticks\n", yminorticksstr, ymajorticksstr);
  if (isON(axisrightstr))
    (void) this->sender( this->xptr, "  ymin ymax %s %s {height mul width exch moveto righttagsize mul 0      rlineto stroke} ticks\n", yminorticksstr, ymajorticksstr);
  (void) this->sender( this->xptr, "  grestore\n");
  (void) this->sender( this->xptr, "  newpath 0 0 moveto width 0 lineto width height lineto 0 height lineto closepath stroke clip\n");
  (void) this->sender( this->xptr, "end } def\n");
  (void) this->sender( this->xptr, "\ngsave\n\n" ) ;

  /* rotate for landscape mode */ 
  if( this->width > this->height ) {
    (void) this->sender( this->xptr, "%% shift orgin and rotate for landscape mode\n" ) ;
    (void) this->sender( this->xptr, "newpath clippath pathbbox pop exch translate pop 90 rotate %% notstand\n" ) ; }    
  (void) this->sender( this->xptr, "%% center image on page\n" ) ;
  (void) this->sender( this->xptr, "newpath clippath pathbbox exch %d sub 2 div exch %d sub 2 div translate pop pop %%notstand\n", this->width, this->height ) ;
  
  /* set clippath - used by axis routine */
  (void) this->sender( this->xptr, "newpath 0 0 moveto %d 0 rlineto 0 %d rlineto %d neg 0 rlineto closepath clip\n", this->width, this->height, this->width ) ;
/*  (void) this->sender( this->xptr, "%f setlinewidth\n/l { lineto } def\n", this->pixels / PIXELS_PER_POINT ) ;*/
  (void) this->sender( this->xptr, "%s setlinewidth\n/l { lineto } def\n", figurelinewidthstr) ;

  (void) this->sender( this->xptr, "1 setlinecap\n/pt {moveto 0 0 rlineto stroke} def\n" ) ;
  (void) this->sender( this->xptr, "106 45 { dup mul exch\n dup mul add 1.0\n exch sub } setscreen\n" ) ;
  
  this->page = 1 ;
  (void) this->sender( this->xptr, "%%%%EndProlog\n%%%%Page %d %d\ngsave\n", this->page, this->page ) ;
  this->showpage = False ;
  return ( ( WindowObject ) this ) ;
}



/*---------------------------------------------------------------*/



WindowObject newFILEWindow( fp, default_x, default_y, default_width, default_height, pixels, pshidden)
     FILE *fp ;
     int default_x, default_y, default_width, default_height, pixels ;
     int pshidden;
{
  extern int fflush() ;
  
  return ( newPostScriptWindow( fp, default_x, default_y, default_width, default_height, pixels, fprintf, (int (*)())0, (int (*)())0, (int (*)())0, (int (*)())0, (int (*)())0, fflush, pshidden )) ;
}



WindowObject newPSWindow( name, default_x, default_y, default_width, default_height, pixels, pshidden )
     char *name ;
     int default_x, default_y, default_width, default_height, pixels ;
     int pshidden ;
{
  extern int fclose() ;
  FILE *fp = stdout ;
  
  if( name != ( char * ) 0 && name[0] != '\000' )
    if( ( fp = fopen( name, "w" ) ) == ( FILE * ) 0 ) {
      (void) fprintf( stderr, "Could not open file \"%s\" for output\n", name ) ;
      exit( 1 ) ;}
  
  return ( newPostScriptWindow( fp, default_x, default_y, default_width, default_height, pixels, fprintf, fclose, (int (*)())0, (int (*)())0, (int (*)())0, (int (*)())0, (int (*)()) 0  , pshidden )  ) ;
}



static short ps__x( this )
     psWindowObject this ;
{
  return( this->x ) ;
}


static short ps__y( this )
     psWindowObject this ;
{
  return( this->y ) ;
}


static short ps__width( this )
     psWindowObject this ;
{
  return( this->width ) ;
}


static short ps__height( this )
     psWindowObject this ;
{
  return( this->height ) ;
}


static void ps__draw( this, xs, ys, points )
     psWindowObject this ;
     short xs[], ys[] ;
     int points ;
{
  int path, point ;
  
  (void) this->sender( this->xptr, "newpath\n" ) ;
  if( points > 0 )
    for( point=1 ; point < points ; point+=path ) {
      (void) this->sender( this->xptr, "%d %d moveto\n", xs[point-1], ys[point-1] ) ;
      for( path=0 ; point+path < points && path < MAX_PATH ; path++ )
	(void) this->sender( this->xptr, "%d %d l\n", xs[point+path], ys[point+path] ) ;
      if( this->hidden && xs[point+path] == xs[point-1] &&
	 ys[point+path] == ys[point-1] )  /*Roy 27-11-92 */
	(void) this->sender( this->xptr, "gsave 1 setgray fill grestore\n" ) ;
      (void) this->sender( this->xptr, "stroke\n" ) ;}
  else {
    (void) this->sender( this->xptr, "gsave currentlinewidth 10. mul setlinewidth\n" ) ;
    for( point=1 ; point < abs(points) ; point++ )
      (void) this->sender( this->xptr, "%d %d pt\n", xs[point], ys[point] ) ;
    (void) this->sender( this->xptr, "grestore\n" ) ;}
  
  this->drawn = True ;
  return ;
}



static void ps__clear( this )
psWindowObject this ;
{
  if( this->drawn ) {
    ++this->page ;
    (void) this->sender( this->xptr, "grestore\n") ;
    (void) this->sender( this->xptr, "%s setlinewidth\n", axislinewidthstr) ;
    if (isON(boxstr))
      (void) this->sender( this->xptr, "(%g)  (%g) (%g)  (%g) AxesBox\n", temp_xmin, temp_xmax, temp_ymin, temp_ymax) ;
    (void) this->sender( this->xptr, "showpage\ngrestore\n%%%%Page: %d %d\ngsave\n", this->page, this->page ) ; }
  (void) this->sender( this->xptr, "gsave clippath 1 setgray fill grestore\n" ) ;
  this->showpage = True ;
  return ;
}



static void ps__close( this )
     psWindowObject this ;
{
  (void) this->sender( this->xptr, "grestore\n") ;
  (void) this->sender( this->xptr, "%s setlinewidth\n", axislinewidthstr) ;
  if (isON(boxstr))
    (void) this->sender( this->xptr, "(%g)  (%g) (%g)  (%g) AxesBox\n", temp_xmin, temp_xmax, temp_ymin, temp_ymax) ;
  if( this->showpage )  
    (void) this->sender( this->xptr, "showpage %% notstand\n" ) ;
  else
    this->page = 0 ;
  (void) this->sender( this->xptr, "grestore\n%%%%Trailer\ngrestore\n%%%%Pages: %d\n", this->page ) ;
  if( this->closer != 0 )
    this->closer( this ) ;
  free( (char *) this ) ;
  return ;
}



static int ps__store( this )
     psWindowObject this ;
{
  if( this->storer != 0 )
    return ( this->storer( this->xptr ) ) ;
  else
    (void) fprintf( stderr, "Invalid call to restore postscript image from memory!!" ) ;
  return 0 ;
}



static void ps__recall( this, which )
     psWindowObject this ;
int which ;
{
  if( this->recaller != 0 )
    this->recaller( this->xptr, which ) ;
  else
    (void) fprintf( stderr, "Invalid call to store postscript image in memory!!" ) ;
  return ;
}



static char *cmap( npixels )
     int *npixels ;
{
#ifdef NeXT
  static char ps_grey_scale[] = "04bf" ;
#else
  static char ps_grey_scale[] = "0123456789abcdef" ;
#endif
  
  *npixels = sizeof ( ps_grey_scale ) - 1 ;
  return ( ps_grey_scale ) ;
}



static void ps__fill( this, col, input, black, white, match, length, row_flag )
     psWindowObject this ;
     int col ;
     short *input;
     int black, white ;
     int *match, length ;
     int row_flag ;
{
  int chans, chan, y, blacky ;
  
  if( this->lookup == 0 ) {
    this->lookup = makeLookup( cmap, black, white, length ) ;
    (void) this->sender( this->xptr, "/picstr %d string def\n", length ) ;}
  if( col == 1 ) {
    if( row_flag )
      (void) this->sender( this->xptr, "%d %d 4\n[1 0 0 -1 0 %d]\n", this->width, this->height, this->height ) ;
    else
      (void) this->sender( this->xptr, "%d %d 4\n[0 1 -1 0 %d 0]\n", this->height, this->width, this->height ) ;
        (void) this->sender( this->xptr, "{currentfile\npicstr readhexstring pop}\nimage\n" ) ;}
  
  (void) this->sender( this->xptr, "%s\n", Lookup( col, this->lookup, input, match, length ) ) ;
  this->drawn = True ;
  return ;
}



static void ps__fillRow( this, row, input, black, white, match, width )
     psWindowObject this ;
     int row ;
     short *input ;
     int black, white ;
     int *match, width ;
{
  ps__fill( this, row, input, black, white, match, width, 1 ) ;
  return ;
}



static void ps__fillCol( this, col, input, black, white, match, height )
     psWindowObject this ;
     int col ;
     short *input ;
     int black, white ;
     int *match, height ;
{
  ps__fill( this, col, input, black, white, match, height, 0 ) ;
  return ;
}



static void ps__function( this, ys, segment, skip, offset, yspan, start, points )
     psWindowObject this ;
     short *ys ;
     int segment, skip ;
     double offset, yspan ;
     int start, points ;
{
  int stop = start + abs( segment ) ;
  int point, path = MAX_PATH, count, miny ;
  short *yptr = ys ;
  
  for( point = start ; point < stop-1 ; point += path-1 ) {
    if( path > stop - point ) 
      path = stop - point ;
    /* too-wide windows: something to do with Width( this) / (points -1.): 
     * next line.  No fix attempted. MAA, 22-1-1993. 
    */		
    this->sender( this->xptr, "newpath 0 0 moveto %d 0 rlineto 0 %d rlineto %d neg 0 rlineto closepath clip\n", this->width, this->height, this->width ) ;
    this->sender( this->xptr, "matrix currentmatrix [0 %g %g 0 0 %g] concat newpath %d %d moveto\n",
		 Height( this ) / yspan, Width( this ) / ( points - 1. ), offset, miny = yptr[0], point ) ;
    this->sender( this->xptr, "%s setlinewidth\n", figurelinewidthstr) ;

#if defined(NeXT)
    this->sender( this->xptr, "[\n" ) ;
    for( count=1 ; count < path ; count++ ) {
      yptr += skip ;
      (void) this->sender( this->xptr, "%d\n", yptr[0]-yptr[-skip] ) ;
      if( miny > yptr[0] )
	miny = yptr[0] ;}
    this->sender( this->xptr, "] {1 rlineto} forall\n" ) ;

#else
    this->sender( this->xptr, "/r {1 rlineto} bind def\n" ) ;
    for( count=1 ; count < path ; count++ ) {
      yptr += skip ;
      (void) this->sender( this->xptr, "%d r\n", yptr[0]-yptr[-skip] ) ;
      if( miny > yptr[0] )
	miny = yptr[0] ;}
#endif

    if( this->hidden ) /* roy 27-11-92 */
      this->sender( this->xptr, "gsave %d 0 rlineto 0 -%d rlineto closepath 1 setgray fill grestore\n", miny-yptr[0], path-1 ) ;
    (void) this->sender( this->xptr, "setmatrix stroke\n" ) ;}
  return ;
}



static int ps__read( this, fp, which )
     psWindowObject this ;
     FILE *fp ;
     int which ;
{
  if( this->reader != 0 )
    this->reader( this->xptr, fp, which ) ;
  else
    (void) fprintf( stderr, "Invalid call to read postscript image from file!!" ) ;
  return ;
}



static void ps__write( this, fp )
     psWindowObject this ;
     FILE *fp ;
{
  if( this->writer != 0 )
    this->writer( this->xptr, fp ) ;
  else
    (void) fprintf( stderr, "Invalid call to write postscript image to file!!" ) ;
  return ;
}



static char ps__pause( this )
     psWindowObject this ;
{
  if( this->pauser != (int (*)()) 0 )
    return this->pauser( this->xptr ) ;
  return '\000' ;
}


static void ps__axes( this, title, xmin, xmax, xtitle, ymin, ymax, ytitle )
     psWindowObject this ;
     char *title ;
     double xmin, xmax ;
     char *xtitle ;
     double ymin, ymax ;
     char *ytitle ;
{
  if (strcmp(xstartstr, "")) xmin = atoi(xstartstr);
  if (strcmp(xendstr, ""))   xmax = atoi(xendstr);
  if (strcmp(ystartstr, "")) ymin = atoi(ystartstr);
  if (strcmp(yendstr, ""))   ymax = atoi(yendstr);
  if (!strcmp(xnewtitlestr, "")) xnewtitlestr=xtitle;
  if (!strcmp(ynewtitlestr, "")) ynewtitlestr=ytitle;  

  temp_xmin = (double) xmin;
  temp_xmax = (double) xmax;
  temp_ymin = (double) ymin;
  temp_ymax = (double) ymax;

  if ( isOFF (rotateaxesstr) )
    (void) this->sender( this->xptr, "(%s)   (%g)  (%g)  (%s)    (%g)  (%g)  (%s) Axes\n", title, xmin, xmax, xnewtitlestr, ymin, ymax, ynewtitlestr ) ;
  else
    (void) this->sender( this->xptr, "(%s)   (%g)  (%g)  (%s)    (%g)  (%g)  (%s) Axes\n", title, ymin, ymax, ytitle, (xmax * -1), (xmin * -1), xtitle ) ;
  this->drawn = True ;
  return ;
}



static void ps__marker( this, label, p, points )
     psWindowObject this ;
     char *label ;
     int p, points ;
{
  short pos = ( this->entries->width( this ) * p + points / 2 ) / points ;
  
  (void) this->sender( this->xptr, "newpath %d %d moveto %d %d rlineto stroke\n", pos, 0, 0, this->entries->height( this ) ) ;
  
  this->drawn = True ;
  return ;
}

static int ps__special( this, code, data )
     psWindowObject this ;
     int code ;
     char *data ;
{
  this->drawn = True ;
  switch( code ) {
  case 1 :
    (void) this->sender( this->xptr, "%s\n", data ) ;
    return 1 ;
  }
  return 0 ;
}



windowsClass *initPostScriptClass( class )
     windowsClass *class ;
{
  class->super    = &psClass ;
  class->entries.x        = ps__x ;
  class->entries.y        = ps__y ;
  class->entries.width    = ps__width ;
  class->entries.height   = ps__height ;
  class->entries.draw     = ps__draw ;
  class->entries.clear    = ps__clear ;
  class->entries.close    = ps__close ;
  class->entries.store    = ps__store ;
  class->entries.recall   = ps__recall ;
  class->entries.fillRow  = ps__fillRow ;
  class->entries.fillCol  = ps__fillCol ;
  class->entries.function = ps__function ;
  class->entries.read     = ps__read ;
  class->entries.write    = ps__write ;
  class->entries.pause    = ps__pause ;
  class->entries.axes     = ps__axes ;
  class->entries.marker   = ps__marker ;
  class->entries.special  = ps__special ;
  
  if( psClass.super == (windowsClass *) 0 )
    (void) initPostScriptClass( &psClass ) ;
  return ( &psClass ) ;
}



/* The End */
/*----------------------------------------------------------------------*/