/******************************************************************************
*
*  NSSDC/CDF                                            CDFwalk.  Part 1 of 2.
*
*  Version 2.3g, 28-Sep-95, Hughes STX.
*
*  Modification history:
*
*   V1.0  25-Jul-91, H Leckner  Original version (for CDF V2.1).
*   V1.0a  5-Aug-91, J Love     Fixed value input.
*   V1.1  20-Sep-91, J Love     Modified for IBM-PC port.
*   V1.2  11-Oct-91, H Leckner  Changed for IBM-RS6000 port.
*   V1.3  18-Oct-91, H Leckner  More changes for IBM-RS6000 port (and fixed
*                               variable name field).
*   V1.3a 22-Oct-91, J Love     Got the right version this time.
*   V2.0  19-Apr-92, H Leckner  IBM PC port.  CDF V2.2.
*                    J Love
*   V2.1  26-Aug-92, H Leckner  CDF V2.3 (shareable/zVar/NeXT).
*                    J Love
*   V2.2  24-Jan-94, H Leckner  CDF V2.4.
*                    J Love
*   V2.2a  4-Feb-94, J Love     DEC Alpha/OpenVMS port.
*   V2.3   6-Dec-94, J Love     CDF V2.5.
*   V2.3a 10-Jan-95, J Love	Uppercase file extensions on the Macintosh.
*   V2.3b  6-Apr-95, J Love	POSIX.
*   V2.3c  9-May-95, J Love	EPOCH styles.
*   V2.3d 13-Jun-95, J Love	Linux.
*   V2.3e 17-Jul-95, J Love	CDFexport-related changes.
*   V2.3f 18-Sep-95, J Love	Macintosh event handling.
*   V2.3g 28-Sep-95, J Love	Macintosh dialog filtering.  Outline default
*				button.
*
******************************************************************************/

#define CDFWALK 1
#include "cdfwalk.h"

/******************************************************************************
* Global variables (local to this source).
******************************************************************************/

#if defined(BORLANDC)
extern unsigned _stklen = BORLANDC_STACK_SIZE;
#endif

long cacheSize;

/******************************************************************************
* Main.
******************************************************************************/

MAIN {
#if defined(mac)
  strcpyX (pgmName, "CDFwalk", MAX_PROGRAM_NAME_LEN);
  MacExecuteFSI (WalkCDFs, WalkQOPs);
  if (FreeMemory(NULL,FatalError) > 0) DisplayWarning ("Abandoned buffers.");
  return EXIT_SUCCESS_;
#else
  Logical success;
  strcpy (pgmName, "CDFwalk");
  success = WalkCDFs (argc, argv);
  if (FreeMemory(NULL,FatalError) > 0) DisplayWarning ("Abandoned buffers.");
  return BOO(success,EXIT_SUCCESS_,EXIT_FAILURE_);
#endif
}

/******************************************************************************
* WalkCDFs.
******************************************************************************/

Logical WalkCDFs (argC, argV)
int             argC;
char            *argV[];
{
static struct   CDF_struct CDF;
static struct   GLOBAL_struct   screen;
struct          variable_struct **variables;
struct          vid_struct      *VAR_display;
union           mixed           *data_values;
CDFstatus       rcode;
int             i;
long            CDF_is_OPEN = FALSE;
static char     open_mes[] = "Opening CDF...";
long            field_num;
long            exit_code;
long            cdf_input = MANUAL;
char            temp[CDF_PATHNAME_LEN];
int             tcode;
static char     noZ_mes[] = "There are no Z variables in this CDF";
QOP *qop;
static char *validQuals[] = { "initial", "specification", "cache", NULL };
static int optRequired[] = { TRUE, TRUE, TRUE, 0 };

firstForCDFname = TRUE;         /* Global variable reset each execution. */

qop = Qop (argC, argV, validQuals, optRequired);
if (qop == NULL) return FALSE;
switch (qop->Nparms) {
  case 0:
    if (qop->qualEntered[SPECqual]) {
      SO.spec_entered = TRUE;
      strcpy (CDF.CDF_name, qop->qualOpt[SPECqual]);
    }
    else 
      strcpy(CDF.CDF_name, default_name);
    break;
  case 1:
    if (qop->qualEntered[SPECqual]) {
      DisplayError ("Conflicting parameter/qualifier.");
      FreeMemory (qop, FatalError);
      return FALSE;
    }
    else {
      cdf_input = AUTO;
      strcpy (CDF.CDF_name, qop->parms[CDFparm]);
      strcpy (temp, qop->parms[CDFparm]);
      strcat (temp,".cdf");
      if (!IsReg(temp)) cdf_input = DIRECTory;
    }
    break;
  default:
    DisplayError ("Too many parameters.");
    FreeMemory (qop, FatalError);
    return FALSE;
}

/******************************************************************************
* Check for `initial' qualifier.
******************************************************************************/
if (qop->qualEntered[INITIALqual]) {
  /****************************************************************************
  * Check for `[no]format'.  Always check for the `no' version first.
  ****************************************************************************/
  if (strstrIgCase(qop->qualOpt[INITIALqual],"NOFORMAT") != NULL)
    SO.variable_format = NOFORMAT;
  else
    if (strstrIgCase(qop->qualOpt[INITIALqual],"FORMAT") != NULL)
      SO.variable_format = FORMAT;
    else
      SO.variable_format = (DEFAULTformatWALK ? FORMAT : NOFORMAT);
  /****************************************************************************
  * Check for `[no]neg2posfp0'.  Always check for the `no' version first.
  ****************************************************************************/
  if (strstrIgCase(qop->qualOpt[INITIALqual],"NONEG2POSFP0") != NULL)
    SO.zero = NOCONVERT;
  else
    if (strstrIgCase(qop->qualOpt[INITIALqual],"NEG2POSFP0") != NULL)
      SO.zero = CONVERT;
    else
      SO.zero = (DEFAULT_NEGtoPOSfp0 ? CONVERT : NOCONVERT);
}
else {
  /****************************************************************************
  * Defaults when `initial' qualifier not entered.
  ****************************************************************************/
  SO.variable_format = (DEFAULTformatWALK ? FORMAT : NOFORMAT);
  SO.zero = (DEFAULT_NEGtoPOSfp0 ? CONVERT : NOCONVERT);
}

if (qop->qualEntered[CACHEqual]) {
  if (sscanf(qop->qualOpt[CACHEqual],"%ld",&cacheSize) != 1) {
    DisplayError ("Illegal cache size for `.cdf' file.");
    FreeMemory (qop, FatalError);
    return FALSE;
  }
}
else
  cacheSize = 0;

FreeMemory (qop, FatalError);

field_num = CDF_FIELD;
rcode = init_var_display(&VAR_display);
if(rcode != 0) return FALSE;
CDFWALK_open_screen(&screen);

HELP_ptr = OnlineHelpFP ("cdfwalk.hlp", argV[0]);

variables = NULL;
data_values = NULL;
print_string = NULL;
while(field_num != EXIT)
 {
 switch (field_num)
      {
      case CDF_FIELD:
	   CDFWALK_put_selection(screen.CDF_vid, CDF_display,
	   CDFNAME_ELEMENT_NUM-1, CDF.CDF_name, CDF_NAME_LENGTH,
				 REVERSE);
	   if(cdf_input != AUTO)
	      CDFWALK_CDF_name(&screen, &CDF, &field_num, &cdf_input);
	   else
	      field_num = WALK_FIELD;
	   if(field_num != QUITkey_WALK && field_num != EXIT && 
	      strlen(CDF.CDF_name) > (size_t) 0)
	      {
	      if(CDF_is_OPEN)
		 {
		 CDFWALK_close(&CDF, variables);
		 if(data_values != NULL) {
		    free(data_values);
		    data_values = NULL;
		  }
		 if(print_string != NULL)
		    {
		    free(print_string);
		    print_string = NULL;
		    }
		 }
	      CDFWALK_put_message(screen.MES_vid, open_mes, NOBELL, BLINKING,
		NOPAUSE);
	      for (i=0; i < CDF_MAX_DIMS; i++)
		   CDF.dim_var_num[i] = NOTTHERE;
	      rcode = CDFWALK_open(&CDF, &variables, &data_values);
	      cdf_input = MANUAL;
	      if((rcode < CDF_OK) || (rcode == NODATA || rcode == NOVARS))
		    {
		    exit_code = print_error(&screen, rcode);
		    if(exit_code == NOCONTINUE)field_num = CDF_FIELD;
		    CDF_is_OPEN = FALSE;
		    }
	      else
		    {
		    CDF_is_OPEN = TRUE;
		    CDFWALK_CDF_info(&screen, &CDF, CDF_display);
		    CDFWALK_clear_row(screen.VAR_vid, VAR_display, 1, 54,
		    VAR_COLUMNS);
		    CDFWALK_clear_row(screen.MES_vid, MES_display, 1, 1,
		    MES_COLUMNS);
		    }
	      }
	   break;
      case WALK_FIELD:
	   CDFWALK_list(&screen, &CDF, *(variables+SO.curr_CDF), VAR_display,
			data_values, &field_num);

	   break;
      case RZ_FIELD:
	   if(CDF.numZvars > 0)
	      {
	      int last_group;
	      last_group = SO.curr_CDF;
	      rcode = CDFWALK_select_RZ(&screen, &CDF, &tcode);
	      if(rcode < CDF_OK)
		 {
		 exit_code = print_error(&screen, rcode);
		 if(exit_code == NOCONTINUE) return FALSE;
		 }
	      else if(tcode != QUITkey_WALK)
		 {
		 CDFWALK_CDF_info(&screen, &CDF, CDF_display);
		 CDFWALK_clear_row(screen.VAR_vid, VAR_display, 1, 54,
		    VAR_COLUMNS);
		 CDFWALK_clear_row(screen.MES_vid, MES_display, 1, 1,
		    MES_COLUMNS);
		 if(SO.curr_CDF != last_group) {
		   for (i=0; i < CDF_MAX_DIMS; i++)
		     CDF.dim_var_num[i] = NOTTHERE;
		   }
		 }
	      }
	   else
	      CDFWALK_put_message(screen.MES_vid, noZ_mes, RINGBELL, NORMAL,
					PAUSE);
	   field_num = WALK_FIELD;
	   break;
      case HELP_FIELD:
	   CDFWALK_help(&screen);
	   CDFWALK_field_menu(&screen, CDF.CDF_id, &field_num);
      }
  }
if(HELP_ptr != NULL)fclose(HELP_ptr);
free(VAR_display);
if(data_values != NULL) {
   free(data_values);
   data_values = NULL;
 }
if(print_string != NULL) {
   free(print_string);
   print_string = NULL;
 }
if(CDF_is_OPEN)CDFWALK_close(&CDF, variables);

CDFWALK_close_screen();
return TRUE;
}

