/*===========================================================================
  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
===========================================================================*/

/*+++++++++++++++++++++++++++ SC interface module SCDD +++++++++++++++++++++++
.LANGUAGE C
.IDENTIFICATION Module SCDD
.AUTHOR         K. Banse 		ESO - Garching
.KEYWORDS       standard interfaces, descriptors
.ENVIRONMENT    VMS and UNIX
.COMMENTS	holds wdscdirec, SCDWRi, SCDHWi (i=C,D,S,H,I,R,L)
 
.VERSION  [1.00] 920211:  pull out from scd.c

 090323		last modif

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

#include <stdlib.h>
#include <fileexts.h>

#include <stdlib.h>
#include <stdio.h>



#define DMULT	    DD_SIZE/II_SIZE
#define SMULT	    SS_SIZE/II_SIZE


static char   dtype[4], help[72], realdescr[52];

static int    newlen, first, bytelem, dblock, dindx, dunit, dsclen;

static struct FCB_STRUCT  *fcbp;

static struct FCT_STRUCT  *fctpntr;


/*

*/

int wdscdirec(jmno,descr,noelm,felem,nval)

/*++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE
handle lower level descr directory stuff common to all descr tytpes
.ALGORITHM
.RETURNS
return status  ( 0 = o.k. )
--------------------------------------------------*/

int  *jmno;	/* IN : no. of data frame */
char  *descr;	/* IN : descriptor name */
int  noelm;  	/* IN : CHAR*noelm  */
int  felem;	/* IN : first element to write */
int  nval;	/* IN : no. of data values to write */

