/******************************************************************************
* Copyright 1996-2014 United States Government as represented by the
* Administrator of the National Aeronautics and Space Administration.
* All Rights Reserved.
******************************************************************************/
/******************************************************************************
*
*  NSSDC/CDF                                    CDFedit, auxiliary routines.
*
*  Version 1.4b, 14-Dec-97, Hughes STX.
*
*  Modification history:
*
*   V1.0  19-Nov-93, 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 23-Jan-95, J Love     IRIX 6.x (64-bit).
*   V1.1b 28-Feb-95, J Love     Pass `char' as `int'.
*   V1.2  21-Mar-95, J Love     POSIX.
*   V1.2a 18-Apr-95, J Love     More POSIX.
*   V1.3   6-Sep-95, J Love     CDFexport-related changes.  FSI key
*                               definitions.
*   V1.4  26-Aug-96, J Love     CDF V2.6.
*   V1.4a 21-Feb-97, J Love	Removed RICE.
*   V1.4b 14-Dec-97, J Love	Added ALPHAVMSi encoding.
*   V3.3  10-Apr-09, M Liu      Changed "MAC" to "PPC" for encoding.
*
******************************************************************************/

#include "cdfedit.h"

/******************************************************************************
* InitializeScreen.
******************************************************************************/

void InitializeScreen () {
  create_pasteboard ();
  set_cursor_mode (CURSORoff);
  return;
}

/******************************************************************************
* CleanupScreen.
******************************************************************************/

void CleanupScreen () {
  delete_pasteboard (ERASE);
  set_cursor_mode (CURSORon);
  return;
}

/******************************************************************************
* ReportStatus.
******************************************************************************/

Logical ReportStatus (status, center)
CDFstatus status;
Logical center;
{
  if ((StatusINFO(status) && report[INFOs]) ||
      (StatusWARN(status) && report[WARNs]) ||
      (StatusERROR(status) && report[ERRORs])) CDFstatusWindow (status,center);
  return StatusOK(status);
}

/******************************************************************************
* CDFstatusWindow.
******************************************************************************/

void CDFstatusWindow (status, center)
CDFstatus status;
Logical center;
{
   static char text[CDF_STATUSTEXT_LEN+1];
   CDFlib (SELECT_, CDF_STATUS_, status,
	   GET_, STATUS_TEXT_, text,
	   NULL_);
   ProblemWindow (text, center);
   return;
}

/******************************************************************************
* ProblemWindow.
******************************************************************************/

void ProblemWindow (message, center)
char *message;
Logical center;
{
   static int exitChars[] = { NUL };
   static struct EditWindowStruct EW = {
     " Enter any key to acknowledge... ", 0, 0, 0, 0, NULL, NULL, 1, 0,
     NULL, FALSE, TRUE, exitChars, REFRESHkey_FSI, NUL, NUL, NUL, NUL, NUL,
     NUL, NUL, NUL, NUL
   };
   if (center) {
     EW.nColsTotal = MaxInt ((int)(strlen(EW.label) + 4),
			     (int)(strlen(message) + 2));
     EW.ULrow = (SCREEN_HEIGHT - 3) / 2;
     EW.ULcol = (SCREEN_WIDTH - EW.nColsTotal) / 2;
   }
   else {
     EW.nColsTotal = SCREEN_WIDTH;
     EW.ULrow = SCREEN_HEIGHT - 3;
     EW.ULcol = 0;
   }
   EW.eText = message;
   EditWindow (NEWew, &EW, LogicalTRUE);
   EditWindow (BEEPew, &EW);
   EditWindow (READew, &EW);
   EditWindow (DELETEew, &EW);
   return;
}

/******************************************************************************
* MessageWindow.
* 
*   void MessageWindow (char **lineS,   Terminate with a NUL-string ("").
*                       char *label,
*                       Logical block);
*
******************************************************************************/

