/******************************************************************************
*
*  NSSDC/CDF                                            CDFwalk.  Part 2 of 2.
*
*  Version 1.5, 12-Aug-96, Hughes STX.
*
*  Modification history:
*
*   V1.0   1-May-92, H Leckner  Original version.
*                    J Love
*   V1.1  21-Aug-92, H Leckner  CDF V2.3 (shareable/zVar/NeXT).
*                    J Love
*   V1.2   2-Dec-93, H Leckner  CDF V2.4.
*   V1.2a  4-Feb-94, J Love     DEC Alpha/OpenVMS port.
*   V1.3  13-Dec-94, J Love     CDF V2.5.
*   V1.3a 23-Feb-95, J Love	Use `IsGraphChr'.
*   V1.4   4-Apr-95, J Love	POSIX.
*   V1.4a 18-Apr-95, J Love	More POSIX.
*   V1.4b 13-Jun-95, J Love	Linux.
*   V1.4c 20-Jun-95, J Love	Fixed bug involving NUL-termination of buffer
*				receiving character data read from the CDF.
*   V1.4d 17-Jul-95, J Love	CDFexport-related changes.
*   V1.4e 18-Sep-95, J Love	Macintosh event handling.
*   V1.5  12-Aug-96, J Love	CDF V2.6.
*
******************************************************************************/

#include "cdfwalk.h"

double r4_r8 PROTOARGs((float *));

/******************************************************************************
* DisplayRIP.
******************************************************************************/

static void DisplayRIP PROTOARGs((void));
static void DisplayRIP () {
  static char text[] = { "\
CDFwalk has been replaced by CDFexport.  You should begin\n\
using CDFexport instead of CDFwalk immediately.  CDFexport\n\
provides the same functionality as CDFwalk in addition to\n\
some new features.  CDFwalk is no longer being maintained\n\
and will eventually be removed from the CDF distribution.\n\
\n\
Enter any key to continue.\n" };
  static int exitKeys[] = { NUL };
  static struct EditWindowStruct EW = {
    " Attention! ", 7, 10, 60, 0, NULL, text, 7, 0, NULL,
    FALSE, TRUE, exitKeys, REFRESHkey_FSI, NUL, NUL, NUL, NUL, NUL, NUL,
    NUL, NUL, NUL
  };
  EditWindow (NEWew, &EW, TRUE);
  EditWindow (READew, &EW);
  EditWindow (DELETEew, &EW);
  return;
}

CDFstatus     CDFWALK_select_RZ(screen, CDF, tcode)
struct  GLOBAL_struct   *screen;
struct  CDF_struct      *CDF;
int                     *tcode;
{
int                     ok;
int                     tempcode;
long                    temp_val = 1;
int                    k,i;
char                    buf[80],temp[10];
int                     len;
int                     RZ_rows, RZ_columns;
struct vid_struct       *RZ_display;
static char             noRvar_mes[] = "There are no rVariables in this CDF";
static char             noRdata_mes[] = "The rVariables contain no data";
if(C.num_ZCDF > RZ_ROWS)
   RZ_rows = RZ_ROWS;
else
   RZ_rows = (int) C.num_ZCDF;
RZ_columns = 0;
RZ_display = (struct vid_struct *)
		  malloc((size_t) C.num_ZCDF * sizeof(struct vid_struct));
if(RZ_display == NULL)return(BAD_MALLOC);
for(k=0; k<C.num_ZCDF; k++)
    {
    for(i=0; i<80; i++)buf[i] = ' ';
    if(k == 0)
	    strcpy(buf, "rVariables");
    else if(C.num_dims[k] == 0)
	    strcpy(buf, "Z  0:[]");
    else
	    {
	    buf[0] = 'Z';
	    sprintf(buf+2,"%2d:[",(int)C.num_dims[k]);
	    if(C.num_dims[k] > 0)
	       {
	       for (i=0; i < C.num_dims[k]; i++)
		    {
		    sprintf(temp, "%ld", C.dim_sizes[k][i]);
		    if(i < C.num_dims[k]-1)
		       strcat(temp, ",");
		    else
		       strcat(temp,"]");
		    strcat(buf, temp);
		    }
	       }
	    }
    len = strlen(buf);
    if(len > RZ_columns)RZ_columns = len;
    RZ_display[k].row = k+1;
    RZ_display[k].col = 1;
    strcpy(RZ_display[k].label,buf);
   }
   if(RZ_columns > RZ_COLUMNS)RZ_columns = RZ_COLUMNS;
   create_virtual_display(RZ_rows+BORDER_ROWS, RZ_columns+BORDER_COLUMNS, 
				&S.RZ_vid, BORDER, NORMAL);
   ok = FALSE;
   while(!ok)
      { 
      CDFWALK_select_menu_item(S.RZ_vid, S.MES_vid,
	   &temp_val, RZ_display, (int) C.num_ZCDF, RZ_rows, RZ_columns,
	   RZ_ROW_PASTE, RZ_COL_PASTE, MENU, &tempcode);
      if(tempcode == QUITkey_WALK)
	      {
	      *tcode = QUITkey_WALK;
	      ok = TRUE;
	      }
      else if(temp_val == 1 && C.numRvars ==  0)
	      CDFWALK_put_message(S.MES_vid, noRvar_mes, RINGBELL,
					NORMAL, PAUSE);
      else if(temp_val == 1 && C.max_record_num[0] == -1)
	      CDFWALK_put_message(S.MES_vid, noRdata_mes, RINGBELL,
					NORMAL, PAUSE);
      else
	      {
	      *tcode = tempcode;
	      SO.curr_CDF = (int) (temp_val - 1);
	      ok = TRUE;
	      }
      }
   free(RZ_display);
   delete_virtual_display(S.RZ_vid);
   return(CDF_OK);
}
void CDFWALK_load_discrete(values, num_values, num_bytes, DIS_display,
			num_rows, num_cols)
char                    values[];
long                    num_values;
long                    num_bytes;
struct vid_struct       *DIS_display;
int                     *num_rows;
int                     *num_cols;
{

int                    i;
for (i=0; i<num_values; i++)
     {
	DIS_display[i].row = 1;
	DIS_display[i].col = 1;
	strncpy(DIS_display[i].label,&values[(int)(i*(num_bytes+1))],
		(size_t) num_bytes);
	DIS_display[i].label[(int)num_bytes] = '\0';
     }

*num_rows = (int) (num_values > DIS_ROWS ? DIS_ROWS : num_values);

*num_cols = (int) (num_bytes < DIS_COLUMNS ? num_bytes : DIS_COLUMNS);
}
void CDFWALK_get_EPOCH(CDF_id, Z, var_num, max_record_num,
			bin_values, char_values)