{
int   imno, status, noelem;
int old_direc();

char  thelp[72];



imno = *jmno;
if ( (imno < 0) || (imno >= FCT.MAXENT) || (nval <= 0) || (noelm < 1) ) 
   return ERR_INPINV;
	
fctpntr = FCT.ENTRIES + imno;
if (fctpntr->PROT == 2)			/* file is write protected... */
   return ERR_FILPRO;

if (fctpntr->LINK[0] >= 2)		/* we write into father frame */
   {
   imno = fctpntr->LINK[1];
   fctpntr = FCT.ENTRIES + imno;
   *jmno = imno;
   }
first = felem;

dsclen = DSCNAM_COPY(realdescr,descr);        /* build uppercase name */

/*
if ((strcmp(realdescr,"HYPOTHETICAL_DESCRIPTOR_NAME_0060") == 0)
   ||  (strcmp(realdescr,"HYPOTHETICAL_DESCRIPTOR_NAME_0061") == 0))
   {
   printf("ojo!\n");
   }
*/

fcbp = fctpntr->FZP;

if (dtype[0] == 'H') 		/* update help text */
   {					/* use global help string */
   status = MID_YDSCDIR(imno,'F',realdescr,dtype,&bytelem,
 	           &noelem,&dunit,&dblock,&dindx,help);
   newlen = 0;			/* avoid "old" help text writing... */
   fctpntr->KAUX[2] = 1;		/* set descriptor-modified flag */
   return status;
   }
else
   {
   thelp[0] = '\0';
   status = MID_YDSCDIR(imno,'F',realdescr,dtype,&bytelem,
      	   	           &noelem,&dunit,&dblock,&dindx,thelp);
   }

dunit = 0;			/* not used yet */

if (status == ERR_DSCNPR)
   {			 		/* if not found, add new descriptor */
   bytelem = noelm;
   if (felem < 1) first = 1;
   noelem = nval + first - 1;
   status = MID_YDSCDIR(imno,'A',realdescr,dtype,&bytelem,
          &noelem,&dunit,&dblock,&dindx,help); 	/* add descr */
   }


else
   {
   if (dtype[0] == 'I')
      {
      if (status == ERR_NORMAL)
         {
         if (felem < 1) first = noelem + 1;	/* append to the end */
         newlen = nval + first - 1;

         if (newlen > noelem) 
            status = MID_YDSCDIR(imno,'E',realdescr,dtype,&bytelem,
                                   &newlen,&dunit,&dblock,&dindx,thelp);
         }
      }

   else if (dtype[0] == 'S')
      {
      if (status == ERR_NORMAL)
         {
         if (felem < 1) first = noelem + 1;	/* append to the end */
         newlen = nval + first - 1;

         if (newlen > noelem) 
            status = MID_YDSCDIR(imno,'E',realdescr,dtype,&bytelem,
                                   &newlen,&dunit,&dblock,&dindx,thelp);
         }
      }

   else if (dtype[0] == 'D')		/* dtype is always updated ... */
      {
      if (status == ERR_DSCTYP)
         {				/* try again with correct type */
         status = MID_YDSCDIR(imno,'F',realdescr,dtype,&bytelem,
                             &noelem,&dunit,&dblock,&dindx,thelp);
         if (status != ERR_NORMAL) return status;
         dunit = 0;
         }

      if (status == ERR_NORMAL)
         {
         if (felem < 1) first = noelem + 1;	/* append to the end */
         newlen = nval + first - 1;

         if (newlen > noelem) 
            status = MID_YDSCDIR(imno,'E',realdescr,dtype,&bytelem,
                                   &newlen,&dunit,&dblock,&dindx,thelp);
         }
      }

   else if (dtype[0] == 'R')		/* dtype is always updated ... */
      {
      if (status == ERR_DSCTYP)
         {				/* try again with correct type */
         status = MID_YDSCDIR(imno,'F',realdescr,dtype,&bytelem,
                             &noelem,&dunit,&dblock,&dindx,thelp);
         if (status != ERR_NORMAL) return status;
         dunit = 0;
         }

      if (status == ERR_NORMAL)
         {
         if (felem < 1) first = noelem + 1;  /* append to the end */
         newlen = nval + first - 1;

         if (newlen > noelem)
            status = MID_YDSCDIR(imno,'E',realdescr,dtype,&bytelem,
                                &newlen,&dunit,&dblock,&dindx,thelp);
         }
      }

   else if (dtype[0] == 'C')
      {
      if (status == ERR_NORMAL)
         {
         if (noelm != bytelem) 
            return ERR_DSCBAD;	/* bytes per element must match! */

         if (felem < 1) first = noelem + 1;  /* append to the end */
         newlen = nval + first - 1;

         if (newlen > noelem)
            status = MID_YDSCDIR(imno,'E',realdescr,dtype,&bytelem,
                                &newlen,&dunit,&dblock,&dindx,thelp);
         }
      }

   else 				/* remains (new) type 'L' */
      {
      if (status == ERR_NORMAL)
         {
         if (felem < 1) first = noelem + 1;  /* append to the end */
         newlen = nval + first - 1;

         if (newlen > noelem)
            status = MID_YDSCDIR(imno,'E',realdescr,dtype,&bytelem,
                                &newlen,&dunit,&dblock,&dindx,thelp);
         }
      }
   }


fctpntr->KAUX[2] = 1;		/* set descriptor-modified flag */

return status;
}
/*

*/

int  wrhelp(imno,descr,htext)
int  imno;
char *descr, *htext;

{
int  noelem, hlen;



hlen = 0;
if (htext != (char *) 0) hlen = (int) strlen(htext);
if (hlen == 0) return ERR_NORMAL;	/* not an error */


/* no need, to check `imno' - we only get here if `imno' o.k. ...*/

fctpntr = FCT.ENTRIES + imno;
if (fctpntr->LINK[0] >= 2)              /* we write into father frame */
   {
   imno = fctpntr->LINK[1];
   fctpntr = FCT.ENTRIES + imno;
   }


fcbp = fctpntr->FZP;
if (fcbp->DSCFLAG != 'Y') return (ERR_INPINV);

if (hlen > 71)
   {                            /* global char.string has 72 chars */
   (void) strncpy(help,htext,71);
   help[71] = '\0';
   }
else
   (void) strcpy(help,htext);

dtype[0] = 'H';
dsclen = DSCNAM_COPY(realdescr,descr);        /* build uppercase name */

(void) MID_YDSCDIR(imno,'F',realdescr,dtype,&bytelem,
                   &noelem,&dunit,&dblock,&dindx,help);

fctpntr->KAUX[2] = 1;		/* set descriptor-modified flag */
return (ERR_NORMAL);
}
/*

*/