#if defined(STDARG)
void MessageWindow (char **lineS, ...)
#else
void MessageWindow (va_alist)
va_dcl
#endif
{
#if !defined(STDARG)
  char **lineS;
#endif
  static int exitChars[] = { NUL };
  static struct EditWindowStruct EW = {
    NULL, 0, 0, 0, 0, NULL, NULL, 0, 0, NULL, FALSE, TRUE, exitChars,
    REFRESHkey_FSI, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL
  };
  va_list ap;
#if defined(STDARG)
  va_start (ap, lineS);
#else
  VA_START (ap);
  lineS = va_arg (ap, char **);
#endif
  if (lineS == NULL) {
    EditWindow (DELETEew, &EW);
    cdf_FreeMemory (EW.eText, FatalError);
  }
  else {
    int lineN; size_t textLength;
    char *label = va_arg (ap, char *);
    Logical block = va_arg (ap, Logical);
    EW.nColsTotal = BOO(label == NULL,0,strlen(label)+4);
    for (textLength = 0, lineN = 0; !NULstring(lineS[lineN]); lineN++) {
       size_t length = strlen (lineS[lineN]);
       EW.nColsTotal = MaxInt (EW.nColsTotal, (int) (length + 2));
       textLength += length + 1;
    }
    EW.eText = (char *) cdf_AllocateMemory ((size_t)textLength + 1, FatalError);
    MakeNUL (EW.eText);
    for (lineN = 0; !NULstring(lineS[lineN]); lineN++) {
       strcatX (EW.eText, lineS[lineN], textLength);
       strcatX (EW.eText, "\n", textLength);
    }
    EW.NeRows = lineN;
    EW.label = label;
    EW.ULrow = 5;
    EW.ULcol = (SCREEN_WIDTH - EW.nColsTotal) / 2;
    EditWindow (NEWew, &EW, LogicalTRUE);
    if (block) EditWindow (READew, &EW);
  }
  va_end (ap);
  return;
}

/******************************************************************************
* ConfirmWindow.
******************************************************************************/

Logical ConfirmWindow (rowN, width, question1, question2, yesInitial, helpId)
int rowN;
int width;
char *question1;
char *question2;        /* If NULL, a one line question. */
Logical yesInitial;     /* If TRUE, <YES> is initial current item. */
int helpId;
{
  static char label[] = " Confirmation ";
  static char *header[] = { NULL, NULL };
  AOSs1 (trailer, "Select: ________   Exit: ________   Help: ________")
  static char *items[] = {
    "",
    "                  <Yes>                              <No>",
    ""
  };
  static int iLineNs[] = { 1, 1 };
  static int iCols[] = { 18, 53 };
  static int iLens[] = { 5, 4 };
  static int exitChars[] = { ENTERkey_FSI, EXITkey_FSI, HELPkey_FSI, NUL };
  static struct ItemWindowStruct IWt = {
    0, 0, 0, label, 0, header, 3, items, 2, iLineNs, iCols, iLens, 3,
    1, trailer, exitChars, REFRESHkey_FSI, FALSE
  };
  Logical answer;
  EncodeKeyDefinitions (1, trailer, ENTERkey_FSI, EXITkey_FSI,
                        HELPkey_FSI);
  IWt.hLines[0] = question1;
  IWt.NhLines = 1; 
  if (question2 != NULL) {
    header[1] = question2;
    IWt.NhLines = 2;
  }
  IWt.ULrow = rowN;
  IWt.ULcol = (SCREEN_WIDTH - width) / 2;
  IWt.nColsTotal = width;
  ItemWindow (NEWiw, &IWt, BOO(yesInitial,0,1));
  if (EnterIW(&IWt,helpId))
    switch (IWt.itemN) {
      case 0:
        answer = TRUE;
        break;
      case 1:
        answer = FALSE;
        break;
    }
  else
    answer = FALSE;
    ItemWindow (DELETEiw, &IWt);
  return answer;
}

/******************************************************************************
* ConfirmWindow2.
******************************************************************************/

