/******************************************************************************
*
*  NSSDC/CDF                                         CDFedit, part 0 (main).
*
*  Version 1.2c, 28-Sep-95, Hughes STX.
*
*  Modification history:
*
*   V1.0  25-Jan-94, J Love     Original version.
*   V1.0a  4-Feb-94, J Love     DEC Alpha/OpenVMS port.
*   V1.1  15-Dec-94, J Love     CDF V2.5.
*   V1.1a 10-Jan-95, J Love	Uppercase file extensions on the Macintosh.
*   V1.1b 23-Jan-95, J Love	IRIX 6.x (64-bit).
*   V1.1c 28-Feb-95, J Love	Pass `char' as `int'.
*   V1.2  11-Apr-95, J Love	POSIX.
*   V1.2a 18-Apr-95, J Love	More POSIX.
*   V1.2b  6-Sep-95, J Love	CDFexport-related changes.  FSI key
*				definitions.
*   V1.2c 28-Sep-95, J Love	Macintosh dialog filtering.  Outline default
*				button.
*
******************************************************************************/

#define CDFEDIT
#include "cdfedit.h"

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

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

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

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

/******************************************************************************
* EditCDFs.
******************************************************************************/

Logical EditCDFs (argC, argV)
int argC;
char *argV[];
{
   QOP *qop;
   static char *validQuals[] = {
     "browse", "nobrowse", "zmode", "format", "noformat", "prompt",
     "noprompt", "report", "neg2posfp0", "noneg2posfp0", "cache",
     "statistics", "nostatistics", "gwithentries", "nogwithentries",
     "vwithentries", "novwithentries", NULL
   };
   static int optRequired[] = {
     FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE,
     FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, 0
   };
   static char *reportTokens[] = { "errors", "warnings", "informationals" };
   char CDFspec[DU_MAX_PATH_LEN+1];
   Logical browseOnly, useFormat, promptForSpec, negToPosFp0, status;
   long zMode, cacheSize;
   Logical qopError = FALSE;
 
   /***************************************************************************
   * Check qualifiers/options/parameters.
   ***************************************************************************/

   switch (argC) {
     case 1:
       InitializeScreen ();
       OnlineHelpWindow (ilhFile, OLHhelpID);
       CleanupScreen ();
       return TRUE;
     default:
       qop = Qop (argC, argV, validQuals, optRequired);
       if (qop == NULL) return FALSE;

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

       switch (qop->Nparms) {
	 case 0:
	   CDFspec[0] = NUL;
	   break;
	 case 1:
	   strcpyX (CDFspec, qop->parms[CDFSPECparm], DU_MAX_PATH_LEN);
#if defined(vms) || defined(dos)
	   Uppercase (CDFspec);
#endif
	   break;
	 default:
	   DisplayError ("Too many parameters.");
	   qopError = TRUE;
	   break;
       }

       /***********************************************************************
       * Check for `browse', `format', `prompt', `neg2posfp0', and `statistics'
       * qualfiers.
       ***********************************************************************/

       qopError = qopError | !TFqualifier(qop,&browseOnly,BROWSEqual,
					  NOBROWSEqual,DEFAULTbrowseEDIT,
					  "browse");
       qopError = qopError | !TFqualifier(qop,&useFormat,FORMATqual,
					  NOFORMATqual,DEFAULTformatEDIT,
					  "format");
       qopError = qopError | !TFqualifier(qop,&promptForSpec,PROMPTqual,
					  NOPROMPTqual,DEFAULTpromptEDIT,
					  "prompt");
       qopError = qopError | !TFqualifier(qop,&negToPosFp0,NEG2POSFP0qual,
					  NONEG2POSFP0qual,DEFAULT_NEGtoPOSfp0,
					  "neg2posfp0");
       qopError = qopError | !TFqualifier(qop,&dumpStatistics,STATSqual,
					  NOSTATSqual,DEFAULTstatsEDIT,
					  "statistics");
       qopError = qopError | !TFqualifier(qop,&gAttrsAndEntries,gWITHqual,
					  NOgWITHqual,DEFAULTgWithEDIT,
					  "gwithentries");
       qopError = qopError | !TFqualifier(qop,&vAttrsAndEntries,vWITHqual,
					  NOvWITHqual,DEFAULTvWithEDIT,
					  "vwithentries");

       /***********************************************************************
       * Check for zMode qualifier.
       ***********************************************************************/

       if (qop->qualEntered[ZMODEqual]) {
	 switch (qop->qualOpt[ZMODEqual][0]) {
	   case '0': zMode = zMODEoff; break;
	   case '1': zMode = zMODEon1; break;
	   case '2': zMode = zMODEon2; break;
	   default: {
	     char tempS[MAX_MESSAGE_TEXT_LEN+1];
	     sprintf (tempS, "Illegal zMode (%s).", qop->qualOpt[ZMODEqual]);
	     DisplayError (tempS);
	     qopError = TRUE;
	   }
	 }
       }
       else
	 zMode = DEFAULTzModeEDIT;

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

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

       /***********************************************************************
       * Check for `report' qualifier.  If absent, use defaults.
       ***********************************************************************/

       if (qop->qualEntered[REPORTqual]) {
	 if (!ParseOptionList(3,reportTokens,
			      qop->qualOpt[REPORTqual],report)) {
	   DisplayError ("Illegal list of `report' options.");
	   qopError = TRUE;
	 }
       }
       else {
	 report[ERRORs] = REPORTerrorsDEFAULT;
	 report[WARNs] = REPORTwarningsDEFAULT;
	 report[INFOs] = REPORTinfosDEFAULT;
       }

       /***********************************************************************
       * Check for missing/conflicting parameters/qualifiers.
       ***********************************************************************/

       if (qop->Nparms < 1 && (!promptForSpec)) {
	 char tempS[MAX_MESSAGE_TEXT_LEN+1];
	 strcpyX (tempS, "Either a CDF(s) specification or the `prompt' ",
		  MAX_MESSAGE_TEXT_LEN);
	 strcatX (tempS, "qualifier must be specified.", MAX_MESSAGE_TEXT_LEN);
	 DisplayError (tempS);
	 qopError = TRUE;
       }

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

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

       break;
   }

   /***************************************************************************
   * Initialize windowing.
   ***************************************************************************/

   InitializeScreen ();

   /***************************************************************************
   * If browsing, display message explaining reduced capability (no modifying,
   * creating, or deleting).
   ***************************************************************************/

   if (browseOnly) {
     static char *eLines[] = {
       "While browsing you will not be able to create",
       "a CDF, delete a CDF, or modify a CDF.  You are",
       "running CDFedit in a read-only mode.  Command",
       "line options are available by entering `CDFedit'",
       "(without any parameters/qualifiers)."
     };
     static char *tLines[] = {
       "Enter any key to continue..."
     };
     static int exitChars[] = { NUL };
     STATIC_ struct EditWindowStruct EW = {
       " Browse Mode ", 7, 14, 50, 0, NULL, 5, 5, eLines, 5, 1, tLines,
       FALSE, TRUE, exitChars, REFRESHkey_FSI, NUL, NUL, NUL, NUL, NUL, NUL
     };
     EditWindow (NEWew, &EW, (Logical) TRUE);
     EditWindow (READew, &EW);
     EditWindow (DELETEew, &EW);
   }

   /***************************************************************************
   * Edit CDF(s).
   ***************************************************************************/

   if (promptForSpec)
     status = SpecificationPrompt (CDFspec, browseOnly, useFormat, negToPosFp0,
				   zMode, cacheSize);
   else
     if (IsDir(CDFspec) || IsWild(CDFspec))
       status = EditCDFsMenu (CDFspec, browseOnly, negToPosFp0, useFormat,
			      zMode, cacheSize);
     else
       status = TryToEditCDF (CDFspec, browseOnly, negToPosFp0, useFormat,
			      zMode, cacheSize);

   /***************************************************************************
   * If a fatal error occurred, close the possibly open CDF.
   ***************************************************************************/

   if (!status) CDFlib (CLOSE_, CDF_,
			NULL_);

   /***************************************************************************
   * Clean up screen and return.
   ***************************************************************************/

   CleanupScreen ();
   return status;
}

