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

/*+++++++++++++++++++++ Module MIDKEYA +++++++++++++++++++++++++++++++++++++++
.LANGUAGE   C
.IDENTIFICATION  Module MIDKEYA
.AUTHOR   Klaus Banse           ESO - Garching
.KEYWORDS Midas keyword utility routines.
.ENVIRONMENT VMS and UNIX
.COMMENT  
holds IPROMPT, RPROMPT, CPROMPT, DPROMPT
      KEYFILE
 
.VERSION  [3.00] 920129: split off original midkey.c

 100616		last modif
------------------------------------------------------------------------*/
 
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
 
#include <fileexts.h>

/*

*/

int MID_CPROMPT(p_string,noval,carray,nullo)
 
/*++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE
display a prompt string on the terminal + read the user input
.ALGORITHM
use MID_TPRO to display prompt string + get user input as character string
convert this string to relevant data via CGN_CNVT
.RETURNS
status:	I*4		return status
--------------------------------------------------*/

char   *p_string	/* IN : prompt string (null terminated) */;
int   *noval		/* IO : length of expected input */;
char   *carray		/* OUT: input data for type = 3 */;
int   *nullo		/* OUT: no. of null values in input */;
 
{
int   save_val, count;
register int  nr;
 
char	work[96], prombuf[96];

 
save_val = *noval;				/* save noval  */
*noval = 0;					/* init to 0 ...  */

/* store prompt string in logfile */

(void) MID_LOG('G',p_string,(int)strlen(p_string));	
 
 
/*  cut off trailing blanks of prompt + read a line from the terminal */
 
CGN_CUTOFF(p_string,prombuf); 
MID_TPRO(prombuf,work,80);
 
count = (int) strlen(work);		/*  test, if something came in  */
if (count <= 0) return ERR_NODATA;
 

/* do not pass more values than required  */

(void) MID_LOG('G',work,count);
if (save_val <= count)
   count = save_val;
else
   memset((void *)carray,32,(size_t)save_val);	  /* fill first with blanks */
*noval = count;

*nullo = 0;
for (nr=0; nr<count; nr++)
   {
   *carray++ = work[nr];
   if (work[nr] == NUL_CVAL) (*nullo) ++;
   }

return ERR_NORMAL;
}
/*

*/

int MID_DPROMPT(p_string,noval,array,nullo)
 
/*++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE
display a prompt string on the terminal + read the user input
.ALGORITHM
use MID_TPRO to display prompt string + get user input as character string
convert this string to relevant data via CGN_CNVT
.RETURNS
status:	I*4		return status
--------------------------------------------------*/

char   *p_string	/* IN : prompt string (null terminated) */;
int   *noval		/* IO : length of expected input */;
double *array		/* OUT: input data */;
int   *nullo		/* OUT: no. of null values in input */;
 
{
int   save_val, status, mm, iar;
register int  nr;

float   rar; 
 
char	work[96], prombuf[96];
 


save_val = *noval;				/* save noval  */
*noval = 0;					/* init to 0 ...  */

/* store prompt string in logfile */

(void) MID_LOG('G',p_string,(int)strlen(p_string));	
 
 
/*  cut off trailing blanks of prompt + read a line from the terminal */
 
CGN_CUTOFF(p_string,prombuf); 
MID_TPRO(prombuf,work,80);
 
mm = (int) strlen(work);		/*  test, if something came in  */
if (mm <= 0) return ERR_NODATA;

(void) MID_LOG('G',work,mm);
mm = CGN_CNVT(work,4,save_val,&iar,&rar,array);
if (mm <= 0) 
   {
   status = ERR_INPINV;			/* conversion error... */
   goto end_of_it;
   }
else
   status = ERR_NORMAL;

*noval = mm;
*nullo = 0;
for (nr=0; nr<mm; nr++)         /* look for null values  */
   {
   if (array[nr] == NUL_DVAL) (*nullo) ++;
   }
 
end_of_it:
if (status != ERR_NORMAL)
   MID_ERROR("MIDAS","MID_DPROMPT",status,0);
 
return status;
}
/*

*/