Logical ConfirmWindow2 (rowN, width, question1, question2, yesInitial, helpId)
int rowN;
int width;
char *question1;
char *question2;        /* If NULL, a one line question. */
Logical yesInitial;     /* If TRUE, <YES> is initial current item. */
int helpId;
{
  static char label[] = " Confirmation ";
  static char *header[] = { NULL, NULL };
  AOSs1 (trailer, "Select: ________   Exit: ________   Help: ________")
  static char *items1[] = {
    "",
    "                  <Yes>                              <No>",
    ""
  };
  static char *items2[] = {
    "",
    "           <Yes to V3>        <Yes to V2>            <No>",
    ""
  };
  static int iLineNs1[] = { 1, 1 };
  static int iLineNs2[] = { 1, 1, 1 };
  static int iCols[2];
  static int iLens[2];
  static int iCols1[] = { 18, 53 };
  static int iLens1[] = { 5, 4 };
  static int iCols2[] = { 11, 30, 53 };
  static int iLens2[] = { 11, 11, 4 };
  static int exitChars[] = { ENTERkey_FSI, EXITkey_FSI, HELPkey_FSI, NUL };
  static struct ItemWindowStruct IWt;
  static struct ItemWindowStruct IWt1 = {
    0, 0, 0, label, 0, header, 3, items1, 2, iLineNs1, iCols1, iLens1, 3,
    1, trailer, exitChars, REFRESHkey_FSI, FALSE
  };
  static struct ItemWindowStruct IWt2 = {
    0, 0, 0, label, 0, header, 3, items2, 3, iLineNs2, iCols2, iLens2, 3,
    1, trailer, exitChars, REFRESHkey_FSI, FALSE
  };
  Logical answer;
  EncodeKeyDefinitions (1, trailer, ENTERkey_FSI, EXITkey_FSI,
			HELPkey_FSI);
  if (CDFgetFileBackwardEnvVar() == 1) 
    IWt = IWt1;
  else
    IWt = IWt2;
  
  IWt.hLines[0] = question1;
  IWt.NhLines = 1;
  if (question2 != NULL) {
    header[1] = question2;
    IWt.NhLines = 2;
  }
  IWt.ULrow = rowN;
  IWt.ULcol = (SCREEN_WIDTH - width) / 2;
  IWt.nColsTotal = width;
  ItemWindow (NEWiw, &IWt, 0);
  if (EnterIW(&IWt,helpId)) {
    if (CDFgetFileBackwardEnvVar() == 1) {
      switch (IWt.itemN) {
        case 0:
	  answer = TRUE;
	  break;
        case 1:
	  answer = FALSE;
	  break;
      }
    } else {
      switch (IWt.itemN) {
        case 0:
          answer = TRUE;
          CDFsetFileBackward(BACKWARDFILEoff);
          break;
        case 1:
          answer = TRUE;
          CDFsetFileBackward(BACKWARDFILEon);
          break;
        case 2:
          answer = FALSE;
          break;
      }
    }
  } else
    answer = FALSE;
  ItemWindow (DELETEiw, &IWt);
  return answer;
}

/******************************************************************************
* EnterIW.
******************************************************************************/

Logical EnterIW (IW, helpId)
struct ItemWindowStruct *IW;
int helpId;
{
  for (;;) {
     ItemWindow (READiw, IW);
     switch (IW->key) {
       case EXITkey_FSI:
	 return FALSE;
       case ENTERkey_FSI:
	 return TRUE;
       case HELPkey_FSI:
	 OnlineHelpWindow (ilhFile, helpId);
	 break;
     }
  }
}

/******************************************************************************
* EnterPW.
******************************************************************************/

Logical EnterPW (PW, helpId)
struct PromptWindowStruct *PW;
int helpId;
{
  for (;;) {
     PromptWindow (READiw, PW);
     switch (PW->key) {
       case EXITkey_FSI:
	 return FALSE;
       case ENTERkey_FSI:
	 return TRUE;
       case HELPkey_FSI:
	 OnlineHelpWindow (ilhFile, helpId);
	 break;
     }
  }
}

/******************************************************************************
* IndexInList.
******************************************************************************/

int IndexInList (match, nItems, items)
char *match;
int nItems;
char **items;
{
  int i;
  for (i = 0; i < nItems; i++) if (!strcmp(match,items[i])) return i;
  return -1;
}

/******************************************************************************
* DataTypeItemN.
******************************************************************************/