int SCDHWC(imno,descr,noelm,values,felem,nval,unit,htext)

int   imno      /* IN : no. of data frame */;
char   *descr   /* IN : descriptor name (max. 48 char.) */;
int noelm       /* IN : CHAR*noelm  */;
char   *values  /* IN : buffer with descriptor data */;
int felem       /* IN : position of 1st descriptor value to be accessed */;
int nval        /* IN : no. of data values to write */;
int   *unit     /* IN : unit-pointer */;
char   *htext   /* IN : help text */;

{
int status;


status = SCDWRC(imno,descr,noelm,values,felem,nval,unit);

if (status == ERR_NORMAL) (void) wrhelp(imno,descr,htext);
return status;
}



int SCDWRC(imno,descr,noelm,values,felem,nval,unit)

/*++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE
Write a descriptor and its data
.ALGORITHM
A new descriptor is written at the end of the existing 
descriptor area or exisitng descriptor data is modified
and extended, if necessary.
.RETURNS
return status  ( 0 = o.k. )
.REMARKS
if 'felem' = -1, descriptor values are appended to existing ones
--------------------------------------------------*/

int   imno	/* IN : no. of data frame */;
char   *descr   /* IN : descriptor name (max. 48 char.) */;
int noelm  	/* IN : CHAR*noelm  */;
char   *values  /* IN : buffer with descriptor data */;
int felem	/* IN : position of 1st descriptor value to be accessed */;
int nval	/* IN : no. of data values to write */;
int   *unit	/* IN : unit-pointer */;

{
int   kk, status, nlen;
register int  nr;
static int   xlen = 0;

static char  *xpntr = (char *) 0;



dtype[0] = 'C';	
help[0] = '\0';
status = wdscdirec(&imno,descr,noelm,felem,nval);

if (status == ERR_NORMAL)
   {
   nlen = nval * bytelem;		/* char array -> flat string */
   first = (first-1)*bytelem + 1;

   for (nr=0; nr<nlen; nr++)
      {
      if (values[nr] == '\0')           /* we don't have enough data */
         {
         kk = nr;
         if (xlen < nlen)                       /* need to allocate more */
            {
            if (xpntr != (char *) 0) free(xpntr);

            xpntr = malloc((size_t)nlen);
            if (xpntr == (char *) 0)
               {
               xpntr = values;
               nlen = kk;                       /* all what we can do ...  */
               }
            xlen = nlen;
            }

         /* first copy data, then pad wth blanks */

         (void) memcpy(xpntr,values,(size_t)kk);          /* copy */
         (void) memset(xpntr+kk,32,(size_t)(nlen-kk));    /* and pad */

         (void) MID_WDSCRC(fctpntr->IOCHAN,dblock,dindx,xpntr,0,first,nlen);
         return ERR_NORMAL;
         }
      }

   (void) MID_WDSCRC(fctpntr->IOCHAN,dblock,dindx,values,0,first,nlen);
   }
 
else
   MID_E2(5,imno,descr,status,1);


return (status);
}
/*

*/

int SCDHWD(imno,descr,values,felem,nval,unit,htext)

int   imno      /* IN : no. of data frame */;
char   *descr   /* IN : descriptor name (max. 48 char.) */;
double *values  /* IN : buffer with descriptor data */;
int felem       /* IN : position of 1st descriptor value to be accessed */;
int  nval       /* IN : no. of data values to write */;
int   *unit     /* IN : unit-pointer */;
char   *htext   /* IN : help text */;

{
int status;


status = SCDWRD(imno,descr,values,felem,nval,unit);

if (status == ERR_NORMAL) (void) wrhelp(imno,descr,htext);
return status;
}



int SCDWRD(imno,descr,values,felem,nval,unit)

/*++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE
Write a descriptor and its data
.ALGORITHM
  A new descriptor is written at the end of the existing 
  descriptor area or existing descriptor data is modified
  and extended, if necessary.
.RETURNS
return status  ( 0 = o.k. )
.REMARKS
if 'felem' = -1, descriptor values are appended to existing ones
--------------------------------------------------*/

