/******************************************************************************
*
*  NSSDC/CDF                                            CDFlist.  Part 1 of 4.
*
*  Version 2.7d, 18-Sep-95, Hughes STX.
*
*  Modification history:
*
*   V1.0  29-Jan-91, H Leckner  Original version (for CDF V2.0).
*   V1.1   5-Feb-91, J Love     Modified error handling.
*   V1.2  12-Feb-91, H Leckner  Fixed variable name handling.
*   V1.3  13-Mar-91, H Leckner  Fixed attribute entry problem.
*   V1.4  20-Mar-91, H Leckner  Fixed problem with large dimension sizes.
*   V1.5  26-Mar-91, J Love     Cast malloc calls to proper type.  Fix for
*                               possible char array overwrite.
*   V1.6   4-Apr-91, H Leckner  Fixed problem with filtering REAL8 values.
*   V1.7   5-Jun-91, S Sudarsan Enhanced file/directory input handling
*                               along with file_names.c.  Changed logical
*                               name for HELP directory.
*   V1.8  25-Jun-91, J Love     Added QOP.  Added CDF_EPOCH as a data type.
*                    H Leckner  Added #include <sys/types.h>.
*   V1.9  12-Jul-91, J Love     TRUE/FALSE.  Changed for Cray/UNICOS port.
*                    H Leckner  Added use of VALIDMIN/VALIDMAX for initial
*                               filters (if NSSDC_STANDARD).  Use 'Exit' &
*                               'ExitBAD'.
*   V1.10 20-Sep-91, H Leckner  Fixed window labeling.  Modified for IBM-PC
*                    J Love     port.
*   V1.11 11-Oct-91, H Leckner  Added ability to select more than 8
*                               variables.
*   V1.12 18-Oct-91, H Leckner  Changed for IBM-RS6000 port.
*   V2.0  30-Apr-92, H Leckner  IBM PC port.  CDF V2.2.
*   V2.1   9-Jun-92, H Leckner  Output file fix.  `Dump' option.
*   V2.2  21-Aug-92, H Leckner  CDF V2.3 (shareable/zVar/NeXT).
*                    J Love
*   V2.3  25-Jan-94, H Leckner  CDF V2.4.
*                    J Love
*   V2.3a  4-Feb-94, J Love     DEC Alpha/OpenVMS port.
*   V2.4   4-Apr-94, H Leckner  Use Hyper calls in CDF output.
*   V2.5  12-Dec-94, J Love     CDF V2.5.
*   V2.6  16-Mar-95, H Leckner  The last change, who cares what it is.  Also,
*		     J Love	ANSI C semantic changes.
*   V2.7   6-Apr-95, J Love	POSIX.
*   V2.7a 18-Apr-95, J Love	More POSIX.
*   V2.7b 13-Jun-95, J Love	Linux.
*   V2.7c 17-Jul-95, J Love	CDFexport-related changes.
*   V2.7d 18-Sep-95, J Love	Macintosh event handling.
*
******************************************************************************/

#define CDFLIST
#include "cdflist.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, "CDFlist", MAX_PROGRAM_NAME_LEN);
  MacExecuteFSI (ListCDFs, ListQOPs);
  if (FreeMemory(NULL,FatalError) > 0) DisplayWarning ("Abandoned buffers.");
  return EXIT_SUCCESS_;
#else
  Logical success;
  strcpy (pgmName, "CDFlist");
  success = ListCDFs (argc, argv);
  if (FreeMemory(NULL,FatalError) > 0) DisplayWarning ("Abandoned buffers.");
  return BOO(success,EXIT_SUCCESS_,EXIT_FAILURE_);
#endif
}

/******************************************************************************
* ListCDFs.
******************************************************************************/

Logical ListCDFs (argC, argV)
int             argC;
char            *argV[];
{
static struct   CDF_struct CDF;
static struct   GLOBAL_struct   screen;
struct VAR      *select;
struct          vid_struct      *VAR_display;
union           mixed           *data_values;
int                             *filters;
CDFstatus       rcode;
int             i;
int             var_rows;
int             var_columns;
long int        num_select;
int             CDF_is_OPEN = FALSE;
static char     open_mes[] = "Opening CDF...";
static char     nodata_mes[] = "There is no data for this r/z group";
static char     novar_mes[] = "No variables selected for listing";
static char     noVAR_mes[] = "There is no variables in this r/z group";
static char     nodisp_mes[] = "All variables turned off in output";
static char     MULT_mes[] =
"Must use default min/max values (EPOCH OK) for this CDF when creating new CDF";
static char     file_close_mes[] =
"Error closing output file, possible disk quota problem";
static char     noCDF_mes[] =
"You must first select a input CDF before entering this field";
int             mult_flag;
FILE            *fptr=NULL;
int             field_num;
int             exit_code;
int             tcode;
int             first_CDF = TRUE;
long int        old_num_vars = 0;
long int        num = 8;
int             cdf_input = MANUAL;
int             status;
char            oSpec[DU_MAX_PATH_LEN+1];
char            oDir[DU_MAX_DIR_LEN+1];
char            oName[DU_MAX_NAME_LEN+1];

char                    mes[80];
char                    temp_name[80],file_name[80];
static char             restore_error_mes[] =
"Error detected opening RESTORE file: ";
static char             save_error_mes[] =
"Error detected creating SAVE file: ";
AOSs1 (SAVEREST_mes,
       "Enter file name(no extension), _____=cancel/action, _____=default:")
int     st;
int     initial_list_mode;


QOP *qop;
static char *validQuals[] = { "dump", "output", "initial", 
			      "specification", "cache", NULL };
static int optRequired[] = { FALSE, TRUE, TRUE, TRUE, TRUE, 0 };
static int exit_keys[] = { SELECTkey_LIST, ACTIONkey_LIST, NUL};

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

EncodeKeyDefinitions(1, SAVEREST_mes, ACTIONkey_LIST, SELECTkey_LIST);
SO.mode = NORMAL;
SO.spec_entered = FALSE;

qop = Qop (argC, argV, validQuals, optRequired);
if (qop == NULL) return FALSE;
if(qop->Nparms == 0){
   if(qop->qualEntered[SPECqual]) {
      SO.spec_entered = TRUE;
      strcpy (CDF.CDF_name, qop->qualOpt[SPECqual]);
    }
   else 
     strcpy(CDF.CDF_name, default_spec);
 }
else {
  if (qop->Nparms > 1) {
    DisplayError ("Too many parameters.");
    FreeMemory (qop, FatalError);
    return FALSE;
  }

  if (qop->qualEntered[SPECqual]) {
    DisplayError ("Conflicting parameter/qualifier.");
    FreeMemory (qop, FatalError);
    return FALSE;
  }

  cdf_input = AUTO;
  strcpy(CDF.CDF_name, qop->parms[CDFparm]);
  if(qop->qualEntered[DUMPqual]) {
    SO.mode = AUTO_DUMP;
/*              
Make Sure the USER didn't enter a directory
*/
    if(IsDir(CDF.CDF_name))
      {
	DisplayError ("You must enter a single CDF only when using the DUMP \
qualifier.");
	FreeMemory (qop, FatalError);
	return FALSE;
      }
    if(qop->qualEntered[OUTPUTqual])
      {
	strcpy (oSpec, qop->qualOpt[OUTPUTqual]);
	ParsePath (oSpec, oDir, oName);
	if (strchr(oName,'.') == NULL) strcat (oSpec, ".lis");
      }
    else
      oSpec[0] = '\0';
  }
  else{
    if(qop->qualEntered[OUTPUTqual])
      {
	DisplayError ("The OUTPUT qualifier must be used in conjunction with \
the DUMP qualifier.");
	FreeMemory (qop, FatalError);
	return FALSE;
      }
    if(!IsCDF(CDF.CDF_name))cdf_input = DIRECTory;
  }

}       
/*
Initialize special options, checking to see if user overrided default
*/
if (qop->qualEntered[INITIALqual]) {
  /****************************************************************************
  * Check for `[no]erase'.  Always check for the `no' version first.
  ****************************************************************************/
  if (strstrIgCase(qop->qualOpt[INITIALqual],"NOERASE") != NULL)
    SO.erasevars = NOERASEVARS;
  else
    if (strstrIgCase(qop->qualOpt[INITIALqual],"ERASE") != NULL)
      SO.erasevars = ERASEVARS;
    else
      SO.erasevars = (DEFAULTeraseLIST ? ERASEVARS : NOERASEVARS);
  /****************************************************************************
  * 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 = (DEFAULTformatLIST ? FORMAT : NOFORMAT);
  /****************************************************************************
  * Check for `[no]filter'.  Always check for the `no' version first.
  ****************************************************************************/
  if (strstrIgCase(qop->qualOpt[INITIALqual],"NOFILTER") != NULL)
    SO.filters = NOFILTER;
  else
    if (strstrIgCase(qop->qualOpt[INITIALqual],"FILTER") != NULL)
      SO.filters = FILTER;
    else
      SO.filters = (DEFAULTfilterLIST ? FILTER : NOFILTER);
  /****************************************************************************
  * Check for `[no]fill'.  Always check for the `no' version first.
  ****************************************************************************/
  if (strstrIgCase(qop->qualOpt[INITIALqual],"NOFILL") != NULL)
    SO.fill_values = NOCHECK_FILL;
  else
    if (strstrIgCase(qop->qualOpt[INITIALqual],"FILL") != NULL)
      SO.fill_values = CHECK_FILL;
    else
      SO.fill_values = (DEFAULTfillLIST ? CHECK_FILL : NOCHECK_FILL);
  /****************************************************************************
  * 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);
  /****************************************************************************
  * Check for `single | multi'.
  ****************************************************************************/
  if (strstrIgCase(qop->qualOpt[INITIALqual],"SINGLE") != NULL)
    SO.file_form = SINGLEF;
  else
    if (strstrIgCase(qop->qualOpt[INITIALqual],"MULTI") != NULL)
      SO.file_form = MULTIF;
    else
      SO.file_form = (DEFAULTsingleLIST ? SINGLEF : MULTIF);
  /****************************************************************************
  * Check for `host | network'.
  ****************************************************************************/
  if (strstrIgCase(qop->qualOpt[INITIALqual],"HOST") != NULL)
    SO.encoding = HOST;
  else
    if (strstrIgCase(qop->qualOpt[INITIALqual],"NETWORK") != NULL)
      SO.encoding = NET;
    else
      SO.encoding = (DEFAULTnetworkLIST ? NET : HOST);
  /****************************************************************************
  * Check for `epoch | epoch1'.  Note that `epoch1' is checked for first since
  * `epoch' is a substring of `epoch1'.
  ****************************************************************************/
  if (strstrIgCase(qop->qualOpt[INITIALqual],"EPOCH1") != NULL)
    SO.EPOCH_format = EPOCHFORM_1;
  else
    if (strstrIgCase(qop->qualOpt[INITIALqual],"EPOCH") != NULL)
      SO.EPOCH_format = EPOCHFORM_DEF;
    else
      SO.EPOCH_format = (DEFAULTepochLIST ? EPOCHFORM_DEF : EPOCHFORM_1);
  /****************************************************************************
  * Check for `horizontal | vertical'.
  ****************************************************************************/
  if (strstrIgCase(qop->qualOpt[INITIALqual],"HORIZONTAL") != NULL)
    SO.print_mode = HORIZONTAL;
  else
    if (strstrIgCase(qop->qualOpt[INITIALqual],"VERTICAL") != NULL)
      SO.print_mode = VERTICAL;
    else
      SO.print_mode = (DEFAULThorizontalLIST ? HORIZONTAL : VERTICAL);
  /****************************************************************************
  * Check for `zmode'.
  ****************************************************************************/
  if (strstrIgCase(qop->qualOpt[INITIALqual],"ZMODE") != NULL)
    SO.list_mode = ZMODE;
  else
    SO.list_mode = (DEFAULTzModeLIST ? ZMODE : REGMODE);
}
else {
  /****************************************************************************
  * Defaults when `initial' qualifier not entered.
  ****************************************************************************/
  SO.erasevars = (DEFAULTeraseLIST ? ERASEVARS : NOERASEVARS);
  SO.variable_format = (DEFAULTformatLIST ? FORMAT : NOFORMAT);
  SO.filters = (DEFAULTfilterLIST ? FILTER : NOFILTER);
  SO.fill_values = (DEFAULTfillLIST ? CHECK_FILL : NOCHECK_FILL);
  SO.zero = (DEFAULT_NEGtoPOSfp0 ? CONVERT : NOCONVERT);
  SO.file_form = (DEFAULTsingleLIST ? SINGLEF : MULTIF);
  SO.encoding = (DEFAULTnetworkLIST ? NET : HOST);
  SO.EPOCH_format = (DEFAULTepochLIST ? EPOCHFORM_DEF : EPOCHFORM_1);
  SO.print_mode = (DEFAULThorizontalLIST ? HORIZONTAL : VERTICAL);
  SO.list_mode = (DEFAULTzModeLIST ? ZMODE : REGMODE);
}
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);

initial_list_mode = SO.list_mode;

if(SO.mode != AUTO_DUMP)HELP_ptr = OnlineHelpFP ("cdflist.hlp", argV[0]);

select = NULL;
VAR_display = NULL;
data_values = NULL;
filters     = NULL;

field_num = CDF_FIELD;
CDF.CDF_id = NULL;
CDF.file_name[0] = '\0';
CDF.output = TERMIN;
FILE_is_OPEN = FALSE;
num_select = 0;
/*
Initialize global variables for Special Options
*/
SO.EPOCH_output_len[0] = 25;
SO.EPOCH_output_len[1] = 17;
SO.format  = FALSE;
SO.fillval = TRUE;
SO.curr_CDF = 0;
if(SO.mode == AUTO_DUMP)
   {
   char tempS[MAX_MESSAGE_TEXT_LEN+1];

   rcode = CDFLIST_open(&CDF, &data_values);

   if(rcode < CDF_OK)
      {
      exit_code = print_error(&screen, rcode);
      if(exit_code == NOCONTINUE) return FALSE;
      }
   rcode = alloc_VAR_display(&VAR_display, CDF.total_vars+RECORD_VAR);
   if(rcode < CDF_OK)
      {
      exit_code = print_error(&screen, rcode);
      if(exit_code == NOCONTINUE) return FALSE;
      }
   rcode = alloc_filters(&filters, CDF.total_vars+RECORD_VAR);
   if(rcode < CDF_OK)
      {
      exit_code = print_error(&screen, rcode);
      if(exit_code == NOCONTINUE) return FALSE;
      }

   if(strlen(oSpec) == 0)
      {
      CDFLIST_default_name(CDF.CDF_name, oSpec);
      strcat(oSpec, ".lis");
      }
   strcpy(CDF.file_name,oSpec);
   fptr = fopen(CDF.file_name, "w");
   if(fptr == NULL)
      {
      sprintf(tempS, "Error opening output file %s, CDF_name %s\n",
	      CDF.file_name,CDF.CDF_name);
      DisplayError (tempS);
      return FALSE;
      }
   sprintf (tempS, "Dumping CDF %s to file %s\n",
	    CDF.CDF_name,CDF.file_name);
   DisplayInfo (tempS);
   SO.filters = NOFILTER;
   CDF.output = FILEOUT;
   if(SO.list_mode == ZMODE)
      {
      zmode_on(CDF.CDF_id);
      CDF.curr_group = CDF.zmode_group;
      if(SO.print_mode == HORIZONTAL)
	 list_data_horizontal(&screen, &CDF, CDF.curr_group->first_var,
			CDF.curr_group->num_vars, data_values, fptr);
      else
	 list_data_vertical(&screen, &CDF, CDF.curr_group->first_var,
			CDF.curr_group->num_vars, data_values, fptr);
      }
   else
      CDFLIST_list_data(&screen, &CDF, CDF.curr_group->first_var,
	    CDF.curr_group->num_vars, data_values, fptr);
   status = fclose(fptr);
   if(status == EOF)perror("Error closing output file\n");
   free(VAR_display);
   free(data_values);
   free(filters);
   CDFLIST_free_vars(&CDF);
   rcode=CDFLIST_close(&CDF);
   return TRUE;
   }
else
   {
   init_var_display(init_display, num);
   CDFLIST_open_screen(&screen);
   }