int DataTypeItemN (dataType)
long dataType;
{
  static char *symbols[] = { DTiwSYMBOLS };
  static int colums[] = { DTiwCOLs };
  static int lineNs[] = { DTiwLINEnS };
  static int lengths[] = { DTiwLENs };
  char token[11+1];     /* Assumes `CDF_EPOCH16' is longest data type token. */
  int itemN; char *symbol;
  for (itemN = 0; itemN < 15; itemN++) {
     strcpyX (token, "CDF_", 11);
     strcatX (token, DataTypeToken(dataType), 11);
     symbol = &(symbols[lineNs[itemN]][colums[itemN]]);
     if (!strncmp(token,symbol,lengths[itemN])) return itemN;
  }
  return 0;
}

/******************************************************************************
* ShowFullName.
******************************************************************************/

void ShowFullName (name, attr)
char *name;
Logical attr;   /* TRUE: attribute, FALSE: variable. */
{
  AOSs6 (lineS, " ",BLANKs78," ","  Enter any key to continue...  "," ","")
  size_t length = strlen (name);
  char delim = PickDelimiter (name, length);
  snprintf (lineS[1], (size_t) sizeof(BLANKs78),
	    "  %c%s%c  ", delim, name, delim);
  MessageWindow (lineS, BOO(attr,"Full attribute name...",
				 "Full variable name..."), LogicalTRUE);
  MessageWindow (NULL);
  return;
}

/******************************************************************************
* SelectMajority.
******************************************************************************/

Logical SelectMajority () {
  long majority; int itemN; CDFstatus status;
  static char *header[] = { "Select new majority..." };
  AOSs1 (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[] = { ENTERkey_FSI, EXITkey_FSI, HELPkey_FSI, NUL };
  static struct ItemWindowStruct IWt = {
    12, 0, 80, NULL, 1, header, 2, items, 2, iLineNs, iCols, iLens, 3, 1,
    trailer, exitChars, REFRESHkey_FSI, FALSE
  };
  EncodeKeyDefinitions (1, trailer, ENTERkey_FSI, EXITkey_FSI, HELPkey_FSI);
  status = CDFlib (GET_, CDF_MAJORITY_, &majority,
		   NULL_);
  if (!ReportStatus(status,FALSE)) 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_);
       if (ReportStatus(status,FALSE)) {
	 ItemWindow (DELETEiw, &IWt);
	 return TRUE;
       }
       if (NoMoreAccess(NULL)) {
	 ItemWindow (DELETEiw, &IWt);
	 return FALSE;
       }
     }
     else
       break;
  }
  ItemWindow (DELETEiw, &IWt);
  return TRUE;
}

/******************************************************************************
* SelectFormat.
******************************************************************************/

Logical SelectFormat () {
  long format; int itemN; CDFstatus status;
  static char *header[] = { "Select new format..." };
  AOSs1 (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[] = { ENTERkey_FSI, EXITkey_FSI, HELPkey_FSI, NUL };
  static struct ItemWindowStruct IWt = {
    12, 0, 80, NULL, 1, header, 2, items, 2, iLineNs, iCols, iLens, 3, 1,
    trailer, exitChars, REFRESHkey_FSI, FALSE
  };
  EncodeKeyDefinitions (1, trailer, ENTERkey_FSI, EXITkey_FSI, HELPkey_FSI);
  status = CDFlib (GET_, CDF_FORMAT_, &format,
		   NULL_);
  if (!ReportStatus(status,FALSE)) 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_);
       if (ReportStatus(status,FALSE)) {
	 ItemWindow (DELETEiw, &IWt);
	 return TRUE;
       }
       if (NoMoreAccess(NULL)) {
	 ItemWindow (DELETEiw, &IWt);
	 return FALSE;
       }
     }
     else
       break;
  }
  ItemWindow (DELETEiw, &IWt);
  return TRUE;
}

/******************************************************************************
* SelectEncoding.
******************************************************************************/

