# include "Ximage.h"

# define DrawLine(X1,Y1,X2,Y2) (fprintf (f, " %6.2f %6.2f %6.2f %6.2f L\n", X1, graphic->dy - Y1, X2, graphic->dy - Y2))
# define DrawCircle(X1,Y1,R) (fprintf (f, " %6.2f %6.2f %6.2f C\n", (X1), (graphic->dy - Y1), (R)))
# define DrawRectangle(X,Y,dX,dY) (fprintf (f, " %6.2f %6.2f %6.2f %6.2f B\n", (dX), (dY), (X-0.5*dX), (graphic->dy-Y-0.5*dY)))
# define FillRectangle(X,Y,dX,dY) (fprintf (f, " %6.2f %6.2f %6.2f %6.2f F\n", (dX), (dY), (X-0.5*dX), (graphic->dy-Y-0.5*dY)))
# define FillTriangle(X1,Y1,X2,Y2, X3, Y3) (fprintf (f, " %6.2f %6.2f %6.2f %6.2f %6.2f %6.2f TF\n", (X1), (graphic->dy-Y1), (X2), (graphic->dy-Y2), (X3), (graphic->dy-Y3)))
# define CONNECT 0
# define HISTOGRAM 1
# define POINTS 2

static Graphic *graphic;

int PSObjects (KapaGraphWidget *graph, FILE *f) {
  
  int i;
  double lweight;
  static char dash[] = "5";
  static char dot[] = "3";
  
  graphic = GetGraphic();

  for (i = 0; i < graph[0].Nobjects; i++) {
    switch (graph[0].objects[i].ltype) {
    case 0:
      break;
    case 1:
      fprintf (f, "[%s] 0 setdash\n", dash);
      break;
    case 2:
      fprintf (f, "[%s] 0 setdash\n", dot);
      break;
    default:
      break;
    }
    
    lweight = MAX (0, MIN (10, graph[0].objects[i].lweight));
    fprintf (f, "%.1f setlinewidth\n", lweight);
    fprintf (f, "%s setrgbcolor\n", KapaColorRGBString(graph[0].objects[i].color));

    switch (graph[0].objects[i].style) {
    case CONNECT: 
      PSConnect (graph, &graph[0].objects[i], f);
      break;
    case HISTOGRAM:
      PSHistogram (graph, &graph[0].objects[i], f);
      break;
    case POINTS:
      PSPoints (graph, &graph[0].objects[i], f);
      break;
    }

    if (graph[0].objects[i].etype & 0x01) {
      PSYErrors (graph, &graph[0].objects[i], f);
    }
    if (graph[0].objects[i].etype & 0x02) {
      PSXErrors (graph, &graph[0].objects[i], f);
    }
    fprintf (f, "[] 0 setdash\n");
    fprintf (f, "0.00 0.00 0.00 setrgbcolor\n");
  }
  return (TRUE);
}

/*******/
void PSConnect (KapaGraphWidget *graph, Gobjects *object, FILE *f) {
  
  int i;
  float *x, *y;
  double mxi, mxj, myi, myj, bxi, bxj, byi, byj, bx, by;
  double sx0, sy0, sx1, sy1;
  double X0, X1, Y0, Y1;

  mxi = graph[0].axis[0].dfx / (object[0].x1 - object[0].x0);
  mxj = graph[0].axis[1].dfx / (object[0].y1 - object[0].y0);
  myi = graph[0].axis[0].dfy / (object[0].x1 - object[0].x0);
  myj = graph[0].axis[1].dfy / (object[0].y1 - object[0].y0); 
  
  bxi  =  graph[0].axis[0].fx - object[0].x0*graph[0].axis[0].dfx/(object[0].x1 - object[0].x0);
  bxj  =  -object[0].y0*graph[0].axis[1].dfx/(object[0].y1 - object[0].y0);
  byi  =  -object[0].x0*graph[0].axis[0].dfy/(object[0].x1 - object[0].x0);
  byj  =  graph[0].axis[1].fy - object[0].y0*graph[0].axis[1].dfy/(object[0].y1 - object[0].y0); 
  
  bx = bxi + bxj;
  by = byi + byj;
  
  X0 = graph[0].axis[0].fx;
  X1 = graph[0].axis[0].fx + graph[0].axis[0].dfx;
  Y0 = graph[0].axis[1].fy;
  Y1 = graph[0].axis[1].fy + graph[0].axis[1].dfy;

  x = object[0].x; y = object[0].y;
  for (i = 0; (i < object[0].Npts) && !(finite(x[i]) && finite(y[i])); i++);
  if (i >= object[0].Npts) return;
  sx0 = x[i]*mxi + y[i]*mxj + bx;
  sy0 = x[i]*myi + y[i]*myj + by;
  
  for (i++; i < object[0].Npts; i++) {
    if (!(finite(x[i]) && finite(y[i]))) continue;
    sx1 = x[i]*mxi + y[i]*mxj + bx;
    sy1 = x[i]*myi + y[i]*myj + by;
    ClipLinePS (sx0, sy0, sx1, sy1, X0, Y0, X1, Y1, f);
    /* DrawLine (sx0, sy0, sx1, sy1); */
    sx0 = sx1; sy0 = sy1;
  }
}