/******************************************************************************
* SpecificationPrompt.
******************************************************************************/

Logical SpecificationPrompt (CDFspec, browseOnly, useFormat, negToPosFp0,
			     zMode, cacheSize)
char CDFspec[DU_MAX_PATH_LEN+1];
Logical browseOnly;
Logical useFormat;
Logical negToPosFp0;
long zMode;
long cacheSize;
{
  for (;;) {
    if (NULstring(CDFspec)) strcpyX (CDFspec,CURRENTDIRECTORY,DU_MAX_PATH_LEN);
    if (!PromptForSpec(CDFspec)) break;
#if defined(vms) || defined(dos)
    Uppercase (CDFspec);
#endif
    if (IsDir(CDFspec) || IsWild(CDFspec)) {
      /************************************************************************
      * Directory/wildcard (more than one CDF).
      ************************************************************************/
      if (!EditCDFsMenu(CDFspec,browseOnly,negToPosFp0,
			useFormat,zMode,cacheSize)) return FALSE;
    }
    else {
      /************************************************************************
      * Assumed to be a complete specification of a single CDF.
      ************************************************************************/
      TryToEditCDF(CDFspec,browseOnly,negToPosFp0,useFormat,zMode,cacheSize);
    }
  }
  return TRUE;
}

/******************************************************************************
* EditCDFsMenu.
******************************************************************************/

Logical EditCDFsMenu (CDFspec, browseOnly, negToPosFp0, useFormat, zMode,
		      cacheSize)