while(field_num != EXIT)
 {
 switch (field_num)
      {
      case CDF_FIELD:
	   CDFLIST_put_selection(screen.CDF_vid, CDF_display,
	   CDFNAME_ELEMENT_NUM-1, CDF.CDF_name, CDF_NAME_LENGTH,
				 REVERSE);
	   if(CDF_is_OPEN)
	     {
	     rcode = zmode_off(CDF.CDF_id);
	     SO.list_mode = /* REGMODE */ initial_list_mode;
	     rcode = close_var_files(&CDF);
	     if(rcode < CDF_OK)
		{
		exit_code = print_error(&screen, rcode);
		if(exit_code == NOCONTINUE) return FALSE;
		}
	     }
	   if(cdf_input != AUTO)
	      tcode = CDFLIST_CDF_name(&screen, &CDF, &field_num, &cdf_input);
	   else
	      {
	      field_num = OUT_FIELD;
	      tcode = CONTINUEkey_LIST;
	      }
	   if(tcode != QUITkey_LIST &&
	      field_num != EXIT &&
	      strlen(CDF.CDF_name) > (size_t) 0) {
	      if(CDF_is_OPEN)
		 {
		 old_num_vars = CDF.curr_group->num_vars;
		 if(SO.erasevars == ERASEVARS)
		    {
		    free(VAR_display);
		    free(filters);
		    }
		 free(data_values);
		 CDFLIST_free_vars(&CDF);
		 rcode=CDFLIST_close(&CDF);
		 if(rcode != CDF_OK)print_error(&screen, rcode);
		 }
	      CDFLIST_put_message(screen.MES_vid, open_mes, NOBELL, BLINKING,
		NOPAUSE);

	      rcode = CDFLIST_open(&CDF, &data_values);
	      cdf_input = MANUAL;
	      if(rcode < CDF_OK || 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;
		    SO.list_mode = initial_list_mode;
		    if(SO.list_mode == REGMODE && CDF.numRvars == 0 &&
		       CDF.numZvars > 0)SO.list_mode = ZMODE;
/*
		    else if(SO.list_mode == ZMODE && CDF.numZvars == 0 &&
		       CDF.numRvars > 0)SO.list_mode = REGMODE;
*/                  
		    if(SO.list_mode == ZMODE) {
		       zmode_on(CDF.CDF_id);
		       CDF.curr_group = CDF.zmode_group;
		       }
		    zmode_label(screen.CDF_vid);
		    num_select = 0;
		    CDFLIST_CDF_info(&screen, &CDF, CDF_display, OUT_display);
		    if(SO.erasevars == ERASEVARS || first_CDF)
		       {
		       CDFLIST_clear_row(screen.VAR_vid, init_display, 4,
				VAR_NUM_ELEMENTS, VAR_COLUMNS);
		       rcode = alloc_VAR_display(&VAR_display, 
				CDF.total_vars+RECORD_VAR);
		       if(rcode < CDF_OK)
			  {
			  exit_code = print_error(&screen, rcode);
			  if(exit_code == NOCONTINUE) return FALSE;
			  }
		       rcode = alloc_filters(&filters, 
					CDF.total_vars+RECORD_VAR);
		       if(rcode < CDF_OK)
			  {
			  exit_code = print_error(&screen, rcode);
			  if(exit_code == NOCONTINUE) return FALSE;
			  }
		       init_var_display(VAR_display, CDF.total_vars+RECORD_VAR);
		       load_vid(screen.VAR_vid, VAR_display, 0,
				VAR_NUM_ELEMENTS, VAR_label);
		       }
		    else
		       {
		      rcode =  copy_display(&screen, &CDF, &VAR_display,
				&filters, old_num_vars);
		      if(rcode < CDF_OK)
			 {
			 exit_code = print_error(&screen, rcode);
			 if(exit_code == NOCONTINUE) return FALSE;
			 }
		       field_num = VAR_FIELD;
		       }
		    CDFLIST_clear_row(screen.MES_vid, MES_display, 1, 1,
		    MES_COLUMNS);
		    first_CDF = FALSE;
		    }
	      }
	   break;
      case OUT_FIELD:
	   CDFLIST_output(&screen, &CDF, &fptr, &field_num);
	   CDFLIST_clear_row(screen.MES_vid, MES_display, 1, 1,
	   MES_COLUMNS);
	   break;
      case SAVE_FIELD:
      case RESTORE_FIELD:
	   if(CDF_is_OPEN)
	      {
	      strcpy(temp_name, "cdflist");
	      CDFLIST_put_message(screen.MES_vid, SAVEREST_mes[0], NOBELL,
		NORMAL, NOPAUSE);
	      input_field(screen.MES_vid, temp_name, 1, 67,
	      12-SR_OFFSET, exit_keys, &tcode,
		INSERTTOGGLEkey_LIST, SOLkey_LIST, EOLkey_LIST, NOTTHERE, 
		DELENDkey_LIST, REFRESHkey_FSI);
	      if(tcode != ACTIONkey_LIST)
		 {
		 if(strlen(temp_name) == 0 || is_blank(temp_name))
		    strcpy(file_name, "cdflist.sav");
		 else
		    {
		    strcpy(file_name, temp_name);
		    strcat(file_name, ".sav");
		    }
		 if(field_num == RESTORE_FIELD)
		    {
		    CDFLIST_clear_row(screen.VAR_vid, init_display, 4,
			VAR_NUM_ELEMENTS, VAR_COLUMNS);
		    for(i=0; i<CDF.total_vars+RECORD_VAR; i++)
			filters[i] = FALSE;
		    st = restore_var(&screen, VAR_display, file_name,
			 CDF.curr_group->first_var, filters,
			 CDF.curr_group->num_vars);
		    if(!st)
		       {
		       strcpy(mes, restore_error_mes);
		       strcat(mes, file_name);
		       CDFLIST_put_message(screen.MES_vid, mes,
					   RINGBELL, NORMAL, PAUSE);
		       }
		    }
		 else
		    {
		    st = save_var(select, file_name, filters);
		    if(!st)
		       {
		       strcpy(mes, save_error_mes);
		       strcat(mes, file_name);
		       CDFLIST_put_message(screen.MES_vid, mes,
					   RINGBELL, NORMAL, PAUSE);
		       }
		    }
		 field_num = VAR_FIELD;
		 }
	      else
		 CDFLIST_field_menu(&screen, &CDF, &field_num);
		 }
	   else
	      {
	      CDFLIST_put_message(screen.MES_vid, noCDF_mes, RINGBELL,
				NORMAL, PAUSE);
	      field_num = CDF_FIELD;
	      }
	   break;
      case VAR_FIELD:
	   if(!CDF_is_OPEN)
	      {
	      CDFLIST_put_message(screen.MES_vid, noCDF_mes, RINGBELL, NORMAL,
					PAUSE);
	      field_num = CDF_FIELD;
	      }
	   else if(CDF.curr_group->num_vars > 0)
	      {
	      CDFLIST_var_menus(&screen, &CDF, &var_rows, &var_columns);
	      free_vars(select);
	      select = NULL;
	      rcode = init_discrete(&screen, &CDF, CDF.curr_group->first_var, 
					  CDF.curr_group->num_vars);
	      if(rcode < CDF_OK)
		 {
		 exit_code = print_error(&screen, rcode);
		 if(exit_code == NOCONTINUE) return FALSE;
		 }
	      CDFLIST_select_VAR(&screen, &CDF, var_rows, var_columns, 
		      VAR_display, &select, &num_select, filters, &field_num);
	      delete_virtual_display(screen.VARSELECT_vid);
	      }
	   else
	      {
	      CDFLIST_put_message(screen.MES_vid, noVAR_mes, RINGBELL, NORMAL,
					PAUSE);
	      CDFLIST_field_menu(&screen, &CDF, &field_num);
	      }
	   break;
      case RZ_FIELD:
#if 1
	    if (!CDF_is_OPEN) {
	      CDFLIST_put_message(screen.MES_vid, noCDF_mes, RINGBELL, NORMAL,
					PAUSE);
	      field_num = CDF_FIELD;
	    }
	    else {
#endif
	      old_num_vars = CDF.curr_group->num_vars;
	      rcode = CDFLIST_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_LIST) {
		  CDFLIST_CDF_info(&screen, &CDF, CDF_display, OUT_display);
		  rcode = copy_display (&screen, &CDF, &VAR_display, &filters,
				        old_num_vars);
		  if (rcode < CDF_OK) {
		     exit_code = print_error(&screen, rcode);
		     if (exit_code == NOCONTINUE) return FALSE;
		  }
		}
	      field_num = VAR_FIELD;
#if 1
	    }
#endif
	    break;
      case HELP_FIELD:
	   CDFLIST_help(&screen);
	   CDFLIST_field_menu(&screen, &CDF, &field_num);
	   break;
      case LIST_DATA:
	   if(num_select == 0)
	      CDFLIST_put_message(screen.MES_vid, novar_mes, RINGBELL, NORMAL,
					NOPAUSE);
	   else if(CDF.curr_group->max_record_num == -1)
	      CDFLIST_put_message(screen.MES_vid, nodata_mes, RINGBELL, NORMAL,
					NOPAUSE);
	   else if(!var_output(select, num_select))
	      CDFLIST_put_message(screen.MES_vid, nodisp_mes, RINGBELL, NORMAL,
					NOPAUSE);
	   else 
	      {
/*
if output is to a CDF add the independent variables that were not selected
to the selected ones.
*/

	      if(CDF.output == CDFOUT && SO.list_mode != ZMODE)
		 {
		 CDFLIST_check_filters(select, num_select,
			CDF.curr_group->first_var,    /* select,*/
			CDF.curr_group->num_vars, &mult_flag);
		 if(mult_flag)CDFLIST_put_message(screen.MES_vid, MULT_mes,
				RINGBELL, NORMAL, PAUSE);
		 rcode = CDFLIST_add_independent(select, &num_select,
			CDF.curr_group->first_var, CDF.curr_group->num_vars);
		 if(rcode < CDF_OK)
		    {
		    exit_code = print_error(&screen, rcode);
		    if(exit_code == NOCONTINUE) return FALSE;
		    }
		 }
	      if(SO.list_mode == ZMODE)
		 {
		 CDF.curr_group = CDF.zmode_group;
		 CDFLIST_check_monoton(select, CDF.curr_group->first_var);
		 if(SO.print_mode == HORIZONTAL || CDF.output == CDFOUT)
		    list_data_horizontal(&screen, &CDF, select, num_select,
			data_values, fptr);
		 else
		    list_data_vertical(&screen, &CDF, select, num_select,
			data_values, fptr);
		 }
	      else {
		 CDFLIST_check_monoton(select, CDF.curr_group->first_var);

		 CDFLIST_list_data(&screen, &CDF, select, num_select,
			data_values, fptr);
		 }
	      }
	   CDFLIST_field_menu(&screen, &CDF, &field_num);
      }
  }
if(HELP_ptr != NULL)fclose(HELP_ptr);
if(FILE_is_OPEN)
   {
   status = fclose(fptr);
   if(status == EOF)
      CDFLIST_put_message(screen.MES_vid, file_close_mes, RINGBELL, NORMAL,
		PAUSE);
   }
if(CDF_is_OPEN)
   {
   free(VAR_display);
   free(data_values);
   free(filters);
   CDFLIST_free_vars(&CDF);
   rcode=CDFLIST_close(&CDF);

   if(rcode != CDF_OK)print_error(&screen, rcode);
   }
CDFLIST_close_screen();
return TRUE;
}

/*****************************************************************************/

double check_epoch(str)
char            str[];
{
double          scale;
static char     default_time[] = " 00:00:00.000";
int             len;
scale = 0.;
len = strlen(str);
if(len == 0)
   return(0.);
else if(len < 11)
	return(-1.);
else if(len < 24)
	strcat(str, default_time+(len+2-13));
scale = parseEPOCH(str);
return(scale);
}
int precision(num)
double          num;
{
double          abs_value;
int     p;
abs_value = fabs(num);
if(abs_value < 1.)
	p = 5;
else if(abs_value < 10.)
	p = 4;
else if(abs_value < 10000.)
	p = 3;
else if(abs_value < 100000.)
	p = 2;
else
	p = 1;
return(p);
}
int CDFLIST_CDF_name(screen, CDF, field_num, input_type)
struct  GLOBAL_struct   *screen;
struct  CDF_struct      *CDF;
int                     *field_num;
int                     *input_type;
{
char                    file_spec[256],temp[256];
static char             save[CDF_PATHNAME_LEN];
char                    save_name[CDF_PATHNAME_LEN];
char                    save_temp[CDF_PATHNAME_LEN];
char                    **directory_list;
char                    **result_spec_list;
int                     num_files = 0;
int                     termcode = CONTINUEkey_LIST;
int                     i, row;
int                     drows;
int                     CDF_num = 1;
int                     tcode;
int                     done;
int                     dir;
char                    row_data[CDF_COLUMNS+1];

#if defined(unix) || defined(posixSHELL)
static char curr_dir[] = "./";
#else
#if defined(dos)
static char curr_dir[] = ".\\";
#else
#if defined(vms)
static char curr_dir[] = "[]";
#else
#if defined(mac)
static char curr_dir[] = "";
#endif
#endif
#endif
#endif

static char dir_mes[] =
"Enter Directory and/or CDF name (default=CDFs in current directory)";
static char dir_error[] = "No CDFs found, reenter directory and/or CDF name";
AOSs1 (select_mes,
       "Select a CDF or press _____ to enter a new Directory/CDF name")
struct vid_struct       *DIR_display;
int                     new_CDF;
int                     regfile;
int                     last_error = FALSE;
static int exit_keys[] = { SELECTkey_LIST, ACTIONkey_LIST, NUL };
EncodeKeyDefinitions(1, select_mes, QUITkey_LIST);
strcpy(save_name, C.CDF_name);
new_CDF= FALSE;
done = FALSE;
regfile = FALSE;
while(!done)
{
if(*input_type == MANUAL)
   {
   if(firstForCDFname)
      {
      CDFLIST_CDFname_keydef(screen);
      if(!last_error && !SO.spec_entered)strcpy(C.CDF_name, default_spec);
      CDFLIST_put_message(S.MES_vid, dir_mes, NOBELL, NORMAL, NOPAUSE);
/*
Read in input CDF name
*/
      input_field(S.CDF_vid, C.CDF_name, CDF_NAME_ROW, CDF_NAME_COL,
	CDF_NAME_LENGTH, exit_keys, &termcode, INSERTTOGGLEkey_LIST, 
	SOLkey_LIST, EOLkey_LIST, NOTTHERE, DELENDkey_LIST, REFRESHkey_FSI);
      }
   else
      CDFLIST_put_selection(S.CDF_vid, CDF_display, 0,
	      save, CDF_NAME_LENGTH, REVERSE);
   }
else
    termcode = SELECTkey_LIST;
*input_type = MANUAL;
firstForCDFname = FALSE;
last_error = FALSE;
CDFLIST_clear_row(S.MES_vid, MES_display, 1, 1, MES_COLUMNS);
if(termcode == ACTIONkey_LIST)
   {
   CDFLIST_field_menu(screen, CDF, field_num);
   if(*field_num != CDF_FIELD)
      {
      done = TRUE;
      tcode = QUITkey_LIST;
      }
   else
      firstForCDFname = TRUE;
   }
else
   {
   row = CDF_NAME_ROW;

   read_display(S.CDF_vid, row, row_data);
   strncpy(temp, row_data+(CDF_NAME_COL-1), CDF_NAME_LENGTH);
   temp[CDF_NAME_LENGTH] = '\0';
   remove_trail(temp);
   
/*
Save for next time
*/
   strcpy(save_temp, temp);

   strcpy (file_spec, temp);
   if (strlen(file_spec) == 0) strcpy (file_spec, curr_dir);

   dir = FALSE;
   regfile = FALSE;

   if (IsCDF(file_spec)) regfile = TRUE;
   if (IsDir(file_spec)) dir = TRUE;

   num_files = /*DirList*/
	       CDFdirList (file_spec, &directory_list, &result_spec_list);

   if(num_files > 0)
      {
      strcpy(save, save_temp);
      done = TRUE;
      if(num_files == 1 && regfile)
	 {
	 tcode = SELECTkey_LIST;
	 firstForCDFname = TRUE;
	 }
       else
	 {
/*
allocate the space for a vid structure which contains the CDF NAMES
*/
	 DIR_display = (struct vid_struct *)
	       malloc((size_t) (num_files * sizeof(struct vid_struct)));
	 if(DIR_display == NULL)return(0);

/*
Load in the cdf names into the structure
*/
	 for (i=0; i<num_files; i++)
	   {
	   DIR_display[i].row = 1;
	   DIR_display[i].col = 1;
	   if(strlen(result_spec_list[i]) < (size_t) DIR_COLUMNS)
	      strcpy(DIR_display[i].label, result_spec_list[i]);
	   else {
	      strncpy(DIR_display[i].label, result_spec_list[i], DIR_COLUMNS);
	      DIR_display[i].label[DIR_COLUMNS] = '\0';
	    }
	   DIR_display[i].field_col = 1;
	   }
	 if(num_files > DIR_ROWS)
	     drows = DIR_ROWS;
	 else
	     drows = num_files;
	 create_virtual_display(drows+BORDER_ROWS, DIR_COLUMNS+BORDER_COLUMNS,
			 &S.DIR_vid, BORDER, NORMAL);
	 CDFLIST_put_message(S.MES_vid, select_mes[0], NOBELL, NORMAL,NOPAUSE);
	 CDFLIST_menu_keydef(screen);
	 CDFLIST_select_menu_item(S.DIR_vid,
	   S.MES_vid, &CDF_num, DIR_display, num_files, drows,
	   DIR_COLUMNS, DIR_ROW_PASTE, DIR_COL_PASTE, MENU, &tcode);
	 delete_virtual_display(S.DIR_vid);
	 free (DIR_display);
	 } /* end num_files > 1 */
	 if(tcode == SELECTkey_LIST)
	      {
	      if(dir || strlen(directory_list[(int) CDF_num-1]) > (size_t) 0)
		 {
		 strcpy(C.CDF_name, directory_list[CDF_num-1]);
		 AppendToDir(C.CDF_name, result_spec_list[CDF_num-1]);
		 }
	      else
		 strcpy(C.CDF_name, result_spec_list[CDF_num-1]);

	      C.CDF_name[CDF_NAME_LENGTH]= '\0';
	      CDFLIST_put_selection(S.CDF_vid, CDF_display, 0,
	      C.CDF_name, CDF_NAME_LENGTH, REVERSE);
	      new_CDF = TRUE;
	      (*field_num)++;
	      }
	   else
	      {
	      change_rendition(S.CDF_vid, CDF_NAME_ROW, CDF_NAME_COL, 1,
		  strlen(C.CDF_name), REVERSE);
	      if(tcode == ACTIONkey_LIST)
		 {
		 CDFLIST_field_menu(screen, CDF, field_num);
		 if((int) (*field_num) == CDF_FIELD)done = FALSE;
		 }
	      else
		 done = FALSE;
	      firstForCDFname = TRUE;
	  } /* num > 1 */
	  FreeMemory (directory_list, FatalError);
	  FreeMemory (result_spec_list, FatalError);
       } /*num_file > 0*/
       else
	   {
	   CDFLIST_put_message(S.MES_vid, dir_error, RINGBELL, NORMAL, PAUSE);
	   firstForCDFname = TRUE;
	   last_error = TRUE;
	   }
   }/*keyboard != C-F*/
}/*done?*/
/*
If a new CDF was not selected put the old one back on the input line
*/
if(!new_CDF)
   {
   strcpy(C.CDF_name, save_name);
   CDFLIST_put_selection(S.CDF_vid, CDF_display, 0,
	      C.CDF_name, CDF_NAME_LENGTH, REVERSE);
   }
SO.spec_entered = FALSE;
return(tcode);

}
int             get_var_num(possible, mnemonic, num_poss)
struct  VAR             *possible;
char                    *mnemonic;
long int                num_poss;
{
int                     i,j;
int                     done;
int                     var_num;
int                     size;
struct VAR              *VN;
var_num = NOTTHERE;
VN = possible;
for(i=0; i<num_poss && var_num == NOTTHERE; i++)
    {
    if(VN->var_mnemonic_len > CDFLIST_MAX_VAR_LENGTH)
       size = CDFLIST_MAX_VAR_LENGTH;
    else
       size = VN->var_mnemonic_len;
    done = FALSE;
    for(j=size; j>0 && !done; j--)
	{
	if(VN->var_mnemonic[j-1] != ' ')
	   done = TRUE;
	else
	   size--;
	}
    if(strncmp(VN->var_mnemonic, mnemonic, size) == 0) var_num = i;
    VN=VN->next_var;
    }
return(var_num);
}
struct VAR *var_load(possible, var_num)
struct  VAR             *possible;
int                     var_num;
{
int                     i;
struct VAR              *VN;
VN = possible;
for(i=0; i<var_num; i++)
    VN=VN->next_var;
return(VN);
}
int     get_1char(screen_vid, prompt, line_count)
WINDOWid        screen_vid;
char            prompt[];
int             line_count;
{
int     resp;
if(line_count == 0)
erase_display(screen_vid, 0, 0, SCREEN_ROWS-1, SCREEN_COLUMNS-1);
put_chars(screen_vid, prompt, strlen(prompt), line_count, 1, ERASE, NORMAL);
read_input(
#if defined(CURSESui)
	   screen_vid,
#endif
		      &resp, PASSTHRUri, TRUE);
if(resp == SELECTkey_LIST)resp = CONTINUEkey_LIST;
#if !defined(mac)
fflush(stdin);
#endif
return(resp);
}
CDFstatus close_var_files(CDF)
struct  CDF_struct      *CDF;
{
int             var_num;
CDFstatus       rcode;
for(var_num=0; var_num < CDF->numRvars; var_num++)
    {
    rcode = CDFlib (SELECT_, CDF_, CDF->CDF_id, rVAR_, (long) var_num,
				 CLOSE_, rVAR_, NULL_);
    if(rcode < CDF_WARN)return(rcode);
    }
for(var_num=0; var_num < CDF->numZvars; var_num++)
    {
    rcode = CDFlib (SELECT_, CDF_, CDF->CDF_id, zVAR_, (long) var_num,
				 CLOSE_, zVAR_, NULL_);
    if(rcode < CDF_WARN)return(rcode);
    }
return(CDF_OK);
}

CDFstatus copy_display(screen, CDF, VAR_display, filters, old_num_vars)
struct  GLOBAL_struct   *screen;
struct  CDF_struct      *CDF;
struct  vid_struct      **VAR_display;
int                     **filters;
long int                old_num_vars;
{
struct  vid_struct      *TEMP_display;
int                     *TEMP_filters;

CDFstatus               rcode;

rcode = alloc_VAR_display(&TEMP_display, CDF->total_vars+RECORD_VAR);
if(rcode < CDF_OK)return(rcode);
rcode = alloc_filters(&TEMP_filters, CDF->total_vars+RECORD_VAR);
if(rcode < CDF_OK)return(rcode);
init_var_display(TEMP_display, CDF->total_vars+RECORD_VAR);
load_vid(screen->VAR_vid, TEMP_display, 0, VAR_NUM_ELEMENTS, VAR_label);
check_vars_CDF(screen, CDF, *VAR_display, TEMP_display,
			*filters, TEMP_filters, old_num_vars);
free(*VAR_display);
free(*filters);
*VAR_display = TEMP_display;
*filters = TEMP_filters;
return(CDF_OK);
}
Logical                 is_var(CDF_id,  mnemonic, data_type, first_group)
CDFid                   CDF_id;
char                    *mnemonic;
long int                *data_type;
struct group            *first_group;
{
long int                var_num;
CDFstatus               rcode;
int                     Z;
long                    num_dims;
long                    ds[CDF_MAX_DIMS];
int                     ZCDF_num;

if(strcmp(mnemonic, "**RECORD_NUM**") == 0) {
  *data_type = CDF_INT4;
  return(TRUE); 
  }
Z = SO.curr_CDF == REGULAR ? FALSE : TRUE;
rcode = CDFlib (SELECT_, CDF_, CDF_id,
		   GET_, Zq(Z,zVAR_NUMBER_, rVAR_NUMBER_),
			 mnemonic, &var_num,
		 NULL_);
if(rcode < CDF_WARN)return(FALSE);
if(Z)
   {
   rcode = CDFlib (SELECT_, CDF_, CDF_id,
			    zVAR_, var_num,
		      GET_, zVAR_NUMDIMS_, &num_dims,
			    zVAR_DIMSIZES_, ds,
			    zVAR_DATATYPE_, data_type,
		      NULL_);
   if(SO.list_mode == ZMODE)return(TRUE);
   ZCDF_num = which_cdf(num_dims, ds, first_group);
   if(ZCDF_num != SO.curr_CDF)return(FALSE);
   }
else
   rcode=CDFlib(SELECT_, CDF_, CDF_id,
		      rVAR_,          var_num,
	     GET_,    rVAR_DATATYPE_, data_type,
	     NULL_);

return(TRUE);

}
void check_vars_CDF(screen, CDF, display, temp_display, filters, temp_filters,
			old_num_vars)
