/*===========================================================================
  Copyright (C) 1995-2005 European Southern Observatory (ESO)
 
  This program is free software; you can redistribute it and/or 
  modify it under the terms of the GNU General Public License as 
  published by the Free Software Foundation; either version 2 of 
  the License, or (at your option) any later version.
 
  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.
 
  You should have received a copy of the GNU General Public 
  License along with this program; if not, write to the Free 
  Software Foundation, Inc., 675 Massachusetts Ave, Cambridge, 
  MA 02139, USA.
 
  Correspondence concerning ESO-MIDAS should be addressed as follows:
	Internet e-mail: midas@eso.org
	Postal address: European Southern Observatory
			Data Management Division 
			Karl-Schwarzschild-Strasse 2
			D 85748 Garching bei Muenchen 
			GERMANY
===========================================================================*/

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.IDENT      fitswdm.c
.LAUGUAGE   C
.AUTHOR     P.Grosbol   ESO/IPG
.KEYWORDS   FITS prime data matrix
.COMMENT    write FITS prime data matrix
.VERSION    1.0  1988-Dec-10 : Creation,   PJG 
.VERSION    1.1  1989-Jan-12 : Modify format flag,   PJG 
.VERSION    1.2  1989-Nov-07 : Include I*4 and R*8 format,   PJG 
.VERSION    1.3  1990-Feb-04 : Change call-seq. for cv-routine, PJG 
.VERSION    2.0  1991-Mar-17 : Change structures, PJG 
.VERSION    2.1  1991-May-15 : NULL fill if too few data, PJG 
.VERSION    2.2  1993-Oct-26 : Update for new SC and prototypes, PJG 
.VERSION    2.3  1994-Jun-28 : Include D_UI2_FORAMT, PJG 
.VERSION    2.4  1995-Sep-27 : Correct buffer size for D_R*_FORMAT, PJG

 051111		last modif

---------------------------------------------------------------------*/

#include   <computer.h>
#include   <fitsfmt.h>
#include   <fitsdef.h>
#include   <fitsextvals.h>
#include   <midas_def.h>

#define    BSIZE        28800   /* size of internal buffer            */

/*

*/

int fitswdm (mfd, mff, ffmt)
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE       write FITS prime data matrix
.RETURN        return status  0:OK, -1:error
---------------------------------------------------------------------*/
int mfd;		/* IN: MIDAS file number              */
int mff;		/* IN: MIDAS file data format         */
int ffmt;		/* IN: FITS file format               */