void ClipLinePS (double x0, double y0, double x1, double y1, double X0, double Y1, double X1, double Y0, FILE *f) {

  /* skip line segement if both points are beyond box */
  if ((x0 <= X0) && (x1 <= X0)) return;
  if ((x0 >= X1) && (x1 >= X1)) return;
  if ((y0 <= Y0) && (y1 <= Y0)) return;
  if ((y0 >= Y1) && (y1 >= Y1)) return;

  /* replace x0,y0 if outside box */
  if ((x0 < X0) && (x1 >= X0)) {
    y0 = y0 + (X0 - x0)*(y1 - y0)/(x1 - x0);
    x0 = X0;
  }
  if ((x0 > X1) && (x1 <= X1)) {
    y0 = y0 + (X1 - x0)*(y1 - y0)/(x1 - x0);
    x0 = X1;
  }
  if ((y0 < Y0) && (y1 >= Y0)) {
    x0 = x0 + (Y0 - y0)*(x1 - x0)/(y1 - y0);
    y0 = Y0;
  }
  if ((y0 > Y1) && (y1 <= Y1)) {
    x0 = x0 + (Y1 - y0)*(x1 - x0)/(y1 - y0);
    y0 = Y1;
  }

  /* skip line segement if both points are beyond box */
  if ((x0 <= X0) && (x1 <= X0)) return;
  if ((x0 >= X1) && (x1 >= X1)) return;
  if ((y0 <= Y0) && (y1 <= Y0)) return;
  if ((y0 >= Y1) && (y1 >= Y1)) return;

  /* replace x1,y1 if outside box */
  if ((x1 < X0) && (x0 >= X0)) {
    y1 = y0 + (X0 - x0)*(y1 - y0)/(x1 - x0);
    x1 = X0;
  }
  if ((x1 > X1) && (x0 <= X1)) {
    y1 = y0 + (X1 - x0)*(y1 - y0)/(x1 - x0);
    x1 = X1;
  }
  if ((y1 < Y0) && (y0 >= Y0)) {
    x1 = x0 + (Y0 - y0)*(x1 - x0)/(y1 - y0);
    y1 = Y0;
  }
  if ((y1 > Y1) && (y0 <= Y1)) {
    x1 = x0 + (Y1 - y0)*(x1 - x0)/(y1 - y0);
    y1 = Y1;
  }
  DrawLine (x0, y0, x1, y1);
}