struct  GLOBAL_struct   *screen;
struct  CDF_struct      *CDF;
struct  vid_struct      *display;
struct  vid_struct      *temp_display;
int                     *filters;
int                     *temp_filters;
long int                old_num_vars;
{
char                    var_mnemonic[80];
char                    mes[80];
int                     field_num, out_field_num, i,j;
int                     len, l2;
int                     row, out_row;
int                     select_num;
int                     video_type;
/* int			test_num; */
long int                data_type;
static char var_not_found[] = " not found in current CDF or R/Z group";

field_num = NUM_HORIZ_FIELDS+1;
out_field_num = NUM_HORIZ_FIELDS+1;
row = 2;
out_row = 2;
select_num = 0;
/* test_num = C.total_vars+1 < 8 ? 8 : C.total_vars+1; */
  
for(i=0; i<old_num_vars; i++)
{
strcpy(var_mnemonic, display[field_num-1].label+(display[field_num-1].field_col-1));
len = strlen(var_mnemonic);
if(len > 0)
   {
   if(is_var(C.CDF_id, var_mnemonic, &data_type, CDF->first_group))
      {
      select_num++;
      if(select_num > C.total_vars+RECORD_VAR)return;
      temp_filters[select_num-1] = filters[i];
      strcpy(temp_display[out_field_num-1].label+
	    (temp_display[out_field_num-1].field_col-1),
		  display[field_num-1].label+
		  (display[field_num-1].field_col-1));
      len = data_type == CDF_EPOCH ? EPOCH_WIDTH-1 : MINMAX_SIZE-1;
      strcpy(temp_display[out_field_num-1+1].label,display[field_num-1+1].label);
      l2 = strlen(display[field_num-1+1].label);
      for(j=l2; j<len; j++)temp_display[out_field_num-1+1].label[j] = ' ';
      temp_display[out_field_num-1+1].label[len] = '\0';
      strcpy(temp_display[out_field_num-1+2].label,display[field_num-1+2].label);
      l2 = strlen(display[field_num-1+2].label);
      for(j=l2; j<len; j++)temp_display[out_field_num-1+2].label[j] = ' ';
      temp_display[out_field_num-1+2].label[len] = '\0';
      strcpy(temp_display[out_field_num-1+3].label,display[field_num-1+3].label);
      if(out_row <= 9)
	 {
	 erase_display(S.VAR_vid, out_row, temp_display[out_field_num-1].field_col,
					out_row, VAR_COLUMNS);
	 if(row <= 9)erase_display(S.VAR_vid, row, display[field_num-1].field_col,
					row, VAR_COLUMNS);
	 len = strlen(var_mnemonic);
	 if(len > CDFLIST_MAX_VAR_LENGTH)len = CDFLIST_MAX_VAR_LENGTH;
	 CDFLIST_put_select_row(S.VAR_vid, temp_display, out_row,
			     out_field_num-1, var_mnemonic, len, REVERSE);
	 if(temp_filters[select_num-1])
	    {
	    len = strlen(temp_display[out_field_num-1+1].label);
	    if(temp_filters[select_num-1] == FILTER_ON)
	       video_type = REVERSE;
	    else
	       video_type = NORMAL;
	    CDFLIST_put_select_row(S.VAR_vid, temp_display, out_row,
		    out_field_num-1+1, temp_display[out_field_num-1+1].label,
			 len, video_type);
	    len = strlen(temp_display[out_field_num-1+2].label);
	    CDFLIST_put_select_row(S.VAR_vid, temp_display, out_row,
		    out_field_num-1+2, temp_display[out_field_num-1+2].label,
			 len, video_type);
	    }
	 len = strlen(temp_display[out_field_num-1+3].label);
	 CDFLIST_put_select_row(S.VAR_vid, temp_display, out_row,
		    out_field_num-1+3, temp_display[out_field_num-1+3].label,
			 len, NORMAL);
	 }
     out_row++; out_field_num +=NUM_HORIZ_FIELDS;
       }
   else
       {
/*
       temp_display[field_num-1].label[display[field_num-1].field_col-1]='\0';
       temp_display[field_num-1+1].label[0] = '\0';
       temp_display[field_num-1+2].label[0] = '\0';
       strcpy(temp_display[field_num-1+3].label," Y ");
*/
       if(row <= 9)erase_display(S.VAR_vid, row, 
	  display[field_num-1].field_col, row, VAR_COLUMNS);
       strcpy(mes, var_mnemonic);
       strcat(mes, var_not_found);
       CDFLIST_put_message(S.MES_vid, mes, RINGBELL, NORMAL, SHORTPAUSE);
       }
   }
field_num +=NUM_HORIZ_FIELDS; row++;
}
for(i=out_row; i<= 9; i++)
    {
    erase_display(S.VAR_vid, i, temp_display[out_field_num-1].field_col,
					i, VAR_COLUMNS);
    len = strlen(temp_display[out_field_num-1+3].label);
    CDFLIST_put_select_row(S.VAR_vid, temp_display, i, out_field_num-1+3,
	temp_display[out_field_num-1+3].label, len, NORMAL);
    out_field_num +=NUM_HORIZ_FIELDS;
    }
}
void record_display_format(select, last_record)
struct VAR      *select;
long            last_record;
{

struct VAR      *VN;
VN=select;
while(VN != NULL) {
  if(VN->var_num == RECORD_VAR_NUM) {
	if(last_record <= 999) {
	    strcpy(VN->format_value, "I3");
	    strcpy(VN->header_name, "REC");
	    VN->field_width = 3;
	    }
	else if(last_record <= 9999) {
	    strcpy(VN->format_value, "I4");
	    strcpy(VN->header_name, "RECD");
	    VN->field_width = 4;
	    }
	else if(last_record <= 99999L) {
	    strcpy(VN->format_value, "I5");
	    strcpy(VN->header_name, "RECRD");
	    VN->field_width = 5;
	    }
	else if(last_record <= 999999L) {
	    strcpy(VN->format_value, "I6");
	    strcpy(VN->header_name, "RECORD");
	    VN->field_width = 6;
	    }
	else if(last_record <= 9999999L) {
	    strcpy(VN->format_value, "I7");
	    strcpy(VN->header_name, "RECORD ");
	    VN->field_width = 7;
	    }
	else {
	    strcpy(VN->format_value, "I12");
	    strcpy(VN->header_name, "RECORDNUMBER");
	    VN->field_width = 12;
	    }
	break;
	}
   VN=VN->next_var;
   }
return;
}

void header(VN, squeeze)
struct VAR      *VN;
int             squeeze;
{
int             i;
int             num_blanks;
int             field_size;

if(VN->var_num == RECORD_VAR_NUM) 
	return;
else if(VN->data_type == CDF_EPOCH)
	field_size = SO.EPOCH_output_len[SO.EPOCH_format-1]-1;
else if(SO.variable_format == FORMAT && VN->format)
	field_size = VN->field_width;
else if(VN->data_type == CDF_CHAR || VN->data_type == CDF_UCHAR )
	{
	if(VN->num_bytes > VN->var_mnemonic_len)
	   field_size = (int) VN->num_bytes;
	else
	   field_size = VN->var_mnemonic_len;
	}

else
	field_size = 14;
if(!squeeze)field_size = field_size*(int)(VN->max_values) + 1;
if(field_size > 79)field_size = 79;
if(VN->var_mnemonic_len <= field_size)
   {
   num_blanks = (field_size - VN->var_mnemonic_len) / 2;
   for(i=0; i < num_blanks; i++)
       VN->header_name[i] = ' ';
   for(i=0; i < VN->var_mnemonic_len; i++)
       VN->header_name[i+num_blanks] = VN->var_mnemonic[i];
   for(i=num_blanks+VN->var_mnemonic_len; i < field_size; i++)
       VN->header_name[i] = ' ';
   }
else
   strncpy(VN->header_name, VN->var_mnemonic, field_size);
VN->header_name[field_size] = '\0';
}
int print_error(screen, rcode)
struct          GLOBAL_struct   *screen;
CDFstatus       rcode;
{
int             exit_code;
char    error_mes[CDF_ERRTEXT_LEN];
if(rcode < CDF_WARN || rcode == NOVARS)
	exit_code = NOCONTINUE;
else if(rcode < CDF_OK)
	exit_code = CONTINUEkey_LIST;
else if(rcode != CDF_OK)
	exit_code = CONTINUEkey_LIST;
/*
Get and print the error message
*/
if(rcode != NOVARS)
  CDFerror(rcode, error_mes);
else
  strcpy(error_mes, "There are no variables in this CDF.");
if(SO.mode == AUTO_DUMP)
   DisplayError (error_mes);
else
   CDFLIST_put_message(S.MES_vid, error_mes, RINGBELL, NORMAL, PAUSE);
return(exit_code);
}

int     which_cdf(num_dims, ds, first_group)
long    num_dims;
long    *ds;
struct  group   *first_group;
{
struct  group   *all;
int     k,found,j;

found = FALSE;
k=1;
all = first_group->next_group;
while(all != NULL)
      {
      if(num_dims != all->num_dims)
	 found=FALSE;
      else
	 {
	 found=TRUE;
	 for(j=0; j<num_dims; j++)
	     {
	     if(ds[j] != all->dim_sizes[j])found=FALSE;
	     }
	 if(found)return(k);
	 }
      all = all->next_group;
      k++;
      }
return(-1);
}
/*
Load all variables from a CDF into groups containing the rVariables and
zVariables with the same dimensionality.  Also append a extra group for
zMode that will contain all variables.  CDFLIST will give the user the
option to select any of these groups from a pop-up window.  
*/
CDFstatus load_sizes(CDF)
struct  CDF_struct      *CDF;
{
struct  group   *curr_group = NULL;
struct  group   *save_group = NULL;
struct  group   *all;
long int        var_num;
int             found;
int             i,j;
long int        num_dims, rnum_dims;
long int        ds[CDF_MAX_DIMS], rds[CDF_MAX_DIMS];
long int        max_record_num;
CDFstatus       status;

/*
The first group will always contain the rVariables
*/
if((curr_group = (struct group *) malloc (sizeof (struct group))) == NULL)
/*
Ran out of space
*/
    return(BAD_MALLOC);

for(j=0; j<CDF_MAX_DIMS; j++)rds[j] = 0;
/*
Retrieve the dimensionality of the CDF (rVariables only)
*/
status = CDFlib (SELECT_, CDF_, C.CDF_id,
		      GET_, rVARs_NUMDIMS_, &rnum_dims,
			    rVARs_DIMSIZES_, rds,
		      NULL_);
if(status < CDF_OK)return(status);
/*
Some CDFs may contain no rVariables
*/
if(C.numRvars == 0)rnum_dims = -1;
/*
Load CDF structure into the first group of the linked list
*/
curr_group->num_dims = rnum_dims;

for(j=0; j<CDF_MAX_DIMS; j++)curr_group->dim_sizes[j] = rds[j];

curr_group->values_per_record = 1;
for(j=0; j<curr_group->num_dims; j++)
    curr_group->values_per_record = curr_group->values_per_record*rds[j];

calcPhysDim(C.majority == ROW_MAJOR ? (Logical) TRUE : (Logical) FALSE, 
    curr_group->num_dims, curr_group->dim_sizes, curr_group->PhyDimValues);
/*
Initialize other structure variables
*/
curr_group->num_vars=1;
curr_group->max_record_num = -1;        
curr_group->first_var=NULL;
curr_group->curr_var=NULL;
curr_group->next_group=NULL;
/*
Now load the address from the first group into the main CDF structure
*/
C.first_group = curr_group;
/*
The first group will also be the current group
*/
C.curr_group = curr_group;
all = curr_group;
/*
num_groups is the total number of groups for this CDF
rVariables + zVariable groups + zMode group
*/
C.num_groups = 1;
/*
Now loop thru the variables looking for new groups, the total_vars are 
the sum of the rVariables and zVariables.
*/
for(i=0; i<C.total_vars; i++)
    {
    if(i < C.numRvars)
       {
/*
The rVariables are always first in a CDF
*/
       var_num = i;
       num_dims = rnum_dims;
       for(j=0; j<CDF_MAX_DIMS; j++)ds[j] = rds[j];
       status = CDFlib (SELECT_, CDF_,     C.CDF_id,
			    rVAR_,          var_num,
		      GET_, rVAR_MAXREC_,  &max_record_num,
		      NULL_);
       }
    else
       {
/*
variabe is a zVariable, retrieve it's structure
*/
       var_num = i - C.numRvars;
       status = CDFlib (SELECT_, CDF_, C.CDF_id,
			    zVAR_, var_num,
		      GET_, zVAR_NUMDIMS_, &num_dims,
			    zVAR_DIMSIZES_, ds,
			    zVAR_MAXREC_,  &max_record_num,
		      NULL_);
       }
    if(status < CDF_OK)return(status);

    all = C.first_group;
    found = FALSE;
/*
Loop thru all groups to see where this variable belongs
*/
    while(all != NULL && !found)
	  {
	  if(num_dims != all->num_dims)
/*
This variable contains a different number of dimensions then this group
no need to keep going
*/
	     found=FALSE;
	  else
	     {
	     found=TRUE;
/*
Now check the size of each dimension in this variable to see if it belongs in
this group
*/
	     for(j=0; j<num_dims; j++)
		 {
		 if(ds[j] != all->dim_sizes[j])found=FALSE;
		 }
	     }
	   if(!found)
	      {
/*
Not found in this group, save the address for later
*/
	      save_group = all;
/*
Move on to the next group
*/
	      all = all->next_group;
	      }
	   } /* End of group loop */

/*
This variables dimensionality was not found in any of the groups, add a new group
*/
	   if(!found)
	      {
	      if((curr_group = (struct group *) malloc (sizeof (struct group))) == NULL)
/*
Out of Space
*/
		  return(BAD_MALLOC);
	      else
		  {
		  C.num_groups++;
/*
Load in structure variables
*/
		  curr_group->num_dims=num_dims;
		  for(j=0; j<curr_group->num_dims; j++)curr_group->dim_sizes[j]=ds[j];
		  curr_group->values_per_record = 1;
		  for(j=0; j<curr_group->num_dims; j++)
		  curr_group->values_per_record = 
		  curr_group->values_per_record*curr_group->dim_sizes[j];
		  calcPhysDim(C.majority == ROW_MAJOR ? (Logical) TRUE : 
							(Logical)FALSE, 
			curr_group->num_dims, curr_group->dim_sizes, 
			curr_group->PhyDimValues);
		  curr_group->num_vars=2;
		  curr_group->max_record_num=max_record_num;
		  curr_group->first_var=NULL;
		  curr_group->curr_var=NULL;
		  curr_group->next_group=NULL;
/*
Add the new group to the linked list
*/
		  save_group->next_group = curr_group;
		  save_group = curr_group;
		  }
	      }
	   else
	      {
/*
Variable's dimensionality found in the current group, just bump up the
number of variables counter
*/
	      all->num_vars++;
/*
Keeping track of the maximum number of records for this group
*/
	      if(max_record_num > all->max_record_num)
		 all->max_record_num = max_record_num;
	      }
       }
/*
Append a group for zMode to the linked list
*/
if((curr_group = (struct group *) malloc (sizeof (struct group))) == NULL)
    return(BAD_MALLOC);
C.num_groups++;
curr_group->num_dims=0;
for(j=0; j<CDF_MAX_DIMS; j++)curr_group->dim_sizes[j]=0; 
curr_group->values_per_record = 1;
curr_group->num_vars=C.total_vars+RECORD_VAR;
curr_group->max_record_num=0;
curr_group->first_var=NULL;
curr_group->curr_var=NULL;
curr_group->next_group=NULL;

all = C.first_group;
found = FALSE;
/*
The zMode's group maximum record_num will equal the maximum record
number for all groups
*/
while(all != NULL && !found)
      {
      if(all->max_record_num > curr_group->max_record_num)
	 curr_group->max_record_num = all->max_record_num;;
      if(all->next_group == NULL)
	 {
	 all->next_group = curr_group;
	 found = TRUE;
	 }
      else
	 all=all->next_group;
      }
C.zmode_group = curr_group;

return(CDF_OK);
}
struct group *load_group(first_group, num, num_poss)
struct group *first_group;
int         num;
int         num_poss;
{
struct  group *all = NULL;
int             i;
if(num < 0 || num > num_poss-1)return(all);
if(num == 0)return(first_group);
all = first_group;
for(i=0; i<num; i++)
    all = all->next_group;
return(all);
}

CDFstatus alloc_VAR_display(VAR_display, total_vars)
struct          vid_struct      **VAR_display;
long int                        total_vars;
{
int                     num;
if(total_vars < 8)
   num = 8;
else
   num = (int) total_vars;
*VAR_display = (struct vid_struct *)
  malloc((size_t)((num+1)*NUM_HORIZ_FIELDS) * sizeof(struct vid_struct));
if(*VAR_display == NULL)return(BAD_MALLOC);
return(CDF_OK);
}
CDFstatus alloc_filters(filters, total_vars)
int             **filters;
long int        total_vars;
{
int             num;
int             i;
if(total_vars < 8)
   num = 8;
else
   num = (int) total_vars;
*filters = (int *) malloc((size_t) (num * sizeof( int )));
if(*filters == NULL)return(BAD_MALLOC);
for(i=0; i<num; i++)(*filters)[i] = FALSE;
return(CDF_OK);
}
CDFstatus CDFLIST_open(CDF, data_values)
struct          CDF_struct      *CDF;
union           mixed           **data_values;
{
CDFstatus               rcode;
long int                var_num;
int                     attr_num;
int                     dim_num;
int                     num_true;
long int                data_type;
long int                format_attr_num;
long int                validmin_attr_num;
long int                validmax_attr_num;
long int                monoton_attr_num;
long                    num_elements;
long                    num_dims, nd;
long                    ds[CDF_MAX_DIMS];
int                     i,j,k,Z;
int                     pass;
struct group            *curr_group;
struct VAR              *VN;
long                    convert0;
convert0 = (SO.zero == CONVERT ? NEGtoPOSfp0on : NEGtoPOSfp0off); 
rcode = CDFlib (OPEN_, CDF_, C.CDF_name, &C.CDF_id,
		SELECT_, CDF_NEGtoPOSfp0_MODE_, convert0,
			 CDF_CACHESIZE_, cacheSize,
		NULL_);
if(rcode < CDF_OK)return (rcode);

rcode = CDFlib (SELECT_, CDF_, C.CDF_id,
		 GET_, CDF_NUMrVARS_, &C.numRvars,
		       CDF_NUMzVARS_, &C.numZvars,
		       NULL_);

C.total_vars = C.numRvars + C.numZvars; 
if(C.total_vars == 0)return(NOVARS);

rcode = CDFlib (SELECT_, CDF_, C.CDF_id,
		 GET_, CDF_ENCODING_,   &C.encoding,
		       CDF_MAJORITY_,   &C.majority,
		       CDF_NUMATTRS_,   &C.num_attrs,
		 NULL_);
if(rcode < CDF_OK)return(rcode);
rcode = CDFlib (SELECT_, CDF_,           C.CDF_id,
		 GET_,    CDF_VERSION_,   &C.version,
			  CDF_RELEASE_,   &C.release,
			  CDF_COPYRIGHT_, C.text,
		 NULL_);
if(C.version == 1)
   {
   C.encoding = HOST_ENCODING;
   C.majority = COL_MAJOR;
   }
else
   if(C.encoding != NETWORK_ENCODING) C.encoding = HOST_ENCODING;

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

C.attr = NULL;
if(C.num_attrs > 0)
   {
   C.attr = (struct attr_struct *)
	    malloc((size_t) (C.num_attrs) * sizeof(struct attr_struct));
   if(C.attr == NULL)return(BAD_MALLOC);
   for(attr_num=0; attr_num<C.num_attrs; attr_num++)
       {
       rcode = CDFlib (SELECT_, CDF_,  C.CDF_id,
		       ATTR_, (long) attr_num,
		       GET_, ATTR_NAME_,    C.attr[attr_num].attr_mnemonic,
			  ATTR_SCOPE_,     &C.attr[attr_num].attr_scope,
		       NULL_);
       if(rcode < CDF_OK)return(rcode);
       if(C.attr[attr_num].attr_scope == GLOBAL_SCOPE) {
	 rcode = CDFlib (SELECT_, CDF_,  C.CDF_id,
			 ATTR_, (long) attr_num,
			 GET_, 
			 ATTR_MAXgENTRY_, &C.attr[attr_num].maxGentry,
			 NULL_);
	 if(rcode < CDF_OK)return(rcode);
       }
	 else
	   C.attr[attr_num].maxGentry = -1;
       }
   }
/*
Make sure these special options are set for this CDF
*/

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;
   format_attr_num = rcode;
   }
else
   SO.format      = TRUE;

rcode = CDFlib (SELECT_, CDF_, C.CDF_id,
		 GET_, ATTR_NUMBER_, "FILLVAL", &C.fillval_attr_num,
		 NULL_);
if(rcode < CDF_WARN)
   {
   SO.fill_values = NOCHECK_FILL;
   SO.fillval = FALSE;
   C.fillval_attr_num = rcode;
   }
else
   SO.fillval = TRUE;

rcode = CDFlib (SELECT_, CDF_, C.CDF_id,
		 GET_, ATTR_NUMBER_, "MONOTON", &monoton_attr_num,
		 NULL_);
