Index: /trunk/Ohana/src/kapa/Makefile
===================================================================
--- /trunk/Ohana/src/kapa/Makefile	(revision 5609)
+++ /trunk/Ohana/src/kapa/Makefile	(revision 5610)
@@ -52,6 +52,15 @@
 $(GDIR)/LoadPtext.$(ARCH).o		  $(GDIR)/DrawPtext.$(ARCH).o		\
 $(GDIR)/PSLabels.$(ARCH).o		  $(GDIR)/PSPtext.$(ARCH).o		\
-$(GDIR)/DrawRotString.$(ARCH).o        	  $(GDIR)/PNGit.$(ARCH).o \
-$(GDIR)/PPMit.$(ARCH).o
+$(GDIR)/PNGit.$(ARCH).o                   $(GDIR)/PPMit.$(ARCH).o	        \
+$(GDIR)/DrawRotString.$(ARCH).o        	  $(GDIR)/RotFont.$(ARCH).o             \
+$(GDIR)/PSRotFont.$(ARCH).o
+
+BDRAW = \
+$(GDIR)/bDrawIt.$(ARCH).o	  	  $(GDIR)/bDrawFuncs.$(ARCH).o          \
+$(GDIR)/bDrawFrame.$(ARCH).o              $(GDIR)/bDrawLabels.$(ARCH).o         \
+$(GDIR)/bDrawObjects.$(ARCH).o            $(GDIR)/bDrawRotFont.$(ARCH).o        \
+$(GDIR)/PNGit2.$(ARCH).o \
+
+$(BDRAW): $(INC)/bDraw.h
 
 SOBJ = \
@@ -69,5 +78,5 @@
 $(SDIR)/MakeCursor.$(ARCH).o
 
-OBJ  =  $(EOBJ) $(GOBJ) $(MOBJ) $(SOBJ) 
+OBJ  =  $(EOBJ) $(GOBJ) $(MOBJ) $(SOBJ) $(BDRAW)
 
 # dependancy rules for include files ########################
Index: /trunk/Ohana/src/kapa/graph/DrawFrame.c
===================================================================
--- /trunk/Ohana/src/kapa/graph/DrawFrame.c	(revision 5609)
+++ /trunk/Ohana/src/kapa/graph/DrawFrame.c	(revision 5610)
@@ -65,7 +65,6 @@
   y = fy + (value-min)*dfy/(max - min);
 
-  dir = 1;
-  if ((naxis == 0) || (naxis == 1)) dir = -1;
-
+  dir = +1;
+  if ((naxis == 0) || (naxis == 1)) dir *= -1;
   dx = dir*size*dfy*n;	
   dy = dir*size*dfx*n;
@@ -84,6 +83,6 @@
     
     /* temporarily assume rectilinear axes */
-    if (naxis == 0) { dx = 0; dy = +(0.8*fontsize + 1); pos = 1; }
-    if (naxis == 2) { dx = 0; dy = -(0.8*fontsize + 1); pos = 7; }
+    if (naxis == 0) { dx = 0; dy = -dir*(0.8*fontsize + 1); pos = 1; }
+    if (naxis == 2) { dx = 0; dy = -dir*(0.8*fontsize + 1); pos = 7; }
 
     if (naxis == 1) { dy = 0; dx = -(0.8*fontsize + 1); pos = 3; }
Index: /trunk/Ohana/src/kapa/graph/DrawRotString.c
===================================================================
--- /trunk/Ohana/src/kapa/graph/DrawRotString.c	(revision 5609)
+++ /trunk/Ohana/src/kapa/graph/DrawRotString.c	(revision 5610)
@@ -2,5 +2,4 @@
 # include "alphabet.h"
 
-# define NROT 256
 # define XPROC(x,y) (scale*(cs*((x) - x0) - sn*((y) - y0)) + X0)
 # define YPROC(x,y) (scale*(cs*((y) - y0) + sn*((x) - x0)) + Y0)
@@ -213,281 +212,2 @@
   return (TRUE);
 }
