/******************************************************************************
*
*  NSSDC/CDF                    CDFdump - dump all records found in .CDF file.
*
*  Version 2.5b, 28-Sep-95, Hughes STX.
*
*  Modification history:
*
*   V1.0  29-May-91, J Love     Original version.
*   V1.1  25-Jun-91, J Love     Moved increment.  Display fill value.  Display
*                               extend records.  CDF_EPOCH added as a data
*                               type.  Added QOP.  Added PageInst.
*   V1.2  26-Jul-91, J Love     Added SEEK_CUR.  Added XDR decoding.
*                               Use 'Exit'/'ExitBAD'.
*   V1.3   7-Oct-91, J Love     Modified for IBM-PC port (and IBM-RS6000).
*   V2.0  21-Apr-92, J Love     IBM PC port/CDF V2.2.
*   V2.1  29-Sep-92, J Love     CDF V2.3 (shareable/NeXT/zVar).
*   V2.2  22-Oct-92, J Love     Newline after pad values.
*   V2.3  24-Jan-94, J Love     CDF V2.4.
*   V2.3a  8-Feb-94, J Love	DEC Alpha/OpenVMS port.
*   V2.4  21-Dec-94, J Love	CDF V2.5.
*   V2.4a 13-Jan-95, J Love	Uppercase file extensions.
*   V2.4b 26-Jan-95, J Love	Display meaning of `flags'.
*   V2.4c 22-Mar-95, J Love	Check for all NULs following copyright.
*   V2.4d  6-Apr-95, J Love	POSIX.
*   V2.5  25-May-95, J Love	EPOCH styles.  Fixed `all NULs' message.
*   V2.5a 19-Sep-95, J Love	CHECKforABORTso.
*   V2.5b 28-Sep-95, J Love	Macintosh dialog filtering.  Outline default
*				button.
*
******************************************************************************/

#include "cdfdump.h"

/******************************************************************************
* Increased stack size for Borland C on IBM PC.
******************************************************************************/

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

/******************************************************************************
* Global variables & macro constants.
******************************************************************************/

long usedBytes;
long wastedBytes;
long GDRcount;
long CDRcount;
long ADRcount;
long AgrEDRcount;
long AzEDRcount;
long rVDRcount;
long zVDRcount;
long VXRcount;
long VVRcount;
long UIRcount;
FILE *OUTfp;
Logical checkSizes;
long level;
long startingOffset;

#define BRIEF_          1L
#define FULL_           2L

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

MAIN {
#if defined(mac)
  strcpyX (pgmName, "CDFdump", MAX_PROGRAM_NAME_LEN);
  MacExecuteSO (DumpCDF, DumpQOPs);
  if (FreeMemory(NULL,FatalError) > 0) DisplayWarning ("Abandoned buffers.");
  return EXIT_SUCCESS_;
#else
  Logical success;
  strcpyX (pgmName, "CDFdump", MAX_PROGRAM_NAME_LEN);
  success = DumpCDF (argc, argv);
  if (FreeMemory(NULL,FatalError) > 0) DisplayWarning ("Abandoned buffers.");
  return BOO(success,EXIT_SUCCESS_,EXIT_FAILURE_);
#endif
}

/******************************************************************************
* DumpCDF.
*    Returns FALSE if an error occurred.
******************************************************************************/