long     print_error(screen, rcode)
struct          GLOBAL_struct   *screen;
CDFstatus       rcode;
{
long            exit_code;
char    error_mes[CDF_ERRTEXT_LEN];
if(rcode == NODATA)
   {
   exit_code = NOCONTINUE;
   strcpy(error_mes, "This CDF contains no records");
   }
else if(rcode == NOVARS)
   {
   exit_code = NOCONTINUE;
   strcpy(error_mes, "This CDF contains no variables");
   }
else
   {
   if(rcode < CDF_WARN)
	exit_code = NOCONTINUE;
   else if(rcode < CDF_OK)
	exit_code = CONTINUEkey_WALK;
   else if(rcode != CDF_OK)
	exit_code = CONTINUEkey_WALK;
/*
Get the error message
*/
   CDFerror(rcode, error_mes);
   }
/*
Print the message
*/
CDFWALK_put_message(S.MES_vid, error_mes, RINGBELL, NORMAL, PAUSE);
return(exit_code);
}
long    which_cdf(num_ZCDF, num_dims, ds, all_num_dims, all_dim_sizes)
long    num_ZCDF;
long    num_dims;
long    *ds;
long    *all_num_dims;
long    **all_dim_sizes;
{
int    k,found,j;

found = FALSE;
for(k=1; k<num_ZCDF && !found; k++)
    {
    if(num_dims != all_num_dims[k])
       found=FALSE;
    else
       {
       found=TRUE;
       for(j=0; j<num_dims; j++)
	   {
	   if(ds[j] != all_dim_sizes[k][j])found=FALSE;
	   }
       if(found)return(k);
       }
    }
return(-1);
}
int alloc_all_dim(ptr, num_vars, num_dims)
long            ***ptr;
long            num_vars;
long            num_dims;
{
int            i;
long            num;

if((*ptr = (long     **)
    malloc((size_t) (num_dims+1) * sizeof(long *))) == NULL)
    return(-1);
else
    {
    num = num_vars > num_dims ? num_vars+1 : num_dims+1;
    for(i=0; i<num_dims+1; i++)
       {
       if(((*ptr)[i] =
	   (long *) malloc((size_t) num * sizeof(long))) == NULL)
	   return(-1);
       }
    }
return(0);
}

void free_all_dim(ptr, num_dims)
long            **ptr;
long            num_dims;
{
int            i;
for(i=0; i<num_dims+1; i++)free(ptr[i]);
free(ptr);
}
CDFstatus       load_sizes(CDF)
struct          CDF_struct      *CDF;
{
long            ds[10];
char            var_mnemonic[CDF_VAR_NAME_LEN];
long            num_dims;
CDFstatus       status;
int             i,j,k;
long            **save,**replay,**saveZ;
long            found;

status = CDFlib (SELECT_, CDF_, C.CDF_id,
		      GET_, rVARs_NUMDIMS_, &CDF->num_dims[0],
			    rVARs_DIMSIZES_, *CDF->dim_sizes,
		      NULL_);
if(status < CDF_OK)return(status);
C.num_ZCDF = 1;
save = C.dim_sizes;
C.dim_sizes++;
saveZ = C.dim_sizes;

for(i=0; i<C.numZvars; i++)
    {
    status = CDFlib (SELECT_, CDF_, C.CDF_id,
			    zVAR_, i,
		      GET_, zVAR_NUMDIMS_, &num_dims,
			    zVAR_DIMSIZES_, ds,
			    zVAR_NAME_, var_mnemonic,
		      NULL_);
    if(C.num_ZCDF > 1)
       {
       replay = saveZ;
       found = FALSE;
       for(k=1; k<C.num_ZCDF && !found; k++)
	   {
	   if(num_dims != C.num_dims[k])
	      found=FALSE;
	   else
	      {
	      found=TRUE;
	      for(j=0; j<num_dims; j++)
		  {
		  if(ds[j] != (*replay)[j])found=FALSE;
		  }
	      }
	   replay++;
	   }
	   if(!found)
	      {
	      C.num_dims[(int)(C.num_ZCDF++)] = num_dims;
	      for(j=0; j<num_dims; j++)(*CDF->dim_sizes)[j] = ds[j];
	      C.dim_sizes++;
	      }
	}
    else
	{
	C.num_dims[(int)C.num_ZCDF] = num_dims;
	for(j=0; j<num_dims; j++) (*CDF->dim_sizes)[j] = ds[j];
	C.dim_sizes++;
	C.num_ZCDF++;
	}
    }
CDF->dim_sizes = save;
return(CDF_OK);
}

CDFstatus alloc_sizes(numDims, dim_sizes, num_vars, max_record_num, numZvars)
long            **numDims;
long            ***dim_sizes;
long            **num_vars;
long            **max_record_num;
long            numZvars;
{
int            i;

if((*numDims = (long *) malloc((size_t) (numZvars+1) * sizeof(long))) == NULL)
	   return(BAD_MALLOC);

if((*dim_sizes = (long     **)
    malloc((size_t) (numZvars+1) * sizeof(long *))) == NULL)
    return(BAD_MALLOC);
else
    {
    for(i=0; i<numZvars+1; i++)
       {
       if(((*dim_sizes)[i] =
	   (long *) malloc(CDF_MAX_DIMS * sizeof(long))) == NULL)
	   return(BAD_MALLOC);
       }
    }
if((*num_vars = (long *) malloc((size_t) (numZvars+1) * sizeof(long))) == NULL)
	   return(BAD_MALLOC);
if((*max_record_num=(long *)malloc((size_t)(numZvars+1)*sizeof(long))) == NULL)
	   return(BAD_MALLOC);

return(CDF_OK);
}