int   imno	/* IN : no. of data frame */;
char   *descr   /* IN : descriptor name (max. 48 char.) */;
double *values  /* IN : buffer with descriptor data */;
int felem	/* IN : position of 1st descriptor value to be accessed */;
int  nval	/* IN : no. of data values to write */;
int   *unit	/* IN : unit-pointer */;

{
int   n, status, *ipntr;


	
dtype[0] = 'D';	
help[0] = '\0';
status = wdscdirec(&imno,descr,DD_SIZE,felem,nval);


if (status == ERR_NORMAL) 
   {
   if (dtype[0] == 'R')			/* write double data to real descr */
      {
      float  *rvals;
      char  tmp[80], *mypntr;

      n = RR_SIZE * nval;
      mypntr = malloc((size_t) n);
      if (mypntr == (char *) 0)
         {
         status = ERR_MEMOUT;
         goto end_of_it;
         }
      rvals = (float *)mypntr;

      for (n=0; n<nval; n++) 		/* double -> float data */
         *rvals++ = (float) values[n];
      rvals = (float *)mypntr;			/* set back to start */
      (void) MID_WDSCRR(fctpntr->IOCHAN,dblock,dindx,rvals,0,first,nval);
      (void) free (mypntr);

      (void) sprintf(tmp,"SCDWRD with descr: %s",descr);
      status = ERR_LOSPRC;                 /* send a warning */
      MID_ERROR("MID",tmp,status,1);
      }

   else
      {		     /* use MID_WDSCRI to write double precision descr... */
      newlen = DMULT * nval;
      first = (DMULT * first) - 1;			
      ipntr = (int *) values;
      (void) MID_WDSCRI(fctpntr->IOCHAN,dblock,dindx,ipntr,0,first,newlen);
      }

   return ERR_NORMAL;
   }
 

end_of_it:
MID_E2(5,imno,descr,status,1);
return (status);
}
/*

*/

int SCDHWS(imno,descr,values,felem,nval,unit,htext)

int   imno      /* IN : no. of data frame */;
char   *descr   /* IN : descriptor name (max. 48 char.) */;
size_t *values  /* IN : buffer with descriptor data */;
int felem       /* IN : position of 1st descriptor value to be accessed */;
int  nval       /* IN : no. of data values to write */;
int   *unit     /* IN : unit-pointer */;
char   *htext   /* IN : help text */;

{
int status;


status = SCDWRS(imno,descr,values,felem,nval,unit);

if (status == ERR_NORMAL) (void) wrhelp(imno,descr,htext);
return status;
}



int SCDWRS(imno,descr,values,felem,nval,unit)

/*++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE
Write a descriptor and its data
.ALGORITHM
  A new descriptor is written at the end of the existing 
  descriptor area or existing descriptor data is modified
  and extended, if necessary.
.RETURNS
return status  ( 0 = o.k. )
.REMARKS
if 'felem' = -1, descriptor values are appended to existing ones
--------------------------------------------------*/

int   imno	/* IN : no. of data frame */;
char   *descr   /* IN : descriptor name (max. 48 char.) */;
size_t *values  /* IN : buffer with descriptor data */;
int felem	/* IN : position of 1st descriptor value to be accessed */;
int  nval	/* IN : no. of data values to write */;
int   *unit	/* IN : unit-pointer */;

{
int   status, *ipntr;


	
dtype[0] = 'S';	
help[0] = '\0';
status = wdscdirec(&imno,descr,SS_SIZE,felem,nval);


if (status == ERR_NORMAL) 
   {			/* use MID_WDSCRI to write size_t descr... */
   newlen = SMULT * nval;
   first = (SMULT * first) - 1;			
   ipntr = (int *) values;
   (void) MID_WDSCRI(fctpntr->IOCHAN,dblock,dindx,ipntr,0,first,newlen);

   return ERR_NORMAL;
   }
 

MID_E2(5,imno,descr,status,1);
return (status);
}
/*

*/

int SCDHWL(imno,descr,values,felem,nval,unit,htext)