Logical SelectEncoding () {
  long encoding; int itemN; CDFstatus status;
  static char *header[] = { "Select new encoding..." };
  AOSs1 (trailer, "Select: ________   Exit: ________   Help:   ________")
  static char *items[] = {
    "HOST      SUN   IBMPC   SGi   HP     ALPHAVMSg   ALPHAVMSi   DECSTATION",
    "NETWORK   VAX   IBMRS   PPC   NeXT   ALPHAVMSd   ALPHAOSF1"
  };
  static int iLineNs[] = { 0,0,0,0,0,0,0,0,1,1,1,1,1,1,1 };
  static int iCols[] = { 0,10,16,24,30,37,49,61,0,10,16,24,30,37,49 };
  static int iLens[] = { 4,3,5,3,2,9,9,10,7,3,5,3,4,9,9 };
  static int exitChars[] = { ENTERkey_FSI, EXITkey_FSI, HELPkey_FSI, NUL };
  static struct ItemWindowStruct IWt = {
    12, 0, 80, NULL, 1, header, 2, items, 15, iLineNs, iCols, iLens, 3, 1,
    trailer, exitChars, REFRESHkey_FSI, FALSE
  };
  char selectedEncoding[10+1], delim = ' ', *selected = NULL, *tmpStr;

  EncodeKeyDefinitions (1, trailer, ENTERkey_FSI, EXITkey_FSI, HELPkey_FSI);
  status = CDFlib (GET_, CDF_ENCODING_, &encoding,
		   NULL_);
  if (!ReportStatus(status,FALSE)) return FALSE;
  for (itemN = 0; itemN < 15; 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)) {
       tmpStr = &items[iLineNs[IWt.itemN]][iCols[IWt.itemN]];
       selected = strchr(tmpStr, delim);   
       if (selected != NULL) 
         strcpyX (selectedEncoding, tmpStr, selected - tmpStr);
       else
         strcpyX (selectedEncoding, tmpStr, strlen(tmpStr));
       encoding = WhichEncoding(selectedEncoding);
       status = CDFlib (PUT_, CDF_ENCODING_, encoding,
			NULL_);
       if (ReportStatus(status,FALSE)) {
	 ItemWindow (DELETEiw, &IWt);
	 return TRUE;
       }
       if (NoMoreAccess(NULL)) {
	 ItemWindow (DELETEiw, &IWt);
	 return FALSE;
       }
     }
     else
       break;
  }
  ItemWindow (DELETEiw, &IWt);
  return TRUE;
}

/******************************************************************************
* SelectSparseness.
******************************************************************************/

Logical SelectSparseness (zVar, changed)
Logical zVar;
Logical *changed;	/* Assumed initialized to FALSE by caller. */
{
  long sRecordsType; CDFstatus status; static Logical first = TRUE;
  static char *header[] = { "Select sparseness..." };
  AOSs1 (trailer, "Select: ________   Exit: ________   Help: ________")
  static char *items[] = {
    "sRecords.NO     sRecords.PAD     sRecords.PREV"
  };
  static int iLineNs[] = { 0,0,0 };
  static int iCols[] = { 0,16,33 };
  static int iLens[] = { 11,12,13 };
  static int exitChars[] = { ENTERkey_FSI, EXITkey_FSI, HELPkey_FSI, NUL };
  static struct ItemWindowStruct IWt = {
    14, 0, 80, NULL, 1, header, 1, items, 3, iLineNs, iCols, iLens, 1, 1,
    trailer, exitChars, REFRESHkey_FSI, TRUE
  };
  static long sRecordsTypes[] = {
    NO_SPARSERECORDS, PAD_SPARSERECORDS, PREV_SPARSERECORDS
  };
  if (first) {
    EncodeKeyDefinitions (1, trailer, ENTERkey_FSI, EXITkey_FSI, HELPkey_FSI);
    first = FALSE;
  }
  ItemWindow (NEWiw, &IWt, 0);
  for (;;) {
     if (EnterIW(&IWt,SPARSENESShelpID)) {
       sRecordsType = sRecordsTypes[IWt.itemN];
       status = CDFlib (PUT_, BOO(zVar,zVAR_SPARSERECORDS_,
				       rVAR_SPARSERECORDS_), sRecordsType,
		        NULL_);
       if (ReportStatus(status,FALSE)) {
	 ItemWindow (DELETEiw, &IWt);
	 ASSIGNnotNULL (changed, TRUE)
	 return TRUE;
       }
       if (NoMoreAccess(NULL)) {
	 ItemWindow (DELETEiw, &IWt);
	 return FALSE;
       }
     }
     else {
       ItemWindow (DELETEiw, &IWt);
       return TRUE;
     }
  }
}