CDFstatus alloc_vars(variables, numZCDF, numRvars, numZvars)
struct variable_struct  ***variables;
long            numZCDF;
long            numRvars;
long            numZvars;
{
int            i;
long            nv;

if ((*variables = (struct variable_struct **)
    malloc((size_t) numZCDF * sizeof(struct variable_struct *))) == NULL)
    return(BAD_MALLOC);
else
    {
    for(i=0; i<numZCDF; i++)
       {
       nv = i == 0 ? numRvars : numZvars;
       if(nv > 0)
	  {
	  if(((*variables)[i] =
	   (struct variable_struct *) malloc((size_t) nv *
	    sizeof(struct variable_struct))) == NULL)
	    return(BAD_MALLOC);
	  }
       else
	  (*variables)[i] = NULL;
       }
    }
return(CDF_OK);
}
CDFstatus CDFWALK_open(CDF, variables, data_values)
struct          CDF_struct      *CDF;
struct          variable_struct ***variables;
union           mixed           **data_values;
{
CDFstatus               rcode;
int                     Z;
int                    i,j;
long                    var_num;
long                    max_bytes = 0;
long                    data_type;
long                    format_attr_num;
char                    temp[CDF_VAR_NAME_LEN+1];
int                     k;
int                    index;
long                    num_dims,ds[CDF_MAX_DIMS];
int                     ok;
long                    max_record_num;

long                    convert0;
convert0 = SO.zero == CONVERT ? NEGtoPOSfp0on : NEGtoPOSfp0off; 
/*
Open the CDF
*/
rcode = CDFlib (OPEN_, CDF_, C.CDF_name, &C.CDF_id,
		SELECT_, CDF_NEGtoPOSfp0_MODE_, convert0, 
		 NULL_);
if(rcode < CDF_OK)return (rcode);

rcode = CDFlib (SELECT_, CDF_, C.CDF_id,
		 GET_, CDF_NUMrVARS_, &C.numRvars,
		       CDF_NUMzVARS_, &C.numZvars,
		       NULL_);
if(C.numRvars > 0)
   SO.curr_CDF = REGULAR;
else
   SO.curr_CDF = 1;

C.total_vars = C.numRvars + C.numZvars;
if(C.total_vars == 0)return(NOVARS);
C.num_vars = NULL;
C.dim_sizes = NULL;
C.num_vars = NULL;
C.max_record_num = NULL;

rcode = alloc_sizes(&C.num_dims, &C.dim_sizes, &C.num_vars, &C.max_record_num,
			C.numZvars);

if(rcode < CDF_OK)return(rcode);

rcode = load_sizes(CDF);
if(rcode < CDF_OK)return(rcode);

rcode = alloc_vars(variables, C.num_ZCDF, C.numRvars, C.numZvars);
if(rcode < CDF_OK)return(rcode);

for(i=0; i<C.numZvars+1; i++)
    {
    C.num_vars[i] = 0;
    C.max_record_num[i] = -1;
    }
C.num_scalars = 0;
C.EPOCH_var_num = NOTTHERE;
C.first_scalar_var_num = NOTTHERE;
C.record_var_num = NOTTHERE;
rcode = CDFlib (SELECT_, CDF_, C.CDF_id,
		 GET_, ATTR_NUMBER_, "FORMAT", &format_attr_num,
		 NULL_);
if(rcode < CDF_WARN)
   {
   SO.variable_format  = NOFORMAT;
   SO.format      = FALSE;
   rcode = CDF_OK;
   }
else
   SO.format      = TRUE;

/*
Get all the variables in the CDF
*/
for(j=0; j<C.total_vars; j++)
    {
    if(j < C.numRvars)
       {
       var_num = j;
       k = 0;
       rcode = CDFlib (SELECT_, CDF_, C.CDF_id,
			    rVAR_, var_num,
		      GET_, rVAR_MAXREC_, &max_record_num,
		      NULL_);
       if(rcode < CDF_OK)return (rcode);
       Z = FALSE;
       }
    else
       {
       var_num = j - C.numRvars;
       rcode = CDFlib (SELECT_, CDF_, C.CDF_id,
			    zVAR_, var_num,
		      GET_, zVAR_NUMDIMS_, &num_dims,
			    zVAR_DIMSIZES_, ds,
			    zVAR_MAXREC_, &max_record_num,
		      NULL_);
       if(rcode < CDF_OK)return (rcode);
       k = (int) which_cdf(C.num_ZCDF, num_dims, ds, C.num_dims, C.dim_sizes);
       Z = TRUE;
       }
    if(max_record_num > C.max_record_num[k])
	C.max_record_num[k] = max_record_num;
    index = (int) C.num_vars[k]++;
    VN.Z = Z;
    VN.max_record_num = max_record_num;
    for(i=0; i<CDF_MAX_DIMS; i++)
	VN.dim_variances[i] = FALSE;
    for(i=0; i<CDFWALK_MAX_VAR_LENGTH; i++)VN.var_mnemonic[i] =  ' ';
    rcode=CDFlib(SELECT_, CDF_, C.CDF_id,
			Zq(Z,zVAR_,rVAR_),                  var_num,
		  GET_, Zq(Z,zVAR_NAME_,rVAR_NAME_),         temp,
			Zq(Z,zVAR_DATATYPE_,rVAR_DATATYPE_),&VN.data_type,
			Zq(Z,zVAR_NUMELEMS_,rVAR_NUMELEMS_),&VN.num_bytes,
			Zq(Z,zVAR_RECVARY_,rVAR_RECVARY_),  &VN.record_variance,
			Zq(Z,zVAR_DIMVARYS_,rVAR_DIMVARYS_), VN.dim_variances,
		       NULL_);
    if(rcode < CDF_OK)return (rcode);
    else
       {
       strncpy(VN.var_mnemonic, temp, CDFWALK_MAX_VAR_LENGTH);
       VN.var_mnemonic[CDFWALK_MAX_VAR_LENGTH] = '\0';
       VN.var_num = var_num;
       VN.dim_variable = FALSE;
       VN.record_variable = FALSE;
       VN.filter = FALSE;
       VN.scalar = SCALAR;
       VN.bin_value = NULL;
       VN.char_value = NULL;
       }
    VN.format = FALSE;
    VN.format_value = NULL;
    if(SO.format)
       {
       rcode = CDFlib (SELECT_, CDF_,                   C.CDF_id,
			  ATTR_,                format_attr_num,
			  Zq(Z,zENTRY_,rENTRY_),var_num,
		 GET_,    Zq(Z,zENTRY_DATATYPE_,rENTRY_DATATYPE_),
				&data_type,
			  Zq(Z,zENTRY_NUMELEMS_, rENTRY_NUMELEMS_),
				&VN.format_num_elements,
		 NULL_);
       if(rcode >= CDF_OK)
	  {
	  VN.format_value = (void *) malloc((size_t)(VN.format_num_elements+1));
	  if(VN.format_value != NULL)
	     {
	     rcode = CDFlib (SELECT_, CDF_,     C.CDF_id,
			     ATTR_,             format_attr_num,
				   Zq(Z,zENTRY_,rENTRY_),var_num,
			     GET_, Zq(Z,zENTRY_DATA_,rENTRY_DATA_),
				   VN.format_value,
			     NULL_);
	     VN.format_value[(int)VN.format_num_elements]='\0';
	     if(rcode >=  CDF_OK)
	       VN.format = TRUE;
	     else
	       rcode = CDF_OK;
	     }
	  }
       else
	 rcode = CDF_OK;
       }

/*
Find out the largest number of bytes for all variables
*/
   if(VN.data_type == CDF_EPOCH)
	   {
	   if( max_bytes < 25)max_bytes = 25;
	   }
   else if(VN.data_type == CDF_CHAR || VN.data_type == CDF_UCHAR)
	   {
	   if( VN.num_bytes+2 > max_bytes)max_bytes = VN.num_bytes+2;
	   }
   else if( max_bytes < 14) max_bytes = 14;

   }/*var loop*/

ok = FALSE;
for(k=0; k<C.num_ZCDF || !ok; k++)
    {
    if(C.max_record_num[k] >= 0)ok = TRUE;
    }
/*
CDF contains no data, nothing to WALK thru
*/
if(!ok)
  return(NODATA);
/*
There are no data in the rVariables, use the zVariables
*/
else if(C.numRvars > 0 && C.max_record_num[0] == -1)
       SO.curr_CDF = 1;
/*
create global variable to display data with
*/
  print_string = (char *) malloc((size_t)(max_bytes+2));
  if(print_string == NULL)return(BAD_MALLOC);

  *data_values = (union mixed *) malloc((size_t) C.total_vars *
						 sizeof(union mixed));
  if(*data_values == NULL)return(BAD_MALLOC);

return (rcode);
}
void CDFWALK_load_dim(CDF, variables, DIM_display, dim_num, num_rows)
struct CDF_struct       *CDF;
struct variable_struct  *variables;
struct vid_struct       *DIM_display;
long                    dim_num;
int                     *num_rows;
{
int                    i;

for(i=0; i<C.num_per_dim[(int)dim_num]; i++)
    {
    DIM_display[i].row = 1;
    DIM_display[i].col = 1;
    strcpy(DIM_display[i].label,
	   variables[(int)C.all_dim_var_num[(int)dim_num][i]].var_mnemonic);
    }
*num_rows = (int) (C.num_per_dim[(int)dim_num] > DIM_ROWS ? DIM_ROWS : 
		   C.num_per_dim[(int)dim_num]);
}

int load_all_dim(CDF, variables)
struct  CDF_struct      *CDF;
struct  variable_struct *variables;
{
int                     rcode;
long                    num;
long                    var_num;
int                    i,j;
long                    dim_num;
long                    num_true;

rcode = alloc_all_dim(&C.all_dim_var_num, C.num_vars[SO.curr_CDF],
	/*CDF_MAX_DIMS*/C.num_dims[SO.curr_CDF]);

if(rcode != 0)return(rcode);

num = C.num_vars[SO.curr_CDF] > C.num_dims[SO.curr_CDF] ? 
      C.num_vars[SO.curr_CDF]+1 : C.num_dims[SO.curr_CDF]+1;
for(i=0; i<C.num_dims[SO.curr_CDF]+1; i++)
    {
    C.num_per_dim[i] = 0;
    for(j=0; j<num; j++)
	C.all_dim_var_num[i][j] = 0;
    }
for(var_num=0; var_num<C.num_vars[SO.curr_CDF]; var_num++)
    {
/*
Check for a scalar or dimensionally variant variable
*/
    num_true = 0;
    for (i=0; i< C.num_dims[SO.curr_CDF]; i++)
	 {
	 if(V.dim_variances[i] != NOVARY)
	    {
	    dim_num=i+1;
	    num_true++;
	    V.scalar = FALSE;
	    }
	 }
    if(num_true == 1 && !V.record_variance)
       {
       C.all_dim_var_num[(int)dim_num][(int)(C.num_per_dim[(int)dim_num]++)] = var_num;
       V.dim_num = dim_num;
       V.num_values=C.dim_sizes[(int)SO.curr_CDF][(int)(dim_num-1)];
       }
    else
       {
       if(!V.record_variance && num_true > 1)
	   V.dim_num = MULTIPLE;
       else
	   V.dim_num = 0;
       V.num_values=0;
       }
    if(V.scalar)
       {
       C.all_dim_var_num[0][(int)(C.num_per_dim[0]++)] = var_num;
       V.num_values = V.max_record_num+1;
       }
    }

return(0);
}

void CDFWALK_list(screen, CDF, variables, VAR_display, data_values,
		curr_field)
