// drawps.cc     read a .draw file and generate a .ps file
//               drawps xxx.draw  xxx.ps

#include <stdio.h> // C++ compilation of C code
#include <string.h>
#include <ctype.h>

float xps(float x); // offset and scale x to page 36 to 576 
float yps(float y); // offset and scale y to page 36 to 756
void  get_xlim(int x0, int x1);
void  get_ylim(int y0, int y1);
static float xminf, yminf, xmaxf, ymaxf;
static float xoff, yoff, xsca, ysca;
// xsca = 540.0/(xmaxf-xminf);
// ysca = 720.0/(ymaxf-yminf);
// xoff = 36.0;
// yoff = 36.0;
// x' = xsca*x + xoff
// y' = ysca*y + yoff
#undef imin
#undef imax
#define imin(a,b) ((a)<(b)?(a):(b))
#define imax(a,b) ((a)>(b)?(a):(b))
#undef iabs
#define iabs(a) ((a)<0?(-(a)):(a))

int main(int argc, char *argv[])
{
  char rline[1000]; // input line
  int x0, y0, x1, y1, x2, y2;
  int which, side, siz;
  char msg[100];
  char * p;
  int i, j, t;
  int width, height, radius;
  int line_width, filled, line_color, fill_color;
  int frame_xmin, frame_ymin, frame_xmax, frame_ymax, frame_auto; 
  int grid_displayed, grid_spacing, grid_snap_on;
  float ps_line[5]= {1.0f, 1.0f, 2.0f, 3.0f, 4.0f};
  float ps_radius;
  int dx, dy, dr, usex;
  float shade=0.75f; /* light,  .25 would be dark */
  FILE * draw_file = stdin;
  FILE * ps_file = stdout;

  char draw_file_name[100]; // name and extension .draw
  char ps_file_name[100];   // name and extension .ps

  if(argc<3)
  {
    printf(" usage: drawps input_file.draw output_file.ps \n");
    return 1;
  }

  xminf= 999.0f; // initialization, values set by first pass
  yminf= 999.0f;
  xmaxf=-999.0f;
  ymaxf=-999.0f;
  xoff = 36.0;
  yoff = 36.0;

  strcpy(draw_file_name, argv[1]);
  draw_file = fopen(draw_file_name, "r");
  if(draw_file==0)
  {
    printf("could not open draw file %s \n", draw_file_name);
    return 1;
  }

  strcpy(ps_file_name, argv[2]);
  ps_file = fopen(ps_file_name, "w");
  if(ps_file==0)
  {
    printf("could not open postscript output file %s for write\n", ps_file_name);
    return 1;
  }

  fprintf(ps_file,"%%!PS-Adobe-1.0\n");



  // Read in the .draw file
  printf("draw to PostScript \n");
  fgets(rline, 999, draw_file);
  // printf("drawps read:%s", rline);
  if(strncmp("start of save, display ", rline, 22)!=0)
  {
    printf("not a .draw  save file\n");
    return 1;
  }
  while(!feof(draw_file))
  {
    fgets(rline, 999, draw_file);
    // printf("drawps read:%s", rline);
    if(strncmp("start of save, paste ", rline, 20)==0) break;
    if(strncmp("line ", rline, 5)==0)
    {
      sscanf(rline,"line  %d,%d %d,%d, %X,%d \n",
                    &x0, &y0, &x1, &y1,
                    &line_color, &line_width);
      printf("line  x0=%d, y0=%d, x1=%d, y1=%d, col=%X, lwid=%d \n",
                    x0, y0, x1, y1, line_color, line_width);
      get_xlim(x0, x1);
      get_ylim(y0, y1);
      printf("scaled x0=%6.2f, y0=%6.2f, x1=%6.2f, y1=%6.2f\n",
	             xps(x0), yps(y0), xps(x1), yps(y1));
      // create_line(x0, y0, x1, y1);
    }
    if(strncmp("text ", rline, 5)==0)
    {
      sscanf(rline,"text  %d,%d %d,%d, %X, %d %s\n",
                    &x0, &y0, &x1, &y1,
                    &line_color, &siz, &msg);
      p=msg;
      while(*p!=0) // loop until ending null
      {
	  if(*p=='\\') *p=' '; // convert backslash to blank
        p++;
      }
      printf("text  x0=%d, y0=%d, x1=%d, y1=%d, col=%X, siz=%d, msg=%s\n",
              x0, y0, x1, y1, line_color, siz, msg);
      x1=(int)(x0+0.8*(p-msg)*(float)siz/72.0f); // length=4/5 fontsize/72 num char
      y1=(int)(y0+(float)siz/72.0f);
      get_xlim(x0, x1);
      get_ylim(y0, y1);
      //create_text(x0, y0, x1, y1, msg, siz);
    }
    if(strncmp("symbol ", rline, 7)==0)
    {
      sscanf(rline, "symbol  %d,%d, %d,%d, %d,%d, %d,%d, %X,%d \n",
		     &x0, &y0, &x1, &y1, &x2, &y2, &side, &which,
                     &line_color, &line_width);
      printf("symbol  x0=%d, y0=%d, x1=%d, y1=%d, x2=%d, y2=%d, side=%d, which=%d, col=%X, lwid=%d \n",
	     x0, y0, x1, y1, x2, y2, side, which, line_color, line_width);
      //create_symbol(x0, y0, x1, y1, x2, y2, side, which);
      switch(which)
      {
	case 34: printf("vmux  x0=%d, y0=%d, x1=%d, y1=%d, side=%d, col=%d, lwid=%d\n",
	                x0, y0, x1, y1, side, line_color, line_width);
                 get_xlim(imin(x0,x0)-side, imax(x0,x1)+side);
                 get_ylim(imin(y0,y1)-side, imax(y0,y1)+side);
	         break;
	case 35: printf("hmux  x0=%d, y0=%d, x1=%d, y1=%d, side=%d, col=%d, lwid=%d\n",
	                x0, y0, x1, y1, side, line_color, line_width);
	         break;
	case 36: printf("alu   x0=%d, y0=%d, x1=%d, y1=%d, side=%d, col=%d, lwid=%d\n",
	                x0, y0, x1, y1, side, line_color, line_width);
	         break;
	case 37: printf("and   x0=%d, y0=%d, x1=%d, y1=%d, side=%d, col=%d, lwid=%d\n",
	                x0, y0, x1, y1, side, line_color, line_width);
                 get_xlim(x0, x0+iabs(y0-y1));
                 get_ylim(y0, y1);
	         break;
	case 38: printf("or    x0=%d, y0=%d, x1=%d, y1=%d, side=%d, col=%d, lwid=%d\n",
	                x0, y0, x1, y1, side, line_color, line_width);
                 get_xlim(x0, x0+iabs(y0-y1));
                 get_ylim(y0, y1);
	         break;
	case 39: printf("xor  x0=%d, y0=%d, x1=%d, y1=%d, side=%d, col=%d, lwid=%d\n",
	                x0, y0, x1, y1, side, line_color, line_width);
                 get_xlim(x0, x0+iabs(y0-y1));
                 get_ylim(y0, y1);
	         break;
	case 40: printf("not  x0=%d, y0=%d, x1=%d, y1=%d, side=%d, col=%d, lwid=%d\n",
	                x0, y0, x1, y1, side, line_color, line_width);
                 get_xlim(x0, x1);
                 get_ylim(y0, y1);
	         break;
	case 41: printf("comp x0=%d, y0=%d, x1=%d, y1=%d, side=%d, col=%d, lwid=%d\n",
	                x0, y0, x1, y1, side, line_color, line_width);
                 get_xlim(x0, x0+side);
                 get_ylim(y0, y0);
	         break;
	case 42: printf("arrow x0=%d, y0=%d, x1=%d, y1=%d, side=%d, col=%d, lwid=%d\n",
	                x0, y0, x1, y1, side, line_color, line_width);
                 get_xlim(x0, x0);
                 get_ylim(y0, y0);
	         break;
	case 43: printf("arc x0=%d, y0=%d, x1=%d, y1=%d, x2=%d, y2=%d, side=%d, col=%d, lwid=%d\n",
	                x0, y0, x1, y1, x2, y2, side, line_color, line_width);
                 get_xlim(x0, x1);
                 get_ylim(y0, y1);
                 get_xlim(x0, x2);
                 get_ylim(y0, y2);
	         break;
	case 44: printf("dot  x0=%d, y0=%d, col=%d, lwid=%d\n",
	                x0, y0, line_color, line_width);
                 get_xlim(x0, x0);
                 get_ylim(y0, y0);
	         break;
      }
    }
    if(strncmp("circle ", rline, 7)==0)
    {
      sscanf(rline, "circle %d,%d %d, %X,%X,%d,%d \n",
                     &x0, &y0, &radius, &line_color,
                     &fill_color, &line_width, &filled);
      printf("circle x0=%d, y0=%d, radius=%d, col=%X, fcol=%X, lwid=%d, filled=%d \n",
              x0, y0, radius, line_color, fill_color, line_width, filled);
      get_xlim(x0-radius, x0+radius);
      get_ylim(y0-radius, y0+radius);
      //create_circle(x0, y0, radius);
    }
    if(strncmp("rectangle ", rline, 10)==0)
    {
      sscanf(rline, "rectangle %d,%d %d,%d, %X,%X,%d,%d \n",
                     &x0, &y0, &width, &height, &line_color,
                     &fill_color, &line_width, &filled);
      printf("rectangle x0=%d, y0=%d, width=%d, height=%d, col=%X, fcol=%X, width=%d, filled=%d \n",
             x0, y0, width, height, line_color, fill_color, line_width, filled);
      get_xlim(x0, x0+width);
      get_ylim(y0, y0+height);
      //create_rectangle(x0, y0, width, height);
    }
    if(strncmp("rectanglec ", rline, 11)==0)
    {
      sscanf(rline, "rectanglec %d,%d %d,%d, %X,%X,%d,%d \n",
                     &x0, &y0, &width, &height, &line_color,
                     &fill_color, &line_width, &filled);
      printf("rectanglec x0=%d, y0=%d, width=%d, height=%d, col=%X, fcol=%X, lwid=%d, filled=%d \n",
              x0, y0, width, height, line_color, fill_color, line_width, filled);
      get_xlim(x0-width/2, x0+width/2);
      get_ylim(y0-height/2, y1+height/2);
      //create_rectanglec(x0, y0, width, height);
    }
    if(strncmp("ellipse ", rline, 8)==0)
    {
      sscanf(rline, "ellipse %d,%d %d,%d, %X,%X,%d,%d \n",
                     &x0, &y0, &width, &height, &line_color,
                     &fill_color, &line_width, &filled);
      printf("ellipse x0=%d, y0=%d, width=%d, height=%d, col=%X, fcol=%X, lwid=%d, filled=%d \n",
              x0, y0, width, height, line_color, fill_color, line_width, filled);
      get_xlim(x0, x0+width);
      get_ylim(y0, y1+height);
    }
    if(strncmp("frame ", rline, 6)==0)
    {
      sscanf(rline, "frame %d %d %d %d %d \n", &frame_xmin, &frame_ymin,
	                                       &frame_xmax, &frame_ymax, &frame_auto);
      printf("frame xmin=%d, ymin=%d, xmax=%d, ymax=%d, auto=%d\n",
	     frame_xmin, frame_ymin, frame_xmax, frame_ymax, frame_auto); 
      // ignore, auto framing
    }
    if(strncmp("grid ", rline, 5)==0)
    {
      sscanf(rline, "grid %d %d %d \n", &grid_snap_on, &grid_spacing, &grid_displayed);
      // ignore
    }
  }

  fclose(draw_file);
  draw_file = fopen(draw_file_name, "r"); // just wanted to rewind 

  xsca=540.0/(xmaxf-xminf);  
  ysca=720.0/(ymaxf-yminf); // can not use both, changes aspect ratio
  if(xsca>1.0) xsca=1.0;    // only scale smaller
  if(ysca>1.0) ysca=1.0;
  if(xsca<ysca) ysca=xsca;
  if(ysca<xsca) xsca=ysca; // now same aspect ratio
  xoff=36.0-xsca*xminf;
  yoff=36.0-ysca*yminf;
  for(i=0; i<5; i++) ps_line[i]=ps_line[i]*xsca;
  printf("\n\nScale Information\n");
  printf("xminf=%6.2f, yminf=%6.2f, xmaxf=%6.2f, ymaxf=%6.2f \n",
	 xminf, yminf, xmaxf, ymaxf);
  printf("xcsa=%6.2f, ysca=%6.2f, xoff=%6.2f, yoff=%6.2f \n",
	 xsca, ysca, xoff, yoff);
  printf("check 36=%6.2f, 36=%6.2f, 576<=%6.2f; 756<=%6.2f \n\n",
         xps(xminf), yps(yminf), xps(xmaxf), yps(ymaxf));

  // reead in the .draw file
  printf("draw to PostScript pass2\n");
  fgets(rline, 999, draw_file);
  // printf("drawps read:%s", rline);
  if(strncmp("start of save, display ", rline, 22)!=0)
  {
    printf("not a .draw  save file\n");
    return 1;
  }
  while(!feof(draw_file))
  {
    fgets(rline, 999, draw_file);
    // printf("drawps read:%s", rline);
    if(strncmp("start of save, paste ", rline, 20)==0) break;
    if(strncmp("line ", rline, 5)==0)
    {
      sscanf(rline,"line  %d,%d %d,%d, %X,%d \n",
                    &x0, &y0, &x1, &y1,
                    &line_color, &line_width);
      fprintf(ps_file," %6.2f setlinewidth\n", ps_line[line_width]);
      fprintf(ps_file,"newpath\n");
      fprintf(ps_file,"%6.2f %6.2f moveto\n", xps(x0), yps(y0));
      fprintf(ps_file,"%6.2f %6.2f lineto\n", xps(x1), yps(y1));
      fprintf(ps_file,"stroke\n");
    }
    if(strncmp("text ", rline, 5)==0)
    {
      sscanf(rline,"text  %d,%d %d,%d, %X, %d %s\n",
                    &x0, &y0, &x1, &y1,
                    &line_color, &siz, &msg);
      p=msg;
      while(*p!=0) // loop until ending null
      {
	  if(*p=='\\') *p=' '; // convert backslash to blank
        p++;
      }
      printf("text scaled x0=%6.2f, y0=%6.2f, x1=%6.2f, y1=%6.2f\n",
	             xps(x0), yps(y0), xps(x1), yps(y1));
      fprintf(ps_file,"newpath\n");
      fprintf(ps_file,"/Courier findfont\n");
      fprintf(ps_file,"%6.2f scalefont setfont\n", xsca*(float)siz);
      fprintf(ps_file,"%6.2f %6.2f moveto (%s) show\n", xps(x0), yps(y0), msg);

    }
    if(strncmp("symbol ", rline, 7)==0)
    {
      sscanf(rline, "symbol  %d,%d, %d,%d, %d,%d, %d,%d, %X,%d \n",
		     &x0, &y0, &x1, &y1, &x2, &y2, &side, &which,
                     &line_color, &line_width);
      printf("symbol  x0=%d, y0=%d, x1=%d, y1=%d, x2=%d, y2=%d, side=%d, which=%d, col=%X, lwid=%d \n",
	     x0, y0, x1, y1, x2, y2, side, which, line_color, line_width);
      //create_symbol(x0, y0, x1, y1, x2, y2, side, which);
      switch(which)
      {
	case 34: printf("vmux  x0=%d, y0=%d, x1=%d, y1=%d, side=%d, col=%d, lwid=%d\n",
	                x0, y0, x1, y1, side, line_color, line_width);
	         if(y1<y0){ t=y1; y1=y0; y0=t;} // y1 always bigger, yps(y1) smaller
                 fprintf(ps_file," %6.2f setlinewidth\n", ps_line[line_width]);
                 fprintf(ps_file,"newpath\n");
                 fprintf(ps_file,"%6.2f %6.2f moveto\n", xps(x0+side), yps(y1));
                 fprintf(ps_file,"%6.2f %6.2f lineto\n", xps(x0+side), yps(y0));
                 fprintf(ps_file,"%6.2f %6.2f %6.2f %d %d arc\n",
                                  xps(x0), yps(y0), xsca*(float)side, 0, 180);
                 fprintf(ps_file,"%6.2f %6.2f lineto\n", xps(x0-side), yps(y1));
                 fprintf(ps_file,"%6.2f %6.2f %6.2f %d %d arc\n",
                                  xps(x0), yps(y1), xsca*(float)side, 180, 360);
                 fprintf(ps_file,"stroke\n");
	         break;
	case 35: printf("hmux  x0=%d, y0=%d, x1=%d, y1=%d, side=%d, col=%d, lwid=%d\n",
	                x0, y0, x1, y1, side, line_color, line_width);
	         if(x1<x0){ t=x1; x1=x0; x0=t;} // x1 always bigger, yps flips
                 fprintf(ps_file," %6.2f setlinewidth\n", ps_line[line_width]);
                 fprintf(ps_file,"newpath\n");
                 fprintf(ps_file,"%6.2f %6.2f moveto\n", xps(x1), yps(y0-side));
                 fprintf(ps_file,"%6.2f %6.2f lineto\n", xps(x0), yps(y0-side));
                 fprintf(ps_file,"%6.2f %6.2f %6.2f %d %d arc\n",
                                  xps(x0), yps(y0), xsca*(float)side, 90, 270);
                 fprintf(ps_file,"%6.2f %6.2f lineto\n", xps(x1), yps(y1+side));
                 fprintf(ps_file,"%6.2f %6.2f %6.2f %d %d arc\n",
                                  xps(x1), yps(y0), xsca*(float)side, 270, 450);
                 fprintf(ps_file,"stroke\n");
	         break;
	case 36: printf("alu   x0=%d, y0=%d, x1=%d, y1=%d, side=%d, col=%d, lwid=%d\n",
	                x0, y0, x1, y1, side, line_color, line_width);
                 fprintf(ps_file," %6.2f setlinewidth\n", ps_line[line_width]);
                 fprintf(ps_file,"newpath\n");
                 fprintf(ps_file,"%6.2f %6.2f moveto\n", xps(x0-side), yps(y0-3*side));
                 fprintf(ps_file,"%6.2f %6.2f lineto\n", xps(x0+side), yps(y0-side));
                 fprintf(ps_file,"%6.2f %6.2f lineto\n", xps(x0+side), yps(y0+side));
                 fprintf(ps_file,"%6.2f %6.2f lineto\n", xps(x0-side), yps(y0+3*side));
                 fprintf(ps_file,"%6.2f %6.2f lineto\n", xps(x0-side), yps(y0+side));
                 fprintf(ps_file,"%6.2f %6.2f lineto\n", xps(x0),      yps(y0));
                 fprintf(ps_file,"%6.2f %6.2f lineto\n", xps(x0-side), yps(y0-side));
                 fprintf(ps_file,"%6.2f %6.2f lineto\n", xps(x0-side), yps(y0-3*side));
                 fprintf(ps_file,"stroke\n");
	         break;
	case 37: printf("and   x0=%d, y0=%d, x1=%d, y1=%d, side=%d, col=%d, lwid=%d\n",
	                x0, y0, x1, y1, side, line_color, line_width);
                 fprintf(ps_file," %6.2f setlinewidth\n", ps_line[line_width]);
                 fprintf(ps_file,"newpath\n");
		 if(y1<y0) // means yps(y1) > yps(y0)
		 {
                   fprintf(ps_file,"%6.2f %6.2f moveto\n", xps(x0+side), yps(y1));
                   fprintf(ps_file,"%6.2f %6.2f lineto\n", xps(x0),      yps(y1));
                   fprintf(ps_file,"%6.2f %6.2f lineto\n", xps(x0),      yps(y0));
                   fprintf(ps_file,"%6.2f %6.2f lineto\n", xps(x0+side), yps(y0));
                   fprintf(ps_file,"%6.2f %6.2f %6.2f %d %d arc\n",
                                    xps(x0+side), yps((y0+y1)/2),
                                    xsca*(float)(iabs(y0-y1))/2.0, 270, 450);
		 }
		 else
		 {
                   fprintf(ps_file,"%6.2f %6.2f moveto\n", xps(x0+side), yps(y0));
                   fprintf(ps_file,"%6.2f %6.2f lineto\n", xps(x0),      yps(y0));
                   fprintf(ps_file,"%6.2f %6.2f lineto\n", xps(x0),      yps(y1));
                   fprintf(ps_file,"%6.2f %6.2f lineto\n", xps(x0+side), yps(y1));
                   fprintf(ps_file,"%6.2f %6.2f %6.2f %d %d arc\n",
                                    xps(x0+side), yps((y0+y1)/2),
                                    xsca*(float)(iabs(y0-y1))/2.0, 270, 450);
		 }
                 fprintf(ps_file,"stroke\n");
	         break;
	case 38: printf("or    x0=%d, y0=%d, x1=%d, y1=%d, side=%d, col=%d, lwid=%d\n",
	                x0, y0, x1, y1, side, line_color, line_width);
                 fprintf(ps_file," %6.2f setlinewidth\n", ps_line[line_width]);
                 fprintf(ps_file,"newpath\n");
		 if(y1<y0) // means yps(y1) > yps(y0)
		 {  
                   dr=y0-y1;
                   fprintf(ps_file,"%6.2f %6.2f moveto\n", xps(x0+side), yps(y0));
                   fprintf(ps_file,"%6.2f %6.2f lineto\n", xps(x0),      yps(y0));
                   fprintf(ps_file,"%6.2f %6.2f %6.2f %6.2f %6.2f arc\n",
                                    xps(x0-2*dr), yps((y1+y0)/2),
                                    xsca*(float)(dr)*2.0, 345.52, 374.48);
                   fprintf(ps_file,"%6.2f %6.2f lineto\n", xps(x0+side), yps(y1));
                   fprintf(ps_file,"stroke\n");
                   fprintf(ps_file,"newpath\n");
                   fprintf(ps_file,"%6.2f %6.2f moveto\n", xps(x0+side), yps(y0));
                   fprintf(ps_file,"%6.2f %6.2f %6.2f %d %d arc\n",
                                    xps(x0+side), yps(y1),
                                    xsca*(float)dr, 270, 330);
                   fprintf(ps_file,"%6.2f %6.2f %6.2f %d %d arc\n",
                                    xps(x0+side), yps(y0),
                                    xsca*(float)dr, 30, 90);
		 }
		 else
		 {
                   dr=y1-y0;
                   fprintf(ps_file,"%6.2f %6.2f moveto\n", xps(x0+side), yps(y1));
                   fprintf(ps_file,"%6.2f %6.2f lineto\n", xps(x0),      yps(y1));
                   fprintf(ps_file,"%6.2f %6.2f %6.2f %6.2f %6.2f arc\n",
                                    xps(x0-2*dr), yps((y1+y0)/2),
                                    xsca*(float)(dr)*2.0, 345.52f, 374.48f);
                   fprintf(ps_file,"%6.2f %6.2f lineto\n", xps(x0+side), yps(y0));
                   fprintf(ps_file,"stroke\n");
                   fprintf(ps_file,"newpath\n");
                   fprintf(ps_file,"%6.2f %6.2f moveto\n", xps(x0+side), yps(y1));
                   fprintf(ps_file,"%6.2f %6.2f %6.2f %d %d arc\n",
                                    xps(x0+side), yps(y0),
                                    xsca*(float)dr, 270, 330);
                   fprintf(ps_file,"%6.2f %6.2f %6.2f %d %d arc\n",
                                    xps(x0+side), yps(y1),
                                    xsca*(float)dr, 30, 90);
		 }
                 fprintf(ps_file,"stroke\n");
	         break;
	case 39: printf("xor  x0=%d, y0=%d, x1=%d, y1=%d, side=%d, col=%d, lwid=%d\n",
	                x0, y0, x1, y1, side, line_color, line_width);
                 fprintf(ps_file," %6.2f setlinewidth\n", ps_line[line_width]);
                 fprintf(ps_file,"newpath\n");
		 if(y1<y0) // means yps(y1) > yps(y0)
		 {  
                   dr=y0-y1;
                   fprintf(ps_file,"%6.2f %6.2f moveto\n", xps(x0+side), yps(y0));
                   fprintf(ps_file,"%6.2f %6.2f lineto\n", xps(x0),      yps(y0));
                   fprintf(ps_file,"%6.2f %6.2f %6.2f %6.2f %6.2f arc\n",
                                    xps(x0-2*dr), yps((y1+y0)/2),
                                    xsca*(float)(dr)*2.0, 345.52f, 374.48f);
                   fprintf(ps_file,"%6.2f %6.2f lineto\n", xps(x0+side), yps(y1));
                   fprintf(ps_file,"stroke\n");
                   fprintf(ps_file,"newpath\n");
                   fprintf(ps_file,"%6.2f %6.2f moveto\n", xps(x0-side), yps(y0));
                   fprintf(ps_file,"%6.2f %6.2f %6.2f %6.2f %6.2f arc\n",
                                    xps(x0-side-2*dr), yps((y1+y0)/2),
                                    xsca*(float)(dr)*2.0, 345.52f, 374.48f);
                   fprintf(ps_file,"stroke\n");
                   fprintf(ps_file,"newpath\n");
                   fprintf(ps_file,"%6.2f %6.2f moveto\n", xps(x0+side), yps(y0));
                   fprintf(ps_file,"%6.2f %6.2f %6.2f %d %d arc\n",
                                    xps(x0+side), yps(y1),
                                    xsca*(float)dr, 270, 330);
                   fprintf(ps_file,"%6.2f %6.2f %6.2f %d %d arc\n",
                                    xps(x0+side), yps(y0),
                                    xsca*(float)dr, 30, 90);
		 }
		 else
		 {
                   dr=y1-y0;
                   fprintf(ps_file,"%6.2f %6.2f moveto\n", xps(x0+side), yps(y1));
                   fprintf(ps_file,"%6.2f %6.2f lineto\n", xps(x0),      yps(y1));
                   fprintf(ps_file,"%6.2f %6.2f %6.2f %6.2f %6.2f arc\n",
                                    xps(x0-2*dr), yps((y1+y0)/2),
                                    xsca*(float)(dr)*2.0, 345.52, 374.48);
                   fprintf(ps_file,"%6.2f %6.2f lineto\n", xps(x0+side), yps(y0));
                   fprintf(ps_file,"stroke\n");
                   fprintf(ps_file,"newpath\n");
                   fprintf(ps_file,"%6.2f %6.2f moveto\n", xps(x0-side), yps(y1));
                   fprintf(ps_file,"%6.2f %6.2f %6.2f %6.2f %6.2f arc\n",
                                    xps(x0-side-2*dr), yps((y1+y0)/2),
                                    xsca*(float)(dr)*2.0, 345.52, 374.48);
                   fprintf(ps_file,"stroke\n");
                   fprintf(ps_file,"newpath\n");
                   fprintf(ps_file,"%6.2f %6.2f moveto\n", xps(x0+side), yps(y1));
                   fprintf(ps_file,"%6.2f %6.2f %6.2f %d %d arc\n",
                                    xps(x0+side), yps(y0),
                                    xsca*(float)dr, 270, 330);
                   fprintf(ps_file,"%6.2f %6.2f %6.2f %d %d arc\n",
                                    xps(x0+side), yps(y1),
                                    xsca*(float)dr, 30, 90);
		 }
                 fprintf(ps_file,"stroke\n");
	         break;
	case 40: printf("not  x0=%d, y0=%d, x1=%d, y1=%d, side=%d, col=%d, lwid=%d\n",
	                x0, y0, x1, y1, side, line_color, line_width);
                 fprintf(ps_file," %6.2f setlinewidth\n", ps_line[line_width]);
                 fprintf(ps_file,"newpath\n");
                 fprintf(ps_file,"%6.2f %6.2f moveto\n", xps(x0), yps(y0));
                 fprintf(ps_file,"%6.2f %6.2f lineto\n", xps(x0), yps(y1));
                 fprintf(ps_file,"%6.2f %6.2f lineto\n", xps(x1), yps((y0+y1)/2));
                 fprintf(ps_file,"%6.2f %6.2f lineto\n", xps(x0), yps(y0));
                 fprintf(ps_file,"stroke\n");
	         break;
	case 41: printf("comp x0=%d, y0=%d, x1=%d, y1=%d, side=%d, col=%d, lwid=%d\n",
	                x0, y0, x1, y1, side, line_color, line_width);
                 fprintf(ps_file," %6.2f setlinewidth\n", ps_line[line_width]);
                 fprintf(ps_file,"newpath\n");
                 fprintf(ps_file,"%6.2f %6.2f moveto\n", xps(x0+side), yps(y0));
                 fprintf(ps_file,"%6.2f %6.2f %6.2f %d %d arc\n",
                         xps(x0+side/2), yps(y0), xsca*(float)(side/2), 0, 360);
                 fprintf(ps_file,"stroke\n");
	         break;
	case 42: printf("arrow x0=%d, y0=%d, x1=%d, y1=%d, side=%d, col=%d, lwid=%d\n",
	                x0, y0, x1, y1, side, line_color, line_width);
                 fprintf(ps_file," %6.2f setlinewidth\n", ps_line[line_width]);
                 fprintf(ps_file,"newpath\n");
                 fprintf(ps_file,"%6.2f %6.2f moveto\n", xps(x0), yps(y0));
		 dx=x0-x1;
		 dy=y0-y1;
		 usex=1;
		 if(iabs(dx)<=iabs(dy)) usex=0;
                 if(usex) // horizontal
                 if(dx>0) // +x pointing
                 {
                   fprintf(ps_file,"%6.2f %6.2f lineto\n", xps(x0-(81*side)/100),
                                                           yps(y0+side/4));
                   fprintf(ps_file,"%6.2f %6.2f lineto\n", xps(x0-side/4), yps(y0));
                   fprintf(ps_file,"%6.2f %6.2f lineto\n", xps(x0-(81*side)/100),
                                                           yps(y0-side/4));
                   fprintf(ps_file,"%6.2f %6.2f lineto\n", xps(x0), yps(y0));
                 }
		 else // -x pointing
		 {
                   fprintf(ps_file,"%6.2f %6.2f lineto\n", xps(x0+(81*side)/100),
                                                           yps(y0+side/4));
                   fprintf(ps_file,"%6.2f %6.2f lineto\n", xps(x0+side/4), yps(y0));
                   fprintf(ps_file,"%6.2f %6.2f lineto\n", xps(x0+(81*side)/100),
                                                           yps(y0-side/4));
                   fprintf(ps_file,"%6.2f %6.2f lineto\n", xps(x0), yps(y0));
		 }
		 else // vertical
		 if(dy>0) // +y pointing
		 {
                   fprintf(ps_file,"%6.2f %6.2f lineto\n", xps(x0+side/4),
                                                           yps(y0-(81*side)/100));
                   fprintf(ps_file,"%6.2f %6.2f lineto\n", xps(x0), yps(y0-side/4));
                   fprintf(ps_file,"%6.2f %6.2f lineto\n", xps(x0-side/4),
                                                           yps(y0-(81*side)/100));
                   fprintf(ps_file,"%6.2f %6.2f lineto\n", xps(x0), yps(y0));
		 }
		 else // -y pointing
		 {
                   fprintf(ps_file,"%6.2f %6.2f lineto\n", xps(x0+side/4),
                                                           yps(y0+(81*side)/100));
                   fprintf(ps_file,"%6.2f %6.2f lineto\n", xps(x0), yps(y0+side/4));
                   fprintf(ps_file,"%6.2f %6.2f lineto\n", xps(x0-side/4),
                                                           yps(y0+(81*side)/100));
                   fprintf(ps_file,"%6.2f %6.2f lineto\n", xps(x0), yps(y0));
		 }
                 fprintf(ps_file,"stroke\n");
	         break;
	case 43: printf("arc x0=%d, y0=%d, x1=%d, y1=%d, x2=%d, y2=%d, side=%d, col=%d, lwid=%d\n",
	                x0, y0, x1, y1, x2, y2, side, line_color, line_width);
	         break;
	case 44: printf("dot  x0=%d, y0=%d, col=%d, lwid=%d\n",
	                x0, y0, line_color, line_width);
                 ps_radius=(ps_line[line_width]+4.0f)/2.0f;
                 fprintf(ps_file,"newpath\n");
                 fprintf(ps_file,"%6.2f %6.2f moveto\n", xps(x0)+ps_radius, yps(y0));
                 fprintf(ps_file,"%6.2f %6.2f %6.2f %d %d arc\n",
                         xps(x0), yps(y0), ps_radius, 0, 360);
                 fprintf(ps_file,"fill\n");
	         break;
      }
    }
    if(strncmp("circle ", rline, 7)==0)
    {
      sscanf(rline, "circle %d,%d %d, %X,%X,%d,%d \n",
                     &x0, &y0, &radius, &line_color,
                     &fill_color, &line_width, &filled);
      fprintf(ps_file," %6.2f setlinewidth\n", ps_line[line_width]);
      if(filled!=0)
      {
        fprintf(ps_file,"newpath\n");
        fprintf(ps_file,"%6.2f %6.2f moveto\n", xps(x0+radius), yps(y0));
        fprintf(ps_file,"%6.2f %6.2f %6.2f %d %d arc\n",
                        xps(x0), yps(y0), xsca*(float)radius, 0, 360);
        fprintf(ps_file," %6.2f setgray fill\n", shade);
        fprintf(ps_file," 0.0 setgray\n");
      }
      fprintf(ps_file,"newpath\n");
      fprintf(ps_file,"%6.2f %6.2f moveto\n", xps(x0+radius), yps(y0));
      fprintf(ps_file,"%6.2f %6.2f %6.2f %d %d arc\n",
                      xps(x0), yps(y0), xsca*(float)radius, 0, 360);
      fprintf(ps_file,"stroke\n");
    }
    if(strncmp("rectangle ", rline, 10)==0)
    {
      sscanf(rline, "rectangle %d,%d %d,%d, %X,%X,%d,%d \n",
                     &x0, &y0, &width, &height, &line_color,
                     &fill_color, &line_width, &filled);
      fprintf(ps_file," %6.2f setlinewidth\n", ps_line[line_width]);
      if(filled!=0)
      {
        fprintf(ps_file,"newpath\n");
        fprintf(ps_file,"%6.2f %6.2f moveto\n", xps(x0),       yps(y0));
        fprintf(ps_file,"%6.2f %6.2f lineto\n", xps(x0),       yps(y0+height));
        fprintf(ps_file,"%6.2f %6.2f lineto\n", xps(x0+width), yps(y0+height));
        fprintf(ps_file,"%6.2f %6.2f lineto\n", xps(x0+width), yps(y0));
        fprintf(ps_file,"%6.2f %6.2f lineto\n", xps(x0),       yps(y0));
        fprintf(ps_file," %6.2f setgray fill\n", shade);
        fprintf(ps_file," 0.0 setgray\n");
      }
      fprintf(ps_file,"newpath\n");
      fprintf(ps_file,"%6.2f %6.2f moveto\n", xps(x0),       yps(y0));
      fprintf(ps_file,"%6.2f %6.2f lineto\n", xps(x0),       yps(y0+height));
      fprintf(ps_file,"%6.2f %6.2f lineto\n", xps(x0+width), yps(y0+height));
      fprintf(ps_file,"%6.2f %6.2f lineto\n", xps(x0+width), yps(y0));
      fprintf(ps_file,"%6.2f %6.2f lineto\n", xps(x0),       yps(y0));
      fprintf(ps_file,"stroke\n");
    }
    if(strncmp("rectanglec ", rline, 11)==0)
    {
      sscanf(rline, "rectanglec %d,%d %d,%d, %X,%X,%d,%d \n",
                     &x0, &y0, &width, &height, &line_color,
                     &fill_color, &line_width, &filled);
      fprintf(ps_file," %6.2f setlinewidth\n", ps_line[line_width]);
      if(filled!=0)
      {
        fprintf(ps_file,"newpath\n");
        fprintf(ps_file,"%6.2f %6.2f moveto\n", xps(x0-width/2), yps(y0-height/2));
        fprintf(ps_file,"%6.2f %6.2f lineto\n", xps(x0-width/2), yps(y0+height/2));
        fprintf(ps_file,"%6.2f %6.2f lineto\n", xps(x0+width/2), yps(y0+height/2));
        fprintf(ps_file,"%6.2f %6.2f lineto\n", xps(x0+width/2), yps(y0-height/2));
        fprintf(ps_file,"%6.2f %6.2f lineto\n", xps(x0-width/2), yps(y0-height/2));
        fprintf(ps_file," %6.2f setgray fill\n", shade);
        fprintf(ps_file," 0.0 setgray\n");
      }
      fprintf(ps_file,"newpath\n");
      fprintf(ps_file,"%6.2f %6.2f moveto\n", xps(x0-width/2), yps(y0-height/2));
      fprintf(ps_file,"%6.2f %6.2f lineto\n", xps(x0-width/2), yps(y0+height/2));
      fprintf(ps_file,"%6.2f %6.2f lineto\n", xps(x0+width/2), yps(y0+height/2));
      fprintf(ps_file,"%6.2f %6.2f lineto\n", xps(x0+width/2), yps(y0-height/2));
      fprintf(ps_file,"%6.2f %6.2f lineto\n", xps(x0-width/2), yps(y0-height/2));
      fprintf(ps_file,"stroke\n");
    }
    if(strncmp("ellipse ", rline, 8)==0)
    {
      sscanf(rline, "ellipse %d,%d %d,%d, %X,%X,%d,%d \n",
                     &x0, &y0, &width, &height, &line_color,
                     &fill_color, &line_width, &filled);
      fprintf(ps_file," %6.2f setlinewidth\n", ps_line[line_width]);
      if(filled!=0)
      {
        fprintf(ps_file,"newpath\n");
        fprintf(ps_file,"%6.2f %6.2f moveto\n", xps(x0), yps(y0+height/2));
        fprintf(ps_file,"%6.2f %6.2f %6.2f %6.2f %6.2f %6.2f curveto\n",
                xps(x0),       yps(y0+height),
                xps(x0+width), yps(y0+height),
                xps(x0+width), yps(y0+height/2));
        fprintf(ps_file,"%6.2f %6.2f %6.2f %6.2f %6.2f %6.2f curveto\n",
                xps(x0+width), yps(y0),
                xps(x0),       yps(y0),
                xps(x0),       yps(y0+height/2));
        fprintf(ps_file," %6.2f setgray fill\n", shade);
        fprintf(ps_file," 0.0 setgray\n");
      }
      fprintf(ps_file,"newpath\n");
        fprintf(ps_file,"%6.2f %6.2f moveto\n", xps(x0), yps(y0+height/2));
        fprintf(ps_file,"%6.2f %6.2f %6.2f %6.2f %6.2f %6.2f curveto\n",
                xps(x0),       yps(y0+height),
                xps(x0+width), yps(y0+height),
                xps(x0+width), yps(y0+height/2));
        fprintf(ps_file,"%6.2f %6.2f %6.2f %6.2f %6.2f %6.2f curveto\n",
                xps(x0+width), yps(y0),
                xps(x0),       yps(y0),
                xps(x0),       yps(y0+height/2));
      fprintf(ps_file,"stroke\n");
    }
    if(strncmp("frame ", rline, 6)==0)
    {
      sscanf(rline, "frame %d %d %d %d %d \n", &frame_xmin, &frame_ymin,
	                                       &frame_xmax, &frame_ymax, &frame_auto);
      // ignore
    }
    if(strncmp("grid ", rline, 5)==0)
    {
      sscanf(rline, "grid %d %d %d \n", &grid_snap_on, &grid_spacing, &grid_displayed);
      // ignore
    }
  }
  fclose(draw_file);

  fprintf(ps_file,"showpage\n");
  fflush(ps_file);
  fclose(ps_file);
  printf("drawps finished.\n");
}

