/*===========================================================================
  Copyright (C) 1995-2009 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 Massachusetss Ave, Cambridge, 
  MA 02139, USA.
 
  Corresponding 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 SCK +++++++++++++++++++++++
.LANGUAGE C
.IDENTIFICATION Module SCK
.AUTHOR         K. Banse  ESO - Garching
.KEYWORDS       standard interfaces, keyword data base
.ENVIRONMENT    VMS and UNIX
.COMMENTS    
holds SCKGETC, SCKRDx routines

.VERSION  [2.00] 871124:  new version
 
 090630		last modif
-----------------------------------------------------------------------------*/

#include <fileexts.h>



/*

*/

int SCKGETC(key,felem,maxvals,actvals,values)

/*++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE
get data from character keyword and terminate with null (no trailing blanks)
buffer 'values' must have at least 'maxvals+1' size, to be able to hold
most 'maxvals' chars + null (end-char.)
.ALGORITHM
use SCKRDC
.RETURNS
return status ( 0 = ok )
--------------------------------------------------*/

char    *key;	/* IN : name of keyword  */
int felem;	/* IN : first data item to be read */
int maxvals;	/* IN : max. no. of elements to get */
int  *actvals;	/* OUT: actual no. of elements returned */
char  *values;	/* OUT: buffer for data values */

{
int   nulo, munit;
int   status, invals, kindx;
register int  nr;

register char mychar;



status = SCKRDC(key,1,felem,maxvals,&invals,values,&munit,&nulo);


/* now get rid of trailing blanks/nulls   */

kindx = invals - 1;			/* point to last buffer element */

mychar = values[kindx];
if ((mychar != ' ') && (mychar != '\0')) 
   {			
   /* this might cause trouble ... 
   if (invals == maxvals)
      {				
      char  txt[80];

      sprintf(txt,"key = %s, maxvals = %d",key,maxvals);
      SCTPUT(txt);
      SCTPUT("must overwrite output buffer...");
      }
   */

   *actvals = invals;	
   values[invals] = '\0';   		/* add(!) Null terminator */
   return status;
   }

for (nr=(kindx-1); nr>=0; nr--)
   {					/* try to truncate */
   mychar = values[nr];
   if ((mychar != ' ') && (mychar != '\0')) 
      {
      *actvals = nr + 1;
      values[nr+1] = '\0';		/* add null terminator  */
      return status;
      }
   }

values[0] = '\0';
*actvals = 0;				/* indicate also in actvals */
return status;
}

/*

*/

int SCKRDC(key,noelm,felem,maxvals,actvals,values,unit,null)

/*++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE
read data from character keyword
.ALGORITHM
straight forward
.RETURNS
return status ( 0 = ok )
--------------------------------------------------*/

char    *key	/* IN : name of keyword  */;
int noelm	/* IN : for char. arrays, CHAR*noelm */;
int felem	/* IN : first data item to be read */;
int maxvals 	/* IN : no. of elements to get  */;
int  *actvals 	/* OUT: actual no. of elements returned */;
char    *values /* OUT: buffer for data values */;
int    *unit  	/* OUT: unit-pointer */;
int  *null	/* OUT: no. of null values in keyword */;

{
int   kk, kunit, status, offset;
/* int   nulflag;   */
int   bytelem, noelem, nn, kentry, noval;
register int  nr;

struct  KEY_STRUCT  *keypntr;

char  k_typ[4];
register char   *cpntr, *valptr;



/*  find entry in keyword control table  */
 
kentry = MID_FNDKEY(key,k_typ,&bytelem,&noelem,&kunit);
if (kentry < 0)
   {
   status = ERR_KEYBAD;
   goto end_of_it;
   }
else if (k_typ[0] != 'C') 
   {
   status = ERR_KEYTYP;
   goto end_of_it;
   }


/*  get info about keyword */

keypntr = KEYALL.KEYNAMES + kentry;

noval = keypntr->NOELEM * keypntr->BYTELEM;	/* real size of keyword */
offset = (felem - 1) * noelm;			/* requested offset */
kk = noval - offset;				/* size available */
kk /= noelm;			 /* no. of elements/values available */


/*  check parameters */

if ( (felem <= 0) || (noelm < 1) || (kk < 1) || (maxvals <= 0) ) 
   {
   status = ERR_OUTLIM;
   goto end_of_it;
   }
	

offset += keypntr->OFFSET;		/* get location in KEY_CWORDS */
if (maxvals < kk) kk = maxvals;		/* minimize ... */
nn = kk * noelm;			/* total no. of bytes to copy */


/* copy data + check for null values at same time  */

cpntr = KCWORDS + offset;
valptr = values;			/* copy pointer */

/* nulflag = *null;		this feature is currently not used !!!

if (nulflag > -1)
   {
   for (nr=0; nr<nn; nr++)
      {
      if (*cpntr == NUL_CVAL) (*null) ++;
      *valptr++ = *cpntr++;
      }
   }
else
   {
   for (nr=0; nr<nn; nr++) *valptr++ = *cpntr++;
   }
*/


for (nr=0; nr<nn; nr++) *valptr++ = *cpntr++;

*null = 0;
*unit = kunit;
*actvals = kk;

return ERR_NORMAL;

				/*  here for errors  */
end_of_it:
MID_E1(5,key,status,1);
return status;
}