struct  GLOBAL_struct   *screen;
struct  CDF_struct      *CDF;
struct  variable_struct *variables;
struct vid_struct       *VAR_display;
union   mixed           *data_values;
long                    *curr_field;
{
struct  vid_struct      *DIS_display;
struct  vid_struct      *DIM_display;
long                    var_index = 0;
long                    var_num;
long                    val_num = 1;
long                     num;
long                    dim_num;
long                    field_num;
long                    col_field;
int                     row;
int                     tcode;
int                     r2;
long                    record_num;
long                    indices[10];
char                    buf[7], buf3[25];
char                    temp[80];
int                    i;
static char             dim_number[] = "1234567890";
static char             record_error_mes[] =
"Record number out of range, valid range is from 1 - ";
static char             indices_error_mes[] =
"Index out of range, valid range is from 1 - ";
static char             input_error_mes[] =
"Error detected in input string ";
static char             noscroll_mes[] =
"All variables are currently displayed on screen";
static char             value_input_mes[] =
"Enter desired value from variable ";
static char             EPOCH_input_mes[] =
"Enter a desired time from the CDF ";
static char             record_input_mes[] =
"Enter record number or a number preceded by +/- to increment or decrement";
static char             indices_input_mes[] =
"Enter index number or a number preceded by +/- to increment or decrement";
AOSs1 (record_indices_mes,
"__________/__________=+/- thru records/indices, _____=input a record/index")
AOSs1A (value_mes,
"__________/__________=+/- thru values,___=input value,_____=select value popup")
static char             load_data_mes[] =
"Loading data from CDF...";
static char             select_begin_mes[] =
"Multiple variables describe ";
static char             select_end_mes[] =
" select one for filtering/display";
static char             no_var_mes[] =
"No variables in CDF describe ";
static char             to_many_mes[] =
"This variable contains too many values to select from popup, select manually";
static char             nodata_mes[] =
"This variable contains no data";
static char             scan_mes[] =
"Scanning for selected data...";
char                    mes[80];
long                    type;
long                    offset;
int                     dis_rows, dis_cols;
int                     dim_rows;
long                    num_bytes;
long                    value;
double                  rvalue;
long                    update_keydef;
int                     len;
long                    rcode;
static long             offsets[2] = {  9, 46 };
static long             lengths[2] = { 24,  6 };
static long             scolumns[2] = { 33, 52 };
static int exit_keys[] = { SELECTkey_WALK, ACTIONkey_WALK, NUL };
EncodeKeyDefinitions(1, record_indices_mes, PREVRECORDkey_WALK, 
		     NEXTRECORDkey_WALK, INPUTkey_WALK);
EncodeKeyDefinitions(1, value_mes, PREVRECORDkey_WALK, 
	NEXTRECORDkey_WALK, INPUTkey_WALK, POPUPkey_WALK);
r2  = load_all_dim(CDF, variables);
if(r2 != 0)ExitBAD;

for(var_num=0; var_num<C.num_vars[SO.curr_CDF]; var_num++) {
    V.record_variable = FALSE;
    V.dim_variable = FALSE;
  }
create_virtual_display((int)(C.num_dims[(int)SO.curr_CDF]+1+BORDER_ROWS), 
		       WALK_COLUMNS+BORDER_COLUMNS, &S.WALK_vid, BORDER, NORMAL);
begin_pasteboard_update();
put_chars(S.WALK_vid, "Record#", 7, 1, 39, ERASE, NORMAL);
/*
Now find  the variables that vary with each dimension and place them on the screen
*/
for(dim_num = 0; dim_num < C.num_dims[SO.curr_CDF]; ++dim_num)
    {
    for(i=0; i<WALK_COLUMNS; i++)temp[i] = ' ';
    strcpy(temp, "Dimension");
    strncpy(temp+9, dim_number + (int) dim_num, 1);
    temp[10] = '\0';
    put_chars(S.WALK_vid, temp, 10, (int) (dim_num+2), 36, ERASE, NORMAL);
    }
paste_virtual_display(S.WALK_vid, WALK_ROW_PASTE, WALK_COL_PASTE);
label_border(S.WALK_vid, WALK_label, REVERSE);
end_pasteboard_update();
/*
Choose a variable for record and each dimension to be displayed in the
WALK window for each dimension if applicable
*/
for(dim_num=0; dim_num<=C.num_dims[SO.curr_CDF]; dim_num++)
 {
 if(C.num_per_dim[(int)dim_num] > 0)
    {
    if(C.dim_var_num[(int)dim_num] == NOTTHERE)
       num = 1;
    else
       {
/*
       if(dim_num == RECORD)
	  variables[C.dim_var_num[dim_num]].record_variable = FALSE;
       else
	  variables[C.dim_var_num[dim_num]].dim_variable = FALSE; 
*/
       for(i=0; i<C.num_per_dim[(int)dim_num]; i++)
	   {
	   if(C.dim_var_num[(int)dim_num] ==
				C.all_dim_var_num[(int)dim_num][i])num=i+1;
	   }
       }
    if(C.num_per_dim[(int)dim_num] > 1)
       {
       DIM_display = (struct vid_struct *)
		    malloc((size_t) C.num_per_dim[(int)dim_num] *
				    sizeof(struct vid_struct));
       CDFWALK_load_dim(CDF, variables, DIM_display, dim_num, &dim_rows);
       create_virtual_display(dim_rows+BORDER_ROWS, DIM_COLUMNS+BORDER_COLUMNS,
				 &S.DIM_vid, BORDER, NORMAL);
       strcpy(mes, select_begin_mes);
       if(dim_num == 0)
	  strcat(mes,"Record Number,");
       else
	  {
	  strcat(mes,"Dimension ");
	  strncpy(mes+38, dim_number + (int) (dim_num-1), 1);
	  mes[39] = ',';
	  mes[40] = '\0';
	  }
       strcat(mes,select_end_mes);
       CDFWALK_put_message(S.MES_vid, mes, NOBELL, NORMAL, NOPAUSE);

       CDFWALK_Menu_keydef(screen);
       CDFWALK_select_menu_item(S.DIM_vid,
	 S.MES_vid, &num, DIM_display, (int) C.num_per_dim[(int)dim_num],
	 dim_rows, DIM_COLUMNS, DIM_ROW_PASTE, DIM_COL_PASTE,
	 MENU, &tcode);
       delete_virtual_display(S.DIM_vid);
       free(DIM_display);
       } /* num_per_dim > 1 */
/*
Only one variable describes this variable or dimension
*/

       if(dim_num != RECORD)
	  {
	  var_num = C.all_dim_var_num[(int)dim_num][(int)(num-1)];
	  C.dim_var_num[(int)dim_num] = var_num;
	  V.dim_variable = TRUE;
	  }
       else
	  {
	  var_num = C.all_dim_var_num[RECORD][(int)(num-1)];
	  C.dim_var_num[RECORD] = var_num;
	  V.record_variable = TRUE;
	  }
       if(V.num_values > 0 && V.num_values <= MAX_VALUES)
       {
       if(V.data_type == CDF_EPOCH)
	  {
	  if((V.bin_value = (double *)
	      malloc((size_t) V.num_values * sizeof(double))) == NULL)
	      {
		FatalError ("Error allocating EPOCH binary discrete ptr.");
	      }
	  if((V.char_value = (char *)
	    malloc((size_t) V.num_values*EPOCH_WIDTH)) == NULL)
	    {
	      FatalError ("Error allocating EPOCH character discrete ptr.");
	    }
/*
Retrieve EPOCH values from CDF
*/
	 CDFWALK_get_EPOCH(C.CDF_id, V.Z, V.var_num,
			   C.max_record_num[SO.curr_CDF], V.bin_value,
							  V.char_value);
	  }
       else if(V.data_type != CDF_CHAR && V.data_type != CDF_UCHAR)
	     {
	     if((V.bin_value = (double *)
		 malloc((size_t) V.num_values * sizeof(double))) == NULL)
		 {
		   char tempS[MAX_MESSAGE_TEXT_LEN+1];
		   sprintf(tempS,
			   "Error allocating binary discrete ptr, %ld %ld.",
			   V.var_num, V.num_values);
		   FatalError (tempS);
		 }
	     if((V.char_value = (char *)
		 malloc((size_t) V.num_values*MINMAX_SIZE)) == NULL)
		 {
		   FatalError ("Error allocating character discrete ptr.");
		 }
/*
Retrieve binary values from the CDF if variable describes a dimension
*/
	    CDFWALK_get_discrete(C.CDF_id, V.Z, dim_num, V.var_num, V.data_type,
				  V.num_values, V.bin_value, V.char_value);
	     }
	  else
	     {
	     if((V.char_value = (char *)
		 malloc((size_t)(V.num_values*(V.num_bytes+1)))) == NULL)
		 {
		   FatalError ("Error allocating character discrete ptr.");
		 }
/*
Retrieve character values from the CDF if variable describes a dimension
*/
	     CDFWALK_get_discrete_char(C.CDF_id, V.Z, dim_num, V.var_num,
		V.num_values, V.num_bytes, V.char_value);
	     }
       } /* MAX_VALUES?? */
       len = strlen(V.var_mnemonic);
       if(len > CDFWALK_MAX_VAR_LENGTH)len = CDFWALK_MAX_VAR_LENGTH;
       put_chars(S.WALK_vid, V.var_mnemonic, len, (int)(dim_num+1),1,NOERASE,NORMAL);
    } /* num_dim > 0 */
 else
    {
    strcpy(mes, no_var_mes);
    if(dim_num == 0)
       strcat(mes,"Record Number ");
    else
       {
       strcat(mes,"Dimension ");
       strncpy(mes+39, dim_number + (int) (dim_num - 1), 1);
       mes[40] = '\0';
       }
    CDFWALK_put_message(S.MES_vid, mes, RINGBELL, NORMAL, PAUSE);
    }
    for(i=0; i<80; i++)mes[i] = ' ';
 }/*end dim loop*/

CDFWALK_alloc_STRING(variables, C.num_vars[SO.curr_CDF], data_values);

CDFWALK_put_message(S.MES_vid, load_data_mes, NOBELL, BLINKING, NOPAUSE);

update_keydef = TRUE;
record_num = 0;
for(dim_num=0; dim_num<C.num_dims[SO.curr_CDF]; dim_num++)indices[(int)dim_num] = 0;
field_num = 0;
if(C.num_per_dim[0] > 0)
   col_field = 0;
else
   col_field = 1;

while(*curr_field == WALK_FIELD)
     {
     sprintf(buf, "%6ld", record_num+1);
     put_chars(S.WALK_vid, buf, strlen(buf), 1, WALK_COLUMNS-5,
		NOERASE, NORMAL);
     for(dim_num=0; dim_num<C.num_dims[SO.curr_CDF]; dim_num++)
	 {
	 sprintf(buf, "%6ld", indices[(int)dim_num] + 1);
	 row = (int) (dim_num + 2);
	 put_chars(S.WALK_vid,buf, strlen(buf),row, WALK_COLUMNS-5,
		NOERASE, NORMAL);
	 }
/*
Retrieve the data for the current record and set of indices
*/
     CDFWALK_get_data(CDF, variables, C.num_vars[SO.curr_CDF], record_num, indices,
			data_values);

/*
Now display the current set of variables and data
*/
     CDFWALK_load_var(screen, CDF, variables, VAR_display, var_index,
		data_values);
     row = (int) (field_num + 1);
     if(col_field == 0)
	CDFWALK_put_message(S.MES_vid, value_mes[0], NOBELL, NORMAL, NOPAUSE);
     else
	CDFWALK_put_message(S.MES_vid, record_indices_mes[0], NOBELL, NORMAL,
					NOPAUSE);
     if (update_keydef) CDFWALK_walk_keydef(screen);
     update_keydef = FALSE;
     set_cursor_abs(S.WALK_vid, (int) row, (int) scolumns[(int)col_field]);

     read_input(
#if defined(CURSESui)
		S.WALK_vid,
#endif
			   &tcode, PASSTHRUri, TRUE);
     switch (tcode)
	     {
	     case NEXTRECORDkey_WALK:
/*
 * Increment the record number
 */
		  if(field_num == 0)
		     {
		     record_num++;
		     if(record_num > C.max_record_num[SO.curr_CDF])
			record_num = 0;
		     }
		  else
/*
 * Increment the current dimension indice
 */
		     {
		     indices[(int)(field_num-1)]++;
		     if(indices[(int)(field_num-1)] ==
			C.dim_sizes[SO.curr_CDF][(int)(field_num-1)])
					     indices[(int)(field_num-1)]=0;
		     }
	     break;

	     case PREVRECORDkey_WALK:
/*
 *  Decrement the record number
 */
		  if (field_num == 0)
		    {
		      record_num--;
		      if(record_num < 0) record_num = 
			C.max_record_num[SO.curr_CDF];
		    }
		  else
/*
 *   Decrement the current dimension indice
 */
		    {
		      indices[(int)(field_num-1)]--;
		      if (indices[(int)(field_num-1)] < 0)
			indices[(int)(field_num-1)] =
			  C.dim_sizes[SO.curr_CDF][(int)(field_num-1)] - 1;
		    }
		  break;

	     case PREVRECDIMkey_WALK:
/*
 *  Move up to record or dimension on the screen
 */
		  field_num--;
		  if(field_num < 0) field_num = C.num_dims[SO.curr_CDF];
		  if(C.num_per_dim[(int)field_num] == 0) col_field = 1;
		  break;

	     case NEXTRECDIMkey_WALK:
/*
 *  Move down to record or dimension on the screen
 */
		  field_num++;
		  if (field_num > C.num_dims[SO.curr_CDF]) field_num = 0;
		  if (C.num_per_dim[(int)field_num] == 0) col_field = 1;
	     break;

	     case NEXTFIELDkey_WALK:
		  col_field++;
		  if (col_field > 1)
		    {
		      col_field = 0;
		      field_num++;
		      if (field_num > C.num_dims[SO.curr_CDF]) field_num = 0;
		      if (C.num_per_dim[(int)field_num] == 0) col_field = 1;
		    }
		  break;

	     case PREVFIELDkey_WALK:
		  col_field--;
		  if (col_field < 0)
		    {
		      col_field = 1;
		      field_num--;
		      if (field_num < 0)field_num = C.num_dims[SO.curr_CDF];
		    }
		  else if (C.num_per_dim[(int)field_num] == 0)
		    col_field = 1;
		  break;

	     case INPUTkey_WALK:
/*
 *  Input a record number, indice, or value
 */
		  read_display(S.WALK_vid, row, temp);
		  strncpy(buf3, temp + (int) offsets[(int)col_field],
			  (size_t) lengths[(int)col_field]);
		  buf3[(int)lengths[(int)col_field]] = '\0';
		  CDFWALK_left_justify(buf3);

		  put_chars(S.WALK_vid, buf3, strlen(buf3), row,
			    (int) offsets[(int)col_field]+1, NOERASE, REVERSE);
		  if (col_field == 0)
		    {
		      var_num = C.dim_var_num[(int)field_num];

		      if (V.data_type == CDF_EPOCH)
			{
			  label_border(S.WALK_vid, WALK_EPOCH_label, REVERSE);
			  strcpy(mes, EPOCH_input_mes);
			}
		      else
			{
			  strcpy(mes, value_input_mes);
			  strcat(mes, V.var_mnemonic);
			}
		      CDFWALK_put_message(S.MES_vid, mes, NOBELL, NORMAL,
					  NOPAUSE);
		    }
		  else
		    {
		      if (field_num == 0)
			CDFWALK_put_message(S.MES_vid, record_input_mes,
					    NOBELL, NORMAL, NOPAUSE);
		      else
			CDFWALK_put_message(S.MES_vid, indices_input_mes,
					    NOBELL, NORMAL, NOPAUSE);
		    }
		  input_field(S.WALK_vid, buf3, row, (int) offsets[(int)col_field]+1,
		    (int)lengths[(int)col_field], exit_keys, &tcode, 
		    INSERTTOGGLEkey_WALK, MOVEtoBEGINkey_WALK, MOVEtoENDkey_WALK, 
		     NOTTHERE, DELETEtoENDkey_WALK, REFRESHkey_FSI);
		  if (col_field == 0)
		    {
/*
 *      Input actual value
 */
		      if (V.data_type != CDF_CHAR && V.data_type != CDF_UCHAR)
			{
			  if (V.data_type == CDF_EPOCH)
			    rvalue = check_epoch(buf3);
			  else
			    rcode = sscanf(buf3, "%lf", &rvalue);   /*V1.0a*/
/*
 *      Retrieve closest indice
 */

			if (rvalue == -1.0)
			  CDFWALK_put_message(S.MES_vid, input_error_mes,
					      RINGBELL, NORMAL, PAUSE);
			else
			  {
			    CDFWALK_put_message(S.MES_vid, scan_mes,
						 NOBELL, BLINKING, NOPAUSE);
			    value = CDFWALK_get_index(C.CDF_id, V.Z, V.dim_num,
					 V.var_num, rvalue, V.data_type,
					 V.bin_value, V.num_values);
			  }
			}
		      else
			{
			  CDFWALK_put_message(S.MES_vid, scan_mes,
					      NOBELL, BLINKING, NOPAUSE);
			  value = CDFWALK_get_index_char(C.CDF_id, V.Z,
						 V.dim_num, V.var_num,
						 buf3, V.num_bytes,
						 V.char_value, V.num_values);
			  rcode = TRUE;
			}
		      type = NORMAL;
		    }
		  else
/*
 *     Input record number or indice
 */
		    {
		      if (strchr(buf3, '+'))
/*
 *  inputing a + in the first character causes the value to be incremented
 *  by the specified amount
 */
			{
			  type = INCREMENT;
			  offset = 1;
			}
		      else if (strchr(buf3, '-'))
/*
 *  inputing a - in the first character causes the value to be incremented
 *  by the specified amount
 */
			{
			  type = DECREMENT;
			  offset = 1;
			}
		      else
			{
			  type = NORMAL;
			  offset = 0;
			}
		      rcode = sscanf(buf3 + (int) offset,"%ld",&value);
		      if (rcode == 0)
			CDFWALK_put_message(S.MES_vid, input_error_mes,
					    RINGBELL, NORMAL, PAUSE);
		    } /* col_field = 2 */
		  if (rcode)
		    {
/*
 *  Check and make sure that values entered were in range
 */
		      if (field_num == 0)
		       {
			 if (type == INCREMENT)
			   value = record_num + value;
			 else if (type == DECREMENT)
			   value = record_num - value;
			 else if (col_field == 1)
/*
 *  Decrement because using 1 instead of 0 on output line
 */
			   --value;
/*
 * Check record
 */
			 if (value >= 0 &&
			     value <= C.max_record_num[SO.curr_CDF])
			   record_num = value;
			 else
			   {
			     strcpy(mes, record_error_mes);
			     sprintf(buf, "%6ld", 
				     C.max_record_num[SO.curr_CDF]+1);
			     strcat(mes, buf);
			     CDFWALK_put_message(S.MES_vid, mes, RINGBELL,
						 NORMAL, NOPAUSE);
			   }
		       } /* field_num == 0 */
		      else
			{
			  if (type == INCREMENT)
			    value = indices[(int)(field_num-1)] + value;
			  else if (type == DECREMENT)
			    value = indices[(int)(field_num-1)] - value;
			  else if (col_field == 1)
/*
 *  Decrement because using 1 instead of 0 on output line
 */
				--value;
/*
 *  Check indice
 */
			  if (value >= 0 &&
			      value <= C.dim_sizes[SO.curr_CDF][(int)(field_num-1)]-1)
			    indices[(int)(field_num-1)]=value;
			  else
			    {
			      strcpy(mes, indices_error_mes);
			      sprintf(buf, "%6ld",
				      C.dim_sizes[SO.curr_CDF][(int)(field_num-1)]);
			      strcat(mes, buf);
			      CDFWALK_put_message(S.MES_vid, mes,
						  RINGBELL, NORMAL, NOPAUSE);
			    }
			} /* field_num = 1 */
		    }
		  CDFWALK_clear_row(S.MES_vid, MES_display, 1, 1, MES_COLUMNS);
		  if (V.data_type == CDF_EPOCH && col_field == 0)
		    label_border(S.WALK_vid, WALK_label, REVERSE);
		  break;

	     case NEWVARkey_WALK:
		  if (C.num_vars[SO.curr_CDF] <= CDFWALK_MAX_VARS_SCREEN)
		    CDFWALK_put_message(S.MES_vid, noscroll_mes,
					RINGBELL, NORMAL, PAUSE);
		  else
/*
 * Scroll in a new set page of variables
 */
		    CDFWALK_scroll_var(screen, CDF, variables, VAR_display,
				       &var_index, data_values, curr_field);
		  CDFWALK_clear_row(S.MES_vid, MES_display, 1, 1, MES_COLUMNS);
		  update_keydef = TRUE;
		  break;

	     case ACTIONkey_WALK:
		  CDFWALK_field_menu(screen, C.CDF_id, curr_field);
		  update_keydef = TRUE;
		  break;

	     case POPUPkey_WALK:
/*
 * Select values from a pop-up if positioned into a value and dimension field
 */
		  var_num = C.dim_var_num[(int)field_num];
		  if (col_field == 0 && (V.num_values > 0 && 
					V.num_values <= MAX_VALUES))
		     {
		     DIS_display = (struct vid_struct *)
			malloc((size_t) V.num_values * sizeof(struct vid_struct));
		     if (DIS_display != NULL)
			{
/*
 * Load in the values in the virtual display
 */

		     if (V.data_type == CDF_EPOCH)
			num_bytes = EPOCH_WIDTH;
		     else
			num_bytes =
			V.data_type == CDF_CHAR || V.data_type == CDF_UCHAR ?
				V.num_bytes+1 : MINMAX_SIZE;
		     CDFWALK_load_discrete(V.char_value, V.num_values,
		     num_bytes-1, DIS_display, &dis_rows, &dis_cols);
		     create_virtual_display(dis_rows+BORDER_ROWS, 
			dis_cols+BORDER_COLUMNS, &S.DIS_vid, BORDER, NORMAL);
/*
 * Select desired value
 */
		     CDFWALK_Menu_keydef(screen);
		     CDFWALK_select_menu_item(S.DIS_vid,
		     S.MES_vid, &val_num, DIS_display,
		     (int) V.num_values,  dis_rows, dis_cols,
		     DIS_ROW_PASTE, DIS_COL_PASTE, MENU, &tcode);
		     if(tcode == SELECTkey_WALK)
			{
			if(field_num == 0)
			   record_num = val_num-1;
			else
			   indices[(int)(field_num-1)] = val_num-1;
			}
		  delete_virtual_display(S.DIS_vid);
		  free(DIS_display);
		  }
		  update_keydef = TRUE;
		  } /* display null */
	       else if(V.num_values > MAX_VALUES)
		       CDFWALK_put_message(S.MES_vid, to_many_mes,
					    RINGBELL, NORMAL, PAUSE);
	       else
		       CDFWALK_put_message(S.MES_vid, nodata_mes,
					    RINGBELL, NORMAL, PAUSE);
	     break;
	     case REFRESHkey_FSI:
		  repaint_screen();
	     break;
	     }
     }
     unpaste_virtual_display(S.WALK_vid);

     CDFWALK_free_STRING(variables, C.num_vars[SO.curr_CDF], data_values);
     CDFWALK_free_discrete(variables, C.num_vars[SO.curr_CDF]);

     free_all_dim(C.all_dim_var_num, C.num_dims[SO.curr_CDF]);


}