CDFid                   CDF_id;
int                     Z;
long                    var_num;
long                    max_record_num;
double                  bin_values[];
char                    *char_values;
{
long                    indices[CDF_MAX_DIMS];
long                    counts[CDF_MAX_DIMS];
long                    intervals[CDF_MAX_DIMS];
long                    record_num;
long                    recInterval;
int                    i;
CDFstatus               rcode;

for (i=0; i < CDF_MAX_DIMS; i++)
     {
     indices[i] = 0;
     counts[i] = 1;
     intervals[i] = 1;
     }
record_num = 0;
recInterval = 1;
rcode = CDFlib (SELECT_, CDF_, CDF_id, 
		     BOO(Z, zVAR_, rVAR_),  var_num,
		     BOO(Z, zVAR_RECNUMBER_,rVARs_RECNUMBER_),record_num,
		     BOO(Z, zVAR_RECCOUNT_, rVARs_RECCOUNT_), max_record_num+1,
		     BOO(Z, zVAR_RECINTERVAL_, rVARs_RECINTERVAL_),  recInterval,
		     BOO(Z, zVAR_DIMINDICES_, rVARs_DIMINDICES_), indices,
		     BOO(Z, zVAR_DIMCOUNTS_, rVARs_DIMCOUNTS_),    counts,
		     BOO(Z, zVAR_DIMINTERVALS_, rVARs_DIMINTERVALS_), intervals,
	    GET_,    BOO(Z, zVAR_HYPERDATA_, rVAR_HYPERDATA_),     bin_values,
		    NULL_);
if(rcode == CDF_OK)
   {
   for (record_num=0; record_num <= max_record_num; record_num++)
     {
     encodeEPOCH (bin_values[(int)record_num],
		  &char_values[(int)(record_num*EPOCH_WIDTH)]);
     }
   }
}
void CDFWALK_get_discrete(CDF_id, Z, dim_num, var_id, data_type, num_values,
		  bin_values, char_values)
CDFid                   CDF_id;
int                     Z;
long                    dim_num;
long                    var_id;
long                    data_type;
long                    num_values;
double                  bin_values[];
char                    *char_values;
{
long                    indices[10];
char                    temp_val[MINMAX_SIZE+1];
int                     i;
long                    record_num;
CDFstatus               rcode;
union   mixed           temp;

record_num = 0;
for (i=0; i < 10; i++)
     indices[i] = 0;
for (i=0; i < num_values; i++)
     {
     if(dim_num > 0)
	indices[(int)(dim_num-1)]=i;
     else
	record_num = i;
     rcode = CDFlib (SELECT_, CDF_, CDF_id,
			  BOO(Z,zVAR_,rVAR_), var_id,
			  BOO(Z,zVAR_RECNUMBER_,rVARs_RECNUMBER_),record_num,
			  BOO(Z,zVAR_DIMINDICES_,rVARs_DIMINDICES_),indices,
		 GET_,    BOO(Z,zVAR_DATA_,rVAR_DATA_), &temp,
		 NULL_);
     
     if(rcode >= CDF_OK)
	{
	switch(data_type)
	     {
	     case CDF_REAL4:
	     case CDF_FLOAT:
	     bin_values[i] = r4_r8(&temp.r4);
	     if(bin_values[i] < -1.e12 ||
		bin_values[i] >  1.e12)
		sprintf(temp_val,"%e",bin_values[i]);
	     else
		sprintf(temp_val,"%f",bin_values[i]);
	     break;
	     case CDF_REAL8:
	     case CDF_DOUBLE:
	     case CDF_EPOCH:
		     if(temp.r8 < -1.e12 ||
			temp.r8 >  1.e12)
			sprintf(temp_val,"%e",temp.r8);
	     else
			sprintf(temp_val,"%f",temp.r8);
		     bin_values[i] = temp.r8;
		     break;
	     case CDF_INT4:
		     sprintf(temp_val,"%ld",temp.i4);
		     bin_values[i] = (double) temp.i4;
		     break;
	     case CDF_UINT4:
		     sprintf(temp_val,"%lu",temp.ui4);
		     bin_values[i] = (double) temp.ui4;
		     break;
	     case CDF_INT2:
		     sprintf(temp_val,"%d",temp.i2);
		     bin_values[i] = (double) temp.i2;
		     break;
	     case CDF_UINT2:
		     sprintf(temp_val,"%u",temp.ui2);
		     bin_values[i] = (double) temp.ui2;
		     break;
	     case CDF_BYTE:
	     case CDF_INT1:
		     sprintf(temp_val,"%d",temp.byte);
		     bin_values[i] = (double) temp.byte;
		     break;
	     case CDF_UINT1:
		     sprintf(temp_val,"%u",temp.ubyte);
		     bin_values[i] = (double) temp.ubyte;
	     }
	temp_val[MINMAX_SIZE-1] = '\0';
	zero_replace(temp_val);
	strcpy(&char_values[i*MINMAX_SIZE], temp_val);
	}
     }
}
void CDFWALK_get_discrete_char(CDF_id, Z, dim_num, var_num, num_values,
		num_bytes, char_values)