char *CDFspec;
Logical browseOnly;
Logical negToPosFp0;
Logical useFormat;
long zMode;
long cacheSize;
{
  CDFstatus status;
  int nCDFs;
  char **dirS;
  char **CDFs;
  char CDFdir[DU_MAX_DIR_LEN+1];
  char CDFname[DU_MAX_NAME_LEN+1];
  char CDFpathT[DU_MAX_PATH_LEN+1];
  static char label[16+DU_MAX_PATH_LEN+2+1];
  AOSs1 (header, BLANKSforHEADER)
  AOSs2 (trailer, "Edit: ________   Create: ________   Help: ________",
		  "Exit: ________   Delete: ________")
  static int exitChars[] = { SELECTkey_EDIT, EXITkey_FSI,
			     CREATECDFkey_EDIT, DELETECDFkey_EDIT,
			     HELPkey_FSI, NUL };
  STATIC_ struct ItemWindowStruct IW = {
     2, 12, CDFs_NAME_LEN+2, label, 1, header, 0, NULL, 0, NULL, NULL,
     NULL, 11, 2, trailer, exitChars, REFRESHkey_FSI, TRUE, NSkey_FSI,
     PSkey_FSI
  };

  EncodeKeyDefinitions (2, trailer, SELECTkey_EDIT, CREATECDFkey_EDIT,
			HELPkey_FSI, EXITkey_FSI, DELETECDFkey_EDIT);
  ParsePath (CDFspec, CDFdir, CDFname);
  BuildCDFsMenu (CDFspec, &nCDFs, &dirS, &CDFs, &IW);
  ItemWindow (NEWiw, &IW, 0);

  for (;;) {
     ItemWindow (READiw, &IW);
     switch (IW.key) {
       /***********************************************************************
       * Edit currently selected CDF.  The CDFs menu is rebuild/updated in
       * case the CDF was deleted.  When the CDFs menu is updated, the new
       * current item is set to the old current item (or the last item in
       * case more than one CDF was deleted [possibly by another user]).
       * If the CDF was deleted, the new current item should be the CDF
       * that followed it in the list (unless it was the last CDF in which
       * case the new current item will be the last CDF in the new list).
       ***********************************************************************/
       case SELECTkey_EDIT:
	 if (IW.nItems == 0) {
	   char tempS[MAX_MESSAGE_TEXT_LEN];
	   strcpyX (tempS, "No CDF selected (no CDFs exist for this ",
		    MAX_MESSAGE_TEXT_LEN);
	   strcatX (tempS, "specification).", MAX_MESSAGE_TEXT_LEN);
	   InputErrorWindow (tempS, FALSE);
	 }
	 else {
	   CDFid id;
	   long readonlyMode = (browseOnly ? READONLYon : READONLYoff);
	   long negToPosFp0Mode = (negToPosFp0 ? NEGtoPOSfp0on :
						 NEGtoPOSfp0off);
	   strcpyX (CDFpathT, dirS[IW.itemN], DU_MAX_PATH_LEN);
	   AppendToDir (CDFpathT, CDFs[IW.itemN]);
	   status = CDFlib (OPEN_, CDF_, CDFpathT, &id,
			    SELECT_, CDF_READONLY_MODE_, readonlyMode,
				     CDF_zMODE_, zMode,
				     CDF_NEGtoPOSfp0_MODE_,negToPosFp0Mode,
			    NULL_);
	   ReportStatus (status);
	   if (StatusOK(status)) {
	     ItemWindow (UNDISPLAYiw, &IW);
	     EditCDF (CDFs[IW.itemN], browseOnly, useFormat, cacheSize);
	     FreeCDFsMenu (dirS, CDFs, &IW);
	     BuildCDFsMenu (CDFspec, &nCDFs, &dirS, &CDFs, &IW);
	     ItemWindow (UPDATEiw, &IW, MINIMUM(IW.itemN,IW.nItems-1));
	     ItemWindow (REDISPLAYiw, &IW);
	   }
	 }
	 break;
       /***********************************************************************
       * Create a CDF.
       ***********************************************************************/
       case CREATECDFkey_EDIT:
	 if (!browseOnly) {
	   char CDFnameT[DU_MAX_NAME_LEN+1];
	   int itemN;
	   ItemWindow (UNDISPLAYiw, &IW);
	   strcpyX (CDFnameT, "", DU_MAX_NAME_LEN);
	   if (CreateCDF(CDFdir,CDFnameT,zMode,browseOnly,
			 useFormat,negToPosFp0,cacheSize)) {
	     FreeCDFsMenu (dirS, CDFs, &IW);
	     BuildCDFsMenu (CDFspec, &nCDFs, &dirS, &CDFs, &IW);
	     itemN = IndexInList (CDFnameT, nCDFs, CDFs);
	     ItemWindow (UPDATEiw, &IW, BOO(itemN < 0,0,itemN));
	   }
	   ItemWindow (REDISPLAYiw, &IW);
	 }
	 else
	   InputErrorWindow ("Creating a CDF is not allowed while browsing.",
			     FALSE);
	 break;
       /***********************************************************************
       * Delete currently selected CDF.  When the CDFs menu is updated, the
       * new current item is set to the old current item (or the last item
       * in case more than one CDF was deleted [possibly by another user]).
       * The new current item should be the CDF (in the list) that followed
       * the CDF that was deleted (unless it was the last CDF in which case
       * the new current item will be the last CDF in the new list).
       ***********************************************************************/
       case DELETECDFkey_EDIT:
	 if (!browseOnly) {
	   if (IW.nItems == 0) {
	     char tempS[MAX_MESSAGE_TEXT_LEN+1];
	     strcpyX (tempS, "No CDF selected (no CDFs exist for this ",
		      MAX_MESSAGE_TEXT_LEN);
	     strcatX (tempS, "specification).", MAX_MESSAGE_TEXT_LEN);
	     InputErrorWindow (tempS, FALSE);
	   }
	   else {
	     char delim, question[DU_MAX_NAME_LEN+15+1];
	     delim = PickDelimiter (CDFs[IW.itemN],strlen(CDFs[IW.itemN]));
	     sprintf (question, "Delete CDF %c%s%c ?", delim,
		      CDFs[IW.itemN], delim);
	     ItemWindow (UNDISPLAYiw, &IW);
	     if (ConfirmWindow(7,question,NULL,FALSE,DELETECDFhelpID)) {
	       CDFid id; CDFstatus status;
	       strcpyX (CDFpathT, dirS[IW.itemN], DU_MAX_PATH_LEN);
	       AppendToDir (CDFpathT, CDFs[IW.itemN]);
	       status = CDFlib (OPEN_, CDF_, CDFpathT, &id,
				DELETE_, CDF_,
				NULL_);
	       ReportStatus (status);
	       if (StatusOK(status)) {
		 FreeCDFsMenu (dirS, CDFs, &IW);
		 BuildCDFsMenu (CDFspec, &nCDFs, &dirS, &CDFs, &IW);
		 ItemWindow (UPDATEiw, &IW, MINIMUM(IW.itemN,IW.nItems-1));
	       }
	     }
	     ItemWindow (REDISPLAYiw, &IW);
	   }
	 }
	 else
	   InputErrorWindow ("Deleting a CDF is not allowed while browsing.",
			     FALSE);
	 break;
       /***********************************************************************
       * Display online help.
       ***********************************************************************/
       case HELPkey_FSI:
	 OnlineHelpWindow (ilhFile, CDFShelpID);
	 break;
       /***********************************************************************
       * Exit.
       ***********************************************************************/
       case EXITkey_FSI:
	 ItemWindow (DELETEiw, &IW);
	 FreeCDFsMenu (dirS, CDFs, &IW);
	 return TRUE;
     }
  }
}

/******************************************************************************
* BuildCDFsMenu.
******************************************************************************/

void BuildCDFsMenu (CDFspec, nCDFs, dirS, CDFs, IW)
char *CDFspec;
int *nCDFs;
char ***dirS;
char ***CDFs;
struct ItemWindowStruct *IW;
{
  int CDFn;

  sprintf (IW->label, " Specification \"%s\" ", CDFspec);
  *nCDFs = CDFdirList (CDFspec, dirS, CDFs);
  sprintf (IW->hLines[0], "%d CDF%s", *nCDFs, (*nCDFs == 1 ? "" : "s"));

  if (*nCDFs > 0) {
    AllocIW (IW, *nCDFs, *nCDFs, CDFs_NAME_LEN, FatalError);
    for (CDFn = 0; CDFn < *nCDFs; CDFn++) {
       strcpyX (IW->iLines[CDFn], (*CDFs)[CDFn], CDFs_NAME_LEN);
       IW->iLineNs[CDFn] = CDFn;
       IW->iCols[CDFn] = 0;
       IW->iLens[CDFn] = MINIMUM((size_t)CDFs_NAME_LEN,
				 strlen(IW->iLines[CDFn]));
    }
  }
  else {
    IW->NiLines = 0;
    IW->nItems = 0;
  }

  return;
}

/******************************************************************************
* FreeCDFsMenu.
******************************************************************************/

void FreeCDFsMenu (dirS, CDFs, IW)
char **dirS;
char **CDFs;
struct ItemWindowStruct *IW;
{
  if (dirS != NULL) FreeMemory (dirS, FatalError);
  if (CDFs != NULL) FreeMemory (CDFs, FatalError);
  FreeIW (IW, FatalError);
  return;
}

/******************************************************************************
* TryToEditCDF.
******************************************************************************/

Logical TryToEditCDF (CDFspec, browseOnly, negToPosFp0, useFormat, zMode,
		      cacheSize)
