/*===========================================================================
  Copyright (C) 1995-2006 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
===========================================================================*/

/*+++++++++++++++++++++++ SC interface module SCF +++++++++++++++++++++++
.LANGUAGE C
.IDENTIFICATION Module SCF
.AUTHOR         K. Banse 		ESO - Garching
.KEYWORDS       standard interfaces, bulk data files
.ENVIRONMENT    VMS and UNIX
.COMMENTS 
holds SCFGET, SCFPUT, SCFDEL, SCFXDEL, SCFCRE, SCFXCR, SCFRNM
.REMARKS
opening modes are: F_I_MODE, F_O_MODE, F_IO_MODE, F_X_MODE.                
data types are: D_R4_FORMAT, D_I2_FORMAT, D_I1_FORMAT, D_OLD_FORMAT.         
filetype no's are: F_IMA_TYPE, F_TBL_TYPE, F_FIT_TYPE.              
 
.VERSION  [1.20] 871109: creation
 060531		last modif

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

#include <fileexts.h>

#include <osyparms.h>
 
/*

*/

int SCFGET(imno,felem,size,actsize,bufadr)

/*++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE
read data from disk frame into memory 
.ALGORITHM
synchronous disk I/O
.RETURNS
return status ( 0 = o.k )
--------------------------------------------------------*/

int   imno;		/* IN : file no. of data frame */
int   felem;		/* IN : 1st pixel to be accessed in data space */
int   size;    		/* IN : number of data values (pixels) to be read 
				if < 1, take all available data*/
int   *actsize; 	/* OUT: actual no. of pixels read */
char	*bufadr;	/* IN: address of data buffer  */

{
int  status;
register int  nr;

char   *pntrs[2];

struct FCT_STRUCT  *fctpntr;



 
/*  check 'imno' + 'felem' */
 
if ( (imno < 0) || (imno >= FCT.MAXENT) || (felem <= 0) )
   {
   status = ERR_INPINV;
   goto end_of_it;
   }


fctpntr = FCT.ENTRIES + imno;

if (fctpntr->FILTYP > 0)		/* FITS file */
   {
   char  *datpntr, *zpntr;
   int   mm, felbytes, nbytes;


   if (fctpntr->DATTYP != fctpntr->FORMAT)
      nbytes = get_byte(fctpntr->DATTYP);
   else
      nbytes = fctpntr->NOBYTE;

   felem --;
   felbytes = felem * nbytes;

   /*
   printf
   ("SCFGET: name = %s, BDADDR[0] = %x\n",fctpntr->NAME,fctpntr->BDADDR[0]);
   */

   if (fctpntr->BDADDR[0] != (char *) 0)
      {
      datpntr = fctpntr->BDADDR[0] + felbytes;
      mm = fctpntr->KAUX[1];
      }
   else
      {
      status = SCFMAP(imno,F_I_MODE,1,-1,&mm,&datpntr);
      if (status != ERR_NORMAL) goto end_of_it;
      
      datpntr += felbytes;
      }

   *actsize = mm - felem;
   if (*actsize > 0)
      {
      if (size < 1) size = fctpntr->SIZE;
      if (*actsize > size) *actsize = size;
      zpntr = bufadr;

      if (fctpntr->FITSOUT == 'Y')
         {			/* we are called from fitswdm() via SCFSAV() */
         if (fctpntr->DATTYP != fctpntr->FORMAT)
            {
            conv_pix(bufadr,datpntr,fctpntr->FORMAT,fctpntr->DATTYP,*actsize);
            return (ERR_NORMAL);
            }
         fctpntr->FITSOUT = ' ';
         }

      /* same data format in memory and in FITS file */

      for (nr=0; nr<((*actsize)*nbytes); nr++) *zpntr++ = *datpntr++;
      return (ERR_NORMAL);
      }

   status = ERR_INPINV;
   }

else
   {
   if (fctpntr->ACCESS == 'X')
      {
      felem --;
      *actsize = fctpntr->SIZE - felem;

      if ( (fctpntr->DATTYP == fctpntr->FORMAT) &&
           (fctpntr->BDADDR[0] != (char *) 0) &&
           (*actsize > 0) )
         {
         char  *datpntr, *zpntr;

         datpntr = fctpntr->BDADDR[0] + (felem * fctpntr->NOBYTE);
         if (size < 1) size = fctpntr->SIZE;
         if (*actsize > size) *actsize = size;

         zpntr = bufadr;
         for (nr=0; nr<((*actsize)*fctpntr->NOBYTE); nr++)
            *zpntr++ = *datpntr++;
         return (ERR_NORMAL);
         }

      status = ERR_INPINV;
      }
   else 
      {
      if (fctpntr->DATTYP != fctpntr->FORMAT)
         {				/* check if data type mismatch */
         pntrs[0] = bufadr;
         status = conv_dat(3,imno,felem,size,actsize,pntrs);
         }
      else
         status = rddisk(imno,felem,size,actsize,bufadr);
      if (status == ERR_NORMAL) return ERR_NORMAL;
      }
   }


end_of_it:
MID_E2(10,imno,"...",status,1);
return (status);
}	
/*

*/