CDFid                   CDF_id;
int                     Z;
long                    dim_num;
long                    var_num;
long                    num_values;
long                    num_bytes;
char                    *char_values;
{
char                    *temp;
long                    indices[10];
int                     i;
long                    record_num;
CDFstatus               rcode;
temp = (char *) malloc((size_t)(num_bytes+1));
record_num = 0;
for (i=0; i < 10; i++)
     indices[i] = 0;
for (i=0; i < num_values; i++)
     {
     indices[(int)(dim_num-1)] = i;
     rcode = CDFlib (SELECT_, CDF_, CDF_id,
			  BOO(Z,zVAR_,rVAR_), var_num,
			  BOO(Z,zVAR_RECNUMBER_,rVARs_RECNUMBER_),record_num,
			  BOO(Z,zVAR_DIMINDICES_,rVARs_DIMINDICES_),indices,
		 GET_,    BOO(Z,zVAR_DATA_,rVAR_DATA_), temp,
		 NULL_);
     temp[(int)num_bytes] = '\0';
     if(rcode == CDF_OK) strcpy(&char_values[(int)(i*(num_bytes+1))], temp);
     }
free (temp);
}
void CDFWALK_clear_row(vid, display, start_elem, end_elem, end_col)
WINDOWid                vid;
struct  vid_struct      display[];
int                     start_elem;
int                     end_elem;
int                     end_col;
{
int                     i;
int                     len;

int                     row, col;

for (i=start_elem; i<=end_elem; i++)
     {
     len = strlen(display[i-1].label);
     row = display[i-1].row;
     col = display[i-1].col + len;
     erase_display(vid, row, col, row, end_col);
     }
}
void CDFWALK_help(screen)
struct          GLOBAL_struct   *screen;
{
long                    dummy = 0;
struct vid_struct       *HELP_display;
long                    help_num_elements = 0;
int                     i;
long                    len;
int                     tcode;
AOSs1 (help_mes, "Press _____ key when done")
static char             help_error_mes[] = "Help not available ";
static char             help_error_mal[] = "Help not available, malloc error ";
char                    temp[80];
int                     help_rows, help_columns, paste_col;
int                     max_len;
EncodeKeyDefinitions(1, help_mes, HELPDONEkey_WALK);
if(HELP_ptr != NULL)
   {
/*
READ text until complete and load into a vid structure
*/
   max_len = 0;
   fseek(HELP_ptr, 0l, SEEK_SET);
   while (fgets(temp,80,HELP_ptr) != NULL)
	  {
	  help_num_elements++;
	  len = lastc(temp);
	  if(len > max_len) max_len = (int) len;
	  }
   if(help_num_elements > HELP_ROWS)
      help_rows = HELP_ROWS;
   else
      help_rows = (int) help_num_elements;

   if(max_len > HELP_COLUMNS)
      help_columns = HELP_COLUMNS;
   else
      help_columns = max_len;

   paste_col = (80-(help_columns+BORDER_COLUMNS))/2;

   create_virtual_display(help_rows+BORDER_ROWS,help_columns+BORDER_COLUMNS,
		 &S.HELP_vid, BORDER, NORMAL);

   HELP_display = (struct vid_struct *)
		  malloc((size_t) help_num_elements * sizeof(struct vid_struct));
   if(HELP_display == NULL)
      {
      CDFWALK_put_message(S.MES_vid, help_error_mal, RINGBELL, NORMAL,
		NOPAUSE);
      return;
      }
   fseek(HELP_ptr, 0l, SEEK_SET);
   i=0;
   for(i=0; i <help_num_elements; i++)
	{
	fgets(temp,80,HELP_ptr);
	HELP_display[i].row = 1;
	HELP_display[i].col = 1;
	len = lastc(temp) - 1;
	strncpy(HELP_display[i].label,temp,(size_t)len);
	HELP_display[i].label[(int)len] = '\0';
	}
/*
LOAD in the keypad definitions for this option
*/
	CDFWALK_help_keydef(screen);
	CDFWALK_put_message(S.MES_vid, help_mes[0], NOBELL, NORMAL, NOPAUSE);
/*
Display the HELP screen
*/
	CDFWALK_select_menu_item(S.HELP_vid, S.MES_vid,
	&dummy, HELP_display, (int) help_num_elements, help_rows, help_columns,
	HELP_ROW_PASTE, paste_col, HELP_MENU, &tcode);
	delete_virtual_display(S.HELP_vid);
	free(HELP_display);
   }
else
   CDFWALK_put_message(S.MES_vid, help_error_mes, RINGBELL, NORMAL, NOPAUSE);
}
int lastc(buf)
char    *buf;
{
int done = FALSE;
int i,j;
int end;
i = strlen(buf) + 1;
end = i;
j = 0;
while(j < end && !done)
      {
      if(!Visible(buf[i-1]))
	 done = TRUE;
      else
	 j++; i--;
      }
return(i);
}

void CDFWALK_field_menu(screen, CDF_id, option)
struct          GLOBAL_struct   *screen;
CDFid           CDF_id;
long            *option;
{
int             tcode, cont;
long            temp;
temp = *option+1;
cont = CONTINUEkey_WALK;
while(cont != DONE)
      {
/*
Choose the particular field you wish to be in
*/
      CDFWALK_Menu_keydef(screen);
      CDFWALK_select_menu_item(S.FIELD_vid, S.MES_vid, &temp,
      FIELD_display, FIELD_NUM_ELEMENTS, FIELD_ROWS, FIELD_COLUMNS,
      FIELD_ROW_PASTE, FIELD_COL_PASTE, MENU, &tcode);
      *option = temp-1;
      if(*option == HELP_FIELD)
	 CDFWALK_help(screen);
      else if(*option == SPECIAL_OPT_FIELD)
	      CDFWALK_special_options(screen, CDF_id);
      else
	 cont = DONE;
       }
}

