Index: branches/eam_branches/ohana.20170822/src/kapa2/src/DrawObjects.c
===================================================================
--- branches/eam_branches/ohana.20170822/src/kapa2/src/DrawObjects.c	(revision 40124)
+++ branches/eam_branches/ohana.20170822/src/kapa2/src/DrawObjects.c	(revision 40125)
@@ -1,7 +1,11 @@
 # include "Ximage.h"
 
+/* DrawRectangle & FillRectangle : take rectangle lower-left corner and widths 
+   DrawCircle & FillCircle : take circle center and radius
+*/
+
 # define DrawLine(X1,Y1,X2,Y2) (XDrawLine (graphic->display, graphic->window, graphic->gc, (int)(X1), (int)(Y1), (int)(X2), (int)(Y2)))
-# define DrawRectangle(X1,Y1,X2,Y2) (XDrawRectangle (graphic->display, graphic->window, graphic->gc, (int)(X1), (int)(Y1), (int)(X2), (int)(Y2)))
-# define FillRectangle(X1,Y1,X2,Y2) (XFillRectangle (graphic->display, graphic->window, graphic->gc, (int)(X1), (int)(Y1), (int)(X2), (int)(Y2)))
+# define DrawRectangle(X,Y,dX,dY) (XDrawRectangle (graphic->display, graphic->window, graphic->gc, (int)(X), (int)(Y), (int)(dX), (int)(dY)))
+# define FillRectangle(X,Y,dX,dY) (XFillRectangle (graphic->display, graphic->window, graphic->gc, (int)(X), (int)(Y), (int)(dX), (int)(dY)))
 # define DrawCircle(X,Y,R) (XDrawArc (graphic->display, graphic->window, graphic->gc, (int)(X-R), (int)(Y-R), abs(2*R), abs(2*R), 0, 23040))
 # define FillCircle(X,Y,R) (XFillArc (graphic->display, graphic->window, graphic->gc, (int)(X-R), (int)(Y-R), abs(2*R), abs(2*R), 0, 23040))
Index: branches/eam_branches/ohana.20170822/src/kapa2/src/PSObjects.c
===================================================================
--- branches/eam_branches/ohana.20170822/src/kapa2/src/PSObjects.c	(revision 40124)
+++ branches/eam_branches/ohana.20170822/src/kapa2/src/PSObjects.c	(revision 40125)
@@ -1,7 +1,13 @@
 # include "Ximage.h"
 
+void PSBars (KapaGraphWidget *graph, Gobjects *object, FILE *f, int mode);
+
+/* DrawRectangle & FillRectangle : take rectangle lower-left corner and widths 
+   DrawCircle & FillCircle : take circle center and radius
+*/
+
 # 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 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 DrawRectangle(X,Y,dX,dY) (fprintf (f, " %6.2f %6.2f %6.2f %6.2f B\n", (dX), (dY), (X), (graphic->dy-Y)))
+# define FillRectangle(X,Y,dX,dY) (fprintf (f, " %6.2f %6.2f %6.2f %6.2f F\n", (dX), (dY), (X), (graphic->dy-Y)))
 # define DrawCircle(X1,Y1,R) (fprintf (f, " %6.2f %6.2f %6.2f C\n", (X1), (graphic->dy - Y1), (R)))
 # define FillCircle(X1,Y1,R) (fprintf (f, " %6.2f %6.2f %6.2f FC\n", (X1), (graphic->dy - Y1), (R)))
@@ -32,6 +38,6 @@
 }
 
