Index: /trunk/Ohana/src/addstar/src/find_matches_closest_refstars.c
===================================================================
--- /trunk/Ohana/src/addstar/src/find_matches_closest_refstars.c	(revision 27789)
+++ /trunk/Ohana/src/addstar/src/find_matches_closest_refstars.c	(revision 27790)
@@ -159,5 +159,8 @@
     /** in replace mode, search for entry and replace values M, dM, R, D */
     // XXX this fails for unsorted catalogs, right?
-    if (options.replace && replace_match (&catalog[0].average[n], catalog[0].measure, stars[N])) continue;
+    if (options.replace && replace_match (&catalog[0].average[n], catalog[0].measure, stars[N])) {
+	i++;
+	continue;
+    }
 
     /* make sure there is space for next entry */
Index: /trunk/Ohana/src/kapa2/doc/mark.issues.txt
===================================================================
--- /trunk/Ohana/src/kapa2/doc/mark.issues.txt	(revision 27789)
+++ /trunk/Ohana/src/kapa2/doc/mark.issues.txt	(revision 27790)
@@ -1,8 +1,13 @@
+
+* option to set window margin
+* option to add section outer box
+* option to set limits based on associated image (and change dynamically...)
+o need consistency of graph defaults : axis, tick, labels should come from kapa
+o clear should erase current plot
+
 -> The "plot" command needs to be fixed so that boundaries of contours do
 not cause it to draw excessive amounts of lines connecting unrelated
 contours. A specific "contour line type" would be useful.
-
--> DVO is not consistently placing the x/y axis labels, especially in
-user-defined sections of the plot window.
+(-pt 100?)
 
 -> DVO does not plot the end-points of histograms properly (e.g., the
@@ -13,3 +18,47 @@
 relay output to the file in the same order. Also, until DVO is closed, the
 output does not appear in the file.
+(fixed both issues)
 
+-> DVO is not consistently placing the x/y axis labels, especially in
+user-defined sections of the plot window. 
+(fixed)
+* box -labelpad -labelpad[x,y] +labelpad[x,y] -
+
+
+---
+
+
+1)You wanted me to remind you to update ~ipp-svn; this was so I could have
+the latest version of DVO on-hand
+
+2)The plotting of axis labels remains inconsistent; depending on section
+dimensions and the presence/absence of tick-marks, labels will change
+their distance from their corresponding axis. This results in labels
+falling off the screen or overlapping with other plot sections
+
+3)Plot section locations in the plot window shift if labels/tick-marks are
+present or absent
+
+4)It would be useful to have an option for the box or section command that
+causes the background to be opaque. This will allow plots to have insets.
+
+5)It would be useful to have a rectangle plotting command in order to
+shade out regions on plots
+
+6)The limits command combined with box will sometimes produce tick-marks
+with only the zero-point labeled, making the axes difficult to interpret
+
+7)Text is printed to a file at different times when using either the echo
+or fprintf commands alongside the output command. Sometimes output is
+printed to the file immediately, while other times it is printed only when
+the file is closed for output.
+
+8)The use of ^C as an interrupt does not always work when a macro is doing
+for loops.
+
+9)It would be useful for DVO to echo which line of a macro contains an
+error, or at which line it was forced to stop. This would help debugging a
+lot.
+
+10)The cgrid could use an option to print RA/DEC tick-mark labels so that
+image plots would be more informative
Index: /trunk/Ohana/src/kapa2/doc/notes.txt
===================================================================
--- /trunk/Ohana/src/kapa2/doc/notes.txt	(revision 27790)
+++ /trunk/Ohana/src/kapa2/doc/notes.txt	(revision 27790)
@@ -0,0 +1,8 @@
+
+2010.04.14
+
+  * one font per frame
+  * user-settable box padding
+  * user-settable label & axis-label padding
+
+  
Index: /trunk/Ohana/src/kapa2/include/prototypes.h
===================================================================
--- /trunk/Ohana/src/kapa2/include/prototypes.h	(revision 27789)
+++ /trunk/Ohana/src/kapa2/include/prototypes.h	(revision 27790)
@@ -26,5 +26,5 @@
 
 /* X drawing utilities */
-void	      DrawFrame		  PROTO((KapaGraphWidget *graph));
+int	      DrawFrame		  PROTO((KapaGraphWidget *graph));
 int           DrawObjects         PROTO((KapaGraphWidget *graph));
 void          DrawLabels          PROTO((KapaGraphWidget *graph));
@@ -39,6 +39,7 @@
 void          DrawXErrors         PROTO((KapaGraphWidget *graph, Gobjects *objects));
 void          DrawYErrors         PROTO((KapaGraphWidget *graph, Gobjects *objects));
-void	      DrawTick		  PROTO((int fx, int fy, int dfx, int dfy, int P, double min, double max, double value, int IsLabel, int IsMajor, int naxis));
+void	      DrawTick		  PROTO((Graphic *graphic, Axis *axis, int P, TickMarkData *tick, int naxis));
 void	      AxisTickScale	  PROTO((Axis *axis, double *major, double *minor));
+TickMarkData *CreateAxisTicks     PROTO((Axis *axis, int *nticks));
 
 /* EventLoop */
@@ -47,4 +48,5 @@
 int           Reconfig            PROTO((XEvent *event));
 void          Refresh             PROTO((void));
+void          DrawSectionBG       PROTO((Graphic *graphic, Section *section));
 
 /* CheckPipe */
@@ -61,4 +63,5 @@
 int           SetSection          PROTO((int sock));
 int           ListSection         PROTO((int sock));
+int           SetSectionBG        PROTO((int sock));
 int           MoveSection         PROTO((int sock));
 int           DefineSection       PROTO((int sock));
@@ -84,5 +87,5 @@
 void          FreeSection	  PROTO((Section *section));
 void          FreeSections	  PROTO((void));
-Section      *AddSection	  PROTO((char *name, float x, float y, float dx, float dy));
+Section      *AddSection	  PROTO((char *name, float x, float y, float dx, float dy, int bg));
 int           DelSection	  PROTO((char *name));
 int           GetSectionByName	  PROTO((char *name));
@@ -112,5 +115,5 @@
 void          PSXErrors           PROTO((KapaGraphWidget *graph, Gobjects *objects, FILE *f));
 void          PSYErrors           PROTO((KapaGraphWidget *graph, Gobjects *objects, FILE *f));
-void	      PSTick		  PROTO((FILE *f, double fx, double fy, double dfx, double dfy, int P, double min, double max, double value, int IsLabel, int IsMajor, int naxis));
+void	      PSTick		  PROTO((Graphic *graphic, Axis *axis, int P, TickMarkData *tick, int naxis, FILE *f));
 void          ClipLinePS          PROTO((double x0, double y0, double x1, double y1, double X0, double Y1, double X1, double Y0, FILE *f));
 int           PSimage    	  PROTO((KapaImageWidget *image, FILE *f));
@@ -131,5 +134,5 @@
 void	      bDrawXErrors	  PROTO((KapaGraphWidget *graph, Gobjects *object));
 void	      bDrawYErrors	  PROTO((KapaGraphWidget *graph, Gobjects *object));
-void	      bDrawTick		  PROTO((double fx, double fy, double dfx, double dfy, int P, double min, double max, double value, int IsLabel, int IsMajor, int naxis));
+void	      bDrawTick		  PROTO((Axis *axis, int P, TickMarkData *tick, int naxis));
 void	      bDrawClipLine	  PROTO((double x0, double y0, double x1, double y1, double X0, double Y1, double X1, double Y0));
 bDrawBuffer  *bDrawIt		  PROTO((void));
Index: /trunk/Ohana/src/kapa2/include/structures.h
===================================================================
--- /trunk/Ohana/src/kapa2/include/structures.h	(revision 27789)
+++ /trunk/Ohana/src/kapa2/include/structures.h	(revision 27790)
@@ -137,8 +137,16 @@
   double min, max;
   char isaxis, areticks, islabel, islog;
+  double pad, labelPad, ticktextPad;
   double fx, dfx, fy, dfy;  /* axis location on graphic */
   double lweight;
   int color;
 } Axis;
+
+// structure to describe the ticks for an axis
+typedef struct {
+  double value;
+  int IsMajor;
+  int IsLabel;
+} TickMarkData;
 
 // a single graph in the display window
@@ -210,4 +218,5 @@
   float  x,  y;
   float dx, dy;
+  int bg;
   char *name;
 } Section;
Index: /trunk/Ohana/src/kapa2/src/CheckPipe.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/CheckPipe.c	(revision 27789)
+++ /trunk/Ohana/src/kapa2/src/CheckPipe.c	(revision 27790)
@@ -221,4 +221,10 @@
   }
   