void CDFWALK_open_screen(screen)
struct  GLOBAL_struct   *screen;
{
create_pasteboard();
DisplayRIP ();
begin_pasteboard_update();
create_virtual_display(CDF_ROWS+BORDER_ROWS, CDF_COLUMNS+BORDER_COLUMNS, 
	&S.CDF_vid, BORDER, NORMAL);
paste_virtual_display(S.CDF_vid, CDF_ROW_PASTE, CDF_COL_PASTE);
load_vid(S.CDF_vid, CDF_display, 0, CDF_NUM_ELEMENTS-1, NO_label);
create_virtual_display(VAR_ROWS+BORDER_ROWS, VAR_COLUMNS+BORDER_COLUMNS, 
			&S.VAR_vid, BORDER, NORMAL);
paste_virtual_display(S.VAR_vid, VAR_ROW_PASTE, VAR_COL_PASTE);
create_virtual_display(KEY_ROWS+BORDER_ROWS, KEY_COLUMNS+BORDER_COLUMNS, 
			&S.KEY_vid, BORDER, NORMAL);
paste_virtual_display(S.KEY_vid, KEY_ROW_PASTE, MES_COL_PASTE);
create_virtual_display(MES_ROWS+BORDER_ROWS, MES_COLUMNS+BORDER_COLUMNS, 
				&S.MES_vid, BORDER, NORMAL);
paste_virtual_display(S.MES_vid, MES_ROW_PASTE, MES_COL_PASTE);
create_virtual_display(VARSCROLL_ROWS+BORDER_ROWS, 
		       VARSCROLL_COLUMNS+BORDER_COLUMNS, &S.VARSCROLL_vid,
			BORDER, NORMAL);
create_virtual_display(FIELD_ROWS+BORDER_ROWS, FIELD_COLUMNS+BORDER_COLUMNS, 
			&S.FIELD_vid, BORDER, NORMAL);
create_virtual_display(DIS_ROWS+BORDER_ROWS, DIS_COLUMNS+BORDER_COLUMNS, 
				&S.DIS_vid, BORDER, NORMAL);
create_virtual_display(DIM_ROWS+BORDER_ROWS, DIM_COLUMNS+BORDER_COLUMNS, 
			&S.DIM_vid, BORDER, NORMAL);
create_virtual_display(DIR_ROWS+BORDER_ROWS, DIR_COLUMNS+BORDER_COLUMNS, 
			&S.DIR_vid, BORDER, NORMAL);
create_virtual_display(SPECIAL_ROWS+BORDER_ROWS,SPECIAL_COLUMNS+BORDER_COLUMNS, 
			&S.SPECIAL_vid, BORDER, NORMAL);
create_virtual_display(VARFORMAT_ROWS+BORDER_ROWS, 
		       VARFORMAT_COLUMNS+BORDER_COLUMNS,
			&S.VARFORMAT_vid, BORDER, NORMAL);
create_virtual_display(ZERO_ROWS+BORDER_ROWS, 
		       ZERO_COLUMNS+BORDER_COLUMNS,
			&S.ZERO_vid, BORDER, NORMAL);
end_pasteboard_update();
/*enable_trap(S.MES_vid);*/
load_vid(S.KEY_vid, KEY_display, 0, KEY_NUM_ELEMENTS, KEY_label);
load_vid(S.MES_vid, MES_display, 0, MES_NUM_ELEMENTS, MES_label);
}
void CDFWALK_special_options(screen, CDF_id)
struct  GLOBAL_struct   *screen;
CDFid                   CDF_id;
{
int     tcode;
int     field_num;
int     save;
static char star[]  = "*";
static char noformat_mes[] =
"This CDF does not a contain the attribute FORMAT, switching back to default";
AOSs1 (VARFORM_mes,
"USE CDF FORMAT attribute to display data, ___ to leave Special Option Window")
AOSs1A (ZERO_mes,
"CONVERT -0.0 to +0.0 or IGNORE -0.0, ___ to quit")
EncodeKeyDefinitions(1, VARFORM_mes, QUITkey_WALK);
EncodeKeyDefinitions(1, ZERO_mes, QUITkey_WALK);

begin_pasteboard_update();
paste_virtual_display(S.SPECIAL_vid, SPECIAL_ROW_PASTE, SPECIAL_COL_PASTE);
label_border(S.SPECIAL_vid, SPECIAL_label, REVERSE);

paste_virtual_display(S.VARFORMAT_vid, VARFORMAT_ROW_PASTE,
			VARFORMAT_COL_PASTE);
load_vid(S.VARFORMAT_vid, VARFORMAT_display, 0,
	VARFORMAT_NUM_ELEMENTS, VARFORMAT_label);

paste_virtual_display(S.ZERO_vid, ZERO_ROW_PASTE,
			ZERO_COL_PASTE);
load_vid(S.ZERO_vid, ZERO_display, 0,
	ZERO_NUM_ELEMENTS, ZERO_label);

end_pasteboard_update();

put_chars(S.VARFORMAT_vid, star, 1, SO.variable_format, 2, NOERASE, NORMAL);
put_chars(S.ZERO_vid, star, 1, SO.zero, 2, NOERASE, NORMAL);
CDFWALK_special_keydef(screen);
tcode = NORMAL;
field_num = VARFORMAT_FIELD;
while(tcode != QUITkey_WALK)
  {
  switch(field_num)
	 {
	 case VARFORMAT_FIELD:
	      CDFWALK_put_message(S.MES_vid, VARFORM_mes[0], NOBELL, NORMAL,
					NOPAUSE);
	      tcode = CDFWALK_special_option_menu(S.VARFORMAT_vid,
			&SO.variable_format, VARFORMAT_NUM_ELEMENTS);
	      if(!SO.format && SO.variable_format == FORMAT)
		 {
		 SO.variable_format = NOFORMAT;
		 CDFWALK_put_message(S.MES_vid, noformat_mes, RINGBELL, NORMAL,
					PAUSE);
		 CDFWALK_disp_opt(S.VARFORMAT_vid, SO.variable_format,
				VARFORMAT_NUM_ELEMENTS);
		 }
	      break;
	 case ZERO_FIELD:
	      CDFWALK_put_message(S.MES_vid, ZERO_mes[0], NOBELL, NORMAL,
					NOPAUSE);
	      save = SO.zero;
	      tcode = CDFWALK_special_option_menu(S.ZERO_vid,
			&SO.zero, ZERO_NUM_ELEMENTS);
	      if(SO.zero != save)NEG_to_POS(CDF_id);
	 }
	 field_num++;
	 if(field_num > ZERO_FIELD)
	    field_num = VARFORMAT_FIELD;
	 else if(field_num < VARFORMAT_FIELD)
		 field_num = ZERO_FIELD;
   }

begin_pasteboard_update();
unpaste_virtual_display(S.VARFORMAT_vid);
unpaste_virtual_display(S.ZERO_vid);
unpaste_virtual_display(S.SPECIAL_vid);

CDFWALK_clear_row(S.MES_vid, MES_display, 1, 1, MES_COLUMNS);

end_pasteboard_update();


}
int CDFWALK_special_option_menu(vid, value, num_rows)
WINDOWid        vid;
int             *value;
int             num_rows;
{
int             done;
int             row,col;
int             tcode;

done = FALSE;
row = *value;
col = 2;
while(!done)
  {
  set_cursor_abs(vid, row, col);
  read_input(
#if defined(CURSESui)
	     vid,
#endif
		 &tcode, PASSTHRUri, TRUE);
  switch(tcode)
	 {
	 case QUITkey_WALK:
	 case ACTIONkey_WALK:
	      tcode = QUITkey_WALK;
	      done = TRUE;
	      break;
	 case SELECTkey_WALK:
	      done = TRUE;
	      break;
	 case PREVITEMkey_WALK:
	      row--;
	      if(row < 1)row = num_rows;
	      break;
	 case NEXTITEMkey_WALK:
	      row++;
	      if(row > num_rows)row = 1;
	      break;
	 case REFRESHkey_FSI:
	      repaint_screen();
	      break;
	  }
  CDFWALK_disp_opt(vid, row, num_rows);
  }

*value = row;
return(tcode);
}
void CDFWALK_disp_opt(vid, row, num_rows)
WINDOWid        vid;
int             row;
int             num_rows;
{
int             i;
static char star[]  = "*";
static char blank[] = " ";

for(i=1; i<=num_rows;i++)
      {
      if(i == row)
	 put_chars(vid, star, 1, i, 2, NOERASE, NORMAL);
      else
	 put_chars(vid, blank, 1, i, 2, NOERASE, NORMAL);
      }
}

