Index: /trunk/psLib/src/fits/psFits.c
===================================================================
--- /trunk/psLib/src/fits/psFits.c	(revision 6766)
+++ /trunk/psLib/src/fits/psFits.c	(revision 6767)
@@ -7,6 +7,6 @@
  *  @author Robert DeSonia, MHPCC
  *
- *  @version $Revision: 1.52 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2006-02-08 01:03:34 $
+ *  @version $Revision: 1.53 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2006-04-04 19:52:42 $
  *
  *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
@@ -166,4 +166,5 @@
             psFits* fits = psAlloc(sizeof(psFits));
         fits->fd = fptr;
+        fits->writable = (iomode == READWRITE);
         psMemSetDeallocator(fits,(psFreeFunc)fitsFree);
 
@@ -252,6 +253,10 @@
             return false;
         }
-
-        return psFitsMoveExtNum(fits,psFitsGetSize(fits),false);
+        int size = psFitsGetSize(fits);
+        if (size == 0) { // empty file -- no action needed
+            return true;
+        } else {
+            return psFitsMoveExtNum(fits,size-1,false);
+        }
     }
 
@@ -329,4 +334,10 @@
         }
 
+        if (! fits->writable) {
+            psError(PS_ERR_IO, true,
+                    PS_ERRORTEXT_psFits_NOT_WRITABLE);
+            return false;
+        }
+
         // move to the specified HDU
         if (! psFitsMoveExtNum(fits,extnum,relative) ) {
@@ -361,4 +372,10 @@
         }
 
+        if (! fits->writable) {
+            psError(PS_ERR_IO, true,
+                    PS_ERRORTEXT_psFits_NOT_WRITABLE);
+            return false;
+        }
+
         // move to the specified HDU
         if (! psFitsMoveExtName(fits,extname) ) {
@@ -442,4 +459,10 @@
             psError(PS_ERR_BAD_PARAMETER_NULL, true,
                     PS_ERRORTEXT_psFits_NULL);
+            return PS_FITS_TYPE_NONE;
+        }
+
+        if (! fits->writable) {
+            psError(PS_ERR_IO, true,
+                    PS_ERRORTEXT_psFits_NOT_WRITABLE);
             return PS_FITS_TYPE_NONE;
         }
Index: /trunk/psLib/src/fits/psFits.h
===================================================================
--- /trunk/psLib/src/fits/psFits.h	(revision 6766)
+++ /trunk/psLib/src/fits/psFits.h	(revision 6767)
@@ -7,6 +7,6 @@
  *  @author Robert DeSonia, MHPCC
  *
- *  @version $Revision: 1.23 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2006-02-08 01:03:34 $
+ *  @version $Revision: 1.24 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2006-04-04 19:52:42 $
  *
  *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
@@ -49,4 +49,5 @@
 {
     fitsfile* fd;                      ///< the CFITSIO fits files handle.
+    bool writable;                     ///< Is the file writable?
 }
 psFits;
Index: /trunk/psLib/src/fits/psFitsHeader.c
===================================================================
--- /trunk/psLib/src/fits/psFitsHeader.c	(revision 6766)
+++ /trunk/psLib/src/fits/psFitsHeader.c	(revision 6767)
@@ -7,6 +7,6 @@
  *  @author Robert DeSonia, MHPCC
  *
- *  @version $Revision: 1.2 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2006-02-08 01:03:34 $
+ *  @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2006-04-04 19:52:42 $
  *
  *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
