Index: /branches/libfits-1-8/Ohana/src/libfits/Makefile
===================================================================
--- /branches/libfits-1-8/Ohana/src/libfits/Makefile	(revision 11932)
+++ /branches/libfits-1-8/Ohana/src/libfits/Makefile	(revision 11932)
@@ -0,0 +1,63 @@
+default: install
+help:
+	@echo "make options: install libfits man clean dist"
+
+include ../../Configure
+HOME	=	$(ROOT)/src/libfits
+BIN	=	$(HOME)/bin
+LIB	=	$(HOME)/lib
+HEAD	=	$(HOME)/header
+MATR	=	$(HOME)/matrix
+TABL	=	$(HOME)/table
+INC	=	$(HOME)/include
+MAN	= 	$(HOME)/doc
+include ../../Makefile.Common
+
+# programs may add their own internal requirements here
+FULL_CFLAGS   = $(BASE_CFLAGS) -fPIC
+FULL_CPPFLAGS = $(BASE_CPPFLAGS)
+FULL_LDFLAGS  = $(BASE_LDFLAGS)
+
+install: $(DESTLIB)/libFITS.a $(DESTLIB)/libFITS.so $(DESTMAN)/fits.1
+libfits: $(LIB)/libFITS.$(ARCH).a $(LIB)/libFITS.$(ARCH).so
+man: $(DESTMAN)/fits.1
+
+INCS = $(DESTINC)/gfitsio.h 
+
+HEADER_OBJ = \
+$(HEAD)/F_modify.$(ARCH).o			$(HEAD)/F_create_H.$(ARCH).o  \
+$(HEAD)/F_free_H.$(ARCH).o			$(HEAD)/F_H_field.$(ARCH).o   \
+$(HEAD)/F_read_H.$(ARCH).o			$(HEAD)/F_write_H.$(ARCH).o   \
+$(HEAD)/F_scan.$(ARCH).o			$(HEAD)/F_print.$(ARCH).o     \
+$(HEAD)/F_copy_H.$(ARCH).o			$(HEAD)/F_delete.$(ARCH).o    \
+$(HEAD)/F_read_XH.$(ARCH).o			$(HEAD)/F_init_H.$(ARCH).o    \
+$(HEAD)/version.$(ARCH).o
+
+MATRIX_OBJ = \
+$(MATR)/F_add_M_value.$(ARCH).o 		$(MATR)/F_add_M.$(ARCH).o        \
+$(MATR)/F_create_M.$(ARCH).o 			$(MATR)/F_divide_M.$(ARCH).o     \
+$(MATR)/F_free_M.$(ARCH).o 			$(MATR)/F_copy_M.$(ARCH).o       \
+$(MATR)/F_write_M.$(ARCH).o 			$(MATR)/F_get_M_value.$(ARCH).o  \
+$(MATR)/F_multiply_M.$(ARCH).o 			$(MATR)/F_read_M.$(ARCH).o       \
+$(MATR)/F_insert_M.$(ARCH).o 			$(MATR)/F_set_M_value.$(ARCH).o  \
+$(MATR)/F_convert_format.$(ARCH).o              $(MATR)/F_read_segment.$(ARCH).o \
+$(MATR)/F_read_portion.$(ARCH).o		$(MATR)/F_load_M.$(ARCH).o	 \
+$(MATR)/F_matrix.$(ARCH).o
+
+TABLE_OBJ = \
+$(TABL)/F_create_T.$(ARCH).o 			$(TABL)/F_create_TH.$(ARCH).o    \
+$(TABL)/F_read_T.$(ARCH).o			$(TABL)/F_read_TH.$(ARCH).o      \
+$(TABL)/F_write_T.$(ARCH).o			$(TABL)/F_write_TH.$(ARCH).o     \
+$(TABL)/F_define_column.$(ARCH).o		$(TABL)/F_table_format.$(ARCH).o \
+$(TABL)/F_set_column.$(ARCH).o			$(TABL)/F_get_column.$(ARCH).o   \
+$(TABL)/F_table_row.$(ARCH).o			$(TABL)/F_free_T.$(ARCH).o
+
+OBJS = $(HEADER_OBJ) $(MATRIX_OBJ) $(TABLE_OBJ)
+
+$(OBJS): $(INCS)
+
+$(LIB)/libFITS.$(ARCH).a: $(OBJS)
+$(LIB)/libFITS.$(ARCH).so: $(OBJS)
+
+$(DESTLIB)/libFITS.a:  $(LIB)/libFITS.$(ARCH).a
+$(DESTLIB)/libFITS.so: $(LIB)/libFITS.$(ARCH).so
Index: /branches/libfits-1-8/Ohana/src/libfits/doc/ChangeLog.txt
===================================================================
--- /branches/libfits-1-8/Ohana/src/libfits/doc/ChangeLog.txt	(revision 11932)
+++ /branches/libfits-1-8/Ohana/src/libfits/doc/ChangeLog.txt	(revision 11932)
@@ -0,0 +1,41 @@
+
+- libfits 1.6 : 2006.08.23
+  * in order to allow compliation with cfitsio programs, I have changed the 
+    entire namespace to 'gfits' from 'fits'  (actually, only fits_copy_header 
+    was conflicting, but it is better to have a sufficiently different namespace).  
+    All ohana programs need to migrate to the new version of libfits.
+  * set buffer to NULL in gfits_init_header 
+
+- libfits 1.5
+  * cleaned up signed/unsigned inconsistencies
+
+libfits-1-4:
+  added dependency on libohana
+  make libfits work with ohana_allocate
+  removed internal fits.h include file, 
+  replaced with the common fitsio.h file
+
+2005.10.07
+
+	I was having some memory collision problems, and attempting to
+	use the ohana_allocate functions reminded me that the libFITS
+	functions were not supported under ohana_allocate.  This was
+	unhelpful.  I bit the bullet and split libohana into libohana
+	(base functions only, including ohana_allocate) and libdvo
+	(functions based on the libautocode structures).  Doing this
+	allowed me to make libFITS depend on libohana (including
+	ohana_allocate).  BUT, this forced me to change all LDFLAGS
+	entries in ohana to swap -lohana -lFITS for -lFITS -lohana,
+	and to add include <fitsio.h> in some cases.
+
+libfits-1-3:
+ added some additional vtable support, fixed minor iterpretation errors
+ in fits_modify.  
+
+libfits-1-1: 
+
+  F_scan now skips leading ' before parsing value : some bad FITS
+  writers add ' to float entries!
+
+libfits-1-0:
+  imported to CVS
Index: /branches/libfits-1-8/Ohana/src/libfits/doc/README
===================================================================
--- /branches/libfits-1-8/Ohana/src/libfits/doc/README	(revision 11932)
+++ /branches/libfits-1-8/Ohana/src/libfits/doc/README	(revision 11932)
@@ -0,0 +1,33 @@
+
+Installing gene's FITS C libraries.
+
+These FITS libraries are part of a larger package, but the rest of the
+package is not needed to make the libraries.  To install it for a
+specific system, the Makefile expects the environment variable ARCH to
+be defined to something appropriate to your machine (ie, sol for
+solaris, or linux for linux machines.  The resulting .o files then
+have machine specific names (ie, F_read_M.sol.o), making it easy to
+recompile for multiple machines.  The compiled library also has
+a machine specific names (libFITS.sol.a), and the installed version is
+then placed with a generic name in a machine specific locations (ie
+lib/sol/libFITS.a).  
+
+
+Edit the Configure file match your current system.  As it stands, the Makefile
+expects the fits directory to be $(ROOT)/src/fits.  The XINC and XLIB
+variables are not actually used by the fits libraries, so you can
+igore them.  
+
+BYTE_SWAP: byte swapping can be forced by placing a -DBYTE_SWAP option
+on the CC line in Configure (see commented out line).  Byte swapping
+is also enabled automatically if ARCH = linux.  (If you have other
+byte swapped machines, you can edit include/fits.h to enable them
+automatically as well).
+
+define an environment variable ARCH and run "make" or "make install"
+to install the library.
+
+good luck
+
+gene
+
Index: /branches/libfits-1-8/Ohana/src/libfits/doc/VERSIONS
===================================================================
--- /branches/libfits-1-8/Ohana/src/libfits/doc/VERSIONS	(revision 11932)
+++ /branches/libfits-1-8/Ohana/src/libfits/doc/VERSIONS	(revision 11932)
@@ -0,0 +1,5 @@
+
+tag names used by libfits:
+
+TAG         : Comment
+libfits-1-0 : first version under CVS
Index: /branches/libfits-1-8/Ohana/src/libfits/doc/fits.1
===================================================================
--- /branches/libfits-1-8/Ohana/src/libfits/doc/fits.1	(revision 11932)
+++ /branches/libfits-1-8/Ohana/src/libfits/doc/fits.1	(revision 11932)
@@ -0,0 +1,256 @@
+.ad l
+.nh
+.TH FITS 1.0 "Sept 18, 1992" "Version 1.0"
+.SH NAME
+\fIFITS HEADER routines:\fP  fits_read_header, fits_write_header, 
+fits_header_field,  fits_scan, fits_print, fits_copy_header,
+fits_create_header, fits_free_header.
+
+\fIFITS MATRIX routines:\fP  fits_read_matrix, fits_write_matrix, 
+fits_get_matrix_value, fits_set_matrix_value, fits_create_matrix, 
+fits_free_matrix, fits_insert_array
+
+.SH SYNOPSIS
+.nf
+.ft B
+(compile with -lFITS)
+# include <fitsio.h>
+.LP
+\fI FITS Header Routines \fP
+.RS
+int   fits_read_header (filename, header)
+char      *filename;
+Header    *header;
+
+int   fits_write_header (filename, header)
+char      *filename;
+Header    *header;
+
+char *fits_header_field (header, field, N)
+Header    *header;
+char      *field;
+int        N;
+
+int   fits_scan   (header, field, mode, N, value)
+int   fits_print  (header, field, mode, N, value)
+int   fits_modify (header, field, mode, N, value)
+Header    *header;
+char      *field, *mode, *value;
+int        N;
+
+int   fits_create_header (header)
+Header    *header;
+
+int   fits_copy_header (header1, header2)
+Header    *header1;
+Header    *header2;
+
+int   fits_free_header (header)
+Header    *header;
+
+.RE
+.LP
+\fI FITS Matrix Routines \fP
+.RS 
+int   fits_read_matrix (filename, matrix)
+char      *filename;
+Matrix    *matrix;
+
+int   fits_write_matrix (filename, matrix)
+char      *filename;
+Matrix    *matrix;
+
+int   fits_get_matrix_value (matrix, x, y)
+Matrix    *matrix;
+int        x, y;
+
+void  fits_set_matrix_value (matrix, x, y, value)
+Matrix    *matrix;
+int        x, y;
+double     value;
+
+int   fits_create_matrix (header, matrix)
+Header    *header;
+Matrix    *matrix;
+
+int   fits_insert_array (matrix, array, x, y)
+Matrix    *matrix;
+Matrix    *array;
+int        x, y;
+
+int   fits_free_matrix (matrix)
+Matrix    *matrix;
+
+
+.SH DESCRIPTION
+.LP
+These functions allow for FITS I/O in a general C-like way.  There are
+several relavant structures defined in \fIfitsio.h\fP (see
+STRUCTURES below).  
+
+\fI FITS Header Routines \fP
+
+.RS 
+\fIfits_read_header\fP opens a file and reads the FITS header into
+a Header structure.  No error checking, except file existence is
+currently provided.  
+
+\fIfits_write_header\fP opens a file and write the Header structure
+into the file in FITS format.  It also puts a RETURN character (0x0a)
+into the N*80 bytes (the end of every header line).  This is not FITS
+standard, but it makes the header more readable.
+
+\fIfits_header_field\fP returns a pointer to the start of the Nth
+header line with the given keyword "field".  No error check is
+provided, except to note the lack of such a field (returns a NULL
+value).
+
+\fIfits_scan\fP, \fIfits_print\fP and \fIfits_modify\fP are modeled on
+\fIfscanf\fP and \fIfprintf\fP but act on a FITS header instead of a
+stream.  \fIfits_print\fP write a new entry, while \fIfits_modify\fP
+alters the value of an existing entry (wiping out the comment line).
+\fBdNote:\fP \fIfits_modify\fP will create a new entry, but \fIfits_print\fP 
+will \fInot\fP modify and existing entry!
+The following modes are supported:
+
+.RS
+.PD 0
+.TP
+%d 
+A signed decimal integer is expected.
+.TP
+%u 
+An unsigned decimal integer is expected.
+.TP
+%ld 
+A long decimal integer is expected.
+.TP
+%hd 
+A short decimal integer is expected.
+.TP
+%f 
+A float is expected.
+.TP 
+%lf 
+A double is expected.
+.TP
+%t 
+A boolean is expected.  The pointer should be of type \fIbool\fP.
+.TP
+%s 
+A string is expected.  The pointer should be of type \fIchar\fP.
+.TP
+%S A comment line string is expected.  The pointer should be of type \fIchar\fP.
+.RE
+
+\fIfits_create_header\fP creates a Header structure based on a partially filled 
+Header structure.  The mandatory structure values (simple, bitpix, Naxes, 
+Naxis[N], extend, unsign) must be set.  The buffer will be filled in 
+according to these values.
+
+\fIfits_copy_header\fP copies the header1 to header2;
+
+\fIfits_free_header\fP frees the allocated pointers associated with the 
+header.
+.RE
+
+\fI FITS Matrix Routines \fP
+
+.RS
+\fIfits_read_matrix\fP opens the given file and reads the matrix structure.
+There is, of course, no decent error checking.
+
+\fIfits_write_matrix\fP opens the given file and writes the matrix structure.
+The matrix is written to the end of the file, in the assumption that
+there is already a Header written to the file.  
+There is, of course, no decent error checking.
+
+\fIfits_get_matrix_value\fP returns the value of the pixel at the given (2-D) 
+coordinates.
+
+\fIfits_set_matrix_value\fP sets the value of the pixel at the given (2-D) 
+coordinates.
+
+\fIfits_create_matrix\fP creates a matrix which corresponds to the format
+described in the Header structure.
+
+\fIfits_copy_matrix\fP makes a duplicate copy of header1 in header2. 
+
+\fIfits_free_matrix\fP frees the allocated pointers associated with the
+Matrix.
+
+\fIfits_insert_array\fP set the values of the Matrix to those of the
+array (a small Matrix), using the x,y values as a relative offset.
+.RE
+
+.SH STRUCTURES
+.PP
+There are several important structures defined in \fIfitsio.h\fP
+which are described here.
+
+# define bool char
+
+# typedef struct {
+  bool                    simple;
+  bool                    unsign;
+  bool                    extend;
+  int                     bitpix;
+  int                     Naxes;
+  int                     Naxis[FT_MAX_NAXES];
+  int                     size;
+  double                  bzero, bscale;
+  char                   *buffer;
+ } Header;
+
+typedef struct {
+  int                     Naxes;
+  int                     Naxis[FT_MAX_NAXES];
+  int                     bitpix;
+  bool                    unsign;
+  double                  bzero, bscale;
+  char                   *buffer;
+  int                     size;
+ } Matrix;
+
+REMINDER: data = (byte value) * bscale + bzero
+
+\fIbool\fP is defined to be a char.
+
+\fIHeader\fP is a structure for holding all header information.  It
+consists of values of the basic header fields required for a FITS file
+(SIMPLE, EXTEND, BITPIX, NAXIS, NAXIS1, NAXIS2...) as well as a
+pointer to the header data itself (\fIbuffer\fP) and the number of
+bytes in the header buffer (\fIsize\fP).  
+
+\fIMatrix\fP is a structure for holding the image matrix data.  It
+consists of the \fINaxes\fP, and \fINaxis[10]\fP entries as well
+as the \fIbuffer\fP and the \fIsize\fP entries.
+
+
+.SH COPYRIGHT
+Copyright 1991 Eugene Magnier
+.PP                                                
+Permission to use, copy, modify, distribute, and sell this software
+and its documentation for any purpose is hereby granted without fee,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of MIT not be used in
+advertising or publicity pertaining to distribution of the software
+without specific, written prior permission.  MIT and the authors make
+no representations about the suitability of this software for any
+purpose.  It is provided "as is" without express or implied warranty.
+.PP
+MIT and the authors disclaim all warranties with regard to this
+software, including all implied warranties of merchantability and
+fitness, in no event shall MIT or the authors be liable for any
+special, indirect or consequential damages or any damages whatsoever
+resulting from loss of use, data or profits, whether in an action of
+contract, negligence or other tortious action, arising out of or in
+connection with the use or performance of this software.
+.SH ACKNOWLEDGEMENTS
+Walter H.G. Lewin for inspiration
+.PP
+NASA for lots of money
+.PP
+.SH AUTHOR
+Eugene Magnier.  MIT - CSR
Index: /branches/libfits-1-8/Ohana/src/libfits/doc/fits.tex
===================================================================
--- /branches/libfits-1-8/Ohana/src/libfits/doc/fits.tex	(revision 11932)
+++ /branches/libfits-1-8/Ohana/src/libfits/doc/fits.tex	(revision 11932)
@@ -0,0 +1,62 @@
+\documentstyle{AA}
+
+\title{FITS I/O Routine}
+\author{gene magnier}
+
+\begin{document}
+\maketitle
+
+        This file documents the C routines I have created for easy
+manipulation of FITS files.  For now, I will assume familiarity with C
+and the FITS format definitions.  (Maybe I will expand this text
+later).  This set of routines consists of a number of subroutines,
+each of which is contained within its own file.  The subroutines fall into
+three classes: those which manipulte headers, those which manipulate
+data matrices, and those which manipulate tables.  Every subroutine
+has a name which starts with the word {\tt fits}, and includes the word
+{\tt header, matrix,} or {\tt table}.  The file names use the letters
+F, H, M, and T as abbreviations for these words.  Below, I list all of
+the subroutines, and following this I describe them and their use.   
+
+\begin{center}
+\begin{tabular}{ll}
+\hline
+routine name               &   file name \\
+\hline
+fits\_read\_header         &   F\_read\_H.c            \\
+fits\_write\_header        &   F\_write\_H.c           \\
+fits\_header\_field        &   F\_H\_field.c           \\
+fits\_scan                 &   F\_scan.c               \\
+fits\_print                &   F\_print.c              \\
+fits\_modify               &   F\_modify.c             \\
+fits\_delete               &   F\_delete.c             \\
+fits\_create\_header       &   F\_create\_H.c          \\
+fits\_copy\_header         &   F\_copy\_H.c            \\
+fits\_free\_header         &   F\_free\_H.c            \\
+\hline
+fits\_read\_matrix         &   F\_read\_M.c            \\
+fits\_write\_matrix        &   F\_write\_M.c           \\
+fits\_get\_matrix\_value   &   F\_get\_M\_value.c      \\
+fits\_set\_matrix\_value   &   F\_set\_M\_value.c      \\
+fits\_add\_matrix\_value   &   F\_add\_M\_value.c      \\
+fits\_create\_matrix       &   F\_create\_M.c          \\
+fits\_copy\_matrix         &   F\_copy\_M.c            \\
+fits\_free\_matrix         &   F\_free\_M.c            \\
+fits\_add\_matrix          &   F\_add\_M.c             \\
+fits\_multiply\_matrix     &   F\_multiply\_M.c        \\
+fits\_divide\_matrix       &   F\_divide\_M.c          \\
+fits\_insert\_matrix       &   F\_insert\_M.c          \\
+fits\_insert\_array        &   F\_insert\_array.c      \\
+\hline
+fits\_read\_Theader        &   F\_read\_TH.c           \\
+fits\_write\_Theader       &   F\_write\_TH.c          \\
+fits\_create\_Theader      &   F\_create\_TH.c         \\
+fits\_read\_table          &   F\_read\_T.c            \\
+fits\_get\_table\_column   &   F\_get\_T\_column.c     \\
+fits\_get\_table\_value    &   F\_get\_T\_value.c      \\
+\hline
+\end{tabular}
+\end{center}
+
+\end{document}
+
Index: /branches/libfits-1-8/Ohana/src/libfits/doc/fits.txt
===================================================================
--- /branches/libfits-1-8/Ohana/src/libfits/doc/fits.txt	(revision 11932)
+++ /branches/libfits-1-8/Ohana/src/libfits/doc/fits.txt	(revision 11932)
@@ -0,0 +1,253 @@
+
+FITS(1.0)         MISC. REFERENCE MANUAL PAGES          FITS(1.0)
+
+NAME
+     _F_I_T_S _H_E_A_D_E_R _r_o_u_t_i_n_e_s:  fits_read_header, fits_write_header,
+     fits_header_field,  fits_scan, fits_print, fits_copy_header,
+     fits_create_header, fits_free_header.
+
+     _F_I_T_S _M_A_T_R_I_X _r_o_u_t_i_n_e_s:  fits_read_matrix, fits_write_matrix,
+     fits_get_matrix_value, fits_set_matrix_value,
+     fits_create_matrix, fits_free_matrix, fits_insert_array
+
+SYNOPSIS
+     (compile with -lFITS)
+     # include <fitsio.h>
+
+      _F_I_T_S _H_e_a_d_e_r _R_o_u_t_i_n_e_s
+          int   fits_read_header (filename, header)
+          char      *filename;
+          Header    *header;
+
+          int   fits_write_header (filename, header)
+          char      *filename;
+          Header    *header;
+
+          char *fits_header_field (header, field, N)
+          Header    *header;
+          char      *field;
+          int        N;
+
+          int   fits_scan   (header, field, mode, value, N)
+          int   fits_print  (header, field, mode, value, N)
+          int   fits_modify (header, field, mode, value, N)
+          Header    *header;
+          char      *field, *mode, *value;
+          int        N;
+
+          int   fits_create_header (header)
+          Header    *header;
+
+          int   fits_copy_header (header1, header2)
+          Header    *header1;
+          Header    *header2;
+
+          int   fits_free_header (header)
+          Header    *header;
+
+      _F_I_T_S _M_a_t_r_i_x _R_o_u_t_i_n_e_s
+          int   fits_read_matrix (filename, matrix)
+          char      *filename;
+          Matrix    *matrix;
+
+          int   fits_write_matrix (filename, matrix)
+
+Version 1.0        Last change: Sept 18, 1992                   1
+
+FITS(1.0)         MISC. REFERENCE MANUAL PAGES          FITS(1.0)
+
+          char      *filename;
+          Matrix    *matrix;
+
+          int   fits_get_matrix_value (matrix, x, y)
+          Matrix    *matrix;
+          int        x, y;
+
+          void  fits_set_matrix_value (matrix, x, y, value)
+          Matrix    *matrix;
+          int        x, y;
+          double     value;
+
+          int   fits_create_matrix (header, matrix)
+          Header    *header;
+          Matrix    *matrix;
+
+          int   fits_insert_array (matrix, array, x, y)
+          Matrix    *matrix;
+          Matrix    *array;
+          int        x, y;
+
+          int   fits_free_matrix (matrix)
+          Matrix    *matrix;
+
+DESCRIPTION
+     These functions allow for FITS I/O in a general C-like way.
+     There are several relavant structures defined in _f_i_t_s_i_o._h
+     (see STRUCTURES below).
+
+      _F_I_T_S _H_e_a_d_e_r _R_o_u_t_i_n_e_s
+
+          _f_i_t_s__r_e_a_d__h_e_a_d_e_r opens a file and reads the FITS header
+          into a Header structure.  No error checking, except
+          file existence is currently provided.
+
+          _f_i_t_s__w_r_i_t_e__h_e_a_d_e_r opens a file and write the Header
+          structure into the file in FITS format.  It also puts a
+          RETURN character (0x0a) into the N*80 bytes (the end of
+          every header line).  This is not FITS standard, but it
+          makes the header more readable.
+
+          _f_i_t_s__h_e_a_d_e_r__f_i_e_l_d returns a pointer to the start of the
+          Nth header line with the given keyword "field".  No
+          error check is provided, except to note the lack of
+          such a field (returns a NULL value).
+
+          _f_i_t_s__s_c_a_n, _f_i_t_s__p_r_i_n_t and _f_i_t_s__m_o_d_i_f_y are modeled on
+          _f_s_c_a_n_f and _f_p_r_i_n_t_f but act on a FITS header instead of
+          a stream.  _f_i_t_s__p_r_i_n_t write a new entry, while
+          _f_i_t_s__m_o_d_i_f_y alters the value of an existing entry
+
+Version 1.0        Last change: Sept 18, 1992                   2
+
+FITS(1.0)         MISC. REFERENCE MANUAL PAGES          FITS(1.0)
+
+          (wiping out the comment line).  The following modes are
+          supported:
+
+               %d   A signed decimal integer is expected.
+               %u   An unsigned decimal integer is expected.
+               %ld  A long decimal integer is expected.
+               %hd  A short decimal integer is expected.
+               %f   A float is expected.
+               %lf  A double is expected.
+               %t   A boolean is expected.  The pointer should be
+                    of type _b_o_o_l.
+               %s   A string is expected.  The pointer should be
+                    of type _c_h_a_r.
+                    should be of type _c_h_a_r.
+               %S A comment line string is expected.  The pointer
+
+          _f_i_t_s__c_r_e_a_t_e__h_e_a_d_e_r creates a Header structure based on
+          a partially filled Header structure.  The mandatory
+          structure values (simple, bitpix, Naxes, Naxis[N],
+          extend, unsign) must be set.  The buffer will be filled
+          in according to these values.
+
+          _f_i_t_s__c_o_p_y__h_e_a_d_e_r copies the header1 to header2;
+
+          _f_i_t_s__f_r_e_e__h_e_a_d_e_r frees the allocated pointers
+          associated with the header.
+
+      _F_I_T_S _M_a_t_r_i_x _R_o_u_t_i_n_e_s
+
+          _f_i_t_s__r_e_a_d__m_a_t_r_i_x opens the given file and reads the
+          matrix structure.  There is, of course, no decent error
+          checking.
+
+          _f_i_t_s__w_r_i_t_e__m_a_t_r_i_x opens the given file and writes the
+          matrix structure.  The matrix is written to the end of
+          the file, in the assumption that there is already a
+          Header written to the file. There is, of course, no
+          decent error checking.
+
+          _f_i_t_s__g_e_t__m_a_t_r_i_x__v_a_l_u_e returns the value of the pixel at
+          the given (2-D) coordinates.
+
+          _f_i_t_s__s_e_t__m_a_t_r_i_x__v_a_l_u_e sets the value of the pixel at
+          the given (2-D) coordinates.
+
+          _f_i_t_s__c_r_e_a_t_e__m_a_t_r_i_x creates a matrix which corresponds
+          to the format described in the Header structure.
+
+          _f_i_t_s__c_o_p_y__m_a_t_r_i_x makes a duplicate copy of header1 in
+          header2.
+
+          _f_i_t_s__f_r_e_e__m_a_t_r_i_x frees the allocated pointers
+
+Version 1.0        Last change: Sept 18, 1992                   3
+
+FITS(1.0)         MISC. REFERENCE MANUAL PAGES          FITS(1.0)
+
+          associated with the Matrix.
+
+          _f_i_t_s__i_n_s_e_r_t__a_r_r_a_y set the values of the Matrix to those
+          of the array (a small Matrix), using the x,y values as
+          a relative offset.
+
+STRUCTURES
+     There are several important structures defined in _f_i_t_s_i_o._h
+     which are described here.
+
+     # define bool char
+
+     # typedef struct {
+       bool                    simple;
+       bool                    unsign;
+       bool                    extend;
+       int                     bitpix;
+       int                     Naxes;
+       int                     Naxis[FT_MAX_NAXES];
+       int                     size;
+       double                  bzero, bscale;
+       char                   *buffer;
+      } Header;
+
+     typedef struct {
+       int                     Naxes;
+       int                     Naxis[FT_MAX_NAXES];
+       int                     bitpix;
+       bool                    unsign;
+       double                  bzero, bscale;
+       char                   *buffer;
+       int                     size;
+      } Matrix;
+
+     REMINDER: data = (byte value) * bscale + bzero
+
+     _b_o_o_l is defined to be a char.
+
+     _H_e_a_d_e_r is a structure for holding all header information.
+     It consists of values of the basic header fields required
+     for a FITS file (SIMPLE, EXTEND, BITPIX, NAXIS, NAXIS1,
+     NAXIS2...) as well as a pointer to the header data itself
+     (_b_u_f_f_e_r) and the number of bytes in the header buffer
+     (_s_i_z_e).
+
+     _M_a_t_r_i_x is a structure for holding the image matrix data.  It
+     consists of the _N_a_x_e_s, and _N_a_x_i_s[_1_0] entries as well as the
+     _b_u_f_f_e_r and the _s_i_z_e entries.
+
+COPYRIGHT
+     Copyright 1991 Eugene Magnier
+
+Version 1.0        Last change: Sept 18, 1992                   4
+
+FITS(1.0)         MISC. REFERENCE MANUAL PAGES          FITS(1.0)
+
+     Permission to use, copy, modify, distribute, and sell this
+     software and its documentation for any purpose is hereby
+     granted without fee, provided that the above copyright
+     notice appear in all copies and that both that copyright
+     notice and this permission notice appear in supporting
+     documentation, and that the name of MIT not be used in
+     advertising or publicity pertaining to distribution of the
+     software without specific, written prior permission.  MIT
+     and the authors make no representations about the
+     suitability of this software for any purpose.  It is
+     provided "as is" without express or implied warranty.
+     MIT and the authors disclaim all warranties with regard to
+     this software, including all implied warranties of
+     merchantability and fitness, in no event shall MIT or the
+     authors be liable for any special, indirect or consequential
+     damages or any damages whatsoever resulting from loss of
+     use, data or profits, whether in an action of contract,
+     negligence or other tortious action, arising out of or in
+     connection with the use or performance of this software.
+ACKNOWLEDGEMENTS
+     Walter H.G. Lewin for inspiration
+     NASA for lots of money
+AUTHOR
+     Eugene Magnier.  MIT - CSR
+
+Version 1.0        Last change: Sept 18, 1992                   5
+
Index: /branches/libfits-1-8/Ohana/src/libfits/doc/notes.txt
===================================================================
--- /branches/libfits-1-8/Ohana/src/libfits/doc/notes.txt	(revision 11932)
+++ /branches/libfits-1-8/Ohana/src/libfits/doc/notes.txt	(revision 11932)
@@ -0,0 +1,133 @@
+
+2002/09/19
+
+I am making some substantial upgrades to libfits.  My primary goal for
+the moment is the improve the table handling, but I am also making
+some minor cleanups in other areas.  A major concern is that no
+changes should be made to existing functions that will alter their
+behavior and break other programs.  Below I list functions that change
+and note if they risk causing any problems.
+
+header:
+
+fits_init_header:   new function (SAFE)
+fits_create_header: changed fits_print to fits_modify (SAFE)
+fits_fread_header:  new function, to eventually replace fits_load_header (SAFE)
+fits_fwrite_header: new function, to eventually replace fits_save_header (SAFE)
+fits_write_header:  cleaned (f == NULL) (SAFE)
+
+matrix:
+
+fits_create_matrix: if NAXIS==0, create 0 size matrix, allocate min 1 byte
+ - this is different, but now follows correct fits standard.
+ - does not affect any existing programs: all assume NAXIS > 0
+fits_fread_matrix:  new function, to eventually replace fits_load_matrix (SAFE)
+fits_load_matrix:   cleanup declaration format (SAFE)
+fits_fwrite_matrix: new function (SAFE)
+fits_write_matrix:  file ops only, wrapper to fwrite (SAFE)
+fits_matrix_size:   new function (SAFE)
+
+table: no changes
+
+---
+
+fits_write_header:  open / truncate file, write header first
+fits_fwrite_header: 
+
+
+
+current table functions: (9/2002)
+
+fits_read_Theader   (char *filename, Header *theader);
+fits_load_Theader   (FILE *f, Header *theader)
+fits_read_table     (char *filename, Table *table);
+fits_table_column   (Table *table, char *field, char *mode, varg array);
+fits_create_Theader (Header *header, char *type);
+
+new functions:
+
+fits_init_header (Header *header);
+ - set all values to defaults: 
+   bitpix = 8, Naxes = 0, bscale = 1, bzero = 0, extend = FALSE, unsign = FALSE;
+   
+fits_create_table_header (Header *header, char *type);
+ - create an empty table header: TFIELDS = 0, NAXIS1 = NAXIS2 = 0
+
+fits_define_table_column (Header *header, char *format, char *type, char *comment, char *unit);
+ - add a column definition to header
+ - add appropriate keywords
+ - update TFIELDS
+ - update NAXIS1
+
+fits_define_bintable_column (Header *header, char *format, char *type, char *comment, char *unit, double scale, double zero);
+ - add a column definition to header
+ - add appropriate keywords
+ - update TFIELDS
+ - update NAXIS1
+
+fits_get_table_column ()
+
+fits_table_column (Table *table, char *field, char *mode, void *result);
+
+
+
+
+typedef struct {
+  int                     simple;
+  int                     unsign;
+  int                     extend;
+  int                     bitpix;
+  int                     Naxes;
+  int                     Naxis[FT_MAX_NAXES];
+  int                     size;
+  double                  bzero;
+  double                  bscale;
+  char                   *buffer;
+} Header;
+
+typedef struct {
+  int                     unsign;
+  int                     bitpix;
+  int                     Naxes;
+  int                     Naxis[FT_MAX_NAXES];
+  int                     size;
+  double                  bzero;
+  double                  bscale;
+  char                   *buffer;
+} Matrix;
+
+typedef struct {
+  int                     bitpix;
+  int                     Nfields;
+  int                     Naxes;
+  int                     Naxis[FT_MAX_NAXES];
+  int                     size;
+  char                   *buffer;
+  Header                  header;
+} Table;
+          
+typedef struct {
+  Header                 *header;
+  char                   *buffer;
+  int                     size;
+} FTable;
+
+typedef struct {
+  Header                 *header;
+  char                  **buffer;
+  int			  Nrow;
+  int                    *row;
+  int                     size;  /* total buffer size */
+  int			  pad;   /* bytes of padding at the end */
+} VTable;
+
+virtual table:
+
+a virtual table contains only part of the data on disk size is the
+total size of the table (disk + mem) buffer is a contiguous block of
+data in the table msize is the size of the memory block stored at
+buffer offset is the start of the memory block
+
+Nx is width of table,
+Ny is number of occupied rows
+size = Nx*Ny + pad;
Index: /branches/libfits-1-8/Ohana/src/libfits/doc/notes2.txt
===================================================================
--- /branches/libfits-1-8/Ohana/src/libfits/doc/notes2.txt	(revision 11932)
+++ /branches/libfits-1-8/Ohana/src/libfits/doc/notes2.txt	(revision 11932)
@@ -0,0 +1,51 @@
+
+complete list of FITS table APIs:
+
+int fits_create_table (Header *header, FTable *table) 
+int fits_create_Theader (Header *header, char *type)  - create empty extension header 
+int fits_create_table_header (Header *header, char *type, char *extname) - create valid table header
+
+int fits_define_bintable_column (Header *header, char *format, char *label, char *comment, char *unit, double bscale, double bzero)
+int fits_define_table_column (Header *header, char *format, char *label, char *comment, char *unit) - 
+
+int fits_get_bintable_column (Header *header, FTable *table, char *label, void **data)
+int fits_get_table_column (Header *header, FTable *table, char *label, void **data)
+
+int fits_set_bintable_column (Header *header, FTable *table, char *label, void *data, int Nrow)
+int fits_set_table_column (Header *header, FTable *table, char *label, void *data, int Nrow)
+
+int fits_read_table (char *filename, Table *table)
+int fits_read_ftable (char *filename, FTable *table, char *extname)
+int fits_fread_ftable (FILE *f, FTable *table, char *extname)
+int fits_fread_vtable (FILE *f, VTable *table, char *extname, int Nrow, int *row)
+
+int fits_read_Theader (char *filename, Header *Theader)
+int fits_load_Theader (FILE *f, Header *Theader)
+int fits_fread_Theader (FILE *f, Header *Theader)
+
+int fits_bintable_format (char *format, char *type, int *Nval, int *Nbytes)
+int fits_table_format (char *format, char *type, int *Nval, int *Nbytes)
+
+  interpret table column format values.  
+  format - input column format value (TFORM), output C-style printing format
+  type   - char, int, float, double : use to case pointers
+  Nval   - number of entries 
+  Nbytes - bytes per entry
+
+int fits_table_to_vtable (FTable *ftable, VTable *vtable, int start, int Nkeep)
+
+int fits_add_rows (FTable *table, char *data, int Nrow, int Nbytes)
+int fits_vadd_rows (VTable *table, char *data, int Nrow, int Nbytes)
+int fits_delete_rows (FTable *table, int Nstart, int Nrow)
+
+int fits_write_table (char *filename, FTable *table)
+int fits_fwrite_table (FILE *f, FTable *table)
+int fits_fwrite_vtable (FILE *f, VTable *table)
+
+int fits_write_Theader (char *filename, Header *header)
+int fits_fwrite_Theader (FILE *f, Header *header)
+
+void fits_get_table_column (table, X, mode, values)  - REMOVED
+void fits_get_table_value (table, X, Y, mode, value) - REMOVED
+int fits_table_column (Table *table, char *field, char *mode,...) - REMOVED
+
Index: /branches/libfits-1-8/Ohana/src/libfits/doc/sample.c
===================================================================
--- /branches/libfits-1-8/Ohana/src/libfits/doc/sample.c	(revision 11932)
+++ /branches/libfits-1-8/Ohana/src/libfits/doc/sample.c	(revision 11932)
@@ -0,0 +1,73 @@
+# include <ohana.h>
+# include <gfitsio.h>
+# define TRUE 1
+
+main () {
+
+  char filename[80];
+  int i, Nrow;
+  Header header, theader1, theader2;
+  Matrix matrix;
+  FTable table1, table2;
+  float zpobs[1000];
+  float zpref[1000];
+  unsigned long int time[1000];
+  char tchar[1000];
+  
+  strcpy (filename, "test.fits");
+  Nrow = 20;
+  for (i = 0; i < Nrow; i++) {
+    zpobs[i] = i + 5;
+    zpref[i] = i + 15;
+    time[i] = i + 300000;
+    sprintf (&tchar[8*i], "%8d", i);
+  }
+
+  /* create primary header */
+  gfits_init_header (&header);    header.extend = TRUE;
+  gfits_create_header (&header);
+  gfits_create_matrix (&header, &matrix);
+  gfits_print (&header, "NEXTEND", "%d", 1, 2);
+
+  /* define bintable header & layout */
+  gfits_create_table_header (&theader1, "BINTABLE", "ZERO_POINTS");
+
+  gfits_define_bintable_column (&theader1, "E", "ZP_OBS", "measured zero point", "mag", 1.0, 0.0);
+  gfits_define_bintable_column (&theader1, "E", "ZP_REF", "measured zero point", "mag", 1.0, 0.0);
+  gfits_define_bintable_column (&theader1, "J", "TIME",   "time of data", "seconds since Jan 1, 1970 UT", 1.0, 0.0);
+  gfits_define_bintable_column (&theader1, "8A", "TCHAR",   "time of data", "seconds since Jan 1, 1970 UT", 1.0, 0.0);
+
+  /* create table, add data values */
+  gfits_create_table (&theader1, &table1);
+
+  /* set table column based on array, extend NAXIS2 as needed/appropriate */
+  gfits_set_bintable_column (&theader1, &table1, "ZP_OBS", zpobs, Nrow);
+  gfits_set_bintable_column (&theader1, &table1, "ZP_REF", zpref, Nrow);
+  gfits_set_bintable_column (&theader1, &table1, "TIME",   time,  Nrow);
+  gfits_set_bintable_column (&theader1, &table1, "TCHAR",  tchar,  Nrow);
+
+  /* define ASCII table header */
+  gfits_create_table_header (&theader2, "TABLE", "ASCII_PTS");
+
+  gfits_define_table_column (&theader2, "F5.2", "ZP_OBS", "measured zero point", "mag");
+  gfits_define_table_column (&theader2, "F5.2", "ZP_REF", "measured zero point", "mag");
+  gfits_define_table_column (&theader2, "I8", "TIME",    "time of data", "seconds");
+  gfits_define_table_column (&theader2, "A8", "TCHAR",   "time of data", "YYYYMMDD");
+
+  /* create table, add data values */
+  gfits_create_table (&theader2, &table2);
+
+  gfits_set_table_column (&theader2, &table2, "ZP_OBS", zpobs, Nrow);
+  gfits_set_table_column (&theader2, &table2, "ZP_REF", zpref, Nrow);
+  gfits_set_table_column (&theader2, &table2, "TIME",   time,  Nrow);
+  gfits_set_table_column (&theader2, &table2, "TCHAR",  tchar, Nrow);
+
+  /* write header, matrix, table1, table2 */
+  gfits_write_header  (filename, &header);
+  gfits_write_matrix  (filename, &matrix);
+  gfits_write_Theader (filename, &theader1);
+  gfits_write_table   (filename, &table1);
+  gfits_write_Theader (filename, &theader2);
+  gfits_write_table   (filename, &table2);
+
+}
Index: /branches/libfits-1-8/Ohana/src/libfits/doc/sample2.c
===================================================================
--- /branches/libfits-1-8/Ohana/src/libfits/doc/sample2.c	(revision 11932)
+++ /branches/libfits-1-8/Ohana/src/libfits/doc/sample2.c	(revision 11932)
@@ -0,0 +1,60 @@
+# include <ohana.h>
+# include <gfitsio.h>
+# include <stdio.h>
+# define TRUE 1
+
+main () {
+
+  char filename[80];
+  int i, j, Nrow;
+  Header header, theader1, theader2;
+  Matrix matrix;
+  FTable table1, table2;
+  float *zpobs, *zpref;
+  unsigned long int *time;
+  char *tchar;
+  
+  table1.header = &theader1;
+  table2.header = &theader2;
+
+  strcpy (filename, "test.fits");
+  gfits_read_header  (filename, &header);
+  gfits_read_matrix  (filename, &matrix);
+  gfits_read_ftable  (filename, &table1, "ZERO_POINTS");
+  gfits_read_ftable  (filename, &table2, "ASCII_PTS");
+  
+  /* set table column based on array, extend NAXIS2 as needed/appropriate */
+  gfits_get_bintable_column (&theader1, &table1, "ZP_OBS", &zpobs);
+  gfits_get_bintable_column (&theader1, &table1, "ZP_REF", &zpref);
+  gfits_get_bintable_column (&theader1, &table1, "TIME",   &time);
+  gfits_get_bintable_column (&theader1, &table1, "TCHAR",  &tchar);
+  gfits_scan (&theader1, "NAXIS2", "%d", 1, &Nrow);
+
+  for (i = 0; i < Nrow; i++) {
+    fprintf (stderr, "%d %f %f %d   ", i, zpobs[i], zpref[i], time[i]);
+    for (j = 0; j < 8; j++) { fprintf (stderr, "%c", tchar[i*8 + j]); }
+    fprintf (stderr, "\n");
+  }
+
+  /* set table column based on array, extend NAXIS2 as needed/appropriate */
+  gfits_get_table_column (&theader2, &table2, "ZP_OBS", &zpobs);
+  gfits_get_table_column (&theader2, &table2, "ZP_REF", &zpref);
+  gfits_get_table_column (&theader2, &table2, "TIME",   &time);
+  gfits_get_table_column (&theader2, &table2, "TCHAR",  &tchar);
+  gfits_scan (&theader2, "NAXIS2", "%d", 1, &Nrow);
+
+  for (i = 0; i < Nrow; i++) {
+    fprintf (stderr, "%d %f %f %d   ", i, zpobs[i], zpref[i], time[i]);
+    for (j = 0; j < 8; j++) { fprintf (stderr, "%c", tchar[i*8 + j]); }
+    fprintf (stderr, "\n");
+  }
+
+
+}      
+
+/*
+  gfits_set_table_column (&theader2, &table2, "ZP_OBS", zpobs, Nrow);
+  gfits_set_table_column (&theader2, &table2, "ZP_REF", zpref, Nrow);
+  gfits_set_table_column (&theader2, &table2, "TIME",   time,  Nrow);
+  gfits_set_table_column (&theader2, &table2, "TCHAR",  tchar, Nrow);
+*/
Index: /branches/libfits-1-8/Ohana/src/libfits/header/F_H_field.c
===================================================================
--- /branches/libfits-1-8/Ohana/src/libfits/header/F_H_field.c	(revision 11932)
+++ /branches/libfits-1-8/Ohana/src/libfits/header/F_H_field.c	(revision 11932)
@@ -0,0 +1,61 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+/*********************** fits header field ****************************/
+char *gfits_header_field (Header *header, char *field, int N) {
+
+  char *buf;
+  int i, Nwant, Nfound;
+  char keyword[10];
+
+  /* create a blank-padded keyword with exactly 8 characters */
+  strcpy (keyword, field);
+  for (i = strlen(field); i < 8; i++) keyword[i] = ' ';
+  keyword[8] = 0;
+
+  buf = header[0].buffer;
+
+  if (N > 0) {
+    /* find the Nth entry */
+    Nfound = 0;
+    for (i = 0; i < header[0].size; i+= FT_LINE_LENGTH, buf += FT_LINE_LENGTH) {
+      if (!strncmp (keyword, buf, 8)) {
+	Nfound ++;
+	if (Nfound == N) return (buf);
+      }
+    }
+  }
+
+  if (N < 0) {
+    /* count the entries */
+    Nfound = 0;
+    for (i = 0; i < header[0].size; i+= FT_LINE_LENGTH, buf += FT_LINE_LENGTH) {
+      if (!strncmp (keyword, buf, 8)) {
+	Nfound ++;
+      }
+    }
+
+    Nwant = Nfound + N + 1;
+    buf = header[0].buffer;
+
+    /* find the Nwant entry */
+    Nfound = 0;
+    for (i = 0; i < header[0].size; i+= FT_LINE_LENGTH, buf += FT_LINE_LENGTH) {
+      if (!strncmp (keyword, buf, 8)) {
+	Nfound ++;
+	if (Nwant == Nfound) return (buf);
+      }
+    }
+
+  }
+
+  return ((char *) NULL);
+
+}
+
+/* 
+
+   find the Nth entry of this keyword.
+   if N < 0, find the last - N - 1 word (ie, -1 = last)
+
+*/
Index: /branches/libfits-1-8/Ohana/src/libfits/header/F_copy_H.c
===================================================================
--- /branches/libfits-1-8/Ohana/src/libfits/header/F_copy_H.c	(revision 11932)
+++ /branches/libfits-1-8/Ohana/src/libfits/header/F_copy_H.c	(revision 11932)
@@ -0,0 +1,25 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+/*********************** fits copy header ***********************************/
+int gfits_copy_header (Header *in, Header *out) {
+
+  int i;
+
+  out[0].simple = in[0].simple;
+  out[0].bitpix = in[0].bitpix;
+  out[0].extend = in[0].extend;
+  out[0].unsign = in[0].unsign;
+  out[0].size   = in[0].size;
+  out[0].bscale = in[0].bscale;
+  out[0].bzero  = in[0].bzero;
+  out[0].Naxes  = in[0].Naxes;
+  for (i = 0; i < FT_MAX_NAXES; i++) 
+    out[0].Naxis[i] = in[0].Naxis[i];
+
+  ALLOCATE (out[0].buffer, char, out[0].size);
+  
+  strncpy (out[0].buffer, in[0].buffer, out[0].size);
+
+  return (TRUE);
+}	
Index: /branches/libfits-1-8/Ohana/src/libfits/header/F_create_H.c
===================================================================
--- /branches/libfits-1-8/Ohana/src/libfits/header/F_create_H.c	(revision 11932)
+++ /branches/libfits-1-8/Ohana/src/libfits/header/F_create_H.c	(revision 11932)
@@ -0,0 +1,38 @@
+# include <ohana.h>
+# include <gfitsio.h>
+# define NBYTES 2880
+
+/******************** fits create header ***********************************/
+int gfits_create_header (Header *header) {
+
+  int i;
+  char axis[10];
+  
+  header[0].size = NBYTES;
+
+  ALLOCATE (header[0].buffer, char, NBYTES);
+
+  for (i = 0; i < NBYTES; i++) 
+    header[0].buffer[i] = ' ';
+  strncpy (header[0].buffer, "END", 3);
+
+  gfits_modify (header, "SIMPLE", "%t", 1, header[0].simple);
+  gfits_modify (header, "BITPIX", "%d", 1, header[0].bitpix);
+  gfits_modify (header, "NAXIS",  "%d", 1, header[0].Naxes);
+				       
+  for (i = 0; i < header[0].Naxes; i++) {
+    sprintf (axis, "NAXIS%d", i + 1);
+    gfits_modify (header,  axis, "%d", 1, header[0].Naxis[i]);
+  }
+
+  /* PCOUNT & GCOUNT are not implemented, but they are required to be here */
+  gfits_modify (header, "PCOUNT", "%d", 1, 0);
+  gfits_modify (header, "GCOUNT", "%d", 1, 1);
+  gfits_modify (header, "BSCALE", "%lf", 1, header[0].bscale);
+  gfits_modify (header, "BZERO",  "%lf", 1, header[0].bzero);
+  gfits_modify (header, "EXTEND", "%t",  1, header[0].extend);
+  return (TRUE);
+
+}	
+
+
Index: /branches/libfits-1-8/Ohana/src/libfits/header/F_delete.c
===================================================================
--- /branches/libfits-1-8/Ohana/src/libfits/header/F_delete.c	(revision 11932)
+++ /branches/libfits-1-8/Ohana/src/libfits/header/F_delete.c	(revision 11932)
@@ -0,0 +1,32 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+/*********************** fits delete ****************************/
+int gfits_delete (Header *header, char *field, int N) {
+  
+  int i, Nbytes;
+  char *p1, *p2;
+  
+  p1 = gfits_header_field (header, field, N);
+  if (p1 == NULL) return (TRUE);
+
+  p2 = gfits_header_field (header, "END", 1);
+  if (p2 == NULL) return (FALSE); 
+
+  /* pull everything from p1 + FT_LINE_LENGTH to p2 + 79 back 80 chars */
+  Nbytes = (p2 - p1);
+  memmove (p1, p1 + FT_LINE_LENGTH, Nbytes);
+
+  for (i = 0; i < FT_LINE_LENGTH; i++) 
+    *(p2 + i) = ' ';
+
+  p2 = gfits_header_field (header, "END", 1);
+  if (header[0].size - (p2 - header[0].buffer + FT_LINE_LENGTH) > FT_RECORD_SIZE) {
+    header[0].size -= FT_RECORD_SIZE;
+    REALLOCATE (header[0].buffer, char, header[0].size);
+  }
+  return (TRUE);
+
+}
+
+
Index: /branches/libfits-1-8/Ohana/src/libfits/header/F_free_H.c
===================================================================
--- /branches/libfits-1-8/Ohana/src/libfits/header/F_free_H.c	(revision 11932)
+++ /branches/libfits-1-8/Ohana/src/libfits/header/F_free_H.c	(revision 11932)
@@ -0,0 +1,12 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+/*********************** fits free header ***********************************/
+void gfits_free_header (Header *header) {
+
+  if (header[0].buffer == (char *) NULL) return;
+  free (header[0].buffer);
+  header[0].buffer = (char *) NULL;
+  
+}
+
Index: /branches/libfits-1-8/Ohana/src/libfits/header/F_init_H.c
===================================================================
--- /branches/libfits-1-8/Ohana/src/libfits/header/F_init_H.c	(revision 11932)
+++ /branches/libfits-1-8/Ohana/src/libfits/header/F_init_H.c	(revision 11932)
@@ -0,0 +1,22 @@
+# include <ohana.h>
+# include <gfitsio.h>
+int FT_UNSIGN_MODE;
+
+/*********************** fits read header ***********************************/
+int gfits_init_header (Header *header) {
+
+  int i;
+
+  header[0].simple = TRUE;
+  header[0].extend = FALSE;
+  header[0].unsign = FALSE;
+  header[0].bscale = 1;
+  header[0].bzero  = 0;
+  header[0].bitpix = 8;
+  header[0].Naxes  = 0;
+  header[0].buffer = NULL;
+  for (i = 0; i < FT_MAX_NAXES; i++)
+    header[0].Naxis[i] = 0;
+
+  return (TRUE);
+}
Index: /branches/libfits-1-8/Ohana/src/libfits/header/F_insert_array.c
===================================================================
--- /branches/libfits-1-8/Ohana/src/libfits/header/F_insert_array.c	(revision 11932)
+++ /branches/libfits-1-8/Ohana/src/libfits/header/F_insert_array.c	(revision 11932)
@@ -0,0 +1,24 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+/*********************** fits insert array ***********************************/
+void gfits_insert_matrix (matrix, array, x, y) 
+Matrix *matrix, *array; 
+int x, y;
+{
+
+  /* there is no check here to match BITPIX, BZERO, or BSCALE */
+
+  int i, start_m, Nbytes_m, Nbytes;
+
+  Nbytes = array[0].Naxis[0]*abs(array[0].bitpix) / 8;
+  Nbytes_m = matrix[0].Naxis[0]*abs(matrix[0].bitpix) / 8;
+  start_m = y*Nbytes_m + x*abs(matrix[0].bitpix) / 8;
+
+  for (i = 0; i < array[0].Naxis[1]; i++) {
+    bcopy (&array[0].buffer[i*Nbytes], 
+	   &matrix[0].buffer[start_m + i*Nbytes_m], Nbytes);
+  }
+  
+}
+
Index: /branches/libfits-1-8/Ohana/src/libfits/header/F_modify.c
===================================================================
--- /branches/libfits-1-8/Ohana/src/libfits/header/F_modify.c	(revision 11932)
+++ /branches/libfits-1-8/Ohana/src/libfits/header/F_modify.c	(revision 11932)
@@ -0,0 +1,187 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+char *gfits_keyword_start (char *line);
+char *gfits_keyword_end (char *line);
+void pad_ending (char *line, char value, int Nbyte);
+
+int gfits_modify (Header *header, char *field, char *mode, int N,...) {
+  
+  /* this function expects one more argument, the value to be written */
+  /* this function is extremely similar to gfits_print, except it allows for changing an existing field. */
+
+  char comment[82], string[82], data[82];
+  char *p, *qs, *qe;
+  va_list argp;
+  
+  va_start (argp, N);
+  bzero (data, 82);
+  bzero (string, 82);
+  bzero (comment, 82);
+
+  if (mode[0] != '%') {
+    fprintf (stderr, "gfits_print: weird mode:  %s\n", mode);
+    return (FALSE);
+  }
+
+  /* find location of desired entry */
+  p = gfits_header_field (header, field, N);
+  if (p == NULL)  {
+    /* new entry, find the END of the header */
+    p = gfits_header_field (header, "END", 1);
+    if (p == NULL) return (FALSE); 
+    
+    /* is there enough space for 1 more line? */
+    if (header[0].size - (p - (header[0].buffer)) < 2*FT_LINE_LENGTH) {
+      header[0].size += FT_RECORD_SIZE;
+      REALLOCATE (header[0].buffer, char, header[0].size);
+      p = gfits_header_field (header, "END", 1);
+      if (p == NULL) return (FALSE); 
+      memset (p + FT_LINE_LENGTH, ' ', FT_RECORD_SIZE);
+    }
+    
+    /* push END line back 1 */
+    memmove ((p + FT_LINE_LENGTH), p, FT_LINE_LENGTH);
+    memset (p, ' ', FT_LINE_LENGTH);
+  } else {
+    /* old entry, save the comment region (is this skipping a character for non-strings?) */
+    qe = gfits_keyword_end (p);
+    qe += 3;
+    qe = MIN (p + 80, qe);
+    strncpy (comment, qe, p + 80 - qe);
+  }
+  pad_ending (comment, ' ', 82);  /* comment must contain spaces to the end */
+
+  /* write the numeric modes */
+  if (!strcmp (mode, "%d"))  snprintf (string, 81, "%-8s= %20d / %-s ",     field, va_arg (argp, int),      comment);
+  if (!strcmp (mode, "%u"))  snprintf (string, 81, "%-8s= %20d / %-s ",     field, va_arg (argp, unsigned), comment);
+  if (!strcmp (mode, "%ld")) snprintf (string, 81, "%-8s= %20ld / %-s ",    field, va_arg (argp, long),     comment);
+  if (!strcmp (mode, "%hd")) snprintf (string, 81, "%-8s= %20d / %-s ",     field, va_arg (argp, int),      comment);
+  if (!strcmp (mode, "%f"))  snprintf (string, 81, "%-8s= %20.10f / %-s ",  field, va_arg (argp, double),   comment); 
+  if (!strcmp (mode, "%lf")) snprintf (string, 81, "%-8s= %20.10f / %-s ",  field, va_arg (argp, double),   comment); 
+  if (!strcmp (mode, "%e"))  snprintf (string, 81, "%-8s= %20.10E / %-s ",  field, va_arg (argp, double),   comment); 
+  if (!strcmp (mode, "%le")) snprintf (string, 81, "%-8s= %20.10E / %-s ",  field, va_arg (argp, double),   comment); 
+  if (!strcmp (mode, "%g"))  snprintf (string, 81, "%-8s= %20.10G / %-s ",  field, va_arg (argp, double),   comment); 
+  if (!strcmp (mode, "%lg")) snprintf (string, 81, "%-8s= %20.10G / %-s ",  field, va_arg (argp, double),   comment); 
+
+  /* write the boolean mode */
+  if (!strcmp (mode, "%t")) {
+    if (va_arg (argp, int)) 
+      snprintf (string, 81, "%-8s= %18s T / %-s ", field, " ", comment);
+    else
+      snprintf (string, 81, "%-8s= %18s F / %-s ", field, " ", comment);
+  }
+
+  /* string value.  Quotes must be at least 18 chars apart */
+  if (!strcmp (mode, "%s")) {
+    strncpy (data, va_arg (argp, char *), 68);
+    snprintf (string, 81, "%-8s= '%-18s' / %-s ", field, data, comment);
+  }
+
+  /* comment type of value.  */
+  if (!strcmp (mode, "%S")) {
+    strncpy (data, va_arg (argp, char *), 71);
+    snprintf (string, 81, "%-8s %-71s", field, data);
+  }  
+
+  /* just a comment associated with a value.  this is assumes a fixed format position for the comment */
+  if (!strcmp (mode, "%C")) { 
+    qe = gfits_keyword_end (p);
+    qs = gfits_keyword_start (p);
+
+    /* keep ' on ends, if there */
+    if (qe[0]  == 0x27) qe ++;
+    if (qs[-1] == 0x27) qs --;
+
+    strncpy (data, qs, MAX (MIN (qe - qs, 71), 0));
+    strncpy (comment, va_arg (argp, char *), 80);
+    pad_ending (comment, ' ', 82);  /* comment must contain spaces to the end */
+    snprintf (string, 81, "%-8s= %s / %-s", field, data, comment);
+    /* this will keep the original line, but truncate the comment */
+  }
+
+  strncpy (p, string, 80);
+  va_end (argp);
+  return (TRUE);
+
+}
+
+/* given a FITS card line, return pointer to the start of the data area */
+char *gfits_keyword_start (char *line) {
+
+  char *c;
+
+  /* find the end of the existing data region */
+  c = line + 8;
+  if (*c != '=') return (c);  /* no data in COMMENT field */
+  
+  c += 2;
+  /* advance pointer over WHITESPACE */
+  while ((*c == ' ') && (c < line + 80)) { c++; }
+  
+  /* skip one quote mark */
+  if ((*c == 0x27) && (c < line + 80)) { c++; }
+
+  return (c);
+}
+
+/* given a FITS card line, return pointer to the end of the data area */
+char *gfits_keyword_end (char *line) {
+
+  int done;
+  char *c1, *c2;
+
+  /* find the end of the existing data region */
+  c1 = line + 8;
+  if (*c1 != '=') return (c1);  /* no data in COMMENT field */
+  c1 += 2;
+
+  /* advance pointer over WHITESPACE */
+  while ((*c1 == ' ') && (c1 < line + 80)) { c1++; }
+  
+  if (c1[0] == 0x27) { /* entry a string, skip over 'fred' */
+    for (done = FALSE, c2 = c1 + 1; !done && (c2 < line + 80); c2++) {
+      if ((c2[0] == 0x27) && (c2[1] == 0x27)) {
+	c2 += 2;
+	continue;
+      }
+      if (c2[0] == 0x27) {
+	c1 = c2;
+	done = TRUE;
+      }
+    }
+    if (!done) { /* error in line: mismatched ' chars, return fixed position */
+      c1 = line + 30;
+    }
+  } else {
+    while ((*c1 != ' ') && (c1 < line + 80)) c1++;
+  }
+  return (c1);
+}
+
+/* according to the FITS guidelines, a string is supposed to start with a single quote
+   on the 11th character.  I'll be generous and allow the string to start at the 10th.
+   I read the string into tmp then strip off the leading single quote and spaces.
+   a string of "  '  fred is here  '  " should become "fred is here".
+   a string of "  fred is here  " should also become "fred is here".
+   the remaining problem:
+   "'O''HARA'" should be kept as O''HARA.  need to test for double single quotes
+   d -- /(0x2f: comment)  (*(p + i + 10) != 0x2f) &&  && (*(p + i + 10) != 0x27)
+ */
+
+/* fill 'line' with Nbyte space from first NULL to last byte with value */
+void pad_ending (char *line, char value, int Nbyte) {
+  
+  char *p;
+  int N;
+
+  line[Nbyte-1] = 0;
+  
+  p = line + strlen (line);
+  N = MAX (Nbyte - strlen (line) - 1, 0);
+  memset (p, value, N);
+}
+
+
+/* in this routine, the value field will expand as needed, forcing out the comment
+   the total line is limited by snprintf to only 80 chars + EOL */
Index: /branches/libfits-1-8/Ohana/src/libfits/header/F_print.c
===================================================================
--- /branches/libfits-1-8/Ohana/src/libfits/header/F_print.c	(revision 11932)
+++ /branches/libfits-1-8/Ohana/src/libfits/header/F_print.c	(revision 11932)
@@ -0,0 +1,100 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+int gfits_print (Header *header, char *field, char *mode, int N,...) {
+  
+  /* this function expects one more argument, the value to be written */
+
+  static char blank[] = " ";
+  char string[82], line[80];
+  char *p, a;
+  va_list argp;  
+
+  va_start (argp, N);
+  
+  if (mode[0] != '%') {
+    fprintf (stderr, "gfits_print: weird mode:  %s\n", mode);
+    return (FALSE);
+  }
+
+  /* this is supposed to create a new field, not modify an old one.  */
+  p = gfits_header_field (header, field, N);
+  if (p != NULL) return (FALSE);
+
+  /* find the END of the header */
+  p = gfits_header_field (header, "END", 1);
+  if (p == NULL) return (FALSE); 
+
+  /* is there enough space for 1 more line? */
+  if (header[0].size - (p - (header[0].buffer)) < 2*FT_LINE_LENGTH) {
+    header[0].size += FT_RECORD_SIZE;
+    REALLOCATE (header[0].buffer, char, header[0].size);
+    /* re-find the "END" marker, in case new memory block is used */
+    p = gfits_header_field (header, "END", 1);
+    if (p == NULL) return (FALSE); 
+    memset (p + FT_LINE_LENGTH, ' ', FT_RECORD_SIZE);
+  }
+
+  /* push END line back 1 */
+  memmove ((p + FT_LINE_LENGTH), p, FT_LINE_LENGTH);
+  memset (p, ' ', FT_LINE_LENGTH);
+
+  /* write the new FITS card, setting the comment to be blank */
+  /* in these lines, the value field will expand as needed, forcing out the comment
+     the total line is limited by snprintf to only 80 chars + EOL */
+
+  /* write the numeric modes */
+  if (!strcmp (mode, "%d"))  { snprintf (string, 81, "%-8s= %20d / %46s ",    field, va_arg (argp, int),      blank); }
+  if (!strcmp (mode, "%u"))  { snprintf (string, 81, "%-8s= %20d / %46s ",    field, va_arg (argp, unsigned), blank); }
+  if (!strcmp (mode, "%ld")) { snprintf (string, 81, "%-8s= %20ld / %46s ",   field, va_arg (argp, long),     blank); }
+  if (!strcmp (mode, "%hd")) { snprintf (string, 81, "%-8s= %20d / %46s ",    field, va_arg (argp, int),      blank); }
+  if (!strcmp (mode, "%f"))  { snprintf (string, 81, "%-8s= %20.10f / %46s ", field, va_arg (argp, double),   blank); }
+  if (!strcmp (mode, "%lf")) { snprintf (string, 81, "%-8s= %20.10f / %46s ", field, va_arg (argp, double),   blank); }
+  if (!strcmp (mode, "%e"))  { snprintf (string, 81, "%-8s= %20.10E / %46s ", field, va_arg (argp, double),   blank); }
+  if (!strcmp (mode, "%le")) { snprintf (string, 81, "%-8s= %20.10E / %46s ", field, va_arg (argp, double),   blank); }
+  if (!strcmp (mode, "%g"))  { snprintf (string, 81, "%-8s= %20.10G / %46s ", field, va_arg (argp, double),   blank); }
+  if (!strcmp (mode, "%lg")) { snprintf (string, 81, "%-8s= %20.10G / %46s ", field, va_arg (argp, double),   blank); }
+
+  /* write the boolean mode */
+  if (!strcmp (mode, "%t")) {
+    a = va_arg (argp, int);
+    if (a == 1)
+      snprintf (string, 81, "%-8s= %18s T / %46s ", field, blank, blank);
+    else
+      snprintf (string, 81, "%-8s= %18s F / %46s ", field, blank, blank);
+  }
+
+  /* string value.  Quotes must be at least 18 chars apart.  Longer lines will this should be fixed to allow arbitrary string lengths, up to 69 chars */
+  if (!strcmp (mode, "%s")) {
+    strcpy (line, va_arg (argp, char *));
+    line[68] = 0;
+    snprintf (string, 81, "%-8s= '%-18s' / %46s ", field, line, blank);
+  }
+
+  /* comment type of value.  */
+  if (!strcmp (mode, "%S")) {
+    /* we are forcing the entry to be <= 69 char long */
+    strcpy (line, va_arg (argp, char *));
+    line[71] = 0;
+    snprintf (string, 81, "%-8s %-71s", field, line);
+  }  
+
+  /*
+maximal string line:
+12345678901234567890123456789012345678901234567890123456789012345678901234567890 .
+KEYWORD = '01234567890123456789012345678901234567890123456789012345678901234567'
+
+maximal comment line:
+12345678901234567890123456789012345678901234567890123456789012345678901234567890 .
+KEYWORD  01234567890123456789012345678901234567890123456789012345678901234567890
+  */
+
+  /* can't write the comment in gfits_print - use gfits_modify */
+  if (!strcmp (mode, "%C")) return (FALSE);
+
+  strncpy (p, string, 80);
+  
+  va_end (argp);
+  return (TRUE);
+
+}
Index: /branches/libfits-1-8/Ohana/src/libfits/header/F_read_H.c
===================================================================
--- /branches/libfits-1-8/Ohana/src/libfits/header/F_read_H.c	(revision 11932)
+++ /branches/libfits-1-8/Ohana/src/libfits/header/F_read_H.c	(revision 11932)
@@ -0,0 +1,89 @@
+# include <ohana.h>
+# include <gfitsio.h>
+int FT_UNSIGN_MODE;
+
+/*********************** fits read header ***********************************/
+int gfits_read_header (char *filename, Header *header) {
+  
+  FILE *f;
+  
+  f = fopen (filename, "r");
+  if (f == NULL) {
+    header[0].buffer = NULL;
+    return (FALSE);
+  }
+  if (!gfits_load_header (f, header)) {
+    fclose (f);
+    return (FALSE);
+  }
+
+  fclose (f);
+  return (TRUE);
+}	
+
+int gfits_load_header (FILE *f, Header *header) {
+
+  int i, done, Nbytes, t1, t2;
+  char *p;
+
+  header[0].size = 0;
+  done = FALSE;
+  ALLOCATE (header[0].buffer, char, 1);
+
+  for (i = 0; !done; i++) {
+    REALLOCATE (header[0].buffer, char, (i + 1)*FT_RECORD_SIZE);
+    Nbytes = fread (&header[0].buffer[i*FT_RECORD_SIZE], 
+		    sizeof(char), FT_RECORD_SIZE, f);
+    header[0].size += Nbytes;
+    if (Nbytes != FT_RECORD_SIZE) {
+      return (FALSE);
+    }
+    if (i == 0) { 
+      /* on first block, verify it is a FITS table: SIMPLE .. or XTENSION ... */
+      t1 = strncmp (header[0].buffer, "SIMPLE", 6);
+      t2 = strncmp (header[0].buffer, "XTENSION", 8);
+      if (t1 && t2) return (FALSE);
+    }
+
+    p = gfits_header_field (header, "END", 1);
+    if (p != NULL)
+      done = TRUE;
+  }
+
+  header[0].unsign = FT_UNSIGN_MODE;
+  header[0].bscale = 1;
+  header[0].bzero  = 0;
+  for (i = 0; i < FT_MAX_NAXES; i++)
+    header[0].Naxis[i] = 0;
+
+  gfits_scan (header,  "SIMPLE", "%t",   1, &header[0].simple);
+  gfits_scan (header,  "BITPIX", "%d",   1, &header[0].bitpix);
+  gfits_scan (header,  "NAXIS",  "%d",   1, &header[0].Naxes);
+				                           
+  gfits_scan (header,  "EXTEND", "%t",   1, &header[0].extend);
+  gfits_scan (header,  "UNSIGN", "%t",   1, &header[0].unsign);
+  gfits_scan (header,  "BSCALE", "%lf",  1, &header[0].bscale);
+  gfits_scan (header,  "BZERO",  "%lf",  1, &header[0].bzero);
+				       
+  gfits_scan (header,  "NAXIS1", "%d", 1, &header[0].Naxis[0]);
+  gfits_scan (header,  "NAXIS2", "%d", 1, &header[0].Naxis[1]);
+  gfits_scan (header,  "NAXIS3", "%d", 1, &header[0].Naxis[2]);
+  gfits_scan (header,  "NAXIS4", "%d", 1, &header[0].Naxis[3]);
+  gfits_scan (header,  "NAXIS5", "%d", 1, &header[0].Naxis[4]);
+  gfits_scan (header,  "NAXIS6", "%d", 1, &header[0].Naxis[5]);
+  gfits_scan (header,  "NAXIS7", "%d", 1, &header[0].Naxis[6]);
+  gfits_scan (header,  "NAXIS8", "%d", 1, &header[0].Naxis[7]);
+  gfits_scan (header,  "NAXIS9", "%d", 1, &header[0].Naxis[8]);
+  gfits_scan (header, "NAXIS10", "%d", 1, &header[0].Naxis[9]);
+
+  return (TRUE);
+
+}
+
+int gfits_fread_header (FILE *f, Header *header) {
+
+  int status;
+  
+  status = gfits_load_header (f, header);
+  return (status);
+}
Index: /branches/libfits-1-8/Ohana/src/libfits/header/F_read_XH.c
===================================================================
--- /branches/libfits-1-8/Ohana/src/libfits/header/F_read_XH.c	(revision 11932)
+++ /branches/libfits-1-8/Ohana/src/libfits/header/F_read_XH.c	(revision 11932)
@@ -0,0 +1,44 @@
+# include <ohana.h>
+# include <gfitsio.h>
+int FT_UNSIGN_MODE;
+
+/*********************** fits read header ***********************************/
+int gfits_read_Xheader (char *filename, Header *header, int N) {
+  
+  /* read header for extension number N */
+
+  FILE *f;
+  int j, Nmatrix, Nskip;
+  Header theader;
+  
+  f = fopen (filename, "r");
+  if (f == NULL) {
+    header[0].buffer = NULL;
+    return (FALSE);
+  }
+
+  Nskip = 0;
+  for (j = -1; j < N; j++) {
+    /* load data for this header */
+    if (!gfits_load_header (f, &theader)) {
+      fclose (f);
+      return (FALSE);
+    }
+
+    Nmatrix = gfits_matrix_size (&theader);
+
+    /* skip to next header */
+    fseek (f, Nmatrix, SEEK_CUR);
+    Nskip += (Nmatrix + theader.size);
+    gfits_free_header (&theader);
+  }
+  
+  if (!gfits_load_header (f, header)) {
+    fclose (f);
+    return (FALSE);
+  }
+  fclose (f);
+  Nskip += header[0].size;
+  return (Nskip);
+}	
+
Index: /branches/libfits-1-8/Ohana/src/libfits/header/F_scan.c
===================================================================
--- /branches/libfits-1-8/Ohana/src/libfits/header/F_scan.c	(revision 11932)
+++ /branches/libfits-1-8/Ohana/src/libfits/header/F_scan.c	(revision 11932)
@@ -0,0 +1,95 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+char *gfits_keyword_start (char *line);
+char *gfits_keyword_end (char *line);
+
+int gfits_scan (Header *header, char *field, char *mode, int N,...) {
+
+  int status;
+  va_list argp;
+  
+  va_start (argp, N);
+  status = gfits_vscan (header, field, mode, N, argp);
+  va_end (argp);
+  return (status);
+}
+  
+int gfits_vscan (Header *header, char *field, char *mode, int N, va_list argp) {
+
+  char *p, *q, *s, tmp[81];
+  int Nchar;
+  double value;
+  
+  /* find the correct line with field */
+  p = gfits_header_field (header, field, N);
+  if (p == NULL) return (FALSE);
+
+  /* non-data entry (COMMENT, HISTORY) */
+  if (!strcmp (mode, "%S")) {
+    strncpy (va_arg (argp, char *), p + 8, FT_HISTORY_LENGTH);
+    return (TRUE);
+  }
+
+  /* all others require '=' in column 8 */
+  if (p[8] != '=') return (FALSE);
+
+  /* comment from data line */
+  if (!strcmp (mode, "%C")) {
+    q = gfits_keyword_end (p) + 3;
+    q = MIN (p + 80, q);
+    bzero (tmp, 81);
+    Nchar = MIN (80, p + 80 - q);
+    memcpy (tmp, q, Nchar);
+    stripwhite (tmp);
+    strcpy (va_arg (argp, char *), tmp);
+    return (TRUE);
+  }
+
+  /* extract data into char array (exclude containing ' chars) */
+  if (!strcmp (mode, "%s")) {
+    s = gfits_keyword_start (p); /* points at first char (not ') */
+    q = gfits_keyword_end (p); /* points at following space or ' */
+
+    Nchar = MAX (0, (q - s));
+    bzero (tmp, 81);
+    memcpy (tmp, s, Nchar);
+    stripwhite (tmp);
+    strcpy (va_arg (argp, char *), tmp);
+    return (TRUE);
+  }
+  
+  /* boolean data, requires int target */
+  if (!strcmp (mode, "%t")) {
+    s = gfits_keyword_start (p);
+    if (*s == 'T') {
+      *va_arg (argp, int *) = TRUE;
+      return (TRUE);
+    }
+    if (*s == 'F') {
+      *va_arg (argp, int *) = FALSE;   
+      return (TRUE);
+    }
+  }
+
+  /* remaining options are numerical data */
+  /* need to interpret 1.0d5 as 1.0e5 */
+  s = gfits_keyword_start (p); /* points at first char (not ') */
+  q = gfits_keyword_end (p); /* points at following space or ' */
+  value = strtod (s, &q);
+  if ((*q == 'd') || (*q == 'D')) 
+    value *= pow (10.0, atof (q + 1));
+
+  if (!strcmp (mode, "%d"))  { *va_arg (argp, int *)       = value; return (TRUE); }
+  if (!strcmp (mode, "%u"))  { *va_arg (argp, unsigned *)  = value; return (TRUE); }
+  if (!strcmp (mode, "%ld")) { *va_arg (argp, long *)      = value; return (TRUE); }
+  if (!strcmp (mode, "%hd")) { *va_arg (argp, short *)     = value; return (TRUE); }
+  if (!strcmp (mode, "%f"))  { *va_arg (argp, float *)     = value; return (TRUE); }
+  if (!strcmp (mode, "%lf")) { *va_arg (argp, double *)    = value; return (TRUE); }
+
+  /* no valid mode found */
+  return (FALSE);
+}
+
+/* if the variable argument stuff breaks on another system, look 
+at F_modify.c as it has the old code */
Index: /branches/libfits-1-8/Ohana/src/libfits/header/F_write_H.c
===================================================================
--- /branches/libfits-1-8/Ohana/src/libfits/header/F_write_H.c	(revision 11932)
+++ /branches/libfits-1-8/Ohana/src/libfits/header/F_write_H.c	(revision 11932)
@@ -0,0 +1,49 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+/*********************** fits write header ***********************************/
+int gfits_write_header (char *filename, Header *header) {
+
+  FILE *f;
+  int Nbytes, status;
+  
+  status = TRUE;
+
+  f = fopen (filename, "w");
+  if (f == (FILE *) NULL) return (FALSE);
+
+  Nbytes = fwrite (header[0].buffer, sizeof(char), header[0].size, f);
+
+  if (Nbytes != header[0].size) {
+    status = FALSE;
+  }
+
+  fclose (f);
+
+  return (status);
+}	
+
+/*********************** fits write header ***********************************/
+int gfits_save_header (FILE *f, Header *header) {
+
+  int Nbytes, status;
+  
+  status = TRUE;
+
+  Nbytes = fwrite (header[0].buffer, sizeof(char), header[0].size, f);
+
+  if (Nbytes != header[0].size) {
+    status = FALSE;
+  }
+
+  return (status);
+}	
+
+
+int gfits_fwrite_header (FILE *f, Header *header) {
+
+  int status;
+  status = gfits_save_header (f, header);
+  return (status);
+}
+
Index: /branches/libfits-1-8/Ohana/src/libfits/header/version.c
===================================================================
--- /branches/libfits-1-8/Ohana/src/libfits/header/version.c	(revision 11932)
+++ /branches/libfits-1-8/Ohana/src/libfits/header/version.c	(revision 11932)
@@ -0,0 +1,7 @@
+# include <ohana.h>
+# include <gfitsio.h>
+static char *name = "$Name: not supported by cvs2svn $";
+
+char *gfits_version () {
+  return (name);
+}
Index: /branches/libfits-1-8/Ohana/src/libfits/include/cfuncs.h
===================================================================
--- /branches/libfits-1-8/Ohana/src/libfits/include/cfuncs.h	(revision 11932)
+++ /branches/libfits-1-8/Ohana/src/libfits/include/cfuncs.h	(revision 11932)
@@ -0,0 +1,60 @@
+/*** random C-functions ***/
+
+void
+  bcopy
+  (char *b1,
+   char *b2,
+   int   length);
+
+void
+  bzero
+  (char *b,
+   int   length);
+
+# ifndef HAS_ANSI_PROTOTYPES
+int
+   fprintf 
+   (FILE *stream,
+    char *format,...);
+
+int
+   fscanf 
+   (FILE *stream,
+    char *format,...);
+
+int 
+  fread
+  (char *ptr,
+   int size, 
+   int nitems,
+   FILE *stream);
+
+/*
+char *
+  malloc
+  (unsigned size);
+
+char *
+  realloc
+  (char *ptr,
+   unsigned size);
+*/
+
+int 
+  fwrite
+  (char *ptr,
+   int size, 
+   int nitems,
+   FILE *stream);
+
+int
+  fseek 
+  (FILE *f,
+   int offset,
+   int from);
+
+int
+  fclose
+  (FILE *f);
+# endif /* HAS_ANSI_PROTOTYPES */
+
Index: /branches/libfits-1-8/Ohana/src/libfits/include/gfitsio.h
===================================================================
--- /branches/libfits-1-8/Ohana/src/libfits/include/gfitsio.h	(revision 11932)
+++ /branches/libfits-1-8/Ohana/src/libfits/include/gfitsio.h	(revision 11932)
@@ -0,0 +1,183 @@
+/* FITS specific macros and structures */
+
+# ifndef GFITSIO
+# define GFITSIO
+
+/* also defined in libautocode/def/common.h */
+/* what about lin64 ?? - 'linux' might be defined automatically by linux */
+# ifndef BYTE_SWAP
+# ifdef linux
+# define BYTE_SWAP
+# endif
+
+# ifdef sid
+# define BYTE_SWAP
+# endif
+
+# ifdef dec
+# define BYTE_SWAP
+# endif
+# endif /* BYTE_SWAP */
+
+# ifndef NEWLINE
+# define NEWLINE                 10  /* UNIX RETURN character */
+# endif /* NEWLINE */
+
+/********** FITS Constants *********/
+# define FT_TEXT_LENGTH          18  /* max length text header field */
+# define FT_MAX_NAXES            10  /* max number of axes */
+# define FT_FIELD_LENGTH          8  /* max length header field */   
+# define FT_COMMENT_LENGTH       47  /* max length comment field */
+# define FT_HISTORY_LENGTH       72  /* max length history / comment */
+# define FT_LINE_LENGTH          80  /* FITS header line length */
+# define FT_RECORD_SIZE        2880  /* FITS block size */
+
+extern int FT_UNSIGN_MODE; /* is unsigned the default? */
+
+/* this structure defines the buffer which contains a header
+   and contains the minimum required keywords */
+
+typedef struct {
+  int                     simple;
+  int                     unsign;
+  int                     extend;
+  int                     bitpix;
+  int                     Naxes;
+  int                     Naxis[FT_MAX_NAXES];
+  int                     size;
+  double                  bzero;
+  double                  bscale;
+  char                   *buffer;
+} Header;
+
+/* this structure defines the buffer which contains a matrix
+   and contains some relavant info */
+
+typedef struct {
+  int                     unsign;
+  int                     bitpix;
+  int                     Naxes;
+  int                     Naxis[FT_MAX_NAXES];
+  int                     size;
+  double                  bzero;
+  double                  bscale;
+  char                   *buffer;
+} Matrix;
+   
+/* the FTable represents a complete table on disk */          
+typedef struct {
+  Header                 *header;
+  char                   *buffer;
+  int                     size;
+} FTable;
+
+/* the VTable represents rows from a table on disk */          
+typedef struct {
+  Header                 *header;
+  char                  **buffer;
+  int                     Nrow;
+  int                    *row;
+  int                     size;  /* total buffer size */
+  int                     pad;   /* bytes of padding at the end */
+} VTable;
+
+# ifndef PROTO
+# define PROTO(A) A
+# endif
+
+char *gfits_version                PROTO(());
+
+/******************************* Header functions *************/
+int   gfits_read_header            PROTO((char *, Header *));
+// int   fits_copy_header            PROTO((Header *, Header *)); 
+int   gfits_copy_header           PROTO((Header *, Header *)); 
+void  gfits_free_header            PROTO((Header *)); 
+int   gfits_write_header           PROTO((char *, Header *)); 
+int   gfits_create_header          PROTO((Header *)); 
+int   gfits_delete                 PROTO((Header *, char *, int)); 
+char *gfits_header_field           PROTO((Header *, char *, int)); 
+int   gfits_read_Xheader           PROTO((char *filename, Header *header, int N));
+int   gfits_load_header            PROTO((FILE *f, Header *header));
+
+int   gfits_fread_header           PROTO((FILE *, Header *));
+int   gfits_fread_Theader          PROTO((FILE *, Header *));
+int   gfits_fread_ftable           PROTO((FILE *, FTable *, char *)); 
+int   gfits_fread_vtable_range     PROTO((FILE *f, VTable *table, int start, int Nrows));
+int   gfits_fread_vtable           PROTO((FILE *f, VTable *table, char *extname, int Nrow, int *row));
+int   gfits_fread_ftable_data      PROTO((FILE *f, FTable *table));
+int   gfits_fwrite_header          PROTO((FILE *, Header *)); 
+int   gfits_fwrite_Theader         PROTO((FILE *, Header *));
+int   gfits_fwrite_matrix          PROTO((FILE *, Matrix *));      
+int   gfits_fwrite_table           PROTO((FILE *, FTable *)); 
+int   gfits_fwrite_vtable          PROTO((FILE *, VTable *)); 
+
+int   gfits_matrix_size            PROTO ((Header *));
+int   gfits_init_header            PROTO ((Header *));
+int   gfits_create_table_header    PROTO ((Header *, char *, char *));
+int   gfits_vtable_from_ftable     PROTO ((FTable *ftable, VTable *vtable, int *row, int Nrow));
+int   gfits_table_to_vtable        PROTO ((FTable *ftable, VTable *vtable, int start, int Nkeep));
+int   gfits_create_table           PROTO ((Header *, FTable *));
+int   gfits_vadd_rows              PROTO ((VTable *, char *, int, int));
+int   gfits_add_rows               PROTO ((FTable *, char *, int, int));
+char *gfits_table_print            PROTO ((FTable *,...));
+
+/******************************* Matrix functions *************/
+int   gfits_read_matrix            PROTO((char *, Matrix *));      
+int   gfits_read_portion           PROTO((char *filename, Matrix *matrix, int Nskip, int Npix));
+void  gfits_free_matrix            PROTO((Matrix *)); 
+int   gfits_copy_matrix            PROTO((Matrix *, Matrix *)); 
+int   gfits_write_matrix           PROTO((char *,Matrix *)); 
+int   gfits_create_matrix          PROTO((Header *, Matrix *)); 
+double  gfits_get_matrix_value     PROTO((Matrix *, int, int)); 
+void  gfits_set_matrix_value       PROTO((Matrix *, int, int, double)); 
+void  gfits_add_matrix_value       PROTO((Matrix *, int, int, double)); 
+int   gfits_multiply_matrix        PROTO((Matrix *, Matrix *, Matrix *)); 
+int   gfits_divide_matrix          PROTO((Matrix *, Matrix *, Matrix *)); 
+void  gfits_insert_array           PROTO((Matrix *, Matrix *, int, int)); 
+int   gfits_load_matrix            PROTO((FILE *f, Matrix *matrix, Header *header));
+int   gfits_fread_matrix           PROTO((FILE *f, Matrix *matrix, Header *header));
+int   gfits_read_segment           PROTO((char *filename, Matrix *matrix, char *region));
+int   gfits_convert_format         PROTO((Header *header, Matrix *matrix, int outBitpix, double outScale, double outZero, int outUnsign));
+
+/******************************* Table functions *************/
+int   gfits_load_Theader           PROTO((FILE *f, Header *Theader));
+int   gfits_read_Theader           PROTO((char *, Header *));     
+int   gfits_read_table             PROTO((char *, FTable *)); 
+int   gfits_read_table             PROTO((char *, FTable *)); 
+int   gfits_write_Theader          PROTO((char *, Header *header));
+int   gfits_write_table            PROTO((char *, FTable *)); 
+int   gfits_fwrite_table           PROTO((FILE *f, FTable *table));
+int   gfits_fwrite_vtable          PROTO((FILE *f, VTable *table));
+
+int   gfits_bintable_format        PROTO((char *, char *, int *, int *));
+int   gfits_table_format           PROTO((char *, char *, int *, int *));
+int   gfits_save_header            PROTO((FILE *, Header *header));
+int   gfits_set_bintable_column    PROTO((Header *header, FTable *table, char *, void *, int));
+int   gfits_set_table_column       PROTO((Header *header, FTable *table, char *, void *, int));
+int   gfits_define_bintable_column PROTO((Header *header, char *, char *, char *, char *, double, double));
+int   gfits_define_table_column    PROTO((Header *header, char *, char *, char *, char *));
+int   gfits_read_ftable            PROTO((char *filename, FTable *table, char *extname));
+
+int   gfits_free_table             PROTO((FTable *table));
+int   gfits_free_vtable            PROTO((VTable *table));
+int   gfits_create_Theader         PROTO((Header *header, char *type));
+
+/* prototyping demanded for these four -- could be a problem on non-ANSI comp comp */
+int   gfits_scan                   PROTO((Header *, char *, char *, int,...)); 
+int   gfits_print                  PROTO((Header *, char *, char *, int,...)); 
+int   gfits_modify                 PROTO((Header *, char *, char *, int,...)); 
+int   gfits_table_column           PROTO((FTable *, char *, char *,...)); 
+int   gfits_table_column           PROTO((FTable *table, char *, char *,...));
+
+char *gfits_keyword_end            PROTO((char *line));
+int   gfits_vscan                  PROTO((Header *header, char *field, char *mode, int N, va_list argp));
+int   gfits_scan                   PROTO((Header *header, char *field, char *mode, int N,...));
+int   gfits_stripwhite             PROTO((char *string));
+int   gfits_matrix_size            PROTO((Header *header));
+
+int   gfits_get_bintable_column_type PROTO((Header *header, char *label, char *type, int *Nval));
+int   gfits_get_bintable_column    PROTO((Header *header, FTable *table, char *label, void **data));
+int   gfits_get_table_column_type  PROTO((Header *header, char *label, char *type));
+int   gfits_get_table_column       PROTO((Header *header, FTable *table, char *label, void **data));
+
+#endif /* FITSIO */
Index: /branches/libfits-1-8/Ohana/src/libfits/lib/.cvsignore
===================================================================
--- /branches/libfits-1-8/Ohana/src/libfits/lib/.cvsignore	(revision 11932)
+++ /branches/libfits-1-8/Ohana/src/libfits/lib/.cvsignore	(revision 11932)
@@ -0,0 +1,1 @@
+*.linux *.lin64 *.sol *.sun *.sid *.hp *.irix
Index: /branches/libfits-1-8/Ohana/src/libfits/matrix/F_add_M.c
===================================================================
--- /branches/libfits-1-8/Ohana/src/libfits/matrix/F_add_M.c	(revision 11932)
+++ /branches/libfits-1-8/Ohana/src/libfits/matrix/F_add_M.c	(revision 11932)
@@ -0,0 +1,31 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+/*********************** fits insert array ***********************************/
+void gfits_add_matrix (matrix, array, x, y) 
+Matrix *matrix, *array; 
+int x, y;
+{
+
+  /* there is no check here to match BITPIX, BZERO, or BSCALE */
+
+  int i, j;
+  double V;
+
+  if ((x + array[0].Naxis[0] > matrix[0].Naxis[0]) ||
+      (y + array[0].Naxis[1] > matrix[0].Naxis[1])) {
+    fprintf (stderr, "can't add array here: (%d,%d) - (%d,%d) vs (%d,%d)\n",
+	     x, y, x + array[0].Naxis[0], y + array[0].Naxis[1],
+	     matrix[0].Naxis[0], matrix[0].Naxis[1]);
+    return;
+  }
+
+  for (i = 0; i < array[0].Naxis[0]; i++) {
+    for (j = 0; j < array[0].Naxis[1]; j++) {
+      V = gfits_get_matrix_value (array, i, j);
+      V += gfits_get_matrix_value (matrix, x + i, y + j);
+      gfits_set_matrix_value (matrix, x + i, y + j, V);
+    }
+  }
+}
+
Index: /branches/libfits-1-8/Ohana/src/libfits/matrix/F_add_M_value.c
===================================================================
--- /branches/libfits-1-8/Ohana/src/libfits/matrix/F_add_M_value.c	(revision 11932)
+++ /branches/libfits-1-8/Ohana/src/libfits/matrix/F_add_M_value.c	(revision 11932)
@@ -0,0 +1,19 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+/***************** fits add matrix value ***********************************/
+void gfits_add_matrix_value (matrix, x, y, Value) 
+Matrix *matrix; 
+int x, y; 
+double Value;
+{
+
+  double value;
+
+  value = gfits_get_matrix_value (matrix, x, y);
+  value += Value;
+  gfits_set_matrix_value (matrix, x, y, value);
+
+}
+
+
Index: /branches/libfits-1-8/Ohana/src/libfits/matrix/F_convert_format.c
===================================================================
--- /branches/libfits-1-8/Ohana/src/libfits/matrix/F_convert_format.c	(revision 11932)
+++ /branches/libfits-1-8/Ohana/src/libfits/matrix/F_convert_format.c	(revision 11932)
@@ -0,0 +1,392 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+# define CONVERTDOWN \
+  inMode  *in; \
+  outMode *out; \
+  out = (outMode *) matrix[0].buffer; \
+  in  = (inMode  *) matrix[0].buffer; \
+  for (i = 0; i < Npixels; i++, out++, in++) \
+    *out = *in*A + B; \
+  REALLOCATE (matrix[0].buffer, char, matrix[0].size); 
+
+# define CONVERTSAME \
+  inMode  *in; \
+  outMode *out; \
+  out = (outMode *) matrix[0].buffer; \
+  in  = (inMode  *) matrix[0].buffer; \
+  for (i = 0; i < Npixels; i++, out++, in++) \
+    *out = *in*A + B; 
+
+# define CONVERTUP \
+  inMode  *in; \
+  outMode *out; \
+  REALLOCATE (matrix[0].buffer, char, matrix[0].size); \
+  out = (outMode *)matrix[0].buffer + Npixels - 1; \
+  in  = (inMode  *)matrix[0].buffer + Npixels - 1; \
+  for (i = 0; i < Npixels; i++, out--, in--) \
+    *out = *in*A + B;
+
+/*********************** fits convert format ***********************************/
+int gfits_convert_format (Header *header, Matrix *matrix, int outBitpix, double outScale, double outZero, int outUnsign) {
+
+  unsigned long i, nbytes, Npixels;
+  int    inBitpix, inUnsign;
+  double inScale, inZero;
+  double A, B;
+
+  inBitpix         = header[0].bitpix;
+  inScale          = header[0].bscale;
+  inZero           = header[0].bzero;
+  inUnsign         = header[0].unsign;
+
+  if ((inBitpix == outBitpix) && (inScale == outScale) && 
+      (inZero == outZero) && (inUnsign == outUnsign))
+    return (TRUE);
+
+  matrix[0].bitpix = header[0].bitpix = outBitpix;
+  matrix[0].bscale = header[0].bscale = outScale;
+  matrix[0].bzero  = header[0].bzero  = outZero;
+  matrix[0].unsign = header[0].unsign = outUnsign;
+  matrix[0].size   = gfits_matrix_size (header);
+  gfits_modify (header, "BITPIX", "%d", 1, outBitpix);
+  gfits_modify (header, "BSCALE", "%lf", 1, outScale);
+  gfits_modify (header, "BZERO",  "%lf", 1, outZero);
+  gfits_modify (header, "UNSIGN", "%t", 1, outUnsign);
+
+  Npixels          = header[0].Naxis[0]*header[0].Naxis[1];
+  nbytes           = Npixels * (abs(outBitpix) / 8);
+
+  A = inScale / outScale;
+  B = (inZero - outZero) / outScale;
+
+  if ((!outUnsign) && (!inUnsign)) {  /** BLOCK 1 **/
+    switch (inBitpix) {
+    case 8: 
+      { typedef char inMode;
+	switch (outBitpix) {
+	case 8:   { typedef char           outMode; CONVERTSAME; break; }
+	case 16:  { typedef short          outMode; CONVERTUP;   break; }
+	case -16: { typedef unsigned short outMode; CONVERTUP;   break; }
+	case 32:  { typedef int            outMode; CONVERTUP;   break; }
+	case -32: { typedef float          outMode; CONVERTUP;   break; }
+	case -64: { typedef double         outMode; CONVERTUP;   break; }
+	}
+      }
+      break;  
+    case 16: 
+      { typedef short inMode;
+	switch (outBitpix) {
+	case 8:   { typedef char           outMode; CONVERTDOWN; break; }
+	case 16:  { typedef short          outMode; CONVERTSAME; break; }
+	case -16: { typedef unsigned short outMode; CONVERTSAME; break; }
+	case 32:  { typedef int            outMode; CONVERTUP;   break; }
+	case -32: { typedef float          outMode; CONVERTUP;   break; }
+	case -64: { typedef double         outMode; CONVERTUP;   break; }
+	}
+      }
+      break;  
+    case -16: 
+      { typedef unsigned short inMode;
+	switch (outBitpix) {
+	case 8:   { typedef char           outMode; CONVERTDOWN; break; }
+	case 16:  { typedef short          outMode; CONVERTSAME; break; }
+	case -16: { typedef unsigned short outMode; CONVERTSAME; break; }
+	case 32:  { typedef int            outMode; CONVERTUP;   break; }
+	case -32: { typedef float          outMode; CONVERTUP;   break; }
+	case -64: { typedef double         outMode; CONVERTUP;   break; }
+	}
+      }
+      break;  
+    case 32: 
+      { typedef int inMode;
+	switch (outBitpix) {
+	case 8:   { typedef char           outMode; CONVERTDOWN; break; }
+	case 16:  { typedef short          outMode; CONVERTDOWN; break; }
+	case -16: { typedef unsigned short outMode; CONVERTDOWN; break; }
+	case 32:  { typedef int            outMode; CONVERTSAME; break; }
+	case -32: { typedef float          outMode; CONVERTSAME; break; }
+	case -64: { typedef double         outMode; CONVERTUP;   break; }
+	}
+      }
+      break;
+    case -32: 
+      { typedef float inMode;
+	switch (outBitpix) {
+	case 8:   { typedef char           outMode; CONVERTDOWN; break; }
+	case 16:  { typedef short          outMode; CONVERTDOWN; break; }
+	case -16: { typedef unsigned short outMode; CONVERTDOWN; break; }
+	case 32:  { typedef int            outMode; CONVERTSAME; break; }
+	case -32: { typedef float          outMode; CONVERTSAME; break; }
+	case -64: { typedef double         outMode; CONVERTUP;   break; }
+	}
+      }
+      break;
+    case -64: 
+      { typedef double inMode;
+	switch (outBitpix) {
+	case 8:   { typedef char           outMode; CONVERTDOWN; break; }
+	case 16:  { typedef short          outMode; CONVERTDOWN; break; }
+	case -16: { typedef unsigned short outMode; CONVERTDOWN; break; }
+	case 32:  { typedef int            outMode; CONVERTDOWN; break; }
+	case -32: { typedef float          outMode; CONVERTDOWN; break; }
+	case -64: { typedef double         outMode; CONVERTSAME; break; }
+	}
+      }
+    }
+  }
+  if ((outUnsign) && (!inUnsign)) {  /** BLOCK 3 **/
+    switch (inBitpix) {
+    case 8: 
+      { typedef char inMode;
+	switch (outBitpix) {
+	case 8:   { typedef unsigned char   outMode; CONVERTSAME; break; }
+	case 16:  { typedef unsigned short  outMode; CONVERTUP;   break; }
+	case -16: { typedef unsigned short  outMode; CONVERTUP;   break; }
+	case 32:  { typedef unsigned int    outMode; CONVERTUP;   break; }
+	case -32: { typedef          float  outMode; CONVERTUP;   break; }
+	case -64: { typedef          double outMode; CONVERTUP;   break; }
+	}
+      }
+      break;  
+    case 16: 
+      { typedef short inMode;
+	switch (outBitpix) {
+	case 8:   { typedef unsigned char   outMode; CONVERTDOWN; break; }
+	case 16:  { typedef unsigned short  outMode; CONVERTSAME; break; }
+	case -16: { typedef unsigned short  outMode; CONVERTSAME; break; }
+	case 32:  { typedef unsigned int    outMode; CONVERTUP;   break; }
+	case -32: { typedef          float  outMode; CONVERTUP;   break; }
+	case -64: { typedef          double outMode; CONVERTUP;   break; }
+	}
+      }
+      break;  
+    case -16: 
+      { typedef unsigned short inMode;
+	switch (outBitpix) {
+	case 8:   { typedef unsigned char   outMode; CONVERTDOWN; break; }
+	case 16:  { typedef unsigned short  outMode; CONVERTSAME; break; }
+	case -16: { typedef unsigned short  outMode; CONVERTSAME; break; }
+	case 32:  { typedef unsigned int    outMode; CONVERTUP;   break; }
+	case -32: { typedef          float  outMode; CONVERTUP;   break; }
+	case -64: { typedef          double outMode; CONVERTUP;   break; }
+	}
+      }
+      break;  
+    case 32: 
+      { typedef int inMode;
+	switch (outBitpix) {
+	case 8:   { typedef unsigned char   outMode; CONVERTDOWN; break; }
+	case 16:  { typedef unsigned short  outMode; CONVERTDOWN; break; }
+	case -16: { typedef unsigned short  outMode; CONVERTDOWN; break; }
+	case 32:  { typedef unsigned int    outMode; CONVERTSAME; break; }
+	case -32: { typedef          float  outMode; CONVERTSAME; break; }
+	case -64: { typedef          double outMode; CONVERTUP;   break; }
+	}
+      }
+      break;
+    case -32: 
+      { typedef float inMode;
+	switch (outBitpix) {
+	case 8:   { typedef unsigned char   outMode; CONVERTDOWN; break; }
+	case 16:  { typedef unsigned short  outMode; CONVERTDOWN; break; }
+	case -16: { typedef unsigned short  outMode; CONVERTDOWN; break; }
+	case 32:  { typedef unsigned int    outMode; CONVERTSAME; break; }
+	case -32: { typedef          float  outMode; CONVERTSAME; break; }
+	case -64: { typedef          double outMode; CONVERTUP;   break; }
+	}
+      }
+      break;
+    case -64: 
+      { typedef double inMode;
+	switch (outBitpix) {
+	case 8:   { typedef unsigned char   outMode; CONVERTDOWN; break; }
+	case 16:  { typedef unsigned short  outMode; CONVERTDOWN; break; }
+	case -16: { typedef unsigned short  outMode; CONVERTDOWN; break; }
+	case 32:  { typedef unsigned int    outMode; CONVERTDOWN; break; }
+	case -32: { typedef          float  outMode; CONVERTDOWN; break; }
+	case -64: { typedef          double outMode; CONVERTSAME; break; }
+	}
+      }
+    }
+  }
+  if ((!outUnsign) && (inUnsign)) {  /** BLOCK 2 **/
+    switch (inBitpix) {
+    case 8: 
+      { typedef unsigned char inMode;
+	switch (outBitpix) {
+	case 8:   { typedef char           outMode; CONVERTSAME; break; }
+	case 16:  { typedef short          outMode; CONVERTUP;   break; }
+	case -16: { typedef unsigned short outMode; CONVERTUP;   break; }
+	case 32:  { typedef int            outMode; CONVERTUP;   break; }
+	case -32: { typedef float          outMode; CONVERTUP;   break; }
+	case -64: { typedef double         outMode; CONVERTUP;   break; }
+	}
+      }
+      break;  
+    case 16: 
+      { typedef unsigned short inMode;
+	switch (outBitpix) {
+	case 8:   { typedef char           outMode; CONVERTDOWN; break; }
+	case 16:  { typedef short          outMode; CONVERTSAME; break; }
+	case -16: { typedef unsigned short outMode; CONVERTSAME; break; }
+	case 32:  { typedef int            outMode; CONVERTUP;   break; }
+	case -32: { typedef float          outMode; CONVERTUP;   break; }
+	case -64: { typedef double         outMode; CONVERTUP;   break; }
+	}
+      }
+      break;  
+    case -16: 
+      { typedef unsigned short inMode;
+	switch (outBitpix) {
+	case 8:   { typedef char           outMode; CONVERTDOWN; break; }
+	case 16:  { typedef short          outMode; CONVERTSAME; break; }
+	case -16: { typedef unsigned short outMode; CONVERTSAME; break; }
+	case 32:  { typedef int            outMode; CONVERTUP;   break; }
+	case -32: { typedef float          outMode; CONVERTUP;   break; }
+	case -64: { typedef double         outMode; CONVERTUP;   break; }
+	}
+      }
+      break;  
+    case 32: 
+      { typedef unsigned int inMode;
+	switch (outBitpix) {
+	case 8:   { typedef char           outMode; CONVERTDOWN; break; }
+	case 16:  { typedef short          outMode; CONVERTDOWN; break; }
+	case -16: { typedef unsigned short outMode; CONVERTDOWN; break; }
+	case 32:  { typedef int            outMode; CONVERTSAME; break; }
+	case -32: { typedef float          outMode; CONVERTSAME; break; }
+	case -64: { typedef double         outMode; CONVERTUP;   break; }
+	}
+      }
+      break;
+    case -32: 
+      { typedef float inMode;
+	switch (outBitpix) {
+	case 8:   { typedef char           outMode; CONVERTDOWN; break; }
+	case 16:  { typedef short          outMode; CONVERTDOWN; break; }
+	case -16: { typedef unsigned short outMode; CONVERTDOWN; break; }
+	case 32:  { typedef int            outMode; CONVERTSAME; break; }
+	case -32: { typedef float          outMode; CONVERTSAME; break; }
+	case -64: { typedef double         outMode; CONVERTUP;   break; }
+	}
+      }
+      break;
+    case -64: 
+      { typedef double inMode;
+	switch (outBitpix) {
+	case 8:   { typedef char           outMode; CONVERTDOWN; break; }
+	case 16:  { typedef short          outMode; CONVERTDOWN; break; }
+	case -16: { typedef unsigned short outMode; CONVERTDOWN; break; }
+	case 32:  { typedef int            outMode; CONVERTDOWN; break; }
+	case -32: { typedef float          outMode; CONVERTDOWN; break; }
+	case -64: { typedef double         outMode; CONVERTSAME; break; }
+	}
+      }
+    }
+  }
+  if ((outUnsign) && (inUnsign)) {
+    switch (inBitpix) {
+    case 8: 
+      { typedef unsigned char inMode;
+	switch (outBitpix) {
+	case 8:   { typedef unsigned char   outMode; CONVERTSAME; break; }
+	case 16:  { typedef unsigned short  outMode; CONVERTUP;   break; }
+	case -16: { typedef unsigned short  outMode; CONVERTDOWN; break; }
+	case 32:  { typedef unsigned int    outMode; CONVERTUP;   break; }
+	case -32: { typedef          float  outMode; CONVERTUP;   break; }
+	case -64: { typedef          double outMode; CONVERTUP;   break; }
+	}
+      }
+      break;  
+    case 16: 
+      { typedef unsigned short inMode;
+	switch (outBitpix) {
+	case 8:   { typedef unsigned char   outMode; CONVERTDOWN; break; }
+	case 16:  { typedef unsigned short  outMode; CONVERTSAME; break; }
+	case -16: { typedef unsigned short  outMode; CONVERTDOWN; break; }
+	case 32:  { typedef unsigned int    outMode; CONVERTUP;   break; }
+	case -32: { typedef          float  outMode; CONVERTUP;   break; }
+	case -64: { typedef          double outMode; CONVERTUP;   break; }
+	}
+      }
+      break;  
+    case -16: 
+      { typedef unsigned short inMode;
+	switch (outBitpix) {
+	case 8:   { typedef unsigned char   outMode; CONVERTDOWN; break; }
+	case 16:  { typedef unsigned short  outMode; CONVERTSAME; break; }
+	case -16: { typedef unsigned short  outMode; CONVERTDOWN; break; }
+	case 32:  { typedef unsigned int    outMode; CONVERTUP;   break; }
+	case -32: { typedef          float  outMode; CONVERTUP;   break; }
+	case -64: { typedef          double outMode; CONVERTUP;   break; }
+	}
+      }
+      break;  
+    case 32: 
+      { typedef unsigned int inMode;
+	switch (outBitpix) {
+	case 8:   { typedef unsigned char   outMode; CONVERTDOWN; break; }
+	case 16:  { typedef unsigned short  outMode; CONVERTDOWN; break; }
+	case -16: { typedef unsigned short  outMode; CONVERTDOWN; break; }
+	case 32:  { typedef unsigned int    outMode; CONVERTSAME; break; }
+	case -32: { typedef          float  outMode; CONVERTSAME; break; }
+	case -64: { typedef          double outMode; CONVERTUP;   break; }
+	}				    
+      }					    
+      break;				    
+    case -32: 				    
+      { typedef float inMode;		    
+	switch (outBitpix) {		    
+	case 8:   { typedef unsigned char   outMode; CONVERTDOWN; break; }
+	case 16:  { typedef unsigned short  outMode; CONVERTDOWN; break; }
+	case -16: { typedef unsigned short  outMode; CONVERTDOWN; break; }
+	case 32:  { typedef unsigned int    outMode; CONVERTSAME; break; }
+	case -32: { typedef          float  outMode; CONVERTSAME; break; }
+	case -64: { typedef          double outMode; CONVERTUP;   break; }
+	}				    
+      }					    
+      break;				    
+    case -64: 				    
+      { typedef double inMode;		    
+	switch (outBitpix) {		    
+	case 8:   { typedef unsigned char   outMode; CONVERTDOWN; break; }
+	case 16:  { typedef unsigned short  outMode; CONVERTDOWN; break; }
+	case -16: { typedef unsigned short  outMode; CONVERTDOWN; break; }
+	case 32:  { typedef unsigned int    outMode; CONVERTDOWN; break; }
+	case -32: { typedef          float  outMode; CONVERTDOWN; break; }
+	case -64: { typedef          double outMode; CONVERTSAME; break; }
+	}
+      }
+    }
+  }
+
+  /* zero the padding region */
+  {
+    char *out;
+    int Nextra;
+    
+    out = (char *)matrix[0].buffer;
+    Nextra = matrix[0].size - nbytes;
+    bzero (&out[nbytes], Nextra);
+  }
+
+  return (TRUE);
+}
+ 
+/* WARNING --- this is STILL machine dependant.  It will now work on all 
+   machines, as long as char, int, short, float, double have sizes of 
+   8, 16, 32, 32, 64 bits resp.  However, the floating pt types are NOT
+   universal (or FITS standard), and so can't exchange from machine to 
+   machine. */
+
+/* NOTICE -- This file looks rather strange.  It is set this way to make 
+   all of the possible inter-conversions without too much excess code. 
+   The macros CONVERTUP and CONVERTDOWN need to be distinct.
+   Going to smaller or equal BITPIX, it is safe to run the array forward 
+   and allocate after the conversion.
+   Going to larger BITPIX, you need to reallocate first and run backwards 
+   to avoid wiping out the pixels.
+   OK, to deal with in and out UNSIGN, I have made four if blocks that are
+   almost identical. this looks silly.  any suggestions? 
+*/
Index: /branches/libfits-1-8/Ohana/src/libfits/matrix/F_copy_M.c
===================================================================
--- /branches/libfits-1-8/Ohana/src/libfits/matrix/F_copy_M.c	(revision 11932)
+++ /branches/libfits-1-8/Ohana/src/libfits/matrix/F_copy_M.c	(revision 11932)
@@ -0,0 +1,25 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+/*********************** fits copy header ***********************************/
+int gfits_copy_matrix (Matrix *matrix1, Matrix *matrix2) {
+
+  int i;
+
+  matrix2[0].unsign = matrix1[0].unsign;
+  matrix2[0].bitpix = matrix1[0].bitpix;
+  matrix2[0].size   = matrix1[0].size;
+  matrix2[0].bzero  = matrix1[0].bzero;
+  matrix2[0].bscale = matrix1[0].bscale;
+  matrix2[0].Naxes  = matrix1[0].Naxes;
+  for (i = 0; i < FT_MAX_NAXES; i++) 
+    matrix2[0].Naxis[i] = matrix1[0].Naxis[i];
+
+  ALLOCATE (matrix2[0].buffer, char, matrix2[0].size);
+  
+  memcpy (matrix2[0].buffer, matrix1[0].buffer, matrix2[0].size);
+
+  return (TRUE);
+}	
+
+
Index: /branches/libfits-1-8/Ohana/src/libfits/matrix/F_create_M.c
===================================================================
--- /branches/libfits-1-8/Ohana/src/libfits/matrix/F_create_M.c	(revision 11932)
+++ /branches/libfits-1-8/Ohana/src/libfits/matrix/F_create_M.c	(revision 11932)
@@ -0,0 +1,28 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+/*********************** fits create matrix *******************************/
+int gfits_create_matrix (header, matrix) 
+Header *header;
+Matrix *matrix;
+{
+
+  int i, Nbytes;
+
+  matrix[0].bitpix = header[0].bitpix;
+  matrix[0].unsign = header[0].unsign;
+  matrix[0].bscale = header[0].bscale;
+  matrix[0].bzero  = header[0].bzero;
+  matrix[0].Naxes  = header[0].Naxes;
+  for (i = 0; i < FT_MAX_NAXES; i++)
+    matrix[0].Naxis[i] = header[0].Naxis[i];
+
+  Nbytes = gfits_matrix_size (header);
+  ALLOCATE (matrix[0].buffer, char, MAX (Nbytes, 1));
+  bzero (matrix[0].buffer, Nbytes);
+  
+  matrix[0].size = Nbytes;
+  return (TRUE);
+
+}
+
Index: /branches/libfits-1-8/Ohana/src/libfits/matrix/F_divide_M.c
===================================================================
--- /branches/libfits-1-8/Ohana/src/libfits/matrix/F_divide_M.c	(revision 11932)
+++ /branches/libfits-1-8/Ohana/src/libfits/matrix/F_divide_M.c	(revision 11932)
@@ -0,0 +1,30 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+/********************* fits divide matrix ***********************************/
+int gfits_divide_matrix (Matrix *M1, Matrix *M2, Matrix *M3) {
+
+  int i,j;
+  double value, val2;
+
+  if ((M1[0].Naxis[0] != M2[0].Naxis[0]) ||
+      (M1[0].Naxis[1] != M2[0].Naxis[1])) 
+    return (FALSE);
+
+  for (i = 0; i < M1[0].Naxis[0]; i++) {
+    for (j = 0; j < M1[0].Naxis[1]; j++) {
+      value = gfits_get_matrix_value (M1, i, j);
+      val2  = gfits_get_matrix_value (M2, i, j);
+      if (val2 != 0) 
+	value = value / val2;
+      else
+	value = 0.0;
+      gfits_set_matrix_value (M3, i, j, value);
+    }
+  }
+  
+  return (TRUE);
+
+}
+
+
Index: /branches/libfits-1-8/Ohana/src/libfits/matrix/F_free_M.c
===================================================================
--- /branches/libfits-1-8/Ohana/src/libfits/matrix/F_free_M.c	(revision 11932)
+++ /branches/libfits-1-8/Ohana/src/libfits/matrix/F_free_M.c	(revision 11932)
@@ -0,0 +1,13 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+/*********************** fits free matrix ***********************************/
+void gfits_free_matrix (Matrix *matrix) {
+
+  if (matrix[0].buffer == (char *) NULL) return;
+  free (matrix[0].buffer);
+  matrix[0].buffer = (char *) NULL;
+  
+}
+
+
Index: /branches/libfits-1-8/Ohana/src/libfits/matrix/F_get_M_value.c
===================================================================
--- /branches/libfits-1-8/Ohana/src/libfits/matrix/F_get_M_value.c	(revision 11932)
+++ /branches/libfits-1-8/Ohana/src/libfits/matrix/F_get_M_value.c	(revision 11932)
@@ -0,0 +1,62 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+/***************** fits get matrix value ***********************************/
+double gfits_get_matrix_value (matrix, x, y) 
+Matrix *matrix; 
+int x, y;
+{
+
+  double value;
+  int pixel;
+
+  if ((x < 0) || (x >= matrix[0].Naxis[0]) || (y < 0) || (y >= matrix[0].Naxis[1]))
+    return (0.0);
+  pixel = matrix[0].Naxis[0]*y + x;
+  value = HUGE_VAL;
+
+  if (matrix[0].unsign) {
+    switch (matrix[0].bitpix) {
+    case 8:
+      value = *((unsigned char  *) matrix[0].buffer + pixel);
+      break;
+    case 16:
+      value = *((unsigned short *) matrix[0].buffer + pixel);
+      break;
+    case 32:
+      value = *((unsigned int   *) matrix[0].buffer + pixel);
+      break;
+    case -32:
+      value = *((float          *) matrix[0].buffer + pixel);
+      break;
+    case -64:
+      value = *((double         *) matrix[0].buffer + pixel);
+      break;
+    }
+  }
+  else {
+    switch (matrix[0].bitpix) {
+    case 8:
+      value = *((char  *) matrix[0].buffer + pixel);
+      break;
+    case 16:
+      value = *((short *) matrix[0].buffer + pixel);
+      break;
+    case 32:
+      value = *((int   *) matrix[0].buffer + pixel);
+      break;
+    case -32:
+      value = *((float          *) matrix[0].buffer + pixel);
+      break;
+    case -64:
+      value = *((double         *) matrix[0].buffer + pixel);
+      break;
+    }
+  }
+
+  value = matrix[0].bscale*value + matrix[0].bzero;
+  return (value);
+
+}
+
+
Index: /branches/libfits-1-8/Ohana/src/libfits/matrix/F_insert_M.c
===================================================================
--- /branches/libfits-1-8/Ohana/src/libfits/matrix/F_insert_M.c	(revision 11932)
+++ /branches/libfits-1-8/Ohana/src/libfits/matrix/F_insert_M.c	(revision 11932)
@@ -0,0 +1,29 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+/*********************** fits insert array ***********************************/
+void gfits_insert_matrix (Matrix  *matrix, Matrix *array, int x, int y) {
+
+  /* there is no check here to match BITPIX, BZERO, or BSCALE */
+
+  int i, start_m, Nbytes_m, Nbytes;
+
+  if ((x + array[0].Naxis[0] > matrix[0].Naxis[0]) ||
+      (y + array[0].Naxis[1] > matrix[0].Naxis[1])) {
+    fprintf (stderr, "can't insert array here: (%d,%d) - (%d,%d) vs (%d,%d)\n",
+	     x, y, x + array[0].Naxis[0], y + array[0].Naxis[1],
+	     matrix[0].Naxis[0], matrix[0].Naxis[1]);
+    return;
+  }
+
+  Nbytes = array[0].Naxis[0]*abs(array[0].bitpix) / 8;
+  Nbytes_m = matrix[0].Naxis[0]*abs(matrix[0].bitpix) / 8;
+  start_m = y*Nbytes_m + x*abs(matrix[0].bitpix) / 8;
+
+  for (i = 0; i < array[0].Naxis[1]; i++) {
+    memmove (&matrix[0].buffer[start_m + i*Nbytes_m], 
+	     &array[0].buffer[i*Nbytes], Nbytes);
+  }
+  
+}
+
Index: /branches/libfits-1-8/Ohana/src/libfits/matrix/F_load_M.c
===================================================================
--- /branches/libfits-1-8/Ohana/src/libfits/matrix/F_load_M.c	(revision 11932)
+++ /branches/libfits-1-8/Ohana/src/libfits/matrix/F_load_M.c	(revision 11932)
@@ -0,0 +1,92 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+int gfits_fread_matrix (FILE *f, Matrix *matrix, Header *header) {
+  
+  int status;
+  
+  status = gfits_load_matrix (f, matrix, header);
+  return (status);
+}
+
+/*********************** fits read matrix ***********************************/
+int gfits_load_matrix (FILE *f, Matrix *matrix, Header *header) {
+
+  int i, nbytes, Nbytes;
+  unsigned char *byte0, *byte1, *byte2, *byte3, *byte4, *byte5, *byte6, *byte7, tmp;
+  int perpix;
+
+  matrix[0].bitpix = header[0].bitpix;
+  matrix[0].unsign = header[0].unsign;
+  matrix[0].bscale = header[0].bscale;
+  matrix[0].bzero  = header[0].bzero;
+  matrix[0].Naxes  = header[0].Naxes;
+  for (i = 0; i < FT_MAX_NAXES; i++)
+    matrix[0].Naxis[i] = header[0].Naxis[i];
+
+  Nbytes = gfits_matrix_size (header);
+  ALLOCATE (matrix[0].buffer, char, Nbytes);
+  matrix[0].size = Nbytes;
+
+  nbytes = fread (matrix[0].buffer, sizeof(char), Nbytes, f);
+
+# ifdef BYTE_SWAP  
+  perpix = abs(header[0].bitpix) / 8;
+  if (perpix > 1) {
+    byte0 = (unsigned char *) matrix[0].buffer;
+    byte1 = (unsigned char *) matrix[0].buffer + 1;
+    byte2 = (unsigned char *) matrix[0].buffer + 2;
+    byte3 = (unsigned char *) matrix[0].buffer + 3;
+    byte4 = (unsigned char *) matrix[0].buffer + 4;
+    byte5 = (unsigned char *) matrix[0].buffer + 5;
+    byte6 = (unsigned char *) matrix[0].buffer + 6;
+    byte7 = (unsigned char *) matrix[0].buffer + 7;
+    if (perpix == 2) {
+      for (i = 0; i < nbytes; i+=2, byte0 += 2, byte1 += 2) {
+	tmp = *byte0;
+	*byte0 = *byte1;
+	*byte1 = tmp;
+      }
+    }
+    if (perpix == 4) {
+      for (i = 0; i < nbytes; i+=4, byte0 += 4, byte1 += 4, byte2 += 4, byte3 += 4) {
+	tmp = *byte0;
+	*byte0 = *byte3;
+	*byte3 = tmp;
+	tmp = *byte1;
+	*byte1 = *byte2;
+	*byte2 = tmp;
+      }
+    }
+    if (perpix == 8) {
+      for (i = 0; i < nbytes; i+=8, byte0 += 8, byte1 += 8, byte2 += 8, byte3 += 8, byte4 += 8, byte5 += 8, byte6 += 8, byte7 += 8) {
+	tmp = *byte0;
+	*byte0 = *byte7;
+	*byte7 = tmp;
+	tmp = *byte1;
+	*byte1 = *byte6;
+	*byte6 = tmp;
+	tmp = *byte1;
+	*byte2 = *byte5;
+	*byte5 = tmp;
+	tmp = *byte1;
+	*byte3 = *byte4;
+	*byte4 = tmp;
+      }
+    }
+  }
+# endif
+
+  if (nbytes < Nbytes - 2880) {  /* this is a bad FITS error: image is not OK */
+    fprintf (stderr, "error reading in matrix data from FITS file\n");
+    return (FALSE);
+  }
+  if (nbytes != Nbytes) {  /* this is a FITS error, but often the image is OK */
+    fprintf (stderr, "incomplete block in FITS file: (%d, %d)\n", nbytes, Nbytes);
+    return (TRUE); 
+  }
+
+  return (TRUE);
+
+}
+
Index: /branches/libfits-1-8/Ohana/src/libfits/matrix/F_matrix.c
===================================================================
--- /branches/libfits-1-8/Ohana/src/libfits/matrix/F_matrix.c	(revision 11932)
+++ /branches/libfits-1-8/Ohana/src/libfits/matrix/F_matrix.c	(revision 11932)
@@ -0,0 +1,22 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+int gfits_matrix_size (Header *header) {
+  
+  int i, Nrec, size;
+
+  if (header[0].Naxes == 0) return (0);
+
+  size = abs(header[0].bitpix / 8);
+
+  for (i = 0; i < header[0].Naxes; i++)
+    size *= header[0].Naxis[i];
+
+  /* round up to next complete block */
+  if (size % FT_RECORD_SIZE) {
+    Nrec = 1 + (int) (size / FT_RECORD_SIZE);
+    size = FT_RECORD_SIZE * Nrec;
+  }
+
+  return (size);
+}
Index: /branches/libfits-1-8/Ohana/src/libfits/matrix/F_multiply_M.c
===================================================================
--- /branches/libfits-1-8/Ohana/src/libfits/matrix/F_multiply_M.c	(revision 11932)
+++ /branches/libfits-1-8/Ohana/src/libfits/matrix/F_multiply_M.c	(revision 11932)
@@ -0,0 +1,26 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+/******************* fits multiply matrix ***********************************/
+int gfits_multiply_matrix (Matrix *M1, Matrix *M2, Matrix *M3) {
+
+  int i,j;
+  double value;
+
+  if ((M1[0].Naxis[0] != M2[0].Naxis[0]) ||
+      (M1[0].Naxis[1] != M2[0].Naxis[1])) 
+    return (FALSE);
+
+  for (i = 0; i < M1[0].Naxis[0]; i++) {
+    for (j = 0; j < M1[0].Naxis[1]; j++) {
+      value = gfits_get_matrix_value (M1, i, j);
+      value *= gfits_get_matrix_value (M2, i, j);
+      gfits_set_matrix_value (M3, i, j, value);
+    }
+  }
+  
+  return (TRUE);
+
+}
+
+
Index: /branches/libfits-1-8/Ohana/src/libfits/matrix/F_read_M.c
===================================================================
--- /branches/libfits-1-8/Ohana/src/libfits/matrix/F_read_M.c	(revision 11932)
+++ /branches/libfits-1-8/Ohana/src/libfits/matrix/F_read_M.c	(revision 11932)
@@ -0,0 +1,29 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+/*********************** fits read matrix ***********************************/
+int gfits_read_matrix (char *filename, Matrix *matrix) {
+
+  FILE *f;
+  Header header;
+  int status;
+
+  status = gfits_read_header (filename, &header);
+  if (!status) {
+    fprintf (stderr, "error reading header of FITS file %s\n", filename);
+    return (FALSE);
+  }
+
+  f = fopen (filename, "r");
+  if (f == NULL) return (FALSE);
+
+  fseek (f, header.size, 0);
+  
+  status = gfits_load_matrix (f, matrix, &header);
+
+  fclose (f);
+
+  return (status);
+
+}
+
Index: /branches/libfits-1-8/Ohana/src/libfits/matrix/F_read_portion.c
===================================================================
--- /branches/libfits-1-8/Ohana/src/libfits/matrix/F_read_portion.c	(revision 11932)
+++ /branches/libfits-1-8/Ohana/src/libfits/matrix/F_read_portion.c	(revision 11932)
@@ -0,0 +1,112 @@
+# include <ohana.h>
+# include <gfitsio.h>
+# ifndef SEEK_CUR 
+# define SEEK_SET 0   
+# define SEEK_CUR 1   
+# define SEEK_END 2
+# endif
+
+/*********************** fits read matrix ***********************************/
+/** the result of this function is a matrix with dimension Npix * 1 **/
+int gfits_read_portion (char *filename, Matrix *matrix, int Nskip, int Npix) {
+
+  FILE *f;
+  Header header;
+  int status, i, nbytes, Nbytes, Nrec;
+  unsigned char *byte0, *byte1, *byte2, *byte3, *byte4, *byte5, *byte6, *byte7, ctmp;
+  int perpix;
+
+  status = gfits_read_header (filename, &header);
+  if (!status) {
+    fprintf (stderr, "error reading header of FITS file %s\n", filename);
+    return (FALSE);
+  }
+
+  matrix[0].bitpix = header.bitpix;
+  matrix[0].unsign = header.unsign;
+  matrix[0].bscale = header.bscale;
+  matrix[0].bzero  = header.bzero;
+  matrix[0].Naxes  = 2;
+  matrix[0].Naxis[0] = Npix;
+  matrix[0].Naxis[1] = 1;
+
+  Nbytes = Npix  * abs (matrix[0].bitpix)/8;
+  Nskip  = Nskip * abs (matrix[0].bitpix)/8;
+
+  /* round up to next complete block */
+  if (Nbytes % FT_RECORD_SIZE) {
+    Nrec = 1 + (int) (Nbytes / FT_RECORD_SIZE);
+    Nbytes = FT_RECORD_SIZE * Nrec;
+  }
+  matrix[0].size = Nbytes;
+  ALLOCATE (matrix[0].buffer, char, Nbytes);
+
+  /* open file, read data, close file */
+  f = fopen (filename, "r");
+  if (f == NULL) return (FALSE);
+  fseek (f, header.size + Nskip, SEEK_SET);
+  nbytes = fread (matrix[0].buffer, sizeof(char), Nbytes, f);
+  fclose (f);
+
+# ifdef BYTE_SWAP  
+  perpix = abs(header.bitpix) / 8;
+  if (perpix > 1) {
+    byte0 = (unsigned char *) matrix[0].buffer;
+    byte1 = (unsigned char *) matrix[0].buffer + 1;
+    byte2 = (unsigned char *) matrix[0].buffer + 2;
+    byte3 = (unsigned char *) matrix[0].buffer + 3;
+    byte4 = (unsigned char *) matrix[0].buffer + 4;
+    byte5 = (unsigned char *) matrix[0].buffer + 5;
+    byte6 = (unsigned char *) matrix[0].buffer + 6;
+    byte7 = (unsigned char *) matrix[0].buffer + 7;
+    if (perpix == 2) {
+      for (i = 0; i < nbytes; i+=2, byte0 += 2, byte1 += 2) {
+	ctmp = *byte0;
+	*byte0 = *byte1;
+	*byte1 = ctmp;
+      }
+    }
+    if (perpix == 4) {
+      for (i = 0; i < nbytes; i+=4, byte0 += 4, byte1 += 4, byte2 += 4, byte3 += 4) {
+	ctmp = *byte0;
+	*byte0 = *byte3;
+	*byte3 = ctmp;
+	ctmp = *byte1;
+	*byte1 = *byte2;
+	*byte2 = ctmp;
+      }
+    }
+    if (perpix == 8) {
+      for (i = 0; i < nbytes; i+=8, byte0 += 8, byte1 += 8, byte2 += 8, byte3 += 8, byte4 += 8, byte5 += 8, byte6 += 8, byte7 += 8) {
+	ctmp = *byte0;
+	*byte0 = *byte7;
+	*byte7 = ctmp;
+	ctmp = *byte1;
+	*byte1 = *byte6;
+	*byte6 = ctmp;
+	ctmp = *byte1;
+	*byte2 = *byte5;
+	*byte5 = ctmp;
+	ctmp = *byte1;
+	*byte3 = *byte4;
+	*byte4 = ctmp;
+      }
+    }
+  }
+# endif
+
+  gfits_free_header (&header);
+
+  if (nbytes < Nbytes - 2880) {  /* this is a bad FITS error: image is not OK */
+    fprintf (stderr, "error reading in matrix data from FITS file %s (%d < %d - 2880)\n", filename, nbytes, Nbytes);
+    return (FALSE);
+  }
+  if (nbytes != Nbytes) {  /* this is a FITS error, but often the image is OK */
+    fprintf (stderr, "incomplete block in %s: (%d, %d)\n", filename, nbytes, Nbytes);
+    return (TRUE); 
+  }
+
+  return (TRUE);
+
+}
+
Index: /branches/libfits-1-8/Ohana/src/libfits/matrix/F_read_segment.c
===================================================================
--- /branches/libfits-1-8/Ohana/src/libfits/matrix/F_read_segment.c	(revision 11932)
+++ /branches/libfits-1-8/Ohana/src/libfits/matrix/F_read_segment.c	(revision 11932)
@@ -0,0 +1,144 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+/** warning: this function requires 'dparse' which is included in libohana.a **/
+int dparse (double *, int, char *region);
+
+/*********************** fits read matrix ***********************************/
+int gfits_read_segment (char *filename, Matrix *matrix, char *region) {
+
+  FILE *f;
+  Header header;
+  int status, i, nbytes, Nbytes, Nskip, NbytesData;
+  int wantaxis[FT_MAX_NAXES][2];
+  unsigned char *byte0, *byte1, *byte2, *byte3, *byte4, *byte5, *byte6, *byte7, ctmp;
+  double tmp;
+  int perpix;
+
+  status = gfits_read_header (filename, &header);
+  if (!status) {
+    fprintf (stderr, "error reading header of FITS file %s\n", filename);
+    return (FALSE);
+  }
+
+  f = fopen (filename, "r");
+  if (f == NULL) {
+    return (FALSE);
+  }
+
+  for (i = 0; i < FT_MAX_NAXES; i++) {
+    wantaxis[i][0] = wantaxis[i][1] = 0;
+  }
+
+  for (i = 0; i < header.Naxes; i++) {
+    status = dparse (&tmp, 2*i + 1, region);
+    if (!status || (tmp < 0))
+      wantaxis[i][0] = 0;
+    else 
+      wantaxis[i][0] = (tmp > header.Naxis[i] - 1) ? header.Naxis[i] - 1 : tmp;
+    status = dparse (&tmp, 2*i + 2, region);
+    if (!status || (tmp < 0))
+      wantaxis[i][1] = header.Naxis[i];
+    else 
+      wantaxis[i][1] = (tmp > header.Naxis[i]) ? header.Naxis[i] : tmp;
+  }
+
+  fseek (f, header.size, 0);
+
+  matrix[0].bitpix = header.bitpix;
+  matrix[0].unsign = header.unsign;
+  matrix[0].bscale = header.bscale;
+  matrix[0].bzero  = header.bzero;
+  matrix[0].Naxes  = header.Naxes;
+  for (i = 0; i < FT_MAX_NAXES; i++)
+    matrix[0].Naxis[i] = wantaxis[i][1] - wantaxis[i][0];
+
+  matrix[0].size = abs (matrix[0].bitpix) / 8;
+  for (i = 0; i < matrix[0].Naxes; i++)
+    matrix[0].size *= matrix[0].Naxis[i];
+
+  Nskip = wantaxis[2][0]*matrix[0].Naxis[0]*matrix[0].Naxis[1]*abs(matrix[0].bitpix)/8;
+  NbytesData = Nskip + matrix[0].size;
+
+  if (NbytesData % FT_RECORD_SIZE) 
+    Nbytes = FT_RECORD_SIZE * ((int) (NbytesData / FT_RECORD_SIZE) + 1) - Nskip;
+  else 
+    Nbytes = FT_RECORD_SIZE * ((int) (NbytesData / FT_RECORD_SIZE)) - Nskip;
+
+  ALLOCATE (matrix[0].buffer, char, MAX (Nbytes, 1));
+
+# ifndef SEEK_CUR 
+# define SEEK_SET 0   
+# define SEEK_CUR 1   
+# define SEEK_END 2
+# endif
+
+  /* currently only good for reading in full planes in 3-D */
+  fseek (f, Nskip, SEEK_CUR);
+
+  nbytes = fread (matrix[0].buffer, sizeof(char), Nbytes, f);
+  fclose (f);
+  matrix[0].size = Nbytes;
+
+# ifdef BYTE_SWAP  
+  perpix = abs(header.bitpix) / 8;
+  if (perpix > 1) {
+    byte0 = (unsigned char *) matrix[0].buffer;
+    byte1 = (unsigned char *) matrix[0].buffer + 1;
+    byte2 = (unsigned char *) matrix[0].buffer + 2;
+    byte3 = (unsigned char *) matrix[0].buffer + 3;
+    byte4 = (unsigned char *) matrix[0].buffer + 4;
+    byte5 = (unsigned char *) matrix[0].buffer + 5;
+    byte6 = (unsigned char *) matrix[0].buffer + 6;
+    byte7 = (unsigned char *) matrix[0].buffer + 7;
+    if (perpix == 2) {
+      for (i = 0; i < nbytes; i+=2, byte0 += 2, byte1 += 2) {
+	ctmp = *byte0;
+	*byte0 = *byte1;
+	*byte1 = ctmp;
+      }
+    }
+    if (perpix == 4) {
+      for (i = 0; i < nbytes; i+=4, byte0 += 4, byte1 += 4, byte2 += 4, byte3 += 4) {
+	ctmp = *byte0;
+	*byte0 = *byte3;
+	*byte3 = ctmp;
+	ctmp = *byte1;
+	*byte1 = *byte2;
+	*byte2 = ctmp;
+      }
+    }
+    if (perpix == 8) {
+      for (i = 0; i < nbytes; i+=8, byte0 += 8, byte1 += 8, byte2 += 8, byte3 += 8, byte4 += 8, byte5 += 8, byte6 += 8, byte7 += 8) {
+	ctmp = *byte0;
+	*byte0 = *byte7;
+	*byte7 = ctmp;
+	ctmp = *byte1;
+	*byte1 = *byte6;
+	*byte6 = ctmp;
+	ctmp = *byte1;
+	*byte2 = *byte5;
+	*byte5 = ctmp;
+	ctmp = *byte1;
+	*byte3 = *byte4;
+	*byte4 = ctmp;
+      }
+    }
+  }
+# endif
+
+  gfits_free_header (&header);
+
+  if (nbytes < Nbytes - 2880) {  /* this is a bad FITS error: image is not OK */
+    fprintf (stderr, "error reading in matrix data from FITS file %s (%d < %d - 2880)\n", filename, nbytes, Nbytes);
+    return (FALSE);
+  }
+  if (nbytes != Nbytes) {  /* this is a FITS error, but often the image is OK */
+    fprintf (stderr, "incomplete block in %s: (%d, %d)\n", filename, nbytes, Nbytes);
+    return (TRUE); 
+  }
+
+  return (TRUE);
+
+}
+
Index: /branches/libfits-1-8/Ohana/src/libfits/matrix/F_set_M_value.c
===================================================================
--- /branches/libfits-1-8/Ohana/src/libfits/matrix/F_set_M_value.c	(revision 11932)
+++ /branches/libfits-1-8/Ohana/src/libfits/matrix/F_set_M_value.c	(revision 11932)
@@ -0,0 +1,58 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+/****************** fits set matrix value ***********************************/
+void gfits_set_matrix_value (matrix, x, y, Value) 
+Matrix *matrix; 
+int x, y; 
+double Value;
+{
+
+  int pixel;
+  double value;
+
+  pixel = matrix[0].Naxis[0]*y + x;
+  value = (Value - matrix[0].bzero) / matrix[0].bscale;
+
+  if (matrix[0].unsign) {
+    switch (matrix[0].bitpix) {
+    case 8:
+      *((char  *) matrix[0].buffer + pixel) = value;
+      break;
+    case 16:
+      *((short *) matrix[0].buffer + pixel) = value;
+      break;
+    case 32:
+      *((int   *) matrix[0].buffer + pixel) = value;
+      break;
+    case -32:
+      *((float          *) matrix[0].buffer + pixel) = value;
+      break;
+    case -64:
+      *((double         *) matrix[0].buffer + pixel) = value;
+      break;
+    }
+  }
+  else {
+    switch (matrix[0].bitpix) {
+    case 8:
+      *((unsigned char  *) matrix[0].buffer + pixel) = value;
+      break;
+    case 16:
+      *((unsigned short *) matrix[0].buffer + pixel) = value;
+      break;
+    case 32:
+      *((unsigned int   *) matrix[0].buffer + pixel) = value;
+      break;
+    case -32:
+      *((float          *) matrix[0].buffer + pixel) = value;
+      break;
+    case -64:
+      *((double         *) matrix[0].buffer + pixel) = value;
+      break;
+    }
+  }
+
+}
+
+
Index: /branches/libfits-1-8/Ohana/src/libfits/matrix/F_write_M.c
===================================================================
--- /branches/libfits-1-8/Ohana/src/libfits/matrix/F_write_M.c	(revision 11932)
+++ /branches/libfits-1-8/Ohana/src/libfits/matrix/F_write_M.c	(revision 11932)
@@ -0,0 +1,142 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+/*********************** fits write matrix ***********************************/
+int gfits_write_matrix (char *filename, Matrix *matrix) {
+
+  FILE *f;
+  int status;
+
+  f = fopen (filename, "a");
+  if (f == NULL) return (FALSE);
+  
+  fseek (f, 0, SEEK_END);  /* write matrix to end of file! */
+
+  status = gfits_fwrite_matrix (f, matrix);
+  fclose (f);
+  return (status);
+}
+
+/*********************** fits write matrix ***********************************/
+int gfits_fwrite_matrix (FILE *f, Matrix *matrix) {
+
+  int i, status, nbytes, Nbytes;
+  unsigned char *byte0, *byte1, *byte2, *byte3, *byte4, *byte5, *byte6, *byte7, tmp;
+  int perpix;
+
+  status = TRUE;
+
+  /* this is a bit dangerous: we are not realloc'ing the matrix.
+     if the size is wrong, it probably should simply pad the fwrite statement.
+     better policy should be defined (ie, matrix.size always correct blocking?)
+ */
+
+  if (matrix[0].size % FT_RECORD_SIZE) 
+    nbytes = FT_RECORD_SIZE * ((int) (matrix[0].size / FT_RECORD_SIZE) + 1);
+  else 
+    nbytes = FT_RECORD_SIZE * ((int) (matrix[0].size / FT_RECORD_SIZE));
+
+  /* this is a bit cumbersome: swap all words, write out file, then swap back... */
+# ifdef BYTE_SWAP  
+  perpix = abs(matrix[0].bitpix) / 8;
+  if (perpix > 1) {
+    byte0 = (unsigned char *) matrix[0].buffer;
+    byte1 = (unsigned char *) matrix[0].buffer + 1;
+    byte2 = (unsigned char *) matrix[0].buffer + 2;
+    byte3 = (unsigned char *) matrix[0].buffer + 3;
+    byte4 = (unsigned char *) matrix[0].buffer + 4;
+    byte5 = (unsigned char *) matrix[0].buffer + 5;
+    byte6 = (unsigned char *) matrix[0].buffer + 6;
+    byte7 = (unsigned char *) matrix[0].buffer + 7;
+    if (perpix == 2) {
+      for (i = 0; i < nbytes; i+=2, byte0 += 2, byte1 += 2) {
+	tmp = *byte0;
+	*byte0 = *byte1;
+	*byte1 = tmp;
+      }
+    }
+    if (perpix == 4) {
+      for (i = 0; i < nbytes; i+=4, byte0 += 4, byte1 += 4, byte2 += 4, byte3 += 4) {
+	tmp = *byte0;
+	*byte0 = *byte3;
+	*byte3 = tmp;
+	tmp = *byte1;
+	*byte1 = *byte2;
+	*byte2 = tmp;
+      }
+    }
+    if (perpix == 8) {
+      for (i = 0; i < nbytes; i+=8, byte0 += 8, byte1 += 8, byte2 += 8, byte3 += 8, byte4 += 8, byte5 += 8, byte6 += 8, byte7 += 8) {
+	tmp = *byte0;
+	*byte0 = *byte7;
+	*byte7 = tmp;
+	tmp = *byte1;
+	*byte1 = *byte6;
+	*byte6 = tmp;
+	tmp = *byte1;
+	*byte2 = *byte5;
+	*byte5 = tmp;
+	tmp = *byte1;
+	*byte3 = *byte4;
+	*byte4 = tmp;
+      }
+    }
+  }
+# endif
+
+  Nbytes = fwrite (matrix[0].buffer, sizeof(char), nbytes, f);
+  if (Nbytes != nbytes) {
+    status = FALSE;
+  }
+
+# ifdef BYTE_SWAP  
+  perpix = abs(matrix[0].bitpix) / 8;
+  if (perpix > 1) {
+    byte0 = (unsigned char *) matrix[0].buffer;
+    byte1 = (unsigned char *) matrix[0].buffer + 1;
+    byte2 = (unsigned char *) matrix[0].buffer + 2;
+    byte3 = (unsigned char *) matrix[0].buffer + 3;
+    byte4 = (unsigned char *) matrix[0].buffer + 4;
+    byte5 = (unsigned char *) matrix[0].buffer + 5;
+    byte6 = (unsigned char *) matrix[0].buffer + 6;
+    byte7 = (unsigned char *) matrix[0].buffer + 7;
+    if (perpix == 2) {
+      for (i = 0; i < nbytes; i+=2, byte0 += 2, byte1 += 2) {
+	tmp = *byte0;
+	*byte0 = *byte1;
+	*byte1 = tmp;
+      }
+    }
+    if (perpix == 4) {
+      for (i = 0; i < nbytes; i+=4, byte0 += 4, byte1 += 4, byte2 += 4, byte3 += 4) {
+	tmp = *byte0;
+	*byte0 = *byte3;
+	*byte3 = tmp;
+	tmp = *byte1;
+	*byte1 = *byte2;
+	*byte2 = tmp;
+      }
+    }
+    if (perpix == 8) {
+      for (i = 0; i < nbytes; i+=8, byte0 += 8, byte1 += 8, byte2 += 8, byte3 += 8, byte4 += 8, byte5 += 8, byte6 += 8, byte7 += 8) {
+	tmp = *byte0;
+	*byte0 = *byte7;
+	*byte7 = tmp;
+	tmp = *byte1;
+	*byte1 = *byte6;
+	*byte6 = tmp;
+	tmp = *byte1;
+	*byte2 = *byte5;
+	*byte5 = tmp;
+	tmp = *byte1;
+	*byte3 = *byte4;
+	*byte4 = tmp;
+      }
+    }
+  }
+# endif
+
+  return (status);
+
+}
+
Index: /branches/libfits-1-8/Ohana/src/libfits/table/F_create_T.c
===================================================================
--- /branches/libfits-1-8/Ohana/src/libfits/table/F_create_T.c	(revision 11932)
+++ /branches/libfits-1-8/Ohana/src/libfits/table/F_create_T.c	(revision 11932)
@@ -0,0 +1,51 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+/*********************** fits create table *******************************/
+int gfits_create_table (Header *header, FTable *table) {
+
+  int Nbytes;
+  char type[80];
+
+  gfits_scan (header, "XTENSION", "%s", 1, type);
+
+  table[0].header = header;
+  
+  Nbytes = gfits_matrix_size (header);
+  ALLOCATE (table[0].buffer, char, MAX (Nbytes, 1));
+  if (!strcmp (type, "TABLE")) {
+    memset (table[0].buffer, ' ', Nbytes);
+  } else {
+    memset (table[0].buffer, 0, Nbytes);
+  }
+  table[0].size = Nbytes;
+  return (TRUE);
+
+}
+
+/* init table structure, allocate space for data array (min 1 byte for 0 length) */
+
+/*********************** fits create table *******************************/
+int gfits_create_vtable (Header *header, VTable *table, int Nrow) {
+
+  int i, Nx, Ny;
+  char type[80];
+
+  gfits_scan (header, "XTENSION", "%s", 1, type);
+
+  table[0].header = header;
+  Nx = table[0].header[0].Naxis[0];
+  Ny = table[0].header[0].Naxis[0];
+  table[0].size = gfits_matrix_size (header);
+  table[0].pad = table[0].size - Nx*Ny;
+ 
+  table[0].Nrow = Nrow;
+  ALLOCATE (table[0].buffer, char *, MAX (Nrow, 1));
+  ALLOCATE (table[0].row, int, MAX (Nrow, 1));
+  for (i = 0; i < Nrow; i++) {
+    ALLOCATE (table[0].buffer[i], char, Nx);
+  }
+  return (TRUE);
+}
+
+/* init table structure, allocate space for data array (min 1 byte for 0 length) */
Index: /branches/libfits-1-8/Ohana/src/libfits/table/F_create_TH.c
===================================================================
--- /branches/libfits-1-8/Ohana/src/libfits/table/F_create_TH.c	(revision 11932)
+++ /branches/libfits-1-8/Ohana/src/libfits/table/F_create_TH.c	(revision 11932)
@@ -0,0 +1,94 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+/* a basic table header (extension) is different from a primary header
+   in that it has the word XTENSION and a type for the first line,
+   instead of SIMPLE */
+
+/*********************** fits create Theader *********************************/
+int gfits_create_Theader (Header *header, char *type) {
+  
+  int i;
+  char axis[10];
+  
+  header[0].size = 2880;
+  ALLOCATE (header[0].buffer, char, 2880);
+  
+  for (i = 0; i < 2880; i++) 
+  header[0].buffer[i] = ' ';
+  strncpy (header[0].buffer, "END", 3);
+  
+  gfits_modify (header, "XTENSION", "%s", 1, type);
+  gfits_modify (header, "BITPIX", "%d", 1, header[0].bitpix);
+  gfits_modify (header, "NAXIS",  "%d", 1, header[0].Naxes);
+  
+  for (i = 0; i < header[0].Naxes; i++) {
+    sprintf (axis, "NAXIS%d", i + 1);
+    gfits_modify (header,  axis, "%d", 1, header[0].Naxis[i], 1);
+  }
+  
+  /* PCOUNT & GCOUNT are not implemented, but they are required to be here */
+  gfits_modify (header, "PCOUNT", "%d", 1, 0);
+  gfits_modify (header, "GCOUNT", "%d", 1, 1);
+  if (!strcmp (type, "IMAGE")) {
+    gfits_modify (header, "BSCALE", "%lf", 1, header[0].bscale);
+    gfits_modify (header, "BZERO",  "%lf", 1, header[0].bzero);
+  }
+
+  return (TRUE);
+}	
+
+/*********************** fits create table header *********************************/
+int gfits_create_table_header (Header *header, char *type, char *extname) {
+  
+  int i, valid;
+  char axis[10];
+
+  /* check valid table types */
+  valid = FALSE;
+  valid |= !strcmp (type, "TABLE");
+  valid |= !strcmp (type, "BINTABLE");
+  if (!valid) return (FALSE);
+
+  /* create empty header buffer */
+  header[0].size = 2880;
+  ALLOCATE (header[0].buffer, char, 2880);
+  
+  for (i = 0; i < 2880; i++) 
+  header[0].buffer[i] = ' ';
+  strncpy (header[0].buffer, "END", 3);
+
+  /* a table has BITPIX = 8, NAXIS = 2 */
+  header[0].simple = FALSE;
+  header[0].unsign = FALSE;
+  header[0].extend = FALSE;
+  header[0].bitpix = 8;
+  header[0].bscale = 1;
+  header[0].bzero  = 0;
+  header[0].Naxes  = 2;
+  for (i = 0; i < FT_MAX_NAXES; i++)
+    header[0].Naxis[i] = 0;
+  
+  /* required keywords */
+  gfits_modify (header, "XTENSION", "%s", 1, type);
+  gfits_modify (header, "BITPIX", "%d", 1, header[0].bitpix);
+  gfits_modify (header, "NAXIS",  "%d", 1, header[0].Naxes);
+  
+  for (i = 0; i < header[0].Naxes; i++) {
+    sprintf (axis, "NAXIS%d", i + 1);
+    gfits_modify (header,  axis, "%d", 1, header[0].Naxis[i], 1);
+  }
+  
+  /* PCOUNT & GCOUNT are not implemented, but they are required to be here */
+  gfits_modify (header, "PCOUNT", "%d", 1, 0);
+  gfits_modify (header, "GCOUNT", "%d", 1, 1);
+  if (!strcmp (type, "IMAGE")) {
+    gfits_modify (header, "BSCALE", "%lf", 1, header[0].bscale);
+    gfits_modify (header, "BZERO",  "%lf", 1, header[0].bzero);
+  }
+
+  gfits_modify (header, "TFIELDS", "%d", 1, 0);
+  gfits_modify (header, "EXTNAME", "%s", 1, extname);
+  
+  return (TRUE);
+}	
Index: /branches/libfits-1-8/Ohana/src/libfits/table/F_define_column.c
===================================================================
--- /branches/libfits-1-8/Ohana/src/libfits/table/F_define_column.c	(revision 11932)
+++ /branches/libfits-1-8/Ohana/src/libfits/table/F_define_column.c	(revision 11932)
@@ -0,0 +1,70 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+/***********************/
+int gfits_define_bintable_column (Header *header, char *format, char *label, char *comment, char *unit, double bscale, double bzero) {
+
+  int Nfields, Nbytes, Nval, Naxis1;
+  char type[16], field[16];
+  
+  if (!gfits_bintable_format (format, type, &Nval, &Nbytes)) return (FALSE);
+  
+  Nfields = 0;
+  gfits_scan (header, "TFIELDS", "%d", 1, &Nfields);
+  gfits_scan (header, "NAXIS1",  "%d", 1, &Naxis1);
+  Nfields ++;
+  Naxis1 += Nbytes*Nval;
+
+  sprintf (field, "TTYPE%d", Nfields);
+  gfits_modify (header, field, "%s", 1, label);
+  gfits_modify (header, field, "%C", 1, comment);
+  sprintf (field, "TUNIT%d", Nfields);
+  gfits_modify (header, field, "%s", 1, unit);
+  sprintf (field, "TFORM%d", Nfields);
+  gfits_modify (header, field, "%s", 1, format);
+  sprintf (field, "TSCAL%d", Nfields);
+  gfits_modify (header, field, "%lf", 1, bscale);
+  sprintf (field, "TZERO%d", Nfields);
+  gfits_modify (header, field, "%lf", 1, bzero);
+
+  /* update TFIELDS & NAXIS1 */
+  gfits_modify (header, "TFIELDS", "%d", 1, Nfields);
+  gfits_modify (header, "NAXIS1",  "%d", 1, Naxis1);
+  header[0].Naxis[0] = Naxis1;
+
+  return (TRUE);
+}
+
+/***********************/
+int gfits_define_table_column (Header *header, char *format, char *label, char *comment, char *unit) {
+
+  int Nstart, Nfields, Nbytes, Nval, Naxis1;
+  char type[16], field[16], cformat[16];
+
+  strcpy (cformat, format);
+  if (!gfits_table_format (cformat, type, &Nval, &Nbytes)) return (FALSE);
+
+  Nfields = 0;
+  gfits_scan (header, "TFIELDS", "%d", 1, &Nfields);
+  gfits_scan (header, "NAXIS1",  "%d", 1, &Naxis1);
+  Nstart = Naxis1 + 1;
+  Nfields ++;
+  Naxis1 += Nbytes*Nval;
+
+  sprintf (field, "TTYPE%d", Nfields);
+  gfits_modify (header, field, "%s", 1, label);
+  gfits_modify (header, field, "%C", 1, comment);
+  sprintf (field, "TUNIT%d", Nfields);
+  gfits_modify (header, field, "%s", 1, unit);
+  sprintf (field, "TFORM%d", Nfields);
+  gfits_modify (header, field, "%s", 1, format);
+
+  sprintf (field, "TBCOL%d", Nfields);
+  gfits_modify (header, field, "%d", 1, Nstart);
+
+  gfits_modify (header, "TFIELDS", "%d", 1, Nfields);
+  gfits_modify (header, "NAXIS1",  "%d", 1, Naxis1);
+  header[0].Naxis[0] = Naxis1;
+
+  return (TRUE);
+}
Index: /branches/libfits-1-8/Ohana/src/libfits/table/F_free_T.c
===================================================================
--- /branches/libfits-1-8/Ohana/src/libfits/table/F_free_T.c	(revision 11932)
+++ /branches/libfits-1-8/Ohana/src/libfits/table/F_free_T.c	(revision 11932)
@@ -0,0 +1,28 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+int gfits_free_table (FTable *table) {
+  
+  if (table[0].buffer == (char *) NULL) return (TRUE);
+  free (table[0].buffer);
+  table[0].buffer = (char *) NULL;
+  return (TRUE);
+}
+
+int gfits_free_vtable (VTable *table) {
+  
+  int i;
+
+  if (table[0].buffer == (char **) NULL) return (TRUE);
+
+  for (i = 0; i < table[0].Nrow; i++) {
+    free (table[0].buffer[i]);
+  }
+  free (table[0].buffer);
+  free (table[0].row);
+
+  table[0].buffer = NULL;
+  table[0].row    = NULL;
+  return (TRUE);
+}
+
Index: /branches/libfits-1-8/Ohana/src/libfits/table/F_get_T_column.c
===================================================================
--- /branches/libfits-1-8/Ohana/src/libfits/table/F_get_T_column.c	(revision 11932)
+++ /branches/libfits-1-8/Ohana/src/libfits/table/F_get_T_column.c	(revision 11932)
@@ -0,0 +1,61 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+/*********************** fits get table column *****************************/
+void gfits_get_table_column (table, X, mode, values) 
+Table *table; 
+int X; 
+char *mode, **values;
+{
+  
+  char Tform[100], field[100], tmp[100];
+  int  start, Nchar, i, N;
+  
+  int    *Ivalues;
+  long   *Lvalues;
+  short  *Svalues;
+  float  *Fvalues;
+  double *Dvalues;
+  char  **Cvalues;
+  
+  /* no error checking, all sorts of problems! */
+  /* should I count fields from 0 or from 1? */
+  
+  sprintf (field, "TBCOL%d\0", X);
+  gfits_scan (&table[0].header, field, "%d", &start, 1);
+  start --;
+  sprintf (field, "TFORM%d\0", X);
+  gfits_scan (&table[0].header, field, "%s", Tform, 1);
+  Nchar = atof (&Tform[1]);
+  
+  if (!strcmp (mode, "%d")) {
+    ALLOCATE (Ivalues, int, table[0].Naxis[1]);
+    for (i = 0; i < table[0].Naxis[1]; i++) {
+      strncpy (tmp, &table[0].buffer[i*table[0].Naxis[0] + start], Nchar);
+      tmp[Nchar] = 0;
+      Ivalues[i] = atof (tmp);
+    }
+    values[0] = (char *) Ivalues;
+  }
+  if (!strcmp (mode, "%lf")) {
+    ALLOCATE (Dvalues, double, table[0].Naxis[1]);
+    for (i = 0; i < table[0].Naxis[1]; i++) {
+      strncpy (tmp, &table[0].buffer[i*table[0].Naxis[0] + start], Nchar);
+      tmp[Nchar] = 0;
+      Dvalues[i] = atof (tmp);
+    }
+    values[0] = (char *) Dvalues;
+  }
+  if ((mode[0] == '%') && (mode[strlen(mode) - 1] == 'c')) {
+    mode[strlen(mode) - 1] = 0;
+    N = atof(&mode[1]);
+    ALLOCATE (Cvalues, char *, table[0].Naxis[1]);
+    for (i = 0; i < table[0].Naxis[1]; i++) {
+      ALLOCATE (Cvalues[i], char, N + 1);
+      strncpy (Cvalues[i], &table[0].buffer[i*table[0].Naxis[0] + start], N);
+      Cvalues[i][N] = 0;
+    }
+    values[0] = (char *) Cvalues;
+  }
+
+}
Index: /branches/libfits-1-8/Ohana/src/libfits/table/F_get_T_value.c
===================================================================
--- /branches/libfits-1-8/Ohana/src/libfits/table/F_get_T_value.c	(revision 11932)
+++ /branches/libfits-1-8/Ohana/src/libfits/table/F_get_T_value.c	(revision 11932)
@@ -0,0 +1,41 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+/*********************** fits get table value ********************************/
+  
+void gfits_get_table_value (table, X, Y, mode, value)
+Table *table; 
+int X, Y; 
+char *mode, *value;
+{
+  
+  char Tform[100], field[100];
+  int  start, Nchar, byte;
+  char tmp[1000];
+  
+  /* no error checking, all sorts of problems! */
+  
+  sprintf (field, "TBCOL%d\0", X);
+  gfits_scan (&table[0].header, field, "%d", &start, 1);
+  start --;
+  
+  sprintf (field, "TFORM%d\0", X);
+  gfits_scan (&table[0].header, field, "%s", Tform, 1);
+  Nchar = atof (&Tform[1]);
+  
+  byte = Y*table[0].Naxis[0] + start;
+  strncpy (tmp, &table[0].buffer[byte], Nchar);
+  tmp[Nchar] = 0;
+
+  if (!strcmp (mode, "%d"))  *(int      *) value = (int)      atof (tmp);
+  if (!strcmp (mode, "%u"))  *(unsigned *) value = (unsigned) atof (tmp);
+  if (!strcmp (mode, "%ld")) *(long     *) value = (long)     atof (tmp);
+  if (!strcmp (mode, "%hd")) *(short    *) value = (short)    atof (tmp);
+  if (!strcmp (mode, "%f"))  *(float    *) value = (float)    atof (tmp);
+  if (!strcmp (mode, "%lf")) *(double   *) value = (double)   atof (tmp);
+
+  if (!strcmp (mode, "%s")) 
+    strcpy (value, tmp);
+
+}
+
Index: /branches/libfits-1-8/Ohana/src/libfits/table/F_get_column.c
===================================================================
--- /branches/libfits-1-8/Ohana/src/libfits/table/F_get_column.c	(revision 11932)
+++ /branches/libfits-1-8/Ohana/src/libfits/table/F_get_column.c	(revision 11932)
@@ -0,0 +1,274 @@
+# include <ohana.h>
+# include <gfitsio.h>
+# define SWAP_BYTE \
+  tmp = Pin[0]; Pin[0] = Pin[1]; Pin[1] = tmp;
+# define SWAP_WORD \
+  tmp = Pin[0]; Pin[0] = Pin[3]; Pin[3] = tmp; \
+  tmp = Pin[1]; Pin[1] = Pin[2]; Pin[2] = tmp;
+# define SWAP_DBLE \
+  tmp = Pin[0]; Pin[0] = Pin[7]; Pin[7] = tmp; \
+  tmp = Pin[1]; Pin[1] = Pin[6]; Pin[6] = tmp; \
+  tmp = Pin[2]; Pin[2] = Pin[5]; Pin[5] = tmp; \
+  tmp = Pin[3]; Pin[3] = Pin[4]; Pin[4] = tmp;
+
+/***********************/
+int gfits_get_bintable_column_type (Header *header, char *label, char *type, int *Nval) {
+
+  int i, N, Nfields, Nbytes;
+  char tlabel[80], field[80], format[80];
+
+  if (label == (char *) NULL) return (FALSE);
+  if (label[0] == 0) return (FALSE);
+
+  /* find label in header */
+  tlabel[0] = 0;
+  gfits_scan (header, "TFIELDS", "%d", 1, &Nfields);
+  for (i = 1; strcmp (label, tlabel) && (i < Nfields + 1); i++) {
+    sprintf (field, "TTYPE%d", i);
+    gfits_scan (header, field, "%s", 1, tlabel);
+  }
+  if (strcmp (label, tlabel)) return (FALSE);
+  N = i - 1;
+
+  sprintf (field, "TFORM%d", N);
+  gfits_scan (header, field, "%s", 1, format);
+
+  if (!gfits_bintable_format (format, type, Nval, &Nbytes)) return (FALSE);
+  return (TRUE);
+}
+
+/***********************/
+int gfits_get_bintable_column (Header *header, FTable *table, char *label, void **data) {
+
+  int i, N, Nfields, Nval, Nbytes, Nx, Ny, Nstart, Nv, Nb;
+  char tlabel[80], field[80], format[80], type[16], tmpline[16];
+  char *Pin, *Pout, *array, tmp;
+  double Bscale, Bzero;
+  int I;
+
+  if (label == (char *) NULL) return (FALSE);
+  if (label[0] == 0) return (FALSE);
+
+  /* find label in header */
+  tlabel[0] = 0;
+  gfits_scan (header, "TFIELDS", "%d", 1, &Nfields);
+  for (i = 1; strcmp (label, tlabel) && (i < Nfields + 1); i++) {
+    sprintf (field, "TTYPE%d", i);
+    gfits_scan (header, field, "%s", 1, tlabel);
+  }
+  if (strcmp (label, tlabel)) return (FALSE);
+  N = i - 1;
+
+  Bscale = 1; 
+  Bzero  = 0;
+
+  /* interpret format */
+  sprintf (field, "TSCAL%d", Nfields);
+  gfits_scan (header, field, "%lf", 1, &Bscale);
+  sprintf (field, "TZERO%d", Nfields);
+  gfits_scan (header, field, "%lf", 1, &Bzero);
+  sprintf (field, "TFORM%d", N);
+  gfits_scan (header, field, "%s", 1, format);
+
+  if (!gfits_bintable_format (format, type, &Nval, &Nbytes)) return (FALSE);
+  
+  /* check existing table dimensions */
+  gfits_scan (header, "NAXIS1",  "%d", 1, &Nx);
+  gfits_scan (header, "NAXIS2",  "%d", 1, &Ny);
+
+  /* scan columns to find insert point */
+  Nstart = 0;
+  for (i = 1; i < N; i++) {
+    sprintf (field, "TFORM%d", i);
+    gfits_scan (header, field, "%s", 1, format);
+    gfits_bintable_format (format, tmpline, &Nv, &Nb);
+    Nstart += Nv*Nb;
+  }
+
+  /* extract bytes from table into temporary array */
+  ALLOCATE (array, char, Nbytes*Nval*Ny);
+  Pin  = table[0].buffer + Nstart;
+  Pout = array;
+  for (i = 0; i < Ny; i++, Pin += Nx, Pout += Nval*Nbytes) {
+    memcpy (Pout, Pin, Nval*Nbytes);
+  }
+
+  /* convert data in-situ with correct type, byte swap and Bzero/Bscale */
+  Pin  = array;
+  Pout = array;
+  if (!strcmp (type, "char")) {
+    for (i = 0; i < Nval*Ny; i++, Pin+=Nbytes, Pout+=Nbytes) {
+      *(char *)Pout = *(char *)Pin*Bscale + Bzero;
+    }
+  }
+  if (!strcmp (type, "short")) {
+    for (i = 0; i < Nval*Ny; i++, Pin+=Nbytes, Pout+=Nbytes) {
+# ifdef BYTE_SWAP
+      I = i*Nbytes;
+      SWAP_BYTE;
+# endif
+      *(short *)Pout = *(short *)Pin*Bscale + Bzero;
+    }  
+  }
+  if (!strcmp (type, "int")) {
+    for (i = 0; i < Nval*Ny; i++, Pin+=Nbytes, Pout+=Nbytes) {
+# ifdef BYTE_SWAP
+      I = i*Nbytes;
+      SWAP_WORD;
+# endif
+      *(int *)Pout = *(int *)Pin*Bscale + Bzero;
+    }
+  }
+  if (!strcmp (type, "float")) {
+    for (i = 0; i < Nval*Ny; i++, Pin+=Nbytes, Pout+=Nbytes) {
+# ifdef BYTE_SWAP
+      I = i*Nbytes;
+      SWAP_WORD;
+# endif
+      *(float *)Pout = *(float *)Pin*Bscale + Bzero;
+    }
+  }
+  if (!strcmp (type, "double")) {
+    for (i = 0; i < Nval*Ny; i++, Pin+=Nbytes, Pout+=Nbytes) {
+# ifdef BYTE_SWAP
+      I = i*Nbytes;
+      SWAP_DBLE;
+# endif
+      *(double *)Pout = *(double *)Pin*Bscale + Bzero;
+    }
+  }
+
+  *data = array;
+  return (TRUE);
+}
+
+/* 
+   valid BINTABLE column formats:
+   L - logical
+   X - bit
+   I - 16 bit int
+   J - 32 bit int
+   A - char
+   E - float 
+   D - double
+   B - unsigned bytes
+   C - complex float
+   M - complex double
+   P - var lenght array descrpt (64 bit)
+   
+   all can be preceeded by integer N which specified number
+   of entries in array
+   
+*/
+
+/***********************/
+int gfits_get_table_column_type (Header *header, char *label, char *type) {
+
+  int i, N, Nfields, Nval, Nbytes;
+  char tlabel[80], field[80], format[80];
+
+  if (label == (char *) NULL) return (FALSE);
+  if (label[0] == 0) return (FALSE);
+
+  /* find label in header */
+  tlabel[0] = 0;
+  gfits_scan (header, "TFIELDS", "%d", 1, &Nfields);
+  for (i = 1; strcmp (label, tlabel) && (i < Nfields + 1); i++) {
+    sprintf (field, "TTYPE%d", i);
+    gfits_scan (header, field, "%s", 1, tlabel);
+  }
+  if (strcmp (label, tlabel)) return (FALSE);
+  N = i - 1;
+
+  /* interpret format */
+  sprintf (field, "TFORM%d", N);
+  gfits_scan (header, field, "%s", 1, format);
+
+  if (!gfits_table_format (format, type, &Nval, &Nbytes)) return (FALSE);
+  return (TRUE);
+}
+
+/***********************/
+int gfits_get_table_column (Header *header, FTable *table, char *label, void **data) {
+
+  int i, N, Nfields, Nval, Nbytes, Nx, Ny, Nstart, Nv, Nb;
+  char tlabel[80], field[80], format[80], cformat[80], type[16], tmp[16];
+  char *array, *Pin, *Pout, *line;
+
+  if (label == (char *) NULL) return (FALSE);
+  if (label[0] == 0) return (FALSE);
+  array = NULL;
+
+  /* find label in header */
+  tlabel[0] = 0;
+  gfits_scan (header, "TFIELDS", "%d", 1, &Nfields);
+  for (i = 1; strcmp (label, tlabel) && (i < Nfields + 1); i++) {
+    sprintf (field, "TTYPE%d", i);
+    gfits_scan (header, field, "%s", 1, tlabel);
+  }
+  if (strcmp (label, tlabel)) return (FALSE);
+  N = i - 1;
+
+  /* interpret format */
+  sprintf (field, "TFORM%d", N);
+  gfits_scan (header, field, "%s", 1, format);
+
+  if (!gfits_table_format (format, type, &Nval, &Nbytes)) return (FALSE);
+  strcpy (cformat, format);
+  
+  /* check existing table dimensions */
+  gfits_scan (header, "NAXIS1",  "%d", 1, &Nx);
+  gfits_scan (header, "NAXIS2",  "%d", 1, &Ny);
+
+  /* scan columns to find insert point */
+  Nstart = 0;
+  for (i = 1; i < N; i++) {
+    sprintf (field, "TFORM%d", i);
+    gfits_scan (header, field, "%s", 1, format);
+    gfits_table_format (format, tmp, &Nv, &Nb);
+    Nstart += Nv*Nb;
+  }
+
+  /* allocate temporary line, init pointers */
+  ALLOCATE (line, char, Nval+1);
+  bzero (line, Nval+1);
+  Pin  = table[0].buffer + Nstart;
+
+  /* allocate output array, copy/scan line as needed */
+  if (!strcmp (type, "char")) {
+    ALLOCATE (array, char, Ny*Nval);
+    Pout = array;
+    for (i = 0; i < Ny; i++, Pin+=Nx, Pout+=Nval*Nbytes) {
+      memcpy (Pout, Pin, Nval*Nbytes);
+    }
+  }
+  if (!strcmp (type, "int")) {
+    ALLOCATE (array, char, Ny*4);
+    Pout = array;
+    for (i = 0; i < Ny; i++, Pin+=Nx, Pout+=4) {
+      memcpy (line, Pin, Nval*Nbytes);
+      sscanf (line, "%d", (int *)Pout);
+    }
+  }
+  if (!strcmp (type, "float")) {
+    ALLOCATE (array, char, Ny*4);
+    Pout = array;
+    for (i = 0; i < Ny; i++, Pin+=Nx, Pout+=4) {
+      memcpy (line, Pin, Nval*Nbytes);
+      sscanf (line, "%f", (float *)Pout);
+    }
+  }
+  *data = array;
+  free (line);
+
+  return (TRUE);
+}
+
+/*
+  valid TABLE column formats:
+  FN.N  - floating point
+  INN   - integer
+  ANN   - NN char string
+  
+*/
+
Index: /branches/libfits-1-8/Ohana/src/libfits/table/F_read_T.c
===================================================================
--- /branches/libfits-1-8/Ohana/src/libfits/table/F_read_T.c	(revision 11932)
+++ /branches/libfits-1-8/Ohana/src/libfits/table/F_read_T.c	(revision 11932)
@@ -0,0 +1,235 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+/*********************** fits read table ***********************************/
+int gfits_read_ftable (char *filename, FTable *table, char *extname) {
+
+  int status;
+  FILE *f;
+
+  f = fopen (filename, "r");
+  if (f == NULL) return (FALSE);
+
+  status = gfits_fread_ftable (f, table, extname);
+  fclose (f);
+  return (status);
+}	
+
+/*********************** fits read table ***********************************/
+int gfits_fread_ftable (FILE *f, FTable *table, char *extname) {
+
+  int j, found, Nbytes;
+  Header *header;
+  char tname[80];
+
+  header = table[0].header;
+  fseek (f, 0, SEEK_SET);
+
+  found = FALSE;
+  for (j = -1; !found; j++) {
+    /* load data for this header */
+    if (!gfits_load_header (f, header)) return (FALSE);
+
+    /* check if this is the correct extension or not */
+    bzero (tname, 80);
+    gfits_scan (header, "EXTNAME", "%s", 1, tname);
+    if (!strcmp (tname, extname)) {
+      if (gfits_fread_ftable_data (f, table)) return (TRUE);
+      gfits_free_header (header);
+      return (FALSE);
+    }
+
+    /* skip to next header */
+    Nbytes = gfits_matrix_size (header);
+    fseek (f, Nbytes, SEEK_CUR);
+    gfits_free_header (header);
+  }
+  return (TRUE);
+}	
+
+/*********************** fits read ftable data ***********************************/
+int gfits_fread_ftable_data (FILE *f, FTable *table) {
+
+  int Nbytes, Nread;
+
+  /* find buffer size */
+  Nbytes = gfits_matrix_size (table[0].header);
+  ALLOCATE (table[0].buffer, char, Nbytes);
+
+  Nread = fread (table[0].buffer, sizeof (char), Nbytes, f);
+  if (Nread != Nbytes) {
+    gfits_free_table  (table);
+    return (FALSE);
+  }
+  table[0].size = Nbytes;
+  return (TRUE);
+}	
+
+/*********************** fits read ftable data ***********************************/
+int gfits_fread_vtable_range (FILE *f, VTable *table, int start, int Nrows) {
+
+  int i, Nbytes, Nread, Nskip, Nx, Ny;
+  char *buffer;
+
+  /* find buffer size */
+  Nx = table[0].header[0].Naxis[0];
+  Ny = table[0].header[0].Naxis[1];
+  table[0].size = gfits_matrix_size (table[0].header);
+  table[0].pad = table[0].size - Nx*Ny;
+
+  if (start < 0) return (FALSE);
+  if (start + Nrows >= Ny) return (FALSE);
+  
+  Nskip = start * Nx;
+  Nbytes = Nrows * Nx;
+  ALLOCATE (buffer, char, MAX (Nbytes, 1));
+
+  fseek (f, Nskip, SEEK_CUR);
+  Nread = fread (buffer, sizeof (char), Nbytes, f);
+  if (Nread != Nbytes) {
+    free (buffer);
+    return (FALSE);
+  }
+
+  ALLOCATE (table[0].row, int, MAX (Nrows, 1));
+  ALLOCATE (table[0].buffer, char *, MAX (Nrows, 1));
+  for (i = 0; i < Nrows; i++) {
+    ALLOCATE (table[0].buffer[i], char, MAX (Nx, 1));
+    memcpy (table[0].buffer[i], &buffer[i*Nx], Nx);
+    table[0].row[i] = start + i;
+  }
+  free (buffer);
+
+  return (TRUE);
+}	
+
+/*********************** fits read virtual table ***********************************/
+int gfits_fread_vtable (FILE *f, VTable *table, char *extname, int Nrow, int *row) {
+
+  int i, j, Nbytes, Nread;
+  int start, Nx, Ny, offset;
+  Header *header;
+  char tname[80];
+
+  header = table[0].header;
+  fseek (f, 0, SEEK_SET);
+
+  for (j = -1; TRUE; j++) {
+    /* load data for this header */
+    if (!gfits_load_header (f, header)) return (FALSE);
+
+    /* find buffer size */
+    Nbytes = gfits_matrix_size (header);
+
+    /* check if this is the correct extension or not */
+    bzero (tname, 80);
+    gfits_scan (header, "EXTNAME", "%s", 1, tname);
+    if (strcmp (tname, extname)) {
+      /* skip to next header */
+      fseek (f, Nbytes, SEEK_CUR);
+      gfits_free_header (header);
+      continue;
+    }
+
+    /* file pointer is at beginning of desired table data */
+    start = ftell (f);
+    gfits_scan (header, "NAXIS1", "%d", 1, &Nx);
+    gfits_scan (header, "NAXIS2", "%d", 1, &Ny);
+    for (i = 0; i < Nrow; i++) {
+      if (row[i] > Ny) { return (FALSE); }
+    }
+
+    ALLOCATE (table[0].buffer, char *, MAX (1, Nrow));
+    for (i = 0; i < Nrow; i++) {
+      ALLOCATE (table[0].buffer[i], char, MAX (1, Nx));
+      offset = start + Nx*row[i];
+      fseek (f, offset, SEEK_SET);
+      Nread = fread (table[0].buffer[i], sizeof (char), Nx, f);
+      if (Nread != Nx) { return (FALSE); }
+    }
+
+    table[0].Nrow  = Nrow;
+    ALLOCATE (table[0].row, int, MAX (1, Nrow));    
+    for (i = 0; i < Nrow; i++) table[0].row[i] = row[i];
+    table[0].size   = gfits_matrix_size (table[0].header);
+    table[0].pad    = table[0].size - Nx*Ny;
+    return (TRUE);
+  }
+}	
+
+# if (0)
+/*********************** fits read table ***********************************/
+/* a poor function: read only the first table, regardless of name */
+/* keep until we are sure ohana code does not use it  */
+int gfits_read_table (char *filename, FTable *table) {
+
+  FILE *f;
+  Header header;
+  int status, i, nbytes, Nbytes, matrix_size;
+
+  if (!gfits_read_header (filename, &header)) {
+    fprintf (stderr, "error reading header of FITS file %s\n", filename);
+    return (FALSE);
+  }
+
+  if (!gfits_read_Theader (filename, &table[0].header)) {
+    fprintf (stderr, "error reading Theader of FITS file %s\n", filename);
+    return (FALSE);
+  }
+
+  if ((f = fopen (filename, "r")) == NULL) {
+    gfits_free_header (&header);
+    gfits_free_header (&table[0].header);
+    return (FALSE);
+  }
+
+  matrix_size = gfits_matrix_size (&header);
+
+  Nbytes = header.size + matrix_size + table[0].header.size;
+  fseek (f, Nbytes, 0);
+  gfits_free_header (&header);
+ 
+  gfits_scan (&table[0].header, "TFIELDS", "%d", 1, &table[0].Nfields);
+
+  /* place the field sizes in the structure? */
+  table[0].bitpix = table[0].header.bitpix;
+  table[0].Naxes  = table[0].header.Naxes;
+  for (i = 0; i < FT_MAX_NAXES; i++)
+    table[0].Naxis[i] = table[0].header.Naxis[i];
+
+  Nbytes = gfits_matrix_size (&table[0].header);
+  ALLOCATE (table[0].buffer, char, Nbytes);
+  nbytes = fread (table[0].buffer, sizeof(char), Nbytes, f);
+  if (nbytes != Nbytes) {
+    fprintf (stderr, "error reading in table data from FITS file %s\n", filename);
+    fclose (f);
+    return (FALSE);
+  }
+  table[0].size = Nbytes;
+  fclose (f);
+  return (TRUE);
+}
+# endif
+
+
+int gfits_fread_header_extname (FILE *f, Header *header, char *extname) {
+
+  int Nbytes;
+  char current[80];
+
+  fseek (f, 0, SEEK_SET);
+  gfits_fread_header (f, header);
+
+  if (!strcasecmp (extname, "PHU")) return (TRUE);
+
+  Nbytes = gfits_matrix_size (header);
+  fseek (f, Nbytes, SEEK_CUR);
+
+  while (gfits_fread_header (f, header)) {
+    gfits_scan (header, "EXTNAME", "%s", 1, current);
+    if (!strcmp (current, extname)) return (TRUE);
+    Nbytes = gfits_matrix_size (header);
+    fseek (f, Nbytes, SEEK_CUR);
+  }
+  return (FALSE);
+}
Index: /branches/libfits-1-8/Ohana/src/libfits/table/F_read_TH.c
===================================================================
--- /branches/libfits-1-8/Ohana/src/libfits/table/F_read_TH.c	(revision 11932)
+++ /branches/libfits-1-8/Ohana/src/libfits/table/F_read_TH.c	(revision 11932)
@@ -0,0 +1,87 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+/*********************** fits read Theader ***********************************/
+int gfits_read_Theader (char *filename, Header *Theader) {
+  
+  FILE *f;
+  Header header;
+  int status, Nbytes;
+  
+  status = gfits_read_header (filename, &header);
+  if (!status) {
+    fprintf (stderr, "error reading header of FITS file %s\n", filename);
+    return (FALSE);
+  }
+
+  f = fopen (filename, "r");
+  if (f == NULL) {
+    Theader[0].buffer = NULL;
+    gfits_free_header (&header);
+    return (FALSE);
+  }
+
+  Nbytes = gfits_matrix_size (&header);
+  fseek (f, Nbytes, SEEK_SET);
+  gfits_free_header (&header);
+
+  status = gfits_load_Theader (f, Theader);
+  fclose (f);
+  return (status);
+}	
+
+/* load table from STREAM positioned at beginning of table header */
+/*********************** fits load Theader ***********************************/
+int gfits_load_Theader (FILE *f, Header *Theader) {
+  
+  char *p;
+  int i, done, status, Nbytes;
+  
+  Theader[0].size = 0;
+  done = FALSE;
+  ALLOCATE (Theader[0].buffer, char, 1);
+
+  for (i = 0; !done; i++) {
+    REALLOCATE (Theader[0].buffer, char, (i + 1)*FT_RECORD_SIZE);
+    Nbytes = fread (&Theader[0].buffer[i*FT_RECORD_SIZE], 
+		    sizeof(char), FT_RECORD_SIZE, f);
+    Theader[0].size += Nbytes;
+    if (Nbytes != FT_RECORD_SIZE) 
+      done = TRUE;
+    p = gfits_header_field (Theader, "END", 1);
+    if (p != NULL)
+      done = TRUE;
+  }
+
+  Theader[0].bscale = 0;
+  Theader[0].bzero  = 0;
+  for (i = 0; i < FT_MAX_NAXES; i++)
+    Theader[0].Naxis[i] = 0;
+
+  status = TRUE;
+  status &= gfits_scan (Theader,  "BITPIX", "%d", 1, &Theader[0].bitpix);
+  status &= gfits_scan (Theader,  "NAXIS",  "%d", 1, &Theader[0].Naxes);
+  if (!status) return (FALSE);
+				                           
+  gfits_scan (Theader,  "NAXIS1", "%d", 1, &Theader[0].Naxis[0]);
+  gfits_scan (Theader,  "NAXIS2", "%d", 1, &Theader[0].Naxis[1]);
+  gfits_scan (Theader,  "NAXIS3", "%d", 1, &Theader[0].Naxis[2]);
+  gfits_scan (Theader,  "NAXIS4", "%d", 1, &Theader[0].Naxis[3]);
+  gfits_scan (Theader,  "NAXIS5", "%d", 1, &Theader[0].Naxis[4]);
+  gfits_scan (Theader,  "NAXIS6", "%d", 1, &Theader[0].Naxis[5]);
+  gfits_scan (Theader,  "NAXIS7", "%d", 1, &Theader[0].Naxis[6]);
+  gfits_scan (Theader,  "NAXIS8", "%d", 1, &Theader[0].Naxis[7]);
+  gfits_scan (Theader,  "NAXIS9", "%d", 1, &Theader[0].Naxis[8]);
+  gfits_scan (Theader, "NAXIS10", "%d", 1, &Theader[0].Naxis[9]);
+
+  return (TRUE);
+}	
+
+/*********************** fits fread Theader ***********************************/
+int gfits_fread_Theader (FILE *f, Header *Theader) {
+  
+  int status;
+  
+  status = gfits_load_Theader (f, Theader);
+  return (status);
+}
Index: /branches/libfits-1-8/Ohana/src/libfits/table/F_set_column.c
===================================================================
--- /branches/libfits-1-8/Ohana/src/libfits/table/F_set_column.c	(revision 11932)
+++ /branches/libfits-1-8/Ohana/src/libfits/table/F_set_column.c	(revision 11932)
@@ -0,0 +1,253 @@
+# include <ohana.h>
+# include <gfitsio.h>
+# define SWAP_BYTE \
+  tmp = Pout[0]; Pout[0] = Pout[1]; Pout[1] = tmp;
+# define SWAP_WORD \
+  tmp = Pout[0]; Pout[0] = Pout[3]; Pout[3] = tmp; \
+  tmp = Pout[1]; Pout[1] = Pout[2]; Pout[2] = tmp;
+# define SWAP_DBLE \
+  tmp = Pout[0]; Pout[0] = Pout[7]; Pout[7] = tmp; \
+  tmp = Pout[1]; Pout[1] = Pout[6]; Pout[6] = tmp; \
+  tmp = Pout[2]; Pout[2] = Pout[5]; Pout[5] = tmp; \
+  tmp = Pout[3]; Pout[3] = Pout[4]; Pout[4] = tmp;
+
+/***********************/
+int gfits_set_bintable_column (Header *header, FTable *table, char *label, void *data, int Nrow) {
+
+  int i, N, Nfields, Nval, Nbytes, Nx, Ny, nbytes, Nstart, Nv, Nb;
+  char tlabel[80], field[80], format[80], type[16], tmpline[16];
+  char *Pin, *Pout, *array, tmp;
+  double Bscale, Bzero;
+  int I;
+
+  if (label == (char *) NULL) return (FALSE);
+  if (label[0] == 0) return (FALSE);
+
+  /* find label in header */
+  tlabel[0] = 0;
+  gfits_scan (header, "TFIELDS", "%d", 1, &Nfields);
+  for (i = 1; strcmp (label, tlabel) && (i < Nfields + 1); i++) {
+    sprintf (field, "TTYPE%d", i);
+    gfits_scan (header, field, "%s", 1, tlabel);
+  }
+  if (strcmp (label, tlabel)) return (FALSE);
+  N = i - 1;
+
+  /* interpret format */
+  sprintf (field, "TSCAL%d", N);
+  gfits_scan (header, field, "%lf", 1, &Bscale);
+  sprintf (field, "TZERO%d", N);
+  gfits_scan (header, field, "%lf", 1, &Bzero);
+  sprintf (field, "TFORM%d", N);
+  gfits_scan (header, field, "%s", 1, format);
+
+  if (!gfits_bintable_format (format, type, &Nval, &Nbytes)) return (FALSE);
+  
+  /* check existing table dimensions */
+  gfits_scan (header, "NAXIS1",  "%d", 1, &Nx);
+  gfits_scan (header, "NAXIS2",  "%d", 1, &Ny);
+  if (Ny == 0) { 
+    Ny = Nrow;
+    header[0].Naxis[1] = Ny;
+    gfits_modify (header, "NAXIS2",  "%d", 1, Ny);
+
+    nbytes = gfits_matrix_size (header);
+    REALLOCATE (table[0].buffer, char, MAX (nbytes, 1));
+    bzero (table[0].buffer, nbytes);
+    table[0].size = nbytes;
+  }
+  if (Ny != Nrow) return (FALSE);
+
+  /* scan columns to find insert point */
+  Nstart = 0;
+  for (i = 1; i < N; i++) {
+    sprintf (field, "TFORM%d", i);
+    gfits_scan (header, field, "%s", 1, format);
+    gfits_bintable_format (format, tmpline, &Nv, &Nb);
+    Nstart += Nv*Nb;
+  }
+
+  /* make duplicate of data with correct type
+     byte swap and Bzero/Bscale */
+  ALLOCATE (array, char, Nbytes*Nval*Nrow);
+  Pin = data;
+  Pout = array;
+  if (!strcmp (type, "char")) {
+    for (i = 0; i < Nval*Nrow; i++, Pin+=Nbytes, Pout+=Nbytes) {
+      *(char *)Pout = (*(char *)Pin - Bzero) / Bscale;
+    }
+  }
+  if (!strcmp (type, "short")) {
+    for (i = 0; i < Nval*Nrow; i++, Pin+=Nbytes, Pout+=Nbytes) {
+      *(short *)Pout = (*(short *)Pin - Bzero) / Bscale;
+# ifdef BYTE_SWAP
+      I = i*Nbytes;
+      SWAP_BYTE;
+# endif
+    }  
+  }
+  if (!strcmp (type, "int")) {
+    for (i = 0; i < Nval*Nrow; i++, Pin+=Nbytes, Pout+=Nbytes) {
+      *(int *)Pout = (*(int *)Pin - Bzero) / Bscale;
+# ifdef BYTE_SWAP
+      I = i*Nbytes;
+      SWAP_WORD;
+# endif
+    }
+  }
+  if (!strcmp (type, "float")) {
+    for (i = 0; i < Nval*Nrow; i++, Pin+=Nbytes, Pout+=Nbytes) {
+      *(float *)Pout = (*(float *)Pin - Bzero) / Bscale;
+# ifdef BYTE_SWAP
+      I = i*Nbytes;
+      SWAP_WORD;
+# endif
+    }
+  }
+  if (!strcmp (type, "double")) {
+    for (i = 0; i < Nval*Nrow; i++, Pin+=Nbytes, Pout+=Nbytes) {
+      *(double *)Pout = (*(double *)Pin - Bzero) / Bscale;
+# ifdef BYTE_SWAP
+      I = i*Nbytes;
+      SWAP_DBLE;
+# endif
+    }
+  }
+
+  /* check array space */
+  if (Nx*Ny < Nx*(Nrow - 1) + Nstart + Nval*Nbytes) {
+    fprintf (stderr, "mismatch in array sizes\n");
+    return (FALSE);
+  }
+
+  /* insert bytes from array into appropriate section of buffer */
+  Pout = table[0].buffer + Nstart;
+  Pin  = array;
+  for (i = 0; i < Nrow; i++, Pout += Nx, Pin += Nval*Nbytes) {
+    memcpy (Pout, Pin, Nval*Nbytes);
+  }
+
+  free (array);
+  return (TRUE);
+}
+
+/* 
+   valid BINTABLE column formats:
+   L - logical
+   X - bit
+   I - 16 bit int
+   J - 32 bit int
+   A - char
+   E - float 
+   D - double
+   B - unsigned bytes
+   C - complex float
+   M - complex double
+   P - var lenght array descrpt (64 bit)
+   
+   all can be preceeded by integer N which specified number
+   of entries in array
+   
+*/
+
+
+/***********************/
+int gfits_set_table_column (Header *header, FTable *table, char *label, void *data, int Nrow) {
+
+  int i, N, Nfields, Nval, Nbytes, Nx, Ny, nbytes, Nstart, Nv, Nb;
+  char tlabel[80], field[80], format[80], cformat[80], type[16], tmp[16];
+  char *array, *Pin, *Pout, *line;
+
+  if (label == (char *) NULL) return (FALSE);
+  if (label[0] == 0) return (FALSE);
+
+  /* find label in header */
+  tlabel[0] = 0;
+  gfits_scan (header, "TFIELDS", "%d", 1, &Nfields);
+  for (i = 1; strcmp (label, tlabel) && (i < Nfields + 1); i++) {
+    sprintf (field, "TTYPE%d", i);
+    gfits_scan (header, field, "%s", 1, tlabel);
+  }
+  if (strcmp (label, tlabel)) return (FALSE);
+  N = i - 1;
+
+  /* interpret format */
+  sprintf (field, "TFORM%d", N);
+  gfits_scan (header, field, "%s", 1, format);
+
+  if (!gfits_table_format (format, type, &Nval, &Nbytes)) return (FALSE);
+  strcpy (cformat, format);
+  
+  /* check existing table dimensions */
+  gfits_scan (header, "NAXIS1",  "%d", 1, &Nx);
+  gfits_scan (header, "NAXIS2",  "%d", 1, &Ny);
+  if (Ny == 0) { 
+    Ny = Nrow;
+    header[0].Naxis[1] = Ny;
+    gfits_modify (header, "NAXIS2",  "%d", 1, Ny);
+
+    nbytes = gfits_matrix_size (header);
+    REALLOCATE (table[0].buffer, char, MAX (nbytes, 1));
+    bzero (table[0].buffer, nbytes);
+    table[0].size = nbytes;
+  }
+  if (Ny != Nrow) return (FALSE);
+
+  /* scan columns to find insert point */
+  Nstart = 0;
+  for (i = 1; i < N; i++) {
+    sprintf (field, "TFORM%d", i);
+    gfits_scan (header, field, "%s", 1, format);
+    gfits_table_format (format, tmp, &Nv, &Nb);
+    Nstart += Nv*Nb;
+  }
+
+  /* print line with appropriate formatting */
+  ALLOCATE (array, char, Nbytes*Nval*Nrow);
+  ALLOCATE (line, char, Nval+1);
+  Pin = data;
+  Pout = array;
+  if (!strcmp (type, "char")) {
+    for (i = 0; i < Nval*Nrow; i++, Pin++, Pout++) {
+      *Pout = *Pin;
+    }
+  }
+  if (!strcmp (type, "int")) {
+    for (i = 0; i < Nrow; i++, Pin+=4, Pout+=Nval) {
+      snprintf (line, Nval + 1, cformat, *(int *)Pin);
+      memcpy (Pout, line, Nval);
+    }
+  }
+  if (!strcmp (type, "float")) {
+    for (i = 0; i < Nrow; i++, Pin+=4, Pout+=Nval) {
+      snprintf (line, Nval + 1, cformat, *(float *)Pin);
+      memcpy (Pout, line, Nval);
+    }
+  }
+
+  /* check array space */
+  if (Nx*Ny < Nx*(Nrow - 1) + Nstart + Nval*Nbytes) {
+    fprintf (stderr, "mismatch in array sizes\n");
+    return (FALSE);
+  }
+
+  /* insert bytes from array into appropriate section of buffer */
+  Pout = table[0].buffer + Nstart;
+  Pin  = array;
+  for (i = 0; i < Nrow; i++, Pout += Nx, Pin += Nval*Nbytes) {
+    memcpy (Pout, Pin, Nval*Nbytes);
+  }
+
+  free (line);
+  free (array);
+  return (TRUE);
+}
+
+/*
+  valid TABLE column formats:
+  FN.N  - floating point
+  INN   - integer
+  ANN   - NN char string
+  
+*/
+
Index: /branches/libfits-1-8/Ohana/src/libfits/table/F_table_column.c
===================================================================
--- /branches/libfits-1-8/Ohana/src/libfits/table/F_table_column.c	(revision 11932)
+++ /branches/libfits-1-8/Ohana/src/libfits/table/F_table_column.c	(revision 11932)
@@ -0,0 +1,95 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+/*********************** fits table column ****************************/
+int gfits_table_column (Table *table, char *field, char *mode,...) {
+/* we expect one more field: the pointer to the array we read in */
+
+  char string[80], this_field[80], form[80], temp[80];
+  int i, j, N, start, end, width, M;
+  va_list argp;
+  double **D;
+  float  **F;
+  char   ***C;
+  int    **I;
+  
+  va_start (argp, mode);
+
+  /* find the correct field */
+  for (i = 0; i < table[0].Nfields; i++) {
+    sprintf (string, "TTYPE%d\0", i+1);
+    gfits_scan (&table[0].header, string, "%s", 1, this_field);
+    if (!strcmp (field, this_field)) {
+      break;
+    }
+  }
+  
+  if (i == table[0].Nfields) {
+    fprintf (stderr, "Table field %s does not exist\n", field);
+    return (FALSE);
+  }
+
+  N = i + 1;
+
+  sprintf (string, "TBCOL%d\0", N);
+  gfits_scan (&table[0].header, string, "%d", 1, &start);
+  sprintf (string, "TFORM%d\0", N);
+  gfits_scan (&table[0].header, string, "%s", 1, form);
+  /* we could use some error checking from the FITS table form, but
+     it is not immediately crucial */
+
+  if (N == table[0].Nfields) { 
+    end = table[0].Naxis[0];
+  } else {
+    sprintf (string, "TBCOL%d\0", N+1);
+    gfits_scan (&table[0].header, string, "%d", 1, &end);
+  }
+  width = end - start;
+  
+  if (!strcmp (mode, "%d")) {
+    I = va_arg (argp, int **);
+    ALLOCATE ((*I), int, table[0].Naxis[1]);
+    M = 0;
+  }
+  if (!strcmp (mode, "%f"))  {
+    F = va_arg (argp, float **);
+    ALLOCATE ((*F), float, table[0].Naxis[1]);
+    M = 1;
+  }
+  if (!strcmp (mode, "%lf")) {
+    D = va_arg (argp, double **);
+    ALLOCATE ((*D), double, table[0].Naxis[1]);
+    M = 2;
+  }
+  if (!strcmp (mode, "%s")) {
+    C = va_arg (argp, char ***);
+    ALLOCATE ((*C), char *, table[0].Naxis[1]);
+    for (i = 0; i < table[0].Naxis[1]; i++) {
+      ALLOCATE ((*C)[i], char, width + 1);
+    }
+    M = 3;
+  }
+
+  for (i = 0; i < table[0].Naxis[1]; i++) {
+    strncpy (temp, &table[0].buffer[i*table[0].Naxis[0] + start - 1], width);
+    temp[width] = 0;
+    switch (M) {
+    case 0:
+      (*I)[i] = (int) atof (temp);
+      break;
+    case 1:
+      (*F)[i] = atof (temp);
+      break;
+    case 2:
+      (*D)[i] = atof (temp);
+      break;
+    case 3:
+      strcpy ((*C)[i], temp);
+      break;
+    default:
+      fprintf (stderr, "unknown gfits_table_column mode: %s\n", mode);
+      return (FALSE);
+    }
+  }
+  return (TRUE);
+}
Index: /branches/libfits-1-8/Ohana/src/libfits/table/F_table_format.c
===================================================================
--- /branches/libfits-1-8/Ohana/src/libfits/table/F_table_format.c	(revision 11932)
+++ /branches/libfits-1-8/Ohana/src/libfits/table/F_table_format.c	(revision 11932)
@@ -0,0 +1,191 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+/***********************/
+int gfits_bintable_format (char *format, char *type, int *Nval, int *Nbytes) {
+
+  char *Lchar, *Fchar;
+  int Nv;
+
+  if (format == (char *) NULL) return (FALSE);
+  if (format[0] == 0) return (FALSE);
+  Lchar = &format[strlen(format) - 1];
+
+  Nv = strtol (format, &Fchar, 10);
+  if (Fchar != Lchar) return (FALSE);
+  if ((Nv == 0) && (Fchar == format)) Nv = 1;
+
+  *Nbytes = 0;
+  if (*Fchar == 'X') { *Nbytes = 1;  strcpy (type, "char");   *Nval = 1 + (int) Nv / 8; }
+  if (*Fchar == 'L') { *Nbytes = 1;  strcpy (type, "char");   *Nval = Nv;               }
+  if (*Fchar == 'A') { *Nbytes = 1;  strcpy (type, "char");   *Nval = Nv;               }
+  if (*Fchar == 'B') { *Nbytes = 1;  strcpy (type, "char");   *Nval = Nv;               }
+  if (*Fchar == 'I') { *Nbytes = 2;  strcpy (type, "short");  *Nval = Nv;               }
+  if (*Fchar == 'J') { *Nbytes = 4;  strcpy (type, "int");    *Nval = Nv;               }
+  if (*Fchar == 'E') { *Nbytes = 4;  strcpy (type, "float");  *Nval = Nv;               }
+  if (*Fchar == 'D') { *Nbytes = 8;  strcpy (type, "double"); *Nval = Nv;               }
+  if (*Fchar == 'P') { *Nbytes = 8;  strcpy (type, "float");  *Nval = 2*Nv;             }
+  if (*Fchar == 'C') { *Nbytes = 8;  strcpy (type, "float");  *Nval = 2*Nv;             }
+  if (*Fchar == 'M') { *Nbytes = 16; strcpy (type, "double"); *Nval = 2*Nv;             }
+  if (!*Nbytes) { return (FALSE); }
+
+  return (TRUE);
+}
+
+/* 
+   valid BINTABLE column formats:
+   L - logical
+   X - bit
+   I - 16 bit int
+   J - 32 bit int
+   A - char
+   E - float 
+   D - double
+   B - unsigned bytes
+   C - complex float
+   M - complex double
+   P - var length array descrpt (64 bit)
+   
+   all can be preceeded by integer N which specified number
+   of entries in array
+   
+*/
+
+/***********************/
+int gfits_table_format (char *format, char *type, int *Nval, int *Nbytes) {
+
+  char Fchar, Size[80], Type;
+  int Nv;
+
+  if (format == (char *) NULL) return (FALSE);
+  if (format[0] == 0) return (FALSE);
+  Fchar = format[0];
+
+  Nv = strtol (&format[1], (char **) NULL, 10);
+  if (Nv == 0) { 
+    Nv = 1;
+    strcpy (Size, "1");
+  } else {
+    strcpy (Size, &format[1]);
+  }
+  
+  Type = 'x';
+  if (Fchar == 'F') { *Nbytes = 1;  strcpy (type, "float");  Type = 'f'; *Nval = Nv; }
+  if (Fchar == 'I') { *Nbytes = 1;  strcpy (type, "int");    Type = 'd'; *Nval = Nv; }
+  if (Fchar == 'A') { *Nbytes = 1;  strcpy (type, "char");   Type = 's'; *Nval = Nv; }
+  if (!*Nbytes) { return (FALSE); }
+  
+  sprintf (format, "%%-%s%c", Size, Type);
+
+  return (TRUE);
+}
+
+/*
+  valid TABLE column formats:
+  FN.N  - floating point
+  INN   - integer
+  ANN   - NN char string
+  
+*/
+
+/** extract a table subset to a vtable ***/
+int gfits_table_to_vtable (FTable *ftable, VTable *vtable, int start, int Nkeep) {
+
+  /* gfits_table_to_vtable (f, v, 0, Ny - 1) - keep all of table
+     gfits_table_to_vtable (f, v, 0, 0)      - keep none of table 
+  */  
+
+  int i, Nx, Ny;
+
+  gfits_scan (ftable[0].header, "NAXIS1", "%d", 1, &Nx);
+  gfits_scan (ftable[0].header, "NAXIS2", "%d", 1, &Ny);
+  
+  if (start + Nkeep > Ny) return (FALSE);
+  if (start < 0) return (FALSE);
+  if (Nkeep < 0) return (FALSE);
+
+  ALLOCATE (vtable[0].row, int, MAX (1, Nkeep));
+  ALLOCATE (vtable[0].buffer, char *, MAX (1, Nkeep));
+  for (i = 0; i < Nkeep; i++) {
+    ALLOCATE (vtable[0].buffer[i], char, MAX (1, Nx));
+    memcpy (vtable[0].buffer[i], &ftable[0].buffer[(i+start)*Nx], Nx);
+    vtable[0].row[i] = i + start;
+  }
+  
+  vtable[0].header = ftable[0].header;
+  vtable[0].size = ftable[0].size;
+  vtable[0].Nrow = Nkeep;
+  vtable[0].pad = vtable[0].size - Nx*Ny;
+
+  return (TRUE);
+}
+
+/** convert specified rows to vtable */
+int gfits_vtable_from_ftable (FTable *ftable, VTable *vtable, int *row, int Nrow) {
+
+  int i, N, Nx, Ny;
+
+  gfits_scan (ftable[0].header, "NAXIS1", "%d", 1, &Nx);
+  gfits_scan (ftable[0].header, "NAXIS2", "%d", 1, &Ny);
+
+  /* make empty vtable from table */
+  vtable[0].header = ftable[0].header;  /* make this a copy? */
+  vtable[0].size   = ftable[0].size;
+  vtable[0].pad    = vtable[0].size - Nx*Ny;
+  vtable[0].Nrow   = Ny;
+
+  /* insert selected rows in vtable (mask rows marked with -1) */ 
+  ALLOCATE (vtable[0].row, int, Nrow);
+  ALLOCATE (vtable[0].buffer, char *, Nrow);
+  for (N = i = 0; i < Nrow; i++) {
+    if (row[i] == -1) continue;
+    vtable[0].row[N] = row[i];
+    ALLOCATE (vtable[0].buffer[N], char, Nx);
+    memcpy (vtable[0].buffer[N], &ftable[0].buffer[Nx*row[i]], Nx);
+    N++;
+  }
+  vtable[0].Nrow = N;
+  return (TRUE);
+}
+
+/* use table def to format a complete string */
+char *gfits_table_print (FTable *table,...) { 
+  
+  int i, Nx, Nfields;
+  int off, Nchar, Nval, Nbytes;
+  char *line, format[64], field[16], type[16];
+  va_list argp;
+  
+  va_start (argp, table);
+
+  gfits_scan (table[0].header, "NAXIS1",  "%d", 1, &Nx);
+  gfits_scan (table[0].header, "TFIELDS", "%d", 1, &Nfields);
+
+  ALLOCATE (line, char, Nx + 1);
+  
+  off = 0;
+  for (i = 1; i <= Nfields; i++) {
+
+    sprintf (field, "TFORM%d", i);
+    gfits_scan (table[0].header, field, "%s", 1, format);       /* get field format */
+    gfits_table_format (format, type, &Nval, &Nbytes); /* convert to c-style */
+    Nchar = Nval * Nbytes;
+    if (!strcmp (type, "int"))   { 
+      /* d = va_arg (argp, int); */
+      snprintf (&line[off], Nchar + 1, format, va_arg (argp, int)); 
+    }
+    if (!strcmp (type, "float")) { 
+      /* f = va_arg (argp, double); */
+      snprintf (&line[off], Nchar + 1, format, va_arg (argp, double)); 
+    }
+    if (!strcmp (type, "char"))  { 
+      /* c = va_arg (argp, char *); */
+      snprintf (&line[off], Nchar + 1, format, va_arg (argp, char *));
+    }
+    off += Nchar;
+  }
+  va_end (argp);
+  return (line);
+}
+
+    /* vsnprintf (&line[off], Nchar + 1, format, argp); */
Index: /branches/libfits-1-8/Ohana/src/libfits/table/F_table_row.c
===================================================================
--- /branches/libfits-1-8/Ohana/src/libfits/table/F_table_row.c	(revision 11932)
+++ /branches/libfits-1-8/Ohana/src/libfits/table/F_table_row.c	(revision 11932)
@@ -0,0 +1,106 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+/*********************** fits table column ****************************/
+int gfits_add_rows (FTable *table, char *data, int Nrow, int Nbytes) {
+
+  int Nx, Ny;
+  int nbytes, Nstart;
+  Header *header;
+
+  header = table[0].header;
+
+  gfits_scan (header, "NAXIS1", "%d", 1, &Nx);
+  gfits_scan (header, "NAXIS2", "%d", 1, &Ny);
+  
+  if (header[0].Naxis[1] != Ny) return (FALSE);
+  if (header[0].Naxis[0] != Nx) return (FALSE);
+  if (header[0].Naxis[0] != Nbytes) return (FALSE);
+  
+  Nstart = Nx*Ny;
+
+  /* update header y dimension */
+  Ny += Nrow;
+  header[0].Naxis[1] = Ny;
+  gfits_modify (header, "NAXIS2",  "%d", 1, Ny);
+
+  nbytes = gfits_matrix_size (header);
+  REALLOCATE (table[0].buffer, char, MAX (nbytes, 1));
+  table[0].size = nbytes;
+  
+  memcpy (&table[0].buffer[Nstart], data, Nbytes*Nrow);
+  memset (&table[0].buffer[Nx*Ny], ' ', nbytes - Nx*Ny);
+  return (TRUE);
+}
+
+/*********************** fits add (real) rows to virtual table ****************************/
+int gfits_vadd_rows (VTable *table, char *data, int Nrow, int Nbytes) {
+
+  int i, Nx, Ny;
+  int Nstart;
+  Header *header;
+
+  header = table[0].header;
+
+  gfits_scan (header, "NAXIS1", "%d", 1, &Nx);
+  gfits_scan (header, "NAXIS2", "%d", 1, &Ny);
+  
+  if (header[0].Naxis[1] != Ny) return (FALSE);
+  if (header[0].Naxis[0] != Nx) return (FALSE);
+  if (header[0].Naxis[0] != Nbytes) return (FALSE);
+  
+  /* Nstart is end of data in memory */
+  Nstart = table[0].Nrow;
+  table[0].Nrow += Nrow;
+  REALLOCATE (table[0].buffer, char *, table[0].Nrow);
+  REALLOCATE (table[0].row, int, table[0].Nrow);
+  for (i = 0; i < Nrow; i++) {
+    ALLOCATE (table[0].buffer[Nstart+i], char, MAX (1, Nx));
+    memcpy (table[0].buffer[Nstart+i], &data[i*Nx], Nx);
+    table[0].row[Nstart+i] = Ny + i;
+  }
+
+  /* update header y dimension */
+  Ny += Nrow;
+  header[0].Naxis[1] = Ny;
+  gfits_modify (header, "NAXIS2",  "%d", 1, Ny);
+
+  table[0].size   = gfits_matrix_size (table[0].header);
+  table[0].pad    = table[0].size - Nx*Ny;
+
+  return (TRUE);
+}
+
+/*********************** fits table column ****************************/
+int gfits_delete_rows (FTable *table, int Nstart, int Nrow) {
+
+  int Nx, Ny, N0, N1, N2;
+  int nbytes;
+  Header *header;
+
+  header = table[0].header;
+
+  gfits_scan (header, "NAXIS1", "%d", 1, &Nx);
+  gfits_scan (header, "NAXIS2", "%d", 1, &Ny);
+  
+  if (header[0].Naxis[1] != Ny) return (FALSE);
+  if (header[0].Naxis[0] != Nx) return (FALSE);
+  if (Ny > Nstart + Nrow) return (FALSE);
+  
+  /* shrink buffer by Nrow entries */
+  N0 = Nx*Nstart;
+  N1 = Nx*(Nstart + Nrow);
+  N2 = Nx*(Ny - Nstart - Nrow);
+  memmove (&table[0].buffer[N0], &table[0].buffer[N1], N2);
+
+  /* update header y dimension */
+  Ny -= Nrow;
+  header[0].Naxis[1] = Ny;
+  gfits_modify (header, "NAXIS2",  "%d", 1, Ny);
+
+  nbytes = gfits_matrix_size (header);
+  REALLOCATE (table[0].buffer, char, MAX (nbytes, 1));
+  table[0].size = nbytes;
+  return (TRUE);
+}
+
Index: /branches/libfits-1-8/Ohana/src/libfits/table/F_write_T.c
===================================================================
--- /branches/libfits-1-8/Ohana/src/libfits/table/F_write_T.c	(revision 11932)
+++ /branches/libfits-1-8/Ohana/src/libfits/table/F_write_T.c	(revision 11932)
@@ -0,0 +1,70 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+/*********************** fits write header *********************************/
+int gfits_write_table (char *filename, FTable *table) {
+  
+  FILE *f;
+  int status;
+  
+  status = TRUE;
+  
+  f = fopen (filename, "a+");
+  if (f == (FILE *) NULL) return (FALSE);
+  
+  status = fseek (f, 0, SEEK_END);  /* write table to end of file! */
+  status = gfits_fwrite_table (f, table);
+
+  fclose (f);
+  return (status);
+}	
+
+/*********************** fits write table *********************************/
+int gfits_fwrite_table (FILE *f, FTable *table) {
+  
+  int Nbytes;
+  
+  Nbytes = fwrite (table[0].buffer, sizeof(char), table[0].size, f);
+  
+  if (Nbytes != table[0].size) return (FALSE);
+  return (TRUE);
+}	
+
+/*********************** fits write virtual table *********************************/
+int gfits_fwrite_vtable (FILE *f, VTable *table) {
+  
+  int i, Nx, Ny, Npad, offset, start;
+  int Nbytes, *row, Nrow;
+  char *pad;
+
+  Nrow = table[0].Nrow;
+  row = table[0].row;
+  gfits_scan (table[0].header, "NAXIS1", "%d", 1, &Nx);
+  gfits_scan (table[0].header, "NAXIS2", "%d", 1, &Ny);
+
+  /* file pointer is at beginning of desired table data */
+  start = ftell (f);
+  
+  for (i = 0; i < Nrow; i++) {
+    offset = start + Nx*row[i];
+    fseek (f, offset, SEEK_SET);
+    Nbytes = fwrite (table[0].buffer[i], sizeof (char), Nx, f);
+    if (Nbytes != Nx) { return (FALSE); }
+  }
+  
+  Npad = table[0].size - Nx*Ny;
+  ALLOCATE (pad, char, Npad);
+  bzero (pad, Npad);
+
+  offset = start + Nx*Ny;
+  fseek (f, offset, SEEK_SET);
+  Nbytes = fwrite (pad, sizeof (char), Npad, f);
+  if (Nbytes != Npad) { return (FALSE); }
+  free (pad);
+
+  return (TRUE);
+}	
+
+
+/* this will add data beyond the end of the table in the file if needed,
+   filling intervening gap with 0 */
Index: /branches/libfits-1-8/Ohana/src/libfits/table/F_write_TH.c
===================================================================
--- /branches/libfits-1-8/Ohana/src/libfits/table/F_write_TH.c	(revision 11932)
+++ /branches/libfits-1-8/Ohana/src/libfits/table/F_write_TH.c	(revision 11932)
@@ -0,0 +1,33 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+/*********************** fits write header *********************************/
+int gfits_write_Theader (char *filename, Header *header) {
+  
+  FILE *f;
+  int status;
+  
+  status = TRUE;
+  
+  f = fopen (filename, "a+");
+  if (f == (FILE *) NULL) return (FALSE);
+  
+  status = fseek (f, 0, SEEK_END);  /* write header to end of file! */
+  status = gfits_fwrite_Theader (f, header);
+
+  fclose (f);
+  return (status);
+}	
+
+/*********************** fits write header *********************************/
+int gfits_fwrite_Theader (FILE *f, Header *header) {
+  
+  int Nbytes;
+  
+  Nbytes = fwrite (header[0].buffer, sizeof(char), header[0].size, f);
+
+  if (Nbytes != header[0].size) return (FALSE);
+  return (TRUE);
+}	
+
+