void CDFWALK_select_menu_item(vid, MES_vid, rvalue, display,
num_elements, num_rows, num_columns, row_start, col_start, mode, termcode)
WINDOWid        vid;
WINDOWid        MES_vid;
long             *rvalue;
struct          vid_struct      display[];
int             num_elements;
int             num_rows;
int             num_columns;
int             row_start;
int             col_start;
int             mode;
int             *termcode;
{
int             in_value;
int             row, col;
int             tcode;
int             done;
int             num_screen;
int             start_page;
int             end;
int             value;
int             row1 = 1;
int             col1 = 1;
static char     top[]    = "Top of menu";
static char     bottom[] = "Bottom of menu";

in_value = (int) *rvalue;
/*
Find out the number of rows to be on the screen at one time
*/
if(num_elements > num_rows)
   num_screen = num_rows;
else
   num_screen = num_elements;
/*
Erase and load data into the menu for selection
*/
value = 1;
row = 1;
col = 1;
begin_pasteboard_update();
erase_display(vid, 1, 1, num_rows, num_columns);
load_menu(vid, display, num_screen, NO_label);
change_rendition(vid,1,1,num_rows,num_columns,NORMAL);
paste_virtual_display(vid, row_start, col_start);
end_pasteboard_update();
start_page = 1;
if(mode == MENU)change_rendition(vid, row, col, 1, num_columns, REVERSE);
done = FALSE;
while(!done)
     {
     set_cursor_abs(vid, row, col);
     read_input(
#if defined(CURSESui)
		vid,
#endif
		    &tcode, PASSTHRUri, TRUE);
     switch (tcode)
	  {
	  case NEXTITEMkey_WALK:
	       if(row == num_rows || value == num_elements)
		  if(value < num_elements)
		     {
/*
SCROLL UP
*/
		     value++; start_page++;
		     begin_pasteboard_update();
		     erase_display(vid, row1, col1, num_rows, num_columns);
		     load_menu(vid, display+(start_page-1),
		     num_screen, NO_label);
		     end_pasteboard_update();
		     }
		  else
		     {
		     value = 1;
		     row = 1;
		     start_page = 1;
		     begin_pasteboard_update();
		     erase_display(vid, 1, 1, num_rows, num_columns);
		     load_menu(vid, display, num_screen, NO_label);
		     end_pasteboard_update();
		     }
	       else
		  {
		  row++; value++;
		  if(row == num_rows && value == num_elements)
		     CDFWALK_put_message(MES_vid, bottom, NOBELL, 
					NORMAL, NOPAUSE);
		  }
	       break;
	  case PREVITEMkey_WALK:
	       if(row > 1)
		  {
		     row--;
		     value--;
		  }
	       else if(value > 1)
		  {
/*
SCROLL DOWN
*/
		     value--; start_page--;
		     begin_pasteboard_update();
		     erase_display(vid, row1, col1, num_rows, num_columns);
		     load_menu(vid, display+(start_page-1),
		     num_screen, NO_label);
		     end_pasteboard_update();
		  }
	       else
		  {
		     start_page = num_elements - num_screen + 1;
		     value = num_elements;
		     row = num_screen;
		     begin_pasteboard_update();
		     erase_display(vid, row1, col1, num_rows, num_columns);
		     load_menu(vid, display+(start_page-1),
		     num_screen, NO_label);
		     end_pasteboard_update();
		  }
	       break;
/*
PAGE DOWN
*/
	  case PAGEDOWNkey_WALK:
	       start_page = start_page + num_screen;
	       end = start_page + num_screen - 1;
	       value = value + num_screen;
	       if(end > num_elements)
		  {
/*
Display the next page down
*/
		  end = num_elements;
		  start_page = end - num_screen + 1;
		  value = num_elements;
		  row = num_rows;
		  CDFWALK_put_message(MES_vid, bottom, NOBELL, NORMAL, NOPAUSE);
		  }
	       begin_pasteboard_update();
	       erase_display(vid, row1, col1, num_rows, num_columns);
	       load_menu(vid, display+(start_page-1), num_screen, NO_label);
	       end_pasteboard_update();
	       break;
/*
PAGE UP
*/
	  case PAGEUPkey_WALK:
	       start_page = start_page - num_screen;
	       value = value - num_screen;
	       if(start_page < 1)
		  {
		  start_page = 1;
		  value = 1;
		  row = 1;
		  CDFWALK_put_message(MES_vid, top, NOBELL, NORMAL, NOPAUSE);
		  }
	       begin_pasteboard_update();
/*
Display the next page up
*/
	       erase_display(vid, row1, col1, num_rows, num_columns);
	       load_menu(vid, display+(start_page-1), num_screen, NO_label);
	       end_pasteboard_update();
	       break;
	  case SELECTkey_WALK:
	       done = TRUE;
	       *rvalue = value;
	       *termcode = SELECTkey_WALK;
	       break;
	  case QUITkey_WALK:
	       done = TRUE;
	       *rvalue = in_value;
	       *termcode = QUITkey_WALK;
	       break;
	  case ACTIONkey_WALK:
	       done = TRUE;
	       *rvalue = value;
	       *termcode = ACTIONkey_WALK;
	       break;
	  case REFRESHkey_FSI:
	       repaint_screen();
	       break;
	  default:
		break;
	  }
	  if(mode == MENU)
	     {
	     change_rendition(vid, 1, 1, num_rows, num_columns, NORMAL);
	     change_rendition(vid, row, 1, 1, num_columns, REVERSE);
	     }
      }
unpaste_virtual_display(vid);
}
int CDFWALK_CDF_name(screen, CDF, field_num, input_type)
struct  GLOBAL_struct   *screen;
struct  CDF_struct      *CDF;
long                    *field_num;
long                    *input_type;
{
char                    file_spec[256],temp[256] /*, dummy[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_WALK;
int                     drows;
int                     i, row;
long                    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_WALK, ACTIONkey_WALK, NUL };
EncodeKeyDefinitions(1, select_mes, QUITkey_WALK);
strcpy(save_name, C.CDF_name);
new_CDF= FALSE;
done = FALSE;
regfile = FALSE;
while(!done)
{
if(*input_type == MANUAL)
   {
   if(firstForCDFname)
      {
      CDFWALK_CDFname_keydef(screen);
      if(!last_error)
	 {
	 if(!SO.spec_entered)strcpy(C.CDF_name, default_name);
	 CDFWALK_put_selection(S.CDF_vid, CDF_display, 0,
	      C.CDF_name, CDF_NAME_LENGTH, REVERSE);
	 }
      CDFWALK_put_message(S.MES_vid, dir_mes, NOBELL, NORMAL, NOPAUSE);
      input_field(S.CDF_vid, C.CDF_name, CDF_NAME_ROW, CDF_NAME_COL,
	CDF_NAME_LENGTH, exit_keys, &termcode, INSERTTOGGLEkey_WALK, 
	MOVEtoBEGINkey_WALK, MOVEtoENDkey_WALK, NOTTHERE, DELETEtoENDkey_WALK,
		  REFRESHkey_FSI);
      }
   else
      CDFWALK_put_selection(S.CDF_vid, CDF_display, 0,
	      save, CDF_NAME_LENGTH, REVERSE);
   }
else
    termcode = SELECTkey_WALK;
*input_type = MANUAL;
firstForCDFname = FALSE;
last_error = FALSE;
CDFWALK_clear_row(S.MES_vid, MES_display, 1, 1, MES_COLUMNS);
if(termcode == ACTIONkey_WALK)
   {
   CDFWALK_field_menu(screen, C.CDF_id, field_num);
   if((int) (*field_num) != CDF_FIELD)
      {
      done = TRUE;
      tcode = QUITkey_WALK;
      }
   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)
	 {
	 CDF_num = 1;
	 tcode = SELECTkey_WALK;
	 firstForCDFname = TRUE;
	 }
       else
	 {
/*
allocate the space for a vid structure which contains the CDF NAMES
*/
	 DIR_display = (struct vid_struct *)
	       malloc(num_files * sizeof(struct vid_struct));
	 if(DIR_display == NULL) return ((int) BAD_MALLOC);
/*
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;
	   strcpy(DIR_display[i].label, result_spec_list[i]);
	   }
	 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);
	 CDFWALK_put_message(S.MES_vid, select_mes[0], NOBELL, NORMAL, NOPAUSE);
	 CDFWALK_Menu_keydef(screen);
	 CDFWALK_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_WALK)
	      {
	      if(dir || strlen(directory_list[(int)(CDF_num-1)]) > (size_t) 0)
		 {
		 strcpy(C.CDF_name, directory_list[(int)(CDF_num-1)]);
		 AppendToDir(C.CDF_name, result_spec_list[(int)(CDF_num-1)]);
		 }
	      else
		 strcpy(C.CDF_name, result_spec_list[(int)(CDF_num-1)]);

	      C.CDF_name[CDF_NAME_LENGTH]= '\0';
	      CDFWALK_put_selection(S.CDF_vid, CDF_display, 0,
	      C.CDF_name, CDF_NAME_LENGTH, REVERSE);
	      new_CDF = TRUE;
	      *field_num = WALK_FIELD;
	      }
	   else
	      {
	      change_rendition(S.CDF_vid, CDF_NAME_ROW, CDF_NAME_COL, 1,
		  strlen(C.CDF_name), REVERSE);
	      if(tcode == ACTIONkey_WALK)
		 {
		 CDFWALK_field_menu(screen, C.CDF_id, 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
	   {
	   CDFWALK_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);
   CDFWALK_put_selection(S.CDF_vid, CDF_display, 0,
	      C.CDF_name, CDF_NAME_LENGTH, REVERSE);
   }
SO.spec_entered = FALSE;
return(tcode);

}
void CDFWALK_CDF_info(screen, CDF, CDF_display)
struct  GLOBAL_struct   *screen;
struct  CDF_struct      *CDF;
struct  vid_struct      CDF_display[];
{
char            string[21];
char            temp[7];
int             i;
sprintf(string, "%ld ", C.num_vars[SO.curr_CDF]);
CDFWALK_clear_row(S.CDF_vid, CDF_display, NUMVAR_ELEMENT_NUM,
			NUMVAR_ELEMENT_NUM, 27);
CDFWALK_put_selection(S.CDF_vid, CDF_display, NUMVAR_ELEMENT_NUM-1, string,
	6, REVERSE);
sprintf(string, "%ld ", C.max_record_num[SO.curr_CDF]+1);
CDFWALK_clear_row(S.CDF_vid, CDF_display, NUMREC_ELEMENT_NUM,
			NUMREC_ELEMENT_NUM, CDF_COLUMNS);
CDFWALK_put_selection(S.CDF_vid, CDF_display, NUMREC_ELEMENT_NUM-1, string,
	6, REVERSE);
sprintf(string, "%ld ", C.num_dims[SO.curr_CDF]);
CDFWALK_clear_row(S.CDF_vid, CDF_display, NUMDIM_ELEMENT_NUM,
			NUMDIM_ELEMENT_NUM, CDF_COLUMNS);
CDFWALK_put_selection(S.CDF_vid, CDF_display, NUMDIM_ELEMENT_NUM-1, string,
	2, REVERSE);
string[0] = '\0';
CDFWALK_clear_row(S.CDF_vid, CDF_display, DIMSIZ_ELEMENT_NUM,
			DIMSIZ_ELEMENT_NUM, CDF_COLUMNS);
if(C.num_dims[SO.curr_CDF] > 0)
   {
   for (i=0; i < C.num_dims[SO.curr_CDF]; i++)
	{
	sprintf(temp, "%ld ", C.dim_sizes[SO.curr_CDF][i]);
	strcat(string, temp);
	}
   }
else
    string[0] = '\0';
CDFWALK_put_selection(S.CDF_vid, CDF_display, DIMSIZ_ELEMENT_NUM-1, string,
	10, REVERSE);
}
void load_vid(vid, display, start_element, num_elements, label)
WINDOWid                vid;
struct  vid_struct      display[];
int                     start_element;
int                     num_elements;
char                    label[];
{
int                     i;
int                     len;

int             erase_mode = NOERASE;
int             video_type = NORMAL;
len = strlen(label);
if(len > 0)label_border(vid, label, REVERSE);
for(i=0; i< num_elements; i++)
    {
    len = strlen(display[i+start_element].label);
    put_chars(vid, display[i+start_element].label, len,
    display[i+start_element].row, display[i+start_element].col,
	erase_mode, video_type);
    }
}
void load_vid_element(vid, display, element_num)
WINDOWid                vid;
struct  vid_struct      display[];
int                     element_num;
{

int                     len;

int                    erase_mode = NOERASE;
int                    video_type = NORMAL;

len = strlen(display[element_num-1].label);
put_chars(vid, display[element_num-1].label, len,
display[element_num-1].row, display[element_num-1].col, erase_mode, video_type);
}
void CDFWALK_load_keydef(vid, line1, line2)
WINDOWid                vid;
char                    line1[];
char                    line2[];
{
int                     row, col;
int                     erase_mode;
int                     video_type;
int                     len;

begin_pasteboard_update();
erase_display(vid, 1, 1, KEY_ROWS, KEY_COLUMNS);
row = 1; col = 1; erase_mode = ERASE; video_type = NORMAL;
len = strlen(line1);
if(len > KEY_COLUMNS)len = KEY_COLUMNS;
put_chars(vid, line1, len, row, col, erase_mode, video_type);
len = strlen(line2);
row = 2; col = 1; erase_mode = ERASE; video_type = NORMAL;
if(len > KEY_COLUMNS)len = KEY_COLUMNS;
put_chars(vid, line2, len, row, col, erase_mode, video_type);
end_pasteboard_update();
}
void CDFWALK_put_selection(vid, display, element_num, selection,
				field_len, video_type)
WINDOWid                vid;
struct  vid_struct      display[];
int                     element_num;
char                    selection[];
int                     field_len;
int                     video_type;
{
/*long                  i;*/
int                     len;

int                     erase_mode = NOERASE;
int                     row, col, end_col;

len = strlen(display[element_num].label);
row = display[element_num].row;
col = display[element_num].col + len;
len = strlen(selection);
end_col = col + field_len - 1;
erase_display(vid, row, col, row, end_col);
put_chars(vid, selection, len, row, col, erase_mode, video_type);
}
void CDFWALK_put_value(vid, display, element_num, bin_value)
WINDOWid                vid;
struct  vid_struct      display[];
int                     element_num;
double                  bin_value;
{
char                    value[20];
int                    i;
int                     len;

int                     erase_mode = NOERASE;
int                     video_type = NORMAL;
int                     row, col, end_col;

len = strlen(display[element_num].label);
row = display[element_num].row;
col = display[element_num].col;
end_col = col + 20;
erase_display(vid, row, col, row, end_col);
sprintf(value,"%f",bin_value);
zero_replace(value);
len = strlen(value);
for(i = len; i<14; i++)
    value[i] = ' ';
value[14] = '\0';
len = 14;
put_chars(vid, value, len, row, col, erase_mode, video_type);
}
void CDFWALK_put_message(vid, message, rbell, video_type, pause)
WINDOWid                vid;
char                    message[];
int                     rbell;
int                     video_type;
int                     pause;
{
/*long                  i;*/
int                     len;

int                     erase_mode = ERASE;
int                     row, col;
#if defined(vms)
float                   wait = 3.;
#endif

len = strlen(message);
row = 1;
col = 1;
if(rbell == RINGBELL)
    ring_bell();
if(len > MES_COLUMNS)len = MES_COLUMNS;
put_chars(vid, message, len, row, col, erase_mode, video_type);
if(pause == PAUSE)
#if 0
#if defined(vms)
		     lib$wait(&wait);
#endif
#if defined(unix) || defined(dos)
		     sleep(3);
#endif
#else
		   zzzzz (3.0);
#endif
}
void load_menu(vid, display, num_elements, label)
WINDOWid                vid;
struct  vid_struct      display[];
int                     num_elements;
char                    label[];
{
int                     i;
int                     len;

int                     erase_mode = NOERASE;
int                     video_type = NORMAL;
int                     row;
int                     col = 1;
len = strlen(label);
if(len > 0)label_border(vid, label, REVERSE);
for(i=0; i< num_elements; i++)
    {
    row = i + 1;
    len = strlen(display[i].label);
    put_chars(vid, display[i].label, len, row, col,
    erase_mode, video_type);
    }
}
void zero_replace(string)
char            string[];
{
long            zero_index;
int             byte /*, ebyte*/ ;
long            found = FALSE;
long            len;

CDFWALK_left_justify(string);
byte = 0;
len = strlen(string);
while(byte < len && !found)
      {
      if(string[byte] == PERIOD)found = TRUE;
      byte++;
      }
if(found)
   {
   zero_index = byte;
   while(byte < len)
      {
      if(string[byte] == '0')
	  {
	  if(zero_index == 0)zero_index = byte;
	  }
      else
	 zero_index = 0;
      byte++;
      }
   if(zero_index > 0)
     {
     for (byte=(int)zero_index; byte<len; byte++)
	  string[byte] = ' ';
     }
   }
}
void CDFWALK_left_justify (field)
	char            field[];
{
	int             i;
	int             index;
	long            done;
	char            *temp;
	long            len;
	len = strlen(field);
	temp = (char *) malloc((size_t)len);

/* Blank out temporary hold area */

	for (i = 0; i < len; i++)
		temp[i] = ' ';


		done = FALSE;
		for (index = 0; done != TRUE && index <= len; index++)

			{
/* Look for a non-blank character */

			if(field[index] != ' ')
				{
/* Left Justify by copying from the non-blank character to the end of field */

				strncpy(temp,field+index,(size_t)(len-index));
				for (i = 0; i < len; i++)
					field[i] = ' ';

/* Now copy from the temporary field back to the permanent field */

				strncpy(field, temp, (size_t) len);
				done = TRUE;
				}
			}
free(temp);
}
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);
}
void CDFWALK_free_discrete(variables, num_vars)
struct variable_struct  *variables;
long                    num_vars;
{
long                    var_num;

for(var_num = 0; var_num < num_vars; var_num++)
    {
    if(V.bin_value != NULL)
       {
       free(V.bin_value);
       V.bin_value = NULL;
       }
    if(V.char_value != NULL)
       {
       free(V.char_value);
       V.char_value = NULL;
       }
    }
}
CDFstatus CDFWALK_close(CDF, vars)
struct  CDF_struct      *CDF;
struct variable_struct  **vars;
{
int                     i,k;
int                     var_num;
CDFstatus               rcode;

for(k=0; k<C.num_ZCDF; k++)
    {
    for(var_num = 0; var_num < C.num_vars[k]; var_num++)
	{
	if(vars[k][var_num].format_value != NULL)
	   {
	   free(vars[k][var_num].format_value);
	   vars[k][var_num].format_value = NULL;
	   }
	}
    if(C.num_vars[k] > 0)free(vars[k]);
    }
free(vars);

if(C.num_dims != NULL)
   {
   free(C.num_dims);
   C.num_dims = NULL;
   }
for(i=0; i<C.numZvars+1; i++)
    free(C.dim_sizes[i]);
if(C.dim_sizes != NULL)
   {
   free(C.dim_sizes);
   C.dim_sizes = NULL;
   }
if(C.num_vars != NULL)
   {
   free(C.num_vars);
   C.num_vars = NULL;
   }
if(C.max_record_num != NULL)
   {
   free(C.max_record_num);
   C.max_record_num = NULL;
   }

rcode = CDFlib(SELECT_, CDF_, C.CDF_id,
		CLOSE_, CDF_,
		NULL_);
return(rcode);
}
void CDFWALK_close_screen()
{
delete_pasteboard(ERASE);
}
double r4_r8(r4_ptr)
float   *r4_ptr;
{
/*
Convert float to double
Based on assumption that float contains 7 significant digits
*/
float r4;
double          r4r8;
double          fracr8;
float           realexp,temp,rfrac,x;
double          base, power;
long            exp,frac;
long            evalue;

r4 = *r4_ptr;
/*
If the REAL*4 value is 0 then just set the REAL*8 value to 0 and return
*/
if(r4 == 0.) return(0.);

temp = r4;
evalue  = 0;
/*
Calculate the exponent of the incoming REAL*4 value
If absolute value ge 10 exponent is positive
If absolute value lt 1  exponent is negative
*/
if(fabs(temp) >= 10.)
	{
	while(fabs(temp) >= 10.)
	      {
	      evalue = evalue + 1;
	      temp = temp / 10.;
	      }
	}
else if(fabs(temp) < 1.)
	{
	while(fabs(temp) < 1.)
	      {
	      evalue = evalue - 1;
	      temp = temp * 10.;
	      }
	}
/*
Extract out the fractional portion of the real value
*/
exp = (long    ) r4;
realexp =  (float) exp;
rfrac = r4-realexp;
/*
Convert significant digits of fraction portion to integer by multiplying.
*/
base = 10.;
power = (double) (6-evalue);
x = rfrac*pow(base,power);
if(x > 0.)
   frac = (long    ) (x + .5);
else
   frac = (long    ) (x - .5);
fracr8 = (double) frac;
r4r8 = (double) exp;
/*
Convert the integer back into a fraction by diving.
then ADD back in the integer portion.
*/
r4r8 = r4r8 + fracr8/(pow(base, power));
return(r4r8);
}
long     CDFWALK_get_index(CDF_id, Z, dim_num, var_num, value, data_type,
				dim_values, num_values)