float xps(float x) // offset and scale x to ps page 36 to 576
{
  return xsca*x + xoff;
} 

float yps(float y) // offset and scale y to ps page 36 to 756
{
  return 792.0f - (ysca*y + yoff); // invert X windows "Y"
}

void  get_xlim(int x0, int x1)
{
  if(x0<xminf) xminf=(float)x0;
  if(x1<xminf) xminf=(float)x1;
  if(x0>xmaxf) xmaxf=(float)x0;
  if(x1>xmaxf) xmaxf=(float)x1;
}

void  get_ylim(int y0, int y1)
{
  if(y0<yminf) yminf=(float)y0;
  if(y1<yminf) yminf=(float)y1;
  if(y0>ymaxf) ymaxf=(float)y0;
  if(y1>ymaxf) ymaxf=(float)y1;
}


// gray shaded triangle, shade=0.1 dark, shade=0.99 light, else white
//void draw_post3(float x1, float y1, float x2, float y2,
//                float x3, float y3, float shade)
//{
//  if (shade==0.0) return;
//  fprintf(ps_file,"newpath\n");
//  fprintf(ps_file," %6.2f %6.2f moveto\n", x1, y1);
//  fprintf(ps_file," %6.2f %6.2f lineto\n", x2, y2);
//  fprintf(ps_file," %6.2f %6.2f lineto\n", x3, y3);
//  fprintf(ps_file," %6.2f %6.2f lineto\n", x1, y1);
//  fprintf(ps_file,"closepath\n");
//  fprintf(ps_file," %6.2f setgray fill\n", shade);
//  fprintf(ps_file," 0.0 setgray\n");
//} /* end draw_post3 */