char *CDFspec;
Logical browseOnly;
Logical negToPosFp0;
Logical useFormat;
long zMode;
long cacheSize;
{
  CDFstatus status; CDFid id;
  char CDFdir[DU_MAX_DIR_LEN+1];
  char CDFname[DU_MAX_NAME_LEN+1];
  long readonlyMode = (browseOnly ? READONLYon : READONLYoff);
  long negToPosFp0Mode = (negToPosFp0 ? NEGtoPOSfp0on : NEGtoPOSfp0off);
  ParsePath (CDFspec, CDFdir, CDFname);
  status = CDFlib (OPEN_, CDF_, CDFspec, &id,
		   SELECT_, CDF_READONLY_MODE_, readonlyMode,
			    CDF_zMODE_, zMode,
			    CDF_NEGtoPOSfp0_MODE_, negToPosFp0Mode,
		   NULL_);
  switch (status) {
    case NO_SUCH_CDF:
      if (!browseOnly) {
	char delim, question[DU_MAX_PATH_LEN+29+1];
	delim = PickDelimiter(CDFspec, strlen(CDFspec));
	sprintf (question, "CDF %c%s%c does not exist.  Create?", delim,
		 CDFspec, delim);
	if (ConfirmWindow(7,question,NULL,TRUE,CREATECDFhelpID))
	  if (!CreateCDF(CDFdir,CDFname,zMode,browseOnly,
			 useFormat,negToPosFp0,cacheSize)) return FALSE;
      }
      else {
	char tempS[MAX_MESSAGE_TEXT_LEN+1];
	strcpyX (tempS, "CDF does not exist (and creating a CDF is not ",
		 MAX_MESSAGE_TEXT_LEN);
	strcatX (tempS, "allowed while browsing).", MAX_MESSAGE_TEXT_LEN);
	InputErrorWindow (tempS, TRUE);
      }
      break;
    default:
      ReportStatus (status);
      if (StatusOK(status)) {
	if (!EditCDF(CDFname,browseOnly,useFormat,cacheSize)) return FALSE;
      }
      break;
  }
  return TRUE;
}

/******************************************************************************
* CreateCDF.
******************************************************************************/

Logical CreateCDF (CDFdir, CDFname, zMode, browseOnly, useFormat, negToPosFp0,
		   cacheSize)
char *CDFdir;           /* Directory in which to create CDF. */
char *CDFname;          /* If null-string (""), then prompt for name.  Returns
			   name entered here. */
long zMode;             /* The zMode to select after CDF is created. */
Logical browseOnly;     /* TRUE if in a browsing only mode - this is simply
			   passed through to `EditCDF' (`EditCDF' is called
			   from other places where this could be TRUE). */
Logical useFormat;      /* TRUE if FORMAT attribute should be used. */
Logical negToPosFp0;    /* TRUE if conversion of -0.0 to +0.0 should be
			   selected after CDF is created. */
long cacheSize;         /* Number of cache buffers for `.cdf' file. */
{
  CDFstatus status; CDFid id;
  long numDims, dimSizes[CDF_MAX_DIMS];
  long negToPosFp0mode = (negToPosFp0 ? NEGtoPOSfp0on : NEGtoPOSfp0off);
  char CDFpathT[DU_MAX_PATH_LEN+1], delim;
  AOSs1 (trailer, "Enter: ________   Exit: ________   Help: ________")
  static int exitChars[] = { ENTERkey_EDIT, EXITkey_FSI, HELPkey_FSI, NUL };
  static char *headerDim[] = {
    "Enter rVariable dimensionality...",
    "Syntax: <numDims>:[<dimSize1>,<dimSize2>,...,<dimSizeN>]",
    "Examples: 0:[], 1:[5], 2:[100,200], 3:[10,20,30]"
  };
  static char valueDim[MAX_DIMENSIONALITY_LEN+1];
  static char labelDim[8+DU_MAX_NAME_LEN+1];
  STATIC_ struct PromptWindowStruct PWdim = {
    labelDim, 7, 10, 60, 3, headerDim, MAX_DIMENSIONALITY_LEN, valueDim,
    1, trailer, exitChars, REFRESHkey_FSI, SOLkey_FSI, EOLkey_FSI,
    INSERTorOVERkey_FSI
  };

  EncodeKeyDefinitions (1, trailer, ENTERkey_EDIT, EXITkey_FSI, HELPkey_FSI);

  if (NULstring(CDFname)) {
    static char *header[] = {
      "Enter CDF name (without delimiters)...",
      "Syntax: <char1><char2>...<charN>",
      "Example: D104B"
    };
    static char label[13+1+DU_MAX_DIR_LEN+1+1+1];
    STATIC_ struct PromptWindowStruct PW = {
      label, 7, 4, 70, 3, header, DU_MAX_NAME_LEN, NULL, 1, trailer,
      exitChars, REFRESHkey_FSI, SOLkey_FSI, EOLkey_FSI,
      INSERTorOVERkey_FSI
    };
    char dirT[DU_MAX_DIR_LEN+1];
    strcpyX (dirT, (NULstring(CDFdir) ? CURRENTDIRECTORY : CDFdir),
	     DU_MAX_DIR_LEN);
    delim = PickDelimiter (dirT, strlen(dirT));
    sprintf (PW.label, " Creating in %c%s%c ", delim, dirT, delim);
    PW.value = CDFname;
    PromptWindow (NEWpw, &PW, 0, (Logical) TRUE);
    for (;;) {
       if (EnterPW(&PW,CDFNAMEhelpID))
	 if (strlen(CDFname) > (size_t) 0) {
#if defined(vms) || defined(dos)
	   Uppercase (CDFname);
#endif
	   break;
	 }
	 else
	   InputErrorWindow ("Illegal CDF name.", FALSE);
       else {
	 PromptWindow (DELETEpw, &PW);
	 return TRUE;
       }
    }
    PromptWindow (DELETEpw, &PW);
  }

  strcpyX (CDFpathT, CDFdir, DU_MAX_PATH_LEN);
  AppendToDir (CDFpathT, CDFname);

  strcpyX (PWdim.value, "", MAX_DIMENSIONALITY_LEN);
  delim = PickDelimiter (CDFname, strlen(CDFname));
  sprintf (labelDim, " CDF %c%s%c ", delim, CDFname, delim);
  PromptWindow (NEWpw, &PWdim, 0, (Logical) TRUE);
  for (;;) {
     if (EnterPW(&PWdim,RDIMhelpID)) {
       if (DecodeDimensionality(PWdim.value,&numDims,dimSizes))
	 break;
       else
	 InputErrorWindow ("Illegal dimensionality.", FALSE);
     }
     else {
       PromptWindow (DELETEpw, &PWdim);
       return TRUE;
     }
  }
  PromptWindow (DELETEpw, &PWdim);

  status = CDFlib (CREATE_, CDF_, CDFpathT, numDims, dimSizes, &id,
		   SELECT_, CDF_zMODE_, zMode,
			    CDF_NEGtoPOSfp0_MODE_, negToPosFp0mode,
		   NULL_);
  ReportStatus (status);
  if (!StatusOK(status)) return FALSE;

  return EditCDF (CDFname, browseOnly, useFormat, cacheSize);
}