@@ -90,7 +90,21 @@
             switch (keyType) {
             case 'X': // bit
+            case 'B': // byte
+                success = psMetadataAdd(out,
+                                        PS_LIST_TAIL,
+                                        keyName,
+                                        PS_DATA_S8 | PS_META_DUPLICATE_OK,
+                                        keyComment,
+                                        atoi(keyValue));
+                break;
             case 'I': // short int.
+                success = psMetadataAdd(out,
+                                        PS_LIST_TAIL,
+                                        keyName,
+                                        PS_DATA_S16 | PS_META_DUPLICATE_OK,
+                                        keyComment,
+                                        (psS16)atoi(keyValue));
+                break;
             case 'J': // int.
-            case 'B': // byte
                 success = psMetadataAdd(out,
                                         PS_LIST_TAIL,
@@ -100,6 +114,14 @@
                                         atoi(keyValue));
                 break;
-            case 'U': // unsigned int. may not fit in a psS32
-            case 'K': // long int. can't all fit in a psS32
+            case 'U': // unsigned int.
+                success = psMetadataAdd(out,
+                                        PS_LIST_TAIL,
+                                        keyName,
+                                        PS_DATA_U32 | PS_META_DUPLICATE_OK,
+                                        keyComment,
+                                        atol(keyValue));
+                break;
+
+            case 'K': // long int. can't all fit in a psS32, put in psF64
             case 'F':
                 success = psMetadataAdd(out,
@@ -167,13 +189,16 @@
 }
 
-psMetadata* psFitsReadHeaderSet(const psFits* fits)
+psMetadata* psFitsReadHeaderSet(psMetadata* out, const psFits* fits)
 {
     if (fits == NULL) {
         psError(PS_ERR_BAD_PARAMETER_NULL, true,
                 PS_ERRORTEXT_psFits_NULL);
+        psFree(out);
         return NULL;
     }
 
-    psMetadata* out = psMetadataAlloc();
+    if (out == NULL) {
+        out = psMetadataAlloc();
+    }
 
     int size = psFitsGetSize(fits);
@@ -244,4 +269,20 @@
                 break;
             }
+        case PS_DATA_S8:
+            fits_update_key(fits->fd,
+                            TBYTE,
+                            item->name,
+                            &item->data.S8,
+                            item->comment,
+                            &status);
+            break;
+        case PS_DATA_S16:
+            fits_update_key(fits->fd,
+                            TSHORT,
+                            item->name,
+                            &item->data.S16,
+                            item->comment,
+                            &status);
+            break;
         case PS_DATA_S32:
             fits_update_key(fits->fd,
@@ -249,4 +290,30 @@
                             item->name,
                             &item->data.S32,
+                            item->comment,
+                            &status);
+            break;
+        case PS_DATA_U8: {
+                unsigned short int temp = item->data.U8;
+                fits_update_key(fits->fd,
+                                TUSHORT,
+                                item->name,
+                                &temp,
+                                item->comment,
+                                &status);
+            }
+            break;
+        case PS_DATA_U16:
+            fits_update_key(fits->fd,
+                            TUSHORT,
+                            item->name,
+                            &item->data.U16,
+                            item->comment,
+                            &status);
+            break;
+        case PS_DATA_U32:
+            fits_update_key(fits->fd,
+                            TUINT,
+                            item->name,
+                            &item->data.U32,
                             item->comment,
                             &status);
@@ -290,5 +357,46 @@
     }
 
+    psFree(iter);
+
     return true;
 }
 
+bool psFitsHeaderValidate(psMetadata *header)
+{
+    bool valid = true;
+    int status;
+
+    if (header == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                PS_ERRORTEXT_psFits_METADATA_NULL);
+        return false;
+    }
+
+    //transverse the metadata list and inspect at each key
+
+    psListIterator* iter = psListIteratorAlloc(header->list,PS_LIST_HEAD,true);
+    psMetadataItem* item;
+    while ( (item=psListGetAndIncrement(iter)) != NULL ) {
+        psDataType type = item->type;
+
+        if (type > PS_DATA_STRING) { // i.e., a non-primitive type
+            valid = false;
+        }
+
+        if (strlen(item->name) > 8) {
+            item->name[8] = '\0'; // truncate to 8 characters
+        }
+
+        fits_uppercase(item->name); // make uppercase
+
+        // now, let's see if CFITSIO thinks this is a good keyword...
+        status = 0;
+        if (fits_test_keyword(item->name,&status) != 0) {
+            valid = false;
+        }
+    }
+
+    psFree(iter);
+
+    return valid;
+}
Index: /trunk/psLib/src/fits/psFitsHeader.h
===================================================================
--- /trunk/psLib/src/fits/psFitsHeader.h	(revision 6766)
+++ /trunk/psLib/src/fits/psFitsHeader.h	(revision 6767)
@@ -7,6 +7,6 @@
  *  @author Robert DeSonia, MHPCC
  *
- *  @version $Revision: 1.2 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2006-02-08 01:03:34 $
+ *  @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2006-04-04 19:52:42 $
  *
  *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
@@ -37,4 +37,5 @@
  */
 psMetadata* psFitsReadHeaderSet(
+    psMetadata* out,                         ///< output metadata or NULL if new psMetadata is to be created.
     const psFits* fits                       ///< the psFits object
 );
@@ -49,24 +50,11 @@
 );
 
-/** Updates the given header to be compatible with the supplied image, updating
- *  BITPIX, NAXIS1, and NAXIS2.  The extension name is (re)set to the given
- *  extname.
+/** psFitsHeaderValidate validates the supplied header so that it is in
+ *  compliance to the FITS standard for header keyword names and types.
  *
- *  @return psMetadata*     updated header.
+ *  @return bool        TRUE if the resulting header conforms to the FITS
+ *                      standard, otherwise FALSE
  */
-psMetadata* psFitsHeaderFromImage(
-    psMetadata* header,                ///< the header to update
-    psImage* image,                    ///< the image to use to determine update values
-    const char* extname                ///< the extension name
-);
-
-/** Updates the given header to be compatible with the given table, i.e. psArray
- *  of psMetadata. The extension name is (re)set to the given extname.
- */
-psMetadata* psFitsHeaderFromTable(
-    psMetadata* header,                ///< the header to update
-    psArray* table,                    ///< the table to use to update header
-    const char* extname                ///< the extension name
-);
+bool psFitsHeaderValidate(psMetadata *header);
 
 /// @}
