/*===========================================================================
  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 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: SHOKEY, DSPKEY
.ENVIRONMENT VMS and UNIX
.COMMENT  
 holds SHOKEY, DSPKEY
.VERSION  

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

 

static int   kunit, kentry, noelem, bytelem;
 
static char       kname[18], k_typ[4], work[96];

static struct KEY_STRUCT  *keypntr;


/*

*/

void MID_SHOKEY(flag,keywo)

/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE display keywords.
.RETURNS nothing
---------------------------------------------------------------*/

int  flag;		/* IN: 0 - display keyword info on screen,
			       1 - only fill keyword M$INFO (this is only
				   applicable for individual keywords... */
char *keywo;		/* IN: name of keyword,
			       `?' to show all keywords + system info,
			       `?+' to show only system info */

{
int   sizbyt, typno, kk;
register int   n, mm;

char  k_typ;

struct KEY_STRUCT  *locpntr;




if (*keywo != '?')
   {
   CGN_UPCOPY(kname,keywo,KEY_NAMELEN);
   kname[KEY_NAMELEN] = '\0';
   for (n=(int)strlen(kname); n<KEY_NAMELEN; n++)
       kname[n] = ' ';


   /*  contrary to the rest, loop first through the local keywords 
       and look for LAST matching keyword name                      */

   keypntr = KEYALL.KEYNAMES + KEYALL.GLOBENT;
   locpntr = KEYALL.KEYNAMES;

   for (mm=KEYALL.GLOBENT; mm <= KEYALL.LOCNO; mm++)
      {
      if (strncmp(kname,keypntr->IDENT,KEY_NAMELEN) == 0)
         locpntr = keypntr;				/* get last match */
      keypntr ++;
      }

   if (locpntr != KEYALL.KEYNAMES)
      {
      keypntr = locpntr;
      k_typ =  keypntr->IDENT[15];
      if (k_typ == 'I')
         {
         sizbyt = II_SIZE;
         typno = 1;
         }
      else if (k_typ == 'R')
         {
         sizbyt = RR_SIZE;
         typno = 2;
         }
      else if (k_typ == 'D')
         {
         sizbyt = DD_SIZE;
         typno = 4;
         }
      else if (k_typ == 'C')
         {
         sizbyt = 1;
         typno = 3;
         }
      else
         {				/* new type: size_t */
         sizbyt = SS_SIZE;
         typno = 5;
         }

      if (flag == 0)
         {
         kname[KEY_NAMELEN] = '\0';
         (void)
         snprintf(work,(size_t)88,
                 "No. %d, IDENT(Name,Type,Level): %s %c%c",mm,kname,
                 k_typ,keypntr->IDENT[16]);
         SCTPUT(work);
         (void)
         snprintf(work,(size_t)88,
                 "     bytes per element = %d, no. of elements = %d",
                 keypntr->BYTELEM,keypntr->NOELEM);
         SCTPUT(work);
         sizbyt *= keypntr->OFFSET;
         (void)
         (void) snprintf(work,(size_t)88,
                 "     length = %d, offset = %d, Pad = %d (all in bytes)",
                 keypntr->LEN,sizbyt,keypntr->FRPAD);
         SCTPUT(work);
         }
      else
         {
         n = OFF_INFO;
         KIWORDS[n++] = typno;
         KIWORDS[n++] = keypntr->NOELEM;
         KIWORDS[n++] = keypntr->BYTELEM;
         }
      return;
      }

   keypntr = KEYALL.KEYNAMES;
   for (mm=0; mm <= KEYALL.GLOBNO; mm++)
      {
      if (strncmp(kname,keypntr->IDENT,KEY_NAMELEN) == 0)
         {
         k_typ =  keypntr->IDENT[15];
         if (k_typ == 'I')
            {
            sizbyt = II_SIZE;
            typno = 1;
            }
         else if (k_typ == 'R')
            {
            sizbyt = RR_SIZE;
            typno = 2;
            }
         else if (k_typ == 'D')
            {
            sizbyt = DD_SIZE;
            typno = 4;
            }
         else if (k_typ == 'C')
            {
            sizbyt = 1;
            typno = 3;
            }
         else
            {                              /* new type: size_t */
            sizbyt = SS_SIZE;
            typno = 5;
            }

         if (flag == 0)
            {
            kname[KEY_NAMELEN] = '\0';
            (void)
            snprintf(work,(size_t)88,
                 "No. %d, IDENT(Name,Type): %s %c",mm,kname,k_typ);
            SCTPUT(work);
            (void)
            snprintf(work,(size_t)88,
                 "     bytes per element = %d, no. of elements = %d",
                    keypntr->BYTELEM,keypntr->NOELEM);
            SCTPUT(work);
            sizbyt *= keypntr->OFFSET;
            (void) snprintf(work,(size_t)88,
                 "     length = %d, offset = %d, Pad = %d (all in bytes)",
                    keypntr->LEN,sizbyt,keypntr->FRPAD);
            SCTPUT(work);
            }
         else
            {
            n = OFF_INFO;
            KIWORDS[n++] = typno;
            KIWORDS[n++] = keypntr->NOELEM;
            KIWORDS[n++] = keypntr->BYTELEM;
            }
         return;
         }
      keypntr ++;
      }

   if (flag == 0)
      {
      (void) snprintf(work,(size_t)88,
                 "keyword %s not found \n",keywo);
      SCTPUT(work);
      }
   else
      KIWORDS[OFF_INFO] = 0;		/* keyword not found */
   return;
   }


keywo++;
if (*keywo == '+')                      /* ?+ omits individual keywords */
   goto last_info;

kname[8] = '\0';
(void) snprintf(work,(size_t)88,"global keywords:");
SCTPUT(work);
(void) snprintf(work,(size_t)88,"----------------\n");
SCTPUT(work);

keypntr = KEYALL.KEYNAMES;
for (mm=0; mm <= KEYALL.GLOBNO; mm++)
   {
   k_typ =  keypntr->IDENT[15];
   if (k_typ == 'I')
      sizbyt = II_SIZE;
   else if (k_typ == 'R')
      sizbyt = RR_SIZE;
   else if (k_typ == 'D')
      sizbyt = DD_SIZE;
   else if (k_typ == 'C')
      sizbyt = 1;
   else
      sizbyt = SS_SIZE;

   strncpy(kname,keypntr->IDENT,(size_t)KEY_NAMELEN);
   (void) 
   snprintf(work,(size_t)88,
            "No. %d, IDENT(Name,Type): %s %c",mm,kname,k_typ);
   SCTPUT(work);
   (void) snprintf(work,(size_t)88,
                 "     bytes per element = %d, no. of elements = %d",
           keypntr->BYTELEM,keypntr->NOELEM);
   SCTPUT(work);
   sizbyt *= keypntr->OFFSET;
   (void) snprintf(work,(size_t)88,
                 "     length = %d, offset = %d, Pad = %d (all in bytes)",
           keypntr->LEN,sizbyt,keypntr->FRPAD);
   SCTPUT(work);
   keypntr ++;
   }

if (KEYALL.LOCNO >= KEYALL.GLOBENT)
   {
   (void) snprintf(work,(size_t)88,"local keywords:");
   SCTPUT(work);
   (void) snprintf(work,(size_t)88,"---------------\n");
   SCTPUT(work);
   }

keypntr = KEYALL.KEYNAMES + KEYALL.GLOBENT;
for (mm=KEYALL.GLOBENT; mm <= KEYALL.LOCNO; mm++)
   {
   k_typ =  keypntr->IDENT[15];
   if (k_typ == 'I')
      sizbyt = II_SIZE;
   else if (k_typ == 'R')
      sizbyt = RR_SIZE;
   else if (k_typ == 'D')
      sizbyt = DD_SIZE;
   else if (k_typ == 'C')
      sizbyt = 1;
   else
      sizbyt = SS_SIZE;

   (void) strncpy(kname,keypntr->IDENT,(size_t)KEY_NAMELEN);
   (void) snprintf(work,(size_t)88,
                 "No. %d, IDENT(Name,Type,Level): %s %c%c",mm,kname,
           k_typ,keypntr->IDENT[16]);
   SCTPUT(work);
   (void) snprintf(work,(size_t)88,
                 "     bytes per element = %d, no. of elements = %d",
           keypntr->BYTELEM,keypntr->NOELEM);
   SCTPUT(work);
   sizbyt *= keypntr->OFFSET;
   (void) snprintf(work,(size_t)88,
                 "     length = %d, offset = %d, Pad = %d (all in bytes)",
           keypntr->LEN,sizbyt,keypntr->FRPAD);
   SCTPUT(work);
   keypntr ++;
   }

(void) snprintf(work,(size_t)88,"\n---------------------------------\n");
SCTPUT(work);

last_info:
mm = KEYALL.GLOBNO + 1;                 /* we counted from 0 on ... */
(void) snprintf(work,(size_t)88,
                 "global keys: no. = %d, space used = %d bytes",
        mm,KEYALL.GLOBEND);
SCTPUT(work);
(void) snprintf(work,(size_t)88,
                 "max. global keys = %d (max. space = %d)",
        KEYALL.GLOBENT,KEYALL.GLOBDAT);
SCTPUT(work);
kk = OFF_INFO;
KIWORDS[kk++] = mm;
KIWORDS[kk++] = KEYALL.GLOBEND;
KIWORDS[kk++] = KEYALL.GLOBENT;
KIWORDS[kk++] = KEYALL.GLOBDAT;

mm = (KEYALL.LOCNO + 1) - KEYALL.GLOBENT;
n = (KEYALL.LOCEND + 1) - KEYALL.GLOBDAT;
(void) snprintf(work,(size_t)88,
                 "local keys: no. = %d, space used = %d bytes",mm,n);
SCTPUT(work);
KIWORDS[kk++] = mm;
KIWORDS[kk++] = n;
mm = KEYALL.LOCENT - KEYALL.GLOBENT;
n = KEYALL.LOCDAT - KEYALL.GLOBDAT;
(void) snprintf(work,(size_t)88,
                 "max. local keys = %d (max. space = %d)",mm,n);
SCTPUT(work);
KIWORDS[kk++] = mm;
KIWORDS[kk] = n;
}