int SCFPUT(imno,felem,size,bufadr)

/*++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE
write data from memory into disk frame 
.ALGORITHM
synchronous disk I/O
.RETURNS
return status ( 0 = o.k )
--------------------------------------------------------*/

int   imno		/* IN : file no. of data frame */;
int   felem	/* IN : 1st pixel to be accessed in data space */;
int   size    	/* IN : no. of data values (pixels) to be written  */;
char	*bufadr;	/* IN: address of data buffer  */

{
int  status, mm;

char   *pntrs[2];

struct FCT_STRUCT  *fctpntr;




/*  check 'imno' + 'felem' + 'size' */
 
if ( (imno < 0) || (imno >= FCT.MAXENT) || (felem <= 0) || (size <= 0) )
   {
   status = ERR_INPINV;
   goto end_of_it;
   }


fctpntr = FCT.ENTRIES + imno;

if (fctpntr->PROT == 2) 
   {
   status = ERR_FILPRO;
   goto end_of_it;
   }


if (fctpntr->LINK[0] == 2) 
   fctpntr->ACCESS = 'O';		/* if son, we update later on ... */


if (fctpntr->FILTYP > 0)               /* FITS file */
   {
   char  *datpntr, *zpntr;
   int   mm, felbytes, nbytes;

   if (fctpntr->DATTYP != fctpntr->FORMAT)
      nbytes = get_byte(fctpntr->DATTYP);
   else
      nbytes = fctpntr->NOBYTE;

   felem --;
   felbytes = felem * nbytes;
                                            /*
                                            printf
                                            ("SCFPUT: name = %s, 
					    BDADDR[0] = %x\n",fctpntr->NAME,
                                            fctpntr->BDADDR[0]);
                                            */
   if (fctpntr->BDADDR[0] != (char *) 0)
      {						/* already mapped in */
      datpntr = fctpntr->BDADDR[0] + felbytes;
      mm = fctpntr->KAUX[1];
      fctpntr->ACCESS = 'O';			/* ensure update at SCFCLO */
      }
   else
      {
      status = SCFMAP(imno,F_O_MODE,1,-1,&mm,&datpntr);
      if (status != ERR_NORMAL) goto end_of_it;

      datpntr += felbytes;
      }

   if (felem+size <= mm)
      {
      register int   nr;

      zpntr = bufadr;
      for (nr=0; nr<((size)*nbytes); nr++) *datpntr++ = *zpntr++;
      return ERR_NORMAL;
      }

   status = ERR_INPINV;
   }

else
   {
                                            /*
                                            printf
                                            ("SCFPUT: DATTYP = %d, 
                                            FORMAT= %d\n", fctpntr->DATTYP,
                                            fctpntr->FORMAT);
                                            */
   if (fctpntr->DATTYP != fctpntr->FORMAT)
      {					/* check if data type mismatch */
      pntrs[0] = bufadr;
      status = conv_dat(2,imno,felem,size,&mm,pntrs);
      }
   else
      status = wrdisk(imno,felem,size,bufadr);

   if (status == ERR_NORMAL) return ERR_NORMAL;
   }


end_of_it:
MID_E2(11,imno,"...",status,1);
return (status);
}	
/*

*/