Index: /trunk/psLib/src/fits/psFitsImage.c
===================================================================
--- /trunk/psLib/src/fits/psFitsImage.c	(revision 6766)
+++ /trunk/psLib/src/fits/psFitsImage.c	(revision 6767)
@@ -7,6 +7,6 @@
  *  @author Robert DeSonia, MHPCC
  *
- *  @version $Revision: 1.1 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2005-11-14 22:18:30 $
+ *  @version $Revision: 1.2 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2006-04-04 19:52:42 $
  *
  *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
@@ -16,4 +16,5 @@
 
 #include "psFits.h"
+#include "psFitsImage.h"
 #include "string.h"
 #include "psError.h"
@@ -292,5 +293,19 @@
                       psMetadata* header,
                       const psImage* input,
-                      int numZPlanes)
+                      int numZPlanes,
+                      const char* extname)
+{
+    // this is equivalent to insert after the last HDU
+
+    psFitsMoveLast(fits);
+    return psFitsInsertImage(fits,header,input,numZPlanes,extname,true);
+}
+
+bool psFitsInsertImage(psFits* fits,
+                       psMetadata* header,
+                       const psImage* input,
+                       int numZPlanes,
+                       const char* extname,
+                       bool after)
 {
 
@@ -330,5 +345,23 @@
     }
 
-    fits_create_img(fits->fd, bitPix, naxis, naxes, &status);
+    int chdu = psFitsGetExtNum(fits);
+    int hdus = psFitsGetSize(fits);
+    if (! after) {
+        if (chdu == 0) {
+            // set status to signal fits_insert_img to insert a new primary HDU
+            status = PREPEND_PRIMARY;
+        } else if (hdus > 0) {
+            // move back one to perform an insert after the previous HDU
+            psFitsMoveExtNum(fits, -1, true);
+        }
+    }
+
+    if (hdus == 0) {
+        status = 0;
+        fits_create_img(fits->fd, bitPix, naxis, naxes, &status);
+
+    } else {
+        fits_insert_img(fits->fd, bitPix, naxis, naxes, &status);
+    }
 
     if (bZero != 0) {        // set the bscale/bzero
@@ -339,6 +372,17 @@
 
     // write the header, if any.
+    if (extname != NULL) {
+        psFitsSetExtName(fits,extname);
+    }
+
     if (header != NULL) {
-        psFitsWriteHeader(header, (psPtr)fits);
+        if (extname != NULL) {
+            psMetadataAddStr(header,PS_LIST_TAIL,"EXTNAME",
+                             PS_META_REPLACE,
+                             "Extenion Name",
+                             extname);
+        }
+
+        psFitsWriteHeader(header, fits);
     }
 
@@ -378,5 +422,6 @@
 bool psFitsUpdateImage(psFits* fits,
                        const psImage* input,
-                       psRegion region,
+                       int x0,
+                       int y0,
                        int z)
 {
@@ -453,18 +498,10 @@
     long lastPixel[3];
 
-    firstPixel[0] = region.x0 + 1;
-    firstPixel[1] = region.y0 + 1;
+    firstPixel[0] = x0 + 1;
+    firstPixel[1] = y0 + 1;
     firstPixel[2] = z + 1;
 
-    if (region.x1 > 0) {
-        lastPixel[0] = region.x1;
-    } else {
-        lastPixel[0] = nAxes[0] + region.x1; // n.b., region.x1 < 0
-    }
-    if (region.y1 > 0) {
-        lastPixel[1] = region.y1;
-    } else {
-        lastPixel[1] = nAxes[1] + region.y1; // n.b., region.y1 < 0
-    }
+    lastPixel[0] = x0 + numCols;
+    lastPixel[1] = y0 + numRows;
     lastPixel[2] = z + 1;
 
@@ -474,31 +511,12 @@
             lastPixel[1] < 1 || lastPixel[1] > nAxes[1]) {
         psError(PS_ERR_BAD_PARAMETER_VALUE, true,
-                "Specified region [%d:%d,%d:%d], is not valid given the %dx%d FITS image.",
-                region.y0,region.y1-1,region.x0,region.x1-1);
-        return false;
-
-    }
-
-    int dx = lastPixel[0] - firstPixel[0];
-    int dy = lastPixel[1] - firstPixel[1];
-    if (dx > numCols ||
-            dy > numRows) {
-        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
-                "The region [%d:%d,%d:%d], is not valid given the input %dx%d image.",
-                firstPixel[1]-1,lastPixel[1]-1,
-                firstPixel[0]-1,lastPixel[0]-1,
-                numCols, numRows);
-        return false;
-    }
-
-    psImage* subset;
-    if (dx != numCols || dy != numRows) {
-        // the input image needs to be subsetted
-        subset = psImageSubset((psImage*)input, psRegionSet(0,dx+1,0,dy+1));
-    } else {
-        subset = psMemIncrRefCounter((psImage*)input);
-    }
-
-    fits_write_subset(fits->fd, dataType, firstPixel, lastPixel, subset->data.V[0], &status);
+                "Input image [size of %ix%i] at position (%i,%i) does not all lay in the %ix%i FITS image.",
+                numCols, numRows,
+                x0, y0,
+                nAxes[0], nAxes[1]);
+        return false;
+    }
+
+    fits_write_subset(fits->fd, dataType, firstPixel, lastPixel, input->data.V[0], &status);
 
     if ( status != 0) {
Index: /trunk/psLib/src/fits/psFitsImage.h
===================================================================
--- /trunk/psLib/src/fits/psFitsImage.h	(revision 6766)
+++ /trunk/psLib/src/fits/psFitsImage.h	(revision 6767)
@@ -7,6 +7,6 @@
  *  @author Robert DeSonia, MHPCC
  *
- *  @version $Revision: 1.1 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2005-11-14 22:18:30 $
+ *  @version $Revision: 1.2 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2006-04-04 19:52:42 $
  *
  *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
@@ -46,8 +46,25 @@
     psMetadata* header,                ///< header items for the new HDU.  Can be NULL.
     const psImage* input,              ///< the image to output
-    int depth                          ///< the number of z-planes of the FITS image data cube
+    int depth,                         ///< the number of z-planes of the FITS image data cube
+    const char* extname                ///< FITS extension name
 );
 