-
-void InitRotFonts () {
-
-  int i, Nhardwired;
-
-  Nhardwired = sizeof (HardwiredFonts) / sizeof (FontSet);
-  
-  Nallfonts = Nhardwired;
-  ALLOCATE (AllFonts, FontSet, Nallfonts);
-  
-  for (i = 0; i < Nhardwired; i++) {
-    AllFonts[i] = HardwiredFonts[i];
-  }
-
-  activefont = AllFonts[DEFFONT].font;
-  activescale = 1.0;
-  strcpy (currentname, AllFonts[DEFFONT].name);
-  currentsize = AllFonts[DEFFONT].size;
-}
-
-int SetRotFont (char *name, int size) {
-  
-  int i, nsize, msize, bsize, bigger, dsize, match, good;
-
-  bigger = good = match = -1;
-  dsize = 10000;
-  bsize = 10000;
-  for (i = 0; i < Nallfonts; i++) {
-    if (!strcasecmp (AllFonts[i].name, name)) {
-      good = i;
-      nsize = abs (AllFonts[i].size - size);
-      if (nsize < dsize) {
-	match = i;
-	dsize = nsize;
-      }
-      msize = AllFonts[i].size - size;
-      if ((msize < bsize) && (msize >= 0)) {
-	bigger = i;
-	bsize = msize;
-      }
-    }
-  }
-  
-  if ((match == -1) && (good != -1)) match = good;
-  if (bigger != -1) match = bigger;
-  if (match != -1) {
-    activefont = AllFonts[match].font;
-    activescale = (double) size / AllFonts[match].size;
-    currentsize = size;
-    strcpy (currentname, name);
-    return (TRUE);
-  } else {
-    fprintf (stderr, "no matching font\n");
-    return (FALSE);
-  }
-
-}
-  
-char *GetRotFont (int *size) {
-
-  *size = currentsize;
-  return (currentname);
-
-}
-
-int RotStrlen (char *c) {
-
-  int i, N, dX, code;
-  double scale; 
-  
-  scale = activescale;
-
-  /* find string length */
-  dX = 0;
-
-  code = FALSE;
-  for (i = 0; i < strlen (c); i++) {
-    N = (int)(c[i]);
-    /* skip non-printing characters */
-    if ((N < 0) || (N >= NROT)) continue;
-
-    /* check for special characters */
-    if (!code) {
-      if (N == 94) { /* super-script */
-	scale *= 0.8;
-	continue;
-      }
-      if (N == 95) { /* sub-script */
-	scale *= 0.8;
-	continue;
-      }
-      if (N == 124) { /* normal-script */
-	scale = activescale;
-	continue;
-      }
-      if (N == 92) { /* backslash */
-	code = TRUE;
-	continue;
-      } 
-      if (N == 38) { /* font-code */
-	i++;
-	continue;
-      }
-    }
-    code = FALSE;
-    dX += scale*activefont[N].dx + 1;
-  }
-  return (dX);
-}
-
-/* writes commands to print string at location and angle using
-   currently set font and size */
-void PSRotText (FILE *f, int x, int y, char *string, int pos, double angle) {
-
-  char *c, *segment, basefont[64];
-  int i, N, code;
-  int dX, dY, Xoff, Yoff, X, Y, Nseg, NSEG, YoffBase;
-  double cs, sn, fscale;
-  int basesize;
-    
-  /* strip off leading whitespace */
-  for (c = string; (*c == ' ') || (*c == '\t'); c++);
-  if (*c == 0) return;
-  
-  /* compute string length */
-  /* PS fonts are somewhat different scales from bitmap font equivalents */
-  fscale = 1.0;
-  if (!strcmp (currentname, "times")) fscale = 1.07;
-  if (!strcmp (currentname, "courier")) fscale = 1.5;
-  if (!strcmp (currentname, "helvetica")) fscale = 0.9;
-  if (!strcmp (currentname, "symbol")) fscale = 1.2;
-  dX = fscale*RotStrlen (c);
-  dY = activefont[65].ascent;
-  
-  /* apply appropriate offset */
-  Xoff = Yoff = 0;
-  switch (pos) {
-  case 0: Xoff =     -dX; Yoff = -dY; break;
-  case 1: Xoff = -0.5*dX; Yoff = -dY; break;
-  case 2: Xoff =       0; Yoff = -dY; break;
-  case 3: Xoff =     -dX; Yoff = -0.5*dY; break;
-  case 4: Xoff = -0.5*dX; Yoff = -0.5*dY; break;
-  case 5: Xoff =       0; Yoff = -0.5*dY; break;
-  case 6: Xoff =     -dX; Yoff = 0; break;
-  case 7: Xoff = -0.5*dX; Yoff = 0; break;
-  case 8: Xoff =       0; Yoff = 0; break;
-  }
-  cs = cos(angle*RAD_DEG);
-  sn = sin(angle*RAD_DEG);
-  X = x + Xoff*cs + Yoff*sn;
-  Y = y - Xoff*sn + Yoff*cs;
-
-  basesize = currentsize;
-  strcpy (basefont, currentname);
-
-  PSSetFont (f, currentsize);
-  fprintf (f, "gsave\n");
-  fprintf (f, " %d %d moveto %f rotate\n", X, Y, -angle);
-
-  Nseg = 0;
-  NSEG = strlen(c) + 2;
-  ALLOCATE (segment, char, NSEG);
-  bzero (segment, NSEG);
-
-  code = FALSE;
-  YoffBase = 0;
-  /* accumulate string segments with common state */
-  for (i = 0; i < strlen (c); i++) {
-    N = (int)(c[i]);
-    if ((N < 0) || (N >= NROT)) continue;
-
-    /* check for special characters */
-    if (!code) {
-      /* superscript character (^) */
-      if (N == 94) {
-	PSDumpRotSegment (f, segment, &Nseg);
-	SetRotFont (currentname, (int)(0.8*currentsize));
-	Yoff = 0.75*activescale*dY;
-	fprintf (f, "0 %d rmoveto\n", Yoff);
-	YoffBase += Yoff;
-	PSSetFont (f, currentsize);
-	continue;
-      }
-      /* subscript character (_) */
-      if (N == 95) { 
-	PSDumpRotSegment (f, segment, &Nseg);
-	SetRotFont (currentname, (int)(0.8*currentsize));
-	Yoff = -0.5*activescale*dY;
-	fprintf (f, "0 %d rmoveto\n", Yoff);
-	YoffBase += Yoff;
-	PSSetFont (f, currentsize);
-	continue;
-      }
-      /* end super/sub script (|) */
-      if (N == 124) {
-	PSDumpRotSegment (f, segment, &Nseg);
-	SetRotFont (currentname, basesize);
-	fprintf (f, "0 %d rmoveto\n", -YoffBase);
-	YoffBase = 0;
-	PSSetFont (f, currentsize);
-	continue;
-      }
-      /* escape char (\) */
-      if (N == 92) {
-	code = TRUE;
-	continue;
-      } 
-      /* begin paren (insert \) */
-      if (N == 40) {
-	code = FALSE;
-	segment[Nseg] = 92;
-	Nseg ++;
-	CHECK_REALLOCATE (segment, char, NSEG, Nseg, 64);
-      }
-      /* end paren (insert \) */
-      if (N == 41) {
-	code = FALSE;
-	segment[Nseg] = 92;
-	Nseg ++;
-	CHECK_REALLOCATE (segment, char, NSEG, Nseg, 64);
-      }
-      /* font change character (&) */
-      if (N == 38) {
-	PSDumpRotSegment (f, segment, &Nseg);
-	if (c[i+1] == 'h') {
-	  SetRotFont ("helvetica", currentsize);
-	  PSSetFont (f, currentsize);
-	}
-	if (c[i+1] == 't') {
-	  SetRotFont ("times", currentsize);
-	  PSSetFont (f, currentsize);
-	}
-	if (c[i+1] == 'c') {
-	  SetRotFont ("courier", currentsize);
-	  PSSetFont (f, currentsize);
-	}
-	if (c[i+1] == 's') {
-	  SetRotFont ("symbol", currentsize);
-	  PSSetFont (f, currentsize);
-	}
-	i++;
-	continue;
-      }
-    }
-    code = FALSE;
-    segment[Nseg] = N;
-    Nseg ++;
-    CHECK_REALLOCATE (segment, char, NSEG, Nseg, 64);
-  }
-  PSDumpRotSegment (f, segment, &Nseg);
-  fprintf (f, "stroke grestore\n");
-  free (segment);
-  SetRotFont (basefont, basesize);
-}
-
-void PSDumpRotSegment (FILE *f, char *segment, int *Nseg) {
-  segment[*Nseg] = 0;
-  fprintf (f, "(%s) show\n", segment);
-  bzero (segment, *Nseg);
-  *Nseg = 0;
-}
-
-void PSSetFont (FILE *f, int size) {
-  if (!strcmp (currentname, "times")) 
-    fprintf (f, "/Times-Roman findfont %d scalefont setfont\n", size);
-  if (!strcmp (currentname, "helvetica")) 
-    fprintf (f, "/Helvetica findfont %d scalefont setfont\n", size);
-  if (!strcmp (currentname, "courier")) 
-    fprintf (f, "/Courier findfont %d scalefont setfont\n", size);
-  if (!strcmp (currentname, "symbol")) 
-    fprintf (f, "/Symbol findfont %d scalefont setfont\n", size);
-}
-
-
-
-  /* test cross hair
-  fprintf (f, "%d %d %d %d L\n", x-10, y, x+10, y);
-  fprintf (f, "%d %d %d %d L\n", x, y-10, x, y+10);
-  */
Index: /trunk/Ohana/src/kapa/graph/PNGit.c
===================================================================
--- /trunk/Ohana/src/kapa/graph/PNGit.c	(revision 5609)
+++ /trunk/Ohana/src/kapa/graph/PNGit.c	(revision 5610)
@@ -2,5 +2,5 @@
 # include <png.h>
 
-int PNGit () {
+int PNGit_old () {
 
   FILE *f;
@@ -35,5 +35,5 @@
   ALLOCATE (rows, png_byte *, dy);
   for (i = 0; i < dy; i++) {
-    ALLOCATE (rows[i], png_byte, 3*dx);
+    ALLOCATE (rows[i], png_byte, dx);
   }
 
@@ -120,9 +120,4 @@
 	    found = TRUE;
 	    rows[j][i] = k;
-	    /*
-	      rows[j][3*i+0] = palette[k].red;
-	      rows[j][3*i+1] = palette[k].green;
-	      rows[j][3*i+2] = palette[k].blue;
-	    */
 	  }
 	}