{
unsigned char *pb;
char  *osmmget();

short *ps;
unsigned short *pu;

int *pi, n, i, nn, i32, ns, np, nb;
int dsize, ioff, err, bscal_flag;

float *pf;

double *pd, bfac, boff;

SDEF *sdef, *fitsbdf();

union
   {
   unsigned char *b;
   char *c;
   short *s;
   unsigned short *u;
   int *i;
   float *f;
   double *d;
   } p;



p.c = osmmget (BSIZE);          /* get internal buffer */
if (!p.b)
   {
   SCTMES(M_RED_COLOR,"Error: cannot allocate internal buffer");
   SCFCLO (mfd);
   return -1;
   }

sdef = fitsbdf (-1, 0, "", &bscal_flag);
bfac = 1.0 / sdef->bfac;
boff = sdef->boff;
dsize = sdef->dsize;

switch (mff)
   {                            /* initiate depending on data format  */
  case D_I1_FORMAT:
   nb = BSIZE;
   break;

  case D_I2_FORMAT:
   nb = BSIZE / 2;
   break;

  case D_UI2_FORMAT:
   nb = BSIZE / 2;
   break;

  case D_I4_FORMAT:
   nb = BSIZE / 4;
   break;

  case D_R4_FORMAT:
   nb = BSIZE / 4;
   i32 = (ffmt == 'B') ? 1 : 0;
   break;

  case D_R8_FORMAT:
   nb = BSIZE / 8;
   i32 = (ffmt == 'B') ? 1 : 0;
   break;

  default:
   SCTMES(M_RED_COLOR,"Error: None supported file data format");
   SCFCLO (mfd);
   osmmfree (p.c);
   return -1;
   }

err = 0;
switch (mff)
   {                            /* convert data to FITS format  */
  case D_I1_FORMAT:
   ioff = 1;
   while (ioff <= dsize)
      {                         /* read-convert-write data      */
      n = (dsize - ioff < nb) ? dsize - ioff + 1 : nb;
      SCFGET (mfd, ioff, n, &ns, (char *) p.b);

      if (ns < n)
         {                      /* NULL fill if needed  */
         pb = p.b + ns;
         i = n - ns;
         while (i--)
         *pb++ = 255;
         }
      ioff += n;
      if (dwrite (p.c, ns) != ns)
         {
         err = -1;
         break;
         }
      }
   break;

  case D_I2_FORMAT:
   ioff = 1;
   while (ioff <= dsize)
      {                         /* read-convert-write data      */
      n = (dsize - ioff < nb) ? dsize - ioff + 1 : nb;
      SCFGET (mfd, ioff, n, &ns, (char *) p.u);

      if (ns < n)
         {                      /* NULL fill if needed  */
         ps = p.s + ns;
         i = n - ns;
         while (i--) toNULLSHORT (*ps++);
         }
      ioff += n;
      np = ns + ns;
      if (!same_comp_i2) cvi2 (p.s, ns, 1);

      if (dwrite (p.c, np) != np)
         {
         err = -1;
         break;
         }
      }
   break;

  case D_UI2_FORMAT:
   ioff = 1;
   while (ioff <= dsize)
      {                         /* read-convert-write data      */
      n = (dsize - ioff < nb) ? dsize - ioff + 1 : nb;
      SCFGET (mfd, ioff, n, &ns, (char *) p.u);
      i = ns;
      pu = p.u;
      ps = p.s;
      while (i--)
         {
         nn = (int) (*pu++) - 32768;
         *ps++ = (unsigned int) nn;
         }
      if (ns < n)
         {                      /* NULL fill if needed  */
         ps = p.s + ns;
         i = n - ns;
         while (i--) toNULLSHORT (*ps++);
         }
      ioff += n;
      np = ns + ns;				/* was: = 2 * ns; */
      if (!same_comp_i2) cvi2 (p.s, ns, 1);

      if (dwrite (p.c, np) != np)
         {
         err = -1;
         break;
         }
      }
   break;

  case D_I4_FORMAT:
   ioff = 1;
   while (ioff <= dsize)
      {                         /* read-convert-write data      */
      n = (dsize - ioff < nb) ? dsize - ioff + 1 : nb;
      SCFGET (mfd, ioff, n, &ns, (char *) p.i);

      if (ns < n)
         {                      /* NULL fill if needed  */
         pi = p.i + ns;
         i = n - ns;
         while (i--) toNULLINT (*pi++);
         }
      ioff += n;
      np = 4 * ns;
      if (!same_comp_i4) cvi4 (p.i, ns, 1);

      if (dwrite (p.c, np) != np)
         {
         err = -1;
         break;
         }
      }
   break;

  case D_R4_FORMAT:
   ioff = 1;
   while (ioff <= dsize)
      {                         /* read-convert-write data      */
      n = (dsize - ioff < nb) ? dsize - ioff + 1 : nb;
      SCFGET (mfd, ioff, n, &ns, (char *) p.f);

      if (ns < n)
         {                      /* NULL fill if needed  */
         pf = p.f + ns;
         i = n - ns;
         while (i--) toNULLFLOAT (*pf++);
         }
      pf = p.f;
      ioff += n;
      np = 4 * ns;
      if (i32)
         {                      /* 32-bit integer format        */
         pi = p.i;
         n = ns;
         while (n--)
         if (isNULLFLOAT (*pf))
            {
            toNULLINT (*pi++);
            *pf++;
            }
         else
            *pi++ = bfac * (*pf++ - boff);
         if (!same_comp_i4) cvi4 (p.i, ns, 1);

         if (dwrite (p.c, np) != np)
            {
            err = -1;
            break;
            }
         }
      else
         {
         cvr4 (pf, ns, 1);
         if (dwrite ((char *) pf, np) != np)
            {
            err = -1;
            break;
            }
         }
      }
   break;

  case D_R8_FORMAT:
   ioff = 1;
   while (ioff <= dsize)
      {                         /* read-convert-write data      */
      n = (dsize - ioff < nb) ? dsize - ioff + 1 : nb;
      SCFGET (mfd, ioff, n, &ns, (char *) p.d);

      if (ns < n)
         {                      /* NULL fill if needed  */
         pd = p.d + ns;
         i = n - ns;
         while (i--) toNULLDOUBLE (*pd++);
         }
      pd = p.d;
      ioff += n;
      np = (i32) ? 4 * ns : 8 * ns;
      if (i32)
         {                      /* 32-bit integer format        */
         pi = p.i;
         n = ns;
         while (n--)
         if (isNULLFLOAT (*pd))
            {
            toNULLINT (*pi++);
            *pd++;
            }
         else
            *pi++ = bfac * (*pd++ - boff);
         if (!same_comp_i4) cvi4 (p.i, ns, 1);

         if (dwrite (p.c, np) != np)
            {
            err = -1;
            break;
            }
         }
      else
         {
         cvr8 (pd, ns, 1);
         if (dwrite ((char *) pd, np) != np)
            {
            err = -1;
            break;
            }
         }
      }
   break;
   }

dbfill ('\0');
osmmfree (p.c);
if (err)
   {
   SCTMES(M_RED_COLOR,"Error: wrong byte-count in write to device");
   SCFCLO (mfd);
   }
return err;
}