/******************************************************************************
* EditCDF.
******************************************************************************/

Logical EditCDF (CDFname, browseOnly, useFormat, cacheSize)
char *CDFname;
Logical browseOnly;
Logical useFormat;
long cacheSize;
{
   CDFstatus status;
   AOSs3 (hLines, BLANKSforHEADER, BLANKSforHEADER, BLANKSforHEADER)
   static char *iLines[] = {
     "<edit rVars> <edit zVars> <edit gAttrs> <edit vAttrs>",
     "<change format>  <change encoding>  <change majority>"
   };
   AOSs2 (tLines, "Select: ________   Delete: ________",
		  "Exit:   ________   Help:   ________")
   static int iLineNs[] = { 0, 0, 0, 0, 1, 1, 1 };
   static int iCols[] = { 0, 13, 26, 40, 0, 17, 36 };
   static int iLens[] = { 12, 12, 13, 13, 15, 17, 17 };
   static int exitChars[] = { SELECTkey_EDIT, EXITkey_FSI, DELETECDFkey_EDIT,
			      HELPkey_FSI, zMODE0key_EDIT, zMODE1key_EDIT,
			      zMODE2key_EDIT, NUL };
   static char label[6+DU_MAX_NAME_LEN+2+1];
   STATIC_ struct ItemWindowStruct IW = {
      2, 12, 55, label, 3, hLines, 2, iLines, 7, iLineNs, iCols, iLens, 2,
      2, tLines, exitChars, REFRESHkey_FSI, FALSE
   };

   /***************************************************************************
   * Try to set number of cache buffers for `.cdf' file.
   ***************************************************************************/

   status = CDFlib (SELECT_, CDF_CACHESIZE_, cacheSize,
		    NULL_);
   ReportStatus (status);

   /***************************************************************************
   * Build main menu.
   ***************************************************************************/

   EncodeKeyDefinitions (2, tLines, SELECTkey_EDIT, DELETECDFkey_EDIT,
			 EXITkey_FSI, HELPkey_FSI);
   if (!BuildCDFmenu(CDFname,&IW)) return FALSE;

   /***************************************************************************
   * Display menu/process keystrokes.
   ***************************************************************************/

   ItemWindow (NEWiw, &IW, 0);
   ItemWindow (READiw, &IW);
   for (;;) {
     switch (IW.key) {
       /***********************************************************************
       * Perform selected function.
       ***********************************************************************/
       case SELECTkey_EDIT:
	 switch (IW.itemN) {
	   /*******************************************************************
	   * Edit rVariables.
	   *******************************************************************/
	   case 0:
	     ItemWindow (UNDISPLAYiw, &IW);
	     if (!EditVars(FALSE,CDFname,useFormat)) return FALSE;
	     if (!BuildCDFmenu(CDFname,&IW)) return FALSE;
	     ItemWindow (UPDATEiw, &IW, IW.itemN);
	     ItemWindow (REDISPLAYiw, &IW);
	     break;
	   /*******************************************************************
	   * Edit zVariables.
	   *******************************************************************/
	   case 1:
	     ItemWindow (UNDISPLAYiw, &IW);
	     if (!EditVars(TRUE,CDFname,useFormat)) return FALSE;
	     if (!BuildCDFmenu(CDFname,&IW)) return FALSE;
	     ItemWindow (UPDATEiw, &IW, IW.itemN);
	     ItemWindow (REDISPLAYiw, &IW);
	     break;
	   /*******************************************************************
	   * Edit gAttributes.
	   *******************************************************************/
	   case 2:
	     ItemWindow (UNDISPLAYiw, &IW);
	     if (gAttrsAndEntries) {
	       if (!EditAttrs(TRUE,CDFname)) return FALSE;
	     }
	     else {
	       if (!EditAttrsX(TRUE,CDFname)) return FALSE;
	     }
	     if (!BuildCDFmenu(CDFname,&IW)) return FALSE;
	     ItemWindow (UPDATEiw, &IW, IW.itemN);
	     ItemWindow (REDISPLAYiw, &IW);
	     break;
	   /*******************************************************************
	   * Edit vAttributes.
	   *******************************************************************/
	   case 3:
	     ItemWindow (UNDISPLAYiw, &IW);
	     if (vAttrsAndEntries) {
	       if (!EditAttrs(FALSE,CDFname)) return FALSE;
	     }
	     else {
	       if (!EditAttrsX(FALSE,CDFname)) return FALSE;
	     }
	     if (!BuildCDFmenu(CDFname,&IW)) return FALSE;
	     ItemWindow (UPDATEiw, &IW, IW.itemN);
	     ItemWindow (REDISPLAYiw, &IW);
	     break;
	   /*******************************************************************
	   * Change format:
	   *******************************************************************/
	   case 4: {
	     long format; int itemN;
	     static char *header[] = { "Select new format..." };
	     AOSs2 (trailer, "Select: ________   Exit: ________",
			     "Help:   ________")
	     static char *items[] = { "SINGLE", "MULTI" };
	     static int iLineNs[] = { 0, 1 };
	     static int iCols[] = { 0, 0 };
	     static int iLens[] = { 6, 5 };
	     static int exitChars[] = { SELECTkey_EDIT, EXITkey_FSI,
					HELPkey_FSI, NUL };
	     STATIC_ struct ItemWindowStruct IWt = {
		8, 23, 35, NULL, 1, header, 2, items, 2, iLineNs, iCols,
		iLens, 2, 2, trailer, exitChars, REFRESHkey_FSI, FALSE
	     };
	     EncodeKeyDefinitions (2, trailer, SELECTkey_EDIT, EXITkey_FSI,
				   HELPkey_FSI);
	     status = CDFlib (GET_, CDF_FORMAT_, &format,
			      NULL_);
	     ReportStatus (status);
	     if (StatusBAD(status)) return FALSE;
	     for (itemN = 0; itemN < 2; itemN++) {
		if (!strcmp(FormatToken(format),IWt.iLines[itemN])) break;
	     }
	     ItemWindow (NEWiw, &IWt, itemN);
	     for (;;) {
		if (EnterIW(&IWt,FORMAThelpID)) {
		  format = WhichFormat(items[IWt.itemN]);
		  status = CDFlib (PUT_, CDF_FORMAT_, format,
				   NULL_);
		  ReportStatus (status);
		  if (StatusOK(status)) {
		    ItemWindow (UNDISPLAYiw, &IWt);
		    BuildCDFmenu (CDFname, &IW);
		    ItemWindow (UPDATEiw, &IW, IW.itemN);
		    break;
		  }
		}
		else
		  break;
	     }
	     ItemWindow (DELETEiw, &IWt);
	     break;
	   }
	   /*******************************************************************
	   * Change encoding:
	   *******************************************************************/
	   case 5: {
	     long encoding; int itemN;
	     static char *header[] = { "Select new encoding..." };
	     AOSs2 (trailer, "Select: ________   Exit: ________",
			     "Help:   ________")
	     static char *items[] = { "HOST        SGi        DECSTATION",
				      "NETWORK     SUN        ALPHAOSF1",
				      "NeXT        IBMRS      ALPHAVMSd",
				      "HP          VAX        ALPHAVMSg",
				      "IBMPC       MAC" };
	     static int iLineNs[] = { 0,0,0,1,1,1,2,2,2,3,3,3,4,4 };
	     static int iCols[] = { 0,12,23,0,12,23,0,12,23,0,12,23,0,12 };
	     static int iLens[] = { 4,3,10,7,3,9,4,5,9,2,3,9,5,3 };
	     static int exitChars[] = { SELECTkey_EDIT, EXITkey_FSI,
					HELPkey_FSI, NUL };
	     STATIC_ struct ItemWindowStruct IWt = {
		8, 23, 35, NULL, 1, header, 5, items, 14, iLineNs, iCols,
		iLens, 5, 2, trailer, exitChars, REFRESHkey_FSI, FALSE
	     };
	     EncodeKeyDefinitions (2, trailer, SELECTkey_EDIT, EXITkey_FSI,
				   HELPkey_FSI);
	     status = CDFlib (GET_, CDF_ENCODING_, &encoding,
			      NULL_);
	     ReportStatus (status);
	     if (StatusBAD(status)) return FALSE;
	     for (itemN = 0; itemN < 14; itemN++) {
		if (!strncmp(EncodingToken(encoding),
			     &(IWt.iLines[IWt.iLineNs[itemN]]
					 [IWt.iCols[itemN]]),
			     IWt.iLens[itemN])) break;
	     }
	     ItemWindow (NEWiw, &IWt, itemN);
	     for (;;) {
		if (EnterIW(&IWt,ENCODINGhelpID)) {
		  encoding = WhichEncoding(&(items[iLineNs[IWt.itemN]]
						  [iCols[IWt.itemN]]));
		  status = CDFlib (PUT_, CDF_ENCODING_, encoding,
				   NULL_);
		  ReportStatus (status);
		  if (StatusOK(status)) {
		    ItemWindow (UNDISPLAYiw, &IWt);
		    BuildCDFmenu (CDFname, &IW);
		    ItemWindow (UPDATEiw, &IW, IW.itemN);
		    break;
		  }
		}
		else
		  break;
	     }
	     ItemWindow (DELETEiw, &IWt);
	     break;
	   }
	   /*******************************************************************
	   * Change majority:
	   *******************************************************************/
	   case 6: {
	     long majority; int itemN;
	     static char *header[] = { "Select new majority..." };
	     AOSs2 (trailer, "Select: ________   Exit: ________",
			     "Help:   ________")
	     static char *items[] = { "ROW", "COLUMN" };
	     static int iLineNs[] = { 0, 1 };
	     static int iCols[] = { 0, 0 };
	     static int iLens[] = { 3, 6 };
	     static int exitChars[] = { SELECTkey_EDIT, EXITkey_FSI,
					HELPkey_FSI, NUL };
	     STATIC_ struct ItemWindowStruct IWt = {
		8, 23, 35, NULL, 1, header, 2, items, 2, iLineNs, iCols,
		iLens, 2, 2, trailer, exitChars, REFRESHkey_FSI, FALSE
	     };
	     EncodeKeyDefinitions (2, trailer, SELECTkey_EDIT, EXITkey_FSI,
				   HELPkey_FSI);
	     status = CDFlib (GET_, CDF_MAJORITY_, &majority,
			      NULL_);
	     ReportStatus (status);
	     if (StatusBAD(status)) return FALSE;
	     for (itemN = 0; itemN < 2; itemN++) {
		if (!strcmp(MajorityToken(majority),IWt.iLines[itemN])) break;
	     }
	     ItemWindow (NEWiw, &IWt, itemN);
	     for (;;) {
		if (EnterIW(&IWt,MAJORITYhelpID)) {
		  long majority = WhichMajority(items[IWt.itemN]);
		  status = CDFlib (PUT_, CDF_MAJORITY_, majority,
				   NULL_);
		  ReportStatus (status);
		  if (StatusOK(status)) {
		    ItemWindow (UNDISPLAYiw, &IWt);
		    BuildCDFmenu (CDFname, &IW);
		    ItemWindow (UPDATEiw, &IW, IW.itemN);
		    break;
		  }
		}
		else
		  break;
	     }
	     ItemWindow (DELETEiw, &IWt);
	     break;
	   }
	 }

	 break;

       /***********************************************************************
       * Delete CDF.  Before attempting to delete CDF, turn off read-only mode
       * (in case it was on).
       ***********************************************************************/
       case DELETECDFkey_EDIT:
	 if (!browseOnly) {
	   char delim, question[DU_MAX_NAME_LEN+15+1];
	   delim = PickDelimiter (CDFname, strlen(CDFname));
	   sprintf (question, "Delete CDF %c%s%c ?", delim, CDFname, delim);
	   ItemWindow (UNDISPLAYiw, &IW);
	   if (ConfirmWindow(7,question,NULL,FALSE,DELETECDFhelpID)) {
	     status = CDFlib (SELECT_, CDF_READONLY_MODE_, READONLYoff,
			      DELETE_, CDF_,
			      NULL_);
	     ReportStatus (status);
	     ItemWindow (DELETEiw, &IW);
	     return StatusOK (status);
	   }
	   ItemWindow (REDISPLAYiw, &IW);
	 }
	 else
	   InputErrorWindow ("Deleting a CDF is not allowed while browsing.",
			     FALSE);
	 break;

       /***********************************************************************
       * zMode selection keys.
       ***********************************************************************/
       case zMODE0key_EDIT:
       case zMODE1key_EDIT:
       case zMODE2key_EDIT: {
	 long zMode;
	 switch (IW.key) {
	   case zMODE0key_EDIT: zMode = zMODEoff; break;
	   case zMODE1key_EDIT: zMode = zMODEon1; break;
	   case zMODE2key_EDIT: zMode = zMODEon2; break;
	 }
	 status = CDFlib (SELECT_, CDF_zMODE_, zMode,
			  NULL_);
	 ReportStatus (status);
	 if (StatusOK(status)) {
	   BuildCDFmenu (CDFname, &IW);
	   ItemWindow (UPDATEiw, &IW, IW.itemN);
	 }
	 break;
       }

       /***********************************************************************
       * Display online help.
       ***********************************************************************/
       case HELPkey_FSI:
	 OnlineHelpWindow (ilhFile, CDFhelpID);
	 break;

       /***********************************************************************
       * Exit menu (closing CDF).
       ***********************************************************************/
       case EXITkey_FSI: {
	 if (dumpStatistics) {
	   vSTATS vStats;
	   char temp1[MAX_SCREENLINE_LEN+1], temp2[MAX_SCREENLINE_LEN+1],
		temp3[MAX_SCREENLINE_LEN+1], label[MAX_SCREENLINE_LEN+1];
	   status = CDFlib (CLOSE_, CDFwithSTATS_, &vStats,
			    NULL_);
	   ReportStatus (status);
	   ItemWindow (DELETEiw, &IW);
	   strcpyX (label, "\"", MAX_SCREENLINE_LEN);
	   strcatX (label, CDFname, MAX_SCREENLINE_LEN);
	   strcatX (label, "\"", MAX_SCREENLINE_LEN);
	   BuildStatistics (label, &vStats, temp1, temp2, temp3);
	   InfoWindow (temp1, temp2, temp3, TRUE);
	 }
	 else {
	   status = CDFlib (CLOSE_, CDF_,
			    NULL_);
	   ReportStatus (status);
	   ItemWindow (DELETEiw, &IW);
	 }
	 return StatusOK (status);
       }
     }

     ItemWindow (READiw, &IW);
   }
}