+  if (!strcmp (word, "BSEC")) {
+    status = SetSectionBG (sock);
+    KiiSendCommand (sock, 4, "DONE");
+    FINISHED (TRUE);
+  }
+  
   if (!strcmp (word, "FONT")) {
     status = SetFont (sock);
Index: /trunk/Ohana/src/kapa2/src/DefineSection.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/DefineSection.c	(revision 27789)
+++ /trunk/Ohana/src/kapa2/src/DefineSection.c	(revision 27790)
@@ -4,10 +4,10 @@
 int DefineSection (int sock) {
   
-  int N, MoveSection;
+  int N, MoveSection, bg;
   char name[128];
   double x, y, dx, dy;
   Section *section;
 
-  KiiScanMessage (sock, "%s %lf %lf %lf %lf", name, &x, &y, &dx, &dy);
+  KiiScanMessage (sock, "%s %lf %lf %lf %lf %d", name, &x, &y, &dx, &dy, &bg);
 
   MoveSection = FALSE;
@@ -15,5 +15,5 @@
   N = GetSectionByName (name);
   if (N < 0) {
-    section = AddSection (name, x, y, dx, dy);
+    section = AddSection (name, x, y, dx, dy, bg);
     MoveSection = TRUE;
   } else {
@@ -30,4 +30,5 @@
     section[0].dx = dx;
     section[0].dy = dy;
+    section[0].bg = bg;
   }
 
Index: /trunk/Ohana/src/kapa2/src/DrawFrame.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/DrawFrame.c	(revision 27789)
+++ /trunk/Ohana/src/kapa2/src/DrawFrame.c	(revision 27790)
@@ -1,90 +1,65 @@
 # include "Ximage.h"
-# define MIN_RANGE 1e-10
 # define DrawLine(X,Y,DX,DY) (XDrawLine (graphic->display, graphic->window, graphic->gc, (int)(X), (int)(Y), (int)(X+DX), (int)(Y+DY)))
   
-static Graphic *graphic;
-
-void DrawFrame (KapaGraphWidget *graph) {
-  
-  int i, fx, fy, dfx, dfy, P, IsLabel, IsMajor;
-  double range, major, minor, first, next, lweight;
+int DrawFrame (KapaGraphWidget *graph) {
+  
+  int i, j, Nticks, P;
+  double fx, fy, dfx, dfy, lweight;
+  Graphic *graphic;
+  TickMarkData *ticks;
+  int color;
 
   graphic = GetGraphic();
 
-  /* each axis is drawn independently, but ticks and labels are placed according to
-     perpendicular distance. */
+  /* each axis is drawn independently, but ticks and labels are placed according to perpendicular distance. */
   for (i = 0; i < 4; i++) {
-    fx = graph[0].axis[i].fx;
-    fy = graph[0].axis[i].fy;
+    fx  = graph[0].axis[i].fx;
+    fy  = graph[0].axis[i].fy;
     dfx = graph[0].axis[i].dfx;
     dfy = graph[0].axis[i].dfy;
-    P = hypot ((double)graph[0].axis[(i+1)%2].dfx, (double)graph[0].axis[(i+1)%2].dfy);
+    P = hypot (graph[0].axis[(i+1)%2].dfx, graph[0].axis[(i+1)%2].dfy);
 
     lweight = MAX (0, MIN (10, graph[0].axis[i].lweight));
+    color = MAX (0, MIN (15, graph[0].axis[i].color));
+
     XSetLineAttributes (graphic->display, graphic->gc, lweight, LineSolid, CapNotLast, JoinMiter);
-    
-    graph[0].axis[i].color = MAX (0, MIN (15, graph[0].axis[i].color));
-
-    XSetForeground (graphic->display, graphic->gc, graphic->color[graph[0].axis[i].color]);
-    DrawRotTextInit (graphic->display, graphic->window, graphic->gc, graphic->color[graph[0].axis[i].color], graphic->back);
-
-    // fprintf (stderr, "axis: %d, color: %d, %ld, weight: %f\n", i, graph[0].axis[i].color, graphic->color[graph[0].axis[i].color], lweight);
+    XSetForeground (graphic->display, graphic->gc, graphic->color[color]);
+    DrawRotTextInit (graphic->display, graphic->window, graphic->gc, graphic->color[color], graphic->back);
 
     if (graph[0].axis[i].isaxis) {
       DrawLine (fx, fy, dfx, dfy);
-      // fprintf (stderr, "%d : %d %d - %d %d\n", i, fx, fy, dfx, dfy);
-      // if (i == 0) {
-      // 	int j;
-      // 	for (j = fx; j < fx + dfx; j+= 10) {
-      // 	  DrawLine (j, fy-10, 0, 20);
-      // 	}
-      // }
     }
     
     if (graph[0].axis[i].areticks) {
-      if (isnan(graph[0].axis[i].min) || isinf(graph[0].axis[i].min)) continue;
-      if (isnan(graph[0].axis[i].max) || isinf(graph[0].axis[i].max)) continue;
-
-      range = graph[0].axis[i].max - graph[0].axis[i].min;
-      if (fabs(range) < MIN_RANGE) continue;
-
-      if (fabs(range) < MIN_RANGE) {
-	range = (range < 0) ? -MIN_RANGE : +MIN_RANGE;
+      ticks = CreateAxisTicks (&graph[0].axis[i], &Nticks);
+      for (j = 0; j < Nticks; j++) {
+	DrawTick (graphic, &graph[0].axis[i], P, &ticks[j], i);
       }
-
-      AxisTickScale (&graph[0].axis[i], &major, &minor);
-
-      first = minor*((int)(graph[0].axis[i].min/minor));
-      if ((range > 0) && (first < graph[0].axis[i].min)) {
-	first += minor;
-      }
-      if ((range < 0) && (first > graph[0].axis[i].min)) {
-	first -= minor;
-      }
-      for (next = first; ((range > 0) && (next <= graph[0].axis[i].max)) || ((range < 0) && (next >= graph[0].axis[i].max));) {
-	IsMajor = FALSE;
-	IsMajor |= (fabs((int)(next/major) - (next/major)) < 0.5*(minor/major));
-	IsMajor |= (fabs((int)((next + 0.5*minor)/major) - (next/major)) < 0.5*(minor/major));
-	IsMajor |= (fabs ((int)((next - 0.5*minor)/major) - (next/major)) < 0.5*(minor/major));
-	IsLabel = (IsMajor && graph[0].axis[i].islabel);
-	DrawTick (fx, fy, dfx, dfy, P, graph[0].axis[i].min, graph[0].axis[i].max, next, IsLabel, IsMajor, i);
-	if (range > 0) 
-	  next += minor;
-	else 
-	  next -= minor;
-      }
+      FREE (ticks);
     }
   }
-}
-
-void DrawTick (int fx, int fy, int dfx, int dfy, 
-	       int P, double min, double max, 
-	       double value, int IsLabel, int IsMajor, int naxis) {
-  
-  int x, y, dx, dy, pos, dir, fontsize;
-  double size, n;
+  return (TRUE);
+}
+
+void DrawTick (Graphic *graphic, Axis *axis, int P, TickMarkData *tick, int naxis) {
+  
+  double x, y, dx, dy;
+  int pos, dir, fontsize;
+  double size, n, pad;
   char string[64], *fontname;
 
-  if (IsMajor) { 
+  double fx  = axis->fx;
+  double fy  = axis->fy;
+  double dfx = axis->dfx;
+  double dfy = axis->dfy;
+
+  double min = axis->min;
+  double max = axis->max;
+
+  double value = tick->value;
+
+  pos = size = 0;
+
+  if (tick->IsMajor) { 
     size = MAX (0.02, 7.0 / P); 
   } else {
@@ -92,10 +67,15 @@
   }
   
-  n = P / sqrt ((double)(dfx*dfx + dfy*dfy));
+  n = P / hypot(dfx, dfy);
   x = fx + (value-min)*dfx/(max - min);
   y = fy + (value-min)*dfy/(max - min);
 
-  dir = +1;
-  if ((naxis == 0) || (naxis == 1)) dir *= -1;
+  if ((naxis == 0) || (naxis == 2)) {
+    x = MAX(x, fx);
+  }
+  //   y = MAX(y, fy);
+  // }
+
+  dir = ((naxis == 0) || (naxis == 1)) ? -1 : +1;
   dx = dir*size*dfy*n;	
   dy = dir*size*dfx*n;
@@ -103,30 +83,28 @@
   DrawLine (x, y, dx, dy);
 
-# ifdef IN_AND_OUT_TICKS
-# define GAP 0.03
-# else
-# define GAP 0.01
-# endif
-
-  if (IsLabel) {
+  if (tick->IsLabel) {
+    int xt, yt;
+
     fontname = GetRotFont (&fontsize);
-    pos = 0;
+    
+    pad = isfinite(axis->ticktextPad) ? axis->ticktextPad*fontsize : fontsize + 4.0;
+    // pad = isfinite(axis->ticktextPad) ? axis->ticktextPad*fontsize : 0.8*fontsize + 1.0;
     
     /* 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 (naxis == 0) { dx = 0; dy = +1.0*pad; pos = 7; }
+    if (naxis == 2) { dx = 0; dy = -1.0*pad; pos = 1; }
+
+    if (naxis == 1) { dy = 0; dx = -0.5*pad; pos = 3; }
+    if (naxis == 3) { dy = 0; dx = +0.5*pad; pos = 5; }
+
+    xt = fx + (value-min)*dfx/(max - min) + dx;
+    yt = fy + (value-min)*dfy/(max - min) + dy;
     if (fabs(value/(max-min)) < 0.001) { value = 0.0; }
     sprintf (string, "%4g", value);
-    DrawRotText (x, y, string, pos, 0.0);
-  }
-  
-}
-
+    DrawRotText (xt, yt, string, pos, 0.0);
+  }
+}
+
+# define MIN_RANGE 1e-10
 
 void AxisTickScale (Axis *axis, double *major, double *minor) {
@@ -192,2 +170,69 @@
   }
 }
+
+TickMarkData *CreateAxisTicks (Axis *axis, int *nticks) {
+
+  TickMarkData *ticks;
+  double range, major, minor, first, value, dPixels, overshoot;
+  int i, NTICKS, nPixels, done, ifirst;
+
+  *nticks = 0;
+
+  if (isnan(axis->min) || isinf(axis->min)) return NULL;
+  if (isnan(axis->max) || isinf(axis->max)) return NULL;
+  
+  range = axis->max - axis->min;
+
+  // not sure why I skip out here instead of using the MIN_RANGE value
+  if (fabs(range) < MIN_RANGE) return NULL;
+  
+  if (fabs(range) < MIN_RANGE) {
+    range = (range < 0) ? -MIN_RANGE : +MIN_RANGE;
+  }
+
+  // length of the axis in pixels
+  nPixels = hypot(axis->dfx, axis->dfy);
+  dPixels = nPixels / range; // axis pixel-scale
+
+  AxisTickScale (axis, &major, &minor);
+
+  // be a little generous 
+  NTICKS = (int)(fabs(range / minor)) + 2;
+  ALLOCATE (ticks, TickMarkData, NTICKS);
+
+  // value of the tick mark
+  ifirst = (axis->min < 0.0) ? (axis->min/minor - 0.05) : (axis->min/minor + 0.05);
+  first = minor*ifirst;
+  
+  // allow undershoot by 1 pixel
+  overshoot = (axis->min - first) * dPixels;
+  // if (overshoot > 0.5) {
+  //   if (range > 0) {
+  //     first += minor;
+  //   } else {
+  //     first -= minor;
+  //   }
+  // }
+
+  // loop to find the ticks
+  done = FALSE;
+  value = first; 
+  for (i = 0; !done && (i < NTICKS); i++) {
+    ticks[i].IsMajor = FALSE;
+    ticks[i].IsMajor |= (fabs((int)(value/major) - (value/major)) < 0.5*(minor/major));
+    ticks[i].IsMajor |= (fabs((int)((value + 0.5*minor)/major) - (value/major)) < 0.5*(minor/major));
+    ticks[i].IsMajor |= (fabs((int)((value - 0.5*minor)/major) - (value/major)) < 0.5*(minor/major));
+    ticks[i].IsLabel = (ticks[i].IsMajor && axis->islabel);
+    ticks[i].value = value;
+    if (range > 0) 
+      value += minor;
+    else 
+      value -= minor;
+    
+    done |= (range > 0) && (value > axis->max);
+    done |= (range < 0) && (value < axis->max);
+  }
+
+  *nticks = i;
+  return (ticks);
+}
Index: /trunk/Ohana/src/kapa2/src/DrawLabels.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/DrawLabels.c	(revision 27789)
+++ /trunk/Ohana/src/kapa2/src/DrawLabels.c	(revision 27790)
@@ -34,6 +34,6 @@
       switch (i) {
       case 0: pos = 7; break;
+      case 2: pos = 1; 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;
Index: /trunk/Ohana/src/kapa2/src/EraseSections.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/EraseSections.c	(revision 27789)
+++ /trunk/Ohana/src/kapa2/src/EraseSections.c	(revision 27790)
@@ -8,5 +8,5 @@
   
   FreeSections ();
-  AddSection ("default", 0.0, 0.0, 1.0, 1.0);
+  AddSection ("default", 0.0, 0.0, 1.0, 1.0, -1);
 
   if (USE_XWINDOW) XClearWindow (graphic->display, graphic->window);
Index: /trunk/Ohana/src/kapa2/src/Graphs.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/Graphs.c	(revision 27789)
+++ /trunk/Ohana/src/kapa2/src/Graphs.c	(revision 27790)
@@ -18,5 +18,20 @@
     graph[0].axis[i].lweight = 0.0;
     graph[0].axis[i].color = 0;
+    graph[0].axis[i].ticktextPad = NAN;
+    graph[0].axis[i].labelPad = NAN;
+    graph[0].axis[i].pad = NAN;
   }    
+  graph[0].data.ticktextPad = NAN;
+
+  graph[0].data.labelPadXm = NAN;
+  graph[0].data.labelPadXp = NAN;
+  graph[0].data.labelPadYm = NAN;
+  graph[0].data.labelPadYp = NAN;
+
+  graph[0].data.padXm = NAN;
+  graph[0].data.padXp = NAN;
+  graph[0].data.padYm = NAN;
+  graph[0].data.padYp = NAN;
+
   for (i = 0; i < 8; i++) {
     strcpy (graph[0].label[i].text, "");
@@ -37,6 +52,18 @@
   graph[0].data.size    = 1.0;		// point size of 1.0
 
-  graph[0].data.flipeast  = 1;		// +East  = -X by default
-  graph[0].data.flipnorth = 0;		// +North = +Y by default
+  graph[0].data.flipeast = TRUE;	// +East  = -X by default
+  graph[0].data.flipnorth = FALSE;	// +North = +Y by default
+
+  graph[0].data.coords.pc1_1 = graph[0].data.coords.pc2_2 = 1.0;
+  graph[0].data.coords.pc1_2 = graph[0].data.coords.pc2_1 = 0.0;
+  graph[0].data.coords.crval1 = 0.0;
+  graph[0].data.coords.crval2 = 0.0;
+  graph[0].data.coords.crpix1 = 0.0;
+  graph[0].data.coords.crpix2 = 0.0;
+  graph[0].data.coords.cdelt1 = graph[0].data.coords.cdelt2 = 1.0;
+  strcpy (graph[0].data.coords.ctype, "RA---LIN");
+  strcpy (graph[0].data.axis, "2222");
+  strcpy (graph[0].data.ticks, "2222");
+  strcpy (graph[0].data.labels, "2222");
 
   graph[0].Nobjects = 0;
Index: /trunk/Ohana/src/kapa2/src/Layout.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/Layout.c	(revision 27789)
+++ /trunk/Ohana/src/kapa2/src/Layout.c	(revision 27790)
@@ -43,4 +43,4 @@
 
   /* create basic section, empty of image or graph */
-  section = AddSection ("default", 0.0, 0.0, 1.0, 1.0);
+  section = AddSection ("default", 0.0, 0.0, 1.0, 1.0, -1);
 }
Index: /trunk/Ohana/src/kapa2/src/LoadFrame.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/LoadFrame.c	(revision 27789)
+++ /trunk/Ohana/src/kapa2/src/LoadFrame.c	(revision 27790)
@@ -3,7 +3,5 @@
 int LoadFrame (int sock) {
   
-  int i, color;
-  char Axis[16], Labels[16], Ticks[16];
-  double lweight;
+  int i;
   Section *section;
   KapaGraphWidget *graph;
@@ -16,7 +14,5 @@
   graph = section->graph;
 
-  KiiScanMessage (sock, "%lf %lf %lf %lf", 
-		  &graph[0].axis[0].min, &graph[0].axis[0].max, 
-		  &graph[0].axis[1].min, &graph[0].axis[1].max);
+  KapaScanGraphData (sock, &graph[0].data);
 
   graph[0].axis[3].min = graph[0].axis[1].min;
@@ -25,14 +21,24 @@
   graph[0].axis[2].max = graph[0].axis[0].max;
   
-  KiiScanMessage (sock, "%lf %d", &lweight, &color);
-  color = MAX (0, MIN (15, color));
+  // XXX this is fragile
+  graph[0].data.color = MAX (0, MIN (15, graph[0].data.color));
 
-  KiiScanMessage (sock, "%s %s %s", Axis, Labels, Ticks);
+  graph[0].axis[0].pad = graph[0].data.padXm;
+  graph[0].axis[1].pad = graph[0].data.padYm;
+  graph[0].axis[2].pad = graph[0].data.padXp;
+  graph[0].axis[3].pad = graph[0].data.padYp;
+
+  graph[0].axis[0].labelPad = graph[0].data.labelPadXm;
+  graph[0].axis[1].labelPad = graph[0].data.labelPadYm;
+  graph[0].axis[2].labelPad = graph[0].data.labelPadXp;
+  graph[0].axis[3].labelPad = graph[0].data.labelPadYp;
 
   for (i = 0; i < 4; i++) {
-    graph[0].axis[i].lweight = lweight;
-    graph[0].axis[i].color = color;
+    graph[0].axis[i].lweight = graph[0].data.lweight;
+    graph[0].axis[i].color = graph[0].data.color;
 
-    switch (Axis[i]) {
+    graph[0].axis[i].ticktextPad = graph[0].data.ticktextPad;
+
+    switch (graph[0].data.axis[i]) {
     case '0':
       graph[0].axis[i].isaxis = FALSE;
@@ -45,5 +51,5 @@
       break;
     }
-    switch (Ticks[i]) {
+    switch (graph[0].data.ticks[i]) {
     case '0':
       graph[0].axis[i].areticks = FALSE;
@@ -56,5 +62,5 @@
       break;
     }
-    switch (Labels[i]) {
+    switch (graph[0].data.labels[i]) {
     case '0':
       graph[0].axis[i].islabel = FALSE;
@@ -70,6 +76,7 @@
 
   SetSectionSizes (section);
-  if (USE_XWINDOW) DrawFrame (graph);
-  FlushDisplay ();
+  Refresh();
+  // if (USE_XWINDOW) DrawFrame (graph);
+  // FlushDisplay ();
 
   /* XXX why did I do this??? */
Index: /trunk/Ohana/src/kapa2/src/PSFrame.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/PSFrame.c	(revision 27789)
+++ /trunk/Ohana/src/kapa2/src/PSFrame.c	(revision 27790)
@@ -4,9 +4,8 @@
 int PSFrame (KapaGraphWidget *graph, FILE *f) {
   
-  int i, P, IsLabel, IsMajor, fontsize;
-  double fx, fy, dfx, dfy, range, major, minor, first, next;
-  char *fontname;
+  int i, Nticks, P;
+  double fx, fy, dfx, dfy, lweight;
   Graphic *graphic;
-  float weight;
+  TickMarkData *ticks;
   bDrawColor color;
 
@@ -14,60 +13,54 @@
 
   /* each axis is drawn independently */
-  fontname = GetRotFont (&fontsize);
   fprintf (f, "1 setlinewidth\n");
   for (i = 0; i < 4; i++) {
-    fx = graph[0].axis[i].fx;
-    fy = graphic->dy - graph[0].axis[i].fy;
+    fx  = graph[0].axis[i].fx;
+    fy  = graphic->dy - graph[0].axis[i].fy;
     dfx = graph[0].axis[i].dfx;
     dfy = -graph[0].axis[i].dfy;
-    P = hypot ((double)graph[0].axis[(i+1)%2].dfx, (double)graph[0].axis[(i+1)%2].dfy);
+    P = hypot (graph[0].axis[(i+1)%2].dfx, graph[0].axis[(i+1)%2].dfy);
 
-    weight = MAX (0, MIN (10, graph[0].axis[i].lweight));
+    lweight = MAX (0, MIN (10, graph[0].axis[i].lweight));
     color = MAX (0, MIN (15, graph[0].axis[i].color));
-    fprintf (f, "%.1f setlinewidth\n", weight);
+
+    fprintf (f, "%.1f setlinewidth\n", lweight);
     fprintf (f, "%s setrgbcolor\n", KapaColorRGBString(color));
+    // no need to init rot font
 
-    if (graph[0].axis[i].isaxis) { DrawLine (fx, fy, dfx, dfy); }
+    if (graph[0].axis[i].isaxis) { 
+      DrawLine (fx, fy, dfx, dfy); 
+    }
     
     if (graph[0].axis[i].areticks) {
-      if (isnan(graph[0].axis[i].min) || isinf(graph[0].axis[i].min)) continue;
-      if (isnan(graph[0].axis[i].max) || isinf(graph[0].axis[i].max)) continue;
-
-      range = graph[0].axis[i].max - graph[0].axis[i].min;
-      AxisTickScale (&graph[0].axis[i], &major, &minor);
-
-      first = minor*((int)(graph[0].axis[i].min/minor));
-      if ((range > 0) && (first < graph[0].axis[i].min)) {
-	first += minor;
+      ticks = CreateAxisTicks (&graph[0].axis[i], &Nticks);
+      for (i = 0; i < Nticks; i++) {
+	PSTick (graphic, &graph[0].axis[i], P, &ticks[i], i, f);
       }
-      if ((range < 0) && (first > graph[0].axis[i].min)) {
-	first -= minor;
-      }
-      for (next = first; ((range > 0) && (next <= graph[0].axis[i].max)) || ((range < 0) && (next >= graph[0].axis[i].max));) {
-	IsMajor = FALSE;
-	IsMajor |= (fabs((int)(next/major) - (next/major)) < 0.5*(minor/major));
-	IsMajor |= (fabs ((int)((next + 0.5*minor)/major) - (next/major)) < 0.5*(minor/major));
-	IsMajor |= (fabs ((int)((next - 0.5*minor)/major) - (next/major)) < 0.5*(minor/major));
-	IsLabel = (IsMajor && graph[0].axis[i].islabel);
-	PSTick (f, fx, fy, dfx, dfy, P, graph[0].axis[i].min, graph[0].axis[i].max, next, IsLabel, IsMajor, i);
-	if (range > 0) 
-	  next += minor;
-	else 
-	  next -= minor;
-      }
-    }
+      FREE (ticks);
+    }      
   }
   return (TRUE);
 }
 
-void PSTick (FILE *f, double fx, double fy, double dfx, double dfy, int P, double min, double max, double value, int IsLabel, int IsMajor, int naxis) {
+void PSTick (Graphic *graphic, Axis *axis, int P, TickMarkData *tick, int naxis, FILE *f) {
   
+  double x, y, dx, dy;
   int pos, dir, fontsize;
-  double size, n, x, y, dx, dy;
+  double size, n, pad;
   char string[64], *fontname;
+
+  double fx  = axis->fx;
+  double fy  = graphic->dy - axis->fy;
+  double dfx = axis->dfx;
+  double dfy = -axis->dfy;
+
+  double min = axis->min;
+  double max = axis->max;
+
+  double value = tick->value;
 
   pos = size = 0;
 
-  if (IsMajor) { 
+  if (tick->IsMajor) { 
     size = MAX (0.02, 7.0 / P); 
   } else {
@@ -75,10 +68,9 @@
   }
   
-  n = P / sqrt ((double)(dfx*dfx + dfy*dfy));
+  n = P / hypot(dfx, dfy);
   x = fx + (value-min)*dfx/(max - min);
   y = fy + (value-min)*dfy/(max - min);
 
-  dir = -1;
-  if ((naxis == 0) || (naxis == 1)) dir *= -1;
+  dir = ((naxis == 0) || (naxis == 1)) ? -1 : +1;
   dx = dir*size*dfy*n;	
   dy = dir*size*dfx*n;
@@ -86,19 +78,23 @@
   DrawLine (x, y, dx, dy);
 
-  if (IsLabel) {
+  if (tick->IsLabel) {
+    int xt, yt;
+
     fontname = GetRotFont (&fontsize);
 
+    pad = isfinite(axis->ticktextPad) ? axis->ticktextPad*fontsize : 0.8*fontsize + 1.0;
+    
     /* 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 == 0) { dx = 0; dy = +pad; pos = 1; }
+    if (naxis == 2) { dx = 0; dy = -pad; 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; }
+    if (naxis == 1) { dy = 0; dx = -pad; pos = 3; }
+    if (naxis == 3) { dy = 0; dx = +pad; 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);
-    PSRotText (f, (int)x, (int)y, string, pos, 0.0);
+    xt = fx + (value-min)*dfx/(max - min) + dx;
+    yt = fy + (value-min)*dfy/(max - min) + dy;
+    if (fabs(value) < 0.001) { value = 0.0; }
+    sprintf (string, "%4g", value);
+    PSRotText (f, xt, yt, string, pos, 0.0);
   }
 }
Index: /trunk/Ohana/src/kapa2/src/Refresh.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/Refresh.c	(revision 27789)
+++ /trunk/Ohana/src/kapa2/src/Refresh.c	(revision 27790)
@@ -21,4 +21,5 @@
   for (i = 0; i < Nsection; i++) {
       section = GetSectionByNumber (i);
+      DrawSectionBG (graphic, section);
       DrawImage (section->image);
       DrawGraph (section->graph);
@@ -28,2 +29,25 @@
 }
 
+void DrawSectionBG (Graphic *graphic, Section *section) {
+
+  int Ncolors;
+  int X0, Y0, dX, dY;
+
+  if (section->bg == -1) return;
+
+  Ncolors = KapaColormapSize();
+
+  if (section->bg < 0) return;
+  if (section->bg >= Ncolors) return;
+
+  XSetForeground (graphic->display, graphic->gc, graphic->color[section->bg]);
+
+  dY = graphic[0].dy * section[0].dy;
+  dX = graphic[0].dx * section[0].dx;
+  Y0 = graphic[0].dy - graphic[0].dy * section[0].y - dY;
+  X0 = graphic[0].dx * section[0].x;
+  // fprintf (stderr, "section: (%s) %d %d - %d %d\n", section[0].name, X0, Y0, dX, dY);
+
+  XFillRectangle (graphic[0].display,  graphic[0].window, graphic[0].gc, X0, Y0, dX, dY);
+  return;
+}
Index: /trunk/Ohana/src/kapa2/src/Sections.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/Sections.c	(revision 27789)
+++ /trunk/Ohana/src/kapa2/src/Sections.c	(revision 27790)
@@ -16,4 +16,5 @@
   section[0].dx = 0;
   section[0].dy = 0;
+  section[0].bg = -1;
 
   section[0].name = NULL;
@@ -42,5 +43,5 @@
 }
 
-Section *AddSection (char *name, float x, float y, float dx, float dy) {
+Section *AddSection (char *name, float x, float y, float dx, float dy, int bg) {
 
   int N;
@@ -61,4 +62,5 @@
   sections[N][0].dx = dx;
   sections[N][0].dy = dy;
+  sections[N][0].bg = bg;
   ActiveSection = N;
   return (sections[N]);
@@ -155,4 +157,22 @@
 }
 
+int SetSectionBG (int sock) {
+
+  int N, background;
+  char name[128];
+
+  KiiScanMessage (sock, "%s %d", name, &background);
+  
+  N = GetSectionByName (name);
+  if (N < 0) {
+    fprintf (stderr, "section %s not found\n", name);
+    return (TRUE);
+  }
+
+  sections[N][0].bg = background;
+
+  return (TRUE);
+}
+
 // return TRUE even for nonsense cases to avoid quitting kapa
 int MoveSection (int sock) {
Index: /trunk/Ohana/src/kapa2/src/SetGraphData.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/SetGraphData.c	(revision 27789)
+++ /trunk/Ohana/src/kapa2/src/SetGraphData.c	(revision 27790)
@@ -18,38 +18,18 @@
   graph = section->graph;
   
-  // get graph data from client 
-  KiiScanMessage (sock, "%d %d %d %d %d %d %lf %lf", 
-		  &graph[0].data.style, 
-		  &graph[0].data.ptype, 
-		  &graph[0].data.ltype, 
-		  &graph[0].data.etype, 
-		  &graph[0].data.ebar, 
-		  &graph[0].data.color, 
-		  &graph[0].data.lweight, 
-		  &graph[0].data.size);
+  KapaScanGraphData (sock, &graph[0].data);
 
-  KiiScanMessage (sock, "%lf %lf %lf %lf", 
-		  &graph[0].data.xmin, 
-		  &graph[0].data.xmax, 
-		  &graph[0].data.ymin, 
-		  &graph[0].data.ymax);
+  for (i = 0; i < 4; i++) {
+    graph[0].axis[i].ticktextPad = graph[0].data.ticktextPad;
+  }    
+  graph[0].axis[0].labelPad = graph[0].data.labelPadXm;
+  graph[0].axis[1].labelPad = graph[0].data.labelPadYm;
+  graph[0].axis[2].labelPad = graph[0].data.labelPadXp;
+  graph[0].axis[3].labelPad = graph[0].data.labelPadYp;
 
-  KiiScanMessage (sock, "%f %f %f %f", 
-		  &graph[0].data.coords.pc1_1, &graph[0].data.coords.pc2_2,
-		  &graph[0].data.coords.pc1_2, &graph[0].data.coords.pc2_1);
-
-  KiiScanMessage (sock, "%d %d %s", 
-		  &graph[0].data.flipeast, &graph[0].data.flipnorth,
-		  graph[0].data.coords.ctype);
-
-  KiiScanMessage (sock, "%lf %lf %f %f %f %f", 
-		  &graph[0].data.coords.crval1,
-		  &graph[0].data.coords.crval2,
-		  &graph[0].data.coords.crpix1,
-		  &graph[0].data.coords.crpix2,
-		  &graph[0].data.coords.cdelt1,
-		  &graph[0].data.coords.cdelt2);
-
-
+  graph[0].axis[0].pad = graph[0].data.padXm;
+  graph[0].axis[1].pad = graph[0].data.padYm;
+  graph[0].axis[2].pad = graph[0].data.padXp;
+  graph[0].axis[3].pad = graph[0].data.padYp;
 
   xmin = graph[0].data.xmin;
@@ -90,29 +70,5 @@
   graph = section->graph;
 
-  KiiSendMessage (sock, "%8d %d %d %d %d %d %f %f", 
-		  graph[0].data.style, 
-		  graph[0].data.ptype, graph[0].data.ltype, 
-		  graph[0].data.etype, graph[0].data.ebar, graph[0].data.color, 
-		  graph[0].data.lweight, graph[0].data.size);
-
-  KiiSendMessage (sock, "%g %g %g %g", 
-		  graph[0].data.xmin, graph[0].data.xmax, 
-		  graph[0].data.ymin, graph[0].data.ymax);
-
-  KiiSendMessage (sock, "%g %g %g %g", 
-		  graph[0].data.coords.pc1_1, graph[0].data.coords.pc2_2,
-		  graph[0].data.coords.pc1_2, graph[0].data.coords.pc2_1);
-
-  KiiSendMessage (sock, "%d %d %s", 
-		  graph[0].data.flipeast, graph[0].data.flipnorth,
-		  graph[0].data.coords.ctype);
-
-  KiiSendMessage (sock, "%g %g %g %g %g %g", 
-		  graph[0].data.coords.crval1,
-		  graph[0].data.coords.crval2,
-		  graph[0].data.coords.crpix1,
-		  graph[0].data.coords.crpix2,
-		  graph[0].data.coords.cdelt1,
-		  graph[0].data.coords.cdelt2);
+  KapaSendGraphData (sock, &graph[0].data);
 
   return (TRUE);
Index: /trunk/Ohana/src/kapa2/src/SetGraphSize.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/SetGraphSize.c	(revision 27789)
+++ /trunk/Ohana/src/kapa2/src/SetGraphSize.c	(revision 27790)
@@ -6,12 +6,16 @@
 void SetGraphSize (Section *section) {
 
-  int fontsize, bump, Nc;
+  int i, Nticks;
+  int fontsize, Nc;
   int textpad, textdY, WdY; 
-  double PADx, PADy, Dx, Dy;
-  double PXm, PXp, PYm, PYp;
+  int dXm, dXp, dYm, dYp;
+  double padXm, padXp, padYm, padYp;
+  double minPADx, maxPADx, minPADy;
+  double minPAD, maxPAD;
   double X0, Y0, dX, dY;
   char string[64], *fontname;
   KapaGraphWidget *graph;
   Graphic *graphic;
+  TickMarkData *ticks;
 
   if (section == NULL) return;
@@ -22,20 +26,95 @@
   fontname = GetRotFont (&fontsize);
 
-  PADx = MAX (graphic->dx / 20.0, fontsize);
-  PADy = MAX (graphic->dy / 20.0, fontsize);
-  Dx = graphic->dx - 2*PADx;
-  Dy = graphic->dy - 2*PADy;
+  minPAD = 1.0*fontsize + 0;
+  maxPAD = 2.0*fontsize + 4;
 
-  /* each graph has a padding PXm, PXp, PYm, PYp */
-  PXm = (graph[0].axis[1].islabel) ? 4*fontsize : 0;
-  PXp = (graph[0].axis[3].islabel) ? 4*fontsize : 0;
-  PYm = (graph[0].axis[0].islabel) ? 4*fontsize : 0;
-  PYp = (graph[0].axis[2].islabel) ? 4*fontsize : 0;
- 
+  minPADx = 1.5*fontsize;
+  maxPADx = 2.5*fontsize + 4.0;
+
+  minPADy = 1.5*fontsize;
+
+  // dXm : offset to label from lower x-axis, dYp : offset to label from right y-axis, etc
+  // padXm : padding below x-axis, padYp : padding to right of y-axis, etc
+
+  // offset from lower x-axis to labels and tick values
+  // these depend on (a) existence of tick labels and (b) auto-offset or not
+  if (isnan(graph[0].axis[0].labelPad)) {
+    dXm = (graph[0].axis[0].islabel) ? maxPAD  : minPAD;
+  } else {
+    dXm = graph[0].axis[0].labelPad * fontsize;
+  }
+  if (isnan(graph[0].axis[0].pad)) {
+    padXm = graph[0].axis[0].islabel ? maxPADx : minPADx;
+  } else {
+    padXm = graph[0].axis[0].pad * fontsize;
+  }
+
+  // offset from upper x-axis to labels and tick values
+  // these depend on (a) existence of tick labels and (b) auto-offset or not
+  if (isnan(graph[0].axis[2].labelPad)) {
+    dXp = (graph[0].axis[2].islabel) ? maxPAD : minPAD;
+  } else {
+    dXp = graph[0].axis[2].labelPad * fontsize;
+  }
+  if (isnan(graph[0].axis[2].pad)) {
+    padXp = graph[0].axis[2].islabel ? maxPADx : minPADx;
+  } else {
+    padXp = graph[0].axis[2].pad * fontsize;
+  }
+
+  // offset from left y-axis to labels and tick values
+  // these depend on (a) existence of tick labels and (b) auto-offset or not.
+  // in the auto-offset case, offset depends on the width of the tick label strings
+  if (graph[0].axis[1].islabel && (isnan(graph[0].axis[1].labelPad) || isnan(graph[0].axis[1].pad))) {
+    /* check for the max size of the axis label */
+    Nc = 0;
+    ticks = CreateAxisTicks (&graph[0].axis[1], &Nticks);
+    for (i = 0; i < Nticks; i++) {
+      if (!ticks[i].IsMajor) continue;
+      sprintf (string, "%g", ticks[i].value);
+      Nc = MAX (Nc, strlen (string));
+    }
+    FREE(ticks);
+  }
+  if (isnan(graph[0].axis[1].labelPad)) {
+    dYm = (graph[0].axis[1].islabel) ? (0.7*(Nc + 1.5)*fontsize) : minPAD;
+  } else {
+    dYm = graph[0].axis[1].labelPad * fontsize;
+  }
+  if (isnan(graph[0].axis[1].pad)) {
+    padYm = graph[0].axis[1].islabel ? (0.7*(Nc + 2.5)*fontsize) : minPADy;
+  } else {
+    padYm = graph[0].axis[1].pad * fontsize;
+  }
+
+  // offset from right y-axis to labels and tick values
+  // these depend on (a) existence of tick labels and (b) auto-offset or not.
+  // in the auto-offset case, offset depends on the width of the tick label strings
+  if (graph[0].axis[3].islabel && (isnan(graph[0].axis[3].labelPad) || isnan(graph[0].axis[3].pad))) {
+    Nc = 0;
+    ticks = CreateAxisTicks (&graph[0].axis[3], &Nticks);
+    for (i = 0; i < Nticks; i++) {
+      if (!ticks[i].IsMajor) continue;
+      sprintf (string, "%g", ticks[i].value);
+      Nc = MAX (Nc, strlen (string));
+    }
+    FREE(ticks);
+  }
+  if (isnan(graph[0].axis[3].labelPad)) {
+    dYp = (graph[0].axis[3].islabel) ? (0.7*(Nc + 1.5)*fontsize) : minPAD;
+  } else {
+    dYp = graph[0].axis[3].labelPad * fontsize;
+  }
+  if (isnan(graph[0].axis[3].pad)) {
+    padYp = graph[0].axis[3].islabel ? (0.7*(Nc + 2.5)*fontsize) : minPADy;
+  } else {
+    padYp = graph[0].axis[3].pad * fontsize;
+  }
+
   /* basic size of the graph in Xwindow coordinates */
-  X0 = PADx + PXm + (Dx * section[0].x);
-  Y0 = PADy + PYm + (Dy * section[0].y);
-  dX = (Dx * section[0].dx) - PXp - PXm;
-  dY = (Dy * section[0].dy) - PYp - PYm;
+  X0 = graphic[0].dx * section[0].x + padYm;
+  Y0 = graphic[0].dy * section[0].y + padXm;
+  dX = graphic[0].dx * section[0].dx - padYm - padYp;
+  dY = graphic[0].dy * section[0].dy - padXm - padXp;
 
   // if we are tied to an image, make mods as needed
@@ -47,9 +126,9 @@
     switch (section->image->location) {
       case 1:
-	Y0 = graphic[0].dy * section[0].y + 2*PAD1 + WdY + 2; // tied to image in Y
+	Y0 = graphic[0].dy * section[0].y  + 2*PAD1 + WdY + 2; // tied to image in Y
 	dY = graphic[0].dy * section[0].dy - 5*PAD1 - WdY - COLORPAD + 1;
 	break;
       case 3:
-	dY = graphic[0].dy * section[0].dy - 5*PAD1 - WdY - COLORPAD - PADy - PYm;
+	dY = graphic[0].dy * section[0].dy - 5*PAD1 - WdY - COLORPAD - padYm - padYp;
 	break;
       case 2:
@@ -58,5 +137,5 @@
 	break;
       case 4:
-	dX = graphic[0].dx * section[0].dx - 3*PAD1 - ZOOM_X - PADx - PXm;
+	dX = graphic[0].dx * section[0].dx - 3*PAD1 - ZOOM_X - padXm - padXp;
 	break;
     }
@@ -84,45 +163,28 @@
   graph[0].axis[3].dfy = -dY;
 
-  PADx = 0.8*fontsize + 2;
-  PADy = 3.0*fontsize + 4;
+  /* define locations of axis labels */
+  graph[0].label[LABELLL].x = graph[0].axis[0].fx;
+  graph[0].label[LABELLL].y = graph[0].axis[0].fy + dXm;
+  graph[0].label[LABELX0].x = graph[0].axis[0].fx + 0.5*graph[0].axis[0].dfx;
+  graph[0].label[LABELX0].y = graph[0].axis[0].fy + dXm;
+  graph[0].label[LABELLR].x = graph[0].axis[0].fx + graph[0].axis[0].dfx;
+  graph[0].label[LABELLR].y = graph[0].axis[0].fy + dXm;
 
-  /* define locations of axis labels */
-  graph[0].label[LABELX0].x = graph[0].axis[0].fx + 0.5*graph[0].axis[0].dfx;
-  bump = (graph[0].axis[0].islabel) ? PADy : PADx;
-  graph[0].label[LABELX0].y = graph[0].axis[0].fy + bump;
-
+  graph[0].label[LABELUL].x = graph[0].axis[2].fx;
+  graph[0].label[LABELUL].y = graph[0].axis[2].fy - dXp;
   graph[0].label[LABELX1].x = graph[0].axis[2].fx + 0.5*graph[0].axis[2].dfx;
-  bump = (graph[0].axis[2].islabel) ? PADy : PADx;
-  graph[0].label[LABELX1].y = graph[0].axis[2].fy - bump;
-
-  /* check for the max size of the axis label */
-  sprintf (string, "%4g", graph[0].axis[1].min);
-  Nc = strlen (string);
-  sprintf (string, "%4g", graph[0].axis[1].max);
-  Nc = MAX (Nc, strlen (string));
+  graph[0].label[LABELX1].y = graph[0].axis[2].fy - dXp;
+  graph[0].label[LABELUR].x = graph[0].axis[2].fx + graph[0].axis[2].dfx;
+  graph[0].label[LABELUR].y = graph[0].axis[2].fy - dXp;
 
   graph[0].label[LABELY0].y = graph[0].axis[1].fy + 0.5*graph[0].axis[1].dfy;
-  bump = (graph[0].axis[1].islabel) ? (0.8*Nc*fontsize + 1) : PADx;
-  graph[0].label[LABELY0].x = graph[0].axis[1].fx - bump;
-
-  sprintf (string, "%4g", graph[0].axis[3].min);
-  Nc = strlen (string);
-  sprintf (string, "%4g", graph[0].axis[3].max);
-  Nc = MAX (Nc, strlen (string));
+  graph[0].label[LABELY0].x = graph[0].axis[1].fx - dYm;
 
   graph[0].label[LABELY1].y = graph[0].axis[3].fy + 0.5*graph[0].axis[3].dfy;
-  bump = (graph[0].axis[3].islabel) ? (0.8*Nc*fontsize + 1) : PADx;
-  graph[0].label[LABELY1].x = graph[0].axis[3].fx + bump;
+  graph[0].label[LABELY1].x = graph[0].axis[3].fx + dYp;
   
+  // fprintf (stderr, "section %s, %f,%f : %f,%f\n", section->name, X0, Y0, dX, dY);
+
   /* these are wrong and have to be adjusted to sit in the corners */
 
-  graph[0].label[LABELUL].x = graph[0].axis[2].fx - PADx;
-  graph[0].label[LABELUL].y = graph[0].axis[2].fy - PADx;
-  graph[0].label[LABELUR].x = graph[0].axis[2].fx + graph[0].axis[2].dfx + PADx;
-  graph[0].label[LABELUR].y = graph[0].axis[2].fy - PADx;
-  graph[0].label[LABELLL].x = graph[0].axis[0].fx - PADx;
-  graph[0].label[LABELLL].y = graph[0].axis[0].fy + PADx;
-  graph[0].label[LABELLR].x = graph[0].axis[0].fx + graph[0].axis[0].dfx + PADx;
-  graph[0].label[LABELLR].y = graph[0].axis[0].fy + PADx;
-
 }
Index: /trunk/Ohana/src/kapa2/src/bDrawFrame.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/bDrawFrame.c	(revision 27789)
+++ /trunk/Ohana/src/kapa2/src/bDrawFrame.c	(revision 27790)
@@ -1,14 +1,16 @@
 # include "Ximage.h"
+// bDrawLine is a function, not a macro like DrawLine
 
 int bDrawFrame (KapaGraphWidget *graph) {
   
-  int i, P, IsLabel, IsMajor, fontsize;
-  double fx, fy, dfx, dfy, range, major, minor, first, next;
-  char *fontname;
-  int weight;
+  int i, Nticks, P;
+  double fx, fy, dfx, dfy, lweight;
+  // Graphic graphic; is not needed
+  TickMarkData *ticks;
   bDrawColor color;
 
+  // don't need graphic, unlink DrawFrame
+
   /* each axis is drawn independently */
-  fontname = GetRotFont (&fontsize);
   for (i = 0; i < 4; i++) {
     fx  = graph[0].axis[i].fx;
@@ -16,9 +18,12 @@
     dfx = graph[0].axis[i].dfx;
     dfy = graph[0].axis[i].dfy;
-    P = hypot ((double)graph[0].axis[(i+1)%2].dfx, (double)graph[0].axis[(i+1)%2].dfy);
+    P = hypot (graph[0].axis[(i+1)%2].dfx, graph[0].axis[(i+1)%2].dfy);
 
-    weight = MAX (0, MIN (10, graph[0].axis[i].lweight));
+    lweight = MAX (0, MIN (10, graph[0].axis[i].lweight));
     color = MAX (0, MIN (15, graph[0].axis[i].color));
-    bDrawSetStyle (color, weight, 0);
+
+    bDrawSetStyle (color, lweight, 0);
+    // function about sets solor and weight
+    // bDrawRotTextInit does not exist
 
     if (graph[0].axis[i].isaxis) { 
@@ -27,30 +32,9 @@
     
     if (graph[0].axis[i].areticks) {
-      if (isnan(graph[0].axis[i].min) || isinf(graph[0].axis[i].min)) continue;
-      if (isnan(graph[0].axis[i].max) || isinf(graph[0].axis[i].max)) continue;
-
-      range = graph[0].axis[i].max - graph[0].axis[i].min;
-
-      AxisTickScale (&graph[0].axis[i], &major, &minor);
-
-      first = minor*((int)(graph[0].axis[i].min/minor));
-      if ((range > 0) && (first < graph[0].axis[i].min)) {
-	first += minor;
+      ticks = CreateAxisTicks (&graph[0].axis[i], &Nticks);
+      for (i = 0; i < Nticks; i++) {
+	bDrawTick (&graph[0].axis[i], P, &ticks[i], i);
       }
-      if ((range < 0) && (first > graph[0].axis[i].min)) {
-	first -= minor;
-      }
-      for (next = first; ((range > 0) && (next <= graph[0].axis[i].max)) || ((range < 0) && (next >= graph[0].axis[i].max));) {
-	IsMajor = FALSE;
-	IsMajor |= (fabs((int)(next/major) - (next/major)) < 0.5*(minor/major));
-	IsMajor |= (fabs ((int)((next + 0.5*minor)/major) - (next/major)) < 0.5*(minor/major));
-	IsMajor |= (fabs ((int)((next - 0.5*minor)/major) - (next/major)) < 0.5*(minor/major));
-	IsLabel = (IsMajor && graph[0].axis[i].islabel);
-	bDrawTick (fx, fy, dfx, dfy, P, graph[0].axis[i].min, graph[0].axis[i].max, next, IsLabel, IsMajor, i);
-	if (range > 0) 
-	  next += minor;
-	else 
-	  next -= minor;
-      }
+      FREE (ticks);
     }
   }
@@ -58,13 +42,24 @@
 }
 
-void bDrawTick (double fx, double fy, double dfx, double dfy, int P, double min, double max, double value, int IsLabel, int IsMajor, int naxis) {
+void bDrawTick (Axis *axis, int P, TickMarkData *tick, int naxis) {
   
+  double x, y, dx, dy;
   int pos, dir, fontsize;
-  double size, n, x, y, dx, dy;
+  double size, n, pad;
   char string[64], *fontname;
+
+  double fx  = axis->fx;
+  double fy  = axis->fy;
+  double dfx = axis->dfx;
+  double dfy = axis->dfy;
+
+  double min = axis->min;
+  double max = axis->max;
+
+  double value = tick->value;
 
   pos = size = 0;
 
-  if (IsMajor) { 
+  if (tick->IsMajor) { 
     size = MAX (0.02, 7.0 / P); 
   } else {
@@ -72,10 +67,9 @@
   }
   
-  n = P / sqrt ((double)(dfx*dfx + dfy*dfy));
+  n = P / hypot(dfx, dfy);
   x = fx + (value-min)*dfx/(max - min);
   y = fy + (value-min)*dfy/(max - min);
 
-  dir = +1;
-  if ((naxis == 0) || (naxis == 1)) dir *= -1;
+  dir = ((naxis == 0) || (naxis == 1)) ? -1 : +1;
   dx = dir*size*dfy*n;	
   dy = dir*size*dfx*n;
@@ -83,19 +77,23 @@
   bDrawLine (x, y, x+dx, y+dy);
 
-  if (IsLabel) {
+  if (tick->IsLabel) {
+    int xt, yt;
+
     fontname = GetRotFont (&fontsize);
 
+    pad = isfinite(axis->ticktextPad) ? axis->ticktextPad*fontsize : 0.8*fontsize + 1.0;
+    
     /* 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 == 0) { dx = 0; dy = +pad; pos = 1; }
+    if (naxis == 2) { dx = 0; dy = -pad; 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; }
+    if (naxis == 1) { dy = 0; dx = -pad; pos = 3; }
+    if (naxis == 3) { dy = 0; dx = +pad; 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);
+    xt = fx + (value-min)*dfx/(max - min) + dx;
+    yt = fy + (value-min)*dfy/(max - min) + dy;
+    if (fabs(value) < 0.001) { value = 0.0; }
+    sprintf (string, "%4g", value);
+    bDrawRotText (xt, yt, string, pos, 0.0);
   }
 }
Index: /trunk/Ohana/src/libkapa/include/kapa.h
===================================================================
--- /trunk/Ohana/src/libkapa/include/kapa.h	(revision 27789)
+++ /trunk/Ohana/src/libkapa/include/kapa.h	(revision 27790)
@@ -72,4 +72,5 @@
   float dx;
   float dy;
+  int bg;
 } KapaSection;
 
@@ -78,4 +79,7 @@
   int style, ptype, ltype, etype, ebar, color;
   double lweight, size;
+  double ticktextPad;
+  double labelPadXm, labelPadYm, labelPadXp, labelPadYp;
+  double padXm, padXp, padYm, padYp;
   Coords coords;
   int flipeast, flipnorth;
@@ -173,7 +177,10 @@
 int KapaSelectSection (int fd, char *name);
 int KapaGetSection (int fd, char *name);
+int KapaSectionBG (int fd, char *name, int bg);
 int KapaMoveSection (int fd, char *name, char *direction);
 int KapaSetGraphData (int fd, Graphdata *graphmode);
 int KapaGetGraphData (int fd, Graphdata *graphmode);
+int KapaScanGraphData (int fd, Graphdata *graphmode);
+int KapaSendGraphData (int fd, Graphdata *graphmode);
 int KapaSetImageData (int fd, KapaImageData *graphmode);
 int KapaGetImageData (int fd, KapaImageData *graphmode);
Index: /trunk/Ohana/src/libkapa/src/KapaWindow.c
===================================================================
--- /trunk/Ohana/src/libkapa/src/KapaWindow.c	(revision 27789)
+++ /trunk/Ohana/src/libkapa/src/KapaWindow.c	(revision 27790)
@@ -38,10 +38,7 @@
 
   KiiSendCommand (fd, 4, "DBOX");
-  KiiSendMessage (fd, "%12.6g %12.6g %12.6g %12.6g", 
-		    graphdata[0].xmin, graphdata[0].xmax, graphdata[0].ymin, graphdata[0].ymax);
-
-  KiiSendMessage (fd, "%lf %d", graphdata[0].lweight, graphdata[0].color);
-
-  KiiSendMessage (fd, "%s %s %s", graphdata[0].axis, graphdata[0].labels, graphdata[0].ticks);
+
+  KapaSendGraphData (fd, graphdata);
+
   KiiWaitAnswer (fd, "DONE");
   return (TRUE);
@@ -84,4 +81,5 @@
 }
 
+// XXX drop this function? : kapa is responsible for the graph initialization
 int KapaInitGraph (Graphdata *graphdata) {
 
@@ -103,7 +101,20 @@
   graphdata[0].flipeast = TRUE;
   graphdata[0].flipnorth = FALSE;
+
   strcpy (graphdata[0].axis, "2222");
   strcpy (graphdata[0].ticks, "2222");
   strcpy (graphdata[0].labels, "2222");
+
+  graphdata[0].ticktextPad = NAN;
+
+  graphdata[0].labelPadXm = NAN;
+  graphdata[0].labelPadXp = NAN;
+  graphdata[0].labelPadYm = NAN;
+  graphdata[0].labelPadYp = NAN;
+
+  graphdata[0].padXm = NAN;
+  graphdata[0].padXp = NAN;
+  graphdata[0].padYm = NAN;
+  graphdata[0].padYp = NAN;
 
   return (TRUE);
@@ -128,10 +139,11 @@
 }
 
-int KapaSetGraphData (int fd, Graphdata *data) {
-
-  /* tell kapa to look for the incoming image */
-  KiiSendCommand (fd, 4, "SSTY"); 
-  
+int KapaSendGraphData (int fd, Graphdata *data) {
+
   /* send kapa the plot details */
+  KiiSendMessage (fd, "%g %g %g %g", 
+		  data[0].xmin, data[0].xmax, 
+		  data[0].ymin, data[0].ymax);
+
   KiiSendMessage (fd, "%8d %d %d %d %d %d %f %f", 
 		  data[0].style, 
@@ -140,7 +152,12 @@
 		  data[0].lweight, data[0].size);
 
+  KiiSendMessage (fd, "%g %g %g %g %g", 
+		  data[0].ticktextPad,
+		  data[0].padXm, data[0].padXp, 
+		  data[0].padYm, data[0].padYp);
+
   KiiSendMessage (fd, "%g %g %g %g", 
-		  data[0].xmin, data[0].xmax, 
-		  data[0].ymin, data[0].ymax);
+		  data[0].labelPadXm, data[0].labelPadXp, 
+		  data[0].labelPadYm, data[0].labelPadYp);
 
   KiiSendMessage (fd, "%g %g %g %g", 
@@ -160,14 +177,16 @@
 		  data[0].coords.cdelt2);
 
-  KiiWaitAnswer (fd, "DONE");
-  return (TRUE);
-}
-
-int KapaGetGraphData (int fd, Graphdata *data) {
-
-  /* tell kapa to look for the incoming image */
-  KiiSendCommand (fd, 4, "GSTY"); 
-  
+  KiiSendMessage (fd, "%s %s %s", data[0].axis, data[0].ticks, data[0].labels);
+
+  return (TRUE);
+}
+
+int KapaScanGraphData (int fd, Graphdata *data) {
+
   /* send kapa the plot details */
+  KiiScanMessage (fd, "%lf %lf %lf %lf", 
+		  &data[0].xmin, &data[0].xmax, 
+		  &data[0].ymin, &data[0].ymax);
+
   KiiScanMessage (fd, "%d %d %d %d %d %d %lf %lf", 
 		  &data[0].style, 
@@ -176,7 +195,12 @@
 		  &data[0].lweight, &data[0].size);
 
+  KiiScanMessage (fd, "%lf %lf %lf %lf %lf", 
+		  &data[0].ticktextPad, 
+		  &data[0].padXm, &data[0].padXp, 
+		  &data[0].padYm, &data[0].padYp);
+
   KiiScanMessage (fd, "%lf %lf %lf %lf", 
-		  &data[0].xmin, &data[0].xmax, 
-		  &data[0].ymin, &data[0].ymax);
+		  &data[0].labelPadXm, &data[0].labelPadXp, 
+		  &data[0].labelPadYm, &data[0].labelPadYp);
 
   KiiScanMessage (fd, "%f %f %f %f", 
@@ -196,8 +220,31 @@
 		  &data[0].coords.cdelt2);
 
+  KiiScanMessage (fd, "%s %s %s", data[0].axis, data[0].ticks, data[0].labels);
+
   // XXX at some point, we need to add polynomials and 2-level mosaic
   // astrometry here.
 
   data[0].coords.Npolyterms = 0;
+
+  return (TRUE);
+}
+
+int KapaSetGraphData (int fd, Graphdata *data) {
+
+  /* tell kapa to look for the incoming image */
+  KiiSendCommand (fd, 4, "SSTY"); 
+  
+  KapaSendGraphData (fd, data);
+
+  KiiWaitAnswer (fd, "DONE");
+  return (TRUE);
+}
+
+int KapaGetGraphData (int fd, Graphdata *data) {
+
+  /* tell kapa to look for the incoming image */
+  KiiSendCommand (fd, 4, "GSTY"); 
+  
+  KapaScanGraphData (fd, data);
 
   KiiWaitAnswer (fd, "DONE");
@@ -312,10 +359,19 @@
 
   KiiSendCommand (fd, 4, "DSEC");
-  KiiSendMessage (fd, "%s %6.3f %6.3f %6.3f %6.3f", 
+  KiiSendMessage (fd, "%s %6.3f %6.3f %6.3f %6.3f %3d", 
 		  section[0].name, 
 		  section[0].x,
 		  section[0].y,
 		  section[0].dx,
-		  section[0].dy);
+		  section[0].dy,
+		  section[0].bg);
+  KiiWaitAnswer (fd, "DONE");
+  return (TRUE);
+}
+
+int KapaSectionBG (int fd, char *name, int bg) {
+
+  KiiSendCommand (fd, 4, "BSEC");
+  KiiSendMessage (fd, "%s %3d", name, bg);
   KiiWaitAnswer (fd, "DONE");
   return (TRUE);
Index: /trunk/Ohana/src/opihi/cmd.basic/opihi.c
===================================================================
--- /trunk/Ohana/src/opihi/cmd.basic/opihi.c	(revision 27789)
+++ /trunk/Ohana/src/opihi/cmd.basic/opihi.c	(revision 27790)
@@ -3,8 +3,8 @@
 int opihi_setmode (int argc, char **argv) {
 
-  int value;
+  OpihiVerboseMode value;
 
   if (argc < 2) {
-    gprint (GP_ERR, "USAGE: opihi (verbose) [on/off]\n");
+    gprint (GP_ERR, "USAGE: opihi (verbose) [on/off/error]\n");
     return (FALSE);
   }
@@ -13,17 +13,30 @@
       if (argc == 2) {
 	  value = get_verbose_shell();
-	  if (value) {
-	    gprint (GP_ERR, "opihi verbose mode: on\n");
-	  } else {
-	    gprint (GP_ERR, "opihi verbose mode: off\n");
-	  }
+	  switch (value) {
+	    case OPIHI_VERBOSE_OFF:
+	      gprint (GP_ERR, "opihi verbose mode: off\n");
+	      break;
+	    case OPIHI_VERBOSE_ON:
+	      gprint (GP_ERR, "opihi verbose mode: on\n");
+	      break;
+	    case OPIHI_VERBOSE_ERROR:
+	      gprint (GP_ERR, "opihi verbose mode: error\n");
+	      break;
+	    default:
+	      fprintf (stderr, "impossible condition\n");
+	      abort();
+	  } 
 	  return (TRUE);
       }
       if (!strcasecmp(argv[2], "on")) {
-	set_verbose_shell (TRUE);
+	set_verbose_shell (OPIHI_VERBOSE_ON);
 	return (TRUE);
       }
       if (!strcasecmp(argv[2], "off")) {
-	set_verbose_shell (FALSE);
+	set_verbose_shell (OPIHI_VERBOSE_OFF);
+	return (TRUE);
+      }
+      if (!strcasecmp(argv[2], "error")) {
+	set_verbose_shell (OPIHI_VERBOSE_ERROR);
 	return (TRUE);
       }
Index: /trunk/Ohana/src/opihi/cmd.data/box.c
===================================================================
--- /trunk/Ohana/src/opihi/cmd.data/box.c	(revision 27789)
+++ /trunk/Ohana/src/opihi/cmd.data/box.c	(revision 27790)
@@ -25,5 +25,5 @@
   } 
 
-  graphmode.lweight = 1;
+  // graphmode.lweight = 1;
   if ((N = get_argument (argc, argv, "-lw"))) {
     remove_argument (N, &argc, argv);
@@ -32,5 +32,5 @@
   }
 
-  graphmode.color = KapaColorByName ("black");
+  // graphmode.color = KapaColorByName ("black");
   if ((N = get_argument (argc, argv, "-c"))) {
     remove_argument (N, &argc, argv);
@@ -40,5 +40,6 @@
   }
 
-  strcpy (graphmode.ticks, "2222");
+  // XXX need to get the current values from kapa
+  // strcpy (graphmode.ticks, "2222");
   if ((N = get_argument (argc, argv, "-ticks"))) {
     remove_argument (N, &argc, argv);
@@ -51,5 +52,5 @@
   }
   
-  strcpy (graphmode.labels, "2222");
+  // strcpy (graphmode.labels, "2222");
   if ((N = get_argument (argc, argv, "-labels"))) {
     remove_argument (N, &argc, argv);
@@ -62,5 +63,5 @@
   }
 
-  strcpy (graphmode.axis, "2222");
+  // strcpy (graphmode.axis, "2222");
   if ((N = get_argument (argc, argv, "-axis"))) {
     remove_argument (N, &argc, argv);
@@ -71,4 +72,72 @@
       if ((graphmode.axis[i] != '0') && (graphmode.axis[i] != '1') && (graphmode.axis[i] != '2')) { goto usage; }
     }
+  }
+
+  if ((N = get_argument (argc, argv, "-tickpad"))) {
+    remove_argument (N, &argc, argv);
+    graphmode.ticktextPad = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if ((N = get_argument (argc, argv, "-labelpadx"))) {
+    remove_argument (N, &argc, argv);
+    graphmode.labelPadXm = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if ((N = get_argument (argc, argv, "-labelpady"))) {
+    remove_argument (N, &argc, argv);
+    graphmode.labelPadYm = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if ((N = get_argument (argc, argv, "+labelpadx"))) {
+    remove_argument (N, &argc, argv);
+    graphmode.labelPadXp = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if ((N = get_argument (argc, argv, "+labelpady"))) {
+    remove_argument (N, &argc, argv);
+    graphmode.labelPadYp = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if ((N = get_argument (argc, argv, "-labelpad"))) {
+    remove_argument (N, &argc, argv);
+    graphmode.labelPadXm = atof(argv[N]);
+    graphmode.labelPadXp = atof(argv[N]);
+    graphmode.labelPadYm = atof(argv[N]);
+    graphmode.labelPadYp = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if ((N = get_argument (argc, argv, "-pad"))) {
+    remove_argument (N, &argc, argv);
+    graphmode.padXm = atof(argv[N]);
+    graphmode.padXp = atof(argv[N]);
+    graphmode.padYm = atof(argv[N]);
+    graphmode.padYp = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if ((N = get_argument (argc, argv, "-xpad"))) {
+    remove_argument (N, &argc, argv);
+    graphmode.padXm = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if ((N = get_argument (argc, argv, "+xpad"))) {
+    remove_argument (N, &argc, argv);
+    graphmode.padXp = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if ((N = get_argument (argc, argv, "-ypad"))) {
+    remove_argument (N, &argc, argv);
+    graphmode.padYm = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if ((N = get_argument (argc, argv, "+ypad"))) {
+    remove_argument (N, &argc, argv);
+    graphmode.padYp = atof(argv[N]);
+    remove_argument (N, &argc, argv);
   }
 
Index: /trunk/Ohana/src/opihi/cmd.data/section.c
===================================================================
--- /trunk/Ohana/src/opihi/cmd.data/section.c	(revision 27789)
+++ /trunk/Ohana/src/opihi/cmd.data/section.c	(revision 27790)
@@ -1,9 +1,9 @@
 # include "data.h"
 
-enum {NONE, LIST, UP, DOWN, TOP, BOTTOM, TOOL};
+enum {NONE, LIST, UP, DOWN, TOP, BOTTOM, TOOL, BG};
 
 int section (int argc, char **argv) {
   
-  int N, action, kapa;
+  int N, action, kapa, background;
   Graphdata graphmode;
   KapaSection section;
@@ -37,4 +37,16 @@
     location = argv[N];
     remove_argument (N, &argc, argv);
+  }
+
+  background = -1; // invisible
+  if ((N = get_argument (argc, argv, "-bg"))) {
+    remove_argument (N, &argc, argv);
+    if (!strcasecmp (argv[N], "NONE")) {
+      background = -1;
+    } else {
+      background = KapaColorByName(argv[N]);
+    }
+    remove_argument (N, &argc, argv);
+    action = BG;
   }
 
@@ -82,4 +94,8 @@
 	break;
 
+      case BG:
+	KapaSectionBG (kapa, argv[1], background);
+	break;
+
       case TOOL:
 	if (!strcmp(location, "-x")) {
@@ -121,4 +137,5 @@
     section.dx = atof (argv[4]);
     section.dy = atof (argv[5]);
+    section.bg = background;
     KapaSetSection (kapa, &section);
     return (TRUE);
Index: /trunk/Ohana/src/opihi/include/shell.h
===================================================================
--- /trunk/Ohana/src/opihi/include/shell.h	(revision 27789)
+++ /trunk/Ohana/src/opihi/include/shell.h	(revision 27790)
@@ -15,4 +15,5 @@
 typedef enum {GP_FILE, GP_BUFF} gpMode;
 typedef enum {GP_LOG, GP_ERR} gpDest;
+typedef enum {OPIHI_VERBOSE_OFF, OPIHI_VERBOSE_ON, OPIHI_VERBOSE_ERROR} OpihiVerboseMode;
 
 typedef int CommandF (int argc, char **argv);
Index: unk/Ohana/src/opihi/lib.data/open_graph.c
===================================================================
--- /trunk/Ohana/src/opihi/lib.data/open_graph.c	(revision 27789)
+++ 	(revision )
@@ -1,176 +1,0 @@
-# include "display.h"
-# include "shell.h"
-# define DEBUG 0
-
-/* we have space for several kapa windows */
-# define NXGRAPH 5
-
-static int       Active;
-static int       Xgraph[NXGRAPH];  
-static Graphdata graphdata[NXGRAPH];
-
-void QuitGraph () {
-
-  int i;
-  
-  for (i = 0; i < NXGRAPH; i++) {
-    KiiClose (Xgraph[i]);
-  }
-}
-
-void InitGraph () {
-
-  int i;
-
-  Active = 0;
-  for (i = 0; i < NXGRAPH; i++) {
-    Xgraph[i] = -1;
-
-    graphdata[i].xmin = graphdata[i].ymin = 0.0;
-    graphdata[i].xmax = graphdata[i].ymax = 1.0;
-    graphdata[i].style = graphdata[i].ptype = 0;
-    graphdata[i].ltype = graphdata[i].color = 0;
-    graphdata[i].etype = graphdata[i].ebar = 0;
-    graphdata[i].lweight = graphdata[i].size = 1.0;
-    
-    graphdata[i].coords.pc1_1 = graphdata[i].coords.pc2_2 = 1.0;
-    graphdata[i].coords.pc1_2 = graphdata[i].coords.pc2_1 = 0.0;
-    strcpy (graphdata[i].coords.ctype, "RA---LIN");
-    graphdata[i].coords.crval1 = 0.0;
-    graphdata[i].coords.crval2 = 0.0;
-    graphdata[i].coords.crpix1 = 0.0;
-    graphdata[i].coords.crpix2 = 0.0;
-    graphdata[i].coords.cdelt1 = graphdata[i].coords.cdelt2 = 1.0;
-    graphdata[i].flipeast = TRUE;
-    graphdata[i].flipnorth = FALSE;
-    strcpy (graphdata[i].axis, "2222");
-    strcpy (graphdata[i].ticks, "2222");
-    strcpy (graphdata[i].labels, "2222");
-  }
-}
-
-/* set SIGPIPE to this function to close cleanly */ 
-void XGraphDead (int input) {
-  signal (SIGPIPE, XGraphDead);
-  gprint (GP_ERR, "kapa is dead, must restart\n");
-  Xgraph[Active] = -1;
-}
-
-/** start socketed connection */
-int open_graph (int N) {
-
-  int fd;
-  char *kapa_exec, name[16];
-  
-  kapa_exec = get_variable ("KAPA");
-  if (kapa_exec == (char *) NULL) {
-    gprint (GP_ERR, "variable KAPA not found\n");
-    return (FALSE);
-  }
-
-  snprintf (name, 16, "[%d]", N);
-  fd = KiiOpen (kapa_exec, name);
-  free (kapa_exec);
-
-  if (fd < 0) {
-    gprint (GP_ERR, "error starting kapa\n");
-    return (FALSE);
-  } 
-
-  Xgraph[N] = fd;
-  return (TRUE);
-}
-
-int close_graph (int N) {
-
-  if (N <  0) return (FALSE);
-  if (N >= NXGRAPH) return (FALSE);
-
-  KiiClose (Xgraph[N]); 
-  Xgraph[N] = -1;
-  return (TRUE);
-}
-
-/* return pointers for current Xgraph, set if desired, test, open if needed */
-int GetGraph (Graphdata *data, int *socket, int *N) {
-
-  int i, n;
-  char buffer[70];
-
-  SetImageDevice (FALSE);
-  if (N == (int *) NULL) {
-    n = Active;
-  } else {
-    if (*N >= NXGRAPH) {
-      gprint (GP_ERR, "invalid Xgraph window %d\n", *N); 
-      return (FALSE);
-    }
-    if (*N < 0) {
-      *N = n = Active;
-    } else {
-      Active = n = *N;
-    }
-  }
-  
-  /* test Xgraph[0], flush junk from pipe */
-  signal (SIGPIPE, XGraphDead);
-  fcntl (Xgraph[n], F_SETFL,  O_NONBLOCK); 
-  for (i = 0; (read (Xgraph[n], buffer, 64) > 0) && (i < 20); i++);
-  fcntl (Xgraph[n], F_SETFL, !O_NONBLOCK); 
-  
-  if (Xgraph[n] < 1) {
-    if (!open_graph(n)) {
-      return (FALSE);
-    }
-  }
-
-  if (data != (Graphdata *) NULL) *data  = graphdata[n];
-  if (socket != (int *) NULL) *socket = Xgraph[n];
-
-  return (TRUE);
-
-}
-
-/* return pointers for given Xgraph, don't set or open */
-int GetGraphData (Graphdata *data, int *sock, int *N) {
-
-  int n;
-
-  if (N == (int *) NULL) {
-    n = Active;
-  } else {
-    if (*N >= NXGRAPH) {
-      gprint (GP_ERR, "invalid Xgraph window %d\n", *N); 
-      return (FALSE);
-    }
-    if (*N < 0) {
-      n = Active;
-    } else {
-      n = *N;
-    }
-  }
-  
-  if (data != (Graphdata *) NULL) *data  = graphdata[n];
-  if (sock != (int *) NULL) *sock = Xgraph[n];
-
-  return (TRUE);
-
-}
-
-/* assign given values to current Xgraph */
-void SetGraph (Graphdata data) {
-  graphdata[Active] = data;
-}
-
-/** internal tracking of current active device type **/
-
-static int       IsImage = FALSE;
-
-int GetCurrentDevice () {
-  return (IsImage);
-}
-
-void SetImageDevice (int state) {
-  IsImage = state;
-}
-
Index: unk/Ohana/src/opihi/lib.data/open_image.c
===================================================================
--- /trunk/Ohana/src/opihi/lib.data/open_image.c	(revision 27789)
+++ 	(revision )
@@ -1,133 +1,0 @@
-# include "display.h"
-# include "shell.h"
-# define DEBUG 0
-
-/* we have space for several kii windows */
-# define NXIMAGE 5
-
-static int       Active;
-static int       Ximage[NXIMAGE];  
-static char      Ximbuffer[NXIMAGE][512];
-static double    Xzero[NXIMAGE];
-static double    Xrange[NXIMAGE];
-
-void QuitImage () {
-
-  int i;
-  
-  for (i = 0; i < NXIMAGE; i++) {
-    KiiClose (Ximage[i]);
-  }
-}
-
-void InitImage () {
-
-  int i;
-
-  Active = 0;
-  for (i = 0; i < NXIMAGE; i++) {
-    Ximage[i] = -1;
-    Xzero[i] = 0;
-    Xrange[i] = 1024;
-    strcpy (Ximbuffer[i], "none");
-  }
-}
-
-/* set SIGPIPE to this function to close cleanly */ 
-void XImageDead (int input) {
-  signal (SIGPIPE, XImageDead);
-  gprint (GP_ERR, "kii is dead, must restart\n");
-  Ximage[Active] = -1;
-}
-
-/** start socketed connection */
-int open_image (int N) {
-
-  int fd;
-  char *kii_exec, name[16];
-
-  kii_exec = get_variable ("KII");
-  if (kii_exec == (char *) NULL) {
-    gprint (GP_ERR, "variable KII not found\n");
-    return (FALSE);
-  }
-
-  snprintf (name, 16, "[%d]", N);
-  fd = KiiOpen (kii_exec, name);
-  free (kii_exec);
-
-  if (fd < 0) {
-    gprint (GP_ERR, "error starting kii\n");
-    return (FALSE);
-  } 
-
-  Ximage[N] = fd;
-  return (TRUE);
-}
-
-int close_image (int N) {
-
-  if (N <  0) return (FALSE);
-  if (N >= NXIMAGE) return (FALSE);
-
-  KiiClose (Ximage[N]); 
-  Ximage[N] = -1;
-  return (TRUE);
-}
-
-/* return pointers for current Ximage, set if desired, test, open if needed */
-int GetImage (int *socket, int *N) {
-
-  int i, n;
-  char buffer[70];
-
-  SetImageDevice (TRUE);
-  if (N == (int *) NULL) {
-    n = Active;
-  } else {
-    if (*N >= NXIMAGE) {
-      gprint (GP_ERR, "invalid Ximage window %d\n", *N); 
-      return (FALSE);
-    }
-    if (*N < 0) {
-      *N = n = Active;
-    } else {
-      Active = n = *N;
-    }
-  }
-  
-  /* test Ximage[0], flush junk from pipe */
-  signal (SIGPIPE, XImageDead);
-  fcntl (Ximage[n], F_SETFL,  O_NONBLOCK); 
-  for (i = 0; (read (Ximage[n], buffer, 64) > 0) && (i < 20); i++);
-  fcntl (Ximage[n], F_SETFL, !O_NONBLOCK); 
-  
-  if (Ximage[n] < 1) {
-    if (!open_image(n)) {
-      return (FALSE);
-    }
-  }
-
-  if (socket != (int *) NULL) *socket = Ximage[n];
-
-  return (TRUE);
-
-}
-
-void SetImageName (char *name) {
-  strcpy (Ximbuffer[Active], name);
-}
-
-char *GetImageName () {
-  return (Ximbuffer[Active]);
-}
- 
-// leave this information on kapa, request when needed? 
-void SetImageScale (double zero, double range) {
-  Xzero[Active] = zero;
-  Xrange[Active] = range;
-}
-void GetImageScale (double *zero, double *range) {
-  *zero = Xzero[Active];
-  *range = Xrange[Active];
-}
Index: /trunk/Ohana/src/opihi/lib.shell/command.c
===================================================================
--- /trunk/Ohana/src/opihi/lib.shell/command.c	(revision 27789)
+++ /trunk/Ohana/src/opihi/lib.shell/command.c	(revision 27790)
@@ -2,5 +2,5 @@
 # define DEBUG 0
 
-static int VERBOSE_SHELL = FALSE;
+static int VERBOSE_SHELL = OPIHI_VERBOSE_OFF;
 
 int command (char *line, char **outline, int VERBOSE) {
@@ -10,6 +10,6 @@
   Command *cmd;
 
-  rawline = NULL;
-  // rawline = strcreate (line);
+  // rawline = NULL;
+  rawline = strcreate (line);
 
   /* force a space between ! and first word: !ls becomes ! ls */
@@ -24,4 +24,9 @@
   /* expand anything of the form fred[N] */ 
   line = expand_vectors (line);  /* line is freed here, new one allocated */
+
+  // print the line with the variables and vectors expanded, but before evaluating 
+  // any in-line math expression
+  if (VERBOSE_SHELL == OPIHI_VERBOSE_ON) gprint (GP_ERR, "opihi: %s\n", line);
+
   /* solve math expresions, assign variable, if needed */
   line = parse (line);        /* line is freed here, new one allocated */
@@ -31,6 +36,4 @@
   *outline = line;
   
-  if (VERBOSE_SHELL) gprint (GP_ERR, "opihi: %s\n", line);
-
   argv = parse_commands (line, &argc);
   if (argc == 0) {
@@ -60,5 +63,5 @@
     msg = get_variable_ptr ("ERRORMSG");
     if (msg != (char *) NULL) gprint (GP_ERR, "%s\n", msg);
-    if (VERBOSE_SHELL) gprint (GP_ERR, "error on line: %s\n", rawline);
+    if (VERBOSE_SHELL != OPIHI_VERBOSE_OFF) gprint (GP_ERR, "error on line: %s\n", rawline);
   }
 
Index: /trunk/Ohana/src/relphot/src/StarOps.c
===================================================================
--- /trunk/Ohana/src/relphot/src/StarOps.c	(revision 27789)
+++ /trunk/Ohana/src/relphot/src/StarOps.c	(revision 27790)
@@ -225,4 +225,5 @@
 	  }
 
+	  // XXX make it optional to apply Mcal (do I need an extra field for advisory Mcal?)
 	  list[N] = Msys - catalog[i].measure[m].Mcal;
 	  dlist[N] = MAX (catalog[i].measure[m].dM, MIN_ERROR);
Index: /trunk/Ohana/src/uniphot/Makefile
===================================================================
--- /trunk/Ohana/src/uniphot/Makefile	(revision 27789)
+++ /trunk/Ohana/src/uniphot/Makefile	(revision 27790)
@@ -1,5 +1,5 @@
-default: uniphot
+default: uniphot setphot
 help:
-	@echo "make options: uniphot (default)"
+@echo "make options: uniphot setphot default help install default (uniphot setphot)"
 
 include ../../Makefile.System
@@ -18,5 +18,6 @@
 
 uniphot: $(BIN)/uniphot.$(ARCH)
-install: $(DESTBIN)/uniphot
+setphot: $(BIN)/setphot.$(ARCH)
+install: $(DESTBIN)/uniphot $(DESTBIN)/setphot 
 
 UNIPHOT = \
@@ -24,5 +25,5 @@
 $(SRC)/initialize.$(ARCH).o	    \
 $(SRC)/ConfigInit.$(ARCH).o	    \
-$(SRC)/args.$(ARCH).o		    \
+$(SRC)/args.$(ARCH).o               \
 $(SRC)/liststats.$(ARCH).o	    \
 $(SRC)/load_images.$(ARCH).o	    \
@@ -39,2 +40,18 @@
 $(UNIPHOT): $(INC)/uniphot.h
 $(BIN)/uniphot.$(ARCH): $(UNIPHOT)
+
+SETPHOT = \
+$(SRC)/setphot.$(ARCH).o	    \
+$(SRC)/initialize.$(ARCH).o	    \
+$(SRC)/ConfigInit.$(ARCH).o	    \
+$(SRC)/args.$(ARCH).o               \
+$(SRC)/liststats.$(ARCH).o	    \
+$(SRC)/load_zpt_table.$(ARCH).o	    \
+$(SRC)/load_images.$(ARCH).o	    \
+$(SRC)/match_zpts_to_images.$(ARCH).o	    \
+$(SRC)/update_catalog_setphot.$(ARCH).o \
+$(SRC)/SetSignals.$(ARCH).o	    \
+$(SRC)/Shutdown.$(ARCH).o	    
+
+$(SETPHOT): $(INC)/uniphot.h
+$(BIN)/setphot.$(ARCH): $(SETPHOT)
Index: /trunk/Ohana/src/uniphot/include/uniphot.h
===================================================================
--- /trunk/Ohana/src/uniphot/include/uniphot.h	(revision 27789)
+++ /trunk/Ohana/src/uniphot/include/uniphot.h	(revision 27790)
@@ -39,4 +39,10 @@
 } Group;
 
+typedef struct {
+    float zpt;
+    e_time time;
+    int found;
+} ZptTable;
+
 /* global variables set in parameter file */
 char         ImageCat[256];
@@ -44,4 +50,7 @@
 char         CATMODE[16];    /* raw, mef, split, mysql */
 char         CATFORMAT[16];  /* internal, elixir, loneos, panstarrs */
+char         SKY_TABLE[256];
+int          SKY_DEPTH;  /** XXX EAM : depth of catalog tables, fix usage */
+char         GSCFILE[256];
 char         STATMODE[64];
 int          VERBOSE;
@@ -66,41 +75,50 @@
 
 /***** prototypes ****/
-void          ConfigInit         PROTO((int *argc, char **argv));
-void          DonePlotting       PROTO((Graphdata *graphmode, int N));
-void          JpegPlot           PROTO((Graphdata *graphmode, int N, char *filename));
-void          PSPlot             PROTO((Graphdata *graphmode, int N, char *filename));
-void          PlotLabel          PROTO((char *string, int N));
-void          PlotVector         PROTO((int Npts, double *vect, int mode, int N));
-void          PrepPlotting       PROTO((int Npts, Graphdata *graphmode, int N));
-void          XDead              PROTO((void));
-int           args               PROTO((int argc, char **argv));
-void          dumpresult         PROTO((void));
-Group        *find_image_sgroups PROTO((FITS_DB *db, ImageLink **imlink, int *Nsgroup));
-Group        *find_image_tgroups PROTO((FITS_DB *db, ImageLink **imlink, int *Ntgroup));
-void          fit_sgroup         PROTO((Group *sgroup, int Nsgroup));
-void          fit_tgroup         PROTO((Group *tgroup, int Ntgroup));
-int           gcatalog           PROTO((Catalog *catalog));
-void          initialize         PROTO((int argc, char **argv));
-void          initstats          PROTO((char *mode));
-int           liststats          PROTO((double *value, double *dvalue, int N, StatType *stats));
-int           load_images        PROTO((FITS_DB *db));
-int           main               PROTO((int argc, char **argv));
-int           open_graph         PROTO((int N));
-void          sort               PROTO((unsigned int *X, int N));
-void          sortB              PROTO((double *X, double *Y, int N));
-void          sortD              PROTO((double *X, double *Y, double *Z, int N));
-void          update_dvo_catalog PROTO((Catalog *catalog, Group *sgroup, int warn));
-void          wcatalog           PROTO((Catalog *catalog));
-void          wimages            PROTO((Image *image, int Nimage));
-void 	      check_permissions  PROTO((char *basefile));
-void 	      lock_image_db 	 PROTO((FITS_DB *db, char *filename));
-void	      unlock_image_db 	 PROTO((FITS_DB *db));
-void	      create_image_db 	 PROTO((FITS_DB *db));
-void	      set_db 		 PROTO((FITS_DB *in));
-int 	      Shutdown 		 PROTO((char *format, ...) OHANA_FORMAT(printf, 1, 2) );
-void 	      TrapSignal 	 PROTO((int sig));
-void 	      SetProtect 	 PROTO((int mode));
-int 	      SetSignals 	 PROTO((void));
-int 	      subset_images 	 PROTO((FITS_DB *db));
-void 	      update 		 PROTO((FITS_DB *db, Group *sgroup, int Nsgroup));
-void 	      sort_time 	 PROTO((unsigned int *value, int N));
+void          ConfigInit          PROTO((int *argc, char **argv));
+void          DonePlotting        PROTO((Graphdata *graphmode, int N));
+void          JpegPlot            PROTO((Graphdata *graphmode, int N, char *filename));
+void          PSPlot              PROTO((Graphdata *graphmode, int N, char *filename));
+void          PlotLabel           PROTO((char *string, int N));
+void          PlotVector          PROTO((int Npts, double *vect, int mode, int N));
+void          PrepPlotting        PROTO((int Npts, Graphdata *graphmode, int N));
+void          XDead               PROTO((void));
+int           args_uniphot        PROTO((int argc, char **argv));
+int           args_setphot        PROTO((int argc, char **argv));
+void          dumpresult          PROTO((void));
+Group        *find_image_sgroups  PROTO((FITS_DB *db, ImageLink **imlink, int *Nsgroup));
+Group        *find_image_tgroups  PROTO((FITS_DB *db, ImageLink **imlink, int *Ntgroup));
+void          fit_sgroup          PROTO((Group *sgroup, int Nsgroup));
+void          fit_tgroup          PROTO((Group *tgroup, int Ntgroup));
+int           gcatalog            PROTO((Catalog *catalog));
+void          initialize_uniphot  PROTO((int argc, char **argv));
+void          initialize_setphot  PROTO((int argc, char **argv));
+void          initstats           PROTO((char *mode));
+int           liststats           PROTO((double *value, double *dvalue, int N, StatType *stats));
+int           load_images_uniphot PROTO((FITS_DB *db));
+int           main                PROTO((int argc, char **argv));
+int           open_graph          PROTO((int N));
+void          sort                PROTO((unsigned int *X, int N));
+void          sortB               PROTO((double *X, double *Y, int N));
+void          sortD               PROTO((double *X, double *Y, double *Z, int N));
+void          update_dvo_catalog  PROTO((Catalog *catalog, Group *sgroup, int warn));
+void          wcatalog            PROTO((Catalog *catalog));
+void          wimages             PROTO((Image *image, int Nimage));
+void 	      check_permissions   PROTO((char *basefile));
+void 	      lock_image_db 	  PROTO((FITS_DB *db, char *filename));
+void	      unlock_image_db 	  PROTO((FITS_DB *db));
+void	      create_image_db 	  PROTO((FITS_DB *db));
+void	      set_db 		  PROTO((FITS_DB *in));
+int 	      Shutdown 		  PROTO((char *format, ...) OHANA_FORMAT(printf, 1, 2) );
+void 	      TrapSignal 	  PROTO((int sig));
+void 	      SetProtect 	  PROTO((int mode));
+int 	      SetSignals 	  PROTO((void));
+int 	      subset_images 	  PROTO((FITS_DB *db));
+void 	      update 		  PROTO((FITS_DB *db, Group *sgroup, int Nsgroup));
+void 	      sort_time 	  PROTO((unsigned int *value, int N));
+
+// setphot-specific prototypes
+ZptTable     *load_zpt_table         PROTO((char *filename, int *nzpts));
+Image        *load_images_setphot    PROTO((FITS_DB *db, off_t *Nimage));
+int           match_zpts_to_images   PROTO((Image *image, off_t Nimage, ZptTable *zpts, int Nzpts));
+int           update_setphot         PROTO((Image *image, off_t Nimage));
+void          update_catalog_setphot PROTO((Catalog *catalog, Image *image, off_t *index, off_t Nimage));
Index: /trunk/Ohana/src/uniphot/src/ConfigInit.c
===================================================================
--- /trunk/Ohana/src/uniphot/src/ConfigInit.c	(revision 27789)
+++ /trunk/Ohana/src/uniphot/src/ConfigInit.c	(revision 27790)
@@ -1,3 +1,5 @@
 # include "uniphot.h"
+
+void GetConfig (char *config, char *field, char *format, int N, void *ptr);
 
 void ConfigInit (int *argc, char **argv) {
@@ -18,5 +20,5 @@
   if (VERBOSE) fprintf (stderr, "loaded config file: %s\n", file);
 
-  ScanConfig (config, "CATDIR",                 "%s",  0, CATDIR);
+  GetConfig (config, "CATDIR",                 "%s",  0, CATDIR);
   ScanConfig (config, "CATMODE",                "%s",  0, CATMODE);
   ScanConfig (config, "CATFORMAT",              "%s",  0, CATFORMAT);
@@ -24,4 +26,12 @@
 
   sprintf (ImageCat, "%s/Images.dat", CATDIR);
+
+  GetConfig (config, "GSCFILE",                 "%s",  0, GSCFILE);
+  if (!ScanConfig (config, "SKY_DEPTH",         "%d",  0, &SKY_DEPTH)) {
+    SKY_DEPTH = 2;
+  }
+  if (!ScanConfig (config, "SKY_TABLE",         "%s",  0, SKY_TABLE)) {
+    SKY_TABLE[0] = 0;
+  }
 
   ScanConfig (config, "ZERO_PT",                "%lf", 0, &ZERO_POINT);
@@ -42,2 +52,14 @@
 
 }
+
+void GetConfig (char *config, char *field, char *format, int N, void *ptr) {
+
+  char *status;
+
+  status = ScanConfig (config, field, format, N, ptr);
+  if (status == NULL) {
+    fprintf (stderr, "error in config, cannot find %s\n", field);
+    exit (1);
+  }
+  return;
+}
Index: /trunk/Ohana/src/uniphot/src/Shutdown.c
===================================================================
--- /trunk/Ohana/src/uniphot/src/Shutdown.c	(revision 27789)
+++ /trunk/Ohana/src/uniphot/src/Shutdown.c	(revision 27790)
@@ -23,5 +23,5 @@
   SetProtect (TRUE);
   gfits_db_close (db);
-  fprintf (stderr, "ERROR: addstar halted\n");
+  fprintf (stderr, "ERROR: halted\n");
   exit (1);
 }
Index: /trunk/Ohana/src/uniphot/src/args.c
===================================================================
--- /trunk/Ohana/src/uniphot/src/args.c	(revision 27789)
+++ /trunk/Ohana/src/uniphot/src/args.c	(revision 27790)
@@ -1,5 +1,5 @@
 # include "uniphot.h"
 
-int args (int argc, char **argv) {
+int args_uniphot (int argc, char **argv) {
 
   int N;
@@ -72,2 +72,26 @@
 }
 
+int args_setphot (int argc, char **argv) {
+
+  int N;
+
+  VERBOSE = FALSE;
+  if ((N = get_argument (argc, argv, "-v"))) {
+    VERBOSE = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  UPDATE = FALSE;
+  if ((N = get_argument (argc, argv, "-update"))) {
+    remove_argument (N, &argc, argv);
+    UPDATE = TRUE;
+  }
+
+  if (argc != 2) {
+    fprintf (stderr, "ERROR: USAGE: setphot (zptfile) [options]\n");
+    exit (2);
+  } 
+
+  return (TRUE);
+}
+
Index: /trunk/Ohana/src/uniphot/src/initialize.c
===================================================================
--- /trunk/Ohana/src/uniphot/src/initialize.c	(revision 27789)
+++ /trunk/Ohana/src/uniphot/src/initialize.c	(revision 27790)
@@ -1,9 +1,9 @@
 # include "uniphot.h"
 
-void initialize (int argc, char **argv) {
+void initialize_uniphot (int argc, char **argv) {
 
   /* are these set correctly? */
   ConfigInit (&argc, argv);
-  args (argc, argv);
+  args_uniphot (argc, argv);
 
   if ((photcode = GetPhotcodebyName (argv[1])) == NULL) {
@@ -21,2 +21,9 @@
 }
 
+void initialize_setphot (int argc, char **argv) {
+
+  /* are these set correctly? */
+  ConfigInit (&argc, argv);
+  args_setphot (argc, argv);
+}
+
Index: /trunk/Ohana/src/uniphot/src/load_images.c
===================================================================
--- /trunk/Ohana/src/uniphot/src/load_images.c	(revision 27789)
+++ /trunk/Ohana/src/uniphot/src/load_images.c	(revision 27790)
@@ -1,5 +1,5 @@
 # include "uniphot.h"
 
-int load_images (FITS_DB *db) {
+int load_images_uniphot (FITS_DB *db) {
 
   if (VERBOSE) fprintf (stderr, "finding images\n");
@@ -10,2 +10,19 @@
   return (TRUE);
 }
+
+Image *load_images_setphot (FITS_DB *db, off_t *Nimage) {
+
+  Image *image;
+
+  if (VERBOSE) fprintf (stderr, "finding images\n");
+
+  /* read entire db table */
+  if (!dvo_image_load (db, VERBOSE, FALSE)) Shutdown ("can't read image catalog %s", db[0].filename);
+
+  /* use a vtable to keep the images to be calibrated */
+  image = gfits_table_get_Image (&db[0].ftable, Nimage, &db[0].swapped);
+
+  fprintf (stderr, "loaded %lld images\n", (long long) *Nimage);
+
+  return (image);
+}
Index: /trunk/Ohana/src/uniphot/src/load_zpt_table.c
===================================================================
--- /trunk/Ohana/src/uniphot/src/load_zpt_table.c	(revision 27790)
+++ /trunk/Ohana/src/uniphot/src/load_zpt_table.c	(revision 27790)
@@ -0,0 +1,41 @@
+# include "uniphot.h"
+
+ZptTable *load_zpt_table (char *filename, int *nzpts) {
+
+  int Nzpts, NZPTS;
+  ZptTable *zpts;
+  double zpt, mjd;
+
+  FILE *f;
+
+  f = fopen (filename, "r");
+  if (!f) {
+    fprintf (stderr, "ERROR: cannot open zpt table file %s\n", filename);
+    exit (1);
+  }
+
+  Nzpts = 0;
+  NZPTS = 100;
+  ALLOCATE (zpts, ZptTable, NZPTS);
+
+  // format is fixed: (time) (zpt)
+  int status;
+  while ((status = fscanf (f, "%lf %lf", &mjd, &zpt)) == 2) {
+    zpts[Nzpts].zpt = zpt;
+    zpts[Nzpts].time = ohana_mjd_to_sec (mjd);
+    zpts[Nzpts].found = FALSE;
+
+    Nzpts ++;
+    CHECK_REALLOCATE (zpts, ZptTable, NZPTS, Nzpts, 100);
+  }
+
+  if (status != EOF) {
+    fprintf (stderr, "unexpected formatting on line %d\n", Nzpts);
+    exit (2);
+  }
+
+  fprintf (stderr, "loaded %d zero points\n", Nzpts);
+
+  *nzpts = Nzpts;
+  return zpts;
+}
Index: /trunk/Ohana/src/uniphot/src/match_zpts_to_images.c
===================================================================
--- /trunk/Ohana/src/uniphot/src/match_zpts_to_images.c	(revision 27790)
+++ /trunk/Ohana/src/uniphot/src/match_zpts_to_images.c	(revision 27790)
@@ -0,0 +1,90 @@
+# include "uniphot.h"
+
+/* sort a coordinate pair (X,Y) and the associated index (S) */
+static void sort_zpts_by_time (ZptTable *zpts, int Nzpts) {
+  
+# define SWAPFUNC(A,B){ ZptTable tmp;		\
+    tmp = zpts[A]; zpts[A] = zpts[B]; zpts[B] = tmp;	\
+  }
+# define COMPARE(A,B)(zpts[A].time < zpts[B].time)
+
+  OHANA_SORT (Nzpts, COMPARE, SWAPFUNC);
+
+# undef SWAPFUNC
+# undef COMPARE
+}
+
+# define SCALE 0.001
+
+int match_zpts_to_images (Image *image, off_t Nimage, ZptTable *zpts, int Nzpts) {
+
+  // I have two lists.  I need to match images->tzero to zpts->time.  multiple images may match a single zpt
+  
+  // sort both lists by time (or at least get sorted indices)
+  // sweep through both lists, advancing the one that is lagging
+  // apply the matches
+
+  int dT, NImatch, Nmatch;
+  off_t i, Ni, Nz, *index;
+  PhotCode *code;
+
+  // create index and sort
+  ALLOCATE (index, off_t, Nimage);
+  for (i = 0; i < Nimage; i++) {
+    index[i] = i;
+  }
+  sort_image_subset(image, index, Nimage);  // slightly misnamed sort function from libdvo
+
+  // sort the zpts
+  sort_zpts_by_time (zpts, Nzpts);
+
+  NImatch = 0; // matched images
+  for (i = Nz = 0; (i < Nimage) && (Nz < Nzpts); ) {
+
+    if (i % 1000 == 0) fprintf (stderr, ".");
+    if (Nz % 100 == 0) fprintf (stderr, "!");
+
+    Ni = index[i];
+    dT = image[Ni].tzero - zpts[Nz].time;
+
+    // negative dT, i is too small (allow a 1sec overlap window)
+    if (dT < -1) {
+      i++;
+      continue;
+    }
+
+    // XXX careful about definition of image->tzero and zpt->time
+    // negative dT, i is too small (allow a 1sec overlap window)
+    if (dT > +1) {
+      Nz++;
+      continue;
+    }
+
+    // check that we have a valid photcode (skip mosaic images)
+    code = GetPhotcodebyCode(image[Ni].photcode);
+    if (!code) { 
+      i++;
+      continue;
+    }
+
+    // we have a match: set zpt and record the match
+    image[Ni].Mcal = SCALE*code[0].C - zpts[Nz].zpt;
+    image[Ni].flags &= ~ID_IMAGE_NOCAL; // clear the NOCAL flag
+    zpts[Nz].found = TRUE;
+    NImatch ++;
+
+    // advance the image counter only -- a single zpt may match more than one image
+    i++;
+  }
+
+  // how many zpts have we matched?
+  Nmatch = 0;
+  for (Nz = 0; Nz < Nzpts; Nz++) {
+    if (zpts[Nz].found) Nmatch ++;
+  }
+
+  fprintf (stderr, "found %d zpt matches, %d image matches\n", Nmatch, NImatch);
+
+  return (TRUE);
+}
+
Index: /trunk/Ohana/src/uniphot/src/setphot.c
===================================================================
--- /trunk/Ohana/src/uniphot/src/setphot.c	(revision 27790)
+++ /trunk/Ohana/src/uniphot/src/setphot.c	(revision 27790)
@@ -0,0 +1,49 @@
+# include "uniphot.h"
+
+int main (int argc, char **argv) {
+
+  off_t Nimage;
+  int status, Nzpts;
+  FITS_DB db;
+  ZptTable *zpts;
+  Image *image;
+
+  /* get configuration info, args, lockfile */
+  initialize_setphot (argc, argv);
+
+  set_db (&db);
+  status = dvo_image_lock (&db, ImageCat, 60.0, (UPDATE ? LCK_XCLD : LCK_SOFT));
+  if (!status) Shutdown ("ERROR: failure to lock image catalog %s", db.filename);
+  if (db.dbstate == LCK_EMPTY) Shutdown ("ERROR: No images in catalog %s (1)", db.filename);
+
+  zpts = load_zpt_table (argv[1], &Nzpts);
+
+  // load images 
+  image  = load_images_setphot (&db, &Nimage);
+  if (!UPDATE) dvo_image_unlock (&db); 
+  
+  match_zpts_to_images (image, Nimage, zpts, Nzpts);
+
+  update_setphot(image, Nimage);
+
+  // write image table
+  if (UPDATE) {
+    dvo_image_save (&db, VERBOSE);
+  }
+
+  exit (0);
+}
+  
+
+/* setphot : set the zero points for images in the db (perhaps based on external information)
+   setphot (zpt_table)
+
+ * load text table of zpts, time (photcode?)
+ * load images
+ * match images to zpts
+ * set zpts
+ * load catalogs
+ * update detection (& averages?)
+
+ */
+
Index: /trunk/Ohana/src/uniphot/src/uniphot.c
===================================================================
--- /trunk/Ohana/src/uniphot/src/uniphot.c	(revision 27789)
+++ /trunk/Ohana/src/uniphot/src/uniphot.c	(revision 27790)
@@ -9,5 +9,5 @@
 
   /* get configuration info, args, lockfile */
-  initialize (argc, argv);
+  initialize_uniphot (argc, argv);
 
   set_db (&db);
@@ -18,5 +18,5 @@
 
   /* load images */
-  load_images (&db);
+  load_images_uniphot (&db);
   
   /* filter image list by selection */
Index: /trunk/Ohana/src/uniphot/src/update_catalog_setphot.c
===================================================================
--- /trunk/Ohana/src/uniphot/src/update_catalog_setphot.c	(revision 27790)
+++ /trunk/Ohana/src/uniphot/src/update_catalog_setphot.c	(revision 27790)
@@ -0,0 +1,97 @@
+# include "uniphot.h"
+# include <glob.h>
+
+int update_setphot (Image *image, off_t Nimage) {
+
+  SkyRegion UserPatch;
+  SkyTable *sky = NULL;
+  SkyList *skylist = NULL;
+  Catalog catalog;
+  off_t i, maxID, *index;
+
+  // create an index for the image IDs
+  maxID = 0;
+  for (i = 0; i < Nimage; i++) {
+    maxID = MAX(maxID, image[i].imageID);
+  }
+  ALLOCATE (index, off_t, maxID + 1);
+  for (i = 0; i < Nimage; i++) {
+    if (!image[i].imageID) continue; // images with ID == 0 are virtual
+    index[image[i].imageID] = i;
+  }
+  
+
+  // load the current sky table (layout of all SkyRegions) 
+  sky = SkyTableLoadOptimal (CATDIR, SKY_TABLE, GSCFILE, TRUE, SKY_DEPTH, VERBOSE);
+  SkyTableSetFilenames (sky, CATDIR, "cpt");
+  
+  // determine the populated SkyRegions overlapping the requested area (default depth)
+  UserPatch.Rmin = 0;
+  UserPatch.Rmax = 360;
+  UserPatch.Dmin = -90;
+  UserPatch.Dmax = +90;
+  skylist = SkyListByPatch (sky, -1, &UserPatch);
+
+  // update measurements for each populated catalog
+  for (i = 0; i < skylist[0].Nregions; i++) {
+
+    // set up the basic catalog info
+    catalog.filename  = skylist[0].filename[i];
+    catalog.catformat = dvo_catalog_catformat (CATFORMAT);    // set the default catformat from config data
+    catalog.catmode   = dvo_catalog_catmode (CATMODE);        // set the default catmode from config data
+    catalog.catflags  = LOAD_AVES | LOAD_MEAS | LOAD_MISS | LOAD_SECF;
+    catalog.Nsecfilt  = GetPhotcodeNsecfilt ();
+
+    if (!dvo_catalog_open (&catalog, skylist[0].regions[i], VERBOSE, "w")) {
+      fprintf (stderr, "ERROR: failure reading catalog %s\n", catalog.filename);
+      exit (1);
+    }
+    if (!catalog.Naves_disk) {
+      if (VERBOSE) fprintf (stderr, "no data in %s, skipping\n", catalog.filename);
+      dvo_catalog_unlock (&catalog);
+      dvo_catalog_free (&catalog);
+      continue;
+    }
+
+    update_catalog_setphot (&catalog, image, index, Nimage);
+
+    if (!UPDATE) {
+      dvo_catalog_unlock (&catalog);
+      dvo_catalog_free (&catalog);
+      continue;
+    }
+    
+    if (VERBOSE) fprintf (stderr, "saving catalog %s\n", catalog.filename);
+    
+    dvo_catalog_save (&catalog, VERBOSE); 
+    dvo_catalog_unlock (&catalog);
+    dvo_catalog_free (&catalog);
+  }
+  return (TRUE);
+}      
+
+void update_catalog_setphot (Catalog *catalog, Image *image, off_t *index, off_t Nimage) {
+
+  off_t i, j, m, id, idx, found;
+  float Mcal;
+
+  found = 0;    
+  for (i = 0; i < catalog[0].Naverage; i++) {
+
+    m = catalog[0].average[i].measureOffset;
+    for (j = 0; j < catalog[0].average[i].Nmeasure; j++, m++) {
+      idx = catalog[0].measure[m].imageID;
+      if (idx <= 0) continue; // detections with imageID == 0 do not have a valid image (eg, ref photcode)
+
+      id = index[idx];
+      Mcal = image[id].Mcal;
+
+      catalog[0].measure[m].Mcal = image[id].Mcal;
+      found ++;
+    }
+  }
+
+  if (found) {
+    fprintf (stderr, "found %lld matches\n", (long long) found);
+  }
+}