CDFid                   CDF_id;
long                    Z;
long                    dim_num;
long                    var_num;
long                    data_type;
double                  value;
double                  dim_values[];
long                    num_values;
{
int                     i;
double                  diff,closest_diff;
long                    closest_indice;
double                  min,max,fudge_up,fudge_down;
long                    indices[10];
long                    record_num;
CDFstatus               rcode;
double                  test_value;
union   mixed           temp;


if(data_type != CDF_REAL8 && data_type != CDF_EPOCH)
   {
   fudge_down = .999999; fudge_up = 1.000001;
   if(value > 0.)
      {
      min = fudge_down*value;
      max = fudge_up*value;
      }
   else
      {
      min = fudge_up*value;
      max = fudge_down*value;
      }
   }
else
   {
   min = value;
   max = value;
   }
if(num_values > MAX_VALUES)
   {
   record_num = 0;
   for (i=0; i < CDF_MAX_DIMS; i++)
     indices[i] = 0;
   }
closest_diff = 1.7e38;
closest_indice = 0;
for(i=0; i<num_values; i++)
    {
    if(num_values > MAX_VALUES)
       {
       if(dim_num > 0)
	  indices[(int)(dim_num-1)]=i;
       else
	  record_num = i;
       rcode = CDFlib (SELECT_, CDF_, CDF_id,
			  BOO(Z,zVAR_,rVAR_), var_num,
			  BOO(Z,zVAR_RECNUMBER_,rVARs_RECNUMBER_),record_num,
			  BOO(Z,zVAR_DIMINDICES_,rVARs_DIMINDICES_),indices,
		   GET_,  BOO(Z,zVAR_DATA_,rVAR_DATA_), &temp,
		   NULL_);
       if(rcode >= CDF_OK)
	  {
	  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;
	      }
	  }
	  if(rcode < CDF_OK)test_value = 1.7e38;
       }
    else
	test_value = dim_values[i];
    if(test_value >= min && test_value <= max)return(i);
    diff = fabs(test_value - value);
    if(diff < closest_diff)
       {
       closest_diff = diff;
       closest_indice = i;
       }
    }