/******************************************************************************
* BuildCDFmenu.
******************************************************************************/

Logical BuildCDFmenu (CDFname, IW)
char *CDFname;
struct ItemWindowStruct *IW;
{
  CDFstatus status;
  long format, encoding, majority;
  long nAttrs, NgAttrs, NvAttrs, NrVars, NzVars;
  long version, release, increment;
  int pad;

  sprintf (IW->label, " CDF \"%s\" ", CDFname);

  status = CDFlib (GET_, CDF_FORMAT_, &format,
			 CDF_ENCODING_, &encoding,
			 CDF_MAJORITY_, &majority,
			 CDF_NUMATTRS_, &nAttrs,
			 CDF_NUMgATTRS_, &NgAttrs,
			 CDF_NUMvATTRS_, &NvAttrs,
			 CDF_NUMrVARS_, &NrVars,
			 CDF_NUMzVARS_, &NzVars,
			 CDF_VERSION_, &version,
			 CDF_RELEASE_, &release,
			 CDF_INCREMENT_, &increment,
		   NULL_);
  ReportStatus (status);
  if (StatusBAD(status)) return FALSE;

  sprintf (IW->hLines[0], "  Format:   %s", FormatToken(format));
  pad = MAIN_MENU_1st_HALF_LEN - strlen(IW->hLines[0]);
  if (pad > 0) CatNcharacters (IW->hLines[0], pad, (int) ' ');
  sprintf (&(IW->hLines[0][strlen(IW->hLines[0])]),
	   "Attributes: %ld (%ldg/%ldv)", nAttrs, NgAttrs, NvAttrs);