SO.monoton = rcode < CDF_WARN ? FALSE : TRUE;

rcode = CDFlib (SELECT_, CDF_, C.CDF_id,
		   GET_, ATTR_NUMBER_, "VALIDMIN", &validmin_attr_num,
		 NULL_);
if(rcode < CDF_WARN)validmin_attr_num = NOTTHERE;
rcode = CDFlib (SELECT_, CDF_, C.CDF_id,
		   GET_, ATTR_NUMBER_, "VALIDMAX", &validmax_attr_num,
		 NULL_);
if(rcode < CDF_WARN)validmax_attr_num = NOTTHERE;
/*
Set default for the "**SELECT ALL**" option in variable selection pop-up window
*/
C.max_var_len = 14;
for(pass = 0; pass<2; pass++)
{
if(pass == ZPASS)
   {
   rcode = zmode_on(C.CDF_id);
   if(rcode < CDF_WARN)return(rcode);
   }
for(j=0; j<C.total_vars /* record number not part of loop */; j++)
    {
    if(j < C.numRvars && pass != ZPASS)
       {
       var_num = (long) j;
       k = 0;
       Z = FALSE;
       num_dims = C.curr_group->num_dims;
       for(i=0; i<num_dims; i++)ds[i] = C.curr_group->dim_sizes[i];
       }
    else
       {
       if(pass == ZPASS)
	  var_num = (long) j;
       else
	  var_num = (long) (j - C.numRvars);
       rcode = CDFlib (SELECT_, CDF_, C.CDF_id,
			    zVAR_, var_num,
		      GET_, zVAR_NUMDIMS_, &num_dims,
			    zVAR_DIMSIZES_, ds,
		      NULL_);
       if(pass != ZPASS)k = which_cdf(num_dims, ds, C.first_group);
       Z = TRUE;
       }
    if(pass != ZPASS)
       curr_group = load_group(C.first_group, k, C.num_groups);
    else
       curr_group = C.zmode_group;

    if((VN = (struct VAR *) malloc (sizeof (struct VAR))) == NULL)
	return(BAD_MALLOC);
    VN->Z = Z;
    for(i=0; i<CDF_MAX_DIMS; i++)
	VN->dim_variances[i] = FALSE;
    rcode=CDFlib(SELECT_, CDF_, C.CDF_id,
			Zq(Z,zVAR_,rVAR_),                  var_num,
		  GET_, Zq(Z,zVAR_NAME_,rVAR_NAME_),         VN->var_mnemonic,
			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)                                          /* V1.1 */
       return (rcode);
    else
       {
       VN->var_num = var_num;
       VN->var_mnemonic_len = strlen(VN->var_mnemonic);
       if(VN->var_mnemonic_len > C.max_var_len)C.max_var_len=VN->var_mnemonic_len;
       VN->filter = FALSE;
       VN->scalar = SCALAR;
       VN->discrete = FALSE;
       VN->multidim = FALSE;
       VN->data_array = NULL;
       VN->data_array_out = NULL;
       VN->bin_value = NULL;
       VN->char_value = NULL;
       VN->minmax_flag[0] = NORMAL;
       VN->minmax_flag[1] = NORMAL;
       VN->display = DISPLAY;
       VN->bytes_value = (int) (CDFelemSize(VN->data_type) * VN->num_bytes);
       VN->max_values = 1;
       for (i=0; i< num_dims; i++)
	    if(VN->dim_variances[i])VN->max_values=VN->max_values*ds[i];
       VN->total_values = 1;
       for (i=0; i< num_dims; i++)
	    VN->total_values=VN->total_values*ds[i];
       if(VN->Z)
	  {
	  VN->var_num_dims=num_dims;
	  for (i=0; i< num_dims; i++)
	       VN->act_dim_sizes[i] = ds[i];
	  for (i=0; i< num_dims; i++)
	       {
	       if(VN->dim_variances[i])
		  VN->var_sizes[i]=ds[i];
	       else
		  VN->var_sizes[i] = 1;
	       }
	  calcPhysDim(
	    C.majority == ROW_MAJOR ? (Logical) TRUE : (Logical) FALSE,
	    VN->var_num_dims, VN->var_sizes, VN->PhyDimValues);
	  }
       else
	  {
	  VN->var_num_dims=C.first_group->num_dims;
	  for (i=0; i< VN->var_num_dims; i++)
	       {
	       VN->act_dim_sizes[i] = C.first_group->dim_sizes[i];
	       VN->var_sizes[i]=C.first_group->dim_sizes[i];
	       }
	  calcPhysDim(
	    C.majority == ROW_MAJOR ? (Logical) TRUE : (Logical) FALSE,
	    VN->var_num_dims, VN->act_dim_sizes, VN->PhyDimValues);
	  }
       num_true=0;
       if(pass == ZPASS)
	  nd = num_dims; /*VN->var_num_dims;*/
       else
	  nd = curr_group->num_dims;
       for (i=0; i< nd; i++)
	    {
	    if(VN->dim_variances[i] != NOVARY)
	       {
	       dim_num=i+1;
	       num_true++;
	       VN->scalar = FALSE;
	       }
	    }
       if((num_true == 1 && !VN->record_variance) &&
	  (VN->data_type != CDF_CHAR && VN->data_type != CDF_UCHAR ))
	  {
	  VN->dim_num = dim_num;
	  VN->discrete = TRUE;
	  if(pass != ZPASS)
	     VN->num_values=curr_group->dim_sizes[dim_num-1];
	  else
	     VN->num_values=VN->var_sizes[dim_num-1];
	  }
      else
	  {
	  if(!VN->record_variance && num_true > 1)
	      VN->dim_num = MULTIPLE;
	  else
	      VN->dim_num=0;
	  VN->num_values=0;
	  }

       if(!VN->scalar && !VN->discrete)VN->multidim = TRUE;
       if(validmin_attr_num != NOTTHERE)
	  CDFLIST_get_double_attr(C.CDF_id, Z, validmin_attr_num,
	var_num, &VN->min, &rcode);
       if(rcode < CDF_OK || validmin_attr_num == NOTTHERE)
	  {
	  VN->minmax_flag[0] = NOTTHERE;
	  VN->min = -1.; /* dummy value */
	  }
       if(validmax_attr_num != NOTTHERE)
       CDFLIST_get_double_attr(C.CDF_id, Z, validmax_attr_num,
	var_num, &VN->max, &rcode);
       if(rcode < CDF_OK || validmin_attr_num == NOTTHERE)
	  {
	  VN->minmax_flag[1] = NOTTHERE;
	  VN->max = 1.; /* dummy value */
	  }
       rcode = 0;
    VN->fillval = FALSE;
    if(SO.fillval)
       {
       CDFLIST_get_double_attr(C.CDF_id, Z, C.fillval_attr_num,
		var_num, &VN->fill_value, &rcode);
       if(rcode >= CDF_OK)
	  VN->fillval = TRUE;
       else
	  rcode = CDF_OK;
       }
    VN->pad_value = NULL;
    VN->format = FALSE;
    VN->format_value = NULL;
    VN->field_width = 0;
    if(VN->data_type == CDF_EPOCH)VN->field_width = EPOCH_WIDTH-1;
    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_),
				&num_elements,
		 NULL_);
       if(rcode >= CDF_OK)
	  {
	  VN->format_value = (void *)
			      malloc((size_t) 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) num_elements]='\0';
	     if(rcode >=  CDF_OK)
		{
		VN->format = TRUE;
		if(VN->data_type != CDF_EPOCH)
		   VN->field_width = FormatWidth(VN->format_value)+1;
		if(VN->data_type == CDF_CHAR || VN->data_type == CDF_UCHAR &&
		   VN->field_width > 0) /* add for delimeter */
		   VN->field_width +=2;
		if(VN->var_mnemonic_len > VN->field_width)
		     VN->field_width = VN->var_mnemonic_len;
		}
	     else
		rcode = CDF_OK;
	     }
	  }
       else
	  rcode = CDF_OK;
       }
    VN->monoton = FALSE;
    VN->monoton_value = NULL;
    if(SO.monoton)
       {
       rcode = CDFlib (SELECT_, CDF_, C.CDF_id,
			  ATTR_,  monoton_attr_num,
			  Zq(Z,zENTRY_,rENTRY_),var_num,
		 GET_,    Zq(Z,zENTRY_NUMELEMS_, rENTRY_NUMELEMS_),
				&num_elements,
		 NULL_);
       if(rcode >= CDF_OK)
	  {
	  VN->monoton_value = (void *) malloc((size_t) num_elements+1);
	  if(VN->monoton_value != NULL)
	     {
	     rcode = CDFlib (SELECT_, CDF_,     C.CDF_id,
			     ATTR_,             monoton_attr_num,
				   Zq(Z,zENTRY_,rENTRY_),var_num,
			     GET_, Zq(Z,zENTRY_DATA_,rENTRY_DATA_),
				   VN->monoton_value,
			     NULL_);
	     VN->monoton_value[(int) num_elements]='\0';
	     if(rcode >=  CDF_OK && strcmp(VN->monoton_value, "FALSE") != 0)
		if(strcmp(VN->monoton_value, "INCREASE") == 0)
		   VN->monoton = INCREASE;
		else if(strcmp(VN->monoton_value, "DECREASE") == 0)
		   VN->monoton = DECREASE;
	     else
		rcode = CDF_OK;
	     }
	  }
       else
	  rcode = CDF_OK;
       }



       }
       VN->next_var = NULL;
       if(curr_group->first_var == NULL)
	     {
	     curr_group->first_var = create_record_var(CDF, curr_group, Z);
	     if(curr_group->first_var == NULL)
		return(BAD_MALLOC);
	     else {
		curr_group->first_var->next_var = VN;
		curr_group->curr_var = VN;
		}
	     }
       else
	     {
	     curr_group->curr_var->next_var=VN;
	     curr_group->curr_var = VN;
	     }
   }/*var loop*/
 /*
Allocate rest of structures needed based upon number of variables
*/
}/* pass */
  *data_values = (union mixed *)
	   malloc((size_t) ((C.total_vars+RECORD_VAR) * sizeof(union mixed)));
  if(*data_values == NULL)return(BAD_MALLOC);

if(C.numRvars > 0 && SO.list_mode == REGMODE)
   {
   SO.curr_CDF = REGULAR;
   rcode = zmode_off(C.CDF_id);
   C.curr_group = C.first_group;
   }
else
   {
   SO.curr_CDF = C.num_groups-1;
   SO.list_mode = ZMODE;
   C.curr_group = C.zmode_group;
   }

  return (rcode);
}
void compute_retrieval_ranges(CDF, select)
struct CDF_struct       *CDF;
struct VAR              *select;
{
struct VAR              *VN;
int                     i;
VN=select;
while(VN != NULL) {
  VN->max_values = 1;
  for (i=0; i< C.select_num_dims; i++)
  if(VN->dim_variances[i])VN->max_values=VN->max_values*C.select_dim_sizes[i];
  VN->total_values = 1;
  for (i=0; i< C.select_num_dims; i++)
       VN->total_values=VN->total_values*C.select_dim_sizes[i];
  VN->var_num_dims=C.select_num_dims;
  for (i=0; i< VN->var_num_dims; i++) {
     VN->act_dim_sizes[i] = C.select_dim_sizes[i];
     VN->var_sizes[i]=C.select_dim_sizes[i];
     }
  calcPhysDim(C.majority == ROW_MAJOR ? (Logical) TRUE : (Logical) FALSE,
	    VN->var_num_dims, VN->act_dim_sizes, VN->PhyDimValues);
  if(VN->discrete)VN->num_values=VN->var_sizes[VN->dim_num-1];
  VN=VN->next_var;
  }
}

void CDFLIST_get_data(CDF, select, num_select, record_num, indices, data_values)
struct CDF_struct       *CDF;
struct VAR              *select;
long int                num_select;
long int                record_num;
long int                indices[];
union  mixed            data_values[];
{
int                     i;
struct VAR              *VN;
VN = select;
for (i = 0; i < num_select; i++)
     {
     get_data(CDF, VN, record_num, indices, &data_values[i]);
     VN=VN->next_var;
     }
}
CDFstatus CDFLIST_alloc_STRING(select, num_select, data_values)
struct VAR              *select;
long int                num_select;
union  mixed            data_values[];
{
int                     i;
struct VAR              *VN;
VN = select;
for (i = 0; i < num_select; i++)
     {
     if(VN->data_type == CDF_CHAR || VN->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)(VN->num_bytes+1));
	   if(data_values[i].string == NULL)return(BAD_MALLOC);
	   }
     VN=VN->next_var;
     }
     return (CDF_OK);
}
void CDFLIST_free_STRING(select, num_select, data_values)
struct VAR              *select;
long int                num_select;
union mixed             data_values[];
{
int                     i;
struct VAR              *VN;
VN=select;
for(i=0; i<num_select; i++)
    {
    if(VN->data_type == CDF_CHAR || VN->data_type == CDF_UCHAR)
       free(data_values[i].string);
    VN=VN->next_var;
    }
}
void CDFLIST_free_ARRAY(select, num_select)
struct VAR              *select;
long int                num_select;
{
int                     i;
struct VAR              *VN;
VN=select;
for(i=0; i<num_select; i++)
    {
    if(VN->data_array != NULL)
	{
	free(VN->data_array);
	VN->data_array = NULL;
	}
    if(VN->data_array_out != NULL)
	{
	free(VN->data_array_out);
	VN->data_array_out = NULL;
	}
    VN=VN->next_var;
    }
}
CDFstatus CDFLIST_create_new_CDF(CDF, select, num_select, new_CDF)
struct  CDF_struct      *CDF;
struct  VAR             *select;
long int                num_select;
struct  CDF_struct      *new_CDF;
{
int                     i,ii;
int                     attr_num;
long int                entry_num;
CDFstatus               rcode;
long int                data_type;
long int                num_elements;
long int                out_attr_num;
long int                NextendRecs;
long int                num_dims;
long int                dim_sizes[CDF_MAX_DIMS];
long convert0;
struct VAR              *VN;
/*
Create the New CDF
*/

if(SO.curr_CDF == 0)
   {
   num_dims = NC.curr_group->num_dims;
   for(i=0; i<num_dims; i++)dim_sizes[i] = NC.curr_group->dim_sizes[i];
   }
else
   {
   num_dims = 0;
   for(i=0; i<CDF_MAX_DIMS; i++)dim_sizes[i] = 0;
   }
convert0 = (SO.zero == CONVERT ? NEGtoPOSfp0on : NEGtoPOSfp0off); 
rcode = CDFlib (CREATE_, CDF_, NC.CDF_name, num_dims,dim_sizes, &NC.CDF_id,
		SELECT_, CDF_CACHESIZE_, cacheSize,
			 CDF_NEGtoPOSfp0_MODE_, convert0,
		PUT_,    CDF_ENCODING_,     NC.encoding,
			 CDF_MAJORITY_,     NC.majority,
			 CDF_FORMAT_,       NC.CDF_form,
		NULL_);
if(rcode < CDF_WARN)return(rcode);
/*
Create the variables
*/
VN=select;
for(i=0; i<num_select; i++)
  {
  if(VN->display == DISPLAY && VN->var_num != RECORD_VAR_NUM)
    {
    if(VN->Z)
       rcode = CDFlib (SELECT_, CDF_, NC.CDF_id,
		       CREATE_, zVAR_,
				VN->var_mnemonic,
				VN->data_type,
				VN->num_bytes,
				VN->var_num_dims,
				VN->act_dim_sizes,
				VN->record_variance,
				VN->dim_variances,
			       &VN->out_var_num,
		      NULL_);
    else
       rcode = CDFlib (SELECT_, CDF_, NC.CDF_id,
		       CREATE_, rVAR_,
				VN->var_mnemonic,
				VN->data_type,
				VN->num_bytes,
				VN->record_variance,
				VN->dim_variances,
			       &VN->out_var_num,
		      NULL_);
    if(rcode < CDF_WARN)return(rcode);
/*
Insert the number of records to extend the current variable
*/
    rcode = CDFlib ( SELECT_, CDF_, C.CDF_id,
			      Zq(VN->Z,zVAR_, rVAR_), VN->var_num,
			GET_, Zq(VN->Z,zVAR_EXTENDRECS_,rVAR_EXTENDRECS_),
			     &NextendRecs,
			NULL_);
     if(rcode < CDF_WARN)
	return(rcode);
     else
	{
	rcode = CDFlib ( SELECT_, CDF_, NC.CDF_id,
			   Zq(VN->Z,zVAR_, rVAR_), VN->out_var_num,
		     PUT_, Zq(VN->Z,zVAR_EXTENDRECS_,rVAR_EXTENDRECS_),
			     NextendRecs,
			NULL_);
	if(rcode < CDF_WARN)return(rcode);
	}
     rcode = put_pad(C.CDF_id, VN->var_num, NC.CDF_id,
		VN->out_var_num, VN->Z, VN->data_type,
		VN->num_bytes, &VN->pad_value);
     if(rcode < CDF_WARN)return(rcode);


      if(SO.list_mode == ZMODE)
	  VN->num_values_out = VN->max_values;
      else {
	  VN->num_values_out = 1;
	  for(ii=0; ii<num_dims; ii++) 
	      if(VN->dim_variances) 
		 VN->num_values_out *= NC.curr_group->dim_sizes[ii];
		 
       }

    } /* Display on */
    VN=VN->next_var;
  } /* end loop */

/*
Create the attributes
*/
for (attr_num=0; attr_num<C.num_attrs; attr_num++)
     {
     rcode = CDFlib (SELECT_, CDF_, NC.CDF_id,
		      CREATE_, ATTR_, C.attr[attr_num].attr_mnemonic,
				      C.attr[attr_num].attr_scope,
				      &out_attr_num,
		      NULL_);
     if(rcode < CDF_WARN)return(rcode);
     }

/*
Insert the global attributes
*/
for (attr_num=0; attr_num<C.num_attrs; attr_num++)
     {
     if(C.attr[attr_num].attr_scope == GLOBAL_SCOPE)
	{                                       /* need to add for maxZentry */
	for(entry_num = 0; entry_num <= C.attr[attr_num].maxGentry; entry_num++)
	    {
	    rcode = CDFlib (SELECT_, CDF_, C.CDF_id,
			  ATTR_,  (long) attr_num,
			  gENTRY_,entry_num,
		 GET_,    gENTRY_DATATYPE_, &data_type,
			  gENTRY_NUMELEMS_, &num_elements,
		 NULL_);
	    if(rcode >= CDF_OK)
	       {
	       rcode =  put_attr_value(C.CDF_id, FALSE, gENTRY_, 
			(long) attr_num,  entry_num, entry_num, 
			NC.CDF_id, data_type, num_elements);
	       if(rcode < CDF_WARN)return(rcode);
	       }
	    else if(rcode != NO_SUCH_ENTRY)
		    return(rcode);
	    }
	}
     }


/*
Insert the variable attributes
*/

for (attr_num=0; attr_num<C.num_attrs; attr_num++)
     {
     VN=select;
     for(i = 0; i < num_select; i++)
       {
	 if((C.attr[attr_num].attr_scope == VARIABLE_SCOPE) &&
	    (VN->display == DISPLAY && VN->var_num != RECORD_VAR_NUM))
	    {
	    rcode = CDFlib (SELECT_, CDF_, C.CDF_id,
			  ATTR_,  (long) attr_num,
			  Zq(VN->Z,zENTRY_,rENTRY_),VN->var_num,
		 GET_,    Zq(VN->Z,zENTRY_DATATYPE_,rENTRY_DATATYPE_),
				&data_type,
			  Zq(VN->Z,zENTRY_NUMELEMS_, rENTRY_NUMELEMS_),
				&num_elements,
		 NULL_);
	    if(rcode >= CDF_OK)
	       {
	       rcode = put_attr_value(C.CDF_id, VN->Z, 
		Zq(VN->Z,zENTRY_,rENTRY_), (long) attr_num, VN->var_num, 
		VN->out_var_num, NC.CDF_id, data_type, num_elements);
	       if(rcode < CDF_WARN)return(rcode);
	       }
	    else if(rcode != NO_SUCH_ENTRY)
		    return(rcode);
	    }
	 VN=VN->next_var;
	 }
     }
return (CDF_OK);
}

CDFstatus put_attr_value(in_CDF_id, Z, entry_type, attr_num,  
	entry_num, out_entry_num, out_CDF_id, data_type, num_elements)