/*******/
void PSHistogram (KapaGraphWidget *graph, Gobjects *object, FILE *f) {

  int i;
  float *x, *y;
  double mxi, mxj, myi, myj, bxi, bxj, byi, byj, bx, by;
  double sx0, sy0, sx1, sy1, sxa;
  double X0, X1, Y0, Y1;

  mxi = graph[0].axis[0].dfx / (object[0].x1 - object[0].x0);
  mxj = graph[0].axis[1].dfx / (object[0].y1 - object[0].y0);
  myi = graph[0].axis[0].dfy / (object[0].x1 - object[0].x0);
  myj = graph[0].axis[1].dfy / (object[0].y1 - object[0].y0); 
  
  bxi  =  graph[0].axis[0].fx - object[0].x0*graph[0].axis[0].dfx/(object[0].x1 - object[0].x0);
  bxj  =  -object[0].y0*graph[0].axis[1].dfx/(object[0].y1 - object[0].y0);
  byi  =  -object[0].x0*graph[0].axis[0].dfy/(object[0].x1 - object[0].x0);
  byj  =  graph[0].axis[1].fy - object[0].y0*graph[0].axis[1].dfy/(object[0].y1 - object[0].y0); 
  
  bx = bxi + bxj;
  by = byi + byj;
  
  X0 = graph[0].axis[0].fx;
  X1 = graph[0].axis[0].fx + graph[0].axis[0].dfx;
  Y0 = graph[0].axis[1].fy;
  Y1 = graph[0].axis[1].fy + graph[0].axis[1].dfy;

  /* find the first valid datapoint */
  x = object[0].x; y = object[0].y;
  for (i = 0; (i < object[0].Npts) && !(finite(x[i]) && finite(y[i])); i++);
  if (i >= object[0].Npts) return;
  sx0 = x[i]*mxi + y[i]*mxj + bx;
  sy0 = x[i]*myi + y[i]*myj + by;
  sx0 = MIN (MAX (sx0, X0), X1);
  sy0 = MAX (MIN (sy0, Y0), Y1);
  
  /* continue with rest of points */
  for (i++; i < object[0].Npts; i++) {
    if (!(finite(x[i]) && finite(y[i]))) continue;
    sx1 = x[i]*mxi + y[i]*mxj + bx;
    sy1 = x[i]*myi + y[i]*myj + by;
    sx1 = MIN (MAX (sx1, X0), X1);
    sy1 = MAX (MIN (sy1, Y0), Y1);
    sxa = 0.5*(sx0 + sx1);
    DrawLine (sx0, sy0, sxa, sy0);
    DrawLine (sxa, sy0, sxa, sy1);
    DrawLine (sxa, sy1, sx1, sy1);
    sx0 = sx1; sy0 = sy1;
  }
}