int SCFXDEL(imno)

/*++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE
delete a frame
.ALGORITHM
use os-modules to do the job
.RETURNS
return status ( 0 = o.k )
--------------------------------------------------*/

int   imno;    /* IN : frame id of file */

{
char   *mypntr, temp[200];

int   status;

struct FCT_STRUCT  *fctpntr;

extern int  osfdelete();




/*  obtain file name  */
 
mypntr = &temp[10];		/* because of eventual error message ... */
status = MID_RETNAM(imno,mypntr,120);

if (status != ERR_NORMAL)
   {
   (void) strcpy(mypntr,"invalid file id...");
   status = 1;
   }

else
   {
   fctpntr = FCT.ENTRIES + imno;
   fctpntr->CATALOG[1] = 'N';		/* we do not add this file to a catal */
   if (fctpntr->CATALOG[0] == 'T')
      status = TCTCLO(imno);
   else
      status = SCFCLO(imno);


   /*  and delete it  */
 
   status = osfdelete(mypntr);
   }

if (status == 0)
   return (ERR_NORMAL);
else
   {
   (void) strncpy(temp,"SCFxDEL: ",9);
   MID_ERROR("FSY",temp,status,1);
   return (ERR_INPINV);
   }
}
/*

*/

int SCFDEL(name)

/*++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE
delete a frame
.ALGORITHM
use FSY modules to do the job
.RETURNS
return status ( 0 = o.k )
--------------------------------------------------*/

char   *name    /* IN : name of object */;

{
char   *mypntr, temp[200];

int   mm, namtyp, part_no;
int   status;

struct FCT_STRUCT  *fctpntr;

extern int  osfdelete();




/*  check file name  */
 
mypntr = &temp[8];		/* because of eventual error message ... */
CGN_CLEANF(name,0,mypntr,FCT_NAME_LEN,&namtyp,&part_no);


mm = MID_FINDFR(mypntr);		/*  look, if file still in FCT  */
if (mm >= 0) 
   {
   fctpntr = FCT.ENTRIES + mm;
   fctpntr->CATALOG[1] = 'N';		/* we do not add this file to a catal */
   status = SCFCLO(mm);
   }


/*  and delete it  */
 
status = osfdelete(mypntr);

if (status == 0)
   return (ERR_NORMAL);
else
   {
   (void) strncpy(temp,"SCFDEL: ",8);
   MID_ERROR("FSY",temp,status,1);
   return (ERR_INPINV);
   }
}
/*

*/

int SCFCRE(name,dattype,iomode,filtype,size,imno)
/*++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE
create an object of given type
.ALGORITHM
wrapper for SCFXCR()
.RETURNS
return status ( 0 = o.k )
--------------------------------------------------*/

char   *name       /* IN: name of object */;
int dattype;  /* IN: data types as defined in Module header  */
int iomode;   /* IN: opening mode, e.g. F_O_MODE, ...   */
int filtype;  /* IN: filetype no., e.g. F_TBL_TYPE, ... */
int size	   /* IN: size of object = no. of data values in file */;
int *imno	   /* OUT: file no.  */;

{
int  optio[4];
size_t sizze;


optio[0] = 0;
sizze = (size_t) size;

return SCFXCR(name,dattype,iomode,filtype,sizze,optio,imno);
}

/*

*/

int SCFXCR(name,dattype,iomode,filtype,sizze,optio,imno)
/*++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE
create an object of given type
.ALGORITHM
depending upon optio we initialize descr's or clone them
set FCB_CATALOG, otherwise MID_INITFR does all the work...
.RETURNS
return status ( 0 = o.k )
--------------------------------------------------*/