int   imno      /* IN : no. of data frame */;
char   *descr   /* IN : descriptor name (max. 48 char.) */;
int *values  /* IN : buffer with (logical) descriptor data */;
int felem       /* IN : position of 1st descriptor value to be accessed */;
int  nval       /* IN : no. of data values to write */;
int   *unit     /* IN : unit-pointer */;
char   *htext   /* IN : help text */;

{
int status;


status = SCDWRL(imno,descr,values,felem,nval,unit);

if (status == ERR_NORMAL) (void) wrhelp(imno,descr,htext);
return status;
}



int SCDWRL(imno,descr,values,felem,nval,unit)

/*++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE
Write a descriptor and its data
.ALGORITHM
  A new descriptor is written at the end of the existing 
  descriptor area or exisitng descriptor data is modified
  and extended, if necessary.
.RETURNS
return status  ( 0 = o.k. )
.REMARKS
if 'felem' = -1, descriptor values are appended to existing ones
--------------------------------------------------*/

int   imno	/* IN : no. of data frame */;
char   *descr   /* IN : descriptor name (max. 48 char.) */;
int *values  /* IN : buffer with (logical) descriptor data */;
int felem	/* IN : position of 1st descriptor value to be accessed */;
int  nval	/* IN : no. of data values to write */;
int   *unit	/* IN : unit-pointer */;

{
int   status;



dtype[0] = 'L';
help[0] = '\0';
status = wdscdirec(&imno,descr,II_SIZE,felem,nval);
	
if (status == ERR_NORMAL)
   (void) MID_WDSCRI(fctpntr->IOCHAN,dblock,dindx,values,0,first,nval);
else
    MID_E2(5,imno,descr,status,1);

return (status);
}
/*

*/

int SCDHWI(imno,descr,values,felem,nval,unit,htext)

int   imno      /* IN : no. of data frame */;
char   *descr   /* IN : descriptor name (max. 48 char.) */;
int *values  /* IN : buffer with descriptor data */;
int felem       /* IN : position of 1st descriptor value to be accessed */;
int  nval       /* IN : no. of data values to write */;
int   *unit     /* IN : unit-pointer */;
char   *htext   /* IN : help text */;

{
int status;


status = SCDWRI(imno,descr,values,felem,nval,unit);

if (status == ERR_NORMAL) (void) wrhelp(imno,descr,htext);
return status;
}



int SCDWRI(imno,descr,values,felem,nval,unit)

/*++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE
Write a descriptor and its data
.ALGORITHM
  A new descriptor is written at the end of the existing 
  descriptor area or exisitng descriptor data is modified
  and extended, if necessary.
.RETURNS
return status  ( 0 = o.k. )
.REMARKS
if 'felem' = -1, descriptor values are appended to existing ones
--------------------------------------------------*/

int   imno	/* IN : no. of data frame */;
char   *descr   /* IN : descriptor name (max. 48 char.) */;
int *values  /* IN : buffer with descriptor data */;
int felem	/* IN : position of 1st descriptor value to be accessed */;
int  nval	/* IN : no. of data values to write */;
int   *unit	/* IN : unit-pointer */;

{
int   status;




dtype[0] = 'I';
help[0] = '\0';
status = wdscdirec(&imno,descr,II_SIZE,felem,nval);
	

if (status == ERR_NORMAL)
   {
   (void) MID_WDSCRI(fctpntr->IOCHAN,dblock,dindx,values,0,first,nval);

   if (realdescr[0] == 'N') 
      {						/* NAXIS, NPIX also -> FCB */
      int  *npix;

      if (strcmp(realdescr,"NAXIS") == 0) 
         fcbp->DATAINFO[0] = *values;		/* keep FCB info in sync */
      else if (strcmp(realdescr,"NPIX") == 0) 
         {
         if (first < 4) 
            {
            npix = values;
            fcbp->DATAINFO[first++] = *npix++;
            if ( ((--nval) > 0) && (first < 4) )
               {
               fcbp->DATAINFO[first++] = *npix++;
               if ( ((--nval) > 0) && (first < 4) )
                  fcbp->DATAINFO[first] = *npix;
               }
            }
         }
      }
   return ERR_NORMAL;
   }

MID_E2(5,imno,descr,status,1);
return (status);
}
/*

*/