-int PSObjectsN (KapaGraphWidget *graph, Gobjects *object, FILE *f) {
-  
+void PSLineStyle (KapaGraphWidget *graph, Gobjects *object, FILE *f) {
+
   static char short_dash[] = "4 4";
   static char long_dash[] = "8 8";
@@ -64,4 +70,9 @@
     fprintf (f, "%s setrgbcolor\n", KapaColorRGBString(object->color));
   }
+}
+
+int PSObjectsN (KapaGraphWidget *graph, Gobjects *object, FILE *f) {
+  
+  PSLineStyle (graph, object, f);
 
   switch (object->style) {
@@ -71,4 +82,13 @@
     case KAPA_PLOT_HISTOGRAM: 
       PSHistogram (graph, object, f);
+      break;
+    case KAPA_PLOT_BARS_SOLID:
+      PSBars (graph, object, f, KAPA_PLOT_BARS_SOLID);
+      break;
+    case KAPA_PLOT_BARS_OUTLINE:
+      PSBars (graph, object, f, KAPA_PLOT_BARS_OUTLINE);
+      break;
+    case KAPA_PLOT_BARS_OUTFILL:
+      PSBars (graph, object, f, KAPA_PLOT_BARS_OUTFILL);
       break;
     case KAPA_PLOT_POINTS: 
@@ -265,25 +285,246 @@
   DrawLine (sx1, sy1, sxa, sy1);
   DrawLine (sxa, sy1, sxa, sya);
-
-# if (0)
-  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++) {
+}
+
+// uses object->color
+# define HISTOGRAM_SOLID(X_VALUE, Y_VALUE, DX_VAL) {			\
+  /* histogram bar corners */						\
+  double sxmin = (X_VALUE) - 0.5*(DX_VAL);				\
+  double sxmax = (X_VALUE) + 0.5*(DX_VAL);				\
+  double symin = Xaxis;							\
+  double symax = (Y_VALUE);						\
+  /* saturated values for corner coords: */				\
+  sxmin = MIN (MAX (sxmin, X0), X1);					\
+  sxmax = MIN (MAX (sxmax, X0), X1);					\
+  symin = MAX (MIN (symin, Y0), Y1);					\
+  symax = MAX (MIN (symax, Y0), Y1);					\
+  double dy = fabs(symax - symin);					\
+  double ylow = MIN(symin, symax);					\
+  FillRectangle (sxmin, ylow, (DX_VAL), dy); }
+
+// uses object->color
+# define HISTOGRAM_OUTLINE(X_VALUE, Y_VALUE, DX_VAL) {			\
+  /* histogram bar corners */						\
+  double sxmin = (X_VALUE) - 0.5*(DX_VAL);				\
+  double sxmax = (X_VALUE) + 0.5*(DX_VAL);				\
+  double symin = Xaxis;							\
+  double symax = (Y_VALUE);						\
+  /* saturated values for corner coords: */				\
+  sxmin = MIN (MAX (sxmin, X0), X1);					\
+  sxmax = MIN (MAX (sxmax, X0), X1);					\
+  symin = MAX (MIN (symin, Y0), Y1);					\
+  symax = MAX (MIN (symax, Y0), Y1);					\
+  double dy = fabs(symax - symin);					\
+  double ylow = MAX(symin, symax);					\
+  DrawRectangle (sxmin, ylow, (DX_VAL), dy); }
+
+# define HISTOGRAM_OUTFILL(X_VALUE, Y_VALUE, DX_VAL) {			\
+  /* histogram bar corners */						\
+  double sxmin = (X_VALUE) - 0.5*(DX_VAL);				\
+  double sxmax = (X_VALUE) + 0.5*(DX_VAL);				\
+  double symin = Xaxis;							\
+  double symax = (Y_VALUE);						\
+  /* saturated values for corner coords: */				\
+  sxmin = MIN (MAX (sxmin, X0), X1);					\
+  sxmax = MIN (MAX (sxmax, X0), X1);					\
+  symin = MIN (MAX (symin, Y0), Y1);					\
+  symax = MIN (MAX (symax, Y0), Y1);					\
+  double dy = fabs(symax - symin);					\
+  double ylow = MIN(symin, symax);					\
+  FillRectangle (sxmin, ylow, (DX_VAL), dy);				\
+  fprintf (f, "0.00 0.00 0.00 setrgbcolor\n");				\
+  DrawRectangle (sxmin, ylow, (DX_VAL), dy);				\
+  fprintf (f, "%s setrgbcolor\n", KapaColorRGBString(object->color)); }
+
+void PSBars (KapaGraphWidget *graph, Gobjects *object, FILE *f, int mode) {
+
+  double mxi = graph[0].axis[0].dfx / (object[0].x1 - object[0].x0); // slope of the x-axis in x-pixels
+  double mxj = graph[0].axis[1].dfx / (object[0].y1 - object[0].y0); // slope of the x-axis in y-pixels (always 0 for now)
+  double myi = graph[0].axis[0].dfy / (object[0].x1 - object[0].x0); // slope of the x-axis in x-pixels (always 0 for now)
+  double myj = graph[0].axis[1].dfy / (object[0].y1 - object[0].y0); // slope of the x-axis in x-pixels
+  
+  // intercepts of axes
+  double bxi  =  graph[0].axis[0].fx - object[0].x0*graph[0].axis[0].dfx/(object[0].x1 - object[0].x0);
+  double bxj  =  -object[0].y0*graph[0].axis[1].dfx/(object[0].y1 - object[0].y0);
+  double byi  =  -object[0].x0*graph[0].axis[0].dfy/(object[0].x1 - object[0].x0);
+  double byj  =  graph[0].axis[1].fy - object[0].y0*graph[0].axis[1].dfy/(object[0].y1 - object[0].y0);
+  
+  double bx = bxi + bxj;
+  double by = byi + byj;
+  
+  // corner coords
+  double X0 = graph[0].axis[0].fx;
+  double X1 = graph[0].axis[0].fx + graph[0].axis[0].dfx;
+  double Y0 = graph[0].axis[1].fy;
+  double Y1 = graph[0].axis[1].fy + graph[0].axis[1].dfy;
+  // NOTE: Y0 > Y1 (dfy is negative)
+
+  /* find the first valid datapoint */
+  float *x = object[0].x;
+  float *y = object[0].y;
+  
+  /* we are drawing bars which are filled rectangles of height y[i] and width 0.5*dx
+     one point at a time
+
+     I need to know the distance to the next and prev points to calculate dx
+     for the first point, dx is x[1] - x[0]
+     for the last point, dx is x[-1] - x[-2] (x[-1] is the last point)
+     for the rest, dx is 0.5*(x[i+1] - x[i-1])
+    
+     rather than working out complex on-the-fly logic, I want to find the first and last
+     valid point in an initial pass, then calculate the above for the remainder.
+     TBD: make an index vector of only valid points?
+  */
+
+  int Ngood = 0;
+  ALLOCATE_PTR (goodPoint, int, object[0].Npts);
+
+  // x = ??, y = 0: this assumes the xaxis is parallel to the plot window (myi = 0)
+  // note: Y0 > Y1 : y runs from large on bottom to small on top
+  float Xaxis = by;
+  Xaxis = MAX (Y1, MIN (Xaxis, Y0));
+
+  for (int i = 0; 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;
-  }
-# endif
+
+    // coordinate on the screen of the point:
+    double sx1r = x[i]*mxi + y[i]*mxj + bx;
+
+    if (sx1r < X0) {
+      // point to the left, skip it
+      continue;
+    }
+    if (sx1r > X1) {
+      // point to the right, skip it
+      continue;
+    }
+
+    goodPoint[Ngood] = i;
+    Ngood ++;
+  }
+    
+  if (Ngood == 0) {
+    free (goodPoint);
+    return;
+  }
+
+  // if we only have 1 point, draw bar half the width of the screen
+  // this works fine, but the auto limits for 1 value are somewhat silly
+  if (Ngood == 1) {
+    // coordinate on the screen of the point:
+    int n = goodPoint[0];
+    double sx1r = x[n]*mxi + y[n]*mxj + bx;
+    double sy1r = x[n]*myi + y[n]*myj + by;
+
+    float dx = 0.5*object->size*(X1 - X0);
+    
+    switch (mode) {
+      case KAPA_PLOT_BARS_SOLID:
+	HISTOGRAM_SOLID(sx1r, sy1r, dx);
+	break;
+      case KAPA_PLOT_BARS_OUTLINE:
+	HISTOGRAM_OUTLINE(sx1r, sy1r, dx);
+	break;
+      case KAPA_PLOT_BARS_OUTFILL:
+	HISTOGRAM_OUTFILL(sx1r, sy1r, dx);
+	break;
+      default:
+	HISTOGRAM_SOLID(sx1r, sy1r, dx);
+	break;
+    }
+
+    free (goodPoint);
+    return;
+  }
+
+  // first point:
+  {
+    int n;
+    n = goodPoint[1];
+    double sx1r = x[n]*mxi + y[n]*mxj + bx;
+
+    n = goodPoint[0];
+    double sx0r = x[n]*mxi + y[n]*mxj + bx;
+    double sy0r = x[n]*myi + y[n]*myj + by;
+
+    double dx = 0.5*object->size*(sx1r - sx0r);
+    
+    switch (mode) {
+      case KAPA_PLOT_BARS_SOLID:
+	HISTOGRAM_SOLID(sx0r, sy0r, dx);
+	break;
+      case KAPA_PLOT_BARS_OUTLINE:
+	HISTOGRAM_OUTLINE(sx0r, sy0r, dx);
+	break;
+      case KAPA_PLOT_BARS_OUTFILL:
+	HISTOGRAM_OUTFILL(sx0r, sy0r, dx);
+	break;
+      default:
+	HISTOGRAM_SOLID(sx0r, sy0r, dx);
+	break;
+    }
+  }
+
+  for (int i = 1; i < Ngood - 1; i++) {
+
+    int n;
+    n = goodPoint[i + 1];
+    double sx2r = x[n]*mxi + y[n]*mxj + bx;
+
+    n = goodPoint[i - 1];
+    double sx0r = x[n]*mxi + y[n]*mxj + bx;
+
+    // below we have 2 factors of 0.5 (we want half of the average spacing)
+    double dx = 0.5*0.5*object->size*(sx2r - sx0r);
+
+    n = goodPoint[i];
+    double sx1r = x[n]*mxi + y[n]*mxj + bx;
+    double sy1r = x[n]*myi + y[n]*myj + by;
+
+    switch (mode) {
+      case KAPA_PLOT_BARS_SOLID:
+	HISTOGRAM_SOLID(sx1r, sy1r, dx);
+	break;
+      case KAPA_PLOT_BARS_OUTLINE:
+	HISTOGRAM_OUTLINE(sx1r, sy1r, dx);
+	break;
+      case KAPA_PLOT_BARS_OUTFILL:
+	HISTOGRAM_OUTFILL(sx1r, sy1r, dx);
+	break;
+      default:
+	HISTOGRAM_SOLID(sx1r, sy1r, dx);
+	break;
+    }
+  }
+  
+  // last point:
+  {
+    int n;
+    n = goodPoint[Ngood - 1];
+    double sx1r = x[n]*mxi + y[n]*mxj + bx;
+    double sy1r = x[n]*myi + y[n]*myj + by;
+
+    n = goodPoint[Ngood - 2];
+    double sx0r = x[n]*mxi + y[n]*mxj + bx;
+
+    double dx = 0.5*object->size*(sx1r - sx0r);
+
+    switch (mode) {
+      case KAPA_PLOT_BARS_SOLID:
+	HISTOGRAM_SOLID(sx1r, sy1r, dx);
+	break;
+      case KAPA_PLOT_BARS_OUTLINE:
+	HISTOGRAM_OUTLINE(sx1r, sy1r, dx);
+	break;
+      case KAPA_PLOT_BARS_OUTFILL:
+	HISTOGRAM_OUTFILL(sx1r, sy1r, dx);
+	break;
+      default:
+	HISTOGRAM_SOLID(sx1r, sy1r, dx);
+	break;
+    }
+  }
+  free (goodPoint);
+  return;
 }
 