/******************************************************************************
* SelectCompression.
******************************************************************************/

Logical SelectCompression (forWhat, row, changed)
int forWhat;
int row;
Logical *changed;	/* Assumed initialized to FALSE by caller. */
{
  long cType, cParms[CDF_MAX_PARMS], compressionItem;
  CDFstatus status; static Logical first = TRUE;
  static char *header[] = { "Select compression..." };
  AOSs1 (trailer, "Select: ________   Exit: ________   Help: ________")
  static char *items[] = {
    "None     RLE.0     HUFF.0     AHUFF.0     GZIP..."
  };
  static int iLineNs[] = { 0,0,0,0,0 };
  static int iCols[] = { 0,9,19,30,42 };
  static int iLens[] = { 4,5,6,7,7 };
  static int exitChars[] = { ENTERkey_FSI, EXITkey_FSI, HELPkey_FSI, NUL };
  static struct ItemWindowStruct IW = {
    0, 0, 80, NULL, 1, header, 1, items, nCOMPRESSIONs, iLineNs, iCols,
    iLens, 1, 1, trailer, exitChars, REFRESHkey_FSI, TRUE
  };
  if (first) {
    EncodeKeyDefinitions (1, trailer, ENTERkey_FSI, EXITkey_FSI, HELPkey_FSI);
    first = FALSE;
  }
  switch (forWhat) {
    case FORCDF: compressionItem = CDF_COMPRESSION_; break;
    case FORzVAR: compressionItem = zVAR_COMPRESSION_; break;
    case FORrVAR: compressionItem = rVAR_COMPRESSION_; break;
  }
  IW.ULrow = row;
  ItemWindow (NEWiw, &IW, 0);
  for (;;) {
     if (EnterIW(&IW,BOO(forWhat == FORCDF,
			 CDFCOMPRESSIONhelpID,
			 VARCOMPRESSIONhelpID))) {
       switch (IW.itemN) {
	 case NOcompressionIN:
	   cType = NO_COMPRESSION;
	   break;
	 case RLE0compressionIN:
	   cType = RLE_COMPRESSION;
	   cParms[0] = RLE_OF_ZEROs;
	   break;
	 case HUFF0compressionIN:
	   cType = HUFF_COMPRESSION;
	   cParms[0] = OPTIMAL_ENCODING_TREES;
	   break;
	 case AHUFF0compressionIN:
	   cType = AHUFF_COMPRESSION;
	   cParms[0] = OPTIMAL_ENCODING_TREES;
	   break;
	 case GZIPcompressionIN: {
	   static char *gzipHeader[] = {
	     "Syntax: GZIP.<1|2|3|4|5|6|7|8|9>"
	   };
	   AOSs1A (gzipTrailer,
		   "Enter: ________   Exit: ________   Help: ________")
	   static char token[MAX_GZIP_TOKEN_LEN+1];
	   static Logical gzipFirst = TRUE;
	   static int gzipExit[] = {
	     ENTERkey_FSI, EXITkey_FSI, HELPkey_FSI, NUL
	   };
	   static struct PromptWindowStruct PW = {
	     "Enter GZIP compression parameters...", 0, 0, 80, 1, gzipHeader,
	     MAX_GZIP_TOKEN_LEN, token, 1, gzipTrailer, gzipExit,
	     REFRESHkey_FSI, SOLkey_FSI, EOLkey_FSI, INSERTorOVERkey_FSI
	   };
	   if (gzipFirst) {
	     EncodeKeyDefinitions (1, gzipTrailer,
				   ENTERkey_FSI, EXITkey_FSI, HELPkey_FSI);
	     strcpyX (PW.value, "GZIP.", MAX_GZIP_TOKEN_LEN);
	     gzipFirst = FALSE;
	   }
	   PW.ULrow = row;
	   PromptWindow (NEWpw, &PW, (int) strlen(PW.value), LogicalTRUE);
	   for (;;) {
	      if (EnterPW(&PW,GZIPhelpID)) {
		int level;
	        if (sscanf(PW.value,"GZIP.%d",&level) == 1) {
		  if (INCLUSIVE(1,level,9)) {
		    cType = GZIP_COMPRESSION;
		    cParms[0] = level;
		    PromptWindow (DELETEpw, &PW);
		    break;
		  }
		  else
		    ProblemWindow ("Illegal GZIP level.", FALSE);
		}
		else
		  ProblemWindow ("Illegal GZIP parameter.", FALSE);
	      }
	      else {
		PromptWindow (DELETEpw, &PW);
		ItemWindow (DELETEiw, &IW);
		return TRUE;
	      }
	   }
	   break;
	 }
       }
       ItemWindow (UNDISPLAYiw, &IW);
       if (forWhat == FORCDF) {
	 AOSs2 (compressingLines, "Changing compression...", "")
	 MessageWindow (compressingLines, NULL, LogicalFALSE);
	 zzzzz (1.0);
       }
       status = CDFlib (PUT_, compressionItem, cType, cParms,
			NULL_);
       if (forWhat == FORCDF) MessageWindow (NULL);
       if (ReportStatus(status,FALSE)) {
	 ItemWindow (DELETEiw, &IW);
	 if (forWhat == FORCDF) compressed = (cType != NO_COMPRESSION);
	 ASSIGNnotNULL (changed, TRUE)
	 return TRUE;
       }
       if (NoMoreAccess(NULL)) {
	 ItemWindow (DELETEiw, &IW);
	 return FALSE;
       }
       ItemWindow (REDISPLAYiw, &IW);
     }
     else {
       ItemWindow (DELETEiw, &IW);
       return TRUE;
     }
  }
}