-/** Updates the FITS file image, given the desired region and z-plane.
+/** Writes an image, given the desired region and z-plane.  A new IMAGE HDU is
+ *  appended to the end of the FITS file.
+ *
+ *  @return bool        TRUE is the write was successful, otherwise FALSE.
+ */
+bool psFitsInsertImage(
+    psFits* fits,                      ///< the psFits object
+    psMetadata* header,                ///< header items for the new HDU.  Can be NULL.
+    const psImage* input,              ///< the image to output
+    int depth,                         ///< the number of z-planes of the FITS image data cube
+    const char* extname,               ///< FITS extension name
+    bool after                         ///< if TRUE, inserts HDU after current HDU, otherwise before
+);
+
+/** Updates the FITS file image, given the desired region and z-plane. a new
+ *  IMAGE HDU is inserted before or after, depending on the AFTER parameter,
+ *  the current HDU.
  *
  *  @return bool        TRUE is the write was successful, otherwise FALSE.
@@ -56,5 +73,6 @@
     psFits* fits,                      ///< the psFits object
     const psImage* input,              ///< the image to output
-    psRegion region,                   ///< the region in the FITS image to write
+    int x0,                            ///< psImage's x-axis origin in FITS image coordinates
+    int y0,                            ///< psImage's y-axis origin in FITS image coordinates
     int z                              ///< the z-planes of the FITS image data cube to write
 );
Index: /trunk/psLib/src/fits/psFitsTable.c
===================================================================
--- /trunk/psLib/src/fits/psFitsTable.c	(revision 6766)
+++ /trunk/psLib/src/fits/psFitsTable.c	(revision 6767)
@@ -7,6 +7,6 @@
  *  @author Robert DeSonia, MHPCC
  *
- *  @version $Revision: 1.6 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2006-02-24 23:43:15 $
+ *  @version $Revision: 1.7 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2006-04-04 19:52:42 $
  *
  *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
@@ -812,4 +812,226 @@
 }
 
+bool psFitsInsertTable(psFits* fits,
+                       const psMetadata* header,
+                       const psArray* table,
+                       bool after)
+{
+    int status = 0;
+
+    if (fits == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                PS_ERRORTEXT_psFits_NULL);
+        return false;
+    }
+
+    if (table == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                PS_ERRORTEXT_psFits_IMAGE_NULL);
+        return false;
+    }
+
+    int rows = table->n;
+    if (rows < 1) {
+        // no table data, what can I do?
+        psError(PS_ERR_BAD_PARAMETER_SIZE, true,
+                PS_ERRORTEXT_psFits_TABLE_EMPTY);
+        return false;
+    }
+
+    // find all the columns needed
+    psArray* columns = psArrayAlloc(((psMetadata*)table->data[0])->list->n);
+    columns->n=0;
+
+    // find the unique items in the array of metadata 'rows'
+    psMetadataItem* item;
+    for (int row=0; row < rows; row++) {
+        psMetadata* rowMeta = table->data[row];
+        if (rowMeta != NULL) {
+            psListIterator* iter = psListIteratorAlloc(rowMeta->list,
+                                   PS_LIST_HEAD,true);
+            while ( (item=psListGetAndIncrement(iter)) != NULL) {
+                if (PS_DATA_IS_PRIMITIVE(item->type) ||
+                        item->type == PS_DATA_STRING ||
+                        item->type == PS_DATA_VECTOR) {
+                    bool found = false;
+                    psMetadataItem* fItem = NULL;
+                    int n;
+                    for (n=0; n < columns->n && ! found; n++) {
+                        fItem = (psMetadataItem*)(columns->data[n]);
+                        if (strcmp(item->name, fItem->name) == 0) {
+                            found = true;
+                            break;
+                        }
+                    }
+                    if (! found) {
+                        psArrayAdd(columns, columns->nalloc, item);
+                    } else if (item->type == PS_DATA_STRING &&
+                               strlen(fItem->data.V) < strlen(item->data.V)) {
+                        // got to keep the longest string value as to know what size to create the table column
+                        psMemDecrRefCounter(fItem);
+                        columns->data[n] = psMemIncrRefCounter(item);
+                        columns->n++;
+
+                    } else if (item->type == PS_DATA_VECTOR &&
+                               ((psVector*)(fItem->data.V))->n < ((psVector*)(item->data.V))->n) {
+                        psMemDecrRefCounter(fItem);
+                        columns->data[n] = psMemIncrRefCounter(item);
+                        columns->n++;
+                    }
+                } else {
+                    // unsupported type -- treating as an error
+                    psError(PS_ERR_BAD_PARAMETER_TYPE, true,
+                            "Unsupported data type (%d) for Metadata Item '%s' in row %d.",
+                            item->type, item->name, row);
+                    psFree(iter);
+                    psFree(columns);
+                    return false;
+                }
+            }
+            psFree(iter);
+        }
+    }
+
+    if (columns->n == 0) { // no table columns found
+        psError(PS_ERR_BAD_PARAMETER_SIZE, true,
+                "Did not find any column data to write to a table.");
+        psFree(columns);
+        return false;
+    }
+
+    //create list of column names and types.
+    columns->n--;
+    psArray* columnNames = psArrayAlloc(columns->n);
+    psArray* columnTypes = psArrayAlloc(columns->n);
+    for (int n=0; n < columns->n; n++) {
+        columnNames->data[n] = psMemIncrRefCounter(((psMetadataItem*)columns->data[n])->name);
+        columnNames->n++;
+        columnTypes->n++;
+        if ( ! getMetadataTForm((psMetadataItem*)columns->data[n],
+                                (char**)&(columnTypes->data[n]),1) ) {
+            psError(PS_ERR_UNKNOWN, true,
+                    "Failed to determine the FITS data type of '%s' (type=%d).",
+                    columnNames->data[n],
+                    ((psMetadataItem*)columns->data[n])->type);
+            psFree(columns);
+            psFree(columnNames);
+            psFree(columnTypes);
+            return false;
+        }
+    }
+
+    psString extname = NULL;
+    if (header != NULL) {
+        extname = psMetadataLookupStr(NULL, header, "EXTNAME");
+        if ( extname == NULL) {
+            extname = psMetadataLookupStr(NULL, header, "HDUNAME");
+        }
+    }
+
+    if (! after) {
+        if (psFitsGetExtNum(fits) == 0) {
+            // set status to signal fits_insert_img to insert a new primary HDU
+            status = PREPEND_PRIMARY;
+        } else {
+            // move back one to perform an insert after the previous HDU
+            psFitsMoveExtNum(fits, -1, true);
+        }
+    }
+
+    fits_insert_btbl(fits->fd,
+                     table->n, // number of rows in table
+                     columns->n, // number of columns in table
+                     (char**)columnNames->data, // names of the columns
+                     (char**)columnTypes->data, // format of the columns
+                     NULL, // physical unit of columns
+                     extname, // extension name
+                     0,
+                     &status);
+
+    psFree(columnNames);
+    psFree(columnTypes);
+
+
+    // fill in the table elements with data
+    for (int n = 0; n < columns->n; n++) {
+        int row;
+        item = columns->data[n];
+        if (PS_DATA_IS_PRIMITIVE(item->type) ) {
+            psVector* col = psVectorAlloc(table->n, item->type);
+            int dataSize = PSELEMTYPE_SIZEOF(item->type);
+            int dataType;
+            convertPsTypeToFits(item->type, NULL,NULL,&dataType);
+            for (row = 0; row < table->n; row++) {
+                psMetadataItem* dataItem = psMetadataLookup(
+                                               table->data[row],
+                                               item->name);
+                memcpy(&col->data.U8[row*dataSize],&dataItem->data,dataSize);
+            }
+            fits_write_col(fits->fd,
+                           dataType,
+                           n+1, // column number
+                           1, // firstrow
+                           1, // firstelem
+                           table->n, // nelements
+                           col->data.U8,
+                           &status);
+            psFree(col);
+        } else if (item->type == PS_DATA_STRING) {
+            psArray* colArray = psArrayAlloc(table->n);
+            for (row = 0; row < table->n; row++) {
+                colArray->data[row] = psStringCopy(psMetadataLookupStr(NULL,
+                                                   table->data[row],
+                                                   item->name));
+                colArray->n++;
+            }
+            fits_write_col_str(fits->fd,
+                               n+1,
+                               1,
+                               1,
+                               table->n,
+                               (char**)colArray->data,
+                               &status);
+            psFree(colArray);
+        } else if (item->type == PS_DATA_VECTOR) {
+            psVector* vec = (psVector*)(item->data.V);
+            psVector* col = psVectorAlloc(table->n*vec->n, vec->type.type);
+            int dataSize = PSELEMTYPE_SIZEOF(vec->type.type)*vec->n;
+            int dataType;
+            convertPsTypeToFits(vec->type.type, NULL,NULL,&dataType);
+            for (row = 0; row < table->n; row++) {
+                psMetadataItem* dataItem = psMetadataLookup(
+                                               table->data[row],
+                                               item->name);
+                memcpy(&col->data.U8[row*dataSize],
+                       ((psVector*)(dataItem->data.V))->data.U8,
+                       dataSize);
+            }
+            fits_write_col(fits->fd,
+                           dataType,
+                           n+1, // column number
+                           1, // firstrow
+                           1, // firstelem
+                           table->n*vec->n, // nelements
+                           col->data.U8,
+                           &status);
+            psFree(col);
+        }
+        if (status != 0) {
+            char fitsErr[MAX_STRING_LENGTH];
+            (void)fits_get_errstatus(status, fitsErr);
+            psError(PS_ERR_IO, true,
+                    PS_ERRORTEXT_psFits_WRITE_FAILED,
+                    fitsErr);
+            psFree(columns);
+            return false;
+        }
+
+    }
+
+    psFree(columns);
+
+    return true;
+}
+
 bool psFitsUpdateTable(psFits* fits,
                        const psMetadata* data,
Index: /trunk/psLib/src/fits/psFitsTable.h
===================================================================
--- /trunk/psLib/src/fits/psFitsTable.h	(revision 6766)
+++ /trunk/psLib/src/fits/psFitsTable.h	(revision 6767)
@@ -7,6 +7,6 @@
  *  @author Robert DeSonia, MHPCC
  *
- *  @version $Revision: 1.1 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2005-11-14 22:18:30 $
+ *  @version $Revision: 1.2 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2006-04-04 19:52:42 $
  *
  *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
@@ -72,10 +72,11 @@
 );
 
-/** Writes a whole FITS table.  The current HDU type must be either
- *  PS_FITS_TYPE_BINARY_TABLE or PS_FITS_TYPE_ASCII_TABLE.
+/** Writes a whole FITS table. A new HDU of the type BINTABLE is appended
+ *  to the file.
  *
  *  @return bool        TRUE if the write was successful, otherwise FALSE
  *
- *  @see psFitsReadTableRow
+ *  @see psFitsReadTable
+ *  @see psFitsInsertTable
  */
 bool psFitsWriteTable(
@@ -84,4 +85,20 @@
     const psArray* table
     ///< Array of psMetadata items, which contains the output data items of each row.
+);
+
+/** Inserts a whole FITS table. A new HDU of the type BINTABLE is inserted either
+ *  before or after, depending on the AFTER parameter, the current HDU.
+ *
+ *  @return bool        TRUE if the insert/write was successful, otherwise FALSE
+ *
+ *  @see psFitsWriteTable
+ */
+bool psFitsInsertTable(
+    psFits* fits,                  ///< the psFits object
+    const psMetadata* header,      ///< header items for the new HDU.  Can be NULL.
+    const psArray* table,
+    ///< Array of psMetadata items, which contains the output data items of each row.
+    bool after
+    ///< TRUE if insert is done after CHDU, otherwise table is inserted before CHDU
 );
 