return(closest_indice);
}
long     CDFWALK_get_index_char(CDF_id, Z, dim_num, var_num, value,
				num_bytes, dim_values, num_values)
CDFid                   CDF_id;
long                    Z;
long                    dim_num;
long                    var_num;
char                    *value;
long                    num_bytes;
char                    dim_values[];
long                    num_values;
{
int                     i;
long                    closest_indice;
long                    most;
long                    num;
long                    indices[CDF_MAX_DIMS];
long                    record_num;
CDFstatus               rcode;
char                    *string;

closest_indice = 0;
most = 0;

string = (char *) malloc ((size_t) (num_bytes+1));
if(string == NULL)return(closest_indice);
if(num_values > MAX_VALUES)
   {
   record_num = 0;
   for (i=0; i < CDF_MAX_DIMS; i++)
     indices[i] = 0;
   }


for(i=0; i<num_values; i++)
    {
    if(num_values > MAX_VALUES)
       {
       if(dim_num > 0)
	  indices[(int)(dim_num-1)]=i;
       else
	  record_num = i;
       rcode = CDFlib (SELECT_, CDF_, CDF_id,
			  BOO(Z,zVAR_,rVAR_), var_num,
			  BOO(Z,zVAR_RECNUMBER_,rVARs_RECNUMBER_),record_num,
			  BOO(Z,zVAR_DIMINDICES_,rVARs_DIMINDICES_),indices,
		   GET_,  BOO(Z,zVAR_DATA_,rVAR_DATA_), string,
		   NULL_);
       if(rcode < CDF_OK)
	  string[0] = '\0';
       else
	  string[(int)num_bytes] = '\0';
       }
    else
       {
       strncpy (string, &dim_values[(int)(i*(num_bytes+1))], (size_t)num_bytes);
       string[(int)num_bytes] = '\0';
       } 
    num = how_many_match(value, string);
    if(num > most)
       {
       closest_indice = i;
       most = num;
       }
    }
free(string);
return(closest_indice);
}
void make_it_upper(upstring,string)
char    *upstring;
char    *string;
{
int     i,len;
len=strlen(string);
for(i=0; i<len; i++)
    {
    upstring[i] = MakeUpper(string[i]);
    }
upstring[len] = '\0';
}
long     how_many_match(str1, str2)
char            *str1;
char            *str2;
{
char            *up1, *up2;
long            num;
int             i;
up1 = (char *) malloc(strlen(str1) + 1);
up2 = (char *) malloc(strlen(str2) + 1);
make_it_upper(up1, str1);
make_it_upper(up2, str2);
for(i=0, num=0; up1[i] != '\0' && up1[i] == up2[i]; i++)
    num++;
free(up1);
free(up2);
return(num);
}
double          check_epoch(str)
char            str[];
{
static char     default_time[] = " 00:00:00.000";
long            len;
double          scale;
scale = 0.;
len = strlen(str);
if(len == 0)
   return(0.);
else if(len < 11)
	return(-1.0);
else if(len < 24)
	strcat(str, default_time + (int) (len+2-13));
scale = parseEPOCH(str);
return(scale);
}

void NEG_to_POS(CDF_id)
CDFid   CDF_id;
{
CDFstatus rcode;
long convert0;
convert0 = SO.zero == CONVERT ? NEGtoPOSfp0on : NEGtoPOSfp0off; 
rcode = CDFlib (SELECT_, CDF_, CDF_id,
			 CDF_NEGtoPOSfp0_MODE_, convert0, 
		 NULL_);
if(rcode != CDF_OK)rcode = CDF_OK; /* Don't want this to be a killer */
return;
}