/*******/
void PSPoints (KapaGraphWidget *graph, Gobjects *object, FILE *f) {
 
  int i;
  float *x, *y, *z;
  double mxi, mxj, myi, myj, bxi, bxj, byi, byj, bx, by;
  double sx, sy, d, sx1, sy1, sx2, sy2;

  mxi = graph[0].axis[0].dfx / (object[0].x1 - object[0].x0);
  mxj = graph[0].axis[1].dfx / (object[0].y1 - object[0].y0);
  myi = graph[0].axis[0].dfy / (object[0].x1 - object[0].x0);
  myj = graph[0].axis[1].dfy / (object[0].y1 - object[0].y0);  
 
  bxi  =  graph[0].axis[0].fx - object[0].x0*graph[0].axis[0].dfx/(object[0].x1 - object[0].x0);
  bxj  =  -object[0].y0*graph[0].axis[1].dfx/(object[0].y1 - object[0].y0);
  byi  =  -object[0].x0*graph[0].axis[0].dfy/(object[0].x1 - object[0].x0);
  byj  =  graph[0].axis[1].fy - object[0].y0*graph[0].axis[1].dfy/(object[0].y1 - object[0].y0);  

  bx = bxi + bxj;
  by = byi + byj;
  
  /* below here, code is identical with DrawObjects */
  /**** points are scaled by object.z ***/
  if (object[0].size < 0) {
    d = 0.5 * (graphic->dx + graphic->dy) * 0.01;
    x = object[0].x; y = object[0].y; z = object[0].z;
    if (object[0].ptype == 0) {	/* filled box */
      for (i = 0; i < object[0].Npts; i++) {
	if (!(finite(x[i]) && finite(y[i]))) continue;
	sx = x[i]*mxi + y[i]*mxj + bx;
	sy = x[i]*myi + y[i]*myj + by;
	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
	  {
	    FillRectangle (sx, sy, 2*d*z[i], 2*d*z[i]);
	  }
      }
    }
    if (object[0].ptype == 1) {	/* open box */
      for (i = 0; i < object[0].Npts; i++) {
	if (!(finite(x[i]) && finite(y[i]))) continue;
	sx = x[i]*mxi + y[i]*mxj + bx;
	sy = x[i]*myi + y[i]*myj + by;
	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
	  {
	    DrawRectangle (sx, sy, 2*d*z[i], 2*d*z[i]);
	  }
      }
    }
    if (object[0].ptype == 2) { /* cross */
      for (i = 0; i < object[0].Npts; i++) {
	if (!(finite(x[i]) && finite(y[i]))) continue;
	sx = x[i]*mxi + y[i]*mxj + bx;
	sy = x[i]*myi + y[i]*myj + by;
	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
	  {
	    DrawLine (sx - d*z[i], sy, sx + d*z[i], sy);
	    DrawLine (sx, sy - d*z[i], sx, sy + d*z[i]);
	  }
      }
    }
    if (object[0].ptype == 3) {	/* x */
      for (i = 0; i < object[0].Npts; i++) {
	if (!(finite(x[i]) && finite(y[i]))) continue;
	sx = x[i]*mxi + y[i]*mxj + bx;
	sy = x[i]*myi + y[i]*myj + by;
	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
	  {
	    DrawLine (sx + d*z[i], sy - d*z[i], sx - d*z[i], sy + d*z[i]);
	    DrawLine (sx - d*z[i], sy - d*z[i], sx + d*z[i], sy + d*z[i]);
	  }
      }
    }
    if (object[0].ptype == 4) {	/* filled triangle */
      for (i = 0; i < object[0].Npts; i++) {
	if (!(finite(x[i]) && finite(y[i]))) continue;
	sx = x[i]*mxi + y[i]*mxj + bx;
	sy = x[i]*myi + y[i]*myj + by;
	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
	  {
	    FillTriangle (sx - d*z[i], sy - 0.58*d*z[i], sx + d*z[i], sy - 0.58*d*z[i], sx, sy + 1.15*d*z[i]);
	    /*
	    DrawLine (sx - d*z[i], sy + 0.58*d*z[i], sx + d*z[i], sy + 0.58*d*z[i]);
	    DrawLine (sx + d*z[i], sy + 0.58*d*z[i], sx,          sy - 1.15*d*z[i]);
	    DrawLine (sx,          sy - 1.15*d*z[i], sx - d*z[i], sy + 0.58*d*z[i]);
	    */
	  }
      }
    }
    if (object[0].ptype == 5) {	/* open triangle */
      for (i = 0; i < object[0].Npts; i++) {
	if (!(finite(x[i]) && finite(y[i]))) continue;
	sx = x[i]*mxi + y[i]*mxj + bx;
	sy = x[i]*myi + y[i]*myj + by;
	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
	  {
	    DrawLine (sx - d*z[i], sy + 0.58*d*z[i], sx + d*z[i], sy + 0.58*d*z[i]);
	    DrawLine (sx + d*z[i], sy + 0.58*d*z[i], sx,          sy - 1.15*d*z[i]);
	    DrawLine (sx,          sy - 1.15*d*z[i], sx - d*z[i], sy + 0.58*d*z[i]);
	  }
      }
    }
    if (object[0].ptype == 6) {	/* Y */
      for (i = 0; i < object[0].Npts; i++) {
	if (!(finite(x[i]) && finite(y[i]))) continue;
	sx = x[i]*mxi + y[i]*mxj + bx;
	sy = x[i]*myi + y[i]*myj + by;
	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
	  {
	    DrawLine (sx, sy, sx - d*z[i], sy + 0.58*d*z[i]);
	    DrawLine (sx, sy, sx + d*z[i], sy + 0.58*d*z[i]);
	    DrawLine (sx, sy, sx,          sy - 1.15*d*z[i]);
	  }
      }
    }
    if (object[0].ptype == 7) {	/* 0 */
      for (i = 0; i < object[0].Npts; i++) {
	if (!(finite(x[i]) && finite(y[i]))) continue;
	sx = x[i]*mxi + y[i]*mxj + bx;
	sy = x[i]*myi + y[i]*myj + by;
	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
	  {
	    DrawCircle (sx, sy, d*z[i]);
	  }
      }
    }
    if (object[0].ptype == 8) {	/* pentagon */
      for (i = 0; i < object[0].Npts; i++) {
	if (!(finite(x[i]) && finite(y[i]))) continue;
	sx = x[i]*mxi + y[i]*mxj + bx;
	sy = x[i]*myi + y[i]*myj + by;
	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
	{
	  DrawLine (sx + 0.00*d*z[i], sy + 1.00*d*z[i], sx + 0.95*d*z[i], sy + 0.31*d*z[i]);
	  DrawLine (sx + 0.95*d*z[i], sy + 0.31*d*z[i], sx + 0.58*d*z[i], sy - 0.81*d*z[i]);
	  DrawLine (sx + 0.58*d*z[i], sy - 0.81*d*z[i], sx - 0.58*d*z[i], sy - 0.81*d*z[i]);
	  DrawLine (sx - 0.58*d*z[i], sy - 0.81*d*z[i], sx - 0.95*d*z[i], sy + 0.31*d*z[i]);
	  DrawLine (sx - 0.95*d*z[i], sy + 0.31*d*z[i], sx + 0.00*d*z[i], sy + 1.00*d*z[i]);
	}
      }
    }
    if (object[0].ptype == 9) {	/* hexagon */
      for (i = 0; i < object[0].Npts; i++) {
	if (!(finite(x[i]) && finite(y[i]))) continue;
	sx = x[i]*mxi + y[i]*mxj + bx;
	sy = x[i]*myi + y[i]*myj + by;
	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
	{
	  DrawLine (sx -      d*z[i], sy,               sx - 0.50*d*z[i], sy + 0.87*d*z[i]);
	  DrawLine (sx - 0.50*d*z[i], sy + 0.87*d*z[i], sx + 0.50*d*z[i], sy + 0.87*d*z[i]);
	  DrawLine (sx + 0.50*d*z[i], sy + 0.87*d*z[i], sx +      d*z[i], sy);

	  DrawLine (sx +      d*z[i], sy,               sx + 0.50*d*z[i], sy - 0.87*d*z[i]);
	  DrawLine (sx + 0.50*d*z[i], sy - 0.87*d*z[i], sx - 0.50*d*z[i], sy - 0.87*d*z[i]);
	  DrawLine (sx - 0.50*d*z[i], sy - 0.87*d*z[i], sx -      d*z[i], sy);
	}
      }
    }
    if (object[0].ptype == 100) {	/* connect a pair of points */
      for (i = 0; i + 1 < object[0].Npts; i+=2) {
	if (!(finite(x[i]) && finite(y[i]))) continue;
	sx1 = x[i]*mxi + y[i]*mxj + bx;
	sy1 = x[i]*myi + y[i]*myj + by;
	sx2 = x[i+1]*mxi + y[i+1]*mxj + bx;
	sy2 = x[i+1]*myi + y[i+1]*myj + by;
	DrawLine (sx1, sy1, sx2, sy2);
      }
    }
  } else {
    d = object[0].size * 0.5 * (graphic->dx + graphic->dy) * 0.003;
    x = object[0].x; y = object[0].y;
    if (object[0].ptype == 0) {	/* filled box */
      for (i = 0; i < object[0].Npts; i++) {
	if (!(finite(x[i]) && finite(y[i]))) continue;
	sx = x[i]*mxi + y[i]*mxj + bx;
	sy = x[i]*myi + y[i]*myj + by;
	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
	  {
	    FillRectangle (sx, sy, 2*d, 2*d);
	  }
      }
    }
    if (object[0].ptype == 1) {		/* open box */
      for (i = 0; i < object[0].Npts; i++) {
	if (!(finite(x[i]) && finite(y[i]))) continue;
	sx = x[i]*mxi + y[i]*mxj + bx;
	sy = x[i]*myi + y[i]*myj + by;
   	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
	  {
	    DrawRectangle (sx, sy, 2*d, 2*d);
	  }
      }
    }
    if (object[0].ptype == 2) { /* cross */
      for (i = 0; i < object[0].Npts; i++) {
	if (!(finite(x[i]) && finite(y[i]))) continue;
	sx = x[i]*mxi + y[i]*mxj + bx;
	sy = x[i]*myi + y[i]*myj + by;
	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
	  {
	    DrawLine (sx - d, sy, sx + d, sy);
	    DrawLine (sx, sy - d, sx, sy + d);
	  }
      }
    }
    if (object[0].ptype == 3) {		/* x */
      for (i = 0; i < object[0].Npts; i++) {
	if (!(finite(x[i]) && finite(y[i]))) continue;
	sx = x[i]*mxi + y[i]*mxj + bx;
	sy = x[i]*myi + y[i]*myj + by;
	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
	  {
	    DrawLine (sx + d, sy - d, sx - d, sy + d);
	    DrawLine (sx - d, sy - d, sx + d, sy + d);
	  }
      }
    }
    if (object[0].ptype == 4) {	/* filled triangle */
      for (i = 0; i < object[0].Npts; i++) {
	if (!(finite(x[i]) && finite(y[i]))) continue;
	sx = x[i]*mxi + y[i]*mxj + bx;
	sy = x[i]*myi + y[i]*myj + by;
	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
	  {
	    /*
	    DrawLine (sx - d, sy + 0.58*d, sx + d, sy + 0.58*d);
	    DrawLine (sx + d, sy + 0.58*d, sx,     sy - 1.15*d);
	    DrawLine (sx,     sy - 1.15*d, sx - d, sy + 0.58*d);
	    */
	    FillTriangle (sx - d, sy - 0.58*d, sx + d, sy - 0.58*d, sx, sy + 1.15*d);
	  }
      }
    }
    if (object[0].ptype == 5) {	/* open triangle */
      for (i = 0; i < object[0].Npts; i++) {
	if (!(finite(x[i]) && finite(y[i]))) continue;
	sx = x[i]*mxi + y[i]*mxj + bx;
	sy = x[i]*myi + y[i]*myj + by;
	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
	  {
	    DrawLine (sx - d, sy - 0.58*d, sx + d, sy - 0.58*d);
	    DrawLine (sx + d, sy - 0.58*d, sx,     sy + 1.15*d);
	    DrawLine (sx,     sy + 1.15*d, sx - d, sy - 0.58*d);
	  }
      }
    }
    if (object[0].ptype == 6) {	/* Y */
      for (i = 0; i < object[0].Npts; i++) {
	if (!(finite(x[i]) && finite(y[i]))) continue;
	sx = x[i]*mxi + y[i]*mxj + bx;
	sy = x[i]*myi + y[i]*myj + by;
	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
	  {
	    DrawLine (sx, sy, sx - d, sy - 0.58*d);
	    DrawLine (sx, sy, sx + d, sy - 0.58*d);
	    DrawLine (sx, sy, sx,     sy + 1.15*d);
	  }
      }
    }
    if (object[0].ptype == 7) {	/* 0 */
      for (i = 0; i < object[0].Npts; i++) {
	if (!(finite(x[i]) && finite(y[i]))) continue;
	sx = x[i]*mxi + y[i]*mxj + bx;
	sy = x[i]*myi + y[i]*myj + by;
	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
	  {
	    DrawCircle (sx, sy, d);
	  }
      }
    }
    if (object[0].ptype == 8) {	/* pentagon */
      for (i = 0; i < object[0].Npts; i++) {
	if (!(finite(x[i]) && finite(y[i]))) continue;
	sx = x[i]*mxi + y[i]*mxj + bx;
	sy = x[i]*myi + y[i]*myj + by;
	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
	{
	  DrawLine (sx + 0.00*d, sy + 1.00*d, sx + 0.95*d, sy + 0.31*d);
	  DrawLine (sx + 0.95*d, sy + 0.31*d, sx + 0.58*d, sy - 0.81*d);
	  DrawLine (sx + 0.58*d, sy - 0.81*d, sx - 0.58*d, sy - 0.81*d);
	  DrawLine (sx - 0.58*d, sy - 0.81*d, sx - 0.95*d, sy + 0.31*d);
	  DrawLine (sx - 0.95*d, sy + 0.31*d, sx + 0.00*d, sy + 1.00*d);
	}
      }
    }
    if (object[0].ptype == 9) {	/* pentagon */
      for (i = 0; i < object[0].Npts; i++) {
	if (!(finite(x[i]) && finite(y[i]))) continue;
	sx = x[i]*mxi + y[i]*mxj + bx;
	sy = x[i]*myi + y[i]*myj + by;
	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
	{
	  DrawLine (sx - 1.00*d, sy + 0.00*d, sx - 0.50*d, sy + 0.87*d);
	  DrawLine (sx - 0.50*d, sy + 0.87*d, sx + 0.50*d, sy + 0.87*d);
	  DrawLine (sx + 0.50*d, sy + 0.87*d, sx + 1.00*d, sy + 0.00*d);
	  DrawLine (sx + 1.00*d, sy + 0.00*d, sx + 0.50*d, sy - 0.87*d);
	  DrawLine (sx + 0.50*d, sy - 0.87*d, sx - 0.50*d, sy - 0.87*d);
	  DrawLine (sx - 0.50*d, sy - 0.87*d, sx - 1.00*d, sy + 0.00*d);
	}
      }
    }
    if (object[0].ptype == 100) {	
      for (i = 0; i + 1 < object[0].Npts; i+=2) {
	if (!(finite(x[i]) && finite(y[i]))) continue;
	sx1 = x[i]*mxi + y[i]*mxj + bx;
	sy1 = x[i]*myi + y[i]*myj + by;
	sx2 = x[i+1]*mxi + y[i+1]*mxj + bx;
	sy2 = x[i+1]*myi + y[i+1]*myj + by;
	DrawLine (sx1, sy1, sx2, sy2);
      }
    }
  }
}
    