Index: /trunk/Ohana/src/kapa/graph/PNGit2.c
===================================================================
--- /trunk/Ohana/src/kapa/graph/PNGit2.c	(revision 5610)
+++ /trunk/Ohana/src/kapa/graph/PNGit2.c	(revision 5610)
@@ -0,0 +1,76 @@
+# include "Ximage.h"
+# include <png.h>
+# include "bDraw.h"
+
+int PNGit () {
+
+  FILE *f;
+  png_structp png_ptr;
+  png_infop info_ptr;
+  png_color *palette;
+  int Npalette;
+  char filename[1024];
+  int Nbytes, status;
+
+  bDrawBuffer *buffer;
+
+  /* expect a line telling the number of bytes and a filename */
+  status = read (sock, filename, 16);
+  filename[16] = 0;
+  sscanf (filename, "%*s %d", &Nbytes);
+  status = read (sock, filename, Nbytes);
+  filename[status] = 0; /* make the string easy to parse */
+
+  f = fopen (filename, "w");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "can't open output file %s\n", "Xgraph.png");
+    return (TRUE);  /* true because otherwise it quits kapa! */
+  }
+
+  png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, (png_voidp) NULL, (png_voidp) NULL, (png_voidp) NULL);
+  if (!png_ptr) {
+    fprintf (stderr, "can't get png structure\n");
+    fclose (f);
+    return (TRUE);
+  }
+
+  info_ptr = png_create_info_struct (png_ptr);
+  if (!info_ptr) {
+    fprintf (stderr, "can't get png info structure\n");
+    png_destroy_write_struct (&png_ptr, (png_infopp) NULL);
+    fclose (f);
+    return (TRUE);
+  }
+
+  if (setjmp (png_ptr[0].jmpbuf)) {
+    fprintf (stderr, "can't get png return\n");
+    png_destroy_write_struct (&png_ptr, &info_ptr);
+    fclose (f);
+    return (TRUE);
+  }
+
+  png_init_io (png_ptr, f);
+
+  /* see docs for write-row-callback to provide progress info */
+
+  png_set_IHDR (png_ptr, info_ptr, graphic.dx, graphic.dy, 8, PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); 
+
+  /* png_set_IHDR (png_ptr, info_ptr, graphic.dx, graphic.dy, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); */
+
+  palette = MakePNGPalette (&Npalette);
+  png_set_PLTE (png_ptr, info_ptr, palette, Npalette); 
+ 
+  png_write_info (png_ptr, info_ptr);
+
+  buffer = bDrawIt ();
+
+  png_write_image (png_ptr, buffer[0].pixels);
+  png_write_end (png_ptr, info_ptr);
+  png_destroy_write_struct (&png_ptr, &info_ptr);
+  
+  bDrawBufferFree (buffer);
+  free (palette);
+  fclose (f);
+  return (TRUE);
+
+}
Index: /trunk/Ohana/src/kapa/graph/PSFrame.c
===================================================================
--- /trunk/Ohana/src/kapa/graph/PSFrame.c	(revision 5609)
+++ /trunk/Ohana/src/kapa/graph/PSFrame.c	(revision 5610)
@@ -22,5 +22,4 @@
     if (layout[0].axis[i].areticks) {
       range = layout[0].axis[i].max - layout[0].axis[i].min;
-
       AxisTickScale (&layout[0].axis[i], &major, &minor);
 
@@ -65,5 +64,5 @@
 
   dir = -1;
-  if ((naxis == 0) || (naxis == 1)) dir = 1;
+  if ((naxis == 0) || (naxis == 1)) dir *= -1;
   dx = dir*size*dfy*n;	
   dy = dir*size*dfx*n;
@@ -75,6 +74,6 @@
 
     /* temporarily assume rectilinear axes */
-    if (naxis == 0) { dx = 0; dy = -(0.8*fontsize + 1); pos = 1; }
-    if (naxis == 2) { dx = 0; dy = +(0.8*fontsize + 1); pos = 7; }
+    if (naxis == 0) { dx = 0; dy = -dir*(0.8*fontsize + 1); pos = 1; }
+    if (naxis == 2) { dx = 0; dy = -dir*(0.8*fontsize + 1); pos = 7; }
 
     if (naxis == 1) { dy = 0; dx = -(0.8*fontsize + 1); pos = 3; }
Index: /trunk/Ohana/src/kapa/graph/PSRotFont.c
===================================================================
--- /trunk/Ohana/src/kapa/graph/PSRotFont.c	(revision 5610)
+++ /trunk/Ohana/src/kapa/graph/PSRotFont.c	(revision 5610)
@@ -0,0 +1,172 @@
+# include "Ximage.h"
+# include "alphabet.h"
+
+/* writes commands to print string at location and angle using
+   currently set font and size */
+void PSRotText (FILE *f, int x, int y, char *string, int pos, double angle) {
+
+  char *c, *segment, basefont[64];
+  int i, N, code;
+  int dX, dY, Xoff, Yoff, X, Y, Nseg, NSEG, YoffBase;
+  double cs, sn, fscale;
+  int basesize;
+    
+  /* strip off leading whitespace */
+  for (c = string; (*c == ' ') || (*c == '\t'); c++);
+  if (*c == 0) return;
+  
+  /* compute string length */
+  /* PS fonts are somewhat different scales from bitmap font equivalents */
+  fscale = 1.0;
+  if (!strcmp (currentname, "times")) fscale = 1.07;
+  if (!strcmp (currentname, "courier")) fscale = 1.5;
+  if (!strcmp (currentname, "helvetica")) fscale = 0.9;
+  if (!strcmp (currentname, "symbol")) fscale = 1.2;
+  dX = fscale*RotStrlen (c);
+  dY = activefont[65].ascent;
+  
+  /* apply appropriate offset */
+  Xoff = Yoff = 0;
+  switch (pos) {
+  case 0: Xoff =     -dX; Yoff = -dY; break;
+  case 1: Xoff = -0.5*dX; Yoff = -dY; break;
+  case 2: Xoff =       0; Yoff = -dY; break;
+  case 3: Xoff =     -dX; Yoff = -0.5*dY; break;
+  case 4: Xoff = -0.5*dX; Yoff = -0.5*dY; break;
+  case 5: Xoff =       0; Yoff = -0.5*dY; break;
+  case 6: Xoff =     -dX; Yoff = 0; break;
+  case 7: Xoff = -0.5*dX; Yoff = 0; break;
+  case 8: Xoff =       0; Yoff = 0; break;
+  }
+  cs = cos(angle*RAD_DEG);
+  sn = sin(angle*RAD_DEG);
+  X = x + Xoff*cs + Yoff*sn;
+  Y = y - Xoff*sn + Yoff*cs;
+
+  basesize = currentsize;
+  strcpy (basefont, currentname);
+
+  PSSetFont (f, currentsize);
+  fprintf (f, "gsave\n");
+  fprintf (f, " %d %d moveto %f rotate\n", X, Y, -angle);
+
+  Nseg = 0;
+  NSEG = strlen(c) + 2;
+  ALLOCATE (segment, char, NSEG);
+  bzero (segment, NSEG);
+
+  code = FALSE;
+  YoffBase = 0;
+  /* accumulate string segments with common state */
+  for (i = 0; i < strlen (c); i++) {
+    N = (int)(c[i]);
+    if ((N < 0) || (N >= NROT)) continue;
+
+    /* check for special characters */
+    if (!code) {
+      /* superscript character (^) */
+      if (N == 94) {
+	PSDumpRotSegment (f, segment, &Nseg);
+	SetRotFont (currentname, (int)(0.8*currentsize));
+	Yoff = 0.75*activescale*dY;
+	fprintf (f, "0 %d rmoveto\n", Yoff);
+	YoffBase += Yoff;
+	PSSetFont (f, currentsize);
+	continue;
+      }
+      /* subscript character (_) */
+      if (N == 95) { 
+	PSDumpRotSegment (f, segment, &Nseg);
+	SetRotFont (currentname, (int)(0.8*currentsize));
+	Yoff = -0.5*activescale*dY;
+	fprintf (f, "0 %d rmoveto\n", Yoff);
+	YoffBase += Yoff;
+	PSSetFont (f, currentsize);
+	continue;
+      }
+      /* end super/sub script (|) */
+      if (N == 124) {
+	PSDumpRotSegment (f, segment, &Nseg);
+	SetRotFont (currentname, basesize);
+	fprintf (f, "0 %d rmoveto\n", -YoffBase);
+	YoffBase = 0;
+	PSSetFont (f, currentsize);
+	continue;
+      }
+      /* escape char (\) */
+      if (N == 92) {
+	code = TRUE;
+	continue;
+      } 
+      /* begin paren (insert \) */
+      if (N == 40) {
+	code = FALSE;
+	segment[Nseg] = 92;
+	Nseg ++;
+	CHECK_REALLOCATE (segment, char, NSEG, Nseg, 64);
+      }
+      /* end paren (insert \) */
+      if (N == 41) {
+	code = FALSE;
+	segment[Nseg] = 92;
+	Nseg ++;
+	CHECK_REALLOCATE (segment, char, NSEG, Nseg, 64);
+      }
+      /* font change character (&) */
+      if (N == 38) {
+	PSDumpRotSegment (f, segment, &Nseg);
+	if (c[i+1] == 'h') {
+	  SetRotFont ("helvetica", currentsize);
+	  PSSetFont (f, currentsize);
+	}
+	if (c[i+1] == 't') {
+	  SetRotFont ("times", currentsize);
+	  PSSetFont (f, currentsize);
+	}
+	if (c[i+1] == 'c') {
+	  SetRotFont ("courier", currentsize);
+	  PSSetFont (f, currentsize);
+	}
+	if (c[i+1] == 's') {
+	  SetRotFont ("symbol", currentsize);
+	  PSSetFont (f, currentsize);
+	}
+	i++;
+	continue;
+      }
+    }
+    code = FALSE;
+    segment[Nseg] = N;
+    Nseg ++;
+    CHECK_REALLOCATE (segment, char, NSEG, Nseg, 64);
+  }
+  PSDumpRotSegment (f, segment, &Nseg);
+  fprintf (f, "stroke grestore\n");
+  free (segment);
+  SetRotFont (basefont, basesize);
+}
+
+void PSDumpRotSegment (FILE *f, char *segment, int *Nseg) {
+  segment[*Nseg] = 0;
+  fprintf (f, "(%s) show\n", segment);
+  bzero (segment, *Nseg);
+  *Nseg = 0;
+}
+
+void PSSetFont (FILE *f, int size) {
+  if (!strcmp (currentname, "times")) 
+    fprintf (f, "/Times-Roman findfont %d scalefont setfont\n", size);
+  if (!strcmp (currentname, "helvetica")) 
+    fprintf (f, "/Helvetica findfont %d scalefont setfont\n", size);
+  if (!strcmp (currentname, "courier")) 
+    fprintf (f, "/Courier findfont %d scalefont setfont\n", size);
+  if (!strcmp (currentname, "symbol")) 
+    fprintf (f, "/Symbol findfont %d scalefont setfont\n", size);
+}
+
+
+
+  /* test cross hair
+  fprintf (f, "%d %d %d %d L\n", x-10, y, x+10, y);
+  fprintf (f, "%d %d %d %d L\n", x, y-10, x, y+10);
+  */
Index: /trunk/Ohana/src/kapa/graph/RotFont.c
===================================================================
--- /trunk/Ohana/src/kapa/graph/RotFont.c	(revision 5610)
+++ /trunk/Ohana/src/kapa/graph/RotFont.c	(revision 5610)
@@ -0,0 +1,112 @@
+# include "Ximage.h"
+# include "alphabet.h"
+# define NROT 256
+  
+void InitRotFonts () {
+
+  int i, Nhardwired;
+
+  Nhardwired = sizeof (HardwiredFonts) / sizeof (FontSet);
+  
+  Nallfonts = Nhardwired;
+  ALLOCATE (AllFonts, FontSet, Nallfonts);
+  
+  for (i = 0; i < Nhardwired; i++) {
+    AllFonts[i] = HardwiredFonts[i];
+  }
+
+  activefont = AllFonts[DEFFONT].font;
+  activescale = 1.0;
+  strcpy (currentname, AllFonts[DEFFONT].name);
+  currentsize = AllFonts[DEFFONT].size;
+}
+
+int SetRotFont (char *name, int size) {
+  
+  int i, nsize, msize, bsize, bigger, dsize, match, good;
+
+  bigger = good = match = -1;
+  dsize = 10000;
+  bsize = 10000;
+  for (i = 0; i < Nallfonts; i++) {
+    if (!strcasecmp (AllFonts[i].name, name)) {
+      good = i;
+      nsize = abs (AllFonts[i].size - size);
+      if (nsize < dsize) {
+	match = i;
+	dsize = nsize;
+      }
+      msize = AllFonts[i].size - size;
+      if ((msize < bsize) && (msize >= 0)) {
+	bigger = i;
+	bsize = msize;
+      }
+    }
+  }
+  
+  if ((match == -1) && (good != -1)) match = good;
+  if (bigger != -1) match = bigger;
+  if (match != -1) {
+    activefont = AllFonts[match].font;
+    activescale = (double) size / AllFonts[match].size;
+    currentsize = size;
+    strcpy (currentname, name);
+    return (TRUE);
+  } else {
+    fprintf (stderr, "no matching font\n");
+    return (FALSE);
+  }
+
+}
+  
+char *GetRotFont (int *size) {
+
+  *size = currentsize;
+  return (currentname);
+
+}
+
+int RotStrlen (char *c) {
+
+  int i, N, dX, code;
+  double scale; 
+  
+  scale = activescale;
+
+  /* find string length */
+  dX = 0;
+
+  code = FALSE;
+  for (i = 0; i < strlen (c); i++) {
+    N = (int)(c[i]);
+    /* skip non-printing characters */
+    if ((N < 0) || (N >= NROT)) continue;
+
+    /* check for special characters */
+    if (!code) {
+      if (N == 94) { /* super-script */
+	scale *= 0.8;
+	continue;
+      }
+      if (N == 95) { /* sub-script */
+	scale *= 0.8;
+	continue;
+      }
+      if (N == 124) { /* normal-script */
+	scale = activescale;
+	continue;
+      }
+      if (N == 92) { /* backslash */
+	code = TRUE;
+	continue;
+      } 
+      if (N == 38) { /* font-code */
+	i++;
+	continue;
+      }
+    }
+    code = FALSE;
+    dX += scale*activefont[N].dx + 1;
+  }
+  return (dX);
+}
Index: /trunk/Ohana/src/kapa/graph/bDrawFrame.c
===================================================================
--- /trunk/Ohana/src/kapa/graph/bDrawFrame.c	(revision 5610)
+++ /trunk/Ohana/src/kapa/graph/bDrawFrame.c	(revision 5610)
@@ -0,0 +1,90 @@
+# include "Ximage.h"
+# include "bDraw.h"
+
+int bDrawFrame (Layout *layout) {
+  
+  int i, P, IsLabel, fontsize;
+  double fx, fy, dfx, dfy, range, major, minor, first, next;
+  char *fontname;
+
+  /* each axis is drawn independently */
+  fontname = GetRotFont (&fontsize);
+  for (i = 0; i < 4; i++) {
+    fx  = layout[0].axis[i].fx;
+    fy  = layout[0].axis[i].fy;
+    dfx = layout[0].axis[i].dfx;
+    dfy = layout[0].axis[i].dfy;
+    P = hypot ((double)layout[0].axis[(i+1)%2].dfx, (double)layout[0].axis[(i+1)%2].dfy);
+
+    if (layout[0].axis[i].isaxis) { 
+      bDrawLine (fx, fy, fx+dfx, fy+dfy, FALSE); 
+    }
+    
+    if (layout[0].axis[i].areticks) {
+      range = layout[0].axis[i].max - layout[0].axis[i].min;
+
+      AxisTickScale (&layout[0].axis[i], &major, &minor);
+
+      first = minor*((int)(layout[0].axis[i].min/minor));
+      if ((range > 0) && (first < layout[0].axis[i].min)) {
+	first += minor;
+      }
+      if ((range < 0) && (first > layout[0].axis[i].min)) {
+	first -= minor;
+      }
+      for (next = first; ((range > 0) && (next <= layout[0].axis[i].max)) || ((range < 0) && (next >= layout[0].axis[i].max));) {
+	IsLabel = FALSE;
+	if ((fabs((int)(next/major) - (next/major)) < 0.5*(minor/major)) || 
+	    (fabs ((int)((next + 0.5*minor)/major) - (next/major)) < 0.5*(minor/major)) ||
+	    (fabs ((int)((next - 0.5*minor)/major) - (next/major)) < 0.5*(minor/major)))
+	  IsLabel = layout[0].axis[i].islabel;
+	bDrawTick (fx, fy, dfx, dfy, P, layout[0].axis[i].min, layout[0].axis[i].max, next, IsLabel, i);
+	if (range > 0) 
+	  next += minor;
+	else 
+	  next -= minor;
+      }
+    }
+  }
+  return (TRUE);
+}
+
+void bDrawTick (double fx, double fy, double dfx, double dfy, int P, double min, double max, double value, int mode, int naxis) {
+  
+  int pos, dir, fontsize;
+  double size, n, x, y, dx, dy;
+  char string[64], *fontname;
+
+  pos = size = 0;
+
+  if (mode == 1) { size = MAX (0.02, 7.0 / P); }
+  if (mode == 0) { size = MAX (0.01, 4.0 / P); }
+  
+  n = P / sqrt ((double)(dfx*dfx + dfy*dfy));
+  x = fx + (value-min)*dfx/(max - min);
+  y = fy + (value-min)*dfy/(max - min);
+
+  dir = +1;
+  if ((naxis == 0) || (naxis == 1)) dir *= -1;
+  dx = dir*size*dfy*n;	
+  dy = dir*size*dfx*n;
+  
+  bDrawLine (x, y, x+dx, y+dy, FALSE);
+
+  if (mode == 1) {
+    fontname = GetRotFont (&fontsize);
+
+    /* temporarily assume rectilinear axes */
+    if (naxis == 0) { dx = 0; dy = -dir*(0.8*fontsize + 1); pos = 1; }
+    if (naxis == 2) { dx = 0; dy = -dir*(0.8*fontsize + 1); pos = 7; }
+
+    if (naxis == 1) { dy = 0; dx = -(0.8*fontsize + 1); pos = 3; }
+    if (naxis == 3) { dy = 0; dx = +(0.8*fontsize + 1); pos = 5; }
+
+    x = fx + (value-min)*dfx/(max - min) + dx;
+    y = fy + (value-min)*dfy/(max - min) + dy;
+    if (fabs(value) < 1e-14) { value = 0.0; }
+    sprintf (string, "%g", value);
+    bDrawRotText ((int)x, (int)y, string, pos, 0.0);
+  }
+}
Index: /trunk/Ohana/src/kapa/graph/bDrawFuncs.c
===================================================================
--- /trunk/Ohana/src/kapa/graph/bDrawFuncs.c	(revision 5610)
+++ /trunk/Ohana/src/kapa/graph/bDrawFuncs.c	(revision 5610)
@@ -0,0 +1,286 @@
+# include "Ximage.h"
+# include "bDraw.h"
+
+static int bWeight;
+static int bType;
+static bDrawColor bColor;
+static bDrawBuffer *bBuffer;
+
+bDrawBuffer *bDrawBufferCreate (int Nx, int Ny) {
+
+  int i, j;
+  bDrawColor white;
+  bDrawBuffer *buffer;
+
+  white = GetColorByName ("white");
+
+  ALLOCATE (buffer, bDrawBuffer, 1);
+  buffer[0].Nx = Nx;
+  buffer[0].Ny = Ny;
+
+  ALLOCATE (buffer[0].pixels, bDrawColor *, Ny);
+  for (i = 0; i < Ny; i++) {
+    ALLOCATE (buffer[0].pixels[i], bDrawColor, Nx);
+    for (j = 0; j < Nx; j++) {
+      buffer[0].pixels[i][j] = white;
+    }
+  }
+  return (buffer);
+}
+
+void bDrawBufferFree (bDrawBuffer *buffer) {
+
+  int i;
+
+  for (i = 0; i < buffer[0].Ny; i++) {
+    free (buffer[0].pixels[i]);
+  }
+  free (buffer[0].pixels);
+  free (buffer);
+  return;
+}
+
+void bDrawSetBuffer (bDrawBuffer *buffer) {
+  bBuffer = buffer;
+  return;
+}
+
+void bDrawSetStyle (bDrawColor color, int lw, int lt) {
+  bColor = color;
+  bWeight = lw;
+  bType = lt;
+  return;
+}
+
+// draw a point in the current color 
+void bDrawPoint (int x, int y) {
+
+  if (x < 0) return;
+  if (y < 0) return;
+  if (x >= bBuffer[0].Nx) return;
+  if (y >= bBuffer[0].Ny) return;
+  bBuffer[0].pixels[y][x] = bColor;
+  return;
+}
+
+// draw a point in the current color 
+void bDrawPointf (float x, float y) {
+
+  bDrawPoint (ROUND(x), ROUND(y));
+  return;
+}
+
+// use the Bresenham line drawing technique
+void bDrawLine (double x1, double y1, double x2, double y2, int swapcoords) {
+
+  int X1, Y1, X2, Y2;
+  int X, Y, dX, dY;
+
+  /* rather than draw the line from float positions, we find the closest
+     integer end-points and draw the line between those pixels */ 
+
+  X1 = ROUND(x1);
+  Y1 = ROUND(y1);
+  X2 = ROUND(x2);
+  Y2 = ROUND(y2);
+
+  dX = X2 - X1;
+  dY = Y2 - Y1;
+
+  // fprintf (stderr, "(%f,%f) - (%f,%f)\n", x1, y1, x2, y2);
+  if (x1 > x2) {
+    // fprintf (stderr, "flip direct\n");
+    bDrawLine (x2, y2, x1, y1, swapcoords);
+    return;
+  }
+  if (abs(dX) < abs(dY)) {
+    // fprintf (stderr, "flip coords\n");
+    bDrawLine (y1, x1, y2, x2, TRUE);
+    return;
+  }
+
+  /* integer-only Bresenham line-draw version which is fast */
+  {
+    int e, e2;
+
+    Y = Y1;
+    e = 0;
+    for (X = X1; X <= X2; X++) {
+      if (swapcoords) {
+	bDrawPoint (Y,X);
+      } else {
+	bDrawPoint (X,Y);
+      }
+      e += dY;
+      e2 = 2 * e;
+      if (e2 > dX) {
+	Y++;
+	e -= dX;
+      } 
+      if (e2 < -dX) {
+	Y--;
+	e += dX;
+      }
+    }
+  }
+  return;
+}
+
+void bDrawRectOpen (int x1, int y1, int x2, int y2) {
+
+  return;
+}
+
+void bDrawRectFill (int x1, int y1, int x2, int y2) {
+
+  return;
+}
+
+void bDrawTriOpen (int x1, int y1, int x2, int y2, int x3, int y3) {
+
+  return;
+}
+
+void bDrawTriFill (int x1, int y1, int x2, int y2, int x3, int y3) {
+
+  return;
+}
+
+void bDrawArc (double Xc, double Yc, double Xr, double Yr, double Ts, double Te) {
+
+  float t, dt;
+  int x, y;
+
+  /* drawing a complete circle */
+//  if ((fabs(Te - Ts) > 360.0) && (Xr == Yr)) {
+//    bDrawCircle (Xc, Yc, Xr);
+//    return;
+//  }
+
+  /* only draw a single loop */
+  if (fabs(Te - Ts) > 360.0) {
+    Te = 360.0;
+    Ts = 0.0;
+  }
+
+  /* smallest angle is 1/Rmax */
+  dt = MAX (fabs(Xr * sin(Ts*RAD_DEG)), fabs(Yr * cos(Ts*RAD_DEG)));
+  dt = 1.0 / dt;
+
+  for (t = Ts*RAD_DEG; t <= Te*RAD_DEG; t += dt) {
+    x = Xr*cos(t) + Xc;
+    y = Yr*sin(t) + Yc;
+
+    /* we could use the value of MAX(dy/dt,dx/dt) to set dt */
+    bDrawPoint (x,y);
+
+    dt = MAX (fabs(Xr * sin(t)), fabs(Yr * cos(t)));
+    dt = 1.0 / dt;
+  }
+  return;
+}
+
+// draw a pure circle  
+void bDrawCircle (double xc, double yc, double radius) {
+
+  int Xc, Yc, Radius;
+  int x, y, d;
+
+  Xc = ROUND(xc);
+  Yc = ROUND(yc);
+  Radius = ROUND(radius);
+
+  x = 0;
+  y = Radius;
+
+  // d = 3 - 2*Radius;
+  d = 5 - 4*radius;
+
+  while (x <= y) {
+    bDrawPoint (Xc+x, Yc+y);
+    bDrawPoint (Xc+x, Yc-y);
+    bDrawPoint (Xc-x, Yc+y);
+    bDrawPoint (Xc-x, Yc-y);
+    bDrawPoint (Xc+y, Yc+x);
+    bDrawPoint (Xc+y, Yc-x);
+    bDrawPoint (Xc-y, Yc+x);
+    bDrawPoint (Xc-y, Yc-x);
+
+    if (d < 0) {
+      // d = d + 4*x + 6;
+      d = d + 8*x + 4;
+    } else {
+      // d = d + 4*(x-y) + 10;
+      d = d + 8*(x-y) + 8;
+      y--;
+    }
+    x++;
+  }
+}
+
+/* 
+the discriminant of inside or outside the circle is:
+
+f(x,y) = x^2 + y^2 - r^2
+
+- negative: (x,y) inside circle
+- positive: (x,y) outside circle
+
+given d(0) = f(x,y); find d(1) = f(x+1,y):
+d(1) = (x+1)^2 + y^2 - r^2
+d(1) = d(0) + 2x + 1
+(use d(1) if d(0) < 0, ie inside circle)
+
+given d(0) = f(x,y); find d(1) = f(x+1,y-1):
+d(1) = (x+1)^2 + (y-1)^2 - r^2
+d(1) = d(0) + 2x + 1 - 2y + 1
+d(1) = d(0) + 2(x-y) + 2
+
+* init d to f(1,r-1/2) instead of r, keeping the effective boundary 
+  between two pixels (also, an inside point)
+
+f(1,r-1/2) = 1 + (r-1/2)^2 - r^2 = 5/4 - r
+f(1,r-1/4) = 1 + (r-1/4)^2 - r^2 = 1 + r/2 + 1/16 = 17/16 + r/2
+
+f(1,r-x)   = 1 + (r-x)^2 - r^2 = 1 - 2xr + x^2 = A (3 - 2r)
+
+1+x^2 = 3A
+-2x = -2A
+
+A = x
+
+1 - 3x + x^2 = 0
+
+(3 +/- sqrt(9 - 4))/2 = (3 - sqrt(5))/2
+
+multiply all d values by 4 to get integer tests:
+
+d'(0) = 5 - 4r
+d'(in) = d' + 8x + 4
+d'(out) = d' + 8(x-y) + 8
+
+*/
+
+/* This is the Bresenham line-drawing algorithm for 1st and 4th quandrant
+   vectors with positive and negative slopes < 1. this is the sequence if we use
+   float errors and tests it is easy to understand, but slower than it could be
+
+  { 
+    float e, m;
+    m = dY / dX;
+    Y = Y1;
+    e = 0;
+    for (X = X1; X <= X2; X++) {
+      plot (X,Y);
+      e += m;
+      if (e > 0.5) {
+	Y++;
+	e -= 1.0;
+      }
+      if (e < -0.5) {
+	Y--;
+	e += 1.0;
+      }
+    }
+  }
+*/
Index: /trunk/Ohana/src/kapa/graph/bDrawIt.c
===================================================================
--- /trunk/Ohana/src/kapa/graph/bDrawIt.c	(revision 5610)
+++ /trunk/Ohana/src/kapa/graph/bDrawIt.c	(revision 5610)
@@ -0,0 +1,25 @@
+# include "Ximage.h"
+# include "bDraw.h"
+
+bDrawBuffer *bDrawIt () {
+
+  int i;
+  bDrawBuffer *buffer;
+  bDrawColor black;
+
+  black = GetColorByName ("black");
+
+  buffer = bDrawBufferCreate (graphic.dx, graphic.dy);
+  bDrawSetBuffer (buffer);
+  bDrawSetStyle (black, 0, 0);
+  
+  for (i = 0; i < Nsection; i++) {
+    bDrawFrame (&section[i]); 
+    bDrawObjects (&section[i]);
+    bDrawLabels (&section[i]);
+    bDrawPtext (&section[i]);
+  }
+  
+  return (buffer);
+}
+
Index: /trunk/Ohana/src/kapa/graph/bDrawLabels.c
===================================================================
--- /trunk/Ohana/src/kapa/graph/bDrawLabels.c	(revision 5610)
+++ /trunk/Ohana/src/kapa/graph/bDrawLabels.c	(revision 5610)
@@ -0,0 +1,66 @@
+# include "Ximage.h"
+# include "bDraw.h"
+  
+void bDrawLabels (Layout *layout) {
+  
+  int i, pos, x, y, size;
+  double angle;
+  char *fontname;
+
+  pos = 0;
+  fontname = GetRotFont (&size);
+  for (i = 0; i < 8; i++) {
+    if (strcmp (layout[0].label[i].text, "")) {
+      angle = 0;
+      switch (i) {
+      case 0: pos = 7; break;
+      case 1: pos = 1; angle = -90; break;
+      case 2: pos = 1; break;
+      case 3: pos = 1; angle =  90; break;
+      case 4: pos = 2; break;
+      case 5: pos = 0; break;
+      case 6: pos = 8; break;
+      case 7: pos = 6; break;
+      }	
+      x = layout[0].label[i].x;
+      y = graphic.dy - layout[0].label[i].y;
+      SetRotFont (layout[0].label[i].font, layout[0].label[i].size); 
+      bDrawRotText (x, y, layout[0].label[i].text, pos, angle);
+    }
+  }
+  SetRotFont (fontname, size);
+}
+
+void bDrawPtext (Layout *layout) {
+
+  int i, x, y, size;
+  double angle;
+  char *fontname;
+
+  fontname = GetRotFont (&size);
+  for (i = 0; i < layout[0].Nptext; i++) {
+    if (strcmp (layout[0].ptext[i].text, "")) {
+      angle = layout[0].ptext[i].angle;
+      x = layout[0].ptext[i].x;
+      y = graphic.dy - layout[0].ptext[i].y;
+      SetRotFont (layout[0].ptext[i].font, layout[0].ptext[i].size);
+      bDrawRotText (x, y, layout[0].ptext[i].text, 5, angle);
+    }
+  }
+  SetRotFont (fontname, size);
+}
+
+/*
+            
+ 4____2___5 
+  |       | 
+  |       | 
+ 1|       |3
+  |       |
+  |       |
+  ---------
+  6   0   7
+
+*/
+
+
Index: /trunk/Ohana/src/kapa/graph/bDrawObjects.c
===================================================================
--- /trunk/Ohana/src/kapa/graph/bDrawObjects.c	(revision 5610)
+++ /trunk/Ohana/src/kapa/graph/bDrawObjects.c	(revision 5610)
@@ -0,0 +1,572 @@
+# include "Ximage.h"
+# include "bDraw.h"
+
+# define DrawLine(X1,Y1,X2,Y2) (bDrawLine ((X1), (Y1), (X2), (Y2), FALSE))
+# define DrawCircle(X1,Y1,R) (bDrawCircle ((X1), (Y1), (R)))
+# define DrawRectangle(X,Y,dX,dY) (bDrawRectOpen ((X-0.5*dX), (Y-0.5*dY), (dX), (dY)))
+# define FillRectangle(X,Y,dX,dY) (bDrawRectFill ((X-0.5*dX), (Y-0.5*dY), (dX), (dY)))
+# define FillTriangle(X1,Y1,X2,Y2,X3,Y3) (bDrawTriFill ((X1), (Y1), (X2), (Y2), (X3), (Y3)))
+# define CONNECT 0
+# define HISTOGRAM 1
+# define POINTS 2
+
+int bDrawObjects (Layout *layout) {
+  
+  int i;
+  int type;
+  int weight;
+  bDrawColor color;
+  bDrawColor black;
+  
+  black = GetColorByName ("black");
+  for (i = 0; i < layout[0].Nobjects; i++) {
+
+    weight = MAX (0, MIN (10, layout[0].objects[i].lweight));
+    type = layout[0].objects[i].ltype;    
+    color = layout[0].objects[i].color;
+    bDrawSetStyle (color, weight, type);
+
+    switch (layout[0].objects[i].style) {
+    case CONNECT: 
+      bDrawConnect (layout, &layout[0].objects[i]);
+      break;
+    case HISTOGRAM:
+      bDrawHistogram (layout, &layout[0].objects[i]);
+      break;
+    case POINTS:
+      bDrawPoints (layout, &layout[0].objects[i]);
+      break;
+    }
+
+    if (layout[0].objects[i].etype & 0x01) {
+      bDrawYErrors (layout, &layout[0].objects[i]);
+    }
+    if (layout[0].objects[i].etype & 0x02) {
+      bDrawXErrors (layout, &layout[0].objects[i]);
+    }
+  }
+  bDrawSetStyle (black, 0, 0);
+  return (TRUE);
+}
+
+void bDrawConnect (Layout *layout, Gobjects *object) {
+  
+  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 = layout[0].axis[0].dfx / (object[0].x1 - object[0].x0);
+  mxj = layout[0].axis[1].dfx / (object[0].y1 - object[0].y0);
+  myi = layout[0].axis[0].dfy / (object[0].x1 - object[0].x0);
+  myj = layout[0].axis[1].dfy / (object[0].y1 - object[0].y0); 
+  
+  bxi  =  layout[0].axis[0].fx - object[0].x0*layout[0].axis[0].dfx/(object[0].x1 - object[0].x0);
+  bxj  =  -object[0].y0*layout[0].axis[1].dfx/(object[0].y1 - object[0].y0);
+  byi  =  -object[0].x0*layout[0].axis[0].dfy/(object[0].x1 - object[0].x0);
+  byj  =  layout[0].axis[1].fy - object[0].y0*layout[0].axis[1].dfy/(object[0].y1 - object[0].y0); 
+  
+  bx = bxi + bxj;
+  by = byi + byj;
+  
+  X0 = layout[0].axis[0].fx;
+  X1 = layout[0].axis[0].fx + layout[0].axis[0].dfx;
+  Y0 = layout[0].axis[1].fy;
+  Y1 = layout[0].axis[1].fy + layout[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;
+    bDrawClipLine (sx0, sy0, sx1, sy1, X0, Y0, X1, Y1);
+    sx0 = sx1; sy0 = sy1;
+  }
+}
+
+void bDrawClipLine (double x0, double y0, double x1, double y1, double X0, double Y1, double X1, double Y0) {
+
+  /* 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 bDrawHistogram (Layout *layout, Gobjects *object) {
+
+  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 = layout[0].axis[0].dfx / (object[0].x1 - object[0].x0);
+  mxj = layout[0].axis[1].dfx / (object[0].y1 - object[0].y0);
+  myi = layout[0].axis[0].dfy / (object[0].x1 - object[0].x0);
+  myj = layout[0].axis[1].dfy / (object[0].y1 - object[0].y0); 
+  
+  bxi  =  layout[0].axis[0].fx - object[0].x0*layout[0].axis[0].dfx/(object[0].x1 - object[0].x0);
+  bxj  =  -object[0].y0*layout[0].axis[1].dfx/(object[0].y1 - object[0].y0);
+  byi  =  -object[0].x0*layout[0].axis[0].dfy/(object[0].x1 - object[0].x0);
+  byj  =  layout[0].axis[1].fy - object[0].y0*layout[0].axis[1].dfy/(object[0].y1 - object[0].y0); 
+  
+  bx = bxi + bxj;
+  by = byi + byj;
+  
+  X0 = layout[0].axis[0].fx;
+  X1 = layout[0].axis[0].fx + layout[0].axis[0].dfx;
+  Y0 = layout[0].axis[1].fy;
+  Y1 = layout[0].axis[1].fy + layout[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[0]*mxi + y[0]*mxj + bx;
+  sy0 = x[0]*myi + y[0]*myj + by;
+  sx0 = MIN (MAX (sx0, X0), X1);
+  sy0 = MAX (MIN (sy0, Y0), Y1);
+  
+  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 bDrawPoints (Layout *layout, Gobjects *object) {
+ 
+  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 = layout[0].axis[0].dfx / (object[0].x1 - object[0].x0);
+  mxj = layout[0].axis[1].dfx / (object[0].y1 - object[0].y0);
+  myi = layout[0].axis[0].dfy / (object[0].x1 - object[0].x0);
+  myj = layout[0].axis[1].dfy / (object[0].y1 - object[0].y0);  
+ 
+  bxi  =  layout[0].axis[0].fx - object[0].x0*layout[0].axis[0].dfx/(object[0].x1 - object[0].x0);
+  bxj  =  -object[0].y0*layout[0].axis[1].dfx/(object[0].y1 - object[0].y0);
+  byi  =  -object[0].x0*layout[0].axis[0].dfy/(object[0].x1 - object[0].x0);
+  byj  =  layout[0].axis[1].fy - object[0].y0*layout[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 > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[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 > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[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 > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[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 > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[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 > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[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]);
+	  }
+      }
+    }
+    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 > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[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 > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[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 > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    DrawCircle (sx, sy, d*z[i]);
+	  }
+      }
+    }
+    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 > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[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 > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[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 > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[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 > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[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 > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    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 > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[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 > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[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 > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    DrawCircle (sx, sy, 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 bDrawXErrors (Layout *layout, Gobjects *object) {
+  
+  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 = layout[0].axis[0].dfx / (object[0].x1 - object[0].x0);
+  mxj = layout[0].axis[1].dfx / (object[0].y1 - object[0].y0);
+  myi = layout[0].axis[0].dfy / (object[0].x1 - object[0].x0);
+  myj = layout[0].axis[1].dfy / (object[0].y1 - object[0].y0);
+  
+  bxi  =  layout[0].axis[0].fx - object[0].x0*layout[0].axis[0].dfx/(object[0].x1 - object[0].x0);
+  bxj  =  -object[0].y0*layout[0].axis[1].dfx/(object[0].y1 - object[0].y0);
+  byi  =  -object[0].x0*layout[0].axis[0].dfy/(object[0].x1 - object[0].x0);
+  byj  =  layout[0].axis[1].fy - object[0].y0*layout[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*layout[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 > layout[0].axis[0].fx) && (sx0 < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	 (sy0 < layout[0].axis[1].fy) && (sy0 > layout[0].axis[1].fy + layout[0].axis[1].dfy)) ||
+	((sx1 > layout[0].axis[0].fx) && (sx1 < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	 (sy1 < layout[0].axis[1].fy) && (sy1 > layout[0].axis[1].fy + layout[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 > layout[0].axis[0].fx) && (sx0 < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	 (sy0 < layout[0].axis[1].fy) && (sy0 > layout[0].axis[1].fy + layout[0].axis[1].dfy)) ||
+	((sx1 > layout[0].axis[0].fx) && (sx1 < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	 (sy1 < layout[0].axis[1].fy) && (sy1 > layout[0].axis[1].fy + layout[0].axis[1].dfy)))
+      {
+	DrawLine (sx0, sy0, sx1, sy1);
+	if (bar) {
+	  sx10 = sy1 - sz;
+	  sx11 = sy1 + sz;
+	  DrawLine (sx1, sx10, sx1, sx11);
+	}
+      }
+  }
+}
+    
+/*******/
+void bDrawYErrors (Layout *layout, Gobjects *object) {
+  
+  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 = layout[0].axis[0].dfx / (object[0].x1 - object[0].x0);
+  mxj = layout[0].axis[1].dfx / (object[0].y1 - object[0].y0);
+  myi = layout[0].axis[0].dfy / (object[0].x1 - object[0].x0);
+  myj = layout[0].axis[1].dfy / (object[0].y1 - object[0].y0);
+  
+  bxi  =  layout[0].axis[0].fx - object[0].x0*layout[0].axis[0].dfx/(object[0].x1 - object[0].x0);
+  bxj  =  -object[0].y0*layout[0].axis[1].dfx/(object[0].y1 - object[0].y0);
+  byi  =  -object[0].x0*layout[0].axis[0].dfy/(object[0].x1 - object[0].x0);
+  byj  =  layout[0].axis[1].fy - object[0].y0*layout[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*layout[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 > layout[0].axis[0].fx) && (sx0 < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	 (sy0 < layout[0].axis[1].fy) && (sy0 > layout[0].axis[1].fy + layout[0].axis[1].dfy)) ||
+	((sx1 > layout[0].axis[0].fx) && (sx1 < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	 (sy1 < layout[0].axis[1].fy) && (sy1 > layout[0].axis[1].fy + layout[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 > layout[0].axis[0].fx) && (sx0 < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	 (sy0 < layout[0].axis[1].fy) && (sy0 > layout[0].axis[1].fy + layout[0].axis[1].dfy)) ||
+	((sx1 > layout[0].axis[0].fx) && (sx1 < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	 (sy1 < layout[0].axis[1].fy) && (sy1 > layout[0].axis[1].fy + layout[0].axis[1].dfy)))
+      {
+	DrawLine (sx0, sy0, sx1, sy1);
+	if (bar) {
+	  sx10 = sx1 - sz;
+	  sx11 = sx1 + sz;
+	  DrawLine (sx10, sy1, sx11, sy1);
+	}
+      }
+  }
+}
Index: /trunk/Ohana/src/kapa/graph/bDrawRotFont.c
===================================================================
--- /trunk/Ohana/src/kapa/graph/bDrawRotFont.c	(revision 5610)
+++ /trunk/Ohana/src/kapa/graph/bDrawRotFont.c	(revision 5610)
@@ -0,0 +1,201 @@
+# include "Ximage.h"
+# include "bDraw.h"
+# include "alphabet.h"
+
+# define XPROC(x,y) (scale*(cs*((x) - x0) - sn*((y) - y0)) + X0)
+# define YPROC(x,y) (scale*(cs*((y) - y0) + sn*((x) - x0)) + Y0)
+# define NEARINT(x) ((x < 0) ? ((int)(x - 0.5)) : ((int)(x + 0.5)))
+  
+static bDrawColor black;
+static bDrawColor white;
+
+int bDrawRotText (int x, int y, char *string, int pos, double angle) {
+
+  char *c, *bitmap, basefont[64];
+  int i, dy, dx, N, X, Y, code;
+  int dX, Xoff, dY, Yoff, YoffBase, basesize;
+  double cs, sn;
+
+  // return (TRUE);
+  white = GetColorByName ("white");
+  black = GetColorByName ("black");
+
+  /* strip leading whitespace */
+  for (c = string; (*c == ' ') || (*c == '\t'); c++);
+  if (*c == 0) return (FALSE);
+  
+  /* compute string length */
+  cs = cos(angle*RAD_DEG);
+  sn = sin(angle*RAD_DEG);
+  dX = RotStrlen (c);
+  dY = activefont[65].ascent;
+
+  /* apply appropriate offset */
+  Xoff = Yoff = 0;
+  switch (pos) {
+  case 0: Xoff =     -dX; Yoff = dY; break;
+  case 1: Xoff = -0.5*dX; Yoff = dY; break;
+  case 2: Xoff =       0; Yoff = dY; break;
+  case 3: Xoff =     -dX; Yoff = 0.5*dY; break;
+  case 4: Xoff = -0.5*dX; Yoff = 0.5*dY; break;
+  case 5: Xoff =       0; Yoff = 0.5*dY; break;
+  case 6: Xoff =     -dX; Yoff = 0; break;
+  case 7: Xoff = -0.5*dX; Yoff = 0; break;
+  case 8: Xoff =       0; Yoff = 0; break;
+  }
+
+  code = FALSE;
+
+  strcpy (basefont, currentname);
+  basesize = currentsize;
+
+  YoffBase = Yoff;
+  /* draw characters one-by-one */
+  for (i = 0; i < strlen(c); i++) {
+    N = (int)(c[i]);
+    if ((N < 0) || (N >= NROT)) continue;
+
+    /* check for special characters */
+    if (!code) {
+      if (N == 94) {
+	SetRotFont (currentname, (int)(0.8*currentsize));
+	Yoff -= 0.5*activescale*dY;
+	continue;
+      }
+      if (N == 95) { 
+	SetRotFont (currentname, (int)(0.8*currentsize));
+	Yoff += 0.5*activescale*dY;
+	continue;
+      }
+      if (N == 124) {
+	SetRotFont (currentname, basesize);
+	Yoff = YoffBase;
+	continue;
+      }
+      if (N == 92) {
+	code = TRUE;
+	continue;
+      } 
+      if (N == 38) {
+	if (c[i+1] == 'h') {
+	  SetRotFont ("helvetica", currentsize);
+	}
+	if (c[i+1] == 't') {
+	  SetRotFont ("times", currentsize);
+	}
+	if (c[i+1] == 'c') {
+	  SetRotFont ("courier", currentsize);
+	}
+	if (c[i+1] == 's') {
+	  SetRotFont ("symbol", currentsize);
+	}
+	i++;
+	continue;
+      }
+    }
+    code = FALSE;
+
+    bitmap = activefont[N].bits;
+    dx = activefont[N].dx;
+    dy = activefont[N].dy;
+    X = x + (int)(Xoff*cs - Yoff*sn) + (int)(activescale*activefont[N].ascent*sn);
+    Y = y + (int)(Xoff*sn + Yoff*cs) - (int)(activescale*activefont[N].ascent*cs);
+    bDrawRotBitmap (X, Y, dx, dy, bitmap, TRUE, angle, activescale);
+    Xoff += 1 + (int)(activescale*dx + 0.5);
+  }
+  SetRotFont (basefont, basesize);
+  return (TRUE);
+}
+
+int bDrawRotBitmap (int x, int y, int dx, int dy, char *bitmap, int mode, double angle, double scale) {
+
+  int ii, jj, byte_line, byte, bit, flag;
+  bDrawColor color;
+  double i, j, cs, sn, rscale, tmp;
+  int X, Y, X0, X1, X2, Y0, Y1, Y2, x0, y0;
+
+  /* this mode option is nort actually used... */
+  if (mode) {
+    color = black;
+  } else {
+    color = white;
+  } 
+    
+  byte_line = (int) ((dx + 7) / 8);
+
+  cs = cos(angle*RAD_DEG);  sn = sin(angle*RAD_DEG);
+  rscale = 1.0 / scale;
+
+  X0 = 0;
+  Y0 = 0;
+  x0 = 0;
+  y0 = 0;
+
+  X2 = X1 = XPROC (0,0);
+  Y2 = Y1 = YPROC (0,0);
+
+  X = XPROC (dx,0);
+  Y = YPROC (dx,0);
+# ifdef DRAWBOXES
+  bDrawLine (x+X, y+Y, x+X1, y+Y1, FALSE);
+  Xt = X;
+  Yt = Y;
+# endif
+  X1 = MIN (X, X1);
+  X2 = MAX (X, X2);
+  Y1 = MIN (Y, Y1);
+  Y2 = MAX (Y, Y2);
+
+  X = XPROC (dx,dy);
+  Y = YPROC (dx,dy);
+# ifdef DRAWBOXES
+  bDrawLine (x+X, y+Y, x+Xt, y+Yt, FALSE);
+  Xt = X;
+  Yt = Y;
+# endif
+  Y1 = MIN (Y, Y1);
+  Y2 = MAX (Y, Y2);
+  X1 = MIN (X, X1);
+  X2 = MAX (X, X2);
+
+  X = XPROC (0,dy);
+  Y = YPROC (0,dy);
+# ifdef DRAWBOXES
+  bDrawLine (x+X, y+Y, x+Xt, y+Yt, FALSE);
+  Xt = X;
+  Yt = Y;
+# endif
+  Y1 = MIN (Y, Y1);
+  Y2 = MAX (Y, Y2);
+  X1 = MIN (X, X1);
+  X2 = MAX (X, X2);
+
+  bDrawSetStyle (color, 0, 0);
+  if (scale > 1) {
+    for (i = X1; i <= X2; i+=1) {
+      for (j = Y1; j <= Y2; j+=1) {
+	tmp = rscale*(cs*(i - X0) + sn*(j - Y0)) + x0;  ii = NEARINT (tmp);
+	tmp = rscale*(cs*(j - Y0) - sn*(i - X0)) + y0;  jj = NEARINT (tmp);
+	if ((ii < 0) || (ii >= dx) || (jj < 0) || (jj >= dy)) continue;
+	byte = byte_line * jj + (ii / 8);
+	bit = ii % 8;
+	flag = 0x01 & (bitmap[byte] >> bit);
+	if (flag) bDrawPointf (x + i, y + j);
+      }
+    }
+  } else {
+    for (i = X1; i <= X2; i+=scale) {
+      for (j = Y1; j <= Y2; j+=scale) {
+	tmp = rscale*(cs*(i - X0) + sn*(j - Y0)) + x0;  ii = NEARINT (tmp);
+	tmp = rscale*(cs*(j - Y0) - sn*(i - X0)) + y0;  jj = NEARINT (tmp);
+	if ((ii < 0) || (ii >= dx) || (jj < 0) || (jj >= dy)) continue;
+	byte = byte_line * jj + (ii / 8);
+	bit = ii % 8;
+	flag = 0x01 & (bitmap[byte] >> bit);
+	if (flag) bDrawPointf (x + i, y + j);
+      }
+    }
+  }
+  bDrawSetStyle (black, 0, 0);
+  return (TRUE);
+}
Index: /trunk/Ohana/src/kapa/include/alphabet.h
===================================================================
--- /trunk/Ohana/src/kapa/include/alphabet.h	(revision 5609)
+++ /trunk/Ohana/src/kapa/include/alphabet.h	(revision 5610)
@@ -61,4 +61,5 @@
 };
 
+/* put these as static in RotFont.c with accessor functions */
 int Nallfonts;
 FontSet *AllFonts;
@@ -68,2 +69,3 @@
 char currentname[64];
 int  currentsize;
+# define NROT 256
Index: /trunk/Ohana/src/kapa/include/bDraw.h
===================================================================
--- /trunk/Ohana/src/kapa/include/bDraw.h	(revision 5610)
+++ /trunk/Ohana/src/kapa/include/bDraw.h	(revision 5610)
@@ -0,0 +1,41 @@
+# include <png.h>
+
+typedef png_byte bDrawColor;
+
+typedef struct {
+  int Nx, Ny;
+  bDrawColor **pixels;
+} bDrawBuffer;
+
+int bDrawObjects (Layout *layout);
+void bDrawConnect (Layout *layout, Gobjects *object);
+void bDrawClipLine (double x0, double y0, double x1, double y1, double X0, double Y1, double X1, double Y0);
+void bDrawHistogram (Layout *layout, Gobjects *object);
+void bDrawPoints (Layout *layout, Gobjects *object);
+void bDrawXErrors (Layout *layout, Gobjects *object);
+void bDrawYErrors (Layout *layout, Gobjects *object);
+
+int bDrawFrame (Layout *layout);
+void bDrawTick (double fx, double fy, double dfx, double dfy, int P, double min, double max, double value, int mode, int naxis);
+void bDrawLabels (Layout *layout);
+void bDrawPtext (Layout *layout);
+
+bDrawBuffer *bDrawBufferCreate (int Nx, int Ny);
+void bDrawBufferFree (bDrawBuffer *buffer);
+void bDrawSetBuffer (bDrawBuffer *buffer);
+void bDrawSetStyle (bDrawColor color, int lw, int lt);
+void bDrawPoint (int x, int y);
+void bDrawPointf (float x, float y);
+void bDrawLine (double x1, double y1, double x2, double y2, int swapcoords);
+void bDrawArc (double Xc, double Yc, double Xr, double Yr, double Ts, double Te);
+void bDrawCircle (double Xc, double Yc, double radius);
+png_color *MakePNGPalette (int *Npalette);
+bDrawColor GetColorByName (char *name);
+bDrawBuffer *bDrawIt ();
+
+void bDrawRectOpen (int x1, int y1, int x2, int y2);
+void bDrawRectFill (int x1, int y1, int x2, int y2);
+void bDrawTriOpen (int x1, int y1, int x2, int y2, int x3, int y3);
+void bDrawTriFill (int x1, int y1, int x2, int y2, int x3, int y3);
+int bDrawRotText (int x, int y, char *string, int pos, double angle);
+int bDrawRotBitmap (int x, int y, int dx, int dy, char *bitmap, int mode, double angle, double scale);
Index: /trunk/Ohana/src/kapa/setup/MakeColormap.c
===================================================================
--- /trunk/Ohana/src/kapa/setup/MakeColormap.c	(revision 5609)
+++ /trunk/Ohana/src/kapa/setup/MakeColormap.c	(revision 5610)
@@ -1,3 +1,4 @@
 # include "Ximage.h"
+# include "bDraw.h"
 
 /* this list must match the one in mana/include/package.h, and equiv
@@ -42,4 +43,23 @@
 }
 
+png_color *MakePNGPalette (int *Npalette) {
+
+  int i;
+  float red, green, blue;
+  png_color *palette;
+
+  ALLOCATE (palette, png_color, NGRAPHCOLORS);
+
+  /* define the palette */
+  for (i = 0; i < NGRAPHCOLORS; i++) {
+    sscanf (GRAPHCOLORS[i][1], "%f %f %f", &red, &green, &blue);
+    palette[i].red = (0xff * red);
+    palette[i].green = (0xff * green);
+    palette[i].blue = (0xff * blue);
+  }
+  *Npalette = NGRAPHCOLORS;
+  return (palette);
+}
+
 void MakeColormap (int argc, char **argv) {
 
@@ -54,2 +74,20 @@
   }
 }
+
+/* default to black */
+bDrawColor GetColorByName (char *name) {
+
+  bDrawColor i;
+
+  for (i = 0; i < NGRAPHCOLORS; i++) {
+    if (!strcasecmp (name, GRAPHCOLORS[i][0])) return (i);
+  }
+  return (0);
+}
+
+/*
+
+kapa objects, bDraw, and png all use the same pallete sequence, defined by
+GRAPHCOLORS above.  the color correspond to a color sequence.  
+
+*/
