Index: trunk/Ohana/src/opihi/lib.data/open_kapa.c
===================================================================
--- trunk/Ohana/src/opihi/lib.data/open_kapa.c	(revision 13344)
+++ trunk/Ohana/src/opihi/lib.data/open_kapa.c	(revision 13344)
@@ -0,0 +1,226 @@
+# include "display.h"
+# include "shell.h"
+
+/* kapa support for the new version of kapa (v2.0), which has both graph and image
+ * elements merged into a single display device.  The user may now open an arbitrary
+ * number of kapa windows, and the display information is retrieved from kapa across the
+ * socket when it is needed.  Communication is now via an INET socket (not a UNIX socket).
+ */
+
+/* list of available socket connections */
+static int        Active;        // currently active socket (not device)
+static int       *Socket = NULL; // list of available sockets
+static int       *Device = NULL; // list of device numbers for each socked
+static int       Nsocket = 0;    // number of available sockets / devices
+
+void InitKapa () {
+
+  Active  = -1;		      // -1 is the INVALID entry
+  Nsocket = 0;		      // number of defined sockets
+  ALLOCATE (Device, int, 1);
+  ALLOCATE (Socket, int, 1);
+  Device[Active] = 0;  
+  Socket[Active] = 0;  
+}
+
+// returns the number of the requested device, or -1 if not found
+int FindKapaDevice (int thisDevice) {
+
+  int i;
+
+  for (i = 0; i < Nsocket; i++) {
+    if (Device[i] == thisDevice) {
+      return (i);
+    }
+  }
+  return (-1);
+}
+
+// set the active device to the given device number, open if needed
+int open_kapa (int thisDevice) {
+
+  int fd, entry;
+  char *kapa_exec, name[16];
+
+  // find the given device number, or create. set this to active
+  entry = FindKapaDevice (thisDevice);
+  if (entry < 0) {
+    Active = Nsocket;
+    Nsocket ++;
+    REALLOCATE (Device, int, Nsocket);
+    REALLOCATE (Socket, int, Nsocket);
+    Device[Active] = -1;
+    Socket[Active] = -1;
+  } else {
+    Active = entry;
+  }
+
+  // if the (now) active socket is not open, open it
+  if (Socket[Active] < 0) {
+    kapa_exec = get_variable ("KAPA");
+    if (kapa_exec == (char *) NULL) {
+      gprint (GP_ERR, "variable KAPA not found\n");
+      return (FALSE);
+    }
+
+    // KAPA may be either kapa://host or /path/to/program
+
+    snprintf (name, 16, "[%d]", thisDevice);
+    fd = KapaOpen (kapa_exec, name);
+    free (kapa_exec);
+
+    if (fd < 0) {
+      gprint (GP_ERR, "error starting kapa\n");
+      // delete the active entry
+      return (FALSE);
+    } 
+    Device[Active] = thisDevice;
+    Socket[Active] = fd;
+  } 
+  return (TRUE);
+}
+
+/**************** graph ops */
+
+// XXX for now, use a local variable.  later: get from kapa
+static Graphdata graphdata;
+
+void InitGraph () {
+  graphdata.xmin = graphdata.ymin = 0.0;
+  graphdata.xmax = graphdata.ymax = 1.0;
+  graphdata.style = graphdata.ptype = 0;
+  graphdata.ltype = graphdata.color = 0;
+  graphdata.etype = graphdata.ebar = 0;
+  graphdata.lweight = graphdata.size = 1.0;
+    
+  graphdata.coords.pc1_1 = graphdata.coords.pc2_2 = 1.0;
+  graphdata.coords.pc1_2 = graphdata.coords.pc2_1 = 0.0;
+  strcpy (graphdata.coords.ctype, "RA---LIN");
+  graphdata.coords.crval1 = 0.0;
+  graphdata.coords.crval2 = 0.0;
+  graphdata.coords.crpix1 = 0.0;
+  graphdata.coords.crpix2 = 0.0;
+  graphdata.coords.cdelt1 = graphdata.coords.cdelt2 = 1.0;
+  graphdata.flipeast = TRUE;
+  graphdata.flipnorth = FALSE;
+  strcpy (graphdata.axis, "2222");
+  strcpy (graphdata.ticks, "2222");
+  strcpy (graphdata.labels, "2222");
+}
+
+# if (0)
+  /* test Xgraph[0], flush junk from pipe */
+  signal (SIGPIPE, XGraphDead);
+  fcntl (Socket[n], F_SETFL,  O_NONBLOCK); 
+  for (i = 0; (read (Socket[n], buffer, 64) > 0) && (i < 20); i++);
+  fcntl (Socket[n], F_SETFL, !O_NONBLOCK); 
+# endif
+
+/* return pointers for current Xgraph, set if desired, test, open if needed */
+int GetGraph (Graphdata *data, int *fd, int *dev) {
+
+  int thisDevice;
+
+  SetImageDevice (FALSE);
+  if (dev == NULL) {
+    if (Active < 0) {
+      thisDevice = 0;
+    } else {
+      thisDevice = Device[Active];
+    }
+  } else {
+    thisDevice = *dev;
+  }
+  
+  if (!open_kapa (thisDevice)) {
+    return (FALSE);
+  }
+  
+  if (data != NULL) *data = graphdata;
+  if (fd != NULL) *fd = Socket[Active];
+
+  return (TRUE);
+}
+
+/* return pointers for given Xgraph, don't set or open */
+int GetGraphData (Graphdata *data, int *fd, int *dev) {
+
+  int n;
+
+  if (dev == NULL) {
+    if (Active < 0) {
+      gprint (GP_ERR, "invalid Xgraph window %d\n", *dev); 
+      return (FALSE);
+    }
+    *fd = Socket[Active];
+    return (TRUE);
+  } 
+
+  n = FindKapaDevice (*dev);
+  if (n < 0) {
+    gprint (GP_ERR, "invalid Xgraph window %d\n", *dev); 
+    return (FALSE);
+  }
+
+  Active = n;
+
+  if (fd != NULL) *fd = Socket[Active];
+  if (data != NULL) *data = graphdata;
+
+  return (TRUE);
+}
+
+/* assign given values to current Xgraph */
+void SetGraph (Graphdata data) {
+  graphdata = data;
+}
+
+/** internal tracking of current active device type **/
+/* drop this stuff */
+static int       IsImage = FALSE;
+
+int GetCurrentDevice () {
+  return (IsImage);
+}
+
+void SetImageDevice (int state) {
+  IsImage = state;
+}
+
+/************* image ops ***********/
+// XXX for now, use local static:
+
+static char      Ximbuffer[512];
+static double    Xzero;
+static double    Xrange;
+
+void InitImage () {
+  Xzero = 0;
+  Xrange = 1024;
+  strcpy (Ximbuffer, "none");
+}
+
+/* return pointers for current Ximage, set if desired, test, open if needed */
+int GetImage (int *fd, int *N) {
+  int status;
+  status = GetGraph (NULL, fd, N);
+  return (status);
+}
+
+void SetImageName (char *name) {
+  strcpy (Ximbuffer, name);
+}
+
+char *GetImageName () {
+  return (Ximbuffer);
+}
+ 
+// leave this information on kapa, request when needed? 
+void SetImageScale (double zero, double range) {
+  Xzero = zero;
+  Xrange = range;
+}
+void GetImageScale (double *zero, double *range) {
+  *zero = Xzero;
+  *range = Xrange;
+}