char   *name;		/* IN: name of object */
int dattype;		/* IN: data types as defined in Module header  */
int iomode;		/* IN: opening mode, e.g. F_O_MODE, ...   */
int filtype;		/* IN: filetype no., e.g. F_TBL_TYPE, ... */
size_t sizze;		/* IN: size of object = no. of data values in file */
int *optio;		/* IN: optio[0] = 1 for cloning, else no
			       optio[1] = imno of source (if optio[0] = 1) */
int *imno;		/* OUT: file no.  */

{
int   mm, namtyp, part_no;
int   entrx, status;

char   temp[200];

struct FCT_STRUCT  *fctpntr;





if (iomode == F_H_MODE)	
   sizze = (size_t) 0;		/* just write the file header (F_H_MODE) */
else			
   {
   if (sizze < 1) 		/* we need size > 0 !!  */
      {		
      status = ERR_OUTLIM;
      goto end_of_it;
      }
   }


/*	
   for iomode = F_X_MODE,  just prepare entry in FCT
*/
	
if (iomode == F_X_MODE)
   {
   entrx = MID_FINDFR(name);			/* look, if already in FCT  */
   if (entrx > -1) 				/* > -1 is the same as >= 0 */
      {
      (void) strcpy(temp,name);
      status = ERR_INPINV;
      goto end_of_it;
      }


   /*  enter file also into FCT with size in bytes  */
 
   entrx = MID_CREFRE(name,-1);
   if (entrx < 0)
      {
      (void) strcpy(temp,name);
      status = ERR_FILNAM;
      goto end_of_it;
      }
  
   fctpntr = FCT.ENTRIES + entrx;
   fctpntr->CATALOG[0] = 'I';			/* type image */
   fctpntr->CATALOG[1] = 'N';			/* no catalog...  */
   fctpntr->ACCESS = 'X';			/* set to scratch access */
   *imno = entrx;


   /* store required data type + default access mode  */

   fctpntr->FORMAT = dattype;
   fctpntr->NOBYTE = get_byte(fctpntr->FORMAT);
   fctpntr->SIZE = sizze;
   fctpntr->STBLOK = 1;			/* no FCB, nor descriptors... */

   status = ERR_NORMAL;
   }

else
   {			/*  create file on disk (store FCB + LDB's)  */

   /* get cleand file name 'temp'  */

   status = CGN_CLEANF(name,filtype,temp,FCT_NAME_LEN,&namtyp,&part_no);
   if ((status != 0) || (part_no != 0))
      {
      status = ERR_FILNAM;
      (void) strcpy(temp,name);
      goto end_of_it;
      }

   infr_loop:				/* pass optio on to MID_INITFR */
   status = MID_INITFR(temp,dattype,namtyp,sizze,optio,imno);

   if (status == (-99))			   /* if an FCT entry already there, */
      {						/* get rid of it  */
      (void) MID_ACCFRM(temp,0,imno,&mm);
      (void) SCFCLO(*imno);
      goto infr_loop;
      }
   
   if (status == ERR_NOCLON) 		/* we cannot clone, tell caller */
      return status;    
   else if (status != ERR_NORMAL) 	/* this is a real problem... */
      goto end_of_it;

   fctpntr = FCT.ENTRIES + (*imno);
   mm = filtype + 4 + OFF_CATINF;	/* point to relevant flag in CATALINF */
   if (KIWORDS[mm] == 1)
      fctpntr->CATALOG[1] = 'Y';	/* we want to catalog that one */
   }


/*  that's it...  */
 
fctpntr->DATTYP = fctpntr->FORMAT;
fctpntr->CR_FLAG = 1;			/* mark as just created */
return status;
 

end_of_it:
MID_E1(4,temp,status,1);
return status;
}
/*

*/

int SCFRNM(oldname,newname)
/*++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE
rename a disk file
.ALGORITHM
use CGN_CLEANF + osfrename
.RETURNS
return status ( 0 = o.k )
--------------------------------------------------------*/

char	*oldname;		/* IN: old name  */
char	*newname;		/* OUT: new name  */

{
char  temp[200];

int   namtyp, part_no;


CGN_CLEANF(oldname,0,temp,FCT_NAME_LEN,&namtyp,&part_no);

return (osfrename(temp,newname));
}	