/******************************************************************************
* SelectDataSpec.
******************************************************************************/

Logical SelectDataSpec (dataType, numElems, label)
long *dataType;         /* If NO_DATATYPE, start at item number 0. */
long *numElems;         /* If NULL, don't prompt for number of elements. */
char *label;            /* If NULL, no label. */
{
  static char *header[] = { "Select data type..." };
  static char *items[] = { DTiwSYMBOLS };
  AOSs1 (trailer, "Select: ________    Exit: ________    Help: ________")
  static int iLineNs[] = { DTiwLINEnS };
  static int iCols[] = { DTiwCOLs };
  static int iLens[] = { DTiwLENs };
  static int exitChars[] = { ENTERkey_FSI, EXITkey_FSI, HELPkey_FSI, NUL };
  static struct ItemWindowStruct IWt = {
    4, 1, 78, NULL, 1, header, 3, items, 17, iLineNs, iCols, iLens, 3, 1,
    trailer, exitChars, REFRESHkey_FSI, FALSE
  };
  static Logical first = TRUE; int itemN;
  char selectedDataType[15+1], delim = ' ', *selected = NULL, *tmpStr;
  if (first) {
    EncodeKeyDefinitions (1, trailer, ENTERkey_FSI, EXITkey_FSI,
			  HELPkey_FSI);
    first = FALSE;
  }
  IWt.label = label;
  itemN = BOO(*dataType == NO_DATATYPE,0,DataTypeItemN(*dataType));
  ItemWindow (NEWiw, &IWt, itemN);
  if (EnterIW(&IWt,VARDATATYPEhelpID)) {
    tmpStr = &items[iLineNs[IWt.itemN]][iCols[IWt.itemN]];
    selected = strchr(tmpStr, delim);
    if (selected != NULL) 
      strcpyX (selectedDataType, tmpStr, selected - tmpStr);
    else
      strcpyX (selectedDataType, tmpStr, strlen(tmpStr));
    *dataType = WhichDataType(selectedDataType);
    ItemWindow (DELETEiw, &IWt);
    if (numElems == NULL) return TRUE;
    if (STRINGdataType(*dataType)) {
      return SelectNumElems(*dataType,numElems,label);
    }
    *numElems = 1;
    return TRUE;
  }
  ItemWindow (DELETEiw, &IWt);
  return FALSE;
}