/*

*/

#ifdef __STDC__
int MID_DSPKEY( char *name, char dflag)
#else
int MID_DSPKEY(name,dflag)
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE
  display the contents of keywords on the terminal
.ALGORITHM
  find keyword entry + display keyword data
.RETURN
  MIDAS error code
----------------------------------------------------------------------*/

char    *name;		/* IN: name of keyword, if blank all keywords  */
char  dflag;		/* IN: disp_flag, if = 'h' don't print header line */
#endif

{
int   sta, nrl, kk, koffs, n1, n2, all;
int   wcindx;
int  n3 = 0;

register int  nr;

char  indstr[18], *datpntr;


sta = 0;
all = 0;
nrl = (int) strlen(name);

extra_key:
wcindx = 0;
n2 = CGN_EXTRSS(name,nrl,',',&sta,kname,KEY_NAMELEN);
if (n2 <= 0)						/* line finished */
   {
   if (n2 == -2) 
      return (ERR_KEYBAD);			/* keyname too long */
   else
      return (ERR_NORMAL);
   }
 

/* check for wildcards */

if (kname[0] == '*')			/* wildcard in the beginning */
   {
   all = 1;
   kentry = 0;
   if (kname[1] != '\0')
      {
      wcindx = -1;
      CGN_UPCOPY(indstr,&kname[1],KEY_NAMELEN);
      indstr[KEY_NAMELEN] = '\0';
      n3 = (int) strlen(indstr);
      }
   goto key_loop;
   }

if (kname[--n2] == '*')			/* wildcard in the end */
   {
   wcindx = 1;
   all = 1;
   kentry = 0;
   kname[n2] = '\0';
   CGN_UPCOPY(indstr,kname,KEY_NAMELEN);
   goto key_loop;
   }

kentry = MID_FNDKEY(kname,k_typ,&bytelem,&noelem,&kunit);
if (kentry < 0) return (ERR_KEYBAD);


/*    set name to keyword name   */

key_loop:
keypntr = KEYALL.KEYNAMES + kentry;             /*  point to specific entry  */
if (*keypntr->IDENT != '\\')			/* no deleted keyword */
   {
   (void) strncpy(kname,keypntr->IDENT,(size_t)KEY_NAMELEN);
   if (wcindx != 0)			/* if wildcard, compare names */
      {
      kname[KEY_NAMELEN] = '\0';
      n1 = CGN_INDEXS(kname,indstr);
      if (wcindx > 0)
         {
         if (n1 != 0) goto wrap_up;
         }
      else
         {
         for (nr=1; nr<KEY_NAMELEN; nr++)     /* get rid of trailing blanks */
            {
            if (kname[nr] == ' ')
               {
               kname[nr] = '\0';
               break;
               }
            }
         n2 = (int) strlen(kname);
         if ((n1 < 0) || ((n1+n3)) != n2) goto wrap_up;
         }
      }
   k_typ[0] = keypntr->IDENT[15];
   bytelem = keypntr->BYTELEM;
   noelem = keypntr->NOELEM;


   /*  keyname o.k. -  treat data according to type  */

   koffs = keypntr->OFFSET;
   n1 = 0;
   memset((void *)work,32,(size_t)80);                 /* int 32 = ' ' */


   /*  integer data   */

   if (k_typ[0] == 'I')
      {
      if (dflag != 'h')
         {
         (void) snprintf(work,(size_t)88,
                 "keyword: %15.15s type: integer  no_elems: %d",
         kname,noelem);
         SCTPUT(work);
         }
      n2 = 8;

     sect_1000:
      if (n2 > noelem) n2 = noelem;
         memset((void *)work,32,(size_t)80);                 /* int 32 = ' ' */

      for (nr=0; nr<(n2-n1)*10; nr+=10)
         (void) snprintf(&work[nr],(size_t)88,"%10d",KIWORDS[koffs++]);
      SCTPUT(work);
      if (n2 < noelem)
         {
         n1 = n2;
         n2 += 8;
         goto sect_1000;
         }
      }


/*  real data   */

   else if (k_typ[0] == 'R')
      {
      if (dflag != 'h')
         {
         (void) snprintf(work,(size_t)88,
                 "keyword: %15.15s type: real     no_elems: %d",
         kname,noelem);
         SCTPUT(work);
         }
      n2 = 6;

     sect_2000:
      if (n2 > noelem) n2 = noelem;
      memset((void *)work,32,(size_t)80);                 /* int 32 = ' ' */

      for (nr=0; nr<(n2-n1)*13; nr+=13)
         (void) snprintf(&work[nr],(size_t)88,"%13.6g",KRWORDS[koffs++]);
      SCTPUT(work);
      if (n2 < noelem)
         {
         n1 = n2;
         n2 += 6;
         goto sect_2000;
         }
      }

   /*  character data  */

   else if (k_typ[0] == 'C')
      {
      if (dflag != 'h')
         {
         (void) snprintf(work,(size_t)88,
                 "keyword: %15.15s type: char*%-3d no_elems: %d",
         kname,bytelem,noelem);
         SCTPUT(work);
         }
      n2 = 80;

      if (bytelem > 1)
         {
         if (bytelem > 90)			/* size of buffer `work' */
            {
            datpntr = malloc((size_t)(bytelem+2));
            for (nr=0; nr<noelem; nr++)
               {
               (void) strncpy(datpntr,&KCWORDS[koffs],(size_t)bytelem);
               *(datpntr+bytelem) = '\0';
               SCTPUT(datpntr);
               koffs += bytelem;
               }
            free (datpntr);
            }
         else
            {
            for (nr=0; nr<noelem; nr++)
               {
               (void) strncpy(work,&KCWORDS[koffs],(size_t)bytelem);
               work[bytelem] = '\0';
               SCTPUT(work);
               koffs += bytelem;
               }
            }
         }
      else
         {
        sect_3000:
         if (n2 > noelem) n2 = noelem;
         kk = n2 - n1;
         (void) strncpy(work,&KCWORDS[koffs],(size_t)kk);
         work[kk] = '\0';
         SCTPUT(work);
         if (n2 < noelem)
            {
            n1 = n2;
            n2 += 80;
            koffs += 80;
            goto sect_3000;
            }
         }
      }


/*  double precision  data   */

   else if (k_typ[0] == 'D')
      {
      if (dflag != 'h')
         {
         (void) snprintf(work,(size_t)88,
                 "keyword: %15.15s type: double   no_elems: %d",
         kname,noelem);
         SCTPUT(work);
         }
      n2 = 3;

     sect_4000:
      if (n2 > noelem) n2 = noelem;
      memset((void *)work,32,(size_t)80);                 /* int 32 = ' ' */

      for (nr=0; nr<(n2-n1)*25; nr+=25)
         (void) snprintf(&work[nr],(size_t)88,"%25.18g",KDWORDS[koffs++]);
      SCTPUT(work);
      if (n2 < noelem)
         {
         n1 = n2;
         n2 += 3;
         goto sect_4000;
         }
      }

/*  size_t  data   */

   else if (k_typ[0] == 'S')
      {
      if (dflag != 'h')
         {
         (void) snprintf(work,(size_t)88,
                 "keyword: %15.15s type: size_t   no_elems: %d",
         kname,noelem);
         SCTPUT(work);
         }
      n2 = 3;

     sect_5000:
      if (n2 > noelem) n2 = noelem;
      memset((void *)work,32,(size_t)80);                 /* int 32 = ' ' */

      for (nr=0; nr<(n2-n1)*25; nr+=25)
         (void) snprintf(&work[nr],(size_t)88,"%25zd",KSWORDS[koffs++]);
      SCTPUT(work);
      if (n2 < noelem)
         {
         n1 = n2;
         n2 += 3;
         goto sect_5000;
         }
      }
   }


wrap_up:				/*  decide if we loop more  */
if (all == 3)
   {
   kentry --;
   if (kentry >= KEYALL.GLOBENT) goto key_loop;
   }

else if (all == 1)
   {
   kentry ++;
   if (kentry <= KEYALL.GLOBNO) goto key_loop;
 
   all = 3;			/* now let's loop through the local k. */
   kentry = KEYALL.LOCNO;
   if (kentry >= KEYALL.GLOBENT)
      {
      if (wcindx == 0) SCTPUT("--- local keywords ---");
      goto key_loop;
      }
   }

goto extra_key;		/* see, if we can extract more  */
}