int MID_IPROMPT(p_string,noval,array,nullo)
 
/*++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE
display a prompt string on the terminal + read the user input
.ALGORITHM
use MID_TPRO to display prompt string + get user input as character string
convert this string to relevant data via CGN_CNVT
.RETURNS
status:	I*4		return status
--------------------------------------------------*/

char   *p_string	/* IN : prompt string (null terminated) */;
int *noval		/* IO : length of expected input */;
int *array		/* OUT: input data */;
int *nullo		/* OUT: no. of null values in input */;
 
{
int   save_val, status, mm;
register int nr;

float     rar; 
double    dar;
 
char	work[96], prombuf[96];

 
save_val = *noval;				/* save noval  */
*noval = 0;					/* init to 0 ...  */

/* store prompt string in logfile */

(void) MID_LOG('G',p_string,(int)strlen(p_string));	
 
 
/*  cut off trailing blanks of prompt + read a line from the terminal */
 
CGN_CUTOFF(p_string,prombuf); 
MID_TPRO(prombuf,work,80);
 
mm = (int) strlen(work);		/*  test, if something came in  */
if (mm <= 0) return ERR_NODATA;

(void) MID_LOG('G',work,mm);
mm = CGN_CNVT(work,1,save_val,array,&rar,&dar);
if (mm <= 0) 
   {
   status = ERR_INPINV;			/* conversion error... */
   goto end_of_it;
   }
else
   status = ERR_NORMAL;

*noval = mm;
*nullo = 0;
for (nr=0; nr<mm; nr++)         /* look for null values  */
   {
   if (array[nr] == NUL_IVAL) (*nullo) ++;
   }
 
end_of_it:
if (status != ERR_NORMAL)
   MID_ERROR("MIDAS","MID_IPROMPT",status,0);
 
return status;
}
/*

*/

int MID_RPROMPT(p_string,noval,array,nullo)
 
/*++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE
display a prompt string on the terminal + read the user input
.ALGORITHM
use MID_TPRO to display prompt string + get user input as character string
convert this string to relevant data via CGN_CNVT
.RETURNS
status:	I*4		return status
--------------------------------------------------*/

char   *p_string	/* IN : prompt string (null terminated) */;
int   *noval		/* IO : length of expected input */;
float  *array		/* OUT: input data */;
int   *nullo		/* OUT: no. of null values in input */;
 
{
int   save_val, status, mm, iar;
register int  nr;

char	work[96], prombuf[96];

double    dar; 

 
save_val = *noval;				/* save noval  */
*noval = 0;					/* init to 0 ...  */

/* store prompt string in logfile */

(void) MID_LOG('G',p_string,(int)strlen(p_string));	
 
 
/*  cut off trailing blanks of prompt + read a line from the terminal */
 
CGN_CUTOFF(p_string,prombuf); 
MID_TPRO(prombuf,work,80);
 
mm = (int) strlen(work);		/*  test, if something came in  */
if (mm <= 0) return ERR_NODATA;

(void) MID_LOG('G',work,mm);
mm = CGN_CNVT(work,2,save_val,&iar,array,&dar);
if (mm <= 0) 
   {
   status = ERR_INPINV;			/* conversion error... */
   goto end_of_it;
   }
else
   status = ERR_NORMAL;

*noval = mm;
*nullo = 0;
for (nr=0; nr<mm; nr++)         /* look for null values  */
   {
   if (array[nr] == NUL_DVAL) (*nullo) ++;
   }
 
end_of_it:
if (status != ERR_NORMAL)
   MID_ERROR("MIDAS","MID_RPROMPT",status,0);
 
return status;
}
/*

*/

int MID_KEYFILE(progname)
 