@@ -94,5 +111,5 @@
  */
 bool psFitsUpdateTable(
-    psFits* fits,                ///< the psFits object
+    psFits* fits,                      ///< the psFits object
     const psMetadata* data,
     ///< Array of psMetadata items, which contains the output data items of each row.
Index: /trunk/psLib/test/fits/tst_psFits.c
===================================================================
--- /trunk/psLib/test/fits/tst_psFits.c	(revision 6766)
+++ /trunk/psLib/test/fits/tst_psFits.c	(revision 6767)
@@ -6,6 +6,6 @@
 *  @author Robert DeSonia, MHPCC
 *
-*  @version $Revision: 1.18 $ $Name: not supported by cvs2svn $
-*  @date $Date: 2006-02-24 23:43:15 $
+*  @version $Revision: 1.19 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2006-04-04 19:52:47 $
 *
 *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
@@ -118,12 +118,7 @@
                       extname);
 
-        psMetadataAdd(header,PS_LIST_TAIL, "EXTNAME",
-                      PS_DATA_STRING,
-                      "Extension Name",
-                      extname);
-
         // set the pixels in the image
         psBinaryOp(image,image,"=",psScalarAlloc(lcv,PS_TYPE_F32));
-        if (! psFitsWriteImage(fitsFile,header,image,1) ) {
+        if (! psFitsWriteImage(fitsFile,header,image,1,extname) ) {
             psError(PS_ERR_UNKNOWN, false,
                     "Could not write image.");
@@ -152,5 +147,5 @@
     psImage* image = psImageAlloc(16,16,PS_TYPE_F32);
 
-    if (! psFitsWriteImage(fitsFile,NULL,image,1) ) {
+    if (! psFitsWriteImage(fitsFile,NULL,image,1,NULL) ) {
         psError(PS_ERR_UNKNOWN, false,
                 "Could not write PHU image.");
@@ -263,5 +258,5 @@
     // write something to the file, otherwise CFITSIO will complain on close
     psImage* img = psImageAlloc(16,16,PS_TYPE_F32);
-    psFitsWriteImage(fitsFile,NULL,img,1);
+    psFitsWriteImage(fitsFile,NULL,img,1,NULL);
 
     psFree(fitsFile); // psFree should be equivalent to psFitsClose
@@ -284,5 +279,5 @@
 
     // write something to the file, otherwise CFITSIO will complain on close
-    psFitsWriteImage(fitsFile,NULL,img,1);
+    psFitsWriteImage(fitsFile,NULL,img,1,NULL);
 
     psFitsClose(fitsFile);
@@ -305,5 +300,5 @@
 
     // write something to the file, otherwise CFITSIO will complain on close
-    psFitsWriteImage(fitsFile,NULL,img,1);
+    psFitsWriteImage(fitsFile,NULL,img,1,NULL);
 
     psFitsClose(fitsFile);
@@ -821,5 +816,5 @@
     psFitsMoveExtNum(fits,numHDUs/2, false);
 
-    psMetadata* headerSet = psFitsReadHeaderSet(fits);
+    psMetadata* headerSet = psFitsReadHeaderSet(NULL,fits);
 
     if (headerSet == NULL) {
@@ -862,12 +857,5 @@
     }
 
-    psMetadata* set2 = psFitsReadHeaderSet(NULL);
-    if (set2 != NULL) {
-        psError(PS_ERR_UNKNOWN, false,
-                "psFitsReadHeaderSet returned non-NULL given a NULL psFits.");
-        return 10;
-    }
-
-    psMetadata* set3 = psFitsReadHeaderSet(fits);
+    psMetadata* set3 = psFitsReadHeaderSet(NULL,fits);
     if (set3 == NULL) {
         psError(PS_ERR_UNKNOWN, false,
@@ -902,9 +890,12 @@
     }
 
-
+    set3 = psFitsReadHeaderSet(set3,NULL);
+    if (set3 != NULL) {
+        psError(PS_ERR_UNKNOWN, false,
+                "psFitsReadHeaderSet returned non-NULL given a NULL psFits.");
+        return 10;
+    }
 
     psFree(headerSet);
-    psFree(set3);
-    // set2 should have been freed by psFitsReadHeaderSet upon an error.
 
     psFitsClose(fits);
@@ -1434,18 +1425,17 @@
         img4 = psImageCopy(img4,img3,PS_TYPE_##TYP); \
         psFits* fits = psFitsOpen(filename, "w"); \
-        psRegion region = {0,0,0,0}; \
-        if (! psFitsWriteImage(fits, NULL, img, 2)) { \
+        if (! psFitsWriteImage(fits, NULL, img, 2, NULL)) { \
             psError(PS_ERR_UNKNOWN, true,"Failed to write test image %s",filename); \
             return 1; \
         } \
-        if (! psFitsUpdateImage(fits,img3, region, 1)) { \
+        if (! psFitsUpdateImage(fits,img3, 0,0, 1)) { \
             psError(PS_ERR_UNKNOWN, true,"Failed to write test image %s",filename); \
             return 2; \
         } \
-        if (! psFitsWriteImage(fits,NULL, img3, 2)) { \
+        if (! psFitsWriteImage(fits,NULL, img3, 2, NULL)) { \
             psError(PS_ERR_UNKNOWN, true,"Failed to write test image %s",filename); \
             return 3; \
         } \
-        if (! psFitsUpdateImage(fits,img,region, 1)) { \
+        if (! psFitsUpdateImage(fits,img, 0, 0, 1)) { \
             psError(PS_ERR_UNKNOWN, true,"Failed to write test image %s",filename); \
             return 4; \
@@ -1588,12 +1578,11 @@
     GENIMAGE(img2,m,n,F32,row+2*col);
     mkdir("tmpImages",0777);
-    psRegion region = {0,0,0,0};
     psFits* fits = psFitsOpen("tmpImages/writeTest.fits","w");
 
-    if (! psFitsWriteImage(fits, NULL, img,1)) {
+    if (! psFitsWriteImage(fits, NULL, img,1, NULL)) {
         psError(PS_ERR_UNKNOWN, true,"Couldn't write writeTest.fits.");
         return 14;
     }
-    if (! psFitsUpdateImage(fits, img2, region, 0)) {
+    if (! psFitsUpdateImage(fits, img2, 0, 0, 0)) {
         psError(PS_ERR_UNKNOWN, true,"Couldn't update writeTest.fits.");
         return 15;
@@ -1604,4 +1593,6 @@
     // Did it really overwrite the pixel values?  Let's read it in and see.
     psFitsClose(fits);
+
+    psRegion region = {0,0,0,0};
     fits = psFitsOpen("tmpImages/writeTest.fits","r");
     img = psFitsReadImage(NULL, fits, region, 0);
@@ -1628,5 +1619,5 @@
     */
     psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message because input image is null.");
-    if ( psFitsWriteImage(fits,NULL,NULL, 1) ) {
+    if ( psFitsWriteImage(fits,NULL,NULL, 1, NULL) ) {
         psError(PS_ERR_UNKNOWN, true,"psImageWriteSection did not return false when input image is NULL.");
         return 20;
Index: /trunk/psLib/test/fits/verified/tst_psFits.stderr
===================================================================
--- /trunk/psLib/test/fits/verified/tst_psFits.stderr	(revision 6766)
+++ /trunk/psLib/test/fits/verified/tst_psFits.stderr	(revision 6767)
@@ -201,5 +201,5 @@
 <DATE><TIME>|<HOST>|I|testImageWrite
     Following should generate an error message because input image is null.
-<DATE><TIME>|<HOST>|E|psFitsWriteImage (FILE:LINENO)
+<DATE><TIME>|<HOST>|E|psFitsInsertImage (FILE:LINENO)
     The input psImage was NULL.  Need a non-NULL psImage for operation to be performed.
 
Index: /trunk/psLib/test/imageops/tst_psImageGeomManip.c
===================================================================
--- /trunk/psLib/test/imageops/tst_psImageGeomManip.c	(revision 6766)
+++ /trunk/psLib/test/imageops/tst_psImageGeomManip.c	(revision 6767)
@@ -6,6 +6,6 @@
  *  @author Robert DeSonia, MHPCC
  *
- *  @version $Revision: 1.5 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2005-11-14 22:18:46 $
+ *  @version $Revision: 1.6 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2006-04-04 19:52:54 $
  *
  *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
@@ -588,17 +588,17 @@
         sBiOut = psImageRotate(sBiOut,sImg,radianRot,-1.0,PS_INTERPOLATE_BILINEAR);
 
-        if (! psFitsWriteImage(fOutFile, NULL, fOut, 1) ) {
+        if (! psFitsWriteImage(fOutFile, NULL, fOut, 1, NULL) ) {
             psError(PS_ERR_UNKNOWN, true,"Can not write fOut.");
             return 20;
         }
-        if (! psFitsWriteImage(sOutFile, NULL, sOut, 1) ) {
+        if (! psFitsWriteImage(sOutFile, NULL, sOut, 1, NULL) ) {
             psError(PS_ERR_UNKNOWN, true,"Can not write sOut.");
             return 21;
         }
-        if (! psFitsWriteImage(fBiOutFile, NULL, fBiOut, 1) ) {
+        if (! psFitsWriteImage(fBiOutFile, NULL, fBiOut, 1, NULL) ) {
             psError(PS_ERR_UNKNOWN, true,"Can not write fBiOut.fits.");
             return 40;
         }
-        if (! psFitsWriteImage(sBiOutFile, NULL, sBiOut, 1) ) {
+        if (! psFitsWriteImage(sBiOutFile, NULL, sBiOut, 1, NULL) ) {
             psError(PS_ERR_UNKNOWN, true,"Can not write sBiOut.fits.");
             return 41;
Index: /trunk/psLib/test/sys/tst_psMemory.c
===================================================================
--- /trunk/psLib/test/sys/tst_psMemory.c	(revision 6766)
+++ /trunk/psLib/test/sys/tst_psMemory.c	(revision 6767)
@@ -6,6 +6,6 @@
 *  @author Robert DeSonia, MHPCC
 *
-*  @version $Revision: 1.7 $ $Name: not supported by cvs2svn $
-*  @date $Date: 2006-01-26 21:10:22 $
+*  @version $Revision: 1.8 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2006-04-04 19:52:55 $
 *
 *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
@@ -583,5 +583,5 @@
     fits = psFitsOpen("test.fits","w");
     psImage* img = psImageAlloc(16,16,PS_TYPE_F32);
-    psFitsWriteImage(fits,NULL,img,1);
+    psFitsWriteImage(fits,NULL,img,1,NULL);
     psFree(img);
     if ( !psMemCheckType(PS_DATA_FITS, fits) ) {