int SCDHWR(imno,descr,values,felem,nval,unit,htext)

int   imno      /* IN : no. of data frame */;
char   *descr   /* IN : descriptor name (max. 48 char.) */;
float *values  /* IN : buffer with descriptor data */;
int felem       /* IN : position of 1st descriptor value to be accessed */;
int  nval       /* IN : no. of data values to write */;
int   *unit     /* IN : unit-pointer */;
char   *htext   /* IN : help text */;

{
int status;


status = SCDWRR(imno,descr,values,felem,nval,unit);

if (status == ERR_NORMAL) (void) wrhelp(imno,descr,htext);
return status;
}



int SCDWRR(imno,descr,values,felem,nval,unit)

/*++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE
Write a descriptor and its data
.ALGORITHM
  A new descriptor is written at the end of the existing 
  descriptor area or exisitng descriptor data is modified
  and extended, if necessary.
.RETURNS
return status  ( 0 = o.k. )
.REMARKS
if 'felem' = -1, descriptor values are appended to existing ones
--------------------------------------------------*/

int   imno	/* IN : no. of data frame */;
char   *descr   /* IN : descriptor name (max. 48 char.) */;
float *values  /* IN : buffer with descriptor data */;
int felem	/* IN : position of 1st descriptor value to be accessed */;
int  nval	/* IN : no. of data values to write */;
int   *unit	/* IN : unit-pointer */;

{
int   status;




dtype[0] = 'R';
help[0] = '\0';
status = wdscdirec(&imno,descr,RR_SIZE,felem,nval);
	

if (status == ERR_NORMAL)
   {
   if (dtype[0] == 'D')			/* write real data to double descr */
      {
      double  *dvals;
      int    *ipntr, n;
      char   *mypntr;

      n = DD_SIZE * nval;
      mypntr = malloc((size_t) n);
      if (mypntr == (char *) 0)
         {
         status = ERR_MEMOUT;
         goto end_of_it;
         }
      dvals = (double *)mypntr;
      for (n=0; n<nval; n++)		/* float -> double data */
         *dvals++ = (double) values[n];
      ipntr = (int *) mypntr;		/* set to start of double data */

      n = DD_SIZE/II_SIZE;
      newlen = n * nval;
      first = (n * first) - 1;			
      (void) MID_WDSCRI(fctpntr->IOCHAN,dblock,dindx,ipntr,0,first,newlen);
      (void) free (mypntr);
      }

   else
      (void) MID_WDSCRR(fctpntr->IOCHAN,dblock,dindx,values,0,first,nval);

   return ERR_NORMAL;
   }
 
end_of_it:
MID_E2(5,imno,descr,status,1);
return (status);
}
/*

*/

int SCDWRH(imno,descr,values,felem,nval)

/*++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE
Write a HELP descriptor and its data
.ALGORITHM
A new descriptor is written at the end of the existing 
descriptor area or existing descriptor data is modified
and extended, if necessary.
.RETURNS
return status  ( 0 = o.k. )
.REMARKS
if 'felem' = -1, descriptor values are appended to existing ones
--------------------------------------------------*/

int   imno	/* IN : no. of data frame */;
char   *descr   /* IN : descriptor name (max. 48 char.) */;
char   *values  /* IN : buffer with descriptor data */;
int felem	/* IN : position of 1st descriptor value to be accessed */;
int nval	/* IN : no. of data values to write */;

{
int   status;




dtype[0] = 'H';	

if (nval > 71) nval = 71;		/* global char.string has 72 chars */
(void) memcpy(help,values,(size_t)nval);
help[nval] = '\0';

status = wdscdirec(&imno,descr,1,felem,nval);

if (status == ERR_NORMAL)
   {
   if (newlen > 0)				/* use static newlen */
      (void) MID_WDSCRC(fctpntr->IOCHAN,dblock,dindx,values,0,first,newlen);
   }
else
   MID_E2(5,imno,descr,status,1);
	
return (status);
}

