Index: /branches/eam_branch_20080124/Ohana/src/kapa2/.cvsignore
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/.cvsignore	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/.cvsignore	(revision 16062)
@@ -0,0 +1,1 @@
+bin
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/Makefile
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/Makefile	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/Makefile	(revision 16062)
@@ -0,0 +1,93 @@
+default: kapa
+help:
+	@echo "make options: kapa (default)"
+
+include ../../Makefile.System
+HOME 	=	$(ROOT)/src/kapa2
+LIB	=	$(HOME)/lib
+BIN	=	$(HOME)/bin
+LIB	=	$(HOME)/lib
+SRC	=	$(HOME)/src
+INC	=	$(HOME)/include
+include ../../Makefile.Common
+
+# programs may add their own internal requirements here
+FULL_CFLAGS   = $(BASE_CFLAGS)
+FULL_CPPFLAGS = $(BASE_CPPFLAGS)
+FULL_LDFLAGS  = -lkapa -ldvo -lFITS -lohana $(BASE_LDFLAGS)
+
+LDDEPS  = $(DESTLIB)/libkapa.a $(DESTLIB)/libdvo.a $(DESTLIB)/libFITS.a $(DESTLIB)/libohana.a
+INDEPS  = $(DESTINC)/kapa.h $(DESTINC)/dvo.h $(DESTINC)/gfitsio.h $(DESTINC)/ohana.h
+
+kapa: $(BIN)/kapa.$(ARCH)
+install: $(DESTBIN)/kapa
+
+KAPA = \
+$(SRC)/kapa.$(ARCH).o                     $(SRC)/args.$(ARCH).o               \
+$(SRC)/SetUpGraphic.$(ARCH).o             $(SRC)/NameWindow.$(ARCH).o         \
+$(SRC)/CheckColors.$(ARCH).o              $(SRC)/MakeGC.$(ARCH).o             \
+$(SRC)/CheckDisplayName.$(ARCH).o  	  $(SRC)/MapWindow.$(ARCH).o          \
+$(SRC)/CheckGeometry.$(ARCH).o     	  $(SRC)/OpenDisplay.$(ARCH).o        \
+$(SRC)/CloseDisplay.$(ARCH).o      	  $(SRC)/QuitX.$(ARCH).o              \
+$(SRC)/CreateWindow.$(ARCH).o      	  $(SRC)/SetNormalHints.$(ARCH).o     \
+$(SRC)/GetColor.$(ARCH).o          	  $(SRC)/SetWMHints.$(ARCH).o         \
+$(SRC)/LoadFont.$(ARCH).o          	  $(SRC)/TopWindow.$(ARCH).o          \
+$(SRC)/MakeCursor.$(ARCH).o		  $(SRC)/FlushDisplay.$(ARCH).o       \
+$(SRC)/LoadObject.$(ARCH).o		  $(SRC)/LoadFrame.$(ARCH).o	      \
+$(SRC)/LoadTextlines.$(ARCH).o		  $(SRC)/LoadLabels.$(ARCH).o         \
+$(SRC)/DrawObjects.$(ARCH).o              $(SRC)/DrawFrame.$(ARCH).o          \
+$(SRC)/DrawTextlines.$(ARCH).o		  $(SRC)/DrawLabels.$(ARCH).o         \
+$(SRC)/PSObjects.$(ARCH).o		  $(SRC)/PSFrame.$(ARCH).o            \
+$(SRC)/PSLabels.$(ARCH).o		  $(SRC)/PSTextlines.$(ARCH).o        \
+$(SRC)/bDrawObjects.$(ARCH).o	  	  $(SRC)/bDrawFrame.$(ARCH).o         \
+$(SRC)/bDrawLabels.$(ARCH).o              $(SRC)/bDrawIt.$(ARCH).o            \
+$(SRC)/PNGit.$(ARCH).o                    $(SRC)/PPMit.$(ARCH).o	      \
+$(SRC)/PSit.$(ARCH).o                     $(SRC)/CrossHairs.$(ARCH).o         \
+$(SRC)/CheckPipe.$(ARCH).o                $(SRC)/EventLoop.$(ARCH).o          \
+$(SRC)/Reconfig.$(ARCH).o                 $(SRC)/Refresh.$(ARCH).o            \
+$(SRC)/Layout.$(ARCH).o		  	  $(SRC)/Sections.$(ARCH).o	      \
+$(SRC)/Graphs.$(ARCH).o                   $(SRC)/SetGraphSize.$(ARCH).o       \
+$(SRC)/Resize.$(ARCH).o                   $(SRC)/ErasePlots.$(ARCH).o         \
+$(SRC)/EraseImage.$(ARCH).o         	  $(SRC)/SetToolbox.$(ARCH).o         \
+$(SRC)/EraseCurrentPlot.$(ARCH).o         $(SRC)/EraseSections.$(ARCH).o      \
+$(SRC)/SetSection.$(ARCH).o		  $(SRC)/DefineSection.$(ARCH).o      \
+$(SRC)/SetLimits.$(ARCH).o                $(SRC)/SetFont.$(ARCH).o            \
+$(SRC)/Center.$(ARCH).o                   $(SRC)/Remap.$(ARCH).o              \
+$(SRC)/Remap8.$(ARCH).o                   $(SRC)/Remap16.$(ARCH).o            \
+$(SRC)/Remap24.$(ARCH).o                  $(SRC)/Remap32.$(ARCH).o            \
+$(SRC)/LoadPicture.$(ARCH).o              $(SRC)/Image.$(ARCH).o              \
+$(SRC)/SetImageSize.$(ARCH).o             $(SRC)/GetPixelCount.$(ARCH).o      \
+$(SRC)/StatusBox.$(ARCH).o                $(SRC)/UpdateStatusBox.$(ARCH).o    \
+$(SRC)/DrawButton.$(ARCH).o               $(SRC)/DrawBitmap.$(ARCH).o         \
+$(SRC)/hh_hms.$(ARCH).o	                  $(SRC)/CreateZoom.$(ARCH).o         \
+$(SRC)/CreateZoom8.$(ARCH).o              $(SRC)/CreateZoom16.$(ARCH).o       \
+$(SRC)/CreateZoom24.$(ARCH).o             $(SRC)/CreateZoom32.$(ARCH).o       \
+$(SRC)/CreatePicture.$(ARCH).o            $(SRC)/CreateColorbar.$(ARCH).o     \
+$(SRC)/MakeColormap.$(ARCH).o		  $(SRC)/SetColormap.$(ARCH).o        \
+$(SRC)/PaintOverlay.$(ARCH).o		  $(SRC)/SetGraphData.$(ARCH).o       \
+$(SRC)/LoadOverlay.$(ARCH).o		  $(SRC)/EraseOverlay.$(ARCH).o       \
+$(SRC)/SaveOverlay.$(ARCH).o              $(SRC)/SetImageData.$(ARCH).o       \
+$(SRC)/CSaveOverlay.$(ARCH).o		  $(SRC)/EraseOverlay.$(ARCH).o       \
+$(SRC)/CheckVisual.$(ARCH).o              $(SRC)/CursorOps.$(ARCH).o          \
+$(SRC)/InterpretKeys.$(ARCH).o            $(SRC)/InterpretPresses.$(ARCH).o   \
+$(SRC)/DragColorbar.$(ARCH).o             $(SRC)/Reorient.$(ARCH).o           \
+$(SRC)/InButton.$(ARCH).o                 $(SRC)/InPicture.$(ARCH).o          \
+$(SRC)/CheckButtons.$(ARCH).o             $(SRC)/InvertButton.$(ARCH).o       \
+$(SRC)/UpdatePointer.$(ARCH).o            $(SRC)/JPEGit24.$(ARCH).o           \
+$(SRC)/bDrawOverlay.$(ARCH).o             $(SRC)/ButtonFunctions.$(ARCH).o    \
+$(SRC)/PSimage.$(ARCH).o                  $(SRC)/PSPixmap.$(ARCH).o           \
+$(SRC)/PSOverlay.$(ARCH).o                $(SRC)/SetChannel.$(ARCH).o         \
+$(SRC)/SetColorScale.$(ARCH).o            $(SRC)/ColorCube.$(ARCH).o          \
+$(SRC)/ColorHistogram.$(ARCH).o           
+
+OBJ  =  $(KAPA)
+
+# dependancy rules for include files ########################
+$(OBJ): $(INC)/Ximage.h \
+	$(INC)/constants.h \
+	$(INC)/structures.h \
+	$(INC)/prototypes.h
+
+$(OBJ): $(INDEPS) $(LDDEPS)
+
+$(BIN)/kapa.$(ARCH): $(OBJ)
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/doc/UpgradeConcepts.txt
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/doc/UpgradeConcepts.txt	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/doc/UpgradeConcepts.txt	(revision 16062)
@@ -0,0 +1,54 @@
+
+2007.05.08
+
+  User Commands:
+  * Add a section (position, type, name)
+  * Add a section element (add graph, add image)
+  * Del a section (by name)
+  * Del a section element (del graph, del image)
+  * Resize window (resizes each section)
+  * Set active section
+  * Get active section
+
+2007.05.06
+
+I am examining plans to upgrade the Kapa / Kii programs.  I have several ideas on this topic:
+
+* Completely merge the code base.  There are many common features, and
+  the merge will be easy.  The biggest difference between them from a
+  programming point of view is that Kapa uses global variables for the
+  layout and graphic (and other minor data), while Kii passes around
+  the Graphic / Layout elements.
+
+  The more object-oriented way to do this is to have private static
+  data for these concepts and to provide accessor functions to operate
+  on or retreive these pointers.  
+
+* Allow an arbitrary number of the graph / image widgets.  The image
+  widget should be considered a single item, which includes the main
+  image window, the zoom box, the status box, the buttons, etc.  The
+  positioning of the multiple graph / image elements in a single
+  window could be equivalent to the 'section' command for the graph
+  sub-boxes.  An image or a graph could be place at any X,Y,dX,dY
+  position with X,Y having a range of 0-1.  In addition, a graph
+  could be optionally tied to a specific image, with the location
+  determined by the image window location (ie, outer box of the image
+  window matched to bounding box of the graph).
+
+* Event parsing would need to go through the list of graph / image
+  elements to determine if the corresond to any of them.  
+
+* Drawing should be done in the order: images first, graphs second.
+  The sequence for the images and / or graphs should be adjustable.
+
+* create an equivalent to the zoom box which is a wide full-view of
+  the current image.
+
+* add the image flipping; this may be easiest using multiple versions
+  of the code with the correct sign flips...
+
+* carry the image data as a full 32 bit buffer
+
+* (optionally?) listed on an IP socket?
+
+
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/include/Ximage.h
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/include/Ximage.h	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/include/Ximage.h	(revision 16062)
@@ -0,0 +1,15 @@
+# include <X11/Xatom.h>
+# include <X11/Xlib.h>
+# include <X11/Xresource.h>
+# include <X11/Xutil.h>
+# include <X11/cursorfont.h>
+# include <X11/keysym.h>
+# include <X11/keysymdef.h>
+
+# include <ohana.h>
+# include <dvo.h>
+# include <kapa.h>
+# include "constants.h"
+# include "structures.h"
+# include "prototypes.h"
+# include "globals.h"
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/include/alphabet.h
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/include/alphabet.h	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/include/alphabet.h	(revision 16062)
@@ -0,0 +1,53 @@
+# include "../rotfont/times8.h"
+# include "../rotfont/times12.h"
+# include "../rotfont/times14.h"
+# include "../rotfont/times18.h"
+# include "../rotfont/times24.h"
+
+# include "../rotfont/courier8.h"
+# include "../rotfont/courier12.h"
+# include "../rotfont/courier14.h"
+# include "../rotfont/courier18.h"
+# include "../rotfont/courier24.h"
+
+# include "../rotfont/helvetica8.h"
+# include "../rotfont/helvetica12.h"
+# include "../rotfont/helvetica14.h"
+# include "../rotfont/helvetica18.h"
+# include "../rotfont/helvetica24.h"
+
+# include "../rotfont/symbol8.h"
+# include "../rotfont/symbol12.h"
+# include "../rotfont/symbol14.h"
+# include "../rotfont/symbol18.h"
+# include "../rotfont/symbol24.h"
+
+# define DEFFONT 1
+static FontSet HardwiredFonts[] = {
+  {times8font,  "times", 8},
+  {times12font, "times", 12},
+  {times14font, "times", 14},
+  {times18font, "times", 18},
+  {times24font, "times", 24},
+  
+  {courier8font,  "courier", 8},
+  {courier12font, "courier", 12},
+  {courier14font, "courier", 14},
+  {courier18font, "courier", 18},
+  {courier24font, "courier", 24},
+  
+  {helvetica8font,  "helvetica", 8},
+  {helvetica12font, "helvetica", 12},
+  {helvetica14font, "helvetica", 14},
+  {helvetica18font, "helvetica", 18},
+  {helvetica24font, "helvetica", 24},
+  
+  {symbol8font,  "symbol", 8},
+  {symbol12font, "symbol", 12},
+  {symbol14font, "symbol", 14},
+  {symbol18font, "symbol", 18},
+  {symbol24font, "symbol", 24}
+};
+
+/* put these as static in RotFont.c with accessor functions */
+# define NROT 256
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/include/buttons.h
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/include/buttons.h	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/include/buttons.h	(revision 16062)
@@ -0,0 +1,120 @@
+#define PS_width 25
+#define PS_height 25
+static char PS_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x81, 0x3f, 0x00,
+   0x82, 0x67, 0x60, 0x00, 0x02, 0x26, 0x40, 0x00, 0x02, 0x24, 0x40, 0x00,
+   0x02, 0x24, 0x00, 0x00, 0x02, 0x24, 0x00, 0x00, 0x02, 0x24, 0x00, 0x00,
+   0x02, 0x24, 0x00, 0x00, 0x02, 0x64, 0x00, 0x00, 0x02, 0xc6, 0x00, 0x00,
+   0x82, 0x07, 0x07, 0x00, 0xfe, 0x01, 0x0c, 0x00, 0x02, 0x00, 0x18, 0x00,
+   0x02, 0x00, 0x20, 0x00, 0x02, 0x00, 0x60, 0x00, 0x02, 0x00, 0x40, 0x00,
+   0x02, 0x00, 0xc0, 0x00, 0x02, 0x10, 0x80, 0x00, 0x02, 0x10, 0xc0, 0x00,
+   0x02, 0x60, 0x60, 0x00, 0x02, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00}; 
+#define grey_width 25
+#define grey_height 25
+static char grey_bits[] = {
+   0x90, 0x40, 0xf7, 0x01, 0x04, 0xaa, 0xad, 0x01, 0x68, 0xd5, 0xfe, 0x01,
+   0x82, 0x28, 0xdb, 0x01, 0x10, 0xd2, 0x75, 0x01, 0x40, 0xad, 0xee, 0x01,
+   0xac, 0x50, 0xbf, 0x01, 0x00, 0xaa, 0xf9, 0x01, 0x52, 0xd5, 0xd6, 0x01,
+   0x80, 0x28, 0x6f, 0x01, 0x28, 0xd2, 0xfd, 0x01, 0x44, 0xad, 0xba, 0x01,
+   0x90, 0x50, 0xf7, 0x01, 0x02, 0xaa, 0xcd, 0x01, 0x68, 0xd5, 0x7e, 0x01,
+   0x80, 0x28, 0xfb, 0x01, 0x14, 0xd2, 0xb5, 0x01, 0x40, 0xad, 0xee, 0x01,
+   0xaa, 0x50, 0xdf, 0x01, 0x00, 0xaa, 0x79, 0x01, 0x50, 0xd5, 0xf6, 0x01,
+   0x84, 0x28, 0xaf, 0x01, 0x28, 0xd2, 0xfd, 0x01, 0x40, 0xad, 0xda, 0x01,
+   0x90, 0x50, 0x77, 0x01};
+#define rainbow_width 25
+#define rainbow_height 25
+static char rainbow_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x80, 0xff, 0x00, 0x00, 0x70, 0x00, 0x01, 0x00, 0x0c, 0x7f, 0x00,
+   0x00, 0xe3, 0x80, 0x01, 0xc0, 0x9c, 0xff, 0x00, 0x20, 0x62, 0x00, 0x01,
+   0x90, 0x99, 0xff, 0x00, 0x48, 0x76, 0x00, 0x01, 0x24, 0x09, 0x00, 0x00,
+   0x94, 0x06, 0x00, 0x00, 0x52, 0x01, 0x00, 0x00, 0xaa, 0x00, 0x00, 0x00,
+   0xa5, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00,
+   0x2a, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
+   0x15, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
+   0x15, 0x00, 0x00, 0x00};
+#define recenter_width 25
+#define recenter_height 25
+static char recenter_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00,
+   0x80, 0xef, 0x03, 0x00, 0xe0, 0x00, 0x0e, 0x00, 0x30, 0x00, 0x18, 0x00,
+   0x10, 0x00, 0x10, 0x00, 0x18, 0x00, 0x30, 0x00, 0x08, 0x00, 0x20, 0x00,
+   0x0c, 0x00, 0x60, 0x00, 0x0c, 0x38, 0x60, 0x00, 0x0c, 0x7c, 0x60, 0x00,
+   0x04, 0x7c, 0x40, 0x00, 0x0c, 0x7c, 0x60, 0x00, 0x0c, 0x38, 0x60, 0x00,
+   0x0c, 0x00, 0x60, 0x00, 0x08, 0x00, 0x20, 0x00, 0x18, 0x00, 0x30, 0x00,
+   0x10, 0x00, 0x10, 0x00, 0x30, 0x00, 0x18, 0x00, 0xe0, 0x00, 0x0e, 0x00,
+   0x80, 0xef, 0x03, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00};
+#define heat_width 25
+#define heat_height 25
+static char heat_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x07, 0xd8, 0x01,
+   0x00, 0x0c, 0x37, 0x00, 0xf8, 0xc9, 0x6f, 0x00, 0x0c, 0xde, 0xf0, 0x00,
+   0x06, 0x5b, 0x1f, 0x00, 0x7b, 0xd9, 0x0c, 0x00, 0xc9, 0x70, 0x06, 0x00,
+   0x81, 0x71, 0x03, 0x00, 0x78, 0xb9, 0x39, 0x00, 0xc8, 0xdb, 0x0f, 0x00,
+   0x84, 0xf7, 0x7f, 0x00, 0x04, 0xff, 0xc3, 0x00, 0xe6, 0xfe, 0x8e, 0x00,
+   0x9a, 0x7d, 0x0b, 0x00, 0x08, 0xbc, 0x01, 0x00, 0x08, 0xfc, 0x3f, 0x00,
+   0x0c, 0xff, 0x78, 0x00, 0x84, 0x39, 0x60, 0x00, 0x40, 0x38, 0x40, 0x00,
+   0x60, 0x38, 0x40, 0x00, 0x20, 0x38, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00,
+   0x00, 0xd6, 0x00, 0x00};
+#define red_width 25
+#define red_height 25
+static char red_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xfc, 0x03, 0x00,
+   0x20, 0x07, 0x06, 0x00, 0xe0, 0x00, 0x0c, 0x00, 0x20, 0x00, 0x08, 0x00,
+   0x20, 0x00, 0x08, 0x00, 0x20, 0x00, 0x08, 0x00, 0x20, 0x00, 0x08, 0x00,
+   0x20, 0x00, 0x0c, 0x00, 0x20, 0x00, 0x06, 0x00, 0x20, 0x80, 0x01, 0x00,
+   0x20, 0xe0, 0x00, 0x00, 0x20, 0x7e, 0x00, 0x00, 0xe0, 0xc3, 0x00, 0x00,
+   0x20, 0xc0, 0x00, 0x00, 0x20, 0x80, 0x00, 0x00, 0x20, 0x80, 0x01, 0x00,
+   0x20, 0x00, 0x01, 0x00, 0x20, 0x00, 0x01, 0x00, 0x20, 0x00, 0x03, 0x00,
+   0x20, 0x00, 0x06, 0x00, 0x20, 0x00, 0x0c, 0x00, 0x20, 0x00, 0x18, 0x00,
+   0x00, 0x00, 0x00, 0x00};
+#define green_width 25
+#define green_height 25
+static char green_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x07, 0x00,
+   0x00, 0x06, 0x04, 0x00, 0x80, 0x03, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00,
+   0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
+   0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
+   0x40, 0x00, 0x00, 0x00, 0x40, 0x80, 0x0f, 0x00, 0x40, 0xc0, 0x30, 0x00,
+   0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00,
+   0x40, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x80, 0x01, 0x08, 0x00,
+   0x00, 0x03, 0x08, 0x00, 0x00, 0x7e, 0x0e, 0x00, 0x00, 0xc0, 0x03, 0x00,
+   0x00, 0x00, 0x00, 0x00};
+#define blue_width 25
+#define blue_height 25
+static char blue_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xfe, 0x00, 0x00,
+   0xc0, 0x83, 0x07, 0x00, 0xc0, 0x00, 0x0c, 0x00, 0x40, 0x00, 0x08, 0x00,
+   0x40, 0x00, 0x08, 0x00, 0x40, 0x00, 0x08, 0x00, 0x40, 0x00, 0x08, 0x00,
+   0x40, 0x00, 0x0c, 0x00, 0x40, 0x00, 0x04, 0x00, 0x40, 0x00, 0x02, 0x00,
+   0x40, 0x80, 0x07, 0x00, 0x40, 0xe0, 0x0c, 0x00, 0xc0, 0x3f, 0x08, 0x00,
+   0x40, 0x00, 0x08, 0x00, 0x40, 0x00, 0x08, 0x00, 0x40, 0x00, 0x08, 0x00,
+   0x40, 0x00, 0x0c, 0x00, 0x40, 0x00, 0x06, 0x00, 0x40, 0x00, 0x02, 0x00,
+   0xc0, 0x80, 0x03, 0x00, 0x40, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00};
+#define yellow_width 25
+#define yellow_height 25
+static char yellow_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x18, 0x00,
+   0x80, 0x01, 0x0c, 0x00, 0x00, 0x03, 0x06, 0x00, 0x00, 0x02, 0x02, 0x00,
+   0x00, 0x84, 0x01, 0x00, 0x00, 0xcc, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00,
+   0x00, 0x30, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00,
+   0x00, 0x10, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00,
+   0x00, 0x20, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00,
+   0x00, 0x30, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
+   0x00, 0x30, 0x00, 0x00, 0x00, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00};
+#define hms_width 25
+#define hms_height 25
+static char hms_bits[] = {
+   0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+   0x02, 0x00, 0x00, 0x00, 0x02, 0x01, 0xf0, 0x00, 0x1e, 0xef, 0x89, 0x00,
+   0x22, 0x11, 0x09, 0x00, 0x22, 0x11, 0x71, 0x00, 0x22, 0x11, 0x81, 0x00,
+   0x22, 0x11, 0x89, 0x00, 0x22, 0x01, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x1e, 0xc7, 0xf1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x80, 0x80, 0x00,
+   0x40, 0x80, 0x80, 0x00, 0x40, 0x80, 0x80, 0x00, 0x40, 0x80, 0x80, 0x00,
+   0x40, 0x80, 0x80, 0x00, 0x5c, 0xb8, 0xb8, 0x00, 0x62, 0xc4, 0xc4, 0x00,
+   0x42, 0x84, 0x84, 0x00, 0x42, 0x84, 0x84, 0x00, 0x62, 0xc4, 0xc4, 0x00,
+   0x5c, 0xb9, 0xb8, 0x00};
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/include/constants.h
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/include/constants.h	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/include/constants.h	(revision 16062)
@@ -0,0 +1,93 @@
+/* hardwired values for some window parameters */
+
+# define EVENT_MASK (long) \
+(ButtonPressMask \
+ | ClientMessage \
+ | ButtonReleaseMask \
+ | KeyPressMask \
+ | ExposureMask \
+ | StructureNotifyMask \
+ | PointerMotionMask)
+
+# define NCHANNELS 3
+# define NPIXELS_DYNAMIC 128
+
+// XXX for the moment, this is set to match the values in SetColorScale3D_CC
+# define NPIXELS_STATIC 4600
+
+# define PAD1  3
+# define PAD2  5
+# define TEXTPAD 25
+# define COLORPAD 10
+# define TEXT_Y 15
+# define ZOOM_X 152
+# define ZOOM_Y 152
+# define NOVERLAYS 4
+# define BUTTON_WIDTH 28
+# define BUTTON_HEIGHT 28
+
+# define DEFAULT_CURSOR XC_crosshair
+# define BORDER_WIDTH 2
+# define MIN_WIDTH 50
+# define MIN_HEIGHT 50
+# define LABEL_MAXLEN 128
+
+typedef enum {
+    KAPA_SCALE_1D,
+    KAPA_SCALE_3D_RUFF,
+    KAPA_SCALE_3D_FULL
+} KapaColorScaleMode;
+
+/* label names */
+typedef enum {
+  LABELX0,
+  LABELY0,
+  LABELX1,
+  LABELY1,
+  LABELUL,
+  LABELUR,
+  LABELLL,
+  LABELLR
+} KapaLabelMode;
+
+typedef enum {
+  KAPA_CHANNEL_RED,
+  KAPA_CHANNEL_GREEN,
+  KAPA_CHANNEL_BLUE,
+} KapaChannels;
+
+// use an enum to identify the 3 dimensions:
+typedef enum {
+  CC_X,
+  CC_Y,
+  CC_Z,
+} CCDimen;
+
+/* EVENT_MASK consists of:
+
+ExposureMask        : Expose
+StructureNotifyMask : CirculateNotify | 
+                      ConfigureNotify | 
+                      DestroyNotify   | 
+		      GravityNotify   | 
+		      MapNotify       |
+		      ReparentNotify  |
+		      UnmapNotify
+ButtonPressMask     : ButtonPress
+ButtonReleaseMask   : ButtonRelease
+KeyPressMask        : KeyPress
+PointerMotionMask   : MotionNotify
+(always)            : ClientMessage 
+(always)            : MappingNotify
+
+*/
+
+# define NOVERLAYS 4
+/* number of overlays is defined here.
+   the number is also crucial in the following files:
+   PositionPictures.c
+   MakeColormap.c
+   prototypes.h
+*/
+
+
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/include/globals.h
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/include/globals.h	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/include/globals.h	(revision 16062)
@@ -0,0 +1,28 @@
+
+int   ACTIVE_CURSOR;
+int   HAVE_BACKING;
+int   DEBUG;
+int   USE_XWINDOW;
+int   MAP_WINDOW;
+int   FOREGROUND;
+char *NAME_WINDOW;
+
+/* these should be absorbed into KapaImageWidget 
+int OVERLAY[NOVERLAYS];
+int MOVE_POINTER;
+int DECIMAL_DEG;
+*/
+
+/* file descriptor for socket connection to mana */
+// int sock; 
+
+/* each layout / section defines one of the active portions of the graphics window
+   there may be an arbitrary number of sections, and each section may fill an arbitrary
+   rectangle in the X window.  The startup configuration assumes 1 section filling the 
+   entire X window. */
+
+// Layout *section;
+// int    Nsection, TheSection;
+
+/* graphic defines the basic details of the X window */
+// Graphic graphic;
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/include/icons.h
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/include/icons.h	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/include/icons.h	(revision 16062)
@@ -0,0 +1,43 @@
+
+#define icon_width 29
+#define icon_height 29
+static unsigned char icon_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0x07,
+   0x04, 0x41, 0x10, 0x04, 0x04, 0x41, 0x10, 0x04, 0x04, 0x41, 0x10, 0x04,
+   0x04, 0x41, 0x10, 0x04, 0x04, 0x41, 0x10, 0x04, 0xfc, 0xff, 0xff, 0x07,
+   0x04, 0x41, 0x10, 0x04, 0x04, 0x41, 0x10, 0x04, 0x04, 0x41, 0x10, 0x04,
+   0x04, 0x41, 0x10, 0x04, 0x04, 0x41, 0x10, 0x04, 0xfc, 0xff, 0xff, 0x07,
+   0x04, 0x41, 0x10, 0x04, 0x04, 0x41, 0x10, 0x04, 0x04, 0x41, 0x10, 0x04,
+   0x04, 0x41, 0x10, 0x04, 0x04, 0x41, 0x10, 0x04, 0xfc, 0xff, 0xff, 0x07,
+   0x04, 0x41, 0x10, 0x04, 0x04, 0x41, 0x10, 0x04, 0x04, 0x41, 0x10, 0x04,
+   0x04, 0x41, 0x10, 0x04, 0x04, 0x41, 0x10, 0x04, 0xfc, 0xff, 0xff, 0x07,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+/* *** icons for buttons, not used ***
+#define arrow_width 6
+#define arrow_height 9
+static char arrow_bits[] = {
+   0x00, 0x02, 0x06, 0x0e, 0x1e, 0x0e, 0x06, 0x02, 0x00};
+#define back_width 16
+#define back_height 16
+static char back_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x3c, 0x00, 0x3f, 0xc0, 0x3f,
+   0xf0, 0x3f, 0xfc, 0x3f, 0xfc, 0x3f, 0xf0, 0x3f, 0xc0, 0x3f, 0x00, 0x3f,
+   0x00, 0x3c, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00};
+#define down_width 9
+#define down_height 6
+static char down_bits[] = {
+   0x00, 0x00, 0xfe, 0x00, 0x7c, 0x00, 0x38, 0x00, 0x10, 0x00, 0x00, 0x00};
+#define fore_width 16
+#define fore_height 16
+static char fore_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x3c, 0x00, 0xfc, 0x00, 0xfc, 0x03,
+   0xfc, 0x0f, 0xfc, 0x3f, 0xfc, 0x3f, 0xfc, 0x0f, 0xfc, 0x03, 0xfc, 0x00,
+   0x3c, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00};
+#define stop_width 16
+#define stop_height 16
+static char stop_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x1f, 0xf8, 0x1f, 0xf8, 0x1f,
+   0xf8, 0x1f, 0xf8, 0x1f, 0xf8, 0x1f, 0xf8, 0x1f, 0xf8, 0x1f, 0xf8, 0x1f,
+   0xf8, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+*/
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/include/kii.proto.h
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/include/kii.proto.h	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/include/kii.proto.h	(revision 16062)
@@ -0,0 +1,124 @@
+
+/* top-level program */
+int           args                PROTO((int *argc, char **argv));
+void          SetUpDisplay        PROTO((Graphic *, int *, char **));
+void          SetUpWindow         PROTO((Graphic *, int *, char **));
+void          DefineLayout        PROTO((Layout *, Graphic *, int, char **));
+int           EventLoop           PROTO((Graphic *, Layout *));
+void          CloseDisplay        PROTO((Graphic *));
+
+/* SetUpDisplay */
+void          CheckDisplayName    PROTO((int *, char **, char *));
+Display      *OpenDisplay         PROTO((char *, int *));
+void	      CheckVisual	  PROTO((Graphic *graphic, int *argc, char **argv));
+void          CheckColors         PROTO((Graphic *, int *, char **));
+
+/* SetUpWindow */
+void          CheckGeometry       PROTO((int *, char **, Graphic *));
+void          TopWindow           PROTO((Graphic *, Icon *));
+void           CreateWindow       PROTO((Graphic *, Window, int, long));
+void           MakeGC             PROTO((Graphic *));
+void           MakeCursor         PROTO((Graphic *, unsigned int));
+void          LoadFont            PROTO((Graphic *, int *, char **, char *));
+void           CheckFontName      PROTO((int *, char **, char *));
+void          SetNormalHints      PROTO((Graphic *));
+void          SetWMHints          PROTO((Graphic *, Icon *));
+void          NameWindow          PROTO((Graphic *, char *));
+void          MapWindow           PROTO((Graphic *));
+
+/* DefineLayout - fns below may be called if layout is changed? */
+void          PositionPictures    PROTO((Layout *, Graphic *));
+
+void          MakeColormap        PROTO((Graphic *, Layout *, int, char **));
+int	      SetColormap	  PROTO((Graphic *graphic, Layout *layout, char *name));
+void          CreateColorbar      PROTO((Layout *, Graphic *));
+void          CreatePicture       PROTO((Layout *, Graphic *));
+
+/* EventLoop */
+int           CheckPipe           PROTO((Graphic *, Layout *));
+int           Reconfig            PROTO((Graphic *, Layout *, XEvent *));
+void          Refresh             PROTO((Graphic *, Layout *, int));
+int           UpdatePointer       PROTO((Graphic *, Layout *, XMotionEvent *));
+int           InterpretKeys       PROTO((Graphic *, Layout *, XEvent *));
+int           InterpretPresses    PROTO((Graphic *, Layout *, XButtonEvent *));
+
+/* CheckPipe */
+int           NewPicture          PROTO((Graphic *, Layout *));
+int           EraseOverlay        PROTO((Graphic *, Layout *));
+int           LoadOverlay         PROTO((Graphic *, Layout *));
+int	      LoadTickmarks	  PROTO((Graphic *graphic, Layout *layout));
+int           SaveOverlay         PROTO((Graphic *, Layout *));
+int           CSaveOverlay        PROTO((Graphic *, Layout *));
+int	      PSit		  PROTO((Graphic *graphic, Layout *layout, int Raw));
+int	      JPEGit		  PROTO((Graphic *graphic, Layout *layout));
+int	      JPEGit24		  PROTO((Graphic *graphic, Layout *layout));
+int	      Resize		  PROTO((Graphic *graphic, Layout *layout));
+int	      Center		  PROTO((Graphic *graphic, Layout *layout));
+
+/* imagezoom functions */
+void          CreateZoom          PROTO((Layout *, Graphic *, double, double));
+void	      CreateZoom8	  PROTO((Layout *layout, Graphic *graphic, double x, double y));
+void	      CreateZoom16	  PROTO((Layout *layout, Graphic *graphic, double x, double y));
+void	      CreateZoom24	  PROTO((Layout *layout, Graphic *graphic, double x, double y));
+void	      CreateZoom32	  PROTO((Layout *layout, Graphic *graphic, double x, double y));
+void	      UpdateStatusBox	  PROTO((Graphic *graphic, Layout *layout, double x, double y, double z, int mode));
+void          CrossHairs          PROTO((Graphic *, Layout *));
+
+/* X image drawing functions */
+void          Reorient            PROTO((Graphic *, Layout *, double, double, int));
+void          ReorientOnButton    PROTO((Graphic *, Layout *, XButtonEvent *));
+int	      Recenter		  PROTO((Graphic *graphic, Layout *layout));
+void          PaintOverlay        PROTO((Graphic *, Layout *, int));
+void	      PaintTickmarks	  PROTO((Graphic *graphic, Layout *layout));
+void          Remap               PROTO((Graphic *, Layout *, Matrix  *));
+void	      Remap8		  PROTO((Graphic *graphic, Layout *layout, Matrix *matrix));
+void	      Remap16		  PROTO((Graphic *graphic, Layout *layout, Matrix *matrix));
+void	      Remap24		  PROTO((Graphic *graphic, Layout *layout, Matrix *matrix));
+void	      Remap32		  PROTO((Graphic *graphic, Layout *layout, Matrix *matrix));
+
+/* PS image drawing functions */
+void	      ConvertPixmap8	  PROTO((Layout *layout, FILE *f));
+void	      ConvertPixmap16	  PROTO((Layout *layout, FILE *f));
+void	      ConvertPixmap24	  PROTO((Layout *layout, FILE *f));
+void	      ConvertPixmap32	  PROTO((Layout *layout, FILE *f));
+void	      DrawOverlay	  PROTO((Graphic *graphic, Layout *layout, int N, FILE *f, int extra));
+
+/* JPEG image drawing functions */
+void	      bDrawOverlay	  PROTO((Layout *layout, int N));
+
+/***** Prototypes for image ***************/
+void          StatusBox           PROTO((Graphic *, Layout *));
+
+/***** Prototypes for action ***************/
+int           InPicture           PROTO((XButtonEvent *, Picture *));
+int           Stop                PROTO((Graphic *, Layout *));
+void          DragColorbar        PROTO((Graphic *, Layout *, XButtonEvent *));
+void          ResetColorbar       PROTO((Graphic *, Layout *, double, double));
+
+/***** Prototypes for button ***************/
+Button       *CheckButtons        PROTO((XButtonEvent *, Layout *));
+void          DrawButton          PROTO((Graphic *, Button *));
+void          FlashButton         PROTO((Graphic *, Button *));
+int           InButton            PROTO((XButtonEvent *, Button *));
+void          InvertButton        PROTO((Graphic *, Button *));
+int           greycolors          PROTO((Graphic *, Layout *));
+int           rainbow             PROTO((Graphic *, Layout *));
+int           puns                PROTO((Graphic *, Layout *));
+int           Recenter            PROTO((Graphic *, Layout *));
+int           RecenterRescale     PROTO((Graphic *, Layout *));
+int           Rescale             PROTO((Graphic *, Layout *));
+int           ToggleDEG           PROTO((Graphic *, Layout *));
+int           Overlay0            PROTO((Graphic *, Layout *));
+int           Overlay1            PROTO((Graphic *, Layout *));
+int           Overlay2            PROTO((Graphic *, Layout *));
+int           Overlay3            PROTO((Graphic *, Layout *));
+
+/***** Prototypes for xtools ***************/
+void	      Screen_to_Image     PROTO((double *x1, double *y1, double x2, double y2, Layout *layout));
+void	      Image_to_Screen	  PROTO((double *x1, double *y1, double x2, double y2, Layout *layout));
+unsigned long GetColor            PROTO((Display *, char *, Colormap, unsigned long));
+void          QuitX               PROTO((Display *, char *, char *));
+void          hh_hms              PROTO((char *, double, double, char));
+void          DrawBitmap          PROTO((Graphic *, int, int, int, int, char *, int));
+int	      cursor		  PROTO((Graphic *graphic, Layout *layout));
+void	      FlushDisplay	  PROTO((Display *display));
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/include/kii.struct.h
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/include/kii.struct.h	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/include/kii.struct.h	(revision 16062)
@@ -0,0 +1,129 @@
+
+/**************** Graphic carries X info around ****************/
+typedef struct {
+  Display       *display;
+  int            screen;
+  int            depth;
+  Window         window;
+  Visual        *visual;
+  int            visualclass;
+  GC             gc;
+  XFontStruct   *font;
+  Cursor         cursor;
+  int            x,  y;
+  int            dx, dy;
+  Colormap       colormap;
+  unsigned long  Npixels, pixels[256];
+  int            Nbits;
+  /*
+  unsigned long  fore;
+  unsigned long  back;
+  */
+  unsigned long  black, white;
+} Graphic;
+
+/**************** X related "widget" structures ****************/
+typedef struct {
+  int      x, y, dx, dy;      /* position and size */
+  int      text;              /* does this have a picture or text? */
+  int      width, height;
+  char    *bitmap;          /* picture on button */
+  int    (*function_1) ();  /* mouse_button 1 function */
+  int    (*function_2) ();  /* mouse_button 2 function */
+  int    (*function_3) ();  /* mouse_button 3 function */
+} Button;
+
+typedef struct {
+  int      x, y, dx, dy;   /* position and size */
+  char    *label;          /* label on TextLine */
+  char     text[1024];     /* words of TextLine */
+  char     old_text[1024]; /* words of TextLine */
+  int      outline;        /* draw an outline?  */ 
+  int      cursor;         /* location of cursor (if selected) */
+  int    (*function) ();   /* textline function */
+} TextLine;
+
+typedef char STRING[1024];
+
+typedef struct {
+  int      x, y, dx, dy;   /* position and size */
+  STRING  *text;           /* words of TextLine */
+  int      Nlines;
+  int      outline;        /* draw an outline?  */ 
+  int      cursor_line;    /* cursor line */
+  int      cursor_x;       /* location of cursor (if selected) */
+  int      cursor_y;       /* location of cursor (if selected) */
+  int    (*function) ();   /* textline function */
+} TextBox;
+
+/**************** general structures ****************/
+typedef struct {
+  Pixmap pixmap;
+  int    width;
+  int    height;
+  char  *bits;
+} Icon;
+
+typedef struct {
+  int      dx, dy, x, y;
+  XImage  *pix;
+  char *data;
+} Picture;
+
+typedef struct {
+  char type[10];
+  double x, y;
+  double dx, dy;
+  double angle;
+  char  *text;
+} Object;
+
+typedef struct {
+  int Nobjects;
+  unsigned long color;
+  Object *objects;
+} Overlay;
+  
+/******** Here we define the Layout struct specific to this program  *******/
+typedef struct {
+  /* objects on the mana window */
+  Picture  picture;
+  Picture  cmapbar;
+  Picture  zoom;
+  Button   PS_button;
+  Button   recenter_button;
+  Button   hms_button; /* toggle HMS/DECIMAL mode (DECIMAL_DEG macro) */
+  Button   grey_button;
+  Button   rainbow_button;
+  Button   puns_button;
+  Button   overlay_button[NOVERLAYS];
+  Overlay  overlay[NOVERLAYS];
+  Overlay  tickmarks;
+  int      text_x, text_y;
+
+  /* file descriptor for socket connection to mana */
+  int Ximage; 
+
+  /* data mana needs */
+  Matrix   matrix;         /* data for picture */
+  double   X, Y;           /* image pixel at screen center */
+  int      expand;         /* zoomscale */
+  double   zero, range;    /* zero, range for picture to cmap */
+  double   max, min;       /* zero, range for data to z-value */
+  double   start, slope;   /* zero, range for cmap to pixels */
+  double   x, y, z;        /* last pointer coords */
+  Coords   coords;
+  char     file[1024];     /* name of file */
+  char     buffer_name[1024];  /* name of buffer */
+
+  /* fundamental pieces */
+  unsigned long  black;
+  unsigned long  white;
+  XColor   cmap[256];
+  int      Npixels;
+
+} Layout;
+
+/* this routine is independent of the number of overlays */
+
+
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/include/prototypes.h
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/include/prototypes.h	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/include/prototypes.h	(revision 16062)
@@ -0,0 +1,245 @@
+
+/* top-level program */
+int	      args		  PROTO((int *argc, char **argv));
+void          SetUpGraphic        PROTO((int *argc, char **argv));
+void          DefineLayout        PROTO((int, char **));
+int	      EventLoop		  PROTO(());
+void	      CloseDisplay	  PROTO(());
+
+/* SetUpGraphic */
+char         *CheckDisplayName    PROTO((int *argc, char **argv));
+Display      *OpenDisplay         PROTO((char *name, int *screen));
+void          CheckColors         PROTO((Graphic *graphic, int *argc, char **argv));
+
+/* SetUpWindow */
+void          CheckGeometry       PROTO((Graphic *graphic, int *argc, char **argv));
+void          TopWindow           PROTO((Graphic *graphic, Icon *icon));
+void          CreateWindow        PROTO((Graphic *graphic, Window parent, int border, long events));
+void	      MakeGC	    	  PROTO((Graphic *graphic));
+void          MakeCursor          PROTO((Graphic *graphic, unsigned int cursor));
+void          LoadFont            PROTO((Graphic *graphic, int *argc, char **argv, char *default_name));
+void          SetNormalHints      PROTO((Graphic *graphic));
+void          SetWMHints          PROTO((Graphic *graphic, Icon *icon));
+void          NameWindow          PROTO((Graphic *graphic, char *name));
+void          MapWindow           PROTO((Graphic *graphic));
+void          CheckVisual         PROTO((Graphic *graphic, int *argc, char **argv));
+
+/* X drawing utilities */
+void	      DrawFrame		  PROTO((KapaGraphWidget *graph));
+int           DrawObjects         PROTO((KapaGraphWidget *graph));
+void          DrawLabels          PROTO((KapaGraphWidget *graph));
+void	      DrawTextlines	  PROTO((KapaGraphWidget *graph));
+void          DrawConnect         PROTO((KapaGraphWidget *graph, Gobjects *objects));
+void          DrawHistogram       PROTO((KapaGraphWidget *graph, Gobjects *objects));
+int           DrawObjectN         PROTO((KapaGraphWidget *graph, Gobjects *objects));
+void          DrawPoints          PROTO((KapaGraphWidget *graph, Gobjects *objects));
+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 mode, int naxis));
+void	      AxisTickScale	  PROTO((Axis *axis, double *major, double *minor));
+
+/* EventLoop */
+int           PScommand           PROTO((int sock));
+int           CheckPipe           PROTO(());
+int           Reconfig            PROTO((XEvent *event));
+void          Refresh             PROTO(());
+
+/* CheckPipe */
+int           PNGit               PROTO((int sock));
+int           PPMit               PROTO((int sock));
+int           LoadFrame           PROTO((int sock));
+int           LoadObject          PROTO((int sock));
+int           LoadLabels          PROTO((int sock));
+int           LoadTextlines       PROTO((int sock));
+int           Resize              PROTO((int sock));
+int           GetLimits           PROTO((int sock));
+int           SetLimits           PROTO((int sock));
+int           SetSection          PROTO((int sock));
+int           ListSection         PROTO((int sock));
+int           MoveSection         PROTO((int sock));
+int           DefineSection       PROTO((int sock));
+int           SetFont             PROTO((int sock));
+int           EraseCurrentPlot    PROTO((void));
+int           ErasePlots          PROTO((void));
+int           EraseSections       PROTO((void));
+int           EraseImage          PROTO((void));
+int           SetGraphData        PROTO((int sock));
+int           GetGraphData        PROTO((int sock));
+int           SetImageData        PROTO((int sock));
+int           GetImageData        PROTO((int sock));
+int           SetImageCoords      PROTO((int sock));
+int           GetImageCoords      PROTO((int sock));
+int           GetImageRange       PROTO((int sock));
+int           SetChannel          PROTO((int sock));
+int           SetColormapFromPipe PROTO((int sock));
+
+int           LoadVectorData      PROTO((int sock, KapaGraphWidget *graph, int N, char *type));
+
+/* Section Utilities */
+Section      *InitSection	  PROTO(());
+void          FreeSection	  PROTO((Section *section));
+void          FreeSections	  PROTO(());
+Section      *AddSection	  PROTO((char *name, float x, float y, float dx, float dy));
+int           DelSection	  PROTO((char *name));
+int           GetSectionByName	  PROTO((char *name));
+int           GetNumberOfSections PROTO(());
+Section      *GetSectionByNumber  PROTO((int N));
+Section      *GetActiveSection	  PROTO(());
+int           SetActiveSectionByNumber PROTO((int N));
+int           ListSection         PROTO((int sock));
+void          SetSectionSizes     PROTO((Section *section));
+
+KapaGraphWidget *InitGraph        PROTO(());
+void          DrawGraph           PROTO((KapaGraphWidget *graph));
+void          SetGraphSize        PROTO((Section *section));
+void          FreeGraph           PROTO((KapaGraphWidget *graph));
+
+void          InitLayout          PROTO((int argc, char **argv));
+
+/* PS drawing utilities */
+int           PSit                PROTO((char *filename, char *pagename, int scaleMode, int pageMode));
+int           PSFrame             PROTO((KapaGraphWidget *graph, FILE *f));
+int           PSObjects           PROTO((KapaGraphWidget *graph, FILE *f));
+void          PSLabels            PROTO((KapaGraphWidget *graph, FILE *f));
+void	      PSTextlines	  PROTO((KapaGraphWidget *graph, FILE *f));
+void          PSConnect           PROTO((KapaGraphWidget *graph, Gobjects *objects, FILE *f));
+void          PSHistogram         PROTO((KapaGraphWidget *graph, Gobjects *objects, FILE *f));
+void          PSPoints            PROTO((KapaGraphWidget *graph, Gobjects *objects, FILE *f));
+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 mode, int naxis));
+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));
+void 	      PSOverlay  	  PROTO((KapaImageWidget *image, int N, FILE *f, int extra));
+void 	      PSPixmap8  	  PROTO((Graphic *graphic, KapaImageWidget *image, FILE *f));
+void 	      PSPixmap16 	  PROTO((Graphic *graphic, KapaImageWidget *image, FILE *f));
+void 	      PSPixmap24 	  PROTO((Graphic *graphic, KapaImageWidget *image, FILE *f));
+void 	      PSPixmap32 	  PROTO((Graphic *graphic, KapaImageWidget *image, FILE *f));
+
+/* kapa bDraw Functions */
+int	      bDrawFrame	  PROTO((KapaGraphWidget *graph));
+int	      bDrawObjects	  PROTO((KapaGraphWidget *graph));
+void	      bDrawLabels	  PROTO((KapaGraphWidget *graph));
+void	      bDrawTextlines	  PROTO((KapaGraphWidget *graph));
+void	      bDrawConnect	  PROTO((KapaGraphWidget *graph, Gobjects *object));
+void	      bDrawHistogram	  PROTO((KapaGraphWidget *graph, Gobjects *object));
+void	      bDrawPoints	  PROTO((KapaGraphWidget *graph, Gobjects *object));
+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 mode, 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          bDrawGraph          PROTO((KapaGraphWidget *graph));
+
+/* misc support */
+int           LastEvent           PROTO((Display *display, int type, XEvent *event));
+void	      FreeObjectData	  PROTO((Gobjects *object));
+void	      FlushDisplay	  PROTO(());
+unsigned long GetColor            PROTO((Display *display, char *name, Colormap colormap, unsigned long default_color));
+void          QuitX               PROTO((Display *display, char *message));
+Graphic      *GetGraphic          PROTO(());
+int           GetPixelCount       PROTO((int sock));
+
+int           Center              PROTO(());
+void          SetColorScale       PROTO((Graphic *graphic, KapaImageWidget *image));
+void          SetColorScale1D     PROTO((Graphic *graphic, KapaImageWidget *image));
+int           SetColorScale3D     PROTO((Graphic *graphic, KapaImageWidget *image));
+void          Remap               PROTO((Graphic *graphic, KapaImageWidget *image));
+void          Remap8              PROTO((Graphic *graphic, KapaImageWidget *image, Matrix *matrix));
+void          Remap16             PROTO((Graphic *graphic, KapaImageWidget *image, Matrix *matrix));
+void          Remap24             PROTO((Graphic *graphic, KapaImageWidget *image, Matrix *matrix));
+void          Remap32             PROTO((Graphic *graphic, KapaImageWidget *image, Matrix *matrix));
+int           LoadPicture         PROTO((int sock));
+
+KapaImageWidget *InitImageWidget  PROTO(());
+int           InitImageChannel    PROTO((KapaImageChannel *channel));
+void          FreeImage           PROTO((KapaImageWidget *image));
+void          SetImageSize        PROTO((Section *section));
+
+void          InitButtonSize      PROTO((Button *button, int width, int height, char *bitmap));
+void          InitButtonFunc      PROTO((Button *button, int (*function)()));
+void          DrawImage           PROTO((KapaImageWidget *image));
+void          DrawButton          PROTO((Graphic *graphic, Button *button));
+void          DrawBitmap          PROTO((Graphic *graphic, int x, int y, int dx, int dy, char *bitmap, int mode));
+void          CrossHairs          PROTO((Graphic *graphic, KapaImageWidget *image));
+void          hh_hms              PROTO((char *line, double ra, double dec, char sep));
+
+int           SetColormap         PROTO((char *name));
+void          MakeColormap        PROTO((int argc, char **argv));
+
+void          PaintOverlay        PROTO((Graphic *graphic, KapaImageWidget *image, int N));
+void          PaintTickmarks      PROTO((Graphic *graphic, KapaImageWidget *image));
+
+void          Screen_to_Image     PROTO((double *x1, double *y1, double x2, double y2, KapaImageWidget *image));
+void          Image_to_Screen     PROTO((double *x1, double *y1, double x2, double y2, KapaImageWidget *image));
+
+void          DragColorbar        PROTO((Graphic *graphic, KapaImageWidget *image, XButtonEvent *mouse_event));
+void          ResetColorbar       PROTO((Graphic *graphic, double start, double slope));
+void          ReorientOnButton    PROTO((Graphic *graphic, KapaImageWidget *image, XButtonEvent *mouse_event));
+void          Reorient            PROTO((Graphic *graphic, KapaImageWidget *image, double X, double Y, int mode));
+
+Button       *CheckButtons        PROTO((XButtonEvent *event, KapaImageWidget *image));
+int           InButton            PROTO((XButtonEvent *event, Button *button));
+int           InPicture           PROTO((XButtonEvent *event, Picture *picture));
+
+/* Button Functions */
+int           greycolors	  PROTO((Graphic *graphic, KapaImageWidget *image));
+int	      heat		  PROTO((Graphic *graphic, KapaImageWidget *image));
+int	      rainbow		  PROTO((Graphic *graphic, KapaImageWidget *image));
+int	      Recenter		  PROTO((Graphic *graphic, KapaImageWidget *image));
+int	      Rescale		  PROTO((Graphic *graphic, KapaImageWidget *image));
+int	      RecenterRescale	  PROTO((Graphic *graphic, KapaImageWidget *image));
+int	      ToggleDEG		  PROTO((Graphic *graphic, KapaImageWidget *image));
+int	      Overlay0		  PROTO((Graphic *graphic, KapaImageWidget *image));
+int	      Overlay1		  PROTO((Graphic *graphic, KapaImageWidget *image));
+int	      Overlay2		  PROTO((Graphic *graphic, KapaImageWidget *image));
+int	      Overlay3		  PROTO((Graphic *graphic, KapaImageWidget *image));
+int	      PSfunction	  PROTO((Graphic *graphic, KapaImageWidget *image));
+
+/* misc functions */
+void 	      SetToolbox   (int sock);
+int  	      EraseOverlay (int sock);
+int  	      LoadOverlay  (int sock);
+int  	      SaveOverlay  (int sock);
+int  	      CSaveOverlay (int sock);
+int  	      JPEGit24     (int sock);
+
+int  	      UpdatePointer (Graphic *graphic, XMotionEvent *event);
+int  	      InterpretPresses (Graphic *graphic, XButtonEvent *event);
+int  	      InterpretKeys (Graphic *graphic, XKeyEvent *event);
+void 	      InitPipe (char *namedSocket);
+void 	      EraseGraph (KapaGraphWidget *graph);
+void 	      StatusBox (Graphic *graphic, KapaImageWidget *image);
+
+void 	      CreatePicture (KapaImageWidget *image, Graphic *graphic);
+void 	      CreateColorbar (KapaImageWidget *image, Graphic *graphic);
+void 	      CreateZoom (KapaImageWidget *image, Graphic *graphic, double x, double y);
+void 	      UpdateStatusBox (Graphic *graphic, KapaImageWidget *image, double x, double y, double z, int mode);
+
+void 	      CreateZoom8  (KapaImageWidget *image, Graphic *graphic, double x, double y);
+void 	      CreateZoom16 (KapaImageWidget *image, Graphic *graphic, double x, double y);
+void 	      CreateZoom24 (KapaImageWidget *image, Graphic *graphic, double x, double y);
+void 	      CreateZoom32 (KapaImageWidget *image, Graphic *graphic, double x, double y);
+
+int  	      GetActiveSocket ();
+void 	      InvertButton (Graphic *graphic, Button *button);
+void 	      bDrawOverlay (KapaImageWidget *image, int N);
+
+/* color cube tools */
+CCNode *CCNodeAlloc ();
+CCNode *CCFindChild (CCNode *node, float x, float y, float z);
+int CCSplitNode (CCNode *node);
+int CCSplitNodeIterate (CCNode *node, int current, int max);
+void CCNodeFree (CCNode *node);
+CCNode *CCFindBottom (CCNode *top, float x, float y, float z);
+int CCNodeExtractCounts (CCNode *node, float **values, int *nvalues, int *NVALUES);
+int CCNodeDivideLimit (CCNode *node, float minValue);
+int CCNodeInitCounts (CCNode *node, float value);
+
+/* 3D color histogram */
+void ColorHistogram (KapaImageWidget *image, CCNode *cube);
+void CCNodeSetColorPixels (KapaImageWidget *image, CCNode *cube);
+int CCNodeSetColorMap (CCNode *node, XColor *cmap, int Npixels, int *current);
+
+int SetColorScale3D_CC (Graphic *graphic, KapaImageWidget *image);
+int SetColorCubeHistogram ();
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/include/structures.h
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/include/structures.h	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/include/structures.h	(revision 16062)
@@ -0,0 +1,205 @@
+
+/*** 3C color cube histogram tree thingy ***/
+typedef struct CCNode {
+  // for the moment, this structure is specific to the color-histogram analysis.  if
+  // this were a void *pointer and we defined some additional apis, we could use this
+  // structure to track any 3D space
+  int count;    
+  int pixel;
+  char bottom;
+  float min[3]; // min value for each of the 3 dimensions for this node
+  float mid[3]; // mid-point for each of the 3 dimensions for this node
+  float max[3]; // max value for each of the 3 dimensions for this node
+  struct CCNode *sub[2][2][2];
+} CCNode;
+
+/**************** Graphic carries X info around ****************/
+typedef struct {
+  Display       *display;     // X display pointer
+  int            screen;      // X screen number
+  int            depth;
+  Window         window;
+  Visual        *visual;
+  int            visualclass; // is visual dynamic? (XXX change name?)
+  int            Nbits;	      // pixel depth in bits (8, 16, 24, 32)
+  GC             gc;
+  XFontStruct   *font;
+  Cursor         cursor;
+  int            x,  y;
+  unsigned int   dx, dy;
+  CCNode        *cube;
+  XColor        *cmap;
+  Colormap       colormap;
+  unsigned long *color;      // graph plotting colors
+  int            Ncolors;
+
+  unsigned long *pixels;      // image pixel colors
+  int Npixels;		      // number of pixels
+
+  int            ColorScaleMode; // single colormap for all images??
+  int nRed;
+  int nBlue;
+  int nGreen;
+
+  unsigned long  fore;	      // basic foreground color 
+  unsigned long  back;	      // basic background color
+
+  unsigned long  overlay_color[NOVERLAYS]; // image plotting colors 
+} Graphic;
+
+/**************** X related "widget" structures ****************/
+typedef struct {
+  int      x, y, dx, dy;      /* position and size */
+  int      width, height;     /* size of the bitmap */
+  char    *bitmap;            /* picture on button */
+  int    (*function_1) ();    /* mouse_button 1 function */
+  int    (*function_2) ();    /* mouse_button 2 function */
+  int    (*function_3) ();    /* mouse_button 3 function */
+} Button;
+
+typedef struct {
+  int      x, y, dx, dy;   /* position and size */
+  char    *label;          /* label on TextLine */
+  char     text[1024];     /* words of TextLine */
+  char     old_text[1024]; /* words of TextLine */
+  int      outline;        /* draw an outline?  */ 
+  int      cursor;         /* location of cursor (if selected) */
+  int    (*function) ();   /* textline function */
+} TextLine;
+
+typedef char STRING[1024];
+
+typedef struct {
+  int      x, y, dx, dy;   /* position and size */
+  STRING  *text;           /* words of TextLine */
+  int      Nlines;
+  int      outline;        /* draw an outline?  */ 
+  int      cursor_line;    /* cursor line */
+  int      cursor_x;       /* location of cursor (if selected) */
+  int      cursor_y;       /* location of cursor (if selected) */
+  int    (*function) ();   /* textline function */
+} TextBox;
+
+/**************** general structures ****************/
+typedef struct {
+  Pixmap pixmap;
+  int    width;
+  int    height;
+  unsigned char *bits;
+} Icon;
+
+typedef struct {
+  int      dx, dy, x, y;
+  XImage  *pix;
+  char    *data;
+} Picture;
+
+// objects associated with a KiiImage
+// XXX rename thi
+typedef struct {
+  char type[10];
+  double x, y;
+  double dx, dy;
+  double angle;
+  char  *text;
+} Object;
+
+typedef struct {
+  int x, y;
+  int dx, dy;
+  double angle;
+  int  size;
+  char font[64]; 
+  char text[LABEL_MAXLEN];
+} Label;
+
+typedef struct {
+  int active;
+  int Nobjects;
+  unsigned long color;
+  KiiOverlay *objects;
+} Overlay;
+  
+typedef struct {
+  float *x, *y, *z, *dxp, *dxm, *dyp, *dym;
+  int Npts;
+  int style, ptype, ltype, color, etype, ebar;
+  double lweight, size;
+  double x0, x1, y0, y1;  /* limits for this object */
+} Gobjects;
+
+typedef struct {
+  double min, max;
+  char isaxis, areticks, islabel, islog;
+  double fx, dfx, fy, dfy;  /* axis location on graphic */
+} Axis;
+
+// a single graph in the display window
+typedef struct {
+  Axis      axis[4];    /* coordinate axes */
+  Label     label[8];   /* fixed axis labels */
+  Graphdata data;       /* current graph data */
+
+  Gobjects *objects;    /* graphic objects */    
+  int      Nobjects;    
+
+  Label    *textline;      /* placed text labels */
+  int      Ntextline;      
+} KapaGraphWidget;
+
+typedef struct {
+  // data associated with this image element
+  Matrix   matrix;         /* data for picture */
+  double   zero, range;    /* zero, range for picture to cmap */
+  double   max, min;       /* zero, range for data to z-value */
+  double   start, slope;   /* zero, range for cmap to pixels */
+  Coords   coords;
+  char     file[1024];     /* name of file */
+  char     name[1024];     /* name of buffer */
+} KapaImageChannel;
+
+// a single image in the display window
+typedef struct {
+  // picture components of the image element
+  Picture  picture;	      // the primary view of the image
+  Picture  zoom;	      // the zoom window
+  Picture  wide;	      // the wide-view window
+  Picture  cmapbar;	      // the colormap bar
+
+  // the control buttons
+  Button   PS_button;
+  Button   recenter_button;
+  Button   hms_button; /* toggle HMS/DECIMAL mode (DECIMAL_DEG macro) */
+  Button   grey_button;
+  Button   rainbow_button;
+  Button   heat_button;
+  Button   overlay_button[NOVERLAYS];
+
+  // location of the status box
+  int      text_x, text_y;
+  int      text_dx, text_dy, text_dyo;
+  int      location;	      // position of the zoom/status widgets (0 = none, 1-4 = bottom,left,top,right)
+  int      MovePointer;
+  int      DecimalDegrees;
+
+  double   X, Y;           /* image pixel at screen center */
+  int      expand;         /* zoomscale */
+  double   x, y, z;        /* last pointer coords */
+
+  Overlay  overlay[NOVERLAYS];
+  Overlay  tickmarks;
+
+  unsigned short   *pixmap;   // lookup table for image pixel value to pixel index
+  int      nPixels;
+ 
+  KapaImageChannel *image;
+  KapaImageChannel channel[NCHANNELS];
+} KapaImageWidget;
+
+typedef struct {
+  KapaGraphWidget *graph;
+  KapaImageWidget *image;
+  float  x,  y;
+  float dx, dy;
+  char *name;
+} Section;
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/ButtonFunctions.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/ButtonFunctions.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/ButtonFunctions.c	(revision 16062)
@@ -0,0 +1,127 @@
+# include "Ximage.h"
+
+int PSfunction (Graphic *graphic, KapaImageWidget *image) {
+
+  int status;
+
+  status = PSit ("kapa.ps", "default", TRUE, KAPA_PS_NEWPLOT);
+  return (status);
+}
+
+int greycolors (Graphic *graphic, KapaImageWidget *image) {
+  SetColormap ("greyscale");
+  CreateColorbar (image, graphic);
+  SetColorScale (graphic, image);
+  Remap (graphic, image);
+  CreateZoom (image, graphic, 0, 0); 
+  Refresh ();
+  XFlush (graphic[0].display);
+  return (TRUE);
+}
+
+int heat (Graphic *graphic, KapaImageWidget *image) {
+  SetColormap ("heat");
+  CreateColorbar (image, graphic);
+  SetColorScale (graphic, image);
+  Remap (graphic, image);
+  CreateZoom (image, graphic, 0, 0); 
+  Refresh ();
+  XFlush (graphic[0].display);
+  return (TRUE);
+}
+
+int rainbow (Graphic *graphic, KapaImageWidget *image) {
+  SetColormap ("rainbow");
+  CreateColorbar (image, graphic);
+  SetColorScale (graphic, image);
+  Remap (graphic, image);
+  CreateZoom (image, graphic, 0, 0); 
+  Refresh ();
+  XFlush (graphic[0].display);
+  return (TRUE);
+}
+
+int Recenter (Graphic *graphic, KapaImageWidget *image) {
+
+  image[0].X = 0;
+  image[0].Y = 0;
+ 
+  Remap (graphic, image);
+  Refresh ();
+  FlushDisplay (graphic[0].display);
+  return (TRUE);
+
+}
+
+int Rescale (Graphic *graphic, KapaImageWidget *image) {
+
+  image[0].expand = 1;
+  Remap (graphic, image);
+  Refresh ();
+  FlushDisplay (graphic[0].display);
+  return (TRUE);
+
+}
+
+int RecenterRescale (Graphic *graphic, KapaImageWidget *image) {
+
+  image[0].X = 0;
+  image[0].Y = 0;
+  image[0].expand = 1;
+ 
+  Remap (graphic, image);
+  Refresh ();
+  FlushDisplay (graphic[0].display);
+  return (TRUE);
+
+}
+
+int ToggleDEG (Graphic *graphic, KapaImageWidget *image) {
+
+  image[0].DecimalDegrees = image[0].DecimalDegrees ^ TRUE;
+  StatusBox (graphic, image);
+  FlushDisplay (graphic[0].display);
+  return (TRUE);
+
+}
+
+/*********** overlay_button functions ************/
+int Overlay0 (Graphic *graphic, KapaImageWidget *image) {
+
+  image[0].overlay[0].active = image[0].overlay[0].active ^ TRUE;
+  Refresh ();
+  FlushDisplay (graphic[0].display);
+  return (TRUE);
+
+}
+
+int Overlay1 (Graphic *graphic, KapaImageWidget *image) {
+
+  image[0].overlay[1].active = image[0].overlay[1].active ^ TRUE;
+  Refresh ();
+  FlushDisplay (graphic[0].display);
+  return (TRUE);
+
+}
+
+int Overlay2 (Graphic *graphic, KapaImageWidget *image) {
+
+  image[0].overlay[2].active = image[0].overlay[2].active ^ TRUE;
+  Refresh ();
+  FlushDisplay (graphic[0].display);
+  return (TRUE);
+
+}
+
+int Overlay3 (Graphic *graphic, KapaImageWidget *image) {
+
+  image[0].overlay[3].active = image[0].overlay[3].active ^ TRUE;
+  Refresh ();
+  FlushDisplay (graphic[0].display);
+  return (TRUE);
+
+}
+
+/* this routine is NOT independent of the number of overlays */
+
+
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/CSaveOverlay.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/CSaveOverlay.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/CSaveOverlay.c	(revision 16062)
@@ -0,0 +1,49 @@
+# include "Ximage.h"
+
+int CSaveOverlay (int sock) {
+
+  char filename[256], *type;
+  int i, N;
+  double ra, dec, ra1, dec1, x1, y1, dra, ddec;
+  FILE *f;
+  Section *section;
+  KapaImageWidget *image;
+
+  KiiScanMessage (sock, "%*s %d %s", &N, filename);
+  
+  section = GetActiveSection();
+  image   = section->image;
+  if (image == NULL) return (TRUE);
+
+  f = fopen (filename, "w");
+  if (f == NULL) {
+    fprintf (stderr, "could not open %s\n", filename);
+    return (TRUE);
+  }
+
+  for (i = 0; i < image[0].overlay[N].Nobjects; i++) {
+    if (image[0].overlay[N].objects[i].type == KII_OVERLAY_LINE) {
+      XY_to_RD (&ra, &dec, image[0].overlay[N].objects[i].x, image[0].overlay[N].objects[i].y, &image[0].image[0].coords);
+      x1 = image[0].overlay[N].objects[i].x + image[0].overlay[N].objects[i].dx;
+      y1 = image[0].overlay[N].objects[i].y + image[0].overlay[N].objects[i].dy;
+      XY_to_RD (&ra1, &dec1, x1, y1, &image[0].image[0].coords);
+      dra = (ra1 - ra);
+      ddec = (dec1 - dec);
+    } else {
+      XY_to_RD (&ra, &dec, image[0].overlay[N].objects[i].x, image[0].overlay[N].objects[i].y, &image[0].image[0].coords);
+      x1 = image[0].overlay[N].objects[i].x;
+      y1 = image[0].overlay[N].objects[i].y + image[0].overlay[N].objects[i].dy;
+      XY_to_RD (&ra1, &dec1, x1, y1, &image[0].image[0].coords);
+      ddec = fabs (dec1 - dec);
+      x1 = image[0].overlay[N].objects[i].x + image[0].overlay[N].objects[i].dx;
+      y1 = image[0].overlay[N].objects[i].y;
+      XY_to_RD (&ra1, &dec1, x1, y1, &image[0].image[0].coords);
+      dra = cos (dec*RAD_DEG) * fabs (ra1 - ra);
+    }
+    type = KiiOverlayTypeByNumber (image[0].overlay[N].objects[i].type);
+    if (type == NULL) continue;
+    fprintf (f, "%s %lf %lf %lf %lf\n", type, ra, dec, dra, ddec);
+   }
+  fclose (f);
+  return (TRUE);
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/Center.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/Center.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/Center.c	(revision 16062)
@@ -0,0 +1,32 @@
+# include "Ximage.h"
+
+int Center (int sock) {
+
+  int zoom;
+  double X, Y;
+  Graphic *graphic;
+  Section *section;
+  KapaImageWidget *image;
+
+  KiiScanMessage (sock, "%lf %lf %d", &X,  &Y, &zoom);
+
+  graphic = GetGraphic();
+  section = GetActiveSection();
+  image = section->image;
+  if (image == NULL) return (TRUE);
+
+  image[0].X = 0.5*image[0].image[0].matrix.Naxis[0] - X;
+  image[0].Y = 0.5*image[0].image[0].matrix.Naxis[1] - Y;
+  if ((zoom != 0) && (zoom != -1)) {
+    image[0].expand = zoom;
+  }
+
+  if (USE_XWINDOW) {
+    Remap (graphic, image);
+    Refresh ();
+    XFlush (graphic[0].display);
+  }
+
+  return (TRUE);
+}
+
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/CheckButtons.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/CheckButtons.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/CheckButtons.c	(revision 16062)
@@ -0,0 +1,48 @@
+# include "Ximage.h"
+
+/******** Here we test the Buttons specific to this program  *******/
+Button *CheckButtons (XButtonEvent  *event, KapaImageWidget *image) {
+
+  int i;
+  Button *button;
+  button = (Button *) NULL;
+
+  if (InButton (event, &image[0].recenter_button)) 
+    button = &image[0].recenter_button;
+
+  if (InButton (event, &image[0].grey_button)) 
+    button = &image[0].grey_button;
+
+  if (InButton (event, &image[0].rainbow_button)) 
+    button = &image[0].rainbow_button;
+
+  if (InButton (event, &image[0].heat_button)) 
+    button = &image[0].heat_button;
+
+  if (InButton (event, &image[0].PS_button)) 
+    button = &image[0].PS_button;
+
+  if (InButton (event, &image[0].hms_button)) 
+    button = &image[0].hms_button;
+
+  for (i = 0; i < NOVERLAYS; i++) {
+    if (InButton (event, &image[0].overlay_button[i])) 
+      button = &image[0].overlay_button[i];
+  }
+
+  return (button);
+
+}
+
+/* To define a button, you must:
+
+   0) add the button to the Image structure in structures.h
+   1) place the info about the button in PositionPicture.c
+   2) (make any bitmaps needed and put them in buttons.h
+   3) place an entry in CheckButtons.c
+   4) Add the button to Refresh.c
+   5) create the button's function
+   6) add it to the Makefile
+   7) add it to the prototypes
+
+*/
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/CheckColors.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/CheckColors.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/CheckColors.c	(revision 16062)
@@ -0,0 +1,44 @@
+# include "Ximage.h"
+
+/************** CheckColors *************/
+void CheckColors (Graphic *graphic, int *argc, char **argv) {
+
+  char *temp_name;
+  int N;
+
+  graphic->fore = BlackPixel (graphic->display, graphic->screen);
+  temp_name = XGetDefault (graphic->display, argv[0], "Foreground");
+  if ((N = get_argument (*argc, argv, "-fg"))) {
+    if (*argc <= N + 1) {
+      fprintf (stderr, "error: usage is -fg color\n");
+      exit (0);
+    }
+    remove_argument (N, argc, argv);
+    temp_name = argv[N];
+    remove_argument (N, argc, argv);
+  } 
+  if (temp_name != NULL) {
+    graphic->fore = GetColor (graphic->display, temp_name, graphic->colormap, graphic->fore);
+  }
+
+  graphic->back = WhitePixel (graphic->display, graphic->screen);
+  temp_name = XGetDefault (graphic->display, argv[0], "Background");
+  if ((N = get_argument (*argc, argv, "-bg"))) {
+    if (*argc <= N + 1) {
+      fprintf (stderr, "error: usage is -bg color\n");
+      exit (0);
+    }
+    remove_argument (N, argc, argv);
+    temp_name = argv[N];
+    remove_argument (N, argc, argv);
+  } 
+  if (temp_name != NULL) {
+    graphic->back = GetColor (graphic->display, temp_name, graphic->colormap, graphic->back);
+  }
+  return;
+}
+
+  /* here we define the values for foreground and background
+     if -fg, or -bg exist, or if Foreground or Background are set in .Xdefaults, 
+     use those.  foreground defaults to black, background defaults to white. */
+
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/CheckDisplayName.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/CheckDisplayName.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/CheckDisplayName.c	(revision 16062)
@@ -0,0 +1,31 @@
+# include "Ximage.h"
+
+/************** CheckDisplayName *************/
+char *CheckDisplayName (int *argc, char **argv) {
+
+  char *name = NULL;
+  int N;
+
+  if ((N = get_argument (*argc, argv, "-d"))) {
+    if (*argc <= N + 1) {
+      fprintf (stderr, "error: usage is [-display/-d] DisplayName\n");
+      exit (0);
+    }
+    remove_argument(N, argc, argv);
+    name = strcreate (argv[N]);
+    remove_argument(N, argc, argv);
+    return (name);
+  }
+
+  if ((N = get_argument (*argc, argv, "-display"))) {
+    if (*argc <= N + 1) {
+      fprintf (stderr, "error: usage is [-display/-d] DisplayName\n");
+      exit (0);
+    }
+    remove_argument(N, argc, argv);
+    name = strcreate (argv[N]);
+    remove_argument(N, argc, argv);
+    return (name);
+  }
+  return (NULL);
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/CheckGeometry.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/CheckGeometry.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/CheckGeometry.c	(revision 16062)
@@ -0,0 +1,26 @@
+# include "Ximage.h"
+
+/************** CheckGeometry *************/
+void CheckGeometry (Graphic *graphic, int *argc, char **argv) {
+
+  int status, N;
+  char *temp_name;
+  
+  temp_name = XGetDefault (graphic->display, argv[0], "geometry");
+  if ((N = get_argument (*argc, argv, "-geom"))) {
+    if (*argc <= N + 1) {
+      fprintf (stderr, "error: usage is -geom DisplayName\n");
+      exit (0);
+    }
+    remove_argument (N, argc, argv);
+    temp_name = argv[N];
+    remove_argument (N, argc, argv);
+  }
+  if (temp_name == NULL) return;
+
+  status = XParseGeometry (temp_name, &graphic->x, &graphic->y, &graphic->dx, &graphic->dy);
+  if (status & XNegative) graphic->x += DisplayWidth  (graphic->display, graphic->screen) - graphic->dx;
+  if (status & YNegative) graphic->y += DisplayHeight (graphic->display, graphic->screen) - graphic->dy;
+
+  return;
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/CheckPipe.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/CheckPipe.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/CheckPipe.c	(revision 16062)
@@ -0,0 +1,315 @@
+# include "Ximage.h"
+# define STRCONST(A) ((int)(0x1000000*A[0] + 0x10000*A[1] + 0x100*A[2] + 0x1*A[3]))
+
+static KapaSockAddress Address;
+static int InitSocket = -1;
+static int sock = -1;
+
+// we can supply a port here, with only small changes
+void InitPipe (char *namedSocket) {
+
+  if (namedSocket == NULL) {
+    InitSocket = KapaServerInit (&Address);
+  } else {
+    sock = KapaWaitNamedSocket (namedSocket);
+  }
+  return;
+}
+
+int GetActiveSocket () {
+  return (sock);
+}
+
+// after we have processed the command, we unblock the socket
+# define FINISHED(A) { fcntl (sock, F_SETFL, O_NONBLOCK); return (A); }
+
+int CheckPipe () {
+
+  int status;
+  char word[5];
+
+  // check if we have a valid connection. if not, see if we can get one
+  if (sock == -1) {
+    sock = KapaServerWait (InitSocket, &Address);
+    if (sock == -1) return (TRUE);
+    close (InitSocket); /* stop listening for new connections */
+    fcntl (sock, F_SETFL, O_NONBLOCK);  
+  }
+
+  /***** read (4 byte) message word from socket ****/
+  status = read (sock, word, 4);
+  word[4] = 0;
+  switch (status) {
+  case -1:                          /* no input from pipe: continue */
+    return (TRUE);
+    break;
+
+  case 0:
+    fprintf (stderr, "pipe has died!\n");
+    return (FALSE);
+    break;
+
+  case 4:
+    break;
+
+  default:
+    fprintf (stderr, "weird signal: too many or few bytes!  %d\n", status);
+    return (TRUE);
+    break;
+  }
+  
+  /* once we get a command, we block to ensure we get complete messages */
+  fcntl (sock, F_SETFL, !O_NONBLOCK);  
+
+  /***** handle different messages ****/
+  if (ACTIVE_CURSOR) {
+    if (strcmp (word, "NCUR")) {
+      fprintf (stderr, "wrong end message %s\n", word);
+      KiiSendCommand (sock, 4, "DONE");
+      FINISHED (TRUE);
+    }
+    ACTIVE_CURSOR = FALSE;
+    KiiSendCommand (sock, 4, "DONE");
+    FINISHED (TRUE);
+  } 
+
+  if (!strcmp (word, "QUIT")) FINISHED (FALSE);
+  
+  if (!strcmp (word, "CURS")) {
+    ACTIVE_CURSOR = TRUE;
+    KiiSendCommand (sock, 4, "DONE");
+    FINISHED (TRUE);
+  }
+  
+  if (!strcmp (word, "PSIT")) {
+    status = PScommand (sock);
+    KiiSendCommand (sock, 4, "DONE");
+    FINISHED (status);
+  }
+  
+  if (!strcmp (word, "PNGF")) {
+    status = PNGit (sock);
+    KiiSendCommand (sock, 4, "DONE");
+    FINISHED (status);
+  }
+  
+  if (!strcmp (word, "PPMF")) {
+    status = PPMit (sock);
+    KiiSendCommand (sock, 4, "DONE");
+    FINISHED (status);
+  }
+  
+  if (!strcmp (word, "DBOX")) {
+    status = LoadFrame (sock);
+    KiiSendCommand (sock, 4, "DONE");
+    FINISHED (status);
+  }
+  
+  if (!strcmp (word, "PLOT")) {
+    status = LoadObject (sock);
+    // LoadObject sends its own handshake
+    // KiiSendCommand (sock, 4, "DONE");
+    FINISHED (status);
+  }
+  
+  if (!strcmp (word, "LABL")) {
+    status = LoadLabels (sock);
+    KiiSendCommand (sock, 4, "DONE");
+    FINISHED (TRUE);
+  }
+  
+  if (!strcmp (word, "PTXT")) {
+    status = LoadTextlines (sock);
+    KiiSendCommand (sock, 4, "DONE");
+    FINISHED (TRUE);
+  }
+  
+  if (!strcmp (word, "RSIZ")) {
+    status = Resize (sock);
+    KiiSendCommand (sock, 4, "DONE");
+    FINISHED (status);
+  }
+
+  if (!strcmp (word, "GLIM")) {
+    GetLimits (sock);
+    KiiSendCommand (sock, 4, "DONE");
+    FINISHED (TRUE);
+  }
+  
+  if (!strcmp (word, "SLIM")) {
+    status = SetLimits (sock);
+    KiiSendCommand (sock, 4, "DONE");
+    FINISHED (TRUE);
+  }
+  
+  if (!strcmp (word, "GSTY")) {
+    GetGraphData (sock);
+    KiiSendCommand (sock, 4, "DONE");
+    FINISHED (TRUE);
+  }
+  
+  if (!strcmp (word, "SSTY")) {
+    status = SetGraphData (sock);
+    KiiSendCommand (sock, 4, "DONE");
+    FINISHED (TRUE);
+  }
+  
+  if (!strcmp (word, "SIMC")) {
+    SetImageCoords (sock);
+    KiiSendCommand (sock, 4, "DONE");
+    FINISHED (TRUE);
+  }
+  
+  if (!strcmp (word, "GIMC")) {
+    GetImageCoords (sock);
+    KiiSendCommand (sock, 4, "DONE");
+    FINISHED (TRUE);
+  }
+  
+  if (!strcmp (word, "GIMR")) {
+    GetImageRange (sock);
+    KiiSendCommand (sock, 4, "DONE");
+    FINISHED (TRUE);
+  }
+  
+  if (!strcmp (word, "GIMD")) {
+    GetImageData (sock);
+    KiiSendCommand (sock, 4, "DONE");
+    FINISHED (TRUE);
+  }
+  
+  if (!strcmp (word, "SIMD")) {
+    status = SetImageData (sock);
+    KiiSendCommand (sock, 4, "DONE");
+    FINISHED (TRUE);
+  }
+  
+  if (!strcmp (word, "TOOL")) {
+    SetToolbox (sock);
+    KiiSendCommand (sock, 4, "DONE");
+    FINISHED (TRUE);
+  }
+  
+  if (!strcmp (word, "SSEC")) {
+    status = SetSection (sock);
+    KiiSendCommand (sock, 4, "DONE");
+    FINISHED (TRUE);
+  }
+  
+  if (!strcmp (word, "LSEC")) {
+    status = ListSection (sock);
+    KiiSendCommand (sock, 4, "DONE");
+    FINISHED (TRUE);
+  }
+  
+  if (!strcmp (word, "DSEC")) {
+    status = DefineSection (sock);
+    KiiSendCommand (sock, 4, "DONE");
+    FINISHED (TRUE);
+  }
+  
+  if (!strcmp (word, "MSEC")) {
+    status = MoveSection (sock);
+    KiiSendCommand (sock, 4, "DONE");
+    FINISHED (TRUE);
+  }
+  
+  if (!strcmp (word, "FONT")) {
+    status = SetFont (sock);
+    KiiSendCommand (sock, 4, "DONE");
+    FINISHED (TRUE);
+  }
+  
+  /* Erase Section */
+  if (!strcmp (word, "ERSC")) {
+    status = EraseCurrentPlot ();
+    KiiSendCommand (sock, 4, "DONE");
+    FINISHED (status);
+  }
+  
+  /* Erase Plots */
+  if (!strcmp (word, "ERSP")) {
+    status = ErasePlots ();
+    KiiSendCommand (sock, 4, "DONE");
+    FINISHED (status);
+  }
+  
+  /* Erase Sections */
+  if (!strcmp (word, "ERSS")) {
+    status = EraseSections ();
+    KiiSendCommand (sock, 4, "DONE");
+    FINISHED (status);
+  }
+
+  /* Erase Image */
+  if (!strcmp (word, "ERSI")) {
+    status = EraseImage ();
+    KiiSendCommand (sock, 4, "DONE");
+    FINISHED (status);
+  }
+
+  /* Erase Overlay for this section */
+  if (!strcmp (word, "ERSO")) {
+    status = EraseOverlay (sock);
+    KiiSendCommand (sock, 4, "DONE");
+    FINISHED (status);
+  }
+
+  if (!strcmp (word, "READ")) {
+    status = LoadPicture (sock);
+    KiiSendCommand (sock, 4, "DONE");
+    FINISHED (status);
+  }
+
+  if (!strcmp (word, "LOAD")) {
+    status = LoadOverlay (sock);
+    KiiSendCommand (sock, 4, "DONE");
+    FINISHED (status);
+  }
+
+  if (!strcmp (word, "CHAN")) {
+    status = SetChannel (sock);
+    KiiSendCommand (sock, 4, "DONE");
+    FINISHED (status);
+  }
+
+  if (!strcmp (word, "CMAP")) {
+    status = SetColormapFromPipe (sock);
+    KiiSendCommand (sock, 4, "DONE");
+    FINISHED (status);
+  }
+
+  if (!strcmp (word, "SAVE")) {
+    status = SaveOverlay (sock);
+    KiiSendCommand (sock, 4, "DONE");
+    FINISHED (status);
+  }
+
+  if (!strcmp (word, "CSVE")) {
+    status = CSaveOverlay (sock);
+    KiiSendCommand (sock, 4, "DONE");
+    FINISHED (status);
+  }
+
+  if (!strcmp (word, "JPEG")) {
+    status = JPEGit24 (sock);
+    KiiSendCommand (sock, 4, "DONE");
+    FINISHED (status);
+  }
+
+  if (!strcmp (word, "CENT")) {
+    status = Center (sock);
+    KiiSendCommand (sock, 4, "DONE");
+    FINISHED (status);
+  }
+
+  if (!strcmp (word, "NPIX")) {
+    GetPixelCount (sock);
+    KiiSendCommand (sock, 4, "DONE");
+    FINISHED (TRUE);
+  }
+
+  fprintf (stderr, "unknown signal %s\n", word);
+  KiiSendCommand (sock, 4, "DONE");
+  FINISHED (TRUE);
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/CheckVisual.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/CheckVisual.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/CheckVisual.c	(revision 16062)
@@ -0,0 +1,182 @@
+# include "Ximage.h"
+
+/* DirectColor doesn't seem to work, even though it is available:
+   I cannot use XAllocColorCells to get pixels under DirectColor
+*/
+
+/* static int try_visual[] = {5, 3, 1, 4, 2, 0}; */
+
+void CheckVisual (Graphic *graphic, int *argc, char **argv) {
+
+  int i, Nfound, N;
+  int isColor, isDefault, isDynamic;
+  XVisualInfo *visual_list, visual_temp;
+  unsigned long planes[3];
+  XPixmapFormatValues *pixmaps;
+  int Npixmaps;
+
+  if (DEBUG) {
+    fprintf (stderr, "DirectColor: %d\n", DirectColor);
+    fprintf (stderr, "PseudoColor: %d\n", PseudoColor);
+    fprintf (stderr, "TrueColor:   %d\n", TrueColor);
+    fprintf (stderr, "GrayScale:   %d\n", GrayScale);
+    fprintf (stderr, "StaticColor: %d\n", StaticColor);
+    fprintf (stderr, "StaticGray:  %d\n", StaticGray);
+  }
+
+  visual_temp.screen = graphic[0].screen;
+  
+  /* find available visuals */
+  visual_list = XGetVisualInfo (graphic[0].display, VisualScreenMask, &visual_temp, &Nfound);
+  if (Nfound == 0) {
+    fprintf (stderr, "error finding useful visual\n");
+    exit (0);
+  }
+  
+  /* check default visual first */ 
+  for (i = 0; (i < Nfound) && (graphic[0].visual != visual_list[i].visual); i++);
+  if (i == Nfound) {
+    fprintf (stderr, "default visual not found??\n");
+    exit (0);
+  }
+
+  // set these based on selected visual
+  isColor = isDefault = isDynamic = FALSE;
+
+  // attempt to select the most desirable type of visual: Default as PseudoColor (XXX is it still true?)
+  if (DEBUG) fprintf (stderr, "default visual class is %d\n", visual_list[i].class);
+  if (visual_list[i].class == PseudoColor) {
+    isColor = isDefault = isDynamic = TRUE;
+    graphic[0].visual = visual_list[i].visual;
+    graphic[0].visualclass = TRUE;
+    goto test_pixels;
+  }
+
+  // attempt to select the most desirable type of visual: PseudoColor (XXX is it still true?)
+  for (i = 0; (i < Nfound) && (visual_list[i].class != PseudoColor); i++);
+  if (i != Nfound) {
+    isColor = isDynamic = TRUE;
+    if (DEBUG) fprintf (stderr, "selected visual class is %d\n", visual_list[i].class);
+    isDefault = (graphic[0].visual == visual_list[i].visual);
+    graphic[0].visual = visual_list[i].visual;
+    graphic[0].visualclass = TRUE;
+    goto test_pixels;
+  }
+
+  // attempt to select the most desirable type of visual: GrayScale (XXX is it still true?)
+  for (i = 0; (i < Nfound) && (visual_list[i].class != GrayScale); i++);
+  if (i != Nfound) {
+    isDynamic = TRUE;
+    if (DEBUG) fprintf (stderr, "selected visual class is %d\n", visual_list[i].class);
+    isDefault = (graphic[0].visual == visual_list[i].visual);
+    graphic[0].visual = visual_list[i].visual;
+    graphic[0].visualclass = TRUE;
+    goto test_pixels;
+  }
+
+  // attempt to select the most desirable type of visual: TrueColor (XXX is it still true?)
+  for (i = 0; (i < Nfound) && (visual_list[i].class != TrueColor); i++);
+  if (i != Nfound) {
+    isColor = TRUE;
+    if (DEBUG) fprintf (stderr, "visual class is %d\n", visual_list[i].class);
+    isDefault = (graphic[0].visual == visual_list[i].visual);
+    graphic[0].visual = visual_list[i].visual;
+    graphic[0].visualclass = FALSE;
+    goto test_pixels;
+  }
+
+  // attempt to select the most desirable type of visual: TrueColor (XXX is it still true?)
+  for (i = 0; (i < Nfound) && (visual_list[i].class != StaticColor); i++);
+  if (i != Nfound) {
+    if (DEBUG) fprintf (stderr, "visual class is %d\n", visual_list[i].class);
+    isDefault = (graphic[0].visual == visual_list[i].visual);
+    graphic[0].visual = visual_list[i].visual;
+    graphic[0].visualclass = FALSE;
+    goto test_pixels;
+  }
+
+  // attempt to select the most desirable type of visual: TrueColor (XXX is it still true?)
+  for (i = 0; (i < Nfound) && (visual_list[i].class != StaticGray); i++);
+  if (i != Nfound) {
+    if (DEBUG) fprintf (stderr, "visual class is %d\n", visual_list[i].class);
+    isDefault = (graphic[0].visual == visual_list[i].visual);
+    graphic[0].visual = visual_list[i].visual;
+    graphic[0].visualclass = FALSE;
+    goto test_pixels;
+  }
+
+  test_pixels:
+
+  /* need to make a colormap if 
+     1) the selected visual is not the default 
+     2) there are not enough colors available */
+
+  /* NEED TO ADD A COUPLE LINES DEFINING THE VARIOUS HARD COLORS (BLACK, WHITE, AND THE OVERLAYS) */
+
+  // allow user to force a private colormap
+  if ((N = get_argument (*argc, argv, "-private"))) {
+    remove_argument(N, argc, argv);
+    isDefault = FALSE;
+  } 
+
+  // allocate a private colormap, if needed
+  if (!isDefault) {
+    if (DEBUG) fprintf (stderr, "allocated private colormap\n");
+    graphic[0].colormap = XCreateColormap (graphic[0].display, RootWindow (graphic[0].display, graphic[0].screen), graphic[0].visual, AllocNone);
+  }
+
+  if (isDynamic) {
+    /* allocate color cells */
+    ALLOCATE (graphic[0].pixels, unsigned long, NPIXELS_DYNAMIC);
+    ALLOCATE (graphic[0].cmap,   XColor,        NPIXELS_DYNAMIC);
+    for (graphic[0].Npixels = NPIXELS_DYNAMIC; graphic[0].Npixels >= 16; graphic[0].Npixels -= 4) {
+      if (DEBUG) fprintf (stderr, "trying %d colors\n", (int) graphic[0].Npixels);
+      if (XAllocColorCells (graphic[0].display, graphic[0].colormap, FALSE, planes, 1, graphic[0].pixels, graphic[0].Npixels)) {
+	break;
+      }
+    }
+
+    /* insufficient cells, can we make a private colormap? */
+    if (graphic[0].Npixels < 16) {
+      if (!isDefault) {
+	fprintf (stderr, "can't allocate enough cells in private colormap\n");
+	exit (0);
+      }
+      if (DEBUG) fprintf (stderr, "can't allocate enough cells, using private colormap\n");
+      graphic[0].colormap = XCreateColormap (graphic[0].display, RootWindow (graphic[0].display, graphic[0].screen), graphic[0].visual, AllocNone);
+
+      for (graphic[0].Npixels = NPIXELS_DYNAMIC; graphic[0].Npixels >= 16; graphic[0].Npixels -= 4) {
+	if (DEBUG) fprintf (stderr, "trying %d colors\n", (int) graphic[0].Npixels);
+	if (XAllocColorCells (graphic[0].display, graphic[0].colormap, FALSE, planes, 1, graphic[0].pixels, graphic[0].Npixels)) {
+	  break;
+	}
+      }
+
+      if ((N = get_argument (*argc, argv, "-colorcount"))) {
+	fprintf (stderr, "kapa can grab %d colors\n", graphic[0].Npixels);
+	exit (0);
+      } 
+      if (graphic[0].Npixels < 16) {
+	fprintf (stderr, "can't even allocate enough cells in private colormap\n");
+	exit (0);
+      }
+    }
+  } else {
+    // XXX allocate the unsigned long *pixels here and above
+    ALLOCATE (graphic[0].pixels, unsigned long, NPIXELS_STATIC);
+    ALLOCATE (graphic[0].cmap,   XColor,        NPIXELS_STATIC);
+    graphic[0].Npixels = NPIXELS_STATIC;
+  }
+
+  if ((N = get_argument (*argc, argv, "-colorcount"))) {
+    fprintf (stderr, "kii can grab %d colors\n", graphic[0].Npixels);
+    exit (0);
+  } 
+  
+  pixmaps = XListPixmapFormats (graphic[0].display, &Npixmaps);
+  for (i = 0; i < Npixmaps; i++) {
+    if (pixmaps[i].depth == graphic[0].depth) {
+      graphic[0].Nbits = pixmaps[i].bits_per_pixel;
+    }
+  }
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/CloseDisplay.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/CloseDisplay.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/CloseDisplay.c	(revision 16062)
@@ -0,0 +1,17 @@
+# include "Ximage.h"
+
+/************** CloseDisplay *************/
+void CloseDisplay () {
+
+  Graphic *graphic;
+
+  if (!USE_XWINDOW) return;
+
+  graphic = GetGraphic();
+  XFreeFont (graphic->display, graphic->font); 
+  XFreeGC (graphic->display, graphic->gc);
+  XDestroySubwindows (graphic->display, graphic->window);
+  XDestroyWindow (graphic->display, graphic->window);
+  XFlush (graphic->display);
+  XCloseDisplay (graphic->display);
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/ColorCube.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/ColorCube.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/ColorCube.c	(revision 16062)
@@ -0,0 +1,225 @@
+# include "Ximage.h"
+
+/* these functions are used to generate an appropriately-sampled color map for a given image.
+   we assume that only a limited number of colors can be allocated (start with, eg, 1024, grow to
+   64k or so).  the RGB image is constructed from the 32bit images, each with their own zero and
+   scale.  We want to allocate set of color cells which sample the actual colors available in the
+   image data.  We generate a 3D histogram of the actual data values.  The histogram is generated
+   using a k-d tree. */
+
+// the k-d tree is built of a bunch of nodes, each of which represents a cubic region in the 3D
+// color space.  each node may be occupied, or may point to a set of 8 children, subdividing the
+// cube into equal cubes.
+
+// NOTE : nothing in this file specifies a relationship between x,y,z and red,blue,green
+
+// set of operations needed:
+
+// allocate empty, bottom-level node
+CCNode *CCNodeAlloc () {
+
+  CCNode *node;
+  int ix, iy, iz;
+
+  ALLOCATE (node, CCNode, 1);
+  node->count = 0;
+  node->pixel = 0;
+  node->bottom = TRUE;
+  for (ix = 0; ix < 2; ix++) {
+    for (iy = 0; iy < 2; iy++) {
+      for (iz = 0; iz < 2; iz++) {
+	node->sub[ix][iy][iz] = NULL;
+      }
+    }
+  }
+  return node;
+}
+
+// given a coordinate and a containing node, find the corresponding child node (if any)
+CCNode *CCFindChild (CCNode *node, float x, float y, float z) {
+
+  int ix, iy, iz;
+
+  assert (x >= node->min[CC_X]);
+  assert (y >= node->min[CC_Y]);
+  assert (z >= node->min[CC_Z]);
+
+  assert (x <= node->max[CC_X]);
+  assert (y <= node->max[CC_Y]);
+  assert (z <= node->max[CC_Z]);
+
+  if (node->bottom) return NULL; // already at the bottom
+
+  ix = (x < node->mid[CC_X]) ? 0 : 1;
+  iy = (y < node->mid[CC_Y]) ? 0 : 1;
+  iz = (z < node->mid[CC_Z]) ? 0 : 1;
+  
+  return node->sub[ix][iy][iz];
+}
+
+// given a coordinate and a containing node, find the corresponding child node (if any)
+int CCSplitNode (CCNode *node) {
+
+  CCNode *child;
+  int ix, iy, iz;
+
+  // trying to split an already split node
+  if (!node->bottom) return FALSE;
+
+  node->bottom = FALSE;
+  for (ix = 0; ix < 2; ix++) {
+    for (iy = 0; iy < 2; iy++) {
+      for (iz = 0; iz < 2; iz++) {
+	child = CCNodeAlloc();
+	child->min[CC_X] = (ix == 0) ? node->min[CC_X] : node->mid[CC_X];
+	child->min[CC_Y] = (iy == 0) ? node->min[CC_Y] : node->mid[CC_Y];
+	child->min[CC_Z] = (iz == 0) ? node->min[CC_Z] : node->mid[CC_Z];
+	child->max[CC_X] = (ix == 0) ? node->mid[CC_X] : node->max[CC_X];
+	child->max[CC_Y] = (iy == 0) ? node->mid[CC_Y] : node->max[CC_Y];
+	child->max[CC_Z] = (iz == 0) ? node->mid[CC_Z] : node->max[CC_Z];
+
+	child->mid[CC_X] = 0.5*(child->min[CC_X] + child->max[CC_X]);
+	child->mid[CC_Y] = 0.5*(child->min[CC_Y] + child->max[CC_Y]);
+	child->mid[CC_Z] = 0.5*(child->min[CC_Z] + child->max[CC_Z]);
+
+	node->sub[ix][iy][iz] = child;
+      }
+    }
+  }
+  return TRUE;
+}
+
+int CCSplitNodeIterate (CCNode *node, int current, int max) {
+
+  int ix, iy, iz;
+
+  if (current == max) return TRUE;
+  current ++;
+
+  CCSplitNode (node);
+  for (ix = 0; ix < 2; ix++) {
+    for (iy = 0; iy < 2; iy++) {
+      for (iz = 0; iz < 2; iz++) {
+	CCSplitNodeIterate (node->sub[ix][iy][iz], current, max);
+      }
+    }
+  }
+  return TRUE;
+}
+
+// allocate empty, bottom-level node
+void CCNodeFree (CCNode *node) {
+
+  int ix, iy, iz;
+
+  for (ix = 0; ix < 2; ix++) {
+    for (iy = 0; iy < 2; iy++) {
+      for (iz = 0; iz < 2; iz++) {
+	if (node->sub[ix][iy][iz]) CCNodeFree (node->sub[ix][iy][iz]);
+      }
+    }
+  }
+  free (node);
+  return;
+}
+
+// given a coordinate and a containing node, find the corresponding child node (if any)
+CCNode *CCFindBottom (CCNode *top, float x, float y, float z) {
+
+  CCNode *node;
+  CCNode *next;
+
+  assert (x >= top->min[CC_X]);
+  assert (y >= top->min[CC_Y]);
+  assert (z >= top->min[CC_Z]);
+
+  assert (x <= top->max[CC_X]);
+  assert (y <= top->max[CC_Y]);
+  assert (z <= top->max[CC_Z]);
+
+  node = top;
+  next = CCFindChild (node, x, y, z);
+  while (next != NULL) {
+    node = next;
+    next = CCFindChild (node, x, y, z);
+  }
+
+  return node;
+}
+
+// iterate over the CCNode tree to generate a single, 1d vector of all data values
+// XXX this function is specific to the color histogram concept
+int CCNodeExtractCounts (CCNode *node, float **values, int *nvalues, int *NVALUES) {
+
+  int ix, iy, iz;
+
+  if (*values == NULL) {
+    nvalues[0] = 0;
+    NVALUES[0] = 32;
+    ALLOCATE (*values, float, NVALUES[0]);
+  }
+
+  if (node->bottom) {
+    values[0][nvalues[0]] = node->count;
+    nvalues[0] ++;
+    if (nvalues[0] >= NVALUES[0]) {
+      NVALUES[0] += 32;
+      REALLOCATE (*values, float, NVALUES[0]);
+    }
+    return TRUE;
+  }
+  
+  for (ix = 0; ix < 2; ix++) {
+    for (iy = 0; iy < 2; iy++) {
+      for (iz = 0; iz < 2; iz++) {
+	CCNodeExtractCounts (node->sub[ix][iy][iz], values, nvalues, NVALUES);
+      }
+    }
+  }
+  return TRUE;
+}
+
+// iterate over the CCNode tree and subdivide any bottom level nodes with value > minValue
+// XXX this function is specific to the color histogram concept
+int CCNodeDivideLimit (CCNode *node, float minValue) {
+
+  int ix, iy, iz;
+
+  if (node->bottom) {
+    if (node->count > minValue) {
+      CCSplitNode (node);
+    }
+    return TRUE;
+  }
+  
+  for (ix = 0; ix < 2; ix++) {
+    for (iy = 0; iy < 2; iy++) {
+      for (iz = 0; iz < 2; iz++) {
+	CCNodeDivideLimit (node->sub[ix][iy][iz], minValue);
+      }
+    }
+  }
+  return TRUE;
+}
+
+// iterate over the CCNode tree and subdivide any bottom level nodes with value > minValue
+// XXX this function is specific to the color histogram concept
+int CCNodeInitCounts (CCNode *node, float value) {
+
+  int ix, iy, iz;
+
+  if (node->bottom) {
+    node->count = value;
+    return TRUE;
+  }
+  
+  for (ix = 0; ix < 2; ix++) {
+    for (iy = 0; iy < 2; iy++) {
+      for (iz = 0; iz < 2; iz++) {
+	CCNodeInitCounts (node->sub[ix][iy][iz], value);
+      }
+    }
+  }
+  return TRUE;
+}
+
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/ColorHistogram.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/ColorHistogram.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/ColorHistogram.c	(revision 16062)
@@ -0,0 +1,188 @@
+# include "Ximage.h"
+
+// in 3D we use channels 0,1,2 to choose the pixel from the cube
+void ColorHistogram (KapaImageWidget *image, CCNode *cube) {
+
+  int i, DX, DY, nPixels;
+  float *rData, *bData, *gData, rValue, gValue, bValue;
+  float redSlope, blueSlope, greenSlope;
+  float redStart, blueStart, greenStart;
+  CCNode *node;
+
+  // Input images are scaled to 0.0 - 1.0 floating point range.  These values are accumulated in the
+  // 3d histogram.  Use the histogram to allocate colors or subdivide the top-populated histogram
+  // cells and re-evaluated.   
+
+  // set start & slope for red (channel 0)
+  if (image[0].channel[KAPA_CHANNEL_RED].range != 0.0) {
+    redSlope = 1.0 / image[0].channel[KAPA_CHANNEL_RED].range;
+    redStart = image[0].channel[KAPA_CHANNEL_RED].zero / image[0].channel[KAPA_CHANNEL_RED].range;
+  } else {
+    redSlope = 1.0;
+    redStart = image[0].channel[KAPA_CHANNEL_RED].zero;
+  }
+  // set start & slope for blue (channel 0)
+  if (image[0].channel[KAPA_CHANNEL_BLUE].range != 0.0) {
+    blueSlope = 1.0 / image[0].channel[KAPA_CHANNEL_BLUE].range;
+    blueStart = image[0].channel[KAPA_CHANNEL_BLUE].zero / image[0].channel[KAPA_CHANNEL_BLUE].range;
+  } else {
+    blueSlope = 1.0;
+    blueStart = image[0].channel[KAPA_CHANNEL_BLUE].zero;
+  }
+  // set start & slope for green (channel 0)
+  if (image[0].channel[KAPA_CHANNEL_GREEN].range != 0.0) {
+    greenSlope = 1.0 / image[0].channel[KAPA_CHANNEL_GREEN].range;
+    greenStart = image[0].channel[KAPA_CHANNEL_GREEN].zero / image[0].channel[KAPA_CHANNEL_GREEN].range;
+  } else {
+    greenSlope = 1.0;
+    greenStart = image[0].channel[KAPA_CHANNEL_GREEN].zero;
+  }
+
+  DX = image[0].channel[KAPA_CHANNEL_GREEN].matrix.Naxis[0];
+  DY = image[0].channel[KAPA_CHANNEL_GREEN].matrix.Naxis[1];
+  // XXX check on equal size for all three channels
+
+  nPixels = DX*DY;
+
+  // loop over pixels, convert data values to range values (0.0 - 1.0), increment 3D histogram cell
+  rData = (float *) image[0].channel[KAPA_CHANNEL_RED].matrix.buffer;
+  bData = (float *) image[0].channel[KAPA_CHANNEL_BLUE].matrix.buffer;
+  gData = (float *) image[0].channel[KAPA_CHANNEL_GREEN].matrix.buffer;
+
+  // convert pixel data values to pixel index values (0 - Npixel)
+  for (i = 0; i < nPixels; i++, rData++, bData++, gData++) {
+    rValue = *rData * redSlope   - redStart;
+    if (rValue < 0.0) rValue = 0.0;
+    if (rValue > 1.0) rValue = 1.0;
+    if (isnan(rValue)) rValue = 0.0;
+    if (isinf(rValue)) rValue = 1.0;
+
+    bValue = *bData * blueSlope  - blueStart;
+    if (bValue < 0.0) bValue = 0.0;
+    if (bValue > 1.0) bValue = 1.0;
+    if (isnan(bValue)) bValue = 0.0;
+    if (isinf(bValue)) bValue = 1.0;
+
+    gValue = *gData * greenSlope - greenStart;
+    if (gValue < 0.0) gValue = 0.0;
+    if (gValue > 1.0) gValue = 1.0;
+    if (isnan(gValue)) gValue = 0.0;
+    if (isinf(gValue)) gValue = 1.0;
+
+    // XXX at the moment, we are saturating before supplying to this function
+    // NOTE : x,y,z = red,green,blue
+    node = CCFindBottom (cube, rValue, gValue, bValue);
+    node->count ++;
+  }
+}
+
+// in 3D we use channels 0,1,2 to choose the pixel from the cube
+void CCNodeSetColorPixels (KapaImageWidget *image, CCNode *cube) {
+
+  int i, DX, DY, nPixels;
+  float *rData, *bData, *gData, rValue, gValue, bValue;
+  unsigned short *oData;
+  float redSlope, blueSlope, greenSlope;
+  float redStart, blueStart, greenStart;
+  CCNode *node;
+
+  // Input images are scaled to 0.0 - 1.0 floating point range.  These values are accumulated in the
+  // 3d histogram.  Use the histogram to allocate colors or subdivide the top-populated histogram
+  // cells and re-evaluated.   
+
+  // set start & slope for red (channel 0)
+  if (image[0].channel[KAPA_CHANNEL_RED].range != 0.0) {
+    redSlope = 1.0 / image[0].channel[KAPA_CHANNEL_RED].range;
+    redStart = image[0].channel[KAPA_CHANNEL_RED].zero / image[0].channel[KAPA_CHANNEL_RED].range;
+  } else {
+    redSlope = 1.0;
+    redStart = image[0].channel[KAPA_CHANNEL_RED].zero;
+  }
+  // set start & slope for blue (channel 0)
+  if (image[0].channel[KAPA_CHANNEL_BLUE].range != 0.0) {
+    blueSlope = 1.0 / image[0].channel[KAPA_CHANNEL_BLUE].range;
+    blueStart = image[0].channel[KAPA_CHANNEL_BLUE].zero / image[0].channel[KAPA_CHANNEL_BLUE].range;
+  } else {
+    blueSlope = 1.0;
+    blueStart = image[0].channel[KAPA_CHANNEL_BLUE].zero;
+  }
+  // set start & slope for green (channel 0)
+  if (image[0].channel[KAPA_CHANNEL_GREEN].range != 0.0) {
+    greenSlope = 1.0 / image[0].channel[KAPA_CHANNEL_GREEN].range;
+    greenStart = image[0].channel[KAPA_CHANNEL_GREEN].zero / image[0].channel[KAPA_CHANNEL_GREEN].range;
+  } else {
+    greenSlope = 1.0;
+    greenStart = image[0].channel[KAPA_CHANNEL_GREEN].zero;
+  }
+
+  DX = image[0].channel[KAPA_CHANNEL_GREEN].matrix.Naxis[0];
+  DY = image[0].channel[KAPA_CHANNEL_GREEN].matrix.Naxis[1];
+  // XXX check on equal size for all three channels
+
+  nPixels = DX*DY;
+  if (image[0].nPixels != nPixels) {
+    REALLOCATE (image[0].pixmap, unsigned short, nPixels);
+    image[0].nPixels = nPixels;
+  }
+
+  // loop over pixels, convert data values to range values (0.0 - 1.0), increment 3D histogram cell
+  rData = (float *) image[0].channel[KAPA_CHANNEL_RED].matrix.buffer;
+  bData = (float *) image[0].channel[KAPA_CHANNEL_BLUE].matrix.buffer;
+  gData = (float *) image[0].channel[KAPA_CHANNEL_GREEN].matrix.buffer;
+
+  oData = image[0].pixmap;
+
+  // convert pixel data values to pixel index values (0 - Npixel)
+  for (i = 0; i < nPixels; i++, rData++, bData++, gData++, oData++) {
+    rValue = *rData * redSlope   - redStart;
+    if (rValue < 0.0) rValue = 0.0;
+    if (rValue > 1.0) rValue = 1.0;
+    if (isnan(rValue)) rValue = 0.0;
+    if (isinf(rValue)) rValue = 1.0;
+
+    bValue = *bData * blueSlope  - blueStart;
+    if (bValue < 0.0) bValue = 0.0;
+    if (bValue > 1.0) bValue = 1.0;
+    if (isnan(bValue)) bValue = 0.0;
+    if (isinf(bValue)) bValue = 1.0;
+
+    gValue = *gData * greenSlope - greenStart;
+    if (gValue < 0.0) gValue = 0.0;
+    if (gValue > 1.0) gValue = 1.0;
+    if (isnan(gValue)) gValue = 0.0;
+    if (isinf(gValue)) gValue = 1.0;
+
+    // XXX at the moment, we are saturating before supplying to this function
+    // NOTE : x,y,z = red,green,blue 
+    node = CCFindBottom (cube, rValue, gValue, bValue);
+    *oData = node->pixel;
+  }
+}
+
+// iterate over the CCNode tree and subdivide any bottom level nodes with value > minValue
+// XXX this function is specific to the color histogram concept
+// NOTE : x,y,z = red,green,blue 
+int CCNodeSetColorMap (CCNode *node, XColor *cmap, int Npixels, int *current) {
+
+  int ix, iy, iz;
+
+  if (node->bottom) {
+    cmap[current[0]].red   = node->mid[CC_X]*0xffff;
+    cmap[current[0]].green = node->mid[CC_Y]*0xffff;
+    cmap[current[0]].blue  = node->mid[CC_Z]*0xffff;
+    cmap[current[0]].flags = DoRed | DoGreen | DoBlue;
+    node->pixel = current[0];
+    current[0] ++;
+    assert (current[0] <= Npixels);
+    return TRUE;
+  }
+  
+  for (ix = 0; ix < 2; ix++) {
+    for (iy = 0; iy < 2; iy++) {
+      for (iz = 0; iz < 2; iz++) {
+	CCNodeSetColorMap (node->sub[ix][iy][iz], cmap, Npixels, current);
+      }
+    }
+  }
+  return TRUE;
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/CreateColorbar.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/CreateColorbar.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/CreateColorbar.c	(revision 16062)
@@ -0,0 +1,73 @@
+# include "Ximage.h"
+
+void CreateColorbar (KapaImageWidget *image, Graphic *graphic) {
+
+  int i, j, dx, dy, extra, start;
+  unsigned long  pixvalue;
+  unsigned int  *out24;
+  unsigned char *out8;
+
+  dx = image[0].cmapbar.dx;
+  dy = image[0].cmapbar.dy;
+
+  /* create the cmap scale */
+  switch (graphic[0].Nbits) {
+  case 8:
+    REALLOCATE (image[0].cmapbar.data, char, dx*dy);
+    out8 = (unsigned char *) image[0].cmapbar.data;
+    for (i = 0; i < dx; i++) {
+      pixvalue = graphic[0].cmap[(int)(i*graphic[0].Npixels/dx)].pixel;
+      for (j = 0; j < dy; j++) {
+	out8[j*dx + i] = pixvalue;
+      }
+    }
+    image[0].cmapbar.pix = XCreateImage (graphic[0].display, graphic[0].visual, graphic[0].depth, ZPixmap, 0, 
+					  image[0].cmapbar.data, dx, dy, 8, 0);
+    break;
+
+  case 16:
+    REALLOCATE (image[0].cmapbar.data, char, 2*dy*dx);
+    out8 = (unsigned char *) image[0].cmapbar.data;
+    for (i = 0; i < dx; i++) {
+      pixvalue = graphic[0].cmap[(int)(i*graphic[0].Npixels/dx)].pixel;
+      for (j = 0; j < dy; j++) {
+	start = 2*j*dx + 2*i;
+	out8[start + 0] = 0x0000ff & pixvalue;
+	out8[start + 1] = 0x0000ff & (pixvalue >> 8);
+      }
+    }
+    image[0].cmapbar.pix = XCreateImage (graphic[0].display, graphic[0].visual, graphic[0].depth, ZPixmap, 0, 
+					  image[0].cmapbar.data, dx, dy, 16, 0);
+    break;
+
+  case 24:
+    extra = 4 - (dx * 3) % 4;
+    REALLOCATE (image[0].cmapbar.data, char, dy*(3*dx + extra));
+    out8 = (unsigned char *) image[0].cmapbar.data;
+    for (i = 0; i < dx; i++) {
+      pixvalue = graphic[0].cmap[(int)(i*graphic[0].Npixels/dx)].pixel;
+      for (j = 0; j < dy; j++) {
+	start = j*(3*dx+extra) + 3*i;
+	out8[start + 0] = 0x0000ff & pixvalue;
+	out8[start + 1] = 0x0000ff & (pixvalue >> 8);
+	out8[start + 2] = 0x0000ff & (pixvalue >> 16);
+      }
+    }
+    image[0].cmapbar.pix = XCreateImage (graphic[0].display, graphic[0].visual, graphic[0].depth, ZPixmap, 0, 
+					  image[0].cmapbar.data, dx, dy, 32, 0);
+    break;
+
+  case 32:
+    REALLOCATE (image[0].cmapbar.data, char, 4*dx*dy);
+    out24 = (unsigned int *) image[0].cmapbar.data;
+    for (i = 0; i < dx; i++) {
+      pixvalue = graphic[0].cmap[(int)(i*graphic[0].Npixels/dx)].pixel;
+      for (j = 0; j < dy; j++) {
+	out24[j*dx + i] = pixvalue;
+      }
+    }
+    image[0].cmapbar.pix = XCreateImage (graphic[0].display, graphic[0].visual, graphic[0].depth, ZPixmap, 0, 
+					 image[0].cmapbar.data, dx, dy, 32, 0);
+    break;
+  }
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/CreatePicture.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/CreatePicture.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/CreatePicture.c	(revision 16062)
@@ -0,0 +1,67 @@
+# include "Ximage.h"
+
+void CreatePicture (KapaImageWidget *image, Graphic *graphic) {
+
+  int i, j, extra;
+  unsigned char *c;
+  unsigned int *l;
+  unsigned int start, start1, start2, start3;
+
+  start = graphic[0].back;
+
+  switch (graphic[0].Nbits) {
+  case 8:
+    REALLOCATE (image[0].picture.data, char, image[0].picture.dx*image[0].picture.dy);
+    c = (unsigned char *) image[0].picture.data;
+    for (i = 0; i < (image[0].picture.dx*image[0].picture.dy); i++, c++)
+      *c = start;
+    image[0].picture.pix = XCreateImage (graphic[0].display, graphic[0].visual, graphic[0].depth, ZPixmap, 0, 
+					  image[0].picture.data, image[0].picture.dx, image[0].picture.dy, 8, 0);
+    break;
+
+  case 16:
+    REALLOCATE (image[0].picture.data, char, 2*image[0].picture.dy*image[0].picture.dx);
+    c = (unsigned char *) image[0].picture.data;
+    start1 = 0x0000ff & (start);
+    start2 = 0x0000ff & (start >> 8);
+    for (i = 0; i < image[0].picture.dy; i++) {
+      for (j = 0; j < image[0].picture.dx; j++, c+=2) {
+	c[0] = start1;
+	c[1] = start2;
+      }
+    }
+    image[0].picture.pix = XCreateImage (graphic[0].display, graphic[0].visual, graphic[0].depth, ZPixmap, 0, 
+					  image[0].picture.data, image[0].picture.dx, image[0].picture.dy, 16, 0);
+    break;
+
+  case 24:
+    extra = 4 - (image[0].picture.dx * 3) % 4;
+    REALLOCATE (image[0].picture.data, char, image[0].picture.dy*(3*image[0].picture.dx+extra));
+    c = (unsigned char *) image[0].picture.data;
+    start1 = 0x0000ff & (start);
+    start2 = 0x0000ff & (start >> 8);
+    start3 = 0x0000ff & (start >> 16);
+    for (i = 0; i < image[0].picture.dy; i++) {
+      for (j = 0; j < image[0].picture.dx; j++, c+=3) {
+	c[0] = start1;
+	c[1] = start2;
+	c[2] = start3;
+      }
+      c+=extra;
+    }
+    image[0].picture.pix = XCreateImage (graphic[0].display, graphic[0].visual, graphic[0].depth, ZPixmap, 0, 
+					  image[0].picture.data, image[0].picture.dx, image[0].picture.dy, 24, 0);
+    break;
+
+  case 32:
+    REALLOCATE (image[0].picture.data, char, (4*image[0].picture.dx*image[0].picture.dy + 32));
+    memset (image[0].picture.data, 0xbd, 4*image[0].picture.dx*image[0].picture.dy + 30);
+    l = (unsigned int *) image[0].picture.data;
+    for (i = 0; i < (image[0].picture.dx*image[0].picture.dy); i++, l++)
+      *l = start;
+    image[0].picture.pix = XCreateImage (graphic[0].display, graphic[0].visual, graphic[0].depth, ZPixmap, 0, 
+					  image[0].picture.data, image[0].picture.dx, image[0].picture.dy, 32, 0);
+    break;
+  }
+    
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/CreateWindow.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/CreateWindow.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/CreateWindow.c	(revision 16062)
@@ -0,0 +1,34 @@
+# include "Ximage.h"
+
+/************** CreateWindow *************/
+void CreateWindow (Graphic *graphic, Window parent, int border, long events) {
+
+  XSetWindowAttributes attributes;
+  unsigned long attribute_mask;
+  Visual *visual = CopyFromParent;
+
+  HAVE_BACKING = (DoesBackingStore (ScreenOfDisplay(graphic->display, graphic->screen)) == Always);
+
+  if (HAVE_BACKING) {
+    attributes.backing_store = Always;
+    attribute_mask = CWBackingStore | CWBackPixel | CWBorderPixel | CWEventMask;
+  } else {
+    attribute_mask = CWBackPixel | CWBorderPixel | CWEventMask;
+  }
+
+  attributes.background_pixel = graphic->back;
+  attributes.border_pixel     = graphic->fore;
+  attributes.event_mask       = events;
+
+  graphic->window = XCreateWindow (graphic->display, parent, 
+				     graphic->x, graphic->y, 
+				     graphic->dx, graphic->dy, 
+				     border, CopyFromParent,
+				     InputOutput, visual, 
+				     attribute_mask, &attributes);
+
+  if (graphic->window == (Window) None)
+    QuitX (graphic->display, "error: could not open window");
+
+  XSelectInput (graphic->display, graphic->window, events);
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/CreateZoom.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/CreateZoom.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/CreateZoom.c	(revision 16062)
@@ -0,0 +1,23 @@
+# include "Ximage.h"
+
+void CreateZoom (KapaImageWidget *image, Graphic *graphic, double x, double y) {
+
+  switch (graphic[0].Nbits) {
+  case 8:
+    CreateZoom8 (image, graphic, x, y);
+    break;
+
+  case 16:
+    CreateZoom16 (image, graphic, x, y);
+    break;
+
+  case 24:
+    CreateZoom24 (image, graphic, x, y);
+    break;
+
+  case 32:
+    CreateZoom32 (image, graphic, x, y);
+    break;
+  }    
+
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/CreateZoom16.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/CreateZoom16.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/CreateZoom16.c	(revision 16062)
@@ -0,0 +1,154 @@
+# include "Ximage.h"
+# define FRAC(a) ((a) - (int)(a))
+
+static float slope = 1.0;
+static float start = 0.0;
+static int MaxValue = 255;
+
+// XXX inline this if needed
+static int PixelLookup(float value) {
+  int out;
+  out = MIN (MAX (slope * value - start, 0), MaxValue);
+  return (out);
+}
+
+void CreateZoom16 (KapaImageWidget *image, Graphic *graphic, double x, double y) {
+
+  int i, j, ii, jj;
+  int i_start, i_end, j_start, j_end;
+  int dropback;  /* this is a bit of a kludge... */
+  int dx, dy, DX, DY, pixelN;
+  double expand, zoomscale, Rx, Ry;
+  int expand_in, expand_out;
+  unsigned char *out_pix, *out_pix2, *data;
+  float *imdata, *in_pix,  *in_pix2;
+  unsigned char pixel1[256], pixel2[256];
+  unsigned char pixvalue1, pixvalue2;
+  unsigned long back;
+  unsigned char back1, back2;
+
+  dx = image[0].zoom.dx;
+  dy = image[0].zoom.dy;
+
+  if (image[0].image[0].matrix.size == 0) {  /* create a test pattern */
+    REALLOCATE (image[0].zoom.data, char, 2*dy*dx);
+    bzero (image[0].zoom.data, image[0].zoom.dx*image[0].zoom.dy);
+    image[0].zoom.pix = XCreateImage (graphic[0].display, graphic[0].visual, graphic[0].depth, ZPixmap, 0, 
+				       image[0].zoom.data, image[0].zoom.dx, image[0].zoom.dy, 16, 0);
+    return;
+  }
+
+  for (i = 0; i < 256; i++) { /* set up pixel array */
+    pixel1[i] = 0x0000ff &  graphic[0].cmap[i].pixel;
+    pixel2[i] = 0x0000ff & (graphic[0].cmap[i].pixel >> 8);
+  }
+  back = graphic[0].back;
+  back1 = 0x0000ff & back;
+  back2 = 0x0000ff & (back >> 8);
+  // define the color transform parameters
+  MaxValue = graphic[0].Npixels - 1;
+  if (image[0].image[0].range != 0.0) {
+    slope = graphic[0].Npixels / image[0].image[0].range;
+    start = graphic[0].Npixels * image[0].image[0].zero / image[0].image[0].range;
+  } else {
+    slope = 1.0;
+    start = image[0].image[0].zero;
+  }
+
+  zoomscale = MAX (5, image[0].expand + 5);
+  expand = 1 / zoomscale;
+  expand_out = (int) zoomscale;
+  expand_in  = 1;
+
+  DX = image[0].image[0].matrix.Naxis[0];
+  DY = image[0].image[0].matrix.Naxis[1];
+  Rx = x - expand*(int)(0.5*(dx + 1)) + 1;
+  Ry = y - expand*(int)(0.5*(dy + 1)) + 1;
+
+  i_start = MIN (MAX (-Rx / expand, (1 - FRAC(Rx)) / expand), dx - expand_out + 1);
+  j_start = MIN (MAX (-Ry / expand, (1 - FRAC(Ry)) / expand), dy - expand_out + 1);
+  i_end   = MAX (MIN ((DX-Rx) / expand, dx - expand_out + 1), 0);
+  j_end   = MAX (MIN ((DY-Ry) / expand, dy - expand_out + 1), 0);
+  dropback = expand_out - (i_end - i_start) % expand_out;
+  if ((i_end - i_start) % expand_out == 0) dropback = 0;
+
+  data = out_pix = (unsigned char *) image[0].zoom.data;
+  imdata  = (float *) image[0].image[0].matrix.buffer;
+  in_pix  = &imdata[DX*(int)MAX(Ry,0) + (int)MAX(Rx,0)];
+
+  /********** below we do the mapping from buffer pixels (in) to picture pixels (out) **********/
+
+  if ((i_end < i_start) || (j_end < j_start)) {
+    for (j = 0; j < dx*dy; j++, out_pix++) 
+      *out_pix = back;
+    return;
+  } 
+  
+  /**** fill in bottom area ****/
+  for (j = 0; j < j_start; j++) {
+    for (i = 0; i < dx; i++, out_pix+=2) {
+      out_pix[0] = back1;
+      out_pix[1] = back2;
+    }
+  }
+
+  for (j = j_start; j < j_end; j+= expand_out, in_pix += expand_in*DX) {
+    out_pix = &data[2*j*dx];
+
+    /**** fill in area to the left of the picture ****/
+    for (jj = 0; jj < expand_out; jj++) { 
+      out_pix2 = out_pix + 2*jj*dx;
+      for (i = 0; i < i_start; i++, out_pix2+=2) {
+	out_pix2[0] = back1;
+	out_pix2[1] = back2;
+      }
+    }
+    out_pix += 2*i_start;
+    
+    /*** fill in the picture region ***/
+    in_pix2 = in_pix;
+    if (expand_out == 1) {
+      for (i = i_start; i < i_end; i++, in_pix2+= expand_in, out_pix+=2) {
+	pixelN = PixelLookup(*in_pix2);
+	out_pix[0] = pixel1[pixelN];
+	out_pix[1] = pixel2[pixelN];
+      }
+    } else {
+      for (i = i_start; i < i_end; i+= expand_out, in_pix2++, out_pix+= 2*expand_out) { 
+	pixelN = PixelLookup(*in_pix2);
+	pixvalue1 = pixel1[pixelN];
+	pixvalue2 = pixel2[pixelN];
+	out_pix2 = out_pix;
+	for (jj = 0; jj < expand_out; jj++, out_pix2+=2*(dx-expand_out)) {
+	  for (ii = 0; ii < expand_out; ii++, out_pix2+=2) {
+	    out_pix2[0] = pixvalue1; 
+	    out_pix2[1] = pixvalue2; 
+	  }
+	}
+      }
+    }
+    out_pix -= 2*dropback;
+    
+    /**** fill in area to the right of the picture ****/
+    for (jj = 0; jj < expand_out; jj++) {
+      out_pix2 = out_pix + 2*jj*dx;
+      for (i = i_end; i < dx; i++, out_pix2+=2) {
+	out_pix2[0] = back1;
+	out_pix2[1] = back2;
+      }
+    }
+  } 
+  
+  out_pix = &data[2*j_end*dx];
+  /**** fill in top area ****/
+  for (j = 0; j < (dy - j_end); j++) {
+    for (i = 0; i < dx; i++, out_pix+=2) { 
+      out_pix[0] = back1;
+      out_pix[1] = back2;
+    }
+  }
+
+  image[0].zoom.pix = XCreateImage (graphic[0].display, graphic[0].visual, graphic[0].depth, ZPixmap, 0, 
+					image[0].zoom.data, image[0].zoom.dx, image[0].zoom.dy, 16, 0);
+  
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/CreateZoom24.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/CreateZoom24.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/CreateZoom24.c	(revision 16062)
@@ -0,0 +1,188 @@
+# include "Ximage.h"
+# define FRAC(a) ((a) - (int)(a))
+
+static float slope = 1.0;
+static float start = 0.0;
+static int MaxValue = 255;
+
+// XXX inline this if needed
+static int PixelLookup(float value) {
+  int out;
+  out = MIN (MAX (slope * value - start, 0), MaxValue);
+  return (out);
+}
+
+void CreateZoom24 (KapaImageWidget *image, Graphic *graphic, double x, double y) {
+
+  int i, j, ii, jj, extra;
+  int i_start, i_end, j_start, j_end;
+  int dropback;  /* this is a bit of a kludge... */
+  int dx, dy, DX, DY, pixelN;
+  double expand, zoomscale, Rx, Ry;
+  int expand_in, expand_out;
+  unsigned char *out_pix, *out_pix2, *data;
+  float *imdata, *in_pix, *in_pix2;
+  unsigned char pixel1[256], pixel2[256], pixel3[256];
+  unsigned char pixvalue1, pixvalue2, pixvalue3;
+  unsigned long back;
+  unsigned char back1, back2, back3;
+
+  dx = image[0].zoom.dx;
+  dy = image[0].zoom.dy;
+  extra = 4 - (dx * 3) % 4;
+
+  if (image[0].image[0].matrix.size == 0) {  /* create a test pattern */
+    REALLOCATE (image[0].zoom.data, char, dy*(3*dx+extra));
+    bzero (image[0].zoom.data, image[0].zoom.dx*image[0].zoom.dy);
+    image[0].zoom.pix = XCreateImage (graphic[0].display, graphic[0].visual, graphic[0].depth, ZPixmap, 0, 
+				       image[0].zoom.data, image[0].zoom.dx, image[0].zoom.dy, 32, 0);
+    return;
+  }
+
+  for (i = 0; i < 256; i++) { /* set up pixel array */
+    pixel1[i] = 0x0000ff &  graphic[0].cmap[i].pixel;
+    pixel2[i] = 0x0000ff & (graphic[0].cmap[i].pixel >> 8);
+    pixel3[i] = 0x0000ff & (graphic[0].cmap[i].pixel >> 16);
+  }
+  back = graphic[0].back;
+  back1 = 0x0000ff & back;
+  back2 = 0x0000ff & (back >> 8);
+  back3 = 0x0000ff & (back >> 16);
+
+  // define the color transform parameters
+  MaxValue = graphic[0].Npixels - 1;
+  if (image[0].image[0].range != 0.0) {
+    slope = graphic[0].Npixels / image[0].image[0].range;
+    start = graphic[0].Npixels * image[0].image[0].zero / image[0].image[0].range;
+  } else {
+    slope = 1.0;
+    start = image[0].image[0].zero;
+  }
+
+  zoomscale = MAX (5, image[0].expand + 5);
+  expand = 1 / zoomscale;
+  expand_out = (int) zoomscale;
+  expand_in  = 1;
+
+  DX = image[0].image[0].matrix.Naxis[0];
+  DY = image[0].image[0].matrix.Naxis[1];
+  Rx = x - expand*(int)(0.5*(dx + 1)) + 1;
+  Ry = y - expand*(int)(0.5*(dy + 1)) + 1;
+
+  i_start = MIN (MAX (-Rx / expand, (1 - FRAC(Rx)) / expand), dx - expand_out + 1);
+  j_start = MIN (MAX (-Ry / expand, (1 - FRAC(Ry)) / expand), dy - expand_out + 1);
+  i_end   = MAX (MIN ((DX-Rx) / expand, dx - expand_out + 1), 0);
+  j_end   = MAX (MIN ((DY-Ry) / expand, dy - expand_out + 1), 0);
+  dropback = expand_out - (i_end - i_start) % expand_out;
+  if ((i_end - i_start) % expand_out == 0) dropback = 0;
+
+  data = out_pix = (unsigned char *) image[0].zoom.data;
+  imdata  = (float *) image[0].image[0].matrix.buffer;
+  in_pix  = &imdata[DX*(int)MAX(Ry,0) + (int)MAX(Rx,0)];
+
+  /********** below we do the mapping from buffer pixels (in) to picture pixels (out) **********/
+
+  if ((i_end < i_start) || (j_end < j_start)) {
+    for (j = 0; j < dx*dy; j++, out_pix++) 
+      *out_pix = back;
+    return;
+  } 
+  
+  /**** fill in bottom area ****/
+  for (j = 0; j < j_start; j++) {
+    for (i = 0; i < dx; i++, out_pix+=3) {
+      out_pix[0] = back1;
+      out_pix[1] = back2;
+      out_pix[2] = back3;
+    }
+    out_pix += extra;
+  }
+
+  for (j = j_start; j < j_end; j+= expand_out, in_pix += expand_in*DX) {
+    out_pix = &data[j*(3*dx+extra)];
+
+    /**** fill in area to the left of the picture ****/
+    for (jj = 0; jj < expand_out; jj++) { 
+      out_pix2 = out_pix + jj*(3*dx + extra);
+      for (i = 0; i < i_start; i++, out_pix2+=3) {
+	out_pix2[0] = back1;
+	out_pix2[1] = back2;
+	out_pix2[2] = back3;
+      }
+    }
+    out_pix += 3*i_start;
+    
+    /*** fill in the picture region ***/
+    in_pix2 = in_pix;
+    if (expand_out == 1) {
+      for (i = i_start; i < i_end; i++, in_pix2+= expand_in, out_pix+=3) {
+	pixelN = PixelLookup(*in_pix2);
+	out_pix[0] = pixel1[pixelN];
+	out_pix[1] = pixel2[pixelN];
+	out_pix[2] = pixel3[pixelN];
+      }
+    } else {
+      for (i = i_start; i < i_end; i+= expand_out, in_pix2++, out_pix+= 3*expand_out) { 
+	pixelN   = PixelLookup(*in_pix2);
+	pixvalue1 = pixel1[pixelN];
+	pixvalue2 = pixel2[pixelN];
+	pixvalue3 = pixel3[pixelN];
+	out_pix2 = out_pix;
+	for (jj = 0; jj < expand_out; jj++, out_pix2+=3*(dx-expand_out)+extra) {
+	  for (ii = 0; ii < expand_out; ii++, out_pix2+=3) {
+	    out_pix2[0] = pixvalue1; 
+	    out_pix2[1] = pixvalue2; 
+	    out_pix2[2] = pixvalue3; 
+	  }
+	}
+      }
+    }
+    out_pix -= 3*dropback;
+    
+    /**** fill in area to the right of the picture ****/
+    for (jj = 0; jj < expand_out; jj++) {
+      out_pix2 = out_pix + jj*(3*dx+extra);
+      for (i = i_end; i < dx; i++, out_pix2+=3) {
+	out_pix2[0] = back1;
+	out_pix2[1] = back2;
+	out_pix2[2] = back3;
+      }
+    }
+  } 
+  
+  /*
+  if ((j_end - j_start) % expand_out > 0)
+    out_pix -= (expand_out - (j_end - j_start) % expand_out);
+  */
+
+  out_pix = &data[j_end*(3*dx+extra)];
+  /**** fill in top area ****/
+  for (j = 0; j < (dy - j_end); j++) {
+    for (i = 0; i < dx; i++, out_pix+=3) { 
+      out_pix[0] = back1;
+      out_pix[1] = back2;
+      out_pix[2] = back3;
+    }
+    out_pix+=extra;
+  }
+
+  /*
+  out_pix = (unsigned char *) image[0].zoom.data;
+  for (i = 0; i < dx*dy; i++) {
+    out_pix[3*i + 0] = back1;
+    out_pix[3*i + 1] = back2;
+    out_pix[3*i + 2] = back3;
+  }
+  for (j = 0; j < dy/2; j++) {
+    for (i = 0; i < dx; i++) {
+      out_pix[j*(extra + 3*dx) + 3*i + 0] = pixel1[10];
+      out_pix[j*(extra + 3*dx) + 3*i + 1] = pixel2[10];
+      out_pix[j*(extra + 3*dx) + 3*i + 2] = pixel3[10];
+    }
+
+  }
+  */
+  image[0].zoom.pix = XCreateImage (graphic[0].display, graphic[0].visual, 24, ZPixmap, 0, 
+					image[0].zoom.data, image[0].zoom.dx, image[0].zoom.dy, 32, 0);
+  
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/CreateZoom32.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/CreateZoom32.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/CreateZoom32.c	(revision 16062)
@@ -0,0 +1,123 @@
+# include "Ximage.h"
+# define FRAC(a) ((a) - (int)(a))
+
+void CreateZoom32 (KapaImageWidget *image, Graphic *graphic, double x, double y) {
+
+  int i, j, ii, jj;
+  int i_start, i_end, j_start, j_end;
+  int dropback;  /* this is a bit of a kludge... */
+  int dx, dy, DX, DY;
+  double expand, zoomscale, Rx, Ry;
+  int expand_in, expand_out;
+  unsigned int *out_pix, *out_pix2;
+  unsigned short *in_pix, *in_pix2;
+  unsigned long *pixel, pixvalue;
+  unsigned long back;
+
+  if (image[0].image[0].matrix.size == 0) {  /* create a test pattern */
+    REALLOCATE (image[0].zoom.data, char, 4*image[0].zoom.dx*image[0].zoom.dy);
+    image[0].zoom.pix = XCreateImage (graphic[0].display, graphic[0].visual, graphic[0].depth, ZPixmap, 0, 
+				       image[0].zoom.data, image[0].zoom.dx, image[0].zoom.dy, 32, 0);
+    return;
+  }
+
+  ALLOCATE (pixel, unsigned long, graphic[0].Npixels);
+
+  // local array for pixel values
+  for (i = 0; i < graphic[0].Npixels; i++) { 
+    pixel[i] = graphic[0].cmap[i].pixel;
+  }
+  back = graphic[0].back;
+
+  zoomscale = MAX (5, image[0].expand + 5);
+  expand = 1 / zoomscale;
+  expand_out = (int) zoomscale;
+  expand_in  = 1;
+
+  dx = image[0].zoom.dx;
+  dy = image[0].zoom.dy;
+  DX = image[0].image[0].matrix.Naxis[0];
+  DY = image[0].image[0].matrix.Naxis[1];
+  
+  /* Rx,Ry are the screen coordinates of the first image pixel */
+  Rx = x - expand*(int)(0.5*(dx + 1)) + 1;
+  Ry = y - expand*(int)(0.5*(dy + 1)) + 1;
+
+  i_start = MIN (MAX (-Rx / expand, (1 - FRAC(Rx)) / expand), dx - expand_out + 1);
+  j_start = MIN (MAX (-Ry / expand, (1 - FRAC(Ry)) / expand), dy - expand_out + 1);
+  i_end   = MAX (MIN ((DX-Rx) / expand, dx - expand_out + 1), 0);
+  j_end   = MAX (MIN ((DY-Ry) / expand, dy - expand_out + 1), 0);
+
+  dropback = expand_out - (i_end - i_start) % expand_out;
+  if ((i_end - i_start) % expand_out == 0) dropback = 0;
+
+  out_pix = (unsigned int *) image[0].zoom.data;
+  in_pix  = &image[0].pixmap[DX*(int)MAX(Ry,0) + (int)MAX(Rx,0)];
+
+  /********** below we do the mapping from buffer pixels (in) to picture pixels (out) **********/
+
+  if ((i_end < i_start) || (j_end < j_start)) {
+    for (j = 0; j < dx*dy; j++, out_pix++) 
+      *out_pix = back;
+    return;
+  } 
+ 
+
+  /**** fill in bottom area ****/
+  for (j = 0; j < dx*j_start; j++, out_pix++) {
+    *out_pix = back;
+  }
+
+  for (j = j_start; j < j_end; j+= expand_out, out_pix+=(expand_out-1)*dx, in_pix += expand_in*DX) {
+
+    /**** fill in area to the left of the picture ****/
+    for (jj = 0; (i_start > 0) && (jj < expand_out); jj++) { 
+      out_pix2 = out_pix + jj*dx;
+      for (i = 0; i < i_start; i++, out_pix2++) {
+	*out_pix2 = back;
+      }
+    }
+    out_pix += i_start;
+    
+    /*** fill in the picture region ***/
+    in_pix2 = in_pix;
+    if (expand_out == 1) {
+      for (i = i_start; i < i_end; i++, in_pix2+= expand_in, out_pix++) {
+	*out_pix = pixel[*in_pix2];
+      }
+    } else {
+      for (i = i_start; i < i_end; i+= expand_out, in_pix2++, out_pix+= expand_out) { 
+	pixvalue = pixel[*in_pix2];
+	out_pix2 = out_pix;
+	for (jj = 0; jj < expand_out; jj++, out_pix2+=(dx-expand_out)) {
+	  for (ii = 0; ii < expand_out; ii++, out_pix2++) {
+	    *out_pix2 = pixvalue; 
+	  }
+	}
+      }
+    }
+    out_pix -= dropback;
+    
+    /**** fill in area to the right of the picture ****/
+    for (jj = 0; jj < expand_out; jj++) {
+      out_pix2 = out_pix + jj*dx;
+      for (i = i_end; i < dx; i++, out_pix2++) {
+	*out_pix2 = back;
+      }
+    }
+    out_pix += (dx - i_end);
+  } 
+  
+  if ((j_end - j_start) % expand_out > 0)
+    out_pix -= (expand_out - (j_end - j_start) % expand_out);
+  
+  /**** fill in top area ****/
+  for (j = 0; (j < dx*(dy - j_end)) && (out_pix - (unsigned int *)image[0].zoom.data < dx*dy); j++, out_pix++) { 
+    *out_pix = back;
+  }
+
+  image[0].zoom.pix = XCreateImage (graphic[0].display, graphic[0].visual, graphic[0].depth, ZPixmap, 0, 
+					image[0].zoom.data, image[0].zoom.dx, image[0].zoom.dy, 32, 0);
+  
+  free (pixel);
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/CreateZoom8.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/CreateZoom8.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/CreateZoom8.c	(revision 16062)
@@ -0,0 +1,140 @@
+# include "Ximage.h"
+# define FRAC(a) ((a) - (int)(a))
+
+static float slope = 1.0;
+static float start = 0.0;
+static int MaxValue = 255;
+
+// XXX inline this if needed
+static int PixelLookup(float value) {
+  int out;
+  out = MIN (MAX (slope * value - start, 0), MaxValue);
+  return (out);
+}
+
+void CreateZoom8 (KapaImageWidget *image, Graphic *graphic, double x, double y) {
+
+  int i, j, ii, jj;
+  int i_start, i_end, j_start, j_end;
+  int dropback;  /* this is a bit of a kludge... */
+  int dx, dy, DX, DY, pixelN;
+  double expand, zoomscale, Rx, Ry;
+  int expand_in, expand_out;
+  unsigned char *out_pix, *out_pix2;
+  float *imdata, *in_pix, *in_pix2;
+  unsigned long pixel[256], pixvalue;
+  unsigned long back;
+
+  if (image[0].image[0].matrix.size == 0) {  /* create a test pattern */
+    REALLOCATE (image[0].zoom.data, char, image[0].zoom.dx*image[0].zoom.dy);
+    bzero (image[0].zoom.data, image[0].zoom.dx*image[0].zoom.dy);
+    image[0].zoom.pix = XCreateImage (graphic[0].display, graphic[0].visual, graphic[0].depth, ZPixmap, 0, 
+				       image[0].zoom.data, image[0].zoom.dx, image[0].zoom.dy, 8, 0);
+    return;
+  }
+
+  for (i = 0; i < 256; i++) { /* set up pixel array */
+    pixel[i] = graphic[0].cmap[i].pixel;
+  }
+  back = graphic[0].back;
+
+  // define the color transform parameters
+  MaxValue = graphic[0].Npixels - 1;
+  if (image[0].image[0].range != 0.0) {
+    slope = graphic[0].Npixels / image[0].image[0].range;
+    start = graphic[0].Npixels * image[0].image[0].zero / image[0].image[0].range;
+  } else {
+    slope = 1.0;
+    start = image[0].image[0].zero;
+  }
+
+  zoomscale = MAX (5, image[0].expand + 5);
+  expand = 1 / zoomscale;
+  expand_out = (int) zoomscale;
+  expand_in  = 1;
+
+  dx = image[0].zoom.dx;
+  dy = image[0].zoom.dy;
+  DX = image[0].image[0].matrix.Naxis[0];
+  DY = image[0].image[0].matrix.Naxis[1];
+  Rx = x - expand*(int)(0.5*(dx + 1)) + 1;
+  Ry = y - expand*(int)(0.5*(dy + 1)) + 1;
+
+  i_start = MIN (MAX (-Rx / expand, (1 - FRAC(Rx)) / expand), dx - expand_out + 1);
+  j_start = MIN (MAX (-Ry / expand, (1 - FRAC(Ry)) / expand), dy - expand_out + 1);
+  i_end   = MAX (MIN ((DX-Rx) / expand, dx - expand_out + 1), 0);
+  j_end   = MAX (MIN ((DY-Ry) / expand, dy - expand_out + 1), 0);
+  dropback = expand_out - (i_end - i_start) % expand_out;
+  if ((i_end - i_start) % expand_out == 0) dropback = 0;
+
+  out_pix = (unsigned char *) image[0].zoom.data;
+  imdata  = (float *) image[0].image[0].matrix.buffer;
+  in_pix  = &imdata[DX*(int)MAX(Ry,0) + (int)MAX(Rx,0)];
+
+  /********** below we do the mapping from buffer pixels (in) to picture pixels (out) **********/
+
+  if ((i_end < i_start) || (j_end < j_start)) {
+    for (j = 0; j < dx*dy; j++, out_pix++) 
+      *out_pix = back;
+    return;
+  } 
+  
+  /**** fill in bottom area ****/
+  for (j = 0; j < dx*j_start; j++, out_pix++) 
+    *out_pix = back;
+  
+  for (j = j_start; j < j_end; j+= expand_out, out_pix+=(expand_out-1)*dx, in_pix += expand_in*DX) {
+
+    /**** fill in area to the left of the picture ****/
+    for (jj = 0; jj < expand_out; jj++) { 
+      out_pix2 = out_pix + jj*dx;
+      for (i = 0; i < i_start; i++, out_pix2++) {
+	*out_pix2 = back;
+      }
+    }
+    out_pix += i_start;
+    
+    /*** fill in the picture region ***/
+    in_pix2 = in_pix;
+    if (expand_out == 1) {
+      for (i = i_start; i < i_end; i++, in_pix2+= expand_in, out_pix++) {
+	pixelN = PixelLookup(*in_pix2);
+	*out_pix = pixel[pixelN];
+      }
+    } else {
+      for (i = i_start; i < i_end; i+= expand_out, in_pix2++, out_pix+= expand_out) { 
+	pixelN   = PixelLookup(*in_pix2);
+	pixvalue = pixel[pixelN];
+	out_pix2 = out_pix;
+	for (jj = 0; jj < expand_out; jj++, out_pix2+=(dx-expand_out)) {
+	  for (ii = 0; ii < expand_out; ii++, out_pix2++) {
+	    *out_pix2 = pixvalue;
+	  }
+	}
+      }
+    }
+    out_pix -= dropback;
+    
+    /**** fill in area to the right of the picture ****/
+    for (jj = 0; jj < expand_out; jj++) {
+      out_pix2 = out_pix + jj*dx;
+      for (i = i_end; i < dx; i++, out_pix2++) {
+	*out_pix2 = back;
+      }
+    }
+    out_pix += (dx - i_end);
+    
+  } 
+  
+  if ((j_end - j_start) % expand_out > 0)
+    out_pix -= expand_out - (j_end - j_start) % expand_out;
+  
+  /**** fill in top area ****/
+  for (j = 0; (j < dx*(dy - j_end)) && (out_pix - (unsigned char *) image[0].zoom.data < dx*dy); j++, out_pix++) { 
+    *out_pix = back;
+  }
+
+  image[0].zoom.pix = XCreateImage (graphic[0].display, graphic[0].visual, graphic[0].depth, ZPixmap, 0, 
+					image[0].zoom.data, image[0].zoom.dx, image[0].zoom.dy, 8, 0);
+  
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/CrossHairs.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/CrossHairs.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/CrossHairs.c	(revision 16062)
@@ -0,0 +1,66 @@
+# include "Ximage.h"
+
+void CrossHairs (Graphic *graphic, KapaImageWidget *image) {
+
+  int x0, x1, x5, x7;
+  int y0, y2, y4, y5;
+  double zoomscale;
+
+  zoomscale = MAX (5, image[0].expand + 5);
+  x0 = (zoomscale) * (0.5 * (ZOOM_X + 1) / zoomscale - 2.5) + image[0].zoom.x;
+  x5 = (zoomscale) * (0.5 * (ZOOM_X + 1) / zoomscale - 0.5) + image[0].zoom.x;
+  x7 = (zoomscale) * (0.5 * (ZOOM_X + 1) / zoomscale + 0.5) + image[0].zoom.x;
+  x1 = (zoomscale) * (0.5 * (ZOOM_X + 1) / zoomscale + 2.5) + image[0].zoom.x;
+						    	 
+  y4 = (zoomscale) * (0.5 * (ZOOM_Y + 1) / zoomscale - 2.5) + image[0].zoom.y;
+  y2 = (zoomscale) * (0.5 * (ZOOM_Y + 1) / zoomscale - 0.5) + image[0].zoom.y;
+  y0 = (zoomscale) * (0.5 * (ZOOM_Y + 1) / zoomscale + 0.5) + image[0].zoom.y;
+  y5 = (zoomscale) * (0.5 * (ZOOM_Y + 1) / zoomscale + 2.5) + image[0].zoom.y;
+
+
+  XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].fore);
+  
+  XDrawLine (graphic[0].display, graphic[0].window, graphic[0].gc, 
+	     x0, y0, x5, y0);
+  XDrawLine (graphic[0].display, graphic[0].window, graphic[0].gc, 
+	     x5, y0, x5, y5);
+
+  XDrawLine (graphic[0].display, graphic[0].window, graphic[0].gc, 
+	     x7, y5, x7, y0);
+  XDrawLine (graphic[0].display, graphic[0].window, graphic[0].gc, 
+	     x7, y0, x1, y0);
+
+  XDrawLine (graphic[0].display, graphic[0].window, graphic[0].gc, 
+	     x0, y2, x5, y2);
+  XDrawLine (graphic[0].display, graphic[0].window, graphic[0].gc, 
+	     x5, y2, x5, y4);
+
+  XDrawLine (graphic[0].display, graphic[0].window, graphic[0].gc, 
+	     x7, y4, x7, y2);
+  XDrawLine (graphic[0].display, graphic[0].window, graphic[0].gc, 
+	     x7, y2, x1, y2);
+
+  XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].back);
+  XDrawLine (graphic[0].display, graphic[0].window, graphic[0].gc, 
+	     x0, y0+1, x5-1, y0+1);
+  XDrawLine (graphic[0].display, graphic[0].window, graphic[0].gc, 
+	     x5-1, y0+1, x5-1, y5);
+
+  XDrawLine (graphic[0].display, graphic[0].window, graphic[0].gc, 
+	     x7+1, y5, x7+1, y0+1);
+  XDrawLine (graphic[0].display, graphic[0].window, graphic[0].gc, 
+	     x7+1, y0+1, x1, y0+1);
+
+  XDrawLine (graphic[0].display, graphic[0].window, graphic[0].gc, 
+	     x0, y2-1, x5-1, y2-1);
+  XDrawLine (graphic[0].display, graphic[0].window, graphic[0].gc, 
+	     x5-1, y2-1, x5-1, y4);
+
+  XDrawLine (graphic[0].display, graphic[0].window, graphic[0].gc, 
+	     x7+1, y4, x7+1, y2-1);
+  XDrawLine (graphic[0].display, graphic[0].window, graphic[0].gc, 
+	     x7+1, y2-1, x1, y2-1);
+
+  XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].fore);
+
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/CursorOps.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/CursorOps.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/CursorOps.c	(revision 16062)
@@ -0,0 +1,37 @@
+# include "Ximage.h"
+
+void Screen_to_Image (double *x1, double *y1, double x2, double y2, KapaImageWidget *image) {
+
+  double expand;
+
+  expand = 1.0;
+  if (image[0].expand > 0) {
+    expand = 1 / (1.0*image[0].expand);
+  }
+  if (image[0].expand < 0) {
+    expand = fabs((double)image[0].expand);
+  }
+  
+  *x1 = expand*(x2 - image[0].picture.x - 0.5*image[0].picture.dx) + 0.5*image[0].image[0].matrix.Naxis[0] - image[0].X;
+  *y1 = expand*(y2 - image[0].picture.y - 0.5*image[0].picture.dy) + 0.5*image[0].image[0].matrix.Naxis[1] - image[0].Y;
+  
+}
+
+void Image_to_Screen (double *x1, double *y1, double x2, double y2, KapaImageWidget *image) {
+
+  double expand;
+
+  /* notice that here, expand is the reciprocal of the expand above */
+  expand = 1.0;
+  if (image[0].expand > 0) {
+    expand = abs(image[0].expand);
+  }
+  if (image[0].expand < 0) {
+    expand = 1 / ((double)abs(image[0].expand));
+  }
+  
+  *x1 = (x2 - 0.5*image[0].image[0].matrix.Naxis[0] + image[0].X) * expand + image[0].picture.x + 0.5*image[0].picture.dx;
+  *y1 = (y2 - 0.5*image[0].image[0].matrix.Naxis[1] + image[0].Y) * expand + image[0].picture.y + 0.5*image[0].picture.dy;
+  
+}
+
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/DefineSection.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/DefineSection.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/DefineSection.c	(revision 16062)
@@ -0,0 +1,40 @@
+# include "Ximage.h"
+
+// define the section, but do not create a graph or image 
+int DefineSection (int sock) {
+  
+  int N, MoveSection;
+  char name[128];
+  double x, y, dx, dy;
+  Section *section;
+
+  KiiScanMessage (sock, "%s %lf %lf %lf %lf", name, &x, &y, &dx, &dy);
+
+  MoveSection = FALSE;
+
+  N = GetSectionByName (name);
+  if (N < 0) {
+    section = AddSection (name, x, y, dx, dy);
+    MoveSection = TRUE;
+  } else {
+    section = GetSectionByNumber (N);
+    SetActiveSectionByNumber (N);
+
+    if (section[0].x != x)   MoveSection = TRUE;
+    if (section[0].y != y)   MoveSection = TRUE;
+    if (section[0].dx != dx) MoveSection = TRUE;
+    if (section[0].dy != dy) MoveSection = TRUE;
+
+    section[0].x = x;
+    section[0].y = y;
+    section[0].dx = dx;
+    section[0].dy = dy;
+  }
+
+  if (MoveSection) {
+    SetSectionSizes (section);
+    Refresh (1);
+  }
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/DragColorbar.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/DragColorbar.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/DragColorbar.c	(revision 16062)
@@ -0,0 +1,106 @@
+# include "Ximage.h"
+/* future expansion: warp mouse to the right spot for the current settings */
+
+void DragColorbar (Graphic *graphic, KapaImageWidget *image, XButtonEvent *mouse_event) {
+
+  double          frac_x, oldfrac_x, frac_y, oldfrac_y, start, slope;
+  int             X, Y;
+  XEvent          event;
+  XMotionEvent   *move;
+  int             xstatus, Npix, center;
+
+  if (!graphic[0].visualclass) return;
+
+  X = mouse_event[0].x;
+  Y = mouse_event[0].y;
+  Npix = graphic[0].Npixels;
+  slope = image[0].image[0].slope;
+  start = image[0].image[0].start;
+  oldfrac_x = oldfrac_y = 10;
+  
+  while (1) {
+    frac_x = X / (1.0*graphic[0].dx);
+    frac_x = MAX (0, frac_x);
+    frac_x = MIN (1, frac_x);
+    frac_y = Y / (1.0*graphic[0].dy);
+    frac_y = MAX (0, frac_y);
+    frac_y = MIN (1, frac_y);
+    switch (mouse_event[0].button) {
+    case 1:
+      center = frac_x*Npix;
+      slope = Npix / (1 + 4*frac_y*frac_y*Npix);
+      start = Npix/2.0 - center*slope;
+      break;
+    case 2:
+      start = 0;
+      slope = 1;
+      break;
+    case 3:
+      center = (Npix/2.0 - start) / slope;
+      slope = Npix / (1 + 4*frac_x*frac_x*Npix);
+      start = Npix/2.0 - center*slope;
+      break;
+    }
+
+    if ((frac_x != oldfrac_x) || (frac_y != oldfrac_y)) {
+      ResetColorbar (graphic, start, slope);
+    }
+    oldfrac_x = frac_x;
+    oldfrac_y = frac_y;
+      
+    if ((xstatus = XCheckMaskEvent (graphic[0].display, EVENT_MASK, &event))) {
+      
+      switch (event.type)  {
+	
+      case MotionNotify:
+	if ((xstatus = XPending (graphic[0].display)) < 2) {
+	  move = (XMotionEvent *) &event;
+	  X = move[0].x;
+	  Y = move[0].y;
+	}
+	break;
+	
+      case ButtonPress:
+      case ButtonRelease:
+	image[0].image[0].start = start;	
+	image[0].image[0].slope = slope;
+	return;
+	break;
+	
+      }
+    }
+  }
+  
+}
+
+void ResetColorbar (Graphic *graphic, double start, double slope) {
+
+  int i, j;
+  XColor cmap[256];
+
+  if (!graphic[0].visualclass) return;
+
+  for (i = 0; i < graphic[0].Npixels; i++) {
+    cmap[i] = graphic[0].cmap[i];
+    j = start + i * slope;
+    if (j < 0) {
+      cmap[i].red = graphic[0].cmap[0].red;
+      cmap[i].blue = graphic[0].cmap[0].blue;
+      cmap[i].green = graphic[0].cmap[0].green;
+    }
+    else {
+      if (j >= graphic[0].Npixels) {
+	cmap[i].red = graphic[0].cmap[graphic[0].Npixels-1].red;
+	cmap[i].blue = graphic[0].cmap[graphic[0].Npixels-1].blue;
+	cmap[i].green = graphic[0].cmap[graphic[0].Npixels-1].green;
+      }
+      else {
+	cmap[i].red = graphic[0].cmap[j].red;
+	cmap[i].blue = graphic[0].cmap[j].blue;
+	cmap[i].green = graphic[0].cmap[j].green;
+      }
+    }
+  }
+
+  XStoreColors(graphic[0].display, graphic[0].colormap, cmap, graphic[0].Npixels);
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/DrawBitmap.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/DrawBitmap.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/DrawBitmap.c	(revision 16062)
@@ -0,0 +1,46 @@
+# include "Ximage.h"
+
+void DrawBitmap (Graphic *graphic, int x, int y, int dx, int dy, char *bitmap, int mode) {
+
+  int i, j, byte_line, byte, bit, flag;
+  unsigned long int fore, back;
+
+  fore = graphic[0].fore;
+  back = graphic[0].back;
+
+  if (mode == 0) {
+    fore = graphic[0].fore;
+    back = graphic[0].back;
+    graphic[0].fore = back;
+    graphic[0].back = back;
+  }
+    
+  if (mode == 2) {
+    fore = graphic[0].fore;
+    back = graphic[0].back;
+    graphic[0].fore = back;
+    graphic[0].back = fore;
+  }
+    
+  
+  byte_line = (int) ((dx + 7) / 8);
+  for (i = 0; i < dy; i++) {
+    for (j = 0; j < dx; j++) {
+      byte = byte_line * i + (j / 8);
+      bit = j % 8;
+      flag = 0x01 & (bitmap[byte] >> bit);
+      if (flag)
+	XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].fore);
+      else 
+	XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].back);
+      XDrawPoint (graphic[0].display, graphic[0].window, 
+		  graphic[0].gc, x + j, y + i);
+    }
+  }
+  if (mode == 0) {
+    graphic[0].fore = fore;
+    graphic[0].back = back;
+  }
+  XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].fore);
+}
+
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/DrawButton.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/DrawButton.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/DrawButton.c	(revision 16062)
@@ -0,0 +1,43 @@
+# include "Ximage.h"
+
+void DrawButton (Graphic *graphic, Button *button) {
+  
+  XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].back);
+  XFillRectangle (graphic[0].display, 
+		  graphic[0].window,
+		  graphic[0].gc,
+		  button[0].x,  button[0].y,
+		  button[0].dx, button[0].dy);
+  XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].fore);
+  XDrawRectangle (graphic[0].display, 
+		  graphic[0].window,
+		  graphic[0].gc,
+		  button[0].x,  button[0].y,
+		  button[0].dx, button[0].dy);
+
+  DrawBitmap (graphic, 
+	      button[0].x + (button[0].dx - button[0].width) / 2 + 1, 
+	      button[0].y + (button[0].dy - button[0].height) / 2 + 1, 
+	      button[0].width, button[0].height, 
+	      button[0].bitmap, 1);
+
+  XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].fore);
+}
+
+# if (0)
+  if (button[0].text) {
+    dX = XTextWidth (graphic[0].font, button[0].bitmap, strlen(button[0].bitmap));
+    y = button[0].y + (button[0].dy + graphic[0].font[0].ascent)/2;
+    XDrawString (graphic[0].display, 
+		 graphic[0].window, 
+		 graphic[0].gc, 
+		 button[0].x + (button[0].dx - dX) / 2, y,
+		 button[0].bitmap, strlen(button[0].bitmap));
+  } else {
+    DrawBitmap (graphic, 
+		button[0].x + (button[0].dx - button[0].width) / 2 + 1, 
+		button[0].y + (button[0].dy - button[0].height) / 2 + 1, 
+		button[0].width, button[0].height, 
+		button[0].bitmap, 1);
+  }
+# endif
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/DrawFrame.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/DrawFrame.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/DrawFrame.c	(revision 16062)
@@ -0,0 +1,179 @@
+# 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;
+  double range, major, minor, first, next;
+
+  graphic = GetGraphic();
+
+  // XXX why is this called for every redraw?
+  DrawRotTextInit (graphic->display, graphic->window, graphic->gc, graphic->fore, graphic->back);
+
+  /* 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;
+    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);
+
+    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;
+      if (fabs(range) < MIN_RANGE) continue;
+
+      if (fabs(range) < MIN_RANGE) {
+	range = (range < 0) ? -MIN_RANGE : +MIN_RANGE;
+      }
+
+      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));) {
+	IsLabel = FALSE;
+	if ((fabs((int)(next/major) - (next/major)) < 0.5*(minor/major)) || 
+	    (fabs ((int)((next + 0.5*minor)/major) - (next/major)) < 0.5*(minor/major)) ||
+	    (fabs ((int)((next - 0.5*minor)/major) - (next/major)) < 0.5*(minor/major)))
+	  IsLabel = graph[0].axis[i].islabel;
+	DrawTick (fx, fy, dfx, dfy, P, graph[0].axis[i].min, graph[0].axis[i].max, next, IsLabel, i);
+	if (range > 0) 
+	  next += minor;
+	else 
+	  next -= minor;
+      }
+    }
+  }
+}
+
+void DrawTick (int fx, int fy, int dfx, int dfy, 
+	       int P, double min, double max, 
+	       double value, int mode, int naxis) {
+  
+  int x, y, dx, dy, pos, dir, fontsize;
+  double size, n;
+  char string[64], *fontname;
+
+  if (mode) { 
+    size = MAX (0.02, 7.0 / P); 
+  } else {
+    size = MAX (0.01, 4.0 / P); 
+  }
+  
+  n = P / sqrt ((double)(dfx*dfx + dfy*dfy));
+  x = fx + (value-min)*dfx/(max - min);
+  y = fy + (value-min)*dfy/(max - min);
+
+  dir = +1;
+  if ((naxis == 0) || (naxis == 1)) dir *= -1;
+  dx = dir*size*dfy*n;	
+  dy = dir*size*dfx*n;
+  
+  DrawLine (x, y, dx, dy);
+
+# ifdef IN_AND_OUT_TICKS
+# define GAP 0.03
+# else
+# define GAP 0.01
+# endif
+
+  if (mode == 1) {
+    fontname = GetRotFont (&fontsize);
+    pos = 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 (fabs(value/(max-min)) < 0.001) { value = 0.0; }
+    sprintf (string, "%4g", value);
+    DrawRotText (x, y, string, pos, 0.0);
+  }
+  
+}
+
+
+void AxisTickScale (Axis *axis, double *major, double *minor) {
+
+  double range, lrange, factor, mantis, fmantis, power;
+
+  range = axis[0].max - axis[0].min;
+  if (fabs(range) < MIN_RANGE) {
+    range = (range < 0) ? -MIN_RANGE : +MIN_RANGE;
+  }
+
+  lrange = log10(MAX(fabs(range), MIN_RANGE));
+  mantis = modf (lrange, &factor);
+  if (mantis < 0.0) {
+    mantis += 1.0;
+    factor -= 1.0;
+  }
+  
+  power = MAX(pow(10.0, factor), MIN_RANGE);
+  fmantis = pow(10.0, mantis);
+  *major = MAX(0.5 * power, MIN_RANGE);
+  *minor = MAX(0.1 * power, MIN_RANGE);
+  
+  if ((fmantis >= 1.0) && (fmantis <  1.999)) {
+    *major = 0.5 * power;
+    *minor = 0.1 * power;
+    if (axis[0].areticks == 1) {
+      *major = 1.0 * power;
+      *minor = 0.2 * power;
+    }	  
+  }
+  if ((fmantis >= 1.999) && (fmantis <  3.999)) {
+    *major = 1.0 * power;
+    *minor = 0.2 * power;
+    if (axis[0].areticks == 1) {
+      *major = 2.0 * power;
+      *minor = 0.5 * power;
+    }	  
+  }
+  if ((fmantis >= 3.999) && (fmantis <  5.999)) {
+    *major = 1.0 * power;
+    *minor = 0.5 * power;
+    if (axis[0].areticks == 1) {
+      *major = 2.0 * power;
+      *minor = 0.5 * power;
+    }	  
+  }
+  if ((fmantis >= 5.999) && (fmantis <   7.999)) {
+    *major = 2.0 * power;
+    *minor = 0.5 * power;
+    if (axis[0].areticks == 1) {
+      *major = 2.5 * power;
+      *minor = 0.5 * power;
+    }	  
+  }
+  if ((fmantis >= 7.999) && (fmantis <  10.000)) {
+    *major = 2.5 * power;
+    *minor = 0.5 * power;
+    if (axis[0].areticks == 1) {
+      *major = 5.0 * power;
+      *minor = 1.0 * power;
+    }	  
+  }
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/DrawLabels.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/DrawLabels.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/DrawLabels.c	(revision 16062)
@@ -0,0 +1,60 @@
+# include "Ximage.h"
+  
+void DrawLabels (KapaGraphWidget *graph) {
+  
+  int i, pos, x, y, size;
+  double angle;
+  char *fontname;
+  Graphic *graphic;
+
+  graphic = GetGraphic();
+
+  pos = 0;
+  fontname = GetRotFont (&size);
+  XSetForeground (graphic->display, graphic->gc, graphic->fore);
+  DrawRotTextInit (graphic->display, graphic->window, graphic->gc, graphic->fore, graphic->back);
+
+  /* each label is drawn independently */
+  for (i = 0; i < 8; i++) {
+    if (strcmp (graph[0].label[i].text, "")) {
+      angle = 0;
+      switch (i) {
+      case 0: pos = 7; break;
+      case 1: pos = 1; angle = -90; break;
+      case 2: pos = 1; break;
+      case 3: pos = 1; angle =  90; break;
+      case 4: pos = 2; break;
+      case 5: pos = 0; break;
+      case 6: pos = 8; break;
+      case 7: pos = 6; break;
+      }	
+      x = graph[0].label[i].x;
+      y = graph[0].label[i].y;
+      SetRotFont (graph[0].label[i].font, graph[0].label[i].size);
+      DrawRotText (x, y, graph[0].label[i].text, pos, angle);
+    }
+  }
+  SetRotFont (fontname, size);
+}
+
+  /*
+            
+ 4____2___5 
+  |       | 
+  |       | 
+ 1|       |3
+  |       |
+  |       |
+  ---------
+  6   0   7
+          
+ 6____7___8 
+  |       | 
+  |       | 
+ 3|   4   |5
+  |       |
+  |       |
+  ---------
+  0   1   2
+
+  */
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/DrawObjects.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/DrawObjects.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/DrawObjects.c	(revision 16062)
@@ -0,0 +1,624 @@
+# include "Ximage.h"
+# define DrawLine(X1,Y1,X2,Y2) (XDrawLine (graphic->display, graphic->window, graphic->gc, (int)(X1+0.5), (int)(Y1+0.5), (int)(X2+0.5), (int)(Y2+0.5)))
+# define DrawRectangle(X1,Y1,X2,Y2) (XDrawRectangle (graphic->display, graphic->window, graphic->gc, (int)(X1+0.5), (int)(Y1+0.5), (int)(X2+0.5), (int)(Y2+0.5)))
+# define FillRectangle(X1,Y1,X2,Y2) (XFillRectangle (graphic->display, graphic->window, graphic->gc, (int)(X1+0.5), (int)(Y1+0.5), (int)(X2+0.5), (int)(Y2+0.5)))
+# define DrawCircle(X,Y,R) (XDrawArc (graphic->display, graphic->window, graphic->gc, (int)(X-R+0.5), (int)(Y-R+0.5), abs(2*R+0.5), abs(2*R+0.5), 0, 23040))
+
+# define CONNECT 0
+# define HISTOGRAM 1
+# define POINTS 2
+
+static Graphic *graphic;
+
+void ClipLine (double x0, double y0, double x1, double y1, double X0, double Y0, double X1, double Y1);
+
+/* draw all objects for this Graph */
+int DrawObjects (KapaGraphWidget *graph) {
+  
+  int i;
+  
+  for (i = 0; i < graph[0].Nobjects; i++) {
+    if (DEBUG) fprintf (stderr, "object: %d\n", i);
+    if (DEBUG) fprintf (stderr, "Npts: %d\n", graph[0].objects[i].Npts);
+    DrawObjectN (graph, &graph[0].objects[i]);
+  }    
+  return (TRUE);
+}
+
+/* Draw a specific object in the graph */
+int DrawObjectN (KapaGraphWidget *graph, Gobjects *object) {
+  
+  static char dash[2] = {5,10};
+  static char dot[2] = {3,3};
+  int lweight;
+  
+  // this function calls all of the supporting Draw... functions below
+  graphic = GetGraphic();
+
+  lweight = MAX (0, MIN (10, object[0].lweight));
+
+  /* set line type */
+  switch (object[0].ltype) {
+  case 0:
+    XSetLineAttributes (graphic->display, graphic->gc, lweight, LineSolid, CapNotLast, JoinMiter);
+    break;
+  case 1:
+    XSetDashes (graphic->display, graphic->gc, 100, dash, 2);
+    XSetLineAttributes (graphic->display, graphic->gc, lweight, LineOnOffDash, CapNotLast, JoinMiter);
+    break;
+  case 2:
+    XSetDashes (graphic->display, graphic->gc, 10, dot, 2);
+    XSetLineAttributes (graphic->display, graphic->gc, lweight, LineOnOffDash, CapNotLast, JoinMiter);
+    break;
+  default:
+    XSetLineAttributes (graphic->display, graphic->gc, lweight, LineSolid, CapNotLast, JoinMiter);
+    break;
+  }
+
+  XSetForeground (graphic->display, graphic->gc, graphic->color[object[0].color]);
+
+  switch (object[0].style) {
+  case CONNECT: 
+    DrawConnect (graph, object);
+    break;
+  case HISTOGRAM:
+    DrawHistogram (graph, object);
+    break;
+  case POINTS:
+    DrawPoints (graph, object);
+    break;
+  }
+    
+  if (object[0].etype & 0x01) {
+    DrawYErrors (graph, object);
+  }
+  if (object[0].etype & 0x02) {
+    DrawXErrors (graph, object);
+  }
+
+  XSetLineAttributes (graphic->display, graphic->gc, 0, LineSolid, CapNotLast, JoinMiter);
+  XSetForeground (graphic->display, graphic->gc, graphic->fore);
+  return (TRUE);
+}
+
+/******/
+void DrawConnect (KapaGraphWidget *graph, Gobjects *object) {
+  
+  int i;
+  float *x, *y;
+  double mxi, mxj, myi, myj, bxi, bxj, byi, byj, bx, by;
+  double sx0, sy0, sx1, sy1;
+  double X0, X1, Y0, Y1;
+
+  mxi = graph[0].axis[0].dfx / (object[0].x1 - object[0].x0);
+  mxj = graph[0].axis[1].dfx / (object[0].y1 - object[0].y0);
+  myi = graph[0].axis[0].dfy / (object[0].x1 - object[0].x0);
+  myj = graph[0].axis[1].dfy / (object[0].y1 - object[0].y0);
+  
+  bxi  =  graph[0].axis[0].fx - object[0].x0*graph[0].axis[0].dfx/(object[0].x1 - object[0].x0);
+  bxj  =  -object[0].y0*graph[0].axis[1].dfx/(object[0].y1 - object[0].y0);
+  byi  =  -object[0].x0*graph[0].axis[0].dfy/(object[0].x1 - object[0].x0);
+  byj  =  graph[0].axis[1].fy - object[0].y0*graph[0].axis[1].dfy/(object[0].y1 - object[0].y0);
+  
+  bx = bxi + bxj;
+  by = byi + byj;
+  
+  X0 = graph[0].axis[0].fx;
+  X1 = graph[0].axis[0].fx + graph[0].axis[0].dfx;
+  Y0 = graph[0].axis[1].fy;
+  Y1 = graph[0].axis[1].fy + graph[0].axis[1].dfy;
+
+  x = object[0].x; y = object[0].y;
+  for (i = 0; (i < object[0].Npts) && !(finite(x[i]) && finite(y[i])); i++);
+  if (i >= object[0].Npts) return;
+  sx0 = x[i]*mxi + y[i]*mxj + bx;
+  sy0 = x[i]*myi + y[i]*myj + by;
+
+  for (i++; i < object[0].Npts; i++) {
+    if (!(finite(x[i]) && finite(y[i]))) continue;
+    sx1 = x[i]*mxi + y[i]*mxj + bx;
+    sy1 = x[i]*myi + y[i]*myj + by;
+    
+    ClipLine (sx0, sy0, sx1, sy1, X0, Y0, X1, Y1);
+    /* DrawLine (sx0, sy0, sx1, sy1); */
+    sx0 = sx1; sy0 = sy1;
+  }
+  
+}
+
+void ClipLine (double x0, double y0, double x1, double y1, double X0, double Y1, double X1, double Y0) {
+
+  /* skip line segement if both points are beyond box */
+  if ((x0 <= X0) && (x1 <= X0)) return;
+  if ((x0 >= X1) && (x1 >= X1)) return;
+  if ((y0 <= Y0) && (y1 <= Y0)) return;
+  if ((y0 >= Y1) && (y1 >= Y1)) return;
+
+  /* replace x0,y0 if outside box */
+  if ((x0 < X0) && (x1 >= X0)) {
+    y0 = y0 + (X0 - x0)*(y1 - y0)/(x1 - x0);
+    x0 = X0;
+  }
+  if ((x0 > X1) && (x1 <= X1)) {
+    y0 = y0 + (X1 - x0)*(y1 - y0)/(x1 - x0);
+    x0 = X1;
+  }
+  if ((y0 < Y0) && (y1 >= Y0)) {
+    x0 = x0 + (Y0 - y0)*(x1 - x0)/(y1 - y0);
+    y0 = Y0;
+  }
+  if ((y0 > Y1) && (y1 <= Y1)) {
+    x0 = x0 + (Y1 - y0)*(x1 - x0)/(y1 - y0);
+    y0 = Y1;
+  }
+
+  /* skip line segement if both points are beyond box */
+  if ((x0 <= X0) && (x1 <= X0)) return;
+  if ((x0 >= X1) && (x1 >= X1)) return;
+  if ((y0 <= Y0) && (y1 <= Y0)) return;
+  if ((y0 >= Y1) && (y1 >= Y1)) return;
+
+  /* replace x1,y1 if outside box */
+  if ((x1 < X0) && (x0 >= X0)) {
+    y1 = y0 + (X0 - x0)*(y1 - y0)/(x1 - x0);
+    x1 = X0;
+  }
+  if ((x1 > X1) && (x0 <= X1)) {
+    y1 = y0 + (X1 - x0)*(y1 - y0)/(x1 - x0);
+    x1 = X1;
+  }
+  if ((y1 < Y0) && (y0 >= Y0)) {
+    x1 = x0 + (Y0 - y0)*(x1 - x0)/(y1 - y0);
+    y1 = Y0;
+  }
+  if ((y1 > Y1) && (y0 <= Y1)) {
+    x1 = x0 + (Y1 - y0)*(x1 - x0)/(y1 - y0);
+    y1 = Y1;
+  }
+  DrawLine (x0, y0, x1, y1);
+}
+  
+
+/******/
+void DrawHistogram (KapaGraphWidget *graph, Gobjects *object) {
+
+  int i;
+  float *x, *y;
+  double mxi, mxj, myi, myj, bxi, bxj, byi, byj, bx, by;
+  double sx0, sy0, sx1, sy1, sxa;
+  double X0, X1, Y0, Y1;
+
+  mxi = graph[0].axis[0].dfx / (object[0].x1 - object[0].x0);
+  mxj = graph[0].axis[1].dfx / (object[0].y1 - object[0].y0);
+  myi = graph[0].axis[0].dfy / (object[0].x1 - object[0].x0);
+  myj = graph[0].axis[1].dfy / (object[0].y1 - object[0].y0);
+  
+  bxi  =  graph[0].axis[0].fx - object[0].x0*graph[0].axis[0].dfx/(object[0].x1 - object[0].x0);
+  bxj  =  -object[0].y0*graph[0].axis[1].dfx/(object[0].y1 - object[0].y0);
+  byi  =  -object[0].x0*graph[0].axis[0].dfy/(object[0].x1 - object[0].x0);
+  byj  =  graph[0].axis[1].fy - object[0].y0*graph[0].axis[1].dfy/(object[0].y1 - object[0].y0);
+  
+  bx = bxi + bxj;
+  by = byi + byj;
+  
+  X0 = graph[0].axis[0].fx;
+  X1 = graph[0].axis[0].fx + graph[0].axis[0].dfx;
+  Y0 = graph[0].axis[1].fy;
+  Y1 = graph[0].axis[1].fy + graph[0].axis[1].dfy;
+
+  /* find the first valid datapoint */
+  x = object[0].x; y = object[0].y;
+  for (i = 0; (i < object[0].Npts) && !(finite(x[i]) && finite(y[i])); i++);
+  if (i >= object[0].Npts) return;
+  sx0 = x[i]*mxi + y[i]*mxj + bx;
+  sy0 = x[i]*myi + y[i]*myj + by;
+  sx0 = MIN (MAX (sx0, X0), X1);
+  sy0 = MAX (MIN (sy0, Y0), Y1);
+  
+  /* continue with rest of points */
+  for (i++; i < object[0].Npts; i++) {
+    if (!(finite(x[i]) && finite(y[i]))) continue;
+    sx1 = x[i]*mxi + y[i]*mxj + bx;
+    sy1 = x[i]*myi + y[i]*myj + by;
+    sx1 = MIN (MAX (sx1, X0), X1);
+    sy1 = MAX (MIN (sy1, Y0), Y1);
+    sxa = 0.5*(sx0 + sx1);
+    DrawLine (sx0, sy0, sxa, sy0);
+    DrawLine (sxa, sy0, sxa, sy1);
+    DrawLine (sxa, sy1, sx1, sy1);
+    sx0 = sx1; sy0 = sy1;
+  }
+}
+
+/******/
+void DrawPoints (KapaGraphWidget *graph, Gobjects *object) {
+
+  int i;
+  float *x, *y, *z;
+  double mxi, mxj, myi, myj, bxi, bxj, byi, byj, bx, by;
+  double sx, sy, d, sx1, sy1, sx2, sy2;
+  
+  mxi = graph[0].axis[0].dfx / (object[0].x1 - object[0].x0);
+  mxj = graph[0].axis[1].dfx / (object[0].y1 - object[0].y0);
+  myi = graph[0].axis[0].dfy / (object[0].x1 - object[0].x0);
+  myj = graph[0].axis[1].dfy / (object[0].y1 - object[0].y0);
+  
+  bxi  =  graph[0].axis[0].fx - object[0].x0*graph[0].axis[0].dfx/(object[0].x1 - object[0].x0);
+  bxj  =  -object[0].y0*graph[0].axis[1].dfx/(object[0].y1 - object[0].y0);
+  byi  =  -object[0].x0*graph[0].axis[0].dfy/(object[0].x1 - object[0].x0);
+  byj  =  graph[0].axis[1].fy - object[0].y0*graph[0].axis[1].dfy/(object[0].y1 - object[0].y0);
+  
+  bx = bxi + bxj;
+  by = byi + byj;
+  
+  /**** points are scaled by object.z ***/
+  if (object[0].size < 0) {
+    d = 0.5 * (graphic->dx + graphic->dy) * 0.01;
+    x = object[0].x; y = object[0].y; z = object[0].z;
+    if (object[0].ptype == 0) {	/* filled box */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    FillRectangle (sx - d*z[i], sy - d*z[i], 2*d*z[i], 2*d*z[i]);
+	  }
+      }
+    }
+    if (object[0].ptype == 1) {	/* open box */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    DrawRectangle (sx - d*z[i], sy - d*z[i], 2*d*z[i], 2*d*z[i]);
+	  }
+      }
+    }
+    if (object[0].ptype == 2) { /* cross */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    DrawLine (sx - d*z[i], sy, sx + d*z[i] + 1, sy);
+	    DrawLine (sx, sy - d*z[i], sx, sy + d*z[i] + 1);
+	  }
+      }
+    }
+    if (object[0].ptype == 3) {	/* x */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    DrawLine (sx + d*z[i] + 1, sy - d*z[i] - 1, sx - d*z[i], sy + d*z[i]);
+	    DrawLine (sx - d*z[i], sy - d*z[i], sx + d*z[i] + 1, sy + d*z[i] + 1);
+	  }
+      }
+    }
+    if (object[0].ptype == 4) {	/* filled triangle */
+      XPoint points[4];
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    points[0].x = sx - d*z[i];  points[0].y = sy + 0.58*d*z[i];  
+	    points[1].x = sx + d*z[i];  points[1].y = sy + 0.58*d*z[i];  
+	    points[2].x = sx;           points[2].y = sy - 1.15*d*z[i];  
+	    points[3].x = sx - d*z[i];  points[3].y = sy + 0.58*d*z[i];  
+	    XFillPolygon (graphic->display, graphic->window, graphic->gc, points, 4, Convex, CoordModeOrigin);
+	  }
+      }
+    }
+    if (object[0].ptype == 5) {	/* open triangle */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    DrawLine (sx - d*z[i], sy + 0.58*d*z[i], sx + d*z[i], sy + 0.58*d*z[i]);
+	    DrawLine (sx + d*z[i], sy + 0.58*d*z[i], sx,          sy - 1.15*d*z[i]);
+	    DrawLine (sx,          sy - 1.15*d*z[i], sx - d*z[i], sy + 0.58*d*z[i]);
+	  }
+      }
+    }
+    if (object[0].ptype == 6) {	/* Y */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    DrawLine (sx, sy, sx - d*z[i], sy + 0.58*d*z[i]);
+	    DrawLine (sx, sy, sx + d*z[i], sy + 0.58*d*z[i]);
+	    DrawLine (sx, sy, sx,          sy - 1.15*d*z[i]);
+	  }
+      }
+    }
+    if (object[0].ptype == 7) {	/* 0 */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    DrawCircle (sx, sy, d*z[i]);
+	  }
+      }
+    }
+    if (object[0].ptype == 100) {	/* connect a pair of points */
+      for (i = 0; i + 1 < object[0].Npts; i+=2) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx1 = x[i]*mxi + y[i]*mxj + bx;
+	sy1 = x[i]*myi + y[i]*myj + by;
+	if (!(finite(x[i+1]) && finite(y[i+1]))) continue;
+	sx2 = x[i+1]*mxi + y[i+1]*mxj + bx;
+	sy2 = x[i+1]*myi + y[i+1]*myj + by;
+	DrawLine (sx1, sy1, sx2, sy2);
+      }
+    }
+  } 
+  /**** points are not scaled by object.z ***/
+  else {
+    d = object[0].size * 0.5 * (graphic->dx + graphic->dy) * 0.003;
+    x = object[0].x; y = object[0].y;
+    if (object[0].ptype == 0) {	/* filled box */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    FillRectangle (sx - d, sy - d, 2*d, 2*d);
+	  }
+      }
+    }
+    if (object[0].ptype == 1) {		/* open box */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+   	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    DrawRectangle (sx - d, sy - d, 2*d, 2*d);
+	  }
+      }
+    }
+    if (object[0].ptype == 2) { /* cross */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    DrawLine (sx - d, sy, sx + d + 1, sy);
+	    DrawLine (sx, sy - d, sx, sy + d + 1);
+	  }
+      }
+    }
+    if (object[0].ptype == 3) {		/* x */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    /* XDrawLine is a little funny, this is needed to fix endpost errors */
+	    DrawLine (sx + d + 1, sy - d - 1, sx - d, sy + d);
+	    DrawLine (sx - d, sy - d, sx + d + 1, sy + d + 1);
+	  }
+      }
+    }
+    if (object[0].ptype == 4) {	/* filled triangle */
+      XPoint points[4];
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    points[0].x = sx - d;  points[0].y = sy + 0.58*d;  
+	    points[1].x = sx + d;  points[1].y = sy + 0.58*d;  
+	    points[2].x = sx;      points[2].y = sy - 1.15*d;  
+	    points[3].x = sx - d;  points[3].y = sy + 0.58*d;  
+	    XFillPolygon (graphic->display, graphic->window, graphic->gc, points, 4, Convex, CoordModeOrigin);
+	  }
+      }
+    }
+    if (object[0].ptype == 5) {	/* open triangle */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    DrawLine (sx - d, sy + 0.58*d, sx + d, sy + 0.58*d);
+	    DrawLine (sx + d, sy + 0.58*d, sx,     sy - 1.15*d);
+	    DrawLine (sx,     sy - 1.15*d, sx - d, sy + 0.58*d);
+	  }
+      }
+    }
+    if (object[0].ptype == 6) {	/* Y */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    DrawLine (sx, sy, sx - d, sy + 0.58*d);
+	    DrawLine (sx, sy, sx + d, sy + 0.58*d);
+	    DrawLine (sx, sy, sx,     sy - 1.15*d);
+	  }
+      }
+    }
+    if (object[0].ptype == 7) {	/* 0 */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    DrawCircle (sx, sy, d);
+	  }
+      }
+    }
+    if (object[0].ptype == 100) {	
+      for (i = 0; i + 1 < object[0].Npts; i+=2) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx1 = x[i]*mxi + y[i]*mxj + bx;
+	sy1 = x[i]*myi + y[i]*myj + by;
+	sx2 = x[i+1]*mxi + y[i+1]*mxj + bx;
+	sy2 = x[i+1]*myi + y[i+1]*myj + by;
+	DrawLine (sx1, sy1, sx2, sy2);
+      }
+    }
+  }
+}
+    
+/******/
+void DrawXErrors (KapaGraphWidget *graph, Gobjects *object) {
+  
+  int i, bar;
+  float *x, *y, *dxm, *dxp;
+  double mxi, mxj, myi, myj, bxi, bxj, byi, byj, bx, by;
+  double sx0, sy0, sx1, sy1, sz, sx10, sx11;
+
+  mxi = graph[0].axis[0].dfx / (object[0].x1 - object[0].x0);
+  mxj = graph[0].axis[1].dfx / (object[0].y1 - object[0].y0);
+  myi = graph[0].axis[0].dfy / (object[0].x1 - object[0].x0);
+  myj = graph[0].axis[1].dfy / (object[0].y1 - object[0].y0);
+  
+  bxi  =  graph[0].axis[0].fx - object[0].x0*graph[0].axis[0].dfx/(object[0].x1 - object[0].x0);
+  bxj  =  -object[0].y0*graph[0].axis[1].dfx/(object[0].y1 - object[0].y0);
+  byi  =  -object[0].x0*graph[0].axis[0].dfy/(object[0].x1 - object[0].x0);
+  byj  =  graph[0].axis[1].fy - object[0].y0*graph[0].axis[1].dfy/(object[0].y1 - object[0].y0);
+  
+  bx = bxi + bxj;
+  by = byi + byj;
+  
+  x = object[0].x; y = object[0].y; dxp = object[0].dxp; dxm = object[0].dxm; 
+  bar = object[0].ebar; sz = object[0].size*graph[0].axis[1].dfy*0.03;
+  
+  for (i = 0; i < object[0].Npts; i++) {
+    if (!(finite(x[i]) && finite(y[i]) && finite(dxp[i]))) continue;
+    sx0 = x[i]*mxi + y[i]*mxj + bx;
+    sy0 = x[i]*myi + y[i]*myj + by;
+    sx1 = (x[i] + dxp[i])*mxi + y[i]*mxj + bx;
+    sy1 = (x[i] + dxp[i])*myi + y[i]*myj + by;
+    if (((sx0 > graph[0].axis[0].fx) && (sx0 < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	 (sy0 < graph[0].axis[1].fy) && (sy0 > graph[0].axis[1].fy + graph[0].axis[1].dfy)) ||
+	((sx1 > graph[0].axis[0].fx) && (sx1 < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	 (sy1 < graph[0].axis[1].fy) && (sy1 > graph[0].axis[1].fy + graph[0].axis[1].dfy))) 
+      {
+	DrawLine (sx0, sy0, sx1, sy1);
+	if (bar) {
+	  sx10 = sy1 - sz;
+	  sx11 = sy1 + sz;
+	  DrawLine (sx1, sx10, sx1, sx11);
+	}
+      }
+    if (!(finite(x[i]) && finite(y[i]) && finite(dxm[i]))) continue;
+    sx0 = x[i]*mxi + y[i]*mxj + bx;
+    sy0 = x[i]*myi + y[i]*myj + by;
+    sx1 = (x[i] - dxm[i])*mxi + y[i]*mxj + bx;
+    sy1 = (x[i] - dxm[i])*myi + y[i]*myj + by;
+    if (((sx0 > graph[0].axis[0].fx) && (sx0 < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	 (sy0 < graph[0].axis[1].fy) && (sy0 > graph[0].axis[1].fy + graph[0].axis[1].dfy)) ||
+	((sx1 > graph[0].axis[0].fx) && (sx1 < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	 (sy1 < graph[0].axis[1].fy) && (sy1 > graph[0].axis[1].fy + graph[0].axis[1].dfy)))
+      {
+	DrawLine (sx0, sy0, sx1, sy1);
+	if (bar) {
+	  sx10 = sy1 - sz;
+	  sx11 = sy1 + sz;
+	  DrawLine (sx1, sx10, sx1, sx11);
+	}
+      }
+  }
+}
+    
+/******/
+void DrawYErrors (KapaGraphWidget *graph, Gobjects *object) {
+
+  int i, bar;
+  float *x, *y, *dym, *dyp;
+  double mxi, mxj, myi, myj, bxi, bxj, byi, byj, bx, by;
+  double sx0, sy0, sx1, sy1, sz, sx10, sx11;
+
+  mxi = graph[0].axis[0].dfx / (object[0].x1 - object[0].x0);
+  mxj = graph[0].axis[1].dfx / (object[0].y1 - object[0].y0);
+  myi = graph[0].axis[0].dfy / (object[0].x1 - object[0].x0);
+  myj = graph[0].axis[1].dfy / (object[0].y1 - object[0].y0);
+  
+  bxi  =  graph[0].axis[0].fx - object[0].x0*graph[0].axis[0].dfx/(object[0].x1 - object[0].x0);
+  bxj  =  -object[0].y0*graph[0].axis[1].dfx/(object[0].y1 - object[0].y0);
+  byi  =  -object[0].x0*graph[0].axis[0].dfy/(object[0].x1 - object[0].x0);
+  byj  =  graph[0].axis[1].fy - object[0].y0*graph[0].axis[1].dfy/(object[0].y1 - object[0].y0);
+  
+  bx = bxi + bxj;
+  by = byi + byj;
+  
+  x = object[0].x; y = object[0].y; dyp = object[0].dyp; dym = object[0].dym; 
+  bar = object[0].ebar; sz = object[0].size*graph[0].axis[0].dfx*0.03;
+  
+  for (i = 0; i < object[0].Npts; i++) {
+    if (!(finite(x[i]) && finite(y[i]) && finite(dyp[i]))) continue;
+    sx0 = x[i]*mxi + y[i]*mxj + bx;
+    sy0 = x[i]*myi + y[i]*myj + by;
+    sx1 = sx0 + dyp[i]*mxj;
+    sy1 = sy0 + dyp[i]*myj;
+    if (((sx0 > graph[0].axis[0].fx) && (sx0 < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	 (sy0 < graph[0].axis[1].fy) && (sy0 > graph[0].axis[1].fy + graph[0].axis[1].dfy)) ||
+	((sx1 > graph[0].axis[0].fx) && (sx1 < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	 (sy1 < graph[0].axis[1].fy) && (sy1 > graph[0].axis[1].fy + graph[0].axis[1].dfy)))
+      {
+	DrawLine (sx0, sy0, sx1, sy1);
+	if (bar) {
+	  sx10 = sx1 - sz;
+	  sx11 = sx1 + sz;
+	  DrawLine (sx10, sy1, sx11, sy1);
+	}
+      }
+    if (!(finite(x[i]) && finite(y[i]) && finite(dym[i]))) continue;
+    sx0 = x[i]*mxi + y[i]*mxj + bx;
+    sy0 = x[i]*myi + y[i]*myj + by;
+    sx1 = x[i]*mxi + (y[i] - dym[i])*mxj + bx;
+    sy1 = x[i]*myi + (y[i] - dym[i])*myj + by;
+    if (((sx0 > graph[0].axis[0].fx) && (sx0 < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	 (sy0 < graph[0].axis[1].fy) && (sy0 > graph[0].axis[1].fy + graph[0].axis[1].dfy)) ||
+	((sx1 > graph[0].axis[0].fx) && (sx1 < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	 (sy1 < graph[0].axis[1].fy) && (sy1 > graph[0].axis[1].fy + graph[0].axis[1].dfy)))
+      {
+	DrawLine (sx0, sy0, sx1, sy1);
+	if (bar) {
+	  sx10 = sx1 - sz;
+	  sx11 = sx1 + sz;
+	  DrawLine (sx10, sy1, sx11, sy1);
+	}
+      }
+  }
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/DrawTextlines.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/DrawTextlines.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/DrawTextlines.c	(revision 16062)
@@ -0,0 +1,39 @@
+# include "Ximage.h"
+  
+void DrawTextlines (KapaGraphWidget *graph) {
+  
+  int i, x, y, size;
+  double angle;
+  char *fontname;
+  Graphic *graphic;
+
+  graphic = GetGraphic();
+
+  fontname = GetRotFont (&size);
+  XSetForeground (graphic->display, graphic->gc, graphic->fore);
+  DrawRotTextInit (graphic->display, graphic->window, graphic->gc, graphic->fore, graphic->back);
+
+  for (i = 0; i < graph[0].Ntextline; i++) {
+    if (strcmp (graph[0].textline[i].text, "")) {
+      angle = graph[0].textline[i].angle;
+      x = graph[0].textline[i].x;
+      y = graph[0].textline[i].y;
+      SetRotFont (graph[0].textline[i].font, graph[0].textline[i].size);
+      DrawRotText (x, y, graph[0].textline[i].text, 5, angle);
+    }
+  }
+  SetRotFont (fontname, size);
+}
+
+  /* pos values
+            
+ 4____2___5 
+  |       | 
+  |       | 
+ 1|   8   |3
+  |       |
+  |       |
+  ---------
+  6   0   7
+
+  */
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/EraseCurrentPlot.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/EraseCurrentPlot.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/EraseCurrentPlot.c	(revision 16062)
@@ -0,0 +1,20 @@
+# include "Ximage.h"
+
+// erase just the current plot
+int EraseCurrentPlot () {
+  
+  Graphic *graphic;
+  Section *section;
+
+  graphic = GetGraphic();
+
+  section = GetActiveSection();
+  if (section->graph == NULL) return (TRUE);
+
+  EraseGraph (section->graph);
+  
+  if (USE_XWINDOW) XClearWindow (graphic->display, graphic->window);
+  Refresh (1);
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/EraseImage.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/EraseImage.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/EraseImage.c	(revision 16062)
@@ -0,0 +1,19 @@
+# include "Ximage.h"
+
+int EraseImage () {
+
+  Graphic *graphic;
+  Section *section;
+  KapaImageWidget *image;
+
+  graphic = GetGraphic();
+  section = GetActiveSection();
+  image = section->image;
+  if (image == NULL) return (TRUE);
+
+  FreeImage (image);
+  section->image = NULL;
+
+  if (USE_XWINDOW) Refresh ();
+  return (TRUE);
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/EraseOverlay.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/EraseOverlay.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/EraseOverlay.c	(revision 16062)
@@ -0,0 +1,33 @@
+# include "Ximage.h"
+
+int EraseOverlay (int sock) {
+
+  int i, N;
+  Graphic *graphic;
+  Section *section;
+  KapaImageWidget *image;
+
+  graphic = GetGraphic();
+  section = GetActiveSection();
+  image = section->image;
+  if (image == NULL) return (TRUE);
+
+  KiiScanCommand (sock, 16, "%*s %d", &N);
+
+  if (N > NOVERLAYS) {
+    REALLOCATE (image[0].tickmarks.objects, KiiOverlay, 1);
+    image[0].tickmarks.Nobjects = 0;
+  } else {
+    for (i = 0; i < image[0].overlay[N].Nobjects; i++) {
+      if (image[0].overlay[N].objects[i].type == KII_OVERLAY_TEXT) {
+	free (image[0].overlay[N].objects[i].text);
+      }
+    }
+    REALLOCATE (image[0].overlay[N].objects, KiiOverlay, 1);
+    image[0].overlay[N].Nobjects = 0;
+    image[0].overlay[N].active = FALSE;
+  }
+
+  if (USE_XWINDOW) Refresh ();
+  return (TRUE);
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/ErasePlots.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/ErasePlots.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/ErasePlots.c	(revision 16062)
@@ -0,0 +1,23 @@
+# include "Ximage.h"
+
+// erase all plots, keep the sections
+int ErasePlots () {
+  
+  int i, Nsection;
+  Graphic *graphic;
+  Section *section;
+
+  graphic = GetGraphic();
+  
+  // reset the sizes for all sections
+  Nsection = GetNumberOfSections ();
+  for (i = 0; i < Nsection; i++) {
+      section = GetSectionByNumber (i);
+      EraseGraph (section->graph);
+  }
+
+  if (USE_XWINDOW) XClearWindow (graphic->display, graphic->window);
+  Refresh (1);
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/EraseSections.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/EraseSections.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/EraseSections.c	(revision 16062)
@@ -0,0 +1,16 @@
+# include "Ximage.h"
+
+int EraseSections () {
+  
+  Graphic *graphic;
+
+  graphic = GetGraphic();
+  
+  FreeSections ();
+  AddSection ("default", 0.0, 0.0, 1.0, 1.0);
+
+  if (USE_XWINDOW) XClearWindow (graphic->display, graphic->window);
+  Refresh (1);
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/EventLoop.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/EventLoop.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/EventLoop.c	(revision 16062)
@@ -0,0 +1,141 @@
+# include "Ximage.h"
+
+/* list events being selected below, all other masks are ignored */ 
+# define IgnoreMask (long) (~(StructureNotifyMask | SubstructureNotifyMask | ExposureMask | KeyPressMask | ButtonPressMask | PointerMotionMask))
+
+int LastEvent (Display *display, int type, XEvent *event) {
+
+  int found;
+
+  found = FALSE;
+  while (XCheckTypedEvent (display, type, event)) {
+    found = TRUE;
+  }
+  return (found);
+}
+
+int EventLoop () {
+  
+  int      status;
+  XEvent   event;
+  Display *display;
+  Graphic *graphic;
+
+  graphic = GetGraphic();
+  display = graphic->display;
+  
+  if (USE_XWINDOW) Refresh (1);
+
+  status = TRUE;
+  while (status) {
+    
+    if (!CheckPipe ()) return (FALSE);
+    
+    if (!USE_XWINDOW) {
+      usleep (50000);
+      continue;
+    }
+
+    if (XEventsQueued (display, QueuedAfterFlush) < 1) {
+      /* fprintf (stderr, "."); */
+      usleep (50000);
+      continue;
+    }
+
+    /* grab the last entry for these events */
+    if (LastEvent (display, ConfigureNotify, &event)) Reconfig (&event);
+    if (LastEvent (display, CirculateNotify, &event)) Reconfig (&event);
+    if (LastEvent (display, Expose,          &event)) Refresh (1);
+    if (LastEvent (display, MappingNotify,   &event)) XRefreshKeyboardMapping ((XMappingEvent *) &event);
+    if (LastEvent (display, MotionNotify,    &event)) UpdatePointer (graphic, (XMotionEvent *) &event);
+    if (LastEvent (display, ButtonPress,     &event)) InterpretPresses (graphic, (XButtonEvent *) &event);
+    if (LastEvent (display, KeyPress,        &event)) InterpretKeys (graphic, (XKeyEvent *) &event);
+
+    /* drop and ignore the following StructureNotifyMask events */
+    LastEvent (display, GravityNotify, &event);
+    LastEvent (display, ReparentNotify, &event);
+    LastEvent (display, MapNotify, &event);
+    LastEvent (display, UnmapNotify, &event);
+
+    /* remove those events we will ignore */
+    while (XCheckMaskEvent (display, IgnoreMask, &event)) continue;
+
+    /* events to remove which have no mask component */
+    while (XCheckTypedEvent (display, MappingNotify, &event)) continue;
+    while (XCheckTypedEvent (display, ClientMessage, &event)) continue;
+    while (XCheckTypedEvent (display, SelectionClear, &event)) continue;
+    while (XCheckTypedEvent (display, SelectionNotify, &event)) continue;
+    while (XCheckTypedEvent (display, SelectionRequest, &event)) continue;
+  }
+  return (status);
+}
+
+# if (0)
+
+/* all masks from X.h for reference: */
+
+#define NoEventMask                     0L
+#define KeyPressMask                    (1L<<0)
+#define KeyReleaseMask                  (1L<<1)
+#define ButtonPressMask                 (1L<<2)
+#define ButtonReleaseMask               (1L<<3)
+#define EnterWindowMask                 (1L<<4)
+#define LeaveWindowMask                 (1L<<5)
+#define PointerMotionMask               (1L<<6)
+#define PointerMotionHintMask           (1L<<7)
+#define Button1MotionMask               (1L<<8)
+#define Button2MotionMask               (1L<<9)
+#define Button3MotionMask               (1L<<10)
+#define Button4MotionMask               (1L<<11)
+#define Button5MotionMask               (1L<<12)
+#define ButtonMotionMask                (1L<<13)
+#define KeymapStateMask                 (1L<<14)
+#define ExposureMask                    (1L<<15)
+#define VisibilityChangeMask            (1L<<16)
+#define StructureNotifyMask             (1L<<17)
+#define ResizeRedirectMask              (1L<<18)
+#define SubstructureNotifyMask          (1L<<19)
+#define SubstructureRedirectMask        (1L<<20)
+#define FocusChangeMask                 (1L<<21)
+#define PropertyChangeMask              (1L<<22)
+#define ColormapChangeMask              (1L<<23)
+#define OwnerGrabButtonMask             (1L<<24)
+
+/* all events from X.h for reference: */
+
+#define KeyPress                2
+#define KeyRelease              3
+#define ButtonPress             4
+#define ButtonRelease           5
+#define MotionNotify            6
+#define EnterNotify             7
+#define LeaveNotify             8
+#define FocusIn                 9
+#define FocusOut                10
+#define KeymapNotify            11
+#define Expose                  12
+#define GraphicsExpose          13
+#define NoExpose                14
+#define VisibilityNotify        15
+#define CreateNotify            16
+#define DestroyNotify           17
+#define UnmapNotify             18
+#define MapNotify               19
+#define MapRequest              20
+#define ReparentNotify          21
+#define ConfigureNotify         22
+#define ConfigureRequest        23
+#define GravityNotify           24
+#define ResizeRequest           25
+#define CirculateNotify         26
+#define CirculateRequest        27
+#define PropertyNotify          28
+#define SelectionClear          29
+#define SelectionRequest        30
+#define SelectionNotify         31
+#define ColormapNotify          32
+#define ClientMessage           33
+#define MappingNotify           34
+#define LASTEvent               35      /* must be bigger than any event # */
+
+# endif
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/FlushDisplay.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/FlushDisplay.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/FlushDisplay.c	(revision 16062)
@@ -0,0 +1,37 @@
+# include "Ximage.h"
+
+static struct timeval reftime; 
+static char reftimeset = FALSE;
+# define DTIME(A,B) ((A.tv_sec - B.tv_sec) + 1e-6*(A.tv_usec - B.tv_usec))
+
+void FlushDisplay () {
+
+  struct timeval now;
+  int flush;
+  double dtime;
+  Graphic *graphic;
+
+  graphic = GetGraphic();
+
+  if (!USE_XWINDOW) return;
+
+  flush = FALSE;
+  if (!reftimeset) {
+    flush = TRUE;
+    gettimeofday (&reftime, NULL);
+  } 
+
+  gettimeofday (&now, NULL);
+  dtime = DTIME (now, reftime);
+
+  if (dtime > 0.1) {
+    flush = TRUE;
+  }
+
+  if (flush) {
+    XFlush (graphic->display);
+    reftime = now;
+  }
+
+}
+
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/GetColor.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/GetColor.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/GetColor.c	(revision 16062)
@@ -0,0 +1,16 @@
+# include "Ximage.h"
+
+/************** GetColor *************/
+unsigned long GetColor (Display *display, char *name, Colormap colormap, unsigned long default_color) {
+
+  int status;
+  XColor rgbcolor, hardwarecolor;
+
+  status = XLookupColor (display, colormap, name, &rgbcolor, &hardwarecolor);
+  if (!status) return (default_color);
+
+  status = XAllocColor (display, colormap, &hardwarecolor);
+  if (!status) return (default_color);
+
+  return (hardwarecolor.pixel);
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/GetPixelCount.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/GetPixelCount.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/GetPixelCount.c	(revision 16062)
@@ -0,0 +1,12 @@
+# include "Ximage.h"
+
+int GetPixelCount (int sock) {
+  
+  Graphic *graphic;
+
+  graphic = GetGraphic();
+
+  KiiSendMessage (sock, "NPIX: %8d", graphic->Npixels);
+  
+  return (TRUE);
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/Graphs.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/Graphs.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/Graphs.c	(revision 16062)
@@ -0,0 +1,118 @@
+# include "Ximage.h"
+
+/* initialize graph data */
+KapaGraphWidget *InitGraph () {
+
+  int i;
+  KapaGraphWidget *graph;
+
+  ALLOCATE (graph, KapaGraphWidget, 1);
+
+  /* set up axis positions */
+  for (i = 0; i < 4; i++) {
+    graph[0].axis[i].min = 0.0;
+    graph[0].axis[i].max = 1.0;
+    graph[0].axis[i].isaxis = FALSE;
+    graph[0].axis[i].areticks = FALSE;
+    graph[0].axis[i].islabel = FALSE;
+  }    
+  for (i = 0; i < 8; i++) {
+    strcpy (graph[0].label[i].text, "");
+  }
+
+  graph[0].data.xmin = 0.0;
+  graph[0].data.xmax = 1.0;
+  graph[0].data.ymin = 0.0;
+  graph[0].data.ymax = 1.0;
+
+  graph[0].data.style 	= 2; 		// points
+  graph[0].data.ptype 	= 2;		// + for points
+  graph[0].data.ltype 	= 0;		// solid line
+  graph[0].data.etype 	= 0;		// no error bars
+  graph[0].data.ebar  	= 0;		// no cross bar
+  graph[0].data.color 	= 0;		// black
+  graph[0].data.lweight = 0.5;		// line weight of 0.5
+  graph[0].data.size    = 1.0;		// point size of 1.0
+
+  graph[0].Nobjects = 0;
+  graph[0].Ntextline = 0;
+
+  ALLOCATE (graph[0].objects, Gobjects, 1);  /* allocate so later free will not crash! */
+  ALLOCATE (graph[0].textline, Label, 1);    /* allocate so later free will not crash! */
+
+  graph[0].objects[0].x   = graph[0].objects[0].y   = graph[0].objects[0].z = NULL;
+  graph[0].objects[0].dxm = graph[0].objects[0].dxp = NULL;
+  graph[0].objects[0].dym = graph[0].objects[0].dyp = NULL;
+
+  return (graph);
+}
+
+void DrawGraph (KapaGraphWidget *graph) {
+  if (graph == NULL) return;
+  DrawFrame    (graph);
+  DrawObjects  (graph);
+  DrawLabels   (graph);
+  DrawTextlines(graph);
+}
+
+/* remove objects */
+void EraseGraph (KapaGraphWidget *graph) {
+
+  int i;
+
+  if (graph == NULL) return;
+
+  /* free data objects, then re-alloc those needed */
+  for (i = 0; i < graph[0].Nobjects; i++) {
+    FREE (graph[0].objects[i].x);
+    FREE (graph[0].objects[i].y);
+    FREE (graph[0].objects[i].z);
+    FREE (graph[0].objects[i].dxm);
+    FREE (graph[0].objects[i].dxp);
+    FREE (graph[0].objects[i].dym);
+    FREE (graph[0].objects[i].dyp);
+  }
+    
+  /* reset axes and labels */
+  for (i = 0; i < 4; i++) {
+    graph[0].axis[i].isaxis = FALSE;
+    graph[0].axis[i].islabel = FALSE;
+    graph[0].axis[i].areticks = FALSE;
+  }
+  for (i = 0; i < 8; i++) {
+    strcpy (graph[0].label[i].text, "");
+  }
+    
+  graph[0].Nobjects = 0;
+  graph[0].Ntextline = 0;
+  REALLOCATE (graph[0].objects, Gobjects, 1);
+  REALLOCATE (graph[0].textline, Label, 1);
+
+  graph[0].objects[0].x   = graph[0].objects[0].y   = graph[0].objects[0].z = NULL;
+  graph[0].objects[0].dxm = graph[0].objects[0].dxp = NULL;
+  graph[0].objects[0].dym = graph[0].objects[0].dyp = NULL;
+}
+
+/* remove objects */
+void FreeGraph (KapaGraphWidget *graph) {
+
+  int i;
+
+  if (graph == NULL) return;
+
+  /* free data objects, then re-alloc those needed */
+  for (i = 0; i < graph[0].Nobjects; i++) {
+    FREE (graph[0].objects[i].x);
+    FREE (graph[0].objects[i].y);
+    FREE (graph[0].objects[i].z);
+    FREE (graph[0].objects[i].dxm);
+    FREE (graph[0].objects[i].dxp);
+    FREE (graph[0].objects[i].dym);
+    FREE (graph[0].objects[i].dyp);
+  }
+    
+  FREE (graph[0].objects);
+  FREE (graph[0].textline);
+  free (graph);
+  return;
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/Image.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/Image.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/Image.c	(revision 16062)
@@ -0,0 +1,182 @@
+# include "Ximage.h"
+# include "buttons.h"
+
+int InitImageChannel (KapaImageChannel *channel) {
+
+  /** set up a bunch of default things **/
+  channel->zero = 0;
+  channel->range = 1;
+  channel->start = 0;
+  channel->slope = 1;
+
+  channel->coords.Npolyterms = 0;
+  channel->matrix.size = 0; /* a flag to show there is no data in the matrix */
+  ALLOCATE (channel->matrix.buffer, char, 1);  /* allocate so later free will not crash! */
+
+  return (TRUE);
+}
+
+/* initialization for things not specific to X */
+KapaImageWidget *InitImageWidget () {
+
+  int i;
+  KapaImageWidget *image;
+  Graphic *graphic;
+
+  graphic = GetGraphic ();
+
+  ALLOCATE (image, KapaImageWidget, 1);
+  memset (image, 0, sizeof(KapaImageWidget));
+
+  for (i = 0; i < NCHANNELS; i++) {
+    InitImageChannel (&image[0].channel[i]);
+  }
+  image[0].image = &image[0].channel[0];
+
+  image[0].nPixels = 0;
+  ALLOCATE (image[0].pixmap, unsigned short, 1);  /* allocate so later free will not crash! */
+
+  // XXXX this has been moved to graphic, which may be wrong
+  // image[0].ColorScaleMode = KAPA_SCALE_1D;
+
+  for (i = 0; i < NOVERLAYS; i++) {
+    image[0].overlay[i].Nobjects = 0;
+    ALLOCATE (image[0].overlay[i].objects, KiiOverlay, 1);  /* allocate so later free will not crash! */
+    image[0].overlay[i].active = FALSE;
+    image[0].overlay[i].color = graphic[0].overlay_color[i];
+  }
+
+  image[0].X = 0.0;
+  image[0].Y = 0.0;
+  image[0].expand = 1;
+  image[0].location = 4;
+
+  image[0].MovePointer = TRUE;
+  image[0].DecimalDegrees  = TRUE;
+  ALLOCATE (image[0].picture.data, char, 1);   /* allocate so later free will not crash! */
+  ALLOCATE (image[0].cmapbar.data, char, 1);   /* allocate so later free will not crash! */
+  ALLOCATE (image[0].zoom.data, char, 1);      /* allocate so later free will not crash! */
+
+  InitButtonSize (&image[0].PS_button, PS_width, PS_height, PS_bits);
+  InitButtonFunc (&image[0].PS_button, PSfunction);
+
+  InitButtonSize (&image[0].grey_button, grey_width, grey_height, grey_bits);
+  InitButtonFunc (&image[0].grey_button, greycolors);
+
+  InitButtonSize (&image[0].rainbow_button, rainbow_width, rainbow_height, rainbow_bits);
+  InitButtonFunc (&image[0].rainbow_button, rainbow);
+
+  InitButtonSize (&image[0].heat_button, heat_width, heat_height, heat_bits);
+  InitButtonFunc (&image[0].heat_button, heat);
+
+  InitButtonSize (&image[0].recenter_button, recenter_width, recenter_height, recenter_bits);
+  image[0].recenter_button.function_1 = Recenter;
+  image[0].recenter_button.function_2 = RecenterRescale;
+  image[0].recenter_button.function_3 = Rescale;
+
+  InitButtonSize (&image[0].overlay_button[0], red_width, red_height, red_bits);
+  InitButtonFunc (&image[0].overlay_button[0], Overlay0);
+
+  InitButtonSize (&image[0].overlay_button[1], green_width, green_height, green_bits);
+  InitButtonFunc (&image[0].overlay_button[1], Overlay1);
+
+  InitButtonSize (&image[0].overlay_button[2], blue_width, blue_height, blue_bits);
+  InitButtonFunc (&image[0].overlay_button[2], Overlay2);
+
+  InitButtonSize (&image[0].overlay_button[3], yellow_width, yellow_height, yellow_bits);
+  InitButtonFunc (&image[0].overlay_button[3], Overlay3);
+
+  InitButtonSize (&image[0].hms_button, hms_width, hms_height, hms_bits);
+  InitButtonFunc (&image[0].hms_button, ToggleDEG);
+
+  return (image);
+}
+
+void InitButtonSize (Button *button, int width, int height, char *bitmap) {
+  button->dx = BUTTON_WIDTH;
+  button->dy = BUTTON_HEIGHT;
+  button->width = width;
+  button->height = height;
+  button->bitmap = bitmap;
+}
+
+void InitButtonFunc (Button *button, int (*function)()) {
+  button->function_1 = function;
+  button->function_2 = function;
+  button->function_3 = function;
+}
+
+void DrawImage (KapaImageWidget *image) {
+
+  int i;
+  Graphic *graphic;
+
+  if (image == NULL) return;
+
+  graphic = GetGraphic ();
+
+  XSetForeground (graphic[0].display,  graphic[0].gc, graphic[0].fore);
+  XDrawRectangle (graphic[0].display,  graphic[0].window, graphic[0].gc, 
+		  image[0].picture.x,  image[0].picture.y, 
+		  image[0].picture.dx+1, image[0].picture.dy+1);
+  
+  XPutImage (graphic[0].display, graphic[0].window, graphic[0].gc,
+	     image[0].picture.pix, 0, 0, 
+	     image[0].picture.x + 1, image[0].picture.y + 1, 
+	     image[0].picture.dx, image[0].picture.dy);
+
+  for (i = 0; i < NOVERLAYS; i++) {
+    if (image[0].overlay[i].active) {
+      PaintOverlay (graphic, image, i);
+    }
+  }
+
+  if (image[0].location) {
+    XPutImage (graphic[0].display, graphic[0].window, graphic[0].gc,
+	       image[0].cmapbar.pix, 0, 0, 
+	       image[0].cmapbar.x, image[0].cmapbar.y, 
+	       image[0].cmapbar.dx, image[0].cmapbar.dy);
+
+    CrossHairs (graphic, image);
+  
+    /* erase everything below zoom box, then draw */
+    /*
+    XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].back);
+    XFillRectangle (graphic[0].display, graphic[0].window, graphic[0].gc, 
+		    image[0].text_x, image[0].text_x, image[0].text_dx, image[0].text_dy); 
+    */    
+    DrawButton (graphic, &image[0].PS_button);
+    DrawButton (graphic, &image[0].recenter_button);
+    DrawButton (graphic, &image[0].grey_button);
+    DrawButton (graphic, &image[0].rainbow_button);
+    DrawButton (graphic, &image[0].heat_button);
+    DrawButton (graphic, &image[0].hms_button);
+
+    for (i = 0; i < NOVERLAYS; i++) {
+      DrawButton (graphic, &image[0].overlay_button[i]);
+    }
+    StatusBox (graphic, image);
+  }
+
+  FlushDisplay (graphic[0].display);
+}
+
+void FreeImage (KapaImageWidget *image) {
+
+  int i;
+
+  if (image == NULL) return;
+
+  for (i = 0; i < NOVERLAYS; i++) {
+    free (image[0].overlay[i].objects);
+  }
+  for (i = 0; i < NCHANNELS; i++) {
+    free (image[0].channel[i].matrix.buffer);
+  }
+  free (image[0].pixmap);
+  free (image[0].picture.data);
+  free (image[0].cmapbar.data);
+  free (image[0].zoom.data);
+
+  free (image);
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/InButton.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/InButton.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/InButton.c	(revision 16062)
@@ -0,0 +1,18 @@
+# include "Ximage.h"
+
+int InButton (XButtonEvent *button_event, Button *button) {
+
+  int answer;
+  int x, y;
+
+  x = button_event[0].x;
+  y = button_event[0].y;
+  
+  answer = ((x >= button[0].x) && (x <= button[0].x + button[0].dx) &&
+	    (y >= button[0].y) && (y <= button[0].y + button[0].dy));
+
+  return (answer);
+
+}
+
+/*** make this a macro? ***/
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/InPicture.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/InPicture.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/InPicture.c	(revision 16062)
@@ -0,0 +1,16 @@
+# include "Ximage.h"
+
+int InPicture (XButtonEvent *button_event, Picture *picture) {
+
+  int answer;
+  int x, y;
+
+  x = button_event[0].x;
+  y = button_event[0].y;
+  
+  answer = ((x >= picture[0].x) && (x <= picture[0].x + picture[0].dx) &&
+	    (y >= picture[0].y) && (y <= picture[0].y + picture[0].dy));
+
+  return (answer);
+
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/InterpretKeys.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/InterpretKeys.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/InterpretKeys.c	(revision 16062)
@@ -0,0 +1,171 @@
+# include "Ximage.h"
+
+int InterpretKeys (Graphic *graphic, XKeyEvent *event) {
+
+  float           *imdata;
+  double 	   X, Y, Z, R, D, offset;
+  int    	   sock, DX, DY, modstate;
+  char   	  *name, string[16];
+  KeySym           keysym;
+  XComposeStatus   composestatus;
+  Section         *section;
+  KapaImageWidget *image;
+  KapaGraphWidget *graph;
+
+  // XXX select the window element which contains the event
+  section = GetActiveSection();
+  image   = section->image;
+  graph   = section->graph;
+
+  XLookupString (event, string, 9, &keysym, &composestatus);
+  modstate = event[0].state;
+
+  // return graph coords by default, image if graph does not exist
+  // XXX allow user to choose graph or image coords
+  if (ACTIVE_CURSOR) {
+
+    sock = GetActiveSocket ();
+    if (sock == -1) goto skip_cursor;
+
+    name = XKeysymToString (keysym);
+
+    // skip the following keys: 
+    if (name == NULL) goto skip_cursor;
+    if (!strcmp (name, "Shift_L")) goto skip_cursor;
+    if (!strcmp (name, "Shift_R")) goto skip_cursor;
+    if (!strcmp (name, "Control_L")) goto skip_cursor;
+    if (!strcmp (name, "Control_R")) goto skip_cursor;
+    if (!strcmp (name, "Alt_L")) goto skip_cursor;
+    if (!strcmp (name, "Alt_R")) goto skip_cursor;
+    if (!strcmp (name, "Super_L")) goto skip_cursor;
+    if (!strcmp (name, "Super_R")) goto skip_cursor;
+    if (!strcmp (name, "Caps_Lock")) goto skip_cursor;
+    if (!strcmp (name, "Pause")) goto skip_cursor;
+    if (!strcmp (name, "Continue")) goto skip_cursor;
+    if (!strcmp (name, "Num_Lock")) goto skip_cursor;
+    if (!strcmp (name, "Scroll_Lock")) goto skip_cursor;
+    if (!strcmp (name, "Print")) goto skip_cursor;
+    if (!strcmp (name, "(null)")) goto skip_cursor;
+
+    Z = -1;
+
+    if (graph) {
+      X = (event[0].x - graph[0].axis[0].fx)*(graph[0].axis[0].max - graph[0].axis[0].min)/graph[0].axis[0].dfx + graph[0].axis[0].min;
+      Y = (event[0].y - graph[0].axis[1].fy)*(graph[0].axis[1].max - graph[0].axis[1].min)/graph[0].axis[1].dfy + graph[0].axis[1].min;
+      XY_to_RD (&R, &D, X, Y, &graph[0].data.coords);
+    } 
+    if (image && !graph) {
+      if (event[0].x < image[0].picture.x) goto skip_cursor;
+      if (event[0].y < image[0].picture.y) goto skip_cursor;
+      if (event[0].x > image[0].picture.x + image[0].picture.dx) goto skip_cursor;
+      if (event[0].y > image[0].picture.y + image[0].picture.dy) goto skip_cursor;
+      Screen_to_Image (&X, &Y, (double)event[0].x, (double)event[0].y, image);
+      XY_to_RD (&R, &D, X, Y, &image[0].image[0].coords);
+
+      DX = image[0].image[0].matrix.Naxis[0];
+      DY = image[0].image[0].matrix.Naxis[1];
+
+      if (X < 0) goto off_image;
+      if (Y < 0) goto off_image;
+      if (X >= DX) goto off_image;
+      if (Y >= DY) goto off_image;
+      imdata = (float *) image[0].image[0].matrix.buffer;
+      Z      = imdata[DX*(int)(Y) + (int)(X)];
+    }
+  off_image:
+    KiiSendMessage (sock, "%12s %12.6f %12.6f %12.6f %12.6f %12.6f", name, X, Y, Z, R, D);
+  }
+
+skip_cursor:
+  if (image == NULL) return (TRUE);
+
+  // offset is in image pixels: 
+  // 0.5 image pixels is 1 screen pixel for expand == +2
+  // 2.0 image pixels is 1 screen pixel for expand == -2
+  if (image[0].expand == 0) image[0].expand = 1;
+  offset = (image[0].expand > 0) ? 1.0 / image[0].expand : -image[0].expand;
+  if (modstate & ControlMask) offset *= 100;
+
+  switch (keysym) {
+
+    case XK_F1:
+      image[0].image = &image[0].channel[0];
+      SetColorScale (graphic, image);
+      Remap (graphic, image);
+      Reorient (graphic, image, image[0].X, image[0].Y, 0);
+      break;
+
+    case XK_F2:
+      image[0].image = &image[0].channel[1];
+      SetColorScale (graphic, image);
+      Remap (graphic, image);
+      Reorient (graphic, image, image[0].X, image[0].Y, 0);
+      break;
+
+    case XK_F3:
+      image[0].image = &image[0].channel[2];
+      SetColorScale (graphic, image);
+      Remap (graphic, image);
+      Reorient (graphic, image, image[0].X, image[0].Y, 0);
+      break;
+
+    case XK_KP_Home:
+    case XK_Home:
+      image[0].expand = 1;
+      Reorient (graphic, image, image[0].X, image[0].Y, 0);
+      break;
+    case XK_KP_End:
+    case XK_End:
+      image[0].expand = 1;
+      Reorient (graphic, image, 0, 0, 0);
+      break;
+    case XK_KP_Enter:
+    case XK_KP_Begin:
+    case XK_Return:
+      Screen_to_Image (&X, &Y, (double)event[0].x, (double)event[0].y, image);
+      X = 0.5*image[0].image[0].matrix.Naxis[0] - X;
+      Y = 0.5*image[0].image[0].matrix.Naxis[1] - Y;
+      Reorient (graphic, image, X, Y, 0);
+      break;
+    case XK_Prior:
+    case XK_KP_Prior:
+      Reorient (graphic, image, image[0].X, image[0].Y, +1);
+      break;
+    case XK_Next:
+    case XK_KP_Next:
+      Reorient (graphic, image, image[0].X, image[0].Y, -1);
+      break;
+    case XK_Up:
+    case XK_KP_Up:
+      Reorient (graphic, image, image[0].X, image[0].Y + offset, 0);
+      break;
+    case XK_Down:
+    case XK_KP_Down:
+      Reorient (graphic, image, image[0].X, image[0].Y - offset, 0);
+      break;
+    case XK_Left:
+    case XK_KP_Left:
+      Reorient (graphic, image, image[0].X + offset, image[0].Y, 0);
+      break;
+    case XK_Right:
+    case XK_KP_Right:
+      Reorient (graphic, image, image[0].X - offset, image[0].Y, 0);
+      break;
+
+    case XK_KP_Add:
+      image[0].image[0].zero += 0.1*image[0].image[0].range;
+      Reorient (graphic, image, image[0].X, image[0].Y, 0);
+      break;
+    case XK_KP_Subtract:
+      image[0].image[0].zero -= 0.1*image[0].image[0].range;
+      Reorient (graphic, image, image[0].X, image[0].Y, 0);
+      break;
+
+    case XK_Tab:
+      image[0].MovePointer = image[0].MovePointer ^ TRUE;
+      if (image[0].MovePointer) UpdatePointer (graphic, (XMotionEvent *)event);
+      break;
+  }
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/InterpretPresses.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/InterpretPresses.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/InterpretPresses.c	(revision 16062)
@@ -0,0 +1,120 @@
+# include "Ximage.h"
+
+int InterpretPresses (Graphic *graphic, XButtonEvent *event) {
+
+  int              sock, DX, DY, status, done, this_button;
+  char             name[16];
+  double           X, Y, Z, R, D;
+  float           *imdata;
+  Button          *button;
+  Section         *section;
+  KapaImageWidget *image;
+  KapaGraphWidget *graph;
+
+  // XXX select the window element which contains the event
+  section = GetActiveSection();
+  image   = section->image;
+  graph   = section->graph;
+
+  // return graph coords by default, image if graph does not exist
+  // XXX allow user to choose graph or image coords
+  if (ACTIVE_CURSOR) {
+    sock = GetActiveSocket ();
+    if (sock == -1) goto skip_cursor;
+
+    sprintf (name, "Button%d", event[0].button);
+    if (graph) {
+      X = (event[0].x - graph[0].axis[0].fx)*(graph[0].axis[0].max - graph[0].axis[0].min)/graph[0].axis[0].dfx + graph[0].axis[0].min;
+      Y = (event[0].y - graph[0].axis[1].fy)*(graph[0].axis[1].max - graph[0].axis[1].min)/graph[0].axis[1].dfy + graph[0].axis[1].min;
+      XY_to_RD (&R, &D, X, Y, &graph[0].data.coords);
+    } 
+    if (image && !graph) {
+      if (event[0].x < image[0].picture.x) goto skip_cursor;
+      if (event[0].y < image[0].picture.y) goto skip_cursor;
+      if (event[0].x > image[0].picture.x + image[0].picture.dx) goto skip_cursor;
+      if (event[0].y > image[0].picture.y + image[0].picture.dy) goto skip_cursor;
+      Screen_to_Image (&X, &Y, (double)event[0].x, (double)event[0].y, image);
+
+      XY_to_RD (&R, &D, X, Y, &image[0].image[0].coords);
+
+      DX = image[0].image[0].matrix.Naxis[0];
+      DY = image[0].image[0].matrix.Naxis[1];
+
+      if (X < 0) goto off_image;
+      if (Y < 0) goto off_image;
+      if (X >= DX) goto off_image;
+      if (Y >= DY) goto off_image;
+      imdata = (float *) image[0].image[0].matrix.buffer;
+      Z      = imdata[DX*(int)(Y) + (int)(X)];
+    }
+  off_image:
+    KiiSendMessage (sock, "%12s %12.6f %12.6f %12.6f %12.6f %12.6f", name, X, Y, Z, R, D);
+  }
+
+skip_cursor:
+  status = TRUE;
+  this_button = event[0].button;
+
+  // XXX add graph buttons here
+  if (image == NULL) return (TRUE);
+  
+  if ((event[0].type == ButtonPress) && InPicture (event, &image[0].picture)) {
+    ReorientOnButton (graphic, image, event);
+  }
+
+  if ((event[0].type == ButtonPress) && InPicture (event, &image[0].cmapbar)) {
+    DragColorbar (graphic, image, event);
+  }
+
+  /* if on an exisiting button, Invert, wait for release, then go (or not) */
+  if ((button = CheckButtons (event, image)) != (Button *) NULL) {
+    InvertButton (graphic, button); 
+    done = FALSE;
+    while (!done) { /* wait for release of this button */
+      XNextEvent (graphic[0].display, (XEvent *) event);
+      if ((event[0].type == ButtonRelease) && (event[0].button == this_button)) {
+	done = TRUE;
+      }
+    }
+    DrawButton (graphic, button);
+    if (InButton (event, button)) {
+      switch (event[0].button) {
+      case 1:
+	status = button[0].function_1(graphic, image);
+	break;
+      case 2:
+	status = button[0].function_2(graphic, image);
+	break;
+      case 3:
+	status = button[0].function_3(graphic, image);
+	break;
+      }
+    } else {
+      return (status);
+    }
+  }
+  return (status);
+}
+
+void ReorientOnButton (Graphic *graphic, KapaImageWidget *image, XButtonEvent *mouse_event) {
+
+  double X, Y;
+
+  Screen_to_Image (&X, &Y, (double)mouse_event[0].x, (double)mouse_event[0].y, image);
+  X = 0.5*image[0].image[0].matrix.Naxis[0] - X;
+  Y = 0.5*image[0].image[0].matrix.Naxis[1] - Y;
+
+  switch (mouse_event[0].button) {
+    case 1:
+      Reorient (graphic, image, X, Y, 0);
+      break;
+    case 2:
+      Reorient (graphic, image, X, Y, -1);
+      break;
+    case 3:
+      Reorient (graphic, image, X, Y, +1);
+      break;
+    default:
+      break;
+  }
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/InvertButton.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/InvertButton.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/InvertButton.c	(revision 16062)
@@ -0,0 +1,19 @@
+# include "Ximage.h"
+
+void InvertButton (Graphic *graphic, Button *button) {
+
+  unsigned long fore, back;
+
+  fore =  graphic[0].fore;
+  back =  graphic[0].back;
+
+  graphic[0].fore = back;
+  graphic[0].back = fore;
+
+  DrawButton (graphic, button);
+  FlushDisplay (graphic[0].display);
+  
+  graphic[0].fore = fore;
+  graphic[0].back = back;
+
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/JPEGit24.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/JPEGit24.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/JPEGit24.c	(revision 16062)
@@ -0,0 +1,235 @@
+# include "Ximage.h"
+# include "jpeglib.h"
+
+# define WHITE_R 255
+# define WHITE_G 255
+# define WHITE_B 255
+
+// XXX this currently writes out the jpeg for just the active image
+int JPEGit24 (int sock) {
+
+  struct jpeg_compress_struct cinfo;
+  struct jpeg_error_mgr jerr;
+  JSAMPROW row_pointer[1];	/* pointer to JSAMPLE row[s] */
+  JSAMPLE *image_buffer;	/* Points to data for current line */
+  JSAMPLE *line_buffer;	        /* Points to data for current line */
+  Section *section;
+  Graphic *graphic;
+  KapaImageWidget *image;
+
+  int ii, i, j;
+  int i_start, i_end, j_start, j_end;
+  int dropback;  /* this is a bit of a kludge... */
+  int dx, dy, DX, DY;
+  int quality;
+  int expand_in, expand_out;
+  double expand, Rx, Ry, X, Y;
+  unsigned char *out_pix;
+  unsigned short *in_pix, *in_pix_ref;
+  unsigned char *pixel1, *pixel2, *pixel3;
+  char filename[1024];
+  FILE *f;
+
+  /* expect a line telling the number of bytes and a filename */
+  KiiScanMessage (sock, "%s", filename);
+
+  graphic = GetGraphic();
+  section = GetActiveSection();
+  image   = section->image;
+  if (image == NULL) return (TRUE);
+
+  /***** JPEG init calls */
+  cinfo.err = jpeg_std_error (&jerr);
+  jpeg_create_compress (&cinfo);
+
+  f = fopen (filename, "w");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "Kii: failed to open %s for output\n", filename);
+    return (TRUE);
+  }
+  jpeg_stdio_dest(&cinfo, f);
+  
+  quality = 75;
+  cinfo.image_width = image[0].picture.dx; 	/* image width and height, in pixels */
+  cinfo.image_height = image[0].picture.dy;
+# ifdef GREYSCALE
+  cinfo.input_components = 1;		        /* # of color components per pixel */
+  cinfo.in_color_space = JCS_GRAYSCALE; 	/* colorspace of input image */
+# else 
+  cinfo.input_components = 3;		        
+  cinfo.in_color_space = JCS_RGB; 	
+# endif
+  jpeg_set_defaults (&cinfo);
+  jpeg_set_quality (&cinfo, quality, TRUE       /* limit to baseline-JPEG values */);
+  jpeg_start_compress (&cinfo, TRUE);
+
+  ALLOCATE (pixel1, unsigned char, graphic[0].Npixels);
+  ALLOCATE (pixel2, unsigned char, graphic[0].Npixels);
+  ALLOCATE (pixel3, unsigned char, graphic[0].Npixels);
+
+  /** cmap[i].pixel must be defined even if X is not used **/
+  for (i = 0; i < graphic[0].Npixels; i++) { /* set up pixel array */
+    pixel1[i] = graphic[0].cmap[i].red >> 8;
+    pixel2[i] = graphic[0].cmap[i].green >> 8;
+    pixel3[i] = graphic[0].cmap[i].blue >> 8;
+  }
+
+  expand = expand_in = expand_out = 1.0;
+  if (image[0].expand == 0) /* set up expansions */
+    image[0].expand = 1;
+  if (image[0].expand > 0) {
+    expand = 1 / (1.0*image[0].expand);
+    expand_out = image[0].expand;
+    expand_in  = 1;
+  }
+  if (image[0].expand < 0) {
+    expand = fabs((double)image[0].expand);
+    expand_out = 1;
+    expand_in  = -image[0].expand;
+  }
+
+  dx = image[0].picture.dx;
+  dy = image[0].picture.dy;
+  DX = image[0].image[0].matrix.Naxis[0];
+  DY = image[0].image[0].matrix.Naxis[1];
+
+  /* X,Y are the image coordinates of the first image pixel */
+  X = MAX(0.5*(DX - dx*expand) - image[0].X, 0);
+  if ((int)X != X) 
+    X = (int) X + 1;
+  else 
+    X = (int) X;
+  Y = MAX(0.5*(DY - dy*expand) - image[0].Y, 0);
+  if ((int)Y != Y) 
+    Y = (int) Y + 1;
+  else 
+    Y = (int) Y;
+
+  /* Rx,Ry are the screen coordinates of the first image pixel */
+  Rx = (X + image[0].X - 0.5*DX)/expand + 0.5*dx;
+  Ry = (Y + image[0].Y - 0.5*DY)/expand + 0.5*dy;
+
+  i_start = MIN (MAX (Rx, 0), dx - expand_out + 1);
+  j_start = MIN (MAX (Ry, 0), dy - expand_out + 1);
+  
+  if (image[0].expand > 0) {
+    i_end = MAX (MIN (i_start + ((int)(expand*(dx-i_start)))/expand, expand_out*(DX-X) + Rx), 0);
+    j_end = MAX (MIN (j_start + ((int)(expand*(dy-j_start)))/expand, expand_out*(DY-Y) + Ry), 0);
+  } else {
+    i_end = MAX (MIN (dx, (DX-X)/expand + Rx), 0);
+    j_end = MAX (MIN (dy, (DY-Y)/expand + Ry), 0);
+  }    
+
+  dropback = expand_out - (i_end - i_start) % expand_out;
+  if ((i_end - i_start) % expand_out == 0) dropback = 0;
+
+  /* output line buffer */
+  ALLOCATE (image_buffer, JSAMPLE, 3*dx*dy);
+  ALLOCATE (line_buffer, JSAMPLE, 3*dx);
+
+  in_pix_ref  = &image[0].pixmap[DX*(int)MAX(Y,0) + (int)MAX(X,0)];
+
+  /********** below we do the mapping from buffer pixels (in) to picture pixels (out) **********/
+
+  /**** fill in bottom area ****/
+  out_pix = line_buffer;
+  for (i = 0; i < dx; i++, out_pix+=3) {
+    out_pix[0] = WHITE_R;
+    out_pix[1] = WHITE_G;
+    out_pix[2] = WHITE_B;
+  }
+  for (j = 0; j < j_start; j++) {
+    memcpy (&image_buffer[j*3*dx], line_buffer, 3*dx);
+  }
+  
+  /*** fill in the image data region ***/
+  for (j = j_start; j < j_end; j+= expand_out, in_pix_ref += expand_in*DX) {
+    
+    /* create one output image line */
+    in_pix = in_pix_ref;
+    out_pix = line_buffer;
+
+    /**** fill in area to the left of the picture ****/
+    for (i = 0; i < i_start; i++, out_pix+=3) {
+      out_pix[0] = WHITE_R;
+      out_pix[1] = WHITE_G;
+      out_pix[2] = WHITE_B;
+    }
+    
+    /*** fill in the picture region ***/
+    for (i = i_start; i < i_end; i+=expand_out, in_pix+=expand_in) {
+      for (ii = 0; ii < expand_out; ii++, out_pix+=3) {
+	out_pix[0] = pixel1[*in_pix];
+	out_pix[1] = pixel2[*in_pix];
+	out_pix[2] = pixel3[*in_pix];
+      }
+    }
+    
+    /**** fill in area to the right of the picture ****/
+    for (i = i_end; i < dx; i++, out_pix+=3) {
+      out_pix[0] = WHITE_R;
+      out_pix[1] = WHITE_G;
+      out_pix[2] = WHITE_B;
+    }
+
+    /* write out the image line expand_out times */
+    for (i = 0; i < expand_out; i++) {
+      memcpy (&image_buffer[(j + i)*3*dx], line_buffer, 3*dx);
+    }
+  }
+
+  /**** fill in top area ****/
+  out_pix = line_buffer;
+  for (i = 0; i < dx; i++, out_pix+=3) { 
+    out_pix[0] = WHITE_R;
+    out_pix[1] = WHITE_G;
+    out_pix[2] = WHITE_B;
+  }
+  for (j = j_end; j < dy; j++) {
+    memcpy (&image_buffer[j*3*dx], line_buffer, 3*dx);
+  }
+
+
+  /* I need to write the overlay objects on the jpeg image.
+     if i can write / overwrite data in jpeg buffer, then do it here,
+     otherwise i need to create a temporary image buffer, then write the 
+     scanlines to that buffer */
+
+  {
+    int Npalette;
+    png_color *palette;
+    bDrawColor white, color;
+    bDrawBuffer *buffer;
+
+    palette = KapaPNGPalette (&Npalette);
+
+    buffer = bDrawBufferCreate (dx, dy);
+    bDrawSetBuffer (buffer);
+    for (i = 0; i < NOVERLAYS; i++) {
+      if (image[i].overlay[i].active) bDrawOverlay (image, i);
+    }
+
+    white = KapaColorByName ("white");
+    for (j = 0; j < dy; j++) {
+      for (i = 0; i < dx; i++) {
+	color = buffer[0].pixels[j][i];
+	if (color == white) continue;
+	image_buffer[j*3*dx + 3*i + 0] = palette[color].red;
+	image_buffer[j*3*dx + 3*i + 1] = palette[color].green;
+	image_buffer[j*3*dx + 3*i + 2] = palette[color].blue;
+      }
+    }
+    bDrawBufferFree (buffer);
+  }
+
+  for (i = 0; i < dy; i++) {
+    row_pointer[0] = &image_buffer[i*3*dx];
+    (void) jpeg_write_scanlines (&cinfo, row_pointer, 1);
+  }
+
+  jpeg_finish_compress (&cinfo);
+  fclose (f);
+  jpeg_destroy_compress (&cinfo);
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/Layout.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/Layout.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/Layout.c	(revision 16062)
@@ -0,0 +1,46 @@
+# include "Ximage.h"
+static char default_colormap[] = "grayscale";
+
+void InitLayout (int argc, char **argv) {
+
+  int N;
+  Section *section;
+  char *namedSocket = NULL;
+  
+  namedSocket = NULL;
+  if ((N = get_argument (argc, argv, "-socket"))) { 
+    remove_argument (N, &argc, argv);
+    namedSocket = argv[N];
+    remove_argument (N, &argc, argv);
+  }
+
+  // if we specify a named socket, wait until we are contacted
+  // otherwise, open an INET sock and check occasionally for requests
+  InitPipe (namedSocket);
+
+  ACTIVE_CURSOR = FALSE;
+
+  /* get the display colors */
+  if (USE_XWINDOW) {
+    MakeColormap (argc, argv);
+  } else {
+    char *colormap;
+    colormap = default_colormap;
+    if ((N = get_argument (argc, argv, "-cm"))) {
+      remove_argument (N, &argc, argv);
+      colormap = argv[N];
+    }
+    SetColormap (colormap);
+  }
+
+  /* move this out of here... */
+  if (argc != 1) {
+    fprintf (stderr, "USAGE: kapa\n");
+    exit (0);
+  }
+
+  InitRotFonts ();
+
+  /* create basic section, empty of image or graph */
+  section = AddSection ("default", 0.0, 0.0, 1.0, 1.0);
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/LoadFont.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/LoadFont.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/LoadFont.c	(revision 16062)
@@ -0,0 +1,46 @@
+# include "Ximage.h"
+
+/************** LoadFont *************/
+void LoadFont (Graphic *graphic, int *argc, char **argv, char *default_name) {
+
+  int N;
+  char *name;
+
+  name = XGetDefault (graphic->display, argv[0], "Font");
+  if (name == NULL) name = default_name;
+
+  /* check for command-line options */
+  if ((N = get_argument (*argc, argv, "-font"))) {
+    if (*argc <= N + 1) {
+      fprintf (stderr, "error: usage is -font fontname\n");
+      exit (0);
+    }
+    remove_argument(N, argc, argv);
+    name = argv[N];
+    remove_argument(N, argc, argv);
+  }   
+  if ((N = get_argument (*argc, argv, "-fn"))) {
+    if (*argc <= N + 1) {
+      fprintf (stderr, "error: usage is -fn fontname\n");
+      exit (0);
+    }
+    remove_argument(N, argc, argv);
+    name = argv[N];
+    remove_argument(N, argc, argv);
+  } 
+
+  graphic->font = XLoadQueryFont (graphic->display, name);
+  if ((graphic->font == NULL) && (name != default_name)) {
+    fprintf (stderr, "Could not load requested font %s, trying %s\n", name, default_name);
+    graphic->font = XLoadQueryFont (graphic->display, default_name);
+  }
+  if (graphic->font == NULL) {
+    fprintf (stderr, "Could not load font %s, using %s\n", default_name, "fixed");
+    graphic->font = XLoadQueryFont (graphic->display, "fixed");
+  }
+  if (graphic->font == NULL) {
+    QuitX (graphic->display, "Error: could not load font");
+  }
+
+  XSetFont (graphic->display, graphic->gc, graphic->font[0].fid);
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/LoadFrame.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/LoadFrame.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/LoadFrame.c	(revision 16062)
@@ -0,0 +1,84 @@
+# include "Ximage.h"
+
+int LoadFrame (int sock) {
+  
+  int i;
+  char Axis[16], Labels[16], Ticks[16];
+  Section *section;
+  KapaGraphWidget *graph;
+
+  section = GetActiveSection();
+  if (section->graph == NULL) {
+    section->graph = InitGraph ();
+    SetSectionSizes (section);
+  }
+  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);
+
+  graph[0].axis[3].min = graph[0].axis[1].min;
+  graph[0].axis[3].max = graph[0].axis[1].max;
+  graph[0].axis[2].min = graph[0].axis[0].min;
+  graph[0].axis[2].max = graph[0].axis[0].max;
+  
+  KiiScanMessage (sock, "%s %s %s", Axis, Labels, Ticks);
+
+  for (i = 0; i < 4; i++) {
+    switch (Axis[i]) {
+    case '0':
+      graph[0].axis[i].isaxis = FALSE;
+      break;
+    case '1':
+      graph[0].axis[i].isaxis = TRUE;
+      break;
+    case '2':
+      graph[0].axis[i].isaxis = TRUE;
+      break;
+    }
+    switch (Ticks[i]) {
+    case '0':
+      graph[0].axis[i].areticks = FALSE;
+      break;
+    case '1':
+      graph[0].axis[i].areticks = TRUE;
+      break;
+    case '2':
+      graph[0].axis[i].areticks = 2;
+      break;
+    }
+    switch (Labels[i]) {
+    case '0':
+      graph[0].axis[i].islabel = FALSE;
+      break;
+    case '1':
+      graph[0].axis[i].islabel = TRUE;
+      break;
+    case '2':
+      graph[0].axis[i].islabel = (i < 2);
+      break;
+    }
+  }
+
+  SetSectionSizes (section);
+  if (USE_XWINDOW) DrawFrame (graph);
+  FlushDisplay ();
+
+  /* XXX why did I do this??? */
+# if (0)
+  status = TRUE;
+  if (status) {
+    for (i = 0; i < Nsection; i++) {
+      PositionPicture (&section[i]);
+    }
+    if (USE_XWINDOW) XClearWindow (graphic.display, graphic.window);
+    Refresh (1);
+  } else {
+    FlushDisplay ();
+  } 
+# endif
+
+  return (TRUE);
+  
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/LoadLabels.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/LoadLabels.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/LoadLabels.c	(revision 16062)
@@ -0,0 +1,35 @@
+# include "Ximage.h"
+
+int LoadLabels (int sock) {
+  
+  char *c, *label;
+  int mode, size, Nbytes;
+  Section *section;
+  KapaGraphWidget *graph;
+
+  section = GetActiveSection();
+  if (section->graph == NULL) {
+    section->graph = InitGraph ();
+    SetSectionSizes (section);
+  }
+  graph = section->graph;
+  
+  KiiScanMessage (sock, "%d", &mode);
+  label = KiiRecvData (sock);
+
+  bzero (graph[0].label[mode].text, LABEL_MAXLEN);
+
+  Nbytes = MIN (strlen(label), LABEL_MAXLEN - 1);
+  strncpy (graph[0].label[mode].text, label, Nbytes);
+  label[Nbytes] = 0;
+  
+  c = GetRotFont (&size);
+  graph[0].label[mode].size = size;
+  strcpy (graph[0].label[mode].font, c);
+  if (USE_XWINDOW) DrawLabels (graph);
+  
+  FlushDisplay ();
+  
+  return (TRUE);
+  
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/LoadObject.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/LoadObject.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/LoadObject.c	(revision 16062)
@@ -0,0 +1,231 @@
+# include "Ximage.h"
+# include <errno.h>
+# define DEBUG 0
+
+int LoadObject (int sock) {
+  
+  int N;
+  Section *section;
+  KapaGraphWidget *graph;
+
+  section = GetActiveSection();
+  if (section->graph == NULL) {
+    section->graph = InitGraph ();
+    SetSectionSizes (section);
+  }
+  graph = section->graph;
+  
+  N = graph[0].Nobjects;
+  graph[0].Nobjects ++;
+  REALLOCATE (graph[0].objects, Gobjects, graph[0].Nobjects);
+  graph[0].objects[N].x = graph[0].objects[N].y = graph[0].objects[N].z = (float *) NULL;
+  graph[0].objects[N].dxm = graph[0].objects[N].dxp = (float *) NULL;
+  graph[0].objects[N].dym = graph[0].objects[N].dyp = (float *) NULL;
+  
+  KiiScanMessage (sock, "%d %d %d %d %d %d %d %lf %lf",
+		  &graph[0].objects[N].Npts, &graph[0].objects[N].style, 
+		  &graph[0].objects[N].ptype, &graph[0].objects[N].ltype, 
+		  &graph[0].objects[N].etype, &graph[0].objects[N].ebar, 
+		  &graph[0].objects[N].color, 
+		  &graph[0].objects[N].lweight, &graph[0].objects[N].size);
+  
+  if (DEBUG) fprintf (stderr, "%d %d %d %d %d %d %d %lf %lf\n",
+		      graph[0].objects[N].Npts, graph[0].objects[N].style, 
+		      graph[0].objects[N].ptype, graph[0].objects[N].ltype, 
+		      graph[0].objects[N].etype, graph[0].objects[N].ebar, 
+		      graph[0].objects[N].color, 
+		      graph[0].objects[N].lweight, graph[0].objects[N].size);
+  
+  /* force valid ranges */
+  if ((graph[0].objects[N].color > KapaColormapSize()) || (graph[0].objects[N].color < 0))
+    graph[0].objects[N].color = 0;
+
+  KiiScanMessage (sock, "%lf %lf %lf %lf",
+		  &graph[0].objects[N].x0, &graph[0].objects[N].x1, 
+		  &graph[0].objects[N].y0, &graph[0].objects[N].y1);
+
+  // acknowledge receipt of the metadata
+  KiiSendCommand (sock, 4, "DONE"); 
+  
+  // XXX Currently, I require these in a special order.  The data includes a message defining the
+  // object type.  This could be made more flexible by using the information (though we still need
+  // to know how many items will be sent)
+
+  if (!LoadVectorData (sock, graph, N, "x")) {
+    FreeObjectData (&graph[0].objects[N]);
+    graph[0].Nobjects --;
+    REALLOCATE (graph[0].objects, Gobjects, MAX (1, graph[0].Nobjects));
+  }
+    
+  if (!LoadVectorData (sock, graph, N, "y")) {
+    FreeObjectData (&graph[0].objects[N]);
+    graph[0].Nobjects --;
+    REALLOCATE (graph[0].objects, Gobjects, MAX (1, graph[0].Nobjects));
+  }
+  if (graph[0].objects[N].size < 0.0) {
+    if (!LoadVectorData (sock, graph, N, "z")) {
+      FreeObjectData (&graph[0].objects[N]);
+      graph[0].Nobjects --;
+      REALLOCATE (graph[0].objects, Gobjects, MAX (1, graph[0].Nobjects));
+    }
+  }
+  if (graph[0].objects[N].etype & 0x01) {
+    if (!LoadVectorData (sock, graph, N, "dym")) {
+      FreeObjectData (&graph[0].objects[N]);
+      graph[0].Nobjects --;
+      REALLOCATE (graph[0].objects, Gobjects, MAX (1, graph[0].Nobjects));
+    }
+    if (!LoadVectorData (sock, graph, N, "dyp")) {
+      FreeObjectData (&graph[0].objects[N]);
+      graph[0].Nobjects --;
+      REALLOCATE (graph[0].objects, Gobjects, MAX (1, graph[0].Nobjects));
+    }
+  }
+  if (graph[0].objects[N].etype & 0x02) {
+    if (!LoadVectorData (sock, graph, N, "dxm")) {
+      FreeObjectData (&graph[0].objects[N]);
+      graph[0].Nobjects --;
+      REALLOCATE (graph[0].objects, Gobjects, MAX (1, graph[0].Nobjects));
+    }
+    if (!LoadVectorData (sock, graph, N, "dxp")) {
+      FreeObjectData (&graph[0].objects[N]);
+      graph[0].Nobjects --;
+      REALLOCATE (graph[0].objects, Gobjects, MAX (1, graph[0].Nobjects));
+    }
+  }
+
+  if (DEBUG) fprintf (stderr, "loaded %d objects, using object %d\n", graph[0].objects[N].Npts, N);
+
+  if (USE_XWINDOW) DrawObjectN (graph, &graph[0].objects[graph[0].Nobjects-1]);
+  FlushDisplay ();
+
+  return (TRUE);
+  
+}
+
+int LoadVectorData (int sock, KapaGraphWidget *graph, int N, char *type) {
+  
+  int i, Npts, Ninpts, status, Ntry;
+  int bytes_left;
+  char *byte, *buffer, type_send[16], tmp;
+  int Npts_send, Nbytes_send, swap_client, swap_host;
+
+  buffer = NULL;
+  Npts = graph[0].objects[N].Npts;
+
+  KiiWaitAnswer (sock, "PLOB");
+  KiiScanMessage (sock, "%s %d %d %d", type_send, &Npts_send, &Nbytes_send, &swap_client);
+  if (strcmp (type, type_send)) {
+    fprintf (stderr, "Kapa Communication error: unexpected data type %s vs %s\n", type_send, type);
+  }
+  if (Npts_send != Npts) {
+    fprintf (stderr, "Kapa Communication error: unexpected number of points %d vs %d\n", Npts_send, Npts);
+  }
+  if (Nbytes_send != Npts_send*sizeof(float)) {
+    fprintf (stderr, "Kapa Communication error: unexpected data size %d vs %ld\n", Nbytes_send, Npts_send*sizeof(float));
+  }
+
+  status = 1;
+  if (!strcmp (type, "x")) {
+    ALLOCATE (graph[0].objects[N].x, float, MAX (1, Npts));
+    buffer = (char *) graph[0].objects[N].x;
+  }
+  if (!strcmp (type, "y")) {
+    ALLOCATE (graph[0].objects[N].y, float, MAX (1, Npts));
+    buffer = (char *) graph[0].objects[N].y;
+  }
+  if (!strcmp (type, "z")) {
+    ALLOCATE (graph[0].objects[N].z, float, MAX (1, Npts));
+    buffer = (char *) graph[0].objects[N].z;
+  }
+  if (!strcmp (type, "dxm")) {
+    ALLOCATE (graph[0].objects[N].dxm, float, MAX (1, Npts));
+    buffer = (char *) graph[0].objects[N].dxm;
+  }
+  if (!strcmp (type, "dxp")) {
+    ALLOCATE (graph[0].objects[N].dxp, float, MAX (1, Npts));
+    buffer = (char *) graph[0].objects[N].dxp;
+  }
+  if (!strcmp (type, "dym")) {
+    ALLOCATE (graph[0].objects[N].dym, float, MAX (1, Npts));
+    buffer = (char *) graph[0].objects[N].dym;
+  }
+  if (!strcmp (type, "dyp")) {
+    ALLOCATE (graph[0].objects[N].dyp, float, MAX (1, Npts));
+    buffer = (char *) graph[0].objects[N].dyp;
+  }
+
+  bytes_left = Npts*sizeof (float);
+
+  fcntl (sock, F_SETFL, O_NONBLOCK);  
+
+  // read the vector data as raw binary in client machine byte order (floats)
+  Ntry = 0;
+  if (DEBUG) fprintf (stderr, "starting vector load\n");
+  Ninpts = 0;
+  byte = buffer;
+  while (bytes_left > 0) {
+    status = read (sock, byte, bytes_left);
+    if (DEBUG) fprintf (stderr, "status: %d, %d\n", status, bytes_left);
+    if (status == 0) {  /* No more pipe */
+      fprintf (stderr, "error: pipe closed\n");
+      return (FALSE);
+    }
+    if (status != -1) { /* pipe has data */
+      Ninpts += status;
+      bytes_left -= status;
+      byte = (char *)(byte + status);
+      Ntry = 0;
+      continue;
+    }
+    if (errno == EAGAIN) {
+      Ntry ++;
+      if (Ntry > 100) {
+	fprintf (stderr, "kapa communication error\n");
+	return (FALSE);
+      }
+      usleep (10000);
+      continue;
+    }
+    perror ("kapa load");
+  }
+
+  fcntl (sock, F_SETFL, !O_NONBLOCK);  
+  KiiSendCommand (sock, 4, "DONE"); 
+
+# ifdef BYTE_SWAP
+  swap_host = 1;
+# else 
+  swap_host = 0;
+# endif  
+
+  // if host and client have opposite swap parities, word swap the incoming data
+  // SWAP_WORD is strangely defined... it takes the number of the start byte in a
+  // buffer called 'byte'
+  if ((swap_host && !swap_client) || (!swap_host && swap_client)) {
+    byte = buffer;
+    for (i = 0; i < Nbytes_send; i+=4) {
+      SWAP_WORD (i);
+    }
+  }
+
+  if (Ninpts != Npts*sizeof(float)) {  
+    fprintf (stderr, "error: expected %d bytes, but got only %d\n", Ninpts, (unsigned int)(Npts*sizeof(float)));
+    return (FALSE);
+  }
+  if (DEBUG) fprintf (stderr, "done vector load\n");
+  return (TRUE);
+
+}
+
+void FreeObjectData (Gobjects *object) {
+
+  if (object[0].x != (float *) NULL) free (object[0].x);
+  if (object[0].y != (float *) NULL) free (object[0].y);
+  if (object[0].z != (float *) NULL) free (object[0].z);
+
+  if (object[0].dxm != (float *) NULL) free (object[0].dxm);
+  if (object[0].dxp != (float *) NULL) free (object[0].dxp);
+  if (object[0].dym != (float *) NULL) free (object[0].dym);
+  if (object[0].dyp != (float *) NULL) free (object[0].dyp);
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/LoadOverlay.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/LoadOverlay.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/LoadOverlay.c	(revision 16062)
@@ -0,0 +1,128 @@
+# include "Ximage.h"
+
+int LoadOverlay (int sock) {
+  
+  int i, j, Ntotal, Nbytes, Nread, Nfound, Ntext, Nobjects, overnum;
+  int Noverlay, Ntextdata;
+  char *textdata, *buffer, *p, *q;
+  Section *section;
+  KapaImageWidget *image;
+  Graphic *graphic;
+  KiiOverlayBase *overlay;
+
+  graphic = GetGraphic ();
+  section = GetActiveSection();
+  if (section->image == NULL) {
+    section->image = InitImageWidget ();
+    SetSectionSizes (section);
+  }
+  image = section->image;
+
+  KiiScanMessage (sock, "%d %d %d %d", &overnum, &Noverlay, &Ntext, &Ntextdata);
+
+  // XXX need to validate overnum 
+  if ((overnum < 0) || (overnum >= NOVERLAYS)) overnum = 0;
+
+  // read the overlay data as binary 
+  Ntotal = 0;
+  Nbytes = Noverlay*sizeof(KiiOverlayBase);
+  fcntl (sock, F_SETFL, O_NONBLOCK);  
+  ALLOCATE (overlay, KiiOverlayBase, Noverlay);
+  buffer = (char *) overlay;
+  while (Nbytes > 0) { 
+    Nread = read (sock, &buffer[Ntotal], Nbytes);
+    // fprintf (stderr, "read: %d of %d remaining, %d so far, %d expected\n", Nread, Nbytes, Ntotal, Noverlay*sizeof(KiiOverlayBase));
+    if (Nread == 0) {  /* No more pipe */
+      fprintf (stderr, "error: pipe closed\n");
+      free (overlay);
+      fcntl (sock, F_SETFL, !O_NONBLOCK);  
+      return (FALSE);
+    }
+    if (Nread != -1) { /* pipe has data */
+      Nbytes -= Nread;
+      Ntotal += Nread;
+    }
+  }
+  fcntl (sock, F_SETFL, !O_NONBLOCK);  
+  KiiSendCommand (sock,  4, "DONE");
+
+  // read the textdata as binary
+  Ntotal = 0;
+  Nbytes = Ntextdata;
+  fcntl (sock, F_SETFL, O_NONBLOCK);  
+  ALLOCATE (textdata, char, Ntextdata);
+  while (Nbytes > 0) { 
+    Nread = read (sock, &textdata[Ntotal], Nbytes);
+    if (Nread == 0) {  /* No more pipe */
+      fprintf (stderr, "error: pipe closed\n");
+      free (textdata);
+      free (overlay);
+      fcntl (sock, F_SETFL, !O_NONBLOCK);  
+      return (FALSE);
+    }
+    if (Nread != -1) { /* pipe has data */
+      Nbytes -= Nread;
+      Ntotal += Nread;
+    }
+  }
+  fcntl (sock, F_SETFL, !O_NONBLOCK);  
+  KiiSendCommand (sock,  4, "DONE");
+
+  // add new overlay objects to existing data
+  Nobjects = image[0].overlay[overnum].Nobjects + Noverlay;
+  REALLOCATE (image[0].overlay[overnum].objects, KiiOverlay, Nobjects);
+
+  j = image[0].overlay[overnum].Nobjects;
+  for (i = 0; i < Noverlay; i++, j++) {
+    image[0].overlay[overnum].objects[j].x     = overlay[i].x;
+    image[0].overlay[overnum].objects[j].y     = overlay[i].y;
+    image[0].overlay[overnum].objects[j].dx    = overlay[i].dx;
+    image[0].overlay[overnum].objects[j].dy    = overlay[i].dy;
+    image[0].overlay[overnum].objects[j].angle = overlay[i].angle;
+    image[0].overlay[overnum].objects[j].type  = overlay[i].type;
+    image[0].overlay[overnum].objects[j].text  = NULL;
+  }
+
+  // parse the text data : text lines are separated by '\n', one per text entry
+  p = textdata;
+  Nfound = 0;
+  for (i = 0; i < Noverlay; i++) {
+    if (overlay[i].type != KII_OVERLAY_TEXT) continue;
+    if (Nfound >= Ntext) {
+      fprintf (stderr, "inconsistent number of text lines\n");
+      break;
+    }
+    if (! *p) {
+      fprintf (stderr, "inconsistent number of text lines\n");
+      break;
+    }
+    q = strchr (p, '\n');
+    if (q == NULL) {
+      fprintf (stderr, "inconsistent text line\n");
+      break;
+    }
+    j = image[0].overlay[overnum].Nobjects + i;
+    image[0].overlay[overnum].objects[j].text = strncreate (p, q-p);
+    p = q + 1;
+    Nfound ++;
+  }
+  if (Nfound != Ntext) {
+    fprintf (stderr, "read %d text lines, expected %d\n", Nfound, Ntext);
+  }
+
+  free (textdata);
+  free (overlay);
+
+  image[0].overlay[overnum].Nobjects = Nobjects;
+  image[0].overlay[overnum].active = TRUE;
+
+  if (USE_XWINDOW) {
+    for (i = 0; i < NOVERLAYS; i++) {
+      if (image[0].overlay[i].active) {
+	PaintOverlay (graphic, image, i);
+      }
+    }
+    XFlush (graphic[0].display);
+  }
+  return (TRUE);
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/LoadPicture.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/LoadPicture.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/LoadPicture.c	(revision 16062)
@@ -0,0 +1,73 @@
+# include "Ximage.h"
+
+int LoadPicture (int sock) {
+
+  Header header;
+  char *buff;
+  int status, bytes_left;
+  Section *section;
+  KapaImageWidget *image;
+  Graphic *graphic;
+
+  graphic = GetGraphic ();
+  section = GetActiveSection();
+  if (section->image == NULL) {
+    section->image = InitImageWidget ();
+    SetSectionSizes (section);
+  }
+  image = section->image;
+  
+  KiiSendMessage (sock, "%d", graphic->Npixels);
+
+  gfits_init_header (&header);
+  header.Naxes = 2;
+  KiiScanMessage (sock, "%d %d %d %d %lf %lf", &header.Naxis[0], &header.Naxis[1]);
+  KiiScanMessage (sock, "%d %d %d %d %lf %lf", &header.bitpix, &header.unsign, &header.bzero, &header.bscale);
+  KiiScanMessage (sock, "%lf %lf %s %s",  &image[0].image[0].zero, &image[0].image[0].range, image[0].image[0].name, image[0].image[0].file);
+  KiiScanMessage (sock, "%lf %lf %d", &image[0].image[0].min,  &image[0].image[0].max, &header.size);
+  KiiScanMessage (sock, "%lf %f %f %f %f", &image[0].image[0].coords.crval1, &image[0].image[0].coords.crpix1, &image[0].image[0].coords.cdelt1, &image[0].image[0].coords.pc1_1, &image[0].image[0].coords.pc1_2);
+  KiiScanMessage (sock, "%lf %f %f %f %f", &image[0].image[0].coords.crval2, &image[0].image[0].coords.crpix2, &image[0].image[0].coords.cdelt2, &image[0].image[0].coords.pc2_1, &image[0].image[0].coords.pc2_2);
+  KiiScanMessage (sock, "%s", image[0].image[0].coords.ctype);
+
+  gfits_free_matrix (&image[0].image[0].matrix);
+  gfits_create_matrix (&header, &image[0].image[0].matrix);
+
+  fcntl (sock, F_SETFL, O_NONBLOCK);  
+
+  status = 1;
+  buff = image[0].image[0].matrix.buffer;
+  bytes_left = header.size;
+  image[0].image[0].matrix.size = 0;
+  while (bytes_left > 0) {
+    status = read (sock, buff, bytes_left);
+    if (status == 0) {  /* No more pipe */
+      fprintf (stderr, "error: pipe closed\n");
+      return (FALSE);
+    }
+    if (status != -1) { /* pipe has data */
+      image[0].image[0].matrix.size += status;
+      bytes_left -= status;
+      buff = (char *)(buff + status);
+    }
+  }
+
+  fcntl (sock, F_SETFL, !O_NONBLOCK);  
+
+  if (DEBUG) fprintf (stderr, "read %d bytes\n", image[0].image[0].matrix.size);
+  /* it it not obvious this condition should kill kii, but ... */
+  if (image[0].image[0].matrix.size != header.size) {  
+    fprintf (stderr, "error: expected %d bytes, but got only %d\n", header.size, image[0].image[0].matrix.size);
+    return (FALSE);
+  }
+
+  if (!USE_XWINDOW) return (TRUE);
+
+  SetColorScale (graphic, image);
+  Remap (graphic, image);
+  if (DEBUG) fprintf (stderr, "remapped image\n");
+  Refresh ();
+  if (DEBUG) fprintf (stderr, "refreshed\n");
+  XFlush (graphic[0].display);
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/LoadTextlines.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/LoadTextlines.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/LoadTextlines.c	(revision 16062)
@@ -0,0 +1,49 @@
+# include "Ximage.h"
+
+int LoadTextlines (int sock) {
+  
+  char *string;
+  int N, size;
+  double tX, tY, tT, L;
+  Section *section;
+  KapaGraphWidget *graph;
+
+  section = GetActiveSection();
+  graph = section->graph;
+    if (section->graph == NULL) {
+    section->graph = InitGraph ();
+    SetSectionSizes (section);
+  }
+
+  graph[0].Ntextline = MAX (graph[0].Ntextline, 0);
+  N = graph[0].Ntextline;
+  graph[0].Ntextline++;
+  REALLOCATE (graph[0].textline, Label, graph[0].Ntextline);
+
+  KiiScanMessage (sock, "%lf %lf %lf", &tX, &tY, &tT);
+
+  L = graph[0].axis[0].dfx;
+  graph[0].textline[N].x = L * (tX - graph[0].axis[0].min) / (graph[0].axis[0].max - graph[0].axis[0].min) + graph[0].axis[0].fx;
+
+  L = graph[0].axis[1].dfy;
+  graph[0].textline[N].y = L * (tY - graph[0].axis[1].min) / (graph[0].axis[1].max - graph[0].axis[1].min) + graph[0].axis[1].fy;
+
+  graph[0].textline[N].angle = tT;
+
+  bzero (graph[0].textline[N].text, LABEL_MAXLEN);
+
+  string = KiiRecvData (sock);
+  strcpy (graph[0].textline[N].text, string);
+  free (string);
+  
+  string = GetRotFont (&size);
+  graph[0].textline[N].size = size;
+  strcpy (graph[0].textline[N].font, string);
+
+  if (USE_XWINDOW) DrawTextlines (graph);
+  
+  FlushDisplay ();
+  
+  return (TRUE);
+  
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/LoadTickmarks.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/LoadTickmarks.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/LoadTickmarks.c	(revision 16062)
@@ -0,0 +1,66 @@
+# include "Ximage.h"
+
+int LoadTickmarks (int sock) {
+  
+  char line[129], type[16];
+  double x, y, dx, dy;
+  int status, NOBJECTS, Nobjects, done;
+  Section *section;
+  KapaImageWidget *image;
+
+  section = GetActiveSection();
+  if (section->image == NULL) {
+    section->image = InitImageWidget ();
+    SetSectionSizes (section);
+  }
+  image   = section->image;
+
+  Nobjects = image[0].tickmarks.Nobjects;
+  NOBJECTS = Nobjects + 100;
+  REALLOCATE (image[0].tickmarks.objects, KiiOverlay, NOBJECTS);
+  
+  done = FALSE;
+  while (!done) {
+    status = read (sock, line, 128); 
+    line[128] = 0; 
+
+    if (!strncmp (line, "DONE", 4)) {
+      done = TRUE;
+      break;
+    }
+    
+    sscanf (line, "%s %lf %lf %lf %lf\n", type, &x, &y, &dx, &dy);
+    
+    if (strcmp (type, "TEXT") && strcmp (type, "LINE") && strcmp (type, "BOX") && strcmp (type, "CIRCLE")) {  /* skip */
+      fprintf (stderr, "don't know %s, skipping\n", type);
+      continue;
+    }
+    
+    strcpy (image[0].tickmarks.objects[Nobjects].type, type);
+    image[0].tickmarks.objects[Nobjects].x = x;
+    image[0].tickmarks.objects[Nobjects].y = y;
+    image[0].tickmarks.objects[Nobjects].dx = dx;
+    image[0].tickmarks.objects[Nobjects].dy = dy;
+    
+    if (!strcmp (type, "TEXT")) { /* dx = Nchar, dy = angle (not yet used) */
+      status = read (sock, line, 128); 
+      line[128] = 0; 
+      ALLOCATE (image[0].tickmarks.objects[Nobjects].text, char, (int) dx + 1);
+      strncpy (image[0].tickmarks.objects[Nobjects].text, line, (int) dx);
+      image[0].tickmarks.objects[Nobjects].text[(int)dx] = 0;
+    }      
+    
+    Nobjects++;
+    if (Nobjects >= NOBJECTS) {
+      NOBJECTS = Nobjects + 100;
+      REALLOCATE (image[0].tickmarks.objects, KiiOverlay, NOBJECTS);
+    }
+
+  }
+
+  REALLOCATE (image[0].tickmarks.objects, KiiOverlay, MAX(Nobjects, 1));
+  image[0].tickmarks.Nobjects = Nobjects;
+
+  if (USE_XWINDOW) Refresh ();
+  return (TRUE);
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/MakeColormap.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/MakeColormap.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/MakeColormap.c	(revision 16062)
@@ -0,0 +1,52 @@
+# include "Ximage.h"
+
+static char default_cmap[] = "grayscale";
+
+void MakeColormap (int argc, char **argv) {
+
+  int i, N, status;
+  char *temp_name;
+  Graphic *graphic;
+
+  graphic = GetGraphic();
+
+  /* hardwired colors - white, black -- for drawing text and overlay graphics */
+  temp_name = XGetDefault (graphic[0].display, argv[0], "ROverlay");
+  graphic[0].overlay_color[0] = GetColor (graphic[0].display, (temp_name == (char *) NULL ? "red"    : temp_name), graphic[0].colormap, graphic[0].fore);
+  temp_name = XGetDefault (graphic[0].display, argv[0], "GOverlay");
+  graphic[0].overlay_color[1] = GetColor (graphic[0].display, (temp_name == (char *) NULL ? "green"  : temp_name), graphic[0].colormap, graphic[0].fore);
+  temp_name = XGetDefault (graphic[0].display, argv[0], "BOverlay");
+  graphic[0].overlay_color[2] = GetColor (graphic[0].display, (temp_name == (char *) NULL ? "blue"   : temp_name), graphic[0].colormap, graphic[0].fore);
+  temp_name = XGetDefault (graphic[0].display, argv[0], "YOverlay");
+  graphic[0].overlay_color[3] = GetColor (graphic[0].display, (temp_name == (char *) NULL ? "yellow" : temp_name), graphic[0].colormap, graphic[0].fore);
+
+  for (i = 0; i < graphic[0].Npixels; i++) {
+    graphic[0].cmap[i].pixel = graphic[0].pixels[i];
+  }
+
+  /* decide on a color map */
+  temp_name = XGetDefault (graphic[0].display, argv[0], "Colormap");
+  if ((N = get_argument (argc, argv, "-cm"))) {
+    if (N + 1 < argc) {
+      temp_name = argv[N+1];
+    } else {
+      fprintf (stderr, "error: usage is -cm ColormapName\n");
+      exit (1);
+    }
+  }
+  if (temp_name == (char *) NULL) temp_name = default_cmap;
+
+  status = SetColormap (temp_name);
+  if (!status) {
+    fprintf (stderr, "invalid colormap, using default %s\n", default_cmap);
+    temp_name = default_cmap;
+    status = SetColormap (temp_name);
+    if (!status) {
+      fprintf (stderr, "problem with default colormap\n");
+      exit (1);
+    }
+  }
+}
+
+/* this routine is NOT independent of the number of overlays */
+
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/MakeCursor.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/MakeCursor.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/MakeCursor.c	(revision 16062)
@@ -0,0 +1,9 @@
+# include "Ximage.h"
+
+/************** MakeCursor *************/
+void MakeCursor (Graphic *graphic, unsigned int cursor) {
+
+  graphic->cursor = XCreateFontCursor (graphic->display, (unsigned) cursor);
+
+  if (graphic->cursor != (Cursor) None) XDefineCursor (graphic->display, graphic->window, graphic->cursor);
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/MakeGC.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/MakeGC.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/MakeGC.c	(revision 16062)
@@ -0,0 +1,14 @@
+# include "Ximage.h"
+
+/************** MakeGC *************/
+void MakeGC (Graphic *graphic) {
+
+  XGCValues gcvalues;
+
+  gcvalues.foreground = graphic->fore;
+  gcvalues.background = graphic->back;
+  graphic->gc = XCreateGC (graphic->display, graphic->window, 
+			     GCForeground | GCBackground, &gcvalues);
+  if (graphic->gc == 0)
+    QuitX (graphic->display, "Error in creating a Graphics Context");
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/MapWindow.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/MapWindow.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/MapWindow.c	(revision 16062)
@@ -0,0 +1,9 @@
+# include "Ximage.h"
+
+/************** MapWindow *************/
+void MapWindow (Graphic *graphic) {
+
+  XMapRaised (graphic->display, graphic->window);
+  XMapSubwindows (graphic->display, graphic->window);
+  FlushDisplay (graphic);
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/NameWindow.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/NameWindow.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/NameWindow.c	(revision 16062)
@@ -0,0 +1,29 @@
+# include "Ximage.h"
+
+/************** NameWindow *************/
+void NameWindow (Graphic *graphic, char *Name) {
+
+  char       *name;
+  char       *class_name;
+  char       *class_type;
+  XClassHint *classhints;
+
+  name = strrchr (Name, '/');
+  if (name != NULL) 
+    name ++;
+  else 
+    name = Name;
+
+  class_type = class_name = name;
+  classhints = XAllocClassHint ();
+
+  if (classhints != (XClassHint *) NULL)  {
+    classhints[0].res_name = class_name;
+    classhints[0].res_class = class_type;
+    XSetClassHint (graphic->display, graphic->window, classhints);
+    XFree (classhints);
+  }
+  
+  XStoreName (graphic->display, graphic->window, name);
+  XSetIconName (graphic->display, graphic->window, name);
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/OpenDisplay.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/OpenDisplay.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/OpenDisplay.c	(revision 16062)
@@ -0,0 +1,15 @@
+# include "Ximage.h"
+
+/************** OpenDisplay *************/
+Display *OpenDisplay (char *name, int *screen) {
+
+  Display *display;
+  
+  display = XOpenDisplay (name);
+  if (display == NULL) {
+    fprintf (stderr, "Error could not open X display to %s\n", XDisplayName (name));
+    exit (0);
+  }
+  *screen = DefaultScreen (display);
+  return (display);
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/PNGit.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/PNGit.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/PNGit.c	(revision 16062)
@@ -0,0 +1,76 @@
+# include "Ximage.h"
+
+int PNGit (int sock) {
+
+  FILE *f;
+  png_structp png_ptr;
+  png_infop info_ptr;
+  png_color *palette;
+  int Npalette;
+  char filename[1024];
+  int Nbytes, status;
+  bDrawBuffer *buffer;
+  Graphic *graphic;
+
+  graphic = GetGraphic();
+
+  /* expect a line telling the number of bytes and a filename */
+  status = read (sock, filename, 16);
+  filename[16] = 0;
+  sscanf (filename, "%*s %d", &Nbytes);
+  status = read (sock, filename, Nbytes);
+  filename[status] = 0; /* make the string easy to parse */
+
+  f = fopen (filename, "w");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "can't open output file %s\n", "Xgraph.png");
+    return (TRUE);  /* true because otherwise it quits kapa! */
+  }
+
+  png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, (png_voidp) NULL, (png_voidp) NULL, (png_voidp) NULL);
+  if (!png_ptr) {
+    fprintf (stderr, "can't get png structure\n");
+    fclose (f);
+    return (TRUE);
+  }
+
+  info_ptr = png_create_info_struct (png_ptr);
+  if (!info_ptr) {
+    fprintf (stderr, "can't get png info structure\n");
+    png_destroy_write_struct (&png_ptr, (png_infopp) NULL);
+    fclose (f);
+    return (TRUE);
+  }
+
+  if (setjmp (png_ptr[0].jmpbuf)) {
+    fprintf (stderr, "can't get png return\n");
+    png_destroy_write_struct (&png_ptr, &info_ptr);
+    fclose (f);
+    return (TRUE);
+  }
+
+  png_init_io (png_ptr, f);
+
+  /* see docs for write-row-callback to provide progress info */
+
+  png_set_IHDR (png_ptr, info_ptr, graphic->dx, graphic->dy, 8, PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); 
+
+  /* png_set_IHDR (png_ptr, info_ptr, graphic->dx, graphic->dy, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); */
+
+  palette = KapaPNGPalette (&Npalette);
+  png_set_PLTE (png_ptr, info_ptr, palette, Npalette); 
+ 
+  png_write_info (png_ptr, info_ptr);
+
+  buffer = bDrawIt ();
+
+  png_write_image (png_ptr, buffer[0].pixels);
+  png_write_end (png_ptr, info_ptr);
+  png_destroy_write_struct (&png_ptr, &info_ptr);
+  
+  bDrawBufferFree (buffer);
+  free (palette);
+  fclose (f);
+  return (TRUE);
+
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/PPMit.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/PPMit.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/PPMit.c	(revision 16062)
@@ -0,0 +1,54 @@
+# include "Ximage.h"
+
+int PPMit (int sock) {
+
+  FILE *f;
+  char *line, filename[1024];
+  int Nbytes, status, dx, dy, i, j, Npalette, color;
+  png_color *palette;
+  bDrawBuffer *buffer;
+  Graphic *graphic;
+
+  graphic = GetGraphic();
+
+  /* expect a line telling the number of bytes and a filename */
+  status = read (sock, filename, 16);
+  filename[16] = 0;
+  sscanf (filename, "%*s %d", &Nbytes);
+  status = read (sock, filename, Nbytes);
+  filename[status] = 0; /* make the string easy to parse */
+
+  f = fopen (filename, "w");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "can't open output file %s\n", filename);
+    return (TRUE);  /* true because otherwise it quits kapa! */
+  }
+  
+  palette = KapaPNGPalette (&Npalette);
+
+  dx = graphic->dx;
+  dy = graphic->dy;
+  
+  fprintf (f, "P6\n");
+  fprintf (f, "%d %d\n", dx, dy);
+  fprintf (f, "255\n");
+
+  buffer = bDrawIt ();
+
+  ALLOCATE (line, char, 3*dx);
+
+  for (i = 0; i < dy; i++) {
+    for (j = 0; j < dx; j++) {
+      color = buffer[0].pixels[i][j];
+      line[3*j + 0] = palette[color].red;
+      line[3*j + 1] = palette[color].green;
+      line[3*j + 2] = palette[color].blue;
+    }
+    fwrite (line, 3, dx, f);
+  }
+  fclose (f);
+  
+  bDrawBufferFree (buffer);
+  return (TRUE);
+
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/PSFrame.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/PSFrame.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/PSFrame.c	(revision 16062)
@@ -0,0 +1,105 @@
+# include "Ximage.h"
+# define DrawLine(X1,Y1,DX,DY) (fprintf (f, " %6.2f %6.2f %6.2f %6.2f L\n", X1, Y1, X1+DX, Y1+DY))
+
+int PSFrame (KapaGraphWidget *graph, FILE *f) {
+  
+  int i, P, IsLabel, fontsize;
+  double fx, fy, dfx, dfy, range, major, minor, first, next;
+  char *fontname;
+  Graphic *graphic;
+
+  graphic = GetGraphic();
+
+  /* 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;
+    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);
+
+    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;
+      }
+      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));) {
+	IsLabel = FALSE;
+	if ((fabs((int)(next/major) - (next/major)) < 0.5*(minor/major)) || 
+	    (fabs ((int)((next + 0.5*minor)/major) - (next/major)) < 0.5*(minor/major)) ||
+	    (fabs ((int)((next - 0.5*minor)/major) - (next/major)) < 0.5*(minor/major)))
+	  IsLabel = graph[0].axis[i].islabel;
+	PSTick (f, fx, fy, dfx, dfy, P, graph[0].axis[i].min, graph[0].axis[i].max, next, IsLabel, i);
+	if (range > 0) 
+	  next += minor;
+	else 
+	  next -= minor;
+      }
+    }
+  }
+  return (TRUE);
+}
+
+void PSTick (FILE *f, double fx, double fy, double dfx, double dfy, int P, double min, double max, double value, int mode, int naxis) {
+  
+  int pos, dir, fontsize;
+  double size, n, x, y, dx, dy;
+  char string[64], *fontname;
+
+  pos = size = 0;
+
+  if (mode == 1) { size = MAX (0.02, 7.0 / P); }
+  if (mode == 0) { size = MAX (0.01, 4.0 / P); }
+  
+  n = P / sqrt ((double)(dfx*dfx + dfy*dfy));
+  x = fx + (value-min)*dfx/(max - min);
+  y = fy + (value-min)*dfy/(max - min);
+
+  dir = -1;
+  if ((naxis == 0) || (naxis == 1)) dir *= -1;
+  dx = dir*size*dfy*n;	
+  dy = dir*size*dfx*n;
+  
+  DrawLine (x, y, dx, dy);
+
+  if (mode == 1) {
+    fontname = GetRotFont (&fontsize);
+
+    /* temporarily assume rectilinear axes */
+    if (naxis == 0) { dx = 0; dy = -dir*(0.8*fontsize + 1); pos = 1; }
+    if (naxis == 2) { dx = 0; dy = -dir*(0.8*fontsize + 1); pos = 7; }
+
+    if (naxis == 1) { dy = 0; dx = -(0.8*fontsize + 1); pos = 3; }
+    if (naxis == 3) { dy = 0; dx = +(0.8*fontsize + 1); pos = 5; }
+
+    x = fx + (value-min)*dfx/(max - min) + dx;
+    y = fy + (value-min)*dfy/(max - min) + dy;
+    if (fabs(value) < 1e-14) { value = 0.0; }
+    sprintf (string, "%g", value);
+    PSRotText (f, (int)x, (int)y, string, pos, 0.0);
+  }
+}
+
+  /* 
+  dx = size*dfy*n;	
+  dy = size*dfx*n;
+  DrawLine (x, y, dx, dy);
+  
+  dx = -size*dfy*n;	
+  dy = -size*dfx*n;
+  DrawLine (x, y, dx, dy);
+  */
+  
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/PSLabels.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/PSLabels.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/PSLabels.c	(revision 16062)
@@ -0,0 +1,49 @@
+# include "Ximage.h"
+  
+void PSLabels (KapaGraphWidget *graph, FILE *f) {
+  
+  int i, pos, x, y, size;
+  double angle;
+  char *fontname;
+  Graphic *graphic;
+
+  graphic = GetGraphic();
+
+  pos = 0;
+  fontname = GetRotFont (&size);
+  for (i = 0; i < 8; i++) {
+    if (strcmp (graph[0].label[i].text, "")) {
+      angle = 0;
+      switch (i) {
+      case 0: pos = 7; break;
+      case 1: pos = 1; angle = -90; break;
+      case 2: pos = 1; break;
+      case 3: pos = 1; angle =  90; break;
+      case 4: pos = 2; break;
+      case 5: pos = 0; break;
+      case 6: pos = 8; break;
+      case 7: pos = 6; break;
+      }	
+      x = graph[0].label[i].x;
+      y = graphic->dy - graph[0].label[i].y;
+      SetRotFont (graph[0].label[i].font, graph[0].label[i].size); 
+      PSRotText (f, x, y, graph[0].label[i].text, pos, angle);
+    }
+  }
+  SetRotFont (fontname, size);
+}
+
+  /*
+            
+ 4____2___5 
+  |       | 
+  |       | 
+ 1|       |3
+  |       |
+  |       |
+  ---------
+  6   0   7
+
+  */
+
+
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/PSObjects.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/PSObjects.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/PSObjects.c	(revision 16062)
@@ -0,0 +1,600 @@
+# include "Ximage.h"
+
+# define DrawLine(X1,Y1,X2,Y2) (fprintf (f, " %6.2f %6.2f %6.2f %6.2f L\n", X1, graphic->dy - Y1, X2, graphic->dy - Y2))
+# define DrawCircle(X1,Y1,R) (fprintf (f, " %6.2f %6.2f %6.2f C\n", (X1), (graphic->dy - Y1), (R)))
+# define DrawRectangle(X,Y,dX,dY) (fprintf (f, " %6.2f %6.2f %6.2f %6.2f B\n", (dX), (dY), (X-0.5*dX), (graphic->dy-Y-0.5*dY)))
+# define FillRectangle(X,Y,dX,dY) (fprintf (f, " %6.2f %6.2f %6.2f %6.2f F\n", (dX), (dY), (X-0.5*dX), (graphic->dy-Y-0.5*dY)))
+# define FillTriangle(X1,Y1,X2,Y2, X3, Y3) (fprintf (f, " %6.2f %6.2f %6.2f %6.2f %6.2f %6.2f TF\n", (X1), (graphic->dy-Y1), (X2), (graphic->dy-Y2), (X3), (graphic->dy-Y3)))
+# define CONNECT 0
+# define HISTOGRAM 1
+# define POINTS 2
+
+static Graphic *graphic;
+
+int PSObjects (KapaGraphWidget *graph, FILE *f) {
+  
+  int i;
+  double lweight;
+  static char dash[] = "5";
+  static char dot[] = "3";
+  
+  graphic = GetGraphic();
+
+  for (i = 0; i < graph[0].Nobjects; i++) {
+    switch (graph[0].objects[i].ltype) {
+    case 0:
+      break;
+    case 1:
+      fprintf (f, "[%s] 0 setdash\n", dash);
+      break;
+    case 2:
+      fprintf (f, "[%s] 0 setdash\n", dot);
+      break;
+    default:
+      break;
+    }
+    
+    lweight = MAX (0, MIN (10, graph[0].objects[i].lweight));
+    fprintf (f, "%.1f setlinewidth\n", lweight);
+    fprintf (f, "%s setrgbcolor\n", KapaColorRGBString(graph[0].objects[i].color));
+
+    switch (graph[0].objects[i].style) {
+    case CONNECT: 
+      PSConnect (graph, &graph[0].objects[i], f);
+      break;
+    case HISTOGRAM:
+      PSHistogram (graph, &graph[0].objects[i], f);
+      break;
+    case POINTS:
+      PSPoints (graph, &graph[0].objects[i], f);
+      break;
+    }
+
+    if (graph[0].objects[i].etype & 0x01) {
+      PSYErrors (graph, &graph[0].objects[i], f);
+    }
+    if (graph[0].objects[i].etype & 0x02) {
+      PSXErrors (graph, &graph[0].objects[i], f);
+    }
+    fprintf (f, "[] 0 setdash\n");
+    fprintf (f, "0.00 0.00 0.00 setrgbcolor\n");
+  }
+  return (TRUE);
+}
+
+/*******/
+void PSConnect (KapaGraphWidget *graph, Gobjects *object, FILE *f) {
+  
+  int i;
+  float *x, *y;
+  double mxi, mxj, myi, myj, bxi, bxj, byi, byj, bx, by;
+  double sx0, sy0, sx1, sy1;
+  double X0, X1, Y0, Y1;
+
+  mxi = graph[0].axis[0].dfx / (object[0].x1 - object[0].x0);
+  mxj = graph[0].axis[1].dfx / (object[0].y1 - object[0].y0);
+  myi = graph[0].axis[0].dfy / (object[0].x1 - object[0].x0);
+  myj = graph[0].axis[1].dfy / (object[0].y1 - object[0].y0); 
+  
+  bxi  =  graph[0].axis[0].fx - object[0].x0*graph[0].axis[0].dfx/(object[0].x1 - object[0].x0);
+  bxj  =  -object[0].y0*graph[0].axis[1].dfx/(object[0].y1 - object[0].y0);
+  byi  =  -object[0].x0*graph[0].axis[0].dfy/(object[0].x1 - object[0].x0);
+  byj  =  graph[0].axis[1].fy - object[0].y0*graph[0].axis[1].dfy/(object[0].y1 - object[0].y0); 
+  
+  bx = bxi + bxj;
+  by = byi + byj;
+  
+  X0 = graph[0].axis[0].fx;
+  X1 = graph[0].axis[0].fx + graph[0].axis[0].dfx;
+  Y0 = graph[0].axis[1].fy;
+  Y1 = graph[0].axis[1].fy + graph[0].axis[1].dfy;
+
+  x = object[0].x; y = object[0].y;
+  for (i = 0; (i < object[0].Npts) && !(finite(x[i]) && finite(y[i])); i++);
+  if (i >= object[0].Npts) return;
+  sx0 = x[i]*mxi + y[i]*mxj + bx;
+  sy0 = x[i]*myi + y[i]*myj + by;
+  
+  for (i++; i < object[0].Npts; i++) {
+    if (!(finite(x[i]) && finite(y[i]))) continue;
+    sx1 = x[i]*mxi + y[i]*mxj + bx;
+    sy1 = x[i]*myi + y[i]*myj + by;
+    ClipLinePS (sx0, sy0, sx1, sy1, X0, Y0, X1, Y1, f);
+    /* DrawLine (sx0, sy0, sx1, sy1); */
+    sx0 = sx1; sy0 = sy1;
+  }
+}
+
+void ClipLinePS (double x0, double y0, double x1, double y1, double X0, double Y1, double X1, double Y0, FILE *f) {
+
+  /* skip line segement if both points are beyond box */
+  if ((x0 <= X0) && (x1 <= X0)) return;
+  if ((x0 >= X1) && (x1 >= X1)) return;
+  if ((y0 <= Y0) && (y1 <= Y0)) return;
+  if ((y0 >= Y1) && (y1 >= Y1)) return;
+
+  /* replace x0,y0 if outside box */
+  if ((x0 < X0) && (x1 >= X0)) {
+    y0 = y0 + (X0 - x0)*(y1 - y0)/(x1 - x0);
+    x0 = X0;
+  }
+  if ((x0 > X1) && (x1 <= X1)) {
+    y0 = y0 + (X1 - x0)*(y1 - y0)/(x1 - x0);
+    x0 = X1;
+  }
+  if ((y0 < Y0) && (y1 >= Y0)) {
+    x0 = x0 + (Y0 - y0)*(x1 - x0)/(y1 - y0);
+    y0 = Y0;
+  }
+  if ((y0 > Y1) && (y1 <= Y1)) {
+    x0 = x0 + (Y1 - y0)*(x1 - x0)/(y1 - y0);
+    y0 = Y1;
+  }
+
+  /* skip line segement if both points are beyond box */
+  if ((x0 <= X0) && (x1 <= X0)) return;
+  if ((x0 >= X1) && (x1 >= X1)) return;
+  if ((y0 <= Y0) && (y1 <= Y0)) return;
+  if ((y0 >= Y1) && (y1 >= Y1)) return;
+
+  /* replace x1,y1 if outside box */
+  if ((x1 < X0) && (x0 >= X0)) {
+    y1 = y0 + (X0 - x0)*(y1 - y0)/(x1 - x0);
+    x1 = X0;
+  }
+  if ((x1 > X1) && (x0 <= X1)) {
+    y1 = y0 + (X1 - x0)*(y1 - y0)/(x1 - x0);
+    x1 = X1;
+  }
+  if ((y1 < Y0) && (y0 >= Y0)) {
+    x1 = x0 + (Y0 - y0)*(x1 - x0)/(y1 - y0);
+    y1 = Y0;
+  }
+  if ((y1 > Y1) && (y0 <= Y1)) {
+    x1 = x0 + (Y1 - y0)*(x1 - x0)/(y1 - y0);
+    y1 = Y1;
+  }
+  DrawLine (x0, y0, x1, y1);
+}
+
+/*******/
+void PSHistogram (KapaGraphWidget *graph, Gobjects *object, FILE *f) {
+
+  int i;
+  float *x, *y;
+  double mxi, mxj, myi, myj, bxi, bxj, byi, byj, bx, by;
+  double sx0, sy0, sx1, sy1, sxa;
+  double X0, X1, Y0, Y1;
+
+  mxi = graph[0].axis[0].dfx / (object[0].x1 - object[0].x0);
+  mxj = graph[0].axis[1].dfx / (object[0].y1 - object[0].y0);
+  myi = graph[0].axis[0].dfy / (object[0].x1 - object[0].x0);
+  myj = graph[0].axis[1].dfy / (object[0].y1 - object[0].y0); 
+  
+  bxi  =  graph[0].axis[0].fx - object[0].x0*graph[0].axis[0].dfx/(object[0].x1 - object[0].x0);
+  bxj  =  -object[0].y0*graph[0].axis[1].dfx/(object[0].y1 - object[0].y0);
+  byi  =  -object[0].x0*graph[0].axis[0].dfy/(object[0].x1 - object[0].x0);
+  byj  =  graph[0].axis[1].fy - object[0].y0*graph[0].axis[1].dfy/(object[0].y1 - object[0].y0); 
+  
+  bx = bxi + bxj;
+  by = byi + byj;
+  
+  X0 = graph[0].axis[0].fx;
+  X1 = graph[0].axis[0].fx + graph[0].axis[0].dfx;
+  Y0 = graph[0].axis[1].fy;
+  Y1 = graph[0].axis[1].fy + graph[0].axis[1].dfy;
+
+  /* find the first valid datapoint */
+  x = object[0].x; y = object[0].y;
+  for (i = 0; (i < object[0].Npts) && !(finite(x[i]) && finite(y[i])); i++);
+  if (i >= object[0].Npts) return;
+  sx0 = x[i]*mxi + y[i]*mxj + bx;
+  sy0 = x[i]*myi + y[i]*myj + by;
+  sx0 = MIN (MAX (sx0, X0), X1);
+  sy0 = MAX (MIN (sy0, Y0), Y1);
+  
+  /* continue with rest of points */
+  for (i++; i < object[0].Npts; i++) {
+    if (!(finite(x[i]) && finite(y[i]))) continue;
+    sx1 = x[i]*mxi + y[i]*mxj + bx;
+    sy1 = x[i]*myi + y[i]*myj + by;
+    sx1 = MIN (MAX (sx1, X0), X1);
+    sy1 = MAX (MIN (sy1, Y0), Y1);
+    sxa = 0.5*(sx0 + sx1);
+    DrawLine (sx0, sy0, sxa, sy0);
+    DrawLine (sxa, sy0, sxa, sy1);
+    DrawLine (sxa, sy1, sx1, sy1);
+    sx0 = sx1; sy0 = sy1;
+  }
+}
+
+/*******/
+void PSPoints (KapaGraphWidget *graph, Gobjects *object, FILE *f) {
+ 
+  int i;
+  float *x, *y, *z;
+  double mxi, mxj, myi, myj, bxi, bxj, byi, byj, bx, by;
+  double sx, sy, d, sx1, sy1, sx2, sy2;
+
+  mxi = graph[0].axis[0].dfx / (object[0].x1 - object[0].x0);
+  mxj = graph[0].axis[1].dfx / (object[0].y1 - object[0].y0);
+  myi = graph[0].axis[0].dfy / (object[0].x1 - object[0].x0);
+  myj = graph[0].axis[1].dfy / (object[0].y1 - object[0].y0);  
+ 
+  bxi  =  graph[0].axis[0].fx - object[0].x0*graph[0].axis[0].dfx/(object[0].x1 - object[0].x0);
+  bxj  =  -object[0].y0*graph[0].axis[1].dfx/(object[0].y1 - object[0].y0);
+  byi  =  -object[0].x0*graph[0].axis[0].dfy/(object[0].x1 - object[0].x0);
+  byj  =  graph[0].axis[1].fy - object[0].y0*graph[0].axis[1].dfy/(object[0].y1 - object[0].y0);  
+
+  bx = bxi + bxj;
+  by = byi + byj;
+  
+  /* below here, code is identical with DrawObjects */
+  /**** points are scaled by object.z ***/
+  if (object[0].size < 0) {
+    d = 0.5 * (graphic->dx + graphic->dy) * 0.01;
+    x = object[0].x; y = object[0].y; z = object[0].z;
+    if (object[0].ptype == 0) {	/* filled box */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    FillRectangle (sx, sy, 2*d*z[i], 2*d*z[i]);
+	  }
+      }
+    }
+    if (object[0].ptype == 1) {	/* open box */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    DrawRectangle (sx, sy, 2*d*z[i], 2*d*z[i]);
+	  }
+      }
+    }
+    if (object[0].ptype == 2) { /* cross */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    DrawLine (sx - d*z[i], sy, sx + d*z[i], sy);
+	    DrawLine (sx, sy - d*z[i], sx, sy + d*z[i]);
+	  }
+      }
+    }
+    if (object[0].ptype == 3) {	/* x */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    DrawLine (sx + d*z[i], sy - d*z[i], sx - d*z[i], sy + d*z[i]);
+	    DrawLine (sx - d*z[i], sy - d*z[i], sx + d*z[i], sy + d*z[i]);
+	  }
+      }
+    }
+    if (object[0].ptype == 4) {	/* filled triangle */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    FillTriangle (sx - d*z[i], sy - 0.58*d*z[i], sx + d*z[i], sy - 0.58*d*z[i], sx, sy + 1.15*d*z[i]);
+	    /*
+	    DrawLine (sx - d*z[i], sy + 0.58*d*z[i], sx + d*z[i], sy + 0.58*d*z[i]);
+	    DrawLine (sx + d*z[i], sy + 0.58*d*z[i], sx,          sy - 1.15*d*z[i]);
+	    DrawLine (sx,          sy - 1.15*d*z[i], sx - d*z[i], sy + 0.58*d*z[i]);
+	    */
+	  }
+      }
+    }
+    if (object[0].ptype == 5) {	/* open triangle */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    DrawLine (sx - d*z[i], sy + 0.58*d*z[i], sx + d*z[i], sy + 0.58*d*z[i]);
+	    DrawLine (sx + d*z[i], sy + 0.58*d*z[i], sx,          sy - 1.15*d*z[i]);
+	    DrawLine (sx,          sy - 1.15*d*z[i], sx - d*z[i], sy + 0.58*d*z[i]);
+	  }
+      }
+    }
+    if (object[0].ptype == 6) {	/* Y */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    DrawLine (sx, sy, sx - d*z[i], sy + 0.58*d*z[i]);
+	    DrawLine (sx, sy, sx + d*z[i], sy + 0.58*d*z[i]);
+	    DrawLine (sx, sy, sx,          sy - 1.15*d*z[i]);
+	  }
+      }
+    }
+    if (object[0].ptype == 7) {	/* 0 */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    DrawCircle (sx, sy, d*z[i]);
+	  }
+      }
+    }
+    if (object[0].ptype == 100) {	/* connect a pair of points */
+      for (i = 0; i + 1 < object[0].Npts; i+=2) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx1 = x[i]*mxi + y[i]*mxj + bx;
+	sy1 = x[i]*myi + y[i]*myj + by;
+	sx2 = x[i+1]*mxi + y[i+1]*mxj + bx;
+	sy2 = x[i+1]*myi + y[i+1]*myj + by;
+	DrawLine (sx1, sy1, sx2, sy2);
+      }
+    }
+  } else {
+    d = object[0].size * 0.5 * (graphic->dx + graphic->dy) * 0.003;
+    x = object[0].x; y = object[0].y;
+    if (object[0].ptype == 0) {	/* filled box */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    FillRectangle (sx, sy, 2*d, 2*d);
+	  }
+      }
+    }
+    if (object[0].ptype == 1) {		/* open box */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+   	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    DrawRectangle (sx, sy, 2*d, 2*d);
+	  }
+      }
+    }
+    if (object[0].ptype == 2) { /* cross */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    DrawLine (sx - d, sy, sx + d, sy);
+	    DrawLine (sx, sy - d, sx, sy + d);
+	  }
+      }
+    }
+    if (object[0].ptype == 3) {		/* x */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    DrawLine (sx + d, sy - d, sx - d, sy + d);
+	    DrawLine (sx - d, sy - d, sx + d, sy + d);
+	  }
+      }
+    }
+    if (object[0].ptype == 4) {	/* filled triangle */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    /*
+	    DrawLine (sx - d, sy + 0.58*d, sx + d, sy + 0.58*d);
+	    DrawLine (sx + d, sy + 0.58*d, sx,     sy - 1.15*d);
+	    DrawLine (sx,     sy - 1.15*d, sx - d, sy + 0.58*d);
+	    */
+	    FillTriangle (sx - d, sy - 0.58*d, sx + d, sy - 0.58*d, sx, sy + 1.15*d);
+	  }
+      }
+    }
+    if (object[0].ptype == 5) {	/* open triangle */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    DrawLine (sx - d, sy - 0.58*d, sx + d, sy - 0.58*d);
+	    DrawLine (sx + d, sy - 0.58*d, sx,     sy + 1.15*d);
+	    DrawLine (sx,     sy + 1.15*d, sx - d, sy - 0.58*d);
+	  }
+      }
+    }
+    if (object[0].ptype == 6) {	/* Y */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    DrawLine (sx, sy, sx - d, sy - 0.58*d);
+	    DrawLine (sx, sy, sx + d, sy - 0.58*d);
+	    DrawLine (sx, sy, sx,     sy + 1.15*d);
+	  }
+      }
+    }
+    if (object[0].ptype == 7) {	/* 0 */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    DrawCircle (sx, sy, d);
+	  }
+      }
+    }
+    if (object[0].ptype == 100) {	
+      for (i = 0; i + 1 < object[0].Npts; i+=2) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx1 = x[i]*mxi + y[i]*mxj + bx;
+	sy1 = x[i]*myi + y[i]*myj + by;
+	sx2 = x[i+1]*mxi + y[i+1]*mxj + bx;
+	sy2 = x[i+1]*myi + y[i+1]*myj + by;
+	DrawLine (sx1, sy1, sx2, sy2);
+      }
+    }
+  }
+}
+    
+/*******/
+void PSXErrors (KapaGraphWidget *graph, Gobjects *object, FILE *f) {
+  
+  int i, bar;
+  float *x, *y, *dxm, *dxp;
+  double mxi, mxj, myi, myj, bxi, bxj, byi, byj, bx, by;
+  double sx0, sy0, sx1, sy1, sz, sx10, sx11;
+
+  mxi = graph[0].axis[0].dfx / (object[0].x1 - object[0].x0);
+  mxj = graph[0].axis[1].dfx / (object[0].y1 - object[0].y0);
+  myi = graph[0].axis[0].dfy / (object[0].x1 - object[0].x0);
+  myj = graph[0].axis[1].dfy / (object[0].y1 - object[0].y0);
+  
+  bxi  =  graph[0].axis[0].fx - object[0].x0*graph[0].axis[0].dfx/(object[0].x1 - object[0].x0);
+  bxj  =  -object[0].y0*graph[0].axis[1].dfx/(object[0].y1 - object[0].y0);
+  byi  =  -object[0].x0*graph[0].axis[0].dfy/(object[0].x1 - object[0].x0);
+  byj  =  graph[0].axis[1].fy - object[0].y0*graph[0].axis[1].dfy/(object[0].y1 - object[0].y0);
+  
+  bx = bxi + bxj;
+  by = byi + byj;
+  
+  x = object[0].x; y = object[0].y; dxp = object[0].dxp; dxm = object[0].dxm; 
+  bar = object[0].ebar; sz = object[0].size*graph[0].axis[1].dfy*0.03;
+   
+  for (i = 0; i < object[0].Npts; i++) {
+    if (!(finite(x[i]) && finite(y[i]) && finite(dxp[i]))) continue;
+    sx0 = x[i]*mxi + y[i]*mxj + bx;
+    sy0 = x[i]*myi + y[i]*myj + by;
+    sx1 = (x[i] + dxp[i])*mxi + y[i]*mxj + bx;
+    sy1 = (x[i] + dxp[i])*myi + y[i]*myj + by;
+    if (((sx0 > graph[0].axis[0].fx) && (sx0 < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	 (sy0 < graph[0].axis[1].fy) && (sy0 > graph[0].axis[1].fy + graph[0].axis[1].dfy)) ||
+	((sx1 > graph[0].axis[0].fx) && (sx1 < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	 (sy1 < graph[0].axis[1].fy) && (sy1 > graph[0].axis[1].fy + graph[0].axis[1].dfy)))
+      {
+	DrawLine (sx0, sy0, sx1, sy1);
+	if (bar) {
+	  sx10 = sy1 - sz;
+	  sx11 = sy1 + sz;
+	  DrawLine (sx1, sx10, sx1, sx11);
+	}
+      }
+    if (!(finite(x[i]) && finite(y[i]) && finite(dxm[i]))) continue;
+    sx0 = x[i]*mxi + y[i]*mxj + bx;
+    sy0 = x[i]*myi + y[i]*myj + by;
+    sx1 = (x[i] - dxm[i])*mxi + y[i]*mxj + bx;
+    sy1 = (x[i] - dxm[i])*myi + y[i]*myj + by;
+    if (((sx0 > graph[0].axis[0].fx) && (sx0 < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	 (sy0 < graph[0].axis[1].fy) && (sy0 > graph[0].axis[1].fy + graph[0].axis[1].dfy)) ||
+	((sx1 > graph[0].axis[0].fx) && (sx1 < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	 (sy1 < graph[0].axis[1].fy) && (sy1 > graph[0].axis[1].fy + graph[0].axis[1].dfy)))
+      {
+	DrawLine (sx0, sy0, sx1, sy1);
+	if (bar) {
+	  sx10 = sy1 - sz;
+	  sx11 = sy1 + sz;
+	  DrawLine (sx1, sx10, sx1, sx11);
+	}
+      }
+  }
+}
+
+    
+/*******/
+void PSYErrors (KapaGraphWidget *graph, Gobjects *object, FILE *f) {
+  
+  int i, bar;
+  float *x, *y, *dym, *dyp;
+  double mxi, mxj, myi, myj, bxi, bxj, byi, byj, bx, by;
+  double sx0, sy0, sx1, sy1, sz, sx10, sx11;
+  
+  mxi = graph[0].axis[0].dfx / (object[0].x1 - object[0].x0);
+  mxj = graph[0].axis[1].dfx / (object[0].y1 - object[0].y0);
+  myi = graph[0].axis[0].dfy / (object[0].x1 - object[0].x0);
+  myj = graph[0].axis[1].dfy / (object[0].y1 - object[0].y0);
+  
+  bxi  =  graph[0].axis[0].fx - object[0].x0*graph[0].axis[0].dfx/(object[0].x1 - object[0].x0);
+  bxj  =  -object[0].y0*graph[0].axis[1].dfx/(object[0].y1 - object[0].y0);
+  byi  =  -object[0].x0*graph[0].axis[0].dfy/(object[0].x1 - object[0].x0);
+  byj  =  graph[0].axis[1].fy - object[0].y0*graph[0].axis[1].dfy/(object[0].y1 - object[0].y0);
+  
+  bx = bxi + bxj;
+  by = byi + byj;
+  
+  x = object[0].x; y = object[0].y; dyp = object[0].dyp; dym = object[0].dym; 
+  bar = object[0].ebar; sz = object[0].size*graph[0].axis[0].dfx*0.03;
+  
+  for (i = 0; i < object[0].Npts; i++) {
+    if (!(finite(x[i]) && finite(y[i]) && finite(dyp[i]))) continue;
+    sx0 = x[i]*mxi + y[i]*mxj + bx;
+    sy0 = x[i]*myi + y[i]*myj + by;
+    sx1 = x[i]*mxi + (y[i] + dyp[i])*mxj + bx;
+    sy1 = x[i]*myi + (y[i] + dyp[i])*myj + by;
+    if (((sx0 > graph[0].axis[0].fx) && (sx0 < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	 (sy0 < graph[0].axis[1].fy) && (sy0 > graph[0].axis[1].fy + graph[0].axis[1].dfy)) ||
+	((sx1 > graph[0].axis[0].fx) && (sx1 < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	 (sy1 < graph[0].axis[1].fy) && (sy1 > graph[0].axis[1].fy + graph[0].axis[1].dfy)))
+      {
+	DrawLine (sx0, sy0, sx1, sy1);
+	if (bar) {
+	  sx10 = sx1 - sz;
+	  sx11 = sx1 + sz;
+	  DrawLine (sx10, sy1, sx11, sy1);
+	}
+      }
+    if (!(finite(x[i]) && finite(y[i]) && finite(dym[i]))) continue;
+    sx0 = x[i]*mxi + y[i]*mxj + bx;
+    sy0 = x[i]*myi + y[i]*myj + by;
+    sx1 = x[i]*mxi + (y[i] - dym[i])*mxj + bx;
+    sy1 = x[i]*myi + (y[i] - dym[i])*myj + by;
+    if (((sx0 > graph[0].axis[0].fx) && (sx0 < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	 (sy0 < graph[0].axis[1].fy) && (sy0 > graph[0].axis[1].fy + graph[0].axis[1].dfy)) ||
+	((sx1 > graph[0].axis[0].fx) && (sx1 < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	 (sy1 < graph[0].axis[1].fy) && (sy1 > graph[0].axis[1].fy + graph[0].axis[1].dfy)))
+      {
+	DrawLine (sx0, sy0, sx1, sy1);
+	if (bar) {
+	  sx10 = sx1 - sz;
+	  sx11 = sx1 + sz;
+	  DrawLine (sx10, sy1, sx11, sy1);
+	}
+      }
+  }
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/PSOverlay.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/PSOverlay.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/PSOverlay.c	(revision 16062)
@@ -0,0 +1,68 @@
+# include "Ximage.h"
+
+void PSOverlay (KapaImageWidget *image, int N, FILE *f, int extra) {
+
+  int i;
+  double X, Y, dX, dY;
+  int Xmin, Ymin, Xmax, Ymax;
+  double expand, X0, Y0;
+ 
+  expand = 1.0;
+  if (image[0].expand > 0) {
+    expand = 1 / (1.0*image[0].expand);
+  }
+  if (image[0].expand < 0) {
+    expand = fabs((double)image[0].expand);
+  }
+
+  Image_to_Screen (&X0, &Y0, 0.0, 0.0, image);
+  X0 -= image[0].picture.x;
+  Y0 -= image[0].picture.y;
+
+  Xmin = 0;
+  Ymin = 0;
+  Xmax = image[0].picture.dx;
+  Ymax = image[0].picture.dy;
+
+  for (i = 0; i < image[0].overlay[N].Nobjects; i++) {
+    X  = (image[0].overlay[N].objects[i].x)/expand + X0;
+    Y =  Ymax - (image[0].overlay[N].objects[i].y)/expand - Y0;
+    dX = (image[0].overlay[N].objects[i].dx)/expand;
+    dY = (image[0].overlay[N].objects[i].dy)/expand;
+    
+    switch (image[0].overlay[N].objects[i].type) {
+      case KII_OVERLAY_LINE:
+	if (((X < Xmin) && (X + dX < Xmin)) || ((X > Xmax) && (X + dX > Xmax)) ||
+	    ((Y < Ymin) && (Y + dY < Ymin)) || ((Y > Ymax) && (Y + dY > Ymax))) {
+	  break;
+	}
+	fprintf (f, " %6.1f %6.1f %6.1f %6.1f L\n", X + extra, Y + extra, (X+dX + extra), (Y-dY + extra));
+	break;
+      case KII_OVERLAY_TEXT:
+	if (((X < Xmin) && (X + dX < Xmin)) || ((X > Xmax) && (X + dX > Xmax)) ||
+	    ((Y < Ymin) && (Y + dY < Ymin)) || ((Y > Ymax) && (Y + dY > Ymax))) {
+	  break;
+	}
+	fprintf (f, "(%s) %6.1f %6.1f T\n", image[0].overlay[N].objects[i].text, X + extra, Y + extra); 
+	break;
+      case KII_OVERLAY_BOX:
+	if (((X - 0.5*dX < Xmin) && (X + 0.5*dX < Xmin)) || ((X - 0.5*dX > Xmax) && (X + 0.5*dX > Xmax)) ||
+	    ((Y - 0.5*dY < Ymin) && (Y + 0.5*dY < Ymin)) || ((Y - 0.5*dY > Ymax) && (Y + 0.5*dY > Ymax))) {
+	  break;
+	}
+	fprintf (f, " %6.1f %6.1f %6.1f %6.1f B\n", (dX + 2*extra), (dY + 2*extra), (X - 0.5*dX - extra), (Y - 0.5*dY - extra));
+	break;
+      case KII_OVERLAY_CIRCLE:
+	if (((X - dX < Xmin) && (X + dX < Xmin)) || ((X - dX > Xmax) && (X + dX > Xmax)) ||
+	    ((Y - dY < Ymin) && (Y + dY < Ymin)) || ((Y - dY > Ymax) && (Y + dY > Ymax))) {
+	  break;
+	}
+	// XXX add in the rotated ellipse version (rotate in PS space)
+	fprintf (f, " %6.1f %6.1f %6.1f C\n", X, Y, fabs(dX + extra));
+	break;
+      default:
+	fprintf (stderr, "skipping unknown object\n");
+	break;
+    }
+  }
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/PSPixmap.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/PSPixmap.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/PSPixmap.c	(revision 16062)
@@ -0,0 +1,183 @@
+# include "Ximage.h"
+
+void PSPixmap8 (Graphic *graphic, KapaImageWidget *image, FILE *f) {
+
+  int i, k, m, val;
+  double Nchar, Npix, start, slope, frac;
+  unsigned char *buff;
+  unsigned long back;
+
+  Nchar = 255.0;
+  Npix = graphic[0].Npixels;
+  frac = Nchar / Npix;
+  /* start at the last line, print lines in decending order */
+  buff = (unsigned char *)image[0].picture.data + image[0].picture.dx*(image[0].picture.dy - 1);
+  slope = image[0].image[0].slope;
+  start = image[0].image[0].start;
+  back  = graphic[0].back;
+
+  for (i = 0; i < image[0].picture.dy; i++) {
+    for (k = 0; k < image[0].picture.dx; k++, buff++) {
+      if (*buff == back) 
+	val = Nchar;
+      else {
+	for (m = 0; (graphic[0].cmap[m].pixel != *buff) && (m < Npix); m++);
+	val = Nchar - frac * MIN (MAX (start + m * slope, 0), Npix);
+      }
+      fprintf (f, "%02x", val);
+      if (!((k+1) % 40)) fprintf (f, "\n"); 
+    }
+    fprintf (f, "\n");
+    buff -= 2*image[0].picture.dx;
+  }
+  return;
+}
+
+void PSPixmap16 (Graphic *graphic, KapaImageWidget *image, FILE *f) {
+
+  int i, k, m, val;
+  double Nchar, Npix, start, slope, frac;
+  unsigned short *buff;
+  unsigned long back;
+
+  Nchar = 255.0;
+  Npix = graphic[0].Npixels;
+  frac = Nchar / Npix;
+  /* start at the last line, print lines in decending order */
+  buff = (unsigned short *)image[0].picture.data + image[0].picture.dx*(image[0].picture.dy - 1);
+  slope = image[0].image[0].slope;
+  start = image[0].image[0].start;
+  back  = graphic[0].back;
+
+  for (i = 0; i < image[0].picture.dy; i++) {
+    for (k = 0; k < image[0].picture.dx; k++, buff++) {
+      if (*buff == back) 
+	val = Nchar;
+      else {
+	for (m = 0; (graphic[0].cmap[m].pixel != *buff) && (m < Npix); m++);
+	val = Nchar - frac * MIN (MAX (start + m * slope, 0), Npix);
+      }
+      fprintf (f, "%02x", val);
+      if (!((k+1) % 40)) fprintf (f, "\n"); 
+    }
+    fprintf (f, "\n");
+    buff -= 2*image[0].picture.dx;
+  }
+  return;
+}
+
+void PSPixmap24 (Graphic *graphic, KapaImageWidget *image, FILE *f) {
+
+  int i, k, m, dx, dy, val, extra;
+  unsigned char *buff;
+  unsigned long color, byte;
+  double Nchar, Npix, start, slope, frac;
+  unsigned long back;
+
+  Nchar = 255.0;
+  Npix = graphic[0].Npixels;
+  frac = Nchar / Npix;
+  dx = image[0].picture.dx;
+  dy = image[0].picture.dy;
+  extra = 4 - (dx * 3) % 4;
+  /* start at the last line, print lines in decending order */
+  buff = (unsigned char *)&image[0].picture.data[(dy - 1)*(3*dx + extra)];
+  slope = image[0].image[0].slope;
+  start = image[0].image[0].start;
+  back  = graphic[0].back;
+
+  for (i = 0; i < dy; i++) {
+    for (k = 0; k < dx; k++, buff+=3) {
+      if (*buff == back) {
+	val = Nchar;
+      } else {
+	color = 0;
+	byte = buff[2];
+	color = (byte << 16);
+	byte = buff[1];
+	color |= (byte << 8);
+	byte = buff[0];
+	color |= byte;
+	for (m = 0; (graphic[0].cmap[m].pixel != color) && (m < Npix); m++);
+	val = Nchar - frac * MIN (MAX (start + m * slope, 0), Npix);
+      }
+      fprintf (f, "%02x", val);
+      if (!((k+1) % 40)) fprintf (f, "\n"); 
+    }
+    fprintf (f, "\n");
+    buff -= 2*3*dx + extra;
+  }
+  return;
+}
+
+void PSPixmap32 (Graphic *graphic, KapaImageWidget *image, FILE *f) {
+
+  int i, k, m, val;
+  double Nchar, Npix, start, slope, frac;
+  unsigned int *buff;
+  unsigned long back;
+
+  Nchar = 255.0;
+  Npix = graphic[0].Npixels;
+  frac = Nchar / Npix;
+  /* start at the last line, print lines in decending order */
+  buff = (unsigned int *)image[0].picture.data + image[0].picture.dx*(image[0].picture.dy - 1);
+  slope = image[0].image[0].slope;
+  start = image[0].image[0].start;
+  back  = graphic[0].back;
+
+  for (i = 0; i < image[0].picture.dy; i++) {
+    for (k = 0; k < image[0].picture.dx; k++, buff++) {
+      if (*buff == back) 
+	val = Nchar;
+      else {
+	for (m = 0; (graphic[0].cmap[m].pixel != *buff) && (m < Npix); m++);
+	val = Nchar - frac * MIN (MAX (start + m * slope, 0), Npix);
+      }
+      fprintf (f, "%02x", val);
+      if (!((k+1) % 40)) fprintf (f, "\n"); 
+    }
+    fprintf (f, "\n");
+    buff -= 2*image[0].picture.dx;
+  }
+  return;
+}
+
+# if (0)
+// XXX needs work!
+void PSPixmap32_RGB (Graphic *graphic, KapaImageWidget *image, FILE *f) {
+
+  int i, k, m, val;
+  double Nchar, Npix, start, slope, frac;
+  unsigned int *buff;
+  unsigned long back;
+  unsigned char 
+
+  ALLOCATE (pixelR, unsigned char, graphic[0].Npixels);
+  ALLOCATE (pixelG, unsigned char, graphic[0].Npixels);
+  ALLOCATE (pixelB, unsigned char, graphic[0].Npixels);
+
+  /** cmap[i].pixel must be defined even if X is not used **/
+  for (i = 0; i < graphic[0].Npixels; i++) { /* set up pixel array */
+    pixelR[i] = graphic[0].cmap[i].red >> 8;
+    pixelG[i] = graphic[0].cmap[i].green >> 8;
+    pixelB[i] = graphic[0].cmap[i].blue >> 8;
+  }
+
+  for (i = 0; i < image[0].picture.dy; i++) {
+    for (k = 0; k < image[0].picture.dx; k++, buff++) {
+      if (*buff == back) 
+	val = Nchar;
+      else {
+	for (m = 0; (graphic[0].cmap[m].pixel != *buff) && (m < Npix); m++);
+	val = Nchar - frac * MIN (MAX (start + m * slope, 0), Npix);
+      }
+      fprintf (f, "%02x", val);
+      if (!((k+1) % 40)) fprintf (f, "\n"); 
+    }
+    fprintf (f, "\n");
+    buff -= 2*image[0].picture.dx;
+  }
+  return;
+}
+# endif
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/PSTextlines.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/PSTextlines.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/PSTextlines.c	(revision 16062)
@@ -0,0 +1,36 @@
+# include "Ximage.h"
+  
+void PSTextlines (KapaGraphWidget *graph, FILE *f) {
+
+  int i, x, y, size;
+  double angle;
+  char *fontname;
+  Graphic *graphic;
+
+  graphic = GetGraphic();
+
+  fontname = GetRotFont (&size);
+  for (i = 0; i < graph[0].Ntextline; i++) {
+    if (strcmp (graph[0].textline[i].text, "")) {
+      angle = graph[0].textline[i].angle;
+      x = graph[0].textline[i].x;
+      y = graphic->dy - graph[0].textline[i].y;
+      SetRotFont (graph[0].textline[i].font, graph[0].textline[i].size);
+      PSRotText (f, x, y, graph[0].textline[i].text, 5, angle);
+    }
+  }
+  SetRotFont (fontname, size);
+}
+
+  /* pos values
+            
+ 4____2___5 
+  |       | 
+  |       | 
+ 1|   8   |3
+  |       |
+  |       |
+  ---------
+  6   0   7
+
+  */
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/PSimage.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/PSimage.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/PSimage.c	(revision 16062)
@@ -0,0 +1,61 @@
+# include "Ximage.h"
+
+int PSimage (KapaImageWidget *image, FILE *f) {
+  
+  int i;
+  Graphic *graphic;
+
+  if (!USE_XWINDOW) {
+    fprintf (stderr, "PSimage not working yet for no X mode\n");
+    return (TRUE);
+  }
+
+  graphic = GetGraphic();
+
+  fprintf (f, " newpath 0 0 moveto %d 0 lineto %d %d lineto 0 %d lineto closepath clip\n\n", 
+	   image[0].picture.dx, image[0].picture.dx, image[0].picture.dy, image[0].picture.dy);
+  fprintf (f, "gsave %% encloses image\n");
+  fprintf (f, "%d %d 8\n", image[0].picture.dx, image[0].picture.dy);
+  fprintf (f, "[1 0 0 1 0 0]\n");
+  fprintf (f, "{currentfile %d string readhexstring pop} image\n\n", image[0].picture.dx);
+
+  /******** First we draw the picture itself ********/
+  /* in !USE_XWINDOW, we'll have to change this to use the JPEG function */
+  switch (graphic[0].Nbits) {
+  case 8:
+    PSPixmap8 (graphic, image, f);
+    break;
+  case 16:
+    PSPixmap16 (graphic, image, f);
+    break;
+  case 24:
+    PSPixmap24 (graphic, image, f);
+    break;
+  case 32:
+    PSPixmap32 (graphic, image, f);
+    break;
+  }
+
+  fprintf (f, "grestore %% end of image\n");
+  fprintf (f, "stroke\n");
+
+  // should we have a 'gsave / grestore' container here?
+  fprintf (f, "%% plot overlay objects\n");
+  fprintf (f, "1 setgray\n");
+
+  for (i = 0; i < NOVERLAYS; i++) {
+    if (image[0].overlay[i].active) {
+      fprintf (f, "%% overlay %d\n", i);
+      PSOverlay (image, i, f, 0);
+    }
+  }
+  fprintf (f, "0 setgray\n");
+  for (i = 0; i < NOVERLAYS; i++) {
+    if (image[0].overlay[i].active) {
+      fprintf (f, "%% overlay %d\n", i);
+      PSOverlay (image, i, f, 1);
+    }
+  }
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/PSit.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/PSit.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/PSit.c	(revision 16062)
@@ -0,0 +1,107 @@
+# include "Ximage.h"
+# define XOFFSET 60
+# define YOFFSET 60
+
+static char *name = "$Name: not supported by cvs2svn $";
+static Graphic *graphic;
+
+int PScommand (int sock) {
+
+  int status, scaleMode, pageMode;
+  char filename[1024], pagename[1024];
+
+  /* expect a line telling the number of bytes and a filename */
+  KiiScanMessage (sock, "%s %s %d %d", filename, pagename, &scaleMode, &pageMode);
+  status = PSit (filename, pagename, scaleMode, pageMode);
+  return (status);
+}
+
+int PSit (char *filename, char *pagename, int scaleMode, int pageMode) {
+
+  int i, Nsection;
+  double scale;
+  FILE *f;
+  char *version;
+  Section *section;
+
+  graphic = GetGraphic();
+
+  if (pageMode == KAPA_PS_NEWPAGE) {
+    f = fopen (filename, "a+");
+  } else {
+    f = fopen (filename, "w");
+  }
+  if (f == NULL) {
+    fprintf (stderr, "can't open output file %s\n", filename);
+    return (TRUE);  /* true because otherwise it quits kapa! */
+  }
+
+  /* two scaling options: expand to fit page / keep absolute size */ 
+  if (scaleMode) {
+    scale = MIN (fabs(500.0 / graphic->dx), fabs (700.0 / graphic->dy));
+  } else {
+    scale = 72.0 / 96.0; /* ratio of screen pixels to points */
+  }
+
+  switch (pageMode) {
+    case KAPA_PS_NEWPLOT:
+      fprintf (f, "%%!PS-Adobe-2.0 EPSF-2.0\n");
+      fprintf (f, "%%%%Title: %s\n", filename);
+      version = strip_version (name);
+      fprintf (f, "%%%%Creator: Kapa (%s)\n", version);
+      free (version);
+      fprintf (f, "%%%%BoundingBox: %d %d %.0f %.0f\n", 
+	       XOFFSET, YOFFSET, XOFFSET + scale*graphic->dx, YOFFSET + scale*graphic->dy);
+      fprintf (f, "%%%%Pages: 1\n");
+      fprintf (f, "%%%%DocumentFonts:\n");
+      fprintf (f, "%%%%EndComments\n");
+      fprintf (f, "%%%%EndProlog\n");
+      fprintf (f, "%%%%Page: %s\n\n", pagename);
+      break;
+
+    case KAPA_PS_NEWPAGE:
+      fprintf (f, "%%%%Page: %s\n\n", pagename);
+      break;
+
+    case KAPA_PS_RAWPAGE:
+      break;
+  } 
+  fprintf (f, "gsave %% encloses picture\n");
+  fprintf (f, "%% local abbreviations\n");
+  fprintf (f, "/Times-Roman findfont 14 scalefont setfont\n");
+  fprintf (f, "/T {moveto show stroke} def\n");
+  fprintf (f, "/B { newpath moveto dup 0 exch rlineto exch dup 0 rlineto exch -1 mul\n");
+  fprintf (f, " 0 exch rlineto -1 mul 0 rlineto closepath stroke } def\n");
+  fprintf (f, "/F { newpath moveto dup 0 exch rlineto exch dup 0 rlineto exch -1 mul\n");
+  fprintf (f, " 0 exch rlineto -1 mul 0 rlineto closepath fill stroke } def\n");
+  fprintf (f, "/C {0 360 arc stroke} def\n");
+  fprintf (f, "/L {newpath moveto lineto stroke} def\n\n");
+  fprintf (f, "/TF {newpath moveto lineto lineto fill stroke} def\n\n");
+
+  if (pageMode != KAPA_PS_RAWPAGE) {
+    fprintf (f, " %d %d translate\n", XOFFSET, YOFFSET);
+    fprintf (f, "  %f  %f scale\n", scale, scale);
+  }
+
+  Nsection = GetNumberOfSections ();
+  for (i = 0; i < Nsection; i++) {
+    section = GetSectionByNumber (i);
+    if (section->graph) {
+      PSFrame (section->graph, f); 
+      PSObjects (section->graph, f);
+      PSLabels (section->graph, f);
+      PSTextlines (section->graph, f);
+    }
+    if (section->image) {
+      PSimage (section->image, f);
+    }
+  }
+  
+  fprintf (f, "grestore %% end of picture\n");
+
+  if (pageMode != KAPA_PS_RAWPAGE) fprintf (f, "showpage\n");
+
+  fclose (f);
+  return (TRUE);
+}
+
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/PaintOverlay.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/PaintOverlay.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/PaintOverlay.c	(revision 16062)
@@ -0,0 +1,84 @@
+# include "Ximage.h"
+
+void PaintOverlay (Graphic *graphic, KapaImageWidget *image, int N) {
+
+  int i;
+  int dX, dY, dx, dy;
+  int x, y, X, Y, Xmin, Ymin, Xmax, Ymax, Xrange, Yrange;
+  double t, expand, X0, Y0;
+ 
+  XSetForeground (graphic[0].display, graphic[0].gc, image[0].overlay[N].color);
+  
+  expand = 1.0;
+  if (image[0].expand > 0) {
+    expand = 1 / (1.0*image[0].expand);
+  }
+  if (image[0].expand < 0) {
+    expand = fabs((double)image[0].expand);
+  }
+
+  Image_to_Screen (&X0, &Y0, 0.0, 0.0, image);
+
+  Xmin = image[0].picture.x;
+  Ymin = image[0].picture.y;
+  Xmax = image[0].picture.x + image[0].picture.dx;
+  Ymax = image[0].picture.y + image[0].picture.dy;
+  Xrange = image[0].picture.dx;
+  Yrange = image[0].picture.dy;
+
+  for (i = 0; i < image[0].overlay[N].Nobjects; i++) {
+    X  = image[0].overlay[N].objects[i].x/expand + X0;
+    Y =  image[0].overlay[N].objects[i].y/expand + Y0;
+    dX = image[0].overlay[N].objects[i].dx/expand;
+    dY = image[0].overlay[N].objects[i].dy/expand;
+    if ((X + dX < Xmin) || (X - dX > Xmax) ||
+	(Y + dY < Ymin) || (Y - dY > Ymax)) {
+      continue;
+    }
+
+    /* for a LINE, (x, y) is the start, (dx, dy) is the distance to end
+       for a CIRCLE (x, y) is the center, (dx, dy) is the radius 
+       for a BOX (x, y) is the center, (dx, dy) is the width */
+
+    switch (image[0].overlay[N].objects[i].type) {
+      case KII_OVERLAY_LINE:
+	// the angle makes no sense for a line...
+	XDrawLine (graphic[0].display, graphic[0].window, graphic[0].gc, X, Y, (X+dX), (Y+dY));
+	break;
+      case KII_OVERLAY_TEXT:
+	// XXX currently we ignore the rectangle angle
+	XDrawString (graphic[0].display, graphic[0].window, graphic[0].gc, X, Y, image[0].overlay[N].objects[i].text, strlen(image[0].overlay[N].objects[i].text));
+	break;
+      case KII_OVERLAY_BOX:
+	dx = MAX (abs(dX),2) / 2;
+	dy = MAX (abs(dY),2) / 2;
+	// XXX currently we ignore the rectangle angle
+	XDrawRectangle (graphic[0].display, graphic[0].window, graphic[0].gc, (X - dx), (Y - dy), 2*dx, 2*dy);
+	break;
+      case KII_OVERLAY_CIRCLE:
+	dx = MAX (abs(dX),2);
+	dy = MAX (abs(dY),2);
+	if (image[0].overlay[N].objects[i].angle == 0.0) {
+	  XDrawArc (graphic[0].display, graphic[0].window, graphic[0].gc, (X - dx), (Y - dy), 2*dx, 2*dy, 0, 23040);
+	} else {
+	  // very stupid rotate ellipse drawing:
+	  double angle = image[0].overlay[N].objects[i].angle * RAD_DEG;
+	  double cs = cos(angle);
+	  double sn = sin(angle);
+	  // XXX dt should be based on the size of the ellipse...
+	  for (t = 0; t < 2*M_PI; t+=0.05) {
+	    x = X + dx*cos(t)*cs + dy*sin(t)*sn;
+	    y = Y - dx*cos(t)*sn + dy*sin(t)*cs;
+	    XDrawPoint (graphic[0].display, graphic[0].window, graphic[0].gc, x, y);
+	  }
+	}
+	break;
+      default:
+	fprintf (stderr, "skipping unknown object\n");
+	break;
+    }
+  }
+  
+  XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].fore);
+  return;
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/PaintTickmarks.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/PaintTickmarks.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/PaintTickmarks.c	(revision 16062)
@@ -0,0 +1,54 @@
+# include "Ximage.h"
+
+void PaintTickmarks (Graphic *graphic, KapaImageWidget *image) {
+
+  int i;
+  int X, Y, dX, dY;
+  int Xmin, Ymin, Xmax, Ymax, Xrange, Yrange;
+ 
+  XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].fore);
+
+  Xmin = image[0].picture.x;
+  Ymin = image[0].picture.y;
+  Xmax = image[0].picture.x + image[0].picture.dx;
+  Ymax = image[0].picture.y + image[0].picture.dy;
+  Xrange = image[0].picture.dx;
+  Yrange = image[0].picture.dy;
+
+  for (i = 0; i < image[0].tickmarks.Nobjects; i++) {
+    X  = image[0].tickmarks.objects[i].x * Xrange + Xmin;
+    Y  = image[0].tickmarks.objects[i].y * Yrange + Ymin;
+    dX = image[0].tickmarks.objects[i].dx * Xrange;
+    dY = image[0].tickmarks.objects[i].dy * Yrange;
+
+    switch (image[0].overlay[0].objects[i].type) {
+      case KII_OVERLAY_LINE:
+	XDrawLine (graphic[0].display, graphic[0].window, graphic[0].gc, X, Y, (X+dX), (Y+dY));
+	break;
+      case KII_OVERLAY_TEXT:
+	if (image[0].tickmarks.objects[i].dy == 0) {
+	    XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].back);
+	    XFillRectangle (graphic[0].display, graphic[0].window, graphic[0].gc, X, Y-11, 6*strlen(image[0].tickmarks.objects[i].text), 11); 
+	    XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].fore);
+	    XDrawString (graphic[0].display, graphic[0].window, graphic[0].gc, X, Y, image[0].tickmarks.objects[i].text, strlen(image[0].tickmarks.objects[i].text));
+	}
+	if (image[0].tickmarks.objects[i].dy == 90) {
+	    XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].back);
+	    XFillRectangle (graphic[0].display, graphic[0].window, graphic[0].gc, X, Y-6*strlen(image[0].tickmarks.objects[i].text), 11, 6*strlen(image[0].tickmarks.objects[i].text)); 
+	    XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].fore);
+	    /* XDrawRotString (graphic[0].display, graphic[0].window, graphic[0].gc, X, Y, image[0].tickmarks.objects[i].text, strlen(image[0].tickmarks.objects[i].text)); */
+	}
+	break;
+      case KII_OVERLAY_BOX:
+	XDrawRectangle (graphic[0].display, graphic[0].window, graphic[0].gc, (int)(X - 0.5*dX), (int)(Y - 0.5*dY), abs(dX), abs(dY));
+	break;
+      case KII_OVERLAY_CIRCLE:
+	XDrawArc (graphic[0].display, graphic[0].window, graphic[0].gc, X - dX, Y - dY, abs(2*dX), abs(2*dY), 0, 23040);
+	break;
+      default:
+	fprintf (stderr, "skipping unknown object\n");
+	break;
+    }
+  }
+  XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].fore);
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/QuitX.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/QuitX.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/QuitX.c	(revision 16062)
@@ -0,0 +1,9 @@
+# include "Ximage.h"
+
+/************** QuitX *************/
+void QuitX (Display *display, char *error_message) {
+
+  fprintf (stderr, "Error: %s\n", error_message);
+  XCloseDisplay (display);
+  exit (0);
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/Reconfig.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/Reconfig.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/Reconfig.c	(revision 16062)
@@ -0,0 +1,34 @@
+# include "Ximage.h"
+
+// XXX merge this code with Resize
+int Reconfig (XEvent *event) {
+
+  int i, Nsection, NX, NY;
+  Graphic *graphic;
+  Section *section;
+
+  graphic = GetGraphic();
+
+  // XXX keep this min limit (or modify for !USE_XWINDOW)?
+  NX = MAX(event[0].xconfigure.width, MIN_WIDTH); 
+  NY = MAX(event[0].xconfigure.height, MIN_HEIGHT); 
+
+  // if the new size is the same as the old size, do nothing.
+  if ((graphic->dx == NX) && (graphic->dy == NY)) return (TRUE);
+
+  // set the new window size
+  graphic->dx = NX; 
+  graphic->dy = NY; 
+
+  // reset the sizes for all sections
+  Nsection = GetNumberOfSections ();
+  for (i = 0; i < Nsection; i++) {
+      section = GetSectionByNumber (i);
+      SetSectionSizes (section);
+  }
+
+  if (USE_XWINDOW) XClearWindow (graphic->display, graphic->window);
+  Refresh (1);
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/Refresh.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/Refresh.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/Refresh.c	(revision 16062)
@@ -0,0 +1,29 @@
+# include "Ximage.h"
+
+void Refresh () {
+
+  int i, Nsection;
+  Graphic *graphic;
+  Section *section;
+
+  if (!USE_XWINDOW) return;
+  if (HAVE_BACKING) return;
+
+  graphic = GetGraphic();
+  
+  /* XClearWindow   (graphic.display, graphic.window); */
+  XSetForeground (graphic->display, graphic->gc, graphic->back);
+  XFillRectangle (graphic->display, graphic->window, graphic->gc, 0, 0, graphic->dx, graphic->dy);
+  XSetForeground (graphic->display, graphic->gc, graphic->fore);
+  
+  // reset the sizes for all sections
+  Nsection = GetNumberOfSections ();
+  for (i = 0; i < Nsection; i++) {
+      section = GetSectionByNumber (i);
+      DrawImage (section->image);
+      DrawGraph (section->graph);
+  }
+
+  FlushDisplay ();
+}
+
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/Remap.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/Remap.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/Remap.c	(revision 16062)
@@ -0,0 +1,21 @@
+# include "Ximage.h"
+
+void Remap (Graphic *graphic, KapaImageWidget *image) {
+
+  switch (graphic[0].Nbits) {
+  case 8:
+    Remap8  (graphic, image, &image->image->matrix);
+    break;
+  case 16:
+    Remap16 (graphic, image, &image->image->matrix);
+    break;
+  case 24:
+    Remap24 (graphic, image, &image->image->matrix);
+    break;
+  case 32:
+    Remap32 (graphic, image, &image->image->matrix);
+    break;
+  }
+
+}
+
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/Remap16.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/Remap16.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/Remap16.c	(revision 16062)
@@ -0,0 +1,178 @@
+# include "Ximage.h"
+
+static float slope = 1.0;
+static float start = 0.0;
+static int MaxValue = 255;
+
+// XXX inline this if needed
+static int PixelLookup(float value) {
+  int out;
+  out = MIN (MAX (slope * value - start, 0), MaxValue);
+  return (out);
+}
+
+void Remap16 (Graphic *graphic, KapaImageWidget *image, Matrix *matrix) {
+
+  int i, j, ii, jj;
+  int i_start, i_end, j_start, j_end;
+  int dropback;  /* this is a bit of a kludge... */
+  int dx, dy, DX, DY, pixelN;
+  double expand, Rx, Ry, X, Y;
+  int expand_in, expand_out;
+  unsigned char *out_pix, *out_pix2, *data;
+  float *imdata, *in_pix, *in_pix2;
+  unsigned char pixel1[256], pixel2[256];
+  unsigned char pixvalue1, pixvalue2;
+  unsigned long back;
+  unsigned char back1, back2;
+
+  // local array for pixel values (is this working??)
+  for (i = 0; i < 256; i++) { /* set up pixel array */
+    pixel1[i] = 0x00ff &  graphic[0].cmap[i].pixel;
+    pixel2[i] = 0x00ff & (graphic[0].cmap[i].pixel >> 8);
+  }
+  back = graphic[0].back;
+  back1 = 0x00ff & back;
+  back2 = 0x00ff & (back >> 8);
+
+  // define the color transform parameters
+  MaxValue = graphic[0].Npixels - 1;
+  if (image[0].image[0].range != 0.0) {
+    slope = graphic[0].Npixels / image[0].image[0].range;
+    start = graphic[0].Npixels * image[0].image[0].zero / image[0].image[0].range;
+  } else {
+    slope = 1.0;
+    start = image[0].image[0].zero;
+  }
+
+  // set up expansions
+  expand = expand_in = expand_out = 1.0;
+  if (image[0].expand == 0) /* set up expansions */
+    image[0].expand = 1;
+  if (image[0].expand > 0) {
+    expand = 1 / (1.0*image[0].expand);
+    expand_out = image[0].expand;
+    expand_in  = 1;
+  }
+  if (image[0].expand < 0) {
+    expand = fabs((double)image[0].expand);
+    expand_out = 1;
+    expand_in  = -image[0].expand;
+  }
+
+  // define the image boundaries
+  dx = image[0].picture.dx;
+  dy = image[0].picture.dy;
+  DX = matrix[0].Naxis[0];
+  DY = matrix[0].Naxis[1];
+
+  /* X,Y are the image coordinates of the first image pixel */
+  X = MAX(0.5*(DX - dx*expand) - image[0].X, 0);
+  if ((int)X != X) 
+    X = (int) X + 1;
+  else 
+    X = (int) X;
+  Y = MAX(0.5*(DY - dy*expand) - image[0].Y, 0);
+  if ((int)Y != Y) 
+    Y = (int) Y + 1;
+  else 
+    Y = (int) Y;
+
+  /* Rx,Ry are the screen coordinates of the first image pixel */
+  Rx = (X + image[0].X - 0.5*DX)/expand + 0.5*dx;
+  Ry = (Y + image[0].Y - 0.5*DY)/expand + 0.5*dy;
+
+  i_start = MIN (MAX (Rx, 0), dx - expand_out + 1);
+  j_start = MIN (MAX (Ry, 0), dy - expand_out + 1);
+  
+  if (image[0].expand > 0) {
+    i_end = MAX (MIN (i_start + ((int)(expand*(dx-i_start)))/expand, expand_out*(DX-X) + Rx), 0);
+    j_end = MAX (MIN (j_start + ((int)(expand*(dy-j_start)))/expand, expand_out*(DY-Y) + Ry), 0);
+  } else {
+    i_end = MAX (MIN (dx, (DX-X)/expand + Rx), 0);
+    j_end = MAX (MIN (dy, (DY-Y)/expand + Ry), 0);
+  }    
+
+  dropback = expand_out - (i_end - i_start) % expand_out;
+  if ((i_end - i_start) % expand_out == 0) dropback = 0;
+
+  data = out_pix = (unsigned char *) image[0].picture.data;
+  imdata  = (float *) matrix[0].buffer;
+  in_pix  = &imdata[DX*(int)MAX(Y,0) + (int)MAX(X,0)];
+
+  /********** below we do the mapping from buffer pixels (in) to picture pixels (out) **********/
+
+  /**** fill in bottom area ****/
+  for (j = 0; j < j_start; j++) {
+    for (i = 0; i < dx; i++, out_pix+=2) {
+      out_pix[0] = back1;
+      out_pix[1] = back2;
+    }
+  }
+  
+  for (j = j_start; j < j_end; j+= expand_out, in_pix += expand_in*DX) {
+    out_pix = &data[2*j*dx];
+
+    /**** fill in area to the left of the picture ****/
+    for (jj = 0; (i_start > 0) && (jj < expand_out); jj++) { 
+      out_pix2 = out_pix + 2*jj*dx;
+      for (i = 0; i < i_start; i++, out_pix2+=2) {
+	out_pix2[0] = back1;
+	out_pix2[1] = back2;
+      }
+    }
+    out_pix += 2*i_start;
+    
+    /*** fill in the picture region ***/
+    in_pix2 = in_pix;
+    if (expand_out == 1) {
+      for (i = i_start; i < i_end; i++, in_pix2+= expand_in, out_pix+=2) {
+	pixelN = PixelLookup(*in_pix2);
+	out_pix[0] = pixel1[pixelN];
+	out_pix[1] = pixel2[pixelN];
+      }
+    }
+    else {
+      for (i = i_start; i < i_end; i+= expand_out, in_pix2++, out_pix+= 2*expand_out) { 
+	pixelN    = PixelLookup(*in_pix2);
+	pixvalue1 = pixel1[pixelN];
+	pixvalue2 = pixel2[pixelN];
+	out_pix2 = out_pix;
+	for (jj = 0; jj < expand_out; jj++, out_pix2+=2*(dx-expand_out)) {
+	  for (ii = 0; ii < expand_out; ii++, out_pix2+=2) {
+	    out_pix2[0] = pixvalue1; 
+	    out_pix2[1] = pixvalue2; 
+	  }
+	}
+      }
+    }
+    out_pix -= 2*dropback;
+    
+    /**** fill in area to the right of the picture ****/
+    for (jj = 0; jj < expand_out; jj++) {
+      out_pix2 = out_pix + 2*jj*dx;
+      for (i = i_end; i < dx; i++, out_pix2+=2) {
+	out_pix2[0] = back1;
+	out_pix2[1] = back2;
+      }
+    }
+  } 
+  
+  /*
+  if ((j_end - j_start) % expand_out > 0)
+    out_pix -= expand_out - (j_end - j_start) % expand_out;
+  */
+  
+  out_pix = &data[2*j_end*dx];
+  /**** fill in top area ****/
+  for (j = 0; j < (dy - j_end); j++) {
+    for (i = 0; i < dx; i++, out_pix+=2) { 
+      out_pix[0] = back1;
+      out_pix[1] = back2;
+    }
+  }
+
+  image[0].picture.pix = XCreateImage (graphic[0].display, graphic[0].visual, graphic[0].depth, ZPixmap, 0, 
+					image[0].picture.data, image[0].picture.dx, image[0].picture.dy, 16, 0);
+}
+
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/Remap24.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/Remap24.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/Remap24.c	(revision 16062)
@@ -0,0 +1,188 @@
+# include "Ximage.h"
+
+static float slope = 1.0;
+static float start = 0.0;
+static int MaxValue = 255;
+
+// XXX inline this if needed
+static int PixelLookup(float value) {
+  int out;
+  out = MIN (MAX (slope * value - start, 0), MaxValue);
+  return (out);
+}
+
+void Remap24 (Graphic *graphic, KapaImageWidget *image, Matrix *matrix) {
+
+  int i, j, ii, jj;
+  int i_start, i_end, j_start, j_end;
+  int dropback, extra;  /* this is a bit of a kludge... */
+  int dx, dy, DX, DY, pixelN;
+  double expand, Rx, Ry, X, Y;
+  int expand_in, expand_out;
+  unsigned char *out_pix, *out_pix2, *data;
+  float *imdata, *in_pix, *in_pix2;
+  unsigned char pixel1[256], pixel2[256], pixel3[256];
+  unsigned char pixvalue1, pixvalue2, pixvalue3;
+  unsigned long back;
+  unsigned char back1, back2, back3;
+
+  // local arrays for pixel values
+  for (i = 0; i < 256; i++) { /* set up pixel array */
+    pixel1[i] = 0x0000ff &  graphic[0].cmap[i].pixel;
+    pixel2[i] = 0x0000ff & (graphic[0].cmap[i].pixel >> 8);
+    pixel3[i] = 0x0000ff & (graphic[0].cmap[i].pixel >> 16);
+  }
+  back = graphic[0].back;
+  back1 = 0x0000ff & back;
+  back2 = 0x0000ff & (back >> 8);
+  back3 = 0x0000ff & (back >> 16);
+
+  // define the color transform parameters
+  MaxValue = graphic[0].Npixels - 1;
+  if (image[0].image[0].range != 0.0) {
+    slope = graphic[0].Npixels / image[0].image[0].range;
+    start = graphic[0].Npixels * image[0].image[0].zero / image[0].image[0].range;
+  } else {
+    slope = 1.0;
+    start = image[0].image[0].zero;
+  }
+
+  // set up expansions
+  expand = expand_in = expand_out = 1.0;
+  if (image[0].expand == 0) /* set up expansions */
+    image[0].expand = 1;
+  if (image[0].expand > 0) {
+    expand = 1 / (1.0*image[0].expand);
+    expand_out = image[0].expand;
+    expand_in  = 1;
+  }
+  if (image[0].expand < 0) {
+    expand = fabs((double)image[0].expand);
+    expand_out = 1;
+    expand_in  = -image[0].expand;
+  }
+
+  dx = image[0].picture.dx;
+  dy = image[0].picture.dy;
+  DX = matrix[0].Naxis[0];
+  DY = matrix[0].Naxis[1];
+  extra = 4 - (dx * 3) % 4;
+
+  /* X,Y are the image coordinates of the first image pixel */
+  X = MAX(0.5*(DX - dx*expand) - image[0].X, 0);
+  if ((int)X != X) 
+    X = (int) X + 1;
+  else 
+    X = (int) X;
+  Y = MAX(0.5*(DY - dy*expand) - image[0].Y, 0);
+  if ((int)Y != Y) 
+    Y = (int) Y + 1;
+  else 
+    Y = (int) Y;
+
+  /* Rx,Ry are the screen coordinates of the first image pixel */
+  Rx = (X + image[0].X - 0.5*DX)/expand + 0.5*dx;
+  Ry = (Y + image[0].Y - 0.5*DY)/expand + 0.5*dy;
+
+  i_start = MIN (MAX (Rx, 0), dx - expand_out + 1);
+  j_start = MIN (MAX (Ry, 0), dy - expand_out + 1);
+  
+  if (image[0].expand > 0) {
+    i_end = MAX (MIN (i_start + ((int)(expand*(dx-i_start)))/expand, expand_out*(DX-X) + Rx), 0);
+    j_end = MAX (MIN (j_start + ((int)(expand*(dy-j_start)))/expand, expand_out*(DY-Y) + Ry), 0);
+  } else {
+    i_end = MAX (MIN (dx, (DX-X)/expand + Rx), 0);
+    j_end = MAX (MIN (dy, (DY-Y)/expand + Ry), 0);
+  }    
+
+  dropback = expand_out - (i_end - i_start) % expand_out;
+  if ((i_end - i_start) % expand_out == 0) dropback = 0;
+
+  data = out_pix = (unsigned char *) image[0].picture.data;
+  imdata  = (float *) matrix[0].buffer;
+  in_pix  = &imdata[DX*(int)MAX(Y,0) + (int)MAX(X,0)];
+
+  /********** below we do the mapping from buffer pixels (in) to picture pixels (out) **********/
+
+  /**** fill in bottom area ****/
+  for (j = 0; j < j_start; j++) {
+    for (i = 0; i < dx; i++, out_pix+=3) {
+      out_pix[0] = back1;
+      out_pix[1] = back2;
+      out_pix[2] = back3;
+    }
+    out_pix += extra;
+  }
+  
+  for (j = j_start; j < j_end; j+= expand_out, in_pix += expand_in*DX) {
+    out_pix = &data[j*(3*dx+extra)];
+
+    /**** fill in area to the left of the picture ****/
+    for (jj = 0; (i_start > 0) && (jj < expand_out); jj++) { 
+      out_pix2 = out_pix + jj*(3*dx + extra);
+      for (i = 0; i < i_start; i++, out_pix2+=3) {
+	out_pix2[0] = back1;
+	out_pix2[1] = back2;
+	out_pix2[2] = back3;
+      }
+    }
+    out_pix += 3*i_start;
+    
+    /*** fill in the picture region ***/
+    in_pix2 = in_pix;
+    if (expand_out == 1) {
+      for (i = i_start; i < i_end; i++, in_pix2+= expand_in, out_pix+=3) {
+	pixelN = PixelLookup(*in_pix2);
+	out_pix[0] = pixel1[pixelN];
+	out_pix[1] = pixel2[pixelN];
+	out_pix[2] = pixel3[pixelN];
+      }
+    } else {
+      for (i = i_start; i < i_end; i+= expand_out, in_pix2++, out_pix+= 3*expand_out) { 
+	pixelN = PixelLookup(*in_pix2);
+	pixvalue1 = pixel1[pixelN];
+	pixvalue2 = pixel2[pixelN];
+	pixvalue3 = pixel3[pixelN];
+	out_pix2 = out_pix;
+	for (jj = 0; jj < expand_out; jj++, out_pix2+=3*(dx-expand_out)+extra) {
+	  for (ii = 0; ii < expand_out; ii++, out_pix2+=3) {
+	    out_pix2[0] = pixvalue1; 
+	    out_pix2[1] = pixvalue2; 
+	    out_pix2[2] = pixvalue3; 
+	  }
+	}
+      }
+    }
+    out_pix -= 3*dropback;
+    
+    /**** fill in area to the right of the picture ****/
+    for (jj = 0; jj < expand_out; jj++) {
+      out_pix2 = out_pix + jj*(3*dx+extra);
+      for (i = i_end; i < dx; i++, out_pix2+=3) {
+	out_pix2[0] = back1;
+	out_pix2[1] = back2;
+	out_pix2[2] = back3;
+      }
+    }
+  } 
+  
+  /*
+  if ((j_end - j_start) % expand_out > 0)
+    out_pix -= expand_out - (j_end - j_start) % expand_out;
+  */
+  
+  out_pix = &data[j_end*(3*dx+extra)];
+  /**** fill in top area ****/
+  for (j = 0; j < (dy - j_end); j++) {
+    for (i = 0; i < dx; i++, out_pix+=3) { 
+      out_pix[0] = back1;
+      out_pix[1] = back2;
+      out_pix[2] = back3;
+    }
+    out_pix+=extra;
+  }
+
+  image[0].picture.pix = XCreateImage (graphic[0].display, graphic[0].visual, graphic[0].depth, ZPixmap, 0, 
+					image[0].picture.data, image[0].picture.dx, image[0].picture.dy, 32, 0);
+}
+
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/Remap32.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/Remap32.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/Remap32.c	(revision 16062)
@@ -0,0 +1,137 @@
+# include "Ximage.h"
+
+void Remap32 (Graphic *graphic, KapaImageWidget *image, Matrix *matrix) {
+
+  int i, j, ii, jj;
+  int i_start, i_end, j_start, j_end;
+  int dropback;  /* this is a bit of a kludge... */
+  int dx, dy, DX, DY;
+  double expand, Rx, Ry, X, Y;
+  int expand_in, expand_out;
+  unsigned int *out_pix, *out_pix2;
+  unsigned short *in_pix, *in_pix2;
+  unsigned long *pixel, pixvalue;
+  unsigned long back;
+
+  ALLOCATE (pixel, unsigned long, graphic[0].Npixels);
+
+  // local array for pixel values
+  for (i = 0; i < graphic[0].Npixels; i++) { 
+    pixel[i] = graphic[0].cmap[i].pixel;
+  }
+  back = graphic[0].back;
+
+  // set up expansions
+  expand = expand_in = expand_out = 1.0;
+  if (image[0].expand == 0) 
+    image[0].expand = 1;
+  if (image[0].expand > 0) {
+    expand = 1 / (1.0*image[0].expand);
+    expand_out = image[0].expand;
+    expand_in  = 1;
+  }
+  if (image[0].expand < 0) {
+    expand = fabs((double)image[0].expand);
+    expand_out = 1;
+    expand_in  = -image[0].expand;
+  }
+
+  // define the image boundaries
+  dx = image[0].picture.dx;
+  dy = image[0].picture.dy;
+  DX = matrix[0].Naxis[0];
+  DY = matrix[0].Naxis[1];
+
+  /* X,Y are the image coordinates of the first image pixel */
+  X = MAX(0.5*(DX - dx*expand) - image[0].X, 0);
+  if ((int)X != X) 
+    X = (int) X + 1;
+  else 
+    X = (int) X;
+  Y = MAX(0.5*(DY - dy*expand) - image[0].Y, 0);
+  if ((int)Y != Y) 
+    Y = (int) Y + 1;
+  else 
+    Y = (int) Y;
+
+  /* Rx,Ry are the screen coordinates of the first image pixel */
+  Rx = (X + image[0].X - 0.5*DX)/expand + 0.5*dx;
+  Ry = (Y + image[0].Y - 0.5*DY)/expand + 0.5*dy;
+
+  i_start = MIN (MAX (Rx, 0), dx - expand_out + 1);
+  j_start = MIN (MAX (Ry, 0), dy - expand_out + 1);
+  
+  if (image[0].expand > 0) {
+    i_end = MAX (MIN (i_start + ((int)(expand*(dx-i_start)))/expand, expand_out*(DX-X) + Rx), 0);
+    j_end = MAX (MIN (j_start + ((int)(expand*(dy-j_start)))/expand, expand_out*(DY-Y) + Ry), 0);
+  } else {
+    i_end = MAX (MIN (dx, (DX-X)/expand + Rx), 0);
+    j_end = MAX (MIN (dy, (DY-Y)/expand + Ry), 0);
+  }    
+
+  dropback = expand_out - (i_end - i_start) % expand_out;
+  if ((i_end - i_start) % expand_out == 0) dropback = 0;
+
+  out_pix = (unsigned int *) image[0].picture.data;
+  in_pix  = &image[0].pixmap[DX*(int)MAX(Y,0) + (int)MAX(X,0)];
+
+  /********** below we do the mapping from buffer pixels (in) to picture pixels (out) **********/
+
+  /**** fill in bottom area ****/
+  for (j = 0; j < dx*j_start; j++, out_pix++) {
+    *out_pix = back;
+  }
+  
+  for (j = j_start; j < j_end; j+= expand_out, out_pix+=(expand_out-1)*dx, in_pix += expand_in*DX) {
+
+    /**** fill in area to the left of the picture ****/
+    for (jj = 0; (i_start > 0) && (jj < expand_out); jj++) { 
+      out_pix2 = out_pix + jj*dx;
+      for (i = 0; i < i_start; i++, out_pix2++) {
+	*out_pix2 = back;
+      }
+    }
+    out_pix += i_start;
+    
+    /*** fill in the picture region ***/
+    in_pix2 = in_pix;
+    if (expand_out == 1) {
+      for (i = i_start; i < i_end; i++, in_pix2+= expand_in, out_pix++) {
+	*out_pix = pixel[*in_pix2];
+      }
+    } else {
+      for (i = i_start; i < i_end; i+= expand_out, in_pix2++, out_pix+= expand_out) { 
+	pixvalue = pixel[*in_pix2];
+	out_pix2 = out_pix;
+	for (jj = 0; jj < expand_out; jj++, out_pix2+=(dx-expand_out)) {
+	  for (ii = 0; ii < expand_out; ii++, out_pix2++) {
+	    *out_pix2 = pixvalue;
+	  }
+	}
+      }
+    }
+    out_pix -= dropback;
+    
+    /**** fill in area to the right of the picture ****/
+    for (jj = 0; jj < expand_out; jj++) {
+      out_pix2 = out_pix + jj*dx;
+      for (i = i_end; i < dx; i++, out_pix2++) {
+	*out_pix2 = back;
+      }
+    }
+    out_pix += (dx - i_end);
+  } 
+  
+  if ((j_end - j_start) % expand_out > 0)
+    out_pix -= expand_out - (j_end - j_start) % expand_out;
+  
+  /**** fill in top area ****/
+  for (j = 0; (j < dx*(dy - j_end)) && (out_pix - (unsigned int *)image[0].picture.data < dx*dy); j++, out_pix++) { 
+    *out_pix = back;
+  }
+
+  image[0].picture.pix = XCreateImage (graphic[0].display, graphic[0].visual, graphic[0].depth, ZPixmap, 0, 
+					image[0].picture.data, image[0].picture.dx, image[0].picture.dy, 32, 0);
+
+  free (pixel);
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/Remap8.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/Remap8.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/Remap8.c	(revision 16062)
@@ -0,0 +1,157 @@
+# include "Ximage.h"
+
+static float slope = 1.0;
+static float start = 0.0;
+static int MaxValue = 255;
+
+// XXX inline this if needed
+static int PixelLookup(float value) {
+  int out;
+  out = MIN (MAX (slope * value - start, 0), MaxValue);
+  return (out);
+}
+
+void Remap8 (Graphic *graphic, KapaImageWidget *image, Matrix *matrix) {
+
+  int i, j, ii, jj;
+  int i_start, i_end, j_start, j_end;
+  int dropback;  /* this is a bit of a kludge... */
+  int dx, dy, DX, DY, pixelN;
+  double expand, Rx, Ry, X, Y;
+  int expand_in, expand_out;
+  unsigned char *out_pix, *out_pix2;
+  float *imdata, *in_pix,  *in_pix2;
+  unsigned long pixel[256], pixvalue;
+  unsigned long back;
+
+  // local array for pixel values
+  for (i = 0; i < 256; i++) {
+    pixel[i] = graphic[0].cmap[i].pixel;
+  }
+  back = graphic[0].back;
+
+  // define the color transform parameters
+  MaxValue = graphic[0].Npixels - 1;
+  if (image[0].image[0].range != 0.0) {
+    slope = graphic[0].Npixels / image[0].image[0].range;
+    start = graphic[0].Npixels * image[0].image[0].zero / image[0].image[0].range;
+  } else {
+    slope = 1.0;
+    start = image[0].image[0].zero;
+  }
+
+  // set up expansions
+  expand = expand_in = expand_out = 1.0;
+  if (image[0].expand == 0) /* set up expansions */
+    image[0].expand = 1;
+  if (image[0].expand > 0) {
+    expand = 1 / (1.0*image[0].expand);
+    expand_out = image[0].expand;
+    expand_in  = 1;
+  }
+  if (image[0].expand < 0) {
+    expand = fabs((double)image[0].expand);
+    expand_out = 1;
+    expand_in  = -image[0].expand;
+  }
+
+  // define the image boundaries
+  dx = image[0].picture.dx;
+  dy = image[0].picture.dy;
+  DX = matrix[0].Naxis[0];
+  DY = matrix[0].Naxis[1];
+
+  /* X,Y are the image coordinates of the first image pixel */
+  X = MAX(0.5*(DX - dx*expand) - image[0].X, 0);
+  if ((int)X != X) 
+    X = (int) X + 1;
+  else 
+    X = (int) X;
+  Y = MAX(0.5*(DY - dy*expand) - image[0].Y, 0);
+  if ((int)Y != Y) 
+    Y = (int) Y + 1;
+  else 
+    Y = (int) Y;
+
+  /* Rx,Ry are the screen coordinates of the first image pixel */
+  Rx = (X + image[0].X - 0.5*DX)/expand + 0.5*dx;
+  Ry = (Y + image[0].Y - 0.5*DY)/expand + 0.5*dy;
+
+  i_start = MIN (MAX (Rx, 0), dx - expand_out + 1);
+  j_start = MIN (MAX (Ry, 0), dy - expand_out + 1);
+  
+  if (image[0].expand > 0) {
+    i_end = MAX (MIN (i_start + ((int)(expand*(dx-i_start)))/expand, expand_out*(DX-X) + Rx), 0);
+    j_end = MAX (MIN (j_start + ((int)(expand*(dy-j_start)))/expand, expand_out*(DY-Y) + Ry), 0);
+  } else {
+    i_end = MAX (MIN (dx, (DX-X)/expand + Rx), 0);
+    j_end = MAX (MIN (dy, (DY-Y)/expand + Ry), 0);
+  }    
+
+  dropback = expand_out - (i_end - i_start) % expand_out;
+  if ((i_end - i_start) % expand_out == 0) dropback = 0;
+
+  out_pix = (unsigned char *) image[0].picture.data;
+  imdata  = (float *) matrix[0].buffer;
+  in_pix  = &imdata[(int)(DX*(int)MAX(Y,0) + (int)MAX(X,0))];
+
+  /********** below we do the mapping from buffer pixels (in) to picture pixels (out) **********/
+
+  /**** fill in bottom area ****/
+  for (j = 0; j < dx*j_start; j++, out_pix++) 
+    *out_pix = back;
+  
+  for (j = j_start; j < j_end; j+= expand_out, out_pix+=(expand_out-1)*dx, in_pix += expand_in*DX) {
+
+    /**** fill in area to the left of the picture ****/
+    for (jj = 0; (i_start > 0) && (jj < expand_out); jj++) { 
+      out_pix2 = out_pix + jj*dx;
+      for (i = 0; i < i_start; i++, out_pix2++) {
+	*out_pix2 = back;
+      }
+    }
+    out_pix += i_start;
+    
+    /*** fill in the picture region ***/
+    in_pix2 = in_pix;
+    if (expand_out == 1) {
+      for (i = i_start; i < i_end; i++, in_pix2+= expand_in, out_pix++) {
+	pixelN = PixelLookup(*in_pix2);
+	*out_pix = pixel[pixelN];
+      }
+    } else {
+      for (i = i_start; i < i_end; i+= expand_out, in_pix2++, out_pix+= expand_out) { 
+	pixelN   = PixelLookup(*in_pix2);
+	pixvalue = pixel[pixelN];
+	out_pix2 = out_pix;
+	for (jj = 0; jj < expand_out; jj++, out_pix2+=(dx-expand_out)) {
+	  for (ii = 0; ii < expand_out; ii++, out_pix2++) {
+	    *out_pix2 = pixvalue;
+	  }
+	}
+      }
+    }
+    out_pix -= dropback;
+    
+    /**** fill in area to the right of the picture ****/
+    for (jj = 0; jj < expand_out; jj++) {
+      out_pix2 = out_pix + jj*dx;
+      for (i = i_end; i < dx; i++, out_pix2++) {
+	*out_pix2 = back;
+      }
+    }
+    out_pix += (dx - i_end);
+    
+  } 
+  
+  if ((j_end - j_start) % expand_out > 0)
+    out_pix -= expand_out - (j_end - j_start) % expand_out;
+  
+  /**** fill in top area ****/
+  for (j = 0; (j < dx*(dy - j_end)) && (out_pix - (unsigned char *)image[0].picture.data < dx*dy); j++, out_pix++) { 
+    *out_pix = back;
+  }
+  image[0].picture.pix = XCreateImage (graphic[0].display, graphic[0].visual, graphic[0].depth, ZPixmap, 0, 
+					image[0].picture.data, image[0].picture.dx, image[0].picture.dy, 8, 0);
+}
+
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/Reorient.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/Reorient.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/Reorient.c	(revision 16062)
@@ -0,0 +1,62 @@
+# include "Ximage.h"
+
+void Reorient (Graphic *graphic, KapaImageWidget *image, double X, double Y, int mode) {
+
+  if (image[0].expand == 0) image[0].expand = 1;
+
+  if ((image[0].X == X) && (image[0].Y == Y) && (mode == 0)) {
+    Refresh ();
+    XFlush (graphic[0].display);
+    return;
+  }
+
+  switch (mode) {
+  case 0:
+    if ((image[0].X != X) || (image[0].Y != Y)) {
+      image[0].X = X;
+      image[0].Y = Y;
+    }
+    break;
+  case -1: 
+    image[0].expand--;
+    if ((image[0].expand == 0) || (image[0].expand == -1))
+      image[0].expand = -2;
+    if (image[0].expand < -30) {
+      fprintf (stderr, "can't get smaller!\n");
+      image[0].expand = -30;
+      return;
+    }
+    image[0].X = X;
+    image[0].Y = Y;
+    break;
+  case +1:
+    image[0].expand++;
+    if ((image[0].expand == 0) || (image[0].expand == -1))
+      image[0].expand = 1;
+    if (image[0].expand > 30) {
+      fprintf (stderr, "can't get bigger!\n");
+      image[0].expand = 30;
+      return;
+    }
+    image[0].X = X;
+    image[0].Y = Y;
+    break;
+  }
+
+  Remap (graphic, image);
+  Refresh ();
+ 
+  XFlush (graphic[0].display);
+}
+
+# if (0) /* the "warp" function seems to be a problem on SUNs for some reason */
+  XQueryPointer (graphic[0].display, graphic[0].window, &dummy1, &dummy1, &dummy2, &dummy2, &x, &y, &dummy3); 
+  if ((x > image[0].picture.x) && (x < image[0].picture.x + image[0].picture.dx) &&
+      (y > image[0].picture.y) && (y < image[0].picture.y + image[0].picture.dy) &&
+      ((mouse_event[0].button == 2) || (mouse_event[0].button == 3))) {
+    XWarpPointer (graphic[0].display, None, graphic[0].window, 0, 0, 0, 0, 
+		  image[0].picture.x + 0.5*image[0].picture.dx,
+		  image[0].picture.y + 0.5*image[0].picture.dy);
+  }
+# endif
+
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/Rescale.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/Rescale.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/Rescale.c	(revision 16062)
@@ -0,0 +1,41 @@
+# include "Ximage.h"
+
+void Rescale (Graphic *graphic, KapaImageWidget *image, Matrix *matrix) {
+
+  int i, j, DX, DY, value;
+  float *iData;
+  unsigned short *oData;
+  float slope;
+  float start;
+  unsigned short MaxValue;
+
+  // define the color transform parameters
+  MaxValue = graphic[0].Npixels - 1;
+  if (image[0].image[0].range != 0.0) {
+    slope = graphic[0].Npixels / image[0].image[0].range;
+    start = graphic[0].Npixels * image[0].image[0].zero / image[0].image[0].range;
+  } else {
+    slope = 1.0;
+    start = image[0].image[0].zero;
+  }
+
+  DX = matrix[0].Naxis[0];
+  DY = matrix[0].Naxis[1];
+
+  oData = graphic[0].pixmap;
+  iData = (float *) matrix[0].buffer;
+
+  // convert pixel data values to pixel index values (0 - Npixel)
+  for (i = 0; i < DX; i++) {
+    for (j = 0; j < DY; j++, iData++, oData++) {
+      value = slope * iData - start;
+      if (value < 0) value = 0;
+      if (value > MaxValue) value = MaxValue;
+      *oData = value;
+    }
+  }
+}
+
+/** in order to call this function, graphic[0].pixmap must be allocated to match the
+ * current matrix (current channel) 
+ */
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/Resize.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/Resize.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/Resize.c	(revision 16062)
@@ -0,0 +1,39 @@
+# include "Ximage.h"
+
+// XXX Should there be a base command + KiiMessage command?
+int Resize (int sock) {
+ 
+  int i, Nsection;
+  unsigned int NX, NY;
+  Graphic *graphic;
+  Section *section;
+
+  graphic = GetGraphic();
+
+  KiiScanMessage (sock, "%d %d", &NX, &NY);
+
+  // XXX keep this min limit (or modify for !USE_XWINDOW)?
+  NX = MAX(NX, MIN_WIDTH); 
+  NY = MAX(NY, MIN_HEIGHT); 
+
+  // if the new size is the same as the old size, do nothing.
+  if ((graphic->dx == NX) && (graphic->dy == NY)) return (TRUE);
+
+  // set the new window size
+  graphic->dx = NX; 
+  graphic->dy = NY; 
+
+  if (USE_XWINDOW) XResizeWindow (graphic->display, graphic->window, NX, NY);
+
+  // reset the sizes for all sections
+  Nsection = GetNumberOfSections ();
+  for (i = 0; i < Nsection; i++) {
+      section = GetSectionByNumber (i);
+      SetSectionSizes (section);
+  }
+
+  if (USE_XWINDOW) XClearWindow (graphic->display, graphic->window);
+  Refresh (1);
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/SaveOverlay.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/SaveOverlay.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/SaveOverlay.c	(revision 16062)
@@ -0,0 +1,39 @@
+# include "Ximage.h"
+
+int SaveOverlay (int sock) {
+
+  int i, N;
+  char filename[256], *type;
+  FILE *f;
+  Section *section;
+  KapaImageWidget *image;
+
+  section = GetActiveSection();
+  image   = section->image;
+  if (image == NULL) return (TRUE);
+
+  KiiScanMessage (sock, "%*s %d %s", &N, filename);
+  
+  f = fopen (filename, "w");
+  if (f == NULL) {
+    fprintf (stderr, "could not open %s\n", filename);
+    return (TRUE);
+  }
+
+  for (i = 0; i < image[0].overlay[N].Nobjects; i++) {
+    type = KiiOverlayTypeByNumber (image[0].overlay[N].objects[i].type);
+    if (type == NULL) continue;
+    fprintf (f, "%s %lf %lf %lf %lf\n", 
+	     type,
+	     image[0].overlay[N].objects[i].x,
+	     image[0].overlay[N].objects[i].y,
+	     image[0].overlay[N].objects[i].dx,
+	     image[0].overlay[N].objects[i].dy);
+  }
+  fclose (f);
+  return (TRUE);
+}
+
+/* this is asymmetric with LoadOverlay.c.  In that case, the client reads the file and sends
+ * the overlay objects to kapa.  In this case, kapa writes the file directly... 
+ */
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/Sections.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/Sections.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/Sections.c	(revision 16062)
@@ -0,0 +1,218 @@
+# include "Ximage.h"
+
+static int  ActiveSection  = 0;
+static int       Nsections = 0;
+static Section **sections = NULL;
+
+Section *InitSection () {
+
+  Section *section;
+  ALLOCATE (section, Section, 1);
+
+  section[0].graph = NULL;
+  section[0].image = NULL;
+  section[0].x = 0;
+  section[0].y = 0;
+  section[0].dx = 0;
+  section[0].dy = 0;
+
+  section[0].name = NULL;
+  return (section);
+}
+
+void FreeSection (Section *section) {
+
+  if (section == NULL) return;
+  FreeGraph (section[0].graph);
+  FreeImage (section[0].image);
+  FREE (section[0].name);
+  free (section);
+}
+
+void FreeSections () {
+
+  int i;
+
+  for (i = 0; i < Nsections; i++) {
+    FreeSection (sections[i]);
+  }
+  free (sections);
+  Nsections = 0;
+  sections = NULL;
+}
+
+Section *AddSection (char *name, float x, float y, float dx, float dy) {
+
+  int N;
+
+  N = Nsections;
+
+  if (sections == NULL) {
+    Nsections = 1;
+    ALLOCATE (sections, Section *, Nsections);
+  } else {
+    Nsections ++;
+    REALLOCATE (sections, Section *, MAX (1, Nsections));
+  }
+  sections[N] = InitSection();
+  sections[N][0].name = strcreate (name);
+  sections[N][0].x = x;
+  sections[N][0].y = y;
+  sections[N][0].dx = dx;
+  sections[N][0].dy = dy;
+  ActiveSection = N;
+  return (sections[N]);
+}
+
+int DelSection (char *name) {
+
+  int i, j;
+
+  for (i = 0; i < Nsections; i++) {
+    if (strcmp (name, sections[i][0].name)) continue;
+    FreeSection (sections[i]);
+    for (j = i; j < Nsections - 1; j++) {
+      sections[j] = sections[j+1];
+    }
+    return (TRUE);
+  }
+  return (FALSE);
+}
+
+int GetSectionByName (char *name) {
+
+  int i;
+
+  for (i = 0; i < Nsections; i++) {
+    if (strcmp (name, sections[i][0].name)) continue;
+    return (i);
+  }
+  return (-1);
+}
+
+int GetNumberOfSections () {
+  return (Nsections);
+}
+
+Section *GetSectionByNumber (int N) {
+  if (N >= Nsections) return NULL;
+  if (N < 0) return NULL;
+  return sections[N];
+}
+
+Section *GetActiveSection () {
+  int N;
+  N = ActiveSection;
+  return (sections[N]);
+}
+
+int SetActiveSectionByNumber (int N) {
+  if (N >= Nsections) return FALSE;
+  if (N < 0) return FALSE;
+  ActiveSection = N;
+  return TRUE;
+}
+
+int ListSection (int sock) {
+  
+  int i, ThisSection;
+  char name[128];
+
+  KiiScanMessage (sock, "%s", name);
+
+  if (!strcmp (name, "*")) {
+    for (i = 0; i < Nsections; i++) {
+      fprintf (stderr, "%s: %6.3f %6.3f %6.3f %6.3f\n", 
+	       sections[i][0].name, sections[i][0].x, sections[i][0].y, sections[i][0].dx, sections[i][0].dy);
+    }
+    return (TRUE);
+  }
+
+  ThisSection = -1;
+  for (i = 0; i < Nsections; i++) {
+    if (!strcmp (name, sections[i][0].name)) {
+      ThisSection = i;
+      break;
+    }
+  }
+  if (ThisSection == -1) {
+    fprintf (stderr, "section %s not found\n", name);
+    return (TRUE);
+  }
+
+  fprintf (stderr, "%s: %6.3f %6.3f %6.3f %6.3f\n", 
+	   sections[ThisSection][0].name, 
+	   sections[ThisSection][0].x,  sections[ThisSection][0].y, 
+	   sections[ThisSection][0].dx, sections[ThisSection][0].dy);
+  return (TRUE);
+}
+
+void SetSectionSizes (Section *section) {
+
+    SetGraphSize (section);
+    SetImageSize (section);
+    return;
+}
+
+// return TRUE even for nonsense cases to avoid quitting kapa
+int MoveSection (int sock) {
+
+  int i, N;
+  char name[128];
+  char direction[16];
+  Section *tmpSection = NULL;
+
+  KiiScanMessage (sock, "%s %s", name, direction);
+  
+  N = GetSectionByName (name);
+  if (N < 0) {
+    fprintf (stderr, "section %s not found\n", name);
+    return (TRUE);
+  }
+
+  if (!strcasecmp (direction, "up")) {
+      if (N < 0) return (TRUE);
+      if (N > Nsections - 2) return (TRUE);
+      tmpSection = sections[N];
+      sections[N] = sections[N+1];
+      sections[N+1] = tmpSection;
+      Refresh (1);
+      return (TRUE);
+  }
+
+  if (!strcasecmp (direction, "down")) {
+      if (N < 1) return (TRUE);
+      if (N > Nsections - 1) return (TRUE);
+      tmpSection = sections[N];
+      sections[N] = sections[N-1];
+      sections[N-1] = tmpSection;
+      Refresh (1);
+      return (TRUE);
+  }
+
+  if (!strcasecmp (direction, "top")) {
+      if (N < 0) return (TRUE);
+      if (N > Nsections - 2) return (TRUE);
+      tmpSection = sections[N];
+      for (i = N; i < Nsections - 1; i++) {
+	sections[i] = sections[i+1];
+      }
+      sections[i] = tmpSection;
+      Refresh (1);
+      return (TRUE);
+  }
+
+  if (!strcasecmp (direction, "bottom")) {
+      if (N < 1) return (TRUE);
+      if (N > Nsections - 1) return (TRUE);
+      tmpSection = sections[N];
+      for (i = N; i >= 1; i--) {
+	sections[i] = sections[i-1];
+      }
+      sections[i] = tmpSection;
+      Refresh (1);
+      return (TRUE);
+  }
+  fprintf (stderr, "unknown direction %s for MoveSection\n", direction);
+  return (TRUE);
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/SetChannel.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/SetChannel.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/SetChannel.c	(revision 16062)
@@ -0,0 +1,66 @@
+# include "Ximage.h"
+
+int SetChannel (int sock) {
+  
+  int Nchannel;
+  Graphic *graphic;
+  Section *section;
+  KapaImageWidget *image;
+
+  graphic = GetGraphic ();
+  section = GetActiveSection();
+  if (section->image == NULL) {
+    section->image = InitImageWidget ();
+    SetSectionSizes (section);
+  }
+  image = section->image;
+
+  KiiScanMessage (sock, "%d", &Nchannel);
+
+  if (Nchannel <  0) return (TRUE);
+  if (Nchannel >= NCHANNELS) return (TRUE);
+  
+  image[0].image = &image[0].channel[Nchannel];
+  SetColorScale (graphic, image);
+
+  if (!USE_XWINDOW) return (TRUE);
+
+  Remap (graphic, image);
+  if (DEBUG) fprintf (stderr, "remapped image\n");
+  Refresh ();
+  if (DEBUG) fprintf (stderr, "refreshed\n");
+  XFlush (graphic[0].display);
+
+  return (TRUE);
+}
+
+int SetColormapFromPipe (int sock) {
+  
+  Graphic *graphic;
+  Section *section;
+  KapaImageWidget *image;
+  char colormap[256];
+  int status;
+
+  graphic = GetGraphic ();
+  section = GetActiveSection();
+  if (section->image == NULL) {
+    section->image = InitImageWidget ();
+    SetSectionSizes (section);
+  }
+  image = section->image;
+
+  KiiScanMessage (sock, "%s", colormap);
+
+  status = SetColormap (colormap);
+  if (!status) fprintf (stderr, "unknown colormap %s\n", colormap);
+
+  SetColorScale (graphic, image);
+  if (!USE_XWINDOW) return (TRUE);
+
+  Remap (graphic, image);
+  Refresh ();
+  XFlush (graphic[0].display);
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/SetColorScale.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/SetColorScale.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/SetColorScale.c	(revision 16062)
@@ -0,0 +1,243 @@
+# include "Ximage.h"
+
+void SetColorScale (Graphic *graphic, KapaImageWidget *image) {
+
+  switch (graphic[0].ColorScaleMode) {
+    case KAPA_SCALE_1D:
+      SetColorScale1D (graphic, image);
+      break;
+    case KAPA_SCALE_3D_RUFF:
+      // fall-back on 1D colors (ie, if images are mis-matched)
+      if (!SetColorScale3D (graphic, image)) {
+	graphic[0].ColorScaleMode = KAPA_SCALE_1D;
+	SetColorScale1D (graphic, image);
+      }
+      break;
+    case KAPA_SCALE_3D_FULL:
+      // fall-back on 1D colors (ie, if images are mis-matched)
+      if (!SetColorScale3D_CC (graphic, image)) {
+	graphic[0].ColorScaleMode = KAPA_SCALE_1D;
+	SetColorScale1D (graphic, image);
+      }
+      break;
+    default:
+      fprintf (stderr, "programming error in kapa: unknown color scale mode\n");
+      return;
+  }
+  return;
+}
+
+void SetColorScale1D (Graphic *graphic, KapaImageWidget *image) {
+  int i, DX, DY, value, nPixels;
+  float *iData;
+  unsigned short *oData;
+  float slope;
+  float start;
+  unsigned short MaxValue;
+  Matrix *matrix;
+
+  // define the color transform parameters
+  MaxValue = graphic[0].Npixels - 1;
+  if (image[0].image[0].range != 0.0) {
+    slope = graphic[0].Npixels / image[0].image[0].range;
+    start = graphic[0].Npixels * image[0].image[0].zero / image[0].image[0].range;
+  } else {
+    slope = 1.0;
+    start = image[0].image[0].zero;
+  }
+
+  matrix = &image->image->matrix;
+
+  DX = matrix[0].Naxis[0];
+  DY = matrix[0].Naxis[1];
+
+  nPixels = DX*DY;
+  if (image[0].nPixels != nPixels) {
+    REALLOCATE (image[0].pixmap, unsigned short, nPixels);
+    image[0].nPixels = nPixels;
+  }
+
+  oData = image[0].pixmap;
+  iData = (float *) matrix[0].buffer;
+
+  // convert pixel data values to pixel index values (0 - Npixel)
+  for (i = 0; i < nPixels; i++, iData++, oData++) {
+    value = *iData * slope - start;
+    if (value < 0) value = 0;
+    if (value > MaxValue) value = MaxValue;
+    *oData = value;
+  }
+}
+
+// in 3D we use channels 0,1,2 to choose the pixel from the cube
+// XXX this uses a crude, uniform-spacing cube
+int SetColorScale3D (Graphic *graphic, KapaImageWidget *image) {
+
+  int i, DX, DY, nPixels, rValue, gValue, bValue;
+  float *rData, *bData, *gData;
+  unsigned short *oData;
+  float redSlope, blueSlope, greenSlope;
+  float redStart, blueStart, greenStart;
+
+  DX = image[0].channel[KAPA_CHANNEL_RED].matrix.Naxis[0];
+  DY = image[0].channel[KAPA_CHANNEL_RED].matrix.Naxis[1];
+
+  if (DX != image[0].channel[KAPA_CHANNEL_GREEN].matrix.Naxis[0]) return FALSE;
+  if (DY != image[0].channel[KAPA_CHANNEL_GREEN].matrix.Naxis[1]) return FALSE;
+  if (DX != image[0].channel[KAPA_CHANNEL_BLUE].matrix.Naxis[0]) return FALSE;
+  if (DY != image[0].channel[KAPA_CHANNEL_BLUE].matrix.Naxis[1]) return FALSE;
+
+  // define the color transform parameters
+  unsigned short maxRed = graphic[0].nRed - 1;
+  unsigned short maxBlue = graphic[0].nBlue - 1;
+  unsigned short maxGreen = graphic[0].nGreen - 1;
+
+  // set start & slope for red (channel 0)
+  if (image[0].channel[KAPA_CHANNEL_RED].range != 0.0) {
+    redSlope = graphic[0].nRed / image[0].channel[KAPA_CHANNEL_RED].range;
+    redStart = graphic[0].nRed * image[0].channel[KAPA_CHANNEL_RED].zero / image[0].channel[KAPA_CHANNEL_RED].range;
+  } else {
+    redSlope = 1.0;
+    redStart = image[0].channel[KAPA_CHANNEL_RED].zero;
+  }
+  // set start & slope for blue (channel 0)
+  if (image[0].channel[KAPA_CHANNEL_BLUE].range != 0.0) {
+    blueSlope = graphic[0].nBlue / image[0].channel[KAPA_CHANNEL_BLUE].range;
+    blueStart = graphic[0].nBlue * image[0].channel[KAPA_CHANNEL_BLUE].zero / image[0].channel[KAPA_CHANNEL_BLUE].range;
+  } else {
+    blueSlope = 1.0;
+    blueStart = image[0].channel[KAPA_CHANNEL_BLUE].zero;
+  }
+  // set start & slope for green (channel 0)
+  if (image[0].channel[KAPA_CHANNEL_GREEN].range != 0.0) {
+    greenSlope = graphic[0].nGreen / image[0].channel[KAPA_CHANNEL_GREEN].range;
+    greenStart = graphic[0].nGreen * image[0].channel[KAPA_CHANNEL_GREEN].zero / image[0].channel[KAPA_CHANNEL_GREEN].range;
+  } else {
+    greenSlope = 1.0;
+    greenStart = image[0].channel[KAPA_CHANNEL_GREEN].zero;
+  }
+
+  nPixels = DX*DY;
+  if (image[0].nPixels != nPixels) {
+    REALLOCATE (image[0].pixmap, unsigned short, nPixels);
+    image[0].nPixels = nPixels;
+  }
+
+  oData = image[0].pixmap;
+  rData = (float *) image[0].channel[KAPA_CHANNEL_RED].matrix.buffer;
+  bData = (float *) image[0].channel[KAPA_CHANNEL_BLUE].matrix.buffer;
+  gData = (float *) image[0].channel[KAPA_CHANNEL_GREEN].matrix.buffer;
+
+  // convert pixel data values to pixel index values (0 - Npixel)
+  for (i = 0; i < nPixels; i++, rData++, bData++, gData++, oData++) {
+    rValue = *rData * redSlope   - redStart;
+    if (rValue < 0) rValue = 0;
+    if (rValue > maxRed) rValue = maxRed;
+
+    bValue = *bData * blueSlope  - blueStart;
+    if (bValue < 0) bValue = 0;
+    if (bValue > maxBlue) bValue = maxBlue;
+
+    gValue = *gData * greenSlope - greenStart;
+    if (gValue < 0) gValue = 0;
+    if (gValue > maxGreen) gValue = maxGreen;
+
+    *oData = gValue + bValue * (maxGreen + 1) + rValue * (maxGreen + 1) * (maxBlue + 1);
+  }
+  return TRUE;
+}
+
+// in 3D we use channels 0,1,2 to choose the pixel from the cube
+int SetColorCubeHistogram () {
+
+  int i, DX, DY, Nvalues, NVALUES, Npixels, Nmin;
+  float *values;
+  CCNode *cube;
+  Graphic *graphic;
+  Section *section;
+  KapaImageWidget *image;
+
+  graphic = GetGraphic ();
+  section = GetActiveSection();
+  if (section->image == NULL) return (FALSE);
+  image = section->image;
+
+  DX = image[0].channel[KAPA_CHANNEL_RED].matrix.Naxis[0];
+  DY = image[0].channel[KAPA_CHANNEL_RED].matrix.Naxis[1];
+  if (DX != image[0].channel[KAPA_CHANNEL_GREEN].matrix.Naxis[0]) return FALSE;
+  if (DY != image[0].channel[KAPA_CHANNEL_GREEN].matrix.Naxis[1]) return FALSE;
+  if (DX != image[0].channel[KAPA_CHANNEL_BLUE].matrix.Naxis[0]) return FALSE;
+  if (DY != image[0].channel[KAPA_CHANNEL_BLUE].matrix.Naxis[1]) return FALSE;
+
+  // create the top-level cube
+  if (graphic[0].cube != NULL) {
+    CCNodeFree (graphic[0].cube);
+  }
+  graphic[0].cube = CCNodeAlloc();
+
+  cube = graphic[0].cube;
+  cube->min[CC_X] = cube->min[CC_Y] = cube->min[CC_Z] = 0.0;
+  cube->max[CC_X] = cube->max[CC_Y] = cube->max[CC_Z] = 1.0;
+  cube->mid[CC_X] = cube->mid[CC_Y] = cube->mid[CC_Z] = 0.5;
+
+  // subdivide cube into first, uniform division (4x4x4)
+  CCSplitNodeIterate (cube, 0, 2);
+
+  // need to allocate at least 64 + NPASS*7*NSPLIT pixels (overestimate if 64 < NSPLIT)
+# define NPASS 5
+# define NSPLIT 128
+
+  for (i = 0; i < NPASS; i++) {
+    // generate histogram
+    ColorHistogram (image, cube);
+
+    // extract histogram values
+    values  = NULL;
+    Nvalues = 0;
+    NVALUES = 0;
+    CCNodeExtractCounts (cube, &values, &Nvalues, &NVALUES);
+  
+    // select top N cells
+    fsort (values, Nvalues);
+
+    // split nodes with more than value[n]
+    Nmin = MAX (0, Nvalues - NSPLIT);
+    CCNodeDivideLimit (cube, values[Nmin]);
+    free (values);
+
+    CCNodeInitCounts (cube, 0.0);
+  }
+
+  // generate histogram
+  ColorHistogram (image, cube);
+  
+  // convert histogram 3D values to cmap colors
+  Npixels = 0;
+  CCNodeSetColorMap (cube, graphic[0].cmap, graphic[0].Npixels, &Npixels);
+
+  // store the colors
+  if (USE_XWINDOW) {
+    if (graphic[0].visualclass) {
+      XStoreColors(graphic[0].display, graphic[0].colormap, graphic[0].cmap, Npixels);
+    } else {
+      for (i = 0; i < Npixels; i++) {
+	if (XAllocColor (graphic[0].display, graphic[0].colormap, &graphic[0].cmap[i]) == 0) {
+	  fprintf (stderr, "error on %d\n", i);
+	}
+      }
+    }
+  }
+  return TRUE;
+}
+
+// in 3D we use channels 0,1,2 to choose the pixel from the cube
+int SetColorScale3D_CC (Graphic *graphic, KapaImageWidget *image) {
+
+  CCNode *cube;
+
+  // create the top-level cube
+  cube = graphic[0].cube;
+  CCNodeSetColorPixels (image, cube);
+  return TRUE;
+}
+
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/SetColormap.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/SetColormap.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/SetColormap.c	(revision 16062)
@@ -0,0 +1,159 @@
+# include "Ximage.h"
+
+# define SETVALUE(VAR,VALUE,MINVAL,MAXVAL) { \
+  float tmp = (VALUE); \
+  if (tmp < MINVAL) { \
+    VAR = MINVAL; \
+  } else if (tmp > MAXVAL) { \
+    VAR = MAXVAL; \
+  } else { \
+    VAR = tmp; \
+  } }   
+
+int SetColormap (char *name) {
+
+  int i, red, blue, green;
+  float scale, blueRef, redRef, greenRef;
+  Graphic *graphic;
+
+  graphic = GetGraphic();
+
+  // the "fullcolor" colormap is uniquely defined for each image;
+  // defer to the 'SetColorScale' step
+  if (!strcasecmp (name, "fullcolor")) {
+    graphic[0].ColorScaleMode = KAPA_SCALE_3D_FULL;
+    if (SetColorCubeHistogram ()) return TRUE;
+  }
+
+  // very simple color model: evenly spaced cube 
+  if (!strcasecmp (name, "ruffcolor")) {
+      graphic[0].nRed  = pow (graphic[0].Npixels, 0.333);
+      graphic[0].nBlue = pow (graphic[0].Npixels, 0.333);
+      graphic[0].nGreen = graphic[0].Npixels / (graphic[0].nRed * graphic[0].nBlue);
+
+      // red,green,blue are values in range 0x0000 to 0xffff
+      float redScale = 0xffff / (graphic[0].nRed - 1);
+      float blueScale = 0xffff / (graphic[0].nBlue - 1);
+      float greenScale = 0xffff / (graphic[0].nGreen - 1);
+
+      i = 0;
+      for (red = 0; red < graphic[0].nRed; red++) {  
+	  for (blue = 0; blue < graphic[0].nBlue; blue++) {  
+	      for (green = 0; green < graphic[0].nGreen; green++, i++) {  
+		  SETVALUE (graphic[0].cmap[i].red,   red*redScale, 0, 0xffff);
+		  SETVALUE (graphic[0].cmap[i].blue,  blue*blueScale, 0, 0xffff);
+		  SETVALUE (graphic[0].cmap[i].green, green*greenScale, 0, 0xffff);
+		  graphic[0].cmap[i].flags = DoRed | DoGreen | DoBlue;
+	      }
+	  }
+      }
+
+      // all other modes are 1D: set the flag:
+      graphic[0].ColorScaleMode = KAPA_SCALE_3D_RUFF;
+      goto store_colors;
+  }
+
+  // all other modes are 1D: set the flag:
+  graphic[0].ColorScaleMode = KAPA_SCALE_1D;
+
+  // red,green,blue are values in range 0x0000 to 0xffff
+  scale = 0xffff / (graphic[0].Npixels - 1);
+
+  /* greyscale */
+  if ((!strcasecmp (name, "grayscale")) || (!strcasecmp (name, "greyscale"))) {
+    for (i = 0; i < graphic[0].Npixels; i++) {  
+      SETVALUE (graphic[0].cmap[i].red,   0xffff - i*scale, 0, 0xffff);
+      SETVALUE (graphic[0].cmap[i].green, 0xffff - i*scale, 0, 0xffff);
+      SETVALUE (graphic[0].cmap[i].blue,  0xffff - i*scale, 0, 0xffff);
+      graphic[0].cmap[i].flags = DoRed | DoGreen | DoBlue;
+    }
+    goto store_colors;
+  }
+  /* -grayscale */
+  if ((!strcasecmp (name, "-grayscale")) || (!strcasecmp (name, "-greyscale"))) {
+    for (i = 0; i < graphic[0].Npixels; i++) {  
+      SETVALUE (graphic[0].cmap[i].red,   i*scale, 0, 0xffff);
+      SETVALUE (graphic[0].cmap[i].green, i*scale, 0, 0xffff);
+      SETVALUE (graphic[0].cmap[i].blue,  i*scale, 0, 0xffff);
+      graphic[0].cmap[i].flags = DoRed | DoGreen | DoBlue;
+    }
+    goto store_colors;
+  }
+  /* heat */
+  if (!strcasecmp (name, "Heat")) {
+    greenRef = 0.25*graphic[0].Npixels*scale*2.0;
+    blueRef  = 0.50*graphic[0].Npixels*scale*2.0;
+    for (i = 0; i < (int)(0.25*graphic[0].Npixels); i++) {  
+      SETVALUE (graphic[0].cmap[i].red,   2*i*scale, 0, 0xffff);
+      graphic[0].cmap[i].green = 0;
+      graphic[0].cmap[i].blue  = 0;
+      graphic[0].cmap[i].flags = DoRed | DoGreen | DoBlue;
+    }
+    for (i = 0.25*graphic[0].Npixels; i < 0.50*graphic[0].Npixels; i++) {  
+      SETVALUE (graphic[0].cmap[i].red,   2*i*scale,            0, 0xffff);
+      SETVALUE (graphic[0].cmap[i].green, 2*i*scale - greenRef, 0, 0xffff);
+      graphic[0].cmap[i].blue = 0;
+      graphic[0].cmap[i].flags = DoRed | DoGreen | DoBlue;
+    }
+    for (i = (int)(0.50*graphic[0].Npixels); i < (int)(0.75*graphic[0].Npixels); i++) {  
+      graphic[0].cmap[i].red = 0xffff;
+      SETVALUE (graphic[0].cmap[i].green, 2*i*scale - greenRef, 0, 0xffff);
+      SETVALUE (graphic[0].cmap[i].blue,  2*i*scale - blueRef,  0, 0xffff);
+      graphic[0].cmap[i].flags = DoRed | DoGreen | DoBlue;
+    }
+    for (i = (int)(0.75*graphic[0].Npixels); i < graphic[0].Npixels; i++) {  
+      graphic[0].cmap[i].red   = 0xffff;
+      graphic[0].cmap[i].green = 0xffff;
+      SETVALUE (graphic[0].cmap[i].blue,  2*i*scale - blueRef,  0, 0xffff);
+      graphic[0].cmap[i].flags = DoRed | DoGreen | DoBlue;
+    }
+    goto store_colors;
+  }
+  /* rainbow */
+  if (!strcasecmp (name, "Rainbow")) {
+    redRef   = 0.25*graphic[0].Npixels*scale*4.0;
+    greenRef = 0.50*graphic[0].Npixels*scale*4.0;
+    blueRef  = 0.50*graphic[0].Npixels*scale*4.0;
+    for (i = 0; i < (int)(0.25*graphic[0].Npixels); i++) {  
+      graphic[0].cmap[i].red   = 0;
+      graphic[0].cmap[i].green = 0;
+      SETVALUE (graphic[0].cmap[i].blue,  4*i*scale,           0, 0xffff);
+      graphic[0].cmap[i].flags = DoRed | DoGreen | DoBlue;
+    }
+    for (i = (int)(0.25*graphic[0].Npixels); i < (int)(0.50*graphic[0].Npixels); i++) {  
+      SETVALUE (graphic[0].cmap[i].red,   4*i*scale - redRef,  0, 0xffff);
+      graphic[0].cmap[i].green = 0;
+      SETVALUE (graphic[0].cmap[i].blue,  blueRef - 4*i*scale, 0, 0xffff);
+      graphic[0].cmap[i].flags = DoRed | DoGreen | DoBlue;
+    }
+    for (i = (int)(0.50*graphic[0].Npixels); i < (int)(0.75*graphic[0].Npixels); i++) {  
+      graphic[0].cmap[i].red  = 0xffff;
+      SETVALUE (graphic[0].cmap[i].green,  4*i*scale - greenRef, 0, 0xffff);
+      graphic[0].cmap[i].blue = 0;
+      graphic[0].cmap[i].flags = DoRed | DoGreen | DoBlue;
+    }
+    blueRef  = 0.75*graphic[0].Npixels*scale*4.0;
+    for (i = (int)(0.75*graphic[0].Npixels); i < graphic[0].Npixels; i++) {  
+      graphic[0].cmap[i].red   = 0xffff;
+      graphic[0].cmap[i].green = 0xffff;
+      SETVALUE (graphic[0].cmap[i].blue,  4*i*scale - blueRef, 0, 0xffff);
+      graphic[0].cmap[i].flags = DoRed | DoGreen | DoBlue;
+    }
+    goto store_colors;
+  }
+  return (FALSE);
+
+ store_colors:
+  if (!USE_XWINDOW) return (TRUE);
+  if (graphic[0].visualclass) {
+    XStoreColors(graphic[0].display, graphic[0].colormap, graphic[0].cmap, graphic[0].Npixels);
+  } else {
+    for (i = 0; i < graphic[0].Npixels; i++) {
+      if (XAllocColor (graphic[0].display, graphic[0].colormap, &graphic[0].cmap[i]) == 0) {
+	fprintf (stderr, "error on %d\n", i);
+      }
+    }
+  }
+  return (TRUE);
+}
+
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/SetFont.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/SetFont.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/SetFont.c	(revision 16062)
@@ -0,0 +1,15 @@
+# include "Ximage.h"
+
+int SetFont (int sock) {
+  
+  char name[64];
+  int size;
+  
+  KiiScanCommand (sock, 16, "%s", name);
+  KiiScanCommand (sock, 16, "%d", &size);
+
+  SetRotFont (name, size);
+  
+  return (TRUE);
+  
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/SetGraphData.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/SetGraphData.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/SetGraphData.c	(revision 16062)
@@ -0,0 +1,119 @@
+# include "Ximage.h"
+
+int SetGraphData (int sock) {
+  
+  int i;
+  double xmin, xmax, ymin, ymax;
+  Graphic *graphic;
+  Section *section;
+  KapaGraphWidget *graph;
+
+  graphic = GetGraphic();
+
+  section = GetActiveSection();
+  if (section->graph == NULL) {
+    section->graph = InitGraph ();
+    SetSectionSizes (section);
+  }
+  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);
+
+  KiiScanMessage (sock, "%lf %lf %lf %lf", 
+		  &graph[0].data.xmin, 
+		  &graph[0].data.xmax, 
+		  &graph[0].data.ymin, 
+		  &graph[0].data.ymax);
+
+  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);
+
+
+
+  xmin = graph[0].data.xmin;
+  xmax = graph[0].data.xmax;
+  ymin = graph[0].data.ymin;
+  ymax = graph[0].data.ymax;
+
+  // XXX there are now two things which track the graph limits
+  // make sure these are kept in sync (or drop one!)
+  graph[0].axis[2].min = graph[0].axis[0].min = xmin;
+  graph[0].axis[2].max = graph[0].axis[0].max = xmax;
+  graph[0].axis[3].min = graph[0].axis[1].min = ymin; 
+  graph[0].axis[3].max = graph[0].axis[1].max = ymax;
+  
+  for (i = 0; i < graph[0].Nobjects; i++) {
+    graph[0].objects[i].x0 = xmin;
+    graph[0].objects[i].x1 = xmax;
+    graph[0].objects[i].y0 = ymin;
+    graph[0].objects[i].y1 = ymax;
+  }
+
+  if (USE_XWINDOW) XClearWindow (graphic->display, graphic->window);
+  Refresh (1);
+
+  return (TRUE);  
+}
+
+int GetGraphData (int sock) {
+  
+  Section *section;
+  KapaGraphWidget *graph;
+
+  section = GetActiveSection();
+  if (section->graph == NULL) {
+    section->graph = InitGraph ();
+    SetSectionSizes (section);
+  }
+  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);
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/SetGraphSize.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/SetGraphSize.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/SetGraphSize.c	(revision 16062)
@@ -0,0 +1,128 @@
+# include "Ximage.h"
+
+/* Set the dimensions of the specific graph based on the current window size.  The graph
+   is placed within the window at the fractional position defined by the section */
+
+void SetGraphSize (Section *section) {
+
+  int fontsize, bump, Nc;
+  int textpad, textdY, WdY; 
+  double PADx, PADy, Dx, Dy;
+  double PXm, PXp, PYm, PYp;
+  double X0, Y0, dX, dY;
+  char string[64], *fontname;
+  KapaGraphWidget *graph;
+  Graphic *graphic;
+
+  if (section == NULL) return;
+  graph = section->graph;
+  if (graph == NULL) return;
+
+  graphic = GetGraphic ();
+  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;
+
+  /* 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;
+ 
+  /* 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;
+
+  // if we are tied to an image, make mods as needed
+  if (section->image) {
+    textpad = USE_XWINDOW ? graphic[0].font[0].ascent : 10;
+    textdY = 6*textpad + 7*PAD1;
+    WdY = MAX (ZOOM_Y, textdY + 2*BUTTON_HEIGHT + PAD1);
+
+    switch (section->image->location) {
+      case 1:
+	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;
+	break;
+      case 2:
+	X0 = graphic[0].dx * section[0].x  + 2*PAD1 + ZOOM_X;
+	dX = graphic[0].dx * section[0].dx - 3*PAD1 - ZOOM_X;
+	break;
+      case 4:
+	dX = graphic[0].dx * section[0].dx - 3*PAD1 - ZOOM_X - PADx - PXm;
+	break;
+    }
+  }
+
+  /* define locations of coordinate axes */
+  graph[0].axis[0].fx  = X0;
+  graph[0].axis[0].fy  = graphic->dy - Y0;
+  graph[0].axis[0].dfx = dX;
+  graph[0].axis[0].dfy = 0;
+  
+  graph[0].axis[1].fx  = X0;
+  graph[0].axis[1].fy  = graphic->dy - Y0;
+  graph[0].axis[1].dfx = 0;
+  graph[0].axis[1].dfy = -dY;
+
+  graph[0].axis[2].fx  = X0;
+  graph[0].axis[2].fy  = graphic->dy - Y0 - dY;
+  graph[0].axis[2].dfx = dX;
+  graph[0].axis[2].dfy = 0;
+
+  graph[0].axis[3].fx  = X0 + dX;
+  graph[0].axis[3].fy  = graphic->dy - Y0;
+  graph[0].axis[3].dfx = 0;
+  graph[0].axis[3].dfy = -dY;
+
+  PADx = 0.8*fontsize + 2;
+  PADy = 3.0*fontsize + 4;
+
+  /* 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[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[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[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;
+  
+  /* 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: /branches/eam_branch_20080124/Ohana/src/kapa2/src/SetGraphStyle.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/SetGraphStyle.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/SetGraphStyle.c	(revision 16062)
@@ -0,0 +1,84 @@
+# include "Ximage.h"
+
+int SetGraphStyle (int sock) {
+  
+  int i;
+  double xmin, xmax, ymin, ymax;
+  Graphic *graphic;
+  Section *section;
+  KapaGraphWidget *graph;
+
+  graphic = GetGraphic();
+
+  section = GetActiveSection();
+  if (section->graph == NULL) {
+    section->graph = InitGraph ();
+    SetSectionSizes (section);
+  }
+  graph = section->graph;
+  
+  // get graph style from client 
+  KiiScanMessage (sock, "%d %d %d %d %d %d %lf %lf", 
+		  &graph[0].style.style, 
+		  &graph[0].style.ptype, 
+		  &graph[0].style.ltype, 
+		  &graph[0].style.etype, 
+		  &graph[0].style.ebar, 
+		  &graph[0].style.color, 
+		  &graph[0].style.lweight, 
+		  &graph[0].style.size);
+
+  KiiScanMessage (sock, "%lf %lf %lf %lf", 
+		  &graph[0].style.xmin, 
+		  &graph[0].style.xmax, 
+		  &graph[0].style.ymin, 
+		  &graph[0].style.ymax);
+
+  xmin = graph[0].style.xmin;
+  xmax = graph[0].style.xmax;
+  ymin = graph[0].style.ymin;
+  ymax = graph[0].style.ymax;
+
+  // XXX there are now two things which track the graph limits
+  // make sure these are kept in sync (or drop one!)
+  graph[0].axis[2].min = graph[0].axis[0].min = xmin;
+  graph[0].axis[2].max = graph[0].axis[0].max = xmax;
+  graph[0].axis[3].min = graph[0].axis[1].min = ymin; 
+  graph[0].axis[3].max = graph[0].axis[1].max = ymax;
+  
+  for (i = 0; i < graph[0].Nobjects; i++) {
+    graph[0].objects[i].x0 = xmin;
+    graph[0].objects[i].x1 = xmax;
+    graph[0].objects[i].y0 = ymin;
+    graph[0].objects[i].y1 = ymax;
+  }
+
+  if (USE_XWINDOW) XClearWindow (graphic->display, graphic->window);
+  Refresh (1);
+
+  return (TRUE);  
+}
+
+int GetGraphStyle (int sock) {
+  
+  Section *section;
+  KapaGraphWidget *graph;
+
+  section = GetActiveSection();
+  if (section->graph == NULL) {
+    section->graph = InitGraph ();
+    SetSectionSizes (section);
+  }
+  graph = section->graph;
+
+  KiiSendMessage (sock, "%8d %d %d %d %d %d %f %f", 
+		  graph[0].style.style, 
+		  graph[0].style.ptype, graph[0].style.ltype, 
+		  graph[0].style.etype, graph[0].style.ebar, graph[0].style.color, 
+		  graph[0].style.lweight, graph[0].style.size);
+  KiiSendMessage (sock, "%g %g %g %g", 
+		  graph[0].style.xmin, graph[0].style.xmax, 
+		  graph[0].style.ymin, graph[0].style.ymax);
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/SetImageData.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/SetImageData.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/SetImageData.c	(revision 16062)
@@ -0,0 +1,134 @@
+# include "Ximage.h"
+
+int SetImageData (int sock) {
+  
+  Graphic *graphic;
+  Section *section;
+  KapaImageWidget *image;
+
+  graphic = GetGraphic();
+
+  section = GetActiveSection();
+  if (section->image == NULL) {
+    section->image = InitImageWidget ();
+    SetSectionSizes (section);
+  }
+  image = section->image;
+  
+  // get image data from client 
+  KiiScanMessage (sock, "%lf %lf %s", 
+		  &image[0].image[0].zero, 
+		  &image[0].image[0].range, 
+		  image[0].image[0].name, 
+		  image[0].image[0].file);
+
+  // XXX when we go to 32bit, this should remap the image
+  // if (USE_XWINDOW) XClearWindow (graphic->display, graphic->window);
+  // Refresh (1);
+
+  return (TRUE);  
+}
+
+int GetImageData (int sock) {
+  
+  Section *section;
+  KapaImageWidget *image;
+
+  section = GetActiveSection();
+  if (section->image == NULL) {
+    section->image = InitImageWidget ();
+    SetSectionSizes (section);
+  }
+  image = section->image;
+
+  KiiSendMessage (sock, "%g %g %s %s", 
+		  image[0].image[0].zero,
+		  image[0].image[0].range,
+		  image[0].image[0].name,
+		  image[0].image[0].file);
+
+  return (TRUE);
+}
+
+int SetImageCoords (int sock) {
+  
+  Graphic *graphic;
+  Section *section;
+  KapaImageWidget *image;
+
+  graphic = GetGraphic();
+
+  section = GetActiveSection();
+  if (section->image == NULL) {
+    section->image = InitImageWidget ();
+    SetSectionSizes (section);
+  }
+  image = section->image;
+  
+  KiiScanMessage (sock, "%f %f %f %f", 
+		  &image[0].image[0].coords.pc1_1, &image[0].image[0].coords.pc2_2,
+		  &image[0].image[0].coords.pc1_2, &image[0].image[0].coords.pc2_1);
+
+  KiiScanMessage (sock, "%s", image[0].image[0].coords.ctype);
+
+  KiiScanMessage (sock, "%lf %lf %f %f %f %f", 
+		  &image[0].image[0].coords.crval1,
+		  &image[0].image[0].coords.crval2,
+		  &image[0].image[0].coords.crpix1,
+		  &image[0].image[0].coords.crpix2,
+		  &image[0].image[0].coords.cdelt1,
+		  &image[0].image[0].coords.cdelt2);
+
+  return (TRUE);  
+}
+
+int GetImageCoords (int sock) {
+  
+  Section *section;
+  KapaImageWidget *image;
+
+  section = GetActiveSection();
+  if (section->image == NULL) {
+    section->image = InitImageWidget ();
+    SetSectionSizes (section);
+  }
+  image = section->image;
+
+  KiiSendMessage (sock, "%g %g %g %g", 
+		  image[0].image[0].coords.pc1_1, image[0].image[0].coords.pc2_2,
+		  image[0].image[0].coords.pc1_2, image[0].image[0].coords.pc2_1);
+
+  KiiSendMessage (sock, "%s", image[0].image[0].coords.ctype);
+
+  KiiSendMessage (sock, "%g %g %g %g %g %g", 
+		  image[0].image[0].coords.crval1,
+		  image[0].image[0].coords.crval2,
+		  image[0].image[0].coords.crpix1,
+		  image[0].image[0].coords.crpix2,
+		  image[0].image[0].coords.cdelt1,
+		  image[0].image[0].coords.cdelt2);
+
+  return (TRUE);
+}
+
+int GetImageRange (int sock) {
+  
+  Section *section;
+  KapaImageWidget *image;
+  double Xmin, Xmax, Ymin, Ymax;
+
+  section = GetActiveSection();
+  if (section->image == NULL) {
+    section->image = InitImageWidget ();
+    SetSectionSizes (section);
+  }
+  image = section->image;
+
+  Screen_to_Image (&Xmin, &Ymin, 0.0, 0.0, image);
+  Screen_to_Image (&Xmax, &Ymax, image[0].picture.dx, image[0].picture.dy, image);
+
+  KiiSendMessage (sock, "%g %g %g %g", Xmin, Xmax, Ymin, Ymax);
+
+  return (TRUE);
+}
+
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/SetImageSize.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/SetImageSize.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/SetImageSize.c	(revision 16062)
@@ -0,0 +1,326 @@
+# include "Ximage.h"
+
+/* Set the dimensions of the specific image based on the current window size.  The image
+   is placed within the window at the fractional position defined by the section */
+
+// XXX currently only set to fill the window; does not adjust for section range
+void SetImageSize (Section *section) {
+
+  int Xs, Ys, dX, dY;
+  int textpad, textdY, WdY; 
+  KapaImageWidget *image;
+  KapaGraphWidget *graph;
+  Graphic *graphic;
+
+  if (section == NULL) return;
+  image = section->image;
+  if (image == NULL) return;
+  graph = section->graph;
+
+  graphic = GetGraphic ();
+
+  /* the image is placed within the graphic window in region specified by section */
+  Xs = graphic[0].dx * section[0].x;
+  Ys = graphic[0].dy * (1 - section[0].y - section[0].dy);
+  dX = graphic[0].dx * section[0].dx;
+  dY = graphic[0].dy * section[0].dy;
+
+  switch (image[0].location) {
+    case 0:
+      if (section->graph) {
+	  image[0].picture.x  = graph[0].axis[0].fx;
+	  image[0].picture.y  = graph[0].axis[1].fy + graph[0].axis[1].dfy;
+	  image[0].picture.dx = MAX(graph[0].axis[0].dfx + 1, 1);
+	  image[0].picture.dy = MAX(fabs(graph[0].axis[1].dfy) - 1, 1);
+      } else {
+	  image[0].picture.x  = Xs + PAD1;
+	  image[0].picture.y  = Ys + PAD1;
+	  image[0].picture.dx = dX - 2*PAD1; 
+	  image[0].picture.dy = dY - 2*PAD1;
+      }
+      if (USE_XWINDOW) CreatePicture (image, graphic);
+      Remap (graphic, image);
+      return;
+
+    case 1:
+      textpad = USE_XWINDOW ? graphic[0].font[0].ascent : 10;
+      textdY = 6*textpad + 7*PAD1;
+      WdY = MAX (ZOOM_Y, textdY + 2*BUTTON_HEIGHT + PAD1);
+
+      if (section->graph) {
+	  image[0].picture.x = graph[0].axis[0].fx;
+	  image[0].picture.y = Ys + 2*PAD1 + COLORPAD;
+	  image[0].picture.dx = graph[0].axis[0].dfx;
+	  image[0].picture.dy = dY - 5*PAD1 - WdY - COLORPAD;
+      } else {
+	  image[0].picture.x  = Xs + PAD1;
+	  image[0].picture.y  = Ys + 2*PAD1 + COLORPAD;
+	  image[0].picture.dx = dX - 2*PAD1; 
+	  image[0].picture.dy = dY - 5*PAD1 - WdY - COLORPAD;
+      }
+
+      image[0].cmapbar.dx = dX - 2*PAD1; 
+      image[0].cmapbar.dy = COLORPAD;
+      image[0].cmapbar.x = Xs + PAD1;
+      image[0].cmapbar.y = Ys + PAD1;
+
+      // XXX zoom should scale somewhat with the image? (with a min and a max)
+      // XXX actually, it is limited by the buttons and status region
+      image[0].zoom.dx = ZOOM_X; 
+      image[0].zoom.dy = ZOOM_Y;
+      image[0].zoom.x = Xs + PAD1;
+      image[0].zoom.y = image[0].picture.y + image[0].picture.dy + PAD1;
+
+      /** everything below is tied in x-dir to the zoom box **/
+      image[0].text_x = image[0].zoom.x + image[0].zoom.dx + PAD1;
+      image[0].text_y = image[0].zoom.y;
+      image[0].text_dx = ZOOM_X;
+      image[0].text_dy = 6*textpad + 7*PAD1;
+      image[0].text_dyo = 3*textpad + 4*PAD1;
+
+      image[0].overlay_button[0].x = image[0].text_x;
+      image[0].overlay_button[0].y = image[0].text_y + image[0].text_dy + PAD1;
+   
+      image[0].overlay_button[1].x = image[0].overlay_button[0].x + image[0].overlay_button[0].dx + PAD1;
+      image[0].overlay_button[1].y = image[0].overlay_button[0].y;
+
+      image[0].overlay_button[2].x = image[0].overlay_button[1].x + image[0].overlay_button[1].dx + PAD1;
+      image[0].overlay_button[2].y = image[0].overlay_button[0].y;
+
+      image[0].overlay_button[3].x = image[0].overlay_button[2].x + image[0].overlay_button[2].dx + PAD1;
+      image[0].overlay_button[3].y = image[0].overlay_button[0].y;
+
+      image[0].hms_button.x = image[0].overlay_button[3].x + image[0].overlay_button[3].dx + PAD1;
+      image[0].hms_button.y = image[0].overlay_button[0].y;
+
+      image[0].PS_button.x = image[0].text_x;
+      image[0].PS_button.y = image[0].overlay_button[0].y + BUTTON_HEIGHT + PAD1;
+
+      /** everything below is tied to the PS_button in y-dir + the neighbor in x-dir **/
+      image[0].grey_button.x = image[0].PS_button.x + image[0].PS_button.dx + PAD1;
+      image[0].grey_button.y = image[0].PS_button.y;
+
+      image[0].rainbow_button.x = image[0].grey_button.x + image[0].grey_button.dx + PAD1;
+      image[0].rainbow_button.y = image[0].PS_button.y;
+
+      image[0].heat_button.x = image[0].rainbow_button.x + image[0].rainbow_button.dx + PAD1;
+      image[0].heat_button.y = image[0].PS_button.y;
+
+      image[0].recenter_button.x = image[0].heat_button.x + image[0].heat_button.dx + PAD1;
+      image[0].recenter_button.y = image[0].PS_button.y;
+      break;
+
+    case 3:
+      textpad = USE_XWINDOW ? graphic[0].font[0].ascent : 10;
+      textdY = 6*textpad + 7*PAD1;
+      WdY = MAX (ZOOM_Y, textdY + 2*BUTTON_HEIGHT + PAD1);
+
+      if (section->graph) {
+	image[0].picture.x = graph[0].axis[0].fx;
+	image[0].picture.y = graph[0].axis[1].fy + graph[0].axis[1].dfy;
+	image[0].picture.dx = MAX(graph[0].axis[0].dfx, 1);
+	image[0].picture.dy = MAX(fabs(graph[0].axis[1].dfy) - 1, 1);
+      } else {
+	image[0].picture.dx = dX - 2*PAD1; 
+	image[0].picture.dy = dY - 5*PAD1 - WdY - COLORPAD;
+	image[0].picture.x = Xs + PAD1;
+	image[0].picture.y = Ys + 4*PAD1 + COLORPAD + WdY;
+      }
+
+      image[0].cmapbar.dx = dX - 2*PAD1; 
+      image[0].cmapbar.dy = COLORPAD;
+      image[0].cmapbar.x = Xs + PAD1;
+      image[0].cmapbar.y = Ys + PAD1;
+
+      // XXX zoom should scale somewhat with the image? (with a min and a max)
+      // XXX actually, it is limited by the buttons and status region
+      image[0].zoom.dx = ZOOM_X; 
+      image[0].zoom.dy = ZOOM_Y;
+      image[0].zoom.x = Xs + PAD1;
+      image[0].zoom.y = Ys + 2*PAD1 + COLORPAD;
+
+      /** everything below is tied in x-dir to the zoom box **/
+      image[0].text_x = image[0].zoom.x + image[0].zoom.dx + PAD1;
+      image[0].text_y = image[0].zoom.y;
+      image[0].text_dx = ZOOM_X;
+      image[0].text_dy = 6*textpad + 7*PAD1;
+      image[0].text_dyo = 3*textpad + 4*PAD1;
+
+      image[0].overlay_button[0].x = image[0].text_x;
+      image[0].overlay_button[0].y = image[0].text_y + image[0].text_dy + PAD1;
+   
+      image[0].overlay_button[1].x = image[0].overlay_button[0].x + image[0].overlay_button[0].dx + PAD1;
+      image[0].overlay_button[1].y = image[0].overlay_button[0].y;
+
+      image[0].overlay_button[2].x = image[0].overlay_button[1].x + image[0].overlay_button[1].dx + PAD1;
+      image[0].overlay_button[2].y = image[0].overlay_button[0].y;
+
+      image[0].overlay_button[3].x = image[0].overlay_button[2].x + image[0].overlay_button[2].dx + PAD1;
+      image[0].overlay_button[3].y = image[0].overlay_button[0].y;
+
+      image[0].hms_button.x = image[0].overlay_button[3].x + image[0].overlay_button[3].dx + PAD1;
+      image[0].hms_button.y = image[0].overlay_button[0].y;
+
+      image[0].PS_button.x = image[0].text_x;
+      image[0].PS_button.y = image[0].overlay_button[0].y + BUTTON_HEIGHT + PAD1;
+
+      /** everything below is tied to the PS_button in y-dir + the neighbor in x-dir **/
+      image[0].grey_button.x = image[0].PS_button.x + image[0].PS_button.dx + PAD1;
+      image[0].grey_button.y = image[0].PS_button.y;
+
+      image[0].rainbow_button.x = image[0].grey_button.x + image[0].grey_button.dx + PAD1;
+      image[0].rainbow_button.y = image[0].PS_button.y;
+
+      image[0].heat_button.x = image[0].rainbow_button.x + image[0].rainbow_button.dx + PAD1;
+      image[0].heat_button.y = image[0].PS_button.y;
+
+      image[0].recenter_button.x = image[0].heat_button.x + image[0].heat_button.dx + PAD1;
+      image[0].recenter_button.y = image[0].PS_button.y;
+      break;
+
+    case 2:
+
+      if (section->graph) {
+	image[0].picture.x = Xs + 2*PAD1 + ZOOM_X;
+	image[0].picture.y = graph[0].axis[1].fy + graph[0].axis[1].dfy;
+	image[0].picture.dx = dX - 3*PAD1 - ZOOM_X; 
+	image[0].picture.dy = MAX(fabs(graph[0].axis[1].dfy) - 1, 1);
+      } else {
+	image[0].picture.dx = dX - 3*PAD1 - ZOOM_X; 
+	image[0].picture.dy = dY - 3*PAD1 - COLORPAD;
+	image[0].picture.x = Xs + 2*PAD1 + ZOOM_X;
+	image[0].picture.y = Ys + 2*PAD1 + COLORPAD;
+      }
+
+      image[0].cmapbar.dx = dX - 2*PAD1; 
+      image[0].cmapbar.dy = COLORPAD;
+      image[0].cmapbar.x = Xs + PAD1;
+      image[0].cmapbar.y = Ys + PAD1;
+
+      // XXX zoom should scale somewhat with the image? (with a min and a max)
+      // XXX actually, it is limited by the buttons and status region
+      image[0].zoom.dx = ZOOM_X; 
+      image[0].zoom.dy = ZOOM_Y;
+      image[0].zoom.x = Xs + PAD1;
+      image[0].zoom.y = image[0].picture.y;
+
+      /** everything below is tied in x-dir to the zoom box **/
+      textpad = USE_XWINDOW ? graphic[0].font[0].ascent : 10;
+      image[0].text_x = image[0].zoom.x;
+      image[0].text_y = image[0].zoom.y + image[0].zoom.dy + PAD1;
+      image[0].text_dx = ZOOM_X;
+      image[0].text_dy = 6*textpad + 7*PAD1;
+      image[0].text_dyo = 3*textpad + 4*PAD1;
+
+      image[0].overlay_button[0].x = image[0].text_x;
+      image[0].overlay_button[0].y = image[0].text_y + image[0].text_dy + PAD1;
+   
+      image[0].overlay_button[1].x = image[0].overlay_button[0].x + image[0].overlay_button[0].dx + PAD1;
+      image[0].overlay_button[1].y = image[0].overlay_button[0].y;
+
+      image[0].overlay_button[2].x = image[0].overlay_button[1].x + image[0].overlay_button[1].dx + PAD1;
+      image[0].overlay_button[2].y = image[0].overlay_button[0].y;
+
+      image[0].overlay_button[3].x = image[0].overlay_button[2].x + image[0].overlay_button[2].dx + PAD1;
+      image[0].overlay_button[3].y = image[0].overlay_button[0].y;
+
+      image[0].hms_button.x = image[0].overlay_button[3].x + image[0].overlay_button[3].dx + PAD1;
+      image[0].hms_button.y = image[0].overlay_button[0].y;
+
+      image[0].PS_button.x = image[0].zoom.x;
+      image[0].PS_button.y = image[0].overlay_button[0].y + BUTTON_HEIGHT + PAD1;
+
+      /** everything below is tied to the PS_button in y-dir + the neighbor in x-dir **/
+      image[0].grey_button.x = image[0].PS_button.x + image[0].PS_button.dx + PAD1;
+      image[0].grey_button.y = image[0].PS_button.y;
+
+      image[0].rainbow_button.x = image[0].grey_button.x + image[0].grey_button.dx + PAD1;
+      image[0].rainbow_button.y = image[0].PS_button.y;
+
+      image[0].heat_button.x = image[0].rainbow_button.x + image[0].rainbow_button.dx + PAD1;
+      image[0].heat_button.y = image[0].PS_button.y;
+
+      image[0].recenter_button.x = image[0].heat_button.x + image[0].heat_button.dx + PAD1;
+      image[0].recenter_button.y = image[0].PS_button.y;
+      break;
+
+    case 4:
+
+      if (section->graph) {
+	image[0].picture.x = graph[0].axis[0].fx;
+	image[0].picture.y = graph[0].axis[1].fy + graph[0].axis[1].dfy;
+	image[0].picture.dx = dX - 3*PAD1 - ZOOM_X - graph[0].axis[0].fx; 
+	image[0].picture.dy = MAX(fabs(graph[0].axis[1].dfy) - 1, 1);
+      } else {
+	image[0].picture.dx = dX - 3*PAD1 - ZOOM_X; 
+	image[0].picture.dy = dY - 3*PAD1 - COLORPAD;
+	image[0].picture.x = Xs + PAD1;
+	image[0].picture.y = Ys + 2*PAD1 + COLORPAD;
+      }
+
+      image[0].cmapbar.dx = dX - 2*PAD1; 
+      image[0].cmapbar.dy = COLORPAD;
+      image[0].cmapbar.x = Xs + PAD1;
+      image[0].cmapbar.y = Ys + PAD1;
+
+      // XXX zoom should scale somewhat with the image? (with a min and a max)
+      // XXX actually, it is limited by the buttons and status region
+      image[0].zoom.dx = ZOOM_X; 
+      image[0].zoom.dy = ZOOM_Y;
+      image[0].zoom.x = image[0].picture.x + image[0].picture.dx + PAD1;
+      image[0].zoom.y = image[0].picture.y;
+
+      /** everything below is tied in x-dir to the zoom box **/
+      textpad = USE_XWINDOW ? graphic[0].font[0].ascent : 10;
+      image[0].text_x = image[0].zoom.x;
+      image[0].text_y = image[0].zoom.y + image[0].zoom.dy + PAD1;
+      image[0].text_dx = ZOOM_X;
+      image[0].text_dy = 6*textpad + 7*PAD1;
+      image[0].text_dyo = 3*textpad + 4*PAD1;
+
+      image[0].overlay_button[0].x = image[0].text_x;
+      image[0].overlay_button[0].y = image[0].text_y + image[0].text_dy + PAD1;
+   
+      image[0].overlay_button[1].x = image[0].overlay_button[0].x + image[0].overlay_button[0].dx + PAD1;
+      image[0].overlay_button[1].y = image[0].overlay_button[0].y;
+
+      image[0].overlay_button[2].x = image[0].overlay_button[1].x + image[0].overlay_button[1].dx + PAD1;
+      image[0].overlay_button[2].y = image[0].overlay_button[0].y;
+
+      image[0].overlay_button[3].x = image[0].overlay_button[2].x + image[0].overlay_button[2].dx + PAD1;
+      image[0].overlay_button[3].y = image[0].overlay_button[0].y;
+
+      image[0].hms_button.x = image[0].overlay_button[3].x + image[0].overlay_button[3].dx + PAD1;
+      image[0].hms_button.y = image[0].overlay_button[0].y;
+
+      image[0].PS_button.x = image[0].zoom.x;
+      image[0].PS_button.y = image[0].overlay_button[0].y + BUTTON_HEIGHT + PAD1;
+
+      /** everything below is tied to the PS_button in y-dir + the neighbor in x-dir **/
+      image[0].grey_button.x = image[0].PS_button.x + image[0].PS_button.dx + PAD1;
+      image[0].grey_button.y = image[0].PS_button.y;
+
+      image[0].rainbow_button.x = image[0].grey_button.x + image[0].grey_button.dx + PAD1;
+      image[0].rainbow_button.y = image[0].PS_button.y;
+
+      image[0].heat_button.x = image[0].rainbow_button.x + image[0].rainbow_button.dx + PAD1;
+      image[0].heat_button.y = image[0].PS_button.y;
+
+      image[0].recenter_button.x = image[0].heat_button.x + image[0].heat_button.dx + PAD1;
+      image[0].recenter_button.y = image[0].PS_button.y;
+      break;
+
+    default:
+      abort ();
+      break;
+  }
+
+  if (USE_XWINDOW) {
+    CreatePicture (image, graphic);
+    CreateColorbar (image, graphic);
+    CreateZoom (image, graphic, 0, 0); 
+  }
+  Remap (graphic, image);
+
+  return;
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/SetLimits.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/SetLimits.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/SetLimits.c	(revision 16062)
@@ -0,0 +1,60 @@
+# include "Ximage.h"
+
+int SetLimits (int sock) {
+  
+  int i;
+  double xmin, xmax, ymin, ymax;
+  Graphic *graphic;
+  Section *section;
+  KapaGraphWidget *graph;
+
+  KiiScanMessage (sock, "%lf %lf %lf %lf", &xmin, &xmax, &ymin, &ymax);
+
+  graphic = GetGraphic();
+
+  section = GetActiveSection();
+  if (section->graph == NULL) {
+    section->graph = InitGraph ();
+    SetSectionSizes (section);
+  }
+  graph = section->graph;
+  
+  graph[0].axis[2].min = graph[0].axis[0].min = xmin;
+  graph[0].axis[2].max = graph[0].axis[0].max = xmax;
+  graph[0].axis[3].min = graph[0].axis[1].min = ymin; 
+  graph[0].axis[3].max = graph[0].axis[1].max = ymax;
+  
+  for (i = 0; i < graph[0].Nobjects; i++) {
+    graph[0].objects[i].x0 = xmin;
+    graph[0].objects[i].x1 = xmax;
+    graph[0].objects[i].y0 = ymin;
+    graph[0].objects[i].y1 = ymax;
+  }
+
+  if (USE_XWINDOW) XClearWindow (graphic->display, graphic->window);
+  Refresh (1);
+
+  return (TRUE);  
+}
+
+int GetLimits (int sock) {
+  
+  double dX, dY;
+  Section *section;
+  KapaGraphWidget *graph;
+
+  section = GetActiveSection();
+  graph = section->graph;
+
+  if (graph == NULL) {
+    dX = 0.0;
+    dY = 0.0;
+  } else {
+    dX = graph[0].axis[0].dfx;
+    dY = graph[0].axis[1].dfy;
+  }
+
+  KiiSendMessage (sock, "%8.1f %8.1f ", dX, dY);
+  
+  return (TRUE);
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/SetNormalHints.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/SetNormalHints.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/SetNormalHints.c	(revision 16062)
@@ -0,0 +1,28 @@
+# include "Ximage.h"
+
+/************** SetNormalHints  *************/
+void SetNormalHints (Graphic *graphic) {
+
+  XSizeHints *sizehints;
+
+  sizehints = XAllocSizeHints ();
+  if (sizehints == NULL) return;
+
+  sizehints[0].x = graphic->x;
+  sizehints[0].y = graphic->x;
+  sizehints[0].width = graphic->dx;
+  sizehints[0].height = graphic->dy;
+  sizehints[0].min_width = MIN_WIDTH;
+  sizehints[0].min_height = MIN_HEIGHT;    
+
+  // XXX : can we drop the position flag 
+  // sizehints[0].flags = USPosition | USSize | PMinSize;
+  sizehints[0].flags = USSize | PMinSize;
+
+  sizehints[0].base_width = graphic->dx;
+  sizehints[0].base_height = graphic->dy;
+  sizehints[0].flags |= PBaseSize;
+    
+  XSetWMNormalHints (graphic->display, graphic->window, sizehints);
+  XFree (sizehints);
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/SetSection.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/SetSection.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/SetSection.c	(revision 16062)
@@ -0,0 +1,19 @@
+# include "Ximage.h"
+
+// set active section
+int SetSection (int sock) {
+  
+  int N;
+  char name[128];
+
+  KiiScanMessage (sock, "%s", name);
+  
+  N = GetSectionByName (name);
+  if (N < 0) {
+    fprintf (stderr, "section %s not found\n", name);
+    return (TRUE);
+  }
+
+  SetActiveSectionByNumber (N);
+  return (TRUE);
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/SetToolbox.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/SetToolbox.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/SetToolbox.c	(revision 16062)
@@ -0,0 +1,33 @@
+# include "Ximage.h"
+
+// set the position of the image toolbox
+void SetToolbox (int sock) {
+
+  int location;
+  Section *section;
+  Graphic *graphic;
+
+  KiiScanMessage (sock, "%d", &location);
+  if ((location < 0) || (location > 4)) {
+    fprintf (stderr, "invalid toolbox location %d\n", location);
+    return;
+  }
+
+  graphic = GetGraphic ();
+  section = GetActiveSection();
+  if (section->image == NULL) { 
+    section->image = InitImageWidget ();
+  }
+  section->image->location = location;
+  SetSectionSizes (section);
+
+  if (!USE_XWINDOW) return;
+
+  Remap (graphic, section->image);
+  if (DEBUG) fprintf (stderr, "remapped image\n");
+  Refresh ();
+  if (DEBUG) fprintf (stderr, "refreshed\n");
+  XFlush (graphic->display);
+
+  return;
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/SetUpGraphic.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/SetUpGraphic.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/SetUpGraphic.c	(revision 16062)
@@ -0,0 +1,69 @@
+# include "Ximage.h"
+# include "icons.h"
+
+static Graphic *graphic = NULL;
+
+/************** SetUpDisplay *************/
+void SetUpGraphic (int *argc, char **argv) {
+
+  Icon icon;
+  char *name;
+  int Ncolors;
+
+  ALLOCATE (graphic, Graphic, 1);
+  graphic->x  = 10;
+  graphic->y  = 10;
+  graphic->dx = 512;
+  graphic->dy = 512; 
+
+  if (!USE_XWINDOW) {
+    ALLOCATE (graphic[0].pixels, unsigned long, NPIXELS_STATIC);
+    ALLOCATE (graphic[0].cmap,   XColor,        NPIXELS_STATIC);
+    graphic[0].Npixels = NPIXELS_STATIC;
+    graphic[0].cube = NULL;
+    return;
+  }
+
+  name = CheckDisplayName (argc, argv);
+
+  graphic->display  = OpenDisplay     (name,    &graphic->screen);
+  graphic->colormap = DefaultColormap (graphic->display, graphic->screen);
+  graphic->depth    = DefaultDepth    (graphic->display, graphic->screen);
+  graphic->visual   = DefaultVisual   (graphic->display, graphic->screen);
+  if (name != NULL) free (name);
+
+  CheckVisual (graphic, argc, argv);
+  CheckColors (graphic, argc, argv);
+
+  icon.width = icon_width;
+  icon.height = icon_height;
+  icon.bits = icon_bits;
+
+  CheckGeometry (graphic, argc, argv);
+  TopWindow (graphic, &icon);
+  LoadFont (graphic, argc, argv, "fixed"); 
+
+  // FlushDisplay (graphic);
+  XSetWindowBackground (graphic->display, graphic->window, graphic->back);
+
+  SetNormalHints (graphic);
+  SetWMHints (graphic, &icon);
+
+  if (NAME_WINDOW == NULL) {
+    NameWindow (graphic, "Kapa");
+  } else {
+    ALLOCATE (name, char, strlen(NAME_WINDOW) + 10);
+    sprintf (name, "Kapa %s", NAME_WINDOW);
+    NameWindow (graphic, name);
+    free (name);
+  }
+
+  graphic->color = KapaX11colors (graphic->display, graphic->colormap, graphic->fore, &Ncolors);
+  if (MAP_WINDOW) MapWindow (graphic);
+  return;
+}
+
+Graphic *GetGraphic () {
+  return graphic;
+}
+
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/SetWMHints.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/SetWMHints.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/SetWMHints.c	(revision 16062)
@@ -0,0 +1,23 @@
+# include "Ximage.h"
+
+/************** SetWMHints  *************/
+void SetWMHints (Graphic *graphic, Icon *icon) {
+
+  XWMHints *wmhints;
+
+  wmhints = XAllocWMHints ();
+  if (wmhints == NULL) return;
+
+  wmhints[0].initial_state = NormalState;
+  wmhints[0].input = True;
+  if (icon[0].pixmap != (Pixmap) None) {
+    wmhints[0].icon_pixmap = icon[0].pixmap;
+    wmhints[0].icon_mask = icon[0].pixmap;
+    wmhints[0].flags = StateHint | InputHint | IconPixmapHint | IconMaskHint;
+  } else {
+    wmhints[0].flags = StateHint | InputHint;
+  }
+    
+  XSetWMHints (graphic->display, graphic->window, wmhints);
+  XFree (wmhints);
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/StatusBox.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/StatusBox.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/StatusBox.c	(revision 16062)
@@ -0,0 +1,21 @@
+# include "Ximage.h"
+
+void StatusBox (Graphic *graphic, KapaImageWidget *image) {
+
+  double  x, y, z;
+
+  if (image[0].MovePointer) {
+    x = 0.5*image[0].image[0].matrix.Naxis[0];
+    y = 0.5*image[0].image[0].matrix.Naxis[1];
+    z = -1;
+    image[0].x = x;
+    image[0].y = y;
+    image[0].z = z;
+  } else {
+    x = image[0].x;
+    y = image[0].y;
+    z = image[0].z;
+  }
+  
+  UpdateStatusBox (graphic, image, x, y, z, 1);
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/TopWindow.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/TopWindow.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/TopWindow.c	(revision 16062)
@@ -0,0 +1,18 @@
+# include "Ximage.h"
+
+/************** TopWindow *************/
+void TopWindow (Graphic *graphic, Icon *icon) {
+
+  Window rootwindow;
+
+  rootwindow = RootWindow (graphic->display, graphic->screen);
+
+  CreateWindow (graphic, rootwindow, BORDER_WIDTH, EVENT_MASK);
+  MakeGC (graphic);
+
+  icon[0].pixmap = XCreateBitmapFromData (graphic->display, graphic->window, (char *) icon[0].bits, icon[0].width, icon[0].height);
+
+  MakeCursor (graphic, DEFAULT_CURSOR);
+  XFreeCursor (graphic->display, graphic->cursor);
+  // FlushDisplay (graphic);
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/UpdatePointer.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/UpdatePointer.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/UpdatePointer.c	(revision 16062)
@@ -0,0 +1,64 @@
+# include "Ximage.h"
+# define FRAC(a) ((a) - (int)(a))
+
+int UpdatePointer (Graphic *graphic, XMotionEvent *event) {
+
+  int textpad;
+  double  x, y, z;
+  float *data;
+  char line[100];
+  Section *section;
+  KapaImageWidget *image;
+
+  // XXX select the window element which contains the event
+  section = GetActiveSection();
+  image   = section->image;
+  if (image == NULL) return (TRUE);
+  if (!image[0].location) return (TRUE);
+
+  if (image[0].MovePointer && InPicture ((XButtonEvent *)event, &image[0].picture)) {
+
+    data = (float *) image[0].image[0].matrix.buffer;
+    Screen_to_Image (&x, &y, (double)event[0].x, (double)event[0].y, image);
+
+    z = -1;
+    if (x < 0) goto skip;
+    if (x >= image[0].image[0].matrix.Naxis[0]) goto skip;
+    if (y < 0) goto skip;
+    if (y >= image[0].image[0].matrix.Naxis[1]) goto skip;
+    z = data[(int)(y)*image[0].image[0].matrix.Naxis[0] + (int)(x)];
+
+  skip:
+    image[0].x = x;
+    image[0].y = y;
+    image[0].z = z;
+    
+    UpdateStatusBox (graphic, image, x, y, z, 0);
+    XFlush (graphic[0].display);
+      
+    CreateZoom (image, graphic, x, y);  
+    XPutImage (graphic[0].display, graphic[0].window, graphic[0].gc,
+	       image[0].zoom.pix, 0, 0, 
+	       image[0].zoom.x, image[0].zoom.y, 
+	       image[0].zoom.dx, image[0].zoom.dy);
+    CrossHairs (graphic, image);
+    XFlush (graphic[0].display);
+  }
+  
+  if (InPicture ((XButtonEvent *)event, &image[0].cmapbar)) {
+    z = image[0].image[0].zero  + image[0].image[0].range * (event[0].x - image[0].cmapbar.x) / image[0].cmapbar.dx;
+    textpad = graphic[0].font[0].ascent;
+    XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].back);
+    XFillRectangle (graphic[0].display, graphic[0].window, graphic[0].gc,
+                  image[0].text_x + 1, image[0].text_y + 1, ZOOM_X - 2, textpad + PAD1 + 1);
+    XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].fore);
+    bzero (line, 100);
+    sprintf (line, "%22.3f", z);
+    XDrawString (graphic[0].display, graphic[0].window, graphic[0].gc, 
+                 image[0].text_x + PAD1, image[0].text_y + textpad + PAD1, 
+		 line, strlen(line));
+    
+  }
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/UpdateStatusBox.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/UpdateStatusBox.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/UpdateStatusBox.c	(revision 16062)
@@ -0,0 +1,62 @@
+# include "Ximage.h"
+
+void UpdateStatusBox (Graphic *graphic, KapaImageWidget *image, double x, double y, double z, int mode) {
+
+  int textpad;
+  double ra, dec; 
+  char line[100];
+
+  XY_to_RD (&ra, &dec, x, y, &image[0].image[0].coords);
+
+  textpad = graphic[0].font[0].ascent;
+
+  if (mode) {
+    XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].back);
+    XFillRectangle (graphic[0].display, graphic[0].window, graphic[0].gc,
+		    image[0].text_x, image[0].text_y, image[0].text_dx, image[0].text_dy);  
+    XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].fore);
+    XDrawRectangle (graphic[0].display, graphic[0].window, graphic[0].gc,
+		    image[0].text_x, image[0].text_y, image[0].text_dx, image[0].text_dy);
+  
+    bzero (line, 100);
+    sprintf (line, "(%d x %d) @ %d                                         ", 
+	     image[0].picture.dx, image[0].picture.dy, image[0].expand); 
+    XDrawString (graphic[0].display, graphic[0].window, graphic[0].gc, 
+		 image[0].text_x + PAD1, image[0].text_y + 4*textpad + 4*PAD1, line, 25);
+    
+    bzero (line, 100);
+    sprintf (line, "%-25s", image[0].image[0].file); 
+    XDrawString (graphic[0].display, graphic[0].window, graphic[0].gc, 
+		 image[0].text_x + PAD1, image[0].text_y + 5*textpad + 5*PAD1, line, strlen(line));
+    
+    bzero (line, 100);
+    sprintf (line, "(%s)                                          ", image[0].image[0].name); 
+    XDrawString (graphic[0].display, graphic[0].window, graphic[0].gc, 
+		 image[0].text_x + PAD1, image[0].text_y + 6*textpad + 6*PAD1, line, 25);
+    
+  } else {
+    XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].back);
+    // XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].overlay_color[1]);
+    XFillRectangle (graphic[0].display, graphic[0].window, graphic[0].gc,
+		    image[0].text_x+1, image[0].text_y+1, image[0].text_dx-1, image[0].text_dyo-2);  
+    XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].fore);
+  }
+  bzero (line, 100);
+  sprintf (line, "%22.3f", z);
+  XDrawString (graphic[0].display, graphic[0].window, graphic[0].gc, 
+	       image[0].text_x + PAD1, image[0].text_y + textpad + PAD1, line, strlen(line));
+  
+  bzero (line, 100);
+  sprintf (line, "%10.1f %10.1f", x, y);
+  XDrawString (graphic[0].display, graphic[0].window, graphic[0].gc, 
+	       image[0].text_x + PAD1, image[0].text_y + 2*textpad + 2*PAD1, line, strlen(line));
+  
+  bzero (line, 100);
+  if (image[0].DecimalDegrees) {
+    sprintf (line, "%10.6f %10.6f", ra, dec); 
+  } else {
+    hh_hms (line, ra, dec, ':');
+  }
+  XDrawString (graphic[0].display, graphic[0].window, graphic[0].gc, 
+	       image[0].text_x + PAD1, image[0].text_y + 3*textpad + 3*PAD1, line, strlen(line));
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/args.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/args.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/args.c	(revision 16062)
@@ -0,0 +1,40 @@
+# include "Ximage.h"
+
+int args (int *argc, char **argv) {
+
+  int N;
+
+  MAP_WINDOW = TRUE;
+  if ((N = get_argument (*argc, argv, "-nomap"))) {
+    remove_argument(N, argc, argv);
+    MAP_WINDOW = FALSE;
+  }
+
+  NAME_WINDOW = NULL;
+  if ((N = get_argument (*argc, argv, "-name"))) {
+    remove_argument(N, argc, argv);
+    NAME_WINDOW = strcreate (argv[N]);
+    remove_argument(N, argc, argv);
+  }
+
+  USE_XWINDOW = TRUE;
+  if ((N = get_argument (*argc, argv, "-noX"))) {
+    remove_argument(N, argc, argv);
+    USE_XWINDOW = FALSE;
+  }
+
+  if ((N = get_argument (*argc, argv, "-debug"))) {
+    remove_argument(N, argc, argv);
+    DEBUG = TRUE;
+  } else {
+    DEBUG = FALSE;
+  }
+
+  FOREGROUND = FALSE;
+  if ((N = get_argument (*argc, argv, "-fg"))) {
+    remove_argument(N, argc, argv);
+    FOREGROUND = TRUE;
+  }
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/bDrawFrame.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/bDrawFrame.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/bDrawFrame.c	(revision 16062)
@@ -0,0 +1,92 @@
+# include "Ximage.h"
+
+int bDrawFrame (KapaGraphWidget *graph) {
+  
+  int i, P, IsLabel, fontsize;
+  double fx, fy, dfx, dfy, range, major, minor, first, next;
+  char *fontname;
+
+  /* each axis is drawn independently */
+  fontname = GetRotFont (&fontsize);
+  for (i = 0; i < 4; i++) {
+    fx  = 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);
+
+    if (graph[0].axis[i].isaxis) { 
+      bDrawLine (fx, fy, fx+dfx, fy+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;
+      }
+      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));) {
+	IsLabel = FALSE;
+	if ((fabs((int)(next/major) - (next/major)) < 0.5*(minor/major)) || 
+	    (fabs ((int)((next + 0.5*minor)/major) - (next/major)) < 0.5*(minor/major)) ||
+	    (fabs ((int)((next - 0.5*minor)/major) - (next/major)) < 0.5*(minor/major)))
+	  IsLabel = graph[0].axis[i].islabel;
+	bDrawTick (fx, fy, dfx, dfy, P, graph[0].axis[i].min, graph[0].axis[i].max, next, IsLabel, i);
+	if (range > 0) 
+	  next += minor;
+	else 
+	  next -= minor;
+      }
+    }
+  }
+  return (TRUE);
+}
+
+void bDrawTick (double fx, double fy, double dfx, double dfy, int P, double min, double max, double value, int mode, int naxis) {
+  
+  int pos, dir, fontsize;
+  double size, n, x, y, dx, dy;
+  char string[64], *fontname;
+
+  pos = size = 0;
+
+  if (mode == 1) { size = MAX (0.02, 7.0 / P); }
+  if (mode == 0) { size = MAX (0.01, 4.0 / P); }
+  
+  n = P / sqrt ((double)(dfx*dfx + dfy*dfy));
+  x = fx + (value-min)*dfx/(max - min);
+  y = fy + (value-min)*dfy/(max - min);
+
+  dir = +1;
+  if ((naxis == 0) || (naxis == 1)) dir *= -1;
+  dx = dir*size*dfy*n;	
+  dy = dir*size*dfx*n;
+  
+  bDrawLine (x, y, x+dx, y+dy);
+
+  if (mode == 1) {
+    fontname = GetRotFont (&fontsize);
+
+    /* temporarily assume rectilinear axes */
+    if (naxis == 0) { dx = 0; dy = -dir*(0.8*fontsize + 1); pos = 1; }
+    if (naxis == 2) { dx = 0; dy = -dir*(0.8*fontsize + 1); pos = 7; }
+
+    if (naxis == 1) { dy = 0; dx = -(0.8*fontsize + 1); pos = 3; }
+    if (naxis == 3) { dy = 0; dx = +(0.8*fontsize + 1); pos = 5; }
+
+    x = fx + (value-min)*dfx/(max - min) + dx;
+    y = fy + (value-min)*dfy/(max - min) + dy;
+    if (fabs(value) < 1e-14) { value = 0.0; }
+    sprintf (string, "%g", value);
+    bDrawRotText ((int)x, (int)y, string, pos, 0.0);
+  }
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/bDrawIt.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/bDrawIt.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/bDrawIt.c	(revision 16062)
@@ -0,0 +1,36 @@
+# include "Ximage.h"
+
+bDrawBuffer *bDrawIt () {
+
+  int i, Nsection;
+  bDrawBuffer *buffer;
+  bDrawColor black;
+  Graphic *graphic;
+  Section *section;
+
+  graphic = GetGraphic();
+
+  black = KapaColorByName ("black");
+
+  buffer = bDrawBufferCreate (graphic->dx, graphic->dy);
+  bDrawSetBuffer (buffer);
+  bDrawSetStyle (black, 0, 0);
+  
+  // reset the sizes for all sections
+  Nsection = GetNumberOfSections ();
+  for (i = 0; i < Nsection; i++) {
+      section = GetSectionByNumber (i);
+      bDrawGraph (section->graph);
+      // bDrawImage (section->image);
+  }
+
+  return (buffer);
+}
+
+void bDrawGraph (KapaGraphWidget *graph) {
+  if (graph == NULL) return;
+  bDrawFrame (graph); 
+  bDrawObjects (graph);
+  bDrawLabels (graph);
+  bDrawTextlines (graph);
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/bDrawLabels.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/bDrawLabels.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/bDrawLabels.c	(revision 16062)
@@ -0,0 +1,65 @@
+# include "Ximage.h"
+  
+void bDrawLabels (KapaGraphWidget *graph) {
+  
+  int i, pos, x, y, size;
+  double angle;
+  char *fontname;
+
+  pos = 0;
+  fontname = GetRotFont (&size);
+  for (i = 0; i < 8; i++) {
+    if (strcmp (graph[0].label[i].text, "")) {
+      angle = 0;
+      switch (i) {
+      case 0: pos = 7; break;
+      case 1: pos = 1; angle = -90; break;
+      case 2: pos = 1; break;
+      case 3: pos = 1; angle =  90; break;
+      case 4: pos = 2; break;
+      case 5: pos = 0; break;
+      case 6: pos = 8; break;
+      case 7: pos = 6; break;
+      }	
+      x = graph[0].label[i].x;
+      y = graph[0].label[i].y;
+      SetRotFont (graph[0].label[i].font, graph[0].label[i].size); 
+      bDrawRotText (x, y, graph[0].label[i].text, pos, angle);
+    }
+  }
+  SetRotFont (fontname, size);
+}
+
+void bDrawTextlines (KapaGraphWidget *graph) {
+
+  int i, x, y, size;
+  double angle;
+  char *fontname;
+
+  fontname = GetRotFont (&size);
+  for (i = 0; i < graph[0].Ntextline; i++) {
+    if (strcmp (graph[0].textline[i].text, "")) {
+      angle = graph[0].textline[i].angle;
+      x = graph[0].textline[i].x;
+      y = graph[0].textline[i].y;
+      SetRotFont (graph[0].textline[i].font, graph[0].textline[i].size);
+      bDrawRotText (x, y, graph[0].textline[i].text, 5, angle);
+    }
+  }
+  SetRotFont (fontname, size);
+}
+
+/*
+            
+ 4____2___5 
+  |       | 
+  |       | 
+ 1|       |3
+  |       |
+  |       |
+  ---------
+  6   0   7
+
+*/
+
+
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/bDrawObjects.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/bDrawObjects.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/bDrawObjects.c	(revision 16062)
@@ -0,0 +1,574 @@
+# include "Ximage.h"
+
+# define DrawLine(X1,Y1,X2,Y2) (bDrawLine ((X1), (Y1), (X2), (Y2)))
+# define DrawCircle(X1,Y1,R) (bDrawCircle ((X1), (Y1), (R)))
+# define DrawRectangle(X,Y,dX,dY) (bDrawRectOpen ((X-0.5*dX), (Y-0.5*dY), (X+0.5*dX), (Y+0.5*dY)))
+# define FillRectangle(X,Y,dX,dY) (bDrawRectFill ((X-0.5*dX), (Y-0.5*dY), (X+0.5*dX), (Y+0.5*dY)))
+# define FillTriangle(X1,Y1,X2,Y2,X3,Y3) (bDrawTriFill ((X1), (Y1), (X2), (Y2), (X3), (Y3)))
+# define OpenTriangle(X1,Y1,X2,Y2,X3,Y3) (bDrawTriOpen ((X1), (Y1), (X2), (Y2), (X3), (Y3)))
+# define CONNECT 0
+# define HISTOGRAM 1
+# define POINTS 2
+
+static Graphic *graphic;
+
+int bDrawObjects (KapaGraphWidget *graph) {
+  
+  int i;
+  int type;
+  int weight;
+  bDrawColor color;
+  bDrawColor black;
+  
+  graphic = GetGraphic();
+
+  black = KapaColorByName ("black");
+  for (i = 0; i < graph[0].Nobjects; i++) {
+
+    weight = MAX (0, MIN (10, graph[0].objects[i].lweight));
+    type = graph[0].objects[i].ltype;    
+    color = graph[0].objects[i].color;
+    bDrawSetStyle (color, weight, type);
+
+    switch (graph[0].objects[i].style) {
+    case CONNECT: 
+      bDrawConnect (graph, &graph[0].objects[i]);
+      break;
+    case HISTOGRAM:
+      bDrawHistogram (graph, &graph[0].objects[i]);
+      break;
+    case POINTS:
+      bDrawPoints (graph, &graph[0].objects[i]);
+      break;
+    }
+
+    if (graph[0].objects[i].etype & 0x01) {
+      bDrawYErrors (graph, &graph[0].objects[i]);
+    }
+    if (graph[0].objects[i].etype & 0x02) {
+      bDrawXErrors (graph, &graph[0].objects[i]);
+    }
+  }
+  bDrawSetStyle (black, 0, 0);
+  return (TRUE);
+}
+
+void bDrawConnect (KapaGraphWidget *graph, Gobjects *object) {
+  
+  int i;
+  float *x, *y;
+  double mxi, mxj, myi, myj, bxi, bxj, byi, byj, bx, by;
+  double sx0, sy0, sx1, sy1;
+  double X0, X1, Y0, Y1;
+
+  mxi = graph[0].axis[0].dfx / (object[0].x1 - object[0].x0);
+  mxj = graph[0].axis[1].dfx / (object[0].y1 - object[0].y0);
+  myi = graph[0].axis[0].dfy / (object[0].x1 - object[0].x0);
+  myj = graph[0].axis[1].dfy / (object[0].y1 - object[0].y0); 
+  
+  bxi  =  graph[0].axis[0].fx - object[0].x0*graph[0].axis[0].dfx/(object[0].x1 - object[0].x0);
+  bxj  =  -object[0].y0*graph[0].axis[1].dfx/(object[0].y1 - object[0].y0);
+  byi  =  -object[0].x0*graph[0].axis[0].dfy/(object[0].x1 - object[0].x0);
+  byj  =  graph[0].axis[1].fy - object[0].y0*graph[0].axis[1].dfy/(object[0].y1 - object[0].y0); 
+  
+  bx = bxi + bxj;
+  by = byi + byj;
+  
+  X0 = graph[0].axis[0].fx;
+  X1 = graph[0].axis[0].fx + graph[0].axis[0].dfx;
+  Y0 = graph[0].axis[1].fy;
+  Y1 = graph[0].axis[1].fy + graph[0].axis[1].dfy;
+
+  x = object[0].x; y = object[0].y;
+  for (i = 0; (i < object[0].Npts) && !(finite(x[i]) && finite(y[i])); i++);
+  if (i >= object[0].Npts) return;
+  sx0 = x[i]*mxi + y[i]*mxj + bx;
+  sy0 = x[i]*myi + y[i]*myj + by;
+  
+  for (i++; i < object[0].Npts; i++) {
+    if (!(finite(x[i]) && finite(y[i]))) continue;
+    sx1 = x[i]*mxi + y[i]*mxj + bx;
+    sy1 = x[i]*myi + y[i]*myj + by;
+    bDrawClipLine (sx0, sy0, sx1, sy1, X0, Y0, X1, Y1);
+    sx0 = sx1; sy0 = sy1;
+  }
+}
+
+void bDrawClipLine (double x0, double y0, double x1, double y1, double X0, double Y1, double X1, double Y0) {
+
+  /* skip line segement if both points are beyond box */
+  if ((x0 <= X0) && (x1 <= X0)) return;
+  if ((x0 >= X1) && (x1 >= X1)) return;
+  if ((y0 <= Y0) && (y1 <= Y0)) return;
+  if ((y0 >= Y1) && (y1 >= Y1)) return;
+
+  /* replace x0,y0 if outside box */
+  if ((x0 < X0) && (x1 >= X0)) {
+    y0 = y0 + (X0 - x0)*(y1 - y0)/(x1 - x0);
+    x0 = X0;
+  }
+  if ((x0 > X1) && (x1 <= X1)) {
+    y0 = y0 + (X1 - x0)*(y1 - y0)/(x1 - x0);
+    x0 = X1;
+  }
+  if ((y0 < Y0) && (y1 >= Y0)) {
+    x0 = x0 + (Y0 - y0)*(x1 - x0)/(y1 - y0);
+    y0 = Y0;
+  }
+  if ((y0 > Y1) && (y1 <= Y1)) {
+    x0 = x0 + (Y1 - y0)*(x1 - x0)/(y1 - y0);
+    y0 = Y1;
+  }
+
+  /* skip line segement if both points are beyond box */
+  if ((x0 <= X0) && (x1 <= X0)) return;
+  if ((x0 >= X1) && (x1 >= X1)) return;
+  if ((y0 <= Y0) && (y1 <= Y0)) return;
+  if ((y0 >= Y1) && (y1 >= Y1)) return;
+
+  /* replace x1,y1 if outside box */
+  if ((x1 < X0) && (x0 >= X0)) {
+    y1 = y0 + (X0 - x0)*(y1 - y0)/(x1 - x0);
+    x1 = X0;
+  }
+  if ((x1 > X1) && (x0 <= X1)) {
+    y1 = y0 + (X1 - x0)*(y1 - y0)/(x1 - x0);
+    x1 = X1;
+  }
+  if ((y1 < Y0) && (y0 >= Y0)) {
+    x1 = x0 + (Y0 - y0)*(x1 - x0)/(y1 - y0);
+    y1 = Y0;
+  }
+  if ((y1 > Y1) && (y0 <= Y1)) {
+    x1 = x0 + (Y1 - y0)*(x1 - x0)/(y1 - y0);
+    y1 = Y1;
+  }
+  DrawLine (x0, y0, x1, y1);
+}
+
+/*******/
+void bDrawHistogram (KapaGraphWidget *graph, Gobjects *object) {
+
+  int i;
+  float *x, *y;
+  double mxi, mxj, myi, myj, bxi, bxj, byi, byj, bx, by;
+  double sx0, sy0, sx1, sy1, sxa;
+  double X0, X1, Y0, Y1;
+
+  mxi = graph[0].axis[0].dfx / (object[0].x1 - object[0].x0);
+  mxj = graph[0].axis[1].dfx / (object[0].y1 - object[0].y0);
+  myi = graph[0].axis[0].dfy / (object[0].x1 - object[0].x0);
+  myj = graph[0].axis[1].dfy / (object[0].y1 - object[0].y0); 
+  
+  bxi  =  graph[0].axis[0].fx - object[0].x0*graph[0].axis[0].dfx/(object[0].x1 - object[0].x0);
+  bxj  =  -object[0].y0*graph[0].axis[1].dfx/(object[0].y1 - object[0].y0);
+  byi  =  -object[0].x0*graph[0].axis[0].dfy/(object[0].x1 - object[0].x0);
+  byj  =  graph[0].axis[1].fy - object[0].y0*graph[0].axis[1].dfy/(object[0].y1 - object[0].y0); 
+  
+  bx = bxi + bxj;
+  by = byi + byj;
+  
+  X0 = graph[0].axis[0].fx;
+  X1 = graph[0].axis[0].fx + graph[0].axis[0].dfx;
+  Y0 = graph[0].axis[1].fy;
+  Y1 = graph[0].axis[1].fy + graph[0].axis[1].dfy;
+
+  /* find the first valid datapoint */
+  x = object[0].x; y = object[0].y;
+  for (i = 0; (i < object[0].Npts) && !(finite(x[i]) && finite(y[i])); i++);
+  if (i >= object[0].Npts) return;
+  sx0 = x[i]*mxi + y[i]*mxj + bx;
+  sy0 = x[i]*myi + y[i]*myj + by;
+  sx0 = MIN (MAX (sx0, X0), X1);
+  sy0 = MAX (MIN (sy0, Y0), Y1);
+  
+  /* continue with rest of points */
+  for (i++; i < object[0].Npts; i++) {
+    if (!(finite(x[i]) && finite(y[i]))) continue;
+    sx1 = x[i]*mxi + y[i]*mxj + bx;
+    sy1 = x[i]*myi + y[i]*myj + by;
+    sx1 = MIN (MAX (sx1, X0), X1);
+    sy1 = MAX (MIN (sy1, Y0), Y1);
+    sxa = 0.5*(sx0 + sx1);
+    DrawLine (sx0, sy0, sxa, sy0);
+    DrawLine (sxa, sy0, sxa, sy1);
+    DrawLine (sxa, sy1, sx1, sy1);
+    sx0 = sx1; sy0 = sy1;
+  }
+}
+
+/*******/
+void bDrawPoints (KapaGraphWidget *graph, Gobjects *object) {
+ 
+  int i;
+  float *x, *y, *z;
+  double mxi, mxj, myi, myj, bxi, bxj, byi, byj, bx, by;
+  double sx, sy, d, sx1, sy1, sx2, sy2;
+
+  mxi = graph[0].axis[0].dfx / (object[0].x1 - object[0].x0);
+  mxj = graph[0].axis[1].dfx / (object[0].y1 - object[0].y0);
+  myi = graph[0].axis[0].dfy / (object[0].x1 - object[0].x0);
+  myj = graph[0].axis[1].dfy / (object[0].y1 - object[0].y0);  
+ 
+  bxi  =  graph[0].axis[0].fx - object[0].x0*graph[0].axis[0].dfx/(object[0].x1 - object[0].x0);
+  bxj  =  -object[0].y0*graph[0].axis[1].dfx/(object[0].y1 - object[0].y0);
+  byi  =  -object[0].x0*graph[0].axis[0].dfy/(object[0].x1 - object[0].x0);
+  byj  =  graph[0].axis[1].fy - object[0].y0*graph[0].axis[1].dfy/(object[0].y1 - object[0].y0);  
+
+  bx = bxi + bxj;
+  by = byi + byj;
+  
+  /* below here, code is identical with DrawObjects */
+  /**** points are scaled by object.z ***/
+  if (object[0].size < 0) {
+    d = 0.5 * (graphic->dx + graphic->dy) * 0.01;
+    x = object[0].x; y = object[0].y; z = object[0].z;
+    if (object[0].ptype == 0) {	/* filled box */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    FillRectangle (sx, sy, 2*d*z[i], 2*d*z[i]);
+	  }
+      }
+    }
+    if (object[0].ptype == 1) {	/* open box */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    DrawRectangle (sx, sy, 2*d*z[i], 2*d*z[i]);
+	  }
+      }
+    }
+    if (object[0].ptype == 2) { /* cross */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    DrawLine (sx - d*z[i], sy, sx + d*z[i], sy);
+	    DrawLine (sx, sy - d*z[i], sx, sy + d*z[i]);
+	  }
+      }
+    }
+    if (object[0].ptype == 3) {	/* x */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    DrawLine (sx + d*z[i], sy - d*z[i], sx - d*z[i], sy + d*z[i]);
+	    DrawLine (sx - d*z[i], sy - d*z[i], sx + d*z[i], sy + d*z[i]);
+	  }
+      }
+    }
+    if (object[0].ptype == 4) {	/* filled triangle */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    FillTriangle (sx - d*z[i], sy - 0.58*d*z[i], sx + d*z[i], sy - 0.58*d*z[i], sx, sy + 1.15*d*z[i]);
+	  }
+      }
+    }
+    if (object[0].ptype == 5) {	/* open triangle */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    OpenTriangle (sx - d*z[i], sy + 0.58*d*z[i], sx, sy - 1.15*d*z[i], sx + d*z[i], sy + 0.58*d*z[i]);
+	  }
+      }
+    }
+    if (object[0].ptype == 6) {	/* Y */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    DrawLine (sx, sy, sx - d*z[i], sy + 0.58*d*z[i]);
+	    DrawLine (sx, sy, sx + d*z[i], sy + 0.58*d*z[i]);
+	    DrawLine (sx, sy, sx,          sy - 1.15*d*z[i]);
+	  }
+      }
+    }
+    if (object[0].ptype == 7) {	/* 0 */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    DrawCircle (sx, sy, d*z[i]);
+	  }
+      }
+    }
+    if (object[0].ptype == 100) {	/* connect a pair of points */
+      for (i = 0; i + 1 < object[0].Npts; i+=2) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx1 = x[i]*mxi + y[i]*mxj + bx;
+	sy1 = x[i]*myi + y[i]*myj + by;
+	sx2 = x[i+1]*mxi + y[i+1]*mxj + bx;
+	sy2 = x[i+1]*myi + y[i+1]*myj + by;
+	DrawLine (sx1, sy1, sx2, sy2);
+      }
+    }
+  } else {
+    d = object[0].size * 0.5 * (graphic->dx + graphic->dy) * 0.003;
+    x = object[0].x; y = object[0].y;
+    if (object[0].ptype == 0) {	/* filled box */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    FillRectangle (sx, sy, 2*d, 2*d);
+	  }
+      }
+    }
+    if (object[0].ptype == 1) {		/* open box */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+   	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    DrawRectangle (sx, sy, 2*d, 2*d);
+	  }
+      }
+    }
+    if (object[0].ptype == 2) { /* cross */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    DrawLine (sx - d, sy, sx + d, sy);
+	    DrawLine (sx, sy - d, sx, sy + d);
+	  }
+      }
+    }
+    if (object[0].ptype == 3) {		/* x */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    DrawLine (sx + d, sy - d, sx - d, sy + d);
+	    DrawLine (sx - d, sy - d, sx + d, sy + d);
+	  }
+      }
+    }
+    if (object[0].ptype == 4) {	/* filled triangle */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    FillTriangle (sx - d, sy - 0.58*d, sx + d, sy - 0.58*d, sx, sy + 1.15*d);
+	  }
+      }
+    }
+    if (object[0].ptype == 5) {	/* open triangle */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    OpenTriangle (sx - d, sy + 0.58*d, sx + d, sy + 0.58*d, sx, sy - 1.15*d);
+	  }
+      }
+    }
+    if (object[0].ptype == 6) {	/* Y */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    DrawLine (sx, sy, sx - d, sy - 0.58*d);
+	    DrawLine (sx, sy, sx + d, sy - 0.58*d);
+	    DrawLine (sx, sy, sx,     sy + 1.15*d);
+	  }
+      }
+    }
+    if (object[0].ptype == 7) {	/* 0 */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    DrawCircle (sx, sy, d);
+	  }
+      }
+    }
+    if (object[0].ptype == 100) {	
+      for (i = 0; i + 1 < object[0].Npts; i+=2) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx1 = x[i]*mxi + y[i]*mxj + bx;
+	sy1 = x[i]*myi + y[i]*myj + by;
+	sx2 = x[i+1]*mxi + y[i+1]*mxj + bx;
+	sy2 = x[i+1]*myi + y[i+1]*myj + by;
+	DrawLine (sx1, sy1, sx2, sy2);
+      }
+    }
+  }
+}
+    
+/*******/
+void bDrawXErrors (KapaGraphWidget *graph, Gobjects *object) {
+  
+  int i, bar;
+  float *x, *y, *dxm, *dxp;
+  double mxi, mxj, myi, myj, bxi, bxj, byi, byj, bx, by;
+  double sx0, sy0, sx1, sy1, sz, sx10, sx11;
+
+  mxi = graph[0].axis[0].dfx / (object[0].x1 - object[0].x0);
+  mxj = graph[0].axis[1].dfx / (object[0].y1 - object[0].y0);
+  myi = graph[0].axis[0].dfy / (object[0].x1 - object[0].x0);
+  myj = graph[0].axis[1].dfy / (object[0].y1 - object[0].y0);
+  
+  bxi  =  graph[0].axis[0].fx - object[0].x0*graph[0].axis[0].dfx/(object[0].x1 - object[0].x0);
+  bxj  =  -object[0].y0*graph[0].axis[1].dfx/(object[0].y1 - object[0].y0);
+  byi  =  -object[0].x0*graph[0].axis[0].dfy/(object[0].x1 - object[0].x0);
+  byj  =  graph[0].axis[1].fy - object[0].y0*graph[0].axis[1].dfy/(object[0].y1 - object[0].y0);
+  
+  bx = bxi + bxj;
+  by = byi + byj;
+  
+  x = object[0].x; y = object[0].y; dxp = object[0].dxp; dxm = object[0].dxm; 
+  bar = object[0].ebar; sz = object[0].size*graph[0].axis[1].dfy*0.03;
+   
+  for (i = 0; i < object[0].Npts; i++) {
+    if (!(finite(x[i]) && finite(y[i]) && finite(dxp[i]))) continue;
+    sx0 = x[i]*mxi + y[i]*mxj + bx;
+    sy0 = x[i]*myi + y[i]*myj + by;
+    sx1 = (x[i] + dxp[i])*mxi + y[i]*mxj + bx;
+    sy1 = (x[i] + dxp[i])*myi + y[i]*myj + by;
+    if (((sx0 > graph[0].axis[0].fx) && (sx0 < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	 (sy0 < graph[0].axis[1].fy) && (sy0 > graph[0].axis[1].fy + graph[0].axis[1].dfy)) ||
+	((sx1 > graph[0].axis[0].fx) && (sx1 < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	 (sy1 < graph[0].axis[1].fy) && (sy1 > graph[0].axis[1].fy + graph[0].axis[1].dfy)))
+      {
+	DrawLine (sx0, sy0, sx1, sy1);
+	if (bar) {
+	  sx10 = sy1 - sz;
+	  sx11 = sy1 + sz;
+	  DrawLine (sx1, sx10, sx1, sx11);
+	}
+      }
+    if (!(finite(x[i]) && finite(y[i]) && finite(dxm[i]))) continue;
+    sx0 = x[i]*mxi + y[i]*mxj + bx;
+    sy0 = x[i]*myi + y[i]*myj + by;
+    sx1 = (x[i] - dxm[i])*mxi + y[i]*mxj + bx;
+    sy1 = (x[i] - dxm[i])*myi + y[i]*myj + by;
+    if (((sx0 > graph[0].axis[0].fx) && (sx0 < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	 (sy0 < graph[0].axis[1].fy) && (sy0 > graph[0].axis[1].fy + graph[0].axis[1].dfy)) ||
+	((sx1 > graph[0].axis[0].fx) && (sx1 < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	 (sy1 < graph[0].axis[1].fy) && (sy1 > graph[0].axis[1].fy + graph[0].axis[1].dfy)))
+      {
+	DrawLine (sx0, sy0, sx1, sy1);
+	if (bar) {
+	  sx10 = sy1 - sz;
+	  sx11 = sy1 + sz;
+	  DrawLine (sx1, sx10, sx1, sx11);
+	}
+      }
+  }
+}
+    
+/*******/
+void bDrawYErrors (KapaGraphWidget *graph, Gobjects *object) {
+  
+  int i, bar;
+  float *x, *y, *dym, *dyp;
+  double mxi, mxj, myi, myj, bxi, bxj, byi, byj, bx, by;
+  double sx0, sy0, sx1, sy1, sz, sx10, sx11;
+  
+  mxi = graph[0].axis[0].dfx / (object[0].x1 - object[0].x0);
+  mxj = graph[0].axis[1].dfx / (object[0].y1 - object[0].y0);
+  myi = graph[0].axis[0].dfy / (object[0].x1 - object[0].x0);
+  myj = graph[0].axis[1].dfy / (object[0].y1 - object[0].y0);
+  
+  bxi  =  graph[0].axis[0].fx - object[0].x0*graph[0].axis[0].dfx/(object[0].x1 - object[0].x0);
+  bxj  =  -object[0].y0*graph[0].axis[1].dfx/(object[0].y1 - object[0].y0);
+  byi  =  -object[0].x0*graph[0].axis[0].dfy/(object[0].x1 - object[0].x0);
+  byj  =  graph[0].axis[1].fy - object[0].y0*graph[0].axis[1].dfy/(object[0].y1 - object[0].y0);
+  
+  bx = bxi + bxj;
+  by = byi + byj;
+  
+  x = object[0].x; y = object[0].y; dyp = object[0].dyp; dym = object[0].dym; 
+  bar = object[0].ebar; sz = object[0].size*graph[0].axis[0].dfx*0.03;
+  
+  for (i = 0; i < object[0].Npts; i++) {
+    if (!(finite(x[i]) && finite(y[i]) && finite(dyp[i]))) continue;
+    sx0 = x[i]*mxi + y[i]*mxj + bx;
+    sy0 = x[i]*myi + y[i]*myj + by;
+    sx1 = x[i]*mxi + (y[i] + dyp[i])*mxj + bx;
+    sy1 = x[i]*myi + (y[i] + dyp[i])*myj + by;
+    if (((sx0 > graph[0].axis[0].fx) && (sx0 < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	 (sy0 < graph[0].axis[1].fy) && (sy0 > graph[0].axis[1].fy + graph[0].axis[1].dfy)) ||
+	((sx1 > graph[0].axis[0].fx) && (sx1 < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	 (sy1 < graph[0].axis[1].fy) && (sy1 > graph[0].axis[1].fy + graph[0].axis[1].dfy)))
+      {
+	DrawLine (sx0, sy0, sx1, sy1);
+	if (bar) {
+	  sx10 = sx1 - sz;
+	  sx11 = sx1 + sz;
+	  DrawLine (sx10, sy1, sx11, sy1);
+	}
+      }
+    if (!(finite(x[i]) && finite(y[i]) && finite(dym[i]))) continue;
+    sx0 = x[i]*mxi + y[i]*mxj + bx;
+    sy0 = x[i]*myi + y[i]*myj + by;
+    sx1 = x[i]*mxi + (y[i] - dym[i])*mxj + bx;
+    sy1 = x[i]*myi + (y[i] - dym[i])*myj + by;
+    if (((sx0 > graph[0].axis[0].fx) && (sx0 < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	 (sy0 < graph[0].axis[1].fy) && (sy0 > graph[0].axis[1].fy + graph[0].axis[1].dfy)) ||
+	((sx1 > graph[0].axis[0].fx) && (sx1 < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	 (sy1 < graph[0].axis[1].fy) && (sy1 > graph[0].axis[1].fy + graph[0].axis[1].dfy)))
+      {
+	DrawLine (sx0, sy0, sx1, sy1);
+	if (bar) {
+	  sx10 = sx1 - sz;
+	  sx11 = sx1 + sz;
+	  DrawLine (sx10, sy1, sx11, sy1);
+	}
+      }
+  }
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/bDrawOverlay.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/bDrawOverlay.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/bDrawOverlay.c	(revision 16062)
@@ -0,0 +1,101 @@
+# include "Ximage.h"
+# define INFRONT 4
+
+static char name[4][16] = {"red", "green", "blue", "yellow"};
+
+void bDrawOverlay (KapaImageWidget *image, int N) {
+
+  int i;
+  int dX, dY, dx, dy;
+  int X, Y, Xmin, Ymin, Xmax, Ymax, Xrange, Yrange;
+  double expand, X0, Y0;
+  bDrawColor color;
+ 
+  /* translate color to bDrawColors : image[0].overlay[N].color */
+  color = KapaColorByName (name[N]);
+  bDrawSetStyle (color, 0, 0);
+  
+  expand = 1.0;
+  if (image[0].expand > 0) {
+    expand = 1 / (1.0*image[0].expand);
+  }
+  if (image[0].expand < 0) {
+    expand = fabs((double)image[0].expand);
+  }
+
+  Image_to_Screen (&X0, &Y0, 0.0, 0.0, image);
+  X0 -= image[0].picture.x;
+  Y0 -= image[0].picture.y;
+
+  Xmin = 0;
+  Ymin = 0;
+  Xmax = image[0].picture.dx;
+  Ymax = image[0].picture.dy;
+  Xrange = image[0].picture.dx;
+  Yrange = image[0].picture.dy;
+
+  for (i = 0; i < image[0].overlay[N].Nobjects; i++) {
+    if (N == INFRONT) {
+      X  = image[0].overlay[N].objects[i].x * Xrange;
+      Y  = image[0].overlay[N].objects[i].y * Yrange;
+      dX = image[0].overlay[N].objects[i].dx * Xrange;
+      dY = image[0].overlay[N].objects[i].dy * Yrange;
+    } else {
+      X  = image[0].overlay[N].objects[i].x/expand + X0;
+      Y =  image[0].overlay[N].objects[i].y/expand + Y0;
+      dX = image[0].overlay[N].objects[i].dx/expand;
+      dY = image[0].overlay[N].objects[i].dy/expand;
+    }
+    if ((X + dX < Xmin) || (X - dX > Xmax) ||
+	(Y + dY < Ymin) || (Y - dY > Ymax)) {
+      continue;
+    }
+
+    /* for a LINE, (x, y) is the start, (dx, dy) is the distance to end
+       for a CIRCLE (x, y) is the center, (dx, dy) is the radius 
+       for a BOX (x, y) is the center, (dx, dy) is the width */
+
+    switch (image[0].overlay[N].objects[i].type) {
+      case KII_OVERLAY_LINE:
+	bDrawLine (X, Y, (X+dX), (Y+dY));
+	break;
+      case KII_OVERLAY_TEXT:
+	bDrawRotText (X, Y, image[0].overlay[N].objects[i].text, 8, 0.0);
+	break;
+      case KII_OVERLAY_BOX:
+	dx = MAX (abs(dX),2) / 2;
+	dy = MAX (abs(dY),2) / 2;
+	bDrawRectOpen ((X-dx), (Y-dy), (X+dx), (Y+dy));
+	// bDrawRectOpen ((X-dx), (Y-dy), (X), (Y));
+	break;
+      case KII_OVERLAY_CIRCLE:
+	dx = MAX (abs(dX),2);
+	dy = MAX (abs(dY),2);
+	if (image[0].overlay[N].objects[i].angle == 0.0) {
+	  bDrawArc (X, Y, dx, dy, 0, 360);
+	} else {
+	  // very stupid rotate ellipse drawing:
+	  double x, y, t;
+	  double angle = image[0].overlay[N].objects[i].angle * RAD_DEG;
+	  double cs = cos(angle);
+	  double sn = sin(angle);
+	  // XXX dt should be based on the size of the ellipse...
+	  for (t = 0; t < 2*M_PI; t+=0.05) {
+	    x = X + dx*cos(t)*cs + dy*sin(t)*sn;
+	    y = Y - dx*cos(t)*sn + dy*sin(t)*cs;
+	    bDrawPoint (x, y);
+	  }
+	}
+	break;
+      default:
+	fprintf (stderr, "skipping unknown object\n");
+	break;
+    }
+  }
+  
+  /* translate color to bDrawColors : image[0].overlay[N].color */
+  bDrawSetStyle (color, 0, 0);
+}
+
+/* this routine is independent of the number of overlays */
+
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/hh_hms.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/hh_hms.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/hh_hms.c	(revision 16062)
@@ -0,0 +1,28 @@
+# include "Ximage.h"
+
+void hh_hms (char *line, double ra, double dec, char sep) {
+
+  int h, m, flag;
+  double s;
+  
+  ra /= 15.0;  /* convert from degrees to hours */
+  flag = SIGN(ra);
+  ra *= flag;
+  h = ra;
+  m = 60.000001*(ra - h);
+  s = 3600*(ra - h - m / 60.0);
+  if (flag > 0)
+    sprintf (line, " %02d%c%02d%c%04.1f  ", h, sep, m, sep, s);
+  else
+    sprintf (line, "-%02d%c%02d%c%04.1f  ", h, sep, m, sep, s);
+  
+  flag = SIGN(dec);
+  dec *= flag;
+  h = dec;
+  m = 60.000001*(dec - h);
+  s = 3600*(dec - h - m / 60.0);
+  if (flag > 0)
+    sprintf (&line[13], " %02d%c%02d%c%04.1f", h, sep, m, sep, s);
+  else
+    sprintf (&line[13], "-%02d%c%02d%c%04.1f", h, sep, m, sep, s);
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/src/kapa.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/src/kapa.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/src/kapa.c	(revision 16062)
@@ -0,0 +1,14 @@
+# include "Ximage.h"
+
+int main (int argc, char **argv) {
+  
+  args (&argc, argv);
+
+  SetUpGraphic (&argc, argv);
+
+  InitLayout (argc, argv);
+  EventLoop ();
+
+  CloseDisplay ();
+  exit (0);
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/test/input
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/test/input	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/test/input	(revision 16062)
@@ -0,0 +1,32 @@
+
+macro go
+  mcreate a 512 512
+  set x = xramp(a)
+  set y = yramp(a)
+  set z = sqrt((x-256)^2 + (y-256)^2)
+  tvchannel 1
+  tv x 0 512
+  tvchannel 2
+  tv y 0 512
+  tvchannel 3
+  tv z 0 512
+end
+
+macro test
+  rd r dub.red.fits
+  rd g dub.green.fits
+  rd b dub.blue.fits
+  set R = r*(r >= 0) + (r + 256)*(r < 0)
+  set G = g*(g >= 0) + (g + 256)*(g < 0)
+  set B = b*(b >= 0) + (b + 256)*(b < 0)
+  tvchannel 1
+  tv R 0 256
+  tvchannel 2
+  tv G 0 256
+  tvchannel 3
+  tv B 0 256
+
+  tvcolor ruffcolor
+  sleep 1
+  tvcolor fullcolor
+end
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/textbox/CheckTextLines.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/textbox/CheckTextLines.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/textbox/CheckTextLines.c	(revision 16062)
@@ -0,0 +1,28 @@
+# include "Ximage.h"
+
+/******** Here we test the TextLines specific to this program  ****
+TextLine *
+CheckTextLines (graphic, event, layout)
+Graphic         graphic[];
+XEvent          event[];
+Layout          layout[];
+{
+
+  TextLine *textline;
+  textline = (TextLine *) NULL;
+
+  if (InTextLine (graphic, event, &layout[0].zero))
+    textline = &layout[0].zero;
+  if (InTextLine (graphic, event, &layout[0].range))
+    textline = &layout[0].range;
+  if (InTextLine (graphic, event, &layout[0].effects))
+    textline = &layout[0].effects;
+  if (InTextLine (graphic, event, &layout[0].command))
+    textline = &layout[0].command;
+
+  return (textline);
+
+}
+
+
+***/
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/textbox/DownArrow.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/textbox/DownArrow.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/textbox/DownArrow.c	(revision 16062)
@@ -0,0 +1,20 @@
+# include "Ximage"
+# include "ScrollBars.h"
+
+int 
+DownArrow (button_event, height, width, SB_x, SB_y)
+XButtonEvent *button_event;
+int height, width, SB_x, SB_y;
+{
+
+  int answer, m_x, m_y;
+
+  m_x = button_event -> x;
+  m_y = button_event -> y;
+  answer = ((m_y > (height - SB_y)) && 
+	    (m_x > (width - SB_y)));
+    return (answer);
+
+}
+
+
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/textbox/DrawCursor.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/textbox/DrawCursor.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/textbox/DrawCursor.c	(revision 16062)
@@ -0,0 +1,45 @@
+# include "Ximage.h"
+# define XBorder 5
+# define YBorder 2
+
+
+
+DrawCursor (graphic, textline)    
+Graphic       graphic[];
+TextLine      textline[];
+{
+
+  int dx, label_width, DX, text_width, i;
+
+  label_width  = XTextWidth (graphic[0].font, 
+			     textline[0].label,
+			     strlen(textline[0].label));
+  
+  text_width  = XTextWidth (graphic[0].font, 
+			    textline[0].text,
+			    strlen(textline[0].text));
+
+  XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].black);
+
+  if (label_width + text_width + 2*XBorder > textline[0].dx) {
+    DX = textline[0].dx - label_width - 2*XBorder - arrow_width;
+    for (i = 1; (i < strlen (textline[0].text)) && (text_width > DX); i++) {
+      text_width  = XTextWidth (graphic[0].font, 
+				&textline[0].text[i],
+				strlen(&textline[0].text[i]));
+    }
+    dx  = XTextWidth (graphic[0].font, &textline[0].text[i - 1], 
+		      textline[0].cursor - i + 1) + arrow_width;
+  }
+  else 
+    dx  = XTextWidth (graphic[0].font, textline[0].text, textline[0].cursor);
+
+  XDrawLine (graphic[0].display, 
+	     graphic[0].window, 
+	     graphic[0].gc, 
+	     textline[0].x + label_width + XBorder + dx, 
+	     textline[0].y + YBorder,
+	     textline[0].x + label_width + XBorder + dx, 
+	     textline[0].y + textline[0].dy - YBorder);
+
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/textbox/DrawTextBox.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/textbox/DrawTextBox.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/textbox/DrawTextBox.c	(revision 16062)
@@ -0,0 +1,63 @@
+# include "Ximage.h"
+# define XBorder 10
+# define YBorder 2
+# define arrow_width 6
+# define arrow_height 9
+static char arrow_bits[] = {
+  0x00, 0x02, 0x06, 0x0e, 0x1e, 0x0e, 0x06, 0x02, 0x00};
+#define down_width 9
+#define down_height 6
+static char down_bits[] = {
+   0x00, 0x00, 0xfe, 0x00, 0x7c, 0x00, 0x38, 0x00, 0x10, 0x00, 0x00, 0x00};
+
+/******************* DrawTextBox ****************/
+DrawTextBox (graphic, textbox)
+Graphic      graphic[];
+TextBox      textbox[];
+{
+
+  int X, Y, y, dy, Nlines, i;
+
+  XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].white);
+  XFillRectangle (graphic[0].display, 
+		  graphic[0].window,
+		  graphic[0].gc,
+		  textbox[0].x  + 1,  textbox[0].y + 1,
+		  XBorder - 2, textbox[0].dy - 2);
+  XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].black);
+  if (textbox[0].outline) {
+    XDrawRectangle (graphic[0].display, 
+		    graphic[0].window,
+		    graphic[0].gc,
+		    textbox[0].x,  textbox[0].y,
+		    textbox[0].dx, textbox[0].dy);
+  }
+
+  dy = graphic[0].font[0].ascent + graphic[0].font[0].descent;
+  Nlines = (textbox[0].dy - 2*YBorder) / dy;
+
+  for (i = 0; (i < Nlines) && (i < textbox[0].Nlines); i++) {
+    y = textbox[0].y + graphic[0].font[0].ascent + dy*i + YBorder;
+    XDrawString (graphic[0].display, 
+		 graphic[0].window, 
+		 graphic[0].gc, 
+		 textbox[0].x + XBorder, y,
+		 textbox[0].text[i], 
+		 strlen(textbox[0].text[i]));
+  }
+
+  if (Nlines < textbox[0].Nlines) {
+    DrawBitmap (graphic, 
+		textbox[0].x + textbox[0].dx - down_width - 2,
+		textbox[0].y + textbox[0].dy - down_height - 2,
+		down_width, down_height, down_bits, 1);
+  }
+
+  XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].black);
+  if (textbox[0].cursor_line != -1) {
+    Y = textbox[0].y + dy*textbox[0].cursor_line + YBorder + (dy - arrow_height)/2;
+    X = textbox[0].x + (XBorder - arrow_width) / 2;
+    DrawBitmap (graphic, X, Y, arrow_width, arrow_height, arrow_bits, 1);
+  }
+}
+
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/textbox/DrawTextLine.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/textbox/DrawTextLine.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/textbox/DrawTextLine.c	(revision 16062)
@@ -0,0 +1,34 @@
+# include "Ximage.h"
+# define XBorder 5
+# define YBorder 2
+
+DrawTextLine (graphic, textline)
+Graphic  graphic[];
+TextLine textline[];
+{
+
+  int y;
+
+  XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].black);
+  if (textline[0].outline) {
+    XDrawRectangle (graphic[0].display, 
+		    graphic[0].window,
+		    graphic[0].gc,
+		    textline[0].x,  textline[0].y,
+		    textline[0].dx, textline[0].dy);
+  }
+
+  y = textline[0].y + (textline[0].dy + graphic[0].font[0].ascent) / 2;
+  XDrawString (graphic[0].display, 
+	       graphic[0].window, 
+	       graphic[0].gc, 
+	       textline[0].x + XBorder, y,
+	       textline[0].label, 
+	       strlen(textline[0].label));
+  RedrawString (graphic, textline);
+
+  if (textline[0].cursor != -1)
+    DrawCursor (graphic, textline);
+
+}
+
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/textbox/InTextBox.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/textbox/InTextBox.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/textbox/InTextBox.c	(revision 16062)
@@ -0,0 +1,57 @@
+# include "Ximage.h"
+# define XBorder 10
+# define YBorder 2
+# define arrow_width 6
+# define arrow_height 9
+static char arrow_bits[] = {
+  0x00, 0x02, 0x06, 0x0e, 0x1e, 0x0e, 0x06, 0x02, 0x00};
+#define down_width 9
+#define down_height 6
+static char down_bits[] = {
+   0x00, 0x00, 0xfe, 0x00, 0x7c, 0x00, 0x38, 0x00, 0x10, 0x00, 0x00, 0x00};
+
+/******************* InTextBox ****************/
+int
+InTextBox (graphic, event, textbox)
+Graphic          graphic[];
+XButtonEvent    *event;
+TextBox          textbox[];
+{
+
+  int answer;
+  int i, x, y, Y, X, dy;
+  int minX, maxX, minY, maxY;
+  
+  x = event[0].x;
+  y = event[0].y;
+  dy = graphic[0].font[0].ascent + graphic[0].font[0].descent;
+  
+  minX = textbox[0].x;
+  maxX = textbox[0].x + textbox[0].dx;
+  minY = textbox[0].y;
+  maxY = textbox[0].y + textbox[0].dy;
+  if (dy*textbox[0].Nlines + 2*YBorder < textbox[0].dy)
+    maxY = textbox[0].y + dy*textbox[0].Nlines + 2*YBorder;
+
+  answer = ((x >= minX) && (x <= maxX) && (y >= minY) && (y <= maxY));
+  
+  /* find the cursor position, erase the old arrow and draw a new arrow */
+  if (answer) {
+    if (textbox[0].cursor_line != -1) {
+      Y = textbox[0].y + dy*textbox[0].cursor_line + YBorder + (dy - arrow_height)/2;
+      X = textbox[0].x + (XBorder - arrow_width) / 2;
+      DrawBitmap (graphic, X, Y, arrow_width, arrow_height, arrow_bits, 0);
+    }
+    textbox[0].cursor_line = (y - textbox[0].y - YBorder)/dy;
+    X = textbox[0].x + (XBorder - arrow_width) / 2;
+    Y = textbox[0].y + dy*textbox[0].cursor_line + YBorder + (dy - arrow_height)/2;
+    DrawBitmap (graphic, X, Y, arrow_width, arrow_height, arrow_bits, 1);
+    textbox[0].cursor_x = x;
+    textbox[0].cursor_y = y;
+    XFlush (graphic[0].display);
+  }
+  
+  return (answer);
+  
+}
+
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/textbox/InTextLine.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/textbox/InTextLine.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/textbox/InTextLine.c	(revision 16062)
@@ -0,0 +1,58 @@
+# include "Ximage.h"
+# define XBorder 5
+# define YBorder 2
+
+int
+InTextLine (graphic, event, textline)
+Graphic          graphic[];
+XButtonEvent    *event;
+TextLine         textline[];
+{
+
+  int answer, done;
+  int i, x, dx, y, text_width, label_width;
+  int minX, maxX, minY, maxY;
+  char testline[1000];
+
+  x = event[0].x;
+  y = event[0].y;
+  
+  label_width  = XTextWidth (graphic[0].font, 
+			     textline[0].label,
+			     strlen(textline[0].label));
+  
+  minX = textline[0].x + XBorder + label_width;
+  maxX = textline[0].x + textline[0].dx;
+  minY = textline[0].y;
+  maxY = textline[0].y + textline[0].dy;
+
+  answer = ((x >= minX) && (x <= maxX) && (y >= minY) && (y <= maxY));
+
+  /* find the cursor position and draw a vertical bar */
+  if (answer) {
+    text_width  = XTextWidth (graphic[0].font, 
+			      textline[0].text,
+			      strlen(textline[0].text));
+    
+    if (x >= minX + text_width) {
+      textline[0].cursor = strlen (textline[0].text);
+    }
+    else {
+      for (i = 1, done = FALSE; (i <= strlen (textline[0].text)) && !done; i++) {
+	dx  = XTextWidth (graphic[0].font, 
+			  textline[0].text, i);
+	if (x < minX + dx) {
+	  textline[0].cursor = i - 1;
+	  done = TRUE;
+	}
+      }
+    }
+    DrawCursor (graphic, textline);
+  }    
+  XFlush (graphic[0].display);
+  
+  return (answer);
+  
+}
+
+
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/textbox/LeftArrow.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/textbox/LeftArrow.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/textbox/LeftArrow.c	(revision 16062)
@@ -0,0 +1,18 @@
+# include "Ximage"
+# include "ScrollBars.h"
+
+int
+LeftArrow (button_event, height, width, SB_x, SB_y) 
+XButtonEvent *button_event;
+int height, width, SB_x, SB_y;
+{
+
+  int answer, m_x, m_y;
+
+  m_x = button_event -> x;
+  m_y = button_event -> y;
+  answer = ((m_x < SB_x) && (m_y < SB_x));
+  return (answer);
+
+}
+
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/textbox/RedrawString.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/textbox/RedrawString.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/textbox/RedrawString.c	(revision 16062)
@@ -0,0 +1,73 @@
+# include "Ximage.h"
+# define XBorder 5
+# define YBorder 2
+
+
+#define arrow_width 6
+#define arrow_height 9
+RedrawString (graphic, textline)
+Graphic       graphic[];
+TextLine      textline[];
+{
+
+  int label_width, text_width, y, i, DX;
+  static char arrow_bits[] = {
+    0x00, 0x10, 0x18, 0x1c, 0x1e, 0x1c, 0x18, 0x10, 0x00};
+  
+  label_width  = XTextWidth (graphic[0].font, 
+			     textline[0].label,
+			     strlen(textline[0].label));
+  
+  text_width  = XTextWidth (graphic[0].font, 
+			    textline[0].text,
+			    strlen(textline[0].text));
+
+  if (label_width + text_width + 2*XBorder > textline[0].dx) {
+    XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].white);
+    XFillRectangle (graphic[0].display, graphic[0].window, graphic[0].gc, 
+		    textline[0].x + XBorder + label_width, 
+		    textline[0].y + YBorder, 
+		    textline[0].dx - XBorder - label_width, 
+		    textline[0].dy - 2*YBorder + 1);
+    
+    DX = textline[0].dx - label_width - 2*XBorder - arrow_width;
+    for (i = 1; (i < strlen (textline[0].text)) && (text_width > DX); i++) {
+      text_width  = XTextWidth (graphic[0].font, 
+				&textline[0].text[i],
+				strlen(&textline[0].text[i]));
+    }
+
+    y = textline[0].y + (textline[0].dy + graphic[0].font[0].ascent) / 2;
+    XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].black);
+    DrawBitmap (graphic, 
+		textline[0].x + XBorder + label_width,
+		textline[0].y + YBorder + (textline[0].dy - arrow_height)/2,
+		arrow_width, arrow_height, arrow_bits, 1);
+    XDrawString (graphic[0].display, 
+		 graphic[0].window, 
+		 graphic[0].gc, 
+		 textline[0].x + XBorder + label_width + arrow_width, y,
+		 &textline[0].text[i - 1], 
+		 strlen(&textline[0].text[i - 1]));
+    XFlush (graphic[0].display);
+  }
+  else {
+    XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].white);
+    XFillRectangle (graphic[0].display, graphic[0].window, graphic[0].gc, 
+		    textline[0].x + XBorder + label_width, 
+		    textline[0].y + YBorder, 
+		    textline[0].dx - XBorder - label_width, 
+		    textline[0].dy - 2*YBorder + 1);
+    
+    y = textline[0].y + (textline[0].dy + graphic[0].font[0].ascent) / 2;
+    
+    XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].black);
+    XDrawString (graphic[0].display, 
+		 graphic[0].window, 
+		 graphic[0].gc, 
+		 textline[0].x + XBorder + label_width, y,
+		 textline[0].text, 
+		 strlen(textline[0].text));
+  }
+
+}
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/textbox/RightArrow.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/textbox/RightArrow.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/textbox/RightArrow.c	(revision 16062)
@@ -0,0 +1,20 @@
+# include "Ximage"
+# include "ScrollBars.h"
+
+int
+RightArrow (button_event, height, width, SB_x, SB_y) 
+XButtonEvent *button_event;
+int height, width, SB_x, SB_y;
+{
+
+  int answer, m_x, m_y;
+
+  m_x = button_event -> x;
+  m_y = button_event -> y;
+  answer = ((m_x < SB_x) && 
+	    (m_y > (height - SB_x - SB_y)) && 
+	    (m_y < (height - SB_y)));
+  return (answer);
+
+}
+
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/textbox/TextLineEntry.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/textbox/TextLineEntry.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/textbox/TextLineEntry.c	(revision 16062)
@@ -0,0 +1,81 @@
+# include "Ximage.h"
+# define XBorder 5
+# define YBorder 2
+
+int 
+TextLineEntry (graphic, textline, keyevent)
+Graphic        graphic[];
+TextLine       textline[];
+XKeyEvent     *keyevent;
+{
+
+  int i, status, N;
+  char dummy[3];
+  XComposeStatus compose_status;
+  KeySym keysym;
+
+  status = TRUE;
+  strcpy (textline[0].old_text, textline[0].text);
+  bzero (&textline[0].text[strlen(textline[0].text)], 
+	 1024 - strlen(textline[0].text));
+  i = textline[0].cursor;
+
+
+  N = XLookupString (keyevent, dummy, 1, &keysym, &compose_status);
+  switch (keysym) {
+  case XK_BackSpace:
+  case XK_Delete:
+    if (textline[0].cursor > 0) {
+      bcopy (&textline[0].text[i], &textline[0].text[i - 1], 
+	     strlen(&textline[0].text[i]) + 1);
+      RedrawString (graphic, textline);
+      textline[0].cursor --;
+      DrawCursor (graphic, textline);
+    }
+    break;
+  case XK_Left:
+    RedrawString (graphic, textline);
+    textline[0].cursor --;
+    if (textline[0].cursor < 0)
+      textline[0].cursor = 0;
+    DrawCursor (graphic, textline);
+    break;
+  case XK_Right:
+    RedrawString (graphic, textline);
+    textline[0].cursor ++;
+    if (textline[0].cursor > strlen (textline[0].text))
+      textline[0].cursor = strlen (textline[0].text);
+    DrawCursor (graphic, textline);
+    break;
+  case XK_Return:
+    RedrawString (graphic, textline);
+    textline[0].cursor = -1;
+    status = FALSE;
+    break;
+  case XK_d:
+  case XK_D: 
+    if (dummy[0] == 4) { /* a control-d was typed! */
+      if (textline[0].cursor < strlen(textline[0].text)) {
+	bcopy (&textline[0].text[i + 1], &textline[0].text[i], 
+	       strlen(&textline[0].text[i]));
+	RedrawString (graphic, textline);
+	DrawCursor (graphic, textline);
+      }
+      break;  /* WARNING: this case MUST come before default.
+		 anything between this and default will be executed
+		 if no cntl-d is typed! */
+    }
+  default:
+    if (N != 0) {
+      bcopy (&textline[0].text[i], &textline[0].text[i + 1], 
+	     strlen(&textline[0].text[i]));
+      textline[0].text[i] = dummy[0];
+      RedrawString (graphic, textline);
+      textline[0].cursor ++;
+      DrawCursor (graphic, textline);
+    }
+  }
+  return (status);
+}
+
+
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/textbox/UpArrow.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/textbox/UpArrow.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/textbox/UpArrow.c	(revision 16062)
@@ -0,0 +1,20 @@
+# include "Ximage"
+# include "ScrollBars.h"
+
+int
+UpArrow (button_event, height, width, SB_x, SB_y) 
+XButtonEvent *button_event;
+int height, width, SB_x, SB_y;
+{
+
+  int answer, m_x, m_y;
+
+  m_x = button_event -> x;
+  m_y = button_event -> y;
+  answer = ((m_y > (height - SB_y)) && 
+	    (m_x > SB_x) && 
+	    (m_x < (SB_x + SB_y)));
+  return (answer);
+
+}
+
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/textbox/xScrollBar.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/textbox/xScrollBar.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/textbox/xScrollBar.c	(revision 16062)
@@ -0,0 +1,26 @@
+# include "Ximage"
+# include "ScrollBars.h"
+
+int 
+xScrollBar (button_event, height, width, SB_x, SB_y, f)
+XButtonEvent *button_event;
+int height, width, SB_x, SB_y;
+double *f;
+{
+
+  int answer, m_x, m_y;
+  double f1, f2;
+
+  m_x = button_event -> x;
+  m_y = button_event -> y;
+  answer = ((m_x < SB_x) && 
+	    (m_y > SB_x) && 
+	    (m_y < (height - SB_x - SB_y)));
+  f1 = (double)(m_y - SB_x);
+  f2 = (double)(height - 2*SB_x - SB_y);
+  *f = f1 / f2;
+  return (answer);
+
+}
+
+
Index: /branches/eam_branch_20080124/Ohana/src/kapa2/textbox/yScrollBar.c
===================================================================
--- /branches/eam_branch_20080124/Ohana/src/kapa2/textbox/yScrollBar.c	(revision 16062)
+++ /branches/eam_branch_20080124/Ohana/src/kapa2/textbox/yScrollBar.c	(revision 16062)
@@ -0,0 +1,26 @@
+# include "Ximage"
+# include "ScrollBars.h"
+
+int
+yScrollBar (button_event, height, width, SB_x, SB_y, f)
+XButtonEvent *button_event;
+int height, width, SB_x, SB_y;
+double *f;
+{
+
+  int answer, m_x, m_y;
+  double f1, f2;
+
+  m_x = button_event -> x;
+  m_y = button_event -> y;
+  answer = ((m_y > (height - SB_y)) && 
+	    (m_x > (SB_x + SB_y)) && 
+	    (m_x < (width - SB_y)));
+  f1 = (double)(m_x - SB_x - SB_y);
+  f2 = (double)(width - 2*SB_y - SB_x);
+  *f = f1 / f2;
+  return (answer);
+
+}
+
+	