/*******/
void PSXErrors (KapaGraphWidget *graph, Gobjects *object, FILE *f) {
  
  int i, bar;
  float *x, *y, *dxm, *dxp;
  double mxi, mxj, myi, myj, bxi, bxj, byi, byj, bx, by;
  double sx0, sy0, sx1, sy1, sz, sx10, sx11;

  mxi = graph[0].axis[0].dfx / (object[0].x1 - object[0].x0);
  mxj = graph[0].axis[1].dfx / (object[0].y1 - object[0].y0);
  myi = graph[0].axis[0].dfy / (object[0].x1 - object[0].x0);
  myj = graph[0].axis[1].dfy / (object[0].y1 - object[0].y0);
  
  bxi  =  graph[0].axis[0].fx - object[0].x0*graph[0].axis[0].dfx/(object[0].x1 - object[0].x0);
  bxj  =  -object[0].y0*graph[0].axis[1].dfx/(object[0].y1 - object[0].y0);
  byi  =  -object[0].x0*graph[0].axis[0].dfy/(object[0].x1 - object[0].x0);
  byj  =  graph[0].axis[1].fy - object[0].y0*graph[0].axis[1].dfy/(object[0].y1 - object[0].y0);
  
  bx = bxi + bxj;
  by = byi + byj;
  
  x = object[0].x; y = object[0].y; dxp = object[0].dxp; dxm = object[0].dxm; 
  bar = object[0].ebar; sz = object[0].size*graph[0].axis[1].dfy*0.03;
   
  for (i = 0; i < object[0].Npts; i++) {
    if (!(finite(x[i]) && finite(y[i]) && finite(dxp[i]))) continue;
    sx0 = x[i]*mxi + y[i]*mxj + bx;
    sy0 = x[i]*myi + y[i]*myj + by;
    sx1 = (x[i] + dxp[i])*mxi + y[i]*mxj + bx;
    sy1 = (x[i] + dxp[i])*myi + y[i]*myj + by;
    if (((sx0 > graph[0].axis[0].fx) && (sx0 < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
	 (sy0 < graph[0].axis[1].fy) && (sy0 > graph[0].axis[1].fy + graph[0].axis[1].dfy)) ||
	((sx1 > graph[0].axis[0].fx) && (sx1 < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
	 (sy1 < graph[0].axis[1].fy) && (sy1 > graph[0].axis[1].fy + graph[0].axis[1].dfy)))
      {
	DrawLine (sx0, sy0, sx1, sy1);
	if (bar) {
	  sx10 = sy1 - sz;
	  sx11 = sy1 + sz;
	  DrawLine (sx1, sx10, sx1, sx11);
	}
      }
    if (!(finite(x[i]) && finite(y[i]) && finite(dxm[i]))) continue;
    sx0 = x[i]*mxi + y[i]*mxj + bx;
    sy0 = x[i]*myi + y[i]*myj + by;
    sx1 = (x[i] - dxm[i])*mxi + y[i]*mxj + bx;
    sy1 = (x[i] - dxm[i])*myi + y[i]*myj + by;
    if (((sx0 > graph[0].axis[0].fx) && (sx0 < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
	 (sy0 < graph[0].axis[1].fy) && (sy0 > graph[0].axis[1].fy + graph[0].axis[1].dfy)) ||
	((sx1 > graph[0].axis[0].fx) && (sx1 < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
	 (sy1 < graph[0].axis[1].fy) && (sy1 > graph[0].axis[1].fy + graph[0].axis[1].dfy)))
      {
	DrawLine (sx0, sy0, sx1, sy1);
	if (bar) {
	  sx10 = sy1 - sz;
	  sx11 = sy1 + sz;
	  DrawLine (sx1, sx10, sx1, sx11);
	}
      }
  }
}

    
/*******/
void PSYErrors (KapaGraphWidget *graph, Gobjects *object, FILE *f) {
  
  int i, bar;
  float *x, *y, *dym, *dyp;
  double mxi, mxj, myi, myj, bxi, bxj, byi, byj, bx, by;
  double sx0, sy0, sx1, sy1, sz, sx10, sx11;
  
  mxi = graph[0].axis[0].dfx / (object[0].x1 - object[0].x0);
  mxj = graph[0].axis[1].dfx / (object[0].y1 - object[0].y0);
  myi = graph[0].axis[0].dfy / (object[0].x1 - object[0].x0);
  myj = graph[0].axis[1].dfy / (object[0].y1 - object[0].y0);
  
  bxi  =  graph[0].axis[0].fx - object[0].x0*graph[0].axis[0].dfx/(object[0].x1 - object[0].x0);
  bxj  =  -object[0].y0*graph[0].axis[1].dfx/(object[0].y1 - object[0].y0);
  byi  =  -object[0].x0*graph[0].axis[0].dfy/(object[0].x1 - object[0].x0);
  byj  =  graph[0].axis[1].fy - object[0].y0*graph[0].axis[1].dfy/(object[0].y1 - object[0].y0);
  
  bx = bxi + bxj;
  by = byi + byj;
  
  x = object[0].x; y = object[0].y; dyp = object[0].dyp; dym = object[0].dym; 
  bar = object[0].ebar; sz = object[0].size*graph[0].axis[0].dfx*0.03;
  
  for (i = 0; i < object[0].Npts; i++) {
    if (!(finite(x[i]) && finite(y[i]) && finite(dyp[i]))) continue;
    sx0 = x[i]*mxi + y[i]*mxj + bx;
    sy0 = x[i]*myi + y[i]*myj + by;
    sx1 = x[i]*mxi + (y[i] + dyp[i])*mxj + bx;
    sy1 = x[i]*myi + (y[i] + dyp[i])*myj + by;
    if (((sx0 > graph[0].axis[0].fx) && (sx0 < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
	 (sy0 < graph[0].axis[1].fy) && (sy0 > graph[0].axis[1].fy + graph[0].axis[1].dfy)) ||
	((sx1 > graph[0].axis[0].fx) && (sx1 < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
	 (sy1 < graph[0].axis[1].fy) && (sy1 > graph[0].axis[1].fy + graph[0].axis[1].dfy)))
      {
	DrawLine (sx0, sy0, sx1, sy1);
	if (bar) {
	  sx10 = sx1 - sz;
	  sx11 = sx1 + sz;
	  DrawLine (sx10, sy1, sx11, sy1);
	}
      }
    if (!(finite(x[i]) && finite(y[i]) && finite(dym[i]))) continue;
    sx0 = x[i]*mxi + y[i]*mxj + bx;
    sy0 = x[i]*myi + y[i]*myj + by;
    sx1 = x[i]*mxi + (y[i] - dym[i])*mxj + bx;
    sy1 = x[i]*myi + (y[i] - dym[i])*myj + by;
    if (((sx0 > graph[0].axis[0].fx) && (sx0 < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
	 (sy0 < graph[0].axis[1].fy) && (sy0 > graph[0].axis[1].fy + graph[0].axis[1].dfy)) ||
	((sx1 > graph[0].axis[0].fx) && (sx1 < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
	 (sy1 < graph[0].axis[1].fy) && (sy1 > graph[0].axis[1].fy + graph[0].axis[1].dfy)))
      {
	DrawLine (sx0, sy0, sx1, sy1);
	if (bar) {
	  sx10 = sx1 - sz;
	  sx11 = sx1 + sz;
	  DrawLine (sx10, sy1, sx11, sy1);
	}
      }
  }
}