/*++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE
read keyword values from ASCII file progname.key
.ALGORITHM
.RETURNS
status:	int		return status
--------------------------------------------------*/

char   *progname;	/* IN : name of calling program */

{
int   slen, cl, nc, nb, fid, m, n;
int   *ibuf, unit, start, first, noelem, sbytelem, bytelem;
int stat = 0;
register int  nr;

float  *rbuf, rwa;

double *dbuf, dwa;

char   *cbuf, cc[4], buff[128];
char   keyname[32], type[16], k_type[4], substr[24];

void  *work_str;




(void) strncpy(buff,progname,120);
buff[120] = '\0';			/* so we have an end... */
m = CGN_INDEXC(buff,' ');
if (m < 0)
   (void) strcat(buff,".KEY");
else
   (void) strcpy(&buff[m],".KEY");

nc = 0;
fid = osaopen(buff,READ);
if (fid < 0) return (ERR_FRMNAC);

work_str = malloc((size_t)200);
 
dbuf = (double *)work_str;
ibuf = (int *)work_str;
rbuf = (float *)work_str;
cbuf = (char *)work_str;

read_loop:
memset((void *)buff,32,(size_t)80);	/* clear read buffer */
slen = osaread(fid,buff,80);
if (slen < 0) 
   {
   stat = 0;
   goto file_end;              /* EOF reached */
   }

nc ++;
if (slen == 0) goto read_loop;

/*
printf("record read: %s\n",buff);
*/

/* we've got some stuff */

for (nr=0; nr<slen; nr++)
   {
   if ((buff[nr] != ' ') && (buff[nr] != '\t')) goto text_a;
   }
goto read_loop;				/* skip empty lines */

text_a:
CGN_strcpy(buff,&buff[nr]);
if (buff[0] == '!') goto read_loop;	/* skip comments */

cl = CGN_INDEXC(buff,' ');
if (cl < 0) 
   {
   printf("invalid syntax - line %d skipped...\n",nc);
   goto read_loop;
   }

buff[cl] = '\0';
CGN_UPSTR(buff);

slen = CGN_INDEXC(buff,'/');
(void) strncpy(keyname,buff,(size_t)slen);
keyname[slen] = '\0';
start = slen + 1;
slen = CGN_EXTRSS(buff,cl,'/',&start,type,15);

MID_TYPCHK(type,cc,&bytelem);
if (type[0] == ' ')
   {
   printf("bad keytype - line %d skipped...\n",nc);
   goto read_loop;
   }

slen = CGN_EXTRSS(buff,cl,'/',&start,substr,20);
if (slen < 1) 
   {
   printf("bad start element - line %d skipped...\n",nc);
   goto read_loop;
   }

n = CGN_CNVT(substr,1,1,&first,&rwa,&dwa);
if (n < 1) 
   {
   printf("bad start element - line %d skipped...\n",nc);
   goto read_loop;
   }

slen = CGN_EXTRSS(buff,cl,'/',&start,substr,20);
n = CGN_CNVT(substr,1,1,&noelem,&rwa,&dwa);
if (n < 1) 
   {
   printf("bad noelem - line %d skipped...\n",nc);
   goto read_loop;
   }
 
n = MID_FNDKEY(keyname,k_type,&sbytelem,&nb,&unit);
if (n >= 0)
   {
   if ( (type[0] != k_type[0]) || (bytelem != sbytelem) )
      {
      printf("wrong keytype - line %d skipped...\n",nc);
      goto read_loop;
      }
   }
else
   {    
   slen = noelem + first - 1;
   m = MID_DEFKEY(keyname,' ',type,slen,&unit);
   if (stat != ERR_NORMAL) 
      {
      printf("problem creating keyword - line %d skipped...\n",nc);
      goto read_loop;
      }
   }

if (type[0] == 'I')
   nb = 1;
else if (type[0] == 'R')
   nb = 2;
else if (type[0] == 'C')
   nb = 3;
else
   nb = 4;

CGN_strcpy(buff,&buff[cl+1]);
slen = (int) strlen(buff);
for (nr=0; nr<slen; nr++)
   {
   if ((buff[nr] != ' ') && (buff[nr] != '\t')) goto text_b;
   }
printf("missing data - line %d skipped...\n",nc);
goto read_loop;                     

text_b:
if (nr > 0) CGN_strcpy(buff,&buff[nr]);

/*
printf("data: %s\nnb = %d, first = %d, noelem = %d\n",buff,nb,first,noelem);
*/

if (nb != 3)
   {
   m = CGN_CNVT(buff,nb,noelem,ibuf,rbuf,dbuf);
   if (m > noelem) m = noelem;

   if (nb == 1)
      stat = SCKWRI(keyname,ibuf,first,m,&unit);
   else if (nb == 2)
      stat = SCKWRR(keyname,rbuf,first,m,&unit);
   else 
      stat = SCKWRD(keyname,dbuf,first,m,&unit);
   }

else
   {
   m = noelem * bytelem;                  /* total size */
   if (m > 200)
      {
      printf("data overflow (> 200) - line %d skipped...\n",nc);
      goto read_loop;
      }

   slen = (int) strlen(buff) - 1;
   if ( (buff[0] == '"') && (slen > 1) && (buff[slen] == '"') )
      {
      cbuf = &buff[1];
      buff[slen--] = '\0';
      }
   else
      {
      cbuf = &buff[0];
      slen++;
      }

   if (slen < m)
      {
      for (nr=slen; nr<m; nr++) cbuf[nr] = ' ';        /* pad with blanks  */
      }

   stat = SCKWRC(keyname,bytelem,cbuf,first,noelem,&unit);
   }
if (stat != ERR_NORMAL)
   printf("problem filling keyword - line %d skipped...\n",nc);

goto read_loop;


file_end:
osaclose(fid);

return stat; 
}
/*

*/