void CDFWALK_scroll_var(screen, CDF, variables, VAR_display, var_index,
			data_values, field_num)
struct GLOBAL_struct    *screen;
struct  CDF_struct      *CDF;
struct variable_struct  *variables;
struct vid_struct       *VAR_display;
long                    *var_index;
union mixed             data_values[];
long                    *field_num;
{
int                     tcode;
AOSs1 (scroll_mes,
"___________/___________ keys to scroll thru variable list, _____ when ready")
EncodeKeyDefinitions(1, scroll_mes, PREVVARkey_WALK, 
		     NEXTVARkey_WALK, SELECTkey_WALK);
begin_pasteboard_update();
load_vid(S.VARSCROLL_vid, VARSCROLL_display, 0, VARSCROLL_NUM_ELEMENTS,
NO_label);
paste_virtual_display(S.VARSCROLL_vid,  VARSCROLL_ROW_PASTE,
					VARSCROLL_COL_PASTE);
end_pasteboard_update();
CDFWALK_scroll_keydef(screen);
CDFWALK_put_message(S.MES_vid, scroll_mes[0], NOBELL, NORMAL, NOPAUSE);
tcode = NOTTHERE;
while(tcode != SELECTkey_WALK)
{
set_cursor_abs(S.VARSCROLL_vid, 1, 34);
read_input(
#if defined(CURSESui)
	   S.VARSCROLL_vid,
#endif
			   &tcode, PASSTHRUri, TRUE);
switch (tcode)
	{
/*
 * calculate a new starting variable number to display
 */
	case PREVVARkey_WALK:
	     (*var_index)++;
	     if(*var_index == C.num_vars[SO.curr_CDF])*var_index = 0;
	     break;
	case NEXTVARkey_WALK:
	     (*var_index)--;
	     if(*var_index < 0)*var_index = C.num_vars[SO.curr_CDF]-1;
	     break;
	case PAGEUPkey_WALK:
	     (*var_index)-=CDFWALK_MAX_VARS_SCREEN;
	     if(*var_index < 0)*var_index = 0;
	     break;
	case PAGEDOWNkey_WALK:
	     (*var_index) += CDFWALK_MAX_VARS_SCREEN;
	     if (*var_index >= C.num_vars[SO.curr_CDF])
	       *var_index  = C.num_vars[SO.curr_CDF] - CDFWALK_MAX_VARS_SCREEN;
	     break;
	case REFRESHkey_FSI:
	     repaint_screen();
	     break;
	case ACTIONkey_WALK:
	     CDFWALK_field_menu(screen, C.CDF_id, field_num);
	     if (field_num != WALK_FIELD)tcode = SELECTkey_WALK;
	     break;
	}
/*
 * Display the new page of variables and data
 */
      CDFWALK_load_var(screen, CDF, variables, VAR_display,
			*var_index, data_values);
}
unpaste_virtual_display(S.VARSCROLL_vid);
}