  sprintf (IW->hLines[1], "  Encoding: %s", EncodingToken(encoding));
  pad = MAIN_MENU_1st_HALF_LEN - strlen(IW->hLines[1]);
  if (pad > 0) CatNcharacters (IW->hLines[1], pad, (int) ' ');
  sprintf (&(IW->hLines[1][strlen(IW->hLines[1])]),
	   "Variables:  %ld (%ldr/%ldz)", NrVars + NzVars, NrVars, NzVars);

  sprintf (IW->hLines[2], "  Majority: %s", MajorityToken(majority));
  pad = MAIN_MENU_1st_HALF_LEN - strlen(IW->hLines[2]);
  if (pad > 0) CatNcharacters (IW->hLines[2], pad, (int) ' ');
  sprintf (&(IW->hLines[2][strlen(IW->hLines[2])]),
	   "Version:    %ld.%ld.%ld", version, release, increment);

  return TRUE;
}

/******************************************************************************
* PromptForSpec.
*     Prompt for the CDF(s) specification.  Returns TRUE if a valid CDF(s)
* specification was entered; FALSE otherwise.
******************************************************************************/

Logical PromptForSpec (CDFspec)
char CDFspec[DU_MAX_PATH_LEN+1];
{
  static char *header[] = {
    "Enter CDF(s) specification (without delimiters)...",
    "Syntax: <char1><char2>...<charN>",
#if defined(vms)
    "Examples: RAIN2, RAIN*, [-.SAMPLES], USER5:[CDF1]IJ01A"
#endif
#if defined(unix) || defined(posixSHELL)
    "Examples: rain2, rain*, ../samples, ~/CDFs/ij01a"
#endif
#if defined(dos)
    "Examples: RAIN2, RAIN*, ..\\SAMPLES, B:\\CDF1\\IJ01A"
#endif
#if defined(mac)
    "Examples: cacsst1, cac*, Boot:CDFs:, :samples"
#endif
  };
  AOSs1 (trailer, "Enter: ________   Exit: ________  Help: ________")
  static int exitChars[] = { ENTERkey_EDIT, EXITkey_FSI, HELPkey_FSI, NUL };
  static char value[DU_MAX_PATH_LEN+1];
  STATIC_ struct PromptWindowStruct PW = {
    " Specification Prompt ", 5, 5, 70, 3, header, DU_MAX_PATH_LEN, value,
    1, trailer, exitChars, REFRESHkey_FSI, SOLkey_FSI, EOLkey_FSI,
    INSERTorOVERkey_FSI
  };
  EncodeKeyDefinitions (1, trailer, ENTERkey_EDIT, EXITkey_FSI, HELPkey_FSI);
  strcpyX (PW.value, CDFspec, DU_MAX_PATH_LEN);
  PromptWindow (NEWpw, &PW, (int) strlen(PW.value), (Logical) TRUE);
  for (;;) {
     if (EnterPW(&PW,SPEChelpID))
       if (strlen(PW.value) > (size_t) 0) {
	 strcpyX (CDFspec, PW.value, DU_MAX_PATH_LEN);
	 PromptWindow (DELETEpw, &PW);
	 return TRUE;
       }
       else
	 InputErrorWindow ("Illegal CDF(s) specification.", FALSE);
     else {
       PromptWindow (DELETEpw, &PW);
       return FALSE;
     }
  }
}

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

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

  static Logical browseOnly = DEFAULTbrowseEDIT;
  static Logical useFormat = DEFAULTformatEDIT;
  static Logical negToPos = DEFAULT_NEGtoPOSfp0;
  static Logical promptFor = DEFAULTpromptEDIT;
  static Logical reportInfos = REPORTinfosDEFAULT;
  static Logical reportWarns = REPORTwarningsDEFAULT;
  static Logical reportErrors = REPORTerrorsDEFAULT;
  static Logical dispStats = DEFAULTstatsEDIT;
  static Logical gWith = DEFAULTgWithEDIT;
  static Logical vWith = DEFAULTgWithEDIT;
  static int zModeSrc = DEFAULTzModeCVT;
  static Str255 cacheText = "\p";
  static Str255 CDFtext = "\p";

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

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

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

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

  if (browseOnly) SetCtlValue (controlHs[BROWSEin], 1);
  if (useFormat) SetCtlValue (controlHs[FORMATin], 1);
  if (negToPos) SetCtlValue (controlHs[NEGZin], 1);
  if (promptFor) SetCtlValue (controlHs[PROMPTin], 1);
  if (reportInfos) SetCtlValue (controlHs[INFOin], 1);
  if (reportWarns) SetCtlValue (controlHs[WARNin], 1);
  if (reportErrors) SetCtlValue (controlHs[ERRORin], 1);
  if (dispStats) SetCtlValue (controlHs[STATSin], 1);
  if (gWith) SetCtlValue (controlHs[gWITHin], 1);
  if (vWith) SetCtlValue (controlHs[vWITHin], 1);

  SetCtlValue (controlHs[ZMODEinBASE+zModeSrc], 1);
  
  SetDItem (dialogP, (short) ODBin, (short) userItem,
	    (Handle) OutlineDefaultButton, &iRect);

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

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

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

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

	browseOnly = GetCtlValue (controlHs[BROWSEin]);
	useFormat = GetCtlValue (controlHs[FORMATin]);
	negToPos = GetCtlValue (controlHs[NEGZin]);
	promptFor = GetCtlValue (controlHs[PROMPTin]);
	reportInfos = GetCtlValue (controlHs[INFOin]);
	reportWarns = GetCtlValue (controlHs[WARNin]);
	reportErrors = GetCtlValue (controlHs[ERRORin]);
	dispStats = GetCtlValue (controlHs[STATSin]);
	gWith = GetCtlValue (controlHs[gWITHin]);
	vWith = GetCtlValue (controlHs[vWITHin]);

	for (zModeSrc = 0; zModeSrc < 3; zModeSrc++) {
	   if (GetCtlValue(controlHs[ZMODEinBASE+zModeSrc])) break;
	}
	
	/**********************************************************************
	* Build argc/argv.
	**********************************************************************/

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

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

	MAKEbooARGv (argV, n, browseOnly, "-browse", "-nobrowse")
	MAKEbooARGv (argV, n, useFormat, "-format", "-noformat")
	MAKEbooARGv (argV, n, negToPos, "-neg2posfp0", "-noneg2posfp0")
	MAKEbooARGv (argV, n, promptFor, "-prompt", "-noprompt")
	MAKEbooARGv (argV, n, dispStats, "-statistics", "-nostatistics")
	MAKEbooARGv (argV, n, gWith, "-gwithentries", "-nogwithentries")
	MAKEbooARGv (argV, n, vWith, "-vwithentries", "-novwithentries")

	MAKEstrARGv (argV, n, "-zmode")
	sprintf (tempS1, "%d", zModeSrc);
	MAKEstrARGv (argV, n, tempS1)

	MAKEstrARGv (argV, n, "-report")
	MAKEstrARGv (argV, n, StatusCodeReportOptions(reportErrors,
						      reportWarns,
						      reportInfos))

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

	/**********************************************************************
	* Close the dialog and return.
	**********************************************************************/
	CloseDialog (dialogP);
	return TRUE;
      }
      /************************************************************************
      * 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 (existing CDF).
      ************************************************************************/
      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 CDF specification (new CDF).
      *     The cursor is set because `StandardPutFile' leaves the cursor as
      * an iBeam (instead of returning it to what it was).
      ************************************************************************/
      case CDFNEWin: {
	StandardFileReply CDFreply;
	char CDFpath[DU_MAX_PATH_LEN+1];
	char prompt[] = "Enter CDF name:";
	StandardPutFile (CtoPstr(prompt), CtoPstr(""), &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);
	}
	SetCursor (&(qd.arrow));
	break;
      }
      /************************************************************************
      * Check boxes.
      ************************************************************************/
      case BROWSEin:
      case FORMATin:
      case INFOin:
      case WARNin:
      case ERRORin:
      case NEGZin:
      case PROMPTin:
      case STATSin:
      case gWITHin:
      case vWITHin:
	SetCtlValue (controlHs[itemN], BOO(GetCtlValue(controlHs[itemN]),0,1));
	break;
      /************************************************************************
      * Radio buttons.
      ************************************************************************/
      case ZMODEinBASE+0:
      case ZMODEinBASE+1:
      case ZMODEinBASE+2:
	for (i = 0; i < 3; i++) SetCtlValue (controlHs[ZMODEinBASE+i], 0);
	SetCtlValue (controlHs[itemN], 1);
	break;
    }
  }
}
#endif