CDFid           in_CDF_id;
int             Z;
long int        entry_type;
long int        attr_num;
long int        entry_num;
long int        out_entry_num;                                  /* V1.3 */
CDFid           out_CDF_id;
long int        data_type;
long int        num_elements;
{
void            *attr_values;
CDFstatus       rcode;

switch(data_type)
       {
	case  CDF_REAL4:
	case  CDF_FLOAT:
	      attr_values =
		(void *) malloc((size_t) (num_elements * sizeof(float)));
	      if(attr_values == NULL)return(BAD_MALLOC);                /* V1.5 */
	      break;
	 case CDF_CHAR:
	 case CDF_UCHAR:
	      attr_values = (void *) malloc((size_t) (num_elements+1)); /* V1.5 */
	      if(attr_values == NULL)return(BAD_MALLOC);
	      break;
	case  CDF_REAL8:
	case  CDF_DOUBLE:
	case  CDF_EPOCH:
	      attr_values =
		(void *) malloc((size_t) (num_elements * sizeof(double)));      /* V1.5 */
	      if(attr_values == NULL)return(BAD_MALLOC);
	      break;
	case  CDF_INT4:
	case  CDF_UINT4:
	      attr_values =
		(void *) malloc((size_t)(num_elements * sizeof(long int)));  /* V1.5 */
	      if(attr_values == NULL)return(BAD_MALLOC);
	      break;
	case  CDF_INT2:
	case  CDF_UINT2:
	      attr_values =
		(void *) malloc((size_t) (num_elements * sizeof(short int)));  /* V1.5 */
	      if(attr_values == NULL)return(BAD_MALLOC);
	      break;
	case  CDF_BYTE:
	case  CDF_INT1:
	case  CDF_UINT1:
	      attr_values = (void *) malloc((size_t) num_elements);     /* V1.5 */
	      if(attr_values == NULL)return(BAD_MALLOC);
}/*end switch*/
if(entry_type == gENTRY_) 
   rcode = CDFlib ( SELECT_, CDF_, in_CDF_id,
		 ATTR_, attr_num,
			entry_type, entry_num,
		 GET_,
			gENTRY_DATA_, attr_values,
		 NULL_);
else
   rcode = CDFlib ( SELECT_, CDF_, in_CDF_id,
		 ATTR_, attr_num,
			entry_type, entry_num,
		 GET_,
			Zq(Z,zENTRY_DATA_,rENTRY_DATA_),attr_values,
		 NULL_);
if(rcode >= CDF_OK)                             /* V1.1 */
   {
   if(entry_type  == gENTRY_)
      rcode = CDFlib ( SELECT_, CDF_, out_CDF_id,
		    ATTR_, attr_num,
			  entry_type, out_entry_num,
		    PUT_, gENTRY_DATA_,
			  data_type, num_elements, attr_values,
		    NULL_);
   else
      rcode = CDFlib ( SELECT_, CDF_, out_CDF_id,
		    ATTR_, attr_num,
			  entry_type, out_entry_num,
		    PUT_, Zq(Z,zENTRY_DATA_,rENTRY_DATA_),
			  data_type, num_elements, attr_values,
		    NULL_);
   }
free (attr_values);
return (rcode);
}

CDFstatus put_pad(in_CDF_id, in_var_num, out_CDF_id, out_var_num, Z,
		  data_type, num_elements, pad_value)           /* V1.3 */