Logical DumpCDF (argC, argV)
int argC;
char *argV[];
{
vFILE *CDFfp;
char CDFpath[DU_MAX_PATH_LEN+1];
char tCDFpath[DU_MAX_PATH_LEN+1];
char oSpec[DU_MAX_PATH_LEN+1];
char oDir[DU_MAX_DIR_LEN+1];
char oName[DU_MAX_NAME_LEN+1];
char delim;
char *docText;
Int32 int4;
Int32 recordSize;
Int32 recordType;
long offset;
long numDims;
long zVarNumDims;
long encoding;
int i, j;
long VarFlags;
long zVarFlags;
long nBytes;
long numElements;
long dataType;
Int32 firstRec[NUM_VXR_ENTRIES];
Int32 lastRec[NUM_VXR_ENTRIES];
Int32 VVRoffset[NUM_VXR_ENTRIES];
long Nentries;
void *padValue;
char attrName[CDF_ATTR_NAME_LEN+1];
char varName[CDF_VAR_NAME_LEN+1];
Byte wastedSpace[VDR_WASTED_SIZE];
void *ptr;
void *valuePtr;
char string[MAX_SCREENLINE_LEN+1];
char text[MAX_SCREENLINE_LEN+1];
Int32 version, release, increment;
Logical VDRwastedSpace;
Logical qopError = FALSE;
QOP *qop;
static char *validQuals[] = { "output", "brief", "full", "page", "nopage",
			      "sizes", "nosizes", "offset", NULL };
static int optRequired[] = { TRUE, FALSE, FALSE, FALSE, FALSE,
			     FALSE, FALSE, TRUE, 0 };

/******************************************************************************
* Determine qualifiers/options/parameters.
******************************************************************************/

switch (argC) {
  case 1:
    PageOLH ("cdfdump.olh", argV[0]);
    return TRUE;
  default:
    qop = Qop (argC, argV, validQuals, optRequired);
    if (qop == NULL) return FALSE;

    /**************************************************************************
    * Get CDF path.
    **************************************************************************/

    if (qop->Nparms < 1) {
      DisplayError ("Missing parameter.");
      qopError = TRUE;
    }
    else
      strcpyX (CDFpath, qop->parms[CDFPATHparm], DU_MAX_PATH_LEN);

    /**************************************************************************
    * Check for `page' qualifier (this must be done if the `output' qualifier
    * is checked).
    **************************************************************************/

    qopError = qopError | !TFqualifier(qop,&pagingOn,PAGEqual,NOPAGEqual,
				       DEFAULTpageDUMP,"page");

    /**************************************************************************
    * Check of offset qualifier.
    **************************************************************************/

    if (qop->qualEntered[OFFSETqual]) {
      if (sscanf(qop->qualOpt[OFFSETqual],"%ld",&startingOffset) != 1) {
	DisplayError ("Illegal starting offset.");
	qopError = TRUE;
      }
      if (startingOffset < 0) {
	DisplayError ("Illegal starting offset.");
	qopError = TRUE;
      }
    }
    else
      startingOffset = -1;

    /**************************************************************************
    * Check for output file qualifier.
    **************************************************************************/

    if (qop->qualEntered[OUTPUTqual]) {
      if (pagingOn) {
	DisplayError ("Conflicting qualifiers (`output' and `page').");
	qopError = TRUE;
      }
      else
        strcpyX (oSpec, qop->qualOpt[OUTPUTqual], DU_MAX_PATH_LEN);
    }
    else
      strcpyX (oSpec, "", DU_MAX_PATH_LEN);

    /**************************************************************************
    * Check for level qualifier.
    **************************************************************************/

    qopError = qopError | !S2qualifierLong(qop,&level,BRIEFqual,BRIEF_,
					   FULLqual,FULL_,
					   (DEFAULTbriefDUMP ? BRIEF_ : FULL_),
					   "level");

    /**************************************************************************
    * Check for `sizes' qualifier.
    **************************************************************************/

    qopError = qopError | !TFqualifier(qop,&checkSizes,SIZESqual,NOSIZESqual,
				       DEFAULTsizesDUMP,"sizes");

    /**************************************************************************
    * Free QOP memory and check for an error.
    **************************************************************************/

    FreeMemory (qop, FatalError);
    if (qopError) return FALSE;

    break;
}

/******************************************************************************
* Open CDF.
******************************************************************************/

CDFfp = V_open (CDFpath, READ_ONLY_a_mode);
if (CDFfp == NULL) {
  strcpyX (tCDFpath, CDFpath, 0);
  strcatX (tCDFpath, ".cdf", 0);
  CDFfp = V_open (tCDFpath, READ_ONLY_a_mode);
  if (CDFfp == NULL) {
    strcpyX (tCDFpath, CDFpath, 0);
    strcatX (tCDFpath, ".CDF", 0);
    CDFfp = V_open (tCDFpath, READ_ONLY_a_mode);
    if (CDFfp == NULL) {
      strcpyX (tCDFpath, CDFpath, 0);
      strcatX (tCDFpath, ".cdf;1", 0);
      CDFfp = V_open (tCDFpath, READ_ONLY_a_mode);
      if (CDFfp == NULL) {
	strcpyX (tCDFpath, CDFpath, 0);
	strcatX (tCDFpath, ".CDF;1", 0);
	CDFfp = V_open (tCDFpath, READ_ONLY_a_mode);
	if (CDFfp == NULL) {
	  WriteOut (stdout, "Error opening CDF.\n");
	  return FALSE;
	}
      }
    }
  }
}

/******************************************************************************
* Open output file (if specified).
******************************************************************************/

if (NULstring(oSpec))
  OUTfp = stdout;
else {
  ParsePath (oSpec, oDir, oName);
  if (strchr(oName,'.') == NULL) strcatX (oSpec, ".dmp", DU_MAX_PATH_LEN);
  OUTfp = fopen (oSpec, "w");
  if (OUTfp == NULL) {
    WriteOut (stdout, "Unable to open output file.\n");
    V_close (CDFfp, NULL);
    return FALSE;
  }
}

/******************************************************************************
* Initialize counters.
******************************************************************************/

usedBytes = 0;
wastedBytes = 0;
GDRcount = 0;
CDRcount = 0;
ADRcount = 0;
AgrEDRcount = 0;
AzEDRcount = 0;
rVDRcount = 0;
zVDRcount = 0;
VXRcount = 0;
VVRcount = 0;
UIRcount = 0;

/******************************************************************************
* Check record sizes (if requested).
******************************************************************************/

if (checkSizes) {
  WriteOut (OUTfp, "\nChecking record sizes...\n\n");

  if (startingOffset != -1)
    offset = startingOffset;
  else
    offset = V2_CDR_OFFSET;		/* Skip magic numbers. */
  V_seek (CDFfp, offset, vSEEK_SET);

  for (;;) {
     Logical bad = FALSE;		/* TRUE when we should break out. */
     recordSize = 0;
     Read32 (CDFfp, &recordSize);
     if (V_eof(CDFfp)) {
       WriteOut (OUTfp, "\nEOF detected.\n");
       break;
     }
     if (recordSize <= 0) {
       sprintf (text, "\nIllegal record size detected (%ld)\n",
		(long) recordSize);
       WriteOut (OUTfp, text);
       break;
     }
     Read32 (CDFfp, &recordType);
     switch (recordType) {
       case CDR_: strcpyX (text, "CDR", MAX_SCREENLINE_LEN); break;
       case GDR_: strcpyX (text, "GDR", MAX_SCREENLINE_LEN); break;
       case rVDR_: strcpyX (text, "rVDR", MAX_SCREENLINE_LEN); break;
       case zVDR_: strcpyX (text, "zVDR", MAX_SCREENLINE_LEN); break;
       case VXR_: strcpyX (text, "VXR", MAX_SCREENLINE_LEN); break;
       case VVR_: strcpyX (text, "VVR", MAX_SCREENLINE_LEN); break;
       case ADR_: strcpyX (text, "ADR", MAX_SCREENLINE_LEN); break;
       case AgrEDR_: strcpyX (text, "AgrEDR", MAX_SCREENLINE_LEN); break;
       case AzEDR_: strcpyX (text, "AzEDR", MAX_SCREENLINE_LEN); break;
       case UIR_: strcpyX (text, "UIR", MAX_SCREENLINE_LEN); break;
       default: {
     	 sprintf (text, "\nUnknown record type detected (%ld).\n",
		  (long) recordType);
	 WriteOut (OUTfp, text);
	 bad = TRUE;
       } 
     }
     if (bad) break;
     strcatX (text, ", ", MAX_SCREENLINE_LEN);
     sprintf (&text[strlen(text)], "%ld bytes (offset: %ld)\n",
	      (long) recordSize, (long) offset);
     WriteOut (OUTfp, text);
     offset += recordSize;
     V_seek (CDFfp, offset, vSEEK_SET);
     CHECKforABORTso
  }
}

/******************************************************************************
* Dump magic number(s).
******************************************************************************/

WriteOut (OUTfp, "\nScanning records...\n\n");

if (startingOffset == -1) {
  V_seek (CDFfp, 0, vSEEK_SET);
  Read32 (CDFfp, &int4);
  if (level == FULL_) {
    sprintf (text, "Magic number (1): %8lX (hex)\n", (long) int4);
    WriteOut (OUTfp, text);
  }
  Read32 (CDFfp, &int4);
  if (level == FULL_) {
    sprintf (text, "Magic number (2): %8lX (hex)\n", (long) int4);
    WriteOut (OUTfp, text);
  }
  usedBytes += 8;
}
else
  V_seek (CDFfp, startingOffset, vSEEK_SET);

/******************************************************************************
* Read and dump records until EOF (or illegal record) reached.
******************************************************************************/

for (;;) {
   /***************************************************************************
   * Record size.
   ***************************************************************************/

   offset = V_tell (CDFfp);

   recordSize = 0;                      /* Just in case. */

   Read32 (CDFfp, &recordSize);
   if (V_eof(CDFfp)) {
     WriteOut (OUTfp, "\nEOF detected.\n");
     DisplayStats (OUTfp);
     V_close (CDFfp, NULL);
     fclose (OUTfp);
     return TRUE;
   }

   if (recordSize <= 0) {
     sprintf (text, "\nIllegal record size detected (%ld)\n", recordSize);
     WriteOut (OUTfp, text);
     DisplayStats (OUTfp);
     V_close (CDFfp, NULL);
     fclose (OUTfp);
     return TRUE;
   }

   if (level == FULL_) {
     sprintf (text, "\nRecordSize: %ld   (at byte offset %ld)\n",
	          (long) recordSize, (long) offset);
     WriteOut (OUTfp, text);
   }

   /***************************************************************************
   * Record type.
   ***************************************************************************/

   Read32 (CDFfp, &recordType);
   if (level == FULL_) {
     sprintf (text, "RecordType: %ld ", (long) recordType);
     switch (recordType) {
       case CDR_:
	 strcatX (text, "(CDR)\n", MAX_SCREENLINE_LEN);
	 break;
       case GDR_:
	 strcatX (text, "(GDR)\n", MAX_SCREENLINE_LEN);
	 break;
       case rVDR_:
	 strcatX (text, "(rVDR)\n", MAX_SCREENLINE_LEN);
	 break;
       case zVDR_:
	 strcatX (text, "(zVDR)\n", MAX_SCREENLINE_LEN);
	 break;
       case VXR_:
	 strcatX (text, "(VXR)\n", MAX_SCREENLINE_LEN);
	 break;
       case VVR_:
	 strcatX (text, "(VVR)\n", MAX_SCREENLINE_LEN);
	 break;
       case ADR_:
	 strcatX (text, "(ADR)\n", MAX_SCREENLINE_LEN);
	 break;
       case AgrEDR_:
	 strcatX (text, "(AgrEDR)\n", MAX_SCREENLINE_LEN);
	 break;
       case AzEDR_:
	 strcatX (text, "(AzEDR)\n", MAX_SCREENLINE_LEN);
	 break;
       case UIR_:
	 strcatX (text, "(UIR)\n", MAX_SCREENLINE_LEN);
	 break;
       default:
	 sprintf (text, "Illegal record type detected (%ld)\n",
		  (long) recordType);
	 WriteOut (OUTfp, text);
	 DisplayStats (OUTfp);
	 V_close (CDFfp, NULL);
	 fclose (OUTfp);
	 return TRUE;
     }
     WriteOut (OUTfp, text);
   }

   switch (recordType) {
      /************************************************************************
      * Unused internal record
      ************************************************************************/
      case UIR_:
	UIRcount++;
	if (recordSize >= 16) {		/* Assumed a post-beta V2.5 CDF. */
	  Read32 (CDFfp, &int4);
	  if (level == FULL_) {
	    sprintf (text, "Next: %ld\n", (long) int4);
	    WriteOut (OUTfp, text);
	  }
	  Read32 (CDFfp, &int4);
	  if (level == FULL_) {
	    sprintf (text, "Prev: %ld\n", (long) int4);
	    WriteOut (OUTfp, text);
	  }
	  nBytes = recordSize - 16;
	  if (nBytes > 0) {
	    ptr = AllocateMemory ((size_t) nBytes, FatalError);
	    V_read (ptr, (size_t) nBytes, 1, CDFfp);
	    FreeMemory (ptr, FatalError);
	  }
	}
	else {				/* Must be a beta V2.5 CDF. */
	  nBytes = recordSize - 8;
	  if (nBytes > 0) {
	    ptr = AllocateMemory ((size_t) nBytes, FatalError);
	    V_read (ptr, (size_t) nBytes, 1, CDFfp);
	    FreeMemory (ptr, FatalError);
	  }
	}
	wastedBytes += recordSize;
	break;

      /************************************************************************
      * CDF descriptor record (CDR).
      ************************************************************************/

      case CDR_:
	CDRcount++;

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "GDRoffset: %ld\n", (long) int4);
	  WriteOut (OUTfp, text);
	}

	Read32 (CDFfp, &version);
	if (level == FULL_) {
	  sprintf (text, "Version: %ld\n", (long) version);
	  WriteOut (OUTfp, text);
	}

	Read32 (CDFfp, &release);
	if (level == FULL_) {
	  sprintf (text, "Release: %ld\n", (long) release);
	  WriteOut (OUTfp, text);
	}

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "Encoding: %ld\n", (long) int4);
	  WriteOut (OUTfp, text);
	}
	encoding = int4;

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "Flags: %ld (", (long) int4);
	  sprintf (EofS(text), "%s,",
		   BOO(BITSET(int4,CDR_MAJORITY_BIT),"Row","Column"));
	  sprintf (EofS(text), "%s)\n",
		   BOO(BITSET(int4,CDR_FORMAT_BIT),"Single","Multi"));
	  WriteOut (OUTfp, text);
	}

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "rfuA: %ld\n", (long) int4);
	  WriteOut (OUTfp, text);
	}

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "rfuB: %ld\n", (long) int4);
	  WriteOut (OUTfp, text);
	}

	Read32 (CDFfp, &increment);
	if (level == FULL_) {
	  sprintf (text, "Increment: %ld\n", (long) increment);
	  WriteOut (OUTfp, text);
	}

	VDRwastedSpace = PriorTo ("2.5", version, release, increment);

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "rfuD: %ld\n", (long) int4);
	  WriteOut (OUTfp, text);
	}

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "rfuE: %ld\n", (long) int4);
	  WriteOut (OUTfp, text);
	}

	nBytes = recordSize - CDR_BASE_SIZE;
	docText = AllocateMemory ((size_t) (nBytes + 1), FatalError);
	V_read (docText, (size_t) nBytes, 1, CDFfp);
	docText[(int)nBytes] = NUL;
	if (level == FULL_) {
	  Logical allNULs = TRUE;
	  WriteOut (OUTfp, "copyright...\n");
	  WriteOut (OUTfp, docText);
	  for (i = strlen(docText); i < nBytes; i++) {
	     if (docText[i] != NUL) allNULs = FALSE;
	  }
	  if (allNULs) WriteOut (OUTfp, "...followed by all NULs.\n");
	}
	FreeMemory (docText, FatalError);

	usedBytes += recordSize;
	break;

      /************************************************************************
      * Global descriptor record (GDR).
      ************************************************************************/

      case GDR_:
	GDRcount++;

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "rVDRhead: %ld\n", (long) int4);
	  WriteOut (OUTfp, text);
	}

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "zVDRhead: %ld\n", (long) int4);
	  WriteOut (OUTfp, text);
	}

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "ADRhead: %ld\n", (long) int4);
	  WriteOut (OUTfp, text);
	}

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "eof: %ld\n", (long) int4);
	  WriteOut (OUTfp, text);
	}

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "NumVar: %ld\n", (long) int4);
	  WriteOut (OUTfp, text);
	}

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "NumAttr: %ld\n", (long) int4);
	  WriteOut (OUTfp, text);
	}

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "rMaxRec: %ld\n", (long) int4);
	  WriteOut (OUTfp, text);
	}

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "NumDims: %ld\n", (long) int4);
	  WriteOut (OUTfp, text);
	}
	numDims = int4;

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "NumZvars: %ld\n", (long) int4);
	  WriteOut (OUTfp, text);
	}

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "UIRhead: %ld\n", (long) int4);
	  WriteOut (OUTfp, text);
	}

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "rfuC: %ld\n", (long) int4);
	  WriteOut (OUTfp, text);
	}

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "rfuD: %ld\n", (long) int4);
	  WriteOut (OUTfp, text);
	}

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "rfuE: %ld\n", (long) int4);
	  WriteOut (OUTfp, text);
	}

	for (j = 0; j < numDims; j++) {
	   Read32 (CDFfp, &int4);
	   if (level == FULL_) {
	     sprintf (text, " DimSizes[%d]: %ld\n", j, (long) int4);
	     WriteOut (OUTfp, text);
	   }
	}

	usedBytes += recordSize;
	break;

      /************************************************************************
      * Variable descriptor record (rVDR).
      ************************************************************************/

      case rVDR_:
	rVDRcount++;

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "rVDRnext: %ld\n", (long) int4);
	  WriteOut (OUTfp, text);
	}

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "DataType: %ld\n", (long) int4);
	  WriteOut (OUTfp, text);
	}
	dataType = int4;

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "MaxRec: %ld\n", (long) int4);
	  WriteOut (OUTfp, text);
	}

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "VXRhead: %ld\n", (long) int4);
	  WriteOut (OUTfp, text);
	}

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "VXRtail: %ld\n", (long) int4);
	  WriteOut (OUTfp, text);
	}

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "Flags: %ld (", (long) int4);
	  sprintf (EofS(text), "%s,",
		   BOO(BITSET(int4,VDR_RECVARY_BIT),"VARY","NOVARY"));
	  sprintf (EofS(text), "%s)\n",
		   BOO(BITSET(int4,VDR_PADVALUE_BIT),"Pad","NoPad"));
	  WriteOut (OUTfp, text);
	}
	VarFlags = int4;

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "rfuA: %ld\n", (long) int4);
	  WriteOut (OUTfp, text);
	}

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "rfuB: %ld\n", (long) int4);
	  WriteOut (OUTfp, text);
	}

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "rfuC: %ld\n", (long) int4);
	  WriteOut (OUTfp, text);
	}

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "rfuF: %ld\n", (long) int4);
	  WriteOut (OUTfp, text);
	}

	if (VDRwastedSpace) {
	  V_read (wastedSpace, VDR_WASTED_SIZE, 1, CDFfp);
	  if (level == FULL_) {
	    WriteOut (OUTfp, "Skipping over wasted space...\n");
	  }
	}

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "numElem: %ld\n", (long) int4);
	  WriteOut (OUTfp, text);
	}
	numElements = int4;

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "Num: %ld\n", (long) int4);
	  WriteOut (OUTfp, text);
	}

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "rfuD: %ld\n", (long) int4);
	  WriteOut (OUTfp, text);
	}

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "NextendRecs: %ld\n", (long) int4);
	  WriteOut (OUTfp, text);
	}

	V_read (varName, CDF_VAR_NAME_LEN, 1, CDFfp);
	varName[CDF_VAR_NAME_LEN] = NUL;
	if (level == FULL_) {
	  delim = PickDelimiter (varName, strlen(varName));
	  sprintf (text, "Name: %c%s%c\n", delim, varName, delim);
	  WriteOut (OUTfp, text);
	}

	for (j = 0; j < numDims; j++) {
	   Read32 (CDFfp, &int4);
	   if (level == FULL_) {
	     sprintf (text, " DimVarys[%d]: %ld\n", j, (long) int4);
	     WriteOut (OUTfp, text);
	   }
	}

	if (BITSET(VarFlags,VDR_PADVALUE_BIT)) {
	  nBytes = CDFelemSize(dataType) * numElements;
	  padValue = AllocateMemory ((size_t) nBytes, FatalError);
	  V_read (padValue, (size_t) nBytes, 1, CDFfp);
	  if (level == FULL_) {
	    ConvertBuffer (encoding, HOST_DECODING, NEGtoPOSfp0off, dataType,
			   numElements, padValue, padValue);
	    strcpyX (string, "PadValue: ", MAX_SCREENLINE_LEN);
	    EncodeValuesFormat (dataType, numElements, padValue,
				&string[strlen(string)], NULL, 0,
				MAX_SCREENLINE_LEN - strlen(string),
				EPOCH0_STYLE);
	    strcatX (string, "\n", MAX_SCREENLINE_LEN);
	    WriteOut (OUTfp, string);
	  }
	  FreeMemory (padValue, FatalError);
	}

	usedBytes += recordSize;
	break;

      /************************************************************************
      * zVariable descriptor record (zVDR).
      ************************************************************************/

      case zVDR_:
	zVDRcount++;

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "zVDRnext: %ld\n", (long) int4);
	  WriteOut (OUTfp, text);
	}

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "DataType: %ld\n", (long) int4);
	  WriteOut (OUTfp, text);
	}
	dataType = int4;

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "MaxRec: %ld\n", (long) int4);
	  WriteOut (OUTfp, text);
	}

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "VXRhead: %ld\n", (long) int4);
	  WriteOut (OUTfp, text);
	}

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "VXRtail: %ld\n", (long) int4);
	  WriteOut (OUTfp, text);
	}

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "Flags: %ld (", (long) int4);
	  sprintf (EofS(text), "%s,",
		   BOO(BITSET(int4,VDR_RECVARY_BIT),"VARY","NOVARY"));
	  sprintf (EofS(text), "%s)\n",
		   BOO(BITSET(int4,VDR_PADVALUE_BIT),"Pad","NoPad"));
	  WriteOut (OUTfp, text);
	}
	zVarFlags = int4;

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "rfuA: %ld\n", (long) int4);
	  WriteOut (OUTfp, text);
	}

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "rfuB: %ld\n", (long) int4);
	  WriteOut (OUTfp, text);
	}

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "rfuC: %ld\n", (long) int4);
	  WriteOut (OUTfp, text);
	}

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "rfuF: %ld\n", (long) int4);
	  WriteOut (OUTfp, text);
	}

	if (VDRwastedSpace) {
	  V_read (wastedSpace, VDR_WASTED_SIZE, 1, CDFfp);
	  if (level == FULL_) {
	    WriteOut (OUTfp, "skipping over wasted space...\n");
	  }
	}

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "NumElem: %ld\n", (long) int4);
	  WriteOut (OUTfp, text);
	}
	numElements = int4;

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "Num: %ld\n", (long) int4);
	  WriteOut (OUTfp, text);
	}

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "rfuD: %ld\n", (long) int4);
	  WriteOut (OUTfp, text);
	}

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "NextendRecs: %ld\n", (long) int4);
	  WriteOut (OUTfp, text);
	}

	V_read (varName, CDF_VAR_NAME_LEN, 1, CDFfp);
	varName[CDF_VAR_NAME_LEN] = NUL;
	if (level == FULL_) {
	  delim = PickDelimiter (varName, strlen(varName));
	  sprintf (text, "Name: %c%s%c\n", delim, varName, delim);
	  WriteOut (OUTfp, text);
	}

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "NumDims: %ld\n", (long) int4);
	  WriteOut (OUTfp, text);
	}
	zVarNumDims = int4;

	for (j = 0; j < zVarNumDims; j++) {
	   Read32 (CDFfp, &int4);
	   if (level == FULL_) {
	     sprintf (text, " DimSizes[%d]: %ld\n", j, (long) int4);
	     WriteOut (OUTfp, text);
	   }
	}

	for (j = 0; j < zVarNumDims; j++) {
	   Read32 (CDFfp, &int4);
	   if (level == FULL_) {
	     sprintf (text, "  DimVarys[%d]: %ld\n", j, (long) int4);
	     WriteOut (OUTfp, text);
	   }
	}

	if (BITSET(zVarFlags,VDR_PADVALUE_BIT)) {
	  nBytes = CDFelemSize(dataType) * numElements;
	  padValue = AllocateMemory ((size_t) nBytes, FatalError);
	  V_read (padValue, (size_t) nBytes, 1, CDFfp);
	  if (level == FULL_) {
	    ConvertBuffer (encoding, HOST_DECODING, NEGtoPOSfp0off, dataType,
			   numElements, padValue, padValue);
	    strcpyX (string, "PadValue: ", MAX_SCREENLINE_LEN);
	    EncodeValuesFormat (dataType, numElements, padValue,
				&string[strlen(string)], NULL, 0,
				MAX_SCREENLINE_LEN - strlen(string),
				EPOCH0_STYLE);
	    strcatX (string, "\n", MAX_SCREENLINE_LEN);
	    WriteOut (OUTfp, string);
	  }
	  FreeMemory (padValue, FatalError);
	}

	usedBytes += recordSize;
	break;

      /************************************************************************
      * Variable Index record (VXR).
      ************************************************************************/

      case VXR_:
	VXRcount++;

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "VXRnext: %ld\n", (long) int4);
	  WriteOut (OUTfp, text);
	}

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "Nentries: %ld\n", (long) int4);
	  WriteOut (OUTfp, text);
	}
	Nentries = NUM_VXR_ENTRIES;

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "NusedEntries: %ld\n", (long) int4);
	  WriteOut (OUTfp, text);
	}

	for (j = 0; j < Nentries; j++) Read32 (CDFfp, &firstRec[j]);
	for (j = 0; j < Nentries; j++) Read32 (CDFfp, &lastRec[j]);
	for (j = 0; j < Nentries; j++) Read32 (CDFfp, &VVRoffset[j]);

	if (level == FULL_)
	  WriteOut (OUTfp, "\n  Entry  FirstRec  LastRec  VVRoffset\n");

	for (j = 0; j < Nentries; j++)
	   if (level == FULL_) {
	     sprintf (text, "   %2d    %5ld    %5ld     %9ld\n", j,
		      (long) firstRec[j], (long) lastRec[j],
		      (long) VVRoffset[j]);
	     WriteOut (OUTfp, text);
	   }

	usedBytes += recordSize;
	break;

      /************************************************************************
      * Variable Values record (VVR).
      ************************************************************************/

      case VVR_:
	VVRcount++;

	V_seek (CDFfp, recordSize - VVR_BASE_SIZE, vSEEK_CUR);
	usedBytes += recordSize;
	break;

      /************************************************************************
      * Attribute descriptor record (ADR).
      ************************************************************************/

      case ADR_:
	ADRcount++;

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "ADRnext: %ld\n", (long) int4);
	  WriteOut (OUTfp, text);
	}

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "AgrEDRhead: %ld\n", (long) int4);
	  WriteOut (OUTfp, text);
	}

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "Scope: %ld\n", (long) int4);
	  WriteOut (OUTfp, text);
	}

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "Num: %ld\n", (long) int4);
	  WriteOut (OUTfp, text);
	}

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "NumRentries: %ld\n", (long) int4);
	  WriteOut (OUTfp, text);
	}

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "MaxRentry: %ld\n", (long) int4);
	  WriteOut (OUTfp, text);
	}

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "rfuA: %ld\n", (long) int4);
	  WriteOut (OUTfp, text);
	}

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "AzEDRhead: %ld\n", (long) int4);
	  WriteOut (OUTfp, text);
	}

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "NumZentries: %ld\n", (long) int4);
	  WriteOut (OUTfp, text);
	}

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "MaxZentry: %ld\n", (long) int4);
	  WriteOut (OUTfp, text);
	}

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "rfuE: %ld\n", (long) int4);
	  WriteOut (OUTfp, text);
	}

	V_read (attrName, CDF_ATTR_NAME_LEN, 1, CDFfp);
	attrName[CDF_ATTR_NAME_LEN] = NUL;
	if (level == FULL_) {
	  delim = PickDelimiter (attrName, strlen(attrName));
	  sprintf (text, "Name: %c%s%c\n", delim, attrName, delim);
	  WriteOut (OUTfp, text);
	}

	usedBytes += recordSize;
	break;

      /************************************************************************
      * Attribute entry descriptor record (ArEDR).
      ************************************************************************/

      case AgrEDR_:
	AgrEDRcount++;

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "AgrEDRnext: %ld\n", (long) int4);
	  WriteOut (OUTfp, text);
	}

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "AttrNum: %ld\n", (long) int4);
	  WriteOut (OUTfp, text);
	}

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "DataType: %ld\n", (long) int4);
	  WriteOut (OUTfp, text);
	}
	dataType = int4;

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "Num: %ld\n", (long) int4);
	  WriteOut (OUTfp, text);
	}

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "NumElem: %ld\n", (long) int4);
	  WriteOut (OUTfp, text);
	}
	numElements = int4;

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "rfuA: %ld\n", (long) int4);
	  WriteOut (OUTfp, text);
	}

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "rfuB: %ld\n", (long) int4);
	  WriteOut (OUTfp, text);
	}

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "rfuC: %ld\n", (long) int4);
	  WriteOut (OUTfp, text);
	}

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "rfuD: %ld\n", (long) int4);
	  WriteOut (OUTfp, text);
	}

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "rfuE: %ld\n", (long) int4);
	  WriteOut (OUTfp, text);
	}

	nBytes = numElements * CDFelemSize(dataType);
	valuePtr = AllocateMemory ((size_t) nBytes, FatalError);
	V_read (valuePtr, (size_t) nBytes, 1, CDFfp);

	if (level == FULL_) {
	  ConvertBuffer (encoding, HOST_DECODING, NEGtoPOSfp0off, dataType,
			 numElements, valuePtr, valuePtr);
	  strcpyX (string, "Value: ", MAX_SCREENLINE_LEN);
	  EncodeValuesFormat (dataType, numElements, valuePtr,
			      &string[strlen(string)], NULL, 0,
			      MAX_SCREENLINE_LEN - strlen(string),
			      EPOCH0_STYLE);
	  strcatX (string, "\n", MAX_SCREENLINE_LEN);
	  WriteOut (OUTfp, string);
	}

	FreeMemory (valuePtr, FatalError);

	usedBytes += recordSize;
	break;

      /************************************************************************
      * Attribute zEntry descriptor record (AzEDR).
      ************************************************************************/

      case AzEDR_:
	AzEDRcount++;

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "AzEDRnext: %ld\n", (long) int4);
	  WriteOut (OUTfp, text);
	}

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "AttrNum: %ld\n", (long) int4);
	  WriteOut (OUTfp, text);
	}

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "DataType: %ld\n", (long) int4);
	  WriteOut (OUTfp, text);
	}
	dataType = int4;

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "Num: %ld\n", (long) int4);
	  WriteOut (OUTfp, text);
	}

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "NumElem: %ld\n", (long) int4);
	  WriteOut (OUTfp, text);
	}
	numElements = int4;

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "rfuA: %ld\n", (long) int4);
	  WriteOut (OUTfp, text);
	}

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "rfuB: %ld\n", (long) int4);
	  WriteOut (OUTfp, text);
	}

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "rfuC: %ld\n", (long) int4);
	  WriteOut (OUTfp, text);
	}

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "rfuD: %ld\n", (long) int4);
	  WriteOut (OUTfp, text);
	}

	Read32 (CDFfp, &int4);
	if (level == FULL_) {
	  sprintf (text, "rfuE: %ld\n", (long) int4);
	  WriteOut (OUTfp, text);
	}

	nBytes = numElements * CDFelemSize(dataType);
	valuePtr = AllocateMemory ((size_t) nBytes, FatalError);
	V_read (valuePtr, (size_t) nBytes, 1, CDFfp);

	if (level == FULL_) {
	  ConvertBuffer (encoding, HOST_DECODING, NEGtoPOSfp0off, dataType,
			 numElements, valuePtr, valuePtr);
	  strcpyX (string, "Value: ", MAX_SCREENLINE_LEN);
	  EncodeValuesFormat (dataType, numElements, valuePtr,
			      &string[strlen(string)], NULL, 0,
			      MAX_SCREENLINE_LEN - strlen(string),
			      EPOCH0_STYLE);
	  strcatX (string, "\n", MAX_SCREENLINE_LEN);
	  WriteOut (OUTfp, string);
	}

	FreeMemory (valuePtr, FatalError);

	usedBytes += recordSize;
	break;

      /************************************************************************
      * Illegal record type.
      ************************************************************************/
      default:
	/* We should never get here since the illegal record type should be
	   detected when the record type is displayed. */
	break;
   }
   CHECKforABORTso
}
}