/*

*/

int SCKRDD(key,felem,maxvals,actvals,values,unit,null)

/*++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE
read data from double keyword
.ALGORITHM
straight forward
.RETURNS
return status ( 0 = ok )
--------------------------------------------------*/

char    *key	/* IN : name of keyword  */;
int  felem	/* IN : first data item to be read */;
int  maxvals /* IN : no. of elements to get  */;
int  *actvals /* OUT: actual no. of elements returned */;
double  *values /* OUT: buffer for data values */;
int    *unit  	/* OUT: unit-pointer */;
int  *null	/* OUT: no. of null values in keyword */;

{
int   kunit, status, offset;
int   bytelem, noelem, kentry, noval;
register int  nr;

struct  KEY_STRUCT  *keypntr;

char  k_typ[4];

double  *dpntr, *valptr;
 


/*  find entry in keyword control table  */
 
kentry = MID_FNDKEY(key,k_typ,&bytelem,&noelem,&kunit);
if (kentry < 0)
   {
   status = ERR_KEYBAD;
   goto end_of_it;
   }
else if (k_typ[0] != 'D') 
   {
   status = ERR_KEYTYP;
   goto end_of_it;
   }


/*  keyname o.k. - check first element + no. of values  */

if ( (felem <= 0) || (felem > noelem) || (maxvals <= 0) ) 
   {
   status = ERR_OUTLIM;
   goto end_of_it;
   }
	

/* get "real" length + offset before 1. value in data block */

keypntr = KEYALL.KEYNAMES + kentry;
nr = felem - 1;

offset = keypntr->OFFSET + nr;
noval = keypntr->NOELEM - nr;
if (noval < maxvals) maxvals = noval;          		/* minimize... */
*unit = kunit;
*actvals = maxvals;


/*  fill input array  */

*null = 0;
dpntr = KDWORDS + offset;
valptr = values;			/* copy pointer */

/* nulflag = *null; 		this feature is currently not used !!!
if (nulflag > -1)
   {
   for (nr=0; nr<maxvals; nr++)
      {
      if (*dpntr == NUL_DVAL) (*null) ++;
      *valptr++ = *dpntr++;
      }
   }

else
   {
   for (nr=0; nr<maxvals; nr++) *valptr++ = *dpntr++;
   }
*/

for (nr=0; nr<maxvals; nr++) *valptr++ = *dpntr++;

 
return ERR_NORMAL;
	
				/*  here for errors  */
end_of_it:
MID_E1(5,key,status,1);
return status;
}

/*

*/

int SCKRDI(key,felem,maxvals,actvals,values,unit,null)

/*++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE
read data from integer keyword
.ALGORITHM
straight forward
.RETURNS
return status ( 0 = ok )
--------------------------------------------------*/

char    *key	/* IN : name of keyword  */;
int  felem	/* IN : first data item to be read */;
int  maxvals /* IN : no. of elements to get  */;
int  *actvals /* OUT: actual no. of elements returned */;
int *values /* OUT: buffer for data values */;
int    *unit  	/* OUT: unit-pointer */;
int  *null	/* OUT: no. of null values in keyword */;

{
int   kunit, status, offset;
int   bytelem, noelem, kentry, noval;
register int  nr, *ipntr, *valptr;

struct  KEY_STRUCT  *keypntr;

char  k_typ[4];



/*  find entry in keyword control table  */
 
kentry = MID_FNDKEY(key,k_typ,&bytelem,&noelem,&kunit);
if (kentry < 0)
   {
   status = ERR_KEYBAD;
   goto end_of_it;
   }
else if (k_typ[0] != 'I') 
   {
   status = ERR_KEYTYP;
   goto end_of_it;
   }


/*  keyname o.k. - check first element + no. of values  */

if ( (felem <= 0) || (felem > noelem) || (maxvals <= 0) ) 
   {
   status = ERR_OUTLIM;
   goto end_of_it;
   }


/* get "real" length + offset before 1. value in data block */

keypntr = KEYALL.KEYNAMES + kentry;
nr = felem - 1;

offset = keypntr->OFFSET + nr;
noval = keypntr->NOELEM - nr;
if (noval < maxvals) maxvals = noval;                     /* minimize... */
*unit = kunit;
*actvals = maxvals;


/*  fill input array  */

*null = 0;
ipntr = KIWORDS + offset;
valptr = values;			/* copy pointer */

/* nulflag = *null; 		this feature is currently not used !!!
if (nulflag > -1)
   {
   for (nr=0; nr<maxvals; nr++)
      {
      if (*ipntr == NUL_IVAL) (*null) ++;
      *valptr++ = *ipntr++;
      }
   }
else
   {
   for (nr=0; nr<maxvals; nr++) *valptr++ = *ipntr++;
   }
*/

for (nr=0; nr<maxvals; nr++) *valptr++ = *ipntr++;

 
return ERR_NORMAL;
	
				/*  here for errors  */
end_of_it:
MID_E1(5,key,status,1);
return status;
}
/*

*/