/******************************************************************************
* SelectNumElems.
******************************************************************************/

Logical SelectNumElems (dataType, numElems, label)
long dataType;
long *numElems;
char *label;
{
  static char *headerCHAR[] = {
    "Enter number of elements (characters) for CDF_CHAR data type..."
  };
  static char *headerUCHAR[] = {
    "Enter number of elements (characters) for CDF_UCHAR data type..."
  };
  AOSs1 (trailer, "Enter: ________    Exit: ________    Help: ________")
  static char value[MAX_NUMELEMS_LEN+1];
  static int exitChars[] = { ENTERkey_FSI, EXITkey_FSI, HELPkey_FSI, NUL };
  static struct PromptWindowStruct PWt = {
    NULL, 4, 1, 78, 1, NULL, MAX_NUMELEMS_LEN, value, 1, trailer, exitChars,
    REFRESHkey_FSI, SOLkey_FSI, EOLkey_FSI, INSERTorOVERkey_FSI
  };
  static Logical first = TRUE; long tNumElems;
  if (first) {
    EncodeKeyDefinitions (1, trailer, ENTERkey_FSI, EXITkey_FSI,
			  HELPkey_FSI);
    first = FALSE;
  }
  strcpyX (PWt.value, "", MAX_NUMELEMS_LEN);
  PWt.hLines = BOO(dataType == CDF_CHAR,headerCHAR,headerUCHAR);
  PWt.label = label;
  PromptWindow (NEWpw, &PWt, 0, LogicalTRUE);
  for (;;) {
     if (EnterPW(&PWt,VARNUMELEMShelpID)) {
       if (sscanf(PWt.value,"%ld",&tNumElems) == 1) {
	 if (tNumElems > 0) {
	   PromptWindow (DELETEpw, &PWt);
	   *numElems = tNumElems;
	   return TRUE;
	 }
	 else
	   ProblemWindow ("Illegal number of elements.", FALSE);
       }
       else
	 ProblemWindow ("Error decoding number of elements.", FALSE);
     }
     else {
       PromptWindow (DELETEpw, &PWt);
       return FALSE;
     }
  }
}

/******************************************************************************
* SelectChecksum.
******************************************************************************/

Logical SelectChecksum () {
  long checksum; int itemN; CDFstatus status;
  static char *header[] = { "Select new checksum method..." };
  AOSs1 (trailer, "Select: ________   Exit: ________   Help:   ________")
  static char *items[] = { "None", "MD5" };
  static int iLineNs[] = { 0, 1 };
  static int iCols[] = { 0, 0 };
  static int iLens[] = { 4, 3 };
  static int exitChars[] = { ENTERkey_FSI, EXITkey_FSI, HELPkey_FSI, NUL };
  static struct ItemWindowStruct IWt = {
    12, 0, 80, NULL, 1, header, 2, items, 2, iLineNs, iCols, iLens, 3, 1,
    trailer, exitChars, REFRESHkey_FSI, FALSE
  };
  EncodeKeyDefinitions (1, trailer, ENTERkey_FSI, EXITkey_FSI, HELPkey_FSI);
  status = CDFlib (GET_, CDF_CHECKSUM_, &checksum,
		   NULL_);
  if (!ReportStatus(status,FALSE)) return FALSE;
  for (itemN = 0; itemN < 2; itemN++) {
     if (!strcmp(ChecksumToken(checksum),IWt.iLines[itemN])) break;
  }
  ItemWindow (NEWiw, &IWt, itemN);
  for (;;) {
     if (EnterIW(&IWt,CHECKSUMhelpID)) {
       checksum = WhichChecksum(items[IWt.itemN]);
       status = CDFlib (PUT_, CDF_CHECKSUM_, checksum,
			NULL_);
       if (ReportStatus(status,FALSE)) {
	 ItemWindow (DELETEiw, &IWt);
	 return TRUE;
       }
       if (NoMoreAccess(NULL)) {
	 ItemWindow (DELETEiw, &IWt);
	 return FALSE;
       }
     }
     else
       break;
  }
  ItemWindow (DELETEiw, &IWt);
  return TRUE;
}

