Index: /trunk/Ohana/src/kapa2/Makefile
===================================================================
--- /trunk/Ohana/src/kapa2/Makefile	(revision 13320)
+++ /trunk/Ohana/src/kapa2/Makefile	(revision 13320)
@@ -0,0 +1,89 @@
+default: kapa2
+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
+
+kapa2: $(BIN)/kapa2.$(ARCH)
+install: $(DESTBIN)/kapa2
+
+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)/EraseCurrentPlot.$(ARCH).o         $(SRC)/EraseSections.$(ARCH).o      \
+$(SRC)/SetSection.$(ARCH).o		  $(SRC)/DefineSection.$(ARCH).o      \
+$(SRC)/SetLimits.$(ARCH).o                $(SRC)/SetFont.$(ARCH).o            \
+$(SRC)/cursor.$(ARCH).o                   $(SRC)/Stop.$(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)/PaintTickmarks.$(ARCH).o     \
+$(SRC)/LoadOverlay.$(ARCH).o		  $(SRC)/EraseOverlay.$(ARCH).o       \
+$(SRC)/LoadTickmarks.$(ARCH).o		  $(SRC)/SaveOverlay.$(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
+
+OBJ  =  $(KAPA)
+
+# dependancy rules for include files ########################
+$(OBJ): $(INC)/Ximage.h \
+	$(INC)/constants.h \
+	$(INC)/structures.h \
+	$(INC)/prototypes.h
+
+$(OBJ): $(INDEPS) $(LDDEPS)
+
+$(BIN)/kapa2.$(ARCH): $(OBJ)
Index: /trunk/Ohana/src/kapa2/include/Ximage.h
===================================================================
--- /trunk/Ohana/src/kapa2/include/Ximage.h	(revision 13320)
+++ /trunk/Ohana/src/kapa2/include/Ximage.h	(revision 13320)
@@ -0,0 +1,7 @@
+# include <Xohana.h>
+# include <dvo.h>
+# include <kapa.h>
+# include "constants.h"
+# include "structures.h"
+# include "prototypes.h"
+# include "globals.h"
Index: /trunk/Ohana/src/kapa2/include/alphabet.h
===================================================================
--- /trunk/Ohana/src/kapa2/include/alphabet.h	(revision 13320)
+++ /trunk/Ohana/src/kapa2/include/alphabet.h	(revision 13320)
@@ -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: /trunk/Ohana/src/kapa2/include/buttons.h
===================================================================
--- /trunk/Ohana/src/kapa2/include/buttons.h	(revision 13320)
+++ /trunk/Ohana/src/kapa2/include/buttons.h	(revision 13320)
@@ -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 puns_width 25
+#define puns_height 25
+static char puns_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: /trunk/Ohana/src/kapa2/include/constants.h
===================================================================
--- /trunk/Ohana/src/kapa2/include/constants.h	(revision 13320)
+++ /trunk/Ohana/src/kapa2/include/constants.h	(revision 13320)
@@ -0,0 +1,66 @@
+/* hardwired values for some window parameters */
+
+# define EVENT_MASK (long) \
+(ButtonPressMask \
+ | ClientMessage \
+ | ButtonReleaseMask \
+ | KeyPressMask \
+ | ExposureMask \
+ | StructureNotifyMask \
+ | PointerMotionMask)
+
+# define PAD1  5
+# define PAD2  3
+# define TEXTPAD 25
+# define COLORPAD 10
+# define TEXT_Y 15
+# define ZOOM_X 170
+# define ZOOM_Y 170
+# 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
+
+/* label names */
+# define LABELX0 0
+# define LABELY0 1
+# define LABELX1 2
+# define LABELY1 3
+# define LABELUL 4
+# define LABELUR 5
+# define LABELLL 6
+# define LABELLR 7
+
+/* 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: /trunk/Ohana/src/kapa2/include/globals.h
===================================================================
--- /trunk/Ohana/src/kapa2/include/globals.h	(revision 13320)
+++ /trunk/Ohana/src/kapa2/include/globals.h	(revision 13320)
@@ -0,0 +1,27 @@
+
+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: /trunk/Ohana/src/kapa2/include/icons.h
===================================================================
--- /trunk/Ohana/src/kapa2/include/icons.h	(revision 13320)
+++ /trunk/Ohana/src/kapa2/include/icons.h	(revision 13320)
@@ -0,0 +1,39 @@
+#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 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};
+#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: /trunk/Ohana/src/kapa2/include/kii.proto.h
===================================================================
--- /trunk/Ohana/src/kapa2/include/kii.proto.h	(revision 13320)
+++ /trunk/Ohana/src/kapa2/include/kii.proto.h	(revision 13320)
@@ -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: /trunk/Ohana/src/kapa2/include/kii.struct.h
===================================================================
--- /trunk/Ohana/src/kapa2/include/kii.struct.h	(revision 13320)
+++ /trunk/Ohana/src/kapa2/include/kii.struct.h	(revision 13320)
@@ -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: /trunk/Ohana/src/kapa2/include/prototypes.h
===================================================================
--- /trunk/Ohana/src/kapa2/include/prototypes.h	(revision 13320)
+++ /trunk/Ohana/src/kapa2/include/prototypes.h	(revision 13320)
@@ -0,0 +1,158 @@
+
+/* 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));
+
+/* 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           CheckPipe           PROTO(());
+int           Reconfig            PROTO((XEvent *event));
+void          Refresh             PROTO(());
+
+/* CheckPipe */
+int           PSit                PROTO(());
+int           PNGit               PROTO(());
+int           PPMit               PROTO(());
+int           LoadFrame           PROTO(());
+int           LoadObject          PROTO(());
+int           LoadLabels          PROTO(());
+int           LoadTextlines       PROTO(());
+int           LoadVectorData      PROTO(());
+int           Resize              PROTO(());
+int           GetLimits           PROTO(());
+int           SetLimits           PROTO(());
+int           SetSection          PROTO(());
+int           ListSection         PROTO(());
+int           DefineSection       PROTO(());
+int           SetFont             PROTO(());
+int           cursor              PROTO(());
+int           EraseCurrentPlot    PROTO(());
+int           ErasePlots          PROTO(());
+int           EraseSections       PROTO(());
+
+/* 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(());
+
+KapaGraphWidget *InitGraph        PROTO(());
+void          DrawGraph           PROTO((KapaGraphWidget *graph));
+void          SetGraphSize        PROTO((Section *section));
+
+void          InitLayout          PROTO((int argc, char **argv));
+
+/* PS drawing utilities */
+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));
+
+/* 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));
+
+# if (0)
+# endif
+
+/* 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           Center              PROTO(());
+void          Remap               PROTO((Graphic *graphic, KapaImageWidget *image, Matrix *matrix));
+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(());
+KapaImageWidget *InitImage        PROTO(());
+void          SetImageSize        PROTO((Section *section));
+int           GetPixelCount       PROTO(());
+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));
Index: /trunk/Ohana/src/kapa2/include/structures.h
===================================================================
--- /trunk/Ohana/src/kapa2/include/structures.h	(revision 13320)
+++ /trunk/Ohana/src/kapa2/include/structures.h	(revision 13320)
@@ -0,0 +1,170 @@
+
+/**************** Graphic carries X info around ****************/
+typedef struct {
+  Display       *display;
+  int            screen;
+  int            depth;
+  Window         window;
+  Visual        *visual;
+  int            visualclass;
+  int            Nbits;
+  GC             gc;
+  XFontStruct   *font;
+  Cursor         cursor;
+  int            x,  y;
+  int            dx, dy;
+  XColor         cmap[256];
+  Colormap       colormap;
+  unsigned long  fore;
+  unsigned long  back;
+  unsigned long  *color;
+  unsigned long  pixels[256];
+  unsigned long  overlay_color[NOVERLAYS];
+  int Npixels;
+  int Ncolors;
+} 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;
+  Object *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 */
+
+  Gobjects *objects;    /* graphic objects */    
+  int      Nobjects;    
+
+  Label    *textline;      /* placed text labels */
+  int      Ntextline;      
+} KapaGraphWidget;
+
+// 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   puns_button;
+  Button   overlay_button[NOVERLAYS];
+
+  // location of the status box
+  int      text_x, text_y;
+  int      location;	      // position of the zoom/status widgets (0 = none, 1-4 = bottom,left,top,right)
+  int      MovePointer;
+  int      DecimalDegrees;
+
+  // data associated with this image element
+  Overlay  overlay[NOVERLAYS];
+  Overlay  tickmarks;
+  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 */
+} KapaImageWidget;
+
+typedef struct {
+  KapaGraphWidget *graph;
+  KapaImageWidget *image;
+  float  x,  y;
+  float dx, dy;
+  char *name;
+} Section;
Index: /trunk/Ohana/src/kapa2/src/CSaveOverlay.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/CSaveOverlay.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/CSaveOverlay.c	(revision 13320)
@@ -0,0 +1,46 @@
+# include "Ximage.h"
+
+int CSaveOverlay () {
+
+  char filename[256];
+  int i, N;
+  double ra, dec, ra1, dec1, x1, y1, dra, ddec;
+  FILE *f;
+  Section *section;
+  KapaImageWidget *image;
+
+  section = GetActiveSection();
+  image   = section->image;
+
+  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++) {
+    if (!strcmp (image[0].overlay[N].objects[i].type, "LINE")) {
+      XY_to_RD (&ra, &dec, image[0].overlay[N].objects[i].x, image[0].overlay[N].objects[i].y, &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].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].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].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].coords);
+      dra = cos (dec*RAD_DEG) * fabs (ra1 - ra);
+    }
+    fprintf (f, "%s %lf %lf %lf %lf\n", image[0].overlay[N].objects[i].type, ra, dec, dra, ddec);
+   }
+  fclose (f);
+  return (TRUE);
+}
Index: /trunk/Ohana/src/kapa2/src/Center.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/Center.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/Center.c	(revision 13320)
@@ -0,0 +1,31 @@
+# include "Ximage.h"
+
+int Center () {
+
+  int zoom;
+  double X, Y;
+  Graphic *graphic;
+  Section *section;
+  KapaImageWidget *image;
+
+  graphic = GetGraphic();
+  section = GetActiveSection();
+  image = section->image;
+
+  KiiScanMessage (sock, "%lf %lf %d", &X,  &Y, &zoom);
+
+  image[0].X = 0.5*image[0].matrix.Naxis[0] - X;
+  image[0].Y = 0.5*image[0].matrix.Naxis[1] - Y;
+  if ((zoom != 0) && (zoom != -1)) {
+    image[0].expand = zoom;
+  }
+
+  if (USE_XWINDOW) {
+    Remap (graphic, image, &image[0].matrix);
+    Refresh ();
+    XFlush (graphic[0].display);
+  }
+
+  return (TRUE);
+}
+
Index: /trunk/Ohana/src/kapa2/src/CheckButtons.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/CheckButtons.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/CheckButtons.c	(revision 13320)
@@ -0,0 +1,53 @@
+# include "Ximage.h"
+# define PAD_X 10
+# define PAD_Y 10
+# define NPLANES 1
+# define NPIXELS 255
+
+/******** 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].puns_button)) 
+    button = &image[0].puns_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: /trunk/Ohana/src/kapa2/src/CheckColors.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/CheckColors.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/CheckColors.c	(revision 13320)
@@ -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: /trunk/Ohana/src/kapa2/src/CheckDisplayName.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/CheckDisplayName.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/CheckDisplayName.c	(revision 13320)
@@ -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: /trunk/Ohana/src/kapa2/src/CheckFontName.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/CheckFontName.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/CheckFontName.c	(revision 13320)
@@ -0,0 +1,28 @@
+# include "Ximage.h"
+
+/************** CheckFontName *************/
+void CheckFontName (int *argc, char **argv, char *fontname) {
+
+  int N;
+
+  if ((N = get_argument (*argc, argv, "-font"))) {
+    if (N + 1 < *argc) {
+      strcpy (fontname, argv[N + 1]);
+      remove_argument(N, argc, argv);
+      remove_argument(N, argc, argv);
+    } else {
+      fprintf (stderr, "error: usage is -font fontname\n");
+      exit (0);
+    }
+  }   
+  if ((N = get_argument (*argc, argv, "-fn"))) {
+    if (N + 1 < *argc) {
+      strcpy (fontname, argv[N + 1]);
+      remove_argument(N, argc, argv);
+      remove_argument(N, argc, argv);
+    } else {
+      fprintf (stderr, "error: usage is -fn fontname\n");
+      exit (0);
+    }
+  }   
+}
Index: /trunk/Ohana/src/kapa2/src/CheckGeometry.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/CheckGeometry.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/CheckGeometry.c	(revision 13320)
@@ -0,0 +1,28 @@
+# include "Ximage.h"
+
+/************** CheckGeometry *************/
+void CheckGeometry (Graphic *graphic, int *argc, char **argv) {
+
+  int status, x, y, N;
+  unsigned int dx, dy;
+  int X, Y, dX, dY;
+  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: /trunk/Ohana/src/kapa2/src/CheckPipe.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/CheckPipe.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/CheckPipe.c	(revision 13320)
@@ -0,0 +1,183 @@
+# include "Ximage.h"
+# define STRCONST(A) ((int)(0x1000000*A[0] + 0x10000*A[1] + 0x100*A[2] + 0x1*A[3]))
+
+int CheckPipe () {
+
+  int status;
+  char buffer[32];
+
+  /***** read (4 byte) message word from socket ****/
+  status = read (sock, buffer, 4);
+  buffer[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;
+  }
+  
+  /***** handle different messages ****/
+  if (!strcmp (buffer, "QUIT")) return (FALSE);
+  
+  if (!strcmp (buffer, "PSIT")) {
+    status = PSit ();
+    write (sock, "DONE", 4);
+    return (status);
+  }
+  
+  if (!strcmp (buffer, "PNGF")) {
+    status = PNGit ();
+    write (sock, "DONE", 4);
+    return (status);
+  }
+  
+  if (!strcmp (buffer, "PPMF")) {
+    status = PPMit ();
+    write (sock, "DONE", 4);
+    return (status);
+  }
+  
+  if (!strcmp (buffer, "DBOX")) {
+    status = LoadFrame ();
+    return (status);
+  }
+  
+  if (!strcmp (buffer, "PLOT")) {
+    status = LoadObject ();
+    return (status);
+  }
+  
+  if (!strcmp (buffer, "LABL")) {
+    status = LoadLabels ();
+    return (TRUE);
+  }
+  
+  if (!strcmp (buffer, "PTXT")) {
+    status = LoadTextlines ();
+    return (TRUE);
+  }
+  
+  if (!strcmp (buffer, "RSIZ")) {
+    status = Resize ();
+    return (status);
+  }
+
+  if (!strcmp (buffer, "LIMS")) {
+    GetLimits ();
+    return (TRUE);
+  }
+  
+  if (!strcmp (buffer, "SLIM")) {
+    status = SetLimits ();
+    return (TRUE);
+  }
+  
+  if (!strcmp (buffer, "SSEC")) {
+    status = SetSection ();
+    return (TRUE);
+  }
+  
+  if (!strcmp (buffer, "LSEC")) {
+    status = ListSection ();
+    return (TRUE);
+  }
+  
+  if (!strcmp (buffer, "DSEC")) {
+    status = DefineSection ();
+    return (TRUE);
+  }
+  
+  if (!strcmp (buffer, "FONT")) {
+    status = SetFont ();
+    return (TRUE);
+  }
+  
+  // XXX replace this with the "ActiveCursor" boolean?
+  if (!strcmp (buffer, "CURS")) {
+    cursor ();
+    return (TRUE);
+  }
+  
+  /* Erase Section */
+  if (!strcmp (buffer, "ERSC")) {
+    status = EraseCurrentPlot (TRUE);
+    return (status);
+  }
+  
+  /* Erase Section */
+  if (!strcmp (buffer, "ERAS")) {
+    status = ErasePlots (TRUE);
+    return (status);
+  }
+  
+  /* Don't Erase Section */
+  if (!strcmp (buffer, "ERSS")) {
+    status = EraseSections (FALSE);
+    return (status);
+  }
+  
+
+  if (!strcmp (buffer, "READ")) {
+    status = LoadPicture ();
+    return (status);
+  }
+
+  // XXX duplicate Command word
+  if (!strcmp (buffer, "ERAS")) {
+    status = EraseOverlay ();
+    return (status);
+  }
+
+  if (!strcmp (buffer, "LOAD")) {
+    status = LoadOverlay ();
+    return (status);
+  }
+
+  if (!strcmp (buffer, "TICK")) {
+    status = LoadTickmarks ();
+    return (status);
+  }
+
+  if (!strcmp (buffer, "SAVE")) {
+    status = SaveOverlay ();
+    return (status);
+  }
+
+  if (!strcmp (buffer, "CSVE")) {
+    status = CSaveOverlay ();
+    return (status);
+  }
+
+  if (!strcmp (buffer, "JPEG")) {
+    status = JPEGit24 ();
+    write (sock, "DONE", 4);
+    return (status);
+  }
+
+  if (!strcmp (buffer, "CENT")) {
+    status = Center ();
+    return (status);
+  }
+
+  if (!strcmp (buffer, "NPIX")) {
+    GetPixelCount ();
+    return (TRUE);
+  }
+
+  fprintf (stderr, "unknown signal %s\n", buffer);
+
+  return (TRUE);
+
+}
Index: /trunk/Ohana/src/kapa2/src/CheckVisual.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/CheckVisual.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/CheckVisual.c	(revision 13320)
@@ -0,0 +1,196 @@
+# include "Ximage.h"
+# define NPIXELS 64
+
+/* 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 col, def, dyn;
+  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);
+  }
+
+  col = def = dyn = FALSE;
+  if (DEBUG) fprintf (stderr, "default visual class is %d\n", visual_list[i].class);
+  switch (visual_list[i].class) {
+  case PseudoColor:
+    col = def = dyn = TRUE;
+    graphic[0].visual = visual_list[i].visual;
+    graphic[0].visualclass = TRUE;
+    goto test_pixels;
+    break;
+  default:
+    break;
+  }
+
+  for (i = 0; i < Nfound; i++) {
+    switch (visual_list[i].class) {
+    case PseudoColor:
+      if (DEBUG) fprintf (stderr, "selected visual class is %d\n", visual_list[i].class);
+      col = dyn = TRUE;
+      if (graphic[0].visual == visual_list[i].visual) {
+	def = TRUE;
+      } else {
+	graphic[0].visual = visual_list[i].visual;
+      }
+      graphic[0].visualclass = TRUE;
+      goto test_pixels;
+      break;
+    default:
+      break;
+    }
+  }
+
+  for (i = 0; i < Nfound; i++) {
+    switch (visual_list[i].class) {
+    case GrayScale:
+      if (DEBUG) fprintf (stderr, "selected visual class is %d\n", visual_list[i].class);
+      dyn = TRUE;
+      if (graphic[0].visual == visual_list[i].visual) {
+	def = TRUE;
+      } else {
+	graphic[0].visual = visual_list[i].visual;
+      }
+      graphic[0].visualclass = TRUE;
+      goto test_pixels;
+      break;
+    default:
+      break;
+    }
+  }
+
+  for (i = 0; (i < Nfound) && (visual_list[i].class != TrueColor); i++);
+  if (i != Nfound) {
+    col = TRUE;
+    if (DEBUG) fprintf (stderr, "visual class is %d\n", visual_list[i].class);
+    if (graphic[0].visual == visual_list[i].visual) {
+      def = TRUE;
+    } else {
+      graphic[0].visual = visual_list[i].visual;
+    }
+    graphic[0].visualclass = FALSE;
+    goto test_pixels;
+  }
+
+  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);
+    if (graphic[0].visual == visual_list[i].visual) {
+      def = TRUE;
+    } else {
+      graphic[0].visual = visual_list[i].visual;
+    }
+    graphic[0].visualclass = FALSE;
+    goto test_pixels;
+  }
+
+  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);
+    if (graphic[0].visual == visual_list[i].visual) {
+      def = TRUE;
+    } else {
+      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) */
+
+  if ((N = get_argument (*argc, argv, "-private"))) {
+    remove_argument(N, argc, argv);
+    def = FALSE;
+  } 
+
+  if (!def) {
+    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 (dyn) {
+    /* allocate color cells  */
+    for (graphic[0].Npixels = NPIXELS;
+	 ((graphic[0].Npixels >= 16) && 
+	  !XAllocColorCells (graphic[0].display, graphic[0].colormap, FALSE, planes, 1, graphic[0].pixels, graphic[0].Npixels));
+	 graphic[0].Npixels -= 4) {
+      if (DEBUG) fprintf (stderr, "trying %d colors\n", (int) graphic[0].Npixels);
+    }
+
+
+    /* make private colormap  */
+    if (graphic[0].Npixels < 16) {
+      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;
+	   ((graphic[0].Npixels >= 16) && 
+	    !XAllocColorCells (graphic[0].display, graphic[0].colormap, FALSE, planes, 1, graphic[0].pixels, graphic[0].Npixels));
+	   graphic[0].Npixels -= 4);
+
+      if ((N = get_argument (*argc, argv, "-colorcount"))) {
+	fprintf (stderr, "kii can grab %d colors\n", (int) graphic[0].Npixels);
+	exit (0);
+      } 
+      if (graphic[0].Npixels < 16) {
+	fprintf (stderr, "can't even allocate enough cells in private colormap\n");
+	exit (0);
+      }
+    }
+  }
+
+  if (!dyn) {
+    graphic[0].Npixels = 256;
+    fprintf (stderr, "can't use dynamic colors, color scrollbar inactive\n");
+    fprintf (stderr, " this can be avoided by using a dynamic visual class\n");
+    fprintf (stderr, " (see Kii help page for details)\n");
+  }
+
+  if ((N = get_argument (*argc, argv, "-colorcount"))) {
+    fprintf (stderr, "kii can grab %d colors\n", (int) 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: /trunk/Ohana/src/kapa2/src/CloseDisplay.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/CloseDisplay.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/CloseDisplay.c	(revision 13320)
@@ -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: /trunk/Ohana/src/kapa2/src/ConvertPixmap.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/ConvertPixmap.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/ConvertPixmap.c	(revision 13320)
@@ -0,0 +1,262 @@
+# include "Ximage.h"
+
+void ConvertPixmap8 (Layout *layout, FILE *f) {
+
+  int i, k, m, val;
+  double Nchar, Npix, start, slope, frac;
+  unsigned char *buff;
+
+  Nchar = 255.0;
+  Npix = layout[0].Npixels;
+  frac = Nchar / Npix;
+  /* start at the last line, print lines in decending order */
+  buff = (unsigned char *)layout[0].picture.data + layout[0].picture.dx*(layout[0].picture.dy - 1);
+  slope = layout[0].slope;
+  start = layout[0].start;
+
+  for (i = 0; i < layout[0].picture.dy; i++) {
+    for (k = 0; k < layout[0].picture.dx; k++, buff++) {
+      if (*buff == layout[0].white) 
+	val = Nchar;
+      else {
+	for (m = 0; (layout[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*layout[0].picture.dx;
+  }
+  return;
+}
+
+void ConvertPixmap16 (Layout *layout, FILE *f) {
+
+  int i, k, m, val;
+  double Nchar, Npix, start, slope, frac;
+  unsigned short *buff;
+
+  Nchar = 255.0;
+  Npix = layout[0].Npixels;
+  frac = Nchar / Npix;
+  /* start at the last line, print lines in decending order */
+  buff = (unsigned short *)layout[0].picture.data + layout[0].picture.dx*(layout[0].picture.dy - 1);
+  slope = layout[0].slope;
+  start = layout[0].start;
+
+  for (i = 0; i < layout[0].picture.dy; i++) {
+    for (k = 0; k < layout[0].picture.dx; k++, buff++) {
+      if (*buff == layout[0].white) 
+	val = Nchar;
+      else {
+	for (m = 0; (layout[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*layout[0].picture.dx;
+  }
+  return;
+}
+
+void ConvertPixmap24 (Layout *layout, FILE *f) {
+
+  int i, k, m, dx, dy, val, extra;
+  unsigned char *buff;
+  unsigned long color, byte;
+  double Nchar, Npix, start, slope, frac;
+
+  Nchar = 255.0;
+  Npix = layout[0].Npixels;
+  frac = Nchar / Npix;
+  dx = layout[0].picture.dx;
+  dy = layout[0].picture.dy;
+  extra = 4 - (dx * 3) % 4;
+  /* start at the last line, print lines in decending order */
+  buff = (unsigned char *)&layout[0].picture.data[(dy - 1)*(3*dx + extra)];
+  slope = layout[0].slope;
+  start = layout[0].start;
+
+  for (i = 0; i < dy; i++) {
+    for (k = 0; k < dx; k++, buff+=3) {
+      color = 0;
+      byte = buff[2];
+      color = (byte << 16);
+      byte = buff[1];
+      color |= (byte << 8);
+      byte = buff[0];
+      color |= byte;
+      for (m = 0; (layout[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 ConvertPixmap32 (Layout *layout, FILE *f) {
+
+  int i, k, m, val;
+  double Nchar, Npix, start, slope, frac;
+  unsigned int *buff;
+
+  Nchar = 255.0;
+  Npix = layout[0].Npixels;
+  frac = Nchar / Npix;
+  /* start at the last line, print lines in decending order */
+  buff = (unsigned int *)layout[0].picture.data + layout[0].picture.dx*(layout[0].picture.dy - 1);
+  slope = layout[0].slope;
+  start = layout[0].start;
+
+  for (i = 0; i < layout[0].picture.dy; i++) {
+    for (k = 0; k < layout[0].picture.dx; k++, buff++) {
+      if (*buff == layout[0].white) 
+	val = Nchar;
+      else {
+	for (m = 0; (layout[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*layout[0].picture.dx;
+  }
+  return;
+}
+
+# if (0)
+void ConvertPixmap (Layout *layout, File *f) {
+  
+  /* set up expansions */
+  expand = expand_in = expand_out = 1.0;
+  if (layout[0].expand == 0)
+    layout[0].expand = 1;
+  if (layout[0].expand > 0) {
+    expand = 1 / (1.0*layout[0].expand);
+    expand_out = layout[0].expand;
+    expand_in  = 1;
+  }
+  if (layout[0].expand < 0) {
+    expand = fabs((double)layout[0].expand);
+    expand_out = 1;
+    expand_in  = -layout[0].expand;
+  }
+
+  dx = layout[0].picture.dx;
+  dy = layout[0].picture.dy;
+  DX = layout[0].matrix.Naxis[0];
+  DY = layout[0].matrix.Naxis[1];
+
+  /* X,Y are the image coordinates of the first image pixel */
+  X = MAX(0.5*(DX - dx*expand) - layout[0].X, 0);
+  if ((int)X != X) 
+    X = (int) X + 1;
+  else 
+    X = (int) X;
+  Y = MAX(0.5*(DY - dy*expand) - layout[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 + layout[0].X - 0.5*DX)/expand + 0.5*dx;
+  Ry = (Y + layout[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 (layout[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 (line_buffer, char, dx);
+
+  in_pix_ref  = (unsigned char *) (layout[0].matrix.buffer) + DX*(int)MAX(Y,0) + (int)MAX(X,0);
+
+  /********** below we do the mapping from buffer pixels (in) to picture pixels (out) **********/
+
+  Nchar = 255.0;
+  Npix = layout[0].Npixels;
+  frac = Nchar / Npix;
+
+  /**** fill in bottom area ****/
+  out_pix = line_buffer;
+  for (i = 0; i < dx; i++, out_pix++) {
+    *out_pix = WHITE;
+  }
+  for (j = 0; j < j_start; j++) {
+    for (i = 0; i < dx; i++) {
+      fprintf (f, "%02x", val);
+      if ((Npt % 40) == 0) {
+	fprintf (f, "\n");
+      }
+    }
+  }
+  
+  /*** 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 = WHITE;
+    }
+    
+    /*** 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++) {
+	*out_pix = *in_pix*frac;
+      }
+    }
+    
+    /**** fill in area to the right of the picture ****/
+    for (i = i_end; i < dx; i++, out_pix++) {
+      *out_pix = WHITE;
+    }
+
+    /* write out the image line expand_out times */
+    for (j = 0; j < expand_out; j++) {
+      for (i = 0; i < dx; i++) {
+	fprintf (f, "%02x", val);
+	if ((Npt % 40) == 0) {
+	  fprintf (f, "\n");
+	}
+      }
+    }
+  }
+
+  /**** fill in top area ****/
+  out_pix = line_buffer;
+  for (i = 0; i < dx; i++, out_pix++) { 
+    *out_pix = WHITE;
+  }
+  for (j = j_end; j < dy; j++) {
+    for (i = 0; i < dx; i++) {
+      fprintf (f, "%02x", val);
+      if ((Npt % 40) == 0) {
+	fprintf (f, "\n");
+      }
+    }
+  }
+}
+# endif
+
Index: /trunk/Ohana/src/kapa2/src/CreateColorbar.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/CreateColorbar.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/CreateColorbar.c	(revision 13320)
@@ -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: /trunk/Ohana/src/kapa2/src/CreatePicture.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/CreatePicture.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/CreatePicture.c	(revision 13320)
@@ -0,0 +1,68 @@
+# 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));
+    fprintf (stderr, "allocating %d for picture data\n", (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: /trunk/Ohana/src/kapa2/src/CreateWindow.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/CreateWindow.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/CreateWindow.c	(revision 13320)
@@ -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: /trunk/Ohana/src/kapa2/src/CreateZoom.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/CreateZoom.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/CreateZoom.c	(revision 13320)
@@ -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: /trunk/Ohana/src/kapa2/src/CreateZoom16.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/CreateZoom16.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/CreateZoom16.c	(revision 13320)
@@ -0,0 +1,134 @@
+# include "Ximage.h"
+# define XPIX(x,Rx,S) (x*S + Rx)
+# define ZPIX(value,Rz1,Rz2) (value*Rz1 - Rz2)
+# define FRAC(a) ((a) - (int)(a))
+
+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;
+  double expand, zoomscale, Rx, Ry;
+  int expand_in, expand_out;
+  unsigned char *out_pix, *out_pix2, *data;
+  unsigned char *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].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);
+
+  zoomscale = MAX (5, image[0].expand + 5);
+  expand = 1 / zoomscale;
+  expand_out = (int) zoomscale;
+  expand_in  = 1;
+
+  DX = image[0].matrix.Naxis[0];
+  DY = 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;
+  in_pix  = (unsigned char *) (image[0].matrix.buffer) + 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) {
+	out_pix[0] = pixel1[*in_pix2];
+	out_pix[1] = pixel2[*in_pix2];
+      }
+    }
+    else {
+      for (i = i_start; i < i_end; i+= expand_out, in_pix2++, out_pix+= 2*expand_out) { 
+	pixvalue1 = pixel1[*in_pix2];
+	pixvalue2 = pixel2[*in_pix2];
+	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, 16, ZPixmap, 0, 
+					image[0].zoom.data, image[0].zoom.dx, image[0].zoom.dy, 32, 0);
+  
+}
Index: /trunk/Ohana/src/kapa2/src/CreateZoom24.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/CreateZoom24.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/CreateZoom24.c	(revision 13320)
@@ -0,0 +1,167 @@
+# include "Ximage.h"
+# define XPIX(x,Rx,S) (x*S + Rx)
+# define ZPIX(value,Rz1,Rz2) (value*Rz1 - Rz2)
+# define FRAC(a) ((a) - (int)(a))
+
+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;
+  double expand, zoomscale, Rx, Ry;
+  int expand_in, expand_out;
+  unsigned char *out_pix, *out_pix2, *data;
+  unsigned char *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].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);
+
+  zoomscale = MAX (5, image[0].expand + 5);
+  expand = 1 / zoomscale;
+  expand_out = (int) zoomscale;
+  expand_in  = 1;
+
+  DX = image[0].matrix.Naxis[0];
+  DY = 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;
+  in_pix  = (unsigned char *) (image[0].matrix.buffer) + 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) {
+	out_pix[0] = pixel1[*in_pix2];
+	out_pix[1] = pixel2[*in_pix2];
+	out_pix[2] = pixel3[*in_pix2];
+      }
+    }
+    else {
+      for (i = i_start; i < i_end; i+= expand_out, in_pix2++, out_pix+= 3*expand_out) { 
+	pixvalue1 = pixel1[*in_pix2];
+	pixvalue2 = pixel2[*in_pix2];
+	pixvalue3 = pixel3[*in_pix2];
+	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: /trunk/Ohana/src/kapa2/src/CreateZoom32.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/CreateZoom32.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/CreateZoom32.c	(revision 13320)
@@ -0,0 +1,122 @@
+# include "Ximage.h"
+# define XPIX(x,Rx,S) (x*S + Rx)
+# define ZPIX(value,Rz1,Rz2) (value*Rz1 - Rz2)
+# 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, *data;
+  unsigned char  *in_pix,  *in_pix2;
+  unsigned long pixel[256], pixvalue;
+  unsigned long back;
+
+  if (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;
+  }
+
+  for (i = 0; i < 256; i++) { /* set up pixel array */
+    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].matrix.Naxis[0];
+  DY = 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 int *) image[0].zoom.data;
+  data = (unsigned int *) image[0].zoom.data;
+  in_pix  = (unsigned char *) (image[0].matrix.buffer) + 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[0] = 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_pix[0] = 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[0] = 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[0] = 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[0] = 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[0] = back;
+  }
+
+  out_pix = (unsigned int *)image[0].zoom.data;
+  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);
+  
+}
Index: /trunk/Ohana/src/kapa2/src/CreateZoom8.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/CreateZoom8.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/CreateZoom8.c	(revision 13320)
@@ -0,0 +1,140 @@
+# include "Ximage.h"
+# define XPIX(x,Rx,S) (x*S + Rx)
+# define ZPIX(value,Rz1,Rz2) (value*Rz1 - Rz2)
+# define FRAC(a) ((a) - (int)(a))
+
+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;
+  double expand, zoomscale, Rx, Ry;
+  int expand_in, expand_out;
+  char  *out_pix, *out_pix2;
+  char  *in_pix,  *in_pix2;
+  unsigned long pixel[256], pixvalue;
+  unsigned long back;
+
+  if (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;
+
+  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].matrix.Naxis[0];
+  DY = image[0].matrix.Naxis[1];
+  Rx = 0.5*(DX - (dx - 1)*expand) - x;
+  Ry = 0.5*(DY - (dy - 1)*expand) - y;
+  data coords of 0,0 point in pic array 
+  X = 0.5*image[0].matrix.Naxis[0] - expand*((int)(0.5*image[0].zoom.dx + 0.5) - 0.0) - image[0].X;
+  Y = 0.5*image[0].matrix.Naxis[1] - expand*((int)(0.5*image[0].zoom.dy + 0.5) - 0.0) - image[0].Y;  
+  i_start = MIN (MAX (-Rx / expand, 0), dx - expand_out + 1);
+  j_start = MIN (MAX (-Ry / expand, 0), 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 = image[0].zoom.data;
+  in_pix  = (char *) (image[0].matrix.buffer) + DX*(int)MAX(Y,0) + (int)MAX(X,0);
+
+  */
+
+  dx = image[0].zoom.dx;
+  dy = image[0].zoom.dy;
+  DX = image[0].matrix.Naxis[0];
+  DY = 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 = (char *) image[0].zoom.data;
+  in_pix  = (char *) (image[0].matrix.buffer) + 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++)
+	*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 - 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: /trunk/Ohana/src/kapa2/src/CrossHairs.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/CrossHairs.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/CrossHairs.c	(revision 13320)
@@ -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: /trunk/Ohana/src/kapa2/src/CursorOps.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/CursorOps.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/CursorOps.c	(revision 13320)
@@ -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].matrix.Naxis[0] - image[0].X;
+  *y1 = expand*(y2 - image[0].picture.y - 0.5*image[0].picture.dy) + 0.5*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].matrix.Naxis[0] + image[0].X) * expand + image[0].picture.x + 0.5*image[0].picture.dx;
+  *y1 = (y2 - 0.5*image[0].matrix.Naxis[1] + image[0].Y) * expand + image[0].picture.y + 0.5*image[0].picture.dy;
+  
+}
+
Index: /trunk/Ohana/src/kapa2/src/DefineLayout.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/DefineLayout.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/DefineLayout.c	(revision 13320)
@@ -0,0 +1,56 @@
+# include "Ximage.h"
+# define PAD 40
+
+/* general initialization for things not specific to X */
+void DefineLayout (int argc, char **argv) {
+
+  int i;
+  
+  /** initiate connection with server **/
+  if (!FOREGROUND) {	
+    if (argc < 2) {
+      fprintf (stderr, "socket path not specified\n");
+      exit (0);
+    }
+    sock = KiiWait (argv[1]);
+  }
+
+  InitRotFonts ();
+
+  /** set up defaults for display region **/
+  /* default startup uses one graphic region, filling the window */
+  
+  Nsection = 1;
+  ALLOCATE (section, Layout, Nsection);
+  TheSection = 0;
+
+  /* set up axis positions */
+  for (i = 0; i < 4; i++) {
+    section[0].axis[i].min = 0.0;
+    section[0].axis[i].max = 1.0;
+    section[0].axis[i].isaxis = FALSE;
+    section[0].axis[i].areticks = FALSE;
+    section[0].axis[i].islabel = FALSE;
+  }    
+  for (i = 0; i < 8; i++) {
+    strcpy (section[0].label[i].text, "");
+  }
+  section[0].x  = 0;
+  section[0].dx = 1; 
+  section[0].y  = 0; 
+  section[0].dy = 1; 
+  strcpy (section[0].name, "default");
+
+  PositionPicture (&section[0]);
+
+  section[0].Nobjects = 0;
+  section[0].Nptext = 0;
+
+  ALLOCATE (section[0].objects, Gobjects, 1);  /* allocate so later free will not crash! */
+  section[0].objects[0].x   = section[0].objects[0].y   = section[0].objects[0].z = (float *) NULL;
+  section[0].objects[0].dxm = section[0].objects[0].dxp = (float *) NULL;
+  section[0].objects[0].dym = section[0].objects[0].dyp = (float *) NULL;
+  
+  ALLOCATE (section[0].ptext, Label, 1);       /* allocate so later free will not crash! */
+
+}
Index: /trunk/Ohana/src/kapa2/src/DefineSection.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/DefineSection.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/DefineSection.c	(revision 13320)
@@ -0,0 +1,40 @@
+# include "Ximage.h"
+
+int DefineSection () {
+  
+  int i, 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);
+    section->graph = InitGraph ();
+    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) {
+    SetGraphSize (section);
+    Refresh (1);
+  }
+
+  return (TRUE);
+}
Index: /trunk/Ohana/src/kapa2/src/DragColorbar.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/DragColorbar.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/DragColorbar.c	(revision 13320)
@@ -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].slope;
+  start = 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].start = start;	
+	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: /trunk/Ohana/src/kapa2/src/DrawBitmap.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/DrawBitmap.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/DrawBitmap.c	(revision 13320)
@@ -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: /trunk/Ohana/src/kapa2/src/DrawButton.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/DrawButton.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/DrawButton.c	(revision 13320)
@@ -0,0 +1,45 @@
+# include "Ximage.h"
+
+void DrawButton (Graphic *graphic, Button *button) {
+  
+  int y, dX;
+  
+  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: /trunk/Ohana/src/kapa2/src/DrawFrame.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/DrawFrame.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/DrawFrame.c	(revision 13320)
@@ -0,0 +1,166 @@
+# include "Ximage.h"
+# 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) {
+      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;
+	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;
+
+  lrange = log10(MAX(fabs(range), 1e-30));
+  mantis = modf (lrange, &factor);
+  if (mantis < 0.0) {
+    mantis += 1.0;
+    factor -= 1.0;
+  }
+  
+  power = pow(10.0, factor);
+  fmantis = pow(10.0, mantis);
+  *major = 0.5 * power;
+  *minor = 0.1 * power;
+  
+  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: /trunk/Ohana/src/kapa2/src/DrawLabels.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/DrawLabels.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/DrawLabels.c	(revision 13320)
@@ -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: /trunk/Ohana/src/kapa2/src/DrawObjects.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/DrawObjects.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/DrawObjects.c	(revision 13320)
@@ -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: /trunk/Ohana/src/kapa2/src/DrawPtext.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/DrawPtext.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/DrawPtext.c	(revision 13320)
@@ -0,0 +1,36 @@
+# include "Ximage.h"
+  
+void DrawPtext (Layout *layout) {
+  
+  int i, x, y, size;
+  double angle;
+  char *fontname;
+
+  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 < layout[0].Nptext; i++) {
+    if (strcmp (layout[0].ptext[i].text, "")) {
+      angle = layout[0].ptext[i].angle;
+      x = layout[0].ptext[i].x;
+      y = layout[0].ptext[i].y;
+      SetRotFont (layout[0].ptext[i].font, layout[0].ptext[i].size);
+      DrawRotText (x, y, layout[0].ptext[i].text, 5, angle);
+    }
+  }
+  SetRotFont (fontname, size);
+}
+
+  /* pos values
+            
+ 4____2___5 
+  |       | 
+  |       | 
+ 1|   8   |3
+  |       |
+  |       |
+  ---------
+  6   0   7
+
+  */
Index: /trunk/Ohana/src/kapa2/src/DrawText.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/DrawText.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/DrawText.c	(revision 13320)
@@ -0,0 +1,39 @@
+# include "Ximage.h"
+  
+/* Draw text centered at x,y */
+
+void DrawText (int x, int y, char *string, int pos) {
+
+  char *c;
+  int dx, dy;
+
+  for (c = string; (*c == ' ') || (*c == '\t'); c++);
+  if (*c == 0) return;
+  
+  dx  = XTextWidth (graphic.font, c, strlen(c));
+  dy  = graphic.font[0].ascent;
+  switch (pos) {
+  case 0: XDrawString (graphic.display, graphic.window, graphic.gc, x - dx,   y + dy,   c, strlen(c)); break;
+  case 1: XDrawString (graphic.display, graphic.window, graphic.gc, x - dx/2, y + dy,   c, strlen(c)); break;
+  case 2: XDrawString (graphic.display, graphic.window, graphic.gc, x,        y + dy,   c, strlen(c)); break;
+  case 3: XDrawString (graphic.display, graphic.window, graphic.gc, x - dx,   y + dy/2, c, strlen(c)); break;
+  case 4: XDrawString (graphic.display, graphic.window, graphic.gc, x - dx/2, y + dy/2, c, strlen(c)); break;
+  case 5: XDrawString (graphic.display, graphic.window, graphic.gc, x,        y + dy/2, c, strlen(c)); break;
+  case 6: XDrawString (graphic.display, graphic.window, graphic.gc, x - dx,   y,        c, strlen(c)); break;
+  case 7: XDrawString (graphic.display, graphic.window, graphic.gc, x - dx/2, y,        c, strlen(c)); break;
+  case 8: XDrawString (graphic.display, graphic.window, graphic.gc, x,        y,        c, strlen(c)); break;
+  }
+}
+
+/*
+            
+ 6____7___8
+  |       | 
+  |       | 
+ 3|   4   |5
+  |       |
+  |       |
+  ---------
+ 0    1   2
+
+*/
Index: /trunk/Ohana/src/kapa2/src/DrawTextlines.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/DrawTextlines.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/DrawTextlines.c	(revision 13320)
@@ -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: /trunk/Ohana/src/kapa2/src/EraseCurrentPlot.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/EraseCurrentPlot.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/EraseCurrentPlot.c	(revision 13320)
@@ -0,0 +1,19 @@
+# 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: /trunk/Ohana/src/kapa2/src/EraseOverlay.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/EraseOverlay.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/EraseOverlay.c	(revision 13320)
@@ -0,0 +1,33 @@
+# include "Ximage.h"
+
+int EraseOverlay () {
+
+  char buffer[256];
+  int i, status, N;
+  Graphic *graphic;
+  Section *section;
+  KapaImageWidget *image;
+
+  graphic = GetGraphic();
+  section = GetActiveSection();
+  image = section->image;
+
+  KiiScanCommand (sock, 16, "%d", &N);
+
+  if (N > NOVERLAYS) {
+    REALLOCATE (image[0].tickmarks.objects, Object, 1);
+    image[0].tickmarks.Nobjects = 0;
+  } else {
+    for (i = 0; i < image[0].overlay[N].Nobjects; i++) {
+      if (!strcmp (image[0].overlay[N].objects[i].type, "TEXT")) {
+	free (image[0].overlay[N].objects[i].text);
+      }
+    }
+    REALLOCATE (image[0].overlay[N].objects, Object, 1);
+    image[0].overlay[N].Nobjects = 0;
+    image[0].overlay[N].active = FALSE;
+  }
+
+  if (USE_XWINDOW) Refresh ();
+  return (TRUE);
+}
Index: /trunk/Ohana/src/kapa2/src/ErasePlot.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/ErasePlot.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/ErasePlot.c	(revision 13320)
@@ -0,0 +1,66 @@
+# include "Ximage.h"
+# define TESTFREE(a) { if ((a) != (float *) NULL) free (a);}
+
+// XXX need to define cases:
+// * erase just the current graph (delete objects & redraw)
+// * erase all graphs
+// * drop all sections
+
+int ErasePlot (int ClearSection) {
+  
+  int i, j;
+
+  for (j = 0; j < Nsection; j++) {
+
+    /* free data objects, then re-alloc those needed */
+    for (i = 0; i < section[j].Nobjects; i++) {
+      TESTFREE (section[j].objects[i].x);
+      TESTFREE (section[j].objects[i].y);
+      TESTFREE (section[j].objects[i].z);
+      TESTFREE (section[j].objects[i].dxm);
+      TESTFREE (section[j].objects[i].dxp);
+      TESTFREE (section[j].objects[i].dym);
+      TESTFREE (section[j].objects[i].dyp);
+    }
+    
+    /* reset axes and labels */
+    for (i = 0; i < 4; i++) {
+      section[j].axis[i].isaxis = FALSE;
+      section[j].axis[i].islabel = FALSE;
+      section[j].axis[i].areticks = FALSE;
+    }
+    for (i = 0; i < 8; i++) {
+      strcpy (section[j].label[i].text, "");
+    }
+    
+    /* free objects and text entries, or re-zero */
+    if (ClearSection && (j != 0)) {
+      free (section[j].objects);
+      free (section[j].ptext);
+    } else {
+      section[j].Nobjects = 0;
+      REALLOCATE (section[j].objects, Gobjects, 1);
+      section[j].Nptext = 0;
+      REALLOCATE (section[j].ptext, Label, 1);
+    }
+  }
+
+  if (ClearSection) {
+    Nsection = 1;
+    TheSection = 0;
+    REALLOCATE (section, Layout, Nsection);
+  }
+
+  if (USE_XWINDOW) XClearWindow (graphic.display, graphic.window);
+  Refresh (1);
+
+  return (TRUE);
+  
+}
+
+
+/** note that 'section' is the global variable
+    of type 'Layout' which carries data and info 
+    about each graph section 
+**/
+
Index: /trunk/Ohana/src/kapa2/src/ErasePlots.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/ErasePlots.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/ErasePlots.c	(revision 13320)
@@ -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: /trunk/Ohana/src/kapa2/src/EraseSections.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/EraseSections.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/EraseSections.c	(revision 13320)
@@ -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: /trunk/Ohana/src/kapa2/src/EventLoop.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/EventLoop.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/EventLoop.c	(revision 13320)
@@ -0,0 +1,143 @@
+# 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 (0)
+    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, &event);
+# endif
+
+    /* 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: /trunk/Ohana/src/kapa2/src/FlashButton.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/FlashButton.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/FlashButton.c	(revision 13320)
@@ -0,0 +1,22 @@
+# include "Ximage.h"
+
+void FlashButton (Graphic *graphic, Button *button) {
+
+  unsigned long black, white;
+
+  black =  graphic[0].black;
+  white =  graphic[0].white;
+  graphic[0].black = white;
+  graphic[0].white = black;
+
+  DrawButton (graphic, button);
+  XFlush (graphic[0].display);
+/*  usleep (20000);  removed - not a standard C sleep command, apparently! */
+  
+  graphic[0].black = black;
+  graphic[0].white = white;
+  DrawButton (graphic, button);
+  XFlush (graphic[0].display);
+
+}
+
Index: /trunk/Ohana/src/kapa2/src/FlushDisplay.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/FlushDisplay.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/FlushDisplay.c	(revision 13320)
@@ -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: /trunk/Ohana/src/kapa2/src/GetColor.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/GetColor.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/GetColor.c	(revision 13320)
@@ -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: /trunk/Ohana/src/kapa2/src/GetPixelCount.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/GetPixelCount.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/GetPixelCount.c	(revision 13320)
@@ -0,0 +1,14 @@
+# include "Ximage.h"
+
+int GetPixelCount () {
+  
+  int i;
+  double xmin, xmax, ymin, ymax;
+  Graphic *graphic;
+
+  graphic = GetGraphic();
+
+  KiiSendMessage (sock, "NPIX: %8d", graphic->Npixels);
+  
+  return (TRUE);
+}
Index: /trunk/Ohana/src/kapa2/src/Graphs.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/Graphs.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/Graphs.c	(revision 13320)
@@ -0,0 +1,103 @@
+# 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].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);
+  return;
+}
Index: /trunk/Ohana/src/kapa2/src/Image.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/Image.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/Image.c	(revision 13320)
@@ -0,0 +1,145 @@
+# include "Ximage.h"
+# include "buttons.h"
+
+/* initialization for things not specific to X */
+KapaImageWidget *InitImage () {
+
+  int i;
+  KapaImageWidget *image;
+  Graphic *graphic;
+
+  graphic = GetGraphic ();
+
+  ALLOCATE (image, KapaImageWidget, 1);
+  memset (image, 0, sizeof(KapaImageWidget));
+
+  /** set up a bunch of default things **/
+  image[0].X = image[0].Y = 0;
+  image[0].expand = 1;
+  image[0].zero = 0;
+  image[0].range = 1;
+  image[0].start = 0;
+  image[0].slope = 1;
+
+  image[0].coords.Npolyterms = 0;
+  for (i = 0; i < NOVERLAYS; i++) {
+    image[0].overlay[i].Nobjects = 0;
+    ALLOCATE (image[0].overlay[i].objects, Object, 1);  /* allocate so later free will not crash! */
+    image[0].overlay[i].active = FALSE;
+    image[0].overlay[i].color = graphic[0].overlay_color[0];
+  }
+  image[0].matrix.size = 0; /* a flag to show there is no data in the matrix */
+
+  image[0].MovePointer = TRUE;
+  image[0].DecimalDegrees  = TRUE;
+  ALLOCATE (image[0].matrix.buffer, char, 1);  /* allocate so later free will not crash! */
+  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, PSit);
+
+  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].puns_button, puns_width, puns_height, puns_bits);
+//  InitButtonFunc (&image[0].puns_button, puns);
+
+  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);
+
+  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);
+
+# if (0)
+  for (i = 0; i < NOVERLAYS; i++) {
+    if (OVERLAY[i])
+      PaintOverlay (graphic, image, i);
+  }
+  PaintTickmarks (graphic, image);
+# endif
+
+  // XXX make this optional?a
+  if (1) {
+    /* 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].zoom.dx, graphic[0].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].puns_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);
+}
Index: /trunk/Ohana/src/kapa2/src/InButton.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/InButton.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/InButton.c	(revision 13320)
@@ -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: /trunk/Ohana/src/kapa2/src/InPicture.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/InPicture.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/InPicture.c	(revision 13320)
@@ -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: /trunk/Ohana/src/kapa2/src/InterpretKeys.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/InterpretKeys.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/InterpretKeys.c	(revision 13320)
@@ -0,0 +1,81 @@
+# include "Ximage.h"
+
+int InterpretKeys (Graphic *graphic, XEvent *event) {
+
+  double X, Y, offset;
+  int    modstate;
+  char   string[10];
+  KeySym keysym;
+  XComposeStatus  composestatus;
+  XKeyEvent *keyevent;
+  Section *section;
+  KapaImageWidget *image;
+
+  // XXX select the window element which contains the event
+  section = GetActiveSection();
+  image   = section->image;
+
+  keyevent = (XKeyEvent *) event;
+  XLookupString (keyevent, string, 9, &keysym, &composestatus);
+  modstate = keyevent[0].state;
+
+  // 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_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)keyevent[0].x, (double)keyevent[0].y, image);
+      X = 0.5*image[0].matrix.Naxis[0] - X;
+      Y = 0.5*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_Tab:
+      image[0].MovePointer = image[0].MovePointer ^ TRUE;
+      if (image[0].MovePointer) UpdatePointer (graphic, image, (XMotionEvent *)event);
+      break;
+  }
+
+  return (TRUE);
+}
Index: /trunk/Ohana/src/kapa2/src/InterpretPresses.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/InterpretPresses.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/InterpretPresses.c	(revision 13320)
@@ -0,0 +1,77 @@
+# include "Ximage.h"
+
+int InterpretPresses (Graphic *graphic, XButtonEvent *event) {
+
+  int             status, done, this_button, x, y, old_cursor;
+  KeySym          keysym;
+  Button         *button;
+  Section *section;
+  KapaImageWidget *image;
+
+  // XXX select the window element which contains the event
+  section = GetActiveSection();
+  image   = section->image;
+
+  status = TRUE;
+  this_button = event[0].button;
+  
+  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].matrix.Naxis[0] - X;
+  Y = 0.5*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: /trunk/Ohana/src/kapa2/src/InvertButton.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/InvertButton.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/InvertButton.c	(revision 13320)
@@ -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: /trunk/Ohana/src/kapa2/src/JPEGit.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/JPEGit.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/JPEGit.c	(revision 13320)
@@ -0,0 +1,153 @@
+# include "Ximage.h"
+# include "jpeglib.h"
+
+int JPEGit (Graphic *graphic, Layout *layout) {
+  
+  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 */
+
+  int j, k, m;
+  unsigned char *buff;
+  double Nchar, Npix, start, slope, frac;
+  int quality;
+  unsigned long pcolor;
+
+  char filename[1024];
+  int Nbytes, status;
+
+  XImage *tmpimage;
+
+  FILE *f;
+  
+  /* expect a line telling the number of bytes and a filename */
+  status = read (layout[0].Ximage, filename, 16);
+  filename[16] = 0;
+  sscanf (filename, "%*s %d", &Nbytes);
+  status = read (layout[0].Ximage, filename, Nbytes);
+  filename[status] = 0; /* make the string easy to parse */
+
+  /* 
+  switch (graphic[0].Nbits) {
+  case 8:
+    break;
+  case 16:
+    fprintf (stderr, "converter to 16 bit not yet implemented\n");
+    return (TRUE);
+    break;
+  case 24:
+    fprintf (stderr, "converter to 24 bit not yet implemented\n");
+    return (TRUE);
+    break;
+  case 32:
+    fprintf (stderr, "converter to 32 bit not yet implemented\n");
+    return (TRUE);
+    break;
+  }
+  */
+
+  /* set up the error handler , initialize the JPEG compression object. */
+  cinfo.err = jpeg_std_error (&jerr);
+  jpeg_create_compress (&cinfo);
+
+  f = fopen (filename, "w");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "failed to open %s for output\n", filename);
+    return (TRUE);
+  }
+  jpeg_stdio_dest(&cinfo, f);
+  
+  quality = 75;
+  cinfo.image_width = layout[0].picture.dx; 	/* image width and height, in pixels */
+  cinfo.image_height = layout[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 (image_buffer, JSAMPLE, 3*layout[0].picture.dx);
+  buff = (unsigned char *)layout[0].picture.data;
+  slope = layout[0].slope;
+  start = layout[0].start;
+  Nchar = 255.0;                                /* range of output values */
+  Npix = layout[0].Npixels;
+  frac = Nchar / Npix;
+  
+  {
+    XWindowAttributes WindowAttributes;
+    Pixmap tmp_pixmap;
+    Window tmp_window;
+    
+    XGetWindowAttributes (graphic[0].display, graphic[0].window, &WindowAttributes);
+    
+    tmp_pixmap = XCreatePixmap (graphic[0].display, graphic[0].window, graphic[0].dx, graphic[0].dy, WindowAttributes.depth);
+
+    tmp_window = graphic[0].window;
+    graphic[0].window = tmp_pixmap;
+
+    Refresh (graphic, layout, 0);
+
+    tmpimage = XGetImage (graphic[0].display, graphic[0].window, layout[0].picture.x+1, layout[0].picture.y+1, layout[0].picture.dx, layout[0].picture.dy, 0xffffffff, ZPixmap);
+
+    for (j = 0; (j < layout[0].picture.dy) && (cinfo.next_scanline < cinfo.image_height); j++) {
+      for (k = 0; k < layout[0].picture.dx; k++) {
+	pcolor = XGetPixel (tmpimage, k, j);
+	if (pcolor == layout[0].white) { 
+	  image_buffer[3*k+0] = Nchar;
+	  image_buffer[3*k+1] = Nchar;
+	  image_buffer[3*k+2] = Nchar;
+	  continue;
+	}
+	if (pcolor == layout[0].overlay[0].color) { 
+	  image_buffer[3*k+0] = Nchar;
+	  image_buffer[3*k+1] = 0;
+	  image_buffer[3*k+2] = 0;
+	  continue;
+	}
+	if (pcolor == layout[0].overlay[1].color) { 
+	  image_buffer[3*k+0] = 0;
+	  image_buffer[3*k+1] = Nchar;
+	  image_buffer[3*k+2] = 0;
+	  continue;
+	}
+	if (pcolor == layout[0].overlay[2].color) { 
+	  image_buffer[3*k+0] = 0;
+	  image_buffer[3*k+1] = 0;
+	  image_buffer[3*k+2] = Nchar;
+	  continue;
+	}
+	if (pcolor == layout[0].overlay[3].color) { 
+	  image_buffer[3*k+0] = Nchar;
+	  image_buffer[3*k+1] = Nchar;
+	  image_buffer[3*k+2] = 0;
+	  continue;
+	}
+	for (m = 0; (layout[0].cmap[m].pixel != pcolor) && (m < Npix); m++);
+	/* val = Nchar - frac * MIN (MAX (start + m * slope, 0), Npix); */
+	image_buffer[3*k+0] = layout[0].cmap[m].red / 256;
+	image_buffer[3*k+1] = layout[0].cmap[m].green / 256;
+	image_buffer[3*k+2] = layout[0].cmap[m].blue / 256;
+      }
+      row_pointer[0] = image_buffer;
+      (void) jpeg_write_scanlines (&cinfo, row_pointer, 1);
+    }
+    graphic[0].window = tmp_window;
+    XFreePixmap (graphic[0].display, tmp_pixmap);
+  }
+
+  XDestroyImage (tmpimage);
+
+  jpeg_finish_compress (&cinfo);
+  fclose (f);
+  jpeg_destroy_compress (&cinfo);
+
+  return (TRUE);
+
+}
Index: /trunk/Ohana/src/kapa2/src/JPEGit24.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/JPEGit24.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/JPEGit24.c	(revision 13320)
@@ -0,0 +1,229 @@
+# 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 the active image
+int JPEGit24 () {
+
+  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 status, Nbytes, quality;
+  int expand_in, expand_out;
+  double expand, Rx, Ry, X, Y;
+  unsigned char *out_pix, *in_pix, *in_pix_ref;
+  unsigned char pixel1[256], pixel2[256], pixel3[256];
+  char filename[1024];
+  FILE *f;
+
+  graphic = GetGraphic();
+  section = GetActiveSection();
+  image   = section->image;
+
+  /* expect a line telling the number of bytes and a filename */
+  KiiScanMessage (sock, "%s", filename);
+
+  /***** 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);
+
+  /** cmap[i].pixel must be defined even if X is not used **/
+  for (i = 0; i < 256; 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].matrix.Naxis[0];
+  DY = 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  = (unsigned char *) (image[0].matrix.buffer) + 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: /trunk/Ohana/src/kapa2/src/Layout.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/Layout.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/Layout.c	(revision 13320)
@@ -0,0 +1,48 @@
+# include "Ximage.h"
+static char default_colormap[] = "grayscale";
+
+void InitLayout (int argc, char **argv) {
+
+  int N, UseGraph;
+  Section *section;
+
+  UseGraph = FALSE;
+  if ((N = get_argument (argc, argv, "-image"))) {
+    remove_argument(N, &argc, argv);
+    UseGraph = FALSE;
+  }
+
+  /** initiate connection with server **/
+  if (!FOREGROUND) {	
+    if (argc < 2) {
+      fprintf (stderr, "socket path not specified\n");
+      exit (0);
+    }
+    sock = KiiWait (argv[1]);
+  }
+
+  /* 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);
+  }
+
+  InitRotFonts ();
+
+  /* create basic section */
+  section = AddSection ("default", 0.0, 0.0, 1.0, 1.0);
+  if (UseGraph) {
+    section->graph = InitGraph ();
+    SetGraphSize (section);
+  } else {
+    section->image = InitImage ();
+    SetImageSize (section);
+  }
+}
Index: /trunk/Ohana/src/kapa2/src/ListSection.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/ListSection.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/ListSection.c	(revision 13320)
@@ -0,0 +1,35 @@
+# include "Ximage.h"
+
+int ListSection () {
+  
+  int i, ThisSection;
+  char name[128];
+
+  KiiScanMessage (sock, "%s", name);
+
+  if (!strcmp (name, "*")) {
+    for (i = 0; i < Nsection; i++) {
+      fprintf (stderr, "%s: %6.3f %6.3f %6.3f %6.3f\n", 
+	       section[i].name, section[i].x, section[i].y, section[i].dx, section[i].dy);
+    }
+    return (TRUE);
+  }
+
+  ThisSection = -1;
+  for (i = 0; i < Nsection; i++) {
+    if (!strcmp (name, section[i].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", 
+	   section[ThisSection].name, 
+	   section[ThisSection].x, section[ThisSection].y, 
+	   section[ThisSection].dx, section[ThisSection].dy);
+  return (TRUE);
+}
Index: /trunk/Ohana/src/kapa2/src/LoadFont.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/LoadFont.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/LoadFont.c	(revision 13320)
@@ -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: /trunk/Ohana/src/kapa2/src/LoadFrame.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/LoadFrame.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/LoadFrame.c	(revision 13320)
@@ -0,0 +1,81 @@
+# include "Ximage.h"
+
+int LoadFrame () {
+  
+  int i, status;
+  char Axis[16], Labels[16], Ticks[16];
+  Section *section;
+  KapaGraphWidget *graph;
+
+  section = GetActiveSection();
+  graph = section->graph;
+
+  // XXX what to do if graph is NULL?
+  
+  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;
+    }
+  }
+
+  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: /trunk/Ohana/src/kapa2/src/LoadLabels.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/LoadLabels.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/LoadLabels.c	(revision 13320)
@@ -0,0 +1,35 @@
+# include "Ximage.h"
+
+int LoadLabels () {
+  
+  char *c, *label;
+  int mode, size, Nbytes;
+  Section *section;
+  KapaGraphWidget *graph;
+
+  section = GetActiveSection();
+  graph = section->graph;
+  
+  fcntl (sock, F_SETFL, !O_NONBLOCK);  
+  
+  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;
+
+  fcntl (sock, F_SETFL, O_NONBLOCK);  
+  
+  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: /trunk/Ohana/src/kapa2/src/LoadObject.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/LoadObject.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/LoadObject.c	(revision 13320)
@@ -0,0 +1,187 @@
+# include "Ximage.h"
+# include <errno.h>
+
+int LoadObject () {
+  
+  int N;
+  Section *section;
+  KapaGraphWidget *graph;
+
+  section = GetActiveSection();
+  graph = section->graph;
+  
+  fcntl (sock, F_SETFL, !O_NONBLOCK);  
+  
+  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);
+  
+  fcntl (sock, F_SETFL, O_NONBLOCK);  
+  
+  if (!LoadVectorData (graph, N, "x")) {
+    FreeObjectData (&graph[0].objects[N]);
+    graph[0].Nobjects --;
+    REALLOCATE (graph[0].objects, Gobjects, MAX (1, graph[0].Nobjects));
+  }
+    
+  if (!LoadVectorData (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 (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 (graph, N, "dym")) {
+      FreeObjectData (&graph[0].objects[N]);
+      graph[0].Nobjects --;
+      REALLOCATE (graph[0].objects, Gobjects, MAX (1, graph[0].Nobjects));
+    }
+    if (!LoadVectorData (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 (graph, N, "dxm")) {
+      FreeObjectData (&graph[0].objects[N]);
+      graph[0].Nobjects --;
+      REALLOCATE (graph[0].objects, Gobjects, MAX (1, graph[0].Nobjects));
+    }
+    if (!LoadVectorData (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);
+  
+}
+
+/* load data for the named component */
+int LoadVectorData (KapaGraphWidget *graph, int N, char *type) {
+  
+  int Npts, Ninpts, status, Ntry;
+  int bytes_left;
+  char *buff;
+
+  buff = NULL;
+  Npts = graph[0].objects[N].Npts;
+  status = 1;
+  if (!strcmp (type, "x")) {
+    ALLOCATE (graph[0].objects[N].x, float, MAX (1, Npts));
+    buff = (char *) graph[0].objects[N].x;
+  }
+  if (!strcmp (type, "y")) {
+    ALLOCATE (graph[0].objects[N].y, float, MAX (1, Npts));
+    buff = (char *) graph[0].objects[N].y;
+  }
+  if (!strcmp (type, "z")) {
+    ALLOCATE (graph[0].objects[N].z, float, MAX (1, Npts));
+    buff = (char *) graph[0].objects[N].z;
+  }
+  if (!strcmp (type, "dxm")) {
+    ALLOCATE (graph[0].objects[N].dxm, float, MAX (1, Npts));
+    buff = (char *) graph[0].objects[N].dxm;
+  }
+  if (!strcmp (type, "dxp")) {
+    ALLOCATE (graph[0].objects[N].dxp, float, MAX (1, Npts));
+    buff = (char *) graph[0].objects[N].dxp;
+  }
+  if (!strcmp (type, "dym")) {
+    ALLOCATE (graph[0].objects[N].dym, float, MAX (1, Npts));
+    buff = (char *) graph[0].objects[N].dym;
+  }
+  if (!strcmp (type, "dyp")) {
+    ALLOCATE (graph[0].objects[N].dyp, float, MAX (1, Npts));
+    buff = (char *) graph[0].objects[N].dyp;
+  }
+
+  bytes_left = Npts*sizeof (float);
+
+  Ntry = 0;
+  if (DEBUG) fprintf (stderr, "starting vector load\n");
+  Ninpts = 0;
+  while (bytes_left > 0) {
+    status = read (sock, buff, 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;
+      buff = (char *)(buff + 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");
+  }
+  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: /trunk/Ohana/src/kapa2/src/LoadOverlay.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/LoadOverlay.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/LoadOverlay.c	(revision 13320)
@@ -0,0 +1,103 @@
+# include "Ximage.h"
+
+// XXX this is a very inefficient method to send the data: binary would be better
+int LoadOverlay () {
+  
+  char word[17], type[16], string[128];
+  char *buffer, *buff;
+  double x, y, dx, dy;
+  int Nin, bytes, status;
+  int i, N, NOBJECTS, Nobjects, Nstart, done;
+  Section *section;
+  KapaImageWidget *image;
+  Graphic *graphic;
+
+  graphic = GetGraphic ();
+  section = GetActiveSection();
+  image   = section->image;
+
+  ALLOCATE (buffer, char, 65536);  /* space for 512 lines of 128 bytes */
+  bzero (buffer, 65536);
+  done = FALSE;
+
+  KiiScanCommand (sock, 16, "%*s %d", &N);
+  Nstart = image[0].overlay[N].Nobjects;
+
+  while (!done) {
+    KiiScanCommand (sock, 16, "%s %d", word, &Nin);
+    if (!strcmp (word, "DONE")) break;
+    if (strcmp (word, "NLINES")) { 
+      fprintf (stderr, "!"); 
+      continue;
+    }
+
+    buff = buffer;
+    bytes = 128*Nin;
+
+    /* accept data from the socket until we have all of the bytes */
+    fcntl (sock, F_SETFL, O_NONBLOCK);  
+    while (bytes > 0) { 
+      status = read (sock, buff, bytes);
+      if (status == 0) {  /* No more pipe */
+	fprintf (stderr, "error: pipe closed\n");
+	free (buffer);
+	fcntl (sock, F_SETFL, O_NONBLOCK);  
+	return (FALSE);
+      }
+      if (status != -1) { /* pipe has data */
+	bytes -= status;
+	buff = (char *)(buff + status);
+      }
+    }
+    fcntl (sock, F_SETFL, !O_NONBLOCK);  
+
+    /* parse buffer data */
+    NOBJECTS = image[0].overlay[N].Nobjects + Nin;
+    Nobjects = image[0].overlay[N].Nobjects;
+    REALLOCATE (image[0].overlay[N].objects, Object, NOBJECTS);
+    for (i = 0; i < Nin; i++) {
+      sscanf (&buffer[i*128], "%s %lf %lf %lf %lf\n", type, &x, &y, &dx, &dy);
+
+      if (strcasecmp (type, "TEXT") && strcasecmp (type, "LINE") && strcasecmp (type, "BOX") && strcasecmp (type, "CIRCLE")) {  /* skip */
+	fprintf (stderr, "don't know %s, skipping\n", type);
+	continue;
+      }
+
+      if (!strcasecmp (type, "TEXT")) { /* end of objects */
+	sscanf (&buffer[i*128], "%s %lf %lf %s\n", type, &x, &y, string);
+      }
+	
+      strcpy (image[0].overlay[N].objects[Nobjects].type, type);
+      image[0].overlay[N].objects[Nobjects].x = x;
+      image[0].overlay[N].objects[Nobjects].y = y;
+      if (!strcmp (type, "TEXT")) {
+	image[0].overlay[N].objects[Nobjects].dx = 0;
+	image[0].overlay[N].objects[Nobjects].dy = 0;
+	image[0].overlay[N].objects[Nobjects].text = strcreate (string);
+      } else {
+	image[0].overlay[N].objects[Nobjects].dx = dx;
+	image[0].overlay[N].objects[Nobjects].dy = dy;
+      }
+      Nobjects++;
+    }
+    REALLOCATE (image[0].overlay[N].objects, Object, MAX(Nobjects, 1));
+    image[0].overlay[N].Nobjects = Nobjects;
+  }
+
+  /* cleanup */
+  free (buffer);
+  REALLOCATE (image[0].overlay[N].objects, Object, MAX (1, image[0].overlay[N].Nobjects));
+  image[0].overlay[N].active = TRUE;
+  fcntl (sock, F_SETFL, O_NONBLOCK);  
+
+  if (USE_XWINDOW) {
+    for (i = 0; i < NOVERLAYS; i++) {
+      if (image[0].overlay[i].active) {
+	PaintOverlay (graphic, image, i);
+      }
+    }
+    PaintTickmarks (graphic, image);
+    XFlush (graphic[0].display);
+  }
+  return (TRUE);
+}
Index: /trunk/Ohana/src/kapa2/src/LoadPicture.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/LoadPicture.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/LoadPicture.c	(revision 13320)
@@ -0,0 +1,69 @@
+# include "Ximage.h"
+
+int LoadPicture () {
+
+  Header header;
+  char *buff;
+  int status, bytes_left;
+  Section *section;
+  KapaImageWidget *image;
+  Graphic *graphic;
+
+  graphic = GetGraphic ();
+  section = GetActiveSection();
+  image   = section->image;
+  
+  KiiSendMessage (sock, "%d", graphic->Npixels);
+
+  fcntl (sock, F_SETFL, !O_NONBLOCK);  
+
+  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",  &image[0].zero, &image[0].range);
+  KiiScanMessage (sock, "%lf %lf %d", &image[0].min,  &image[0].max, &header.size);
+  KiiScanMessage (sock, "%lf %f %f %f %f", &image[0].coords.crval1, &image[0].coords.crpix1, &image[0].coords.cdelt1, &image[0].coords.pc1_1, &image[0].coords.pc1_2);
+  KiiScanMessage (sock, "%lf %f %f %f %f", &image[0].coords.crval2, &image[0].coords.crpix2, &image[0].coords.cdelt2, &image[0].coords.pc2_1, &image[0].coords.pc2_2);
+	  
+  KiiScanMessage (sock, "%s %s %s", image[0].coords.ctype, image[0].file, image[0].buffer_name);
+
+  gfits_free_matrix (&image[0].matrix);
+  gfits_create_matrix (&header, &image[0].matrix);
+
+  fcntl (sock, F_SETFL, O_NONBLOCK);  
+
+  status = 1;
+  buff = image[0].matrix.buffer;
+  bytes_left = header.size;
+  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].matrix.size += status;
+      bytes_left -= status;
+      buff = (char *)(buff + status);
+    }
+  }
+
+  if (DEBUG) fprintf (stderr, "read %d bytes\n", image[0].matrix.size);
+  /* it it not obvious this condition should kill kii, but ... */
+  if (image[0].matrix.size != header.size) {  
+    fprintf (stderr, "error: expected %d bytes, but got only %d\n", header.size, image[0].matrix.size);
+    return (FALSE);
+  }
+
+  if (!USE_XWINDOW) return (TRUE);
+
+  Remap (graphic, image, &image[0].matrix);
+  if (DEBUG) fprintf (stderr, "remapped image\n");
+  Refresh ();
+  if (DEBUG) fprintf (stderr, "refreshed\n");
+  XFlush (graphic[0].display);
+
+  return (TRUE);
+}
Index: /trunk/Ohana/src/kapa2/src/LoadTextlines.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/LoadTextlines.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/LoadTextlines.c	(revision 13320)
@@ -0,0 +1,49 @@
+# include "Ximage.h"
+
+int LoadTextlines () {
+  
+  char *string;
+  int N, size;
+  double tX, tY, tT, L;
+  Section *section;
+  KapaGraphWidget *graph;
+
+  section = GetActiveSection();
+  graph = section->graph;
+  
+  fcntl (sock, F_SETFL, !O_NONBLOCK);  
+  
+  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);
+
+  fcntl (sock, F_SETFL, O_NONBLOCK);  
+  
+  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: /trunk/Ohana/src/kapa2/src/LoadTickmarks.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/LoadTickmarks.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/LoadTickmarks.c	(revision 13320)
@@ -0,0 +1,66 @@
+# include "Ximage.h"
+
+int LoadTickmarks () {
+  
+  char line[129], type[16];
+  double x, y, dx, dy;
+  int status, NOBJECTS, Nobjects, done;
+  Section *section;
+  KapaImageWidget *image;
+
+  section = GetActiveSection();
+  image   = section->image;
+  fcntl (sock, F_SETFL, !O_NONBLOCK);  
+
+  Nobjects = image[0].tickmarks.Nobjects;
+  NOBJECTS = Nobjects + 100;
+  REALLOCATE (image[0].tickmarks.objects, Object, 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, Object, NOBJECTS);
+    }
+
+  }
+
+  REALLOCATE (image[0].tickmarks.objects, Object, MAX(Nobjects, 1));
+  image[0].tickmarks.Nobjects = Nobjects;
+
+  if (USE_XWINDOW) Refresh ();
+
+  fcntl (sock, F_SETFL, O_NONBLOCK);  
+  return (TRUE);
+  
+}
Index: /trunk/Ohana/src/kapa2/src/MakeColormap.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/MakeColormap.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/MakeColormap.c	(revision 13320)
@@ -0,0 +1,53 @@
+# include "Ximage.h"
+# define NPIXELS 64
+
+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: /trunk/Ohana/src/kapa2/src/MakeCursor.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/MakeCursor.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/MakeCursor.c	(revision 13320)
@@ -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: /trunk/Ohana/src/kapa2/src/MakeGC.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/MakeGC.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/MakeGC.c	(revision 13320)
@@ -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: /trunk/Ohana/src/kapa2/src/MapWindow.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/MapWindow.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/MapWindow.c	(revision 13320)
@@ -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: /trunk/Ohana/src/kapa2/src/NameWindow.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/NameWindow.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/NameWindow.c	(revision 13320)
@@ -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: /trunk/Ohana/src/kapa2/src/OpenDisplay.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/OpenDisplay.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/OpenDisplay.c	(revision 13320)
@@ -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: /trunk/Ohana/src/kapa2/src/PNGit.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/PNGit.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/PNGit.c	(revision 13320)
@@ -0,0 +1,76 @@
+# include "Ximage.h"
+
+int PNGit () {
+
+  FILE *f;
+  png_structp png_ptr;
+  png_infop info_ptr;
+  png_color *palette;
+  int Npalette;
+  char filename[1024];
+  int Nbytes, status;
+  bDrawBuffer *buffer;
+  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: /trunk/Ohana/src/kapa2/src/PPMit.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/PPMit.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/PPMit.c	(revision 13320)
@@ -0,0 +1,54 @@
+# include "Ximage.h"
+
+int PPMit () {
+
+  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: /trunk/Ohana/src/kapa2/src/PSFrame.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/PSFrame.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/PSFrame.c	(revision 13320)
@@ -0,0 +1,102 @@
+# 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) {
+      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: /trunk/Ohana/src/kapa2/src/PSLabels.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/PSLabels.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/PSLabels.c	(revision 13320)
@@ -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: /trunk/Ohana/src/kapa2/src/PSObjects.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/PSObjects.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/PSObjects.c	(revision 13320)
@@ -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: /trunk/Ohana/src/kapa2/src/PSPtext.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/PSPtext.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/PSPtext.c	(revision 13320)
@@ -0,0 +1,33 @@
+# include "Ximage.h"
+  
+void PSPtext (Layout *layout, FILE *f) {
+
+  int i, x, y, size;
+  double angle;
+  char *fontname;
+
+  fontname = GetRotFont (&size);
+  for (i = 0; i < layout[0].Nptext; i++) {
+    if (strcmp (layout[0].ptext[i].text, "")) {
+      angle = layout[0].ptext[i].angle;
+      x = layout[0].ptext[i].x;
+      y = graphic.dy - layout[0].ptext[i].y;
+      SetRotFont (layout[0].ptext[i].font, layout[0].ptext[i].size);
+      PSRotText (f, x, y, layout[0].ptext[i].text, 5, angle);
+    }
+  }
+  SetRotFont (fontname, size);
+}
+
+  /* pos values
+            
+ 4____2___5 
+  |       | 
+  |       | 
+ 1|   8   |3
+  |       |
+  |       |
+  ---------
+  6   0   7
+
+  */
Index: /trunk/Ohana/src/kapa2/src/PSTextlines.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/PSTextlines.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/PSTextlines.c	(revision 13320)
@@ -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: /trunk/Ohana/src/kapa2/src/PSit.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/PSit.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/PSit.c	(revision 13320)
@@ -0,0 +1,98 @@
+# include "Ximage.h"
+# define XOFFSET 60
+# define YOFFSET 60
+
+static char *name = "$Name: not supported by cvs2svn $";
+static Graphic *graphic;
+
+int PSit () {
+
+  int i, Nsection, pageMode, scaleMode;
+  double scale;
+  FILE *f;
+  char filename[1024], pagename[1024], *version;
+  Section *section;
+
+  graphic = GetGraphic();
+
+  /* expect a line telling the number of bytes and a filename */
+  KiiScanMessage (sock, "%s %s %d %d", filename, pagename, &scaleMode, &pageMode);
+
+  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);
+  }
+
+  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 ();
+    }
+  }
+  
+  fprintf (f, "grestore %% end of picture\n");
+
+  if (pageMode != KAPA_PS_RAWPAGE) fprintf (f, "showpage\n");
+
+  fclose (f);
+  return (TRUE);
+}
+
Index: /trunk/Ohana/src/kapa2/src/PaintOverlay.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/PaintOverlay.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/PaintOverlay.c	(revision 13320)
@@ -0,0 +1,68 @@
+# include "Ximage.h"
+
+void PaintOverlay (Graphic *graphic, KapaImageWidget *image, int N) {
+
+  int i;
+  int dX, dY, dx, dy;
+  int X, Y, Xmin, Ymin, Xmax, Ymax, Xrange, Yrange;
+  double 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 */
+
+    if (!strcasecmp (image[0].overlay[N].objects[i].type, "LINE")) {
+      XDrawLine (graphic[0].display, graphic[0].window, graphic[0].gc, X, Y, (X+dX), (Y+dY));
+      continue;
+    }
+    if (!strcasecmp (image[0].overlay[N].objects[i].type, "TEXT")) {
+      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));
+      continue;
+    }
+    if (!strcasecmp (image[0].overlay[N].objects[i].type, "BOX")) {
+      dx = MAX (abs(dX),2) / 2;
+      dy = MAX (abs(dY),2) / 2;
+      XDrawRectangle (graphic[0].display, graphic[0].window, graphic[0].gc, (X - dx), (Y - dy), 2*dx, 2*dy);
+       continue;
+    }
+    if (!strcasecmp (image[0].overlay[N].objects[i].type, "CIRCLE")) {
+      dx = MAX (abs(dX),2);
+      dy = MAX (abs(dY),2);
+      XDrawArc (graphic[0].display, graphic[0].window, graphic[0].gc, (X - dx), (Y - dy), 2*dx, 2*dy, 0, 23040);
+      continue;
+    }
+    fprintf (stderr, "don't know %s, skipping (PO)\n", image[0].overlay[N].objects[i].type);
+  }
+  
+  XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].fore);
+  return;
+}
Index: /trunk/Ohana/src/kapa2/src/PaintTickmarks.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/PaintTickmarks.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/PaintTickmarks.c	(revision 13320)
@@ -0,0 +1,56 @@
+# 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;
+
+    if (!strcmp (image[0].tickmarks.objects[i].type, "LINE")) {
+      XDrawLine (graphic[0].display, graphic[0].window, graphic[0].gc, X, Y, (X+dX), (Y+dY));
+      continue;
+    }
+    if (!strcmp (image[0].tickmarks.objects[i].type, "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)); */
+      }
+      continue;
+    }
+    if (!strcmp (image[0].tickmarks.objects[i].type, "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));
+       continue;
+    }
+    if (!strcmp (image[0].tickmarks.objects[i].type, "CIRCLE")) {
+      XDrawArc (graphic[0].display, graphic[0].window, graphic[0].gc, X - dX, Y - dY, abs(2*dX), abs(2*dY), 0, 23040);
+      continue;
+    }
+    fprintf (stderr, "don't know %s, skipping (PO)\n", image[0].tickmarks.objects[i].type);
+  }
+  
+  XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].fore);
+
+}
Index: /trunk/Ohana/src/kapa2/src/PositionPicture.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/PositionPicture.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/PositionPicture.c	(revision 13320)
@@ -0,0 +1,95 @@
+# include "Ximage.h"
+
+void PositionPicture (Layout *layout) {
+
+  int fontsize, bump, Nc;
+  double PADx, PADy, Dx, Dy;
+  double PXm, PXp, PYm, PYp;
+  double X0, Y0, dX, dY;
+  char string[64], *fontname;
+
+  fontname = GetRotFont (&fontsize);
+
+  /* window has outer bounding box with margins Wx, Wy 
+     section commands subdivide the internal box (Dx,Dy)
+   */
+
+  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 = (layout[0].axis[1].islabel) ? 4*fontsize : 0;
+  PXp = (layout[0].axis[3].islabel) ? 4*fontsize : 0;
+  PYm = (layout[0].axis[0].islabel) ? 4*fontsize : 0;
+  PYp = (layout[0].axis[2].islabel) ? 4*fontsize : 0;
+ 
+  X0 = PADx + PXm + (Dx * layout[0].x);
+  Y0 = PADy + PYm + (Dy * layout[0].y);
+  dX = (Dx * layout[0].dx) - PXp - PXm;
+  dY = (Dy * layout[0].dy) - PYp - PYm;
+
+  /* define locations of coordinate axes */
+  layout[0].axis[0].fx  = X0;
+  layout[0].axis[0].fy  = graphic.dy - Y0;
+  layout[0].axis[0].dfx = dX;
+  layout[0].axis[0].dfy = 0;
+  
+  layout[0].axis[1].fx  = X0;
+  layout[0].axis[1].fy  = graphic.dy - Y0;
+  layout[0].axis[1].dfx = 0;
+  layout[0].axis[1].dfy = -dY;
+
+  layout[0].axis[2].fx  = X0;
+  layout[0].axis[2].fy  = graphic.dy - Y0 - dY;
+  layout[0].axis[2].dfx = dX;
+  layout[0].axis[2].dfy = 0;
+
+  layout[0].axis[3].fx  = X0 + dX;
+  layout[0].axis[3].fy  = graphic.dy - Y0;
+  layout[0].axis[3].dfx = 0;
+  layout[0].axis[3].dfy = -dY;
+
+  PADx = 0.8*fontsize + 2;
+  PADy = 3.0*fontsize + 4;
+
+  /* define locations of axis labels */
+  layout[0].label[LABELX0].x = layout[0].axis[0].fx + 0.5*layout[0].axis[0].dfx;
+  bump = (layout[0].axis[0].islabel) ? PADy : PADx;
+  layout[0].label[LABELX0].y = layout[0].axis[0].fy + bump;
+
+  layout[0].label[LABELX1].x = layout[0].axis[2].fx + 0.5*layout[0].axis[2].dfx;
+  bump = (layout[0].axis[2].islabel) ? PADy : PADx;
+  layout[0].label[LABELX1].y = layout[0].axis[2].fy - bump;
+
+  sprintf (string, "%4g", layout[0].axis[1].min);
+  Nc = strlen (string);
+  sprintf (string, "%4g", layout[0].axis[1].max);
+  Nc = MAX (Nc, strlen (string));
+
+  layout[0].label[LABELY0].y = layout[0].axis[1].fy + 0.5*layout[0].axis[1].dfy;
+  bump = (layout[0].axis[1].islabel) ? (0.8*Nc*fontsize + 1) : PADx;
+  layout[0].label[LABELY0].x = layout[0].axis[1].fx - bump;
+
+  sprintf (string, "%4g", layout[0].axis[1].min);
+  Nc = strlen (string);
+  sprintf (string, "%4g", layout[0].axis[1].max);
+  Nc = MAX (Nc, strlen (string));
+
+  layout[0].label[LABELY1].y = layout[0].axis[3].fy + 0.5*layout[0].axis[3].dfy;
+  bump = (layout[0].axis[3].islabel) ? (0.8*Nc*fontsize + 1) : PADx;
+  layout[0].label[LABELY1].x = layout[0].axis[3].fx + bump;
+  
+  /* these are wrong and have to be adjusted to sit in the corners */
+
+  layout[0].label[LABELUL].x = layout[0].axis[2].fx - PADx;
+  layout[0].label[LABELUL].y = layout[0].axis[2].fy - PADx;
+  layout[0].label[LABELUR].x = layout[0].axis[2].fx + layout[0].axis[2].dfx + PADx;
+  layout[0].label[LABELUR].y = layout[0].axis[2].fy - PADx;
+  layout[0].label[LABELLL].x = layout[0].axis[0].fx - PADx;
+  layout[0].label[LABELLL].y = layout[0].axis[0].fy + PADx;
+  layout[0].label[LABELLR].x = layout[0].axis[0].fx + layout[0].axis[0].dfx + PADx;
+  layout[0].label[LABELLR].y = layout[0].axis[0].fy + PADx;
+
+}
Index: /trunk/Ohana/src/kapa2/src/QuitX.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/QuitX.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/QuitX.c	(revision 13320)
@@ -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: /trunk/Ohana/src/kapa2/src/Reconfig.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/Reconfig.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/Reconfig.c	(revision 13320)
@@ -0,0 +1,35 @@
+# 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);
+      SetGraphSize (section);
+      SetImageSize (section);
+  }
+
+  if (USE_XWINDOW) XClearWindow (graphic->display, graphic->window);
+  Refresh (1);
+
+  return (TRUE);
+}
Index: /trunk/Ohana/src/kapa2/src/Refresh.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/Refresh.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/Refresh.c	(revision 13320)
@@ -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);
+      DrawGraph (section->graph);
+      DrawImage (section->image);
+  }
+
+  FlushDisplay ();
+}
+
Index: /trunk/Ohana/src/kapa2/src/Remap.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/Remap.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/Remap.c	(revision 13320)
@@ -0,0 +1,21 @@
+# include "Ximage.h"
+
+void Remap (Graphic *graphic, KapaImageWidget *image, Matrix *matrix) {
+
+  switch (graphic[0].Nbits) {
+  case 8:
+    Remap8 (graphic, image, matrix);
+    break;
+  case 16:
+    Remap16 (graphic, image, matrix);
+    break;
+  case 24:
+    Remap24 (graphic, image, matrix);
+    break;
+  case 32:
+    Remap32 (graphic, image, matrix);
+    break;
+  }
+
+}
+
Index: /trunk/Ohana/src/kapa2/src/Remap16.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/Remap16.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/Remap16.c	(revision 13320)
@@ -0,0 +1,153 @@
+# include "Ximage.h"
+# define FRAC(a) ((a) - (int)(a))
+
+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;
+  double expand, Rx, Ry, X, Y;
+  int expand_in, expand_out;
+  unsigned char *out_pix, *out_pix2, *data;
+  unsigned char *in_pix,  *in_pix2;
+  unsigned char pixel1[256], pixel2[256], pixel3[256];
+  unsigned char pixvalue1, pixvalue2;
+  unsigned long back;
+  unsigned char back1, back2;
+
+  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 = 0x00ff & back;
+  back2 = 0x00ff & (back >> 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 = 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;
+  in_pix  = (unsigned char *) (matrix[0].buffer) + 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) {
+	out_pix[0] = pixel1[*in_pix2];
+	out_pix[1] = pixel2[*in_pix2];
+      }
+    }
+    else {
+      for (i = i_start; i < i_end; i+= expand_out, in_pix2++, out_pix+= 2*expand_out) { 
+	pixvalue1 = pixel1[*in_pix2];
+	pixvalue2 = pixel2[*in_pix2];
+	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: /trunk/Ohana/src/kapa2/src/Remap24.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/Remap24.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/Remap24.c	(revision 13320)
@@ -0,0 +1,164 @@
+# include "Ximage.h"
+# define FRAC(a) ((a) - (int)(a))
+
+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;
+  double expand, Rx, Ry, X, Y;
+  int expand_in, expand_out;
+  unsigned char *out_pix, *out_pix2, *data;
+  unsigned char *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;
+
+  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);
+
+  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;
+  in_pix  = (unsigned char *) (matrix[0].buffer) + 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) {
+	out_pix[0] = pixel1[*in_pix2];
+	out_pix[1] = pixel2[*in_pix2];
+	out_pix[2] = pixel3[*in_pix2];
+      }
+    }
+    else {
+      for (i = i_start; i < i_end; i+= expand_out, in_pix2++, out_pix+= 3*expand_out) { 
+	pixvalue1 = pixel1[*in_pix2];
+	pixvalue2 = pixel2[*in_pix2];
+	pixvalue3 = pixel3[*in_pix2];
+	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: /trunk/Ohana/src/kapa2/src/Remap32.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/Remap32.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/Remap32.c	(revision 13320)
@@ -0,0 +1,132 @@
+# include "Ximage.h"
+# define FRAC(a) ((a) - (int)(a))
+
+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 char *in_pix,  *in_pix2;
+  unsigned long pixel[256], pixvalue;
+  unsigned long back;
+
+  for (i = 0; i < 256; i++) { /* set up pixel array */
+    pixel[i] = graphic[0].cmap[i].pixel;
+  }
+  back = graphic[0].back;
+
+  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];
+  /* 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  = (unsigned char *) (matrix[0].buffer) + 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];
+      }
+      /* *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);
+}
+
Index: /trunk/Ohana/src/kapa2/src/Remap8.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/Remap8.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/Remap8.c	(revision 13320)
@@ -0,0 +1,132 @@
+# include "Ximage.h"
+# define FRAC(a) ((a) - (int)(a))
+
+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;
+  double expand, Rx, Ry, X, Y;
+  int expand_in, expand_out;
+  unsigned char *out_pix, *out_pix2;
+  unsigned char *in_pix,  *in_pix2;
+  unsigned long pixel[256], pixvalue;
+  unsigned long back;
+
+  for (i = 0; i < 256; i++) { /* set up pixel array */
+    pixel[i] = graphic[0].cmap[i].pixel;
+  }
+  back = graphic[0].back;
+
+  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];
+  /* 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;
+  in_pix  = (unsigned char *) matrix[0].buffer + 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];
+      }
+      /* *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 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: /trunk/Ohana/src/kapa2/src/Reorient.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/Reorient.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/Reorient.c	(revision 13320)
@@ -0,0 +1,56 @@
+# include "Ximage.h"
+
+void Reorient (Graphic *graphic, KapaImageWidget *image, double X, double Y, int mode) {
+
+  if (image[0].expand == 0) image[0].expand = 1;
+
+  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, &image[0].matrix);
+  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: /trunk/Ohana/src/kapa2/src/Rescale.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/Rescale.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/Rescale.c	(revision 13320)
@@ -0,0 +1,16 @@
+# include "Ximage.h"
+
+void
+Rescale (graphic, layout)
+Graphic graphic[];
+Layout  layout[];
+{
+
+  fprintf (stdout, "enter new zero, range: ");
+  fscanf (stdin, "%lf%lf", &layout[0].zero, &layout[0].range);
+
+  Remap (graphic, layout, &layout[0].matrix);
+  Refresh (graphic, layout, 0);
+  
+  XFlush (graphic[0].display);
+}
Index: /trunk/Ohana/src/kapa2/src/Resize.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/Resize.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/Resize.c	(revision 13320)
@@ -0,0 +1,40 @@
+# include "Ximage.h"
+
+// XXX Should there be a base command + KiiMessage command?
+int Resize () {
+ 
+  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);
+      SetGraphSize (section);
+      SetImageSize (section);
+  }
+
+  if (USE_XWINDOW) XClearWindow (graphic->display, graphic->window);
+  Refresh (1);
+
+  return (TRUE);
+}
Index: /trunk/Ohana/src/kapa2/src/SaveOverlay.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/SaveOverlay.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/SaveOverlay.c	(revision 13320)
@@ -0,0 +1,32 @@
+# include "Ximage.h"
+
+int SaveOverlay () {
+
+  int i, N;
+  char filename[256];
+  FILE *f;
+  Section *section;
+  KapaImageWidget *image;
+
+  section = GetActiveSection();
+  image   = section->image;
+
+  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++) {
+    fprintf (f, "%s %lf %lf %lf %lf\n", 
+	     image[0].overlay[N].objects[i].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);
+}
Index: /trunk/Ohana/src/kapa2/src/Sections.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/Sections.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/Sections.c	(revision 13320)
@@ -0,0 +1,150 @@
+# 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;
+  if (section[0].graph != NULL) FreeGraph (section[0].graph);
+  // if (section[0].image != NULL) FreeImage (section[0].image);
+  if (section[0].name  != NULL) 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;
+}
+
+// XXX how to set the section type?
+// XXX set active section on Add?
+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 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);
+}
Index: /trunk/Ohana/src/kapa2/src/SetColormap.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/SetColormap.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/SetColormap.c	(revision 13320)
@@ -0,0 +1,104 @@
+# include "Ximage.h"
+
+/*** this function uses only private colormaps.  it should try the standard colormap
+     first to get better control over the smooth greyscales ***/
+
+int SetColormap (char *name) {
+
+  int i;
+  Graphic *graphic;
+
+  graphic = GetGraphic();
+
+  /* greyscale */
+  if ((!strcmp (name, "grayscale")) || (!strcmp (name, "greyscale"))) {
+    for (i = 0; i < graphic[0].Npixels; i++) {  
+      graphic[0].cmap[i].red = 256*(255 - 255*i/graphic[0].Npixels);
+      graphic[0].cmap[i].green = 256*(255 - 255*i/graphic[0].Npixels);
+      graphic[0].cmap[i].blue = 256*(255 - 255*i/graphic[0].Npixels);
+      graphic[0].cmap[i].flags = DoRed | DoGreen | DoBlue;
+    }
+    goto store_colors;
+  }
+  /* heat */
+  if (!strcmp (name, "Puns")) {
+    for (i = 0; i < (int)(0.25*graphic[0].Npixels); i++) {  
+      graphic[0].cmap[i].green = 0;
+      graphic[0].cmap[i].blue = 0;
+      graphic[0].cmap[i].red = MIN (256*255, 256*255*2*i/(1.0*graphic[0].Npixels));  
+      graphic[0].cmap[i].flags = DoRed | DoGreen | DoBlue;
+    }
+    for (i = (int)(0.25*graphic[0].Npixels); i < (int)(0.50*graphic[0].Npixels); i++) {  
+      graphic[0].cmap[i].red = MIN (256*255, 256*255*2*i/(1.0*graphic[0].Npixels));
+      graphic[0].cmap[i].green = MIN (256*255, 256*255*2*(i/(1.0*graphic[0].Npixels) - 0.25));
+      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 = 256*255;
+      graphic[0].cmap[i].green = MIN (256*255, 256*255*2*(i/(1.0*graphic[0].Npixels) - 0.25));
+      graphic[0].cmap[i].blue = MIN (256*255, 256*255*2*(i/(1.0*graphic[0].Npixels) - 0.50));
+      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 = 256*255;
+      graphic[0].cmap[i].green = 256*255;
+      graphic[0].cmap[i].blue = MIN (256*255, 256*255*2*(i/(1.0*graphic[0].Npixels) - 0.50));
+      graphic[0].cmap[i].flags = DoRed | DoGreen | DoBlue;
+    }
+    goto store_colors;
+  }
+  /* -grayscale */
+  if ((!strcmp (name, "-grayscale")) || (!strcmp (name, "-greyscale"))) {
+    for (i = 0; i < graphic[0].Npixels; i++) {  
+      graphic[0].cmap[i].red = 256*(255*i/graphic[0].Npixels);
+      graphic[0].cmap[i].green = 256*(255*i/graphic[0].Npixels);
+      graphic[0].cmap[i].blue = 256*(255*i/graphic[0].Npixels);
+      graphic[0].cmap[i].flags = DoRed | DoGreen | DoBlue;
+    }
+    goto store_colors;
+  }
+  /* rainbow */
+  if (!strcmp (name, "Rainbow")) {
+    for (i = 0; i < (int)(0.25*graphic[0].Npixels); i++) {  
+      graphic[0].cmap[i].red = 0;
+      graphic[0].cmap[i].green = 0;
+      graphic[0].cmap[i].blue = 256*(255*4*(i/(1.0*graphic[0].Npixels)));  
+      graphic[0].cmap[i].flags = DoRed | DoGreen | DoBlue;
+    }
+    for (i = (int)(0.25*graphic[0].Npixels); i < (int)(0.50*graphic[0].Npixels); i++) {  
+      graphic[0].cmap[i].red = 256*(255*4*((i/(1.0*graphic[0].Npixels)) - 0.25));
+      graphic[0].cmap[i].green = 0;
+      graphic[0].cmap[i].blue = 256*(255*4*(0.50 - (i/(1.0*graphic[0].Npixels))));
+      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 = 256*255;
+      graphic[0].cmap[i].green = 256*(255*4*((i/(1.0*graphic[0].Npixels)) - 0.50));
+      graphic[0].cmap[i].blue = 0;
+      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 = 256*255;
+      graphic[0].cmap[i].green = 256*255;
+      graphic[0].cmap[i].blue = 256*(255*4*((i/(1.0*graphic[0].Npixels)) - 0.75));
+      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: /trunk/Ohana/src/kapa2/src/SetFont.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/SetFont.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/SetFont.c	(revision 13320)
@@ -0,0 +1,15 @@
+# include "Ximage.h"
+
+int SetFont () {
+  
+  char name[64];
+  int size;
+  
+  KiiScanCommand (sock, 16, "%s", name);
+  KiiScanCommand (sock, 16, "%d", &size);
+
+  SetRotFont (name, size);
+  
+  return (TRUE);
+  
+}
Index: /trunk/Ohana/src/kapa2/src/SetGraphSize.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/SetGraphSize.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/SetGraphSize.c	(revision 13320)
@@ -0,0 +1,103 @@
+# 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;
+  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;
+ 
+  /* 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;
+
+  /* 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: /trunk/Ohana/src/kapa2/src/SetImageSize.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/SetImageSize.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/SetImageSize.c	(revision 13320)
@@ -0,0 +1,77 @@
+# 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) {
+
+  KapaImageWidget *image;
+  Graphic *graphic;
+
+  if (section == NULL) return;
+  image = section->image;
+  if (image == NULL) return;
+
+  graphic = GetGraphic ();
+
+  image[0].cmapbar.dx = graphic[0].dx - 2*PAD1; 
+  image[0].cmapbar.dy = COLORPAD;
+  image[0].cmapbar.x = PAD1;
+  image[0].cmapbar.y = PAD1;
+
+  image[0].zoom.dx = ZOOM_X; 
+  image[0].zoom.dy = ZOOM_Y;
+  image[0].zoom.x = graphic[0].dx - PAD1 - ZOOM_X;
+  image[0].zoom.y = image[0].cmapbar.y + image[0].cmapbar.dy + PAD2;
+
+  image[0].picture.dx = image[0].zoom.x - 2*PAD1 - 25; 
+  image[0].picture.dy = graphic[0].dy - 2*PAD1 - PAD2 - COLORPAD - 25;
+  image[0].picture.x = PAD1 + 25;
+  image[0].picture.y = PAD1 + PAD2 + COLORPAD;
+
+  /** everything below is tied in x-dir to the zoom box **/
+  image[0].text_x = image[0].zoom.x;
+  image[0].text_y = image[0].zoom.y + image[0].zoom.dy + PAD2;
+
+  /*  image[0].PS_button.y = graphic[0].dy - BUTTON_HEIGHT - PAD1; */
+  image[0].PS_button.x = image[0].zoom.x + 5;
+  image[0].PS_button.y = 2*ZOOM_Y;
+
+  /** everything below is tied to the PS_button in y-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].puns_button.x = image[0].rainbow_button.x + image[0].rainbow_button.dx + PAD1;
+  image[0].puns_button.y = image[0].PS_button.y;
+
+  image[0].recenter_button.x = image[0].puns_button.x + image[0].puns_button.dx + PAD1;
+  image[0].recenter_button.y = image[0].PS_button.y;
+
+  image[0].overlay_button[0].x = image[0].zoom.x + 5;
+  image[0].overlay_button[0].y = image[0].PS_button.y - BUTTON_HEIGHT - 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].PS_button.y - BUTTON_HEIGHT - PAD1;
+
+  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].PS_button.y - BUTTON_HEIGHT - PAD1;
+
+  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].PS_button.y - BUTTON_HEIGHT - PAD1;
+
+  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].PS_button.y - BUTTON_HEIGHT - PAD1;
+
+  if (USE_XWINDOW) {
+    CreatePicture (image, graphic);
+    CreateColorbar (image, graphic);
+    CreateZoom (image, graphic, 0, 0); 
+  }
+  Remap (graphic, image, &image[0].matrix);
+
+  return;
+}
Index: /trunk/Ohana/src/kapa2/src/SetLimits.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/SetLimits.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/SetLimits.c	(revision 13320)
@@ -0,0 +1,58 @@
+# include "Ximage.h"
+
+int SetLimits () {
+  
+  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) return (TRUE);
+  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 () {
+  
+  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: /trunk/Ohana/src/kapa2/src/SetNormalHints.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/SetNormalHints.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/SetNormalHints.c	(revision 13320)
@@ -0,0 +1,27 @@
+# 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].base_width = graphic->dx;
+  sizehints[0].base_height = graphic->dy;
+  sizehints[0].flags |= PBaseSize;
+    
+  XSetWMNormalHints (graphic->display, graphic->window, sizehints);
+  XFree (sizehints);
+}
Index: /trunk/Ohana/src/kapa2/src/SetSection.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/SetSection.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/SetSection.c	(revision 13320)
@@ -0,0 +1,19 @@
+# include "Ximage.h"
+
+// set active section
+int SetSection () {
+  
+  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: /trunk/Ohana/src/kapa2/src/SetUpGraphic.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/SetUpGraphic.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/SetUpGraphic.c	(revision 13320)
@@ -0,0 +1,63 @@
+# 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) 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: /trunk/Ohana/src/kapa2/src/SetWMHints.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/SetWMHints.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/SetWMHints.c	(revision 13320)
@@ -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: /trunk/Ohana/src/kapa2/src/StatusBox.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/StatusBox.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/StatusBox.c	(revision 13320)
@@ -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].matrix.Naxis[0];
+    y = 0.5*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: /trunk/Ohana/src/kapa2/src/Stop.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/Stop.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/Stop.c	(revision 13320)
@@ -0,0 +1,8 @@
+# include "Ximage.h"
+
+int Stop () {
+  return (FALSE);
+}
+
+/******  this function looks stupid, but it has to be like this:
+  it is called as a pointer to function **/
Index: /trunk/Ohana/src/kapa2/src/TopWindow.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/TopWindow.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/TopWindow.c	(revision 13320)
@@ -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: /trunk/Ohana/src/kapa2/src/UpdatePointer.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/UpdatePointer.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/UpdatePointer.c	(revision 13320)
@@ -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;
+  char line[100];
+  Section *section;
+  KapaImageWidget *image;
+
+  // XXX select the window element which contains the event
+  section = GetActiveSection();
+  image   = section->image;
+
+  if (image[0].MovePointer && InPicture ((XButtonEvent *)event, &image[0].picture)) {
+
+    Screen_to_Image (&x, &y, (double)event[0].x, (double)event[0].y, image);
+
+    if ((x >= 0) && (x < image[0].matrix.Naxis[0]) && (y >= 0) && (y < image[0].matrix.Naxis[1])) {
+      /*
+      X = event[0].x - image[0].picture.x;
+      Y = event[0].y - image[0].picture.y;
+      pix = MIN (MAX (X + Y*image[0].picture.dx, 0), image[0].picture.dx*image[0].picture.dy - 1);
+      z = image[0].range * image[0].picture.data[pix] / image[0].Npixels + image[0].zero;
+      */
+      z = -1;
+    }
+    else
+      z = -1;
+    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].zero  + 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, "%25.2f", 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: /trunk/Ohana/src/kapa2/src/UpdateStatusBox.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/UpdateStatusBox.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/UpdateStatusBox.c	(revision 13320)
@@ -0,0 +1,61 @@
+# 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].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, ZOOM_X, 6*textpad+7*PAD1);  
+    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, ZOOM_X, 6*textpad+7*PAD1);
+  
+    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].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].buffer_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);
+    XFillRectangle (graphic[0].display, graphic[0].window, graphic[0].gc,
+		    image[0].text_x + 1, image[0].text_y + 1, ZOOM_X - 2, 3*textpad+3*PAD1 +1);  
+    XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].fore);
+  }
+  bzero (line, 100);
+  sprintf (line, "%25.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, "%12.1f %12.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, "%12.6f %12.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: /trunk/Ohana/src/kapa2/src/args.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/args.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/args.c	(revision 13320)
@@ -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: /trunk/Ohana/src/kapa2/src/bDrawFrame.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/bDrawFrame.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/bDrawFrame.c	(revision 13320)
@@ -0,0 +1,89 @@
+# 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) {
+      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: /trunk/Ohana/src/kapa2/src/bDrawIt.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/bDrawIt.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/bDrawIt.c	(revision 13320)
@@ -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->graph);
+  }
+
+  return (buffer);
+}
+
+void bDrawGraph (KapaGraphWidget *graph) {
+  if (graph == NULL) return;
+  bDrawFrame (graph); 
+  bDrawObjects (graph);
+  bDrawLabels (graph);
+  bDrawTextlines (graph);
+}
Index: /trunk/Ohana/src/kapa2/src/bDrawLabels.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/bDrawLabels.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/bDrawLabels.c	(revision 13320)
@@ -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: /trunk/Ohana/src/kapa2/src/bDrawObjects.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/bDrawObjects.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/bDrawObjects.c	(revision 13320)
@@ -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: /trunk/Ohana/src/kapa2/src/bDrawOverlay.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/bDrawOverlay.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/bDrawOverlay.c	(revision 13320)
@@ -0,0 +1,93 @@
+# 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);
+  }
+  /* 
+  X = 0.5*image[0].matrix.Naxis[0] - expand*((int)(0.5*image[0].picture.dx + 0.5) - 0.0) - image[0].X;
+  Y = 0.5*image[0].matrix.Naxis[1] - expand*((int)(0.5*image[0].picture.dy + 0.5) - 0.0) - image[0].Y;  
+  X0 =  (image[0].X + 1 - (int)(0.5*image[0].matrix.Naxis[0] + 0.5) - X + (int)X)/expand + image[0].picture.x + 0.5*image[0].picture.dx;
+  Y0 =  (image[0].Y + 1 - (int)(0.5*image[0].matrix.Naxis[1] + 0.5) - Y + (int)Y)/expand + image[0].picture.y + 0.5*image[0].picture.dy;
+  */
+
+  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 */
+
+    if (!strcasecmp (image[0].overlay[N].objects[i].type, "LINE")) {
+      bDrawLine (X, Y, (X+dX), (Y+dY));
+      continue;
+    }
+    if (!strcasecmp (image[0].overlay[N].objects[i].type, "TEXT")) {
+      bDrawRotText (X, Y, image[0].overlay[N].objects[i].text, 8, 0.0);
+      continue;
+    }
+    if (!strcasecmp (image[0].overlay[N].objects[i].type, "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));
+       continue;
+    }
+    if (!strcasecmp (image[0].overlay[N].objects[i].type, "CIRCLE")) {
+      dx = MAX (abs(dX),2);
+      dy = MAX (abs(dY),2);
+      bDrawArc (X, Y, dx, dy, 0, 360);
+      continue;
+    }
+    fprintf (stderr, "don't know %s, skipping (PO)\n", image[0].overlay[N].objects[i].type);
+  }
+  
+  /* translate color to bDrawColors : image[0].overlay[N].color */
+  bDrawSetStyle (color, 0, 0);
+}
+
+/* this routine is independent of the number of overlays */
+
Index: /trunk/Ohana/src/kapa2/src/cursor.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/cursor.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/cursor.c	(revision 13320)
@@ -0,0 +1,118 @@
+# include "Ximage.h"
+
+/* # define IgnoreMask (long) (ClientMessage | ButtonReleaseMask | PointerMotionMask) */
+# define IgnoreMask (long) (~(StructureNotifyMask | SubstructureNotifyMask | ExposureMask | KeyPressMask | ButtonPressMask))
+
+int LastEvent (Display *display, int type, XEvent *event);
+
+int cursor () {
+
+  Display        *display;
+  XEvent          event;
+  KeySym          keysym;
+  int             status, value;
+  XComposeStatus  composestatus;
+  char            string[10], line[40], *name;
+  double          x, y;
+  char            buffer[10];
+  XButtonEvent   *mouse_event;
+  Section        *section;
+  Graphic        *graphic;
+  KapaGraphWidget *graph;
+
+  graphic = GetGraphic();
+  display = graphic->display;
+  section = GetActiveSection();
+  graph = section->graph;
+
+  while (1) {
+    
+    /* check the pipe for messages */
+    status = read (sock, buffer, 4);
+    buffer[4] = 0;
+    
+    if (status == -1) goto events;
+    if (status ==  0) return (FALSE);
+    if (status ==  4) {
+      if (!strcmp (buffer, "NCUR")) return (TRUE);
+      goto events;
+    }
+    fprintf (stderr, "weird signal: too many or few bytes!  %d\n", status);
+    return (TRUE);
+
+  events:
+    if (XEventsQueued (display, QueuedAfterFlush) < 1) {
+      usleep (50000);
+      continue;
+    }
+
+    /* check for x events */
+
+    /* 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);
+	
+    /* drop and ignore the following StructureNotifyMask events */
+    LastEvent (display, GravityNotify, &event);
+    LastEvent (display, ReparentNotify, &event);
+    LastEvent (display, MapNotify, &event);
+    LastEvent (display, UnmapNotify, &event);
+
+    /* handle button presses */
+    /* XXX put this in something */
+    /* XXX this will need to know whether to return graph or image coords */
+    if (LastEvent (display, ButtonPress, &event) && (graph != NULL)) {
+      mouse_event = (XButtonEvent *) &event;
+      sprintf (string, "Button%d", mouse_event[0].button);
+      x = (mouse_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 = (mouse_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;
+      snprintf (line, 40, "%12s %12.6f %12.6f ", string, x, y);
+      write (sock, line, 40);
+    }
+
+    /* handle key presses */
+    if (LastEvent (display, KeyPress, &event) && (graph != NULL)) {
+      value = XLookupString ((XKeyEvent *) &event, string, 9, &keysym, &composestatus);
+      name = XKeysymToString (keysym);
+
+      // ignore unmapped keys
+      if (name == NULL) continue;
+
+      x = (event.xkey.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.xkey.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;
+
+      // skip the following keys: 
+      if (!strcmp (name, "Shift_L")) continue;
+      if (!strcmp (name, "Shift_R")) continue;
+      if (!strcmp (name, "Control_L")) continue;
+      if (!strcmp (name, "Control_R")) continue;
+      if (!strcmp (name, "Alt_L")) continue;
+      if (!strcmp (name, "Alt_R")) continue;
+      if (!strcmp (name, "Super_L")) continue;
+      if (!strcmp (name, "Super_R")) continue;
+      if (!strcmp (name, "Caps_Lock")) continue;
+      if (!strcmp (name, "Pause")) continue;
+      if (!strcmp (name, "Continue")) continue;
+      if (!strcmp (name, "Num_Lock")) continue;
+      if (!strcmp (name, "Scroll_Lock")) continue;
+      if (!strcmp (name, "Print")) continue;
+      if (!strcmp (name, "(null)")) continue;
+
+      snprintf (line, 40, "%12s %12.6f %12.6f ", name, x, y);
+      write (sock, line, 40);
+    }
+
+    /* remove those events we will ignore */
+    while (XCheckMaskEvent (display, IgnoreMask, &event)) continue;
+
+    /* events to remove which have no mask component */
+    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 (FALSE);
+}
Index: /trunk/Ohana/src/kapa2/src/hh_hms.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/hh_hms.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/hh_hms.c	(revision 13320)
@@ -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: /trunk/Ohana/src/kapa2/src/kapa.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/kapa.c	(revision 13320)
+++ /trunk/Ohana/src/kapa2/src/kapa.c	(revision 13320)
@@ -0,0 +1,16 @@
+# include "Ximage.h"
+
+int main (int argc, char **argv) {
+  
+  args (&argc, argv);
+
+  SetUpGraphic (&argc, argv);
+
+  // XXX get socket connection here?
+
+  InitLayout (argc, argv);
+  EventLoop ();
+
+  CloseDisplay ();
+  exit (0);
+}