CDFid           in_CDF_id;
long int        in_var_num;
CDFid           out_CDF_id;
long int        out_var_num;
int             Z;
long int        data_type;
long int        num_elements;
void            **pad_value;
{
CDFstatus       rcode;

switch(data_type)
       {
	case  CDF_REAL4:
	case  CDF_FLOAT:
	      *pad_value =
		(void **) malloc((size_t) (num_elements * sizeof(float)));
	      if(*pad_value == NULL)return(BAD_MALLOC);         /* V1.5 */
	      break;
	 case CDF_CHAR:
	 case CDF_UCHAR:
	      *pad_value = (void **) malloc((size_t) (num_elements+1)); /* V1.5 */
	      if(*pad_value == NULL)return(BAD_MALLOC);
	      break;
	case  CDF_REAL8:
	case  CDF_DOUBLE:
	case  CDF_EPOCH:
	      *pad_value =
		(void **) malloc((size_t) (num_elements * sizeof(double)));     /* V1.5 */
	      if(*pad_value == NULL)return(BAD_MALLOC);
	      break;
	case  CDF_INT4:
	case  CDF_UINT4:
	      *pad_value =
		(void **) malloc((size_t)(num_elements * sizeof(long int)));  /* V1.5 */
	      if(*pad_value == NULL)return(BAD_MALLOC);
	      break;
	case  CDF_INT2:
	case  CDF_UINT2:
	      *pad_value =
		(void **) malloc((size_t) (num_elements * sizeof(short int)));  /* V1.5 */
	      if(*pad_value == NULL)return(BAD_MALLOC);
	      break;
	case  CDF_BYTE:
	case  CDF_INT1:
	case  CDF_UINT1:
	      *pad_value = (void *) malloc((size_t) num_elements);      /* V1.5 */
	      if(*pad_value == NULL)return(BAD_MALLOC);
}/*end switch*/
rcode = CDFlib ( SELECT_, CDF_, in_CDF_id,
			Zq(Z,zVAR_,rVAR_),in_var_num,
		 GET_,
			Zq(Z,zVAR_PADVALUE_,rVAR_PADVALUE_),*pad_value,
		 NULL_);
/*
Pad value was specifield, use it
*/
if(rcode >= CDF_OK && rcode != NO_PADVALUE_SPECIFIED)           /* V1.1 */
	{
	rcode = CDFlib ( SELECT_, CDF_, out_CDF_id,
			Zq(Z,zVAR_,rVAR_),out_var_num,
		    PUT_, 
			Zq(Z,zVAR_PADVALUE_,rVAR_PADVALUE_),*pad_value,
		    NULL_);
	}
/*free (pad_value);*/
return (CDF_OK);
}
double  get_dim_value(CDF_id, Z, var_num, data_type, indices)
CDFid           CDF_id;
int             Z;
long            var_num;
long            data_type;
long            indices[];
{
double                  test_value;
union mixed             temp;
long int                record_num = 0;
CDFstatus               rcode;

rcode = CDFlib (SELECT_, CDF_, CDF_id,
		  Zq(Z,zVAR_,rVAR_), var_num,
		  Zq(Z,zVAR_RECNUMBER_,rVARs_RECNUMBER_),record_num,
		  Zq(Z,zVAR_DIMINDICES_,rVARs_DIMINDICES_),indices,
	 GET_,    Zq(Z,zVAR_DATA_,rVAR_DATA_), &temp,
	 NULL_);
switch(data_type)
       {
       case CDF_REAL4:
       case CDF_FLOAT:
	    test_value = r4_r8(&temp.r4);
       break;
       case CDF_REAL8:
       case CDF_DOUBLE:
       case CDF_EPOCH:
	    test_value = temp.r8;
	    break;
       case CDF_INT4:
	    test_value = (double) temp.i4;
	    break;
       case CDF_UINT4:
	    test_value = (double) temp.ui4;
	    break;
       case CDF_INT2:
	    test_value = (double) temp.i2;
	    break;
       case CDF_UINT2:
	    test_value = (double) temp.ui2;
	    break;
       case CDF_BYTE:
       case CDF_INT1:
	    test_value = (double) temp.byte;
	    break;
       case CDF_UINT1:
	    test_value = (double) temp.ubyte;
       } /* End Switch */
       if(rcode < CDF_OK)test_value = 1.7e38;
return(test_value);
}
CDFstatus CDFLIST_new_CDF_info(CDF, select, num_select, new_CDF)
struct  CDF_struct      *CDF;
struct  VAR             *select;
long int                num_select;
struct  CDF_struct      *new_CDF;
{
int                     i,j, ii, jj;
int                     temp_dim_size;
int                     vars_per_dim[CDF_MAX_DIMS];
int                     num_pass;
int                     num_vars;
int                     dim_num;
long int                indices[CDF_MAX_DIMS];
double                  test_value;
int                     first_indice_found;
int                     done_w_dimension;
struct  group           *curr_group = NULL;
struct  VAR             *VN;

NC.CDF_id = NUL;
NC.attr = NULL;
NC.num_attrs = C.num_attrs;
for(j=0; j<CDF_MAX_DIMS; j++)
    C.first_indice[j] = 0;
if(SO.list_mode == ZMODE && C.output != CDFOUT)return(CDF_OK);

if((curr_group = (struct group *) malloc (sizeof (struct group))) == NULL)
    return(BAD_MALLOC);
curr_group->next_group=NULL;
curr_group->num_vars=0;
curr_group->max_record_num = -1;
curr_group->num_dims = C.curr_group->num_dims;
for(j=0; j<C.curr_group->num_dims; j++)
    {
    curr_group->dim_sizes[j] = C.curr_group->dim_sizes[j];
    curr_group->PhyDimValues[j] = C.curr_group->PhyDimValues[j];
    }
curr_group->values_per_record = C.curr_group->values_per_record;
NC.first_group = curr_group;
NC.curr_group = curr_group;

strcpy(NC.CDF_name,C.file_name);
NC.majority = C.majority;
NC.encoding = SO.encoding == NET ? NETWORK_ENCODING : HOST_ENCODING;
NC.CDF_form = SO.file_form == SINGLEF ? SINGLE_FILE  : MULTI_FILE;
C.select_num_dims     = C.curr_group->num_dims;
C.select_values_per_record = 1;
for(j=0; j<C.curr_group->num_dims; j++) {
    C.select_dim_sizes[j]    = C.curr_group->dim_sizes[j];
    C.last_indice[j] = C.curr_group->dim_sizes[j] - 1;
    C.select_values_per_record *=C.select_dim_sizes[j];
    C.select_PhyDimValues[j] = C.curr_group->PhyDimValues[j];
    }
/*
If no filtering will take place in this run there is no need to go on
*/
if(SO.filters == NOFILTER)return(CDF_OK);
/*
If we are in zMODE no reduction of dimensions will be done so again
there is no need to go on
*/
if(SO.list_mode == ZMODE)return(CDF_OK);
/*
Go thru all dimensions to calculate new dimension sizes
*/
for(dim_num=1; dim_num <= NC.curr_group->num_dims; dim_num++)
    {
    first_indice_found = FALSE;
    num_vars = 0;
    for(jj = 0; jj < NC.curr_group->num_dims; jj++)
	indices[jj] = 0;
/*
Look for variables that vary with respect to the current dimension
*/
    VN=select;
    for(j=0; j<num_select; j++)
	{
	if(VN->dim_num == dim_num)
	   {
	   vars_per_dim[num_vars] = j;
	   num_vars++;
	   }
	VN=VN->next_var;
	}
/*
Make sure there were variables selected for this dimension
*/
	if(num_vars > 0)
	   {
/*
Loop thru all values in this dimension, all variables in this
dimension must be checked
*/
	   temp_dim_size = 0;
	   done_w_dimension = FALSE;
	   for (j = 0; j < NC.curr_group->dim_sizes[dim_num-1] &&
		       !done_w_dimension; j++)
		{
		num_pass=0;
		for (ii = 0; ii <num_vars && !done_w_dimension; ii++)
		     {
		     i = vars_per_dim[ii];
		     VN=var_load(select, i);
		     if(!VN->filter)
			num_pass++;
		     else
			{
			if(NC.curr_group->dim_sizes[dim_num-1] > MAX_VALUES)
			   {
			   indices[dim_num-1]=j;
			   test_value = get_dim_value(C.CDF_id, VN->Z, i,
				VN->data_type, indices);
			   } /*End num_values > MAX_VALUES */
			else
			   test_value = ((double *) VN->bin_value)[j];

			switch(VN->filter)
			  {
			  case MIN_MAX:
			       {
			       if(test_value >= VN->filter_min &&
				  test_value <= VN->filter_max)
				  num_pass++;
			       else if(first_indice_found && VN->monoton)
				  done_w_dimension = TRUE;
			       }
			       break;
			  case MIN_ONLY:
			       {
			       if(test_value >= VN->filter_min)
				  num_pass++;
			       else if(first_indice_found && VN->monoton)
				  done_w_dimension = TRUE;
			       break;
			       }
			  case MAX_ONLY:
			       {
			       if(test_value <= VN->filter_max)
				  num_pass++;
			       else if(first_indice_found && VN->monoton)
				  done_w_dimension = TRUE;
			       break;
			       }
			  }
			}
		     }
/*
if the number of variables that passed the test is equal to the number of
variables selected for this dimension bump the dim size by one
*/
		    if(num_pass == num_vars) {
		       temp_dim_size++;
		       if(!first_indice_found) {
			  C.first_indice[dim_num-1] = j;
			  first_indice_found = TRUE;
		       }
		       if(first_indice_found)C.last_indice[dim_num-1] = j;
		    }
		}/*loop thru values per dim*/
/*
Load in the new size for this dimension
*/
		NC.curr_group->dim_sizes[dim_num-1] = temp_dim_size;
	     }/*num_vars>0*/
    }/*dimension numbers*/
/*
Make sure a 0 dimension size was not requested
*/
if(C.output == CDFOUT)
   {
   for(dim_num=1; dim_num <= NC.curr_group->num_dims; dim_num++)
    {
    if(NC.curr_group->dim_sizes[dim_num-1] == 0)
       {
       free(NC.first_group);
       NC.first_group = NULL;
       NC.curr_group = NULL;
       return(BAD_DIM_SIZE);
       }
    }
   }
NC.curr_group->values_per_record = 1;
for(j=0; j<NC.curr_group->num_dims; j++)
    NC.curr_group->values_per_record *=NC.curr_group->dim_sizes[j];

calcPhysDim(NC.majority == ROW_MAJOR ? (Logical) TRUE : (Logical) FALSE,
	    NC.curr_group->num_dims, NC.curr_group->dim_sizes,
	    NC.curr_group->PhyDimValues);
C.select_num_dims     = NC.curr_group->num_dims;
C.select_values_per_record = 1;
for(i=1; i<=C.curr_group->num_dims; i++) {
    C.select_dim_sizes[i-1] = C.last_indice[i-1] - C.first_indice[i-1] + 1;
    C.select_values_per_record *=C.select_dim_sizes[i-1];
    }
calcPhysDim(C.majority == ROW_MAJOR ? (Logical) TRUE : (Logical) FALSE,
	    C.curr_group->num_dims, C.select_dim_sizes,
	    C.select_PhyDimValues);
return(CDF_OK);
}
void clear_scalars(select)
struct VAR        *select;
{
struct VAR        *VN;
VN=select;
while(VN != NULL)
      {
      VN->scalar_entered = FALSE;
      VN = VN->next_var;
      }
}
int     scalar_check(CDF, select, record_num, data_values)
struct CDF_struct *CDF;
struct VAR        *select;
long               record_num;
union mixed       *data_values;
{
struct VAR        *VN;
int                var_num;
int                record_pass;
if(SO.filters == NOFILTER)return(TRUE);
/*
Get the data for the scalars to see if the record passes
*/
VN=select;
var_num=0;
while(VN != NULL)
      {
	 /* Monotonic variables already checked */
      if(VN->filter && VN->scalar && !VN->monoton) 
	 {
	 static long indices[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
	 get_data(CDF, VN, record_num, indices, &data_values[var_num]);
	 VN->scalar_entered = TRUE;
	 record_pass = filter1(VN, &data_values[var_num]);
	 if(!record_pass)return(FALSE);
	 }
      VN=VN->next_var;
      var_num++;

      }
return(TRUE);
}

void    was_record_selected(select, first_record, last_record)
struct VAR      *select;
long            **first_record;
long            **last_record;
{
struct  VAR     *VN;
VN = select;
while(VN != NULL) {
      if(VN->var_num == RECORD_VAR_NUM && VN->filter) {
	 if(VN->min < 1.)VN->min = 1.;
	 if(VN->filter != MAX_ONLY)**first_record = (long) VN->min-1;
	 if(VN->max > (**last_record)+1)VN->max = (double) (**last_record)+1;
	 if(VN->filter != MIN_ONLY)**last_record  = (long) VN->max-1;
	 VN->first_record = **first_record;
	 VN->last_record = **last_record;
	 break;
	 }
      VN=VN->next_var;
      }
}
int find_records(CDF, select, data_values, first_record, last_record)
struct CDF_struct *CDF;
struct VAR        *select;
union mixed       *data_values;
long int          *first_record;
long int          *last_record;
{
struct VAR        *VN;
int                var_num;
long int           record_num;
long int           prev_record_num = -1;
long int           low_end, high_end;
static long        indices[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
double             value0;
double             first_value, last_value;
double             filter_value;
long int           max_range = -1;
long int           range;
int                pass0, pass1;
/*
Get the data for the scalars to see if the record passes
*/
VN=select;
var_num=0;

*first_record = 0;
*last_record  = C.curr_group->max_record_num;
was_record_selected(select, &first_record, &last_record);
clear_scalars(select);
if(SO.filters == NOFILTER)  return(TRUE);
while(VN != NULL) {
  VN->first_record = *first_record;
  VN->last_record  = *last_record;
  if(VN->scalar && VN->var_num != RECORD_VAR_NUM && VN->filter && VN->monoton) 
     {
     
/*
This variable is a scalar and is monotonic, find the first record that 
passes all filters
*/
     low_end = VN->first_record;
     high_end = VN->last_record;
     get_data(CDF, VN, low_end, indices, &data_values[var_num]);
     first_value = convert_value(VN->data_type, &data_values[var_num]);
     get_data(CDF, VN, high_end, indices, &data_values[var_num]);
     last_value = convert_value(VN->data_type, &data_values[var_num]);
     filter_value = VN->monoton == INCREASE ? VN->min : VN->max;
     if(((VN->monoton == INCREASE) && 
	 (VN->max < first_value || VN->min > last_value)) ||
	((VN->monoton == DECREASE) && 
	 (VN->min > first_value || VN->max < last_value)))
	     return(FALSE);   
     else if((VN->monoton == INCREASE && filter_value > first_value) ||
	     (VN->monoton == DECREASE && filter_value < first_value) ||
	     (VN->filter == MAX_ONLY)) {
	     for(;;) {
	       record_num = (high_end+low_end)/2;
	       if(record_num == prev_record_num)return(FALSE);
	       get_data(CDF, VN, record_num, indices, &data_values[var_num]);
	       pass0 = filter1(VN, &data_values[var_num]);
	       value0 = convert_value(VN->data_type, &data_values[var_num]);
	       get_data(CDF, VN, record_num+1, indices, &data_values[var_num]);
	       pass1 = filter1(VN, &data_values[var_num]);
	       if(!pass0 && pass1)
		   {
		   VN->first_record = record_num+1;
		   break;
		   }
	       else 
		   {
		   if(pass0 && pass1)
		      high_end = record_num - 1;
		   else if(((VN->monoton == INCREASE) && (filter_value <= value0)) ||
			   ((VN->monoton == DECREASE) && (filter_value >= value0)))
		      high_end = record_num - 1;
		   else
		      low_end  = record_num + 1;
		   }
	       prev_record_num = record_num;
	       }/* End of binary search loop for beginning record*/
	   }/* check for min */
/*
Now calculate the ending record
*/
	 prev_record_num = -1;
	 low_end = VN->first_record;
	 high_end = VN->last_record;
	 filter_value = VN->monoton == INCREASE ? VN->max : 
						  VN->min;
	 if((VN->monoton == INCREASE && filter_value < last_value) ||
	    (VN->monoton == DECREASE && filter_value > last_value) ||
	    (VN->filter == MIN_ONLY)) {
	   for(;;) 
	     {
	     record_num = (high_end+low_end)/2;
	     if(record_num == prev_record_num)return(FALSE);
	     get_data(CDF, VN, record_num, indices, &data_values[var_num]);
	     pass0 = filter1(VN, &data_values[var_num]);
	     value0 = convert_value(VN->data_type, &data_values[var_num]);
	     get_data(CDF, VN, record_num+1, indices, &data_values[var_num]);
	     pass1 = filter1(VN, &data_values[var_num]);
	     if(pass0 && !pass1) {
		VN->last_record = record_num;
		break;
		}               
	     else {
		if(pass0 && pass1)
		      low_end  = record_num + 1;
		else if(((VN->monoton == INCREASE) && (filter_value <= value0)) ||
			((VN->monoton == DECREASE) && (filter_value >= value0)))
		     high_end = record_num - 1;
		else
		     low_end  = record_num + 1;
		}
	     prev_record_num = record_num;
	     }/* End of binary search loop for last record*/
	} /* max_check */
      }/* scalar */
      VN=VN->next_var;
      var_num++;

    }/* Var Loop */

VN=select;
while(VN != NULL) {
  if(VN->scalar) {
     range = VN->last_record;
     if(range > max_range) {
	*first_record = VN->first_record;
	*last_record  = VN->last_record;
	max_range=range;
     }
  }
  VN=VN->next_var;
}

VN=select;
while(VN != NULL) {
  if(VN->scalar) {
     if(VN->last_record < *first_record || VN->first_record > *last_record)
	return(FALSE);
     else {
	if(VN->first_record > *first_record) *first_record = VN->first_record;
	if(VN->last_record  < *last_record)  *last_record  = VN->last_record;
     }
  }
  VN=VN->next_var;
}
return(TRUE);
}

void init_array(select)
struct VAR      *select;
{
struct VAR      *VN;
int             i;

if(!SO.hyper_out )return;
VN = select;
while(VN != NULL) {
      if(VN->multidim) {
	 for(i=0; i<VN->num_values_out; i++) 
		memmove((Byte *)VN->data_array_out+i*VN->bytes_value, 
			VN->pad_value, VN->bytes_value);
	} /* VN->multidim */
	VN=VN->next_var;
    }
}
void CDFLIST_list_data(screen, CDF, select, num_select, data_values, fptr)
struct  GLOBAL_struct   *screen;
struct  CDF_struct      *CDF;
struct  VAR             *select;
long int                num_select;
union mixed             *data_values;
FILE                    *fptr;
{
struct  CDF_struct      new_CDF;
int                     cont;
int                     valid;
int                     first_valid;
int                     data_found_in_record;
long int                record_num, out_record_num;
int                     dim_num;
long int                x[CDF_MAX_DIMS],ox[CDF_MAX_DIMS];
int                     copy_complete;
long int                rcode;
int                     num_lines_page;
int                     exit_code;
int                     line_cnt;
int                     i;
long int                cnt, out_cnt;
struct VAR              *VN;
int                     col,end_col;
int                     data_found = FALSE;
int                     change_output = FALSE;
long                    first_record, last_record;
cont = CONTINUEkey_LIST;
line_cnt = 0;

rcode = CDFLIST_list_startup(screen, CDF, select, num_select,
	&num_lines_page, data_values, fptr, &new_CDF, 
	&first_record, &last_record);
if(rcode != CDF_OK)
   {
   if(rcode != NODATA) {
      exit_code = print_error(screen, rcode);
      if(rcode == BAD_MALLOC)ExitBAD;
    }
   else
     exit_code = NOCONTINUE;

   if(exit_code == NOCONTINUE)
      {
      rcode = CDFLIST_list_endup(screen, CDF, select, num_select,
	data_found, cont, change_output, line_cnt, data_values, &new_CDF);
      return;
      }
   }

first_valid = TRUE;
out_record_num = -1;
/* standby for liftoff */
for(record_num=first_record; record_num <= last_record && cont==CONTINUEkey_LIST;
  ++record_num)
    {
    for(dim_num = 0; dim_num < C.curr_group->num_dims; ++dim_num) {
	x[dim_num] = ox[dim_num] = 0;
	}
 
    cnt = 1; 
    out_cnt = 1;
    clear_scalars(select);
    if(scalar_check(CDF, select, record_num, data_values))
	{
/*      if(C.output == CDFOUT)init_array(select); */
	data_found_in_record = FALSE;
	copy_complete = FALSE;
	while (!copy_complete && cont == CONTINUEkey_LIST)
	     {
/*
Get the data for the variables
*/
	     CDFLIST_get_data(CDF, select, num_select,
		  record_num, x, data_values);
/*
See if the data falls within the range of the specified filters
If the CDF has zero dimensions, the record has already passed
*/

	     if(CDF->curr_group->num_dims > 0 && SO.filters == FILTER )
		   valid = CDFLIST_filter(select,num_select,data_values, 
				C.output);
	     else
		   valid = TRUE;
	     if(valid)
		{
		if(C.output == CDFOUT)
		   {
		   if(!data_found_in_record)out_record_num++;
		   data_found_in_record = TRUE;
		   rcode = CDFLIST_put_CDF(&new_CDF, out_cnt, out_record_num, 
			ox, select, num_select, data_values);
		   if(rcode < CDF_WARN) {
		      exit_code = print_error(screen, rcode);
		      if(exit_code == NOCONTINUE) {
			 rcode = CDFLIST_list_endup(screen, CDF, select, 
			   num_select, data_found, cont, change_output, 
			   line_cnt, data_values, &new_CDF);
			  return;
		      }
		   }
		   data_found = TRUE;
		   } /* valid CDF output */
		else
		   {
/*
Data passes all filters, if this is the first time then save off the
SMG so data may be listed to the screen
*/
		   if((first_valid) &&
		      (C.output == TERMIN || C.output == TERMFILE))
		       paste_virtual_display(S.SCREEN_vid, SCREEN_ROW_PASTE, SCREEN_COL_PASTE);

		   data_found = TRUE;
/*
Print a HEADER to the listing
*/
		   if(line_cnt == 0)
		      {
		      if(C.output != FILEOUT)
			 erase_display(S.SCREEN_vid, 0, 0, SCREEN_ROWS-1,
				SCREEN_COLUMNS-1);
		      CDFLIST_print_header(S.SCREEN_vid, &line_cnt, select, num_select,
					C.output, fptr, first_valid);
		      }
		   first_valid = FALSE;
		   VN=select;
		   col = 1;
		   for(i=0; i<num_select && cont == CONTINUEkey_LIST; i++)
		     {
		     if(VN->display == DISPLAY)
			{
			CDFLIST_print_string(VN, NORMAL_PRINT, &data_values[i]);
			end_col = col + strlen(print_string);
			if((end_col > 80) &&
			   (C.output == TERMIN || C.output == TERMFILE))
			   {
			   line_cnt++;
			   col = 1;
			   if(line_cnt == num_lines_page-1)cont = end_of_page(screen, CDF,
			      select, num_select, &line_cnt, fptr, &change_output);
			   }
			if(cont == CONTINUEkey_LIST)CDFLIST_print_data(S.SCREEN_vid, line_cnt, &col,
					    C.output, fptr);
			} /* Display variable */
		     VN=VN->next_var;
		     }/* end-of-loop*/
		   if(C.output == TERMFILE || C.output == FILEOUT)
		      write_eol(fptr);
		   line_cnt++;
		   col = 1;
		   if((line_cnt == num_lines_page-1) &&
		      (C.output == TERMIN || C.output == TERMFILE))
		       cont = end_of_page(screen, CDF, select, num_select,
				&line_cnt, fptr, &change_output);
		   } /* valid terminal output */
/*
Check output indices to see if all output indices have been filled
*/
		   OffsetIndices(out_cnt++, 
		    new_CDF.curr_group->values_per_record,
		    new_CDF.majority == ROW_MAJOR ? (Logical) TRUE : (Logical) FALSE, 
		    new_CDF.curr_group->num_dims, 
		    new_CDF.curr_group->PhyDimValues,
		    ox, &copy_complete);
		} /* valid point */
/*
Generate next set of input indices
*/
		if(cont == CONTINUEkey_LIST && !copy_complete)
		   OffsetIndices(cnt++, 
		    C.select_values_per_record,
		    C.majority == ROW_MAJOR ? (Logical) TRUE : (Logical) FALSE, 
		    C.select_num_dims, C.select_PhyDimValues,
		    x, &copy_complete);
	      }/* !copy_comple*/
	if(C.output == CDFOUT && SO.hyper_out) {
	   rcode = CDFLIST_write_multidim_to_CDF(&new_CDF, select, 
			out_record_num);
	   if(rcode < CDF_WARN) {
	      exit_code = print_error(screen, rcode);
	      if(exit_code == NOCONTINUE) {
		 rcode = CDFLIST_list_endup(screen, CDF, select, 
		   num_select, data_found, cont, change_output, 
		   line_cnt, data_values, &new_CDF);
		  return;
		  }
	      }
	   }
	}/* record pass */
/*
Look for user trying to break the search - aw3
*/

#if defined(dos)
	    if(dos_cont() == NOCONTINUE)
	       {
	       copy_complete = TRUE;
	       cont = NOCONTINUE;
	       }
#endif
   }/*record_num*/
rcode = CDFLIST_list_endup(screen, CDF, select, num_select,
	data_found, cont, change_output, line_cnt, data_values, &new_CDF);
if(rcode != CDF_OK)
   {
   exit_code = print_error(screen, rcode);
   if(exit_code == NOCONTINUE)ExitBAD;
   }
}
void next_indices(x, num_dims, dim_sizes, copy_complete)
long int        x[];
long int        num_dims;
/*
long int        dim_sizes[];
*/
long int        *dim_sizes;
int             *copy_complete;
{
int             cp;
int             valid_perm;
int             dim_num;
cp = *copy_complete;
if(num_dims == 0)
   cp = TRUE;
else
   {
   valid_perm = FALSE;
   dim_num = 1;
   while (!valid_perm && !cp)
       {
       if (x[dim_num-1] < (dim_sizes[dim_num-1] - 1))
	   {
	   x[dim_num-1] = x[dim_num-1] + 1;
	   valid_perm = TRUE;
	   }
       else
	   {
	   if (dim_num < num_dims)
	       {
	       x[dim_num-1] = 0;
	       dim_num = dim_num + 1;
	       }
	   else
	       cp = TRUE;
	   }
       }/*valid_perm*/
   }
*copy_complete = cp;
}
void CDFLIST_check_monoton(select, variables)
struct VAR              *select;
struct VAR              *variables;
{
long int                found;
struct VAR              *SN,*VN;
/*
Verify the monotonic value, just in case it was changed out of sequence
*/

SN=select;
while(SN != NULL)
     {
     found = FALSE;
     VN=variables;
     while(VN != NULL && !found)
	  {
	  if(strcmp(SN->var_mnemonic,VN->var_mnemonic)==0)
	     {
	     SN->monoton = VN->monoton;
	     found = TRUE;
	     }
	  VN=VN->next_var;
	  }
     SN=SN->next_var;
     }
}
void CDFLIST_check_filters(select, num_select, variables, num_vars, mult_flag)
struct VAR              *select;
long int                num_select;
struct VAR              *variables;
long int                num_vars;
int                     *mult_flag;
{
long int                i,j;
long int                found;
struct VAR              *SN,*VN;
*mult_flag = FALSE;
SN=select;
for (j=0; j<num_select; j++)
     {
     if(SN->dim_num == MULTIPLE)
	{
	*mult_flag = TRUE;
	found = FALSE;
	VN=variables;
	for (i=0; i<num_vars && !found; i++)
	     {
	     if(strcmp(SN->var_mnemonic,VN->var_mnemonic)==0)
		{
		SN->filter = FALSE;
		found = TRUE;
		}
	     VN=VN->next_var;
	     }
	}
     SN=SN->next_var;
     }
#if 0
SN=select;
for (j=0; j<num_select; j++)
     {
     if(SN->filter && SN->record_variance == VARY && !SN->scalar)
	SN->filter = FALSE;
     SN=SN->next_var;
     }
#endif
}
CDFstatus CDFLIST_add_independent(select, num_select, variables, num_vars)
struct VAR              *select;
long int                *num_select;
struct VAR              *variables;
long int                num_vars;
{
int                     i,j;
long int                ns;
int                     found;
struct VAR              *VN;
struct VAR              *SN;
struct VAR              *already_selected;
struct VAR              *last;
ns = *num_select;
VN = variables;
for (i=0; i<num_vars; i++)
  {
  if(!VN->record_variance)
     {
     found = FALSE;
     already_selected = select;
     for (j=0; j<ns; j++)
	  {
	  if(strcmp(already_selected->var_mnemonic, VN->var_mnemonic)==0)
	     found = TRUE;
	  already_selected = already_selected->next_var;
	  }
	  if(!found)
	     {
	     if((SN = (struct VAR *) malloc (sizeof (struct VAR))) == NULL)
		 return(BAD_MALLOC);
	     memmove(SN, VN, sizeof(struct VAR));
	     SN->filter = FALSE;
	     SN->display = DISPLAY;
	     SN->next_var = NULL;
	     last = var_load(select, (int) ((*num_select)-1));
	     last->next_var = SN;
	     *num_select = *num_select + 1;
	     }
	}/*RV FALSE*/
     VN=VN->next_var;
     }/*var loop*/
return(CDF_OK);
}
CDFstatus init_discrete(screen, CDF, possible, num_poss)
struct  GLOBAL_struct   *screen;
struct  CDF_struct      *CDF;
struct  VAR             *possible;
long int                num_poss;
{
int     i;
struct  VAR             *VN;
CDFstatus               rcode;
int                     exit_code;
/*
Load in discrete values for popup menues
*/
VN=possible;
for(i=0; i<num_poss; i++)
    {
    if(VN->discrete)
       {
/*
Check to see if it is already loaded
*/
       if(VN->bin_value == NULL)
	  {
	  rcode = CDF_OK;
/*
Make sure there isn't to many values to load
*/
	  if(VN->num_values <= MAX_VALUES)
	     {
	     VN->bin_value = (double *)
			      malloc((size_t) (VN->num_values*sizeof(double)));
	     if(VN->bin_value != NULL)
		{
		VN->char_value = (char *) malloc((size_t) (VN->num_values*MINMAX_SIZE));
		if(VN->char_value == NULL)
		   {
		   exit_code = print_error(screen, BAD_MALLOC);
		   if(exit_code == NOCONTINUE)return(BAD_MALLOC);
		   }
		}
	     else
		{
		exit_code = print_error(screen, BAD_MALLOC);
		if(exit_code == NOCONTINUE)return(BAD_MALLOC);
		}
		rcode = CDFLIST_get_discrete(C.CDF_id, VN->Z,
				  VN->dim_num, VN->var_num, VN->data_type,
				  VN->num_values, VN->bin_value, VN->char_value);
		if(rcode < CDF_WARN)
		   {
		   exit_code = print_error(screen, rcode);
		   if(exit_code == NOCONTINUE)return(rcode);
		   }
	     } /* to many values */
	   } /* var already loaded */
       }/* discrete variable */
       VN=VN->next_var;
    } /* end_of_loop */
return(CDF_OK);
}
void CDFLIST_select_VAR(screen, CDF, num_rows, num_cols, display, 
	select, num_select, filters, in_field_num)
struct                  GLOBAL_struct   *screen;
struct                  CDF_struct      *CDF;
int                     num_rows;
int                     num_cols;
struct vid_struct       display[];
struct VAR              **select;
long int                *num_select;
int                     *filters;
int                     *in_field_num;
{
struct vid_struct       *DIS_display;
struct vid_struct       *SELECT_display;
struct VAR              *possible;
long int                num_vars;
long int                num_poss;
int                     i, n;
double                  min_max;
int                     var_num, val_num, select_num;
int                     row, col;
int                     scroll;
int                     tcode;
int                     col_field;
int                     col_paste, dis_rows;
int                     first_blank;
int                     field_num, temp_field;
int                     last_error;
int                     len;
int                     exit_code;
char                    mes[80];
char                    row_data[80];
char                    value[EPOCH_WIDTH];
char                    mnemonic[CDFLIST_MAX_VAR_LENGTH+1];
char                    temp[81];
static int              scolumns[4] = { 6, 26, 51, 76 };
int                     error;
int                     select_all, start, end;
int                     erase_mode;
int                     value_entered;
int                     start_page; /*jtl*/
int                     ok;
int                     video_type;
double                  echeck;
int                     bump;
int                     redraw;
struct VAR              *VN;
int                     rcode;
static char             dup_mes[] = " has already been selected";
static char             min_max_error[] = "Error detected in MIN_MAX field";
AOSs1 (select_var_mes,
       "Press _____ to view valid variables and select from pop-up menu")
AOSs1A (select_data_mes,
    "Enter a value or press _____ to select discrete values from pop-up menu")
static char             to_many_mes[] =
"Variable has too many values to select from pop-up,manual input required";
static char             no_discrete_mes[] =
"Current Variable does not contain only discrete values, enter manually";

static char             string_mes[] =
"Variable not available for filtering, use another variable if possible";
static char             min_gt_max[] =
"Minimum value greater than Maximum value";
static char             EPOCH_format[] =
"DD-MMM-YYYY HH:MM:SS.MSC";
static char             EPOCH_error_mes[] =
"Error detected reading EPOCH";
AOSs1B (Display_var_mes,
       "Enter ___ to display current variable or ___ to not display variable")
static char             truncation[] = "...";
static int exit_keys[] = { SELECTkey_LIST,  ACTIONkey_LIST,    POPUPkey_LIST,
			   PREVVARkey_LIST, NEXTVARkey_LIST, PREVFIELDkey_LIST, NUL};
EncodeKeyDefinitions(1, select_var_mes,  POPUPkey_LIST);
EncodeKeyDefinitions(1, select_data_mes, POPUPkey_LIST);
EncodeKeyDefinitions(1, Display_var_mes, OUTPUTkey_LIST, NOOUTPUTkey_LIST);

possible = C.curr_group->first_var;
num_vars = C.curr_group->num_vars;

if(num_vars < 8)
   num_poss = 8;
else
   num_poss = num_vars;

SELECT_display = (struct vid_struct *)
		  malloc((size_t) ((num_vars+1)*sizeof(struct vid_struct)));
if(SELECT_display == NULL)
   {
   exit_code = print_error(screen, BAD_MALLOC);
   if(exit_code == NOCONTINUE)ExitBAD;
   }

VN=possible;
for(i=0; i<num_vars+1; i++)
    {
    SELECT_display[i].row = i;
    SELECT_display[i].col = 1;
    SELECT_display[i].field_col = 1;
    if(i == 0)
       strcpy(SELECT_display[i].label,"**SELECT ALL**");
    else if(i == 1) {
       strcpy(SELECT_display[i].label,"**RECORD_NUM**");
       VN=VN->next_var;
       }
    else
       {
       if(VN->var_mnemonic_len < VARSELECT_COLUMNS)
	   strcpy(SELECT_display[i].label, VN->var_mnemonic);
       else
	   {
	   strncpy(SELECT_display[i].label,VN->var_mnemonic,
		   VARSELECT_COLUMNS-3);
	   strcat(SELECT_display[i].label,truncation);
	   }
       VN=VN->next_var;
       }
    }
var_num = 1;
tcode = CONTINUEkey_LIST;
last_error = FALSE;
col_field = 1;
redraw = TRUE;
row = 2;
read_display(S.VAR_vid, row,  row_data);
get_field(row_data, 1, 3, mnemonic, &first_blank, &value_entered);
sscanf(row_data, "%3d",&select_num);
start_page = select_num;
while(tcode != ACTIONkey_LIST)
      {
      CDFLIST_selectvar_keydef(screen, col_field);
/*
Calculate which position to be positioned to
*/
      field_num = select_num * NUM_HORIZ_FIELDS + col_field;
      col = scolumns[col_field-1];
      if(redraw)
	 {
	 redraw = FALSE;
	 erase_mode = ERASE;
	 begin_pasteboard_update();
	 for(i=0; i<NUM_HORIZ_FIELDS; i++)
	     {
	     put_chars(S.VAR_vid, display[i].label, strlen(display[i].label),
		display[i].row, display[i].col, erase_mode, NORMAL);
	     erase_mode = NOERASE;
	     }
	 end_pasteboard_update();
	 }
      if(col_field == 1 || col_field == 4)
	 {
/*
Select a variable
*/
	 if(col_field == 1)
	    {   
	    if(!last_error)CDFLIST_put_message(S.MES_vid, select_var_mes[0], 
		NOBELL, NORMAL, NOPAUSE);
	    last_error = FALSE;
	    }
	 else
	    CDFLIST_put_message(S.MES_vid, Display_var_mes[0], NOBELL, NORMAL, 
		NOPAUSE);
	 set_cursor_abs(S.VAR_vid, row, col);
/*
See if the USER wishes to select a variable
*/
	    read_input(
#if defined(CURSESui)
		       S.VAR_vid,
#endif
				 &tcode, PASSTHRUri, TRUE);
	 }
      else
	 { /* min or max */
/*
Minimum or Maximum range input
first Copy Mnemonic
*/
	 read_display(S.VAR_vid, row,  row_data);
	 get_field(row_data, 6, CDFLIST_MAX_VAR_LENGTH, mnemonic,
		   &first_blank, &value_entered);
	 error = TRUE;
	 while (error)
	       {
	       error = FALSE;
	       set_cursor_abs(S.VAR_vid, row, col);
	       read_display(S.VAR_vid, row,  row_data);
/*
Copy Mnemonic
*/
	       get_field(row_data, 6, CDFLIST_MAX_VAR_LENGTH, mnemonic,
		   &first_blank, &value_entered);
/*
Copy Minimum or Maximum value so it may be edited
*/
	       var_num = get_var_num(possible, mnemonic, num_vars);
	       VN = var_load(possible, var_num);
	       if(var_num == NOTTHERE || VN->data_type != CDF_EPOCH)
		  {
		  len = MINMAX_SIZE;
		  get_field(row_data, col, len-1, value, &first_blank,
		  &value_entered);
		  }
	       else
		  {
		  len = EPOCH_WIDTH;
		  put_chars(S.VAR_vid, EPOCH_format, EPOCH_WIDTH-1,
		  display[col_field-1].row, display[col_field-1].col,
		  NOERASE, NORMAL);
		  redraw = TRUE;
		  get_field(row_data, col, len-1, value, &first_blank,
		  &value_entered);
		  }
	       if(!last_error)
		  CDFLIST_put_message(S.MES_vid, select_data_mes[0], NOBELL,
		  NORMAL, NOPAUSE);
	       input_field(S.VAR_vid, value, row, col, len-1, exit_keys, &tcode, 
		INSERTTOGGLEkey_LIST, SOLkey_LIST, EOLkey_LIST, NOTTHERE, 
		DELENDkey_LIST, REFRESHkey_FSI);
	       if(!is_blank(value))
		{
		if(filters[select_num-1] == FILTER_OFF)
		    change_rendition(S.VAR_vid,row,col,1,len-1,NORMAL);
		else
		    change_rendition(S.VAR_vid,row,col,1,len-1,REVERSE);
		if(VN->data_type != CDF_EPOCH)
		  {
		  n = sscanf(value,"%lf",&min_max);
		  if(n == MIN_MAX_ERROR)
		     {
		     CDFLIST_put_message(S.MES_vid, min_max_error, RINGBELL,
					BLINKING, PAUSE);
		     error = TRUE;
		     }
		  else
		     {
		     strcpy(display[field_num-1].label, value);
		     if(error)CDFLIST_clear_row(S.MES_vid, MES_display, 1, 1,
				MES_COLUMNS);
		     }
		  } /* normal min or max */
	       else
		  { /* EPOCH min or MAX */
		  echeck = check_epoch(value);
		  if(echeck == -1.0)
		     {
		     CDFLIST_put_message(S.MES_vid, EPOCH_error_mes, RINGBELL,
					BLINKING, PAUSE);
		     error = TRUE;
		     }
		  else
		     {
		     if(filters[select_num-1] == FILTER_OFF)
			video_type = NORMAL;
		     else
			video_type = REVERSE;
		     CDFLIST_put_select_row(S.VAR_vid, display, row, field_num-1,
		     value, EPOCH_WIDTH-1, video_type);
		     strcpy(display[field_num-1].label, value);
		     if(error)
		     CDFLIST_clear_row(S.MES_vid, MES_display, 1, 1,
			MES_COLUMNS);
		     }
		  } /* end EPOCH min or max */
	       } /* read in value */
	    else
	       strcpy(display[field_num-1].label, value);
	     }/* not blank */
	 }/* min or max end */
      switch (tcode)
	  {
	  case NEXTVARkey_LIST:
	       row++; select_num++;
	       if(select_num > num_poss)select_num = 1;
	       if(row > 9)
		  {
		  if(num_poss > 8)
		     {
		     row = 9;
		     start_page++;
		     if(start_page > num_poss)start_page = 1;
		     load_vars(S.VAR_vid, display, start_page, num_poss,
			filters);
		     }
		  else
		     {
		     row = 2;
		     select_num = 1;
		     start_page = 1;
		     }
		  }
	       break;
	  case PREVVARkey_LIST:
	       row--; select_num--;
	       if(select_num < 1)select_num = (int) num_poss;
	       if(row < 2)
		  {
		  if(num_poss > 8)
		     {
		     row = 2;
		     start_page--;
		     if(start_page < 1)start_page = (int) num_poss;
		     load_vars(S.VAR_vid, display, start_page, num_poss,
			filters);
		     }
		  else
		     {
		     row = 9;
		     select_num = 8;
		     start_page = 1;
		     }
		  }
	       break;
	  case NEXTFIELDkey_LIST:
	       col_field++;
	       scroll = FALSE;
	       next_field(&col_field, &select_num, &start_page, &row, &scroll,
				num_poss);
	       if(scroll)
		  load_vars(S.VAR_vid, display, start_page, num_poss, filters);
	       break;
	  case PREVFIELDkey_LIST:
	       col_field--;
	       scroll = FALSE;
	       next_field(&col_field, &select_num, &start_page, &row, &scroll,
				num_poss);
	       if(scroll)
		  load_vars(S.VAR_vid, display, start_page, num_poss, filters);
	       break;
	  case POPUPkey_LIST:
	       if(col_field == 1)
		  {
/*
Select variables from a POP-UP
*/
		  CDFLIST_menu_keydef(screen);
		  CDFLIST_select_menu_item(S.VARSELECT_vid,
		  S.MES_vid,&var_num, SELECT_display, num_vars+1, num_rows,
		  num_cols, VARSELECT_ROW_PASTE, VARSELECT_COL_PASTE,
		  MENU, &tcode);
		  if(tcode == ACTIONkey_LIST)
			{
			rcode = CDFLIST_read_VAR(display, possible,
			num_vars, num_poss, select, num_select, filters);
			if(rcode == 0)
			   CDFLIST_field_menu(screen, CDF, in_field_num);
			else if(rcode == MIN_GT_MAX)
			   {
			   CDFLIST_put_message(S.MES_vid, min_gt_max, RINGBELL,
					NORMAL, NOPAUSE);
			   last_error = TRUE;
			   tcode = CONTINUEkey_LIST;
			   }
			else {
			  exit_code = print_error(screen, BAD_MALLOC);
			  if(exit_code == NOCONTINUE)ExitBAD;
			}

			}
		  else if(tcode == SELECTkey_LIST)
			  {
/*
USER selected a variable
*/
			 if(var_num == SELECT_ALL)
			    {
/*

"SELECT ALL" option: loop thru all variables
*/
			    start = 1;
			    end = (int) num_vars;
			    select_num = 1;
			    start_page = 1;
			    select_all = TRUE;
			    row = 2;
			    init_var_display(display, num_poss);
			    if(num_vars < 8)
			       CDFLIST_clear_row(S.VAR_vid, display, 4,
			       VAR_NUM_ELEMENTS, VAR_COLUMNS);

			    load_vid(S.VAR_vid, display, 0,
				VAR_NUM_ELEMENTS, VAR_label);
			    }
			  else
			    {
/*
Selecting one variable
*/
			    start = var_num - 1;
			    end = var_num - 1;
			    select_all = FALSE;
			    }
			  for(var_num = start; var_num <= end; var_num++)
			  {
			  VN = var_load(possible, var_num-1);
			  field_num = select_num * NUM_HORIZ_FIELDS + col_field;
			  len = strlen(SELECT_display[var_num].label);
/*
			  if(len > CDFLIST_MAX_VAR_LENGTH)len=CDFLIST_MAX_VAR_LENGTH;
			  strncpy(temp, SELECT_display[var_num].label, len);
			  temp[len] = '\0';
*/
			  strcpy(temp, SELECT_display[var_num].label);
			  if(!select_all)
/*
Check if current variable has been selected
*/
			     ok = check_var(display, temp, num_poss);
			  else
			     ok = TRUE;
			  if(!ok)
			     {
			     strcpy(mes,temp);
			     strcat(mes,dup_mes);
			     CDFLIST_put_message(S.MES_vid, mes, RINGBELL,
					NORMAL, NOPAUSE);
			     last_error = TRUE;
			     }
			  else
			     {
			     erase_display(S.VAR_vid, row, col, row,
				VAR_COLUMNS);
/*
Display selected variable
*/
			     len = strlen(temp);
			     if(len > CDFLIST_MAX_VAR_LENGTH)
				len = CDFLIST_MAX_VAR_LENGTH;
			     CDFLIST_put_select_row(S.VAR_vid, display, row,
			     field_num-1, temp, len, REVERSE);
/*
Save selected variable
*/
			     strcpy(display[field_num-1].label+
				   (display[field_num-1].field_col-1), temp);
			     display[field_num-1+1].label[0]='\0';
			     display[field_num-1+2].label[0]='\0';
	
			     if(VN->data_type == CDF_CHAR ||
				VN->data_type == CDF_UCHAR)
				filters[select_num-1] = FALSE;
			     else
				filters[select_num-1] = FILTER_ON;

			     if(filters[select_num-1] == FILTER_OFF)
				   video_type = NORMAL;
			     else
				   video_type = REVERSE;
/*
Display VALIDMIN & VALIDMAX
*/
			     if(VN->data_type == CDF_EPOCH)
				   {
/*
Display EPOCH time, if attributes are there
*/
				   if(VN->minmax_flag[0] !=
				      NOTTHERE)
				      CDFLIST_put_TIME(S.VAR_vid, display, row,
				       field_num-1+1, VN->min,
					video_type, DISPLAY);
				   if(VN->minmax_flag[1] !=
				      NOTTHERE)
				      CDFLIST_put_TIME(S.VAR_vid, display, row,
				       field_num-1+2, VN->max, video_type,
					DISPLAY);
				   }
			      else
				   {
				   if(VN->data_type != CDF_CHAR
				   && VN->data_type != CDF_UCHAR)
				      {
				      if(VN->minmax_flag[0] !=
					 NOTTHERE)
					 CDFLIST_put_value(S.VAR_vid, display,
					 row, field_num-1+1, VN->min,
						video_type, DISPLAY);
				      if(VN->minmax_flag[1] != NOTTHERE)
					 CDFLIST_put_value(S.VAR_vid, display,
					 row, field_num-1+2,VN->max, video_type,
							DISPLAY);
				      } /* datatype not CDF_CHAR */
				   } /* Not EPOCH data type */
			     strcpy(display[field_num-1+3].label," Y ");
			     len = strlen(display[field_num-1+3].label);
			     CDFLIST_put_select_row(S.VAR_vid, display, row,
			     field_num-1+3, display[field_num-1+3].label, len,
				 NORMAL);
			     if(!select_all)
				col_field++;
			     else
				col_field = NUM_HORIZ_FIELDS+1;
			     scroll = FALSE;
			     next_field(&col_field, &select_num,
					&start_page, &row, &scroll, num_poss);
			     if(scroll)
				load_vars(S.VAR_vid, display, start_page, num_poss, filters);
			     }
			  }/*select loop*/
/*
Now scroll back up to the top
*/
			  if(select_all && num_poss > 8)
			    {
			    for(i=0; i<7; i++)
				{
				start_page++;
				load_vars(S.VAR_vid, display, start_page,
				num_poss, filters);
				}
				row = 2;
				start_page = 1;
				select_num = 1;
			    }
			}/*SELECTkey_LIST*/
		  }
	       else if(col_field != 4)
		  {
		  bump = TRUE;
/*
USER wishes to select from a POP-UP menu of values for a variable
EPOCH does not have a discrete set of values
Find the variable that the USER wishes to select from
*/
		  var_num = get_var_num(possible, mnemonic, num_vars);
		  VN = var_load(possible, var_num);
		  if(var_num != NOTTHERE)
		     {
		     if(VN->num_values == 0 || VN->num_values > MAX_VALUES)
			{
			bump = FALSE;
			if(VN->num_values > MAX_VALUES)
			   CDFLIST_put_message(S.MES_vid, to_many_mes,
					 RINGBELL, NORMAL, PAUSE);
			else if(VN->data_type != CDF_CHAR &&
				VN->data_type != CDF_UCHAR)
				CDFLIST_put_message(S.MES_vid, no_discrete_mes,
					RINGBELL, NORMAL, PAUSE);
			else
			   CDFLIST_put_message(S.MES_vid, string_mes, RINGBELL,
							  NORMAL, PAUSE);
			}
		     else
			{
			DIS_display = (struct vid_struct *) malloc((size_t)
				(VN->num_values*sizeof(struct vid_struct)));
			if(DIS_display == NULL)
			   {
			   exit_code = print_error(screen, BAD_MALLOC);
			   if(exit_code == NOCONTINUE)ExitBAD;
			   }
/*
Load in the values in the virtual display
*/
		       CDFLIST_load_discrete(VN->char_value,
			 VN->num_values, col_field,
			 DIS_display, &dis_rows, &col_paste);

		       create_virtual_display(dis_rows+BORDER_ROWS, 
			DIS_COLUMNS+BORDER_COLUMNS, &S.DIS_vid, BORDER, NORMAL);
/*
Select desired value
*/
		       CDFLIST_menu_keydef(screen);
		       val_num=1;
		       CDFLIST_select_menu_item(S.DIS_vid,
			S.MES_vid, &val_num, DIS_display,
			VN->num_values,  dis_rows, DIS_COLUMNS,
			DIS_ROW_PASTE, col_paste, MENU, &tcode);
			delete_virtual_display(S.DIS_vid);
			if(tcode == ACTIONkey_LIST)
			  {
			  rcode = CDFLIST_read_VAR(display, possible,
			   num_vars, num_poss, select, num_select, filters);
			  if(rcode == 0)
			   CDFLIST_field_menu(screen, CDF, in_field_num);
			  else if(rcode == MIN_GT_MAX)
			     {
			     CDFLIST_put_message(S.MES_vid, min_gt_max, RINGBELL,
					NORMAL, NOPAUSE);
			     last_error = TRUE;
			     tcode = CONTINUEkey_LIST;
			     }
			  else {
			    exit_code = print_error(screen, BAD_MALLOC);
			    if(exit_code == NOCONTINUE)ExitBAD;
			  }
			  }
			else if(tcode != QUITkey_LIST)
			     {
			     if(filters[select_num-1] == FILTER_OFF)
				video_type = NORMAL;
			     else
				video_type = REVERSE;
			     len = strlen(DIS_display[val_num-1].label);
			     erase_display(S.VAR_vid, row, scolumns[col_field-1], 
						      row, scolumns[col_field-1]+EPOCH_WIDTH-1);
			     CDFLIST_put_select_row(S.VAR_vid, display, row,
			     field_num-1, DIS_display[val_num-1].label,
			     len, video_type);
			     change_rendition(S.VAR_vid,row,
				scolumns[col_field-1], 1, MINMAX_SIZE-1 ,
				video_type);
			     strcpy(display[field_num-1].label,
			       DIS_display[val_num-1].label);
			     }
			free(DIS_display);
			}
		     }/*var_num there or not*/
		     if(bump)
			{
			col_field++;
			scroll = FALSE;
			next_field(&col_field, &select_num,
				&start_page, &row, &scroll, num_poss);
			if(scroll)
			   load_vars(S.VAR_vid, display, start_page,
					num_poss, filters);
			}
		  }
	       break;
	  case ACTIONkey_LIST:
	       rcode = CDFLIST_read_VAR(display, possible, num_vars, num_poss,
		       select, num_select, filters);
	       if(rcode == 0)
		  CDFLIST_field_menu(screen, CDF, in_field_num);
	       else if(rcode == MIN_GT_MAX)
		  {
		  CDFLIST_put_message(S.MES_vid, min_gt_max, RINGBELL,
					NORMAL, NOPAUSE);
		  last_error = TRUE;
		  tcode = CONTINUEkey_LIST;
		  }
	       else {
		 exit_code = print_error(screen, BAD_MALLOC);
		 if(exit_code == NOCONTINUE)ExitBAD;
	       }
	       break;
	  case REFRESHkey_FSI:
	       repaint_screen();
	       break;
	  case DELETEVARkey_LIST:
	       erase_display(S.VAR_vid, row, col, row, VAR_COLUMNS);
/*
Delete current variable
*/
	       display[field_num-1].label[display[field_num-1].field_col-1]='\0';
	       display[field_num-1+1].label[0]='\0';
	       display[field_num-1+2].label[0]='\0';
	       filters[select_num-1] = FALSE;
	       break;
	  case FILTERTOGGLEkey_LIST:
	       if(col_field == 1)
		  {
		  read_display(S.VAR_vid, row,  row_data);
		  get_field(row_data, 6, CDFLIST_MAX_VAR_LENGTH, mnemonic,
		   &first_blank, &value_entered);
		  if(value_entered)
		     {
		     var_num = get_var_num(possible, mnemonic, num_vars);
		     VN = var_load(possible, var_num);
		     if(var_num == NOTTHERE)
			len = MINMAX_SIZE-1;
		     else if(VN->data_type != CDF_EPOCH)
			len = MINMAX_SIZE-1;
		     else
			len = EPOCH_WIDTH-1;
		     if(filters[select_num-1] == FILTER_ON)
			{
/*
Turn filter off for this variable
*/
			change_rendition(S.VAR_vid,row,scolumns[1],1,len,NORMAL);
			change_rendition(S.VAR_vid,row,scolumns[2],1,len,NORMAL);
			filters[select_num-1] = FILTER_OFF;
			}
		     else
/*
Turn filter back on
*/
			{
			change_rendition(S.VAR_vid,row,scolumns[1],1,len,REVERSE);
			change_rendition(S.VAR_vid,row,scolumns[2],1,len,REVERSE);
			filters[select_num-1] = FILTER_ON;
			}
		     }
		  }
	       break;
	  case OUTPUTkey_LIST:
	  case NOOUTPUTkey_LIST:
	       if(col_field == 1 || col_field == 4)
		  {
		  if(col_field == 1)
		     temp_field = field_num+3;
		  else
		     temp_field = field_num;
		  if(tcode == OUTPUTkey_LIST)
		     strcpy(display[temp_field-1].label, " Y ");
		  else
		     strcpy(display[temp_field-1].label, " N ");
		  len = 1;
		  put_chars(S.VAR_vid, display[temp_field-1].label+1, len,
		    row, display[temp_field-1].col+1, 
		    erase_mode, NORMAL);
		  }
	       break;
	  }
      }
free(SELECT_display);
}
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';
}
int save_var(select, file_name, filters)
struct VAR              *select;
char                    *file_name;
int                     *filters;
{
long int                n;
long int                select_num;
FILE                    *SAVE_ptr=NULL;
struct variable
	{
	char    var_mnemonic[CDF_VAR_NAME_LEN];
	double  min;
	double  max;
	int     filter;
	int     flag;
	int     output;
	};
struct  variable        var;
struct  VAR             *VN;
SAVE_ptr = fopen(file_name, "wb");
if(SAVE_ptr != NULL)
   {
   select_num=1;
   VN=select;
   while(VN != NULL)
	 {
	 strcpy(var.var_mnemonic, VN->var_mnemonic);
	 var.min = VN->min;
	 var.max = VN->max;
	 var.filter = filters[VN->out_select_num];
	 var.flag = VN->restore;
	 var.output = VN->display;
	 n = fwrite(&var,sizeof(struct variable), 1, SAVE_ptr);
	 if(n == 0)return(FALSE);
	 select_num++;
	 VN=VN->next_var;
	 }
   fclose(SAVE_ptr);
   return(TRUE);
   }
return(FALSE);
}
int restore_var(screen, display, file_name, variables, filters, num_vars)
struct GLOBAL_struct    *screen;
struct vid_struct       *display;
char                    *file_name;
struct VAR              *variables;
int                     *filters;
long int                num_vars;
{
long int                n;
int                     len;
int                     var_num;
FILE                    *SAVE_ptr;
char                    mes[80];

int                     select_num;
int                     field_num;
int                     mode;
int                     row;
struct VAR              *VN;
struct variable
	{
	char    var_mnemonic[CDF_VAR_NAME_LEN];
	double  min;
	double  max;
	int     filter;
	int     flag;
	int     output;
	};
int done;
int video_type = REVERSE;
struct  variable        var;
static char var_not_found[] = " not found in current CDF or R/Z group";
SAVE_ptr = fopen(file_name, "rb");
if(SAVE_ptr != NULL)
   {
   init_var_display(display, num_vars);
   load_vid(S.VAR_vid, display, 0, VAR_NUM_ELEMENTS, VAR_label);
   row = 2;
   select_num = 1;
   field_num = NUM_HORIZ_FIELDS+1;
   done = FALSE;
   while(!done)
   {
   n = fread(&var,sizeof(struct variable), 1, SAVE_ptr);
   if(n == 1)
     {
     var_num = get_var_num(variables, var.var_mnemonic, num_vars);
     if(var_num != NOTTHERE)
	{
	VN = var_load(variables, var_num);
	len = strlen(var.var_mnemonic);
	if(len > CDFLIST_MAX_VAR_LENGTH)len = CDFLIST_MAX_VAR_LENGTH;

	strcpy(display[field_num-1].label+
	       (display[field_num-1].field_col-1), var.var_mnemonic);
/*
	strncpy(display[field_num-1].label+
	       (display[field_num-1].field_col-1), var.var_mnemonic, len);
	display[field_num-1].label[display[field_num-1].field_col-1+len] = '\0';
*/
	mode = NONDISPLAY;
	if(row <= 9)
	   {
	   CDFLIST_put_select_row(S.VAR_vid, display, row,
			     field_num-1, var.var_mnemonic, len, REVERSE);
	   mode = DISPLAY;
	   }
	filters[select_num-1] = var.filter;
	if(var.filter)
	   {
	   if(var.filter == FILTER_ON)
	      video_type = REVERSE;
	   else
	      video_type = NORMAL;
	   if(VN->data_type == CDF_EPOCH)
	      {
	      if(var.flag != MAX_ONLY)
	      CDFLIST_put_TIME(S.VAR_vid, display, row, field_num-1+1, var.min,
					video_type, mode);
	      if(var.flag != MIN_ONLY)
	      CDFLIST_put_TIME(S.VAR_vid, display, row, field_num-1+2, var.max,
					video_type, mode);
	      }
	   else if(VN->data_type != CDF_CHAR  && VN->data_type != CDF_UCHAR)
	      {
	      if(var.flag != MAX_ONLY)
	      CDFLIST_put_value(S.VAR_vid, display, row, field_num-1+1, var.min,
			video_type, mode);
	      if(var.flag != MIN_ONLY)
	      CDFLIST_put_value(S.VAR_vid, display, row, field_num-1+2, var.max,
			video_type, mode);
	      } /* Not EPOCH data type */
	   }
	if(var.output == DISPLAY)
	   strcpy(display[field_num-1+3].label, " Y ");
	else
	   strcpy(display[field_num-1+3].label, " N ");
	if(row <= 9)
	   {
	   len = strlen(display[field_num-1+3].label);
	   CDFLIST_put_select_row(S.VAR_vid, display, row, field_num-1+3,
		display[field_num-1+3].label, len, NORMAL);
	   }
	row++; field_num +=NUM_HORIZ_FIELDS; select_num++;
	}
     else
	{
	strcpy(mes, var.var_mnemonic);
	strcat(mes, var_not_found);
	CDFLIST_put_message(S.MES_vid, mes, RINGBELL, NORMAL, SHORTPAUSE);
	}
       }
    else
	done = TRUE;
     }
   fclose(SAVE_ptr);
   return(TRUE);
   }
return(FALSE);
}
void get_list_info(select, num_select, output, num_lines_page, squeeze)
struct VAR      *select;
long int        num_select;
int             output;
int             *num_lines_page;
int             *squeeze;
{
struct VAR      *VN;
int             i;
int             line_width;
int             total_line_width;
*squeeze = TRUE;
/*
on UNIX we will only be able to write out 132 chars to screen
*/
/*
Calculate number of lines per page if listing output to terminal
*/
if(output != TERMFILE)
   *num_lines_page = 24;
else
   *num_lines_page = 23;


if(output != CDFOUT)
   {
   line_width = 0;
   total_line_width = 0;
   VN = select;
   for(i=0; i < num_select; i++)
       {
       if(VN->display == DISPLAY)
	  {
	  if(VN->data_type == CDF_EPOCH)
		{
		line_width +=SO.EPOCH_output_len[SO.EPOCH_format-1];
		if(SO.print_mode == HORIZONTAL)
		   total_line_width +=
		 (int)(SO.EPOCH_output_len[SO.EPOCH_format-1]*VN->max_values);
		}
	  else if((SO.variable_format == FORMAT && VN->format) ||
		  (VN->var_num == RECORD_VAR_NUM))
		{
		line_width +=VN->field_width;
		if(SO.print_mode == HORIZONTAL)
		   total_line_width += (int) (VN->field_width*VN->max_values);
		}
	  else if(VN->data_type == CDF_CHAR ||
		VN->data_type == CDF_UCHAR)
		{
		line_width +=(int) VN->num_bytes;
		if(SO.print_mode == HORIZONTAL)
		   total_line_width +=(int) (VN->num_bytes*VN->max_values);
		}
	  else
		{
		line_width +=14;
		if(SO.print_mode == HORIZONTAL)
		   total_line_width +=(int) (14*VN->max_values);
		}
	  }/*DISPLAY*/
	  VN=VN->next_var;
       }/* end loop */
       if(SO.list_mode == ZMODE && SO.print_mode == HORIZONTAL &&
	  total_line_width <= 80)*squeeze = FALSE;
   } /* not cdf out */
}
void whats_happening(MES_vid, output, file_name)
WINDOWid        MES_vid;
int             output;
char            *file_name;
{
char            mes[80];
static char             file_mes[]   = "Output to file ";
static char             tp[] = " taking place...";
static char             cdf_mes[]   = "Output to CDF ";
#if defined(dos)
static char             scan_mes[] =
"Scanning for selected data.  Hit <Q> to interrupt...";
#else
static char             scan_mes[] =
"Scanning for selected data...";
#endif
if(output == TERMFILE || output == TERMIN)
   CDFLIST_put_message(MES_vid, scan_mes, NOBELL, BLINKING, NOPAUSE);
else
   {
   *mes = '\0';
   if(output == FILEOUT)
      strcat(mes, file_mes);
   else
      strcat(mes, cdf_mes);
   strcat(mes, file_name);
   strcat(mes, tp);
   CDFLIST_put_message(MES_vid, mes, NOBELL, BLINKING, NOPAUSE);
   }
}
#if defined(dos)
int     dos_cont()
{
char    ch;
/*
Look for user trying to break the search - aw3
*/
if (kbhit())  /* abort disp if keypressed */
    {
    if ( (ch = getch()) == 0)
	  ch = 0x80 | getch();
    if ((ch == 'Q') || (ch == 'q'))
	 return(NOCONTINUE);
    }
return(CONTINUEkey_LIST);
}
#endif

CDFstatus CDFLIST_list_startup(screen, CDF, select, num_select,
	num_lines_page, data_values, fptr, new_CDF, first_record, 
			       last_record)
struct GLOBAL_struct    *screen;
struct CDF_struct       *CDF;
struct VAR              *select;
long int                num_select;
int                     *num_lines_page;
union mixed             *data_values;
FILE                    *fptr;
struct CDF_struct       *new_CDF;
long                    *first_record;
long                    *last_record;
{
CDFstatus               rcode;
int                     status;
long int                max_bytes = 0;
int                     squeeze;

rcode = CDFLIST_alloc_STRING(select, num_select, data_values);
if(rcode != CDF_OK)return(BAD_MALLOC);

fudge_it(select, num_select);

if(!find_records(CDF, select, data_values, first_record, last_record)) 
   return(NODATA);

record_display_format(select, *last_record);

get_list_info(select, num_select, C.output, num_lines_page, &squeeze);
print_string = NULL;
if(C.output != CDFOUT)
   {
   get_header(select, num_select, squeeze);
/*
create global variable to print data with, unless output is to CDF
*/
   max_bytes = get_max_bytes(select, num_select);
   print_string = (char *) malloc((size_t) (max_bytes+1));
   if(print_string == NULL)return(BAD_MALLOC);
   }
/*
if output to a file is specified create a file header
with the variable information for the listing
*/
if(C.output == FILEOUT || C.output == TERMFILE)
   CDFLIST_file_header(CDF, select, num_select, fptr);
/*
Tell the USER what's going on
*/
if(SO.mode != AUTO_DUMP)whats_happening(S.MES_vid, C.output, C.file_name);
/*
Generate information about output as though we are always creating
a new CDF, this will speed processing time
*/

rcode = CDFLIST_new_CDF_info(CDF, select, num_select, new_CDF);
if(rcode < CDF_WARN)return(rcode);
if(C.output == CDFOUT)
   {
/*
Create the NEW CDF
*/
   rcode = CDFLIST_create_new_CDF(CDF, select, num_select, new_CDF);
   if(rcode < CDF_WARN)return(rcode);
   }

if(SO.list_mode == REGMODE)compute_retrieval_ranges(CDF, select);

status = CDFLIST_alloc_ARRAY(select, num_select);
if(status != HYPER)
   {
   CDFLIST_free_ARRAY(select, num_select);
   SO.hyper = FALSE;
   }
else
   SO.hyper = TRUE;
if(SO.hyper)get_init_data(CDF, select); 
SO.hyper_out = FALSE;
if(C.output == CDFOUT) { 
   status = CDFLIST_alloc_OUTARRAY(select, num_select);
   if(status == HYPER) 
      SO.hyper_out = TRUE;
   else 
      CDFLIST_free_ARRAY(select, num_select);
   }
#if !defined(mac)
fflush(stdin);
#endif
if(rcode < CDF_WARN)return(rcode);
return(CDF_OK);
}
CDFstatus CDFLIST_list_endup(screen, CDF, select, num_select,
	data_found, cont, change_output, line_cnt, data_values, new_CDF)
struct GLOBAL_struct    *screen;
struct CDF_struct       *CDF;
struct VAR              *select;
long int                num_select;
int                     data_found;
int                     cont;
int                     change_output;
int                     line_cnt;
union mixed             *data_values;
struct CDF_struct       *new_CDF;
{
AOSs1 (end_prompt, "END of LISTING, Hit _____ to continue ")
static char             file_done_mes[] = "File Processing complete ";
static char             nodata_mes[] = "No data found in the specified range";
CDFstatus               rcode;
EncodeKeyDefinitions(1, end_prompt, CONTINUEkey_LIST);
CDFLIST_free_STRING(select, num_select, data_values);
CDFLIST_free_ARRAY(select, num_select);
if(C.output != CDFOUT && print_string != NULL) {
  free(print_string);
  print_string = NULL;
}
if((C.output == TERMIN || C.output == TERMFILE) &&
   (cont == CONTINUEkey_LIST && data_found))
    cont = get_1char(S.SCREEN_vid, end_prompt[0], line_cnt);

else if (C.output == CDFOUT)
	 {
	 rcode=CDFLIST_close(new_CDF);
	 if(rcode != CDF_OK)return(rcode);
	 }
if((data_found) &&
   (C.output == TERMIN || C.output == TERMFILE))
   {
/*
Restore SCREEN so additional listings may be produced
*/
   erase_display(S.SCREEN_vid, 0, 0, SCREEN_ROWS-1, SCREEN_COLUMNS-1);
   unpaste_virtual_display(S.SCREEN_vid);
   CDFLIST_clear_row(S.MES_vid, MES_display, 1, 1, MES_COLUMNS);
   }
else if(!data_found)
/*
These was no data found in the specified ranges
*/
	CDFLIST_put_message(S.MES_vid, nodata_mes, RINGBELL, NORMAL, NOPAUSE);
else if(SO.mode != AUTO_DUMP)
	CDFLIST_put_message(S.MES_vid, file_done_mes, NOBELL, NORMAL, NOPAUSE);
if(change_output)C.output = TERMFILE;

return(CDF_OK);
}
int keep_goin(screen, output, line_cnt, file_name, change_output)
struct  GLOBAL_struct   *screen;
int                     *output;
int                     line_cnt;
char                    *file_name;
int                     *change_output;
{
int                     cont_file;
int                     cont;
int                     resp;
char                    mes[80];
static char             file_mes[]   = "Output to file ";
static char             tp[] = " taking place...";
AOSs1 (cont_prompt,
       "Hit _____ to continue listing, any other key to end ")
#if defined(vms)
static char             contfile_prompt[] =
"Would you like to continue the output to your file (Y/N)";
#endif
#if defined(unix) || defined(dos) || defined(mac) || defined(posixSHELL)
static char             contfile_prompt[] =
"\nWould you like to continue the output to your file (Y/N)";
#endif
/*
End of a full page, see if the USER wishes to continue (TERMINAL output)
*/
EncodeKeyDefinitions(1, cont_prompt, CONTINUEkey_LIST);
cont = get_1char(S.SCREEN_vid, cont_prompt[0], line_cnt);
if(cont != CONTINUEkey_LIST && *output == TERMFILE)
   {
/*
USER wishes to stop TERMINAL output, if he is using TERMINAL/FILE output
see if he wishes to continue his output to his FILE
*/
   resp = FALSE;
   while(!resp)
      {
      cont_file = get_1char(S.SCREEN_vid, contfile_prompt, line_cnt+1);
      if(cont_file == YES || cont_file == yes)
	 {
	 *output = FILEOUT;
/*
Restore main CDFLIST input screen
*/
	 unpaste_virtual_display(S.SCREEN_vid);
	 mes[0] = '\0';
	 strcat(mes, file_mes); strcat(mes, file_name);
	 strcat(mes, tp);
	 CDFLIST_put_message(S.MES_vid, mes, NOBELL, BLINKING, NOPAUSE);
	 cont = CONTINUEkey_LIST; resp = OK_RESP;
	 *change_output = TRUE;
	 }
      else if(cont_file == NO || cont_file == no)
	      resp = OK_RESP;
    }

 }
return(cont);
}
int end_of_page(screen, CDF, select, num_select, line_cnt, fptr, change_output)
struct GLOBAL_struct    *screen;
struct CDF_struct       *CDF;
struct VAR              *select;
long int                num_select;
int                     *line_cnt;
FILE                    *fptr;
int                     *change_output;
{
int                     cont;

/*
We are at the end of page see if the user wishes to continue
*/
cont = keep_goin(screen, &C.output, *line_cnt, C.file_name, change_output);
if(cont == CONTINUEkey_LIST && C.output != FILEOUT)
   {
/*
user wishes to continue, print a file header
*/
   *line_cnt = 0;
   erase_display(S.SCREEN_vid, 0, 0, SCREEN_ROWS-1, SCREEN_COLUMNS-1);
   CDFLIST_print_header(S.SCREEN_vid, line_cnt, select,
			num_select, C.output, fptr, FALSE);
   }
return(cont);
}
void write_eol(fptr)
FILE *fptr;
{
fprintf(fptr, "\n");
}
Logical var_output(select, num_select)
struct  VAR     *select;
long int        num_select;
{
int i;
struct VAR      *VN;
VN=select;
/*
Making sure the user selected at least 1 variable
*/
for(i=0; i<num_select; i++)
  {
  if(VN->display == DISPLAY)return(TRUE);
  VN=VN->next_var;
  }
return(FALSE);
}
int CDFLIST_alloc_OUTARRAY(select, num_select)
struct VAR      *select;
long            num_select;
{
struct VAR      *VN;
int             i;
int             rcode;

VN = select;
for (i = 0; i < num_select; i++)
     {
     if(VN->multidim) {
	 rcode = alloc_array(&VN->data_array_out, VN->num_values_out, 
				VN->data_type);
	if(rcode != HYPER)return(rcode);
	}
     VN=VN->next_var;
     }
return (HYPER);
}
int CDFLIST_alloc_ARRAY(select, num_select)
struct VAR      *select;
long            num_select;
{
struct VAR      *VN;
int             i;
int             rcode;

VN = select;
for (i = 0; i < num_select; i++)
     {
     if(!VN->scalar)
	{
	if(VN->discrete)
	   rcode = alloc_array(&VN->data_array, VN->num_values, VN->data_type);
	else
	   rcode = alloc_array(&VN->data_array, VN->total_values, VN->data_type);
	if(rcode != HYPER)return(rcode);
	}
     VN=VN->next_var;
     }
return (HYPER);
}
int alloc_array(ptr, num_values, data_type)
void            **ptr;
long int        num_values;
long int        data_type;
{
int             rcode;
long int        size;

switch(data_type)
	   {
	   case CDF_REAL4:
	   case CDF_FLOAT:
		{
		size = num_values * sizeof(float);
#if defined(dos)
		if(size > MAX_ARRAY_SIZE)return(NO_HYPER);
#endif
		*ptr = (float *) malloc((size_t) size);
		break;
		}
	   case CDF_REAL8:
	   case CDF_DOUBLE:
	   case CDF_EPOCH:
		{
		size = num_values * sizeof(double);
#if defined(dos)
		if(size > MAX_ARRAY_SIZE)return(NO_HYPER);
#endif
		*ptr = (double *) malloc((size_t) size);
		break;
		}
	   case CDF_UINT4:
	   case CDF_INT4:
		{
		size = num_values * sizeof(long int);
#if defined(dos)
		if(size > MAX_ARRAY_SIZE)return(NO_HYPER);
#endif
		*ptr = (long int *) malloc((size_t) size);
		break;
		}
	   case CDF_INT2:
	   case CDF_UINT2:
		{
		size = num_values * sizeof(short int);
#if defined(dos)
		if(size > MAX_ARRAY_SIZE)return(NO_HYPER);
#endif
		*ptr = (short int *) malloc((size_t) size);
		break;
		}
	   case CDF_BYTE:
	   case CDF_INT1:
	   case CDF_UCHAR:
	   case CDF_UINT1:
		{
		size = num_values * sizeof(char);
#if defined(dos)
		if(size > MAX_ARRAY_SIZE)return(NO_HYPER);
#endif
		*ptr = (char *) malloc((size_t) size);
		}
	   }

rcode = *ptr == NULL ? NO_HYPER : HYPER;
return(rcode);

}
#include "cdfdist.h"

void calcPhysDim(rowMajor, numDims, dimSizes, PhyDimValues)
Logical rowMajor;
long    numDims;
long    *dimSizes;
long    *PhyDimValues;
{
int     i,ii,j;
int     terminator;
int     dimN;

  for (i = 0, dimN = (rowMajor ? 0 : (int)(numDims-1));
       i < numDims; 
       i++, (rowMajor ? dimN++ : dimN--))
       {
       PhyDimValues[dimN] = 1;
       terminator = rowMajor ? (int) numDims : -1;
       for(ii = 0, j= (rowMajor ? dimN+1 : dimN-1);
	   (ii < (int)(numDims-1) && j != terminator); 
	   ii++, (rowMajor ? j++ : j--) )
	   PhyDimValues[dimN] *= dimSizes[j]; 
       }

}
/******************************************************************************
* IndicesOffset.
******************************************************************************/

long IndicesOffset (numDims, dimIndices, nPhyDimValues)
long numDims;
long *dimIndices;
long *nPhyDimValues;
{
  long offset = 0;
  int dimN;
  for (dimN = 0; dimN < numDims; dimN++)
       offset += (dimIndices[dimN] * nPhyDimValues[dimN]);
  return offset;
}

/******************************************************************************
* OffsetIndices.
******************************************************************************/

void OffsetIndices (offset, max_values, rowMajor, numDims, 
				nPhyDimValues, indices, copy_complete)
long offset;
long max_values;
Logical rowMajor;
long numDims;
long *nPhyDimValues;
long *indices;
int *copy_complete;
{
  int dimN, i;
  *copy_complete = offset == max_values ? TRUE : FALSE;
  if(*copy_complete)return;
  for (i = 0, dimN = (rowMajor ? 0 : (int)(numDims-1));
       i < numDims; 
       i++, (rowMajor ? dimN++ : dimN--))
       {
       indices[dimN] = offset / nPhyDimValues[dimN];
       offset = offset % nPhyDimValues[dimN];
       } 
  return;
}
struct VAR *create_record_var(CDF, curr_group, Z)
struct CDF_struct       *CDF;
struct group            *curr_group;
int                     Z;
{
long                    num_dims;
long                    ds[CDF_MAX_DIMS];
int                     i;
struct VAR              *VN;
if(!Z)
   {
   num_dims = C.curr_group->num_dims;
   for(i=0; i<num_dims; i++)ds[i] = curr_group->dim_sizes[i];
   }
else
   num_dims = 0;
VN = NULL;
if((VN = (struct VAR *) malloc (sizeof (struct VAR))) == NULL)
   return(VN);

VN->Z = Z;
strcpy(VN->var_mnemonic, "**RECORD_NUM**");
VN->data_type = CDF_INT4;
VN->num_bytes = 1;
VN->record_variance = TRUE;
for(i=0; i<CDF_MAX_DIMS; i++)
    VN->dim_variances[i] = FALSE;
VN->var_num = RECORD_VAR_NUM;
VN->var_mnemonic_len = 14;
VN->filter = FALSE;
VN->scalar = SCALAR;
VN->discrete = FALSE;
VN->multidim = FALSE;
VN->data_array = NULL;
VN->data_array_out = NULL;
VN->bin_value = NULL;
VN->char_value = NULL;
VN->min = 1;
VN->max = curr_group->max_record_num+1;
VN->minmax_flag[0] = NORMAL;
VN->minmax_flag[1] = NORMAL;
VN->display = DISPLAY;
VN->bytes_value = (int) (CDFelemSize(VN->data_type) * VN->num_bytes);
VN->max_values = 1;
VN->total_values = 1;
for (i=0; i< num_dims; i++)
     VN->total_values=VN->total_values*ds[i];
if(VN->Z)
   {
   VN->var_num_dims=num_dims;
   for (i=0; i< num_dims; i++)
	{
	VN->act_dim_sizes[i] = ds[i];
	VN->var_sizes[i] = ds[i];
	}
   calcPhysDim( C.majority == ROW_MAJOR ? (Logical) TRUE : (Logical) FALSE,
		VN->var_num_dims, ds, VN->PhyDimValues);
   }
else
   {
   VN->var_num_dims=curr_group->num_dims;
   for(i=0; i< VN->var_num_dims; i++)
       {
       VN->act_dim_sizes[i] = curr_group->dim_sizes[i];
       VN->var_sizes[i]=curr_group->dim_sizes[i];
       }
   calcPhysDim(C.majority == ROW_MAJOR ? (Logical) TRUE : (Logical) FALSE,
	    VN->var_num_dims, VN->act_dim_sizes, VN->PhyDimValues);
   }
VN->dim_num=0;
VN->num_values=0;
VN->fillval = FALSE;
VN->format = TRUE;
VN->format_value = (void *) malloc((size_t) 4);
VN->pad_value = (void *) malloc((size_t) 4);
VN->format = TRUE;
VN->monoton = FALSE;
VN->monoton_value = NULL;
VN->monoton_value = (void *) malloc((size_t) 9);
if(VN->monoton_value != NULL)strcpy(VN->monoton_value, "INCREASE");

VN->monoton = INCREASE;
VN->next_var = NULL;
return (VN);
}