@@ -310,6 +551,5 @@
   by = byi + byj;
   
-  Graphic *graphic = GetGraphic();
-
+  // scaled colors use the colormap defined for the graphic
   ALLOCATE (pixel1, float, graphic[0].Npixels);
   ALLOCATE (pixel2, float, graphic[0].Npixels);
@@ -347,5 +587,5 @@
 	  }
 	  D = scaleSize ? dz*z[i] : ds;
-	  DrawRectangle (sx, sy, 2*D, 2*D);
+	  DrawRectangle (sx - D, sy - D, 2*D, 2*D);
 	}
       }
@@ -605,5 +845,5 @@
 	  }
 	  D = scaleSize ? dz*z[i] : ds;
-	  FillRectangle (sx, sy, 2*D, 2*D);
+	  FillRectangle (sx - D, sy - D, 2*D, 2*D);
 	}
       }
Index: branches/eam_branches/ohana.20170822/src/kapa2/src/bDrawObjects.c
===================================================================
--- branches/eam_branches/ohana.20170822/src/kapa2/src/bDrawObjects.c	(revision 40124)
+++ branches/eam_branches/ohana.20170822/src/kapa2/src/bDrawObjects.c	(revision 40125)
@@ -507,6 +507,4 @@
   
   // scaled colors use the colormap defined for the graphic
-  Graphic *graphic = GetGraphic();
-
   ALLOCATE (pixel1, unsigned char, graphic[0].Npixels);
   ALLOCATE (pixel2, unsigned char, graphic[0].Npixels);
@@ -520,5 +518,5 @@
   }
 
-  /**** points are scaled by object.z ***/
+  /**** point sizes are scaled by object.size, colors by object.color ***/
   int scaleSize = (object[0].size < 0);
   int scaleColor = (object[0].color < 0);