void CDFWALK_print_data(screen, select, VAR_display, field_num, var_num,
			data_values, walker_only)
struct GLOBAL_struct    *screen;
struct variable_struct  select[];
struct vid_struct       *VAR_display;
long                    field_num;
long                    var_num;
union mixed             data_values[];
int                     walker_only;
{
long                    len;
int                    j;
double                  value;
char                    var_data[15];
char                    dim_data[25];

    for(j=0; j<15; j++)var_data[j] = ' ';
    for(j=0; j<25; j++)dim_data[j] = ' ';
    if(select[(int)var_num].data_type == CDF_EPOCH)
	 {
	 encodeEPOCH (data_values[(int)var_num].r8, dim_data);       /*jtl*/
	 encodeEPOCH2 (data_values[(int)var_num].r8, var_data);      /*jtl*/
	 }
    else if(select[(int)var_num].data_type == CDF_CHAR ||
	    select[(int)var_num].data_type == CDF_UCHAR)
	    {
	    if(SO.variable_format == FORMAT && select[(int)var_num].format)
	       EncodeString(select[(int)var_num].num_bytes,
			data_values[(int)var_num].string, print_string,
			 (int) (select[(int)var_num].num_bytes+2),
			 (int) (select[(int)var_num].num_bytes+2));
	    else
	       {
	       remove_trail(data_values[(int)var_num].string);
	       strcpy(print_string, data_values[(int)var_num].string);
	       }
	    len = strlen(print_string);
	    if(select[(int)var_num].dim_variable || select[(int)var_num].record_variable)
	       {
/*
Variable is the first to vary with a dimension, will be displayed in the
WALK window
*/
	       if(len > 24)
		  {
/*
24 character limit, truncate
*/
		  strncpy(dim_data, print_string, 22);
		  dim_data[22] = '\0';
		  strcat(dim_data,"..");
		  }
	       else
		  strcpy(dim_data + (int) (24-len), print_string);
	       }

/*
Display variable only in VAR window
*/
	    if(len > 14)
	       {
/*
14 character limit, truncate
*/
	       strncpy(var_data, print_string, 12);
	       var_data[12] = '\0';
	       strcat(var_data,"..");
	       }
	    else
	       strcpy(var_data + (int) (14-len), print_string);
	    }
    else
	{
	switch(select[(int)var_num].data_type)
	   {
	   case CDF_REAL4:
	   case CDF_FLOAT:
		if(SO.variable_format == FORMAT && select[(int)var_num].format)
		   {
		   EncodeValueFormat(select[(int)var_num].data_type,
			&data_values[(int)var_num].r4, print_string,
			select[(int)var_num].format_value, 14, 14,
			EPOCH0_STYLE);
		   strncpy(var_data, print_string,14);
		   var_data[14] = '\0';
		   }
		else
		   {
		   value = (double) data_values[(int)var_num].r4;
		   if(value < -1.e12 || value >  1.e12)
		      sprintf(var_data," %13.6e",value);
		   else
		      sprintf(var_data," %13.*f",precision(value),value);
		   }
		break;
	   case CDF_REAL8:
	   case CDF_DOUBLE:
		if(SO.variable_format == FORMAT && select[(int)var_num].format)
		   {
		   EncodeValueFormat(select[(int)var_num].data_type,
			&data_values[(int)var_num].r8, print_string,
			select[(int)var_num].format_value, 14, 14,
			EPOCH0_STYLE);
		   strncpy(var_data, print_string,14);
		   var_data[14] = '\0';
		   }
		else
		   {
		   value = data_values[(int)var_num].r8;
		   if(value < -1.e12 || value >  1.e12)
		      sprintf(var_data," %13.6e",value);
		   else
		      sprintf(var_data," %13.*f",precision(value),value);
		   }
		break;
	   case CDF_INT4:
		if(SO.variable_format == FORMAT && select[(int)var_num].format)
		   {
		   EncodeValueFormat(select[(int)var_num].data_type,
			&data_values[(int)var_num].i4, print_string,
			select[(int)var_num].format_value, 14, 14,
			EPOCH0_STYLE);
		   strncpy(var_data, print_string,14);
		   var_data[14] = '\0';
		   }
		else
		   sprintf(var_data,"   %11ld",data_values[(int)var_num].i4);
		break;
	   case CDF_UINT4:
		if(SO.variable_format == FORMAT && select[(int)var_num].format)
		   {
		   EncodeValueFormat(select[(int)var_num].data_type,
			&data_values[(int)var_num].ui4, print_string,
			select[(int)var_num].format_value, 14, 14,
			EPOCH0_STYLE);
		   strncpy(var_data, print_string,14);
		   var_data[14] = '\0';
		   }
		else
		   sprintf(var_data,"    %10lu",data_values[(int)var_num].ui4);
		break;
	   case CDF_INT2:
		if(SO.variable_format == FORMAT && select[(int)var_num].format)
		   {
		   EncodeValueFormat(select[(int)var_num].data_type,
			&data_values[(int)var_num].i2, print_string,
			select[(int)var_num].format_value, 14, 14,
			EPOCH0_STYLE);
		   strncpy(var_data, print_string,14);
		   var_data[14] = '\0';
		   }
		else
		   sprintf(var_data,"        %6d",data_values[(int)var_num].i2);
		break;
	   case CDF_UINT2:
		if(SO.variable_format == FORMAT && select[(int)var_num].format)
		   {
		   EncodeValueFormat(select[(int)var_num].data_type,
			&data_values[(int)var_num].ui2, print_string,
			select[(int)var_num].format_value, 14, 14,
			EPOCH0_STYLE);
		   strncpy(var_data, print_string,14);
		   var_data[14] = '\0';
		   }
		else
		   sprintf(var_data,"        %6u",data_values[(int)var_num].ui2);
		break;
	   case CDF_BYTE:
	   case CDF_INT1:
		if(SO.variable_format == FORMAT && select[(int)var_num].format)
		   {
		   EncodeValueFormat(select[(int)var_num].data_type,
			&data_values[(int)var_num].byte, print_string,
			select[(int)var_num].format_value, 14, 14,
			EPOCH0_STYLE);
		   strncpy(var_data, print_string,14);
		   var_data[14] = '\0';
		   }
		else
		   sprintf(var_data,"          %4d",data_values[(int)var_num].byte);
		break;
	   case CDF_UINT1:
		if(SO.variable_format == FORMAT && select[(int)var_num].format)
		   {
		   EncodeValueFormat(select[(int)var_num].data_type,
			&data_values[(int)var_num].ubyte, print_string,
			select[(int)var_num].format_value, 14, 14,
			EPOCH0_STYLE);
		   strncpy(var_data, print_string,14);
		   var_data[14] = '\0';
		   }
		else
		   sprintf(var_data,"           %3u",data_values[(int)var_num].ubyte);
	   }
	   if(select[(int)var_num].dim_variable || 
	      select[(int)var_num].record_variable)
	      {
	      strncpy(dim_data+10, var_data, 14);
	      dim_data[24] = '\0';
	      }
	}
/*
Now display the data
*/
       if((select[(int)var_num].dim_variable ||
	   select[(int)var_num].record_variable) ||
	  (walker_only))
	  put_chars(S.WALK_vid, dim_data, 24,
		    (int) (select[(int)var_num].dim_num + 1), 10,
		    NOERASE, NORMAL);
       if(!walker_only)
       CDFWALK_put_selection(S.VAR_vid, VAR_display,
		(int) (field_num+(VAR_NUM_ELEMENTS/2)), var_data, 14, NORMAL);
}
void remove_trail(str)
char            *str;
{
int             len,offset;
offset = len = strlen(str);
if(len == 0)return;
str+= len-1;
while(offset > 0 && *str == ' ') 
      {
      str--;
      offset--;
      }
*(str+1) = '\0';
}
void CDFWALK_load_var(screen, CDF, variables, VAR_display, index, data_values)
struct  GLOBAL_struct   *screen;
struct  CDF_struct      *CDF;
struct  variable_struct *variables;
struct  vid_struct      *VAR_display;
long                    index;
union mixed             data_values[];
{
long                    var_num;
long                    num_elements;
long                    num;
int                     dim_num;
num = 0;
if(C.num_vars[SO.curr_CDF] > CDFWALK_MAX_VARS_SCREEN)
   {
   for(dim_num = 0; dim_num <= C.num_dims[SO.curr_CDF]; dim_num++)
       {
       if(C.num_per_dim[dim_num] > 0)
	  CDFWALK_print_data(screen, variables, VAR_display, num,
	  C.dim_var_num[dim_num], data_values, TRUE);
       }
   }
num_elements=C.num_vars[SO.curr_CDF] < VAR_NUM_ELEMENTS/2  ? 
	     C.num_vars[SO.curr_CDF] : VAR_NUM_ELEMENTS/2;
begin_pasteboard_update();
for(num=0; num < num_elements; num++)
    {
    var_num = num+index < C.num_vars[SO.curr_CDF] ? num+index : 
	      num+index - C.num_vars[SO.curr_CDF];
   CDFWALK_put_selection(S.VAR_vid, VAR_display, (int) num,
	V.var_mnemonic,CDFWALK_MAX_VAR_LENGTH,  NORMAL);
    CDFWALK_print_data(screen, variables, VAR_display, num, var_num,
		data_values, FALSE);
    }
end_pasteboard_update();
}

