Index: branches/eam_branches/ipp-20110213/Ohana/src/tools/src/ftable.c
===================================================================
--- branches/eam_branches/ipp-20110213/Ohana/src/tools/src/ftable.c	(revision 30681)
+++ branches/eam_branches/ipp-20110213/Ohana/src/tools/src/ftable.c	(revision 30698)
@@ -3,5 +3,5 @@
 # include "inttypes.h"
 
-char *print_table_row (char *row, Header *header);
+int print_table_rows (FTable *table, int start, int Nrows);
 FILE *load_extension (char *file, int Nextend, char *Extname, Header *header);
 void print_column (FTable *table, int Column, char *Colname);
@@ -13,7 +13,7 @@
 int main (int argc, char **argv) {
 
-  off_t i, Nx, Ny, Nbytes, Nread, Row;
+  off_t Nx, Ny, Nbytes, Nread, Row;
   int N, Nextend, Column, ListExtname, Layout;
-  char *Extname, *Colname, *line, ttype[80];
+  char *Extname, *Colname, ttype[80];
   FTable table;
   Header header;
@@ -104,45 +104,148 @@
   /* print a row */
   if (Row) {
-    line = print_table_row (&table.buffer[Nx*Row], table.header);
-    fprintf (stdout, "%s\n", line);
-    free (line);
+    if (!print_table_rows (&table, Row, 1)) {
+      fprintf (stderr, "failed to print row\n");
+    }
     exit (0);
   }
 
   /* print complete table */
-  for (i = 0; i < Ny; i++) {
-    line = print_table_row (&table.buffer[Nx*i], table.header);
-    fprintf (stdout, "%s\n", line);
-    free (line);
+  if (!print_table_rows (&table, 0, Ny)) {
+    fprintf (stderr, "failed to print table\n");
   }    
   exit (0);
 }
 
-/* print an ASCII table to a row with single spaces separating value */
-char *print_table_row (char *row, Header *header) {
+# define SWAP_BYTE(BYTE)					\
+  tmp = BYTE[0]; BYTE[0] = BYTE[1]; BYTE[1] = tmp;
+# define SWAP_WORD(BYTE) \
+  tmp = BYTE[0]; BYTE[0] = BYTE[3]; BYTE[3] = tmp; \
+  tmp = BYTE[1]; BYTE[1] = BYTE[2]; BYTE[2] = tmp;
+# define SWAP_DBLE(BYTE) \
+  tmp = BYTE[0]; BYTE[0] = BYTE[7]; BYTE[7] = tmp; \
+  tmp = BYTE[1]; BYTE[1] = BYTE[6]; BYTE[6] = tmp; \
+  tmp = BYTE[2]; BYTE[2] = BYTE[5]; BYTE[5] = tmp; \
+  tmp = BYTE[3]; BYTE[3] = BYTE[4]; BYTE[4] = tmp;
+
+/* print Nrows of the given table starting at row 'start' */
+int print_table_rows (FTable *table, int start, int Nrows) {
   
-  off_t Nx;
-  int i, j, Nfields, Nbytes, Nvals, Oout, Oin;
-  char field[16], type[16], format[16], *line;
-
-  gfits_scan (header, "NAXIS1",  OFF_T_FMT, 1,  &Nx);
-  gfits_scan (header, "TFIELDS", "%d", 1, &Nfields);
+  off_t Nx, Ny;
+  int n, i, j, Nfields, *Nbyte, *Nvals, Oout, Oin, Nv, Nb, byte, status;
+  char field[16], **types, format[16], type[80], *line, *row, tmp;
+  double *Tzero, *Tscal;
+
+  gfits_scan (table->header, "NAXIS1",  OFF_T_FMT, 1,  &Nx);
+  gfits_scan (table->header, "NAXIS2",  OFF_T_FMT, 1,  &Ny);
+  gfits_scan (table->header, "TFIELDS", "%d", 1, &Nfields);
+
+  if (start <   0) return FALSE;
+  if (start >= Ny) return FALSE;
+  if (Nrows <   0) return FALSE;
+  if (start + Nrows > Ny) return FALSE;
 
   /* assume we have one space per byte column */
-  ALLOCATE (line, char, 2*Nx + 1);
-
-  Oin = Oout = 0;
-  for (i = 1; i <= Nfields; i++) {
-    sprintf (field, "TFORM%d", i);
-    gfits_scan (header, field, "%s", 1, format); /* get field format */
-    gfits_table_format (format, type, &Nvals, &Nbytes);    /* convert to c-style */
-    memcpy (&line[Oout], &row[Oin], Nvals*Nbytes);
-    for (j = 0; j < Nvals*Nbytes; j++) if (line[Oout+j] == 0) line[Oout+j] = ' ';
-    line[Oout+Nvals*Nbytes] = ' ';
-    Oout += Nvals*Nbytes + 1;
-    Oin += Nvals*Nbytes;
-  }
-
-  return (line);
+  ALLOCATE (line, char, MAX(2*Nx+1,512));
+
+  ALLOCATE (types, char *, Nfields);
+  ALLOCATE (Nvals, int, Nfields);
+  ALLOCATE (Nbyte, int, Nfields);
+  ALLOCATE (Tzero, double, Nfields);
+  ALLOCATE (Tscal, double, Nfields);
+
+  // determine the layout of the columns
+  for (i = 0; i < Nfields; i++) {
+    sprintf (field, "TFORM%d", i+1);
+    gfits_scan (table->header, field, "%s", 1, format); /* get field format */
+
+    if (Binary)  {
+      gfits_bintable_format (format, type, &Nv, &Nb);    /* convert to c-style */
+
+      sprintf (field, "TZERO%d", i+1);
+      status = gfits_scan (table[0].header, field, "%lf", 1, &Tzero[i]);       /* get field format */
+      if (!status) Tzero[i] = 0.0;
+      
+      sprintf (field, "TSCAL%d", i+1);
+      status = gfits_scan (table[0].header, field, "%lf", 1, &Tscal[i]);       /* get field format */
+      if (!status) Tscal[i] = 1.0;
+    } else {
+      gfits_table_format (format, type, &Nv, &Nb);    /* convert to c-style */
+    }
+    
+    types[i] = strcreate (type);
+    Nvals[i] = Nv;
+    Nbyte[i] = Nb;
+  }
+
+  for (n = start; n < start + Nrows; n++) {
+
+    row = &table->buffer[Nx*n];
+
+    if (Binary) {
+      byte = 0;  // counter for byte element of this row
+      for (i = 0; i < Nfields; i++) {
+	int found = FALSE;
+	if (!strcmp (types[i], "char")) {
+	  memcpy (line, &row[byte], Nvals[i]*Nbyte[i]);
+	  fprintf (stdout, "%s ", line);
+	  found = TRUE;
+	} else {
+	  for (j = 0; j < Nvals[i]; j++) {
+	    memcpy (line, &row[byte + Nbyte[i]*j], Nbyte[i]);
+	    if (!strcmp (types[i], "int")) {
+# ifdef BYTE_SWAP
+	      SWAP_WORD (line);
+# endif
+	      fprintf (stdout, "%d ", (int)(*(int *)line * Tscal[i] + Tzero[i]));
+	      found = TRUE;
+	    }
+	    if (!strcmp (types[i], "short")) {
+# ifdef BYTE_SWAP
+	      SWAP_BYTE (line);
+# endif
+	      fprintf (stdout, "%d ", (int)(*(short *)line * Tscal[i] + Tzero[i]));
+	      found = TRUE;
+	    }
+	    if (!strcmp (types[i], "int64_t")) {
+# ifdef BYTE_SWAP
+	      SWAP_DBLE (line);
+# endif
+	      fprintf (stdout, "%" PRId64" ",  (int64_t)(*(int64_t*)line * Tscal[i] + Tzero[i]));
+	      found = TRUE;
+	    }
+	    if (!strcmp (types[i], "float")) {
+# ifdef BYTE_SWAP
+	      SWAP_WORD (line);
+# endif
+	      fprintf (stdout, "%e ", (*(float *)line * Tscal[i] + Tzero[i]));
+	      found = TRUE;
+	    }
+	    if (!strcmp (types[i], "double")) {
+# ifdef BYTE_SWAP
+	      SWAP_DBLE (line);
+# endif
+	      fprintf (stdout, "%e ", (*(double *)line * Tscal[i] + Tzero[i]));
+	      found = TRUE;
+	    }
+	  }
+	}
+	byte += Nvals[i]*Nbyte[i];
+	if (!found) {
+	  fprintf (stderr, "failed to find format for %d : %s\n", i, types[i]);
+	}
+      }
+    } else {
+      for (i = 0; i < Nfields; i++) {
+	memcpy (&line[Oout], &row[Oin], Nvals[i]*Nbyte[i]);
+	for (j = 0; j < Nvals[i]*Nbyte[i]; j++) if (line[Oout+j] == 0) line[Oout+j] = ' ';
+	line[Oout+Nvals[i]*Nbyte[i]] = ' ';
+	Oout += Nvals[i]*Nbyte[i] + 1;
+	Oin += Nvals[i]*Nbyte[i];
+      }
+      fprintf (stdout, "%s ", line);
+    }
+    fprintf (stdout, "\n");
+  }
+  return (TRUE);
 }
 
@@ -325,8 +428,9 @@
     sprintf (field, "TFORM%d", i);
     gfits_scan (header, field, "%s", 1, format);
-    if (Binary) 
+    if (Binary)  {
+      gfits_bintable_format (format, type, &Nv, &Nb);
+    } else {
       gfits_table_format (format, type, &Nv, &Nb);
-    else 
-      gfits_bintable_format (format, type, &Nv, &Nb);
+    }
     Nstart += Nv*Nb;
   }
@@ -334,9 +438,9 @@
   sprintf (field, "TFORM%d", Column);
   gfits_scan (header, field, "%s", 1, format);
-  if (Binary) 
+  if (Binary)  {
     gfits_bintable_format (format, type, &Nv, &Nb);    /* convert to c-style */
-  else 
+  } else {
     gfits_table_format (format, type, &Nv, &Nb);    /* convert to c-style */
-
+  }
   ALLOCATE (line, char, Nv*Nb + 1);
 