int MID_SPROMPT(p_string,noval,array,nullo)
 
/*++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE
display a prompt string on the terminal + read the user input
.ALGORITHM
use MID_TPRO to display prompt string + get user input as character string
convert this string to relevant data via CGN_xCNVT
.RETURNS
return status
--------------------------------------------------*/

char   *p_string	/* IN : prompt string (null terminated) */;
int   *noval		/* IO : length of expected input */;
size_t *array		/* OUT: input data */;
int   *nullo		/* OUT: no. of null values in input */;
 
{
int   save_val, status, mm, iar;
register int  nr;

float   rar; 
double  dar; 
 
char	work[96], prombuf[96];

size_t  snul;

 


save_val = *noval;				/* save noval  */
*noval = 0;					/* init to 0 ...  */

/* store prompt string in logfile */

(void) MID_LOG('G',p_string,(int)strlen(p_string));	
 
 
/*  cut off trailing blanks of prompt + read a line from the terminal */
 
CGN_CUTOFF(p_string,prombuf); 
MID_TPRO(prombuf,work,80);
 
mm = (int) strlen(work);		/*  test, if something came in  */
if (mm <= 0) return ERR_NODATA;

(void) MID_LOG('G',work,mm);
mm = CGN_xCNVT(work,5,save_val,&iar,&rar,&dar,array);
if (mm <= 0) 
   {
   status = ERR_INPINV;			/* conversion error... */
   goto end_of_it;
   }
else
   status = ERR_NORMAL;

*noval = mm;
*nullo = 0;
snul = (size_t)NUL_DVAL;
for (nr=0; nr<mm; nr++)         /* look for null values  */
   {
   if (array[nr] == snul) (*nullo) ++;
   }
 
end_of_it:
if (status != ERR_NORMAL)
   MID_ERROR("MIDAS","MID_DPROMPT",status,0);
 
return status;
}