void CDFWALK_get_data(CDF, select, num_select, record_num, indices,
			data_values)
struct CDF_struct       *CDF;
struct variable_struct  select[];
long                    num_select;
long                    record_num;
long                    indices[];
union  mixed            data_values[];

{
int            i;

for (i = 0; i < num_select; i++)
     {
     if(select[i].data_type == CDF_UCHAR || select[i].data_type == CDF_CHAR)
	{
	select[i].rcode = CDFlib (SELECT_, CDF_, C.CDF_id,
			  Zq(select[i].Z,zVAR_,rVAR_), select[i].var_num,
			  Zq(select[i].Z,zVAR_RECNUMBER_,rVARs_RECNUMBER_),
				record_num,
			  Zq(select[i].Z,zVAR_DIMINDICES_,rVARs_DIMINDICES_),
				indices,
		 GET_,    Zq(select[i].Z,zVAR_DATA_,rVAR_DATA_),
				  data_values[i].string,
		 NULL_);
	data_values[i].string[(int)select[i].num_bytes] = '\0';
	}
     else
	select[i].rcode = CDFlib (SELECT_, CDF_, C.CDF_id,
			  Zq(select[i].Z,zVAR_,rVAR_), select[i].var_num,
			  Zq(select[i].Z,zVAR_RECNUMBER_,rVARs_RECNUMBER_),
				record_num,
			  Zq(select[i].Z,zVAR_DIMINDICES_,rVARs_DIMINDICES_),
				indices,
		 GET_,    Zq(select[i].Z,zVAR_DATA_,rVAR_DATA_),
				  &data_values[i],
		 NULL_);
   }/* end loop */
}

void CDFWALK_alloc_STRING(select, num_select, data_values)
struct variable_struct  select[];
long                    num_select;
union  mixed            data_values[];
{
int                    i;

for (i = 0; i < num_select; i++)
     {
     if(select[i].data_type == CDF_CHAR || select[i].data_type == CDF_UCHAR)
/*
If this is a STRING variable allocate a enough space in the union array
to hold this variable
*/
	   data_values[i].string = (char *) malloc((size_t)select[i].num_bytes+1);
     }
}