int SCKRDR(key,felem,maxvals,actvals,values,unit,null)

/*++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE
read data from character keyword
.ALGORITHM
use lower level routines MID_RDKEYR
.RETURNS
return status ( 0 = ok )
--------------------------------------------------*/

char    *key	/* IN : name of keyword  */;
int  felem	/* IN : first data item to be read */;
int  maxvals /* IN : no. of elements to get  */;
int  *actvals /* OUT: actual no. of elements returned */;
float *values /* OUT: buffer for data values */;
int    *unit  	/* OUT: unit-pointer */;
int  *null	/* OUT: no. of null values in keyword */;

{
int   kunit, status, offset;
int   bytelem, noelem, kentry, noval;
register int  nr;

struct  KEY_STRUCT  *keypntr;

char  k_typ[4];

register float  *rpntr, *valptr;



/*  find entry in keyword control table  */
 
kentry = MID_FNDKEY(key,k_typ,&bytelem,&noelem,&kunit);
if (kentry < 0)
   {
   status = ERR_KEYBAD;
   goto end_of_it;
   }
else if (k_typ[0] != 'R') 
   {
   status = ERR_KEYTYP;
   goto end_of_it;
   }


/*  keyname o.k. - check first element + no. of values  */

if ( (felem <= 0) || (felem > noelem) || (maxvals <= 0) ) 
   {
   status = ERR_OUTLIM;
   goto end_of_it;
   }


/* get "real" length + offset before 1. value in data block */

keypntr = KEYALL.KEYNAMES + kentry;
nr = felem - 1;

offset = keypntr->OFFSET + nr;
noval = keypntr->NOELEM - nr;
if (noval < maxvals) maxvals = noval;                     /* minimize... */
*unit = kunit;
*actvals = maxvals;


/*  fill input array  */

*null = 0;
rpntr = KRWORDS + offset;
valptr = values;			/* copy pointer */

/* nulflag = *null; 		this feature is currently not used !!!
if (nulflag > -1)
   {
   for (nr=0; nr<maxvals; nr++)
      {
      if (*rpntr == NUL_RVAL) (*null) ++;
      *valptr++ = *rpntr++;
      }
   }
else
   {
   for (nr=0; nr<maxvals; nr++) *valptr++ = *rpntr++;
   }
*/

for (nr=0; nr<maxvals; nr++) *valptr++ = *rpntr++;

 
return ERR_NORMAL;
	
				/*  here for errors  */
end_of_it:
MID_E1(5,key,status,1);
return status;
}
/*

*/

int SCKRDS(key,felem,maxvals,actvals,values,unit,null)
/*++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE
read data from size_t keyword
.ALGORITHM
.RETURNS
return status ( 0 = ok )
--------------------------------------------------*/

char    *key	/* IN : name of keyword  */;
int  felem	/* IN : first data item to be read */;
int  maxvals /* IN : no. of elements to get  */;
int  *actvals /* OUT: actual no. of elements returned */;
size_t *values /* OUT: buffer for data values */;
int    *unit  	/* OUT: unit-pointer */;
int  *null	/* OUT: no. of null values in keyword */;

{
int   kunit, status, offset;
int   bytelem, noelem, kentry, noval;
register int  nr;

struct  KEY_STRUCT  *keypntr;

char  k_typ[4];

register size_t  *spntr, *valptr;



/*  find entry in keyword control table  */
 
kentry = MID_FNDKEY(key,k_typ,&bytelem,&noelem,&kunit);
if (kentry < 0)
   {
   status = ERR_KEYBAD;
   goto end_of_it;
   }
else if (k_typ[0] != 'S') 
   {
   status = ERR_KEYTYP;
   goto end_of_it;
   }


/*  keyname o.k. - check first element + no. of values  */

if ( (felem <= 0) || (felem > noelem) || (maxvals <= 0) ) 
   {
   status = ERR_OUTLIM;
   goto end_of_it;
   }


/* get "real" length + offset before 1. value in data block */

keypntr = KEYALL.KEYNAMES + kentry;
nr = felem - 1;

offset = keypntr->OFFSET + nr;
noval = keypntr->NOELEM - nr;
if (noval < maxvals) maxvals = noval;                     /* minimize... */
*unit = kunit;
*actvals = maxvals;


/*  fill input array  */

*null = 0;
spntr = KSWORDS + offset;
valptr = values;			/* copy pointer */

/* nulflag = *null; 		this feature is currently not used !!!
if (nulflag > -1)
   {
   for (nr=0; nr<maxvals; nr++)
      {
      if (*spntr == NUL_IVAL) (*null) ++;
      *valptr++ = *spntr++;
      }
   }
else
   {
   for (nr=0; nr<maxvals; nr++) *valptr++ = *spntr++;
   }
*/

for (nr=0; nr<maxvals; nr++) *valptr++ = *spntr++;

 
return ERR_NORMAL;
	
				/*  here for errors  */
end_of_it:
MID_E1(5,key,status,1);
return status;
}