/******************************************************************************
* DisplayStats.
******************************************************************************/

static void DisplayStats (oFp)
FILE *oFp;
{
  char text[132+1];
  long totalBytes = usedBytes + wastedBytes;
  long totalBlocks = ((totalBytes - 1) / 512) + 1;
  float pctUsed = 100.0 * (((float) usedBytes) / ((float) totalBytes));
  float pctWasted = 100.0 * (((float) wastedBytes) / ((float) totalBytes));

  WriteOut (oFp, "\n\nSummary...");

  sprintf (text, "\n\n   Total bytes: %9ld  (%ld blocks [512-byte])\n",
	       totalBytes, totalBlocks);
  WriteOut (oFp, text);

  sprintf (text, "    Used bytes: %9ld  (%5.1f%%)\n", usedBytes, pctUsed);
  WriteOut (oFp, text);

  sprintf (text, "  Unused bytes: %9ld  (%5.1f%%)\n", wastedBytes, pctWasted);
  WriteOut (oFp, text);

  sprintf (text, "\n     CDR count: %9ld\n", (long) CDRcount);
  WriteOut (oFp, text);
  sprintf (text, "     GDR count: %9ld\n", (long) GDRcount);
  WriteOut (oFp, text);
  sprintf (text, "     ADR count: %9ld\n", (long) ADRcount);
  WriteOut (oFp, text);
  sprintf (text, "  AgrEDR count: %9ld\n", (long) AgrEDRcount);
  WriteOut (oFp, text);
  sprintf (text, "   AzEDR count: %9ld\n", (long) AzEDRcount);
  WriteOut (oFp, text);
  sprintf (text, "    rVDR count: %9ld\n", (long) rVDRcount);
  WriteOut (oFp, text);
  sprintf (text, "    zVDR count: %9ld\n", (long) zVDRcount);
  WriteOut (oFp, text);
  sprintf (text, "     VXR count: %9ld\n", (long) VXRcount);
  WriteOut (oFp, text);
  sprintf (text, "     VVR count: %9ld\n", (long) VVRcount);
  WriteOut (oFp, text);
  sprintf (text, "     UIR count: %9ld\n\n\n", (long) UIRcount);
  WriteOut (oFp, text);

  return;
}

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

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

  static Logical briefDump = DEFAULTbriefDUMP;
  static Logical pageOutput = DEFAULTpageCVT;
  static Logical checkSizes = DEFAULTsizesDUMP;
  static Str255 CDFtext = "\p";
  static Str255 outText = "\p";

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

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

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

  SetIText ((Handle) controlHs[CDFTEXTin], CDFtext);
  SetIText ((Handle) controlHs[OUTTEXTin], outText);

  if (briefDump)
    SetCtlValue (controlHs[BRIEFin], 1);
  else
    SetCtlValue (controlHs[FULLin], 1);

  if (pageOutput) SetCtlValue (controlHs[PAGEin], 1);
  if (checkSizes) SetCtlValue (controlHs[SIZESin], 1);

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

  /****************************************************************************
  * Change the "Quit" button to a "Cancel" button after the first time.
  ****************************************************************************/

  if (first)
    first = FALSE;
  else
    SetCTitle (controlHs[CANCELin], CtoPstr(cancelTitle));

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

  for (;;) {
    ModalDialog (FilterDialogQOPso, &itemN);
    switch (itemN) {
      /************************************************************************
      * Ok.
      ************************************************************************/
      case OKin: {
	int n;

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

	GetIText ((Handle) controlHs[CDFTEXTin], CDFtext);
	GetIText ((Handle) controlHs[OUTTEXTin], outText);

	briefDump = GetCtlValue (controlHs[BRIEFin]);
	pageOutput = GetCtlValue (controlHs[PAGEin]);
	checkSizes = GetCtlValue (controlHs[SIZESin]);
	
	/**********************************************************************
	* Build argc/argv.
	**********************************************************************/

        *argC = 4 + BOO(NULpString(CDFtext),0,1) +
		    BOO(NULpString(outText),0,2);
        *argV = (char **) AllocateMemory (*argC * sizeof(char *), FatalError);
	
	n = 0;

	MAKEstrARGv (argV, n, pgmName)

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

	MAKEbooARGv (argV, n, briefDump, "-brief", "-full")
	MAKEbooARGv (argV, n, pageOutput, "-page", "-nopage")
	MAKEbooARGv (argV, n, checkSizes, "-sizes", "-nosizes")
	
	if (!NULpString(outText)) {
	  MAKEstrARGv (argV, n, "-output")
	  PtoCstr (outText);
	  MAKEstrARGv (argV, n, (char *) outText)
	  CtoPstr ((char *) outText);
	}

	/**********************************************************************
	* Close the dialog and return.
	**********************************************************************/
        CloseDialog (dialogP);
        return TRUE;
      }
      /************************************************************************
      * Help.
      ************************************************************************/
      case HELPin: {
        int n;
        *argC = 1;
        *argV = (char **) AllocateMemory (*argC * sizeof(char *), FatalError);
	n = 0;
	MAKEstrARGv (argV, n, pgmName)
	CloseDialog (dialogP);
        return TRUE;
      }
      /************************************************************************
      * Cancel.
      ************************************************************************/
      case CANCELin:
        CloseDialog (dialogP);
        return FALSE;
      /************************************************************************
      * Select CDF specification.
      ************************************************************************/
      case CDFSELECTin: {
	StandardFileReply CDFreply;
	char CDFpath[DU_MAX_PATH_LEN+1];
	StandardGetFile (FilterForCDFs, -1, NULL, &CDFreply);
	if (CDFreply.sfGood && !CDFreply.sfIsFolder && !CDFreply.sfIsVolume) {
	  BuildMacPath (&CDFreply.sfFile, CDFpath, TRUE);
	  CDFtext[0] = strlen (CDFpath);
	  strcpyX ((char *) &CDFtext[1], CDFpath, 255);
	  SetIText ((Handle) controlHs[CDFTEXTin], CDFtext);
	}
	break;
      }
      /************************************************************************
      * Select output file specification.
      *     The cursor is set because `StandardPutFile' leaves the cursor as
      * an iBeam (instead of returning it to what it was).
      ************************************************************************/
      case OUTSELECTin: {
	StandardFileReply outReply;
	char outPath[DU_MAX_PATH_LEN+1], prompt[] = "Enter output file:";
	StandardPutFile (CtoPstr(prompt), CtoPstr(""), &outReply);
	if (outReply.sfGood && !outReply.sfIsFolder && !outReply.sfIsVolume) {
	  BuildMacPath (&outReply.sfFile, outPath, TRUE);
	  outText[0] = strlen (outPath);
	  strcpyX ((char *) &outText[1], outPath, 255);
	  SetIText ((Handle) controlHs[OUTTEXTin], outText);
	}
	SetCursor (&(qd.arrow));
	break;
      }
      /************************************************************************
      * Check boxes.
      ************************************************************************/
      case SIZESin:
      case PAGEin:
        SetCtlValue (controlHs[itemN], BOO(GetCtlValue(controlHs[itemN]),0,1));
        break;
      /************************************************************************
      * Radio buttons.
      ************************************************************************/
      case BRIEFin:
        SetCtlValue (controlHs[FULLin], 0);
        SetCtlValue (controlHs[BRIEFin], 1);
        break;
      case FULLin:
        SetCtlValue (controlHs[BRIEFin], 0);
        SetCtlValue (controlHs[FULLin], 1);
        break;
    }
  }
}
#endif