void CDFWALK_free_STRING(select, num_select, data_values)
struct variable_struct  select[];
long                    num_select;
union mixed             data_values[];
{
int                    i;
for(i=0; i<num_select; i++)
    {
    if(select[i].data_type == CDF_CHAR || select[i].data_type == CDF_UCHAR)
       free(data_values[i].string);
    }
}
void CDFWALK_walk_keydef(screen)
struct                  GLOBAL_struct   *screen;
{
AOSs2 (keydefs,
"_____=Action  ___________=Up   ____________= -1 _____=Input  _____=Next field",
"_____=Redraw  ___________=Down ____________= +1 _____=Scroll _____=Back field")
/*
Load up keypad definitions for selecting a menu item
*/
EncodeKeyDefinitions(2, keydefs, 
	ACTIONkey_WALK, PREVRECDIMkey_WALK, PREVRECORDkey_WALK, INPUTkey_WALK, 
		     NEXTFIELDkey_WALK, 
	REFRESHkey_FSI, NEXTRECDIMkey_WALK, NEXTRECORDkey_WALK, NEWVARkey_WALK, 
		     PREVFIELDkey_WALK);
CDFWALK_load_keydef(S.KEY_vid, keydefs[0], keydefs[1]);
}
void CDFWALK_Menu_keydef(screen)
struct                  GLOBAL_struct   *screen;
{
AOSs2 (keydefs,
"_____=Action ___________=Up   _____=Page up    _____=Select  _____=Quit popup",
"_____=Redraw ___________=Down _____=Page down  HELP=_____")
/*
Load up keypad definitions for selecting a menu item
*/
EncodeKeyDefinitions(2, keydefs, 
	ACTIONkey_WALK, PREVITEMkey_WALK, PAGEUPkey_WALK,   SELECTkey_WALK,   
		     QUITkey_WALK, 
	REFRESHkey_FSI, NEXTITEMkey_WALK, PAGEDOWNkey_WALK, ACTIONkey_WALK);
CDFWALK_load_keydef(S.KEY_vid, keydefs[0], keydefs[1]);
}
void CDFWALK_special_keydef(screen)
struct                  GLOBAL_struct   *screen;
{
AOSs2 (keydefs,
  "_____=Action  ___________=Up    _____=Select  _____=Quit popup",
  "_____=Redraw  ___________=Down  HELP=______")
/*
Load up keypad definitions for selecting a menu item
*/
EncodeKeyDefinitions(2, keydefs, 
	ACTIONkey_WALK, PREVITEMkey_WALK, SELECTkey_WALK, QUITkey_WALK,
	REFRESHkey_FSI, NEXTITEMkey_WALK, ACTIONkey_WALK);
CDFWALK_load_keydef(S.KEY_vid, keydefs[0], keydefs[1]);
}

void CDFWALK_scroll_keydef(screen)
struct                  GLOBAL_struct   *screen;
{
AOSs2 (keydefs,
   "_____=Action  ___________=Prev var  _____=Page up    _____=SELECT",
   "_____=Redraw  ___________=Next var  _____=Page down  HELP=______")
EncodeKeyDefinitions(2, keydefs, 
	ACTIONkey_WALK, PREVVARkey_WALK, PAGEUPkey_WALK,   SELECTkey_WALK,
	REFRESHkey_FSI, NEXTVARkey_WALK, PAGEDOWNkey_WALK, ACTIONkey_WALK);
CDFWALK_load_keydef(S.KEY_vid, keydefs[0], keydefs[1]);
}
void CDFWALK_help_keydef(screen)
struct                  GLOBAL_struct   *screen;
{
AOSs2 (keydefs,
"___________=Up    _____=page up    _____=Done",
"___________=Down  _____=page down  _____=Redraw")
EncodeKeyDefinitions(2, keydefs, 
	PREVITEMkey_WALK, PAGEUPkey_WALK,   HELPDONEkey_WALK,
	NEXTITEMkey_WALK, PAGEDOWNkey_WALK, REFRESHkey_FSI);
CDFWALK_load_keydef(S.KEY_vid, keydefs[0], keydefs[1]);
}
void CDFWALK_CDFname_keydef(screen)
struct GLOBAL_struct *screen;
{
AOSs2 (keydefs,
  "_____=Action  _____ = Move   to end-of-line   ______=Select",
  "_____=Redraw  _____ = Delete to end-of-line   HELP=_____")
EncodeKeyDefinitions(2, keydefs, 
       ACTIONkey_WALK, MOVEtoENDkey_WALK, SELECTkey_WALK,
       REFRESHkey_FSI, DELETEtoENDkey_WALK, ACTIONkey_WALK);
CDFWALK_load_keydef(S.KEY_vid, keydefs[0], keydefs[1]);
}

int init_var_display(display)
struct  vid_struct      **display;
{
int                    i;
int                     row;
int                     col_index;
static int              cols[] = { 2, 27, 52, 11, 36, 61 };
row = 1;
col_index = 0;
*display = (struct vid_struct *)
		malloc(VAR_NUM_ELEMENTS * sizeof(struct vid_struct));
if(*display == NULL)return ((int)(BAD_MALLOC));

for(i=0; i<VAR_NUM_ELEMENTS; i++)
    {
    (*display)[i].row = row;
    (*display)[i].col = cols[col_index];
    (*display)[i].label[0] = '\0';
    if(row == 9)
       {
       row = 1;
       col_index++;
       }
    else
       row++;
    }
return(0);
}

/******************************************************************************
* WalkQOPs.
*    Returns TRUE if execution should continue.
******************************************************************************/

#if defined(mac)
Logical WalkQOPs (argC, argV)
int *argC;
char **argV[];
{
  DialogPtr dialogP;
  DialogRecord dRecord;
  WindowPtr behind = (WindowPtr) -1;
  ControlHandle controlHs[MAXIMUMin+1];
  Rect iRect;
  short itemN, iType;

  static Logical useFormat = DEFAULTformatWALK;
  static Logical negToPos = DEFAULT_NEGtoPOSfp0;
  static Str255 cacheText = "\p";
  static Str255 CDFtext = "\p";

  /****************************************************************************
  * Create the dialog and get the control handles.
  ****************************************************************************/

  dialogP = GetNewDialog (QOPri, &dRecord, behind);
  
  for (itemN = 1; itemN <= MAXIMUMin; itemN++) {
     GetDItem (dialogP, itemN, &iType, (Handle *) &controlHs[itemN], &iRect);
  }

  /****************************************************************************
  * Set the control values.
  ****************************************************************************/

  SetIText ((Handle) controlHs[CDFTEXTin], CDFtext);
  SetIText ((Handle) controlHs[CACHEin], cacheText);

  if (useFormat) SetCtlValue (controlHs[FORMATin], 1);
  if (negToPos) SetCtlValue (controlHs[NEGZin], 1);

  SetDItem (dialogP, (short) ODBin, (short) userItem,
	    (Handle) OutlineDefaultButton, &iRect);

  /****************************************************************************
  * Display the dialog and wait for user actions.
  ****************************************************************************/
    
  ShowWindow ((WindowPtr) dialogP);
  SetCursor (ARROW_CURSOR);

  for (;;) {
    ModalDialog (FilterDialogQOPfsi, &itemN);
    switch (itemN) {
      /************************************************************************
      * Ok.
      ************************************************************************/
      case OKin: {
	int n;
	char tempS[8+1+12+1];

	/**********************************************************************
	* Get the value of each control.
	**********************************************************************/

	GetIText ((Handle) controlHs[CDFTEXTin], CDFtext);
	GetIText ((Handle) controlHs[CACHEin], cacheText);

	useFormat = GetCtlValue (controlHs[FORMATin]);
	negToPos = GetCtlValue (controlHs[NEGZin]);
	
	/**********************************************************************
	* Build argc/argv.
	**********************************************************************/

	*argC = 3 + BOO(NULpString(CDFtext),0,1) +
		    BOO(NULpString(cacheText),0,2);
	*argV = (char **) AllocateMemory (*argC * sizeof(char *), FatalError);
	
	n = 0;
	MAKEstrARGv (argV, n, pgmName)

	if (!NULpString(CDFtext)) {
	  PtoCstr (CDFtext);
	  MAKEstrARGv (argV, n, (char *) CDFtext)
	  CtoPstr ((char *) CDFtext);
	}

	MAKEstrARGv (argV, n, "-initial");
	strcpyX (tempS, BOO(useFormat,"format","noformat"), 0);
	strcatX (tempS, BOO(negToPos,",neg2posfp0",",noneg2posfp0"), 0);
	MAKEstrARGv (argV, n, tempS);

	if (!NULpString(cacheText)) {
	  MAKEstrARGv (argV, n, "-cache")
	  PtoCstr (cacheText);
	  MAKEstrARGv (argV, n, (char *) cacheText)
	  CtoPstr ((char *) cacheText);
	}

	/**********************************************************************
	* Close the dialog and return.
	**********************************************************************/
	CloseDialog (dialogP);
	return TRUE;
      }
      /************************************************************************
      * Cancel.
      ************************************************************************/
      case CANCELin:
	CloseDialog (dialogP);
	return FALSE;
      /************************************************************************
      * Select CDF specification.
      ************************************************************************/
      case CDFSELECTin: {
	StandardFileReply CDFreply;
	char CDFpath[DU_MAX_PATH_LEN+1];
	StandardGetFile (FilterForCDFs, -1, NULL, &CDFreply);
	if (CDFreply.sfGood && !CDFreply.sfIsFolder && !CDFreply.sfIsVolume) {
	  BuildMacPath (&CDFreply.sfFile, CDFpath, TRUE);
	  CDFtext[0] = strlen (CDFpath);
	  strcpyX ((char *) &CDFtext[1], CDFpath, 255);
	  SetIText ((Handle) controlHs[CDFTEXTin], CDFtext);
	}
	break;
      }
      /************************************************************************
      * Check boxes.
      ************************************************************************/
      case FORMATin:
      case NEGZin:
	SetCtlValue (controlHs[itemN], BOO(GetCtlValue(controlHs[itemN]),0,1));
	break;
    }
  }
}
#endif
